001package gudusoft.gsqlparser.stmt; 002 003import gudusoft.gsqlparser.*; 004import gudusoft.gsqlparser.compiler.TStmtScope; 005import gudusoft.gsqlparser.nodes.*; 006import gudusoft.gsqlparser.nodes.hana.TTimeTravel; 007import gudusoft.gsqlparser.nodes.hive.*; 008import gudusoft.gsqlparser.nodes.mssql.TOptionClause; 009import gudusoft.gsqlparser.nodes.THierarchical; 010import gudusoft.gsqlparser.nodes.teradata.TExpandOnClause; 011import gudusoft.gsqlparser.sqlenv.ESQLDataObjectType; 012import gudusoft.gsqlparser.sqlenv.IdentifierService; 013import gudusoft.gsqlparser.sqlenv.TSQLEnv; 014import gudusoft.gsqlparser.sqlenv.TSQLTable; 015 016import java.util.ArrayList; 017import java.util.Collections; 018import java.util.TreeMap; 019 020 021/** 022 * Class {@link gudusoft.gsqlparser.stmt.TSelectSqlStatement } represents query specification, query expression and select statement. 023 * <br><br><b>query specification</b> including following clause: 024 * <ul> 025 * <li>select list {@link #getResultColumnList}</li> 026 * <li>from clause {@link #joins}</li> 027 * <li>where clause {@link #getWhereClause}</li> 028 * <li>group clause {@link #getGroupByClause}</li> 029 * <li>having clause {@link #getGroupByClause}</li> 030 * </ul> 031 * In some databases, query specification also known as sub-select. 032 * 033 * <br><br><b>query expression</b> including all elements in query specification and following clause: 034 * <ul> 035 * <li>order by clause {@link #getOrderbyClause}</li> 036 * <li>offset clause {@link #getOffsetClause}</li> 037 * <li>for clause</li> 038 * </ul> 039 * In some databases, query expression also known as full-select. 040 * <br>It is a component of the select-statement, the INSERT statement, and the CREATE VIEW statement. 041 * And a full-select that is enclosed in parentheses is sometimes called a sub-query. 042 * 043 * <br><br>select statement including all elements in query expression and following clause: 044 * <ul> 045 * <li>compute clause {@link #getComputeClause}</li> 046 * <li>for update clause {@link #getForUpdateClause}</li> 047 * <li>optimizer hint</li> 048 * <li>ctes {@link #getCteList}</li> 049 * </ul> 050 * Lots of clauses on this level are db vendors specific. 051 * 052 053 * <br><br> 054 * Use {@link #isCombinedQuery} to check whether UNION, EXCEPT and INTERSECT operators is used. 055 * If returns true, use {@link #getLeftStmt} and {@link #getRightStmt} to get query expression. 056 * You need to check {@link #isCombinedQuery} recursively, all clauses of {@link gudusoft.gsqlparser.stmt.TSelectSqlStatement} 057 * only available when this function returns false. 058 * 059 */ 060 061public class TSelectSqlStatement extends TCustomSqlStatement { 062 063 // 如果是 combined query, 并且当前select 没有预先设定的 endToken, 则取最右边 query 的 endToken 064 public TSourceToken getEndToken() { 065 if (super.getEndToken() != null) return super.getEndToken(); 066 if (this.isCombinedQuery()){ 067 return this.getRightStmt().getEndToken(); 068 }else{ 069 return super.getEndToken(); 070 } 071 } 072 073 public void setSubQueryInFromClauseCanUseParentSelectAsEnclosingScope(boolean subQueryInFromClauseCanUseParentSelectAsEnclosingScope) { 074 this.subQueryInFromClauseCanUseParentSelectAsEnclosingScope = subQueryInFromClauseCanUseParentSelectAsEnclosingScope; 075 } 076 077 public boolean isSubQueryInFromClauseCanUseParentSelectAsEnclosingScope() { 078 return subQueryInFromClauseCanUseParentSelectAsEnclosingScope; 079 } 080 081 private boolean subQueryInFromClauseCanUseParentSelectAsEnclosingScope = false; 082 083 boolean starColumnPushedDown = false; 084 085 public boolean isStarColumnPushedDown() { 086 return starColumnPushedDown; 087 } 088 089 public void setStarColumnPushedDown(boolean starColumnPushedDown) { 090 this.starColumnPushedDown = starColumnPushedDown; 091 } 092 093 // StarRocks pipe operator support 094 private TPTNodeList<TParseTreeNode> pipeOperators; 095 private boolean isPipeQuery = false; 096 097 // Oracle 12c WITH FUNCTION/PROCEDURE support - inline PL/SQL definitions 098 private TStatementListSqlNode withPlsqlItems; 099 100 /** 101 * Get the inline PL/SQL function/procedure definitions from WITH clause. 102 * Oracle 12c+ allows defining PL/SQL functions inline in the WITH clause: 103 * WITH FUNCTION f(x NUMBER) RETURN NUMBER IS BEGIN RETURN x*2; END; 104 * SELECT f(1) FROM dual 105 * 106 * @return list of inline function/procedure definitions, or null if none 107 */ 108 public TStatementListSqlNode getWithPlsqlItems() { 109 return withPlsqlItems; 110 } 111 112 /** 113 * Set the inline PL/SQL function/procedure definitions. 114 * @param withPlsqlItems list of inline function/procedure definitions 115 */ 116 public void setWithPlsqlItems(TStatementListSqlNode withPlsqlItems) { 117 this.withPlsqlItems = withPlsqlItems; 118 } 119 120 /** 121 * Get the list of pipe operators for StarRocks pipe query syntax. 122 * Pipe queries use the |> operator to chain operations: 123 * FROM table |> SELECT * |> WHERE cond |> ORDER BY col 124 * 125 * @return list of TPipeOperator nodes, or null if not a pipe query 126 */ 127 public TPTNodeList<TParseTreeNode> getPipeOperators() { 128 return pipeOperators; 129 } 130 131 /** 132 * Set the pipe operators list. 133 * @param pipeOperators list of pipe operator nodes 134 */ 135 public void setPipeOperators(TPTNodeList<TParseTreeNode> pipeOperators) { 136 this.pipeOperators = pipeOperators; 137 } 138 139 /** 140 * Check if this is a StarRocks pipe query. 141 * Pipe queries use the syntax: FROM table |> SELECT * |> WHERE ... 142 * 143 * @return true if this is a pipe query 144 */ 145 public boolean isPipeQuery() { 146 return isPipeQuery; 147 } 148 149 /** 150 * Set whether this is a pipe query. 151 * @param isPipeQuery true if this is a pipe query 152 */ 153 public void setIsPipeQuery(boolean isPipeQuery) { 154 this.isPipeQuery = isPipeQuery; 155 } 156 157 /** 158 * 在 sql script 中,和该 relation 关联的 attribute。 159 * select a from t; 160 * attribute a 就是 relation t 的 referenceAttribute, 如果没有 metadata and ddl, 161 * relation t 的 getAttributes() 应该可以推断出包含 a, 但 t 是否还包含其他的 attribute 就无从得知。 162 */ 163 164 @Override 165 public ArrayList<TAttributeNode> getAttributes(){ 166 if (this.getFromClause() == null) return null; 167 168 return this.getFromClause().getAttributes(); 169 170// relationAttributes.clear(); 171// for(TTable table:getRelations()){ 172// relationAttributes.addAll(table.getAttributes()); 173// } 174// 175// if (relationAttributes.size() > 0){ 176// TBaseType.log ("relationAttributes.size() in select is :"+relationAttributes.size() 177// +", relation size: "+getRelations().size() 178// +", relation 0 type:"+getRelations().get(0).getTableType() 179// ,1); 180// // System.out.println(this.toString()); 181// } 182// 183// return relationAttributes; 184 } 185 186 ArrayList<TAttributeNode> relationAttributes = new ArrayList<>(); 187 188// private TExpression skipOffset; 189// private TExpression firstMax; 190// private TExpression limitMax; 191// 192// public void setSkipOffset(TExpression skipOffset) { 193// this.skipOffset = skipOffset; 194// } 195// 196// public void setFirstMax(TExpression firstMax) { 197// this.firstMax = firstMax; 198// } 199// 200// public void setLimitMax(TExpression limitMax) { 201// this.limitMax = limitMax; 202// } 203// 204// /** 205// * Informix skip offset 206// * @return skip offset 207// */ 208// public TExpression getSkipOffset() { 209// 210// return skipOffset; 211// } 212// 213// /** 214// * Informix first Max 215// * @return first Max 216// */ 217// public TExpression getFirstMax() { 218// return firstMax; 219// } 220// 221// /** 222// * Informix limit max 223// * @return limit max 224// */ 225// public TExpression getLimitMax() { 226// return limitMax; 227// } 228 229 private ArrayList<TSelectSqlStatement> multiSelectStatements; 230 231 /** 232 * Hive, from ... select, select,... 233 * <br> Multiple select statement in Hive from query syntax 234 * 235 * @return Multiple select statement in Hive from query syntax 236 */ 237 public ArrayList<TSelectSqlStatement> getMultiSelectStatements() { 238 if(multiSelectStatements == null){ 239 multiSelectStatements = new ArrayList<>(); 240 } 241 return multiSelectStatements; 242 } 243 244 private TClusterBy clusterBy; 245 246 public void setClusterBy(TClusterBy clusterBy) { 247 this.clusterBy = clusterBy; 248 } 249 250 public TClusterBy getClusterBy() { 251 return clusterBy; 252 } 253 254 private boolean isConsume; 255 256 public void setConsume(boolean consume) { 257 isConsume = consume; 258 } 259 260 public boolean isConsume() { 261 return isConsume; 262 } 263 264 private TStatementList hiveBodyList = null; 265 266 /** 267 * @deprecated since 2.6.3.5, please use {@link #getMultiSelectStatements()} to retrieve 268 * multimple select statement in Hive from query ... select, select, ... 269 * 270 * @return 271 */ 272 public TStatementList getHiveBodyList() { 273 if (hiveBodyList == null) 274 hiveBodyList = new TStatementList(); 275 return hiveBodyList; 276 } 277 278 public void setSelectModifiers(ArrayList<TSelectModifier> selectModifiers) { 279 this.selectModifiers = selectModifiers; 280 } 281 282 public ArrayList<TSelectModifier> getSelectModifiers() { 283 return selectModifiers; 284 } 285 286 private ArrayList<TSelectModifier> selectModifiers; 287 288 289 private TTimeTravel timeTravel; // hana 290 private THintClause hintClause; //hana 291 292 public void setTimeTravel(TTimeTravel timeTravel) { 293 setNewSubNode(this.timeTravel,timeTravel,getAnchorNode()); 294 this.timeTravel = timeTravel; 295 } 296 297 public void setHintClause(THintClause hintClause) { 298 setNewSubNode(this.hintClause,hintClause,getAnchorNode()); 299 this.hintClause = hintClause; 300 } 301 302 303 public TTimeTravel getTimeTravel() { 304 305 return timeTravel; 306 } 307 308 public THintClause getHintClause() { 309 return hintClause; 310 } 311 312 private int parenthesisCount = 0; 313 private int parenthesisCountBeforeOrder = 0; 314 315 public void setFetchFirstClause(TFetchFirstClause fetchFirstClause) { 316 setNewSubNode(this.fetchFirstClause,fetchFirstClause,getAnchorNode()); 317 this.fetchFirstClause = fetchFirstClause; 318 } 319 320 321 public void setParenthesisCount(int parenthesisCount) { 322 this.parenthesisCount = parenthesisCount; 323 } 324 325 public void setParenthesisCountBeforeOrder(int parenthesisCountBeforeOrder) { 326 this.parenthesisCountBeforeOrder = parenthesisCountBeforeOrder; 327 } 328 329 public void setAll(boolean all) { 330 this.all = all; 331 } 332 333 public void setSetOperatorType(ESetOperatorType setOperatorType) { 334 this.setOperatorType = setOperatorType; 335 } 336 337 public void setWindowClause(TWindowClause windowClause) { 338 setNewSubNode(this.windowClause,windowClause,getAnchorNode()); 339 this.windowClause = windowClause; 340 } 341 342 public void setLockingClauses(TPTNodeList<TLockingClause> lockingClauses) { 343 this.lockingClauses = lockingClauses; 344 } 345 346 public void setSelectDistinct(TSelectDistinct selectDistinct) { 347 setNewSubNode(this.selectDistinct,selectDistinct,getAnchorNode()); 348 this.selectDistinct = selectDistinct; 349 } 350 351 public void setExpandOnClause(TExpandOnClause expandOnClause) { 352 setNewSubNode(this.expandOnClause,expandOnClause,getAnchorNode()); 353 this.expandOnClause = expandOnClause; 354 } 355 356 357 public void setSetOperator(int setOperator) { 358 this.setOperator = setOperator; 359 } 360 361 public void setLeftStmt(TSelectSqlStatement leftStmt) { 362 this.leftStmt = leftStmt; 363 } 364 365 public void setRightStmt(TSelectSqlStatement rightStmt) { 366 this.rightStmt = rightStmt; 367 } 368 369 public void setValueClause(TValueClause valueClause) { 370 setNewSubNode(this.valueClause,valueClause,getAnchorNode()); 371 this.valueClause = valueClause; 372 } 373 374 public void setOracleHint(String oracleHint) { 375 this.oracleHint = oracleHint; 376 } 377 378 public void setHiveHintClause(THiveHintClause hiveHintClause) { 379 setNewSubNode(this.hiveHintClause,hiveHintClause,getAnchorNode()); 380 this.hiveHintClause = hiveHintClause; 381 } 382 383 384 public void setTransformClause(THiveTransformClause transformClause) { 385 setNewSubNode(this.transformClause,transformClause,getAnchorNode()); 386 this.transformClause = transformClause; 387 } 388 389 public void setDistributeBy(TDistributeBy distributeBy) { 390 setNewSubNode(this.distributeBy,distributeBy,getAnchorNode()); 391 this.distributeBy = distributeBy; 392 } 393 394 395 public void setIntoClause(TIntoClause intoClause) { 396 setNewSubNode(this.intoClause,intoClause,getAnchorNode()); 397 this.intoClause = intoClause; 398 } 399 400 public void setOrderbyClause(TOrderBy newOrderbyClause) { 401 setNewSubNode(this.orderbyClause,newOrderbyClause,getAnchorNode()); 402 this.orderbyClause = newOrderbyClause; 403 } 404 405// public void setOrderbyClause(TOrderBy newOrderbyClause, TParseTreeNode anchorNode) { 406// if (newOrderbyClause == null){ 407// //remove 408// this.orderbyClause.removeTokens(); 409// this.orderbyClause = null; 410// }else{ 411// if (this.orderbyClause != null){ 412// this.orderbyClause.replaceWithNewNode(newOrderbyClause); 413// }else{ 414// doAppendNewNode(newOrderbyClause,anchorNode,false); 415// } 416// this.orderbyClause = newOrderbyClause; 417// } 418// } 419 420 public void setQualifyClause(TQualifyClause qualifyClause) { 421 setNewSubNode(this.qualifyClause,qualifyClause,getAnchorNode()); 422 this.qualifyClause = qualifyClause; 423 } 424 425 public void setSampleClause(TSampleClause sampleClause) { 426 setNewSubNode(this.sampleClause,sampleClause,getAnchorNode()); 427 this.sampleClause = sampleClause; 428 } 429 430 public void setTeradataWithClause(TTeradataWithClause teradataWithClause) { 431 setNewSubNode(this.teradataWithClause,teradataWithClause,getAnchorNode()); 432 this.teradataWithClause = teradataWithClause; 433 } 434 435 public void setForUpdateClause(TForUpdate forUpdateClause) { 436 setNewSubNode(this.forUpdateClause,forUpdateClause,getAnchorNode()); 437 this.forUpdateClause = forUpdateClause; 438 } 439 440 441 public void setComputeClause(TComputeClause computeClause) { 442 this.computeClause = computeClause; 443 } 444 445 public void setGroupByClause(TGroupBy groupByClause) { 446 setNewSubNode(this.groupByClause,groupByClause,getAnchorNode()); 447 this.groupByClause = groupByClause; 448 } 449 450 451 public void setHierarchicalClause(THierarchical hierarchicalClause) { 452 setNewSubNode(this.hierarchicalClause,hierarchicalClause,getAnchorNode()); 453 this.hierarchicalClause = hierarchicalClause; 454 } 455 456 457 public void setLimitClause(TLimitClause limitClause) { 458 setNewSubNode(this.limitClause,limitClause,getAnchorNode()); 459 this.limitClause = limitClause; 460 } 461 462 public void setOffsetClause(TOffsetClause offsetClause) { 463 setNewSubNode(this.offsetClause,offsetClause,getAnchorNode()); 464 this.offsetClause = offsetClause; 465 } 466 467 public void setOptionClause(TOptionClause optionClause) { 468 setNewSubNode(this.optionClause,optionClause,getAnchorNode()); 469 this.optionClause = optionClause; 470 } 471 472 public void setIsolationClause(TIsolationClause isolationClause) { 473 setNewSubNode(this.isolationClause,isolationClause,getAnchorNode()); 474 this.isolationClause = isolationClause; 475 } 476 477// public void setHiveClusterBy(THiveClusterBy hiveClusterBy) { 478// setNewSubNode(this.hiveClusterBy,hiveClusterBy,getAnchorNode()); 479// this.hiveClusterBy = hiveClusterBy; 480// } 481 482 483 public void setSortBy(TSortBy sortBy) { 484 setNewSubNode(this.sortBy,sortBy,getAnchorNode()); 485 this.sortBy = sortBy; 486 } 487 488 public void setIntoTableClause(TIntoTableClause intoTableClause) { 489 setNewSubNode(this.intoTableClause,intoTableClause,getAnchorNode()); 490 this.intoTableClause = intoTableClause; 491 } 492 493 public int getParenthesisCountBeforeOrder() { 494 return parenthesisCountBeforeOrder; 495 } 496 497 public int getParenthesisCount() { 498 return parenthesisCount; 499 } 500 501 private boolean queryOfCTE; 502 503 public void setQueryOfCTE(boolean queryOfCTE) { 504 this.queryOfCTE = queryOfCTE; 505 } 506 507 public boolean isQueryOfCTE() { 508 return queryOfCTE; 509 } 510 511 /** 512 * Offset clause. 513 * <br> 514 * <pre>OFFSET 2 ROWS FETCH NEXT 4 ROWS ONLY;</pre> 515 * @return {@link TOffsetClause offset clause} 516 */ 517 public TOffsetClause getOffsetClause() { 518 return offsetClause; 519 } 520 521 /** 522 * Fetch first/next clause 523 * <br> 524 * <pre>OFFSET 2 ROWS FETCH NEXT 4 ROWS ONLY;</pre> 525 * @return {@link TFetchFirstClause fetch first/next clause} 526 */ 527 public TFetchFirstClause getFetchFirstClause() { 528 529 return fetchFirstClause; 530 } 531 532 private TFetchFirstClause fetchFirstClause; 533 private TOffsetClause offsetClause; 534 535 private TOptionClause optionClause; 536 537 /** 538 * 539 * @return {@link TOptionClause sql server option clause} 540 * 541 * @see gudusoft.gsqlparser.nodes.mssql.TOptionClause 542 */ 543 public TOptionClause getOptionClause() { 544 return optionClause; 545 } 546 547 548 /** 549 * 550 * @return {@link TIsolationClause isolation clause} 551 */ 552 public TIsolationClause getIsolationClause() { 553 return isolationClause; 554 } 555 556 private TIsolationClause isolationClause; 557 558// private THiveClusterBy hiveClusterBy; 559// 560// /** 561// * 562// * @return {@link THiveClusterBy Hive cluster by clause} 563// */ 564// public THiveClusterBy getHiveClusterBy() { 565// return hiveClusterBy; 566// } 567 568 private TSortBy sortBy; 569 570 /** 571 * 572 * @return {@link TSortBy Hive sort by clause} 573 */ 574 public TSortBy getSortBy() { 575 return sortBy; 576 } 577 578 private TIntoTableClause intoTableClause; 579 580 /** 581 * 582 * @return {@link TIntoTableClause informix into table clause} 583 */ 584 public TIntoTableClause getIntoTableClause() { 585 return intoTableClause; 586 } 587 588 public void setSelectToken(TSourceToken selectToken) { 589 this.selectToken = selectToken; 590 } 591 592 /** 593 * 594 * @return SELECT token of this query. 595 */ 596 public TSourceToken getSelectToken() { 597 return selectToken; 598 } 599 600 private TSourceToken selectToken = null; 601 602 public static final int SET_OPERATOR_NONE = 0; 603 604 public static final int setOperator_union = 1; 605 public static final int setOperator_unionall = 2; 606 public static final int SET_OPERATOR_UNIONDISTINCT = 9; 607 608 public static final int setOperator_intersect = 3; 609 public static final int setOperator_intersectall = 4; 610 public static final int SET_OPERATOR_INTERSECTDISTINCT = 10; 611 612 public static final int setOperator_minus = 5; 613 public static final int setOperator_minusall = 6; 614 public static final int SET_OPERATOR_MINUSDISTINCT = 11; 615 616 public static final int setOperator_except = 7; 617 public static final int setOperator_exceptall = 8; 618 public static final int SET_OPERATOR_EXCEPTDISTINCT = 11; 619 620 public boolean isAll() { 621 return all; 622 } 623 624 private boolean all = false; 625 626 public boolean isSetOpDistinct() { 627 return setOpDistinct; 628 } 629 630 private boolean setOpDistinct = false; 631 private ESetOperatorType setOperatorType = ESetOperatorType.none; 632 633 public ESetOperatorType getSetOperatorType() { 634 return setOperatorType; 635 } 636 637 private TWindowClause windowClause; 638 639 /** 640 * 641 * @return {@link TWindowClause window clause.} 642 */ 643 public TWindowClause getWindowClause() { 644 return windowClause; 645 } 646 647 private TPTNodeList <TLockingClause> lockingClauses; 648 649 /** 650 * PostgreSQL, for update of, for read only. 651 * <br> 652 * @return list of {@link TLockingClause} 653 */ 654 public TPTNodeList<TLockingClause> getLockingClauses() { 655 return lockingClauses; 656 } 657 658 /** 659 * 660 * @return {@link TSelectDistinct distinct clause} 661 */ 662 public TSelectDistinct getSelectDistinct() { 663 return selectDistinct; 664 } 665 666 private TSelectDistinct selectDistinct = null; 667 668 /** 669 * 670 * @return {@link gudusoft.gsqlparser.nodes.TIntoClause into clause} 671 */ 672 public TIntoClause getIntoClause() { 673 return intoClause; 674 } 675 676 private TIntoClause intoClause = null; 677 678 679 private TOrderBy orderbyClause; 680 681 /** 682 * @return {@link TOrderBy order by clause} 683 */ 684 public TOrderBy getOrderbyClause() { 685 return orderbyClause; 686 } 687 688 public TSelectSqlStatement(EDbVendor dbvendor) { 689 super(dbvendor); 690 sqlstatementtype = ESqlStatementType.sstselect; 691 } 692 693 void buildsql() { 694 } 695 696 void clear() { 697 } 698 699 String getasprettytext() { 700 return ""; 701 } 702 703 void iterate(TVisitorAbs pvisitor) { 704 } 705 706 /** 707 * 708 * @return {@link TQualifyClause teradata qualify clause} 709 */ 710 public TQualifyClause getQualifyClause() { 711 return qualifyClause; 712 } 713 714 private TQualifyClause qualifyClause = null; 715 private TSampleClause sampleClause = null; 716 private TTeradataWithClause teradataWithClause = null; 717 718 /** 719 * @return {@link TTeradataWithClause Teradata with clause } 720 */ 721 public TTeradataWithClause getTeradataWithClause() { 722 return teradataWithClause; 723 } 724 725 /** 726 * 727 * @return {@link gudusoft.gsqlparser.nodes.TSampleClause SQL Server sample clause} 728 */ 729 public TSampleClause getSampleClause() { 730 return sampleClause; 731 } 732 733 /** 734 * @return {@link gudusoft.gsqlparser.nodes.TForUpdate for update clause} 735 */ 736 public TForUpdate getForUpdateClause() { 737 return forUpdateClause; 738 } 739 740 private TForUpdate forUpdateClause; 741 742 /** 743 * 744 * @return {@link TComputeClause SQL Server compute clause} 745 */ 746 public TComputeClause getComputeClause() { 747 return computeClause; 748 } 749 750 private TComputeClause computeClause = null; 751 752 /** 753 * @return {@link TGroupBy group by clause and having clause} 754 */ 755 public TGroupBy getGroupByClause() { 756 return groupByClause; 757 } 758 759 private TGroupBy groupByClause = null; 760 761 762 /** 763 * Oracle hierarchical_query_clause 764 * @return {@link gudusoft.gsqlparser.nodes.THierarchical Oracle hierarchical_query_clause} 765 */ 766 public THierarchical getHierarchicalClause() { 767 return hierarchicalClause; 768 } 769 770 private THierarchical hierarchicalClause = null; 771 772 /** 773 * MySQL,PostgreSQL limit clause 774 * @return {@link TLimitClause MySQL,PostgreSQL limit clause} 775 */ 776 public TLimitClause getLimitClause() { 777 return limitClause; 778 } 779 780 private TLimitClause limitClause = null; 781 782 783 private TExpandOnClause expandOnClause; 784 785 /** 786 * 787 * @return {@link TExpandOnClause Teradata expand on clause} 788 */ 789 public TExpandOnClause getExpandOnClause() { 790 return expandOnClause; 791 } 792 793 /** 794 * 795 * The set operators UNION, EXCEPT, and INTERSECT correspond to the relational operators union, difference, and intersection. 796 * @return set operator of this statement.If a set operator is not used, setOperator_none will be returned. 797 * otherwise, set operand can be fetched by using getLeftStmt() and getRightStmt(). 798 * 799 * @deprecated As of v1.6.4.2, use {@link #getSetOperatorType()} and {@link #isAll()} instead. 800 */ 801 public int getSetOperator() { 802 return setOperator; 803 } 804 805 private int setOperator = 0; 806 807 /** 808 * Valid when {@link #getSetOperator} is not setOperator_none. 809 * @return left side query expression 810 */ 811 public TSelectSqlStatement getLeftStmt() { 812 return leftStmt; 813 } 814 815 public TSelectSqlStatement getFarLeftStmt() { 816 TSelectSqlStatement current = leftStmt; 817 while (current.isCombinedQuery()) { 818 current = current.getLeftStmt(); 819 } 820 return current; 821 } 822 823 /** 824 * Valid when {@link #getSetOperator} is not setOperator_none. 825 * @return right side query expression. 826 */ 827 public TSelectSqlStatement getRightStmt() { 828 return rightStmt; 829 } 830 831 private TSelectSqlStatement leftStmt; 832 private TSelectSqlStatement rightStmt; 833 834 private TValueClause valueClause = null; 835 836 private String oracleHint; 837 838 private String hint; 839 840 private boolean isValueClause = false; 841 842 public boolean isValueClause() { 843 return isValueClause; 844 } 845 846 /** 847 * Hint for Oracle and MySQL 848 * 849 * @return hint string 850 */ 851 public String getHint() { 852 return hint; 853 } 854 855 /** 856 * Hint for Oracle and MySQL 857 * 858 * @return hint string. 859 */ 860 /** 861 * @deprecated As of 2.0.4.5, replaced by {@link #getHint()} 862 */ 863 public String getOracleHint() { 864 return oracleHint; 865 } 866 867 private THiveHintClause hiveHintClause; 868 869 /** 870 * 871 * @return {@link THiveHintClause Hive hint clause} 872 */ 873 public THiveHintClause getHiveHintClause() { 874 return hiveHintClause; 875 } 876 877 private THiveTransformClause transformClause; 878 879 /** 880 * 881 * @return {@link THiveTransformClause Hive from clause} 882 */ 883 public THiveTransformClause getTransformClause() { 884 return transformClause; 885 } 886 887 private TDistributeBy distributeBy; 888 889 /** 890 * 891 * @return {@link TDistributeBy Hive distribute by clause} 892 */ 893 public TDistributeBy getDistributeBy() { 894 return distributeBy; 895 } 896 897 /** 898 * DB2 value clause 899 * @return {@link TValueClause DB2 value clause} 900 */ 901 public TValueClause getValueClause() { 902 return valueClause; 903 } 904 905 public void setChildOfCombinedQuery(boolean childOfCombinedQuery) { 906 this.childOfCombinedQuery = childOfCombinedQuery; 907 } 908 909 public boolean isChildOfCombinedQuery() { 910 911 return childOfCombinedQuery; 912 } 913 914 private boolean childOfCombinedQuery = false; 915 916 917 @Override 918 public TreeMap<String,TResultColumn> getExpandedResultColumns() { 919 if (this.setOperatorType == ESetOperatorType.none){ 920 return super.getExpandedResultColumns(); 921 }else{ 922 return this.getLeftStmt().getExpandedResultColumns(); 923 } 924 } 925 926 private ArrayList<TSelectSqlStatement> flattenSelects = null; 927 928 public ArrayList<TSelectSqlStatement> getFlattenedSelects() { 929 if (!isCombinedQuery()) return null; 930 if (this.flattenSelects != null) return this.flattenSelects; 931 932 this.flattenSelects = new ArrayList<TSelectSqlStatement>(); 933 this.flattenSelects.add(this.rightStmt); 934 doFlattenCombinedSelect(this.leftStmt,this.flattenSelects); 935 936 Collections.reverse(this.flattenSelects); 937 return flattenSelects; 938 } 939 940 void doFlattenCombinedSelect(TSelectSqlStatement select, ArrayList<TSelectSqlStatement> container){ 941 TSelectSqlStatement current = select; 942 while (current.isCombinedQuery()){ 943 container.add(current.getRightStmt()); 944 current = current.getLeftStmt(); 945 } 946 container.add(current); 947 } 948 949 /** 950 * This function is used internal. DON'T call it explicitly. 951 * 952 * @param psql input query. 953 * @return zero means there is no syntax error detected. 954 */ 955 public int doParseStatement(TCustomSqlStatement psql) { 956 if (rootNode == null) return -1; 957 958 if ((rootNode instanceof TSelectSqlNode) 959 && (this.sourcetokenlist.size() == 0)){ 960 // subquery nested in other statements. 961 TSelectSqlNode selectNode = (TSelectSqlNode)rootNode; 962 this.setStartToken(selectNode.getStartToken()); 963 this.setEndToken(selectNode.getEndToken()); 964 } 965 966 super.doParseStatement(psql); 967 968 if (!(rootNode instanceof TSelectSqlNode)) { 969 return reportInvalidSelectStatement(); 970 } 971 972 TSelectSqlNode selectNode = (TSelectSqlNode)rootNode; 973 if (hasInvalidResultColumnList(selectNode, psql)) { 974 return reportInvalidSelectStatement(); 975 } 976 977 this.selectToken = selectNode.getSelectToken(); 978 parenthesisCount = selectNode.getParenthesisCount(); 979 parenthesisCountBeforeOrder = selectNode.getParenthissisCountBeforeOrder(); 980 981 setOperator = selectNode.getSetOperator(); 982 initSetOperatorFields(); 983 984 if(selectNode.isCombinedQuery()){ 985 TCustomSqlStatement lcParentSql = psql; 986 if ((lcParentSql == null)||(!childOfCombinedQuery)){ 987 lcParentSql = this; 988 } 989 990 if (selectNode.cteList != null){ 991 this.setCteList(selectNode.cteList); 992 for(int i=0;i<getCteList().size();i++){ 993 getCteList().getCTE(i).doParse(this,ESqlClause.cte); 994 } 995 } 996 997 // Oracle 12c WITH FUNCTION/PROCEDURE support 998 if (selectNode.getWithPlsqlItems() != null){ 999 this.setWithPlsqlItems(selectNode.getWithPlsqlItems()); 1000 } 1001 1002 // Iterative construction of the left-recursive UNION/INTERSECT/EXCEPT chain. 1003 // This avoids StackOverflow for queries with many set operations (e.g., 2000+ UNION ALL). 1004 // We collect the chain of combined query nodes, set up their properties top-down, 1005 // then process leaf children and clauses from deepest to shallowest. 1006 1007 ArrayList<TSelectSqlStatement> stmtChain = new ArrayList<>(); 1008 ArrayList<TSelectSqlNode> nodeChain = new ArrayList<>(); 1009 1010 stmtChain.add(this); 1011 nodeChain.add(selectNode); 1012 1013 TSelectSqlStatement currentStmt = this; 1014 TSelectSqlNode currentNode = selectNode; 1015 1016 // Walk down the left chain, creating intermediate TSelectSqlStatements 1017 while (currentNode.getLeftNode() != null && currentNode.getLeftNode().isCombinedQuery()) { 1018 TSelectSqlNode leftNode = currentNode.getLeftNode(); 1019 1020 TSelectSqlStatement nextStmt = new TSelectSqlStatement(dbvendor); 1021 nextStmt.rootNode = leftNode; 1022 nextStmt.setChildOfCombinedQuery(true); 1023 1024 // Wire up parent's leftStmt 1025 currentStmt.leftStmt = nextStmt; 1026 1027 // Inline common setup (equivalent of super.doParseStatement + field init) 1028 if (nextStmt.sourcetokenlist.size() == 0) { 1029 nextStmt.setStartToken(leftNode.getStartToken()); 1030 nextStmt.setEndToken(leftNode.getEndToken()); 1031 } 1032 // Equivalent of TCustomSqlStatement.doParseStatement(lcParentSql) 1033 nextStmt.setParentStmt(lcParentSql); 1034 nextStmt.setFrameStack(lcParentSql.getFrameStack()); 1035 lcParentSql.getStmtScope().incrementCurrentStmtIndex(); 1036 nextStmt.setQueryId(String.format("%s#stmt_%d_%s", 1037 lcParentSql.getQueryId(), 1038 lcParentSql.getStmtScope().getCurrentStmtIndex(), 1039 nextStmt.sqlstatementtype)); 1040 nextStmt.setStmtScope(new TStmtScope(lcParentSql.getStmtScope(), nextStmt)); 1041 if (nextStmt.getStartToken() == null && nextStmt.rootNode != null) { 1042 nextStmt.setStartToken(nextStmt.rootNode.getStartToken()); 1043 } 1044 if (nextStmt.getEndToken() == null && nextStmt.rootNode != null) { 1045 nextStmt.setEndToken(nextStmt.rootNode.getEndToken()); 1046 } 1047 if (nextStmt.getGsqlparser() == null && nextStmt.rootNode != null) { 1048 nextStmt.setGsqlparser(nextStmt.rootNode.getGsqlparser()); 1049 } 1050 1051 nextStmt.selectToken = leftNode.getSelectToken(); 1052 nextStmt.parenthesisCount = leftNode.getParenthesisCount(); 1053 nextStmt.parenthesisCountBeforeOrder = leftNode.getParenthissisCountBeforeOrder(); 1054 nextStmt.setOperator = leftNode.getSetOperator(); 1055 nextStmt.initSetOperatorFields(); 1056 1057 stmtChain.add(nextStmt); 1058 nodeChain.add(leftNode); 1059 1060 currentStmt = nextStmt; 1061 currentNode = leftNode; 1062 } 1063 1064 // Create and process the leftmost leaf (non-combined SELECT) 1065 TSelectSqlStatement leftmostLeaf = new TSelectSqlStatement(dbvendor); 1066 leftmostLeaf.rootNode = currentNode.getLeftNode(); 1067 leftmostLeaf.setChildOfCombinedQuery(true); 1068 currentStmt.leftStmt = leftmostLeaf; 1069 leftmostLeaf.doParseStatement(lcParentSql); 1070 1071 // Process right children and clauses from deepest to shallowest 1072 for (int i = stmtChain.size() - 1; i >= 0; i--) { 1073 TSelectSqlStatement stmt = stmtChain.get(i); 1074 TSelectSqlNode node = nodeChain.get(i); 1075 1076 // Create and process right child (always a leaf for left-recursive grammar) 1077 stmt.rightStmt = new TSelectSqlStatement(dbvendor); 1078 stmt.rightStmt.rootNode = node.getRightNode(); 1079 stmt.rightStmt.setChildOfCombinedQuery(true); 1080 stmt.rightStmt.doParseStatement(lcParentSql); 1081 1082 // Handle clauses for this level 1083 if (node.getOrderbyClause() != null) { 1084 node.getOrderbyClause().doParse(stmt, ESqlClause.orderby); 1085 stmt.orderbyClause = node.getOrderbyClause(); 1086 } 1087 stmt.limitClause = node.getLimitClause(); 1088 if (node.getForupdateClause() != null) { 1089 node.getForupdateClause().doParse(stmt, ESqlClause.forUpdate); 1090 stmt.forUpdateClause = node.getForupdateClause(); 1091 } 1092 if (node.getComputeClause() != null) { 1093 node.getComputeClause().doParse(stmt, ESqlClause.compute); 1094 stmt.computeClause = node.getComputeClause(); 1095 } 1096 stmt.optionClause = node.getOptionClause(); 1097 stmt.timeTravel = node.getTimeTravel(); 1098 stmt.hintClause = node.getHintClause(); 1099 } 1100 1101 return 0; 1102 } 1103 1104 if (selectNode.getValueClause() != null){ 1105 this.valueClause = selectNode.getValueClause(); 1106 this.valueClause.doParse(this,ESqlClause.selectValue); 1107 isValueClause = true; 1108 return 0; 1109 } 1110 1111 if (selectNode.getTransformClause() != null){ 1112 this.transformClause = selectNode.getTransformClause(); 1113 this.transformClause.doParse(this,ESqlClause.transformClause); 1114 } 1115 1116 if (selectNode.cteList != null){ 1117 this.setCteList(selectNode.cteList); 1118 this.getCteList().doParse(this,ESqlClause.cte); 1119 } 1120 1121 // Oracle 12c WITH FUNCTION/PROCEDURE support 1122 if (selectNode.getWithPlsqlItems() != null){ 1123 this.setWithPlsqlItems(selectNode.getWithPlsqlItems()); 1124 } 1125 1126 if (selectNode.isHiveFromQuery()){ 1127 if(selectNode.getSelectSqlNodes() != null){ 1128 for(int i=1;i<selectNode.getSelectSqlNodes().size();i++){ 1129 //start from the second, the first select statement is represented by this class instance. 1130 1131 TSelectSqlStatement select = new TSelectSqlStatement(EDbVendor.dbvhive); 1132 select.rootNode = selectNode.getSelectSqlNodes().get(i); 1133 select.doParseStatement(this); 1134 this.getMultiSelectStatements().add(select); 1135 } 1136 } 1137 1138 // Hive: from query insert... 1139// if (selectNode.getFromTableList() != null){ 1140// TFromTable lcFromTable; 1141// TJoin lcJoin; 1142// 1143// for(int i=0; i<selectNode.getFromTableList().size();i++){ 1144// lcFromTable = selectNode.getFromTableList().getFromTable(i); 1145// TTable lcTable = null; 1146// 1147// if (lcFromTable.getFromtableType() != ETableSource.join){ 1148// lcJoin = new TJoin(); 1149// lcTable = analyzeFromTable(lcFromTable,true); 1150// lcTable.setEffectType(ETableEffectType.tetSelect); 1151// lcJoin.setTable(lcTable); 1152// lcJoin.setStartToken(lcJoin.getTable().getStartToken()); 1153// lcJoin.setEndToken(lcJoin.getTable().getEndToken()); 1154// lcJoin.setGsqlparser(getGsqlparser()); 1155// }else{ 1156// lcJoin = analyzeJoin(lcFromTable.getJoinExpr(),null,true); 1157// lcJoin.doParse(this, ESqlClause.join); 1158// 1159// if (lcFromTable.getLateralViewList() != null){ 1160// for(TLateralView lateralView:lcFromTable.getLateralViewList()){ 1161// addToTables(lateralView.createATable(this)); 1162// } 1163// } 1164// } 1165// 1166// joins.addJoin(lcJoin); 1167// } 1168// } 1169 1170 1171// if (selectNode.getHiveBodyList() != null){ 1172// for(int i = 0; i<selectNode.getHiveBodyList().size();i++){ 1173// TParseTreeNode node1 = selectNode.getHiveBodyList().get(i); 1174// switch (node1.getNodeType()){ 1175// case TStatementSqlNode.select: 1176// TSelectSqlStatement select = new TSelectSqlStatement(EDbVendor.dbvhive); 1177// select.rootNode = node1; 1178// select.doParseStatement(this); 1179// this.getHiveBodyList().add(select); 1180// 1181// break; 1182// case TStatementSqlNode.insert: 1183// 1184// TInsertSqlStatement insert = new TInsertSqlStatement(EDbVendor.dbvhive); 1185// insert.rootNode = node1; 1186// insert.doParseStatement(this); 1187// this.getHiveBodyList().add(insert); 1188// break; 1189// default: 1190// break; 1191// } 1192// } 1193// } 1194 // return 0; 1195 } 1196 1197 // get oracle hint 1198 if((dbvendor == EDbVendor.dbvoracle)||(dbvendor == EDbVendor.dbvmysql)){ 1199 TSourceToken lcnextst = this.selectToken.container.nextsolidtoken(this.selectToken.posinlist,1,true); 1200 while (lcnextst != null){ 1201 if (!((lcnextst.tokentype == ETokenType.ttsimplecomment) || (lcnextst.tokentype == ETokenType.ttbracketedcomment))) break; 1202 1203 if (lcnextst.tokentype == ETokenType.ttbracketedcomment){ 1204 if (lcnextst.toString().startsWith("/*+")){ 1205 //lcnextst.setDbObjType(TObjectName.ttObjOracleHint); 1206 lcnextst.setDbObjectType(EDbObjectType.oracleHint); 1207 if (oracleHint == null){ 1208 oracleHint = lcnextst.toString(); 1209 }else { 1210 oracleHint = oracleHint + " " + lcnextst.toString(); 1211 } 1212 } 1213 } 1214 1215 if (lcnextst.tokentype == ETokenType.ttsimplecomment){ 1216 if (lcnextst.toString().startsWith("--+")){ 1217 //lcnextst.setDbObjType(TObjectName.ttObjOracleHint); 1218 lcnextst.setDbObjectType(EDbObjectType.oracleHint); 1219 if (oracleHint == null){ 1220 oracleHint = lcnextst.toString(); 1221 }else { 1222 oracleHint = oracleHint + " " + lcnextst.toString(); 1223 } 1224 } 1225 } 1226 1227 lcnextst = lcnextst.container.nextsolidtoken(lcnextst,1,true); 1228 } 1229 1230 hint = oracleHint; 1231 } 1232 1233 if (selectNode.getHiveHintClause() != null){ 1234 hiveHintClause = selectNode.getHiveHintClause(); 1235 } 1236 1237 isConsume = selectNode.isConsume(); 1238 1239 if (selectNode.getTopClause() != null){ 1240 selectNode.getTopClause().doParse(this,ESqlClause.top); 1241 this.setTopClause(selectNode.getTopClause()); 1242 } 1243 1244 // this.skipOffset = selectNode.getSkipOffset(); 1245// this.firstMax = selectNode.getFirstMax(); 1246// this.limitMax = selectNode.getLimitMax(); 1247 1248 if (selectNode.getSelectDistinct() != null){ 1249 this.selectDistinct = selectNode.getSelectDistinct(); 1250 } 1251 1252 this.selectModifiers = selectNode.getSelectModifiers(); 1253 1254 TFromTable lcFromTable = null; 1255 TJoin lcJoin = null; 1256 1257 if (selectNode.getFromTableList() != null){ 1258 fromClause = new TFromClause(this.getRelations()); 1259 fromClause.setStartToken(selectNode.getFromTableList().getStartToken()); 1260 fromClause.setEndToken(selectNode.getFromTableList().getEndToken()); 1261 1262 for(int i=0; i<selectNode.getFromTableList().size();i++){ 1263 lcFromTable = selectNode.getFromTableList().getFromTable(i); 1264 lcJoin = analyzeTableOrJoin(lcFromTable); 1265 joins.addJoin(lcJoin); 1266 } 1267 } 1268 1269 // ClickHouse expression-CTEs (WITH <expr> AS ident) are evaluated in 1270 // this statement's own scope, so their column references can only 1271 // link once the FROM clause above has populated tables — the 1272 // cteList.doParse earlier in this method runs before that. 1273 if ((dbvendor == EDbVendor.dbvclickhouse) && (this.getCteList() != null)){ 1274 for(int i=0;i<getCteList().size();i++){ 1275 TCTE lcCte = getCteList().getCTE(i); 1276 if (lcCte.getExpression() != null){ 1277 lcCte.getExpression().doParse(this,ESqlClause.cte); 1278 } 1279 } 1280 } 1281 1282 // Publish the hierarchical clause before the select list is parsed. 1283 // doParse() for the clause itself still runs in its usual place below; 1284 // this only makes getHierarchicalClause() answer truthfully while the 1285 // result columns are being linked, which is when 1286 // TCustomSqlStatement.isOraclePseudoColumnReference() needs to know 1287 // whether CONNECT_BY_ISLEAF / CONNECT_BY_ISCYCLE are pseudocolumns 1288 // here or ordinary identifiers (Mantis #4675). 1289 if (selectNode.getHierarchicalClause() != null){ 1290 this.hierarchicalClause = selectNode.getHierarchicalClause(); 1291 } 1292 1293 if (selectNode.getResultColumnList() != null){ 1294 this.setResultColumnList(selectNode.getResultColumnList()); 1295 1296// if ((this.getResultColumnList().size() > 10) 1297// &&(this.getTables().size() == 1) 1298// &&(this.getTables().getTable(0).getTableType() == ETableSource.subquery) 1299// &&( this.getTables().getTable(0).getSubquery().getResultColumnList().size() == this.getResultColumnList().size() ) 1300// ){ 1301// TTable t0 = this.getTables().getTable(0); 1302// ArrayList<TResultColumn> targetColumnArrayList = this.getResultColumnList().getSortedColumns(); 1303// ArrayList<TResultColumn> sourceColumnArrayList = t0.getSubquery().getResultColumnList().getSortedColumns(); 1304// int i=0; 1305// for(TResultColumn rc:targetColumnArrayList){ 1306// TObjectName targetColumn = rc.getExpr().getObjectOperand(); 1307// TResultColumn sourceResultColumn = sourceColumnArrayList.get(i++); 1308// //TObjectName sourceColumn = sourceResultColumn.getExpr().getObjectOperand(); 1309// if (targetColumn != null){ 1310// //System.out.println(targetColumn+"\t->\t"+sourceResultColumn.getDisplayName()); 1311// targetColumn.setSourceTable(t0); 1312// t0.getLinkedColumns().addObjectName(targetColumn); 1313// targetColumn.setSourceColumn(sourceResultColumn); 1314// sourceResultColumn.getTargetColumns().addObjectName(targetColumn); 1315// } 1316// } 1317// } 1318 1319 selectNode.getResultColumnList().doParse(this,ESqlClause.selectList); 1320 1321 // Slice 73: link DISTINCT ON expression list (PostgreSQL / 1322 // Greenplum `SELECT DISTINCT ON (cols) ...`) so each 1323 // TObjectName inside gets dbObjectType=column and 1324 // sourceTable populated. Without this, the expressions 1325 // remain EDbObjectType.unknown. The legacy column-linker 1326 // (linkColumnToTable) is invoked here via TExpression.doParse; 1327 // resolver-2 picks the same expressions up via the 1328 // TSelectDistinct.acceptChildren descent that slice 73 1329 // also wires up. Tables are populated by the FROM clause 1330 // loop above so column linking has a relation list to 1331 // resolve against. Mirrors the TGroupBy.doParse → 1332 // items.doParse pattern. 1333 if (this.selectDistinct != null 1334 && this.selectDistinct.getExpressionList() != null) { 1335 TExpressionList distinctOnExprList = 1336 this.selectDistinct.getExpressionList(); 1337 for (int i = 0; i < distinctOnExprList.size(); i++) { 1338 TExpression e = distinctOnExprList.getExpression(i); 1339 if (e != null) { 1340 e.doParse(this, ESqlClause.unknown); 1341 } 1342 } 1343 } 1344 1345 for(int i=0;i<selectNode.getResultColumnList().size();i++){ 1346 TResultColumn resultColumn = selectNode.getResultColumnList().getResultColumn(i); 1347 TExpression expression = resultColumn.getExpr(); 1348 String expressionText = expression.toString(); 1349 if (expressionText.endsWith("*")){ 1350 TTable starSourceTable = null; 1351 //System.out.println(resultColumn.toString()+":"+resultColumn.getStartToken().lineNo+","+resultColumn.getStartToken().columnNo); 1352 if (expressionText.startsWith("*")){ 1353 // add all result columns in from tables 1354 for(int j=0;j<getTables().size();j++){ 1355 if (getTables().getTable(j).getTableType() == ETableSource.subquery){ 1356 getExpandedResultColumns().putAll(getTables().getTable(j).getSubquery().getExpandedResultColumns()); 1357 }else{ 1358 // ToDo for real table 1359 } 1360 //System.out.println("\t"+getTables().getTable(j).toString()+",\t"+getTables().getTable(j).getTableType()+",\t"+getTables().getTable(j).isCTEName()); 1361 } 1362 if (getTables().size() == 1){ 1363 starSourceTable = getTables().getTable(0); 1364 } 1365 1366 }else{ 1367 for(int j=0;j<getTables().size();j++){ 1368 if (getTables().getTable(j).getAliasName().equalsIgnoreCase( resultColumn.toString().split("[.]")[0])){ 1369 if (getTables().getTable(j).getTableType() == ETableSource.subquery){ 1370 getExpandedResultColumns().putAll(getTables().getTable(j).getSubquery().getExpandedResultColumns()); 1371 }else{ 1372 // ToDo for real table 1373 } 1374 starSourceTable = getTables().getTable(j); 1375 break; 1376 } 1377 } 1378 } 1379 if (starSourceTable != null) { 1380 TObjectName objectOperand = expression.getObjectOperand(); 1381 if (objectOperand == null) { 1382 return reportInvalidSelectStatement(); 1383 } 1384 objectOperand.setSourceTable(starSourceTable); 1385 } 1386 }else{ 1387 String expandedKey = IdentifierService.normalizeStatic(this.dbvendor, ESQLDataObjectType.dotColumn,resultColumn.getDisplayName()); 1388 if (expandedKey == null){ 1389 return reportInvalidSelectStatement(); 1390 } 1391 getExpandedResultColumns().put(expandedKey,resultColumn); 1392 } 1393 } 1394 } 1395 1396 if (selectNode.getIntoClause() != null){ 1397 this.intoClause = selectNode.getIntoClause(); 1398 this.intoClause.doParse(this,ESqlClause.selectInto); 1399 } 1400 1401 1402 if (selectNode.getWhereCondition() != null){ 1403 selectNode.getWhereCondition().doParse(this,ESqlClause.where); 1404 this.setWhereClause( selectNode.getWhereCondition()); 1405 } 1406 1407 if (selectNode.getHierarchicalClause() != null){ 1408 selectNode.getHierarchicalClause().doParse(this,ESqlClause.hierarchical); 1409 this.hierarchicalClause = selectNode.getHierarchicalClause(); 1410 } 1411 1412 if (selectNode.getGroupByClause() != null){ 1413 selectNode.getGroupByClause().doParse(this,ESqlClause.groupby); 1414 this.groupByClause = selectNode.getGroupByClause(); 1415 } 1416 1417 if (selectNode.getQualifyClause() != null){ 1418 selectNode.getQualifyClause().doParse(this,ESqlClause.qualify); 1419 this.qualifyClause = selectNode.getQualifyClause(); 1420 } 1421 1422 if (selectNode.getSampleClause() != null){ 1423 selectNode.getSampleClause().doParse(this,ESqlClause.sample); 1424 this.sampleClause = selectNode.getSampleClause(); 1425 } 1426 1427 if (selectNode.getExpandOnClause() != null){ 1428 selectNode.getExpandOnClause().doParse(this,ESqlClause.expandOn); 1429 this.expandOnClause = selectNode.getExpandOnClause(); 1430 } 1431 1432 if (selectNode.getWithClause() != null){ 1433 selectNode.getWithClause().doParse(this,ESqlClause.teradataWith); 1434 this.teradataWithClause = selectNode.getWithClause(); 1435 } 1436 1437 if (selectNode.getOrderbyClause() != null){ 1438 selectNode.getOrderbyClause().doParse(this,ESqlClause.orderby); 1439 this.orderbyClause = selectNode.getOrderbyClause(); 1440 } 1441 1442 if (selectNode.getLockingClauses() != null){ 1443 selectNode.getLockingClauses().doParse(this,ESqlClause.lockingClause); 1444 this.lockingClauses = selectNode.getLockingClauses(); 1445 } 1446 1447 this.sortBy = selectNode.getSortBy(); 1448 if (this.sortBy != null){ 1449 this.sortBy.doParse(this,ESqlClause.sortby); 1450 } 1451 1452 this.clusterBy = selectNode.getClusterBy(); 1453 if (this.clusterBy != null){ 1454 this.clusterBy.doParse(this,ESqlClause.cluster); 1455 } 1456 1457 this.windowClause = selectNode.getWindowClause(); 1458 if (this.windowClause != null){ 1459 this.windowClause.doParse(this,ESqlClause.windowClause); 1460 } 1461 this.limitClause = selectNode.getLimitClause(); 1462 if (this.limitClause != null){ 1463 this.limitClause.doParse(this,ESqlClause.limit); 1464 } 1465 1466 if (selectNode.getForupdateClause() != null){ 1467 selectNode.getForupdateClause().doParse(this,ESqlClause.forUpdate); 1468 this.forUpdateClause = selectNode.getForupdateClause(); 1469 } 1470 1471 if (selectNode.getComputeClause() != null){ 1472 selectNode.getComputeClause().doParse(this,ESqlClause.compute); 1473 this.computeClause = selectNode.getComputeClause(); 1474 } 1475 1476 this.intoTableClause = selectNode.getIntoTableClause(); 1477 1478 if (selectNode.getDistributeBy() != null){ 1479 this.distributeBy = selectNode.getDistributeBy(); 1480 this.distributeBy.doParse(this,ESqlClause.distributeBy); 1481 } 1482 1483 1484 this.isolationClause = selectNode.getIsolationClause(); 1485 1486 this.optionClause = selectNode.getOptionClause(); 1487 1488 this.offsetClause = selectNode.getOffsetClause(); 1489 this.fetchFirstClause = selectNode.getFetchFirstClause(); 1490 1491 this.timeTravel = selectNode.getTimeTravel(); 1492 this.hintClause = selectNode.getHintClause(); 1493 1494 if (selectNode.getForXMLClause() != null){ 1495 if (tables.size() > 0){ 1496 tables.getTable(0).setForXMLClause(selectNode.getForXMLClause()); 1497 } 1498 } 1499 1500 // StarRocks pipe operator support 1501 this.pipeOperators = selectNode.getPipeOperators(); 1502 this.isPipeQuery = selectNode.isPipeQuery(); 1503 1504 return 0; 1505 } 1506 1507 private boolean hasInvalidResultColumnList(TSelectSqlNode selectNode, 1508 TCustomSqlStatement psql) { 1509 TResultColumnList resultColumns = selectNode.getResultColumnList(); 1510 if (resultColumns == null) { 1511 return false; 1512 } 1513 1514 for (int i = 0; i < resultColumns.size(); i++) { 1515 TResultColumn resultColumn = resultColumns.getResultColumn(i); 1516 if ((resultColumn == null) || (resultColumn.getExpr() == null)) { 1517 return true; 1518 } 1519 1520 TExpression expression = resultColumn.getExpr(); 1521 String expressionText = expression.toString(); 1522 if (expressionText == null) { 1523 return true; 1524 } 1525 if (!expressionText.endsWith("*") 1526 && (resultColumn.getDisplayName() == null)) { 1527 return true; 1528 } 1529 } 1530 1531 if (((dbvendor == EDbVendor.dbvmssql) 1532 || (dbvendor == EDbVendor.dbvoracle)) 1533 && (psql instanceof TInsertSqlStatement) 1534 && (resultColumns.getEndToken() != null) 1535 && (resultColumns.getEndToken().container != null)) { 1536 TSourceToken resultListEnd = resultColumns.getEndToken(); 1537 TSourceToken nextToken = resultListEnd.container 1538 .nextsolidtoken(resultListEnd, 1, true); 1539 if ((nextToken != null) && (nextToken.tokencode == ',')) { 1540 TSourceToken tokenAfterComma = nextToken.container 1541 .nextsolidtoken(nextToken, 1, true); 1542 if ((tokenAfterComma != null) 1543 && (tokenAfterComma.tokencode == TBaseType.rrw_from)) { 1544 return true; 1545 } 1546 } 1547 } 1548 1549 return false; 1550 } 1551 1552 private int reportInvalidSelectStatement() { 1553 TSourceToken errorToken = rootNode.getStartToken(); 1554 if ((errorToken == null) && (sourcetokenlist.size() > 0)) { 1555 errorToken = sourcetokenlist.get(0); 1556 } 1557 if (errorToken != null) { 1558 parseerrormessagehandle(new TSyntaxError(errorToken, 1559 "invalid SELECT statement", EErrorType.sperror, 1560 TBaseType.MSG_ERROR_SYNTAX_ERROR, this)); 1561 } else { 1562 parseerrormessagehandle(new TSyntaxError("SELECT", 0, 0, 1563 "invalid SELECT statement", EErrorType.sperror, 1564 TBaseType.MSG_ERROR_SYNTAX_ERROR, this, -1)); 1565 } 1566 return TBaseType.MSG_ERROR_SYNTAX_ERROR; 1567 } 1568 1569 /** 1570 * Determine whether The UNION, EXCEPT and INTERSECT operators were used. 1571 * @return true if one of those operators were used. 1572 */ 1573 public boolean isCombinedQuery(){ 1574 // combine multiple queries using the set operators UNION, UNION ALL, INTERSECT, and MINUS. 1575 return (setOperator > 0); 1576 } 1577 1578 /** 1579 * Initialize setOperatorType, all, and setOpDistinct fields from setOperator value. 1580 * Used by doParseStatement's iterative combined query construction. 1581 */ 1582 private void initSetOperatorFields() { 1583 switch (setOperator) { 1584 case SET_OPERATOR_NONE: 1585 setOperatorType = ESetOperatorType.none; all = false; break; 1586 case setOperator_union: 1587 setOperatorType = ESetOperatorType.union; all = false; break; 1588 case setOperator_unionall: 1589 setOperatorType = ESetOperatorType.union; all = true; break; 1590 case SET_OPERATOR_UNIONDISTINCT: 1591 setOperatorType = ESetOperatorType.union; setOpDistinct = true; break; 1592 case setOperator_intersect: 1593 setOperatorType = ESetOperatorType.intersect; all = false; break; 1594 case setOperator_intersectall: 1595 setOperatorType = ESetOperatorType.intersect; all = true; break; 1596 case setOperator_except: 1597 setOperatorType = ESetOperatorType.except; all = false; break; 1598 case setOperator_exceptall: 1599 setOperatorType = ESetOperatorType.except; all = true; break; 1600 case setOperator_minus: 1601 setOperatorType = ESetOperatorType.minus; all = false; break; 1602 case setOperator_minusall: 1603 setOperatorType = ESetOperatorType.minus; all = true; break; 1604 case SET_OPERATOR_INTERSECTDISTINCT: 1605 setOperatorType = ESetOperatorType.intersect; setOpDistinct = true; break; 1606 case SET_OPERATOR_EXCEPTDISTINCT: 1607 setOperatorType = ESetOperatorType.except; setOpDistinct = true; break; 1608 } 1609 } 1610 1611 public void accept(TParseTreeVisitor v) 1612 { 1613 v.preVisit(this); 1614 v.postVisit(this); 1615 } 1616 1617 /** 1618 * Accept visitor to visit this class. 1619 * @param v user defined visitor. 1620 */ 1621 public void acceptChildren(TParseTreeVisitor v) 1622 { 1623 1624 if(this.isCombinedQuery()){ 1625 1626 // Iterative traversal for combined queries to avoid StackOverflow 1627 // on deeply nested left-recursive UNION/INTERSECT/EXCEPT chains. 1628 // Collect the left-recursive chain of combined query nodes. 1629 ArrayList<TSelectSqlStatement> chain = new ArrayList<>(); 1630 TSelectSqlStatement current = this; 1631 while (current.isCombinedQuery()) { 1632 chain.add(current); 1633 current = current.getLeftStmt(); 1634 } 1635 // 'current' is now the leftmost leaf (non-combined SELECT) 1636 1637 // Phase 1: preVisit all combined nodes and their CTEs, from root to deepest 1638 for (int i = 0; i < chain.size(); i++) { 1639 TSelectSqlStatement node = chain.get(i); 1640 v.preVisit(node); 1641 if (node.getCteList() != null) { 1642 node.getCteList().acceptChildren(v); 1643 } 1644 } 1645 1646 // Phase 2: Visit leftmost leaf SELECT 1647 current.acceptChildren(v); 1648 1649 // Phase 3: Visit right branches and postVisit, from deepest to root 1650 for (int i = chain.size() - 1; i >= 0; i--) { 1651 TSelectSqlStatement node = chain.get(i); 1652 node.getRightStmt().acceptChildren(v); 1653 1654 if (node.getOrderbyClause() != null) { 1655 node.getOrderbyClause().acceptChildren(v); 1656 } 1657 if (node.getLimitClause() != null) { 1658 node.getLimitClause().acceptChildren(v); 1659 } 1660 if (node.getForUpdateClause() != null) { 1661 node.getForUpdateClause().acceptChildren(v); 1662 } 1663 if (node.getComputeClause() != null) { 1664 node.getComputeClause().acceptChildren(v); 1665 } 1666 v.postVisit(node); 1667 } 1668 1669 return ; 1670 } 1671 1672 // System.out.println(this.toString().hashCode()+" "+ this.toString().substring(0,50)); 1673 1674 v.preVisit(this); 1675 1676 if (this.getTransformClause() != null){ 1677 this.getTransformClause().acceptChildren(v); 1678 } 1679 1680 if (this.getCteList() != null){ 1681 this.getCteList().acceptChildren(v); 1682 } 1683 1684 if (TBaseType.USE_JOINEXPR_INSTEAD_OF_JOIN){ 1685// fromClause.acceptChildren(v); 1686 v.preVisit(fromClause); 1687 for(TTable table:getRelations()){ 1688 table.acceptChildren(v); 1689 } 1690 v.postVisit(fromClause); 1691 }else{ 1692 if (this.getJoins() != null){ 1693 this.getJoins().acceptChildren(v); 1694 } 1695 } 1696 1697 if (this.getHiveHintClause() != null){ 1698 this.getHiveHintClause().acceptChildren(v); 1699 } 1700 1701 1702 if (this.getTopClause() != null){ 1703 this.getTopClause().acceptChildren(v); 1704 } 1705 1706 if (this.getSelectDistinct() != null){ 1707 this.getSelectDistinct().acceptChildren(v); 1708 } 1709 1710 if (this.getResultColumnList() != null){ 1711 this.getResultColumnList().acceptChildren(v); 1712 } 1713 1714 if (this.getIntoClause() != null){ 1715 this.getIntoClause().acceptChildren(v); 1716 } 1717 1718 1719 if (this.getWhereClause() != null){ 1720 this.getWhereClause().acceptChildren(v); 1721 } 1722 1723 if (this.getHierarchicalClause() != null){ 1724 this.getHierarchicalClause().acceptChildren(v); 1725 } 1726 1727 if (this.getGroupByClause() != null){ 1728 this.getGroupByClause().acceptChildren(v); 1729 } 1730 1731 if (this.getQualifyClause() != null){ 1732 this.getQualifyClause().acceptChildren(v); 1733 } 1734 1735 if (this.getSampleClause() != null){ 1736 this.getSampleClause().acceptChildren(v); 1737 } 1738 1739 if (this.getExpandOnClause() != null){ 1740 this.getExpandOnClause().acceptChildren(v); 1741 } 1742 1743 if (this.getTeradataWithClause() != null){ 1744 this.getTeradataWithClause().acceptChildren(v); 1745 } 1746 1747 if (this.getOrderbyClause() != null){ 1748 this.getOrderbyClause().acceptChildren(v); 1749 } 1750 1751 if (this.getLockingClauses() != null){ 1752 this.getLockingClauses().acceptChildren(v); 1753 } 1754 1755 if (this.getSortBy() != null){ 1756 this.getSortBy().acceptChildren(v); 1757 } 1758 1759 if (this.getClusterBy() != null){ 1760 this.getClusterBy().acceptChildren(v); 1761 } 1762 1763 if (this.getWindowClause() != null){ 1764 this.getWindowClause().acceptChildren(v); 1765 } 1766 1767 if (this.getLimitClause() != null){ 1768 this.getLimitClause().acceptChildren(v); 1769 } 1770 1771 if (this.getForUpdateClause() != null){ 1772 this.getForUpdateClause().acceptChildren(v); 1773 } 1774 1775 if (this.getComputeClause() != null){ 1776 this.getComputeClause().acceptChildren(v); 1777 } 1778 1779 if (this.getIntoTableClause() != null){ 1780 this.getIntoTableClause().acceptChildren(v); 1781 } 1782 1783 if (this.getDistributeBy() != null){ 1784 this.getDistributeBy().acceptChildren(v); 1785 } 1786 1787 if (this.getIsolationClause() != null){ 1788 this.getIsolationClause().acceptChildren(v); 1789 } 1790 1791 if (this.getOptionClause() != null){ 1792 this.getOptionClause().acceptChildren(v); 1793 } 1794 1795 if (this.getOffsetClause() != null){ 1796 this.getOffsetClause().acceptChildren(v); 1797 } 1798 1799 if (this.getFetchFirstClause() != null){ 1800 this.getFetchFirstClause().acceptChildren(v); 1801 } 1802 1803 if (this.getTimeTravel() != null){ 1804 this.getTimeTravel().acceptChildren(v); 1805 } 1806 1807 if (this.getHintClause() != null){ 1808 this.getHintClause().acceptChildren(v); 1809 } 1810 1811 v.postVisit(this); 1812 return ; 1813 1814 }; 1815 1816 /** 1817 * Add an order by clause to this class. 1818 * @param orderByStr new order by string 1819 * @return added order by clause. 1820 */ 1821 public TOrderBy addOrderBy(String orderByStr){ 1822 if (this.getOrderbyClause() != null){ 1823 this.getOrderbyClause().addOrderByItem(orderByStr); 1824 }else{ 1825 1826 TOrderBy orderBy = new TOrderBy(); 1827 orderBy.setGsqlparser(this.getGsqlparser()); 1828 orderBy.setString(" order by "+orderByStr); 1829 this.orderbyClause = orderBy; 1830 TSourceToken last_token = null; 1831 if (this.getGroupByClause() != null){ 1832 last_token = this.getGroupByClause().getEndToken(); 1833 }else if (this.getWhereClause() != null){ 1834 last_token = this.getWhereClause().getEndToken(); 1835 }else{ 1836 last_token = joins.getEndToken(); 1837 } 1838 1839 orderbyClause.addAllMyTokensToTokenList(last_token.container, last_token.posinlist+1); 1840 1841 for(int i=0;i<last_token.getNodesEndWithThisToken().size();i++){ 1842 TParseTreeNode node = last_token.getNodesEndWithThisToken().get(i); 1843 if (node instanceof TSelectSqlStatement) 1844 { 1845 // change all end token of parse tree node except the last order by item 1846 node.setEndToken(orderbyClause.getEndToken()); 1847 } 1848 } 1849 } 1850 1851 return this.getOrderbyClause(); 1852 } 1853 1854 /** 1855 * this function is alias of addWhereClause 1856 * @param condition new condition 1857 * @return new where clause 1858 */ 1859 public TWhereClause addCondition(String condition){ 1860 return addWhereClause(condition); 1861 } 1862 1863 public TWhereClause addConditionOR(String condition){ 1864 return addWhereClauseOR(condition); 1865 } 1866 1867 public TWhereClause addWhereClause(String condition){ 1868 return doAddWhereClause(condition,true); 1869 } 1870 1871 public TWhereClause addWhereClauseOR(String condition){ 1872 return doAddWhereClause(condition,false); 1873 } 1874 1875 protected TWhereClause doAddWhereClause(String condition, boolean isAnd){ 1876 1877 if (this.getWhereClause() != null){ 1878 if (isAnd){ 1879 this.getWhereClause().getCondition().addANDCondition(condition); 1880 }else{ 1881 this.getWhereClause().getCondition().addORCondition(condition); 1882 } 1883 1884 }else{ 1885 TWhereClause whereClause = new TWhereClause(); 1886 whereClause.setGsqlparser(this.getGsqlparser()); 1887 whereClause.setString(" where "+condition); 1888 this.setWhereClause(whereClause); 1889 1890 TSourceToken last_token = null; 1891 TJoin lastjoin = joins.getJoin(joins.size()-1); 1892 if (lastjoin.getJoinItems().size() > 0){ 1893 TJoinItem lastitem = lastjoin.getJoinItems().getJoinItem(lastjoin.getJoinItems().size()-1); 1894 last_token = lastitem.getEndToken(); 1895 }else { 1896 last_token = joins.getEndToken(); 1897 } 1898 1899 whereClause.addAllMyTokensToTokenList(last_token.container, last_token.posinlist+1); 1900 1901 for(int i=0;i<last_token.getNodesEndWithThisToken().size();i++){ 1902 TParseTreeNode node = last_token.getNodesEndWithThisToken().get(i); 1903 if (!((node instanceof TJoinList) 1904 ||(node instanceof TJoin) 1905 ||(node instanceof TJoinItemList) 1906 ||(node instanceof TJoinItem) 1907 )) 1908 { 1909 // change all end token of parse tree node except the last order by item 1910 node.setEndToken(whereClause.getEndToken()); 1911 } 1912 } 1913 1914 } 1915 return this.getWhereClause(); 1916 } 1917 1918 private ArrayList<String> columnsInFromClause = null; 1919 1920 1921 @Override 1922 public TFromClause getFromClause() { 1923 // #todo , select union 类型的 sql 语句,需要穿透到低层的各个 子 select 语句,需要进一步完善 1924 TFromClause ret = super.getFromClause(); 1925 if ((ret == null)&&(isCombinedQuery()&&(this.getRightStmt()!=null))){ 1926 return this.getRightStmt().getFromClause(); 1927 }else{ 1928 return ret; 1929 } 1930 } 1931 1932 public TResultColumnList getResultColumnList(boolean useColumnsFromLeftmost) { 1933 TResultColumnList ret = super.getResultColumnList(); 1934 if (ret != null) return ret; 1935 1936 if (isCombinedQuery()){ 1937 if (useColumnsFromLeftmost) { 1938 return this.getFarLeftStmt().getResultColumnList(); 1939 } else { 1940 return this.getRightStmt().getResultColumnList(); 1941 } 1942 } 1943 return ret; 1944 1945 1946// if ((ret == null)&&(isCombinedQuery()&&(this.getRightStmt()!=null))){ 1947// return this.getRightStmt().getResultColumnList(); 1948// }else{ 1949// return ret; 1950// } 1951 } 1952 1953 @Override 1954 public TResultColumnList getResultColumnList() { 1955 return getResultColumnList(false); 1956 1957// TResultColumnList ret = super.getResultColumnList(); 1958// if ((ret == null)&&(isCombinedQuery()&&(this.getRightStmt()!=null))){ 1959// return this.getRightStmt().getResultColumnList(); 1960// }else{ 1961// return ret; 1962// } 1963 } 1964 1965 public ArrayList<String> getColumnsInFromClause() { 1966 if (columnsInFromClause != null) return columnsInFromClause; 1967 columnsInFromClause = new ArrayList<String>(); 1968 TTable lcTable; 1969 for(int j=0;j<tables.size();j++){ 1970 lcTable = tables.getTable(j); 1971 switch (lcTable.getTableType()){ 1972 case objectname: 1973 break; 1974 case subquery: 1975 TSelectSqlStatement subQuery = lcTable.getSubquery(); 1976 if (subQuery.getResultColumnList() != null) 1977 for(int i=0;i<subQuery.getResultColumnList().size();i++){ 1978 TResultColumn resultColumn = subQuery.getResultColumnList().getResultColumn(i); 1979 String aliasName = null; 1980 if (resultColumn.getAliasClause() != null){ 1981 aliasName = resultColumn.getAliasClause().getAliasName().toString(); 1982 }else{ 1983 if (resultColumn.getExpr().getObjectOperand() != null){ 1984 aliasName = resultColumn.getExpr().getObjectOperand().toString(); 1985 } 1986 } 1987 if (aliasName != null){ 1988 columnsInFromClause.add(TSQLEnv.getObjectName(aliasName)); 1989 } 1990 } 1991 break; 1992 } 1993 } 1994 return columnsInFromClause; 1995 } 1996 1997 public void addColumnInSelectListToSQLEnv(TSQLTable sqlTable){ 1998 1999 if (sqlTable == null) return; 2000 if (this.getValueClause() != null) return; 2001 2002 if (this.getResultColumnList() != null) 2003 for(int i=0;i<this.getResultColumnList().size();i++){ 2004 TResultColumn resultColumn = this.getResultColumnList().getResultColumn(i); 2005 String aliasName = null; 2006 if (resultColumn.getAliasClause() != null){ 2007 aliasName = resultColumn.getAliasClause().getAliasName().toString(); 2008 }else{ 2009 if (resultColumn.getExpr().getObjectOperand() != null){ 2010 aliasName = resultColumn.getExpr().getObjectOperand().toString(); 2011 } 2012 } 2013 if (aliasName != null){ 2014 sqlTable.addColumn(TSQLEnv.getObjectName(aliasName)); 2015 } 2016 } 2017 } 2018 2019 /** 2020 * search column in the select list 2021 * 2022 * Internal function, DON'T call it explicitly. 2023 * @param pColumn 2024 * @param pMustIn 2025 * @return true if found. 2026 */ 2027 public boolean searchColumnInResultSet(TObjectName pColumn,boolean pMustIn){ 2028 boolean lcResult = false; 2029 int candidateTableCnt = 0; 2030 int numOfColumnStar = 0; 2031 TResultColumn columnStar = null; 2032 2033 2034 2035 TResultColumn c = null; 2036 String lookupKey = IdentifierService.normalizeStatic(this.dbvendor, ESQLDataObjectType.dotColumn,pColumn.getColumnNameOnly()); 2037 if ( (lookupKey != null) && (c= this.getExpandedResultColumns().get(lookupKey)) != null) 2038 { 2039 //System.out.println("Found:"+pColumn.toString()); 2040 pColumn.setSourceColumn(c); 2041 c.getTargetColumns().addObjectName(pColumn); 2042 2043 return true; 2044 }else{ 2045 // System.out.println("NotCatch:"+pColumn.toString()); 2046 } 2047 2048 if (isCombinedQuery()){ 2049 boolean lcResult1;//,lcResult2; 2050 // search column in all select 2051 lcResult1 = getFarLeftStmt().searchColumnInResultSet(pColumn,pMustIn); 2052 if (!lcResult1) 2053 lcResult1 = rightStmt.searchColumnInResultSet(pColumn,pMustIn); 2054 return lcResult1; 2055 } 2056 2057 if (getResultColumnList() == null) return false; 2058 2059 if (pColumn.toString().endsWith("*")){ 2060 // pColumn here is o1.* 2061 // select o1.*, o2.c1 2062 // from (select c123, c345 from some_table) o1, other_table o2 2063 pColumn.setColumnsLinkedToStar(this.getResultColumnList()); 2064 return true; 2065 } 2066 2067 // search columns in select list, skip t.* but count it for later use 2068 for(int i=0;i<getResultColumnList().size();i++){ 2069 TResultColumn lcField = getResultColumnList().getResultColumn(i); 2070 if (lcField.toString().endsWith("*")){ 2071 numOfColumnStar++; 2072 columnStar = lcField; 2073 continue; 2074 } 2075 lcResult = lcField.isMatchedWithResultColumn(this.dbvendor, pColumn); 2076 if (lcResult){ 2077 pColumn.setSourceColumn(lcField); 2078 lcField.getTargetColumns().addObjectName(pColumn); 2079 break; 2080 } 2081 } 2082 2083 if (lcResult) return true; 2084 2085// // search in * column, including t.* and * 2086 for(int i=0;i<getResultColumnList().size();i++){ 2087 TResultColumn lcField = getResultColumnList().getResultColumn(i); 2088 if (lcField.toString().endsWith("*")){ 2089 // search column in t.*, have to check column in table t 2090 String prefixTableName = ""; 2091 if (lcField.toString().endsWith(".*")){ 2092 String[] a = lcField.toString().split("[.]"); 2093 prefixTableName = a[a.length - 2]; 2094 } 2095 for(int j=0;j<tables.size();j++){ 2096 lcResult = tables.getTable(j).searchColumn(this,prefixTableName,pColumn,false); 2097 if (lcResult) { 2098// tables.getTable(j).getLinkedColumns().addObjectName(pColumn); 2099// pColumn.setSourceTable(tables.getTable(j)); 2100 pColumn.setSourceColumn(lcField); 2101 lcField.getTargetColumns().addObjectName(pColumn); 2102 break; 2103 } 2104 } 2105 }else{ 2106 continue; 2107 } 2108 if (lcResult) break; 2109 } 2110 2111 if (lcResult) return true; 2112 2113 if (pMustIn){ 2114 if (tables.size() == 1){ // only a single table in from clause 2115 lcResult = true; 2116 boolean inStarColumn = false; 2117// tables.getTable(0).getLinkedColumns().addObjectName(pColumn); 2118// pColumn.setSourceTable(tables.getTable(0)); 2119 for(int i=0;i<getResultColumnList().size();i++) { 2120 TResultColumn lcField = getResultColumnList().getResultColumn(i); 2121 if (lcField.toString().endsWith("*")) { 2122 String prefixTableName = ""; 2123 if (lcField.toString().endsWith(".*")){ 2124 String[] a = lcField.toString().split("[.]"); 2125 prefixTableName = a[a.length - 2]; 2126 } 2127 tables.getTable(0).searchColumn(this,prefixTableName,pColumn,true); 2128 pColumn.setSourceColumn(lcField); 2129 lcField.getTargetColumns().addObjectName(pColumn); 2130 inStarColumn = true; 2131 break; 2132 } 2133 } 2134 if (!inStarColumn){ 2135 2136 if (!locateVariableOrParameter(pColumn)){ 2137 // check variable before raise error 2138 2139 // raise 2140 TSyntaxError err = new TSyntaxError(pColumn.getStartToken().toString() 2141 ,pColumn.getStartToken().lineNo,pColumn.getStartToken().columnNo 2142 ,String.format("Column %s is not found in subquery",pColumn.toString()) 2143 ,EErrorType.sphint ,TBaseType.MSG_ERROR_COLUMN_NOT_FOUND,this,pColumn.getStartToken().posinlist); 2144 this.parseerrormessagehandle( err); 2145 } 2146 2147 } 2148 }else if (numOfColumnStar == 1){// only a single * column in select list, but more than one table in from clause 2149 2150 pColumn.setSourceColumn(columnStar); 2151 columnStar.getTargetColumns().addObjectName(pColumn); 2152 if (columnStar.toString().endsWith(".*")){ 2153 lcResult = true; 2154 String[] a = columnStar.toString().split("[.]"); 2155 String prefixTableName = a[a.length - 2]; 2156 for(int i=0;i<tables.size();i++){ 2157 if (tables.getTable(i).checkTableByName(prefixTableName)){ 2158 tables.getTable(i).searchColumn(this,prefixTableName,pColumn,true); 2159// tables.getTable(i).getLinkedColumns().addObjectName(pColumn); 2160// pColumn.setSourceTable(tables.getTable(i)); 2161 pColumn.setSourceColumn(columnStar); 2162 columnStar.getTargetColumns().addObjectName(pColumn); 2163 break; 2164 } 2165 } 2166 }else{ 2167 lcResult = false; 2168 // * column, no table prefix, this column can only be in one of tables 2169 for(int i=0;i<tables.size();i++){ 2170 lcResult = tables.getTable(i).searchColumn(this,"",pColumn,false); 2171 //tables.getTable(i).getLinkedColumns().addObjectName(pColumn); 2172 //pColumn.setSourceTable(tables.getTable(i)); 2173 pColumn.setSourceColumn(columnStar); 2174 columnStar.getTargetColumns().addObjectName(pColumn); 2175 } 2176 } 2177 if (!lcResult) { 2178 lcResult = linkToFirstTable(pColumn,0); 2179 } 2180 }else{ 2181 // multi tables in from clause and multi * column in select list. 2182 lcResult = linkToFirstTable(pColumn,0); 2183 } 2184 } 2185 2186 return lcResult; 2187 2188 //if (lcResult) return true; 2189 2190 // From now on, let's search in * column, there maybe more than one * column in the select list, such as t1.*, t2.* 2191// TResultColumn resultColumn = getResultColumnList().getResultColumn(0); 2192// if ((getResultColumnList().size() == 1) &&(resultColumn.toString().equalsIgnoreCase("*") )){ 2193// // search in * or t1.* in the select list 2194// int tableCntInFromClause = 0; 2195// TTable tableInFromClause = null; 2196// for(int i=0;i<tables.size();i++){ 2197// TTable tn = tables.getTable(i); 2198// if (tn.getEffectType() == ETableEffectType.tetTeradataReference) continue; 2199// tableInFromClause = tn; 2200// tableCntInFromClause++; 2201// } 2202// //if (tables.size() == 1){ 2203// if (tableCntInFromClause == 1){ 2204// //TTable t0 = tables.getTable(0); 2205// TTable t0 = tableInFromClause; 2206// 2207// if (t0.isBaseTable()){ 2208// lcResult = fireOnMetaDatabaseTableColumn(t0.getPrefixServer(),t0.getPrefixDatabase(),t0.getPrefixSchema(),t0.getName(),pColumn.getColumnNameOnly()); 2209// if (! lcResult) candidateTableCnt++; 2210// }else{ 2211// if (t0.getTableType() == ETableSource.subquery){ 2212// if (t0.isIncludeColumnAlias()){ 2213// lcResult = t0.searchColumnInAlias(pColumn); 2214// }else{ 2215// lcResult = t0.getSubquery().searchColumnInResultSet(pColumn,pMustIn); 2216// if (! lcResult) candidateTableCnt++; 2217// } 2218// }else if (t0.isCTEName()){ 2219// lcResult = t0.getCTE().searchColumnInResultSet(this,t0,pColumn,pMustIn); 2220// if (! lcResult) candidateTableCnt++; 2221// } 2222// } 2223// if (pMustIn) lcResult = true; 2224// if (lcResult){ 2225// t0.getLinkedColumns().addObjectName(pColumn); 2226// pColumn.setSourceTable(t0); 2227// pColumn.setSourceColumn(resultColumn); 2228// resultColumn.getTargetColumns().addObjectName(pColumn); 2229// } 2230// }else{ // more than one table 2231// candidateTableCnt = 0; 2232// for(int i=0;i<tables.size();i++){ 2233// TTable tn = tables.getTable(i); 2234// if (tn.isBaseTable()){ 2235// lcResult = fireOnMetaDatabaseTableColumn(tn.getPrefixServer(),tn.getPrefixDatabase(),tn.getPrefixSchema(),tn.getName(),pColumn.getColumnNameOnly()); 2236// if (!lcResult) candidateTableCnt++; 2237// }else{ 2238// if (tn.getTableType() == ETableSource.subquery){ 2239// if (tn.isIncludeColumnAlias()){ 2240// lcResult = tn.searchColumnInAlias(pColumn); 2241// }else{ 2242// lcResult = tn.getSubquery().searchColumnInResultSet(pColumn,false); 2243// if (!lcResult) candidateTableCnt++; 2244// } 2245// }else if (tn.isCTEName()){ 2246// lcResult = tn.getCTE().searchColumnInResultSet(this,tn,pColumn,false); 2247// if (!lcResult) candidateTableCnt++; 2248// } 2249// } 2250// 2251// if (lcResult){ 2252// tn.getLinkedColumns().addObjectName(pColumn); 2253// pColumn.setSourceTable(tn); 2254// pColumn.setSourceColumn(resultColumn); 2255// resultColumn.getTargetColumns().addObjectName(pColumn); 2256// break; 2257// } 2258// } 2259// if ((!lcResult) && (pMustIn)) linkToFirstTable(pColumn,candidateTableCnt); 2260// } 2261// // } 2262// } 2263// 2264// if (lcResult) return true; 2265// 2266// // search t.* 2267// //int starColumnPos = 0, 2268// int numOfTableDotStar=0; 2269// for (int i=0;i<getResultColumnList().size();i++){ 2270// if (getResultColumnList().getResultColumn(i).toString().endsWith(".*")){ 2271// numOfTableDotStar++; 2272// } 2273// } 2274// 2275// TResultColumn rc = null; 2276// TTable tn = null; 2277// for (int i=0;i<getResultColumnList().size();i++){ 2278// if (!getResultColumnList().getResultColumn(i).toString().endsWith(".*")) continue; 2279// rc = getResultColumnList().getResultColumn(i); 2280// // starColumnPos = i; 2281// 2282// for (int j=0;j<tables.size();j++){ 2283// if (! tables.getTable(j).equalByName(rc.getPrefixTable())) continue; 2284// tn = tables.getTable(j); 2285// 2286// if (tn.isBaseTable()){ 2287// lcResult = fireOnMetaDatabaseTableColumn(tn.getPrefixServer(),tn.getPrefixDatabase(),tn.getPrefixSchema(),tn.getName(),pColumn.getColumnNameOnly()); 2288// if (!lcResult) candidateTableCnt++; 2289// }else{ 2290// if (tn.getTableType() == ETableSource.subquery){ 2291// if (tn.isIncludeColumnAlias()){ 2292// lcResult = tn.searchColumnInAlias(pColumn); 2293// }else{ 2294// lcResult = tn.getSubquery().searchColumnInResultSet(pColumn,((pMustIn)&&(numOfTableDotStar == 1))); 2295// if (!lcResult) candidateTableCnt++; 2296// } 2297// }else if (tn.isCTEName()){ 2298// lcResult = tn.getCTE().searchColumnInResultSet(this,tn,pColumn,((pMustIn)&&(numOfTableDotStar == 1))); 2299// if (!lcResult) candidateTableCnt++; 2300// } 2301// } 2302// 2303// if (lcResult){ 2304// tn.getLinkedColumns().addObjectName(pColumn); 2305// pColumn.setSourceTable(tn); 2306// pColumn.setSourceColumn(rc); 2307// rc.getTargetColumns().addObjectName(pColumn); 2308// break; 2309// } 2310// } 2311// if (lcResult) break; 2312// } 2313// 2314// if (lcResult) return true; 2315// 2316// if ((pMustIn) && (numOfTableDotStar == 1) && (tn != null)){ 2317// tn.getLinkedColumns().addObjectName(pColumn); 2318// pColumn.setSourceTable(tn); 2319// pColumn.setSourceColumn(rc); 2320// rc.getTargetColumns().addObjectName(pColumn); 2321// lcResult = true; 2322// } 2323// 2324// if (lcResult) return true; 2325// 2326// if ((pMustIn) && (numOfTableDotStar > 0)) lcResult = linkToFirstTable(pColumn,candidateTableCnt); 2327// 2328// if ((pMustIn)&&(!lcResult)) try { 2329// throw new Exception(" column must be found in the select list:"+pColumn.toString()); 2330// } catch (Exception e) { 2331// e.printStackTrace(); 2332// } 2333// 2334// return lcResult; 2335 } 2336 2337 2338}