7#if defined (Q_OS_WIN32)
23#include <QtSql/private/qsqldriver_p.h>
24#include <QtSql/private/qsqlresult_p.h>
25#include "private/qtools_p.h"
33#define SQL_SS_TIME2 (-154)
37#define ODBC_CHECK_DRIVER
42static constexpr SQLSMALLINT
qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT };
44template<
typename C,
int SIZE = sizeof(SQLTCHAR)>
49 if (realsize > 0 &&
input[realsize - 1] == 0)
51 if constexpr (
SIZE == 1)
53 else if constexpr (
SIZE == 2)
55 else if constexpr (
SIZE == 4)
59 "Don't know how to handle sizeof(SQLTCHAR) != 1/2/4");
62template<
int SIZE = sizeof(SQLTCHAR)>
65 if constexpr (
SIZE == 1)
67 else if constexpr (
SIZE == 2)
69 else if constexpr (
SIZE == 4)
73 "Don't know how to handle sizeof(SQLTCHAR) != 1/2/4");
82 result.resize((
end -
reinterpret_cast<char *
>(
result.data())) /
sizeof(SQLTCHAR));
119 bool isQuoteInitialized =
false;
134 bool exec()
override;
144 bool fetch(
int i)
override;
147 bool isNull(
int field)
override;
165 unicode = drv_d_func()->unicode;
174 SQLHANDLE
dpEnv()
const {
return drv_d_func() ? drv_d_func()->hEnv : 0;}
175 SQLHANDLE
dpDbc()
const {
return drv_d_func() ? drv_d_func()->hDbc : 0;}
192 return drv_d_func() &&
disconnectCount == drv_d_func()->disconnectCount;
208 SQLINTEGER nativeCode = 0;
209 SQLSMALLINT msgLen = 0;
211 SQLRETURN
r = SQL_NO_DATA;
227 if (msgLen >= description.
size()) {
228 description.
resize(msgLen + 1);
231 if (
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO) {
235 }
else if (
r == SQL_ERROR ||
r == SQL_INVALID_HANDLE) {
239 }
while (
r != SQL_NO_DATA);
244 const SQLHANDLE envHandle =
nullptr,
245 const SQLHANDLE pDbC =
nullptr)
268 a.sqlState + u
';' +
b.sqlState,
269 a.errorCode + u
';' +
b.errorCode};
271 return std::accumulate(std::next(records.
begin()), records.
end(), records.
front(),
add);
281 return QSqlError(
"QODBC: "_L1 + err, combined.description +
", "_L1 + combined.sqlState,
type,
288 return combined.description;
319 type = QMetaType::Double;
322 type = QMetaType::Float;
325 type = isSigned ? QMetaType::Short : QMetaType::UShort;
329 type = isSigned ? QMetaType::Int : QMetaType::UInt;
332 type = QMetaType::UInt;
335 type = isSigned ? QMetaType::LongLong : QMetaType::ULongLong;
339 case SQL_LONGVARBINARY:
340 type = QMetaType::QByteArray;
344 type = QMetaType::QDate;
349 type = QMetaType::QTime;
352 case SQL_TYPE_TIMESTAMP:
353 type = QMetaType::QDateTime;
357 case SQL_WLONGVARCHAR:
358 type = QMetaType::QString;
362#if (ODBCVER >= 0x0350)
365 case SQL_LONGVARCHAR:
366 type = QMetaType::QString;
369 type = QMetaType::QByteArray;
375template <
typename CT>
379 SQLRETURN
r = SQL_ERROR;
380 SQLLEN lengthIndicator = 0;
383 r = SQLGetData(hStmt,
386 SQLPOINTER(
buf.data()), SQLINTEGER(
buf.size() *
sizeof(CT)),
388 if (
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO) {
389 if (lengthIndicator == SQL_NULL_DATA) {
398 if (lengthIndicator == SQL_NO_TOTAL) {
399 fieldVal += fromSQLTCHAR<QVarLengthArray<CT>,
sizeof(CT)>(
buf,
buf.size());
406 const qsizetype rSize = (
r == SQL_SUCCESS_WITH_INFO)
408 :
qsizetype(lengthIndicator /
sizeof(CT));
409 fieldVal += fromSQLTCHAR<QVarLengthArray<CT>,
sizeof(CT)>(
buf, rSize);
411 if (lengthIndicator < SQLLEN((
buf.size() - 1) *
sizeof(CT))) {
415 }
else if (
r == SQL_NO_DATA) {
418 qSqlWarning(
"qGetStringData: Error while fetching data:"_L1, hStmt);
429 }
else if (colSize > 65536) {
434 return unicode ? getStringDataImpl<SQLTCHAR>(hStmt,
column, colSize, SQL_C_TCHAR)
435 : getStringDataImpl<SQLCHAR>(hStmt,
column, colSize, SQL_C_CHAR);
441 SQLSMALLINT colNameLen;
444 SQLSMALLINT colScale;
445 SQLSMALLINT nullable;
446 SQLLEN lengthIndicator = 0;
447 SQLRETURN
r = SQL_ERROR;
451 r = SQLDescribeCol(hStmt,
453 colName.
data(), SQLSMALLINT(colName.
size()),
459 if (
r != SQL_SUCCESS)
460 qWarning() <<
"qGetBinaryData: Unable to describe column" <<
column;
464 else if (colSize > 65536)
469 r = SQLGetData(hStmt,
475 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO)
477 if (lengthIndicator == SQL_NULL_DATA)
479 if (lengthIndicator > SQLLEN(colSize) || lengthIndicator == SQL_NO_TOTAL) {
483 read += lengthIndicator;
485 if (
r == SQL_SUCCESS) {
496 SQLINTEGER intbuf = 0;
497 SQLLEN lengthIndicator = 0;
498 SQLRETURN
r = SQLGetData(hStmt,
500 isSigned ? SQL_C_SLONG : SQL_C_ULONG,
504 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO)
506 if (lengthIndicator == SQL_NULL_DATA)
507 return QVariant(QMetaType::fromType<int>());
517 SQLLEN lengthIndicator = 0;
518 SQLRETURN
r = SQLGetData(hStmt,
521 (SQLPOINTER) &dblbuf,
524 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO) {
527 if (lengthIndicator == SQL_NULL_DATA)
528 return QVariant(QMetaType::fromType<double>());
530 return (
double) dblbuf;
536 SQLBIGINT lngbuf = 0;
537 SQLLEN lengthIndicator = 0;
538 SQLRETURN
r = SQLGetData(hStmt,
540 isSigned ? SQL_C_SBIGINT : SQL_C_UBIGINT,
541 (SQLPOINTER) &lngbuf,
544 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO)
546 if (lengthIndicator == SQL_NULL_DATA)
547 return QVariant(QMetaType::fromType<qlonglong>());
557 SQLLEN nNumericAttribute = 0;
558 const SQLRETURN
r = ::SQLColAttribute(hStmt,
column + 1, SQL_DESC_AUTO_UNIQUE_VALUE,
559 0, 0, 0, &nNumericAttribute);
560 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO) {
565 return nNumericAttribute != SQL_FALSE;
584 if (required == SQL_NO_NULLS)
586 else if (required == SQL_NULLABLE)
587 f.setRequired(
false);
603 SQLSMALLINT colNameLen;
606 SQLSMALLINT colScale;
607 SQLSMALLINT nullable;
608 SQLRETURN
r = SQL_ERROR;
611 r = SQLDescribeCol(hStmt,
613 colName.
data(), SQLSMALLINT(colName.
size()),
620 if (
r != SQL_SUCCESS) {
625 SQLLEN unsignedFlag = SQL_FALSE;
626 r = SQLColAttribute (hStmt,
633 if (
r != SQL_SUCCESS) {
642 f.setSqlType(colType);
643 f.setLength(colSize == 0 ? -1 : int(colSize));
644 f.setPrecision(colScale == 0 ? -1 : int(colScale));
645 if (nullable == SQL_NO_NULLS)
647 else if (nullable == SQL_NULLABLE)
648 f.setRequired(
false);
652 SQLSMALLINT tableNameLen;
653 r = SQLColAttribute(hStmt,
655 SQL_DESC_BASE_TABLE_NAME,
657 SQLSMALLINT(tableName.
size() *
sizeof(SQLTCHAR)),
660 if (
r == SQL_SUCCESS)
661 f.setTableName(
fromSQLTCHAR(tableName, tableNameLen /
sizeof(SQLTCHAR)));
674 if (!isQuoteInitialized) {
675 SQLTCHAR driverResponse[4];
677 int r = SQLGetInfo(
hDbc,
678 SQL_IDENTIFIER_QUOTE_CHAR,
680 sizeof(driverResponse),
682 if (
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO)
683 quote =
QChar(driverResponse[0]);
686 isQuoteInitialized =
true;
694 return SQLSetConnectAttr(
handle, attr,
704 SQLRETURN
r = SQL_SUCCESS;
705 for (
int i = 0;
i < opts.count(); ++
i) {
708 if ((idx = tmp.
indexOf(u
'=')) == -1) {
709 qWarning() <<
"QODBCDriver::open: Illegal connect option value '" << tmp <<
'\'';
717 if (
opt.toUpper() ==
"SQL_ATTR_ACCESS_MODE"_L1) {
718 if (
val.toUpper() ==
"SQL_MODE_READ_ONLY"_L1) {
719 v = SQL_MODE_READ_ONLY;
720 }
else if (
val.toUpper() ==
"SQL_MODE_READ_WRITE"_L1) {
721 v = SQL_MODE_READ_WRITE;
723 qWarning() <<
"QODBCDriver::open: Unknown option value '" <<
val <<
'\'';
726 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_ACCESS_MODE, (SQLPOINTER)
size_t(
v), 0);
727 }
else if (
opt.toUpper() ==
"SQL_ATTR_CONNECTION_TIMEOUT"_L1) {
729 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER)
size_t(
v), 0);
730 }
else if (
opt.toUpper() ==
"SQL_ATTR_LOGIN_TIMEOUT"_L1) {
732 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)
size_t(
v), 0);
733 }
else if (
opt.toUpper() ==
"SQL_ATTR_CURRENT_CATALOG"_L1) {
735 }
else if (
opt.toUpper() ==
"SQL_ATTR_METADATA_ID"_L1) {
736 if (
val.toUpper() ==
"SQL_TRUE"_L1) {
738 }
else if (
val.toUpper() ==
"SQL_FALSE"_L1) {
741 qWarning() <<
"QODBCDriver::open: Unknown option value '" <<
val <<
'\'';
744 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_METADATA_ID, (SQLPOINTER)
size_t(
v), 0);
745 }
else if (
opt.toUpper() ==
"SQL_ATTR_PACKET_SIZE"_L1) {
747 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_PACKET_SIZE, (SQLPOINTER)
size_t(
v), 0);
748 }
else if (
opt.toUpper() ==
"SQL_ATTR_TRACEFILE"_L1) {
750 }
else if (
opt.toUpper() ==
"SQL_ATTR_TRACE"_L1) {
751 if (
val.toUpper() ==
"SQL_OPT_TRACE_OFF"_L1) {
752 v = SQL_OPT_TRACE_OFF;
753 }
else if (
val.toUpper() ==
"SQL_OPT_TRACE_ON"_L1) {
754 v = SQL_OPT_TRACE_ON;
756 qWarning() <<
"QODBCDriver::open: Unknown option value '" <<
val <<
'\'';
759 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_TRACE, (SQLPOINTER)
size_t(
v), 0);
760 }
else if (
opt.toUpper() ==
"SQL_ATTR_CONNECTION_POOLING"_L1) {
761 if (
val ==
"SQL_CP_OFF"_L1)
763 else if (
val.toUpper() ==
"SQL_CP_ONE_PER_DRIVER"_L1)
764 v = SQL_CP_ONE_PER_DRIVER;
765 else if (
val.toUpper() ==
"SQL_CP_ONE_PER_HENV"_L1)
766 v = SQL_CP_ONE_PER_HENV;
767 else if (
val.toUpper() ==
"SQL_CP_DEFAULT"_L1)
770 qWarning() <<
"QODBCDriver::open: Unknown option value '" <<
val <<
'\'';
773 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_CONNECTION_POOLING, (SQLPOINTER)
size_t(
v), 0);
774 }
else if (
opt.toUpper() ==
"SQL_ATTR_CP_MATCH"_L1) {
775 if (
val.toUpper() ==
"SQL_CP_STRICT_MATCH"_L1)
776 v = SQL_CP_STRICT_MATCH;
777 else if (
val.toUpper() ==
"SQL_CP_RELAXED_MATCH"_L1)
778 v = SQL_CP_RELAXED_MATCH;
779 else if (
val.toUpper() ==
"SQL_CP_MATCH_DEFAULT"_L1)
780 v = SQL_CP_MATCH_DEFAULT;
782 qWarning() <<
"QODBCDriver::open: Unknown option value '" <<
val <<
'\'';
785 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_CP_MATCH, (SQLPOINTER)
size_t(
v), 0);
786 }
else if (
opt.toUpper() ==
"SQL_ATTR_ODBC_VERSION"_L1) {
790 qWarning() <<
"QODBCDriver::open: Unknown connection attribute '" <<
opt <<
'\'';
792 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO)
812 schema = l.
at(0).toString();
816 catalog = l.
at(0).toString();
817 schema = l.
at(1).toString();
822 .
arg(qualifier),
this);
831 int r = SQLGetInfo(
hDbc,
836 if (
r != SQL_SUCCESS)
846 case (SQL_IC_SENSITIVE):
890 if (
d->hStmt &&
d->isStmtHandleValid() &&
driver() &&
driver()->isOpen()) {
891 SQLRETURN
r = SQLFreeHandle(SQL_HANDLE_STMT,
d->hStmt);
892 if (
r != SQL_SUCCESS)
893 qSqlWarning(
"QODBCDriver: Unable to free statement handle "_L1
904 d->fieldCache.clear();
905 d->fieldCacheIdx = 0;
910 if (
d->hStmt &&
d->isStmtHandleValid()) {
911 r = SQLFreeHandle(SQL_HANDLE_STMT,
d->hStmt);
912 if (
r != SQL_SUCCESS) {
913 qSqlWarning(
"QODBCResult::reset: Unable to free statement handle"_L1,
d);
917 r = SQLAllocHandle(SQL_HANDLE_STMT,
920 if (
r != SQL_SUCCESS) {
921 qSqlWarning(
"QODBCResult::reset: Unable to allocate statement handle"_L1,
d);
925 d->updateStmtHandleState();
928 r = SQLSetStmtAttr(
d->hStmt,
929 SQL_ATTR_CURSOR_TYPE,
930 (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
933 r = SQLSetStmtAttr(
d->hStmt,
934 SQL_ATTR_CURSOR_TYPE,
935 (SQLPOINTER)SQL_CURSOR_STATIC,
938 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO) {
940 "QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. "
947 r = SQLExecDirect(
d->hStmt,
951 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO &&
r!= SQL_NO_DATA) {
957 SQLULEN isScrollable = 0;
958 r = SQLGetStmtAttr(
d->hStmt, SQL_ATTR_CURSOR_SCROLLABLE, &isScrollable, SQL_IS_INTEGER, 0);
959 if (
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO)
962 SQLSMALLINT
count = 0;
963 SQLNumResultCols(
d->hStmt, &
count);
966 for (SQLSMALLINT
i = 0;
i <
count; ++
i) {
969 d->fieldCache.resize(
count);
989 int actualIdx =
i + 1;
990 if (actualIdx <= 0) {
997 while (
ok &&
i >
at())
1001 r = SQLFetchScroll(
d->hStmt,
1005 if (
r != SQL_SUCCESS) {
1006 if (
r != SQL_NO_DATA)
1021 if (
d->hasSQLFetchScroll)
1022 r = SQLFetchScroll(
d->hStmt,
1026 r = SQLFetch(
d->hStmt);
1028 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO) {
1029 if (
r != SQL_NO_DATA)
1048 r = SQLFetchScroll(
d->hStmt,
1051 if (
r != SQL_SUCCESS) {
1052 if (
r != SQL_NO_DATA)
1068 r = SQLFetchScroll(
d->hStmt,
1071 if (
r != SQL_SUCCESS) {
1072 if (
r != SQL_NO_DATA)
1100 r = SQLFetchScroll(
d->hStmt,
1103 if (
r != SQL_SUCCESS) {
1104 if (
r != SQL_NO_DATA)
1109 SQLULEN currRow = 0;
1110 r = SQLGetStmtAttr(
d->hStmt,
1115 if (
r != SQL_SUCCESS)
1124 if (field >=
d->rInf.count() || field < 0) {
1125 qWarning() <<
"QODBCResult::data: column" << field <<
"out of range";
1128 if (field < d->fieldCacheIdx)
1129 return d->fieldCache.at(field);
1132 SQLLEN lengthIndicator = 0;
1134 for (
int i =
d->fieldCacheIdx;
i <= field; ++
i) {
1138 switch (
info.metaType().id()) {
1139 case QMetaType::LongLong:
1142 case QMetaType::ULongLong:
1145 case QMetaType::Int:
1146 case QMetaType::Short:
1149 case QMetaType::UInt:
1150 case QMetaType::UShort:
1153 case QMetaType::QDate:
1155 r = SQLGetData(
d->hStmt,
1161 if ((
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA))
1164 d->fieldCache[
i] =
QVariant(QMetaType::fromType<QDate>());
1166 case QMetaType::QTime:
1168 r = SQLGetData(
d->hStmt,
1174 if ((
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA))
1175 d->fieldCache[
i] =
QVariant(
QTime(tbuf.hour, tbuf.minute, tbuf.second));
1177 d->fieldCache[
i] =
QVariant(QMetaType::fromType<QTime>());
1179 case QMetaType::QDateTime:
1180 TIMESTAMP_STRUCT dtbuf;
1181 r = SQLGetData(
d->hStmt,
1187 if ((
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA))
1189 QTime(dtbuf.hour, dtbuf.minute, dtbuf.second, dtbuf.fraction / 1000000)));
1191 d->fieldCache[
i] =
QVariant(QMetaType::fromType<QDateTime>());
1193 case QMetaType::QByteArray:
1196 case QMetaType::QString:
1199 case QMetaType::Double:
1211 const int extra =
info.precision() > 0 ? 1 : 0;
1220 d->fieldCacheIdx = field + 1;
1222 return d->fieldCache[field];
1228 if (field < 0 || field >=
d->fieldCache.size())
1230 if (field >=
d->fieldCacheIdx) {
1236 return d->fieldCache.at(field).isNull();
1247 SQLLEN affectedRowCount = 0;
1248 SQLRETURN
r = SQLRowCount(
d->hStmt, &affectedRowCount);
1249 if (
r == SQL_SUCCESS)
1250 return affectedRowCount;
1252 qSqlWarning(
"QODBCResult::numRowsAffected: Unable to count affected rows"_L1,
d);
1264 if (
d->hStmt &&
d->isStmtHandleValid()) {
1265 r = SQLFreeHandle(SQL_HANDLE_STMT,
d->hStmt);
1266 if (
r != SQL_SUCCESS) {
1267 qSqlWarning(
"QODBCResult::prepare: Unable to close statement"_L1,
d);
1271 r = SQLAllocHandle(SQL_HANDLE_STMT,
1274 if (
r != SQL_SUCCESS) {
1275 qSqlWarning(
"QODBCResult::prepare: Unable to allocate statement handle"_L1,
d);
1279 d->updateStmtHandleState();
1282 r = SQLSetStmtAttr(
d->hStmt,
1283 SQL_ATTR_CURSOR_TYPE,
1284 (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
1287 r = SQLSetStmtAttr(
d->hStmt,
1288 SQL_ATTR_CURSOR_TYPE,
1289 (SQLPOINTER)SQL_CURSOR_STATIC,
1292 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO) {
1294 "QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. "
1301 r = SQLPrepare(
d->hStmt,
1306 if (
r != SQL_SUCCESS) {
1320 d->fieldCache.clear();
1321 d->fieldCacheIdx = 0;
1324 qSqlWarning(
"QODBCResult::exec: No statement handle available"_L1,
d);
1329 SQLCloseCursor(
d->hStmt);
1341 SQLLEN *ind = &indicators[
i];
1343 *ind = SQL_NULL_DATA;
1344 switch (
val.typeId()) {
1345 case QMetaType::QDate: {
1348 DATE_STRUCT *dt = (DATE_STRUCT *)
const_cast<char *
>(
ba.
constData());
1351 dt->month = qdt.
month();
1352 dt->day = qdt.
day();
1353 r = SQLBindParameter(
d->hStmt,
1362 *ind == SQL_NULL_DATA ? ind : NULL);
1364 case QMetaType::QTime: {
1367 TIME_STRUCT *dt = (TIME_STRUCT *)
const_cast<char *
>(
ba.
constData());
1370 dt->minute = qdt.
minute();
1371 dt->second = qdt.
second();
1372 r = SQLBindParameter(
d->hStmt,
1381 *ind == SQL_NULL_DATA ? ind : NULL);
1383 case QMetaType::QDateTime: {
1385 ba.
resize(
sizeof(TIMESTAMP_STRUCT));
1386 TIMESTAMP_STRUCT *dt =
reinterpret_cast<TIMESTAMP_STRUCT *
>(
const_cast<char *
>(
ba.
constData()));
1390 dt->year = qdate.
year();
1391 dt->month = qdate.
month();
1392 dt->day = qdate.
day();
1393 dt->hour = qtime.
hour();
1394 dt->minute = qtime.
minute();
1395 dt->second = qtime.
second();
1397 const int precision =
d->drv_d_func()->datetimePrecision - 20;
1401 dt->fraction = qtime.
msec() * 1000000;
1405 dt->fraction = (dt->fraction / keep) * keep;
1408 r = SQLBindParameter(
d->hStmt,
1413 d->drv_d_func()->datetimePrecision,
1417 *ind == SQL_NULL_DATA ? ind : NULL);
1419 case QMetaType::Int:
1420 r = SQLBindParameter(
d->hStmt,
1427 const_cast<void *
>(
val.constData()),
1429 *ind == SQL_NULL_DATA ? ind : NULL);
1431 case QMetaType::UInt:
1432 r = SQLBindParameter(
d->hStmt,
1439 const_cast<void *
>(
val.constData()),
1441 *ind == SQL_NULL_DATA ? ind : NULL);
1443 case QMetaType::Short:
1444 r = SQLBindParameter(
d->hStmt,
1451 const_cast<void *
>(
val.constData()),
1453 *ind == SQL_NULL_DATA ? ind : NULL);
1455 case QMetaType::UShort:
1456 r = SQLBindParameter(
d->hStmt,
1463 const_cast<void *
>(
val.constData()),
1465 *ind == SQL_NULL_DATA ? ind : NULL);
1467 case QMetaType::Double:
1468 r = SQLBindParameter(
d->hStmt,
1475 const_cast<void *
>(
val.constData()),
1477 *ind == SQL_NULL_DATA ? ind : NULL);
1479 case QMetaType::Float:
1480 r = SQLBindParameter(
d->hStmt,
1487 const_cast<void *
>(
val.constData()),
1489 *ind == SQL_NULL_DATA ? ind : NULL);
1491 case QMetaType::LongLong:
1492 r = SQLBindParameter(
d->hStmt,
1499 const_cast<void *
>(
val.constData()),
1501 *ind == SQL_NULL_DATA ? ind : NULL);
1503 case QMetaType::ULongLong:
1504 r = SQLBindParameter(
d->hStmt,
1511 const_cast<void *
>(
val.constData()),
1513 *ind == SQL_NULL_DATA ? ind : NULL);
1515 case QMetaType::QByteArray:
1516 if (*ind != SQL_NULL_DATA) {
1517 *ind =
val.toByteArray().size();
1519 r = SQLBindParameter(
d->hStmt,
1524 val.toByteArray().size(),
1526 const_cast<char *
>(
val.toByteArray().constData()),
1527 val.toByteArray().size(),
1530 case QMetaType::Bool:
1531 r = SQLBindParameter(
d->hStmt,
1538 const_cast<void *
>(
val.constData()),
1540 *ind == SQL_NULL_DATA ? ind : NULL);
1542 case QMetaType::QString:
1551 if (*ind != SQL_NULL_DATA)
1555 r = SQLBindParameter(
d->hStmt,
1559 ba.
size() > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
1567 r = SQLBindParameter(
d->hStmt,
1571 ba.
size() > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
1583 if (*ind != SQL_NULL_DATA)
1587 r = SQLBindParameter(
d->hStmt,
1591 strSize > 254 ? SQL_LONGVARCHAR : SQL_VARCHAR,
1602 if (*ind != SQL_NULL_DATA)
1604 r = SQLBindParameter(
d->hStmt,
1616 if (
r != SQL_SUCCESS) {
1617 qSqlWarning(
"QODBCResult::exec: unable to bind variable:"_L1,
d);
1623 r = SQLExecute(
d->hStmt);
1624 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO &&
r != SQL_NO_DATA) {
1625 qSqlWarning(
"QODBCResult::exec: Unable to execute statement:"_L1,
d);
1631 SQLULEN isScrollable = 0;
1632 r = SQLGetStmtAttr(
d->hStmt, SQL_ATTR_CURSOR_SCROLLABLE, &isScrollable, SQL_IS_INTEGER, 0);
1633 if (
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO)
1636 SQLSMALLINT
count = 0;
1637 SQLNumResultCols(
d->hStmt, &
count);
1640 for (SQLSMALLINT
i = 0;
i <
count; ++
i) {
1643 d->fieldCache.resize(
count);
1655 switch (
values.at(
i).typeId()) {
1656 case QMetaType::QDate: {
1657 DATE_STRUCT ds = *((DATE_STRUCT *)
const_cast<char *
>(tmpStorage.at(
i).constData()));
1660 case QMetaType::QTime: {
1661 TIME_STRUCT dt = *((TIME_STRUCT *)
const_cast<char *
>(tmpStorage.at(
i).constData()));
1664 case QMetaType::QDateTime: {
1665 TIMESTAMP_STRUCT dt = *((TIMESTAMP_STRUCT*)
1666 const_cast<char *
>(tmpStorage.at(
i).constData()));
1668 QTime(dt.hour, dt.minute, dt.second, dt.fraction / 1000000)));
1670 case QMetaType::Bool:
1671 case QMetaType::Short:
1672 case QMetaType::UShort:
1673 case QMetaType::Int:
1674 case QMetaType::UInt:
1675 case QMetaType::Float:
1676 case QMetaType::Double:
1677 case QMetaType::QByteArray:
1678 case QMetaType::LongLong:
1679 case QMetaType::ULongLong:
1682 case QMetaType::QString:
1686 const auto strSize = bytes.
size() /
sizeof(SQLTCHAR);
1688 memcpy(
string.
data(), bytes.
data(), strSize *
sizeof(SQLTCHAR));
1699 if (indicators[
i] == SQL_NULL_DATA)
1718 switch (
driver()->dbmsType()) {
1721 sql =
"SELECT @@IDENTITY;"_L1;
1724 sql =
"SELECT LAST_INSERT_ID();"_L1;
1727 sql =
"SELECT lastval();"_L1;
1736 return qry.
value(0);
1738 qSqlWarning(
"QODBCResult::lastInsertId: Unable to get lastInsertId"_L1,
d);
1740 qSqlWarning(
"QODBCResult::lastInsertId: not implemented for this DBMS"_L1,
d);
1749 return QVariant(QMetaType::fromType<SQLHANDLE>(), &
d->hStmt);
1758 d->fieldCache.clear();
1759 d->fieldCacheIdx = 0;
1762 SQLRETURN
r = SQLMoreResults(
d->hStmt);
1763 if (
r != SQL_SUCCESS) {
1764 if (
r == SQL_SUCCESS_WITH_INFO) {
1768 if (
r != SQL_NO_DATA)
1775 SQLSMALLINT
count = 0;
1776 SQLNumResultCols(
d->hStmt, &
count);
1779 for (SQLSMALLINT
i = 0;
i <
count; ++
i) {
1782 d->fieldCache.resize(
count);
1800 SQLCloseCursor(
d->hStmt);
1837 int r = SQLGetInfo(
d->hDbc,
1838 (SQLUSMALLINT)SQL_TXN_CAPABLE,
1842 if (
r != SQL_SUCCESS || txn == SQL_TC_NONE)
1867 return d->hasMultiResultSets;
1889 r = SQLAllocHandle(SQL_HANDLE_ENV,
1892 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO) {
1893 qSqlWarning(
"QODBCDriver::open: Unable to allocate environment"_L1,
d);
1897 r = SQLSetEnvAttr(
d->hEnv,
1898 SQL_ATTR_ODBC_VERSION,
1901 r = SQLAllocHandle(SQL_HANDLE_DBC,
1904 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO) {
1905 qSqlWarning(
"QODBCDriver::open: Unable to allocate connection"_L1,
d);
1911 if (!
d->setConnectionOptions(connOpts)) {
1920 connQStr =
"FILEDSN="_L1 +
db;
1925 connQStr =
"DSN="_L1 +
db;
1928 connQStr +=
";UID="_L1 + user;
1930 connQStr +=
";PWD="_L1 + password;
1936 r = SQLDriverConnect(
d->hDbc,
1939 connOut.
data(), SQLSMALLINT(connOut.
size()),
1944 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO) {
1951 if (!
d->checkDriver()) {
1960 d->checkSchemaUsage();
1962 d->checkHasSQLFetchScroll();
1963 d->checkHasMultiResults();
1964 d->checkDateTimePrecision();
1969 i.exec(
"SET QUOTED_IDENTIFIER ON"_L1);
1981void QODBCDriver::cleanup()
1989 r = SQLDisconnect(
d->hDbc);
1990 if (
r != SQL_SUCCESS)
1991 qSqlWarning(
"QODBCDriver::disconnect: Unable to disconnect datasource"_L1,
d);
1993 d->disconnectCount++;
1996 r = SQLFreeHandle(SQL_HANDLE_DBC,
d->hDbc);
1997 if (
r != SQL_SUCCESS)
1998 qSqlWarning(
"QODBCDriver::cleanup: Unable to free connection handle"_L1,
d);
2003 r = SQLFreeHandle(SQL_HANDLE_ENV,
d->hEnv);
2004 if (
r != SQL_SUCCESS)
2005 qSqlWarning(
"QODBCDriver::cleanup: Unable to free environment handle"_L1,
d);
2018 r = SQLGetInfo(
hDbc,
2023 if ((
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WCHAR)) {
2028 r = SQLGetInfo(
hDbc,
2029 SQL_CONVERT_VARCHAR,
2033 if ((
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WVARCHAR)) {
2038 r = SQLGetInfo(
hDbc,
2039 SQL_CONVERT_LONGVARCHAR,
2043 if ((
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WLONGVARCHAR)) {
2048 r = SQLAllocHandle(SQL_HANDLE_STMT,
2054 const auto statements = {
2056 "values('test')"_L1,
2057 "select 'test' from dual"_L1,
2059 for (
const auto &statement : statements) {
2062 if (
r == SQL_SUCCESS)
2065 if (
r == SQL_SUCCESS) {
2066 r = SQLFetch(hStmt);
2067 if (
r == SQL_SUCCESS) {
2069 r = SQLGetData(hStmt, 1, SQL_C_WCHAR,
buffer.data(),
buffer.size() *
sizeof(SQLWCHAR), NULL);
2075 r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
2080#ifdef ODBC_CHECK_DRIVER
2081 static constexpr SQLUSMALLINT reqFunc[] = {
2082 SQL_API_SQLDESCRIBECOL, SQL_API_SQLGETDATA, SQL_API_SQLCOLUMNS,
2083 SQL_API_SQLGETSTMTATTR, SQL_API_SQLGETDIAGREC, SQL_API_SQLEXECDIRECT,
2084 SQL_API_SQLGETINFO, SQL_API_SQLTABLES
2088 static constexpr SQLUSMALLINT optFunc[] = {
2089 SQL_API_SQLNUMRESULTCOLS, SQL_API_SQLROWCOUNT
2096 for (
const SQLUSMALLINT
func : reqFunc) {
2100 if (
r != SQL_SUCCESS) {
2101 qSqlWarning(
"QODBCDriver::checkDriver: Cannot get list of supported functions"_L1,
this);
2104 if (sup == SQL_FALSE) {
2105 qWarning () <<
"QODBCDriver::open: Warning - Driver doesn't support all needed functionality ("
2107 <<
").\nPlease look at the Qt SQL Module Driver documentation for more information.";
2113 for (
const SQLUSMALLINT
func : optFunc) {
2117 if (
r != SQL_SUCCESS) {
2118 qSqlWarning(
"QODBCDriver::checkDriver: Cannot get list of supported functions"_L1,
this);
2121 if (sup == SQL_FALSE) {
2122 qWarning() <<
"QODBCDriver::checkDriver: Warning - Driver doesn't support some non-critical functions ("
2137 r = SQLGetInfo(
hDbc,
2142 if (
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO)
2152 r = SQLGetInfo(
hDbc,
2154 serverString.
data(),
2155 SQLSMALLINT(serverString.
size() *
sizeof(SQLTCHAR)),
2157 if (
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO) {
2170 r = SQLGetInfo(
hDbc,
2172 serverString.
data(),
2173 SQLSMALLINT(serverString.
size() *
sizeof(SQLTCHAR)),
2175 if (
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO) {
2185 SQLRETURN
r = SQLGetFunctions(
hDbc, SQL_API_SQLFETCHSCROLL, &sup);
2186 if ((
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO) || sup != SQL_TRUE) {
2188 qWarning(
"QODBCDriver::checkHasSQLFetchScroll: Warning - Driver doesn't support scrollable result sets, use forward only mode for queries");
2196 SQLRETURN
r = SQLGetInfo(
hDbc,
2197 SQL_MULT_RESULT_SETS,
2198 driverResponse.
data(),
2199 SQLSMALLINT(driverResponse.
size() *
sizeof(SQLTCHAR)),
2201 if (
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO)
2207 SQLINTEGER columnSize;
2210 SQLRETURN
r = SQLAllocHandle(SQL_HANDLE_STMT,
hDbc, &hStmt);
2211 if (
r != SQL_SUCCESS) {
2215 r = SQLGetTypeInfo(hStmt, SQL_TIMESTAMP);
2216 if (
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO) {
2217 r = SQLFetch(hStmt);
2218 if (
r == SQL_SUCCESS ||
r == SQL_SUCCESS_WITH_INFO )
2220 if (SQLGetData(hStmt, 3, SQL_INTEGER, &columnSize,
sizeof(columnSize), 0) == SQL_SUCCESS) {
2225 SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
2237 qWarning(
"QODBCDriver::beginTransaction: Database not open");
2240 SQLUINTEGER ac(SQL_AUTOCOMMIT_OFF);
2241 SQLRETURN
r = SQLSetConnectAttr(
d->hDbc,
2242 SQL_ATTR_AUTOCOMMIT,
2243 (SQLPOINTER)
size_t(ac),
2245 if (
r != SQL_SUCCESS) {
2257 qWarning(
"QODBCDriver::commitTransaction: Database not open");
2260 SQLRETURN
r = SQLEndTran(SQL_HANDLE_DBC,
2263 if (
r != SQL_SUCCESS) {
2275 qWarning(
"QODBCDriver::rollbackTransaction: Database not open");
2278 SQLRETURN
r = SQLEndTran(SQL_HANDLE_DBC,
2281 if (
r != SQL_SUCCESS) {
2289bool QODBCDriver::endTrans()
2292 SQLUINTEGER ac(SQL_AUTOCOMMIT_ON);
2293 SQLRETURN
r = SQLSetConnectAttr(
d->hDbc,
2294 SQL_ATTR_AUTOCOMMIT,
2295 (SQLPOINTER)
size_t(ac),
2297 if (
r != SQL_SUCCESS) {
2312 SQLRETURN
r = SQLAllocHandle(SQL_HANDLE_STMT,
2315 if (
r != SQL_SUCCESS) {
2316 qSqlWarning(
"QODBCDriver::tables: Unable to allocate handle"_L1,
d);
2319 r = SQLSetStmtAttr(hStmt,
2320 SQL_ATTR_CURSOR_TYPE,
2321 (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
2325 tableType +=
"TABLE"_L1;
2327 tableType +=
"VIEW"_L1;
2329 tableType +=
"SYSTEM TABLE"_L1;
2330 if (tableType.isEmpty())
2334 auto joinedTableTypeString =
toSQLTCHAR(tableType.join(u
','));
2336 r = SQLTables(hStmt,
2340 joinedTableTypeString.data(), joinedTableTypeString.size());
2343 if (
r != SQL_SUCCESS)
2344 qSqlWarning(
"QODBCDriver::tables Unable to execute table list"_L1,
d);
2346 if (
d->hasSQLFetchScroll)
2347 r = SQLFetchScroll(hStmt,
2351 r = SQLFetch(hStmt);
2353 if (
r != SQL_SUCCESS &&
r != SQL_SUCCESS_WITH_INFO &&
r != SQL_NO_DATA) {
2354 qSqlWarning(
"QODBCDriver::tables failed to retrieve table/view list: ("_L1
2360 while (
r == SQL_SUCCESS) {
2363 if (
d->hasSQLFetchScroll)
2364 r = SQLFetchScroll(hStmt,
2368 r = SQLFetch(hStmt);
2371 r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
2372 if (
r!= SQL_SUCCESS)
2383 bool usingSpecialColumns =
false;
2387 SQLRETURN
r = SQLAllocHandle(SQL_HANDLE_STMT,
2390 if (
r != SQL_SUCCESS) {
2391 qSqlWarning(
"QODBCDriver::primaryIndex: Unable to list primary key"_L1,
d);
2395 d->splitTableQualifier(tablename, catalog, schema,
table);
2400 catalog =
d->adjustCase(catalog);
2405 schema =
d->adjustCase(schema);
2412 r = SQLSetStmtAttr(hStmt,
2413 SQL_ATTR_CURSOR_TYPE,
2414 (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
2420 r = SQLPrimaryKeys(hStmt,
2421 catalog.
isEmpty() ?
nullptr :
c.data(),
c.size(),
2423 t.data(),
t.size());
2429 if (
r != SQL_SUCCESS) {
2433 r = SQLSpecialColumns(hStmt,
2435 catalog.
isEmpty() ?
nullptr :
c.data(),
c.size(),
2441 if (
r != SQL_SUCCESS) {
2442 qSqlWarning(
"QODBCDriver::primaryIndex: Unable to execute primary key list"_L1,
d);
2444 usingSpecialColumns =
true;
2448 if (
d->hasSQLFetchScroll)
2449 r = SQLFetchScroll(hStmt,
2453 r = SQLFetch(hStmt);
2458 while (
r == SQL_SUCCESS) {
2459 if (usingSpecialColumns) {
2467 index.setName(idxName);
2469 if (
d->hasSQLFetchScroll)
2470 r = SQLFetchScroll(hStmt,
2474 r = SQLFetch(hStmt);
2477 r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
2478 if (
r!= SQL_SUCCESS)
2492 d->splitTableQualifier(tablename, catalog, schema,
table);
2497 catalog =
d->adjustCase(catalog);
2502 schema =
d->adjustCase(schema);
2509 SQLRETURN
r = SQLAllocHandle(SQL_HANDLE_STMT,
2512 if (
r != SQL_SUCCESS) {
2513 qSqlWarning(
"QODBCDriver::record: Unable to allocate handle"_L1,
d);
2516 r = SQLSetStmtAttr(hStmt,
2517 SQL_ATTR_CURSOR_TYPE,
2518 (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
2524 r = SQLColumns(hStmt,
2525 catalog.
isEmpty() ?
nullptr :
c.data(),
c.size(),
2531 if (
r != SQL_SUCCESS)
2532 qSqlWarning(
"QODBCDriver::record: Unable to execute column list"_L1,
d);
2534 if (
d->hasSQLFetchScroll)
2535 r = SQLFetchScroll(hStmt,
2539 r = SQLFetch(hStmt);
2542 while (
r == SQL_SUCCESS) {
2546 if (
d->hasSQLFetchScroll)
2547 r = SQLFetchScroll(hStmt,
2551 r = SQLFetch(hStmt);
2554 r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
2555 if (
r!= SQL_SUCCESS)
2562 bool trimStrings)
const
2567 }
else if (field.
metaType().
id() == QMetaType::QDateTime) {
2583 }
else if (field.
metaType().
id() == QMetaType::QByteArray) {
2587 for (
const char c :
ba) {
2601 return QVariant(QMetaType::fromType<SQLHANDLE>(), &
d->hDbc);
2611 res.replace(
quote, quoteStr + quoteStr);
2612 res.replace(u
'.', quoteStr + u
'.' + quoteStr);
2622 return identifier.
size() > 2
2629#include "moc_qsql_odbc_p.cpp"
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
void reserve(qsizetype size)
Attempts to allocate memory for at least size bytes.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
qsizetype length() const noexcept
Same as size().
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
\threadsafe
\inmodule QtCore\reentrant
QTime time() const
Returns the time part of the datetime.
bool isValid() const
Returns true if this datetime represents a definite moment, otherwise false.
QDate date() const
Returns the date part of the datetime.
\inmodule QtCore \reentrant
int month() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
int day() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
int year() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
QList< T > & fill(parameter_type t, qsizetype size=-1)
bool empty() const noexcept
const_reference at(qsizetype i) const noexcept
qsizetype count() const noexcept
void checkHasMultiResults()
DefaultCase defaultCase() const
bool setConnectionOptions(const QString &connOpts)
void checkHasSQLFetchScroll()
void splitTableQualifier(const QString &qualifier, QString &catalog, QString &schema, QString &table) const
QString adjustCase(const QString &) const
void checkDateTimePrecision()
QString formatValue(const QSqlField &field, bool trimStrings) const override
Returns a string representation of the field value for the database.
QSqlResult * createResult() const override
Creates an empty SQL result on the database.
QODBCDriver(QObject *parent=nullptr)
QString escapeIdentifier(const QString &identifier, IdentifierType type) const override
Returns the identifier escaped according to the database rules.
QVariant handle() const override
Returns the low-level database handle wrapped in a QVariant or an invalid variant if there is no hand...
bool isIdentifierEscaped(const QString &identifier, IdentifierType type) const override
Returns whether identifier is escaped according to the database rules.
bool beginTransaction() override
This function is called to begin a transaction.
void close() override
Derived classes must reimplement this pure virtual function in order to close the database connection...
bool rollbackTransaction() override
This function is called to rollback a transaction.
QSqlIndex primaryIndex(const QString &tablename) const override
Returns the primary index for table tableName.
bool hasFeature(DriverFeature f) const override
Returns true if the driver supports feature feature; otherwise returns false.
bool open(const QString &db, const QString &user, const QString &password, const QString &host, int port, const QString &connOpts) override
Derived classes must reimplement this pure virtual function to open a database connection on database...
bool commitTransaction() override
This function is called to commit a transaction.
QSqlRecord record(const QString &tablename) const override
Returns a QSqlRecord populated with the names of the fields in table tableName.
QStringList tables(QSql::TableType) const override
Returns a list of the names of the tables in the database.
bool isStmtHandleValid() const
void updateStmtHandleState()
bool prepare(const QString &query) override
Prepares the given query for execution; the query will normally use placeholders so that it can be ex...
int numRowsAffected() override
Returns the number of rows affected by the last query executed, or -1 if it cannot be determined or i...
QVariant data(int field) override
Returns the data for field index in the current row as a QVariant.
QSqlRecord record() const override
Returns the current record if the query is active; otherwise returns an empty QSqlRecord.
bool nextResult() override
int size() override
Returns the size of the SELECT result, or -1 if it cannot be determined or if the query is not a SELE...
bool fetchFirst() override
Positions the result to the first record (row 0) in the result.
bool exec() override
Executes the query, returning true if successful; otherwise returns false.
void detachFromResultSet() override
QVariant lastInsertId() const override
Returns the object ID of the most recent inserted row if the database supports it.
void virtual_hook(int id, void *data) override
bool reset(const QString &query) override
Sets the result to use the SQL statement query for subsequent data retrieval.
bool fetchLast() override
Positions the result to the last record (last row) in the result.
bool isNull(int field) override
Returns true if the field at position index in the current row is null; otherwise returns false.
bool fetchPrevious() override
Positions the result to the previous record (row) in the result.
bool fetchNext() override
Positions the result to the next available record (row) in the result.
bool fetch(int i) override
Positions the result to an arbitrary (zero-based) row index.
QODBCResult(const QODBCDriver *db)
QVariant handle() const override
Returns the low-level database handle for this result set wrapped in a QVariant or an invalid QVarian...
QSqlDriverPrivate(QSqlDriver::DbmsType type=QSqlDriver::UnknownDbms)
QSqlDriver::DbmsType dbmsType
The QSqlDriver class is an abstract base class for accessing specific SQL databases.
virtual QString formatValue(const QSqlField &field, bool trimStrings=false) const
Returns a string representation of the field value for the database.
IdentifierType
This enum contains a list of SQL identifier types.
virtual QString stripDelimiters(const QString &identifier, IdentifierType type) const
Returns the identifier with the leading and trailing delimiters removed, identifier can either be a t...
DriverFeature
This enum contains a list of features a driver might support.
virtual void setLastError(const QSqlError &e)
This function is used to set the value of the last error, error, that occurred on the database.
virtual bool isOpen() const
Returns true if the database connection is open; otherwise returns false.
virtual void setOpenError(bool e)
This function sets the open error state of the database to error.
virtual void setOpen(bool o)
This function sets the open state of the database to open.
The QSqlError class provides SQL database error information.
ErrorType
This enum type describes the context in which the error occurred, e.g., a connection error,...
The QSqlField class manipulates the fields in SQL database tables and views.
QMetaType metaType() const
Returns the field's type as stored in the database.
QVariant value() const
Returns the value of the field as a QVariant.
bool isNull() const
Returns true if the field's value is NULL; otherwise returns false.
The QSqlIndex class provides functions to manipulate and describe database indexes.
The QSqlQuery class provides a means of executing and manipulating SQL statements.
bool next()
Retrieves the next record in the result, if available, and positions the query on the retrieved recor...
QVariant value(int i) const
Returns the value of field index in the current record.
bool exec(const QString &query)
Executes the SQL in query.
The QSqlRecord class encapsulates a database record.
QSqlField field(int i) const
Returns the field at position index.
void append(const QSqlField &field)
Append a copy of field field to the end of the record.
static bool isVariantNull(const QVariant &variant)
The QSqlResult class provides an abstract interface for accessing data from specific SQL databases.
bool isForwardOnly() const
Returns true if you can only scroll forward through the result set; otherwise returns false.
QSql::ParamType bindValueType(const QString &placeholder) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
virtual void virtual_hook(int id, void *data)
int at() const
Returns the current (zero-based) row position of the result.
bool isSelect() const
Returns true if the current result is from a SELECT statement; otherwise returns false.
virtual void setAt(int at)
This function is provided for derived classes to set the internal (zero-based) row position to index.
virtual void setSelect(bool s)
This function is provided for derived classes to indicate whether or not the current statement is a S...
bool hasOutValues() const
Returns true if at least one of the query's bound values is a QSql::Out or a QSql::InOut; otherwise r...
virtual void setActive(bool a)
This function is provided for derived classes to set the internal active state to active.
QVariantList & boundValues(QT6_DECL_NEW_OVERLOAD)
QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const
virtual void setLastError(const QSqlError &e)
This function is provided for derived classes to set the last error to error.
const QSqlDriver * driver() const
Returns the driver associated with the result.
virtual void setForwardOnly(bool forward)
Sets forward only mode to forward.
bool isActive() const
Returns true if the result has records to be retrieved; otherwise returns false.
Encoding
\value Utf8 Create a converter to or from UTF-8 \value Utf16 Create a converter to or from UTF-16.
char * appendToBuffer(char *out, QStringView in)
Encodes in and writes the encoded result into the buffer starting at out.
qsizetype requiredSpace(qsizetype inputLength) const
Returns the maximum amount of characters required to be able to process inputLength decoded data.
Q_CORE_EXPORT QList< QStringView > split(QStringView sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the view into substring views wherever sep occurs, and returns the list of those string views.
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
QString rightJustified(qsizetype width, QChar fill=u' ', bool trunc=false) const
Returns a string of size() width that contains the fill character followed by the string.
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
static QString fromUtf16(const char16_t *, qsizetype size=-1)
static QString fromUcs4(const char32_t *, qsizetype size=-1)
void clear()
Clears the contents of the string and makes it null.
const QChar * constData() const
Returns a pointer to the data stored in the QString.
qsizetype size() const
Returns the number of characters in this string.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
QString simplified() const &
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
QString toLower() const &
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString & append(QChar c)
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
QByteArray toUtf8() const &
QString toUpper() const &
qsizetype length() const
Returns the number of characters in this string.
\inmodule QtCore \reentrant
int hour() const
Returns the hour part (0 to 23) of the time.
int minute() const
Returns the minute part (0 to 59) of the time.
int msec() const
Returns the millisecond part (0 to 999) of the time.
int second() const
Returns the second part (0 to 59) of the time.
constexpr size_type size() const noexcept
void resize(qsizetype sz)
QDateTime toDateTime() const
Returns the variant as a QDateTime if the variant has userType() \l QMetaType::QDateTime,...
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
bool isNull() const
Returns true if this is a null variant, false otherwise.
QByteArray toByteArray() const
Returns the variant as a QByteArray if the variant has userType() \l QMetaType::QByteArray or \l QMet...
Combined button and popup list for selecting options.
constexpr char toHexLower(char32_t value) noexcept
#define SIZE(large, small, mini)
constexpr const T & qMin(const T &a, const T &b)
GLenum GLsizei GLsizei GLint * values
[15]
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLuint64 GLenum void * handle
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLenum GLuint GLenum GLsizei const GLchar * buf
GLuint64 GLenum handleType
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei void GLsizei void * column
GLdouble GLdouble GLdouble GLdouble q
GLenum GLenum GLenum input
GLenum GLenum GLsizei void * table
GLenum GLint GLint * precision
GLsizei const GLchar *const * string
[0]
static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
static QSqlField qMakeFieldInfo(const QDB2ResultPrivate *d, int i)
static void qSqlWarning(const QString &message, const QDB2DriverPrivate *d)
static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool &isNull)
static QSqlError qMakeError(const QString &err, QSqlError::ErrorType type, const QDB2DriverPrivate *p)
QStringConverter::Encoding encodingForSqlTChar()
static bool isAutoValue(const SQLHANDLE hStmt, int column)
static QSqlField qMakeFieldInfo(const SQLHANDLE hStmt, int i, QString *errorMessage)
static QVarLengthArray< SQLTCHAR > toSQLTCHAR(const QString &input)
static QVariant qGetStringData(SQLHANDLE hStmt, SQLUSMALLINT column, int colSize, bool unicode)
static DiagRecord combineRecords(const QList< DiagRecord > &records)
static QList< DiagRecord > qODBCWarn(const SQLHANDLE hStmt, const SQLHANDLE envHandle=nullptr, const SQLHANDLE pDbC=nullptr)
static QMetaType qDecodeODBCType(SQLSMALLINT sqltype, bool isSigned=true)
static QString fromSQLTCHAR(const C &input, qsizetype size=-1)
static QVariant qGetBinaryData(SQLHANDLE hStmt, int column)
static constexpr int COLNAMESIZE
static QVariant qGetBigIntData(SQLHANDLE hStmt, int column, bool isSigned=true)
static QString errorStringFromDiagRecords(const QList< DiagRecord > &records)
static QSqlError errorFromDiagRecords(const QString &err, QSqlError::ErrorType type, const QList< DiagRecord > &records)
static QSqlError qMakeError(const QString &err, QSqlError::ErrorType type, const QODBCResultPrivate *p)
static QVariant qGetDoubleData(SQLHANDLE hStmt, int column)
static QVariant getStringDataImpl(SQLHANDLE hStmt, SQLUSMALLINT column, qsizetype colSize, SQLSMALLINT targetType)
static constexpr SQLSMALLINT qParamType[4]
static void qSqlWarning(const QString &message, T &&val)
static QVariant qGetIntData(SQLHANDLE hStmt, int column, bool isSigned=true)
static constexpr SQLSMALLINT TABLENAMESIZE
static QList< DiagRecord > qWarnODBCHandle(int handleType, SQLHANDLE handle)
static SQLRETURN qt_string_SQLSetConnectAttr(SQLHDBC handle, SQLINTEGER attr, const QString &val)
static size_t qGetODBCVersion(const QString &connOpts)
#define Q_DECLARE_SQLDRIVER_PRIVATE(Class)
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define QStringLiteral(str)
unsigned long long quint64
static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
static QString quote(const QString &str)
ReturnedValue read(const char *data)
QFileInfo info(fileName)
[8]
\inmodule QtCore \reentrant
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent