001package gudusoft.gsqlparser.sqlcmds;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.stmt.*;
005import gudusoft.gsqlparser.stmt.couchbase.*;
006import gudusoft.gsqlparser.stmt.oracle.*;
007
008/**
009 * Couchbase SQL command resolver.
010 * Contains all Couchbase-specific SQL command recognition logic.
011 *
012 * @since 3.1.0.9
013 */
014public class TSqlCmdsCouchbase extends AbstractSqlCmds {
015
016    // Temporary field for statement type during issql processing
017    private ESqlStatementType gnewsqlstatementtype = ESqlStatementType.sstinvalid;
018
019    public TSqlCmdsCouchbase() {
020        super(EDbVendor.dbvcouchbase);
021    }
022
023    @Override
024    protected String getToken1Str(int token1) {
025        // Handle Couchbase vendor-specific reserved words (token codes > TBaseType.rrw_abort)
026        switch (token1) {
027            case TBaseType.rrw_couchbase_build:
028                return "build";
029            case TBaseType.rrw_couchbase_infer:
030                return "infer";
031            case TBaseType.rrw_couchbase_upsert:
032                return "upsert";
033            default:
034                return null;
035        }
036    }
037
038    @Override
039    protected void initializeCommands() {
040        // Couchbase commands extracted from TSqlCmds.initcouchbasecmds()
041        // Longer patterns BEFORE shorter patterns with same prefix
042
043        // BUILD INDEX
044        addCmd(TBaseType.rrw_couchbase_build, "index", ESqlStatementType.sstBuildIndex);
045
046        // CREATE commands
047        addCmd(TBaseType.rrw_create, "primary", "index", ESqlStatementType.sstcreateindex);
048        addCmd(TBaseType.rrw_create, "index", ESqlStatementType.sstcreateindex);
049
050        // DELETE
051        addCmd(TBaseType.rrw_delete, ESqlStatementType.sstdelete);
052
053        // DROP commands
054        addCmd(TBaseType.rrw_drop, "primary", "index", ESqlStatementType.sstdropindex);
055        addCmd(TBaseType.rrw_drop, "index", ESqlStatementType.sstdropindex);
056
057        // EXECUTE
058        addCmd(TBaseType.rrw_execute, ESqlStatementType.sstExecutePreparedStmt);
059
060        // EXPLAIN
061        addCmd(TBaseType.rrw_explain, ESqlStatementType.sstExplain);
062
063        // INFER
064        addCmd(TBaseType.rrw_couchbase_infer, ESqlStatementType.sstinfer);
065
066        // INSERT
067        addCmd(TBaseType.rrw_insert, ESqlStatementType.sstinsert);
068
069        // MERGE
070        addCmd(TBaseType.rrw_merge, ESqlStatementType.sstmerge);
071
072        // PREPARE
073        addCmd(TBaseType.rrw_prepare, ESqlStatementType.sstprepare);
074
075        // SELECT
076        addCmd(TBaseType.rrw_select, ESqlStatementType.sstselect);
077
078        // UPDATE
079        addCmd(TBaseType.rrw_update, ESqlStatementType.sstupdate);
080
081        // UPSERT
082        addCmd(TBaseType.rrw_couchbase_upsert, ESqlStatementType.sstupsert);
083    }
084
085    @Override
086    public TCustomSqlStatement issql(TSourceToken pcst, EFindSqlStateType pstate, TCustomSqlStatement psqlstatement) {
087        TCustomSqlStatement ret = null;
088
089        gnewsqlstatementtype = ESqlStatementType.sstinvalid;
090
091        // Skip comments, whitespace, and semicolons
092        if ((pcst.tokencode == TBaseType.cmtdoublehyphen)
093                || (pcst.tokencode == TBaseType.cmtslashstar)
094                || (pcst.tokencode == TBaseType.lexspace)
095                || (pcst.tokencode == TBaseType.lexnewline)
096                || (pcst.tokentype == ETokenType.ttsemicolon)) {
097            return null;
098        }
099
100        int lcpos = pcst.posinlist;
101        TSourceTokenList lcsourcetokenlist = pcst.container;
102        TCustomSqlStatement lccurrentsqlstatement = psqlstatement;
103
104        // Subquery after semicolon or at first line
105        if ((pstate == EFindSqlStateType.stnormal) && (pcst.tokentype == ETokenType.ttleftparenthesis)) { // (
106            int k = lcsourcetokenlist.solidtokenafterpos(lcpos, TBaseType.rrw_select, 1, "(");
107            if (k > 0) {
108                ret = new TSelectSqlStatement(vendor);
109            }
110
111            return ret;
112        }
113
114        // CTE - use base class findcte() method
115        if ((pstate == EFindSqlStateType.stnormal) && (pcst.tokencode == TBaseType.rrw_with)) {
116            ret = findcte(pcst);
117            if ((ret != null)) return ret;
118        }
119
120        gnewsqlstatementtype = getStatementTypeForToken(pcst);
121
122        TSourceToken lcprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcpos);
123        switch (gnewsqlstatementtype) {
124            case sstinvalid: {
125                ret = null;
126
127                if (pstate == EFindSqlStateType.stnormal) {
128                    if (pcst.tokencode == TBaseType.label_begin) {
129                        ret = new TCommonBlock(vendor);
130                        gnewsqlstatementtype = ret.sqlstatementtype;
131                    } else if (pcst.tokencode == TBaseType.rrw_declare) {
132                        ret = new TCommonBlock(vendor);
133                        gnewsqlstatementtype = ret.sqlstatementtype;
134                    } else if (pcst.tokencode == TBaseType.rrw_begin) {
135                        ret = new TCommonBlock(vendor);
136                        gnewsqlstatementtype = ret.sqlstatementtype;
137                    } else if (pcst.tokencode == TBaseType.rrw_procedure) {
138                        ret = new TPlsqlCreateProcedure(vendor);
139                        gnewsqlstatementtype = ret.sqlstatementtype;
140                    } else if (pcst.tokencode == TBaseType.rrw_function) {
141                        ret = new TPlsqlCreateFunction(vendor);
142                        gnewsqlstatementtype = ret.sqlstatementtype;
143                    } else if (pcst.tokencode == TBaseType.rrw_package) {
144                        ret = new TPlsqlCreatePackage(vendor);
145                        gnewsqlstatementtype = ret.sqlstatementtype;
146                    }
147                }
148                break;
149            }
150            case sstselect: {
151                boolean lcisnewsql = true;
152
153                if (pstate != EFindSqlStateType.stnormal) {
154                    if ((lcprevsolidtoken != null)) {
155                        if (lcprevsolidtoken.tokentype == ETokenType.ttleftparenthesis)
156                            lcisnewsql = false; // subquery
157                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_union)
158                            lcisnewsql = false;
159                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_intersect)
160                            lcisnewsql = false;
161                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_minus)
162                            lcisnewsql = false;
163                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_except)
164                            lcisnewsql = false;
165                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_return)
166                            lcisnewsql = false;
167                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_as) {
168                            if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetable)
169                                lcisnewsql = false;
170                            if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreateview)
171                                lcisnewsql = false;
172                        }
173
174                        if (lcisnewsql && (lcprevsolidtoken.tokencode == TBaseType.rrw_all)) {
175                            TSourceToken lcpprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcprevsolidtoken.posinlist);
176                            if ((lcpprevsolidtoken != null)) {
177                                if (lcpprevsolidtoken.tokencode == TBaseType.rrw_union)
178                                    lcisnewsql = false;
179                            }
180                        }
181                    }
182
183                    if ((lccurrentsqlstatement != null)) {
184                        if (lccurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstinsert)
185                            lcisnewsql = false;
186                    }
187                }
188
189                if (lcisnewsql)
190                    ret = new TSelectSqlStatement(vendor);
191
192                break;
193            }
194            case sstinsert: {
195                boolean lcisnewsql = true;
196                if (pstate != EFindSqlStateType.stnormal) {
197                    if ((lccurrentsqlstatement != null)) {
198                        // Additional checks could be added here
199                    }
200                }
201
202                if (lcisnewsql)
203                    ret = new TInsertSqlStatement(vendor);
204
205                break;
206            }
207            case sstupdate: {
208                boolean lcisnewsql = true;
209                if (pstate != EFindSqlStateType.stnormal) {
210                    lcprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcpos);
211                    if ((lcprevsolidtoken != null)) {
212                        if (lcprevsolidtoken.tokencode == TBaseType.rrw_on)
213                            lcisnewsql = false;
214                        else if (lcprevsolidtoken.tokencode == TBaseType.rrw_for)
215                            lcisnewsql = false;
216                    }
217
218                    TSourceToken lcnextsolidtoken = lcsourcetokenlist.nextsolidtoken(lcpos, 1, false);
219                    if ((lcnextsolidtoken != null)) {
220                        if (lcnextsolidtoken.tokentype == ETokenType.ttleftparenthesis) {
221                            int k = lcsourcetokenlist.solidtokenafterpos(lcnextsolidtoken.posinlist, TBaseType.rrw_select, 1, "(");
222                            if (k == 0) lcisnewsql = false;
223                        }
224                    }
225
226                    if ((lccurrentsqlstatement != null)) {
227                        // Additional checks could be added here
228                    }
229                }
230
231                if (lcisnewsql) {
232                    ret = new TUpdateSqlStatement(vendor);
233                    ret.dummytag = 1; // means set clause in update is not found yet, used to separate set clause from set statement
234                }
235                break;
236            }
237            case sstdelete: {
238                boolean lcisnewsql = true;
239
240                if (pstate != EFindSqlStateType.stnormal) {
241                    lcprevsolidtoken = lcsourcetokenlist.solidtokenbefore(lcpos);
242                    if ((lcprevsolidtoken != null)) {
243                        if (lcprevsolidtoken.tokencode == TBaseType.rrw_on)
244                            lcisnewsql = false;
245                    }
246
247                    if ((lccurrentsqlstatement != null)) {
248                        // Additional checks could be added here
249                    }
250                }
251
252                if (lcisnewsql)
253                    ret = new TDeleteSqlStatement(vendor);
254
255                break;
256            }
257            case sstmerge: {
258                ret = new TMergeSqlStatement(vendor);
259                ret.sqlstatementtype = gnewsqlstatementtype;
260                break;
261            }
262            case sstcreateindex: {
263                ret = new TCreateIndexSqlStatement(vendor);
264                break;
265            }
266            case sstdropindex: {
267                ret = new TDropIndexSqlStatement(vendor);
268                break;
269            }
270            case sstBuildIndex:
271                ret = new TTBuildIndexesStmt(vendor);
272                break;
273            case sstinfer:
274                ret = new TInferKeyspaceStmt(vendor);
275                break;
276            case sstupsert:
277                ret = new TUpsertStmt(vendor);
278                break;
279            case sstExplain: {
280                ret = new TExplainPlan(vendor);
281                break;
282            }
283            case sstprepare: {
284                ret = new TExplainPlan(vendor);
285                ret.sqlstatementtype = ESqlStatementType.sstprepare;
286                break;
287            }
288            case sstExecutePreparedStmt:
289                ret = new TExecuteSqlStatement(vendor);
290                break;
291            default: {
292                ret = new TUnknownSqlStatement(vendor);
293                ret.sqlstatementtype = gnewsqlstatementtype;
294                break;
295            }
296        }
297
298        return ret;
299    }
300}