aboutsummaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/coreSQLiteStudio/tablemodifier.h
blob: 675202d38056d2cff5bc7f55614f004074cbd4b1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#ifndef TABLEMODIFIER_H
#define TABLEMODIFIER_H

#include "db/db.h"
#include "selectresolver.h"
#include "parser/ast/sqlitecreatetable.h"
#include "parser/ast/sqliteupdate.h"
#include "parser/ast/sqliteinsert.h"
#include "parser/ast/sqlitedelete.h"
#include "parser/ast/sqlitecreateindex.h"
#include "parser/ast/sqlitecreatetrigger.h"
#include "parser/ast/sqlitecreateview.h"
#include "common/strhash.h"

class API_EXPORT TableModifier
{
    public:
        TableModifier(Db* db, const QString& table);
        TableModifier(Db* db, const QString& database, const QString& table);

        void alterTable(SqliteCreateTablePtr newCreateTable);

        QStringList generateSqls() const;
        bool isValid() const;
        QStringList getErrors() const;
        QStringList getWarnings() const;
        QStringList getModifiedTables() const;
        QStringList getModifiedIndexes() const;
        QStringList getModifiedTriggers() const;
        QStringList getModifiedViews() const;
        bool hasMessages() const;

    private:
        void init();
        void parseDdl();
        QString getTempTableName();
        void copyDataTo(const QString& targetTable, const QStringList& srcCols, const QStringList& dstCols);
        void renameTo(const QString& newName);
        QString renameToTemp();
        void copyDataTo(const QString& table);
        void copyDataTo(SqliteCreateTablePtr newCreateTable);

        void handleIndexes();
        void handleIndex(SqliteCreateIndexPtr index);
        void handleTriggers();
        void handleTrigger(SqliteCreateTriggerPtr trigger);
        void handleTriggerQueries(SqliteCreateTriggerPtr trigger);
        void handleViews();
        void handleView(SqliteCreateViewPtr view);
        SqliteQuery* handleTriggerQuery(SqliteQuery* query, const QString& trigName, const QString& trigTable);
        SqliteSelect* handleSelect(SqliteSelect* select, const QString& trigTable = QString());
        SqliteUpdate* handleTriggerUpdate(SqliteUpdate* update, const QString& trigName, const QString& trigTable);
        SqliteInsert* handleTriggerInsert(SqliteInsert* insert, const QString& trigName, const QString& trigTable);
        SqliteDelete* handleTriggerDelete(SqliteDelete* del, const QString& trigName, const QString& trigTable);
        StrHash<SelectResolver::Table> tablesAsNameHash(const QSet<SelectResolver::Table> &resolvedTables);
        bool isTableAliasUsedForColumn(const TokenPtr& token, const StrHash<SelectResolver::Table>& resolvedTables, const QList<SqliteSelect::Core::SingleSource*>& selSources);
        bool handleSubSelects(SqliteStatement* stmt, const QString& trigTable);
        bool handleExprWithSelect(SqliteExpr* expr, const QString& trigTable);
        bool handleAllExprWithTrigTable(SqliteStatement* stmt, const QString& contextTable);
        bool handleExprListWithTrigTable(const QList<SqliteExpr*>& exprList);
        bool handleExprWithTrigTable(SqliteExpr* expr);
        void simpleHandleIndexes();
        void simpleHandleTriggers(const QString& view = QString::null);
        SqliteQueryPtr parseQuery(const QString& ddl);

        /**
         * @brief alterTableHandleFks
         * @param newCreateTable
         * Finds all tables referencing currently modified table and updates their referenced table name and columns.
         */
        void handleFks(const QString& tempTableName);
        void subHandleFks(const QString& oldName, const QString& oldTempName);
        bool subHandleFks(SqliteForeignKey* fk, const QString& oldName, const QString& oldTempName);

        bool handleName(const QString& oldName, QString& valueToUpdate);
        bool handleIndexedColumns(QList<SqliteIndexedColumn*>& columnsToUpdate);
        bool handleColumnNames(QStringList& columnsToUpdate);
        bool handleColumnTokens(TokenList& columnsToUpdate);
        bool handleUpdateColumns(SqliteUpdate* update);

        Db* db = nullptr;
        Dialect dialect;

        /**
         * @brief Database name. The "main" is default.
         * Other databases (temp, attached...) are not supported at the moment.
         */
        QString database;

        /**
         * @brief Current table name (after renaming)
         */
        QString table;

        /**
         * @brief Initial table name, before any renaming.
         */
        QString originalTable;

        /**
         * @brief createTable Original DDL.
         */
        SqliteCreateTablePtr createTable;

        /**
         * @brief Statements to be executed to make changes real.
         */
        QStringList sqls;

        QStringList warnings;
        QStringList errors;

        QString newName;
        QStringList existingColumns;
        QHash<QString, QString> tableColMap;
        QHash<QString, QString> triggerNameToDdlMap;
        QStringList modifiedTables;
        QStringList modifiedIndexes;
        QStringList modifiedTriggers;
        QStringList modifiedViews;
        QStringList usedTempTableNames;
};

#endif // TABLEMODIFIER_H