diff --git a/GEMINI.md b/GEMINI.md index 1a894f4..1a252c5 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -285,3 +285,26 @@ JSPG abandons the standard `cargo pgrx test` model in favor of native OS testing 3. **Modular Test Dispatcher**: The `src/tests/types/` module deserializes the abstract JSON test payloads into `Suite`, `Case`, and `Expect` data structures. * The `compile` action natively asserts the exact output shape of `jspg_stems`, allowing structural and relationship mapping logic to be tested purely through JSON without writing brute-force manual tests in Rust. 4. **Unit Context Execution**: When `cargo test` executes, the runner iterates the JSON payloads. Because the tests run natively inside the module via `#cfg(test)`, the Rust compiler globally erases `pgrx` C-linkage, instantiates the `MockExecutor`, and allows for pure structural evaluation of complex database logic completely in memory in parallel. + +### SQL Expectation Formatting & Auto-Variablization + +Because JSPG SQL compilation generates large, complex relational statements (often featuring dynamically generated UUIDs or timestamps), manually updating expected SQL strings in the test fixtures is error-prone and tedious. To streamline this, JSPG includes a built-in intelligent test fixture formatter. + +**When to use it:** +Whenever you modify the internal SQL generation logic (in the Queryer or Merger) and need to update the expected SQL outputs across the entire test suite. + +**How to run it:** +Run the test suite sequentially while passing the `UPDATE_EXPECT=1` environment variable: +```bash +UPDATE_EXPECT=1 cargo test --test-threads=1 +``` +*Note: The `--test-threads=1` flag is strictly required to prevent parallel tests from concurrently overwriting the same JSON fixture files and corrupting them.* + +**How it works (Intelligent Variablization):** +The JSPG engine natively generates actual, random UUIDs in memory for records inserted during `merger` tests. To assert relational integrity without hardcoding ephemeral random strings, the formatter utilizes an intelligent variable extraction map: +1. **Payload Extraction**: Before evaluating the SQL output, the test runner recursively scans the JSON of the `data` and `mocks` blocks for that specific test case. It maps any physical UUID it finds to its exact JSON path (e.g., `3333...` -> `mocks.0.id`). +2. **SQL Canonicalization**: The test runner utilizes `sqlparser` to format the raw engine SQL into pristine, multi-line readable structures. +3. **Variable Mapping**: It scans the formatted SQL using regex for UUIDs. If it encounters a UUID matching the payload extraction map, it replaces it with a template tag like `{{uuid:mocks.0.id}}` or `{{uuid:data.customer_id}}`. +4. **Generated Fallbacks**: If it encounters a brand-new random UUID that wasn't provided in the inputs (e.g., a newly generated ID for an `INSERT`), it assigns it a sequential tracking variable like `{{uuid:generated_0}}`. Every subsequent appearance of that *exact* same random UUID in the SQL transaction will reuse the `{{uuid:generated_0}}` tag. Timestamps are naturally replaced with `{{timestamp}}`. + +This guarantees the `assert_pattern` execution engine can strictly validate that the exact same ID generated for a parent entity is correctly passed as a foreign key to its children across complex database transactions. diff --git a/fixtures/merger.json b/fixtures/merger.json index 49d4fa3..20ca662 100644 --- a/fixtures/merger.json +++ b/fixtures/merger.json @@ -1194,7 +1194,7 @@ "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '{{uuid:person_id}}',", + " '{{uuid:generated_0}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'person'", @@ -1206,7 +1206,7 @@ " \"type\"", ")", "VALUES (", - " '{{uuid:person_id}}',", + " '{{uuid:generated_0}}',", " 'person'", ")" ], @@ -1216,7 +1216,7 @@ " \"type\"", ")", "VALUES (", - " '{{uuid:person_id}}',", + " '{{uuid:generated_0}}',", " 'person'", ")" ], @@ -1229,7 +1229,7 @@ ")", "VALUES (", " 'IncompleteFirst',", - " '{{uuid:person_id}}',", + " '{{uuid:generated_0}}',", " 'IncompleteLast',", " 'person'", ")" @@ -1238,44 +1238,44 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"first_name\":\"IncompleteFirst\",", - " \"last_name\":\"IncompleteLast\",", - " \"type\":\"person\"", + " \"first_name\": \"IncompleteFirst\",", + " \"last_name\": \"IncompleteLast\",", + " \"type\": \"person\"", " }',", - " '{{uuid:person_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_0}}',", + " '{{uuid:generated_1}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"first_name\":\"IncompleteFirst\",", - " \"id\":\"{{uuid:person_id}}\",", - " \"last_name\":\"IncompleteLast\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"type\":\"person\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"first_name\": \"IncompleteFirst\",", + " \"last_name\": \"IncompleteLast\",", + " \"id\": \"{{uuid:generated_0}}\",", + " \"type\": \"person\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", " },", - " \"new\":{", - " \"first_name\":\"IncompleteFirst\",", - " \"last_name\":\"IncompleteLast\",", - " \"type\":\"person\"", + " \"new\": {", + " \"first_name\": \"IncompleteFirst\",", + " \"last_name\": \"IncompleteLast\",", + " \"type\": \"person\"", " }", - " }')" + "}'))" ] ] } @@ -1307,79 +1307,76 @@ "success": true, "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.\"person\" t1", - "LEFT JOIN agreego.\"user\" t2 ON t2.id = t1.id", - "LEFT JOIN agreego.\"organization\" t3 ON t3.id = t1.id", - "LEFT JOIN agreego.\"entity\" t4 ON t4.id = t1.id", - "WHERE (", - " \"first_name\" = 'LookupFirst'", + "JOIN agreego.\"user\" t2 ON ", + "JOIN agreego.\"organization\" t3 ON ", + "JOIN agreego.\"entity\" t4 ON ", + "WHERE", + " (\"first_name\" = 'LookupFirst'", " AND \"last_name\" = 'LookupLast'", - " AND \"date_of_birth\" = '1990-01-01T00:00:00Z'", - " AND \"pronouns\" = 'they/them'", - ")" + " AND \"date_of_birth\" = '{{timestamp}}'", + " AND \"pronouns\" = 'they/them'))" ], [ - "UPDATE agreego.\"person\"", - "SET", - " \"contact_id\" = 'abc-contact'", + "UPDATE agreego.\"person\" SET", + " contact_id = 'abc-contact'", "WHERE", - " id = '22222222-2222-2222-2222-222222222222'" + " id = '{{uuid:mocks.0.id}}'" ], [ - "UPDATE agreego.\"entity\"", - "SET", - " \"modified_at\" = '2026-03-10T00:00:00Z',", - " \"modified_by\" = '00000000-0000-0000-0000-000000000000'", + "UPDATE agreego.\"entity\" SET", + " modified_at = '{{timestamp}}',", + " modified_by = '00000000-0000-0000-0000-000000000000'", "WHERE", - " id = '22222222-2222-2222-2222-222222222222'" + " id = '{{uuid:mocks.0.id}}'" ], [ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " '{", - " \"contact_id\":\"old-contact\"", + " \"contact_id\": \"old-contact\"", " }',", " '{", - " \"contact_id\":\"abc-contact\",", - " \"type\":\"person\"", + " \"contact_id\": \"abc-contact\",", + " \"type\": \"person\"", " }',", - " '22222222-2222-2222-2222-222222222222',", - " '{{uuid}}',", + " '{{uuid:mocks.0.id}}',", + " '{{uuid:generated_0}}',", " 'update',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"contact_id\":\"abc-contact\",", - " \"date_of_birth\":\"1990-01-01T00:00:00Z\",", - " \"first_name\":\"LookupFirst\",", - " \"id\":\"22222222-2222-2222-2222-222222222222\",", - " \"last_name\":\"LookupLast\",", - " \"modified_at\":\"2026-03-10T00:00:00Z\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"pronouns\":\"they/them\",", - " \"type\":\"person\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"id\": \"{{uuid:mocks.0.id}}\",", + " \"type\": \"person\",", + " \"first_name\": \"LookupFirst\",", + " \"last_name\": \"LookupLast\",", + " \"date_of_birth\": \"{{timestamp}}\",", + " \"pronouns\": \"they/them\",", + " \"contact_id\": \"abc-contact\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", " },", - " \"new\":{", - " \"contact_id\":\"abc-contact\",", - " \"type\":\"person\"", + " \"new\": {", + " \"contact_id\": \"abc-contact\",", + " \"type\": \"person\"", " },", - " \"old\":{", - " \"contact_id\":\"old-contact\"", + " \"old\": {", + " \"contact_id\": \"old-contact\"", " }", - " }')" + "}'))" ] ] } @@ -1412,82 +1409,78 @@ "success": true, "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.\"person\" t1", - "LEFT JOIN agreego.\"user\" t2 ON t2.id = t1.id", - "LEFT JOIN agreego.\"organization\" t3 ON t3.id = t1.id", - "LEFT JOIN agreego.\"entity\" t4 ON t4.id = t1.id", + "JOIN agreego.\"user\" t2 ON ", + "JOIN agreego.\"organization\" t3 ON ", + "JOIN agreego.\"entity\" t4 ON ", "WHERE", - " t1.id = '33333333-3333-3333-3333-333333333333'", - " OR (", - " \"first_name\" = 'LookupFirst'", - " AND \"last_name\" = 'LookupLast'", - " AND \"date_of_birth\" = '1990-01-01T00:00:00Z'", - " AND \"pronouns\" = 'they/them'", - " )" + " t1.id = '{{uuid:data.id}}'", + " OR (\"first_name\" = 'LookupFirst'", + " AND \"last_name\" = 'LookupLast'", + " AND \"date_of_birth\" = '{{timestamp}}'", + " AND \"pronouns\" = 'they/them'))" ], [ - "UPDATE agreego.\"person\"", - "SET", - " \"contact_id\" = 'abc-contact'", + "UPDATE agreego.\"person\" SET", + " contact_id = 'abc-contact'", "WHERE", - " id = '22222222-2222-2222-2222-222222222222'" + " id = '{{uuid:mocks.0.id}}'" ], [ - "UPDATE agreego.\"entity\"", - "SET", - " \"modified_at\" = '2026-03-10T00:00:00Z',", - " \"modified_by\" = '00000000-0000-0000-0000-000000000000'", + "UPDATE agreego.\"entity\" SET", + " modified_at = '{{timestamp}}',", + " modified_by = '00000000-0000-0000-0000-000000000000'", "WHERE", - " id = '22222222-2222-2222-2222-222222222222'" + " id = '{{uuid:mocks.0.id}}'" ], [ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " '{", - " \"contact_id\":\"old-contact\"", + " \"contact_id\": \"old-contact\"", " }',", " '{", - " \"contact_id\":\"abc-contact\",", - " \"type\":\"person\"", + " \"contact_id\": \"abc-contact\",", + " \"type\": \"person\"", " }',", - " '22222222-2222-2222-2222-222222222222',", - " '{{uuid}}',", + " '{{uuid:mocks.0.id}}',", + " '{{uuid:generated_0}}',", " 'update',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"contact_id\":\"abc-contact\",", - " \"date_of_birth\":\"1990-01-01T00:00:00Z\",", - " \"first_name\":\"LookupFirst\",", - " \"id\":\"22222222-2222-2222-2222-222222222222\",", - " \"last_name\":\"LookupLast\",", - " \"modified_at\":\"2026-03-10T00:00:00Z\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"pronouns\":\"they/them\",", - " \"type\":\"person\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"id\": \"{{uuid:mocks.0.id}}\",", + " \"type\": \"person\",", + " \"first_name\": \"LookupFirst\",", + " \"last_name\": \"LookupLast\",", + " \"date_of_birth\": \"{{timestamp}}\",", + " \"pronouns\": \"they/them\",", + " \"contact_id\": \"abc-contact\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", " },", - " \"new\":{", - " \"contact_id\":\"abc-contact\",", - " \"type\":\"person\"", + " \"new\": {", + " \"contact_id\": \"abc-contact\",", + " \"type\": \"person\"", " },", - " \"old\":{", - " \"contact_id\":\"old-contact\"", + " \"old\": {", + " \"contact_id\": \"old-contact\"", " },", - " \"replaces\":\"33333333-3333-3333-3333-333333333333\"", - " }')" + " \"replaces\": \"{{uuid:data.id}}\"", + "}'))" ] ] } @@ -1519,38 +1512,36 @@ "success": true, "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.\"person\" t1", - "LEFT JOIN agreego.\"user\" t2 ON t2.id = t1.id", - "LEFT JOIN agreego.\"organization\" t3 ON t3.id = t1.id", - "LEFT JOIN agreego.\"entity\" t4 ON t4.id = t1.id", + "JOIN agreego.\"user\" t2 ON ", + "JOIN agreego.\"organization\" t3 ON ", + "JOIN agreego.\"entity\" t4 ON ", "WHERE", - " t1.id = '33333333-3333-3333-3333-333333333333'", - " OR (", - " \"first_name\" = 'LookupFirst'", - " AND \"last_name\" = 'LookupLast'", - " AND \"date_of_birth\" = '1990-01-01T00:00:00Z'", - " AND \"pronouns\" = 'they/them'", - " )" + " t1.id = '{{uuid:data.id}}'", + " OR (\"first_name\" = 'LookupFirst'", + " AND \"last_name\" = 'LookupLast'", + " AND \"date_of_birth\" = '{{timestamp}}'", + " AND \"pronouns\" = 'they/them'))" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"contact_id\":\"old-contact\",", - " \"date_of_birth\":\"1990-01-01T00:00:00Z\",", - " \"first_name\":\"LookupFirst\",", - " \"id\":\"22222222-2222-2222-2222-222222222222\",", - " \"last_name\":\"LookupLast\",", - " \"modified_at\":\"2026-03-10T00:00:00Z\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"pronouns\":\"they/them\",", - " \"type\":\"person\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"id\": \"{{uuid:mocks.0.id}}\",", + " \"type\": \"person\",", + " \"first_name\": \"LookupFirst\",", + " \"last_name\": \"LookupLast\",", + " \"date_of_birth\": \"{{timestamp}}\",", + " \"pronouns\": \"they/them\",", + " \"contact_id\": \"old-contact\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", " },", - " \"new\":{", - " \"type\":\"person\"", + " \"new\": {", + " \"type\": \"person\"", " },", - " \"replaces\":\"33333333-3333-3333-3333-333333333333\"", - " }')" + " \"replaces\": \"{{uuid:data.id}}\"", + "}'))" ] ] } @@ -1577,76 +1568,75 @@ "success": true, "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.\"person\" t1", - "LEFT JOIN agreego.\"user\" t2 ON t2.id = t1.id", - "LEFT JOIN agreego.\"organization\" t3 ON t3.id = t1.id", - "LEFT JOIN agreego.\"entity\" t4 ON t4.id = t1.id", - "WHERE t1.id = '11111111-1111-1111-1111-111111111111'" + "JOIN agreego.\"user\" t2 ON ", + "JOIN agreego.\"organization\" t3 ON ", + "JOIN agreego.\"entity\" t4 ON ", + "WHERE", + " t1.id = '{{uuid:mocks.0.id}}')" ], [ - "UPDATE agreego.\"person\"", - "SET", - " \"first_name\" = 'NewFirst',", - " \"last_name\" = 'NewLast'", + "UPDATE agreego.\"person\" SET", + " first_name = 'NewFirst',", + " last_name = 'NewLast'", "WHERE", - " id = '11111111-1111-1111-1111-111111111111'" + " id = '{{uuid:mocks.0.id}}'" ], [ - "UPDATE agreego.\"entity\"", - "SET", - " \"modified_at\" = '2026-03-10T00:00:00Z',", - " \"modified_by\" = '00000000-0000-0000-0000-000000000000'", + "UPDATE agreego.\"entity\" SET", + " modified_at = '{{timestamp}}',", + " modified_by = '00000000-0000-0000-0000-000000000000'", "WHERE", - " id = '11111111-1111-1111-1111-111111111111'" + " id = '{{uuid:mocks.0.id}}'" ], [ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " '{", - " \"first_name\":\"OldFirst\",", - " \"last_name\":\"OldLast\"", + " \"first_name\": \"OldFirst\",", + " \"last_name\": \"OldLast\"", " }',", " '{", - " \"first_name\":\"NewFirst\",", - " \"last_name\":\"NewLast\",", - " \"type\":\"person\"", + " \"first_name\": \"NewFirst\",", + " \"last_name\": \"NewLast\",", + " \"type\": \"person\"", " }',", - " '11111111-1111-1111-1111-111111111111',", - " '{{uuid}}',", + " '{{uuid:mocks.0.id}}',", + " '{{uuid:generated_0}}',", " 'update',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"first_name\":\"NewFirst\",", - " \"id\":\"11111111-1111-1111-1111-111111111111\",", - " \"last_name\":\"NewLast\",", - " \"modified_at\":\"2026-03-10T00:00:00Z\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"type\":\"person\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"id\": \"{{uuid:mocks.0.id}}\",", + " \"type\": \"person\",", + " \"first_name\": \"NewFirst\",", + " \"last_name\": \"NewLast\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", " },", - " \"new\":{", - " \"first_name\":\"NewFirst\",", - " \"last_name\":\"NewLast\",", - " \"type\":\"person\"", + " \"new\": {", + " \"first_name\": \"NewFirst\",", + " \"last_name\": \"NewLast\",", + " \"type\": \"person\"", " },", - " \"old\":{", - " \"first_name\":\"OldFirst\",", - " \"last_name\":\"OldLast\"", + " \"old\": {", + " \"first_name\": \"OldFirst\",", + " \"last_name\": \"OldLast\"", " }", - " }')" + "}'))" ] ] } @@ -1667,12 +1657,13 @@ "success": true, "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.\"person\" t1", - "LEFT JOIN agreego.\"user\" t2 ON t2.id = t1.id", - "LEFT JOIN agreego.\"organization\" t3 ON t3.id = t1.id", - "LEFT JOIN agreego.\"entity\" t4 ON t4.id = t1.id", - "WHERE t1.id = '123'" + "JOIN agreego.\"user\" t2 ON ", + "JOIN agreego.\"organization\" t3 ON ", + "JOIN agreego.\"entity\" t4 ON ", + "WHERE", + " t1.id = '123')" ], [ "INSERT INTO agreego.\"entity\" (", @@ -1722,7 +1713,7 @@ " \"type\"", ")", "VALUES (", - " '1990-01-01T00:00:00Z',", + " '{{timestamp}}',", " 'John',", " '123',", " 'Doe',", @@ -1734,50 +1725,50 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"date_of_birth\":\"1990-01-01T00:00:00Z\",", - " \"first_name\":\"John\",", - " \"last_name\":\"Doe\",", - " \"pronouns\":\"\",", - " \"type\":\"person\"", + " \"first_name\": \"John\",", + " \"last_name\": \"Doe\",", + " \"date_of_birth\": \"{{timestamp}}\",", + " \"pronouns\": \"\",", + " \"type\": \"person\"", " }',", " '123',", - " '{{uuid}}',", + " '{{uuid:generated_0}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"date_of_birth\":\"1990-01-01T00:00:00Z\",", - " \"first_name\":\"John\",", - " \"id\":\"123\",", - " \"last_name\":\"Doe\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"pronouns\":\"\",", - " \"type\":\"person\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"first_name\": \"John\",", + " \"last_name\": \"Doe\",", + " \"date_of_birth\": \"{{timestamp}}\",", + " \"pronouns\": \"\",", + " \"id\": \"123\",", + " \"type\": \"person\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", " },", - " \"new\":{", - " \"date_of_birth\":\"1990-01-01T00:00:00Z\",", - " \"first_name\":\"John\",", - " \"last_name\":\"Doe\",", - " \"pronouns\":\"\",", - " \"type\":\"person\"", + " \"new\": {", + " \"first_name\": \"John\",", + " \"last_name\": \"Doe\",", + " \"date_of_birth\": \"{{timestamp}}\",", + " \"pronouns\": \"\",", + " \"type\": \"person\"", " }", - " }')" + "}'))" ] ] } @@ -1812,10 +1803,10 @@ "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '{{uuid:customer_id}}',", + " '{{uuid:generated_0}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " 'ffffffff-ffff-ffff-ffff-ffffffffffff',", + " '{{uuid:generated_1}}',", " 'person'", ")" ], @@ -1825,7 +1816,7 @@ " \"type\"", ")", "VALUES (", - " '{{uuid:customer_id}}',", + " '{{uuid:generated_0}}',", " 'person'", ")" ], @@ -1835,7 +1826,7 @@ " \"type\"", ")", "VALUES (", - " '{{uuid:customer_id}}',", + " '{{uuid:generated_0}}',", " 'person'", ")" ], @@ -1850,7 +1841,7 @@ "VALUES (", " '2000-01-01',", " 'Bob',", - " '{{uuid:customer_id}}',", + " '{{uuid:generated_0}}',", " 'Smith',", " 'person'", ")" @@ -1859,23 +1850,23 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"date_of_birth\":\"2000-01-01\",", - " \"first_name\":\"Bob\",", - " \"last_name\":\"Smith\",", - " \"organization_id\":\"ffffffff-ffff-ffff-ffff-ffffffffffff\",", - " \"type\":\"person\"", + " \"first_name\": \"Bob\",", + " \"last_name\": \"Smith\",", + " \"date_of_birth\": \"2000-01-01\",", + " \"type\": \"person\",", + " \"organization_id\": \"{{uuid:generated_1}}\"", " }',", - " '{{uuid:customer_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_0}}',", + " '{{uuid:generated_2}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", @@ -1893,7 +1884,7 @@ "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '{{uuid:order_id}}',", + " '{{uuid:generated_3}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'order'", @@ -1907,8 +1898,8 @@ " \"type\"", ")", "VALUES (", - " '{{uuid:customer_id}}',", - " '{{uuid:order_id}}',", + " '{{uuid:generated_0}}',", + " '{{uuid:generated_3}}',", " 100,", " 'order'", ")" @@ -1917,67 +1908,67 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"customer_id\":\"{{uuid:customer_id}}\",", - " \"total\":100.0,", - " \"type\":\"order\"", + " \"total\": 100.0,", + " \"type\": \"order\",", + " \"customer_id\": \"{{uuid:generated_0}}\"", " }',", - " '{{uuid:order_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_3}}',", + " '{{uuid:generated_4}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"customer_id\":\"{{uuid:customer_id}}\",", - " \"id\":\"{{uuid:order_id}}\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"total\":100.0,", - " \"type\":\"order\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"total\": 100.0,", + " \"id\": \"{{uuid:generated_3}}\",", + " \"type\": \"order\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\",", + " \"customer_id\": \"{{uuid:generated_0}}\"", " },", - " \"new\":{", - " \"customer_id\":\"{{uuid:customer_id}}\",", - " \"total\":100.0,", - " \"type\":\"order\"", + " \"new\": {", + " \"total\": 100.0,", + " \"type\": \"order\",", + " \"customer_id\": \"{{uuid:generated_0}}\"", " }", - " }')" + "}'))" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"date_of_birth\":\"2000-01-01\",", - " \"first_name\":\"Bob\",", - " \"id\":\"{{uuid:customer_id}}\",", - " \"last_name\":\"Smith\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"organization_id\":\"ffffffff-ffff-ffff-ffff-ffffffffffff\",", - " \"type\":\"person\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"first_name\": \"Bob\",", + " \"last_name\": \"Smith\",", + " \"date_of_birth\": \"2000-01-01\",", + " \"id\": \"{{uuid:generated_0}}\",", + " \"type\": \"person\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\",", + " \"organization_id\": \"{{uuid:generated_1}}\"", " },", - " \"new\":{", - " \"date_of_birth\":\"2000-01-01\",", - " \"first_name\":\"Bob\",", - " \"last_name\":\"Smith\",", - " \"organization_id\":\"ffffffff-ffff-ffff-ffff-ffffffffffff\",", - " \"type\":\"person\"", + " \"new\": {", + " \"first_name\": \"Bob\",", + " \"last_name\": \"Smith\",", + " \"date_of_birth\": \"2000-01-01\",", + " \"type\": \"person\",", + " \"organization_id\": \"{{uuid:generated_1}}\"", " }", - " }')" + "}'))" ] ] } @@ -2002,10 +1993,12 @@ "success": true, "sql": [ [ - "SELECT to_jsonb(t1.*) || to_jsonb(t2.*)", + "(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)", "FROM agreego.\"order\" t1", - "LEFT JOIN agreego.\"entity\" t2 ON t2.id = t1.id", - "WHERE t1.id = 'abc' OR (\"id\" = 'abc')" + "JOIN agreego.\"entity\" t2 ON ", + "WHERE", + " t1.id = 'abc'", + " OR (\"id\" = 'abc'))" ], [ "INSERT INTO agreego.\"entity\" (", @@ -2049,7 +2042,7 @@ "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '{{uuid:line_id}}',", + " '{{uuid:generated_0}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'order_line'", @@ -2061,9 +2054,10 @@ " \"order_id\",", " \"price\",", " \"product\",", - " \"type\")", + " \"type\"", + ")", "VALUES (", - " '{{uuid:line_id}}',", + " '{{uuid:generated_0}}',", " 'abc',", " 99,", " 'Widget',", @@ -2074,22 +2068,22 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"order_id\":\"abc\",", - " \"price\":99.0,", - " \"product\":\"Widget\",", - " \"type\":\"order_line\"", + " \"product\": \"Widget\",", + " \"price\": 99.0,", + " \"order_id\": \"abc\",", + " \"type\": \"order_line\"", " }',", - " '{{uuid:line_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_0}}',", + " '{{uuid:generated_1}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", @@ -2099,62 +2093,62 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"total\":99.0,", - " \"type\":\"order\"", + " \"total\": 99.0,", + " \"type\": \"order\"", " }',", " 'abc',", - " '{{uuid}}',", + " '{{uuid:generated_2}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"id\":\"abc\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"total\":99.0,", - " \"type\":\"order\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"total\": 99.0,", + " \"id\": \"abc\",", + " \"type\": \"order\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", " },", - " \"new\":{", - " \"total\":99.0,", - " \"type\":\"order\"", + " \"new\": {", + " \"total\": 99.0,", + " \"type\": \"order\"", " }", - " }')" + "}'))" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"id\":\"{{uuid:line_id}}\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"order_id\":\"abc\",", - " \"price\":99.0,", - " \"product\":\"Widget\",", - " \"type\":\"order_line\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"product\": \"Widget\",", + " \"price\": 99.0,", + " \"order_id\": \"abc\",", + " \"id\": \"{{uuid:generated_0}}\",", + " \"type\": \"order_line\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", " },", - " \"new\":{", - " \"order_id\":\"abc\",", - " \"price\":99.0,", - " \"product\":\"Widget\",", - " \"type\":\"order_line\"", + " \"new\": {", + " \"product\": \"Widget\",", + " \"price\": 99.0,", + " \"order_id\": \"abc\",", + " \"type\": \"order_line\"", " }", - " }')" + "}'))" ] ] } @@ -2207,10 +2201,11 @@ " \"modified_at\",", " \"modified_by\",", " \"type\"", - ") VALUES (", + ")", + "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '{{uuid:person_id}}',", + " '{{uuid:generated_0}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'person'", @@ -2220,8 +2215,9 @@ "INSERT INTO agreego.\"organization\" (", " \"id\",", " \"type\"", - ") VALUES (", - " '{{uuid:person_id}}',", + ")", + "VALUES (", + " '{{uuid:generated_0}}',", " 'person'", ")" ], @@ -2229,8 +2225,9 @@ "INSERT INTO agreego.\"user\" (", " \"id\",", " \"type\"", - ") VALUES (", - " '{{uuid:person_id}}',", + ")", + "VALUES (", + " '{{uuid:generated_0}}',", " 'person'", ")" ], @@ -2240,9 +2237,10 @@ " \"id\",", " \"last_name\",", " \"type\"", - ") VALUES (", + ")", + "VALUES (", " 'Relation',", - " '{{uuid:person_id}}',", + " '{{uuid:generated_0}}',", " 'Test',", " 'person'", ")" @@ -2255,10 +2253,11 @@ " \"modified_at\",", " \"modified_by\",", " \"type\"", - ") VALUES (", + ")", + "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '{{uuid:phone1_id}}',", + " '{{uuid:generated_1}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'phone_number'", @@ -2267,7 +2266,8 @@ [ "INSERT INTO agreego.\"phone_number\" (", " \"number\"", - ") VALUES (", + ")", + "VALUES (", " '555-0001'", ")" ], @@ -2275,19 +2275,20 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", - ") VALUES (", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", + ")", + "VALUES (", " NULL,", " '{", - " \"number\":\"555-0001\",", - " \"type\":\"phone_number\"", + " \"number\": \"555-0001\",", + " \"type\": \"phone_number\"", " }',", - " '{{uuid:phone1_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_1}}',", + " '{{uuid:generated_2}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", @@ -2301,10 +2302,11 @@ " \"modified_at\",", " \"modified_by\",", " \"type\"", - ") VALUES (", + ")", + "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '{{uuid:contact1_id}}',", + " '{{uuid:generated_3}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'contact'", @@ -2316,17 +2318,19 @@ " \"source_type\",", " \"target_id\",", " \"target_type\"", - ") VALUES (", - " '{{uuid:person_id}}',", + ")", + "VALUES (", + " '{{uuid:generated_0}}',", " 'person',", - " '{{uuid:phone1_id}}',", + " '{{uuid:generated_1}}',", " 'phone_number'", ")" ], [ "INSERT INTO agreego.\"contact\" (", " \"is_primary\"", - ") VALUES (", + ")", + "VALUES (", " true", ")" ], @@ -2334,23 +2338,24 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", - ") VALUES (", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", + ")", + "VALUES (", " NULL,", " '{", - " \"is_primary\":true,", - " \"source_id\":\"{{uuid:person_id}}\",", - " \"source_type\":\"person\",", - " \"target_id\":\"{{uuid:phone1_id}}\",", - " \"target_type\":\"phone_number\",", - " \"type\":\"contact\"", + " \"is_primary\": true,", + " \"source_id\": \"{{uuid:generated_0}}\",", + " \"source_type\": \"person\",", + " \"target_id\": \"{{uuid:generated_1}}\",", + " \"target_type\": \"phone_number\",", + " \"type\": \"contact\"", " }',", - " '{{uuid:contact1_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_3}}',", + " '{{uuid:generated_4}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", @@ -2364,10 +2369,11 @@ " \"modified_at\",", " \"modified_by\",", " \"type\"", - ") VALUES (", + ")", + "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '{{uuid:email1_id}}',", + " '{{uuid:generated_5}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'email_address'", @@ -2376,7 +2382,8 @@ [ "INSERT INTO agreego.\"email_address\" (", " \"address\"", - ") VALUES (", + ")", + "VALUES (", " 'test@example.com'", ")" ], @@ -2384,19 +2391,20 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", - ") VALUES (", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", + ")", + "VALUES (", " NULL,", " '{", - " \"address\":\"test@example.com\",", - " \"type\":\"email_address\"", + " \"address\": \"test@example.com\",", + " \"type\": \"email_address\"", " }',", - " '{{uuid:email1_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_5}}',", + " '{{uuid:generated_6}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", @@ -2410,10 +2418,11 @@ " \"modified_at\",", " \"modified_by\",", " \"type\"", - ") VALUES (", + ")", + "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '{{uuid:contact2_id}}',", + " '{{uuid:generated_7}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'contact'", @@ -2425,17 +2434,19 @@ " \"source_type\",", " \"target_id\",", " \"target_type\"", - ") VALUES (", - " '{{uuid:person_id}}',", + ")", + "VALUES (", + " '{{uuid:generated_0}}',", " 'person',", - " '{{uuid:email1_id}}',", + " '{{uuid:generated_5}}',", " 'email_address'", ")" ], [ "INSERT INTO agreego.\"contact\" (", " \"is_primary\"", - ") VALUES (", + ")", + "VALUES (", " false", ")" ], @@ -2443,23 +2454,24 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", - ") VALUES (", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", + ")", + "VALUES (", " NULL,", " '{", - " \"is_primary\":false,", - " \"source_id\":\"{{uuid:person_id}}\",", - " \"source_type\":\"person\",", - " \"target_id\":\"{{uuid:email1_id}}\",", - " \"target_type\":\"email_address\",", - " \"type\":\"contact\"", + " \"is_primary\": false,", + " \"source_id\": \"{{uuid:generated_0}}\",", + " \"source_type\": \"person\",", + " \"target_id\": \"{{uuid:generated_5}}\",", + " \"target_type\": \"email_address\",", + " \"type\": \"contact\"", " }',", - " '{{uuid:contact2_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_7}}',", + " '{{uuid:generated_8}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", @@ -2473,10 +2485,11 @@ " \"modified_at\",", " \"modified_by\",", " \"type\"", - ") VALUES (", + ")", + "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '{{uuid:email2_id}}',", + " '{{uuid:generated_9}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'email_address'", @@ -2485,7 +2498,8 @@ [ "INSERT INTO agreego.\"email_address\" (", " \"address\"", - ") VALUES (", + ")", + "VALUES (", " 'test2@example.com'", ")" ], @@ -2493,19 +2507,20 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", - ") VALUES (", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", + ")", + "VALUES (", " NULL,", " '{", - " \"address\":\"test2@example.com\",", - " \"type\":\"email_address\"", + " \"address\": \"test2@example.com\",", + " \"type\": \"email_address\"", " }',", - " '{{uuid:email2_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_9}}',", + " '{{uuid:generated_10}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", @@ -2519,10 +2534,11 @@ " \"modified_at\",", " \"modified_by\",", " \"type\"", - ") VALUES (", + ")", + "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '{{uuid:contact3_id}}',", + " '{{uuid:generated_11}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'contact'", @@ -2534,17 +2550,19 @@ " \"source_type\",", " \"target_id\",", " \"target_type\"", - ") VALUES (", - " '{{uuid:person_id}}',", + ")", + "VALUES (", + " '{{uuid:generated_0}}',", " 'person',", - " '{{uuid:email2_id}}',", + " '{{uuid:generated_9}}',", " 'email_address'", ")" ], [ "INSERT INTO agreego.\"contact\" (", " \"is_primary\"", - ") VALUES (", + ")", + "VALUES (", " false", ")" ], @@ -2552,23 +2570,24 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", - ") VALUES (", + " \"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\"", + " \"is_primary\": false,", + " \"source_id\": \"{{uuid:generated_0}}\",", + " \"source_type\": \"person\",", + " \"target_id\": \"{{uuid:generated_9}}\",", + " \"target_type\": \"email_address\",", + " \"type\": \"contact\"", " }',", - " '{{uuid:contact3_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_11}}',", + " '{{uuid:generated_12}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", @@ -2578,169 +2597,170 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", - ") VALUES (", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", + ")", + "VALUES (", " NULL,", " '{", - " \"first_name\":\"Relation\",", - " \"last_name\":\"Test\",", - " \"type\":\"person\"", + " \"first_name\": \"Relation\",", + " \"last_name\": \"Test\",", + " \"type\": \"person\"", " }',", - " '{{uuid:person_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_0}}',", + " '{{uuid:generated_13}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"first_name\":\"Relation\",", - " \"id\":\"{{uuid:person_id}}\",", - " \"last_name\":\"Test\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"type\":\"person\"", - " },", - " \"new\":{", - " \"first_name\":\"Relation\",", - " \"last_name\":\"Test\",", - " \"type\":\"person\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"first_name\": \"Relation\",", + " \"last_name\": \"Test\",", + " \"id\": \"{{uuid:generated_0}}\",", + " \"type\": \"person\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", + " },", + " \"new\": {", + " \"first_name\": \"Relation\",", + " \"last_name\": \"Test\",", + " \"type\": \"person\"", " }", - " }')" + "}'))" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"id\":\"{{uuid:contact1_id}}\",", - " \"is_primary\":true,", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"source_id\":\"{{uuid:person_id}}\",", - " \"source_type\":\"person\",", - " \"target_id\":\"{{uuid:phone1_id}}\",", - " \"target_type\":\"phone_number\",", - " \"type\":\"contact\"", - " },", - " \"new\":{", - " \"is_primary\":true,", - " \"source_id\":\"{{uuid:person_id}}\",", - " \"source_type\":\"person\",", - " \"target_id\":\"{{uuid:phone1_id}}\",", - " \"target_type\":\"phone_number\",", - " \"type\":\"contact\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"is_primary\": true,", + " \"source_id\": \"{{uuid:generated_0}}\",", + " \"source_type\": \"person\",", + " \"target_id\": \"{{uuid:generated_1}}\",", + " \"target_type\": \"phone_number\",", + " \"id\": \"{{uuid:generated_3}}\",", + " \"type\": \"contact\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", + " },", + " \"new\": {", + " \"is_primary\": true,", + " \"source_id\": \"{{uuid:generated_0}}\",", + " \"source_type\": \"person\",", + " \"target_id\": \"{{uuid:generated_1}}\",", + " \"target_type\": \"phone_number\",", + " \"type\": \"contact\"", " }", - " }')" + "}'))" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"id\":\"{{uuid:phone1_id}}\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"number\":\"555-0001\",", - " \"type\":\"phone_number\"", - " },", - " \"new\":{", - " \"number\":\"555-0001\",", - " \"type\":\"phone_number\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"number\": \"555-0001\",", + " \"id\": \"{{uuid:generated_1}}\",", + " \"type\": \"phone_number\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", + " },", + " \"new\": {", + " \"number\": \"555-0001\",", + " \"type\": \"phone_number\"", " }", - " }')" + "}'))" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"id\":\"{{uuid:contact2_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_type\":\"email_address\",", - " \"type\":\"contact\"", - " },", - " \"new\":{", - " \"is_primary\":false,", - " \"source_id\":\"{{uuid:person_id}}\",", - " \"source_type\":\"person\",", - " \"target_id\":\"{{uuid:email1_id}}\",", - " \"target_type\":\"email_address\",", - " \"type\":\"contact\"", - " }", - "}')" + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"is_primary\": false,", + " \"source_id\": \"{{uuid:generated_0}}\",", + " \"source_type\": \"person\",", + " \"target_id\": \"{{uuid:generated_5}}\",", + " \"target_type\": \"email_address\",", + " \"id\": \"{{uuid:generated_7}}\",", + " \"type\": \"contact\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", + " },", + " \"new\": {", + " \"is_primary\": false,", + " \"source_id\": \"{{uuid:generated_0}}\",", + " \"source_type\": \"person\",", + " \"target_id\": \"{{uuid:generated_5}}\",", + " \"target_type\": \"email_address\",", + " \"type\": \"contact\"", + " }", + "}'))" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"address\":\"test@example.com\",", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"id\":\"{{uuid:email1_id}}\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"type\":\"email_address\"", - " },", - " \"new\":{", - " \"address\":\"test@example.com\",", - " \"type\":\"email_address\"", - " }", - "}')" + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"address\": \"test@example.com\",", + " \"id\": \"{{uuid:generated_5}}\",", + " \"type\": \"email_address\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", + " },", + " \"new\": {", + " \"address\": \"test@example.com\",", + " \"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\": {", + " \"is_primary\": false,", + " \"source_id\": \"{{uuid:generated_0}}\",", + " \"source_type\": \"person\",", + " \"target_id\": \"{{uuid:generated_9}}\",", + " \"target_type\": \"email_address\",", + " \"id\": \"{{uuid:generated_11}}\",", + " \"type\": \"contact\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", + " },", + " \"new\": {", + " \"is_primary\": false,", + " \"source_id\": \"{{uuid:generated_0}}\",", + " \"source_type\": \"person\",", + " \"target_id\": \"{{uuid:generated_9}}\",", + " \"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\"", - " }", - "}')" + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"address\": \"test2@example.com\",", + " \"id\": \"{{uuid:generated_9}}\",", + " \"type\": \"email_address\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", + " },", + " \"new\": {", + " \"address\": \"test2@example.com\",", + " \"type\": \"email_address\"", + " }", + "}'))" ] ] } @@ -2767,60 +2787,66 @@ "success": true, "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.\"person\" t1", - "LEFT JOIN agreego.\"user\" t2 ON t2.id = t1.id", - "LEFT JOIN agreego.\"organization\" t3 ON t3.id = t1.id", - "LEFT JOIN agreego.\"entity\" t4 ON t4.id = t1.id", - "WHERE t1.id = 'abc-archived'" + "JOIN agreego.\"user\" t2 ON ", + "JOIN agreego.\"organization\" t3 ON ", + "JOIN agreego.\"entity\" t4 ON ", + "WHERE", + " t1.id = 'abc-archived')" ], [ "UPDATE agreego.\"entity\" SET", - " \"archived\" = true,", - " \"modified_at\" = '{{timestamp}}',", - " \"modified_by\" = '00000000-0000-0000-0000-000000000000'", - "WHERE id = 'abc-archived'" + " archived = true,", + " modified_at = '{{timestamp}}',", + " modified_by = '00000000-0000-0000-0000-000000000000'", + "WHERE", + " id = 'abc-archived'" ], [ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", - ") VALUES (", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", + ")", + "VALUES (", " '{", - " \"archived\":false", + " \"archived\": false", + " }',", + " '{", + " \"archived\": true,", + " \"type\": \"person\"", " }',", - " '{\"archived\":true,\"type\":\"person\"}',", " 'abc-archived',", - " '{{uuid}}',", + " '{{uuid:generated_0}}',", " 'delete',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"archived\":true,", - " \"first_name\":\"ArchivedFirst\",", - " \"id\":\"abc-archived\",", - " \"last_name\":\"ArchivedLast\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"type\":\"person\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"id\": \"abc-archived\",", + " \"type\": \"person\",", + " \"first_name\": \"ArchivedFirst\",", + " \"last_name\": \"ArchivedLast\",", + " \"archived\": true,", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", " },", - " \"new\":{", - " \"archived\":true,", - " \"type\":\"person\"", + " \"new\": {", + " \"archived\": true,", + " \"type\": \"person\"", " },", - " \"old\":{", - " \"archived\":false", + " \"old\": {", + " \"archived\": false", " }", - " }')" + "}'))" ] ] } @@ -2857,7 +2883,7 @@ "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '{{uuid:attachment_id}}',", + " '{{uuid:generated_0}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'attachment'", @@ -2873,57 +2899,82 @@ ")", "VALUES (", " '{\"urgent\",\"reviewed\"}',", - " '{{uuid:attachment_id}}',", - " '{\"other\":\"hello\"}',", + " '{{uuid:generated_0}}',", + " '{", + " \"other\": \"hello\"", + " }',", " 'attachment',", - " '{\"type\":\"type_metadata\"}'", + " '{", + " \"type\": \"type_metadata\"", + " }'", ")" ], [ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"flags\":[\"urgent\",\"reviewed\"],", - " \"other_metadata\":{\"other\":\"hello\"},", - " \"type\":\"attachment\",", - " \"type_metadata\":{\"type\":\"type_metadata\"}", + " \"flags\": [", + " \"urgent\",", + " \"reviewed\"", + " ],", + " \"other_metadata\": {", + " \"other\": \"hello\"", + " },", + " \"type_metadata\": {", + " \"type\": \"type_metadata\"", + " },", + " \"type\": \"attachment\"", " }',", - " '{{uuid:attachment_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_0}}',", + " '{{uuid:generated_1}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"flags\":[\"urgent\",\"reviewed\"],", - " \"id\":\"{{uuid:attachment_id}}\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"other_metadata\":{\"other\":\"hello\"},", - " \"type\":\"attachment\",", - " \"type_metadata\":{\"type\":\"type_metadata\"}", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"flags\": [", + " \"urgent\",", + " \"reviewed\"", + " ],", + " \"other_metadata\": {", + " \"other\": \"hello\"", + " },", + " \"type_metadata\": {", + " \"type\": \"type_metadata\"", + " },", + " \"id\": \"{{uuid:generated_0}}\",", + " \"type\": \"attachment\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", " },", - " \"new\":{", - " \"flags\":[\"urgent\",\"reviewed\"],", - " \"other_metadata\":{\"other\":\"hello\"},", - " \"type\":\"attachment\",", - " \"type_metadata\":{\"type\":\"type_metadata\"}", + " \"new\": {", + " \"flags\": [", + " \"urgent\",", + " \"reviewed\"", + " ],", + " \"other_metadata\": {", + " \"other\": \"hello\"", + " },", + " \"type_metadata\": {", + " \"type\": \"type_metadata\"", + " },", + " \"type\": \"attachment\"", " }", - " }')" + "}'))" ] ] } @@ -2958,7 +3009,7 @@ "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '{{uuid:line_id}}',", + " '{{uuid:generated_0}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'order_line'", @@ -2973,7 +3024,7 @@ " \"type\"", ")", "VALUES (", - " '{{uuid:line_id}}',", + " '{{uuid:generated_0}}',", " 'abc',", " 99,", " 'Widget',", @@ -2984,47 +3035,47 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"order_id\":\"abc\",", - " \"price\":99.0,", - " \"product\":\"Widget\",", - " \"type\":\"order_line\"", + " \"product\": \"Widget\",", + " \"price\": 99.0,", + " \"order_id\": \"abc\",", + " \"type\": \"order_line\"", " }',", - " '{{uuid:line_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_0}}',", + " '{{uuid:generated_1}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"id\":\"{{uuid:line_id}}\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"order_id\":\"abc\",", - " \"price\":99.0,", - " \"product\":\"Widget\",", - " \"type\":\"order_line\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"product\": \"Widget\",", + " \"price\": 99.0,", + " \"order_id\": \"abc\",", + " \"id\": \"{{uuid:generated_0}}\",", + " \"type\": \"order_line\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", " },", - " \"new\":{", - " \"order_id\":\"abc\",", - " \"price\":99.0,", - " \"product\":\"Widget\",", - " \"type\":\"order_line\"", + " \"new\": {", + " \"product\": \"Widget\",", + " \"price\": 99.0,", + " \"order_id\": \"abc\",", + " \"type\": \"order_line\"", " }", - " }')" + "}'))" ] ] } @@ -3049,10 +3100,11 @@ "success": true, "sql": [ [ - "SELECT to_jsonb(t1.*) || to_jsonb(t2.*)", + "(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)", "FROM agreego.\"order_line\" t1", - "LEFT JOIN agreego.\"entity\" t2 ON t2.id = t1.id", - "WHERE t1.id = '11111111-2222-3333-4444-555555555555'" + "JOIN agreego.\"entity\" t2 ON ", + "WHERE", + " t1.id = '{{uuid:data.lines.0.id}}')" ], [ "INSERT INTO agreego.\"entity\" (", @@ -3066,7 +3118,7 @@ "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '11111111-2222-3333-4444-555555555555',", + " '{{uuid:data.lines.0.id}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'order_line'", @@ -3081,7 +3133,7 @@ " \"type\"", ")", "VALUES (", - " '11111111-2222-3333-4444-555555555555',", + " '{{uuid:data.lines.0.id}}',", " 'abc',", " 99,", " 'Widget',", @@ -3092,47 +3144,47 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"order_id\":\"abc\",", - " \"price\":99.0,", - " \"product\":\"Widget\",", - " \"type\":\"order_line\"", + " \"product\": \"Widget\",", + " \"price\": 99.0,", + " \"order_id\": \"abc\",", + " \"type\": \"order_line\"", " }',", - " '11111111-2222-3333-4444-555555555555',", - " '{{uuid}}',", + " '{{uuid:data.lines.0.id}}',", + " '{{uuid:generated_0}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"id\":\"11111111-2222-3333-4444-555555555555\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"order_id\":\"abc\",", - " \"price\":99.0,", - " \"product\":\"Widget\",", - " \"type\":\"order_line\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"product\": \"Widget\",", + " \"price\": 99.0,", + " \"order_id\": \"abc\",", + " \"id\": \"{{uuid:data.lines.0.id}}\",", + " \"type\": \"order_line\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", " },", - " \"new\":{", - " \"order_id\":\"abc\",", - " \"price\":99.0,", - " \"product\":\"Widget\",", - " \"type\":\"order_line\"", + " \"new\": {", + " \"product\": \"Widget\",", + " \"price\": 99.0,", + " \"order_id\": \"abc\",", + " \"type\": \"order_line\"", " }", - " }')" + "}'))" ] ] } @@ -3171,10 +3223,12 @@ "success": true, "sql": [ [ - "SELECT to_jsonb(t1.*) || to_jsonb(t2.*)", + "(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)", "FROM agreego.\"invoice\" t1", - "LEFT JOIN agreego.\"entity\" t2 ON t2.id = t1.id", - "WHERE t1.id = '11111111-2222-3333-4444-555555555555' OR (\"id\" = '11111111-2222-3333-4444-555555555555')" + "JOIN agreego.\"entity\" t2 ON ", + "WHERE", + " t1.id = '{{uuid:data.id}}'", + " OR (\"id\" = '{{uuid:data.id}}'))" ], [ "INSERT INTO agreego.\"entity\" (", @@ -3188,7 +3242,7 @@ "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '11111111-2222-3333-4444-555555555555',", + " '{{uuid:data.id}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'invoice'", @@ -3205,11 +3259,23 @@ " \"type\"", ")", "VALUES (", - " '11111111-2222-3333-4444-555555555555',", - " '{\"price\":50}',", + " '{{uuid:data.id}}',", + " '{", + " \"price\": 50", + " }',", " '[{\"price\":25}]',", - " '{\"line\":{\"price\":75}}',", - " '{\"lines\":[{\"price\":100}]}',", + " '{", + " \"line\": {", + " \"price\": 75", + " }", + " }',", + " '{", + " \"lines\": [", + " {", + " \"price\": 100", + " }", + " ]", + " }',", " 200,", " 'invoice'", ")" @@ -3218,24 +3284,40 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"metadata_line\":{\"price\":50},", - " \"metadata_lines\":[{\"price\":25}],", - " \"metadata_nested_line\":{\"line\":{\"price\":75}},", - " \"metadata_nested_lines\":{\"lines\":[{\"price\":100}]},", - " \"total\":200.0,", - " \"type\":\"invoice\"", + " \"total\": 200.0,", + " \"metadata_line\": {", + " \"price\": 50", + " },", + " \"metadata_lines\": [", + " {", + " \"price\": 25", + " }", + " ],", + " \"metadata_nested_line\": {", + " \"line\": {", + " \"price\": 75", + " }", + " },", + " \"metadata_nested_lines\": {", + " \"lines\": [", + " {", + " \"price\": 100", + " }", + " ]", + " },", + " \"type\": \"invoice\"", " }',", - " '11111111-2222-3333-4444-555555555555',", - " '{{uuid}}',", + " '{{uuid:data.id}}',", + " '{{uuid:generated_0}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", @@ -3258,10 +3340,11 @@ "success": true, "sql": [ [ - "SELECT to_jsonb(t1.*) || to_jsonb(t2.*)", + "(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)", "FROM agreego.\"account\" t1", - "LEFT JOIN agreego.\"entity\" t2 ON t2.id = t1.id", - "WHERE t1.id = '11111111-2222-3333-4444-555555555555'" + "JOIN agreego.\"entity\" t2 ON ", + "WHERE", + " t1.id = '{{uuid:data.id}}')" ], [ "INSERT INTO agreego.\"entity\" (", @@ -3275,7 +3358,7 @@ "VALUES (", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", - " '11111111-2222-3333-4444-555555555555',", + " '{{uuid:data.id}}',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000',", " 'account'", @@ -3289,7 +3372,7 @@ " \"type\"", ")", "VALUES (", - " '11111111-2222-3333-4444-555555555555',", + " '{{uuid:data.id}}',", " 'checking',", " '123456789',", " 'account'", @@ -3299,44 +3382,44 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"kind\":\"checking\",", - " \"routing_number\":\"123456789\",", - " \"type\":\"account\"", + " \"kind\": \"checking\",", + " \"routing_number\": \"123456789\",", + " \"type\": \"account\"", " }',", - " '11111111-2222-3333-4444-555555555555',", - " '{{uuid}}',", + " '{{uuid:data.id}}',", + " '{{uuid:generated_0}}',", " 'create',", " '{{timestamp}}',", " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"id\":\"11111111-2222-3333-4444-555555555555\",", - " \"kind\":\"checking\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"routing_number\":\"123456789\",", - " \"type\":\"account\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"kind\": \"checking\",", + " \"routing_number\": \"123456789\",", + " \"id\": \"{{uuid:data.id}}\",", + " \"type\": \"account\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", " },", - " \"new\":{", - " \"kind\":\"checking\",", - " \"routing_number\":\"123456789\",", - " \"type\":\"account\"", + " \"new\": {", + " \"kind\": \"checking\",", + " \"routing_number\": \"123456789\",", + " \"type\": \"account\"", " }", - " }')" + "}'))" ] ] } @@ -3378,11 +3461,11 @@ ")", "VALUES (", " '{{timestamp}}',", - " '{{uuid}}',", - " '{{uuid:person_id}}',", + " '00000000-0000-0000-0000-000000000000',", + " '{{uuid:generated_0}}',", " '{{timestamp}}',", - " '{{uuid}}',", - " 'ffffffff-ffff-ffff-ffff-ffffffffffff',", + " '00000000-0000-0000-0000-000000000000',", + " '{{uuid:generated_1}}',", " 'person'", ")" ], @@ -3392,7 +3475,7 @@ " \"type\"", ")", "VALUES (", - " '{{uuid:person_id}}',", + " '{{uuid:generated_0}}',", " 'person'", ")" ], @@ -3402,7 +3485,7 @@ " \"type\"", ")", "VALUES (", - " '{{uuid:person_id}}',", + " '{{uuid:generated_0}}',", " 'person'", ")" ], @@ -3415,7 +3498,7 @@ ")", "VALUES (", " 'Const',", - " '{{uuid:person_id}}',", + " '{{uuid:generated_0}}',", " 'Person',", " 'person'", ")" @@ -3424,25 +3507,25 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"first_name\":\"Const\",", - " \"last_name\":\"Person\",", - " \"organization_id\":\"ffffffff-ffff-ffff-ffff-ffffffffffff\",", - " \"type\":\"person\"", + " \"first_name\": \"Const\",", + " \"last_name\": \"Person\",", + " \"type\": \"person\",", + " \"organization_id\": \"{{uuid:generated_1}}\"", " }',", - " '{{uuid:person_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_0}}',", + " '{{uuid:generated_2}}',", " 'create',", " '{{timestamp}}',", - " '{{uuid}}'", + " '00000000-0000-0000-0000-000000000000'", ")" ], [ @@ -3457,10 +3540,10 @@ ")", "VALUES (", " '{{timestamp}}',", - " '{{uuid}}',", - " '{{uuid:order_id}}',", + " '00000000-0000-0000-0000-000000000000',", + " '{{uuid:generated_3}}',", " '{{timestamp}}',", - " '{{uuid}}',", + " '00000000-0000-0000-0000-000000000000',", " 'parent-org-id',", " 'order'", ")" @@ -3472,8 +3555,8 @@ " \"type\"", ")", "VALUES (", - " '{{uuid:person_id}}',", - " '{{uuid:order_id}}',", + " '{{uuid:generated_0}}',", + " '{{uuid:generated_3}}',", " 'order'", ")" ], @@ -3489,10 +3572,10 @@ ")", "VALUES (", " '{{timestamp}}',", - " '{{uuid}}',", - " '{{uuid:line1_id}}',", + " '00000000-0000-0000-0000-000000000000',", + " '{{uuid:generated_4}}',", " '{{timestamp}}',", - " '{{uuid}}',", + " '00000000-0000-0000-0000-000000000000',", " 'parent-org-id',", " 'order_line'", ")" @@ -3504,8 +3587,8 @@ " \"type\"", ")", "VALUES (", - " '{{uuid:line1_id}}',", - " '{{uuid:order_id}}',", + " '{{uuid:generated_4}}',", + " '{{uuid:generated_3}}',", " 'order_line'", ")" ], @@ -3513,24 +3596,24 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"order_id\":\"{{uuid:order_id}}\",", - " \"organization_id\":\"parent-org-id\",", - " \"type\":\"order_line\"", + " \"order_id\": \"{{uuid:generated_3}}\",", + " \"type\": \"order_line\",", + " \"organization_id\": \"parent-org-id\"", " }',", - " '{{uuid:line1_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_4}}',", + " '{{uuid:generated_5}}',", " 'create',", " '{{timestamp}}',", - " '{{uuid}}'", + " '00000000-0000-0000-0000-000000000000'", ")" ], [ @@ -3545,10 +3628,10 @@ ")", "VALUES (", " '{{timestamp}}',", - " '{{uuid}}',", - " '{{uuid:line2_id}}',", + " '00000000-0000-0000-0000-000000000000',", + " '{{uuid:generated_6}}',", " '{{timestamp}}',", - " '{{uuid}}',", + " '00000000-0000-0000-0000-000000000000',", " 'explicit-org-id',", " 'order_line'", ")" @@ -3560,8 +3643,8 @@ " \"type\"", ")", "VALUES (", - " '{{uuid:line2_id}}',", - " '{{uuid:order_id}}',", + " '{{uuid:generated_6}}',", + " '{{uuid:generated_3}}',", " 'order_line'", ")" ], @@ -3569,127 +3652,127 @@ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"order_id\":\"{{uuid:order_id}}\",", - " \"organization_id\":\"explicit-org-id\",", - " \"type\":\"order_line\"", + " \"organization_id\": \"explicit-org-id\",", + " \"order_id\": \"{{uuid:generated_3}}\",", + " \"type\": \"order_line\"", " }',", - " '{{uuid:line2_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_6}}',", + " '{{uuid:generated_7}}',", " 'create',", " '{{timestamp}}',", - " '{{uuid}}'", + " '00000000-0000-0000-0000-000000000000'", ")" ], [ "INSERT INTO agreego.change (", " \"old\",", " \"new\",", - " entity_id,", - " id,", - " kind,", - " modified_at,", - " modified_by", + " \"entity_id\",", + " \"id\",", + " \"kind\",", + " \"modified_at\",", + " \"modified_by\"", ")", "VALUES (", " NULL,", " '{", - " \"customer_id\":\"{{uuid:person_id}}\",", - " \"organization_id\":\"parent-org-id\",", - " \"type\":\"order\"", + " \"organization_id\": \"parent-org-id\",", + " \"type\": \"order\",", + " \"customer_id\": \"{{uuid:generated_0}}\"", " }',", - " '{{uuid:order_id}}',", - " '{{uuid}}',", + " '{{uuid:generated_3}}',", + " '{{uuid:generated_8}}',", " 'create',", " '{{timestamp}}',", - " '{{uuid}}'", + " '00000000-0000-0000-0000-000000000000'", ")" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"customer_id\":\"{{uuid:person_id}}\",", - " \"id\":\"{{uuid:order_id}}\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"organization_id\":\"parent-org-id\",", - " \"type\":\"order\"", - " },", - " \"new\":{", - " \"customer_id\":\"{{uuid:person_id}}\",", - " \"organization_id\":\"parent-org-id\",", - " \"type\":\"order\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"organization_id\": \"parent-org-id\",", + " \"id\": \"{{uuid:generated_3}}\",", + " \"type\": \"order\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\",", + " \"customer_id\": \"{{uuid:generated_0}}\"", + " },", + " \"new\": {", + " \"organization_id\": \"parent-org-id\",", + " \"type\": \"order\",", + " \"customer_id\": \"{{uuid:generated_0}}\"", " }", - " }')" + "}'))" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"first_name\":\"Const\",", - " \"id\":\"{{uuid:person_id}}\",", - " \"last_name\":\"Person\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"organization_id\":\"ffffffff-ffff-ffff-ffff-ffffffffffff\",", - " \"type\":\"person\"", - " },", - " \"new\":{", - " \"first_name\":\"Const\",", - " \"last_name\":\"Person\",", - " \"organization_id\":\"ffffffff-ffff-ffff-ffff-ffffffffffff\",", - " \"type\":\"person\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"first_name\": \"Const\",", + " \"last_name\": \"Person\",", + " \"id\": \"{{uuid:generated_0}}\",", + " \"type\": \"person\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\",", + " \"organization_id\": \"{{uuid:generated_1}}\"", + " },", + " \"new\": {", + " \"first_name\": \"Const\",", + " \"last_name\": \"Person\",", + " \"type\": \"person\",", + " \"organization_id\": \"{{uuid:generated_1}}\"", " }", - " }')" + "}'))" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"id\":\"{{uuid:line1_id}}\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"order_id\":\"{{uuid:order_id}}\",", - " \"organization_id\":\"parent-org-id\",", - " \"type\":\"order_line\"", - " },", - " \"new\":{", - " \"order_id\":\"{{uuid:order_id}}\",", - " \"organization_id\":\"parent-org-id\",", - " \"type\":\"order_line\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"order_id\": \"{{uuid:generated_3}}\",", + " \"id\": \"{{uuid:generated_4}}\",", + " \"type\": \"order_line\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\",", + " \"organization_id\": \"parent-org-id\"", + " },", + " \"new\": {", + " \"order_id\": \"{{uuid:generated_3}}\",", + " \"type\": \"order_line\",", + " \"organization_id\": \"parent-org-id\"", " }", - " }')" + "}'))" ], [ - "SELECT pg_notify('entity', '{", - " \"complete\":{", - " \"created_at\":\"{{timestamp}}\",", - " \"created_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"id\":\"{{uuid:line2_id}}\",", - " \"modified_at\":\"{{timestamp}}\",", - " \"modified_by\":\"00000000-0000-0000-0000-000000000000\",", - " \"order_id\":\"{{uuid:order_id}}\",", - " \"organization_id\":\"explicit-org-id\",", - " \"type\":\"order_line\"", - " },", - " \"new\":{", - " \"order_id\":\"{{uuid:order_id}}\",", - " \"organization_id\":\"explicit-org-id\",", - " \"type\":\"order_line\"", + "(SELECT pg_notify('entity', '{", + " \"complete\": {", + " \"organization_id\": \"explicit-org-id\",", + " \"order_id\": \"{{uuid:generated_3}}\",", + " \"id\": \"{{uuid:generated_6}}\",", + " \"type\": \"order_line\",", + " \"created_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"created_at\": \"{{timestamp}}\",", + " \"modified_by\": \"00000000-0000-0000-0000-000000000000\",", + " \"modified_at\": \"{{timestamp}}\"", + " },", + " \"new\": {", + " \"organization_id\": \"explicit-org-id\",", + " \"order_id\": \"{{uuid:generated_3}}\",", + " \"type\": \"order_line\"", " }", - " }')" + "}'))" ] ] } diff --git a/fixtures/queryer.json b/fixtures/queryer.json index 9aa4507..80616eb 100644 --- a/fixtures/queryer.json +++ b/fixtures/queryer.json @@ -1180,13 +1180,17 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT jsonb_build_object(", - " 'archived', entity_1.archived,", - " 'created_at', entity_1.created_at,", - " 'id', entity_1.id,", - " 'type', entity_1.type)", - "FROM agreego.entity entity_1", - "WHERE NOT entity_1.archived)))" + "((SELECT jsonb_strip_nulls((", + " SELECT jsonb_build_object(", + " 'id', entity_1.id,", + " 'type', entity_1.type,", + " 'archived', entity_1.archived,", + " 'created_at', entity_1.created_at", + " )", + " FROM agreego.entity entity_1", + " WHERE", + " NOT entity_1.archived", + "))))" ] ] } @@ -1223,28 +1227,29 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT jsonb_build_object(", - " 'archived', entity_1.archived,", - " 'created_at', entity_1.created_at,", - " 'id', entity_1.id,", - " 'type', entity_1.type", - ")", - "FROM agreego.entity entity_1", - "WHERE", - " NOT entity_1.archived", - " AND entity_1.archived = ($1#>>'{}')::boolean", - " AND entity_1.archived != ($2#>>'{}')::boolean", - " AND entity_1.created_at = ($3#>>'{}')::timestamptz", - " AND entity_1.created_at > ($4#>>'{}')::timestamptz", - " AND entity_1.created_at >= ($5#>>'{}')::timestamptz", - " AND entity_1.created_at < ($6#>>'{}')::timestamptz", - " AND entity_1.created_at <= ($7#>>'{}')::timestamptz", - " AND entity_1.created_at != ($8#>>'{}')::timestamptz", - " AND entity_1.id = ($9#>>'{}')::uuid", - " AND entity_1.id != ($10#>>'{}')::uuid", - " AND entity_1.id NOT IN (SELECT value::uuid FROM jsonb_array_elements_text(($11#>>'{}')::jsonb))", - " AND entity_1.id IN (SELECT value::uuid FROM jsonb_array_elements_text(($12#>>'{}')::jsonb))", - ")))" + "((SELECT jsonb_strip_nulls((", + " SELECT jsonb_build_object(", + " 'id', entity_1.id,", + " 'type', entity_1.type,", + " 'archived', entity_1.archived,", + " 'created_at', entity_1.created_at", + " )", + " FROM agreego.entity entity_1", + " WHERE", + " NOT entity_1.archived", + " AND entity_1.archived = ($1 #>> '{}')::BOOLEAN", + " AND entity_1.archived <> ($2 #>> '{}')::BOOLEAN", + " AND entity_1.created_at = ($3 #>> '{}')::TIMESTAMPTZ", + " AND entity_1.created_at > ($4 #>> '{}')::TIMESTAMPTZ", + " AND entity_1.created_at >= ($5 #>> '{}')::TIMESTAMPTZ", + " AND entity_1.created_at < ($6 #>> '{}')::TIMESTAMPTZ", + " AND entity_1.created_at <= ($7 #>> '{}')::TIMESTAMPTZ", + " AND entity_1.created_at <> ($8 #>> '{}')::TIMESTAMPTZ", + " AND entity_1.id = ($9 #>> '{}')::UUID", + " AND entity_1.id <> ($10 #>> '{}')::UUID", + " AND entity_1.id NOT IN (SELECT value::UUID FROM jsonb_array_elements_text(($11 #>> '{}')::jsonb))", + " AND entity_1.id IN (SELECT value::UUID FROM jsonb_array_elements_text(($12 #>> '{}')::jsonb))", + "))))" ] ] } @@ -1257,19 +1262,23 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT jsonb_build_object(", - " 'archived', entity_3.archived,", - " 'created_at', entity_3.created_at,", - " 'id', entity_3.id,", - " 'type', entity_3.type,", - " 'name', organization_2.name,", - " 'age', person_1.age,", - " 'first_name', person_1.first_name,", - " 'last_name', person_1.last_name)", - "FROM agreego.person person_1", - "JOIN agreego.organization organization_2 ON organization_2.id = person_1.id", - "JOIN agreego.entity entity_3 ON entity_3.id = organization_2.id", - "WHERE NOT entity_3.archived)))" + "((SELECT jsonb_strip_nulls((", + " SELECT jsonb_build_object(", + " 'id', entity_3.id,", + " 'type', entity_3.type,", + " 'archived', entity_3.archived,", + " 'created_at', entity_3.created_at,", + " 'name', organization_2.name,", + " 'first_name', person_1.first_name,", + " 'last_name', person_1.last_name,", + " 'age', person_1.age", + " )", + " FROM agreego.person person_1", + " JOIN agreego.organization organization_2 ON organization_2.id = person_1.id", + " JOIN agreego.entity entity_3 ON entity_3.id = organization_2.id", + " WHERE", + " NOT entity_3.archived", + "))))" ] ] } @@ -1282,159 +1291,173 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT jsonb_build_object(", - " 'addresses',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_6.archived,", - " 'created_at', entity_6.created_at,", - " 'id', entity_6.id,", - " 'is_primary', contact_4.is_primary,", - " 'target',", - " (SELECT jsonb_build_object(", - " 'archived', entity_8.archived,", - " 'city', address_7.city,", - " 'created_at', entity_8.created_at,", - " 'id', entity_8.id,", - " 'type', entity_8.type", + "((SELECT jsonb_strip_nulls((", + " SELECT jsonb_build_object(", + " 'id', entity_3.id,", + " 'type', entity_3.type,", + " 'archived', entity_3.archived,", + " 'created_at', entity_3.created_at,", + " 'name', organization_2.name,", + " 'first_name', person_1.first_name,", + " 'last_name', person_1.last_name,", + " 'age', person_1.age,", + " 'phone_numbers', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', entity_6.id,", + " 'type', entity_6.type,", + " 'archived', entity_6.archived,", + " 'created_at', entity_6.created_at,", + " 'is_primary', contact_4.is_primary,", + " 'target', (", + " SELECT jsonb_build_object(", + " 'id', entity_8.id,", + " 'type', entity_8.type,", + " 'archived', entity_8.archived,", + " 'created_at', entity_8.created_at,", + " 'number', phone_number_7.number", + " )", + " FROM agreego.phone_number phone_number_7", + " JOIN agreego.entity entity_8 ON entity_8.id = phone_number_7.id", + " WHERE", + " NOT entity_8.archived", + " AND relationship_5.target_id = entity_8.id", + " )", + " )), '[]'::jsonb)", + " FROM agreego.contact contact_4", + " JOIN agreego.relationship relationship_5 ON relationship_5.id = contact_4.id", + " JOIN agreego.entity entity_6 ON entity_6.id = relationship_5.id", + " WHERE", + " NOT entity_6.archived", + " AND relationship_5.target_type = 'phone_number'", + " AND relationship_5.source_id = entity_3.id", + " ),", + " 'email_addresses', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', entity_11.id,", + " 'type', entity_11.type,", + " 'archived', entity_11.archived,", + " 'created_at', entity_11.created_at,", + " 'is_primary', contact_9.is_primary,", + " 'target', (", + " SELECT jsonb_build_object(", + " 'id', entity_13.id,", + " 'type', entity_13.type,", + " 'archived', entity_13.archived,", + " 'created_at', entity_13.created_at,", + " 'address', email_address_12.address", + " )", + " FROM agreego.email_address email_address_12", + " JOIN agreego.entity entity_13 ON entity_13.id = email_address_12.id", + " WHERE", + " NOT entity_13.archived", + " AND relationship_10.target_id = entity_13.id", + " )", + " )), '[]'::jsonb)", + " FROM agreego.contact contact_9", + " JOIN agreego.relationship relationship_10 ON relationship_10.id = contact_9.id", + " JOIN agreego.entity entity_11 ON entity_11.id = relationship_10.id", + " WHERE", + " NOT entity_11.archived", + " AND relationship_10.target_type = 'email_address'", + " AND relationship_10.source_id = entity_3.id", + " ),", + " 'addresses', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', entity_16.id,", + " 'type', entity_16.type,", + " 'archived', entity_16.archived,", + " 'created_at', entity_16.created_at,", + " 'is_primary', contact_14.is_primary,", + " 'target', (", + " SELECT jsonb_build_object(", + " 'id', entity_18.id,", + " 'type', entity_18.type,", + " 'archived', entity_18.archived,", + " 'created_at', entity_18.created_at,", + " 'city', address_17.city", + " )", + " FROM agreego.address address_17", + " JOIN agreego.entity entity_18 ON entity_18.id = address_17.id", + " WHERE", + " NOT entity_18.archived", + " AND relationship_15.target_id = entity_18.id", + " )", + " )), '[]'::jsonb)", + " FROM agreego.contact contact_14", + " JOIN agreego.relationship relationship_15 ON relationship_15.id = contact_14.id", + " JOIN agreego.entity entity_16 ON entity_16.id = relationship_15.id", + " WHERE", + " NOT entity_16.archived", + " AND relationship_15.target_type = 'address'", + " AND relationship_15.source_id = entity_3.id", + " ),", + " 'contacts', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', entity_21.id,", + " 'type', entity_21.type,", + " 'archived', entity_21.archived,", + " 'created_at', entity_21.created_at,", + " 'is_primary', contact_19.is_primary,", + " 'target', CASE", + " WHEN relationship_20.target_type = 'phone_number' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_23.id,", + " 'type', entity_23.type,", + " 'archived', entity_23.archived,", + " 'created_at', entity_23.created_at,", + " 'number', phone_number_22.number", + " )", + " FROM agreego.phone_number phone_number_22", + " JOIN agreego.entity entity_23 ON entity_23.id = phone_number_22.id", + " WHERE", + " NOT entity_23.archived", + " AND relationship_20.target_id = entity_23.id", + " ))", + " WHEN relationship_20.target_type = 'email_address' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_25.id,", + " 'type', entity_25.type,", + " 'archived', entity_25.archived,", + " 'created_at', entity_25.created_at,", + " 'address', email_address_24.address", + " )", + " FROM agreego.email_address email_address_24", + " JOIN agreego.entity entity_25 ON entity_25.id = email_address_24.id", + " WHERE", + " NOT entity_25.archived", + " AND relationship_20.target_id = entity_25.id", + " ))", + " WHEN relationship_20.target_type = 'address' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_27.id,", + " 'type', entity_27.type,", + " 'archived', entity_27.archived,", + " 'created_at', entity_27.created_at,", + " 'city', address_26.city", + " )", + " FROM agreego.address address_26", + " JOIN agreego.entity entity_27 ON entity_27.id = address_26.id", + " WHERE", + " NOT entity_27.archived", + " AND relationship_20.target_id = entity_27.id", + " ))", + " ELSE NULL", + " END", + " )), '[]'::jsonb)", + " FROM agreego.contact contact_19", + " JOIN agreego.relationship relationship_20 ON relationship_20.id = contact_19.id", + " JOIN agreego.entity entity_21 ON entity_21.id = relationship_20.id", + " WHERE", + " NOT entity_21.archived", + " AND relationship_20.source_id = entity_3.id", " )", - " FROM agreego.address address_7", - " JOIN agreego.entity entity_8 ON entity_8.id = address_7.id", - " WHERE", - " NOT entity_8.archived", - " AND relationship_5.target_id = entity_8.id),", - " 'type', entity_6.type", - " )), '[]'::jsonb)", - " FROM agreego.contact contact_4", - " JOIN agreego.relationship relationship_5 ON relationship_5.id = contact_4.id", - " JOIN agreego.entity entity_6 ON entity_6.id = relationship_5.id", + " )", + " FROM agreego.person person_1", + " JOIN agreego.organization organization_2 ON organization_2.id = person_1.id", + " JOIN agreego.entity entity_3 ON entity_3.id = organization_2.id", " WHERE", - " NOT entity_6.archived", - " AND relationship_5.target_type = 'address'", - " AND relationship_5.source_id = entity_3.id),", - " 'age', person_1.age,", - " 'archived', entity_3.archived,", - " 'contacts',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_11.archived,", - " 'created_at', entity_11.created_at,", - " 'id', entity_11.id,", - " 'is_primary', contact_9.is_primary,", - " 'target', CASE", - " WHEN relationship_10.target_type = 'address' THEN", - " ((SELECT jsonb_build_object(", - " 'archived', entity_13.archived,", - " 'city', address_12.city,", - " 'created_at', entity_13.created_at,", - " 'id', entity_13.id,", - " 'type', entity_13.type", - " )", - " FROM agreego.address address_12", - " JOIN agreego.entity entity_13 ON entity_13.id = address_12.id", - " WHERE", - " NOT entity_13.archived", - " AND relationship_10.target_id = entity_13.id))", - " WHEN relationship_10.target_type = 'email_address' THEN", - " ((SELECT jsonb_build_object(", - " 'address', email_address_14.address,", - " 'archived', entity_15.archived,", - " 'created_at', entity_15.created_at,", - " 'id', entity_15.id,", - " 'type', entity_15.type", - " )", - " FROM agreego.email_address email_address_14", - " JOIN agreego.entity entity_15 ON entity_15.id = email_address_14.id", - " WHERE", - " NOT entity_15.archived", - " AND relationship_10.target_id = entity_15.id))", - " WHEN relationship_10.target_type = 'phone_number' THEN", - " ((SELECT jsonb_build_object(", - " 'archived', entity_17.archived,", - " 'created_at', entity_17.created_at,", - " 'id', entity_17.id,", - " 'number', phone_number_16.number,", - " 'type', entity_17.type", - " )", - " FROM agreego.phone_number phone_number_16", - " JOIN agreego.entity entity_17 ON entity_17.id = phone_number_16.id", - " WHERE", - " NOT entity_17.archived", - " AND relationship_10.target_id = entity_17.id))", - " ELSE NULL END,", - " 'type', entity_11.type", - " )), '[]'::jsonb)", - " FROM agreego.contact contact_9", - " JOIN agreego.relationship relationship_10 ON relationship_10.id = contact_9.id", - " JOIN agreego.entity entity_11 ON entity_11.id = relationship_10.id", - " WHERE", - " NOT entity_11.archived", - " AND relationship_10.source_id = entity_3.id),", - " 'created_at', entity_3.created_at,", - " 'email_addresses',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_20.archived,", - " 'created_at', entity_20.created_at,", - " 'id', entity_20.id,", - " 'is_primary', contact_18.is_primary,", - " 'target',", - " (SELECT jsonb_build_object(", - " 'address', email_address_21.address,", - " 'archived', entity_22.archived,", - " 'created_at', entity_22.created_at,", - " 'id', entity_22.id,", - " 'type', entity_22.type", - " )", - " FROM agreego.email_address email_address_21", - " JOIN agreego.entity entity_22 ON entity_22.id = email_address_21.id", - " WHERE", - " NOT entity_22.archived", - " AND relationship_19.target_id = entity_22.id),", - " 'type', entity_20.type", - " )), '[]'::jsonb)", - " FROM agreego.contact contact_18", - " JOIN agreego.relationship relationship_19 ON relationship_19.id = contact_18.id", - " JOIN agreego.entity entity_20 ON entity_20.id = relationship_19.id", - " WHERE", - " NOT entity_20.archived", - " AND relationship_19.target_type = 'email_address'", - " AND relationship_19.source_id = entity_3.id),", - " 'first_name', person_1.first_name,", - " 'id', entity_3.id,", - " 'last_name', person_1.last_name,", - " 'name', organization_2.name,", - " 'phone_numbers',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_25.archived,", - " 'created_at', entity_25.created_at,", - " 'id', entity_25.id,", - " 'is_primary', contact_23.is_primary,", - " 'target',", - " (SELECT jsonb_build_object(", - " 'archived', entity_27.archived,", - " 'created_at', entity_27.created_at,", - " 'id', entity_27.id,", - " 'number', phone_number_26.number,", - " 'type', entity_27.type", - " )", - " FROM agreego.phone_number phone_number_26", - " JOIN agreego.entity entity_27 ON entity_27.id = phone_number_26.id", - " WHERE", - " NOT entity_27.archived", - " AND relationship_24.target_id = entity_27.id),", - " 'type', entity_25.type", - " )), '[]'::jsonb)", - " FROM agreego.contact contact_23", - " JOIN agreego.relationship relationship_24 ON relationship_24.id = contact_23.id", - " JOIN agreego.entity entity_25 ON entity_25.id = relationship_24.id", - " WHERE", - " NOT entity_25.archived", - " AND relationship_24.target_type = 'phone_number'", - " AND relationship_24.source_id = entity_3.id),", - " 'type', entity_3.type", - ")", - "FROM agreego.person person_1", - "JOIN agreego.organization organization_2 ON organization_2.id = person_1.id", - "JOIN agreego.entity entity_3 ON entity_3.id = organization_2.id", - "WHERE NOT entity_3.archived)))" + " NOT entity_3.archived", + "))))" ] ] } @@ -1518,192 +1541,205 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT jsonb_build_object(", - " 'addresses',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_6.archived,", - " 'created_at', entity_6.created_at,", - " 'id', entity_6.id,", - " 'is_primary', contact_4.is_primary,", - " 'target',", - " (SELECT jsonb_build_object(", - " 'archived', entity_8.archived,", - " 'city', address_7.city,", - " 'created_at', entity_8.created_at,", - " 'id', entity_8.id,", - " 'type', entity_8.type", + "((SELECT jsonb_strip_nulls((", + " SELECT jsonb_build_object(", + " 'id', entity_3.id,", + " 'type', entity_3.type,", + " 'archived', entity_3.archived,", + " 'created_at', entity_3.created_at,", + " 'name', organization_2.name,", + " 'first_name', person_1.first_name,", + " 'last_name', person_1.last_name,", + " 'age', person_1.age,", + " 'phone_numbers', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', entity_6.id,", + " 'type', entity_6.type,", + " 'archived', entity_6.archived,", + " 'created_at', entity_6.created_at,", + " 'is_primary', contact_4.is_primary,", + " 'target', (", + " SELECT jsonb_build_object(", + " 'id', entity_8.id,", + " 'type', entity_8.type,", + " 'archived', entity_8.archived,", + " 'created_at', entity_8.created_at,", + " 'number', phone_number_7.number", + " )", + " FROM agreego.phone_number phone_number_7", + " JOIN agreego.entity entity_8 ON entity_8.id = phone_number_7.id", + " WHERE", + " NOT entity_8.archived", + " AND phone_number_7.number ILIKE $32 #>> '{}'", + " AND relationship_5.target_id = entity_8.id", + " )", + " )), '[]'::jsonb)", + " FROM agreego.contact contact_4", + " JOIN agreego.relationship relationship_5 ON relationship_5.id = contact_4.id", + " JOIN agreego.entity entity_6 ON entity_6.id = relationship_5.id", + " WHERE", + " NOT entity_6.archived", + " AND relationship_5.target_type = 'phone_number'", + " AND relationship_5.source_id = entity_3.id", + " ),", + " 'email_addresses', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', entity_11.id,", + " 'type', entity_11.type,", + " 'archived', entity_11.archived,", + " 'created_at', entity_11.created_at,", + " 'is_primary', contact_9.is_primary,", + " 'target', (", + " SELECT jsonb_build_object(", + " 'id', entity_13.id,", + " 'type', entity_13.type,", + " 'archived', entity_13.archived,", + " 'created_at', entity_13.created_at,", + " 'address', email_address_12.address", + " )", + " FROM agreego.email_address email_address_12", + " JOIN agreego.entity entity_13 ON entity_13.id = email_address_12.id", + " WHERE", + " NOT entity_13.archived", + " AND relationship_10.target_id = entity_13.id", + " )", + " )), '[]'::jsonb)", + " FROM agreego.contact contact_9", + " JOIN agreego.relationship relationship_10 ON relationship_10.id = contact_9.id", + " JOIN agreego.entity entity_11 ON entity_11.id = relationship_10.id", + " WHERE", + " NOT entity_11.archived", + " AND relationship_10.target_type = 'email_address'", + " AND relationship_10.source_id = entity_3.id", + " ),", + " 'addresses', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', entity_16.id,", + " 'type', entity_16.type,", + " 'archived', entity_16.archived,", + " 'created_at', entity_16.created_at,", + " 'is_primary', contact_14.is_primary,", + " 'target', (", + " SELECT jsonb_build_object(", + " 'id', entity_18.id,", + " 'type', entity_18.type,", + " 'archived', entity_18.archived,", + " 'created_at', entity_18.created_at,", + " 'city', address_17.city", + " )", + " FROM agreego.address address_17", + " JOIN agreego.entity entity_18 ON entity_18.id = address_17.id", + " WHERE", + " NOT entity_18.archived", + " AND relationship_15.target_id = entity_18.id", + " )", + " )), '[]'::jsonb)", + " FROM agreego.contact contact_14", + " JOIN agreego.relationship relationship_15 ON relationship_15.id = contact_14.id", + " JOIN agreego.entity entity_16 ON entity_16.id = relationship_15.id", + " WHERE", + " NOT entity_16.archived", + " AND relationship_15.target_type = 'address'", + " AND relationship_15.source_id = entity_3.id", + " ),", + " 'contacts', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', entity_21.id,", + " 'type', entity_21.type,", + " 'archived', entity_21.archived,", + " 'created_at', entity_21.created_at,", + " 'is_primary', contact_19.is_primary,", + " 'target', CASE", + " WHEN relationship_20.target_type = 'phone_number' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_23.id,", + " 'type', entity_23.type,", + " 'archived', entity_23.archived,", + " 'created_at', entity_23.created_at,", + " 'number', phone_number_22.number", + " )", + " FROM agreego.phone_number phone_number_22", + " JOIN agreego.entity entity_23 ON entity_23.id = phone_number_22.id", + " WHERE", + " NOT entity_23.archived", + " AND relationship_20.target_id = entity_23.id", + " ))", + " WHEN relationship_20.target_type = 'email_address' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_25.id,", + " 'type', entity_25.type,", + " 'archived', entity_25.archived,", + " 'created_at', entity_25.created_at,", + " 'address', email_address_24.address", + " )", + " FROM agreego.email_address email_address_24", + " JOIN agreego.entity entity_25 ON entity_25.id = email_address_24.id", + " WHERE", + " NOT entity_25.archived", + " AND relationship_20.target_id = entity_25.id", + " ))", + " WHEN relationship_20.target_type = 'address' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_27.id,", + " 'type', entity_27.type,", + " 'archived', entity_27.archived,", + " 'created_at', entity_27.created_at,", + " 'city', address_26.city", + " )", + " FROM agreego.address address_26", + " JOIN agreego.entity entity_27 ON entity_27.id = address_26.id", + " WHERE", + " NOT entity_27.archived", + " AND relationship_20.target_id = entity_27.id", + " ))", + " ELSE NULL", + " END", + " )), '[]'::jsonb)", + " FROM agreego.contact contact_19", + " JOIN agreego.relationship relationship_20 ON relationship_20.id = contact_19.id", + " JOIN agreego.entity entity_21 ON entity_21.id = relationship_20.id", + " WHERE", + " NOT entity_21.archived", + " AND contact_19.is_primary = ($11 #>> '{}')::BOOLEAN", + " AND relationship_20.source_id = entity_3.id", " )", - " FROM agreego.address address_7", - " JOIN agreego.entity entity_8 ON entity_8.id = address_7.id", - " WHERE", - " NOT entity_8.archived", - " AND relationship_5.target_id = entity_8.id),", - " 'type', entity_6.type", - " )), '[]'::jsonb)", - " FROM agreego.contact contact_4", - " JOIN agreego.relationship relationship_5 ON relationship_5.id = contact_4.id", - " JOIN agreego.entity entity_6 ON entity_6.id = relationship_5.id", + " )", + " FROM agreego.person person_1", + " JOIN agreego.organization organization_2 ON organization_2.id = person_1.id", + " JOIN agreego.entity entity_3 ON entity_3.id = organization_2.id", " WHERE", - " NOT entity_6.archived", - " AND relationship_5.target_type = 'address'", - " AND relationship_5.source_id = entity_3.id),", - " 'age', person_1.age,", - " 'archived', entity_3.archived,", - " 'contacts',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_11.archived,", - " 'created_at', entity_11.created_at,", - " 'id', entity_11.id,", - " 'is_primary', contact_9.is_primary,", - " 'target', CASE", - " WHEN relationship_10.target_type = 'address' THEN", - " ((SELECT jsonb_build_object(", - " 'archived', entity_13.archived,", - " 'city', address_12.city,", - " 'created_at', entity_13.created_at,", - " 'id', entity_13.id,", - " 'type', entity_13.type", - " )", - " FROM agreego.address address_12", - " JOIN agreego.entity entity_13 ON entity_13.id = address_12.id", - " WHERE", - " NOT entity_13.archived", - " AND relationship_10.target_id = entity_13.id))", - " WHEN relationship_10.target_type = 'email_address' THEN", - " ((SELECT jsonb_build_object(", - " 'address', email_address_14.address,", - " 'archived', entity_15.archived,", - " 'created_at', entity_15.created_at,", - " 'id', entity_15.id,", - " 'type', entity_15.type", - " )", - " FROM agreego.email_address email_address_14", - " JOIN agreego.entity entity_15 ON entity_15.id = email_address_14.id", - " WHERE", - " NOT entity_15.archived", - " AND relationship_10.target_id = entity_15.id))", - " WHEN relationship_10.target_type = 'phone_number' THEN", - " ((SELECT jsonb_build_object(", - " 'archived', entity_17.archived,", - " 'created_at', entity_17.created_at,", - " 'id', entity_17.id,", - " 'number', phone_number_16.number,", - " 'type', entity_17.type", - " )", - " FROM agreego.phone_number phone_number_16", - " JOIN agreego.entity entity_17 ON entity_17.id = phone_number_16.id", - " WHERE", - " NOT entity_17.archived", - " AND relationship_10.target_id = entity_17.id))", - " ELSE NULL END,", - " 'type', entity_11.type", - " )), '[]'::jsonb)", - " FROM agreego.contact contact_9", - " JOIN agreego.relationship relationship_10 ON relationship_10.id = contact_9.id", - " JOIN agreego.entity entity_11 ON entity_11.id = relationship_10.id", - " WHERE", - " NOT entity_11.archived", - " AND contact_9.is_primary = ($11#>>'{}')::boolean", - " AND relationship_10.source_id = entity_3.id),", - " 'created_at', entity_3.created_at,", - " 'email_addresses',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_20.archived,", - " 'created_at', entity_20.created_at,", - " 'id', entity_20.id,", - " 'is_primary', contact_18.is_primary,", - " 'target',", - " (SELECT jsonb_build_object(", - " 'address', email_address_21.address,", - " 'archived', entity_22.archived,", - " 'created_at', entity_22.created_at,", - " 'id', entity_22.id,", - " 'type', entity_22.type", - " )", - " FROM agreego.email_address email_address_21", - " JOIN agreego.entity entity_22 ON entity_22.id = email_address_21.id", - " WHERE", - " NOT entity_22.archived", - " AND relationship_19.target_id = entity_22.id),", - " 'type', entity_20.type", - " )), '[]'::jsonb)", - " FROM agreego.contact contact_18", - " JOIN agreego.relationship relationship_19 ON relationship_19.id = contact_18.id", - " JOIN agreego.entity entity_20 ON entity_20.id = relationship_19.id", - " WHERE", - " NOT entity_20.archived", - " AND relationship_19.target_type = 'email_address'", - " AND relationship_19.source_id = entity_3.id),", - " 'first_name', person_1.first_name,", - " 'id', entity_3.id,", - " 'last_name', person_1.last_name,", - " 'name', organization_2.name,", - " 'phone_numbers',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_25.archived,", - " 'created_at', entity_25.created_at,", - " 'id', entity_25.id,", - " 'is_primary', contact_23.is_primary,", - " 'target',", - " (SELECT jsonb_build_object(", - " 'archived', entity_27.archived,", - " 'created_at', entity_27.created_at,", - " 'id', entity_27.id,", - " 'number', phone_number_26.number,", - " 'type', entity_27.type", - " )", - " FROM agreego.phone_number phone_number_26", - " JOIN agreego.entity entity_27 ON entity_27.id = phone_number_26.id", - " WHERE", - " NOT entity_27.archived", - " AND phone_number_26.number ILIKE $32#>>'{}'", - " AND relationship_24.target_id = entity_27.id),", - " 'type', entity_25.type", - " )), '[]'::jsonb)", - " FROM agreego.contact contact_23", - " JOIN agreego.relationship relationship_24 ON relationship_24.id = contact_23.id", - " JOIN agreego.entity entity_25 ON entity_25.id = relationship_24.id", - " WHERE", - " NOT entity_25.archived", - " AND relationship_24.target_type = 'phone_number'", - " AND relationship_24.source_id = entity_3.id),", - " 'type', entity_3.type", - ")", - "FROM agreego.person person_1", - "JOIN agreego.organization organization_2 ON organization_2.id = person_1.id", - "JOIN agreego.entity entity_3 ON entity_3.id = organization_2.id", - "WHERE", - " NOT entity_3.archived", - " AND person_1.age = ($1#>>'{}')::numeric", - " AND person_1.age > ($2#>>'{}')::numeric", - " AND person_1.age >= ($3#>>'{}')::numeric", - " AND person_1.age < ($4#>>'{}')::numeric", - " AND person_1.age <= ($5#>>'{}')::numeric", - " AND person_1.age != ($6#>>'{}')::numeric", - " AND person_1.age NOT IN (SELECT value::numeric FROM jsonb_array_elements_text(($7#>>'{}')::jsonb))", - " AND person_1.age IN (SELECT value::numeric FROM jsonb_array_elements_text(($8#>>'{}')::jsonb))", - " AND entity_3.archived = ($9#>>'{}')::boolean", - " AND entity_3.archived != ($10#>>'{}')::boolean", - " AND entity_3.created_at = ($12#>>'{}')::timestamptz", - " AND entity_3.created_at > ($13#>>'{}')::timestamptz", - " AND entity_3.created_at >= ($14#>>'{}')::timestamptz", - " AND entity_3.created_at < ($15#>>'{}')::timestamptz", - " AND entity_3.created_at <= ($16#>>'{}')::timestamptz", - " AND entity_3.created_at != ($17#>>'{}')::timestamptz", - " AND person_1.first_name ILIKE $18#>>'{}'", - " AND person_1.first_name > ($19#>>'{}')", - " AND person_1.first_name >= ($20#>>'{}')", - " AND person_1.first_name < ($21#>>'{}')", - " AND person_1.first_name <= ($22#>>'{}')", - " AND person_1.first_name NOT ILIKE $23#>>'{}'", - " AND person_1.first_name NOT IN (SELECT value FROM jsonb_array_elements_text(($24#>>'{}')::jsonb))", - " AND person_1.first_name IN (SELECT value FROM jsonb_array_elements_text(($25#>>'{}')::jsonb))", - " AND entity_3.id = ($26#>>'{}')::uuid", - " AND entity_3.id != ($27#>>'{}')::uuid", - " AND entity_3.id NOT IN (SELECT value::uuid FROM jsonb_array_elements_text(($28#>>'{}')::jsonb))", - " AND entity_3.id IN (SELECT value::uuid FROM jsonb_array_elements_text(($29#>>'{}')::jsonb))", - " AND person_1.last_name ILIKE $30#>>'{}'", - " AND person_1.last_name NOT ILIKE $31#>>'{}')))" + " NOT entity_3.archived", + " AND person_1.age = ($1 #>> '{}')::NUMERIC", + " AND person_1.age > ($2 #>> '{}')::NUMERIC", + " AND person_1.age >= ($3 #>> '{}')::NUMERIC", + " AND person_1.age < ($4 #>> '{}')::NUMERIC", + " AND person_1.age <= ($5 #>> '{}')::NUMERIC", + " AND person_1.age <> ($6 #>> '{}')::NUMERIC", + " AND person_1.age NOT IN (SELECT value::NUMERIC FROM jsonb_array_elements_text(($7 #>> '{}')::jsonb))", + " AND person_1.age IN (SELECT value::NUMERIC FROM jsonb_array_elements_text(($8 #>> '{}')::jsonb))", + " AND entity_3.archived = ($9 #>> '{}')::BOOLEAN", + " AND entity_3.archived <> ($10 #>> '{}')::BOOLEAN", + " AND entity_3.created_at = ($12 #>> '{}')::TIMESTAMPTZ", + " AND entity_3.created_at > ($13 #>> '{}')::TIMESTAMPTZ", + " AND entity_3.created_at >= ($14 #>> '{}')::TIMESTAMPTZ", + " AND entity_3.created_at < ($15 #>> '{}')::TIMESTAMPTZ", + " AND entity_3.created_at <= ($16 #>> '{}')::TIMESTAMPTZ", + " AND entity_3.created_at <> ($17 #>> '{}')::TIMESTAMPTZ", + " AND person_1.first_name ILIKE $18 #>> '{}'", + " AND person_1.first_name > ($19 #>> '{)", + " AND person_1.first_name >= ($20 #>> '{)", + " AND person_1.first_name < ($21 #>> '{)", + " AND person_1.first_name <= ($22 #>> '{)", + " AND person_1.first_name NOT ILIKE $23 #>> '{}'", + " AND person_1.first_name NOT IN (SELECT value FROM jsonb_array_elements_text(($24 #>> '{}')::jsonb))", + " AND person_1.first_name IN (SELECT value FROM jsonb_array_elements_text(($25 #>> '{}')::jsonb))", + " AND entity_3.id = ($26 #>> '{}')::UUID", + " AND entity_3.id <> ($27 #>> '{}')::UUID", + " AND entity_3.id NOT IN (SELECT value::UUID FROM jsonb_array_elements_text(($28 #>> '{}')::jsonb))", + " AND entity_3.id IN (SELECT value::UUID FROM jsonb_array_elements_text(($29 #>> '{}')::jsonb))", + " AND person_1.last_name ILIKE $30 #>> '{}'", + " AND person_1.last_name NOT ILIKE $31 #>> '{}'", + " ))))" ] ] } @@ -1716,32 +1752,35 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_3.archived,", - " 'created_at', entity_3.created_at,", - " 'id', entity_3.id,", - " 'is_primary', contact_1.is_primary,", - " 'target',", - " (SELECT jsonb_build_object(", - " 'address', email_address_4.address,", - " 'archived', entity_5.archived,", - " 'created_at', entity_5.created_at,", - " 'id', entity_5.id,", - " 'type', entity_5.type", - " )", - " FROM agreego.email_address email_address_4", - " JOIN agreego.entity entity_5 ON entity_5.id = email_address_4.id", + "((SELECT jsonb_strip_nulls((", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', entity_3.id,", + " 'type', entity_3.type,", + " 'archived', entity_3.archived,", + " 'created_at', entity_3.created_at,", + " 'is_primary', contact_1.is_primary,", + " 'target', (", + " SELECT jsonb_build_object(", + " 'id', entity_5.id,", + " 'type', entity_5.type,", + " 'archived', entity_5.archived,", + " 'created_at', entity_5.created_at,", + " 'address', email_address_4.address", + " )", + " FROM agreego.email_address email_address_4", + " JOIN agreego.entity entity_5 ON entity_5.id = email_address_4.id", + " WHERE", + " NOT entity_5.archived", + " AND relationship_2.target_id = entity_5.id", + " )", + " )), '[]'::jsonb)", + " FROM agreego.contact contact_1", + " JOIN agreego.relationship relationship_2 ON relationship_2.id = contact_1.id", + " JOIN agreego.entity entity_3 ON entity_3.id = relationship_2.id", " WHERE", - " NOT entity_5.archived", - " AND relationship_2.target_id = entity_5.id),", - " 'type', entity_3.type", - ")), '[]'::jsonb)", - "FROM agreego.contact contact_1", - "JOIN agreego.relationship relationship_2 ON relationship_2.id = contact_1.id", - "JOIN agreego.entity entity_3 ON entity_3.id = relationship_2.id", - "WHERE", - " NOT entity_3.archived", - " AND relationship_2.target_type = 'email_address')))" + " NOT entity_3.archived", + " AND relationship_2.target_type = 'email_address'", + "))))" ] ] } @@ -1754,49 +1793,54 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT jsonb_build_object(", - " 'archived', entity_2.archived,", - " 'created_at', entity_2.created_at,", - " 'customer',", - " (SELECT jsonb_build_object(", - " 'age', person_3.age,", - " 'archived', entity_5.archived,", - " 'created_at', entity_5.created_at,", - " 'first_name', person_3.first_name,", - " 'id', entity_5.id,", - " 'last_name', person_3.last_name,", - " 'name', organization_4.name,", - " 'type', entity_5.type", + "((SELECT jsonb_strip_nulls((", + " SELECT jsonb_build_object(", + " 'id', order_1.id,", + " 'type', order_1.type,", + " 'archived', entity_2.archived,", + " 'created_at', entity_2.created_at,", + " 'total', order_1.total,", + " 'customer_id', order_1.customer_id,", + " 'customer', (", + " SELECT jsonb_build_object(", + " 'id', entity_5.id,", + " 'type', entity_5.type,", + " 'archived', entity_5.archived,", + " 'created_at', entity_5.created_at,", + " 'name', organization_4.name,", + " 'first_name', person_3.first_name,", + " 'last_name', person_3.last_name,", + " 'age', person_3.age", + " )", + " FROM agreego.person person_3", + " JOIN agreego.organization organization_4 ON organization_4.id = person_3.id", + " JOIN agreego.entity entity_5 ON entity_5.id = organization_4.id", + " WHERE", + " NOT entity_5.archived", + " AND order_1.customer_id = person_3.id", + " ),", + " 'lines', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', order_line_6.id,", + " 'type', order_line_6.type,", + " 'archived', entity_7.archived,", + " 'created_at', entity_7.created_at,", + " 'order_id', order_line_6.order_id,", + " 'product', order_line_6.product,", + " 'price', order_line_6.price", + " )), '[]'::jsonb)", + " FROM agreego.order_line order_line_6", + " JOIN agreego.entity entity_7 ON entity_7.id = order_line_6.id", + " WHERE", + " NOT entity_7.archived", + " AND order_line_6.order_id = order_1.id", + " )", " )", - " FROM agreego.person person_3", - " JOIN agreego.organization organization_4 ON organization_4.id = person_3.id", - " JOIN agreego.entity entity_5 ON entity_5.id = organization_4.id", + " FROM agreego.order order_1", + " JOIN agreego.entity entity_2 ON entity_2.id = order_1.id", " WHERE", - " NOT entity_5.archived", - " AND order_1.customer_id = person_3.id),", - " 'customer_id', order_1.customer_id,", - " 'id', entity_2.id,", - " 'lines',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_7.archived,", - " 'created_at', entity_7.created_at,", - " 'id', entity_7.id,", - " 'order_id', order_line_6.order_id,", - " 'price', order_line_6.price,", - " 'product', order_line_6.product,", - " 'type', entity_7.type", - " )), '[]'::jsonb)", - " FROM agreego.order_line order_line_6", - " JOIN agreego.entity entity_7 ON entity_7.id = order_line_6.id", - " WHERE", - " NOT entity_7.archived", - " AND order_line_6.order_id = order_1.id),", - " 'total', order_1.total,", - " 'type', entity_2.type", - ")", - "FROM agreego.order order_1", - "JOIN agreego.entity entity_2 ON entity_2.id = order_1.id", - "WHERE NOT entity_2.archived)))" + " NOT entity_2.archived", + "))))" ] ] } @@ -1809,16 +1853,19 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT jsonb_build_object(", - " 'archived', entity_2.archived,", - " 'created_at', entity_2.created_at,", - " 'id', entity_2.id,", - " 'name', organization_1.name,", - " 'type', entity_2.type", - ")", - "FROM agreego.organization organization_1", - "JOIN agreego.entity entity_2 ON entity_2.id = organization_1.id", - "WHERE NOT entity_2.archived)))" + "((SELECT jsonb_strip_nulls((", + " SELECT jsonb_build_object(", + " 'id', entity_2.id,", + " 'type', entity_2.type,", + " 'archived', entity_2.archived,", + " 'created_at', entity_2.created_at,", + " 'name', organization_1.name", + " )", + " FROM agreego.organization organization_1", + " JOIN agreego.entity entity_2 ON entity_2.id = organization_1.id", + " WHERE", + " NOT entity_2.archived", + "))))" ] ] } @@ -1831,63 +1878,64 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT COALESCE(jsonb_agg(", - " CASE", - " WHEN organization_1.type = 'bot' THEN (", - " (SELECT jsonb_build_object(", + "((SELECT jsonb_strip_nulls((", + " SELECT COALESCE(jsonb_agg(CASE", + " WHEN organization_1.type = 'bot' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_5.id,", + " 'type', entity_5.type,", " 'archived', entity_5.archived,", " 'created_at', entity_5.created_at,", - " 'id', entity_5.id,", " 'name', organization_4.name,", - " 'role', bot_3.role,", " 'token', bot_3.token,", - " 'type', entity_5.type", + " 'role', bot_3.role", " )", " FROM agreego.bot bot_3", " JOIN agreego.organization organization_4 ON organization_4.id = bot_3.id", " JOIN agreego.entity entity_5 ON entity_5.id = organization_4.id", " WHERE", " NOT entity_5.archived", - " AND entity_5.id = entity_2.id)", - " )", - " WHEN organization_1.type = 'organization' THEN (", - " (SELECT jsonb_build_object(", + " AND entity_5.id = entity_2.id", + " ))", + " WHEN organization_1.type = 'organization' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_7.id,", + " 'type', entity_7.type,", " 'archived', entity_7.archived,", " 'created_at', entity_7.created_at,", - " 'id', entity_7.id,", - " 'name', organization_6.name,", - " 'type', entity_7.type", + " 'name', organization_6.name", " )", " FROM agreego.organization organization_6", " JOIN agreego.entity entity_7 ON entity_7.id = organization_6.id", " WHERE", " NOT entity_7.archived", - " AND entity_7.id = entity_2.id)", - " )", - " WHEN organization_1.type = 'person' THEN (", - " (SELECT jsonb_build_object(", - " 'age', person_8.age,", + " AND entity_7.id = entity_2.id", + " ))", + " WHEN organization_1.type = 'person' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_10.id,", + " 'type', entity_10.type,", " 'archived', entity_10.archived,", " 'created_at', entity_10.created_at,", - " 'first_name', person_8.first_name,", - " 'id', entity_10.id,", - " 'last_name', person_8.last_name,", " 'name', organization_9.name,", - " 'type', entity_10.type", + " 'first_name', person_8.first_name,", + " 'last_name', person_8.last_name,", + " 'age', person_8.age", " )", " FROM agreego.person person_8", " JOIN agreego.organization organization_9 ON organization_9.id = person_8.id", " JOIN agreego.entity entity_10 ON entity_10.id = organization_9.id", " WHERE", " NOT entity_10.archived", - " AND entity_10.id = entity_2.id)", - " )", + " AND entity_10.id = entity_2.id", + " ))", " ELSE NULL", - " END", - "), '[]'::jsonb)", - "FROM agreego.organization organization_1", - "JOIN agreego.entity entity_2 ON entity_2.id = organization_1.id", - "WHERE NOT entity_2.archived)))" + " END), '[]'::jsonb)", + " FROM agreego.organization organization_1", + " JOIN agreego.entity entity_2 ON entity_2.id = organization_1.id", + " WHERE", + " NOT entity_2.archived", + "))))" ] ] } @@ -1900,42 +1948,48 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT ", - " CASE", - " WHEN organization_1.type = 'bot' THEN (", - " (SELECT jsonb_build_object(", + "((SELECT jsonb_strip_nulls((", + " SELECT CASE", + " WHEN organization_1.type = 'bot' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_5.id,", + " 'type', entity_5.type,", " 'archived', entity_5.archived,", " 'created_at', entity_5.created_at,", - " 'id', entity_5.id,", " 'name', organization_4.name,", - " 'token', bot_3.token,", - " 'type', entity_5.type", + " 'token', bot_3.token", " )", " FROM agreego.bot bot_3", " JOIN agreego.organization organization_4 ON organization_4.id = bot_3.id", " JOIN agreego.entity entity_5 ON entity_5.id = organization_4.id", - " WHERE NOT entity_5.archived AND entity_5.id = entity_2.id)", - " )", - " WHEN organization_1.type = 'person' THEN (", - " (SELECT jsonb_build_object(", + " WHERE", + " NOT entity_5.archived", + " AND entity_5.id = entity_2.id", + " ))", + " WHEN organization_1.type = 'person' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_8.id,", + " 'type', entity_8.type,", " 'archived', entity_8.archived,", " 'created_at', entity_8.created_at,", - " 'first_name', person_6.first_name,", - " 'id', entity_8.id,", - " 'last_name', person_6.last_name,", " 'name', organization_7.name,", - " 'type', entity_8.type", + " 'first_name', person_6.first_name,", + " 'last_name', person_6.last_name", " )", " FROM agreego.person person_6", " JOIN agreego.organization organization_7 ON organization_7.id = person_6.id", " JOIN agreego.entity entity_8 ON entity_8.id = organization_7.id", - " WHERE NOT entity_8.archived AND entity_8.id = entity_2.id)", - " )", + " WHERE", + " NOT entity_8.archived", + " AND entity_8.id = entity_2.id", + " ))", " ELSE NULL", " END", - "FROM agreego.organization organization_1", - "JOIN agreego.entity entity_2 ON entity_2.id = organization_1.id", - "WHERE NOT entity_2.archived)))" + " FROM agreego.organization organization_1", + " JOIN agreego.entity entity_2 ON entity_2.id = organization_1.id", + " WHERE", + " NOT entity_2.archived", + "))))" ] ] } @@ -1948,171 +2002,183 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT CASE", - " WHEN organization_1.type = 'person' THEN (", - " (SELECT jsonb_build_object(", - " 'addresses',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_8.archived,", - " 'created_at', entity_8.created_at,", - " 'id', entity_8.id,", - " 'is_primary', contact_6.is_primary,", - " 'target',", - " (SELECT jsonb_build_object(", - " 'archived', entity_10.archived,", - " 'city', address_9.city,", - " 'created_at', entity_10.created_at,", - " 'id', entity_10.id,", - " 'type', entity_10.type", - " )", - " FROM agreego.address address_9", - " JOIN agreego.entity entity_10 ON entity_10.id = address_9.id", - " WHERE", - " NOT entity_10.archived", - " AND relationship_7.target_id = entity_10.id),", - " 'type', entity_8.type", - " )), '[]'::jsonb)", - " FROM agreego.contact contact_6", - " JOIN agreego.relationship relationship_7 ON relationship_7.id = contact_6.id", - " JOIN agreego.entity entity_8 ON entity_8.id = relationship_7.id", - " WHERE", - " NOT entity_8.archived", - " AND relationship_7.target_type = 'address'", - " AND relationship_7.source_id = entity_5.id),", - " 'age', person_3.age,", - " 'archived', entity_5.archived,", - " 'contacts',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_13.archived,", - " 'created_at', entity_13.created_at,", - " 'id', entity_13.id,", - " 'is_primary', contact_11.is_primary,", - " 'target',", - " CASE", - " WHEN relationship_12.target_type = 'address' THEN (", - " (SELECT jsonb_build_object(", - " 'archived', entity_15.archived,", - " 'city', address_14.city,", - " 'created_at', entity_15.created_at,", - " 'id', entity_15.id,", - " 'type', entity_15.type", - " )", - " FROM agreego.address address_14", - " JOIN agreego.entity entity_15 ON entity_15.id = address_14.id", + "((SELECT jsonb_strip_nulls((", + " SELECT CASE", + " WHEN organization_1.type = 'person' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_5.id,", + " 'type', entity_5.type,", + " 'archived', entity_5.archived,", + " 'created_at', entity_5.created_at,", + " 'name', organization_4.name,", + " 'first_name', person_3.first_name,", + " 'last_name', person_3.last_name,", + " 'age', person_3.age,", + " 'phone_numbers', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', entity_8.id,", + " 'type', entity_8.type,", + " 'archived', entity_8.archived,", + " 'created_at', entity_8.created_at,", + " 'is_primary', contact_6.is_primary,", + " 'target', (", + " SELECT jsonb_build_object(", + " 'id', entity_10.id,", + " 'type', entity_10.type,", + " 'archived', entity_10.archived,", + " 'created_at', entity_10.created_at,", + " 'number', phone_number_9.number", + " )", + " FROM agreego.phone_number phone_number_9", + " JOIN agreego.entity entity_10 ON entity_10.id = phone_number_9.id", + " WHERE", + " NOT entity_10.archived", + " AND relationship_7.target_id = entity_10.id", + " )", + " )), '[]'::jsonb)", + " FROM agreego.contact contact_6", + " JOIN agreego.relationship relationship_7 ON relationship_7.id = contact_6.id", + " JOIN agreego.entity entity_8 ON entity_8.id = relationship_7.id", " WHERE", - " NOT entity_15.archived", - " AND relationship_12.target_id = entity_15.id)", - " )", - " WHEN relationship_12.target_type = 'email_address' THEN (", - " (SELECT jsonb_build_object(", - " 'address', email_address_16.address,", - " 'archived', entity_17.archived,", - " 'created_at', entity_17.created_at,", - " 'id', entity_17.id,", - " 'type', entity_17.type", - " )", - " FROM agreego.email_address email_address_16", - " JOIN agreego.entity entity_17 ON entity_17.id = email_address_16.id", + " NOT entity_8.archived", + " AND relationship_7.target_type = 'phone_number'", + " AND relationship_7.source_id = entity_5.id", + " ),", + " 'email_addresses', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', entity_13.id,", + " 'type', entity_13.type,", + " 'archived', entity_13.archived,", + " 'created_at', entity_13.created_at,", + " 'is_primary', contact_11.is_primary,", + " 'target', (", + " SELECT jsonb_build_object(", + " 'id', entity_15.id,", + " 'type', entity_15.type,", + " 'archived', entity_15.archived,", + " 'created_at', entity_15.created_at,", + " 'address', email_address_14.address", + " )", + " FROM agreego.email_address email_address_14", + " JOIN agreego.entity entity_15 ON entity_15.id = email_address_14.id", + " WHERE", + " NOT entity_15.archived", + " AND relationship_12.target_id = entity_15.id", + " )", + " )), '[]'::jsonb)", + " FROM agreego.contact contact_11", + " JOIN agreego.relationship relationship_12 ON relationship_12.id = contact_11.id", + " JOIN agreego.entity entity_13 ON entity_13.id = relationship_12.id", " WHERE", - " NOT entity_17.archived", - " AND relationship_12.target_id = entity_17.id)", - " )", - " WHEN relationship_12.target_type = 'phone_number' THEN (", - " (SELECT jsonb_build_object(", - " 'archived', entity_19.archived,", - " 'created_at', entity_19.created_at,", - " 'id', entity_19.id,", - " 'number', phone_number_18.number,", - " 'type', entity_19.type", - " )", - " FROM agreego.phone_number phone_number_18", - " JOIN agreego.entity entity_19 ON entity_19.id = phone_number_18.id", + " NOT entity_13.archived", + " AND relationship_12.target_type = 'email_address'", + " AND relationship_12.source_id = entity_5.id", + " ),", + " 'addresses', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', entity_18.id,", + " 'type', entity_18.type,", + " 'archived', entity_18.archived,", + " 'created_at', entity_18.created_at,", + " 'is_primary', contact_16.is_primary,", + " 'target', (", + " SELECT jsonb_build_object(", + " 'id', entity_20.id,", + " 'type', entity_20.type,", + " 'archived', entity_20.archived,", + " 'created_at', entity_20.created_at,", + " 'city', address_19.city", + " )", + " FROM agreego.address address_19", + " JOIN agreego.entity entity_20 ON entity_20.id = address_19.id", + " WHERE", + " NOT entity_20.archived", + " AND relationship_17.target_id = entity_20.id", + " )", + " )), '[]'::jsonb)", + " FROM agreego.contact contact_16", + " JOIN agreego.relationship relationship_17 ON relationship_17.id = contact_16.id", + " JOIN agreego.entity entity_18 ON entity_18.id = relationship_17.id", " WHERE", - " NOT entity_19.archived", - " AND relationship_12.target_id = entity_19.id)", + " NOT entity_18.archived", + " AND relationship_17.target_type = 'address'", + " AND relationship_17.source_id = entity_5.id", + " ),", + " 'contacts', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', entity_23.id,", + " 'type', entity_23.type,", + " 'archived', entity_23.archived,", + " 'created_at', entity_23.created_at,", + " 'is_primary', contact_21.is_primary,", + " 'target', CASE", + " WHEN relationship_22.target_type = 'phone_number' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_25.id,", + " 'type', entity_25.type,", + " 'archived', entity_25.archived,", + " 'created_at', entity_25.created_at,", + " 'number', phone_number_24.number", + " )", + " FROM agreego.phone_number phone_number_24", + " JOIN agreego.entity entity_25 ON entity_25.id = phone_number_24.id", + " WHERE", + " NOT entity_25.archived", + " AND relationship_22.target_id = entity_25.id", + " ))", + " WHEN relationship_22.target_type = 'email_address' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_27.id,", + " 'type', entity_27.type,", + " 'archived', entity_27.archived,", + " 'created_at', entity_27.created_at,", + " 'address', email_address_26.address", + " )", + " FROM agreego.email_address email_address_26", + " JOIN agreego.entity entity_27 ON entity_27.id = email_address_26.id", + " WHERE", + " NOT entity_27.archived", + " AND relationship_22.target_id = entity_27.id", + " ))", + " WHEN relationship_22.target_type = 'address' THEN ((", + " SELECT jsonb_build_object(", + " 'id', entity_29.id,", + " 'type', entity_29.type,", + " 'archived', entity_29.archived,", + " 'created_at', entity_29.created_at,", + " 'city', address_28.city", + " )", + " FROM agreego.address address_28", + " JOIN agreego.entity entity_29 ON entity_29.id = address_28.id", + " WHERE", + " NOT entity_29.archived", + " AND relationship_22.target_id = entity_29.id", + " ))", + " ELSE NULL", + " END", + " )), '[]'::jsonb)", + " FROM agreego.contact contact_21", + " JOIN agreego.relationship relationship_22 ON relationship_22.id = contact_21.id", + " JOIN agreego.entity entity_23 ON entity_23.id = relationship_22.id", + " WHERE", + " NOT entity_23.archived", + " AND relationship_22.source_id = entity_5.id", " )", - " ELSE NULL", - " END,", - " 'type', entity_13.type", - " )), '[]'::jsonb)", - " FROM agreego.contact contact_11", - " JOIN agreego.relationship relationship_12 ON relationship_12.id = contact_11.id", - " JOIN agreego.entity entity_13 ON entity_13.id = relationship_12.id", - " WHERE", - " NOT entity_13.archived", - " AND relationship_12.source_id = entity_5.id),", - " 'created_at', entity_5.created_at,", - " 'email_addresses',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_22.archived,", - " 'created_at', entity_22.created_at,", - " 'id', entity_22.id,", - " 'is_primary', contact_20.is_primary,", - " 'target',", - " (SELECT jsonb_build_object(", - " 'address', email_address_23.address,", - " 'archived', entity_24.archived,", - " 'created_at', entity_24.created_at,", - " 'id', entity_24.id,", - " 'type', entity_24.type", " )", - " FROM agreego.email_address email_address_23", - " JOIN agreego.entity entity_24 ON entity_24.id = email_address_23.id", + " FROM agreego.person person_3", + " JOIN agreego.organization organization_4 ON organization_4.id = person_3.id", + " JOIN agreego.entity entity_5 ON entity_5.id = organization_4.id", " WHERE", - " NOT entity_24.archived", - " AND relationship_21.target_id = entity_24.id),", - " 'type', entity_22.type", - " )), '[]'::jsonb)", - " FROM agreego.contact contact_20", - " JOIN agreego.relationship relationship_21 ON relationship_21.id = contact_20.id", - " JOIN agreego.entity entity_22 ON entity_22.id = relationship_21.id", - " WHERE", - " NOT entity_22.archived", - " AND relationship_21.target_type = 'email_address'", - " AND relationship_21.source_id = entity_5.id),", - " 'first_name', person_3.first_name,", - " 'id', entity_5.id,", - " 'last_name', person_3.last_name,", - " 'name', organization_4.name,", - " 'phone_numbers',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_27.archived,", - " 'created_at', entity_27.created_at,", - " 'id', entity_27.id,", - " 'is_primary', contact_25.is_primary,", - " 'target',", - " (SELECT jsonb_build_object(", - " 'archived', entity_29.archived,", - " 'created_at', entity_29.created_at,", - " 'id', entity_29.id,", - " 'number', phone_number_28.number,", - " 'type', entity_29.type", - " )", - " FROM agreego.phone_number phone_number_28", - " JOIN agreego.entity entity_29 ON entity_29.id = phone_number_28.id", - " WHERE", - " NOT entity_29.archived", - " AND relationship_26.target_id = entity_29.id),", - " 'type', entity_27.type", - " )), '[]'::jsonb)", - " FROM agreego.contact contact_25", - " JOIN agreego.relationship relationship_26 ON relationship_26.id = contact_25.id", - " JOIN agreego.entity entity_27 ON entity_27.id = relationship_26.id", - " WHERE", - " NOT entity_27.archived", - " AND relationship_26.target_type = 'phone_number'", - " AND relationship_26.source_id = entity_5.id),", - " 'type', entity_5.type", - " )", - " FROM agreego.person person_3", - " JOIN agreego.organization organization_4 ON organization_4.id = person_3.id", - " JOIN agreego.entity entity_5 ON entity_5.id = organization_4.id", - " WHERE NOT entity_5.archived AND entity_5.id = entity_2.id))", - " ELSE NULL", - "END", - "FROM agreego.organization organization_1", - "JOIN agreego.entity entity_2 ON entity_2.id = organization_1.id", - "WHERE NOT entity_2.archived)))" + " NOT entity_5.archived", + " AND entity_5.id = entity_2.id", + " ))", + " ELSE NULL", + " END", + " FROM agreego.organization organization_1", + " JOIN agreego.entity entity_2 ON entity_2.id = organization_1.id", + " WHERE", + " NOT entity_2.archived", + "))))" ] ] } @@ -2125,34 +2191,38 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_2.archived,", - " 'created_at', entity_2.created_at,", - " 'customer',", - " (SELECT jsonb_build_object(", - " 'age', person_3.age,", - " 'archived', entity_5.archived,", - " 'created_at', entity_5.created_at,", - " 'first_name', person_3.first_name,", - " 'id', entity_5.id,", - " 'last_name', person_3.last_name,", - " 'name', organization_4.name,", - " 'type', entity_5.type", - " )", - " FROM agreego.person person_3", - " JOIN agreego.organization organization_4 ON organization_4.id = person_3.id", - " JOIN agreego.entity entity_5 ON entity_5.id = organization_4.id", + "((SELECT jsonb_strip_nulls((", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', order_1.id,", + " 'type', order_1.type,", + " 'archived', entity_2.archived,", + " 'created_at', entity_2.created_at,", + " 'total', order_1.total,", + " 'customer_id', order_1.customer_id,", + " 'customer', (", + " SELECT jsonb_build_object(", + " 'id', entity_5.id,", + " 'type', entity_5.type,", + " 'archived', entity_5.archived,", + " 'created_at', entity_5.created_at,", + " 'name', organization_4.name,", + " 'first_name', person_3.first_name,", + " 'last_name', person_3.last_name,", + " 'age', person_3.age", + " )", + " FROM agreego.person person_3", + " JOIN agreego.organization organization_4 ON organization_4.id = person_3.id", + " JOIN agreego.entity entity_5 ON entity_5.id = organization_4.id", + " WHERE", + " NOT entity_5.archived", + " AND order_1.customer_id = person_3.id", + " )", + " )), '[]'::jsonb)", + " FROM agreego.order order_1", + " JOIN agreego.entity entity_2 ON entity_2.id = order_1.id", " WHERE", - " NOT entity_5.archived", - " AND order_1.customer_id = person_3.id),", - " 'customer_id', order_1.customer_id,", - " 'id', entity_2.id,", - " 'total', order_1.total,", - " 'type', entity_2.type", - ")), '[]'::jsonb)", - "FROM agreego.order order_1", - "JOIN agreego.entity entity_2 ON entity_2.id = order_1.id", - "WHERE NOT entity_2.archived)))" + " NOT entity_2.archived", + "))))" ] ] } @@ -2165,32 +2235,29 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT COALESCE(jsonb_agg(", - " CASE", - " WHEN widget_1.kind = 'stock' THEN (", - " jsonb_build_object(", - " 'archived', entity_2.archived,", - " 'created_at', entity_2.created_at,", - " 'id', entity_2.id,", - " 'kind', widget_1.kind,", - " 'type', entity_2.type", - " )", - " )", - " WHEN widget_1.kind = 'tasks' THEN (", - " jsonb_build_object(", - " 'archived', entity_2.archived,", - " 'created_at', entity_2.created_at,", - " 'id', entity_2.id,", - " 'kind', widget_1.kind,", - " 'type', entity_2.type", - " )", - " )", + "((SELECT jsonb_strip_nulls((", + " SELECT COALESCE(jsonb_agg(CASE", + " WHEN widget_1.kind = 'stock' THEN (jsonb_build_object(", + " 'id', entity_2.id,", + " 'type', entity_2.type,", + " 'archived', entity_2.archived,", + " 'created_at', entity_2.created_at,", + " 'kind', widget_1.kind", + " ))", + " WHEN widget_1.kind = 'tasks' THEN (jsonb_build_object(", + " 'id', entity_2.id,", + " 'type', entity_2.type,", + " 'archived', entity_2.archived,", + " 'created_at', entity_2.created_at,", + " 'kind', widget_1.kind", + " ))", " ELSE NULL", - " END", - "), '[]'::jsonb)", - "FROM agreego.widget widget_1", - "JOIN agreego.entity entity_2 ON entity_2.id = widget_1.id", - "WHERE NOT entity_2.archived)))" + " END), '[]'::jsonb)", + " FROM agreego.widget widget_1", + " JOIN agreego.entity entity_2 ON entity_2.id = widget_1.id", + " WHERE", + " NOT entity_2.archived", + "))))" ] ] } @@ -2203,34 +2270,38 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT jsonb_build_object(", - " 'archived', entity_2.archived,", - " 'created_at', entity_2.created_at,", - " 'id', entity_2.id,", - " 'lines',", - " (SELECT COALESCE(jsonb_agg(jsonb_build_object(", - " 'archived', entity_4.archived,", - " 'created_at', entity_4.created_at,", - " 'id', entity_4.id,", - " 'invoice_id', invoice_line_3.invoice_id,", - " 'price', invoice_line_3.price,", - " 'type', entity_4.type", - " )), '[]'::jsonb)", - " FROM agreego.invoice_line invoice_line_3", - " JOIN agreego.entity entity_4 ON entity_4.id = invoice_line_3.id", + "((SELECT jsonb_strip_nulls((", + " SELECT jsonb_build_object(", + " 'id', invoice_1.id,", + " 'type', invoice_1.type,", + " 'archived', entity_2.archived,", + " 'created_at', entity_2.created_at,", + " 'total', invoice_1.total,", + " 'lines', (", + " SELECT COALESCE(jsonb_agg(jsonb_build_object(", + " 'id', invoice_line_3.id,", + " 'type', invoice_line_3.type,", + " 'archived', entity_4.archived,", + " 'created_at', entity_4.created_at,", + " 'invoice_id', invoice_line_3.invoice_id,", + " 'price', invoice_line_3.price", + " )), '[]'::jsonb)", + " FROM agreego.invoice_line invoice_line_3", + " JOIN agreego.entity entity_4 ON entity_4.id = invoice_line_3.id", + " WHERE", + " NOT entity_4.archived", + " AND invoice_line_3.invoice_id = invoice_1.id", + " ),", + " 'metadata_line', invoice_1.metadata_line,", + " 'metadata_lines', invoice_1.metadata_lines,", + " 'metadata_nested_line', invoice_1.metadata_nested_line,", + " 'metadata_nested_lines', invoice_1.metadata_nested_lines", + " )", + " FROM agreego.invoice invoice_1", + " JOIN agreego.entity entity_2 ON entity_2.id = invoice_1.id", " WHERE", - " NOT entity_4.archived", - " AND invoice_line_3.invoice_id = invoice_1.id),", - " 'metadata_line', invoice_1.metadata_line,", - " 'metadata_lines', invoice_1.metadata_lines,", - " 'metadata_nested_line', invoice_1.metadata_nested_line,", - " 'metadata_nested_lines', invoice_1.metadata_nested_lines,", - " 'total', invoice_1.total,", - " 'type', entity_2.type", - ")", - "FROM agreego.invoice invoice_1", - "JOIN agreego.entity entity_2 ON entity_2.id = invoice_1.id", - "WHERE NOT entity_2.archived)))" + " NOT entity_2.archived", + "))))" ] ] } @@ -2243,18 +2314,21 @@ "success": true, "sql": [ [ - "(SELECT jsonb_strip_nulls((SELECT jsonb_build_object(", - " 'archived', entity_2.archived,", - " 'card_number', account_1.card_number,", - " 'created_at', entity_2.created_at,", - " 'id', entity_2.id,", - " 'kind', account_1.kind,", - " 'routing_number', account_1.routing_number,", - " 'type', entity_2.type", - ")", - "FROM agreego.account account_1", - "JOIN agreego.entity entity_2 ON entity_2.id = account_1.id", - "WHERE NOT entity_2.archived)))" + "((SELECT jsonb_strip_nulls((", + " SELECT jsonb_build_object(", + " 'id', entity_2.id,", + " 'type', entity_2.type,", + " 'archived', entity_2.archived,", + " 'created_at', entity_2.created_at,", + " 'kind', account_1.kind,", + " 'routing_number', account_1.routing_number,", + " 'card_number', account_1.card_number", + " )", + " FROM agreego.account account_1", + " JOIN agreego.entity entity_2 ON entity_2.id = account_1.id", + " WHERE", + " NOT entity_2.archived", + "))))" ] ] } diff --git a/scripts/format_fixtures.py b/scripts/format_fixtures.py deleted file mode 100644 index 5fcfeca..0000000 --- a/scripts/format_fixtures.py +++ /dev/null @@ -1,128 +0,0 @@ -import json -import re -import subprocess -import os - -def format_sql(sql_str): - """ - Given a single-line SQL string from the test runner, - formats it with beautiful indentation according to the - rules seen in the jspg project fixtures. - """ - - # 1. First, let's normalize spaces around operators to make splitting easier. - # We'll use a simple regex tokenizer. - # The actual SQL doesn't have spaces around =, >, <, etc. - sql_str = re.sub(r'([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)=([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)', r'\1.\2 = \3.\4', sql_str) - sql_str = re.sub(r"([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)='([a-zA-Z0-9_]+)'", r"\1.\2 = '\3'", sql_str) - sql_str = re.sub(r"([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)>([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)", r"\1.\2 > \3.\4", sql_str) - sql_str = sql_str.replace("AND ", " AND ") - sql_str = sql_str.replace("WHERE NOT", "WHERE NOT") - - # We'll just run a basic custom state-machine formatter - # Let's clean up tokens to preserve spaces. - - # We will build the string by adding newlines and indentation where appropriate. - out = [] - indent = 0 - i = 0 - - # A quick helper to match and consume - def match(prefix): - if sql_str[i:].startswith(prefix): - return True - return False - - in_build_object = [] - - # Let's just use a simpler replacement strategy for line breaks, - # then iterate over lines to fix indentation. - - # Pre-process for line breaks: - s = sql_str - - # Break before certain keywords - s = s.replace("(SELECT COALESCE", "\n(SELECT COALESCE") - s = s.replace("FROM ", "\nFROM ") - s = s.replace("JOIN ", "\nJOIN ") - s = s.replace("WHERE ", "\nWHERE\n ") - s = s.replace(" AND ", "\n AND ") - - # Break before keys in jsonb_build_object, but only if they are followed by a subquery - # We'll do this by matching: ,'key_name',(SELECT - s = re.sub(r",('([^']+)')\s*,\s*\(SELECT", r",\n\1,\n(SELECT", s) - - # Also break scalar keys in jsonb_build_object - s = re.sub(r",('([^']+)')\s*,", r",\n\1, ", s) - s = s.replace("jsonb_build_object('", "jsonb_build_object(\n'") - - # CASE statements - s = s.replace("CASE WHEN", "CASE\nWHEN") - s = s.replace("THEN(", "THEN\n(") - s = s.replace("ELSE NULL END", "\nELSE NULL END") - s = s.replace(" WHEN ", "\nWHEN ") - - lines = [l.strip() for l in s.split('\n') if l.strip()] - - # Now we do a pass to compute indentations based on parenthesis matching and keywords. - formatted_lines = [] - current_indent = 0 - - for idx, line in enumerate(lines): - # Calculate indent delta before - close_paren_count = 0 - while line.startswith(')'): - close_paren_count += 1 - line = line[1:] - - if close_paren_count > 0: - current_indent = max(0, current_indent - 2 * close_paren_count) - # Prepend the closed parens to the line properly if there's text left, - # or just emit them if it's just parens. - if line: - pass # We handle adding them back later - else: - formatted_lines.append(" " * current_indent + ")" * close_paren_count) - continue - - # Handle specific keywords - if line.startswith("FROM ") or line.startswith("JOIN ") or line.startswith("WHERE"): - pass # Keep parent indent - elif line.startswith("AND "): - line = " " + line - elif line.startswith("WHEN "): - line = " " + line - elif line.startswith("ELSE "): - line = " " + line - - # If it's a key value pair in build_object, we indent - if line.startswith("'") and "jsonb_build_object" not in line: - # We add 2 extra spaces for the items inside build_object - line = " " + line - - if line.startswith("(SELECT jsonb_build_object"): - line = " " + line - - formatted_line = (" " * current_indent) + (")" * close_paren_count) + line - - # Calculate indent delta after - open_paren_count = line.count('(') - line.count(')') - current_indent += max(0, open_paren_count * 2) - - formatted_lines.append(formatted_line) - - return formatted_lines - -def format_sql_regex(sql_str): - # The actual jspg parser output might be tricky, let's use a simpler heuristic formatting - # based exactly on the user's provided output format. - # It requires custom tokenizing because of nested SELECTs. - - # Let's try to tokenise - tokens = re.split(r"(\(SELECT COALESCE|\(SELECT jsonb_build_object|FROM|JOIN|WHERE|AND|CASE|WHEN|THEN|ELSE NULL END|\n|,\s*')", sql_str) - - pass - -# We will actually just run `cargo test -- --nocapture` to grab the actual SQLs -# and do some string replacements. -# Given the complexity, let's build a dedicated node-based formatter in python. diff --git a/src/database/compile/polymorphism.rs b/src/database/compile/polymorphism.rs index df0ca9c..fce6bab 100644 --- a/src/database/compile/polymorphism.rs +++ b/src/database/compile/polymorphism.rs @@ -1,3 +1,4 @@ +use indexmap::IndexSet; use crate::database::schema::Schema; impl Schema { @@ -65,10 +66,10 @@ impl Schema { } } } else if let Some(one_of) = &self.obj.one_of { - let mut type_vals = std::collections::HashSet::new(); - let mut kind_vals = std::collections::HashSet::new(); + let mut type_vals = IndexSet::new(); + let mut kind_vals = IndexSet::new(); let mut disjoint_base = true; - let mut structural_types = std::collections::HashSet::new(); + let mut structural_types = IndexSet::new(); for c in one_of { let mut child_id = String::new(); diff --git a/src/database/enum.rs b/src/database/enum.rs index f6df2e5..a89395e 100644 --- a/src/database/enum.rs +++ b/src/database/enum.rs @@ -1,4 +1,5 @@ use crate::database::schema::Schema; +use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use std::sync::Arc; @@ -10,5 +11,5 @@ pub struct Enum { pub source: String, pub values: Vec, #[serde(default)] - pub schemas: std::collections::BTreeMap>, + pub schemas: IndexMap>, } diff --git a/src/database/punc.rs b/src/database/punc.rs index 55fa9d7..b451894 100644 --- a/src/database/punc.rs +++ b/src/database/punc.rs @@ -1,5 +1,6 @@ use crate::database::page::Page; use crate::database::schema::Schema; +use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use std::sync::Arc; @@ -18,5 +19,5 @@ pub struct Punc { pub save: Option, pub page: Option, #[serde(default)] - pub schemas: std::collections::BTreeMap>, + pub schemas: IndexMap>, } diff --git a/src/database/type.rs b/src/database/type.rs index 98a9fcd..e47f852 100644 --- a/src/database/type.rs +++ b/src/database/type.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use indexmap::{IndexMap, IndexSet}; use crate::database::schema::Schema; use serde::{Deserialize, Serialize}; @@ -25,7 +25,7 @@ pub struct Type { #[serde(default)] pub hierarchy: Vec, #[serde(default)] - pub variations: HashSet, + pub variations: IndexSet, #[serde(default)] pub relationship: bool, #[serde(default)] @@ -39,5 +39,5 @@ pub struct Type { pub default_fields: Vec, pub field_types: Option, #[serde(default)] - pub schemas: std::collections::BTreeMap>, + pub schemas: IndexMap>, } diff --git a/src/tests/formatter.rs b/src/tests/formatter.rs new file mode 100644 index 0000000..5c6ff14 --- /dev/null +++ b/src/tests/formatter.rs @@ -0,0 +1,393 @@ +use sqlparser::ast::{ + BinaryOperator, Expr, Function, FunctionArg, Join, JoinConstraint, JoinOperator, + Query, Select, SelectItem, SetExpr, Statement, TableWithJoins, Value +}; +use sqlparser::dialect::PostgreSqlDialect; +use sqlparser::parser::Parser; + +pub struct SqlFormatter { + pub lines: Vec, + pub indent: usize, +} + +impl SqlFormatter { + pub fn new() -> Self { + Self { + lines: Vec::new(), + indent: 0, + } + } + + pub fn format(sql: &str) -> Vec { + let dialect = PostgreSqlDialect {}; + let ast = match Parser::parse_sql(&dialect, sql) { + Ok(ast) => ast, + Err(e) => { + println!("DEBUG PARSE SQL ERROR: {:?}", e); + return vec![sql.to_string()]; + } + }; + + if ast.is_empty() { + return vec![sql.to_string()]; + } + + let mut formatter = SqlFormatter::new(); + formatter.format_statement(&ast[0]); + formatter.lines + } + + fn push_str(&mut self, s: &str) { + if self.lines.is_empty() { + self.lines.push(format!("{}{}", " ".repeat(self.indent), s.replace("JSONB", "jsonb"))); + } else { + let last = self.lines.last_mut().unwrap(); + last.push_str(&s.replace("JSONB", "jsonb")); + } + } + + fn push_line(&mut self, s: &str) { + self.lines.push(format!("{}{}", " ".repeat(self.indent), s.replace("JSONB", "jsonb"))); + } + + fn format_statement(&mut self, stmt: &Statement) { + match stmt { + Statement::Query(query) => { + self.push_line("("); + self.format_query(query); + self.push_str(")"); + } + Statement::Update(_update) => { + let sql = stmt.to_string(); + self.format_update_fallback(&sql); + } + _ => { + let sql = stmt.to_string(); + if sql.starts_with("INSERT") { + self.format_insert_fallback(&sql); + } else { + self.push_line(&sql); + } + } + } + } + + fn format_insert_fallback(&mut self, sql: &str) { + let s = sql.to_string(); + if let Some(values_idx) = s.find(" VALUES (") { + let prefix = &s[..values_idx]; + let suffix = &s[values_idx + 9..]; + + if let Some(paren_idx) = prefix.find(" (") { + self.push_line(&format!("{} (", &prefix[..paren_idx])); + self.indent += 2; + let cols = &prefix[paren_idx + 2..prefix.len() - 1]; + let cols_split: Vec<&str> = cols.split(", ").collect(); + for (i, col) in cols_split.iter().enumerate() { + let comma = if i < cols_split.len() - 1 { "," } else { "" }; + let c = col.replace("\"", ""); + self.push_line(&format!("\"{}\"{}", c, comma)); + } + self.indent -= 2; + self.push_line(")"); + } else { + self.push_line(prefix); + } + + self.push_line("VALUES ("); + self.indent += 2; + + let vals = if suffix.ends_with(")") { &suffix[..suffix.len() - 1] } else { suffix }; + let mut val_tokens = Vec::new(); + let mut curr = String::new(); + let mut in_str = false; + for c in vals.chars() { + if c == '\'' { + in_str = !in_str; + curr.push(c); + } else if c == ',' && !in_str { + val_tokens.push(curr.trim().to_string()); + curr = String::new(); + } else { + curr.push(c); + } + } + if !curr.trim().is_empty() { + val_tokens.push(curr.trim().to_string()); + } + + for (i, val) in val_tokens.iter().enumerate() { + let comma = if i < val_tokens.len() - 1 { "," } else { "" }; + + if val.starts_with("'{") && val.ends_with("}'") { + let inner = &val[1..val.len() - 1]; + // Unescape single quotes from SQL strings + let unescaped = inner.replace("''", "'"); + if let Ok(json) = serde_json::from_str::(&unescaped) { + if let Ok(pretty) = serde_json::to_string_pretty(&json) { + let lines: Vec<&str> = pretty.split('\n').collect(); + self.push_line("'{"); + self.indent += 2; + for (j, line) in lines.iter().skip(1).enumerate() { + if j == lines.len() - 2 { + self.indent -= 2; + // re-escape single quotes for SQL + self.push_line(&format!("{}'{}", line.replace("'", "''"), comma)); + } else { + self.push_line(&line.replace("'", "''")); + } + } + continue; + } + } + } + + self.push_line(&format!("{}{}", val, comma)); + } + self.indent -= 2; + self.push_line(")"); + } else { + self.push_line(&s); + } + } + + fn format_update_fallback(&mut self, sql: &str) { + let s = sql.to_string(); + if let Some(set_idx) = s.find(" SET ") { + self.push_line(&format!("{} SET", &s[..set_idx])); + self.indent += 2; + + let after_set = &s[set_idx + 5..]; + let where_idx = after_set.find(" WHERE "); + let assigns = if let Some(w) = where_idx { &after_set[..w] } else { after_set }; + let assigns_split: Vec<&str> = assigns.split(", ").collect(); + for (i, assign) in assigns_split.iter().enumerate() { + let comma = if i < assigns_split.len() - 1 { "," } else { "" }; + self.push_line(&format!("{}{}", assign.replace("\"", ""), comma)); + } + self.indent -= 2; + + if let Some(w) = where_idx { + self.push_line("WHERE"); + self.indent += 2; + self.push_line(&after_set[w + 7..]); + self.indent -= 2; + } + } else { + self.push_line(&s); + } + } + + fn format_query(&mut self, query: &Query) { + match &*query.body { + SetExpr::Select(select) => self.format_select(select), + SetExpr::Query(inner_query) => { + self.push_str("("); + self.format_query(inner_query); + self.push_str(")"); + } + _ => self.push_str(&query.to_string()), + } + } + + fn format_select(&mut self, select: &Select) { + self.push_str("SELECT "); + for (i, p) in select.projection.iter().enumerate() { + let comma = if i < select.projection.len() - 1 { ", " } else { "" }; + self.format_select_item(p); + self.push_str(comma); + } + + if !select.from.is_empty() { + self.push_line("FROM "); + for (i, table) in select.from.iter().enumerate() { + let comma = if i < select.from.len() - 1 { ", " } else { "" }; + self.format_table_with_joins(table); + self.push_str(comma); + } + + if let Some(selection) = &select.selection { + self.push_line("WHERE"); + self.indent += 2; + self.push_line(""); // new line for where clauses + self.format_expr(selection); + self.indent -= 2; + } + } + } + + fn format_select_item(&mut self, item: &SelectItem) { + match item { + SelectItem::UnnamedExpr(expr) => self.format_expr(expr), + SelectItem::ExprWithAlias { expr, alias } => { + self.format_expr(expr); + self.push_str(&format!(" AS {}", alias)); + } + _ => self.push_str(&item.to_string()), + } + } + + fn format_table_with_joins(&mut self, table: &TableWithJoins) { + self.push_str(&table.relation.to_string()); + for join in &table.joins { + self.push_line(""); + self.format_join(join); + } + } + + fn format_join(&mut self, join: &Join) { + let op = match &join.join_operator { + JoinOperator::Inner(_) => "JOIN", + JoinOperator::LeftOuter(_) => "LEFT JOIN", + _ => "JOIN", + }; + self.push_str(&format!("{} {} ON ", op, join.relation)); + + match &join.join_operator { + JoinOperator::Inner(JoinConstraint::On(expr)) => self.format_expr(expr), + JoinOperator::LeftOuter(JoinConstraint::On(expr)) => self.format_expr(expr), + JoinOperator::Join(JoinConstraint::On(expr)) => self.format_expr(expr), + _ => { + println!("FALLBACK JOIN OP: {:?}", join.join_operator); + } + } + } + + fn format_expr(&mut self, expr: &Expr) { + match expr { + Expr::Function(func) => self.format_function(func), + Expr::BinaryOp { left, op, right } => { + if *op == BinaryOperator::And || *op == BinaryOperator::Or { + self.format_expr(left); + self.push_line(&format!("{} ", op)); + self.format_expr(right); + } else { + self.format_expr(left); + self.push_str(&format!(" {} ", op)); + self.format_expr(right); + } + } + Expr::Nested(inner) => { + self.push_str("("); + self.format_expr(inner); + self.push_str(")"); + } + Expr::IsNull(inner) => { + self.format_expr(inner); + self.push_str(" IS NULL"); + } + Expr::IsNotNull(inner) => { + self.format_expr(inner); + self.push_str(" IS NOT NULL"); + } + Expr::Subquery(query) => { + self.push_str("("); + self.indent += 2; + self.push_line(""); + self.format_query(query); + self.indent -= 2; + self.push_line(")"); + } + Expr::Case { operand, conditions, else_result, .. } => { + self.push_str("CASE"); + if let Some(op) = operand { + self.push_str(" "); + self.format_expr(op); + } + self.indent += 2; + for when in conditions { + self.push_line("WHEN "); + self.format_expr(&when.condition); + self.push_str(" THEN "); + self.format_expr(&when.result); + } + if let Some(els) = else_result { + self.push_line("ELSE "); + self.format_expr(els); + } + self.indent -= 2; + self.push_line("END"); + } + Expr::UnaryOp { op, expr: inner } => { + self.push_str(&format!("{} ", op)); + self.format_expr(inner); + } + + Expr::Value(sqlparser::ast::ValueWithSpan { value: Value::SingleQuotedString(s), .. }) | Expr::Value(sqlparser::ast::ValueWithSpan { value: Value::EscapedStringLiteral(s), .. }) => { + if s.starts_with('{') && s.ends_with('}') { + if let Ok(json) = serde_json::from_str::(s) { + if let Ok(pretty) = serde_json::to_string_pretty(&json) { + let lines: Vec<&str> = pretty.split('\n').collect(); + self.push_str("'{"); + self.indent += 2; + for (j, line) in lines.iter().skip(1).enumerate() { + if j == lines.len() - 2 { + self.indent -= 2; + self.push_line(&format!("{}'", line.replace("'", "''"))); + } else { + self.push_line(&line.replace("'", "''")); + } + } + return; + } + } + } + self.push_str(&expr.to_string()); + } + _ => { + self.push_str(&expr.to_string()); + } + } + } + + fn format_function(&mut self, func: &Function) { + let name = func.name.to_string(); + self.push_str(&format!("{}(", name)); + + if let sqlparser::ast::FunctionArguments::List(list) = &func.args { + if name == "jsonb_build_object" { + self.indent += 2; + self.push_line(""); + let mut i = 0; + while i < list.args.len() { + let arg_key = &list.args[i]; + let arg_val = if i + 1 < list.args.len() { Some(&list.args[i+1]) } else { None }; + + self.format_function_arg(arg_key); + self.push_str(", "); + if let Some(val) = arg_val { + self.format_function_arg(val); + } + + if i + 2 < list.args.len() { + self.push_str(","); + self.push_line(""); + } + i += 2; + } + self.indent -= 2; + self.push_line(")"); + } else { + for (i, arg) in list.args.iter().enumerate() { + let comma = if i < list.args.len() - 1 { ", " } else { "" }; + self.format_function_arg(arg); + self.push_str(comma); + } + self.push_str(")"); + } + } else { + self.push_str(")"); + } + } + + fn format_function_arg(&mut self, arg: &FunctionArg) { + match arg { + FunctionArg::Unnamed(sqlparser::ast::FunctionArgExpr::Expr(expr)) => self.format_expr(expr), + _ => { + println!("FALLBACK ARG: {:?}", arg); + self.push_str(&arg.to_string()); + } + } + } +} + diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 268b2a7..2e9a7f2 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -1,4 +1,5 @@ use crate::*; +pub mod formatter; pub mod runner; pub mod types; use serde_json::json; diff --git a/src/tests/runner.rs b/src/tests/runner.rs index 87bcf7c..19b74e3 100644 --- a/src/tests/runner.rs +++ b/src/tests/runner.rs @@ -127,7 +127,7 @@ pub fn run_test_case(path: &str, suite_idx: usize, case_idx: usize) -> Result<() } } "merge" => { - let result = test.run_merge(db_unwrapped.unwrap()); + let result = test.run_merge(db_unwrapped.unwrap(), path, suite_idx, case_idx); if let Err(e) = result { println!("TEST MERGE ERROR FOR '{}': {}", test.description, e); failures.push(format!( @@ -137,7 +137,7 @@ pub fn run_test_case(path: &str, suite_idx: usize, case_idx: usize) -> Result<() } } "query" => { - let result = test.run_query(db_unwrapped.unwrap()); + let result = test.run_query(db_unwrapped.unwrap(), path, suite_idx, case_idx); if let Err(e) = result { println!("TEST QUERY ERROR FOR '{}': {}", test.description, e); failures.push(format!( @@ -160,3 +160,83 @@ pub fn run_test_case(path: &str, suite_idx: usize, case_idx: usize) -> Result<() Ok(()) } + +pub fn extract_uuids(val: &Value, path: &str, map: &mut HashMap) { + let uuid_re = regex::Regex::new(r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$").unwrap(); + + match val { + Value::Object(obj) => { + for (k, v) in obj { + let new_path = if path.is_empty() { k.clone() } else { format!("{}.{}", path, k) }; + extract_uuids(v, &new_path, map); + } + } + Value::Array(arr) => { + for (i, v) in arr.iter().enumerate() { + let new_path = if path.is_empty() { i.to_string() } else { format!("{}.{}", path, i) }; + extract_uuids(v, &new_path, map); + } + } + Value::String(s) => { + if s != "00000000-0000-0000-0000-000000000000" && uuid_re.is_match(s) { + map.insert(s.clone(), path.to_string()); + } + } + _ => {} + } +} + +pub fn canonicalize_with_map(s: &str, uuid_map: &HashMap, gen_map: &mut HashMap) -> String { + let uuid_re = regex::Regex::new(r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}").unwrap(); + let s1 = uuid_re.replace_all(s, |caps: ®ex::Captures| { + let val = &caps[0]; + if val == "00000000-0000-0000-0000-000000000000" { + val.to_string() + } else if let Some(path) = uuid_map.get(val) { + format!("{{{{uuid:{}}}}}", path) + } else { + let next_idx = gen_map.len(); + let idx = *gen_map.entry(val.to_string()).or_insert(next_idx); + format!("{{{{uuid:generated_{}}}}}", idx) + } + }); + + let ts_re = regex::Regex::new(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,6})?(?:Z|\+\d{2}(?::\d{2})?)?").unwrap(); + ts_re.replace_all(&s1, "{{timestamp}}").to_string() +} + +pub fn update_sql_fixture(path: &str, suite_idx: usize, case_idx: usize, queries: &[String]) { + use crate::tests::formatter::SqlFormatter; + let content = fs::read_to_string(path).unwrap(); + let mut file_data: Value = serde_json::from_str(&content).unwrap(); + + let mut uuid_map = HashMap::new(); + if let Some(test_case) = file_data.get(suite_idx).and_then(|s| s.get("tests")).and_then(|t| t.get(case_idx)) { + if let Some(data) = test_case.get("data") { + extract_uuids(data, "data", &mut uuid_map); + } + if let Some(mocks) = test_case.get("mocks") { + extract_uuids(mocks, "mocks", &mut uuid_map); + } + } + + let mut gen_map = HashMap::new(); + + let mut formatted_sql = Vec::new(); + for q in queries { + let res = SqlFormatter::format(q); + let mapped_res: Vec = res.into_iter().map(|l| canonicalize_with_map(&l, &uuid_map, &mut gen_map)).collect(); + formatted_sql.push(mapped_res); + } + + if let Some(expect) = file_data[suite_idx]["tests"][case_idx].get_mut("expect") { + if let Some(obj) = expect.as_object_mut() { + obj.remove("pattern"); + obj.insert("sql".to_string(), serde_json::json!(formatted_sql)); + } + } + + // To preserve original formatting, we just use serde_json pretty output + let formatted_json = serde_json::to_string_pretty(&file_data).unwrap(); + fs::write(path, formatted_json).unwrap(); +} diff --git a/src/tests/types/case.rs b/src/tests/types/case.rs index 0f5f4df..3f73646 100644 --- a/src/tests/types/case.rs +++ b/src/tests/types/case.rs @@ -75,7 +75,7 @@ impl Case { Ok(()) } - pub fn run_merge(&self, db: Arc) -> Result<(), String> { + pub fn run_merge(&self, db: Arc, path: &str, suite_idx: usize, case_idx: usize) -> Result<(), String> { if let Some(mocks) = &self.mocks { if let Some(arr) = mocks.as_array() { db.executor.set_mocks(arr.clone()); @@ -94,7 +94,10 @@ impl Case { } else if result.errors.is_empty() { // Only assert SQL if merge succeeded let queries = db.executor.get_queries(); - expect.assert_pattern(&queries).and_then(|_| expect.assert_sql(&queries)) + if std::env::var("UPDATE_EXPECT").is_ok() { + crate::tests::runner::update_sql_fixture(path, suite_idx, case_idx, &queries); + } + expect.assert_sql(&queries) } else { Ok(()) } @@ -106,7 +109,7 @@ impl Case { return_val } - pub fn run_query(&self, db: Arc) -> Result<(), String> { + pub fn run_query(&self, db: Arc, path: &str, suite_idx: usize, case_idx: usize) -> Result<(), String> { if let Some(mocks) = &self.mocks { if let Some(arr) = mocks.as_array() { db.executor.set_mocks(arr.clone()); @@ -123,7 +126,10 @@ impl Case { Err(format!("Query {}", e)) } else if result.errors.is_empty() { let queries = db.executor.get_queries(); - expect.assert_pattern(&queries).and_then(|_| expect.assert_sql(&queries)) + if std::env::var("UPDATE_EXPECT").is_ok() { + crate::tests::runner::update_sql_fixture(path, suite_idx, case_idx, &queries); + } + expect.assert_sql(&queries) } else { Ok(()) }