Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| abf1d12e43 | |||
| a885713563 | |||
| d9b4f417f6 |
@ -1320,62 +1320,17 @@
|
|||||||
" AND \"pronouns\" = 'they/them'))"
|
" AND \"pronouns\" = 'they/them'))"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"INSERT INTO agreego.\"entity\" (",
|
"UPDATE agreego.\"entity\" SET",
|
||||||
" \"created_at\",",
|
" modified_at = '{{timestamp}}',",
|
||||||
" \"created_by\",",
|
" modified_by = '00000000-0000-0000-0000-000000000000'",
|
||||||
" \"id\",",
|
"WHERE",
|
||||||
" \"modified_at\",",
|
" id = '{{uuid:mocks.0.id}}'"
|
||||||
" \"modified_by\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" '{{uuid:generated_0}}',",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"INSERT INTO agreego.\"organization\" (",
|
"UPDATE agreego.\"person\" SET",
|
||||||
" \"id\",",
|
" contact_id = 'abc-contact'",
|
||||||
" \"type\"",
|
"WHERE",
|
||||||
")",
|
" id = '{{uuid:mocks.0.id}}'"
|
||||||
"VALUES (",
|
|
||||||
" '{{uuid:generated_0}}',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"user\" (",
|
|
||||||
" \"id\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" '{{uuid:generated_0}}',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"person\" (",
|
|
||||||
" \"contact_id\",",
|
|
||||||
" \"date_of_birth\",",
|
|
||||||
" \"first_name\",",
|
|
||||||
" \"id\",",
|
|
||||||
" \"last_name\",",
|
|
||||||
" \"pronouns\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" 'abc-contact',",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" 'LookupFirst',",
|
|
||||||
" '{{uuid:generated_0}}',",
|
|
||||||
" 'LookupLast',",
|
|
||||||
" 'they/them',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"INSERT INTO agreego.change (",
|
"INSERT INTO agreego.change (",
|
||||||
@ -1388,45 +1343,40 @@
|
|||||||
" \"modified_by\"",
|
" \"modified_by\"",
|
||||||
")",
|
")",
|
||||||
"VALUES (",
|
"VALUES (",
|
||||||
" NULL,",
|
|
||||||
" '{",
|
" '{",
|
||||||
" \"first_name\": \"LookupFirst\",",
|
" \"contact_id\": \"old-contact\"",
|
||||||
" \"last_name\": \"LookupLast\",",
|
" }',",
|
||||||
" \"date_of_birth\": \"{{timestamp}}\",",
|
" '{",
|
||||||
" \"pronouns\": \"they/them\",",
|
|
||||||
" \"contact_id\": \"abc-contact\",",
|
" \"contact_id\": \"abc-contact\",",
|
||||||
" \"type\": \"person\"",
|
" \"type\": \"person\"",
|
||||||
" }',",
|
" }',",
|
||||||
|
" '{{uuid:mocks.0.id}}',",
|
||||||
" '{{uuid:generated_0}}',",
|
" '{{uuid:generated_0}}',",
|
||||||
" '{{uuid:generated_1}}',",
|
" 'update',",
|
||||||
" 'create',",
|
|
||||||
" '{{timestamp}}',",
|
" '{{timestamp}}',",
|
||||||
" '00000000-0000-0000-0000-000000000000'",
|
" '00000000-0000-0000-0000-000000000000'",
|
||||||
")"
|
")"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"(SELECT pg_notify('entity', '{",
|
"(SELECT pg_notify('entity', '{",
|
||||||
" \"kind\": \"create\",",
|
" \"kind\": \"update\",",
|
||||||
" \"complete\": {",
|
" \"complete\": {",
|
||||||
|
" \"id\": \"{{uuid:mocks.0.id}}\",",
|
||||||
|
" \"type\": \"person\",",
|
||||||
" \"first_name\": \"LookupFirst\",",
|
" \"first_name\": \"LookupFirst\",",
|
||||||
" \"last_name\": \"LookupLast\",",
|
" \"last_name\": \"LookupLast\",",
|
||||||
" \"date_of_birth\": \"{{timestamp}}\",",
|
" \"date_of_birth\": \"{{timestamp}}\",",
|
||||||
" \"pronouns\": \"they/them\",",
|
" \"pronouns\": \"they/them\",",
|
||||||
" \"contact_id\": \"abc-contact\",",
|
" \"contact_id\": \"abc-contact\",",
|
||||||
" \"id\": \"{{uuid:generated_0}}\",",
|
|
||||||
" \"type\": \"person\",",
|
|
||||||
" \"created_by\": \"00000000-0000-0000-0000-000000000000\",",
|
|
||||||
" \"created_at\": \"{{timestamp}}\",",
|
|
||||||
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
|
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
|
||||||
" \"modified_at\": \"{{timestamp}}\"",
|
" \"modified_at\": \"{{timestamp}}\"",
|
||||||
" },",
|
" },",
|
||||||
" \"new\": {",
|
" \"new\": {",
|
||||||
" \"first_name\": \"LookupFirst\",",
|
|
||||||
" \"last_name\": \"LookupLast\",",
|
|
||||||
" \"date_of_birth\": \"{{timestamp}}\",",
|
|
||||||
" \"pronouns\": \"they/them\",",
|
|
||||||
" \"contact_id\": \"abc-contact\",",
|
" \"contact_id\": \"abc-contact\",",
|
||||||
" \"type\": \"person\"",
|
" \"type\": \"person\"",
|
||||||
|
" },",
|
||||||
|
" \"old\": {",
|
||||||
|
" \"contact_id\": \"old-contact\"",
|
||||||
" }",
|
" }",
|
||||||
"}'))"
|
"}'))"
|
||||||
]
|
]
|
||||||
@ -1461,75 +1411,20 @@
|
|||||||
"success": true,
|
"success": true,
|
||||||
"sql": [
|
"sql": [
|
||||||
[
|
[
|
||||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
|
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*) FROM agreego.\"entity\" t1 LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id WHERE t1.id = '{{uuid:data.id}}' UNION SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*) FROM agreego.\"entity\" t1 LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id WHERE (\"first_name\" = 'LookupFirst' AND \"last_name\" = 'LookupLast' AND \"date_of_birth\" = '{{timestamp}}' AND \"pronouns\" = 'they/them'))"
|
||||||
"FROM agreego.\"entity\" t1",
|
],
|
||||||
"JOIN agreego.\"organization\" t2 ON ",
|
[
|
||||||
"JOIN agreego.\"user\" t3 ON ",
|
"UPDATE agreego.\"entity\" SET",
|
||||||
"JOIN agreego.\"person\" t4 ON ",
|
" modified_at = '{{timestamp}}',",
|
||||||
|
" modified_by = '00000000-0000-0000-0000-000000000000'",
|
||||||
"WHERE",
|
"WHERE",
|
||||||
" t1.id = '{{uuid:data.id}}'",
|
" id = '{{uuid:mocks.0.id}}'"
|
||||||
" OR (\"first_name\" = 'LookupFirst'",
|
|
||||||
" AND \"last_name\" = 'LookupLast'",
|
|
||||||
" AND \"date_of_birth\" = '{{timestamp}}'",
|
|
||||||
" AND \"pronouns\" = 'they/them'))"
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"INSERT INTO agreego.\"entity\" (",
|
"UPDATE agreego.\"person\" SET",
|
||||||
" \"created_at\",",
|
" contact_id = 'abc-contact'",
|
||||||
" \"created_by\",",
|
"WHERE",
|
||||||
" \"id\",",
|
" id = '{{uuid:mocks.0.id}}'"
|
||||||
" \"modified_at\",",
|
|
||||||
" \"modified_by\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" '{{uuid:data.id}}',",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"organization\" (",
|
|
||||||
" \"id\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" '{{uuid:data.id}}',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"user\" (",
|
|
||||||
" \"id\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" '{{uuid:data.id}}',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"person\" (",
|
|
||||||
" \"contact_id\",",
|
|
||||||
" \"date_of_birth\",",
|
|
||||||
" \"first_name\",",
|
|
||||||
" \"id\",",
|
|
||||||
" \"last_name\",",
|
|
||||||
" \"pronouns\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" 'abc-contact',",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" 'LookupFirst',",
|
|
||||||
" '{{uuid:data.id}}',",
|
|
||||||
" 'LookupLast',",
|
|
||||||
" 'they/them',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"INSERT INTO agreego.change (",
|
"INSERT INTO agreego.change (",
|
||||||
@ -1542,46 +1437,42 @@
|
|||||||
" \"modified_by\"",
|
" \"modified_by\"",
|
||||||
")",
|
")",
|
||||||
"VALUES (",
|
"VALUES (",
|
||||||
" NULL,",
|
|
||||||
" '{",
|
" '{",
|
||||||
" \"first_name\": \"LookupFirst\",",
|
" \"contact_id\": \"old-contact\"",
|
||||||
" \"last_name\": \"LookupLast\",",
|
" }',",
|
||||||
" \"date_of_birth\": \"{{timestamp}}\",",
|
" '{",
|
||||||
" \"pronouns\": \"they/them\",",
|
|
||||||
" \"contact_id\": \"abc-contact\",",
|
" \"contact_id\": \"abc-contact\",",
|
||||||
" \"type\": \"person\"",
|
" \"type\": \"person\"",
|
||||||
" }',",
|
" }',",
|
||||||
" '{{uuid:data.id}}',",
|
" '{{uuid:mocks.0.id}}',",
|
||||||
" '{{uuid:generated_0}}',",
|
" '{{uuid:generated_0}}',",
|
||||||
" 'create',",
|
" 'update',",
|
||||||
" '{{timestamp}}',",
|
" '{{timestamp}}',",
|
||||||
" '00000000-0000-0000-0000-000000000000'",
|
" '00000000-0000-0000-0000-000000000000'",
|
||||||
")"
|
")"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"(SELECT pg_notify('entity', '{",
|
"(SELECT pg_notify('entity', '{",
|
||||||
" \"kind\": \"create\",",
|
" \"kind\": \"update\",",
|
||||||
" \"complete\": {",
|
" \"complete\": {",
|
||||||
|
" \"id\": \"{{uuid:mocks.0.id}}\",",
|
||||||
|
" \"type\": \"person\",",
|
||||||
" \"first_name\": \"LookupFirst\",",
|
" \"first_name\": \"LookupFirst\",",
|
||||||
" \"last_name\": \"LookupLast\",",
|
" \"last_name\": \"LookupLast\",",
|
||||||
" \"date_of_birth\": \"{{timestamp}}\",",
|
" \"date_of_birth\": \"{{timestamp}}\",",
|
||||||
" \"pronouns\": \"they/them\",",
|
" \"pronouns\": \"they/them\",",
|
||||||
" \"contact_id\": \"abc-contact\",",
|
" \"contact_id\": \"abc-contact\",",
|
||||||
" \"id\": \"{{uuid:data.id}}\",",
|
|
||||||
" \"type\": \"person\",",
|
|
||||||
" \"created_by\": \"00000000-0000-0000-0000-000000000000\",",
|
|
||||||
" \"created_at\": \"{{timestamp}}\",",
|
|
||||||
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
|
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
|
||||||
" \"modified_at\": \"{{timestamp}}\"",
|
" \"modified_at\": \"{{timestamp}}\"",
|
||||||
" },",
|
" },",
|
||||||
" \"new\": {",
|
" \"new\": {",
|
||||||
" \"first_name\": \"LookupFirst\",",
|
|
||||||
" \"last_name\": \"LookupLast\",",
|
|
||||||
" \"date_of_birth\": \"{{timestamp}}\",",
|
|
||||||
" \"pronouns\": \"they/them\",",
|
|
||||||
" \"contact_id\": \"abc-contact\",",
|
" \"contact_id\": \"abc-contact\",",
|
||||||
" \"type\": \"person\"",
|
" \"type\": \"person\"",
|
||||||
" }",
|
" },",
|
||||||
|
" \"old\": {",
|
||||||
|
" \"contact_id\": \"old-contact\"",
|
||||||
|
" },",
|
||||||
|
" \"replaces\": \"{{uuid:data.id}}\"",
|
||||||
"}'))"
|
"}'))"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -1614,122 +1505,26 @@
|
|||||||
"success": true,
|
"success": true,
|
||||||
"sql": [
|
"sql": [
|
||||||
[
|
[
|
||||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
|
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*) FROM agreego.\"entity\" t1 LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id WHERE t1.id = '{{uuid:data.id}}' UNION SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*) FROM agreego.\"entity\" t1 LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id WHERE (\"first_name\" = 'LookupFirst' AND \"last_name\" = 'LookupLast' AND \"date_of_birth\" = '{{timestamp}}' AND \"pronouns\" = 'they/them'))"
|
||||||
"FROM agreego.\"entity\" t1",
|
|
||||||
"JOIN agreego.\"organization\" t2 ON ",
|
|
||||||
"JOIN agreego.\"user\" t3 ON ",
|
|
||||||
"JOIN agreego.\"person\" t4 ON ",
|
|
||||||
"WHERE",
|
|
||||||
" t1.id = '{{uuid:data.id}}'",
|
|
||||||
" OR (\"first_name\" = 'LookupFirst'",
|
|
||||||
" AND \"last_name\" = 'LookupLast'",
|
|
||||||
" AND \"date_of_birth\" = '{{timestamp}}'",
|
|
||||||
" AND \"pronouns\" = 'they/them'))"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"entity\" (",
|
|
||||||
" \"created_at\",",
|
|
||||||
" \"created_by\",",
|
|
||||||
" \"id\",",
|
|
||||||
" \"modified_at\",",
|
|
||||||
" \"modified_by\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" '{{uuid:data.id}}',",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"organization\" (",
|
|
||||||
" \"id\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" '{{uuid:data.id}}',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"user\" (",
|
|
||||||
" \"id\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" '{{uuid:data.id}}',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"person\" (",
|
|
||||||
" \"date_of_birth\",",
|
|
||||||
" \"first_name\",",
|
|
||||||
" \"id\",",
|
|
||||||
" \"last_name\",",
|
|
||||||
" \"pronouns\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" 'LookupFirst',",
|
|
||||||
" '{{uuid:data.id}}',",
|
|
||||||
" 'LookupLast',",
|
|
||||||
" 'they/them',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.change (",
|
|
||||||
" \"old\",",
|
|
||||||
" \"new\",",
|
|
||||||
" \"entity_id\",",
|
|
||||||
" \"id\",",
|
|
||||||
" \"kind\",",
|
|
||||||
" \"modified_at\",",
|
|
||||||
" \"modified_by\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" NULL,",
|
|
||||||
" '{",
|
|
||||||
" \"first_name\": \"LookupFirst\",",
|
|
||||||
" \"last_name\": \"LookupLast\",",
|
|
||||||
" \"date_of_birth\": \"{{timestamp}}\",",
|
|
||||||
" \"pronouns\": \"they/them\",",
|
|
||||||
" \"type\": \"person\"",
|
|
||||||
" }',",
|
|
||||||
" '{{uuid:data.id}}',",
|
|
||||||
" '{{uuid:generated_0}}',",
|
|
||||||
" 'create',",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000'",
|
|
||||||
")"
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"(SELECT pg_notify('entity', '{",
|
"(SELECT pg_notify('entity', '{",
|
||||||
" \"kind\": \"create\",",
|
" \"kind\": \"replace\",",
|
||||||
" \"complete\": {",
|
" \"complete\": {",
|
||||||
|
" \"id\": \"{{uuid:mocks.0.id}}\",",
|
||||||
|
" \"type\": \"person\",",
|
||||||
" \"first_name\": \"LookupFirst\",",
|
" \"first_name\": \"LookupFirst\",",
|
||||||
" \"last_name\": \"LookupLast\",",
|
" \"last_name\": \"LookupLast\",",
|
||||||
" \"date_of_birth\": \"{{timestamp}}\",",
|
" \"date_of_birth\": \"{{timestamp}}\",",
|
||||||
" \"pronouns\": \"they/them\",",
|
" \"pronouns\": \"they/them\",",
|
||||||
" \"id\": \"{{uuid:data.id}}\",",
|
" \"contact_id\": \"old-contact\",",
|
||||||
" \"type\": \"person\",",
|
|
||||||
" \"created_by\": \"00000000-0000-0000-0000-000000000000\",",
|
|
||||||
" \"created_at\": \"{{timestamp}}\",",
|
|
||||||
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
|
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
|
||||||
" \"modified_at\": \"{{timestamp}}\"",
|
" \"modified_at\": \"{{timestamp}}\"",
|
||||||
" },",
|
" },",
|
||||||
" \"new\": {",
|
" \"new\": {",
|
||||||
" \"first_name\": \"LookupFirst\",",
|
|
||||||
" \"last_name\": \"LookupLast\",",
|
|
||||||
" \"date_of_birth\": \"{{timestamp}}\",",
|
|
||||||
" \"pronouns\": \"they/them\",",
|
|
||||||
" \"type\": \"person\"",
|
" \"type\": \"person\"",
|
||||||
" }",
|
" },",
|
||||||
|
" \"replaces\": \"{{uuid:data.id}}\"",
|
||||||
"}'))"
|
"}'))"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -1766,56 +1561,18 @@
|
|||||||
" t1.id = '{{uuid:mocks.0.id}}')"
|
" t1.id = '{{uuid:mocks.0.id}}')"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"INSERT INTO agreego.\"entity\" (",
|
"UPDATE agreego.\"entity\" SET",
|
||||||
" \"created_at\",",
|
" modified_at = '{{timestamp}}',",
|
||||||
" \"created_by\",",
|
" modified_by = '00000000-0000-0000-0000-000000000000'",
|
||||||
" \"id\",",
|
"WHERE",
|
||||||
" \"modified_at\",",
|
" id = '{{uuid:mocks.0.id}}'"
|
||||||
" \"modified_by\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" '{{uuid:mocks.0.id}}',",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"INSERT INTO agreego.\"organization\" (",
|
"UPDATE agreego.\"person\" SET",
|
||||||
" \"id\",",
|
" first_name = 'NewFirst',",
|
||||||
" \"type\"",
|
" last_name = 'NewLast'",
|
||||||
")",
|
"WHERE",
|
||||||
"VALUES (",
|
" id = '{{uuid:mocks.0.id}}'"
|
||||||
" '{{uuid:mocks.0.id}}',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"user\" (",
|
|
||||||
" \"id\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" '{{uuid:mocks.0.id}}',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"person\" (",
|
|
||||||
" \"first_name\",",
|
|
||||||
" \"id\",",
|
|
||||||
" \"last_name\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" 'NewFirst',",
|
|
||||||
" '{{uuid:mocks.0.id}}',",
|
|
||||||
" 'NewLast',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"INSERT INTO agreego.change (",
|
"INSERT INTO agreego.change (",
|
||||||
@ -1828,7 +1585,10 @@
|
|||||||
" \"modified_by\"",
|
" \"modified_by\"",
|
||||||
")",
|
")",
|
||||||
"VALUES (",
|
"VALUES (",
|
||||||
" NULL,",
|
" '{",
|
||||||
|
" \"first_name\": \"OldFirst\",",
|
||||||
|
" \"last_name\": \"OldLast\"",
|
||||||
|
" }',",
|
||||||
" '{",
|
" '{",
|
||||||
" \"first_name\": \"NewFirst\",",
|
" \"first_name\": \"NewFirst\",",
|
||||||
" \"last_name\": \"NewLast\",",
|
" \"last_name\": \"NewLast\",",
|
||||||
@ -1836,21 +1596,19 @@
|
|||||||
" }',",
|
" }',",
|
||||||
" '{{uuid:mocks.0.id}}',",
|
" '{{uuid:mocks.0.id}}',",
|
||||||
" '{{uuid:generated_0}}',",
|
" '{{uuid:generated_0}}',",
|
||||||
" 'create',",
|
" 'update',",
|
||||||
" '{{timestamp}}',",
|
" '{{timestamp}}',",
|
||||||
" '00000000-0000-0000-0000-000000000000'",
|
" '00000000-0000-0000-0000-000000000000'",
|
||||||
")"
|
")"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"(SELECT pg_notify('entity', '{",
|
"(SELECT pg_notify('entity', '{",
|
||||||
" \"kind\": \"create\",",
|
" \"kind\": \"update\",",
|
||||||
" \"complete\": {",
|
" \"complete\": {",
|
||||||
" \"first_name\": \"NewFirst\",",
|
|
||||||
" \"last_name\": \"NewLast\",",
|
|
||||||
" \"id\": \"{{uuid:mocks.0.id}}\",",
|
" \"id\": \"{{uuid:mocks.0.id}}\",",
|
||||||
" \"type\": \"person\",",
|
" \"type\": \"person\",",
|
||||||
" \"created_by\": \"00000000-0000-0000-0000-000000000000\",",
|
" \"first_name\": \"NewFirst\",",
|
||||||
" \"created_at\": \"{{timestamp}}\",",
|
" \"last_name\": \"NewLast\",",
|
||||||
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
|
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
|
||||||
" \"modified_at\": \"{{timestamp}}\"",
|
" \"modified_at\": \"{{timestamp}}\"",
|
||||||
" },",
|
" },",
|
||||||
@ -1858,6 +1616,10 @@
|
|||||||
" \"first_name\": \"NewFirst\",",
|
" \"first_name\": \"NewFirst\",",
|
||||||
" \"last_name\": \"NewLast\",",
|
" \"last_name\": \"NewLast\",",
|
||||||
" \"type\": \"person\"",
|
" \"type\": \"person\"",
|
||||||
|
" },",
|
||||||
|
" \"old\": {",
|
||||||
|
" \"first_name\": \"OldFirst\",",
|
||||||
|
" \"last_name\": \"OldLast\"",
|
||||||
" }",
|
" }",
|
||||||
"}'))"
|
"}'))"
|
||||||
]
|
]
|
||||||
@ -2219,12 +1981,7 @@
|
|||||||
"success": true,
|
"success": true,
|
||||||
"sql": [
|
"sql": [
|
||||||
[
|
[
|
||||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)",
|
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) FROM agreego.\"entity\" t1 LEFT JOIN agreego.\"order\" t2 ON t2.id = t1.id WHERE t1.id = 'abc' UNION SELECT to_jsonb(t1.*) || to_jsonb(t2.*) FROM agreego.\"entity\" t1 LEFT JOIN agreego.\"order\" t2 ON t2.id = t1.id WHERE (\"id\" = 'abc'))"
|
||||||
"FROM agreego.\"entity\" t1",
|
|
||||||
"JOIN agreego.\"order\" t2 ON ",
|
|
||||||
"WHERE",
|
|
||||||
" t1.id = 'abc'",
|
|
||||||
" OR (\"id\" = 'abc'))"
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"INSERT INTO agreego.\"entity\" (",
|
"INSERT INTO agreego.\"entity\" (",
|
||||||
@ -3031,54 +2788,12 @@
|
|||||||
" t1.id = 'abc-archived')"
|
" t1.id = 'abc-archived')"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"INSERT INTO agreego.\"entity\" (",
|
"UPDATE agreego.\"entity\" SET",
|
||||||
" \"archived\",",
|
" archived = true,",
|
||||||
" \"created_at\",",
|
" modified_at = '{{timestamp}}',",
|
||||||
" \"created_by\",",
|
" modified_by = '00000000-0000-0000-0000-000000000000'",
|
||||||
" \"id\",",
|
"WHERE",
|
||||||
" \"modified_at\",",
|
" id = 'abc-archived'"
|
||||||
" \"modified_by\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" true,",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" 'abc-archived',",
|
|
||||||
" '{{timestamp}}',",
|
|
||||||
" '00000000-0000-0000-0000-000000000000',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"organization\" (",
|
|
||||||
" \"id\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" 'abc-archived',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"user\" (",
|
|
||||||
" \"id\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" 'abc-archived',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"INSERT INTO agreego.\"person\" (",
|
|
||||||
" \"id\",",
|
|
||||||
" \"type\"",
|
|
||||||
")",
|
|
||||||
"VALUES (",
|
|
||||||
" 'abc-archived',",
|
|
||||||
" 'person'",
|
|
||||||
")"
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"INSERT INTO agreego.change (",
|
"INSERT INTO agreego.change (",
|
||||||
@ -3091,33 +2806,38 @@
|
|||||||
" \"modified_by\"",
|
" \"modified_by\"",
|
||||||
")",
|
")",
|
||||||
"VALUES (",
|
"VALUES (",
|
||||||
" NULL,",
|
" '{",
|
||||||
|
" \"archived\": false",
|
||||||
|
" }',",
|
||||||
" '{",
|
" '{",
|
||||||
" \"archived\": true,",
|
" \"archived\": true,",
|
||||||
" \"type\": \"person\"",
|
" \"type\": \"person\"",
|
||||||
" }',",
|
" }',",
|
||||||
" 'abc-archived',",
|
" 'abc-archived',",
|
||||||
" '{{uuid:generated_0}}',",
|
" '{{uuid:generated_0}}',",
|
||||||
" 'create',",
|
" 'delete',",
|
||||||
" '{{timestamp}}',",
|
" '{{timestamp}}',",
|
||||||
" '00000000-0000-0000-0000-000000000000'",
|
" '00000000-0000-0000-0000-000000000000'",
|
||||||
")"
|
")"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"(SELECT pg_notify('entity', '{",
|
"(SELECT pg_notify('entity', '{",
|
||||||
" \"kind\": \"create\",",
|
" \"kind\": \"delete\",",
|
||||||
" \"complete\": {",
|
" \"complete\": {",
|
||||||
" \"archived\": true,",
|
|
||||||
" \"id\": \"abc-archived\",",
|
" \"id\": \"abc-archived\",",
|
||||||
" \"type\": \"person\",",
|
" \"type\": \"person\",",
|
||||||
" \"created_by\": \"00000000-0000-0000-0000-000000000000\",",
|
" \"first_name\": \"ArchivedFirst\",",
|
||||||
" \"created_at\": \"{{timestamp}}\",",
|
" \"last_name\": \"ArchivedLast\",",
|
||||||
|
" \"archived\": true,",
|
||||||
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
|
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
|
||||||
" \"modified_at\": \"{{timestamp}}\"",
|
" \"modified_at\": \"{{timestamp}}\"",
|
||||||
" },",
|
" },",
|
||||||
" \"new\": {",
|
" \"new\": {",
|
||||||
" \"archived\": true,",
|
" \"archived\": true,",
|
||||||
" \"type\": \"person\"",
|
" \"type\": \"person\"",
|
||||||
|
" },",
|
||||||
|
" \"old\": {",
|
||||||
|
" \"archived\": false",
|
||||||
" }",
|
" }",
|
||||||
"}'))"
|
"}'))"
|
||||||
]
|
]
|
||||||
@ -3499,12 +3219,7 @@
|
|||||||
"success": true,
|
"success": true,
|
||||||
"sql": [
|
"sql": [
|
||||||
[
|
[
|
||||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)",
|
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) FROM agreego.\"entity\" t1 LEFT JOIN agreego.\"invoice\" t2 ON t2.id = t1.id WHERE t1.id = '{{uuid:data.id}}' UNION SELECT to_jsonb(t1.*) || to_jsonb(t2.*) FROM agreego.\"entity\" t1 LEFT JOIN agreego.\"invoice\" t2 ON t2.id = t1.id WHERE (\"id\" = '{{uuid:data.id}}'))"
|
||||||
"FROM agreego.\"entity\" t1",
|
|
||||||
"JOIN agreego.\"invoice\" t2 ON ",
|
|
||||||
"WHERE",
|
|
||||||
" t1.id = '{{uuid:data.id}}'",
|
|
||||||
" OR (\"id\" = '{{uuid:data.id}}'))"
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"INSERT INTO agreego.\"entity\" (",
|
"INSERT INTO agreego.\"entity\" (",
|
||||||
@ -4057,6 +3772,143 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Existence probes hit the same row via id and lookup key (dedup, updates)",
|
||||||
|
"action": "merge",
|
||||||
|
"data": {
|
||||||
|
"id": "22222222-2222-2222-2222-222222222222",
|
||||||
|
"type": "person",
|
||||||
|
"first_name": "LookupFirst",
|
||||||
|
"last_name": "LookupLast",
|
||||||
|
"date_of_birth": "1990-01-01T00:00:00Z",
|
||||||
|
"pronouns": "they/them",
|
||||||
|
"contact_id": "new-contact"
|
||||||
|
},
|
||||||
|
"mocks": [
|
||||||
|
{
|
||||||
|
"id": "22222222-2222-2222-2222-222222222222",
|
||||||
|
"type": "person",
|
||||||
|
"first_name": "LookupFirst",
|
||||||
|
"last_name": "LookupLast",
|
||||||
|
"date_of_birth": "1990-01-01T00:00:00Z",
|
||||||
|
"pronouns": "they/them",
|
||||||
|
"contact_id": "old-contact"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schema_id": "person",
|
||||||
|
"expect": {
|
||||||
|
"success": true,
|
||||||
|
"sql": [
|
||||||
|
[
|
||||||
|
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*) FROM agreego.\"entity\" t1 LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id WHERE t1.id = '{{uuid:mocks.0.id}}' UNION SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*) FROM agreego.\"entity\" t1 LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id WHERE (\"first_name\" = 'LookupFirst' AND \"last_name\" = 'LookupLast' AND \"date_of_birth\" = '{{timestamp}}' AND \"pronouns\" = 'they/them'))"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"UPDATE agreego.\"entity\" SET",
|
||||||
|
" modified_at = '{{timestamp}}',",
|
||||||
|
" modified_by = '00000000-0000-0000-0000-000000000000'",
|
||||||
|
"WHERE",
|
||||||
|
" id = '{{uuid:mocks.0.id}}'"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"UPDATE agreego.\"person\" SET",
|
||||||
|
" contact_id = 'new-contact'",
|
||||||
|
"WHERE",
|
||||||
|
" id = '{{uuid:mocks.0.id}}'"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"INSERT INTO agreego.change (",
|
||||||
|
" \"old\",",
|
||||||
|
" \"new\",",
|
||||||
|
" \"entity_id\",",
|
||||||
|
" \"id\",",
|
||||||
|
" \"kind\",",
|
||||||
|
" \"modified_at\",",
|
||||||
|
" \"modified_by\"",
|
||||||
|
")",
|
||||||
|
"VALUES (",
|
||||||
|
" '{",
|
||||||
|
" \"contact_id\": \"old-contact\"",
|
||||||
|
" }',",
|
||||||
|
" '{",
|
||||||
|
" \"contact_id\": \"new-contact\",",
|
||||||
|
" \"type\": \"person\"",
|
||||||
|
" }',",
|
||||||
|
" '{{uuid:mocks.0.id}}',",
|
||||||
|
" '{{uuid:generated_0}}',",
|
||||||
|
" 'update',",
|
||||||
|
" '{{timestamp}}',",
|
||||||
|
" '00000000-0000-0000-0000-000000000000'",
|
||||||
|
")"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"(SELECT pg_notify('entity', '{",
|
||||||
|
" \"kind\": \"update\",",
|
||||||
|
" \"complete\": {",
|
||||||
|
" \"id\": \"{{uuid:mocks.0.id}}\",",
|
||||||
|
" \"type\": \"person\",",
|
||||||
|
" \"first_name\": \"LookupFirst\",",
|
||||||
|
" \"last_name\": \"LookupLast\",",
|
||||||
|
" \"date_of_birth\": \"{{timestamp}}\",",
|
||||||
|
" \"pronouns\": \"they/them\",",
|
||||||
|
" \"contact_id\": \"new-contact\",",
|
||||||
|
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
|
||||||
|
" \"modified_at\": \"{{timestamp}}\"",
|
||||||
|
" },",
|
||||||
|
" \"new\": {",
|
||||||
|
" \"contact_id\": \"new-contact\",",
|
||||||
|
" \"type\": \"person\"",
|
||||||
|
" },",
|
||||||
|
" \"old\": {",
|
||||||
|
" \"contact_id\": \"old-contact\"",
|
||||||
|
" }",
|
||||||
|
"}'))"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Id probe and lookup probe find different rows (TOO_MANY_LOOKUP_ROWS)",
|
||||||
|
"action": "merge",
|
||||||
|
"data": {
|
||||||
|
"id": "22222222-2222-2222-2222-222222222222",
|
||||||
|
"type": "person",
|
||||||
|
"first_name": "OtherFirst",
|
||||||
|
"last_name": "OtherLast",
|
||||||
|
"date_of_birth": "1991-02-02T00:00:00Z",
|
||||||
|
"pronouns": "she/her"
|
||||||
|
},
|
||||||
|
"mocks": [
|
||||||
|
{
|
||||||
|
"id": "22222222-2222-2222-2222-222222222222",
|
||||||
|
"type": "person",
|
||||||
|
"first_name": "LookupFirst",
|
||||||
|
"last_name": "LookupLast",
|
||||||
|
"date_of_birth": "1990-01-01T00:00:00Z",
|
||||||
|
"pronouns": "they/them"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "44444444-4444-4444-4444-444444444444",
|
||||||
|
"type": "person",
|
||||||
|
"first_name": "OtherFirst",
|
||||||
|
"last_name": "OtherLast",
|
||||||
|
"date_of_birth": "1991-02-02T00:00:00Z",
|
||||||
|
"pronouns": "she/her"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schema_id": "person",
|
||||||
|
"expect": {
|
||||||
|
"success": false,
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"code": "MERGE_FAILED",
|
||||||
|
"values": {
|
||||||
|
"error": "TOO_MANY_LOOKUP_ROWS: Lookup for person found too many existing rows"
|
||||||
|
},
|
||||||
|
"details": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -116,99 +116,17 @@ fn parse_and_match_mocks(sql: &str, mocks: &[Value]) -> Option<Vec<Value>> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Extract table name
|
// The merger's existence read emits one SELECT per probe (id / lookup key)
|
||||||
let table_regex = Regex::new(r#"(?i)\s+FROM\s+(?:[a-zA-Z_]\w*\.)?"?([a-zA-Z_]\w*)"?"#).ok()?;
|
// joined by UNION. Match each arm independently against its own tables and
|
||||||
let table = if let Some(caps) = table_regex.captures(sql) {
|
// WHERE clause; a mock matching any arm is returned once, mirroring UNION's
|
||||||
caps.get(1)?.as_str()
|
// dedup semantics.
|
||||||
} else {
|
let union_regex = Regex::new(r"(?i)\s+UNION\s+(?:ALL\s+)?").ok()?;
|
||||||
return None;
|
let arms: Vec<&str> = union_regex.split(sql).collect();
|
||||||
};
|
|
||||||
|
|
||||||
// 2. Extract WHERE conditions string
|
|
||||||
let mut where_clause = String::new();
|
|
||||||
if let Some(where_idx) = sql_upper.find(" WHERE ") {
|
|
||||||
let mut where_end = sql_upper.find(" ORDER BY ").unwrap_or(sql_upper.len());
|
|
||||||
if let Some(limit_idx) = sql_upper.find(" LIMIT ") {
|
|
||||||
if limit_idx < where_end {
|
|
||||||
where_end = limit_idx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
where_clause = sql[where_idx + 7..where_end].to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Find matching mocks
|
|
||||||
let mut matches = Vec::new();
|
let mut matches = Vec::new();
|
||||||
let or_regex = Regex::new(r"(?i)\s+OR\s+").ok()?;
|
|
||||||
let and_regex = Regex::new(r"(?i)\s+AND\s+").ok()?;
|
|
||||||
|
|
||||||
for mock in mocks {
|
for mock in mocks {
|
||||||
if let Some(mock_obj) = mock.as_object() {
|
if let Some(mock_obj) = mock.as_object() {
|
||||||
if let Some(t) = mock_obj.get("type") {
|
if arms.iter().any(|arm| arm_matches_mock(arm, mock_obj)) {
|
||||||
if t.as_str() != Some(table) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if where_clause.is_empty() {
|
|
||||||
matches.push(mock.clone());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let or_parts = or_regex.split(&where_clause);
|
|
||||||
let mut any_branch_matched = false;
|
|
||||||
|
|
||||||
for or_part in or_parts {
|
|
||||||
let branch_str = or_part.replace('(', "").replace(')', "");
|
|
||||||
let mut branch_matches = true;
|
|
||||||
|
|
||||||
for part in and_regex.split(&branch_str) {
|
|
||||||
if let Some(eq_idx) = part.find('=') {
|
|
||||||
let left = part[..eq_idx]
|
|
||||||
.trim()
|
|
||||||
.split('.')
|
|
||||||
.last()
|
|
||||||
.unwrap_or("")
|
|
||||||
.trim_matches('"');
|
|
||||||
let right = part[eq_idx + 1..].trim().trim_matches('\'');
|
|
||||||
|
|
||||||
let mock_val_str = match mock_obj.get(left) {
|
|
||||||
Some(Value::String(s)) => s.clone(),
|
|
||||||
Some(Value::Number(n)) => n.to_string(),
|
|
||||||
Some(Value::Bool(b)) => b.to_string(),
|
|
||||||
Some(Value::Null) => "null".to_string(),
|
|
||||||
_ => "".to_string(),
|
|
||||||
};
|
|
||||||
if mock_val_str != right {
|
|
||||||
branch_matches = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if part.to_uppercase().contains(" IS NULL") {
|
|
||||||
let left = part[..part.to_uppercase().find(" IS NULL").unwrap()]
|
|
||||||
.trim()
|
|
||||||
.split('.')
|
|
||||||
.last()
|
|
||||||
.unwrap_or("")
|
|
||||||
.trim_matches('"');
|
|
||||||
|
|
||||||
let mock_val_str = match mock_obj.get(left) {
|
|
||||||
Some(Value::Null) => "null".to_string(),
|
|
||||||
_ => "".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if mock_val_str != "null" {
|
|
||||||
branch_matches = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if branch_matches {
|
|
||||||
any_branch_matched = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if any_branch_matched {
|
|
||||||
matches.push(mock.clone());
|
matches.push(mock.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,3 +134,103 @@ fn parse_and_match_mocks(sql: &str, mocks: &[Value]) -> Option<Vec<Value>> {
|
|||||||
|
|
||||||
Some(matches)
|
Some(matches)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn arm_matches_mock(arm: &str, mock_obj: &serde_json::Map<String, Value>) -> bool {
|
||||||
|
let arm_upper = arm.to_uppercase();
|
||||||
|
|
||||||
|
// 1. The mock's type must name one of the arm's tables. Hierarchy reads
|
||||||
|
// SELECT FROM the root (entity) and JOIN the subtype tables, so every
|
||||||
|
// FROM/JOIN table counts, not just the first.
|
||||||
|
let table_regex = match Regex::new(r#"(?i)\b(?:FROM|JOIN)\s+(?:[a-zA-Z_]\w*\.)?"?([a-zA-Z_]\w*)"?"#) {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(_) => return false,
|
||||||
|
};
|
||||||
|
let tables: Vec<&str> = table_regex.captures_iter(arm).filter_map(|c| c.get(1)).map(|m| m.as_str()).collect();
|
||||||
|
if tables.is_empty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if let Some(t) = mock_obj.get("type") {
|
||||||
|
if !tables.iter().any(|table| t.as_str() == Some(table)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Extract this arm's WHERE conditions
|
||||||
|
let mut where_clause = String::new();
|
||||||
|
if let Some(where_idx) = arm_upper.find(" WHERE ") {
|
||||||
|
let mut where_end = arm_upper.find(" ORDER BY ").unwrap_or(arm_upper.len());
|
||||||
|
if let Some(limit_idx) = arm_upper.find(" LIMIT ") {
|
||||||
|
if limit_idx < where_end {
|
||||||
|
where_end = limit_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
where_clause = arm[where_idx + 7..where_end].to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
if where_clause.is_empty() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Match the mock against the conditions
|
||||||
|
let or_regex = match Regex::new(r"(?i)\s+OR\s+") {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(_) => return false,
|
||||||
|
};
|
||||||
|
let and_regex = match Regex::new(r"(?i)\s+AND\s+") {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(_) => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
for or_part in or_regex.split(&where_clause) {
|
||||||
|
let branch_str = or_part.replace('(', "").replace(')', "");
|
||||||
|
let mut branch_matches = true;
|
||||||
|
|
||||||
|
for part in and_regex.split(&branch_str) {
|
||||||
|
if let Some(eq_idx) = part.find('=') {
|
||||||
|
let left = part[..eq_idx]
|
||||||
|
.trim()
|
||||||
|
.split('.')
|
||||||
|
.last()
|
||||||
|
.unwrap_or("")
|
||||||
|
.trim_matches('"');
|
||||||
|
let right = part[eq_idx + 1..].trim().trim_matches('\'');
|
||||||
|
|
||||||
|
let mock_val_str = match mock_obj.get(left) {
|
||||||
|
Some(Value::String(s)) => s.clone(),
|
||||||
|
Some(Value::Number(n)) => n.to_string(),
|
||||||
|
Some(Value::Bool(b)) => b.to_string(),
|
||||||
|
Some(Value::Null) => "null".to_string(),
|
||||||
|
_ => "".to_string(),
|
||||||
|
};
|
||||||
|
if mock_val_str != right {
|
||||||
|
branch_matches = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if part.to_uppercase().contains(" IS NULL") {
|
||||||
|
let left = part[..part.to_uppercase().find(" IS NULL").unwrap()]
|
||||||
|
.trim()
|
||||||
|
.split('.')
|
||||||
|
.last()
|
||||||
|
.unwrap_or("")
|
||||||
|
.trim_matches('"');
|
||||||
|
|
||||||
|
let mock_val_str = match mock_obj.get(left) {
|
||||||
|
Some(Value::Null) => "null".to_string(),
|
||||||
|
_ => "".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if mock_val_str != "null" {
|
||||||
|
branch_matches = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if branch_matches {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|||||||
@ -744,9 +744,19 @@ impl Merger {
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let where_clause = format!("WHERE {}", where_parts.join(" OR "));
|
// An OR across the hierarchy join is un-indexable — it forces a full scan
|
||||||
|
// of the subtype table on every child merge. UNION lets each arm use its
|
||||||
let final_sql = format!("{} {}", fetch_sql_template, where_clause);
|
// own index (pk for the id arm, the lk_ unique index for the lookup arm)
|
||||||
|
// and still dedups, so TOO_MANY_LOOKUP_ROWS semantics are preserved.
|
||||||
|
let final_sql = if where_parts.len() == 1 {
|
||||||
|
format!("{} WHERE {}", fetch_sql_template, where_parts[0])
|
||||||
|
} else {
|
||||||
|
where_parts
|
||||||
|
.iter()
|
||||||
|
.map(|p| format!("{} WHERE {}", fetch_sql_template, p))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(" UNION ")
|
||||||
|
};
|
||||||
|
|
||||||
let fetched = match self.db.query(&final_sql, None) {
|
let fetched = match self.db.query(&final_sql, None) {
|
||||||
Ok(Value::Array(table)) => {
|
Ok(Value::Array(table)) => {
|
||||||
|
|||||||
@ -7660,3 +7660,15 @@ fn test_merger_0_15() {
|
|||||||
let path = format!("{}/fixtures/merger.json", env!("CARGO_MANIFEST_DIR"));
|
let path = format!("{}/fixtures/merger.json", env!("CARGO_MANIFEST_DIR"));
|
||||||
crate::tests::runner::run_test_case(&path, 0, 15).unwrap();
|
crate::tests::runner::run_test_case(&path, 0, 15).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_merger_0_16() {
|
||||||
|
let path = format!("{}/fixtures/merger.json", env!("CARGO_MANIFEST_DIR"));
|
||||||
|
crate::tests::runner::run_test_case(&path, 0, 16).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_merger_0_17() {
|
||||||
|
let path = format!("{}/fixtures/merger.json", env!("CARGO_MANIFEST_DIR"));
|
||||||
|
crate::tests::runner::run_test_case(&path, 0, 17).unwrap();
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user