14
14
package io .trino .plugin .deltalake ;
15
15
16
16
import com .fasterxml .jackson .annotation .JsonCreator ;
17
+ import com .fasterxml .jackson .annotation .JsonIgnore ;
17
18
import com .fasterxml .jackson .annotation .JsonProperty ;
18
19
import io .trino .plugin .hive .HiveColumnHandle ;
19
20
import io .trino .spi .connector .ColumnHandle ;
23
24
import java .util .Optional ;
24
25
import java .util .OptionalInt ;
25
26
27
+ import static com .google .common .base .Preconditions .checkArgument ;
28
+ import static com .google .common .base .Preconditions .checkState ;
26
29
import static io .airlift .slice .SizeOf .estimatedSizeOf ;
27
30
import static io .airlift .slice .SizeOf .instanceSize ;
28
31
import static io .airlift .slice .SizeOf .sizeOf ;
29
32
import static io .trino .plugin .deltalake .DeltaHiveTypeTranslator .toHiveType ;
33
+ import static io .trino .plugin .deltalake .DeltaLakeColumnType .REGULAR ;
30
34
import static io .trino .plugin .deltalake .DeltaLakeColumnType .SYNTHESIZED ;
31
35
import static io .trino .spi .type .BigintType .BIGINT ;
32
36
import static io .trino .spi .type .RowType .field ;
@@ -56,64 +60,68 @@ public class DeltaLakeColumnHandle
56
60
public static final String FILE_MODIFIED_TIME_COLUMN_NAME = "$file_modified_time" ;
57
61
public static final Type FILE_MODIFIED_TIME_TYPE = TIMESTAMP_TZ_MILLIS ;
58
62
59
- private final String name ;
60
- private final Type type ;
61
- private final OptionalInt fieldId ;
63
+ private final String baseColumnName ;
64
+ private final Type baseType ;
65
+ private final OptionalInt baseFieldId ;
62
66
// Hold field names in Parquet files
63
67
// The value is same as 'name' when the column mapping mode is none
64
68
// The value is same as 'delta.columnMapping.physicalName' when the column mapping mode is id or name. e.g. col-6707cc9e-f3aa-4e6b-b8ef-1b03d3475680
65
- private final String physicalName ;
69
+ private final String basePhysicalColumnName ;
66
70
// Hold type in Parquet files
67
71
// The value is same as 'type' when the column mapping mode is none
68
72
// The value is same as 'delta.columnMapping.physicalName' when the column mapping mode is id or name. e.g. row(col-5924c8b3-04cf-4146-abb5-2c229e7ff708 integer)
69
- private final Type physicalType ;
73
+ private final Type basePhysicalType ;
70
74
private final DeltaLakeColumnType columnType ;
75
+ private final Optional <DeltaLakeColumnProjectionInfo > projectionInfo ;
71
76
72
77
@ JsonCreator
73
78
public DeltaLakeColumnHandle (
74
- @ JsonProperty ("name" ) String name ,
75
- @ JsonProperty ("type" ) Type type ,
76
- @ JsonProperty ("fieldId" ) OptionalInt fieldId ,
77
- @ JsonProperty ("physicalName" ) String physicalName ,
78
- @ JsonProperty ("physicalType" ) Type physicalType ,
79
- @ JsonProperty ("columnType" ) DeltaLakeColumnType columnType )
80
- {
81
- this .name = requireNonNull (name , "name is null" );
82
- this .type = requireNonNull (type , "type is null" );
83
- this .fieldId = requireNonNull (fieldId , "fieldId is null" );
84
- this .physicalName = requireNonNull (physicalName , "physicalName is null" );
85
- this .physicalType = requireNonNull (physicalType , "physicalType is null" );
79
+ @ JsonProperty ("baseColumnName" ) String baseColumnName ,
80
+ @ JsonProperty ("baseType" ) Type baseType ,
81
+ @ JsonProperty ("baseFieldId" ) OptionalInt baseFieldId ,
82
+ @ JsonProperty ("basePhysicalColumnName" ) String basePhysicalColumnName ,
83
+ @ JsonProperty ("basePhysicalType" ) Type basePhysicalType ,
84
+ @ JsonProperty ("columnType" ) DeltaLakeColumnType columnType ,
85
+ @ JsonProperty ("projectionInfo" ) Optional <DeltaLakeColumnProjectionInfo > projectionInfo )
86
+ {
87
+ this .baseColumnName = requireNonNull (baseColumnName , "baseColumnName is null" );
88
+ this .baseType = requireNonNull (baseType , "baseType is null" );
89
+ this .baseFieldId = requireNonNull (baseFieldId , "baseFieldId is null" );
90
+ this .basePhysicalColumnName = requireNonNull (basePhysicalColumnName , "basePhysicalColumnName is null" );
91
+ this .basePhysicalType = requireNonNull (basePhysicalType , "basePhysicalType is null" );
86
92
this .columnType = requireNonNull (columnType , "columnType is null" );
93
+ checkArgument (projectionInfo .isEmpty () || columnType == REGULAR , "Projection info present for column type: %s" , columnType );
94
+ this .projectionInfo = projectionInfo ;
87
95
}
88
96
89
97
@ JsonProperty
90
- public String getName ()
98
+ public String getBaseColumnName ()
91
99
{
92
- return name ;
100
+ return baseColumnName ;
93
101
}
94
102
95
103
@ JsonProperty
96
- public Type getType ()
104
+ public Type getBaseType ()
97
105
{
98
- return type ;
106
+ return baseType ;
99
107
}
100
108
101
109
@ JsonProperty
102
- public OptionalInt getFieldId ()
110
+ public OptionalInt getBaseFieldId ()
103
111
{
104
- return fieldId ;
112
+ return baseFieldId ;
105
113
}
106
114
107
115
@ JsonProperty
108
- public String getPhysicalName ()
116
+ public String getBasePhysicalColumnName ()
109
117
{
110
- return physicalName ;
118
+ return basePhysicalColumnName ;
111
119
}
112
120
113
121
@ JsonProperty
114
- public Type getPhysicalType ()
122
+ public Type getBasePhysicalType ()
115
123
{
116
- return physicalType ;
124
+ return basePhysicalType ;
117
125
}
118
126
119
127
@ JsonProperty
@@ -122,6 +130,12 @@ public DeltaLakeColumnType getColumnType()
122
130
return columnType ;
123
131
}
124
132
133
+ @ JsonProperty
134
+ public Optional <DeltaLakeColumnProjectionInfo > getProjectionInfo ()
135
+ {
136
+ return projectionInfo ;
137
+ }
138
+
125
139
@ Override
126
140
public boolean equals (Object obj )
127
141
{
@@ -132,64 +146,88 @@ public boolean equals(Object obj)
132
146
return false ;
133
147
}
134
148
DeltaLakeColumnHandle other = (DeltaLakeColumnHandle ) obj ;
135
- return Objects .equals (this .name , other .name ) &&
136
- Objects .equals (this .type , other .type ) &&
137
- Objects .equals (this .fieldId , other .fieldId ) &&
138
- Objects .equals (this .physicalName , other .physicalName ) &&
139
- Objects .equals (this .physicalType , other .physicalType ) &&
140
- this .columnType == other .columnType ;
149
+ return Objects .equals (this .baseColumnName , other .baseColumnName ) &&
150
+ Objects .equals (this .baseType , other .baseType ) &&
151
+ Objects .equals (this .baseFieldId , other .baseFieldId ) &&
152
+ Objects .equals (this .basePhysicalColumnName , other .basePhysicalColumnName ) &&
153
+ Objects .equals (this .basePhysicalType , other .basePhysicalType ) &&
154
+ this .columnType == other .columnType &&
155
+ Objects .equals (this .projectionInfo , other .projectionInfo );
156
+ }
157
+
158
+ @ JsonIgnore
159
+ public String getColumnName ()
160
+ {
161
+ checkState (isBaseColumn (), "Unexpected dereference: %s" , this );
162
+ return baseColumnName ;
163
+ }
164
+
165
+ @ JsonIgnore
166
+ public String getQualifiedPhysicalName ()
167
+ {
168
+ return projectionInfo .map (projectionInfo -> basePhysicalColumnName + "#" + projectionInfo .getPartialName ())
169
+ .orElse (basePhysicalColumnName );
141
170
}
142
171
143
172
public long getRetainedSizeInBytes ()
144
173
{
145
174
// type is not accounted for as the instances are cached (by TypeRegistry) and shared
146
175
return INSTANCE_SIZE
147
- + estimatedSizeOf (name )
148
- + sizeOf (fieldId )
149
- + estimatedSizeOf (physicalName );
176
+ + estimatedSizeOf (baseColumnName )
177
+ + sizeOf (baseFieldId )
178
+ + estimatedSizeOf (basePhysicalColumnName )
179
+ + projectionInfo .map (DeltaLakeColumnProjectionInfo ::getRetainedSizeInBytes ).orElse (0L );
180
+ }
181
+
182
+ @ JsonIgnore
183
+ public boolean isBaseColumn ()
184
+ {
185
+ return projectionInfo .isEmpty ();
150
186
}
151
187
152
188
@ Override
153
189
public int hashCode ()
154
190
{
155
- return Objects .hash (name , type , fieldId , physicalName , physicalType , columnType );
191
+ return Objects .hash (baseColumnName , baseType , baseFieldId , basePhysicalColumnName , basePhysicalType , columnType , projectionInfo );
156
192
}
157
193
158
194
@ Override
159
195
public String toString ()
160
196
{
161
- return name + ":" + type .getDisplayName () + ":" + columnType ;
197
+ return getQualifiedPhysicalName () +
198
+ ":" + projectionInfo .map (DeltaLakeColumnProjectionInfo ::getType ).orElse (baseType ).getDisplayName () +
199
+ ":" + columnType ;
162
200
}
163
201
164
202
public HiveColumnHandle toHiveColumnHandle ()
165
203
{
166
204
return new HiveColumnHandle (
167
- physicalName , // this name is used for accessing Parquet files, so it should be physical name
205
+ basePhysicalColumnName , // this name is used for accessing Parquet files, so it should be physical name
168
206
0 , // hiveColumnIndex; we provide fake value because we always find columns by name
169
- toHiveType (physicalType ),
170
- physicalType ,
171
- Optional . empty ( ),
207
+ toHiveType (basePhysicalType ),
208
+ basePhysicalType ,
209
+ projectionInfo . map ( DeltaLakeColumnProjectionInfo :: toHiveColumnProjectionInfo ),
172
210
columnType .toHiveColumnType (),
173
211
Optional .empty ());
174
212
}
175
213
176
214
public static DeltaLakeColumnHandle pathColumnHandle ()
177
215
{
178
- return new DeltaLakeColumnHandle (PATH_COLUMN_NAME , PATH_TYPE , OptionalInt .empty (), PATH_COLUMN_NAME , PATH_TYPE , SYNTHESIZED );
216
+ return new DeltaLakeColumnHandle (PATH_COLUMN_NAME , PATH_TYPE , OptionalInt .empty (), PATH_COLUMN_NAME , PATH_TYPE , SYNTHESIZED , Optional . empty () );
179
217
}
180
218
181
219
public static DeltaLakeColumnHandle fileSizeColumnHandle ()
182
220
{
183
- return new DeltaLakeColumnHandle (FILE_SIZE_COLUMN_NAME , FILE_SIZE_TYPE , OptionalInt .empty (), FILE_SIZE_COLUMN_NAME , FILE_SIZE_TYPE , SYNTHESIZED );
221
+ return new DeltaLakeColumnHandle (FILE_SIZE_COLUMN_NAME , FILE_SIZE_TYPE , OptionalInt .empty (), FILE_SIZE_COLUMN_NAME , FILE_SIZE_TYPE , SYNTHESIZED , Optional . empty () );
184
222
}
185
223
186
224
public static DeltaLakeColumnHandle fileModifiedTimeColumnHandle ()
187
225
{
188
- return new DeltaLakeColumnHandle (FILE_MODIFIED_TIME_COLUMN_NAME , FILE_MODIFIED_TIME_TYPE , OptionalInt .empty (), FILE_MODIFIED_TIME_COLUMN_NAME , FILE_MODIFIED_TIME_TYPE , SYNTHESIZED );
226
+ return new DeltaLakeColumnHandle (FILE_MODIFIED_TIME_COLUMN_NAME , FILE_MODIFIED_TIME_TYPE , OptionalInt .empty (), FILE_MODIFIED_TIME_COLUMN_NAME , FILE_MODIFIED_TIME_TYPE , SYNTHESIZED , Optional . empty () );
189
227
}
190
228
191
229
public static DeltaLakeColumnHandle mergeRowIdColumnHandle ()
192
230
{
193
- return new DeltaLakeColumnHandle (ROW_ID_COLUMN_NAME , MERGE_ROW_ID_TYPE , OptionalInt .empty (), ROW_ID_COLUMN_NAME , MERGE_ROW_ID_TYPE , SYNTHESIZED );
231
+ return new DeltaLakeColumnHandle (ROW_ID_COLUMN_NAME , MERGE_ROW_ID_TYPE , OptionalInt .empty (), ROW_ID_COLUMN_NAME , MERGE_ROW_ID_TYPE , SYNTHESIZED , Optional . empty () );
194
232
}
195
233
}
0 commit comments