@@ -187,10 +187,10 @@ class QMYSQLResultPrivate: public QSqlResultPrivate
187187 bool preparedQuery = false ;
188188};
189189
190- static QSqlError qMakeError (const QString& err, QSqlError::ErrorType type,
191- const QMYSQLDriverPrivate* p)
190+ static QSqlError qMakeError (const QString & err, QSqlError::ErrorType type,
191+ const QMYSQLDriverPrivate * p)
192192{
193- const char *cerr = p->mysql ? mysql_error (p->mysql ) : 0 ;
193+ const char *cerr = p->mysql ? mysql_error (p->mysql ) : nullptr ;
194194 return QSqlError (" QMYSQL: " _L1 + err,
195195 QString::fromUtf8 (cerr),
196196 type, QString::number (mysql_errno (p->mysql )));
@@ -269,8 +269,8 @@ static QSqlField qToField(MYSQL_FIELD *field)
269269 return f;
270270}
271271
272- static QSqlError qMakeStmtError (const QString& err, QSqlError::ErrorType type,
273- MYSQL_STMT* stmt)
272+ static QSqlError qMakeStmtError (const QString & err, QSqlError::ErrorType type,
273+ MYSQL_STMT * stmt)
274274{
275275 const char *cerr = mysql_stmt_error (stmt);
276276 return QSqlError (" QMYSQL: " _L1 + err,
@@ -409,9 +409,8 @@ void QMYSQLResult::cleanup()
409409 d->meta = 0 ;
410410 }
411411
412- int i;
413- for (i = 0 ; i < d->fields .size (); ++i)
414- delete[] d->fields [i].outField ;
412+ for (const QMYSQLResultPrivate::QMyField &f : std::as_const (d->fields ))
413+ delete[] f.outField ;
415414
416415 if (d->outBinds ) {
417416 delete[] d->outBinds ;
@@ -501,12 +500,7 @@ bool QMYSQLResult::fetchLast()
501500 return success;
502501 }
503502
504- my_ulonglong numRows;
505- if (d->preparedQuery ) {
506- numRows = mysql_stmt_num_rows (d->stmt );
507- } else {
508- numRows = mysql_num_rows (d->result );
509- }
503+ my_ulonglong numRows = d->preparedQuery ? mysql_stmt_num_rows (d->stmt ) : mysql_num_rows (d->result );
510504 if (at () == int (numRows))
511505 return true ;
512506 if (!numRows)
@@ -747,7 +741,7 @@ QSqlRecord QMYSQLResult::record() const
747741 if (!mysql_errno (d->drv_d_func ()->mysql )) {
748742 mysql_field_seek (res, 0 );
749743 MYSQL_FIELD* field = mysql_fetch_field (res);
750- while (field) {
744+ while (field) {
751745 info.append (qToField (field));
752746 field = mysql_fetch_field (res);
753747 }
@@ -770,8 +764,8 @@ bool QMYSQLResult::nextResult()
770764 d->result = 0 ;
771765 setSelect (false );
772766
773- for (int i = 0 ; i < d->fields . size (); ++i )
774- delete[] d-> fields [i] .outField ;
767+ for (const QMYSQLResultPrivate::QMyField &f : std::as_const ( d->fields ) )
768+ delete[] f .outField ;
775769 d->fields .clear ();
776770
777771 int status = mysql_next_result (d->drv_d_func ()->mysql );
@@ -784,7 +778,7 @@ bool QMYSQLResult::nextResult()
784778 }
785779
786780 d->result = mysql_store_result (d->drv_d_func ()->mysql );
787- int numFields = mysql_field_count (d->drv_d_func ()->mysql );
781+ unsigned int numFields = mysql_field_count (d->drv_d_func ()->mysql );
788782 if (!d->result && numFields > 0 ) {
789783 setLastError (qMakeError (QCoreApplication::translate (" QMYSQLResult" , " Unable to store next result" ),
790784 QSqlError::StatementError, d->drv_d_func ()));
@@ -796,8 +790,8 @@ bool QMYSQLResult::nextResult()
796790 d->rowsAffected = mysql_affected_rows (d->drv_d_func ()->mysql );
797791
798792 if (isSelect ()) {
799- for (int i = 0 ; i < numFields; i++) {
800- MYSQL_FIELD* field = mysql_fetch_field_direct (d->result , i);
793+ for (unsigned int i = 0 ; i < numFields; i++) {
794+ MYSQL_FIELD * field = mysql_fetch_field_direct (d->result , i);
801795 d->fields [i].type = qDecodeMYSQLType (field->type , field->flags );
802796 }
803797 }
@@ -902,7 +896,7 @@ bool QMYSQLResult::exec()
902896 mysql_stmt_param_count (d->stmt ) == (uint)values.size ()) {
903897
904898 nullVector.resize (values.size ());
905- for (int i = 0 ; i < values.size (); ++i) {
899+ for (qsizetype i = 0 ; i < values.size (); ++i) {
906900 const QVariant &val = boundValues ().at (i);
907901 void *data = const_cast <void *>(val.constData ());
908902
@@ -1145,7 +1139,7 @@ bool QMYSQLDriver::hasFeature(DriverFeature f) const
11451139 return false ;
11461140}
11471141
1148- static void setOptionFlag (uint &optionFlags, const QString & opt)
1142+ static void setOptionFlag (uint &optionFlags, QStringView opt)
11491143{
11501144 if (opt == " CLIENT_COMPRESS" _L1)
11511145 optionFlags |= CLIENT_COMPRESS;
@@ -1160,85 +1154,115 @@ static void setOptionFlag(uint &optionFlags, const QString &opt)
11601154 else if (opt == " CLIENT_ODBC" _L1)
11611155 optionFlags |= CLIENT_ODBC;
11621156 else if (opt == " CLIENT_SSL" _L1)
1163- qWarning (" QMYSQLDriver: SSL_KEY, SSL_CERT and SSL_CA should be used instead of CLIENT_SSL." );
1157+ qWarning (" QMYSQLDriver: MYSQL_OPT_SSL_KEY, MYSQL_OPT_SSL_CERT and MYSQL_OPT_SSL_CA should be used instead of CLIENT_SSL." );
11641158 else
11651159 qWarning (" QMYSQLDriver::open: Unknown connect option '%s'" , opt.toLocal8Bit ().constData ());
11661160}
11671161
1168- bool QMYSQLDriver::open (const QString& db,
1169- const QString& user,
1170- const QString& password,
1171- const QString& host,
1172- int port,
1173- const QString& connOpts)
1162+ static bool setOptionString (MYSQL *mysql, mysql_option option, QStringView v)
1163+ {
1164+ return mysql_options (mysql, option, v.toUtf8 ().constData ()) == 0 ;
1165+ }
1166+
1167+ static bool setOptionInt (MYSQL *mysql, mysql_option option, QStringView v)
1168+ {
1169+ bool bOk;
1170+ const auto val = v.toInt (&bOk);
1171+ return bOk ? mysql_options (mysql, option, &val) == 0 : false ;
1172+ }
1173+
1174+ static bool setOptionBool (MYSQL *mysql, mysql_option option, QStringView v)
1175+ {
1176+ bool val = (v.isEmpty () || v == " TRUE" _L1 || v == " 1" _L1);
1177+ return mysql_options (mysql, option, &val) == 0 ;
1178+ }
1179+
1180+ bool QMYSQLDriver::open (const QString &db,
1181+ const QString &user,
1182+ const QString &password,
1183+ const QString &host,
1184+ int port,
1185+ const QString &connOpts)
11741186{
11751187 Q_D (QMYSQLDriver);
11761188 if (isOpen ())
11771189 close ();
11781190
1191+ if (!(d->mysql = mysql_init (nullptr ))) {
1192+ setLastError (qMakeError (tr (" Unable to allocate a MYSQL object" ),
1193+ QSqlError::ConnectionError, d));
1194+ setOpenError (true );
1195+ return false ;
1196+ }
1197+
1198+ typedef bool (*SetOptionFunc)(MYSQL*, mysql_option, QStringView);
1199+ struct mysqloptions {
1200+ QLatin1StringView key;
1201+ mysql_option option;
1202+ SetOptionFunc func;
1203+ };
1204+ const mysqloptions options[] = {
1205+ {" SSL_KEY" _L1, MYSQL_OPT_SSL_KEY, setOptionString},
1206+ {" SSL_CERT" _L1, MYSQL_OPT_SSL_CERT, setOptionString},
1207+ {" SSL_CA" _L1, MYSQL_OPT_SSL_CA, setOptionString},
1208+ {" SSL_CAPATH" _L1, MYSQL_OPT_SSL_CAPATH, setOptionString},
1209+ {" SSL_CIPHER" _L1, MYSQL_OPT_SSL_CIPHER, setOptionString},
1210+ {" MYSQL_OPT_SSL_KEY" _L1, MYSQL_OPT_SSL_KEY, setOptionString},
1211+ {" MYSQL_OPT_SSL_CERT" _L1, MYSQL_OPT_SSL_CERT, setOptionString},
1212+ {" MYSQL_OPT_SSL_CA" _L1, MYSQL_OPT_SSL_CA, setOptionString},
1213+ {" MYSQL_OPT_SSL_CAPATH" _L1, MYSQL_OPT_SSL_CAPATH, setOptionString},
1214+ {" MYSQL_OPT_SSL_CIPHER" _L1, MYSQL_OPT_SSL_CIPHER, setOptionString},
1215+ {" MYSQL_OPT_SSL_CRL" _L1, MYSQL_OPT_SSL_CRL, setOptionString},
1216+ {" MYSQL_OPT_SSL_CRLPATH" _L1, MYSQL_OPT_SSL_CRLPATH, setOptionString},
1217+ {" MYSQL_OPT_CONNECT_TIMEOUT" _L1, MYSQL_OPT_CONNECT_TIMEOUT, setOptionInt},
1218+ {" MYSQL_OPT_READ_TIMEOUT" _L1, MYSQL_OPT_READ_TIMEOUT, setOptionInt},
1219+ {" MYSQL_OPT_WRITE_TIMEOUT" _L1, MYSQL_OPT_WRITE_TIMEOUT, setOptionInt},
1220+ {" MYSQL_OPT_RECONNECT" _L1, MYSQL_OPT_RECONNECT, setOptionBool},
1221+ {" MYSQL_OPT_LOCAL_INFILE" _L1, MYSQL_OPT_LOCAL_INFILE, setOptionInt},
1222+ };
1223+ auto trySetOption = [&](const QStringView &key, const QStringView &value) -> bool {
1224+ for (const mysqloptions &opt : options) {
1225+ if (key == opt.key ) {
1226+ if (!opt.func (d->mysql , opt.option , value)) {
1227+ qWarning (" QMYSQLDriver::open: Could not set connect option value '%s' to '%s'" ,
1228+ key.toLocal8Bit ().constData (), value.toLocal8Bit ().constData ());
1229+ }
1230+ return true ;
1231+ }
1232+ }
1233+ return false ;
1234+ };
1235+
11791236 /* This is a hack to get MySQL's stored procedure support working.
11801237 Since a stored procedure _may_ return multiple result sets,
11811238 we have to enable CLIEN_MULTI_STATEMENTS here, otherwise _any_
11821239 stored procedure call will fail.
11831240 */
11841241 unsigned int optionFlags = CLIENT_MULTI_STATEMENTS;
1185- const QStringList opts (connOpts.split (u' ;' , Qt::SkipEmptyParts));
1242+ const QList<QStringView> opts (QStringView ( connOpts) .split (u' ;' , Qt::SkipEmptyParts));
11861243 QString unixSocket;
1187- QString sslCert;
1188- QString sslCA;
1189- QString sslKey;
1190- QString sslCAPath;
1191- QString sslCipher;
1192- my_bool reconnect=false ;
1193- uint connectTimeout = 0 ;
1194- uint readTimeout = 0 ;
1195- uint writeTimeout = 0 ;
11961244
11971245 // extract the real options from the string
1198- for (int i = 0 ; i < opts. size (); ++i ) {
1199- QString tmp (opts. at (i). simplified () );
1246+ for (const auto &option : opts) {
1247+ const QStringView sv = QStringView (option). trimmed ( );
12001248 qsizetype idx;
1201- if ((idx = tmp.indexOf (u' =' )) != -1 ) {
1202- QString val = tmp.mid (idx + 1 ).simplified ();
1203- QString opt = tmp.left (idx).simplified ();
1204- if (opt == " UNIX_SOCKET" _L1)
1205- unixSocket = val;
1206- else if (opt == " MYSQL_OPT_RECONNECT" _L1) {
1207- if (val == " TRUE" _L1 || val == " 1" _L1 || val.isEmpty ())
1208- reconnect = true ;
1209- } else if (opt == " MYSQL_OPT_CONNECT_TIMEOUT" _L1)
1210- connectTimeout = val.toInt ();
1211- else if (opt == " MYSQL_OPT_READ_TIMEOUT" _L1)
1212- readTimeout = val.toInt ();
1213- else if (opt == " MYSQL_OPT_WRITE_TIMEOUT" _L1)
1214- writeTimeout = val.toInt ();
1215- else if (opt == " SSL_KEY" _L1)
1216- sslKey = val;
1217- else if (opt == " SSL_CERT" _L1)
1218- sslCert = val;
1219- else if (opt == " SSL_CA" _L1)
1220- sslCA = val;
1221- else if (opt == " SSL_CAPATH" _L1)
1222- sslCAPath = val;
1223- else if (opt == " SSL_CIPHER" _L1)
1224- sslCipher = val;
1249+ if ((idx = sv.indexOf (u' =' )) != -1 ) {
1250+ const QStringView key = sv.left (idx).trimmed ();
1251+ const QStringView val = sv.mid (idx + 1 ).trimmed ();
1252+ if (trySetOption (key, val))
1253+ continue ;
1254+ else if (key == " UNIX_SOCKET" _L1)
1255+ unixSocket = val.toString ();
12251256 else if (val == " TRUE" _L1 || val == " 1" _L1)
1226- setOptionFlag (optionFlags, tmp. left (idx). simplified () );
1257+ setOptionFlag (optionFlags, key );
12271258 else
12281259 qWarning (" QMYSQLDriver::open: Illegal connect option value '%s'" ,
1229- tmp .toLocal8Bit ().constData ());
1260+ sv .toLocal8Bit ().constData ());
12301261 } else {
1231- setOptionFlag (optionFlags, tmp );
1262+ setOptionFlag (optionFlags, sv );
12321263 }
12331264 }
12341265
1235- if (!(d->mysql = mysql_init (nullptr ))) {
1236- setLastError (qMakeError (tr (" Unable to allocate a MYSQL object" ),
1237- QSqlError::ConnectionError, d));
1238- setOpenError (true );
1239- return false ;
1240- }
1241-
12421266 // try utf8 with non BMP first, utf8 (BMP only) if that fails
12431267 static const char wanted_charsets[][8 ] = { " utf8mb4" , " utf8" };
12441268#ifdef MARIADB_VERSION_ID
@@ -1257,23 +1281,6 @@ bool QMYSQLDriver::open(const QString& db,
12571281 } *cs = nullptr ;
12581282#endif
12591283
1260- if (!sslKey.isNull () || !sslCert.isNull () || !sslCA.isNull () ||
1261- !sslCAPath.isNull () || !sslCipher.isNull ()) {
1262- mysql_ssl_set (d->mysql ,
1263- sslKey.isNull () ? nullptr : sslKey.toUtf8 ().constData (),
1264- sslCert.isNull () ? nullptr : sslCert.toUtf8 ().constData (),
1265- sslCA.isNull () ? nullptr : sslCA.toUtf8 ().constData (),
1266- sslCAPath.isNull () ? nullptr : sslCAPath.toUtf8 ().constData (),
1267- sslCipher.isNull () ? nullptr : sslCipher.toUtf8 ().constData ());
1268- }
1269-
1270- if (connectTimeout != 0 )
1271- mysql_options (d->mysql , MYSQL_OPT_CONNECT_TIMEOUT, &connectTimeout);
1272- if (readTimeout != 0 )
1273- mysql_options (d->mysql , MYSQL_OPT_READ_TIMEOUT, &readTimeout);
1274- if (writeTimeout != 0 )
1275- mysql_options (d->mysql , MYSQL_OPT_WRITE_TIMEOUT, &writeTimeout);
1276-
12771284 MYSQL *mysql = mysql_real_connect (d->mysql ,
12781285 host.isNull () ? nullptr : host.toUtf8 ().constData (),
12791286 user.isNull () ? nullptr : user.toUtf8 ().constData (),
@@ -1314,9 +1321,6 @@ bool QMYSQLDriver::open(const QString& db,
13141321 return false ;
13151322 }
13161323
1317- if (reconnect)
1318- mysql_options (d->mysql , MYSQL_OPT_RECONNECT, &reconnect);
1319-
13201324 d->preparedQuerysEnabled = checkPreparedQueries (d->mysql );
13211325
13221326#if QT_CONFIG(thread)
@@ -1369,7 +1373,7 @@ QStringList QMYSQLDriver::tables(QSql::TableType type) const
13691373 return tl;
13701374}
13711375
1372- QSqlIndex QMYSQLDriver::primaryIndex (const QString& tablename) const
1376+ QSqlIndex QMYSQLDriver::primaryIndex (const QString & tablename) const
13731377{
13741378 QSqlIndex idx;
13751379 if (!isOpen ())
@@ -1390,22 +1394,19 @@ QSqlIndex QMYSQLDriver::primaryIndex(const QString& tablename) const
13901394 return idx;
13911395}
13921396
1393- QSqlRecord QMYSQLDriver::record (const QString& tablename) const
1397+ QSqlRecord QMYSQLDriver::record (const QString & tablename) const
13941398{
13951399 Q_D (const QMYSQLDriver);
1396- QString table=tablename;
1397- if (isIdentifierEscaped (table, QSqlDriver::TableName))
1398- table = stripDelimiters (table, QSqlDriver::TableName);
1400+ const QString table = stripDelimiters (tablename, QSqlDriver::TableName);
13991401
14001402 QSqlRecord info;
14011403 if (!isOpen ())
14021404 return info;
1403- MYSQL_RES* r = mysql_list_fields (d->mysql , table.toUtf8 ().constData (), 0 );
1404- if (!r) {
1405+ MYSQL_RES * r = mysql_list_fields (d->mysql , table.toUtf8 ().constData (), nullptr );
1406+ if (!r)
14051407 return info;
1406- }
1407- MYSQL_FIELD* field;
14081408
1409+ MYSQL_FIELD *field;
14091410 while ((field = mysql_fetch_field (r)))
14101411 info.append (qToField (field));
14111412 mysql_free_result (r);
@@ -1516,9 +1517,9 @@ QString QMYSQLDriver::formatValue(const QSqlField &field, bool trimStrings) cons
15161517QString QMYSQLDriver::escapeIdentifier (const QString &identifier, IdentifierType) const
15171518{
15181519 QString res = identifier;
1519- if (!identifier.isEmpty () && !identifier.startsWith (u' `' ) && !identifier.endsWith (u' `' ) ) {
1520- res.prepend (u' `' ).append (u' `' );
1520+ if (!identifier.isEmpty () && !identifier.startsWith (u' `' ) && !identifier.endsWith (u' `' )) {
15211521 res.replace (u' .' , " `.`" _L1);
1522+ res = u' `' + res + u' `' ;
15221523 }
15231524 return res;
15241525}
0 commit comments