@@ -958,6 +958,19 @@ pub struct NodeBuilder {
958958 pub selections : Vec < NodeSelection > ,
959959}
960960
961+ #[ derive( Clone , Debug ) ]
962+ pub struct NodeByPkBuilder {
963+ // args - map of column name to value
964+ pub pk_values : HashMap < String , serde_json:: Value > ,
965+
966+ pub _alias : String ,
967+
968+ // metadata
969+ pub table : Arc < Table > ,
970+
971+ pub selections : Vec < NodeSelection > ,
972+ }
973+
961974#[ derive( Clone , Debug ) ]
962975pub enum NodeSelection {
963976 Connection ( ConnectionBuilder ) ,
@@ -1816,6 +1829,188 @@ where
18161829 } )
18171830}
18181831
1832+ pub fn to_node_by_pk_builder < ' a , T > (
1833+ field : & __Field ,
1834+ query_field : & graphql_parser:: query:: Field < ' a , T > ,
1835+ fragment_definitions : & Vec < FragmentDefinition < ' a , T > > ,
1836+ variables : & serde_json:: Value ,
1837+ variable_definitions : & Vec < VariableDefinition < ' a , T > > ,
1838+ ) -> Result < NodeByPkBuilder , String >
1839+ where
1840+ T : Text < ' a > + Eq + AsRef < str > + Clone ,
1841+ T :: Value : Hash ,
1842+ {
1843+ let type_ = field. type_ ( ) . unmodified_type ( ) ;
1844+ let alias = alias_or_name ( query_field) ;
1845+
1846+ match type_ {
1847+ __Type:: Node ( xtype) => {
1848+ let type_name = xtype
1849+ . name ( )
1850+ . ok_or ( "Encountered type without name in node_by_pk builder" ) ?;
1851+
1852+ let field_map = field_map ( & __Type:: Node ( xtype. clone ( ) ) ) ;
1853+
1854+ // Get primary key columns from the table
1855+ let pkey = xtype
1856+ . table
1857+ . primary_key ( )
1858+ . ok_or ( "Table has no primary key" . to_string ( ) ) ?;
1859+
1860+ // Create a map of expected field arguments based on the field's arg definitions
1861+ let mut pk_arg_map = HashMap :: new ( ) ;
1862+ for arg in field. args ( ) {
1863+ if let Some ( NodeSQLType :: Column ( col) ) = & arg. sql_type {
1864+ pk_arg_map. insert ( arg. name ( ) . to_string ( ) , col. name . clone ( ) ) ;
1865+ }
1866+ }
1867+
1868+ let mut pk_values = HashMap :: new ( ) ;
1869+
1870+ // Process each argument in the query
1871+ for arg in & query_field. arguments {
1872+ let arg_name = arg. 0 . as_ref ( ) ;
1873+
1874+ // Find the corresponding column name from our argument map
1875+ if let Some ( col_name) = pk_arg_map. get ( arg_name) {
1876+ let value = to_gson ( & arg. 1 , variables, variable_definitions) ?;
1877+ let json_value = gson:: gson_to_json ( & value) ?;
1878+ pk_values. insert ( col_name. clone ( ) , json_value) ;
1879+ }
1880+ }
1881+
1882+ // Need values for all primary key columns
1883+ if pk_values. len ( ) != pkey. column_names . len ( ) {
1884+ return Err ( "All primary key columns must be provided" . to_string ( ) ) ;
1885+ }
1886+
1887+ let mut builder_fields = vec ! [ ] ;
1888+ let selection_fields = normalize_selection_set (
1889+ & query_field. selection_set ,
1890+ fragment_definitions,
1891+ & type_name,
1892+ variables,
1893+ ) ?;
1894+
1895+ for selection_field in selection_fields {
1896+ match field_map. get ( selection_field. name . as_ref ( ) ) {
1897+ None => {
1898+ return Err ( format ! (
1899+ "Unknown field '{}' on type '{}'" ,
1900+ selection_field. name. as_ref( ) ,
1901+ & type_name
1902+ ) )
1903+ }
1904+ Some ( f) => {
1905+ let alias = alias_or_name ( & selection_field) ;
1906+
1907+ let node_selection = match & f. sql_type {
1908+ Some ( node_sql_type) => match node_sql_type {
1909+ NodeSQLType :: Column ( col) => NodeSelection :: Column ( ColumnBuilder {
1910+ alias,
1911+ column : Arc :: clone ( col) ,
1912+ } ) ,
1913+ NodeSQLType :: Function ( func) => {
1914+ let function_selection = match & f. type_ ( ) {
1915+ __Type:: Scalar ( _) => FunctionSelection :: ScalarSelf ,
1916+ __Type:: List ( _) => FunctionSelection :: Array ,
1917+ __Type:: Node ( _) => {
1918+ let node_builder = to_node_builder (
1919+ f,
1920+ & selection_field,
1921+ fragment_definitions,
1922+ variables,
1923+ & [ ] ,
1924+ variable_definitions,
1925+ ) ?;
1926+ FunctionSelection :: Node ( node_builder)
1927+ }
1928+ __Type:: Connection ( _) => {
1929+ let connection_builder = to_connection_builder (
1930+ f,
1931+ & selection_field,
1932+ fragment_definitions,
1933+ variables,
1934+ & [ ] ,
1935+ variable_definitions,
1936+ ) ?;
1937+ FunctionSelection :: Connection ( connection_builder)
1938+ }
1939+ _ => {
1940+ return Err (
1941+ "invalid return type from function" . to_string ( )
1942+ )
1943+ }
1944+ } ;
1945+ NodeSelection :: Function ( FunctionBuilder {
1946+ alias,
1947+ function : Arc :: clone ( func) ,
1948+ table : Arc :: clone ( & xtype. table ) ,
1949+ selection : function_selection,
1950+ } )
1951+ }
1952+ NodeSQLType :: NodeId ( pkey_columns) => {
1953+ NodeSelection :: NodeId ( NodeIdBuilder {
1954+ alias,
1955+ columns : pkey_columns. clone ( ) ,
1956+ table_name : xtype. table . name . clone ( ) ,
1957+ schema_name : xtype. table . schema . clone ( ) ,
1958+ } )
1959+ }
1960+ } ,
1961+ _ => match f. name ( ) . as_ref ( ) {
1962+ "__typename" => NodeSelection :: Typename {
1963+ alias : alias_or_name ( & selection_field) ,
1964+ typename : xtype. name ( ) . expect ( "node type should have a name" ) ,
1965+ } ,
1966+ _ => match f. type_ ( ) . unmodified_type ( ) {
1967+ __Type:: Connection ( _) => {
1968+ let con_builder = to_connection_builder (
1969+ f,
1970+ & selection_field,
1971+ fragment_definitions,
1972+ variables,
1973+ & [ ] ,
1974+ variable_definitions,
1975+ ) ;
1976+ NodeSelection :: Connection ( con_builder?)
1977+ }
1978+ __Type:: Node ( _) => {
1979+ let node_builder = to_node_builder (
1980+ f,
1981+ & selection_field,
1982+ fragment_definitions,
1983+ variables,
1984+ & [ ] ,
1985+ variable_definitions,
1986+ ) ;
1987+ NodeSelection :: Node ( node_builder?)
1988+ }
1989+ _ => {
1990+ return Err ( format ! (
1991+ "unexpected field type on node {}" ,
1992+ f. name( )
1993+ ) ) ;
1994+ }
1995+ } ,
1996+ } ,
1997+ } ;
1998+ builder_fields. push ( node_selection) ;
1999+ }
2000+ }
2001+ }
2002+
2003+ Ok ( NodeByPkBuilder {
2004+ pk_values,
2005+ _alias : alias,
2006+ table : Arc :: clone ( & xtype. table ) ,
2007+ selections : builder_fields,
2008+ } )
2009+ }
2010+ _ => Err ( "cannot build query for non-node type" . to_string ( ) ) ,
2011+ }
2012+ }
2013+
18192014// Introspection
18202015
18212016#[ allow( clippy:: large_enum_variant) ]
0 commit comments