diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp index 3525c2577ac..923ed0d09a9 100644 --- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp +++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp @@ -1475,12 +1475,39 @@ QSqlIndex QMYSQLDriver::primaryIndex(const QString &tablename) const QSqlRecord QMYSQLDriver::record(const QString &tablename) const { + Q_D(const QMYSQLDriver); if (!isOpen()) return {}; QSqlQuery i(createResult()); QString stmt("SELECT * FROM %1 LIMIT 0"_L1); i.exec(stmt.arg(escapeIdentifier(tablename, QSqlDriver::TableName))); - return i.record(); + auto r = i.record(); + if (r.isEmpty()) + return r; + // no binding of WHERE possible with MySQL + // escaping on WHERE clause does not work, so use mysql_real_escape_string() + stmt = "SELECT column_name, column_default FROM information_schema.columns WHERE table_name = '%1'"_L1; + const auto baTableName = tablename.toUtf8(); + QVarLengthArray tableNameQuoted(baTableName.size() * 2 + 1); +#if defined(MARIADB_VERSION_ID) + const auto len = mysql_real_escape_string(d->mysql, tableNameQuoted.data(), + baTableName.data(), baTableName.size()); +#else + const auto len = mysql_real_escape_string_quote(d->mysql, tableNameQuoted.data(), + baTableName.data(), baTableName.size(), '\''); +#endif + if (i.exec(stmt.arg(QString::fromUtf8(tableNameQuoted.data(), len)))) { + while (i.next()) { + const auto colName = i.value(0).toString(); + const auto recordIdx = r.indexOf(colName); + if (recordIdx >= 0) { + auto field = r.field(recordIdx); + field.setDefaultValue(i.value(1)); + r.replace(recordIdx, field); + } + } + } + return r; } QVariant QMYSQLDriver::handle() const diff --git a/src/sql/kernel/qsqlfield.cpp b/src/sql/kernel/qsqlfield.cpp index 5964b474149..2995d05779d 100644 --- a/src/sql/kernel/qsqlfield.cpp +++ b/src/sql/kernel/qsqlfield.cpp @@ -208,6 +208,8 @@ void QSqlField::setPrecision(int precision) \since 6.8 This property holds the default value for this field. + Only some database drivers supports this property. Currently + those are SQLite, PostgreSQL, Oracle and MySQL/MariaDB. */ /*! diff --git a/tests/auto/sql/kernel/qsqldriver/tst_qsqldriver.cpp b/tests/auto/sql/kernel/qsqldriver/tst_qsqldriver.cpp index 2947fb70401..fb8d804843e 100644 --- a/tests/auto/sql/kernel/qsqldriver/tst_qsqldriver.cpp +++ b/tests/auto/sql/kernel/qsqldriver/tst_qsqldriver.cpp @@ -35,6 +35,7 @@ static bool driverSupportsDefaultValues(QSqlDriver::DbmsType dbType) case QSqlDriver::SQLite: case QSqlDriver::PostgreSQL: case QSqlDriver::Oracle: + case QSqlDriver::MySqlServer: return true; default: break; @@ -132,8 +133,14 @@ void tst_QSqlDriver::record() for (int i = 0; i < fields.size(); ++i) QCOMPARE(rec.fieldName(i), fields[i]); - if (driverSupportsDefaultValues(dbType)) - QCOMPARE(rec.field(QStringLiteral("name")).defaultValue().toString(), QStringLiteral("defaultVal")); + if (driverSupportsDefaultValues(dbType)) { + auto defVal = rec.field(QStringLiteral("name")).defaultValue().toString(); + if (dbType == QSqlDriver::MySqlServer && defVal.startsWith('\'') && defVal.endsWith('\'')) { + qDebug() << "MariaDB 10.6 default string value is escaped:" << defVal; + defVal = defVal.mid(1, defVal.size() - 2); + } + QCOMPARE(defVal, QStringLiteral("defaultVal")); + } if (dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2) tablename = tablename.toUpper();