001package gudusoft.gsqlparser.nodes; 002 003import gudusoft.gsqlparser.*; 004import gudusoft.gsqlparser.sqlenv.TSQLTable; 005import gudusoft.gsqlparser.visitors.TColumnNameVisitor; 006 007import java.util.ArrayList; 008 009/** 010* use the PIVOT and UNPIVOT relational operators to change a table-valued expression into another table. 011*/ 012 013public class TPivotClause extends TNodeWithAliasClause implements IRelation { 014 015 016 ArrayList<TAttributeNode> relationAttributes = new ArrayList<>(); 017 @Override 018 public ArrayList<TAttributeNode> getAttributes(){ 019 return relationAttributes; 020 } 021 022 @Override 023 public int size(){ 024 return relationAttributes.size(); 025 } 026 027 @Override 028 public String getRelationName(){ 029 return displayName; 030 }; 031 032 private String displayName; 033 public String getDisplayName(){ 034 return displayName; 035 } 036 public void initAttributes(){ 037 displayName = ""; 038 ArrayList<String> columns = new ArrayList<>(); 039 040 switch (getType()) { 041 case pivot: 042 displayName = TTable.PIVOT_CLAUSE_ALIAS; 043 if (pivotInClause.getItems() != null){ 044 for(TResultColumn resultColumn: pivotInClause.getItems()){ 045 columns.add(resultColumn.getDisplayName()); 046 } 047 } 048 break; 049 case unpivot: 050 displayName = TTable.UNPIVOT_CLAUSE_ALIAS; 051 break; 052 } 053 054 055 if (getAliasClause() != null){ 056 displayName = getAliasClause().getAliasName().toString(); 057 if (getAliasClause().getColumns() != null){ 058 columns.clear(); 059 for(TObjectName column:getAliasClause().getColumns()){ 060 061 columns.add(column.toString()); 062 } 063 } 064 } 065 066 for(String c:columns){ 067 TAttributeNode node = new TAttributeNode(displayName+"."+c,pivotTable); 068 //relationAttributes.add(node); 069 TAttributeNode.addNodeToList(node,relationAttributes); 070 } 071 072 } 073 074 075 public final static int pivot = 1; 076 public final static int unpivot = 2; 077 078 private int type = pivot; 079 080 public TTable getPivotTable() { 081 return pivotTable; 082 } 083 084 private TTable pivotTable = null; 085 086 087// private TAliasClause aliasClause = null; 088// 089// @Override 090// public TAliasClause getAliasClause() { 091// return aliasClause; 092// } 093// 094// @Override 095// public void setAliasClause(TAliasClause aliasClause) { 096// 097// this.aliasClause = aliasClause; 098// } 099 100 private TPivotInClause pivotInClause; 101 102 /** 103 * The names of the columns this operator generates, in text order, duplicates included: for UNPIVOT its value 104 * and FOR columns, for PIVOT the names of its alias column list or one per IN item. The rule is resolver2's 105 * ({@code PivotNamespace.generatedColumnNames}), so a consumer that publishes a pivot's columns names them as 106 * a reference to them is resolved (plan 09 slice 10). 107 */ 108 public java.util.List<String> getGeneratedColumnNames() { 109 return gudusoft.gsqlparser.resolver2.namespace.PivotNamespace.generatedColumnNames(this); 110 } 111 112 /** 113 * For each name of {@link #getGeneratedColumnNames()}, whether it is the column's stored name as written: the 114 * literal of an unaliased IN value in a dialect that names the column after it ({@code IN ('direct')} in Oracle 115 * names the column {@code 'direct'}, referenced as {@code "'direct'"}), never an identifier spelling to fold. 116 */ 117 public java.util.List<Boolean> getGeneratedColumnStored() { 118 return gudusoft.gsqlparser.resolver2.namespace.PivotNamespace.generatedColumnsStored(this); 119 } 120 121 public TPivotInClause getPivotInClause() { 122 return pivotInClause; 123 } 124 125 private TUnpivotInClause unpivotInClause; 126 127 public TUnpivotInClause getUnpivotInClause() { 128 return unpivotInClause; 129 } 130 131 private TResultColumnList aggregation_function_list; 132 /** 133 * @deprecated since 1.7.1.1 134 */ 135 private TResultColumnList in_result_list; 136 137 private TObjectNameList pivotColumnList; 138 139 public TObjectNameList getPivotColumnList() { 140 return pivotColumnList; 141 } 142 143 /** 144 * @deprecated since 1.7.1.1, use {@link #getPivotInClause} instead 145 * @return result column list 146 */ 147 public TResultColumnList getIn_result_list() { 148 return in_result_list; 149 } 150 151 public TResultColumnList getAggregation_function_list() { 152 153 return aggregation_function_list; 154 } 155 156 public void setType(int type) { 157 this.type = type; 158 } 159 160 public int getType() { 161 162 return type; 163 } 164 165 private TFunctionCall aggregation_function = null; 166 /** 167 * @deprecated since 1.7.1.1, use {@link #valueColumnList} instead 168 */ 169 private TObjectName valueColumn = null; 170 private TObjectNameList valueColumnList = null; 171 172 public TObjectNameList getValueColumnList() { 173 return valueColumnList; 174 } 175 176 /** 177 * @deprecated since 1.7.1.1, use {@link #getPivotColumnList} instead. 178 */ 179 private TObjectName pivotColumn = null; 180 private TObjectNameList columnList = null; 181 182 /** 183 * 184 * @return Is a system or user-defined aggregate function that accepts one or more inputs. 185 */ 186 public TFunctionCall getAggregation_function() { 187 return aggregation_function; 188 } 189 190 /** 191 * 192 * @return In the PIVOT clause, lists the values in the pivot_column that will become the column names of the output table. The list cannot specify any column names that already exist in the input table_source that is being pivoted. 193 * In the UNPIVOT clause, lists the columns in table_source that will be narrowed into a single pivot_column. 194 */ 195 public TObjectNameList getColumnList() { 196 return columnList; 197 } 198 199 /** 200 * @deprecated since 1.7.1.1 , use {@link #getPivotColumnList} instead. 201 * @return Is the pivot column of the PIVOT operator. 202 */ 203 public TObjectName getPivotColumn() { 204 return pivotColumn; 205 } 206 207 /** 208 * @deprecated since 1.7.1.1, use {@link #getValueColumnList} instead. 209 * @return Is the value column of the PIVOT operator. 210 * When used with UNPIVOT, value_column cannot be the name of an existing column in the input table_source. 211 */ 212 public TObjectName getValueColumn() { 213 return valueColumn; 214 } 215 216 public void init(Object arg1,Object arg2){ 217 if (arg1 instanceof TFunctionCall){ 218 aggregation_function = (TFunctionCall)arg1; // pivot clause, sql server 219 }else if (arg1 instanceof TResultColumnList){ 220 aggregation_function_list = (TResultColumnList)arg1; // pivot clause, oracle 221 }else if (arg1 instanceof TObjectNameList){ 222 valueColumnList = (TObjectNameList)arg1; // unpivot clause 223 }else if (arg1 instanceof TObjectName){ 224 valueColumn = (TObjectName)arg1; 225 } 226 227 if (arg2 instanceof TObjectName){ 228 pivotColumn = (TObjectName)arg2; 229 }else if (arg2 instanceof TObjectNameList){ 230 pivotColumnList = (TObjectNameList)arg2; 231 } 232 } 233 234 public void init(Object arg1,Object arg2,Object arg3){ 235 init(arg1,arg2); 236 if (arg3 instanceof TUnpivotInClause){ 237 unpivotInClause = (TUnpivotInClause)arg3; 238 } else if (arg3 instanceof TPivotInClause){ 239 pivotInClause = (TPivotInClause)arg3; 240 } 241// else if (arg3 instanceof TResultColumnList){ 242// in_result_list = (TResultColumnList)arg3; 243// } else if (arg3 instanceof TObjectNameList){ 244// pivotColumnList = (TObjectNameList)arg3; 245// } 246 } 247 248 public void doParse(TCustomSqlStatement psql, ESqlClause plocation){ 249 TSQLTable sqlTable = null; 250 boolean addColumnFromAlias = false; 251 252 if (getAliasClause() != null){ 253 getAliasClause().doParse(psql,plocation); 254 255 pivotTable = new TTable(); 256 257 pivotTable.setTableName(getAliasClause().getAliasName()); 258 pivotTable.setTableType(ETableSource.pivoted_table); 259 pivotTable.setEffectType(ETableEffectType.tetPivot); 260 psql.getTables().addTable(pivotTable); 261 262 pivotTable.setSourceTableOfPivot(psql.getTables().getTable(0)); 263 264 if (psql.getSqlEnv() != null) { 265 sqlTable = psql.getSqlEnv().addTable(pivotTable.getFullName(), true); 266 } 267 if (getAliasClause().getColumns()!=null){ 268 addColumnFromAlias = true; 269 for(TObjectName column:getAliasClause().getColumns()){ 270 pivotTable.getLinkedColumns().addObjectName(column); 271 column.setSourceTable(pivotTable); 272 } 273 274 if (sqlTable != null){ 275 for(TObjectName column:getAliasClause().getColumns()){ 276 sqlTable.addColumn(column.toString()); 277 } 278 } 279 } 280 }else { // alias is not specified 281 282 pivotTable = new TTable(); 283 if (getType() == pivot){ 284 pivotTable.setTableName(TObjectName.createObjectName (psql.dbvendor, EDbObjectType.column_alias,new TSourceToken("pivot_alias"))); 285 }else{ 286 pivotTable.setTableName(TObjectName.createObjectName (psql.dbvendor,EDbObjectType.column_alias,new TSourceToken("unpivot_alias"))); 287 } 288 289 290 pivotTable.setTableType(ETableSource.pivoted_table); 291 pivotTable.setEffectType(ETableEffectType.tetPivot); 292 psql.getTables().addTable(pivotTable); 293 294 pivotTable.setSourceTableOfPivot(psql.getTables().getTable(0)); 295 296 if (psql.getSqlEnv() != null) { 297 sqlTable = psql.getSqlEnv().addTable(pivotTable.getFullName(), true); 298 } 299 } 300 301 switch (getType()){ 302 case pivot: 303 if (aggregation_function_list != null){ 304 TColumnNameVisitor objectNameVisitor = new TColumnNameVisitor(); 305 aggregation_function_list.acceptChildren(objectNameVisitor); 306 for(TObjectName objectName:objectNameVisitor.getObjectNames()){ 307 pivotTable.getSourceTableOfPivot().getLinkedColumns().addObjectName(objectName); 308 objectName.setSourceTable(pivotTable.getSourceTableOfPivot()); 309 } 310 aggregation_function_list.doParse(psql,plocation); 311 }else if (aggregation_function != null){ 312 TColumnNameVisitor objectNameVisitor = new TColumnNameVisitor(); 313 aggregation_function.getArgs().acceptChildren(objectNameVisitor); 314 for(TObjectName objectName:objectNameVisitor.getObjectNames()){ 315 pivotTable.getSourceTableOfPivot().getLinkedColumns().addObjectName(objectName); 316 objectName.setSourceTable(pivotTable.getSourceTableOfPivot()); 317 } 318 319 aggregation_function.doParse(psql,plocation); 320 }; 321 322 if (pivotColumnList != null){ 323 for(TObjectName objectName:pivotColumnList){ 324 pivotTable.getSourceTableOfPivot().getLinkedColumns().addObjectName(objectName); 325 objectName.setSourceTable(pivotTable.getSourceTableOfPivot()); 326 } 327 } 328 pivotInClause.doParse(psql,plocation); 329 if (!addColumnFromAlias){ 330 pivotInClause.linkColumnToTable(pivotTable, sqlTable); 331 } 332 333 break; 334 case unpivot: 335 //valueColumnList. 336 if (pivotTable!=null){ 337 if (valueColumnList != null){ 338 for(TObjectName objectName: valueColumnList){ 339 pivotTable.getLinkedColumns().addObjectName(objectName); 340 objectName.setSourceTable(pivotTable); 341 if (sqlTable != null){ 342 sqlTable.addColumn(objectName.toString()); 343 } 344 } 345 } 346 347 if (pivotColumnList!=null){ 348 for(TObjectName objectName: pivotColumnList){ 349 pivotTable.getLinkedColumns().addObjectName(objectName); 350 objectName.setSourceTable(pivotTable); 351 if (sqlTable != null){ 352 sqlTable.addColumn(objectName.toString()); 353 } 354 } 355 } 356 } 357 unpivotInClause.doParse(psql,plocation); 358 unpivotInClause.linkColumnToPivotSourceTable(pivotTable.getSourceTableOfPivot()); 359 break; 360 } 361 } 362 363 public void accept(TParseTreeVisitor v){ 364 v.preVisit(this); 365 v.postVisit(this); 366 } 367 368 public void acceptChildren(TParseTreeVisitor v){ 369 v.preVisit(this); 370 // pivotTable.acceptChildren(v); 371 switch (getType()){ 372 case pivot: 373 if (aggregation_function_list != null){ 374 aggregation_function_list.acceptChildren(v); 375 }else if (aggregation_function != null){ 376 aggregation_function.acceptChildren(v); 377 } 378 pivotColumnList.acceptChildren(v); 379 if (pivotInClause != null){ 380 pivotInClause.acceptChildren(v); 381 } 382 break; 383 case unpivot: 384 valueColumnList.acceptChildren(v); 385 pivotColumnList.acceptChildren(v); 386 unpivotInClause.acceptChildren(v); 387 break; 388 } 389 390 391 if (getAliasClause() != null){ 392 getAliasClause().acceptChildren(v); 393 } 394 v.postVisit(this); 395 } 396 397 public void setPivotInClause(TPivotInClause pivotInClause) { 398 this.pivotInClause = pivotInClause; 399 } 400 401 public void setUnpivotInClause(TUnpivotInClause unpivotInClause) { 402 this.unpivotInClause = unpivotInClause; 403 } 404 405 public void setAggregation_function_list(TResultColumnList aggregation_function_list) { 406 this.aggregation_function_list = aggregation_function_list; 407 } 408 409 public void setPivotColumnList(TObjectNameList pivotColumnList) { 410 this.pivotColumnList = pivotColumnList; 411 } 412 413 public void setAggregation_function(TFunctionCall aggregation_function) { 414 this.aggregation_function = aggregation_function; 415 } 416 417 public void setValueColumnList(TObjectNameList valueColumnList) { 418 this.valueColumnList = valueColumnList; 419 } 420 421 public void setColumnList(TObjectNameList columnList) { 422 this.columnList = columnList; 423 } 424}