Skip to content

Commit 8da22dc

Browse files
committed
on conflict functional
1 parent fe15ade commit 8da22dc

File tree

4 files changed

+75
-9
lines changed

4 files changed

+75
-9
lines changed

src/builder.rs

+36-6
Original file line numberDiff line numberDiff line change
@@ -200,25 +200,22 @@ where
200200
variable_definitions,
201201
)?;
202202

203-
let insert_type: OnConflictType = match field.get_arg("onConflict") {
203+
let conflict_type: OnConflictType = match field.get_arg("onConflict") {
204204
None => return Ok(None),
205205
Some(x) => match x.type_().unmodified_type() {
206206
__Type::OnConflictInput(insert_on_conflict) => insert_on_conflict,
207207
_ => return Err("Could not locate Insert Entity type".to_string()),
208208
},
209209
};
210210

211-
let filter: FilterBuilder =
212-
read_argument_filter(field, query_field, variables, variable_definitions)?;
213-
214211
let on_conflict_builder = match validated {
215212
gson::Value::Absent | gson::Value::Null => None,
216213
gson::Value::Object(contents) => {
217214
let constraint = match contents
218215
.get("constraint")
219216
.expect("OnConflict revalidation error. Expected constraint")
220217
{
221-
gson::Value::String(ix_name) => insert_type
218+
gson::Value::String(ix_name) => conflict_type
222219
.table
223220
.indexes
224221
.iter()
@@ -231,6 +228,36 @@ where
231228
}
232229
};
233230

231+
// TODO: Filter reading logic is partially duplicated from read_argument_filter
232+
// ideally this should be refactored
233+
let filter_gson = contents
234+
.get("filter")
235+
.expect("onConflict revalidation error");
236+
237+
let filter = match filter_gson {
238+
gson::Value::Null | gson::Value::Absent => FilterBuilder { elems: vec![] },
239+
gson::Value::Object(_) => {
240+
let filter_type = conflict_type
241+
.input_fields()
242+
.expect("Failed to unwrap input fields on OnConflict type")
243+
.iter()
244+
.find(|in_f| in_f.name() == "filter")
245+
.expect("Failed to get filter input_field on onConflict type")
246+
.type_()
247+
.unmodified_type();
248+
249+
if !matches!(filter_type, __Type::FilterEntity(_)) {
250+
return Err("Could not locate Filter Entity type".to_string());
251+
}
252+
let filter_field_map = input_field_map(&filter_type);
253+
let filter_elems = create_filters(&filter_gson, &filter_field_map)?;
254+
FilterBuilder {
255+
elems: filter_elems,
256+
}
257+
}
258+
_ => return Err("OnConflict revalidation error. invalid filter object".to_string()),
259+
};
260+
234261
let update_fields = match contents
235262
.get("updateFields")
236263
.expect("OnConflict revalidation error. Expected updateFields")
@@ -240,7 +267,7 @@ where
240267
for col_name in col_names {
241268
match col_name {
242269
gson::Value::String(c) => {
243-
let col = insert_type.table.columns.iter().find(|column| &column.name == c).expect("OnConflict revalidation error. updateFields: unknown column name");
270+
let col = conflict_type.table.columns.iter().find(|column| &column.name == c).expect("OnConflict revalidation error. updateFields: unknown column name");
244271
update_columns.insert(Arc::clone(col));
245272
}
246273
_ => return Err("OnConflict revalidation error. Expected updateFields to be column names".to_string()),
@@ -1145,11 +1172,14 @@ where
11451172
variable_definitions,
11461173
)?;
11471174

1175+
//return Err(format!("Err {:?}", validated));
1176+
11481177
let filter_type = field
11491178
.get_arg("filter")
11501179
.expect("failed to get filter argument")
11511180
.type_()
11521181
.unmodified_type();
1182+
11531183
if !matches!(filter_type, __Type::FilterEntity(_)) {
11541184
return Err("Could not locate Filter Entity type".to_string());
11551185
}

src/graphql.rs

-1
Original file line numberDiff line numberDiff line change
@@ -3181,7 +3181,6 @@ impl ___Type for OnConflictType {
31813181
fn input_fields(&self) -> Option<Vec<__InputValue>> {
31823182
Some(vec![
31833183
__InputValue {
3184-
// TODO: Create a custom type for available constraints
31853184
name_: "constraint".to_string(),
31863185
// If triggers are involved, we can't detect if a field is non-null. Default
31873186
// all fields to non-null and let postgres errors handle it.

src/parser_util.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,10 @@ pub fn validate_arg_from_input_object(
529529

530530
match input_obj.get(&obj_field_key) {
531531
None => {
532-
validate_arg_from_type(&obj_field_type, &GsonValue::Null)?;
532+
// If there was no provided key, use "Absent" so all arguments
533+
// always exist in the validated input datat
534+
validate_arg_from_type(&obj_field_type, &GsonValue::Absent)?;
535+
out_map.insert(obj_field_key, GsonValue::Absent);
533536
}
534537
Some(x) => {
535538
let out_val = validate_arg_from_type(&obj_field_type, x)?;

src/transpile.rs

+35-1
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,45 @@ impl MutationEntrypoint<'_> for InsertBuilder {
309309

310310
let values_clause = values_rows_clause.join(", ");
311311

312+
let insert_quoted_block_name = rand_block_name();
313+
let on_conflict_clause = match &self.on_conflict {
314+
Some(on_conflict) => {
315+
let constraint_name = &on_conflict.constraint.name;
316+
let do_update_set_clause = on_conflict
317+
.update_fields
318+
.iter()
319+
.map(|col| {
320+
format!(
321+
"{} = excluded.{}",
322+
quote_ident(&col.name),
323+
quote_ident(&col.name),
324+
)
325+
})
326+
.join(", ");
327+
328+
let conflict_where_clause = on_conflict.filter.to_where_clause(
329+
&insert_quoted_block_name,
330+
&self.table,
331+
param_context,
332+
)?;
333+
334+
format!(
335+
"
336+
on conflict on constraint {constraint_name}
337+
do update set {do_update_set_clause}
338+
where {conflict_where_clause}
339+
",
340+
)
341+
}
342+
None => "".to_string(),
343+
};
344+
312345
Ok(format!(
313346
"
314347
with affected as (
315-
insert into {quoted_schema}.{quoted_table}({referenced_columns_clause})
348+
insert into {quoted_schema}.{quoted_table} as {insert_quoted_block_name} ({referenced_columns_clause})
316349
values {values_clause}
350+
{on_conflict_clause}
317351
returning {selectable_columns_clause}
318352
)
319353
select

0 commit comments

Comments
 (0)