001package gudusoft.gsqlparser; 002 003 004import java.io.BufferedReader; 005import java.io.IOException; 006import java.util.ArrayList; 007import java.util.HashMap; 008import java.util.Locale; 009 010/** 011 * Base lexer of all databases. 012 */ 013public class TCustomLexer { 014 015 // 在 lexer level 创建 token table, 按照 token code存储所有 token 的一些关键信息,主要用于处理一个关键字token被用作column,table name的情况 016 public static int MAX_TOKEN_SIZE = 2048; // 所有可能的token的数量 017 public static int MAX_TOKEN_COLUMN_SIZE = 10; 018 019 // 定义一个具有 MAX_TOKEN_SIZE 个元素的常量数组,每个元素有 MAX_TOKEN_COLUMN_SIZE 列, 列的类型为整数 020 // column 0: 代表该token出现的次数 021 // column 1: 代表该token第一次出现的 x position 022 // column 2: 代表该token第一次出现的 y position 023 // column 3: 代表该token最后一次出现的 x position 024 // column 4: 代表该token最后一次出现的 y position 025 // column 5: 代表该token第一次出现的 position in the token list 026 // column 6: 代表该token最后一次出现的 position in the token list 027 028 public static int COLUMN0_COUNT = 0; 029 public static int COLUMN1_FIRST_X = 1; 030 public static int COLUMN2_FIRST_Y = 2; 031 public static int COLUMN3_LAST_X = 3; 032 public static int COLUMN4_LAST_Y = 4; 033 public static int COLUMN5_FIRST_POS = 5; 034 public static int COLUMN6_LAST_POS = 6; 035 036 public long[][] TOKEN_TABLE = new long[MAX_TOKEN_SIZE][MAX_TOKEN_COLUMN_SIZE]; 037 038 // define a function to reset all values in TOKEN_TABLE to 0 039 public void resetTokenTable() { 040 for (int i = 0; i < MAX_TOKEN_SIZE; i++) { 041 for (int j = 0; j < MAX_TOKEN_COLUMN_SIZE; j++) { 042 TOKEN_TABLE[i][j] = 0L; 043 } 044 } 045 } 046 047 // define a function to set value when token is found, input is token id, a token with TSourceToken type 048 public void setTokenTableValue( TSourceToken token) { 049 if (token == null) return; 050 int tokenId = token.tokencode; 051 052 if (tokenId < 0 || tokenId >= MAX_TOKEN_SIZE) { 053 return; 054 } 055 if (TOKEN_TABLE[tokenId][COLUMN0_COUNT] == 0) { 056 TOKEN_TABLE[tokenId][COLUMN0_COUNT] = 1; 057 TOKEN_TABLE[tokenId][COLUMN1_FIRST_X] = token.lineNo; 058 TOKEN_TABLE[tokenId][COLUMN2_FIRST_Y] = token.columnNo; 059 TOKEN_TABLE[tokenId][COLUMN3_LAST_X] = token.lineNo; 060 TOKEN_TABLE[tokenId][COLUMN4_LAST_Y] = token.columnNo; 061 TOKEN_TABLE[tokenId][COLUMN5_FIRST_POS] = token.posinlist; 062 TOKEN_TABLE[tokenId][COLUMN6_LAST_POS] = token.posinlist; 063 } else { 064 TOKEN_TABLE[tokenId][COLUMN0_COUNT] += 1; 065 TOKEN_TABLE[tokenId][COLUMN3_LAST_X] = token.lineNo; 066 TOKEN_TABLE[tokenId][COLUMN4_LAST_Y] = token.columnNo; 067 TOKEN_TABLE[tokenId][COLUMN6_LAST_POS] = token.posinlist; 068 } 069 } 070 071 public BufferedReader yyinput; 072 long yylineno,yycolno,offset,yylineno_p,yycolno_p,offset_p; 073 int bufptr,yystate,yysstate,yylstate,yytextlen,yyretval, yytextbufsize, 074 yymatches,yysleng; 075 char[] yyline; 076 String yylvalstr; 077 public String dolqstart = "";//postgresql, start part of Dollar-quoted String Constants 078 char yylastchar,yyactchar,yytablechar; 079 boolean yydone,yyreject; 080 char[] yytextbuf; 081 char[] buf; 082 int bufsize; 083 boolean endOfInput; 084 085 //StringBuffer literalbuf; 086 StringBuilder literalbuf; 087 int literallen,literalalloc,xcdepth,nchars,slashstar,dashdash; 088 boolean isqmarktoident; 089 boolean insqlpluscmd; 090 char dummych1,dummych2,dummych3; 091 boolean utf8NoBreakSpaceReady = false; 092 093 int nestedLessThan = 0; 094 095 boolean isReadyForFunctionBody = false, isInFunctionBody = false; 096 int functionBodyDelimiterIndex = -1; 097 ArrayList<String> functionBodyDelimiter = new ArrayList<>(); 098 099 public static int keyword_type_reserved = 0x0001; 100 public static int keyword_type_keyword = 0x0002; 101 public static int keyword_type_identifier = 0x0004; 102 public static int keyword_type_column = 0x0008; 103 104 public char delimiterchar; 105 public String defaultDelimiterStr; 106 public String tmpDelimiter; 107 108 final static int intial_bufsize = 16384; 109 final static char lf = (char)10; 110 final static int max_chars = 65536*10*2; 111 final static int max_rules = 256*2*10; 112 int max_matches = 1024*20*10*2; 113 114 115 // 下面这些常量按照在 l 文件中出现的次序,必须以 +2 的方式递加. 为什么以 +2 的方式递加 原因忘了,尚未搞清楚。 116 final static int init = 2; 117 final static int xc = 4; 118 final static int xd = 6; 119 final static int xq = 8; 120 final static int xqq = 10; //oracle 121 final static int xdolq = 10;//postgresql 122 final static int xdbracket = 10; 123 final static int xdbrace = 12; 124 final static int xbacktick = 12; 125 126 final static int xbracketrs = 12; //redshift 127 final static int xqtriple = 14;//bigquery 128 final static int xdtriple = 16;//bigquery 129 130 131 132 //https://docs.microsoft.com/en-us/sql/sql-server/maximum-capacity-specifications-for-sql-server 133 final static int namedatalen = 8060;//255; 134 135 final static int cmtslashstar = 257; 136 final static int cmtdoublehyphen = 258; 137 final static int lexspace = 259; 138 final static int lexnewline = 260; 139 final static int fconst = 261; 140 final static int sconst = 262; 141 final static int iconst = 263; 142 final static int ident = 264; 143 final static int op = 265; 144 final static int cmpop = 266; 145 final static int bind_v = 267; 146 final static int assign_sign = 268; 147 final static int double_dot = 269; 148 final static int label_begin = 270; 149 final static int label_end = 271; 150 final static int substitution_v = 272; 151 final static int filepath_sign = TBaseType.filepath_sign; 152 final static int sqlpluscmd = 273; 153 final static int atversion = TBaseType.atversion; //databricks 154 final static int error = 274; 155 final static int variable = 275; 156 final static int mslabel = 276; 157 public final static int bconst = TBaseType.bconst; //postgresql 158 final static int leftjoin_op = 277; 159 final static int odbc_esc_prefix = 277; 160 final static int rightjoin_op = 278; 161 final static int odbc_esc_terminator = 278; 162 final static int db2label = 279; 163 public final static int xconst = TBaseType.xconst; //postgresql 164 final static int ref_arrow = 280; 165 final static int rw_scriptoptions = 281; 166 public final static int UNICODE_ENCODE_ID = 281; 167 final static int mysqllabel = 282; 168 final static int NAMED_PARAMETER_SIGN = 282; //oracle,db2,snowflake CALL update_order (5000, NEW_STATUS => 'Shipped') 169 final static int QUOTED_IDENT = 282;//used in mdx 170 final static int BTEQCMD = 282; 171 final static int concatenationop = 283; 172 final static int rw_not_deferrable = 284; 173 final static int rw_for1 = 285; 174 final static int stmt_delimiter = 286; 175 final static int AMP_QUOTED_ID = 285; //used in mdx 176 final static int AMP_UNQUOTED_ID = 286; //used in mdx 177 final static int m_clause = 287; 178 final static int MySQL_CHARSET_NAME = 287; 179 final static int typecast = TBaseType.typecast;//postgresql 180 final static int k_clause = 288; 181 final static int slash_dot = 288; 182 final static int outer_join = 289; 183 184 final static int not_equal = 290; 185 186 final static int param = TBaseType.param; 187 final static int mysql_null = TBaseType.rrw_mysql_null; 188 189 final static int rw_locktable = 296; 190 final static int rw_foreign2 = 297; 191 final static int rw_constraint2 = 298; 192 final static int rw_primary2 = 299; 193 final static int rw_unique2 = 300; 194 final static int NEXT_PARAM = TBaseType.NEXT_PARAM; 195 final static int POSITIONAL_PARAM = TBaseType.POSITIONAL_PARAM; 196 final static int NAMED_PARAM = TBaseType.NAMED_PARAM; 197 198 final static int castoperator = TBaseType.castoperator; 199 final static int twocolons = TBaseType.twocolons; 200 final static int compoundAssignmentOperator = TBaseType.compoundAssignmentOperator; 201 final static int postgresql_function_delimiter = TBaseType.rrw_postgresql_function_delimiter; 202 final static int greenplum_function_delimiter = TBaseType.rrw_greenplum_function_delimiter; 203 204 final static int redshift_function_delimiter = TBaseType.rrw_redshift_function_delimiter; 205 final static int snowflake_function_delimiter = TBaseType.rrw_snowflake_function_delimiter; 206 207 208 209 int[] yypos;// = new int[max_rules + 1]; // 1 based in delphi, Position 0 was not used here 210 int[] yystack;// = new int[max_matches + 1]; // 1 based in delphi, Position 0 was not used here 211 // ArrayList yystack; 212 213 //String keywordvaluefile,keywordfile,yyk_file,yym_file,yykl_file; 214 //String yykh_file,yyml_file,yymh_file,yytl_file,yyth_file,yytint_file,yyt_file; 215 216 EDbVendor dbvendor; 217 TSourceToken prevToken = null; 218 219 public void setSqlCharset(String sqlCharset) { 220 this.sqlCharset = sqlCharset; 221 } 222 223 public String getSqlCharset() { 224 return sqlCharset; 225 } 226 227 private String sqlCharset = null; 228 229 public TCustomLexer(){ 230 //this.yyinput = pbuf; 231 yytextbufsize = intial_bufsize - 1; 232 yytextbuf = new char[intial_bufsize]; 233 checkyytextbuf(yytextbufsize); 234 235 bufsize = intial_bufsize - 1; 236 buf = new char[intial_bufsize]; 237 checkbuf(bufsize); 238 239 //literalbuf = new StringBuffer(); 240 literalbuf = new StringBuilder(); 241 //keywordList = new TreeMap(); 242 delimiterchar = ';'; 243 tmpDelimiter = ""; 244 245 xcdepth = 0; 246 nchars = 0; 247 isqmarktoident = true; 248 249 yylvalstr = ""; 250 yysstate = 0; 251 yylstate = 0; 252 yymatches = 0; 253 yysleng = 0; 254 bufptr = 0; 255 yylineno = 0; 256 yycolno = 0; 257 offset = -1; 258 yylineno_p = 1; 259 yycolno_p = 1; 260 offset_p = 0; 261 262 yypos = new int[max_rules + 1]; 263 max_matches = TBaseType.LEXER_INIT_MAX_MATCHES; 264 yystack = new int[max_matches + 1]; 265 266 prevToken = null; 267 } 268 269 /* 270 * this function is not used. 271 private void getkeywordvaluefromfile(){ 272 int i; 273 keywordValueList.clear(); 274 for(i=0; i<keywordlist.length; i++){ 275 // System.out.println(keywordlist[i]); 276 String[] ss = keywordlist[i].split("[=]"); 277 keywordValueList.put(ss[0].toUpperCase(),ss[1]); 278 } 279 } 280 */ 281 282public int iskeyword(String str){ 283 return -1; 284} 285 286public boolean isAtBeginOfLine(){ 287 return (yyretval == lexnewline || yyretval == 0); 288} 289 290//public boolean canBeColumnName(int tokencode){ 291// return false; 292//} 293 294 295public String getStringByCode(int tokenCode){ 296 return null; 297} 298 299 public int getkeywordvalue(String keyword){ 300 return 0; 301 } 302 303 304 /** 305 * @deprecated , please use keywordChecker.isKeyword() instead. 306 * 307 * because there are so many non-reserved keywords in some databases, it's not suitable to put those 308 * non-reserved keywords in lexer and parser. 309 * 310 * @param keyword 311 * @param keywordValueList 312 * @param keywordTypeList 313 * @return 314 */ 315 public static EKeywordType getKeywordType(String keyword, HashMap<String, Integer> keywordValueList,HashMap<Integer, Integer> keywordTypeList){ 316 EKeywordType ret = EKeywordType.NOT_A_KEYWORD; 317 Integer s = keywordValueList.get(keyword.toUpperCase(Locale.ENGLISH)); 318 if( s == null) return ret; 319 320 Integer i = keywordTypeList.get(s); 321 if (i == 1) return EKeywordType.RESERVED_WORD; 322 else if (i == 2) return EKeywordType.NON_RESERVED_KEYWORD; 323 else return ret; 324 } 325 326 /** 327 * 如果是ascii 字符,直接返回,如果是unicode 字符,需要进行转换。否则 String.charAt() 返回的unicode字符不是我们想要的字符, 328 * 例如中文的括号,我们实际需要的ascii的括号 329 * 330 * @param pYylvalstr 331 * @param index 332 * @return 333 */ 334 char lexer_charAt(String pYylvalstr,int index){ 335 char ret = pYylvalstr.charAt(index); 336 if (ret > 255){ 337 // this is a unicode code 338 if ((ret == 0xFF08)){ 339 // https://www.utf8-chartable.de/unicode-utf8-table.pl?start=65280&number=128 340 // Unicode code point for FULLWIDTH LEFT PARENTHESIS (, 0xFF08 341 //System.out.println(c); 342 ret = '('; 343 } 344 if ( (ret == 0xFF09)){ 345 // https://www.utf8-chartable.de/unicode-utf8-table.pl?start=65280&number=128 346 // Unicode code point for FULLWIDTH RIGHT PARENTHESIS ), 0xFF09 347 // System.out.println(c); 348 ret = ')'; 349 } 350 } 351 return ret; 352 } 353 void totablechar(){ 354 //System.out.println("char:"+yyactchar+" ,hex:"+String.format("%04x", (int) yyactchar)); 355 //System.out.println(String.format("0x%08X", (int)yyactchar)+", "+(char)yyactchar); 356 357 if (((int) yyactchar == 0) && !endOfInput) { 358 yytablechar = (char)255; 359 return; 360 } 361 362 if ((int)(yyactchar) < 228){ // 228 is ä in unicode 363 yytablechar = yyactchar; 364 if ((((int)(yyactchar) == 160)&&(utf8NoBreakSpaceReady))||(yyactchar == 0xA0)){ 365 yytablechar = (char)32; 366 } 367 utf8NoBreakSpaceReady = false; 368// if (yyactchar == 0x27){ 369// insideSingleQuoteStr = !insideSingleQuoteStr; 370// } 371 }else{ 372 yytablechar = (char)'a';//(char)255; 373 374 if ((int)(yyactchar) == 914) { // c2 a0, utf-8 NO-BREAK SPACE 375 utf8NoBreakSpaceReady = true; 376 yytablechar = (char) 32; 377 }else if ((yyactchar == 0x2018)||(yyactchar == 0x2019)){ 378 if (stringLiteralStartWithUnicodeSingleQuote){ 379 // WHERE Name LIKE ‘Acme%’ 380 // 如上,如果string literal 以unicode quote 开始,则不管当前是否在string literal中,新碰到的unicode quote都看成是string literal的结尾符, 381 yytablechar = 0x27; // treat Unicode Character 'LEFT SINGLE QUOTATION MARK' as the ascii char ', but don't change it 382 }else { 383 if (insideSingleQuoteStr){ 384 // don't change the unicode quote char 385 }else { 386 yytablechar = 0x27; // treat Unicode Character 'LEFT SINGLE QUOTATION MARK' as the ascii char ', but don't change it 387 } 388 } 389 390 }else if ((yyactchar == 0x200B)||(yyactchar == 0x3000)){ 391 // Unicode code point 0x200B: treat Unicode Character ZERO WIDTH SPACE as the ascii char space, but don't change it 392 // Unicode code point 0x3000: treat Unicode Character IDEOGRAPHIC SPACE (UTF-8: e3 80 80) as the ascii char space, but don't change it 393 yytablechar = 0x20; 394 }else if (yyactchar == 0xFF08){ 395 yytablechar = '('; // treat Unicode code point for FULLWIDTH LEFT PARENTHESIS as the ascii char (, but don't change it 396 }else if (yyactchar == 0xFF09){ 397 yytablechar = ')'; // treat Unicode code point for FULLWIDTH RIGHT PARENTHESIS as the ascii char ), but don't change it 398 }else if (yyactchar == 0xFF0C){ 399 yytablechar = ','; // treat Unicode code point for FULLWIDTH COMMA as the ascii char comma, but don't change it 400 }else { 401 utf8NoBreakSpaceReady = false; 402 } 403 } 404 } 405 406 String getyytext(){ 407 return new String(yytextbuf,0,yytextlen); 408 } 409 410 void checkyytextbuf(int size){ 411 while ( size >= yytextbufsize){ 412 yytextbufsize = yytextbufsize * 2 > intial_bufsize ? yytextbufsize * 2: intial_bufsize; 413 char[] tmp = new char[yytextbufsize]; 414 System.arraycopy(yytextbuf,0,tmp,0, yytextbuf.length); 415 yytextbuf = tmp; 416 } 417 } 418 419 void checkbuf(int size){ 420 // System.out.println("while begin2"+" size:"+size+" bufsize:"+bufsize); 421 while ( size >= bufsize){ 422 bufsize = bufsize * 2 > intial_bufsize ? bufsize * 2: intial_bufsize; 423 char[] tmp = new char[bufsize]; 424 System.arraycopy(buf,0,tmp,0, buf.length); 425 buf = tmp; 426 } 427 // System.out.println("while end2"); 428 } 429 430 boolean eof(BufferedReader pbuf){ 431 try{ 432 return !pbuf.ready(); 433 }catch(IOException e){ 434 return true; 435 } 436 } 437 438 void yynew(){ 439 if (yylastchar != (char)0){ 440 if(yylastchar == lf){ 441 yylstate = 1; 442 }else{ 443 yylstate = 0; 444 } 445 } 446 447 yystate = yysstate + yylstate; 448 checkyytextbuf(0); 449 yytextlen = 0; 450 yymatches = 0; 451 yydone = false; 452 } 453 454 void yyscan(){ 455 yyactchar = get_char(); 456 checkyytextbuf(yytextlen + 1); 457 yytextlen++; 458 yytextbuf[yytextlen - 1] = yyactchar; 459 } 460 461 void yymark(int n){ 462 if (n > max_rules ){ 463 System.out.println("n > max_rules "); 464 } 465 yypos[n] = yytextlen; 466 } 467 468 void yymatch(int n){ 469 yymatches++; 470 if(yymatches > max_matches){ 471 472 int new_yystack[] = new int[max_matches*2+1]; 473 System.arraycopy(yystack, 0, new_yystack, 0, max_matches); 474 yystack = new_yystack; 475 max_matches = max_matches * 2; 476 477 // this is valid in JDK 1.6, proguard will report warning and stop 478 // yystack = Arrays.copyOf(yystack,max_matches+1); 479 480 } 481 yystack [yymatches] = n; 482 } 483 484 int yyfind(){ 485 //return -1 mean not found 486 int ret = -1; 487 488 yyreject = false; 489 490 while (( yymatches > 0 ) && ( yypos[yystack[yymatches]] == 0 )) { 491 yymatches-- ; 492 } 493 494 495 if (yymatches > 0){ 496 yysleng = yytextlen; 497 ret = yystack[yymatches]; 498 yyless( yypos[ret] ); 499 yypos[ret] = 0; 500 if (yytextlen >0){ 501 yylastchar = yytextbuf [yytextlen-1]; 502 }else{ 503 yylastchar = (char)0; 504 } 505 }else{ 506 yyless( 0 ); 507 yylastchar = (char)0; 508 } 509 510 return ret; 511 } 512 513 boolean yydefault(){ 514 boolean ret; 515 516 yyreject = false; 517 yyactchar = get_char(); 518 if (yyactchar != (char)0){ 519 //put_char( yyactchar ); 520 ret = true; 521 }else{ 522 yylstate = 1; 523 ret = false; 524 } 525 yylastchar = yyactchar; 526 return ret; 527 } 528 void yyless(int n){ 529 for(int i= yytextlen; i> n; i--){ 530 unget_char(yytextbuf[i - 1]); 531 } 532 checkyytextbuf(n); 533 yytextlen = n; 534 } 535 void returni(int n){ 536 yyretval = n; 537 yydone = true; 538 } 539 void returnc(char c){ 540 yyretval = (int)c; 541 yydone = true; 542 } 543 void yyclear(){ 544 bufptr = 0; 545 yysstate = 0; 546 yylstate = 1; 547 yylastchar = (char)0; 548 yytextlen = 0; 549 yylineno = 0; 550 yycolno = 0; 551 offset = -1; 552 // yystext := ''; 553 554 yylineno_p = 1; 555 yycolno_p = 1; 556 offset_p = 0; 557 558 } 559 560 561 boolean yywrap(){ 562 return true; 563 } 564 int getyysstate(){ 565 return yysstate; 566 } 567 void start(int pstate){ 568 yysstate = pstate; 569 if (pstate == xq){ 570 insideSingleQuoteStr = true; 571 if ((yylvalstr.charAt(0) == 0x2018)||(yylvalstr.charAt(0) == 0x2019)){ 572 stringLiteralStartWithUnicodeSingleQuote = true; 573 }else{ 574 stringLiteralStartWithUnicodeSingleQuote = false; 575 } 576 }else{ 577 insideSingleQuoteStr = false; 578 } 579 } 580 581 582 void unget_char(char pchar){ 583 if(bufptr == max_chars) 584 { 585 System.out.println("input buffer overflow"); 586 } 587 // if (bufptr > 0) { 588 bufptr++; 589 yycolno--; 590 offset--; 591 checkbuf(bufptr+1); 592 buf[bufptr] = pchar; 593 // } 594 595 } 596 597 public void reset(){ 598 insideSingleQuoteStr = false; 599 nestedLessThan = 0; 600 } 601 602 public boolean insideSingleQuoteStr = false; 603 public boolean stringLiteralStartWithUnicodeSingleQuote = false; 604 605 606 // Previous implementation of readln, 2025-05-04 607 // char[] readln() throws IOException { 608 // int c; 609 // char[] buffer = new char[80]; 610 // int bufferSize = 0; 611 612 // while ((c = yyinput.read()) != -1) { 613 // if (bufferSize >= buffer.length) { 614 // char[] newBuffer = new char[buffer.length * 2]; 615 // System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); 616 // buffer = newBuffer; 617 // } 618 619 // buffer[bufferSize++] = (char)c; 620 621 // if (c == '\n' || c == '\r') { 622 // break; 623 // } 624 // } 625 626 // if (bufferSize > 0 && buffer[bufferSize - 1] == '\r') { 627 // yyinput.mark(1); 628 // c = yyinput.read(); 629 // if (c == '\n') { 630 // if (bufferSize >= buffer.length) { 631 // char[] newBuffer = new char[buffer.length + 1]; 632 // System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); 633 // buffer = newBuffer; 634 // } 635 // buffer[bufferSize++] = '\n'; 636 // } else { 637 // yyinput.reset(); 638 // } 639 // } 640 641 // if (bufferSize == 0) { 642 // return null; 643 // }else{ 644 // char[] result = new char[bufferSize]; 645 // System.arraycopy(buffer, 0, result, 0, bufferSize); 646 // return result; 647 // } 648 // } 649 650/** 651 * High-performance line reader with optimal buffer management 652 * @return char array containing the line including line ending, or null if end of stream 653 */ 654char[] readln() throws IOException { 655 if (yyinput == null) return null; 656 657 // Use larger initial buffer size to reduce reallocations 658 char[] buffer = new char[4096]; 659 int position = 0; 660 int c; 661 662 // Read characters until line ending or EOF 663 while ((c = yyinput.read()) != -1) { 664 // Expand buffer if needed 665 if (position >= buffer.length) { 666 char[] newBuffer = new char[buffer.length * 2]; 667 System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); 668 buffer = newBuffer; 669 } 670 671 // Store character 672 buffer[position++] = (char)c; 673 674 // Check for line endings 675 if (c == '\n') { 676 break; // LF - end of line 677 } else if (c == '\r') { 678 // Need to check for CR+LF sequence 679 yyinput.mark(1); 680 c = yyinput.read(); 681 682 if (c == '\n') { 683 // CR+LF sequence - include LF in result 684 if (position >= buffer.length) { 685 char[] newBuffer = new char[buffer.length + 1]; 686 System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); 687 buffer = newBuffer; 688 } 689 buffer[position++] = '\n'; 690 } else { 691 // CR only - reset stream to keep the character after CR 692 yyinput.reset(); 693 } 694 break; 695 } 696 } 697 698 // Return null if no characters were read (end of stream) 699 if (position == 0) { 700 return null; 701 } 702 703 // Create right-sized result array 704 char[] result = new char[position]; 705 System.arraycopy(buffer, 0, result, 0, position); 706 return result; 707} 708 709 char get_char(){ 710 711 char ret ; 712 boolean readlineok = true; 713 714 if ((bufptr == 0) && !eof(yyinput) ) 715 { 716 try{ 717 endOfInput = false; 718 yyline = readln();//yyinput.readLine(); 719 // System.out.println("readln: "+yyline); 720 if (yyline == null){ 721 readlineok = false; 722 } else{ 723 yylineno++; 724 yycolno = 0; 725 //bufptr = yyline.length(); 726 bufptr = yyline.length; 727 checkbuf(bufptr+1); 728 for(int k=1;k<=bufptr;k++){ 729 buf[k] = yyline[bufptr - k]; 730 // buf[k] = yyline.charAt(bufptr - k); 731 } 732 // System.out.println("line read:\r\n "+yyline); 733 } 734 }catch(IOException e){ 735 readlineok = false; 736 } 737 } 738 739 if (! readlineok){ 740 endOfInput = true; 741 return (char)0; 742 } 743 744 if (bufptr > 0){ 745 bufptr--; 746 yycolno++; 747 offset++; 748 749 return buf[bufptr+1]; 750 //return yyline.charAt(yyline.length() - (bufptr + 1)); 751 }else{ 752 // bufptr--; 753 endOfInput = true; 754 return (char)0; 755 } 756 757 } 758 759 void startlit(){ 760 literalbuf.setLength(0); 761 literallen = 0; 762 literalalloc = 0; 763 } 764 765 void addlit(String ytext, int yleng){ 766 literallen = literallen + yleng; 767 literalbuf.append(ytext,0,yleng); 768 } 769 770 void addlitchar(char ychar){ 771 literallen++; 772 literalbuf.append(ychar); 773 } 774 775 String litbufdup(){ 776 return literalbuf.toString();//.intern(); 777 } 778 779 boolean isopchar(char ch){ 780 String opstr = new String("~!@#^&|`?$%"); 781 return opstr.indexOf((int)ch) != -1; 782 } 783 784 boolean isselfchar(char ch){ 785 String opstr = new String(",()[].;$:+-*/%^<>=!"); 786 return opstr.indexOf((int)ch) != -1; 787 } 788 789 boolean charinarray(char c, char[] a){ 790 // return new String(a).indexOf((int)c) != -1; 791 int len = a.length; 792 for (int i = 0; i < len; i++) { 793 if (a[i] == c) 794 return true; 795 } 796 return false; 797 } 798 799 void setlengthofliteralbuf(int plen){ 800 literalbuf.setLength(plen); 801 } 802 803 void yyaction(int yyruleno){ 804 } 805 806 int yylex(){ 807 return 0; 808 } 809 810 811 int yylexwrap(TSourceToken psourcetoken) { 812 // Get token code and handle EOF 813 if ((psourcetoken.tokencode = yylex()) == 0) return 0; 814 815 // Assign token text 816 psourcetoken.astext = yylvalstr; 817 818 // Record token position information 819 psourcetoken.lineNo = yylineno_p; 820 psourcetoken.columnNo = yycolno_p; 821 psourcetoken.offset = offset_p; 822 yylineno_p = yylineno; 823 yycolno_p = yycolno + 1; 824 offset_p = offset + 1; 825 826 // Track token in token table for analysis 827 setTokenTableValue(psourcetoken); 828 829 // Handle token types based on token code 830 switch (psourcetoken.tokencode) { 831 case cmtdoublehyphen: 832 psourcetoken.tokentype = ETokenType.ttsimplecomment; 833 if (dbvendor == EDbVendor.dbvmdx && psourcetoken.toString().startsWith("/")) { 834 psourcetoken.tokentype = ETokenType.ttCPPComment; 835 } 836 break; 837 838 case cmtslashstar: 839 psourcetoken.tokentype = ETokenType.ttbracketedcomment; 840 break; 841 842 case lexspace: 843 psourcetoken.tokentype = ETokenType.ttwhitespace; 844 break; 845 846 case lexnewline: 847 psourcetoken.tokentype = ETokenType.ttreturn; 848 break; 849 850 case bind_v: 851 psourcetoken.tokentype = ETokenType.ttbindvar; 852 if (dbvendor == EDbVendor.dbvoracle) { 853 psourcetoken.astext = psourcetoken.astext.replace(TBaseType.newline, ""); 854 } 855 break; 856 857 case stmt_delimiter: 858 psourcetoken.tokentype = ETokenType.ttstmt_delimiter; 859 psourcetoken.tokencode = cmtslashstar; 860 break; 861 862 case concatenationop: 863 psourcetoken.tokentype = ETokenType.ttconcatenationop; 864 break; 865 866 case variable: 867 psourcetoken.tokentype = ETokenType.ttsqlvar; 868 break; 869 870 case fconst: 871 case iconst: 872 psourcetoken.tokentype = ETokenType.ttnumber; 873 break; 874 875 case sconst: 876 psourcetoken.tokentype = ETokenType.ttsqstring; 877 psourcetoken.dolqstart = dolqstart; 878 dolqstart = ""; 879 break; 880 881 case ident: 882 case QUOTED_IDENT: 883 handleIdentifierToken(psourcetoken); 884 break; 885 886 case cmpop: 887 handleComparisonOperator(psourcetoken); 888 break; 889 890 case op: 891 handleOperatorToken(psourcetoken); 892 break; 893 894 default: 895 handleDefaultToken(psourcetoken); 896 break; 897 } 898 899 prevToken = psourcetoken; 900 return psourcetoken.tokencode; 901 } 902 903 // Helper methods to better organize the complex token handling logic 904 private void handleIdentifierToken(TSourceToken psourcetoken) { 905 psourcetoken.tokentype = ETokenType.ttidentifier; 906 String tokenText = psourcetoken.astext.trim(); 907 908 if (tokenText.startsWith("\"")) { 909 psourcetoken.tokentype = ETokenType.ttdqstring; 910 } else if (tokenText.startsWith("[")) { 911 if (dbvendor == EDbVendor.dbvmssql || dbvendor == EDbVendor.dbvsybase) { 912 psourcetoken.tokentype = ETokenType.ttdbstring; 913 } 914 } else if (tokenText.startsWith("{")) { 915 if (dbvendor == EDbVendor.dbvmssql || dbvendor == EDbVendor.dbvsybase) { 916 psourcetoken.tokentype = ETokenType.ttbrstring; 917 if (tokenText.toLowerCase().startsWith("{escape")) { 918 psourcetoken.tokencode = TBaseType.rrw_sqlserver_odbc_escape; 919 } 920 } 921 } else if (tokenText.startsWith("&")) { 922 if (dbvendor == EDbVendor.dbvmdx) { 923 if (psourcetoken.tokencode == QUOTED_IDENT) { 924 psourcetoken.tokencode = AMP_QUOTED_ID; 925 } else if (psourcetoken.tokencode == ident) { 926 psourcetoken.tokencode = AMP_UNQUOTED_ID; 927 } 928 } 929 } else if (tokenText.startsWith(".")) { 930 if (dbvendor == EDbVendor.dbvteradata) { 931 psourcetoken.tokentype = ETokenType.ttBTEQCmd; 932 } 933 } 934 } 935 936 private void handleComparisonOperator(TSourceToken psourcetoken) { 937 psourcetoken.tokentype = ETokenType.ttmulticharoperator; 938 String token = yylvalstr; 939 940 if ((token.startsWith("!") && token.endsWith("=")) || 941 (token.startsWith("^") && token.endsWith("=")) || 942 (token.startsWith("<") && token.endsWith(">"))) { 943 944 psourcetoken.tokencode = TBaseType.not_equal; 945 946 // Handle MySQL NULL-safe equal 947 if (token.indexOf("=", 1) > 0 && 948 token.startsWith("<") && token.endsWith(">")) { 949 psourcetoken.tokencode = (int)'='; 950 } 951 } else if (token.startsWith(">") && token.endsWith("=")) { 952 psourcetoken.tokencode = TBaseType.great_equal; 953 } else if (token.startsWith("<") && token.endsWith("=")) { 954 psourcetoken.tokencode = TBaseType.less_equal; 955 } else if ((token.startsWith("!") && token.endsWith("<")) || 956 (token.startsWith("^") && token.endsWith("<"))) { 957 psourcetoken.tokencode = TBaseType.not_less; 958 } else if ((token.startsWith("!") && token.endsWith(">")) || 959 (token.startsWith("^") && token.endsWith(">"))) { 960 psourcetoken.tokencode = TBaseType.not_great; 961 } else if (token.length() == 2 && token.charAt(0) == ':' && token.charAt(1) == '=') { 962 psourcetoken.tokencode = assign_sign; 963 } 964 } 965 966 private void handleOperatorToken(TSourceToken psourcetoken) { 967 psourcetoken.tokentype = ETokenType.ttmulticharoperator; 968 String token = yylvalstr; 969 int tokenLength = token.length(); 970 char firstChar = tokenLength > 0 ? token.charAt(0) : '\0'; 971 char secondChar = tokenLength > 1 ? token.charAt(1) : '\0'; 972 973 // Handle question mark specially 974 if (token.equals("?") && isqmarktoident) { 975 handleQuestionMark(psourcetoken); 976 return; 977 } 978 979 // Handle special two-character operators 980 if (tokenLength == 2) { 981 if (handleTwoCharOperator(psourcetoken, firstChar, secondChar)) { 982 return; 983 } 984 } 985 986 // Handle special three-character operators 987 if (tokenLength == 3) { 988 if (handleThreeCharOperator(psourcetoken, firstChar, secondChar, token.charAt(2))) { 989 return; 990 } 991 } 992 993 // Handle comparison operators 994 if (handleComparisonOp(psourcetoken, token)) { 995 return; 996 } 997 998 // Handle single character operators 999 if (tokenLength == 1) { 1000 handleSingleCharOperator(psourcetoken, firstChar); 1001 } 1002 } 1003 1004 private boolean handleTwoCharOperator(TSourceToken psourcetoken, char firstChar, char secondChar) { 1005 switch (firstChar) { 1006 case '<': 1007 if (secondChar == '<') { 1008 return handleLeftShiftOperator(psourcetoken); 1009 } else if (secondChar == '@') { 1010 psourcetoken.tokencode = TBaseType.JSON_RIGHT_CONTAIN; 1011 return true; 1012 } 1013 break; 1014 1015 case '>': 1016 if (secondChar == '>') { 1017 return handleRightShiftOperator(psourcetoken); 1018 } 1019 break; 1020 1021 case '=': 1022 if (secondChar == '>') { 1023 if (dbvendor == EDbVendor.dbvodbc) { 1024 psourcetoken.tokencode = TBaseType.great_equal; 1025 } else if (dbvendor == EDbVendor.dbvpostgresql || dbvendor == EDbVendor.dbvgaussdb) { 1026 psourcetoken.tokencode = TBaseType.assign_sign; 1027 } else { 1028 psourcetoken.tokencode = NAMED_PARAMETER_SIGN; 1029 } 1030 return true; 1031 } else if (secondChar == '*') { 1032 if (dbvendor == EDbVendor.dbvmssql || dbvendor == EDbVendor.dbvsybase) { 1033 psourcetoken.tokencode = rightjoin_op; 1034 } 1035 return true; 1036 } else if (secondChar == '<') { 1037 if (dbvendor == EDbVendor.dbvodbc) { 1038 psourcetoken.tokencode = TBaseType.less_equal; 1039 } 1040 return true; 1041 } else if (secondChar == '=') { 1042 if (dbvendor == EDbVendor.dbvsparksql) { 1043 psourcetoken.tokencode = '='; 1044 } 1045 return true; 1046 } 1047 break; 1048 1049 case '-': 1050 if (secondChar == '>') { 1051 if (dbvendor == EDbVendor.dbvpostgresql || dbvendor == EDbVendor.dbvgaussdb 1052 || dbvendor == EDbVendor.dbvgreenplum || dbvendor == EDbVendor.dbvmysql) { 1053 psourcetoken.tokencode = TBaseType.JSON_GET_OBJECT; 1054 } else { 1055 psourcetoken.tokencode = ref_arrow; 1056 } 1057 return true; 1058 } else if (secondChar == '=') { 1059 if (dbvendor == EDbVendor.dbvmssql || dbvendor == EDbVendor.dbvsybase) { 1060 psourcetoken.tokencode = compoundAssignmentOperator; 1061 } 1062 return true; 1063 } 1064 break; 1065 1066 case '.': 1067 if (secondChar == '.') { 1068 if (dbvendor == EDbVendor.dbvdb2 || dbvendor == EDbVendor.dbvoracle 1069 || dbvendor == EDbVendor.dbvmysql || dbvendor == EDbVendor.dbvhana) { 1070 psourcetoken.tokencode = double_dot; 1071 } 1072 return true; 1073 } 1074 break; 1075 1076 case '*': 1077 if (secondChar == '=') { 1078 if (dbvendor == EDbVendor.dbvmssql || dbvendor == EDbVendor.dbvsybase) { 1079 psourcetoken.tokencode = leftjoin_op; 1080 } 1081 return true; 1082 } else if (secondChar == '*') { 1083 if (dbvendor == EDbVendor.dbvteradata || dbvendor == EDbVendor.dbvnetezza) { 1084 psourcetoken.tokencode = TBaseType.exponentiate; 1085 } 1086 return true; 1087 } 1088 break; 1089 1090 case '|': 1091 if (secondChar == '|') { 1092 if (dbvendor == EDbVendor.dbvmysql) { 1093 psourcetoken.tokencode = TBaseType.logical_or; 1094 } else if (isStringConcatVendor(dbvendor)) { 1095 psourcetoken.tokencode = TBaseType.concatenationop; 1096 } 1097 return true; 1098 } else if (secondChar == '/') { 1099 if (dbvendor == EDbVendor.dbvredshift) { 1100 psourcetoken.tokencode = TBaseType.square_root; 1101 } 1102 return true; 1103 } 1104 break; 1105 1106 case '&': 1107 if (secondChar == '&') { 1108 if (dbvendor == EDbVendor.dbvmysql) { 1109 psourcetoken.tokencode = TBaseType.logical_and; 1110 } 1111 return true; 1112 } 1113 break; 1114 1115 case '?': 1116 if (secondChar == '|') { 1117 psourcetoken.tokencode = TBaseType.JSON_ANY_EXIST; 1118 return true; 1119 } else if (secondChar == '&') { 1120 psourcetoken.tokencode = TBaseType.JSON_ALL_EXIST; 1121 return true; 1122 } 1123 break; 1124 1125 case '@': 1126 if (secondChar == '>') { 1127 psourcetoken.tokencode = TBaseType.JSON_LEFT_CONTAIN; 1128 return true; 1129 } 1130 break; 1131 1132 case '#': 1133 if (secondChar == '>') { 1134 psourcetoken.tokencode = TBaseType.JSON_GET_OBJECT_AT_PATH; 1135 return true; 1136 } 1137 break; 1138 1139 case ':': 1140 if (secondChar == '=') { 1141 psourcetoken.tokencode = assign_sign; 1142 return true; 1143 } 1144 break; 1145 } 1146 1147 // Handle compound assignment operators 1148 if ((firstChar == '+' || firstChar == '-' || firstChar == '*' || 1149 firstChar == '/' || firstChar == '%' || firstChar == '&' || 1150 firstChar == '^' || firstChar == '|') && secondChar == '=') { 1151 if (dbvendor == EDbVendor.dbvmssql || dbvendor == EDbVendor.dbvsybase) { 1152 psourcetoken.tokencode = compoundAssignmentOperator; 1153 return true; 1154 } else if (dbvendor == EDbVendor.dbvmysql && firstChar == '^' && secondChar == '=') { 1155 psourcetoken.tokencode = not_equal; 1156 return true; 1157 } 1158 } 1159 1160 return false; 1161 } 1162 1163 private boolean handleThreeCharOperator(TSourceToken psourcetoken, char firstChar, char secondChar, char thirdChar) { 1164 if (firstChar == '-' && secondChar == '>' && thirdChar == '>') { 1165 psourcetoken.tokencode = TBaseType.JSON_GET_TEXT; 1166 return true; 1167 } else if (firstChar == '#' && secondChar == '>' && thirdChar == '>') { 1168 psourcetoken.tokencode = TBaseType.JSON_GET_TEXT_AT_PATH; 1169 return true; 1170 } else if (firstChar == '|' && secondChar == '|' && thirdChar == '/') { 1171 if (dbvendor == EDbVendor.dbvredshift) { 1172 psourcetoken.tokencode = TBaseType.cube_root; 1173 return true; 1174 } 1175 } 1176 return false; 1177 } 1178 1179 private boolean handleComparisonOp(TSourceToken psourcetoken, String token) { 1180 if ((token.startsWith("!") && token.endsWith("=")) || 1181 (token.startsWith("^") && token.endsWith("=")) || 1182 (token.startsWith("<") && token.endsWith(">"))) { 1183 psourcetoken.tokencode = TBaseType.not_equal; 1184 return true; 1185 } else if (token.startsWith(">") && token.endsWith("=")) { 1186 psourcetoken.tokencode = TBaseType.great_equal; 1187 return true; 1188 } else if (token.startsWith("<") && token.endsWith("=")) { 1189 psourcetoken.tokencode = TBaseType.less_equal; 1190 return true; 1191 } else if ((token.startsWith("!") && token.endsWith("<")) || 1192 (token.startsWith("^") && token.endsWith("<"))) { 1193 psourcetoken.tokencode = TBaseType.not_less; 1194 return true; 1195 } else if ((token.startsWith("!") && token.endsWith(">")) || 1196 (token.startsWith("^") && token.endsWith(">"))) { 1197 psourcetoken.tokencode = TBaseType.not_great; 1198 return true; 1199 } 1200 return false; 1201 } 1202 1203 private void handleSingleCharOperator(TSourceToken psourcetoken, char ch) { 1204 switch (ch) { 1205 case '~': 1206 if (dbvendor == EDbVendor.dbvmysql || dbvendor == EDbVendor.dbvredshift || 1207 dbvendor == EDbVendor.dbvsnowflake) { 1208 psourcetoken.tokencode = (int)'~'; 1209 } 1210 break; 1211 1212 case '#': 1213 if (dbvendor == EDbVendor.dbvmssql) { 1214 psourcetoken.tokencode = (int)'#'; 1215 } 1216 break; 1217 1218 case '&': 1219 if (dbvendor == EDbVendor.dbvmysql || dbvendor == EDbVendor.dbvvertica || 1220 dbvendor == EDbVendor.dbvsparksql) { 1221 psourcetoken.tokencode = (int)'&'; 1222 } 1223 break; 1224 1225 case '|': 1226 if (dbvendor == EDbVendor.dbvmysql || dbvendor == EDbVendor.dbvvertica) { 1227 psourcetoken.tokencode = (int)'|'; 1228 } 1229 break; 1230 } 1231 } 1232 1233 private void handleQuestionMark(TSourceToken psourcetoken) { 1234 if (dbvendor == EDbVendor.dbvpostgresql || dbvendor == EDbVendor.dbvgaussdb || 1235 dbvendor == EDbVendor.dbvgreenplum) { 1236 psourcetoken.tokencode = TBaseType.JSON_EXIST; 1237 } else if (dbvendor == EDbVendor.dbvodbc) { 1238 psourcetoken.tokencode = '?'; 1239 } else if (dbvendor == EDbVendor.dbvsnowflake) { 1240 psourcetoken.tokencode = bind_v; 1241 psourcetoken.tokentype = ETokenType.ttquestionmark; 1242 } else { 1243 psourcetoken.tokencode = ident; 1244 } 1245 } 1246 1247 private boolean handleLeftShiftOperator(TSourceToken psourcetoken) { 1248 if (dbvendor == EDbVendor.dbvoracle || dbvendor == EDbVendor.dbvmssql || 1249 dbvendor == EDbVendor.dbvsybase || dbvendor == EDbVendor.dbvpostgresql || 1250 dbvendor == EDbVendor.dbvgaussdb || dbvendor == EDbVendor.dbvaccess || 1251 dbvendor == EDbVendor.dbvgreenplum) { 1252 psourcetoken.tokencode = label_begin; 1253 } else if (dbvendor == EDbVendor.dbvmysql) { 1254 psourcetoken.tokencode = TBaseType.rrw_left_shift; 1255 } else if (dbvendor == EDbVendor.dbvredshift) { 1256 psourcetoken.tokencode = TBaseType.bitwise_shift_left; 1257 } else if (dbvendor == EDbVendor.dbvnetezza) { 1258 psourcetoken.tokencode = TBaseType.rrw_netezza_op_less_less; 1259 } 1260 return true; 1261 } 1262 1263 private boolean handleRightShiftOperator(TSourceToken psourcetoken) { 1264 if (dbvendor == EDbVendor.dbvoracle || dbvendor == EDbVendor.dbvmssql || 1265 dbvendor == EDbVendor.dbvsybase || dbvendor == EDbVendor.dbvpostgresql || 1266 dbvendor == EDbVendor.dbvgaussdb || dbvendor == EDbVendor.dbvgreenplum || 1267 dbvendor == EDbVendor.dbvaccess) { 1268 psourcetoken.tokencode = label_end; 1269 } else if (dbvendor == EDbVendor.dbvmysql) { 1270 psourcetoken.tokencode = TBaseType.rrw_right_shift; 1271 } else if (dbvendor == EDbVendor.dbvredshift) { 1272 psourcetoken.tokencode = TBaseType.bitwise_shift_right; 1273 } else if (dbvendor == EDbVendor.dbvnetezza) { 1274 psourcetoken.tokencode = TBaseType.rrw_netezza_op_great_great; 1275 } 1276 return true; 1277 } 1278 1279 private boolean isStringConcatVendor(EDbVendor vendor) { 1280 return vendor == EDbVendor.dbvdb2 || vendor == EDbVendor.dbvnetezza || 1281 vendor == EDbVendor.dbvpostgresql || vendor == EDbVendor.dbvgaussdb || 1282 vendor == EDbVendor.dbvredshift || vendor == EDbVendor.dbvgreenplum || 1283 vendor == EDbVendor.dbvbigquery || vendor == EDbVendor.dbvsnowflake || 1284 vendor == EDbVendor.dbvsparksql || vendor == EDbVendor.dbvvertica; 1285 } 1286 1287 private void handleDefaultToken(TSourceToken psourcetoken) { 1288 psourcetoken.tokentype = ETokenType.ttkeyword; 1289 1290 if (psourcetoken.tokencode < 255) { 1291 // Single character operators (ASCII characters) 1292 psourcetoken.astext = Character.toString(yylvalstr.charAt(0)); 1293 psourcetoken.tokentype = ETokenType.ttsinglecharoperator; 1294 1295 switch (psourcetoken.tokencode) { 1296 case ',': 1297 psourcetoken.tokentype = ETokenType.ttcomma; 1298 break; 1299 case '(': 1300 psourcetoken.tokentype = ETokenType.ttleftparenthesis; 1301 break; 1302 case ')': 1303 psourcetoken.tokentype = ETokenType.ttrightparenthesis; 1304 break; 1305 case '[': 1306 psourcetoken.tokentype = ETokenType.ttleftbracket; 1307 break; 1308 case ']': 1309 psourcetoken.tokentype = ETokenType.ttrightbracket; 1310 break; 1311 case '.': 1312 psourcetoken.tokentype = ETokenType.ttperiod; 1313 break; 1314 case ';': 1315 psourcetoken.tokentype = ETokenType.ttsemicolon; 1316 break; 1317 case '$': 1318 psourcetoken.tokentype = ETokenType.ttdolorsign; 1319 break; 1320 case ':': 1321 psourcetoken.tokentype = ETokenType.ttcolon; 1322 break; 1323 case '+': 1324 psourcetoken.tokentype = ETokenType.ttplussign; 1325 break; 1326 case '-': 1327 psourcetoken.tokentype = ETokenType.ttminussign; 1328 break; 1329 case '*': 1330 psourcetoken.tokentype = ETokenType.ttasterisk; 1331 break; 1332 case '/': 1333 psourcetoken.tokentype = ETokenType.ttslash; 1334 break; 1335 case '^': 1336 psourcetoken.tokentype = ETokenType.ttcaret; 1337 break; 1338 case '<': 1339 psourcetoken.tokentype = ETokenType.ttlessthan; 1340 break; 1341 case '>': 1342 psourcetoken.tokentype = ETokenType.ttgreaterthan; 1343 break; 1344 case '=': 1345 psourcetoken.tokentype = ETokenType.ttequals; 1346 break; 1347 case '@': 1348 if (delimiterchar == '@') { 1349 psourcetoken.tokencode = (int)';'; 1350 psourcetoken.tokentype = ETokenType.ttsemicolon; 1351 } else { 1352 psourcetoken.tokentype = ETokenType.ttatsign; 1353 } 1354 break; 1355 case '~': 1356 psourcetoken.tokentype = ETokenType.tttilde; 1357 break; 1358 case '&': 1359 psourcetoken.tokentype = ETokenType.ttampersand; 1360 break; 1361 case '|': 1362 psourcetoken.tokentype = ETokenType.ttverticalbar; 1363 break; 1364 case '?': 1365 if (isqmarktoident && dbvendor != EDbVendor.dbvodbc && 1366 dbvendor != EDbVendor.dbvpostgresql && dbvendor != EDbVendor.dbvgaussdb) { 1367 psourcetoken.tokencode = ident; 1368 } 1369 break; 1370 } 1371 } else if (dbvendor == EDbVendor.dbvhive && psourcetoken.tokencode == TBaseType.hive_equal) { 1372 psourcetoken.tokentype = ETokenType.ttequals; 1373 } 1374 } 1375 1376} 1377