diff options
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/parser/ast')
29 files changed, 338 insertions, 220 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitealtertable.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitealtertable.cpp index 5ca593f..42cb59b 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitealtertable.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitealtertable.cpp @@ -8,7 +8,8 @@ SqliteAlterTable::SqliteAlterTable() } SqliteAlterTable::SqliteAlterTable(const SqliteAlterTable& other) - : SqliteQuery(other), command(other.command), newName(other.newName), database(other.database), table(other.table), columnKw(other.columnKw) + : SqliteQuery(other), command(other.command), newName(other.newName), database(other.database), table(other.table), + dropColumnName(other.dropColumnName), columnKw(other.columnKw) { DEEP_COPY_FIELD(SqliteCreateTable::Column, newColumn); } @@ -32,10 +33,17 @@ SqliteAlterTable::SqliteAlterTable(const QString& name1, const QString& name2, b column->setParent(this); } +SqliteAlterTable::SqliteAlterTable(const QString& name1, const QString& name2, bool columnKw, const QString& dropColumn) + : SqliteAlterTable() +{ + command = Command::DROP_COLUMN; + initName(name1, name2); + this->columnKw = columnKw; + this->dropColumnName = dropColumn; +} + SqliteAlterTable::~SqliteAlterTable() { -// if (newColumn) - // delete newColumn; } SqliteStatement* SqliteAlterTable::clone() @@ -43,6 +51,15 @@ SqliteStatement* SqliteAlterTable::clone() return new SqliteAlterTable(*this); } +QStringList SqliteAlterTable::getColumnsInStatement() +{ + QStringList list; + if (!dropColumnName.isNull()) + list << dropColumnName; + + return list; +} + QStringList SqliteAlterTable::getTablesInStatement() { QStringList list; @@ -60,6 +77,14 @@ QStringList SqliteAlterTable::getDatabasesInStatement() return getStrListFromValue(database); } +TokenList SqliteAlterTable::getColumnTokensInStatement() +{ + if (command == Command::DROP_COLUMN && tokensMap.contains("nm")) + return extractPrintableTokens(tokensMap["nm"]); + + return TokenList(); +} + TokenList SqliteAlterTable::getTableTokensInStatement() { return getObjectTokenListFromFullname(); @@ -110,17 +135,32 @@ TokenList SqliteAlterTable::rebuildTokensFromContents() builder.withOther(table).withSpace(); - if (newColumn) - { - builder.withKeyword("ADD").withSpace(); - if (columnKw) - builder.withKeyword("COLUMN").withSpace(); - - builder.withStatement(newColumn); - } - else if (!newName.isNull()) - { - builder.withKeyword("RENAME").withSpace().withKeyword("TO").withSpace().withOther(newName); + switch (command) { + case Command::RENAME: + { + builder.withKeyword("RENAME").withSpace().withKeyword("TO").withSpace().withOther(newName); + break; + } + case Command::ADD_COLUMN: + { + builder.withKeyword("ADD").withSpace(); + if (columnKw) + builder.withKeyword("COLUMN").withSpace(); + + builder.withStatement(newColumn); + break; + } + case Command::DROP_COLUMN: + { + builder.withKeyword("DROP").withSpace(); + if (columnKw) + builder.withKeyword("COLUMN").withSpace(); + + builder.withOther(dropColumnName); + break; + } + case Command::null: + break; } builder.withOperator(";"); diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitealtertable.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitealtertable.h index fbac3fe..1733dfc 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitealtertable.h +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitealtertable.h @@ -11,6 +11,7 @@ class API_EXPORT SqliteAlterTable : public SqliteQuery { RENAME, ADD_COLUMN, + DROP_COLUMN, null }; @@ -18,12 +19,15 @@ class API_EXPORT SqliteAlterTable : public SqliteQuery SqliteAlterTable(const SqliteAlterTable& other); SqliteAlterTable(const QString& name1, const QString& name2, const QString& newName); SqliteAlterTable(const QString& name1, const QString& name2, bool columnKw, SqliteCreateTable::Column* column); + SqliteAlterTable(const QString& name1, const QString& name2, bool columnKw, const QString& dropColumn); ~SqliteAlterTable(); SqliteStatement* clone(); protected: + QStringList getColumnsInStatement(); QStringList getTablesInStatement(); QStringList getDatabasesInStatement(); + TokenList getColumnTokensInStatement(); TokenList getTableTokensInStatement(); TokenList getDatabaseTokensInStatement(); QList<FullObject> getFullObjectsInStatement(); @@ -37,6 +41,7 @@ class API_EXPORT SqliteAlterTable : public SqliteQuery QString newName = QString(); QString database = QString(); QString table = QString(); + QString dropColumnName = QString(); bool columnKw = false; SqliteCreateTable::Column* newColumn = nullptr; }; diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecopy.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecopy.cpp deleted file mode 100644 index c3ff500..0000000 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecopy.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "sqlitecopy.h" -#include "sqlitequerytype.h" - -#include <parser/statementtokenbuilder.h> - -SqliteCopy::SqliteCopy() -{ - queryType = SqliteQueryType::Copy; -} - -SqliteCopy::SqliteCopy(const SqliteCopy& other) : - SqliteQuery(other), onConflict(other.onConflict), database(other.database), table(other.table), file(other.file), delimiter(other.delimiter) -{ -} - -SqliteCopy::SqliteCopy(SqliteConflictAlgo onConflict, const QString &name1, const QString &name2, const QString &name3, const QString &delim) - : SqliteCopy() -{ - this->onConflict = onConflict; - - if (!name2.isNull()) - { - database = name1; - table = name2; - } - else - table = name1; - - file = name3; - delimiter = delim; -} - -SqliteStatement* SqliteCopy::clone() -{ - return new SqliteCopy(*this); -} - -QStringList SqliteCopy::getTablesInStatement() -{ - return getStrListFromValue(table); -} - -QStringList SqliteCopy::getDatabasesInStatement() -{ - return getStrListFromValue(database); -} - -TokenList SqliteCopy::getTableTokensInStatement() -{ - return getObjectTokenListFromNmDbnm(); -} - -TokenList SqliteCopy::getDatabaseTokensInStatement() -{ - return getDbTokenListFromNmDbnm(); -} - -QList<SqliteStatement::FullObject> SqliteCopy::getFullObjectsInStatement() -{ - QList<FullObject> result; - - FullObject fullObj = getFullObjectFromNmDbnm(FullObject::TABLE); - if (fullObj.isValid()) - result << fullObj; - - fullObj = getFirstDbFullObject(); - if (fullObj.isValid()) - result << fullObj; - - return result; -} - -TokenList SqliteCopy::rebuildTokensFromContents() -{ - StatementTokenBuilder builder; - builder.withTokens(SqliteQuery::rebuildTokensFromContents()); - builder.withKeyword("COPY").withSpace(); - if (onConflict != SqliteConflictAlgo::null) - builder.withKeyword("OR").withSpace().withKeyword(sqliteConflictAlgo(onConflict)).withSpace(); - - if (!database.isNull()) - builder.withOther(database).withSpace(); - - builder.withOther(table).withSpace().withKeyword("FROM").withSpace().withString(file); - - if (!delimiter.isNull()) - builder.withSpace().withKeyword("USING").withSpace().withKeyword("DELIMITERS").withSpace().withString(delimiter); - - builder.withOperator(";"); - - return builder.build(); -} diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecopy.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecopy.h deleted file mode 100644 index 1e4b5b7..0000000 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecopy.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SQLITECOPY_H -#define SQLITECOPY_H - -#include "sqlitequery.h" -#include "sqliteconflictalgo.h" - -class API_EXPORT SqliteCopy : public SqliteQuery -{ - public: - SqliteCopy(); - SqliteCopy(const SqliteCopy& other); - SqliteCopy(SqliteConflictAlgo onConflict, const QString& name1, const QString& name2, const QString& name3, const QString& delim = QString()); - SqliteStatement* clone(); - - SqliteConflictAlgo onConflict = SqliteConflictAlgo::null; - QString database = QString(); - QString table = QString(); - QString file = QString(); - QString delimiter = QString(); - - protected: - QStringList getTablesInStatement(); - QStringList getDatabasesInStatement(); - TokenList getTableTokensInStatement(); - TokenList getDatabaseTokensInStatement(); - QList<FullObject> getFullObjectsInStatement(); - TokenList rebuildTokensFromContents(); -}; - -typedef QSharedPointer<SqliteCopy> SqliteCopyPtr; - -#endif // SQLITECOPY_H diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.cpp index b747c33..1749e9a 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.cpp @@ -172,3 +172,13 @@ void SqliteCreateIndex::setTargetDatabase(const QString& database) { this->database = database; } + +QString SqliteCreateIndex::getObjectName() const +{ + return index; +} + +void SqliteCreateIndex::setObjectName(const QString& name) +{ + index = name; +} diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.h index 870ed17..b8876a2 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.h +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.h @@ -29,6 +29,8 @@ class API_EXPORT SqliteCreateIndex : public SqliteQuery, public SqliteTableRelat QString getTargetTable() const; QString getTargetDatabase() const; void setTargetDatabase(const QString& database); + QString getObjectName() const; + void setObjectName(const QString& name); bool uniqueKw = false; bool ifNotExistsKw = false; diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.cpp index d82270e..fff4036 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.cpp @@ -1,6 +1,6 @@ #include "sqlitecreatetable.h" +#include "parser/parser_helper_stubs.h" #include "parser/statementtokenbuilder.h" -#include "common/utils_sql.h" #include "common/global.h" const QRegExp SqliteCreateTable::Column::GENERATED_ALWAYS_REGEXP = QRegExp("GENERATED\\s+ALWAYS"); @@ -12,7 +12,7 @@ SqliteCreateTable::SqliteCreateTable() SqliteCreateTable::SqliteCreateTable(const SqliteCreateTable& other) : SqliteQuery(other), ifNotExistsKw(other.ifNotExistsKw), tempKw(other.tempKw), temporaryKw(other.temporaryKw), - database(other.database), table(other.table), withOutRowId(other.withOutRowId) + database(other.database), table(other.table), withOutRowId(other.withOutRowId), strict(other.strict) { DEEP_COPY_COLLECTION(Column, columns); DEEP_COPY_COLLECTION(Constraint, constraints); @@ -40,10 +40,11 @@ SqliteCreateTable::SqliteCreateTable(bool ifNotExistsKw, int temp, const QString } } -SqliteCreateTable::SqliteCreateTable(bool ifNotExistsKw, int temp, const QString& name1, const QString& name2, const QList<SqliteCreateTable::Column*>& columns, const QList<SqliteCreateTable::Constraint*>& constraints, const QString& withOutRowId) : +SqliteCreateTable::SqliteCreateTable(bool ifNotExistsKw, int temp, const QString& name1, const QString& name2, const QList<SqliteCreateTable::Column*>& columns, const QList<SqliteCreateTable::Constraint*>& constraints, const QList<ParserStubCreateTableOption*>& options) : SqliteCreateTable(ifNotExistsKw, temp, name1, name2, columns, constraints) { - this->withOutRowId = withOutRowId; + this->withOutRowId = parserStubFindCreateTableOption(options, ParserStubCreateTableOption::WITHOUT_ROWID) != nullptr; + this->strict = parserStubFindCreateTableOption(options, ParserStubCreateTableOption::STRICT) != nullptr; } SqliteCreateTable::SqliteCreateTable(bool ifNotExistsKw, int temp, const QString &name1, const QString &name2, SqliteSelect *select) @@ -76,7 +77,7 @@ QList<SqliteCreateTable::Constraint*> SqliteCreateTable::getConstraints(SqliteCr SqliteStatement* SqliteCreateTable::getPrimaryKey() const { - for (Constraint* constr : getConstraints(Constraint::PRIMARY_KEY)) + for (Constraint*& constr : getConstraints(Constraint::PRIMARY_KEY)) return constr; Column::Constraint* colConstr = nullptr; @@ -115,7 +116,7 @@ QStringList SqliteCreateTable::getPrimaryKeyColumns() const SqliteCreateTable::Column* SqliteCreateTable::getColumn(const QString& colName) { - for (Column* col : columns) + for (Column*& col : columns) { if (col->name.compare(colName, Qt::CaseInsensitive) == 0) return col; @@ -142,6 +143,18 @@ QList<SqliteCreateTable::Column::Constraint*> SqliteCreateTable::getColumnForeig return results; } +void SqliteCreateTable::removeColumnConstraint(Column::Constraint* constr) +{ + for (Column* col : columns) + { + if (col->constraints.contains(constr)) + { + col->constraints.removeOne(constr); + return; + } + } +} + QStringList SqliteCreateTable::getColumnNames() const { QStringList names; @@ -236,8 +249,21 @@ TokenList SqliteCreateTable::rebuildTokensFromContents() builder.withParRight(); - if (!withOutRowId.isNull()) + bool atLeastOneOption = false; + if (withOutRowId) + { builder.withSpace().withKeyword("WITHOUT").withSpace().withOther("ROWID"); + atLeastOneOption = true; + } + + if (strict) + { + if (atLeastOneOption) + builder.withOperator(","); + + builder.withSpace().withOther("STRICT"); + //atLeastOneOption = true; // to uncomment if there are further options down below + } } builder.withOperator(";"); @@ -564,7 +590,7 @@ bool SqliteCreateTable::Constraint::doesAffectColumn(const QString& columnName) int SqliteCreateTable::Constraint::getAffectedColumnIdx(const QString& columnName) { int i = 0; - for (SqliteIndexedColumn* idxCol : indexedColumns) + for (SqliteIndexedColumn*& idxCol : indexedColumns) { if (idxCol->name.compare(columnName, Qt::CaseInsensitive) == 0) return i; @@ -604,12 +630,12 @@ TokenList SqliteCreateTable::Constraint::rebuildTokensFromContents() { case SqliteCreateTable::Constraint::PRIMARY_KEY: { - builder.withKeyword("PRIMARY").withSpace().withKeyword("KEY").withSpace().withParLeft().withStatementList(indexedColumns).withParRight(); + builder.withKeyword("PRIMARY").withSpace().withKeyword("KEY").withSpace().withParLeft().withStatementList(indexedColumns); if (autoincrKw) builder.withSpace().withKeyword("AUTOINCREMENT"); - builder.withConflict(onConflict); + builder.withParRight().withConflict(onConflict); break; } case SqliteCreateTable::Constraint::UNIQUE: @@ -861,3 +887,13 @@ void SqliteCreateTable::setTargetDatabase(const QString& database) { this->database = database; } + +QString SqliteCreateTable::getObjectName() const +{ + return table; +} + +void SqliteCreateTable::setObjectName(const QString& name) +{ + table = name; +} diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.h index d34688c..5d797c1 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.h +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.h @@ -15,6 +15,8 @@ #include <QList> #include <QRegExp> +struct ParserStubCreateTableOption; + class API_EXPORT SqliteCreateTable : public SqliteQuery, public SqliteDdlWithDbContext { public: @@ -189,7 +191,7 @@ class API_EXPORT SqliteCreateTable : public SqliteQuery, public SqliteDdlWithDbC const QList<Column*>& columns, const QList<Constraint*>& constraints); SqliteCreateTable(bool ifNotExistsKw, int temp, const QString& name1, const QString& name2, const QList<Column*>& columns, const QList<Constraint*>& constraints, - const QString& withOutRowId); + const QList<ParserStubCreateTableOption*>& options); SqliteCreateTable(bool ifNotExistsKw, int temp, const QString& name1, const QString& name2, SqliteSelect* select); ~SqliteCreateTable(); @@ -201,10 +203,13 @@ class API_EXPORT SqliteCreateTable : public SqliteQuery, public SqliteDdlWithDbC Column* getColumn(const QString& colName); QList<Constraint*> getForeignKeysByTable(const QString& foreignTable) const; QList<Column::Constraint*> getColumnForeignKeysByTable(const QString& foreignTable) const; + void removeColumnConstraint(Column::Constraint* constr); QStringList getColumnNames() const; QHash<QString,QString> getModifiedColumnsMap(bool lowercaseKeys = false, Qt::CaseSensitivity cs = Qt::CaseInsensitive) const; QString getTargetDatabase() const; void setTargetDatabase(const QString& database); + QString getObjectName() const; + void setObjectName(const QString& name); bool ifNotExistsKw = false; bool tempKw = false; @@ -213,8 +218,9 @@ class API_EXPORT SqliteCreateTable : public SqliteQuery, public SqliteDdlWithDbC QString table = QString(); QList<Column*> columns; QList<Constraint*> constraints; + bool withOutRowId = false; + bool strict = false; SqliteSelect* select = nullptr; - QString withOutRowId = QString(); protected: QStringList getTablesInStatement(); diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.cpp index 3f2c4e3..597395f 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.cpp @@ -370,3 +370,13 @@ void SqliteCreateTrigger::setTargetDatabase(const QString& database) { this->database = database; } + +QString SqliteCreateTrigger::getObjectName() const +{ + return trigger; +} + +void SqliteCreateTrigger::setObjectName(const QString& name) +{ + trigger = name; +} diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.h index ac7b81f..44b953a 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.h +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.h @@ -66,6 +66,8 @@ class API_EXPORT SqliteCreateTrigger : public SqliteQuery, public SqliteTableRel QString getTargetTable() const; QString getTargetDatabase() const; void setTargetDatabase(const QString& database); + QString getObjectName() const; + void setObjectName(const QString& name); bool tempKw = false; bool temporaryKw = false; diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.cpp index f5b54e7..0e11619 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.cpp @@ -129,3 +129,13 @@ void SqliteCreateView::setTargetDatabase(const QString& database) { this->database = database; } + +QString SqliteCreateView::getObjectName() const +{ + return view; +} + +void SqliteCreateView::setObjectName(const QString& name) +{ + view = name; +} diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.h index 74f6b91..645532c 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.h +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.h @@ -21,6 +21,8 @@ class API_EXPORT SqliteCreateView : public SqliteQuery, public SqliteDdlWithDbCo SqliteStatement* clone(); QString getTargetDatabase() const; void setTargetDatabase(const QString& database); + QString getObjectName() const; + void setObjectName(const QString& name); bool tempKw = false; bool temporaryKw = false; diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteddlwithdbcontext.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteddlwithdbcontext.h index cb64986..0daf378 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteddlwithdbcontext.h +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteddlwithdbcontext.h @@ -9,6 +9,9 @@ class API_EXPORT SqliteDdlWithDbContext public: virtual QString getTargetDatabase() const = 0; virtual void setTargetDatabase(const QString& database) = 0; + + virtual QString getObjectName() const = 0; + virtual void setObjectName(const QString& name) = 0; }; typedef QSharedPointer<SqliteDdlWithDbContext> SqliteDdlWithDbContextPtr; diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitedelete.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitedelete.cpp index dd4d7cb..faf92a4 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitedelete.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitedelete.cpp @@ -16,20 +16,21 @@ SqliteDelete::SqliteDelete(const SqliteDelete& other) : { DEEP_COPY_FIELD(SqliteExpr, where); DEEP_COPY_FIELD(SqliteWith, with); + DEEP_COPY_COLLECTION(SqliteResultColumn, returning); } -SqliteDelete::SqliteDelete(const QString &name1, const QString &name2, const QString& indexedByName, SqliteExpr *where, SqliteWith* with) +SqliteDelete::SqliteDelete(const QString &name1, const QString &name2, const QString& indexedByName, SqliteExpr *where, SqliteWith* with, const QList<SqliteResultColumn*>& returning) : SqliteDelete() { - init(name1, name2, where, with); + init(name1, name2, where, with, returning); this->indexedBy = indexedByName; this->indexedByKw = true; } -SqliteDelete::SqliteDelete(const QString &name1, const QString &name2, bool notIndexedKw, SqliteExpr *where, SqliteWith* with) +SqliteDelete::SqliteDelete(const QString &name1, const QString &name2, bool notIndexedKw, SqliteExpr *where, SqliteWith* with, const QList<SqliteResultColumn*>& returning) : SqliteDelete() { - init(name1, name2, where, with); + init(name1, name2, where, with, returning); this->notIndexedKw = notIndexedKw; } @@ -37,7 +38,7 @@ SqliteDelete::~SqliteDelete() { } -SqliteStatement*SqliteDelete::clone() +SqliteStatement* SqliteDelete::clone() { return new SqliteDelete(*this); } @@ -91,7 +92,7 @@ QList<SqliteStatement::FullObject> SqliteDelete::getFullObjectsInStatement() return result; } -void SqliteDelete::init(const QString &name1, const QString &name2, SqliteExpr *where, SqliteWith* with) +void SqliteDelete::init(const QString &name1, const QString &name2, SqliteExpr *where, SqliteWith* with, const QList<SqliteResultColumn*>& returning) { this->where = where; if (where) @@ -108,6 +109,10 @@ void SqliteDelete::init(const QString &name1, const QString &name2, SqliteExpr * } else table = name1; + + this->returning = returning; + for (SqliteResultColumn*& retCol : this->returning) + retCol->setParent(this); } TokenList SqliteDelete::rebuildTokensFromContents() @@ -131,6 +136,13 @@ TokenList SqliteDelete::rebuildTokensFromContents() if (where) builder.withSpace().withKeyword("WHERE").withStatement(where); + if (!returning.isEmpty()) + { + builder.withKeyword("RETURNING"); + for (SqliteResultColumn*& retCol : returning) + builder.withSpace().withStatement(retCol); + } + builder.withOperator(";"); return builder.build(); diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitedelete.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitedelete.h index 5d24619..faa38fe 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitedelete.h +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitedelete.h @@ -2,8 +2,9 @@ #define SQLITEDELETE_H #include "sqlitequery.h" - +#include "sqliteselect.h" #include <QString> +#include <QList> class SqliteExpr; class SqliteWith; @@ -13,8 +14,10 @@ class API_EXPORT SqliteDelete : public SqliteQuery public: SqliteDelete(); SqliteDelete(const SqliteDelete& other); - SqliteDelete(const QString& name1, const QString& name2, const QString& indexedByName, SqliteExpr* where, SqliteWith* with); - SqliteDelete(const QString& name1, const QString& name2, bool notIndexedKw, SqliteExpr* where, SqliteWith* with); + SqliteDelete(const QString& name1, const QString& name2, const QString& indexedByName, SqliteExpr* where, SqliteWith* with, + const QList<SqliteResultColumn*>& returning); + SqliteDelete(const QString& name1, const QString& name2, bool notIndexedKw, SqliteExpr* where, SqliteWith* with, + const QList<SqliteResultColumn*>& returning); ~SqliteDelete(); SqliteStatement* clone(); @@ -28,7 +31,8 @@ class API_EXPORT SqliteDelete : public SqliteQuery TokenList rebuildTokensFromContents(); private: - void init(const QString& name1, const QString& name2, SqliteExpr* where, SqliteWith* with); + void init(const QString& name1, const QString& name2, SqliteExpr* where, SqliteWith* with, + const QList<SqliteResultColumn*>& returning); public: QString database = QString(); @@ -38,6 +42,7 @@ class API_EXPORT SqliteDelete : public SqliteQuery QString indexedBy = QString(); SqliteExpr* where = nullptr; SqliteWith* with = nullptr; + QList<SqliteResultColumn*> returning; }; typedef QSharedPointer<SqliteDelete> SqliteDeletePtr; diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteexpr.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteexpr.cpp index e2c79ea..89c6b9b 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteexpr.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteexpr.cpp @@ -231,6 +231,19 @@ void SqliteExpr::initUnaryOp(SqliteExpr *expr, const QString& op) expr->setParent(this); } +void SqliteExpr::initPtrOp(SqliteExpr* expr1, const QString& op, SqliteExpr* expr2) +{ + mode = SqliteExpr::Mode::PTR_OP; + this->expr1 = expr1; + this->expr2 = expr2; + ptrOp = op; + if (expr1) + expr1->setParent(this); + + if (expr2) + expr2->setParent(this); +} + void SqliteExpr::initLike(SqliteExpr *expr1, bool notKw, LikeOp likeOp, SqliteExpr *expr2, SqliteExpr *expr3) { mode = SqliteExpr::Mode::LIKE; @@ -271,6 +284,19 @@ void SqliteExpr::initIs(SqliteExpr *expr1, bool notKw, SqliteExpr *expr2) expr2->setParent(this); } +void SqliteExpr::initDistinct(SqliteExpr* expr1, bool notKw, SqliteExpr* expr2) +{ + mode = SqliteExpr::Mode::DISTINCT; + this->expr1 = expr1; + this->notKw = notKw; + this->expr2 = expr2; + if (expr1) + expr1->setParent(this); + + if (expr2) + expr2->setParent(this); +} + void SqliteExpr::initBetween(SqliteExpr *expr1, bool notKw, SqliteExpr *expr2, SqliteExpr *expr3) { mode = SqliteExpr::Mode::BETWEEN; @@ -549,6 +575,9 @@ TokenList SqliteExpr::rebuildTokensFromContents() case SqliteExpr::Mode::BINARY_OP: builder.withStatement(expr1).withSpace().withOperator(binaryOp).withSpace().withStatement(expr2); break; + case SqliteExpr::Mode::PTR_OP: + builder.withStatement(expr1).withSpace().withOperator(ptrOp).withSpace().withStatement(expr2); + break; case SqliteExpr::Mode::FUNCTION: builder.withOther(function).withParLeft(); if (distinctKw) @@ -598,6 +627,9 @@ TokenList SqliteExpr::rebuildTokensFromContents() case SqliteExpr::Mode::IS: builder.withTokens(rebuildIs()); break; + case SqliteExpr::Mode::DISTINCT: + builder.withTokens(rebuildDistinct()); + break; case SqliteExpr::Mode::BETWEEN: builder.withTokens(rebuildBetween()); break; @@ -691,6 +723,17 @@ TokenList SqliteExpr::rebuildIs() return builder.build(); } +TokenList SqliteExpr::rebuildDistinct() +{ + StatementTokenBuilder builder; + builder.withStatement(expr1).withSpace().withKeyword("IS"); + if (notKw) + builder.withSpace().withKeyword("NOT"); + + builder.withSpace().withKeyword("DISTINCT").withSpace().withKeyword("FROM").withSpace().withStatement(expr2); + return builder.build(); +} + TokenList SqliteExpr::rebuildBetween() { StatementTokenBuilder builder; diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteexpr.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteexpr.h index ef4c7da..f5fc6c2 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteexpr.h +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteexpr.h @@ -23,6 +23,7 @@ class API_EXPORT SqliteExpr : public SqliteStatement ID, UNARY_OP, BINARY_OP, + PTR_OP, FUNCTION, SUB_EXPR, ROW_VALUE, @@ -32,6 +33,7 @@ class API_EXPORT SqliteExpr : public SqliteStatement NULL_, NOTNULL, IS, + DISTINCT, BETWEEN, IN, EXISTS, @@ -85,9 +87,11 @@ class API_EXPORT SqliteExpr : public SqliteStatement void initWindowFunction(const QString& fnName, SqliteFilterOver* filterOver); void initBinOp(SqliteExpr* expr1, const QString& op, SqliteExpr* expr2); void initUnaryOp(SqliteExpr* expr, const QString& op); + void initPtrOp(SqliteExpr* expr1, const QString& op, SqliteExpr* expr2); void initLike(SqliteExpr* expr1, bool notKw, SqliteExpr::LikeOp likeOp, SqliteExpr* expr2, SqliteExpr* expr3 = nullptr); void initNull(SqliteExpr* expr, const QString& value); void initIs(SqliteExpr* expr1, bool notKw, SqliteExpr* expr2); + void initDistinct(SqliteExpr* expr1, bool notKw, SqliteExpr* expr2); void initBetween(SqliteExpr* expr1, bool notKw, SqliteExpr* expr2, SqliteExpr* expr3); void initIn(SqliteExpr* expr, bool notKw, const QList<SqliteExpr*>& exprList); void initIn(SqliteExpr* expr, bool notKw, SqliteSelect* select); @@ -108,6 +112,7 @@ class API_EXPORT SqliteExpr : public SqliteStatement QString column = QString(); QString unaryOp = QString(); QString binaryOp = QString(); + QString ptrOp = QString(); QString function = QString(); QString collation = QString(); QString ctime = QString(); @@ -144,6 +149,7 @@ class API_EXPORT SqliteExpr : public SqliteStatement TokenList rebuildLike(); TokenList rebuildNotNull(); TokenList rebuildIs(); + TokenList rebuildDistinct(); TokenList rebuildBetween(); TokenList rebuildIn(); TokenList rebuildCase(); diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteinsert.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteinsert.cpp index 906b385..5242fa6 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteinsert.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteinsert.cpp @@ -20,14 +20,14 @@ SqliteInsert::SqliteInsert(const SqliteInsert& other) : DEEP_COPY_FIELD(SqliteSelect, select); DEEP_COPY_FIELD(SqliteWith, with); DEEP_COPY_FIELD(SqliteUpsert, upsert); + DEEP_COPY_COLLECTION(SqliteResultColumn, returning); } SqliteInsert::SqliteInsert(bool replace, SqliteConflictAlgo onConflict, const QString &name1, const QString &name2, const QList<QString> &columns, - const QList<SqliteExpr *> &row, SqliteWith* with) : + const QList<SqliteExpr *> &row, SqliteWith* with, const QList<SqliteResultColumn*>& returning) : SqliteInsert() { - initName(name1, name2); - initMode(replace, onConflict); + init(name1, name2, replace, onConflict, returning); columnNames = columns; values = row; @@ -40,11 +40,10 @@ SqliteInsert::SqliteInsert(bool replace, SqliteConflictAlgo onConflict, const QS } SqliteInsert::SqliteInsert(bool replace, SqliteConflictAlgo onConflict, const QString &name1, const QString &name2, const QList<QString> &columns, - SqliteSelect *select, SqliteWith* with, SqliteUpsert* upsert) : + SqliteSelect *select, SqliteWith* with, SqliteUpsert* upsert, const QList<SqliteResultColumn*>& returning) : SqliteInsert() { - initName(name1, name2); - initMode(replace, onConflict); + init(name1, name2, replace, onConflict, returning); this->with = with; if (with) @@ -61,11 +60,10 @@ SqliteInsert::SqliteInsert(bool replace, SqliteConflictAlgo onConflict, const QS } SqliteInsert::SqliteInsert(bool replace, SqliteConflictAlgo onConflict, const QString &name1, const QString &name2, const QList<QString> &columns, - SqliteWith* with) : + SqliteWith* with, const QList<SqliteResultColumn*>& returning) : SqliteInsert() { - initName(name1, name2); - initMode(replace, onConflict); + init(name1, name2, replace, onConflict, returning); this->with = with; if (with) @@ -104,7 +102,7 @@ QStringList SqliteInsert::getDatabasesInStatement() TokenList SqliteInsert::getColumnTokensInStatement() { TokenList list; - for (TokenPtr token : getTokenListFromNamedKey("idlist_opt", -1)) + for (TokenPtr& token : getTokenListFromNamedKey("idlist_opt", -1)) { if (token->type != Token::OTHER && token->type != Token::KEYWORD) continue; @@ -153,7 +151,7 @@ QList<SqliteStatement::FullObject> SqliteInsert::getFullObjectsInStatement() return result; } -void SqliteInsert::initName(const QString& name1, const QString& name2) +void SqliteInsert::init(const QString& name1, const QString& name2, bool replace, SqliteConflictAlgo onConflict, const QList<SqliteResultColumn*>& returning) { if (!name2.isNull()) { @@ -162,12 +160,13 @@ void SqliteInsert::initName(const QString& name1, const QString& name2) } else table = name1; -} -void SqliteInsert::initMode(bool replace, SqliteConflictAlgo onConflict) -{ replaceKw = replace; this->onConflict = onConflict; + + this->returning = returning; + for (SqliteResultColumn*& retCol : this->returning) + retCol->setParent(this); } TokenList SqliteInsert::rebuildTokensFromContents() @@ -212,6 +211,13 @@ TokenList SqliteInsert::rebuildTokensFromContents() } } + if (!returning.isEmpty()) + { + builder.withKeyword("RETURNING"); + for (SqliteResultColumn*& retCol : returning) + builder.withSpace().withStatement(retCol); + } + builder.withOperator(";"); return builder.build(); diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteinsert.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteinsert.h index 40581cd..b409abc 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteinsert.h +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteinsert.h @@ -3,10 +3,10 @@ #include "sqlitequery.h" #include "sqliteconflictalgo.h" +#include "sqliteselect.h" #include <QString> #include <QList> -class SqliteSelect; class SqliteExpr; class SqliteWith; class SqliteUpsert; @@ -18,11 +18,14 @@ class API_EXPORT SqliteInsert : public SqliteQuery SqliteInsert(const SqliteInsert& other); SqliteInsert(bool replace, SqliteConflictAlgo onConflict, const QString& name1, const QString& name2, const QList<QString>& columns, - const QList<SqliteExpr*>& row, SqliteWith* with); + const QList<SqliteExpr*>& row, SqliteWith* with, + const QList<SqliteResultColumn*>& returning); SqliteInsert(bool replace, SqliteConflictAlgo onConflict, const QString& name1, - const QString& name2, const QList<QString>& columns, SqliteSelect* select, SqliteWith* with, SqliteUpsert* upsert = nullptr); + const QString& name2, const QList<QString>& columns, SqliteSelect* select, SqliteWith* with, + SqliteUpsert* upsert, const QList<SqliteResultColumn*>& returning); SqliteInsert(bool replace, SqliteConflictAlgo onConflict, const QString& name1, - const QString& name2, const QList<QString>& columns, SqliteWith* with); + const QString& name2, const QList<QString>& columns, SqliteWith* with, + const QList<SqliteResultColumn*>& returning); ~SqliteInsert(); SqliteStatement* clone(); @@ -38,8 +41,8 @@ class API_EXPORT SqliteInsert : public SqliteQuery TokenList rebuildTokensFromContents(); private: - void initName(const QString& name1, const QString& name2); - void initMode(bool replace, SqliteConflictAlgo onConflict); + void init(const QString& name1, const QString& name2, bool replace, SqliteConflictAlgo onConflict, + const QList<SqliteResultColumn*>& returning); public: bool replaceKw = false; @@ -52,6 +55,7 @@ class API_EXPORT SqliteInsert : public SqliteQuery SqliteSelect* select = nullptr; SqliteWith* with = nullptr; SqliteUpsert* upsert = nullptr; + QList<SqliteResultColumn*> returning; }; typedef QSharedPointer<SqliteInsert> SqliteInsertPtr; diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.cpp index 732c0a2..4db4b5d 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.cpp @@ -88,18 +88,20 @@ void SqliteOrderBy::setColumnName(const QString& name) void SqliteOrderBy::setCollation(const QString& name) { - if (expr && expr->mode == SqliteExpr::Mode::COLLATE) + if (!expr) + return; + + if (expr->mode == SqliteExpr::Mode::COLLATE) { expr->collation = name; + return; } - else - { - SqliteExpr* theExpr = expr; - SqliteExpr* collationExpr = new SqliteExpr(); - collationExpr->initCollate(theExpr, name); - theExpr->setParent(collationExpr); - collationExpr->setParent(this); - } + + SqliteExpr* collationExpr = new SqliteExpr(); + collationExpr->initCollate(expr, name); + expr->setParent(collationExpr); + collationExpr->setParent(this); + expr = collationExpr; } TokenList SqliteOrderBy::rebuildTokensFromContents() diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitequerytype.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitequerytype.cpp index 1c04ca6..b70778e 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitequerytype.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitequerytype.cpp @@ -60,9 +60,8 @@ QString sqliteQueryTypeToString(const SqliteQueryType& type) return "Update"; case SqliteQueryType::Vacuum: return "Vacuum"; - default: - return QString(); } + return QString(); } bool isDataReturningQuery(const SqliteQueryType& type) @@ -98,7 +97,7 @@ bool isDataReturningQuery(const SqliteQueryType& type) case SqliteQueryType::Savepoint: case SqliteQueryType::Update: case SqliteQueryType::Vacuum: - default: return false; } + return false; } diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteselect.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteselect.cpp index e0439d2..501f7f3 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteselect.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteselect.cpp @@ -118,7 +118,7 @@ SqliteSelect::CompoundOperator SqliteSelect::compoundOperator(const QString& op) void SqliteSelect::reset() { - for (Core* core : coreSelects) + for (Core*& core : coreSelects) delete core; coreSelects.clear(); @@ -443,7 +443,7 @@ QStringList SqliteSelect::Core::JoinConstraint::getColumnsInStatement() TokenList SqliteSelect::Core::JoinConstraint::getColumnTokensInStatement() { TokenList list; - for (TokenPtr token : getTokenListFromNamedKey("idlist", -1)) + for (TokenPtr& token : getTokenListFromNamedKey("idlist", -1)) { if (token->type == Token::OPERATOR) // a COMMA continue; @@ -573,7 +573,7 @@ SqliteSelect::Core::JoinSource::JoinSource(SqliteSelect::Core::SingleSource *sin if (singleSource) singleSource->setParent(this); - for (JoinSourceOther* other : otherSources) + for (JoinSourceOther*& other : otherSources) other->setParent(this); } @@ -667,11 +667,6 @@ TokenList SqliteSelect::Core::SingleSource::rebuildTokensFromContents() TokenList SqliteSelect::Core::JoinOp::rebuildTokensFromContents() { - return rebuildTokensForSqlite3(); -} - -TokenList SqliteSelect::Core::JoinOp::rebuildTokensForSqlite3() -{ StatementTokenBuilder builder; if (comma) { @@ -682,9 +677,16 @@ TokenList SqliteSelect::Core::JoinOp::rebuildTokensForSqlite3() if (naturalKw) builder.withKeyword("NATURAL").withSpace(); - if (leftKw) + if (leftKw || fullKw || rightKw) { - builder.withKeyword("LEFT").withSpace(); + if (leftKw) + builder.withKeyword("LEFT"); + else if (fullKw) + builder.withKeyword("FULL"); + else if (rightKw) + builder.withKeyword("RIGHT"); + + builder.withSpace(); if (outerKw) builder.withKeyword("OUTER").withSpace(); } @@ -780,7 +782,7 @@ TokenList SqliteSelect::rebuildTokensFromContents() if (with) builder.withStatement(with); - for (SqliteSelect::Core* core : coreSelects) + for (SqliteSelect::Core*& core : coreSelects) { if (core->compoundOp == CompoundOperator::UNION_ALL) { diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteselect.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteselect.h index 58babfe..dfed9c2 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteselect.h +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteselect.h @@ -123,9 +123,6 @@ class API_EXPORT SqliteSelect : public SqliteQuery protected: TokenList rebuildTokensFromContents(); - - private: - TokenList rebuildTokensForSqlite3(); }; class API_EXPORT JoinConstraint : public SqliteStatement @@ -232,5 +229,6 @@ class API_EXPORT SqliteSelect : public SqliteQuery }; typedef QSharedPointer<SqliteSelect> SqliteSelectPtr; +typedef SqliteSelect::Core::ResultColumn SqliteResultColumn; #endif // SQLITESELECT_H diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitestatement.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitestatement.h index 43a60ba..167321f 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitestatement.h +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitestatement.h @@ -228,6 +228,12 @@ class API_EXPORT SqliteStatement : public QObject virtual SqliteStatement* clone() = 0; template <class T> + T* typeClone() + { + return dynamic_cast<T*>(clone()); + } + + template <class T> void attach(QList<T*>& listMemberForChild, T* childStatementToAttach) { listMemberForChild << childStatementToAttach; diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteupdate.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteupdate.cpp index 89c8195..55d8b34 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteupdate.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteupdate.cpp @@ -27,6 +27,7 @@ SqliteUpdate::SqliteUpdate(const SqliteUpdate& other) : DEEP_COPY_FIELD(SqliteExpr, where); DEEP_COPY_FIELD(SqliteWith, with); DEEP_COPY_FIELD(SqliteSelect::Core::JoinSource, from); + DEEP_COPY_COLLECTION(SqliteResultColumn, returning); } SqliteUpdate::~SqliteUpdate() @@ -34,7 +35,7 @@ SqliteUpdate::~SqliteUpdate() } SqliteUpdate::SqliteUpdate(SqliteConflictAlgo onConflict, const QString &name1, const QString &name2, bool notIndexedKw, const QString &indexedBy, - const QList<ColumnAndValue>& values, SqliteSelect::Core::JoinSource* from, SqliteExpr *where, SqliteWith* with) + const QList<ColumnAndValue>& values, SqliteSelect::Core::JoinSource* from, SqliteExpr *where, SqliteWith* with, const QList<SqliteResultColumn*>& returning) : SqliteUpdate() { this->onConflict = onConflict; @@ -64,8 +65,12 @@ SqliteUpdate::SqliteUpdate(SqliteConflictAlgo onConflict, const QString &name1, if (with) with->setParent(this); - for (const ColumnAndValue& keyValue : keyValueMap) + for (ColumnAndValue& keyValue : keyValueMap) keyValue.second->setParent(this); + + this->returning = returning; + for (SqliteResultColumn*& retCol : this->returning) + retCol->setParent(this); } SqliteStatement*SqliteUpdate::clone() @@ -75,7 +80,7 @@ SqliteStatement*SqliteUpdate::clone() SqliteExpr* SqliteUpdate::getValueForColumnSet(const QString& column) { - for (const ColumnAndValue& keyValue : keyValueMap) + for (ColumnAndValue& keyValue : keyValueMap) { if (keyValue.first == column) return keyValue.second; @@ -86,7 +91,7 @@ SqliteExpr* SqliteUpdate::getValueForColumnSet(const QString& column) QStringList SqliteUpdate::getColumnsInStatement() { QStringList columns; - for (const ColumnAndValue& keyValue : keyValueMap) + for (ColumnAndValue& keyValue : keyValueMap) { if (keyValue.first.type() == QVariant::StringList) columns += keyValue.first.toStringList(); @@ -120,7 +125,7 @@ TokenList SqliteUpdate::getColumnTokensInStatement() int end; int start = 0; SqliteExpr* expr = nullptr; - for (const ColumnAndValue& keyValue : keyValueMap) + for (ColumnAndValue& keyValue : keyValueMap) { expr = keyValue.second; end = setListTokens.indexOf(expr->tokens[0]); @@ -205,7 +210,7 @@ TokenList SqliteUpdate::rebuildTokensFromContents() builder.withKeyword("SET").withSpace(); bool first = true; - for (const ColumnAndValue& keyVal : keyValueMap) + for (ColumnAndValue& keyVal : keyValueMap) { if (!first) builder.withOperator(",").withSpace(); @@ -225,6 +230,13 @@ TokenList SqliteUpdate::rebuildTokensFromContents() if (where) builder.withSpace().withKeyword("WHERE").withStatement(where); + if (!returning.isEmpty()) + { + builder.withKeyword("RETURNING"); + for (SqliteResultColumn*& retCol : returning) + builder.withSpace().withStatement(retCol); + } + builder.withOperator(";"); return builder.build(); diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteupdate.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteupdate.h index e843bcd..be121b2 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteupdate.h +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteupdate.h @@ -21,7 +21,7 @@ class API_EXPORT SqliteUpdate : public SqliteQuery ~SqliteUpdate(); SqliteUpdate(SqliteConflictAlgo onConflict, const QString& name1, const QString& name2, bool notIndexedKw, const QString& indexedBy, const QList<ColumnAndValue>& values, - SqliteSelect::Core::JoinSource* from, SqliteExpr* where, SqliteWith* with); + SqliteSelect::Core::JoinSource* from, SqliteExpr* where, SqliteWith* with, const QList<SqliteResultColumn*>& returning); SqliteStatement* clone(); SqliteExpr* getValueForColumnSet(const QString& column); @@ -36,6 +36,7 @@ class API_EXPORT SqliteUpdate : public SqliteQuery SqliteSelect::Core::JoinSource* from = nullptr; SqliteExpr* where = nullptr; SqliteWith* with = nullptr; + QList<SqliteResultColumn*> returning; protected: QStringList getColumnsInStatement(); diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitewindowdefinition.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitewindowdefinition.cpp index adf135f..69138b6 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitewindowdefinition.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitewindowdefinition.cpp @@ -265,7 +265,7 @@ SqliteWindowDefinition::Window::Frame::Bound::Bound(SqliteExpr* expr, const QStr if (upper == "UNBOUNDED PRECEDING") type = Type::UNBOUNDED_PRECEDING; else if (expr && upper == "PRECEDING") - type = Type::EXPR_FOLLOWING; + type = Type::EXPR_PRECEDING; else if (upper == "UNBOUNDED FOLLOWING") type = Type::UNBOUNDED_FOLLOWING; else if (expr && upper == "FOLLOWING") diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitewith.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitewith.cpp index 901ac56..c15b447 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitewith.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitewith.cpp @@ -36,19 +36,19 @@ SqliteWith::CommonTableExpression::CommonTableExpression() } SqliteWith::CommonTableExpression::CommonTableExpression(const SqliteWith::CommonTableExpression& other) : - SqliteStatement(other), table(other.table) + SqliteStatement(other), table(other.table), asMode(other.asMode) { DEEP_COPY_COLLECTION(SqliteIndexedColumn, indexedColumns); DEEP_COPY_FIELD(SqliteSelect, select); } -SqliteWith::CommonTableExpression::CommonTableExpression(const QString& tableName, const QList<SqliteIndexedColumn*>& indexedColumns, SqliteSelect* select) : - table(tableName), indexedColumns(indexedColumns), select(select) +SqliteWith::CommonTableExpression::CommonTableExpression(const QString& tableName, const QList<SqliteIndexedColumn*>& indexedColumns, SqliteSelect* select, AsMode asMode) : + table(tableName), indexedColumns(indexedColumns), select(select), asMode(asMode) { select->setParent(this); } -SqliteStatement*SqliteWith::CommonTableExpression::clone() +SqliteStatement* SqliteWith::CommonTableExpression::clone() { return new SqliteWith::CommonTableExpression(*this); } @@ -61,7 +61,19 @@ TokenList SqliteWith::CommonTableExpression::rebuildTokensFromContents() if (indexedColumns.size() > 0) builder.withSpace().withParLeft().withStatementList(indexedColumns).withParRight(); - builder.withSpace().withKeyword("AS").withSpace().withParLeft().withStatement(select).withParRight(); + builder.withSpace().withKeyword("AS"); + switch (asMode) { + case ANY: + break; + case MATERIALIZED: + builder.withKeyword("MATERIALIZED"); + break; + case NOT_MATERIALIZED: + builder.withKeyword("NOT").withSpace().withKeyword("MATERIALIZED"); + break; + } + + builder.withSpace().withParLeft().withStatement(select).withParRight(); return builder.build(); } diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitewith.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitewith.h index 30f8181..8429e53 100644 --- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitewith.h +++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitewith.h @@ -12,15 +12,23 @@ class SqliteWith : public SqliteStatement class CommonTableExpression : public SqliteStatement { public: + enum AsMode { + ANY, + MATERIALIZED, + NOT_MATERIALIZED + }; + CommonTableExpression(); CommonTableExpression(const CommonTableExpression& other); - CommonTableExpression(const QString& tableName, const QList<SqliteIndexedColumn*>& indexedColumns, SqliteSelect* select); + CommonTableExpression(const QString& tableName, const QList<SqliteIndexedColumn*>& indexedColumns, SqliteSelect* select, + AsMode asMode); SqliteStatement* clone(); QString table; QList<SqliteIndexedColumn*> indexedColumns; SqliteSelect* select = nullptr; + AsMode asMode = ANY; protected: TokenList rebuildTokensFromContents(); |
