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
101        // UPDATE
102        addCmd(TBaseType.rrw_update, ESqlStatementType.sstupdate);
103
104        // VACUUM
105        addCmd(TBaseType.rrw_postgresql_vacuum, ESqlStatementType.sstVacuum);
106
107        // VALUES
108        addCmd(TBaseType.rrw_values, ESqlStatementType.sstValues);
109    }
110
111    @Override
112    public TCustomSqlStatement issql(TSourceToken token, EFindSqlStateType state, TCustomSqlStatement currentStatement) {
113        TCustomSqlStatement ret = null;
114
115        gnewsqlstatementtype = ESqlStatementType.sstinvalid;
116
117        // Skip comments, whitespace, and semicolons
118        if ((token.tokencode == TBaseType.cmtdoublehyphen)
119                || (token.tokencode == TBaseType.cmtslashstar)
120                || (token.tokencode == TBaseType.lexspace)
121                || (token.tokencode == TBaseType.lexnewline)
122                || (token.tokentype == ETokenType.ttsemicolon)) {
123            return null;
124        }
125
126        int lcpos = token.posinlist;
127        TSourceTokenList lcsourcetokenlist = token.container;
128        TCustomSqlStatement lccurrentsqlstatement = currentStatement;
129
130        // Subquery after semicolon or at first line
131        if ((state == EFindSqlStateType.stnormal) && (token.tokentype == ETokenType.ttleftparenthesis)) {
132            int k = lcsourcetokenlist.solidtokenafterpos(lcpos, TBaseType.rrw_select, 1, "(");
133            if (k > 0) {
134                ret = new TSelectSqlStatement(vendor);
135            }
136            return ret;
137        }
138
139        // CTE detection
140        if ((state == EFindSqlStateType.stnormal) && (token.tokencode == TBaseType.rrw_with)) {
141            ret = findcte(token);
142            if (ret != null) return ret;
143        }
144
145        gnewsqlstatementtype = getStatementTypeForToken(token);
146
147        TSourceToken lcprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcpos);
148
149        switch (gnewsqlstatementtype) {
150            case sstinvalid: {
151                ret = null;
152                break;
153            }
154
155            case sstselect: {
156                boolean lcisnewsql = true;
157
158                if (state != EFindSqlStateType.stnormal) {
159                    if (lccurrentsqlstatement != null) {
160                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger)
161                            lcisnewsql = false;
162                    }
163                    if (lcisnewsql) {
164                        if (lcprevsolidtoken != null) {
165                            if (lcprevsolidtoken.tokentype == ETokenType.ttleftparenthesis)
166                                lcisnewsql = false;
167                            else if (lcprevsolidtoken.tokencode == TBaseType.rrw_union)
168                                lcisnewsql = false;
169                            else if (lcprevsolidtoken.tokencode == TBaseType.rrw_intersect)
170                                lcisnewsql = false;
171                            else if (lcprevsolidtoken.tokencode == TBaseType.rrw_except)
172                                lcisnewsql = false;
173                            else if (lcprevsolidtoken.tokencode == TBaseType.rrw_as) {
174                                if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetable)
175                                    lcisnewsql = false;
176                                if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreateview)
177                                    lcisnewsql = false;
178                            }
179
180                            if (lcisnewsql && (lcprevsolidtoken.tokencode == TBaseType.rrw_all)) {
181                                TSourceToken lcpprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcprevsolidtoken.posinlist);
182                                if (lcpprevsolidtoken != null) {
183                                    if (lcpprevsolidtoken.tokencode == TBaseType.rrw_union)
184                                        lcisnewsql = false;
185                                }
186                            }
187                        }
188
189                        if (lccurrentsqlstatement != null) {
190                            if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstinsert)
191                                lcisnewsql = false;
192                        }
193                    }
194                }
195
196                if (lcisnewsql)
197                    ret = new TSelectSqlStatement(vendor);
198
199                break;
200            }
201
202            case sstinsert: {
203                boolean lcisnewsql = true;
204                if (state != EFindSqlStateType.stnormal) {
205                    if (lccurrentsqlstatement != null) {
206                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger)
207                            lcisnewsql = false;
208                    }
209                }
210
211                if (lcisnewsql)
212                    ret = new TInsertSqlStatement(vendor);
213
214                break;
215            }
216
217            case sstupdate: {
218                boolean lcisnewsql = true;
219                if (state != EFindSqlStateType.stnormal) {
220                    if (lccurrentsqlstatement != null) {
221                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger)
222                            lcisnewsql = false;
223                    }
224                    if (lcisnewsql) {
225                        lcprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcpos);
226                        if (lcprevsolidtoken != null) {
227                            if (lcprevsolidtoken.tokencode == TBaseType.rrw_on)
228                                lcisnewsql = false;
229                            else if (lcprevsolidtoken.tokencode == TBaseType.rrw_for)
230                                lcisnewsql = false;
231                        }
232
233                        TSourceToken lcnextsolidtoken = lcsourcetokenlist.nextsolidtoken(lcpos, 1, false);
234                        if (lcnextsolidtoken != null) {
235                            if (lcnextsolidtoken.tokentype == ETokenType.ttleftparenthesis) {
236                                int k = lcsourcetokenlist.solidtokenafterpos(lcnextsolidtoken.posinlist, TBaseType.rrw_select, 1, "(");
237                                if (k == 0) lcisnewsql = false;
238                            }
239                        }
240                    }
241                }
242
243                if (lcisnewsql) {
244                    ret = new TUpdateSqlStatement(vendor);
245                    ret.dummytag = 1;
246                }
247                break;
248            }
249
250            case sstdelete: {
251                boolean lcisnewsql = true;
252
253                if (state != EFindSqlStateType.stnormal) {
254                    if (lccurrentsqlstatement != null) {
255                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger)
256                            lcisnewsql = false;
257                    }
258                    if (lcisnewsql) {
259                        lcprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcpos);
260                        if (lcprevsolidtoken != null) {
261                            if (lcprevsolidtoken.tokencode == TBaseType.rrw_on)
262                                lcisnewsql = false;
263                        }
264                    }
265                }
266
267                if (lcisnewsql)
268                    ret = new TDeleteSqlStatement(vendor);
269
270                break;
271            }
272
273            case sstcreatetable:
274                ret = new TCreateTableSqlStatement(vendor);
275                break;
276
277            case sstaltertable:
278                ret = new TAlterTableStatement(vendor);
279                break;
280
281            case sstpostgresqlCreateIndex:
282                ret = new TCreateIndexSqlStatement(vendor);
283                break;
284
285            case sstpostgresqlCreateView:
286                ret = new TCreateViewSqlStatement(vendor);
287                break;
288
289            case sstcreatetrigger:
290                ret = new TCreateTriggerStmt(vendor);
291                break;
292
293            case sstpostgresqlDropTable:
294                ret = new TDropTableSqlStatement(vendor);
295                break;
296
297            case sstpostgresqlDropView:
298                ret = new TDropViewSqlStatement(vendor);
299                break;
300
301            case sstpostgresqlDropTrigger:
302                ret = new TDropTriggerSqlStatement(vendor);
303                break;
304
305            case sstdropindex:
306                ret = new TDropIndexSqlStatement(vendor);
307                break;
308
309            case sstpostgresqlCommit:
310                ret = new TCommitStmt(vendor);
311                break;
312
313            case sstVacuum:
314                ret = new TVacuumStmt(vendor);
315                break;
316
317            case sstReindex:
318                ret = new TReindexStmt(vendor);
319                break;
320
321            case sstSqlitePragma:
322                ret = new TPragmaStmt(vendor);
323                break;
324
325            case sstSqliteAttach:
326                ret = new TAttachStmt(vendor);
327                break;
328
329            case sstSqliteDetach:
330                ret = new TDetachStmt(vendor);
331                break;
332
333            case sstSqliteCreateVirtualTable:
334                ret = new TSqliteCreateVirtualTableStmt(vendor);
335                break;
336
337            case sstpostgresqlBegin: {
338                // BEGIN inside a CREATE TRIGGER body is not a new statement
339                boolean lcisnewsql = true;
340                if (state != EFindSqlStateType.stnormal) {
341                    if (lccurrentsqlstatement != null) {
342                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger)
343                            lcisnewsql = false;
344                    }
345                }
346                if (lcisnewsql) {
347                    ret = new TUnknownSqlStatement(vendor);
348                    ret.sqlstatementtype = gnewsqlstatementtype;
349                }
350                break;
351            }
352
353            case sstpostgresqlEnd: {
354                // END inside a CREATE TRIGGER body is not a new statement
355                boolean lcisnewsql = true;
356                if (state != EFindSqlStateType.stnormal) {
357                    if (lccurrentsqlstatement != null) {
358                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger)
359                            lcisnewsql = false;
360                    }
361                }
362                if (lcisnewsql) {
363                    ret = new TUnknownSqlStatement(vendor);
364                    ret.sqlstatementtype = gnewsqlstatementtype;
365                }
366                break;
367            }
368
369            case sstpostgresqlExplain:
370                ret = new TExplainPlan(vendor);
371                gnewsqlstatementtype = ret.sqlstatementtype;
372                break;
373
374            default:
375                ret = new TUnknownSqlStatement(vendor);
376                ret.sqlstatementtype = gnewsqlstatementtype;
377                break;
378        }
379
380        return ret;
381    }
382}