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