@@ -53,22 +53,50 @@ pub struct NativeQueryInfo {
53
53
#[ derive( Debug , Clone , PartialEq , Eq ) ]
54
54
pub struct RootAndCurrentTables {
55
55
/// The root (top-most) table in the query.
56
- pub root_table : TableNameAndReference ,
56
+ pub root_table : TableSourceAndReference ,
57
57
/// The current table we are processing.
58
- pub current_table : TableNameAndReference ,
58
+ pub current_table : TableSourceAndReference ,
59
59
}
60
60
61
61
/// For a table in the query, We'd like to track what is its reference in the query
62
- /// (the name we can use to address them, an alias we generate), and what is their name in the
62
+ /// (the name we can use to address them, an alias we generate), and what is their source in the
63
63
/// metadata (so we can get their information such as which columns are available for that table).
64
64
#[ derive( Debug , Clone , PartialEq , Eq ) ]
65
- pub struct TableNameAndReference {
65
+ pub struct TableSourceAndReference {
66
66
/// Table name for column lookup
67
- pub name : models :: CollectionName ,
67
+ pub source : TableSource ,
68
68
/// Table alias to query from
69
69
pub reference : sql:: ast:: TableReference ,
70
70
}
71
71
72
+ /// How to find the relevant information about a table.
73
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
74
+ pub enum TableSource {
75
+ /// Using the collection name.
76
+ Collection ( models:: CollectionName ) ,
77
+ /// Using the nested field path.
78
+ NestedField {
79
+ type_name : models:: TypeName ,
80
+ // These are used to create a nice table alias.
81
+ collection_name : models:: CollectionName ,
82
+ field_path : FieldPath ,
83
+ } ,
84
+ }
85
+
86
+ impl TableSource {
87
+ /// Generate a nice name that can be used to give a table alias for this source.
88
+ pub fn name_for_alias ( & self ) -> String {
89
+ match self {
90
+ TableSource :: Collection ( collection_name) => collection_name. to_string ( ) ,
91
+ TableSource :: NestedField {
92
+ collection_name,
93
+ field_path,
94
+ type_name : _,
95
+ } => format ! ( "{collection_name}.{}" , field_path. 0 . join( "." ) ) ,
96
+ }
97
+ }
98
+ }
99
+
72
100
#[ derive( Debug ) ]
73
101
/// Information about columns
74
102
pub struct ColumnInfo {
@@ -108,11 +136,11 @@ pub enum CompositeTypeInfo<'env> {
108
136
/// Metadata information about any object that can have fields
109
137
pub enum FieldsInfo < ' env > {
110
138
Table {
111
- name : & ' env models:: CollectionName ,
139
+ name : models:: CollectionName ,
112
140
info : & ' env metadata:: TableInfo ,
113
141
} ,
114
142
NativeQuery {
115
- name : & ' env models:: CollectionName ,
143
+ name : models:: CollectionName ,
116
144
info : & ' env metadata:: NativeQueryInfo ,
117
145
} ,
118
146
CompositeType {
@@ -124,7 +152,10 @@ pub enum FieldsInfo<'env> {
124
152
impl < ' a > From < & ' a CompositeTypeInfo < ' a > > for FieldsInfo < ' a > {
125
153
fn from ( value : & ' a CompositeTypeInfo < ' a > ) -> Self {
126
154
match value {
127
- CompositeTypeInfo :: Table { name, info } => FieldsInfo :: Table { name, info } ,
155
+ CompositeTypeInfo :: Table { name, info } => FieldsInfo :: Table {
156
+ name : name. clone ( ) ,
157
+ info,
158
+ } ,
128
159
CompositeTypeInfo :: CompositeType { name, info } => FieldsInfo :: CompositeType {
129
160
name : name. clone ( ) ,
130
161
info,
@@ -136,8 +167,14 @@ impl<'a> From<&'a CompositeTypeInfo<'a>> for FieldsInfo<'a> {
136
167
impl < ' a > From < & ' a CollectionInfo < ' a > > for FieldsInfo < ' a > {
137
168
fn from ( value : & ' a CollectionInfo < ' a > ) -> Self {
138
169
match value {
139
- CollectionInfo :: Table { name, info } => FieldsInfo :: Table { name, info } ,
140
- CollectionInfo :: NativeQuery { name, info } => FieldsInfo :: NativeQuery { name, info } ,
170
+ CollectionInfo :: Table { name, info } => FieldsInfo :: Table {
171
+ name : ( * name) . clone ( ) ,
172
+ info,
173
+ } ,
174
+ CollectionInfo :: NativeQuery { name, info } => FieldsInfo :: NativeQuery {
175
+ name : ( * name) . clone ( ) ,
176
+ info,
177
+ } ,
141
178
}
142
179
}
143
180
}
@@ -182,55 +219,63 @@ impl<'request> Env<'request> {
182
219
/// Queries, and Composite Types.
183
220
///
184
221
/// This is used to translate field selection, where any of these may occur.
185
- pub fn lookup_fields_info (
186
- & self ,
187
- type_name : & ' request models:: CollectionName ,
188
- ) -> Result < FieldsInfo < ' request > , Error > {
189
- // Lookup the fields of a type name in a specific order:
190
- // tables, then composite types, then native queries.
191
- let info = self
192
- . metadata
193
- . tables
194
- . 0
195
- . get ( type_name)
196
- . map ( |t| FieldsInfo :: Table {
197
- name : type_name,
198
- info : t,
199
- } )
200
- . or_else ( || {
201
- self . metadata
222
+ pub fn lookup_fields_info ( & self , source : & TableSource ) -> Result < FieldsInfo < ' request > , Error > {
223
+ match source {
224
+ TableSource :: NestedField {
225
+ collection_name : _,
226
+ type_name,
227
+ field_path : _,
228
+ } => {
229
+ let info = self
230
+ . metadata
202
231
. composite_types
203
232
. 0
204
233
. get ( type_name. as_str ( ) )
205
234
. map ( |t| FieldsInfo :: CompositeType {
206
235
name : t. type_name . clone ( ) . into ( ) ,
207
236
info : t,
208
- } )
209
- } )
210
- . or_else ( || {
211
- self . metadata
212
- . native_operations
213
- . queries
237
+ } ) ;
238
+
239
+ info. ok_or ( Error :: ScalarTypeNotFound ( type_name. as_str ( ) . into ( ) ) )
240
+ }
241
+ TableSource :: Collection ( collection_name) => {
242
+ // Lookup the fields of a type name in a specific order:
243
+ // tables, then composite types, then native queries.
244
+ let info = self
245
+ . metadata
246
+ . tables
214
247
. 0
215
- . get ( type_name )
216
- . map ( |nq | FieldsInfo :: NativeQuery {
217
- name : type_name ,
218
- info : nq ,
248
+ . get ( collection_name )
249
+ . map ( |t | FieldsInfo :: Table {
250
+ name : collection_name . clone ( ) ,
251
+ info : t ,
219
252
} )
220
- } )
221
- . or_else ( || {
222
- self . metadata
223
- . native_operations
224
- . mutations
225
- . 0
226
- . get ( type_name . as_str ( ) )
227
- . map ( |nq| FieldsInfo :: NativeQuery {
228
- name : type_name ,
229
- info : nq ,
253
+ . or_else ( || {
254
+ self . metadata
255
+ . native_operations
256
+ . queries
257
+ . 0
258
+ . get ( collection_name )
259
+ . map ( |nq| FieldsInfo :: NativeQuery {
260
+ name : collection_name . clone ( ) ,
261
+ info : nq ,
262
+ } )
230
263
} )
231
- } ) ;
232
-
233
- info. ok_or ( Error :: CollectionNotFound ( type_name. as_str ( ) . into ( ) ) )
264
+ . or_else ( || {
265
+ self . metadata
266
+ . native_operations
267
+ . mutations
268
+ . 0
269
+ . get ( collection_name. as_str ( ) )
270
+ . map ( |nq| FieldsInfo :: NativeQuery {
271
+ name : collection_name. clone ( ) ,
272
+ info : nq,
273
+ } )
274
+ } ) ;
275
+
276
+ info. ok_or ( Error :: CollectionNotFound ( collection_name. as_str ( ) . into ( ) ) )
277
+ }
278
+ }
234
279
}
235
280
236
281
/// Lookup a metadata object which can be described by a Composite Type. This can be any of
@@ -265,7 +310,7 @@ impl<'request> Env<'request> {
265
310
} )
266
311
} ) ;
267
312
268
- info. ok_or ( Error :: CollectionNotFound ( type_name. as_str ( ) . into ( ) ) )
313
+ info. ok_or ( Error :: ScalarTypeNotFound ( type_name. as_str ( ) . into ( ) ) )
269
314
}
270
315
271
316
/// Lookup a collection's information in the metadata.
@@ -591,7 +636,7 @@ impl NativeQueries {
591
636
}
592
637
593
638
/// A newtype wrapper around an ndc-spec type which represents accessing a nested field.
594
- #[ derive( Debug , Clone ) ]
639
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
595
640
pub struct FieldPath ( pub Vec < models:: FieldName > ) ;
596
641
597
642
impl From < & Option < Vec < models:: FieldName > > > for FieldPath {
0 commit comments