24#include "KDbConnection.h"
25#include "KDbConnectionData.h"
27#include "KDbDateTime.h"
28#include "KDbDriverBehavior.h"
29#include "KDbDriverManager.h"
30#include "KDbDriver_p.h"
31#include "KDbLookupFieldSchema.h"
32#include "KDbMessageHandler.h"
33#include "KDbNativeStatementBuilder.h"
34#include "KDbQuerySchema.h"
35#include "KDbRecordData.h"
36#include "KDbSqlResult.h"
37#include "KDbTableOrQuerySchema.h"
38#include "KDbVersionInfo.h"
41#include "transliteration/transliteration_table.h"
50#include <QProgressDialog>
52#include <QApplication>
62class ConnectionTestDialog;
64class ConnectionTestThread :
public QThread
68 ConnectionTestThread(ConnectionTestDialog *dlg,
const KDbConnectionData& connData);
75 ConnectionTestDialog* m_dlg;
79 Q_DISABLE_COPY(ConnectionTestThread)
88 ~ConnectionTestDialog()
override;
97 void accept()
override;
98 void reject()
override;
114 Q_DISABLE_COPY(ConnectionTestDialog)
117ConnectionTestThread::ConnectionTestThread(ConnectionTestDialog* dlg,
const KDbConnectionData& connData)
118 : m_dlg(dlg), m_connData(connData)
125 m_driver = manager.
driver(m_connData.driverId());
137 emit error(msg, details);
140void ConnectionTestThread::run()
146 if (conn.isNull() || m_driver->result().
isError()) {
147 emitError(*m_driver);
150 if (!conn->connect() || conn->result().isError()) {
157 if (!conn->useTemporaryDatabaseIfNeeded(&tmpDbName)) {
162 if (!conn->closeDatabase()) {
172 , m_thread(new ConnectionTestThread(this, data))
174 , m_msgHandler(msgHandler)
177 , m_stopWaiting(false)
179 setWindowTitle(tr(
"Test Connection",
"Dialog's title: testing database connection"));
180 setLabelText(tr(
"Testing connection to \"%1\" database server...")
184 connect(&m_timer, SIGNAL(timeout()),
this, SLOT(slotTimeout()));
186 resize(250, height());
189ConnectionTestDialog::~ConnectionTestDialog()
191 if (m_thread->isRunning()) {
192 m_thread->terminate();
194 m_thread->deleteLater();
197int ConnectionTestDialog::exec()
208void ConnectionTestDialog::slotTimeout()
212 bool notResponding =
false;
213 if (m_elapsedTime >= 1000*5) {
214 m_stopWaiting =
true;
215 notResponding =
true;
227 message =
tr(
"Test connection to \"%1\" database server failed.")
233 type = KDbMessageHandler::Sorry;
235 }
else if (notResponding) {
238 message =
tr(
"Test connection to \"%1\" database server failed. The server is not responding.")
240 type = KDbMessageHandler::Sorry;
244 message =
tr(
"Test connection to \"%1\" database server established successfully.")
246 type = KDbMessageHandler::Information;
257void ConnectionTestDialog::error(
const QString& msg,
const QString& details)
261 m_stopWaiting =
true;
266 kdbDebug() <<
"Error:" << msg << details;
270void ConnectionTestDialog::accept()
276void ConnectionTestDialog::reject()
282void ConnectionTestDialog::finish()
284 if (m_thread->isRunning()) {
285 m_thread->terminate();
294inline static unsigned char hexDigitToInt(
char digit)
296 if (digit >=
'0' && digit <=
'9') {
299 if (digit >=
'a' && digit <=
'f') {
300 return digit -
'a' + 10;
302 if (digit >=
'A' && digit <=
'F') {
303 return digit -
'A' + 10;
311inline static bool hexToByteArrayInternal(
const char* data,
int length,
QByteArray *array)
313 Q_ASSERT(length >= 0);
314 Q_ASSERT(data || length == 0);
315 array->
resize(length / 2 + length % 2);
316 for(
int i = 0; length > 0; --length, ++data, ++i) {
317 unsigned char d1 = hexDigitToInt(data[0]);
319 if (i == 0 && (length % 2) == 1) {
326 d2 = hexDigitToInt(data[0]);
328 if (d1 == 0xFF || d2 == 0xFF) {
331 (*array)[i] = (d1 << 4) + d2;
339 KDB_VERSION_MAJOR, KDB_VERSION_MINOR, KDB_VERSION_PATCH);
393 const QString &autoIncrementFieldName,
394 const QString &tableName, quint64 *recordId)
397 return std::numeric_limits<quint64>::max();
399 const quint64 foundRecordId = result->lastInsertRecordId();
401 *recordId = foundRecordId;
404 foundRecordId, autoIncrementFieldName, tableName);
408 const QString &autoIncrementFieldName,
416 if (recordId == std::numeric_limits<quint64>::max()
419 + escapeIdentifier(autoIncrementFieldName)
420 +
" FROM " + escapeIdentifier(tableName)
422 +
'=' + KDbEscapedString::number(recordId), &rdata))
424 return std::numeric_limits<quint64>::max();
426 return rdata[0].toULongLong();
456 list = tlist.
value(tg);
457 name_list = nlist.
value(tg);
458 str_list = slist.
value(tg);
464 nlist[ tg ] = name_list;
465 slist[ tg ] = str_list;
473 def_tlist[ KDbField::DateTimeGroup ] = KDbField::Date;
483Q_GLOBAL_STATIC(TypeCache, KDb_typeCache)
487 return KDb_typeCache->tlist.value(typeGroup);
492 return KDb_typeCache->nlist.
value(typeGroup);
497 return KDb_typeCache->slist.
value(typeGroup);
502 return (typeGroup <= KDbField::LastTypeGroup) ? KDb_typeCache->def_tlist.value(typeGroup) :
KDbField::InvalidType;
508 kdbWarning() <<
"Missing 'msg' parameter";
512 kdbWarning() <<
"Missing 'details' parameter";
515 const KDbResult result(resultable.result());
528 *details +=
QLatin1String(
"<p><b>") + kdb::tr(
"Message from server:")
531 *details +=
QLatin1String(
"<p><b>") + kdb::tr(
"SQL statement:")
533 int serverErrorCode = 0;
543 || serverErrorCode != 0)
546 *details += (
QLatin1String(
"<p><b>") + kdb::tr(
"Server result code:")
548 if (!serverResultName.
isEmpty()) {
553 if (!serverResultName.
isEmpty()) {
554 *details += (
QLatin1String(
"<p><b>") + kdb::tr(
"Server result:")
573 kdbWarning() <<
"Missing 'info' parameter";
583 KDbEscapedString(
"SELECT o_id FROM kexi__objects WHERE o_name=%1 AND o_type=%2")
595 ConnectionTestDialog dlg(data, msgHandler, parent);
596 const int result = dlg.exec();
607 if (!tableName || !fieldName) {
616 if (
id <= 0 ||
id ==
int(
string.length() - 1))
618 *tableName =
string.
left(
id);
619 *fieldName =
string.
mid(
id + 1);
629inline static QString numberToString(
double value,
int decimalPlaces,
const QLocale *locale)
633 if (decimalPlaces == 0) {
634 result = locale ? locale->
toString(qlonglong(value))
638 result = locale ? locale->
toString(value,
'f', realDecimalPlaces)
640 if (decimalPlaces < 0) {
641 int i = result.
length() - 1;
645 if (result[i].isDigit()) {
656 return ::numberToString(value, decimalPlaces,
nullptr);
662 return ::numberToString(value, decimalPlaces, &defaultLocale);
667 return ::numberToString(value, decimalPlaces, &locale);
680 if (typeGroup <
int(KDbField::InvalidGroup) || typeGroup >
int(KDbField::LastTypeGroup)) {
681 return KDbField::InvalidGroup;
690 const int intType = value.
toInt(&ok);
692 kdbWarning() <<
"Could not convert value" << value <<
"to field type";
696 kdbWarning() <<
"Invalid field type" << intType;
704struct KDb_BuiltinFieldProperties {
705 KDb_BuiltinFieldProperties() {
706#define ADD(name) set.insert(name)
710 ADD(
"autoIncrement");
719 ADD(
"maxLengthIsDefault");
723 ADD(
"visibleDecimalPlaces");
731Q_GLOBAL_STATIC(KDb_BuiltinFieldProperties, KDb_builtinFieldProperties)
736 return KDb_builtinFieldProperties->set.contains(propertyName);
744 if (!visibleColumns.
isEmpty()) {
745 return visibleColumns.
first();
752 for(
int column : visibleColumns) {
753 variantList.
append(column);
769 values->
insert(
"rowSourceValues",
772 values->
insert(
"visibleColumn", visibleColumnValue(lookup));
776 for(
const QVariant& variant : columnWidths) {
777 variantList.
append(variant);
780 values->
insert(
"columnWidths", lookup ? variantList :
QVariant());
796 values->
insert(
"primaryKey", constraints.
testFlag(KDbField::PrimaryKey));
797 values->
insert(
"indexed", constraints.
testFlag(KDbField::Indexed));
799 && constraints.
testFlag(KDbField::AutoInc));
801 values->
insert(
"notNull", constraints.
testFlag(KDbField::NotNull));
840 if (!setIntToFieldType(field, *it))
844#define SET_BOOLEAN_FLAG(flag, value) { \
845 constraints |= KDbField::flag; \
847 constraints ^= KDbField::flag; \
852 if ((it = values.
find(
"primaryKey")) != values.
constEnd())
853 SET_BOOLEAN_FLAG(PrimaryKey, (*it).toBool());
855 SET_BOOLEAN_FLAG(Indexed, (*it).toBool());
856 if ((it = values.
find(
"autoIncrement")) != values.
constEnd()
858 SET_BOOLEAN_FLAG(AutoInc, (*it).toBool());
860 SET_BOOLEAN_FLAG(Unique, (*it).toBool());
862 SET_BOOLEAN_FLAG(NotNull, (*it).toBool());
863 if ((it = values.
find(
"allowEmpty")) != values.
constEnd())
864 SET_BOOLEAN_FLAG(NotEmpty, !(*it).toBool());
868 if ((it = values.
find(
"unsigned")) != values.
constEnd()) {
869 options |= KDbField::Unsigned;
871 options ^= KDbField::Unsigned;
876 field->
setName((*it).toString());
879 if ((it = values.
find(
"description")) != values.
constEnd())
881 if ((it = values.
find(
"maxLength")) != values.
constEnd())
882 field->
setMaxLength((*it).isNull() ? 0 : (*it).toInt(&ok));
885 if ((it = values.
find(
"maxLengthIsDefault")) != values.
constEnd()
890 if ((it = values.
find(
"precision")) != values.
constEnd())
891 field->
setPrecision((*it).isNull() ? 0 : (*it).toInt(&ok));
894 if ((it = values.
find(
"defaultValue")) != values.
constEnd())
898 if ((it = values.
find(
"defaultWidth")) != values.
constEnd())
899 field.setDefaultWidth((*it).isNull() ? 0 : (*it).toInt(&ok));
905 if ((it = values.
find(
"visibleDecimalPlaces")) != values.
constEnd()
911 if (field->
table() && containsLookupFieldSchemaProperties(values)) {
920 createdLookup.
take();
928#undef SET_BOOLEAN_FLAG
932struct KDb_ExtendedProperties {
933 KDb_ExtendedProperties() {
934#define ADD(name) set.insert( name )
935 ADD(
"visibledecimalplaces");
937 ADD(
"rowsourcetype");
938 ADD(
"rowsourcevalues");
940 ADD(
"visiblecolumn");
942 ADD(
"showcolumnheaders");
945 ADD(
"displaywidget");
952Q_GLOBAL_STATIC(KDb_ExtendedProperties, KDb_extendedProperties)
956 return KDb_extendedProperties->set.contains(
QByteArray(propertyName).toLower());
960struct KDb_LookupFieldSchemaProperties {
961 KDb_LookupFieldSchemaProperties() {
967 set.
insert(it.key().toLower());
974Q_GLOBAL_STATIC(KDb_LookupFieldSchemaProperties, KDb_lookupFieldSchemaProperties)
978 return KDb_lookupFieldSchemaProperties->set.contains(propertyName.toLower());
986#define SET_BOOLEAN_FLAG(flag, value) { \
987 constraints |= KDbField::flag; \
989 constraints ^= KDbField::flag; \
990 field->setConstraints( constraints ); \
993#define GET_INT(method) { \
994 const int ival = value.toInt(&ok); \
997 field->method( ival ); \
1007 if (
"visibleDecimalPlaces" == propertyName
1009 GET_INT(setVisibleDecimalPlaces);
1012 if (!field->
table()) {
1013 kdbWarning() <<
"Could not set" << propertyName <<
"property - no table assigned for field";
1016 const bool createLookup = !lookup;
1029 if (
"type" == propertyName)
1030 return setIntToFieldType(field, value);
1033 if (
"primaryKey" == propertyName)
1034 SET_BOOLEAN_FLAG(PrimaryKey, value.
toBool());
1035 if (
"indexed" == propertyName)
1036 SET_BOOLEAN_FLAG(Indexed, value.
toBool());
1037 if (
"autoIncrement" == propertyName
1039 SET_BOOLEAN_FLAG(AutoInc, value.
toBool());
1040 if (
"unique" == propertyName)
1041 SET_BOOLEAN_FLAG(Unique, value.
toBool());
1042 if (
"notNull" == propertyName)
1043 SET_BOOLEAN_FLAG(NotNull, value.
toBool());
1044 if (
"allowEmpty" == propertyName)
1045 SET_BOOLEAN_FLAG(NotEmpty, !value.
toBool());
1048 if (
"unsigned" == propertyName) {
1049 options |= KDbField::Unsigned;
1051 options ^= KDbField::Unsigned;
1056 if (
"name" == propertyName) {
1062 if (
"caption" == propertyName) {
1066 if (
"description" == propertyName) {
1070 if (
"maxLength" == propertyName)
1071 GET_INT(setMaxLength);
1072 if (
"maxLengthIsDefault" == propertyName) {
1075 if (
"precision" == propertyName)
1076 GET_INT(setPrecision);
1077 if (
"defaultValue" == propertyName) {
1084 if (
"defaultWidth" == propertyName)
1085 GET_INT(setDefaultWidth);
1091 kdbWarning() <<
"Field property" << propertyName <<
"not found!";
1093#undef SET_BOOLEAN_FLAG
1100 if (valueType.
isEmpty() || valueType !=
"number") {
1106 int val = text.
toInt(ok);
1113 if (valueType !=
"string") {
1135 if (valueType ==
"string") {
1138 else if (valueType ==
"cstring") {
1141 else if (valueType ==
"number") {
1148 const int val = text.
toInt(&_ok);
1151 const qint64 valLong = text.
toLongLong(&_ok);
1156 else if (valueType ==
"bool") {
1162 kdbWarning() <<
"Unknown property type" << valueType;
1170 const QString& elementName,
int value)
1172 if (!doc || !parentEl || elementName.
isEmpty()) {
1184 const QString& elementName,
bool value)
1186 if (!doc || !parentEl || elementName.
isEmpty()) {
1199struct KDb_EmptyValueForFieldTypeCache {
1200 KDb_EmptyValueForFieldTypeCache()
1201 : values(int(
KDbField::LastType) + 1) {
1202#define ADD(t, value) values.insert(t, value);
1220Q_GLOBAL_STATIC(KDb_EmptyValueForFieldTypeCache, KDb_emptyValueForFieldTypeCache)
1224 const QVariant val(KDb_emptyValueForFieldTypeCache->values.at(
1229 if (type == KDbField::Date)
1231 if (type == KDbField::DateTime)
1233 if (type == KDbField::Time)
1241struct KDb_NotEmptyValueForFieldTypeCache {
1242 KDb_NotEmptyValueForFieldTypeCache()
1243 : values(int(
KDbField::LastType) + 1) {
1244#define ADD(t, value) values.insert(t, value);
1247 if (i == KDbField::Date || i == KDbField::DateTime || i == KDbField::Time)
1260 QPixmap pm(SmallIcon(
"document-new"));
1261 pm.save(&buffer,
"PNG");
1273Q_GLOBAL_STATIC(KDb_NotEmptyValueForFieldTypeCache, KDb_notEmptyValueForFieldTypeCache)
1277 const QVariant val(KDb_notEmptyValueForFieldTypeCache->values.at(
1282 if (type == KDbField::Date)
1284 if (type == KDbField::DateTime)
1286 if (type == KDbField::Time)
1295inline static int estimatedNewLength(
const T &
string,
bool addQuotes)
1297 if (
string.length() < 10)
1298 return string.length() * 2 + (addQuotes ? 2 : 0);
1299 return string.length() * 3 / 2;
1304template<
typename T,
typename Latin1StringType,
typename Latin1CharType,
typename CharType>
1305inline static T escapeIdentifier(
const T&
string,
bool addQuotes)
1307 const Latin1CharType quote(
'"');
1309 Latin1StringType escapedQuote(
"\"\"");
1311 newString.reserve(estimatedNewLength(
string, addQuotes));
1313 newString.append(quote);
1315 for (
int i = 0; i <
string.length(); i++) {
1316 const CharType c =
string.at(i);
1318 newString.append(escapedQuote);
1320 newString.append(c);
1323 newString.append(quote);
1325 newString.squeeze();
1329static bool shouldAddQuotesToIdentifier(
const QByteArray&
string)
1336 return ::escapeIdentifier<QString, QLatin1String, QLatin1Char, QChar>(
1337 string, shouldAddQuotesToIdentifier(
string.toLatin1()));
1342 return ::escapeIdentifier<QByteArray, QByteArray, char, char>(
1343 string, shouldAddQuotesToIdentifier(
string));
1348 return ::escapeIdentifier<QString, QLatin1String, QLatin1Char, QChar>(
string,
true);
1353 return ::escapeIdentifier<QByteArray, QByteArray, char, char>(
string,
true);
1362 newString.
reserve(estimatedNewLength(
string,
true));
1363 for (
int i = 0; i <
string.length(); i++) {
1364 const QChar c =
string.at(i);
1365 const ushort unicode = c.
unicode();
1366 if (unicode == quote)
1368 else if (unicode ==
'\t')
1370 else if (unicode ==
'\\')
1372 else if (unicode ==
'\n')
1374 else if (unicode ==
'\r')
1376 else if (unicode ==
'\0')
1396const int CODE_POINT_DIGITS = std::numeric_limits<int>::max();
1398const int MAX_CODE_POINT_VALUE = 0x10FFFF;
1409static int handleHex(
QString *result,
int *from,
int stringLen,
int *errorPosition,
int digits)
1412 for (
int i=0; i<digits; ++i) {
1413 if ((*from + 1) >= stringLen) {
1414 if (errorPosition) {
1415 *errorPosition = *from;
1420 if (digits == CODE_POINT_DIGITS && (*result)[*from] ==
QLatin1Char(
'}')) {
1423 if (errorPosition) {
1424 *errorPosition = *from;
1430 const unsigned char d = hexDigitToInt((*result)[*from].toLatin1());
1432 if (errorPosition) {
1433 *errorPosition = *from;
1437 digit = (digit << 4) + d;
1438 if (digits == CODE_POINT_DIGITS) {
1439 if (digit > MAX_CODE_POINT_VALUE) {
1440 if (errorPosition) {
1441 *errorPosition = *from;
1453static bool handleXhh(
QString *result,
int *from,
int to,
int stringLen,
int *errorPosition)
1455 const int intDigit = handleHex(result, from, stringLen, errorPosition, 2);
1456 if (intDigit == -1) {
1459 (*result)[to] =
QChar(
static_cast<unsigned char>(intDigit), 0);
1466static bool handleUxxxx(
QString *result,
int *from,
int to,
int stringLen,
int *errorPosition)
1468 const int intDigit = handleHex(result, from, stringLen, errorPosition, 4);
1469 if (intDigit == -1) {
1472 (*result)[to] =
QChar(
static_cast<unsigned short>(intDigit));
1479static bool handleUcodePoint(
QString *result,
int *from,
int to,
int stringLen,
int *errorPosition)
1481 const int intDigit = handleHex(result, from, stringLen, errorPosition, CODE_POINT_DIGITS);
1482 if (intDigit == -1) {
1485 (*result)[to] =
QChar(intDigit);
1492static bool handleEscape(
QString *result,
int *from,
int *to,
int stringLen,
int *errorPosition)
1494 const QCharRef c2 = (*result)[*from];
1496 if (!handleXhh(result, from, *to, stringLen, errorPosition)) {
1500 if ((*from + 1) >= stringLen) {
1501 if (errorPosition) {
1502 *errorPosition = *from;
1507 const QCharRef c3 = (*result)[*from];
1509 if (!handleUcodePoint(result, from, *to, stringLen, errorPosition)) {
1514 if (!handleUxxxx(result, from, *to, stringLen, errorPosition)) {
1518#define _RULE(in, out) \
1519 } else if (c2 == QLatin1Char(in)) { \
1520 (*result)[*to] = QLatin1Char(out);
1521 _RULE(
'0',
'\0') _RULE('b', '\b') _RULE('f', '\f') _RULE('n', '\n')
1522 _RULE('r', '\r') _RULE('t', '\t') _RULE('v', '\v')
1525 (*result)[*to] = c2;
1532 if (quote !=
'\'' && quote !=
'\"') {
1533 if (errorPosition) {
1539 if (
string.isEmpty()
1540 || (!
string.contains(
QLatin1Char(
'\\')) && !
string.contains(quoteChar)))
1542 if (errorPosition) {
1543 *errorPosition = -1;
1548 const int stringLen =
string.length();
1551 bool doubleQuoteExpected =
false;
1552 while (from < stringLen) {
1553 const QCharRef c = result[from];
1554 if (doubleQuoteExpected) {
1555 if (c == quoteChar) {
1557 doubleQuoteExpected =
false;
1560 if (errorPosition) {
1561 *errorPosition = from - 1;
1565 }
else if (c == quoteChar) {
1566 doubleQuoteExpected =
true;
1570 if ((from + 1) >= stringLen) {
1574 if (!handleEscape(&result, &from, &to, stringLen, errorPosition)) {
1578 result[to] = result[from];
1583 if (doubleQuoteExpected) {
1584 if (errorPosition) {
1585 *errorPosition = from - 1;
1589 if (errorPosition) {
1590 *errorPosition = -1;
1597inline static char intToHexDigit(
unsigned char val)
1599 return (val < 10) ? (
'0' + val) : (
'A' + (val - 10));
1604 const int size = array.
size();
1605 if (size == 0 && type == BLOBEscapingType::ZeroXHex)
1607 int escaped_length = size * 2;
1608 if (type == BLOBEscapingType::ZeroXHex || type == BLOBEscapingType::Octal)
1609 escaped_length += 2;
1610 else if (type == BLOBEscapingType::XHex)
1611 escaped_length += 3;
1612 else if (type == BLOBEscapingType::ByteaHex)
1613 escaped_length += (4 + 8);
1617 if (str.
capacity() < escaped_length) {
1618 kdbWarning() <<
"Not enough memory (cannot allocate" << escaped_length <<
"characters)";
1621 if (type == BLOBEscapingType::XHex)
1623 else if (type == BLOBEscapingType::ZeroXHex)
1625 else if (type == BLOBEscapingType::Octal)
1627 else if (type == BLOBEscapingType::ByteaHex)
1630 if (type == BLOBEscapingType::Octal) {
1634 for (
int i = 0; i < size; i++) {
1635 const unsigned char val = array[i];
1636 if (val < 32 || val >= 127 || val == 39 || val == 92) {
1647 for (
int i = 0; i < size; i++) {
1648 const unsigned char val = array[i];
1653 if (type == BLOBEscapingType::XHex || type == BLOBEscapingType::Octal) {
1655 }
else if (type == BLOBEscapingType::ByteaHex) {
1669 length = qstrlen(data);
1671 for (
int pass = 0; pass < 2; pass++) {
1673 const char* s = data;
1674 const char*
end = s + length;
1680 for (
int input = 0; s <
end; output++) {
1682 if (s[0] ==
'\\' && (s + 1) < end) {
1686 array[output] =
'\'';
1688 }
else if (s[1] ==
'\\') {
1690 array[output] =
'\\';
1692 }
else if ((input + 3) < length) {
1694 array[output] = char((
int(s[1] -
'0') * 8 +
int(s[2] -
'0')) * 8 +
int(s[3] -
'0'));
1697 kdbWarning() <<
"Missing octal value after backslash";
1702 array[output] = s[0];
1714 length = qstrlen(data);
1716 if (length < 3 || data[0] !=
'X' || data[1] !=
'\'' || data[length-1] !=
'\'') {
1725 if (!hexToByteArrayInternal(data, length, &array)) {
1743 length = qstrlen(data);
1745 if (length < 3 || data[0] !=
'0' || data[1] !=
'x') {
1754 if (!hexToByteArrayInternal(data, length, &array)) {
1769 foreach (
const QString &item, list) {
1770 int val = item.
toInt(ok);
1794 while (++it != end) {
1822 bool quoted =
false;
1823 for (
int p = 0; p < data.
length(); p++) {
1827 }
else if (data[p].unicode() ==
QLatin1Char(
'\\')) {
1829 }
else if (data[p].unicode() ==
QLatin1Char(
',')) {
1872 const int len = s.
length();
1874 ba.
resize(len / 2 + len % 2);
1875 for (
int i = 0; i < (len - 1); i += 2) {
1877 int c = s.midRef(i, 2).
toInt(&_ok, 16);
1881 kdbWarning() <<
"Error in digit" << i;
1897 if (!result.convert(type)) {
1913 Signedness signedness)
1915 if (!minValue || !maxValue) {
1921 *minValue = signedness ==
KDb::Signed ? -0x80 : 0;
1922 *maxValue = signedness ==
KDb::Signed ? 0x7F : 0xFF;
1925 *minValue = signedness ==
KDb::Signed ? -0x8000 : 0;
1926 *maxValue = signedness ==
KDb::Signed ? 0x7FFF : 0xFFFF;
1931 *minValue = signedness ==
KDb::Signed ? qlonglong(-0x07FFFFFFF) : qlonglong(0);
1932 *maxValue = signedness ==
KDb::Signed ? qlonglong(0x07FFFFFFF) : qlonglong(0x0FFFFFFFF);
1954 return KDbField::tr(
"Number");
1957 return KDbField::tr(
"Image");
1973template <
typename T>
1975 qlonglong minValue, qlonglong maxValue,
bool *ok)
1979 *
ok = minValue <= v && v <= maxValue;
1988 bool *thisOk =
ok ?
ok : &tempOk;
2005 qlonglong minValue, maxValue;
2013 :
convert(&
QString::toShort, data, length, minValue, maxValue, thisOk);
2017 :
convert(&
QString::toInt, data, length, minValue, maxValue, thisOk);
2021 qFatal(
"Unsupported integer type %d", type);
2029 *thisOk = length >= 0;
2046 foreach (
const QString& path, qApp->libraryPaths()) {
2048 if (
QDir(dir).exists() &&
QDir(dir).isReadable()) {
2062 for (
int i = 0; i < 10; ++i) {
2068 }
else if (res ==
false) {
2078 kdbWarning() <<
"Could not find program \"sqlite3\"";
2091 if (!fi.isReadable()) {
2092 kdbWarning() <<
"No readable input file" << fi.absoluteFilePath();
2098 kdbWarning() <<
"Could not remove output file" << fo.absoluteFilePath();
2102 kdbDebug() << inputFileName << fi.absoluteDir().path() << fo.absoluteFilePath();
2107 kdbWarning() <<
"Failed to start program" << sqlite_app;
2112 kdbWarning() <<
"Failed to send \".read\" command to program" << sqlite_app;
2117 kdbWarning() <<
"Failed to finish program" << sqlite_app;
2128 const int sLength = s.
length();
2129 for (i = 0; i < sLength; i++) {
2130 const char c = s.
at(i).
toLower().toLatin1();
2131 if (c == 0 || !(c ==
'_' || (c >=
'a' && c <=
'z') || (i > 0 && c >=
'0' && c <=
'9')))
2134 return i > 0 && i == sLength;
2140 const int sLength = s.
length();
2141 for (i = 0; i < sLength; i++) {
2142 const char c = s.
at(i);
2143 if (c == 0 || !(c ==
'_' || (c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z') || (i > 0 && c >=
'0' && c <=
'9'))) {
2147 return i > 0 && i == sLength;
2152 if (c.
unicode() >= TRANSLITERATION_TABLE_SIZE)
2154 const char *
const s = transliteration_table[c.
unicode()];
2167 const QChar c =
id[0];
2170 bool wasUnderscore =
false;
2172 if (ch >=
'0' && ch <=
'9') {
2175 add = charToIdentifier(c);
2180 const int idLength =
id.length();
2181 for (
int i = 1; i < idLength; i++) {
2182 add = charToIdentifier(
id.at(i));
2193 return QLatin1String(
"<p>") + kdb::tr(
"Value of \"%1\" field must be an identifier.")
2203 return valueToSqlInternal(
nullptr, ftype, v);
2208 QByteArray result(QByteArrayLiteral(
"<INVALID_DATE>"));
2211 if (date.isValid() || allowInvalidKDbDate) {
2212 result = date.toString();
2216 if (date.isValid()) {
2230 QByteArray result(QByteArrayLiteral(
"<INVALID_TIME>"));
2233 if (time.isValid() || allowInvalidKDbTime) {
2234 result = time.toString();
2238 if (time.isValid()) {
2239 if (time.msec() == 0) {
2242 result = KDbUtils::toISODateStringWithMs(time).
toLatin1();
2254static QByteArray dateTimeToSqlInternal(
const QVariant& v,
char separator,
bool allowInvalidKDbDateTime)
2256 QByteArray result(QByteArrayLiteral(
"<INVALID_DATETIME>"));
2259 if (dateTime.isValid() || allowInvalidKDbDateTime) {
2260 result = dateTime.toString();
2264 if (dateTime.isValid()) {
2265 result = dateTime.date().toString(
Qt::ISODate).toLatin1() + separator;
2266 const QTime time(dateTime.time());
2267 if (time.msec() == 0) {
2270 result += KDbUtils::toISODateStringWithMs(time).
toLatin1();
2306static KDb::DebugGUIHandler s_debugGUIHandler =
nullptr;
2308void KDb::setDebugGUIHandler(KDb::DebugGUIHandler handler)
2310 s_debugGUIHandler = handler;
2313void KDb::debugGUI(
const QString& text)
2315 if (s_debugGUIHandler)
2316 s_debugGUIHandler(text);
2319static KDb::AlterTableActionDebugGUIHandler s_alterTableActionDebugHandler =
nullptr;
2321void KDb::setAlterTableActionDebugHandler(KDb::AlterTableActionDebugGUIHandler handler)
2323 s_alterTableActionDebugHandler = handler;
2326void KDb::alterTableActionDebugGUI(
const QString& text,
int nestingLevel)
2328 if (s_alterTableActionDebugHandler)
2329 s_alterTableActionDebugHandler(text, nestingLevel);
Database specific connection data, e.g. host, port.
QString toUserVisibleString(UserVisibleStringOptions options=UserVisibleStringOption::AddUser) const
Provides database connection, allowing queries and data modification.
virtual KDbEscapedString escapeString(const QString &str) const
bool executeSql(const KDbEscapedString &sql)
Executes a new native (raw, backend-specific) SQL query.
virtual QString escapeIdentifier(const QString &id) const
Identifier escaping function in the associated KDbDriver.
KDbDriver * driver() const
tristate querySingleRecord(const KDbEscapedString &sql, KDbRecordData *data, QueryRecordOptions options=QueryRecordOption::Default)
tristate querySingleNumber(const KDbEscapedString &sql, int *number, int column=0, QueryRecordOptions options=QueryRecordOption::Default)
tristate containsTable(const QString &tableName)
Generic date/time constant.
Detailed definition of driver's default behavior.
QString ROW_ID_FIELD_NAME
bool ROW_ID_FIELD_RETURNS_LAST_AUTOINCREMENTED_VALUE
A driver manager for finding and loading driver plugins.
KDbResultable * resultable() const
KDbDriver * driver(const QString &id)
Database driver's abstraction.
KDbConnection * createConnection(const KDbConnectionData &connData, const KDbConnectionOptions &options)
virtual KDbEscapedString escapeString(const QString &str) const =0
virtual KDbEscapedString valueToSql(KDbField::Type ftype, const QVariant &v) const
Specialized string for escaping.
MaxLengthStrategy maxLengthStrategy() const
void setDescription(const QString &description)
bool isNumericType() const
bool isAutoIncrementAllowed() const
void setOptions(Options options)
QVariant::Type variantType() const
Converts field's type to QVariant equivalent as accurate as possible.
void setCaption(const QString &caption)
@ DefaultMaxLength
Default maximum text length defined globally by the application.
QString description() const
void setDefaultValue(const QVariant &def)
void setMaxLengthStrategy(MaxLengthStrategy strategy)
bool isFPNumericType() const
@ NotEmpty
only legal for string-like and blob fields
void setVisibleDecimalPlaces(int p)
void setName(const QString &name)
Constraints constraints() const
void setMaxLength(int maxLength)
bool isIntegerType() const
QString typeString() const
QString typeGroupName() const
QVariant defaultValue() const
void setCustomProperty(const QByteArray &propertyName, const QVariant &value)
Sets value value for custom property propertyName.
void setConstraints(Constraints c)
TypeGroup typeGroup() const
Record source information that can be specified for the lookup field schema.
QStringList values() const
Provides information about lookup field's setup.
bool setProperties(const QMap< QByteArray, QVariant > &values)
QList< int > visibleColumns() const
QList< int > columnWidths() const
KDbLookupFieldSchemaRecordSource recordSource() const
bool setProperty(const QByteArray &propertyName, const QVariant &value)
DisplayWidget displayWidget() const
bool columnHeadersVisible() const
int maxVisibleRecords() const
MessageType
Message types.
virtual void showErrorMessage(KDbMessageHandler::MessageType messageType, const QString &message, const QString &details=QString(), const QString &caption=QString())=0
Structure for storing single record with type information.
QString description
Detailed error description, empty by default.
QString message
Error message, empty by default.
virtual KDbEscapedString recentSqlString() const
Interface for classes providing a result.
virtual QString serverResultName() const
KDbLookupFieldSchema * lookupFieldSchema(const KDbField &field)
bool setLookupFieldSchema(const QString &fieldName, KDbLookupFieldSchema *lookupFieldSchema)
3-state logical type with three values: true, false and cancelled and convenient operators.
Type type(const QSqlDatabase &db)
A database connectivity and creation framework.
KDB_EXPORT KDbEscapedString timeToSql(const QVariant &v)
Converts time value to its string representation required by KDBSQL commands.
KDB_EXPORT KDbEscapedString dateToSql(const QVariant &v)
Converts date value to its string representation required by KDBSQL commands.
@ Hex
Escaping like 1FAD without quotes or prefixes.
KDB_EXPORT QString sqlite3ProgramPath()
KDB_EXPORT QString escapeIdentifierAndAddQuotes(const QString &string)
T iif(bool ok, const T &value)
KDB_EXPORT QDomElement saveNumberElementToDom(QDomDocument *doc, QDomElement *parentEl, const QString &elementName, int value)
KDB_EXPORT bool isExtendedTableFieldProperty(const QByteArray &propertyName)
for isExtendedTableProperty()
KDB_EXPORT QString numberToString(double value, int decimalPlaces)
KDB_EXPORT void getProperties(const KDbLookupFieldSchema *lookup, QMap< QByteArray, QVariant > *values)
KDB_EXPORT QString escapeBLOB(const QByteArray &array, BLOBEscapingType type)
KDB_EXPORT bool setFieldProperties(KDbField *field, const QMap< QByteArray, QVariant > &values)
SplitToTableAndFieldPartsOptions
Used in splitToTableAndFieldParts().
@ SetFieldNameIfNoTableName
see splitToTableAndFieldParts()
KDB_EXPORT bool isIdentifier(const QString &s)
KDB_EXPORT QByteArray pgsqlByteaToByteArray(const char *data, int length=-1)
KDB_EXPORT QString escapeIdentifier(const QString &string)
KDB_EXPORT KDbEscapedString timeToIsoString(const QVariant &v)
Converts time value to its string representation in ISO 8601 Time format.
KDB_EXPORT quint64 lastInsertedAutoIncValue(QSharedPointer< KDbSqlResult > result, const QString &autoIncrementFieldName, const QString &tableName, quint64 *recordId=nullptr)
Returns value of last inserted record for an autoincrement field.
KDB_EXPORT bool deleteRecords(KDbConnection *conn, const QString &tableName, const QString &keyname, KDbField::Type keytype, const QVariant &keyval)
Deletes records using one generic criteria.
KDB_EXPORT QString defaultFileBasedDriverMimeType()
KDB_EXPORT KDbEscapedString sqlWhere(KDbDriver *drv, KDbField::Type t, const QString &fieldName, const QVariant &value)
KDB_EXPORT KDbField::Type maximumForIntegerFieldTypes(KDbField::Type t1, KDbField::Type t2)
KDB_EXPORT QStringList deserializeList(const QString &data)
KDB_EXPORT bool isEmptyValue(KDbField::Type type, const QVariant &value)
KDB_EXPORT QStringList fieldTypeStringsForGroup(KDbField::TypeGroup typeGroup)
KDB_EXPORT QString defaultFileBasedDriverId()
KDB_EXPORT bool isLookupFieldSchemaProperty(const QByteArray &propertyName)
for isLookupFieldSchemaProperty()
KDB_EXPORT KDbEscapedString dateToIsoString(const QVariant &v)
Converts date value to its string representation in ISO 8601 DateTime format.
KDB_EXPORT void getFieldProperties(const KDbField &field, QMap< QByteArray, QVariant > *values)
KDB_EXPORT bool importSqliteFile(const QString &inputFileName, const QString &outputFileName)
KDB_EXPORT QString escapeString(const QString &string)
KDB_EXPORT KDbVersionInfo version()
KDB_EXPORT QString variantToString(const QVariant &v)
KDB_EXPORT bool isKDbSqlKeyword(const QByteArray &word)
KDB_EXPORT KDbField::Type defaultFieldTypeForGroup(KDbField::TypeGroup typeGroup)
KDB_EXPORT QList< int > stringListToIntList(const QStringList &list, bool *ok=nullptr)
KDB_EXPORT bool supportsVisibleDecimalPlacesProperty(KDbField::Type type)
KDB_EXPORT QStringList fieldTypeNamesForGroup(KDbField::TypeGroup typeGroup)
KDB_EXPORT QString identifierExpectedMessage(const QString &valueName, const QVariant &v)
KDB_EXPORT KDbEscapedString dateTimeToIsoString(const QVariant &v)
Converts date/time value to its string representation in ISO 8601 DateTime format - with "T" delimite...
KDB_EXPORT QString stringToIdentifier(const QString &s)
KDB_EXPORT QString loadStringPropertyValueFromDom(const QDomNode &node, bool *ok)
KDB_EXPORT QString simplifiedFieldTypeName(KDbField::Type type)
KDB_EXPORT KDbEscapedString valueToSql(KDbField::Type ftype, const QVariant &v)
KDB_EXPORT bool setFieldProperty(KDbField *field, const QByteArray &propertyName, const QVariant &value)
KDB_EXPORT QDomElement saveBooleanElementToDom(QDomDocument *doc, QDomElement *parentEl, const QString &elementName, bool value)
KDB_EXPORT KDbField::Type intToFieldType(int type)
KDB_EXPORT QVariant emptyValueForFieldType(KDbField::Type type)
Used in KDb::emptyValueForFieldType()
KDB_EXPORT int loadIntPropertyValueFromDom(const QDomNode &node, bool *ok)
KDB_EXPORT QString serializeList(const QStringList &list)
KDB_EXPORT tristate showConnectionTestDialog(QWidget *parent, const KDbConnectionData &data, KDbMessageHandler *msgHandler)
Shows connection test dialog.
KDB_EXPORT bool deleteAllRecords(KDbConnection *conn, const QString &tableName)
Deletes all records from table tableName.
Signedness
A property of numeric values.
@ Signed
Values can be both positive and negative.
@ Unsigned
Values can be both non-negative.
KDB_EXPORT tristate idForObjectName(KDbConnection *conn, int *id, const QString &objName, int objType)
Finds an identifier for object objName of type objType.
KDB_EXPORT void getLimitsForFieldType(KDbField::Type type, qlonglong *minValue, qlonglong *maxValue, KDb::Signedness signedness=KDb::Signed)
Provides limits for values of type type.
KDB_EXPORT QString unescapeString(const QString &string, char quote, int *errorPosition=nullptr)
Unescapes characters in string string for the KDBSQL dialect.
KDB_EXPORT QVariant cstringToVariant(const char *data, KDbField::Type type, bool *ok, int length=-1, KDb::Signedness signedness=KDb::Signed)
KDB_EXPORT QStringList libraryPaths()
KDB_EXPORT QString numberToLocaleString(double value, int decimalPlaces)
Returns number converted to string using default locale.
KDB_EXPORT bool splitToTableAndFieldParts(const QString &string, QString *tableName, QString *fieldName, SplitToTableAndFieldPartsOptions option=FailIfNoTableOrFieldName)
KDB_EXPORT KDbField::TypeGroup intToFieldTypeGroup(int typeGroup)
KDB_EXPORT QByteArray xHexToByteArray(const char *data, int length=-1, bool *ok=nullptr)
KDB_EXPORT QVariant loadPropertyValueFromDom(const QDomNode &node, bool *ok)
KDB_EXPORT QByteArray zeroXHexToByteArray(const char *data, int length=-1, bool *ok=nullptr)
KDB_EXPORT void getHTMLErrorMesage(const KDbResultable &resultable, QString *msg, QString *details)
Sets HTML-formatted error message with extra details obtained from result object.
KDB_EXPORT QVariant stringToVariant(const QString &s, QVariant::Type type, bool *ok)
KDB_EXPORT QString temporaryTableName(KDbConnection *conn, const QString &baseName)
KDB_EXPORT bool isDefaultValueAllowed(const KDbField &field)
KDB_DEPRECATED_EXPORT KDbEscapedString dateTimeToSql(const QDateTime &v)
Converts date/time value to its string representation in ISO 8601 DateTime format - with "T" delimite...
KDB_EXPORT QList< int > deserializeIntList(const QString &data, bool *ok)
T convert(const QVariant &value)
QString path(const QString &relativePath)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
KIOCORE_EXPORT QString dir(const QString &fileClass)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
KIOCORE_EXPORT void add(const QString &fileClass, const QString &directory)
QString name(StandardAction id)
const QList< QKeySequence > & end()
int decimalPlaces(const int rangeMax, const int significantFigures)
char at(qsizetype i) const const
bool isEmpty() const const
bool isNull() const const
qsizetype length() const const
void resize(qsizetype newSize, char c)
qsizetype size() const const
char toLatin1() const const
char32_t toLower(char32_t ucs4)
QDateTime currentDateTime()
QDomElement createElement(const QString &tagName)
QDomText createTextNode(const QString &value)
QString text() const const
QDomNode appendChild(const QDomNode &newChild)
QString nodeName() const const
QDomElement toElement() const const
QByteArray encodeName(const QString &fileName)
bool exists(const QString &fileName)
bool testFlag(Enum flag) const const
bool contains(const Key &key) const const
T value(const Key &key) const const
qint64 write(const QByteArray &data)
void append(QList< T > &&value)
const_iterator constBegin() const const
const_iterator constEnd() const const
qsizetype count() const const
bool isEmpty() const const
T value(qsizetype i) const const
QString toString(QDate date, FormatType format) const const
const_iterator constBegin() const const
const_iterator constEnd() const const
iterator find(const Key &key)
iterator insert(const Key &key, const T &value)
bool disconnect(const QMetaObject::Connection &connection)
QObject * parent() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
void start(OpenMode mode)
virtual bool waitForBytesWritten(int msecs) override
bool waitForFinished(int msecs)
bool waitForStarted(int msecs)
void setValue(int progress)
iterator insert(const T &value)
QString & append(QChar ch)
QString arg(Args &&... args) const const
const QChar at(qsizetype position) const const
qsizetype capacity() const const
int compare(QLatin1StringView s1, const QString &s2, Qt::CaseSensitivity cs)
QString fromLatin1(QByteArrayView str)
QString fromUtf8(QByteArrayView str)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
bool isNull() const const
QString left(qsizetype n) const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString number(double n, char format, int precision)
QString & prepend(QChar ch)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
void reserve(qsizetype size)
QString simplified() const const
qsizetype size() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
double toDouble(bool *ok) const const
int toInt(bool *ok, int base) const const
QByteArray toLatin1() const const
qlonglong toLongLong(bool *ok, int base) const const
uint toUInt(bool *ok, int base) const const
ushort toUShort(bool *ok, int base) const const
void truncate(qsizetype position)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool canConvert() const const
bool isNull() const const
bool toBool() const const
QByteArray toByteArray() const const
QDate toDate() const const
QDateTime toDateTime() const const
int toInt(bool *ok) const const
QString toString() const const
QStringList toStringList() const const
QTime toTime() const const