2222import com .facebook .presto .spi .relation .VariableReferenceExpression ;
2323import com .fasterxml .jackson .annotation .JsonCreator ;
2424import com .fasterxml .jackson .annotation .JsonProperty ;
25+ import com .google .common .collect .ImmutableList ;
26+ import com .google .common .collect .ImmutableMap ;
2527import com .google .errorprone .annotations .Immutable ;
2628
29+ import java .util .Collection ;
2730import java .util .List ;
2831import java .util .Map ;
2932import java .util .Optional ;
3033
3134import static com .google .common .base .Preconditions .checkArgument ;
35+ import static com .google .common .collect .ImmutableList .toImmutableList ;
3236import static java .util .Objects .requireNonNull ;
3337
3438@ Immutable
@@ -37,22 +41,24 @@ public class TableFunctionNode
3741{
3842 private final String name ;
3943 private final Map <String , Argument > arguments ;
40- private final List <VariableReferenceExpression > outputVariables ;
44+ private final List <VariableReferenceExpression > properOutputs ;
4145 private final List <PlanNode > sources ;
4246 private final List <TableArgumentProperties > tableArgumentProperties ;
47+ private final List <List <String >> copartitioningLists ;
4348 private final TableFunctionHandle handle ;
4449
4550 @ JsonCreator
4651 public TableFunctionNode (
4752 @ JsonProperty ("id" ) PlanNodeId id ,
4853 @ JsonProperty ("name" ) String name ,
4954 @ JsonProperty ("arguments" ) Map <String , Argument > arguments ,
50- @ JsonProperty ("outputVariables " ) List <VariableReferenceExpression > outputVariables ,
55+ @ JsonProperty ("properOutputs " ) List <VariableReferenceExpression > properOutputs ,
5156 @ JsonProperty ("sources" ) List <PlanNode > sources ,
5257 @ JsonProperty ("tableArgumentProperties" ) List <TableArgumentProperties > tableArgumentProperties ,
58+ @ JsonProperty ("copartitioningLists" ) List <List <String >> copartitioningLists ,
5359 @ JsonProperty ("handle" ) TableFunctionHandle handle )
5460 {
55- this (Optional .empty (), id , Optional .empty (), name , arguments , outputVariables , sources , tableArgumentProperties , handle );
61+ this (Optional .empty (), id , Optional .empty (), name , arguments , properOutputs , sources , tableArgumentProperties , copartitioningLists , handle );
5662 }
5763
5864 public TableFunctionNode (
@@ -61,17 +67,21 @@ public TableFunctionNode(
6167 Optional <PlanNode > statsEquivalentPlanNode ,
6268 String name ,
6369 Map <String , Argument > arguments ,
64- List <VariableReferenceExpression > outputVariables ,
70+ List <VariableReferenceExpression > properOutputs ,
6571 List <PlanNode > sources ,
6672 List <TableArgumentProperties > tableArgumentProperties ,
73+ List <List <String >> copartitioningLists ,
6774 TableFunctionHandle handle )
6875 {
6976 super (sourceLocation , id , statsEquivalentPlanNode );
7077 this .name = requireNonNull (name , "name is null" );
71- this .arguments = requireNonNull (arguments , "arguments is null" );
72- this .outputVariables = requireNonNull (outputVariables , "outputVariables is null" );
73- this .sources = requireNonNull (sources , "sources is null" );
74- this .tableArgumentProperties = requireNonNull (tableArgumentProperties , "tableArgumentProperties is null" );
78+ this .arguments = ImmutableMap .copyOf (arguments );
79+ this .properOutputs = ImmutableList .copyOf (properOutputs );
80+ this .sources = ImmutableList .copyOf (sources );
81+ this .tableArgumentProperties = ImmutableList .copyOf (tableArgumentProperties );
82+ this .copartitioningLists = requireNonNull (copartitioningLists , "copartitioningLists is null" ).stream ()
83+ .map (ImmutableList ::copyOf )
84+ .collect (toImmutableList ());
7585 this .handle = requireNonNull (handle , "handle is null" );
7686 }
7787
@@ -87,10 +97,25 @@ public Map<String, Argument> getArguments()
8797 return arguments ;
8898 }
8999
90- @ JsonProperty
100+ @ Override
91101 public List <VariableReferenceExpression > getOutputVariables ()
92102 {
93- return outputVariables ;
103+ ImmutableList .Builder <VariableReferenceExpression > variables = ImmutableList .builder ();
104+ variables .addAll (properOutputs );
105+
106+ tableArgumentProperties .stream ()
107+ .map (TableArgumentProperties ::getPassThroughSpecification )
108+ .map (PassThroughSpecification ::getColumns )
109+ .flatMap (Collection ::stream )
110+ .map (PassThroughColumn ::getVariable )
111+ .forEach (variables ::add );
112+
113+ return variables .build ();
114+ }
115+
116+ public List <VariableReferenceExpression > getProperOutputs ()
117+ {
118+ return properOutputs ;
94119 }
95120
96121 @ JsonProperty
@@ -99,6 +124,12 @@ public List<TableArgumentProperties> getTableArgumentProperties()
99124 return tableArgumentProperties ;
100125 }
101126
127+ @ JsonProperty
128+ public List <List <String >> getCopartitioningLists ()
129+ {
130+ return copartitioningLists ;
131+ }
132+
102133 @ JsonProperty
103134 public TableFunctionHandle getHandle ()
104135 {
@@ -122,35 +153,47 @@ public <R, C> R accept(InternalPlanVisitor<R, C> visitor, C context)
122153 public PlanNode replaceChildren (List <PlanNode > newSources )
123154 {
124155 checkArgument (sources .size () == newSources .size (), "wrong number of new children" );
125- return new TableFunctionNode (getId (), name , arguments , outputVariables , newSources , tableArgumentProperties , handle );
156+ return new TableFunctionNode (getId (), name , arguments , properOutputs , newSources , tableArgumentProperties , copartitioningLists , handle );
126157 }
127158
128159 @ Override
129160 public PlanNode assignStatsEquivalentPlanNode (Optional <PlanNode > statsEquivalentPlanNode )
130161 {
131- return new TableFunctionNode (getSourceLocation (), getId (), statsEquivalentPlanNode , name , arguments , outputVariables , sources , tableArgumentProperties , handle );
162+ return new TableFunctionNode (getSourceLocation (), getId (), statsEquivalentPlanNode , name , arguments , properOutputs , sources , tableArgumentProperties , copartitioningLists , handle );
132163 }
133164
134165 public static class TableArgumentProperties
135166 {
167+ private final String argumentName ;
136168 private final boolean rowSemantics ;
137169 private final boolean pruneWhenEmpty ;
138- private final boolean passThroughColumns ;
170+ private final PassThroughSpecification passThroughSpecification ;
171+ private final List <VariableReferenceExpression > requiredColumns ;
139172 private final Optional <DataOrganizationSpecification > specification ;
140173
141174 @ JsonCreator
142175 public TableArgumentProperties (
176+ @ JsonProperty ("argumentName" ) String argumentName ,
143177 @ JsonProperty ("rowSemantics" ) boolean rowSemantics ,
144178 @ JsonProperty ("pruneWhenEmpty" ) boolean pruneWhenEmpty ,
145- @ JsonProperty ("passThroughColumns" ) boolean passThroughColumns ,
179+ @ JsonProperty ("passThroughSpecification" ) PassThroughSpecification passThroughSpecification ,
180+ @ JsonProperty ("requiredColumns" ) List <VariableReferenceExpression > requiredColumns ,
146181 @ JsonProperty ("specification" ) Optional <DataOrganizationSpecification > specification )
147182 {
183+ this .argumentName = requireNonNull (argumentName , "argumentName is null" );
148184 this .rowSemantics = rowSemantics ;
149185 this .pruneWhenEmpty = pruneWhenEmpty ;
150- this .passThroughColumns = passThroughColumns ;
186+ this .passThroughSpecification = requireNonNull (passThroughSpecification , "passThroughSpecification is null" );
187+ this .requiredColumns = ImmutableList .copyOf (requiredColumns );
151188 this .specification = requireNonNull (specification , "specification is null" );
152189 }
153190
191+ @ JsonProperty
192+ public String getArgumentName ()
193+ {
194+ return argumentName ;
195+ }
196+
154197 @ JsonProperty
155198 public boolean isRowSemantics ()
156199 {
@@ -164,15 +207,83 @@ public boolean isPruneWhenEmpty()
164207 }
165208
166209 @ JsonProperty
167- public boolean isPassThroughColumns ()
210+ public PassThroughSpecification getPassThroughSpecification ()
211+ {
212+ return passThroughSpecification ;
213+ }
214+
215+ @ JsonProperty
216+ public List <VariableReferenceExpression > getRequiredColumns ()
168217 {
169- return passThroughColumns ;
218+ return requiredColumns ;
170219 }
171220
172221 @ JsonProperty
173- public Optional <DataOrganizationSpecification > specification ()
222+ public Optional <DataOrganizationSpecification > getSpecification ()
174223 {
175224 return specification ;
176225 }
177226 }
227+
228+ /**
229+ * Specifies how columns from source tables are passed through to the output of a table function.
230+ * This class manages both explicitly declared pass-through columns and partitioning columns
231+ * that must be preserved in the output.
232+ */
233+ public static class PassThroughSpecification
234+ {
235+ private final boolean declaredAsPassThrough ;
236+ private final List <PassThroughColumn > columns ;
237+
238+ @ JsonCreator
239+ public PassThroughSpecification (
240+ @ JsonProperty ("declaredAsPassThrough" ) boolean declaredAsPassThrough ,
241+ @ JsonProperty ("columns" ) List <PassThroughColumn > columns )
242+ {
243+ this .declaredAsPassThrough = declaredAsPassThrough ;
244+ this .columns = ImmutableList .copyOf (requireNonNull (columns , "columns is null" ));
245+ checkArgument (
246+ declaredAsPassThrough || this .columns .stream ().allMatch (PassThroughColumn ::isPartitioningColumn ),
247+ "non-partitioning pass-through column for non-pass-through source of a table function" );
248+ }
249+
250+ @ JsonProperty
251+ public boolean isDeclaredAsPassThrough ()
252+ {
253+ return declaredAsPassThrough ;
254+ }
255+
256+ @ JsonProperty
257+ public List <PassThroughColumn > getColumns ()
258+ {
259+ return columns ;
260+ }
261+ }
262+
263+ public static class PassThroughColumn
264+ {
265+ private final VariableReferenceExpression variable ;
266+ private final boolean isPartitioningColumn ;
267+
268+ @ JsonCreator
269+ public PassThroughColumn (
270+ @ JsonProperty ("variable" ) VariableReferenceExpression variable ,
271+ @ JsonProperty ("partitioningColumn" ) boolean isPartitioningColumn )
272+ {
273+ this .variable = requireNonNull (variable , "variable is null" );
274+ this .isPartitioningColumn = isPartitioningColumn ;
275+ }
276+
277+ @ JsonProperty
278+ public VariableReferenceExpression getVariable ()
279+ {
280+ return variable ;
281+ }
282+
283+ @ JsonProperty
284+ public boolean isPartitioningColumn ()
285+ {
286+ return isPartitioningColumn ;
287+ }
288+ }
178289}
0 commit comments