@@ -991,6 +991,19 @@ pub struct NodeBuilder {
991
991
pub selections : Vec < NodeSelection > ,
992
992
}
993
993
994
+ #[ derive( Clone , Debug ) ]
995
+ pub struct NodeByPkBuilder {
996
+ // args - map of column name to value
997
+ pub pk_values : HashMap < String , serde_json:: Value > ,
998
+
999
+ pub _alias : String ,
1000
+
1001
+ // metadata
1002
+ pub table : Arc < Table > ,
1003
+
1004
+ pub selections : Vec < NodeSelection > ,
1005
+ }
1006
+
994
1007
#[ derive( Clone , Debug ) ]
995
1008
pub enum NodeSelection {
996
1009
Connection ( ConnectionBuilder ) ,
@@ -2028,6 +2041,188 @@ where
2028
2041
} )
2029
2042
}
2030
2043
2044
+ pub fn to_node_by_pk_builder < ' a , T > (
2045
+ field : & __Field ,
2046
+ query_field : & graphql_parser:: query:: Field < ' a , T > ,
2047
+ fragment_definitions : & Vec < FragmentDefinition < ' a , T > > ,
2048
+ variables : & serde_json:: Value ,
2049
+ variable_definitions : & Vec < VariableDefinition < ' a , T > > ,
2050
+ ) -> Result < NodeByPkBuilder , String >
2051
+ where
2052
+ T : Text < ' a > + Eq + AsRef < str > + Clone ,
2053
+ T :: Value : Hash ,
2054
+ {
2055
+ let type_ = field. type_ ( ) . unmodified_type ( ) ;
2056
+ let alias = alias_or_name ( query_field) ;
2057
+
2058
+ match type_ {
2059
+ __Type:: Node ( xtype) => {
2060
+ let type_name = xtype
2061
+ . name ( )
2062
+ . ok_or ( "Encountered type without name in node_by_pk builder" ) ?;
2063
+
2064
+ let field_map = field_map ( & __Type:: Node ( xtype. clone ( ) ) ) ;
2065
+
2066
+ // Get primary key columns from the table
2067
+ let pkey = xtype
2068
+ . table
2069
+ . primary_key ( )
2070
+ . ok_or ( "Table has no primary key" . to_string ( ) ) ?;
2071
+
2072
+ // Create a map of expected field arguments based on the field's arg definitions
2073
+ let mut pk_arg_map = HashMap :: new ( ) ;
2074
+ for arg in field. args ( ) {
2075
+ if let Some ( NodeSQLType :: Column ( col) ) = & arg. sql_type {
2076
+ pk_arg_map. insert ( arg. name ( ) . to_string ( ) , col. name . clone ( ) ) ;
2077
+ }
2078
+ }
2079
+
2080
+ let mut pk_values = HashMap :: new ( ) ;
2081
+
2082
+ // Process each argument in the query
2083
+ for arg in & query_field. arguments {
2084
+ let arg_name = arg. 0 . as_ref ( ) ;
2085
+
2086
+ // Find the corresponding column name from our argument map
2087
+ if let Some ( col_name) = pk_arg_map. get ( arg_name) {
2088
+ let value = to_gson ( & arg. 1 , variables, variable_definitions) ?;
2089
+ let json_value = gson:: gson_to_json ( & value) ?;
2090
+ pk_values. insert ( col_name. clone ( ) , json_value) ;
2091
+ }
2092
+ }
2093
+
2094
+ // Need values for all primary key columns
2095
+ if pk_values. len ( ) != pkey. column_names . len ( ) {
2096
+ return Err ( "All primary key columns must be provided" . to_string ( ) ) ;
2097
+ }
2098
+
2099
+ let mut builder_fields = vec ! [ ] ;
2100
+ let selection_fields = normalize_selection_set (
2101
+ & query_field. selection_set ,
2102
+ fragment_definitions,
2103
+ & type_name,
2104
+ variables,
2105
+ ) ?;
2106
+
2107
+ for selection_field in selection_fields {
2108
+ match field_map. get ( selection_field. name . as_ref ( ) ) {
2109
+ None => {
2110
+ return Err ( format ! (
2111
+ "Unknown field '{}' on type '{}'" ,
2112
+ selection_field. name. as_ref( ) ,
2113
+ & type_name
2114
+ ) )
2115
+ }
2116
+ Some ( f) => {
2117
+ let alias = alias_or_name ( & selection_field) ;
2118
+
2119
+ let node_selection = match & f. sql_type {
2120
+ Some ( node_sql_type) => match node_sql_type {
2121
+ NodeSQLType :: Column ( col) => NodeSelection :: Column ( ColumnBuilder {
2122
+ alias,
2123
+ column : Arc :: clone ( col) ,
2124
+ } ) ,
2125
+ NodeSQLType :: Function ( func) => {
2126
+ let function_selection = match & f. type_ ( ) {
2127
+ __Type:: Scalar ( _) => FunctionSelection :: ScalarSelf ,
2128
+ __Type:: List ( _) => FunctionSelection :: Array ,
2129
+ __Type:: Node ( _) => {
2130
+ let node_builder = to_node_builder (
2131
+ f,
2132
+ & selection_field,
2133
+ fragment_definitions,
2134
+ variables,
2135
+ & [ ] ,
2136
+ variable_definitions,
2137
+ ) ?;
2138
+ FunctionSelection :: Node ( node_builder)
2139
+ }
2140
+ __Type:: Connection ( _) => {
2141
+ let connection_builder = to_connection_builder (
2142
+ f,
2143
+ & selection_field,
2144
+ fragment_definitions,
2145
+ variables,
2146
+ & [ ] ,
2147
+ variable_definitions,
2148
+ ) ?;
2149
+ FunctionSelection :: Connection ( connection_builder)
2150
+ }
2151
+ _ => {
2152
+ return Err (
2153
+ "invalid return type from function" . to_string ( )
2154
+ )
2155
+ }
2156
+ } ;
2157
+ NodeSelection :: Function ( FunctionBuilder {
2158
+ alias,
2159
+ function : Arc :: clone ( func) ,
2160
+ table : Arc :: clone ( & xtype. table ) ,
2161
+ selection : function_selection,
2162
+ } )
2163
+ }
2164
+ NodeSQLType :: NodeId ( pkey_columns) => {
2165
+ NodeSelection :: NodeId ( NodeIdBuilder {
2166
+ alias,
2167
+ columns : pkey_columns. clone ( ) ,
2168
+ table_name : xtype. table . name . clone ( ) ,
2169
+ schema_name : xtype. table . schema . clone ( ) ,
2170
+ } )
2171
+ }
2172
+ } ,
2173
+ _ => match f. name ( ) . as_ref ( ) {
2174
+ "__typename" => NodeSelection :: Typename {
2175
+ alias : alias_or_name ( & selection_field) ,
2176
+ typename : xtype. name ( ) . expect ( "node type should have a name" ) ,
2177
+ } ,
2178
+ _ => match f. type_ ( ) . unmodified_type ( ) {
2179
+ __Type:: Connection ( _) => {
2180
+ let con_builder = to_connection_builder (
2181
+ f,
2182
+ & selection_field,
2183
+ fragment_definitions,
2184
+ variables,
2185
+ & [ ] ,
2186
+ variable_definitions,
2187
+ ) ;
2188
+ NodeSelection :: Connection ( con_builder?)
2189
+ }
2190
+ __Type:: Node ( _) => {
2191
+ let node_builder = to_node_builder (
2192
+ f,
2193
+ & selection_field,
2194
+ fragment_definitions,
2195
+ variables,
2196
+ & [ ] ,
2197
+ variable_definitions,
2198
+ ) ;
2199
+ NodeSelection :: Node ( node_builder?)
2200
+ }
2201
+ _ => {
2202
+ return Err ( format ! (
2203
+ "unexpected field type on node {}" ,
2204
+ f. name( )
2205
+ ) ) ;
2206
+ }
2207
+ } ,
2208
+ } ,
2209
+ } ;
2210
+ builder_fields. push ( node_selection) ;
2211
+ }
2212
+ }
2213
+ }
2214
+
2215
+ Ok ( NodeByPkBuilder {
2216
+ pk_values,
2217
+ _alias : alias,
2218
+ table : Arc :: clone ( & xtype. table ) ,
2219
+ selections : builder_fields,
2220
+ } )
2221
+ }
2222
+ _ => Err ( "cannot build query for non-node type" . to_string ( ) ) ,
2223
+ }
2224
+ }
2225
+
2031
2226
// Introspection
2032
2227
2033
2228
#[ allow( clippy:: large_enum_variant) ]
0 commit comments