@@ -958,6 +958,19 @@ pub struct NodeBuilder {
958
958
pub selections : Vec < NodeSelection > ,
959
959
}
960
960
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
+
961
974
#[ derive( Clone , Debug ) ]
962
975
pub enum NodeSelection {
963
976
Connection ( ConnectionBuilder ) ,
@@ -1816,6 +1829,188 @@ where
1816
1829
} )
1817
1830
}
1818
1831
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
+
1819
2014
// Introspection
1820
2015
1821
2016
#[ allow( clippy:: large_enum_variant) ]
0 commit comments