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 808 public void setTableKeyword(boolean tableKeyword) { 809 this.tableKeyword = tableKeyword; 810 } 811 812 public void setOnlyKeyword(boolean onlyKeyword) { 813 this.onlyKeyword = onlyKeyword; 814 } 815 816 public boolean isTableKeyword() { 817 818 return tableKeyword; 819 } 820 821 public boolean isOnlyKeyword() { 822 return onlyKeyword; 823 } 824 825 public void setParenthesisCount(int parenthesisCount) { 826 this.parenthesisCount = parenthesisCount; 827 } 828 829 public void setParenthesisAfterAliasCount(int parenthesisAfterAliasCount) { 830 this.parenthesisAfterAliasCount = parenthesisAfterAliasCount; 831 } 832 833 public int getParenthesisCount() { 834 835 return parenthesisCount; 836 } 837 838 public int getParenthesisAfterAliasCount() { 839 return parenthesisAfterAliasCount; 840 } 841 842 private TMergeSqlStatement outputMerge; 843 844 public void setOutputMerge(TMergeSqlStatement outputMerge) { 845 this.outputMerge = outputMerge; 846 } 847 848 public TMergeSqlStatement getOutputMerge() { 849 850 return outputMerge; 851 } 852 853 private TPivotedTable pivotedTable; 854 855 public void setPivotedTable(TPivotedTable pivotedTable) { 856 this.pivotedTable = pivotedTable; 857 } 858 859 public TPivotedTable getPivotedTable() { 860 861 return pivotedTable; 862 } 863 864 private ETableEffectType effectType; 865 866 public void setEffectType(ETableEffectType effectType) { 867 this.effectType = effectType; 868 } 869 870 public ETableEffectType getEffectType() { 871 872 return effectType; 873 } 874 875 private TTable linkTable; 876 877 public void setLinkTable(TTable linkTable) { 878 this.linkTable = linkTable; 879 isLinkTable = (this.linkTable != null); 880 } 881 882 public TTable getLinkTable() { 883 884 return linkTable; 885 } 886 887 public boolean isLinkTable() { 888 return isLinkTable; 889 } 890 891 /** 892 * @deprecated As of v1.8.4.6, set in {@link #setLinkTable} 893 */ 894 public void setLinkTable(boolean isLinkTable) { 895 896 this.isLinkTable = isLinkTable; 897 } 898 899 private boolean isLinkTable; 900 901 902 public String getAliasName(){ 903 if (getAliasClause() == null) return ""; 904 TObjectName aliasName = getAliasClause().getAliasName(); 905 return (aliasName == null) ? "" : aliasName.toString(); 906 } 907 908 public boolean equalByName(String pTableName){ 909 if (getAliasClause() != null){ 910 return getAliasClause().getAliasName().toString().equalsIgnoreCase(pTableName); 911 }else{ 912 return getName().equalsIgnoreCase(pTableName); 913 } 914 } 915 916 private TPTNodeList<THiveKeyValueProperty> tableProperties; 917 918 public void setTableProperties(TPTNodeList<THiveKeyValueProperty> tableProperties) { 919 this.tableProperties = tableProperties; 920 } 921 922 /** 923 * 924 * @return hive table property list 925 */ 926 927 public TPTNodeList<THiveKeyValueProperty> getTableProperties() { 928 return tableProperties; 929 } 930 931 private ArrayList<TLateralView> lateralViewList = null; 932 933 public void setLateralViewList(ArrayList<TLateralView> lateralViewList) { 934 this.lateralViewList = lateralViewList; 935 } 936 937 public ArrayList<TLateralView> getLateralViewList() { 938 return lateralViewList; 939 940 } 941 942 private TTableSample tableSample; 943 944 public void setTableSample(TTableSample tableSample) { 945 this.tableSample = tableSample; 946 } 947 948 public TTableSample getTableSample() { 949 950 return tableSample; 951 } 952 953 public void setPartitionExtensionClause(TPartitionExtensionClause partitionExtensionClause) { 954 this.partitionExtensionClause = partitionExtensionClause; 955 } 956 957 private TPartitionExtensionClause partitionExtensionClause; 958 959 public TPartitionExtensionClause getPartitionExtensionClause() { 960 return partitionExtensionClause; 961 } 962 963 public void setOuterClause(TInformixOuterClause outerClause) { 964 this.outerClause = outerClause; 965 } 966 967 public TInformixOuterClause getOuterClause() { 968 969 return outerClause; 970 } 971 972 private TInformixOuterClause outerClause; 973 974 private TXmlTable xmlTable; 975 976 private TFromTableList fromTableList; 977 978 public void setFromTableList(TFromTableList fromTableList) { 979 this.fromTableList = fromTableList; 980 } 981 982 public TFromTableList getFromTableList() { 983 984 return fromTableList; 985 } 986 987 public TXmlTable getXmlTable() { 988 return xmlTable; 989 } 990 991 public void setXmlTable(TXmlTable xmlTable) { 992 993 this.xmlTable = xmlTable; 994 } 995 996 private TOpenQuery openquery = null; 997 998 public void setTableHintList(TPTNodeList<TTableHint> tableHintList) { 999 this.tableHintList = tableHintList; 1000 } 1001 1002 1003 public TPTNodeList<TTableHint> getTableHintList() { 1004 1005 return tableHintList; 1006 } 1007 1008 private TPTNodeList<TTableHint> tableHintList; 1009 1010 public TOpenQuery getOpenquery() { 1011 return openquery; 1012 } 1013 1014 public TSelectSqlStatement getSubquery() { 1015 return subquery; 1016 } 1017 1018 public void setOpenquery(TOpenQuery openquery) { 1019 1020 this.openquery = openquery; 1021 } 1022 1023 public void setOpenDatasource(TOpenDatasource openDatasource) { 1024 this.openDatasource = openDatasource; 1025 } 1026 1027 /** 1028 * Valid when {@link #tableType} is ftt_opendatasource. 1029 * @return 1030 */ 1031 public TOpenDatasource getOpenDatasource() { 1032 1033 return openDatasource; 1034 } 1035 1036 private TOpenDatasource openDatasource = null; 1037 1038 public void setOpenXML(TOpenXML openXML) { 1039 this.openXML = openXML; 1040 } 1041 1042 public TOpenXML getOpenXML() { 1043 1044 return openXML; 1045 } 1046 1047 private TOpenXML openXML = null; 1048 1049 public TOpenRowSet getOpenRowSet() { 1050 return openRowSet; 1051 } 1052 1053 public void setOpenRowSet(TOpenRowSet openRowSet) { 1054 1055 this.openRowSet = openRowSet; 1056 } 1057 1058 private TOpenRowSet openRowSet = null; 1059 1060 public TContainsTable getContainsTable() { 1061 return containsTable; 1062 } 1063 1064 public void setContainsTable(TContainsTable containsTable) { 1065 this.containsTable = containsTable; 1066 } 1067 1068 private TContainsTable containsTable = null; 1069 1070 public TFunctionCall getFuncCall() { 1071 return funcCall; 1072 } 1073 1074 public void setFuncCall(TFunctionCall funcCall) { 1075 this.funcCall = funcCall; 1076 } 1077 1078 1079 private TFunctionCall funcCall = null; 1080 1081 private TMultiTargetList rowList; 1082 1083 /** 1084 * @deprecated As of v2.3.6.9, please use {@link #getValueClause()} instead 1085 * 1086 * row constructor like this: '(' RW_VALUES MultiTargets ')' 1087 * @return TMultiTargetList 1088 */ 1089 public TMultiTargetList getRowList() { 1090 return rowList; 1091 } 1092 1093 public boolean isBaseTable(){ 1094 boolean retval = (tableType == ETableSource.objectname); 1095 if (retval){ 1096 if (isCTEName()){ 1097 retval = false; 1098 } 1099 } 1100 1101 if (retval){ 1102 if (getFullName().startsWith("@")) { 1103 retval = false; 1104 } 1105 } 1106 return retval; 1107 } 1108 1109 public void setCteColomnReferences(TObjectNameList cteColomnReferences) { 1110 this.cteColomnReferences = cteColomnReferences; 1111 } 1112 1113 private TObjectNameList cteColomnReferences = null; 1114 1115 public TObjectNameList getCteColomnReferences() { 1116 return cteColomnReferences; 1117 } 1118 1119 public void setObjectNameReferences(TObjectNameList objectNameReferences) { 1120 1121 this.objectNameReferences = objectNameReferences; 1122 } 1123 1124 private TCTE CTE; 1125 1126 public boolean setCTE(TCTE pCTE) { 1127 if (pCTE == null){ 1128 this.CTE = null; 1129 return true; 1130 } 1131 1132 if ((!pCTE.isRecursive()) && (pCTE.getSubquery() != null) && (TParseTreeNode.subNodeInNode(this,pCTE.getSubquery()))){ 1133 // 如果这个table是属于一个CTE的子查询,那么不再设置CTE,因为该table不可能是该CTE的引用, 但前提条件是 1134 // 1. 该 subquery 非 combined query 1135 // 2. 如果该 subquery 是 combined query , 该 table 属于第一个subquery 中的 table 1136 1137 // 如果不是以上两种情况,那么该table就是该CTE的引用,需要返回 true 1138 // refer to: public void testSearchTable1() 1139 1140 if (!pCTE.getSubquery().isCombinedQuery()) return false; 1141 1142 if (TParseTreeNode.subNodeInNode(this,pCTE.getSubquery().getLeftStmt())){ 1143 return false; 1144 } 1145 1146 } 1147 1148 this.CTE = pCTE; 1149 return true; 1150 } 1151 1152 public TCTE getCTE() { 1153 1154 return CTE; 1155 } 1156 1157 public boolean isCTEName() { 1158 1159 return isCTEName; 1160 } 1161 1162 public void setCTEName(boolean CTEName) { 1163 isCTEName = CTEName; 1164 } 1165 1166 private boolean isCTEName = false; 1167 1168 public TSelectSqlStatement subquery = null; 1169 private THiveFromQuery hiveFromQuery; 1170 1171 public void setHiveFromQuery(THiveFromQuery hiveFromQuery) { 1172 this.hiveFromQuery = hiveFromQuery; 1173 } 1174 1175 /** 1176 * @deprecated As of v2.1.0.0, please use {@link #getSubquery()} 1177 * @return 1178 */ 1179 public THiveFromQuery getHiveFromQuery() { 1180 1181 return hiveFromQuery; 1182 } 1183 1184 public TExpression getTableExpr() { 1185 return tableExpr; 1186 } 1187 1188 public void setTableExpr(TExpression tableExpr) { 1189 this.tableExpr = tableExpr; 1190 } 1191 1192 private TExpression tableExpr; 1193 1194 public void setTableType(ETableSource tableType) { 1195 this.tableType = tableType; 1196 } 1197 1198 /** 1199 * 1200 * @return what's kind of type this table is. 1201 *<ul> 1202 * <li>{@link ETableSource#objectname}, in from clause, a simple table/view name, reference: {@link TTable#tableName}<li> 1203 * <li>{@link ETableSource#subquery}, is a subquery that retrieves rows from the database, also known as derived table. reference: {@link TTable#subquery}</li> 1204 * <li>{@link ETableSource#tableExpr},it's usually a table-valued expression., reference: {@link TTable#tableExpr}</li> 1205 * <li>{@link ETableSource#function}, it's usually a table-valued function., reference: {@link TTable#funcCall}</li> 1206 * <li>{@link ETableSource#rowList}, it's constructed rows, reference: {@link TTable#rowList}</li> 1207 * <li>{@link ETableSource#containsTable}, CONTAINSTABLE clause of sql server. reference: {@link TTable#containsTable}, type of {@link TContainsTable}</li> 1208 * <li>{@link ETableSource#freetextTable}, FREETEXTTABLE clause of sql server. reference: {@link TTable#containsTable}, type of {@link TContainsTable}</li> 1209 * <li>{@link ETableSource#openrowset}, OPENROWSET clause of sql server. reference: {@link TTable#openRowSet}, type of {@link TOpenRowSet}</li> 1210 * <li>{@link ETableSource#openxml}, OPENXML clause of sql server. reference: {@link TTable#openXML}, type of {@link TOpenXML }</li> 1211 * <li>{@link ETableSource#opendatasource}, OPENDATASOURCE clause of sql server. reference: {@link TTable#openDatasource}, type of {@link TOpenDatasource}</li> 1212 * <li>{@link ETableSource#openquery}, OPENQUERY clause of sql server. reference: {@link TTable#openquery}, type of (@link TOpenQuery)</li> 1213 * </ul> 1214 */ 1215 public ETableSource getTableType() { 1216 1217 return tableType; 1218 } 1219 1220 private ETableSource tableType; 1221 1222 public void setTableName(TObjectName tableName) { 1223 this.tableName = tableName; 1224 tableType = ETableSource.objectname; 1225 this.tableName.splitNameInQuotedIdentifier(); 1226 if (this.getStartToken() == null){ 1227 this.setStartToken(tableName.getStartToken()); 1228 } 1229 1230 if (this.getEndToken() == null){ 1231 this.setEndToken(tableName.getEndToken()); 1232 } 1233 } 1234 1235 public TObjectName getTableName() { 1236 TObjectName ret = tableName; 1237 1238 if (tableType == null) return ret; 1239 1240 switch (tableType){ 1241 case tableExpr: 1242 if (tableExpr.getExpressionType() == EExpressionType.function_t){ 1243 ret = tableExpr.getFunctionCall().getFunctionName(); 1244 } 1245 break; 1246 case function: 1247 ret = getFuncCall().getFunctionName(); 1248 break; 1249 case openrowset: 1250 ret = TObjectName.createObjectName (this.dbvendor, EDbObjectType.table,new TSourceToken("openrowset")); 1251 break; 1252 case rowList: 1253 ret = TObjectName.createObjectName (this.dbvendor, EDbObjectType.table,new TSourceToken("(values_table)")); 1254 break; 1255 case subquery: 1256 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("subquery")); 1257 break; 1258 case td_unpivot: 1259 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("td_unpivot")); 1260 break; 1261 case pivoted_table: 1262 // Check if this is an UNPIVOT to use the correct suffix 1263 String pivotSuffix = "(piviot_table)"; 1264 if (getPivotedTable() != null && getPivotedTable().getPivotClause() != null 1265 && getPivotedTable().getPivotClause().getType() == TPivotClause.unpivot) { 1266 pivotSuffix = "(unpivot_table)"; 1267 } 1268 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken(tableName+pivotSuffix)); 1269 break; 1270 case xmltable: 1271 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("xmltable")); 1272 break; 1273 case jsonTable: 1274 ret = getJsonTable().getFunctionName();// TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("jsontable"));// 1275 break; 1276 case containsTable: 1277 if (containsTable.getType() == TContainsTable.containstable){ 1278 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("containsTable")); 1279 }else { 1280 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("freetexttable")); 1281 } 1282 break; 1283 case opendatasource: 1284 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("opendatasource")); 1285 break; 1286 case unnest: 1287 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken(getAliasName()+"(unnest table)")); 1288 break; 1289 case openxml: 1290 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("openxml")); 1291 break; 1292 case openquery: 1293 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("openquery")); 1294 break; 1295 case output_merge: 1296 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("merge")); 1297 break; 1298 case externalTable: 1299 ret = this.tableName; 1300 break; 1301 case join: 1302 ret = TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("join_expr")); 1303 break; 1304 } 1305 if (ret == null) { 1306 return TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,new TSourceToken("unknown")); 1307 } 1308 else return ret; 1309 } 1310 1311 private TObjectName tableName; 1312 1313 public TTable(TObjectName pobjectname){ 1314 this.tableName = pobjectname; 1315 this.setStartToken(this.tableName.getStartToken()); 1316 this.setEndToken(this.tableName.getEndToken()); 1317 } 1318 1319 1320 public TTable(){ 1321 this.tableName = null; 1322 } 1323 1324 public String getName() { 1325 if (tableName != null) 1326 return tableName.getObjectString(); 1327 else 1328 return getTableName().toString(); 1329 } 1330 1331 1332 public String getPrefixServer(){ 1333 if (tableName != null) return tableName.getServerString(); 1334 else return ""; 1335 } 1336 public String getPrefixDatabase(){ 1337 if (tableName != null) return tableName.getDatabaseString(); 1338 else return ""; 1339 } 1340 public String getPrefixSchema(){ 1341 if (tableName != null) return tableName.getSchemaString(); 1342 else return ""; 1343 } 1344 1345 public boolean isIncludeColumnAlias(){ 1346 // return (this.getAliasClause() != null); 1347 return false; 1348 // ToDo 1349 } 1350 1351 1352 public int searchColumnInAlias(TObjectName pColumn){ 1353 if (getAliasClause() == null) return -1; 1354 return getAliasClause().searchColumn(pColumn); 1355 } 1356 1357 public boolean checkTableByName(String pTablename){ 1358 boolean lcResult = false; 1359 String a,b,c; 1360 b = TBaseType.getTextWithoutQuoted(pTablename); 1361 if (this.getAliasClause() != null){ 1362 a = TBaseType.getTextWithoutQuoted(this.getAliasName()); 1363 lcResult = a.equalsIgnoreCase(b); 1364 } 1365 if (lcResult) return true; 1366 c = TBaseType.getTextWithoutQuoted(this.getTableName().toString()); 1367 lcResult = c.equalsIgnoreCase(b); 1368 return lcResult; 1369 } 1370 1371 public boolean searchColumn(TSelectSqlStatement select, String tableName, TObjectName pColumn, boolean pMustIn){ 1372 // pColumn maybe qualified, so check the table name at first 1373 boolean lcResult = false, isSameTable = false; 1374 if ( tableName.length() == 0){ 1375 isSameTable = true; 1376 }else { 1377 isSameTable = checkTableByName(tableName); 1378 } 1379 1380 if (!isSameTable) return lcResult; 1381 1382 if (this.isBaseTable()){ 1383 lcResult = select.fireOnMetaDatabaseTableColumn(this.getPrefixServer(),this.getPrefixDatabase(),this.getPrefixSchema(),this.getName(),pColumn.getColumnNameOnly()); 1384 }else{ 1385 if (this.getTableType() == ETableSource.subquery){ 1386 if (this.isIncludeColumnAlias()){ 1387 lcResult = this.searchColumnInAlias(pColumn)>=0; 1388 }else{ 1389 lcResult = this.getSubquery().searchColumnInResultSet(pColumn,pMustIn); 1390 } 1391 }else if (this.isCTEName()){ 1392 lcResult = this.getCTE().searchColumnInResultSet(select,this,pColumn,pMustIn); 1393 } 1394 } 1395 1396 if (lcResult){ 1397 this.getLinkedColumns().addObjectName(pColumn); 1398 pColumn.setSourceTable(this); 1399 }else if (pMustIn){ 1400 this.getLinkedColumns().addObjectName(pColumn); 1401 pColumn.setSourceTable(this); 1402 lcResult = true; 1403 } 1404 1405 if (!lcResult){ 1406 if (this.getTableType() == ETableSource.pivoted_table){ 1407 if (this.getLinkedColumns().size() > 0){ 1408 for(TObjectName c: this.getLinkedColumns()){ 1409 lcResult = c.toString().equalsIgnoreCase(pColumn.getColumnNameOnly()); 1410 if (lcResult) break; 1411 } 1412 } 1413 } 1414 } 1415 1416 return lcResult; 1417 } 1418 1419 private TObjectNameList linkedColumns = null; 1420 1421 /** 1422 * @deprecated , this method is deprecated since version 3.3.1.0, don't use it in TSQLResolver2 1423 * @return 1424 */ 1425 public TObjectNameList getLinkedColumns() { 1426 if (linkedColumns == null) { 1427 linkedColumns = new TObjectNameList(); 1428 linkedColumns.setObjectType(TObjectName.ttobjColumn); 1429 } 1430 return linkedColumns; 1431 } 1432 1433 1434 1435 public String getFullNameWithAliasString() { 1436 if (getAliasClause() != null){ 1437 return getFullName()+" "+getAliasClause().toString(); 1438 }else{ 1439 return getFullName(); 1440 } 1441 } 1442 1443 public String getFullName() { 1444 if (tableName == null) return null; 1445 return tableName.toString(); 1446 /* 1447 if (tableName.getSchemaString() == null) 1448 {return this.getName();} 1449 else{ 1450 return tableName.getSchemaString()+"."+this.getName(); 1451 } 1452 */ 1453 1454 } 1455 1456 /** 1457 * 1458 * @return column name related to this table. 1459 * @deprecated As of v1.6.0.1, use {@link #getLinkedColumns()} instead 1460 */ 1461 public TObjectNameList getObjectNameReferences() { 1462 if (objectNameReferences == null){ 1463 objectNameReferences = new TObjectNameList(); 1464 objectNameReferences.setObjectType(TObjectName.ttobjColumn); 1465 } 1466 return objectNameReferences; 1467 } 1468 1469 private TPivotClause pivotClause = null; 1470 1471 public void setPivotClause(TPivotClause pivotClause) { 1472 this.pivotClause = pivotClause; 1473 } 1474 1475 /** 1476 * @deprecated As of v1.6.2.4, replaced by {@link gudusoft.gsqlparser.nodes.TPivotedTable} 1477 * @return 1478 */ 1479 public TPivotClause getPivotClause() { 1480 1481 return pivotClause; 1482 } 1483 1484 /** 1485 * Stored all column names that belong to this table. 1486 */ 1487 private TObjectNameList objectNameReferences = null; 1488 1489 public TTableReferenceList tablerefs = new TTableReferenceList(); 1490 1491 private TDataChangeTable datachangeTable = null; 1492 1493 public void setDatachangeTable(TDataChangeTable datachangeTable) { 1494 this.datachangeTable = datachangeTable; 1495 } 1496 1497 /** 1498 * DB2 data change 1499 * @return 1500 */ 1501 public TDataChangeTable getDatachangeTable() { 1502 return datachangeTable; 1503 } 1504 1505 1506 public boolean isTableRefBelongToThisTable(TTableReference tableref){ 1507 1508 boolean retval = (this.tableName == tableref.objectname); 1509 if (retval) {return retval;} 1510 if (this.tableName.getObjectString().equalsIgnoreCase(tableref.objectname.getObjectString())){ 1511 if ((this.tableName.getSchemaString() == null) 1512 ||(tableref.objectname.getSchemaString() == null) 1513 ) { 1514 retval = true; 1515 }else{ 1516 retval = (this.tableName.getSchemaString().equalsIgnoreCase(tableref.objectname.getSchemaString())); 1517 } 1518 } 1519 return retval; 1520 } 1521 1522 public void accept(TParseTreeVisitor v){ 1523 v.preVisit(this); 1524 1525 v.postVisit(this); 1526 } 1527 1528 public void setColumnDefinitions(TColumnDefinitionList columnDefinitions) { 1529 this.columnDefinitions = columnDefinitions; 1530 } 1531 1532 public void acceptChildren(TParseTreeVisitor v){ 1533 v.preVisit(this); 1534 1535 switch(getTableType()){ 1536 case objectname:{ 1537 getTableName().acceptChildren(v); 1538 if (getFlashback() != null){ 1539 getFlashback().acceptChildren(v); 1540 } 1541 break; 1542 } 1543 case tableExpr:{ 1544 getTableExpr().acceptChildren(v); 1545 break; 1546 } 1547 case subquery:{ 1548 getSubquery().acceptChildren(v); 1549 break; 1550 } 1551 case function:{ 1552 getFuncCall().acceptChildren(v); 1553 break; 1554 } 1555 case pivoted_table:{ 1556 if (this.getEffectType() == ETableEffectType.tetPivot) break; 1557 getPivotedTable().acceptChildren(v); 1558 break; 1559 } 1560 case output_merge:{ 1561 if (getOutputMerge() != null) getOutputMerge().acceptChildren(v); 1562 //e_table_reference.setTextContent(node.getOutputMerge().toString()); 1563 break; 1564 } 1565 case containsTable:{ 1566 getContainsTable().acceptChildren(v); 1567 break; 1568 } 1569 1570 case openrowset:{ 1571 getOpenRowSet().acceptChildren(v); 1572 break; 1573 } 1574 1575 case openxml:{ 1576 getOpenXML().acceptChildren(v); 1577 break; 1578 } 1579 1580 case opendatasource:{ 1581 getOpenDatasource().acceptChildren(v); 1582 break; 1583 } 1584 1585 case openquery:{ 1586 getOpenquery().acceptChildren(v); 1587 break; 1588 } 1589 1590 case datachangeTable:{ 1591 getDatachangeTable().acceptChildren(v); 1592 break; 1593 } 1594 case rowList:{ 1595 getValueClause().acceptChildren(v); 1596 break; 1597 } 1598 case xmltable:{ 1599 getXmlTable().acceptChildren(v); 1600 break; 1601 } 1602 case jsonTable:{ 1603 getJsonTable().acceptChildren(v); 1604 break; 1605 } 1606 case informixOuter:{ 1607 getOuterClause().acceptChildren(v); 1608 break; 1609 } 1610 1611 case table_ref_list:{ 1612 getFromTableList().acceptChildren(v); 1613 break; 1614 } 1615 case hiveFromQuery:{ 1616 getHiveFromQuery().acceptChildren(v); 1617 break; 1618 } 1619 case externalTable: 1620 this.columnDefinitions.acceptChildren(v); 1621 break; 1622 case join: 1623 this.joinExpr.acceptChildren(v); 1624 break; 1625 case unnest: 1626 this.getUnnestClause().acceptChildren(v); 1627 break; 1628 default: 1629 //sb.append(node.toString().replace(">",">").replace("<","<")); 1630 break; 1631 1632 } 1633 1634 1635 if (getPxGranule() != null){ 1636 getPxGranule().acceptChildren(v); 1637 } 1638 1639 if (getTableSample() != null){ 1640 getTableSample().acceptChildren(v); 1641 } 1642 1643 if (getAliasClause() != null){ 1644 getAliasClause().acceptChildren(v); 1645 } 1646 1647 1648 if (getTableHintList() != null){ 1649 for(int i=0;i<getTableHintList().size();i++){ 1650 TTableHint tableHint = getTableHintList().getElement(i); 1651 tableHint.acceptChildren(v); 1652 } 1653 } 1654 1655 if (getLateralViewList() != null){ 1656 for(TLateralView lateralView:getLateralViewList()){ 1657 lateralView.acceptChildren(v); 1658 } 1659 } 1660 1661 1662 v.postVisit(this); 1663 } 1664 1665 public void setRowList(TMultiTargetList rowList) { 1666 this.rowList = rowList; 1667 } 1668 1669 public void setSubquery(TSelectSqlStatement subquery) { 1670 this.subquery = subquery; 1671 } 1672 1673 public void setLinkedColumns(TObjectNameList linkedColumns) { 1674 this.linkedColumns = linkedColumns; 1675 } 1676 1677 public void setTablerefs(TTableReferenceList tablerefs) { 1678 this.tablerefs = tablerefs; 1679 } 1680 1681 private boolean starColumnExpanded = false; 1682 1683 private ArrayList<String> expandedStarColumns = new ArrayList<String>(); 1684 1685 private void getExpandStarColumnsFromSubquery(TSelectSqlStatement subquery, ArrayList<String> expandedStarColumns){ 1686 1687 for(TResultColumn resultColumn:subquery.getResultColumnList()){ 1688 if (resultColumn.toString().endsWith("*")){ 1689 TTable srcTable = resultColumn.getExpr().getObjectOperand().getSourceTable(); 1690 if ( srcTable!= null){ 1691 ArrayList<String> list = srcTable.getExpandedStarColumns(); 1692 expandedStarColumns.addAll(list); 1693 } 1694 }else{ 1695 expandedStarColumns.add(resultColumn.getDisplayName()); 1696 } 1697 } 1698 } 1699 1700 /** 1701 * If a star column is linked to this table, use this method to returns all underlying columns that represented by 1702 * the star column. 1703 * <br> 1704 * <br> The returned column always prefixed with 1705 * <br> 1. the table alias. 1706 * <br> 2. the table name 1707 * <br> 3. the alias of query (if the table is a subquery) 1708 * <br> 4. empty if the no alias is specified for a subquery 1709 * 1710 * @return a list of columns 1711 */ 1712 public ArrayList<String> getExpandedStarColumns(){ 1713 if (starColumnExpanded) return expandedStarColumns; 1714 1715 switch (getTableType()){ 1716 case objectname: 1717 if (this.isCTEName()){ 1718 if (this.getCteColomnReferences()!=null){ 1719 for(TObjectName n:this.getCteColomnReferences()){ 1720 expandedStarColumns.add(n.toString()); 1721 } 1722 }else if (this.getCTE().getSubquery() != null){ 1723 this.getExpandStarColumnsFromSubquery(this.getCTE().getSubquery(),this.expandedStarColumns); 1724 } 1725 }else{ 1726 if (this.getSqlEnv() != null){ 1727 ArrayList<String> columns = this.getSqlEnv().getColumnsInTable(this.getPrefixDatabase() +"."+this.getPrefixSchema()+"."+this.getName(),false); 1728 if (columns != null) expandedStarColumns = columns; 1729 if (this.getAliasClause() != null){ 1730 //replace table name with alias 1731 } 1732 } 1733 if ((expandedStarColumns.size() == 0)&&(getLinkedColumns().size()>0)){ 1734 for(TObjectName linkColumn:getLinkedColumns()){ 1735 if (linkColumn.toString().endsWith("*")) continue; 1736 String s = linkColumn.getColumnNameOnly(); 1737 if (this.getAliasClause() != null){ 1738 s = this.getAliasName()+"."+s; 1739 }else{ 1740 s = this.getName()+"."+s; 1741 } 1742 if (expandedStarColumns.indexOf(s) == -1) expandedStarColumns.add(s); 1743 } 1744 } 1745 } 1746 1747 break; 1748 case subquery: 1749 this.getExpandStarColumnsFromSubquery(this.getSubquery(),this.expandedStarColumns); 1750 break; 1751 default: 1752 break; 1753 } 1754 1755 starColumnExpanded = true; 1756 return expandedStarColumns; 1757 } 1758 1759// @Override 1760// public String toString(){ 1761// if (getAliasClause() != null) return getAliasClause().toString(); 1762// 1763// switch (getTableType()){ 1764// case objectname: 1765// return getName().toString(); 1766// break; 1767// default: 1768// 1769// break; 1770// } 1771// } 1772 1773 @Override 1774 public String toString(){ 1775 String ret = super.toString(); 1776 if (ret != null) return ret; 1777 if (tableName != null) return tableName.getObjectString(); 1778 return null; 1779 } 1780 1781}