001package gudusoft.gsqlparser.parser;
002
003import gudusoft.gsqlparser.EDbVendor;
004import gudusoft.gsqlparser.TBaseType;
005import gudusoft.gsqlparser.TGSqlParser;
006import gudusoft.gsqlparser.TCustomLexer;
007import gudusoft.gsqlparser.TCustomParser;
008import gudusoft.gsqlparser.TCustomSqlStatement;
009import gudusoft.gsqlparser.TLexerSoql;
010import gudusoft.gsqlparser.TParserSoql;
011import gudusoft.gsqlparser.TSourceToken;
012import gudusoft.gsqlparser.TSourceTokenList;
013import gudusoft.gsqlparser.TStatementList;
014import gudusoft.gsqlparser.TSyntaxError;
015import gudusoft.gsqlparser.EFindSqlStateType;
016import gudusoft.gsqlparser.ETokenType;
017import gudusoft.gsqlparser.ETokenStatus;
018import gudusoft.gsqlparser.ESqlStatementType;
019import gudusoft.gsqlparser.EErrorType;
020import gudusoft.gsqlparser.stmt.TUnknownSqlStatement;
021import gudusoft.gsqlparser.stmt.mssql.TMssqlBlock;
022import gudusoft.gsqlparser.stmt.mssql.TMssqlExecute;
023import gudusoft.gsqlparser.sqlcmds.ISqlCmds;
024import gudusoft.gsqlparser.sqlcmds.SqlCmdsFactory;
025import gudusoft.gsqlparser.compiler.TContext;
026import gudusoft.gsqlparser.sqlenv.TSQLEnv;
027import gudusoft.gsqlparser.compiler.TGlobalScope;
028import gudusoft.gsqlparser.compiler.TFrame;
029import gudusoft.gsqlparser.resolver.TSQLResolver;
030import gudusoft.gsqlparser.resolver2.TSQLResolver2;
031import gudusoft.gsqlparser.resolver2.TSQLResolverConfig;
032import gudusoft.gsqlparser.TLog;
033import gudusoft.gsqlparser.compiler.TASTEvaluator;
034
035import java.io.BufferedReader;
036import java.util.ArrayList;
037import java.util.List;
038import java.util.Stack;
039
040import static gudusoft.gsqlparser.ESqlStatementType.sstmssqlreturn;
041
042/**
043 * Salesforce SOQL (Salesforce Object Query Language) parser implementation.
044 *
045 * <p>This parser handles SOQL-specific SQL syntax including:
046 * <ul>
047 *   <li>SOQL SELECT statements</li>
048 *   <li>SOQL relationship queries</li>
049 *   <li>SOQL aggregate functions</li>
050 *   <li>Salesforce-specific syntax elements</li>
051 * </ul>
052 *
053 * <p><b>Design Notes:</b>
054 * <ul>
055 *   <li>Extends {@link AbstractSqlParser} using the template method pattern</li>
056 *   <li>Uses {@link TLexerSoql} for tokenization</li>
057 *   <li>Uses {@link TParserSoql} for parsing</li>
058 *   <li>Tokenization follows MSSQL pattern</li>
059 *   <li>Delimiter character: ';' for SOQL statements</li>
060 * </ul>
061 *
062 * @see SqlParser
063 * @see AbstractSqlParser
064 * @see TLexerSoql
065 * @see TParserSoql
066 * @since 3.2.0.0
067 */
068public class SoqlSqlParser extends AbstractSqlParser {
069
070    /**
071     * Construct SOQL parser.
072     * <p>
073     * Configures the parser for Salesforce SOQL with default delimiter (;).
074     */
075    public SoqlSqlParser() {
076        super(EDbVendor.dbvsoql);
077        this.delimiterChar = ';';
078        this.defaultDelimiterStr = ";";
079
080        // Create lexer once - will be reused for all parsing operations
081        this.flexer = new TLexerSoql();
082        this.flexer.delimiterchar = this.delimiterChar;
083        this.flexer.defaultDelimiterStr = this.defaultDelimiterStr;
084
085        // Set parent's lexer reference for shared tokenization logic
086        this.lexer = this.flexer;
087
088        // Create parser once - will be reused for all parsing operations
089        this.fparser = new TParserSoql(null);
090        this.fparser.lexer = this.flexer;
091    }
092
093    // ========== Parser Components ==========
094
095    /** The SOQL lexer used for tokenization */
096    public TLexerSoql flexer;
097
098    /** SOQL parser (for SOQL statements) */
099    private TParserSoql fparser;
100
101    /** Current statement being built during extraction */
102    private TCustomSqlStatement gcurrentsqlstatement;
103
104    // ========== AbstractSqlParser Abstract Methods Implementation ==========
105
106    /**
107     * Return the SOQL lexer instance.
108     */
109    @Override
110    protected TCustomLexer getLexer(ParserContext context) {
111        return this.flexer;
112    }
113
114    /**
115     * Return the SOQL parser instance with updated token list.
116     */
117    @Override
118    protected TCustomParser getParser(ParserContext context, TSourceTokenList tokens) {
119        this.fparser.sourcetokenlist = tokens;
120        return this.fparser;
121    }
122
123    /**
124     * Call SOQL-specific tokenization logic.
125     * <p>
126     * SOQL uses MSSQL-like tokenization.
127     */
128    @Override
129    protected void tokenizeVendorSql() {
130        dosoqlsqltexttotokenlist();
131    }
132
133    /**
134     * Setup SOQL parser for raw statement extraction.
135     */
136    @Override
137    protected void setupVendorParsersForExtraction() {
138        this.fparser.sqlcmds = this.sqlcmds;
139        this.fparser.sourcetokenlist = this.sourcetokenlist;
140    }
141
142    /**
143     * Call SOQL-specific raw statement extraction logic.
144     */
145    @Override
146    protected void extractVendorRawStatements(SqlParseResult.Builder builder) {
147        dosoqlgetrawsqlstatements(builder);
148    }
149
150    /**
151     * Perform full parsing of statements with syntax checking.
152     */
153    @Override
154    protected TStatementList performParsing(ParserContext context,
155                                           TCustomParser parser,
156                                           TCustomParser secondaryParser,
157                                           TSourceTokenList tokens,
158                                           TStatementList rawStatements) {
159        this.fparser = (TParserSoql) parser;
160        this.sourcetokenlist = tokens;
161        this.parserContext = context;
162        this.sqlstatements = rawStatements;
163
164        this.sqlcmds = SqlCmdsFactory.get(vendor);
165        this.fparser.sqlcmds = this.sqlcmds;
166
167        if (context != null && context.getGsqlparser() != null) {
168            TGSqlParser gsqlparser = (TGSqlParser) context.getGsqlparser();
169            this.frameStack = gsqlparser.getFrameStack();
170            this.fparser.getNf().setGsqlParser(gsqlparser);
171            this.globalContext = new TContext();
172            this.sqlEnv = new TSQLEnv(this.vendor) {
173                @Override
174                public void initSQLEnv() {
175                }
176            };
177            this.globalContext.setSqlEnv(this.sqlEnv, this.sqlstatements);
178        } else {
179            initializeGlobalContext();
180        }
181
182        for (int i = 0; i < sqlstatements.size(); i++) {
183            TCustomSqlStatement stmt = sqlstatements.getRawSql(i);
184
185            try {
186                stmt.setFrameStack(frameStack);
187                int parseResult = stmt.parsestatement(null, false, context.isOnlyNeedRawParseTree());
188
189                boolean doRecover = TBaseType.ENABLE_ERROR_RECOVER_IN_CREATE_TABLE;
190                if (doRecover && ((parseResult != 0) || (stmt.getErrorCount() > 0))) {
191                    handleCreateTableErrorRecovery(stmt);
192                }
193
194                if ((parseResult != 0) || (stmt.getErrorCount() > 0)) {
195                    copyErrorsFromStatement(stmt);
196                }
197
198            } catch (Exception ex) {
199                handleStatementParsingException(stmt, i, ex);
200                continue;
201            }
202        }
203
204        if (globalFrame != null) {
205            globalFrame.popMeFromStack(frameStack);
206        }
207
208        return this.sqlstatements;
209    }
210
211    private void handleCreateTableErrorRecovery(TCustomSqlStatement stmt) {
212        if (((stmt.sqlstatementtype == ESqlStatementType.sstcreatetable)
213                || (stmt.sqlstatementtype == ESqlStatementType.sstcreateindex))
214                && (!TBaseType.c_createTableStrictParsing)) {
215
216            int nested = 0;
217            boolean isIgnore = false, isFoundIgnoreToken = false;
218            TSourceToken firstIgnoreToken = null;
219
220            for (int k = 0; k < stmt.sourcetokenlist.size(); k++) {
221                TSourceToken st = stmt.sourcetokenlist.get(k);
222                if (isIgnore) {
223                    if (st.issolidtoken() && (st.tokencode != ';')) {
224                        isFoundIgnoreToken = true;
225                        if (firstIgnoreToken == null) {
226                            firstIgnoreToken = st;
227                        }
228                    }
229                    if (st.tokencode != ';') {
230                        st.tokencode = TBaseType.sqlpluscmd;
231                    }
232                    continue;
233                }
234                if (st.tokencode == (int) ')') {
235                    nested--;
236                    if (nested == 0) {
237                        boolean isSelect = false;
238                        TSourceToken st1 = st.searchToken(TBaseType.rrw_as, 1);
239                        if (st1 != null) {
240                            TSourceToken st2 = st.searchToken((int) '(', 2);
241                            if (st2 != null) {
242                                TSourceToken st3 = st.searchToken(TBaseType.rrw_select, 3);
243                                isSelect = (st3 != null);
244                            }
245                        }
246                        if (!isSelect) isIgnore = true;
247                    }
248                } else if (st.tokencode == (int) '(') {
249                    nested++;
250                }
251            }
252
253            if (isFoundIgnoreToken) {
254                stmt.clearError();
255                stmt.parsestatement(null, false);
256            }
257        }
258    }
259
260    @Override
261    protected void performSemanticAnalysis(ParserContext context, TStatementList statements) {
262        if (context != null && context.getGsqlparser() != null) {
263            return;
264        }
265
266        if (getSyntaxErrors().isEmpty()) {
267            if (TBaseType.isEnableResolver2()) {
268                TSQLResolverConfig config = new TSQLResolverConfig();
269                config.setVendor(vendor);
270                TSQLResolver2 resolver2 = new TSQLResolver2(null, statements, config);
271                if (this.sqlEnv != null) {
272                    resolver2.setSqlEnv(this.sqlEnv);
273                }
274                resolver2.resolve();
275            } else if (TBaseType.isEnableResolver()) {
276                TSQLResolver resolver = new TSQLResolver(globalContext, statements);
277                resolver.resolve();
278            }
279        }
280    }
281
282    @Override
283    protected void performInterpreter(ParserContext context, TStatementList statements) {
284        if (TBaseType.ENABLE_INTERPRETER && getSyntaxErrors().isEmpty()) {
285            TLog.clearLogs();
286            TGlobalScope interpreterScope = new TGlobalScope(sqlEnv);
287            TLog.enableInterpreterLogOnly();
288            TASTEvaluator astEvaluator = new TASTEvaluator(statements, interpreterScope);
289            astEvaluator.eval();
290        }
291    }
292
293    // ========== Helper Methods ==========
294
295    /**
296     * Add token to current statement with proper statement linkage.
297     * This replicates TCustomSqlStatement.addtokentolist() behavior
298     * which sets st.stmt = this before adding.
299     */
300    private void addTokenToStatement(TSourceToken st) {
301        st.stmt = gcurrentsqlstatement;
302        gcurrentsqlstatement.sourcetokenlist.add(st);
303    }
304
305    // ========== SOQL-Specific Tokenization ==========
306
307    /**
308     * SOQL-specific tokenization logic.
309     * <p>
310     * SOQL uses MSSQL-like tokenization.
311     * Migrated from TGSqlParser.dosoqlsqltexttotokenlist()
312     */
313    private void dosoqlsqltexttotokenlist() {
314        // SOQL tokenization follows MSSQL pattern
315        TSourceToken lcprevtoken = null;
316        int lcsteps = 0;
317        TSourceToken asourcetoken, lctoken, lctoken2, lctoken3;
318        int yychar;
319        boolean iskeywordgo;
320
321        asourcetoken = getanewsourcetoken();
322
323        if (asourcetoken == null) return;
324
325        yychar = asourcetoken.tokencode;
326
327        boolean lcinopenrowset = false;
328        int lcnested = 0;
329
330        while (yychar > 0) {
331
332            if (asourcetoken.tokencode == TBaseType.rrw_openrowset) {
333                lcinopenrowset = true;
334                lcnested = 0;
335            } else if (asourcetoken.tokentype == ETokenType.ttleftparenthesis) {
336                if ((lcsteps > 0) && TBaseType.assigned(lcprevtoken)) {
337                    if (lcprevtoken.tokencode == TBaseType.rrw_primary) {
338                        lcprevtoken.tokencode = TBaseType.rrw_select - 2;
339                        checkconstarinttoken(lcprevtoken);
340                    } else if (lcprevtoken.tokencode == TBaseType.rrw_foreign) {
341                        lcprevtoken.tokencode = TBaseType.rrw_select - 4;
342                        checkconstarinttoken(lcprevtoken);
343                    } else if (lcprevtoken.tokencode == TBaseType.rrw_unique) {
344                        lcprevtoken.tokencode = TBaseType.rrw_select - 1;
345                        checkconstarinttoken(lcprevtoken);
346                    }
347                    lcprevtoken = null;
348                    lcsteps = 0;
349                }
350
351                if (lcinopenrowset)
352                    lcnested++;
353            } else if (asourcetoken.tokentype == ETokenType.ttrightparenthesis) {
354                if (lcinopenrowset) {
355                    if ((lcnested > 0))
356                        lcnested--;
357                    if (lcnested == 0)
358                        lcinopenrowset = false;
359                }
360            } else if (asourcetoken.tokentype == ETokenType.ttsemicolon) {
361                if (lcinopenrowset) {
362                    asourcetoken.tokentype = ETokenType.ttsemicolon2;
363                } else {
364                    lctoken2 = asourcetoken.searchToken(TBaseType.rrw_begin, -1);
365                    if (lctoken2 != null) {
366                        asourcetoken.tokencode = TBaseType.SEMI_COLON_AFTER_BEGIN;
367                        asourcetoken.tokentype = ETokenType.ttsemicolon3;
368                    } else {
369                        lctoken2 = asourcetoken.searchToken(TBaseType.rrw_try, -1);
370                        if (lctoken2 == null) {
371                            lctoken2 = asourcetoken.searchToken(TBaseType.rrw_catch, -1);
372                        }
373                        if (lctoken2 != null) {
374                            lctoken3 = asourcetoken.searchToken(TBaseType.rrw_begin, -2);
375                            if (lctoken3 != null) {
376                                asourcetoken.tokencode = TBaseType.SEMI_COLON_AFTER_BEGIN;
377                                asourcetoken.tokentype = ETokenType.ttsemicolon3;
378                            }
379                        }
380                    }
381                }
382
383                lctoken = getprevtoken(asourcetoken);
384                if ((lctoken != null)) {
385                    if (lctoken.tokentype == ETokenType.ttsemicolon) {
386                        asourcetoken.tokencode = TBaseType.lexspace;
387                    }
388                }
389            } else if (asourcetoken.tokentype == ETokenType.ttperiod) {
390                lctoken = getprevtoken(asourcetoken);
391                if (TBaseType.assigned(lctoken)) {
392                    if (lctoken.tokencode == TBaseType.rrw_go) {
393                        lctoken.tokencode = TBaseType.ident;
394                        lctoken.tokentype = ETokenType.ttidentifier;
395                    }
396                }
397            } else if (asourcetoken.tokencode == TBaseType.rrw_table) {
398                lctoken = getprevtoken(asourcetoken);
399                if (TBaseType.assigned(lctoken)) {
400                    if (lctoken.tokencode == TBaseType.rrw_lock) {
401                        lctoken.tokencode = TBaseType.rw_locktable;
402                    }
403                }
404            } else if (asourcetoken.tokencode == TBaseType.rrw_into) {
405                lctoken = getprevtoken(asourcetoken);
406                if (TBaseType.assigned(lctoken)) {
407                    if (lctoken.tokencode == TBaseType.rrw_sqlserver_copy) {
408                        lctoken.tokencode = TBaseType.rrw_sqlserver_copyinto;
409                    }
410                }
411            } else if (asourcetoken.tokencode == TBaseType.rrw_sqlserver_column) {
412                lctoken = getprevtoken(asourcetoken);
413                if (TBaseType.assigned(lctoken)) {
414                    if (lctoken.tokencode == TBaseType.rrw_drop) {
415                        asourcetoken.tokencode = TBaseType.rrw_sqlserver_drop_column;
416                    }
417                }
418            } else if (asourcetoken.tokencode == TBaseType.rrw_go) {
419                iskeywordgo = true;
420                lctoken = getprevtoken(asourcetoken);
421                if (TBaseType.assigned(lctoken)) {
422                    if ((lctoken.lineNo == asourcetoken.lineNo) && (lctoken.tokencode != ';')) {
423                        iskeywordgo = false;
424                    }
425                }
426
427                if (iskeywordgo) {
428                    lcinopenrowset = false;
429                    lcnested = 0;
430                    lcprevtoken = asourcetoken;
431                } else {
432                    asourcetoken.tokencode = TBaseType.ident;
433                    asourcetoken.tokentype = ETokenType.ttidentifier;
434                }
435            } else if (asourcetoken.tokencode == TBaseType.rrw_primary) {
436                lcsteps = 2;
437                lcprevtoken = asourcetoken;
438            } else if (asourcetoken.tokencode == TBaseType.rrw_foreign) {
439                lcsteps = 2;
440                lcprevtoken = asourcetoken;
441            } else if (asourcetoken.tokencode == TBaseType.rrw_unique) {
442                lcsteps = 1;
443                lcprevtoken = asourcetoken;
444            } else if (asourcetoken.issolidtoken()) {
445                if (lcsteps > 0) {
446                    if (!(TBaseType.mysametext("clustered", asourcetoken.toString())
447                            || TBaseType.mysametext("nonclustered", asourcetoken.toString())
448                            || TBaseType.mysametext("hash", asourcetoken.toString())
449                    ))
450                        lcsteps--;
451                }
452            }
453
454            sourcetokenlist.add(asourcetoken);
455
456            asourcetoken = getanewsourcetoken();
457            if (asourcetoken == null) break;
458            yychar = asourcetoken.tokencode;
459        }
460    }
461
462    private TSourceToken getprevtoken(TSourceToken ptoken) {
463        TSourceTokenList lcstlist = ptoken.container;
464        if (TBaseType.assigned(lcstlist)) {
465            if ((ptoken.posinlist > 0) && (lcstlist.size() > ptoken.posinlist - 1)) {
466                if (!((lcstlist.get(ptoken.posinlist - 1).tokentype == ETokenType.ttwhitespace)
467                        || (lcstlist.get(ptoken.posinlist - 1).tokentype == ETokenType.ttreturn)
468                        || (lcstlist.get(ptoken.posinlist - 1).tokentype == ETokenType.ttsimplecomment)
469                        || (lcstlist.get(ptoken.posinlist - 1).tokentype == ETokenType.ttbracketedcomment)
470                )) {
471                    return lcstlist.get(ptoken.posinlist - 1);
472                } else {
473                    return lcstlist.nextsolidtoken(ptoken.posinlist - 1, -1, false);
474                }
475            }
476        }
477        return null;
478    }
479
480    private void checkconstarinttoken(TSourceToken token) {
481        TSourceTokenList lcStList = token.container;
482        if (TBaseType.assigned(lcStList)) {
483            TSourceToken lcPPToken = lcStList.nextsolidtoken(token.posinlist, -2, false);
484            if (TBaseType.assigned(lcPPToken)) {
485                if (lcPPToken.tokencode == flexer.getkeywordvalue("constraint")) {
486                    lcPPToken.tokencode = TBaseType.rw_constraint2;
487                }
488            }
489        }
490    }
491
492    // ========== SOQL-Specific Raw Statement Extraction ==========
493
494    /**
495     * SOQL-specific raw statement extraction logic.
496     * <p>
497     * Migrated from TGSqlParser.dosoqlgetrawsqlstatements()
498     */
499    private void dosoqlgetrawsqlstatements(SqlParseResult.Builder builder) {
500        int errorcount = 0;
501        int case_end_nest = 0;
502
503        if (TBaseType.assigned(sqlstatements)) sqlstatements.clear();
504        if (!TBaseType.assigned(sourcetokenlist)) {
505            builder.errorCode(-1);
506            builder.errorMessage("Source token list is null");
507            return;
508        }
509
510        gcurrentsqlstatement = null;
511        EFindSqlStateType gst = EFindSqlStateType.stnormal;
512        int lcblocklevel = 0;
513        int lctrycatchlevel = 0;
514        TSourceToken lcprevsolidtoken = null, lcnextsolidtoken, lcnnextsolidtoken;
515        TSourceToken ast = null;
516        int i, lcMergeInSelectNested = 0;
517        boolean lcisendconversation, lcstillinsql, lcMergeInSelect = false;
518
519        for (i = 0; i < sourcetokenlist.size(); i++) {
520
521            if ((ast != null) && (ast.issolidtoken()))
522                lcprevsolidtoken = ast;
523
524            ast = sourcetokenlist.get(i);
525            sourcetokenlist.curpos = i;
526
527            if (lcMergeInSelect) {
528                if (ast.tokencode == '(') lcMergeInSelectNested++;
529                if (ast.tokencode == ')') {
530                    lcMergeInSelectNested--;
531                    if (lcMergeInSelectNested == 0) {
532                        lcMergeInSelect = false;
533                    }
534                }
535                addTokenToStatement(ast);
536                continue;
537            }
538
539            if (ast.tokenstatus == ETokenStatus.tsignoredbygetrawstatement) {
540                addTokenToStatement(ast);
541                continue;
542            }
543
544            // SOQL-specific: Handle UPDATE TRACKING/VIEWSTAT clauses
545            // These are SOQL clauses for Knowledge articles, not UPDATE statements
546            if (ast.tokencode == TBaseType.rrw_update) {
547                TSourceToken st1 = ast.nextSolidToken();
548                if (st1 != null) {
549                    if (st1.toString().equalsIgnoreCase("tracking")
550                            || st1.toString().equalsIgnoreCase("viewstat")) {
551                        // UPDATE TRACKING | UPDATE VIEWSTAT
552                        ast.tokencode = TBaseType.rrw_soql_update_tracking;
553                    }
554                }
555            }
556
557            if (ast.tokencode == TBaseType.rrw_minus) {
558                TSourceToken st1 = ast.searchToken('(', 1);
559                if (st1 == null) {
560                    st1 = ast.searchToken(TBaseType.rrw_select, 1);
561                    if (st1 == null) {
562                        ast.tokencode = TBaseType.ident;
563                    }
564                }
565            } else if (ast.tokencode == TBaseType.rrw_merge) {
566                TSourceToken st1 = ast.nextSolidToken();
567                if (st1 != null && st1.tokencode == TBaseType.rrw_join) {
568                    ast.tokencode = TBaseType.rrw_merge2_sqlserver;
569                }
570                if ((lcprevsolidtoken != null) && (lcprevsolidtoken.tokencode == '(')) {
571                    lcMergeInSelect = true;
572                    lcMergeInSelectNested++;
573                    addTokenToStatement(ast);
574                    continue;
575                }
576            } else if (ast.tokencode == TBaseType.rrw_sqlserver_value) {
577                if ((lcprevsolidtoken != null) && (lcprevsolidtoken.tokencode == '.')) {
578                    TSourceToken st1 = ast.searchToken('(', 1);
579                    if (st1 != null) {
580                        ast.tokencode = TBaseType.rrw_xml_value;
581                    }
582                }
583            } else if (ast.tokencode == TBaseType.rrw_sqlserver_modify) {
584                if ((lcprevsolidtoken != null) && (lcprevsolidtoken.tokencode == '.')) {
585                    TSourceToken st1 = ast.searchToken('(', 1);
586                    if (st1 != null) {
587                        ast.tokencode = TBaseType.rrw_xml_modify;
588                    }
589                }
590            } else if (ast.tokencode == TBaseType.rrw_sqlserver_query) {
591                if ((lcprevsolidtoken != null) && (lcprevsolidtoken.tokencode == '.')) {
592                    TSourceToken st1 = ast.searchToken('(', 1);
593                    if (st1 != null) {
594                        ast.tokencode = TBaseType.rrw_xml_query;
595                    }
596                }
597            } else if (ast.tokencode == TBaseType.rrw_sqlserver_exist) {
598                if ((lcprevsolidtoken != null) && (lcprevsolidtoken.tokencode == '.')) {
599                    TSourceToken st1 = ast.searchToken('(', 1);
600                    if (st1 != null) {
601                        ast.tokencode = TBaseType.rrw_xml_exist;
602                    }
603                }
604            } else if (ast.tokencode == TBaseType.rrw_sqlserver_nodes) {
605                if ((lcprevsolidtoken != null) && (lcprevsolidtoken.tokencode == '.')) {
606                    TSourceToken st1 = ast.searchToken('(', 1);
607                    if (st1 != null) {
608                        ast.tokencode = TBaseType.rrw_xml_nodes;
609                    }
610                }
611            } else if (ast.tokencode == TBaseType.rrw_check) {
612                if ((lcprevsolidtoken != null) && (lcprevsolidtoken.tokencode == TBaseType.rrw_with)) {
613                    lcprevsolidtoken.tokencode = TBaseType.rrw_sqlserver_check_with;
614                }
615            } else if (ast.tokencode == TBaseType.rrw_sqlserver_next) {
616                TSourceToken st1 = ast.nextSolidToken();
617                if ((st1 != null) && (st1.tokencode == '.')) {
618                    ast.tokencode = TBaseType.ident;
619                }
620            } else if (ast.tokencode == TBaseType.rrw_fetch) {
621                if ((lcprevsolidtoken != null) && ((lcprevsolidtoken.tokencode == TBaseType.rrw_sqlserver_row) || (lcprevsolidtoken.tokencode == TBaseType.rrw_sqlserver_rows))) {
622                    TSourceToken prev2 = lcprevsolidtoken.searchToken(TBaseType.rrw_open, -1);
623                    if (prev2 == null) {
624                        ast.tokencode = TBaseType.rrw_sqlserver_offset_fetch;
625                    }
626                }
627            } else if ((ast.tokencode == TBaseType.rrw_exec) || (ast.tokencode == TBaseType.rrw_execute)) {
628                int searchRange = 4;
629                TSourceToken endTokenInSameLine = ast.searchTokenAtTheEndOfSameLine();
630                if (endTokenInSameLine != null) {
631                    searchRange = endTokenInSameLine.posinlist - ast.posinlist;
632                }
633                TSourceToken st1 = ast.searchToken(';', searchRange);
634                if (st1 != null) {
635                    TSourceToken numSt = st1.nextSolidToken();
636                    if ((numSt != null) && (numSt.tokentype == ETokenType.ttnumber)) {
637                        st1.tokencode = TBaseType.rrw_sqlserver_semicolon_module_number;
638                        st1.tokentype = ETokenType.ttidentifier;
639                    }
640                }
641            } else if (ast.tokencode == TBaseType.rrw_sqlserver_trim) {
642                TSourceToken st1 = ast.nextSolidToken();
643                if (st1 != null) {
644                    if (st1.tokencode == '(') {
645                        // keep as trim keyword
646                    } else {
647                        ast.tokencode = TBaseType.ident;
648                    }
649                }
650            }
651
652            if (gst == EFindSqlStateType.ststoredprocedurebody) {
653                if (!((ast.tokencode == TBaseType.rrw_go)
654                        || (ast.tokencode == TBaseType.rrw_create)
655                        || (ast.tokencode == TBaseType.rrw_alter))) {
656                    addTokenToStatement(ast);
657                    continue;
658                }
659            }
660
661            TCustomSqlStatement lcnextsqlstatement = sqlcmds.issql(ast, gst, gcurrentsqlstatement);
662
663            switch (gst) {
664                case sterror: {
665                    if (TBaseType.assigned(lcnextsqlstatement)) {
666                        onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
667                        gcurrentsqlstatement = lcnextsqlstatement;
668                        addTokenToStatement(ast);
669                        gst = EFindSqlStateType.stsql;
670                    } else if ((ast.tokentype == ETokenType.ttsemicolon)) {
671                        addTokenToStatement(ast);
672                        onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
673                        gst = EFindSqlStateType.stnormal;
674                    } else {
675                        addTokenToStatement(ast);
676                    }
677                    break;
678                }
679                case stnormal: {
680                    if ((ast.tokencode == TBaseType.cmtdoublehyphen)
681                            || (ast.tokencode == TBaseType.cmtslashstar)
682                            || (ast.tokencode == TBaseType.lexspace)
683                            || (ast.tokencode == TBaseType.lexnewline)
684                            || (ast.tokentype == ETokenType.ttsemicolon)) {
685                        if (TBaseType.assigned(gcurrentsqlstatement)) {
686                            addTokenToStatement(ast);
687                        }
688
689                        if (TBaseType.assigned(lcprevsolidtoken) && (ast.tokentype == ETokenType.ttsemicolon)) {
690                            if (lcprevsolidtoken.tokentype == ETokenType.ttsemicolon) {
691                                ast.tokentype = ETokenType.ttsimplecomment;
692                                ast.tokencode = TBaseType.cmtdoublehyphen;
693                            }
694                        }
695
696                        continue;
697                    }
698
699                    gcurrentsqlstatement = lcnextsqlstatement;
700
701                    if (TBaseType.assigned(gcurrentsqlstatement)) {
702                        switch (gcurrentsqlstatement.sqlstatementtype) {
703                            case sstmssqlcreateprocedure:
704                            case sstmssqlcreatefunction:
705                            case sstcreatetrigger:
706                            case sstmssqlalterprocedure:
707                            case sstmssqlalterfunction:
708                            case sstmssqlaltertrigger: {
709                                addTokenToStatement(ast);
710                                gst = EFindSqlStateType.ststoredprocedure;
711                                break;
712                            }
713                            case sstmssqlbegintry:
714                            case sstmssqlbegincatch: {
715                                addTokenToStatement(ast);
716                                gst = EFindSqlStateType.sttrycatch;
717                                lctrycatchlevel = 0;
718                                break;
719                            }
720                            case sstmssqlgo: {
721                                addTokenToStatement(ast);
722                                onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
723                                gst = EFindSqlStateType.stnormal;
724                                break;
725                            }
726                            default: {
727                                addTokenToStatement(ast);
728                                gst = EFindSqlStateType.stsql;
729                                break;
730                            }
731                        }
732                    } else {
733                        if (ast.tokencode == TBaseType.rrw_begin) {
734                            gcurrentsqlstatement = new TMssqlBlock(vendor);
735                            gcurrentsqlstatement.sqlstatementtype = ESqlStatementType.sstmssqlblock;
736                            addTokenToStatement(ast);
737                            gst = EFindSqlStateType.stblock;
738                        } else {
739                            if (sqlstatements.size() == 0) {
740                                gst = EFindSqlStateType.stsql;
741                                gcurrentsqlstatement = new TMssqlExecute(vendor);
742                                addTokenToStatement(ast);
743                            } else if (sqlstatements.get(sqlstatements.size() - 1).sqlstatementtype == ESqlStatementType.sstmssqlgo) {
744                                gst = EFindSqlStateType.stsql;
745                                gcurrentsqlstatement = new TMssqlExecute(vendor);
746                                addTokenToStatement(ast);
747                            }
748                        }
749                    }
750
751                    if (!TBaseType.assigned(gcurrentsqlstatement)) {
752                        this.syntaxErrors.add(new TSyntaxError(ast.getAstext(), ast.lineNo, (ast.columnNo < 0 ? 0 : ast.columnNo)
753                                , "Error when tokenlize", EErrorType.spwarning, TBaseType.MSG_WARNING_ERROR_WHEN_TOKENIZE, null, ast.posinlist));
754
755                        ast.tokentype = ETokenType.tttokenlizererrortoken;
756                        gst = EFindSqlStateType.sterror;
757
758                        gcurrentsqlstatement = new TUnknownSqlStatement(vendor);
759                        gcurrentsqlstatement.sqlstatementtype = ESqlStatementType.sstinvalid;
760                        addTokenToStatement(ast);
761                    }
762                    break;
763                }
764                case stblock: {
765                    if (TBaseType.assigned(lcnextsqlstatement)) {
766                        if (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlgo) {
767                            onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
768                            gcurrentsqlstatement = lcnextsqlstatement;
769                            addTokenToStatement(ast);
770                            onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
771                            gst = EFindSqlStateType.stnormal;
772                        } else {
773                            lcnextsqlstatement = null;
774                        }
775                    }
776
777                    if (gst == EFindSqlStateType.stblock) {
778                        addTokenToStatement(ast);
779                        if (ast.tokencode == TBaseType.rrw_begin) {
780                            lcnextsolidtoken = sourcetokenlist.nextsolidtoken(i, 1, false);
781                            if (TBaseType.assigned(lcnextsolidtoken)) {
782                                if (!((lcnextsolidtoken.tokencode == TBaseType.rrw_sqlserver_tran)
783                                        || (lcnextsolidtoken.tokencode == TBaseType.rrw_sqlserver_transaction)
784                                        || (lcnextsolidtoken.tokencode == TBaseType.rrw_sqlserver_distributed)
785                                        || (lcnextsolidtoken.tokencode == TBaseType.rrw_sqlserver_dialog)
786                                        || (lcnextsolidtoken.tokencode == TBaseType.rrw_sqlserver_conversation)
787                                ))
788                                    lcblocklevel++;
789                            } else
790                                lcblocklevel++;
791
792                        } else if (ast.tokencode == TBaseType.rrw_case)
793                            lcblocklevel++;
794                        else if (ast.tokencode == TBaseType.rrw_end) {
795
796                            lcisendconversation = false;
797
798                            lcnextsolidtoken = sourcetokenlist.nextsolidtoken(i, 1, false);
799                            if (TBaseType.assigned(lcnextsolidtoken)) {
800                                if (lcnextsolidtoken.tokencode == TBaseType.rrw_sqlserver_conversation)
801                                    lcisendconversation = true;
802                            }
803
804                            if (!lcisendconversation) {
805
806                                if (lcblocklevel == 0) {
807                                    if (gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlif) {
808                                        if (TBaseType.assigned(lcnextsolidtoken)) {
809                                            if (lcnextsolidtoken.tokencode == TBaseType.rrw_else) {
810                                                gst = EFindSqlStateType.stsql;
811                                            } else if (lcnextsolidtoken.tokentype == ETokenType.ttsemicolon) {
812                                                lcnnextsolidtoken = sourcetokenlist.nextsolidtoken(lcnextsolidtoken.posinlist, 1, false);
813                                                if (TBaseType.assigned(lcnnextsolidtoken)) {
814                                                    if (lcnnextsolidtoken.tokencode == TBaseType.rrw_else) {
815                                                        gst = EFindSqlStateType.stsql;
816                                                    }
817                                                }
818                                            }
819                                        }
820                                    }
821
822                                    if (gst != EFindSqlStateType.stsql) {
823                                        onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
824                                        gst = EFindSqlStateType.stnormal;
825                                    }
826
827                                } else {
828                                    lcblocklevel--;
829                                }
830
831                            }
832                        }
833                    }
834                    break;
835                }
836                case sttrycatch: {
837
838                    if (TBaseType.assigned(lcnextsqlstatement)) {
839                        if (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlgo) {
840                            onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
841                            gcurrentsqlstatement = lcnextsqlstatement;
842                            addTokenToStatement(ast);
843                            onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
844                            gst = EFindSqlStateType.stnormal;
845                        } else {
846                            if (
847                                    (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlbegintry)
848                                            || (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlbegincatch)
849                            )
850                                lctrycatchlevel++;
851                            lcnextsqlstatement = null;
852                        }
853                    }
854
855                    if (gst == EFindSqlStateType.sttrycatch) {
856                        addTokenToStatement(ast);
857                        if ((ast.tokencode == TBaseType.rrw_try) ||
858                                (ast.tokencode == TBaseType.rrw_catch)) {
859                            if (TBaseType.assigned(lcprevsolidtoken)) {
860                                if (lcprevsolidtoken.tokencode == TBaseType.rrw_end) {
861                                    if (lctrycatchlevel == 0) {
862                                        onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
863                                        gst = EFindSqlStateType.stnormal;
864                                    } else
865                                        lctrycatchlevel--;
866                                }
867                            }
868                        }
869                    }
870                    break;
871                }
872                case stprocedureWithReturn: {
873                    if (TBaseType.assigned(lcnextsqlstatement)) {
874                        if (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlgo) {
875                            onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
876                            gcurrentsqlstatement = lcnextsqlstatement;
877                            addTokenToStatement(ast);
878                            onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
879                            gst = EFindSqlStateType.stnormal;
880                            break;
881                        }
882                    }
883
884                    addTokenToStatement(ast);
885                    if ((gst == EFindSqlStateType.stprocedureWithReturn) && (ast.tokentype == ETokenType.ttsemicolon)) {
886                        onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
887                        gst = EFindSqlStateType.stnormal;
888                    }
889                    break;
890                }
891                case stsql: {
892                    if ((ast.tokentype == ETokenType.ttsemicolon)) {
893                        lcstillinsql = false;
894                        if (gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlif) {
895                            lcnextsolidtoken = sourcetokenlist.nextsolidtoken(i, 1, false);
896                            if (TBaseType.assigned(lcnextsolidtoken)) {
897                                if (lcnextsolidtoken.tokencode == TBaseType.rrw_else) {
898                                    addTokenToStatement(ast);
899                                    lcstillinsql = true;
900                                }
901
902                            }
903                        }
904
905                        if (!lcstillinsql) {
906                            gst = EFindSqlStateType.stnormal;
907                            addTokenToStatement(ast);
908                            gcurrentsqlstatement.semicolonended = ast;
909                            onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
910                        }
911
912                    } else if (TBaseType.assigned(lcnextsqlstatement)) {
913
914                        if (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlgo) {
915                            onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
916                            gcurrentsqlstatement = lcnextsqlstatement;
917                            addTokenToStatement(ast);
918                            onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
919                            gst = EFindSqlStateType.stnormal;
920                            continue;
921                        }
922
923                        switch (gcurrentsqlstatement.sqlstatementtype) {
924                            case sstmssqlif:
925                            case sstmssqlwhile: {
926                                if ((lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlbegincatch)
927                                        || (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlbegintry)) {
928                                    addTokenToStatement(ast);
929                                    gst = EFindSqlStateType.stblock;
930                                    lcblocklevel = 1;
931                                    lcnextsqlstatement = null;
932                                    continue;
933
934                                } else if (gcurrentsqlstatement.dummytag == 1) {
935                                    addTokenToStatement(ast);
936
937                                    if ((lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlif)
938                                            || (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlwhile))
939                                        gcurrentsqlstatement.dummytag = 1;
940                                    else
941                                        gcurrentsqlstatement.dummytag = 0;
942
943                                    lcnextsqlstatement = null;
944                                    continue;
945                                } else {
946                                    if (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlif) {
947                                        if ((ast.nextSolidToken() != null) && (ast.nextSolidToken().tokencode == TBaseType.rrw_sqlserver_exists)) {
948                                            addTokenToStatement(ast);
949                                            lcnextsqlstatement = null;
950                                            continue;
951                                        }
952                                    }
953                                }
954                                break;
955                            }
956                            case sstmssqlalterqueue: {
957                                if (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlexec) {
958                                    addTokenToStatement(ast);
959                                    lcnextsqlstatement = null;
960                                    continue;
961
962                                }
963                                break;
964                            }
965                            case sstmssqlcreateschema: {
966                                addTokenToStatement(ast);
967                                lcnextsqlstatement = null;
968                                continue;
969                            }
970                        }
971
972                        onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
973                        gcurrentsqlstatement = lcnextsqlstatement;
974                        addTokenToStatement(ast);
975
976                        switch (gcurrentsqlstatement.sqlstatementtype) {
977                            case sstmssqlcreateprocedure:
978                            case sstmssqlcreatefunction:
979                            case sstcreatetrigger:
980                            case sstmssqlalterprocedure:
981                            case sstmssqlalterfunction:
982                            case sstmssqlaltertrigger: {
983                                gst = EFindSqlStateType.ststoredprocedure;
984                                break;
985                            }
986                            case sstmssqlbegintry:
987                            case sstmssqlbegincatch: {
988                                gst = EFindSqlStateType.sttrycatch;
989                                lctrycatchlevel = 0;
990                                break;
991                            }
992                            case sstmssqlgo: {
993                                gst = EFindSqlStateType.stnormal;
994                                break;
995                            }
996                            default: {
997                                gst = EFindSqlStateType.stsql;
998                                break;
999                            }
1000                        }
1001
1002                    } else if ((ast.tokencode == TBaseType.rrw_begin)) {
1003                        if ((gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlif)
1004                                || (gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlwhile)) {
1005                            gst = EFindSqlStateType.stblock;
1006                            lcblocklevel = 0;
1007                            addTokenToStatement(ast);
1008                        } else if (gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqldeclare) {
1009                            onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
1010                            gcurrentsqlstatement = new TMssqlBlock(vendor);
1011                            gcurrentsqlstatement.sqlstatementtype = ESqlStatementType.sstmssqlblock;
1012                            addTokenToStatement(ast);
1013                            gst = EFindSqlStateType.stblock;
1014                        } else {
1015                            addTokenToStatement(ast);
1016                        }
1017                    } else if ((ast.tokencode == TBaseType.rrw_case)) {
1018                        case_end_nest++;
1019                        addTokenToStatement(ast);
1020                    } else if ((ast.tokencode == TBaseType.rrw_end)) {
1021                        if (case_end_nest > 0) {
1022                            case_end_nest--;
1023                        }
1024                        addTokenToStatement(ast);
1025                    } else if ((ast.tokencode == TBaseType.rrw_else)) {
1026                        addTokenToStatement(ast);
1027                        if (((gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlif)
1028                                || (gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlwhile)
1029                        ) && (case_end_nest == 0))
1030                            gcurrentsqlstatement.dummytag = 1;
1031                    } else {
1032                        addTokenToStatement(ast);
1033                    }
1034                    break;
1035                }
1036                case ststoredprocedure: {
1037                    if (TBaseType.assigned(lcnextsqlstatement)) {
1038                        if (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlgo) {
1039                            onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
1040                            gcurrentsqlstatement = lcnextsqlstatement;
1041                            addTokenToStatement(ast);
1042                            onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
1043                            gst = EFindSqlStateType.stnormal;
1044                        } else if (lcnextsqlstatement.sqlstatementtype == sstmssqlreturn) {
1045                            gst = EFindSqlStateType.stprocedureWithReturn;
1046                            addTokenToStatement(ast);
1047                            lcnextsqlstatement = null;
1048                        } else {
1049                            gst = EFindSqlStateType.ststoredprocedurebody;
1050                            addTokenToStatement(ast);
1051
1052                            lcnextsqlstatement = null;
1053                        }
1054                    }
1055
1056                    if (gst == EFindSqlStateType.ststoredprocedure) {
1057                        addTokenToStatement(ast);
1058                        if (ast.tokencode == TBaseType.rrw_begin) {
1059                            gst = EFindSqlStateType.stblock;
1060                        }
1061                    }
1062                    break;
1063                }
1064                case ststoredprocedurebody: {
1065                    if (TBaseType.assigned(lcnextsqlstatement)) {
1066                        switch (lcnextsqlstatement.sqlstatementtype) {
1067                            case sstmssqlgo: {
1068                                onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
1069                                gcurrentsqlstatement = lcnextsqlstatement;
1070                                addTokenToStatement(ast);
1071                                onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
1072                                gst = EFindSqlStateType.stnormal;
1073                                break;
1074                            }
1075                            case sstmssqlcreateprocedure:
1076                            case sstmssqlcreatefunction:
1077                            case sstcreatetrigger:
1078                            case sstmssqlalterprocedure:
1079                            case sstmssqlalterfunction:
1080                            case sstmssqlaltertrigger: {
1081                                onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
1082                                gcurrentsqlstatement = lcnextsqlstatement;
1083                                addTokenToStatement(ast);
1084                                gst = EFindSqlStateType.ststoredprocedure;
1085                                break;
1086                            }
1087                            case sstcreateview:
1088                            case sstcreatetable: {
1089
1090                                boolean readForNewStmt = false;
1091                                TSourceToken st1 = ast.searchToken(';', -1);
1092                                if (st1 != null) {
1093                                    TSourceToken st2 = ast.searchToken(TBaseType.rrw_end, -2);
1094                                    if (st2 != null) {
1095                                        readForNewStmt = true;
1096                                    }
1097                                }
1098
1099                                if (readForNewStmt) {
1100                                    onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
1101                                    gcurrentsqlstatement = lcnextsqlstatement;
1102                                    addTokenToStatement(ast);
1103                                    gst = EFindSqlStateType.stsql;
1104                                } else {
1105                                    lcnextsqlstatement = null;
1106                                }
1107                                break;
1108                            }
1109                            case sstmssqlDropSecurityPolicy:
1110                            case sstmssqlAlterSecurityPolicy:
1111                            case sstmssqlCreateSecurityPolicy:
1112                                onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder);
1113                                gcurrentsqlstatement = lcnextsqlstatement;
1114                                addTokenToStatement(ast);
1115                                gst = EFindSqlStateType.stsql;
1116
1117                                break;
1118                            default: {
1119                                lcnextsqlstatement = null;
1120                                break;
1121                            }
1122                        }
1123                    }
1124
1125                    if (gst == EFindSqlStateType.ststoredprocedurebody)
1126                        addTokenToStatement(ast);
1127                }
1128                break;
1129            }
1130        }
1131
1132        // last statement
1133        if (TBaseType.assigned(gcurrentsqlstatement) && (gst != EFindSqlStateType.stnormal)) {
1134            onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, true, builder);
1135        }
1136
1137        builder.sqlStatements(this.sqlstatements);
1138        builder.errorCode(errorcount);
1139        builder.errorMessage(errorcount == 0 ? "" : String.format("Extraction completed with %d error(s)", errorcount));
1140    }
1141}