File indexing completed on 2024-04-28 15:58:54
0001 /* This file is part of the KDE project 0002 Copyright (C) 2003-2015 Jarosław Staniek <staniek@kde.org> 0003 0004 This program is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this program; see the file COPYING. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "SqliteDriver.h" 0021 #include "SqliteConnection.h" 0022 #include "SqliteConnection_p.h" 0023 #include "SqliteAdmin.h" 0024 0025 #include "KDbConnection.h" 0026 #include "KDbDriverManager.h" 0027 #include "KDbDriverBehavior.h" 0028 #include "KDbExpression.h" 0029 #include "KDb.h" 0030 0031 #include <KPluginFactory> 0032 0033 #include <sqlite3.h> 0034 0035 KDB_DRIVER_PLUGIN_FACTORY(SqliteDriver, "kdb_sqlitedriver.json") 0036 0037 //! driver specific private data 0038 //! @internal 0039 class SqliteDriverPrivate 0040 { 0041 public: 0042 SqliteDriverPrivate() 0043 : collate(QLatin1String(" COLLATE ''")) 0044 { 0045 } 0046 KDbEscapedString collate; 0047 Q_DISABLE_COPY(SqliteDriverPrivate) 0048 }; 0049 0050 SqliteDriver::SqliteDriver(QObject *parent, const QVariantList &args) 0051 : KDbDriver(parent, args) 0052 , dp(new SqliteDriverPrivate) 0053 { 0054 KDbDriverBehavior *beh = behavior(); 0055 beh->features = SingleTransactions | CursorForward | CompactingDatabaseSupported; 0056 0057 //special method for autoincrement definition 0058 beh->SPECIAL_AUTO_INCREMENT_DEF = true; 0059 beh->AUTO_INCREMENT_FIELD_OPTION = QString(); //not available 0060 beh->AUTO_INCREMENT_TYPE = QLatin1String("INTEGER"); 0061 beh->AUTO_INCREMENT_PK_FIELD_OPTION = QLatin1String("PRIMARY KEY"); 0062 beh->AUTO_INCREMENT_REQUIRES_PK = true; 0063 beh->ROW_ID_FIELD_NAME = QLatin1String("OID"); 0064 beh->IS_DB_OPEN_AFTER_CREATE = true; 0065 beh->_1ST_ROW_READ_AHEAD_REQUIRED_TO_KNOW_IF_THE_RESULT_IS_EMPTY = true; 0066 beh->OPENING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER = '['; 0067 beh->CLOSING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER = ']'; 0068 beh->SELECT_1_SUBQUERY_SUPPORTED = true; 0069 beh->CONNECTION_REQUIRED_TO_CHECK_DB_EXISTENCE = false; 0070 beh->CONNECTION_REQUIRED_TO_CREATE_DB = false; 0071 beh->CONNECTION_REQUIRED_TO_DROP_DB = false; 0072 beh->GET_TABLE_NAMES_SQL 0073 = KDbEscapedString("SELECT name FROM sqlite_master WHERE type='table'"); 0074 0075 initDriverSpecificKeywords(keywords); 0076 0077 // internal properties 0078 beh->properties.insert("client_library_version", QLatin1String(sqlite3_libversion())); 0079 beh->properties.insert("default_server_encoding", QLatin1String("UTF8")); //OK? 0080 0081 beh->typeNames[KDbField::Byte] = QLatin1String("Byte"); 0082 beh->typeNames[KDbField::ShortInteger] = QLatin1String("ShortInteger"); 0083 beh->typeNames[KDbField::Integer] = QLatin1String("Integer"); 0084 beh->typeNames[KDbField::BigInteger] = QLatin1String("BigInteger"); 0085 beh->typeNames[KDbField::Boolean] = QLatin1String("Boolean"); 0086 beh->typeNames[KDbField::Date] = QLatin1String("Date"); // In fact date/time types could be declared as datetext etc. 0087 beh->typeNames[KDbField::DateTime] = QLatin1String("DateTime"); // to force text affinity..., see https://sqlite.org/datatype3.html 0088 beh->typeNames[KDbField::Time] = QLatin1String("Time"); 0089 beh->typeNames[KDbField::Float] = QLatin1String("Float"); 0090 beh->typeNames[KDbField::Double] = QLatin1String("Double"); 0091 beh->typeNames[KDbField::Text] = QLatin1String("Text"); 0092 beh->typeNames[KDbField::LongText] = QLatin1String("CLOB"); 0093 beh->typeNames[KDbField::BLOB] = QLatin1String("BLOB"); 0094 } 0095 0096 SqliteDriver::~SqliteDriver() 0097 { 0098 delete dp; 0099 } 0100 0101 0102 KDbConnection* 0103 SqliteDriver::drv_createConnection(const KDbConnectionData& connData, 0104 const KDbConnectionOptions &options) 0105 { 0106 return new SqliteConnection(this, connData, options); 0107 } 0108 0109 bool SqliteDriver::isSystemObjectName(const QString& name) const 0110 { 0111 return name.startsWith(QLatin1String("sqlite_"), Qt::CaseInsensitive); 0112 } 0113 0114 bool SqliteDriver::isSystemDatabaseName(const QString& name) const 0115 { 0116 Q_UNUSED(name); 0117 return false; 0118 } 0119 0120 bool SqliteDriver::drv_isSystemFieldName(const QString& name) const 0121 { 0122 return 0 == name.compare(QLatin1String("_rowid_"), Qt::CaseInsensitive) 0123 || 0 == name.compare(QLatin1String("rowid"), Qt::CaseInsensitive) 0124 || 0 == name.compare(QLatin1String("oid"), Qt::CaseInsensitive); 0125 } 0126 0127 KDbEscapedString SqliteDriver::escapeString(const QString& str) const 0128 { 0129 return KDbEscapedString("'") + KDbEscapedString(str).replace('\'', "''") + '\''; 0130 } 0131 0132 KDbEscapedString SqliteDriver::escapeString(const QByteArray& str) const 0133 { 0134 return KDbEscapedString("'") + KDbEscapedString(str).replace('\'', "''") + '\''; 0135 } 0136 0137 KDbEscapedString SqliteDriver::escapeBLOB(const QByteArray& array) const 0138 { 0139 return KDbEscapedString(KDb::escapeBLOB(array, KDb::BLOBEscapingType::XHex)); 0140 } 0141 0142 QString SqliteDriver::drv_escapeIdentifier(const QString& str) const 0143 { 0144 return QString(str).replace(QLatin1Char('"'), QLatin1String("\"\"")); 0145 } 0146 0147 QByteArray SqliteDriver::drv_escapeIdentifier(const QByteArray& str) const 0148 { 0149 return QByteArray(str).replace('"', "\"\""); 0150 } 0151 0152 KDbAdminTools* SqliteDriver::drv_createAdminTools() const 0153 { 0154 return new SqliteAdminTools(); 0155 } 0156 0157 KDbEscapedString SqliteDriver::collationSql() const 0158 { 0159 return dp->collate; 0160 } 0161 0162 KDbEscapedString SqliteDriver::greatestOrLeastFunctionToString(const QString &name, 0163 const KDbNArgExpression &args, 0164 KDbQuerySchemaParameterValueListIterator* params, 0165 KDb::ExpressionCallStack* callStack) const 0166 { 0167 Q_ASSERT(args.argCount() >= 2); 0168 static QString greatestString(QLatin1String("GREATEST")); 0169 static QString maxString(QLatin1String("MAX")); 0170 static QString minString(QLatin1String("MIN")); 0171 const QString realName( 0172 name == greatestString ? maxString : minString); 0173 if (args.argCount() >= 2 && KDbField::isTextType(args.arg(0).type())) { 0174 KDbEscapedString s; 0175 s.reserve(256); 0176 for(int i=0; i < args.argCount(); ++i) { 0177 if (!s.isEmpty()) { 0178 s += ", "; 0179 } 0180 s += QLatin1Char('(') + args.arg(i).toString(this, params, callStack) + QLatin1String(") ") + collationSql(); 0181 } 0182 return realName + QLatin1Char('(') + s + QLatin1Char(')'); 0183 } 0184 return KDbFunctionExpression::toString(realName, this, args, params, callStack); 0185 } 0186 0187 KDbEscapedString SqliteDriver::randomFunctionToString(const KDbNArgExpression &args, 0188 KDbQuerySchemaParameterValueListIterator* params, 0189 KDb::ExpressionCallStack* callStack) const 0190 { 0191 if (args.isNull() || args.argCount() < 1 ) { 0192 static KDbEscapedString randomStatic("((RANDOM()+9223372036854775807)/18446744073709551615)"); 0193 return randomStatic; 0194 } 0195 Q_ASSERT(args.argCount() == 2); 0196 const KDbEscapedString x(args.arg(0).toString(this, params, callStack)); 0197 const KDbEscapedString y(args.arg(1).toString(this, params, callStack)); 0198 static KDbEscapedString floorRandomStatic("+CAST((("); 0199 static KDbEscapedString floorRandomStatic2("))*(RANDOM()+9223372036854775807)/18446744073709551615 AS INT))"); 0200 //! (X + CAST((Y - X) * (RANDOM()+9223372036854775807)/18446744073709551615 AS INT)). 0201 return KDbEscapedString("((") + x + QLatin1Char(')') + floorRandomStatic + y + QLatin1Char(')') 0202 + QLatin1String("-(") + x + floorRandomStatic2; 0203 } 0204 0205 KDbEscapedString SqliteDriver::ceilingOrFloorFunctionToString(const QString &name, 0206 const KDbNArgExpression &args, 0207 KDbQuerySchemaParameterValueListIterator* params, 0208 KDb::ExpressionCallStack* callStack) const 0209 { 0210 Q_ASSERT(args.argCount() == 1); 0211 static QLatin1String ceilingString("CEILING"); 0212 KDbEscapedString x(args.arg(0).toString(this, params, callStack)); 0213 if (name == ceilingString) { 0214 return KDbEscapedString("(CASE WHEN ") 0215 + x + QLatin1String("=CAST(") + x + QLatin1String(" AS INT) THEN CAST(") 0216 + x + QLatin1String(" AS INT) WHEN ") 0217 + x + QLatin1String(">=0 THEN CAST(") 0218 + x + QLatin1String(" AS INT)+1 ELSE CAST(") 0219 + x + QLatin1String(" AS INT) END)"); 0220 } 0221 // floor(): 0222 return KDbEscapedString("(CASE WHEN ") + x + QLatin1String(">=0 OR ") 0223 + x + QLatin1String("=CAST(") + x + QLatin1String(" AS INT) THEN CAST(") 0224 + x + QLatin1String(" AS INT) ELSE CAST(") 0225 + x + QLatin1String(" AS INT)-1 END)"); 0226 } 0227 0228 #include "SqliteDriver.moc"