001package gudusoft.gsqlparser.nodes; 002 003import gudusoft.gsqlparser.*; 004import gudusoft.gsqlparser.compiler.TStmtScope; 005import gudusoft.gsqlparser.nodes.hive.THiveKeyValueProperty; 006import gudusoft.gsqlparser.nodes.mssql.TForXMLClause; 007import gudusoft.gsqlparser.nodes.snowflake.TAtBeforeClause; 008import gudusoft.gsqlparser.nodes.snowflake.TStageReference; 009import gudusoft.gsqlparser.nodes.teradata.THashByClause; 010import gudusoft.gsqlparser.nodes.teradata.TTDUnpivot; 011import gudusoft.gsqlparser.resolver.TResolverHelpUtils; 012import gudusoft.gsqlparser.sqlenv.ESQLDataObjectType; 013import gudusoft.gsqlparser.sqlenv.TSQLEnv; 014import gudusoft.gsqlparser.sqlenv.TSQLTable; 015import gudusoft.gsqlparser.util.SQLUtil; 016import gudusoft.gsqlparser.stmt.TMergeSqlStatement; 017import gudusoft.gsqlparser.stmt.TSelectSqlStatement; 018import gudusoft.gsqlparser.stmt.hive.THiveFromQuery; 019 020import java.util.ArrayList; 021 022/** 023 * Represents various kinds of table source in from clause. Can also be a simple table/view name in create table and all other places. 024 * result of {@link #getTableType} can be one of: 025 *<ul> 026 * <li>ftt_objectname, in from clause, a simple table/view name, reference: {@link TTable#tableName}<li> 027 * <li>ftt_subquery, is a subquery that retrieves rows from the database, also known as derived table. reference: {@link TTable#subquery}</li> 028 * <li>ftt_tableExpr,it's usually a table-valued expression., reference: {@link TTable#tableExpr}</li> 029 * <li>ftt_function, it's usually a table-valued function., reference: {@link TTable#funcCall}</li> 030 * <li>{@link ETableSource#rowList}, it's constructed rows, reference: {@link TTable#rowList}</li> 031 * <li>ftt_containsTable, CONTAINSTABLE clause of sql server. reference: {@link TTable#containsTable}, type of {@link TContainsTable}</li> 032 * <li>ftt_freetextTable, FREETEXTTABLE clause of sql server. reference: {@link TTable#containsTable}, type of {@link TContainsTable}</li> 033 * <li>ftt_openrowset, OPENROWSET clause of sql server. reference: {@link TTable#openRowSet}, type of {@link TOpenRowSet}</li> 034 * <li>ftt_openxml, OPENXML clause of sql server. reference: {@link TTable#openXML}, type of {@link TOpenXML }</li> 035 * <li>ftt_opendatasource, OPENDATASOURCE clause of sql server. reference: {@link TTable#openDatasource}, type of {@link TOpenDatasource}</li> 036 * <li>ftt_openquery, OPENQUERY clause of sql server. reference: {@link TTable#openquery}, type of (@link TOpenQuery)</li> 037 * </ul> 038 * 039 * 040*/ 041 042public class TTable extends TNodeWithAliasClause implements IRelation { 043 private ArrayList<TAttributeNode> relationAttributes; 044 045 /** 046 * @deprecated , this method is deprecated since version 3.3.1.0, don't use it in TSQLResolver2 047 * @return 048 */ 049 @Override 050 public ArrayList<TAttributeNode> getAttributes(){ 051 if (relationAttributes == null) { 052 relationAttributes = new ArrayList<>(); 053 } 054 return relationAttributes; 055 } 056 057 @Override 058 public String getRelationName(){ 059 return this.getName(); 060 } 061 062 @Override 063 public int size(){ 064 return relationAttributes != null ? relationAttributes.size() : 0; 065 } 066 067 public void setStageReference(TStageReference stageReference) { 068 this.stageReference = stageReference; 069 } 070 071 private TStageReference stageReference; 072 073 public TStageReference getStageReference() { 074 return stageReference; 075 } 076 private TAtBeforeClause timeTravelClause; 077 078 public void setTimeTravelClause(TAtBeforeClause timeTravelClause) { 079 this.timeTravelClause = timeTravelClause; 080 } 081 082 public TAtBeforeClause getTimeTravelClause() { 083 return timeTravelClause; 084 } 085 086 private TCaseJoinClause caseJoin; 087 088 public void setCaseJoin(TCaseJoinClause caseJoin) { 089 this.caseJoin = caseJoin; 090 } 091 092 public TCaseJoinClause getCaseJoin() { 093 return caseJoin; 094 } 095 096 public String getStageName(){ 097 if (this.getTableName() == null) return null; 098 if (this.getTableName().getDbObjectType() != EDbObjectType.stage) return null; 099 return this.getTableName().getObjectString(); 100 } 101 public final static String PIVOT_CLAUSE_ALIAS = "(pivot_table)"; 102 public final static String UNPIVOT_CLAUSE_ALIAS = "(unpivot_table)"; 103 public final static String TABLE_COLLECTION_ALIAS = "(table_collection)"; 104 105 106 boolean isAttributesInitialized = false; 107 108 /** 109 * Initialize a star attribute node (tableName.*) for this table. 110 * This is used for regular tables (without DDL/metadata) in contexts where 111 * they need to compete with subqueries that have star columns. 112 * For example, in MERGE statements, the target table needs a star attribute 113 * so that unqualified columns in the ON clause can be resolved to it 114 * instead of being incorrectly pushed down through the source subquery's star column. 115 */ 116 public void initStarAttribute(){ 117 if (isAttributesInitialized) return; 118 TAttributeNode.addNodeToList(new TAttributeNode( getDisplayName()+".*",this),getAttributes()); 119 isAttributesInitialized = true; 120 } 121 122 public void initAttributeForXMLTable(){ 123 // if (isAttributesInitialized) return; 124 //relationAttributes.add(new TAttributeNode( getDisplayName()+".*",this)); 125 TAttributeNode.addNodeToList(new TAttributeNode( getDisplayName()+".*",this),getAttributes()); 126 isAttributesInitialized = true; 127 } 128 129 public void initAttributeForTableFunction(){ 130 // if (isAttributesInitialized) return; 131 //relationAttributes.add( new TAttributeNode( getDisplayName()+".value",this)); 132 TAttributeNode.addNodeToList(new TAttributeNode( getDisplayName()+".value",this),getAttributes()); 133 if (this.getName().equals("STRING_SPLIT")){ 134 // TRING_SPLIT函数生成的表只有两个字段:value和可选的ordinal 135 TAttributeNode.addNodeToList(new TAttributeNode( getDisplayName()+".ordinal",this),getAttributes()); 136 } 137 isAttributesInitialized = true; 138 } 139 140 public void initAttributeForRowList(){ 141 // if (isAttributesInitialized) return; 142 // relationAttributes.add( new TAttributeNode( getDisplayName()+".value",this)); 143 if (getValueClause() == null) return; 144 if (getValueClause().getRows().size() == 0) return; 145 146 int i = 0; 147 String columnName = ""; 148 TObjectNameList aliasColumnNameList = null; 149 // 1. 如果有 table alias 中指定 column, 遍历alias column 150 // 2. 如果 table alias 没有指定column, 遍历 subquery or values() 中的 resultcolumn 151 // 如果遍历alias column,可能存在 alias column 中column 数量和 subquery or values() 中的 resultcolumn 中不等的现象 152 // 例如 subquery or values() 中的 resultcolumn 中为 * column, 153 // 或者 snowflake 中的 pivot clause.(c:\prg\gsp_sqlfiles\TestCases\private\dataflow\snowflake\pivot_clause_1.sql) 154 155 TAliasClause aliasClause = this.getAliasClause(); 156 if (aliasClause != null){ 157 aliasColumnNameList = aliasClause.getColumns(); 158 } 159 for(TResultColumn resultColumn:getValueClause().getRows().get(0)){ 160 columnName = resultColumn.getDisplayName(); 161 if ((aliasColumnNameList != null)&&(aliasColumnNameList.size()>i)){ 162 columnName = aliasColumnNameList.getObjectName(i).getColumnNameOnly(); 163 } 164 TAttributeNode newNode = new TAttributeNode(this.getDisplayName() + "." + columnName, this, resultColumn); 165 //newNode.setAttributeCreatedFromAliasColumn(true); 166 //relationAttributes.add(newNode); 167 TAttributeNode.addNodeToList(newNode,relationAttributes); 168 i++; 169 } 170 171 TBaseType.log(String.format("Prepare attributes (num = %d) for rowList (values) : <%s>",this.getAttributes().size() ,this.getDisplayName()),TLog.DEBUG,this.getTableName()); 172 int c = 0; 173 for(TAttributeNode node: this.getAttributes()){ 174 TBaseType.log(String.format("\tAttribute: <%s>, result column: <%s>",node.getName(), node.getSubLevelResultColumn()!=null?node.getSubLevelResultColumn().toString():"N/A" ),TLog.DEBUG); 175 c++; 176 if (c > TLog.OUTPUT_ATTRIBUTES_MAX){ 177 TBaseType.log(String.format("\t...skipped after output %d attributes",c-1),TLog.DEBUG,this.getTableName().getStartToken()); 178 break; 179 } 180 } 181 182 183 isAttributesInitialized = true; 184 } 185 186 187 public void initAttributesFromCTE(TCTE cte){ 188 // if (isAttributesInitialized) return; 189 190 for (TAttributeNode node1 : cte.getAttributes()) { 191 TAttributeNode newNode = new TAttributeNode(this.getDisplayName() + "." + node1.getLastPartOfName(), this, node1.getSqlColumn(), node1.getSubLevelResultColumn()); 192 if (node1.getAccompaniedAttributeNodes().size() > 0){ 193 for(TAttributeNode n:node1.getAccompaniedAttributeNodes()){ 194 newNode.getAccompaniedAttributeNodes().add(n); 195 } 196 } 197 //relationAttributes.add(newNode); 198 TAttributeNode.addNodeToList(newNode,relationAttributes); 199 } 200 201 TBaseType.log(String.format("Prepare attributes (num = %d) for cte ref: <%s>",this.getAttributes().size() ,this.getTableName().toString()),TLog.DEBUG,this.getTableName()); 202 int c = 0; 203 for(TAttributeNode node: this.getAttributes()){ 204 if (node.getSqlColumn() != null){ 205 TBaseType.log(String.format("\tAttribute: <%s>, SQL column: <%s>",node.getName(), node.getSqlColumn()!=null?node.getSqlColumn().toString():"N/A" ),TLog.DEBUG); 206 }else{ 207 TBaseType.log(String.format("\tAttribute: <%s>, Select list column: <%s>",node.getName(), node.getSubLevelResultColumn()!=null?node.getSubLevelResultColumn().toString():"N/A" ),TLog.DEBUG); 208 } 209 c++; 210 if (c > TLog.OUTPUT_ATTRIBUTES_MAX){ 211 TBaseType.log(String.format("\t...skipped after output %d attributes",c-1),TLog.DEBUG,this.getTableName().getStartToken()); 212 break; 213 } 214 } 215 216 isAttributesInitialized = true; 217 } 218 public void initAttributesFromSubquery(TSelectSqlStatement subquery, String prefix){ 219 // TODO, not thread safe? 220 // if ((isAttributesInitialized) && (!relationAttributes.isEmpty())) return; 221 if (subquery.getResultColumnList() == null) return; 222 int i = 0; 223 if (subquery.getResultColumnList() != null) { 224 TResultColumnList resultColumnListFromSubQuery = subquery.getResultColumnList(true); 225 for(TResultColumn column: resultColumnListFromSubQuery){ 226 if (column.getAliasNameList().size() > 0){ 227 // 如果 column 有 alias name list, 则遍历 alias name list, 并把每个 alias name 作为 attribute node 添加到 relationAttributes 中 228 // as (b1, b2, b3, b4, b5) 229 // select t.a1, t.a2, stack(2, 'T', t.a1, t.a2, t.a3/t.a4, t.a5/t.a6, 'T+0', t.a7, t.a8, t.a9/t.a10, t.a11/t.a12) as (b1, b2, b3, b4, b5) from db1.table1 t 230 231 for(TObjectName aliasName: column.getAliasNameList()){ 232 this.addAttribute(new TAttributeNode(prefix + TBaseType.removeQuoteChar(aliasName.toString()),this,column,i)); 233 i++; 234 } 235 }else { 236 if (column.getDisplayName().endsWith("*")){ 237 TObjectName objectName = column.getExpr().getObjectOperand(); 238 if (objectName.getAttributeNodesDerivedFromFromClause().size() > 0){ 239 for(TAttributeNode attributeNode:objectName.getAttributeNodesDerivedFromFromClause()){ 240 //relationAttributes.add(new TAttributeNode( prefix + attributeNode.getLastPartOfName() ,this, attributeNode.getSqlColumn(), column,i)); 241 this.addAttribute(new TAttributeNode( prefix + attributeNode.getLastPartOfName() ,this, attributeNode.getSqlColumn(), column,i)); 242 } 243 }else{ 244 // no attribute node derived from from clause, add the object name directly 245 //relationAttributes.add(new TAttributeNode(prefix +"*",this,column,i)); 246 this.addAttribute(new TAttributeNode(prefix +"*",this,column,i)); 247 } 248 }else{ 249 //relationAttributes.add(new TAttributeNode(prefix +column.getDisplayName(),this,column,i)); 250 this.addAttribute(new TAttributeNode(prefix +column.getDisplayName(),this,column,i)); 251 } 252 i++; 253 } 254 } 255 } 256 257 // 如果 subQuery 是 combined query, 需要把所有 query 中的 select list 都加入进来。上面处理的仅仅为最右面的那个 subQuery 258 if (subquery.isCombinedQuery()){ 259 TSelectSqlStatement left = subquery.getLeftStmt(); 260 addNewAttributeFromSubQuery(left.getResultColumnList(true),getAttributes(),prefix); 261 while (left.isCombinedQuery()){ 262 left = left.getLeftStmt(); 263 addNewAttributeFromSubQuery(left.getResultColumnList(true),getAttributes(),prefix); 264 } 265 } 266 isAttributesInitialized = true; 267 } 268 269 void addNewAttributeFromSubQuery(TResultColumnList resultColumnList, ArrayList<TAttributeNode> attributeNodes, String prefix){ 270 addNewAttributeFromSubQuery(resultColumnList,attributeNodes,prefix,null); 271 } 272 273 /** 274 * 当 subQuery 为 combined query 时,不仅仅把 right most 那个 subQuery 的 select list 作为 子查询的 attribute node list 添加上来 275 * 还需要把 其他 combined query 中的 subQuery 加入进来 276 * 277 * 278 * 279 * @param resultColumnList subQuery 中的 select list 280 * @param attributeNodes 需要在该 attribute node 的 getAccompaniedAttributeNodes() 中添加新 node 281 * @param prefix 该前缀为 subQuery 的 alias,或 CTE 的 name 决定 282 * @param specifiedColumnList 当 table 为 CTE 时,并且 CTE 自己指定了 column list, 那么 attribute node 的 name 由该 column list 决定, 283 * 而不是 subQuery 中的 select list 确定 284 * 285 */ 286 void addNewAttributeFromSubQuery(TResultColumnList resultColumnList, ArrayList<TAttributeNode> attributeNodes, String prefix, TObjectNameList specifiedColumnList){ 287 if (resultColumnList == null) return; 288 if (resultColumnList.size() != attributeNodes.size()){ 289 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 290 TBaseType.log(String.format("When add attribute from subQuery, the size of select list and attributes is not the same: %d <> %d",resultColumnList.size(),attributeNodes.size()) 291 ,TLog.ERROR,resultColumnList.getStartToken()); 292 } 293 return; 294 } 295 int i = 0; 296 for(TResultColumn column: resultColumnList){ 297 TAttributeNode node = attributeNodes.get(i); // 根据 i 的值,找到原来对应位置的 attribute node,用来添加 accompanied node 298 299 if (column.getDisplayName().endsWith("*")){ 300 TObjectName objectName = column.getExpr().getObjectOperand(); 301 for(TAttributeNode attributeNode:objectName.getAttributeNodesDerivedFromFromClause()){ 302 if (specifiedColumnList == null){ 303 node.getAccompaniedAttributeNodes().add(new TAttributeNode( prefix + attributeNode.getLastPartOfName() ,this, attributeNode.getSqlColumn(), column,i)); 304 }else{ 305 TObjectName c = specifiedColumnList.getObjectName(i); 306 node.getAccompaniedAttributeNodes().add(new TAttributeNode( prefix + c.toString() ,this, attributeNode.getSqlColumn(), column,i)); 307 } 308 } 309 }else{ 310 if (specifiedColumnList == null){ 311 node.getAccompaniedAttributeNodes().add(new TAttributeNode(prefix +column.getDisplayName(),this,column,i)); 312 }else{ 313 TObjectName c = specifiedColumnList.getObjectName(i); 314 node.getAccompaniedAttributeNodes().add(new TAttributeNode(prefix + c.toString(),this,column,i)); 315 } 316 } 317 i++; 318 } 319 } 320 321 public String getDisplayName(){ 322 if (getAliasClause() != null) return getAliasName(); 323 String ret = null; 324 switch (getTableType()){ 325 case objectname: 326 ret = getFullName(); 327 break; 328 case tableExpr: 329 ret = TTable.TABLE_COLLECTION_ALIAS; 330 break; 331 default: 332 ret = toString(); 333 break; 334 } 335 return ret; 336 } 337 338 public String getDisplayName(boolean removeDBLink){ 339 if (!removeDBLink) return getDisplayName(); 340 if (dbvendor != EDbVendor.dbvoracle) return getDisplayName(); 341 // DM_MINING.FATURA_ODEME_SEGMENTASYONU@dblinkx 342 String ret = getDisplayName(); 343 int atIndex = ret.indexOf('@'); 344 if (atIndex > 0){ 345 ret = ret.substring(0,atIndex); 346 } 347 return ret; 348 } 349 350 351 /** 352 * 在 sql script 中,和该 relation 关联的 attribute。 353 * select a from t; 354 * attribute a 就是 relation t 的 referenceAttribute, 如果没有 metadata and ddl, 355 * relation t 的 relationAttributes 应该可以推断出包含 a, 但 t 是否还包含其他的 attribute 就无从得知。 356 */ 357 ArrayList<TObjectName> referenceAttributes = new ArrayList<>(); 358 359// public ArrayList<TObjectName> getReferenceAttributes(){ 360// return null; 361// } 362 363 public void initAttributesForPivotTable(){ 364 // if (isAttributesInitialized) return; 365 TPivotClause pivotClause = this.getPivotedTable().getPivotClauseList().getElement(0); 366 if (pivotClause.getType() == TPivotClause.pivot){ 367 368 // 先添加 pivot clause 中的 attribute,以防止 先处理 [p].[3] -> p.*, 而导致 [p].[3] -> [p].[3] 没能正确匹配 369 370 // SELECT [p].[ADDRESS_ID] 371 // ,[p].[3] AS ADDRESS_LINE3 372 // ,[p].[2] AS ADDRESS_LINE2 373 // ,[p].[1] AS ADDRESS_LINE1 FROM [ADDRESS_LINES_CTE] 374 // PIVOT(MAX(value) FOR id IN ([1],[2],[3])) p 375 376 //relationAttributes.addAll(pivotClause.getAttributes()); 377 TAttributeNode.addAllNodesToList(pivotClause.getAttributes(),getAttributes()); 378 379 TTable sourceTable = this.getPivotedTable().getRelations().get(0); 380 // 如果 pivot alias clause 不为空,整个table的 prefix 都用这个alias 381 // 否则使用当前table的display name 382 String prefix; 383 if (pivotClause.getAliasClause() != null){ 384 prefix = pivotClause.getDisplayName(); 385 }else{ 386 prefix = sourceTable.getDisplayName(); 387 } 388 389 for(TAttributeNode node: sourceTable.getAttributes()){ 390 //relationAttributes.add(new TAttributeNode(prefix+"."+ TBaseType.getLastPartOfQualifiedName(node.getName()),sourceTable,node.getSubLevelResultColumn())); 391 TAttributeNode.addNodeToList(new TAttributeNode(prefix+"."+ TBaseType.getLastPartOfQualifiedName(node.getName()),sourceTable,node.getSubLevelResultColumn()),getAttributes()); 392 } 393 394 395 } 396 397 isAttributesInitialized = true; 398 } 399 400 /** 401 * 主要是在处理列级别的信息, 402 * 它的主要目的是确保 JOIN 操作后的表对象包含所有参与 JOIN 的表的列信息,这对于后续的查询处理(特别是列引用解析)是必要的。 403 */ 404 public void initAttributesForJoin(){ 405 //if (isAttributesInitialized) return; 406 //relationAttributes.addAll(getJoinExpr().getAttributes()); 407 TAttributeNode.addAllNodesToList(getJoinExpr().getAttributes(),getAttributes()); 408 isAttributesInitialized = true; 409 } 410 411 public void initAttributesForUnnest(TSQLEnv sqlEnv, TSelectSqlStatement select ){ 412 // if (isAttributesInitialized) return; 413 if (this.getAliasClause() != null){ 414 if (this.getAliasClause().getColumns() != null){ 415 for(TObjectName pColumn:this.getAliasClause().getColumns()){ 416 //relationAttributes.add( new TAttributeNode( this.getDisplayName()+"."+pColumn.toString() ,this)); 417 TAttributeNode.addNodeToList(new TAttributeNode( this.getDisplayName()+"."+pColumn.toString() ,this),getAttributes()); 418 } 419 }else if (this.getAliasClause().getAliasName() != null){ 420// SELECT * 421// FROM UNNEST(['foo', 'bar', 'baz', 'qux', 'corge', 'garply', 'waldo', 'fred']) AS element 422// WITH OFFSET AS offset 423 // add element as column of unnest table. 424 if (this.getUnnestClause().getColumns() != null){ 425 // UNCOVERED_MOVE_Stage1 AS 426 // (SELECT 427 // Instrument_Partition_Key , 428 // Consolidation_Entity_Levels , 429 // FOTC_UDF_calc_uncovered_roll_off(ARRAY_AGG(STRUCT<Partition_Key STRING , Order_Number INT64 , Movement_In_Short FLOAT64 , Short_Increase_Uncovered FLOAT64 , Short_Increase_Covered_CS FLOAT64 , Short_Increase_Covered_RR FLOAT64> (Instrument_Partition_Key , Order_Number , Movement_In_Short_Balance_LCY , Short_Increase_Uncovered , Maturing_CS_Covering_Short_Increase , Maturing_RR_Covering_Short_Increase) 430 // ORDER BY Order_Number)) AS result_uncovered_moves , 431 // FOTC_UDF_calc_uncovered_roll_off(ARRAY_AGG(STRUCT<Partition_Key STRING , Order_Number INT64 , Movement_In_Short FLOAT64 , Short_Increase_Uncovered FLOAT64 , Short_Increase_Covered_CS FLOAT64 , Short_Increase_Covered_RR FLOAT64> (Instrument_Partition_Key , Order_Number , Movement_In_Short_Balance_LCY , Short_Increase_Uncovered_By_Settled_RR , Maturing_CS_Covering_Short_Increase , Maturing_Settled_RR_Covering_Short_Increase) 432 // ORDER BY Order_Number)) AS result_uncovered_by_settled_moves 433 // FROM SHORTS_COVERING_RR 434 // GROUP BY 435 // Instrument_Partition_Key , 436 // Consolidation_Entity_Levels) , 437 // UNCOVERED_MOVE AS 438 // (SELECT 439 // Consolidation_Entity_Levels , 440 // X.* , 441 // Y.uncovered_move AS Move_Uncovered_By_Settled_RR_Short , 442 // Y.covered_cs_move AS Move_Covered_By_Settled_CS_Short , 443 // Y.covered_rr_move AS Move_Covered_By_Settled_RR_Short 444 // FROM 445 // UNCOVERED_MOVE_Stage1 , 446 // UNNEST(result_uncovered_moves) AS X 447 // JOIN UNNEST(result_uncovered_by_settled_moves) AS Y ON X.Partition_Key = Y.Partition_Key 448 // AND X.order_key= Y.order_key) 449 450 // UNNEST(result_uncovered_moves) 中的 result_uncovered_moves 来自 ARRAY_AGG(), 451 // 这时候因为还没有进行 column resolver,所以无法知道 result_uncovered_moves 到底包含哪些 column 452 // 因为 UNNEST(result_uncovered_moves) AS X 指定了 X 作为 Alias, 因此增加 X.* 作为 attributeNode 453 // 不会导致问题。 454 455 ArrayList<String> tf = null; 456 TObjectName objectName = this.getUnnestClause().getColumns().getObjectName(0); 457 for(TTable table: select.getRelations()){ 458 if (TParseTreeNode.subNodeInNode(this,table)) break; 459 for(TAttributeNode attributeNode:table.getAttributes()){ 460 int matchResult = TStmtScope.matchAttribute(objectName.toString(), attributeNode.getName(),0,select); 461 if (matchResult == TBaseType.MATCH_COLUMN_RESULT_MATCHED ) { 462 objectName.setSourceTableBySQLResolver(select,attributeNode,table); 463 objectName.setSourceAttributeNode(attributeNode); 464 break; 465 } 466 } 467 if (objectName.getSourceAttributeNode() != null){ 468 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 469 TBaseType.log(String.format("Unnest table from source column: <%s>, linked to attribute node: <%s>" 470 ,objectName.toString(),objectName.getSourceAttributeNode().getName()),TLog.DEBUG,objectName); 471 } 472 473 // unnest(column), 其中的 column 可能对应array, 或者是 struct 474 // 找一下看看是否有 struct 475 476 tf = TResolverHelpUtils.searchTypedStruct(sqlEnv, objectName.getSourceAttributeNode().getSubLevelResultColumn()); 477 break; 478 } 479 } 480 if (tf != null){ 481 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 482 TBaseType.log(String.format("Prepare attribute node for unnest %s",this.getDisplayName()),TLog.DEBUG,this.getStartToken()); 483 } 484 for(String columnName:tf){ 485 TAttributeNode newNode = new TAttributeNode(String.format("%s.%s",this.getDisplayName(),columnName),this,objectName.getSourceAttributeNode().getSubLevelResultColumn()); 486 //relationAttributes.add(newNode); 487 TAttributeNode.addNodeToList(newNode,relationAttributes); 488 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 489 TBaseType.log(String.format("\t attribute node from struct: %s.%s with source column: %s" 490 , this.getDisplayName(),columnName, objectName.getSourceAttributeNode().getSubLevelResultColumn()==null?"N/A":objectName.getSourceAttributeNode().getSubLevelResultColumn().toString() ),TLog.DEBUG,this.getStartToken()); 491 } 492 } 493 }else{ 494 //relationAttributes.add( new TAttributeNode( this.getDisplayName()+".*",this)); 495 TAttributeNode.addNodeToList(new TAttributeNode( this.getDisplayName()+".*",this),getAttributes()); 496 } 497 498 }else{ 499 //relationAttributes.add( new TAttributeNode( this.getDisplayName()+"."+this.getAliasClause().getAliasName().toString() ,this)); 500 TAttributeNode.addNodeToList(new TAttributeNode( this.getDisplayName()+"."+this.getAliasClause().getAliasName().toString() ,this),getAttributes()); 501 } 502 } 503 }else{ 504 //SELECT value FROM UNNEST(nested_attribute) 505 // #TODO, 未处理 UNNEST 中的 nested_attribute, nested_attribute 一般是一个 struct,那么应该把 struct 中的 column 也加入进来 506 // 没有指定输出 column 的name,默认为 value 507 //relationAttributes.add( new TAttributeNode( this.getDisplayName()+"."+"value" ,this)); 508 TAttributeNode.addNodeToList(new TAttributeNode( this.getDisplayName()+"."+"value" ,this),getAttributes()); 509 } 510 511 for(int i=0;i<getAttributes().size();i++){ 512 TAttributeNode node = getAttributes().get(i); 513 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 514 TBaseType.log(String.format("Prepare attribute node <%d> for unnest %s: %s",i+1,this.getDisplayName(),node.getName()),TLog.DEBUG,this.getStartToken()); 515 } 516 } 517 518 isAttributesInitialized = true; 519 } 520 521 522 523 524// private ArrayList<String> expandedAttributes = new ArrayList<>(); 525// 526// public ArrayList<String> getExpandedAttributes() { 527// return expandedAttributes; 528// } 529 530 531 public void addAttribute(TAttributeNode node) { 532 if (node == null) return; 533 534 // 检查是否已存在同名节点 535 for (TAttributeNode existing : getAttributes()) { 536 if (existing.getName().equals(node.getName())) { 537 return; 538 } 539 } 540 541 //relationAttributes.add(node); 542 TAttributeNode.addNodeToList(node,relationAttributes); 543 } 544 545 private ArrayList<TObjectName> attributesReferenceToThisRelation = new ArrayList<>(); 546 547 public ArrayList<TObjectName> getAttributesReferenceToThisRelation() { 548 return attributesReferenceToThisRelation; 549 } 550 551// public boolean resolveAttribute(TObjectName attribute){ 552// boolean result = false; 553// if (attribute.isQualified()) { 554// result = attribute.resolveWithThisTable(this); 555// if (result) { 556// attributesReferenceToThisRelation.add(attribute); 557// attribute.setResolvedRelation(this); 558// } 559// return result; 560// } 561// if (this.getResolvedTable() != null){ 562// result = this.getResolvedTable().searchColumn(attribute.toString()); 563// if (result){ 564// attribute.setResolvedRelation(this); 565// return result; 566// } 567// } 568// return result; 569// } 570 571 private TSQLTable resolvedTable = null; 572 private boolean isResolved = false; 573 private ETableCatalogStatus catalogStatus = ETableCatalogStatus.NOT_CHECKED; 574 575 public void setResolvedTable(TSQLTable resolvedTable) { 576 this.resolvedTable = resolvedTable; 577 isResolved = true; 578 // A catalog entry in hand is FOUND by definition. A null says nothing on its own: the 579 // caller that did the lookup knows whether there was metadata to look in, and says so 580 // through setCatalogStatus. 581 if (resolvedTable != null) { 582 catalogStatus = ETableCatalogStatus.FOUND; 583 } 584 } 585 586 /** 587 * Whether this table reference was found in the catalog metadata. A fact about the table, 588 * separate from which table a column belongs to: see {@link ETableCatalogStatus}. 589 */ 590 public ETableCatalogStatus getCatalogStatus() { 591 return catalogStatus; 592 } 593 594 public void setCatalogStatus(ETableCatalogStatus catalogStatus) { 595 this.catalogStatus = catalogStatus == null ? ETableCatalogStatus.NOT_CHECKED : catalogStatus; 596 } 597 598 public void setResolved(boolean resolved) { 599 isResolved = resolved; 600 } 601 602 public TSQLTable getResolvedTable() { 603 return resolvedTable; 604 } 605 606 public boolean isResolved() { 607 return isResolved; 608 } 609 610 private ArrayList<TObjectName> columnsFromSQLEnv; 611 612 public ArrayList<TObjectName> getColumnsFromSQLEnv(TSQLEnv sqlEnv) { 613 if (columnsFromSQLEnv == null){ 614 columnsFromSQLEnv = new ArrayList<>(); 615 } 616 617 ArrayList<String> columns = sqlEnv.getColumnsInTable(this.tableName.toString(),true); 618 if (columns == null) return null; 619 620 for(String s:columns){ 621 TObjectName column = TObjectName.createObjectName(this.dbvendor, EDbObjectType.column,new TSourceToken(s)); 622 columnsFromSQLEnv.add(column); 623 } 624 625 return columnsFromSQLEnv; 626 } 627 628 private TJoinExpr joinExpr; 629 630 public void setJoinExpr(TJoinExpr joinExpr) { 631 this.joinExpr = joinExpr; 632 } 633 634 public TJoinExpr getJoinExpr() { 635 return joinExpr; 636 } 637 638 /** 639 * 该 table 对应的 sqlenv 中的 table 定义,包含具体的字段信息,有字段名称、数据类型等。 640 * 641 */ 642// private TSQLTable sqlTable; 643// 644// public void setSqlTable(TSQLTable sqlTable) { 645// this.sqlTable = sqlTable; 646// } 647// 648// public TSQLTable getSqlTable() { 649// return sqlTable; 650// } 651 652 653 654 private TForXMLClause forXMLClause; 655 656 public void setForXMLClause(TForXMLClause forXMLClause) { 657 this.forXMLClause = forXMLClause; 658 } 659 660 /** 661 * SQL Server for xml clause 662 * @return SQL Server for xml clause 663 */ 664 public TForXMLClause getForXMLClause() { 665 return forXMLClause; 666 } 667 668 private TColumnDefinitionList columnDefinitions; 669 670 public TColumnDefinitionList getColumnDefinitions() { 671 return columnDefinitions; 672 } 673 674 /** Input correlation name inside a Teradata table operator's ON clause. */ 675 private TAliasClause tableOperatorInputAlias; 676 /** Partition expressions over the ON input, separate from its output alias. */ 677 private TPartitionClause tableOperatorPartitionBy; 678 /** Ordering of rows supplied to a Teradata table operator. */ 679 private TOrderBy tableOperatorOrderBy; 680 681 public TAliasClause getTableOperatorInputAlias() { return tableOperatorInputAlias; } 682 public void setTableOperatorInputAlias(TAliasClause value) { tableOperatorInputAlias = value; } 683 public TPartitionClause getTableOperatorPartitionBy() { return tableOperatorPartitionBy; } 684 public void setTableOperatorPartitionBy(TPartitionClause value) { tableOperatorPartitionBy = value; } 685 public TOrderBy getTableOperatorOrderBy() { return tableOperatorOrderBy; } 686 public void setTableOperatorOrderBy(TOrderBy value) { tableOperatorOrderBy = value; } 687 688 /** 689 * Teradata HASH BY clause for table functions. 690 */ 691 private THashByClause hashByClause; 692 693 /** 694 * Gets the HASH BY clause for Teradata table functions. 695 * 696 * @return the HASH BY clause, or null if not specified 697 */ 698 public THashByClause getHashByClause() { 699 return hashByClause; 700 } 701 702 /** 703 * Sets the HASH BY clause for Teradata table functions. 704 * 705 * @param hashByClause the HASH BY clause 706 */ 707 public void setHashByClause(THashByClause hashByClause) { 708 this.hashByClause = hashByClause; 709 } 710 711 /** 712 * Teradata LOCAL ORDER BY clause for table functions. 713 */ 714 private TOrderBy localOrderBy; 715 716 /** 717 * Gets the LOCAL ORDER BY clause for Teradata table functions. 718 * 719 * @return the LOCAL ORDER BY clause, or null if not specified 720 */ 721 public TOrderBy getLocalOrderBy() { 722 return localOrderBy; 723 } 724 725 /** 726 * Sets the LOCAL ORDER BY clause for Teradata table functions. 727 * 728 * @param localOrderBy the LOCAL ORDER BY clause 729 */ 730 public void setLocalOrderBy(TOrderBy localOrderBy) { 731 this.localOrderBy = localOrderBy; 732 } 733 734 private TSQLEnv sqlEnv; 735 736 public void setSqlEnv(TSQLEnv sqlEnv) { 737 this.sqlEnv = sqlEnv; 738 } 739 740 public TSQLEnv getSqlEnv() { 741 return sqlEnv; 742 } 743 744 private TValueClause valueClause; 745 746 public TValueClause getValueClause() { 747 return valueClause; 748 } 749 750 public void setValueClause(TValueClause valueClause) { 751 this.valueClause = valueClause; 752 } 753 754 private TTable sourceTableOfPivot; 755 756 public void setSourceTableOfPivot(TTable sourceTableOfPivot) { 757 this.sourceTableOfPivot = sourceTableOfPivot; 758 } 759 760 public TTable getSourceTableOfPivot() { 761 return sourceTableOfPivot; 762 } 763 764 private TJsonTable jsonTable; 765 766 public void setJsonTable(TJsonTable jsonTable) { 767 this.jsonTable = jsonTable; 768 } 769 770 public TJsonTable getJsonTable() { 771 return jsonTable; 772 } 773 774 public void setPropertyFromObjectName(TObjectName objectName, ETableEffectType tableEffectType){ 775 setStartToken(objectName.getStartToken()); 776 setEndToken(objectName.getEndToken()); 777 setGsqlparser(objectName.getGsqlparser()); 778 setEffectType(tableEffectType); 779 setTableType(ETableSource.objectname); 780 } 781 private TTDUnpivot tdUnpivot; 782 783 public void setTdUnpivot(TTDUnpivot tdUnpivot) { 784 this.tdUnpivot = tdUnpivot; 785 } 786 787 public TTDUnpivot getTdUnpivot() { 788 789 return tdUnpivot; 790 } 791 792 private TUnnestClause unnestClause; 793 794 public void setUnnestClause(TUnnestClause unnestClause) { 795 this.unnestClause = unnestClause; 796 } 797 798 public TUnnestClause getUnnestClause() { 799 800 return unnestClause; 801 } 802 //select b.TemaTakipNo, b.SevkID, db.FromDepo, db.ToDepo, d.UrunID UrunID1, r.UrunID2, d.Miktar AsortiMiktar, r.Miktar ReceteMiktar 803 //into #tmpIrsaliye 804 /** 805 * list of columns in select list, used as metadata to determine whether a column belong to this temp table in TCustomSqlStatement.linkColumnToTable 806 */ 807 private TResultColumnList columnListInTempTable; 808 809 public void setColumnListInTempTable(TResultColumnList columnListInTempTable) { 810 this.columnListInTempTable = columnListInTempTable; 811 } 812 813 public TResultColumnList getColumnListInTempTable() { 814 815 return columnListInTempTable; 816 } 817 818 public void setPxGranule(TPxGranule pxGranule) { 819 this.pxGranule = pxGranule; 820 } 821 822 public TPxGranule getPxGranule() { 823 824 return pxGranule; 825 } 826 827 private TPxGranule pxGranule; 828 private TFlashback flashback; 829 830 public void setFlashback(TFlashback flashback) { 831 this.flashback = flashback; 832 } 833 834 public TFlashback getFlashback() { 835 return flashback; 836 } 837 838 /** 839 * The expression that picks the point in time a table is read at: {@code AS OF <expr>} (Oracle flashback, 840 * Teradata temporal tables) or {@code AT | BEFORE (TIMESTAMP | OFFSET => <expr>)} (Snowflake time travel). 841 * 842 * @return the expression, or null when the table is read as it is now 843 */ 844 public TExpression getPointInTime() { 845 if ((flashback != null) && (flashback.getExpr() != null)) { 846 return flashback.getExpr(); 847 } 848 if (timeTravelClause != null) { 849 return timeTravelClause.getTimestamp() != null ? timeTravelClause.getTimestamp() : timeTravelClause.getOffset(); 850 } 851 return null; 852 } 853 854 private int parenthesisCount = 0; 855 private int parenthesisAfterAliasCount = 0; 856 private boolean tableKeyword = false; 857 private boolean onlyKeyword = false; 858 private boolean npathOnClauseTable = false; 859 860 /** 861 * Redshift array-unnesting positional index alias. 862 * <p> 863 * When a Redshift array column is unnested in the FROM clause with a 864 * positional index, e.g. 865 * <pre>FROM schema.tbl t, t.array_col AS element AT idx</pre> 866 * this table represents {@code t.array_col} with element alias 867 * {@code element} (the regular {@link #getAliasClause() aliasClause}) and 868 * {@code idx} captured here as the array index alias. 869 */ 870 private TObjectName arrayIndexAlias; 871 872 public TObjectName getArrayIndexAlias() { 873 return arrayIndexAlias; 874 } 875 876 public void setArrayIndexAlias(TObjectName arrayIndexAlias) { 877 this.arrayIndexAlias = arrayIndexAlias; 878 } 879 880 /** 881 * Redshift SUPER object unpivoting source, e.g. 882 * <pre>FROM c.c_orders AS o, UNPIVOT o AS val AT attr</pre> 883 * When {@code true} this table represents the unpivoted SUPER expression: 884 * the regular alias is the value alias and {@link #getArrayIndexAlias()} 885 * (from {@code AT}) is the attribute-name alias. 886 */ 887 private boolean superUnpivot = false; 888 889 public boolean isSuperUnpivot() { 890 return superUnpivot; 891 } 892 893 public void setSuperUnpivot(boolean superUnpivot) { 894 this.superUnpivot = superUnpivot; 895 } 896 897 /** 898 * Marks this table as coming from a Teradata NPath function's ON clause. 899 * This is used for data lineage to trace back to the source table inside NPath. 900 */ 901 public void setNPathOnClauseTable(boolean npathOnClauseTable) { 902 this.npathOnClauseTable = npathOnClauseTable; 903 } 904 905 /** 906 * Returns true if this table comes from a Teradata NPath function's ON clause. 907 */ 908 public boolean isNPathOnClauseTable() { 909 return npathOnClauseTable; 910 } 911 912 public void setTableKeyword(boolean tableKeyword) { 913 this.tableKeyword = tableKeyword; 914 } 915 916 public void setOnlyKeyword(boolean onlyKeyword) { 917 this.onlyKeyword = onlyKeyword; 918 } 919 920 public boolean isTableKeyword() { 921 922 return tableKeyword; 923 } 924 925 public boolean isOnlyKeyword() { 926 return onlyKeyword; 927 } 928 929 public void setParenthesisCount(int parenthesisCount) { 930 this.parenthesisCount = parenthesisCount; 931 } 932 933 public void setParenthesisAfterAliasCount(int parenthesisAfterAliasCount) { 934 this.parenthesisAfterAliasCount = parenthesisAfterAliasCount; 935 } 936 937 public int getParenthesisCount() { 938 939 return parenthesisCount; 940 } 941 942 public int getParenthesisAfterAliasCount() { 943 return parenthesisAfterAliasCount; 944 } 945 946 private TMergeSqlStatement outputMerge; 947 948 public void setOutputMerge(TMergeSqlStatement outputMerge) { 949 this.outputMerge = outputMerge; 950 } 951 952 public TMergeSqlStatement getOutputMerge() { 953 954 return outputMerge; 955 } 956 957 private TPivotedTable pivotedTable; 958 959 public void setPivotedTable(TPivotedTable pivotedTable) { 960 this.pivotedTable = pivotedTable; 961 } 962 963 public TPivotedTable getPivotedTable() { 964 965 return pivotedTable; 966 } 967 968 private ETableEffectType effectType; 969 970 public void setEffectType(ETableEffectType effectType) { 971 this.effectType = effectType; 972 } 973 974 public ETableEffectType getEffectType() { 975 976 return effectType; 977 } 978 979 private TTable linkTable; 980 981 public void setLinkTable(TTable linkTable) { 982 this.linkTable = linkTable; 983 isLinkTable = (this.linkTable != null); 984 } 985 986 public TTable getLinkTable() { 987 988 return linkTable; 989 } 990 991 public boolean isLinkTable() { 992 return isLinkTable; 993 } 994 995 /** 996 * @deprecated As of v1.8.4.6, set in {@link #setLinkTable} 997 */ 998 public void setLinkTable(boolean isLinkTable) { 999 1000 this.isLinkTable = isLinkTable; 1001 } 1002 1003 private boolean isLinkTable; 1004 1005 1006 public String getAliasName(){ 1007 if (getAliasClause() == null) return ""; 1008 TObjectName aliasName = getAliasClause().getAliasName(); 1009 return (aliasName == null) ? "" : aliasName.toString(); 1010 } 1011 1012 public boolean equalByName(String pTableName){ 1013 if (getAliasClause() != null){ 1014 return SQLUtil.sameName(this.dbvendor, ESQLDataObjectType.dotTable, getAliasClause().getAliasName().toString(), pTableName); 1015 }else{ 1016 return SQLUtil.compareIdentifier(this.dbvendor, ESQLDataObjectType.dotTable, getName(), pTableName); 1017 } 1018 } 1019 1020 private TPTNodeList<THiveKeyValueProperty> tableProperties; 1021 1022 public void setTableProperties(TPTNodeList<THiveKeyValueProperty> tableProperties) { 1023 this.tableProperties = tableProperties; 1024 } 1025 1026 /** 1027 * 1028 * @return hive table property list 1029 */ 1030 1031 public TPTNodeList<THiveKeyValueProperty> getTableProperties() { 1032 return tableProperties; 1033 } 1034 1035 private ArrayList<TLateralView> lateralViewList = null; 1036 1037 public void setLateralViewList(ArrayList<TLateralView> lateralViewList) { 1038 this.lateralViewList = lateralViewList; 1039 } 1040 1041 /** For the table of a LATERAL VIEW ({@link ETableSource#lateralView}), the view it was made from. */ 1042 private TLateralView lateralView; 1043 1044 /** 1045 * The LATERAL VIEW this table stands for when it is the relation a Hive-family {@code LATERAL VIEW} adds to its 1046 * SELECT ({@link TLateralView#createATable}); null for any other table. 1047 */ 1048 public TLateralView getLateralView() { 1049 return lateralView; 1050 } 1051 1052 public void setLateralView(TLateralView lateralView) { 1053 this.lateralView = lateralView; 1054 } 1055 1056 public ArrayList<TLateralView> getLateralViewList() { 1057 return lateralViewList; 1058 1059 } 1060 1061 /** 1062 * The columns this FROM item's call generates, in order (a built-in table function, {@code UNNEST}, a Hive-family 1063 * {@code LATERAL VIEW} generator), by the rule resolver2 resolves their names with 1064 * ({@link gudusoft.gsqlparser.resolver2.namespace.TableFunctionLayout}); null when the rule does not settle the 1065 * call's columns. An element is null for a column the vendor leaves without a name a query can use. 1066 * 1067 * @since 4.2.17 1068 */ 1069 public java.util.List<String> getLateralColumnNames() { 1070 gudusoft.gsqlparser.resolver2.namespace.TableFunctionLayout layout = 1071 gudusoft.gsqlparser.resolver2.namespace.TableFunctionLayout.of(this); 1072 return layout == null ? null : layout.getNames(); 1073 } 1074 1075 /** 1076 * Per column of {@link #getLateralColumnNames()}, the indexes in {@link #getLateralArguments()} of the arguments 1077 * whose values make it ({@code "0,1"}), or the empty string for a column computed over the generated rows (an 1078 * ordinal); null when the arguments are not settled. 1079 * 1080 * @since 4.2.17 1081 */ 1082 public java.util.List<String> getLateralColumnInputs() { 1083 gudusoft.gsqlparser.resolver2.namespace.TableFunctionLayout layout = 1084 gudusoft.gsqlparser.resolver2.namespace.TableFunctionLayout.of(this); 1085 return layout == null ? null : layout.getInputs(); 1086 } 1087 1088 /** 1089 * The indexes in {@link #getLateralArguments()} of the arguments whose values decide the rows the call generates 1090 * ({@code "0,1"}; empty when none, as for an array literal), or null when the rule does not settle the rows. The 1091 * rows can be settled while the columns are not ({@link #getLateralColumnNames()} null). 1092 * 1093 * @since 4.2.17 1094 */ 1095 public String getLateralRowInputs() { 1096 gudusoft.gsqlparser.resolver2.namespace.TableFunctionLayout layout = 1097 gudusoft.gsqlparser.resolver2.namespace.TableFunctionLayout.of(this); 1098 return layout == null ? null : layout.getRowInputs(); 1099 } 1100 1101 /** 1102 * Whether {@link #getLateralColumnNames()} are all the call's columns (false for an array of unknown element type, 1103 * whose STRUCT or ROW fields would be columns of their own). 1104 * 1105 * @since 4.2.17 1106 */ 1107 public boolean isLateralLayoutClosed() { 1108 gudusoft.gsqlparser.resolver2.namespace.TableFunctionLayout layout = 1109 gudusoft.gsqlparser.resolver2.namespace.TableFunctionLayout.of(this); 1110 return layout != null && layout.isClosed(); 1111 } 1112 1113 /** 1114 * The arguments {@link #getLateralColumnInputs()} index: the call's argument expressions (a named argument's 1115 * value), or the arrays of an {@code UNNEST} (an expression, or the column name of its legacy form); null when the 1116 * call has no layout. 1117 * 1118 * @since 4.2.17 1119 */ 1120 public java.util.List<TParseTreeNode> getLateralArguments() { 1121 gudusoft.gsqlparser.resolver2.namespace.TableFunctionLayout layout = 1122 gudusoft.gsqlparser.resolver2.namespace.TableFunctionLayout.of(this); 1123 return layout == null ? null : layout.getArguments(); 1124 } 1125 1126 private java.util.List<String> declaredFunctionColumns; 1127 1128 /** 1129 * The columns of the user table function this FROM item calls, as the catalog declares them (a CREATE FUNCTION of 1130 * the input registered before the call, or catalog metadata): recorded by resolver2 when it resolves the call, so 1131 * that {@link #getLateralColumnNames()} and resolver2 read one layout. Null when none is known. 1132 * 1133 * @since 4.2.17 1134 */ 1135 public java.util.List<String> getDeclaredFunctionColumns() { 1136 return declaredFunctionColumns; 1137 } 1138 1139 /** 1140 * Sets the declared columns of the user table function this FROM item calls (see 1141 * {@link #getDeclaredFunctionColumns()}). 1142 * 1143 * @since 4.2.17 1144 */ 1145 public void setDeclaredFunctionColumns(java.util.List<String> columns) { 1146 this.declaredFunctionColumns = columns == null ? null 1147 : java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(columns)); 1148 } 1149 1150 private TTableSample tableSample; 1151 1152 public void setTableSample(TTableSample tableSample) { 1153 this.tableSample = tableSample; 1154 } 1155 1156 public TTableSample getTableSample() { 1157 1158 return tableSample; 1159 } 1160 1161 public void setPartitionExtensionClause(TPartitionExtensionClause partitionExtensionClause) { 1162 this.partitionExtensionClause = partitionExtensionClause; 1163 } 1164 1165 private TPartitionExtensionClause partitionExtensionClause; 1166 1167 public TPartitionExtensionClause getPartitionExtensionClause() { 1168 return partitionExtensionClause; 1169 } 1170 1171 public void setOuterClause(TInformixOuterClause outerClause) { 1172 this.outerClause = outerClause; 1173 } 1174 1175 public TInformixOuterClause getOuterClause() { 1176 1177 return outerClause; 1178 } 1179 1180 private TInformixOuterClause outerClause; 1181 1182 private TXmlTable xmlTable; 1183 1184 private TFromTableList fromTableList; 1185 1186 public void setFromTableList(TFromTableList fromTableList) { 1187 this.fromTableList = fromTableList; 1188 } 1189 1190 public TFromTableList getFromTableList() { 1191 1192 return fromTableList; 1193 } 1194 1195 public TXmlTable getXmlTable() { 1196 return xmlTable; 1197 } 1198 1199 public void setXmlTable(TXmlTable xmlTable) { 1200 1201 this.xmlTable = xmlTable; 1202 } 1203 1204 private TOpenQuery openquery = null; 1205 1206 public void setTableHintList(TPTNodeList<TTableHint> tableHintList) { 1207 this.tableHintList = tableHintList; 1208 } 1209 1210 1211 public TPTNodeList<TTableHint> getTableHintList() { 1212 1213 return tableHintList; 1214 } 1215 1216 private TPTNodeList<TTableHint> tableHintList; 1217 1218 public TOpenQuery getOpenquery() { 1219 return openquery; 1220 } 1221 1222 public TSelectSqlStatement getSubquery() { 1223 return subquery; 1224 } 1225 1226 public void setOpenquery(TOpenQuery openquery) { 1227 1228 this.openquery = openquery; 1229 } 1230 1231 public void setOpenDatasource(TOpenDatasource openDatasource) { 1232 this.openDatasource = openDatasource; 1233 } 1234 1235 /** 1236 * Valid when {@link #tableType} is ftt_opendatasource. 1237 * @return 1238 */ 1239 public TOpenDatasource getOpenDatasource() { 1240 1241 return openDatasource; 1242 } 1243 1244 private TOpenDatasource openDatasource = null; 1245 1246 public void setOpenXML(TOpenXML openXML) { 1247 this.openXML = openXML; 1248 } 1249 1250 public TOpenXML getOpenXML() { 1251 1252 return openXML; 1253 } 1254 1255 private TOpenXML openXML = null; 1256 1257 public TOpenRowSet getOpenRowSet() { 1258 return openRowSet; 1259 } 1260 1261 public void setOpenRowSet(TOpenRowSet openRowSet) { 1262 1263 this.openRowSet = openRowSet; 1264 } 1265 1266 private TOpenRowSet openRowSet = null; 1267 1268 public TContainsTable getContainsTable() { 1269 return containsTable; 1270 } 1271 1272 public void setContainsTable(TContainsTable containsTable) { 1273 this.containsTable = containsTable; 1274 } 1275 1276 private TContainsTable containsTable = null; 1277 1278 public TFunctionCall getFuncCall() { 1279 return funcCall; 1280 } 1281 1282 public void setFuncCall(TFunctionCall funcCall) { 1283 this.funcCall = funcCall; 1284 } 1285 1286 1287 private TFunctionCall funcCall = null; 1288 1289 private TMultiTargetList rowList; 1290 1291 /** 1292 * @deprecated As of v2.3.6.9, please use {@link #getValueClause()} instead 1293 * 1294 * row constructor like this: '(' RW_VALUES MultiTargets ')' 1295 * @return TMultiTargetList 1296 */ 1297 public TMultiTargetList getRowList() { 1298 return rowList; 1299 } 1300 1301 public boolean isBaseTable(){ 1302 boolean retval = (tableType == ETableSource.objectname); 1303 if (retval){ 1304 if (isCTEName()){ 1305 retval = false; 1306 } 1307 } 1308 1309 if (retval){ 1310 if (getFullName().startsWith("@")) { 1311 retval = false; 1312 } 1313 } 1314 return retval; 1315 } 1316 1317 public void setCteColomnReferences(TObjectNameList cteColomnReferences) { 1318 this.cteColomnReferences = cteColomnReferences; 1319 } 1320 1321 private TObjectNameList cteColomnReferences = null; 1322 1323 public TObjectNameList getCteColomnReferences() { 1324 return cteColomnReferences; 1325 } 1326 1327 public void setObjectNameReferences(TObjectNameList objectNameReferences) { 1328 1329 this.objectNameReferences = objectNameReferences; 1330 } 1331 1332 private TCTE CTE; 1333 1334 public boolean setCTE(TCTE pCTE) { 1335 if (pCTE == null){ 1336 this.CTE = null; 1337 return true; 1338 } 1339 1340 if ((!pCTE.isRecursive()) && (pCTE.getSubquery() != null) && (TParseTreeNode.subNodeInNode(this,pCTE.getSubquery()))){ 1341 // 如果这个table是属于一个CTE的子查询,那么不再设置CTE,因为该table不可能是该CTE的引用, 但前提条件是 1342 // 1. 该 subquery 非 combined query 1343 // 2. 如果该 subquery 是 combined query , 该 table 属于第一个subquery 中的 table 1344 1345 // 如果不是以上两种情况,那么该table就是该CTE的引用,需要返回 true 1346 // refer to: public void testSearchTable1() 1347 1348 if (!pCTE.getSubquery().isCombinedQuery()) return false; 1349 1350 if (TParseTreeNode.subNodeInNode(this,pCTE.getSubquery().getLeftStmt())){ 1351 return false; 1352 } 1353 1354 } 1355 1356 this.CTE = pCTE; 1357 return true; 1358 } 1359 1360 public TCTE getCTE() { 1361 1362 return CTE; 1363 } 1364 1365 public boolean isCTEName() { 1366 1367 return isCTEName; 1368 } 1369 1370 public void setCTEName(boolean CTEName) { 1371 isCTEName = CTEName; 1372 } 1373 1374 private boolean isCTEName = false; 1375 1376 public TSelectSqlStatement subquery = null; 1377 private THiveFromQuery hiveFromQuery; 1378 1379 public void setHiveFromQuery(THiveFromQuery hiveFromQuery) { 1380 this.hiveFromQuery = hiveFromQuery; 1381 } 1382 1383 /** 1384 * @deprecated As of v2.1.0.0, please use {@link #getSubquery()} 1385 * @return 1386 */ 1387 public THiveFromQuery getHiveFromQuery() { 1388 1389 return hiveFromQuery; 1390 } 1391 1392 public TExpression getTableExpr() { 1393 return tableExpr; 1394 } 1395 1396 public void setTableExpr(TExpression tableExpr) { 1397 this.tableExpr = tableExpr; 1398 } 1399 1400 private TExpression tableExpr; 1401 1402 public void setTableType(ETableSource tableType) { 1403 this.tableType = tableType; 1404 } 1405 1406 /** 1407 * 1408 * @return what's kind of type this table is. 1409 *<ul> 1410 * <li>{@link ETableSource#objectname}, in from clause, a simple table/view name, reference: {@link TTable#tableName}<li> 1411 * <li>{@link ETableSource#subquery}, is a subquery that retrieves rows from the database, also known as derived table. reference: {@link TTable#subquery}</li> 1412 * <li>{@link ETableSource#tableExpr},it's usually a table-valued expression., reference: {@link TTable#tableExpr}</li> 1413 * <li>{@link ETableSource#function}, it's usually a table-valued function., reference: {@link TTable#funcCall}</li> 1414 * <li>{@link ETableSource#rowList}, it's constructed rows, reference: {@link TTable#rowList}</li> 1415 * <li>{@link ETableSource#containsTable}, CONTAINSTABLE clause of sql server. reference: {@link TTable#containsTable}, type of {@link TContainsTable}</li> 1416 * <li>{@link ETableSource#freetextTable}, FREETEXTTABLE clause of sql server. reference: {@link TTable#containsTable}, type of {@link TContainsTable}</li> 1417 * <li>{@link ETableSource#openrowset}, OPENROWSET clause of sql server. reference: {@link TTable#openRowSet}, type of {@link TOpenRowSet}</li> 1418 * <li>{@link ETableSource#openxml}, OPENXML clause of sql server. reference: {@link TTable#openXML}, type of {@link TOpenXML }</li> 1419 * <li>{@link ETableSource#opendatasource}, OPENDATASOURCE clause of sql server. reference: {@link TTable#openDatasource}, type of {@link TOpenDatasource}</li> 1420 * <li>{@link ETableSource#openquery}, OPENQUERY clause of sql server. reference: {@link TTable#openquery}, type of (@link TOpenQuery)</li> 1421 * </ul> 1422 */ 1423 public ETableSource getTableType() { 1424 1425 return tableType; 1426 } 1427 1428 private ETableSource tableType; 1429 1430 public void setTableName(TObjectName tableName) { 1431 this.tableName = tableName; 1432 tableType = ETableSource.objectname; 1433 this.tableName.splitNameInQuotedIdentifier(); 1434 if (this.getStartToken() == null){ 1435 this.setStartToken(tableName.getStartToken()); 1436 } 1437 1438 if (this.getEndToken() == null){ 1439 this.setEndToken(tableName.getEndToken()); 1440 } 1441 } 1442 1443 public TObjectName getTableName() { 1444 TObjectName ret = tableName; 1445 1446 if (tableType == null) return ret; 1447 1448 switch (tableType){ 1449 case tableExpr: 1450 if (tableExpr.getExpressionType() == EExpressionType.function_t){ 1451 ret = tableExpr.getFunctionCall().getFunctionName(); 1452 } 1453 break; 1454 case function: 1455 ret = getFuncCall().getFunctionName(); 1456 break; 1457 case openrowset: 1458 ret = TObjectName.createObjectName (this.dbvendor, EDbObjectType.table,new TSourceToken("openrowset")); 1459 break; 1460 case rowList: 1461 ret = TObjectName.createObjectName (this.dbvendor, EDbObjectType.table,new TSourceToken("(values_table)")); 1462 break; 1463 case subquery: 1464 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("subquery")); 1465 break; 1466 case td_unpivot: 1467 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("td_unpivot")); 1468 break; 1469 case pivoted_table: 1470 // Check if this is an UNPIVOT to use the correct suffix 1471 String pivotSuffix = "(piviot_table)"; 1472 if (getPivotedTable() != null && getPivotedTable().getPivotClause() != null 1473 && getPivotedTable().getPivotClause().getType() == TPivotClause.unpivot) { 1474 pivotSuffix = "(unpivot_table)"; 1475 } 1476 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken(tableName+pivotSuffix)); 1477 break; 1478 case xmltable: 1479 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("xmltable")); 1480 break; 1481 case jsonTable: 1482 ret = getJsonTable().getFunctionName();// TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("jsontable"));// 1483 break; 1484 case containsTable: 1485 if (containsTable.getType() == TContainsTable.containstable){ 1486 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("containsTable")); 1487 }else { 1488 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("freetexttable")); 1489 } 1490 break; 1491 case opendatasource: 1492 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("opendatasource")); 1493 break; 1494 case unnest: 1495 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken(getAliasName()+"(unnest table)")); 1496 break; 1497 case openxml: 1498 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("openxml")); 1499 break; 1500 case openquery: 1501 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("openquery")); 1502 break; 1503 case output_merge: 1504 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("merge")); 1505 break; 1506 case externalTable: 1507 ret = this.tableName; 1508 break; 1509 case join: 1510 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("join_expr")); 1511 break; 1512 } 1513 if (ret == null) { 1514 return TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("unknown")); 1515 } 1516 else return ret; 1517 } 1518 1519 private TObjectName tableName; 1520 1521 public TTable(TObjectName pobjectname){ 1522 this.tableName = pobjectname; 1523 this.setStartToken(this.tableName.getStartToken()); 1524 this.setEndToken(this.tableName.getEndToken()); 1525 } 1526 1527 1528 public TTable(){ 1529 this.tableName = null; 1530 } 1531 1532 public String getName() { 1533 if (tableName != null) 1534 return tableName.getObjectString(); 1535 else 1536 return getTableName().toString(); 1537 } 1538 1539 1540 public String getPrefixServer(){ 1541 if (tableName != null) return tableName.getServerString(); 1542 else return ""; 1543 } 1544 public String getPrefixDatabase(){ 1545 if (tableName != null) return tableName.getDatabaseString(); 1546 else return ""; 1547 } 1548 public String getPrefixSchema(){ 1549 if (tableName != null) return tableName.getSchemaString(); 1550 else return ""; 1551 } 1552 1553 public boolean isIncludeColumnAlias(){ 1554 // return (this.getAliasClause() != null); 1555 return false; 1556 // ToDo 1557 } 1558 1559 1560 public int searchColumnInAlias(TObjectName pColumn){ 1561 if (getAliasClause() == null) return -1; 1562 return getAliasClause().searchColumn(pColumn); 1563 } 1564 1565 public boolean checkTableByName(String pTablename){ 1566 boolean lcResult = false; 1567 String a,b,c; 1568 b = TBaseType.getTextWithoutQuoted(pTablename); 1569 if (this.getAliasClause() != null){ 1570 a = TBaseType.getTextWithoutQuoted(this.getAliasName()); 1571 lcResult = a.equalsIgnoreCase(b); 1572 } 1573 if (lcResult) return true; 1574 c = TBaseType.getTextWithoutQuoted(this.getTableName().toString()); 1575 lcResult = c.equalsIgnoreCase(b); 1576 return lcResult; 1577 } 1578 1579 public boolean searchColumn(TSelectSqlStatement select, String tableName, TObjectName pColumn, boolean pMustIn){ 1580 // pColumn maybe qualified, so check the table name at first 1581 boolean lcResult = false, isSameTable = false; 1582 if ( tableName.length() == 0){ 1583 isSameTable = true; 1584 }else { 1585 isSameTable = checkTableByName(tableName); 1586 } 1587 1588 if (!isSameTable) return lcResult; 1589 1590 if (this.isBaseTable()){ 1591 lcResult = select.fireOnMetaDatabaseTableColumn(this.getPrefixServer(),this.getPrefixDatabase(),this.getPrefixSchema(),this.getName(),pColumn.getColumnNameOnly()); 1592 }else{ 1593 if (this.getTableType() == ETableSource.subquery){ 1594 if (this.isIncludeColumnAlias()){ 1595 lcResult = this.searchColumnInAlias(pColumn)>=0; 1596 }else{ 1597 lcResult = this.getSubquery().searchColumnInResultSet(pColumn,pMustIn); 1598 } 1599 }else if (this.isCTEName()){ 1600 lcResult = this.getCTE().searchColumnInResultSet(select,this,pColumn,pMustIn); 1601 } 1602 } 1603 1604 if (lcResult){ 1605 this.getLinkedColumns().addObjectName(pColumn); 1606 pColumn.setSourceTable(this); 1607 }else if (pMustIn){ 1608 this.getLinkedColumns().addObjectName(pColumn); 1609 pColumn.setSourceTable(this); 1610 lcResult = true; 1611 } 1612 1613 if (!lcResult){ 1614 if (this.getTableType() == ETableSource.pivoted_table){ 1615 if (this.getLinkedColumns().size() > 0){ 1616 for(TObjectName c: this.getLinkedColumns()){ 1617 lcResult = c.toString().equalsIgnoreCase(pColumn.getColumnNameOnly()); 1618 if (lcResult) break; 1619 } 1620 } 1621 } 1622 } 1623 1624 return lcResult; 1625 } 1626 1627 private TObjectNameList linkedColumns = null; 1628 1629 /** 1630 * @deprecated , this method is deprecated since version 3.3.1.0, don't use it in TSQLResolver2 1631 * @return 1632 */ 1633 public TObjectNameList getLinkedColumns() { 1634 if (linkedColumns == null) { 1635 linkedColumns = new TObjectNameList(); 1636 linkedColumns.setObjectType(TObjectName.ttobjColumn); 1637 } 1638 return linkedColumns; 1639 } 1640 1641 1642 1643 public String getFullNameWithAliasString() { 1644 if (getAliasClause() != null){ 1645 return getFullName()+" "+getAliasClause().toString(); 1646 }else{ 1647 return getFullName(); 1648 } 1649 } 1650 1651 public String getFullName() { 1652 if (tableName == null) return null; 1653 return tableName.toString(); 1654 /* 1655 if (tableName.getSchemaString() == null) 1656 {return this.getName();} 1657 else{ 1658 return tableName.getSchemaString()+"."+this.getName(); 1659 } 1660 */ 1661 1662 } 1663 1664 /** 1665 * 1666 * @return column name related to this table. 1667 * @deprecated As of v1.6.0.1, use {@link #getLinkedColumns()} instead 1668 */ 1669 public TObjectNameList getObjectNameReferences() { 1670 if (objectNameReferences == null){ 1671 objectNameReferences = new TObjectNameList(); 1672 objectNameReferences.setObjectType(TObjectName.ttobjColumn); 1673 } 1674 return objectNameReferences; 1675 } 1676 1677 private TPivotClause pivotClause = null; 1678 1679 public void setPivotClause(TPivotClause pivotClause) { 1680 this.pivotClause = pivotClause; 1681 } 1682 1683 /** 1684 * @deprecated As of v1.6.2.4, replaced by {@link gudusoft.gsqlparser.nodes.TPivotedTable} 1685 * @return 1686 */ 1687 public TPivotClause getPivotClause() { 1688 1689 return pivotClause; 1690 } 1691 1692 /** 1693 * Stored all column names that belong to this table. 1694 */ 1695 private TObjectNameList objectNameReferences = null; 1696 1697 public TTableReferenceList tablerefs = new TTableReferenceList(); 1698 1699 private TDataChangeTable datachangeTable = null; 1700 1701 public void setDatachangeTable(TDataChangeTable datachangeTable) { 1702 this.datachangeTable = datachangeTable; 1703 } 1704 1705 /** 1706 * DB2 data change 1707 * @return 1708 */ 1709 public TDataChangeTable getDatachangeTable() { 1710 return datachangeTable; 1711 } 1712 1713 1714 public boolean isTableRefBelongToThisTable(TTableReference tableref){ 1715 1716 boolean retval = (this.tableName == tableref.objectname); 1717 if (retval) {return retval;} 1718 if (SQLUtil.sameName(this.dbvendor, ESQLDataObjectType.dotTable, this.tableName.getObjectString(), tableref.objectname.getObjectString())){ 1719 if ((this.tableName.getSchemaString() == null) 1720 ||(tableref.objectname.getSchemaString() == null) 1721 ) { 1722 retval = true; 1723 }else{ 1724 retval = SQLUtil.sameName(this.dbvendor, ESQLDataObjectType.dotSchema, this.tableName.getSchemaString(), tableref.objectname.getSchemaString()); 1725 } 1726 } 1727 return retval; 1728 } 1729 1730 public void accept(TParseTreeVisitor v){ 1731 v.preVisit(this); 1732 1733 v.postVisit(this); 1734 } 1735 1736 public void setColumnDefinitions(TColumnDefinitionList columnDefinitions) { 1737 this.columnDefinitions = columnDefinitions; 1738 } 1739 1740 public void acceptChildren(TParseTreeVisitor v){ 1741 v.preVisit(this); 1742 1743 switch(getTableType()){ 1744 case objectname:{ 1745 getTableName().acceptChildren(v); 1746 if (getFlashback() != null){ 1747 getFlashback().acceptChildren(v); 1748 } 1749 if (getTimeTravelClause() != null){ 1750 getTimeTravelClause().acceptChildren(v); 1751 } 1752 break; 1753 } 1754 case tableExpr:{ 1755 getTableExpr().acceptChildren(v); 1756 break; 1757 } 1758 case subquery:{ 1759 getSubquery().acceptChildren(v); 1760 break; 1761 } 1762 case function:{ 1763 getFuncCall().acceptChildren(v); 1764 break; 1765 } 1766 case pivoted_table:{ 1767 if (this.getEffectType() == ETableEffectType.tetPivot) break; 1768 getPivotedTable().acceptChildren(v); 1769 break; 1770 } 1771 case output_merge:{ 1772 if (getOutputMerge() != null) getOutputMerge().acceptChildren(v); 1773 //e_table_reference.setTextContent(node.getOutputMerge().toString()); 1774 break; 1775 } 1776 case containsTable:{ 1777 getContainsTable().acceptChildren(v); 1778 break; 1779 } 1780 1781 case openrowset:{ 1782 getOpenRowSet().acceptChildren(v); 1783 break; 1784 } 1785 1786 case openxml:{ 1787 getOpenXML().acceptChildren(v); 1788 break; 1789 } 1790 1791 case opendatasource:{ 1792 getOpenDatasource().acceptChildren(v); 1793 break; 1794 } 1795 1796 case openquery:{ 1797 getOpenquery().acceptChildren(v); 1798 break; 1799 } 1800 1801 case datachangeTable:{ 1802 getDatachangeTable().acceptChildren(v); 1803 break; 1804 } 1805 case rowList:{ 1806 getValueClause().acceptChildren(v); 1807 break; 1808 } 1809 case xmltable:{ 1810 getXmlTable().acceptChildren(v); 1811 break; 1812 } 1813 case jsonTable:{ 1814 getJsonTable().acceptChildren(v); 1815 break; 1816 } 1817 case informixOuter:{ 1818 getOuterClause().acceptChildren(v); 1819 break; 1820 } 1821 1822 case table_ref_list:{ 1823 getFromTableList().acceptChildren(v); 1824 break; 1825 } 1826 case hiveFromQuery:{ 1827 getHiveFromQuery().acceptChildren(v); 1828 break; 1829 } 1830 case externalTable: 1831 this.columnDefinitions.acceptChildren(v); 1832 break; 1833 case join: 1834 this.joinExpr.acceptChildren(v); 1835 break; 1836 case unnest: 1837 this.getUnnestClause().acceptChildren(v); 1838 break; 1839 default: 1840 //sb.append(node.toString().replace(">",">").replace("<","<")); 1841 break; 1842 1843 } 1844 1845 1846 if (tableOperatorPartitionBy != null) tableOperatorPartitionBy.acceptChildren(v); 1847 if (tableOperatorOrderBy != null) tableOperatorOrderBy.acceptChildren(v); 1848 1849 if (getPxGranule() != null){ 1850 getPxGranule().acceptChildren(v); 1851 } 1852 1853 if (getTableSample() != null){ 1854 getTableSample().acceptChildren(v); 1855 } 1856 1857 if (getAliasClause() != null){ 1858 getAliasClause().acceptChildren(v); 1859 } 1860 1861 1862 if (getTableHintList() != null){ 1863 for(int i=0;i<getTableHintList().size();i++){ 1864 TTableHint tableHint = getTableHintList().getElement(i); 1865 tableHint.acceptChildren(v); 1866 } 1867 } 1868 1869 if (getLateralViewList() != null){ 1870 for(TLateralView lateralView:getLateralViewList()){ 1871 lateralView.acceptChildren(v); 1872 } 1873 } 1874 1875 1876 v.postVisit(this); 1877 } 1878 1879 public void setRowList(TMultiTargetList rowList) { 1880 this.rowList = rowList; 1881 } 1882 1883 public void setSubquery(TSelectSqlStatement subquery) { 1884 this.subquery = subquery; 1885 } 1886 1887 public void setLinkedColumns(TObjectNameList linkedColumns) { 1888 this.linkedColumns = linkedColumns; 1889 } 1890 1891 public void setTablerefs(TTableReferenceList tablerefs) { 1892 this.tablerefs = tablerefs; 1893 } 1894 1895 private boolean starColumnExpanded = false; 1896 1897 private ArrayList<String> expandedStarColumns = new ArrayList<String>(); 1898 1899 private void getExpandStarColumnsFromSubquery(TSelectSqlStatement subquery, ArrayList<String> expandedStarColumns){ 1900 1901 for(TResultColumn resultColumn:subquery.getResultColumnList()){ 1902 if (resultColumn.toString().endsWith("*")){ 1903 TTable srcTable = resultColumn.getExpr().getObjectOperand().getSourceTable(); 1904 if ( srcTable!= null){ 1905 ArrayList<String> list = srcTable.getExpandedStarColumns(); 1906 expandedStarColumns.addAll(list); 1907 } 1908 }else{ 1909 expandedStarColumns.add(resultColumn.getDisplayName()); 1910 } 1911 } 1912 } 1913 1914 /** 1915 * If a star column is linked to this table, use this method to returns all underlying columns that represented by 1916 * the star column. 1917 * <br> 1918 * <br> The returned column always prefixed with 1919 * <br> 1. the table alias. 1920 * <br> 2. the table name 1921 * <br> 3. the alias of query (if the table is a subquery) 1922 * <br> 4. empty if the no alias is specified for a subquery 1923 * 1924 * @return a list of columns 1925 */ 1926 public ArrayList<String> getExpandedStarColumns(){ 1927 if (starColumnExpanded) return expandedStarColumns; 1928 1929 switch (getTableType()){ 1930 case objectname: 1931 if (this.isCTEName()){ 1932 if (this.getCteColomnReferences()!=null){ 1933 for(TObjectName n:this.getCteColomnReferences()){ 1934 expandedStarColumns.add(n.toString()); 1935 } 1936 }else if (this.getCTE().getSubquery() != null){ 1937 this.getExpandStarColumnsFromSubquery(this.getCTE().getSubquery(),this.expandedStarColumns); 1938 } 1939 }else{ 1940 if (this.getSqlEnv() != null){ 1941 ArrayList<String> columns; 1942 if (tableName != null && (tableName.getServerToken() != null || tableName.getDblink() != null)) { 1943 // The composed name drops the server or the link; ask with the whole name, so a linked 1944 // server or a database link never meets a table declared without a database (Mantis 4751). 1945 TSQLTable table = this.getSqlEnv().searchTable(tableName); 1946 columns = table == null ? null : table.getColumns(false); 1947 } else { 1948 columns = this.getSqlEnv().getColumnsInTable(this.getPrefixDatabase() +"."+this.getPrefixSchema()+"."+this.getName(),false); 1949 } 1950 if (columns != null) expandedStarColumns = columns; 1951 if (this.getAliasClause() != null){ 1952 //replace table name with alias 1953 } 1954 } 1955 if ((expandedStarColumns.size() == 0)&&(getLinkedColumns().size()>0)){ 1956 for(TObjectName linkColumn:getLinkedColumns()){ 1957 if (linkColumn.toString().endsWith("*")) continue; 1958 String s = linkColumn.getColumnNameOnly(); 1959 if (this.getAliasClause() != null){ 1960 s = this.getAliasName()+"."+s; 1961 }else{ 1962 s = this.getName()+"."+s; 1963 } 1964 if (expandedStarColumns.indexOf(s) == -1) expandedStarColumns.add(s); 1965 } 1966 } 1967 } 1968 1969 break; 1970 case subquery: 1971 this.getExpandStarColumnsFromSubquery(this.getSubquery(),this.expandedStarColumns); 1972 break; 1973 default: 1974 break; 1975 } 1976 1977 starColumnExpanded = true; 1978 return expandedStarColumns; 1979 } 1980 1981// @Override 1982// public String toString(){ 1983// if (getAliasClause() != null) return getAliasClause().toString(); 1984// 1985// switch (getTableType()){ 1986// case objectname: 1987// return getName().toString(); 1988// break; 1989// default: 1990// 1991// break; 1992// } 1993// } 1994 1995 @Override 1996 public String toString(){ 1997 String ret = super.toString(); 1998 if (ret != null) return ret; 1999 if (tableName != null) return tableName.getObjectString(); 2000 return null; 2001 } 2002 2003}