diff --git a/src/builder.rs b/src/builder.rs index d1a225e0..31ebdefb 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -48,6 +48,7 @@ fn read_argument<'a, T>( field: &__Field, query_field: &graphql_parser::query::Field<'a, T>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, @@ -66,7 +67,7 @@ where let user_json_unvalidated = match user_input { None => gson::Value::Absent, - Some(val) => to_gson(val, variables)?, + Some(val) => to_gson(val, variables, variable_definitions)?, }; let user_json_validated = validate_arg_from_type(&input_value.type_(), &user_json_unvalidated)?; @@ -77,12 +78,19 @@ fn read_argument_at_most<'a, T>( field: &__Field, query_field: &graphql_parser::query::Field<'a, T>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, { - let at_most: gson::Value = read_argument("atMost", field, query_field, variables) - .unwrap_or(gson::Value::Number(gson::Number::Integer(1))); + let at_most: gson::Value = read_argument( + "atMost", + field, + query_field, + variables, + variable_definitions, + ) + .unwrap_or(gson::Value::Number(gson::Number::Integer(1))); match at_most { gson::Value::Number(gson::Number::Integer(x)) => Ok(x), _ => Err("Internal Error: failed to parse validated atFirst".to_string()), @@ -144,13 +152,19 @@ fn read_argument_node_id<'a, T>( field: &__Field, query_field: &graphql_parser::query::Field<'a, T>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, { // nodeId is a base64 encoded string of [schema, table, pkey_val1, pkey_val2, ...] - let node_id_base64_encoded_json_string: gson::Value = - read_argument("nodeId", field, query_field, variables)?; + let node_id_base64_encoded_json_string: gson::Value = read_argument( + "nodeId", + field, + query_field, + variables, + variable_definitions, + )?; parse_node_id(node_id_base64_encoded_json_string) } @@ -159,12 +173,19 @@ fn read_argument_objects<'a, T>( field: &__Field, query_field: &graphql_parser::query::Field<'a, T>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result, String> where T: Text<'a> + Eq + AsRef, { // [{"name": "bob", "email": "a@b.com"}, {..}] - let validated: gson::Value = read_argument("objects", field, query_field, variables)?; + let validated: gson::Value = read_argument( + "objects", + field, + query_field, + variables, + variable_definitions, + )?; // [OrderBy!] let insert_type: InsertInputType = @@ -229,6 +250,7 @@ pub fn to_insert_builder<'a, T>( query_field: &graphql_parser::query::Field<'a, T>, fragment_definitions: &Vec>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, @@ -246,7 +268,7 @@ where restrict_allowed_arguments(&["objects"], query_field)?; let objects: Vec = - read_argument_objects(field, query_field, variables)?; + read_argument_objects(field, query_field, variables, variable_definitions)?; let mut builder_fields: Vec = vec![]; @@ -271,6 +293,7 @@ where fragment_definitions, variables, &[], + variable_definitions, ); InsertSelection::Records(node_builder?) } @@ -330,11 +353,13 @@ fn read_argument_set<'a, T>( field: &__Field, query_field: &graphql_parser::query::Field<'a, T>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, { - let validated: gson::Value = read_argument("set", field, query_field, variables)?; + let validated: gson::Value = + read_argument("set", field, query_field, variables, variable_definitions)?; let update_type: UpdateInputType = match field.get_arg("set").unwrap().type_().unmodified_type() { @@ -384,6 +409,7 @@ pub fn to_update_builder<'a, T>( query_field: &graphql_parser::query::Field<'a, T>, fragment_definitions: &Vec>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, @@ -400,9 +426,12 @@ where // Raise for disallowed arguments restrict_allowed_arguments(&["set", "filter", "atMost"], query_field)?; - let set: SetBuilder = read_argument_set(field, query_field, variables)?; - let filter: FilterBuilder = read_argument_filter(field, query_field, variables)?; - let at_most: i64 = read_argument_at_most(field, query_field, variables)?; + let set: SetBuilder = + read_argument_set(field, query_field, variables, variable_definitions)?; + let filter: FilterBuilder = + read_argument_filter(field, query_field, variables, variable_definitions)?; + let at_most: i64 = + read_argument_at_most(field, query_field, variables, variable_definitions)?; let mut builder_fields: Vec = vec![]; @@ -427,6 +456,7 @@ where fragment_definitions, variables, &[], + variable_definitions, ); UpdateSelection::Records(node_builder?) } @@ -482,6 +512,7 @@ pub fn to_delete_builder<'a, T>( query_field: &graphql_parser::query::Field<'a, T>, fragment_definitions: &Vec>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, @@ -498,8 +529,10 @@ where // Raise for disallowed arguments restrict_allowed_arguments(&["filter", "atMost"], query_field)?; - let filter: FilterBuilder = read_argument_filter(field, query_field, variables)?; - let at_most: i64 = read_argument_at_most(field, query_field, variables)?; + let filter: FilterBuilder = + read_argument_filter(field, query_field, variables, variable_definitions)?; + let at_most: i64 = + read_argument_at_most(field, query_field, variables, variable_definitions)?; let mut builder_fields: Vec = vec![]; @@ -524,6 +557,7 @@ where fragment_definitions, variables, &[], + variable_definitions, ); DeleteSelection::Records(node_builder?) } @@ -585,6 +619,7 @@ pub fn to_function_call_builder<'a, T>( query_field: &graphql_parser::query::Field<'a, T>, fragment_definitions: &Vec>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, @@ -597,7 +632,13 @@ where let args = field.args(); let allowed_args: Vec<&str> = args.iter().map(|a| a.name_.as_str()).collect(); restrict_allowed_arguments(&allowed_args, query_field)?; - let args = read_func_call_args(field, query_field, variables, func_call_resp_type)?; + let args = read_func_call_args( + field, + query_field, + variables, + func_call_resp_type, + variable_definitions, + )?; let return_type_builder = match func_call_resp_type.return_type.deref() { __Type::Scalar(_) => FuncCallReturnTypeBuilder::Scalar, @@ -609,6 +650,7 @@ where fragment_definitions, variables, &allowed_args, + variable_definitions, )?; FuncCallReturnTypeBuilder::Node(node_builder) } @@ -619,6 +661,7 @@ where fragment_definitions, variables, &allowed_args, + variable_definitions, )?; FuncCallReturnTypeBuilder::Connection(connection_builder) } @@ -653,6 +696,7 @@ fn read_func_call_args<'a, T>( query_field: &graphql_parser::query::Field<'a, T>, variables: &serde_json::Value, func_call_resp_type: &FuncCallResponseType, + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, @@ -660,7 +704,13 @@ where let inflected_to_sql_args = func_call_resp_type.inflected_to_sql_args(); let mut args = vec![]; for arg in field.args() { - let arg_value = read_argument(&arg.name(), field, query_field, variables)?; + let arg_value = read_argument( + &arg.name(), + field, + query_field, + variables, + variable_definitions, + )?; if !arg_value.is_absent() { let func_call_sql_arg_name = inflected_to_sql_args @@ -970,11 +1020,18 @@ fn read_argument_filter<'a, T>( field: &__Field, query_field: &graphql_parser::query::Field<'a, T>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, { - let validated: gson::Value = read_argument("filter", field, query_field, variables)?; + let validated: gson::Value = read_argument( + "filter", + field, + query_field, + variables, + variable_definitions, + )?; let filter_type = field.get_arg("filter").unwrap().type_().unmodified_type(); if !matches!(filter_type, __Type::FilterEntity(_)) { @@ -1113,12 +1170,19 @@ fn read_argument_order_by<'a, T>( field: &__Field, query_field: &graphql_parser::query::Field<'a, T>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, { // [{"id": "DescNullsLast"}] - let validated: gson::Value = read_argument("orderBy", field, query_field, variables)?; + let validated: gson::Value = read_argument( + "orderBy", + field, + query_field, + variables, + variable_definitions, + )?; // [
OrderBy!] let order_type: OrderByEntityType = @@ -1198,11 +1262,18 @@ fn read_argument_cursor<'a, T>( field: &__Field, query_field: &graphql_parser::query::Field<'a, T>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result, String> where T: Text<'a> + Eq + AsRef, { - let validated: gson::Value = read_argument(arg_name, field, query_field, variables)?; + let validated: gson::Value = read_argument( + arg_name, + field, + query_field, + variables, + variable_definitions, + )?; let _: Scalar = match field.get_arg(arg_name).unwrap().type_().unmodified_type() { __Type::Scalar(x) => x, _ => return Err(format!("Could not argument {}", arg_name)), @@ -1227,6 +1298,7 @@ pub fn to_connection_builder<'a, T>( fragment_definitions: &Vec>, variables: &serde_json::Value, extra_allowed_args: &[&str], + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, @@ -1247,7 +1319,8 @@ where restrict_allowed_arguments(&allowed_args, query_field)?; // TODO: only one of first/last, before/after provided - let first: gson::Value = read_argument("first", field, query_field, variables)?; + let first: gson::Value = + read_argument("first", field, query_field, variables, variable_definitions)?; let first: Option = match first { gson::Value::Absent | gson::Value::Null => None, gson::Value::Number(gson::Number::Integer(n)) if n < 0 => { @@ -1259,7 +1332,8 @@ where } }; - let last: gson::Value = read_argument("last", field, query_field, variables)?; + let last: gson::Value = + read_argument("last", field, query_field, variables, variable_definitions)?; let last: Option = match last { gson::Value::Absent | gson::Value::Null => None, gson::Value::Number(gson::Number::Integer(n)) if n < 0 => { @@ -1280,10 +1354,15 @@ where .map(|x| x.directives.max_rows) .unwrap_or(30); - let before: Option = - read_argument_cursor("before", field, query_field, variables)?; + let before: Option = read_argument_cursor( + "before", + field, + query_field, + variables, + variable_definitions, + )?; let after: Option = - read_argument_cursor("after", field, query_field, variables)?; + read_argument_cursor("after", field, query_field, variables, variable_definitions)?; // Validate compatible input arguments if first.is_some() && last.is_some() { @@ -1296,8 +1375,10 @@ where return Err("\"last\" may only be used with \"before\"".to_string()); } - let filter: FilterBuilder = read_argument_filter(field, query_field, variables)?; - let order_by: OrderByBuilder = read_argument_order_by(field, query_field, variables)?; + let filter: FilterBuilder = + read_argument_filter(field, query_field, variables, variable_definitions)?; + let order_by: OrderByBuilder = + read_argument_order_by(field, query_field, variables, variable_definitions)?; let mut builder_fields: Vec = vec![]; @@ -1317,6 +1398,7 @@ where selection_field, fragment_definitions, variables, + variable_definitions, )?), __Type::PageInfo(_) => ConnectionSelection::PageInfo(to_page_info_builder( f, @@ -1427,6 +1509,7 @@ fn to_edge_builder<'a, T>( query_field: &graphql_parser::query::Field<'a, T>, fragment_definitions: &Vec>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, @@ -1461,6 +1544,7 @@ where fragment_definitions, variables, &[], + variable_definitions, )?; EdgeSelection::Node(node_builder) } @@ -1492,6 +1576,7 @@ pub fn to_node_builder<'a, T>( fragment_definitions: &Vec>, variables: &serde_json::Value, extra_allowed_args: &[&str], + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + Eq + AsRef, @@ -1509,7 +1594,8 @@ where restrict_allowed_arguments(&["nodeId"], query_field)?; // The nodeId argument is only valid on the entrypoint field for Node // relationships to "node" e.g. within edges, do not have any arguments - let node_id: NodeIdInstance = read_argument_node_id(field, query_field, variables)?; + let node_id: NodeIdInstance = + read_argument_node_id(field, query_field, variables, variable_definitions)?; let possible_types: Vec<__Type> = node_interface.possible_types().unwrap_or(vec![]); let xtype = possible_types.iter().find_map(|x| match x { @@ -1551,7 +1637,12 @@ where // The nodeId argument is only valid on the entrypoint field for Node // relationships to "node" e.g. within edges, do not have any arguments let node_id: Option = match field.get_arg("nodeId").is_some() { - true => Some(read_argument_node_id(field, query_field, variables)?), + true => Some(read_argument_node_id( + field, + query_field, + variables, + variable_definitions, + )?), false => None, }; @@ -1590,6 +1681,7 @@ where fragment_definitions, variables, &[], + variable_definitions, // TODO need ref to fkey here )?; FunctionSelection::Node(node_builder) @@ -1601,6 +1693,7 @@ where fragment_definitions, variables, &[], // TODO need ref to fkey here + variable_definitions, )?; FunctionSelection::Connection(connection_builder) } @@ -1635,6 +1728,7 @@ where fragment_definitions, variables, &[], + variable_definitions, ); NodeSelection::Connection(con_builder?) } @@ -1645,6 +1739,7 @@ where fragment_definitions, variables, &[], + variable_definitions, ); NodeSelection::Node(node_builder?) } @@ -1875,6 +1970,7 @@ impl __Schema { query_field: &graphql_parser::query::Field<'a, T>, fragment_definitions: &Vec>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result<__InputValueBuilder, String> where T: Text<'a> + Eq + AsRef, @@ -1902,6 +1998,7 @@ impl __Schema { selection_field, fragment_definitions, variables, + variable_definitions, )?; __InputValueField::Type(t_builder) } @@ -1938,6 +2035,7 @@ impl __Schema { query_field: &graphql_parser::query::Field<'a, T>, fragment_definitions: &Vec>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result<__FieldBuilder, String> where T: Text<'a> + Eq + AsRef, @@ -1967,6 +2065,7 @@ impl __Schema { selection_field, fragment_definitions, variables, + variable_definitions, )?; f_builders.push(f_builder) } @@ -1980,6 +2079,7 @@ impl __Schema { selection_field, fragment_definitions, variables, + variable_definitions, )?; __FieldField::Type(t_builder) } @@ -2011,6 +2111,7 @@ impl __Schema { fragment_definitions: &Vec>, mut type_name: Option, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result, String> where T: Text<'a> + Eq + AsRef, @@ -2020,7 +2121,7 @@ impl __Schema { } let name_arg_result: Result = - read_argument("name", field, query_field, variables); + read_argument("name", field, query_field, variables, variable_definitions); let name_arg: Option = match name_arg_result { // This builder (too) is overloaded and the arg is not present in all uses Err(_) => None, @@ -2051,6 +2152,7 @@ impl __Schema { query_field, fragment_definitions, variables, + variable_definitions, ) .map(Some) } @@ -2064,6 +2166,7 @@ impl __Schema { query_field: &graphql_parser::query::Field<'a, T>, fragment_definitions: &Vec>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result<__TypeBuilder, String> where T: Text<'a> + Eq + AsRef, @@ -2110,6 +2213,7 @@ impl __Schema { selection_field, fragment_definitions, variables, + variable_definitions, )?; f_builders.push(f_builder) } @@ -2130,6 +2234,7 @@ impl __Schema { selection_field, fragment_definitions, variables, + variable_definitions, )?; f_builders.push(f_builder) } @@ -2147,6 +2252,7 @@ impl __Schema { selection_field, fragment_definitions, variables, + variable_definitions, )?; interface_builders.push(interface_builder); } @@ -2186,6 +2292,7 @@ impl __Schema { selection_field, fragment_definitions, variables, + variable_definitions, )?; type_builders.push(type_builder); @@ -2195,11 +2302,12 @@ impl __Schema { None => __TypeField::PossibleTypes(None), }, "ofType" => { - let field_type = if let __Type::FuncCallResponse(func_call_resp_type) = type_ { - func_call_resp_type.return_type.deref() - } else { - type_ - }; + let field_type = + if let __Type::FuncCallResponse(func_call_resp_type) = type_ { + func_call_resp_type.return_type.deref() + } else { + type_ + }; let unwrapped_type_builder = match field_type { __Type::List(list_type) => { let inner_type: __Type = (*(list_type.type_)).clone(); @@ -2208,6 +2316,7 @@ impl __Schema { selection_field, fragment_definitions, variables, + variable_definitions, )?) } __Type::NonNull(non_null_type) => { @@ -2217,6 +2326,7 @@ impl __Schema { selection_field, fragment_definitions, variables, + variable_definitions, )?) } _ => None, @@ -2250,6 +2360,7 @@ impl __Schema { query_field: &graphql_parser::query::Field<'a, T>, fragment_definitions: &Vec>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result<__DirectiveBuilder, String> where T: Text<'a> + Eq + AsRef, @@ -2280,6 +2391,7 @@ impl __Schema { selection_field, fragment_definitions, variables, + variable_definitions, )?; builders.push(builder) } @@ -2317,6 +2429,7 @@ impl __Schema { query_field: &graphql_parser::query::Field<'a, T>, fragment_definitions: &Vec>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result<__SchemaBuilder, String> where T: Text<'a> + Eq + AsRef, @@ -2361,6 +2474,7 @@ impl __Schema { fragment_definitions, t.name(), variables, + variable_definitions, ) .map(|x| x.unwrap()) }) @@ -2375,6 +2489,7 @@ impl __Schema { fragment_definitions, Some("Query".to_string()), variables, + variable_definitions, )?; __SchemaField::QueryType(builder.unwrap()) } @@ -2385,6 +2500,7 @@ impl __Schema { fragment_definitions, Some("Mutation".to_string()), variables, + variable_definitions, )?; __SchemaField::MutationType(builder) } @@ -2399,6 +2515,7 @@ impl __Schema { selection_field, fragment_definitions, variables, + variable_definitions, ) }) .collect::, _>>()?; diff --git a/src/parser_util.rs b/src/parser_util.rs index 0e0057ce..ff8e8dd1 100644 --- a/src/parser_util.rs +++ b/src/parser_util.rs @@ -210,6 +210,7 @@ where pub fn to_gson<'a, T>( graphql_value: &Value<'a, T>, variables: &serde_json::Value, + variable_definitions: &Vec>, ) -> Result where T: Text<'a> + AsRef, @@ -236,7 +237,7 @@ where Value::List(x_arr) => { let mut out_arr: Vec = vec![]; for x in x_arr { - let val = to_gson(x, variables)?; + let val = to_gson(x, variables, variable_definitions)?; out_arr.push(val); } gson::Value::Array(out_arr) @@ -244,7 +245,7 @@ where Value::Object(obj) => { let mut out_map: HashMap = HashMap::new(); for (key, graphql_val) in obj.iter() { - let val = to_gson(graphql_val, variables)?; + let val = to_gson(graphql_val, variables, variable_definitions)?; out_map.insert(key.as_ref().to_string(), val); } gson::Value::Object(out_map) @@ -252,8 +253,20 @@ where Value::Variable(var_name) => { let var = variables.get(var_name.as_ref()); match var { - None => gson::Value::Absent, Some(x) => gson::json_to_gson(x)?, + None => { + let variable_default: Option<&graphql_parser::query::Value<'a, T>> = + variable_definitions + .iter() + .find(|var_def| var_def.name.as_ref() == var_name.as_ref()) + .map(|x| x.default_value.as_ref()) + .flatten(); + + match variable_default { + Some(x) => to_gson(x, variables, variable_definitions)?, + None => gson::Value::Absent, + } + } } } }; diff --git a/src/resolve.rs b/src/resolve.rs index 7d80162b..cee49e61 100644 --- a/src/resolve.rs +++ b/src/resolve.rs @@ -6,7 +6,7 @@ use crate::sql_types::get_one_readonly; use crate::transpile::{MutationEntrypoint, QueryEntrypoint}; use graphql_parser::query::{ Definition, Document, FragmentDefinition, Mutation, OperationDefinition, Query, SelectionSet, - Text, + Text, VariableDefinition, }; use itertools::Itertools; use serde_json::{json, Value}; @@ -93,7 +93,7 @@ where resolve_query(query, schema, variables, fragment_defs) } OperationDefinition::SelectionSet(selection_set) => { - resolve_selection_set(selection_set, schema, variables, fragment_defs) + resolve_selection_set(selection_set, schema, variables, fragment_defs, &vec![]) } OperationDefinition::Mutation(mutation) => { resolve_mutation(mutation, schema, variables, fragment_defs) @@ -117,11 +117,13 @@ fn resolve_query<'a, 'b, T>( where T: Text<'a> + Eq + AsRef, { + let variable_definitions = &query.variable_definitions; resolve_selection_set( query.selection_set, schema_type, variables, fragment_definitions, + variable_definitions, ) } @@ -130,6 +132,7 @@ fn resolve_selection_set<'a, 'b, T>( schema_type: &__Schema, variables: &Value, fragment_definitions: Vec>, + variable_definitions: &Vec>, ) -> GraphQLResponse where T: Text<'a> + Eq + AsRef, @@ -190,6 +193,7 @@ where &fragment_definitions, variables, &[], + variable_definitions, ); match connection_builder { @@ -209,6 +213,7 @@ where &fragment_definitions, variables, &[], + variable_definitions, ); match node_builder { @@ -228,6 +233,7 @@ where &fragment_definitions, None, variables, + variable_definitions, ); match __type_builder { @@ -243,6 +249,7 @@ where selection, &fragment_definitions, variables, + variable_definitions, ); match __schema_builder { @@ -271,6 +278,7 @@ where selection, &fragment_definitions, variables, + variable_definitions, ); match function_call_builder { @@ -316,11 +324,13 @@ fn resolve_mutation<'a, 'b, T>( where T: Text<'a> + Eq + AsRef, { + let variable_definitions = &query.variable_definitions; resolve_mutation_selection_set( query.selection_set, schema_type, variables, fragment_definitions, + variable_definitions, ) } @@ -329,6 +339,7 @@ fn resolve_mutation_selection_set<'a, 'b, T>( schema_type: &__Schema, variables: &Value, fragment_definitions: Vec>, + variable_definitions: &Vec>, ) -> GraphQLResponse where T: Text<'a> + Eq + AsRef, @@ -391,6 +402,7 @@ where selection, &fragment_definitions, variables, + variable_definitions, ) { Ok(builder) => builder, Err(err) => { @@ -409,6 +421,7 @@ where selection, &fragment_definitions, variables, + variable_definitions, ) { Ok(builder) => builder, Err(err) => { @@ -426,6 +439,7 @@ where selection, &fragment_definitions, variables, + variable_definitions, ) { Ok(builder) => builder, Err(err) => { @@ -449,6 +463,7 @@ where selection, &fragment_definitions, variables, + variable_definitions, ) { Ok(builder) => builder, Err(err) => { diff --git a/test/expected/variable_default.out b/test/expected/variable_default.out new file mode 100644 index 00000000..5aba1fb7 --- /dev/null +++ b/test/expected/variable_default.out @@ -0,0 +1,67 @@ +begin; + create table blog( + id int primary key + ); + insert into blog(id) + select generate_series(1, 5); + -- User defined default for variable $first. + -- Returns 2 rows + -- No value provided for variable $first so user defined default applies + select graphql.resolve($$ + query Blogs($first: Int = 2) { + blogCollection(first: $first) { + edges { + node { + id + } + } + } + } + $$); + resolve +------------------------------------------------------------------------------------- + {"data": {"blogCollection": {"edges": [{"node": {"id": 1}}, {"node": {"id": 2}}]}}} +(1 row) + + -- Returns 1 row + -- Provided value for variable $first applies + select graphql.resolve($$ + query Blogs($first: Int = 2) { + blogCollection(first: $first) { + edges { + node { + id + } + } + } + } + $$, + variables := jsonb_build_object( + 'first', 1 + ) + ); + resolve +---------------------------------------------------------------- + {"data": {"blogCollection": {"edges": [{"node": {"id": 1}}]}}} +(1 row) + + -- Returns all rows + -- No default, no variable value. Falls back to sever side behavior + select graphql.resolve($$ + query Blogs($first: Int) { + blogCollection(first: $first) { + edges { + node { + id + } + } + } + } + $$ + ); + resolve +---------------------------------------------------------------------------------------------------------------------------------------------------- + {"data": {"blogCollection": {"edges": [{"node": {"id": 1}}, {"node": {"id": 2}}, {"node": {"id": 3}}, {"node": {"id": 4}}, {"node": {"id": 5}}]}}} +(1 row) + +rollback; diff --git a/test/sql/variable_default.sql b/test/sql/variable_default.sql new file mode 100644 index 00000000..99010afb --- /dev/null +++ b/test/sql/variable_default.sql @@ -0,0 +1,59 @@ +begin; + + create table blog( + id int primary key + ); + + insert into blog(id) + select generate_series(1, 5); + + -- User defined default for variable $first. + + -- Returns 2 rows + -- No value provided for variable $first so user defined default applies + select graphql.resolve($$ + query Blogs($first: Int = 2) { + blogCollection(first: $first) { + edges { + node { + id + } + } + } + } + $$); + + -- Returns 1 row + -- Provided value for variable $first applies + select graphql.resolve($$ + query Blogs($first: Int = 2) { + blogCollection(first: $first) { + edges { + node { + id + } + } + } + } + $$, + variables := jsonb_build_object( + 'first', 1 + ) + ); + + -- Returns all rows + -- No default, no variable value. Falls back to sever side behavior + select graphql.resolve($$ + query Blogs($first: Int) { + blogCollection(first: $first) { + edges { + node { + id + } + } + } + } + $$ + ); + +rollback;