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 TSelectSqlNode selectNode = (TSelectSqlNode)rootNode; 958 959 if (this.sourcetokenlist.size() == 0){ 960 // subquery nested in other statements. 961 this.setStartToken(selectNode.getStartToken()); 962 this.setEndToken(selectNode.getEndToken()); 963 } 964 965 super.doParseStatement(psql); 966 this.selectToken = selectNode.getSelectToken(); 967 parenthesisCount = selectNode.getParenthesisCount(); 968 parenthesisCountBeforeOrder = selectNode.getParenthissisCountBeforeOrder(); 969 970 setOperator = selectNode.getSetOperator(); 971 initSetOperatorFields(); 972 973 if(selectNode.isCombinedQuery()){ 974 TCustomSqlStatement lcParentSql = psql; 975 if ((lcParentSql == null)||(!childOfCombinedQuery)){ 976 lcParentSql = this; 977 } 978 979 if (selectNode.cteList != null){ 980 this.setCteList(selectNode.cteList); 981 for(int i=0;i<getCteList().size();i++){ 982 getCteList().getCTE(i).doParse(this,ESqlClause.cte); 983 } 984 } 985 986 // Oracle 12c WITH FUNCTION/PROCEDURE support 987 if (selectNode.getWithPlsqlItems() != null){ 988 this.setWithPlsqlItems(selectNode.getWithPlsqlItems()); 989 } 990 991 // Iterative construction of the left-recursive UNION/INTERSECT/EXCEPT chain. 992 // This avoids StackOverflow for queries with many set operations (e.g., 2000+ UNION ALL). 993 // We collect the chain of combined query nodes, set up their properties top-down, 994 // then process leaf children and clauses from deepest to shallowest. 995 996 ArrayList<TSelectSqlStatement> stmtChain = new ArrayList<>(); 997 ArrayList<TSelectSqlNode> nodeChain = new ArrayList<>(); 998 999 stmtChain.add(this); 1000 nodeChain.add(selectNode); 1001 1002 TSelectSqlStatement currentStmt = this; 1003 TSelectSqlNode currentNode = selectNode; 1004 1005 // Walk down the left chain, creating intermediate TSelectSqlStatements 1006 while (currentNode.getLeftNode() != null && currentNode.getLeftNode().isCombinedQuery()) { 1007 TSelectSqlNode leftNode = currentNode.getLeftNode(); 1008 1009 TSelectSqlStatement nextStmt = new TSelectSqlStatement(dbvendor); 1010 nextStmt.rootNode = leftNode; 1011 nextStmt.setChildOfCombinedQuery(true); 1012 1013 // Wire up parent's leftStmt 1014 currentStmt.leftStmt = nextStmt; 1015 1016 // Inline common setup (equivalent of super.doParseStatement + field init) 1017 if (nextStmt.sourcetokenlist.size() == 0) { 1018 nextStmt.setStartToken(leftNode.getStartToken()); 1019 nextStmt.setEndToken(leftNode.getEndToken()); 1020 } 1021 // Equivalent of TCustomSqlStatement.doParseStatement(lcParentSql) 1022 nextStmt.setParentStmt(lcParentSql); 1023 nextStmt.setFrameStack(lcParentSql.getFrameStack()); 1024 lcParentSql.getStmtScope().incrementCurrentStmtIndex(); 1025 nextStmt.setQueryId(String.format("%s#stmt_%d_%s", 1026 lcParentSql.getQueryId(), 1027 lcParentSql.getStmtScope().getCurrentStmtIndex(), 1028 nextStmt.sqlstatementtype)); 1029 nextStmt.setStmtScope(new TStmtScope(lcParentSql.getStmtScope(), nextStmt)); 1030 if (nextStmt.getStartToken() == null && nextStmt.rootNode != null) { 1031 nextStmt.setStartToken(nextStmt.rootNode.getStartToken()); 1032 } 1033 if (nextStmt.getEndToken() == null && nextStmt.rootNode != null) { 1034 nextStmt.setEndToken(nextStmt.rootNode.getEndToken()); 1035 } 1036 if (nextStmt.getGsqlparser() == null && nextStmt.rootNode != null) { 1037 nextStmt.setGsqlparser(nextStmt.rootNode.getGsqlparser()); 1038 } 1039 1040 nextStmt.selectToken = leftNode.getSelectToken(); 1041 nextStmt.parenthesisCount = leftNode.getParenthesisCount(); 1042 nextStmt.parenthesisCountBeforeOrder = leftNode.getParenthissisCountBeforeOrder(); 1043 nextStmt.setOperator = leftNode.getSetOperator(); 1044 nextStmt.initSetOperatorFields(); 1045 1046 stmtChain.add(nextStmt); 1047 nodeChain.add(leftNode); 1048 1049 currentStmt = nextStmt; 1050 currentNode = leftNode; 1051 } 1052 1053 // Create and process the leftmost leaf (non-combined SELECT) 1054 TSelectSqlStatement leftmostLeaf = new TSelectSqlStatement(dbvendor); 1055 leftmostLeaf.rootNode = currentNode.getLeftNode(); 1056 leftmostLeaf.setChildOfCombinedQuery(true); 1057 currentStmt.leftStmt = leftmostLeaf; 1058 leftmostLeaf.doParseStatement(lcParentSql); 1059 1060 // Process right children and clauses from deepest to shallowest 1061 for (int i = stmtChain.size() - 1; i >= 0; i--) { 1062 TSelectSqlStatement stmt = stmtChain.get(i); 1063 TSelectSqlNode node = nodeChain.get(i); 1064 1065 // Create and process right child (always a leaf for left-recursive grammar) 1066 stmt.rightStmt = new TSelectSqlStatement(dbvendor); 1067 stmt.rightStmt.rootNode = node.getRightNode(); 1068 stmt.rightStmt.setChildOfCombinedQuery(true); 1069 stmt.rightStmt.doParseStatement(lcParentSql); 1070 1071 // Handle clauses for this level 1072 if (node.getOrderbyClause() != null) { 1073 node.getOrderbyClause().doParse(stmt, ESqlClause.orderby); 1074 stmt.orderbyClause = node.getOrderbyClause(); 1075 } 1076 stmt.limitClause = node.getLimitClause(); 1077 if (node.getForupdateClause() != null) { 1078 node.getForupdateClause().doParse(stmt, ESqlClause.forUpdate); 1079 stmt.forUpdateClause = node.getForupdateClause(); 1080 } 1081 if (node.getComputeClause() != null) { 1082 node.getComputeClause().doParse(stmt, ESqlClause.compute); 1083 stmt.computeClause = node.getComputeClause(); 1084 } 1085 stmt.optionClause = node.getOptionClause(); 1086 stmt.timeTravel = node.getTimeTravel(); 1087 stmt.hintClause = node.getHintClause(); 1088 } 1089 1090 return 0; 1091 } 1092 1093 if (selectNode.getValueClause() != null){ 1094 this.valueClause = selectNode.getValueClause(); 1095 this.valueClause.doParse(this,ESqlClause.selectValue); 1096 isValueClause = true; 1097 return 0; 1098 } 1099 1100 if (selectNode.getTransformClause() != null){ 1101 this.transformClause = selectNode.getTransformClause(); 1102 this.transformClause.doParse(this,ESqlClause.transformClause); 1103 } 1104 1105 if (selectNode.cteList != null){ 1106 this.setCteList(selectNode.cteList); 1107 this.getCteList().doParse(this,ESqlClause.cte); 1108 } 1109 1110 // Oracle 12c WITH FUNCTION/PROCEDURE support 1111 if (selectNode.getWithPlsqlItems() != null){ 1112 this.setWithPlsqlItems(selectNode.getWithPlsqlItems()); 1113 } 1114 1115 if (selectNode.isHiveFromQuery()){ 1116 if(selectNode.getSelectSqlNodes() != null){ 1117 for(int i=1;i<selectNode.getSelectSqlNodes().size();i++){ 1118 //start from the second, the first select statement is represented by this class instance. 1119 1120 TSelectSqlStatement select = new TSelectSqlStatement(EDbVendor.dbvhive); 1121 select.rootNode = selectNode.getSelectSqlNodes().get(i); 1122 select.doParseStatement(this); 1123 this.getMultiSelectStatements().add(select); 1124 } 1125 } 1126 1127 // Hive: from query insert... 1128// if (selectNode.getFromTableList() != null){ 1129// TFromTable lcFromTable; 1130// TJoin lcJoin; 1131// 1132// for(int i=0; i<selectNode.getFromTableList().size();i++){ 1133// lcFromTable = selectNode.getFromTableList().getFromTable(i); 1134// TTable lcTable = null; 1135// 1136// if (lcFromTable.getFromtableType() != ETableSource.join){ 1137// lcJoin = new TJoin(); 1138// lcTable = analyzeFromTable(lcFromTable,true); 1139// lcTable.setEffectType(ETableEffectType.tetSelect); 1140// lcJoin.setTable(lcTable); 1141// lcJoin.setStartToken(lcJoin.getTable().getStartToken()); 1142// lcJoin.setEndToken(lcJoin.getTable().getEndToken()); 1143// lcJoin.setGsqlparser(getGsqlparser()); 1144// }else{ 1145// lcJoin = analyzeJoin(lcFromTable.getJoinExpr(),null,true); 1146// lcJoin.doParse(this, ESqlClause.join); 1147// 1148// if (lcFromTable.getLateralViewList() != null){ 1149// for(TLateralView lateralView:lcFromTable.getLateralViewList()){ 1150// addToTables(lateralView.createATable(this)); 1151// } 1152// } 1153// } 1154// 1155// joins.addJoin(lcJoin); 1156// } 1157// } 1158 1159 1160// if (selectNode.getHiveBodyList() != null){ 1161// for(int i = 0; i<selectNode.getHiveBodyList().size();i++){ 1162// TParseTreeNode node1 = selectNode.getHiveBodyList().get(i); 1163// switch (node1.getNodeType()){ 1164// case TStatementSqlNode.select: 1165// TSelectSqlStatement select = new TSelectSqlStatement(EDbVendor.dbvhive); 1166// select.rootNode = node1; 1167// select.doParseStatement(this); 1168// this.getHiveBodyList().add(select); 1169// 1170// break; 1171// case TStatementSqlNode.insert: 1172// 1173// TInsertSqlStatement insert = new TInsertSqlStatement(EDbVendor.dbvhive); 1174// insert.rootNode = node1; 1175// insert.doParseStatement(this); 1176// this.getHiveBodyList().add(insert); 1177// break; 1178// default: 1179// break; 1180// } 1181// } 1182// } 1183 // return 0; 1184 } 1185 1186 // get oracle hint 1187 if((dbvendor == EDbVendor.dbvoracle)||(dbvendor == EDbVendor.dbvmysql)){ 1188 TSourceToken lcnextst = this.selectToken.container.nextsolidtoken(this.selectToken.posinlist,1,true); 1189 while (lcnextst != null){ 1190 if (!((lcnextst.tokentype == ETokenType.ttsimplecomment) || (lcnextst.tokentype == ETokenType.ttbracketedcomment))) break; 1191 1192 if (lcnextst.tokentype == ETokenType.ttbracketedcomment){ 1193 if (lcnextst.toString().startsWith("/*+")){ 1194 //lcnextst.setDbObjType(TObjectName.ttObjOracleHint); 1195 lcnextst.setDbObjectType(EDbObjectType.oracleHint); 1196 if (oracleHint == null){ 1197 oracleHint = lcnextst.toString(); 1198 }else { 1199 oracleHint = oracleHint + " " + lcnextst.toString(); 1200 } 1201 } 1202 } 1203 1204 if (lcnextst.tokentype == ETokenType.ttsimplecomment){ 1205 if (lcnextst.toString().startsWith("--+")){ 1206 //lcnextst.setDbObjType(TObjectName.ttObjOracleHint); 1207 lcnextst.setDbObjectType(EDbObjectType.oracleHint); 1208 if (oracleHint == null){ 1209 oracleHint = lcnextst.toString(); 1210 }else { 1211 oracleHint = oracleHint + " " + lcnextst.toString(); 1212 } 1213 } 1214 } 1215 1216 lcnextst = lcnextst.container.nextsolidtoken(lcnextst,1,true); 1217 } 1218 1219 hint = oracleHint; 1220 } 1221 1222 if (selectNode.getHiveHintClause() != null){ 1223 hiveHintClause = selectNode.getHiveHintClause(); 1224 } 1225 1226 isConsume = selectNode.isConsume(); 1227 1228 if (selectNode.getTopClause() != null){ 1229 selectNode.getTopClause().doParse(this,ESqlClause.top); 1230 this.setTopClause(selectNode.getTopClause()); 1231 } 1232 1233 // this.skipOffset = selectNode.getSkipOffset(); 1234// this.firstMax = selectNode.getFirstMax(); 1235// this.limitMax = selectNode.getLimitMax(); 1236 1237 if (selectNode.getSelectDistinct() != null){ 1238 this.selectDistinct = selectNode.getSelectDistinct(); 1239 } 1240 1241 this.selectModifiers = selectNode.getSelectModifiers(); 1242 1243 TFromTable lcFromTable = null; 1244 TJoin lcJoin = null; 1245 1246 if (selectNode.getFromTableList() != null){ 1247 fromClause = new TFromClause(this.getRelations()); 1248 fromClause.setStartToken(selectNode.getFromTableList().getStartToken()); 1249 fromClause.setEndToken(selectNode.getFromTableList().getEndToken()); 1250 1251 for(int i=0; i<selectNode.getFromTableList().size();i++){ 1252 lcFromTable = selectNode.getFromTableList().getFromTable(i); 1253 lcJoin = analyzeTableOrJoin(lcFromTable); 1254 joins.addJoin(lcJoin); 1255 } 1256 } 1257 1258 if (selectNode.getResultColumnList() != null){ 1259 this.setResultColumnList(selectNode.getResultColumnList()); 1260 1261// if ((this.getResultColumnList().size() > 10) 1262// &&(this.getTables().size() == 1) 1263// &&(this.getTables().getTable(0).getTableType() == ETableSource.subquery) 1264// &&( this.getTables().getTable(0).getSubquery().getResultColumnList().size() == this.getResultColumnList().size() ) 1265// ){ 1266// TTable t0 = this.getTables().getTable(0); 1267// ArrayList<TResultColumn> targetColumnArrayList = this.getResultColumnList().getSortedColumns(); 1268// ArrayList<TResultColumn> sourceColumnArrayList = t0.getSubquery().getResultColumnList().getSortedColumns(); 1269// int i=0; 1270// for(TResultColumn rc:targetColumnArrayList){ 1271// TObjectName targetColumn = rc.getExpr().getObjectOperand(); 1272// TResultColumn sourceResultColumn = sourceColumnArrayList.get(i++); 1273// //TObjectName sourceColumn = sourceResultColumn.getExpr().getObjectOperand(); 1274// if (targetColumn != null){ 1275// //System.out.println(targetColumn+"\t->\t"+sourceResultColumn.getDisplayName()); 1276// targetColumn.setSourceTable(t0); 1277// t0.getLinkedColumns().addObjectName(targetColumn); 1278// targetColumn.setSourceColumn(sourceResultColumn); 1279// sourceResultColumn.getTargetColumns().addObjectName(targetColumn); 1280// } 1281// } 1282// } 1283 1284 selectNode.getResultColumnList().doParse(this,ESqlClause.selectList); 1285 1286 // Slice 73: link DISTINCT ON expression list (PostgreSQL / 1287 // Greenplum `SELECT DISTINCT ON (cols) ...`) so each 1288 // TObjectName inside gets dbObjectType=column and 1289 // sourceTable populated. Without this, the expressions 1290 // remain EDbObjectType.unknown. The legacy column-linker 1291 // (linkColumnToTable) is invoked here via TExpression.doParse; 1292 // resolver-2 picks the same expressions up via the 1293 // TSelectDistinct.acceptChildren descent that slice 73 1294 // also wires up. Tables are populated by the FROM clause 1295 // loop above so column linking has a relation list to 1296 // resolve against. Mirrors the TGroupBy.doParse → 1297 // items.doParse pattern. 1298 if (this.selectDistinct != null 1299 && this.selectDistinct.getExpressionList() != null) { 1300 TExpressionList distinctOnExprList = 1301 this.selectDistinct.getExpressionList(); 1302 for (int i = 0; i < distinctOnExprList.size(); i++) { 1303 TExpression e = distinctOnExprList.getExpression(i); 1304 if (e != null) { 1305 e.doParse(this, ESqlClause.unknown); 1306 } 1307 } 1308 } 1309 1310 for(int i=0;i<selectNode.getResultColumnList().size();i++){ 1311 TResultColumn resultColumn = selectNode.getResultColumnList().getResultColumn(i); 1312 if (resultColumn.getExpr().toString().endsWith("*")){ 1313 //System.out.println(resultColumn.toString()+":"+resultColumn.getStartToken().lineNo+","+resultColumn.getStartToken().columnNo); 1314 if (resultColumn.getExpr().toString().startsWith("*")){ 1315 // add all result columns in from tables 1316 for(int j=0;j<getTables().size();j++){ 1317 if (getTables().getTable(j).getTableType() == ETableSource.subquery){ 1318 getExpandedResultColumns().putAll(getTables().getTable(j).getSubquery().getExpandedResultColumns()); 1319 }else{ 1320 // ToDo for real table 1321 } 1322 //System.out.println("\t"+getTables().getTable(j).toString()+",\t"+getTables().getTable(j).getTableType()+",\t"+getTables().getTable(j).isCTEName()); 1323 } 1324 if (getTables().size() == 1){ 1325 resultColumn.getExpr().getObjectOperand().setSourceTable(getTables().getTable(0)); 1326 } 1327 1328 }else{ 1329 for(int j=0;j<getTables().size();j++){ 1330 if (getTables().getTable(j).getAliasName().equalsIgnoreCase( resultColumn.toString().split("[.]")[0])){ 1331 if (getTables().getTable(j).getTableType() == ETableSource.subquery){ 1332 getExpandedResultColumns().putAll(getTables().getTable(j).getSubquery().getExpandedResultColumns()); 1333 }else{ 1334 // ToDo for real table 1335 } 1336 resultColumn.getExpr().getObjectOperand().setSourceTable(getTables().getTable(j)); 1337 break; 1338 } 1339 } 1340 } 1341 }else{ 1342 getExpandedResultColumns().put(IdentifierService.normalizeStatic(this.dbvendor, ESQLDataObjectType.dotColumn,resultColumn.getDisplayName()),resultColumn); 1343 } 1344 } 1345 } 1346 1347 if (selectNode.getIntoClause() != null){ 1348 this.intoClause = selectNode.getIntoClause(); 1349 this.intoClause.doParse(this,ESqlClause.selectInto); 1350 } 1351 1352 1353 if (selectNode.getWhereCondition() != null){ 1354 selectNode.getWhereCondition().doParse(this,ESqlClause.where); 1355 this.setWhereClause( selectNode.getWhereCondition()); 1356 } 1357 1358 if (selectNode.getHierarchicalClause() != null){ 1359 selectNode.getHierarchicalClause().doParse(this,ESqlClause.hierarchical); 1360 this.hierarchicalClause = selectNode.getHierarchicalClause(); 1361 } 1362 1363 if (selectNode.getGroupByClause() != null){ 1364 selectNode.getGroupByClause().doParse(this,ESqlClause.groupby); 1365 this.groupByClause = selectNode.getGroupByClause(); 1366 } 1367 1368 if (selectNode.getQualifyClause() != null){ 1369 selectNode.getQualifyClause().doParse(this,ESqlClause.qualify); 1370 this.qualifyClause = selectNode.getQualifyClause(); 1371 } 1372 1373 if (selectNode.getSampleClause() != null){ 1374 selectNode.getSampleClause().doParse(this,ESqlClause.sample); 1375 this.sampleClause = selectNode.getSampleClause(); 1376 } 1377 1378 if (selectNode.getExpandOnClause() != null){ 1379 selectNode.getExpandOnClause().doParse(this,ESqlClause.expandOn); 1380 this.expandOnClause = selectNode.getExpandOnClause(); 1381 } 1382 1383 if (selectNode.getWithClause() != null){ 1384 selectNode.getWithClause().doParse(this,ESqlClause.teradataWith); 1385 this.teradataWithClause = selectNode.getWithClause(); 1386 } 1387 1388 if (selectNode.getOrderbyClause() != null){ 1389 selectNode.getOrderbyClause().doParse(this,ESqlClause.orderby); 1390 this.orderbyClause = selectNode.getOrderbyClause(); 1391 } 1392 1393 if (selectNode.getLockingClauses() != null){ 1394 selectNode.getLockingClauses().doParse(this,ESqlClause.lockingClause); 1395 this.lockingClauses = selectNode.getLockingClauses(); 1396 } 1397 1398 this.sortBy = selectNode.getSortBy(); 1399 if (this.sortBy != null){ 1400 this.sortBy.doParse(this,ESqlClause.sortby); 1401 } 1402 1403 this.clusterBy = selectNode.getClusterBy(); 1404 if (this.clusterBy != null){ 1405 this.clusterBy.doParse(this,ESqlClause.cluster); 1406 } 1407 1408 this.windowClause = selectNode.getWindowClause(); 1409 if (this.windowClause != null){ 1410 this.windowClause.doParse(this,ESqlClause.windowClause); 1411 } 1412 this.limitClause = selectNode.getLimitClause(); 1413 if (this.limitClause != null){ 1414 this.limitClause.doParse(this,ESqlClause.limit); 1415 } 1416 1417 if (selectNode.getForupdateClause() != null){ 1418 selectNode.getForupdateClause().doParse(this,ESqlClause.forUpdate); 1419 this.forUpdateClause = selectNode.getForupdateClause(); 1420 } 1421 1422 if (selectNode.getComputeClause() != null){ 1423 selectNode.getComputeClause().doParse(this,ESqlClause.compute); 1424 this.computeClause = selectNode.getComputeClause(); 1425 } 1426 1427 this.intoTableClause = selectNode.getIntoTableClause(); 1428 1429 if (selectNode.getDistributeBy() != null){ 1430 this.distributeBy = selectNode.getDistributeBy(); 1431 this.distributeBy.doParse(this,ESqlClause.distributeBy); 1432 } 1433 1434 1435 this.isolationClause = selectNode.getIsolationClause(); 1436 1437 this.optionClause = selectNode.getOptionClause(); 1438 1439 this.offsetClause = selectNode.getOffsetClause(); 1440 this.fetchFirstClause = selectNode.getFetchFirstClause(); 1441 1442 this.timeTravel = selectNode.getTimeTravel(); 1443 this.hintClause = selectNode.getHintClause(); 1444 1445 if (selectNode.getForXMLClause() != null){ 1446 if (tables.size() > 0){ 1447 tables.getTable(0).setForXMLClause(selectNode.getForXMLClause()); 1448 } 1449 } 1450 1451 // StarRocks pipe operator support 1452 this.pipeOperators = selectNode.getPipeOperators(); 1453 this.isPipeQuery = selectNode.isPipeQuery(); 1454 1455 return 0; 1456 } 1457 1458 /** 1459 * Determine whether The UNION, EXCEPT and INTERSECT operators were used. 1460 * @return true if one of those operators were used. 1461 */ 1462 public boolean isCombinedQuery(){ 1463 // combine multiple queries using the set operators UNION, UNION ALL, INTERSECT, and MINUS. 1464 return (setOperator > 0); 1465 } 1466 1467 /** 1468 * Initialize setOperatorType, all, and setOpDistinct fields from setOperator value. 1469 * Used by doParseStatement's iterative combined query construction. 1470 */ 1471 private void initSetOperatorFields() { 1472 switch (setOperator) { 1473 case SET_OPERATOR_NONE: 1474 setOperatorType = ESetOperatorType.none; all = false; break; 1475 case setOperator_union: 1476 setOperatorType = ESetOperatorType.union; all = false; break; 1477 case setOperator_unionall: 1478 setOperatorType = ESetOperatorType.union; all = true; break; 1479 case SET_OPERATOR_UNIONDISTINCT: 1480 setOperatorType = ESetOperatorType.union; setOpDistinct = true; break; 1481 case setOperator_intersect: 1482 setOperatorType = ESetOperatorType.intersect; all = false; break; 1483 case setOperator_intersectall: 1484 setOperatorType = ESetOperatorType.intersect; all = true; break; 1485 case setOperator_except: 1486 setOperatorType = ESetOperatorType.except; all = false; break; 1487 case setOperator_exceptall: 1488 setOperatorType = ESetOperatorType.except; all = true; break; 1489 case setOperator_minus: 1490 setOperatorType = ESetOperatorType.minus; all = false; break; 1491 case setOperator_minusall: 1492 setOperatorType = ESetOperatorType.minus; all = true; break; 1493 case SET_OPERATOR_INTERSECTDISTINCT: 1494 setOperatorType = ESetOperatorType.intersect; setOpDistinct = true; break; 1495 case SET_OPERATOR_EXCEPTDISTINCT: 1496 setOperatorType = ESetOperatorType.except; setOpDistinct = true; break; 1497 } 1498 } 1499 1500 public void accept(TParseTreeVisitor v) 1501 { 1502 v.preVisit(this); 1503 v.postVisit(this); 1504 } 1505 1506 /** 1507 * Accept visitor to visit this class. 1508 * @param v user defined visitor. 1509 */ 1510 public void acceptChildren(TParseTreeVisitor v) 1511 { 1512 1513 if(this.isCombinedQuery()){ 1514 1515 // Iterative traversal for combined queries to avoid StackOverflow 1516 // on deeply nested left-recursive UNION/INTERSECT/EXCEPT chains. 1517 // Collect the left-recursive chain of combined query nodes. 1518 ArrayList<TSelectSqlStatement> chain = new ArrayList<>(); 1519 TSelectSqlStatement current = this; 1520 while (current.isCombinedQuery()) { 1521 chain.add(current); 1522 current = current.getLeftStmt(); 1523 } 1524 // 'current' is now the leftmost leaf (non-combined SELECT) 1525 1526 // Phase 1: preVisit all combined nodes and their CTEs, from root to deepest 1527 for (int i = 0; i < chain.size(); i++) { 1528 TSelectSqlStatement node = chain.get(i); 1529 v.preVisit(node); 1530 if (node.getCteList() != null) { 1531 node.getCteList().acceptChildren(v); 1532 } 1533 } 1534 1535 // Phase 2: Visit leftmost leaf SELECT 1536 current.acceptChildren(v); 1537 1538 // Phase 3: Visit right branches and postVisit, from deepest to root 1539 for (int i = chain.size() - 1; i >= 0; i--) { 1540 TSelectSqlStatement node = chain.get(i); 1541 node.getRightStmt().acceptChildren(v); 1542 1543 if (node.getOrderbyClause() != null) { 1544 node.getOrderbyClause().acceptChildren(v); 1545 } 1546 if (node.getLimitClause() != null) { 1547 node.getLimitClause().acceptChildren(v); 1548 } 1549 if (node.getForUpdateClause() != null) { 1550 node.getForUpdateClause().acceptChildren(v); 1551 } 1552 if (node.getComputeClause() != null) { 1553 node.getComputeClause().acceptChildren(v); 1554 } 1555 v.postVisit(node); 1556 } 1557 1558 return ; 1559 } 1560 1561 // System.out.println(this.toString().hashCode()+" "+ this.toString().substring(0,50)); 1562 1563 v.preVisit(this); 1564 1565 if (this.getTransformClause() != null){ 1566 this.getTransformClause().acceptChildren(v); 1567 } 1568 1569 if (this.getCteList() != null){ 1570 this.getCteList().acceptChildren(v); 1571 } 1572 1573 if (TBaseType.USE_JOINEXPR_INSTEAD_OF_JOIN){ 1574// fromClause.acceptChildren(v); 1575 v.preVisit(fromClause); 1576 for(TTable table:getRelations()){ 1577 table.acceptChildren(v); 1578 } 1579 v.postVisit(fromClause); 1580 }else{ 1581 if (this.getJoins() != null){ 1582 this.getJoins().acceptChildren(v); 1583 } 1584 } 1585 1586 if (this.getHiveHintClause() != null){ 1587 this.getHiveHintClause().acceptChildren(v); 1588 } 1589 1590 1591 if (this.getTopClause() != null){ 1592 this.getTopClause().acceptChildren(v); 1593 } 1594 1595 if (this.getSelectDistinct() != null){ 1596 this.getSelectDistinct().acceptChildren(v); 1597 } 1598 1599 if (this.getResultColumnList() != null){ 1600 this.getResultColumnList().acceptChildren(v); 1601 } 1602 1603 if (this.getIntoClause() != null){ 1604 this.getIntoClause().acceptChildren(v); 1605 } 1606 1607 1608 if (this.getWhereClause() != null){ 1609 this.getWhereClause().acceptChildren(v); 1610 } 1611 1612 if (this.getHierarchicalClause() != null){ 1613 this.getHierarchicalClause().acceptChildren(v); 1614 } 1615 1616 if (this.getGroupByClause() != null){ 1617 this.getGroupByClause().acceptChildren(v); 1618 } 1619 1620 if (this.getQualifyClause() != null){ 1621 this.getQualifyClause().acceptChildren(v); 1622 } 1623 1624 if (this.getSampleClause() != null){ 1625 this.getSampleClause().acceptChildren(v); 1626 } 1627 1628 if (this.getExpandOnClause() != null){ 1629 this.getExpandOnClause().acceptChildren(v); 1630 } 1631 1632 if (this.getTeradataWithClause() != null){ 1633 this.getTeradataWithClause().acceptChildren(v); 1634 } 1635 1636 if (this.getOrderbyClause() != null){ 1637 this.getOrderbyClause().acceptChildren(v); 1638 } 1639 1640 if (this.getLockingClauses() != null){ 1641 this.getLockingClauses().acceptChildren(v); 1642 } 1643 1644 if (this.getSortBy() != null){ 1645 this.getSortBy().acceptChildren(v); 1646 } 1647 1648 if (this.getClusterBy() != null){ 1649 this.getClusterBy().acceptChildren(v); 1650 } 1651 1652 if (this.getWindowClause() != null){ 1653 this.getWindowClause().acceptChildren(v); 1654 } 1655 1656 if (this.getLimitClause() != null){ 1657 this.getLimitClause().acceptChildren(v); 1658 } 1659 1660 if (this.getForUpdateClause() != null){ 1661 this.getForUpdateClause().acceptChildren(v); 1662 } 1663 1664 if (this.getComputeClause() != null){ 1665 this.getComputeClause().acceptChildren(v); 1666 } 1667 1668 if (this.getIntoTableClause() != null){ 1669 this.getIntoTableClause().acceptChildren(v); 1670 } 1671 1672 if (this.getDistributeBy() != null){ 1673 this.getDistributeBy().acceptChildren(v); 1674 } 1675 1676 if (this.getIsolationClause() != null){ 1677 this.getIsolationClause().acceptChildren(v); 1678 } 1679 1680 if (this.getOptionClause() != null){ 1681 this.getOptionClause().acceptChildren(v); 1682 } 1683 1684 if (this.getOffsetClause() != null){ 1685 this.getOffsetClause().acceptChildren(v); 1686 } 1687 1688 if (this.getFetchFirstClause() != null){ 1689 this.getFetchFirstClause().acceptChildren(v); 1690 } 1691 1692 if (this.getTimeTravel() != null){ 1693 this.getTimeTravel().acceptChildren(v); 1694 } 1695 1696 if (this.getHintClause() != null){ 1697 this.getHintClause().acceptChildren(v); 1698 } 1699 1700 v.postVisit(this); 1701 return ; 1702 1703 }; 1704 1705 /** 1706 * Add an order by clause to this class. 1707 * @param orderByStr new order by string 1708 * @return added order by clause. 1709 */ 1710 public TOrderBy addOrderBy(String orderByStr){ 1711 if (this.getOrderbyClause() != null){ 1712 this.getOrderbyClause().addOrderByItem(orderByStr); 1713 }else{ 1714 1715 TOrderBy orderBy = new TOrderBy(); 1716 orderBy.setGsqlparser(this.getGsqlparser()); 1717 orderBy.setString(" order by "+orderByStr); 1718 this.orderbyClause = orderBy; 1719 TSourceToken last_token = null; 1720 if (this.getGroupByClause() != null){ 1721 last_token = this.getGroupByClause().getEndToken(); 1722 }else if (this.getWhereClause() != null){ 1723 last_token = this.getWhereClause().getEndToken(); 1724 }else{ 1725 last_token = joins.getEndToken(); 1726 } 1727 1728 orderbyClause.addAllMyTokensToTokenList(last_token.container, last_token.posinlist+1); 1729 1730 for(int i=0;i<last_token.getNodesEndWithThisToken().size();i++){ 1731 TParseTreeNode node = last_token.getNodesEndWithThisToken().get(i); 1732 if (node instanceof TSelectSqlStatement) 1733 { 1734 // change all end token of parse tree node except the last order by item 1735 node.setEndToken(orderbyClause.getEndToken()); 1736 } 1737 } 1738 } 1739 1740 return this.getOrderbyClause(); 1741 } 1742 1743 /** 1744 * this function is alias of addWhereClause 1745 * @param condition new condition 1746 * @return new where clause 1747 */ 1748 public TWhereClause addCondition(String condition){ 1749 return addWhereClause(condition); 1750 } 1751 1752 public TWhereClause addConditionOR(String condition){ 1753 return addWhereClauseOR(condition); 1754 } 1755 1756 public TWhereClause addWhereClause(String condition){ 1757 return doAddWhereClause(condition,true); 1758 } 1759 1760 public TWhereClause addWhereClauseOR(String condition){ 1761 return doAddWhereClause(condition,false); 1762 } 1763 1764 protected TWhereClause doAddWhereClause(String condition, boolean isAnd){ 1765 1766 if (this.getWhereClause() != null){ 1767 if (isAnd){ 1768 this.getWhereClause().getCondition().addANDCondition(condition); 1769 }else{ 1770 this.getWhereClause().getCondition().addORCondition(condition); 1771 } 1772 1773 }else{ 1774 TWhereClause whereClause = new TWhereClause(); 1775 whereClause.setGsqlparser(this.getGsqlparser()); 1776 whereClause.setString(" where "+condition); 1777 this.setWhereClause(whereClause); 1778 1779 TSourceToken last_token = null; 1780 TJoin lastjoin = joins.getJoin(joins.size()-1); 1781 if (lastjoin.getJoinItems().size() > 0){ 1782 TJoinItem lastitem = lastjoin.getJoinItems().getJoinItem(lastjoin.getJoinItems().size()-1); 1783 last_token = lastitem.getEndToken(); 1784 }else { 1785 last_token = joins.getEndToken(); 1786 } 1787 1788 whereClause.addAllMyTokensToTokenList(last_token.container, last_token.posinlist+1); 1789 1790 for(int i=0;i<last_token.getNodesEndWithThisToken().size();i++){ 1791 TParseTreeNode node = last_token.getNodesEndWithThisToken().get(i); 1792 if (!((node instanceof TJoinList) 1793 ||(node instanceof TJoin) 1794 ||(node instanceof TJoinItemList) 1795 ||(node instanceof TJoinItem) 1796 )) 1797 { 1798 // change all end token of parse tree node except the last order by item 1799 node.setEndToken(whereClause.getEndToken()); 1800 } 1801 } 1802 1803 } 1804 return this.getWhereClause(); 1805 } 1806 1807 private ArrayList<String> columnsInFromClause = null; 1808 1809 1810 @Override 1811 public TFromClause getFromClause() { 1812 // #todo , select union 类型的 sql 语句,需要穿透到低层的各个 子 select 语句,需要进一步完善 1813 TFromClause ret = super.getFromClause(); 1814 if ((ret == null)&&(isCombinedQuery()&&(this.getRightStmt()!=null))){ 1815 return this.getRightStmt().getFromClause(); 1816 }else{ 1817 return ret; 1818 } 1819 } 1820 1821 public TResultColumnList getResultColumnList(boolean useColumnsFromLeftmost) { 1822 TResultColumnList ret = super.getResultColumnList(); 1823 if (ret != null) return ret; 1824 1825 if (isCombinedQuery()){ 1826 if (useColumnsFromLeftmost) { 1827 return this.getFarLeftStmt().getResultColumnList(); 1828 } else { 1829 return this.getRightStmt().getResultColumnList(); 1830 } 1831 } 1832 return ret; 1833 1834 1835// if ((ret == null)&&(isCombinedQuery()&&(this.getRightStmt()!=null))){ 1836// return this.getRightStmt().getResultColumnList(); 1837// }else{ 1838// return ret; 1839// } 1840 } 1841 1842 @Override 1843 public TResultColumnList getResultColumnList() { 1844 return getResultColumnList(false); 1845 1846// TResultColumnList ret = super.getResultColumnList(); 1847// if ((ret == null)&&(isCombinedQuery()&&(this.getRightStmt()!=null))){ 1848// return this.getRightStmt().getResultColumnList(); 1849// }else{ 1850// return ret; 1851// } 1852 } 1853 1854 public ArrayList<String> getColumnsInFromClause() { 1855 if (columnsInFromClause != null) return columnsInFromClause; 1856 columnsInFromClause = new ArrayList<String>(); 1857 TTable lcTable; 1858 for(int j=0;j<tables.size();j++){ 1859 lcTable = tables.getTable(j); 1860 switch (lcTable.getTableType()){ 1861 case objectname: 1862 break; 1863 case subquery: 1864 TSelectSqlStatement subQuery = lcTable.getSubquery(); 1865 if (subQuery.getResultColumnList() != null) 1866 for(int i=0;i<subQuery.getResultColumnList().size();i++){ 1867 TResultColumn resultColumn = subQuery.getResultColumnList().getResultColumn(i); 1868 String aliasName = null; 1869 if (resultColumn.getAliasClause() != null){ 1870 aliasName = resultColumn.getAliasClause().getAliasName().toString(); 1871 }else{ 1872 if (resultColumn.getExpr().getObjectOperand() != null){ 1873 aliasName = resultColumn.getExpr().getObjectOperand().toString(); 1874 } 1875 } 1876 if (aliasName != null){ 1877 columnsInFromClause.add(TSQLEnv.getObjectName(aliasName)); 1878 } 1879 } 1880 break; 1881 } 1882 } 1883 return columnsInFromClause; 1884 } 1885 1886 public void addColumnInSelectListToSQLEnv(TSQLTable sqlTable){ 1887 1888 if (this.getValueClause() != null) return; 1889 1890 if (this.getResultColumnList() != null) 1891 for(int i=0;i<this.getResultColumnList().size();i++){ 1892 TResultColumn resultColumn = this.getResultColumnList().getResultColumn(i); 1893 String aliasName = null; 1894 if (resultColumn.getAliasClause() != null){ 1895 aliasName = resultColumn.getAliasClause().getAliasName().toString(); 1896 }else{ 1897 if (resultColumn.getExpr().getObjectOperand() != null){ 1898 aliasName = resultColumn.getExpr().getObjectOperand().toString(); 1899 } 1900 } 1901 if (aliasName != null){ 1902 sqlTable.addColumn(TSQLEnv.getObjectName(aliasName)); 1903 } 1904 } 1905 } 1906 1907 /** 1908 * search column in the select list 1909 * 1910 * Internal function, DON'T call it explicitly. 1911 * @param pColumn 1912 * @param pMustIn 1913 * @return true if found. 1914 */ 1915 public boolean searchColumnInResultSet(TObjectName pColumn,boolean pMustIn){ 1916 boolean lcResult = false; 1917 int candidateTableCnt = 0; 1918 int numOfColumnStar = 0; 1919 TResultColumn columnStar = null; 1920 1921 1922 1923 TResultColumn c = null; 1924 if ( (c= this.getExpandedResultColumns().get(IdentifierService.normalizeStatic(this.dbvendor, ESQLDataObjectType.dotColumn,pColumn.getColumnNameOnly()))) != null) 1925 { 1926 //System.out.println("Found:"+pColumn.toString()); 1927 pColumn.setSourceColumn(c); 1928 c.getTargetColumns().addObjectName(pColumn); 1929 1930 return true; 1931 }else{ 1932 // System.out.println("NotCatch:"+pColumn.toString()); 1933 } 1934 1935 if (isCombinedQuery()){ 1936 boolean lcResult1;//,lcResult2; 1937 // search column in all select 1938 lcResult1 = getFarLeftStmt().searchColumnInResultSet(pColumn,pMustIn); 1939 if (!lcResult1) 1940 lcResult1 = rightStmt.searchColumnInResultSet(pColumn,pMustIn); 1941 return lcResult1; 1942 } 1943 1944 if (getResultColumnList() == null) return false; 1945 1946 if (pColumn.toString().endsWith("*")){ 1947 // pColumn here is o1.* 1948 // select o1.*, o2.c1 1949 // from (select c123, c345 from some_table) o1, other_table o2 1950 pColumn.setColumnsLinkedToStar(this.getResultColumnList()); 1951 return true; 1952 } 1953 1954 // search columns in select list, skip t.* but count it for later use 1955 for(int i=0;i<getResultColumnList().size();i++){ 1956 TResultColumn lcField = getResultColumnList().getResultColumn(i); 1957 if (lcField.toString().endsWith("*")){ 1958 numOfColumnStar++; 1959 columnStar = lcField; 1960 continue; 1961 } 1962 lcResult = lcField.isMatchedWithResultColumn(this.dbvendor, pColumn); 1963 if (lcResult){ 1964 pColumn.setSourceColumn(lcField); 1965 lcField.getTargetColumns().addObjectName(pColumn); 1966 break; 1967 } 1968 } 1969 1970 if (lcResult) return true; 1971 1972// // search in * column, including t.* and * 1973 for(int i=0;i<getResultColumnList().size();i++){ 1974 TResultColumn lcField = getResultColumnList().getResultColumn(i); 1975 if (lcField.toString().endsWith("*")){ 1976 // search column in t.*, have to check column in table t 1977 String prefixTableName = ""; 1978 if (lcField.toString().endsWith(".*")){ 1979 String[] a = lcField.toString().split("[.]"); 1980 prefixTableName = a[a.length - 2]; 1981 } 1982 for(int j=0;j<tables.size();j++){ 1983 lcResult = tables.getTable(j).searchColumn(this,prefixTableName,pColumn,false); 1984 if (lcResult) { 1985// tables.getTable(j).getLinkedColumns().addObjectName(pColumn); 1986// pColumn.setSourceTable(tables.getTable(j)); 1987 pColumn.setSourceColumn(lcField); 1988 lcField.getTargetColumns().addObjectName(pColumn); 1989 break; 1990 } 1991 } 1992 }else{ 1993 continue; 1994 } 1995 if (lcResult) break; 1996 } 1997 1998 if (lcResult) return true; 1999 2000 if (pMustIn){ 2001 if (tables.size() == 1){ // only a single table in from clause 2002 lcResult = true; 2003 boolean inStarColumn = false; 2004// tables.getTable(0).getLinkedColumns().addObjectName(pColumn); 2005// pColumn.setSourceTable(tables.getTable(0)); 2006 for(int i=0;i<getResultColumnList().size();i++) { 2007 TResultColumn lcField = getResultColumnList().getResultColumn(i); 2008 if (lcField.toString().endsWith("*")) { 2009 String prefixTableName = ""; 2010 if (lcField.toString().endsWith(".*")){ 2011 String[] a = lcField.toString().split("[.]"); 2012 prefixTableName = a[a.length - 2]; 2013 } 2014 tables.getTable(0).searchColumn(this,prefixTableName,pColumn,true); 2015 pColumn.setSourceColumn(lcField); 2016 lcField.getTargetColumns().addObjectName(pColumn); 2017 inStarColumn = true; 2018 break; 2019 } 2020 } 2021 if (!inStarColumn){ 2022 2023 if (!locateVariableOrParameter(pColumn)){ 2024 // check variable before raise error 2025 2026 // raise 2027 TSyntaxError err = new TSyntaxError(pColumn.getStartToken().toString() 2028 ,pColumn.getStartToken().lineNo,pColumn.getStartToken().columnNo 2029 ,String.format("Column %s is not found in subquery",pColumn.toString()) 2030 ,EErrorType.sphint ,TBaseType.MSG_ERROR_COLUMN_NOT_FOUND,this,pColumn.getStartToken().posinlist); 2031 this.parseerrormessagehandle( err); 2032 } 2033 2034 } 2035 }else if (numOfColumnStar == 1){// only a single * column in select list, but more than one table in from clause 2036 2037 pColumn.setSourceColumn(columnStar); 2038 columnStar.getTargetColumns().addObjectName(pColumn); 2039 if (columnStar.toString().endsWith(".*")){ 2040 lcResult = true; 2041 String[] a = columnStar.toString().split("[.]"); 2042 String prefixTableName = a[a.length - 2]; 2043 for(int i=0;i<tables.size();i++){ 2044 if (tables.getTable(i).checkTableByName(prefixTableName)){ 2045 tables.getTable(i).searchColumn(this,prefixTableName,pColumn,true); 2046// tables.getTable(i).getLinkedColumns().addObjectName(pColumn); 2047// pColumn.setSourceTable(tables.getTable(i)); 2048 pColumn.setSourceColumn(columnStar); 2049 columnStar.getTargetColumns().addObjectName(pColumn); 2050 break; 2051 } 2052 } 2053 }else{ 2054 lcResult = false; 2055 // * column, no table prefix, this column can only be in one of tables 2056 for(int i=0;i<tables.size();i++){ 2057 lcResult = tables.getTable(i).searchColumn(this,"",pColumn,false); 2058 //tables.getTable(i).getLinkedColumns().addObjectName(pColumn); 2059 //pColumn.setSourceTable(tables.getTable(i)); 2060 pColumn.setSourceColumn(columnStar); 2061 columnStar.getTargetColumns().addObjectName(pColumn); 2062 } 2063 } 2064 if (!lcResult) { 2065 lcResult = linkToFirstTable(pColumn,0); 2066 } 2067 }else{ 2068 // multi tables in from clause and multi * column in select list. 2069 lcResult = linkToFirstTable(pColumn,0); 2070 } 2071 } 2072 2073 return lcResult; 2074 2075 //if (lcResult) return true; 2076 2077 // From now on, let's search in * column, there maybe more than one * column in the select list, such as t1.*, t2.* 2078// TResultColumn resultColumn = getResultColumnList().getResultColumn(0); 2079// if ((getResultColumnList().size() == 1) &&(resultColumn.toString().equalsIgnoreCase("*") )){ 2080// // search in * or t1.* in the select list 2081// int tableCntInFromClause = 0; 2082// TTable tableInFromClause = null; 2083// for(int i=0;i<tables.size();i++){ 2084// TTable tn = tables.getTable(i); 2085// if (tn.getEffectType() == ETableEffectType.tetTeradataReference) continue; 2086// tableInFromClause = tn; 2087// tableCntInFromClause++; 2088// } 2089// //if (tables.size() == 1){ 2090// if (tableCntInFromClause == 1){ 2091// //TTable t0 = tables.getTable(0); 2092// TTable t0 = tableInFromClause; 2093// 2094// if (t0.isBaseTable()){ 2095// lcResult = fireOnMetaDatabaseTableColumn(t0.getPrefixServer(),t0.getPrefixDatabase(),t0.getPrefixSchema(),t0.getName(),pColumn.getColumnNameOnly()); 2096// if (! lcResult) candidateTableCnt++; 2097// }else{ 2098// if (t0.getTableType() == ETableSource.subquery){ 2099// if (t0.isIncludeColumnAlias()){ 2100// lcResult = t0.searchColumnInAlias(pColumn); 2101// }else{ 2102// lcResult = t0.getSubquery().searchColumnInResultSet(pColumn,pMustIn); 2103// if (! lcResult) candidateTableCnt++; 2104// } 2105// }else if (t0.isCTEName()){ 2106// lcResult = t0.getCTE().searchColumnInResultSet(this,t0,pColumn,pMustIn); 2107// if (! lcResult) candidateTableCnt++; 2108// } 2109// } 2110// if (pMustIn) lcResult = true; 2111// if (lcResult){ 2112// t0.getLinkedColumns().addObjectName(pColumn); 2113// pColumn.setSourceTable(t0); 2114// pColumn.setSourceColumn(resultColumn); 2115// resultColumn.getTargetColumns().addObjectName(pColumn); 2116// } 2117// }else{ // more than one table 2118// candidateTableCnt = 0; 2119// for(int i=0;i<tables.size();i++){ 2120// TTable tn = tables.getTable(i); 2121// if (tn.isBaseTable()){ 2122// lcResult = fireOnMetaDatabaseTableColumn(tn.getPrefixServer(),tn.getPrefixDatabase(),tn.getPrefixSchema(),tn.getName(),pColumn.getColumnNameOnly()); 2123// if (!lcResult) candidateTableCnt++; 2124// }else{ 2125// if (tn.getTableType() == ETableSource.subquery){ 2126// if (tn.isIncludeColumnAlias()){ 2127// lcResult = tn.searchColumnInAlias(pColumn); 2128// }else{ 2129// lcResult = tn.getSubquery().searchColumnInResultSet(pColumn,false); 2130// if (!lcResult) candidateTableCnt++; 2131// } 2132// }else if (tn.isCTEName()){ 2133// lcResult = tn.getCTE().searchColumnInResultSet(this,tn,pColumn,false); 2134// if (!lcResult) candidateTableCnt++; 2135// } 2136// } 2137// 2138// if (lcResult){ 2139// tn.getLinkedColumns().addObjectName(pColumn); 2140// pColumn.setSourceTable(tn); 2141// pColumn.setSourceColumn(resultColumn); 2142// resultColumn.getTargetColumns().addObjectName(pColumn); 2143// break; 2144// } 2145// } 2146// if ((!lcResult) && (pMustIn)) linkToFirstTable(pColumn,candidateTableCnt); 2147// } 2148// // } 2149// } 2150// 2151// if (lcResult) return true; 2152// 2153// // search t.* 2154// //int starColumnPos = 0, 2155// int numOfTableDotStar=0; 2156// for (int i=0;i<getResultColumnList().size();i++){ 2157// if (getResultColumnList().getResultColumn(i).toString().endsWith(".*")){ 2158// numOfTableDotStar++; 2159// } 2160// } 2161// 2162// TResultColumn rc = null; 2163// TTable tn = null; 2164// for (int i=0;i<getResultColumnList().size();i++){ 2165// if (!getResultColumnList().getResultColumn(i).toString().endsWith(".*")) continue; 2166// rc = getResultColumnList().getResultColumn(i); 2167// // starColumnPos = i; 2168// 2169// for (int j=0;j<tables.size();j++){ 2170// if (! tables.getTable(j).equalByName(rc.getPrefixTable())) continue; 2171// tn = tables.getTable(j); 2172// 2173// if (tn.isBaseTable()){ 2174// lcResult = fireOnMetaDatabaseTableColumn(tn.getPrefixServer(),tn.getPrefixDatabase(),tn.getPrefixSchema(),tn.getName(),pColumn.getColumnNameOnly()); 2175// if (!lcResult) candidateTableCnt++; 2176// }else{ 2177// if (tn.getTableType() == ETableSource.subquery){ 2178// if (tn.isIncludeColumnAlias()){ 2179// lcResult = tn.searchColumnInAlias(pColumn); 2180// }else{ 2181// lcResult = tn.getSubquery().searchColumnInResultSet(pColumn,((pMustIn)&&(numOfTableDotStar == 1))); 2182// if (!lcResult) candidateTableCnt++; 2183// } 2184// }else if (tn.isCTEName()){ 2185// lcResult = tn.getCTE().searchColumnInResultSet(this,tn,pColumn,((pMustIn)&&(numOfTableDotStar == 1))); 2186// if (!lcResult) candidateTableCnt++; 2187// } 2188// } 2189// 2190// if (lcResult){ 2191// tn.getLinkedColumns().addObjectName(pColumn); 2192// pColumn.setSourceTable(tn); 2193// pColumn.setSourceColumn(rc); 2194// rc.getTargetColumns().addObjectName(pColumn); 2195// break; 2196// } 2197// } 2198// if (lcResult) break; 2199// } 2200// 2201// if (lcResult) return true; 2202// 2203// if ((pMustIn) && (numOfTableDotStar == 1) && (tn != null)){ 2204// tn.getLinkedColumns().addObjectName(pColumn); 2205// pColumn.setSourceTable(tn); 2206// pColumn.setSourceColumn(rc); 2207// rc.getTargetColumns().addObjectName(pColumn); 2208// lcResult = true; 2209// } 2210// 2211// if (lcResult) return true; 2212// 2213// if ((pMustIn) && (numOfTableDotStar > 0)) lcResult = linkToFirstTable(pColumn,candidateTableCnt); 2214// 2215// if ((pMustIn)&&(!lcResult)) try { 2216// throw new Exception(" column must be found in the select list:"+pColumn.toString()); 2217// } catch (Exception e) { 2218// e.printStackTrace(); 2219// } 2220// 2221// return lcResult; 2222 } 2223 2224 2225}