001package gudusoft.gsqlparser.sqlcmds;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.stmt.*;
005import gudusoft.gsqlparser.stmt.postgresql.*;
006import gudusoft.gsqlparser.stmt.sqlite.TAttachStmt;
007import gudusoft.gsqlparser.stmt.sqlite.TSqliteCreateVirtualTableStmt;
008import gudusoft.gsqlparser.stmt.sqlite.TDetachStmt;
009import gudusoft.gsqlparser.stmt.sqlite.TPragmaStmt;
010
011/**
012 * SQLite SQL command resolver.
013 * Handles SQLite statement recognition.
014 * Based on PostgreSQL command resolver since SQLite uses PostgreSQL grammar as its base.
015 *
016 * @since 3.2.0.0
017 */
018public class TSqlCmdsSqlite extends AbstractSqlCmds {
019
020    public TSqlCmdsSqlite() {
021        super(EDbVendor.dbvsqlite);
022    }
023
024    @Override
025    protected void initializeCommands() {
026        // SQLite commands - subset of PostgreSQL plus SQLite-specific statements
027
028        // ALTER TABLE
029        addCmd(TBaseType.rrw_alter, "table", ESqlStatementType.sstaltertable);
030
031        // ANALYZE
032        addCmd(TBaseType.rrw_analyze, ESqlStatementType.sstpostgresqlAnalyze);
033
034        // BEGIN (transaction)
035        addCmd(TBaseType.rrw_begin, ESqlStatementType.sstpostgresqlBegin);
036
037        // COMMIT
038        addCmd(TBaseType.rrw_commit, ESqlStatementType.sstpostgresqlCommit);
039
040        // CREATE commands
041        addCmd(TBaseType.rrw_create, "index", ESqlStatementType.sstpostgresqlCreateIndex);
042        addCmd(TBaseType.rrw_create, "table", ESqlStatementType.sstcreatetable);
043        addCmd(TBaseType.rrw_create, "temp", "table", ESqlStatementType.sstcreatetable);
044        addCmd(TBaseType.rrw_create, "temporary", "table", ESqlStatementType.sstcreatetable);
045        addCmd(TBaseType.rrw_create, "trigger", ESqlStatementType.sstcreatetrigger);
046        addCmd(TBaseType.rrw_create, "unique", "index", ESqlStatementType.sstpostgresqlCreateIndex);
047        addCmd(TBaseType.rrw_create, "view", ESqlStatementType.sstpostgresqlCreateView);
048        addCmd(TBaseType.rrw_create, "temp", "view", ESqlStatementType.sstpostgresqlCreateView);
049        addCmd(TBaseType.rrw_create, "temporary", "view", ESqlStatementType.sstpostgresqlCreateView);
050        addCmd(TBaseType.rrw_create, "virtual", "table", ESqlStatementType.sstSqliteCreateVirtualTable);
051
052        // DELETE
053        addCmd(TBaseType.rrw_delete, ESqlStatementType.sstdelete);
054
055        // DROP commands
056        addCmd(TBaseType.rrw_drop, "index", ESqlStatementType.sstdropindex);
057        addCmd(TBaseType.rrw_drop, "table", ESqlStatementType.sstpostgresqlDropTable);
058        addCmd(TBaseType.rrw_drop, "trigger", ESqlStatementType.sstpostgresqlDropTrigger);
059        addCmd(TBaseType.rrw_drop, "view", ESqlStatementType.sstpostgresqlDropView);
060
061        // END (transaction - alias for COMMIT)
062        addCmd(TBaseType.rrw_end, ESqlStatementType.sstpostgresqlEnd);
063
064        // EXPLAIN
065        addCmd(TBaseType.rrw_explain, ESqlStatementType.sstpostgresqlExplain);
066
067        // INSERT
068        addCmd(TBaseType.rrw_insert, ESqlStatementType.sstinsert);
069
070        // ATTACH DATABASE
071        addCmd(TBaseType.rrw_sqlite_attach, ESqlStatementType.sstSqliteAttach);
072        addCmd(TBaseType.rrw_sqlite_attach, "database", ESqlStatementType.sstSqliteAttach);
073
074        // DETACH DATABASE
075        addCmd(TBaseType.rrw_sqlite_detach, ESqlStatementType.sstSqliteDetach);
076        addCmd(TBaseType.rrw_sqlite_detach, "database", ESqlStatementType.sstSqliteDetach);
077
078        // PRAGMA
079        addCmd(TBaseType.rrw_sqlite_pragma, ESqlStatementType.sstSqlitePragma);
080
081        // REPLACE (equivalent to INSERT OR REPLACE)
082        addCmd(TBaseType.rrw_replace, ESqlStatementType.sstinsert);
083
084        // REINDEX
085        addCmd(TBaseType.rrw_postgresql_reindex, ESqlStatementType.sstReindex);
086
087        // RELEASE (savepoint)
088        addCmd(TBaseType.rrw_release, ESqlStatementType.sstpostgresqlReleaseSavepoint);
089        addCmd(TBaseType.rrw_release, "savepoint", ESqlStatementType.sstpostgresqlReleaseSavepoint);
090
091        // ROLLBACK
092        addCmd(TBaseType.rrw_rollback, ESqlStatementType.sstpostgresqlRollback);
093        addCmd(TBaseType.rrw_rollback, "to", "savepoint", ESqlStatementType.sstpostgresqlRollbackToSavepoint);
094
095        // SAVEPOINT
096        addCmd(TBaseType.rrw_savepoint, ESqlStatementType.sstpostgresqlSavepoint);
097
098        // SELECT
099        addCmd(TBaseType.rrw_select, ESqlStatementType.sstselect);
100        addCmd(TBaseType.rrw_table, ESqlStatementType.sstselect);  // TABLE t = SELECT * FROM t
101
102        // UPDATE
103        addCmd(TBaseType.rrw_update, ESqlStatementType.sstupdate);
104
105        // VACUUM
106        addCmd(TBaseType.rrw_postgresql_vacuum, ESqlStatementType.sstVacuum);
107
108        // VALUES
109        addCmd(TBaseType.rrw_values, ESqlStatementType.sstValues);
110    }
111
112    @Override
113    public TCustomSqlStatement issql(TSourceToken token, EFindSqlStateType state, TCustomSqlStatement currentStatement) {
114        TCustomSqlStatement ret = null;
115
116        gnewsqlstatementtype = ESqlStatementType.sstinvalid;
117
118        // Skip comments, whitespace, and semicolons
119        if ((token.tokencode == TBaseType.cmtdoublehyphen)
120                || (token.tokencode == TBaseType.cmtslashstar)
121                || (token.tokencode == TBaseType.lexspace)
122                || (token.tokencode == TBaseType.lexnewline)
123                || (token.tokentype == ETokenType.ttsemicolon)) {
124            return null;
125        }
126
127        int lcpos = token.posinlist;
128        TSourceTokenList lcsourcetokenlist = token.container;
129        TCustomSqlStatement lccurrentsqlstatement = currentStatement;
130
131        // Subquery after semicolon or at first line
132        if ((state == EFindSqlStateType.stnormal) && (token.tokentype == ETokenType.ttleftparenthesis)) {
133            int k = lcsourcetokenlist.solidtokenafterpos(lcpos, TBaseType.rrw_select, 1, "(");
134            if (k > 0) {
135                ret = new TSelectSqlStatement(vendor);
136            }
137            return ret;
138        }
139
140        // CTE detection
141        if ((state == EFindSqlStateType.stnormal) && (token.tokencode == TBaseType.rrw_with)) {
142            ret = findcte(token);
143            if (ret != null) return ret;
144        }
145
146        gnewsqlstatementtype = getStatementTypeForToken(token);
147
148        TSourceToken lcprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcpos);
149
150        switch (gnewsqlstatementtype) {
151            case sstinvalid: {
152                ret = null;
153                break;
154            }
155
156            case sstselect: {
157                boolean lcisnewsql = true;
158
159                if (state != EFindSqlStateType.stnormal) {
160                    if (lccurrentsqlstatement != null) {
161                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger)
162                            lcisnewsql = false;
163                    }
164                    if (lcisnewsql) {
165                        if (lcprevsolidtoken != null) {
166                            if (lcprevsolidtoken.tokentype == ETokenType.ttleftparenthesis)
167                                lcisnewsql = false;
168                            else if (lcprevsolidtoken.tokencode == TBaseType.rrw_union)
169                                lcisnewsql = false;
170                            else if (lcprevsolidtoken.tokencode == TBaseType.rrw_intersect)
171                                lcisnewsql = false;
172                            else if (lcprevsolidtoken.tokencode == TBaseType.rrw_except)
173                                lcisnewsql = false;
174                            else if (lcprevsolidtoken.tokencode == TBaseType.rrw_as) {
175                                if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetable)
176                                    lcisnewsql = false;
177                                if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreateview)
178                                    lcisnewsql = false;
179                            }
180
181                            if (lcisnewsql && (lcprevsolidtoken.tokencode == TBaseType.rrw_all)) {
182                                TSourceToken lcpprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcprevsolidtoken.posinlist);
183                                if (lcpprevsolidtoken != null) {
184                                    if (lcpprevsolidtoken.tokencode == TBaseType.rrw_union)
185                                        lcisnewsql = false;
186                                }
187                            }
188                        }
189
190                        if (lccurrentsqlstatement != null) {
191                            if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstinsert)
192                                lcisnewsql = false;
193                        }
194                    }
195                }
196
197                if (lcisnewsql)
198                    ret = new TSelectSqlStatement(vendor);
199
200                break;
201            }
202
203            case sstinsert: {
204                boolean lcisnewsql = true;
205                if (state != EFindSqlStateType.stnormal) {
206                    if (lccurrentsqlstatement != null) {
207                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger)
208                            lcisnewsql = false;
209                    }
210                }
211
212                if (lcisnewsql)
213                    ret = new TInsertSqlStatement(vendor);
214
215                break;
216            }
217
218            case sstupdate: {
219                boolean lcisnewsql = true;
220                if (state != EFindSqlStateType.stnormal) {
221                    if (lccurrentsqlstatement != null) {
222                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger)
223                            lcisnewsql = false;
224                    }
225                    if (lcisnewsql) {
226                        lcprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcpos);
227                        if (lcprevsolidtoken != null) {
228                            if (lcprevsolidtoken.tokencode == TBaseType.rrw_on)
229                                lcisnewsql = false;
230                            else if (lcprevsolidtoken.tokencode == TBaseType.rrw_for)
231                                lcisnewsql = false;
232                        }
233
234                        TSourceToken lcnextsolidtoken = lcsourcetokenlist.nextsolidtoken(lcpos, 1, false);
235                        if (lcnextsolidtoken != null) {
236                            if (lcnextsolidtoken.tokentype == ETokenType.ttleftparenthesis) {
237                                int k = lcsourcetokenlist.solidtokenafterpos(lcnextsolidtoken.posinlist, TBaseType.rrw_select, 1, "(");
238                                if (k == 0) lcisnewsql = false;
239                            }
240                        }
241                    }
242                }
243
244                if (lcisnewsql) {
245                    ret = new TUpdateSqlStatement(vendor);
246                    ret.dummytag = 1;
247                }
248                break;
249            }
250
251            case sstdelete: {
252                boolean lcisnewsql = true;
253
254                if (state != EFindSqlStateType.stnormal) {
255                    if (lccurrentsqlstatement != null) {
256                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger)
257                            lcisnewsql = false;
258                    }
259                    if (lcisnewsql) {
260                        lcprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcpos);
261                        if (lcprevsolidtoken != null) {
262                            if (lcprevsolidtoken.tokencode == TBaseType.rrw_on)
263                                lcisnewsql = false;
264                        }
265                    }
266                }
267
268                if (lcisnewsql)
269                    ret = new TDeleteSqlStatement(vendor);
270
271                break;
272            }
273
274            case sstcreatetable:
275                ret = new TCreateTableSqlStatement(vendor);
276                break;
277
278            case sstaltertable:
279                ret = new TAlterTableStatement(vendor);
280                break;
281
282            case sstpostgresqlCreateIndex:
283                ret = new TCreateIndexSqlStatement(vendor);
284                break;
285
286            case sstpostgresqlCreateView:
287                ret = new TCreateViewSqlStatement(vendor);
288                break;
289
290            case sstcreatetrigger:
291                ret = new TCreateTriggerStmt(vendor);
292                break;
293
294            case sstpostgresqlDropTable:
295                ret = new TDropTableSqlStatement(vendor);
296                break;
297
298            case sstpostgresqlDropView:
299                ret = new TDropViewSqlStatement(vendor);
300                break;
301
302            case sstpostgresqlDropTrigger:
303                ret = new TDropTriggerSqlStatement(vendor);
304                break;
305
306            case sstdropindex:
307                ret = new TDropIndexSqlStatement(vendor);
308                break;
309
310            case sstpostgresqlCommit:
311                ret = new TCommitStmt(vendor);
312                break;
313
314            case sstVacuum:
315                ret = new TVacuumStmt(vendor);
316                break;
317
318            case sstReindex:
319                ret = new TReindexStmt(vendor);
320                break;
321
322            case sstSqlitePragma:
323                ret = new TPragmaStmt(vendor);
324                break;
325
326            case sstSqliteAttach:
327                ret = new TAttachStmt(vendor);
328                break;
329
330            case sstSqliteDetach:
331                ret = new TDetachStmt(vendor);
332                break;
333
334            case sstSqliteCreateVirtualTable:
335                ret = new TSqliteCreateVirtualTableStmt(vendor);
336                break;
337
338            case sstpostgresqlBegin: {
339                // BEGIN inside a CREATE TRIGGER body is not a new statement
340                boolean lcisnewsql = true;
341                if (state != EFindSqlStateType.stnormal) {
342                    if (lccurrentsqlstatement != null) {
343                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger)
344                            lcisnewsql = false;
345                    }
346                }
347                if (lcisnewsql) {
348                    ret = new TUnknownSqlStatement(vendor);
349                    ret.sqlstatementtype = gnewsqlstatementtype;
350                }
351                break;
352            }
353
354            case sstpostgresqlEnd: {
355                // END inside a CREATE TRIGGER body is not a new statement
356                boolean lcisnewsql = true;
357                if (state != EFindSqlStateType.stnormal) {
358                    if (lccurrentsqlstatement != null) {
359                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger)
360                            lcisnewsql = false;
361                    }
362                }
363                if (lcisnewsql) {
364                    ret = new TUnknownSqlStatement(vendor);
365                    ret.sqlstatementtype = gnewsqlstatementtype;
366                }
367                break;
368            }
369
370            case sstpostgresqlExplain:
371                ret = new TExplainPlan(vendor);
372                gnewsqlstatementtype = ret.sqlstatementtype;
373                break;
374
375            default:
376                ret = new TUnknownSqlStatement(vendor);
377                ret.sqlstatementtype = gnewsqlstatementtype;
378                break;
379        }
380
381        return ret;
382    }
383}