KDb

SqliteDriver.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2003-2015 JarosÅ‚aw Staniek <[email protected]>
3 
4  This program is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this program; see the file COPYING. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18 */
19 
20 #include "SqliteDriver.h"
21 #include "SqliteConnection.h"
22 #include "SqliteConnection_p.h"
23 #include "SqliteAdmin.h"
24 
25 #include "KDbConnection.h"
26 #include "KDbDriverManager.h"
27 #include "KDbDriverBehavior.h"
28 #include "KDbExpression.h"
29 #include "KDb.h"
30 
31 #include <KPluginFactory>
32 
33 #include <sqlite3.h>
34 
35 K_PLUGIN_CLASS_WITH_JSON(SqliteDriver, "kdb_sqlitedriver.json")
36 
37 //! driver specific private data
38 //! @internal
39 class SqliteDriverPrivate
40 {
41 public:
42  SqliteDriverPrivate()
43  : collate(QLatin1String(" COLLATE ''"))
44  {
45  }
46  KDbEscapedString collate;
47  Q_DISABLE_COPY(SqliteDriverPrivate)
48 };
49 
50 SqliteDriver::SqliteDriver(QObject *parent, const QVariantList &args)
51  : KDbDriver(parent, args)
52  , dp(new SqliteDriverPrivate)
53 {
54  KDbDriverBehavior *beh = behavior();
55  beh->features = SingleTransactions | CursorForward | CompactingDatabaseSupported;
56 
57  //special method for autoincrement definition
58  beh->SPECIAL_AUTO_INCREMENT_DEF = true;
59  beh->AUTO_INCREMENT_FIELD_OPTION = QString(); //not available
60  beh->AUTO_INCREMENT_TYPE = QLatin1String("INTEGER");
61  beh->AUTO_INCREMENT_PK_FIELD_OPTION = QLatin1String("PRIMARY KEY");
62  beh->AUTO_INCREMENT_REQUIRES_PK = true;
63  beh->ROW_ID_FIELD_NAME = QLatin1String("OID");
64  beh->IS_DB_OPEN_AFTER_CREATE = true;
68  beh->SELECT_1_SUBQUERY_SUPPORTED = true;
71  beh->CONNECTION_REQUIRED_TO_DROP_DB = false;
73  = KDbEscapedString("SELECT name FROM sqlite_master WHERE type='table'");
74 
75  initDriverSpecificKeywords(keywords);
76 
77  // internal properties
78  beh->properties.insert("client_library_version", QLatin1String(sqlite3_libversion()));
79  beh->properties.insert("default_server_encoding", QLatin1String("UTF8")); //OK?
80 
81  beh->typeNames[KDbField::Byte] = QLatin1String("Byte");
82  beh->typeNames[KDbField::ShortInteger] = QLatin1String("ShortInteger");
83  beh->typeNames[KDbField::Integer] = QLatin1String("Integer");
84  beh->typeNames[KDbField::BigInteger] = QLatin1String("BigInteger");
85  beh->typeNames[KDbField::Boolean] = QLatin1String("Boolean");
86  beh->typeNames[KDbField::Date] = QLatin1String("Date"); // In fact date/time types could be declared as datetext etc.
87  beh->typeNames[KDbField::DateTime] = QLatin1String("DateTime"); // to force text affinity..., see https://sqlite.org/datatype3.html
88  beh->typeNames[KDbField::Time] = QLatin1String("Time");
89  beh->typeNames[KDbField::Float] = QLatin1String("Float");
90  beh->typeNames[KDbField::Double] = QLatin1String("Double");
91  beh->typeNames[KDbField::Text] = QLatin1String("Text");
93  beh->typeNames[KDbField::BLOB] = QLatin1String("BLOB");
94 }
95 
96 SqliteDriver::~SqliteDriver()
97 {
98  delete dp;
99 }
100 
101 
105 {
106  return new SqliteConnection(this, connData, options);
107 }
108 
110 {
111  return name.startsWith(QLatin1String("sqlite_"), Qt::CaseInsensitive);
112 }
113 
115 {
116  Q_UNUSED(name);
117  return false;
118 }
119 
121 {
122  return 0 == name.compare(QLatin1String("_rowid_"), Qt::CaseInsensitive)
123  || 0 == name.compare(QLatin1String("rowid"), Qt::CaseInsensitive)
124  || 0 == name.compare(QLatin1String("oid"), Qt::CaseInsensitive);
125 }
126 
128 {
129  return KDbEscapedString("'") + KDbEscapedString(str).replace('\'', "''") + '\'';
130 }
131 
133 {
134  return KDbEscapedString("'") + KDbEscapedString(str).replace('\'', "''") + '\'';
135 }
136 
138 {
140 }
141 
143 {
144  return QString(str).replace(QLatin1Char('"'), QLatin1String("\"\""));
145 }
146 
148 {
149  return QByteArray(str).replace('"', "\"\"");
150 }
151 
153 {
154  return new SqliteAdminTools();
155 }
156 
158 {
159  return dp->collate;
160 }
161 
163  const KDbNArgExpression &args,
165  KDb::ExpressionCallStack* callStack) const
166 {
167  Q_ASSERT(args.argCount() >= 2);
168  static QString greatestString(QLatin1String("GREATEST"));
169  static QString maxString(QLatin1String("MAX"));
170  static QString minString(QLatin1String("MIN"));
171  const QString realName(
172  name == greatestString ? maxString : minString);
173  if (args.argCount() >= 2 && KDbField::isTextType(args.arg(0).type())) {
175  s.reserve(256);
176  for(int i=0; i < args.argCount(); ++i) {
177  if (!s.isEmpty()) {
178  s += ", ";
179  }
180  s += QLatin1Char('(') + args.arg(i).toString(this, params, callStack) + QLatin1String(") ") + collationSql();
181  }
182  return realName + QLatin1Char('(') + s + QLatin1Char(')');
183  }
184  return KDbFunctionExpression::toString(realName, this, args, params, callStack);
185 }
186 
189  KDb::ExpressionCallStack* callStack) const
190 {
191  if (args.isNull() || args.argCount() < 1 ) {
192  static KDbEscapedString randomStatic("((RANDOM()+9223372036854775807)/18446744073709551615)");
193  return randomStatic;
194  }
195  Q_ASSERT(args.argCount() == 2);
196  const KDbEscapedString x(args.arg(0).toString(this, params, callStack));
197  const KDbEscapedString y(args.arg(1).toString(this, params, callStack));
198  static KDbEscapedString floorRandomStatic("+CAST(((");
199  static KDbEscapedString floorRandomStatic2("))*(RANDOM()+9223372036854775807)/18446744073709551615 AS INT))");
200  //! (X + CAST((Y - X) * (RANDOM()+9223372036854775807)/18446744073709551615 AS INT)).
201  return KDbEscapedString("((") + x + QLatin1Char(')') + floorRandomStatic + y + QLatin1Char(')')
202  + QLatin1String("-(") + x + floorRandomStatic2;
203 }
204 
206  const KDbNArgExpression &args,
208  KDb::ExpressionCallStack* callStack) const
209 {
210  Q_ASSERT(args.argCount() == 1);
211  static QLatin1String ceilingString("CEILING");
212  KDbEscapedString x(args.arg(0).toString(this, params, callStack));
213  if (name == ceilingString) {
214  return KDbEscapedString("(CASE WHEN ")
215  + x + QLatin1String("=CAST(") + x + QLatin1String(" AS INT) THEN CAST(")
216  + x + QLatin1String(" AS INT) WHEN ")
217  + x + QLatin1String(">=0 THEN CAST(")
218  + x + QLatin1String(" AS INT)+1 ELSE CAST(")
219  + x + QLatin1String(" AS INT) END)");
220  }
221  // floor():
222  return KDbEscapedString("(CASE WHEN ") + x + QLatin1String(">=0 OR ")
223  + x + QLatin1String("=CAST(") + x + QLatin1String(" AS INT) THEN CAST(")
224  + x + QLatin1String(" AS INT) ELSE CAST(")
225  + x + QLatin1String(" AS INT)-1 END)");
226 }
227 
228 #include "SqliteDriver.moc"
KDbEscapedString GET_TABLE_NAMES_SQL
SQL statement used to obtain list of physical table names.
KDbEscapedString escapeString(const QString &str) const override
Escape a string for use as a value.
KDbEscapedString collationSql() const override
KDbEscapedString ceilingOrFloorFunctionToString(const QString &name, const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const override
Generates native (driver-specific) CEILING() and FLOOR() function calls.
void insert(const QByteArray &name, const QVariant &value, const QString &caption=QString())
Inserts property with a given name, value and caption.
Definition: KDbUtils.cpp:659
KDbEscapedString greatestOrLeastFunctionToString(const QString &name, const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const override
Generates native (driver-specific) GREATEST() and LEAST() function calls.
KDbEscapedString randomFunctionToString(const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const override
Generates native (driver-specific) RANDOM() and RANDOM(X,Y) function calls.
KDbExpression arg(int i) const
CaseInsensitive
An iterator for a list of values of query schema parameters Allows to iterate over parameters and ret...
@ Text
Definition: KDbField.h:98
Specialized string for escaping.
QString AUTO_INCREMENT_TYPE
"" by default, used as type string for autoinc.
Database driver's abstraction.
Definition: KDbDriver.h:49
QVector< QString > typeNames
real type names for this engine
KDbAdminTools * drv_createAdminTools() const override
QString AUTO_INCREMENT_FIELD_OPTION
"AUTO_INCREMENT" by default, used as add-in word to field definition May be also used as full definit...
bool isSystemObjectName(const QString &n) const override
KDbConnection * drv_createConnection(const KDbConnectionData &connData, const KDbConnectionOptions &options) override
QString AUTO_INCREMENT_PK_FIELD_OPTION
"AUTO_INCREMENT PRIMARY KEY" by default, used as add-in word to field definition May be also used as ...
bool isTextType() const
Definition: KDbField.h:353
bool isSystemDatabaseName(const QString &) const override
@ Integer
Definition: KDbField.h:90
KDbEscapedString toString(const KDbDriver *driver, KDbQuerySchemaParameterValueListIterator *params=nullptr, KDb::ExpressionCallStack *callStack=nullptr) const
@ XHex
Escaping like X'1FAD', used by sqlite (hex numbers)
KDbUtils::PropertySet properties
QString drv_escapeIdentifier(const QString &str) const override
@ BigInteger
Definition: KDbField.h:91
SQLite database driver.
Definition: SqliteDriver.h:29
@ Double
Definition: KDbField.h:97
@ LongText
Definition: KDbField.h:99
QByteArray & replace(int pos, int len, const char *after)
QString & replace(int position, int n, QChar after)
@ Byte
Definition: KDbField.h:87
KDbEscapedString escapeBLOB(const QByteArray &array) const override
Escape BLOB value array.
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
The KDbNArgExpression class represents a base class N-argument expression.
KDB_EXPORT QString escapeBLOB(const QByteArray &array, BLOBEscapingType type)
An interface containing a set of tools for database administration.
Definition: KDbAdmin.h:30
Detailed definition of driver's default behavior.
@ Boolean
Definition: KDbField.h:92
bool isNull() const
KDbConnectionOptions * options()
static KDbEscapedString toString(const QString &name, const KDbDriver *driver, const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack)
Database specific connection data, e.g. host, port.
Generic options for a single connection. The options are accessible using key/value pairs....
char CLOSING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER
SqliteConnection(KDbDriver *driver, const KDbConnectionData &connData, const KDbConnectionOptions &options)
bool CONNECTION_REQUIRED_TO_CHECK_DB_EXISTENCE
@ Float
Definition: KDbField.h:96
int compare(const QString &other, Qt::CaseSensitivity cs) const const
Provides database connection, allowing queries and data modification.
Definition: KDbConnection.h:51
#define K_PLUGIN_CLASS_WITH_JSON(classname, jsonFile)
bool _1ST_ROW_READ_AHEAD_REQUIRED_TO_KNOW_IF_THE_RESULT_IS_EMPTY
KDbField::Type type() const
An interface containing a set of tools for SQLite database administration.
Definition: SqliteAdmin.h:27
@ ShortInteger
Definition: KDbField.h:89
char OPENING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER
bool drv_isSystemFieldName(const QString &n) const override
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sat Jun 25 2022 06:21:34 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.