diff options
Diffstat (limited to 'src/libs/sqlite')
51 files changed, 4908 insertions, 0 deletions
diff --git a/src/libs/sqlite/columndefinition.cpp b/src/libs/sqlite/columndefinition.cpp new file mode 100644 index 0000000000..0bacb27c56 --- /dev/null +++ b/src/libs/sqlite/columndefinition.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "columndefinition.h" + +namespace Internal { + +void ColumnDefinition::setName(const Utf8String &name) +{ + name_ = name; +} + +const Utf8String &ColumnDefinition::name() const +{ + return name_; +} + +void ColumnDefinition::setType(ColumnType type) +{ + type_ = type; +} + +ColumnType ColumnDefinition::type() const +{ + return type_; +} + +Utf8String ColumnDefinition::typeString() const +{ + switch (type_) { + case ColumnType::None: return Utf8String(); + case ColumnType::Numeric: return Utf8StringLiteral("NUMERIC"); + case ColumnType::Integer: return Utf8StringLiteral("INTEGER"); + case ColumnType::Real: return Utf8StringLiteral("REAL"); + case ColumnType::Text: return Utf8StringLiteral("TEXT"); + } + + Q_UNREACHABLE(); +} + +void ColumnDefinition::setIsPrimaryKey(bool isPrimaryKey) +{ + isPrimaryKey_ = isPrimaryKey; +} + +bool ColumnDefinition::isPrimaryKey() const +{ + return isPrimaryKey_; +} + +} diff --git a/src/libs/sqlite/columndefinition.h b/src/libs/sqlite/columndefinition.h new file mode 100644 index 0000000000..ef63a709dd --- /dev/null +++ b/src/libs/sqlite/columndefinition.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef COLUMNDEFINITION_H +#define COLUMNDEFINITION_H + +#include "sqliteglobal.h" +#include "utf8string.h" + +namespace Internal { + +class ColumnDefinition +{ +public: + void setName(const Utf8String &name); + const Utf8String &name() const; + + void setType(ColumnType type); + ColumnType type() const; + Utf8String typeString() const; + + void setIsPrimaryKey(bool isPrimaryKey); + bool isPrimaryKey() const; + +private: + Utf8String name_; + ColumnType type_; + bool isPrimaryKey_ = false; +}; + +} + +#endif // COLUMNDEFINITION_H diff --git a/src/libs/sqlite/createtablecommand.cpp b/src/libs/sqlite/createtablecommand.cpp new file mode 100644 index 0000000000..5d54323e46 --- /dev/null +++ b/src/libs/sqlite/createtablecommand.cpp @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "createtablecommand.h" + +namespace Internal { + +void CreateTableCommand::registerType() +{ + qRegisterMetaType<CreateTableCommand>("CreateTableCommand"); +} + +} // namespace Internal + diff --git a/src/libs/sqlite/createtablecommand.h b/src/libs/sqlite/createtablecommand.h new file mode 100644 index 0000000000..cd4bdd46db --- /dev/null +++ b/src/libs/sqlite/createtablecommand.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef INTERNAL_CREATETABLECOMMAND_H +#define INTERNAL_CREATETABLECOMMAND_H + +#include <QMetaType> +#include <QVector> + +#include "utf8string.h" +#include "columndefinition.h" + +namespace Internal { + +class CreateTableCommand +{ +public: + QVector<ColumnDefinition> definitions; + Utf8String tableName; + bool useWithoutRowId; + + static void registerType(); + +}; + +} // namespace Internal + +Q_DECLARE_METATYPE(Internal::CreateTableCommand) + +#endif // INTERNAL_CREATETABLECOMMAND_H diff --git a/src/libs/sqlite/createtablesqlstatementbuilder.cpp b/src/libs/sqlite/createtablesqlstatementbuilder.cpp new file mode 100644 index 0000000000..5122001c19 --- /dev/null +++ b/src/libs/sqlite/createtablesqlstatementbuilder.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "createtablesqlstatementbuilder.h" + +#include "utf8stringvector.h" + +namespace Internal { + +CreateTableSqlStatementBuilder::CreateTableSqlStatementBuilder() + : sqlStatementBuilder(Utf8StringLiteral("CREATE TABLE IF NOT EXISTS $table($columnDefinitions)$withoutRowId")), + useWithoutRowId(false) +{ +} + +void CreateTableSqlStatementBuilder::setTable(const Utf8String &tableName) +{ + sqlStatementBuilder.clear(); + + this->tableName = tableName; +} + +void CreateTableSqlStatementBuilder::addColumnDefinition(const Utf8String &columnName, + ColumnType columnType, + bool isPrimaryKey) +{ + sqlStatementBuilder.clear(); + + ColumnDefinition columnDefinition; + columnDefinition.setName(columnName); + columnDefinition.setType(columnType); + columnDefinition.setIsPrimaryKey(isPrimaryKey); + + columnDefinitions.append(columnDefinition); +} + +void CreateTableSqlStatementBuilder::setColumnDefinitions(const QVector<ColumnDefinition> &columnDefinitions) +{ + sqlStatementBuilder.clear(); + + this->columnDefinitions = columnDefinitions; +} + +void CreateTableSqlStatementBuilder::setUseWithoutRowId(bool useWithoutRowId) +{ + this->useWithoutRowId = useWithoutRowId; +} + +void CreateTableSqlStatementBuilder::clear() +{ + sqlStatementBuilder.clear(); + columnDefinitions.clear(); + tableName.clear(); + useWithoutRowId = false; +} + +void CreateTableSqlStatementBuilder::clearColumns() +{ + sqlStatementBuilder.clear(); + columnDefinitions.clear(); +} + +Utf8String CreateTableSqlStatementBuilder::sqlStatement() const +{ + if (!sqlStatementBuilder.isBuild()) + bindAll(); + + return sqlStatementBuilder.sqlStatement(); +} + +bool CreateTableSqlStatementBuilder::isValid() const +{ + return tableName.hasContent() && !columnDefinitions.isEmpty(); +} + +void CreateTableSqlStatementBuilder::bindColumnDefinitions() const +{ + Utf8StringVector columnDefinitionStrings; + + foreach (const ColumnDefinition &columnDefinition, columnDefinitions) { + Utf8String columnDefinitionString = columnDefinition.name() + Utf8StringLiteral(" ") + columnDefinition.typeString(); + + if (columnDefinition.isPrimaryKey()) + columnDefinitionString.append(Utf8StringLiteral(" PRIMARY KEY")); + + columnDefinitionStrings.append(columnDefinitionString); + } + + sqlStatementBuilder.bind(Utf8StringLiteral("$columnDefinitions"), columnDefinitionStrings); +} + +void CreateTableSqlStatementBuilder::bindAll() const +{ + sqlStatementBuilder.bind(Utf8StringLiteral("$table"), tableName); + + bindColumnDefinitions(); + + if (useWithoutRowId) + sqlStatementBuilder.bind(Utf8StringLiteral("$withoutRowId"), Utf8StringLiteral(" WITHOUT ROWID")); + else + sqlStatementBuilder.bindEmptyText(Utf8StringLiteral("$withoutRowId")); +} + +} diff --git a/src/libs/sqlite/createtablesqlstatementbuilder.h b/src/libs/sqlite/createtablesqlstatementbuilder.h new file mode 100644 index 0000000000..f70c972f39 --- /dev/null +++ b/src/libs/sqlite/createtablesqlstatementbuilder.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CREATETABLESQLSTATEMENTBUILDER_H +#define CREATETABLESQLSTATEMENTBUILDER_H + +#include <QVector> + +#include "sqlstatementbuilder.h" + +#include "columndefinition.h" + +namespace Internal { + +class SQLITE_EXPORT CreateTableSqlStatementBuilder +{ +public: + CreateTableSqlStatementBuilder(); + + void setTable(const Utf8String &tableName); + void addColumnDefinition(const Utf8String &columnName, ColumnType columnType, bool isPrimaryKey = false); + void setColumnDefinitions(const QVector<ColumnDefinition> & columnDefinitions); + void setUseWithoutRowId(bool useWithoutRowId); + + void clear(); + void clearColumns(); + + Utf8String sqlStatement() const; + + bool isValid() const; + +protected: + void bindColumnDefinitions() const; + void bindAll() const; + +private: + mutable SqlStatementBuilder sqlStatementBuilder; + Utf8String tableName; + QVector<ColumnDefinition> columnDefinitions; + bool useWithoutRowId; +}; + +} + +#endif // CREATETABLESQLSTATEMENTBUILDER_H diff --git a/src/libs/sqlite/sqlite-lib.pri b/src/libs/sqlite/sqlite-lib.pri new file mode 100644 index 0000000000..35a02f55a6 --- /dev/null +++ b/src/libs/sqlite/sqlite-lib.pri @@ -0,0 +1,64 @@ +contains(CONFIG, dll) { + DEFINES += BUILD_SQLITE_LIBRARY +} else { + DEFINES += BUILD_SQLITE_STATIC_LIBRARY +} + +INCLUDEPATH += $$PWD + +unix:LIBS += -ldl + +include(../3rdparty/sqlite/sqlite.pri) + +SOURCES += \ + $$PWD/columndefinition.cpp \ + $$PWD/createtablecommand.cpp \ + $$PWD/createtablesqlstatementbuilder.cpp \ + $$PWD/sqlitedatabasebackend.cpp \ + $$PWD/sqlitedatabaseconnection.cpp \ + $$PWD/sqlitedatabaseconnectionproxy.cpp \ + $$PWD/sqliteexception.cpp \ + $$PWD/sqliteglobal.cpp \ + $$PWD/sqlitereadstatement.cpp \ + $$PWD/sqlitereadwritestatement.cpp \ + $$PWD/sqlitestatement.cpp \ + $$PWD/sqlitetransaction.cpp \ + $$PWD/sqliteworkerthread.cpp \ + $$PWD/sqlitewritestatement.cpp \ + $$PWD/sqlstatementbuilder.cpp \ + $$PWD/sqlstatementbuilderexception.cpp \ + $$PWD/utf8string.cpp \ + $$PWD/utf8stringvector.cpp \ + $$PWD/sqlitedatabase.cpp \ + $$PWD/sqlitetable.cpp \ + $$PWD/sqlitecolumn.cpp \ + $$PWD/tablewriteworker.cpp \ + $$PWD/tablewriteworkerproxy.cpp +HEADERS += \ + $$PWD/columndefinition.h \ + $$PWD/createtablesqlstatementbuilder.h \ + $$PWD/sqlitedatabasebackend.h \ + $$PWD/sqlitedatabaseconnection.h \ + $$PWD/sqlitedatabaseconnectionproxy.h \ + $$PWD/sqliteexception.h \ + $$PWD/sqliteglobal.h \ + $$PWD/sqlitereadstatement.h \ + $$PWD/sqlitereadwritestatement.h \ + $$PWD/sqlitestatement.h \ + $$PWD/sqlitetransaction.h \ + $$PWD/sqliteworkerthread.h \ + $$PWD/sqlitewritestatement.h \ + $$PWD/sqlstatementbuilder.h \ + $$PWD/sqlstatementbuilderexception.h \ + $$PWD/utf8string.h \ + $$PWD/utf8stringvector.h \ + $$PWD/sqlitedatabase.h \ + $$PWD/sqlitetable.h \ + $$PWD/sqlitecolumn.h \ + $$PWD/tablewriteworker.h \ + $$PWD/tablewriteworkerproxy.h \ + $$PWD/createtablecommand.h + +DEFINES += SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA + +contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols diff --git a/src/libs/sqlite/sqlite-source.pri b/src/libs/sqlite/sqlite-source.pri new file mode 100644 index 0000000000..b297e31da2 --- /dev/null +++ b/src/libs/sqlite/sqlite-source.pri @@ -0,0 +1,53 @@ +INCLUDEPATH += $$PWD +VPATH += $$PWD + +SOURCES += \ + columndefinition.cpp \ + createtablecommand.cpp \ + createtablesqlstatementbuilder.cpp \ + sqlitedatabasebackend.cpp \ + sqlitedatabaseconnection.cpp \ + sqlitedatabaseconnectionproxy.cpp \ + sqliteexception.cpp \ + sqliteglobal.cpp \ + sqlitereadstatement.cpp \ + sqlitereadwritestatement.cpp \ + sqlitestatement.cpp \ + sqlitetransaction.cpp \ + sqliteworkerthread.cpp \ + sqlitewritestatement.cpp \ + sqlstatementbuilder.cpp \ + sqlstatementbuilderexception.cpp \ + utf8string.cpp \ + utf8stringvector.cpp \ + sqlitedatabase.cpp \ + sqlitetable.cpp \ + sqlitecolumn.cpp \ + tablewriteworker.cpp \ + tablewriteworkerproxy.cpp +HEADERS += \ + columndefinition.h \ + createtablesqlstatementbuilder.h \ + sqlitedatabasebackend.h \ + sqlitedatabaseconnection.h \ + sqlitedatabaseconnectionproxy.h \ + sqliteexception.h \ + sqliteglobal.h \ + sqlitereadstatement.h \ + sqlitereadwritestatement.h \ + sqlitestatement.h \ + sqlitetransaction.h \ + sqliteworkerthread.h \ + sqlitewritestatement.h \ + sqlstatementbuilder.h \ + sqlstatementbuilderexception.h \ + utf8string.h \ + utf8stringvector.h \ + sqlitedatabase.h \ + sqlitetable.h \ + sqlitecolumn.h \ + tablewriteworker.h \ + tablewriteworkerproxy.h \ + createtablecommand.h + + diff --git a/src/libs/sqlite/sqlite.pro b/src/libs/sqlite/sqlite.pro new file mode 100644 index 0000000000..741e6a6cbf --- /dev/null +++ b/src/libs/sqlite/sqlite.pro @@ -0,0 +1,5 @@ +unix:QMAKE_CXXFLAGS_DEBUG += -O2 +win32:QMAKE_CXXFLAGS_DEBUG += -O2 + +include(../../qtcreatorlibrary.pri) +include(sqlite-lib.pri) diff --git a/src/libs/sqlite/sqlite.qbs b/src/libs/sqlite/sqlite.qbs new file mode 100644 index 0000000000..92ff6a6c51 --- /dev/null +++ b/src/libs/sqlite/sqlite.qbs @@ -0,0 +1,42 @@ +import qbs 1.0 + +QtcLibrary { + name: "Sqlite" + + cpp.includePaths: base.concat(["../3rdparty/sqlite", "."]) + cpp.defines: base.concat([ + "BUILD_SQLITE_LIBRARY", + "SQLITE_THREADSAFE=2", + "SQLITE_ENABLE_FTS4", + "SQLITE_ENABLE_FTS3_PARENTHESIS", + "SQLITE_ENABLE_UNLOCK_NOTIFY", + "SQLITE_ENABLE_COLUMN_METADATA" + ]) + cpp.optimization: "fast" + cpp.dynamicLibraries: base.concat("dl") + + + Group { + name: "ThirdPartySqlite" + prefix: "../3rdparty/sqlite/" + files: [ + "sqlite3.c", + "sqlite3.h", + "sqlite3ext.h", + ] + } + + Group { + files: [ + "*.h", + "*.cpp" + ] + } + + Export { + cpp.includePaths: base.concat([ + "../3rdparty/sqlite", + "." + ]) + } +} diff --git a/src/libs/sqlite/sqlite_dependencies.pri b/src/libs/sqlite/sqlite_dependencies.pri new file mode 100644 index 0000000000..cb383c8e63 --- /dev/null +++ b/src/libs/sqlite/sqlite_dependencies.pri @@ -0,0 +1,3 @@ +QTC_LIB_NAME = Sqlite +INCLUDEPATH *= $$IDE_SOURCE_TREE/src/libs/3rdparty/sqlite +INCLUDEPATH *= $$IDE_SOURCE_TREE/src/libs/sqlite diff --git a/src/libs/sqlite/sqlitecolumn.cpp b/src/libs/sqlite/sqlitecolumn.cpp new file mode 100644 index 0000000000..5005c50441 --- /dev/null +++ b/src/libs/sqlite/sqlitecolumn.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqlitecolumn.h" + +SqliteColumn::SqliteColumn() + : type_(ColumnType::Numeric), + isPrimaryKey_(false) +{ + +} + +void SqliteColumn::clear() +{ + name_.clear(); + type_ = ColumnType::Numeric; + isPrimaryKey_ = false; +} + +void SqliteColumn::setName(const Utf8String &newName) +{ + name_ = newName; +} + +const Utf8String &SqliteColumn::name() const +{ + return name_; +} + +void SqliteColumn::setType(ColumnType newType) +{ + type_ = newType; +} + +ColumnType SqliteColumn::type() const +{ + return type_; +} + +void SqliteColumn::setIsPrimaryKey(bool isPrimaryKey) +{ + isPrimaryKey_ = isPrimaryKey; +} + +bool SqliteColumn::isPrimaryKey() const +{ + return isPrimaryKey_; +} + +Internal::ColumnDefinition SqliteColumn::columnDefintion() const +{ + Internal::ColumnDefinition columnDefinition; + + columnDefinition.setName(name_); + columnDefinition.setType(type_); + columnDefinition.setIsPrimaryKey(isPrimaryKey_); + + return columnDefinition; +} diff --git a/src/libs/sqlite/sqlitecolumn.h b/src/libs/sqlite/sqlitecolumn.h new file mode 100644 index 0000000000..a25fa1fa28 --- /dev/null +++ b/src/libs/sqlite/sqlitecolumn.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITECOLUMN_H +#define SQLITECOLUMN_H + +#include <QObject> + +#include "utf8string.h" +#include "columndefinition.h" + +class SQLITE_EXPORT SqliteColumn : public QObject +{ + Q_OBJECT +public: + SqliteColumn(); + + void clear(); + + void setName(const Utf8String &newName); + const Utf8String &name() const; + + void setType(ColumnType newType); + ColumnType type() const; + + void setIsPrimaryKey(bool isPrimaryKey); + bool isPrimaryKey() const; + + Internal::ColumnDefinition columnDefintion() const; + +private: + Utf8String name_; + ColumnType type_; + bool isPrimaryKey_; +}; + +#endif // SQLITECOLUMN_H diff --git a/src/libs/sqlite/sqlitedatabase.cpp b/src/libs/sqlite/sqlitedatabase.cpp new file mode 100644 index 0000000000..66ce669551 --- /dev/null +++ b/src/libs/sqlite/sqlitedatabase.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqlitedatabase.h" + +#include "sqlitetable.h" + +SqliteDatabase::SqliteDatabase() + : readDatabaseConnection(QStringLiteral("ReadWorker")), + writeDatabaseConnection(QStringLiteral("WriterWorker")), + journalMode_(JournalMode::Wal) +{ + connect(&readDatabaseConnection, &SqliteDatabaseConnectionProxy::connectionIsOpened, this, &SqliteDatabase::handleReadDatabaseConnectionIsOpened); + connect(&writeDatabaseConnection, &SqliteDatabaseConnectionProxy::connectionIsOpened, this, &SqliteDatabase::handleWriteDatabaseConnectionIsOpened); + connect(&readDatabaseConnection, &SqliteDatabaseConnectionProxy::connectionIsClosed, this, &SqliteDatabase::handleReadDatabaseConnectionIsClosed); + connect(&writeDatabaseConnection, &SqliteDatabaseConnectionProxy::connectionIsClosed, this, &SqliteDatabase::handleWriteDatabaseConnectionIsClosed); +} + +SqliteDatabase::~SqliteDatabase() +{ + qDeleteAll(sqliteTables); +} + +void SqliteDatabase::open() +{ + writeDatabaseConnection.setDatabaseFilePath(databaseFilePath()); + writeDatabaseConnection.setJournalMode(journalMode()); +} + +void SqliteDatabase::close() +{ + writeDatabaseConnection.close(); +} + +bool SqliteDatabase::isOpen() const +{ + return readDatabaseConnection.isOpen() && writeDatabaseConnection.isOpen(); +} + +void SqliteDatabase::addTable(SqliteTable *newSqliteTable) +{ + newSqliteTable->setSqliteDatabase(this); + sqliteTables.append(newSqliteTable); +} + +const QVector<SqliteTable *> &SqliteDatabase::tables() const +{ + return sqliteTables; +} + +void SqliteDatabase::setDatabaseFilePath(const QString &databaseFilePath) +{ + databaseFilePath_ = databaseFilePath; +} + +const QString &SqliteDatabase::databaseFilePath() const +{ + return databaseFilePath_; +} + +void SqliteDatabase::setJournalMode(JournalMode journalMode) +{ + journalMode_ = journalMode; +} + +JournalMode SqliteDatabase::journalMode() const +{ + return journalMode_; +} + +QThread *SqliteDatabase::writeWorkerThread() const +{ + return writeDatabaseConnection.connectionThread(); +} + +QThread *SqliteDatabase::readWorkerThread() const +{ + return readDatabaseConnection.connectionThread(); +} + +void SqliteDatabase::handleReadDatabaseConnectionIsOpened() +{ + if (writeDatabaseConnection.isOpen() && readDatabaseConnection.isOpen()) { + initializeTables(); + emit databaseIsOpened(); + } +} + +void SqliteDatabase::handleWriteDatabaseConnectionIsOpened() +{ + readDatabaseConnection.setDatabaseFilePath(databaseFilePath()); +} + +void SqliteDatabase::handleReadDatabaseConnectionIsClosed() +{ + if (!writeDatabaseConnection.isOpen() && !readDatabaseConnection.isOpen()) { + shutdownTables(); + emit databaseIsClosed(); + } +} + +void SqliteDatabase::handleWriteDatabaseConnectionIsClosed() +{ + readDatabaseConnection.close(); +} + +void SqliteDatabase::initializeTables() +{ + for (SqliteTable *table: tables()) + table->initialize(); +} + +void SqliteDatabase::shutdownTables() +{ + for (SqliteTable *table: tables()) + table->shutdown(); +} + + diff --git a/src/libs/sqlite/sqlitedatabase.h b/src/libs/sqlite/sqlitedatabase.h new file mode 100644 index 0000000000..a7d367cf16 --- /dev/null +++ b/src/libs/sqlite/sqlitedatabase.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITEDATABASE_H +#define SQLITEDATABASE_H + +#include <QString> +#include <QVector> + +#include "sqliteglobal.h" +#include "sqlitedatabaseconnectionproxy.h" + +class SqliteTable; + +class SQLITE_EXPORT SqliteDatabase : public QObject +{ + Q_OBJECT + +public: + SqliteDatabase(); + ~SqliteDatabase(); + + void open(); + void close(); + + bool isOpen() const; + + void addTable(SqliteTable *newSqliteTable); + const QVector<SqliteTable *> &tables() const; + + void setDatabaseFilePath(const QString &databaseFilePath); + const QString &databaseFilePath() const; + + void setJournalMode(JournalMode journalMode); + JournalMode journalMode() const; + + QThread *writeWorkerThread() const; + QThread *readWorkerThread() const; + +signals: + void databaseIsOpened(); + void databaseIsClosed(); + +private: + void handleReadDatabaseConnectionIsOpened(); + void handleWriteDatabaseConnectionIsOpened(); + void handleReadDatabaseConnectionIsClosed(); + void handleWriteDatabaseConnectionIsClosed(); + void initializeTables(); + void shutdownTables(); + +private: + SqliteDatabaseConnectionProxy readDatabaseConnection; + SqliteDatabaseConnectionProxy writeDatabaseConnection; + QVector<SqliteTable*> sqliteTables; + QString databaseFilePath_; + JournalMode journalMode_; +}; + +#endif // SQLITEDATABASE_H diff --git a/src/libs/sqlite/sqlitedatabasebackend.cpp b/src/libs/sqlite/sqlitedatabasebackend.cpp new file mode 100644 index 0000000000..c17aab3f72 --- /dev/null +++ b/src/libs/sqlite/sqlitedatabasebackend.cpp @@ -0,0 +1,397 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqlitedatabasebackend.h" + +#include <QThread> +#include <QtDebug> + +#include "sqlite3.h" + +#include "okapi_bm25.h" + +#include "sqliteexception.h" +#include "sqlitestatement.h" +#include "sqlitereadstatement.h" +#include "sqlitewritestatement.h" +#include "sqlitereadwritestatement.h" + +#if defined(Q_OS_UNIX) +#define QTC_THREAD_LOCAL __thread +#elif defined(Q_OS_WIN) +#define QTC_THREAD_LOCAL __declspec(thread) +#else +#define static QTC_THREAD_LOCAL thread_local +#endif + +#define SIZE_OF_BYTEARRAY_ARRAY(array) sizeof(array)/sizeof(QByteArray) + +QTC_THREAD_LOCAL SqliteDatabaseBackend *sqliteDatabaseBackend = nullptr; + +SqliteDatabaseBackend::SqliteDatabaseBackend() + : databaseHandle(nullptr), + cachedTextEncoding(Utf8) +{ + sqliteDatabaseBackend = this; +} + +SqliteDatabaseBackend::~SqliteDatabaseBackend() +{ + closeWithoutException(); + sqliteDatabaseBackend = nullptr; +} + +void SqliteDatabaseBackend::setMmapSize(qint64 defaultSize, qint64 maximumSize) +{ + int resultCode = sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, defaultSize, maximumSize); + checkMmapSizeIsSet(resultCode); +} + +void SqliteDatabaseBackend::activateMultiThreading() +{ + int resultCode = sqlite3_config(SQLITE_CONFIG_MULTITHREAD); + checkIfMultithreadingIsActivated(resultCode); +} + +static void sqliteLog(void*,int errorCode,const char *errorMessage) +{ + qWarning() << sqlite3_errstr(errorCode) << errorMessage; +} + +void SqliteDatabaseBackend::activateLogging() +{ + int resultCode = sqlite3_config(SQLITE_CONFIG_LOG, sqliteLog, nullptr); + checkIfLoogingIsActivated(resultCode); +} + +void SqliteDatabaseBackend::initializeSqliteLibrary() +{ + int resultCode = sqlite3_initialize(); + checkInitializeSqliteLibraryWasSuccesful(resultCode); +} + +void SqliteDatabaseBackend::shutdownSqliteLibrary() +{ + int resultCode = sqlite3_shutdown(); + checkShutdownSqliteLibraryWasSuccesful(resultCode); +} + +void SqliteDatabaseBackend::checkpointFullWalLog() +{ + int resultCode = sqlite3_wal_checkpoint_v2(sqliteDatabaseHandle(), nullptr, SQLITE_CHECKPOINT_FULL, nullptr, nullptr); + checkIfLogCouldBeCheckpointed(resultCode); +} + +void SqliteDatabaseBackend::open(const QString &databaseFilePath) +{ + checkCanOpenDatabase(databaseFilePath); + + QByteArray databaseUtf8Path = databaseFilePath.toUtf8(); + int resultCode = sqlite3_open_v2(databaseUtf8Path.data(), + &databaseHandle, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, + NULL); + + checkDatabaseCouldBeOpened(resultCode); + + registerBusyHandler(); + registerRankingFunction(); + cacheTextEncoding(); +} + +sqlite3 *SqliteDatabaseBackend::sqliteDatabaseHandle() +{ + checkDatabaseBackendIsNotNull(); + checkDatabaseHandleIsNotNull(); + return threadLocalInstance()->databaseHandle; +} + +void SqliteDatabaseBackend::setPragmaValue(const Utf8String &pragmaKey, const Utf8String &newPragmaValue) +{ + SqliteReadWriteStatement::execute(Utf8StringLiteral("PRAGMA ") + pragmaKey + Utf8StringLiteral("='") + newPragmaValue + Utf8StringLiteral("'")); + Utf8String pragmeValueInDatabase = SqliteReadWriteStatement::toValue<Utf8String>(Utf8StringLiteral("PRAGMA ") + pragmaKey); + + checkPragmaValue(pragmeValueInDatabase, newPragmaValue); +} + +Utf8String SqliteDatabaseBackend::pragmaValue(const Utf8String &pragma) const +{ + return SqliteReadWriteStatement::toValue<Utf8String>(Utf8StringLiteral("PRAGMA ") + pragma); +} + +void SqliteDatabaseBackend::setJournalMode(JournalMode journalMode) +{ + setPragmaValue(Utf8StringLiteral("journal_mode"), journalModeToPragma(journalMode)); +} + +JournalMode SqliteDatabaseBackend::journalMode() const +{ + return pragmaToJournalMode(pragmaValue(Utf8StringLiteral("journal_mode"))); +} + +void SqliteDatabaseBackend::setTextEncoding(TextEncoding textEncoding) +{ + setPragmaValue(Utf8StringLiteral("encoding"), textEncodingToPragma(textEncoding)); + cacheTextEncoding(); +} + +TextEncoding SqliteDatabaseBackend::textEncoding() +{ + return cachedTextEncoding; +} + + +Utf8StringVector SqliteDatabaseBackend::columnNames(const Utf8String &tableName) +{ + SqliteReadStatement statement(Utf8StringLiteral("SELECT * FROM ") + tableName); + return statement.columnNames(); +} + +int SqliteDatabaseBackend::changesCount() +{ + return sqlite3_changes(sqliteDatabaseHandle()); +} + +int SqliteDatabaseBackend::totalChangesCount() +{ + return sqlite3_total_changes(sqliteDatabaseHandle()); +} + +void SqliteDatabaseBackend::close() +{ + checkForOpenDatabaseWhichCanBeClosed(); + + int resultCode = sqlite3_close(databaseHandle); + + checkDatabaseClosing(resultCode); + + databaseHandle = nullptr; + +} + +SqliteDatabaseBackend *SqliteDatabaseBackend::threadLocalInstance() +{ + checkDatabaseBackendIsNotNull(); + return sqliteDatabaseBackend; +} + +bool SqliteDatabaseBackend::databaseIsOpen() const +{ + return databaseHandle != nullptr; +} + +void SqliteDatabaseBackend::closeWithoutException() +{ + if (databaseHandle) { + int resultCode = sqlite3_close_v2(databaseHandle); + databaseHandle = nullptr; + if (resultCode != SQLITE_OK) + qWarning() << "SqliteDatabaseBackend::closeWithoutException: Unexpected error at closing the database!"; + } +} + +void SqliteDatabaseBackend::registerBusyHandler() +{ + sqlite3_busy_handler(sqliteDatabaseHandle(), &busyHandlerCallback, nullptr); +} + +void SqliteDatabaseBackend::registerRankingFunction() +{ + sqlite3_create_function_v2(sqliteDatabaseHandle(), "okapi_bm25", -1, SQLITE_ANY, 0, okapi_bm25, 0, 0, 0); + sqlite3_create_function_v2(sqliteDatabaseHandle(), "okapi_bm25f", -1, SQLITE_UTF8, 0, okapi_bm25f, 0, 0, 0); + sqlite3_create_function_v2(sqliteDatabaseHandle(), "okapi_bm25f_kb", -1, SQLITE_UTF8, 0, okapi_bm25f_kb, 0, 0, 0); +} + +int SqliteDatabaseBackend::busyHandlerCallback(void *, int counter) +{ + Q_UNUSED(counter); +#ifdef QT_DEBUG + //qWarning() << "Busy handler invoked" << counter << "times!"; +#endif + QThread::msleep(10); + + return true; +} + +void SqliteDatabaseBackend::cacheTextEncoding() +{ + cachedTextEncoding = pragmaToTextEncoding(pragmaValue(Utf8StringLiteral("encoding"))); +} + +void SqliteDatabaseBackend::checkForOpenDatabaseWhichCanBeClosed() +{ + if (databaseHandle == nullptr) + throwException("SqliteDatabaseBackend::close: database is not open so it can not be closed."); +} + +void SqliteDatabaseBackend::checkDatabaseClosing(int resultCode) +{ + switch (resultCode) { + case SQLITE_OK: return; + default: throwException("SqliteDatabaseBackend::close: unknown error happens at closing!"); + } +} + +void SqliteDatabaseBackend::checkCanOpenDatabase(const QString &databaseFilePath) +{ + if (databaseFilePath.isEmpty()) + throw SqliteException("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened:", "database file path is empty!"); + + if (databaseIsOpen()) + throw SqliteException("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened:", "database is already open!"); +} + +void SqliteDatabaseBackend::checkDatabaseCouldBeOpened(int resultCode) +{ + switch (resultCode) { + case SQLITE_OK: + return; + default: + closeWithoutException(); + throw SqliteException("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened:", sqlite3_errmsg(sqliteDatabaseHandle())); + } +} + +void SqliteDatabaseBackend::checkPragmaValue(const Utf8String &databaseValue, const Utf8String &expectedValue) +{ + if (databaseValue != expectedValue) + throwException("SqliteDatabaseBackend::setPragmaValue: pragma value is not set!"); +} + +void SqliteDatabaseBackend::checkDatabaseHandleIsNotNull() +{ + if (sqliteDatabaseBackend->databaseHandle == nullptr) + throwException("SqliteDatabaseBackend: database is not open!"); +} + +void SqliteDatabaseBackend::checkDatabaseBackendIsNotNull() +{ + if (sqliteDatabaseBackend == nullptr) + throwException("SqliteDatabaseBackend: database backend is not initialized!"); +} + +void SqliteDatabaseBackend::checkIfMultithreadingIsActivated(int resultCode) +{ + if (resultCode != SQLITE_OK) + throwException("SqliteDatabaseBackend::activateMultiThreading: multithreading can't be activated!"); +} + +void SqliteDatabaseBackend::checkIfLoogingIsActivated(int resultCode) +{ + if (resultCode != SQLITE_OK) + throwException("SqliteDatabaseBackend::activateLogging: logging can't be activated!"); +} + +void SqliteDatabaseBackend::checkMmapSizeIsSet(int resultCode) +{ + if (resultCode != SQLITE_OK) + throwException("SqliteDatabaseBackend::checkMmapSizeIsSet: mmap size can't be changed!"); +} + +void SqliteDatabaseBackend::checkInitializeSqliteLibraryWasSuccesful(int resultCode) +{ + if (resultCode != SQLITE_OK) + throwException("SqliteDatabaseBackend::initializeSqliteLibrary: SqliteLibrary cannot initialized!"); +} + +void SqliteDatabaseBackend::checkShutdownSqliteLibraryWasSuccesful(int resultCode) +{ + if (resultCode != SQLITE_OK) + throwException("SqliteDatabaseBackend::shutdownSqliteLibrary: SqliteLibrary cannot be shutdowned!"); +} + +void SqliteDatabaseBackend::checkIfLogCouldBeCheckpointed(int resultCode) +{ + if (resultCode != SQLITE_OK) + throwException("SqliteDatabaseBackend::checkpointFullWalLog: WAL log could not be checkpointed!"); +} + +int SqliteDatabaseBackend::indexOfPragma(const Utf8String pragma, const Utf8String pragmas[], size_t pragmaCount) +{ + for (unsigned int index = 0; index < pragmaCount; index++) { + if (pragma == pragmas[index]) + return int(index); + } + + return -1; + +} + +static const Utf8String journalModeStrings[] = { + Utf8StringLiteral("delete"), + Utf8StringLiteral("truncate"), + Utf8StringLiteral("persist"), + Utf8StringLiteral("memory"), + Utf8StringLiteral("wal") +}; + +const Utf8String &SqliteDatabaseBackend::journalModeToPragma(JournalMode journalMode) +{ + return journalModeStrings[int(journalMode)]; +} + +JournalMode SqliteDatabaseBackend::pragmaToJournalMode(const Utf8String &pragma) +{ + int index = indexOfPragma(pragma, journalModeStrings, SIZE_OF_BYTEARRAY_ARRAY(journalModeStrings)); + + if (index < 0) + throwException("SqliteDatabaseBackend::pragmaToJournalMode: pragma can't be transformed in a journal mode enumeration!"); + + return static_cast<JournalMode>(index); +} + +static const Utf8String textEncodingStrings[] = { + Utf8StringLiteral("UTF-8"), + Utf8StringLiteral("UTF-16le"), + Utf8StringLiteral("UTF-16be") +}; + +const Utf8String &SqliteDatabaseBackend::textEncodingToPragma(TextEncoding textEncoding) +{ + return textEncodingStrings[textEncoding]; +} + +TextEncoding SqliteDatabaseBackend::pragmaToTextEncoding(const Utf8String &pragma) +{ + int index = indexOfPragma(pragma, textEncodingStrings, SIZE_OF_BYTEARRAY_ARRAY(textEncodingStrings)); + + if (index < 0) + throwException("SqliteDatabaseBackend::pragmaToTextEncoding: pragma can't be transformed in a text encoding enumeration!"); + + return static_cast<TextEncoding>(index); +} + +void SqliteDatabaseBackend::throwException(const char *whatHasHappens) +{ + if (sqliteDatabaseBackend && sqliteDatabaseBackend->databaseHandle) + throw SqliteException(whatHasHappens, sqlite3_errmsg(sqliteDatabaseBackend->databaseHandle)); + else + throw SqliteException(whatHasHappens); +} diff --git a/src/libs/sqlite/sqlitedatabasebackend.h b/src/libs/sqlite/sqlitedatabasebackend.h new file mode 100644 index 0000000000..5b1b21788c --- /dev/null +++ b/src/libs/sqlite/sqlitedatabasebackend.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITEDATABASEBACKEND_H +#define SQLITEDATABASEBACKEND_H + +#include <QStringList> + +#include "sqliteglobal.h" + +#include "utf8stringvector.h" + +struct sqlite3; + +class SQLITE_EXPORT SqliteDatabaseBackend +{ +public: + + SqliteDatabaseBackend(); + ~SqliteDatabaseBackend(); + + static void setMmapSize(qint64 defaultSize, qint64 maximumSize); + static void activateMultiThreading(); + static void activateLogging(); + static void initializeSqliteLibrary(); + static void shutdownSqliteLibrary(); + static void checkpointFullWalLog(); + + void open(const QString &databaseFilePath); + void close(); + void closeWithoutException(); + + static SqliteDatabaseBackend *threadLocalInstance(); + static sqlite3* sqliteDatabaseHandle(); + + void setJournalMode(JournalMode journalMode); + JournalMode journalMode() const; + + void setTextEncoding(TextEncoding textEncoding); + TextEncoding textEncoding(); + + + + static Utf8StringVector columnNames(const Utf8String &tableName); + + static int changesCount(); + static int totalChangesCount(); + +protected: + bool databaseIsOpen() const; + + void setPragmaValue(const Utf8String &pragma, const Utf8String &value); + Utf8String pragmaValue(const Utf8String &pragma) const; + + void registerBusyHandler(); + void registerRankingFunction(); + static int busyHandlerCallback(void*, int counter); + + void cacheTextEncoding(); + + void checkForOpenDatabaseWhichCanBeClosed(); + void checkDatabaseClosing(int resultCode); + void checkCanOpenDatabase(const QString &databaseFilePath); + void checkDatabaseCouldBeOpened(int resultCode); + void checkPragmaValue(const Utf8String &databaseValue, const Utf8String &expectedValue); + static void checkDatabaseHandleIsNotNull(); + static void checkDatabaseBackendIsNotNull(); + static void checkIfMultithreadingIsActivated(int resultCode); + static void checkIfLoogingIsActivated(int resultCode); + static void checkMmapSizeIsSet(int resultCode); + static void checkInitializeSqliteLibraryWasSuccesful(int resultCode); + static void checkShutdownSqliteLibraryWasSuccesful(int resultCode); + static void checkIfLogCouldBeCheckpointed(int resultCode); + + static int indexOfPragma(const Utf8String pragma, const Utf8String pragmas[], size_t pragmaCount); + static const Utf8String &journalModeToPragma(JournalMode journalMode); + static JournalMode pragmaToJournalMode(const Utf8String &pragma); + static const Utf8String &textEncodingToPragma(TextEncoding textEncoding); + static TextEncoding pragmaToTextEncoding(const Utf8String &pragma); + + Q_NORETURN static void throwException(const char *whatHasHappens); + +private: + sqlite3 *databaseHandle; + TextEncoding cachedTextEncoding; + +}; + +#endif // SQLITEDATABASEBACKEND_H diff --git a/src/libs/sqlite/sqlitedatabaseconnection.cpp b/src/libs/sqlite/sqlitedatabaseconnection.cpp new file mode 100644 index 0000000000..29e1d19fec --- /dev/null +++ b/src/libs/sqlite/sqlitedatabaseconnection.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqlitedatabaseconnection.h" + +#include <sqlite3.h> + +#include <QtDebug> + +#ifdef Q_OS_LINUX +#include <sys/resource.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/syscall.h> +#endif + +#include "sqliteexception.h" +#include "sqliteglobal.h" + +SqliteDatabaseConnection::SqliteDatabaseConnection(QObject *parent) : + QObject(parent) +{ +} + +SqliteDatabaseConnection::~SqliteDatabaseConnection() +{ + +} + +sqlite3 *SqliteDatabaseConnection::currentSqliteDatabase() +{ + return SqliteDatabaseBackend::sqliteDatabaseHandle(); +} + +void SqliteDatabaseConnection::setDatabaseFilePath(const QString &databaseFilePath) +{ + + prioritizeThreadDown(); + + try { + databaseBackend.open(databaseFilePath); + + emit databaseConnectionIsOpened(); + } catch (SqliteException &exception) { + exception.printWarning(); + } +} + +void SqliteDatabaseConnection::setJournalMode(JournalMode journalMode) +{ + try { + databaseBackend.setJournalMode(journalMode); + } catch (SqliteException &exception) { + exception.printWarning(); + } +} + +void SqliteDatabaseConnection::close() +{ + databaseBackend.closeWithoutException(); + + emit databaseConnectionIsClosed(); +} + +void SqliteDatabaseConnection::prioritizeThreadDown() +{ +#ifdef Q_OS_LINUX + pid_t processId = syscall(SYS_gettid); + int returnCode = setpriority(PRIO_PROCESS, processId, 10); + if (returnCode == -1) + qWarning() << "cannot renice" << strerror(errno); +#endif +} diff --git a/src/libs/sqlite/sqlitedatabaseconnection.h b/src/libs/sqlite/sqlitedatabaseconnection.h new file mode 100644 index 0000000000..548bcb32ce --- /dev/null +++ b/src/libs/sqlite/sqlitedatabaseconnection.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITEDATABASECONNECTIONCONTROLLER_H +#define SQLITEDATABASECONNECTIONCONTROLLER_H + +#include <QObject> + +#include "sqlitedatabasebackend.h" + +struct sqlite3; + +class SQLITE_EXPORT SqliteDatabaseConnection final : public QObject +{ + Q_OBJECT +public: + explicit SqliteDatabaseConnection(QObject *parent = 0); + ~SqliteDatabaseConnection(); + + static sqlite3 *currentSqliteDatabase(); + +public slots: + void setDatabaseFilePath(const QString &databaseName); + void setJournalMode(JournalMode journalMode); + void close(); + +protected: + void prioritizeThreadDown(); + +signals: + void databaseConnectionIsOpened(); + void databaseConnectionIsClosed(); + +private: + SqliteDatabaseBackend databaseBackend; +}; + +#endif // SQLITEDATABASECONNECTIONCONTROLLER_H diff --git a/src/libs/sqlite/sqlitedatabaseconnectionproxy.cpp b/src/libs/sqlite/sqlitedatabaseconnectionproxy.cpp new file mode 100644 index 0000000000..994b5e028d --- /dev/null +++ b/src/libs/sqlite/sqlitedatabaseconnectionproxy.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqlitedatabaseconnectionproxy.h" + +#include "sqlitedatabaseconnection.h" +#include "sqliteworkerthread.h" + +#include <QCoreApplication> + + +SqliteDatabaseConnectionProxy::SqliteDatabaseConnectionProxy(const QString &threadName) : + QObject(), + databaseConnectionIsOpen(false) +{ + + databaseConnectionThread = new SqliteWorkerThread; + databaseConnectionThread->setObjectName(threadName); + + databaseConnectionThread->start(QThread::LowPriority); + + SqliteDatabaseConnection *connection = databaseConnectionThread->databaseConnection(); + + + connect(this, &SqliteDatabaseConnectionProxy::setDatabaseFilePath, connection, &SqliteDatabaseConnection::setDatabaseFilePath); + connect(this, &SqliteDatabaseConnectionProxy::setJournalMode, connection, &SqliteDatabaseConnection::setJournalMode); + connect(this, &SqliteDatabaseConnectionProxy::close, connection, &SqliteDatabaseConnection::close); + + connect(connection, &SqliteDatabaseConnection::databaseConnectionIsOpened, this, &SqliteDatabaseConnectionProxy::handleDatabaseConnectionIsOpened); + connect(connection, &SqliteDatabaseConnection::databaseConnectionIsClosed, this, &SqliteDatabaseConnectionProxy::handleDatabaseConnectionIsClosed); + +} + +SqliteDatabaseConnectionProxy::~SqliteDatabaseConnectionProxy() +{ + if (databaseConnectionThread) { + databaseConnectionThread->quit(); + databaseConnectionThread->wait(); + databaseConnectionThread->deleteLater(); + } +} + +QThread *SqliteDatabaseConnectionProxy::connectionThread() const +{ + return databaseConnectionThread; +} + +bool SqliteDatabaseConnectionProxy::isOpen() const +{ + return databaseConnectionIsOpen; +} + +void SqliteDatabaseConnectionProxy::registerTypes() +{ + qRegisterMetaType<JournalMode>("JournalMode"); +} + +void SqliteDatabaseConnectionProxy::handleDatabaseConnectionIsOpened() +{ + databaseConnectionIsOpen = true; + + emit connectionIsOpened(); +} + +void SqliteDatabaseConnectionProxy::handleDatabaseConnectionIsClosed() +{ + databaseConnectionIsOpen = false; + + emit connectionIsClosed(); +} diff --git a/src/libs/sqlite/sqlitedatabaseconnectionproxy.h b/src/libs/sqlite/sqlitedatabaseconnectionproxy.h new file mode 100644 index 0000000000..21885645e5 --- /dev/null +++ b/src/libs/sqlite/sqlitedatabaseconnectionproxy.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITEDATABASECONNECTION_H +#define SQLITEDATABASECONNECTION_H + +#include <QObject> +#include <QPointer> + +#include <sqliteglobal.h> + +struct sqlite3; +class SqliteWorkerThread; + +class SQLITE_EXPORT SqliteDatabaseConnectionProxy final : public QObject +{ + Q_OBJECT +public: + explicit SqliteDatabaseConnectionProxy(const QString &threadName); + ~SqliteDatabaseConnectionProxy(); + + QThread *connectionThread() const; + + bool isOpen() const; + + static void registerTypes(); + +signals: + void setDatabaseFilePath(const QString &databaseFilePath); + void setJournalMode(JournalMode journal); + void connectionIsOpened(); + void connectionIsClosed(); + void close(); + +private slots: + void handleDatabaseConnectionIsOpened(); + void handleDatabaseConnectionIsClosed(); + +private: + QPointer<SqliteWorkerThread> databaseConnectionThread; + bool databaseConnectionIsOpen; +}; + +#endif // SQLITEDATABASECONNECTION_H diff --git a/src/libs/sqlite/sqliteexception.cpp b/src/libs/sqlite/sqliteexception.cpp new file mode 100644 index 0000000000..fde46941b6 --- /dev/null +++ b/src/libs/sqlite/sqliteexception.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqliteexception.h" + +#include <QtDebug> + +SqliteException::SqliteException(const char *whatErrorHasHappen, const char *sqliteErrorMessage) + : whatErrorHasHappen(whatErrorHasHappen), + sqliteErrorMessage_(sqliteErrorMessage) +{ +} + +void SqliteException::printWarning() const +{ + if (!sqliteErrorMessage_.isEmpty()) + qWarning() << whatErrorHasHappen << sqliteErrorMessage_; + else + qWarning() << whatErrorHasHappen; +} + diff --git a/src/libs/sqlite/sqliteexception.h b/src/libs/sqlite/sqliteexception.h new file mode 100644 index 0000000000..beab962c6e --- /dev/null +++ b/src/libs/sqlite/sqliteexception.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITEEXCEPTION_H +#define SQLITEEXCEPTION_H + +#include <QByteArray> + +#include "sqliteglobal.h" + +class SQLITE_EXPORT SqliteException +{ +public: + SqliteException(const char *whatErrorHasHappen, const char *sqliteErrorMessage = 0); + + void printWarning() const; + +private: + const char *whatErrorHasHappen; + QByteArray sqliteErrorMessage_; +}; + +#endif // SQLITEEXCEPTION_H diff --git a/src/libs/sqlite/sqliteglobal.cpp b/src/libs/sqlite/sqliteglobal.cpp new file mode 100644 index 0000000000..74e76aab5a --- /dev/null +++ b/src/libs/sqlite/sqliteglobal.cpp @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqliteglobal.h" + +#include "createtablecommand.h" + +namespace Sqlite { + +void registerTypes() +{ + Internal::CreateTableCommand::registerType(); + + qRegisterMetaType<JournalMode>("JournalMode"); +} + +} diff --git a/src/libs/sqlite/sqliteglobal.h b/src/libs/sqlite/sqliteglobal.h new file mode 100644 index 0000000000..0b14b21a4b --- /dev/null +++ b/src/libs/sqlite/sqliteglobal.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITEGLOBAL_H +#define SQLITEGLOBAL_H + +#include <QtGlobal> + +#if defined(BUILD_SQLITE_LIBRARY) +# define SQLITE_EXPORT Q_DECL_EXPORT +#elif defined(BUILD_SQLITE_STATIC_LIBRARY) +# define SQLITE_EXPORT +#else +# define SQLITE_EXPORT Q_DECL_IMPORT +#endif + + +namespace Sqlite { +SQLITE_EXPORT void registerTypes(); +} + +enum class ColumnType { + Numeric, + Integer, + Real, + Text, + None +}; + +enum class ColumnConstraint { + PrimaryKey +}; + +enum class JournalMode { + Delete, + Truncate, + Persist, + Memory, + Wal +}; + +enum TextEncoding { + Utf8, + Utf16le, + Utf16be, +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + Utf16 = Utf16le +#else + Utf16 = Utf16be +#endif + +}; + +QT_BEGIN_NAMESPACE +template <typename T> class QVector; +template <typename T> class QSet; +template <class Key, class T> class QHash; +template <class Key, class T> class QMap; +class QVariant; +QT_END_NAMESPACE + +class Utf8String; +class Utf8StringVector; + +typedef QMap<Utf8String, QVariant> RowDictionary; +typedef QVector<RowDictionary> RowDictionaries; + + +#endif // SQLITEGLOBAL_H diff --git a/src/libs/sqlite/sqlitereadstatement.cpp b/src/libs/sqlite/sqlitereadstatement.cpp new file mode 100644 index 0000000000..e04b577d39 --- /dev/null +++ b/src/libs/sqlite/sqlitereadstatement.cpp @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqlitereadstatement.h" + +#include "sqlite3.h" + +SqliteReadStatement::SqliteReadStatement(const Utf8String &sqlStatementUtf8) + : SqliteStatement(sqlStatementUtf8) +{ + checkIsReadOnlyStatement(); +} + +void SqliteReadStatement::checkIsReadOnlyStatement() +{ + if (!isReadOnlyStatement()) + throwException("SqliteStatement::SqliteReadStatement: is not read only statement!"); +} diff --git a/src/libs/sqlite/sqlitereadstatement.h b/src/libs/sqlite/sqlitereadstatement.h new file mode 100644 index 0000000000..abc1ea80dc --- /dev/null +++ b/src/libs/sqlite/sqlitereadstatement.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITEREADSTATEMENT_H +#define SQLITEREADSTATEMENT_H + +#include "sqlitestatement.h" + +class SQLITE_EXPORT SqliteReadStatement final : private SqliteStatement +{ +public: + explicit SqliteReadStatement(const Utf8String &sqlStatementUtf8); + + using SqliteStatement::next; + using SqliteStatement::reset; + using SqliteStatement::value; + using SqliteStatement::values; + using SqliteStatement::rowColumnValueMap; + using SqliteStatement::twoColumnValueMap; + using SqliteStatement::columnCount; + using SqliteStatement::columnNames; + using SqliteStatement::bind; + using SqliteStatement::bindingIndexForName; + using SqliteStatement::setBindingColumnNames; + using SqliteStatement::bindingColumnNames; + using SqliteStatement::toValue; + +protected: + void checkIsReadOnlyStatement(); +}; + +#endif // SQLITEREADSTATEMENT_H diff --git a/src/libs/sqlite/sqlitereadwritestatement.cpp b/src/libs/sqlite/sqlitereadwritestatement.cpp new file mode 100644 index 0000000000..1427a83a0d --- /dev/null +++ b/src/libs/sqlite/sqlitereadwritestatement.cpp @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqlitereadwritestatement.h" + + +SqliteReadWriteStatement::SqliteReadWriteStatement(const Utf8String &sqlStatementUft8) + : SqliteStatement(sqlStatementUft8) +{ +} + diff --git a/src/libs/sqlite/sqlitereadwritestatement.h b/src/libs/sqlite/sqlitereadwritestatement.h new file mode 100644 index 0000000000..02825fc295 --- /dev/null +++ b/src/libs/sqlite/sqlitereadwritestatement.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITEREADWRITESTATEMENT_H +#define SQLITEREADWRITESTATEMENT_H + +#include "sqlitestatement.h" + +class SQLITE_EXPORT SqliteReadWriteStatement final : private SqliteStatement +{ +public: + explicit SqliteReadWriteStatement(const Utf8String &sqlStatementUft8); + + using SqliteStatement::next; + using SqliteStatement::step; + using SqliteStatement::reset; + using SqliteStatement::bind; + using SqliteStatement::bindingIndexForName; + using SqliteStatement::setBindingColumnNames; + using SqliteStatement::bindingColumnNames; + using SqliteStatement::write; + using SqliteStatement::value; + using SqliteStatement::values; + using SqliteStatement::rowColumnValueMap; + using SqliteStatement::columnCount; + using SqliteStatement::columnNames; + using SqliteStatement::toValue; + using SqliteStatement::execute; +}; + +#endif // SQLITEREADWRITESTATEMENT_H diff --git a/src/libs/sqlite/sqlitestatement.cpp b/src/libs/sqlite/sqlitestatement.cpp new file mode 100644 index 0000000000..4b8e3338a4 --- /dev/null +++ b/src/libs/sqlite/sqlitestatement.cpp @@ -0,0 +1,676 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqlitestatement.h" + +#include <QMutex> +#include <QWaitCondition> +#include <QVariant> +#include <QtGlobal> + +#include "sqlite3.h" + +#include "sqlitedatabasebackend.h" +#include "sqliteexception.h" + +#if defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wignored-qualifiers" +#endif + +SqliteStatement::SqliteStatement(const Utf8String &sqlStatementUtf8) + : compiledStatement(nullptr, deleteCompiledStatement), + bindingParameterCount(0), + columnCount_(0), + isReadyToFetchValues(false) +{ + prepare(sqlStatementUtf8); + setBindingParameterCount(); + setBindingColumnNamesFromStatement(); + setColumnCount(); +} + +void SqliteStatement::deleteCompiledStatement(sqlite3_stmt *compiledStatement) +{ + if (compiledStatement) + sqlite3_finalize(compiledStatement); +} + +class UnlockNotification { + +public: + UnlockNotification() : fired(false) {}; + + static void unlockNotifyCallBack(void **arguments, int argumentCount) + { + for (int index = 0; index < argumentCount; index++) { + UnlockNotification *unlockNotification = static_cast<UnlockNotification *>(arguments[index]); + unlockNotification->wakeupWaitCondition(); + } + } + + void wakeupWaitCondition() + { + mutex.lock(); + fired = 1; + waitCondition.wakeAll(); + mutex.unlock(); + } + + void wait() + { + mutex.lock(); + + if (!fired) { + waitCondition.wait(&mutex); + } + + mutex.unlock(); + } + +private: + bool fired; + QWaitCondition waitCondition; + QMutex mutex; +}; + +void SqliteStatement::waitForUnlockNotify() const +{ + UnlockNotification unlockNotification; + int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(), UnlockNotification::unlockNotifyCallBack, &unlockNotification); + + if (resultCode == SQLITE_OK) + unlockNotification.wait(); + else + throwException("SqliteStatement::waitForUnlockNotify: database is in a dead lock!"); +} + +void SqliteStatement::reset() const +{ + int resultCode = sqlite3_reset(compiledStatement.get()); + if (resultCode != SQLITE_OK) + throwException("SqliteStatement::reset: can't reset statement!"); + + isReadyToFetchValues = false; +} + +bool SqliteStatement::next() const +{ + int resultCode; + + do { + resultCode = sqlite3_step(compiledStatement.get()); + if (resultCode == SQLITE_LOCKED) { + waitForUnlockNotify(); + sqlite3_reset(compiledStatement.get()); + } + + } while (resultCode == SQLITE_LOCKED); + + setIfIsReadyToFetchValues(resultCode); + + return checkForStepError(resultCode); +} + +void SqliteStatement::step() const +{ + next(); +} + +void SqliteStatement::write(const RowDictionary &rowDictionary) +{ + bind(rowDictionary); + step(); + reset(); +} + +void SqliteStatement::writeUnchecked(const RowDictionary &rowDictionary) +{ + bindUnchecked(rowDictionary); + step(); + reset(); +} + +int SqliteStatement::columnCount() const +{ + return columnCount_; +} + +Utf8StringVector SqliteStatement::columnNames() const +{ + Utf8StringVector columnNames; + int columnCount = SqliteStatement::columnCount(); + columnNames.reserve(columnCount); + for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) + columnNames.append(Utf8String(sqlite3_column_origin_name(compiledStatement.get(), columnIndex), -1)); + + return columnNames; +} + +void SqliteStatement::bind(int index, int value) +{ + int resultCode = sqlite3_bind_int(compiledStatement.get(), index, value); + if (resultCode != SQLITE_OK) + throwException("SqliteStatement::bind: cant' bind 32 bit integer!"); +} + +void SqliteStatement::bind(int index, qint64 value) +{ + int resultCode = sqlite3_bind_int64(compiledStatement.get(), index, value); + if (resultCode != SQLITE_OK) + throwException("SqliteStatement::bind: cant' bind 64 bit integer!"); +} + +void SqliteStatement::bind(int index, double value) +{ + int resultCode = sqlite3_bind_double(compiledStatement.get(), index, value); + if (resultCode != SQLITE_OK) + throwException("SqliteStatement::bind: cant' bind double!"); +} + +void SqliteStatement::bind(int index, const QString &text) +{ + int resultCode; + if (databaseTextEncoding() == Utf8) { + QByteArray textUtf8 = text.toUtf8(); + resultCode = sqlite3_bind_text(compiledStatement.get(), index, textUtf8.constData(), textUtf8.size(), SQLITE_TRANSIENT); + } else { + resultCode = sqlite3_bind_text16(compiledStatement.get(), index, text.constData(), text.size() * 2, SQLITE_TRANSIENT); + } + + if (resultCode != SQLITE_OK) + throwException("SqliteStatement::bind: cant' not bind text!"); +} + +void SqliteStatement::bind(int index, const QByteArray &blob) +{ + sqlite3_bind_blob(compiledStatement.get(), index, blob.constData(), blob.size(), SQLITE_TRANSIENT); +} + +void SqliteStatement::bind(int index, const QVariant &value) +{ + checkBindingIndex(index); + + switch (value.type()) { + case QVariant::Bool: + case QVariant::Int: + bind(index, value.toInt()); + break; + case QVariant::UInt: + case QVariant::LongLong: + case QVariant::ULongLong: + bind(index, value.toLongLong()); + break; + case QVariant::Double: + bind(index, value.toDouble()); + break; + case QVariant::String: + bind(index, value.toString()); + break; + case QVariant::ByteArray: + bind(index, value.toByteArray()); + break; + default: + sqlite3_bind_null(compiledStatement.get(), index); + } +} + +template <typename Type> +void SqliteStatement::bind(const Utf8String &name, const Type &value) +{ + int index = bindingIndexForName(name); + checkBindingName(index); + bind(index, value); +} + +template SQLITE_EXPORT void SqliteStatement::bind(const Utf8String &name, const int &value); +template SQLITE_EXPORT void SqliteStatement::bind(const Utf8String &name, const qint64 &value); +template SQLITE_EXPORT void SqliteStatement::bind(const Utf8String &name, const double &value); +template SQLITE_EXPORT void SqliteStatement::bind(const Utf8String &name, const QString &text); +template SQLITE_EXPORT void SqliteStatement::bind(const Utf8String &name, const QByteArray &blob); +template SQLITE_EXPORT void SqliteStatement::bind(const Utf8String &name, const QVariant &value); + +int SqliteStatement::bindingIndexForName(const Utf8String &name) +{ + return sqlite3_bind_parameter_index(compiledStatement.get(), name.constData()); +} + +void SqliteStatement::bind(const RowDictionary &rowDictionary) +{ + checkBindingValueMapIsEmpty(rowDictionary); + + int columnIndex = 1; + foreach (const Utf8String &columnName, bindingColumnNames_) { + checkParameterCanBeBound(rowDictionary, columnName); + QVariant value = rowDictionary.value(columnName); + bind(columnIndex, value); + columnIndex += 1; + } +} + +void SqliteStatement::bindUnchecked(const RowDictionary &rowDictionary) +{ + checkBindingValueMapIsEmpty(rowDictionary); + + int columnIndex = 1; + foreach (const Utf8String &columnName, bindingColumnNames_) { + if (rowDictionary.contains(columnName)) { + QVariant value = rowDictionary.value(columnName); + bind(columnIndex, value); + } + columnIndex += 1; + } +} + +void SqliteStatement::setBindingColumnNames(const Utf8StringVector &bindingColumnNames) +{ + bindingColumnNames_ = bindingColumnNames; +} + +const Utf8StringVector &SqliteStatement::bindingColumnNames() const +{ + return bindingColumnNames_; +} + +void SqliteStatement::execute(const Utf8String &sqlStatementUtf8) +{ + SqliteStatement statement(sqlStatementUtf8); + statement.step(); +} + +void SqliteStatement::prepare(const Utf8String &sqlStatementUtf8) +{ + int resultCode; + + do { + sqlite3_stmt *sqliteStatement = nullptr; + resultCode = sqlite3_prepare_v2(sqliteDatabaseHandle(), sqlStatementUtf8.constData(), sqlStatementUtf8.byteSize(), &sqliteStatement, nullptr); + compiledStatement.reset(sqliteStatement); + + if (resultCode == SQLITE_LOCKED) + waitForUnlockNotify(); + + } while (resultCode == SQLITE_LOCKED); + + checkForPrepareError(resultCode); +} + +sqlite3 *SqliteStatement::sqliteDatabaseHandle() +{ +return SqliteDatabaseBackend::sqliteDatabaseHandle(); +} + +TextEncoding SqliteStatement::databaseTextEncoding() +{ + if (SqliteDatabaseBackend::threadLocalInstance()) + return SqliteDatabaseBackend::threadLocalInstance()->textEncoding(); + + throwException("SqliteStatement::databaseTextEncoding: database backend instance is null!"); + + Q_UNREACHABLE(); +} + +bool SqliteStatement::checkForStepError(int resultCode) const +{ + switch (resultCode) { + case SQLITE_ROW: return true; + case SQLITE_DONE: return false; + case SQLITE_BUSY: throwException("SqliteStatement::stepStatement: database engine was unable to acquire the database locks!"); + case SQLITE_ERROR : throwException("SqliteStatement::stepStatement: run-time error (such as a constraint violation) has occurred!"); + case SQLITE_MISUSE: throwException("SqliteStatement::stepStatement: was called inappropriately!"); + case SQLITE_CONSTRAINT: throwException("SqliteStatement::stepStatement: contraint prevent insert or update!"); + } + + throwException("SqliteStatement::stepStatement: unknown error has happen!"); + + Q_UNREACHABLE(); +} + +void SqliteStatement::checkForPrepareError(int resultCode) const +{ + switch (resultCode) { + case SQLITE_OK: return; + case SQLITE_BUSY: throwException("SqliteStatement::prepareStatement: database engine was unable to acquire the database locks!"); + case SQLITE_ERROR : throwException("SqliteStatement::prepareStatement: run-time error (such as a constraint violation) has occurred!"); + case SQLITE_MISUSE: throwException("SqliteStatement::prepareStatement: was called inappropriately!"); + } + + throwException("SqliteStatement::prepareStatement: unknown error has happen!"); +} + +void SqliteStatement::setIfIsReadyToFetchValues(int resultCode) const +{ + if (resultCode == SQLITE_ROW) + isReadyToFetchValues = true; + else + isReadyToFetchValues = false; + +} + +void SqliteStatement::checkIfIsReadyToFetchValues() const +{ + if (!isReadyToFetchValues) + throwException("SqliteStatement::value: there are no values to fetch!"); +} + +void SqliteStatement::checkColumnsAreValid(const QVector<int> &columns) const +{ + foreach (int column, columns) { + if (column < 0 || column >= columnCount_) + throwException("SqliteStatement::values: column index out of bound!"); + } +} + +void SqliteStatement::checkColumnIsValid(int column) const +{ + if (column < 0 || column >= columnCount_) + throwException("SqliteStatement::values: column index out of bound!"); +} + +void SqliteStatement::checkBindingIndex(int index) const +{ + if (index <= 0 || index > bindingParameterCount) + throwException("SqliteStatement::bind: binding index is out of bound!"); +} + +void SqliteStatement::checkBindingName(int index) const +{ + if (index <= 0 || index > bindingParameterCount) + throwException("SqliteStatement::bind: binding name are not exists in this statement!"); +} + +void SqliteStatement::checkParameterCanBeBound(const RowDictionary &rowDictionary, const Utf8String &columnName) +{ + if (!rowDictionary.contains(columnName)) + throwException("SqliteStatement::bind: Not all parameters are bound!"); +} + +void SqliteStatement::setBindingParameterCount() +{ + bindingParameterCount = sqlite3_bind_parameter_count(compiledStatement.get()); +} + +Utf8String chopFirstLetter(const char *rawBindingName) +{ + QByteArray bindingName(rawBindingName); + bindingName = bindingName.mid(1); + + return Utf8String::fromByteArray(bindingName); +} + +void SqliteStatement::setBindingColumnNamesFromStatement() +{ + for (int index = 1; index <= bindingParameterCount; index++) { + Utf8String bindingName = chopFirstLetter(sqlite3_bind_parameter_name(compiledStatement.get(), index)); + bindingColumnNames_.append(bindingName); + } +} + +void SqliteStatement::setColumnCount() +{ + columnCount_ = sqlite3_column_count(compiledStatement.get()); +} + +void SqliteStatement::checkBindingValueMapIsEmpty(const RowDictionary &rowDictionary) const +{ + if (rowDictionary.isEmpty()) + throwException("SqliteStatement::bind: can't bind empty row!"); +} + +bool SqliteStatement::isReadOnlyStatement() const +{ + return sqlite3_stmt_readonly(compiledStatement.get()); +} + +void SqliteStatement::throwException(const char *whatHasHappened) +{ + throw SqliteException(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); +} + +QString SqliteStatement::columnName(int column) const +{ + return QString::fromUtf8(sqlite3_column_name(compiledStatement.get(), column)); +} + +static bool columnIsBlob(sqlite3_stmt *sqlStatment, int column) +{ + return sqlite3_column_type(sqlStatment, column) == SQLITE_BLOB; +} + +static QByteArray byteArrayForColumn(sqlite3_stmt *sqlStatment, int column) +{ + if (columnIsBlob(sqlStatment, column)) { + const char *blob = static_cast<const char*>(sqlite3_column_blob(sqlStatment, column)); + int size = sqlite3_column_bytes(sqlStatment, column); + + return QByteArray(blob, size); + } + + return QByteArray(); +} + +static QString textForColumn(sqlite3_stmt *sqlStatment, int column) +{ + const QChar *text = static_cast<const QChar*>(sqlite3_column_text16(sqlStatment, column)); + int size = sqlite3_column_bytes16(sqlStatment, column) / 2; + + return QString(text, size); +} + +static Utf8String utf8TextForColumn(sqlite3_stmt *sqlStatment, int column) +{ + const char *text = reinterpret_cast<const char*>(sqlite3_column_text(sqlStatment, column)); + int size = sqlite3_column_bytes(sqlStatment, column); + + return Utf8String(text, size); +} + + +static Utf8String convertedToUtf8StringForColumn(sqlite3_stmt *sqlStatment, int column) +{ + int dataType = sqlite3_column_type(sqlStatment, column); + switch (dataType) { + case SQLITE_INTEGER: return Utf8String::fromByteArray(QByteArray::number(sqlite3_column_int64(sqlStatment, column))); + case SQLITE_FLOAT: return Utf8String::fromByteArray(QByteArray::number(sqlite3_column_double(sqlStatment, column))); + case SQLITE_BLOB: return Utf8String(); + case SQLITE3_TEXT: return utf8TextForColumn(sqlStatment, column); + case SQLITE_NULL: return Utf8String(); + } + + Q_UNREACHABLE(); +} + + +static QVariant variantForColumn(sqlite3_stmt *sqlStatment, int column) +{ + int dataType = sqlite3_column_type(sqlStatment, column); + switch (dataType) { + case SQLITE_INTEGER: return QVariant::fromValue(sqlite3_column_int64(sqlStatment, column)); + case SQLITE_FLOAT: return QVariant::fromValue(sqlite3_column_double(sqlStatment, column)); + case SQLITE_BLOB: return QVariant::fromValue(byteArrayForColumn(sqlStatment, column)); + case SQLITE3_TEXT: return QVariant::fromValue(textForColumn(sqlStatment, column)); + case SQLITE_NULL: return QVariant(); + } + + Q_UNREACHABLE(); +} + +template<> +int SqliteStatement::value<int>(int column) const +{ + checkIfIsReadyToFetchValues(); + checkColumnIsValid(column); + return sqlite3_column_int(compiledStatement.get(), column); +} + +template<> +qint64 SqliteStatement::value<qint64>(int column) const +{ + checkIfIsReadyToFetchValues(); + checkColumnIsValid(column); + return sqlite3_column_int64(compiledStatement.get(), column); +} + +template<> +double SqliteStatement::value<double>(int column) const +{ + checkIfIsReadyToFetchValues(); + checkColumnIsValid(column); + return sqlite3_column_double(compiledStatement.get(), column); +} + +template<> +QByteArray SqliteStatement::value<QByteArray>(int column) const +{ + checkIfIsReadyToFetchValues(); + checkColumnIsValid(column); + return byteArrayForColumn(compiledStatement.get(), column); +} + +template<> +Utf8String SqliteStatement::value<Utf8String>(int column) const +{ + checkIfIsReadyToFetchValues(); + checkColumnIsValid(column); + return convertedToUtf8StringForColumn(compiledStatement.get(), column); +} + +template<> +QString SqliteStatement::value<QString>(int column) const +{ + checkIfIsReadyToFetchValues(); + checkColumnIsValid(column); + return textForColumn(compiledStatement.get(), column); +} + +template<> +QVariant SqliteStatement::value<QVariant>(int column) const +{ + checkIfIsReadyToFetchValues(); + checkColumnIsValid(column); + return variantForColumn(compiledStatement.get(), column); +} + +template <typename ContainerType> + ContainerType SqliteStatement::columnValues(const QVector<int> &columnIndices) const +{ + typedef typename ContainerType::value_type ElementType; + ContainerType valueContainer; + valueContainer.reserve(columnIndices.count()); + for (int columnIndex : columnIndices) + valueContainer += value<ElementType>(columnIndex); + + return valueContainer; +} + +QMap<QString, QVariant> SqliteStatement::rowColumnValueMap() const +{ + QMap<QString, QVariant> values; + + reset(); + + if (next()) { + for (int column = 0; column < columnCount(); column++) + values.insert(columnName(column), variantForColumn(compiledStatement.get(), column)); + } + + return values; +} + +QMap<QString, QVariant> SqliteStatement::twoColumnValueMap() const +{ + QMap<QString, QVariant> values; + + reset(); + + while (next()) + values.insert(textForColumn(compiledStatement.get(), 0), variantForColumn(compiledStatement.get(), 1)); + + return values; +} + +template <typename ContainerType> +ContainerType SqliteStatement::values(const QVector<int> &columns, int size) const +{ + checkColumnsAreValid(columns); + + ContainerType resultValues; + resultValues.reserve(size); + + reset(); + + while (next()) { + resultValues += columnValues<ContainerType>(columns); + } + + return resultValues; +} + +template SQLITE_EXPORT QVector<QVariant> SqliteStatement::values<QVector<QVariant>>(const QVector<int> &columnIndices, int size) const; +template SQLITE_EXPORT QVector<Utf8String> SqliteStatement::values<QVector<Utf8String>>(const QVector<int> &columnIndices, int size) const; + +template <typename ContainerType> +ContainerType SqliteStatement::values(int column) const +{ + typedef typename ContainerType::value_type ElementType; + ContainerType resultValues; + + reset(); + + while (next()) { + resultValues += value<ElementType>(column); + } + + return resultValues; +} + +template SQLITE_EXPORT QVector<qint64> SqliteStatement::values<QVector<qint64>>(int column) const; +template SQLITE_EXPORT QVector<double> SqliteStatement::values<QVector<double>>(int column) const; +template SQLITE_EXPORT QVector<QByteArray> SqliteStatement::values<QVector<QByteArray>>(int column) const; +template SQLITE_EXPORT Utf8StringVector SqliteStatement::values<Utf8StringVector>(int column) const; +template SQLITE_EXPORT QVector<QString> SqliteStatement::values<QVector<QString>>(int column) const; + +template <typename Type> +Type SqliteStatement::toValue(const Utf8String &sqlStatementUtf8) +{ + SqliteStatement statement(sqlStatementUtf8); + + statement.next(); + + return statement.value<Type>(0); +} + +template SQLITE_EXPORT int SqliteStatement::toValue<int>(const Utf8String &sqlStatementUtf8); +template SQLITE_EXPORT qint64 SqliteStatement::toValue<qint64>(const Utf8String &sqlStatementUtf8); +template SQLITE_EXPORT double SqliteStatement::toValue<double>(const Utf8String &sqlStatementUtf8); +template SQLITE_EXPORT QString SqliteStatement::toValue<QString>(const Utf8String &sqlStatementUtf8); +template SQLITE_EXPORT QByteArray SqliteStatement::toValue<QByteArray>(const Utf8String &sqlStatementUtf8); +template SQLITE_EXPORT Utf8String SqliteStatement::toValue<Utf8String>(const Utf8String &sqlStatementUtf8); +template SQLITE_EXPORT QVariant SqliteStatement::toValue<QVariant>(const Utf8String &sqlStatementUtf8); + diff --git a/src/libs/sqlite/sqlitestatement.h b/src/libs/sqlite/sqlitestatement.h new file mode 100644 index 0000000000..7c19af335a --- /dev/null +++ b/src/libs/sqlite/sqlitestatement.h @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITESTATEMENT_H +#define SQLITESTATEMENT_H + +#include <type_traits> +#include <memory> + +#include <QString> +#include <QVariant> +#include <QVector> + +#include "sqliteglobal.h" + +struct sqlite3_stmt; +struct sqlite3; + +#include "sqliteexception.h" +#include "utf8stringvector.h" + + + +class SQLITE_EXPORT SqliteStatement +{ +protected: + explicit SqliteStatement(const Utf8String &sqlStatementUtf8); + + static void deleteCompiledStatement(sqlite3_stmt *compiledStatement); + + bool next() const; + void step() const; + void reset() const; + + template<typename Type> + Type value(int column) const; + int columnCount() const; + Utf8StringVector columnNames() const; + + void bind(int index, int value); + void bind(int index, qint64 value); + void bind(int index, double value); + void bind(int index, const QString &text); + void bind(int index, const QByteArray &blob); + void bind(int index, const QVariant &value); + + template <typename Type> + void bind(const Utf8String &name, const Type &value); + + int bindingIndexForName(const Utf8String &name); + + void bind(const RowDictionary &rowDictionary); + void bindUnchecked(const RowDictionary &rowDictionary); + + void setBindingColumnNames(const Utf8StringVector &bindingColumnNames); + const Utf8StringVector &bindingColumnNames() const; + + template <typename ContainerType> + ContainerType values(const QVector<int> &columns, int size = 0) const; + + template <typename ContainerType> + ContainerType values(int column = 0) const; + + QMap<QString, QVariant> rowColumnValueMap() const; + QMap<QString, QVariant> twoColumnValueMap() const; + + static void execute(const Utf8String &sqlStatementUtf8); + + template <typename Type> + static Type toValue(const Utf8String &sqlStatementUtf8); + + void prepare(const Utf8String &sqlStatementUtf8); + void waitForUnlockNotify() const; + + void write(const RowDictionary &rowDictionary); + void writeUnchecked(const RowDictionary &rowDictionary); + + static sqlite3 *sqliteDatabaseHandle(); + static TextEncoding databaseTextEncoding(); + + + bool checkForStepError(int resultCode) const; + void checkForPrepareError(int resultCode) const; + void setIfIsReadyToFetchValues(int resultCode) const; + void checkIfIsReadyToFetchValues() const; + void checkColumnsAreValid(const QVector<int> &columns) const; + void checkColumnIsValid(int column) const; + void checkBindingIndex(int index) const; + void checkBindingName(int index) const; + void checkParameterCanBeBound(const RowDictionary &rowDictionary, const Utf8String &columnName); + void setBindingParameterCount(); + void setBindingColumnNamesFromStatement(); + void setColumnCount(); + void checkBindingValueMapIsEmpty(const RowDictionary &rowDictionary) const; + bool isReadOnlyStatement() const; + Q_NORETURN static void throwException(const char *whatHasHappened); + + template <typename ContainerType> + ContainerType columnValues(const QVector<int> &columnIndices) const; + + QString columnName(int column) const; + +private: + std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt*)> compiledStatement; + Utf8StringVector bindingColumnNames_; + int bindingParameterCount; + int columnCount_; + mutable bool isReadyToFetchValues; +}; + +#endif // SQLITESTATEMENT_H diff --git a/src/libs/sqlite/sqlitetable.cpp b/src/libs/sqlite/sqlitetable.cpp new file mode 100644 index 0000000000..8135dfde83 --- /dev/null +++ b/src/libs/sqlite/sqlitetable.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqlitetable.h" + +#include "sqlitecolumn.h" +#include "sqlitedatabase.h" + +SqliteTable::SqliteTable() + : withoutRowId(false) +{ + +} + +SqliteTable::~SqliteTable() +{ + qDeleteAll(sqliteColumns); +} + +void SqliteTable::setName(const Utf8String &name) +{ + tableName = name; +} + +const Utf8String &SqliteTable::name() const +{ + return tableName; +} + +void SqliteTable::setUseWithoutRowId(bool useWithoutWorId) +{ + withoutRowId = useWithoutWorId; +} + +bool SqliteTable::useWithoutRowId() const +{ + return withoutRowId; +} + +void SqliteTable::addColumn(SqliteColumn *newColumn) +{ + sqliteColumns.append(newColumn); +} + +const QVector<SqliteColumn *> &SqliteTable::columns() const +{ + return sqliteColumns; +} + +void SqliteTable::setSqliteDatabase(SqliteDatabase *database) +{ + sqliteDatabase = database; + writeWorker.moveWorkerToThread(sqliteDatabase->writeWorkerThread()); +} + +void SqliteTable::initialize() +{ + writeWorker.connectWithWorker(this); + + writeWorker.createTable(createTableCommand()); +} + +void SqliteTable::shutdown() +{ + writeWorker.disconnectWithWorker(this); +} + +void SqliteTable::handleTableCreated() +{ + emit tableIsReady(); +} + +Internal::CreateTableCommand SqliteTable::createTableCommand() const +{ + Internal::CreateTableCommand createTableCommand; + + createTableCommand.tableName = tableName; + createTableCommand.useWithoutRowId = withoutRowId; + createTableCommand.definitions = createColumnDefintions(); + + return createTableCommand; +} + +QVector<Internal::ColumnDefinition> SqliteTable::createColumnDefintions() const +{ + QVector<Internal::ColumnDefinition> columnDefintions; + + for (SqliteColumn *sqliteColumn: sqliteColumns) + columnDefintions.append(sqliteColumn->columnDefintion()); + + return columnDefintions; +} diff --git a/src/libs/sqlite/sqlitetable.h b/src/libs/sqlite/sqlitetable.h new file mode 100644 index 0000000000..ed4be02462 --- /dev/null +++ b/src/libs/sqlite/sqlitetable.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITETABLE_H +#define SQLITETABLE_H + +#include <QObject> +#include <QVector> +#include "utf8string.h" + +#include "sqliteglobal.h" +#include "tablewriteworkerproxy.h" + +class SqliteColumn; +class SqliteDatabase; + +class SQLITE_EXPORT SqliteTable : public QObject +{ + Q_OBJECT + + friend class Internal::TableWriteWorkerProxy; + +public: + SqliteTable(); + ~SqliteTable(); + + void setName(const Utf8String &name); + const Utf8String &name() const; + + void setUseWithoutRowId(bool useWithoutWorId); + bool useWithoutRowId() const; + + void addColumn(SqliteColumn *newColumn); + const QVector<SqliteColumn *> &columns() const; + + void setSqliteDatabase(SqliteDatabase *database); + + void initialize(); + void shutdown(); + +signals: + void tableIsReady(); + +private: + void handleTableCreated(); + Internal::CreateTableCommand createTableCommand() const; + QVector<Internal::ColumnDefinition> createColumnDefintions() const; + +private: + Internal::TableWriteWorkerProxy writeWorker; + QVector<SqliteColumn*> sqliteColumns; + Utf8String tableName; + SqliteDatabase *sqliteDatabase; + bool withoutRowId; +}; + +#endif // SQLITETABLE_H diff --git a/src/libs/sqlite/sqlitetransaction.cpp b/src/libs/sqlite/sqlitetransaction.cpp new file mode 100644 index 0000000000..6e2b757569 --- /dev/null +++ b/src/libs/sqlite/sqlitetransaction.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqlitetransaction.h" + +#include "sqlitewritestatement.h" + + +SqliteAbstractTransaction::~SqliteAbstractTransaction() +{ + if (!isAlreadyCommited) + SqliteWriteStatement::execute(Utf8StringLiteral("ROLLBACK")); +} + +void SqliteAbstractTransaction::commit() +{ + SqliteWriteStatement::execute(Utf8StringLiteral("COMMIT")); + isAlreadyCommited = true; +} + +SqliteTransaction::SqliteTransaction() +{ + SqliteWriteStatement::execute(Utf8StringLiteral("BEGIN")); +} + +SqliteImmediateTransaction::SqliteImmediateTransaction() +{ + SqliteWriteStatement::execute(Utf8StringLiteral("BEGIN IMMEDIATE")); +} + +SqliteExclusiveTransaction::SqliteExclusiveTransaction() +{ + SqliteWriteStatement::execute(Utf8StringLiteral("BEGIN EXCLUSIVE")); +} diff --git a/src/libs/sqlite/sqlitetransaction.h b/src/libs/sqlite/sqlitetransaction.h new file mode 100644 index 0000000000..5c994b5614 --- /dev/null +++ b/src/libs/sqlite/sqlitetransaction.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITETRANSACTION_H +#define SQLITETRANSACTION_H + +#include "sqliteglobal.h" + +class SQLITE_EXPORT SqliteAbstractTransaction +{ +public: + virtual ~SqliteAbstractTransaction(); + + void commit(); + +private: + bool isAlreadyCommited = false; +}; + + +class SQLITE_EXPORT SqliteTransaction final : public SqliteAbstractTransaction +{ +public: + SqliteTransaction(); + +}; + +class SQLITE_EXPORT SqliteImmediateTransaction final : public SqliteAbstractTransaction +{ +public: + SqliteImmediateTransaction(); + +}; + +class SQLITE_EXPORT SqliteExclusiveTransaction final : public SqliteAbstractTransaction +{ +public: + SqliteExclusiveTransaction(); + +}; + + +#endif // SQLITETRANSACTION_H diff --git a/src/libs/sqlite/sqliteworkerthread.cpp b/src/libs/sqlite/sqliteworkerthread.cpp new file mode 100644 index 0000000000..8789a6e7d5 --- /dev/null +++ b/src/libs/sqlite/sqliteworkerthread.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqliteworkerthread.h" + +#include "sqlitedatabaseconnection.h" + +#include <QMutexLocker> + +SqliteWorkerThread::SqliteWorkerThread(QObject *parent) : + QThread(parent) +{ +} + +void SqliteWorkerThread::run() +{ + QMutexLocker locker(&connectionMutex); + + connection = new SqliteDatabaseConnection; + + locker.unlock(); + connectionChanged.wakeAll(); + + QThread::run(); + + locker.relock(); + delete connection; + connection = 0; +} + +SqliteDatabaseConnection *SqliteWorkerThread::databaseConnection() const +{ + QMutexLocker locker(&connectionMutex); + connectionChanged.wait(&connectionMutex); + + return connection; +} diff --git a/src/libs/sqlite/sqliteworkerthread.h b/src/libs/sqlite/sqliteworkerthread.h new file mode 100644 index 0000000000..5a504a69aa --- /dev/null +++ b/src/libs/sqlite/sqliteworkerthread.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITEWORKERTHREAD_H +#define SQLITEWORKERTHREAD_H + +#include <QThread> +#include <QPointer> +#include <QMutex> +#include <QWaitCondition> + +class SqliteDatabaseConnection; + +class SqliteWorkerThread : public QThread +{ + Q_OBJECT +public: + explicit SqliteWorkerThread(QObject *parent = 0); + + void run() override; + + SqliteDatabaseConnection *databaseConnection() const; + +private: + mutable QMutex connectionMutex; + mutable QWaitCondition connectionChanged; + QPointer<SqliteDatabaseConnection> connection; +}; + +#endif // SQLITEWORKERTHREAD_H diff --git a/src/libs/sqlite/sqlitewritestatement.cpp b/src/libs/sqlite/sqlitewritestatement.cpp new file mode 100644 index 0000000000..7effb9618b --- /dev/null +++ b/src/libs/sqlite/sqlitewritestatement.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqlitewritestatement.h" + +SqliteWriteStatement::SqliteWriteStatement(const Utf8String &sqlStatementUtf8) + : SqliteStatement(sqlStatementUtf8) +{ + checkIsWritableStatement(); +} + +void SqliteWriteStatement::checkIsWritableStatement() +{ + if (isReadOnlyStatement()) + throwException("SqliteStatement::SqliteWriteStatement: is not a writable statement!"); +} diff --git a/src/libs/sqlite/sqlitewritestatement.h b/src/libs/sqlite/sqlitewritestatement.h new file mode 100644 index 0000000000..c8d9b31845 --- /dev/null +++ b/src/libs/sqlite/sqlitewritestatement.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLITEWRITESTATEMENT_H +#define SQLITEWRITESTATEMENT_H + +#include "sqlitestatement.h" + +class SQLITE_EXPORT SqliteWriteStatement : private SqliteStatement +{ +public: + explicit SqliteWriteStatement(const Utf8String &sqlStatementUtf8); + + using SqliteStatement::step; + using SqliteStatement::reset; + using SqliteStatement::bind; + using SqliteStatement::bindUnchecked; + using SqliteStatement::bindingIndexForName; + using SqliteStatement::setBindingColumnNames; + using SqliteStatement::bindingColumnNames; + using SqliteStatement::write; + using SqliteStatement::writeUnchecked; + using SqliteStatement::execute; + +protected: + void checkIsWritableStatement(); +}; + +#endif // SQLITEWRITESTATEMENT_H diff --git a/src/libs/sqlite/sqlstatementbuilder.cpp b/src/libs/sqlite/sqlstatementbuilder.cpp new file mode 100644 index 0000000000..9f73907b2e --- /dev/null +++ b/src/libs/sqlite/sqlstatementbuilder.cpp @@ -0,0 +1,238 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqlstatementbuilder.h" + +#include "sqlstatementbuilderexception.h" +#include "utf8stringvector.h" + +#include <algorithm> + +SqlStatementBuilder::SqlStatementBuilder(const Utf8String &sqlTemplate) + : sqlTemplate(sqlTemplate) +{ +} + +void SqlStatementBuilder::bindEmptyText(const Utf8String &name) +{ + clearSqlStatement(); + checkIfPlaceHolderExists(name); + changeBinding(name, Utf8String()); +} + +void SqlStatementBuilder::bind(const Utf8String &name, const Utf8String &text) +{ + clearSqlStatement(); + checkBindingTextIsNotEmpty(text); + checkIfPlaceHolderExists(name); + changeBinding(name, text); +} + +void SqlStatementBuilder::bind(const Utf8String &name, const Utf8StringVector &textVector) +{ + clearSqlStatement(); + checkBindingTextVectorIsNotEmpty(textVector); + checkIfPlaceHolderExists(name); + changeBinding(name, textVector.join(Utf8StringLiteral(", "))); +} + +void SqlStatementBuilder::bind(const Utf8String &name, int value) +{ + clearSqlStatement(); + checkIfPlaceHolderExists(name); + changeBinding(name, Utf8String::number(value)); +} + +void SqlStatementBuilder::bind(const Utf8String &name, const QVector<int> &integerVector) +{ + clearSqlStatement(); + checkBindingIntegerVectorIsNotEmpty(integerVector); + checkIfPlaceHolderExists(name); + changeBinding(name, Utf8StringVector::fromIntegerVector(integerVector).join(Utf8StringLiteral(", "))); +} + +void SqlStatementBuilder::bindWithInsertTemplateParameters(const Utf8String &name, const Utf8StringVector &columns) +{ + clearSqlStatement(); + checkBindingTextVectorIsNotEmpty(columns); + checkIfPlaceHolderExists(name); + changeBinding(name, insertTemplateParameters(columns)); +} + +void SqlStatementBuilder::bindWithUpdateTemplateParameters(const Utf8String &name, const Utf8StringVector &columns) +{ + clearSqlStatement(); + checkBindingTextVectorIsNotEmpty(columns); + checkIfPlaceHolderExists(name); + changeBinding(name, updateTemplateParameters(columns)); +} + +void SqlStatementBuilder::bindWithUpdateTemplateNames(const Utf8String &name, const Utf8StringVector &columns) +{ + clearSqlStatement(); + checkBindingTextVectorIsNotEmpty(columns); + checkIfPlaceHolderExists(name); + changeBinding(name, updateTemplateNames(columns)); +} + +void SqlStatementBuilder::clear() +{ + bindings.clear(); + sqlStatement_.clear(); +} + +const Utf8String SqlStatementBuilder::insertTemplateParameters(const Utf8StringVector &columns) +{ + const Utf8StringVector templateParamters(columns.count(), Utf8StringLiteral("?")); + + return templateParamters.join(Utf8StringLiteral(", ")); +} + +const Utf8String SqlStatementBuilder::updateTemplateParameters(const Utf8StringVector &columns) +{ + Utf8String templateParamters = columns.join(Utf8StringLiteral("=?, ")); + templateParamters.append(Utf8StringLiteral("=?")); + + return templateParamters; +} + +const Utf8String SqlStatementBuilder::updateTemplateNames(const Utf8StringVector &columns) +{ + Utf8StringVector templateNames; + + foreach (const Utf8String &columnName, columns) + templateNames.append(columnName+Utf8StringLiteral("=@")+columnName); + + return templateNames.join(Utf8StringLiteral(", ")); +} + +void SqlStatementBuilder::sortBindings() const +{ + std::sort(bindings.begin(), bindings.end(), [] (const BindingPair &lhs,const BindingPair &rhs) + { + return lhs.first.byteSize() == rhs.first.byteSize() ? lhs.first.toByteArray() < rhs.first.toByteArray() : lhs.first.byteSize() > rhs.first.byteSize(); + }); +} + +Utf8String SqlStatementBuilder::sqlStatement() const +{ + if (!isBuild()) + generateSqlStatement(); + + return sqlStatement_; +} + +bool SqlStatementBuilder::isBuild() const +{ + return sqlStatement_.hasContent(); +} + +Utf8String SqlStatementBuilder::columnTypeToString(ColumnType columnType) +{ + switch (columnType) { + case ColumnType::Numeric: return Utf8StringLiteral("NUMERIC"); + case ColumnType::Integer: return Utf8StringLiteral("INTEGER"); + case ColumnType::Real: return Utf8StringLiteral("REAL"); + case ColumnType::Text: return Utf8StringLiteral("TEXT"); + case ColumnType::None: return Utf8String(); + } + + Q_UNREACHABLE(); +} + +void SqlStatementBuilder::generateSqlStatement() const +{ + sqlStatement_ = sqlTemplate; + + sortBindings(); + + auto bindingIterator = bindings.cbegin(); + while (bindingIterator != bindings.cend()) { + const Utf8String &placeHolderToken = bindingIterator->first; + const Utf8String &replacementToken = bindingIterator->second; + sqlStatement_.replace(placeHolderToken, replacementToken); + ++bindingIterator; + } + + checkIfNoPlaceHoldersAynmoreExists(); +} + +void SqlStatementBuilder::changeBinding(const Utf8String &name, const Utf8String &text) +{ + + auto findBindingIterator = std::find_if(bindings.begin(), bindings.end(), [name] (const BindingPair &binding) { + return binding.first == name; + }); + + if (findBindingIterator == bindings.end()) + bindings.push_back(std::make_pair(name, text)); + else + findBindingIterator->second = text; +} + +void SqlStatementBuilder::clearSqlStatement() +{ + sqlStatement_.clear(); +} + +void SqlStatementBuilder::checkIfPlaceHolderExists(const Utf8String &name) const +{ + if (name.byteSize() < 2 || !name.startsWith('$') || !sqlTemplate.contains(name)) + throwException("SqlStatementBuilder::bind: placeholder name does not exists!", name.constData()); +} + +void SqlStatementBuilder::checkIfNoPlaceHoldersAynmoreExists() const +{ + if (sqlStatement_.contains('$')) + throwException("SqlStatementBuilder::bind: there are still placeholder in the sql statement!", sqlTemplate.constData()); +} + +void SqlStatementBuilder::checkBindingTextIsNotEmpty(const Utf8String &text) const +{ + if (text.isEmpty()) + throwException("SqlStatementBuilder::bind: binding text it empty!", sqlTemplate.constData()); +} + +void SqlStatementBuilder::checkBindingTextVectorIsNotEmpty(const Utf8StringVector &textVector) const +{ + if (textVector.isEmpty()) + throwException("SqlStatementBuilder::bind: binding text vector it empty!", sqlTemplate.constData()); +} + +void SqlStatementBuilder::checkBindingIntegerVectorIsNotEmpty(const QVector<int> &integerVector) const +{ + if (integerVector.isEmpty()) + throwException("SqlStatementBuilder::bind: binding integer vector it empty!", sqlTemplate.constData()); +} + +void SqlStatementBuilder::throwException(const char *whatHasHappened, const char *errorMessage) +{ + throw SqlStatementBuilderException(whatHasHappened, errorMessage); +} diff --git a/src/libs/sqlite/sqlstatementbuilder.h b/src/libs/sqlite/sqlstatementbuilder.h new file mode 100644 index 0000000000..5fcd3d51f0 --- /dev/null +++ b/src/libs/sqlite/sqlstatementbuilder.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLSTATEMENTBUILDER_H +#define SQLSTATEMENTBUILDER_H + +#include <vector> +#include <utility> + +#include "utf8string.h" + +class SQLITE_EXPORT SqlStatementBuilder +{ + using BindingPair = std::pair<Utf8String, Utf8String>; +public: + SqlStatementBuilder(const Utf8String &sqlTemplate); + + void bindEmptyText(const Utf8String &name); + void bind(const Utf8String &name, const Utf8String &text); + void bind(const Utf8String &name, const Utf8StringVector &textVector); + void bind(const Utf8String &name, int value); + void bind(const Utf8String &name, const QVector<int> &integerVector); + void bindWithInsertTemplateParameters(const Utf8String &name, const Utf8StringVector &columns); + void bindWithUpdateTemplateParameters(const Utf8String &name, const Utf8StringVector &columns); + void bindWithUpdateTemplateNames(const Utf8String &name, const Utf8StringVector &columns); + void clear(); + + Utf8String sqlStatement() const; + + bool isBuild() const; + + static Utf8String columnTypeToString(ColumnType columnType); + +protected: + static const Utf8String insertTemplateParameters(const Utf8StringVector &columns); + static const Utf8String updateTemplateParameters(const Utf8StringVector &columns); + static const Utf8String updateTemplateNames(const Utf8StringVector &columns); + + void sortBindings() const; + void generateSqlStatement() const; + + void changeBinding(const Utf8String &name, const Utf8String &text); + + void clearSqlStatement(); + void checkIfPlaceHolderExists(const Utf8String &name) const; + void checkIfNoPlaceHoldersAynmoreExists() const; + void checkBindingTextIsNotEmpty(const Utf8String &text) const; + void checkBindingTextVectorIsNotEmpty(const Utf8StringVector &textVector) const; + void checkBindingIntegerVectorIsNotEmpty(const QVector<int> &integerVector) const; + + Q_NORETURN static void throwException(const char *whatHasHappened, const char *errorMessage); + +private: + Utf8String sqlTemplate; + mutable Utf8String sqlStatement_; + mutable std::vector<BindingPair> bindings; +}; + +#endif // SQLSTATEMENTBUILDER_H diff --git a/src/libs/sqlite/sqlstatementbuilderexception.cpp b/src/libs/sqlite/sqlstatementbuilderexception.cpp new file mode 100644 index 0000000000..65addc681f --- /dev/null +++ b/src/libs/sqlite/sqlstatementbuilderexception.cpp @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "sqlstatementbuilderexception.h" + +SqlStatementBuilderException::SqlStatementBuilderException(const char *whatErrorHasHappen, const char *errorMessage) + : SqliteException(whatErrorHasHappen, errorMessage) +{ +} diff --git a/src/libs/sqlite/sqlstatementbuilderexception.h b/src/libs/sqlite/sqlstatementbuilderexception.h new file mode 100644 index 0000000000..ef3943ba7f --- /dev/null +++ b/src/libs/sqlite/sqlstatementbuilderexception.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SQLSTATEMENTBUILDEREXCEPTION_H +#define SQLSTATEMENTBUILDEREXCEPTION_H + +#include "sqliteexception.h" + +class SQLITE_EXPORT SqlStatementBuilderException : public SqliteException +{ +public: + SqlStatementBuilderException(const char *whatErrorHasHappen, const char *errorMessage = 0); +}; + +#endif // SQLSTATEMENTBUILDEREXCEPTION_H diff --git a/src/libs/sqlite/tablewriteworker.cpp b/src/libs/sqlite/tablewriteworker.cpp new file mode 100644 index 0000000000..6a84909e0d --- /dev/null +++ b/src/libs/sqlite/tablewriteworker.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "tablewriteworker.h" + +#include "createtablesqlstatementbuilder.h" + +#include "sqlitewritestatement.h" +#include "sqlitetransaction.h" + +namespace Internal { + +TableWriteWorker::TableWriteWorker(QObject *parent) + : QObject(parent) +{ + +} + +TableWriteWorker::~TableWriteWorker() +{ + +} + +void TableWriteWorker::createTable(const CreateTableCommand &command) +{ + try { + CreateTableSqlStatementBuilder createTableSqlStatementBuilder; + + createTableSqlStatementBuilder.setTable(command.tableName); + createTableSqlStatementBuilder.setUseWithoutRowId(command.useWithoutRowId); + createTableSqlStatementBuilder.setColumnDefinitions(command.definitions); + + SqliteImmediateTransaction transaction; + SqliteWriteStatement::execute(createTableSqlStatementBuilder.sqlStatement()); + transaction.commit(); + + emit tableCreated(); + } catch (const SqliteException &exception) { + exception.printWarning(); + } +} + +} // namespace Internal + diff --git a/src/libs/sqlite/tablewriteworker.h b/src/libs/sqlite/tablewriteworker.h new file mode 100644 index 0000000000..b2a369add5 --- /dev/null +++ b/src/libs/sqlite/tablewriteworker.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef INTERNAL_TABLEWRITEWORKER_H +#define INTERNAL_TABLEWRITEWORKER_H + +#include <QObject> + +#include "createtablecommand.h" + +namespace Internal { + +class TableWriteWorker : public QObject +{ + Q_OBJECT +public: + explicit TableWriteWorker(QObject *parent = 0); + ~TableWriteWorker(); + + void createTable(const CreateTableCommand &command); + +signals: + void tableCreated(); + +}; + +} // namespace Internal + +#endif // INTERNAL_TABLEWRITEWORKER_H diff --git a/src/libs/sqlite/tablewriteworkerproxy.cpp b/src/libs/sqlite/tablewriteworkerproxy.cpp new file mode 100644 index 0000000000..b6df81bae4 --- /dev/null +++ b/src/libs/sqlite/tablewriteworkerproxy.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "tablewriteworkerproxy.h" + +#include "tablewriteworker.h" +#include "sqlitetable.h" + +#include "createtablecommand.h" + +namespace Internal { + +TableWriteWorkerProxy::TableWriteWorkerProxy() + : worker(new TableWriteWorker) +{ +} + +TableWriteWorkerProxy::~TableWriteWorkerProxy() +{ + delete worker; +} + +void TableWriteWorkerProxy::connectWithWorker(SqliteTable *sqliterTable) +{ + connect(this, &TableWriteWorkerProxy::createTable, worker, &TableWriteWorker::createTable); + connect(worker, &TableWriteWorker::tableCreated, sqliterTable, &SqliteTable::handleTableCreated); +} + +void TableWriteWorkerProxy::disconnectWithWorker(SqliteTable *sqliterTable) +{ + disconnect(this, &TableWriteWorkerProxy::createTable, worker, &TableWriteWorker::createTable); + disconnect(worker, &TableWriteWorker::tableCreated, sqliterTable, &SqliteTable::handleTableCreated); +} + +void TableWriteWorkerProxy::moveWorkerToThread(QThread *workerThread) +{ + worker->moveToThread(workerThread); +} + +} // namespace Internal + diff --git a/src/libs/sqlite/tablewriteworkerproxy.h b/src/libs/sqlite/tablewriteworkerproxy.h new file mode 100644 index 0000000000..4a1d4e0333 --- /dev/null +++ b/src/libs/sqlite/tablewriteworkerproxy.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef INTERNAL_TABLEWRITEWORKERPROXY_H +#define INTERNAL_TABLEWRITEWORKERPROXY_H + +#include <QObject> + +#include <memory> + +#include "createtablecommand.h" + +QT_BEGIN_NAMESPACE +class QThread; +QT_END_NAMESPACE + +class SqliteTable; + +namespace Internal { + +class TableWriteWorker; + +class TableWriteWorkerProxy : public QObject +{ + Q_OBJECT +public: + explicit TableWriteWorkerProxy(); + ~TableWriteWorkerProxy(); + + void connectWithWorker(SqliteTable *sqliterTable); + void disconnectWithWorker(SqliteTable *sqliterTable); + + void moveWorkerToThread(QThread *workerThread); + +signals: + void createTable(const CreateTableCommand &command); + +private: + TableWriteWorker *worker; +}; + +} // namespace Internal + +#endif // INTERNAL_TABLEWRITEWORKERPROXY_H diff --git a/src/libs/sqlite/utf8string.cpp b/src/libs/sqlite/utf8string.cpp new file mode 100644 index 0000000000..2ad6d8491b --- /dev/null +++ b/src/libs/sqlite/utf8string.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "utf8string.h" + +#include "utf8stringvector.h" + +#include <QString> +#include <QDebug> + +#ifdef QT_TESTLIB_LIB +#include <QTest> +#endif + +#include <QDataStream> + +#include <ostream> + +Utf8String::Utf8String(const char *utf8Text, int size) + : byteArray(utf8Text, size) +{ +} + +Utf8String::Utf8String(const QString &text) + : byteArray(text.toUtf8()) +{ +} + +const char *Utf8String::constData() const +{ + return byteArray.constData(); +} + +int Utf8String::byteSize() const +{ + return byteArray.size(); +} + +Utf8String Utf8String::fromUtf8(const char *utf8Text) +{ + return Utf8String(utf8Text, -1); +} + +Utf8String::Utf8String(const QByteArray &utf8ByteArray) + : byteArray(utf8ByteArray) +{ +} + +Utf8String Utf8String::fromByteArray(const QByteArray &utf8ByteArray) +{ + return Utf8String(utf8ByteArray); +} + +const QByteArray &Utf8String::toByteArray() const +{ + return byteArray; +} + +Utf8String Utf8String::fromString(const QString &text) +{ + return Utf8String::fromByteArray(text.toUtf8()); +} + +QString Utf8String::toString() const +{ + return QString::fromUtf8(byteArray, byteArray.size()); +} + +Utf8String Utf8String::mid(int position, int length) const +{ + return Utf8String(byteArray.mid(position, length)); +} + +void Utf8String::replace(const Utf8String &before, const Utf8String &after) +{ + byteArray.replace(before.byteArray, after.byteArray); +} + +Utf8StringVector Utf8String::split(char separator) const +{ + Utf8StringVector utf8Vector; + + foreach (const QByteArray &byteArray, byteArray.split(separator)) + utf8Vector.append(Utf8String::fromByteArray(byteArray)); + + return utf8Vector; +} + +void Utf8String::clear() +{ + byteArray.clear(); +} + +void Utf8String::append(const Utf8String &textToAppend) +{ + byteArray.append(textToAppend.byteArray); +} + +bool Utf8String::contains(const Utf8String &text) const +{ + return byteArray.contains(text.byteArray); +} + +bool Utf8String::contains(const char *text) const +{ + return byteArray.contains(text); +} + +bool Utf8String::contains(char character) const +{ + return byteArray.contains(character); +} + +bool Utf8String::startsWith(const Utf8String &text) const +{ + return byteArray.startsWith(text.byteArray); +} + +bool Utf8String::startsWith(const char *text) const +{ + return byteArray.startsWith(text); +} + +bool Utf8String::startsWith(char character) const +{ + return byteArray.startsWith(character); +} + +bool Utf8String::isEmpty() const +{ + return byteArray.isEmpty(); +} + +bool Utf8String::hasContent() const +{ + return !isEmpty(); +} + +void Utf8String::reserve(int reserveSize) +{ + byteArray.reserve(reserveSize); +} + +Utf8String Utf8String::number(int number, int base) +{ + return Utf8String::fromByteArray(QByteArray::number(number, base)); +} + +const Utf8String &Utf8String::operator+=(const Utf8String &text) +{ + byteArray += text.byteArray; + + return *this; +} + +void Utf8String::registerType() +{ + qRegisterMetaType<Utf8String>("Utf8String"); +} + +Utf8String::operator const QByteArray &() const +{ + return byteArray; +} + +Utf8String::operator QString() const +{ + return toString(); +} + +const Utf8String operator +(const Utf8String &first, const Utf8String &second) +{ + return Utf8String(first.byteArray + second.byteArray); +} + + +bool operator !=(const Utf8String &first, const Utf8String &second) +{ + return first.byteArray != second.byteArray; +} + + +bool operator ==(const Utf8String &first, const Utf8String &second) +{ + return first.byteArray == second.byteArray; +} + +bool operator ==(const Utf8String &first, const char *second) +{ + return first.byteArray == second; +} + +bool operator <(const Utf8String &first, const Utf8String &second) +{ + if (first.byteSize() == second.byteSize()) + return first.byteArray < second.byteArray; + + return first.byteSize() < second.byteSize(); +} + + +QDataStream &operator<<(QDataStream &datastream, const Utf8String &text) +{ + datastream << text.byteArray; + + return datastream; +} + + +QDataStream &operator>>(QDataStream &datastream, Utf8String &text) +{ + datastream >> text.byteArray; + + return datastream; +} + + +QDebug operator<<(QDebug debug, const Utf8String &text) +{ + debug << text.constData(); + + return debug; +} + +void PrintTo(const Utf8String &text, ::std::ostream* os) +{ + *os << "\"" << text.toByteArray().data() << "\""; +} diff --git a/src/libs/sqlite/utf8string.h b/src/libs/sqlite/utf8string.h new file mode 100644 index 0000000000..7461535a2a --- /dev/null +++ b/src/libs/sqlite/utf8string.h @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef UTF8STRING_H +#define UTF8STRING_H + +#include <QByteArray> +#include <QMetaType> + +#include "sqliteglobal.h" + +class Utf8StringVector; +class Utf8String; + +class SQLITE_EXPORT Utf8String +{ + friend class Utf8StringVector; + + friend SQLITE_EXPORT const Utf8String operator +(const Utf8String &first, const Utf8String &second); + + friend SQLITE_EXPORT bool operator !=(const Utf8String &first, const Utf8String &second); + friend SQLITE_EXPORT bool operator ==(const Utf8String &first, const Utf8String &second); + friend SQLITE_EXPORT bool operator ==(const Utf8String &first, const char *second); + friend SQLITE_EXPORT bool operator <(const Utf8String &first, const Utf8String &second); + + friend SQLITE_EXPORT QDataStream &operator<<(QDataStream &datastream, const Utf8String &text); + friend SQLITE_EXPORT QDataStream &operator>>(QDataStream &datastream, Utf8String &text); + +public: + Utf8String() = default; + explicit Utf8String(const char *utf8Text, int size); + Utf8String(const QString &text); + + const char *constData() const; + + int byteSize() const; + + static Utf8String fromUtf8(const char *utf8Text); + static Utf8String fromByteArray(const QByteArray &utf8ByteArray); + const QByteArray &toByteArray() const; + + static Utf8String fromString(const QString &text); + QString toString() const; + + Utf8String mid(int position, int length = -1) const; + void replace(const Utf8String &before, const Utf8String &after); + Utf8StringVector split(char separator) const; + + void clear(); + + void append(const Utf8String &textToAppend); + bool contains(const Utf8String &text) const; + bool contains(const char *text) const; + bool contains(char character) const; + bool startsWith(const Utf8String &text) const; + bool startsWith(const char *text) const; + bool startsWith(char character) const; + bool isEmpty() const; + bool hasContent() const; + + void reserve(int reserveSize); + + static Utf8String number(int number, int base=10); + + const Utf8String &operator+=(const Utf8String &text); + + static void registerType(); + + operator QString () const; + operator const QByteArray & () const; + +protected: + explicit Utf8String(const QByteArray &utf8ByteArray); + +private: + QByteArray byteArray; +}; + +SQLITE_EXPORT const Utf8String operator +(const Utf8String &first, const Utf8String &second); + +SQLITE_EXPORT bool operator !=(const Utf8String &first, const Utf8String &second); +SQLITE_EXPORT bool operator ==(const Utf8String &first, const Utf8String &second); +SQLITE_EXPORT bool operator ==(const Utf8String &first, const char *second); +SQLITE_EXPORT bool operator <(const Utf8String &first, const Utf8String &second); + +SQLITE_EXPORT QDataStream &operator<<(QDataStream &datastream, const Utf8String &text); +SQLITE_EXPORT QDataStream &operator>>(QDataStream &datastream, Utf8String &text); +SQLITE_EXPORT QDebug operator<<(QDebug debug, const Utf8String &text); +SQLITE_EXPORT void PrintTo(const Utf8String &text, ::std::ostream* os); + +#if defined(Q_COMPILER_LAMBDA) + +# define Utf8StringLiteral(str) \ + ([]() -> Utf8String { \ + enum { Size = sizeof(str) - 1 }; \ + static const QStaticByteArrayData<Size> qbytearray_literal = { \ + Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER(Size), \ + str }; \ + QByteArrayDataPtr holder = { qbytearray_literal.data_ptr() }; \ + const QByteArray byteArray(holder); \ + return Utf8String::fromByteArray(byteArray); \ + }()) \ + /**/ + +#endif + +#ifndef Utf8StringLiteral +// no lambdas, not GCC, just return a temporary QByteArray + +# define Utf8StringLiteral(str) Utf8String(str, sizeof(str) - 1) +#endif + +Q_DECLARE_METATYPE(Utf8String) + +#endif // UTF8STRING_H diff --git a/src/libs/sqlite/utf8stringvector.cpp b/src/libs/sqlite/utf8stringvector.cpp new file mode 100644 index 0000000000..0c60551e96 --- /dev/null +++ b/src/libs/sqlite/utf8stringvector.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "utf8stringvector.h" + +#include <QStringList> +#include <QDebug> + +#include <ostream> + +Utf8StringVector::Utf8StringVector() +{ +} + +Utf8StringVector::Utf8StringVector(std::initializer_list<Utf8String> initializerList) + : QVector<Utf8String>(initializerList) +{ + +} + +Utf8StringVector::Utf8StringVector(const Utf8String &utf8String) +{ + append(utf8String); +} + +Utf8StringVector::Utf8StringVector(const QVector<Utf8String> &vector) + : QVector<Utf8String>(vector) +{ + +} + +Utf8StringVector::Utf8StringVector(const QStringList &stringList) +{ + reserve(stringList.count()); + + foreach (const QString &string, stringList) + append(Utf8String(string)); +} + +Utf8StringVector::Utf8StringVector(int size, const Utf8String &text) + : QVector<Utf8String>(size, text) +{ +} + +Utf8String Utf8StringVector::join(const Utf8String &separator) const +{ + Utf8String joindedString; + + joindedString.reserve(totalByteSize() + separator.byteSize() * count()); + + for (auto position = begin(); position != end(); ++position) { + joindedString.append(*position); + if (std::next(position) != end()) + joindedString.append(separator); + } + + return joindedString; +} + +Utf8StringVector Utf8StringVector::fromIntegerVector(const QVector<int> &integerVector) +{ + Utf8StringVector utf8StringVector; + utf8StringVector.reserve(integerVector.count()); + + foreach (int integer, integerVector) + utf8StringVector.append(Utf8String::number(integer)); + + return utf8StringVector; +} + +void Utf8StringVector::registerType() +{ + qRegisterMetaType<Utf8StringVector>("Utf8StringVector"); +} + +int Utf8StringVector::totalByteSize() const +{ + int totalSize = 0; + + for (const Utf8String &utf8String : *this) + totalSize += utf8String.byteSize(); + + return totalSize; +} + +QDebug operator<<(QDebug debug, const Utf8StringVector &textVector) +{ + debug << "Utf8StringVector(" << textVector.join(Utf8StringLiteral(", ")).constData() << ")"; + + return debug; +} + +void PrintTo(const Utf8StringVector &textVector, ::std::ostream* os) +{ + *os << "Utf8StringVector(" << textVector.join(Utf8StringLiteral(", ")).constData() << ")"; +} diff --git a/src/libs/sqlite/utf8stringvector.h b/src/libs/sqlite/utf8stringvector.h new file mode 100644 index 0000000000..f8ee679e8d --- /dev/null +++ b/src/libs/sqlite/utf8stringvector.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef UTF8STRINGVECTOR_H +#define UTF8STRINGVECTOR_H + +#include "utf8string.h" + +#include <QVector> + +#include "sqliteglobal.h" + +class SQLITE_EXPORT Utf8StringVector : public QVector<Utf8String> +{ +public: + Utf8StringVector(); + Utf8StringVector(std::initializer_list<Utf8String> initializerList); + explicit Utf8StringVector(const Utf8String &utf8String); + Utf8StringVector(const QVector<Utf8String> &vector); + explicit Utf8StringVector(const QStringList &stringList); + explicit Utf8StringVector(int size, const Utf8String &text); + + Utf8String join(const Utf8String &separator) const; + + static Utf8StringVector fromIntegerVector(const QVector<int> &integerVector); + + static void registerType(); + + inline bool removeFast(const Utf8String &valueToBeRemoved); + +protected: + int totalByteSize() const; +}; + +bool Utf8StringVector::removeFast(const Utf8String &valueToBeRemoved) +{ + auto position = std::remove(begin(), end(), valueToBeRemoved); + + bool hasEntry = position != end(); + + erase(position, end()); + + return hasEntry; +} + + +SQLITE_EXPORT QDebug operator<<(QDebug debug, const Utf8StringVector &textVector); +SQLITE_EXPORT void PrintTo(const Utf8StringVector &textVector, ::std::ostream* os); + +Q_DECLARE_METATYPE(Utf8StringVector) + +#endif // UTF8STRINGVECTOR_H |