616 QList<QByteArray> tmpStorage;
617 QVarLengthArray<SQLLEN, 32> indicators(boundValues().count());
619 memset(indicators.data(), 0, indicators.size() *
sizeof(SQLLEN));
621 setAt(QSql::BeforeFirstRow);
625 d->emptyValueCache();
627 if (!qMakeStatement(d, isForwardOnly(),
false))
631 QList<QVariant> &values = boundValues();
633 for (i = 0; i < values.count(); ++i) {
635 SQLLEN *ind = &indicators[i];
636 if (QSqlResultPrivate::isVariantNull(values.at(i)))
637 *ind = SQL_NULL_DATA;
638 if (bindValueType(i) & QSql::Out)
641 switch (values.at(i).metaType().id()) {
642 case QMetaType::QDate: {
644 ba.resize(
sizeof(DATE_STRUCT));
645 DATE_STRUCT *dt = (DATE_STRUCT *)ba.constData();
646 QDate qdt = values.at(i).toDate();
647 dt->year = qdt.year();
648 dt->month = qdt.month();
650 r = SQLBindParameter(d->hStmt,
652 qParamType[bindValueType(i) & 3],
659 *ind == SQL_NULL_DATA ? ind : NULL);
660 tmpStorage.append(ba);
662 case QMetaType::QTime: {
664 ba.resize(
sizeof(TIME_STRUCT));
665 TIME_STRUCT *dt = (TIME_STRUCT *)ba.constData();
666 QTime qdt = values.at(i).toTime();
667 dt->hour = qdt.hour();
668 dt->minute = qdt.minute();
669 dt->second = qdt.second();
670 r = SQLBindParameter(d->hStmt,
672 qParamType[bindValueType(i) & 3],
679 *ind == SQL_NULL_DATA ? ind : NULL);
680 tmpStorage.append(ba);
682 case QMetaType::QDateTime: {
684 ba.resize(
sizeof(TIMESTAMP_STRUCT));
685 TIMESTAMP_STRUCT * dt = (TIMESTAMP_STRUCT *)ba.constData();
686 QDateTime qdt = values.at(i).toDateTime();
687 dt->year = qdt.date().year();
688 dt->month = qdt.date().month();
689 dt->day = qdt.date().day();
690 dt->hour = qdt.time().hour();
691 dt->minute = qdt.time().minute();
692 dt->second = qdt.time().second();
693 dt->fraction = qdt.time().msec() * 1000000;
694 r = SQLBindParameter(d->hStmt,
696 qParamType[bindValueType(i) & 3],
703 *ind == SQL_NULL_DATA ? ind : NULL);
704 tmpStorage.append(ba);
707 r = SQLBindParameter(d->hStmt,
709 qParamType[bindValueType(i) & 3],
714 (
void *)values.at(i).constData(),
716 *ind == SQL_NULL_DATA ? ind : NULL);
718 case QMetaType::Double:
719 r = SQLBindParameter(d->hStmt,
721 qParamType[bindValueType(i) & 3],
726 (
void *)values.at(i).constData(),
728 *ind == SQL_NULL_DATA ? ind : NULL);
730 case QMetaType::QByteArray: {
731 int len = values.at(i).toByteArray().size();
732 if (*ind != SQL_NULL_DATA)
734 r = SQLBindParameter(d->hStmt,
736 qParamType[bindValueType(i) & 3],
741 (
void *)values.at(i).toByteArray().constData(),
745 case QMetaType::QString:
747 const QString str(values.at(i).toString());
748 if (*ind != SQL_NULL_DATA)
749 *ind = str.length() *
sizeof(QChar);
750 if (bindValueType(i) & QSql::Out) {
751 QByteArray ba((
char *)str.data(), str.capacity() *
sizeof(QChar));
752 r = SQLBindParameter(d->hStmt,
754 qParamType[bindValueType(i) & 3],
759 (
void *)ba.constData(),
762 tmpStorage.append(ba);
764 void *data = (
void*)str.utf16();
765 int len = str.length();
766 r = SQLBindParameter(d->hStmt,
768 qParamType[bindValueType(i) & 3],
780 QByteArray ba = values.at(i).toString().toLatin1();
781 int len = ba.length() + 1;
782 if (*ind != SQL_NULL_DATA)
784 r = SQLBindParameter(d->hStmt,
786 qParamType[bindValueType(i) & 3],
791 (
void *) ba.constData(),
794 tmpStorage.append(ba);
797 if (r != SQL_SUCCESS) {
798 qWarning(
"QDB2Result::exec: unable to bind variable: %s",
799 qDB2Warn(d).toLocal8Bit().constData());
800 setLastError(qMakeError(QCoreApplication::translate(
"QDB2Result",
801 "Unable to bind variable"), QSqlError::StatementError, d));
806 r = SQLExecute(d->hStmt);
807 if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
808 qWarning(
"QDB2Result::exec: Unable to execute statement: %s",
809 qDB2Warn(d).toLocal8Bit().constData());
810 setLastError(qMakeError(QCoreApplication::translate(
"QDB2Result",
811 "Unable to execute statement"), QSqlError::StatementError, d));
814 SQLSMALLINT count = 0;
815 r = SQLNumResultCols(d->hStmt, &count);
818 for (
int i = 0; i < count; ++i) {
819 d->recInf.append(qMakeFieldInfo(d, i));
825 d->valueCache.resize(count);
826 d->valueCache.fill(NULL);
832 for (i = 0; i < values.count(); ++i) {
833 switch (values[i].metaType().id()) {
834 case QMetaType::QDate: {
835 DATE_STRUCT ds = *((DATE_STRUCT *)tmpStorage.takeFirst().constData());
836 values[i] = QVariant(QDate(ds.year, ds.month, ds.day));
838 case QMetaType::QTime: {
839 TIME_STRUCT dt = *((TIME_STRUCT *)tmpStorage.takeFirst().constData());
840 values[i] = QVariant(QTime(dt.hour, dt.minute, dt.second));
842 case QMetaType::QDateTime: {
843 TIMESTAMP_STRUCT dt = *((TIMESTAMP_STRUCT *)tmpStorage.takeFirst().constData());
844 values[i] = QVariant(QDateTime(QDate(dt.year, dt.month, dt.day),
845 QTime(dt.hour, dt.minute, dt.second, dt.fraction / 1000000)));
848 case QMetaType::Double:
849 case QMetaType::QByteArray:
851 case QMetaType::QString:
852 if (bindValueType(i) & QSql::Out)
853 values[i] = QString((
const QChar *)tmpStorage.takeFirst().constData());
856 values[i] = QString::fromLatin1(tmpStorage.takeFirst().constData());
859 if (indicators[i] == SQL_NULL_DATA)
860 values[i] = QVariant(values[i].metaType());
975 if (field >= d->recInf.count()) {
976 qWarning(
"QDB2Result::data: column %d out of range", field);
980 SQLLEN lengthIndicator = 0;
982 const QSqlField info = d->recInf.field(field);
984 if (!info.isValid() || field >= d->valueCache.size())
987 if (d->valueCache[field])
988 return *d->valueCache[field];
991 QVariant *v =
nullptr;
992 switch (info.metaType().id()) {
993 case QMetaType::LongLong:
994 v =
new QVariant((qint64) qGetBigIntData(d->hStmt, field, isNull));
997 v =
new QVariant(qGetIntData(d->hStmt, field, isNull));
999 case QMetaType::QDate: {
1001 r = SQLGetData(d->hStmt,
1007 if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA)) {
1008 v =
new QVariant(QDate(dbuf.year, dbuf.month, dbuf.day));
1010 v =
new QVariant(QDate());
1014 case QMetaType::QTime: {
1016 r = SQLGetData(d->hStmt,
1022 if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA)) {
1023 v =
new QVariant(QTime(tbuf.hour, tbuf.minute, tbuf.second));
1025 v =
new QVariant(QTime());
1029 case QMetaType::QDateTime: {
1030 TIMESTAMP_STRUCT dtbuf;
1031 r = SQLGetData(d->hStmt,
1034 (SQLPOINTER) &dtbuf,
1037 if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA)) {
1038 v =
new QVariant(QDateTime(QDate(dtbuf.year, dtbuf.month, dtbuf.day),
1039 QTime(dtbuf.hour, dtbuf.minute, dtbuf.second, dtbuf.fraction / 1000000)));
1041 v =
new QVariant(QDateTime());
1045 case QMetaType::QByteArray:
1046 v =
new QVariant(qGetBinaryData(d->hStmt, field, lengthIndicator, isNull));
1048 case QMetaType::Double:
1050 switch(numericalPrecisionPolicy()) {
1051 case QSql::LowPrecisionInt32:
1052 v =
new QVariant(qGetIntData(d->hStmt, field, isNull));
1054 case QSql::LowPrecisionInt64:
1055 v =
new QVariant((qint64) qGetBigIntData(d->hStmt, field, isNull));
1057 case QSql::LowPrecisionDouble:
1058 v =
new QVariant(qGetDoubleData(d->hStmt, field, isNull));
1060 case QSql::HighPrecision:
1063 v =
new QVariant(qGetStringData(d->hStmt, field, info.length() + 1, isNull));
1068 case QMetaType::QString:
1070 v =
new QVariant(qGetStringData(d->hStmt, field, info.length(), isNull));
1074 *v = QVariant(info.metaType());
1075 d->valueCache[field] = v;
1182bool QDB2Driver::open(
const QString& db,
const QString& user,
const QString& password,
const QString& host,
int port,
1183 const QString& connOpts)
1189 r = SQLAllocHandle(SQL_HANDLE_ENV,
1192 if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
1193 qSqlWarning(
"QDB2Driver::open: Unable to allocate environment"_L1, d);
1198 r = SQLAllocHandle(SQL_HANDLE_DBC,
1201 if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
1202 qSqlWarning(
"QDB2Driver::open: Unable to allocate connection"_L1, d);
1209 const QStringList opts(connOpts.split(u';', Qt::SkipEmptyParts));
1210 for (
int i = 0; i < opts.count(); ++i) {
1211 const QString tmp(opts.at(i));
1213 if ((idx = tmp.indexOf(u'=')) == -1) {
1214 qWarning(
"QDB2Driver::open: Illegal connect option value '%s'",
1215 tmp.toLocal8Bit().constData());
1219 const QString opt(tmp.left(idx));
1220 const QString val(tmp.mid(idx + 1).simplified());
1224 if (opt ==
"SQL_ATTR_ACCESS_MODE"_L1) {
1225 if (val ==
"SQL_MODE_READ_ONLY"_L1) {
1226 v = SQL_MODE_READ_ONLY;
1227 }
else if (val ==
"SQL_MODE_READ_WRITE"_L1) {
1228 v = SQL_MODE_READ_WRITE;
1230 qWarning(
"QDB2Driver::open: Unknown option value '%s'",
1231 tmp.toLocal8Bit().constData());
1234 r = SQLSetConnectAttr(d->hDbc, SQL_ATTR_ACCESS_MODE,
reinterpret_cast<SQLPOINTER>(v), 0);
1235 }
else if (opt ==
"SQL_ATTR_LOGIN_TIMEOUT"_L1) {
1237 r = SQLSetConnectAttr(d->hDbc, SQL_ATTR_LOGIN_TIMEOUT,
reinterpret_cast<SQLPOINTER>(v), 0);
1238 }
else if (opt.compare(
"PROTOCOL"_L1, Qt::CaseInsensitive) == 0) {
1242 qWarning(
"QDB2Driver::open: Unknown connection attribute '%s'",
1243 tmp.toLocal8Bit().constData());
1245 if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO)
1246 qSqlWarning(QString::fromLatin1(
"QDB2Driver::open: "
1247 "Unable to set connection attribute '%1'").arg(opt), d);
1250 if (protocol.isEmpty())
1251 protocol =
"PROTOCOL=TCPIP"_L1;
1257 connQStr = protocol +
";DATABASE="_L1 + db +
";HOSTNAME="_L1 + host
1258 +
";PORT="_L1 + QString::number(port) +
";UID="_L1 + user
1259 +
";PWD="_L1 + password;
1262 SQLTCHAR connOut[SQL_MAX_OPTION_STRING_LENGTH];
1265 r = SQLDriverConnect(d->hDbc,
1268 (SQLSMALLINT) connQStr.length(),
1270 SQL_MAX_OPTION_STRING_LENGTH,
1272 SQL_DRIVER_NOPROMPT);
1273 if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
1274 setLastError(qMakeError(tr(
"Unable to connect"),
1275 QSqlError::ConnectionError, d));
1282 setOpenError(
false);
1318QSqlRecord QDB2Driver::record(
const QString& tableName)
const
1320 Q_D(
const QDB2Driver);
1326 QString catalog, schema, table;
1327 d->qSplitTableQualifier(tableName, catalog, schema, table);
1328 if (schema.isEmpty())
1331 if (isIdentifierEscaped(catalog, QSqlDriver::TableName))
1332 catalog = stripDelimiters(catalog, QSqlDriver::TableName);
1334 catalog = catalog.toUpper();
1336 if (isIdentifierEscaped(schema, QSqlDriver::TableName))
1337 schema = stripDelimiters(schema, QSqlDriver::TableName);
1339 schema = schema.toUpper();
1341 if (isIdentifierEscaped(table, QSqlDriver::TableName))
1342 table = stripDelimiters(table, QSqlDriver::TableName);
1344 table = table.toUpper();
1346 SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT,
1349 if (r != SQL_SUCCESS) {
1350 qSqlWarning(
"QDB2Driver::record: Unable to allocate handle"_L1, d);
1354 r = SQLSetStmtAttr(hStmt,
1355 SQL_ATTR_CURSOR_TYPE,
1356 (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY,
1362 r = SQLColumns(hStmt,
1372 if (r != SQL_SUCCESS)
1373 qSqlWarning(
"QDB2Driver::record: Unable to execute column list"_L1, d);
1374 r = SQLFetchScroll(hStmt,
1377 while (r == SQL_SUCCESS) {
1378 QSqlField fld = qMakeFieldInfo(hStmt);
1379 fld.setTableName(tableName);
1381 r = SQLFetchScroll(hStmt,
1386 r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
1387 if (r != SQL_SUCCESS)
1388 qSqlWarning(
"QDB2Driver: Unable to free statement handle "_L1
1389 + QString::number(r), d);
1394QStringList QDB2Driver::tables(QSql::TableType type)
const
1396 Q_D(
const QDB2Driver);
1403 SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT,
1406 if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
1407 qSqlWarning(
"QDB2Driver::tables: Unable to allocate handle"_L1, d);
1410 r = SQLSetStmtAttr(hStmt,
1411 SQL_ATTR_CURSOR_TYPE,
1412 (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
1416 if (type & QSql::Tables)
1417 tableType +=
"TABLE,"_L1;
1418 if (type & QSql::Views)
1419 tableType +=
"VIEW,"_L1;
1420 if (type & QSql::SystemTables)
1421 tableType +=
"SYSTEM TABLE,"_L1;
1422 if (tableType.isEmpty())
1426 r = SQLTables(hStmt,
1433 qToTChar(tableType),
1434 tableType.length());
1436 if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO)
1437 qSqlWarning(
"QDB2Driver::tables: Unable to execute table list"_L1, d);
1438 r = SQLFetchScroll(hStmt,
1441 while (r == SQL_SUCCESS) {
1443 QString fieldVal = qGetStringData(hStmt, 2, -1, isNull);
1444 QString userVal = qGetStringData(hStmt, 1, -1, isNull);
1445 QString user = d->user;
1446 if ( isIdentifierEscaped(user, QSqlDriver::TableName))
1447 user = stripDelimiters(user, QSqlDriver::TableName);
1449 user = user.toUpper();
1451 if (userVal != user)
1452 fieldVal = userVal + u'.' + fieldVal;
1453 tl.append(fieldVal);
1454 r = SQLFetchScroll(hStmt,
1459 r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
1460 if (r != SQL_SUCCESS)
1461 qSqlWarning(
"QDB2Driver::tables: Unable to free statement handle "_L1
1462 + QString::number(r), d);
1466QSqlIndex QDB2Driver::primaryIndex(
const QString& tablename)
const
1468 Q_D(
const QDB2Driver);
1469 QSqlIndex index(tablename);
1472 QSqlRecord rec = record(tablename);
1475 SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT,
1478 if (r != SQL_SUCCESS) {
1479 qSqlWarning(
"QDB2Driver::primaryIndex: Unable to list primary key"_L1, d);
1482 QString catalog, schema, table;
1483 d->qSplitTableQualifier(tablename, catalog, schema, table);
1485 if (isIdentifierEscaped(catalog, QSqlDriver::TableName))
1486 catalog = stripDelimiters(catalog, QSqlDriver::TableName);
1488 catalog = catalog.toUpper();
1490 if (isIdentifierEscaped(schema, QSqlDriver::TableName))
1491 schema = stripDelimiters(schema, QSqlDriver::TableName);
1493 schema = schema.toUpper();
1495 if (isIdentifierEscaped(table, QSqlDriver::TableName))
1496 table = stripDelimiters(table, QSqlDriver::TableName);
1498 table = table.toUpper();
1500 r = SQLSetStmtAttr(hStmt,
1501 SQL_ATTR_CURSOR_TYPE,
1502 (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
1505 r = SQLPrimaryKeys(hStmt,
1512 r = SQLFetchScroll(hStmt,
1517 QString cName, idxName;
1519 while (r == SQL_SUCCESS) {
1520 cName = qGetStringData(hStmt, 3, -1, isNull);
1521 idxName = qGetStringData(hStmt, 5, -1, isNull);
1522 index.append(rec.field(cName));
1523 index.setName(idxName);
1524 r = SQLFetchScroll(hStmt,
1528 r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
1529 if (r!= SQL_SUCCESS)
1530 qSqlWarning(
"QDB2Driver: Unable to free statement handle "_L1
1531 + QString::number(r), d);
1621QString QDB2Driver::formatValue(
const QSqlField &field,
bool trimStrings)
const
1626 switch (field.metaType().id()) {
1627 case QMetaType::QDateTime: {
1629 if (field.value().toDateTime().isValid()) {
1630 QDate dt = field.value().toDateTime().date();
1631 QTime tm = field.value().toDateTime().time();
1633 return u'\'' + QString::number(dt.year()) + u'-'
1634 + QString::number(dt.month()) + u'-'
1635 + QString::number(dt.day()) + u'-'
1636 + QString::number(tm.hour()) + u'.'
1637 + QString::number(tm.minute()).rightJustified(2, u'0',
true)
1639 + QString::number(tm.second()).rightJustified(2, u'0',
true)
1641 + QString::number(tm.msec() * 1000).rightJustified(6, u'0',
true)
1647 case QMetaType::QByteArray: {
1648 const QByteArray ba = field.value().toByteArray();
1650 r.reserve(ba.size() * 2 + 9);
1652 for (
const char c : ba) {
1653 const uchar s = uchar(c);
1654 r += QLatin1Char(QtMiscUtils::toHexLower(s >> 4));
1655 r += QLatin1Char(QtMiscUtils::toHexLower(s & 0x0f));
1661 return QSqlDriver::formatValue(field, trimStrings);