Skip to content

Commit 13905e1

Browse files
committed
trying to get computed functions to work
1 parent 8ebfb06 commit 13905e1

58 files changed

Lines changed: 1095 additions & 101 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

crates/deno-subsystem/deno-graphql-resolver/extension/exograph.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ export function exograph_version() {
2525
//
2626
globalThis.ExographExtension = ({
2727
executeQuery: async function (query_string, variables) {
28-
const result = await op_exograph_execute_query(query_string, variables);
28+
const normalizedVars = variables === undefined ? null : variables;
29+
const result = await op_exograph_execute_query(query_string, normalizedVars);
2930
return result;
3031
},
3132

@@ -34,7 +35,9 @@ globalThis.ExographExtension = ({
3435
},
3536

3637
executeQueryPriv: async function (query_string, variables, context_override) {
37-
const result = await op_exograph_execute_query_priv(query_string, variables, context_override);
38+
const normalizedVars = variables === undefined ? null : variables;
39+
const normalizedContext = context_override === undefined ? null : context_override;
40+
const result = await op_exograph_execute_query_priv(query_string, normalizedVars, normalizedContext);
3841
return result;
3942
},
4043
})

crates/deno-subsystem/deno-graphql-resolver/src/exograph_ops.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,33 @@ pub async fn op_exograph_execute_query_helper(
3434
variables: Option<Value>,
3535
context_override: Value,
3636
) -> Result<Value, DenoExecutionError> {
37+
let query_str = query_string.as_str().ok_or_else(|| {
38+
DenoExecutionError::Explicit(format!(
39+
"executeQuery expects query_string to be a string, got {}",
40+
query_string
41+
))
42+
})?;
43+
let variables = match variables {
44+
Some(Value::Object(obj)) => Some(obj),
45+
Some(other) => {
46+
return Err(DenoExecutionError::Explicit(format!(
47+
"executeQuery expects variables to be an object, got {}",
48+
other
49+
)));
50+
}
51+
None => None,
52+
};
53+
let context_override = match context_override {
54+
Value::Null => Value::Null,
55+
Value::Object(_) => context_override,
56+
other => {
57+
return Err(DenoExecutionError::Explicit(format!(
58+
"executeQuery expects context_override to be an object or null, got {}",
59+
other
60+
)));
61+
}
62+
};
63+
3764
let (response_sender, response_receiver) = tokio::sync::oneshot::channel();
3865

3966
let sender = {
@@ -43,8 +70,8 @@ pub async fn op_exograph_execute_query_helper(
4370

4471
sender
4572
.send(RequestFromDenoMessage::ExographExecute {
46-
query_string: query_string.as_str().unwrap().to_string(),
47-
variables: variables.as_ref().map(|o| o.as_object().unwrap().clone()),
73+
query_string: query_str.to_string(),
74+
variables,
4875
context_override,
4976
response_sender,
5077
})

crates/deno-subsystem/deno-graphql-resolver/src/exograph_shim.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99

1010
({
1111
executeQuery: async function (query_string, variables) {
12-
const result = await ExographExtension.executeQuery(query_string, variables);
12+
const normalizedVars = variables === undefined ? null : variables;
13+
const result = await ExographExtension.executeQuery(query_string, normalizedVars);
1314
return result;
1415
},
1516

crates/postgres-subsystem/postgres-graphql-builder/src/predicate_builder.rs

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,17 @@ pub fn build_shallow(types: &MappedArena<ResolvedType>, building: &mut SystemCon
134134
.predicate_types
135135
.add(&shallow_type.name.clone(), shallow_type);
136136
}
137+
// Some filter type (for one-to-many relation filters)
138+
{
139+
let shallow_type = PredicateParameterType {
140+
name: get_some_filter_type_name(&c.name),
141+
kind: PredicateParameterTypeKind::ImplicitEqual, // Will be set to the correct value in expand_type
142+
underlying_type: None,
143+
};
144+
building
145+
.predicate_types
146+
.add(&shallow_type.name.clone(), shallow_type);
147+
}
137148
// Unique filter type
138149
{
139150
let shallow_type = PredicateParameterType {
@@ -178,21 +189,31 @@ pub fn build_expanded(resolved_env: &ResolvedTypeEnv, building: &mut SystemConte
178189
continue;
179190
}
180191

192+
let resolved_type = resolved_env
193+
.resolved_types
194+
.get_by_key(&entity_type.name)
195+
.unwrap();
196+
181197
{
182198
let param_type_name = get_filter_type_name(&entity_type.name);
183199
let existing_param_id = building.predicate_types.get_id(&param_type_name);
184200

185-
let resolved_type = resolved_env
186-
.resolved_types
187-
.get_by_key(&entity_type.name)
188-
.unwrap();
189-
190201
let new_kind = expand_entity_type(resolved_type, entity_type, building);
191202
let param_type = &mut building.predicate_types[existing_param_id.unwrap()];
192203
param_type.kind = new_kind;
193204
param_type.underlying_type = Some(entity_type_id);
194205
}
195206

207+
{
208+
let param_type_name = get_some_filter_type_name(&entity_type.name);
209+
let existing_param_id = building.predicate_types.get_id(&param_type_name);
210+
let new_kind = expand_some_filter_type(resolved_type, entity_type, building);
211+
212+
let param_type = &mut building.predicate_types[existing_param_id.unwrap()];
213+
param_type.kind = new_kind;
214+
param_type.underlying_type = Some(entity_type_id);
215+
}
216+
196217
{
197218
let param_type_name = get_unique_filter_type_name(&entity_type.name);
198219
let existing_param_id = building.predicate_types.get_id(&param_type_name);
@@ -217,6 +238,10 @@ pub fn get_array_filter_type_name(type_name: &str) -> String {
217238
format!("{type_name}ArrayFilter")
218239
}
219240

241+
pub fn get_some_filter_type_name(type_name: &str) -> String {
242+
format!("{type_name}SomeFilter")
243+
}
244+
220245
fn expand_primitive_type(
221246
typ: &PostgresPrimitiveType,
222247
building: &SystemContextBuilding,
@@ -293,6 +318,11 @@ fn expand_entity_type(
293318
&& matches!(field.typ.base_type(), FieldType::List(_))
294319
{
295320
get_array_filter_type_name(field.typ.name())
321+
} else if matches!(
322+
field.relation,
323+
PostgresRelation::OneToMany(_) | PostgresRelation::Transitive(_)
324+
) {
325+
get_some_filter_type_name(field.typ.name())
296326
} else {
297327
get_filter_type_name(field.typ.name())
298328
};
@@ -375,6 +405,49 @@ fn expand_entity_type(
375405
}
376406
}
377407

408+
fn expand_some_filter_type(
409+
resolved_type: &ResolvedType,
410+
entity_type: &EntityType,
411+
building: &SystemContextBuilding,
412+
) -> PredicateParameterTypeKind {
413+
let (mut field_params, logical_op_params) =
414+
match expand_entity_type(resolved_type, entity_type, building) {
415+
PredicateParameterTypeKind::Composite {
416+
field_params,
417+
logical_op_params,
418+
} => (field_params, logical_op_params),
419+
other => return other,
420+
};
421+
422+
let param_type_name = get_filter_type_name(&entity_type.name);
423+
let param_type_id = building
424+
.predicate_types
425+
.get_id(&param_type_name)
426+
.unwrap_or_else(|| panic!("Could not find predicate type '{param_type_name}'"));
427+
428+
let param_type =
429+
FieldType::Optional(Box::new(FieldType::Plain(PredicateParameterTypeWrapper {
430+
name: param_type_name,
431+
type_id: param_type_id,
432+
})));
433+
434+
field_params.insert(
435+
0,
436+
PredicateParameter {
437+
name: "some".to_string(),
438+
typ: param_type,
439+
column_path_link: None,
440+
access: None,
441+
vector_distance_function: None,
442+
},
443+
);
444+
445+
PredicateParameterTypeKind::Composite {
446+
field_params,
447+
logical_op_params,
448+
}
449+
}
450+
378451
fn expand_unique_type(
379452
entity_type: &EntityType,
380453
building: &SystemContextBuilding,

crates/postgres-subsystem/postgres-graphql-resolver/src/abstract_operation_resolver.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,22 @@ pub async fn resolve_operation<'e>(
3535
return_type,
3636
} = resolved_operation;
3737

38-
let mut tx = request_context
39-
.system_context
40-
.transaction_holder
41-
.try_lock()
42-
.unwrap();
38+
let result = {
39+
let mut tx = request_context
40+
.system_context
41+
.transaction_holder
42+
.try_lock()
43+
.unwrap();
4344

44-
let result = subsystem_resolver
45-
.executor
46-
.execute(
47-
operation,
48-
&mut tx,
49-
&subsystem_resolver.subsystem.core_subsystem.database,
50-
)
51-
.await;
45+
subsystem_resolver
46+
.executor
47+
.execute(
48+
operation,
49+
&mut tx,
50+
&subsystem_resolver.subsystem.core_subsystem.database,
51+
)
52+
.await
53+
};
5254

5355
if let Err(DatabaseError::Precheck(_)) = result {
5456
return Err(PostgresExecutionError::Authorization);

crates/postgres-subsystem/postgres-graphql-resolver/src/predicate_mapper.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,8 +408,7 @@ impl<'a> SQLMapper<'a, AbstractPredicate> for PredicateParamInput<'a> {
408408
&self.parent_column_path,
409409
subsystem,
410410
parameter.name.as_str() == "in",
411-
)
412-
.expect("Could not get operands");
411+
)?;
413412

414413
Ok(predicate_from_name(
415414
&parameter.name,

crates/testing/src/loader/test_suite.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,12 @@ fn collect_exo_projects(root_directory: &Path) -> Vec<PathBuf> {
135135
if subdir.path().is_dir() {
136136
let subdir_path = subdir.path();
137137
// Skip directories with .skip suffix
138-
if let Some(dir_name) = subdir_path.file_name() {
139-
if dir_name.to_str().map_or(false, |s| s.ends_with(".skip")) {
140-
continue;
141-
}
138+
if subdir_path
139+
.file_name()
140+
.and_then(|n| n.to_str())
141+
.is_some_and(|s| s.ends_with(".skip"))
142+
{
143+
continue;
142144
}
143145
if is_exoproject_with_tests(&subdir_path) {
144146
acc.push(subdir_path);

integration-tests/access-expressions/schema-tests/introspection.expected.graphql

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,21 @@ input AdminNoteReferenceInput {
119119
id: Int!
120120
}
121121

122+
"""
123+
Predicate for the `AdminNote` type parameter.
124+
If a field is omitted, no filter is applied for that field.
125+
To check a field against null, use a `<field name>: null` filter
126+
"""
127+
input AdminNoteSomeFilter {
128+
some: AdminNoteFilter
129+
id: IntFilter
130+
content: StringFilter
131+
user: UserFilter
132+
and: [AdminNoteFilter!]
133+
or: [AdminNoteFilter!]
134+
not: AdminNoteFilter
135+
}
136+
122137
input AdminNoteUpdateInput {
123138
id: Int
124139
content: String
@@ -333,6 +348,21 @@ input MembershipReferenceInput {
333348
id: Int!
334349
}
335350

351+
"""
352+
Predicate for the `Membership` type parameter.
353+
If a field is omitted, no filter is applied for that field.
354+
To check a field against null, use a `<field name>: null` filter
355+
"""
356+
input MembershipSomeFilter {
357+
some: MembershipFilter
358+
id: IntFilter
359+
kind: StringFilter
360+
user: UserFilter
361+
and: [MembershipFilter!]
362+
or: [MembershipFilter!]
363+
not: MembershipFilter
364+
}
365+
336366
input MembershipUpdateInput {
337367
id: Int
338368
kind: String
@@ -440,8 +470,8 @@ To check a field against null, use a `<field name>: null` filter
440470
input UserFilter {
441471
id: IntFilter
442472
name: StringFilter
443-
membership: MembershipFilter
444-
notes: AdminNoteFilter
473+
membership: MembershipSomeFilter
474+
notes: AdminNoteSomeFilter
445475
and: [UserFilter!]
446476
or: [UserFilter!]
447477
not: UserFilter

integration-tests/access-null-field-check/schema-tests/introspection.expected.graphql

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,21 @@ input IssueReferenceInput {
6060
id: Int!
6161
}
6262

63+
"""
64+
Predicate for the `Issue` type parameter.
65+
If a field is omitted, no filter is applied for that field.
66+
To check a field against null, use a `<field name>: null` filter
67+
"""
68+
input IssueSomeFilter {
69+
some: IssueFilter
70+
id: IntFilter
71+
title: StringFilter
72+
assignee: UserFilter
73+
and: [IssueFilter!]
74+
or: [IssueFilter!]
75+
not: IssueFilter
76+
}
77+
6378
input IssueUpdateInput {
6479
id: Int
6580
title: String
@@ -127,7 +142,7 @@ To check a field against null, use a `<field name>: null` filter
127142
input UserFilter {
128143
id: IntFilter
129144
name: StringFilter
130-
assignedIssues: IssueFilter
145+
assignedIssues: IssueSomeFilter
131146
and: [UserFilter!]
132147
or: [UserFilter!]
133148
not: UserFilter

integration-tests/basic-model-no-auth/schema-tests/introspection.expected.graphql

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,23 @@ input ConcertReferenceInput {
6464
id: Int!
6565
}
6666

67+
"""
68+
Predicate for the `Concert` type parameter.
69+
If a field is omitted, no filter is applied for that field.
70+
To check a field against null, use a `<field name>: null` filter
71+
"""
72+
input ConcertSomeFilter {
73+
some: ConcertFilter
74+
id: IntFilter
75+
title: StringFilter
76+
venue: VenueFilter
77+
published: BooleanFilter
78+
price: DecimalFilter
79+
and: [ConcertFilter!]
80+
or: [ConcertFilter!]
81+
not: ConcertFilter
82+
}
83+
6784
input ConcertUpdateInput {
6885
id: Int
6986
title: String
@@ -194,7 +211,7 @@ To check a field against null, use a `<field name>: null` filter
194211
input VenueFilter {
195212
id: IntFilter
196213
name: StringFilter
197-
concerts: ConcertFilter
214+
concerts: ConcertSomeFilter
198215
published: BooleanFilter
199216
latitude: FloatFilter
200217
and: [VenueFilter!]

0 commit comments

Comments
 (0)