001package gudusoft.gsqlparser.sqlcmds;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.stmt.*;
005
006/**
007 * Apache Doris SQL command resolver.
008 * Handles Doris-specific statement detection and command resolution.
009 *
010 * Doris is MySQL-compatible, so this extends MySQL commands with Doris-specific additions.
011 *
012 * @since 3.2.0.0
013 */
014public class TSqlCmdsDoris extends AbstractSqlCmds {
015
016    public TSqlCmdsDoris() {
017        super(EDbVendor.dbvdoris);
018    }
019
020    @Override
021    protected String getToken1Str(int token1) {
022        switch (token1) {
023            case TBaseType.rrw_doris_export:
024                return "EXPORT";
025            case TBaseType.rrw_doris_switch:
026                return "SWITCH";
027            case TBaseType.rrw_doris_admin:
028                return "ADMIN";
029            case TBaseType.rrw_doris_recover:
030                return "RECOVER";
031            case TBaseType.rrw_doris_cancel:
032                return "CANCEL";
033            case TBaseType.rrw_doris_pause:
034                return "PAUSE";
035            case TBaseType.rrw_doris_resume:
036                return "RESUME";
037            default:
038                return null;
039        }
040    }
041
042    @Override
043    protected void initializeCommands() {
044        // Standard SQL commands (SELECT, INSERT, UPDATE, DELETE)
045        addCmd(TBaseType.rrw_select, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstselect);
046        addCmd(TBaseType.rrw_insert, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstinsert);
047        addCmd(TBaseType.rrw_update, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstupdate);
048        addCmd(TBaseType.rrw_delete, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstdelete);
049
050        // MERGE INTO (Doris supports this)
051        addCmd(TBaseType.rrw_merge, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmerge);
052
053        // CREATE statements
054        addCmd(TBaseType.rrw_create, "database", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlcreatedatabase);
055        addCmd(TBaseType.rrw_create, "schema", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlcreatedatabase);
056        addCmd(TBaseType.rrw_create, "external", "table", " ", " ", " ", " ", ESqlStatementType.sstcreatetable);
057        addCmd(TBaseType.rrw_create, "table", " ", " ", " ", " ", " ", ESqlStatementType.sstcreatetable);
058        addCmd(TBaseType.rrw_create, "temporary", "table", " ", " ", " ", " ", ESqlStatementType.sstcreatetable);
059        addCmd(TBaseType.rrw_create, "view", " ", " ", " ", " ", " ", ESqlStatementType.sstcreateview);
060        addCmd(TBaseType.rrw_create, "or", "replace", "view", " ", " ", " ", ESqlStatementType.sstcreateview);
061        // a materialized view has a grammar of its own that the parser does not have: it stays a typed statement
062        // without an AST, as before (Mantis 4855)
063        addCmd(TBaseType.rrw_create, "materialized", "view", " ", " ", " ", " ", ESqlStatementType.sstcreatematerializedview);
064        addCmd(TBaseType.rrw_create, "index", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlcreateindex);
065        addCmd(TBaseType.rrw_create, "unique", "index", " ", " ", " ", " ", ESqlStatementType.sstmysqlcreateindex);
066        addCmd(TBaseType.rrw_create, "user", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlcreateuser);
067        addCmd(TBaseType.rrw_create, "function", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlcreatefunction);
068        addCmd(TBaseType.rrw_create, "procedure", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlcreateprocedure);
069        addCmd(TBaseType.rrw_create, "routine", "load", " ", " ", " ", " ", ESqlStatementType.sstmysqlloaddatainfile);
070        addCmd(TBaseType.rrw_create, "catalog", " ", " ", " ", " ", " ", ESqlStatementType.sstcreatecatalog);
071        addCmd(TBaseType.rrw_create, "external", "catalog", " ", " ", " ", " ", ESqlStatementType.sstcreatecatalog);
072        addCmd(TBaseType.rrw_create, "resource", " ", " ", " ", " ", " ", ESqlStatementType.sstCreateResourcePool);
073        addCmd(TBaseType.rrw_create, "external", "resource", " ", " ", " ", " ", ESqlStatementType.sstCreateResourcePool);
074        addCmd(TBaseType.rrw_create, "workload", "group", " ", " ", " ", " ", ESqlStatementType.sstCreateResourcePool);
075
076        // BACKUP (Doris specific - BACKUP SNAPSHOT db.snapshot TO repository ON (...) PROPERTIES (...))
077        addCmd(TBaseType.rrw_backup, "snapshot", " ", " ", " ", " ", " ", ESqlStatementType.sstmssqlbackup);
078
079        // RESTORE (Doris specific - RESTORE SNAPSHOT db.snapshot FROM repository ON (...) PROPERTIES (...))
080        addCmd(TBaseType.rrw_restore, "snapshot", " ", " ", " ", " ", " ", ESqlStatementType.sstmssqlrestore);
081
082        // ALTER statements
083        addCmd(TBaseType.rrw_alter, "database", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlalterdatabase);
084        addCmd(TBaseType.rrw_alter, "table", " ", " ", " ", " ", " ", ESqlStatementType.sstaltertable);
085        addCmd(TBaseType.rrw_alter, "view", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlalterview);
086        addCmd(TBaseType.rrw_alter, "user", " ", " ", " ", " ", " ", ESqlStatementType.sstmssqlalteruser);
087
088        // DROP statements
089        addCmd(TBaseType.rrw_drop, "database", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqldropdatabase);
090        addCmd(TBaseType.rrw_drop, "schema", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqldropdatabase);
091        addCmd(TBaseType.rrw_drop, "table", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqldroptable);
092        addCmd(TBaseType.rrw_drop, "tables", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqldroptable);
093        addCmd(TBaseType.rrw_drop, "view", " ", " ", " ", " ", " ", ESqlStatementType.sstdropview);
094        addCmd(TBaseType.rrw_drop, "index", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqldropindex);
095        addCmd(TBaseType.rrw_drop, "user", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqldropuser);
096        addCmd(TBaseType.rrw_drop, "function", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqldropfunction);
097        addCmd(TBaseType.rrw_drop, "procedure", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqldropprocedure);
098
099        // TRUNCATE
100        addCmd(TBaseType.rrw_truncate, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqltruncate);
101        addCmd(TBaseType.rrw_truncate, "table", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqltruncate);
102
103        // Transaction control
104        addCmd(TBaseType.rrw_begin, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlstarttransaction);
105        addCmd(TBaseType.rrw_commit, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlcommit);
106        addCmd(TBaseType.rrw_rollback, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlrollback);
107
108        // SHOW statements (Doris supports many SHOW commands)
109        addCmd(TBaseType.rrw_show, "databases", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowdatabases);
110        addCmd(TBaseType.rrw_show, "tables", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowtables);
111        addCmd(TBaseType.rrw_show, "full", "tables", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowtables);
112        addCmd(TBaseType.rrw_show, "columns", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowcolumns);
113        addCmd(TBaseType.rrw_show, "full", "columns", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowcolumns);
114        addCmd(TBaseType.rrw_show, "create", "database", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowcreatedatabase);
115        addCmd(TBaseType.rrw_show, "create", "table", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowcreatetable);
116        addCmd(TBaseType.rrw_show, "create", "view", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowcreateview);
117        addCmd(TBaseType.rrw_show, "index", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowindex);
118        addCmd(TBaseType.rrw_show, "indexes", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowindex);
119        addCmd(TBaseType.rrw_show, "status", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowstatus);
120        addCmd(TBaseType.rrw_show, "table", "status", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowtablestatus);
121        addCmd(TBaseType.rrw_show, "variables", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowvariables);
122        addCmd(TBaseType.rrw_show, "global", "variables", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowvariables);
123        addCmd(TBaseType.rrw_show, "session", "variables", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowvariables);
124        addCmd(TBaseType.rrw_show, "warnings", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowwarnings);
125        addCmd(TBaseType.rrw_show, "errors", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowerrors);
126        addCmd(TBaseType.rrw_show, "processlist", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowprocesslist);
127        addCmd(TBaseType.rrw_show, "full", "processlist", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowprocesslist);
128        addCmd(TBaseType.rrw_show, "grants", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlshowgrants);
129        addCmd(TBaseType.rrw_show, "partitions", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlshow);
130        addCmd(TBaseType.rrw_show, "data", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlshow);
131
132        // SET statements
133        addCmd(TBaseType.rrw_set, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlset);
134        addCmd(TBaseType.rrw_set, "global", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlset);
135        addCmd(TBaseType.rrw_set, "session", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlset);
136
137        // USE statement
138        addCmd(TBaseType.rrw_use, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqluse);
139
140        // DESCRIBE/DESC
141        addCmd(TBaseType.rrw_describe, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstdescribe);
142
143        // EXPLAIN
144        addCmd(TBaseType.rrw_explain, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstExplain);
145
146        // GRANT/REVOKE
147        addCmd(TBaseType.rrw_grant, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlgrant);
148        addCmd(TBaseType.rrw_revoke, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlrevoke);
149
150        // LOAD DATA (Doris specific)
151        addCmd(TBaseType.rrw_load, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlloaddatainfile);
152        addCmd(TBaseType.rrw_load, "label", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlloaddatainfile);
153
154        // EXPORT (Doris specific)
155        addCmd(TBaseType.rrw_doris_export, "table", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlloaddatainfile);
156
157        // ANALYZE
158        addCmd(TBaseType.rrw_analyze, "table", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlanalyzetable);
159
160        // KILL
161        addCmd(TBaseType.rrw_kill, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlkill);
162
163        // CALL
164        addCmd(TBaseType.rrw_call, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlcall);
165
166        // PREPARE/EXECUTE/DEALLOCATE
167        addCmd(TBaseType.rrw_prepare, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlprepare);
168        addCmd(TBaseType.rrw_execute, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqlexecute);
169        addCmd(TBaseType.rrw_deallocate, "prepare", " ", " ", " ", " ", " ", ESqlStatementType.sstmysqldeallocateprepare);
170
171        // SWITCH (Doris specific - switch catalog)
172        addCmd(TBaseType.rrw_doris_switch, " ", " ", " ", " ", " ", " ", ESqlStatementType.sstUseCatalog);
173
174        // ADMIN commands (Doris specific)
175        // ADMIN SET REPLICA STATUS - Sets replica status for tablet management
176        addCmd(TBaseType.rrw_doris_admin, "set", "replica", "status", " ", " ", " ", ESqlStatementType.sstmysqlset);
177        // ADMIN REPAIR TABLE - Triggers repair of a table
178        addCmd(TBaseType.rrw_doris_admin, "repair", "table", " ", " ", " ", " ", ESqlStatementType.sstmysqlrepairtable);
179        // ADMIN CHECK TABLET - Checks tablet consistency
180        addCmd(TBaseType.rrw_doris_admin, "check", "tablet", " ", " ", " ", " ", ESqlStatementType.sstmysqlchecktable);
181
182        // RECOVER commands (Doris specific)
183        // RECOVER DATABASE - Recovers a dropped database
184        addCmd(TBaseType.rrw_doris_recover, "database", " ", " ", " ", " ", " ", ESqlStatementType.sstrecoverdatabase);
185        // RECOVER TABLE - Recovers a dropped table
186        addCmd(TBaseType.rrw_doris_recover, "table", " ", " ", " ", " ", " ", ESqlStatementType.sstrecoverdata);
187        // RECOVER PARTITION - Recovers a dropped partition
188        addCmd(TBaseType.rrw_doris_recover, "partition", " ", " ", " ", " ", " ", ESqlStatementType.sstrecoverdata);
189
190        // CANCEL commands (Doris specific)
191        // CANCEL LOAD - Cancel a running load job
192        addCmd(TBaseType.rrw_doris_cancel, "load", " ", " ", " ", " ", " ", ESqlStatementType.sstbackupcancel);
193
194        // PAUSE/RESUME commands (Doris specific)
195        // PAUSE ROUTINE LOAD FOR job_name - Pause a running routine load job
196        addCmd(TBaseType.rrw_doris_pause, "routine", "load", "for", " ", " ", " ", ESqlStatementType.sstmysqlloaddatainfile);
197        // RESUME ROUTINE LOAD FOR job_name - Resume a paused routine load job
198        addCmd(TBaseType.rrw_doris_resume, "routine", "load", "for", " ", " ", " ", ESqlStatementType.sstmysqlloaddatainfile);
199
200        // REFRESH commands (Doris specific)
201        // REFRESH CATALOG catalog_name - Refresh external catalog metadata
202        addCmd(TBaseType.rrw_refresh, "catalog", " ", " ", " ", " ", " ", ESqlStatementType.sstRefresh);
203    }
204
205    @Override
206    public TCustomSqlStatement issql(TSourceToken pcst, EFindSqlStateType pstate, TCustomSqlStatement psqlstatement) {
207        TCustomSqlStatement ret = null;
208        int k;
209        boolean lcisnewsql;
210        TSourceToken lcpprevsolidtoken, lcnextsolidtoken;
211
212        gnewsqlstatementtype = ESqlStatementType.sstinvalid;
213
214        if ((pcst.tokencode == TBaseType.cmtdoublehyphen)
215                || (pcst.tokencode == TBaseType.cmtslashstar)
216                || (pcst.tokencode == TBaseType.lexspace)
217                || (pcst.tokencode == TBaseType.lexnewline)
218                || (pcst.tokentype == ETokenType.ttsemicolon)) {
219            return ret;
220        }
221
222        int lcpos = pcst.posinlist;
223        TSourceTokenList lcsourcetokenlist = pcst.container;
224        TCustomSqlStatement lccurrentsqlstatement = psqlstatement;
225
226        // Subquery after semicolon or at first line
227        if ((pstate == EFindSqlStateType.stnormal) && (pcst.tokentype == ETokenType.ttleftparenthesis)) {
228            k = lcsourcetokenlist.solidtokenafterpos(lcpos, TBaseType.rrw_select, 1, "(");
229            if (k > 0) {
230                ret = new TSelectSqlStatement(vendor);
231            }
232            return ret;
233        }
234
235        // CTE
236        if ((pstate == EFindSqlStateType.stnormal) && (pcst.tokencode == TBaseType.rrw_with)) {
237            ret = findcte(pcst);
238            if ((ret != null)) return ret;
239        }
240
241        gnewsqlstatementtype = getStatementTypeForToken(pcst);
242
243        TSourceToken lcprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcpos);
244
245        // Handle CREATE ... VIEW pattern
246        if ((gnewsqlstatementtype == ESqlStatementType.sstinvalid) && (pcst.tokencode == TBaseType.rrw_create)) {
247            TSourceToken viewToken = pcst.container.searchToken(TBaseType.rrw_view, "", pcst, 15);
248            if (viewToken != null) {
249                gnewsqlstatementtype = ESqlStatementType.sstcreateview;
250            }
251        }
252
253        switch (gnewsqlstatementtype) {
254            case sstcreatetable:
255                ret = new TCreateTableSqlStatement(vendor);
256                break;
257
258            // The statements that carry lineage go to their grammar rules (Mantis 4855): as typed unknown
259            // statements they had no AST, so dlineage found nothing in them.
260            case sstinsert:
261                ret = new TInsertSqlStatement(vendor);
262                break;
263            case sstupdate:
264                ret = new TUpdateSqlStatement(vendor);
265                break;
266            case sstdelete:
267                ret = new TDeleteSqlStatement(vendor);
268                break;
269            case sstcreateview:
270                ret = new TCreateViewSqlStatement(vendor);
271                break;
272
273            case sstinvalid: {
274                ret = null;
275                break;
276            }
277            case sstselect: {
278                lcisnewsql = true;
279
280                if (pstate != EFindSqlStateType.stnormal) {
281                    if (TBaseType.assigned(lcprevsolidtoken)) {
282                        if (lcprevsolidtoken.tokentype == ETokenType.ttleftparenthesis)
283                            lcisnewsql = false;
284                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_union)
285                            lcisnewsql = false;
286                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_intersect)
287                            lcisnewsql = false;
288                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_minus)
289                            lcisnewsql = false;
290                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_except)
291                            lcisnewsql = false;
292                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_return)
293                            lcisnewsql = false;
294                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_as) {
295                            if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetable)
296                                lcisnewsql = false;
297                            else if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreateview)
298                                lcisnewsql = false;
299                        }
300                    }
301                }
302                if (lcisnewsql) {
303                    ret = new TSelectSqlStatement(vendor);
304                }
305                break;
306            }
307            default: {
308                ret = new TUnknownSqlStatement(vendor);
309                ret.sqlstatementtype = gnewsqlstatementtype;
310                break;
311            }
312        }
313
314        return ret;
315    }
316}