15
15
16
16
import com .fasterxml .jackson .annotation .JsonCreator ;
17
17
import com .fasterxml .jackson .annotation .JsonProperty ;
18
+ import com .google .common .collect .ImmutableList ;
18
19
import com .google .common .collect .ImmutableSet ;
19
20
import io .trino .Session ;
20
21
import io .trino .cost .PlanCostEstimate ;
24
25
import io .trino .spi .connector .CatalogSchemaTableName ;
25
26
import io .trino .spi .connector .ColumnHandle ;
26
27
import io .trino .spi .connector .ColumnMetadata ;
28
+ import io .trino .spi .eventlistener .OutputColumnMetadata ;
27
29
import io .trino .spi .predicate .Domain ;
28
30
import io .trino .spi .predicate .Range ;
29
31
import io .trino .spi .predicate .TupleDomain ;
30
32
import io .trino .spi .type .Type ;
31
33
import io .trino .sql .PlannerContext ;
34
+ import io .trino .sql .analyzer .Analysis ;
35
+ import io .trino .sql .analyzer .OutputColumn ;
32
36
import io .trino .sql .planner .DomainTranslator ;
33
37
import io .trino .sql .planner .Plan ;
34
38
import io .trino .sql .planner .plan .FilterNode ;
47
51
import io .trino .sql .planner .planprinter .IoPlanPrinter .IoPlan .IoPlanBuilder ;
48
52
49
53
import java .util .HashSet ;
54
+ import java .util .List ;
50
55
import java .util .Map ;
51
56
import java .util .Objects ;
52
57
import java .util .Optional ;
53
58
import java .util .Set ;
54
59
55
60
import static com .google .common .base .MoreObjects .toStringHelper ;
61
+ import static com .google .common .collect .ImmutableList .toImmutableList ;
56
62
import static com .google .common .collect .ImmutableSet .toImmutableSet ;
57
63
import static io .airlift .json .JsonCodec .jsonCodec ;
58
64
import static java .lang .String .format ;
@@ -64,26 +70,28 @@ public class IoPlanPrinter
64
70
private final PlannerContext plannerContext ;
65
71
private final Session session ;
66
72
private final ValuePrinter valuePrinter ;
73
+ private final Optional <Analysis > analysis ;
67
74
68
- private IoPlanPrinter (Plan plan , PlannerContext plannerContext , Session session )
75
+ private IoPlanPrinter (Plan plan , PlannerContext plannerContext , Session session , Optional < Analysis > analysis )
69
76
{
70
77
this .plan = requireNonNull (plan , "plan is null" );
71
78
this .plannerContext = requireNonNull (plannerContext , "plannerContext is null" );
72
79
this .session = requireNonNull (session , "session is null" );
80
+ this .analysis = requireNonNull (analysis , "analysis is null" );
73
81
this .valuePrinter = new ValuePrinter (plannerContext .getMetadata (), plannerContext .getFunctionManager (), session );
74
82
}
75
83
76
84
/**
77
85
* @throws io.trino.NotInTransactionException if called without an active transaction
78
86
*/
79
- public static String textIoPlan (Plan plan , PlannerContext plannerContext , Session session )
87
+ public static String textIoPlan (Plan plan , PlannerContext plannerContext , Session session , Analysis analysis )
80
88
{
81
- return new IoPlanPrinter (plan , plannerContext , session ).print ();
89
+ return new IoPlanPrinter (plan , plannerContext , session , Optional . of ( analysis ) ).print ();
82
90
}
83
91
84
92
private String print ()
85
93
{
86
- IoPlanBuilder ioPlanBuilder = new IoPlanBuilder (plan );
94
+ IoPlanBuilder ioPlanBuilder = new IoPlanBuilder (plan , analysis );
87
95
plan .getRoot ().accept (new IoPlanVisitor (), ioPlanBuilder );
88
96
return jsonCodec (IoPlan .class ).toJson (ioPlanBuilder .build ());
89
97
}
@@ -93,16 +101,19 @@ public static class IoPlan
93
101
private final Set <TableColumnInfo > inputTableColumnInfos ;
94
102
private final Optional <CatalogSchemaTableName > outputTable ;
95
103
private final EstimatedStatsAndCost estimate ;
104
+ private final Optional <List <OutputColumnMetadata >> columns ;
96
105
97
106
@ JsonCreator
98
107
public IoPlan (
99
108
@ JsonProperty ("inputTableColumnInfos" ) Set <TableColumnInfo > inputTableColumnInfos ,
100
109
@ JsonProperty ("outputTable" ) Optional <CatalogSchemaTableName > outputTable ,
101
- @ JsonProperty ("estimate" ) EstimatedStatsAndCost estimate )
110
+ @ JsonProperty ("estimate" ) EstimatedStatsAndCost estimate ,
111
+ @ JsonProperty ("outputColumns" ) Optional <List <OutputColumnMetadata >> columns )
102
112
{
103
113
this .inputTableColumnInfos = ImmutableSet .copyOf (requireNonNull (inputTableColumnInfos , "inputTableColumnInfos is null" ));
104
114
this .outputTable = requireNonNull (outputTable , "outputTable is null" );
105
115
this .estimate = requireNonNull (estimate , "estimate is null" );
116
+ this .columns = requireNonNull (columns , "columns is null" ).map (ImmutableList ::copyOf );
106
117
}
107
118
108
119
@ JsonProperty
@@ -123,6 +134,12 @@ public EstimatedStatsAndCost getEstimate()
123
134
return estimate ;
124
135
}
125
136
137
+ @ JsonProperty
138
+ public Optional <List <OutputColumnMetadata >> getColumns ()
139
+ {
140
+ return columns ;
141
+ }
142
+
126
143
@ Override
127
144
public boolean equals (Object obj )
128
145
{
@@ -134,7 +151,8 @@ public boolean equals(Object obj)
134
151
}
135
152
IoPlan o = (IoPlan ) obj ;
136
153
return Objects .equals (inputTableColumnInfos , o .inputTableColumnInfos ) &&
137
- Objects .equals (outputTable , o .outputTable );
154
+ Objects .equals (outputTable , o .outputTable ) &&
155
+ Objects .equals (columns , o .columns );
138
156
}
139
157
140
158
@ Override
@@ -150,20 +168,25 @@ public String toString()
150
168
.add ("inputTableColumnInfos" , inputTableColumnInfos )
151
169
.add ("outputTable" , outputTable )
152
170
.add ("estimate" , estimate )
171
+ .add ("outputColumns" , columns )
153
172
.toString ();
154
173
}
155
174
156
175
protected static class IoPlanBuilder
157
176
{
158
177
private final Plan plan ;
178
+ private final Optional <Analysis > analysis ;
159
179
private final Set <TableColumnInfo > inputTableColumnInfos ;
160
180
private Optional <CatalogSchemaTableName > outputTable ;
181
+ private Optional <List <OutputColumnMetadata >> columns ;
161
182
162
- private IoPlanBuilder (Plan plan )
183
+ private IoPlanBuilder (Plan plan , Optional < Analysis > analysis )
163
184
{
164
185
this .plan = plan ;
186
+ this .analysis = analysis ;
165
187
this .inputTableColumnInfos = new HashSet <>();
166
188
this .outputTable = Optional .empty ();
189
+ this .columns = Optional .empty ();
167
190
}
168
191
169
192
private IoPlanBuilder addInputTableColumnInfo (TableColumnInfo tableColumnInfo )
@@ -172,6 +195,32 @@ private IoPlanBuilder addInputTableColumnInfo(TableColumnInfo tableColumnInfo)
172
195
return this ;
173
196
}
174
197
198
+ private IoPlanBuilder setOutputColumns (Optional <List <OutputColumnMetadata >> columns )
199
+ {
200
+ this .columns = columns ;
201
+ return this ;
202
+ }
203
+
204
+ private void setOutputColumns ()
205
+ {
206
+ analysis .ifPresent (analysis ->
207
+ setOutputColumns (analysis .getTarget ()
208
+ .flatMap (target -> target .getColumns ()
209
+ .map (columns -> columns .stream ()
210
+ .map (this ::createOutputColumnMetadata )
211
+ .collect (toImmutableList ())))));
212
+ }
213
+
214
+ private OutputColumnMetadata createOutputColumnMetadata (OutputColumn column )
215
+ {
216
+ return new OutputColumnMetadata (
217
+ column .getColumn ().getName (),
218
+ column .getColumn ().getType (),
219
+ column .getSourceColumns ().stream ()
220
+ .map (Analysis .SourceColumn ::getColumnDetail )
221
+ .collect (toImmutableSet ()));
222
+ }
223
+
175
224
private IoPlanBuilder setOutputTable (CatalogSchemaTableName outputTable )
176
225
{
177
226
this .outputTable = Optional .of (outputTable );
@@ -180,7 +229,7 @@ private IoPlanBuilder setOutputTable(CatalogSchemaTableName outputTable)
180
229
181
230
private IoPlan build ()
182
231
{
183
- return new IoPlan (inputTableColumnInfos , outputTable , getEstimatedStatsAndCost ());
232
+ return new IoPlan (inputTableColumnInfos , outputTable , getEstimatedStatsAndCost (), columns );
184
233
}
185
234
186
235
private EstimatedStatsAndCost getEstimatedStatsAndCost ()
@@ -721,6 +770,7 @@ else if (writerTarget instanceof CreateReference || writerTarget instanceof Inse
721
770
else {
722
771
throw new IllegalStateException (format ("Unknown WriterTarget subclass %s" , writerTarget .getClass ().getSimpleName ()));
723
772
}
773
+ context .setOutputColumns ();
724
774
return processChildren (node , context );
725
775
}
726
776
0 commit comments