001package gudusoft.gsqlparser.nodes; 002 003 004import gudusoft.gsqlparser.*; 005import gudusoft.gsqlparser.sqlenv.TSQLTable; 006import gudusoft.gsqlparser.stmt.TSelectSqlStatement; 007 008import java.util.ArrayList; 009 010public class TPivotInClause extends TParseTreeNode { 011 private TResultColumnList items; 012 private TSelectSqlNode selectSqlNode; 013 private ArrayList<TExpressionList> valueList; 014 015 public ArrayList<TExpressionList> getValueList() { 016 return valueList; 017 } 018 019 public TSelectSqlStatement getSubQuery() { 020 return subQuery; 021 } 022 023 private TSelectSqlStatement subQuery; 024 025 public void linkColumnToTable(TTable table, TSQLTable sqlTable){ 026 027 if (items != null){ 028 for(TResultColumn resultColumn:items){ 029 // An explicit alias names the generated column outright: 030 // IN ('direct' AS Store) produces a column called Store, not 'direct'. 031 // Oracle, Snowflake, BigQuery and Teradata all behave this way. 032 // Kept verbatim, quote state included, to match 033 // PivotNamespace.inListItemAlias - the name published here and the 034 // name resolver2 lets the column be resolved by must agree. 035 TObjectName itemAlias = (resultColumn.getAliasClause() == null) 036 ? null : resultColumn.getAliasClause().getAliasName(); 037 if (itemAlias != null && itemAlias.toString().length() > 0){ 038 TObjectName newObject = TObjectName.createObjectName (this.dbvendor, EDbObjectType.column, new TSourceToken(itemAlias.toString())); 039 table.getLinkedColumns().addObjectName(newObject); 040 newObject.setSourceTable(table); 041 }else if (resultColumn.getExpr().getExpressionType() == EExpressionType.simple_object_name_t){ 042 // the name follows PivotNamespace's rule (BigQuery "HOUSTON" is a string naming HOUSTON); 043 // the operand keeps its own link to the pivot either way 044 TObjectName operand = resultColumn.getExpr().getObjectOperand(); 045 String name = gudusoft.gsqlparser.resolver2.namespace.PivotNamespace.inListItemColumnName(resultColumn); 046 if (name == null || name.equals(operand.toString())) { 047 table.getLinkedColumns().addObjectName(operand); 048 } else { 049 TObjectName newObject = TObjectName.createObjectName (this.dbvendor, EDbObjectType.column, new TSourceToken(name)); 050 table.getLinkedColumns().addObjectName(newObject); 051 newObject.setSourceTable(table); 052 } 053 operand.setSourceTable(table); 054 }else if (resultColumn.getExpr().getExpressionType() == EExpressionType.simple_constant_t){ 055 // the name follows PivotNamespace's rule: the literal as written (Oracle, Snowflake, Teradata), 056 // else its value (BigQuery IN ('AA') names AA) 057 TSourceToken value = resultColumn.getExpr().getConstantOperand().getValueToken(); 058 String name = gudusoft.gsqlparser.resolver2.namespace.PivotNamespace.inListItemColumnName(resultColumn); 059 // IN (NULL) has no value token: the column is still named by the rule (Oracle names it NULL) 060 TObjectName newObject= TObjectName.createObjectName (this.dbvendor, EDbObjectType.column, 061 name == null || (value != null && name.equals(value.toString())) ? value 062 : new TSourceToken(name)); 063 table.getLinkedColumns().addObjectName(newObject); 064 newObject.setSourceTable(table); 065 } 066 } 067 068 if (sqlTable != null){ 069 for(TResultColumn resultColumn:items){ 070 sqlTable.addColumn(resultColumn.getDisplayName()); 071 } 072 } 073 }else if (subQuery != null){ 074 for(TResultColumn resultColumn:subQuery.getResultColumnList()){ 075 TObjectName pivotColumn = TObjectName.createObjectName (this.dbvendor, EDbObjectType.column,new TSourceToken(resultColumn.getDisplayName())); 076 table.getLinkedColumns().addObjectName(pivotColumn); 077 pivotColumn.setSourceTable(table); 078 pivotColumn.setSourceColumn(resultColumn); 079 if (sqlTable != null){ 080 sqlTable.addColumn(pivotColumn.toString()); 081 } 082 } 083 } 084 } 085 086 public TResultColumnList getItems() { 087 return items; 088 } 089 090 public void init(Object arg1){ 091 if (arg1 instanceof TResultColumnList){ 092 items = (TResultColumnList)arg1; 093 }else if (arg1 instanceof TSelectSqlNode){ 094 selectSqlNode = (TSelectSqlNode)arg1; 095 }else{ 096 valueList = (ArrayList<TExpressionList>)arg1; 097 } 098 099 } 100 101 public void doParse(TCustomSqlStatement psql, ESqlClause plocation){ 102 if (selectSqlNode != null){ 103 subQuery = new TSelectSqlStatement(psql.dbvendor); 104 subQuery.rootNode = selectSqlNode; 105 subQuery.setLocation(ESqlClause.pivot_in); 106 subQuery.doParseStatement(psql); 107 } 108 } 109 110 public void accept(TParseTreeVisitor v){ 111 v.preVisit(this); 112 v.postVisit(this); 113 } 114 115 public void acceptChildren(TParseTreeVisitor v) { 116 v.preVisit(this); 117 if (items != null) items.accept(v); 118 if (subQuery != null) subQuery.accept(v); 119 v.postVisit(this); 120 } 121 122 public void setItems(TResultColumnList items) { 123 this.items = items; 124 } 125 126 public void setSubQuery(TSelectSqlStatement subQuery) { 127 this.subQuery = subQuery; 128 } 129}