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.TLexerSybase; 010import gudusoft.gsqlparser.TParserSybase; 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 040/** 041 * Sybase SQL parser implementation. 042 * 043 * <p>This parser handles Sybase-specific SQL syntax including: 044 * <ul> 045 * <li>Sybase stored procedures with GO statement boundaries</li> 046 * <li>Sybase BEGIN/END blocks</li> 047 * <li>Sybase TRY/CATCH blocks</li> 048 * <li>Sybase-specific statement types</li> 049 * </ul> 050 * 051 * <p><b>Design Notes:</b> 052 * <ul> 053 * <li>Extends {@link AbstractSqlParser} using the template method pattern</li> 054 * <li>Uses {@link TLexerSybase} for tokenization</li> 055 * <li>Uses {@link TParserSybase} for parsing</li> 056 * <li>Tokenization and statement extraction similar to MSSQL</li> 057 * <li>Delimiter character: ';' for Sybase statements</li> 058 * </ul> 059 * 060 * @see SqlParser 061 * @see AbstractSqlParser 062 * @see TLexerSybase 063 * @see TParserSybase 064 * @since 3.2.0.0 065 */ 066public class SybaseSqlParser extends AbstractSqlParser { 067 068 /** 069 * Construct Sybase SQL parser. 070 * <p> 071 * Configures the parser for Sybase with default delimiter (;). 072 */ 073 public SybaseSqlParser() { 074 super(EDbVendor.dbvsybase); 075 this.delimiterChar = ';'; 076 this.defaultDelimiterStr = ";"; 077 078 // Create lexer once - will be reused for all parsing operations 079 this.flexer = new TLexerSybase(); 080 this.flexer.delimiterchar = this.delimiterChar; 081 this.flexer.defaultDelimiterStr = this.defaultDelimiterStr; 082 083 // Set parent's lexer reference for shared tokenization logic 084 this.lexer = this.flexer; 085 086 // Create parser once - will be reused for all parsing operations 087 this.fparser = new TParserSybase(null); 088 this.fparser.lexer = this.flexer; 089 } 090 091 // ========== Parser Components ========== 092 093 /** The Sybase lexer used for tokenization */ 094 public TLexerSybase flexer; 095 096 /** Sybase parser (for Sybase statements) */ 097 private TParserSybase fparser; 098 099 /** Current statement being built during extraction */ 100 private TCustomSqlStatement gcurrentsqlstatement; 101 102 // ========== AbstractSqlParser Abstract Methods Implementation ========== 103 104 /** 105 * Return the Sybase lexer instance. 106 */ 107 @Override 108 protected TCustomLexer getLexer(ParserContext context) { 109 return this.flexer; 110 } 111 112 /** 113 * Return the Sybase parser instance with updated token list. 114 */ 115 @Override 116 protected TCustomParser getParser(ParserContext context, TSourceTokenList tokens) { 117 this.fparser.sourcetokenlist = tokens; 118 return this.fparser; 119 } 120 121 /** 122 * Call Sybase-specific tokenization logic. 123 * <p> 124 * Sybase uses MSSQL-like tokenization. 125 */ 126 @Override 127 protected void tokenizeVendorSql() { 128 dosybasesqltexttotokenlist(); 129 } 130 131 /** 132 * Setup Sybase parser for raw statement extraction. 133 */ 134 @Override 135 protected void setupVendorParsersForExtraction() { 136 this.fparser.sqlcmds = this.sqlcmds; 137 this.fparser.sourcetokenlist = this.sourcetokenlist; 138 } 139 140 /** 141 * Call Sybase-specific raw statement extraction logic. 142 */ 143 @Override 144 protected void extractVendorRawStatements(SqlParseResult.Builder builder) { 145 dosybasegetrawsqlstatements(builder); 146 } 147 148 /** 149 * Perform full parsing of statements with syntax checking. 150 */ 151 @Override 152 protected TStatementList performParsing(ParserContext context, 153 TCustomParser parser, 154 TCustomParser secondaryParser, 155 TSourceTokenList tokens, 156 TStatementList rawStatements) { 157 this.fparser = (TParserSybase) parser; 158 this.sourcetokenlist = tokens; 159 this.parserContext = context; 160 this.sqlstatements = rawStatements; 161 162 this.sqlcmds = SqlCmdsFactory.get(vendor); 163 this.fparser.sqlcmds = this.sqlcmds; 164 165 if (context != null && context.getGsqlparser() != null) { 166 TGSqlParser gsqlparser = (TGSqlParser) context.getGsqlparser(); 167 this.frameStack = gsqlparser.getFrameStack(); 168 this.fparser.getNf().setGsqlParser(gsqlparser); 169 this.globalContext = new TContext(); 170 this.sqlEnv = new TSQLEnv(this.vendor) { 171 @Override 172 public void initSQLEnv() { 173 } 174 }; 175 this.globalContext.setSqlEnv(this.sqlEnv, this.sqlstatements); 176 } else { 177 initializeGlobalContext(); 178 } 179 180 for (int i = 0; i < sqlstatements.size(); i++) { 181 TCustomSqlStatement stmt = sqlstatements.getRawSql(i); 182 183 try { 184 stmt.setFrameStack(frameStack); 185 int parseResult = stmt.parsestatement(null, false, context.isOnlyNeedRawParseTree()); 186 187 boolean doRecover = TBaseType.ENABLE_ERROR_RECOVER_IN_CREATE_TABLE; 188 if (doRecover && ((parseResult != 0) || (stmt.getErrorCount() > 0))) { 189 handleCreateTableErrorRecovery(stmt); 190 } 191 192 if ((parseResult != 0) || (stmt.getErrorCount() > 0)) { 193 copyErrorsFromStatement(stmt); 194 } 195 196 } catch (Exception ex) { 197 handleStatementParsingException(stmt, i, ex); 198 continue; 199 } 200 } 201 202 if (globalFrame != null) { 203 globalFrame.popMeFromStack(frameStack); 204 } 205 206 return this.sqlstatements; 207 } 208 209 private void handleCreateTableErrorRecovery(TCustomSqlStatement stmt) { 210 if (((stmt.sqlstatementtype == ESqlStatementType.sstcreatetable) 211 || (stmt.sqlstatementtype == ESqlStatementType.sstcreateindex)) 212 && (!TBaseType.c_createTableStrictParsing)) { 213 214 int nested = 0; 215 boolean isIgnore = false, isFoundIgnoreToken = false; 216 TSourceToken firstIgnoreToken = null; 217 218 for (int k = 0; k < stmt.sourcetokenlist.size(); k++) { 219 TSourceToken st = stmt.sourcetokenlist.get(k); 220 if (isIgnore) { 221 if (st.issolidtoken() && (st.tokencode != ';')) { 222 isFoundIgnoreToken = true; 223 if (firstIgnoreToken == null) { 224 firstIgnoreToken = st; 225 } 226 } 227 if (st.tokencode != ';') { 228 st.tokencode = TBaseType.sqlpluscmd; 229 } 230 continue; 231 } 232 if (st.tokencode == (int) ')') { 233 nested--; 234 if (nested == 0) { 235 boolean isSelect = false; 236 TSourceToken st1 = st.searchToken(TBaseType.rrw_as, 1); 237 if (st1 != null) { 238 TSourceToken st2 = st.searchToken((int) '(', 2); 239 if (st2 != null) { 240 TSourceToken st3 = st.searchToken(TBaseType.rrw_select, 3); 241 isSelect = (st3 != null); 242 } 243 } 244 if (!isSelect) isIgnore = true; 245 } 246 } else if (st.tokencode == (int) '(') { 247 nested++; 248 } 249 } 250 251 if (isFoundIgnoreToken) { 252 stmt.clearError(); 253 stmt.parsestatement(null, false); 254 } 255 } 256 } 257 258 @Override 259 protected void performSemanticAnalysis(ParserContext context, TStatementList statements) { 260 if (context != null && context.getGsqlparser() != null) { 261 return; 262 } 263 264 if (getSyntaxErrors().isEmpty()) { 265 if (TBaseType.isEnableResolver2()) { 266 TSQLResolverConfig config = new TSQLResolverConfig(); 267 config.setVendor(vendor); 268 TSQLResolver2 resolver2 = new TSQLResolver2(null, statements, config); 269 if (this.sqlEnv != null) { 270 resolver2.setSqlEnv(this.sqlEnv); 271 } 272 resolver2.resolve(); 273 } else if (TBaseType.isEnableResolver()) { 274 TSQLResolver resolver = new TSQLResolver(globalContext, statements); 275 resolver.resolve(); 276 } 277 } 278 } 279 280 @Override 281 protected void performInterpreter(ParserContext context, TStatementList statements) { 282 if (TBaseType.ENABLE_INTERPRETER && getSyntaxErrors().isEmpty()) { 283 TLog.clearLogs(); 284 TGlobalScope interpreterScope = new TGlobalScope(sqlEnv); 285 TLog.enableInterpreterLogOnly(); 286 TASTEvaluator astEvaluator = new TASTEvaluator(statements, interpreterScope); 287 astEvaluator.eval(); 288 } 289 } 290 291 // ========== Helper Methods ========== 292 293 /** 294 * Add token to current statement with proper statement linkage. 295 * This replicates TCustomSqlStatement.addtokentolist() behavior 296 * which sets st.stmt = this before adding. 297 */ 298 private void addTokenToStatement(TSourceToken st) { 299 st.stmt = gcurrentsqlstatement; 300 gcurrentsqlstatement.sourcetokenlist.add(st); 301 } 302 303 // ========== Sybase-Specific Tokenization ========== 304 305 /** 306 * Sybase-specific tokenization logic. 307 * <p> 308 * Sybase uses MSSQL-like tokenization. 309 * Migrated from TGSqlParser.dosybasesqltexttotokenlist() 310 */ 311 private void dosybasesqltexttotokenlist() { 312 TSourceToken lcprevtoken = null; 313 int lcsteps = 0; 314 TSourceToken asourcetoken, lctoken, lctoken2, lctoken3; 315 int yychar; 316 boolean iskeywordgo; 317 318 asourcetoken = getanewsourcetoken(); 319 320 if (asourcetoken == null) return; 321 322 yychar = asourcetoken.tokencode; 323 324 boolean lcinopenrowset = false; 325 int lcnested = 0; 326 327 while (yychar > 0) { 328 329 if (asourcetoken.tokencode == TBaseType.rrw_openrowset) { 330 lcinopenrowset = true; 331 lcnested = 0; 332 } else if (asourcetoken.tokentype == ETokenType.ttleftparenthesis) { 333 if ((lcsteps > 0) && TBaseType.assigned(lcprevtoken)) { 334 if (lcprevtoken.tokencode == TBaseType.rrw_primary) { 335 lcprevtoken.tokencode = TBaseType.rrw_select - 2; 336 checkconstarinttoken(lcprevtoken); 337 } else if (lcprevtoken.tokencode == TBaseType.rrw_foreign) { 338 lcprevtoken.tokencode = TBaseType.rrw_select - 4; 339 checkconstarinttoken(lcprevtoken); 340 } else if (lcprevtoken.tokencode == TBaseType.rrw_unique) { 341 lcprevtoken.tokencode = TBaseType.rrw_select - 1; 342 checkconstarinttoken(lcprevtoken); 343 } 344 lcprevtoken = null; 345 lcsteps = 0; 346 } 347 348 if (lcinopenrowset) 349 lcnested++; 350 } else if (asourcetoken.tokentype == ETokenType.ttrightparenthesis) { 351 if (lcinopenrowset) { 352 if ((lcnested > 0)) 353 lcnested--; 354 if (lcnested == 0) 355 lcinopenrowset = false; 356 } 357 } else if (asourcetoken.tokentype == ETokenType.ttsemicolon) { 358 if (lcinopenrowset) { 359 asourcetoken.tokentype = ETokenType.ttsemicolon2; 360 } else { 361 lctoken2 = asourcetoken.searchToken(TBaseType.rrw_begin, -1); 362 if (lctoken2 != null) { 363 asourcetoken.tokencode = TBaseType.SEMI_COLON_AFTER_BEGIN; 364 asourcetoken.tokentype = ETokenType.ttsemicolon3; 365 } else { 366 lctoken2 = asourcetoken.searchToken(TBaseType.rrw_try, -1); 367 if (lctoken2 == null) { 368 lctoken2 = asourcetoken.searchToken(TBaseType.rrw_catch, -1); 369 } 370 if (lctoken2 != null) { 371 lctoken3 = asourcetoken.searchToken(TBaseType.rrw_begin, -2); 372 if (lctoken3 != null) { 373 asourcetoken.tokencode = TBaseType.SEMI_COLON_AFTER_BEGIN; 374 asourcetoken.tokentype = ETokenType.ttsemicolon3; 375 } 376 } 377 } 378 } 379 } else if (asourcetoken.tokentype == ETokenType.ttperiod) { 380 lctoken = getprevtoken(asourcetoken); 381 if (TBaseType.assigned(lctoken)) { 382 if (lctoken.tokencode == TBaseType.rrw_go) { 383 lctoken.tokencode = TBaseType.ident; 384 lctoken.tokentype = ETokenType.ttidentifier; 385 } 386 } 387 } else if (asourcetoken.tokencode == TBaseType.rrw_table) { 388 lctoken = getprevtoken(asourcetoken); 389 if (TBaseType.assigned(lctoken)) { 390 if (lctoken.tokencode == TBaseType.rrw_lock) { 391 lctoken.tokencode = TBaseType.rw_locktable; 392 } 393 } 394 } else if (asourcetoken.tokencode == TBaseType.rrw_sybase_isolation) { 395 // AT ISOLATION clause - change 'at' token code for grammar recognition 396 lctoken = getprevtoken(asourcetoken); 397 if (TBaseType.assigned(lctoken)) { 398 if (lctoken.tokencode == TBaseType.rrw_sybase_at) { 399 lctoken.tokencode = TBaseType.rw_sybase_at1; 400 } 401 } 402 } else if (asourcetoken.tokencode == TBaseType.rrw_update) { 403 // UPDATE in create trigger context 404 lctoken = getprevtoken(asourcetoken); 405 if (TBaseType.assigned(lctoken)) { 406 if ((lctoken.tokencode == TBaseType.rrw_not) 407 || (lctoken.tokencode == TBaseType.rrw_and) 408 || (lctoken.tokencode == TBaseType.rrw_or) 409 || (lctoken.tokencode == TBaseType.rrw_if) 410 ) { 411 // this is update(column) in create trigger 412 asourcetoken.tokencode = TBaseType.rw_sybase_update1; 413 } 414 } 415 } else if (asourcetoken.tokencode == TBaseType.rrw_go) { 416 iskeywordgo = true; 417 lctoken = getprevtoken(asourcetoken); 418 if (TBaseType.assigned(lctoken)) { 419 if ((lctoken.lineNo == asourcetoken.lineNo) && (lctoken.tokencode != ';')) { 420 iskeywordgo = false; 421 } 422 } 423 424 if (iskeywordgo) { 425 lcinopenrowset = false; 426 lcnested = 0; 427 lcprevtoken = asourcetoken; 428 } else { 429 asourcetoken.tokencode = TBaseType.ident; 430 asourcetoken.tokentype = ETokenType.ttidentifier; 431 } 432 } else if (asourcetoken.tokencode == TBaseType.rrw_primary) { 433 lcsteps = 2; 434 lcprevtoken = asourcetoken; 435 } else if (asourcetoken.tokencode == TBaseType.rrw_foreign) { 436 lcsteps = 2; 437 lcprevtoken = asourcetoken; 438 } else if (asourcetoken.tokencode == TBaseType.rrw_unique) { 439 lcsteps = 1; 440 lcprevtoken = asourcetoken; 441 } else if (asourcetoken.issolidtoken()) { 442 if (lcsteps > 0) { 443 if (!(TBaseType.mysametext("clustered", asourcetoken.toString()) 444 || TBaseType.mysametext("nonclustered", asourcetoken.toString()) 445 || TBaseType.mysametext("hash", asourcetoken.toString()) 446 )) 447 lcsteps--; 448 } 449 } 450 451 sourcetokenlist.add(asourcetoken); 452 453 asourcetoken = getanewsourcetoken(); 454 if (asourcetoken == null) break; 455 yychar = asourcetoken.tokencode; 456 } 457 } 458 459 private TSourceToken getprevtoken(TSourceToken ptoken) { 460 TSourceTokenList lcstlist = ptoken.container; 461 if (TBaseType.assigned(lcstlist)) { 462 if ((ptoken.posinlist > 0) && (lcstlist.size() > ptoken.posinlist - 1)) { 463 if (!((lcstlist.get(ptoken.posinlist - 1).tokentype == ETokenType.ttwhitespace) 464 || (lcstlist.get(ptoken.posinlist - 1).tokentype == ETokenType.ttreturn) 465 || (lcstlist.get(ptoken.posinlist - 1).tokentype == ETokenType.ttsimplecomment) 466 || (lcstlist.get(ptoken.posinlist - 1).tokentype == ETokenType.ttbracketedcomment) 467 )) { 468 return lcstlist.get(ptoken.posinlist - 1); 469 } else { 470 return lcstlist.nextsolidtoken(ptoken.posinlist - 1, -1, false); 471 } 472 } 473 } 474 return null; 475 } 476 477 private void checkconstarinttoken(TSourceToken token) { 478 TSourceTokenList lcStList = token.container; 479 if (TBaseType.assigned(lcStList)) { 480 TSourceToken lcPPToken = lcStList.nextsolidtoken(token.posinlist, -2, false); 481 if (TBaseType.assigned(lcPPToken)) { 482 if (lcPPToken.tokencode == flexer.getkeywordvalue("constraint")) { 483 lcPPToken.tokencode = TBaseType.rw_constraint2; 484 } 485 } 486 } 487 } 488 489 // ========== Sybase-Specific Raw Statement Extraction ========== 490 491 /** 492 * Sybase-specific raw statement extraction logic. 493 * <p> 494 * Migrated from TGSqlParser.dosybasegetrawsqlstatements() 495 */ 496 private void dosybasegetrawsqlstatements(SqlParseResult.Builder builder) { 497 int errorcount = 0; 498 int case_end_nest = 0; 499 500 if (TBaseType.assigned(sqlstatements)) sqlstatements.clear(); 501 if (!TBaseType.assigned(sourcetokenlist)) { 502 builder.errorCode(-1); 503 builder.errorMessage("Source token list is null"); 504 return; 505 } 506 507 gcurrentsqlstatement = null; 508 EFindSqlStateType gst = EFindSqlStateType.stnormal; 509 int lcblocklevel = 0; 510 int lctrycatchlevel = 0; 511 TSourceToken lcprevsolidtoken = null, lcnextsolidtoken, lcnnextsolidtoken; 512 TSourceToken ast = null; 513 int i; 514 boolean lcisendconversation, lcstillinsql; 515 516 for (i = 0; i < sourcetokenlist.size(); i++) { 517 518 if ((ast != null) && (ast.issolidtoken())) 519 lcprevsolidtoken = ast; 520 521 ast = sourcetokenlist.get(i); 522 sourcetokenlist.curpos = i; 523 if (ast.tokenstatus == ETokenStatus.tsignoredbygetrawstatement) { 524 addTokenToStatement(ast); 525 continue; 526 } 527 528 if (gst == EFindSqlStateType.ststoredprocedurebody) { 529 if (!((ast.tokencode == TBaseType.rrw_go) 530 || (ast.tokencode == TBaseType.rrw_create) 531 || (ast.tokencode == TBaseType.rrw_alter))) { 532 addTokenToStatement(ast); 533 continue; 534 } 535 } 536 537 TCustomSqlStatement lcnextsqlstatement = sqlcmds.issql(ast, gst, gcurrentsqlstatement); 538 539 switch (gst) { 540 case sterror: { 541 if (TBaseType.assigned(lcnextsqlstatement)) { 542 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 543 gcurrentsqlstatement = lcnextsqlstatement; 544 addTokenToStatement(ast); 545 gst = EFindSqlStateType.stsql; 546 } else if ((ast.tokentype == ETokenType.ttsemicolon)) { 547 addTokenToStatement(ast); 548 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 549 gst = EFindSqlStateType.stnormal; 550 } else { 551 addTokenToStatement(ast); 552 } 553 break; 554 } 555 case stnormal: { 556 if ((ast.tokencode == TBaseType.cmtdoublehyphen) 557 || (ast.tokencode == TBaseType.cmtslashstar) 558 || (ast.tokencode == TBaseType.lexspace) 559 || (ast.tokencode == TBaseType.lexnewline) 560 || (ast.tokentype == ETokenType.ttsemicolon)) { 561 if (TBaseType.assigned(gcurrentsqlstatement)) { 562 addTokenToStatement(ast); 563 } 564 565 if (TBaseType.assigned(lcprevsolidtoken) && (ast.tokentype == ETokenType.ttsemicolon)) { 566 if (lcprevsolidtoken.tokentype == ETokenType.ttsemicolon) { 567 ast.tokentype = ETokenType.ttsimplecomment; 568 ast.tokencode = TBaseType.cmtdoublehyphen; 569 } 570 } 571 572 continue; 573 } 574 575 gcurrentsqlstatement = lcnextsqlstatement; 576 577 if (TBaseType.assigned(gcurrentsqlstatement)) { 578 switch (gcurrentsqlstatement.sqlstatementtype) { 579 case sstmssqlcreateprocedure: 580 case sstmssqlcreatefunction: 581 case sstcreatetrigger: 582 case sstmssqlalterprocedure: 583 case sstmssqlalterfunction: 584 case sstmssqlaltertrigger: { 585 addTokenToStatement(ast); 586 gst = EFindSqlStateType.ststoredprocedure; 587 break; 588 } 589 case sstmssqlbegintry: 590 case sstmssqlbegincatch: { 591 addTokenToStatement(ast); 592 gst = EFindSqlStateType.sttrycatch; 593 lctrycatchlevel = 0; 594 break; 595 } 596 case sstmssqlgo: { 597 addTokenToStatement(ast); 598 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 599 gst = EFindSqlStateType.stnormal; 600 break; 601 } 602 default: { 603 addTokenToStatement(ast); 604 if (gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqllabel) { 605 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 606 gst = EFindSqlStateType.stnormal; 607 } else { 608 gst = EFindSqlStateType.stsql; 609 } 610 break; 611 } 612 } 613 } else { 614 if (ast.tokencode == TBaseType.rrw_begin) { 615 gcurrentsqlstatement = new TMssqlBlock(vendor); 616 gcurrentsqlstatement.sqlstatementtype = ESqlStatementType.sstmssqlblock; 617 addTokenToStatement(ast); 618 gst = EFindSqlStateType.stblock; 619 } else { 620 if (sqlstatements.size() == 0) { 621 gst = EFindSqlStateType.stsql; 622 gcurrentsqlstatement = new TMssqlExecute(vendor); 623 ast.tokencode = TBaseType.rrw_sybase_exce_proc_name; 624 addTokenToStatement(ast); 625 } else if (sqlstatements.get(sqlstatements.size() - 1).sqlstatementtype == ESqlStatementType.sstmssqlgo) { 626 gst = EFindSqlStateType.stsql; 627 gcurrentsqlstatement = new TMssqlExecute(vendor); 628 ast.tokencode = TBaseType.rrw_sybase_exce_proc_name; 629 addTokenToStatement(ast); 630 } 631 } 632 } 633 634 if (!TBaseType.assigned(gcurrentsqlstatement)) { 635 this.syntaxErrors.add(new TSyntaxError(ast.getAstext(), ast.lineNo, (ast.columnNo < 0 ? 0 : ast.columnNo) 636 , "Error when tokenlize", EErrorType.spwarning, TBaseType.MSG_WARNING_ERROR_WHEN_TOKENIZE, null, ast.posinlist)); 637 638 ast.tokentype = ETokenType.tttokenlizererrortoken; 639 gst = EFindSqlStateType.sterror; 640 641 gcurrentsqlstatement = new TUnknownSqlStatement(vendor); 642 gcurrentsqlstatement.sqlstatementtype = ESqlStatementType.sstinvalid; 643 addTokenToStatement(ast); 644 } 645 break; 646 } 647 case stblock: { 648 if (TBaseType.assigned(lcnextsqlstatement)) { 649 if (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlgo) { 650 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 651 gcurrentsqlstatement = lcnextsqlstatement; 652 addTokenToStatement(ast); 653 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 654 gst = EFindSqlStateType.stnormal; 655 } else { 656 lcnextsqlstatement = null; 657 } 658 } 659 660 if (gst == EFindSqlStateType.stblock) { 661 addTokenToStatement(ast); 662 if (ast.tokencode == TBaseType.rrw_begin) { 663 lcnextsolidtoken = sourcetokenlist.nextsolidtoken(i, 1, false); 664 if (TBaseType.assigned(lcnextsolidtoken)) { 665 if (!(TBaseType.mysametext(lcnextsolidtoken.getAstext(), "tran") 666 || TBaseType.mysametext(lcnextsolidtoken.getAstext(), "transaction") 667 || TBaseType.mysametext(lcnextsolidtoken.getAstext(), "distributed") 668 || TBaseType.mysametext(lcnextsolidtoken.getAstext(), "dialog") 669 || TBaseType.mysametext(lcnextsolidtoken.getAstext(), "conversation") 670 )) 671 lcblocklevel++; 672 } else 673 lcblocklevel++; 674 675 } else if (ast.tokencode == TBaseType.rrw_case) 676 lcblocklevel++; 677 else if (ast.tokencode == TBaseType.rrw_end) { 678 679 lcisendconversation = false; 680 681 lcnextsolidtoken = sourcetokenlist.nextsolidtoken(i, 1, false); 682 if (TBaseType.assigned(lcnextsolidtoken)) { 683 if (lcnextsolidtoken.tokencode == flexer.getkeywordvalue("CONVERSATION")) 684 lcisendconversation = true; 685 } 686 687 if (!lcisendconversation) { 688 689 if (lcblocklevel == 0) { 690 if (gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlif) { 691 if (TBaseType.assigned(lcnextsolidtoken)) { 692 if (lcnextsolidtoken.tokencode == TBaseType.rrw_else) { 693 gst = EFindSqlStateType.stsql; 694 } else if (lcnextsolidtoken.tokentype == ETokenType.ttsemicolon) { 695 lcnnextsolidtoken = sourcetokenlist.nextsolidtoken(lcnextsolidtoken.posinlist, 1, false); 696 if (TBaseType.assigned(lcnnextsolidtoken)) { 697 if (lcnnextsolidtoken.tokencode == TBaseType.rrw_else) { 698 gst = EFindSqlStateType.stsql; 699 } 700 } 701 } 702 } 703 } 704 705 if (gst != EFindSqlStateType.stsql) { 706 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 707 gst = EFindSqlStateType.stnormal; 708 } 709 710 } else { 711 lcblocklevel--; 712 } 713 714 } 715 } 716 } 717 break; 718 } 719 case sttrycatch: { 720 721 if (TBaseType.assigned(lcnextsqlstatement)) { 722 if (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlgo) { 723 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 724 gcurrentsqlstatement = lcnextsqlstatement; 725 addTokenToStatement(ast); 726 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 727 gst = EFindSqlStateType.stnormal; 728 } else { 729 if ( 730 (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlbegintry) 731 || (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlbegincatch) 732 ) 733 lctrycatchlevel++; 734 lcnextsqlstatement = null; 735 } 736 } 737 738 if (gst == EFindSqlStateType.sttrycatch) { 739 addTokenToStatement(ast); 740 if ((ast.tokencode == TBaseType.rrw_try) || 741 (ast.tokencode == TBaseType.rrw_catch)) { 742 if (TBaseType.assigned(lcprevsolidtoken)) { 743 if (lcprevsolidtoken.tokencode == TBaseType.rrw_end) { 744 if (lctrycatchlevel == 0) { 745 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 746 gst = EFindSqlStateType.stnormal; 747 } else 748 lctrycatchlevel--; 749 } 750 } 751 } 752 } 753 break; 754 } 755 case stsql: { 756 if ((ast.tokentype == ETokenType.ttsemicolon)) { 757 lcstillinsql = false; 758 if (gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlif) { 759 lcnextsolidtoken = sourcetokenlist.nextsolidtoken(i, 1, false); 760 if (TBaseType.assigned(lcnextsolidtoken)) { 761 if (lcnextsolidtoken.tokencode == TBaseType.rrw_else) { 762 addTokenToStatement(ast); 763 lcstillinsql = true; 764 } 765 766 } 767 } 768 769 if (!lcstillinsql) { 770 gst = EFindSqlStateType.stnormal; 771 addTokenToStatement(ast); 772 gcurrentsqlstatement.semicolonended = ast; 773 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 774 } 775 776 } else if (TBaseType.assigned(lcnextsqlstatement)) { 777 778 if (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlgo) { 779 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 780 gcurrentsqlstatement = lcnextsqlstatement; 781 addTokenToStatement(ast); 782 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 783 gst = EFindSqlStateType.stnormal; 784 continue; 785 } 786 787 switch (gcurrentsqlstatement.sqlstatementtype) { 788 case sstmssqlif: 789 case sstmssqlwhile: { 790 if ((lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlbegincatch) 791 || (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlbegintry)) { 792 addTokenToStatement(ast); 793 gst = EFindSqlStateType.stblock; 794 lcblocklevel = 1; 795 lcnextsqlstatement = null; 796 continue; 797 798 } else if (gcurrentsqlstatement.dummytag == 1) { 799 addTokenToStatement(ast); 800 801 if ((lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlif) 802 || (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlwhile)) 803 gcurrentsqlstatement.dummytag = 1; 804 else 805 gcurrentsqlstatement.dummytag = 0; 806 807 808 lcnextsqlstatement = null; 809 continue; 810 } 811 break; 812 } 813 case sstmssqlalterqueue: { 814 if (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlexec) { 815 addTokenToStatement(ast); 816 817 lcnextsqlstatement = null; 818 continue; 819 820 } 821 break; 822 } 823 case sstmssqlcreateschema: { 824 addTokenToStatement(ast); 825 lcnextsqlstatement = null; 826 continue; 827 } 828 } 829 830 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 831 gcurrentsqlstatement = lcnextsqlstatement; 832 addTokenToStatement(ast); 833 834 switch (gcurrentsqlstatement.sqlstatementtype) { 835 case sstmssqlcreateprocedure: 836 case sstmssqlcreatefunction: 837 case sstcreatetrigger: 838 case sstmssqlalterprocedure: 839 case sstmssqlalterfunction: 840 case sstmssqlaltertrigger: { 841 gst = EFindSqlStateType.ststoredprocedure; 842 break; 843 } 844 case sstmssqlbegintry: 845 case sstmssqlbegincatch: { 846 gst = EFindSqlStateType.sttrycatch; 847 lctrycatchlevel = 0; 848 break; 849 } 850 case sstmssqlgo: { 851 gst = EFindSqlStateType.stnormal; 852 break; 853 } 854 default: { 855 gst = EFindSqlStateType.stsql; 856 break; 857 } 858 } 859 860 } else if ((ast.tokencode == TBaseType.rrw_begin)) { 861 if ((gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlif) 862 || (gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlwhile)) { 863 gst = EFindSqlStateType.stblock; 864 lcblocklevel = 0; 865 addTokenToStatement(ast); 866 } else if (gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqldeclare) { 867 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 868 gcurrentsqlstatement = new TMssqlBlock(vendor); 869 gcurrentsqlstatement.sqlstatementtype = ESqlStatementType.sstmssqlblock; 870 addTokenToStatement(ast); 871 gst = EFindSqlStateType.stblock; 872 } else { 873 addTokenToStatement(ast); 874 } 875 } else if ((ast.tokencode == TBaseType.rrw_case)) { 876 case_end_nest++; 877 addTokenToStatement(ast); 878 } else if ((ast.tokencode == TBaseType.rrw_end)) { 879 if (case_end_nest > 0) { 880 case_end_nest--; 881 } 882 addTokenToStatement(ast); 883 } else if ((ast.tokencode == TBaseType.rrw_else)) { 884 addTokenToStatement(ast); 885 if (((gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlif) 886 || (gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlwhile) 887 ) && (case_end_nest == 0)) 888 gcurrentsqlstatement.dummytag = 1; 889 } else { 890 addTokenToStatement(ast); 891 if (gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlset) { 892 if (ast.tokencode == TBaseType.rrw_on) { 893 gst = EFindSqlStateType.stnormal; 894 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 895 } 896 } 897 } 898 break; 899 } 900 case ststoredprocedure: { 901 if (TBaseType.assigned(lcnextsqlstatement)) { 902 if (lcnextsqlstatement.sqlstatementtype == ESqlStatementType.sstmssqlgo) { 903 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 904 gcurrentsqlstatement = lcnextsqlstatement; 905 addTokenToStatement(ast); 906 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 907 gst = EFindSqlStateType.stnormal; 908 } else { 909 gst = EFindSqlStateType.ststoredprocedurebody; 910 addTokenToStatement(ast); 911 912 lcnextsqlstatement = null; 913 } 914 } 915 916 if (gst == EFindSqlStateType.ststoredprocedure) { 917 addTokenToStatement(ast); 918 if (ast.tokencode == TBaseType.rrw_begin) { 919 gst = EFindSqlStateType.stblock; 920 } 921 } 922 break; 923 } 924 case ststoredprocedurebody: { 925 if (TBaseType.assigned(lcnextsqlstatement)) { 926 switch (lcnextsqlstatement.sqlstatementtype) { 927 case sstmssqlgo: { 928 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 929 gcurrentsqlstatement = lcnextsqlstatement; 930 addTokenToStatement(ast); 931 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 932 gst = EFindSqlStateType.stnormal; 933 break; 934 } 935 case sstmssqlcreateprocedure: 936 case sstmssqlcreatefunction: 937 case sstcreatetrigger: 938 case sstmssqlalterprocedure: 939 case sstmssqlalterfunction: 940 case sstmssqlaltertrigger: { 941 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, false, builder); 942 gcurrentsqlstatement = lcnextsqlstatement; 943 addTokenToStatement(ast); 944 gst = EFindSqlStateType.ststoredprocedure; 945 break; 946 } 947 default: { 948 lcnextsqlstatement = null; 949 break; 950 } 951 } 952 } 953 954 if (gst == EFindSqlStateType.ststoredprocedurebody) 955 addTokenToStatement(ast); 956 } 957 break; 958 } 959 } 960 961 // last statement 962 if (TBaseType.assigned(gcurrentsqlstatement) && (gst != EFindSqlStateType.stnormal)) { 963 onRawStatementComplete(parserContext, gcurrentsqlstatement, fparser, null, sqlstatements, true, builder); 964 } 965 966 builder.sqlStatements(this.sqlstatements); 967 builder.errorCode(errorcount); 968 builder.errorMessage(errorcount == 0 ? "" : String.format("Extraction completed with %d error(s)", errorcount)); 969 } 970}