001/* 002 * Decompiled with CFR 0.152. 003 */ 004package gudusoft.gsqlparser.parser; 005 006import gudusoft.gsqlparser.EDataType; 007import gudusoft.gsqlparser.EDbVendor; 008import gudusoft.gsqlparser.EErrorType; 009import gudusoft.gsqlparser.EFindSqlStateType; 010import gudusoft.gsqlparser.ESqlStatementType; 011import gudusoft.gsqlparser.ETokenType; 012import gudusoft.gsqlparser.TBaseType; 013import gudusoft.gsqlparser.TCustomLexer; 014import gudusoft.gsqlparser.TCustomParser; 015import gudusoft.gsqlparser.TCustomSqlStatement; 016import gudusoft.gsqlparser.TLexerTeradata; 017import gudusoft.gsqlparser.TParserTeradata; 018import gudusoft.gsqlparser.TSourceToken; 019import gudusoft.gsqlparser.TSourceTokenList; 020import gudusoft.gsqlparser.TStatementList; 021import gudusoft.gsqlparser.TSyntaxError; 022import gudusoft.gsqlparser.nodes.TDatatypeAttribute; 023import gudusoft.gsqlparser.nodes.TFunctionCall; 024import gudusoft.gsqlparser.nodes.TTypeName; 025import gudusoft.gsqlparser.nodes.teradata.TTeradataHelper; 026import gudusoft.gsqlparser.parser.AbstractSqlParser; 027import gudusoft.gsqlparser.parser.ParserContext; 028import gudusoft.gsqlparser.parser.SqlParseResult; 029import gudusoft.gsqlparser.resolver.TSQLResolver; 030import gudusoft.gsqlparser.sqlcmds.SqlCmdsFactory; 031import gudusoft.gsqlparser.stmt.TUnknownSqlStatement; 032import gudusoft.gsqlparser.stmt.teradata.TTeradataBTEQCmd; 033import gudusoft.gsqlparser.stmt.teradata.TTeradataFastExportCmd; 034import gudusoft.gsqlparser.stmt.teradata.TTeradataFastLoadCmd; 035import gudusoft.gsqlparser.stmt.teradata.TTeradataMultiLoadCmd; 036import gudusoft.gsqlparser.stmt.teradata.utilities.BteqCmdType; 037import java.util.ArrayList; 038 039public class TeradataSqlParser 040extends AbstractSqlParser { 041 public TLexerTeradata flexer; 042 private TParserTeradata fparser; 043 private TCustomSqlStatement gcurrentsqlstatement; 044 private char curdelimiterchar = (char)59; 045 046 // BTEQ state tracking - must persist across token processing 047 private boolean inBTEQComment = false; 048 private boolean isContinueBTEQCmd = false; 049 050 public TeradataSqlParser() { 051 super(EDbVendor.dbvteradata); 052 this.delimiterChar = '/'; // Teradata uses forward slash as delimiter for stored procedures 053 this.defaultDelimiterStr = ";"; // Match TGSqlParser default 054 this.flexer = new TLexerTeradata(); 055 this.flexer.delimiterchar = '/'; // Must match TGSqlParser: delimiterchar = '/' 056 this.flexer.defaultDelimiterStr = ";"; // Match TGSqlParser default 057 this.lexer = this.flexer; 058 this.fparser = new TParserTeradata(null); 059 this.fparser.lexer = this.flexer; 060 } 061 062 @Override 063 protected TCustomLexer getLexer(ParserContext context) { 064 // Transfer Teradata utility type from context to lexer 065 if (context.getTeradataUtilityType() != null) { 066 this.flexer.setTeradataUtilityType(context.getTeradataUtilityType()); 067 } 068 return this.flexer; 069 } 070 071 @Override 072 protected TCustomParser getParser(ParserContext context, TSourceTokenList tokens) { 073 this.fparser.sourcetokenlist = tokens; 074 return this.fparser; 075 } 076 077 @Override 078 protected TCustomParser getSecondaryParser(ParserContext context, TSourceTokenList tokens) { 079 return null; 080 } 081 082 @Override 083 protected void tokenizeVendorSql() { 084 this.doteradatatexttotokenlist(); 085 } 086 087 @Override 088 protected void setupVendorParsersForExtraction() { 089 this.fparser.sqlcmds = this.sqlcmds; 090 this.fparser.sourcetokenlist = this.sourcetokenlist; 091 } 092 093 @Override 094 protected void extractVendorRawStatements(SqlParseResult.Builder builder) { 095 this.doteradatagetrawsqlstatements(builder); 096 } 097 098 private void doteradatatexttotokenlist() { 099 TSourceToken asourcetoken, lcprevst; 100 int yychar; 101 102 asourcetoken = this.getanewsourcetoken(); 103 if (asourcetoken == null) { 104 return; 105 } 106 yychar = asourcetoken.tokencode; 107 108 while (yychar > 0) { 109 this.sourcetokenlist.add(asourcetoken); 110 asourcetoken = this.getanewsourcetoken(); 111 if (asourcetoken == null) break; 112 113 if ((asourcetoken.tokencode == TBaseType.rrw_casespecific) 114 || (asourcetoken.tokencode == TBaseType.rrw_teradata_cs)) { 115 // change not to not1 to make "not null column constraints" work correctly 116 // |RW_NOT1 RW_CASESPECIFIC 117 lcprevst = this.getprevsolidtoken(asourcetoken); 118 if (lcprevst != null) { 119 if (lcprevst.tokencode == TBaseType.rrw_not) { 120 lcprevst.tokencode = TBaseType.rw_not1; 121 } 122 } 123 } else if (asourcetoken.tokencode == ';') { 124 lcprevst = this.getprevsolidtoken(asourcetoken); 125 if (lcprevst != null) { 126 if (lcprevst.tokencode == ';') { 127 asourcetoken.tokencode = TBaseType.sqlpluscmd; 128 } 129 } 130 } else if (asourcetoken.tokencode == TBaseType.variable) { // mantisbt/view.php?id=972 131 if (asourcetoken.toString().toLowerCase().endsWith("begin")) { // MYPROC :BEGIN 132 asourcetoken.tokencode = TBaseType.rrw_begin; 133 asourcetoken.tokentype = ETokenType.ttkeyword; 134 135 lcprevst = this.getprevsolidtoken(asourcetoken); 136 if (lcprevst != null) { 137 lcprevst.tokencode = TBaseType.mslabel; 138 } 139 } 140 } else if (asourcetoken.tokencode == TCustomLexer.UNICODE_ENCODE_ID) { 141 if (asourcetoken.toString().endsWith("008D")) { // REVERSE LINE FEED, https://codepoints.net/U+008D?lang=en 142 asourcetoken.tokencode = TBaseType.lexspace; 143 } else { 144 asourcetoken.tokencode = TBaseType.ident; 145 } 146 } 147 148 yychar = asourcetoken.tokencode; 149 } 150 } 151 152 private TSourceToken getprevsolidtoken(TSourceToken ptoken) { 153 TSourceToken ret = null; 154 TSourceTokenList lctokenlist = ptoken.container; 155 if (lctokenlist != null && ptoken.posinlist > 0 && lctokenlist.size() > ptoken.posinlist - 1) { 156 ret = lctokenlist.get((int)(ptoken.posinlist - 1)).tokentype != ETokenType.ttwhitespace && lctokenlist.get((int)(ptoken.posinlist - 1)).tokentype != ETokenType.ttreturn && lctokenlist.get((int)(ptoken.posinlist - 1)).tokentype != ETokenType.ttsimplecomment && lctokenlist.get((int)(ptoken.posinlist - 1)).tokentype != ETokenType.ttbracketedcomment ? lctokenlist.get(ptoken.posinlist - 1) : lctokenlist.nextsolidtoken(ptoken.posinlist - 1, -1, false); 157 } 158 return ret; 159 } 160 161 private int doteradatagetrawsqlstatements(SqlParseResult.Builder builder) { 162 this.gcurrentsqlstatement = null; 163 EFindSqlStateType gst = EFindSqlStateType.stnormal; 164 int lcNestedParens = 0; 165 int lcNestedBeginEnd = 0; 166 int lcNestedCase = 0; 167 int lcNestedSample = 0; 168 Object lcprevst = null; 169 Object lcnextst = null; 170 Object lcnextst2 = null; 171 Object lcnextst3 = null; 172 TSourceToken lcprevsolidtoken = null; 173 TSourceToken ast = null; 174 int errorcount = 0; 175 // Note: inBTEQComment and isContinueBTEQCmd are now instance fields 176 this.inBTEQComment = false; 177 this.isContinueBTEQCmd = false; 178 char ch; 179 String lcstr; 180 block10: for (int i = 0; i < this.sourcetokenlist.size(); ++i) { 181 if (ast != null && ast.issolidtoken()) { 182 lcprevsolidtoken = ast; 183 } 184 ast = this.sourcetokenlist.get(i); 185 this.sourcetokenlist.curpos = i; 186 if (ast.tokencode != TBaseType.rrw_time && ast.tokencode != TBaseType.rrw_date && ast.tokencode != TBaseType.rrw_timestamp) { 187 if (ast.tokencode == '(') { 188 this.handleLeftParenthesisToken(ast, i); 189 } else if (ast.tokencode == TBaseType.rrw_for) { 190 this.handleForToken(ast); 191 } else if (ast.tokencode == TBaseType.rrw_teradata_last) { 192 this.handleLastToken(ast); 193 } else if (ast.tokencode == TBaseType.rrw_teradata_pivot) { 194 this.handlePivotToken(ast); 195 } else if (ast.tokencode == TBaseType.rrw_teradata_period) { 196 this.handlePeriodToken(ast); 197 } else if (ast.tokencode == TBaseType.rrw_teradata_transaction) { 198 this.handleTransactionToken(ast); 199 } else if (ast.tokencode == TBaseType.rrw_replace) { 200 this.handleReplaceToken(ast); 201 } else if (ast.tokencode == TBaseType.rrw_between) { 202 this.handleBetweenToken(ast); 203 } else if (ast.tokencode == TBaseType.rrw_declare) { 204 this.handleDeclareToken(ast); 205 } else if (ast.tokencode == TBaseType.rrw_case && ast.tag == 0 && ast.posinlist + 1 < this.sourcetokenlist.size()) { 206 this.handleCaseToken(ast); 207 } else if (ast.tokencode == TBaseType.rrw_grant) { 208 this.handleGrantToken(ast); 209 } else if (ast.tokencode == TBaseType.variable) { 210 this.handleVariableToken(ast); 211 } else if (ast.tokencode == TBaseType.rrw_teradata_sequenced || ast.tokencode == TBaseType.rrw_teradata_nonsequenced) { 212 this.handleSequencedToken(ast); 213 } 214 } 215 switch (gst) { 216 case sterror: { 217 if (ast.tokentype == ETokenType.ttsemicolon) { 218 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 219 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 220 gst = EFindSqlStateType.stnormal; 221 continue block10; 222 } 223 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 224 continue block10; 225 } 226 case stMultiLoadCmd: { 227 gst = this.handleMultiLoadCmdState(ast, gst, builder); 228 continue block10; 229 } 230 case stFastExportCmd: { 231 gst = this.handleFastExportCmdState(ast, gst, builder); 232 continue block10; 233 } 234 case stFastLoadCmd: { 235 gst = this.handleFastLoadCmdState(ast, gst, builder); 236 continue block10; 237 } 238 case stBTEQCmd: { 239 gst = this.handleBTEQCmdState(ast, builder); 240 continue block10; 241 } 242 case stnormal: { 243 gst = this.handleNormalState(ast, gst, lcprevsolidtoken, builder); 244 if (gst != EFindSqlStateType.ststoredprocedure) continue block10; 245 lcNestedParens = 0; 246 continue block10; 247 } 248 case stsql: { 249 boolean readyToEnd = true; 250 if (this.gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstteradatacreatemacro) { 251 if (ast.tokencode == '(' || ast.tokencode == TBaseType.left_parenthesis_2) { 252 ++lcNestedParens; 253 } 254 if (ast.tokencode == ')') { 255 --lcNestedParens; 256 if (lcNestedParens < 0) { 257 lcNestedParens = 0; 258 } 259 } 260 readyToEnd = lcNestedParens == 0; 261 } 262 if (ast.tokentype == ETokenType.ttsemicolon && readyToEnd) { 263 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 264 this.gcurrentsqlstatement.semicolonended = ast; 265 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 266 gst = EFindSqlStateType.stnormal; 267 continue block10; 268 } 269 if (ast.tokencode == TBaseType.cmtdoublehyphen && ast.toString().trim().endsWith(TBaseType.sqlflow_stmt_delimiter_str)) { 270 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 271 gst = EFindSqlStateType.stnormal; 272 continue block10; 273 } 274 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 275 continue block10; 276 } 277 case ststoredprocedure: { 278 boolean readyToEnd = true; 279 if (ast.tokencode == ';') { 280 // don't count case..end, sample ... end after ; 281 lcNestedSample = 0; 282 lcNestedCase = 0; 283 } else if (ast.tokencode == TBaseType.rrw_case) { // case ... end 284 ++lcNestedCase; 285 TSourceToken prevst = ast.prevSolidToken(); 286 if (prevst != null && prevst.tokencode == TBaseType.rrw_end) { 287 // don't count: end case 288 --lcNestedCase; 289 } 290 } else if (ast.tokencode == TBaseType.rrw_teradata_sample) { // sample ... end 291 ++lcNestedSample; 292 } 293 if (this.gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger 294 || this.gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreateprocedure 295 || this.gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatefunction) { 296 if (ast.tokencode == '(' || ast.tokencode == TBaseType.left_parenthesis_2) { 297 ++lcNestedParens; 298 } 299 if (ast.tokencode == ')' && --lcNestedParens < 0) { 300 lcNestedParens = 0; 301 } 302 if (ast.tokencode == TBaseType.rrw_begin) { 303 ++lcNestedBeginEnd; 304 } 305 if (ast.tokencode == TBaseType.rrw_end) { 306 boolean countThisEnd = true; 307 if (lcNestedSample > 0) { 308 // don't count sample...end 309 --lcNestedSample; 310 countThisEnd = false; 311 } else if (lcNestedCase > 0) { 312 // don't count case...end 313 --lcNestedCase; 314 countThisEnd = false; 315 } 316 if (countThisEnd) { 317 // don't count end while/if/case/loop/for/repeat 318 TSourceToken nt = ast.nextSolidToken(); 319 if (nt != null) { 320 countThisEnd = nt.tokencode != TBaseType.rrw_while 321 && nt.tokencode != TBaseType.rrw_if 322 && nt.tokencode != TBaseType.rrw_case 323 && nt.tokencode != TBaseType.rrw_loop 324 && nt.tokencode != TBaseType.rrw_for 325 && nt.tokencode != TBaseType.rrw_repeat; 326 } 327 } 328 if (countThisEnd && --lcNestedBeginEnd < 0) { 329 lcNestedBeginEnd = 0; 330 } 331 } 332 readyToEnd = lcNestedParens == 0 && lcNestedBeginEnd == 0; 333 } 334 // single stmt in function/procedure/trigger may use ; as terminate char 335 // so default terminate char is ;, if begin is found, then 336 // set terminate char to DelimiterChar 337 if (this.curdelimiterchar != this.delimiterChar) { 338 if (ast.tokencode == TBaseType.rrw_begin) { 339 this.curdelimiterchar = this.delimiterChar; 340 } else if (ast.tokencode == TBaseType.mslabel && ast.container.nextsolidtoken(ast, 1, false).tokencode == TBaseType.rrw_begin) { 341 this.curdelimiterchar = this.delimiterChar; 342 } 343 } 344 if (this.curdelimiterchar == ';') { 345 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 346 if (ast.tokentype == ETokenType.ttsemicolon 347 && (this.gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger 348 || this.gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreateprocedure) 349 && readyToEnd) { 350 gst = EFindSqlStateType.stnormal; 351 this.gcurrentsqlstatement.semicolonended = ast; 352 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 353 continue block10; 354 } 355 } else { 356 if (ast.getAstext().length() == 1) { 357 ch = ast.getAstext().charAt(0); 358 } else if (ast.getAstext().length() > 1) { 359 ch = ast.getAstext().charAt(ast.getAstext().length() - 1); 360 } else { 361 ch = ' '; 362 } 363 if (ast.tokencode != TBaseType.cmtslashstar && ast.tokencode != TBaseType.cmtdoublehyphen 364 && ch == this.curdelimiterchar && ast.isFirstTokenOfLine() && readyToEnd) { 365 if (ast.getAstext().length() > 1) { 366 lcstr = ast.getAstext().substring(0, ast.getAstext().length() - 1); 367 int c2 = this.flexer.getkeywordvalue(lcstr); 368 if (c2 > 0) { 369 ast.tokencode = c2; 370 } 371 } else { 372 this.gcurrentsqlstatement.semicolonended = ast; 373 } 374 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 375 gst = EFindSqlStateType.stnormal; 376 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 377 } else if (ast.searchToken(TBaseType.rrw_create, 1) != null && ast.searchToken(TBaseType.rrw_procedure, 4) != null && readyToEnd) { 378 gst = EFindSqlStateType.stnormal; 379 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 380 } else if (ast.tokencode == ';') { 381 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 382 boolean startNewStatement = false; 383 if (readyToEnd) { 384 startNewStatement = this.sqlcmds.issql(ast.nextSolidToken(), gst, this.gcurrentsqlstatement) != null; 385 } 386 if (startNewStatement) { 387 gst = EFindSqlStateType.stnormal; 388 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 389 } 390 } else { 391 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 392 } 393 } 394 if (gst == EFindSqlStateType.ststoredprocedure && ast.tokencode == TBaseType.cmtdoublehyphen && ast.toString().trim().endsWith(TBaseType.sqlflow_stmt_delimiter_str)) { 395 gst = EFindSqlStateType.stnormal; 396 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 397 } 398 } 399 } 400 } 401 if (TBaseType.assigned(this.gcurrentsqlstatement) && (gst == EFindSqlStateType.stsql || gst == EFindSqlStateType.stBTEQCmd || gst == EFindSqlStateType.ststoredprocedure || gst == EFindSqlStateType.sterror)) { 402 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, true, builder); 403 } 404 builder.sqlStatements(this.sqlstatements); 405 builder.syntaxErrors(this.syntaxErrors instanceof ArrayList ? (ArrayList)this.syntaxErrors : new ArrayList(this.syntaxErrors)); 406 builder.errorCode(this.syntaxErrors.isEmpty() ? 0 : this.syntaxErrors.size()); 407 return errorcount; 408 } 409 410 private void handleLeftParenthesisToken(TSourceToken ast, int i) { 411 TSourceToken lcnextst = this.sourcetokenlist.nextsolidtoken(i, 1, false); 412 TSourceToken lcprevst = this.getprevsolidtoken(ast); 413 if ((lcprevst != null) && ( 414 (lcprevst.tokencode == TBaseType.rrw_teradata_cast) 415 || (lcprevst.tokencode == TBaseType.rrw_year) // sample sql: select year(date) - 1 mantisbt/view.php?id=3049 416 )) { 417 lcnextst = null; // don't check next token if prev token is cast. sample: cast(DATETIME as BIGINT) 418 } 419 if ((lcprevst != null) && (TFunctionCall.isBuiltIn(lcprevst.toString(), EDbVendor.dbvteradata))) { 420 if (((lcprevst.tokencode == TBaseType.rrw_end) 421 || (lcprevst.tokencode == TBaseType.rrw_time) 422 || (lcprevst.tokencode == TBaseType.rrw_date) 423 || (lcprevst.tokencode == TBaseType.rrw_timestamp) 424 || (lcprevst.tokencode == TBaseType.rrw_teradata_type) 425 || (lcprevst.toString().equalsIgnoreCase("current_date")) 426 || (lcprevst.toString().equalsIgnoreCase("current_time")) 427 || (lcprevst.toString().equalsIgnoreCase("current_timestamp")) 428 || (lcprevst.toString().equalsIgnoreCase("user")) 429 || (lcprevst.toString().equalsIgnoreCase("current_user")) 430 )) { 431 // Keep lcnextst as is 432 } else { 433 lcnextst = null; 434 } 435 } 436 if (lcnextst != null) { 437 EDataType dataType = TTypeName.searchTeradataTypeByName(lcnextst.toString()); 438 if ((dataType != null) && (lcprevst != null) && (lcprevst.tokencode != TBaseType.rrw_teradata_period)) { 439 ast.tokencode = TBaseType.rrw_teradata_start_data_conversion; 440 // lcnextst2 is the token 2 steps after ( 441 TSourceToken lcnextst2 = this.sourcetokenlist.nextsolidtoken(i, 2, false); 442 // lcnextst3 is the token 3 steps after ( 443 TSourceToken lcnextst3 = this.sourcetokenlist.nextsolidtoken(i, 3, false); 444 if (lcnextst2.tokencode == ',') { 445 // this is data conversion: (date,format '$xxx'), 446 // this is not data conversion: trunc(date,'yy') 447 TSourceToken st1 = lcnextst3; 448 TSourceToken st2 = this.sourcetokenlist.nextsolidtoken(i, 4, false); 449 if (TDatatypeAttribute.searchDataTypeAttributeByName(st1, st2) == null) { 450 // this is not data conversion, such as :trunc(date,'yy') 451 ast.tokencode = '('; 452 } 453 } else if (lcnextst2 != null && lcnextst3 != null) { 454 this.handleDataTypeConversion(ast, dataType, lcnextst2, lcnextst3); 455 } 456 } else { 457 TSourceToken st1 = lcnextst; 458 TSourceToken st2 = this.sourcetokenlist.nextsolidtoken(i, 2, false); 459 if (TDatatypeAttribute.searchDataTypeAttributeByName(st1, st2) != null) { 460 ast.tokencode = TBaseType.rrw_teradata_start_data_conversion; 461 } 462 } 463 } 464 } 465 466 private void handleDataTypeConversion(TSourceToken ast, EDataType dataType, TSourceToken lcnextst2, TSourceToken lcnextst3) { 467 switch (dataType) { 468 case date_t: 469 case time_t: 470 // next token is: ) or comma or data attribute token 471 if ((lcnextst2.tokencode == ')') 472 || ((lcnextst2.tokencode == '(') && (lcnextst3.tokencode == TBaseType.iconst))) { // hire_date (time(6)) 473 // (date) 474 // select (date) from t, here (date) is a function, not a data conversion, 475 } else { 476 ast.tokencode = '('; 477 } 478 break; 479 case timestamp_t: 480 case interval_t: 481 if (lcnextst2.tokencode == TBaseType.sconst) { // INSERT t1 (TIME '10:44:25.123-08:00',TIMESTAMP '2000-09-20 10:44:25.1234') 482 ast.tokencode = '('; 483 } 484 break; 485 case period_t: 486 if (lcnextst2.tokencode == '(') { 487 // 只有 period() 才确保这里 period 是datatype,否则period不是datatype 488 } else { 489 ast.tokencode = '('; 490 } 491 break; 492 case char_t: 493 if (lcnextst2.tokencode == ')') { 494 // NULL (CHAR) AS B 495 } else if (lcnextst3.tokencode != TBaseType.iconst) { // INSERT t1 (TIME '10:44:25.123-08:00',TIMESTAMP '2000-09-20 10:44:25.1234') 496 ast.tokencode = '('; 497 } 498 break; 499 default: 500 break; 501 } 502 } 503 504 private void handleForToken(TSourceToken ast) { 505 TSourceToken nextToken = ast.searchTokenAfterObjectName(); 506 if (nextToken != null) { 507 if (nextToken.tokencode == TBaseType.rrw_as) { 508 ast.tokencode = TBaseType.rrw_teradata_for_loop; 509 } 510 } 511 } 512 513 private void handleLastToken(TSourceToken ast) { 514 TSourceToken nextToken = ast.searchToken('(', 1); 515 if (nextToken != null) { 516 ast.tokencode = TBaseType.rrw_last_function; 517 } 518 } 519 520 private void handlePivotToken(TSourceToken ast) { 521 TSourceToken nextToken = ast.searchToken('(', 1); 522 if (nextToken == null) { 523 ast.tokencode = TBaseType.ident; 524 } 525 } 526 527 private void handlePeriodToken(TSourceToken ast) { 528 TSourceToken nextToken = ast.nextSolidToken(); 529 if (nextToken == null) { 530 ast.tokencode = TBaseType.ident; 531 } else if (nextToken.tokencode == '(') { 532 // keep it as keyword 533 } else if (nextToken.tokencode == TBaseType.rrw_for) { 534 // keep it as keyword 535 } else if (nextToken.tokencode == TBaseType.sconst) { 536 // sample: DEFAULT PERIOD '(2005-02-03, 2006-02-03)' 537 // keep it as keyword 538 } else { 539 if (ast.prevSolidToken() == null) { 540 ast.tokencode = TBaseType.ident; 541 } else { 542 if (!ast.prevSolidToken().toString().equalsIgnoreCase("anchor")) { 543 ast.tokencode = TBaseType.ident; 544 } 545 } 546 } 547 } 548 549 private void handleTransactionToken(TSourceToken ast) { 550 TSourceToken lcprevst = this.getprevsolidtoken(ast); 551 if (lcprevst != null) { 552 if (lcprevst.tokencode == TBaseType.rrw_end) { 553 lcprevst.tokencode = TBaseType.rrw_teradata_end_t; 554 } 555 } 556 } 557 558 private void handleReplaceToken(TSourceToken ast) { 559 TSourceToken nextToken = ast.searchToken('(', 1); 560 if (nextToken != null) { 561 ast.tokencode = TBaseType.ident; 562 } 563 } 564 565 private void handleBetweenToken(TSourceToken ast) { 566 TSourceToken nextToken = ast.nextSolidToken(); 567 if (nextToken != null) { 568 if ((nextToken.tokencode == TBaseType.rrw_begin) || (nextToken.tokencode == TBaseType.rrw_end)) { 569 // BETWEEN begin(DODD_EFF_PERI) 570 nextToken.tokencode = TBaseType.ident; 571 } 572 } 573 } 574 575 private void handleDeclareToken(TSourceToken ast) { 576 TSourceToken nextToken = ast.nextSolidToken(); 577 if (nextToken != null) { 578 TSourceToken nextnextToken = nextToken.nextSolidToken(); 579 if (nextnextToken != null) { 580 if ((nextnextToken.toString().equalsIgnoreCase("cursor")) 581 || (nextnextToken.toString().equalsIgnoreCase("insensitive")) 582 || (nextnextToken.toString().equalsIgnoreCase("scroll")) 583 || (nextnextToken.toString().equalsIgnoreCase("no"))) { 584 nextToken.tokencode = TBaseType.rrw_teradata_cursor_name; 585 } else if ((nextnextToken.toString().equalsIgnoreCase("condition"))) { 586 nextToken.tokencode = TBaseType.rrw_teradata_condition_name; 587 } 588 } 589 } 590 } 591 592 private void handleCaseToken(TSourceToken ast) { 593 int lcNest = 1; 594 for (int m = ast.posinlist + 1; m < this.sourcetokenlist.size() - 1; m++) { 595 TSourceToken st = this.sourcetokenlist.get(m); 596 if (st.tokencode == TBaseType.rrw_case) { 597 st.tag = 1; // this is nested case keyword, don't check this token later 598 lcNest++; 599 } 600 if (st.tokencode == TBaseType.rrw_end) { 601 lcNest--; 602 if (lcNest == 0) { 603 TSourceToken caseToken = st.nextSolidToken(); 604 if (caseToken != null) { 605 if (caseToken.tokencode == TBaseType.rrw_case) { 606 ast.tokencode = TBaseType.rrw_teradata_case_stmt; 607 caseToken.tag = 1; // this is case after end, don't check this token later 608 } 609 } 610 // Always break after finding the matching END, whether it's followed by CASE or not 611 // This prevents CASE expressions from incorrectly matching with later "END CASE" constructs 612 break; 613 } 614 } 615 } 616 } 617 618 private void handleGrantToken(TSourceToken ast) { 619 TSourceToken prevSolidToken = ast.prevSolidToken(); 620 if (prevSolidToken != null) { 621 if (prevSolidToken.tokencode == TBaseType.rrw_with) { 622 prevSolidToken.tokencode = TBaseType.rrw_teradata_with_grant; 623 } 624 } 625 } 626 627 private void handleVariableToken(TSourceToken ast) { 628 // USING ( _spVV8 VARCHAR(1024) CHARACTER SET UNICODE ) SELECT INTO :_spVV8 ; 629 // variable after into keyword treat as identifier 630 TSourceToken prevSolidToken = ast.prevSolidToken(); 631 if (prevSolidToken != null) { 632 if (prevSolidToken.tokencode == TBaseType.rrw_into) { 633 ast.tokencode = TBaseType.ident; 634 } 635 } 636 } 637 638 private void handleSequencedToken(TSourceToken ast) { 639 TSourceToken nextSolidToken = ast.nextSolidToken(); 640 if (nextSolidToken != null) { 641 if ((nextSolidToken.tokencode == TBaseType.rrw_teradata_validtime)) { 642 TSourceToken nextToken2 = nextSolidToken.nextSolidToken(); 643 if (nextToken2 != null) { 644 if ((nextToken2.tokencode == TBaseType.rrw_select) 645 || (nextToken2.tokencode == TBaseType.rrw_insert) 646 || (nextToken2.tokencode == TBaseType.rrw_update) 647 || (nextToken2.tokencode == TBaseType.rrw_delete) 648 || (nextToken2.tokencode == TBaseType.rrw_merge)) { 649 // SEQUENCED VALIDTIME select/insert/update/delete/merge 650 ast.tokencode = TBaseType.lexspace; 651 nextSolidToken.tokencode = TBaseType.lexspace; 652 } 653 } 654 } 655 } 656 } 657 658 private EFindSqlStateType handleMultiLoadCmdState(TSourceToken ast, EFindSqlStateType gst, SqlParseResult.Builder builder) { 659 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 660 if ((ast.tokencode == ';') && (ast.isLastTokenOfLine())) { 661 TSourceToken nextToken = ast.nextSolidToken(); 662 TSourceToken nextToken2 = nextToken != null ? nextToken.nextSolidToken() : null; 663 if (nextToken != null && nextToken2 != null && 664 nextToken.tokencode == '.' && 665 nextToken2.toString().equalsIgnoreCase("FIELD") && 666 nextToken.isFirstTokenOfLine()) { 667 // Remain in stMultiLoadCmd state 668 } else { 669 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 670 gst = EFindSqlStateType.stnormal; 671 } 672 } else if (ast.isLastTokenOfLine()) { 673 // .IF ERRORCODE <> 0 THEN 674 // INSERT INTO Sou_EMP_Tab 675 // (1, 'bala'); 676 String cmdstr = this.gcurrentsqlstatement.sourcetokenlist.get(0).toString(); 677 if (this.gcurrentsqlstatement.sourcetokenlist.size() > 1) { 678 cmdstr = cmdstr + this.gcurrentsqlstatement.sourcetokenlist.get(1).toString(); 679 } 680 if ((cmdstr.toLowerCase().startsWith(".if")) || (cmdstr.toLowerCase().startsWith(".set")) || (cmdstr.toLowerCase().startsWith("set"))) { 681 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 682 gst = EFindSqlStateType.stnormal; 683 } 684 } 685 return gst; 686 } 687 688 private EFindSqlStateType handleFastExportCmdState(TSourceToken ast, EFindSqlStateType gst, SqlParseResult.Builder builder) { 689 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 690 if ((ast.tokencode == ';') && (ast.isLastTokenOfLine())) { 691 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 692 gst = EFindSqlStateType.stnormal; 693 } else { 694 boolean findSQL = false; 695 TSourceToken nextst = ast.nextToken(); 696 if (nextst != null) { 697 if (nextst.tokentype == ETokenType.ttreturn) { 698 findSQL = (this.sqlcmds.issql(ast.nextSolidToken(), gst, this.gcurrentsqlstatement) != null); 699 if (findSQL) { 700 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 701 gst = EFindSqlStateType.stnormal; 702 } 703 } 704 } 705 } 706 return gst; 707 } 708 709 private EFindSqlStateType handleFastLoadCmdState(TSourceToken ast, EFindSqlStateType gst, SqlParseResult.Builder builder) { 710 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 711 if ((ast.tokencode == ';') && (ast.isLastTokenOfLine())) { 712 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 713 gst = EFindSqlStateType.stnormal; 714 } else if (ast.tokencode == TBaseType.lexnewline) { 715 TSourceToken nextst = ast.nextSolidToken(); 716 if (nextst != null) { 717 if (nextst.tokencode == TBaseType.BTEQCMD) { 718 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 719 gst = EFindSqlStateType.stFastLoadCmd; 720 } else if (nextst.tokencode == '.') { 721 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 722 gst = EFindSqlStateType.stFastLoadCmd; 723 } else if (this.sqlcmds.issql(nextst, gst, this.gcurrentsqlstatement) != null) { 724 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 725 gst = EFindSqlStateType.stnormal; 726 } 727 } 728 } 729 return gst; 730 } 731 732 private EFindSqlStateType handleBTEQCmdState(TSourceToken ast, SqlParseResult.Builder builder) { 733 EFindSqlStateType gst = EFindSqlStateType.stBTEQCmd; 734 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 735 736 if (ast.tokencode == TBaseType.lexnewline) { 737 if (this.isContinueBTEQCmd) { 738 this.isContinueBTEQCmd = false; 739 } else { 740 if (((TTeradataBTEQCmd)this.gcurrentsqlstatement).getBteqCmdType() == BteqCmdType.LOGON) { 741 boolean findSQL = (this.sqlcmds.issql(ast.nextSolidToken(), gst, this.gcurrentsqlstatement) != null); 742 if (findSQL) { 743 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 744 gst = EFindSqlStateType.stnormal; 745 } 746 } else { 747 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 748 gst = EFindSqlStateType.stnormal; 749 } 750 } 751 } else if ((ast.tokencode == '-') && (ast.isLastTokenOfLine())) { 752 if (!this.inBTEQComment) { 753 this.isContinueBTEQCmd = true; 754 } 755 } else if (ast.tokencode == TBaseType.lexspace) { 756 // Do nothing 757 } else if (ast.tokencode == ';') { 758 this.onRawStatementComplete(this.parserContext, this.gcurrentsqlstatement, this.fparser, null, this.sqlstatements, false, builder); 759 boolean findNewCmdInSameLine = this.checkForNewBTEQCmdInSameLine(ast); 760 if (findNewCmdInSameLine) { 761 gst = EFindSqlStateType.stBTEQCmd; 762 } else { 763 gst = EFindSqlStateType.stnormal; 764 } 765 } else if (ast.tokencode == '*') { 766 this.isContinueBTEQCmd = false; 767 } else { // solid token 768 this.isContinueBTEQCmd = false; 769 } 770 return gst; 771 } 772 773 private boolean checkForNewBTEQCmdInSameLine(TSourceToken ast) { 774 boolean findNewCmdInSameLine = false; 775 if (!ast.isLastTokenOfLine()) { 776 // check if next cmd like below: 777 // .SET SIDETITLES ON; .SET FOLDLINE ON ALL 778 TSourceToken nextst = ast.nextSolidToken(); 779 if ((nextst != null) && (nextst.tokencode == '.')) { 780 TSourceToken nextst2 = nextst.nextSolidToken(); 781 TSourceToken searchToken = null; 782 if (nextst2 != null) { 783 if (nextst2.tokencode == TBaseType.rrw_set) { 784 TSourceToken nextst3 = nextst2.nextSolidToken(); 785 if (nextst3 != null) { 786 searchToken = nextst3; 787 } 788 } else { 789 searchToken = nextst2; 790 } 791 792 BteqCmdType bteqCmdType = BteqCmdType.searchBteqCmd(searchToken); 793 if (bteqCmdType != null) { 794 this.gcurrentsqlstatement = new TTeradataBTEQCmd(this.vendor); 795 ((TTeradataBTEQCmd)this.gcurrentsqlstatement).setBteqCmdType(bteqCmdType); 796 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 797 findNewCmdInSameLine = true; 798 } 799 } 800 } 801 } 802 return findNewCmdInSameLine; 803 } 804 805 private EFindSqlStateType handleNormalState(TSourceToken ast, EFindSqlStateType gst, TSourceToken lcprevsolidtoken, SqlParseResult.Builder builder) { 806 if ((ast.tokencode == TBaseType.cmtdoublehyphen) 807 || (ast.tokencode == TBaseType.cmtslashstar) 808 || (ast.tokencode == TBaseType.lexspace) 809 || (ast.tokencode == TBaseType.lexnewline) 810 || (ast.tokentype == ETokenType.ttsemicolon)) { 811 if (TBaseType.assigned(this.gcurrentsqlstatement)) { 812 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 813 } 814 815 if ((lcprevsolidtoken != null) && (ast.tokentype == ETokenType.ttsemicolon)) { 816 if (lcprevsolidtoken.tokentype == ETokenType.ttsemicolon) { 817 // ;;;; continuous semicolon, treat it as comment 818 ast.tokentype = ETokenType.ttsimplecomment; 819 ast.tokencode = TBaseType.cmtdoublehyphen; 820 } 821 } 822 823 return gst; 824 } 825 if ((gst = this.checkForBTEQOrUtilityCommand(ast, gst)) != EFindSqlStateType.stnormal) { 826 return gst; 827 } 828 829 // find a tokentext to start sql or stored procedure mode 830 this.gcurrentsqlstatement = this.sqlcmds.issql(ast, gst, this.gcurrentsqlstatement); 831 832 if (TBaseType.assigned(this.gcurrentsqlstatement)) { 833 ESqlStatementType[] ses = {ESqlStatementType.sstcreateprocedure, ESqlStatementType.sstteradatacreatefunction, ESqlStatementType.sstcreatetrigger}; 834 if (this.includesqlstatementtype(this.gcurrentsqlstatement.sqlstatementtype, ses)) { 835 gst = EFindSqlStateType.ststoredprocedure; 836 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 837 if ((this.gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreateprocedure) 838 || (this.gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstteradatacreatefunction) 839 || (this.gcurrentsqlstatement.sqlstatementtype == ESqlStatementType.sstcreatetrigger)) { 840 this.curdelimiterchar = ';'; 841 } 842 } else { 843 gst = EFindSqlStateType.stsql; 844 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 845 } 846 } 847 848 if ((!TBaseType.assigned(this.gcurrentsqlstatement)) && (ast.isFirstTokenOfLine())) { 849 gst = this.flexer.cmdType(ast); 850 if ((gst == EFindSqlStateType.stMultiLoadCmd) || (gst == EFindSqlStateType.stFastLoadCmd) || (gst == EFindSqlStateType.stFastExportCmd)) { 851 this.gcurrentsqlstatement = new TTeradataBTEQCmd(this.vendor); 852 ((TTeradataBTEQCmd)this.gcurrentsqlstatement).setFindSqlStateType(gst); 853 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 854 return gst; 855 } 856 gst = EFindSqlStateType.stnormal; 857 } 858 859 if (!TBaseType.assigned(this.gcurrentsqlstatement)) { // error tokentext found 860 this.syntaxErrors.add(new TSyntaxError(ast.getAstext(), ast.lineNo, (ast.columnNo < 0 ? 0 : ast.columnNo), 861 "Error when tokenlize", EErrorType.spwarning, TBaseType.MSG_WARNING_ERROR_WHEN_TOKENIZE, null, ast.posinlist)); 862 863 ast.tokentype = ETokenType.tttokenlizererrortoken; 864 gst = EFindSqlStateType.sterror; 865 866 this.gcurrentsqlstatement = new TUnknownSqlStatement(this.vendor); 867 this.gcurrentsqlstatement.sqlstatementtype = ESqlStatementType.sstinvalid; 868 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 869 } 870 return gst; 871 } 872 873 private EFindSqlStateType checkForBTEQOrUtilityCommand(TSourceToken ast, EFindSqlStateType gst) { 874 // Check for .bteq commands: either "." at start of line, or "." after ";" at start of line 875 boolean isDotAtStartOfLine = (ast.tokencode == '.') && (ast.isFirstTokenOfLine()); 876 boolean isDotAfterSemicolonAtStartOfLine = false; 877 if ((ast.tokencode == '.') && !isDotAtStartOfLine) { 878 TSourceToken prevToken = ast.prevSolidToken(); 879 if ((prevToken != null) && (prevToken.tokencode == ';') && (prevToken.isFirstTokenOfLine())) { 880 isDotAfterSemicolonAtStartOfLine = true; 881 } 882 } 883 884 if (isDotAtStartOfLine || isDotAfterSemicolonAtStartOfLine) { 885 // .bteq commands 886 TSourceToken nextst = ast.nextSolidToken(); 887 if (nextst != null) { 888 gst = this.flexer.cmdType(nextst); 889 boolean foundCmd = false; 890 switch (gst) { 891 case stMultiLoadCmd: 892 this.gcurrentsqlstatement = new TTeradataMultiLoadCmd(this.vendor); 893 gst = EFindSqlStateType.stMultiLoadCmd; 894 ((TTeradataMultiLoadCmd)this.gcurrentsqlstatement).setCmdType(TTeradataHelper.searchMultiLoadTypeByName(nextst.getAstext())); 895 foundCmd = true; 896 break; 897 case stFastExportCmd: 898 this.gcurrentsqlstatement = new TTeradataFastExportCmd(this.vendor); 899 gst = EFindSqlStateType.stFastExportCmd; 900 foundCmd = true; 901 break; 902 case stFastLoadCmd: 903 this.gcurrentsqlstatement = new TTeradataFastLoadCmd(this.vendor); 904 gst = EFindSqlStateType.stFastLoadCmd; 905 foundCmd = true; 906 break; 907 case stBTEQCmd: 908 this.gcurrentsqlstatement = new TTeradataBTEQCmd(this.vendor); 909 ((TTeradataBTEQCmd)this.gcurrentsqlstatement).setBteqCmdType(BteqCmdType.searchBteqCmd(nextst)); 910 gst = EFindSqlStateType.stBTEQCmd; 911 foundCmd = true; 912 break; 913 default: 914 break; 915 } 916 if (foundCmd) { 917 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 918 return gst; 919 } 920 } 921 } else if ((ast.tokencode == '*') && (ast.isFirstTokenOfLine())) { 922 // BTEQ comment: * comment 923 gst = EFindSqlStateType.stBTEQCmd; 924 this.inBTEQComment = true; // Mark that we're in a BTEQ comment 925 this.gcurrentsqlstatement = new TTeradataBTEQCmd(this.vendor); 926 ((TTeradataBTEQCmd)this.gcurrentsqlstatement).setBteqCmdType(BteqCmdType.COMMENT); 927 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 928 return gst; 929 } else if ((ast.tokencode == '=') && (ast.isFirstTokenOfLine())) { 930 // BTEQ command starting with = 931 TSourceToken st1 = ast.prevSolidToken(); 932 if ((st1 != null) && (st1.tokencode == ';')) { 933 gst = EFindSqlStateType.stBTEQCmd; 934 this.gcurrentsqlstatement = new TTeradataBTEQCmd(this.vendor); 935 ((TTeradataBTEQCmd)this.gcurrentsqlstatement).setFindSqlStateType(gst); 936 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 937 return gst; 938 } 939 } else if ((ast.isFirstTokenOfLine()) && (BteqCmdType.searchBteqCmd(ast) != null)) { 940 TSourceToken st1 = ast.prevSolidToken(); 941 if ((st1 != null) && (st1.tokencode == ';')) { 942 gst = EFindSqlStateType.stBTEQCmd; 943 this.gcurrentsqlstatement = new TTeradataBTEQCmd(this.vendor); 944 ((TTeradataBTEQCmd)this.gcurrentsqlstatement).setFindSqlStateType(gst); 945 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 946 return gst; 947 } 948 } else if ((ast.tokencode == '&') && (ast.isFirstTokenOfLine())) { 949 // Teradata macro/substitution variable: &VARIABLE_NAME at start of line 950 // Treat it as a BTEQ-like command that ends at end of line 951 TSourceToken nextst = ast.nextSolidToken(); 952 if (nextst != null && (nextst.tokencode == TBaseType.ident || nextst.tokentype == ETokenType.ttidentifier)) { 953 gst = EFindSqlStateType.stBTEQCmd; 954 this.gcurrentsqlstatement = new TTeradataBTEQCmd(this.vendor); 955 ((TTeradataBTEQCmd)this.gcurrentsqlstatement).setFindSqlStateType(gst); 956 this.gcurrentsqlstatement.sourcetokenlist.add(ast); 957 return gst; 958 } 959 } 960 return EFindSqlStateType.stnormal; 961 } 962 963 964 private boolean includesqlstatementtype(ESqlStatementType type, ESqlStatementType[] types) { 965 for (ESqlStatementType t : types) { 966 if (type != t) continue; 967 return true; 968 } 969 return false; 970 } 971 972 @Override 973 protected TStatementList performParsing(ParserContext context, TCustomParser parser, TCustomParser secondaryParser, TSourceTokenList tokens, TStatementList rawStatements) { 974 this.fparser = (TParserTeradata)parser; 975 this.sourcetokenlist = tokens; 976 this.parserContext = context; 977 this.sqlstatements = rawStatements; 978 if (this.sqlstatements == null) { 979 this.sqlstatements = new TStatementList(); 980 return this.sqlstatements; 981 } 982 if (this.sqlcmds == null) { 983 this.sqlcmds = SqlCmdsFactory.get(this.vendor); 984 } 985 this.fparser.sqlcmds = this.sqlcmds; 986 987 // Initialize global context for semantic analysis 988 // CRITICAL: When delegated from TGSqlParser, use TGSqlParser's frameStack 989 // so that variables set in SET statements can be found by EXECUTE statements 990 if (context != null && context.getGsqlparser() != null) { 991 gudusoft.gsqlparser.TGSqlParser gsqlparser = (gudusoft.gsqlparser.TGSqlParser) context.getGsqlparser(); 992 this.frameStack = gsqlparser.getFrameStack(); 993 994 // CRITICAL: Set gsqlparser on the NodeFactory - matches TGSqlParser behavior 995 // This is needed for proper AST node creation during parsing 996 this.fparser.getNf().setGsqlParser(gsqlparser); 997 998 // Create global context if needed 999 this.globalContext = new gudusoft.gsqlparser.compiler.TContext(); 1000 this.sqlEnv = new gudusoft.gsqlparser.sqlenv.TSQLEnv(this.vendor) { 1001 @Override 1002 public void initSQLEnv() { 1003 } 1004 }; 1005 this.globalContext.setSqlEnv(this.sqlEnv, this.sqlstatements); 1006 } else { 1007 this.initializeGlobalContext(); 1008 } 1009 1010 for (int i = 0; i < this.sqlstatements.size(); ++i) { 1011 TCustomSqlStatement stmt = this.sqlstatements.getRawSql(i); 1012 try { 1013 stmt.setFrameStack(this.frameStack); 1014 int parseResult = stmt.parsestatement(null, false, context.isOnlyNeedRawParseTree()); 1015 boolean doRecover = TBaseType.ENABLE_ERROR_RECOVER_IN_CREATE_TABLE; 1016 if (doRecover && (parseResult != 0 || stmt.getErrorCount() > 0)) { 1017 this.handleCreateTableErrorRecovery(stmt); 1018 } 1019 if (parseResult == 0 && stmt.getErrorCount() <= 0) continue; 1020 this.copyErrorsFromStatement(stmt); 1021 continue; 1022 } 1023 catch (Exception ex) { 1024 ex.printStackTrace(); 1025 this.handleStatementParsingException(stmt, i, ex); 1026 } 1027 } 1028 if (this.globalFrame != null) { 1029 this.globalFrame.popMeFromStack(this.frameStack); 1030 } 1031 return this.sqlstatements; 1032 } 1033 1034 private void handleCreateTableErrorRecovery(TCustomSqlStatement stmt) { 1035 if (!(stmt.sqlstatementtype != ESqlStatementType.sstcreatetable && stmt.sqlstatementtype != ESqlStatementType.sstcreateindex || TBaseType.c_createTableStrictParsing)) { 1036 int nested = 0; 1037 boolean isIgnore = false; 1038 boolean isFoundIgnoreToken = false; 1039 TSourceToken firstIgnoreToken = null; 1040 for (int k = 0; k < stmt.sourcetokenlist.size(); ++k) { 1041 TSourceToken st = stmt.sourcetokenlist.get(k); 1042 if (isIgnore) { 1043 if (st.issolidtoken() && st.tokencode != 59) { 1044 isFoundIgnoreToken = true; 1045 if (firstIgnoreToken == null) { 1046 firstIgnoreToken = st; 1047 } 1048 } 1049 if (st.tokencode == 59) continue; 1050 st.tokencode = 273; 1051 continue; 1052 } 1053 if (st.tokencode == 41 && --nested == 0) { 1054 isIgnore = true; 1055 } 1056 if (st.tokencode != 40) continue; 1057 ++nested; 1058 } 1059 if (isFoundIgnoreToken) { 1060 stmt.parsestatement(null, false, this.parserContext.isOnlyNeedRawParseTree()); 1061 } 1062 } 1063 } 1064 1065 @Override 1066 protected void performSemanticAnalysis(ParserContext context, TStatementList statements) { 1067 if (!TBaseType.isEnableResolver()) { 1068 return; 1069 } 1070 if (!this.getSyntaxErrors().isEmpty()) { 1071 return; 1072 } 1073 TSQLResolver resolver = new TSQLResolver(this.globalContext, statements); 1074 resolver.resolve(); 1075 } 1076 1077 @Override 1078 protected void performInterpreter(ParserContext context, TStatementList statements) { 1079 } 1080 1081 @Override 1082 public String toString() { 1083 return "TeradataSqlParser{vendor=" + (Object)((Object)this.vendor) + "}"; 1084 } 1085}