19#include <QtSql/private/qsqldriver_p.h>
20#include <QtSql/private/qsqlresult_p.h>
25# define Q_NO_MYSQL_EMBEDDED
33#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID < 50709
34#define MYSQL_TYPE_JSON 245
39using my_bool =
decltype(mysql_stmt_bind_result(
nullptr,
nullptr));
70#if !QT_CONFIG(datestring)
82#if !QT_CONFIG(datestring)
94#if !QT_CONFIG(datestring)
100 if (
val.size() == 14)
102 val.insert(4, u
'-').insert(7, u
'-').insert(10, u
'T').insert(13, u
':').insert(16, u
':');
110 std::unique_ptr<MYSQL_STMT,
decltype(&mysql_stmt_close)> stmt(mysql_stmt_init(mysql), &mysql_stmt_close);
114 static const char dummyQuery[] =
"SELECT ? + ?";
115 if (mysql_stmt_prepare(stmt.get(), dummyQuery,
sizeof(dummyQuery) - 1))
118 return mysql_stmt_param_count(stmt.get()) == 2;
135 bool fetch(
int i) override;
140 bool isNull(
int field) override;
151 bool exec() override;
171 char *outField =
nullptr;
172 const MYSQL_FIELD *myField =
nullptr;
180 MYSQL_STMT *stmt =
nullptr;
181 MYSQL_RES *meta =
nullptr;
183 MYSQL_BIND *inBinds =
nullptr;
184 MYSQL_BIND *outBinds =
nullptr;
186 int rowsAffected = 0;
187 bool hasBlobs =
false;
188 bool preparedQuery =
false;
194 const char *cerr =
p->mysql ? mysql_error(
p->mysql) :
nullptr;
205 case MYSQL_TYPE_TINY:
206 type = (
flags & UNSIGNED_FLAG) ? QMetaType::UChar : QMetaType::Char;
208 case MYSQL_TYPE_SHORT:
209 type = (
flags & UNSIGNED_FLAG) ? QMetaType::UShort : QMetaType::Short;
211 case MYSQL_TYPE_LONG:
212 case MYSQL_TYPE_INT24:
213 type = (
flags & UNSIGNED_FLAG) ? QMetaType::UInt : QMetaType::Int;
215 case MYSQL_TYPE_YEAR:
216 type = QMetaType::Int;
219 case MYSQL_TYPE_LONGLONG:
220 type = (
flags & UNSIGNED_FLAG) ? QMetaType::ULongLong : QMetaType::LongLong;
222 case MYSQL_TYPE_FLOAT:
223 case MYSQL_TYPE_DOUBLE:
224 case MYSQL_TYPE_DECIMAL:
225 case MYSQL_TYPE_NEWDECIMAL:
226 type = QMetaType::Double;
228 case MYSQL_TYPE_DATE:
229 type = QMetaType::QDate;
231 case MYSQL_TYPE_TIME:
234 type = QMetaType::QString;
236 case MYSQL_TYPE_DATETIME:
237 case MYSQL_TYPE_TIMESTAMP:
238 type = QMetaType::QDateTime;
240 case MYSQL_TYPE_STRING:
241 case MYSQL_TYPE_VAR_STRING:
242 case MYSQL_TYPE_BLOB:
243 case MYSQL_TYPE_TINY_BLOB:
244 case MYSQL_TYPE_MEDIUM_BLOB:
245 case MYSQL_TYPE_LONG_BLOB:
246 case MYSQL_TYPE_GEOMETRY:
247 case MYSQL_TYPE_JSON:
248 type = (
flags & BINARY_FLAG) ? QMetaType::QByteArray : QMetaType::QString;
250 case MYSQL_TYPE_ENUM:
252 type = QMetaType::QString;
255 type = QMetaType::QString;
266 f.setRequired(IS_NOT_NULL(field->flags));
267 f.setLength(field->length);
268 f.setPrecision(field->decimals);
269 f.setSqlType(field->type);
270 f.setAutoValue(field->flags & AUTO_INCREMENT_FLAG);
277 const char *cerr = mysql_stmt_error(stmt);
285 return t == MYSQL_TYPE_TINY_BLOB
286 ||
t == MYSQL_TYPE_BLOB
287 ||
t == MYSQL_TYPE_MEDIUM_BLOB
288 ||
t == MYSQL_TYPE_LONG_BLOB
289 ||
t == MYSQL_TYPE_JSON;
296 return t == MYSQL_TYPE_DATE ||
t == MYSQL_TYPE_DATETIME ||
t == MYSQL_TYPE_TIMESTAMP;
301 return t == QMetaType::Char ||
t == QMetaType::UChar
302 ||
t == QMetaType::Short ||
t == QMetaType::UShort
303 ||
t == QMetaType::Int ||
t == QMetaType::UInt
304 ||
t == QMetaType::LongLong ||
t == QMetaType::ULongLong;
309 return type == MYSQL_TYPE_BIT;
314 for (
int i = 0;
i < fields.size(); ++
i) {
315 const MYSQL_FIELD *fieldInfo = fields.at(
i).myField;
316 if (
qIsBlob(inBinds[
i].buffer_type) && meta && fieldInfo) {
317 MYSQL_BIND *
bind = &inBinds[
i];
318 bind->buffer_length = fieldInfo->max_length;
319 delete[]
static_cast<char*
>(
bind->buffer);
320 bind->buffer =
new char[fieldInfo->max_length];
321 fields[
i].outField =
static_cast<char*
>(
bind->buffer);
329 meta = mysql_stmt_result_metadata(stmt);
333 fields.resize(mysql_num_fields(meta));
335 inBinds =
new MYSQL_BIND[fields.size()];
336 memset(inBinds, 0, fields.size() *
sizeof(MYSQL_BIND));
338 const MYSQL_FIELD *fieldInfo;
341 while((fieldInfo = mysql_fetch_field(meta))) {
342 MYSQL_BIND *
bind = &inBinds[
i];
346 bind->buffer_length =
f.bufLength = fieldInfo->length + 1;
347 bind->buffer_type = fieldInfo->type;
349 if (
qIsBlob(fieldInfo->type)) {
353 bind->buffer_length =
f.bufLength = 0;
358 bind->buffer_length =
f.bufLength = 8;
360 bind->buffer_type = MYSQL_TYPE_STRING;
363 bind->is_null = &
f.nullIndicator;
364 bind->length = &
f.bufLength;
365 bind->is_unsigned = fieldInfo->flags & UNSIGNED_FLAG ? 1 : 0;
367 char *field =
bind->buffer_length ?
new char[
bind->buffer_length + 1]{} :
nullptr;
368 bind->buffer =
f.outField = field;
388 if (
d->preparedQuery)
398 mysql_free_result(
d->result);
402 while (
driver() &&
d->drv_d_func()->mysql && mysql_next_result(
d->drv_d_func()->mysql) == 0) {
403 MYSQL_RES *
res = mysql_store_result(
d->drv_d_func()->mysql);
405 mysql_free_result(
res);
409 if (mysql_stmt_close(
d->stmt))
410 qWarning(
"QMYSQLResult::cleanup: unable to free statement handle");
415 mysql_free_result(
d->meta);
423 delete[]
d->outBinds;
456 if (
d->preparedQuery) {
457 mysql_stmt_data_seek(
d->stmt,
i);
459 int nRC = mysql_stmt_fetch(
d->stmt);
461 if (nRC == 1 || nRC == MYSQL_DATA_TRUNCATED)
467 mysql_data_seek(
d->result,
i);
468 d->row = mysql_fetch_row(
d->result);
482 if (
d->preparedQuery) {
483 int nRC = mysql_stmt_fetch(
d->stmt);
485 if (nRC == 1 || nRC == MYSQL_DATA_TRUNCATED)
491 d->row = mysql_fetch_row(
d->result);
510 my_ulonglong numRows =
d->preparedQuery ? mysql_stmt_num_rows(
d->stmt) : mysql_num_rows(
d->result);
511 if (
at() ==
int(numRows))
515 return fetch(numRows - 1);
528static inline uint64_t
532 const auto numBytes = (
f.myField->length + 7) / 8;
534 for (
unsigned long i = 0;
i < numBytes && outField; ++
i) {
535 uint64_t tmp =
static_cast<uint8_t
>(outField[
i]);
545 if (!
isSelect() || field >=
d->fields.size()) {
546 qWarning(
"QMYSQLResult::data: column %d out of range", field);
553 my_ulonglong fieldLength = 0;
556 if (
d->preparedQuery) {
564 if (
f.type.id() == QMetaType::UChar)
566 else if (
f.type.id() == QMetaType::Char)
573 if (
f.type.id() != QMetaType::QTime)
575 if (
f.type.id() != QMetaType::QDate)
576 time =
QTime(
t->hour,
t->minute,
t->second,
t->second_part / 1000);
577 if (
f.type.id() == QMetaType::QDateTime)
579 else if (
f.type.id() == QMetaType::QDate)
585 if (
f.type.id() != QMetaType::QByteArray)
588 if (
d->row[field] ==
nullptr) {
596 fieldLength = mysql_fetch_lengths(
d->result)[field];
598 if (
f.type.id() != QMetaType::QByteArray)
602 switch (
f.type.id()) {
603 case QMetaType::LongLong:
605 case QMetaType::ULongLong:
607 case QMetaType::Char:
608 case QMetaType::Short:
611 case QMetaType::UChar:
612 case QMetaType::UShort:
613 case QMetaType::UInt:
615 case QMetaType::Double: {
618 double dbl =
val.toDouble(&
ok);
639 case QMetaType::QDate:
641 case QMetaType::QTime:
643 case QMetaType::QDateTime:
645 case QMetaType::QByteArray: {
648 if (
d->preparedQuery) {
655 case QMetaType::QString:
665 if (field < 0 || field >=
d->fields.size())
667 if (
d->preparedQuery)
668 return d->fields.at(field).nullIndicator;
670 return d->row[field] ==
nullptr;
679 d->preparedQuery =
false;
684 if (mysql_real_query(
d->drv_d_func()->mysql, encQuery.
data(), encQuery.
size())) {
689 d->result = mysql_store_result(
d->drv_d_func()->mysql);
690 if (!
d->result && mysql_field_count(
d->drv_d_func()->mysql) > 0) {
695 int numFields = mysql_field_count(
d->drv_d_func()->mysql);
697 d->fields.resize(numFields);
698 d->rowsAffected = mysql_affected_rows(
d->drv_d_func()->mysql);
701 for(
int i = 0;
i < numFields;
i++) {
702 MYSQL_FIELD* field = mysql_fetch_field_direct(
d->result,
i);
704 d->fields[
i].myField = field;
716 if (
d->preparedQuery)
717 return mysql_stmt_num_rows(
d->stmt);
719 return int(mysql_num_rows(
d->result));
727 return d->rowsAffected;
734 if (
d->preparedQuery) {
735 mysql_stmt_free_result(
d->stmt);
745 if (
d->preparedQuery) {
746 quint64 id = mysql_stmt_insert_id(
d->stmt);
750 quint64 id = mysql_insert_id(
d->drv_d_func()->mysql);
765 res =
d->preparedQuery ?
d->meta :
d->result;
767 if (!mysql_errno(
d->drv_d_func()->mysql)) {
768 mysql_field_seek(
res, 0);
769 MYSQL_FIELD* field = mysql_fetch_field(
res);
772 field = mysql_fetch_field(
res);
775 mysql_field_seek(
res, 0);
789 mysql_free_result(
d->result);
797 int status = mysql_next_result(
d->drv_d_func()->mysql);
802 }
else if (status == -1) {
806 d->result = mysql_store_result(
d->drv_d_func()->mysql);
807 unsigned int numFields = mysql_field_count(
d->drv_d_func()->mysql);
808 if (!
d->result && numFields > 0) {
815 d->fields.resize(numFields);
816 d->rowsAffected = mysql_affected_rows(
d->drv_d_func()->mysql);
819 for (
unsigned int i = 0;
i < numFields;
i++) {
820 MYSQL_FIELD *field = mysql_fetch_field_direct(
d->result,
i);
822 d->fields[
i].myField = field;
838 ||
type == QMetaType::QDateTime);
842 if (
type == QMetaType::QTime ||
type == QMetaType::QDateTime) {
846 myTime->second_part =
time.
msec() * 1000;
848 if (
type == QMetaType::QDate ||
type == QMetaType::QDateTime) {
864 if (!
d->drv_d_func()->preparedQuerysEnabled)
873 d->stmt = mysql_stmt_init(
d->drv_d_func()->mysql);
881 r = mysql_stmt_prepare(
d->stmt, encQuery.
constData(), encQuery.
size());
889 const auto paramCount = mysql_stmt_param_count(
d->stmt);
891 d->outBinds =
new MYSQL_BIND[paramCount]();
894 d->preparedQuery =
true;
903 if (!
d->preparedQuery)
915 r = mysql_stmt_reset(
d->stmt);
922 if (mysql_stmt_param_count(
d->stmt) > 0 &&
923 mysql_stmt_param_count(
d->stmt) == (
uint)
values.size()) {
928 void *
data =
const_cast<void *
>(
val.constData());
930 MYSQL_BIND* currBind = &
d->outBinds[
i];
933 currBind->is_null = &nullVector[
i];
935 currBind->is_unsigned = 0;
937 switch (
val.userType()) {
938 case QMetaType::QByteArray:
939 currBind->buffer_type = MYSQL_TYPE_BLOB;
940 currBind->buffer =
const_cast<char *
>(
val.toByteArray().constData());
941 currBind->buffer_length =
val.toByteArray().size();
944 case QMetaType::QTime:
945 case QMetaType::QDate:
946 case QMetaType::QDateTime: {
948 timeVector.
append(myTime);
950 currBind->buffer = myTime;
951 switch (
val.userType()) {
952 case QMetaType::QTime:
953 currBind->buffer_type = MYSQL_TYPE_TIME;
954 myTime->
time_type = MYSQL_TIMESTAMP_TIME;
956 case QMetaType::QDate:
957 currBind->buffer_type = MYSQL_TYPE_DATE;
958 myTime->
time_type = MYSQL_TIMESTAMP_DATE;
960 case QMetaType::QDateTime:
961 currBind->buffer_type = MYSQL_TYPE_DATETIME;
962 myTime->
time_type = MYSQL_TIMESTAMP_DATETIME;
968 currBind->length = 0;
970 case QMetaType::UInt:
972 currBind->buffer_type = MYSQL_TYPE_LONG;
973 currBind->buffer =
data;
974 currBind->buffer_length =
sizeof(int);
975 currBind->is_unsigned = (
val.userType() != QMetaType::Int);
977 case QMetaType::Bool:
978 currBind->buffer_type = MYSQL_TYPE_TINY;
979 currBind->buffer =
data;
980 currBind->buffer_length =
sizeof(bool);
981 currBind->is_unsigned =
false;
983 case QMetaType::Double:
984 currBind->buffer_type = MYSQL_TYPE_DOUBLE;
985 currBind->buffer =
data;
986 currBind->buffer_length =
sizeof(double);
988 case QMetaType::LongLong:
989 case QMetaType::ULongLong:
990 currBind->buffer_type = MYSQL_TYPE_LONGLONG;
991 currBind->buffer =
data;
992 currBind->buffer_length =
sizeof(
qint64);
993 currBind->is_unsigned = (
val.userType() == QMetaType::ULongLong);
995 case QMetaType::QString:
999 currBind->buffer_type = MYSQL_TYPE_STRING;
1000 currBind->buffer =
const_cast<char *
>(
ba.
constData());
1001 currBind->buffer_length =
ba.
size();
1006 r = mysql_stmt_bind_param(
d->stmt,
d->outBinds);
1014 r = mysql_stmt_execute(
d->stmt);
1026 d->rowsAffected = mysql_stmt_affected_rows(
d->stmt);
1029 my_bool update_max_length =
true;
1031 r = mysql_stmt_bind_result(
d->stmt,
d->inBinds);
1038 mysql_stmt_attr_set(
d->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &update_max_length);
1040 r = mysql_stmt_store_result(
d->stmt);
1052 r = mysql_stmt_bind_result(
d->stmt,
d->inBinds);
1072#ifndef Q_NO_MYSQL_EMBEDDED
1076 if (mysql_library_init(0, 0, 0)) {
1077 qWarning(
"QMYSQLDriver::qServerInit: unable to start server.");
1081#if defined(MARIADB_BASE_VERSION) || defined(MARIADB_VERSION_ID)
1088#if !defined(MARIADB_BASE_VERSION) && !defined(MARIADB_VERSION_ID)
1089# if !defined(Q_NO_MYSQL_EMBEDDED)
1090 mysql_library_end();
1123void QMYSQLDriver::init()
1143 if ((
d->mysql->server_capabilities & CLIENT_TRANSACTIONS) == CLIENT_TRANSACTIONS)
1162 return d->preparedQuerysEnabled;
1171 if (
opt ==
"CLIENT_COMPRESS"_L1)
1172 optionFlags |= CLIENT_COMPRESS;
1173 else if (
opt ==
"CLIENT_FOUND_ROWS"_L1)
1174 optionFlags |= CLIENT_FOUND_ROWS;
1175 else if (
opt ==
"CLIENT_IGNORE_SPACE"_L1)
1176 optionFlags |= CLIENT_IGNORE_SPACE;
1177 else if (
opt ==
"CLIENT_INTERACTIVE"_L1)
1178 optionFlags |= CLIENT_INTERACTIVE;
1179 else if (
opt ==
"CLIENT_NO_SCHEMA"_L1)
1180 optionFlags |= CLIENT_NO_SCHEMA;
1181 else if (
opt ==
"CLIENT_ODBC"_L1)
1182 optionFlags |= CLIENT_ODBC;
1183 else if (
opt ==
"CLIENT_SSL"_L1)
1184 qWarning(
"QMYSQLDriver: MYSQL_OPT_SSL_KEY, MYSQL_OPT_SSL_CERT and MYSQL_OPT_SSL_CA should be used instead of CLIENT_SSL.");
1186 qWarning(
"QMYSQLDriver::open: Unknown connect option '%s'",
opt.toLocal8Bit().constData());
1191 return mysql_options(mysql,
option,
v.toUtf8().constData()) == 0;
1197 const auto val =
v.toInt(&bOk);
1198 return bOk ? mysql_options(mysql,
option, &
val) == 0 :
false;
1203 bool val = (
v.isEmpty() ||
v ==
"TRUE"_L1 ||
v ==
"1"_L1);
1204 return mysql_options(mysql,
option, &
val) == 0;
1208#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 50711 && !defined(MARIADB_VERSION_ID)
1211 mysql_ssl_mode sslMode = SSL_MODE_DISABLED;
1212 if (
v ==
"DISABLED"_L1 ||
v ==
"SSL_MODE_DISABLED"_L1)
1213 sslMode = SSL_MODE_DISABLED;
1214 else if (
v ==
"PREFERRED"_L1 ||
v ==
"SSL_MODE_PREFERRED"_L1)
1215 sslMode = SSL_MODE_PREFERRED;
1216 else if (
v ==
"REQUIRED"_L1 ||
v ==
"SSL_MODE_REQUIRED"_L1)
1217 sslMode = SSL_MODE_REQUIRED;
1218 else if (
v ==
"VERIFY_CA"_L1 ||
v ==
"SSL_MODE_VERIFY_CA"_L1)
1219 sslMode = SSL_MODE_VERIFY_CA;
1220 else if (
v ==
"VERIFY_IDENTITY"_L1 ||
v ==
"SSL_MODE_VERIFY_IDENTITY"_L1)
1221 sslMode = SSL_MODE_VERIFY_IDENTITY;
1223 qWarning() <<
"Unknown ssl mode '" <<
v <<
"' - using SSL_MODE_DISABLED";
1224 return mysql_options(mysql,
option, &sslMode) == 0;
1230 mysql_protocol_type proto = MYSQL_PROTOCOL_DEFAULT;
1231 if (
v ==
"TCP"_L1 ||
v ==
"MYSQL_PROTOCOL_TCP"_L1)
1232 proto = MYSQL_PROTOCOL_TCP;
1233 else if (
v ==
"SOCKET"_L1 ||
v ==
"MYSQL_PROTOCOL_SOCKET"_L1)
1234 proto = MYSQL_PROTOCOL_SOCKET;
1235 else if (
v ==
"PIPE"_L1 ||
v ==
"MYSQL_PROTOCOL_PIPE"_L1)
1236 proto = MYSQL_PROTOCOL_PIPE;
1237 else if (
v ==
"MEMORY"_L1 ||
v ==
"MYSQL_PROTOCOL_MEMORY"_L1)
1238 proto = MYSQL_PROTOCOL_MEMORY;
1239 else if (
v ==
"DEFAULT"_L1 ||
v ==
"MYSQL_PROTOCOL_DEFAULT"_L1)
1240 proto = MYSQL_PROTOCOL_DEFAULT;
1242 qWarning() <<
"Unknown protocol '" <<
v <<
"' - using MYSQL_PROTOCOL_DEFAULT";
1243 return mysql_options(mysql,
option, &proto) == 0;
1257 if (!(
d->mysql = mysql_init(
nullptr))) {
1264 typedef bool (*SetOptionFunc)(MYSQL*, mysql_option,
QStringView);
1265 struct mysqloptions {
1270 const mysqloptions options[] = {
1283#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 50710
1286#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 50711 && !defined(MARIADB_VERSION_ID)
1287 {
"MYSQL_OPT_SSL_MODE"_L1, MYSQL_OPT_SSL_MODE, setOptionSslMode},
1289 {
"MYSQL_OPT_CONNECT_TIMEOUT"_L1, MYSQL_OPT_CONNECT_TIMEOUT,
setOptionInt},
1290 {
"MYSQL_OPT_READ_TIMEOUT"_L1, MYSQL_OPT_READ_TIMEOUT,
setOptionInt},
1291 {
"MYSQL_OPT_WRITE_TIMEOUT"_L1, MYSQL_OPT_WRITE_TIMEOUT,
setOptionInt},
1292 {
"MYSQL_OPT_RECONNECT"_L1, MYSQL_OPT_RECONNECT,
setOptionBool},
1293 {
"MYSQL_OPT_LOCAL_INFILE"_L1, MYSQL_OPT_LOCAL_INFILE,
setOptionInt},
1295 {
"MYSQL_SHARED_MEMORY_BASE_NAME"_L1, MYSQL_SHARED_MEMORY_BASE_NAME,
setOptionString},
1298 for (
const mysqloptions &
opt : options) {
1301 qWarning(
"QMYSQLDriver::open: Could not set connect option value '%s' to '%s'",
1302 key.toLocal8Bit().constData(),
value.toLocal8Bit().constData());
1315 unsigned int optionFlags = CLIENT_MULTI_STATEMENTS;
1320 for (
const auto &
option : opts) {
1323 if ((idx = sv.
indexOf(u
'=')) != -1) {
1326 if (trySetOption(
key,
val))
1328 else if (
key ==
"UNIX_SOCKET"_L1)
1329 unixSocket =
val.toString();
1330 else if (
val ==
"TRUE"_L1 ||
val ==
"1"_L1)
1333 qWarning(
"QMYSQLDriver::open: Illegal connect option value '%s'",
1341 static const char wanted_charsets[][8] = {
"utf8mb4",
"utf8" };
1342#ifdef MARIADB_VERSION_ID
1343 MARIADB_CHARSET_INFO *cs =
nullptr;
1344 for (
const char *
p : wanted_charsets) {
1345 cs = mariadb_get_charset_by_name(
p);
1347 d->mysql->charset = cs;
1358 MYSQL *mysql = mysql_real_connect(
d->mysql,
1367 if (mysql !=
d->mysql) {
1370 mysql_close(
d->mysql);
1377 if (!cs || mysql_set_character_set(
d->mysql, cs->csname) != 0) {
1379 for (
const char *
p : wanted_charsets) {
1380 if (mysql_set_character_set(
d->mysql,
p) == 0) {
1386 qWarning(
"MySQL: Unable to set the client character set to utf8 (\"%s\"). Using '%s' instead.",
1387 mysql_error(
d->mysql),
1388 mysql_character_set_name(
d->mysql));
1391 if (!
db.isEmpty() && mysql_select_db(
d->mysql,
db.toUtf8().constData())) {
1393 mysql_close(
d->mysql);
1401#if QT_CONFIG(thread)
1402 mysql_thread_init();
1414#if QT_CONFIG(thread)
1417 mysql_close(
d->mysql);
1436 QString sql =
"select table_name from information_schema.tables where table_schema = '"_L1 +
d->dbName +
"' and table_type = 'BASE TABLE'"_L1;
1440 tl.append(
q.value(0).toString());
1443 QString sql =
"select table_name from information_schema.tables where table_schema = '"_L1 +
d->dbName +
"' and table_type = 'VIEW'"_L1;
1447 tl.append(
q.value(0).toString());
1459 QString stmt(
"show index from %1;"_L1);
1462 while (
i.isActive() &&
i.next()) {
1463 if (
i.value(2).toString() ==
"PRIMARY"_L1) {
1466 idx.
setName(
i.value(2).toString());
1481 MYSQL_RES *
r = mysql_list_fields(
d->mysql,
table.toUtf8().constData(),
nullptr);
1486 while ((field = mysql_fetch_field(
r)))
1488 mysql_free_result(
r);
1502 qWarning(
"QMYSQLDriver::beginTransaction: Database not open");
1505 if (mysql_query(
d->mysql,
"BEGIN WORK")) {
1517 qWarning(
"QMYSQLDriver::commitTransaction: Database not open");
1520 if (mysql_query(
d->mysql,
"COMMIT")) {
1532 qWarning(
"QMYSQLDriver::rollbackTransaction: Database not open");
1535 if (mysql_query(
d->mysql,
"ROLLBACK")) {
1551 case QMetaType::Double:
1554 case QMetaType::QString:
1557 r.replace(
"\\"_L1,
"\\\\"_L1);
1559 case QMetaType::QByteArray:
1564 auto escapedSize = mysql_real_escape_string(
d->mysql,
buffer.data(),
ba.
data(),
ba.
size());
1565 r.reserve(escapedSize + 3);
1569 qWarning(
"QMYSQLDriver::formatValue: Database not open");
1572 case QMetaType::QDateTime:
1606 return identifier.
size() > 2
1613#include "moc_qsql_mysql_p.cpp"
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
\threadsafe
\inmodule QtCore\reentrant
\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...
qsizetype length() const noexcept
const_reference at(qsizetype i) const noexcept
void resize(qsizetype size)
void append(parameter_type t)
bool preparedQuerysEnabled
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...
QSqlIndex primaryIndex(const QString &tablename) const override
Returns the primary index for table tableName.
void close() override
Derived classes must reimplement this pure virtual function in order to close the database connection...
QString escapeIdentifier(const QString &identifier, IdentifierType type) const override
Returns the identifier escaped according to the database rules.
QStringList tables(QSql::TableType) const override
Returns a list of the names of the tables in the database.
QString formatValue(const QSqlField &field, bool trimStrings) const override
Returns a string representation of the field value for the database.
QMYSQLDriver(QObject *parent=nullptr)
bool commitTransaction() override
This function is called to commit a transaction.
QVariant handle() const override
Returns the low-level database handle wrapped in a QVariant or an invalid variant if there is no hand...
bool beginTransaction() override
This function is called to begin a transaction.
bool rollbackTransaction() override
This function is called to rollback a transaction.
bool hasFeature(DriverFeature f) const override
Returns true if the driver supports feature feature; otherwise returns false.
QSqlResult * createResult() const override
Creates an empty SQL result on the database.
bool isIdentifierEscaped(const QString &identifier, IdentifierType type) const override
Returns whether identifier is escaped according to the database rules.
QSqlRecord record(const QString &tablename) const override
Returns a QSqlRecord populated with the names of the fields in table tableName.
QMYSQLResult(const QMYSQLDriver *db)
QSqlRecord record() const override
Returns the current record if the query is active; otherwise returns an empty QSqlRecord.
bool exec() override
Executes the query, returning true if successful; otherwise returns false.
bool isNull(int field) override
Returns true if the field at position index in the current row is null; otherwise returns false.
int numRowsAffected() override
Returns the number of rows affected by the last query executed, or -1 if it cannot be determined or i...
bool fetchNext() override
Positions the result to the next available record (row) in the result.
bool fetchFirst() override
Positions the result to the first record (row 0) in the result.
QVariant lastInsertId() const override
Returns the object ID of the most recent inserted row if the database supports it.
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 reset(const QString &query) override
Sets the result to use the SQL statement query for subsequent data retrieval.
void virtual_hook(int id, void *data) override
QVariant data(int field) override
Returns the data for field index in the current row as a QVariant.
bool fetch(int i) override
Positions the result to an arbitrary (zero-based) row index.
QVariant handle() const override
Returns the low-level database handle for this result set wrapped in a QVariant or an invalid QVarian...
bool fetchLast() override
Positions the result to the last record (last row) in the result.
bool prepare(const QString &stmt) override
Prepares the given query for execution; the query will normally use placeholders so that it can be ex...
void detachFromResultSet() override
bool nextResult() override
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.
int precision() const
Returns the field's precision; this is only meaningful for numeric types.
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.
void setName(const QString &name)
Sets the name of the index to name.
void setCursorName(const QString &cursorName)
Sets the name of the cursor that the index is associated with to cursorName.
void append(const QSqlField &field)
Appends the field field to the list of indexed fields.
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)
QSqlResultPrivate(QSqlResult *q, const QSqlDriver *drv)
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.
virtual void virtual_hook(int id, void *data)
int at() const
Returns the current (zero-based) row position of the result.
virtual bool prepare(const QString &query)
Prepares the given query for execution; the query will normally use placeholders so that it can be ex...
virtual bool exec()
Executes the query, returning true if successful; otherwise returns false.
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...
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.
bool isActive() const
Returns true if the result has records to be retrieved; otherwise returns false.
constexpr QStringView left(qsizetype n) const noexcept
QByteArray toLocal8Bit() const
Returns a local 8-bit representation of the string as a QByteArray.
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
QStringView trimmed() const noexcept
Strips leading and trailing whitespace and returns the result.
qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
\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 & replace(qsizetype i, qsizetype len, QChar after)
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isNull() const
Returns true if this string is null; otherwise returns false.
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 arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') 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.
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 &
\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.
QDateTime toDateTime() const
Returns the variant as a QDateTime if the variant has userType() \l QMetaType::QDateTime,...
double toDouble(bool *ok=nullptr) const
Returns the variant as a double if the variant has userType() \l QMetaType::Double,...
qlonglong toLongLong(bool *ok=nullptr) const
Returns the variant as a long long int if the variant has userType() \l QMetaType::LongLong,...
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
uint toUInt(bool *ok=nullptr) const
Returns the variant as an unsigned int if the variant has userType() \l QMetaType::UInt,...
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
QByteArray toByteArray() const
Returns the variant as a QByteArray if the variant has userType() \l QMetaType::QByteArray or \l QMet...
qDeleteAll(list.begin(), list.end())
Combined button and popup list for selecting options.
void qAddPostRoutine(QtCleanUpFunction p)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLenum GLsizei GLsizei GLint * values
[15]
GLsizei const GLfloat * v
[13]
GLuint64 GLenum void * handle
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLdouble GLdouble GLdouble GLdouble q
GLenum GLenum GLsizei void * table
static void split(QT_FT_Vector *b)
static QSqlError qMakeError(const QString &err, QSqlError::ErrorType type, const QDB2DriverPrivate *p)
static bool setOptionString(MYSQL *mysql, mysql_option option, QStringView v)
static bool qMySqlInitHandledByUser
static QVariant qTimeFromString(const QString &val)
static bool qIsTimeOrDate(enum_field_types t)
static void setOptionFlag(uint &optionFlags, QStringView opt)
static bool setOptionInt(MYSQL *mysql, mysql_option option, QStringView v)
static QVariant qDateTimeFromString(QString &val)
static bool setOptionBool(MYSQL *mysql, mysql_option option, QStringView v)
static bool checkPreparedQueries(MYSQL *mysql)
static bool qIsBlob(enum_field_types t)
static uint64_t qDecodeBitfield(const QMYSQLResultPrivate::QMyField &f, const char *outField)
static bool qIsInteger(int t)
static void qLibraryInit()
static QSqlError qMakeError(const QString &err, QSqlError::ErrorType type, const QMYSQLDriverPrivate *p)
static QVariant qDateFromString(const QString &val)
static bool qIsBitfield(enum_field_types type)
static int qMySqlConnectionCount
static QSqlError qMakeStmtError(const QString &err, QSqlError::ErrorType type, MYSQL_STMT *stmt)
static void qLibraryEnd()
static QSqlField qToField(MYSQL_FIELD *field)
static bool setOptionProtocol(MYSQL *mysql, mysql_option option, QStringView v)
static QMetaType qDecodeMYSQLType(enum_field_types mysqltype, uint flags)
static QT_MYSQL_TIME * toMySqlDate(QDate date, QTime time, int type)
decltype(mysql_stmt_bind_result(nullptr, nullptr)) my_bool
#define Q_DECLARE_SQLDRIVER_PRIVATE(Class)
#define QStringLiteral(str)
unsigned long long quint64
QFileInfo info(fileName)
[8]
socketLayer bind(QHostAddress::Any, 4000)
const MYSQL_FIELD * myField
unsigned long second_part
enum enum_mysql_timestamp_type time_type
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent