7#if defined (Q_OS_WIN32)
24#include <QtSql/private/qsqldriver_p.h>
25#include <QtSql/private/qsqlresult_p.h>
26#include "private/qtools_p.h"
32using namespace
Qt::StringLiterals;
36#define SQL_SS_TIME2 (-154)
40#define ODBC_CHECK_DRIVER
45static constexpr SQLSMALLINT
qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT };
52 SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &
stmtHandle);
70template<
typename C,
int SIZE = sizeof(SQLTCHAR)>
75 if (realsize > 0 &&
input[realsize - 1] == 0)
77 if constexpr (
SIZE == 1)
79 else if constexpr (
SIZE == 2)
81 else if constexpr (
SIZE == 4)
85 "Don't know how to handle sizeof(SQLTCHAR) != 1/2/4");
88template<
int SIZE = sizeof(SQLTCHAR)>
91 if constexpr (
SIZE == 1)
93 else if constexpr (
SIZE == 2)
95 else if constexpr (
SIZE == 4)
99 "Don't know how to handle sizeof(SQLTCHAR) != 1/2/4");
104 QVarLengthArray<SQLTCHAR>
result;
107 const auto end = enc.appendToBuffer(
reinterpret_cast<char *
>(
result.data()),
input);
108 result.resize((
end -
reinterpret_cast<char *
>(
result.data())) /
sizeof(SQLTCHAR));
147 bool isQuoteInitialized =
false;
163 bool exec()
override;
173 bool fetch(
int i)
override;
176 bool isNull(
int field)
override;
194 unicode = drv_d_func()->unicode;
203 SQLHANDLE
dpEnv()
const {
return drv_d_func() ? drv_d_func()->hEnv : 0;}
204 SQLHANDLE
dpDbc()
const {
return drv_d_func() ? drv_d_func()->hDbc : 0;}
221 return drv_d_func() &&
disconnectCount == drv_d_func()->disconnectCount;
237 SQLINTEGER nativeCode = 0;
238 SQLSMALLINT msgLen = 0;
240 SQLRETURN
r = SQL_NO_DATA;
241 QVarLengthArray<SQLTCHAR, SQL_SQLSTATE_SIZE + 1>
state(SQL_SQLSTATE_SIZE + 1);
242 QVarLengthArray<SQLTCHAR, SQL_MAX_MESSAGE_LENGTH + 1> description(SQL_MAX_MESSAGE_LENGTH + 1);
256 if (msgLen >= description.size()) {
257 description.resize(msgLen + 1);
260 if (SQL_SUCCEEDED(
r)) {
264 }
else if (
r == SQL_ERROR ||
r == SQL_INVALID_HANDLE) {
268 }
while (
r != SQL_NO_DATA);
272static QList<DiagRecord>
qODBCWarn(
const SQLHANDLE hStmt,
273 const SQLHANDLE envHandle =
nullptr,
274 const SQLHANDLE pDbC =
nullptr)
285 return qODBCWarn(odbc->hStmt, odbc->dpEnv(), odbc->dpDbc());
290 return qODBCWarn(
nullptr, odbc->hEnv, odbc->hDbc);
297 a.sqlState + u
';' +
b.sqlState,
298 a.errorCode + u
';' +
b.errorCode};
300 if (records.isEmpty())
302 return std::accumulate(std::next(records.begin()), records.end(), records.front(),
add);
307 const QList<DiagRecord> &records)
312 return QSqlError(
"QODBC: "_L1 + err, combined.description +
", "_L1 + combined.sqlState,
type,
319 return combined.description;
326 if (addMsg.isEmpty())
354 type = QMetaType::Double;
357 type = QMetaType::Float;
360 type = isSigned ? QMetaType::Short : QMetaType::UShort;
364 type = isSigned ? QMetaType::Int : QMetaType::UInt;
367 type = QMetaType::UInt;
370 type = isSigned ? QMetaType::LongLong : QMetaType::ULongLong;
374 case SQL_LONGVARBINARY:
375 type = QMetaType::QByteArray;
379 type = QMetaType::QDate;
384 type = QMetaType::QTime;
387 case SQL_TYPE_TIMESTAMP:
388 type = QMetaType::QDateTime;
392 case SQL_WLONGVARCHAR:
393 type = QMetaType::QString;
397#if (ODBCVER >= 0x0350)
400 case SQL_LONGVARCHAR:
401 type = QMetaType::QString;
404 type = QMetaType::QByteArray;
410template <
typename CT>
414 SQLRETURN
r = SQL_ERROR;
415 SQLLEN lengthIndicator = 0;
416 QVarLengthArray<CT>
buf(colSize);
418 r = SQLGetData(hStmt,
421 SQLPOINTER(
buf.data()), SQLINTEGER(
buf.size() *
sizeof(CT)),
423 if (SQL_SUCCEEDED(
r)) {
424 if (lengthIndicator == SQL_NULL_DATA) {
433 if (lengthIndicator == SQL_NO_TOTAL) {
434 fieldVal += fromSQLTCHAR<QVarLengthArray<CT>,
sizeof(CT)>(
buf,
buf.size());
441 const qsizetype rSize = (
r == SQL_SUCCESS_WITH_INFO)
443 :
qsizetype(lengthIndicator /
sizeof(CT));
444 fieldVal += fromSQLTCHAR<QVarLengthArray<CT>,
sizeof(CT)>(
buf, rSize);
446 if (lengthIndicator < SQLLEN((
buf.size() - 1) *
sizeof(CT))) {
450 }
else if (
r == SQL_NO_DATA) {
453 qSqlWarning(
"QODBC::getStringData: Error while fetching data"_L1, hStmt);
464 }
else if (colSize > 65536) {
469 return unicode ? getStringDataImpl<SQLTCHAR>(hStmt,
column, colSize, SQL_C_TCHAR)
470 : getStringDataImpl<SQLCHAR>(hStmt,
column, colSize, SQL_C_CHAR);
476 SQLSMALLINT colNameLen;
479 SQLSMALLINT colScale;
480 SQLSMALLINT nullable;
481 SQLLEN lengthIndicator = 0;
482 SQLRETURN
r = SQL_ERROR;
484 QVarLengthArray<SQLTCHAR, COLNAMESIZE> colName(
COLNAMESIZE);
486 r = SQLDescribeCol(hStmt,
488 colName.data(), SQLSMALLINT(colName.size()),
494 if (
r != SQL_SUCCESS)
495 qSqlWarning((
"QODBC::qGetBinaryData: Unable to describe column %1"_L1)
500 else if (colSize > 65536)
502 fieldVal.resize(colSize);
505 r = SQLGetData(hStmt,
508 const_cast<char *
>(fieldVal.constData() +
read),
511 if (!SQL_SUCCEEDED(
r))
513 if (lengthIndicator == SQL_NULL_DATA)
515 if (lengthIndicator > SQLLEN(colSize) || lengthIndicator == SQL_NO_TOTAL) {
519 read += lengthIndicator;
521 if (
r == SQL_SUCCESS) {
522 fieldVal.resize(
read);
525 fieldVal.resize(fieldVal.size() + colSize);
532 SQLINTEGER intbuf = 0;
533 SQLLEN lengthIndicator = 0;
534 SQLRETURN
r = SQLGetData(hStmt,
536 isSigned ? SQL_C_SLONG : SQL_C_ULONG,
540 if (!SQL_SUCCEEDED(
r))
542 if (lengthIndicator == SQL_NULL_DATA)
543 return QVariant(QMetaType::fromType<int>());
553 SQLLEN lengthIndicator = 0;
554 SQLRETURN
r = SQLGetData(hStmt,
557 (SQLPOINTER) &dblbuf,
560 if (!SQL_SUCCEEDED(
r)) {
563 if (lengthIndicator == SQL_NULL_DATA)
564 return QVariant(QMetaType::fromType<double>());
566 return (
double) dblbuf;
572 SQLBIGINT lngbuf = 0;
573 SQLLEN lengthIndicator = 0;
574 SQLRETURN
r = SQLGetData(hStmt,
576 isSigned ? SQL_C_SBIGINT : SQL_C_UBIGINT,
577 (SQLPOINTER) &lngbuf,
580 if (!SQL_SUCCEEDED(
r))
582 if (lengthIndicator == SQL_NULL_DATA)
583 return QVariant(QMetaType::fromType<qlonglong>());
593 SQLLEN nNumericAttribute = 0;
594 const SQLRETURN
r = ::SQLColAttribute(hStmt,
column + 1, SQL_DESC_AUTO_UNIQUE_VALUE,
595 0, 0, 0, &nNumericAttribute);
596 if (!SQL_SUCCEEDED(
r)) {
597 qSqlWarning((
"QODBC::isAutoValue: Unable to get autovalue attribute for column %1"_L1)
601 return nNumericAttribute != SQL_FALSE;
617 if (required == SQL_NO_NULLS)
619 else if (required == SQL_NULLABLE)
620 f.setRequired(
false);
627 SQLSMALLINT colNameLen;
630 SQLSMALLINT colScale;
631 SQLSMALLINT nullable;
632 SQLRETURN
r = SQL_ERROR;
633 QVarLengthArray<SQLTCHAR, COLNAMESIZE> colName(
COLNAMESIZE);
634 r = SQLDescribeCol(
p->hStmt,
636 colName.data(), SQLSMALLINT(colName.size()),
643 if (
r != SQL_SUCCESS) {
644 qSqlWarning((
"QODBC::qMakeFieldInfo: Unable to describe column %1"_L1)
649 SQLLEN unsignedFlag = SQL_FALSE;
650 r = SQLColAttribute (
p->hStmt,
657 if (
r != SQL_SUCCESS) {
658 qSqlWarning((
"QODBC::qMakeFieldInfo: Unable to get column attributes for column %1"_L1)
666 f.setLength(colSize == 0 ? -1 : int(colSize));
667 f.setPrecision(colScale == 0 ? -1 : int(colScale));
668 if (nullable == SQL_NO_NULLS)
670 else if (nullable == SQL_NULLABLE)
671 f.setRequired(
false);
674 QVarLengthArray<SQLTCHAR, TABLENAMESIZE> tableName(
TABLENAMESIZE);
675 SQLSMALLINT tableNameLen;
676 r = SQLColAttribute(
p->hStmt,
678 SQL_DESC_BASE_TABLE_NAME,
680 SQLSMALLINT(tableName.size() *
sizeof(SQLTCHAR)),
683 if (
r == SQL_SUCCESS)
684 f.setTableName(
fromSQLTCHAR(tableName, tableNameLen /
sizeof(SQLTCHAR)));
697 if (!isQuoteInitialized) {
698 SQLTCHAR driverResponse[4];
700 int r = SQLGetInfo(
hDbc,
701 SQL_IDENTIFIER_QUOTE_CHAR,
703 sizeof(driverResponse),
705 if (SQL_SUCCEEDED(
r))
706 quote =
QChar(driverResponse[0]);
709 isQuoteInitialized =
true;
722 return SQLFetchScroll(hStmt, SQL_FETCH_NEXT, 0);
723 return SQLFetch(hStmt);
729 return SQLSetConnectAttr(
handle, attr,
738 SQLRETURN
r = SQL_SUCCESS;
741 if ((idx = connOpt.indexOf(u
'=')) == -1) {
742 qSqlWarning((
"QODBCDriver::open: Illegal connect option value '%1'"_L1)
743 .
arg(connOpt),
this);
746 const auto opt(connOpt.left(idx));
747 const auto val(connOpt.mid(idx + 1).trimmed());
751 if (
opt ==
"SQL_ATTR_ACCESS_MODE"_L1) {
752 if (
val ==
"SQL_MODE_READ_ONLY"_L1) {
753 v = SQL_MODE_READ_ONLY;
754 }
else if (
val ==
"SQL_MODE_READ_WRITE"_L1) {
755 v = SQL_MODE_READ_WRITE;
757 qSqlWarning((
"QODBCDriver::open: Unknown option value '%1'"_L1)
761 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_ACCESS_MODE, (SQLPOINTER)
size_t(
v), 0);
762 }
else if (
opt ==
"SQL_ATTR_CONNECTION_TIMEOUT"_L1) {
764 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER)
size_t(
v), 0);
765 }
else if (
opt ==
"SQL_ATTR_LOGIN_TIMEOUT"_L1) {
767 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)
size_t(
v), 0);
768 }
else if (
opt ==
"SQL_ATTR_CURRENT_CATALOG"_L1) {
770 }
else if (
opt ==
"SQL_ATTR_METADATA_ID"_L1) {
771 if (
val ==
"SQL_TRUE"_L1) {
773 }
else if (
val ==
"SQL_FALSE"_L1) {
776 qSqlWarning((
"QODBCDriver::open: Unknown option value '%1'"_L1)
780 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_METADATA_ID, (SQLPOINTER)
size_t(
v), 0);
781 }
else if (
opt ==
"SQL_ATTR_PACKET_SIZE"_L1) {
783 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_PACKET_SIZE, (SQLPOINTER)
size_t(
v), 0);
784 }
else if (
opt ==
"SQL_ATTR_TRACEFILE"_L1) {
786 }
else if (
opt ==
"SQL_ATTR_TRACE"_L1) {
787 if (
val ==
"SQL_OPT_TRACE_OFF"_L1) {
788 v = SQL_OPT_TRACE_OFF;
789 }
else if (
val ==
"SQL_OPT_TRACE_ON"_L1) {
790 v = SQL_OPT_TRACE_ON;
792 qSqlWarning((
"QODBCDriver::open: Unknown option value '%1'"_L1)
796 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_TRACE, (SQLPOINTER)
size_t(
v), 0);
797 }
else if (
opt ==
"SQL_ATTR_CONNECTION_POOLING"_L1) {
798 if (
val ==
"SQL_CP_OFF"_L1)
800 else if (
val ==
"SQL_CP_ONE_PER_DRIVER"_L1)
801 v = SQL_CP_ONE_PER_DRIVER;
802 else if (
val ==
"SQL_CP_ONE_PER_HENV"_L1)
803 v = SQL_CP_ONE_PER_HENV;
804 else if (
val ==
"SQL_CP_DEFAULT"_L1)
807 qSqlWarning((
"QODBCDriver::open: Unknown option value '%1'"_L1)
811 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_CONNECTION_POOLING, (SQLPOINTER)
size_t(
v), 0);
812 }
else if (
opt ==
"SQL_ATTR_CP_MATCH"_L1) {
813 if (
val ==
"SQL_CP_STRICT_MATCH"_L1)
814 v = SQL_CP_STRICT_MATCH;
815 else if (
val ==
"SQL_CP_RELAXED_MATCH"_L1)
816 v = SQL_CP_RELAXED_MATCH;
817 else if (
val ==
"SQL_CP_MATCH_DEFAULT"_L1)
818 v = SQL_CP_MATCH_DEFAULT;
820 qSqlWarning((
"QODBCDriver::open: Unknown option value '%1'"_L1)
824 r = SQLSetConnectAttr(
hDbc, SQL_ATTR_CP_MATCH, (SQLPOINTER)
size_t(
v), 0);
825 }
else if (
opt ==
"SQL_ATTR_ODBC_VERSION"_L1) {
829 qSqlWarning((
"QODBCDriver::open: Unknown connection attribute '%1'"_L1)
832 if (!SQL_SUCCEEDED(
r))
833 qSqlWarning((
"QODBCDriver::open: Unable to set connection attribute '%1'"_L1)
852 table = adjustName(qualifier);
858 table = adjustName(qualifier);
861 schema = adjustName(l.at(0).toString());
862 table = adjustName(l.at(1).toString());
865 catalog = adjustName(l.at(0).toString());
866 schema = adjustName(l.at(1).toString());
867 table = adjustName(l.at(2).toString());
870 qSqlWarning((
"QODBCDriver::splitTableQualifier: Unable to split table qualifier '%1'"_L1)
871 .
arg(qualifier),
this);
880 SQLRETURN
r = SQLGetInfo(
hDbc,
885 if (
r == SQL_SUCCESS) {
893 case SQL_IC_SENSITIVE:
909 switch (m_defaultCase) {
931 if (
d->hStmt &&
d->isStmtHandleValid() &&
driver() &&
driver()->isOpen()) {
932 SQLRETURN
r = SQLFreeHandle(SQL_HANDLE_STMT,
d->hStmt);
933 if (
r != SQL_SUCCESS)
934 qSqlWarning((
"QODBCResult: Unable to free statement handle "_L1),
d);
944 d->fieldCache.clear();
945 d->fieldCacheIdx = 0;
950 if (
d->hStmt &&
d->isStmtHandleValid()) {
951 r = SQLFreeHandle(SQL_HANDLE_STMT,
d->hStmt);
952 if (
r != SQL_SUCCESS) {
953 qSqlWarning(
"QODBCResult::reset: Unable to free statement handle"_L1,
d);
957 r = SQLAllocHandle(SQL_HANDLE_STMT,
960 if (
r != SQL_SUCCESS) {
961 qSqlWarning(
"QODBCResult::reset: Unable to allocate statement handle"_L1,
d);
965 d->updateStmtHandleState();
968 r = SQLSetStmtAttr(
d->hStmt,
969 SQL_ATTR_CURSOR_TYPE,
970 (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
973 r = SQLSetStmtAttr(
d->hStmt,
974 SQL_ATTR_CURSOR_TYPE,
975 (SQLPOINTER)SQL_CURSOR_STATIC,
978 if (!SQL_SUCCEEDED(
r)) {
980 "QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. "
987 r = SQLExecDirect(
d->hStmt,
991 if (!SQL_SUCCEEDED(
r) &&
r!= SQL_NO_DATA) {
997 SQLULEN isScrollable = 0;
998 r = SQLGetStmtAttr(
d->hStmt, SQL_ATTR_CURSOR_SCROLLABLE, &isScrollable, SQL_IS_INTEGER, 0);
999 if (SQL_SUCCEEDED(
r))
1002 SQLSMALLINT
count = 0;
1003 SQLNumResultCols(
d->hStmt, &
count);
1006 for (SQLSMALLINT
i = 0;
i <
count; ++
i) {
1009 d->fieldCache.resize(
count);
1029 int actualIdx =
i + 1;
1030 if (actualIdx <= 0) {
1037 while (
ok &&
i >
at())
1041 r = SQLFetchScroll(
d->hStmt,
1045 if (
r != SQL_SUCCESS) {
1046 if (
r != SQL_NO_DATA)
1061 if (
d->hasSQLFetchScroll)
1062 r = SQLFetchScroll(
d->hStmt,
1066 r = SQLFetch(
d->hStmt);
1068 if (!SQL_SUCCEEDED(
r)) {
1069 if (
r != SQL_NO_DATA)
1088 r = SQLFetchScroll(
d->hStmt,
1091 if (
r != SQL_SUCCESS) {
1092 if (
r != SQL_NO_DATA)
1108 r = SQLFetchScroll(
d->hStmt,
1111 if (
r != SQL_SUCCESS) {
1112 if (
r != SQL_NO_DATA)
1140 r = SQLFetchScroll(
d->hStmt,
1143 if (
r != SQL_SUCCESS) {
1144 if (
r != SQL_NO_DATA)
1149 SQLULEN currRow = 0;
1150 r = SQLGetStmtAttr(
d->hStmt,
1155 if (
r != SQL_SUCCESS)
1164 if (field >=
d->rInf.count() || field < 0) {
1165 qSqlWarning((
"QODBCResult::data: column %1 out of range"_L1)
1169 if (field < d->fieldCacheIdx)
1170 return d->fieldCache.at(field);
1173 SQLLEN lengthIndicator = 0;
1175 for (
int i =
d->fieldCacheIdx;
i <= field; ++
i) {
1179 switch (
info.metaType().id()) {
1180 case QMetaType::LongLong:
1183 case QMetaType::ULongLong:
1186 case QMetaType::Int:
1187 case QMetaType::Short:
1190 case QMetaType::UInt:
1191 case QMetaType::UShort:
1194 case QMetaType::QDate:
1196 r = SQLGetData(
d->hStmt,
1202 if (SQL_SUCCEEDED(
r) && (lengthIndicator != SQL_NULL_DATA))
1205 d->fieldCache[
i] =
QVariant(QMetaType::fromType<QDate>());
1207 case QMetaType::QTime:
1209 r = SQLGetData(
d->hStmt,
1215 if (SQL_SUCCEEDED(
r) && (lengthIndicator != SQL_NULL_DATA))
1216 d->fieldCache[
i] =
QVariant(
QTime(tbuf.hour, tbuf.minute, tbuf.second));
1218 d->fieldCache[
i] =
QVariant(QMetaType::fromType<QTime>());
1220 case QMetaType::QDateTime:
1221 TIMESTAMP_STRUCT dtbuf;
1222 r = SQLGetData(
d->hStmt,
1228 if (SQL_SUCCEEDED(
r) && (lengthIndicator != SQL_NULL_DATA))
1230 QTime(dtbuf.hour, dtbuf.minute, dtbuf.second, dtbuf.fraction / 1000000)));
1232 d->fieldCache[
i] =
QVariant(QMetaType::fromType<QDateTime>());
1234 case QMetaType::QByteArray:
1237 case QMetaType::QString:
1240 case QMetaType::Double:
1252 const int extra =
info.precision() > 0 ? 1 : 0;
1261 d->fieldCacheIdx = field + 1;
1263 return d->fieldCache[field];
1269 if (field < 0 || field >=
d->fieldCache.size())
1271 if (field >=
d->fieldCacheIdx) {
1277 return d->fieldCache.at(field).isNull();
1288 SQLLEN affectedRowCount = 0;
1289 SQLRETURN
r = SQLRowCount(
d->hStmt, &affectedRowCount);
1290 if (
r == SQL_SUCCESS)
1291 return affectedRowCount;
1292 qSqlWarning(
"QODBCResult::numRowsAffected: Unable to count affected rows"_L1,
d);
1304 if (
d->hStmt &&
d->isStmtHandleValid()) {
1305 r = SQLFreeHandle(SQL_HANDLE_STMT,
d->hStmt);
1306 if (
r != SQL_SUCCESS) {
1307 qSqlWarning(
"QODBCResult::prepare: Unable to close statement"_L1,
d);
1311 r = SQLAllocHandle(SQL_HANDLE_STMT,
1314 if (
r != SQL_SUCCESS) {
1315 qSqlWarning(
"QODBCResult::prepare: Unable to allocate statement handle"_L1,
d);
1319 d->updateStmtHandleState();
1322 r = SQLSetStmtAttr(
d->hStmt,
1323 SQL_ATTR_CURSOR_TYPE,
1324 (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
1327 r = SQLSetStmtAttr(
d->hStmt,
1328 SQL_ATTR_CURSOR_TYPE,
1329 (SQLPOINTER)SQL_CURSOR_STATIC,
1332 if (!SQL_SUCCEEDED(
r)) {
1334 "QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. "
1341 r = SQLPrepare(
d->hStmt,
1346 if (
r != SQL_SUCCESS) {
1360 d->fieldCache.clear();
1361 d->fieldCacheIdx = 0;
1364 qSqlWarning(
"QODBCResult::exec: No statement handle available"_L1,
d);
1369 SQLCloseCursor(
d->hStmt);
1373 QVarLengthArray<SQLLEN, 32> indicators(
values.count(), 0);
1381 SQLLEN *ind = &indicators[
i];
1383 *ind = SQL_NULL_DATA;
1384 switch (
val.typeId()) {
1385 case QMetaType::QDate: {
1388 DATE_STRUCT *dt = (DATE_STRUCT *)
const_cast<char *
>(
ba.
constData());
1390 dt->
year = qdt.year();
1391 dt->month = qdt.month();
1392 dt->day = qdt.day();
1393 r = SQLBindParameter(
d->hStmt,
1402 *ind == SQL_NULL_DATA ? ind : NULL);
1404 case QMetaType::QTime: {
1407 TIME_STRUCT *dt = (TIME_STRUCT *)
const_cast<char *
>(
ba.
constData());
1409 dt->
hour = qdt.hour();
1410 dt->minute = qdt.minute();
1411 dt->second = qdt.second();
1412 r = SQLBindParameter(
d->hStmt,
1421 *ind == SQL_NULL_DATA ? ind : NULL);
1423 case QMetaType::QDateTime: {
1425 ba.
resize(
sizeof(TIMESTAMP_STRUCT));
1426 TIMESTAMP_STRUCT *dt =
reinterpret_cast<TIMESTAMP_STRUCT *
>(
const_cast<char *
>(
ba.
constData()));
1428 const QDate qdate = qdt.date();
1429 const QTime qtime = qdt.time();
1430 dt->year = qdate.year();
1431 dt->month = qdate.month();
1432 dt->day = qdate.day();
1433 dt->
hour = qtime.hour();
1434 dt->minute = qtime.minute();
1435 dt->second = qtime.second();
1437 const int precision =
d->drv_d_func()->datetimePrecision - 20;
1441 dt->fraction = qtime.msec() * 1000000;
1445 dt->fraction = (dt->fraction / keep) * keep;
1448 r = SQLBindParameter(
d->hStmt,
1453 d->drv_d_func()->datetimePrecision,
1457 *ind == SQL_NULL_DATA ? ind : NULL);
1459 case QMetaType::Int:
1460 r = SQLBindParameter(
d->hStmt,
1467 const_cast<void *
>(
val.constData()),
1469 *ind == SQL_NULL_DATA ? ind : NULL);
1471 case QMetaType::UInt:
1472 r = SQLBindParameter(
d->hStmt,
1479 const_cast<void *
>(
val.constData()),
1481 *ind == SQL_NULL_DATA ? ind : NULL);
1483 case QMetaType::Short:
1484 r = SQLBindParameter(
d->hStmt,
1491 const_cast<void *
>(
val.constData()),
1493 *ind == SQL_NULL_DATA ? ind : NULL);
1495 case QMetaType::UShort:
1496 r = SQLBindParameter(
d->hStmt,
1503 const_cast<void *
>(
val.constData()),
1505 *ind == SQL_NULL_DATA ? ind : NULL);
1507 case QMetaType::Double:
1508 r = SQLBindParameter(
d->hStmt,
1515 const_cast<void *
>(
val.constData()),
1517 *ind == SQL_NULL_DATA ? ind : NULL);
1519 case QMetaType::Float:
1520 r = SQLBindParameter(
d->hStmt,
1527 const_cast<void *
>(
val.constData()),
1529 *ind == SQL_NULL_DATA ? ind : NULL);
1531 case QMetaType::LongLong:
1532 r = SQLBindParameter(
d->hStmt,
1539 const_cast<void *
>(
val.constData()),
1541 *ind == SQL_NULL_DATA ? ind : NULL);
1543 case QMetaType::ULongLong:
1544 r = SQLBindParameter(
d->hStmt,
1551 const_cast<void *
>(
val.constData()),
1553 *ind == SQL_NULL_DATA ? ind : NULL);
1555 case QMetaType::QByteArray:
1556 if (*ind != SQL_NULL_DATA) {
1557 *ind =
val.toByteArray().size();
1559 r = SQLBindParameter(
d->hStmt,
1564 val.toByteArray().size(),
1566 const_cast<char *
>(
val.toByteArray().constData()),
1567 val.toByteArray().size(),
1570 case QMetaType::Bool:
1571 r = SQLBindParameter(
d->hStmt,
1578 const_cast<void *
>(
val.constData()),
1580 *ind == SQL_NULL_DATA ? ind : NULL);
1582 case QMetaType::QString:
1591 if (*ind != SQL_NULL_DATA)
1595 r = SQLBindParameter(
d->hStmt,
1599 ba.
size() > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
1607 r = SQLBindParameter(
d->hStmt,
1611 ba.
size() > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
1623 if (*ind != SQL_NULL_DATA)
1627 r = SQLBindParameter(
d->hStmt,
1631 strSize > 254 ? SQL_LONGVARCHAR : SQL_VARCHAR,
1642 if (*ind != SQL_NULL_DATA)
1644 r = SQLBindParameter(
d->hStmt,
1656 if (
r != SQL_SUCCESS) {
1657 qSqlWarning(
"QODBCResult::exec: unable to bind variable:"_L1,
d);
1663 r = SQLExecute(
d->hStmt);
1664 if (!SQL_SUCCEEDED(
r) &&
r != SQL_NO_DATA) {
1665 qSqlWarning(
"QODBCResult::exec: Unable to execute statement:"_L1,
d);
1671 SQLULEN isScrollable = 0;
1672 r = SQLGetStmtAttr(
d->hStmt, SQL_ATTR_CURSOR_SCROLLABLE, &isScrollable, SQL_IS_INTEGER, 0);
1673 if (SQL_SUCCEEDED(
r))
1676 SQLSMALLINT
count = 0;
1677 SQLNumResultCols(
d->hStmt, &
count);
1680 for (SQLSMALLINT
i = 0;
i <
count; ++
i) {
1683 d->fieldCache.resize(
count);
1695 switch (
values.at(
i).typeId()) {
1696 case QMetaType::QDate: {
1697 DATE_STRUCT ds = *((DATE_STRUCT *)
const_cast<char *
>(tmpStorage.at(
i).constData()));
1700 case QMetaType::QTime: {
1701 TIME_STRUCT dt = *((TIME_STRUCT *)
const_cast<char *
>(tmpStorage.at(
i).constData()));
1704 case QMetaType::QDateTime: {
1705 TIMESTAMP_STRUCT dt = *((TIMESTAMP_STRUCT*)
1706 const_cast<char *
>(tmpStorage.at(
i).constData()));
1708 QTime(dt.hour, dt.minute, dt.second, dt.fraction / 1000000)));
1710 case QMetaType::Bool:
1711 case QMetaType::Short:
1712 case QMetaType::UShort:
1713 case QMetaType::Int:
1714 case QMetaType::UInt:
1715 case QMetaType::Float:
1716 case QMetaType::Double:
1717 case QMetaType::QByteArray:
1718 case QMetaType::LongLong:
1719 case QMetaType::ULongLong:
1722 case QMetaType::QString:
1726 const auto strSize = bytes.
size() /
sizeof(SQLTCHAR);
1727 QVarLengthArray<SQLTCHAR>
string(strSize);
1728 memcpy(
string.
data(), bytes.
data(), strSize *
sizeof(SQLTCHAR));
1739 if (indicators[
i] == SQL_NULL_DATA)
1758 switch (
driver()->dbmsType()) {
1761 sql =
"SELECT @@IDENTITY;"_L1;
1764 sql =
"SELECT LAST_INSERT_ID();"_L1;
1767 sql =
"SELECT lastval();"_L1;
1775 if (qry.exec(sql) && qry.next())
1776 return qry.value(0);
1778 qSqlWarning(
"QODBCResult::lastInsertId: Unable to get lastInsertId"_L1,
d);
1780 qSqlWarning(
"QODBCResult::lastInsertId: not implemented for this DBMS"_L1,
d);
1789 return QVariant(QMetaType::fromType<SQLHANDLE>(), &
d->hStmt);
1798 d->fieldCache.clear();
1799 d->fieldCacheIdx = 0;
1802 SQLRETURN
r = SQLMoreResults(
d->hStmt);
1803 if (
r != SQL_SUCCESS) {
1804 if (
r == SQL_SUCCESS_WITH_INFO) {
1807 if (
r != SQL_NO_DATA)
1814 SQLSMALLINT
count = 0;
1815 SQLNumResultCols(
d->hStmt, &
count);
1818 for (SQLSMALLINT
i = 0;
i <
count; ++
i) {
1821 d->fieldCache.resize(
count);
1839 SQLCloseCursor(
d->hStmt);
1876 int r = SQLGetInfo(
d->hDbc,
1877 (SQLUSMALLINT)SQL_TXN_CAPABLE,
1881 if (
r != SQL_SUCCESS || txn == SQL_TC_NONE)
1906 return d->hasMultiResultSets;
1926 if (
arg.startsWith(u
'"'))
1928 else if (
arg.startsWith(u
'\''))
1930 else if (
arg.contains(u
';'))
1934 return quoteChar +
arg + quoteChar;
1940 r = SQLAllocHandle(SQL_HANDLE_ENV,
1943 if (!SQL_SUCCEEDED(
r)) {
1944 qSqlWarning(
"QODBCDriver::open: Unable to allocate environment"_L1,
d);
1948 r = SQLSetEnvAttr(
d->hEnv,
1949 SQL_ATTR_ODBC_VERSION,
1952 r = SQLAllocHandle(SQL_HANDLE_DBC,
1955 if (!SQL_SUCCEEDED(
r)) {
1956 qSqlWarning(
"QODBCDriver::open: Unable to allocate connection"_L1,
d);
1962 if (!
d->setConnectionOptions(connOpts)) {
1971 connQStr =
"FILEDSN="_L1 + ensureEscaped(
db);
1976 connQStr =
"DSN="_L1 + ensureEscaped(
db);
1979 connQStr +=
";UID="_L1 + ensureEscaped(user);
1981 connQStr +=
";PWD="_L1 + ensureEscaped(password);
1984 QVarLengthArray<SQLTCHAR, 1024> connOut(1024);
1987 r = SQLDriverConnect(
d->hDbc,
1990 connOut.data(), SQLSMALLINT(connOut.size()),
1995 if (!SQL_SUCCEEDED(
r)) {
2002 if (!
d->checkDriver()) {
2011 d->checkSchemaUsage();
2013 d->checkHasSQLFetchScroll();
2014 d->checkHasMultiResults();
2015 d->checkDateTimePrecision();
2016 d->checkDefaultCase();
2021 i.exec(
"SET QUOTED_IDENTIFIER ON"_L1);
2033void QODBCDriver::cleanup()
2041 r = SQLDisconnect(
d->hDbc);
2042 if (
r != SQL_SUCCESS)
2043 qSqlWarning(
"QODBCDriver::disconnect: Unable to disconnect datasource"_L1,
d);
2045 d->disconnectCount++;
2048 r = SQLFreeHandle(SQL_HANDLE_DBC,
d->hDbc);
2049 if (
r != SQL_SUCCESS)
2050 qSqlWarning(
"QODBCDriver::cleanup: Unable to free connection handle"_L1,
d);
2055 r = SQLFreeHandle(SQL_HANDLE_ENV,
d->hEnv);
2056 if (
r != SQL_SUCCESS)
2057 qSqlWarning(
"QODBCDriver::cleanup: Unable to free environment handle"_L1,
d);
2070 r = SQLGetInfo(
hDbc,
2075 if (SQL_SUCCEEDED(
r) && (fFunc & SQL_CVT_WCHAR)) {
2080 r = SQLGetInfo(
hDbc,
2081 SQL_CONVERT_VARCHAR,
2085 if (SQL_SUCCEEDED(
r) && (fFunc & SQL_CVT_WVARCHAR)) {
2090 r = SQLGetInfo(
hDbc,
2091 SQL_CONVERT_LONGVARCHAR,
2095 if (SQL_SUCCEEDED(
r) && (fFunc & SQL_CVT_WLONGVARCHAR)) {
2103 const std::array<QStringView, 3> statements = {
2106 u
"select 'test' from dual",
2108 for (
const auto &statement : statements) {
2111 if (
r == SQL_SUCCESS)
2114 if (
r == SQL_SUCCESS) {
2116 if (
r == SQL_SUCCESS) {
2117 QVarLengthArray<SQLWCHAR, 10>
buffer(10);
2118 r = SQLGetData(hStmt.
handle(), 1, SQL_C_WCHAR,
buffer.data(),
2119 buffer.size() *
sizeof(SQLWCHAR), NULL);
2129#ifdef ODBC_CHECK_DRIVER
2130 static constexpr SQLUSMALLINT reqFunc[] = {
2131 SQL_API_SQLDESCRIBECOL, SQL_API_SQLGETDATA, SQL_API_SQLCOLUMNS,
2132 SQL_API_SQLGETSTMTATTR, SQL_API_SQLGETDIAGREC, SQL_API_SQLEXECDIRECT,
2133 SQL_API_SQLGETINFO, SQL_API_SQLTABLES
2137 static constexpr SQLUSMALLINT optFunc[] = {
2138 SQL_API_SQLNUMRESULTCOLS, SQL_API_SQLROWCOUNT
2145 for (
const SQLUSMALLINT
func : reqFunc) {
2149 if (
r != SQL_SUCCESS) {
2150 qSqlWarning(
"QODBCDriver::checkDriver: Cannot get list of supported functions"_L1,
this);
2153 if (sup == SQL_FALSE) {
2154 qSqlWarning((
"QODBCDriver::checkDriver: Driver doesn't support all needed "
2155 "functionality (func id %1).\nPlease look at the Qt SQL Module "
2156 "Driver documentation for more information."_L1)
2163 for (
const SQLUSMALLINT
func : optFunc) {
2167 if (
r != SQL_SUCCESS) {
2168 qSqlWarning(
"QODBCDriver::checkDriver: Cannot get list of supported functions"_L1,
this);
2171 if (sup == SQL_FALSE) {
2172 qSqlWarning((
"QODBCDriver::checkDriver: Driver doesn't support some "
2173 "non-critical functions (func id %1)."_L1)
2188 r = SQLGetInfo(
hDbc,
2193 if (SQL_SUCCEEDED(
r))
2200 QVarLengthArray<SQLTCHAR, 200> serverString(200);
2203 r = SQLGetInfo(
hDbc,
2205 serverString.data(),
2206 SQLSMALLINT(serverString.size() *
sizeof(SQLTCHAR)),
2208 if (SQL_SUCCEEDED(
r)) {
2221 r = SQLGetInfo(
hDbc,
2223 serverString.data(),
2224 SQLSMALLINT(serverString.size() *
sizeof(SQLTCHAR)),
2226 if (SQL_SUCCEEDED(
r)) {
2236 SQLRETURN
r = SQLGetFunctions(
hDbc, SQL_API_SQLFETCHSCROLL, &sup);
2237 if ((!SQL_SUCCEEDED(
r)) || sup != SQL_TRUE) {
2239 qSqlWarning(
"QODBCDriver::checkHasSQLFetchScroll: Driver doesn't support "
2240 "scrollable result sets, use forward only mode for queries"_L1,
this);
2246 QVarLengthArray<SQLTCHAR, 2> driverResponse(2);
2248 SQLRETURN
r = SQLGetInfo(
hDbc,
2249 SQL_MULT_RESULT_SETS,
2250 driverResponse.data(),
2251 SQLSMALLINT(driverResponse.size() *
sizeof(SQLTCHAR)),
2253 if (SQL_SUCCEEDED(
r))
2259 SQLINTEGER columnSize;
2265 SQLRETURN
r = SQLGetTypeInfo(hStmt.
handle(), SQL_TIMESTAMP);
2266 if (SQL_SUCCEEDED(
r)) {
2268 if (SQL_SUCCEEDED(
r)) {
2269 if (SQLGetData(hStmt.
handle(), 3, SQL_INTEGER, &columnSize,
sizeof(columnSize), 0) == SQL_SUCCESS)
2284 qSqlWarning(
"QODBCDriver::beginTransaction: Database not open"_L1,
d);
2287 SQLUINTEGER ac(SQL_AUTOCOMMIT_OFF);
2288 SQLRETURN
r = SQLSetConnectAttr(
d->hDbc,
2289 SQL_ATTR_AUTOCOMMIT,
2290 (SQLPOINTER)
size_t(ac),
2292 if (
r != SQL_SUCCESS) {
2304 qSqlWarning(
"QODBCDriver::commitTransaction: Database not open"_L1,
d);
2307 SQLRETURN
r = SQLEndTran(SQL_HANDLE_DBC,
2310 if (
r != SQL_SUCCESS) {
2322 qSqlWarning(
"QODBCDriver::rollbackTransaction: Database not open"_L1,
d);
2325 SQLRETURN
r = SQLEndTran(SQL_HANDLE_DBC,
2328 if (
r != SQL_SUCCESS) {
2336bool QODBCDriver::endTrans()
2339 SQLUINTEGER ac(SQL_AUTOCOMMIT_ON);
2340 SQLRETURN
r = SQLSetConnectAttr(
d->hDbc,
2341 SQL_ATTR_AUTOCOMMIT,
2342 (SQLPOINTER)
size_t(ac),
2344 if (
r != SQL_SUCCESS) {
2360 qSqlWarning(
"QODBCDriver::tables: Unable to allocate handle"_L1,
d);
2363 SQLRETURN
r = SQLSetStmtAttr(hStmt.
handle(),
2364 SQL_ATTR_CURSOR_TYPE,
2365 (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
2369 tableType +=
"TABLE"_L1;
2371 tableType +=
"VIEW"_L1;
2373 tableType +=
"SYSTEM TABLE"_L1;
2374 if (tableType.isEmpty())
2378 auto joinedTableTypeString =
toSQLTCHAR(tableType.join(u
','));
2384 joinedTableTypeString.data(), joinedTableTypeString.size());
2387 if (
r != SQL_SUCCESS)
2388 qSqlWarning(
"QODBCDriver::tables Unable to execute table list"_L1,
2391 r =
d->sqlFetchNext(hStmt);
2392 if (!SQL_SUCCEEDED(
r) &&
r != SQL_NO_DATA) {
2393 qSqlWarning(
"QODBCDriver::tables failed to retrieve table/view list"_L1,
2398 while (
r == SQL_SUCCESS) {
2400 r =
d->sqlFetchNext(hStmt);
2412 bool usingSpecialColumns =
false;
2417 qSqlWarning(
"QODBCDriver::primaryIndex: Unable to allocate handle"_L1,
d);
2421 d->splitTableQualifier(tablename, catalog, schema,
table);
2423 SQLRETURN
r = SQLSetStmtAttr(hStmt.
handle(),
2424 SQL_ATTR_CURSOR_TYPE,
2425 (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
2431 r = SQLPrimaryKeys(hStmt.
handle(),
2432 catalog.
isEmpty() ?
nullptr :
c.data(),
c.size(),
2433 schema.isEmpty() ?
nullptr :
s.data(),
s.size(),
2434 t.data(),
t.size());
2440 if (
r != SQL_SUCCESS) {
2444 r = SQLSpecialColumns(hStmt.
handle(),
2446 catalog.
isEmpty() ?
nullptr :
c.data(),
c.size(),
2447 schema.isEmpty() ?
nullptr :
s.data(),
s.size(),
2452 if (
r != SQL_SUCCESS) {
2453 qSqlWarning(
"QODBCDriver::primaryIndex: Unable to execute primary key list"_L1,
2456 usingSpecialColumns =
true;
2460 r =
d->sqlFetchNext(hStmt);
2465 while (
r == SQL_SUCCESS) {
2466 if (usingSpecialColumns) {
2474 index.setName(idxName);
2476 r =
d->sqlFetchNext(hStmt);
2490 qSqlWarning(
"QODBCDriver::record: Unable to allocate handle"_L1,
d);
2495 d->splitTableQualifier(tablename, catalog, schema,
table);
2497 SQLRETURN
r = SQLSetStmtAttr(hStmt.
handle(),
2498 SQL_ATTR_CURSOR_TYPE,
2499 (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
2505 r = SQLColumns(hStmt.
handle(),
2506 catalog.
isEmpty() ?
nullptr :
c.data(),
c.size(),
2507 schema.isEmpty() ?
nullptr :
s.data(),
s.size(),
2512 if (
r != SQL_SUCCESS)
2513 qSqlWarning(
"QODBCDriver::record: Unable to execute column list"_L1, hStmt.
handle());
2515 r =
d->sqlFetchNext(hStmt);
2517 while (
r == SQL_SUCCESS) {
2519 r =
d->sqlFetchNext(hStmt);
2525 bool trimStrings)
const
2530 }
else if (field.
metaType().
id() == QMetaType::QDateTime) {
2547 }
else if (field.
metaType().
id() == QMetaType::QByteArray) {
2551 for (
const char c :
ba) {
2565 return QVariant(QMetaType::fromType<SQLHANDLE>(), &
d->hDbc);
2575 res.replace(
quote, quoteStr + quoteStr);
2576 res.replace(u
'.', quoteStr + u
'.' + quoteStr);
2586 return identifier.
size() > 2
2593#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().
char at(qsizetype i) const
Returns the byte at index position i in the byte array.
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 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)
void checkHasMultiResults()
bool setConnectionOptions(const QString &connOpts)
void checkHasSQLFetchScroll()
void splitTableQualifier(const QString &qualifier, QString &catalog, QString &schema, QString &table) const
SQLRETURN sqlFetchNext(const SqlStmtHandle &hStmt) 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.
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.
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.
The QSqlRecord class encapsulates a database record.
QSqlField field(int i) const
Returns the field at position index.
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.
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.
static QString fromUtf16(const char16_t *, qsizetype size=-1)
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
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 noexcept
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...
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; 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...
QByteArray toUtf8() const &
QString toUpper() const &
qsizetype length() const noexcept
Returns the number of characters in this string.
\inmodule QtCore \reentrant
int hour() const
Returns the hour part (0 to 23) of the time.
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,...
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...
SqlStmtHandle(SQLHANDLE hDbc)
Combined button and popup list for selecting options.
constexpr char toHexLower(char32_t value) noexcept
QList< QString > QStringList
Constructs a string list that contains the given string, str.
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#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
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLenum GLsizei const GLchar * buf
GLuint64 GLenum handleType
GLuint GLsizei const GLchar * message
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 QSqlField qMakeFieldInfo(const SQLHANDLE hStmt, const QODBCDriverPrivate *p)
static bool isAutoValue(const SQLHANDLE hStmt, int column)
static SQLRETURN qt_string_SQLSetConnectAttr(SQLHDBC handle, SQLINTEGER attr, QStringView val)
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 QVarLengthArray< SQLTCHAR > toSQLTCHAR(QStringView input)
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 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)
unsigned long long quint64
static QString quote(const QString &str)
ReturnedValue read(const char *data)
\inmodule QtCore \reentrant