Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 930d0513cd | |||
| cad651dbd8 | |||
| ea9ac8469c | |||
| ebcdb661fa | |||
| c893e29c59 | |||
| 7523431007 |
@ -19,7 +19,7 @@
|
|||||||
{
|
{
|
||||||
"id": "22222222-2222-2222-2222-222222222222",
|
"id": "22222222-2222-2222-2222-222222222222",
|
||||||
"type": "relation",
|
"type": "relation",
|
||||||
"constraint": "fk_order_customer",
|
"constraint": "fk_order_customer_person",
|
||||||
"source_type": "order",
|
"source_type": "order",
|
||||||
"source_columns": [
|
"source_columns": [
|
||||||
"customer_id"
|
"customer_id"
|
||||||
@ -41,8 +41,7 @@
|
|||||||
"destination_type": "order",
|
"destination_type": "order",
|
||||||
"destination_columns": [
|
"destination_columns": [
|
||||||
"id"
|
"id"
|
||||||
],
|
]
|
||||||
"prefix": "lines"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "44444444-4444-4444-4444-444444444444",
|
"id": "44444444-4444-4444-4444-444444444444",
|
||||||
@ -75,6 +74,20 @@
|
|||||||
"type"
|
"type"
|
||||||
],
|
],
|
||||||
"prefix": "target"
|
"prefix": "target"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "66666666-6666-6666-6666-666666666666",
|
||||||
|
"type": "relation",
|
||||||
|
"constraint": "fk_entity_organization",
|
||||||
|
"source_type": "entity",
|
||||||
|
"source_columns": [
|
||||||
|
"organization_id"
|
||||||
|
],
|
||||||
|
"destination_type": "organization",
|
||||||
|
"destination_columns": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"prefix": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"types": [
|
"types": [
|
||||||
@ -283,6 +296,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"email_addresses": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "contact",
|
||||||
|
"properties": {
|
||||||
|
"target": {
|
||||||
|
"$ref": "email_address"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1834,16 +1858,18 @@
|
|||||||
"type": "contact",
|
"type": "contact",
|
||||||
"is_primary": false,
|
"is_primary": false,
|
||||||
"target": {
|
"target": {
|
||||||
"type": "phone_number",
|
"type": "email_address",
|
||||||
"number": "555-0002"
|
"address": "test@example.com"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
],
|
||||||
|
"email_addresses": [
|
||||||
{
|
{
|
||||||
"type": "contact",
|
"type": "contact",
|
||||||
"is_primary": false,
|
"is_primary": false,
|
||||||
"target": {
|
"target": {
|
||||||
"type": "email_address",
|
"type": "email_address",
|
||||||
"address": "test@example.com"
|
"address": "test2@example.com"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -1935,7 +1961,10 @@
|
|||||||
" modified_by",
|
" modified_by",
|
||||||
") VALUES (",
|
") VALUES (",
|
||||||
" NULL,",
|
" NULL,",
|
||||||
" '{\"number\":\"555-0001\",\"type\":\"phone_number\"}',",
|
" '{",
|
||||||
|
" \"number\":\"555-0001\",",
|
||||||
|
" \"type\":\"phone_number\"",
|
||||||
|
" }',",
|
||||||
" '{{uuid:phone1_id}}',",
|
" '{{uuid:phone1_id}}',",
|
||||||
" '{{uuid}}',",
|
" '{{uuid}}',",
|
||||||
" 'create',",
|
" 'create',",
|
||||||
@ -2006,115 +2035,6 @@
|
|||||||
" '00000000-0000-0000-0000-000000000000'",
|
" '00000000-0000-0000-0000-000000000000'",
|
||||||
")"
|
")"
|
||||||
],
|
],
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"entity\" (",
|
|
||||||
" \"created_at\",",
|
|
||||||
" \"created_by\",",
|
|
||||||
" \"id\",",
|
|
||||||
" \"modified_at\",",
|
|
||||||
" \"modified_by\",",
|
|
||||||
" \"type\"",
|
|
||||||
") VALUES (",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" '{{uuid:phone2_id}}',",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" 'phone_number'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"phone_number\" (",
|
|
||||||
" \"number\"",
|
|
||||||
") VALUES (",
|
|
||||||
" '555-0002'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.change (",
|
|
||||||
" \"old\",",
|
|
||||||
" \"new\",",
|
|
||||||
" entity_id,",
|
|
||||||
" id,",
|
|
||||||
" kind,",
|
|
||||||
" modified_at,",
|
|
||||||
" modified_by",
|
|
||||||
") VALUES (",
|
|
||||||
" NULL,",
|
|
||||||
" '{",
|
|
||||||
" \"number\":\"555-0002\",",
|
|
||||||
" \"type\":\"phone_number\"",
|
|
||||||
" }',",
|
|
||||||
" '{{uuid:phone2_id}}',",
|
|
||||||
" '{{uuid}}',",
|
|
||||||
" 'create',",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"entity\" (",
|
|
||||||
" \"created_at\",",
|
|
||||||
" \"created_by\",",
|
|
||||||
" \"id\",",
|
|
||||||
" \"modified_at\",",
|
|
||||||
" \"modified_by\",",
|
|
||||||
" \"type\"",
|
|
||||||
") VALUES (",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" '{{uuid:contact2_id}}',",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" 'contact'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"relationship\" (",
|
|
||||||
" \"source_id\",",
|
|
||||||
" \"source_type\",",
|
|
||||||
" \"target_id\",",
|
|
||||||
" \"target_type\"",
|
|
||||||
") VALUES (",
|
|
||||||
" '{{uuid:person_id}}',",
|
|
||||||
" 'person',",
|
|
||||||
" '{{uuid:phone2_id}}',",
|
|
||||||
" 'phone_number'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"contact\" (",
|
|
||||||
" \"is_primary\"",
|
|
||||||
") VALUES (",
|
|
||||||
" false",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.change (",
|
|
||||||
" \"old\",",
|
|
||||||
" \"new\",",
|
|
||||||
" entity_id,",
|
|
||||||
" id,",
|
|
||||||
" kind,",
|
|
||||||
" modified_at,",
|
|
||||||
" modified_by",
|
|
||||||
") VALUES (",
|
|
||||||
" NULL,",
|
|
||||||
" '{",
|
|
||||||
" \"is_primary\":false,",
|
|
||||||
" \"source_id\":\"{{uuid:person_id}}\",",
|
|
||||||
" \"source_type\":\"person\",",
|
|
||||||
" \"target_id\":\"{{uuid:phone2_id}}\",",
|
|
||||||
" \"target_type\":\"phone_number\",",
|
|
||||||
" \"type\":\"contact\"",
|
|
||||||
" }',",
|
|
||||||
" '{{uuid:contact2_id}}',",
|
|
||||||
" '{{uuid}}',",
|
|
||||||
" 'create',",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
[
|
||||||
"INSERT INTO agreego.\"entity\" (",
|
"INSERT INTO agreego.\"entity\" (",
|
||||||
" \"created_at\",",
|
" \"created_at\",",
|
||||||
@ -2172,7 +2092,7 @@
|
|||||||
") VALUES (",
|
") VALUES (",
|
||||||
" '{{timestamp}}',",
|
" '{{timestamp}}',",
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
" '00000000-0000-0000-0000-000000000000',",
|
||||||
" '{{uuid:contact3_id}}',",
|
" '{{uuid:contact2_id}}',",
|
||||||
" '{{timestamp}}',",
|
" '{{timestamp}}',",
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
" '00000000-0000-0000-0000-000000000000',",
|
||||||
" 'contact'",
|
" 'contact'",
|
||||||
@ -2217,6 +2137,115 @@
|
|||||||
" \"target_type\":\"email_address\",",
|
" \"target_type\":\"email_address\",",
|
||||||
" \"type\":\"contact\"",
|
" \"type\":\"contact\"",
|
||||||
" }',",
|
" }',",
|
||||||
|
" '{{uuid:contact2_id}}',",
|
||||||
|
" '{{uuid}}',",
|
||||||
|
" 'create',",
|
||||||
|
" '{{timestamp}}',",
|
||||||
|
" '00000000-0000-0000-0000-000000000000'",
|
||||||
|
")"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"INSERT INTO agreego.\"entity\" (",
|
||||||
|
" \"created_at\",",
|
||||||
|
" \"created_by\",",
|
||||||
|
" \"id\",",
|
||||||
|
" \"modified_at\",",
|
||||||
|
" \"modified_by\",",
|
||||||
|
" \"type\"",
|
||||||
|
") VALUES (",
|
||||||
|
" '{{timestamp}}',",
|
||||||
|
" '00000000-0000-0000-0000-000000000000',",
|
||||||
|
" '{{uuid:email2_id}}',",
|
||||||
|
" '{{timestamp}}',",
|
||||||
|
" '00000000-0000-0000-0000-000000000000',",
|
||||||
|
" 'email_address'",
|
||||||
|
")"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"INSERT INTO agreego.\"email_address\" (",
|
||||||
|
" \"address\"",
|
||||||
|
") VALUES (",
|
||||||
|
" 'test2@example.com'",
|
||||||
|
")"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"INSERT INTO agreego.change (",
|
||||||
|
" \"old\",",
|
||||||
|
" \"new\",",
|
||||||
|
" entity_id,",
|
||||||
|
" id,",
|
||||||
|
" kind,",
|
||||||
|
" modified_at,",
|
||||||
|
" modified_by",
|
||||||
|
") VALUES (",
|
||||||
|
" NULL,",
|
||||||
|
" '{",
|
||||||
|
" \"address\":\"test2@example.com\",",
|
||||||
|
" \"type\":\"email_address\"",
|
||||||
|
" }',",
|
||||||
|
" '{{uuid:email2_id}}',",
|
||||||
|
" '{{uuid}}',",
|
||||||
|
" 'create',",
|
||||||
|
" '{{timestamp}}',",
|
||||||
|
" '00000000-0000-0000-0000-000000000000'",
|
||||||
|
")"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"INSERT INTO agreego.\"entity\" (",
|
||||||
|
" \"created_at\",",
|
||||||
|
" \"created_by\",",
|
||||||
|
" \"id\",",
|
||||||
|
" \"modified_at\",",
|
||||||
|
" \"modified_by\",",
|
||||||
|
" \"type\"",
|
||||||
|
") VALUES (",
|
||||||
|
" '{{timestamp}}',",
|
||||||
|
" '00000000-0000-0000-0000-000000000000',",
|
||||||
|
" '{{uuid:contact3_id}}',",
|
||||||
|
" '{{timestamp}}',",
|
||||||
|
" '00000000-0000-0000-0000-000000000000',",
|
||||||
|
" 'contact'",
|
||||||
|
")"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"INSERT INTO agreego.\"relationship\" (",
|
||||||
|
" \"source_id\",",
|
||||||
|
" \"source_type\",",
|
||||||
|
" \"target_id\",",
|
||||||
|
" \"target_type\"",
|
||||||
|
") VALUES (",
|
||||||
|
" '{{uuid:person_id}}',",
|
||||||
|
" 'person',",
|
||||||
|
" '{{uuid:email2_id}}',",
|
||||||
|
" 'email_address'",
|
||||||
|
")"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"INSERT INTO agreego.\"contact\" (",
|
||||||
|
" \"is_primary\"",
|
||||||
|
") VALUES (",
|
||||||
|
" false",
|
||||||
|
")"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"INSERT INTO agreego.change (",
|
||||||
|
" \"old\",",
|
||||||
|
" \"new\",",
|
||||||
|
" entity_id,",
|
||||||
|
" id,",
|
||||||
|
" kind,",
|
||||||
|
" modified_at,",
|
||||||
|
" modified_by",
|
||||||
|
") VALUES (",
|
||||||
|
" NULL,",
|
||||||
|
" '{",
|
||||||
|
" \"is_primary\":false,",
|
||||||
|
" \"source_id\":\"{{uuid:person_id}}\",",
|
||||||
|
" \"source_type\":\"person\",",
|
||||||
|
" \"target_id\":\"{{uuid:email2_id}}\",",
|
||||||
|
" \"target_type\":\"email_address\",",
|
||||||
|
" \"type\":\"contact\"",
|
||||||
|
" }',",
|
||||||
" '{{uuid:contact3_id}}',",
|
" '{{uuid:contact3_id}}',",
|
||||||
" '{{uuid}}',",
|
" '{{uuid}}',",
|
||||||
" 'create',",
|
" 'create',",
|
||||||
@ -2319,48 +2348,6 @@
|
|||||||
" \"modified_by\":\"00000000-0000-0000-0000-000000000000\",",
|
" \"modified_by\":\"00000000-0000-0000-0000-000000000000\",",
|
||||||
" \"source_id\":\"{{uuid:person_id}}\",",
|
" \"source_id\":\"{{uuid:person_id}}\",",
|
||||||
" \"source_type\":\"person\",",
|
" \"source_type\":\"person\",",
|
||||||
" \"target_id\":\"{{uuid:phone2_id}}\",",
|
|
||||||
" \"target_type\":\"phone_number\",",
|
|
||||||
" \"type\":\"contact\"",
|
|
||||||
" },",
|
|
||||||
" \"new\":{",
|
|
||||||
" \"is_primary\":false,",
|
|
||||||
" \"source_id\":\"{{uuid:person_id}}\",",
|
|
||||||
" \"source_type\":\"person\",",
|
|
||||||
" \"target_id\":\"{{uuid:phone2_id}}\",",
|
|
||||||
" \"target_type\":\"phone_number\",",
|
|
||||||
" \"type\":\"contact\"",
|
|
||||||
" }",
|
|
||||||
" }')"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"SELECT pg_notify('entity', '{",
|
|
||||||
" \"complete\":{",
|
|
||||||
" \"created_at\":\"{{timestamp}}\",",
|
|
||||||
" \"created_by\":\"00000000-0000-0000-0000-000000000000\",",
|
|
||||||
" \"id\":\"{{uuid:phone2_id}}\",",
|
|
||||||
" \"modified_at\":\"{{timestamp}}\",",
|
|
||||||
" \"modified_by\":\"00000000-0000-0000-0000-000000000000\",",
|
|
||||||
" \"number\":\"555-0002\",",
|
|
||||||
" \"type\":\"phone_number\"",
|
|
||||||
" },",
|
|
||||||
" \"new\":{",
|
|
||||||
" \"number\":\"555-0002\",",
|
|
||||||
" \"type\":\"phone_number\"",
|
|
||||||
" }",
|
|
||||||
" }')"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"SELECT pg_notify('entity', '{",
|
|
||||||
" \"complete\":{",
|
|
||||||
" \"created_at\":\"{{timestamp}}\",",
|
|
||||||
" \"created_by\":\"00000000-0000-0000-0000-000000000000\",",
|
|
||||||
" \"id\":\"{{uuid:contact3_id}}\",",
|
|
||||||
" \"is_primary\":false,",
|
|
||||||
" \"modified_at\":\"{{timestamp}}\",",
|
|
||||||
" \"modified_by\":\"00000000-0000-0000-0000-000000000000\",",
|
|
||||||
" \"source_id\":\"{{uuid:person_id}}\",",
|
|
||||||
" \"source_type\":\"person\",",
|
|
||||||
" \"target_id\":\"{{uuid:email1_id}}\",",
|
" \"target_id\":\"{{uuid:email1_id}}\",",
|
||||||
" \"target_type\":\"email_address\",",
|
" \"target_type\":\"email_address\",",
|
||||||
" \"type\":\"contact\"",
|
" \"type\":\"contact\"",
|
||||||
@ -2373,7 +2360,7 @@
|
|||||||
" \"target_type\":\"email_address\",",
|
" \"target_type\":\"email_address\",",
|
||||||
" \"type\":\"contact\"",
|
" \"type\":\"contact\"",
|
||||||
" }",
|
" }",
|
||||||
" }')"
|
"}')"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"SELECT pg_notify('entity', '{",
|
"SELECT pg_notify('entity', '{",
|
||||||
@ -2390,7 +2377,49 @@
|
|||||||
" \"address\":\"test@example.com\",",
|
" \"address\":\"test@example.com\",",
|
||||||
" \"type\":\"email_address\"",
|
" \"type\":\"email_address\"",
|
||||||
" }",
|
" }",
|
||||||
" }')"
|
"}')"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"SELECT pg_notify('entity', '{",
|
||||||
|
" \"complete\":{",
|
||||||
|
" \"created_at\":\"{{timestamp}}\",",
|
||||||
|
" \"created_by\":\"00000000-0000-0000-0000-000000000000\",",
|
||||||
|
" \"id\":\"{{uuid:contact3_id}}\",",
|
||||||
|
" \"is_primary\":false,",
|
||||||
|
" \"modified_at\":\"{{timestamp}}\",",
|
||||||
|
" \"modified_by\":\"00000000-0000-0000-0000-000000000000\",",
|
||||||
|
" \"source_id\":\"{{uuid:person_id}}\",",
|
||||||
|
" \"source_type\":\"person\",",
|
||||||
|
" \"target_id\":\"{{uuid:email2_id}}\",",
|
||||||
|
" \"target_type\":\"email_address\",",
|
||||||
|
" \"type\":\"contact\"",
|
||||||
|
" },",
|
||||||
|
" \"new\":{",
|
||||||
|
" \"is_primary\":false,",
|
||||||
|
" \"source_id\":\"{{uuid:person_id}}\",",
|
||||||
|
" \"source_type\":\"person\",",
|
||||||
|
" \"target_id\":\"{{uuid:email2_id}}\",",
|
||||||
|
" \"target_type\":\"email_address\",",
|
||||||
|
" \"type\":\"contact\"",
|
||||||
|
" }",
|
||||||
|
"}')"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"SELECT pg_notify('entity', '{",
|
||||||
|
" \"complete\":{",
|
||||||
|
" \"address\":\"test2@example.com\",",
|
||||||
|
" \"created_at\":\"{{timestamp}}\",",
|
||||||
|
" \"created_by\":\"00000000-0000-0000-0000-000000000000\",",
|
||||||
|
" \"id\":\"{{uuid:email2_id}}\",",
|
||||||
|
" \"modified_at\":\"{{timestamp}}\",",
|
||||||
|
" \"modified_by\":\"00000000-0000-0000-0000-000000000000\",",
|
||||||
|
" \"type\":\"email_address\"",
|
||||||
|
" },",
|
||||||
|
" \"new\":{",
|
||||||
|
" \"address\":\"test2@example.com\",",
|
||||||
|
" \"type\":\"email_address\"",
|
||||||
|
" }",
|
||||||
|
"}')"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,7 +71,7 @@
|
|||||||
{
|
{
|
||||||
"id": "22222222-2222-2222-2222-222222222222",
|
"id": "22222222-2222-2222-2222-222222222222",
|
||||||
"type": "relation",
|
"type": "relation",
|
||||||
"constraint": "fk_order_customer",
|
"constraint": "fk_order_customer_person",
|
||||||
"source_type": "order",
|
"source_type": "order",
|
||||||
"source_columns": [
|
"source_columns": [
|
||||||
"customer_id"
|
"customer_id"
|
||||||
@ -79,7 +79,8 @@
|
|||||||
"destination_type": "person",
|
"destination_type": "person",
|
||||||
"destination_columns": [
|
"destination_columns": [
|
||||||
"id"
|
"id"
|
||||||
]
|
],
|
||||||
|
"prefix": "customer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "22222222-2222-2222-2222-222222222227",
|
"id": "22222222-2222-2222-2222-222222222227",
|
||||||
|
|||||||
@ -79,9 +79,9 @@ impl DatabaseExecutor for SpiExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pgrx::debug1!("JSPG_SQL: {}", sql);
|
||||||
self.transact(|| {
|
self.transact(|| {
|
||||||
Spi::connect(|client| {
|
Spi::connect(|client| {
|
||||||
pgrx::notice!("JSPG_SQL: {}", sql);
|
|
||||||
match client.select(sql, Some(args_with_oid.len() as i64), &args_with_oid) {
|
match client.select(sql, Some(args_with_oid.len() as i64), &args_with_oid) {
|
||||||
Ok(tup_table) => {
|
Ok(tup_table) => {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
@ -110,9 +110,9 @@ impl DatabaseExecutor for SpiExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pgrx::debug1!("JSPG_SQL: {}", sql);
|
||||||
self.transact(|| {
|
self.transact(|| {
|
||||||
Spi::connect_mut(|client| {
|
Spi::connect_mut(|client| {
|
||||||
pgrx::notice!("JSPG_SQL: {}", sql);
|
|
||||||
match client.update(sql, Some(args_with_oid.len() as i64), &args_with_oid) {
|
match client.update(sql, Some(args_with_oid.len() as i64), &args_with_oid) {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(e) => Err(format!("SPI Execution Failure: {}", e)),
|
Err(e) => Err(format!("SPI Execution Failure: {}", e)),
|
||||||
|
|||||||
@ -508,7 +508,7 @@ impl Schema {
|
|||||||
if let Some(family) = &self.obj.family {
|
if let Some(family) = &self.obj.family {
|
||||||
parent_type_name = Some(family.split('.').next_back().unwrap_or(family).to_string());
|
parent_type_name = Some(family.split('.').next_back().unwrap_or(family).to_string());
|
||||||
} else if let Some(identifier) = self.obj.identifier() {
|
} else if let Some(identifier) = self.obj.identifier() {
|
||||||
parent_type_name = Some(identifier);
|
parent_type_name = Some(identifier.split('.').next_back().unwrap_or(&identifier).to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(p_type) = parent_type_name {
|
if let Some(p_type) = parent_type_name {
|
||||||
@ -530,11 +530,11 @@ impl Schema {
|
|||||||
if let Some(family) = &target_schema.obj.family {
|
if let Some(family) = &target_schema.obj.family {
|
||||||
child_type_name = Some(family.split('.').next_back().unwrap_or(family).to_string());
|
child_type_name = Some(family.split('.').next_back().unwrap_or(family).to_string());
|
||||||
} else if let Some(ref_id) = target_schema.obj.identifier() {
|
} else if let Some(ref_id) = target_schema.obj.identifier() {
|
||||||
child_type_name = Some(ref_id);
|
child_type_name = Some(ref_id.split('.').next_back().unwrap_or(&ref_id).to_string());
|
||||||
} else if let Some(arr) = &target_schema.obj.one_of {
|
} else if let Some(arr) = &target_schema.obj.one_of {
|
||||||
if let Some(first) = arr.first() {
|
if let Some(first) = arr.first() {
|
||||||
if let Some(ref_id) = first.obj.identifier() {
|
if let Some(ref_id) = first.obj.identifier() {
|
||||||
child_type_name = Some(ref_id);
|
child_type_name = Some(ref_id.split('.').next_back().unwrap_or(&ref_id).to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -622,8 +622,43 @@ pub(crate) fn resolve_relation<'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !resolved && relative_keys.is_some() {
|
||||||
|
// 1. M:M Disambiguation: The child schema explicitly defines an outbound property
|
||||||
|
// matching one of the relational prefixes (e.g. "target"). We first identify that consumed relation.
|
||||||
|
let keys = relative_keys.unwrap();
|
||||||
|
let mut consumed_rel_idx = None;
|
||||||
|
for (i, rel) in matching_rels.iter().enumerate() {
|
||||||
|
if let Some(prefix) = &rel.prefix {
|
||||||
|
if keys.contains(prefix) {
|
||||||
|
consumed_rel_idx = Some(i);
|
||||||
|
break; // Found the routing edge explicitly consumed by the schema payload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then, we find its exact Twin on the same junction boundary that provides the reverse ownership.
|
||||||
|
if let Some(used_idx) = consumed_rel_idx {
|
||||||
|
let used_rel = matching_rels[used_idx];
|
||||||
|
let mut twin_ids = Vec::new();
|
||||||
|
for (i, rel) in matching_rels.iter().enumerate() {
|
||||||
|
if i != used_idx
|
||||||
|
&& rel.source_type == used_rel.source_type
|
||||||
|
&& rel.destination_type == used_rel.destination_type
|
||||||
|
&& rel.prefix.is_some()
|
||||||
|
{
|
||||||
|
twin_ids.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if twin_ids.len() == 1 {
|
||||||
|
chosen_idx = twin_ids[0];
|
||||||
|
resolved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !resolved {
|
if !resolved {
|
||||||
// 1. If there's EXACTLY ONE relation with a null prefix, it's the base structural edge. Pick it.
|
// 2. Base 1:M Fallback. If there's EXACTLY ONE relation with a null prefix, it's the base structural edge.
|
||||||
let mut null_prefix_ids = Vec::new();
|
let mut null_prefix_ids = Vec::new();
|
||||||
for (i, rel) in matching_rels.iter().enumerate() {
|
for (i, rel) in matching_rels.iter().enumerate() {
|
||||||
if rel.prefix.is_none() {
|
if rel.prefix.is_none() {
|
||||||
@ -632,24 +667,6 @@ pub(crate) fn resolve_relation<'a>(
|
|||||||
}
|
}
|
||||||
if null_prefix_ids.len() == 1 {
|
if null_prefix_ids.len() == 1 {
|
||||||
chosen_idx = null_prefix_ids[0];
|
chosen_idx = null_prefix_ids[0];
|
||||||
resolved = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !resolved && relative_keys.is_some() {
|
|
||||||
// 2. M:M Disambiguation: The child schema will explicitly define an outbound property
|
|
||||||
// matching one of the relational prefixes (e.g. "target"). We use the OTHER one (e.g. "source").
|
|
||||||
let keys = relative_keys.unwrap();
|
|
||||||
let mut missing_prefix_ids = Vec::new();
|
|
||||||
for (i, rel) in matching_rels.iter().enumerate() {
|
|
||||||
if let Some(prefix) = &rel.prefix {
|
|
||||||
if !keys.contains(prefix) {
|
|
||||||
missing_prefix_ids.push(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if missing_prefix_ids.len() == 1 {
|
|
||||||
chosen_idx = missing_prefix_ids[0];
|
|
||||||
// resolved = true;
|
// resolved = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
pub mod cache;
|
pub mod cache;
|
||||||
|
|
||||||
use crate::database::r#type::Type;
|
|
||||||
use crate::database::Database;
|
use crate::database::Database;
|
||||||
|
use crate::database::r#type::Type;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -50,15 +50,21 @@ impl Merger {
|
|||||||
let mut final_cause = None;
|
let mut final_cause = None;
|
||||||
|
|
||||||
if let Ok(Value::Object(map)) = serde_json::from_str::<Value>(&msg) {
|
if let Ok(Value::Object(map)) = serde_json::from_str::<Value>(&msg) {
|
||||||
if let (Some(Value::String(e_msg)), Some(Value::String(e_code))) = (map.get("error"), map.get("code")) {
|
if let (Some(Value::String(e_msg)), Some(Value::String(e_code))) =
|
||||||
|
(map.get("error"), map.get("code"))
|
||||||
|
{
|
||||||
final_message = e_msg.clone();
|
final_message = e_msg.clone();
|
||||||
final_code = e_code.clone();
|
final_code = e_code.clone();
|
||||||
let mut cause_parts = Vec::new();
|
let mut cause_parts = Vec::new();
|
||||||
if let Some(Value::String(d)) = map.get("detail") {
|
if let Some(Value::String(d)) = map.get("detail") {
|
||||||
if !d.is_empty() { cause_parts.push(d.clone()); }
|
if !d.is_empty() {
|
||||||
|
cause_parts.push(d.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let Some(Value::String(h)) = map.get("hint") {
|
if let Some(Value::String(h)) = map.get("hint") {
|
||||||
if !h.is_empty() { cause_parts.push(h.clone()); }
|
if !h.is_empty() {
|
||||||
|
cause_parts.push(h.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if !cause_parts.is_empty() {
|
if !cause_parts.is_empty() {
|
||||||
final_cause = Some(cause_parts.join("\n"));
|
final_cause = Some(cause_parts.join("\n"));
|
||||||
@ -253,7 +259,11 @@ impl Merger {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(compiled_edges) = schema.obj.compiled_edges.get() {
|
if let Some(compiled_edges) = schema.obj.compiled_edges.get() {
|
||||||
println!("Compiled Edges keys for relation {}: {:?}", relation_name, compiled_edges.keys().collect::<Vec<_>>());
|
println!(
|
||||||
|
"Compiled Edges keys for relation {}: {:?}",
|
||||||
|
relation_name,
|
||||||
|
compiled_edges.keys().collect::<Vec<_>>()
|
||||||
|
);
|
||||||
if let Some(edge) = compiled_edges.get(&relation_name) {
|
if let Some(edge) = compiled_edges.get(&relation_name) {
|
||||||
println!("FOUND EDGE {} -> {:?}", relation_name, edge.constraint);
|
println!("FOUND EDGE {} -> {:?}", relation_name, edge.constraint);
|
||||||
if let Some(relation) = self.db.relations.get(&edge.constraint) {
|
if let Some(relation) = self.db.relations.get(&edge.constraint) {
|
||||||
@ -266,15 +276,16 @@ impl Merger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut merged_relative = match self.merge_internal(rel_schema.clone(), Value::Object(relative), notifications)? {
|
let mut merged_relative = match self.merge_internal(
|
||||||
|
rel_schema.clone(),
|
||||||
|
Value::Object(relative),
|
||||||
|
notifications,
|
||||||
|
)? {
|
||||||
Value::Object(m) => m,
|
Value::Object(m) => m,
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
merged_relative.insert(
|
merged_relative.insert("type".to_string(), Value::String(relative_type_name));
|
||||||
"type".to_string(),
|
|
||||||
Value::String(relative_type_name),
|
|
||||||
);
|
|
||||||
|
|
||||||
Self::apply_entity_relation(
|
Self::apply_entity_relation(
|
||||||
&mut entity_fields,
|
&mut entity_fields,
|
||||||
@ -297,7 +308,11 @@ impl Merger {
|
|||||||
&entity_fields,
|
&entity_fields,
|
||||||
);
|
);
|
||||||
|
|
||||||
let merged_relative = match self.merge_internal(rel_schema.clone(), Value::Object(relative), notifications)? {
|
let merged_relative = match self.merge_internal(
|
||||||
|
rel_schema.clone(),
|
||||||
|
Value::Object(relative),
|
||||||
|
notifications,
|
||||||
|
)? {
|
||||||
Value::Object(m) => m,
|
Value::Object(m) => m,
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
@ -360,7 +375,9 @@ impl Merger {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let mut item_schema = rel_schema.clone();
|
let mut item_schema = rel_schema.clone();
|
||||||
if let Some(crate::database::schema::SchemaTypeOrArray::Single(t)) = &rel_schema.obj.type_ {
|
if let Some(crate::database::schema::SchemaTypeOrArray::Single(t)) =
|
||||||
|
&rel_schema.obj.type_
|
||||||
|
{
|
||||||
if t == "array" {
|
if t == "array" {
|
||||||
if let Some(items_def) = &rel_schema.obj.items {
|
if let Some(items_def) = &rel_schema.obj.items {
|
||||||
item_schema = items_def.clone();
|
item_schema = items_def.clone();
|
||||||
@ -368,8 +385,11 @@ impl Merger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let merged_relative =
|
let merged_relative = match self.merge_internal(
|
||||||
match self.merge_internal(item_schema, Value::Object(relative_item), notifications)? {
|
item_schema,
|
||||||
|
Value::Object(relative_item),
|
||||||
|
notifications,
|
||||||
|
)? {
|
||||||
Value::Object(m) => m,
|
Value::Object(m) => m,
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
@ -548,7 +568,12 @@ impl Merger {
|
|||||||
entity_fields = new_fields;
|
entity_fields = new_fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((entity_fields, entity_change_kind, entity_fetched, replaces_id))
|
Ok((
|
||||||
|
entity_fields,
|
||||||
|
entity_change_kind,
|
||||||
|
entity_fetched,
|
||||||
|
replaces_id,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_entity(
|
fn fetch_entity(
|
||||||
@ -735,9 +760,7 @@ impl Merger {
|
|||||||
columns.join(", "),
|
columns.join(", "),
|
||||||
values.join(", ")
|
values.join(", ")
|
||||||
);
|
);
|
||||||
self
|
self.db.execute(&sql, None)?;
|
||||||
.db
|
|
||||||
.execute(&sql, None)?;
|
|
||||||
} else if change_kind == "update" || change_kind == "delete" {
|
} else if change_kind == "update" || change_kind == "delete" {
|
||||||
entity_pairs.remove("id");
|
entity_pairs.remove("id");
|
||||||
entity_pairs.remove("type");
|
entity_pairs.remove("type");
|
||||||
@ -769,9 +792,7 @@ impl Merger {
|
|||||||
set_clauses.join(", "),
|
set_clauses.join(", "),
|
||||||
Self::quote_literal(&Value::String(id_str.to_string()))
|
Self::quote_literal(&Value::String(id_str.to_string()))
|
||||||
);
|
);
|
||||||
self
|
self.db.execute(&sql, None)?;
|
||||||
.db
|
|
||||||
.execute(&sql, None)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user