@@ -28,7 +28,7 @@ use delta_kernel::schema::{ArrayType, DataType, MapType, PrimitiveType, StructTy
28
28
/// that element's (already-visited) children.
29
29
/// 4. The [`visit_schema`] method returns the id of the list of top-level columns
30
30
// WARNING: the visitor MUST NOT retain internal references to the string slices passed to visitor methods
31
- // TODO: struct nullability and field metadata
31
+ // TODO: struct field metadata
32
32
#[ repr( C ) ]
33
33
pub struct EngineSchemaVisitor {
34
34
/// opaque state pointer
@@ -43,6 +43,7 @@ pub struct EngineSchemaVisitor {
43
43
data : * mut c_void ,
44
44
sibling_list_id : usize ,
45
45
name : KernelStringSlice ,
46
+ is_nullable : bool ,
46
47
child_list_id : usize ,
47
48
) ,
48
49
@@ -52,7 +53,7 @@ pub struct EngineSchemaVisitor {
52
53
data : * mut c_void ,
53
54
sibling_list_id : usize ,
54
55
name : KernelStringSlice ,
55
- contains_null : bool , // if this array can contain null values
56
+ is_nullable : bool ,
56
57
child_list_id : usize ,
57
58
) ,
58
59
@@ -63,7 +64,7 @@ pub struct EngineSchemaVisitor {
63
64
data : * mut c_void ,
64
65
sibling_list_id : usize ,
65
66
name : KernelStringSlice ,
66
- value_contains_null : bool , // if this map can contain null values
67
+ is_nullable : bool ,
67
68
child_list_id : usize ,
68
69
) ,
69
70
@@ -72,57 +73,106 @@ pub struct EngineSchemaVisitor {
72
73
data : * mut c_void ,
73
74
sibling_list_id : usize ,
74
75
name : KernelStringSlice ,
76
+ is_nullable : bool ,
75
77
precision : u8 ,
76
78
scale : u8 ,
77
79
) ,
78
80
79
81
/// Visit a `string` belonging to the list identified by `sibling_list_id`.
80
- pub visit_string :
81
- extern "C" fn ( data : * mut c_void , sibling_list_id : usize , name : KernelStringSlice ) ,
82
+ pub visit_string : extern "C" fn (
83
+ data : * mut c_void ,
84
+ sibling_list_id : usize ,
85
+ name : KernelStringSlice ,
86
+ is_nullable : bool ,
87
+ ) ,
82
88
83
89
/// Visit a `long` belonging to the list identified by `sibling_list_id`.
84
- pub visit_long :
85
- extern "C" fn ( data : * mut c_void , sibling_list_id : usize , name : KernelStringSlice ) ,
90
+ pub visit_long : extern "C" fn (
91
+ data : * mut c_void ,
92
+ sibling_list_id : usize ,
93
+ name : KernelStringSlice ,
94
+ is_nullable : bool ,
95
+ ) ,
86
96
87
97
/// Visit an `integer` belonging to the list identified by `sibling_list_id`.
88
- pub visit_integer :
89
- extern "C" fn ( data : * mut c_void , sibling_list_id : usize , name : KernelStringSlice ) ,
98
+ pub visit_integer : extern "C" fn (
99
+ data : * mut c_void ,
100
+ sibling_list_id : usize ,
101
+ name : KernelStringSlice ,
102
+ is_nullable : bool ,
103
+ ) ,
90
104
91
105
/// Visit a `short` belonging to the list identified by `sibling_list_id`.
92
- pub visit_short :
93
- extern "C" fn ( data : * mut c_void , sibling_list_id : usize , name : KernelStringSlice ) ,
106
+ pub visit_short : extern "C" fn (
107
+ data : * mut c_void ,
108
+ sibling_list_id : usize ,
109
+ name : KernelStringSlice ,
110
+ is_nullable : bool ,
111
+ ) ,
94
112
95
113
/// Visit a `byte` belonging to the list identified by `sibling_list_id`.
96
- pub visit_byte :
97
- extern "C" fn ( data : * mut c_void , sibling_list_id : usize , name : KernelStringSlice ) ,
114
+ pub visit_byte : extern "C" fn (
115
+ data : * mut c_void ,
116
+ sibling_list_id : usize ,
117
+ name : KernelStringSlice ,
118
+ is_nullable : bool ,
119
+ ) ,
98
120
99
121
/// Visit a `float` belonging to the list identified by `sibling_list_id`.
100
- pub visit_float :
101
- extern "C" fn ( data : * mut c_void , sibling_list_id : usize , name : KernelStringSlice ) ,
122
+ pub visit_float : extern "C" fn (
123
+ data : * mut c_void ,
124
+ sibling_list_id : usize ,
125
+ name : KernelStringSlice ,
126
+ is_nullable : bool ,
127
+ ) ,
102
128
103
129
/// Visit a `double` belonging to the list identified by `sibling_list_id`.
104
- pub visit_double :
105
- extern "C" fn ( data : * mut c_void , sibling_list_id : usize , name : KernelStringSlice ) ,
130
+ pub visit_double : extern "C" fn (
131
+ data : * mut c_void ,
132
+ sibling_list_id : usize ,
133
+ name : KernelStringSlice ,
134
+ is_nullable : bool ,
135
+ ) ,
106
136
107
137
/// Visit a `boolean` belonging to the list identified by `sibling_list_id`.
108
- pub visit_boolean :
109
- extern "C" fn ( data : * mut c_void , sibling_list_id : usize , name : KernelStringSlice ) ,
138
+ pub visit_boolean : extern "C" fn (
139
+ data : * mut c_void ,
140
+ sibling_list_id : usize ,
141
+ name : KernelStringSlice ,
142
+ is_nullable : bool ,
143
+ ) ,
110
144
111
145
/// Visit `binary` belonging to the list identified by `sibling_list_id`.
112
- pub visit_binary :
113
- extern "C" fn ( data : * mut c_void , sibling_list_id : usize , name : KernelStringSlice ) ,
146
+ pub visit_binary : extern "C" fn (
147
+ data : * mut c_void ,
148
+ sibling_list_id : usize ,
149
+ name : KernelStringSlice ,
150
+ is_nullable : bool ,
151
+ ) ,
114
152
115
153
/// Visit a `date` belonging to the list identified by `sibling_list_id`.
116
- pub visit_date :
117
- extern "C" fn ( data : * mut c_void , sibling_list_id : usize , name : KernelStringSlice ) ,
154
+ pub visit_date : extern "C" fn (
155
+ data : * mut c_void ,
156
+ sibling_list_id : usize ,
157
+ name : KernelStringSlice ,
158
+ is_nullable : bool ,
159
+ ) ,
118
160
119
161
/// Visit a `timestamp` belonging to the list identified by `sibling_list_id`.
120
- pub visit_timestamp :
121
- extern "C" fn ( data : * mut c_void , sibling_list_id : usize , name : KernelStringSlice ) ,
162
+ pub visit_timestamp : extern "C" fn (
163
+ data : * mut c_void ,
164
+ sibling_list_id : usize ,
165
+ name : KernelStringSlice ,
166
+ is_nullable : bool ,
167
+ ) ,
122
168
123
169
/// Visit a `timestamp` with no timezone belonging to the list identified by `sibling_list_id`.
124
- pub visit_timestamp_ntz :
125
- extern "C" fn ( data : * mut c_void , sibling_list_id : usize , name : KernelStringSlice ) ,
170
+ pub visit_timestamp_ntz : extern "C" fn (
171
+ data : * mut c_void ,
172
+ sibling_list_id : usize ,
173
+ name : KernelStringSlice ,
174
+ is_nullable : bool ,
175
+ ) ,
126
176
}
127
177
128
178
/// Visit the schema of the passed `SnapshotHandle`, using the provided `visitor`. See the
@@ -143,28 +193,55 @@ pub unsafe extern "C" fn visit_schema(
143
193
fn visit_struct_fields ( visitor : & EngineSchemaVisitor , s : & StructType ) -> usize {
144
194
let child_list_id = ( visitor. make_field_list ) ( visitor. data , s. fields . len ( ) ) ;
145
195
for field in s. fields ( ) {
146
- visit_schema_item ( field. data_type ( ) , field. name ( ) , visitor, child_list_id) ;
196
+ visit_schema_item (
197
+ field. name ( ) ,
198
+ field. data_type ( ) ,
199
+ field. is_nullable ( ) ,
200
+ visitor,
201
+ child_list_id,
202
+ ) ;
147
203
}
148
204
child_list_id
149
205
}
150
206
151
- fn visit_array_item ( visitor : & EngineSchemaVisitor , at : & ArrayType ) -> usize {
207
+ fn visit_array_item (
208
+ visitor : & EngineSchemaVisitor ,
209
+ at : & ArrayType ,
210
+ contains_null : bool ,
211
+ ) -> usize {
152
212
let child_list_id = ( visitor. make_field_list ) ( visitor. data , 1 ) ;
153
- visit_schema_item ( & at. element_type , "array_element" , visitor, child_list_id) ;
213
+ visit_schema_item (
214
+ "array_element" ,
215
+ & at. element_type ,
216
+ contains_null,
217
+ visitor,
218
+ child_list_id,
219
+ ) ;
154
220
child_list_id
155
221
}
156
222
157
- fn visit_map_types ( visitor : & EngineSchemaVisitor , mt : & MapType ) -> usize {
223
+ fn visit_map_types (
224
+ visitor : & EngineSchemaVisitor ,
225
+ mt : & MapType ,
226
+ value_contains_null : bool ,
227
+ ) -> usize {
158
228
let child_list_id = ( visitor. make_field_list ) ( visitor. data , 2 ) ;
159
- visit_schema_item ( & mt. key_type , "map_key" , visitor, child_list_id) ;
160
- visit_schema_item ( & mt. value_type , "map_value" , visitor, child_list_id) ;
229
+ visit_schema_item ( "map_key" , & mt. key_type , false , visitor, child_list_id) ;
230
+ visit_schema_item (
231
+ "map_value" ,
232
+ & mt. value_type ,
233
+ value_contains_null,
234
+ visitor,
235
+ child_list_id,
236
+ ) ;
161
237
child_list_id
162
238
}
163
239
164
240
// Visit a struct field (recursively) and add the result to the list of siblings.
165
241
fn visit_schema_item (
166
- data_type : & DataType ,
167
242
name : & str ,
243
+ data_type : & DataType ,
244
+ is_nullable : bool ,
168
245
visitor : & EngineSchemaVisitor ,
169
246
sibling_list_id : usize ,
170
247
) {
@@ -173,7 +250,8 @@ pub unsafe extern "C" fn visit_schema(
173
250
( visitor. $visitor_fn) (
174
251
visitor. data,
175
252
sibling_list_id,
176
- kernel_string_slice!( name)
253
+ kernel_string_slice!( name) ,
254
+ is_nullable
177
255
$( , $extra_args) *
178
256
)
179
257
} ;
@@ -183,12 +261,11 @@ pub unsafe extern "C" fn visit_schema(
183
261
DataType :: Map ( mt) => {
184
262
call ! (
185
263
visit_map,
186
- mt. value_contains_null,
187
- visit_map_types( visitor, mt)
264
+ visit_map_types( visitor, mt, mt. value_contains_null)
188
265
)
189
266
}
190
267
DataType :: Array ( at) => {
191
- call ! ( visit_array, at . contains_null , visit_array_item( visitor, at) )
268
+ call ! ( visit_array, visit_array_item( visitor, at, at . contains_null ) )
192
269
}
193
270
DataType :: Primitive ( PrimitiveType :: Decimal ( precision, scale) ) => {
194
271
call ! ( visit_decimal, * precision, * scale)
0 commit comments