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 574 public void setResolvedTable(TSQLTable resolvedTable) { 575 this.resolvedTable = resolvedTable; 576 isResolved = true; 577 } 578 579 public void setResolved(boolean resolved) { 580 isResolved = resolved; 581 } 582 583 public TSQLTable getResolvedTable() { 584 return resolvedTable; 585 } 586 587 public boolean isResolved() { 588 return isResolved; 589 } 590 591 private ArrayList<TObjectName> columnsFromSQLEnv; 592 593 public ArrayList<TObjectName> getColumnsFromSQLEnv(TSQLEnv sqlEnv) { 594 if (columnsFromSQLEnv == null){ 595 columnsFromSQLEnv = new ArrayList<>(); 596 } 597 598 ArrayList<String> columns = sqlEnv.getColumnsInTable(this.tableName.toString(),true); 599 if (columns == null) return null; 600 601 for(String s:columns){ 602 TObjectName column = TObjectName.createObjectName(this.dbvendor, EDbObjectType.column,new TSourceToken(s)); 603 columnsFromSQLEnv.add(column); 604 } 605 606 return columnsFromSQLEnv; 607 } 608 609 private TJoinExpr joinExpr; 610 611 public void setJoinExpr(TJoinExpr joinExpr) { 612 this.joinExpr = joinExpr; 613 } 614 615 public TJoinExpr getJoinExpr() { 616 return joinExpr; 617 } 618 619 /** 620 * 该 table 对应的 sqlenv 中的 table 定义,包含具体的字段信息,有字段名称、数据类型等。 621 * 622 */ 623// private TSQLTable sqlTable; 624// 625// public void setSqlTable(TSQLTable sqlTable) { 626// this.sqlTable = sqlTable; 627// } 628// 629// public TSQLTable getSqlTable() { 630// return sqlTable; 631// } 632 633 634 635 private TForXMLClause forXMLClause; 636 637 public void setForXMLClause(TForXMLClause forXMLClause) { 638 this.forXMLClause = forXMLClause; 639 } 640 641 /** 642 * SQL Server for xml clause 643 * @return SQL Server for xml clause 644 */ 645 public TForXMLClause getForXMLClause() { 646 return forXMLClause; 647 } 648 649 private TColumnDefinitionList columnDefinitions; 650 651 public TColumnDefinitionList getColumnDefinitions() { 652 return columnDefinitions; 653 } 654 655 /** 656 * Teradata HASH BY clause for table functions. 657 */ 658 private THashByClause hashByClause; 659 660 /** 661 * Gets the HASH BY clause for Teradata table functions. 662 * 663 * @return the HASH BY clause, or null if not specified 664 */ 665 public THashByClause getHashByClause() { 666 return hashByClause; 667 } 668 669 /** 670 * Sets the HASH BY clause for Teradata table functions. 671 * 672 * @param hashByClause the HASH BY clause 673 */ 674 public void setHashByClause(THashByClause hashByClause) { 675 this.hashByClause = hashByClause; 676 } 677 678 /** 679 * Teradata LOCAL ORDER BY clause for table functions. 680 */ 681 private TOrderBy localOrderBy; 682 683 /** 684 * Gets the LOCAL ORDER BY clause for Teradata table functions. 685 * 686 * @return the LOCAL ORDER BY clause, or null if not specified 687 */ 688 public TOrderBy getLocalOrderBy() { 689 return localOrderBy; 690 } 691 692 /** 693 * Sets the LOCAL ORDER BY clause for Teradata table functions. 694 * 695 * @param localOrderBy the LOCAL ORDER BY clause 696 */ 697 public void setLocalOrderBy(TOrderBy localOrderBy) { 698 this.localOrderBy = localOrderBy; 699 } 700 701 private TSQLEnv sqlEnv; 702 703 public void setSqlEnv(TSQLEnv sqlEnv) { 704 this.sqlEnv = sqlEnv; 705 } 706 707 public TSQLEnv getSqlEnv() { 708 return sqlEnv; 709 } 710 711 private TValueClause valueClause; 712 713 public TValueClause getValueClause() { 714 return valueClause; 715 } 716 717 public void setValueClause(TValueClause valueClause) { 718 this.valueClause = valueClause; 719 } 720 721 private TTable sourceTableOfPivot; 722 723 public void setSourceTableOfPivot(TTable sourceTableOfPivot) { 724 this.sourceTableOfPivot = sourceTableOfPivot; 725 } 726 727 public TTable getSourceTableOfPivot() { 728 return sourceTableOfPivot; 729 } 730 731 private TJsonTable jsonTable; 732 733 public void setJsonTable(TJsonTable jsonTable) { 734 this.jsonTable = jsonTable; 735 } 736 737 public TJsonTable getJsonTable() { 738 return jsonTable; 739 } 740 741 public void setPropertyFromObjectName(TObjectName objectName, ETableEffectType tableEffectType){ 742 setStartToken(objectName.getStartToken()); 743 setEndToken(objectName.getEndToken()); 744 setGsqlparser(objectName.getGsqlparser()); 745 setEffectType(tableEffectType); 746 setTableType(ETableSource.objectname); 747 } 748 private TTDUnpivot tdUnpivot; 749 750 public void setTdUnpivot(TTDUnpivot tdUnpivot) { 751 this.tdUnpivot = tdUnpivot; 752 } 753 754 public TTDUnpivot getTdUnpivot() { 755 756 return tdUnpivot; 757 } 758 759 private TUnnestClause unnestClause; 760 761 public void setUnnestClause(TUnnestClause unnestClause) { 762 this.unnestClause = unnestClause; 763 } 764 765 public TUnnestClause getUnnestClause() { 766 767 return unnestClause; 768 } 769 //select b.TemaTakipNo, b.SevkID, db.FromDepo, db.ToDepo, d.UrunID UrunID1, r.UrunID2, d.Miktar AsortiMiktar, r.Miktar ReceteMiktar 770 //into #tmpIrsaliye 771 /** 772 * list of columns in select list, used as metadata to determine whether a column belong to this temp table in TCustomSqlStatement.linkColumnToTable 773 */ 774 private TResultColumnList columnListInTempTable; 775 776 public void setColumnListInTempTable(TResultColumnList columnListInTempTable) { 777 this.columnListInTempTable = columnListInTempTable; 778 } 779 780 public TResultColumnList getColumnListInTempTable() { 781 782 return columnListInTempTable; 783 } 784 785 public void setPxGranule(TPxGranule pxGranule) { 786 this.pxGranule = pxGranule; 787 } 788 789 public TPxGranule getPxGranule() { 790 791 return pxGranule; 792 } 793 794 private TPxGranule pxGranule; 795 private TFlashback flashback; 796 797 public void setFlashback(TFlashback flashback) { 798 this.flashback = flashback; 799 } 800 801 public TFlashback getFlashback() { 802 return flashback; 803 } 804 805 private int parenthesisCount = 0; 806 private int parenthesisAfterAliasCount = 0; 807 private boolean tableKeyword = false; 808 private boolean onlyKeyword = false; 809 private boolean npathOnClauseTable = false; 810 811 /** 812 * Redshift array-unnesting positional index alias. 813 * <p> 814 * When a Redshift array column is unnested in the FROM clause with a 815 * positional index, e.g. 816 * <pre>FROM schema.tbl t, t.array_col AS element AT idx</pre> 817 * this table represents {@code t.array_col} with element alias 818 * {@code element} (the regular {@link #getAliasClause() aliasClause}) and 819 * {@code idx} captured here as the array index alias. 820 */ 821 private TObjectName arrayIndexAlias; 822 823 public TObjectName getArrayIndexAlias() { 824 return arrayIndexAlias; 825 } 826 827 public void setArrayIndexAlias(TObjectName arrayIndexAlias) { 828 this.arrayIndexAlias = arrayIndexAlias; 829 } 830 831 /** 832 * Redshift SUPER object unpivoting source, e.g. 833 * <pre>FROM c.c_orders AS o, UNPIVOT o AS val AT attr</pre> 834 * When {@code true} this table represents the unpivoted SUPER expression: 835 * the regular alias is the value alias and {@link #getArrayIndexAlias()} 836 * (from {@code AT}) is the attribute-name alias. 837 */ 838 private boolean superUnpivot = false; 839 840 public boolean isSuperUnpivot() { 841 return superUnpivot; 842 } 843 844 public void setSuperUnpivot(boolean superUnpivot) { 845 this.superUnpivot = superUnpivot; 846 } 847 848 /** 849 * Marks this table as coming from a Teradata NPath function's ON clause. 850 * This is used for data lineage to trace back to the source table inside NPath. 851 */ 852 public void setNPathOnClauseTable(boolean npathOnClauseTable) { 853 this.npathOnClauseTable = npathOnClauseTable; 854 } 855 856 /** 857 * Returns true if this table comes from a Teradata NPath function's ON clause. 858 */ 859 public boolean isNPathOnClauseTable() { 860 return npathOnClauseTable; 861 } 862 863 public void setTableKeyword(boolean tableKeyword) { 864 this.tableKeyword = tableKeyword; 865 } 866 867 public void setOnlyKeyword(boolean onlyKeyword) { 868 this.onlyKeyword = onlyKeyword; 869 } 870 871 public boolean isTableKeyword() { 872 873 return tableKeyword; 874 } 875 876 public boolean isOnlyKeyword() { 877 return onlyKeyword; 878 } 879 880 public void setParenthesisCount(int parenthesisCount) { 881 this.parenthesisCount = parenthesisCount; 882 } 883 884 public void setParenthesisAfterAliasCount(int parenthesisAfterAliasCount) { 885 this.parenthesisAfterAliasCount = parenthesisAfterAliasCount; 886 } 887 888 public int getParenthesisCount() { 889 890 return parenthesisCount; 891 } 892 893 public int getParenthesisAfterAliasCount() { 894 return parenthesisAfterAliasCount; 895 } 896 897 private TMergeSqlStatement outputMerge; 898 899 public void setOutputMerge(TMergeSqlStatement outputMerge) { 900 this.outputMerge = outputMerge; 901 } 902 903 public TMergeSqlStatement getOutputMerge() { 904 905 return outputMerge; 906 } 907 908 private TPivotedTable pivotedTable; 909 910 public void setPivotedTable(TPivotedTable pivotedTable) { 911 this.pivotedTable = pivotedTable; 912 } 913 914 public TPivotedTable getPivotedTable() { 915 916 return pivotedTable; 917 } 918 919 private ETableEffectType effectType; 920 921 public void setEffectType(ETableEffectType effectType) { 922 this.effectType = effectType; 923 } 924 925 public ETableEffectType getEffectType() { 926 927 return effectType; 928 } 929 930 private TTable linkTable; 931 932 public void setLinkTable(TTable linkTable) { 933 this.linkTable = linkTable; 934 isLinkTable = (this.linkTable != null); 935 } 936 937 public TTable getLinkTable() { 938 939 return linkTable; 940 } 941 942 public boolean isLinkTable() { 943 return isLinkTable; 944 } 945 946 /** 947 * @deprecated As of v1.8.4.6, set in {@link #setLinkTable} 948 */ 949 public void setLinkTable(boolean isLinkTable) { 950 951 this.isLinkTable = isLinkTable; 952 } 953 954 private boolean isLinkTable; 955 956 957 public String getAliasName(){ 958 if (getAliasClause() == null) return ""; 959 TObjectName aliasName = getAliasClause().getAliasName(); 960 return (aliasName == null) ? "" : aliasName.toString(); 961 } 962 963 public boolean equalByName(String pTableName){ 964 if (getAliasClause() != null){ 965 return SQLUtil.sameName(this.dbvendor, ESQLDataObjectType.dotTable, getAliasClause().getAliasName().toString(), pTableName); 966 }else{ 967 return SQLUtil.compareIdentifier(this.dbvendor, ESQLDataObjectType.dotTable, getName(), pTableName); 968 } 969 } 970 971 private TPTNodeList<THiveKeyValueProperty> tableProperties; 972 973 public void setTableProperties(TPTNodeList<THiveKeyValueProperty> tableProperties) { 974 this.tableProperties = tableProperties; 975 } 976 977 /** 978 * 979 * @return hive table property list 980 */ 981 982 public TPTNodeList<THiveKeyValueProperty> getTableProperties() { 983 return tableProperties; 984 } 985 986 private ArrayList<TLateralView> lateralViewList = null; 987 988 public void setLateralViewList(ArrayList<TLateralView> lateralViewList) { 989 this.lateralViewList = lateralViewList; 990 } 991 992 public ArrayList<TLateralView> getLateralViewList() { 993 return lateralViewList; 994 995 } 996 997 private TTableSample tableSample; 998 999 public void setTableSample(TTableSample tableSample) { 1000 this.tableSample = tableSample; 1001 } 1002 1003 public TTableSample getTableSample() { 1004 1005 return tableSample; 1006 } 1007 1008 public void setPartitionExtensionClause(TPartitionExtensionClause partitionExtensionClause) { 1009 this.partitionExtensionClause = partitionExtensionClause; 1010 } 1011 1012 private TPartitionExtensionClause partitionExtensionClause; 1013 1014 public TPartitionExtensionClause getPartitionExtensionClause() { 1015 return partitionExtensionClause; 1016 } 1017 1018 public void setOuterClause(TInformixOuterClause outerClause) { 1019 this.outerClause = outerClause; 1020 } 1021 1022 public TInformixOuterClause getOuterClause() { 1023 1024 return outerClause; 1025 } 1026 1027 private TInformixOuterClause outerClause; 1028 1029 private TXmlTable xmlTable; 1030 1031 private TFromTableList fromTableList; 1032 1033 public void setFromTableList(TFromTableList fromTableList) { 1034 this.fromTableList = fromTableList; 1035 } 1036 1037 public TFromTableList getFromTableList() { 1038 1039 return fromTableList; 1040 } 1041 1042 public TXmlTable getXmlTable() { 1043 return xmlTable; 1044 } 1045 1046 public void setXmlTable(TXmlTable xmlTable) { 1047 1048 this.xmlTable = xmlTable; 1049 } 1050 1051 private TOpenQuery openquery = null; 1052 1053 public void setTableHintList(TPTNodeList<TTableHint> tableHintList) { 1054 this.tableHintList = tableHintList; 1055 } 1056 1057 1058 public TPTNodeList<TTableHint> getTableHintList() { 1059 1060 return tableHintList; 1061 } 1062 1063 private TPTNodeList<TTableHint> tableHintList; 1064 1065 public TOpenQuery getOpenquery() { 1066 return openquery; 1067 } 1068 1069 public TSelectSqlStatement getSubquery() { 1070 return subquery; 1071 } 1072 1073 public void setOpenquery(TOpenQuery openquery) { 1074 1075 this.openquery = openquery; 1076 } 1077 1078 public void setOpenDatasource(TOpenDatasource openDatasource) { 1079 this.openDatasource = openDatasource; 1080 } 1081 1082 /** 1083 * Valid when {@link #tableType} is ftt_opendatasource. 1084 * @return 1085 */ 1086 public TOpenDatasource getOpenDatasource() { 1087 1088 return openDatasource; 1089 } 1090 1091 private TOpenDatasource openDatasource = null; 1092 1093 public void setOpenXML(TOpenXML openXML) { 1094 this.openXML = openXML; 1095 } 1096 1097 public TOpenXML getOpenXML() { 1098 1099 return openXML; 1100 } 1101 1102 private TOpenXML openXML = null; 1103 1104 public TOpenRowSet getOpenRowSet() { 1105 return openRowSet; 1106 } 1107 1108 public void setOpenRowSet(TOpenRowSet openRowSet) { 1109 1110 this.openRowSet = openRowSet; 1111 } 1112 1113 private TOpenRowSet openRowSet = null; 1114 1115 public TContainsTable getContainsTable() { 1116 return containsTable; 1117 } 1118 1119 public void setContainsTable(TContainsTable containsTable) { 1120 this.containsTable = containsTable; 1121 } 1122 1123 private TContainsTable containsTable = null; 1124 1125 public TFunctionCall getFuncCall() { 1126 return funcCall; 1127 } 1128 1129 public void setFuncCall(TFunctionCall funcCall) { 1130 this.funcCall = funcCall; 1131 } 1132 1133 1134 private TFunctionCall funcCall = null; 1135 1136 private TMultiTargetList rowList; 1137 1138 /** 1139 * @deprecated As of v2.3.6.9, please use {@link #getValueClause()} instead 1140 * 1141 * row constructor like this: '(' RW_VALUES MultiTargets ')' 1142 * @return TMultiTargetList 1143 */ 1144 public TMultiTargetList getRowList() { 1145 return rowList; 1146 } 1147 1148 public boolean isBaseTable(){ 1149 boolean retval = (tableType == ETableSource.objectname); 1150 if (retval){ 1151 if (isCTEName()){ 1152 retval = false; 1153 } 1154 } 1155 1156 if (retval){ 1157 if (getFullName().startsWith("@")) { 1158 retval = false; 1159 } 1160 } 1161 return retval; 1162 } 1163 1164 public void setCteColomnReferences(TObjectNameList cteColomnReferences) { 1165 this.cteColomnReferences = cteColomnReferences; 1166 } 1167 1168 private TObjectNameList cteColomnReferences = null; 1169 1170 public TObjectNameList getCteColomnReferences() { 1171 return cteColomnReferences; 1172 } 1173 1174 public void setObjectNameReferences(TObjectNameList objectNameReferences) { 1175 1176 this.objectNameReferences = objectNameReferences; 1177 } 1178 1179 private TCTE CTE; 1180 1181 public boolean setCTE(TCTE pCTE) { 1182 if (pCTE == null){ 1183 this.CTE = null; 1184 return true; 1185 } 1186 1187 if ((!pCTE.isRecursive()) && (pCTE.getSubquery() != null) && (TParseTreeNode.subNodeInNode(this,pCTE.getSubquery()))){ 1188 // 如果这个table是属于一个CTE的子查询,那么不再设置CTE,因为该table不可能是该CTE的引用, 但前提条件是 1189 // 1. 该 subquery 非 combined query 1190 // 2. 如果该 subquery 是 combined query , 该 table 属于第一个subquery 中的 table 1191 1192 // 如果不是以上两种情况,那么该table就是该CTE的引用,需要返回 true 1193 // refer to: public void testSearchTable1() 1194 1195 if (!pCTE.getSubquery().isCombinedQuery()) return false; 1196 1197 if (TParseTreeNode.subNodeInNode(this,pCTE.getSubquery().getLeftStmt())){ 1198 return false; 1199 } 1200 1201 } 1202 1203 this.CTE = pCTE; 1204 return true; 1205 } 1206 1207 public TCTE getCTE() { 1208 1209 return CTE; 1210 } 1211 1212 public boolean isCTEName() { 1213 1214 return isCTEName; 1215 } 1216 1217 public void setCTEName(boolean CTEName) { 1218 isCTEName = CTEName; 1219 } 1220 1221 private boolean isCTEName = false; 1222 1223 public TSelectSqlStatement subquery = null; 1224 private THiveFromQuery hiveFromQuery; 1225 1226 public void setHiveFromQuery(THiveFromQuery hiveFromQuery) { 1227 this.hiveFromQuery = hiveFromQuery; 1228 } 1229 1230 /** 1231 * @deprecated As of v2.1.0.0, please use {@link #getSubquery()} 1232 * @return 1233 */ 1234 public THiveFromQuery getHiveFromQuery() { 1235 1236 return hiveFromQuery; 1237 } 1238 1239 public TExpression getTableExpr() { 1240 return tableExpr; 1241 } 1242 1243 public void setTableExpr(TExpression tableExpr) { 1244 this.tableExpr = tableExpr; 1245 } 1246 1247 private TExpression tableExpr; 1248 1249 public void setTableType(ETableSource tableType) { 1250 this.tableType = tableType; 1251 } 1252 1253 /** 1254 * 1255 * @return what's kind of type this table is. 1256 *<ul> 1257 * <li>{@link ETableSource#objectname}, in from clause, a simple table/view name, reference: {@link TTable#tableName}<li> 1258 * <li>{@link ETableSource#subquery}, is a subquery that retrieves rows from the database, also known as derived table. reference: {@link TTable#subquery}</li> 1259 * <li>{@link ETableSource#tableExpr},it's usually a table-valued expression., reference: {@link TTable#tableExpr}</li> 1260 * <li>{@link ETableSource#function}, it's usually a table-valued function., reference: {@link TTable#funcCall}</li> 1261 * <li>{@link ETableSource#rowList}, it's constructed rows, reference: {@link TTable#rowList}</li> 1262 * <li>{@link ETableSource#containsTable}, CONTAINSTABLE clause of sql server. reference: {@link TTable#containsTable}, type of {@link TContainsTable}</li> 1263 * <li>{@link ETableSource#freetextTable}, FREETEXTTABLE clause of sql server. reference: {@link TTable#containsTable}, type of {@link TContainsTable}</li> 1264 * <li>{@link ETableSource#openrowset}, OPENROWSET clause of sql server. reference: {@link TTable#openRowSet}, type of {@link TOpenRowSet}</li> 1265 * <li>{@link ETableSource#openxml}, OPENXML clause of sql server. reference: {@link TTable#openXML}, type of {@link TOpenXML }</li> 1266 * <li>{@link ETableSource#opendatasource}, OPENDATASOURCE clause of sql server. reference: {@link TTable#openDatasource}, type of {@link TOpenDatasource}</li> 1267 * <li>{@link ETableSource#openquery}, OPENQUERY clause of sql server. reference: {@link TTable#openquery}, type of (@link TOpenQuery)</li> 1268 * </ul> 1269 */ 1270 public ETableSource getTableType() { 1271 1272 return tableType; 1273 } 1274 1275 private ETableSource tableType; 1276 1277 public void setTableName(TObjectName tableName) { 1278 this.tableName = tableName; 1279 tableType = ETableSource.objectname; 1280 this.tableName.splitNameInQuotedIdentifier(); 1281 if (this.getStartToken() == null){ 1282 this.setStartToken(tableName.getStartToken()); 1283 } 1284 1285 if (this.getEndToken() == null){ 1286 this.setEndToken(tableName.getEndToken()); 1287 } 1288 } 1289 1290 public TObjectName getTableName() { 1291 TObjectName ret = tableName; 1292 1293 if (tableType == null) return ret; 1294 1295 switch (tableType){ 1296 case tableExpr: 1297 if (tableExpr.getExpressionType() == EExpressionType.function_t){ 1298 ret = tableExpr.getFunctionCall().getFunctionName(); 1299 } 1300 break; 1301 case function: 1302 ret = getFuncCall().getFunctionName(); 1303 break; 1304 case openrowset: 1305 ret = TObjectName.createObjectName (this.dbvendor, EDbObjectType.table,new TSourceToken("openrowset")); 1306 break; 1307 case rowList: 1308 ret = TObjectName.createObjectName (this.dbvendor, EDbObjectType.table,new TSourceToken("(values_table)")); 1309 break; 1310 case subquery: 1311 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("subquery")); 1312 break; 1313 case td_unpivot: 1314 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("td_unpivot")); 1315 break; 1316 case pivoted_table: 1317 // Check if this is an UNPIVOT to use the correct suffix 1318 String pivotSuffix = "(piviot_table)"; 1319 if (getPivotedTable() != null && getPivotedTable().getPivotClause() != null 1320 && getPivotedTable().getPivotClause().getType() == TPivotClause.unpivot) { 1321 pivotSuffix = "(unpivot_table)"; 1322 } 1323 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken(tableName+pivotSuffix)); 1324 break; 1325 case xmltable: 1326 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("xmltable")); 1327 break; 1328 case jsonTable: 1329 ret = getJsonTable().getFunctionName();// TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("jsontable"));// 1330 break; 1331 case containsTable: 1332 if (containsTable.getType() == TContainsTable.containstable){ 1333 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("containsTable")); 1334 }else { 1335 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("freetexttable")); 1336 } 1337 break; 1338 case opendatasource: 1339 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("opendatasource")); 1340 break; 1341 case unnest: 1342 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken(getAliasName()+"(unnest table)")); 1343 break; 1344 case openxml: 1345 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("openxml")); 1346 break; 1347 case openquery: 1348 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("openquery")); 1349 break; 1350 case output_merge: 1351 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("merge")); 1352 break; 1353 case externalTable: 1354 ret = this.tableName; 1355 break; 1356 case join: 1357 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("join_expr")); 1358 break; 1359 } 1360 if (ret == null) { 1361 return TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("unknown")); 1362 } 1363 else return ret; 1364 } 1365 1366 private TObjectName tableName; 1367 1368 public TTable(TObjectName pobjectname){ 1369 this.tableName = pobjectname; 1370 this.setStartToken(this.tableName.getStartToken()); 1371 this.setEndToken(this.tableName.getEndToken()); 1372 } 1373 1374 1375 public TTable(){ 1376 this.tableName = null; 1377 } 1378 1379 public String getName() { 1380 if (tableName != null) 1381 return tableName.getObjectString(); 1382 else 1383 return getTableName().toString(); 1384 } 1385 1386 1387 public String getPrefixServer(){ 1388 if (tableName != null) return tableName.getServerString(); 1389 else return ""; 1390 } 1391 public String getPrefixDatabase(){ 1392 if (tableName != null) return tableName.getDatabaseString(); 1393 else return ""; 1394 } 1395 public String getPrefixSchema(){ 1396 if (tableName != null) return tableName.getSchemaString(); 1397 else return ""; 1398 } 1399 1400 public boolean isIncludeColumnAlias(){ 1401 // return (this.getAliasClause() != null); 1402 return false; 1403 // ToDo 1404 } 1405 1406 1407 public int searchColumnInAlias(TObjectName pColumn){ 1408 if (getAliasClause() == null) return -1; 1409 return getAliasClause().searchColumn(pColumn); 1410 } 1411 1412 public boolean checkTableByName(String pTablename){ 1413 boolean lcResult = false; 1414 String a,b,c; 1415 b = TBaseType.getTextWithoutQuoted(pTablename); 1416 if (this.getAliasClause() != null){ 1417 a = TBaseType.getTextWithoutQuoted(this.getAliasName()); 1418 lcResult = a.equalsIgnoreCase(b); 1419 } 1420 if (lcResult) return true; 1421 c = TBaseType.getTextWithoutQuoted(this.getTableName().toString()); 1422 lcResult = c.equalsIgnoreCase(b); 1423 return lcResult; 1424 } 1425 1426 public boolean searchColumn(TSelectSqlStatement select, String tableName, TObjectName pColumn, boolean pMustIn){ 1427 // pColumn maybe qualified, so check the table name at first 1428 boolean lcResult = false, isSameTable = false; 1429 if ( tableName.length() == 0){ 1430 isSameTable = true; 1431 }else { 1432 isSameTable = checkTableByName(tableName); 1433 } 1434 1435 if (!isSameTable) return lcResult; 1436 1437 if (this.isBaseTable()){ 1438 lcResult = select.fireOnMetaDatabaseTableColumn(this.getPrefixServer(),this.getPrefixDatabase(),this.getPrefixSchema(),this.getName(),pColumn.getColumnNameOnly()); 1439 }else{ 1440 if (this.getTableType() == ETableSource.subquery){ 1441 if (this.isIncludeColumnAlias()){ 1442 lcResult = this.searchColumnInAlias(pColumn)>=0; 1443 }else{ 1444 lcResult = this.getSubquery().searchColumnInResultSet(pColumn,pMustIn); 1445 } 1446 }else if (this.isCTEName()){ 1447 lcResult = this.getCTE().searchColumnInResultSet(select,this,pColumn,pMustIn); 1448 } 1449 } 1450 1451 if (lcResult){ 1452 this.getLinkedColumns().addObjectName(pColumn); 1453 pColumn.setSourceTable(this); 1454 }else if (pMustIn){ 1455 this.getLinkedColumns().addObjectName(pColumn); 1456 pColumn.setSourceTable(this); 1457 lcResult = true; 1458 } 1459 1460 if (!lcResult){ 1461 if (this.getTableType() == ETableSource.pivoted_table){ 1462 if (this.getLinkedColumns().size() > 0){ 1463 for(TObjectName c: this.getLinkedColumns()){ 1464 lcResult = c.toString().equalsIgnoreCase(pColumn.getColumnNameOnly()); 1465 if (lcResult) break; 1466 } 1467 } 1468 } 1469 } 1470 1471 return lcResult; 1472 } 1473 1474 private TObjectNameList linkedColumns = null; 1475 1476 /** 1477 * @deprecated , this method is deprecated since version 3.3.1.0, don't use it in TSQLResolver2 1478 * @return 1479 */ 1480 public TObjectNameList getLinkedColumns() { 1481 if (linkedColumns == null) { 1482 linkedColumns = new TObjectNameList(); 1483 linkedColumns.setObjectType(TObjectName.ttobjColumn); 1484 } 1485 return linkedColumns; 1486 } 1487 1488 1489 1490 public String getFullNameWithAliasString() { 1491 if (getAliasClause() != null){ 1492 return getFullName()+" "+getAliasClause().toString(); 1493 }else{ 1494 return getFullName(); 1495 } 1496 } 1497 1498 public String getFullName() { 1499 if (tableName == null) return null; 1500 return tableName.toString(); 1501 /* 1502 if (tableName.getSchemaString() == null) 1503 {return this.getName();} 1504 else{ 1505 return tableName.getSchemaString()+"."+this.getName(); 1506 } 1507 */ 1508 1509 } 1510 1511 /** 1512 * 1513 * @return column name related to this table. 1514 * @deprecated As of v1.6.0.1, use {@link #getLinkedColumns()} instead 1515 */ 1516 public TObjectNameList getObjectNameReferences() { 1517 if (objectNameReferences == null){ 1518 objectNameReferences = new TObjectNameList(); 1519 objectNameReferences.setObjectType(TObjectName.ttobjColumn); 1520 } 1521 return objectNameReferences; 1522 } 1523 1524 private TPivotClause pivotClause = null; 1525 1526 public void setPivotClause(TPivotClause pivotClause) { 1527 this.pivotClause = pivotClause; 1528 } 1529 1530 /** 1531 * @deprecated As of v1.6.2.4, replaced by {@link gudusoft.gsqlparser.nodes.TPivotedTable} 1532 * @return 1533 */ 1534 public TPivotClause getPivotClause() { 1535 1536 return pivotClause; 1537 } 1538 1539 /** 1540 * Stored all column names that belong to this table. 1541 */ 1542 private TObjectNameList objectNameReferences = null; 1543 1544 public TTableReferenceList tablerefs = new TTableReferenceList(); 1545 1546 private TDataChangeTable datachangeTable = null; 1547 1548 public void setDatachangeTable(TDataChangeTable datachangeTable) { 1549 this.datachangeTable = datachangeTable; 1550 } 1551 1552 /** 1553 * DB2 data change 1554 * @return 1555 */ 1556 public TDataChangeTable getDatachangeTable() { 1557 return datachangeTable; 1558 } 1559 1560 1561 public boolean isTableRefBelongToThisTable(TTableReference tableref){ 1562 1563 boolean retval = (this.tableName == tableref.objectname); 1564 if (retval) {return retval;} 1565 if (SQLUtil.sameName(this.dbvendor, ESQLDataObjectType.dotTable, this.tableName.getObjectString(), tableref.objectname.getObjectString())){ 1566 if ((this.tableName.getSchemaString() == null) 1567 ||(tableref.objectname.getSchemaString() == null) 1568 ) { 1569 retval = true; 1570 }else{ 1571 retval = SQLUtil.sameName(this.dbvendor, ESQLDataObjectType.dotSchema, this.tableName.getSchemaString(), tableref.objectname.getSchemaString()); 1572 } 1573 } 1574 return retval; 1575 } 1576 1577 public void accept(TParseTreeVisitor v){ 1578 v.preVisit(this); 1579 1580 v.postVisit(this); 1581 } 1582 1583 public void setColumnDefinitions(TColumnDefinitionList columnDefinitions) { 1584 this.columnDefinitions = columnDefinitions; 1585 } 1586 1587 public void acceptChildren(TParseTreeVisitor v){ 1588 v.preVisit(this); 1589 1590 switch(getTableType()){ 1591 case objectname:{ 1592 getTableName().acceptChildren(v); 1593 if (getFlashback() != null){ 1594 getFlashback().acceptChildren(v); 1595 } 1596 break; 1597 } 1598 case tableExpr:{ 1599 getTableExpr().acceptChildren(v); 1600 break; 1601 } 1602 case subquery:{ 1603 getSubquery().acceptChildren(v); 1604 break; 1605 } 1606 case function:{ 1607 getFuncCall().acceptChildren(v); 1608 break; 1609 } 1610 case pivoted_table:{ 1611 if (this.getEffectType() == ETableEffectType.tetPivot) break; 1612 getPivotedTable().acceptChildren(v); 1613 break; 1614 } 1615 case output_merge:{ 1616 if (getOutputMerge() != null) getOutputMerge().acceptChildren(v); 1617 //e_table_reference.setTextContent(node.getOutputMerge().toString()); 1618 break; 1619 } 1620 case containsTable:{ 1621 getContainsTable().acceptChildren(v); 1622 break; 1623 } 1624 1625 case openrowset:{ 1626 getOpenRowSet().acceptChildren(v); 1627 break; 1628 } 1629 1630 case openxml:{ 1631 getOpenXML().acceptChildren(v); 1632 break; 1633 } 1634 1635 case opendatasource:{ 1636 getOpenDatasource().acceptChildren(v); 1637 break; 1638 } 1639 1640 case openquery:{ 1641 getOpenquery().acceptChildren(v); 1642 break; 1643 } 1644 1645 case datachangeTable:{ 1646 getDatachangeTable().acceptChildren(v); 1647 break; 1648 } 1649 case rowList:{ 1650 getValueClause().acceptChildren(v); 1651 break; 1652 } 1653 case xmltable:{ 1654 getXmlTable().acceptChildren(v); 1655 break; 1656 } 1657 case jsonTable:{ 1658 getJsonTable().acceptChildren(v); 1659 break; 1660 } 1661 case informixOuter:{ 1662 getOuterClause().acceptChildren(v); 1663 break; 1664 } 1665 1666 case table_ref_list:{ 1667 getFromTableList().acceptChildren(v); 1668 break; 1669 } 1670 case hiveFromQuery:{ 1671 getHiveFromQuery().acceptChildren(v); 1672 break; 1673 } 1674 case externalTable: 1675 this.columnDefinitions.acceptChildren(v); 1676 break; 1677 case join: 1678 this.joinExpr.acceptChildren(v); 1679 break; 1680 case unnest: 1681 this.getUnnestClause().acceptChildren(v); 1682 break; 1683 default: 1684 //sb.append(node.toString().replace(">",">").replace("<","<")); 1685 break; 1686 1687 } 1688 1689 1690 if (getPxGranule() != null){ 1691 getPxGranule().acceptChildren(v); 1692 } 1693 1694 if (getTableSample() != null){ 1695 getTableSample().acceptChildren(v); 1696 } 1697 1698 if (getAliasClause() != null){ 1699 getAliasClause().acceptChildren(v); 1700 } 1701 1702 1703 if (getTableHintList() != null){ 1704 for(int i=0;i<getTableHintList().size();i++){ 1705 TTableHint tableHint = getTableHintList().getElement(i); 1706 tableHint.acceptChildren(v); 1707 } 1708 } 1709 1710 if (getLateralViewList() != null){ 1711 for(TLateralView lateralView:getLateralViewList()){ 1712 lateralView.acceptChildren(v); 1713 } 1714 } 1715 1716 1717 v.postVisit(this); 1718 } 1719 1720 public void setRowList(TMultiTargetList rowList) { 1721 this.rowList = rowList; 1722 } 1723 1724 public void setSubquery(TSelectSqlStatement subquery) { 1725 this.subquery = subquery; 1726 } 1727 1728 public void setLinkedColumns(TObjectNameList linkedColumns) { 1729 this.linkedColumns = linkedColumns; 1730 } 1731 1732 public void setTablerefs(TTableReferenceList tablerefs) { 1733 this.tablerefs = tablerefs; 1734 } 1735 1736 private boolean starColumnExpanded = false; 1737 1738 private ArrayList<String> expandedStarColumns = new ArrayList<String>(); 1739 1740 private void getExpandStarColumnsFromSubquery(TSelectSqlStatement subquery, ArrayList<String> expandedStarColumns){ 1741 1742 for(TResultColumn resultColumn:subquery.getResultColumnList()){ 1743 if (resultColumn.toString().endsWith("*")){ 1744 TTable srcTable = resultColumn.getExpr().getObjectOperand().getSourceTable(); 1745 if ( srcTable!= null){ 1746 ArrayList<String> list = srcTable.getExpandedStarColumns(); 1747 expandedStarColumns.addAll(list); 1748 } 1749 }else{ 1750 expandedStarColumns.add(resultColumn.getDisplayName()); 1751 } 1752 } 1753 } 1754 1755 /** 1756 * If a star column is linked to this table, use this method to returns all underlying columns that represented by 1757 * the star column. 1758 * <br> 1759 * <br> The returned column always prefixed with 1760 * <br> 1. the table alias. 1761 * <br> 2. the table name 1762 * <br> 3. the alias of query (if the table is a subquery) 1763 * <br> 4. empty if the no alias is specified for a subquery 1764 * 1765 * @return a list of columns 1766 */ 1767 public ArrayList<String> getExpandedStarColumns(){ 1768 if (starColumnExpanded) return expandedStarColumns; 1769 1770 switch (getTableType()){ 1771 case objectname: 1772 if (this.isCTEName()){ 1773 if (this.getCteColomnReferences()!=null){ 1774 for(TObjectName n:this.getCteColomnReferences()){ 1775 expandedStarColumns.add(n.toString()); 1776 } 1777 }else if (this.getCTE().getSubquery() != null){ 1778 this.getExpandStarColumnsFromSubquery(this.getCTE().getSubquery(),this.expandedStarColumns); 1779 } 1780 }else{ 1781 if (this.getSqlEnv() != null){ 1782 ArrayList<String> columns = this.getSqlEnv().getColumnsInTable(this.getPrefixDatabase() +"."+this.getPrefixSchema()+"."+this.getName(),false); 1783 if (columns != null) expandedStarColumns = columns; 1784 if (this.getAliasClause() != null){ 1785 //replace table name with alias 1786 } 1787 } 1788 if ((expandedStarColumns.size() == 0)&&(getLinkedColumns().size()>0)){ 1789 for(TObjectName linkColumn:getLinkedColumns()){ 1790 if (linkColumn.toString().endsWith("*")) continue; 1791 String s = linkColumn.getColumnNameOnly(); 1792 if (this.getAliasClause() != null){ 1793 s = this.getAliasName()+"."+s; 1794 }else{ 1795 s = this.getName()+"."+s; 1796 } 1797 if (expandedStarColumns.indexOf(s) == -1) expandedStarColumns.add(s); 1798 } 1799 } 1800 } 1801 1802 break; 1803 case subquery: 1804 this.getExpandStarColumnsFromSubquery(this.getSubquery(),this.expandedStarColumns); 1805 break; 1806 default: 1807 break; 1808 } 1809 1810 starColumnExpanded = true; 1811 return expandedStarColumns; 1812 } 1813 1814// @Override 1815// public String toString(){ 1816// if (getAliasClause() != null) return getAliasClause().toString(); 1817// 1818// switch (getTableType()){ 1819// case objectname: 1820// return getName().toString(); 1821// break; 1822// default: 1823// 1824// break; 1825// } 1826// } 1827 1828 @Override 1829 public String toString(){ 1830 String ret = super.toString(); 1831 if (ret != null) return ret; 1832 if (tableName != null) return tableName.getObjectString(); 1833 return null; 1834 } 1835 1836}