Skip to content

Commit

Permalink
Merge pull request #4817 from tuffnatty/functions_as_table
Browse files Browse the repository at this point in the history
PoC: Store script functions as a table for easier bulk import/export
  • Loading branch information
pawelsalawa authored Apr 4, 2024
2 parents a640943 + 1ae4ffe commit 6aa0114
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 12 deletions.
9 changes: 9 additions & 0 deletions SQLiteStudio3/Tests/TestUtils/configmock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,15 @@ void ConfigMock::refreshDdlHistory()
{
}

QList<QHash<QString, QVariant> > ConfigMock::getScriptFunctions()
{
return QList<QHash<QString, QVariant> >();
}

void ConfigMock::setScriptFunctions(const QList<QHash<QString, QVariant> >&)
{
}

QString ConfigMock::getSqlite3Version() const
{
return "3.8.8";
Expand Down
2 changes: 2 additions & 0 deletions SQLiteStudio3/Tests/TestUtils/configmock.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class ConfigMock : public Config
QList<DdlHistoryEntryPtr> getDdlHistoryFor(const QString&, const QString&, const QDate&);
DdlHistoryModel* getDdlHistoryModel();
void clearDdlHistory();
QList<QHash<QString, QVariant> > getScriptFunctions();
void setScriptFunctions(const QList<QHash<QString, QVariant> >&);
void begin();
void commit();
void rollback();
Expand Down
6 changes: 4 additions & 2 deletions SQLiteStudio3/coreSQLiteStudio/services/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <QSharedPointer>
#include <QDateTime>

const int SQLITESTUDIO_CONFIG_VERSION = 3;
const int SQLITESTUDIO_CONFIG_VERSION = 4;

CFG_CATEGORIES(Core,
CFG_CATEGORY(General,
Expand All @@ -29,7 +29,6 @@ CFG_CATEGORIES(Core,
CFG_ENTRY(int, HistorySize, 100)
)
CFG_CATEGORY(Internal,
CFG_ENTRY(QVariantList, Functions, QVariantList())
CFG_ENTRY(QVariantList, Collations, QVariantList())
CFG_ENTRY(QVariantList, Extensions, QVariantList())
CFG_ENTRY(QVariantList, CodeSnippets, QVariantList())
Expand Down Expand Up @@ -185,6 +184,9 @@ class API_EXPORT Config : public QObject
virtual void deleteReport(int id) = 0;
virtual void clearReportHistory() = 0;

virtual QList<QHash<QString, QVariant> > getScriptFunctions() = 0;
virtual void setScriptFunctions(const QList<QHash<QString, QVariant> >& newFunctions) = 0;

virtual void begin() = 0;
virtual void commit() = 0;
virtual void rollback() = 0;
Expand Down
73 changes: 70 additions & 3 deletions SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <QtGlobal>
#include <QDebug>
#include <QList>
#include <QJsonArray>
#include <QJsonDocument>
#include <QDir>
#include <QFileInfo>
#include <QDataStream>
Expand Down Expand Up @@ -616,16 +618,20 @@ QString ConfigImpl::getLegacyConfigPath()
#endif
}

void ConfigImpl::dropTables(const QList<QString>& tables)
{
for (const QString& table : tables)
db->exec("DROP TABLE " + table);
}

void ConfigImpl::initTables()
{
SqlQueryPtr results = db->exec("SELECT lower(name) AS name FROM sqlite_master WHERE type = 'table'");
QList<QString> tables = results->columnAsList<QString>(0);

if (!tables.contains("version"))
{
for (const QString& table : tables)
db->exec("DROP TABLE "+table);

dropTables(tables);
tables.clear();
db->exec("CREATE TABLE version (version NUMERIC)");
db->exec("INSERT INTO version VALUES ("+QString::number(SQLITESTUDIO_CONFIG_VERSION)+")");
Expand Down Expand Up @@ -682,6 +688,10 @@ void ConfigImpl::initTables()

if (!tables.contains("reports_history"))
db->exec("CREATE TABLE reports_history (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, feature_request BOOLEAN, title TEXT, url TEXT)");

if (!tables.contains("script_functions"))
db->exec("CREATE TABLE script_functions (name TEXT, lang TEXT, code TEXT, \"initCode\" TEXT, \"finalCode\" TEXT, databases TEXT, arguments TEXT,"
" \"type\" INTEGER, \"undefinedArgs\" BOOLEAN, \"allDatabases\" BOOLEAN, deterministic BOOLEAN)");
}

void ConfigImpl::initDbFile()
Expand Down Expand Up @@ -1128,6 +1138,29 @@ void ConfigImpl::updateConfigDb()
{
// 2->3
db->exec("ALTER TABLE groups ADD db_expanded INTEGER DEFAULT 0");
Q_FALLTHROUGH();
}
case 3:
{
// 3->4
QVariant oldFuncs = get("Internal", "Functions");
if (oldFuncs.isValid() && !oldFuncs.isNull())
{
for (const QVariant& var : oldFuncs.toList())
{
QHash<QString, QVariant> fnHash = var.toHash();
db->exec("INSERT INTO script_functions"
" (name, lang, code, \"initCode\", \"finalCode\", databases, arguments, \"type\", \"undefinedArgs\", \"allDatabases\", deterministic)"
" VALUES (?, REPLACE(?, 'QtScript', 'JavaScript'), ?, ?, ?, ?, ?, ?, ?, ?, ?)",
{ fnHash["name"].toString(), fnHash["lang"].toString(),
fnHash["code"].toString(), fnHash["initCode"].toString(), fnHash["finalCode"].toString(),
QString::fromUtf8(QJsonDocument(QJsonArray::fromVariantList(fnHash["databases"].toList())).toJson(QJsonDocument::Compact)),
QString::fromUtf8(QJsonDocument(QJsonArray::fromVariantList(fnHash["arguments"].toList())).toJson(QJsonDocument::Compact)),
fnHash["type"].toInt(), fnHash["undefinedArgs"].toBool(), fnHash["allDatabases"].toBool(),
fnHash["deterministic"].toBool() });
}
}
db->exec("DELETE FROM settings WHERE [group] = 'Internal' AND [key] = 'Functions'");
}
// Add cases here for next versions,
// without a "break" instruction,
Expand Down Expand Up @@ -1174,3 +1207,37 @@ void ConfigImpl::refreshDdlHistory()
if (ddlHistoryModel)
ddlHistoryModel->refresh();
}

QList<QHash<QString, QVariant> > ConfigImpl::getScriptFunctions()
{
QList<QHash<QString, QVariant> > list;
SqlQueryPtr results = db->exec("SELECT * FROM script_functions");
while (results->hasNext())
{
SqlResultsRowPtr row = results->next();
QHash<QString, QVariant> fnHash = row->valueMap();
fnHash["databases"] = QJsonDocument::fromJson(row->value("databases").toByteArray()).toVariant();
fnHash["arguments"] = QJsonDocument::fromJson(row->value("arguments").toByteArray()).toVariant();
list << fnHash;
}
return list;
}

void ConfigImpl::setScriptFunctions(const QList<QHash<QString, QVariant> >& newFunctions)
{
db->begin();
db->exec("DELETE FROM script_functions");
for (const QHash<QString, QVariant>& fnHash : newFunctions)
{
db->exec("INSERT INTO script_functions"
" (name, lang, code, \"initCode\", \"finalCode\", databases, arguments,"
" \"type\", \"undefinedArgs\", \"allDatabases\", deterministic)"
" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
{fnHash["name"].toString(), fnHash["lang"].toString(),
fnHash["code"].toString(), fnHash["initCode"].toString(), fnHash["finalCode"].toString(),
QString::fromUtf8(QJsonDocument(QJsonArray::fromVariantList(fnHash["databases"].toList())).toJson(QJsonDocument::Compact)),
QString::fromUtf8(QJsonDocument(QJsonArray::fromVariantList(fnHash["arguments"].toList())).toJson(QJsonDocument::Compact)),
fnHash["type"], fnHash["undefinedArgs"], fnHash["allDatabases"], fnHash["deterministic"]});
}
db->commit();
}
4 changes: 4 additions & 0 deletions SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ class API_EXPORT ConfigImpl : public Config
void deleteReport(int id);
void clearReportHistory();

QList<QHash<QString, QVariant> > getScriptFunctions();
void setScriptFunctions(const QList<QHash<QString, QVariant> >& newFunctions);

void begin();
void commit();
void rollback();
Expand All @@ -110,6 +113,7 @@ class API_EXPORT ConfigImpl : public Config
void storeGroup(const DbGroupPtr& group, qint64 parentId = -1);
void readGroupRecursively(DbGroupPtr group);
QString getConfigPath();
void dropTables(const QList<QString>& tables);
void initTables();
void initDbFile();
QList<ConfigDirCandidate> getStdDbPaths();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,8 @@ void FunctionManagerImpl::refreshFunctionsByKey()

void FunctionManagerImpl::storeInConfig()
{
QVariantList list;
QHash<QString,QVariant> fnHash;
QList<QHash<QString, QVariant> > list;
QHash<QString, QVariant> fnHash;
for (ScriptFunction* func : functions)
{
fnHash["name"] = func->name;
Expand All @@ -352,21 +352,21 @@ void FunctionManagerImpl::storeInConfig()
fnHash["type"] = static_cast<int>(func->type);
fnHash["undefinedArgs"] = func->undefinedArgs;
fnHash["allDatabases"] = func->allDatabases;
fnHash["deterministic"] = func->deterministic;
list << fnHash;
}
CFG_CORE.Internal.Functions.set(list);
CFG->setScriptFunctions(list);
}

void FunctionManagerImpl::loadFromConfig()
{
clearFunctions();

QVariantList list = CFG_CORE.Internal.Functions.get();
QHash<QString,QVariant> fnHash;
QList<QHash<QString, QVariant> > list = CFG->getScriptFunctions();
QHash<QString, QVariant> fnHash;
ScriptFunction* func = nullptr;
for (const QVariant& var : list)
for (const QHash<QString, QVariant>& fnHash : list)
{
fnHash = var.toHash();
func = new ScriptFunction();
func->name = fnHash["name"].toString();
func->lang = updateScriptingQtLang(fnHash["lang"].toString());
Expand All @@ -378,6 +378,7 @@ void FunctionManagerImpl::loadFromConfig()
func->type = static_cast<ScriptFunction::Type>(fnHash["type"].toInt());
func->undefinedArgs = fnHash["undefinedArgs"].toBool();
func->allDatabases = fnHash["allDatabases"].toBool();
func->deterministic = fnHash["deterministic"].toBool();
functions << func;
}
}
Expand Down

0 comments on commit 6aa0114

Please sign in to comment.