001package gudusoft.gsqlparser.sqlcmds;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.stmt.*;
005import gudusoft.gsqlparser.stmt.sparksql.*;
006import gudusoft.gsqlparser.stmt.mysql.TLoadDataStmt;
007import gudusoft.gsqlparser.stmt.mysql.TMySQLBlock;
008
009/**
010 * SparkSQL SQL command resolver.
011 * Extracted from monolithic TSqlCmds to support modular lazy-loading.
012 *
013 * @since 3.1.0.9
014 */
015public class TSqlCmdsSparksql extends AbstractSqlCmds {
016
017    public TSqlCmdsSparksql() {
018        super(EDbVendor.dbvsparksql);
019    }
020
021    @Override
022    protected void initializeCommands() {
023        // Extracted from TSqlCmds.initsparksqlcmds() lines 1530-1597
024        // Commands ordered with longer patterns before shorter ones
025
026        // BEGIN commands
027        addCmd(TBaseType.rrw_begin, ESqlStatementType.sstBegin);
028
029        // ADD commands
030        addCmd(TBaseType.rrw_add, "archive", ESqlStatementType.sstAddJar);
031        addCmd(TBaseType.rrw_add, "archives", ESqlStatementType.sstAddJar);
032        addCmd(TBaseType.rrw_add, "file", ESqlStatementType.sstAddFile);
033        addCmd(TBaseType.rrw_add, "files", ESqlStatementType.sstAddFile);
034        addCmd(TBaseType.rrw_add, "jar", ESqlStatementType.sstAddJar);
035        addCmd(TBaseType.rrw_add, "jars", ESqlStatementType.sstAddJar);
036
037        // ALTER commands
038        addCmd(TBaseType.rrw_alter, "database", ESqlStatementType.sstalterdatabase);
039        addCmd(TBaseType.rrw_alter, "table", ESqlStatementType.sstaltertable);
040        addCmd(TBaseType.rrw_alter, "view", ESqlStatementType.sstalterview);
041
042        // ANALYZE commands
043        addCmd(TBaseType.rrw_analyze, "table", ESqlStatementType.sstanalyzeTable);
044        addCmd(TBaseType.rrw_analyze, "tables", ESqlStatementType.sstanalyzeTable);
045
046        // CACHE commands
047        addCmd(TBaseType.rrw_cache, "lazy", "table", ESqlStatementType.sstCacheTable);
048        addCmd(TBaseType.rrw_cache, "table", ESqlStatementType.sstCacheTable);
049
050        // CLEAR commands
051        addCmd(TBaseType.rrw_clear, "cache", ESqlStatementType.sstClearCache);
052
053        // DECLARE commands
054        addCmd(TBaseType.rrw_declare, ESqlStatementType.sstmysqldeclare);
055
056        // CREATE commands (longer patterns first)
057        addCmd(TBaseType.rrw_create, "or", "replace", "global", "temporary", "view", ESqlStatementType.sstcreateview);
058        addCmd(TBaseType.rrw_create, "or", "replace", "temporary", "function", ESqlStatementType.sstcreatefunction);
059        addCmd(TBaseType.rrw_create, "or", "replace", "temporary", "view", ESqlStatementType.sstcreateview);
060        addCmd(TBaseType.rrw_create, "or", "replace", "function", ESqlStatementType.sstcreatefunction);
061        addCmd(TBaseType.rrw_create, "or", "replace", "view", ESqlStatementType.sstcreateview);
062        addCmd(TBaseType.rrw_create, "global", "temporary", "view", ESqlStatementType.sstcreateview);
063        addCmd(TBaseType.rrw_create, "external", "table", ESqlStatementType.sstcreatetable);
064        addCmd(TBaseType.rrw_create, "temporary", "function", ESqlStatementType.sstcreatefunction);
065        addCmd(TBaseType.rrw_create, "temporary", "view", ESqlStatementType.sstcreateview);
066        addCmd(TBaseType.rrw_create, "database", ESqlStatementType.sstcreatedatabase);
067        addCmd(TBaseType.rrw_create, "schema", ESqlStatementType.sstcreatedatabase);
068        addCmd(TBaseType.rrw_create, "function", ESqlStatementType.sstcreatefunction);
069        addCmd(TBaseType.rrw_create, "table", ESqlStatementType.sstcreatetable);
070        addCmd(TBaseType.rrw_create, "view", ESqlStatementType.sstcreateview);
071
072        // DESCRIBE commands (DESC and DESCRIBE variants)
073        addCmd(TBaseType.rrw_spark_desc, "database", ESqlStatementType.sstdescribeDatabase);
074        addCmd(TBaseType.rrw_spark_desc, "function", ESqlStatementType.sstdescribeFunction);
075        addCmd(TBaseType.rrw_spark_desc, "query", ESqlStatementType.sstdescribeQuery);
076        addCmd(TBaseType.rrw_spark_desc, "table", ESqlStatementType.sstdescribeTable);
077        addCmd(TBaseType.rrw_spark_desc, ESqlStatementType.sstdescribeTable);
078        addCmd(TBaseType.rrw_describe, "database", ESqlStatementType.sstdescribeDatabase);
079        addCmd(TBaseType.rrw_describe, "function", ESqlStatementType.sstdescribeFunction);
080        addCmd(TBaseType.rrw_describe, "query", ESqlStatementType.sstdescribeQuery);
081        addCmd(TBaseType.rrw_describe, "table", ESqlStatementType.sstdescribeTable);
082        addCmd(TBaseType.rrw_describe, ESqlStatementType.sstdescribe);
083
084        // DROP commands
085        addCmd(TBaseType.rrw_drop, "temporary", "function", ESqlStatementType.sstdropfunction);
086        addCmd(TBaseType.rrw_drop, "temporary", "variable", ESqlStatementType.sstdropfunction);
087        addCmd(TBaseType.rrw_drop, "temporary", "var", ESqlStatementType.sstdropfunction);
088        addCmd(TBaseType.rrw_drop, "database", ESqlStatementType.sstdropdatabase);
089        addCmd(TBaseType.rrw_drop, "function", ESqlStatementType.sstdropfunction);
090        addCmd(TBaseType.rrw_drop, "schema", ESqlStatementType.sstdropdatabase);
091        addCmd(TBaseType.rrw_drop, "table", ESqlStatementType.sstdroptable);
092        addCmd(TBaseType.rrw_drop, "view", ESqlStatementType.sstdropview);
093
094        // EXECUTE commands
095        addCmd(TBaseType.rrw_execute, "immediate", ESqlStatementType.sstplsql_execimmestmt);
096        addCmd(TBaseType.rrw_execute, ESqlStatementType.sstexecutestmt);
097
098        // EXPLAIN commands
099        addCmd(TBaseType.rrw_explain, ESqlStatementType.sstExplain);
100
101        // INSERT commands
102        addCmd(TBaseType.rrw_insert, ESqlStatementType.sstinsert);
103
104        // LIST commands
105        addCmd(TBaseType.rrw_spark_list, "archive", ESqlStatementType.sstListJar);
106        addCmd(TBaseType.rrw_spark_list, "archives", ESqlStatementType.sstListJar);
107        addCmd(TBaseType.rrw_spark_list, "file", ESqlStatementType.sstListFile);
108        addCmd(TBaseType.rrw_spark_list, "files", ESqlStatementType.sstListFile);
109        addCmd(TBaseType.rrw_spark_list, "jar", ESqlStatementType.sstListJar);
110        addCmd(TBaseType.rrw_spark_list, "jars", ESqlStatementType.sstListJar);
111
112        // LOAD commands
113        addCmd(TBaseType.rrw_load, "data", ESqlStatementType.sstLoadData);
114
115        // MSCK commands
116        addCmd(TBaseType.rrw_spark_msck, "repair", "table", ESqlStatementType.sstmsck);
117
118        // REFRESH commands
119        addCmd(TBaseType.rrw_refresh, "function", ESqlStatementType.sstRefreshFunction);
120        addCmd(TBaseType.rrw_refresh, "table", ESqlStatementType.sstRefreshTable);
121        addCmd(TBaseType.rrw_refresh, ESqlStatementType.sstRefresh);
122
123        // REPAIR commands
124        addCmd(TBaseType.rrw_repair, "table", ESqlStatementType.sstrepairtable);
125
126        // RESET commands
127        addCmd(TBaseType.rrw_reset, ESqlStatementType.sstReset);
128
129        // SELECT commands
130        addCmd(TBaseType.rrw_select, ESqlStatementType.sstselect);
131
132        // SET commands
133        addCmd(TBaseType.rrw_set, "time", "zone", ESqlStatementType.sstSetTimeZone);
134        addCmd(TBaseType.rrw_set, ESqlStatementType.sstset);
135
136        // SHOW commands
137        addCmd(TBaseType.rrw_show, "create", "table", ESqlStatementType.sstShowCreateTable);
138        addCmd(TBaseType.rrw_show, "table", "extended", ESqlStatementType.sstShowTableExtended);
139        addCmd(TBaseType.rrw_show, "system", "functions", ESqlStatementType.sstShowFunctions);
140        addCmd(TBaseType.rrw_show, "all", "functions", ESqlStatementType.sstShowFunctions);
141        addCmd(TBaseType.rrw_show, "columns", ESqlStatementType.sstShowColumns);
142        addCmd(TBaseType.rrw_show, "databases", ESqlStatementType.sstShowDatabases);
143        addCmd(TBaseType.rrw_show, "schemas", ESqlStatementType.sstShowDatabases);
144        addCmd(TBaseType.rrw_show, "functions", ESqlStatementType.sstShowFunctions);
145        addCmd(TBaseType.rrw_show, "partitions", ESqlStatementType.sstShowPartitions);
146        addCmd(TBaseType.rrw_show, "tables", ESqlStatementType.sstShowTables);
147        addCmd(TBaseType.rrw_show, "tblproperties", ESqlStatementType.sstShowTblProperties);
148        addCmd(TBaseType.rrw_show, "user", ESqlStatementType.sstShowUser);
149        addCmd(TBaseType.rrw_show, "views", ESqlStatementType.sstShowViews);
150
151        // TRUNCATE commands
152        addCmd(TBaseType.rrw_truncate, "table", ESqlStatementType.ssttruncatetable);
153
154        // UNCACHE commands
155        addCmd(TBaseType.rrw_spark_uncache, "table", ESqlStatementType.sstUnCacheTable);
156
157        // USE commands
158        addCmd(TBaseType.rrw_use, ESqlStatementType.sstUse);
159    }
160
161    @Override
162    protected String getToken1Str(int token1) {
163        // SparkSQL vendor-specific tokens
164        switch (token1) {
165            case TBaseType.rrw_spark_uncache:
166                return "uncache";
167            case TBaseType.rrw_spark_desc:
168                return "desc";
169            case TBaseType.rrw_spark_list:
170                return "list";
171            case TBaseType.rrw_spark_msck:
172                return "msck";
173            default:
174                return null;
175        }
176    }
177
178    @Override
179    public TCustomSqlStatement issql(TSourceToken token, EFindSqlStateType state, TCustomSqlStatement currentStatement) {
180        // Extracted from TSqlCmds.issparksql() lines 14877-15214
181
182        TCustomSqlStatement ret = null;
183        int k;
184        boolean lcisnewsql;
185        TSourceToken lcpprevsolidtoken, lcnextsolidtoken;
186
187        gnewsqlstatementtype = ESqlStatementType.sstinvalid;
188
189        if ((token.tokencode == TBaseType.cmtdoublehyphen)
190                || (token.tokencode == TBaseType.cmtslashstar)
191                || (token.tokencode == TBaseType.lexspace)
192                || (token.tokencode == TBaseType.lexnewline)
193                || (token.tokentype == ETokenType.ttsemicolon)) {
194            return ret;
195        }
196
197        int lcpos = token.posinlist;
198        TSourceTokenList lcsourcetokenlist = token.container;
199        TCustomSqlStatement lccurrentsqlstatement = currentStatement;
200
201        // subquery after semicolon || at first line
202        if ((state == EFindSqlStateType.stnormal) && (token.tokentype == ETokenType.ttleftparenthesis)) {
203            k = lcsourcetokenlist.solidtokenafterpos(lcpos, TBaseType.rrw_select, 1, "(");
204            if (k > 0) {
205                ret = new TSelectSqlStatement(this.vendor);
206            }
207            return ret;
208        }
209
210        // cte
211        if ((state == EFindSqlStateType.stnormal) && (token.tokencode == TBaseType.rrw_with)) {
212            ret = findcte(token);
213            if ((ret != null)) return ret;
214        }
215
216        // Pipe syntax: FROM as standalone query start (e.g., FROM t |> SELECT ...)
217        if ((state == EFindSqlStateType.stnormal) && (token.tokencode == TBaseType.rrw_from)) {
218            ret = new TSelectSqlStatement(this.vendor);
219            return ret;
220        }
221
222        // Pipe syntax: VALUES as standalone query start (e.g., VALUES (0),(1) tab(col) |> WHERE ...)
223        if ((state == EFindSqlStateType.stnormal) && (token.tokencode == TBaseType.rrw_values)) {
224            ret = new TSelectSqlStatement(this.vendor);
225            return ret;
226        }
227
228        // Standalone TABLE expression: TABLE name (= SELECT * FROM name)
229        if ((state == EFindSqlStateType.stnormal) && (token.tokencode == TBaseType.rrw_table)) {
230            ret = new TSelectSqlStatement(this.vendor);
231            return ret;
232        }
233
234        gnewsqlstatementtype = getStatementTypeForToken(token);
235
236        TSourceToken lcprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcpos);
237
238        if ((gnewsqlstatementtype == ESqlStatementType.sstinvalid) && (token.tokencode == TBaseType.rrw_create)) {
239            TSourceToken viewToken = token.container.searchToken(TBaseType.rrw_view, "", token, 15);
240            if (viewToken != null) {
241                gnewsqlstatementtype = ESqlStatementType.sstcreateview;
242            }
243        }
244
245        switch (gnewsqlstatementtype) {
246            case sstinvalid: {
247                ret = null;
248
249                // Handle labeled blocks: label: BEGIN...END label
250                if (state == EFindSqlStateType.stnormal) {
251                    if (token.tokencode == TBaseType.ident) {
252                        // label : BEGIN (separate tokens)
253                        TSourceToken nextToken = lcsourcetokenlist.nextsolidtoken(lcpos, 1, false);
254                        if (nextToken != null && nextToken.tokencode == ':') {
255                            TSourceToken afterColon = lcsourcetokenlist.nextsolidtoken(nextToken.posinlist, 1, false);
256                            if (afterColon != null && afterColon.tokencode == TBaseType.rrw_begin) {
257                                ret = new TCommonBlock(this.vendor);
258                                gnewsqlstatementtype = ret.sqlstatementtype;
259                            }
260                        }
261                    } else if (token.tokencode == TBaseType.mysqllabel) {
262                        // label: BEGIN (mysqllabel is a single token like "lbl:")
263                        TSourceToken nextToken = lcsourcetokenlist.nextsolidtoken(lcpos, 1, false);
264                        if (nextToken != null && nextToken.tokencode == TBaseType.rrw_begin) {
265                            ret = new TCommonBlock(this.vendor);
266                            gnewsqlstatementtype = ret.sqlstatementtype;
267                        }
268                    }
269                }
270
271                break;
272            }
273            case sstselect: {
274                lcisnewsql = true;
275
276                // Pipe syntax: |> SELECT, |> FROM, |> VALUES should NOT start a new statement
277                if (TBaseType.assigned(lcprevsolidtoken)) {
278                    if (lcprevsolidtoken.tokencode == TBaseType.sparksql_pipe_arrow)
279                        lcisnewsql = false;
280                }
281
282                if (state != EFindSqlStateType.stnormal) {
283                    if (TBaseType.assigned(lcprevsolidtoken)) {
284                        if (lcprevsolidtoken.tokentype == ETokenType.ttleftparenthesis)
285                            lcisnewsql = false; // subquery
286                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_union)
287                            lcisnewsql = false;
288                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_intersect)
289                            lcisnewsql = false;
290                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_minus)
291                            lcisnewsql = false;
292                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_except)
293                            lcisnewsql = false;
294                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_return)
295                            lcisnewsql = false;
296                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_as) {
297                            if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetable)
298                                lcisnewsql = false;
299                            if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreateview)
300                                lcisnewsql = false;
301                        }
302
303                        if (lcisnewsql && (lcprevsolidtoken.tokencode == TBaseType.rrw_all)) {
304                            lcpprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcprevsolidtoken.posinlist);
305                            if (TBaseType.assigned(lcpprevsolidtoken)) {
306                                if (lcpprevsolidtoken.tokencode == TBaseType.rrw_union)
307                                    lcisnewsql = false;
308                            }
309                        }
310                    }
311
312                    if (TBaseType.assigned(lccurrentsqlstatement)) {
313                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstinsert)
314                            lcisnewsql = false;
315                    }
316                }
317
318                if (lcisnewsql)
319                    ret = new TSelectSqlStatement(this.vendor);
320                break;
321            }
322            case sstinsert: {
323                lcisnewsql = true;
324                if (state != EFindSqlStateType.stnormal) {
325                    if (TBaseType.assigned(lccurrentsqlstatement)) {
326                        // No special handling needed
327                    }
328                }
329
330                if (lcisnewsql)
331                    ret = new TInsertSqlStatement(this.vendor);
332                ret.sqlstatementtype = gnewsqlstatementtype;
333                break;
334            }
335            case sstupdate: {
336                lcisnewsql = true;
337                if (state != EFindSqlStateType.stnormal) {
338                    lcprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcpos);
339                    if (TBaseType.assigned(lcprevsolidtoken)) {
340                        if (lcprevsolidtoken.tokencode == TBaseType.rrw_on)
341                            lcisnewsql = false;
342                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_for)
343                            lcisnewsql = false;
344                    }
345
346                    lcnextsolidtoken = lcsourcetokenlist.nextsolidtoken(lcpos, 1, false);
347                    if (TBaseType.assigned(lcnextsolidtoken)) {
348                        if (lcnextsolidtoken.tokentype == ETokenType.ttleftparenthesis) {
349                            k = lcsourcetokenlist.solidtokenafterpos(lcnextsolidtoken.posinlist, TBaseType.rrw_select, 1, "(");
350                            if (k == 0) lcisnewsql = false;
351                        }
352                    }
353
354                    if (TBaseType.assigned(lccurrentsqlstatement)) {
355                        // No special handling needed
356                    }
357                }
358
359                if (lcisnewsql) {
360                    ret = new TUpdateSqlStatement(this.vendor);
361                    ret.dummytag = 1; // means set clause in update is not found yet, used to separate set clause from set statement
362                }
363                break;
364            }
365            case sstdelete: {
366                lcisnewsql = true;
367
368                if (state != EFindSqlStateType.stnormal) {
369                    lcprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcpos);
370                    if (TBaseType.assigned(lcprevsolidtoken)) {
371                        if (lcprevsolidtoken.tokencode == TBaseType.rrw_on)
372                            lcisnewsql = false;
373                    }
374
375                    if (TBaseType.assigned(lccurrentsqlstatement)) {
376                        // No special handling needed
377                    }
378                }
379
380                if (lcisnewsql)
381                    ret = new TDeleteSqlStatement(this.vendor);
382                break;
383            }
384            case sstcreatetable: {
385                ret = new TCreateTableSqlStatement(this.vendor);
386                break;
387            }
388            case sstcreateview: {
389                ret = new TCreateViewSqlStatement(this.vendor);
390                break;
391            }
392            case sstcreatedatabase: {
393                ret = new TCreateDatabaseSqlStatement(this.vendor);
394                break;
395            }
396            case sstdroptable: {
397                ret = new TDropTableSqlStatement(this.vendor);
398                break;
399            }
400            case sstdropview: {
401                ret = new TDropViewSqlStatement(this.vendor);
402                break;
403            }
404            case sstaltertable: {
405                ret = new TAlterTableStatement(this.vendor);
406                break;
407            }
408            case sstset:
409            case sstReset:
410            case sstSetTimeZone: {
411                lcisnewsql = true;
412                // Pipe syntax: |> SET should NOT start a new statement
413                if (TBaseType.assigned(lcprevsolidtoken)) {
414                    if (lcprevsolidtoken.tokencode == TBaseType.sparksql_pipe_arrow)
415                        lcisnewsql = false;
416                }
417                if (state != EFindSqlStateType.stnormal) {
418                    if (TBaseType.assigned(lccurrentsqlstatement)) {
419                        lcisnewsql = false;
420                    }
421                }
422
423                if (lcisnewsql) {
424                    ret = new TSetStmt(this.vendor);
425                }
426                break;
427            }
428            case sstcreatefunction: {
429                ret = new TCreateFunctionStmt(this.vendor);
430                break;
431            }
432            case sstTruncate: {
433                ret = new TTruncateStatement(this.vendor);
434                break;
435            }
436            case sstdescribe: {
437                ret = new TDescribeStmt(this.vendor);
438                break;
439            }
440            case sstExplain: {
441                ret = new TExplainPlan(this.vendor);
442                break;
443            }
444            case sstUse: {
445                ret = new TUseDatabase(this.vendor);
446                break;
447            }
448            case sstLoadData: {
449                ret = new TLoadDataStmt(this.vendor);
450                break;
451            }
452            case sstShowColumns:
453            case sstShowCreateTable:
454            case sstShowDatabases:
455            case sstShowFunctions:
456            case sstShowPartitions:
457            case sstShowTableExtended:
458            case sstShowTables:
459            case sstShowTblProperties:
460            case sstShowViews:
461            case sstShowUser:
462                ret = new TShowStmt(this.vendor);
463                ret.sqlstatementtype = gnewsqlstatementtype;
464                break;
465            case sstalterdatabase:
466                ret = new TAlterDatabaseStmt(this.vendor);
467                break;
468            case sstdescribeDatabase:
469            case sstdescribeTable:
470            case sstdescribeFunction:
471                ret = new TDescribeStmt(this.vendor);
472                break;
473            case sstalterview:
474                ret = new TAlterViewStatement(this.vendor);
475                break;
476            case sstAddFile:
477            case sstAddJar:
478            case sstListFile:
479            case sstListJar:
480                ret = new TResourceManagement(this.vendor);
481                ret.sqlstatementtype = gnewsqlstatementtype;
482                break;
483            case sstdropdatabase:
484                ret = new TDropDatabaseStmt(this.vendor);
485                break;
486            case sstdropfunction:
487                ret = new TDropFunctionStmt(this.vendor);
488                break;
489            case ssttruncatetable:
490                ret = new TTruncateStatement(this.vendor);
491                break;
492            case sstmsck: {
493                ret = new TMSCKStmt(this.vendor);
494                break;
495            }
496            case sstanalyzeTable: {
497                ret = new TAnalyzeStmt(this.vendor);
498                break;
499            }
500            case sstCacheTable:
501            case sstUnCacheTable:
502            case sstClearCache:
503                ret = new TCacheTable(this.vendor);
504                break;
505            case sstRefreshTable:
506            case sstRefreshFunction:
507            case sstRefresh:
508                ret = new TRefresh(this.vendor);
509                break;
510            case sstBegin: {
511                // BEGIN...END compound block
512                ret = new TCommonBlock(this.vendor);
513                gnewsqlstatementtype = ret.sqlstatementtype;
514                break;
515            }
516            case sstplsql_execimmestmt: {
517                ret = new TExecImmeStmt(this.vendor);
518                break;
519            }
520            case sstexecutestmt: {
521                ret = new TUnknownSqlStatement(this.vendor);
522                ret.sqlstatementtype = gnewsqlstatementtype;
523                break;
524            }
525            default: {
526                ret = new TUnknownSqlStatement(this.vendor);
527                ret.sqlstatementtype = gnewsqlstatementtype;
528                break;
529            }
530        }
531
532        return ret;
533    }
534}