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