1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qsqldriver.h"
5
6#include "qdatetime.h"
7#include "qsqlerror.h"
8#include "qsqlfield.h"
9#include "qsqlindex.h"
10#include "private/qsqldriver_p.h"
11#include "private/qtools_p.h"
12
13#include <limits.h>
14
15QT_BEGIN_NAMESPACE
16
17using namespace Qt::StringLiterals;
18
19static QString prepareIdentifier(const QString &identifier,
20 QSqlDriver::IdentifierType type, const QSqlDriver *driver)
21{
22 Q_ASSERT(driver != nullptr);
23 QString ret = identifier;
24 if (!driver->isIdentifierEscaped(identifier, type))
25 ret = driver->escapeIdentifier(identifier, type);
26 return ret;
27}
28
29/*!
30 \class QSqlDriver
31 \brief The QSqlDriver class is an abstract base class for accessing
32 specific SQL databases.
33
34 \ingroup database
35 \inmodule QtSql
36
37 This class should not be used directly. Use QSqlDatabase instead.
38
39 If you want to create your own SQL drivers, you can subclass this
40 class and reimplement its pure virtual functions and those
41 virtual functions that you need. See \l{How to Write Your Own
42 Database Driver} for more information.
43
44 \sa QSqlDatabase, QSqlResult
45*/
46
47/*!
48 Constructs a new driver with the given \a parent.
49*/
50
51QSqlDriver::QSqlDriver(QObject *parent)
52 : QObject(*new QSqlDriverPrivate, parent)
53{
54}
55
56/*! \internal
57*/
58QSqlDriver::QSqlDriver(QSqlDriverPrivate &dd, QObject *parent)
59 : QObject(dd, parent)
60{
61}
62
63/*!
64 Destroys the object and frees any allocated resources.
65*/
66
67QSqlDriver::~QSqlDriver()
68{
69}
70
71/*!
72 \since 5.0
73
74 \fn QSqlDriver::notification(const QString &name, QSqlDriver::NotificationSource source, const QVariant & payload)
75
76 This signal is emitted when the database posts an event notification
77 that the driver subscribes to. \a name identifies the event notification, \a source indicates the signal source,
78 \a payload holds the extra data optionally delivered with the notification.
79
80 \sa subscribeToNotification()
81*/
82
83/*!
84 \fn bool QSqlDriver::open(const QString &db, const QString &user, const QString& password,
85 const QString &host, int port, const QString &options)
86
87 Derived classes must reimplement this pure virtual function to
88 open a database connection on database \a db, using user name \a
89 user, password \a password, host \a host, port \a port and
90 connection options \a options.
91
92 The function must return true on success and false on failure.
93
94 \sa setOpen()
95*/
96
97/*!
98 \fn bool QSqlDriver::close()
99
100 Derived classes must reimplement this pure virtual function in
101 order to close the database connection. Return true on success,
102 false on failure.
103
104 \sa open(), setOpen()
105*/
106
107/*!
108 \fn QSqlResult *QSqlDriver::createResult() const
109
110 Creates an empty SQL result on the database. Derived classes must
111 reimplement this function and return a QSqlResult object
112 appropriate for their database to the caller.
113*/
114
115/*!
116 Returns \c true if the database connection is open; otherwise returns
117 false.
118*/
119
120bool QSqlDriver::isOpen() const
121{
122 Q_D(const QSqlDriver);
123 return d->isOpen;
124}
125
126/*!
127 Returns \c true if the there was an error opening the database
128 connection; otherwise returns \c false.
129*/
130
131bool QSqlDriver::isOpenError() const
132{
133 Q_D(const QSqlDriver);
134 return d->isOpenError;
135}
136
137/*!
138 \enum QSqlDriver::DriverFeature
139
140 This enum contains a list of features a driver might support. Use
141 hasFeature() to query whether a feature is supported or not.
142
143 \value Transactions Whether the driver supports SQL transactions.
144 \value QuerySize Whether the database is capable of reporting the size
145 of a query. Note that some databases do not support returning the size
146 (i.e. number of rows returned) of a query, in which case
147 QSqlQuery::size() will return -1.
148 \value BLOB Whether the driver supports Binary Large Object fields.
149 \value Unicode Whether the driver supports Unicode strings if the
150 database server does.
151 \value PreparedQueries Whether the driver supports prepared query execution.
152 \value NamedPlaceholders Whether the driver supports the use of named placeholders.
153 \value PositionalPlaceholders Whether the driver supports the use of positional placeholders.
154 \value LastInsertId Whether the driver supports returning the Id of the last touched row.
155 \value BatchOperations Whether the driver supports batched operations, see QSqlQuery::execBatch()
156 \value SimpleLocking Whether the driver disallows a write lock on a table while other queries have a read lock on it.
157 \value LowPrecisionNumbers Whether the driver allows fetching numerical values with low precision.
158 \value EventNotifications Whether the driver supports database event notifications.
159 \value FinishQuery Whether the driver can do any low-level resource cleanup when QSqlQuery::finish() is called.
160 \value MultipleResultSets Whether the driver can access multiple result sets returned from batched statements or stored procedures.
161 \value CancelQuery Whether the driver allows cancelling a running query.
162
163 More information about supported features can be found in the
164 \l{sql-driver.html}{Qt SQL driver} documentation.
165
166 \sa hasFeature()
167*/
168
169/*!
170 \enum QSqlDriver::StatementType
171
172 This enum contains a list of SQL statement (or clause) types the
173 driver can create.
174
175 \value WhereStatement An SQL \c WHERE statement (e.g., \c{WHERE f = 5}).
176 \value SelectStatement An SQL \c SELECT statement (e.g., \c{SELECT f FROM t}).
177 \value UpdateStatement An SQL \c UPDATE statement (e.g., \c{UPDATE TABLE t set f = 1}).
178 \value InsertStatement An SQL \c INSERT statement (e.g., \c{INSERT INTO t (f) values (1)}).
179 \value DeleteStatement An SQL \c DELETE statement (e.g., \c{DELETE FROM t}).
180
181 \sa sqlStatement()
182*/
183
184/*!
185 \enum QSqlDriver::IdentifierType
186
187 This enum contains a list of SQL identifier types.
188
189 \value FieldName A SQL field name
190 \value TableName A SQL table name
191*/
192
193/*!
194 \enum QSqlDriver::NotificationSource
195
196 This enum contains a list of SQL notification sources.
197
198 \value UnknownSource The notification source is unknown
199 \value SelfSource The notification source is this connection
200 \value OtherSource The notification source is another connection
201*/
202
203/*!
204 \enum QSqlDriver::DbmsType
205 \internal
206
207 This enum contains DBMS types.
208
209 \value UnknownDbms
210 \value MSSqlServer
211 \value MySqlServer
212 \value PostgreSQL
213 \value Oracle
214 \value Sybase
215 \value SQLite
216 \value Interbase
217 \value DB2
218 \value [since 6.6] MimerSQL
219*/
220
221/*!
222 \fn bool QSqlDriver::hasFeature(DriverFeature feature) const
223
224 Returns \c true if the driver supports feature \a feature; otherwise
225 returns \c false.
226
227 Note that some databases need to be open() before this can be
228 determined.
229
230 \sa DriverFeature
231*/
232
233/*!
234 This function sets the open state of the database to \a open.
235 Derived classes can use this function to report the status of
236 open().
237
238 \sa open(), setOpenError()
239*/
240
241void QSqlDriver::setOpen(bool open)
242{
243 Q_D(QSqlDriver);
244 d->isOpen = open;
245}
246
247/*!
248 This function sets the open error state of the database to \a
249 error. Derived classes can use this function to report the status
250 of open(). Note that if \a error is true the open state of the
251 database is set to closed (i.e., isOpen() returns \c false).
252
253 \sa open(), setOpen()
254*/
255
256void QSqlDriver::setOpenError(bool error)
257{
258 Q_D(QSqlDriver);
259 d->isOpenError = error;
260 if (error)
261 d->isOpen = false;
262}
263
264/*!
265 This function is called to begin a transaction. If successful,
266 return true, otherwise return false. The default implementation
267 does nothing and returns \c false.
268
269 \sa commitTransaction(), rollbackTransaction()
270*/
271
272bool QSqlDriver::beginTransaction()
273{
274 return false;
275}
276
277/*!
278 This function is called to commit a transaction. If successful,
279 return true, otherwise return false. The default implementation
280 does nothing and returns \c false.
281
282 \sa beginTransaction(), rollbackTransaction()
283*/
284
285bool QSqlDriver::commitTransaction()
286{
287 return false;
288}
289
290/*!
291 This function is called to rollback a transaction. If successful,
292 return true, otherwise return false. The default implementation
293 does nothing and returns \c false.
294
295 \sa beginTransaction(), commitTransaction()
296*/
297
298bool QSqlDriver::rollbackTransaction()
299{
300 return false;
301}
302
303/*!
304 This function is used to set the value of the last error, \a error,
305 that occurred on the database.
306
307 \sa lastError()
308*/
309
310void QSqlDriver::setLastError(const QSqlError &error)
311{
312 Q_D(QSqlDriver);
313 d->error = error;
314}
315
316/*!
317 Returns a QSqlError object which contains information about the
318 last error that occurred on the database.
319*/
320
321QSqlError QSqlDriver::lastError() const
322{
323 Q_D(const QSqlDriver);
324 return d->error;
325}
326
327/*!
328 Returns a list of the names of the tables in the database. The
329 default implementation returns an empty list.
330
331 The \a tableType argument describes what types of tables
332 should be returned. Due to binary compatibility, the string
333 contains the value of the enum QSql::TableTypes as text.
334 An empty string should be treated as QSql::Tables for
335 backward compatibility.
336*/
337
338QStringList QSqlDriver::tables(QSql::TableType) const
339{
340 return QStringList();
341}
342
343/*!
344 Returns the primary index for table \a tableName. Returns an empty
345 QSqlIndex if the table doesn't have a primary index. The default
346 implementation returns an empty index.
347*/
348
349QSqlIndex QSqlDriver::primaryIndex(const QString&) const
350{
351 return QSqlIndex();
352}
353
354
355/*!
356 Returns a QSqlRecord populated with the names of the fields in
357 table \a tableName. If no such table exists, an empty record is
358 returned. The default implementation returns an empty record.
359*/
360
361QSqlRecord QSqlDriver::record(const QString & /* tableName */) const
362{
363 return QSqlRecord();
364}
365
366/*!
367 Returns the \a identifier escaped according to the database rules.
368 \a identifier can either be a table name or field name, dependent
369 on \a type.
370
371 The default implementation does nothing.
372 \sa isIdentifierEscaped()
373 */
374QString QSqlDriver::escapeIdentifier(const QString &identifier, IdentifierType) const
375{
376 return identifier;
377}
378
379/*!
380 Returns whether \a identifier is escaped according to the database rules.
381 \a identifier can either be a table name or field name, dependent
382 on \a type.
383
384 Reimplement this function if you want to provide your own implementation in your
385 QSqlDriver subclass,
386
387 \sa stripDelimiters(), escapeIdentifier()
388 */
389bool QSqlDriver::isIdentifierEscaped(const QString &identifier, IdentifierType type) const
390{
391 Q_UNUSED(type);
392 return identifier.size() > 2
393 && identifier.startsWith(c: u'"') //left delimited
394 && identifier.endsWith(c: u'"'); //right delimited
395}
396
397/*!
398 Returns the \a identifier with the leading and trailing delimiters removed,
399 \a identifier can either be a table name or field name,
400 dependent on \a type. If \a identifier does not have leading
401 and trailing delimiter characters, \a identifier is returned without
402 modification.
403
404 Reimplement this function if you want to provide your own implementation in your
405 QSqlDriver subclass,
406
407 \since 4.5
408 \sa isIdentifierEscaped()
409 */
410QString QSqlDriver::stripDelimiters(const QString &identifier, IdentifierType type) const
411{
412 QString ret;
413 if (isIdentifierEscaped(identifier, type)) {
414 ret = identifier.mid(position: 1);
415 ret.chop(n: 1);
416 } else {
417 ret = identifier;
418 }
419 return ret;
420}
421
422/*!
423 Returns a SQL statement of type \a type for the table \a tableName
424 with the values from \a rec. If \a preparedStatement is true, the
425 string will contain placeholders instead of values.
426
427 The generated flag in each field of \a rec determines whether the
428 field is included in the generated statement.
429
430 This method can be used to manipulate tables without having to worry
431 about database-dependent SQL dialects. For non-prepared statements,
432 the values will be properly escaped.
433
434 In the WHERE statement, each non-null field of \a rec specifies a
435 filter condition of equality to the field value, or if prepared, a
436 placeholder. However, prepared or not, a null field specifies the
437 condition IS NULL and never introduces a placeholder. The
438 application must not attempt to bind data for the null field during
439 execution. The field must be set to some non-null value if a
440 placeholder is desired. Furthermore, since non-null fields specify
441 equality conditions and SQL NULL is not equal to anything, even
442 itself, it is generally not useful to bind a null to a placeholder.
443
444*/
445QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName,
446 const QSqlRecord &rec, bool preparedStatement) const
447{
448 const auto tableNameString = tableName.isEmpty() ? QString()
449 : prepareIdentifier(identifier: tableName, type: QSqlDriver::TableName, driver: this);
450 QString s;
451 s.reserve(asize: 128);
452 switch (type) {
453 case SelectStatement:
454 for (qsizetype i = 0; i < rec.count(); ++i) {
455 if (rec.isGenerated(i))
456 s.append(s: prepareIdentifier(identifier: rec.fieldName(i), type: QSqlDriver::FieldName, driver: this)).append(s: ", "_L1);
457 }
458 if (s.isEmpty())
459 return s;
460 s.chop(n: 2);
461 s = "SELECT "_L1 + s + " FROM "_L1 + tableNameString;
462 break;
463 case WhereStatement:
464 {
465 const QString tableNamePrefix = tableNameString.isEmpty()
466 ? QString() : tableNameString + u'.';
467 for (qsizetype i = 0; i < rec.count(); ++i) {
468 if (!rec.isGenerated(i))
469 continue;
470 s.append(s: s.isEmpty() ? "WHERE "_L1 : " AND "_L1);
471 s.append(s: tableNamePrefix);
472 s.append(s: prepareIdentifier(identifier: rec.fieldName(i), type: QSqlDriver::FieldName, driver: this));
473 if (rec.isNull(i))
474 s.append(s: " IS NULL"_L1);
475 else if (preparedStatement)
476 s.append(s: " = ?"_L1);
477 else
478 s.append(s: " = "_L1).append(s: formatValue(field: rec.field(i)));
479 }
480 break;
481 }
482 case UpdateStatement:
483 s = s + "UPDATE "_L1 + tableNameString + " SET "_L1;
484 for (qsizetype i = 0; i < rec.count(); ++i) {
485 if (!rec.isGenerated(i))
486 continue;
487 s.append(s: prepareIdentifier(identifier: rec.fieldName(i), type: QSqlDriver::FieldName, driver: this)).append(c: u'=');
488 if (preparedStatement)
489 s.append(c: u'?');
490 else
491 s.append(s: formatValue(field: rec.field(i)));
492 s.append(s: ", "_L1);
493 }
494 if (s.endsWith(s: ", "_L1))
495 s.chop(n: 2);
496 else
497 s.clear();
498 break;
499 case DeleteStatement:
500 s = s + "DELETE FROM "_L1 + tableNameString;
501 break;
502 case InsertStatement: {
503 s = s + "INSERT INTO "_L1 + tableNameString + " ("_L1;
504 QString vals;
505 for (qsizetype i = 0; i < rec.count(); ++i) {
506 if (!rec.isGenerated(i))
507 continue;
508 s.append(s: prepareIdentifier(identifier: rec.fieldName(i), type: QSqlDriver::FieldName, driver: this)).append(s: ", "_L1);
509 if (preparedStatement)
510 vals.append(c: u'?');
511 else
512 vals.append(s: formatValue(field: rec.field(i)));
513 vals.append(s: ", "_L1);
514 }
515 if (vals.isEmpty()) {
516 s.clear();
517 } else {
518 vals.chop(n: 2); // remove trailing comma
519 s[s.size() - 2] = u')';
520 s.append(s: "VALUES ("_L1).append(s: vals).append(c: u')');
521 }
522 break; }
523 }
524 return s;
525}
526
527/*!
528 Returns a string representation of the \a field value for the
529 database. This is used, for example, when constructing INSERT and
530 UPDATE statements.
531
532 The default implementation returns the value formatted as a string
533 according to the following rules:
534
535 \list
536
537 \li If \a field is character data, the value is returned enclosed
538 in single quotation marks, which is appropriate for many SQL
539 databases. Any embedded single-quote characters are escaped
540 (replaced with two single-quote characters). If \a trimStrings is
541 true (the default is false), all trailing whitespace is trimmed
542 from the field.
543
544 \li If \a field is date/time data, the value is formatted in ISO
545 format and enclosed in single quotation marks. If the date/time
546 data is invalid, "NULL" is returned.
547
548 \li If \a field is \l{QByteArray}{bytearray} data, and the
549 driver can edit binary fields, the value is formatted as a
550 hexadecimal string.
551
552 \li For any other field type, toString() is called on its value
553 and the result of this is returned.
554
555 \endlist
556
557 \sa QVariant::toString()
558
559*/
560QString QSqlDriver::formatValue(const QSqlField &field, bool trimStrings) const
561{
562 const auto nullTxt = "NULL"_L1;
563
564 QString r;
565 if (field.isNull())
566 r = nullTxt;
567 else {
568 switch (field.metaType().id()) {
569 case QMetaType::Int:
570 case QMetaType::UInt:
571 if (field.value().userType() == QMetaType::Bool)
572 r = field.value().toBool() ? "1"_L1 : "0"_L1;
573 else
574 r = field.value().toString();
575 break;
576#if QT_CONFIG(datestring)
577 case QMetaType::QDate:
578 if (field.value().toDate().isValid())
579 r = u'\'' + field.value().toDate().toString(format: Qt::ISODate) + u'\'';
580 else
581 r = nullTxt;
582 break;
583 case QMetaType::QTime:
584 if (field.value().toTime().isValid())
585 r = u'\'' + field.value().toTime().toString(f: Qt::ISODate) + u'\'';
586 else
587 r = nullTxt;
588 break;
589 case QMetaType::QDateTime:
590 if (field.value().toDateTime().isValid())
591 r = u'\'' + field.value().toDateTime().toString(format: Qt::ISODate) + u'\'';
592 else
593 r = nullTxt;
594 break;
595#endif
596 case QMetaType::QString:
597 case QMetaType::QChar:
598 {
599 QString result = field.value().toString();
600 if (trimStrings) {
601 int end = result.size();
602 while (end && result.at(i: end-1).isSpace()) /* skip white space from end */
603 end--;
604 result.truncate(pos: end);
605 }
606 /* escape the "'" character */
607 result.replace(c: u'\'', after: "''"_L1);
608 r = u'\'' + result + u'\'';
609 break;
610 }
611 case QMetaType::Bool:
612 r = QString::number(field.value().toBool());
613 break;
614 case QMetaType::QByteArray : {
615 if (hasFeature(f: BLOB)) {
616 const QByteArray ba = field.value().toByteArray();
617 r.reserve(asize: (ba.size() + 1) * 2);
618 r += u'\'';
619 for (const char c : ba) {
620 const uchar s = uchar(c);
621 r += QLatin1Char(QtMiscUtils::toHexLower(value: s >> 4));
622 r += QLatin1Char(QtMiscUtils::toHexLower(value: s & 0x0f));
623 }
624 r += u'\'';
625 break;
626 }
627 }
628 Q_FALLTHROUGH();
629 default:
630 r = field.value().toString();
631 break;
632 }
633 }
634 return r;
635}
636
637/*!
638 Returns the low-level database handle wrapped in a QVariant or an
639 invalid variant if there is no handle.
640
641 \warning Use this with uttermost care and only if you know what you're doing.
642
643 \warning The handle returned here can become a stale pointer if the connection
644 is modified (for example, if you close the connection).
645
646 \warning The handle can be NULL if the connection is not open yet.
647
648 The handle returned here is database-dependent, you should query the type
649 name of the variant before accessing it.
650
651 This example retrieves the handle for a connection to sqlite:
652
653 \snippet code/src_sql_kernel_qsqldriver.cpp 0
654
655 This snippet returns the handle for PostgreSQL or MySQL:
656
657 \snippet code/src_sql_kernel_qsqldriver.cpp 1
658
659 \sa QSqlResult::handle()
660*/
661QVariant QSqlDriver::handle() const
662{
663 return QVariant();
664}
665
666/*!
667 This function is called to subscribe to event notifications from the database.
668 \a name identifies the event notification.
669
670 If successful, return true, otherwise return false.
671
672 The database must be open when this function is called. When the database is closed
673 by calling close() all subscribed event notifications are automatically unsubscribed.
674 Note that calling open() on an already open database may implicitly cause close() to
675 be called, which will cause the driver to unsubscribe from all event notifications.
676
677 When an event notification identified by \a name is posted by the database the
678 notification() signal is emitted.
679
680 Reimplement this function if you want to provide event notification support in your
681 own QSqlDriver subclass,
682
683 \since 4.4
684 \sa unsubscribeFromNotification(), subscribedToNotifications(), QSqlDriver::hasFeature()
685*/
686bool QSqlDriver::subscribeToNotification(const QString &name)
687{
688 Q_UNUSED(name);
689 return false;
690}
691
692/*!
693 This function is called to unsubscribe from event notifications from the database.
694 \a name identifies the event notification.
695
696 If successful, return true, otherwise return false.
697
698 The database must be open when this function is called. All subscribed event
699 notifications are automatically unsubscribed from when the close() function is called.
700
701 After calling \e this function the notification() signal will no longer be emitted
702 when an event notification identified by \a name is posted by the database.
703
704 Reimplement this function if you want to provide event notification support in your
705 own QSqlDriver subclass,
706
707 \since 4.4
708 \sa subscribeToNotification(), subscribedToNotifications()
709*/
710bool QSqlDriver::unsubscribeFromNotification(const QString &name)
711{
712 Q_UNUSED(name);
713 return false;
714}
715
716/*!
717 Returns a list of the names of the event notifications that are currently subscribed to.
718
719 Reimplement this function if you want to provide event notification support in your
720 own QSqlDriver subclass,
721
722 \since 4.4
723 \sa subscribeToNotification(), unsubscribeFromNotification()
724*/
725QStringList QSqlDriver::subscribedToNotifications() const
726{
727 return QStringList();
728}
729
730/*!
731 \since 4.6
732
733 Sets the default numerical precision policy used by queries created
734 by this driver to \a precisionPolicy.
735
736 Note: Setting the default precision policy to \a precisionPolicy
737 doesn't affect any currently active queries.
738
739 \sa QSql::NumericalPrecisionPolicy, numericalPrecisionPolicy(),
740 QSqlQuery::setNumericalPrecisionPolicy(), QSqlQuery::numericalPrecisionPolicy()
741*/
742void QSqlDriver::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy)
743{
744 Q_D(QSqlDriver);
745 d->precisionPolicy = precisionPolicy;
746}
747
748/*!
749 \since 4.6
750
751 Returns the current default precision policy for the database connection.
752
753 \sa QSql::NumericalPrecisionPolicy, setNumericalPrecisionPolicy(),
754 QSqlQuery::numericalPrecisionPolicy(), QSqlQuery::setNumericalPrecisionPolicy()
755*/
756QSql::NumericalPrecisionPolicy QSqlDriver::numericalPrecisionPolicy() const
757{
758 Q_D(const QSqlDriver);
759 return d->precisionPolicy;
760}
761
762/*!
763 \since 5.4
764 \internal
765
766 Returns the current DBMS type for the database connection.
767*/
768QSqlDriver::DbmsType QSqlDriver::dbmsType() const
769{
770 Q_D(const QSqlDriver);
771 return d->dbmsType;
772}
773
774/*!
775 \since 5.0
776 \internal
777
778 Tries to cancel the running query, if the underlying driver has the
779 capability to cancel queries. Returns \c true on success, otherwise false.
780
781 This function can be called from a different thread.
782
783 If you use this function as a slot, you need to use a Qt::DirectConnection
784 from a different thread.
785
786 Reimplement this function to support canceling running queries in
787 your own QSqlDriver subclass. It must be implemented in a thread-safe
788 manner.
789
790 \sa QSqlDriver::hasFeature()
791*/
792bool QSqlDriver::cancelQuery()
793{
794 return false;
795}
796
797/*!
798 \since 6.0
799
800 Returns the maximum length for the identifier \a type according to the database settings. Returns
801 INT_MAX by default if the is no maximum for the database.
802*/
803
804int QSqlDriver::maximumIdentifierLength(QSqlDriver::IdentifierType type) const
805{
806 Q_UNUSED(type);
807 return INT_MAX;
808}
809
810QT_END_NAMESPACE
811
812#include "moc_qsqldriver.cpp"
813

source code of qtbase/src/sql/kernel/qsqldriver.cpp