From ccb8c9526a62e87c14dc457e02d97b2fb6588669 Mon Sep 17 00:00:00 2001 From: Marcus Gartner Date: Mon, 15 Nov 2021 18:11:44 -0500 Subject: [PATCH] sql: fix placeholder type resolution When assignment casts for inserts were add in #70722, type resolution of placeholders in prepared statements was changed so that during the prepare phase the optimizer would only plan assignment casts when it could not be guaranteed that an insert column would be an identical type to the target column. Unfortunately, the change to placeholder type resolution change strays from Postgres's behavior and breaks some third-party tools. This commit reverts the type resolution changes, and as a result, assignment casts are always planned to convert each insert column to its target column type, even if the cast ends up being a no-op because the types are identical. I attempted to implement a solution that did not plan assignment casts in all cases, but it proved to be tedious and error prone, so I opted for this simpler solution for now. My attempt required annotating each placeholder expression in the memo with a context: a non-assignment context or an assignment context. This context would be used during the EXECUTE to determine whether a placeholder value should undergo a regular cast or an assignment cast: a critical decision due to their slightly different behaviors (see `PerformAssignmentCast`). The problem is that correctly annotating placeholders in complex mutations with expressions like subqueries or CTEs is difficult. Fixes #71576 There is no release note because this bug was never present in a release. Release note: None --- .../logic_test/multi_region_query_behavior | 10 +- .../testdata/logic_test/new_schema_changer | 1 - .../testdata/logic_test/partitioning_implicit | 7 +- .../logic_test/regional_by_row_query_behavior | 42 +- .../testdata/logic_test/alter_primary_key | 16 +- pkg/sql/opt/exec/execbuilder/testdata/explain | 45 +- .../testdata/explain_analyze_plans | 18 +- pkg/sql/opt/exec/execbuilder/testdata/fk | 217 +- .../execbuilder/testdata/hash_sharded_index | 35 +- pkg/sql/opt/exec/execbuilder/testdata/insert | 26 +- pkg/sql/opt/exec/execbuilder/testdata/orderby | 4 +- pkg/sql/opt/exec/execbuilder/testdata/spool | 90 +- pkg/sql/opt/exec/execbuilder/testdata/unique | 602 +++-- .../exec/execbuilder/testdata/vectorize_local | 6 +- .../exec/execbuilder/testdata/virtual_columns | 215 +- pkg/sql/opt/exec/execbuilder/testdata/with | 2 +- pkg/sql/opt/exec/explain/testdata/gists | 44 +- pkg/sql/opt/memo/expr.go | 2 +- pkg/sql/opt/memo/testdata/logprops/insert | 393 ++-- pkg/sql/opt/memo/testdata/logprops/join | 38 +- pkg/sql/opt/memo/testdata/logprops/upsert | 217 +- pkg/sql/opt/memo/testdata/stats/insert | 139 +- pkg/sql/opt/memo/typing.go | 7 +- pkg/sql/opt/norm/rules/scalar.opt | 2 +- pkg/sql/opt/norm/testdata/rules/groupby | 439 ++-- pkg/sql/opt/norm/testdata/rules/prune_cols | 36 +- pkg/sql/opt/norm/testdata/rules/with | 173 +- pkg/sql/opt/optbuilder/mutation_builder.go | 66 +- .../opt/optbuilder/testdata/fk-checks-insert | 843 ++++--- pkg/sql/opt/optbuilder/testdata/insert | 1570 ++++++++----- .../opt/optbuilder/testdata/inverted-indexes | 48 +- .../opt/optbuilder/testdata/partial-indexes | 973 ++++---- .../opt/optbuilder/testdata/projection-reuse | 85 +- pkg/sql/opt/optbuilder/testdata/select | 87 +- .../optbuilder/testdata/unique-checks-insert | 2040 ++++++++++------- pkg/sql/opt/optbuilder/testdata/upsert | 256 ++- .../opt/optbuilder/testdata/virtual-columns | 360 +-- pkg/sql/opt/optbuilder/testdata/with | 132 +- .../Syntaxes/optgen.tmLanguage | 1 + pkg/sql/opt/optgen/lang/support/vim/cropt.vim | 2 +- .../syntaxes/optgen.tmLanguage | 1 + pkg/sql/opt/xform/testdata/coster/join | 130 +- pkg/sql/opt/xform/testdata/external/tpcc | 238 +- .../xform/testdata/external/tpcc-later-stats | 238 +- .../opt/xform/testdata/external/tpcc-no-stats | 238 +- pkg/sql/opt/xform/testdata/external/tpce | 991 ++++---- .../opt/xform/testdata/external/tpce-no-stats | 991 ++++---- pkg/sql/opt/xform/testdata/external/trading | 34 +- .../xform/testdata/external/trading-mutation | 36 +- pkg/sql/opt/xform/testdata/external/ycsb | 58 +- pkg/sql/opt/xform/testdata/physprops/ordering | 174 +- pkg/sql/opt/xform/testdata/rules/groupby | 51 +- pkg/sql/opt/xform/testdata/rules/join | 33 +- pkg/sql/opt/xform/testdata/rules/scan | 27 +- pkg/sql/pgwire/testdata/pgtest/char | 8 +- pkg/sql/sem/tree/cast.go | 10 +- pkg/sql/sem/tree/type_check.go | 12 +- pkg/sql/sem/tree/type_check_test.go | 4 +- pkg/sql/types/types.go | 84 - pkg/sql/types/types_test.go | 113 - 60 files changed, 7382 insertions(+), 5378 deletions(-) diff --git a/pkg/ccl/logictestccl/testdata/logic_test/multi_region_query_behavior b/pkg/ccl/logictestccl/testdata/logic_test/multi_region_query_behavior index 8308523678b4..158f307cf4a5 100644 --- a/pkg/ccl/logictestccl/testdata/logic_test/multi_region_query_behavior +++ b/pkg/ccl/logictestccl/testdata/logic_test/multi_region_query_behavior @@ -205,8 +205,14 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 11 columns, 1 row +│ └── • render +│ │ estimated row count: 1 +│ │ +│ └── • render +│ │ estimated row count: 1 +│ │ +│ └── • values +│ size: 9 columns, 1 row │ ├── • constraint-check │ │ diff --git a/pkg/ccl/logictestccl/testdata/logic_test/new_schema_changer b/pkg/ccl/logictestccl/testdata/logic_test/new_schema_changer index 3d70995b1872..7eaf1c1cbe6e 100644 --- a/pkg/ccl/logictestccl/testdata/logic_test/new_schema_changer +++ b/pkg/ccl/logictestccl/testdata/logic_test/new_schema_changer @@ -10,4 +10,3 @@ statement ok CREATE INDEX id1 ON defaultdb.t1 (id, name) STORING (money) PARTITION BY LIST (id) (PARTITION p1 VALUES IN (1)); - diff --git a/pkg/ccl/logictestccl/testdata/logic_test/partitioning_implicit b/pkg/ccl/logictestccl/testdata/logic_test/partitioning_implicit index 9deca50be21b..2364b1c94cfc 100644 --- a/pkg/ccl/logictestccl/testdata/logic_test/partitioning_implicit +++ b/pkg/ccl/logictestccl/testdata/logic_test/partitioning_implicit @@ -734,8 +734,11 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 8 columns, 1 row +│ └── • render +│ │ estimated row count: 1 +│ │ +│ └── • values +│ size: 7 columns, 1 row │ ├── • constraint-check │ │ diff --git a/pkg/ccl/logictestccl/testdata/logic_test/regional_by_row_query_behavior b/pkg/ccl/logictestccl/testdata/logic_test/regional_by_row_query_behavior index a4b034a57aa2..31c01652e789 100644 --- a/pkg/ccl/logictestccl/testdata/logic_test/regional_by_row_query_behavior +++ b/pkg/ccl/logictestccl/testdata/logic_test/regional_by_row_query_behavior @@ -1073,8 +1073,12 @@ SELECT * FROM [EXPLAIN INSERT INTO child VALUES (1, 1)] OFFSET 2 │ equality cols are key │ lookup condition: (column2 = p_id) AND (crdb_region = 'ap-southeast-2') │ - └── • scan buffer - label: buffer 1 + └── • filter + │ estimated row count: 1 + │ filter: column2 IS NOT NULL + │ + └── • scan buffer + label: buffer 1 query T SELECT * FROM [EXPLAIN UPSERT INTO child VALUES (1, 1)] OFFSET 2 @@ -1425,8 +1429,11 @@ SELECT * FROM [EXPLAIN INSERT INTO regional_by_row_table (pk, pk2, a, b) VALUES │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 8 columns, 1 row +│ └── • render +│ │ estimated row count: 1 +│ │ +│ └── • values +│ size: 7 columns, 1 row │ ├── • constraint-check │ │ @@ -1760,8 +1767,14 @@ SELECT * FROM [EXPLAIN INSERT INTO regional_by_row_table_as (pk, a, b) VALUES (1 │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 5 columns, 1 row +│ └── • render +│ │ estimated row count: 1 +│ │ +│ └── • render +│ │ estimated row count: 1 +│ │ +│ └── • values +│ size: 3 columns, 1 row │ └── • constraint-check │ @@ -1821,8 +1834,11 @@ SELECT * FROM [EXPLAIN INSERT INTO regional_by_row_table_virt (pk, a, b) VALUES │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 7 columns, 1 row +│ └── • render +│ │ estimated row count: 1 +│ │ +│ └── • values +│ size: 4 columns, 1 row │ ├── • constraint-check │ │ @@ -2000,8 +2016,14 @@ SELECT * FROM [EXPLAIN INSERT INTO regional_by_row_table_virt_partial (pk, a, b) │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 9 columns, 1 row +│ └── • render +│ │ estimated row count: 1 +│ │ +│ └── • render +│ │ estimated row count: 1 +│ │ +│ └── • values +│ size: 4 columns, 1 row │ ├── • constraint-check │ │ diff --git a/pkg/sql/logictest/testdata/logic_test/alter_primary_key b/pkg/sql/logictest/testdata/logic_test/alter_primary_key index ef1d47e617fb..03d888b953f1 100644 --- a/pkg/sql/logictest/testdata/logic_test/alter_primary_key +++ b/pkg/sql/logictest/testdata/logic_test/alter_primary_key @@ -377,10 +377,18 @@ query T SELECT * FROM [EXPLAIN INSERT INTO t VALUES (4, 5, 6)] OFFSET 2 ---- · -• insert fast path - into: t(x, y, z, crdb_internal_z_shard_5, crdb_internal_y_shard_10) - auto commit - size: 7 columns, 1 row +• insert +│ into: t(x, y, z, crdb_internal_z_shard_5, crdb_internal_y_shard_10) +│ auto commit +│ +└── • render + │ estimated row count: 1 + │ + └── • render + │ estimated row count: 1 + │ + └── • values + size: 3 columns, 1 row # Ensure that all of the indexes have been rewritten. query IT diff --git a/pkg/sql/opt/exec/execbuilder/testdata/explain b/pkg/sql/opt/exec/execbuilder/testdata/explain index 36dc20079260..04d45bdcb549 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/explain +++ b/pkg/sql/opt/exec/execbuilder/testdata/explain @@ -793,8 +793,8 @@ vectorized: true into: t(k, v) auto commit size: 2 columns, 1 row - row 0, expr 0: (1)[int] - row 0, expr 1: (2)[int] + row 0, expr 0: (crdb_internal.assignment_cast((1)[int], ((NULL)[unknown]::INT8)[int]))[int] + row 0, expr 1: (crdb_internal.assignment_cast((2)[int], ((NULL)[unknown]::INT8)[int]))[int] query T EXPLAIN (TYPES) SELECT 42 AS a @@ -1408,20 +1408,26 @@ vectorized: true │ auto commit │ arbiter indexes: u_pkey, u_v_key │ -└── • lookup join (anti) - │ table: u@u_v_key - │ equality: (column2) = (v) - │ equality cols are key +└── • distinct + │ distinct on: column2 + │ nulls are distinct │ - └── • cross join (anti) - │ - ├── • values - │ size: 2 columns, 1 row + └── • distinct + │ distinct on: column1 + │ nulls are distinct │ - └── • scan - missing stats - table: u@u_pkey - spans: [/1 - /1] + └── • lookup join (anti) + │ table: u@u_pkey + │ equality: (column1) = (k) + │ equality cols are key + │ + └── • lookup join (anti) + │ table: u@u_v_key + │ equality: (column2) = (v) + │ equality cols are key + │ + └── • values + size: 2 columns, 1 row # Make sure EXPLAIN (VERBOSE) works when there is a constrained scan of a # virtual table (#58193). @@ -1560,9 +1566,14 @@ EXPLAIN INSERT INTO t2 SELECT x FROM t2 WHERE false distribution: local vectorized: true · -• insert fast path - into: t2(x) - auto commit +• insert +│ into: t2(x) +│ auto commit +│ +└── • render + │ estimated row count: 0 + │ + └── • norows statement ok PREPARE prep AS SELECT $1 + 1 diff --git a/pkg/sql/opt/exec/execbuilder/testdata/explain_analyze_plans b/pkg/sql/opt/exec/execbuilder/testdata/explain_analyze_plans index 284743faac26..80f76f726d83 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/explain_analyze_plans +++ b/pkg/sql/opt/exec/execbuilder/testdata/explain_analyze_plans @@ -351,11 +351,17 @@ regions: │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ nodes: -│ regions: -│ actual row count: 1 -│ size: 2 columns, 1 row +│ └── • render +│ │ nodes: +│ │ regions: +│ │ actual row count: 1 +│ │ estimated row count: 1 +│ │ +│ └── • values +│ nodes: +│ regions: +│ actual row count: 1 +│ size: 1 column, 1 row │ ├── • subquery │ │ id: @S1 @@ -414,5 +420,5 @@ regions: label: buffer 1 · Diagram 1 (subquery): https://cockroachdb.github.io/distsqlplan/decode.html#eJysUtFq20oQfb9fMcyTDRssOVwo-5Q0uGDiyMV2DKWYsF4NyhJpV90d1XaNP6s_0C8rlqw2IsRtaR_nzJzZM2fPHsOnHCWOk_lotoBxspiCfjR5Csvryf1oDr1YQG8-moxuFlAY2yv78G42vYNSebLc76NA61JKVEEB5UeMUeD_uBJYeqcpBOeP8L4eGqdblJFAY8uKj_BKoHaeUO6RDeeEEhN34crBEAWmxMrk9VLakq7YOAtsCpIQffsaUOBasX6kAK7ismIJEQr0bvMTiHF1ENhUp_cCq4xQXh7EM03xeU0Ltc5pRiolP4i6yhobrkpvCuV3KHBeKhskXKDAiSkMw9GQ22VX-O0StLNM9uVNt0uoT_CkUtmS1zumFnoDb1Hg3fLmBgJTCdpVlqFHWx4Yy30JUa2xGSB6em2gUFsoqHB-ByrPnVZMqYSo3v4XxsZ_Yux1lnnKFDs_iLu-XicfHpLp4iG5n0x6V_ExZv8-BMOO1l8Ec0ahdDZQR-drm6PDSiClGTXhD67ymt57p-tnmnJa82ogpcBN97IpxrZpHQU-J8dnycPz5OFZctQl16fUV6El3jj_BLlisnr3w_kW3yjD3T9JKZA3Kjdf1MsPa2mnmGsyn-kU9bbV5r3tNZlvuwWFoLLOQPS7QVgd_vseAAD___Xaogg= -Diagram 2 (main-query): https://cockroachdb.github.io/distsqlplan/decode.html#eJyskcFq8zAQhO__Uyx7SkAQK0ed8lNcMKRxSdJeig-uvCQCRXKlVRsIfqy-QJ-s2C60KbQQ6HFmZ0Yf6ITxyaLCYrXJ11soVtsS9N7YBu7_L-_yDUykgMkmX-ZXWzgYN2mncL0ub6CtAzmeTlGg8w2t6gNFVA8osRLYBq8pRh966zQEiuaIKhNoXJu4tyuB2gdCdUI2bAkVWq9rC8-1TRQhm2UosCGujR2Wy8QKFnOxkCiQjqQTG--AzYEUZG-vEQU-1qz3FMEnbvt4PxH8y6chseoEjuqDInK9I1SyE5eSap8cg5zJc9C_Z5tfwram2HoX6Qzqp-WsqwRSs6Pxp6JPQdNt8Hp4ZpTl0BuMhiKPVzmKwo2nHvBrWf5ann8rV92_9wAAAP__OpjUsw== +Diagram 2 (main-query): https://cockroachdb.github.io/distsqlplan/decode.html#eJysktGK1TAQhu99imGuTiG4zV5JrhSpUKg90tP1RsqSTYazgTSpyVQXDn0sX8Ank7aCu4LKgnf5_5l_8mXIBfNnjwrr9lR1PdRtfwRz77yFj2-am-oEByngcKqa6m0PowuHqYB33fE9TDpR4KJAgSFaavVIGdUnlDgInFI0lHNMq3XZGmr7gKoU6MI082oPAk1MhOqC7NgTKvTRaA9ftJ8pQ3lVokBLrJ3fJncULCUFJtm7WxeYUtD-pc7ZncNIgW-NznyQSqm67V-J9qZp9mMh_pF5LR93o0B6IDOziwHYjaSg_P4to8A7zeaeMsSZp5kVrIApfv1lSBwWgbv6-cbM-kyo5CKeuwcT58Agr-TTNfx_tuvnsHWUpxgyPYH60-RyGQSSPdP-D3Kck6EPKZrtml0et9xmWMq8V-Uu6rCXVsDHYfnX8PVv4WF58SMAAP__iA_1uQ== Diagram 3 (postquery): https://cockroachdb.github.io/distsqlplan/decode.html#eJy0lMGO2jAQhu99itGcQLJEAnuofNrtipWyZJMKslwqDsYZdt0Ndmo7KgjxWH2BPlmVmFVLV6BStTfm9_zjb_it7NB9qZBjks3G0wKSrMhBPquqhPlN-jieQS9m0JuN0_FtAWule3Uf7qb5A9TCkvb9PjLUpqRMrMkh_4QxLhjW1khyzthW2nUNSblBHjFUum58Ky8YSmMJ-Q698hUhx8pIUYGTQsOyWa3IQjSIkGFJXqiqG583nsP1EBnShmTjldHg1Zo4RN-_OWS4FF4-kwPT-Lrtbf3WfP0pxLjYMwzVgcN58UTI4z37c9Y7VXmyZAfxMWDQOVzHkMwgywvIHtP0v_AOL-G9N0pPSZRkB8Nj4mJbE4d0fFfATVYkcJ8nGTIMAV_XVq2F3SLD1JiXpobPRmkwut0Q2SGP9ld3ObToLfNr7byoquONJ_M3tTTak37750zm3UCwJMowdTKH5dbTq_QePiDDh_ntLThPNUjTaA892viB0r7PDw8oNBC9nGr423Cik-GMLgknPHyy1lhQq7BzPBgd5_TvGa8uYZySq412dAR1anK0XzCk8onCB8CZxkr6aI3srgll3vk6oSTnw2kcikSHoxbwV3N81jw8bx6eNY_Om0dnzVe_mRf7dz8CAAD__4iLwK8= diff --git a/pkg/sql/opt/exec/execbuilder/testdata/fk b/pkg/sql/opt/exec/execbuilder/testdata/fk index 63ea37b78bb6..e9302db6ee25 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/fk +++ b/pkg/sql/opt/exec/execbuilder/testdata/fk @@ -26,8 +26,11 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 2 columns, 2 rows +│ └── • render +│ │ estimated row count: 2 +│ │ +│ └── • values +│ size: 2 columns, 2 rows │ └── • constraint-check │ @@ -59,10 +62,12 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • scan -│ missing stats -│ table: xy@xy_pkey -│ spans: FULL SCAN +│ └── • render +│ │ +│ └── • scan +│ missing stats +│ table: xy@xy_pkey +│ spans: FULL SCAN │ └── • constraint-check │ @@ -99,8 +104,11 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 2 columns, 2 rows +│ └── • render +│ │ estimated row count: 2 +│ │ +│ └── • values +│ size: 2 columns, 2 rows │ └── • constraint-check │ @@ -112,7 +120,7 @@ vectorized: true │ equality cols are key │ └── • filter - │ estimated row count: 1 + │ estimated row count: 2 │ filter: column2 IS NOT NULL │ └── • scan buffer @@ -144,8 +152,11 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 4 columns, 2 rows +│ └── • render +│ │ estimated row count: 2 +│ │ +│ └── • values +│ size: 4 columns, 2 rows │ └── • constraint-check │ @@ -157,7 +168,7 @@ vectorized: true │ equality cols are key │ └── • filter - │ estimated row count: 1 + │ estimated row count: 2 │ filter: (column2 IS NOT NULL) AND (column3 IS NOT NULL) │ └── • scan buffer @@ -193,8 +204,11 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 4 columns, 2 rows +│ └── • render +│ │ estimated row count: 2 +│ │ +│ └── • values +│ size: 4 columns, 2 rows │ ├── • constraint-check │ │ @@ -206,7 +220,7 @@ vectorized: true │ │ equality cols are key │ │ │ └── • filter -│ │ estimated row count: 1 +│ │ estimated row count: 2 │ │ filter: column2 IS NOT NULL │ │ │ └── • scan buffer @@ -222,7 +236,7 @@ vectorized: true │ equality cols are key │ └── • filter - │ estimated row count: 1 + │ estimated row count: 2 │ filter: (column3 IS NOT NULL) AND (column4 IS NOT NULL) │ └── • scan buffer @@ -235,12 +249,48 @@ EXPLAIN INSERT INTO multi_ref_child VALUES (1, NULL, NULL, NULL) distribution: local vectorized: true · -• insert -│ into: multi_ref_child(k, a, b, c) -│ auto commit +• root +│ +├── • insert +│ │ into: multi_ref_child(k, a, b, c) +│ │ +│ └── • buffer +│ │ label: buffer 1 +│ │ +│ └── • values +│ size: 4 columns, 1 row +│ +├── • constraint-check +│ │ +│ └── • error if rows +│ │ +│ └── • lookup join (anti) +│ │ table: multi_ref_parent_a@multi_ref_parent_a_pkey +│ │ equality: (column2) = (a) +│ │ equality cols are key +│ │ +│ └── • filter +│ │ estimated row count: 1 +│ │ filter: column2 IS NOT NULL +│ │ +│ └── • scan buffer +│ label: buffer 1 │ -└── • values - size: 4 columns, 1 row +└── • constraint-check + │ + └── • error if rows + │ + └── • lookup join (anti) + │ table: multi_ref_parent_bc@multi_ref_parent_bc_pkey + │ equality: (column3, column4) = (b,c) + │ equality cols are key + │ + └── • filter + │ estimated row count: 1 + │ filter: (column3 IS NOT NULL) AND (column4 IS NOT NULL) + │ + └── • scan buffer + label: buffer 1 # -- Tests with DELETE -- @@ -924,17 +974,51 @@ EXPLAIN (VERBOSE) INSERT INTO child VALUES (1,1), (2,2) distribution: local vectorized: true · -• insert fast path - columns: () - estimated row count: 0 (missing stats) - into: child(c, p) - auto commit - FK check: parent@parent_pkey - size: 2 columns, 2 rows - row 0, expr 0: 1 - row 0, expr 1: 1 - row 1, expr 0: 2 - row 1, expr 1: 2 +• root +│ columns: () +│ +├── • insert +│ │ columns: () +│ │ estimated row count: 0 (missing stats) +│ │ into: child(c, p) +│ │ +│ └── • buffer +│ │ columns: (column1, column2) +│ │ label: buffer 1 +│ │ +│ └── • render +│ │ columns: (column1, column2) +│ │ estimated row count: 2 +│ │ render column1: crdb_internal.assignment_cast(column1, NULL::INT8) +│ │ render column2: crdb_internal.assignment_cast(column2, NULL::INT8) +│ │ +│ └── • values +│ columns: (column1, column2) +│ size: 2 columns, 2 rows +│ row 0, expr 0: 1 +│ row 0, expr 1: 1 +│ row 1, expr 0: 2 +│ row 1, expr 1: 2 +│ +└── • constraint-check + │ + └── • error if rows + │ columns: () + │ + └── • lookup join (anti) + │ columns: (column2) + │ estimated row count: 0 (missing stats) + │ table: parent@parent_pkey + │ equality: (column2) = (p) + │ equality cols are key + │ + └── • project + │ columns: (column2) + │ estimated row count: 2 + │ + └── • scan buffer + columns: (column1, column2) + label: buffer 1 # We shouldn't use the fast path if the VALUES columns are not in order. query B @@ -1197,11 +1281,32 @@ EXPLAIN INSERT INTO c VALUES (1,1), (2,2) distribution: local vectorized: true · -• insert fast path - into: c(c, p) - auto commit - FK check: p@p_pkey - size: 2 columns, 2 rows +• root +│ +├── • insert +│ │ into: c(c, p) +│ │ +│ └── • buffer +│ │ label: buffer 1 +│ │ +│ └── • render +│ │ estimated row count: 2 +│ │ +│ └── • values +│ size: 2 columns, 2 rows +│ +└── • constraint-check + │ + └── • error if rows + │ + └── • lookup join (anti) + │ estimated row count: 1 + │ table: p@p_pkey + │ equality: (column2) = (p) + │ equality cols are key + │ + └── • scan buffer + label: buffer 1 # These queries should not be using lookup joins (we're inserting more rows # than exist in the tables). @@ -1219,8 +1324,11 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 2 columns, 10 rows +│ └── • render +│ │ estimated row count: 10 +│ │ +│ └── • values +│ size: 2 columns, 10 rows │ └── • constraint-check │ @@ -1327,11 +1435,32 @@ EXPLAIN INSERT INTO c VALUES (1,1), (2,2), (3,3), (4,4), (5,5), (6,6), (7,7), (8 distribution: local vectorized: true · -• insert fast path - into: c(c, p) - auto commit - FK check: p@p_pkey - size: 2 columns, 10 rows +• root +│ +├── • insert +│ │ into: c(c, p) +│ │ +│ └── • buffer +│ │ label: buffer 1 +│ │ +│ └── • render +│ │ estimated row count: 10 +│ │ +│ └── • values +│ size: 2 columns, 10 rows +│ +└── • constraint-check + │ + └── • error if rows + │ + └── • lookup join (anti) + │ estimated row count: 9 + │ table: p@p_pkey + │ equality: (column2) = (p) + │ equality cols are key + │ + └── • scan buffer + label: buffer 1 query T EXPLAIN UPDATE c SET p=p+c WHERE c > 0 diff --git a/pkg/sql/opt/exec/execbuilder/testdata/hash_sharded_index b/pkg/sql/opt/exec/execbuilder/testdata/hash_sharded_index index f9f1f16dcbcb..e7cb00b328c6 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/hash_sharded_index +++ b/pkg/sql/opt/exec/execbuilder/testdata/hash_sharded_index @@ -31,11 +31,16 @@ vectorized: true │ render crdb_internal_a_shard_11_comp: mod(fnv32(crdb_internal.datums_to_bytes(column1)), 11)::INT4 │ render column1: column1 │ - └── • values - columns: (column1) - size: 1 column, 2 rows - row 0, expr 0: 1 - row 1, expr 0: 2 + └── • render + │ columns: (column1) + │ estimated row count: 2 + │ render column1: crdb_internal.assignment_cast(column1, NULL::INT8) + │ + └── • values + columns: (column1) + size: 1 column, 2 rows + row 0, expr 0: 1 + row 1, expr 0: 2 statement ok CREATE TABLE sharded_secondary (a INT8, INDEX (a) USING HASH WITH BUCKET_COUNT=12) @@ -61,17 +66,23 @@ vectorized: true │ render crdb_internal_a_shard_12_comp: crdb_internal_a_shard_12_comp │ └── • render - │ columns: (crdb_internal_a_shard_12_comp, rowid_default, column1) + │ columns: (crdb_internal_a_shard_12_comp, column1, rowid_default) │ estimated row count: 2 │ render crdb_internal_a_shard_12_comp: mod(fnv32(crdb_internal.datums_to_bytes(column1)), 12)::INT4 - │ render rowid_default: unique_rowid() │ render column1: column1 + │ render rowid_default: rowid_default │ - └── • values - columns: (column1) - size: 1 column, 2 rows - row 0, expr 0: 1 - row 1, expr 0: 2 + └── • render + │ columns: (rowid_default, column1) + │ estimated row count: 2 + │ render rowid_default: unique_rowid() + │ render column1: crdb_internal.assignment_cast(column1, NULL::INT8) + │ + └── • values + columns: (column1) + size: 1 column, 2 rows + row 0, expr 0: 1 + row 1, expr 0: 2 statement ok diff --git a/pkg/sql/opt/exec/execbuilder/testdata/insert b/pkg/sql/opt/exec/execbuilder/testdata/insert index e6a31b806566..e8785b74ca56 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/insert +++ b/pkg/sql/opt/exec/execbuilder/testdata/insert @@ -318,8 +318,8 @@ vectorized: true │ columns: (x, v, rowid_default) │ estimated row count: 10 (missing stats) │ render rowid_default: unique_rowid() - │ render x: x - │ render v: v + │ render x: crdb_internal.assignment_cast(x, NULL::INT8) + │ render v: crdb_internal.assignment_cast(v, NULL::INT8) │ └── • top-k │ columns: (x, v) @@ -351,8 +351,8 @@ vectorized: true │ columns: (x, v, rowid_default) │ estimated row count: 1 (missing stats) │ render rowid_default: unique_rowid() - │ render x: x - │ render v: v + │ render x: crdb_internal.assignment_cast(x, NULL::INT8) + │ render v: crdb_internal.assignment_cast(v, NULL::INT8) │ └── • scan columns: (x, v) @@ -467,8 +467,8 @@ vectorized: true │ columns: (length, "?column?", rowid_default) │ estimated row count: 10 (missing stats) │ render rowid_default: unique_rowid() - │ render length: length - │ render ?column?: "?column?" + │ render length: crdb_internal.assignment_cast(length, NULL::INT8) + │ render ?column?: crdb_internal.assignment_cast("?column?", NULL::INT8) │ └── • top-k │ columns: (length, "?column?", column12) @@ -516,7 +516,7 @@ vectorized: true estimated row count: 1 into: mutation(x, rowid, y) size: 3 columns, 1 row - row 0, expr 0: 2 + row 0, expr 0: crdb_internal.assignment_cast(2, NULL::INT8) row 0, expr 1: unique_rowid() row 0, expr 2: 10 @@ -538,8 +538,8 @@ vectorized: true estimated row count: 0 (missing stats) into: mutation(x, y, rowid) size: 3 columns, 1 row - row 0, expr 0: 2 - row 0, expr 1: 2 + row 0, expr 0: crdb_internal.assignment_cast(2, NULL::INT8) + row 0, expr 1: crdb_internal.assignment_cast(2, NULL::INT8) row 0, expr 2: unique_rowid() statement ok @@ -596,9 +596,9 @@ vectorized: true │ columns: (a, b, c, rowid_default) │ estimated row count: 1,000 (missing stats) │ render rowid_default: unique_rowid() - │ render a: a - │ render b: b - │ render c: c + │ render a: crdb_internal.assignment_cast(a, NULL::INT8) + │ render b: crdb_internal.assignment_cast(b, NULL::INT8) + │ render c: crdb_internal.assignment_cast(c, NULL::INT8) │ └── • scan columns: (a, b, c) @@ -644,5 +644,5 @@ vectorized: true FK check: t62270_parent@t62270_parent_pkey size: 3 columns, 1 row row 0, expr 0: gen_random_uuid() - row 0, expr 1: 1 + row 0, expr 1: crdb_internal.assignment_cast(1, NULL::INT8) row 0, expr 2: unique_rowid() diff --git a/pkg/sql/opt/exec/execbuilder/testdata/orderby b/pkg/sql/opt/exec/execbuilder/testdata/orderby index fbf0f40a9ad3..c8276023e3e8 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/orderby +++ b/pkg/sql/opt/exec/execbuilder/testdata/orderby @@ -725,8 +725,8 @@ vectorized: true into: t(a, b, c) auto commit size: 3 columns, 1 row - row 0, expr 0: 1 - row 0, expr 1: 2 + row 0, expr 0: crdb_internal.assignment_cast(1, NULL::INT8) + row 0, expr 1: crdb_internal.assignment_cast(2, NULL::INT8) row 0, expr 2: CAST(NULL AS BOOL) query T diff --git a/pkg/sql/opt/exec/execbuilder/testdata/spool b/pkg/sql/opt/exec/execbuilder/testdata/spool index 9dca46a13102..364f088ad197 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/spool +++ b/pkg/sql/opt/exec/execbuilder/testdata/spool @@ -33,10 +33,12 @@ vectorized: true └── • insert │ into: t(x) │ - └── • scan - missing stats - table: t2@t2_pkey - spans: FULL SCAN + └── • render + │ + └── • scan + missing stats + table: t2@t2_pkey + spans: FULL SCAN query T EXPLAIN WITH a AS (DELETE FROM t RETURNING x) @@ -163,10 +165,12 @@ vectorized: true └── • insert │ into: t(x) │ - └── • scan - missing stats - table: t2@t2_pkey - spans: FULL SCAN + └── • render + │ + └── • scan + missing stats + table: t2@t2_pkey + spans: FULL SCAN query T EXPLAIN SELECT * FROM [DELETE FROM t RETURNING x] LIMIT 1 @@ -288,10 +292,12 @@ vectorized: true └── • insert │ into: t(x) │ - └── • scan - missing stats - table: t2@t2_pkey - spans: FULL SCAN + └── • render + │ + └── • scan + missing stats + table: t2@t2_pkey + spans: FULL SCAN query T EXPLAIN SELECT * FROM [INSERT INTO t SELECT * FROM t2 RETURNING x], t @@ -322,10 +328,12 @@ vectorized: true └── • insert │ into: t(x) │ - └── • scan - missing stats - table: t2@t2_pkey - spans: FULL SCAN + └── • render + │ + └── • scan + missing stats + table: t2@t2_pkey + spans: FULL SCAN # Check that if a spool is already added at some level, then it is not added # again at levels below. @@ -357,10 +365,12 @@ vectorized: true │ └── • insert │ │ into: t(x) │ │ -│ └── • scan -│ missing stats -│ table: t2@t2_pkey -│ spans: FULL SCAN +│ └── • render +│ │ +│ └── • scan +│ missing stats +│ table: t2@t2_pkey +│ spans: FULL SCAN │ └── • subquery │ id: @S2 @@ -401,10 +411,12 @@ vectorized: true └── • insert │ into: t(x) │ - └── • scan - missing stats - table: t2@t2_pkey - spans: FULL SCAN + └── • render + │ + └── • scan + missing stats + table: t2@t2_pkey + spans: FULL SCAN # Check that no spool is used for a top-level INSERT, but # sub-INSERTs still get a spool. @@ -435,10 +447,12 @@ vectorized: true └── • insert │ into: t(x) │ - └── • scan - missing stats - table: t2@t2_pkey - spans: FULL SCAN + └── • render + │ + └── • scan + missing stats + table: t2@t2_pkey + spans: FULL SCAN # Check that simple computations using RETURNING get their spool pulled up. query T @@ -471,10 +485,12 @@ vectorized: true └── • insert │ into: t(x) │ - └── • scan - missing stats - table: t2@t2_pkey - spans: FULL SCAN + └── • render + │ + └── • scan + missing stats + table: t2@t2_pkey + spans: FULL SCAN # Check that a pulled up spool gets elided at the top level. query T @@ -504,7 +520,9 @@ vectorized: true └── • insert │ into: t(x) │ - └── • scan - missing stats - table: t2@t2_pkey - spans: FULL SCAN + └── • render + │ + └── • scan + missing stats + table: t2@t2_pkey + spans: FULL SCAN diff --git a/pkg/sql/opt/exec/execbuilder/testdata/unique b/pkg/sql/opt/exec/execbuilder/testdata/unique index dddde4ab7707..b76abef4dc43 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/unique +++ b/pkg/sql/opt/exec/execbuilder/testdata/unique @@ -254,8 +254,11 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 5 columns, 2 rows +│ └── • render +│ │ estimated row count: 2 +│ │ +│ └── • values +│ size: 5 columns, 2 rows │ ├── • constraint-check │ │ @@ -305,8 +308,27 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 5 columns, 2 rows +│ └── • render +│ │ estimated row count: 2 +│ │ +│ └── • values +│ size: 5 columns, 2 rows +│ +├── • constraint-check +│ │ +│ └── • error if rows +│ │ +│ └── • hash join (right semi) +│ │ equality: (w) = (column3) +│ │ pred: column1 != k +│ │ +│ ├── • scan +│ │ missing stats +│ │ table: uniq@uniq_pkey +│ │ spans: FULL SCAN +│ │ +│ └── • scan buffer +│ label: buffer 1 │ └── • constraint-check │ @@ -340,55 +362,76 @@ vectorized: true │ arbiter indexes: uniq_pkey, uniq_v_key │ arbiter constraints: unique_w, unique_x_y │ -└── • cross join (right anti) +└── • distinct │ columns: (column1, column2, column3, column4, column5) │ estimated row count: 0 (missing stats) + │ distinct on: column4, column5 + │ nulls are distinct │ - ├── • scan - │ columns: (k) - │ estimated row count: 1 (missing stats) - │ table: uniq@uniq_pkey - │ spans: /1/0 - │ - └── • hash join (right anti) + └── • distinct │ columns: (column1, column2, column3, column4, column5) │ estimated row count: 0 (missing stats) - │ equality: (w) = (column3) - │ right cols are key - │ - ├── • scan - │ columns: (w) - │ estimated row count: 1,000 (missing stats) - │ table: uniq@uniq_pkey - │ spans: FULL SCAN + │ distinct on: column3 + │ nulls are distinct │ - └── • lookup join (anti) + └── • distinct │ columns: (column1, column2, column3, column4, column5) │ estimated row count: 0 (missing stats) - │ table: uniq@uniq_v_key - │ equality: (column2) = (v) - │ equality cols are key + │ distinct on: column2 + │ nulls are distinct │ - └── • hash join (right anti) + └── • distinct │ columns: (column1, column2, column3, column4, column5) │ estimated row count: 0 (missing stats) - │ equality: (x, y) = (column4, column5) - │ right cols are key - │ - ├── • scan - │ columns: (x, y) - │ estimated row count: 1,000 (missing stats) - │ table: uniq@uniq_pkey - │ spans: FULL SCAN + │ distinct on: column1 + │ nulls are distinct │ - └── • values - columns: (column1, column2, column3, column4, column5) - size: 5 columns, 1 row - row 0, expr 0: 1 - row 0, expr 1: 2 - row 0, expr 2: 3 - row 0, expr 3: 4 - row 0, expr 4: 5 + └── • hash join (right anti) + │ columns: (column1, column2, column3, column4, column5) + │ estimated row count: 0 (missing stats) + │ equality: (w) = (column3) + │ right cols are key + │ + ├── • scan + │ columns: (w) + │ estimated row count: 1,000 (missing stats) + │ table: uniq@uniq_pkey + │ spans: FULL SCAN + │ + └── • lookup join (anti) + │ columns: (column1, column2, column3, column4, column5) + │ estimated row count: 0 (missing stats) + │ table: uniq@uniq_pkey + │ equality: (column1) = (k) + │ equality cols are key + │ + └── • lookup join (anti) + │ columns: (column1, column2, column3, column4, column5) + │ estimated row count: 0 (missing stats) + │ table: uniq@uniq_v_key + │ equality: (column2) = (v) + │ equality cols are key + │ + └── • hash join (right anti) + │ columns: (column1, column2, column3, column4, column5) + │ estimated row count: 0 (missing stats) + │ equality: (x, y) = (column4, column5) + │ right cols are key + │ + ├── • scan + │ columns: (x, y) + │ estimated row count: 1,000 (missing stats) + │ table: uniq@uniq_pkey + │ spans: FULL SCAN + │ + └── • values + columns: (column1, column2, column3, column4, column5) + size: 5 columns, 1 row + row 0, expr 0: crdb_internal.assignment_cast(1, NULL::INT8) + row 0, expr 1: crdb_internal.assignment_cast(2, NULL::INT8) + row 0, expr 2: crdb_internal.assignment_cast(3, NULL::INT8) + row 0, expr 3: crdb_internal.assignment_cast(4, NULL::INT8) + row 0, expr 4: crdb_internal.assignment_cast(5, NULL::INT8) # Insert with non-constant input. query T @@ -405,10 +448,12 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • scan -│ missing stats -│ table: other@other_pkey -│ spans: FULL SCAN +│ └── • render +│ │ +│ └── • scan +│ missing stats +│ table: other@other_pkey +│ spans: FULL SCAN │ ├── • constraint-check │ │ @@ -458,8 +503,11 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 4 columns, 2 rows +│ └── • render +│ │ estimated row count: 2 +│ │ +│ └── • values +│ size: 4 columns, 2 rows │ ├── • constraint-check │ │ @@ -726,17 +774,25 @@ vectorized: true │ │ render column3: column3 │ │ render column4: column4 │ │ -│ └── • values -│ columns: (column1, column2, column3, column4) -│ size: 4 columns, 2 rows -│ row 0, expr 0: 'us-west' -│ row 0, expr 1: 'foo' -│ row 0, expr 2: 1 -│ row 0, expr 3: 1 -│ row 1, expr 0: 'us-east' -│ row 1, expr 1: 'bar' -│ row 1, expr 2: 2 -│ row 1, expr 3: 2 +│ └── • render +│ │ columns: (column1, column2, column3, column4) +│ │ estimated row count: 2 +│ │ render column1: crdb_internal.assignment_cast(column1, NULL::public.region) +│ │ render column2: crdb_internal.assignment_cast(column2, NULL::STRING) +│ │ render column3: crdb_internal.assignment_cast(column3, NULL::INT8) +│ │ render column4: crdb_internal.assignment_cast(column4, NULL::INT8) +│ │ +│ └── • values +│ columns: (column1, column2, column3, column4) +│ size: 4 columns, 2 rows +│ row 0, expr 0: 'us-west' +│ row 0, expr 1: 'foo' +│ row 0, expr 2: 1 +│ row 0, expr 3: 1 +│ row 1, expr 0: 'us-east' +│ row 1, expr 1: 'bar' +│ row 1, expr 2: 2 +│ row 1, expr 3: 2 │ ├── • constraint-check │ │ @@ -752,18 +808,18 @@ vectorized: true │ │ estimated row count: 1 (missing stats) │ │ │ └── • lookup join (semi) -│ │ columns: ("lookup_join_const_col_@12", column1, column3) +│ │ columns: ("lookup_join_const_col_@16", column1, column3) │ │ table: uniq_enum@uniq_enum_pkey -│ │ equality: (lookup_join_const_col_@12, column3) = (r,i) +│ │ equality: (lookup_join_const_col_@16, column3) = (r,i) │ │ equality cols are key │ │ pred: column1 != r │ │ │ └── • cross join (inner) -│ │ columns: ("lookup_join_const_col_@12", column1, column3) +│ │ columns: ("lookup_join_const_col_@16", column1, column3) │ │ estimated row count: 6 │ │ │ ├── • values -│ │ columns: ("lookup_join_const_col_@12") +│ │ columns: ("lookup_join_const_col_@16") │ │ size: 1 column, 3 rows │ │ row 0, expr 0: 'us-east' │ │ row 1, expr 0: 'us-west' @@ -791,18 +847,18 @@ vectorized: true │ estimated row count: 1 (missing stats) │ └── • lookup join (semi) - │ columns: ("lookup_join_const_col_@22", column1, column2, column3, column4) + │ columns: ("lookup_join_const_col_@26", column1, column2, column3, column4) │ table: uniq_enum@uniq_enum_r_s_j_key - │ equality: (lookup_join_const_col_@22, column2, column4) = (r,s,j) + │ equality: (lookup_join_const_col_@26, column2, column4) = (r,s,j) │ equality cols are key │ pred: (column1 != r) OR (column3 != i) │ └── • cross join (inner) - │ columns: ("lookup_join_const_col_@22", column1, column2, column3, column4) + │ columns: ("lookup_join_const_col_@26", column1, column2, column3, column4) │ estimated row count: 6 │ ├── • values - │ columns: ("lookup_join_const_col_@22") + │ columns: ("lookup_join_const_col_@26") │ size: 1 column, 3 rows │ row 0, expr 0: 'us-east' │ row 1, expr 0: 'us-west' @@ -850,8 +906,8 @@ vectorized: true │ │ estimated row count: 2 │ │ render r_default: CASE (random() * 3.0)::INT8 WHEN 0 THEN 'us-east' WHEN 1 THEN 'us-west' ELSE 'eu-west' END │ │ render j_default: CAST(NULL AS INT8) -│ │ render column1: column1 -│ │ render column2: column2 +│ │ render column1: crdb_internal.assignment_cast(column1, NULL::STRING) +│ │ render column2: crdb_internal.assignment_cast(column2, NULL::INT8) │ │ │ └── • values │ columns: (column1, column2) @@ -875,18 +931,18 @@ vectorized: true │ estimated row count: 1 (missing stats) │ └── • lookup join (semi) - │ columns: ("lookup_join_const_col_@12", r_default, column2) + │ columns: ("lookup_join_const_col_@14", r_default, column2) │ table: uniq_enum@uniq_enum_pkey - │ equality: (lookup_join_const_col_@12, column2) = (r,i) + │ equality: (lookup_join_const_col_@14, column2) = (r,i) │ equality cols are key │ pred: r_default != r │ └── • cross join (inner) - │ columns: ("lookup_join_const_col_@12", r_default, column2) + │ columns: ("lookup_join_const_col_@14", r_default, column2) │ estimated row count: 6 │ ├── • values - │ columns: ("lookup_join_const_col_@12") + │ columns: ("lookup_join_const_col_@14") │ size: 1 column, 3 rows │ row 0, expr 0: 'us-east' │ row 1, expr 0: 'us-west' @@ -926,45 +982,77 @@ vectorized: true │ render column3: column3 │ render column4: column4 │ - └── • lookup join (anti) + └── • distinct │ columns: (column1, column2, column3, column4) │ estimated row count: 0 (missing stats) - │ table: uniq_enum@uniq_enum_r_s_j_key - │ equality cols are key - │ lookup condition: ((column2 = s) AND (column4 = j)) AND (r IN ('us-east', 'us-west', 'eu-west')) + │ distinct on: column2, column4 + │ nulls are distinct │ - └── • lookup join (anti) + └── • distinct │ columns: (column1, column2, column3, column4) │ estimated row count: 0 (missing stats) - │ table: uniq_enum@uniq_enum_pkey - │ equality cols are key - │ lookup condition: (column3 = i) AND (r IN ('us-east', 'us-west', 'eu-west')) + │ distinct on: column3 + │ nulls are distinct │ - └── • lookup join (anti) + └── • distinct │ columns: (column1, column2, column3, column4) │ estimated row count: 0 (missing stats) - │ table: uniq_enum@uniq_enum_pkey - │ equality: (column1, column3) = (r,i) - │ equality cols are key + │ distinct on: column1, column2, column4 + │ nulls are distinct │ - └── • lookup join (anti) + └── • distinct │ columns: (column1, column2, column3, column4) │ estimated row count: 0 (missing stats) - │ table: uniq_enum@uniq_enum_r_s_j_key - │ equality: (column1, column2, column4) = (r,s,j) - │ equality cols are key + │ distinct on: column1, column3 + │ nulls are distinct │ - └── • values - columns: (column1, column2, column3, column4) - size: 4 columns, 2 rows - row 0, expr 0: 'us-west' - row 0, expr 1: 'foo' - row 0, expr 2: 1 - row 0, expr 3: 1 - row 1, expr 0: 'us-east' - row 1, expr 1: 'bar' - row 1, expr 2: 2 - row 1, expr 3: 2 + └── • lookup join (anti) + │ columns: (column1, column2, column3, column4) + │ estimated row count: 0 (missing stats) + │ table: uniq_enum@uniq_enum_r_s_j_key + │ equality cols are key + │ lookup condition: ((column2 = s) AND (column4 = j)) AND (r IN ('us-east', 'us-west', 'eu-west')) + │ + └── • lookup join (anti) + │ columns: (column1, column2, column3, column4) + │ estimated row count: 0 (missing stats) + │ table: uniq_enum@uniq_enum_pkey + │ equality cols are key + │ lookup condition: (column3 = i) AND (r IN ('us-east', 'us-west', 'eu-west')) + │ + └── • lookup join (anti) + │ columns: (column1, column2, column3, column4) + │ estimated row count: 0 (missing stats) + │ table: uniq_enum@uniq_enum_pkey + │ equality: (column1, column3) = (r,i) + │ equality cols are key + │ + └── • lookup join (anti) + │ columns: (column1, column2, column3, column4) + │ estimated row count: 0 (missing stats) + │ table: uniq_enum@uniq_enum_r_s_j_key + │ equality: (column1, column2, column4) = (r,s,j) + │ equality cols are key + │ + └── • render + │ columns: (column1, column2, column3, column4) + │ estimated row count: 2 + │ render column1: crdb_internal.assignment_cast(column1, NULL::public.region) + │ render column2: crdb_internal.assignment_cast(column2, NULL::STRING) + │ render column3: crdb_internal.assignment_cast(column3, NULL::INT8) + │ render column4: crdb_internal.assignment_cast(column4, NULL::INT8) + │ + └── • values + columns: (column1, column2, column3, column4) + size: 4 columns, 2 rows + row 0, expr 0: 'us-west' + row 0, expr 1: 'foo' + row 0, expr 2: 1 + row 0, expr 3: 1 + row 1, expr 0: 'us-east' + row 1, expr 1: 'bar' + row 1, expr 2: 2 + row 1, expr 3: 2 # None of the inserted values have nulls. query T @@ -981,8 +1069,11 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 3 columns, 2 rows +│ └── • render +│ │ estimated row count: 2 +│ │ +│ └── • values +│ size: 3 columns, 2 rows │ ├── • constraint-check │ │ @@ -1046,8 +1137,35 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 3 columns, 2 rows +│ └── • render +│ │ estimated row count: 2 +│ │ +│ └── • values +│ size: 3 columns, 2 rows +│ +├── • constraint-check +│ │ +│ └── • error if rows +│ │ +│ └── • hash join (right semi) +│ │ equality: (a) = (column2) +│ │ pred: column1 != k +│ │ +│ ├── • filter +│ │ │ filter: b > 0 +│ │ │ +│ │ └── • scan +│ │ missing stats +│ │ table: uniq_partial@uniq_partial_pkey +│ │ spans: FULL SCAN +│ │ +│ └── • filter +│ │ estimated row count: 1 +│ │ filter: column3 > 0 +│ │ +│ └── • scan buffer +│ estimated row count: 2 +│ label: buffer 1 │ └── • constraint-check │ @@ -1095,7 +1213,7 @@ vectorized: true └── • distinct │ columns: (arbiter_unique_b_distinct, column1, column2, column3) │ estimated row count: 0 (missing stats) - │ distinct on: arbiter_unique_b_distinct + │ distinct on: arbiter_unique_b_distinct, column3 │ nulls are distinct │ └── • render @@ -1109,7 +1227,7 @@ vectorized: true └── • distinct │ columns: (arbiter_unique_a_distinct, column1, column2, column3) │ estimated row count: 0 (missing stats) - │ distinct on: arbiter_unique_a_distinct + │ distinct on: arbiter_unique_a_distinct, column2 │ nulls are distinct │ └── • render @@ -1120,57 +1238,60 @@ vectorized: true │ render column2: column2 │ render column3: column3 │ - └── • hash join (right anti) + └── • distinct │ columns: (column1, column2, column3) │ estimated row count: 0 (missing stats) - │ equality: (b) = (column3) - │ right cols are key - │ - ├── • filter - │ │ columns: (b) - │ │ estimated row count: 333 (missing stats) - │ │ filter: b > 0 - │ │ - │ └── • scan - │ columns: (b) - │ estimated row count: 1,000 (missing stats) - │ table: uniq_partial@uniq_partial_pkey - │ spans: FULL SCAN + │ distinct on: column1 + │ nulls are distinct │ └── • hash join (right anti) │ columns: (column1, column2, column3) │ estimated row count: 0 (missing stats) - │ equality: (a) = (column2) + │ equality: (b) = (column3) │ right cols are key - │ pred: column3 > 0 │ ├── • filter - │ │ columns: (a, b) + │ │ columns: (b) │ │ estimated row count: 333 (missing stats) │ │ filter: b > 0 │ │ │ └── • scan - │ columns: (a, b) + │ columns: (b) │ estimated row count: 1,000 (missing stats) │ table: uniq_partial@uniq_partial_pkey │ spans: FULL SCAN │ - └── • cross join (anti) + └── • lookup join (anti) │ columns: (column1, column2, column3) │ estimated row count: 0 (missing stats) + │ table: uniq_partial@uniq_partial_pkey + │ equality: (column1) = (k) + │ equality cols are key │ - ├── • values - │ columns: (column1, column2, column3) - │ size: 3 columns, 1 row - │ row 0, expr 0: 1 - │ row 0, expr 1: 2 - │ row 0, expr 2: 3 - │ - └── • scan - columns: (k) - estimated row count: 1 (missing stats) - table: uniq_partial@uniq_partial_pkey - spans: /1/0 + └── • hash join (right anti) + │ columns: (column1, column2, column3) + │ estimated row count: 0 (missing stats) + │ equality: (a) = (column2) + │ right cols are key + │ pred: column3 > 0 + │ + ├── • filter + │ │ columns: (a, b) + │ │ estimated row count: 333 (missing stats) + │ │ filter: b > 0 + │ │ + │ └── • scan + │ columns: (a, b) + │ estimated row count: 1,000 (missing stats) + │ table: uniq_partial@uniq_partial_pkey + │ spans: FULL SCAN + │ + └── • values + columns: (column1, column2, column3) + size: 3 columns, 1 row + row 0, expr 0: crdb_internal.assignment_cast(1, NULL::INT8) + row 0, expr 1: crdb_internal.assignment_cast(2, NULL::INT8) + row 0, expr 2: crdb_internal.assignment_cast(3, NULL::INT8) # Insert with non-constant input. query T @@ -1187,10 +1308,12 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • scan -│ missing stats -│ table: other@other_pkey -│ spans: FULL SCAN +│ └── • render +│ │ +│ └── • scan +│ missing stats +│ table: other@other_pkey +│ spans: FULL SCAN │ ├── • constraint-check │ │ @@ -1244,10 +1367,15 @@ EXPLAIN INSERT INTO uniq_partial_overlaps_pk VALUES (1, 1, 1), (2, 2, 2) distribution: local vectorized: true · -• insert fast path - into: uniq_partial_overlaps_pk(k, a, b) - auto commit - size: 3 columns, 2 rows +• insert +│ into: uniq_partial_overlaps_pk(k, a, b) +│ auto commit +│ +└── • render + │ estimated row count: 2 + │ + └── • values + size: 3 columns, 2 rows # Insert with non-constant input. # Add inequality filters for the hidden primary key column. @@ -1276,23 +1404,23 @@ vectorized: true │ └── • error if rows │ - └── • hash join (semi) - │ equality: (v) = (b) + └── • hash join (right semi) + │ equality: (b) = (v) │ pred: rowid_default != rowid │ ├── • filter - │ │ filter: x > 0 + │ │ filter: c > 0 │ │ - │ └── • scan buffer - │ label: buffer 1 + │ └── • scan + │ missing stats + │ table: uniq_partial_hidden_pk@uniq_partial_hidden_pk_pkey + │ spans: FULL SCAN │ └── • filter - │ filter: c > 0 + │ filter: x > 0 │ - └── • scan - missing stats - table: uniq_partial_hidden_pk@uniq_partial_hidden_pk_pkey - spans: FULL SCAN + └── • scan buffer + label: buffer 1 # Test that we use the partial index when available for the insert checks. query T @@ -1323,17 +1451,25 @@ vectorized: true │ │ render column3: column3 │ │ render column4: column4 │ │ -│ └── • values -│ columns: (column1, column2, column3, column4) -│ size: 4 columns, 2 rows -│ row 0, expr 0: 'us-west' -│ row 0, expr 1: 1 -│ row 0, expr 2: 1 -│ row 0, expr 3: 'foo' -│ row 1, expr 0: 'us-east' -│ row 1, expr 1: 2 -│ row 1, expr 2: 2 -│ row 1, expr 3: 'bar' +│ └── • render +│ │ columns: (column1, column2, column3, column4) +│ │ estimated row count: 2 +│ │ render column1: crdb_internal.assignment_cast(column1, NULL::public.region) +│ │ render column2: crdb_internal.assignment_cast(column2, NULL::INT8) +│ │ render column3: crdb_internal.assignment_cast(column3, NULL::INT8) +│ │ render column4: crdb_internal.assignment_cast(column4, NULL::STRING) +│ │ +│ └── • values +│ columns: (column1, column2, column3, column4) +│ size: 4 columns, 2 rows +│ row 0, expr 0: 'us-west' +│ row 0, expr 1: 1 +│ row 0, expr 2: 1 +│ row 0, expr 3: 'foo' +│ row 1, expr 0: 'us-east' +│ row 1, expr 1: 2 +│ row 1, expr 2: 2 +│ row 1, expr 3: 'bar' │ └── • constraint-check │ @@ -1349,17 +1485,17 @@ vectorized: true │ estimated row count: 1 │ └── • lookup join (semi) - │ columns: ("lookup_join_const_col_@13", column1, column2, column3, column4) + │ columns: ("lookup_join_const_col_@17", column1, column2, column3, column4) │ table: uniq_partial_enum@uniq_partial_enum_r_b_idx (partial index) - │ equality: (lookup_join_const_col_@13, column3) = (r,b) + │ equality: (lookup_join_const_col_@17, column3) = (r,b) │ pred: (column1 != r) OR (column2 != a) │ └── • cross join (inner) - │ columns: ("lookup_join_const_col_@13", column1, column2, column3, column4) + │ columns: ("lookup_join_const_col_@17", column1, column2, column3, column4) │ estimated row count: 6 │ ├── • values - │ columns: ("lookup_join_const_col_@13") + │ columns: ("lookup_join_const_col_@17") │ size: 1 column, 3 rows │ row 0, expr 0: 'us-east' │ row 1, expr 0: 'us-west' @@ -1420,31 +1556,45 @@ vectorized: true │ render column3: column3 │ render column4: column4 │ - └── • lookup join (anti) + └── • distinct │ columns: (column1, column2, column3, column4) │ estimated row count: 0 - │ table: uniq_partial_enum@uniq_partial_enum_r_b_idx (partial index) - │ lookup condition: (column3 = b) AND (r IN ('us-east', 'us-west', 'eu-west')) - │ pred: column4 IN ('bar', 'baz', 'foo') + │ distinct on: column1, column2 + │ nulls are distinct │ └── • lookup join (anti) │ columns: (column1, column2, column3, column4) │ estimated row count: 0 - │ table: uniq_partial_enum@uniq_partial_enum_pkey - │ equality: (column1, column2) = (r,a) - │ equality cols are key + │ table: uniq_partial_enum@uniq_partial_enum_r_b_idx (partial index) + │ lookup condition: (column3 = b) AND (r IN ('us-east', 'us-west', 'eu-west')) + │ pred: column4 IN ('bar', 'baz', 'foo') │ - └── • values - columns: (column1, column2, column3, column4) - size: 4 columns, 2 rows - row 0, expr 0: 'us-west' - row 0, expr 1: 1 - row 0, expr 2: 1 - row 0, expr 3: 'foo' - row 1, expr 0: 'us-east' - row 1, expr 1: 2 - row 1, expr 2: 2 - row 1, expr 3: 'bar' + └── • lookup join (anti) + │ columns: (column1, column2, column3, column4) + │ estimated row count: 0 + │ table: uniq_partial_enum@uniq_partial_enum_pkey + │ equality: (column1, column2) = (r,a) + │ equality cols are key + │ + └── • render + │ columns: (column1, column2, column3, column4) + │ estimated row count: 2 + │ render column1: crdb_internal.assignment_cast(column1, NULL::public.region) + │ render column2: crdb_internal.assignment_cast(column2, NULL::INT8) + │ render column3: crdb_internal.assignment_cast(column3, NULL::INT8) + │ render column4: crdb_internal.assignment_cast(column4, NULL::STRING) + │ + └── • values + columns: (column1, column2, column3, column4) + size: 4 columns, 2 rows + row 0, expr 0: 'us-west' + row 0, expr 1: 1 + row 0, expr 2: 1 + row 0, expr 3: 'foo' + row 1, expr 0: 'us-east' + row 1, expr 1: 2 + row 1, expr 2: 2 + row 1, expr 3: 'bar' # We can eliminate uniqueness checks for i and s due to functional dependencies. # We cannot eliminate checks for d, since functional dependencies could not be @@ -1466,8 +1616,11 @@ vectorized: true │ └── • render │ │ estimated row count: 2 │ │ -│ └── • values -│ size: 3 columns, 2 rows +│ └── • render +│ │ estimated row count: 2 +│ │ +│ └── • values +│ size: 3 columns, 2 rows │ └── • constraint-check │ @@ -1501,8 +1654,28 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 3 columns, 1 row +│ └── • render +│ │ estimated row count: 1 +│ │ +│ └── • values +│ size: 1 column, 1 row +│ +├── • constraint-check +│ │ +│ └── • error if rows +│ │ +│ └── • hash join (right semi) +│ │ equality: (id1) = (column1) +│ │ right cols are key +│ │ pred: rowid_default != rowid +│ │ +│ ├── • scan +│ │ missing stats +│ │ table: uniq_uuid@uniq_uuid_pkey +│ │ spans: FULL SCAN +│ │ +│ └── • scan buffer +│ label: buffer 1 │ └── • constraint-check │ @@ -1538,8 +1711,28 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 3 columns, 1 row +│ └── • render +│ │ estimated row count: 1 +│ │ +│ └── • values +│ size: 1 column, 1 row +│ +├── • constraint-check +│ │ +│ └── • error if rows +│ │ +│ └── • hash join (right semi) +│ │ equality: (id1) = (column1) +│ │ right cols are key +│ │ pred: rowid_default != rowid +│ │ +│ ├── • scan +│ │ missing stats +│ │ table: uniq_uuid@uniq_uuid_pkey +│ │ spans: FULL SCAN +│ │ +│ └── • scan buffer +│ label: buffer 1 │ └── • constraint-check │ @@ -1580,6 +1773,22 @@ vectorized: true │ table: other@other_pkey │ spans: FULL SCAN │ +├── • constraint-check +│ │ +│ └── • error if rows +│ │ +│ └── • hash join (semi) +│ │ equality: (gen_random_uuid) = (id1) +│ │ pred: rowid_default != rowid +│ │ +│ ├── • scan buffer +│ │ label: buffer 1 +│ │ +│ └── • scan +│ missing stats +│ table: uniq_uuid@uniq_uuid_pkey +│ spans: FULL SCAN +│ └── • constraint-check │ └── • error if rows @@ -1614,8 +1823,11 @@ vectorized: true │ └── • buffer │ │ label: buffer 1 │ │ -│ └── • values -│ size: 3 columns, 1 row +│ └── • render +│ │ estimated row count: 1 +│ │ +│ └── • values +│ size: 1 column, 1 row │ ├── • constraint-check │ │ diff --git a/pkg/sql/opt/exec/execbuilder/testdata/vectorize_local b/pkg/sql/opt/exec/execbuilder/testdata/vectorize_local index e55e92ad6fc6..563f6fd506cd 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/vectorize_local +++ b/pkg/sql/opt/exec/execbuilder/testdata/vectorize_local @@ -398,9 +398,9 @@ EXPLAIN (VEC) INSERT INTO t66568 VALUES (1) ON CONFLICT DO NOTHING │ └ Node 1 └ *sql.planNodeToRowSource - └ *colexecjoin.crossJoiner - ├ *sql.planNodeToRowSource - └ *colfetcher.ColBatchScan + └ *colexec.unorderedDistinct + └ *rowexec.joinReader + └ *sql.planNodeToRowSource statement ok CREATE TABLE t_string (a STRING); diff --git a/pkg/sql/opt/exec/execbuilder/testdata/virtual_columns b/pkg/sql/opt/exec/execbuilder/testdata/virtual_columns index 5aaa8493fdbe..a120db77201b 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/virtual_columns +++ b/pkg/sql/opt/exec/execbuilder/testdata/virtual_columns @@ -200,15 +200,24 @@ EXPLAIN (VERBOSE) INSERT INTO t VALUES (1, 1) distribution: local vectorized: true · -• insert fast path - columns: () - estimated row count: 0 (missing stats) - into: t(a, b, v) - auto commit - size: 3 columns, 1 row - row 0, expr 0: 1 - row 0, expr 1: 1 - row 0, expr 2: 2 +• insert +│ columns: () +│ estimated row count: 0 (missing stats) +│ into: t(a, b, v) +│ auto commit +│ +└── • render + │ columns: (column1, column2, v_comp) + │ estimated row count: 1 + │ render v_comp: column1 + column2 + │ render column1: column1 + │ render column2: column2 + │ + └── • values + columns: (column1, column2) + size: 2 columns, 1 row + row 0, expr 0: crdb_internal.assignment_cast(1, NULL::INT8) + row 0, expr 1: crdb_internal.assignment_cast(1, NULL::INT8) query T EXPLAIN (VERBOSE) INSERT INTO t VALUES (1, 1) RETURNING v @@ -220,15 +229,24 @@ vectorized: true │ columns: (v) │ estimated row count: 1 │ -└── • insert fast path - columns: (a, v) - estimated row count: 1 - into: t(a, b, v) - auto commit - size: 3 columns, 1 row - row 0, expr 0: 1 - row 0, expr 1: 1 - row 0, expr 2: 2 +└── • insert + │ columns: (a, v) + │ estimated row count: 1 + │ into: t(a, b, v) + │ auto commit + │ + └── • render + │ columns: (column1, column2, v_comp) + │ estimated row count: 1 + │ render v_comp: column1 + column2 + │ render column1: column1 + │ render column2: column2 + │ + └── • values + columns: (column1, column2) + size: 2 columns, 1 row + row 0, expr 0: crdb_internal.assignment_cast(1, NULL::INT8) + row 0, expr 1: crdb_internal.assignment_cast(1, NULL::INT8) query T EXPLAIN (VERBOSE) INSERT INTO t_idx VALUES (1, 1, 1) @@ -236,17 +254,27 @@ EXPLAIN (VERBOSE) INSERT INTO t_idx VALUES (1, 1, 1) distribution: local vectorized: true · -• insert fast path - columns: () - estimated row count: 0 (missing stats) - into: t_idx(a, b, c, v, w) - auto commit - size: 5 columns, 1 row - row 0, expr 0: 1 - row 0, expr 1: 1 - row 0, expr 2: 1 - row 0, expr 3: 2 - row 0, expr 4: 2 +• insert +│ columns: () +│ estimated row count: 0 (missing stats) +│ into: t_idx(a, b, c, v, w) +│ auto commit +│ +└── • render + │ columns: (column1, column2, column3, v_comp, w_comp) + │ estimated row count: 1 + │ render v_comp: column1 + column2 + │ render w_comp: column3 + 1 + │ render column1: column1 + │ render column2: column2 + │ render column3: column3 + │ + └── • values + columns: (column1, column2, column3) + size: 3 columns, 1 row + row 0, expr 0: crdb_internal.assignment_cast(1, NULL::INT8) + row 0, expr 1: crdb_internal.assignment_cast(1, NULL::INT8) + row 0, expr 2: crdb_internal.assignment_cast(1, NULL::INT8) subtest Delete @@ -812,27 +840,39 @@ vectorized: true │ auto commit │ arbiter indexes: t_pkey │ - └── • lookup join (anti) + └── • distinct │ columns: (column1, column2, v_comp) │ estimated row count: 0 (missing stats) - │ table: t@t_pkey - │ equality: (column1) = (a) - │ equality cols are key + │ distinct on: column1 + │ nulls are distinct │ - └── • render + └── • lookup join (anti) │ columns: (v_comp, column1, column2) - │ estimated row count: 2 - │ render v_comp: column1 + column2 - │ render column1: column1 - │ render column2: column2 + │ estimated row count: 0 (missing stats) + │ table: t@t_pkey + │ equality: (column1) = (a) + │ equality cols are key │ - └── • values - columns: (column1, column2) - size: 2 columns, 2 rows - row 0, expr 0: 5 - row 0, expr 1: 51 - row 1, expr 0: 6 - row 1, expr 1: 60 + └── • render + │ columns: (v_comp, column1, column2) + │ estimated row count: 2 + │ render v_comp: column1 + column2 + │ render column1: column1 + │ render column2: column2 + │ + └── • render + │ columns: (column1, column2) + │ estimated row count: 2 + │ render column1: crdb_internal.assignment_cast(column1, NULL::INT8) + │ render column2: crdb_internal.assignment_cast(column2, NULL::INT8) + │ + └── • values + columns: (column1, column2) + size: 2 columns, 2 rows + row 0, expr 0: 5 + row 0, expr 1: 51 + row 1, expr 0: 6 + row 1, expr 1: 60 query T EXPLAIN (VERBOSE) INSERT INTO t VALUES (4, 100), (6, 100), (7, 100) ON CONFLICT (a) DO UPDATE SET b = t.v @@ -1118,50 +1158,63 @@ vectorized: true │ distinct on: w_comp │ nulls are distinct │ - └── • lookup join (anti) + └── • distinct │ columns: (v_comp, w_comp, column1, column2, column3) │ estimated row count: 0 (missing stats) - │ table: t_idx@t_idx_pkey - │ equality: (column1) = (a) - │ equality cols are key + │ distinct on: column1 + │ nulls are distinct │ - └── • hash join (right anti) + └── • lookup join (anti) │ columns: (v_comp, w_comp, column1, column2, column3) │ estimated row count: 0 (missing stats) - │ equality: (w) = (w_comp) - │ - ├── • render - │ │ columns: (w) - │ │ estimated row count: 1,000 (missing stats) - │ │ render w: c + 1 - │ │ - │ └── • scan - │ columns: (c) - │ estimated row count: 1,000 (missing stats) - │ table: t_idx@t_idx_pkey - │ spans: FULL SCAN + │ table: t_idx@t_idx_pkey + │ equality: (column1) = (a) + │ equality cols are key │ - └── • render + └── • hash join (right anti) │ columns: (v_comp, w_comp, column1, column2, column3) - │ estimated row count: 3 - │ render v_comp: column1 + column2 - │ render w_comp: column3 + 1 - │ render column1: column1 - │ render column2: column2 - │ render column3: column3 + │ estimated row count: 0 (missing stats) + │ equality: (w) = (w_comp) │ - └── • values - columns: (column1, column2, column3) - size: 3 columns, 3 rows - row 0, expr 0: 4 - row 0, expr 1: 41 - row 0, expr 2: 301 - row 1, expr 0: 6 - row 1, expr 1: 60 - row 1, expr 2: 600 - row 2, expr 0: 7 - row 2, expr 1: 70 - row 2, expr 2: 100 + ├── • render + │ │ columns: (w) + │ │ estimated row count: 1,000 (missing stats) + │ │ render w: c + 1 + │ │ + │ └── • scan + │ columns: (c) + │ estimated row count: 1,000 (missing stats) + │ table: t_idx@t_idx_pkey + │ spans: FULL SCAN + │ + └── • render + │ columns: (v_comp, w_comp, column1, column2, column3) + │ estimated row count: 3 + │ render v_comp: column1 + column2 + │ render w_comp: column3 + 1 + │ render column1: column1 + │ render column2: column2 + │ render column3: column3 + │ + └── • render + │ columns: (column1, column2, column3) + │ estimated row count: 3 + │ render column1: crdb_internal.assignment_cast(column1, NULL::INT8) + │ render column2: crdb_internal.assignment_cast(column2, NULL::INT8) + │ render column3: crdb_internal.assignment_cast(column3, NULL::INT8) + │ + └── • values + columns: (column1, column2, column3) + size: 3 columns, 3 rows + row 0, expr 0: 4 + row 0, expr 1: 41 + row 0, expr 2: 301 + row 1, expr 0: 6 + row 1, expr 1: 60 + row 1, expr 2: 600 + row 2, expr 0: 7 + row 2, expr 1: 70 + row 2, expr 2: 100 query T EXPLAIN (VERBOSE) INSERT INTO t_idx VALUES (4, 10, 100), (6, 10, 100), (7, 70, 700) ON CONFLICT (a) DO UPDATE SET c = 0 diff --git a/pkg/sql/opt/exec/execbuilder/testdata/with b/pkg/sql/opt/exec/execbuilder/testdata/with index ddc40d991eee..4138a9e9a445 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/with +++ b/pkg/sql/opt/exec/execbuilder/testdata/with @@ -99,7 +99,7 @@ vectorized: true └── • values columns: (column1, rowid_default) size: 2 columns, 1 row - row 0, expr 0: 1 + row 0, expr 0: crdb_internal.assignment_cast(1, NULL::INT8) row 0, expr 1: unique_rowid() # Regression test for #39010. diff --git a/pkg/sql/opt/exec/explain/testdata/gists b/pkg/sql/opt/exec/explain/testdata/gists index 85f7091d8151..0c8212e262c7 100644 --- a/pkg/sql/opt/exec/explain/testdata/gists +++ b/pkg/sql/opt/exec/explain/testdata/gists @@ -625,25 +625,29 @@ explain(gist): gist-explain-roundtrip INSERT INTO abc SELECT * from abc ---- -hash: 16772965416642504445 -plan-gist: AgFuAgAHAAAAH24B +hash: 8314977196645465964 +plan-gist: AgFuAgAHAAAABwYfbgE= explain(shape): • insert │ into: abc(a, b, c) │ auto commit │ -└── • scan - missing stats - table: abc@abc_pkey - spans: FULL SCAN +└── • render + │ + └── • scan + missing stats + table: abc@abc_pkey + spans: FULL SCAN explain(gist): • insert │ into: abc() │ auto commit │ -└── • scan - table: abc@abc_pkey - spans: FULL SCAN +└── • render + │ + └── • scan + table: abc@abc_pkey + spans: FULL SCAN # ConstructUpdate gist-explain-roundtrip @@ -917,8 +921,8 @@ explain(gist): gist-explain-roundtrip SELECT * FROM [INSERT INTO abc SELECT a, b, c FROM abc RETURNING a] ORDER BY a ---- -hash: 15302623232936960462 -plan-gist: AgFuAgAHAAAAH24AMDERBgI= +hash: 7687402044975188737 +plan-gist: AgFuAgAHAAAABwYfbgAwMREGAg== explain(shape): • root │ @@ -939,10 +943,12 @@ explain(shape): └── • insert │ into: abc(a, b, c) │ - └── • scan - missing stats - table: abc@abc_pkey - spans: FULL SCAN + └── • render + │ + └── • scan + missing stats + table: abc@abc_pkey + spans: FULL SCAN explain(gist): • root │ @@ -962,9 +968,11 @@ explain(gist): └── • insert │ into: abc() │ - └── • scan - table: abc@abc_pkey - spans: FULL SCAN + └── • render + │ + └── • scan + table: abc@abc_pkey + spans: FULL SCAN # ConstructRecursiveCTE/recursiveCTEOp gist-explain-roundtrip diff --git a/pkg/sql/opt/memo/expr.go b/pkg/sql/opt/memo/expr.go index d52a526e0744..703704e999f2 100644 --- a/pkg/sql/opt/memo/expr.go +++ b/pkg/sql/opt/memo/expr.go @@ -888,7 +888,7 @@ func ExprIsNeverNull(e opt.ScalarExpr, notNullCols opt.ColSet) bool { } return ExprIsNeverNull(t.Input, notNullCols) && ExprIsNeverNull(t.OrElse, notNullCols) - case *CastExpr, *NotExpr, *RangeExpr: + case *CastExpr, *AssignmentCastExpr, *NotExpr, *RangeExpr: return ExprIsNeverNull(t.Child(0).(opt.ScalarExpr), notNullCols) case *AndExpr, *OrExpr, *GeExpr, *GtExpr, *NeExpr, *EqExpr, *LeExpr, *LtExpr, *LikeExpr, diff --git a/pkg/sql/opt/memo/testdata/logprops/insert b/pkg/sql/opt/memo/testdata/logprops/insert index 6511d4a9a936..0e8dc7f2cf5c 100644 --- a/pkg/sql/opt/memo/testdata/logprops/insert +++ b/pkg/sql/opt/memo/testdata/logprops/insert @@ -23,58 +23,66 @@ INSERT INTO abcde (a, b) SELECT y, y FROM xyz ORDER BY y, z LIMIT 10 insert abcde ├── columns: ├── insert-mapping: - │ ├── y:10 => a:1 - │ ├── y:10 => b:2 - │ ├── c_default:14 => c:3 - │ ├── d_comp:17 => d:4 - │ ├── rowid_default:15 => rowid:5 - │ └── e_default:16 => e:6 + │ ├── y:14 => a:1 + │ ├── y:15 => b:2 + │ ├── c_default:16 => c:3 + │ ├── d_comp:19 => d:4 + │ ├── rowid_default:17 => rowid:5 + │ └── e_default:18 => e:6 ├── cardinality: [0 - 0] ├── volatile, mutations └── project - ├── columns: d_comp:17(int!null) y:10(int!null) c_default:14(int!null) rowid_default:15(int) e_default:16(int) + ├── columns: d_comp:19(int!null) y:14(int!null) y:15(int!null) c_default:16(int!null) rowid_default:17(int) e_default:18(int) ├── cardinality: [0 - 10] ├── volatile - ├── fd: ()-->(14,16), (10)-->(17) - ├── prune: (10,14-17) - ├── interesting orderings: (+10 opt(14,16)) + ├── fd: ()-->(16,18), (15)-->(19) + ├── prune: (14-19) ├── project - │ ├── columns: c_default:14(int!null) rowid_default:15(int) e_default:16(int) y:10(int!null) + │ ├── columns: c_default:16(int!null) rowid_default:17(int) e_default:18(int) y:14(int!null) y:15(int!null) │ ├── cardinality: [0 - 10] │ ├── volatile - │ ├── fd: ()-->(14,16) - │ ├── prune: (10,14-16) - │ ├── interesting orderings: (+10 opt(14,16)) - │ ├── limit - │ │ ├── columns: y:10(int!null) z:11(float) - │ │ ├── internal-ordering: +10,+11 + │ ├── fd: ()-->(16,18) + │ ├── prune: (14-18) + │ ├── project + │ │ ├── columns: y:14(int!null) y:15(int!null) │ │ ├── cardinality: [0 - 10] - │ │ ├── interesting orderings: (+10,+11) - │ │ ├── sort - │ │ │ ├── columns: y:10(int!null) z:11(float) - │ │ │ ├── ordering: +10,+11 - │ │ │ ├── limit hint: 10.00 - │ │ │ ├── prune: (10,11) - │ │ │ └── project - │ │ │ ├── columns: y:10(int!null) z:11(float) - │ │ │ ├── prune: (10,11) - │ │ │ └── scan xyz - │ │ │ ├── columns: x:9(string!null) y:10(int!null) z:11(float) xyz.crdb_internal_mvcc_timestamp:12(decimal) xyz.tableoid:13(oid) - │ │ │ ├── key: (9) - │ │ │ ├── fd: (9)-->(10-13) - │ │ │ ├── prune: (9-13) - │ │ │ └── interesting orderings: (+9) - │ │ └── const: 10 [type=int] + │ │ ├── immutable + │ │ ├── prune: (14,15) + │ │ ├── limit + │ │ │ ├── columns: xyz.y:10(int!null) z:11(float) + │ │ │ ├── internal-ordering: +10,+11 + │ │ │ ├── cardinality: [0 - 10] + │ │ │ ├── interesting orderings: (+10,+11) + │ │ │ ├── sort + │ │ │ │ ├── columns: xyz.y:10(int!null) z:11(float) + │ │ │ │ ├── ordering: +10,+11 + │ │ │ │ ├── limit hint: 10.00 + │ │ │ │ ├── prune: (10,11) + │ │ │ │ └── project + │ │ │ │ ├── columns: xyz.y:10(int!null) z:11(float) + │ │ │ │ ├── prune: (10,11) + │ │ │ │ └── scan xyz + │ │ │ │ ├── columns: x:9(string!null) xyz.y:10(int!null) z:11(float) xyz.crdb_internal_mvcc_timestamp:12(decimal) xyz.tableoid:13(oid) + │ │ │ │ ├── key: (9) + │ │ │ │ ├── fd: (9)-->(10-13) + │ │ │ │ ├── prune: (9-13) + │ │ │ │ └── interesting orderings: (+9) + │ │ │ └── const: 10 [type=int] + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=y:14, type=int, outer=(10), immutable] + │ │ │ └── variable: xyz.y:10 [type=int] + │ │ └── assignment-cast: INT8 [as=y:15, type=int, outer=(10), immutable] + │ │ └── variable: xyz.y:10 [type=int] │ └── projections - │ ├── const: 10 [as=c_default:14, type=int] - │ ├── function: unique_rowid [as=rowid_default:15, type=int, volatile] - │ └── cast: INT8 [as=e_default:16, type=int, immutable] + │ ├── const: 10 [as=c_default:16, type=int] + │ ├── function: unique_rowid [as=rowid_default:17, type=int, volatile] + │ └── cast: INT8 [as=e_default:18, type=int, immutable] │ └── null [type=unknown] └── projections - └── plus [as=d_comp:17, type=int, outer=(10,14), immutable] + └── plus [as=d_comp:19, type=int, outer=(15,16), immutable] ├── plus [type=int] - │ ├── variable: y:10 [type=int] - │ └── variable: c_default:14 [type=int] + │ ├── variable: y:15 [type=int] + │ └── variable: c_default:16 [type=int] └── const: 1 [type=int] # Properties with RETURNING clause. @@ -85,64 +93,72 @@ project ├── columns: a:1(int!null) b:2(int!null) c:3(int!null) d:4(int!null) ├── cardinality: [0 - 10] ├── volatile, mutations - ├── fd: ()-->(3), (1)==(2), (2)==(1), (1)-->(4) + ├── fd: ()-->(3), (2)-->(4) ├── prune: (1-4) └── insert abcde ├── columns: a:1(int!null) b:2(int!null) c:3(int!null) d:4(int!null) rowid:5(int!null) ├── insert-mapping: - │ ├── y:10 => a:1 - │ ├── y:10 => b:2 - │ ├── c_default:14 => c:3 - │ ├── d_comp:17 => d:4 - │ ├── rowid_default:15 => rowid:5 - │ └── e_default:16 => e:6 + │ ├── y:14 => a:1 + │ ├── y:15 => b:2 + │ ├── c_default:16 => c:3 + │ ├── d_comp:19 => d:4 + │ ├── rowid_default:17 => rowid:5 + │ └── e_default:18 => e:6 ├── cardinality: [0 - 10] ├── volatile, mutations - ├── fd: ()-->(3), (1)==(2), (2)==(1), (1)-->(4) + ├── fd: ()-->(3), (2)-->(4) └── project - ├── columns: d_comp:17(int!null) y:10(int!null) c_default:14(int!null) rowid_default:15(int) e_default:16(int) + ├── columns: d_comp:19(int!null) y:14(int!null) y:15(int!null) c_default:16(int!null) rowid_default:17(int) e_default:18(int) ├── cardinality: [0 - 10] ├── volatile - ├── fd: ()-->(14,16), (10)-->(17) - ├── prune: (10,14-17) - ├── interesting orderings: (+10 opt(14,16)) + ├── fd: ()-->(16,18), (15)-->(19) + ├── prune: (14-19) ├── project - │ ├── columns: c_default:14(int!null) rowid_default:15(int) e_default:16(int) y:10(int!null) + │ ├── columns: c_default:16(int!null) rowid_default:17(int) e_default:18(int) y:14(int!null) y:15(int!null) │ ├── cardinality: [0 - 10] │ ├── volatile - │ ├── fd: ()-->(14,16) - │ ├── prune: (10,14-16) - │ ├── interesting orderings: (+10 opt(14,16)) - │ ├── limit - │ │ ├── columns: y:10(int!null) z:11(float) - │ │ ├── internal-ordering: +10,+11 + │ ├── fd: ()-->(16,18) + │ ├── prune: (14-18) + │ ├── project + │ │ ├── columns: y:14(int!null) y:15(int!null) │ │ ├── cardinality: [0 - 10] - │ │ ├── interesting orderings: (+10,+11) - │ │ ├── sort - │ │ │ ├── columns: y:10(int!null) z:11(float) - │ │ │ ├── ordering: +10,+11 - │ │ │ ├── limit hint: 10.00 - │ │ │ ├── prune: (10,11) - │ │ │ └── project - │ │ │ ├── columns: y:10(int!null) z:11(float) - │ │ │ ├── prune: (10,11) - │ │ │ └── scan xyz - │ │ │ ├── columns: x:9(string!null) y:10(int!null) z:11(float) xyz.crdb_internal_mvcc_timestamp:12(decimal) xyz.tableoid:13(oid) - │ │ │ ├── key: (9) - │ │ │ ├── fd: (9)-->(10-13) - │ │ │ ├── prune: (9-13) - │ │ │ └── interesting orderings: (+9) - │ │ └── const: 10 [type=int] + │ │ ├── immutable + │ │ ├── prune: (14,15) + │ │ ├── limit + │ │ │ ├── columns: xyz.y:10(int!null) z:11(float) + │ │ │ ├── internal-ordering: +10,+11 + │ │ │ ├── cardinality: [0 - 10] + │ │ │ ├── interesting orderings: (+10,+11) + │ │ │ ├── sort + │ │ │ │ ├── columns: xyz.y:10(int!null) z:11(float) + │ │ │ │ ├── ordering: +10,+11 + │ │ │ │ ├── limit hint: 10.00 + │ │ │ │ ├── prune: (10,11) + │ │ │ │ └── project + │ │ │ │ ├── columns: xyz.y:10(int!null) z:11(float) + │ │ │ │ ├── prune: (10,11) + │ │ │ │ └── scan xyz + │ │ │ │ ├── columns: x:9(string!null) xyz.y:10(int!null) z:11(float) xyz.crdb_internal_mvcc_timestamp:12(decimal) xyz.tableoid:13(oid) + │ │ │ │ ├── key: (9) + │ │ │ │ ├── fd: (9)-->(10-13) + │ │ │ │ ├── prune: (9-13) + │ │ │ │ └── interesting orderings: (+9) + │ │ │ └── const: 10 [type=int] + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=y:14, type=int, outer=(10), immutable] + │ │ │ └── variable: xyz.y:10 [type=int] + │ │ └── assignment-cast: INT8 [as=y:15, type=int, outer=(10), immutable] + │ │ └── variable: xyz.y:10 [type=int] │ └── projections - │ ├── const: 10 [as=c_default:14, type=int] - │ ├── function: unique_rowid [as=rowid_default:15, type=int, volatile] - │ └── cast: INT8 [as=e_default:16, type=int, immutable] + │ ├── const: 10 [as=c_default:16, type=int] + │ ├── function: unique_rowid [as=rowid_default:17, type=int, volatile] + │ └── cast: INT8 [as=e_default:18, type=int, immutable] │ └── null [type=unknown] └── projections - └── plus [as=d_comp:17, type=int, outer=(10,14), immutable] + └── plus [as=d_comp:19, type=int, outer=(15,16), immutable] ├── plus [type=int] - │ ├── variable: y:10 [type=int] - │ └── variable: c_default:14 [type=int] + │ ├── variable: y:15 [type=int] + │ └── variable: c_default:16 [type=int] └── const: 1 [type=int] # Properties with RETURNING clause. @@ -152,48 +168,57 @@ INSERT INTO abcde (a, b) SELECT y, y FROM xyz ORDER BY y, z RETURNING * project ├── columns: a:1(int!null) b:2(int!null) c:3(int!null) d:4(int!null) ├── volatile, mutations - ├── fd: ()-->(3), (1)==(2), (2)==(1), (1)-->(4) + ├── fd: ()-->(3), (2)-->(4) ├── prune: (1-4) └── insert abcde ├── columns: a:1(int!null) b:2(int!null) c:3(int!null) d:4(int!null) rowid:5(int!null) ├── insert-mapping: - │ ├── y:10 => a:1 - │ ├── y:10 => b:2 - │ ├── c_default:14 => c:3 - │ ├── d_comp:17 => d:4 - │ ├── rowid_default:15 => rowid:5 - │ └── e_default:16 => e:6 + │ ├── y:14 => a:1 + │ ├── y:15 => b:2 + │ ├── c_default:16 => c:3 + │ ├── d_comp:19 => d:4 + │ ├── rowid_default:17 => rowid:5 + │ └── e_default:18 => e:6 ├── volatile, mutations - ├── fd: ()-->(3), (1)==(2), (2)==(1), (1)-->(4) + ├── fd: ()-->(3), (2)-->(4) └── project - ├── columns: d_comp:17(int!null) y:10(int!null) c_default:14(int!null) rowid_default:15(int) e_default:16(int) + ├── columns: d_comp:19(int!null) y:14(int!null) y:15(int!null) c_default:16(int!null) rowid_default:17(int) e_default:18(int) ├── volatile - ├── fd: ()-->(14,16), (10)-->(17) - ├── prune: (10,14-17) + ├── fd: ()-->(16,18), (15)-->(19) + ├── prune: (14-19) ├── project - │ ├── columns: c_default:14(int!null) rowid_default:15(int) e_default:16(int) y:10(int!null) + │ ├── columns: c_default:16(int!null) rowid_default:17(int) e_default:18(int) y:14(int!null) y:15(int!null) │ ├── volatile - │ ├── fd: ()-->(14,16) - │ ├── prune: (10,14-16) + │ ├── fd: ()-->(16,18) + │ ├── prune: (14-18) │ ├── project - │ │ ├── columns: y:10(int!null) z:11(float) - │ │ ├── prune: (10,11) - │ │ └── scan xyz - │ │ ├── columns: x:9(string!null) y:10(int!null) z:11(float) xyz.crdb_internal_mvcc_timestamp:12(decimal) xyz.tableoid:13(oid) - │ │ ├── key: (9) - │ │ ├── fd: (9)-->(10-13) - │ │ ├── prune: (9-13) - │ │ └── interesting orderings: (+9) + │ │ ├── columns: y:14(int!null) y:15(int!null) + │ │ ├── immutable + │ │ ├── prune: (14,15) + │ │ ├── project + │ │ │ ├── columns: xyz.y:10(int!null) z:11(float) + │ │ │ ├── prune: (10,11) + │ │ │ └── scan xyz + │ │ │ ├── columns: x:9(string!null) xyz.y:10(int!null) z:11(float) xyz.crdb_internal_mvcc_timestamp:12(decimal) xyz.tableoid:13(oid) + │ │ │ ├── key: (9) + │ │ │ ├── fd: (9)-->(10-13) + │ │ │ ├── prune: (9-13) + │ │ │ └── interesting orderings: (+9) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=y:14, type=int, outer=(10), immutable] + │ │ │ └── variable: xyz.y:10 [type=int] + │ │ └── assignment-cast: INT8 [as=y:15, type=int, outer=(10), immutable] + │ │ └── variable: xyz.y:10 [type=int] │ └── projections - │ ├── const: 10 [as=c_default:14, type=int] - │ ├── function: unique_rowid [as=rowid_default:15, type=int, volatile] - │ └── cast: INT8 [as=e_default:16, type=int, immutable] + │ ├── const: 10 [as=c_default:16, type=int] + │ ├── function: unique_rowid [as=rowid_default:17, type=int, volatile] + │ └── cast: INT8 [as=e_default:18, type=int, immutable] │ └── null [type=unknown] └── projections - └── plus [as=d_comp:17, type=int, outer=(10,14), immutable] + └── plus [as=d_comp:19, type=int, outer=(15,16), immutable] ├── plus [type=int] - │ ├── variable: y:10 [type=int] - │ └── variable: c_default:14 [type=int] + │ ├── variable: y:15 [type=int] + │ └── variable: c_default:16 [type=int] └── const: 1 [type=int] # Input is cardinality 1 VALUES expression. @@ -203,49 +228,61 @@ INSERT INTO abcde (a, b) (VALUES (1, 2)) RETURNING *, rowid; insert abcde ├── columns: a:1(int!null) b:2(int!null) c:3(int!null) d:4(int!null) rowid:5(int!null) ├── insert-mapping: - │ ├── column1:9 => a:1 - │ ├── column2:10 => b:2 - │ ├── c_default:11 => c:3 - │ ├── d_comp:14 => d:4 - │ ├── rowid_default:12 => rowid:5 - │ └── e_default:13 => e:6 + │ ├── column1:11 => a:1 + │ ├── column2:12 => b:2 + │ ├── c_default:13 => c:3 + │ ├── d_comp:16 => d:4 + │ ├── rowid_default:14 => rowid:5 + │ └── e_default:15 => e:6 ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () ├── fd: ()-->(1-5) └── project - ├── columns: d_comp:14(int!null) column1:9(int!null) column2:10(int!null) c_default:11(int!null) rowid_default:12(int) e_default:13(int) + ├── columns: d_comp:16(int!null) column1:11(int!null) column2:12(int!null) c_default:13(int!null) rowid_default:14(int) e_default:15(int) ├── cardinality: [1 - 1] ├── volatile ├── key: () - ├── fd: ()-->(9-14) - ├── prune: (9-14) + ├── fd: ()-->(11-16) + ├── prune: (11-16) ├── project - │ ├── columns: c_default:11(int!null) rowid_default:12(int) e_default:13(int) column1:9(int!null) column2:10(int!null) + │ ├── columns: c_default:13(int!null) rowid_default:14(int) e_default:15(int) column1:11(int!null) column2:12(int!null) │ ├── cardinality: [1 - 1] │ ├── volatile │ ├── key: () - │ ├── fd: ()-->(9-13) - │ ├── prune: (9-13) - │ ├── values - │ │ ├── columns: column1:9(int!null) column2:10(int!null) + │ ├── fd: ()-->(11-15) + │ ├── prune: (11-15) + │ ├── project + │ │ ├── columns: column1:11(int!null) column2:12(int!null) │ │ ├── cardinality: [1 - 1] + │ │ ├── immutable │ │ ├── key: () - │ │ ├── fd: ()-->(9,10) - │ │ ├── prune: (9,10) - │ │ └── tuple [type=tuple{int, int}] - │ │ ├── const: 1 [type=int] - │ │ └── const: 2 [type=int] + │ │ ├── fd: ()-->(11,12) + │ │ ├── prune: (11,12) + │ │ ├── values + │ │ │ ├── columns: column1:9(int!null) column2:10(int!null) + │ │ │ ├── cardinality: [1 - 1] + │ │ │ ├── key: () + │ │ │ ├── fd: ()-->(9,10) + │ │ │ ├── prune: (9,10) + │ │ │ └── tuple [type=tuple{int, int}] + │ │ │ ├── const: 1 [type=int] + │ │ │ └── const: 2 [type=int] + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:11, type=int, outer=(9), immutable] + │ │ │ └── variable: column1:9 [type=int] + │ │ └── assignment-cast: INT8 [as=column2:12, type=int, outer=(10), immutable] + │ │ └── variable: column2:10 [type=int] │ └── projections - │ ├── const: 10 [as=c_default:11, type=int] - │ ├── function: unique_rowid [as=rowid_default:12, type=int, volatile] - │ └── cast: INT8 [as=e_default:13, type=int, immutable] + │ ├── const: 10 [as=c_default:13, type=int] + │ ├── function: unique_rowid [as=rowid_default:14, type=int, volatile] + │ └── cast: INT8 [as=e_default:15, type=int, immutable] │ └── null [type=unknown] └── projections - └── plus [as=d_comp:14, type=int, outer=(10,11), immutable] + └── plus [as=d_comp:16, type=int, outer=(12,13), immutable] ├── plus [type=int] - │ ├── variable: column2:10 [type=int] - │ └── variable: c_default:11 [type=int] + │ ├── variable: column2:12 [type=int] + │ └── variable: c_default:13 [type=int] └── const: 1 [type=int] # Filter FD set. @@ -260,58 +297,68 @@ project └── insert abcde ├── columns: a:1(int!null) b:2(int) c:3(int!null) d:4(int) rowid:5(int!null) ├── insert-mapping: - │ ├── y:10 => a:1 - │ ├── int8:14 => b:2 - │ ├── c_default:15 => c:3 - │ ├── d_comp:18 => d:4 - │ ├── rowid_default:16 => rowid:5 - │ └── e_default:17 => e:6 + │ ├── y:15 => a:1 + │ ├── int8:16 => b:2 + │ ├── c_default:17 => c:3 + │ ├── d_comp:20 => d:4 + │ ├── rowid_default:18 => rowid:5 + │ └── e_default:19 => e:6 ├── volatile, mutations ├── fd: ()-->(1,3), (2)-->(4) └── project - ├── columns: d_comp:18(int) y:10(int!null) int8:14(int) c_default:15(int!null) rowid_default:16(int) e_default:17(int) + ├── columns: d_comp:20(int) y:15(int!null) int8:16(int) c_default:17(int!null) rowid_default:18(int) e_default:19(int) ├── volatile - ├── fd: ()-->(10,15,17), (14)-->(18) - ├── prune: (10,14-18) + ├── fd: ()-->(15,17,19), (16)-->(20) + ├── prune: (15-20) ├── project - │ ├── columns: c_default:15(int!null) rowid_default:16(int) e_default:17(int) y:10(int!null) int8:14(int) + │ ├── columns: c_default:17(int!null) rowid_default:18(int) e_default:19(int) y:15(int!null) int8:16(int) │ ├── volatile - │ ├── fd: ()-->(10,15,17) - │ ├── prune: (10,14-17) + │ ├── fd: ()-->(15,17,19) + │ ├── prune: (15-19) │ ├── project - │ │ ├── columns: int8:14(int) y:10(int!null) + │ │ ├── columns: y:15(int!null) int8:16(int) │ │ ├── immutable - │ │ ├── fd: ()-->(10) - │ │ ├── prune: (10,14) - │ │ ├── select - │ │ │ ├── columns: x:9(string!null) y:10(int!null) z:11(float) xyz.crdb_internal_mvcc_timestamp:12(decimal) xyz.tableoid:13(oid) - │ │ │ ├── key: (9) - │ │ │ ├── fd: ()-->(10), (9)-->(11-13) - │ │ │ ├── prune: (9,11-13) - │ │ │ ├── interesting orderings: (+9 opt(10)) - │ │ │ ├── scan xyz - │ │ │ │ ├── columns: x:9(string!null) y:10(int!null) z:11(float) xyz.crdb_internal_mvcc_timestamp:12(decimal) xyz.tableoid:13(oid) + │ │ ├── fd: ()-->(15) + │ │ ├── prune: (15,16) + │ │ ├── project + │ │ │ ├── columns: int8:14(int) xyz.y:10(int!null) + │ │ │ ├── immutable + │ │ │ ├── fd: ()-->(10) + │ │ │ ├── prune: (10,14) + │ │ │ ├── select + │ │ │ │ ├── columns: x:9(string!null) xyz.y:10(int!null) z:11(float) xyz.crdb_internal_mvcc_timestamp:12(decimal) xyz.tableoid:13(oid) │ │ │ │ ├── key: (9) - │ │ │ │ ├── fd: (9)-->(10-13) - │ │ │ │ ├── prune: (9-13) - │ │ │ │ └── interesting orderings: (+9) - │ │ │ └── filters - │ │ │ └── eq [type=bool, outer=(10), constraints=(/10: [/1 - /1]; tight), fd=()-->(10)] - │ │ │ ├── variable: y:10 [type=int] - │ │ │ └── const: 1 [type=int] + │ │ │ │ ├── fd: ()-->(10), (9)-->(11-13) + │ │ │ │ ├── prune: (9,11-13) + │ │ │ │ ├── interesting orderings: (+9 opt(10)) + │ │ │ │ ├── scan xyz + │ │ │ │ │ ├── columns: x:9(string!null) xyz.y:10(int!null) z:11(float) xyz.crdb_internal_mvcc_timestamp:12(decimal) xyz.tableoid:13(oid) + │ │ │ │ │ ├── key: (9) + │ │ │ │ │ ├── fd: (9)-->(10-13) + │ │ │ │ │ ├── prune: (9-13) + │ │ │ │ │ └── interesting orderings: (+9) + │ │ │ │ └── filters + │ │ │ │ └── eq [type=bool, outer=(10), constraints=(/10: [/1 - /1]; tight), fd=()-->(10)] + │ │ │ │ ├── variable: xyz.y:10 [type=int] + │ │ │ │ └── const: 1 [type=int] + │ │ │ └── projections + │ │ │ └── cast: INT8 [as=int8:14, type=int, outer=(11), immutable] + │ │ │ └── plus [type=float] + │ │ │ ├── variable: z:11 [type=float] + │ │ │ └── const: 1.0 [type=float] │ │ └── projections - │ │ └── cast: INT8 [as=int8:14, type=int, outer=(11), immutable] - │ │ └── plus [type=float] - │ │ ├── variable: z:11 [type=float] - │ │ └── const: 1.0 [type=float] + │ │ ├── assignment-cast: INT8 [as=y:15, type=int, outer=(10), immutable] + │ │ │ └── variable: xyz.y:10 [type=int] + │ │ └── assignment-cast: INT8 [as=int8:16, type=int, outer=(14), immutable] + │ │ └── variable: int8:14 [type=int] │ └── projections - │ ├── const: 10 [as=c_default:15, type=int] - │ ├── function: unique_rowid [as=rowid_default:16, type=int, volatile] - │ └── cast: INT8 [as=e_default:17, type=int, immutable] + │ ├── const: 10 [as=c_default:17, type=int] + │ ├── function: unique_rowid [as=rowid_default:18, type=int, volatile] + │ └── cast: INT8 [as=e_default:19, type=int, immutable] │ └── null [type=unknown] └── projections - └── plus [as=d_comp:18, type=int, outer=(14,15), immutable] + └── plus [as=d_comp:20, type=int, outer=(16,17), immutable] ├── plus [type=int] - │ ├── variable: int8:14 [type=int] - │ └── variable: c_default:15 [type=int] + │ ├── variable: int8:16 [type=int] + │ └── variable: c_default:17 [type=int] └── const: 1 [type=int] diff --git a/pkg/sql/opt/memo/testdata/logprops/join b/pkg/sql/opt/memo/testdata/logprops/join index 1ed4d0a0f1f4..6f640d9ddf11 100644 --- a/pkg/sql/opt/memo/testdata/logprops/join +++ b/pkg/sql/opt/memo/testdata/logprops/join @@ -1711,49 +1711,51 @@ SELECT (SELECT m FROM ) FROM uv ---- with &1 - ├── columns: m:29(int) + ├── columns: m:31(int) ├── volatile, mutations - ├── prune: (29) + ├── prune: (31) ├── project - │ ├── columns: uv.u:6(int!null) uv.v:7(int!null) + │ ├── columns: uv.u:6(int) uv.v:7(int!null) │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () │ ├── fd: ()-->(6,7) │ ├── prune: (6,7) │ └── insert uv - │ ├── columns: uv.u:6(int!null) uv.v:7(int!null) rowid:8(int!null) + │ ├── columns: uv.u:6(int) uv.v:7(int!null) rowid:8(int!null) │ ├── insert-mapping: - │ │ ├── column1:11 => uv.u:6 - │ │ ├── column2:12 => uv.v:7 - │ │ └── rowid_default:13 => rowid:8 + │ │ ├── column1:13 => uv.u:6 + │ │ ├── column2:14 => uv.v:7 + │ │ └── rowid_default:15 => rowid:8 │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () │ ├── fd: ()-->(6-8) │ └── values - │ ├── columns: column1:11(int!null) column2:12(int!null) rowid_default:13(int) + │ ├── columns: column1:13(int) column2:14(int) rowid_default:15(int) │ ├── cardinality: [1 - 1] │ ├── volatile │ ├── key: () - │ ├── fd: ()-->(11-13) - │ ├── prune: (11-13) + │ ├── fd: ()-->(13-15) + │ ├── prune: (13-15) │ └── tuple [type=tuple{int, int, int}] - │ ├── const: 1 [type=int] - │ ├── const: 2 [type=int] + │ ├── assignment-cast: INT8 [type=int] + │ │ └── const: 1 [type=int] + │ ├── assignment-cast: INT8 [type=int] + │ │ └── const: 2 [type=int] │ └── function: unique_rowid [type=int] └── project - ├── columns: m:29(int) - ├── prune: (29) + ├── columns: m:31(int) + ├── prune: (31) ├── scan uv └── projections - └── subquery [as=m:29, type=int, subquery] + └── subquery [as=m:31, type=int, subquery] └── values - ├── columns: mn.m:21(int!null) + ├── columns: mn.m:23(int!null) ├── cardinality: [0 - 0] ├── key: () - ├── fd: ()-->(21) - └── prune: (21) + ├── fd: ()-->(23) + └── prune: (23) # Regression test #40456. opt diff --git a/pkg/sql/opt/memo/testdata/logprops/upsert b/pkg/sql/opt/memo/testdata/logprops/upsert index e3d83f1ce2c1..2ac1b828b3f9 100644 --- a/pkg/sql/opt/memo/testdata/logprops/upsert +++ b/pkg/sql/opt/memo/testdata/logprops/upsert @@ -217,163 +217,162 @@ project ├── columns: a:1(int!null) b:2(int) c:3(int) ├── volatile, mutations ├── key: (1) - ├── fd: (1)-->(2,3), (2)-->(3), (2,3)~~>(1) + ├── fd: (2)-->(3), (1)-->(2,3), (2,3)~~>(1) ├── prune: (1-3) └── insert abc ├── columns: a:1(int!null) b:2(int) c:3(int) rowid:4(int!null) ├── arbiter indexes: abc_pkey abc_a_key abc_b_c_key ├── insert-mapping: - │ ├── x:7 => a:1 - │ ├── y:8 => b:2 - │ ├── c_comp:13 => c:3 - │ └── rowid_default:12 => rowid:4 + │ ├── x:12 => a:1 + │ ├── y:13 => b:2 + │ ├── c_comp:15 => c:3 + │ └── rowid_default:14 => rowid:4 ├── volatile, mutations ├── key: (1) - ├── fd: (1)-->(2-4), (2)-->(3), (4)~~>(1-3), (2,3)~~>(1,4) + ├── fd: (2)-->(3), (4)~~>(1-3), (1)-->(2-4), (2,3)~~>(1,4) └── upsert-distinct-on - ├── columns: x:7(int!null) y:8(int) rowid_default:12(int) c_comp:13(int) - ├── grouping columns: y:8(int) c_comp:13(int) + ├── columns: x:12(int!null) y:13(int) rowid_default:14(int) c_comp:15(int) + ├── grouping columns: y:13(int) c_comp:15(int) ├── volatile - ├── key: (7) - ├── fd: (7)-->(8,12,13), (8)-->(13), (12)~~>(7,8,13), (8,13)~~>(7,12) + ├── key: (12) + ├── fd: (13)-->(15), (14)~~>(12,13,15), (12)-->(13-15), (13,15)~~>(12,14) ├── upsert-distinct-on - │ ├── columns: x:7(int!null) y:8(int) rowid_default:12(int) c_comp:13(int) - │ ├── grouping columns: x:7(int!null) + │ ├── columns: x:12(int!null) y:13(int) rowid_default:14(int) c_comp:15(int) + │ ├── grouping columns: x:12(int!null) │ ├── volatile - │ ├── key: (7) - │ ├── fd: (7)-->(8,12,13), (8)-->(13), (12)~~>(7,8,13) + │ ├── key: (12) + │ ├── fd: (13)-->(15), (14)~~>(12,13,15), (12)-->(13-15) │ ├── upsert-distinct-on - │ │ ├── columns: x:7(int!null) y:8(int) rowid_default:12(int) c_comp:13(int) - │ │ ├── grouping columns: rowid_default:12(int) + │ │ ├── columns: x:12(int!null) y:13(int) rowid_default:14(int) c_comp:15(int) + │ │ ├── grouping columns: rowid_default:14(int) │ │ ├── volatile - │ │ ├── key: (7) - │ │ ├── fd: (7)-->(8,12), (8)-->(13), (12)~~>(7,8,13) + │ │ ├── lax-key: (14) + │ │ ├── fd: (13)-->(15), (14)~~>(12,13,15) │ │ ├── anti-join (hash) - │ │ │ ├── columns: x:7(int!null) y:8(int) rowid_default:12(int) c_comp:13(int) + │ │ │ ├── columns: x:12(int!null) y:13(int) rowid_default:14(int) c_comp:15(int) │ │ │ ├── volatile - │ │ │ ├── key: (7) - │ │ │ ├── fd: (7)-->(8,12), (8)-->(13) - │ │ │ ├── interesting orderings: (+7) (+8) + │ │ │ ├── fd: (13)-->(15) │ │ │ ├── anti-join (hash) - │ │ │ │ ├── columns: x:7(int!null) y:8(int) rowid_default:12(int) c_comp:13(int) + │ │ │ │ ├── columns: x:12(int!null) y:13(int) rowid_default:14(int) c_comp:15(int) │ │ │ │ ├── volatile - │ │ │ │ ├── key: (7) - │ │ │ │ ├── fd: (7)-->(8,12), (8)-->(13) - │ │ │ │ ├── prune: (8,13) - │ │ │ │ ├── interesting orderings: (+7) (+8) + │ │ │ │ ├── fd: (13)-->(15) + │ │ │ │ ├── prune: (13,15) │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ ├── columns: x:7(int!null) y:8(int) rowid_default:12(int) c_comp:13(int) + │ │ │ │ │ ├── columns: x:12(int!null) y:13(int) rowid_default:14(int) c_comp:15(int) │ │ │ │ │ ├── volatile - │ │ │ │ │ ├── key: (7) - │ │ │ │ │ ├── fd: (7)-->(8,12), (8)-->(13) - │ │ │ │ │ ├── prune: (7,8,13) - │ │ │ │ │ ├── interesting orderings: (+7) (+8) + │ │ │ │ │ ├── fd: (13)-->(15) + │ │ │ │ │ ├── prune: (12,13,15) │ │ │ │ │ ├── project - │ │ │ │ │ │ ├── columns: c_comp:13(int) x:7(int!null) y:8(int) rowid_default:12(int) + │ │ │ │ │ │ ├── columns: c_comp:15(int) x:12(int!null) y:13(int) rowid_default:14(int) │ │ │ │ │ │ ├── volatile - │ │ │ │ │ │ ├── key: (7) - │ │ │ │ │ │ ├── fd: (7)-->(8,12), (8)-->(13) - │ │ │ │ │ │ ├── prune: (7,8,12,13) - │ │ │ │ │ │ ├── interesting orderings: (+7) (+8) + │ │ │ │ │ │ ├── fd: (13)-->(15) + │ │ │ │ │ │ ├── prune: (12-15) │ │ │ │ │ │ ├── unfiltered-cols: (7-11) │ │ │ │ │ │ ├── project - │ │ │ │ │ │ │ ├── columns: rowid_default:12(int) x:7(int!null) y:8(int) + │ │ │ │ │ │ │ ├── columns: rowid_default:14(int) x:12(int!null) y:13(int) │ │ │ │ │ │ │ ├── volatile - │ │ │ │ │ │ │ ├── key: (7) - │ │ │ │ │ │ │ ├── fd: (7)-->(8,12) - │ │ │ │ │ │ │ ├── prune: (7,8,12) - │ │ │ │ │ │ │ ├── interesting orderings: (+7) (+8) + │ │ │ │ │ │ │ ├── prune: (12-14) │ │ │ │ │ │ │ ├── unfiltered-cols: (7-11) │ │ │ │ │ │ │ ├── project - │ │ │ │ │ │ │ │ ├── columns: x:7(int!null) y:8(int) - │ │ │ │ │ │ │ │ ├── key: (7) - │ │ │ │ │ │ │ │ ├── fd: (7)-->(8) - │ │ │ │ │ │ │ │ ├── prune: (7,8) - │ │ │ │ │ │ │ │ ├── interesting orderings: (+7) (+8) + │ │ │ │ │ │ │ │ ├── columns: x:12(int!null) y:13(int) + │ │ │ │ │ │ │ │ ├── immutable + │ │ │ │ │ │ │ │ ├── prune: (12,13) │ │ │ │ │ │ │ │ ├── unfiltered-cols: (7-11) - │ │ │ │ │ │ │ │ └── scan xyz - │ │ │ │ │ │ │ │ ├── columns: x:7(int!null) y:8(int) z:9(int) xyz.crdb_internal_mvcc_timestamp:10(decimal) xyz.tableoid:11(oid) - │ │ │ │ │ │ │ │ ├── key: (7) - │ │ │ │ │ │ │ │ ├── fd: (7)-->(8-11), (8,9)~~>(7,10,11) - │ │ │ │ │ │ │ │ ├── prune: (7-11) - │ │ │ │ │ │ │ │ ├── interesting orderings: (+7) (+8,+9,+7) (+9,+8,+7) - │ │ │ │ │ │ │ │ └── unfiltered-cols: (7-11) + │ │ │ │ │ │ │ │ ├── project + │ │ │ │ │ │ │ │ │ ├── columns: xyz.x:7(int!null) xyz.y:8(int) + │ │ │ │ │ │ │ │ │ ├── key: (7) + │ │ │ │ │ │ │ │ │ ├── fd: (7)-->(8) + │ │ │ │ │ │ │ │ │ ├── prune: (7,8) + │ │ │ │ │ │ │ │ │ ├── interesting orderings: (+7) (+8) + │ │ │ │ │ │ │ │ │ ├── unfiltered-cols: (7-11) + │ │ │ │ │ │ │ │ │ └── scan xyz + │ │ │ │ │ │ │ │ │ ├── columns: xyz.x:7(int!null) xyz.y:8(int) z:9(int) xyz.crdb_internal_mvcc_timestamp:10(decimal) xyz.tableoid:11(oid) + │ │ │ │ │ │ │ │ │ ├── key: (7) + │ │ │ │ │ │ │ │ │ ├── fd: (7)-->(8-11), (8,9)~~>(7,10,11) + │ │ │ │ │ │ │ │ │ ├── prune: (7-11) + │ │ │ │ │ │ │ │ │ ├── interesting orderings: (+7) (+8,+9,+7) (+9,+8,+7) + │ │ │ │ │ │ │ │ │ └── unfiltered-cols: (7-11) + │ │ │ │ │ │ │ │ └── projections + │ │ │ │ │ │ │ │ ├── assignment-cast: INT8 [as=x:12, type=int, outer=(7), immutable] + │ │ │ │ │ │ │ │ │ └── variable: xyz.x:7 [type=int] + │ │ │ │ │ │ │ │ └── assignment-cast: INT8 [as=y:13, type=int, outer=(8), immutable] + │ │ │ │ │ │ │ │ └── variable: xyz.y:8 [type=int] │ │ │ │ │ │ │ └── projections - │ │ │ │ │ │ │ └── function: unique_rowid [as=rowid_default:12, type=int, volatile] + │ │ │ │ │ │ │ └── function: unique_rowid [as=rowid_default:14, type=int, volatile] │ │ │ │ │ │ └── projections - │ │ │ │ │ │ └── plus [as=c_comp:13, type=int, outer=(8), immutable] - │ │ │ │ │ │ ├── variable: y:8 [type=int] + │ │ │ │ │ │ └── plus [as=c_comp:15, type=int, outer=(13), immutable] + │ │ │ │ │ │ ├── variable: y:13 [type=int] │ │ │ │ │ │ └── const: 1 [type=int] │ │ │ │ │ ├── scan abc - │ │ │ │ │ │ ├── columns: a:14(int!null) b:15(int) c:16(int) rowid:17(int!null) + │ │ │ │ │ │ ├── columns: a:16(int!null) b:17(int) c:18(int) rowid:19(int!null) │ │ │ │ │ │ ├── computed column expressions - │ │ │ │ │ │ │ └── c:16 + │ │ │ │ │ │ │ └── c:18 │ │ │ │ │ │ │ └── plus [type=int] - │ │ │ │ │ │ │ ├── variable: b:15 [type=int] + │ │ │ │ │ │ │ ├── variable: b:17 [type=int] │ │ │ │ │ │ │ └── const: 1 [type=int] - │ │ │ │ │ │ ├── key: (17) - │ │ │ │ │ │ ├── fd: (17)-->(14-16), (14)-->(15-17), (15,16)~~>(14,17), (15)-->(16) - │ │ │ │ │ │ ├── prune: (14-17) - │ │ │ │ │ │ ├── interesting orderings: (+17) (+14) (+15,+17) - │ │ │ │ │ │ └── unfiltered-cols: (14-19) + │ │ │ │ │ │ ├── key: (19) + │ │ │ │ │ │ ├── fd: (19)-->(16-18), (16)-->(17-19), (17,18)~~>(16,19), (17)-->(18) + │ │ │ │ │ │ ├── prune: (16-19) + │ │ │ │ │ │ ├── interesting orderings: (+19) (+16) (+17,+19) + │ │ │ │ │ │ └── unfiltered-cols: (16-21) │ │ │ │ │ └── filters - │ │ │ │ │ └── eq [type=bool, outer=(12,17), constraints=(/12: (/NULL - ]; /17: (/NULL - ]), fd=(12)==(17), (17)==(12)] - │ │ │ │ │ ├── variable: rowid_default:12 [type=int] - │ │ │ │ │ └── variable: rowid:17 [type=int] + │ │ │ │ │ └── eq [type=bool, outer=(14,19), constraints=(/14: (/NULL - ]; /19: (/NULL - ]), fd=(14)==(19), (19)==(14)] + │ │ │ │ │ ├── variable: rowid_default:14 [type=int] + │ │ │ │ │ └── variable: rowid:19 [type=int] │ │ │ │ ├── scan abc - │ │ │ │ │ ├── columns: a:20(int!null) b:21(int) c:22(int) rowid:23(int!null) + │ │ │ │ │ ├── columns: a:22(int!null) b:23(int) c:24(int) rowid:25(int!null) │ │ │ │ │ ├── computed column expressions - │ │ │ │ │ │ └── c:22 + │ │ │ │ │ │ └── c:24 │ │ │ │ │ │ └── plus [type=int] - │ │ │ │ │ │ ├── variable: b:21 [type=int] + │ │ │ │ │ │ ├── variable: b:23 [type=int] │ │ │ │ │ │ └── const: 1 [type=int] - │ │ │ │ │ ├── key: (23) - │ │ │ │ │ ├── fd: (23)-->(20-22), (20)-->(21-23), (21,22)~~>(20,23), (21)-->(22) - │ │ │ │ │ ├── prune: (20-23) - │ │ │ │ │ ├── interesting orderings: (+23) (+20) (+21,+23) - │ │ │ │ │ └── unfiltered-cols: (20-25) + │ │ │ │ │ ├── key: (25) + │ │ │ │ │ ├── fd: (25)-->(22-24), (22)-->(23-25), (23,24)~~>(22,25), (23)-->(24) + │ │ │ │ │ ├── prune: (22-25) + │ │ │ │ │ ├── interesting orderings: (+25) (+22) (+23,+25) + │ │ │ │ │ └── unfiltered-cols: (22-27) │ │ │ │ └── filters - │ │ │ │ └── eq [type=bool, outer=(7,20), constraints=(/7: (/NULL - ]; /20: (/NULL - ]), fd=(7)==(20), (20)==(7)] - │ │ │ │ ├── variable: x:7 [type=int] - │ │ │ │ └── variable: a:20 [type=int] + │ │ │ │ └── eq [type=bool, outer=(12,22), constraints=(/12: (/NULL - ]; /22: (/NULL - ]), fd=(12)==(22), (22)==(12)] + │ │ │ │ ├── variable: x:12 [type=int] + │ │ │ │ └── variable: a:22 [type=int] │ │ │ ├── scan abc - │ │ │ │ ├── columns: a:26(int!null) b:27(int) c:28(int) rowid:29(int!null) + │ │ │ │ ├── columns: a:28(int!null) b:29(int) c:30(int) rowid:31(int!null) │ │ │ │ ├── computed column expressions - │ │ │ │ │ └── c:28 + │ │ │ │ │ └── c:30 │ │ │ │ │ └── plus [type=int] - │ │ │ │ │ ├── variable: b:27 [type=int] + │ │ │ │ │ ├── variable: b:29 [type=int] │ │ │ │ │ └── const: 1 [type=int] - │ │ │ │ ├── key: (29) - │ │ │ │ ├── fd: (29)-->(26-28), (26)-->(27-29), (27,28)~~>(26,29), (27)-->(28) - │ │ │ │ ├── prune: (26-29) - │ │ │ │ ├── interesting orderings: (+29) (+26) (+27,+29) - │ │ │ │ └── unfiltered-cols: (26-31) + │ │ │ │ ├── key: (31) + │ │ │ │ ├── fd: (31)-->(28-30), (28)-->(29-31), (29,30)~~>(28,31), (29)-->(30) + │ │ │ │ ├── prune: (28-31) + │ │ │ │ ├── interesting orderings: (+31) (+28) (+29,+31) + │ │ │ │ └── unfiltered-cols: (28-33) │ │ │ └── filters - │ │ │ ├── eq [type=bool, outer=(8,27), constraints=(/8: (/NULL - ]; /27: (/NULL - ]), fd=(8)==(27), (27)==(8)] - │ │ │ │ ├── variable: y:8 [type=int] - │ │ │ │ └── variable: b:27 [type=int] - │ │ │ └── eq [type=bool, outer=(13,28), constraints=(/13: (/NULL - ]; /28: (/NULL - ]), fd=(13)==(28), (28)==(13)] - │ │ │ ├── variable: c_comp:13 [type=int] - │ │ │ └── variable: c:28 [type=int] + │ │ │ ├── eq [type=bool, outer=(13,29), constraints=(/13: (/NULL - ]; /29: (/NULL - ]), fd=(13)==(29), (29)==(13)] + │ │ │ │ ├── variable: y:13 [type=int] + │ │ │ │ └── variable: b:29 [type=int] + │ │ │ └── eq [type=bool, outer=(15,30), constraints=(/15: (/NULL - ]; /30: (/NULL - ]), fd=(15)==(30), (30)==(15)] + │ │ │ ├── variable: c_comp:15 [type=int] + │ │ │ └── variable: c:30 [type=int] │ │ └── aggregations - │ │ ├── first-agg [as=x:7, type=int, outer=(7)] - │ │ │ └── variable: x:7 [type=int] - │ │ ├── first-agg [as=y:8, type=int, outer=(8)] - │ │ │ └── variable: y:8 [type=int] - │ │ └── first-agg [as=c_comp:13, type=int, outer=(13)] - │ │ └── variable: c_comp:13 [type=int] + │ │ ├── first-agg [as=x:12, type=int, outer=(12)] + │ │ │ └── variable: x:12 [type=int] + │ │ ├── first-agg [as=y:13, type=int, outer=(13)] + │ │ │ └── variable: y:13 [type=int] + │ │ └── first-agg [as=c_comp:15, type=int, outer=(15)] + │ │ └── variable: c_comp:15 [type=int] │ └── aggregations - │ ├── first-agg [as=y:8, type=int, outer=(8)] - │ │ └── variable: y:8 [type=int] - │ ├── first-agg [as=rowid_default:12, type=int, outer=(12)] - │ │ └── variable: rowid_default:12 [type=int] - │ └── first-agg [as=c_comp:13, type=int, outer=(13)] - │ └── variable: c_comp:13 [type=int] + │ ├── first-agg [as=y:13, type=int, outer=(13)] + │ │ └── variable: y:13 [type=int] + │ ├── first-agg [as=rowid_default:14, type=int, outer=(14)] + │ │ └── variable: rowid_default:14 [type=int] + │ └── first-agg [as=c_comp:15, type=int, outer=(15)] + │ └── variable: c_comp:15 [type=int] └── aggregations - ├── first-agg [as=x:7, type=int, outer=(7)] - │ └── variable: x:7 [type=int] - └── first-agg [as=rowid_default:12, type=int, outer=(12)] - └── variable: rowid_default:12 [type=int] + ├── first-agg [as=x:12, type=int, outer=(12)] + │ └── variable: x:12 [type=int] + └── first-agg [as=rowid_default:14, type=int, outer=(14)] + └── variable: rowid_default:14 [type=int] # UPSERT case. build diff --git a/pkg/sql/opt/memo/testdata/stats/insert b/pkg/sql/opt/memo/testdata/stats/insert index 0ddb3ed28570..1446d0304200 100644 --- a/pkg/sql/opt/memo/testdata/stats/insert +++ b/pkg/sql/opt/memo/testdata/stats/insert @@ -39,52 +39,64 @@ FROM [INSERT INTO xyz (x, y, z) SELECT b, a, c FROM abc WHERE b='foo' RETURNING WHERE z > 1.0 ---- with &1 - ├── columns: x:12(string!null) y:13(int!null) z:14(float!null) + ├── columns: x:15(string!null) y:16(int!null) z:17(float!null) ├── volatile, mutations - ├── stats: [rows=66.5105818, distinct(14)=43.4214373, null(14)=0] - ├── fd: ()-->(12), (13)-->(14) + ├── stats: [rows=66.6666667, distinct(17)=43.4214373, null(17)=0] + ├── fd: ()-->(15) ├── insert xyz │ ├── columns: xyz.x:1(string!null) xyz.y:2(int!null) xyz.z:3(float) │ ├── insert-mapping: - │ │ ├── b:7 => xyz.x:1 - │ │ ├── a:6 => xyz.y:2 - │ │ └── c:8 => xyz.z:3 + │ │ ├── b:12 => xyz.x:1 + │ │ ├── a:13 => xyz.y:2 + │ │ └── c:14 => xyz.z:3 │ ├── volatile, mutations - │ ├── stats: [rows=200, distinct(1)=1, null(1)=0, distinct(2)=200, null(2)=0, distinct(3)=130.264312, null(3)=2] - │ ├── fd: ()-->(1), (2)-->(3) + │ ├── stats: [rows=200, distinct(1)=1, null(1)=0, distinct(2)=200, null(2)=0, distinct(3)=130.264312, null(3)=0] + │ ├── fd: ()-->(1) │ └── project - │ ├── columns: a:6(int!null) b:7(string!null) c:8(float) - │ ├── stats: [rows=200, distinct(6)=200, null(6)=0, distinct(7)=1, null(7)=0, distinct(8)=130.264312, null(8)=2] - │ ├── fd: ()-->(7), (6)-->(8) - │ └── select - │ ├── columns: a:6(int!null) b:7(string!null) c:8(float) rowid:9(int!null) abc.crdb_internal_mvcc_timestamp:10(decimal) abc.tableoid:11(oid) - │ ├── stats: [rows=200, distinct(6)=200, null(6)=0, distinct(7)=1, null(7)=0, distinct(8)=130.264312, null(8)=2] - │ ├── key: (9) - │ ├── fd: ()-->(7), (9)-->(6,8,10,11), (6)-->(8) - │ ├── scan abc - │ │ ├── columns: a:6(int!null) b:7(string) c:8(float) rowid:9(int!null) abc.crdb_internal_mvcc_timestamp:10(decimal) abc.tableoid:11(oid) - │ │ ├── computed column expressions - │ │ │ └── c:8 - │ │ │ └── a:6::FLOAT8 [type=float] - │ │ ├── stats: [rows=2000, distinct(6)=2000, null(6)=0, distinct(7)=10, null(7)=0, distinct(8)=200, null(8)=20, distinct(9)=2000, null(9)=0] - │ │ ├── key: (9) - │ │ └── fd: (9)-->(6-8,10,11), (6)-->(8) - │ └── filters - │ └── b:7 = 'foo' [type=bool, outer=(7), constraints=(/7: [/'foo' - /'foo']; tight), fd=()-->(7)] + │ ├── columns: b:12(string!null) a:13(int!null) c:14(float) + │ ├── immutable + │ ├── stats: [rows=200, distinct(12)=1, null(12)=0, distinct(13)=200, null(13)=0, distinct(14)=130.264312, null(14)=0] + │ ├── fd: ()-->(12) + │ ├── project + │ │ ├── columns: abc.a:6(int!null) abc.b:7(string!null) abc.c:8(float) + │ │ ├── stats: [rows=200, distinct(6)=200, null(6)=0, distinct(7)=1, null(7)=0, distinct(8)=130.264312, null(8)=2] + │ │ ├── fd: ()-->(7), (6)-->(8) + │ │ └── select + │ │ ├── columns: abc.a:6(int!null) abc.b:7(string!null) abc.c:8(float) rowid:9(int!null) abc.crdb_internal_mvcc_timestamp:10(decimal) abc.tableoid:11(oid) + │ │ ├── stats: [rows=200, distinct(6)=200, null(6)=0, distinct(7)=1, null(7)=0, distinct(8)=130.264312, null(8)=2] + │ │ ├── key: (9) + │ │ ├── fd: ()-->(7), (9)-->(6,8,10,11), (6)-->(8) + │ │ ├── scan abc + │ │ │ ├── columns: abc.a:6(int!null) abc.b:7(string) abc.c:8(float) rowid:9(int!null) abc.crdb_internal_mvcc_timestamp:10(decimal) abc.tableoid:11(oid) + │ │ │ ├── computed column expressions + │ │ │ │ └── abc.c:8 + │ │ │ │ └── abc.a:6::FLOAT8 [type=float] + │ │ │ ├── stats: [rows=2000, distinct(6)=2000, null(6)=0, distinct(7)=10, null(7)=0, distinct(8)=200, null(8)=20, distinct(9)=2000, null(9)=0] + │ │ │ ├── key: (9) + │ │ │ └── fd: (9)-->(6-8,10,11), (6)-->(8) + │ │ └── filters + │ │ └── abc.b:7 = 'foo' [type=bool, outer=(7), constraints=(/7: [/'foo' - /'foo']; tight), fd=()-->(7)] + │ └── projections + │ ├── assignment-cast: STRING [as=b:12, type=string, outer=(7), immutable] + │ │ └── abc.b:7 [type=string] + │ ├── assignment-cast: INT8 [as=a:13, type=int, outer=(6), immutable] + │ │ └── abc.a:6 [type=int] + │ └── assignment-cast: FLOAT8 [as=c:14, type=float, outer=(8), immutable] + │ └── abc.c:8 [type=float] └── select - ├── columns: x:12(string!null) y:13(int!null) z:14(float!null) - ├── stats: [rows=66.5105818, distinct(14)=43.4214373, null(14)=0] - ├── fd: ()-->(12), (13)-->(14) + ├── columns: x:15(string!null) y:16(int!null) z:17(float!null) + ├── stats: [rows=66.6666667, distinct(17)=43.4214373, null(17)=0] + ├── fd: ()-->(15) ├── with-scan &1 - │ ├── columns: x:12(string!null) y:13(int!null) z:14(float) + │ ├── columns: x:15(string!null) y:16(int!null) z:17(float) │ ├── mapping: - │ │ ├── xyz.x:1(string) => x:12(string) - │ │ ├── xyz.y:2(int) => y:13(int) - │ │ └── xyz.z:3(float) => z:14(float) - │ ├── stats: [rows=200, distinct(12)=1, null(12)=0, distinct(13)=200, null(13)=0, distinct(14)=130.264312, null(14)=2] - │ └── fd: ()-->(12), (13)-->(14) + │ │ ├── xyz.x:1(string) => x:15(string) + │ │ ├── xyz.y:2(int) => y:16(int) + │ │ └── xyz.z:3(float) => z:17(float) + │ ├── stats: [rows=200, distinct(15)=1, null(15)=0, distinct(16)=200, null(16)=0, distinct(17)=130.264312, null(17)=0] + │ └── fd: ()-->(15) └── filters - └── z:14 > 1.0 [type=bool, outer=(14), constraints=(/14: [/1.0000000000000002 - ]; tight)] + └── z:17 > 1.0 [type=bool, outer=(17), constraints=(/17: [/1.0000000000000002 - ]; tight)] # Cardinality is zero. build @@ -93,31 +105,42 @@ INSERT INTO xyz (x, y, z) SELECT b, a, c FROM abc WHERE False RETURNING * insert xyz ├── columns: x:1(string!null) y:2(int!null) z:3(float) ├── insert-mapping: - │ ├── b:7 => x:1 - │ ├── a:6 => y:2 - │ └── c:8 => z:3 + │ ├── b:12 => x:1 + │ ├── a:13 => y:2 + │ └── c:14 => z:3 ├── cardinality: [0 - 0] ├── volatile, mutations ├── stats: [rows=0] - ├── fd: (2)-->(3) └── project - ├── columns: a:6(int!null) b:7(string) c:8(float) + ├── columns: b:12(string) a:13(int!null) c:14(float) ├── cardinality: [0 - 0] + ├── immutable ├── stats: [rows=0] - ├── fd: (6)-->(8) - └── select - ├── columns: a:6(int!null) b:7(string) c:8(float) rowid:9(int!null) abc.crdb_internal_mvcc_timestamp:10(decimal) abc.tableoid:11(oid) - ├── cardinality: [0 - 0] - ├── stats: [rows=0] - ├── key: (9) - ├── fd: (9)-->(6-8,10,11), (6)-->(8) - ├── scan abc - │ ├── columns: a:6(int!null) b:7(string) c:8(float) rowid:9(int!null) abc.crdb_internal_mvcc_timestamp:10(decimal) abc.tableoid:11(oid) - │ ├── computed column expressions - │ │ └── c:8 - │ │ └── a:6::FLOAT8 [type=float] - │ ├── stats: [rows=2000] - │ ├── key: (9) - │ └── fd: (9)-->(6-8,10,11), (6)-->(8) - └── filters - └── false [type=bool, constraints=(contradiction; tight)] + ├── project + │ ├── columns: abc.a:6(int!null) abc.b:7(string) abc.c:8(float) + │ ├── cardinality: [0 - 0] + │ ├── stats: [rows=0] + │ ├── fd: (6)-->(8) + │ └── select + │ ├── columns: abc.a:6(int!null) abc.b:7(string) abc.c:8(float) rowid:9(int!null) abc.crdb_internal_mvcc_timestamp:10(decimal) abc.tableoid:11(oid) + │ ├── cardinality: [0 - 0] + │ ├── stats: [rows=0] + │ ├── key: (9) + │ ├── fd: (9)-->(6-8,10,11), (6)-->(8) + │ ├── scan abc + │ │ ├── columns: abc.a:6(int!null) abc.b:7(string) abc.c:8(float) rowid:9(int!null) abc.crdb_internal_mvcc_timestamp:10(decimal) abc.tableoid:11(oid) + │ │ ├── computed column expressions + │ │ │ └── abc.c:8 + │ │ │ └── abc.a:6::FLOAT8 [type=float] + │ │ ├── stats: [rows=2000] + │ │ ├── key: (9) + │ │ └── fd: (9)-->(6-8,10,11), (6)-->(8) + │ └── filters + │ └── false [type=bool, constraints=(contradiction; tight)] + └── projections + ├── assignment-cast: STRING [as=b:12, type=string, outer=(7), immutable] + │ └── abc.b:7 [type=string] + ├── assignment-cast: INT8 [as=a:13, type=int, outer=(6), immutable] + │ └── abc.a:6 [type=int] + └── assignment-cast: FLOAT8 [as=c:14, type=float, outer=(8), immutable] + └── abc.c:8 [type=float] diff --git a/pkg/sql/opt/memo/typing.go b/pkg/sql/opt/memo/typing.go index b937c3444805..2ce747ace2e3 100644 --- a/pkg/sql/opt/memo/typing.go +++ b/pkg/sql/opt/memo/typing.go @@ -19,9 +19,10 @@ import ( "github.com/cockroachdb/errors" ) -// InferType derives the type of the given scalar expression and stores it in -// the expression's Type field. Depending upon the operator, the type may be -// fixed, or it may be dependent upon the expression children. +// InferType derives the type of the given scalar expression. The result is +// stored in the expression's Type field by Memoize[Expr] functions. Depending +// upon the operator, the type may be fixed, or it may be dependent upon the +// expression children. func InferType(mem *Memo, e opt.ScalarExpr) *types.T { // Special-case Variable, since it's the only expression that needs the memo. if e.Op() == opt.VariableOp { diff --git a/pkg/sql/opt/norm/rules/scalar.opt b/pkg/sql/opt/norm/rules/scalar.opt index fc65c80fc637..c6961850d634 100644 --- a/pkg/sql/opt/norm/rules/scalar.opt +++ b/pkg/sql/opt/norm/rules/scalar.opt @@ -60,7 +60,7 @@ $item # EliminateCast discards the cast operator if its input already has a type # that's equivalent to the desired static type. - +# # Note that CastExpr removes unnecessary casts during type-checking; this rule # can still be helpful if some other rule creates an unnecessary CastExpr. [EliminateCast, Normalize] diff --git a/pkg/sql/opt/norm/testdata/rules/groupby b/pkg/sql/opt/norm/testdata/rules/groupby index 6bfc9084ca77..1685fafe2214 100644 --- a/pkg/sql/opt/norm/testdata/rules/groupby +++ b/pkg/sql/opt/norm/testdata/rules/groupby @@ -946,36 +946,37 @@ insert xy ├── columns: ├── arbiter indexes: xy_pkey ├── insert-mapping: - │ ├── y:6 => x:1 - │ └── y_default:9 => y:2 + │ ├── y:9 => x:1 + │ └── y_default:10 => xy.y:2 ├── cardinality: [0 - 0] ├── volatile, mutations └── limit - ├── columns: y:6!null y_default:9 + ├── columns: y:9!null y_default:10 ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(6,9) + ├── fd: ()-->(9,10) ├── anti-join (hash) - │ ├── columns: y:6!null y_default:9 - │ ├── fd: ()-->(6,9) + │ ├── columns: y:9!null y_default:10 + │ ├── fd: ()-->(9,10) │ ├── limit hint: 1.00 │ ├── project - │ │ ├── columns: y_default:9 y:6!null - │ │ ├── fd: ()-->(6,9) + │ │ ├── columns: y_default:10 y:9!null + │ │ ├── fd: ()-->(9,10) │ │ ├── select - │ │ │ ├── columns: y:6!null + │ │ │ ├── columns: xy.y:6!null │ │ │ ├── fd: ()-->(6) │ │ │ ├── scan xy - │ │ │ │ └── columns: y:6 + │ │ │ │ └── columns: xy.y:6 │ │ │ └── filters - │ │ │ └── y:6 = 0 [outer=(6), constraints=(/6: [/0 - /0]; tight), fd=()-->(6)] + │ │ │ └── xy.y:6 = 0 [outer=(6), constraints=(/6: [/0 - /0]; tight), fd=()-->(6)] │ │ └── projections - │ │ └── CAST(NULL AS INT8) [as=y_default:9] + │ │ ├── CAST(NULL AS INT8) [as=y_default:10] + │ │ └── xy.y:6 [as=y:9, outer=(6)] │ ├── scan xy - │ │ ├── columns: x:10!null - │ │ └── key: (10) + │ │ ├── columns: x:11!null + │ │ └── key: (11) │ └── filters - │ └── y:6 = x:10 [outer=(6,10), constraints=(/6: (/NULL - ]; /10: (/NULL - ]), fd=(6)==(10), (10)==(6)] + │ └── y:9 = x:11 [outer=(9,11), constraints=(/9: (/NULL - ]; /11: (/NULL - ]), fd=(9)==(11), (11)==(9)] └── 1 # EnsureUpsertDistinctOn should reduce non-nullable constant grouping column. @@ -1044,38 +1045,39 @@ insert xy ├── columns: ├── arbiter indexes: xy_pkey ├── insert-mapping: - │ ├── y:6 => x:1 - │ └── y_default:9 => y:2 + │ ├── y:9 => x:1 + │ └── y_default:10 => xy.y:2 ├── cardinality: [0 - 0] ├── volatile, mutations └── upsert-distinct-on - ├── columns: y:6 y_default:9 - ├── grouping columns: y:6 - ├── lax-key: (6) - ├── fd: ()-->(6,9) + ├── columns: y:9 y_default:10 + ├── grouping columns: y:9 + ├── lax-key: (9) + ├── fd: ()-->(9,10) ├── anti-join (hash) - │ ├── columns: y:6 y_default:9 - │ ├── fd: ()-->(6,9) + │ ├── columns: y:9 y_default:10 + │ ├── fd: ()-->(9,10) │ ├── project - │ │ ├── columns: y_default:9 y:6 - │ │ ├── fd: ()-->(6,9) + │ │ ├── columns: y_default:10 y:9 + │ │ ├── fd: ()-->(9,10) │ │ ├── select - │ │ │ ├── columns: y:6 + │ │ │ ├── columns: xy.y:6 │ │ │ ├── fd: ()-->(6) │ │ │ ├── scan xy - │ │ │ │ └── columns: y:6 + │ │ │ │ └── columns: xy.y:6 │ │ │ └── filters - │ │ │ └── y:6 IS NULL [outer=(6), constraints=(/6: [/NULL - /NULL]; tight), fd=()-->(6)] + │ │ │ └── xy.y:6 IS NULL [outer=(6), constraints=(/6: [/NULL - /NULL]; tight), fd=()-->(6)] │ │ └── projections - │ │ └── CAST(NULL AS INT8) [as=y_default:9] + │ │ ├── CAST(NULL AS INT8) [as=y_default:10] + │ │ └── xy.y:6 [as=y:9, outer=(6)] │ ├── scan xy - │ │ ├── columns: x:10!null - │ │ └── key: (10) + │ │ ├── columns: x:11!null + │ │ └── key: (11) │ └── filters - │ └── y:6 = x:10 [outer=(6,10), constraints=(/6: (/NULL - ]; /10: (/NULL - ]), fd=(6)==(10), (10)==(6)] + │ └── y:9 = x:11 [outer=(9,11), constraints=(/9: (/NULL - ]; /11: (/NULL - ]), fd=(9)==(11), (11)==(9)] └── aggregations - └── first-agg [as=y_default:9, outer=(9)] - └── y_default:9 + └── first-agg [as=y_default:10, outer=(10)] + └── y_default:10 # EnsureUpsertDistinctOn should not reduce nullable constant grouping column. norm expect-not=ReduceNotNullGroupingCols @@ -1667,48 +1669,49 @@ insert a ├── columns: ├── arbiter indexes: si_idx ├── insert-mapping: - │ ├── "?column?":15 => k:1 - │ ├── i:9 => i:2 - │ ├── f_default:17 => f:3 - │ ├── "?column?":16 => s:4 - │ └── j_default:18 => j:5 + │ ├── "?column?":17 => k:1 + │ ├── i:18 => a.i:2 + │ ├── f_default:20 => f:3 + │ ├── "?column?":19 => s:4 + │ └── j_default:21 => j:5 ├── cardinality: [0 - 0] ├── volatile, mutations └── limit - ├── columns: i:9!null "?column?":15!null "?column?":16!null f_default:17 j_default:18 + ├── columns: "?column?":17!null i:18!null "?column?":19!null f_default:20 j_default:21 ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(9,15-18) + ├── fd: ()-->(17-21) ├── anti-join (hash) - │ ├── columns: i:9!null "?column?":15!null "?column?":16!null f_default:17 j_default:18 - │ ├── fd: ()-->(9,15-18) + │ ├── columns: "?column?":17!null i:18!null "?column?":19!null f_default:20 j_default:21 + │ ├── fd: ()-->(17-21) │ ├── limit hint: 1.00 │ ├── project - │ │ ├── columns: f_default:17 j_default:18 "?column?":15!null "?column?":16!null i:9!null - │ │ ├── fd: ()-->(9,15-18) + │ │ ├── columns: f_default:20 j_default:21 "?column?":17!null i:18!null "?column?":19!null + │ │ ├── fd: ()-->(17-21) │ │ ├── select - │ │ │ ├── columns: i:9!null + │ │ │ ├── columns: a.i:9!null │ │ │ ├── fd: ()-->(9) │ │ │ ├── scan a - │ │ │ │ └── columns: i:9!null + │ │ │ │ └── columns: a.i:9!null │ │ │ └── filters - │ │ │ └── i:9 = 1 [outer=(9), constraints=(/9: [/1 - /1]; tight), fd=()-->(9)] + │ │ │ └── a.i:9 = 1 [outer=(9), constraints=(/9: [/1 - /1]; tight), fd=()-->(9)] │ │ └── projections - │ │ ├── CAST(NULL AS FLOAT8) [as=f_default:17] - │ │ ├── CAST(NULL AS JSONB) [as=j_default:18] - │ │ ├── 1 [as="?column?":15] - │ │ └── 'foo' [as="?column?":16] + │ │ ├── CAST(NULL AS FLOAT8) [as=f_default:20] + │ │ ├── CAST(NULL AS JSONB) [as=j_default:21] + │ │ ├── 1 [as="?column?":17] + │ │ ├── a.i:9 [as=i:18, outer=(9)] + │ │ └── 'foo' [as="?column?":19] │ ├── select - │ │ ├── columns: i:20!null s:22!null - │ │ ├── key: (20) - │ │ ├── fd: ()-->(22) + │ │ ├── columns: a.i:23!null s:25!null + │ │ ├── key: (23) + │ │ ├── fd: ()-->(25) │ │ ├── scan a - │ │ │ ├── columns: i:20!null s:22!null - │ │ │ └── key: (20,22) + │ │ │ ├── columns: a.i:23!null s:25!null + │ │ │ └── key: (23,25) │ │ └── filters - │ │ └── s:22 = 'foo' [outer=(22), constraints=(/22: [/'foo' - /'foo']; tight), fd=()-->(22)] + │ │ └── s:25 = 'foo' [outer=(25), constraints=(/25: [/'foo' - /'foo']; tight), fd=()-->(25)] │ └── filters - │ └── i:9 = i:20 [outer=(9,20), constraints=(/9: (/NULL - ]; /20: (/NULL - ]), fd=(9)==(20), (20)==(9)] + │ └── i:18 = a.i:23 [outer=(18,23), constraints=(/18: (/NULL - ]; /23: (/NULL - ]), fd=(18)==(23), (23)==(18)] └── 1 # -------------------------------------------------- @@ -2108,35 +2111,35 @@ insert a ├── columns: ├── arbiter indexes: si_idx ├── insert-mapping: - │ ├── column1:8 => k:1 - │ ├── column3:10 => i:2 - │ ├── f_default:11 => f:3 - │ ├── column2:9 => s:4 - │ └── j_default:12 => j:5 + │ ├── column1:11 => k:1 + │ ├── column3:13 => i:2 + │ ├── f_default:14 => f:3 + │ ├── column2:12 => s:4 + │ └── j_default:15 => j:5 ├── cardinality: [0 - 0] ├── volatile, mutations └── anti-join (hash) - ├── columns: column1:8!null column2:9 column3:10 f_default:11 j_default:12 + ├── columns: column1:11!null column2:12 column3:13 f_default:14 j_default:15 ├── cardinality: [0 - 2] - ├── fd: ()-->(11,12) + ├── fd: ()-->(14,15) ├── project - │ ├── columns: f_default:11 j_default:12 column1:8!null column2:9 column3:10 + │ ├── columns: f_default:14 j_default:15 column1:11!null column2:12 column3:13 │ ├── cardinality: [2 - 2] - │ ├── fd: ()-->(11,12) + │ ├── fd: ()-->(14,15) │ ├── values - │ │ ├── columns: column1:8!null column2:9 column3:10 + │ │ ├── columns: column1:11!null column2:12 column3:13 │ │ ├── cardinality: [2 - 2] │ │ ├── (1, NULL, NULL) │ │ └── (1, NULL, NULL) │ └── projections - │ ├── CAST(NULL AS FLOAT8) [as=f_default:11] - │ └── CAST(NULL AS JSONB) [as=j_default:12] + │ ├── CAST(NULL AS FLOAT8) [as=f_default:14] + │ └── CAST(NULL AS JSONB) [as=j_default:15] ├── scan a - │ ├── columns: i:14!null s:16!null - │ └── key: (14,16) + │ ├── columns: i:17!null s:19!null + │ └── key: (17,19) └── filters - ├── column3:10 = i:14 [outer=(10,14), constraints=(/10: (/NULL - ]; /14: (/NULL - ]), fd=(10)==(14), (14)==(10)] - └── column2:9 = s:16 [outer=(9,16), constraints=(/9: (/NULL - ]; /16: (/NULL - ]), fd=(9)==(16), (16)==(9)] + ├── column3:13 = i:17 [outer=(13,17), constraints=(/13: (/NULL - ]; /17: (/NULL - ]), fd=(13)==(17), (17)==(13)] + └── column2:12 = s:19 [outer=(12,19), constraints=(/12: (/NULL - ]; /19: (/NULL - ]), fd=(12)==(19), (19)==(12)] # EnsureUpsertDistinctOn treats NULL values as distinct, so it can be eliminated. norm expect=EliminateDistinctOnValues @@ -2266,54 +2269,54 @@ insert a ├── columns: ├── arbiter indexes: a_pkey si_idx fi_idx ├── insert-mapping: - │ ├── column1:8 => k:1 - │ ├── column3:10 => i:2 - │ ├── column4:11 => f:3 - │ ├── column2:9 => s:4 - │ └── j_default:12 => j:5 + │ ├── column1:12 => k:1 + │ ├── column3:14 => i:2 + │ ├── column4:15 => f:3 + │ ├── column2:13 => s:4 + │ └── j_default:16 => j:5 ├── cardinality: [0 - 0] ├── volatile, mutations └── anti-join (hash) - ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null j_default:12 + ├── columns: column1:12!null column2:13!null column3:14!null column4:15!null j_default:16 ├── cardinality: [0 - 3] - ├── fd: ()-->(12) + ├── fd: ()-->(16) ├── anti-join (hash) - │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null j_default:12 + │ ├── columns: column1:12!null column2:13!null column3:14!null column4:15!null j_default:16 │ ├── cardinality: [0 - 3] - │ ├── fd: ()-->(12) + │ ├── fd: ()-->(16) │ ├── anti-join (hash) - │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null j_default:12 + │ │ ├── columns: column1:12!null column2:13!null column3:14!null column4:15!null j_default:16 │ │ ├── cardinality: [0 - 3] - │ │ ├── fd: ()-->(12) + │ │ ├── fd: ()-->(16) │ │ ├── project - │ │ │ ├── columns: j_default:12 column1:8!null column2:9!null column3:10!null column4:11!null + │ │ │ ├── columns: j_default:16 column1:12!null column2:13!null column3:14!null column4:15!null │ │ │ ├── cardinality: [3 - 3] - │ │ │ ├── fd: ()-->(12) + │ │ │ ├── fd: ()-->(16) │ │ │ ├── values - │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null + │ │ │ │ ├── columns: column1:12!null column2:13!null column3:14!null column4:15!null │ │ │ │ ├── cardinality: [3 - 3] │ │ │ │ ├── (1, 'foo', 1, 1.0) │ │ │ │ ├── (2, 'bar', 2, 2.0) │ │ │ │ └── (3, 'foo', 2, 1.0) │ │ │ └── projections - │ │ │ └── CAST(NULL AS JSONB) [as=j_default:12] + │ │ │ └── CAST(NULL AS JSONB) [as=j_default:16] │ │ ├── scan a - │ │ │ ├── columns: k:13!null - │ │ │ └── key: (13) + │ │ │ ├── columns: k:17!null + │ │ │ └── key: (17) │ │ └── filters - │ │ └── column1:8 = k:13 [outer=(8,13), constraints=(/8: (/NULL - ]; /13: (/NULL - ]), fd=(8)==(13), (13)==(8)] + │ │ └── column1:12 = k:17 [outer=(12,17), constraints=(/12: (/NULL - ]; /17: (/NULL - ]), fd=(12)==(17), (17)==(12)] │ ├── scan a - │ │ ├── columns: i:21!null s:23!null - │ │ └── key: (21,23) + │ │ ├── columns: i:25!null s:27!null + │ │ └── key: (25,27) │ └── filters - │ ├── column3:10 = i:21 [outer=(10,21), constraints=(/10: (/NULL - ]; /21: (/NULL - ]), fd=(10)==(21), (21)==(10)] - │ └── column2:9 = s:23 [outer=(9,23), constraints=(/9: (/NULL - ]; /23: (/NULL - ]), fd=(9)==(23), (23)==(9)] + │ ├── column3:14 = i:25 [outer=(14,25), constraints=(/14: (/NULL - ]; /25: (/NULL - ]), fd=(14)==(25), (25)==(14)] + │ └── column2:13 = s:27 [outer=(13,27), constraints=(/13: (/NULL - ]; /27: (/NULL - ]), fd=(13)==(27), (27)==(13)] ├── scan a - │ ├── columns: i:28!null f:29 - │ └── lax-key: (28,29) + │ ├── columns: i:32!null f:33 + │ └── lax-key: (32,33) └── filters - ├── column3:10 = i:28 [outer=(10,28), constraints=(/10: (/NULL - ]; /28: (/NULL - ]), fd=(10)==(28), (28)==(10)] - └── column4:11 = f:29 [outer=(11,29), constraints=(/11: (/NULL - ]; /29: (/NULL - ]), fd=(11)==(29), (29)==(11)] + ├── column3:14 = i:32 [outer=(14,32), constraints=(/14: (/NULL - ]; /32: (/NULL - ]), fd=(14)==(32), (32)==(14)] + └── column4:15 = f:33 [outer=(15,33), constraints=(/15: (/NULL - ]; /33: (/NULL - ]), fd=(15)==(33), (33)==(15)] # DO NOTHING case where one distinct op can be removed (k), but two others # can't: (s, i) and (f, i). @@ -2325,81 +2328,81 @@ insert a ├── columns: ├── arbiter indexes: a_pkey si_idx fi_idx ├── insert-mapping: - │ ├── column1:8 => k:1 - │ ├── i_default:11 => i:2 - │ ├── column3:10 => f:3 - │ ├── column2:9 => s:4 - │ └── j_default:12 => j:5 + │ ├── column1:11 => k:1 + │ ├── i_default:14 => i:2 + │ ├── column3:13 => f:3 + │ ├── column2:12 => s:4 + │ └── j_default:15 => j:5 ├── cardinality: [0 - 0] ├── volatile, mutations └── upsert-distinct-on - ├── columns: column1:8!null column2:9!null column3:10!null i_default:11 j_default:12 - ├── grouping columns: column3:10!null i_default:11 + ├── columns: column1:11!null column2:12!null column3:13!null i_default:14 j_default:15 + ├── grouping columns: column3:13!null i_default:14 ├── cardinality: [0 - 3] - ├── lax-key: (9,11) - ├── fd: ()-->(11,12), (9,11)~~>(8,10), (10,11)~~>(8,9,12) + ├── lax-key: (12,14) + ├── fd: ()-->(14,15), (12,14)~~>(11,13), (13,14)~~>(11,12,15) ├── upsert-distinct-on - │ ├── columns: column1:8!null column2:9!null column3:10!null i_default:11 j_default:12 - │ ├── grouping columns: column2:9!null i_default:11 + │ ├── columns: column1:11!null column2:12!null column3:13!null i_default:14 j_default:15 + │ ├── grouping columns: column2:12!null i_default:14 │ ├── cardinality: [0 - 3] - │ ├── lax-key: (9,11) - │ ├── fd: ()-->(11,12), (9,11)~~>(8,10,12) + │ ├── lax-key: (12,14) + │ ├── fd: ()-->(14,15), (12,14)~~>(11,13,15) │ ├── anti-join (hash) - │ │ ├── columns: column1:8!null column2:9!null column3:10!null i_default:11 j_default:12 + │ │ ├── columns: column1:11!null column2:12!null column3:13!null i_default:14 j_default:15 │ │ ├── cardinality: [0 - 3] - │ │ ├── fd: ()-->(11,12) + │ │ ├── fd: ()-->(14,15) │ │ ├── anti-join (hash) - │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null i_default:11 j_default:12 + │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null i_default:14 j_default:15 │ │ │ ├── cardinality: [0 - 3] - │ │ │ ├── fd: ()-->(11,12) + │ │ │ ├── fd: ()-->(14,15) │ │ │ ├── anti-join (hash) - │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null i_default:11 j_default:12 + │ │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null i_default:14 j_default:15 │ │ │ │ ├── cardinality: [0 - 3] - │ │ │ │ ├── fd: ()-->(11,12) + │ │ │ │ ├── fd: ()-->(14,15) │ │ │ │ ├── project - │ │ │ │ │ ├── columns: i_default:11 j_default:12 column1:8!null column2:9!null column3:10!null + │ │ │ │ │ ├── columns: i_default:14 j_default:15 column1:11!null column2:12!null column3:13!null │ │ │ │ │ ├── cardinality: [3 - 3] - │ │ │ │ │ ├── fd: ()-->(11,12) + │ │ │ │ │ ├── fd: ()-->(14,15) │ │ │ │ │ ├── values - │ │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null + │ │ │ │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null │ │ │ │ │ │ ├── cardinality: [3 - 3] │ │ │ │ │ │ ├── (1, 'foo', 1.0) │ │ │ │ │ │ ├── (2, 'bar', 2.0) │ │ │ │ │ │ └── (3, 'foo', 1.0) │ │ │ │ │ └── projections - │ │ │ │ │ ├── CAST(NULL AS INT8) [as=i_default:11] - │ │ │ │ │ └── CAST(NULL AS JSONB) [as=j_default:12] + │ │ │ │ │ ├── CAST(NULL AS INT8) [as=i_default:14] + │ │ │ │ │ └── CAST(NULL AS JSONB) [as=j_default:15] │ │ │ │ ├── scan a - │ │ │ │ │ ├── columns: k:13!null - │ │ │ │ │ └── key: (13) + │ │ │ │ │ ├── columns: k:16!null + │ │ │ │ │ └── key: (16) │ │ │ │ └── filters - │ │ │ │ └── column1:8 = k:13 [outer=(8,13), constraints=(/8: (/NULL - ]; /13: (/NULL - ]), fd=(8)==(13), (13)==(8)] + │ │ │ │ └── column1:11 = k:16 [outer=(11,16), constraints=(/11: (/NULL - ]; /16: (/NULL - ]), fd=(11)==(16), (16)==(11)] │ │ │ ├── scan a - │ │ │ │ ├── columns: i:21!null s:23!null - │ │ │ │ └── key: (21,23) + │ │ │ │ ├── columns: i:24!null s:26!null + │ │ │ │ └── key: (24,26) │ │ │ └── filters - │ │ │ ├── i_default:11 = i:21 [outer=(11,21), constraints=(/11: (/NULL - ]; /21: (/NULL - ]), fd=(11)==(21), (21)==(11)] - │ │ │ └── column2:9 = s:23 [outer=(9,23), constraints=(/9: (/NULL - ]; /23: (/NULL - ]), fd=(9)==(23), (23)==(9)] + │ │ │ ├── i_default:14 = i:24 [outer=(14,24), constraints=(/14: (/NULL - ]; /24: (/NULL - ]), fd=(14)==(24), (24)==(14)] + │ │ │ └── column2:12 = s:26 [outer=(12,26), constraints=(/12: (/NULL - ]; /26: (/NULL - ]), fd=(12)==(26), (26)==(12)] │ │ ├── scan a - │ │ │ ├── columns: i:28!null f:29 - │ │ │ └── lax-key: (28,29) + │ │ │ ├── columns: i:31!null f:32 + │ │ │ └── lax-key: (31,32) │ │ └── filters - │ │ ├── i_default:11 = i:28 [outer=(11,28), constraints=(/11: (/NULL - ]; /28: (/NULL - ]), fd=(11)==(28), (28)==(11)] - │ │ └── column3:10 = f:29 [outer=(10,29), constraints=(/10: (/NULL - ]; /29: (/NULL - ]), fd=(10)==(29), (29)==(10)] + │ │ ├── i_default:14 = i:31 [outer=(14,31), constraints=(/14: (/NULL - ]; /31: (/NULL - ]), fd=(14)==(31), (31)==(14)] + │ │ └── column3:13 = f:32 [outer=(13,32), constraints=(/13: (/NULL - ]; /32: (/NULL - ]), fd=(13)==(32), (32)==(13)] │ └── aggregations - │ ├── first-agg [as=column1:8, outer=(8)] - │ │ └── column1:8 - │ ├── first-agg [as=column3:10, outer=(10)] - │ │ └── column3:10 - │ └── first-agg [as=j_default:12, outer=(12)] - │ └── j_default:12 + │ ├── first-agg [as=column1:11, outer=(11)] + │ │ └── column1:11 + │ ├── first-agg [as=column3:13, outer=(13)] + │ │ └── column3:13 + │ └── first-agg [as=j_default:15, outer=(15)] + │ └── j_default:15 └── aggregations - ├── first-agg [as=column1:8, outer=(8)] - │ └── column1:8 - ├── first-agg [as=column2:9, outer=(9)] - │ └── column2:9 - └── first-agg [as=j_default:12, outer=(12)] - └── j_default:12 + ├── first-agg [as=column1:11, outer=(11)] + │ └── column1:11 + ├── first-agg [as=column2:12, outer=(12)] + │ └── column2:12 + └── first-agg [as=j_default:15, outer=(15)] + └── j_default:15 # DO NOTHING case where innermost distinct op cannot be removed (because it # groups on a non-constant column). Ensure that outer distinct ops can still be @@ -2412,74 +2415,74 @@ insert a ├── columns: ├── arbiter indexes: a_pkey si_idx fi_idx ├── insert-mapping: - │ ├── column1:8 => k:1 - │ ├── column3:10 => i:2 - │ ├── column4:11 => f:3 - │ ├── column2:9 => s:4 - │ └── j_default:12 => j:5 + │ ├── column1:12 => k:1 + │ ├── column3:14 => i:2 + │ ├── column4:15 => f:3 + │ ├── column2:13 => s:4 + │ └── j_default:16 => j:5 ├── cardinality: [0 - 0] ├── volatile, mutations └── upsert-distinct-on - ├── columns: column1:8 column2:9!null column3:10!null column4:11!null j_default:12 - ├── grouping columns: column1:8 + ├── columns: column1:12 column2:13!null column3:14!null column4:15!null j_default:16 + ├── grouping columns: column1:12 ├── cardinality: [0 - 2] ├── volatile - ├── lax-key: (8) - ├── fd: ()-->(12), (8)~~>(9-12) + ├── lax-key: (12) + ├── fd: ()-->(16), (12)~~>(13-16) ├── anti-join (hash) - │ ├── columns: column1:8 column2:9!null column3:10!null column4:11!null j_default:12 + │ ├── columns: column1:12 column2:13!null column3:14!null column4:15!null j_default:16 │ ├── cardinality: [0 - 2] │ ├── volatile - │ ├── fd: ()-->(12) + │ ├── fd: ()-->(16) │ ├── anti-join (hash) - │ │ ├── columns: column1:8 column2:9!null column3:10!null column4:11!null j_default:12 + │ │ ├── columns: column1:12 column2:13!null column3:14!null column4:15!null j_default:16 │ │ ├── cardinality: [0 - 2] │ │ ├── volatile - │ │ ├── fd: ()-->(12) + │ │ ├── fd: ()-->(16) │ │ ├── anti-join (hash) - │ │ │ ├── columns: column1:8 column2:9!null column3:10!null column4:11!null j_default:12 + │ │ │ ├── columns: column1:12 column2:13!null column3:14!null column4:15!null j_default:16 │ │ │ ├── cardinality: [0 - 2] │ │ │ ├── volatile - │ │ │ ├── fd: ()-->(12) + │ │ │ ├── fd: ()-->(16) │ │ │ ├── project - │ │ │ │ ├── columns: j_default:12 column1:8 column2:9!null column3:10!null column4:11!null + │ │ │ │ ├── columns: j_default:16 column1:12 column2:13!null column3:14!null column4:15!null │ │ │ │ ├── cardinality: [2 - 2] │ │ │ │ ├── volatile - │ │ │ │ ├── fd: ()-->(12) + │ │ │ │ ├── fd: ()-->(16) │ │ │ │ ├── values - │ │ │ │ │ ├── columns: column1:8 column2:9!null column3:10!null column4:11!null + │ │ │ │ │ ├── columns: column1:12 column2:13!null column3:14!null column4:15!null │ │ │ │ │ ├── cardinality: [2 - 2] │ │ │ │ │ ├── volatile │ │ │ │ │ ├── (unique_rowid(), 'foo', 1, 1.0) │ │ │ │ │ └── (unique_rowid(), 'bar', 2, 2.0) │ │ │ │ └── projections - │ │ │ │ └── CAST(NULL AS JSONB) [as=j_default:12] + │ │ │ │ └── CAST(NULL AS JSONB) [as=j_default:16] │ │ │ ├── scan a - │ │ │ │ ├── columns: k:13!null - │ │ │ │ └── key: (13) + │ │ │ │ ├── columns: k:17!null + │ │ │ │ └── key: (17) │ │ │ └── filters - │ │ │ └── column1:8 = k:13 [outer=(8,13), constraints=(/8: (/NULL - ]; /13: (/NULL - ]), fd=(8)==(13), (13)==(8)] + │ │ │ └── column1:12 = k:17 [outer=(12,17), constraints=(/12: (/NULL - ]; /17: (/NULL - ]), fd=(12)==(17), (17)==(12)] │ │ ├── scan a - │ │ │ ├── columns: i:21!null s:23!null - │ │ │ └── key: (21,23) + │ │ │ ├── columns: i:25!null s:27!null + │ │ │ └── key: (25,27) │ │ └── filters - │ │ ├── column3:10 = i:21 [outer=(10,21), constraints=(/10: (/NULL - ]; /21: (/NULL - ]), fd=(10)==(21), (21)==(10)] - │ │ └── column2:9 = s:23 [outer=(9,23), constraints=(/9: (/NULL - ]; /23: (/NULL - ]), fd=(9)==(23), (23)==(9)] + │ │ ├── column3:14 = i:25 [outer=(14,25), constraints=(/14: (/NULL - ]; /25: (/NULL - ]), fd=(14)==(25), (25)==(14)] + │ │ └── column2:13 = s:27 [outer=(13,27), constraints=(/13: (/NULL - ]; /27: (/NULL - ]), fd=(13)==(27), (27)==(13)] │ ├── scan a - │ │ ├── columns: i:28!null f:29 - │ │ └── lax-key: (28,29) + │ │ ├── columns: i:32!null f:33 + │ │ └── lax-key: (32,33) │ └── filters - │ ├── column3:10 = i:28 [outer=(10,28), constraints=(/10: (/NULL - ]; /28: (/NULL - ]), fd=(10)==(28), (28)==(10)] - │ └── column4:11 = f:29 [outer=(11,29), constraints=(/11: (/NULL - ]; /29: (/NULL - ]), fd=(11)==(29), (29)==(11)] + │ ├── column3:14 = i:32 [outer=(14,32), constraints=(/14: (/NULL - ]; /32: (/NULL - ]), fd=(14)==(32), (32)==(14)] + │ └── column4:15 = f:33 [outer=(15,33), constraints=(/15: (/NULL - ]; /33: (/NULL - ]), fd=(15)==(33), (33)==(15)] └── aggregations - ├── first-agg [as=column2:9, outer=(9)] - │ └── column2:9 - ├── first-agg [as=column3:10, outer=(10)] - │ └── column3:10 - ├── first-agg [as=column4:11, outer=(11)] - │ └── column4:11 - └── first-agg [as=j_default:12, outer=(12)] - └── j_default:12 + ├── first-agg [as=column2:13, outer=(13)] + │ └── column2:13 + ├── first-agg [as=column3:14, outer=(14)] + │ └── column3:14 + ├── first-agg [as=column4:15, outer=(15)] + │ └── column4:15 + └── first-agg [as=j_default:16, outer=(16)] + └── j_default:16 # DO NOTHING case with explicit conflict columns (only add upsert-distinct-on # for one index). @@ -2491,48 +2494,52 @@ insert a ├── columns: ├── arbiter indexes: si_idx ├── insert-mapping: - │ ├── i:9 => k:1 - │ ├── i:9 => i:2 - │ ├── f_default:16 => f:3 - │ ├── "?column?":15 => s:4 - │ └── j_default:17 => j:5 + │ ├── i:16 => k:1 + │ ├── i:18 => a.i:2 + │ ├── f_default:19 => f:3 + │ ├── "?column?":17 => s:4 + │ └── j_default:20 => j:5 ├── cardinality: [0 - 0] ├── volatile, mutations └── upsert-distinct-on - ├── columns: i:9!null "?column?":15!null f_default:16 j_default:17 - ├── grouping columns: i:9!null - ├── key: (9) - ├── fd: ()-->(15-17) + ├── columns: i:16!null "?column?":17!null i:18!null f_default:19 j_default:20 + ├── grouping columns: i:18!null + ├── key: (18) + ├── fd: ()-->(17,19,20), (16)==(18), (18)==(16), (18)-->(16,17,19,20) ├── anti-join (hash) - │ ├── columns: i:9!null "?column?":15!null f_default:16 j_default:17 - │ ├── fd: ()-->(15-17) + │ ├── columns: i:16!null "?column?":17!null i:18!null f_default:19 j_default:20 + │ ├── fd: ()-->(17,19,20), (16)==(18), (18)==(16) │ ├── project - │ │ ├── columns: f_default:16 j_default:17 "?column?":15!null i:9!null - │ │ ├── fd: ()-->(15-17) + │ │ ├── columns: f_default:19 j_default:20 i:16!null "?column?":17!null i:18!null + │ │ ├── fd: ()-->(17,19,20), (16)==(18), (18)==(16) │ │ ├── scan a - │ │ │ └── columns: i:9!null + │ │ │ └── columns: a.i:9!null │ │ └── projections - │ │ ├── CAST(NULL AS FLOAT8) [as=f_default:16] - │ │ ├── CAST(NULL AS JSONB) [as=j_default:17] - │ │ └── 'foo' [as="?column?":15] + │ │ ├── CAST(NULL AS FLOAT8) [as=f_default:19] + │ │ ├── CAST(NULL AS JSONB) [as=j_default:20] + │ │ ├── a.i:9 [as=i:16, outer=(9)] + │ │ ├── 'foo' [as="?column?":17] + │ │ └── a.i:9 [as=i:18, outer=(9)] │ ├── select - │ │ ├── columns: i:19!null s:21!null - │ │ ├── key: (19) - │ │ ├── fd: ()-->(21) + │ │ ├── columns: a.i:22!null s:24!null + │ │ ├── key: (22) + │ │ ├── fd: ()-->(24) │ │ ├── scan a - │ │ │ ├── columns: i:19!null s:21!null - │ │ │ └── key: (19,21) + │ │ │ ├── columns: a.i:22!null s:24!null + │ │ │ └── key: (22,24) │ │ └── filters - │ │ └── s:21 = 'foo' [outer=(21), constraints=(/21: [/'foo' - /'foo']; tight), fd=()-->(21)] + │ │ └── s:24 = 'foo' [outer=(24), constraints=(/24: [/'foo' - /'foo']; tight), fd=()-->(24)] │ └── filters - │ └── i:9 = i:19 [outer=(9,19), constraints=(/9: (/NULL - ]; /19: (/NULL - ]), fd=(9)==(19), (19)==(9)] + │ └── i:18 = a.i:22 [outer=(18,22), constraints=(/18: (/NULL - ]; /22: (/NULL - ]), fd=(18)==(22), (22)==(18)] └── aggregations - ├── first-agg [as=f_default:16, outer=(16)] - │ └── f_default:16 - ├── first-agg [as=j_default:17, outer=(17)] - │ └── j_default:17 - └── const-agg [as="?column?":15, outer=(15)] - └── "?column?":15 + ├── first-agg [as=i:16, outer=(16)] + │ └── i:16 + ├── first-agg [as=f_default:19, outer=(19)] + │ └── f_default:19 + ├── first-agg [as=j_default:20, outer=(20)] + │ └── j_default:20 + └── const-agg [as="?column?":17, outer=(17)] + └── "?column?":17 # -------------------------------------------------- # PushAggDistinctIntoGroupBy diff --git a/pkg/sql/opt/norm/testdata/rules/prune_cols b/pkg/sql/opt/norm/testdata/rules/prune_cols index f0666bd326ce..492bac85a648 100644 --- a/pkg/sql/opt/norm/testdata/rules/prune_cols +++ b/pkg/sql/opt/norm/testdata/rules/prune_cols @@ -3492,19 +3492,37 @@ INSERT INTO checks (a, c, d) VALUES (1, 3, 4) insert checks ├── columns: ├── insert-mapping: - │ ├── column1:7 => a:1 - │ ├── b_default:10 => b:2 - │ ├── column2:8 => c:3 - │ └── column3:9 => d:4 - ├── check columns: check1:11 check2:12 check3:13 + │ ├── column1:10 => a:1 + │ ├── b_default:13 => b:2 + │ ├── column2:11 => c:3 + │ └── column3:12 => d:4 + ├── check columns: check1:14 check2:15 check3:16 ├── cardinality: [0 - 0] ├── volatile, mutations - └── values - ├── columns: column1:7!null column2:8!null column3:9!null b_default:10!null check1:11!null check2:12!null check3:13!null + └── project + ├── columns: check1:14 check2:15!null check3:16 column1:10 column2:11 column3:12 b_default:13!null ├── cardinality: [1 - 1] + ├── immutable ├── key: () - ├── fd: ()-->(7-13) - └── (1, 3, 4, 20, true, true, false) + ├── fd: ()-->(10-16) + ├── values + │ ├── columns: column1:10 column2:11 column3:12 b_default:13!null + │ ├── cardinality: [1 - 1] + │ ├── immutable + │ ├── key: () + │ ├── fd: ()-->(10-13) + │ └── tuple + │ ├── assignment-cast: INT8 + │ │ └── 1 + │ ├── assignment-cast: INT8 + │ │ └── 3 + │ ├── assignment-cast: INT8 + │ │ └── 4 + │ └── 20 + └── projections + ├── column1:10 > 0 [as=check1:14, outer=(10)] + ├── true [as=check2:15] + └── column2:11 > 20 [as=check3:16, outer=(11)] # Do not prune check columns for an upsert that does not require a scan. norm expect-not=PruneMutationInputCols diff --git a/pkg/sql/opt/norm/testdata/rules/with b/pkg/sql/opt/norm/testdata/rules/with index b23ad24d842d..d3aa92410472 100644 --- a/pkg/sql/opt/norm/testdata/rules/with +++ b/pkg/sql/opt/norm/testdata/rules/with @@ -394,40 +394,47 @@ norm WITH foo AS (INSERT INTO a VALUES (1) RETURNING *) SELECT * FROM foo ---- with &1 (foo) - ├── columns: k:13!null i:14 f:15 s:16 j:17 + ├── columns: k:14!null i:15 f:16 s:17 j:18 ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(13-17) + ├── fd: ()-->(14-18) ├── insert a │ ├── columns: a.k:1!null a.i:2 a.f:3 a.s:4 a.j:5 │ ├── insert-mapping: - │ │ ├── column1:8 => a.k:1 - │ │ ├── i_default:9 => a.i:2 - │ │ ├── f_default:10 => a.f:3 - │ │ ├── s_default:11 => a.s:4 - │ │ └── j_default:12 => a.j:5 + │ │ ├── column1:9 => a.k:1 + │ │ ├── i_default:10 => a.i:2 + │ │ ├── f_default:11 => a.f:3 + │ │ ├── s_default:12 => a.s:4 + │ │ └── j_default:13 => a.j:5 │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () │ ├── fd: ()-->(1-5) │ └── values - │ ├── columns: column1:8!null i_default:9 f_default:10 s_default:11 j_default:12 + │ ├── columns: column1:9 i_default:10 f_default:11 s_default:12 j_default:13 │ ├── cardinality: [1 - 1] + │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(8-12) - │ └── (1, NULL, NULL, NULL, NULL) + │ ├── fd: ()-->(9-13) + │ └── tuple + │ ├── assignment-cast: INT8 + │ │ └── 1 + │ ├── CAST(NULL AS INT8) + │ ├── CAST(NULL AS FLOAT8) + │ ├── CAST(NULL AS STRING) + │ └── CAST(NULL AS JSONB) └── with-scan &1 (foo) - ├── columns: k:13!null i:14 f:15 s:16 j:17 + ├── columns: k:14!null i:15 f:16 s:17 j:18 ├── mapping: - │ ├── a.k:1 => k:13 - │ ├── a.i:2 => i:14 - │ ├── a.f:3 => f:15 - │ ├── a.s:4 => s:16 - │ └── a.j:5 => j:17 + │ ├── a.k:1 => k:14 + │ ├── a.i:2 => i:15 + │ ├── a.f:3 => f:16 + │ ├── a.s:4 => s:17 + │ └── a.j:5 => j:18 ├── cardinality: [1 - 1] ├── key: () - └── fd: ()-->(13-17) + └── fd: ()-->(14-18) norm expect-not=InlineWith WITH foo AS (SELECT crdb_internal.notice('foo')) SELECT * FROM foo @@ -547,111 +554,127 @@ norm format=show-all WITH cte AS (INSERT INTO child VALUES (1, 1) RETURNING c) SELECT c FROM cte UNION SELECT c+1 FROM cte ---- with &2 (cte) - ├── columns: c:14(int!null) + ├── columns: c:16(int!null) ├── cardinality: [1 - 2] ├── volatile, mutations - ├── stats: [rows=2, distinct(14)=2, null(14)=0] - ├── cost: 1056.9075 - ├── key: (14) + ├── stats: [rows=2, distinct(16)=2, null(16)=0] + ├── cost: 1056.9375 + ├── key: (16) ├── insert t.public.child │ ├── columns: t.public.child.c:1(int!null) │ ├── insert-mapping: - │ │ ├── column1:5 => t.public.child.c:1 - │ │ └── column2:6 => t.public.child.p:2 + │ │ ├── column1:7 => t.public.child.c:1 + │ │ └── column2:8 => t.public.child.p:2 │ ├── input binding: &1 │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── stats: [rows=1, distinct(1)=1, null(1)=0] - │ ├── cost: 1056.7975 + │ ├── cost: 1056.8275 │ ├── key: () │ ├── fd: ()-->(1) │ ├── values - │ │ ├── columns: column1:5(int!null) column2:6(int!null) + │ │ ├── columns: column1:7(int) column2:8(int) │ │ ├── cardinality: [1 - 1] - │ │ ├── stats: [rows=1, distinct(5)=1, null(5)=0, distinct(6)=1, null(6)=0] + │ │ ├── immutable + │ │ ├── stats: [rows=1, distinct(7)=1, null(7)=0, distinct(8)=1, null(8)=0] │ │ ├── cost: 0.02 │ │ ├── key: () - │ │ ├── fd: ()-->(5,6) - │ │ ├── prune: (5,6) + │ │ ├── fd: ()-->(7,8) + │ │ ├── prune: (7,8) │ │ └── tuple [type=tuple{int, int}] - │ │ ├── const: 1 [type=int] - │ │ └── const: 1 [type=int] + │ │ ├── assignment-cast: INT8 [type=int] + │ │ │ └── const: 1 [type=int] + │ │ └── assignment-cast: INT8 [type=int] + │ │ └── const: 1 [type=int] │ └── f-k-checks │ └── f-k-checks-item: child(p) -> parent(p) │ └── anti-join (hash) - │ ├── columns: p:7(int!null) + │ ├── columns: p:9(int!null) │ ├── cardinality: [0 - 1] │ ├── stats: [rows=1e-10] - │ ├── cost: 1056.7675 + │ ├── cost: 1056.7975 │ ├── key: () - │ ├── fd: ()-->(7) + │ ├── fd: ()-->(9) │ ├── cte-uses - │ │ └── &1: count=1 used-columns=(6) - │ ├── with-scan &1 - │ │ ├── columns: p:7(int!null) - │ │ ├── mapping: - │ │ │ └── column2:6(int) => p:7(int) - │ │ ├── cardinality: [1 - 1] - │ │ ├── stats: [rows=1, distinct(7)=1, null(7)=0] - │ │ ├── cost: 0.01 + │ │ └── &1: count=1 used-columns=(8) + │ ├── select + │ │ ├── columns: p:9(int!null) + │ │ ├── cardinality: [0 - 1] + │ │ ├── stats: [rows=1, distinct(9)=1, null(9)=0] + │ │ ├── cost: 0.04 │ │ ├── key: () - │ │ ├── fd: ()-->(7) - │ │ ├── prune: (7) - │ │ └── cte-uses - │ │ └── &1: count=1 used-columns=(6) + │ │ ├── fd: ()-->(9) + │ │ ├── cte-uses + │ │ │ └── &1: count=1 used-columns=(8) + │ │ ├── with-scan &1 + │ │ │ ├── columns: p:9(int) + │ │ │ ├── mapping: + │ │ │ │ └── column2:8(int) => p:9(int) + │ │ │ ├── cardinality: [1 - 1] + │ │ │ ├── stats: [rows=1, distinct(9)=1, null(9)=0] + │ │ │ ├── cost: 0.01 + │ │ │ ├── key: () + │ │ │ ├── fd: ()-->(9) + │ │ │ ├── prune: (9) + │ │ │ └── cte-uses + │ │ │ └── &1: count=1 used-columns=(8) + │ │ └── filters + │ │ └── is-not [type=bool, outer=(9), constraints=(/9: (/NULL - ]; tight)] + │ │ ├── variable: p:9 [type=int] + │ │ └── null [type=unknown] │ ├── scan t.public.parent - │ │ ├── columns: t.public.parent.p:8(int!null) - │ │ ├── stats: [rows=1000, distinct(8)=1000, null(8)=0] + │ │ ├── columns: t.public.parent.p:10(int!null) + │ │ ├── stats: [rows=1000, distinct(10)=1000, null(10)=0] │ │ ├── cost: 1044.22 - │ │ ├── key: (8) - │ │ ├── prune: (8) - │ │ ├── interesting orderings: (+8) - │ │ └── unfiltered-cols: (8-10) + │ │ ├── key: (10) + │ │ ├── prune: (10) + │ │ ├── interesting orderings: (+10) + │ │ └── unfiltered-cols: (10-12) │ └── filters - │ └── eq [type=bool, outer=(7,8), constraints=(/7: (/NULL - ]; /8: (/NULL - ]), fd=(7)==(8), (8)==(7)] - │ ├── variable: p:7 [type=int] - │ └── variable: t.public.parent.p:8 [type=int] + │ └── eq [type=bool, outer=(9,10), constraints=(/9: (/NULL - ]; /10: (/NULL - ]), fd=(9)==(10), (10)==(9)] + │ ├── variable: p:9 [type=int] + │ └── variable: t.public.parent.p:10 [type=int] └── union - ├── columns: c:14(int!null) - ├── left columns: c:11(int) - ├── right columns: "?column?":13(int) + ├── columns: c:16(int!null) + ├── left columns: c:13(int) + ├── right columns: "?column?":15(int) ├── cardinality: [1 - 2] ├── immutable - ├── stats: [rows=2, distinct(14)=2, null(14)=0] + ├── stats: [rows=2, distinct(16)=2, null(16)=0] ├── cost: 0.1 - ├── key: (14) + ├── key: (16) ├── with-scan &2 (cte) - │ ├── columns: c:11(int!null) + │ ├── columns: c:13(int!null) │ ├── mapping: - │ │ └── t.public.child.c:1(int) => c:11(int) + │ │ └── t.public.child.c:1(int) => c:13(int) │ ├── cardinality: [1 - 1] - │ ├── stats: [rows=1, distinct(11)=1, null(11)=0] + │ ├── stats: [rows=1, distinct(13)=1, null(13)=0] │ ├── cost: 0.01 │ ├── key: () - │ ├── fd: ()-->(11) - │ └── prune: (11) + │ ├── fd: ()-->(13) + │ └── prune: (13) └── project - ├── columns: "?column?":13(int!null) + ├── columns: "?column?":15(int!null) ├── cardinality: [1 - 1] ├── immutable - ├── stats: [rows=1, distinct(13)=1, null(13)=0] + ├── stats: [rows=1, distinct(15)=1, null(15)=0] ├── cost: 0.04 ├── key: () - ├── fd: ()-->(13) - ├── prune: (13) + ├── fd: ()-->(15) + ├── prune: (15) ├── with-scan &2 (cte) - │ ├── columns: c:12(int!null) + │ ├── columns: c:14(int!null) │ ├── mapping: - │ │ └── t.public.child.c:1(int) => c:12(int) + │ │ └── t.public.child.c:1(int) => c:14(int) │ ├── cardinality: [1 - 1] - │ ├── stats: [rows=1, distinct(12)=1, null(12)=0] + │ ├── stats: [rows=1, distinct(14)=1, null(14)=0] │ ├── cost: 0.01 │ ├── key: () - │ ├── fd: ()-->(12) - │ └── prune: (12) + │ ├── fd: ()-->(14) + │ └── prune: (14) └── projections - └── plus [as="?column?":13, type=int, outer=(12), immutable] - ├── variable: c:12 [type=int] + └── plus [as="?column?":15, type=int, outer=(14), immutable] + ├── variable: c:14 [type=int] └── const: 1 [type=int] # Original CTE is inlined, adding "NOT MATERIALIZED" should not change the behavior. diff --git a/pkg/sql/opt/optbuilder/mutation_builder.go b/pkg/sql/opt/optbuilder/mutation_builder.go index b9d2f5d1741f..f528c9fb0e2a 100644 --- a/pkg/sql/opt/optbuilder/mutation_builder.go +++ b/pkg/sql/opt/optbuilder/mutation_builder.go @@ -1386,54 +1386,42 @@ func checkDatumTypeFitsColumnType(col *cat.Column, typ *types.T) { // addAssignmentCasts builds a projection that wraps mutation values with // assignment casts when possible so that the resulting columns have types -// identical to those in outTypes. If all the columns in inScope already have -// identical types, then no projection is built. If there is no valid assignment -// cast from a column type in inScope to the corresponding target column type, -// then this function will error. +// identical to those in outTypes. If there is no valid assignment cast from a +// column type in inScope to the corresponding target column type, then this +// function will error. +// +// Assignment casts are always wrap mutation columns even if the type of a +// mutation column is identical to its target type. This is required in order to +// correctly cast placeholder values. When a memo is built at PREPARE-time, the +// type of a placeholder value provided at EXECUTE-time cannot be known. If a +// value provided does not have a type identical to its target column's type, an +// assignment cast must be performed. If the value's type is the correct type, +// the assignment cast is a no-op. func (mb *mutationBuilder) addAssignmentCasts(inScope *scope, outTypes []*types.T) *scope { expr := inScope.expr.(memo.RelExpr) - // Do a quick check to see if any casts are needed. - castRequired := false - for i := 0; i < len(inScope.cols); i++ { - if !inScope.cols[i].typ.Identical(outTypes[i]) { - castRequired = true - break - } - } - if !castRequired { - // No mutation casts are needed. - return inScope - } - projectionScope := inScope.push() projectionScope.cols = make([]scopeColumn, 0, len(inScope.cols)) for i := 0; i < len(inScope.cols); i++ { srcType := inScope.cols[i].typ targetType := outTypes[i] - if !srcType.Identical(targetType) { - // Check if an assignment cast is available from the inScope column - // type to the out type. - if !tree.ValidCast(srcType, targetType, tree.CastContextAssignment) { - ord := mb.tabID.ColumnOrdinal(mb.targetColList[i]) - colName := string(mb.tab.Column(ord).ColName()) - err := pgerror.Newf(pgcode.DatatypeMismatch, - "value type %s doesn't match type %s of column %q", - srcType, targetType, tree.ErrNameString(colName)) - err = errors.WithHint(err, "you will need to rewrite or cast the expression") - panic(err) - } - - // Create a new column which casts the input column to the correct - // type. - variable := mb.b.factory.ConstructVariable(inScope.cols[i].id) - cast := mb.b.factory.ConstructAssignmentCast(variable, outTypes[i]) - mb.b.synthesizeColumn(projectionScope, inScope.cols[i].name, outTypes[i], nil /* expr */, cast) - } else { - // The column is already the correct type, so add it as a - // passthrough column. - projectionScope.appendColumn(&inScope.cols[i]) + // Check if an assignment cast is available from the inScope column + // type to the out type. + if !tree.ValidCast(srcType, targetType, tree.CastContextAssignment) { + ord := mb.tabID.ColumnOrdinal(mb.targetColList[i]) + colName := string(mb.tab.Column(ord).ColName()) + err := pgerror.Newf(pgcode.DatatypeMismatch, + "value type %s doesn't match type %s of column %q", + srcType, targetType, tree.ErrNameString(colName)) + err = errors.WithHint(err, "you will need to rewrite or cast the expression") + panic(err) } + + // Create a new column which casts the input column to the correct + // type. + variable := mb.b.factory.ConstructVariable(inScope.cols[i].id) + cast := mb.b.factory.ConstructAssignmentCast(variable, outTypes[i]) + mb.b.synthesizeColumn(projectionScope, inScope.cols[i].name, outTypes[i], nil /* expr */, cast) } projectionScope.expr = mb.b.constructProject(expr, projectionScope.cols) diff --git a/pkg/sql/opt/optbuilder/testdata/fk-checks-insert b/pkg/sql/opt/optbuilder/testdata/fk-checks-insert index 89feaa5659aa..dd6b8847ffa4 100644 --- a/pkg/sql/opt/optbuilder/testdata/fk-checks-insert +++ b/pkg/sql/opt/optbuilder/testdata/fk-checks-insert @@ -12,25 +12,32 @@ INSERT INTO child VALUES (100, 1), (200, 1) insert child ├── columns: ├── insert-mapping: - │ ├── column1:5 => c:1 - │ └── column2:6 => child.p:2 + │ ├── column1:7 => c:1 + │ └── column2:8 => child.p:2 ├── input binding: &1 - ├── values - │ ├── columns: column1:5!null column2:6!null - │ ├── (100, 1) - │ └── (200, 1) + ├── project + │ ├── columns: column1:7!null column2:8!null + │ ├── values + │ │ ├── columns: column1:5!null column2:6!null + │ │ ├── (100, 1) + │ │ └── (200, 1) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:7] + │ │ └── column1:5 + │ └── assignment-cast: INT8 [as=column2:8] + │ └── column2:6 └── f-k-checks └── f-k-checks-item: child(p) -> parent(p) └── anti-join (hash) - ├── columns: p:7!null + ├── columns: p:9!null ├── with-scan &1 - │ ├── columns: p:7!null + │ ├── columns: p:9!null │ └── mapping: - │ └── column2:6 => p:7 + │ └── column2:8 => p:9 ├── scan parent - │ └── columns: parent.p:8!null + │ └── columns: parent.p:10!null └── filters - └── p:7 = parent.p:8 + └── p:9 = parent.p:10 build INSERT INTO child VALUES (100, 1), (200, 1) ON CONFLICT DO NOTHING @@ -39,37 +46,44 @@ insert child ├── columns: ├── arbiter indexes: child_pkey ├── insert-mapping: - │ ├── column1:5 => c:1 - │ └── column2:6 => child.p:2 + │ ├── column1:7 => c:1 + │ └── column2:8 => child.p:2 ├── input binding: &1 ├── upsert-distinct-on - │ ├── columns: column1:5!null column2:6!null - │ ├── grouping columns: column1:5!null + │ ├── columns: column1:7!null column2:8!null + │ ├── grouping columns: column1:7!null │ ├── anti-join (hash) - │ │ ├── columns: column1:5!null column2:6!null - │ │ ├── values - │ │ │ ├── columns: column1:5!null column2:6!null - │ │ │ ├── (100, 1) - │ │ │ └── (200, 1) + │ │ ├── columns: column1:7!null column2:8!null + │ │ ├── project + │ │ │ ├── columns: column1:7!null column2:8!null + │ │ │ ├── values + │ │ │ │ ├── columns: column1:5!null column2:6!null + │ │ │ │ ├── (100, 1) + │ │ │ │ └── (200, 1) + │ │ │ └── projections + │ │ │ ├── assignment-cast: INT8 [as=column1:7] + │ │ │ │ └── column1:5 + │ │ │ └── assignment-cast: INT8 [as=column2:8] + │ │ │ └── column2:6 │ │ ├── scan child - │ │ │ └── columns: c:7!null child.p:8!null + │ │ │ └── columns: c:9!null child.p:10!null │ │ └── filters - │ │ └── column1:5 = c:7 + │ │ └── column1:7 = c:9 │ └── aggregations - │ └── first-agg [as=column2:6] - │ └── column2:6 + │ └── first-agg [as=column2:8] + │ └── column2:8 └── f-k-checks └── f-k-checks-item: child(p) -> parent(p) └── anti-join (hash) - ├── columns: p:11!null + ├── columns: p:13!null ├── with-scan &1 - │ ├── columns: p:11!null + │ ├── columns: p:13!null │ └── mapping: - │ └── column2:6 => p:11 + │ └── column2:8 => p:13 ├── scan parent - │ └── columns: parent.p:12!null + │ └── columns: parent.p:14!null └── filters - └── p:11 = parent.p:12 + └── p:13 = parent.p:14 # Use a non-constant input. exec-ddl @@ -82,25 +96,32 @@ INSERT INTO child SELECT x, y FROM xy insert child ├── columns: ├── insert-mapping: - │ ├── x:5 => c:1 - │ └── y:6 => child.p:2 + │ ├── x:10 => c:1 + │ └── y:11 => child.p:2 ├── input binding: &1 ├── project - │ ├── columns: x:5 y:6 - │ └── scan xy - │ └── columns: x:5 y:6 rowid:7!null xy.crdb_internal_mvcc_timestamp:8 xy.tableoid:9 + │ ├── columns: x:10 y:11 + │ ├── project + │ │ ├── columns: xy.x:5 xy.y:6 + │ │ └── scan xy + │ │ └── columns: xy.x:5 xy.y:6 rowid:7!null xy.crdb_internal_mvcc_timestamp:8 xy.tableoid:9 + │ └── projections + │ ├── assignment-cast: INT8 [as=x:10] + │ │ └── xy.x:5 + │ └── assignment-cast: INT8 [as=y:11] + │ └── xy.y:6 └── f-k-checks └── f-k-checks-item: child(p) -> parent(p) └── anti-join (hash) - ├── columns: p:10 + ├── columns: p:12 ├── with-scan &1 - │ ├── columns: p:10 + │ ├── columns: p:12 │ └── mapping: - │ └── y:6 => p:10 + │ └── y:11 => p:12 ├── scan parent - │ └── columns: parent.p:11!null + │ └── columns: parent.p:13!null └── filters - └── p:10 = parent.p:11 + └── p:12 = parent.p:13 exec-ddl CREATE TABLE child_nullable (c INT PRIMARY KEY, p INT REFERENCES parent(p)); @@ -114,29 +135,36 @@ INSERT INTO child_nullable VALUES (100, 1), (200, NULL) insert child_nullable ├── columns: ├── insert-mapping: - │ ├── column1:5 => c:1 - │ └── column2:6 => child_nullable.p:2 + │ ├── column1:7 => c:1 + │ └── column2:8 => child_nullable.p:2 ├── input binding: &1 - ├── values - │ ├── columns: column1:5!null column2:6 - │ ├── (100, 1) - │ └── (200, NULL::INT8) + ├── project + │ ├── columns: column1:7!null column2:8 + │ ├── values + │ │ ├── columns: column1:5!null column2:6 + │ │ ├── (100, 1) + │ │ └── (200, NULL::INT8) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:7] + │ │ └── column1:5 + │ └── assignment-cast: INT8 [as=column2:8] + │ └── column2:6 └── f-k-checks └── f-k-checks-item: child_nullable(p) -> parent(p) └── anti-join (hash) - ├── columns: p:7!null + ├── columns: p:9!null ├── select - │ ├── columns: p:7!null + │ ├── columns: p:9!null │ ├── with-scan &1 - │ │ ├── columns: p:7 + │ │ ├── columns: p:9 │ │ └── mapping: - │ │ └── column2:6 => p:7 + │ │ └── column2:8 => p:9 │ └── filters - │ └── p:7 IS NOT NULL + │ └── p:9 IS NOT NULL ├── scan parent - │ └── columns: parent.p:8!null + │ └── columns: parent.p:10!null └── filters - └── p:7 = parent.p:8 + └── p:9 = parent.p:10 # The column is nullable but we know that the input is not null, so we don't # need to plan the filter. @@ -146,25 +174,32 @@ INSERT INTO child_nullable VALUES (100, 1), (200, 1) insert child_nullable ├── columns: ├── insert-mapping: - │ ├── column1:5 => c:1 - │ └── column2:6 => child_nullable.p:2 + │ ├── column1:7 => c:1 + │ └── column2:8 => child_nullable.p:2 ├── input binding: &1 - ├── values - │ ├── columns: column1:5!null column2:6!null - │ ├── (100, 1) - │ └── (200, 1) + ├── project + │ ├── columns: column1:7!null column2:8!null + │ ├── values + │ │ ├── columns: column1:5!null column2:6!null + │ │ ├── (100, 1) + │ │ └── (200, 1) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:7] + │ │ └── column1:5 + │ └── assignment-cast: INT8 [as=column2:8] + │ └── column2:6 └── f-k-checks └── f-k-checks-item: child_nullable(p) -> parent(p) └── anti-join (hash) - ├── columns: p:7!null + ├── columns: p:9!null ├── with-scan &1 - │ ├── columns: p:7!null + │ ├── columns: p:9!null │ └── mapping: - │ └── column2:6 => p:7 + │ └── column2:8 => p:9 ├── scan parent - │ └── columns: parent.p:8!null + │ └── columns: parent.p:10!null └── filters - └── p:7 = parent.p:8 + └── p:9 = parent.p:10 # In this case, we know that we are inserting *only* NULL values, so we don't # need to check any FKs. @@ -174,12 +209,36 @@ INSERT INTO child_nullable VALUES (100, NULL), (200, NULL) insert child_nullable ├── columns: ├── insert-mapping: - │ ├── column1:5 => c:1 - │ └── column2:6 => p:2 - └── values - ├── columns: column1:5!null column2:6 - ├── (100, NULL::INT8) - └── (200, NULL::INT8) + │ ├── column1:7 => c:1 + │ └── column2:8 => child_nullable.p:2 + ├── input binding: &1 + ├── project + │ ├── columns: column1:7!null column2:8 + │ ├── values + │ │ ├── columns: column1:5!null column2:6 + │ │ ├── (100, NULL::INT8) + │ │ └── (200, NULL::INT8) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:7] + │ │ └── column1:5 + │ └── assignment-cast: INT8 [as=column2:8] + │ └── column2:6 + └── f-k-checks + └── f-k-checks-item: child_nullable(p) -> parent(p) + └── anti-join (hash) + ├── columns: p:9!null + ├── select + │ ├── columns: p:9!null + │ ├── with-scan &1 + │ │ ├── columns: p:9 + │ │ └── mapping: + │ │ └── column2:8 => p:9 + │ └── filters + │ └── p:9 IS NOT NULL + ├── scan parent + │ └── columns: parent.p:10!null + └── filters + └── p:9 = parent.p:10 # Same as above. build @@ -188,16 +247,21 @@ INSERT INTO child_nullable (c) VALUES (100), (200) insert child_nullable ├── columns: ├── insert-mapping: - │ ├── column1:5 => c:1 - │ └── p_default:6 => p:2 + │ ├── column1:6 => c:1 + │ └── p_default:7 => p:2 └── project - ├── columns: p_default:6 column1:5!null - ├── values - │ ├── columns: column1:5!null - │ ├── (100,) - │ └── (200,) + ├── columns: p_default:7 column1:6!null + ├── project + │ ├── columns: column1:6!null + │ ├── values + │ │ ├── columns: column1:5!null + │ │ ├── (100,) + │ │ └── (200,) + │ └── projections + │ └── assignment-cast: INT8 [as=column1:6] + │ └── column1:5 └── projections - └── NULL::INT8 [as=p_default:6] + └── NULL::INT8 [as=p_default:7] # Check planning of filter with FULL match (which should be the same on a # single column). @@ -211,29 +275,36 @@ INSERT INTO child_nullable_full VALUES (100, 1), (200, NULL) insert child_nullable_full ├── columns: ├── insert-mapping: - │ ├── column1:5 => c:1 - │ └── column2:6 => child_nullable_full.p:2 + │ ├── column1:7 => c:1 + │ └── column2:8 => child_nullable_full.p:2 ├── input binding: &1 - ├── values - │ ├── columns: column1:5!null column2:6 - │ ├── (100, 1) - │ └── (200, NULL::INT8) + ├── project + │ ├── columns: column1:7!null column2:8 + │ ├── values + │ │ ├── columns: column1:5!null column2:6 + │ │ ├── (100, 1) + │ │ └── (200, NULL::INT8) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:7] + │ │ └── column1:5 + │ └── assignment-cast: INT8 [as=column2:8] + │ └── column2:6 └── f-k-checks └── f-k-checks-item: child_nullable_full(p) -> parent(p) └── anti-join (hash) - ├── columns: p:7!null + ├── columns: p:9!null ├── select - │ ├── columns: p:7!null + │ ├── columns: p:9!null │ ├── with-scan &1 - │ │ ├── columns: p:7 + │ │ ├── columns: p:9 │ │ └── mapping: - │ │ └── column2:6 => p:7 + │ │ └── column2:8 => p:9 │ └── filters - │ └── p:7 IS NOT NULL + │ └── p:9 IS NOT NULL ├── scan parent - │ └── columns: parent.p:8!null + │ └── columns: parent.p:10!null └── filters - └── p:7 = parent.p:8 + └── p:9 = parent.p:10 # No FK check needed. build @@ -242,16 +313,21 @@ INSERT INTO child_nullable_full (c) VALUES (100), (200) insert child_nullable_full ├── columns: ├── insert-mapping: - │ ├── column1:5 => c:1 - │ └── p_default:6 => p:2 + │ ├── column1:6 => c:1 + │ └── p_default:7 => p:2 └── project - ├── columns: p_default:6 column1:5!null - ├── values - │ ├── columns: column1:5!null - │ ├── (100,) - │ └── (200,) + ├── columns: p_default:7 column1:6!null + ├── project + │ ├── columns: column1:6!null + │ ├── values + │ │ ├── columns: column1:5!null + │ │ ├── (100,) + │ │ └── (200,) + │ └── projections + │ └── assignment-cast: INT8 [as=column1:6] + │ └── column1:5 └── projections - └── NULL::INT8 [as=p_default:6] + └── NULL::INT8 [as=p_default:7] # Tests with multicolumn FKs. exec-ddl @@ -273,37 +349,48 @@ INSERT INTO multi_col_child VALUES (4, NULL, NULL, NULL), (5, 1, 2, 3) insert multi_col_child ├── columns: ├── insert-mapping: - │ ├── column1:7 => c:1 - │ ├── column2:8 => multi_col_child.p:2 - │ ├── column3:9 => multi_col_child.q:3 - │ └── column4:10 => multi_col_child.r:4 + │ ├── column1:11 => c:1 + │ ├── column2:12 => multi_col_child.p:2 + │ ├── column3:13 => multi_col_child.q:3 + │ └── column4:14 => multi_col_child.r:4 ├── input binding: &1 - ├── values - │ ├── columns: column1:7!null column2:8 column3:9 column4:10 - │ ├── (4, NULL::INT8, NULL::INT8, NULL::INT8) - │ └── (5, 1, 2, 3) + ├── project + │ ├── columns: column1:11!null column2:12 column3:13 column4:14 + │ ├── values + │ │ ├── columns: column1:7!null column2:8 column3:9 column4:10 + │ │ ├── (4, NULL::INT8, NULL::INT8, NULL::INT8) + │ │ └── (5, 1, 2, 3) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:11] + │ │ └── column1:7 + │ ├── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:8 + │ ├── assignment-cast: INT8 [as=column3:13] + │ │ └── column3:9 + │ └── assignment-cast: INT8 [as=column4:14] + │ └── column4:10 └── f-k-checks └── f-k-checks-item: multi_col_child(p,q,r) -> multi_col_parent(p,q,r) └── anti-join (hash) - ├── columns: p:11!null q:12!null r:13!null + ├── columns: p:15!null q:16!null r:17!null ├── select - │ ├── columns: p:11!null q:12!null r:13!null + │ ├── columns: p:15!null q:16!null r:17!null │ ├── with-scan &1 - │ │ ├── columns: p:11 q:12 r:13 + │ │ ├── columns: p:15 q:16 r:17 │ │ └── mapping: - │ │ ├── column2:8 => p:11 - │ │ ├── column3:9 => q:12 - │ │ └── column4:10 => r:13 + │ │ ├── column2:12 => p:15 + │ │ ├── column3:13 => q:16 + │ │ └── column4:14 => r:17 │ └── filters - │ ├── p:11 IS NOT NULL - │ ├── q:12 IS NOT NULL - │ └── r:13 IS NOT NULL + │ ├── p:15 IS NOT NULL + │ ├── q:16 IS NOT NULL + │ └── r:17 IS NOT NULL ├── scan multi_col_parent - │ └── columns: multi_col_parent.p:14!null multi_col_parent.q:15!null multi_col_parent.r:16!null + │ └── columns: multi_col_parent.p:18!null multi_col_parent.q:19!null multi_col_parent.r:20!null └── filters - ├── p:11 = multi_col_parent.p:14 - ├── q:12 = multi_col_parent.q:15 - └── r:13 = multi_col_parent.r:16 + ├── p:15 = multi_col_parent.p:18 + ├── q:16 = multi_col_parent.q:19 + └── r:17 = multi_col_parent.r:20 # Only p and q are nullable. build @@ -312,36 +399,47 @@ INSERT INTO multi_col_child VALUES (2, NULL, 20, 20), (3, 20, NULL, 20) insert multi_col_child ├── columns: ├── insert-mapping: - │ ├── column1:7 => c:1 - │ ├── column2:8 => multi_col_child.p:2 - │ ├── column3:9 => multi_col_child.q:3 - │ └── column4:10 => multi_col_child.r:4 + │ ├── column1:11 => c:1 + │ ├── column2:12 => multi_col_child.p:2 + │ ├── column3:13 => multi_col_child.q:3 + │ └── column4:14 => multi_col_child.r:4 ├── input binding: &1 - ├── values - │ ├── columns: column1:7!null column2:8 column3:9 column4:10!null - │ ├── (2, NULL::INT8, 20, 20) - │ └── (3, 20, NULL::INT8, 20) + ├── project + │ ├── columns: column1:11!null column2:12 column3:13 column4:14!null + │ ├── values + │ │ ├── columns: column1:7!null column2:8 column3:9 column4:10!null + │ │ ├── (2, NULL::INT8, 20, 20) + │ │ └── (3, 20, NULL::INT8, 20) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:11] + │ │ └── column1:7 + │ ├── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:8 + │ ├── assignment-cast: INT8 [as=column3:13] + │ │ └── column3:9 + │ └── assignment-cast: INT8 [as=column4:14] + │ └── column4:10 └── f-k-checks └── f-k-checks-item: multi_col_child(p,q,r) -> multi_col_parent(p,q,r) └── anti-join (hash) - ├── columns: p:11!null q:12!null r:13!null + ├── columns: p:15!null q:16!null r:17!null ├── select - │ ├── columns: p:11!null q:12!null r:13!null + │ ├── columns: p:15!null q:16!null r:17!null │ ├── with-scan &1 - │ │ ├── columns: p:11 q:12 r:13!null + │ │ ├── columns: p:15 q:16 r:17!null │ │ └── mapping: - │ │ ├── column2:8 => p:11 - │ │ ├── column3:9 => q:12 - │ │ └── column4:10 => r:13 + │ │ ├── column2:12 => p:15 + │ │ ├── column3:13 => q:16 + │ │ └── column4:14 => r:17 │ └── filters - │ ├── p:11 IS NOT NULL - │ └── q:12 IS NOT NULL + │ ├── p:15 IS NOT NULL + │ └── q:16 IS NOT NULL ├── scan multi_col_parent - │ └── columns: multi_col_parent.p:14!null multi_col_parent.q:15!null multi_col_parent.r:16!null + │ └── columns: multi_col_parent.p:18!null multi_col_parent.q:19!null multi_col_parent.r:20!null └── filters - ├── p:11 = multi_col_parent.p:14 - ├── q:12 = multi_col_parent.q:15 - └── r:13 = multi_col_parent.r:16 + ├── p:15 = multi_col_parent.p:18 + ├── q:16 = multi_col_parent.q:19 + └── r:17 = multi_col_parent.r:20 # All the FK columns are not-null; no filter necessary. build @@ -350,30 +448,41 @@ INSERT INTO multi_col_child VALUES (1, 10, 10, 10) insert multi_col_child ├── columns: ├── insert-mapping: - │ ├── column1:7 => c:1 - │ ├── column2:8 => multi_col_child.p:2 - │ ├── column3:9 => multi_col_child.q:3 - │ └── column4:10 => multi_col_child.r:4 + │ ├── column1:11 => c:1 + │ ├── column2:12 => multi_col_child.p:2 + │ ├── column3:13 => multi_col_child.q:3 + │ └── column4:14 => multi_col_child.r:4 ├── input binding: &1 - ├── values - │ ├── columns: column1:7!null column2:8!null column3:9!null column4:10!null - │ └── (1, 10, 10, 10) + ├── project + │ ├── columns: column1:11!null column2:12!null column3:13!null column4:14!null + │ ├── values + │ │ ├── columns: column1:7!null column2:8!null column3:9!null column4:10!null + │ │ └── (1, 10, 10, 10) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:11] + │ │ └── column1:7 + │ ├── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:8 + │ ├── assignment-cast: INT8 [as=column3:13] + │ │ └── column3:9 + │ └── assignment-cast: INT8 [as=column4:14] + │ └── column4:10 └── f-k-checks └── f-k-checks-item: multi_col_child(p,q,r) -> multi_col_parent(p,q,r) └── anti-join (hash) - ├── columns: p:11!null q:12!null r:13!null + ├── columns: p:15!null q:16!null r:17!null ├── with-scan &1 - │ ├── columns: p:11!null q:12!null r:13!null + │ ├── columns: p:15!null q:16!null r:17!null │ └── mapping: - │ ├── column2:8 => p:11 - │ ├── column3:9 => q:12 - │ └── column4:10 => r:13 + │ ├── column2:12 => p:15 + │ ├── column3:13 => q:16 + │ └── column4:14 => r:17 ├── scan multi_col_parent - │ └── columns: multi_col_parent.p:14!null multi_col_parent.q:15!null multi_col_parent.r:16!null + │ └── columns: multi_col_parent.p:18!null multi_col_parent.q:19!null multi_col_parent.r:20!null └── filters - ├── p:11 = multi_col_parent.p:14 - ├── q:12 = multi_col_parent.q:15 - └── r:13 = multi_col_parent.r:16 + ├── p:15 = multi_col_parent.p:18 + ├── q:16 = multi_col_parent.q:19 + └── r:17 = multi_col_parent.r:20 # No FK check needed - we have only NULL values for a FK column. build @@ -382,13 +491,45 @@ INSERT INTO multi_col_child VALUES (1, 10, NULL, 10) insert multi_col_child ├── columns: ├── insert-mapping: - │ ├── column1:7 => c:1 - │ ├── column2:8 => p:2 - │ ├── column3:9 => q:3 - │ └── column4:10 => r:4 - └── values - ├── columns: column1:7!null column2:8!null column3:9 column4:10!null - └── (1, 10, NULL::INT8, 10) + │ ├── column1:11 => c:1 + │ ├── column2:12 => multi_col_child.p:2 + │ ├── column3:13 => multi_col_child.q:3 + │ └── column4:14 => multi_col_child.r:4 + ├── input binding: &1 + ├── project + │ ├── columns: column1:11!null column2:12!null column3:13 column4:14!null + │ ├── values + │ │ ├── columns: column1:7!null column2:8!null column3:9 column4:10!null + │ │ └── (1, 10, NULL::INT8, 10) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:11] + │ │ └── column1:7 + │ ├── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:8 + │ ├── assignment-cast: INT8 [as=column3:13] + │ │ └── column3:9 + │ └── assignment-cast: INT8 [as=column4:14] + │ └── column4:10 + └── f-k-checks + └── f-k-checks-item: multi_col_child(p,q,r) -> multi_col_parent(p,q,r) + └── anti-join (hash) + ├── columns: p:15!null q:16!null r:17!null + ├── select + │ ├── columns: p:15!null q:16!null r:17!null + │ ├── with-scan &1 + │ │ ├── columns: p:15!null q:16 r:17!null + │ │ └── mapping: + │ │ ├── column2:12 => p:15 + │ │ ├── column3:13 => q:16 + │ │ └── column4:14 => r:17 + │ └── filters + │ └── q:16 IS NOT NULL + ├── scan multi_col_parent + │ └── columns: multi_col_parent.p:18!null multi_col_parent.q:19!null multi_col_parent.r:20!null + └── filters + ├── p:15 = multi_col_parent.p:18 + ├── q:16 = multi_col_parent.q:19 + └── r:17 = multi_col_parent.r:20 exec-ddl CREATE TABLE multi_col_child_full ( @@ -405,35 +546,46 @@ INSERT INTO multi_col_child_full VALUES (4, NULL, NULL, NULL), (5, 1, 2, 3) insert multi_col_child_full ├── columns: ├── insert-mapping: - │ ├── column1:7 => c:1 - │ ├── column2:8 => multi_col_child_full.p:2 - │ ├── column3:9 => multi_col_child_full.q:3 - │ └── column4:10 => multi_col_child_full.r:4 + │ ├── column1:11 => c:1 + │ ├── column2:12 => multi_col_child_full.p:2 + │ ├── column3:13 => multi_col_child_full.q:3 + │ └── column4:14 => multi_col_child_full.r:4 ├── input binding: &1 - ├── values - │ ├── columns: column1:7!null column2:8 column3:9 column4:10 - │ ├── (4, NULL::INT8, NULL::INT8, NULL::INT8) - │ └── (5, 1, 2, 3) + ├── project + │ ├── columns: column1:11!null column2:12 column3:13 column4:14 + │ ├── values + │ │ ├── columns: column1:7!null column2:8 column3:9 column4:10 + │ │ ├── (4, NULL::INT8, NULL::INT8, NULL::INT8) + │ │ └── (5, 1, 2, 3) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:11] + │ │ └── column1:7 + │ ├── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:8 + │ ├── assignment-cast: INT8 [as=column3:13] + │ │ └── column3:9 + │ └── assignment-cast: INT8 [as=column4:14] + │ └── column4:10 └── f-k-checks └── f-k-checks-item: multi_col_child_full(p,q,r) -> multi_col_parent(p,q,r) └── anti-join (hash) - ├── columns: p:11 q:12 r:13 + ├── columns: p:15 q:16 r:17 ├── select - │ ├── columns: p:11 q:12 r:13 + │ ├── columns: p:15 q:16 r:17 │ ├── with-scan &1 - │ │ ├── columns: p:11 q:12 r:13 + │ │ ├── columns: p:15 q:16 r:17 │ │ └── mapping: - │ │ ├── column2:8 => p:11 - │ │ ├── column3:9 => q:12 - │ │ └── column4:10 => r:13 + │ │ ├── column2:12 => p:15 + │ │ ├── column3:13 => q:16 + │ │ └── column4:14 => r:17 │ └── filters - │ └── ((p:11 IS NOT NULL) OR (q:12 IS NOT NULL)) OR (r:13 IS NOT NULL) + │ └── ((p:15 IS NOT NULL) OR (q:16 IS NOT NULL)) OR (r:17 IS NOT NULL) ├── scan multi_col_parent - │ └── columns: multi_col_parent.p:14!null multi_col_parent.q:15!null multi_col_parent.r:16!null + │ └── columns: multi_col_parent.p:18!null multi_col_parent.q:19!null multi_col_parent.r:20!null └── filters - ├── p:11 = multi_col_parent.p:14 - ├── q:12 = multi_col_parent.q:15 - └── r:13 = multi_col_parent.r:16 + ├── p:15 = multi_col_parent.p:18 + ├── q:16 = multi_col_parent.q:19 + └── r:17 = multi_col_parent.r:20 # Only p and q are nullable; no filter necessary. build @@ -442,31 +594,42 @@ INSERT INTO multi_col_child_full VALUES (2, NULL, 20, 20), (3, 20, NULL, 20) insert multi_col_child_full ├── columns: ├── insert-mapping: - │ ├── column1:7 => c:1 - │ ├── column2:8 => multi_col_child_full.p:2 - │ ├── column3:9 => multi_col_child_full.q:3 - │ └── column4:10 => multi_col_child_full.r:4 + │ ├── column1:11 => c:1 + │ ├── column2:12 => multi_col_child_full.p:2 + │ ├── column3:13 => multi_col_child_full.q:3 + │ └── column4:14 => multi_col_child_full.r:4 ├── input binding: &1 - ├── values - │ ├── columns: column1:7!null column2:8 column3:9 column4:10!null - │ ├── (2, NULL::INT8, 20, 20) - │ └── (3, 20, NULL::INT8, 20) + ├── project + │ ├── columns: column1:11!null column2:12 column3:13 column4:14!null + │ ├── values + │ │ ├── columns: column1:7!null column2:8 column3:9 column4:10!null + │ │ ├── (2, NULL::INT8, 20, 20) + │ │ └── (3, 20, NULL::INT8, 20) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:11] + │ │ └── column1:7 + │ ├── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:8 + │ ├── assignment-cast: INT8 [as=column3:13] + │ │ └── column3:9 + │ └── assignment-cast: INT8 [as=column4:14] + │ └── column4:10 └── f-k-checks └── f-k-checks-item: multi_col_child_full(p,q,r) -> multi_col_parent(p,q,r) └── anti-join (hash) - ├── columns: p:11 q:12 r:13!null + ├── columns: p:15 q:16 r:17!null ├── with-scan &1 - │ ├── columns: p:11 q:12 r:13!null + │ ├── columns: p:15 q:16 r:17!null │ └── mapping: - │ ├── column2:8 => p:11 - │ ├── column3:9 => q:12 - │ └── column4:10 => r:13 + │ ├── column2:12 => p:15 + │ ├── column3:13 => q:16 + │ └── column4:14 => r:17 ├── scan multi_col_parent - │ └── columns: multi_col_parent.p:14!null multi_col_parent.q:15!null multi_col_parent.r:16!null + │ └── columns: multi_col_parent.p:18!null multi_col_parent.q:19!null multi_col_parent.r:20!null └── filters - ├── p:11 = multi_col_parent.p:14 - ├── q:12 = multi_col_parent.q:15 - └── r:13 = multi_col_parent.r:16 + ├── p:15 = multi_col_parent.p:18 + ├── q:16 = multi_col_parent.q:19 + └── r:17 = multi_col_parent.r:20 # All the FK columns are not-null; no filter necessary. build @@ -475,30 +638,41 @@ INSERT INTO multi_col_child_full VALUES (1, 10, 10, 10) insert multi_col_child_full ├── columns: ├── insert-mapping: - │ ├── column1:7 => c:1 - │ ├── column2:8 => multi_col_child_full.p:2 - │ ├── column3:9 => multi_col_child_full.q:3 - │ └── column4:10 => multi_col_child_full.r:4 + │ ├── column1:11 => c:1 + │ ├── column2:12 => multi_col_child_full.p:2 + │ ├── column3:13 => multi_col_child_full.q:3 + │ └── column4:14 => multi_col_child_full.r:4 ├── input binding: &1 - ├── values - │ ├── columns: column1:7!null column2:8!null column3:9!null column4:10!null - │ └── (1, 10, 10, 10) + ├── project + │ ├── columns: column1:11!null column2:12!null column3:13!null column4:14!null + │ ├── values + │ │ ├── columns: column1:7!null column2:8!null column3:9!null column4:10!null + │ │ └── (1, 10, 10, 10) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:11] + │ │ └── column1:7 + │ ├── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:8 + │ ├── assignment-cast: INT8 [as=column3:13] + │ │ └── column3:9 + │ └── assignment-cast: INT8 [as=column4:14] + │ └── column4:10 └── f-k-checks └── f-k-checks-item: multi_col_child_full(p,q,r) -> multi_col_parent(p,q,r) └── anti-join (hash) - ├── columns: p:11!null q:12!null r:13!null + ├── columns: p:15!null q:16!null r:17!null ├── with-scan &1 - │ ├── columns: p:11!null q:12!null r:13!null + │ ├── columns: p:15!null q:16!null r:17!null │ └── mapping: - │ ├── column2:8 => p:11 - │ ├── column3:9 => q:12 - │ └── column4:10 => r:13 + │ ├── column2:12 => p:15 + │ ├── column3:13 => q:16 + │ └── column4:14 => r:17 ├── scan multi_col_parent - │ └── columns: multi_col_parent.p:14!null multi_col_parent.q:15!null multi_col_parent.r:16!null + │ └── columns: multi_col_parent.p:18!null multi_col_parent.q:19!null multi_col_parent.r:20!null └── filters - ├── p:11 = multi_col_parent.p:14 - ├── q:12 = multi_col_parent.q:15 - └── r:13 = multi_col_parent.r:16 + ├── p:15 = multi_col_parent.p:18 + ├── q:16 = multi_col_parent.q:19 + └── r:17 = multi_col_parent.r:20 # No FK check needed when all FK columns only have NULL values. build @@ -507,13 +681,45 @@ INSERT INTO multi_col_child_full VALUES (1, NULL, NULL, NULL) insert multi_col_child_full ├── columns: ├── insert-mapping: - │ ├── column1:7 => c:1 - │ ├── column2:8 => p:2 - │ ├── column3:9 => q:3 - │ └── column4:10 => r:4 - └── values - ├── columns: column1:7!null column2:8 column3:9 column4:10 - └── (1, NULL::INT8, NULL::INT8, NULL::INT8) + │ ├── column1:11 => c:1 + │ ├── column2:12 => multi_col_child_full.p:2 + │ ├── column3:13 => multi_col_child_full.q:3 + │ └── column4:14 => multi_col_child_full.r:4 + ├── input binding: &1 + ├── project + │ ├── columns: column1:11!null column2:12 column3:13 column4:14 + │ ├── values + │ │ ├── columns: column1:7!null column2:8 column3:9 column4:10 + │ │ └── (1, NULL::INT8, NULL::INT8, NULL::INT8) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:11] + │ │ └── column1:7 + │ ├── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:8 + │ ├── assignment-cast: INT8 [as=column3:13] + │ │ └── column3:9 + │ └── assignment-cast: INT8 [as=column4:14] + │ └── column4:10 + └── f-k-checks + └── f-k-checks-item: multi_col_child_full(p,q,r) -> multi_col_parent(p,q,r) + └── anti-join (hash) + ├── columns: p:15 q:16 r:17 + ├── select + │ ├── columns: p:15 q:16 r:17 + │ ├── with-scan &1 + │ │ ├── columns: p:15 q:16 r:17 + │ │ └── mapping: + │ │ ├── column2:12 => p:15 + │ │ ├── column3:13 => q:16 + │ │ └── column4:14 => r:17 + │ └── filters + │ └── ((p:15 IS NOT NULL) OR (q:16 IS NOT NULL)) OR (r:17 IS NOT NULL) + ├── scan multi_col_parent + │ └── columns: multi_col_parent.p:18!null multi_col_parent.q:19!null multi_col_parent.r:20!null + └── filters + ├── p:15 = multi_col_parent.p:18 + ├── q:16 = multi_col_parent.q:19 + └── r:17 = multi_col_parent.r:20 # But with MATCH FULL, the FK check is needed when only a subset of the columns # only have NULL values. @@ -523,30 +729,41 @@ INSERT INTO multi_col_child_full VALUES (1, NULL, 2, NULL) insert multi_col_child_full ├── columns: ├── insert-mapping: - │ ├── column1:7 => c:1 - │ ├── column2:8 => multi_col_child_full.p:2 - │ ├── column3:9 => multi_col_child_full.q:3 - │ └── column4:10 => multi_col_child_full.r:4 + │ ├── column1:11 => c:1 + │ ├── column2:12 => multi_col_child_full.p:2 + │ ├── column3:13 => multi_col_child_full.q:3 + │ └── column4:14 => multi_col_child_full.r:4 ├── input binding: &1 - ├── values - │ ├── columns: column1:7!null column2:8 column3:9!null column4:10 - │ └── (1, NULL::INT8, 2, NULL::INT8) + ├── project + │ ├── columns: column1:11!null column2:12 column3:13!null column4:14 + │ ├── values + │ │ ├── columns: column1:7!null column2:8 column3:9!null column4:10 + │ │ └── (1, NULL::INT8, 2, NULL::INT8) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:11] + │ │ └── column1:7 + │ ├── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:8 + │ ├── assignment-cast: INT8 [as=column3:13] + │ │ └── column3:9 + │ └── assignment-cast: INT8 [as=column4:14] + │ └── column4:10 └── f-k-checks └── f-k-checks-item: multi_col_child_full(p,q,r) -> multi_col_parent(p,q,r) └── anti-join (hash) - ├── columns: p:11 q:12!null r:13 + ├── columns: p:15 q:16!null r:17 ├── with-scan &1 - │ ├── columns: p:11 q:12!null r:13 + │ ├── columns: p:15 q:16!null r:17 │ └── mapping: - │ ├── column2:8 => p:11 - │ ├── column3:9 => q:12 - │ └── column4:10 => r:13 + │ ├── column2:12 => p:15 + │ ├── column3:13 => q:16 + │ └── column4:14 => r:17 ├── scan multi_col_parent - │ └── columns: multi_col_parent.p:14!null multi_col_parent.q:15!null multi_col_parent.r:16!null + │ └── columns: multi_col_parent.p:18!null multi_col_parent.q:19!null multi_col_parent.r:20!null └── filters - ├── p:11 = multi_col_parent.p:14 - ├── q:12 = multi_col_parent.q:15 - └── r:13 = multi_col_parent.r:16 + ├── p:15 = multi_col_parent.p:18 + ├── q:16 = multi_col_parent.q:19 + └── r:17 = multi_col_parent.r:20 exec-ddl CREATE TABLE multi_ref_parent_a (a INT PRIMARY KEY, other INT) @@ -573,50 +790,61 @@ INSERT INTO multi_ref_child VALUES (1, 1, NULL, NULL), (2, NULL, 2, NULL), (3, N insert multi_ref_child ├── columns: ├── insert-mapping: - │ ├── column1:7 => k:1 - │ ├── column2:8 => multi_ref_child.a:2 - │ ├── column3:9 => multi_ref_child.b:3 - │ └── column4:10 => multi_ref_child.c:4 + │ ├── column1:11 => k:1 + │ ├── column2:12 => multi_ref_child.a:2 + │ ├── column3:13 => multi_ref_child.b:3 + │ └── column4:14 => multi_ref_child.c:4 ├── input binding: &1 - ├── values - │ ├── columns: column1:7!null column2:8 column3:9 column4:10 - │ ├── (1, 1, NULL::INT8, NULL::INT8) - │ ├── (2, NULL::INT8, 2, NULL::INT8) - │ └── (3, NULL::INT8, NULL::INT8, 3) + ├── project + │ ├── columns: column1:11!null column2:12 column3:13 column4:14 + │ ├── values + │ │ ├── columns: column1:7!null column2:8 column3:9 column4:10 + │ │ ├── (1, 1, NULL::INT8, NULL::INT8) + │ │ ├── (2, NULL::INT8, 2, NULL::INT8) + │ │ └── (3, NULL::INT8, NULL::INT8, 3) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:11] + │ │ └── column1:7 + │ ├── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:8 + │ ├── assignment-cast: INT8 [as=column3:13] + │ │ └── column3:9 + │ └── assignment-cast: INT8 [as=column4:14] + │ └── column4:10 └── f-k-checks ├── f-k-checks-item: multi_ref_child(a) -> multi_ref_parent_a(a) │ └── anti-join (hash) - │ ├── columns: a:11!null + │ ├── columns: a:15!null │ ├── select - │ │ ├── columns: a:11!null + │ │ ├── columns: a:15!null │ │ ├── with-scan &1 - │ │ │ ├── columns: a:11 + │ │ │ ├── columns: a:15 │ │ │ └── mapping: - │ │ │ └── column2:8 => a:11 + │ │ │ └── column2:12 => a:15 │ │ └── filters - │ │ └── a:11 IS NOT NULL + │ │ └── a:15 IS NOT NULL │ ├── scan multi_ref_parent_a - │ │ └── columns: multi_ref_parent_a.a:12!null + │ │ └── columns: multi_ref_parent_a.a:16!null │ └── filters - │ └── a:11 = multi_ref_parent_a.a:12 + │ └── a:15 = multi_ref_parent_a.a:16 └── f-k-checks-item: multi_ref_child(b,c) -> multi_ref_parent_bc(b,c) └── anti-join (hash) - ├── columns: b:16!null c:17!null + ├── columns: b:20!null c:21!null ├── select - │ ├── columns: b:16!null c:17!null + │ ├── columns: b:20!null c:21!null │ ├── with-scan &1 - │ │ ├── columns: b:16 c:17 + │ │ ├── columns: b:20 c:21 │ │ └── mapping: - │ │ ├── column3:9 => b:16 - │ │ └── column4:10 => c:17 + │ │ ├── column3:13 => b:20 + │ │ └── column4:14 => c:21 │ └── filters - │ ├── b:16 IS NOT NULL - │ └── c:17 IS NOT NULL + │ ├── b:20 IS NOT NULL + │ └── c:21 IS NOT NULL ├── scan multi_ref_parent_bc - │ └── columns: multi_ref_parent_bc.b:18!null multi_ref_parent_bc.c:19!null + │ └── columns: multi_ref_parent_bc.b:22!null multi_ref_parent_bc.c:23!null └── filters - ├── b:16 = multi_ref_parent_bc.b:18 - └── c:17 = multi_ref_parent_bc.c:19 + ├── b:20 = multi_ref_parent_bc.b:22 + └── c:21 = multi_ref_parent_bc.c:23 build INSERT INTO multi_ref_child VALUES (1, NULL, NULL, NULL) @@ -624,13 +852,59 @@ INSERT INTO multi_ref_child VALUES (1, NULL, NULL, NULL) insert multi_ref_child ├── columns: ├── insert-mapping: - │ ├── column1:7 => k:1 - │ ├── column2:8 => a:2 - │ ├── column3:9 => b:3 - │ └── column4:10 => c:4 - └── values - ├── columns: column1:7!null column2:8 column3:9 column4:10 - └── (1, NULL::INT8, NULL::INT8, NULL::INT8) + │ ├── column1:11 => k:1 + │ ├── column2:12 => multi_ref_child.a:2 + │ ├── column3:13 => multi_ref_child.b:3 + │ └── column4:14 => multi_ref_child.c:4 + ├── input binding: &1 + ├── project + │ ├── columns: column1:11!null column2:12 column3:13 column4:14 + │ ├── values + │ │ ├── columns: column1:7!null column2:8 column3:9 column4:10 + │ │ └── (1, NULL::INT8, NULL::INT8, NULL::INT8) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:11] + │ │ └── column1:7 + │ ├── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:8 + │ ├── assignment-cast: INT8 [as=column3:13] + │ │ └── column3:9 + │ └── assignment-cast: INT8 [as=column4:14] + │ └── column4:10 + └── f-k-checks + ├── f-k-checks-item: multi_ref_child(a) -> multi_ref_parent_a(a) + │ └── anti-join (hash) + │ ├── columns: a:15!null + │ ├── select + │ │ ├── columns: a:15!null + │ │ ├── with-scan &1 + │ │ │ ├── columns: a:15 + │ │ │ └── mapping: + │ │ │ └── column2:12 => a:15 + │ │ └── filters + │ │ └── a:15 IS NOT NULL + │ ├── scan multi_ref_parent_a + │ │ └── columns: multi_ref_parent_a.a:16!null + │ └── filters + │ └── a:15 = multi_ref_parent_a.a:16 + └── f-k-checks-item: multi_ref_child(b,c) -> multi_ref_parent_bc(b,c) + └── anti-join (hash) + ├── columns: b:20!null c:21!null + ├── select + │ ├── columns: b:20!null c:21!null + │ ├── with-scan &1 + │ │ ├── columns: b:20 c:21 + │ │ └── mapping: + │ │ ├── column3:13 => b:20 + │ │ └── column4:14 => c:21 + │ └── filters + │ ├── b:20 IS NOT NULL + │ └── c:21 IS NOT NULL + ├── scan multi_ref_parent_bc + │ └── columns: multi_ref_parent_bc.b:22!null multi_ref_parent_bc.c:23!null + └── filters + ├── b:20 = multi_ref_parent_bc.b:22 + └── c:21 = multi_ref_parent_bc.c:23 # Verify that the join hint is set. build prefer-lookup-joins-for-fks @@ -639,23 +913,30 @@ INSERT INTO child VALUES (100, 1), (200, 1) insert child ├── columns: ├── insert-mapping: - │ ├── column1:5 => c:1 - │ └── column2:6 => child.p:2 + │ ├── column1:7 => c:1 + │ └── column2:8 => child.p:2 ├── input binding: &1 - ├── values - │ ├── columns: column1:5!null column2:6!null - │ ├── (100, 1) - │ └── (200, 1) + ├── project + │ ├── columns: column1:7!null column2:8!null + │ ├── values + │ │ ├── columns: column1:5!null column2:6!null + │ │ ├── (100, 1) + │ │ └── (200, 1) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:7] + │ │ └── column1:5 + │ └── assignment-cast: INT8 [as=column2:8] + │ └── column2:6 └── f-k-checks └── f-k-checks-item: child(p) -> parent(p) └── anti-join (hash) - ├── columns: p:7!null + ├── columns: p:9!null ├── flags: prefer lookup join (into right side) ├── with-scan &1 - │ ├── columns: p:7!null + │ ├── columns: p:9!null │ └── mapping: - │ └── column2:6 => p:7 + │ └── column2:8 => p:9 ├── scan parent - │ └── columns: parent.p:8!null + │ └── columns: parent.p:10!null └── filters - └── p:7 = parent.p:8 + └── p:9 = parent.p:10 diff --git a/pkg/sql/opt/optbuilder/testdata/insert b/pkg/sql/opt/optbuilder/testdata/insert index 8254b1ccf8fb..a08f97e17ac9 100644 --- a/pkg/sql/opt/optbuilder/testdata/insert +++ b/pkg/sql/opt/optbuilder/testdata/insert @@ -93,23 +93,32 @@ INSERT INTO abcde VALUES (1, 2, 3) insert abcde ├── columns: ├── insert-mapping: - │ ├── column1:9 => a:1 - │ ├── column2:10 => b:2 - │ ├── column3:11 => c:3 - │ ├── d_comp:13 => d:4 - │ ├── column1:9 => e:5 - │ └── rowid_default:12 => rowid:6 + │ ├── column1:12 => a:1 + │ ├── column2:13 => b:2 + │ ├── column3:14 => c:3 + │ ├── d_comp:16 => d:4 + │ ├── column1:12 => e:5 + │ └── rowid_default:15 => rowid:6 └── project - ├── columns: d_comp:13!null column1:9!null column2:10!null column3:11!null rowid_default:12 + ├── columns: d_comp:16!null column1:12!null column2:13!null column3:14!null rowid_default:15 ├── project - │ ├── columns: rowid_default:12 column1:9!null column2:10!null column3:11!null - │ ├── values - │ │ ├── columns: column1:9!null column2:10!null column3:11!null - │ │ └── (1, 2, 3) + │ ├── columns: rowid_default:15 column1:12!null column2:13!null column3:14!null + │ ├── project + │ │ ├── columns: column1:12!null column2:13!null column3:14!null + │ │ ├── values + │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ └── (1, 2, 3) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:12] + │ │ │ └── column1:9 + │ │ ├── assignment-cast: INT8 [as=column2:13] + │ │ │ └── column2:10 + │ │ └── assignment-cast: INT8 [as=column3:14] + │ │ └── column3:11 │ └── projections - │ └── unique_rowid() [as=rowid_default:12] + │ └── unique_rowid() [as=rowid_default:15] └── projections - └── (column2:10 + column3:11) + 1 [as=d_comp:13] + └── (column2:13 + column3:14) + 1 [as=d_comp:16] # Don't specify values for null or default columns. build @@ -118,25 +127,30 @@ INSERT INTO abcde VALUES (1) insert abcde ├── columns: ├── insert-mapping: - │ ├── column1:9 => a:1 - │ ├── b_default:10 => b:2 - │ ├── c_default:11 => c:3 - │ ├── d_comp:13 => d:4 - │ ├── column1:9 => e:5 - │ └── rowid_default:12 => rowid:6 + │ ├── column1:10 => a:1 + │ ├── b_default:11 => b:2 + │ ├── c_default:12 => c:3 + │ ├── d_comp:14 => d:4 + │ ├── column1:10 => e:5 + │ └── rowid_default:13 => rowid:6 └── project - ├── columns: d_comp:13 column1:9!null b_default:10 c_default:11!null rowid_default:12 + ├── columns: d_comp:14 column1:10!null b_default:11 c_default:12!null rowid_default:13 ├── project - │ ├── columns: b_default:10 c_default:11!null rowid_default:12 column1:9!null - │ ├── values - │ │ ├── columns: column1:9!null - │ │ └── (1,) + │ ├── columns: b_default:11 c_default:12!null rowid_default:13 column1:10!null + │ ├── project + │ │ ├── columns: column1:10!null + │ │ ├── values + │ │ │ ├── columns: column1:9!null + │ │ │ └── (1,) + │ │ └── projections + │ │ └── assignment-cast: INT8 [as=column1:10] + │ │ └── column1:9 │ └── projections - │ ├── NULL::INT8 [as=b_default:10] - │ ├── 10 [as=c_default:11] - │ └── unique_rowid() [as=rowid_default:12] + │ ├── NULL::INT8 [as=b_default:11] + │ ├── 10 [as=c_default:12] + │ └── unique_rowid() [as=rowid_default:13] └── projections - └── (b_default:10 + c_default:11) + 1 [as=d_comp:13] + └── (b_default:11 + c_default:12) + 1 [as=d_comp:14] # Ordered input. build @@ -145,34 +159,39 @@ INSERT INTO abcde SELECT y FROM xyz ORDER BY y, z LIMIT 10 insert abcde ├── columns: ├── insert-mapping: - │ ├── y:10 => a:1 - │ ├── b_default:14 => b:2 - │ ├── c_default:15 => c:3 - │ ├── d_comp:17 => d:4 - │ ├── y:10 => e:5 - │ └── rowid_default:16 => rowid:6 + │ ├── y:14 => a:1 + │ ├── b_default:15 => b:2 + │ ├── c_default:16 => c:3 + │ ├── d_comp:18 => d:4 + │ ├── y:14 => e:5 + │ └── rowid_default:17 => rowid:6 └── project - ├── columns: d_comp:17 y:10 b_default:14 c_default:15!null rowid_default:16 + ├── columns: d_comp:18 y:14 b_default:15 c_default:16!null rowid_default:17 ├── project - │ ├── columns: b_default:14 c_default:15!null rowid_default:16 y:10 - │ ├── limit - │ │ ├── columns: y:10 z:11 - │ │ ├── internal-ordering: +10,+11 - │ │ ├── sort - │ │ │ ├── columns: y:10 z:11 - │ │ │ ├── ordering: +10,+11 - │ │ │ ├── limit hint: 10.00 - │ │ │ └── project - │ │ │ ├── columns: y:10 z:11 - │ │ │ └── scan xyz - │ │ │ └── columns: x:9!null y:10 z:11 xyz.crdb_internal_mvcc_timestamp:12 xyz.tableoid:13 - │ │ └── 10 + │ ├── columns: b_default:15 c_default:16!null rowid_default:17 y:14 + │ ├── project + │ │ ├── columns: y:14 + │ │ ├── limit + │ │ │ ├── columns: xyz.y:10 z:11 + │ │ │ ├── internal-ordering: +10,+11 + │ │ │ ├── sort + │ │ │ │ ├── columns: xyz.y:10 z:11 + │ │ │ │ ├── ordering: +10,+11 + │ │ │ │ ├── limit hint: 10.00 + │ │ │ │ └── project + │ │ │ │ ├── columns: xyz.y:10 z:11 + │ │ │ │ └── scan xyz + │ │ │ │ └── columns: x:9!null xyz.y:10 z:11 xyz.crdb_internal_mvcc_timestamp:12 xyz.tableoid:13 + │ │ │ └── 10 + │ │ └── projections + │ │ └── assignment-cast: INT8 [as=y:14] + │ │ └── xyz.y:10 │ └── projections - │ ├── NULL::INT8 [as=b_default:14] - │ ├── 10 [as=c_default:15] - │ └── unique_rowid() [as=rowid_default:16] + │ ├── NULL::INT8 [as=b_default:15] + │ ├── 10 [as=c_default:16] + │ └── unique_rowid() [as=rowid_default:17] └── projections - └── (b_default:14 + c_default:15) + 1 [as=d_comp:17] + └── (b_default:15 + c_default:16) + 1 [as=d_comp:18] # Ignore ORDER BY without LIMIT. build @@ -181,26 +200,31 @@ INSERT INTO abcde SELECT y FROM xyz ORDER BY y, z insert abcde ├── columns: ├── insert-mapping: - │ ├── y:10 => a:1 - │ ├── b_default:14 => b:2 - │ ├── c_default:15 => c:3 - │ ├── d_comp:17 => d:4 - │ ├── y:10 => e:5 - │ └── rowid_default:16 => rowid:6 + │ ├── y:14 => a:1 + │ ├── b_default:15 => b:2 + │ ├── c_default:16 => c:3 + │ ├── d_comp:18 => d:4 + │ ├── y:14 => e:5 + │ └── rowid_default:17 => rowid:6 └── project - ├── columns: d_comp:17 y:10 b_default:14 c_default:15!null rowid_default:16 + ├── columns: d_comp:18 y:14 b_default:15 c_default:16!null rowid_default:17 ├── project - │ ├── columns: b_default:14 c_default:15!null rowid_default:16 y:10 + │ ├── columns: b_default:15 c_default:16!null rowid_default:17 y:14 │ ├── project - │ │ ├── columns: y:10 z:11 - │ │ └── scan xyz - │ │ └── columns: x:9!null y:10 z:11 xyz.crdb_internal_mvcc_timestamp:12 xyz.tableoid:13 + │ │ ├── columns: y:14 + │ │ ├── project + │ │ │ ├── columns: xyz.y:10 z:11 + │ │ │ └── scan xyz + │ │ │ └── columns: x:9!null xyz.y:10 z:11 xyz.crdb_internal_mvcc_timestamp:12 xyz.tableoid:13 + │ │ └── projections + │ │ └── assignment-cast: INT8 [as=y:14] + │ │ └── xyz.y:10 │ └── projections - │ ├── NULL::INT8 [as=b_default:14] - │ ├── 10 [as=c_default:15] - │ └── unique_rowid() [as=rowid_default:16] + │ ├── NULL::INT8 [as=b_default:15] + │ ├── 10 [as=c_default:16] + │ └── unique_rowid() [as=rowid_default:17] └── projections - └── (b_default:14 + c_default:15) + 1 [as=d_comp:17] + └── (b_default:15 + c_default:16) + 1 [as=d_comp:18] # Use placeholders. build @@ -209,12 +233,21 @@ INSERT INTO xyz VALUES ($1, $2, $3) insert xyz ├── columns: ├── insert-mapping: - │ ├── column1:6 => x:1 - │ ├── column2:7 => y:2 - │ └── column3:8 => z:3 - └── values - ├── columns: column1:6 column2:7 column3:8 - └── ($1, $2, $3) + │ ├── column1:9 => x:1 + │ ├── column2:10 => y:2 + │ └── column3:11 => z:3 + └── project + ├── columns: column1:9 column2:10 column3:11 + ├── values + │ ├── columns: column1:6 column2:7 column3:8 + │ └── ($1, $2, $3) + └── projections + ├── assignment-cast: STRING [as=column1:9] + │ └── column1:6 + ├── assignment-cast: INT8 [as=column2:10] + │ └── column2:7 + └── assignment-cast: FLOAT8 [as=column3:11] + └── column3:8 # Null expressions. build @@ -223,23 +256,32 @@ INSERT INTO abcde VALUES (2, null, null) insert abcde ├── columns: ├── insert-mapping: - │ ├── column1:9 => a:1 - │ ├── column2:10 => b:2 - │ ├── column3:11 => c:3 - │ ├── d_comp:13 => d:4 - │ ├── column1:9 => e:5 - │ └── rowid_default:12 => rowid:6 + │ ├── column1:12 => a:1 + │ ├── column2:13 => b:2 + │ ├── column3:14 => c:3 + │ ├── d_comp:16 => d:4 + │ ├── column1:12 => e:5 + │ └── rowid_default:15 => rowid:6 └── project - ├── columns: d_comp:13 column1:9!null column2:10 column3:11 rowid_default:12 + ├── columns: d_comp:16 column1:12!null column2:13 column3:14 rowid_default:15 ├── project - │ ├── columns: rowid_default:12 column1:9!null column2:10 column3:11 - │ ├── values - │ │ ├── columns: column1:9!null column2:10 column3:11 - │ │ └── (2, NULL::INT8, NULL::INT8) + │ ├── columns: rowid_default:15 column1:12!null column2:13 column3:14 + │ ├── project + │ │ ├── columns: column1:12!null column2:13 column3:14 + │ │ ├── values + │ │ │ ├── columns: column1:9!null column2:10 column3:11 + │ │ │ └── (2, NULL::INT8, NULL::INT8) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:12] + │ │ │ └── column1:9 + │ │ ├── assignment-cast: INT8 [as=column2:13] + │ │ │ └── column2:10 + │ │ └── assignment-cast: INT8 [as=column3:14] + │ │ └── column3:11 │ └── projections - │ └── unique_rowid() [as=rowid_default:12] + │ └── unique_rowid() [as=rowid_default:15] └── projections - └── (column2:10 + column3:11) + 1 [as=d_comp:13] + └── (column2:13 + column3:14) + 1 [as=d_comp:16] # Duplicate expressions. build @@ -248,27 +290,36 @@ INSERT INTO abcde SELECT 2, $1 + 1, $1 + 1 insert abcde ├── columns: ├── insert-mapping: - │ ├── "?column?":9 => a:1 - │ ├── "?column?":10 => b:2 - │ ├── "?column?":10 => c:3 - │ ├── d_comp:12 => d:4 - │ ├── "?column?":9 => e:5 - │ └── rowid_default:11 => rowid:6 + │ ├── "?column?":11 => a:1 + │ ├── "?column?":12 => b:2 + │ ├── "?column?":13 => c:3 + │ ├── d_comp:15 => d:4 + │ ├── "?column?":11 => e:5 + │ └── rowid_default:14 => rowid:6 └── project - ├── columns: d_comp:12 "?column?":9!null "?column?":10 rowid_default:11 + ├── columns: d_comp:15 "?column?":11!null "?column?":12 "?column?":13 rowid_default:14 ├── project - │ ├── columns: rowid_default:11 "?column?":9!null "?column?":10 + │ ├── columns: rowid_default:14 "?column?":11!null "?column?":12 "?column?":13 │ ├── project - │ │ ├── columns: "?column?":9!null "?column?":10 - │ │ ├── values - │ │ │ └── () + │ │ ├── columns: "?column?":11!null "?column?":12 "?column?":13 + │ │ ├── project + │ │ │ ├── columns: "?column?":9!null "?column?":10 + │ │ │ ├── values + │ │ │ │ └── () + │ │ │ └── projections + │ │ │ ├── 2 [as="?column?":9] + │ │ │ └── $1 + 1 [as="?column?":10] │ │ └── projections - │ │ ├── 2 [as="?column?":9] - │ │ └── $1 + 1 [as="?column?":10] + │ │ ├── assignment-cast: INT8 [as="?column?":11] + │ │ │ └── "?column?":9 + │ │ ├── assignment-cast: INT8 [as="?column?":12] + │ │ │ └── "?column?":10 + │ │ └── assignment-cast: INT8 [as="?column?":13] + │ │ └── "?column?":10 │ └── projections - │ └── unique_rowid() [as=rowid_default:11] + │ └── unique_rowid() [as=rowid_default:14] └── projections - └── ("?column?":10 + "?column?":10) + 1 [as=d_comp:12] + └── ("?column?":12 + "?column?":13) + 1 [as=d_comp:15] # Use DEFAULT VALUES. build @@ -296,26 +347,35 @@ INSERT INTO abcde ((VALUES (1, DEFAULT, 2), (2, 3, 4), (3, 2, DEFAULT), (4, DEFA insert abcde ├── columns: ├── insert-mapping: - │ ├── column1:9 => a:1 - │ ├── column2:10 => b:2 - │ ├── column3:11 => c:3 - │ ├── d_comp:13 => d:4 - │ ├── column1:9 => e:5 - │ └── rowid_default:12 => rowid:6 + │ ├── column1:12 => a:1 + │ ├── column2:13 => b:2 + │ ├── column3:14 => c:3 + │ ├── d_comp:16 => d:4 + │ ├── column1:12 => e:5 + │ └── rowid_default:15 => rowid:6 └── project - ├── columns: d_comp:13 column1:9!null column2:10 column3:11!null rowid_default:12 + ├── columns: d_comp:16 column1:12!null column2:13 column3:14!null rowid_default:15 ├── project - │ ├── columns: rowid_default:12 column1:9!null column2:10 column3:11!null - │ ├── values - │ │ ├── columns: column1:9!null column2:10 column3:11!null - │ │ ├── (1, NULL::INT8, 2) - │ │ ├── (2, 3, 4) - │ │ ├── (3, 2, 10) - │ │ └── (4, NULL::INT8, 10) + │ ├── columns: rowid_default:15 column1:12!null column2:13 column3:14!null + │ ├── project + │ │ ├── columns: column1:12!null column2:13 column3:14!null + │ │ ├── values + │ │ │ ├── columns: column1:9!null column2:10 column3:11!null + │ │ │ ├── (1, NULL::INT8, 2) + │ │ │ ├── (2, 3, 4) + │ │ │ ├── (3, 2, 10) + │ │ │ └── (4, NULL::INT8, 10) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:12] + │ │ │ └── column1:9 + │ │ ├── assignment-cast: INT8 [as=column2:13] + │ │ │ └── column2:10 + │ │ └── assignment-cast: INT8 [as=column3:14] + │ │ └── column3:11 │ └── projections - │ └── unique_rowid() [as=rowid_default:12] + │ └── unique_rowid() [as=rowid_default:15] └── projections - └── (column2:10 + column3:11) + 1 [as=d_comp:13] + └── (column2:13 + column3:14) + 1 [as=d_comp:16] # Use DEFAULT expressions in VALUES expression wrapped by WITH clause (error). build @@ -338,102 +398,117 @@ project └── insert abcde ├── columns: a:1!null b:2 c:3!null d:4 e:5!null rowid:6!null ├── insert-mapping: - │ ├── "?column?":9 => a:1 - │ ├── b_default:10 => b:2 - │ ├── c_default:11 => c:3 - │ ├── d_comp:13 => d:4 - │ ├── "?column?":9 => e:5 - │ └── rowid_default:12 => rowid:6 + │ ├── "?column?":10 => a:1 + │ ├── b_default:11 => b:2 + │ ├── c_default:12 => c:3 + │ ├── d_comp:14 => d:4 + │ ├── "?column?":10 => e:5 + │ └── rowid_default:13 => rowid:6 └── project - ├── columns: d_comp:13 "?column?":9!null b_default:10 c_default:11!null rowid_default:12 + ├── columns: d_comp:14 "?column?":10!null b_default:11 c_default:12!null rowid_default:13 ├── project - │ ├── columns: b_default:10 c_default:11!null rowid_default:12 "?column?":9!null + │ ├── columns: b_default:11 c_default:12!null rowid_default:13 "?column?":10!null │ ├── project - │ │ ├── columns: "?column?":9!null - │ │ ├── values - │ │ │ └── () + │ │ ├── columns: "?column?":10!null + │ │ ├── project + │ │ │ ├── columns: "?column?":9!null + │ │ │ ├── values + │ │ │ │ └── () + │ │ │ └── projections + │ │ │ └── 1 [as="?column?":9] │ │ └── projections - │ │ └── 1 [as="?column?":9] + │ │ └── assignment-cast: INT8 [as="?column?":10] + │ │ └── "?column?":9 │ └── projections - │ ├── NULL::INT8 [as=b_default:10] - │ ├── 10 [as=c_default:11] - │ └── unique_rowid() [as=rowid_default:12] + │ ├── NULL::INT8 [as=b_default:11] + │ ├── 10 [as=c_default:12] + │ └── unique_rowid() [as=rowid_default:13] └── projections - └── (b_default:10 + c_default:11) + 1 [as=d_comp:13] + └── (b_default:11 + c_default:12) + 1 [as=d_comp:14] # Return values from aliased table. build INSERT INTO abcde AS foo SELECT 1 RETURNING foo.a + 1, foo.b * foo.c ---- project - ├── columns: "?column?":14!null "?column?":15 + ├── columns: "?column?":15!null "?column?":16 ├── insert abcde [as=foo] │ ├── columns: a:1!null b:2 c:3!null d:4 e:5!null rowid:6!null │ ├── insert-mapping: - │ │ ├── "?column?":9 => a:1 - │ │ ├── b_default:10 => b:2 - │ │ ├── c_default:11 => c:3 - │ │ ├── d_comp:13 => d:4 - │ │ ├── "?column?":9 => e:5 - │ │ └── rowid_default:12 => rowid:6 + │ │ ├── "?column?":10 => a:1 + │ │ ├── b_default:11 => b:2 + │ │ ├── c_default:12 => c:3 + │ │ ├── d_comp:14 => d:4 + │ │ ├── "?column?":10 => e:5 + │ │ └── rowid_default:13 => rowid:6 │ └── project - │ ├── columns: d_comp:13 "?column?":9!null b_default:10 c_default:11!null rowid_default:12 + │ ├── columns: d_comp:14 "?column?":10!null b_default:11 c_default:12!null rowid_default:13 │ ├── project - │ │ ├── columns: b_default:10 c_default:11!null rowid_default:12 "?column?":9!null + │ │ ├── columns: b_default:11 c_default:12!null rowid_default:13 "?column?":10!null │ │ ├── project - │ │ │ ├── columns: "?column?":9!null - │ │ │ ├── values - │ │ │ │ └── () + │ │ │ ├── columns: "?column?":10!null + │ │ │ ├── project + │ │ │ │ ├── columns: "?column?":9!null + │ │ │ │ ├── values + │ │ │ │ │ └── () + │ │ │ │ └── projections + │ │ │ │ └── 1 [as="?column?":9] │ │ │ └── projections - │ │ │ └── 1 [as="?column?":9] + │ │ │ └── assignment-cast: INT8 [as="?column?":10] + │ │ │ └── "?column?":9 │ │ └── projections - │ │ ├── NULL::INT8 [as=b_default:10] - │ │ ├── 10 [as=c_default:11] - │ │ └── unique_rowid() [as=rowid_default:12] + │ │ ├── NULL::INT8 [as=b_default:11] + │ │ ├── 10 [as=c_default:12] + │ │ └── unique_rowid() [as=rowid_default:13] │ └── projections - │ └── (b_default:10 + c_default:11) + 1 [as=d_comp:13] + │ └── (b_default:11 + c_default:12) + 1 [as=d_comp:14] └── projections - ├── a:1 + 1 [as="?column?":14] - └── b:2 * c:3 [as="?column?":15] + ├── a:1 + 1 [as="?column?":15] + └── b:2 * c:3 [as="?column?":16] # Use returning INSERT as a FROM expression. build SELECT * FROM [INSERT INTO abcde VALUES (1) RETURNING *] ---- with &1 - ├── columns: a:14!null b:15 c:16!null d:17 e:18!null + ├── columns: a:15!null b:16 c:17!null d:18 e:19!null ├── project │ ├── columns: abcde.a:1!null abcde.b:2 abcde.c:3!null abcde.d:4 abcde.e:5!null │ └── insert abcde │ ├── columns: abcde.a:1!null abcde.b:2 abcde.c:3!null abcde.d:4 abcde.e:5!null rowid:6!null │ ├── insert-mapping: - │ │ ├── column1:9 => abcde.a:1 - │ │ ├── b_default:10 => abcde.b:2 - │ │ ├── c_default:11 => abcde.c:3 - │ │ ├── d_comp:13 => abcde.d:4 - │ │ ├── column1:9 => abcde.e:5 - │ │ └── rowid_default:12 => rowid:6 + │ │ ├── column1:10 => abcde.a:1 + │ │ ├── b_default:11 => abcde.b:2 + │ │ ├── c_default:12 => abcde.c:3 + │ │ ├── d_comp:14 => abcde.d:4 + │ │ ├── column1:10 => abcde.e:5 + │ │ └── rowid_default:13 => rowid:6 │ └── project - │ ├── columns: d_comp:13 column1:9!null b_default:10 c_default:11!null rowid_default:12 + │ ├── columns: d_comp:14 column1:10!null b_default:11 c_default:12!null rowid_default:13 │ ├── project - │ │ ├── columns: b_default:10 c_default:11!null rowid_default:12 column1:9!null - │ │ ├── values - │ │ │ ├── columns: column1:9!null - │ │ │ └── (1,) + │ │ ├── columns: b_default:11 c_default:12!null rowid_default:13 column1:10!null + │ │ ├── project + │ │ │ ├── columns: column1:10!null + │ │ │ ├── values + │ │ │ │ ├── columns: column1:9!null + │ │ │ │ └── (1,) + │ │ │ └── projections + │ │ │ └── assignment-cast: INT8 [as=column1:10] + │ │ │ └── column1:9 │ │ └── projections - │ │ ├── NULL::INT8 [as=b_default:10] - │ │ ├── 10 [as=c_default:11] - │ │ └── unique_rowid() [as=rowid_default:12] + │ │ ├── NULL::INT8 [as=b_default:11] + │ │ ├── 10 [as=c_default:12] + │ │ └── unique_rowid() [as=rowid_default:13] │ └── projections - │ └── (b_default:10 + c_default:11) + 1 [as=d_comp:13] + │ └── (b_default:11 + c_default:12) + 1 [as=d_comp:14] └── with-scan &1 - ├── columns: a:14!null b:15 c:16!null d:17 e:18!null + ├── columns: a:15!null b:16 c:17!null d:18 e:19!null └── mapping: - ├── abcde.a:1 => a:14 - ├── abcde.b:2 => b:15 - ├── abcde.c:3 => c:16 - ├── abcde.d:4 => d:17 - └── abcde.e:5 => e:18 + ├── abcde.a:1 => a:15 + ├── abcde.b:2 => b:16 + ├── abcde.c:3 => c:17 + ├── abcde.d:4 => d:18 + └── abcde.e:5 => e:19 # Try to use aggregate function in RETURNING clause. build @@ -467,26 +542,33 @@ with &1 (a) └── insert abcde ├── columns: ├── insert-mapping: - │ ├── y:15 => a:7 - │ ├── "?column?":16 => b:8 - │ ├── c_default:17 => c:9 - │ ├── d_comp:19 => d:10 - │ ├── y:15 => e:11 - │ └── rowid_default:18 => rowid:12 + │ ├── y:17 => a:7 + │ ├── "?column?":18 => b:8 + │ ├── c_default:19 => c:9 + │ ├── d_comp:21 => d:10 + │ ├── y:17 => e:11 + │ └── rowid_default:20 => rowid:12 └── project - ├── columns: d_comp:19 y:15 "?column?":16 c_default:17!null rowid_default:18 + ├── columns: d_comp:21 y:17 "?column?":18 c_default:19!null rowid_default:20 ├── project - │ ├── columns: c_default:17!null rowid_default:18 y:15 "?column?":16 - │ ├── with-scan &1 (a) - │ │ ├── columns: y:15 "?column?":16 - │ │ └── mapping: - │ │ ├── xyz.y:2 => y:15 - │ │ └── "?column?":6 => "?column?":16 + │ ├── columns: c_default:19!null rowid_default:20 y:17 "?column?":18 + │ ├── project + │ │ ├── columns: y:17 "?column?":18 + │ │ ├── with-scan &1 (a) + │ │ │ ├── columns: y:15 "?column?":16 + │ │ │ └── mapping: + │ │ │ ├── xyz.y:2 => y:15 + │ │ │ └── "?column?":6 => "?column?":16 + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=y:17] + │ │ │ └── y:15 + │ │ └── assignment-cast: INT8 [as="?column?":18] + │ │ └── "?column?":16 │ └── projections - │ ├── 10 [as=c_default:17] - │ └── unique_rowid() [as=rowid_default:18] + │ ├── 10 [as=c_default:19] + │ └── unique_rowid() [as=rowid_default:20] └── projections - └── ("?column?":16 + c_default:17) + 1 [as=d_comp:19] + └── ("?column?":18 + c_default:19) + 1 [as=d_comp:21] # Use CTE with multiple variables. build @@ -510,35 +592,42 @@ with &1 (a) └── insert abcde ├── columns: ├── insert-mapping: - │ ├── y:25 => a:13 - │ ├── "?column?":26 => b:14 - │ ├── c_default:27 => c:15 - │ ├── d_comp:29 => d:16 - │ ├── y:25 => e:17 - │ └── rowid_default:28 => rowid:18 + │ ├── y:27 => a:13 + │ ├── "?column?":28 => b:14 + │ ├── c_default:29 => c:15 + │ ├── d_comp:31 => d:16 + │ ├── y:27 => e:17 + │ └── rowid_default:30 => rowid:18 └── project - ├── columns: d_comp:29 y:25 "?column?":26 c_default:27!null rowid_default:28 + ├── columns: d_comp:31 y:27 "?column?":28 c_default:29!null rowid_default:30 ├── project - │ ├── columns: c_default:27!null rowid_default:28 y:25 "?column?":26 - │ ├── union - │ │ ├── columns: y:25 "?column?":26 - │ │ ├── left columns: y:21 "?column?":22 - │ │ ├── right columns: "?column?":23 y:24 - │ │ ├── with-scan &1 (a) - │ │ │ ├── columns: y:21 "?column?":22 - │ │ │ └── mapping: - │ │ │ ├── xyz.y:2 => y:21 - │ │ │ └── "?column?":6 => "?column?":22 - │ │ └── with-scan &2 (b) - │ │ ├── columns: "?column?":23 y:24 - │ │ └── mapping: - │ │ ├── "?column?":12 => "?column?":23 - │ │ └── xyz.y:8 => y:24 + │ ├── columns: c_default:29!null rowid_default:30 y:27 "?column?":28 + │ ├── project + │ │ ├── columns: y:27 "?column?":28 + │ │ ├── union + │ │ │ ├── columns: y:25 "?column?":26 + │ │ │ ├── left columns: y:21 "?column?":22 + │ │ │ ├── right columns: "?column?":23 y:24 + │ │ │ ├── with-scan &1 (a) + │ │ │ │ ├── columns: y:21 "?column?":22 + │ │ │ │ └── mapping: + │ │ │ │ ├── xyz.y:2 => y:21 + │ │ │ │ └── "?column?":6 => "?column?":22 + │ │ │ └── with-scan &2 (b) + │ │ │ ├── columns: "?column?":23 y:24 + │ │ │ └── mapping: + │ │ │ ├── "?column?":12 => "?column?":23 + │ │ │ └── xyz.y:8 => y:24 + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=y:27] + │ │ │ └── y:25 + │ │ └── assignment-cast: INT8 [as="?column?":28] + │ │ └── "?column?":26 │ └── projections - │ ├── 10 [as=c_default:27] - │ └── unique_rowid() [as=rowid_default:28] + │ ├── 10 [as=c_default:29] + │ └── unique_rowid() [as=rowid_default:30] └── projections - └── ("?column?":26 + c_default:27) + 1 [as=d_comp:29] + └── ("?column?":28 + c_default:29) + 1 [as=d_comp:31] # Non-referenced CTE with mutation. build @@ -550,58 +639,68 @@ with &1 │ └── insert abcde │ ├── columns: abcde.a:1!null abcde.b:2 abcde.c:3!null abcde.d:4 abcde.e:5!null rowid:6!null │ ├── insert-mapping: - │ │ ├── column1:9 => abcde.a:1 - │ │ ├── b_default:10 => abcde.b:2 - │ │ ├── c_default:11 => abcde.c:3 - │ │ ├── d_comp:13 => abcde.d:4 - │ │ ├── column1:9 => abcde.e:5 - │ │ └── rowid_default:12 => rowid:6 + │ │ ├── column1:10 => abcde.a:1 + │ │ ├── b_default:11 => abcde.b:2 + │ │ ├── c_default:12 => abcde.c:3 + │ │ ├── d_comp:14 => abcde.d:4 + │ │ ├── column1:10 => abcde.e:5 + │ │ └── rowid_default:13 => rowid:6 │ └── project - │ ├── columns: d_comp:13 column1:9!null b_default:10 c_default:11!null rowid_default:12 + │ ├── columns: d_comp:14 column1:10!null b_default:11 c_default:12!null rowid_default:13 │ ├── project - │ │ ├── columns: b_default:10 c_default:11!null rowid_default:12 column1:9!null - │ │ ├── values - │ │ │ ├── columns: column1:9!null - │ │ │ └── (1,) + │ │ ├── columns: b_default:11 c_default:12!null rowid_default:13 column1:10!null + │ │ ├── project + │ │ │ ├── columns: column1:10!null + │ │ │ ├── values + │ │ │ │ ├── columns: column1:9!null + │ │ │ │ └── (1,) + │ │ │ └── projections + │ │ │ └── assignment-cast: INT8 [as=column1:10] + │ │ │ └── column1:9 │ │ └── projections - │ │ ├── NULL::INT8 [as=b_default:10] - │ │ ├── 10 [as=c_default:11] - │ │ └── unique_rowid() [as=rowid_default:12] + │ │ ├── NULL::INT8 [as=b_default:11] + │ │ ├── 10 [as=c_default:12] + │ │ └── unique_rowid() [as=rowid_default:13] │ └── projections - │ └── (b_default:10 + c_default:11) + 1 [as=d_comp:13] + │ └── (b_default:11 + c_default:12) + 1 [as=d_comp:14] └── with &2 (cte) ├── project - │ ├── columns: b:15 + │ ├── columns: b:16 │ └── with-scan &1 - │ ├── columns: a:14!null b:15 c:16!null d:17 e:18!null + │ ├── columns: a:15!null b:16 c:17!null d:18 e:19!null │ └── mapping: - │ ├── abcde.a:1 => a:14 - │ ├── abcde.b:2 => b:15 - │ ├── abcde.c:3 => c:16 - │ ├── abcde.d:4 => d:17 - │ └── abcde.e:5 => e:18 + │ ├── abcde.a:1 => a:15 + │ ├── abcde.b:2 => b:16 + │ ├── abcde.c:3 => c:17 + │ ├── abcde.d:4 => d:18 + │ └── abcde.e:5 => e:19 └── insert abcde ├── columns: ├── insert-mapping: - │ ├── column1:27 => abcde.a:19 - │ ├── b_default:28 => abcde.b:20 - │ ├── c_default:29 => abcde.c:21 - │ ├── d_comp:31 => abcde.d:22 - │ ├── column1:27 => abcde.e:23 - │ └── rowid_default:30 => rowid:24 + │ ├── column1:29 => abcde.a:20 + │ ├── b_default:30 => abcde.b:21 + │ ├── c_default:31 => abcde.c:22 + │ ├── d_comp:33 => abcde.d:23 + │ ├── column1:29 => abcde.e:24 + │ └── rowid_default:32 => rowid:25 └── project - ├── columns: d_comp:31 column1:27!null b_default:28 c_default:29!null rowid_default:30 + ├── columns: d_comp:33 column1:29!null b_default:30 c_default:31!null rowid_default:32 ├── project - │ ├── columns: b_default:28 c_default:29!null rowid_default:30 column1:27!null - │ ├── values - │ │ ├── columns: column1:27!null - │ │ └── (1,) + │ ├── columns: b_default:30 c_default:31!null rowid_default:32 column1:29!null + │ ├── project + │ │ ├── columns: column1:29!null + │ │ ├── values + │ │ │ ├── columns: column1:28!null + │ │ │ └── (1,) + │ │ └── projections + │ │ └── assignment-cast: INT8 [as=column1:29] + │ │ └── column1:28 │ └── projections - │ ├── NULL::INT8 [as=b_default:28] - │ ├── 10 [as=c_default:29] - │ └── unique_rowid() [as=rowid_default:30] + │ ├── NULL::INT8 [as=b_default:30] + │ ├── 10 [as=c_default:31] + │ └── unique_rowid() [as=rowid_default:32] └── projections - └── (b_default:28 + c_default:29) + 1 [as=d_comp:31] + └── (b_default:30 + c_default:31) + 1 [as=d_comp:33] # Insert CTE that returns no columns. build @@ -626,23 +725,32 @@ INSERT INTO abcde (c, b, a) VALUES (1, 2, 3) insert abcde ├── columns: ├── insert-mapping: - │ ├── column3:11 => a:1 - │ ├── column2:10 => b:2 - │ ├── column1:9 => c:3 - │ ├── d_comp:13 => d:4 - │ ├── column3:11 => e:5 - │ └── rowid_default:12 => rowid:6 + │ ├── column3:14 => a:1 + │ ├── column2:13 => b:2 + │ ├── column1:12 => c:3 + │ ├── d_comp:16 => d:4 + │ ├── column3:14 => e:5 + │ └── rowid_default:15 => rowid:6 └── project - ├── columns: d_comp:13!null column1:9!null column2:10!null column3:11!null rowid_default:12 + ├── columns: d_comp:16!null column1:12!null column2:13!null column3:14!null rowid_default:15 ├── project - │ ├── columns: rowid_default:12 column1:9!null column2:10!null column3:11!null - │ ├── values - │ │ ├── columns: column1:9!null column2:10!null column3:11!null - │ │ └── (1, 2, 3) + │ ├── columns: rowid_default:15 column1:12!null column2:13!null column3:14!null + │ ├── project + │ │ ├── columns: column1:12!null column2:13!null column3:14!null + │ │ ├── values + │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ └── (1, 2, 3) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:12] + │ │ │ └── column1:9 + │ │ ├── assignment-cast: INT8 [as=column2:13] + │ │ │ └── column2:10 + │ │ └── assignment-cast: INT8 [as=column3:14] + │ │ └── column3:11 │ └── projections - │ └── unique_rowid() [as=rowid_default:12] + │ └── unique_rowid() [as=rowid_default:15] └── projections - └── (column2:10 + column1:9) + 1 [as=d_comp:13] + └── (column2:13 + column1:12) + 1 [as=d_comp:16] # Don't specify values for null or default columns. build @@ -651,25 +759,30 @@ INSERT INTO abcde (a) VALUES (1) insert abcde ├── columns: ├── insert-mapping: - │ ├── column1:9 => a:1 - │ ├── b_default:10 => b:2 - │ ├── c_default:11 => c:3 - │ ├── d_comp:13 => d:4 - │ ├── column1:9 => e:5 - │ └── rowid_default:12 => rowid:6 + │ ├── column1:10 => a:1 + │ ├── b_default:11 => b:2 + │ ├── c_default:12 => c:3 + │ ├── d_comp:14 => d:4 + │ ├── column1:10 => e:5 + │ └── rowid_default:13 => rowid:6 └── project - ├── columns: d_comp:13 column1:9!null b_default:10 c_default:11!null rowid_default:12 + ├── columns: d_comp:14 column1:10!null b_default:11 c_default:12!null rowid_default:13 ├── project - │ ├── columns: b_default:10 c_default:11!null rowid_default:12 column1:9!null - │ ├── values - │ │ ├── columns: column1:9!null - │ │ └── (1,) + │ ├── columns: b_default:11 c_default:12!null rowid_default:13 column1:10!null + │ ├── project + │ │ ├── columns: column1:10!null + │ │ ├── values + │ │ │ ├── columns: column1:9!null + │ │ │ └── (1,) + │ │ └── projections + │ │ └── assignment-cast: INT8 [as=column1:10] + │ │ └── column1:9 │ └── projections - │ ├── NULL::INT8 [as=b_default:10] - │ ├── 10 [as=c_default:11] - │ └── unique_rowid() [as=rowid_default:12] + │ ├── NULL::INT8 [as=b_default:11] + │ ├── 10 [as=c_default:12] + │ └── unique_rowid() [as=rowid_default:13] └── projections - └── (b_default:10 + c_default:11) + 1 [as=d_comp:13] + └── (b_default:11 + c_default:12) + 1 [as=d_comp:14] # Insert value into hidden rowid column. build @@ -680,24 +793,31 @@ project └── insert abcde ├── columns: a:1!null b:2 c:3!null d:4 e:5!null rowid:6!null ├── insert-mapping: - │ ├── column1:9 => a:1 - │ ├── b_default:11 => b:2 - │ ├── c_default:12 => c:3 - │ ├── d_comp:13 => d:4 - │ ├── column1:9 => e:5 - │ └── column2:10 => rowid:6 + │ ├── column1:11 => a:1 + │ ├── b_default:13 => b:2 + │ ├── c_default:14 => c:3 + │ ├── d_comp:15 => d:4 + │ ├── column1:11 => e:5 + │ └── column2:12 => rowid:6 └── project - ├── columns: d_comp:13 column1:9!null column2:10!null b_default:11 c_default:12!null + ├── columns: d_comp:15 column1:11!null column2:12!null b_default:13 c_default:14!null ├── project - │ ├── columns: b_default:11 c_default:12!null column1:9!null column2:10!null - │ ├── values - │ │ ├── columns: column1:9!null column2:10!null - │ │ └── (1, 2) + │ ├── columns: b_default:13 c_default:14!null column1:11!null column2:12!null + │ ├── project + │ │ ├── columns: column1:11!null column2:12!null + │ │ ├── values + │ │ │ ├── columns: column1:9!null column2:10!null + │ │ │ └── (1, 2) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:11] + │ │ │ └── column1:9 + │ │ └── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:10 │ └── projections - │ ├── NULL::INT8 [as=b_default:11] - │ └── 10 [as=c_default:12] + │ ├── NULL::INT8 [as=b_default:13] + │ └── 10 [as=c_default:14] └── projections - └── (b_default:11 + c_default:12) + 1 [as=d_comp:13] + └── (b_default:13 + c_default:14) + 1 [as=d_comp:15] # Use DEFAULT expressions in VALUES expression. build @@ -708,21 +828,32 @@ RETURNING *, rowid insert abcde ├── columns: a:1!null b:2 c:3!null d:4 e:5!null rowid:6!null ├── insert-mapping: - │ ├── column3:11 => a:1 - │ ├── column2:10 => b:2 - │ ├── column1:9 => c:3 - │ ├── d_comp:13 => d:4 - │ ├── column3:11 => e:5 - │ └── column4:12 => rowid:6 + │ ├── column3:15 => a:1 + │ ├── column2:14 => b:2 + │ ├── column1:13 => c:3 + │ ├── d_comp:17 => d:4 + │ ├── column3:15 => e:5 + │ └── column4:16 => rowid:6 └── project - ├── columns: d_comp:13 column1:9!null column2:10 column3:11!null column4:12 - ├── values - │ ├── columns: column1:9!null column2:10 column3:11!null column4:12 - │ ├── (10, NULL::INT8, 1, unique_rowid()) - │ ├── (3, 2, 1, unique_rowid()) - │ └── (10, NULL::INT8, 2, 100) + ├── columns: d_comp:17 column1:13!null column2:14 column3:15!null column4:16 + ├── project + │ ├── columns: column1:13!null column2:14 column3:15!null column4:16 + │ ├── values + │ │ ├── columns: column1:9!null column2:10 column3:11!null column4:12 + │ │ ├── (10, NULL::INT8, 1, unique_rowid()) + │ │ ├── (3, 2, 1, unique_rowid()) + │ │ └── (10, NULL::INT8, 2, 100) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:13] + │ │ └── column1:9 + │ ├── assignment-cast: INT8 [as=column2:14] + │ │ └── column2:10 + │ ├── assignment-cast: INT8 [as=column3:15] + │ │ └── column3:11 + │ └── assignment-cast: INT8 [as=column4:16] + │ └── column4:12 └── projections - └── (column2:10 + column1:9) + 1 [as=d_comp:13] + └── (column2:14 + column1:13) + 1 [as=d_comp:17] # Verify that there is no compile-time error when trying to insert a NULL # DEFAULT value into a not-null column (it will fail at runtime). @@ -732,25 +863,30 @@ INSERT INTO abcde (a) VALUES (DEFAULT) insert abcde ├── columns: ├── insert-mapping: - │ ├── column1:9 => a:1 - │ ├── b_default:10 => b:2 - │ ├── c_default:11 => c:3 - │ ├── d_comp:13 => d:4 - │ ├── column1:9 => e:5 - │ └── rowid_default:12 => rowid:6 + │ ├── column1:10 => a:1 + │ ├── b_default:11 => b:2 + │ ├── c_default:12 => c:3 + │ ├── d_comp:14 => d:4 + │ ├── column1:10 => e:5 + │ └── rowid_default:13 => rowid:6 └── project - ├── columns: d_comp:13 column1:9 b_default:10 c_default:11!null rowid_default:12 + ├── columns: d_comp:14 column1:10 b_default:11 c_default:12!null rowid_default:13 ├── project - │ ├── columns: b_default:10 c_default:11!null rowid_default:12 column1:9 - │ ├── values - │ │ ├── columns: column1:9 - │ │ └── (NULL::INT8,) + │ ├── columns: b_default:11 c_default:12!null rowid_default:13 column1:10 + │ ├── project + │ │ ├── columns: column1:10 + │ │ ├── values + │ │ │ ├── columns: column1:9 + │ │ │ └── (NULL::INT8,) + │ │ └── projections + │ │ └── assignment-cast: INT8 [as=column1:10] + │ │ └── column1:9 │ └── projections - │ ├── NULL::INT8 [as=b_default:10] - │ ├── 10 [as=c_default:11] - │ └── unique_rowid() [as=rowid_default:12] + │ ├── NULL::INT8 [as=b_default:11] + │ ├── 10 [as=c_default:12] + │ └── unique_rowid() [as=rowid_default:13] └── projections - └── (b_default:10 + c_default:11) + 1 [as=d_comp:13] + └── (b_default:11 + c_default:12) + 1 [as=d_comp:14] # Mismatched type. build @@ -763,9 +899,9 @@ insert xyz │ ├── y_default:8 => y:2 │ └── z_default:9 => z:3 └── project - ├── columns: y_default:8 z_default:9 column1:7 + ├── columns: y_default:8 z_default:9 column1:7!null ├── project - │ ├── columns: column1:7 + │ ├── columns: column1:7!null │ ├── values │ │ ├── columns: column1:6!null │ │ └── (10,) @@ -821,27 +957,34 @@ project └── insert abcde ├── columns: a:1!null b:2!null c:3!null d:4!null e:5 rowid:6!null ├── insert-mapping: - │ ├── y:10 => a:1 - │ ├── x:14 => b:2 - │ ├── c_default:15 => c:3 - │ ├── d_comp:17 => d:4 - │ ├── y:10 => e:5 - │ └── rowid_default:16 => rowid:6 + │ ├── y:16 => a:1 + │ ├── x:15 => b:2 + │ ├── c_default:17 => c:3 + │ ├── d_comp:19 => d:4 + │ ├── y:16 => e:5 + │ └── rowid_default:18 => rowid:6 └── project - ├── columns: d_comp:17!null y:10 x:14!null c_default:15!null rowid_default:16 + ├── columns: d_comp:19!null x:15!null y:16 c_default:17!null rowid_default:18 ├── project - │ ├── columns: c_default:15!null rowid_default:16 y:10 x:14!null + │ ├── columns: c_default:17!null rowid_default:18 x:15!null y:16 │ ├── project - │ │ ├── columns: x:14!null y:10 - │ │ ├── scan xyz - │ │ │ └── columns: xyz.x:9!null y:10 z:11 xyz.crdb_internal_mvcc_timestamp:12 xyz.tableoid:13 + │ │ ├── columns: x:15!null y:16 + │ │ ├── project + │ │ │ ├── columns: x:14!null xyz.y:10 + │ │ │ ├── scan xyz + │ │ │ │ └── columns: xyz.x:9!null xyz.y:10 z:11 xyz.crdb_internal_mvcc_timestamp:12 xyz.tableoid:13 + │ │ │ └── projections + │ │ │ └── xyz.x:9::INT8 [as=x:14] │ │ └── projections - │ │ └── xyz.x:9::INT8 [as=x:14] + │ │ ├── assignment-cast: INT8 [as=x:15] + │ │ │ └── x:14 + │ │ └── assignment-cast: INT8 [as=y:16] + │ │ └── xyz.y:10 │ └── projections - │ ├── 10 [as=c_default:15] - │ └── unique_rowid() [as=rowid_default:16] + │ ├── 10 [as=c_default:17] + │ └── unique_rowid() [as=rowid_default:18] └── projections - └── (x:14 + c_default:15) + 1 [as=d_comp:17] + └── (x:15 + c_default:17) + 1 [as=d_comp:19] # Return hidden column. build @@ -850,65 +993,79 @@ INSERT INTO abcde (rowid, a) VALUES (1, 2) RETURNING *, rowid insert abcde ├── columns: a:1!null b:2 c:3!null d:4 e:5!null rowid:6!null ├── insert-mapping: - │ ├── column2:10 => a:1 - │ ├── b_default:11 => b:2 - │ ├── c_default:12 => c:3 - │ ├── d_comp:13 => d:4 - │ ├── column2:10 => e:5 - │ └── column1:9 => rowid:6 + │ ├── column2:12 => a:1 + │ ├── b_default:13 => b:2 + │ ├── c_default:14 => c:3 + │ ├── d_comp:15 => d:4 + │ ├── column2:12 => e:5 + │ └── column1:11 => rowid:6 └── project - ├── columns: d_comp:13 column1:9!null column2:10!null b_default:11 c_default:12!null + ├── columns: d_comp:15 column1:11!null column2:12!null b_default:13 c_default:14!null ├── project - │ ├── columns: b_default:11 c_default:12!null column1:9!null column2:10!null - │ ├── values - │ │ ├── columns: column1:9!null column2:10!null - │ │ └── (1, 2) + │ ├── columns: b_default:13 c_default:14!null column1:11!null column2:12!null + │ ├── project + │ │ ├── columns: column1:11!null column2:12!null + │ │ ├── values + │ │ │ ├── columns: column1:9!null column2:10!null + │ │ │ └── (1, 2) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:11] + │ │ │ └── column1:9 + │ │ └── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:10 │ └── projections - │ ├── NULL::INT8 [as=b_default:11] - │ └── 10 [as=c_default:12] + │ ├── NULL::INT8 [as=b_default:13] + │ └── 10 [as=c_default:14] └── projections - └── (b_default:11 + c_default:12) + 1 [as=d_comp:13] + └── (b_default:13 + c_default:14) + 1 [as=d_comp:15] # Use returning INSERT as a FROM expression. build SELECT * FROM [INSERT INTO abcde (a, b) SELECT y+1, y FROM xyz RETURNING *] ---- with &1 - ├── columns: a:18!null b:19 c:20!null d:21 e:22 + ├── columns: a:20!null b:21 c:22!null d:23 e:24 ├── project │ ├── columns: abcde.a:1!null abcde.b:2 abcde.c:3!null abcde.d:4 abcde.e:5 │ └── insert abcde │ ├── columns: abcde.a:1!null abcde.b:2 abcde.c:3!null abcde.d:4 abcde.e:5 rowid:6!null │ ├── insert-mapping: - │ │ ├── "?column?":14 => abcde.a:1 - │ │ ├── y:10 => abcde.b:2 - │ │ ├── c_default:15 => abcde.c:3 - │ │ ├── d_comp:17 => abcde.d:4 - │ │ ├── "?column?":14 => abcde.e:5 - │ │ └── rowid_default:16 => rowid:6 + │ │ ├── "?column?":15 => abcde.a:1 + │ │ ├── y:16 => abcde.b:2 + │ │ ├── c_default:17 => abcde.c:3 + │ │ ├── d_comp:19 => abcde.d:4 + │ │ ├── "?column?":15 => abcde.e:5 + │ │ └── rowid_default:18 => rowid:6 │ └── project - │ ├── columns: d_comp:17 y:10 "?column?":14 c_default:15!null rowid_default:16 + │ ├── columns: d_comp:19 "?column?":15 y:16 c_default:17!null rowid_default:18 │ ├── project - │ │ ├── columns: c_default:15!null rowid_default:16 y:10 "?column?":14 + │ │ ├── columns: c_default:17!null rowid_default:18 "?column?":15 y:16 │ │ ├── project - │ │ │ ├── columns: "?column?":14 y:10 - │ │ │ ├── scan xyz - │ │ │ │ └── columns: x:9!null y:10 z:11 xyz.crdb_internal_mvcc_timestamp:12 xyz.tableoid:13 + │ │ │ ├── columns: "?column?":15 y:16 + │ │ │ ├── project + │ │ │ │ ├── columns: "?column?":14 xyz.y:10 + │ │ │ │ ├── scan xyz + │ │ │ │ │ └── columns: x:9!null xyz.y:10 z:11 xyz.crdb_internal_mvcc_timestamp:12 xyz.tableoid:13 + │ │ │ │ └── projections + │ │ │ │ └── xyz.y:10 + 1 [as="?column?":14] │ │ │ └── projections - │ │ │ └── y:10 + 1 [as="?column?":14] + │ │ │ ├── assignment-cast: INT8 [as="?column?":15] + │ │ │ │ └── "?column?":14 + │ │ │ └── assignment-cast: INT8 [as=y:16] + │ │ │ └── xyz.y:10 │ │ └── projections - │ │ ├── 10 [as=c_default:15] - │ │ └── unique_rowid() [as=rowid_default:16] + │ │ ├── 10 [as=c_default:17] + │ │ └── unique_rowid() [as=rowid_default:18] │ └── projections - │ └── (y:10 + c_default:15) + 1 [as=d_comp:17] + │ └── (y:16 + c_default:17) + 1 [as=d_comp:19] └── with-scan &1 - ├── columns: a:18!null b:19 c:20!null d:21 e:22 + ├── columns: a:20!null b:21 c:22!null d:23 e:24 └── mapping: - ├── abcde.a:1 => a:18 - ├── abcde.b:2 => b:19 - ├── abcde.c:3 => c:20 - ├── abcde.d:4 => d:21 - └── abcde.e:5 => e:22 + ├── abcde.a:1 => a:20 + ├── abcde.b:2 => b:21 + ├── abcde.c:3 => c:22 + ├── abcde.d:4 => d:23 + └── abcde.e:5 => e:24 # ------------------------------------------------------------------------------ # Propagate desired INSERT types. @@ -921,12 +1078,21 @@ INSERT INTO xyz VALUES ($1, $2 + 1, $3 + 1) insert xyz ├── columns: ├── insert-mapping: - │ ├── column1:6 => x:1 - │ ├── column2:7 => y:2 - │ └── column3:8 => z:3 - └── values - ├── columns: column1:6 column2:7 column3:8 - └── ($1, $2 + 1, $3 + 1.0) + │ ├── column1:9 => x:1 + │ ├── column2:10 => y:2 + │ └── column3:11 => z:3 + └── project + ├── columns: column1:9 column2:10 column3:11 + ├── values + │ ├── columns: column1:6 column2:7 column3:8 + │ └── ($1, $2 + 1, $3 + 1.0) + └── projections + ├── assignment-cast: STRING [as=column1:9] + │ └── column1:6 + ├── assignment-cast: INT8 [as=column2:10] + │ └── column2:7 + └── assignment-cast: FLOAT8 [as=column3:11] + └── column3:8 # Propagate types to VALUES (named columns). build @@ -935,12 +1101,21 @@ INSERT INTO xyz (z, y, x) VALUES ($1 + 1, $2 + 1, $3) insert xyz ├── columns: ├── insert-mapping: - │ ├── column3:8 => x:1 - │ ├── column2:7 => y:2 - │ └── column1:6 => z:3 - └── values - ├── columns: column1:6 column2:7 column3:8 - └── ($1 + 1.0, $2 + 1, $3) + │ ├── column3:11 => x:1 + │ ├── column2:10 => y:2 + │ └── column1:9 => z:3 + └── project + ├── columns: column1:9 column2:10 column3:11 + ├── values + │ ├── columns: column1:6 column2:7 column3:8 + │ └── ($1 + 1.0, $2 + 1, $3) + └── projections + ├── assignment-cast: FLOAT8 [as=column1:9] + │ └── column1:6 + ├── assignment-cast: INT8 [as=column2:10] + │ └── column2:7 + └── assignment-cast: STRING [as=column3:11] + └── column3:8 # Propagate types to projection list. build @@ -949,17 +1124,26 @@ INSERT INTO xyz ((SELECT $1, $2 + 1, $3 + 1)) insert xyz ├── columns: ├── insert-mapping: - │ ├── "?column?":6 => x:1 - │ ├── "?column?":7 => y:2 - │ └── "?column?":8 => z:3 + │ ├── "?column?":9 => x:1 + │ ├── "?column?":10 => y:2 + │ └── "?column?":11 => z:3 └── project - ├── columns: "?column?":6 "?column?":7 "?column?":8 - ├── values - │ └── () + ├── columns: "?column?":9 "?column?":10 "?column?":11 + ├── project + │ ├── columns: "?column?":6 "?column?":7 "?column?":8 + │ ├── values + │ │ └── () + │ └── projections + │ ├── $1 [as="?column?":6] + │ ├── $2 + 1 [as="?column?":7] + │ └── $3 + 1.0 [as="?column?":8] └── projections - ├── $1 [as="?column?":6] - ├── $2 + 1 [as="?column?":7] - └── $3 + 1.0 [as="?column?":8] + ├── assignment-cast: STRING [as="?column?":9] + │ └── "?column?":6 + ├── assignment-cast: INT8 [as="?column?":10] + │ └── "?column?":7 + └── assignment-cast: FLOAT8 [as="?column?":11] + └── "?column?":8 # Propagate types to projection list (named columns). build @@ -968,17 +1152,26 @@ INSERT INTO xyz (x, y, z) SELECT $1, $2 + 1, $3 + 1 insert xyz ├── columns: ├── insert-mapping: - │ ├── "?column?":6 => x:1 - │ ├── "?column?":7 => y:2 - │ └── "?column?":8 => z:3 + │ ├── "?column?":9 => x:1 + │ ├── "?column?":10 => y:2 + │ └── "?column?":11 => z:3 └── project - ├── columns: "?column?":6 "?column?":7 "?column?":8 - ├── values - │ └── () + ├── columns: "?column?":9 "?column?":10 "?column?":11 + ├── project + │ ├── columns: "?column?":6 "?column?":7 "?column?":8 + │ ├── values + │ │ └── () + │ └── projections + │ ├── $1 [as="?column?":6] + │ ├── $2 + 1 [as="?column?":7] + │ └── $3 + 1.0 [as="?column?":8] └── projections - ├── $1 [as="?column?":6] - ├── $2 + 1 [as="?column?":7] - └── $3 + 1.0 [as="?column?":8] + ├── assignment-cast: STRING [as="?column?":9] + │ └── "?column?":6 + ├── assignment-cast: INT8 [as="?column?":10] + │ └── "?column?":7 + └── assignment-cast: FLOAT8 [as="?column?":11] + └── "?column?":8 # Propagate types to UNION. build @@ -987,29 +1180,38 @@ INSERT INTO xyz (SELECT $1, $2 + 1, $3 + 1) UNION ALL (SELECT $1, $2 + 1, $3 + 1 insert xyz ├── columns: ├── insert-mapping: - │ ├── "?column?":12 => x:1 - │ ├── "?column?":13 => y:2 - │ └── "?column?":14 => z:3 - └── union-all - ├── columns: "?column?":12 "?column?":13 "?column?":14 - ├── left columns: "?column?":6 "?column?":7 "?column?":8 - ├── right columns: "?column?":9 "?column?":10 "?column?":11 - ├── project - │ ├── columns: "?column?":6 "?column?":7 "?column?":8 - │ ├── values - │ │ └── () - │ └── projections - │ ├── $1 [as="?column?":6] - │ ├── $2 + 1 [as="?column?":7] - │ └── $3 + 1.0 [as="?column?":8] - └── project - ├── columns: "?column?":9 "?column?":10 "?column?":11 - ├── values - │ └── () - └── projections - ├── $1 [as="?column?":9] - ├── $2 + 1 [as="?column?":10] - └── $3 + 1.0 [as="?column?":11] + │ ├── "?column?":15 => x:1 + │ ├── "?column?":16 => y:2 + │ └── "?column?":17 => z:3 + └── project + ├── columns: "?column?":15 "?column?":16 "?column?":17 + ├── union-all + │ ├── columns: "?column?":12 "?column?":13 "?column?":14 + │ ├── left columns: "?column?":6 "?column?":7 "?column?":8 + │ ├── right columns: "?column?":9 "?column?":10 "?column?":11 + │ ├── project + │ │ ├── columns: "?column?":6 "?column?":7 "?column?":8 + │ │ ├── values + │ │ │ └── () + │ │ └── projections + │ │ ├── $1 [as="?column?":6] + │ │ ├── $2 + 1 [as="?column?":7] + │ │ └── $3 + 1.0 [as="?column?":8] + │ └── project + │ ├── columns: "?column?":9 "?column?":10 "?column?":11 + │ ├── values + │ │ └── () + │ └── projections + │ ├── $1 [as="?column?":9] + │ ├── $2 + 1 [as="?column?":10] + │ └── $3 + 1.0 [as="?column?":11] + └── projections + ├── assignment-cast: STRING [as="?column?":15] + │ └── "?column?":12 + ├── assignment-cast: INT8 [as="?column?":16] + │ └── "?column?":13 + └── assignment-cast: FLOAT8 [as="?column?":17] + └── "?column?":14 # Propagate types to UNION (named columns). build @@ -1018,29 +1220,38 @@ INSERT INTO xyz (x, z, y) SELECT $1, $2 + 1, $3 + 1 UNION ALL SELECT $1, $2 + 1, insert xyz ├── columns: ├── insert-mapping: - │ ├── "?column?":12 => x:1 - │ ├── "?column?":14 => y:2 - │ └── "?column?":13 => z:3 - └── union-all - ├── columns: "?column?":12 "?column?":13 "?column?":14 - ├── left columns: "?column?":6 "?column?":7 "?column?":8 - ├── right columns: "?column?":9 "?column?":10 "?column?":11 - ├── project - │ ├── columns: "?column?":6 "?column?":7 "?column?":8 - │ ├── values - │ │ └── () - │ └── projections - │ ├── $1 [as="?column?":6] - │ ├── $2 + 1.0 [as="?column?":7] - │ └── $3 + 1 [as="?column?":8] - └── project - ├── columns: "?column?":9 "?column?":10 "?column?":11 - ├── values - │ └── () - └── projections - ├── $1 [as="?column?":9] - ├── $2 + 1.0 [as="?column?":10] - └── $3 + 1 [as="?column?":11] + │ ├── "?column?":15 => x:1 + │ ├── "?column?":17 => y:2 + │ └── "?column?":16 => z:3 + └── project + ├── columns: "?column?":15 "?column?":16 "?column?":17 + ├── union-all + │ ├── columns: "?column?":12 "?column?":13 "?column?":14 + │ ├── left columns: "?column?":6 "?column?":7 "?column?":8 + │ ├── right columns: "?column?":9 "?column?":10 "?column?":11 + │ ├── project + │ │ ├── columns: "?column?":6 "?column?":7 "?column?":8 + │ │ ├── values + │ │ │ └── () + │ │ └── projections + │ │ ├── $1 [as="?column?":6] + │ │ ├── $2 + 1.0 [as="?column?":7] + │ │ └── $3 + 1 [as="?column?":8] + │ └── project + │ ├── columns: "?column?":9 "?column?":10 "?column?":11 + │ ├── values + │ │ └── () + │ └── projections + │ ├── $1 [as="?column?":9] + │ ├── $2 + 1.0 [as="?column?":10] + │ └── $3 + 1 [as="?column?":11] + └── projections + ├── assignment-cast: STRING [as="?column?":15] + │ └── "?column?":12 + ├── assignment-cast: FLOAT8 [as="?column?":16] + │ └── "?column?":13 + └── assignment-cast: INT8 [as="?column?":17] + └── "?column?":14 # ------------------------------------------------------------------------------ # Tests with mutation columns. @@ -1053,26 +1264,33 @@ INSERT INTO mutation (m, n) VALUES (1, 2) insert mutation ├── columns: ├── insert-mapping: - │ ├── column1:8 => m:1 - │ ├── column2:9 => n:2 - │ ├── o_default:10 => o:3 - │ └── p_comp:11 => p:4 - ├── check columns: check1:12 + │ ├── column1:10 => m:1 + │ ├── column2:11 => n:2 + │ ├── o_default:12 => o:3 + │ └── p_comp:13 => p:4 + ├── check columns: check1:14 └── project - ├── columns: check1:12!null column1:8!null column2:9!null o_default:10!null p_comp:11!null + ├── columns: check1:14!null column1:10!null column2:11!null o_default:12!null p_comp:13!null ├── project - │ ├── columns: p_comp:11!null column1:8!null column2:9!null o_default:10!null + │ ├── columns: p_comp:13!null column1:10!null column2:11!null o_default:12!null │ ├── project - │ │ ├── columns: o_default:10!null column1:8!null column2:9!null - │ │ ├── values - │ │ │ ├── columns: column1:8!null column2:9!null - │ │ │ └── (1, 2) + │ │ ├── columns: o_default:12!null column1:10!null column2:11!null + │ │ ├── project + │ │ │ ├── columns: column1:10!null column2:11!null + │ │ │ ├── values + │ │ │ │ ├── columns: column1:8!null column2:9!null + │ │ │ │ └── (1, 2) + │ │ │ └── projections + │ │ │ ├── assignment-cast: INT8 [as=column1:10] + │ │ │ │ └── column1:8 + │ │ │ └── assignment-cast: INT8 [as=column2:11] + │ │ │ └── column2:9 │ │ └── projections - │ │ └── 10 [as=o_default:10] + │ │ └── 10 [as=o_default:12] │ └── projections - │ └── o_default:10 + column2:9 [as=p_comp:11] + │ └── o_default:12 + column2:11 [as=p_comp:13] └── projections - └── column1:8 > 0 [as=check1:12] + └── column1:10 > 0 [as=check1:14] # Use RETURNING clause and ensure that mutation columns aren't projected. build @@ -1081,26 +1299,33 @@ INSERT INTO mutation (m, n) VALUES (1, 2) RETURNING * insert mutation ├── columns: m:1!null n:2!null ├── insert-mapping: - │ ├── column1:8 => m:1 - │ ├── column2:9 => n:2 - │ ├── o_default:10 => o:3 - │ └── p_comp:11 => p:4 - ├── check columns: check1:12 + │ ├── column1:10 => m:1 + │ ├── column2:11 => n:2 + │ ├── o_default:12 => o:3 + │ └── p_comp:13 => p:4 + ├── check columns: check1:14 └── project - ├── columns: check1:12!null column1:8!null column2:9!null o_default:10!null p_comp:11!null + ├── columns: check1:14!null column1:10!null column2:11!null o_default:12!null p_comp:13!null ├── project - │ ├── columns: p_comp:11!null column1:8!null column2:9!null o_default:10!null + │ ├── columns: p_comp:13!null column1:10!null column2:11!null o_default:12!null │ ├── project - │ │ ├── columns: o_default:10!null column1:8!null column2:9!null - │ │ ├── values - │ │ │ ├── columns: column1:8!null column2:9!null - │ │ │ └── (1, 2) + │ │ ├── columns: o_default:12!null column1:10!null column2:11!null + │ │ ├── project + │ │ │ ├── columns: column1:10!null column2:11!null + │ │ │ ├── values + │ │ │ │ ├── columns: column1:8!null column2:9!null + │ │ │ │ └── (1, 2) + │ │ │ └── projections + │ │ │ ├── assignment-cast: INT8 [as=column1:10] + │ │ │ │ └── column1:8 + │ │ │ └── assignment-cast: INT8 [as=column2:11] + │ │ │ └── column2:9 │ │ └── projections - │ │ └── 10 [as=o_default:10] + │ │ └── 10 [as=o_default:12] │ └── projections - │ └── o_default:10 + column2:9 [as=p_comp:11] + │ └── o_default:12 + column2:11 [as=p_comp:13] └── projections - └── column1:8 > 0 [as=check1:12] + └── column1:10 > 0 [as=check1:14] # Try to reference write-only mutation column in RETURNING clause. build @@ -1131,23 +1356,32 @@ INSERT INTO checks (a, b, c) VALUES (1, 2, 3) insert checks ├── columns: ├── insert-mapping: - │ ├── column1:7 => a:1 - │ ├── column2:8 => b:2 - │ ├── column3:9 => c:3 - │ └── d_comp:10 => d:4 - ├── check columns: check1:11 check2:12 + │ ├── column1:10 => a:1 + │ ├── column2:11 => b:2 + │ ├── column3:12 => c:3 + │ └── d_comp:13 => d:4 + ├── check columns: check1:14 check2:15 └── project - ├── columns: check1:11!null check2:12!null column1:7!null column2:8!null column3:9!null d_comp:10!null + ├── columns: check1:14!null check2:15!null column1:10!null column2:11!null column3:12!null d_comp:13!null ├── project - │ ├── columns: d_comp:10!null column1:7!null column2:8!null column3:9!null - │ ├── values - │ │ ├── columns: column1:7!null column2:8!null column3:9!null - │ │ └── (1, 2, 3) + │ ├── columns: d_comp:13!null column1:10!null column2:11!null column3:12!null + │ ├── project + │ │ ├── columns: column1:10!null column2:11!null column3:12!null + │ │ ├── values + │ │ │ ├── columns: column1:7!null column2:8!null column3:9!null + │ │ │ └── (1, 2, 3) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:10] + │ │ │ └── column1:7 + │ │ ├── assignment-cast: INT8 [as=column2:11] + │ │ │ └── column2:8 + │ │ └── assignment-cast: INT8 [as=column3:12] + │ │ └── column3:9 │ └── projections - │ └── column3:9 + 1 [as=d_comp:10] + │ └── column3:12 + 1 [as=d_comp:13] └── projections - ├── column2:8 < d_comp:10 [as=check1:11] - └── column1:7 > 0 [as=check2:12] + ├── column2:11 < d_comp:13 [as=check1:14] + └── column1:10 > 0 [as=check2:15] # Insert results of SELECT. build @@ -1156,29 +1390,38 @@ INSERT INTO checks SELECT a, b, c FROM abcde insert checks ├── columns: ├── insert-mapping: - │ ├── abcde.a:7 => checks.a:1 - │ ├── abcde.b:8 => checks.b:2 - │ ├── abcde.c:9 => checks.c:3 - │ └── d_comp:15 => checks.d:4 - ├── check columns: check1:16 check2:17 + │ ├── a:15 => checks.a:1 + │ ├── b:16 => checks.b:2 + │ ├── c:17 => checks.c:3 + │ └── d_comp:18 => checks.d:4 + ├── check columns: check1:19 check2:20 └── project - ├── columns: check1:16 check2:17!null abcde.a:7!null abcde.b:8 abcde.c:9 d_comp:15 + ├── columns: check1:19 check2:20!null a:15!null b:16 c:17 d_comp:18 ├── project - │ ├── columns: d_comp:15 abcde.a:7!null abcde.b:8 abcde.c:9 + │ ├── columns: d_comp:18 a:15!null b:16 c:17 │ ├── project - │ │ ├── columns: abcde.a:7!null abcde.b:8 abcde.c:9 - │ │ └── scan abcde - │ │ ├── columns: abcde.a:7!null abcde.b:8 abcde.c:9 abcde.d:10 e:11 rowid:12!null abcde.crdb_internal_mvcc_timestamp:13 abcde.tableoid:14 - │ │ └── computed column expressions - │ │ ├── abcde.d:10 - │ │ │ └── (abcde.b:8 + abcde.c:9) + 1 - │ │ └── e:11 - │ │ └── abcde.a:7 + │ │ ├── columns: a:15!null b:16 c:17 + │ │ ├── project + │ │ │ ├── columns: abcde.a:7!null abcde.b:8 abcde.c:9 + │ │ │ └── scan abcde + │ │ │ ├── columns: abcde.a:7!null abcde.b:8 abcde.c:9 abcde.d:10 e:11 rowid:12!null abcde.crdb_internal_mvcc_timestamp:13 abcde.tableoid:14 + │ │ │ └── computed column expressions + │ │ │ ├── abcde.d:10 + │ │ │ │ └── (abcde.b:8 + abcde.c:9) + 1 + │ │ │ └── e:11 + │ │ │ └── abcde.a:7 + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=a:15] + │ │ │ └── abcde.a:7 + │ │ ├── assignment-cast: INT8 [as=b:16] + │ │ │ └── abcde.b:8 + │ │ └── assignment-cast: INT8 [as=c:17] + │ │ └── abcde.c:9 │ └── projections - │ └── abcde.c:9 + 1 [as=d_comp:15] + │ └── c:17 + 1 [as=d_comp:18] └── projections - ├── abcde.b:8 < d_comp:15 [as=check1:16] - └── abcde.a:7 > 0 [as=check2:17] + ├── b:16 < d_comp:18 [as=check1:19] + └── a:15 > 0 [as=check2:20] # ------------------------------------------------------------------------------ # Test assignment casts. @@ -1191,31 +1434,33 @@ insert decimals ├── columns: ├── insert-mapping: │ ├── column1:9 => a:1 - │ ├── column2:8 => b:2 - │ ├── c_default:10 => c:3 - │ └── d_comp:11 => d:4 - ├── check columns: check1:12 check2:13 + │ ├── column2:10 => b:2 + │ ├── c_default:11 => c:3 + │ └── d_comp:12 => d:4 + ├── check columns: check1:13 check2:14 └── project - ├── columns: check1:12 check2:13 column2:8 column1:9 c_default:10!null d_comp:11 + ├── columns: check1:13 check2:14 column1:9!null column2:10 c_default:11!null d_comp:12!null ├── project - │ ├── columns: d_comp:11 column2:8 column1:9 c_default:10!null + │ ├── columns: d_comp:12!null column1:9!null column2:10 c_default:11!null │ ├── project - │ │ ├── columns: c_default:10!null column2:8 column1:9 + │ │ ├── columns: c_default:11!null column1:9!null column2:10 │ │ ├── project - │ │ │ ├── columns: column1:9 column2:8 + │ │ │ ├── columns: column1:9!null column2:10 │ │ │ ├── values │ │ │ │ ├── columns: column1:7!null column2:8 │ │ │ │ └── (1.1, ARRAY[0.95,NULL,15]) │ │ │ └── projections - │ │ │ └── assignment-cast: DECIMAL(10) [as=column1:9] - │ │ │ └── column1:7 + │ │ │ ├── assignment-cast: DECIMAL(10) [as=column1:9] + │ │ │ │ └── column1:7 + │ │ │ └── assignment-cast: DECIMAL(5,1)[] [as=column2:10] + │ │ │ └── column2:8 │ │ └── projections - │ │ └── 1.23::DECIMAL(10,1) [as=c_default:10] + │ │ └── 1.23::DECIMAL(10,1) [as=c_default:11] │ └── projections - │ └── (column1:9::DECIMAL + c_default:10::DECIMAL)::DECIMAL(10,1) [as=d_comp:11] + │ └── (column1:9::DECIMAL + c_default:11::DECIMAL)::DECIMAL(10,1) [as=d_comp:12] └── projections - ├── round(column1:9) = column1:9 [as=check1:12] - └── column2:8[0] > 1 [as=check2:13] + ├── round(column1:9) = column1:9 [as=check1:13] + └── column2:10[0] > 1 [as=check2:14] assign-placeholders-norm query-args=(1.1, (ARRAY[0.95, NULL, 15])) INSERT INTO decimals (a, b) VALUES ($1, $2) @@ -1251,13 +1496,13 @@ insert assn_cast ├── insert-mapping: │ ├── column1:12 => c:1 │ ├── column2:13 => qc:2 - │ ├── column3:10 => i:3 - │ ├── column4:14 => s:4 - │ └── rowid_default:15 => rowid:5 + │ ├── column3:14 => i:3 + │ ├── column4:15 => s:4 + │ └── rowid_default:16 => rowid:5 └── project - ├── columns: rowid_default:15 column3:10!null column1:12 column2:13 column4:14 + ├── columns: rowid_default:16 column1:12!null column2:13!null column3:14!null column4:15!null ├── project - │ ├── columns: column1:12 column2:13 column4:14 column3:10!null + │ ├── columns: column1:12!null column2:13!null column3:14!null column4:15!null │ ├── values │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null │ │ └── ('', 'f', 1, 2) @@ -1266,10 +1511,12 @@ insert assn_cast │ │ └── column1:8 │ ├── assignment-cast: "char" [as=column2:13] │ │ └── column2:9 - │ └── assignment-cast: STRING [as=column4:14] + │ ├── assignment-cast: INT8 [as=column3:14] + │ │ └── column3:10 + │ └── assignment-cast: STRING [as=column4:15] │ └── column4:11 └── projections - └── unique_rowid() [as=rowid_default:15] + └── unique_rowid() [as=rowid_default:16] assign-placeholders-norm query-args=(' ', 'foo', '1') INSERT INTO assn_cast (c, qc, i) VALUES ($1, $2, $3) @@ -1279,19 +1526,20 @@ insert assn_cast ├── insert-mapping: │ ├── column1:11 => c:1 │ ├── column2:12 => qc:2 - │ ├── column3:10 => i:3 - │ ├── s_default:13 => s:4 - │ └── rowid_default:14 => rowid:5 + │ ├── column3:13 => i:3 + │ ├── s_default:14 => s:4 + │ └── rowid_default:15 => rowid:5 └── values - ├── columns: column3:10!null s_default:13 rowid_default:14 column1:11 column2:12 + ├── columns: s_default:14 rowid_default:15 column1:11 column2:12 column3:13 └── tuple - ├── 1 ├── CAST(NULL AS STRING) ├── unique_rowid() ├── assignment-cast: CHAR - │ └── ' ' - └── assignment-cast: "char" - └── 'foo' + │ └── '' + ├── assignment-cast: "char" + │ └── 'f' + └── assignment-cast: INT8 + └── 1 # Regression test for #38293; the default values should be separate projections. exec-ddl @@ -1308,17 +1556,22 @@ INSERT INTO defvals(id) VALUES (1) insert defvals ├── columns: ├── insert-mapping: - │ ├── column1:6 => id:1 - │ ├── arr1_default:7 => arr1:2 - │ └── arr2_default:8 => arr2:3 + │ ├── column1:7 => id:1 + │ ├── arr1_default:8 => arr1:2 + │ └── arr2_default:9 => arr2:3 └── project - ├── columns: arr1_default:7!null arr2_default:8!null column1:6!null - ├── values - │ ├── columns: column1:6!null - │ └── (1,) + ├── columns: arr1_default:8!null arr2_default:9!null column1:7!null + ├── project + │ ├── columns: column1:7!null + │ ├── values + │ │ ├── columns: column1:6!null + │ │ └── (1,) + │ └── projections + │ └── assignment-cast: INT8 [as=column1:7] + │ └── column1:6 └── projections - ├── ARRAY[] [as=arr1_default:7] - └── ARRAY[] [as=arr2_default:8] + ├── ARRAY[] [as=arr1_default:8] + └── ARRAY[] [as=arr2_default:9] exec-ddl CREATE TABLE defvals2 ( @@ -1334,17 +1587,22 @@ INSERT INTO defvals2(id) VALUES (1) insert defvals2 ├── columns: ├── insert-mapping: - │ ├── column1:6 => id:1 - │ ├── arr1_default:7 => arr1:2 - │ └── arr2_default:8 => arr2:3 + │ ├── column1:7 => id:1 + │ ├── arr1_default:8 => arr1:2 + │ └── arr2_default:9 => arr2:3 └── project - ├── columns: arr1_default:7 arr2_default:8 column1:6!null - ├── values - │ ├── columns: column1:6!null - │ └── (1,) + ├── columns: arr1_default:8 arr2_default:9 column1:7!null + ├── project + │ ├── columns: column1:7!null + │ ├── values + │ │ ├── columns: column1:6!null + │ │ └── (1,) + │ └── projections + │ └── assignment-cast: INT8 [as=column1:7] + │ └── column1:6 └── projections - ├── ARRAY[NULL] [as=arr1_default:7] - └── ARRAY[NULL] [as=arr2_default:8] + ├── ARRAY[NULL] [as=arr1_default:8] + └── ARRAY[NULL] [as=arr2_default:9] # Regression test for #67100. Do not prune check columns for INSERTs even if the # expression does not reference any mutating columns. @@ -1364,22 +1622,27 @@ INSERT INTO t67100 VALUES (1) insert t67100 ├── columns: ├── insert-mapping: - │ ├── column1:5 => a:1 - │ └── rowid_default:6 => rowid:2 - ├── check columns: check1:7 check2:8 check3:9 + │ ├── column1:6 => a:1 + │ └── rowid_default:7 => rowid:2 + ├── check columns: check1:8 check2:9 check3:10 └── project - ├── columns: check1:7!null check2:8!null check3:9!null column1:5!null rowid_default:6 + ├── columns: check1:8!null check2:9!null check3:10!null column1:6!null rowid_default:7 ├── project - │ ├── columns: rowid_default:6 column1:5!null - │ ├── values - │ │ ├── columns: column1:5!null - │ │ └── (1,) + │ ├── columns: rowid_default:7 column1:6!null + │ ├── project + │ │ ├── columns: column1:6!null + │ │ ├── values + │ │ │ ├── columns: column1:5!null + │ │ │ └── (1,) + │ │ └── projections + │ │ └── assignment-cast: INT8 [as=column1:6] + │ │ └── column1:5 │ └── projections - │ └── unique_rowid() [as=rowid_default:6] + │ └── unique_rowid() [as=rowid_default:7] └── projections - ├── false [as=check1:7] - ├── 0 > 1 [as=check2:8] - └── true AND (0 > 1) [as=check3:9] + ├── false [as=check1:8] + ├── 0 > 1 [as=check2:9] + └── true AND (0 > 1) [as=check3:10] # ------------------------------------------------------------------------------ # ON UPDATE tests. @@ -1391,16 +1654,23 @@ INSERT INTO on_update_bare VALUES (1, 2) insert on_update_bare ├── columns: ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => v:2 - │ └── rowid_default:8 => rowid:3 + │ ├── column1:8 => a:1 + │ ├── column2:9 => v:2 + │ └── rowid_default:10 => rowid:3 └── project - ├── columns: rowid_default:8 column1:6!null column2:7!null - ├── values - │ ├── columns: column1:6!null column2:7!null - │ └── (1, 2) + ├── columns: rowid_default:10 column1:8!null column2:9!null + ├── project + │ ├── columns: column1:8!null column2:9!null + │ ├── values + │ │ ├── columns: column1:6!null column2:7!null + │ │ └── (1, 2) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:8] + │ │ └── column1:6 + │ └── assignment-cast: INT8 [as=column2:9] + │ └── column2:7 └── projections - └── unique_rowid() [as=rowid_default:8] + └── unique_rowid() [as=rowid_default:10] build INSERT INTO on_update_bare VALUES (1) @@ -1408,17 +1678,22 @@ INSERT INTO on_update_bare VALUES (1) insert on_update_bare ├── columns: ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── v_default:7 => v:2 - │ └── rowid_default:8 => rowid:3 + │ ├── column1:7 => a:1 + │ ├── v_default:8 => v:2 + │ └── rowid_default:9 => rowid:3 └── project - ├── columns: v_default:7 rowid_default:8 column1:6!null - ├── values - │ ├── columns: column1:6!null - │ └── (1,) + ├── columns: v_default:8 rowid_default:9 column1:7!null + ├── project + │ ├── columns: column1:7!null + │ ├── values + │ │ ├── columns: column1:6!null + │ │ └── (1,) + │ └── projections + │ └── assignment-cast: INT8 [as=column1:7] + │ └── column1:6 └── projections - ├── NULL::INT8 [as=v_default:7] - └── unique_rowid() [as=rowid_default:8] + ├── NULL::INT8 [as=v_default:8] + └── unique_rowid() [as=rowid_default:9] build @@ -1427,16 +1702,23 @@ INSERT INTO on_update_with_default VALUES (1, 2) insert on_update_with_default ├── columns: ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => v:2 - │ └── rowid_default:8 => rowid:3 + │ ├── column1:8 => a:1 + │ ├── column2:9 => v:2 + │ └── rowid_default:10 => rowid:3 └── project - ├── columns: rowid_default:8 column1:6!null column2:7!null - ├── values - │ ├── columns: column1:6!null column2:7!null - │ └── (1, 2) + ├── columns: rowid_default:10 column1:8!null column2:9!null + ├── project + │ ├── columns: column1:8!null column2:9!null + │ ├── values + │ │ ├── columns: column1:6!null column2:7!null + │ │ └── (1, 2) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:8] + │ │ └── column1:6 + │ └── assignment-cast: INT8 [as=column2:9] + │ └── column2:7 └── projections - └── unique_rowid() [as=rowid_default:8] + └── unique_rowid() [as=rowid_default:10] build @@ -1445,17 +1727,22 @@ INSERT INTO on_update_with_default VALUES (1) insert on_update_with_default ├── columns: ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── v_default:7 => v:2 - │ └── rowid_default:8 => rowid:3 + │ ├── column1:7 => a:1 + │ ├── v_default:8 => v:2 + │ └── rowid_default:9 => rowid:3 └── project - ├── columns: v_default:7!null rowid_default:8 column1:6!null - ├── values - │ ├── columns: column1:6!null - │ └── (1,) + ├── columns: v_default:8!null rowid_default:9 column1:7!null + ├── project + │ ├── columns: column1:7!null + │ ├── values + │ │ ├── columns: column1:6!null + │ │ └── (1,) + │ └── projections + │ └── assignment-cast: INT8 [as=column1:7] + │ └── column1:6 └── projections - ├── 3 [as=v_default:7] - └── unique_rowid() [as=rowid_default:8] + ├── 3 [as=v_default:8] + └── unique_rowid() [as=rowid_default:9] # With GENERATED AS IDENTITY syntax exec-ddl @@ -1488,18 +1775,25 @@ INSERT INTO generated_as_identity (a, c) VALUES (1, 10) insert generated_as_identity ├── columns: ├── insert-mapping: - │ ├── column1:7 => a:1 - │ ├── b_default:9 => b:2 - │ ├── column2:8 => c:3 - │ └── rowid_default:10 => rowid:4 + │ ├── column1:9 => a:1 + │ ├── b_default:11 => b:2 + │ ├── column2:10 => c:3 + │ └── rowid_default:12 => rowid:4 └── project - ├── columns: b_default:9 rowid_default:10 column1:7!null column2:8!null - ├── values - │ ├── columns: column1:7!null column2:8!null - │ └── (1, 10) + ├── columns: b_default:11 rowid_default:12 column1:9!null column2:10!null + ├── project + │ ├── columns: column1:9!null column2:10!null + │ ├── values + │ │ ├── columns: column1:7!null column2:8!null + │ │ └── (1, 10) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:9] + │ │ └── column1:7 + │ └── assignment-cast: INT8 [as=column2:10] + │ └── column2:8 └── projections - ├── nextval('t.public.generated_as_identity_b_seq') [as=b_default:9] - └── unique_rowid() [as=rowid_default:10] + ├── nextval('t.public.generated_as_identity_b_seq') [as=b_default:11] + └── unique_rowid() [as=rowid_default:12] build INSERT INTO generated_as_identity (a) VALUES (2) @@ -1507,19 +1801,24 @@ INSERT INTO generated_as_identity (a) VALUES (2) insert generated_as_identity ├── columns: ├── insert-mapping: - │ ├── column1:7 => a:1 - │ ├── b_default:8 => b:2 - │ ├── c_default:9 => c:3 - │ └── rowid_default:10 => rowid:4 + │ ├── column1:8 => a:1 + │ ├── b_default:9 => b:2 + │ ├── c_default:10 => c:3 + │ └── rowid_default:11 => rowid:4 └── project - ├── columns: b_default:8 c_default:9 rowid_default:10 column1:7!null - ├── values - │ ├── columns: column1:7!null - │ └── (2,) + ├── columns: b_default:9 c_default:10 rowid_default:11 column1:8!null + ├── project + │ ├── columns: column1:8!null + │ ├── values + │ │ ├── columns: column1:7!null + │ │ └── (2,) + │ └── projections + │ └── assignment-cast: INT8 [as=column1:8] + │ └── column1:7 └── projections - ├── nextval('t.public.generated_as_identity_b_seq') [as=b_default:8] - ├── nextval('t.public.generated_as_identity_c_seq') [as=c_default:9] - └── unique_rowid() [as=rowid_default:10] + ├── nextval('t.public.generated_as_identity_b_seq') [as=b_default:9] + ├── nextval('t.public.generated_as_identity_c_seq') [as=c_default:10] + └── unique_rowid() [as=rowid_default:11] # With SERIAL syntax exec-ddl @@ -1535,14 +1834,19 @@ INSERT INTO serial_t (b) VALUES (2) insert serial_t ├── columns: ├── insert-mapping: - │ ├── a_default:7 => a:1 - │ ├── column1:6 => b:2 - │ └── rowid_default:8 => rowid:3 + │ ├── a_default:8 => a:1 + │ ├── column1:7 => b:2 + │ └── rowid_default:9 => rowid:3 └── project - ├── columns: a_default:7 rowid_default:8 column1:6!null - ├── values - │ ├── columns: column1:6!null - │ └── (2,) + ├── columns: a_default:8 rowid_default:9 column1:7!null + ├── project + │ ├── columns: column1:7!null + │ ├── values + │ │ ├── columns: column1:6!null + │ │ └── (2,) + │ └── projections + │ └── assignment-cast: INT8 [as=column1:7] + │ └── column1:6 └── projections - ├── unique_rowid() [as=a_default:7] - └── unique_rowid() [as=rowid_default:8] + ├── unique_rowid() [as=a_default:8] + └── unique_rowid() [as=rowid_default:9] diff --git a/pkg/sql/opt/optbuilder/testdata/inverted-indexes b/pkg/sql/opt/optbuilder/testdata/inverted-indexes index 40e83575ad12..f996ef942bd0 100644 --- a/pkg/sql/opt/optbuilder/testdata/inverted-indexes +++ b/pkg/sql/opt/optbuilder/testdata/inverted-indexes @@ -44,11 +44,18 @@ INSERT INTO kj VALUES (1, '{"a": 2}') insert kj ├── columns: ├── insert-mapping: - │ ├── column1:6 => k:1 - │ └── column2:7 => j:2 - └── values - ├── columns: column1:6!null column2:7!null - └── (1, '{"a": 2}') + │ ├── column1:8 => k:1 + │ └── column2:9 => j:2 + └── project + ├── columns: column1:8!null column2:9!null + ├── values + │ ├── columns: column1:6!null column2:7!null + │ └── (1, '{"a": 2}') + └── projections + ├── assignment-cast: INT8 [as=column1:8] + │ └── column1:6 + └── assignment-cast: JSONB [as=column2:9] + └── column2:7 build UPSERT INTO kj VALUES (1, '{"a": 2}') @@ -90,23 +97,30 @@ insert kj ├── columns: ├── arbiter indexes: kj_pkey ├── insert-mapping: - │ ├── column1:6 => k:1 - │ └── column2:7 => j:2 + │ ├── column1:8 => k:1 + │ └── column2:9 => j:2 └── upsert-distinct-on - ├── columns: column1:6!null column2:7!null - ├── grouping columns: column1:6!null + ├── columns: column1:8!null column2:9!null + ├── grouping columns: column1:8!null ├── anti-join (hash) - │ ├── columns: column1:6!null column2:7!null - │ ├── values - │ │ ├── columns: column1:6!null column2:7!null - │ │ └── (1, '{"a": 2}') + │ ├── columns: column1:8!null column2:9!null + │ ├── project + │ │ ├── columns: column1:8!null column2:9!null + │ │ ├── values + │ │ │ ├── columns: column1:6!null column2:7!null + │ │ │ └── (1, '{"a": 2}') + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:8] + │ │ │ └── column1:6 + │ │ └── assignment-cast: JSONB [as=column2:9] + │ │ └── column2:7 │ ├── scan kj - │ │ └── columns: k:8!null j:9 + │ │ └── columns: k:10!null j:11 │ └── filters - │ └── column1:6 = k:8 + │ └── column1:8 = k:10 └── aggregations - └── first-agg [as=column2:7] - └── column2:7 + └── first-agg [as=column2:9] + └── column2:9 build INSERT INTO kj VALUES (1, '{"a": 2}') ON CONFLICT (k) DO UPDATE SET j = '{"a": 3}' diff --git a/pkg/sql/opt/optbuilder/testdata/partial-indexes b/pkg/sql/opt/optbuilder/testdata/partial-indexes index fede520fa668..097a4c431641 100644 --- a/pkg/sql/opt/optbuilder/testdata/partial-indexes +++ b/pkg/sql/opt/optbuilder/testdata/partial-indexes @@ -97,20 +97,29 @@ INSERT INTO partial_indexes VALUES (2, 1, 'bar') insert partial_indexes ├── columns: ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => b:2 - │ └── column3:8 => c:3 - ├── partial index put columns: partial_index_put1:9 partial_index_put2:10 partial_index_put3:11 partial_index_put4:12 + │ ├── column1:9 => a:1 + │ ├── column2:10 => b:2 + │ └── column3:11 => c:3 + ├── partial index put columns: partial_index_put1:12 partial_index_put2:13 partial_index_put3:14 partial_index_put4:15 └── project - ├── columns: partial_index_put1:9!null partial_index_put2:10!null partial_index_put3:11!null partial_index_put4:12!null column1:6!null column2:7!null column3:8!null - ├── values - │ ├── columns: column1:6!null column2:7!null column3:8!null - │ └── (2, 1, 'bar') + ├── columns: partial_index_put1:12!null partial_index_put2:13!null partial_index_put3:14!null partial_index_put4:15!null column1:9!null column2:10!null column3:11!null + ├── project + │ ├── columns: column1:9!null column2:10!null column3:11!null + │ ├── values + │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ └── (2, 1, 'bar') + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:9] + │ │ └── column1:6 + │ ├── assignment-cast: INT8 [as=column2:10] + │ │ └── column2:7 + │ └── assignment-cast: STRING [as=column3:11] + │ └── column3:8 └── projections - ├── column3:8 = 'foo' [as=partial_index_put1:9] - ├── (column1:6 > column2:7) AND (column3:8 = 'bar') [as=partial_index_put2:10] - ├── column3:8 = 'delete-only' [as=partial_index_put3:11] - └── column3:8 = 'write-only' [as=partial_index_put4:12] + ├── column3:11 = 'foo' [as=partial_index_put1:12] + ├── (column1:9 > column2:10) AND (column3:11 = 'bar') [as=partial_index_put2:13] + ├── column3:11 = 'delete-only' [as=partial_index_put3:14] + └── column3:11 = 'write-only' [as=partial_index_put4:15] # Do not error with "column reference is ambiguous" when table column names # match synthesized column names. @@ -120,29 +129,38 @@ INSERT INTO ambig (partial_index_put1, partial_index_del1, check1) VALUES (1, 2, insert ambig ├── columns: ├── insert-mapping: - │ ├── column1:7 => ambig.partial_index_put1:1 - │ ├── column2:8 => partial_index_del1:2 - │ ├── column3:9 => ambig.check1:3 - │ └── rowid_default:10 => rowid:4 - ├── check columns: check1:11 - ├── partial index put columns: partial_index_put1:12 partial_index_put2:13 partial_index_put3:14 + │ ├── column1:10 => ambig.partial_index_put1:1 + │ ├── column2:11 => partial_index_del1:2 + │ ├── column3:12 => ambig.check1:3 + │ └── rowid_default:13 => rowid:4 + ├── check columns: check1:14 + ├── partial index put columns: partial_index_put1:15 partial_index_put2:16 partial_index_put3:17 └── project - ├── columns: partial_index_put1:12!null partial_index_put2:13!null partial_index_put3:14!null column1:7!null column2:8!null column3:9!null rowid_default:10 check1:11!null + ├── columns: partial_index_put1:15!null partial_index_put2:16!null partial_index_put3:17!null column1:10!null column2:11!null column3:12!null rowid_default:13 check1:14!null ├── project - │ ├── columns: check1:11!null column1:7!null column2:8!null column3:9!null rowid_default:10 + │ ├── columns: check1:14!null column1:10!null column2:11!null column3:12!null rowid_default:13 │ ├── project - │ │ ├── columns: rowid_default:10 column1:7!null column2:8!null column3:9!null - │ │ ├── values - │ │ │ ├── columns: column1:7!null column2:8!null column3:9!null - │ │ │ └── (1, 2, 3) + │ │ ├── columns: rowid_default:13 column1:10!null column2:11!null column3:12!null + │ │ ├── project + │ │ │ ├── columns: column1:10!null column2:11!null column3:12!null + │ │ │ ├── values + │ │ │ │ ├── columns: column1:7!null column2:8!null column3:9!null + │ │ │ │ └── (1, 2, 3) + │ │ │ └── projections + │ │ │ ├── assignment-cast: INT8 [as=column1:10] + │ │ │ │ └── column1:7 + │ │ │ ├── assignment-cast: INT8 [as=column2:11] + │ │ │ │ └── column2:8 + │ │ │ └── assignment-cast: INT8 [as=column3:12] + │ │ │ └── column3:9 │ │ └── projections - │ │ └── unique_rowid() [as=rowid_default:10] + │ │ └── unique_rowid() [as=rowid_default:13] │ └── projections - │ └── column1:7 > 10 [as=check1:11] + │ └── column1:10 > 10 [as=check1:14] └── projections - ├── column1:7 > 0 [as=partial_index_put1:12] - ├── column2:8 > 0 [as=partial_index_put2:13] - └── column3:9 > 0 [as=partial_index_put3:14] + ├── column1:10 > 0 [as=partial_index_put1:15] + ├── column2:11 > 0 [as=partial_index_put2:16] + └── column3:12 > 0 [as=partial_index_put3:17] build INSERT INTO comp (a, b, c) VALUES (2, 1, 'Foo') @@ -150,25 +168,34 @@ INSERT INTO comp (a, b, c) VALUES (2, 1, 'Foo') insert comp ├── columns: ├── insert-mapping: - │ ├── column1:8 => a:1 - │ ├── column2:9 => b:2 - │ ├── column3:10 => c:3 - │ ├── d_comp:11 => d:4 - │ └── e_comp:12 => e:5 - ├── partial index put columns: partial_index_put1:13 partial_index_put2:14 + │ ├── column1:11 => a:1 + │ ├── column2:12 => b:2 + │ ├── column3:13 => c:3 + │ ├── d_comp:14 => d:4 + │ └── e_comp:15 => e:5 + ├── partial index put columns: partial_index_put1:16 partial_index_put2:17 └── project - ├── columns: partial_index_put1:13 partial_index_put2:14 column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + ├── columns: partial_index_put1:16 partial_index_put2:17 column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 ├── project - │ ├── columns: d_comp:11 e_comp:12 column1:8!null column2:9!null column3:10!null - │ ├── values - │ │ ├── columns: column1:8!null column2:9!null column3:10!null - │ │ └── (2, 1, 'Foo') + │ ├── columns: d_comp:14 e_comp:15 column1:11!null column2:12!null column3:13!null + │ ├── project + │ │ ├── columns: column1:11!null column2:12!null column3:13!null + │ │ ├── values + │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null + │ │ │ └── (2, 1, 'Foo') + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:11] + │ │ │ └── column1:8 + │ │ ├── assignment-cast: INT8 [as=column2:12] + │ │ │ └── column2:9 + │ │ └── assignment-cast: STRING [as=column3:13] + │ │ └── column3:10 │ └── projections - │ ├── lower(column3:10) [as=d_comp:11] - │ └── upper(column3:10) [as=e_comp:12] + │ ├── lower(column3:13) [as=d_comp:14] + │ └── upper(column3:13) [as=e_comp:15] └── projections - ├── d_comp:11 = 'foo' [as=partial_index_put1:13] - └── e_comp:12 = 'FOO' [as=partial_index_put2:14] + ├── d_comp:14 = 'foo' [as=partial_index_put1:16] + └── e_comp:15 = 'FOO' [as=partial_index_put2:17] # Regression test for issue #52546. Building partial index predicate expressions # that are only a single column reference should not panic. @@ -183,17 +210,24 @@ INSERT INTO t52546 VALUES (1, true) insert t52546 ├── columns: ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => b:2 - │ └── rowid_default:8 => rowid:3 - ├── partial index put columns: column2:7 + │ ├── column1:8 => a:1 + │ ├── column2:9 => b:2 + │ └── rowid_default:10 => rowid:3 + ├── partial index put columns: column2:9 └── project - ├── columns: rowid_default:8 column1:6!null column2:7!null - ├── values - │ ├── columns: column1:6!null column2:7!null - │ └── (1, true) + ├── columns: rowid_default:10 column1:8!null column2:9!null + ├── project + │ ├── columns: column1:8!null column2:9!null + │ ├── values + │ │ ├── columns: column1:6!null column2:7!null + │ │ └── (1, true) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:8] + │ │ └── column1:6 + │ └── assignment-cast: BOOL [as=column2:9] + │ └── column2:7 └── projections - └── unique_rowid() [as=rowid_default:8] + └── unique_rowid() [as=rowid_default:10] # -- DELETE tests -- @@ -594,65 +628,74 @@ insert partial_indexes ├── columns: ├── arbiter indexes: partial_indexes_pkey partial_indexes_b_c_key ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => b:2 - │ └── column3:8 => c:3 - ├── partial index put columns: partial_index_put1:19 partial_index_put2:20 partial_index_put3:21 partial_index_put4:22 + │ ├── column1:9 => a:1 + │ ├── column2:10 => b:2 + │ └── column3:11 => c:3 + ├── partial index put columns: partial_index_put1:22 partial_index_put2:23 partial_index_put3:24 partial_index_put4:25 └── project - ├── columns: partial_index_put1:19!null partial_index_put2:20!null partial_index_put3:21!null partial_index_put4:22!null column1:6!null column2:7!null column3:8!null + ├── columns: partial_index_put1:22!null partial_index_put2:23!null partial_index_put3:24!null partial_index_put4:25!null column1:9!null column2:10!null column3:11!null ├── upsert-distinct-on - │ ├── columns: column1:6!null column2:7!null column3:8!null - │ ├── grouping columns: column2:7!null column3:8!null + │ ├── columns: column1:9!null column2:10!null column3:11!null + │ ├── grouping columns: column2:10!null column3:11!null │ ├── upsert-distinct-on - │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ ├── grouping columns: column1:6!null + │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ ├── grouping columns: column1:9!null │ │ ├── anti-join (hash) - │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null │ │ │ ├── anti-join (hash) - │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ ├── values - │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ │ └── (2, 1, 'bar') + │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ ├── project + │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ │ ├── values + │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ │ │ └── (2, 1, 'bar') + │ │ │ │ │ └── projections + │ │ │ │ │ ├── assignment-cast: INT8 [as=column1:9] + │ │ │ │ │ │ └── column1:6 + │ │ │ │ │ ├── assignment-cast: INT8 [as=column2:10] + │ │ │ │ │ │ └── column2:7 + │ │ │ │ │ └── assignment-cast: STRING [as=column3:11] + │ │ │ │ │ └── column3:8 │ │ │ │ ├── scan partial_indexes - │ │ │ │ │ ├── columns: a:9!null b:10 c:11 + │ │ │ │ │ ├── columns: a:12!null b:13 c:14 │ │ │ │ │ └── partial index predicates │ │ │ │ │ ├── partial_indexes_b_idx1: filters - │ │ │ │ │ │ └── c:11 = 'foo' + │ │ │ │ │ │ └── c:14 = 'foo' │ │ │ │ │ ├── partial_indexes_c_idx: filters - │ │ │ │ │ │ └── (a:9 > b:10) AND (c:11 = 'bar') + │ │ │ │ │ │ └── (a:12 > b:13) AND (c:14 = 'bar') │ │ │ │ │ ├── b: filters - │ │ │ │ │ │ └── c:11 = 'delete-only' + │ │ │ │ │ │ └── c:14 = 'delete-only' │ │ │ │ │ └── b: filters - │ │ │ │ │ └── c:11 = 'write-only' + │ │ │ │ │ └── c:14 = 'write-only' │ │ │ │ └── filters - │ │ │ │ └── column1:6 = a:9 + │ │ │ │ └── column1:9 = a:12 │ │ │ ├── scan partial_indexes - │ │ │ │ ├── columns: a:14!null b:15 c:16 + │ │ │ │ ├── columns: a:17!null b:18 c:19 │ │ │ │ └── partial index predicates │ │ │ │ ├── partial_indexes_b_idx1: filters - │ │ │ │ │ └── c:16 = 'foo' + │ │ │ │ │ └── c:19 = 'foo' │ │ │ │ ├── partial_indexes_c_idx: filters - │ │ │ │ │ └── (a:14 > b:15) AND (c:16 = 'bar') + │ │ │ │ │ └── (a:17 > b:18) AND (c:19 = 'bar') │ │ │ │ ├── b: filters - │ │ │ │ │ └── c:16 = 'delete-only' + │ │ │ │ │ └── c:19 = 'delete-only' │ │ │ │ └── b: filters - │ │ │ │ └── c:16 = 'write-only' + │ │ │ │ └── c:19 = 'write-only' │ │ │ └── filters - │ │ │ ├── column2:7 = b:15 - │ │ │ └── column3:8 = c:16 + │ │ │ ├── column2:10 = b:18 + │ │ │ └── column3:11 = c:19 │ │ └── aggregations - │ │ ├── first-agg [as=column2:7] - │ │ │ └── column2:7 - │ │ └── first-agg [as=column3:8] - │ │ └── column3:8 + │ │ ├── first-agg [as=column2:10] + │ │ │ └── column2:10 + │ │ └── first-agg [as=column3:11] + │ │ └── column3:11 │ └── aggregations - │ └── first-agg [as=column1:6] - │ └── column1:6 + │ └── first-agg [as=column1:9] + │ └── column1:9 └── projections - ├── column3:8 = 'foo' [as=partial_index_put1:19] - ├── (column1:6 > column2:7) AND (column3:8 = 'bar') [as=partial_index_put2:20] - ├── column3:8 = 'delete-only' [as=partial_index_put3:21] - └── column3:8 = 'write-only' [as=partial_index_put4:22] + ├── column3:11 = 'foo' [as=partial_index_put1:22] + ├── (column1:9 > column2:10) AND (column3:11 = 'bar') [as=partial_index_put2:23] + ├── column3:11 = 'delete-only' [as=partial_index_put3:24] + └── column3:11 = 'write-only' [as=partial_index_put4:25] build INSERT INTO partial_indexes VALUES (2, 1, 'bar') ON CONFLICT (b, c) DO UPDATE SET b = partial_indexes.b + 1, c = 'baz' @@ -793,57 +836,66 @@ insert comp ├── columns: ├── arbiter indexes: comp_pkey ├── insert-mapping: - │ ├── column1:8 => a:1 - │ ├── column2:9 => b:2 - │ ├── column3:10 => c:3 - │ ├── d_comp:11 => d:4 - │ └── e_comp:12 => e:5 - ├── partial index put columns: partial_index_put1:20 partial_index_put2:21 + │ ├── column1:11 => a:1 + │ ├── column2:12 => b:2 + │ ├── column3:13 => c:3 + │ ├── d_comp:14 => d:4 + │ └── e_comp:15 => e:5 + ├── partial index put columns: partial_index_put1:23 partial_index_put2:24 └── project - ├── columns: partial_index_put1:20 partial_index_put2:21 column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + ├── columns: partial_index_put1:23 partial_index_put2:24 column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 ├── upsert-distinct-on - │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 - │ ├── grouping columns: column1:8!null + │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 + │ ├── grouping columns: column1:11!null │ ├── anti-join (hash) - │ │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + │ │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 │ │ ├── project - │ │ │ ├── columns: d_comp:11 e_comp:12 column1:8!null column2:9!null column3:10!null - │ │ │ ├── values - │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null - │ │ │ │ └── (2, 1, 'Foo') + │ │ │ ├── columns: d_comp:14 e_comp:15 column1:11!null column2:12!null column3:13!null + │ │ │ ├── project + │ │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null + │ │ │ │ ├── values + │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null + │ │ │ │ │ └── (2, 1, 'Foo') + │ │ │ │ └── projections + │ │ │ │ ├── assignment-cast: INT8 [as=column1:11] + │ │ │ │ │ └── column1:8 + │ │ │ │ ├── assignment-cast: INT8 [as=column2:12] + │ │ │ │ │ └── column2:9 + │ │ │ │ └── assignment-cast: STRING [as=column3:13] + │ │ │ │ └── column3:10 │ │ │ └── projections - │ │ │ ├── lower(column3:10) [as=d_comp:11] - │ │ │ └── upper(column3:10) [as=e_comp:12] + │ │ │ ├── lower(column3:13) [as=d_comp:14] + │ │ │ └── upper(column3:13) [as=e_comp:15] │ │ ├── project - │ │ │ ├── columns: d:16 a:13!null b:14 c:15 e:17 + │ │ │ ├── columns: d:19 a:16!null b:17 c:18 e:20 │ │ │ ├── scan comp - │ │ │ │ ├── columns: a:13!null b:14 c:15 e:17 + │ │ │ │ ├── columns: a:16!null b:17 c:18 e:20 │ │ │ │ ├── computed column expressions - │ │ │ │ │ ├── d:16 - │ │ │ │ │ │ └── lower(c:15) - │ │ │ │ │ └── e:17 - │ │ │ │ │ └── upper(c:15) + │ │ │ │ │ ├── d:19 + │ │ │ │ │ │ └── lower(c:18) + │ │ │ │ │ └── e:20 + │ │ │ │ │ └── upper(c:18) │ │ │ │ └── partial index predicates │ │ │ │ ├── comp_b_idx: filters - │ │ │ │ │ └── lower(c:15) = 'foo' + │ │ │ │ │ └── lower(c:18) = 'foo' │ │ │ │ └── comp_b_idx1: filters - │ │ │ │ └── e:17 = 'FOO' + │ │ │ │ └── e:20 = 'FOO' │ │ │ └── projections - │ │ │ └── lower(c:15) [as=d:16] + │ │ │ └── lower(c:18) [as=d:19] │ │ └── filters - │ │ └── column1:8 = a:13 + │ │ └── column1:11 = a:16 │ └── aggregations - │ ├── first-agg [as=column2:9] - │ │ └── column2:9 - │ ├── first-agg [as=column3:10] - │ │ └── column3:10 - │ ├── first-agg [as=d_comp:11] - │ │ └── d_comp:11 - │ └── first-agg [as=e_comp:12] - │ └── e_comp:12 + │ ├── first-agg [as=column2:12] + │ │ └── column2:12 + │ ├── first-agg [as=column3:13] + │ │ └── column3:13 + │ ├── first-agg [as=d_comp:14] + │ │ └── d_comp:14 + │ └── first-agg [as=e_comp:15] + │ └── e_comp:15 └── projections - ├── d_comp:11 = 'foo' [as=partial_index_put1:20] - └── e_comp:12 = 'FOO' [as=partial_index_put2:21] + ├── d_comp:14 = 'foo' [as=partial_index_put1:23] + └── e_comp:15 = 'FOO' [as=partial_index_put2:24] build INSERT INTO comp VALUES (2, 1, 'Foo') ON CONFLICT (a) DO UPDATE SET b = comp.b + 1, c = 'Bar' @@ -1012,62 +1064,71 @@ insert uniq ├── columns: ├── arbiter indexes: uniq_pkey uniq_b_key ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => b:2 - │ └── column3:8 => c:3 - ├── partial index put columns: partial_index_put1:20 + │ ├── column1:9 => a:1 + │ ├── column2:10 => b:2 + │ └── column3:11 => c:3 + ├── partial index put columns: partial_index_put1:23 └── project - ├── columns: partial_index_put1:20!null column1:6!null column2:7!null column3:8!null + ├── columns: partial_index_put1:23!null column1:9!null column2:10!null column3:11!null ├── project - │ ├── columns: column1:6!null column2:7!null column3:8!null + │ ├── columns: column1:9!null column2:10!null column3:11!null │ └── upsert-distinct-on - │ ├── columns: column1:6!null column2:7!null column3:8!null arbiter_uniq_b_key_distinct:19 - │ ├── grouping columns: column2:7!null arbiter_uniq_b_key_distinct:19 + │ ├── columns: column1:9!null column2:10!null column3:11!null arbiter_uniq_b_key_distinct:22 + │ ├── grouping columns: column2:10!null arbiter_uniq_b_key_distinct:22 │ ├── project - │ │ ├── columns: arbiter_uniq_b_key_distinct:19 column1:6!null column2:7!null column3:8!null + │ │ ├── columns: arbiter_uniq_b_key_distinct:22 column1:9!null column2:10!null column3:11!null │ │ ├── upsert-distinct-on - │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ ├── grouping columns: column1:6!null + │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ ├── grouping columns: column1:9!null │ │ │ ├── anti-join (hash) - │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ │ ├── values - │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ │ │ └── (1, 1, 'bar') + │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ │ ├── project + │ │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ │ │ ├── values + │ │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ │ │ │ └── (1, 1, 'bar') + │ │ │ │ │ │ └── projections + │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column1:9] + │ │ │ │ │ │ │ └── column1:6 + │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column2:10] + │ │ │ │ │ │ │ └── column2:7 + │ │ │ │ │ │ └── assignment-cast: STRING [as=column3:11] + │ │ │ │ │ │ └── column3:8 │ │ │ │ │ ├── scan uniq - │ │ │ │ │ │ ├── columns: a:9!null b:10 c:11 + │ │ │ │ │ │ ├── columns: a:12!null b:13 c:14 │ │ │ │ │ │ └── partial index predicates │ │ │ │ │ │ └── uniq_b_key: filters - │ │ │ │ │ │ └── c:11 = 'foo' + │ │ │ │ │ │ └── c:14 = 'foo' │ │ │ │ │ └── filters - │ │ │ │ │ └── column1:6 = a:9 + │ │ │ │ │ └── column1:9 = a:12 │ │ │ │ ├── select - │ │ │ │ │ ├── columns: a:14!null b:15 c:16!null + │ │ │ │ │ ├── columns: a:17!null b:18 c:19!null │ │ │ │ │ ├── scan uniq - │ │ │ │ │ │ ├── columns: a:14!null b:15 c:16 + │ │ │ │ │ │ ├── columns: a:17!null b:18 c:19 │ │ │ │ │ │ └── partial index predicates │ │ │ │ │ │ └── uniq_b_key: filters - │ │ │ │ │ │ └── c:16 = 'foo' + │ │ │ │ │ │ └── c:19 = 'foo' │ │ │ │ │ └── filters - │ │ │ │ │ └── c:16 = 'foo' + │ │ │ │ │ └── c:19 = 'foo' │ │ │ │ └── filters - │ │ │ │ ├── column2:7 = b:15 - │ │ │ │ └── column3:8 = 'foo' + │ │ │ │ ├── column2:10 = b:18 + │ │ │ │ └── column3:11 = 'foo' │ │ │ └── aggregations - │ │ │ ├── first-agg [as=column2:7] - │ │ │ │ └── column2:7 - │ │ │ └── first-agg [as=column3:8] - │ │ │ └── column3:8 + │ │ │ ├── first-agg [as=column2:10] + │ │ │ │ └── column2:10 + │ │ │ └── first-agg [as=column3:11] + │ │ │ └── column3:11 │ │ └── projections - │ │ └── (column3:8 = 'foo') OR NULL::BOOL [as=arbiter_uniq_b_key_distinct:19] + │ │ └── (column3:11 = 'foo') OR NULL::BOOL [as=arbiter_uniq_b_key_distinct:22] │ └── aggregations - │ ├── first-agg [as=column1:6] - │ │ └── column1:6 - │ └── first-agg [as=column3:8] - │ └── column3:8 + │ ├── first-agg [as=column1:9] + │ │ └── column1:9 + │ └── first-agg [as=column3:11] + │ └── column3:11 └── projections - └── column3:8 = 'foo' [as=partial_index_put1:20] + └── column3:11 = 'foo' [as=partial_index_put1:23] exec-ddl CREATE UNIQUE INDEX u2 ON uniq (b) WHERE c = 'bar' @@ -1081,78 +1142,87 @@ insert uniq ├── columns: ├── arbiter indexes: uniq_b_key u2 ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => b:2 - │ └── column3:8 => c:3 - ├── partial index put columns: partial_index_put1:21 partial_index_put2:22 + │ ├── column1:9 => a:1 + │ ├── column2:10 => b:2 + │ └── column3:11 => c:3 + ├── partial index put columns: partial_index_put1:24 partial_index_put2:25 └── project - ├── columns: partial_index_put1:21!null partial_index_put2:22!null column1:6!null column2:7!null column3:8!null + ├── columns: partial_index_put1:24!null partial_index_put2:25!null column1:9!null column2:10!null column3:11!null ├── project - │ ├── columns: column1:6!null column2:7!null column3:8!null + │ ├── columns: column1:9!null column2:10!null column3:11!null │ └── upsert-distinct-on - │ ├── columns: column1:6!null column2:7!null column3:8!null arbiter_u2_distinct:20 - │ ├── grouping columns: column2:7!null arbiter_u2_distinct:20 + │ ├── columns: column1:9!null column2:10!null column3:11!null arbiter_u2_distinct:23 + │ ├── grouping columns: column2:10!null arbiter_u2_distinct:23 │ ├── project - │ │ ├── columns: arbiter_u2_distinct:20 column1:6!null column2:7!null column3:8!null + │ │ ├── columns: arbiter_u2_distinct:23 column1:9!null column2:10!null column3:11!null │ │ ├── project - │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null │ │ │ └── upsert-distinct-on - │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null arbiter_uniq_b_key_distinct:19 - │ │ │ ├── grouping columns: column2:7!null arbiter_uniq_b_key_distinct:19 + │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null arbiter_uniq_b_key_distinct:22 + │ │ │ ├── grouping columns: column2:10!null arbiter_uniq_b_key_distinct:22 │ │ │ ├── project - │ │ │ │ ├── columns: arbiter_uniq_b_key_distinct:19 column1:6!null column2:7!null column3:8!null + │ │ │ │ ├── columns: arbiter_uniq_b_key_distinct:22 column1:9!null column2:10!null column3:11!null │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null │ │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ │ │ ├── values - │ │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ │ │ │ └── (1, 1, 'bar') + │ │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ │ │ ├── project + │ │ │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ │ │ │ ├── values + │ │ │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ │ │ │ │ └── (1, 1, 'bar') + │ │ │ │ │ │ │ └── projections + │ │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column1:9] + │ │ │ │ │ │ │ │ └── column1:6 + │ │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column2:10] + │ │ │ │ │ │ │ │ └── column2:7 + │ │ │ │ │ │ │ └── assignment-cast: STRING [as=column3:11] + │ │ │ │ │ │ │ └── column3:8 │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ ├── columns: a:9!null b:10 c:11!null + │ │ │ │ │ │ │ ├── columns: a:12!null b:13 c:14!null │ │ │ │ │ │ │ ├── scan uniq - │ │ │ │ │ │ │ │ ├── columns: a:9!null b:10 c:11 + │ │ │ │ │ │ │ │ ├── columns: a:12!null b:13 c:14 │ │ │ │ │ │ │ │ └── partial index predicates │ │ │ │ │ │ │ │ ├── uniq_b_key: filters - │ │ │ │ │ │ │ │ │ └── c:11 = 'foo' + │ │ │ │ │ │ │ │ │ └── c:14 = 'foo' │ │ │ │ │ │ │ │ └── u2: filters - │ │ │ │ │ │ │ │ └── c:11 = 'bar' + │ │ │ │ │ │ │ │ └── c:14 = 'bar' │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ └── c:11 = 'foo' + │ │ │ │ │ │ │ └── c:14 = 'foo' │ │ │ │ │ │ └── filters - │ │ │ │ │ │ ├── column2:7 = b:10 - │ │ │ │ │ │ └── column3:8 = 'foo' + │ │ │ │ │ │ ├── column2:10 = b:13 + │ │ │ │ │ │ └── column3:11 = 'foo' │ │ │ │ │ ├── select - │ │ │ │ │ │ ├── columns: a:14!null b:15 c:16!null + │ │ │ │ │ │ ├── columns: a:17!null b:18 c:19!null │ │ │ │ │ │ ├── scan uniq - │ │ │ │ │ │ │ ├── columns: a:14!null b:15 c:16 + │ │ │ │ │ │ │ ├── columns: a:17!null b:18 c:19 │ │ │ │ │ │ │ └── partial index predicates │ │ │ │ │ │ │ ├── uniq_b_key: filters - │ │ │ │ │ │ │ │ └── c:16 = 'foo' + │ │ │ │ │ │ │ │ └── c:19 = 'foo' │ │ │ │ │ │ │ └── u2: filters - │ │ │ │ │ │ │ └── c:16 = 'bar' + │ │ │ │ │ │ │ └── c:19 = 'bar' │ │ │ │ │ │ └── filters - │ │ │ │ │ │ └── c:16 = 'bar' + │ │ │ │ │ │ └── c:19 = 'bar' │ │ │ │ │ └── filters - │ │ │ │ │ ├── column2:7 = b:15 - │ │ │ │ │ └── column3:8 = 'bar' + │ │ │ │ │ ├── column2:10 = b:18 + │ │ │ │ │ └── column3:11 = 'bar' │ │ │ │ └── projections - │ │ │ │ └── (column3:8 = 'foo') OR NULL::BOOL [as=arbiter_uniq_b_key_distinct:19] + │ │ │ │ └── (column3:11 = 'foo') OR NULL::BOOL [as=arbiter_uniq_b_key_distinct:22] │ │ │ └── aggregations - │ │ │ ├── first-agg [as=column1:6] - │ │ │ │ └── column1:6 - │ │ │ └── first-agg [as=column3:8] - │ │ │ └── column3:8 + │ │ │ ├── first-agg [as=column1:9] + │ │ │ │ └── column1:9 + │ │ │ └── first-agg [as=column3:11] + │ │ │ └── column3:11 │ │ └── projections - │ │ └── (column3:8 = 'bar') OR NULL::BOOL [as=arbiter_u2_distinct:20] + │ │ └── (column3:11 = 'bar') OR NULL::BOOL [as=arbiter_u2_distinct:23] │ └── aggregations - │ ├── first-agg [as=column1:6] - │ │ └── column1:6 - │ └── first-agg [as=column3:8] - │ └── column3:8 + │ ├── first-agg [as=column1:9] + │ │ └── column1:9 + │ └── first-agg [as=column3:11] + │ └── column3:11 └── projections - ├── column3:8 = 'foo' [as=partial_index_put1:21] - └── column3:8 = 'bar' [as=partial_index_put2:22] + ├── column3:11 = 'foo' [as=partial_index_put1:24] + └── column3:11 = 'bar' [as=partial_index_put2:25] # Error when no arbiter is found because the arbiter predicate in the query # (non-existent in this case) does not imply any unique partial index predicates @@ -1176,37 +1246,46 @@ insert uniq ├── columns: ├── arbiter indexes: u3 ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => b:2 - │ └── column3:8 => c:3 - ├── partial index put columns: partial_index_put1:14 partial_index_put2:15 + │ ├── column1:9 => a:1 + │ ├── column2:10 => b:2 + │ └── column3:11 => c:3 + ├── partial index put columns: partial_index_put1:17 partial_index_put2:18 └── project - ├── columns: partial_index_put1:14!null partial_index_put2:15!null column1:6!null column2:7!null column3:8!null + ├── columns: partial_index_put1:17!null partial_index_put2:18!null column1:9!null column2:10!null column3:11!null ├── upsert-distinct-on - │ ├── columns: column1:6!null column2:7!null column3:8!null - │ ├── grouping columns: column2:7!null + │ ├── columns: column1:9!null column2:10!null column3:11!null + │ ├── grouping columns: column2:10!null │ ├── anti-join (hash) - │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ ├── values - │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ └── (1, 1, 'bar') + │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ ├── project + │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ ├── values + │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ └── (1, 1, 'bar') + │ │ │ └── projections + │ │ │ ├── assignment-cast: INT8 [as=column1:9] + │ │ │ │ └── column1:6 + │ │ │ ├── assignment-cast: INT8 [as=column2:10] + │ │ │ │ └── column2:7 + │ │ │ └── assignment-cast: STRING [as=column3:11] + │ │ │ └── column3:8 │ │ ├── scan uniq - │ │ │ ├── columns: a:9!null b:10 c:11 + │ │ │ ├── columns: a:12!null b:13 c:14 │ │ │ └── partial index predicates │ │ │ ├── uniq_b_key: filters - │ │ │ │ └── c:11 = 'foo' + │ │ │ │ └── c:14 = 'foo' │ │ │ └── u2: filters - │ │ │ └── c:11 = 'bar' + │ │ │ └── c:14 = 'bar' │ │ └── filters - │ │ └── column2:7 = b:10 + │ │ └── column2:10 = b:13 │ └── aggregations - │ ├── first-agg [as=column1:6] - │ │ └── column1:6 - │ └── first-agg [as=column3:8] - │ └── column3:8 + │ ├── first-agg [as=column1:9] + │ │ └── column1:9 + │ └── first-agg [as=column3:11] + │ └── column3:11 └── projections - ├── column3:8 = 'foo' [as=partial_index_put1:14] - └── column3:8 = 'bar' [as=partial_index_put2:15] + ├── column3:11 = 'foo' [as=partial_index_put1:17] + └── column3:11 = 'bar' [as=partial_index_put2:18] exec-ddl DROP INDEX u3 @@ -1232,28 +1311,47 @@ insert uniq ├── columns: ├── arbiter indexes: u4 ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => b:2 - │ └── column3:8 => c:3 - ├── partial index put columns: partial_index_put1:15 partial_index_put2:16 partial_index_put3:17 + │ ├── column1:9 => a:1 + │ ├── column2:10 => b:2 + │ └── column3:11 => c:3 + ├── partial index put columns: partial_index_put1:18 partial_index_put2:19 partial_index_put3:20 └── project - ├── columns: partial_index_put1:15!null partial_index_put2:16!null partial_index_put3:17!null column1:6!null column2:7!null column3:8!null - ├── anti-join (cross) - │ ├── columns: column1:6!null column2:7!null column3:8!null - │ ├── values - │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ └── (1, 1, 'bar') - │ ├── select - │ │ ├── columns: b:10!null - │ │ ├── scan uniq@u4,partial - │ │ │ └── columns: b:10 - │ │ └── filters - │ │ └── b:10 = 1 - │ └── filters (true) + ├── columns: partial_index_put1:18 partial_index_put2:19 partial_index_put3:20!null column1:9 column2:10 column3:11 + ├── upsert-distinct-on + │ ├── columns: column1:9 column2:10 column3:11 arbiter_u4_distinct:17!null + │ ├── grouping columns: column2:10 + │ ├── project + │ │ ├── columns: arbiter_u4_distinct:17!null column1:9 column2:10 column3:11 + │ │ ├── anti-join (merge) + │ │ │ ├── columns: column1:9 column2:10 column3:11 + │ │ │ ├── left ordering: +10 + │ │ │ ├── right ordering: +13 + │ │ │ ├── values + │ │ │ │ ├── columns: column1:9 column2:10 column3:11 + │ │ │ │ └── tuple + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 1 + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 1 + │ │ │ │ └── assignment-cast: STRING + │ │ │ │ └── 'bar' + │ │ │ ├── scan uniq@u4,partial + │ │ │ │ ├── columns: b:13 + │ │ │ │ └── ordering: +13 + │ │ │ └── filters (true) + │ │ └── projections + │ │ └── true [as=arbiter_u4_distinct:17] + │ └── aggregations + │ ├── first-agg [as=column1:9] + │ │ └── column1:9 + │ ├── first-agg [as=column3:11] + │ │ └── column3:11 + │ └── const-agg [as=arbiter_u4_distinct:17] + │ └── arbiter_u4_distinct:17 └── projections - ├── column3:8 = 'foo' [as=partial_index_put1:15] - ├── column3:8 = 'bar' [as=partial_index_put2:16] - └── true [as=partial_index_put3:17] + ├── column3:11 = 'foo' [as=partial_index_put1:18] + ├── column3:11 = 'bar' [as=partial_index_put2:19] + └── true [as=partial_index_put3:20] exec-ddl DROP INDEX u4 @@ -1434,104 +1532,113 @@ insert comp ├── columns: ├── arbiter indexes: comp_pkey u1 ├── insert-mapping: - │ ├── column1:8 => a:1 - │ ├── column2:9 => b:2 - │ ├── column3:10 => c:3 - │ ├── d_comp:11 => d:4 - │ └── e_comp:12 => e:5 - ├── partial index put columns: partial_index_put1:28 partial_index_put2:29 partial_index_put1:28 + │ ├── column1:11 => a:1 + │ ├── column2:12 => b:2 + │ ├── column3:13 => c:3 + │ ├── d_comp:14 => d:4 + │ └── e_comp:15 => e:5 + ├── partial index put columns: partial_index_put1:31 partial_index_put2:32 partial_index_put1:31 └── project - ├── columns: partial_index_put1:28 partial_index_put2:29 column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + ├── columns: partial_index_put1:31 partial_index_put2:32 column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 ├── project - │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 │ └── upsert-distinct-on - │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 arbiter_u1_distinct:27 - │ ├── grouping columns: column2:9!null arbiter_u1_distinct:27 + │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 arbiter_u1_distinct:30 + │ ├── grouping columns: column2:12!null arbiter_u1_distinct:30 │ ├── project - │ │ ├── columns: arbiter_u1_distinct:27 column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + │ │ ├── columns: arbiter_u1_distinct:30 column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 │ │ ├── upsert-distinct-on - │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 - │ │ │ ├── grouping columns: column1:8!null + │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 + │ │ │ ├── grouping columns: column1:11!null │ │ │ ├── anti-join (hash) - │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + │ │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + │ │ │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 │ │ │ │ │ ├── project - │ │ │ │ │ │ ├── columns: d_comp:11 e_comp:12 column1:8!null column2:9!null column3:10!null - │ │ │ │ │ │ ├── values - │ │ │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null - │ │ │ │ │ │ │ └── (1, 1, 'bar') + │ │ │ │ │ │ ├── columns: d_comp:14 e_comp:15 column1:11!null column2:12!null column3:13!null + │ │ │ │ │ │ ├── project + │ │ │ │ │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null + │ │ │ │ │ │ │ ├── values + │ │ │ │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null + │ │ │ │ │ │ │ │ └── (1, 1, 'bar') + │ │ │ │ │ │ │ └── projections + │ │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column1:11] + │ │ │ │ │ │ │ │ └── column1:8 + │ │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column2:12] + │ │ │ │ │ │ │ │ └── column2:9 + │ │ │ │ │ │ │ └── assignment-cast: STRING [as=column3:13] + │ │ │ │ │ │ │ └── column3:10 │ │ │ │ │ │ └── projections - │ │ │ │ │ │ ├── lower(column3:10) [as=d_comp:11] - │ │ │ │ │ │ └── upper(column3:10) [as=e_comp:12] + │ │ │ │ │ │ ├── lower(column3:13) [as=d_comp:14] + │ │ │ │ │ │ └── upper(column3:13) [as=e_comp:15] │ │ │ │ │ ├── project - │ │ │ │ │ │ ├── columns: d:16 a:13!null b:14 c:15 e:17 + │ │ │ │ │ │ ├── columns: d:19 a:16!null b:17 c:18 e:20 │ │ │ │ │ │ ├── scan comp - │ │ │ │ │ │ │ ├── columns: a:13!null b:14 c:15 e:17 + │ │ │ │ │ │ │ ├── columns: a:16!null b:17 c:18 e:20 │ │ │ │ │ │ │ ├── computed column expressions - │ │ │ │ │ │ │ │ ├── d:16 - │ │ │ │ │ │ │ │ │ └── lower(c:15) - │ │ │ │ │ │ │ │ └── e:17 - │ │ │ │ │ │ │ │ └── upper(c:15) + │ │ │ │ │ │ │ │ ├── d:19 + │ │ │ │ │ │ │ │ │ └── lower(c:18) + │ │ │ │ │ │ │ │ └── e:20 + │ │ │ │ │ │ │ │ └── upper(c:18) │ │ │ │ │ │ │ └── partial index predicates │ │ │ │ │ │ │ ├── comp_b_idx: filters - │ │ │ │ │ │ │ │ └── lower(c:15) = 'foo' + │ │ │ │ │ │ │ │ └── lower(c:18) = 'foo' │ │ │ │ │ │ │ ├── comp_b_idx1: filters - │ │ │ │ │ │ │ │ └── e:17 = 'FOO' + │ │ │ │ │ │ │ │ └── e:20 = 'FOO' │ │ │ │ │ │ │ └── u1: filters - │ │ │ │ │ │ │ └── lower(c:15) = 'foo' + │ │ │ │ │ │ │ └── lower(c:18) = 'foo' │ │ │ │ │ │ └── projections - │ │ │ │ │ │ └── lower(c:15) [as=d:16] + │ │ │ │ │ │ └── lower(c:18) [as=d:19] │ │ │ │ │ └── filters - │ │ │ │ │ └── column1:8 = a:13 + │ │ │ │ │ └── column1:11 = a:16 │ │ │ │ ├── select - │ │ │ │ │ ├── columns: a:20!null b:21 c:22 d:23!null e:24 + │ │ │ │ │ ├── columns: a:23!null b:24 c:25 d:26!null e:27 │ │ │ │ │ ├── project - │ │ │ │ │ │ ├── columns: d:23 a:20!null b:21 c:22 e:24 + │ │ │ │ │ │ ├── columns: d:26 a:23!null b:24 c:25 e:27 │ │ │ │ │ │ ├── scan comp - │ │ │ │ │ │ │ ├── columns: a:20!null b:21 c:22 e:24 + │ │ │ │ │ │ │ ├── columns: a:23!null b:24 c:25 e:27 │ │ │ │ │ │ │ ├── computed column expressions - │ │ │ │ │ │ │ │ ├── d:23 - │ │ │ │ │ │ │ │ │ └── lower(c:22) - │ │ │ │ │ │ │ │ └── e:24 - │ │ │ │ │ │ │ │ └── upper(c:22) + │ │ │ │ │ │ │ │ ├── d:26 + │ │ │ │ │ │ │ │ │ └── lower(c:25) + │ │ │ │ │ │ │ │ └── e:27 + │ │ │ │ │ │ │ │ └── upper(c:25) │ │ │ │ │ │ │ └── partial index predicates │ │ │ │ │ │ │ ├── comp_b_idx: filters - │ │ │ │ │ │ │ │ └── lower(c:22) = 'foo' + │ │ │ │ │ │ │ │ └── lower(c:25) = 'foo' │ │ │ │ │ │ │ ├── comp_b_idx1: filters - │ │ │ │ │ │ │ │ └── e:24 = 'FOO' + │ │ │ │ │ │ │ │ └── e:27 = 'FOO' │ │ │ │ │ │ │ └── u1: filters - │ │ │ │ │ │ │ └── lower(c:22) = 'foo' + │ │ │ │ │ │ │ └── lower(c:25) = 'foo' │ │ │ │ │ │ └── projections - │ │ │ │ │ │ └── lower(c:22) [as=d:23] + │ │ │ │ │ │ └── lower(c:25) [as=d:26] │ │ │ │ │ └── filters - │ │ │ │ │ └── d:23 = 'foo' + │ │ │ │ │ └── d:26 = 'foo' │ │ │ │ └── filters - │ │ │ │ ├── column2:9 = b:21 - │ │ │ │ └── d_comp:11 = 'foo' + │ │ │ │ ├── column2:12 = b:24 + │ │ │ │ └── d_comp:14 = 'foo' │ │ │ └── aggregations - │ │ │ ├── first-agg [as=column2:9] - │ │ │ │ └── column2:9 - │ │ │ ├── first-agg [as=column3:10] - │ │ │ │ └── column3:10 - │ │ │ ├── first-agg [as=d_comp:11] - │ │ │ │ └── d_comp:11 - │ │ │ └── first-agg [as=e_comp:12] - │ │ │ └── e_comp:12 + │ │ │ ├── first-agg [as=column2:12] + │ │ │ │ └── column2:12 + │ │ │ ├── first-agg [as=column3:13] + │ │ │ │ └── column3:13 + │ │ │ ├── first-agg [as=d_comp:14] + │ │ │ │ └── d_comp:14 + │ │ │ └── first-agg [as=e_comp:15] + │ │ │ └── e_comp:15 │ │ └── projections - │ │ └── (d_comp:11 = 'foo') OR NULL::BOOL [as=arbiter_u1_distinct:27] + │ │ └── (d_comp:14 = 'foo') OR NULL::BOOL [as=arbiter_u1_distinct:30] │ └── aggregations - │ ├── first-agg [as=column1:8] - │ │ └── column1:8 - │ ├── first-agg [as=column3:10] - │ │ └── column3:10 - │ ├── first-agg [as=d_comp:11] - │ │ └── d_comp:11 - │ └── first-agg [as=e_comp:12] - │ └── e_comp:12 + │ ├── first-agg [as=column1:11] + │ │ └── column1:11 + │ ├── first-agg [as=column3:13] + │ │ └── column3:13 + │ ├── first-agg [as=d_comp:14] + │ │ └── d_comp:14 + │ └── first-agg [as=e_comp:15] + │ └── e_comp:15 └── projections - ├── d_comp:11 = 'foo' [as=partial_index_put1:28] - └── e_comp:12 = 'FOO' [as=partial_index_put2:29] + ├── d_comp:14 = 'foo' [as=partial_index_put1:31] + └── e_comp:15 = 'FOO' [as=partial_index_put2:32] exec-ddl CREATE UNIQUE INDEX u2 ON comp (b) WHERE e = 'bar' @@ -1546,120 +1653,129 @@ insert comp ├── columns: ├── arbiter indexes: u1 u2 ├── insert-mapping: - │ ├── column1:8 => a:1 - │ ├── column2:9 => b:2 - │ ├── column3:10 => c:3 - │ ├── d_comp:11 => d:4 - │ └── e_comp:12 => e:5 - ├── partial index put columns: partial_index_put1:29 partial_index_put2:30 partial_index_put1:29 partial_index_put4:31 + │ ├── column1:11 => a:1 + │ ├── column2:12 => b:2 + │ ├── column3:13 => c:3 + │ ├── d_comp:14 => d:4 + │ └── e_comp:15 => e:5 + ├── partial index put columns: partial_index_put1:32 partial_index_put2:33 partial_index_put1:32 partial_index_put4:34 └── project - ├── columns: partial_index_put1:29 partial_index_put2:30 partial_index_put4:31 column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + ├── columns: partial_index_put1:32 partial_index_put2:33 partial_index_put4:34 column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 ├── project - │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 │ └── upsert-distinct-on - │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 arbiter_u2_distinct:28 - │ ├── grouping columns: column2:9!null arbiter_u2_distinct:28 + │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 arbiter_u2_distinct:31 + │ ├── grouping columns: column2:12!null arbiter_u2_distinct:31 │ ├── project - │ │ ├── columns: arbiter_u2_distinct:28 column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + │ │ ├── columns: arbiter_u2_distinct:31 column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 │ │ ├── project - │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 │ │ │ └── upsert-distinct-on - │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 arbiter_u1_distinct:27 - │ │ │ ├── grouping columns: column2:9!null arbiter_u1_distinct:27 + │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 arbiter_u1_distinct:30 + │ │ │ ├── grouping columns: column2:12!null arbiter_u1_distinct:30 │ │ │ ├── project - │ │ │ │ ├── columns: arbiter_u1_distinct:27 column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + │ │ │ │ ├── columns: arbiter_u1_distinct:30 column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + │ │ │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 │ │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + │ │ │ │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 │ │ │ │ │ │ ├── project - │ │ │ │ │ │ │ ├── columns: d_comp:11 e_comp:12 column1:8!null column2:9!null column3:10!null - │ │ │ │ │ │ │ ├── values - │ │ │ │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null - │ │ │ │ │ │ │ │ └── (1, 1, 'bar') + │ │ │ │ │ │ │ ├── columns: d_comp:14 e_comp:15 column1:11!null column2:12!null column3:13!null + │ │ │ │ │ │ │ ├── project + │ │ │ │ │ │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null + │ │ │ │ │ │ │ │ ├── values + │ │ │ │ │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null + │ │ │ │ │ │ │ │ │ └── (1, 1, 'bar') + │ │ │ │ │ │ │ │ └── projections + │ │ │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column1:11] + │ │ │ │ │ │ │ │ │ └── column1:8 + │ │ │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column2:12] + │ │ │ │ │ │ │ │ │ └── column2:9 + │ │ │ │ │ │ │ │ └── assignment-cast: STRING [as=column3:13] + │ │ │ │ │ │ │ │ └── column3:10 │ │ │ │ │ │ │ └── projections - │ │ │ │ │ │ │ ├── lower(column3:10) [as=d_comp:11] - │ │ │ │ │ │ │ └── upper(column3:10) [as=e_comp:12] + │ │ │ │ │ │ │ ├── lower(column3:13) [as=d_comp:14] + │ │ │ │ │ │ │ └── upper(column3:13) [as=e_comp:15] │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ ├── columns: a:13!null b:14 c:15 d:16!null e:17 + │ │ │ │ │ │ │ ├── columns: a:16!null b:17 c:18 d:19!null e:20 │ │ │ │ │ │ │ ├── project - │ │ │ │ │ │ │ │ ├── columns: d:16 a:13!null b:14 c:15 e:17 + │ │ │ │ │ │ │ │ ├── columns: d:19 a:16!null b:17 c:18 e:20 │ │ │ │ │ │ │ │ ├── scan comp - │ │ │ │ │ │ │ │ │ ├── columns: a:13!null b:14 c:15 e:17 + │ │ │ │ │ │ │ │ │ ├── columns: a:16!null b:17 c:18 e:20 │ │ │ │ │ │ │ │ │ ├── computed column expressions - │ │ │ │ │ │ │ │ │ │ ├── d:16 - │ │ │ │ │ │ │ │ │ │ │ └── lower(c:15) - │ │ │ │ │ │ │ │ │ │ └── e:17 - │ │ │ │ │ │ │ │ │ │ └── upper(c:15) + │ │ │ │ │ │ │ │ │ │ ├── d:19 + │ │ │ │ │ │ │ │ │ │ │ └── lower(c:18) + │ │ │ │ │ │ │ │ │ │ └── e:20 + │ │ │ │ │ │ │ │ │ │ └── upper(c:18) │ │ │ │ │ │ │ │ │ └── partial index predicates │ │ │ │ │ │ │ │ │ ├── comp_b_idx: filters - │ │ │ │ │ │ │ │ │ │ └── lower(c:15) = 'foo' + │ │ │ │ │ │ │ │ │ │ └── lower(c:18) = 'foo' │ │ │ │ │ │ │ │ │ ├── comp_b_idx1: filters - │ │ │ │ │ │ │ │ │ │ └── e:17 = 'FOO' + │ │ │ │ │ │ │ │ │ │ └── e:20 = 'FOO' │ │ │ │ │ │ │ │ │ ├── u1: filters - │ │ │ │ │ │ │ │ │ │ └── lower(c:15) = 'foo' + │ │ │ │ │ │ │ │ │ │ └── lower(c:18) = 'foo' │ │ │ │ │ │ │ │ │ └── u2: filters - │ │ │ │ │ │ │ │ │ └── e:17 = 'bar' + │ │ │ │ │ │ │ │ │ └── e:20 = 'bar' │ │ │ │ │ │ │ │ └── projections - │ │ │ │ │ │ │ │ └── lower(c:15) [as=d:16] + │ │ │ │ │ │ │ │ └── lower(c:18) [as=d:19] │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ └── d:16 = 'foo' + │ │ │ │ │ │ │ └── d:19 = 'foo' │ │ │ │ │ │ └── filters - │ │ │ │ │ │ ├── column2:9 = b:14 - │ │ │ │ │ │ └── d_comp:11 = 'foo' + │ │ │ │ │ │ ├── column2:12 = b:17 + │ │ │ │ │ │ └── d_comp:14 = 'foo' │ │ │ │ │ ├── select - │ │ │ │ │ │ ├── columns: a:20!null b:21 c:22 d:23 e:24!null + │ │ │ │ │ │ ├── columns: a:23!null b:24 c:25 d:26 e:27!null │ │ │ │ │ │ ├── project - │ │ │ │ │ │ │ ├── columns: d:23 a:20!null b:21 c:22 e:24 + │ │ │ │ │ │ │ ├── columns: d:26 a:23!null b:24 c:25 e:27 │ │ │ │ │ │ │ ├── scan comp - │ │ │ │ │ │ │ │ ├── columns: a:20!null b:21 c:22 e:24 + │ │ │ │ │ │ │ │ ├── columns: a:23!null b:24 c:25 e:27 │ │ │ │ │ │ │ │ ├── computed column expressions - │ │ │ │ │ │ │ │ │ ├── d:23 - │ │ │ │ │ │ │ │ │ │ └── lower(c:22) - │ │ │ │ │ │ │ │ │ └── e:24 - │ │ │ │ │ │ │ │ │ └── upper(c:22) + │ │ │ │ │ │ │ │ │ ├── d:26 + │ │ │ │ │ │ │ │ │ │ └── lower(c:25) + │ │ │ │ │ │ │ │ │ └── e:27 + │ │ │ │ │ │ │ │ │ └── upper(c:25) │ │ │ │ │ │ │ │ └── partial index predicates │ │ │ │ │ │ │ │ ├── comp_b_idx: filters - │ │ │ │ │ │ │ │ │ └── lower(c:22) = 'foo' + │ │ │ │ │ │ │ │ │ └── lower(c:25) = 'foo' │ │ │ │ │ │ │ │ ├── comp_b_idx1: filters - │ │ │ │ │ │ │ │ │ └── e:24 = 'FOO' + │ │ │ │ │ │ │ │ │ └── e:27 = 'FOO' │ │ │ │ │ │ │ │ ├── u1: filters - │ │ │ │ │ │ │ │ │ └── lower(c:22) = 'foo' + │ │ │ │ │ │ │ │ │ └── lower(c:25) = 'foo' │ │ │ │ │ │ │ │ └── u2: filters - │ │ │ │ │ │ │ │ └── e:24 = 'bar' + │ │ │ │ │ │ │ │ └── e:27 = 'bar' │ │ │ │ │ │ │ └── projections - │ │ │ │ │ │ │ └── lower(c:22) [as=d:23] + │ │ │ │ │ │ │ └── lower(c:25) [as=d:26] │ │ │ │ │ │ └── filters - │ │ │ │ │ │ └── e:24 = 'bar' + │ │ │ │ │ │ └── e:27 = 'bar' │ │ │ │ │ └── filters - │ │ │ │ │ ├── column2:9 = b:21 - │ │ │ │ │ └── e_comp:12 = 'bar' + │ │ │ │ │ ├── column2:12 = b:24 + │ │ │ │ │ └── e_comp:15 = 'bar' │ │ │ │ └── projections - │ │ │ │ └── (d_comp:11 = 'foo') OR NULL::BOOL [as=arbiter_u1_distinct:27] + │ │ │ │ └── (d_comp:14 = 'foo') OR NULL::BOOL [as=arbiter_u1_distinct:30] │ │ │ └── aggregations - │ │ │ ├── first-agg [as=column1:8] - │ │ │ │ └── column1:8 - │ │ │ ├── first-agg [as=column3:10] - │ │ │ │ └── column3:10 - │ │ │ ├── first-agg [as=d_comp:11] - │ │ │ │ └── d_comp:11 - │ │ │ └── first-agg [as=e_comp:12] - │ │ │ └── e_comp:12 + │ │ │ ├── first-agg [as=column1:11] + │ │ │ │ └── column1:11 + │ │ │ ├── first-agg [as=column3:13] + │ │ │ │ └── column3:13 + │ │ │ ├── first-agg [as=d_comp:14] + │ │ │ │ └── d_comp:14 + │ │ │ └── first-agg [as=e_comp:15] + │ │ │ └── e_comp:15 │ │ └── projections - │ │ └── (e_comp:12 = 'bar') OR NULL::BOOL [as=arbiter_u2_distinct:28] + │ │ └── (e_comp:15 = 'bar') OR NULL::BOOL [as=arbiter_u2_distinct:31] │ └── aggregations - │ ├── first-agg [as=column1:8] - │ │ └── column1:8 - │ ├── first-agg [as=column3:10] - │ │ └── column3:10 - │ ├── first-agg [as=d_comp:11] - │ │ └── d_comp:11 - │ └── first-agg [as=e_comp:12] - │ └── e_comp:12 + │ ├── first-agg [as=column1:11] + │ │ └── column1:11 + │ ├── first-agg [as=column3:13] + │ │ └── column3:13 + │ ├── first-agg [as=d_comp:14] + │ │ └── d_comp:14 + │ └── first-agg [as=e_comp:15] + │ └── e_comp:15 └── projections - ├── d_comp:11 = 'foo' [as=partial_index_put1:29] - ├── e_comp:12 = 'FOO' [as=partial_index_put2:30] - └── e_comp:12 = 'bar' [as=partial_index_put4:31] + ├── d_comp:14 = 'foo' [as=partial_index_put1:32] + ├── e_comp:15 = 'FOO' [as=partial_index_put2:33] + └── e_comp:15 = 'bar' [as=partial_index_put4:34] # Error when no arbiter is found because the arbiter predicate in the query # (non-existent in this case) does not imply any unique partial index predicates @@ -1683,62 +1799,71 @@ insert comp ├── columns: ├── arbiter indexes: u3 ├── insert-mapping: - │ ├── column1:8 => a:1 - │ ├── column2:9 => b:2 - │ ├── column3:10 => c:3 - │ ├── d_comp:11 => d:4 - │ └── e_comp:12 => e:5 - ├── partial index put columns: partial_index_put1:20 partial_index_put2:21 partial_index_put1:20 partial_index_put4:22 + │ ├── column1:11 => a:1 + │ ├── column2:12 => b:2 + │ ├── column3:13 => c:3 + │ ├── d_comp:14 => d:4 + │ └── e_comp:15 => e:5 + ├── partial index put columns: partial_index_put1:23 partial_index_put2:24 partial_index_put1:23 partial_index_put4:25 └── project - ├── columns: partial_index_put1:20 partial_index_put2:21 partial_index_put4:22 column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + ├── columns: partial_index_put1:23 partial_index_put2:24 partial_index_put4:25 column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 ├── upsert-distinct-on - │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 - │ ├── grouping columns: column2:9!null + │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 + │ ├── grouping columns: column2:12!null │ ├── anti-join (hash) - │ │ ├── columns: column1:8!null column2:9!null column3:10!null d_comp:11 e_comp:12 + │ │ ├── columns: column1:11!null column2:12!null column3:13!null d_comp:14 e_comp:15 │ │ ├── project - │ │ │ ├── columns: d_comp:11 e_comp:12 column1:8!null column2:9!null column3:10!null - │ │ │ ├── values - │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null - │ │ │ │ └── (1, 1, 'bar') + │ │ │ ├── columns: d_comp:14 e_comp:15 column1:11!null column2:12!null column3:13!null + │ │ │ ├── project + │ │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null + │ │ │ │ ├── values + │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null + │ │ │ │ │ └── (1, 1, 'bar') + │ │ │ │ └── projections + │ │ │ │ ├── assignment-cast: INT8 [as=column1:11] + │ │ │ │ │ └── column1:8 + │ │ │ │ ├── assignment-cast: INT8 [as=column2:12] + │ │ │ │ │ └── column2:9 + │ │ │ │ └── assignment-cast: STRING [as=column3:13] + │ │ │ │ └── column3:10 │ │ │ └── projections - │ │ │ ├── lower(column3:10) [as=d_comp:11] - │ │ │ └── upper(column3:10) [as=e_comp:12] + │ │ │ ├── lower(column3:13) [as=d_comp:14] + │ │ │ └── upper(column3:13) [as=e_comp:15] │ │ ├── project - │ │ │ ├── columns: d:16 a:13!null b:14 c:15 e:17 + │ │ │ ├── columns: d:19 a:16!null b:17 c:18 e:20 │ │ │ ├── scan comp - │ │ │ │ ├── columns: a:13!null b:14 c:15 e:17 + │ │ │ │ ├── columns: a:16!null b:17 c:18 e:20 │ │ │ │ ├── computed column expressions - │ │ │ │ │ ├── d:16 - │ │ │ │ │ │ └── lower(c:15) - │ │ │ │ │ └── e:17 - │ │ │ │ │ └── upper(c:15) + │ │ │ │ │ ├── d:19 + │ │ │ │ │ │ └── lower(c:18) + │ │ │ │ │ └── e:20 + │ │ │ │ │ └── upper(c:18) │ │ │ │ └── partial index predicates │ │ │ │ ├── comp_b_idx: filters - │ │ │ │ │ └── lower(c:15) = 'foo' + │ │ │ │ │ └── lower(c:18) = 'foo' │ │ │ │ ├── comp_b_idx1: filters - │ │ │ │ │ └── e:17 = 'FOO' + │ │ │ │ │ └── e:20 = 'FOO' │ │ │ │ ├── u1: filters - │ │ │ │ │ └── lower(c:15) = 'foo' + │ │ │ │ │ └── lower(c:18) = 'foo' │ │ │ │ └── u2: filters - │ │ │ │ └── e:17 = 'bar' + │ │ │ │ └── e:20 = 'bar' │ │ │ └── projections - │ │ │ └── lower(c:15) [as=d:16] + │ │ │ └── lower(c:18) [as=d:19] │ │ └── filters - │ │ └── column2:9 = b:14 + │ │ └── column2:12 = b:17 │ └── aggregations - │ ├── first-agg [as=column1:8] - │ │ └── column1:8 - │ ├── first-agg [as=column3:10] - │ │ └── column3:10 - │ ├── first-agg [as=d_comp:11] - │ │ └── d_comp:11 - │ └── first-agg [as=e_comp:12] - │ └── e_comp:12 + │ ├── first-agg [as=column1:11] + │ │ └── column1:11 + │ ├── first-agg [as=column3:13] + │ │ └── column3:13 + │ ├── first-agg [as=d_comp:14] + │ │ └── d_comp:14 + │ └── first-agg [as=e_comp:15] + │ └── e_comp:15 └── projections - ├── d_comp:11 = 'foo' [as=partial_index_put1:20] - ├── e_comp:12 = 'FOO' [as=partial_index_put2:21] - └── e_comp:12 = 'bar' [as=partial_index_put4:22] + ├── d_comp:14 = 'foo' [as=partial_index_put1:23] + ├── e_comp:15 = 'FOO' [as=partial_index_put2:24] + └── e_comp:15 = 'bar' [as=partial_index_put4:25] exec-ddl DROP INDEX u3 diff --git a/pkg/sql/opt/optbuilder/testdata/projection-reuse b/pkg/sql/opt/optbuilder/testdata/projection-reuse index 3353f0e89b1a..43edd2d41649 100644 --- a/pkg/sql/opt/optbuilder/testdata/projection-reuse +++ b/pkg/sql/opt/optbuilder/testdata/projection-reuse @@ -86,16 +86,23 @@ INSERT INTO ab VALUES (random(), random()) insert ab ├── columns: ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => b:2 - │ └── rowid_default:8 => rowid:3 + │ ├── column1:8 => a:1 + │ ├── column2:9 => b:2 + │ └── rowid_default:10 => rowid:3 └── project - ├── columns: rowid_default:8 column1:6 column2:7 - ├── values - │ ├── columns: column1:6 column2:7 - │ └── (random(), random()) + ├── columns: rowid_default:10 column1:8 column2:9 + ├── project + │ ├── columns: column1:8 column2:9 + │ ├── values + │ │ ├── columns: column1:6 column2:7 + │ │ └── (random(), random()) + │ └── projections + │ ├── assignment-cast: FLOAT8 [as=column1:8] + │ │ └── column1:6 + │ └── assignment-cast: FLOAT8 [as=column2:9] + │ └── column2:7 └── projections - └── unique_rowid() [as=rowid_default:8] + └── unique_rowid() [as=rowid_default:10] # Make sure impure default expressions are not deduplicated. exec-ddl @@ -108,20 +115,27 @@ INSERT INTO abcd VALUES (1, 1) insert abcd ├── columns: ├── insert-mapping: - │ ├── column1:8 => a:1 - │ ├── column2:9 => b:2 - │ ├── c_default:10 => c:3 - │ ├── d_default:11 => d:4 - │ └── rowid_default:12 => rowid:5 + │ ├── column1:10 => a:1 + │ ├── column2:11 => b:2 + │ ├── c_default:12 => c:3 + │ ├── d_default:13 => d:4 + │ └── rowid_default:14 => rowid:5 └── project - ├── columns: c_default:10 d_default:11 rowid_default:12 column1:8!null column2:9!null - ├── values - │ ├── columns: column1:8!null column2:9!null - │ └── (1.0, 1.0) + ├── columns: c_default:12 d_default:13 rowid_default:14 column1:10!null column2:11!null + ├── project + │ ├── columns: column1:10!null column2:11!null + │ ├── values + │ │ ├── columns: column1:8!null column2:9!null + │ │ └── (1.0, 1.0) + │ └── projections + │ ├── assignment-cast: FLOAT8 [as=column1:10] + │ │ └── column1:8 + │ └── assignment-cast: FLOAT8 [as=column2:11] + │ └── column2:9 └── projections - ├── random() [as=c_default:10] - ├── random() [as=d_default:11] - └── unique_rowid() [as=rowid_default:12] + ├── random() [as=c_default:12] + ├── random() [as=d_default:13] + └── unique_rowid() [as=rowid_default:14] build INSERT INTO abcd VALUES (random(), random()) @@ -129,20 +143,27 @@ INSERT INTO abcd VALUES (random(), random()) insert abcd ├── columns: ├── insert-mapping: - │ ├── column1:8 => a:1 - │ ├── column2:9 => b:2 - │ ├── c_default:10 => c:3 - │ ├── d_default:11 => d:4 - │ └── rowid_default:12 => rowid:5 + │ ├── column1:10 => a:1 + │ ├── column2:11 => b:2 + │ ├── c_default:12 => c:3 + │ ├── d_default:13 => d:4 + │ └── rowid_default:14 => rowid:5 └── project - ├── columns: c_default:10 d_default:11 rowid_default:12 column1:8 column2:9 - ├── values - │ ├── columns: column1:8 column2:9 - │ └── (random(), random()) + ├── columns: c_default:12 d_default:13 rowid_default:14 column1:10 column2:11 + ├── project + │ ├── columns: column1:10 column2:11 + │ ├── values + │ │ ├── columns: column1:8 column2:9 + │ │ └── (random(), random()) + │ └── projections + │ ├── assignment-cast: FLOAT8 [as=column1:10] + │ │ └── column1:8 + │ └── assignment-cast: FLOAT8 [as=column2:11] + │ └── column2:9 └── projections - ├── random() [as=c_default:10] - ├── random() [as=d_default:11] - └── unique_rowid() [as=rowid_default:12] + ├── random() [as=c_default:12] + ├── random() [as=d_default:13] + └── unique_rowid() [as=rowid_default:14] build UPSERT INTO abcd VALUES (1, 1) diff --git a/pkg/sql/opt/optbuilder/testdata/select b/pkg/sql/opt/optbuilder/testdata/select index e06a4b394288..8ff2e725f48f 100644 --- a/pkg/sql/opt/optbuilder/testdata/select +++ b/pkg/sql/opt/optbuilder/testdata/select @@ -1256,39 +1256,44 @@ build WITH cte AS (SELECT b FROM [INSERT INTO abc VALUES (1) RETURNING *] LIMIT 1) SELECT * FROM abc ---- with &1 - ├── columns: a:11!null b:12 c:13 + ├── columns: a:12!null b:13 c:14 ├── insert abc │ ├── columns: abc.a:1!null abc.b:2 abc.c:3 │ ├── insert-mapping: - │ │ ├── column1:6 => abc.a:1 - │ │ ├── b_default:7 => abc.b:2 - │ │ └── b_default:7 => abc.c:3 + │ │ ├── column1:7 => abc.a:1 + │ │ ├── b_default:8 => abc.b:2 + │ │ └── b_default:8 => abc.c:3 │ └── project - │ ├── columns: b_default:7 column1:6!null - │ ├── values - │ │ ├── columns: column1:6!null - │ │ └── (1,) + │ ├── columns: b_default:8 column1:7!null + │ ├── project + │ │ ├── columns: column1:7!null + │ │ ├── values + │ │ │ ├── columns: column1:6!null + │ │ │ └── (1,) + │ │ └── projections + │ │ └── assignment-cast: INT8 [as=column1:7] + │ │ └── column1:6 │ └── projections - │ └── NULL::INT8 [as=b_default:7] + │ └── NULL::INT8 [as=b_default:8] └── with &2 (cte) - ├── columns: abc.a:11!null abc.b:12 abc.c:13 + ├── columns: abc.a:12!null abc.b:13 abc.c:14 ├── limit - │ ├── columns: b:9 + │ ├── columns: b:10 │ ├── project - │ │ ├── columns: b:9 + │ │ ├── columns: b:10 │ │ ├── limit hint: 1.00 │ │ └── with-scan &1 - │ │ ├── columns: a:8!null b:9 c:10 + │ │ ├── columns: a:9!null b:10 c:11 │ │ ├── mapping: - │ │ │ ├── abc.a:1 => a:8 - │ │ │ ├── abc.b:2 => b:9 - │ │ │ └── abc.c:3 => c:10 + │ │ │ ├── abc.a:1 => a:9 + │ │ │ ├── abc.b:2 => b:10 + │ │ │ └── abc.c:3 => c:11 │ │ └── limit hint: 1.00 │ └── 1 └── project - ├── columns: abc.a:11!null abc.b:12 abc.c:13 + ├── columns: abc.a:12!null abc.b:13 abc.c:14 └── scan abc - └── columns: abc.a:11!null abc.b:12 abc.c:13 crdb_internal_mvcc_timestamp:14 tableoid:15 + └── columns: abc.a:12!null abc.b:13 abc.c:14 crdb_internal_mvcc_timestamp:15 tableoid:16 # Tests for the square bracket syntax. build @@ -1311,22 +1316,31 @@ build SELECT * FROM [INSERT INTO abc VALUES (1, 2, 3) RETURNING a] ---- with &1 - ├── columns: a:9!null + ├── columns: a:12!null ├── project │ ├── columns: abc.a:1!null │ └── insert abc │ ├── columns: abc.a:1!null b:2!null c:3!null │ ├── insert-mapping: - │ │ ├── column1:6 => abc.a:1 - │ │ ├── column2:7 => b:2 - │ │ └── column3:8 => c:3 - │ └── values - │ ├── columns: column1:6!null column2:7!null column3:8!null - │ └── (1, 2, 3) + │ │ ├── column1:9 => abc.a:1 + │ │ ├── column2:10 => b:2 + │ │ └── column3:11 => c:3 + │ └── project + │ ├── columns: column1:9!null column2:10!null column3:11!null + │ ├── values + │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ └── (1, 2, 3) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:9] + │ │ └── column1:6 + │ ├── assignment-cast: INT8 [as=column2:10] + │ │ └── column2:7 + │ └── assignment-cast: INT8 [as=column3:11] + │ └── column3:8 └── with-scan &1 - ├── columns: a:9!null + ├── columns: a:12!null └── mapping: - └── abc.a:1 => a:9 + └── abc.a:1 => a:12 # Statement inside brackets cannot refer to outer column. build @@ -1439,15 +1453,20 @@ INSERT INTO inaccessible VALUES (1) insert inaccessible ├── columns: ├── insert-mapping: - │ ├── column1:5 => k:1 - │ └── v_default:6 => v:2 + │ ├── column1:6 => k:1 + │ └── v_default:7 => v:2 └── project - ├── columns: v_default:6 column1:5!null - ├── values - │ ├── columns: column1:5!null - │ └── (1,) + ├── columns: v_default:7 column1:6!null + ├── project + │ ├── columns: column1:6!null + │ ├── values + │ │ ├── columns: column1:5!null + │ │ └── (1,) + │ └── projections + │ └── assignment-cast: INT8 [as=column1:6] + │ └── column1:5 └── projections - └── NULL::INT8 [as=v_default:6] + └── NULL::INT8 [as=v_default:7] build INSERT INTO inaccessible VALUES (1) RETURNING v diff --git a/pkg/sql/opt/optbuilder/testdata/unique-checks-insert b/pkg/sql/opt/optbuilder/testdata/unique-checks-insert index b4a73a3aebed..463bfd0c85a9 100644 --- a/pkg/sql/opt/optbuilder/testdata/unique-checks-insert +++ b/pkg/sql/opt/optbuilder/testdata/unique-checks-insert @@ -16,54 +16,67 @@ INSERT INTO uniq VALUES (1, 1, 1, 1, 1), (2, 2, 2, 2, 2) insert uniq ├── columns: ├── insert-mapping: - │ ├── column1:8 => uniq.k:1 - │ ├── column2:9 => uniq.v:2 - │ ├── column3:10 => uniq.w:3 - │ ├── column4:11 => uniq.x:4 - │ └── column5:12 => uniq.y:5 + │ ├── column1:13 => uniq.k:1 + │ ├── column2:14 => uniq.v:2 + │ ├── column3:15 => uniq.w:3 + │ ├── column4:16 => uniq.x:4 + │ └── column5:17 => uniq.y:5 ├── input binding: &1 - ├── values - │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null - │ ├── (1, 1, 1, 1, 1) - │ └── (2, 2, 2, 2, 2) + ├── project + │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null + │ ├── values + │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null + │ │ ├── (1, 1, 1, 1, 1) + │ │ └── (2, 2, 2, 2, 2) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:13] + │ │ └── column1:8 + │ ├── assignment-cast: INT8 [as=column2:14] + │ │ └── column2:9 + │ ├── assignment-cast: INT8 [as=column3:15] + │ │ └── column3:10 + │ ├── assignment-cast: INT8 [as=column4:16] + │ │ └── column4:11 + │ └── assignment-cast: INT8 [as=column5:17] + │ └── column5:12 └── unique-checks ├── unique-checks-item: uniq(w) │ └── project - │ ├── columns: w:22!null + │ ├── columns: w:27!null │ └── semi-join (hash) - │ ├── columns: k:20!null v:21!null w:22!null x:23!null y:24!null + │ ├── columns: k:25!null v:26!null w:27!null x:28!null y:29!null │ ├── with-scan &1 - │ │ ├── columns: k:20!null v:21!null w:22!null x:23!null y:24!null + │ │ ├── columns: k:25!null v:26!null w:27!null x:28!null y:29!null │ │ └── mapping: - │ │ ├── column1:8 => k:20 - │ │ ├── column2:9 => v:21 - │ │ ├── column3:10 => w:22 - │ │ ├── column4:11 => x:23 - │ │ └── column5:12 => y:24 + │ │ ├── column1:13 => k:25 + │ │ ├── column2:14 => v:26 + │ │ ├── column3:15 => w:27 + │ │ ├── column4:16 => x:28 + │ │ └── column5:17 => y:29 │ ├── scan uniq - │ │ └── columns: uniq.k:13!null uniq.v:14 uniq.w:15 uniq.x:16 uniq.y:17 + │ │ └── columns: uniq.k:18!null uniq.v:19 uniq.w:20 uniq.x:21 uniq.y:22 │ └── filters - │ ├── w:22 = uniq.w:15 - │ └── k:20 != uniq.k:13 + │ ├── w:27 = uniq.w:20 + │ └── k:25 != uniq.k:18 └── unique-checks-item: uniq(x,y) └── project - ├── columns: x:35!null y:36!null + ├── columns: x:40!null y:41!null └── semi-join (hash) - ├── columns: k:32!null v:33!null w:34!null x:35!null y:36!null + ├── columns: k:37!null v:38!null w:39!null x:40!null y:41!null ├── with-scan &1 - │ ├── columns: k:32!null v:33!null w:34!null x:35!null y:36!null + │ ├── columns: k:37!null v:38!null w:39!null x:40!null y:41!null │ └── mapping: - │ ├── column1:8 => k:32 - │ ├── column2:9 => v:33 - │ ├── column3:10 => w:34 - │ ├── column4:11 => x:35 - │ └── column5:12 => y:36 + │ ├── column1:13 => k:37 + │ ├── column2:14 => v:38 + │ ├── column3:15 => w:39 + │ ├── column4:16 => x:40 + │ └── column5:17 => y:41 ├── scan uniq - │ └── columns: uniq.k:25!null uniq.v:26 uniq.w:27 uniq.x:28 uniq.y:29 + │ └── columns: uniq.k:30!null uniq.v:31 uniq.w:32 uniq.x:33 uniq.y:34 └── filters - ├── x:35 = uniq.x:28 - ├── y:36 = uniq.y:29 - └── k:32 != uniq.k:25 + ├── x:40 = uniq.x:33 + ├── y:41 = uniq.y:34 + └── k:37 != uniq.k:30 # Some of the inserted values have nulls. build @@ -72,55 +85,68 @@ INSERT INTO uniq VALUES (1, 1, 1, 1, 1), (2, 2, 2, 2, 2), (3, NULL, NULL, NULL, insert uniq ├── columns: ├── insert-mapping: - │ ├── column1:8 => uniq.k:1 - │ ├── column2:9 => uniq.v:2 - │ ├── column3:10 => uniq.w:3 - │ ├── column4:11 => uniq.x:4 - │ └── column5:12 => uniq.y:5 + │ ├── column1:13 => uniq.k:1 + │ ├── column2:14 => uniq.v:2 + │ ├── column3:15 => uniq.w:3 + │ ├── column4:16 => uniq.x:4 + │ └── column5:17 => uniq.y:5 ├── input binding: &1 - ├── values - │ ├── columns: column1:8!null column2:9 column3:10 column4:11 column5:12!null - │ ├── (1, 1, 1, 1, 1) - │ ├── (2, 2, 2, 2, 2) - │ └── (3, NULL::INT8, NULL::INT8, NULL::INT8, 3) + ├── project + │ ├── columns: column1:13!null column2:14 column3:15 column4:16 column5:17!null + │ ├── values + │ │ ├── columns: column1:8!null column2:9 column3:10 column4:11 column5:12!null + │ │ ├── (1, 1, 1, 1, 1) + │ │ ├── (2, 2, 2, 2, 2) + │ │ └── (3, NULL::INT8, NULL::INT8, NULL::INT8, 3) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:13] + │ │ └── column1:8 + │ ├── assignment-cast: INT8 [as=column2:14] + │ │ └── column2:9 + │ ├── assignment-cast: INT8 [as=column3:15] + │ │ └── column3:10 + │ ├── assignment-cast: INT8 [as=column4:16] + │ │ └── column4:11 + │ └── assignment-cast: INT8 [as=column5:17] + │ └── column5:12 └── unique-checks ├── unique-checks-item: uniq(w) │ └── project - │ ├── columns: w:22 + │ ├── columns: w:27 │ └── semi-join (hash) - │ ├── columns: k:20!null v:21 w:22 x:23 y:24!null + │ ├── columns: k:25!null v:26 w:27 x:28 y:29!null │ ├── with-scan &1 - │ │ ├── columns: k:20!null v:21 w:22 x:23 y:24!null + │ │ ├── columns: k:25!null v:26 w:27 x:28 y:29!null │ │ └── mapping: - │ │ ├── column1:8 => k:20 - │ │ ├── column2:9 => v:21 - │ │ ├── column3:10 => w:22 - │ │ ├── column4:11 => x:23 - │ │ └── column5:12 => y:24 + │ │ ├── column1:13 => k:25 + │ │ ├── column2:14 => v:26 + │ │ ├── column3:15 => w:27 + │ │ ├── column4:16 => x:28 + │ │ └── column5:17 => y:29 │ ├── scan uniq - │ │ └── columns: uniq.k:13!null uniq.v:14 uniq.w:15 uniq.x:16 uniq.y:17 + │ │ └── columns: uniq.k:18!null uniq.v:19 uniq.w:20 uniq.x:21 uniq.y:22 │ └── filters - │ ├── w:22 = uniq.w:15 - │ └── k:20 != uniq.k:13 + │ ├── w:27 = uniq.w:20 + │ └── k:25 != uniq.k:18 └── unique-checks-item: uniq(x,y) └── project - ├── columns: x:35 y:36!null + ├── columns: x:40 y:41!null └── semi-join (hash) - ├── columns: k:32!null v:33 w:34 x:35 y:36!null + ├── columns: k:37!null v:38 w:39 x:40 y:41!null ├── with-scan &1 - │ ├── columns: k:32!null v:33 w:34 x:35 y:36!null + │ ├── columns: k:37!null v:38 w:39 x:40 y:41!null │ └── mapping: - │ ├── column1:8 => k:32 - │ ├── column2:9 => v:33 - │ ├── column3:10 => w:34 - │ ├── column4:11 => x:35 - │ └── column5:12 => y:36 + │ ├── column1:13 => k:37 + │ ├── column2:14 => v:38 + │ ├── column3:15 => w:39 + │ ├── column4:16 => x:40 + │ └── column5:17 => y:41 ├── scan uniq - │ └── columns: uniq.k:25!null uniq.v:26 uniq.w:27 uniq.x:28 uniq.y:29 + │ └── columns: uniq.k:30!null uniq.v:31 uniq.w:32 uniq.x:33 uniq.y:34 └── filters - ├── x:35 = uniq.x:28 - ├── y:36 = uniq.y:29 - └── k:32 != uniq.k:25 + ├── x:40 = uniq.x:33 + ├── y:41 = uniq.y:34 + └── k:37 != uniq.k:30 # No need to plan checks for w since it's always null. build @@ -129,36 +155,67 @@ INSERT INTO uniq VALUES (1, 1, NULL, 1, 1), (2, 2, NULL, 2, 2) insert uniq ├── columns: ├── insert-mapping: - │ ├── column1:8 => uniq.k:1 - │ ├── column2:9 => uniq.v:2 - │ ├── column3:10 => uniq.w:3 - │ ├── column4:11 => uniq.x:4 - │ └── column5:12 => uniq.y:5 + │ ├── column1:13 => uniq.k:1 + │ ├── column2:14 => uniq.v:2 + │ ├── column3:15 => uniq.w:3 + │ ├── column4:16 => uniq.x:4 + │ └── column5:17 => uniq.y:5 ├── input binding: &1 - ├── values - │ ├── columns: column1:8!null column2:9!null column3:10 column4:11!null column5:12!null - │ ├── (1, 1, NULL::INT8, 1, 1) - │ └── (2, 2, NULL::INT8, 2, 2) + ├── project + │ ├── columns: column1:13!null column2:14!null column3:15 column4:16!null column5:17!null + │ ├── values + │ │ ├── columns: column1:8!null column2:9!null column3:10 column4:11!null column5:12!null + │ │ ├── (1, 1, NULL::INT8, 1, 1) + │ │ └── (2, 2, NULL::INT8, 2, 2) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:13] + │ │ └── column1:8 + │ ├── assignment-cast: INT8 [as=column2:14] + │ │ └── column2:9 + │ ├── assignment-cast: INT8 [as=column3:15] + │ │ └── column3:10 + │ ├── assignment-cast: INT8 [as=column4:16] + │ │ └── column4:11 + │ └── assignment-cast: INT8 [as=column5:17] + │ └── column5:12 └── unique-checks + ├── unique-checks-item: uniq(w) + │ └── project + │ ├── columns: w:27 + │ └── semi-join (hash) + │ ├── columns: k:25!null v:26!null w:27 x:28!null y:29!null + │ ├── with-scan &1 + │ │ ├── columns: k:25!null v:26!null w:27 x:28!null y:29!null + │ │ └── mapping: + │ │ ├── column1:13 => k:25 + │ │ ├── column2:14 => v:26 + │ │ ├── column3:15 => w:27 + │ │ ├── column4:16 => x:28 + │ │ └── column5:17 => y:29 + │ ├── scan uniq + │ │ └── columns: uniq.k:18!null uniq.v:19 uniq.w:20 uniq.x:21 uniq.y:22 + │ └── filters + │ ├── w:27 = uniq.w:20 + │ └── k:25 != uniq.k:18 └── unique-checks-item: uniq(x,y) └── project - ├── columns: x:23!null y:24!null + ├── columns: x:40!null y:41!null └── semi-join (hash) - ├── columns: k:20!null v:21!null w:22 x:23!null y:24!null + ├── columns: k:37!null v:38!null w:39 x:40!null y:41!null ├── with-scan &1 - │ ├── columns: k:20!null v:21!null w:22 x:23!null y:24!null + │ ├── columns: k:37!null v:38!null w:39 x:40!null y:41!null │ └── mapping: - │ ├── column1:8 => k:20 - │ ├── column2:9 => v:21 - │ ├── column3:10 => w:22 - │ ├── column4:11 => x:23 - │ └── column5:12 => y:24 + │ ├── column1:13 => k:37 + │ ├── column2:14 => v:38 + │ ├── column3:15 => w:39 + │ ├── column4:16 => x:40 + │ └── column5:17 => y:41 ├── scan uniq - │ └── columns: uniq.k:13!null uniq.v:14 uniq.w:15 uniq.x:16 uniq.y:17 + │ └── columns: uniq.k:30!null uniq.v:31 uniq.w:32 uniq.x:33 uniq.y:34 └── filters - ├── x:23 = uniq.x:16 - ├── y:24 = uniq.y:17 - └── k:20 != uniq.k:13 + ├── x:40 = uniq.x:33 + ├── y:41 = uniq.y:34 + └── k:37 != uniq.k:30 # No need to plan checks for x,y since x is always null. build @@ -167,35 +224,67 @@ INSERT INTO uniq VALUES (1, 1, 1, NULL, 1), (2, 2, NULL, NULL, 2) insert uniq ├── columns: ├── insert-mapping: - │ ├── column1:8 => uniq.k:1 - │ ├── column2:9 => uniq.v:2 - │ ├── column3:10 => uniq.w:3 - │ ├── column4:11 => uniq.x:4 - │ └── column5:12 => uniq.y:5 + │ ├── column1:13 => uniq.k:1 + │ ├── column2:14 => uniq.v:2 + │ ├── column3:15 => uniq.w:3 + │ ├── column4:16 => uniq.x:4 + │ └── column5:17 => uniq.y:5 ├── input binding: &1 - ├── values - │ ├── columns: column1:8!null column2:9!null column3:10 column4:11 column5:12!null - │ ├── (1, 1, 1, NULL::INT8, 1) - │ └── (2, 2, NULL::INT8, NULL::INT8, 2) + ├── project + │ ├── columns: column1:13!null column2:14!null column3:15 column4:16 column5:17!null + │ ├── values + │ │ ├── columns: column1:8!null column2:9!null column3:10 column4:11 column5:12!null + │ │ ├── (1, 1, 1, NULL::INT8, 1) + │ │ └── (2, 2, NULL::INT8, NULL::INT8, 2) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:13] + │ │ └── column1:8 + │ ├── assignment-cast: INT8 [as=column2:14] + │ │ └── column2:9 + │ ├── assignment-cast: INT8 [as=column3:15] + │ │ └── column3:10 + │ ├── assignment-cast: INT8 [as=column4:16] + │ │ └── column4:11 + │ └── assignment-cast: INT8 [as=column5:17] + │ └── column5:12 └── unique-checks - └── unique-checks-item: uniq(w) + ├── unique-checks-item: uniq(w) + │ └── project + │ ├── columns: w:27 + │ └── semi-join (hash) + │ ├── columns: k:25!null v:26!null w:27 x:28 y:29!null + │ ├── with-scan &1 + │ │ ├── columns: k:25!null v:26!null w:27 x:28 y:29!null + │ │ └── mapping: + │ │ ├── column1:13 => k:25 + │ │ ├── column2:14 => v:26 + │ │ ├── column3:15 => w:27 + │ │ ├── column4:16 => x:28 + │ │ └── column5:17 => y:29 + │ ├── scan uniq + │ │ └── columns: uniq.k:18!null uniq.v:19 uniq.w:20 uniq.x:21 uniq.y:22 + │ └── filters + │ ├── w:27 = uniq.w:20 + │ └── k:25 != uniq.k:18 + └── unique-checks-item: uniq(x,y) └── project - ├── columns: w:22 + ├── columns: x:40 y:41!null └── semi-join (hash) - ├── columns: k:20!null v:21!null w:22 x:23 y:24!null + ├── columns: k:37!null v:38!null w:39 x:40 y:41!null ├── with-scan &1 - │ ├── columns: k:20!null v:21!null w:22 x:23 y:24!null + │ ├── columns: k:37!null v:38!null w:39 x:40 y:41!null │ └── mapping: - │ ├── column1:8 => k:20 - │ ├── column2:9 => v:21 - │ ├── column3:10 => w:22 - │ ├── column4:11 => x:23 - │ └── column5:12 => y:24 + │ ├── column1:13 => k:37 + │ ├── column2:14 => v:38 + │ ├── column3:15 => w:39 + │ ├── column4:16 => x:40 + │ └── column5:17 => y:41 ├── scan uniq - │ └── columns: uniq.k:13!null uniq.v:14 uniq.w:15 uniq.x:16 uniq.y:17 + │ └── columns: uniq.k:30!null uniq.v:31 uniq.w:32 uniq.x:33 uniq.y:34 └── filters - ├── w:22 = uniq.w:15 - └── k:20 != uniq.k:13 + ├── x:40 = uniq.x:33 + ├── y:41 = uniq.y:34 + └── k:37 != uniq.k:30 # No need to plan checks for x,y since y is always null. build @@ -204,35 +293,67 @@ INSERT INTO uniq VALUES (1, 1, 1, 1, NULL), (2, 2, 2, 2, NULL) insert uniq ├── columns: ├── insert-mapping: - │ ├── column1:8 => uniq.k:1 - │ ├── column2:9 => uniq.v:2 - │ ├── column3:10 => uniq.w:3 - │ ├── column4:11 => uniq.x:4 - │ └── column5:12 => uniq.y:5 + │ ├── column1:13 => uniq.k:1 + │ ├── column2:14 => uniq.v:2 + │ ├── column3:15 => uniq.w:3 + │ ├── column4:16 => uniq.x:4 + │ └── column5:17 => uniq.y:5 ├── input binding: &1 - ├── values - │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12 - │ ├── (1, 1, 1, 1, NULL::INT8) - │ └── (2, 2, 2, 2, NULL::INT8) + ├── project + │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17 + │ ├── values + │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12 + │ │ ├── (1, 1, 1, 1, NULL::INT8) + │ │ └── (2, 2, 2, 2, NULL::INT8) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:13] + │ │ └── column1:8 + │ ├── assignment-cast: INT8 [as=column2:14] + │ │ └── column2:9 + │ ├── assignment-cast: INT8 [as=column3:15] + │ │ └── column3:10 + │ ├── assignment-cast: INT8 [as=column4:16] + │ │ └── column4:11 + │ └── assignment-cast: INT8 [as=column5:17] + │ └── column5:12 └── unique-checks - └── unique-checks-item: uniq(w) + ├── unique-checks-item: uniq(w) + │ └── project + │ ├── columns: w:27!null + │ └── semi-join (hash) + │ ├── columns: k:25!null v:26!null w:27!null x:28!null y:29 + │ ├── with-scan &1 + │ │ ├── columns: k:25!null v:26!null w:27!null x:28!null y:29 + │ │ └── mapping: + │ │ ├── column1:13 => k:25 + │ │ ├── column2:14 => v:26 + │ │ ├── column3:15 => w:27 + │ │ ├── column4:16 => x:28 + │ │ └── column5:17 => y:29 + │ ├── scan uniq + │ │ └── columns: uniq.k:18!null uniq.v:19 uniq.w:20 uniq.x:21 uniq.y:22 + │ └── filters + │ ├── w:27 = uniq.w:20 + │ └── k:25 != uniq.k:18 + └── unique-checks-item: uniq(x,y) └── project - ├── columns: w:22!null + ├── columns: x:40!null y:41 └── semi-join (hash) - ├── columns: k:20!null v:21!null w:22!null x:23!null y:24 + ├── columns: k:37!null v:38!null w:39!null x:40!null y:41 ├── with-scan &1 - │ ├── columns: k:20!null v:21!null w:22!null x:23!null y:24 + │ ├── columns: k:37!null v:38!null w:39!null x:40!null y:41 │ └── mapping: - │ ├── column1:8 => k:20 - │ ├── column2:9 => v:21 - │ ├── column3:10 => w:22 - │ ├── column4:11 => x:23 - │ └── column5:12 => y:24 + │ ├── column1:13 => k:37 + │ ├── column2:14 => v:38 + │ ├── column3:15 => w:39 + │ ├── column4:16 => x:40 + │ └── column5:17 => y:41 ├── scan uniq - │ └── columns: uniq.k:13!null uniq.v:14 uniq.w:15 uniq.x:16 uniq.y:17 + │ └── columns: uniq.k:30!null uniq.v:31 uniq.w:32 uniq.x:33 uniq.y:34 └── filters - ├── w:22 = uniq.w:15 - └── k:20 != uniq.k:13 + ├── x:40 = uniq.x:33 + ├── y:41 = uniq.y:34 + └── k:37 != uniq.k:30 # No need to plan any checks, since w, x and y are always null. build @@ -241,15 +362,67 @@ INSERT INTO uniq VALUES (1, 1, NULL, NULL, NULL), (2, 2, NULL, NULL, NULL) insert uniq ├── columns: ├── insert-mapping: - │ ├── column1:8 => k:1 - │ ├── column2:9 => v:2 - │ ├── column3:10 => w:3 - │ ├── column4:11 => x:4 - │ └── column5:12 => y:5 - └── values - ├── columns: column1:8!null column2:9!null column3:10 column4:11 column5:12 - ├── (1, 1, NULL::INT8, NULL::INT8, NULL::INT8) - └── (2, 2, NULL::INT8, NULL::INT8, NULL::INT8) + │ ├── column1:13 => uniq.k:1 + │ ├── column2:14 => uniq.v:2 + │ ├── column3:15 => uniq.w:3 + │ ├── column4:16 => uniq.x:4 + │ └── column5:17 => uniq.y:5 + ├── input binding: &1 + ├── project + │ ├── columns: column1:13!null column2:14!null column3:15 column4:16 column5:17 + │ ├── values + │ │ ├── columns: column1:8!null column2:9!null column3:10 column4:11 column5:12 + │ │ ├── (1, 1, NULL::INT8, NULL::INT8, NULL::INT8) + │ │ └── (2, 2, NULL::INT8, NULL::INT8, NULL::INT8) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:13] + │ │ └── column1:8 + │ ├── assignment-cast: INT8 [as=column2:14] + │ │ └── column2:9 + │ ├── assignment-cast: INT8 [as=column3:15] + │ │ └── column3:10 + │ ├── assignment-cast: INT8 [as=column4:16] + │ │ └── column4:11 + │ └── assignment-cast: INT8 [as=column5:17] + │ └── column5:12 + └── unique-checks + ├── unique-checks-item: uniq(w) + │ └── project + │ ├── columns: w:27 + │ └── semi-join (hash) + │ ├── columns: k:25!null v:26!null w:27 x:28 y:29 + │ ├── with-scan &1 + │ │ ├── columns: k:25!null v:26!null w:27 x:28 y:29 + │ │ └── mapping: + │ │ ├── column1:13 => k:25 + │ │ ├── column2:14 => v:26 + │ │ ├── column3:15 => w:27 + │ │ ├── column4:16 => x:28 + │ │ └── column5:17 => y:29 + │ ├── scan uniq + │ │ └── columns: uniq.k:18!null uniq.v:19 uniq.w:20 uniq.x:21 uniq.y:22 + │ └── filters + │ ├── w:27 = uniq.w:20 + │ └── k:25 != uniq.k:18 + └── unique-checks-item: uniq(x,y) + └── project + ├── columns: x:40 y:41 + └── semi-join (hash) + ├── columns: k:37!null v:38!null w:39 x:40 y:41 + ├── with-scan &1 + │ ├── columns: k:37!null v:38!null w:39 x:40 y:41 + │ └── mapping: + │ ├── column1:13 => k:37 + │ ├── column2:14 => v:38 + │ ├── column3:15 => w:39 + │ ├── column4:16 => x:40 + │ └── column5:17 => y:41 + ├── scan uniq + │ └── columns: uniq.k:30!null uniq.v:31 uniq.w:32 uniq.x:33 uniq.y:34 + └── filters + ├── x:40 = uniq.x:33 + ├── y:41 = uniq.y:34 + └── k:37 != uniq.k:30 # Use all the unique indexes and constraints as arbiters for DO NOTHING with no # conflict columns. @@ -261,85 +434,98 @@ insert uniq ├── arbiter indexes: uniq_pkey uniq_v_key ├── arbiter constraints: unique_w unique_x_y ├── insert-mapping: - │ ├── column1:8 => k:1 - │ ├── column2:9 => v:2 - │ ├── column3:10 => w:3 - │ ├── column4:11 => x:4 - │ └── column5:12 => y:5 + │ ├── column1:13 => k:1 + │ ├── column2:14 => v:2 + │ ├── column3:15 => w:3 + │ ├── column4:16 => x:4 + │ └── column5:17 => y:5 └── upsert-distinct-on - ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null - ├── grouping columns: column4:11!null column5:12!null + ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null + ├── grouping columns: column4:16!null column5:17!null ├── upsert-distinct-on - │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null - │ ├── grouping columns: column3:10!null + │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null + │ ├── grouping columns: column3:15!null │ ├── upsert-distinct-on - │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null - │ │ ├── grouping columns: column2:9!null + │ │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null + │ │ ├── grouping columns: column2:14!null │ │ ├── upsert-distinct-on - │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null - │ │ │ ├── grouping columns: column1:8!null + │ │ │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null + │ │ │ ├── grouping columns: column1:13!null │ │ │ ├── anti-join (hash) - │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null + │ │ │ │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null + │ │ │ │ │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null │ │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null + │ │ │ │ │ │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null │ │ │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null - │ │ │ │ │ │ │ ├── values - │ │ │ │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null - │ │ │ │ │ │ │ │ └── (1, 2, 3, 4, 5) + │ │ │ │ │ │ │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null + │ │ │ │ │ │ │ ├── project + │ │ │ │ │ │ │ │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null + │ │ │ │ │ │ │ │ ├── values + │ │ │ │ │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null + │ │ │ │ │ │ │ │ │ └── (1, 2, 3, 4, 5) + │ │ │ │ │ │ │ │ └── projections + │ │ │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column1:13] + │ │ │ │ │ │ │ │ │ └── column1:8 + │ │ │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column2:14] + │ │ │ │ │ │ │ │ │ └── column2:9 + │ │ │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column3:15] + │ │ │ │ │ │ │ │ │ └── column3:10 + │ │ │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column4:16] + │ │ │ │ │ │ │ │ │ └── column4:11 + │ │ │ │ │ │ │ │ └── assignment-cast: INT8 [as=column5:17] + │ │ │ │ │ │ │ │ └── column5:12 │ │ │ │ │ │ │ ├── scan uniq - │ │ │ │ │ │ │ │ └── columns: k:13!null v:14 w:15 x:16 y:17 + │ │ │ │ │ │ │ │ └── columns: k:18!null v:19 w:20 x:21 y:22 │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ └── column1:8 = k:13 + │ │ │ │ │ │ │ └── column1:13 = k:18 │ │ │ │ │ │ ├── scan uniq - │ │ │ │ │ │ │ └── columns: k:20!null v:21 w:22 x:23 y:24 + │ │ │ │ │ │ │ └── columns: k:25!null v:26 w:27 x:28 y:29 │ │ │ │ │ │ └── filters - │ │ │ │ │ │ └── column2:9 = v:21 + │ │ │ │ │ │ └── column2:14 = v:26 │ │ │ │ │ ├── scan uniq - │ │ │ │ │ │ └── columns: k:27!null v:28 w:29 x:30 y:31 + │ │ │ │ │ │ └── columns: k:32!null v:33 w:34 x:35 y:36 │ │ │ │ │ └── filters - │ │ │ │ │ └── column3:10 = w:29 + │ │ │ │ │ └── column3:15 = w:34 │ │ │ │ ├── scan uniq - │ │ │ │ │ └── columns: k:34!null v:35 w:36 x:37 y:38 + │ │ │ │ │ └── columns: k:39!null v:40 w:41 x:42 y:43 │ │ │ │ └── filters - │ │ │ │ ├── column4:11 = x:37 - │ │ │ │ └── column5:12 = y:38 + │ │ │ │ ├── column4:16 = x:42 + │ │ │ │ └── column5:17 = y:43 │ │ │ └── aggregations - │ │ │ ├── first-agg [as=column2:9] - │ │ │ │ └── column2:9 - │ │ │ ├── first-agg [as=column3:10] - │ │ │ │ └── column3:10 - │ │ │ ├── first-agg [as=column4:11] - │ │ │ │ └── column4:11 - │ │ │ └── first-agg [as=column5:12] - │ │ │ └── column5:12 + │ │ │ ├── first-agg [as=column2:14] + │ │ │ │ └── column2:14 + │ │ │ ├── first-agg [as=column3:15] + │ │ │ │ └── column3:15 + │ │ │ ├── first-agg [as=column4:16] + │ │ │ │ └── column4:16 + │ │ │ └── first-agg [as=column5:17] + │ │ │ └── column5:17 │ │ └── aggregations - │ │ ├── first-agg [as=column1:8] - │ │ │ └── column1:8 - │ │ ├── first-agg [as=column3:10] - │ │ │ └── column3:10 - │ │ ├── first-agg [as=column4:11] - │ │ │ └── column4:11 - │ │ └── first-agg [as=column5:12] - │ │ └── column5:12 + │ │ ├── first-agg [as=column1:13] + │ │ │ └── column1:13 + │ │ ├── first-agg [as=column3:15] + │ │ │ └── column3:15 + │ │ ├── first-agg [as=column4:16] + │ │ │ └── column4:16 + │ │ └── first-agg [as=column5:17] + │ │ └── column5:17 │ └── aggregations - │ ├── first-agg [as=column1:8] - │ │ └── column1:8 - │ ├── first-agg [as=column2:9] - │ │ └── column2:9 - │ ├── first-agg [as=column4:11] - │ │ └── column4:11 - │ └── first-agg [as=column5:12] - │ └── column5:12 + │ ├── first-agg [as=column1:13] + │ │ └── column1:13 + │ ├── first-agg [as=column2:14] + │ │ └── column2:14 + │ ├── first-agg [as=column4:16] + │ │ └── column4:16 + │ └── first-agg [as=column5:17] + │ └── column5:17 └── aggregations - ├── first-agg [as=column1:8] - │ └── column1:8 - ├── first-agg [as=column2:9] - │ └── column2:9 - └── first-agg [as=column3:10] - └── column3:10 + ├── first-agg [as=column1:13] + │ └── column1:13 + ├── first-agg [as=column2:14] + │ └── column2:14 + └── first-agg [as=column3:15] + └── column3:15 # On conflict clause references unique without index constraint. build @@ -349,53 +535,66 @@ insert uniq ├── columns: ├── arbiter constraints: unique_w ├── insert-mapping: - │ ├── column1:8 => uniq.k:1 - │ ├── column2:9 => uniq.v:2 - │ ├── column3:10 => uniq.w:3 - │ ├── column4:11 => uniq.x:4 - │ └── column5:12 => uniq.y:5 + │ ├── column1:13 => uniq.k:1 + │ ├── column2:14 => uniq.v:2 + │ ├── column3:15 => uniq.w:3 + │ ├── column4:16 => uniq.x:4 + │ └── column5:17 => uniq.y:5 ├── input binding: &1 ├── upsert-distinct-on - │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null - │ ├── grouping columns: column3:10!null + │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null + │ ├── grouping columns: column3:15!null │ ├── anti-join (hash) - │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null - │ │ ├── values - │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null - │ │ │ └── (1, 2, 3, 4, 5) + │ │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null + │ │ ├── project + │ │ │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null + │ │ │ ├── values + │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null column5:12!null + │ │ │ │ └── (1, 2, 3, 4, 5) + │ │ │ └── projections + │ │ │ ├── assignment-cast: INT8 [as=column1:13] + │ │ │ │ └── column1:8 + │ │ │ ├── assignment-cast: INT8 [as=column2:14] + │ │ │ │ └── column2:9 + │ │ │ ├── assignment-cast: INT8 [as=column3:15] + │ │ │ │ └── column3:10 + │ │ │ ├── assignment-cast: INT8 [as=column4:16] + │ │ │ │ └── column4:11 + │ │ │ └── assignment-cast: INT8 [as=column5:17] + │ │ │ └── column5:12 │ │ ├── scan uniq - │ │ │ └── columns: uniq.k:13!null uniq.v:14 uniq.w:15 uniq.x:16 uniq.y:17 + │ │ │ └── columns: uniq.k:18!null uniq.v:19 uniq.w:20 uniq.x:21 uniq.y:22 │ │ └── filters - │ │ └── column3:10 = uniq.w:15 + │ │ └── column3:15 = uniq.w:20 │ └── aggregations - │ ├── first-agg [as=column1:8] - │ │ └── column1:8 - │ ├── first-agg [as=column2:9] - │ │ └── column2:9 - │ ├── first-agg [as=column4:11] - │ │ └── column4:11 - │ └── first-agg [as=column5:12] - │ └── column5:12 + │ ├── first-agg [as=column1:13] + │ │ └── column1:13 + │ ├── first-agg [as=column2:14] + │ │ └── column2:14 + │ ├── first-agg [as=column4:16] + │ │ └── column4:16 + │ └── first-agg [as=column5:17] + │ └── column5:17 └── unique-checks └── unique-checks-item: uniq(x,y) └── project - ├── columns: x:30!null y:31!null + ├── columns: x:35!null y:36!null └── semi-join (hash) - ├── columns: k:27!null v:28!null w:29!null x:30!null y:31!null + ├── columns: k:32!null v:33!null w:34!null x:35!null y:36!null ├── with-scan &1 - │ ├── columns: k:27!null v:28!null w:29!null x:30!null y:31!null + │ ├── columns: k:32!null v:33!null w:34!null x:35!null y:36!null │ └── mapping: - │ ├── column1:8 => k:27 - │ ├── column2:9 => v:28 - │ ├── column3:10 => w:29 - │ ├── column4:11 => x:30 - │ └── column5:12 => y:31 + │ ├── column1:13 => k:32 + │ ├── column2:14 => v:33 + │ ├── column3:15 => w:34 + │ ├── column4:16 => x:35 + │ └── column5:17 => y:36 ├── scan uniq - │ └── columns: uniq.k:20!null uniq.v:21 uniq.w:22 uniq.x:23 uniq.y:24 + │ └── columns: uniq.k:25!null uniq.v:26 uniq.w:27 uniq.x:28 uniq.y:29 └── filters - ├── x:30 = uniq.x:23 - ├── y:31 = uniq.y:24 - └── k:27 != uniq.k:20 + ├── x:35 = uniq.x:28 + ├── y:36 = uniq.y:29 + └── k:32 != uniq.k:25 exec-ddl CREATE TABLE other (k INT, v INT, w INT NOT NULL, x INT, y INT) @@ -408,54 +607,67 @@ INSERT INTO uniq SELECT k, v, w, x, y FROM other insert uniq ├── columns: ├── insert-mapping: - │ ├── other.k:8 => uniq.k:1 - │ ├── other.v:9 => uniq.v:2 - │ ├── other.w:10 => uniq.w:3 - │ ├── other.x:11 => uniq.x:4 - │ └── other.y:12 => uniq.y:5 + │ ├── k:16 => uniq.k:1 + │ ├── v:17 => uniq.v:2 + │ ├── w:18 => uniq.w:3 + │ ├── x:19 => uniq.x:4 + │ └── y:20 => uniq.y:5 ├── input binding: &1 ├── project - │ ├── columns: other.k:8 other.v:9 other.w:10!null other.x:11 other.y:12 - │ └── scan other - │ └── columns: other.k:8 other.v:9 other.w:10!null other.x:11 other.y:12 rowid:13!null other.crdb_internal_mvcc_timestamp:14 other.tableoid:15 + │ ├── columns: k:16 v:17 w:18!null x:19 y:20 + │ ├── project + │ │ ├── columns: other.k:8 other.v:9 other.w:10!null other.x:11 other.y:12 + │ │ └── scan other + │ │ └── columns: other.k:8 other.v:9 other.w:10!null other.x:11 other.y:12 rowid:13!null other.crdb_internal_mvcc_timestamp:14 other.tableoid:15 + │ └── projections + │ ├── assignment-cast: INT8 [as=k:16] + │ │ └── other.k:8 + │ ├── assignment-cast: INT8 [as=v:17] + │ │ └── other.v:9 + │ ├── assignment-cast: INT8 [as=w:18] + │ │ └── other.w:10 + │ ├── assignment-cast: INT8 [as=x:19] + │ │ └── other.x:11 + │ └── assignment-cast: INT8 [as=y:20] + │ └── other.y:12 └── unique-checks ├── unique-checks-item: uniq(w) │ └── project - │ ├── columns: w:25!null + │ ├── columns: w:30!null │ └── semi-join (hash) - │ ├── columns: k:23 v:24 w:25!null x:26 y:27 + │ ├── columns: k:28 v:29 w:30!null x:31 y:32 │ ├── with-scan &1 - │ │ ├── columns: k:23 v:24 w:25!null x:26 y:27 + │ │ ├── columns: k:28 v:29 w:30!null x:31 y:32 │ │ └── mapping: - │ │ ├── other.k:8 => k:23 - │ │ ├── other.v:9 => v:24 - │ │ ├── other.w:10 => w:25 - │ │ ├── other.x:11 => x:26 - │ │ └── other.y:12 => y:27 + │ │ ├── k:16 => k:28 + │ │ ├── v:17 => v:29 + │ │ ├── w:18 => w:30 + │ │ ├── x:19 => x:31 + │ │ └── y:20 => y:32 │ ├── scan uniq - │ │ └── columns: uniq.k:16!null uniq.v:17 uniq.w:18 uniq.x:19 uniq.y:20 + │ │ └── columns: uniq.k:21!null uniq.v:22 uniq.w:23 uniq.x:24 uniq.y:25 │ └── filters - │ ├── w:25 = uniq.w:18 - │ └── k:23 != uniq.k:16 + │ ├── w:30 = uniq.w:23 + │ └── k:28 != uniq.k:21 └── unique-checks-item: uniq(x,y) └── project - ├── columns: x:38 y:39 + ├── columns: x:43 y:44 └── semi-join (hash) - ├── columns: k:35 v:36 w:37!null x:38 y:39 + ├── columns: k:40 v:41 w:42!null x:43 y:44 ├── with-scan &1 - │ ├── columns: k:35 v:36 w:37!null x:38 y:39 + │ ├── columns: k:40 v:41 w:42!null x:43 y:44 │ └── mapping: - │ ├── other.k:8 => k:35 - │ ├── other.v:9 => v:36 - │ ├── other.w:10 => w:37 - │ ├── other.x:11 => x:38 - │ └── other.y:12 => y:39 + │ ├── k:16 => k:40 + │ ├── v:17 => v:41 + │ ├── w:18 => w:42 + │ ├── x:19 => x:43 + │ └── y:20 => y:44 ├── scan uniq - │ └── columns: uniq.k:28!null uniq.v:29 uniq.w:30 uniq.x:31 uniq.y:32 + │ └── columns: uniq.k:33!null uniq.v:34 uniq.w:35 uniq.x:36 uniq.y:37 └── filters - ├── x:38 = uniq.x:31 - ├── y:39 = uniq.y:32 - └── k:35 != uniq.k:28 + ├── x:43 = uniq.x:36 + ├── y:44 = uniq.y:37 + └── k:40 != uniq.k:33 exec-ddl CREATE TABLE uniq_overlaps_pk ( @@ -480,69 +692,80 @@ INSERT INTO uniq_overlaps_pk VALUES (1, 1, 1, 1), (2, 2, 2, 2) insert uniq_overlaps_pk ├── columns: ├── insert-mapping: - │ ├── column1:7 => uniq_overlaps_pk.a:1 - │ ├── column2:8 => uniq_overlaps_pk.b:2 - │ ├── column3:9 => uniq_overlaps_pk.c:3 - │ └── column4:10 => uniq_overlaps_pk.d:4 + │ ├── column1:11 => uniq_overlaps_pk.a:1 + │ ├── column2:12 => uniq_overlaps_pk.b:2 + │ ├── column3:13 => uniq_overlaps_pk.c:3 + │ └── column4:14 => uniq_overlaps_pk.d:4 ├── input binding: &1 - ├── values - │ ├── columns: column1:7!null column2:8!null column3:9!null column4:10!null - │ ├── (1, 1, 1, 1) - │ └── (2, 2, 2, 2) + ├── project + │ ├── columns: column1:11!null column2:12!null column3:13!null column4:14!null + │ ├── values + │ │ ├── columns: column1:7!null column2:8!null column3:9!null column4:10!null + │ │ ├── (1, 1, 1, 1) + │ │ └── (2, 2, 2, 2) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:11] + │ │ └── column1:7 + │ ├── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:8 + │ ├── assignment-cast: INT8 [as=column3:13] + │ │ └── column3:9 + │ └── assignment-cast: INT8 [as=column4:14] + │ └── column4:10 └── unique-checks ├── unique-checks-item: uniq_overlaps_pk(b,c) │ └── project - │ ├── columns: b:18!null c:19!null + │ ├── columns: b:22!null c:23!null │ └── semi-join (hash) - │ ├── columns: a:17!null b:18!null c:19!null d:20!null + │ ├── columns: a:21!null b:22!null c:23!null d:24!null │ ├── with-scan &1 - │ │ ├── columns: a:17!null b:18!null c:19!null d:20!null + │ │ ├── columns: a:21!null b:22!null c:23!null d:24!null │ │ └── mapping: - │ │ ├── column1:7 => a:17 - │ │ ├── column2:8 => b:18 - │ │ ├── column3:9 => c:19 - │ │ └── column4:10 => d:20 + │ │ ├── column1:11 => a:21 + │ │ ├── column2:12 => b:22 + │ │ ├── column3:13 => c:23 + │ │ └── column4:14 => d:24 │ ├── scan uniq_overlaps_pk - │ │ └── columns: uniq_overlaps_pk.a:11!null uniq_overlaps_pk.b:12!null uniq_overlaps_pk.c:13 uniq_overlaps_pk.d:14 + │ │ └── columns: uniq_overlaps_pk.a:15!null uniq_overlaps_pk.b:16!null uniq_overlaps_pk.c:17 uniq_overlaps_pk.d:18 │ └── filters - │ ├── b:18 = uniq_overlaps_pk.b:12 - │ ├── c:19 = uniq_overlaps_pk.c:13 - │ └── a:17 != uniq_overlaps_pk.a:11 + │ ├── b:22 = uniq_overlaps_pk.b:16 + │ ├── c:23 = uniq_overlaps_pk.c:17 + │ └── a:21 != uniq_overlaps_pk.a:15 ├── unique-checks-item: uniq_overlaps_pk(a) │ └── project - │ ├── columns: a:27!null + │ ├── columns: a:31!null │ └── semi-join (hash) - │ ├── columns: a:27!null b:28!null c:29!null d:30!null + │ ├── columns: a:31!null b:32!null c:33!null d:34!null │ ├── with-scan &1 - │ │ ├── columns: a:27!null b:28!null c:29!null d:30!null + │ │ ├── columns: a:31!null b:32!null c:33!null d:34!null │ │ └── mapping: - │ │ ├── column1:7 => a:27 - │ │ ├── column2:8 => b:28 - │ │ ├── column3:9 => c:29 - │ │ └── column4:10 => d:30 + │ │ ├── column1:11 => a:31 + │ │ ├── column2:12 => b:32 + │ │ ├── column3:13 => c:33 + │ │ └── column4:14 => d:34 │ ├── scan uniq_overlaps_pk - │ │ └── columns: uniq_overlaps_pk.a:21!null uniq_overlaps_pk.b:22!null uniq_overlaps_pk.c:23 uniq_overlaps_pk.d:24 + │ │ └── columns: uniq_overlaps_pk.a:25!null uniq_overlaps_pk.b:26!null uniq_overlaps_pk.c:27 uniq_overlaps_pk.d:28 │ └── filters - │ ├── a:27 = uniq_overlaps_pk.a:21 - │ └── b:28 != uniq_overlaps_pk.b:22 + │ ├── a:31 = uniq_overlaps_pk.a:25 + │ └── b:32 != uniq_overlaps_pk.b:26 └── unique-checks-item: uniq_overlaps_pk(c,d) └── project - ├── columns: c:39!null d:40!null + ├── columns: c:43!null d:44!null └── semi-join (hash) - ├── columns: a:37!null b:38!null c:39!null d:40!null + ├── columns: a:41!null b:42!null c:43!null d:44!null ├── with-scan &1 - │ ├── columns: a:37!null b:38!null c:39!null d:40!null + │ ├── columns: a:41!null b:42!null c:43!null d:44!null │ └── mapping: - │ ├── column1:7 => a:37 - │ ├── column2:8 => b:38 - │ ├── column3:9 => c:39 - │ └── column4:10 => d:40 + │ ├── column1:11 => a:41 + │ ├── column2:12 => b:42 + │ ├── column3:13 => c:43 + │ └── column4:14 => d:44 ├── scan uniq_overlaps_pk - │ └── columns: uniq_overlaps_pk.a:31!null uniq_overlaps_pk.b:32!null uniq_overlaps_pk.c:33 uniq_overlaps_pk.d:34 + │ └── columns: uniq_overlaps_pk.a:35!null uniq_overlaps_pk.b:36!null uniq_overlaps_pk.c:37 uniq_overlaps_pk.d:38 └── filters - ├── c:39 = uniq_overlaps_pk.c:33 - ├── d:40 = uniq_overlaps_pk.d:34 - └── (a:37 != uniq_overlaps_pk.a:31) OR (b:38 != uniq_overlaps_pk.b:32) + ├── c:43 = uniq_overlaps_pk.c:37 + ├── d:44 = uniq_overlaps_pk.d:38 + └── (a:41 != uniq_overlaps_pk.a:35) OR (b:42 != uniq_overlaps_pk.b:36) # Insert with non-constant input. # Add inequality filters for the primary key columns that are not part of each @@ -553,69 +776,80 @@ INSERT INTO uniq_overlaps_pk SELECT k, v, x, y FROM other insert uniq_overlaps_pk ├── columns: ├── insert-mapping: - │ ├── k:7 => uniq_overlaps_pk.a:1 - │ ├── v:8 => uniq_overlaps_pk.b:2 - │ ├── x:10 => uniq_overlaps_pk.c:3 - │ └── y:11 => uniq_overlaps_pk.d:4 + │ ├── k:15 => uniq_overlaps_pk.a:1 + │ ├── v:16 => uniq_overlaps_pk.b:2 + │ ├── x:17 => uniq_overlaps_pk.c:3 + │ └── y:18 => uniq_overlaps_pk.d:4 ├── input binding: &1 ├── project - │ ├── columns: k:7 v:8 x:10 y:11 - │ └── scan other - │ └── columns: k:7 v:8 w:9!null x:10 y:11 rowid:12!null other.crdb_internal_mvcc_timestamp:13 other.tableoid:14 + │ ├── columns: k:15 v:16 x:17 y:18 + │ ├── project + │ │ ├── columns: other.k:7 other.v:8 other.x:10 other.y:11 + │ │ └── scan other + │ │ └── columns: other.k:7 other.v:8 w:9!null other.x:10 other.y:11 rowid:12!null other.crdb_internal_mvcc_timestamp:13 other.tableoid:14 + │ └── projections + │ ├── assignment-cast: INT8 [as=k:15] + │ │ └── other.k:7 + │ ├── assignment-cast: INT8 [as=v:16] + │ │ └── other.v:8 + │ ├── assignment-cast: INT8 [as=x:17] + │ │ └── other.x:10 + │ └── assignment-cast: INT8 [as=y:18] + │ └── other.y:11 └── unique-checks ├── unique-checks-item: uniq_overlaps_pk(b,c) │ └── project - │ ├── columns: b:22 c:23 + │ ├── columns: b:26 c:27 │ └── semi-join (hash) - │ ├── columns: a:21 b:22 c:23 d:24 + │ ├── columns: a:25 b:26 c:27 d:28 │ ├── with-scan &1 - │ │ ├── columns: a:21 b:22 c:23 d:24 + │ │ ├── columns: a:25 b:26 c:27 d:28 │ │ └── mapping: - │ │ ├── k:7 => a:21 - │ │ ├── v:8 => b:22 - │ │ ├── x:10 => c:23 - │ │ └── y:11 => d:24 + │ │ ├── k:15 => a:25 + │ │ ├── v:16 => b:26 + │ │ ├── x:17 => c:27 + │ │ └── y:18 => d:28 │ ├── scan uniq_overlaps_pk - │ │ └── columns: uniq_overlaps_pk.a:15!null uniq_overlaps_pk.b:16!null uniq_overlaps_pk.c:17 uniq_overlaps_pk.d:18 + │ │ └── columns: uniq_overlaps_pk.a:19!null uniq_overlaps_pk.b:20!null uniq_overlaps_pk.c:21 uniq_overlaps_pk.d:22 │ └── filters - │ ├── b:22 = uniq_overlaps_pk.b:16 - │ ├── c:23 = uniq_overlaps_pk.c:17 - │ └── a:21 != uniq_overlaps_pk.a:15 + │ ├── b:26 = uniq_overlaps_pk.b:20 + │ ├── c:27 = uniq_overlaps_pk.c:21 + │ └── a:25 != uniq_overlaps_pk.a:19 ├── unique-checks-item: uniq_overlaps_pk(a) │ └── project - │ ├── columns: a:31 + │ ├── columns: a:35 │ └── semi-join (hash) - │ ├── columns: a:31 b:32 c:33 d:34 + │ ├── columns: a:35 b:36 c:37 d:38 │ ├── with-scan &1 - │ │ ├── columns: a:31 b:32 c:33 d:34 + │ │ ├── columns: a:35 b:36 c:37 d:38 │ │ └── mapping: - │ │ ├── k:7 => a:31 - │ │ ├── v:8 => b:32 - │ │ ├── x:10 => c:33 - │ │ └── y:11 => d:34 + │ │ ├── k:15 => a:35 + │ │ ├── v:16 => b:36 + │ │ ├── x:17 => c:37 + │ │ └── y:18 => d:38 │ ├── scan uniq_overlaps_pk - │ │ └── columns: uniq_overlaps_pk.a:25!null uniq_overlaps_pk.b:26!null uniq_overlaps_pk.c:27 uniq_overlaps_pk.d:28 + │ │ └── columns: uniq_overlaps_pk.a:29!null uniq_overlaps_pk.b:30!null uniq_overlaps_pk.c:31 uniq_overlaps_pk.d:32 │ └── filters - │ ├── a:31 = uniq_overlaps_pk.a:25 - │ └── b:32 != uniq_overlaps_pk.b:26 + │ ├── a:35 = uniq_overlaps_pk.a:29 + │ └── b:36 != uniq_overlaps_pk.b:30 └── unique-checks-item: uniq_overlaps_pk(c,d) └── project - ├── columns: c:43 d:44 + ├── columns: c:47 d:48 └── semi-join (hash) - ├── columns: a:41 b:42 c:43 d:44 + ├── columns: a:45 b:46 c:47 d:48 ├── with-scan &1 - │ ├── columns: a:41 b:42 c:43 d:44 + │ ├── columns: a:45 b:46 c:47 d:48 │ └── mapping: - │ ├── k:7 => a:41 - │ ├── v:8 => b:42 - │ ├── x:10 => c:43 - │ └── y:11 => d:44 + │ ├── k:15 => a:45 + │ ├── v:16 => b:46 + │ ├── x:17 => c:47 + │ └── y:18 => d:48 ├── scan uniq_overlaps_pk - │ └── columns: uniq_overlaps_pk.a:35!null uniq_overlaps_pk.b:36!null uniq_overlaps_pk.c:37 uniq_overlaps_pk.d:38 + │ └── columns: uniq_overlaps_pk.a:39!null uniq_overlaps_pk.b:40!null uniq_overlaps_pk.c:41 uniq_overlaps_pk.d:42 └── filters - ├── c:43 = uniq_overlaps_pk.c:37 - ├── d:44 = uniq_overlaps_pk.d:38 - └── (a:41 != uniq_overlaps_pk.a:35) OR (b:42 != uniq_overlaps_pk.b:36) + ├── c:47 = uniq_overlaps_pk.c:41 + ├── d:48 = uniq_overlaps_pk.d:42 + └── (a:45 != uniq_overlaps_pk.a:39) OR (b:46 != uniq_overlaps_pk.b:40) exec-ddl CREATE TABLE uniq_hidden_pk ( @@ -637,78 +871,89 @@ INSERT INTO uniq_hidden_pk VALUES (1, 1, 1, 1), (2, 2, 2, 2) insert uniq_hidden_pk ├── columns: ├── insert-mapping: - │ ├── column1:8 => uniq_hidden_pk.a:1 - │ ├── column2:9 => uniq_hidden_pk.b:2 - │ ├── column3:10 => uniq_hidden_pk.c:3 - │ ├── column4:11 => uniq_hidden_pk.d:4 - │ └── rowid_default:12 => uniq_hidden_pk.rowid:5 + │ ├── column1:12 => uniq_hidden_pk.a:1 + │ ├── column2:13 => uniq_hidden_pk.b:2 + │ ├── column3:14 => uniq_hidden_pk.c:3 + │ ├── column4:15 => uniq_hidden_pk.d:4 + │ └── rowid_default:16 => uniq_hidden_pk.rowid:5 ├── input binding: &1 ├── project - │ ├── columns: rowid_default:12 column1:8!null column2:9!null column3:10!null column4:11!null - │ ├── values - │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null - │ │ ├── (1, 1, 1, 1) - │ │ └── (2, 2, 2, 2) + │ ├── columns: rowid_default:16 column1:12!null column2:13!null column3:14!null column4:15!null + │ ├── project + │ │ ├── columns: column1:12!null column2:13!null column3:14!null column4:15!null + │ │ ├── values + │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null column4:11!null + │ │ │ ├── (1, 1, 1, 1) + │ │ │ └── (2, 2, 2, 2) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:12] + │ │ │ └── column1:8 + │ │ ├── assignment-cast: INT8 [as=column2:13] + │ │ │ └── column2:9 + │ │ ├── assignment-cast: INT8 [as=column3:14] + │ │ │ └── column3:10 + │ │ └── assignment-cast: INT8 [as=column4:15] + │ │ └── column4:11 │ └── projections - │ └── unique_rowid() [as=rowid_default:12] + │ └── unique_rowid() [as=rowid_default:16] └── unique-checks ├── unique-checks-item: uniq_hidden_pk(b,c) │ └── project - │ ├── columns: b:21!null c:22!null + │ ├── columns: b:25!null c:26!null │ └── semi-join (hash) - │ ├── columns: a:20!null b:21!null c:22!null d:23!null rowid:24 + │ ├── columns: a:24!null b:25!null c:26!null d:27!null rowid:28 │ ├── with-scan &1 - │ │ ├── columns: a:20!null b:21!null c:22!null d:23!null rowid:24 + │ │ ├── columns: a:24!null b:25!null c:26!null d:27!null rowid:28 │ │ └── mapping: - │ │ ├── column1:8 => a:20 - │ │ ├── column2:9 => b:21 - │ │ ├── column3:10 => c:22 - │ │ ├── column4:11 => d:23 - │ │ └── rowid_default:12 => rowid:24 + │ │ ├── column1:12 => a:24 + │ │ ├── column2:13 => b:25 + │ │ ├── column3:14 => c:26 + │ │ ├── column4:15 => d:27 + │ │ └── rowid_default:16 => rowid:28 │ ├── scan uniq_hidden_pk - │ │ └── columns: uniq_hidden_pk.a:13 uniq_hidden_pk.b:14 uniq_hidden_pk.c:15 uniq_hidden_pk.d:16 uniq_hidden_pk.rowid:17!null + │ │ └── columns: uniq_hidden_pk.a:17 uniq_hidden_pk.b:18 uniq_hidden_pk.c:19 uniq_hidden_pk.d:20 uniq_hidden_pk.rowid:21!null │ └── filters - │ ├── b:21 = uniq_hidden_pk.b:14 - │ ├── c:22 = uniq_hidden_pk.c:15 - │ └── rowid:24 != uniq_hidden_pk.rowid:17 + │ ├── b:25 = uniq_hidden_pk.b:18 + │ ├── c:26 = uniq_hidden_pk.c:19 + │ └── rowid:28 != uniq_hidden_pk.rowid:21 ├── unique-checks-item: uniq_hidden_pk(a,b,d) │ └── project - │ ├── columns: a:32!null b:33!null d:35!null + │ ├── columns: a:36!null b:37!null d:39!null │ └── semi-join (hash) - │ ├── columns: a:32!null b:33!null c:34!null d:35!null rowid:36 + │ ├── columns: a:36!null b:37!null c:38!null d:39!null rowid:40 │ ├── with-scan &1 - │ │ ├── columns: a:32!null b:33!null c:34!null d:35!null rowid:36 + │ │ ├── columns: a:36!null b:37!null c:38!null d:39!null rowid:40 │ │ └── mapping: - │ │ ├── column1:8 => a:32 - │ │ ├── column2:9 => b:33 - │ │ ├── column3:10 => c:34 - │ │ ├── column4:11 => d:35 - │ │ └── rowid_default:12 => rowid:36 + │ │ ├── column1:12 => a:36 + │ │ ├── column2:13 => b:37 + │ │ ├── column3:14 => c:38 + │ │ ├── column4:15 => d:39 + │ │ └── rowid_default:16 => rowid:40 │ ├── scan uniq_hidden_pk - │ │ └── columns: uniq_hidden_pk.a:25 uniq_hidden_pk.b:26 uniq_hidden_pk.c:27 uniq_hidden_pk.d:28 uniq_hidden_pk.rowid:29!null + │ │ └── columns: uniq_hidden_pk.a:29 uniq_hidden_pk.b:30 uniq_hidden_pk.c:31 uniq_hidden_pk.d:32 uniq_hidden_pk.rowid:33!null │ └── filters - │ ├── a:32 = uniq_hidden_pk.a:25 - │ ├── b:33 = uniq_hidden_pk.b:26 - │ ├── d:35 = uniq_hidden_pk.d:28 - │ └── rowid:36 != uniq_hidden_pk.rowid:29 + │ ├── a:36 = uniq_hidden_pk.a:29 + │ ├── b:37 = uniq_hidden_pk.b:30 + │ ├── d:39 = uniq_hidden_pk.d:32 + │ └── rowid:40 != uniq_hidden_pk.rowid:33 └── unique-checks-item: uniq_hidden_pk(a) └── project - ├── columns: a:44!null + ├── columns: a:48!null └── semi-join (hash) - ├── columns: a:44!null b:45!null c:46!null d:47!null rowid:48 + ├── columns: a:48!null b:49!null c:50!null d:51!null rowid:52 ├── with-scan &1 - │ ├── columns: a:44!null b:45!null c:46!null d:47!null rowid:48 + │ ├── columns: a:48!null b:49!null c:50!null d:51!null rowid:52 │ └── mapping: - │ ├── column1:8 => a:44 - │ ├── column2:9 => b:45 - │ ├── column3:10 => c:46 - │ ├── column4:11 => d:47 - │ └── rowid_default:12 => rowid:48 + │ ├── column1:12 => a:48 + │ ├── column2:13 => b:49 + │ ├── column3:14 => c:50 + │ ├── column4:15 => d:51 + │ └── rowid_default:16 => rowid:52 ├── scan uniq_hidden_pk - │ └── columns: uniq_hidden_pk.a:37 uniq_hidden_pk.b:38 uniq_hidden_pk.c:39 uniq_hidden_pk.d:40 uniq_hidden_pk.rowid:41!null + │ └── columns: uniq_hidden_pk.a:41 uniq_hidden_pk.b:42 uniq_hidden_pk.c:43 uniq_hidden_pk.d:44 uniq_hidden_pk.rowid:45!null └── filters - ├── a:44 = uniq_hidden_pk.a:37 - └── rowid:48 != uniq_hidden_pk.rowid:41 + ├── a:48 = uniq_hidden_pk.a:41 + └── rowid:52 != uniq_hidden_pk.rowid:45 # Insert with non-constant input. # Add inequality filters for the hidden primary key column. @@ -718,78 +963,89 @@ INSERT INTO uniq_hidden_pk SELECT k, v, x, y FROM other insert uniq_hidden_pk ├── columns: ├── insert-mapping: - │ ├── k:8 => uniq_hidden_pk.a:1 - │ ├── v:9 => uniq_hidden_pk.b:2 - │ ├── x:11 => uniq_hidden_pk.c:3 - │ ├── y:12 => uniq_hidden_pk.d:4 - │ └── rowid_default:16 => uniq_hidden_pk.rowid:5 + │ ├── k:16 => uniq_hidden_pk.a:1 + │ ├── v:17 => uniq_hidden_pk.b:2 + │ ├── x:18 => uniq_hidden_pk.c:3 + │ ├── y:19 => uniq_hidden_pk.d:4 + │ └── rowid_default:20 => uniq_hidden_pk.rowid:5 ├── input binding: &1 ├── project - │ ├── columns: rowid_default:16 k:8 v:9 x:11 y:12 + │ ├── columns: rowid_default:20 k:16 v:17 x:18 y:19 │ ├── project - │ │ ├── columns: k:8 v:9 x:11 y:12 - │ │ └── scan other - │ │ └── columns: k:8 v:9 w:10!null x:11 y:12 other.rowid:13!null other.crdb_internal_mvcc_timestamp:14 other.tableoid:15 + │ │ ├── columns: k:16 v:17 x:18 y:19 + │ │ ├── project + │ │ │ ├── columns: other.k:8 other.v:9 other.x:11 other.y:12 + │ │ │ └── scan other + │ │ │ └── columns: other.k:8 other.v:9 w:10!null other.x:11 other.y:12 other.rowid:13!null other.crdb_internal_mvcc_timestamp:14 other.tableoid:15 + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=k:16] + │ │ │ └── other.k:8 + │ │ ├── assignment-cast: INT8 [as=v:17] + │ │ │ └── other.v:9 + │ │ ├── assignment-cast: INT8 [as=x:18] + │ │ │ └── other.x:11 + │ │ └── assignment-cast: INT8 [as=y:19] + │ │ └── other.y:12 │ └── projections - │ └── unique_rowid() [as=rowid_default:16] + │ └── unique_rowid() [as=rowid_default:20] └── unique-checks ├── unique-checks-item: uniq_hidden_pk(b,c) │ └── project - │ ├── columns: b:25 c:26 + │ ├── columns: b:29 c:30 │ └── semi-join (hash) - │ ├── columns: a:24 b:25 c:26 d:27 rowid:28 + │ ├── columns: a:28 b:29 c:30 d:31 rowid:32 │ ├── with-scan &1 - │ │ ├── columns: a:24 b:25 c:26 d:27 rowid:28 + │ │ ├── columns: a:28 b:29 c:30 d:31 rowid:32 │ │ └── mapping: - │ │ ├── k:8 => a:24 - │ │ ├── v:9 => b:25 - │ │ ├── x:11 => c:26 - │ │ ├── y:12 => d:27 - │ │ └── rowid_default:16 => rowid:28 + │ │ ├── k:16 => a:28 + │ │ ├── v:17 => b:29 + │ │ ├── x:18 => c:30 + │ │ ├── y:19 => d:31 + │ │ └── rowid_default:20 => rowid:32 │ ├── scan uniq_hidden_pk - │ │ └── columns: uniq_hidden_pk.a:17 uniq_hidden_pk.b:18 uniq_hidden_pk.c:19 uniq_hidden_pk.d:20 uniq_hidden_pk.rowid:21!null + │ │ └── columns: uniq_hidden_pk.a:21 uniq_hidden_pk.b:22 uniq_hidden_pk.c:23 uniq_hidden_pk.d:24 uniq_hidden_pk.rowid:25!null │ └── filters - │ ├── b:25 = uniq_hidden_pk.b:18 - │ ├── c:26 = uniq_hidden_pk.c:19 - │ └── rowid:28 != uniq_hidden_pk.rowid:21 + │ ├── b:29 = uniq_hidden_pk.b:22 + │ ├── c:30 = uniq_hidden_pk.c:23 + │ └── rowid:32 != uniq_hidden_pk.rowid:25 ├── unique-checks-item: uniq_hidden_pk(a,b,d) │ └── project - │ ├── columns: a:36 b:37 d:39 + │ ├── columns: a:40 b:41 d:43 │ └── semi-join (hash) - │ ├── columns: a:36 b:37 c:38 d:39 rowid:40 + │ ├── columns: a:40 b:41 c:42 d:43 rowid:44 │ ├── with-scan &1 - │ │ ├── columns: a:36 b:37 c:38 d:39 rowid:40 + │ │ ├── columns: a:40 b:41 c:42 d:43 rowid:44 │ │ └── mapping: - │ │ ├── k:8 => a:36 - │ │ ├── v:9 => b:37 - │ │ ├── x:11 => c:38 - │ │ ├── y:12 => d:39 - │ │ └── rowid_default:16 => rowid:40 + │ │ ├── k:16 => a:40 + │ │ ├── v:17 => b:41 + │ │ ├── x:18 => c:42 + │ │ ├── y:19 => d:43 + │ │ └── rowid_default:20 => rowid:44 │ ├── scan uniq_hidden_pk - │ │ └── columns: uniq_hidden_pk.a:29 uniq_hidden_pk.b:30 uniq_hidden_pk.c:31 uniq_hidden_pk.d:32 uniq_hidden_pk.rowid:33!null + │ │ └── columns: uniq_hidden_pk.a:33 uniq_hidden_pk.b:34 uniq_hidden_pk.c:35 uniq_hidden_pk.d:36 uniq_hidden_pk.rowid:37!null │ └── filters - │ ├── a:36 = uniq_hidden_pk.a:29 - │ ├── b:37 = uniq_hidden_pk.b:30 - │ ├── d:39 = uniq_hidden_pk.d:32 - │ └── rowid:40 != uniq_hidden_pk.rowid:33 + │ ├── a:40 = uniq_hidden_pk.a:33 + │ ├── b:41 = uniq_hidden_pk.b:34 + │ ├── d:43 = uniq_hidden_pk.d:36 + │ └── rowid:44 != uniq_hidden_pk.rowid:37 └── unique-checks-item: uniq_hidden_pk(a) └── project - ├── columns: a:48 + ├── columns: a:52 └── semi-join (hash) - ├── columns: a:48 b:49 c:50 d:51 rowid:52 + ├── columns: a:52 b:53 c:54 d:55 rowid:56 ├── with-scan &1 - │ ├── columns: a:48 b:49 c:50 d:51 rowid:52 + │ ├── columns: a:52 b:53 c:54 d:55 rowid:56 │ └── mapping: - │ ├── k:8 => a:48 - │ ├── v:9 => b:49 - │ ├── x:11 => c:50 - │ ├── y:12 => d:51 - │ └── rowid_default:16 => rowid:52 + │ ├── k:16 => a:52 + │ ├── v:17 => b:53 + │ ├── x:18 => c:54 + │ ├── y:19 => d:55 + │ └── rowid_default:20 => rowid:56 ├── scan uniq_hidden_pk - │ └── columns: uniq_hidden_pk.a:41 uniq_hidden_pk.b:42 uniq_hidden_pk.c:43 uniq_hidden_pk.d:44 uniq_hidden_pk.rowid:45!null + │ └── columns: uniq_hidden_pk.a:45 uniq_hidden_pk.b:46 uniq_hidden_pk.c:47 uniq_hidden_pk.d:48 uniq_hidden_pk.rowid:49!null └── filters - ├── a:48 = uniq_hidden_pk.a:41 - └── rowid:52 != uniq_hidden_pk.rowid:45 + ├── a:52 = uniq_hidden_pk.a:45 + └── rowid:56 != uniq_hidden_pk.rowid:49 exec-ddl CREATE TABLE uniq_partial ( @@ -807,33 +1063,42 @@ INSERT INTO uniq_partial VALUES (1, 1, 1), (2, 2, 2) insert uniq_partial ├── columns: ├── insert-mapping: - │ ├── column1:6 => uniq_partial.k:1 - │ ├── column2:7 => uniq_partial.a:2 - │ └── column3:8 => uniq_partial.b:3 + │ ├── column1:9 => uniq_partial.k:1 + │ ├── column2:10 => uniq_partial.a:2 + │ └── column3:11 => uniq_partial.b:3 ├── input binding: &1 - ├── values - │ ├── columns: column1:6!null column2:7!null column3:8!null - │ ├── (1, 1, 1) - │ └── (2, 2, 2) + ├── project + │ ├── columns: column1:9!null column2:10!null column3:11!null + │ ├── values + │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ ├── (1, 1, 1) + │ │ └── (2, 2, 2) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:9] + │ │ └── column1:6 + │ ├── assignment-cast: INT8 [as=column2:10] + │ │ └── column2:7 + │ └── assignment-cast: INT8 [as=column3:11] + │ └── column3:8 └── unique-checks └── unique-checks-item: uniq_partial(a) └── project - ├── columns: a:15!null + ├── columns: a:18!null └── semi-join (hash) - ├── columns: k:14!null a:15!null b:16!null + ├── columns: k:17!null a:18!null b:19!null ├── with-scan &1 - │ ├── columns: k:14!null a:15!null b:16!null + │ ├── columns: k:17!null a:18!null b:19!null │ └── mapping: - │ ├── column1:6 => k:14 - │ ├── column2:7 => a:15 - │ └── column3:8 => b:16 + │ ├── column1:9 => k:17 + │ ├── column2:10 => a:18 + │ └── column3:11 => b:19 ├── scan uniq_partial - │ └── columns: uniq_partial.k:9!null uniq_partial.a:10 uniq_partial.b:11 + │ └── columns: uniq_partial.k:12!null uniq_partial.a:13 uniq_partial.b:14 └── filters - ├── a:15 = uniq_partial.a:10 - ├── b:16 > 0 - ├── uniq_partial.b:11 > 0 - └── k:14 != uniq_partial.k:9 + ├── a:18 = uniq_partial.a:13 + ├── b:19 > 0 + ├── uniq_partial.b:14 > 0 + └── k:17 != uniq_partial.k:12 # Some of the inserted values have nulls. build @@ -842,34 +1107,43 @@ INSERT INTO uniq_partial VALUES (1, 1, 1), (2, 2, 2), (3, NULL, 3) insert uniq_partial ├── columns: ├── insert-mapping: - │ ├── column1:6 => uniq_partial.k:1 - │ ├── column2:7 => uniq_partial.a:2 - │ └── column3:8 => uniq_partial.b:3 + │ ├── column1:9 => uniq_partial.k:1 + │ ├── column2:10 => uniq_partial.a:2 + │ └── column3:11 => uniq_partial.b:3 ├── input binding: &1 - ├── values - │ ├── columns: column1:6!null column2:7 column3:8!null - │ ├── (1, 1, 1) - │ ├── (2, 2, 2) - │ └── (3, NULL::INT8, 3) + ├── project + │ ├── columns: column1:9!null column2:10 column3:11!null + │ ├── values + │ │ ├── columns: column1:6!null column2:7 column3:8!null + │ │ ├── (1, 1, 1) + │ │ ├── (2, 2, 2) + │ │ └── (3, NULL::INT8, 3) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:9] + │ │ └── column1:6 + │ ├── assignment-cast: INT8 [as=column2:10] + │ │ └── column2:7 + │ └── assignment-cast: INT8 [as=column3:11] + │ └── column3:8 └── unique-checks └── unique-checks-item: uniq_partial(a) └── project - ├── columns: a:15 + ├── columns: a:18 └── semi-join (hash) - ├── columns: k:14!null a:15 b:16!null + ├── columns: k:17!null a:18 b:19!null ├── with-scan &1 - │ ├── columns: k:14!null a:15 b:16!null + │ ├── columns: k:17!null a:18 b:19!null │ └── mapping: - │ ├── column1:6 => k:14 - │ ├── column2:7 => a:15 - │ └── column3:8 => b:16 + │ ├── column1:9 => k:17 + │ ├── column2:10 => a:18 + │ └── column3:11 => b:19 ├── scan uniq_partial - │ └── columns: uniq_partial.k:9!null uniq_partial.a:10 uniq_partial.b:11 + │ └── columns: uniq_partial.k:12!null uniq_partial.a:13 uniq_partial.b:14 └── filters - ├── a:15 = uniq_partial.a:10 - ├── b:16 > 0 - ├── uniq_partial.b:11 > 0 - └── k:14 != uniq_partial.k:9 + ├── a:18 = uniq_partial.a:13 + ├── b:19 > 0 + ├── uniq_partial.b:14 > 0 + └── k:17 != uniq_partial.k:12 # No need to plan checks for a since it's always null. build @@ -878,13 +1152,42 @@ INSERT INTO uniq_partial VALUES (1, NULL, 1), (2, NULL, 2) insert uniq_partial ├── columns: ├── insert-mapping: - │ ├── column1:6 => k:1 - │ ├── column2:7 => a:2 - │ └── column3:8 => b:3 - └── values - ├── columns: column1:6!null column2:7 column3:8!null - ├── (1, NULL::INT8, 1) - └── (2, NULL::INT8, 2) + │ ├── column1:9 => uniq_partial.k:1 + │ ├── column2:10 => uniq_partial.a:2 + │ └── column3:11 => uniq_partial.b:3 + ├── input binding: &1 + ├── project + │ ├── columns: column1:9!null column2:10 column3:11!null + │ ├── values + │ │ ├── columns: column1:6!null column2:7 column3:8!null + │ │ ├── (1, NULL::INT8, 1) + │ │ └── (2, NULL::INT8, 2) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:9] + │ │ └── column1:6 + │ ├── assignment-cast: INT8 [as=column2:10] + │ │ └── column2:7 + │ └── assignment-cast: INT8 [as=column3:11] + │ └── column3:8 + └── unique-checks + └── unique-checks-item: uniq_partial(a) + └── project + ├── columns: a:18 + └── semi-join (hash) + ├── columns: k:17!null a:18 b:19!null + ├── with-scan &1 + │ ├── columns: k:17!null a:18 b:19!null + │ └── mapping: + │ ├── column1:9 => k:17 + │ ├── column2:10 => a:18 + │ └── column3:11 => b:19 + ├── scan uniq_partial + │ └── columns: uniq_partial.k:12!null uniq_partial.a:13 uniq_partial.b:14 + └── filters + ├── a:18 = uniq_partial.a:13 + ├── b:19 > 0 + ├── uniq_partial.b:14 > 0 + └── k:17 != uniq_partial.k:12 # Use all the unique constraint as an arbiter for DO NOTHING with no conflict # columns. @@ -896,52 +1199,61 @@ insert uniq_partial ├── arbiter indexes: uniq_partial_pkey ├── arbiter constraints: unique_a ├── insert-mapping: - │ ├── column1:6 => k:1 - │ ├── column2:7 => a:2 - │ └── column3:8 => b:3 + │ ├── column1:9 => k:1 + │ ├── column2:10 => a:2 + │ └── column3:11 => b:3 └── project - ├── columns: column1:6!null column2:7!null column3:8!null + ├── columns: column1:9!null column2:10!null column3:11!null └── upsert-distinct-on - ├── columns: column1:6!null column2:7!null column3:8!null arbiter_unique_a_distinct:19 - ├── grouping columns: column2:7!null arbiter_unique_a_distinct:19 + ├── columns: column1:9!null column2:10!null column3:11!null arbiter_unique_a_distinct:22 + ├── grouping columns: column2:10!null arbiter_unique_a_distinct:22 ├── project - │ ├── columns: arbiter_unique_a_distinct:19 column1:6!null column2:7!null column3:8!null + │ ├── columns: arbiter_unique_a_distinct:22 column1:9!null column2:10!null column3:11!null │ ├── upsert-distinct-on - │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ ├── grouping columns: column1:6!null + │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ ├── grouping columns: column1:9!null │ │ ├── anti-join (hash) - │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null │ │ │ ├── anti-join (hash) - │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ ├── values - │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ │ ├── (1, 2, 3) - │ │ │ │ │ └── (2, 2, 3) + │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ ├── project + │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ │ ├── values + │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ │ │ ├── (1, 2, 3) + │ │ │ │ │ │ └── (2, 2, 3) + │ │ │ │ │ └── projections + │ │ │ │ │ ├── assignment-cast: INT8 [as=column1:9] + │ │ │ │ │ │ └── column1:6 + │ │ │ │ │ ├── assignment-cast: INT8 [as=column2:10] + │ │ │ │ │ │ └── column2:7 + │ │ │ │ │ └── assignment-cast: INT8 [as=column3:11] + │ │ │ │ │ └── column3:8 │ │ │ │ ├── scan uniq_partial - │ │ │ │ │ └── columns: k:9!null a:10 b:11 + │ │ │ │ │ └── columns: k:12!null a:13 b:14 │ │ │ │ └── filters - │ │ │ │ └── column1:6 = k:9 + │ │ │ │ └── column1:9 = k:12 │ │ │ ├── select - │ │ │ │ ├── columns: k:14!null a:15 b:16!null + │ │ │ │ ├── columns: k:17!null a:18 b:19!null │ │ │ │ ├── scan uniq_partial - │ │ │ │ │ └── columns: k:14!null a:15 b:16 + │ │ │ │ │ └── columns: k:17!null a:18 b:19 │ │ │ │ └── filters - │ │ │ │ └── b:16 > 0 + │ │ │ │ └── b:19 > 0 │ │ │ └── filters - │ │ │ ├── column2:7 = a:15 - │ │ │ └── column3:8 > 0 + │ │ │ ├── column2:10 = a:18 + │ │ │ └── column3:11 > 0 │ │ └── aggregations - │ │ ├── first-agg [as=column2:7] - │ │ │ └── column2:7 - │ │ └── first-agg [as=column3:8] - │ │ └── column3:8 + │ │ ├── first-agg [as=column2:10] + │ │ │ └── column2:10 + │ │ └── first-agg [as=column3:11] + │ │ └── column3:11 │ └── projections - │ └── (column3:8 > 0) OR NULL::BOOL [as=arbiter_unique_a_distinct:19] + │ └── (column3:11 > 0) OR NULL::BOOL [as=arbiter_unique_a_distinct:22] └── aggregations - ├── first-agg [as=column1:6] - │ └── column1:6 - └── first-agg [as=column3:8] - └── column3:8 + ├── first-agg [as=column1:9] + │ └── column1:9 + └── first-agg [as=column3:11] + └── column3:11 # Error when there is no arbiter predicate to match the partial unique # constraint predicate. @@ -958,37 +1270,46 @@ insert uniq_partial ├── columns: ├── arbiter constraints: unique_a ├── insert-mapping: - │ ├── column1:6 => k:1 - │ ├── column2:7 => a:2 - │ └── column3:8 => b:3 + │ ├── column1:9 => k:1 + │ ├── column2:10 => a:2 + │ └── column3:11 => b:3 └── project - ├── columns: column1:6!null column2:7!null column3:8!null + ├── columns: column1:9!null column2:10!null column3:11!null └── upsert-distinct-on - ├── columns: column1:6!null column2:7!null column3:8!null arbiter_unique_a_distinct:14 - ├── grouping columns: column2:7!null arbiter_unique_a_distinct:14 + ├── columns: column1:9!null column2:10!null column3:11!null arbiter_unique_a_distinct:17 + ├── grouping columns: column2:10!null arbiter_unique_a_distinct:17 ├── project - │ ├── columns: arbiter_unique_a_distinct:14 column1:6!null column2:7!null column3:8!null + │ ├── columns: arbiter_unique_a_distinct:17 column1:9!null column2:10!null column3:11!null │ ├── anti-join (hash) - │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ ├── values - │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ └── (1, 2, 3) + │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ ├── project + │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ ├── values + │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ └── (1, 2, 3) + │ │ │ └── projections + │ │ │ ├── assignment-cast: INT8 [as=column1:9] + │ │ │ │ └── column1:6 + │ │ │ ├── assignment-cast: INT8 [as=column2:10] + │ │ │ │ └── column2:7 + │ │ │ └── assignment-cast: INT8 [as=column3:11] + │ │ │ └── column3:8 │ │ ├── select - │ │ │ ├── columns: k:9!null a:10 b:11!null + │ │ │ ├── columns: k:12!null a:13 b:14!null │ │ │ ├── scan uniq_partial - │ │ │ │ └── columns: k:9!null a:10 b:11 + │ │ │ │ └── columns: k:12!null a:13 b:14 │ │ │ └── filters - │ │ │ └── b:11 > 0 + │ │ │ └── b:14 > 0 │ │ └── filters - │ │ ├── column2:7 = a:10 - │ │ └── column3:8 > 0 + │ │ ├── column2:10 = a:13 + │ │ └── column3:11 > 0 │ └── projections - │ └── (column3:8 > 0) OR NULL::BOOL [as=arbiter_unique_a_distinct:14] + │ └── (column3:11 > 0) OR NULL::BOOL [as=arbiter_unique_a_distinct:17] └── aggregations - ├── first-agg [as=column1:6] - │ └── column1:6 - └── first-agg [as=column3:8] - └── column3:8 + ├── first-agg [as=column1:9] + │ └── column1:9 + └── first-agg [as=column3:11] + └── column3:11 # Insert with non-constant input. build @@ -997,33 +1318,42 @@ INSERT INTO uniq_partial SELECT k, v, w FROM other insert uniq_partial ├── columns: ├── insert-mapping: - │ ├── other.k:6 => uniq_partial.k:1 - │ ├── v:7 => uniq_partial.a:2 - │ └── w:8 => uniq_partial.b:3 + │ ├── k:14 => uniq_partial.k:1 + │ ├── v:15 => uniq_partial.a:2 + │ └── w:16 => uniq_partial.b:3 ├── input binding: &1 ├── project - │ ├── columns: other.k:6 v:7 w:8!null - │ └── scan other - │ └── columns: other.k:6 v:7 w:8!null x:9 y:10 rowid:11!null other.crdb_internal_mvcc_timestamp:12 other.tableoid:13 + │ ├── columns: k:14 v:15 w:16!null + │ ├── project + │ │ ├── columns: other.k:6 other.v:7 other.w:8!null + │ │ └── scan other + │ │ └── columns: other.k:6 other.v:7 other.w:8!null x:9 y:10 rowid:11!null other.crdb_internal_mvcc_timestamp:12 other.tableoid:13 + │ └── projections + │ ├── assignment-cast: INT8 [as=k:14] + │ │ └── other.k:6 + │ ├── assignment-cast: INT8 [as=v:15] + │ │ └── other.v:7 + │ └── assignment-cast: INT8 [as=w:16] + │ └── other.w:8 └── unique-checks └── unique-checks-item: uniq_partial(a) └── project - ├── columns: a:20 + ├── columns: a:23 └── semi-join (hash) - ├── columns: k:19 a:20 b:21!null + ├── columns: k:22 a:23 b:24!null ├── with-scan &1 - │ ├── columns: k:19 a:20 b:21!null + │ ├── columns: k:22 a:23 b:24!null │ └── mapping: - │ ├── other.k:6 => k:19 - │ ├── v:7 => a:20 - │ └── w:8 => b:21 + │ ├── k:14 => k:22 + │ ├── v:15 => a:23 + │ └── w:16 => b:24 ├── scan uniq_partial - │ └── columns: uniq_partial.k:14!null uniq_partial.a:15 uniq_partial.b:16 + │ └── columns: uniq_partial.k:17!null uniq_partial.a:18 uniq_partial.b:19 └── filters - ├── a:20 = uniq_partial.a:15 - ├── b:21 > 0 - ├── uniq_partial.b:16 > 0 - └── k:19 != uniq_partial.k:14 + ├── a:23 = uniq_partial.a:18 + ├── b:24 > 0 + ├── uniq_partial.b:19 > 0 + └── k:22 != uniq_partial.k:17 exec-ddl CREATE TABLE uniq_partial_overlaps_pk ( @@ -1049,74 +1379,85 @@ INSERT INTO uniq_partial_overlaps_pk VALUES (1, 1, 1, 1), (2, 2, 2, 2) insert uniq_partial_overlaps_pk ├── columns: ├── insert-mapping: - │ ├── column1:7 => uniq_partial_overlaps_pk.a:1 - │ ├── column2:8 => uniq_partial_overlaps_pk.b:2 - │ ├── column3:9 => uniq_partial_overlaps_pk.c:3 - │ └── column4:10 => uniq_partial_overlaps_pk.d:4 + │ ├── column1:11 => uniq_partial_overlaps_pk.a:1 + │ ├── column2:12 => uniq_partial_overlaps_pk.b:2 + │ ├── column3:13 => uniq_partial_overlaps_pk.c:3 + │ └── column4:14 => uniq_partial_overlaps_pk.d:4 ├── input binding: &1 - ├── values - │ ├── columns: column1:7!null column2:8!null column3:9!null column4:10!null - │ ├── (1, 1, 1, 1) - │ └── (2, 2, 2, 2) + ├── project + │ ├── columns: column1:11!null column2:12!null column3:13!null column4:14!null + │ ├── values + │ │ ├── columns: column1:7!null column2:8!null column3:9!null column4:10!null + │ │ ├── (1, 1, 1, 1) + │ │ └── (2, 2, 2, 2) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:11] + │ │ └── column1:7 + │ ├── assignment-cast: INT8 [as=column2:12] + │ │ └── column2:8 + │ ├── assignment-cast: INT8 [as=column3:13] + │ │ └── column3:9 + │ └── assignment-cast: INT8 [as=column4:14] + │ └── column4:10 └── unique-checks ├── unique-checks-item: uniq_partial_overlaps_pk(c) │ └── project - │ ├── columns: c:19!null + │ ├── columns: c:23!null │ └── semi-join (hash) - │ ├── columns: a:17!null b:18!null c:19!null d:20!null + │ ├── columns: a:21!null b:22!null c:23!null d:24!null │ ├── with-scan &1 - │ │ ├── columns: a:17!null b:18!null c:19!null d:20!null + │ │ ├── columns: a:21!null b:22!null c:23!null d:24!null │ │ └── mapping: - │ │ ├── column1:7 => a:17 - │ │ ├── column2:8 => b:18 - │ │ ├── column3:9 => c:19 - │ │ └── column4:10 => d:20 + │ │ ├── column1:11 => a:21 + │ │ ├── column2:12 => b:22 + │ │ ├── column3:13 => c:23 + │ │ └── column4:14 => d:24 │ ├── scan uniq_partial_overlaps_pk - │ │ └── columns: uniq_partial_overlaps_pk.a:11!null uniq_partial_overlaps_pk.b:12!null uniq_partial_overlaps_pk.c:13 uniq_partial_overlaps_pk.d:14 + │ │ └── columns: uniq_partial_overlaps_pk.a:15!null uniq_partial_overlaps_pk.b:16!null uniq_partial_overlaps_pk.c:17 uniq_partial_overlaps_pk.d:18 │ └── filters - │ ├── c:19 = uniq_partial_overlaps_pk.c:13 - │ ├── d:20 > 0 - │ ├── uniq_partial_overlaps_pk.d:14 > 0 - │ └── (a:17 != uniq_partial_overlaps_pk.a:11) OR (b:18 != uniq_partial_overlaps_pk.b:12) + │ ├── c:23 = uniq_partial_overlaps_pk.c:17 + │ ├── d:24 > 0 + │ ├── uniq_partial_overlaps_pk.d:18 > 0 + │ └── (a:21 != uniq_partial_overlaps_pk.a:15) OR (b:22 != uniq_partial_overlaps_pk.b:16) ├── unique-checks-item: uniq_partial_overlaps_pk(a) │ └── project - │ ├── columns: a:27!null + │ ├── columns: a:31!null │ └── semi-join (hash) - │ ├── columns: a:27!null b:28!null c:29!null d:30!null + │ ├── columns: a:31!null b:32!null c:33!null d:34!null │ ├── with-scan &1 - │ │ ├── columns: a:27!null b:28!null c:29!null d:30!null + │ │ ├── columns: a:31!null b:32!null c:33!null d:34!null │ │ └── mapping: - │ │ ├── column1:7 => a:27 - │ │ ├── column2:8 => b:28 - │ │ ├── column3:9 => c:29 - │ │ └── column4:10 => d:30 + │ │ ├── column1:11 => a:31 + │ │ ├── column2:12 => b:32 + │ │ ├── column3:13 => c:33 + │ │ └── column4:14 => d:34 │ ├── scan uniq_partial_overlaps_pk - │ │ └── columns: uniq_partial_overlaps_pk.a:21!null uniq_partial_overlaps_pk.b:22!null uniq_partial_overlaps_pk.c:23 uniq_partial_overlaps_pk.d:24 + │ │ └── columns: uniq_partial_overlaps_pk.a:25!null uniq_partial_overlaps_pk.b:26!null uniq_partial_overlaps_pk.c:27 uniq_partial_overlaps_pk.d:28 │ └── filters - │ ├── a:27 = uniq_partial_overlaps_pk.a:21 - │ ├── d:30 > 0 - │ ├── uniq_partial_overlaps_pk.d:24 > 0 - │ └── b:28 != uniq_partial_overlaps_pk.b:22 + │ ├── a:31 = uniq_partial_overlaps_pk.a:25 + │ ├── d:34 > 0 + │ ├── uniq_partial_overlaps_pk.d:28 > 0 + │ └── b:32 != uniq_partial_overlaps_pk.b:26 └── unique-checks-item: uniq_partial_overlaps_pk(b,c) └── project - ├── columns: b:38!null c:39!null + ├── columns: b:42!null c:43!null └── semi-join (hash) - ├── columns: a:37!null b:38!null c:39!null d:40!null + ├── columns: a:41!null b:42!null c:43!null d:44!null ├── with-scan &1 - │ ├── columns: a:37!null b:38!null c:39!null d:40!null + │ ├── columns: a:41!null b:42!null c:43!null d:44!null │ └── mapping: - │ ├── column1:7 => a:37 - │ ├── column2:8 => b:38 - │ ├── column3:9 => c:39 - │ └── column4:10 => d:40 + │ ├── column1:11 => a:41 + │ ├── column2:12 => b:42 + │ ├── column3:13 => c:43 + │ └── column4:14 => d:44 ├── scan uniq_partial_overlaps_pk - │ └── columns: uniq_partial_overlaps_pk.a:31!null uniq_partial_overlaps_pk.b:32!null uniq_partial_overlaps_pk.c:33 uniq_partial_overlaps_pk.d:34 + │ └── columns: uniq_partial_overlaps_pk.a:35!null uniq_partial_overlaps_pk.b:36!null uniq_partial_overlaps_pk.c:37 uniq_partial_overlaps_pk.d:38 └── filters - ├── b:38 = uniq_partial_overlaps_pk.b:32 - ├── c:39 = uniq_partial_overlaps_pk.c:33 - ├── d:40 > 0 - ├── uniq_partial_overlaps_pk.d:34 > 0 - └── a:37 != uniq_partial_overlaps_pk.a:31 + ├── b:42 = uniq_partial_overlaps_pk.b:36 + ├── c:43 = uniq_partial_overlaps_pk.c:37 + ├── d:44 > 0 + ├── uniq_partial_overlaps_pk.d:38 > 0 + └── a:41 != uniq_partial_overlaps_pk.a:35 # Insert with non-constant input. # Do not build uniqueness checks when the primary key columns are a subset of @@ -1127,74 +1468,85 @@ INSERT INTO uniq_partial_overlaps_pk SELECT k, v, x, y FROM other insert uniq_partial_overlaps_pk ├── columns: ├── insert-mapping: - │ ├── k:7 => uniq_partial_overlaps_pk.a:1 - │ ├── v:8 => uniq_partial_overlaps_pk.b:2 - │ ├── x:10 => uniq_partial_overlaps_pk.c:3 - │ └── y:11 => uniq_partial_overlaps_pk.d:4 + │ ├── k:15 => uniq_partial_overlaps_pk.a:1 + │ ├── v:16 => uniq_partial_overlaps_pk.b:2 + │ ├── x:17 => uniq_partial_overlaps_pk.c:3 + │ └── y:18 => uniq_partial_overlaps_pk.d:4 ├── input binding: &1 ├── project - │ ├── columns: k:7 v:8 x:10 y:11 - │ └── scan other - │ └── columns: k:7 v:8 w:9!null x:10 y:11 rowid:12!null other.crdb_internal_mvcc_timestamp:13 other.tableoid:14 + │ ├── columns: k:15 v:16 x:17 y:18 + │ ├── project + │ │ ├── columns: other.k:7 other.v:8 other.x:10 other.y:11 + │ │ └── scan other + │ │ └── columns: other.k:7 other.v:8 w:9!null other.x:10 other.y:11 rowid:12!null other.crdb_internal_mvcc_timestamp:13 other.tableoid:14 + │ └── projections + │ ├── assignment-cast: INT8 [as=k:15] + │ │ └── other.k:7 + │ ├── assignment-cast: INT8 [as=v:16] + │ │ └── other.v:8 + │ ├── assignment-cast: INT8 [as=x:17] + │ │ └── other.x:10 + │ └── assignment-cast: INT8 [as=y:18] + │ └── other.y:11 └── unique-checks ├── unique-checks-item: uniq_partial_overlaps_pk(c) │ └── project - │ ├── columns: c:23 + │ ├── columns: c:27 │ └── semi-join (hash) - │ ├── columns: a:21 b:22 c:23 d:24 + │ ├── columns: a:25 b:26 c:27 d:28 │ ├── with-scan &1 - │ │ ├── columns: a:21 b:22 c:23 d:24 + │ │ ├── columns: a:25 b:26 c:27 d:28 │ │ └── mapping: - │ │ ├── k:7 => a:21 - │ │ ├── v:8 => b:22 - │ │ ├── x:10 => c:23 - │ │ └── y:11 => d:24 + │ │ ├── k:15 => a:25 + │ │ ├── v:16 => b:26 + │ │ ├── x:17 => c:27 + │ │ └── y:18 => d:28 │ ├── scan uniq_partial_overlaps_pk - │ │ └── columns: uniq_partial_overlaps_pk.a:15!null uniq_partial_overlaps_pk.b:16!null uniq_partial_overlaps_pk.c:17 uniq_partial_overlaps_pk.d:18 + │ │ └── columns: uniq_partial_overlaps_pk.a:19!null uniq_partial_overlaps_pk.b:20!null uniq_partial_overlaps_pk.c:21 uniq_partial_overlaps_pk.d:22 │ └── filters - │ ├── c:23 = uniq_partial_overlaps_pk.c:17 - │ ├── d:24 > 0 - │ ├── uniq_partial_overlaps_pk.d:18 > 0 - │ └── (a:21 != uniq_partial_overlaps_pk.a:15) OR (b:22 != uniq_partial_overlaps_pk.b:16) + │ ├── c:27 = uniq_partial_overlaps_pk.c:21 + │ ├── d:28 > 0 + │ ├── uniq_partial_overlaps_pk.d:22 > 0 + │ └── (a:25 != uniq_partial_overlaps_pk.a:19) OR (b:26 != uniq_partial_overlaps_pk.b:20) ├── unique-checks-item: uniq_partial_overlaps_pk(a) │ └── project - │ ├── columns: a:31 + │ ├── columns: a:35 │ └── semi-join (hash) - │ ├── columns: a:31 b:32 c:33 d:34 + │ ├── columns: a:35 b:36 c:37 d:38 │ ├── with-scan &1 - │ │ ├── columns: a:31 b:32 c:33 d:34 + │ │ ├── columns: a:35 b:36 c:37 d:38 │ │ └── mapping: - │ │ ├── k:7 => a:31 - │ │ ├── v:8 => b:32 - │ │ ├── x:10 => c:33 - │ │ └── y:11 => d:34 + │ │ ├── k:15 => a:35 + │ │ ├── v:16 => b:36 + │ │ ├── x:17 => c:37 + │ │ └── y:18 => d:38 │ ├── scan uniq_partial_overlaps_pk - │ │ └── columns: uniq_partial_overlaps_pk.a:25!null uniq_partial_overlaps_pk.b:26!null uniq_partial_overlaps_pk.c:27 uniq_partial_overlaps_pk.d:28 + │ │ └── columns: uniq_partial_overlaps_pk.a:29!null uniq_partial_overlaps_pk.b:30!null uniq_partial_overlaps_pk.c:31 uniq_partial_overlaps_pk.d:32 │ └── filters - │ ├── a:31 = uniq_partial_overlaps_pk.a:25 - │ ├── d:34 > 0 - │ ├── uniq_partial_overlaps_pk.d:28 > 0 - │ └── b:32 != uniq_partial_overlaps_pk.b:26 + │ ├── a:35 = uniq_partial_overlaps_pk.a:29 + │ ├── d:38 > 0 + │ ├── uniq_partial_overlaps_pk.d:32 > 0 + │ └── b:36 != uniq_partial_overlaps_pk.b:30 └── unique-checks-item: uniq_partial_overlaps_pk(b,c) └── project - ├── columns: b:42 c:43 + ├── columns: b:46 c:47 └── semi-join (hash) - ├── columns: a:41 b:42 c:43 d:44 + ├── columns: a:45 b:46 c:47 d:48 ├── with-scan &1 - │ ├── columns: a:41 b:42 c:43 d:44 + │ ├── columns: a:45 b:46 c:47 d:48 │ └── mapping: - │ ├── k:7 => a:41 - │ ├── v:8 => b:42 - │ ├── x:10 => c:43 - │ └── y:11 => d:44 + │ ├── k:15 => a:45 + │ ├── v:16 => b:46 + │ ├── x:17 => c:47 + │ └── y:18 => d:48 ├── scan uniq_partial_overlaps_pk - │ └── columns: uniq_partial_overlaps_pk.a:35!null uniq_partial_overlaps_pk.b:36!null uniq_partial_overlaps_pk.c:37 uniq_partial_overlaps_pk.d:38 + │ └── columns: uniq_partial_overlaps_pk.a:39!null uniq_partial_overlaps_pk.b:40!null uniq_partial_overlaps_pk.c:41 uniq_partial_overlaps_pk.d:42 └── filters - ├── b:42 = uniq_partial_overlaps_pk.b:36 - ├── c:43 = uniq_partial_overlaps_pk.c:37 - ├── d:44 > 0 - ├── uniq_partial_overlaps_pk.d:38 > 0 - └── a:41 != uniq_partial_overlaps_pk.a:35 + ├── b:46 = uniq_partial_overlaps_pk.b:40 + ├── c:47 = uniq_partial_overlaps_pk.c:41 + ├── d:48 > 0 + ├── uniq_partial_overlaps_pk.d:42 > 0 + └── a:45 != uniq_partial_overlaps_pk.a:39 exec-ddl CREATE TABLE uniq_partial_hidden_pk ( @@ -1213,40 +1565,47 @@ INSERT INTO uniq_partial_hidden_pk VALUES (1, 1), (2, 2) insert uniq_partial_hidden_pk ├── columns: ├── insert-mapping: - │ ├── column1:7 => uniq_partial_hidden_pk.a:1 - │ ├── column2:8 => uniq_partial_hidden_pk.b:2 - │ ├── c_default:9 => uniq_partial_hidden_pk.c:3 - │ └── rowid_default:10 => uniq_partial_hidden_pk.rowid:4 + │ ├── column1:9 => uniq_partial_hidden_pk.a:1 + │ ├── column2:10 => uniq_partial_hidden_pk.b:2 + │ ├── c_default:11 => uniq_partial_hidden_pk.c:3 + │ └── rowid_default:12 => uniq_partial_hidden_pk.rowid:4 ├── input binding: &1 ├── project - │ ├── columns: c_default:9 rowid_default:10 column1:7!null column2:8!null - │ ├── values - │ │ ├── columns: column1:7!null column2:8!null - │ │ ├── (1, 1) - │ │ └── (2, 2) + │ ├── columns: c_default:11 rowid_default:12 column1:9!null column2:10!null + │ ├── project + │ │ ├── columns: column1:9!null column2:10!null + │ │ ├── values + │ │ │ ├── columns: column1:7!null column2:8!null + │ │ │ ├── (1, 1) + │ │ │ └── (2, 2) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:9] + │ │ │ └── column1:7 + │ │ └── assignment-cast: INT8 [as=column2:10] + │ │ └── column2:8 │ └── projections - │ ├── NULL::INT8 [as=c_default:9] - │ └── unique_rowid() [as=rowid_default:10] + │ ├── NULL::INT8 [as=c_default:11] + │ └── unique_rowid() [as=rowid_default:12] └── unique-checks └── unique-checks-item: uniq_partial_hidden_pk(b) └── project - ├── columns: b:18!null + ├── columns: b:20!null └── semi-join (hash) - ├── columns: a:17!null b:18!null c:19 rowid:20 + ├── columns: a:19!null b:20!null c:21 rowid:22 ├── with-scan &1 - │ ├── columns: a:17!null b:18!null c:19 rowid:20 + │ ├── columns: a:19!null b:20!null c:21 rowid:22 │ └── mapping: - │ ├── column1:7 => a:17 - │ ├── column2:8 => b:18 - │ ├── c_default:9 => c:19 - │ └── rowid_default:10 => rowid:20 + │ ├── column1:9 => a:19 + │ ├── column2:10 => b:20 + │ ├── c_default:11 => c:21 + │ └── rowid_default:12 => rowid:22 ├── scan uniq_partial_hidden_pk - │ └── columns: uniq_partial_hidden_pk.a:11 uniq_partial_hidden_pk.b:12 uniq_partial_hidden_pk.c:13 uniq_partial_hidden_pk.rowid:14!null + │ └── columns: uniq_partial_hidden_pk.a:13 uniq_partial_hidden_pk.b:14 uniq_partial_hidden_pk.c:15 uniq_partial_hidden_pk.rowid:16!null └── filters - ├── b:18 = uniq_partial_hidden_pk.b:12 - ├── c:19 > 0 - ├── uniq_partial_hidden_pk.c:13 > 0 - └── rowid:20 != uniq_partial_hidden_pk.rowid:14 + ├── b:20 = uniq_partial_hidden_pk.b:14 + ├── c:21 > 0 + ├── uniq_partial_hidden_pk.c:15 > 0 + └── rowid:22 != uniq_partial_hidden_pk.rowid:16 # Add inequality filters for the hidden primary key column. build @@ -1255,40 +1614,47 @@ INSERT INTO uniq_partial_hidden_pk SELECT k, v FROM other insert uniq_partial_hidden_pk ├── columns: ├── insert-mapping: - │ ├── k:7 => uniq_partial_hidden_pk.a:1 - │ ├── v:8 => uniq_partial_hidden_pk.b:2 - │ ├── c_default:15 => uniq_partial_hidden_pk.c:3 - │ └── rowid_default:16 => uniq_partial_hidden_pk.rowid:4 + │ ├── k:15 => uniq_partial_hidden_pk.a:1 + │ ├── v:16 => uniq_partial_hidden_pk.b:2 + │ ├── c_default:17 => uniq_partial_hidden_pk.c:3 + │ └── rowid_default:18 => uniq_partial_hidden_pk.rowid:4 ├── input binding: &1 ├── project - │ ├── columns: c_default:15 rowid_default:16 k:7 v:8 + │ ├── columns: c_default:17 rowid_default:18 k:15 v:16 │ ├── project - │ │ ├── columns: k:7 v:8 - │ │ └── scan other - │ │ └── columns: k:7 v:8 w:9!null x:10 y:11 other.rowid:12!null other.crdb_internal_mvcc_timestamp:13 other.tableoid:14 + │ │ ├── columns: k:15 v:16 + │ │ ├── project + │ │ │ ├── columns: other.k:7 other.v:8 + │ │ │ └── scan other + │ │ │ └── columns: other.k:7 other.v:8 w:9!null x:10 y:11 other.rowid:12!null other.crdb_internal_mvcc_timestamp:13 other.tableoid:14 + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=k:15] + │ │ │ └── other.k:7 + │ │ └── assignment-cast: INT8 [as=v:16] + │ │ └── other.v:8 │ └── projections - │ ├── NULL::INT8 [as=c_default:15] - │ └── unique_rowid() [as=rowid_default:16] + │ ├── NULL::INT8 [as=c_default:17] + │ └── unique_rowid() [as=rowid_default:18] └── unique-checks └── unique-checks-item: uniq_partial_hidden_pk(b) └── project - ├── columns: b:24 + ├── columns: b:26 └── semi-join (hash) - ├── columns: a:23 b:24 c:25 rowid:26 + ├── columns: a:25 b:26 c:27 rowid:28 ├── with-scan &1 - │ ├── columns: a:23 b:24 c:25 rowid:26 + │ ├── columns: a:25 b:26 c:27 rowid:28 │ └── mapping: - │ ├── k:7 => a:23 - │ ├── v:8 => b:24 - │ ├── c_default:15 => c:25 - │ └── rowid_default:16 => rowid:26 + │ ├── k:15 => a:25 + │ ├── v:16 => b:26 + │ ├── c_default:17 => c:27 + │ └── rowid_default:18 => rowid:28 ├── scan uniq_partial_hidden_pk - │ └── columns: uniq_partial_hidden_pk.a:17 uniq_partial_hidden_pk.b:18 uniq_partial_hidden_pk.c:19 uniq_partial_hidden_pk.rowid:20!null + │ └── columns: uniq_partial_hidden_pk.a:19 uniq_partial_hidden_pk.b:20 uniq_partial_hidden_pk.c:21 uniq_partial_hidden_pk.rowid:22!null └── filters - ├── b:24 = uniq_partial_hidden_pk.b:18 - ├── c:25 > 0 - ├── uniq_partial_hidden_pk.c:19 > 0 - └── rowid:26 != uniq_partial_hidden_pk.rowid:20 + ├── b:26 = uniq_partial_hidden_pk.b:20 + ├── c:27 > 0 + ├── uniq_partial_hidden_pk.c:21 > 0 + └── rowid:28 != uniq_partial_hidden_pk.rowid:22 exec-ddl CREATE TABLE uniq_partial_constraint_and_index ( @@ -1311,56 +1677,73 @@ insert uniq_partial_constraint_and_index ├── columns: ├── arbiter indexes: uniq_partial_constraint_and_index_a_key ├── insert-mapping: - │ ├── column1:6 => uniq_partial_constraint_and_index.k:1 - │ ├── column2:7 => uniq_partial_constraint_and_index.a:2 - │ └── column3:8 => uniq_partial_constraint_and_index.b:3 - ├── partial index put columns: partial_index_put1:15 + │ ├── column1:9 => uniq_partial_constraint_and_index.k:1 + │ ├── column2:10 => uniq_partial_constraint_and_index.a:2 + │ └── column3:11 => uniq_partial_constraint_and_index.b:3 + ├── partial index put columns: partial_index_put1:18 ├── input binding: &1 ├── project - │ ├── columns: partial_index_put1:15!null column1:6!null column2:7!null column3:8!null - │ ├── anti-join (cross) - │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ ├── values - │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ └── (1, 1, 1) - │ │ ├── select - │ │ │ ├── columns: uniq_partial_constraint_and_index.a:10!null - │ │ │ ├── scan uniq_partial_constraint_and_index - │ │ │ │ ├── columns: uniq_partial_constraint_and_index.a:10 - │ │ │ │ └── partial index predicates - │ │ │ │ └── uniq_partial_constraint_and_index_a_key: filters (true) - │ │ │ └── filters - │ │ │ └── uniq_partial_constraint_and_index.a:10 = 1 - │ │ └── filters (true) + │ ├── columns: partial_index_put1:18!null column1:9 column2:10 column3:11 + │ ├── upsert-distinct-on + │ │ ├── columns: column1:9 column2:10 column3:11 arbiter_uniq_partial_constraint_and_index_a_key_distinct:17!null + │ │ ├── grouping columns: column2:10 + │ │ ├── project + │ │ │ ├── columns: arbiter_uniq_partial_constraint_and_index_a_key_distinct:17!null column1:9 column2:10 column3:11 + │ │ │ ├── anti-join (hash) + │ │ │ │ ├── columns: column1:9 column2:10 column3:11 + │ │ │ │ ├── values + │ │ │ │ │ ├── columns: column1:9 column2:10 column3:11 + │ │ │ │ │ └── tuple + │ │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ │ └── 1 + │ │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ │ └── 1 + │ │ │ │ │ └── assignment-cast: INT8 + │ │ │ │ │ └── 1 + │ │ │ │ ├── scan uniq_partial_constraint_and_index + │ │ │ │ │ ├── columns: uniq_partial_constraint_and_index.a:13 + │ │ │ │ │ └── partial index predicates + │ │ │ │ │ └── uniq_partial_constraint_and_index_a_key: filters (true) + │ │ │ │ └── filters + │ │ │ │ └── column2:10 = uniq_partial_constraint_and_index.a:13 + │ │ │ └── projections + │ │ │ └── true [as=arbiter_uniq_partial_constraint_and_index_a_key_distinct:17] + │ │ └── aggregations + │ │ ├── first-agg [as=column1:9] + │ │ │ └── column1:9 + │ │ ├── first-agg [as=column3:11] + │ │ │ └── column3:11 + │ │ └── const-agg [as=arbiter_uniq_partial_constraint_and_index_a_key_distinct:17] + │ │ └── arbiter_uniq_partial_constraint_and_index_a_key_distinct:17 │ └── projections - │ └── true [as=partial_index_put1:15] + │ └── true [as=partial_index_put1:18] └── unique-checks └── unique-checks-item: uniq_partial_constraint_and_index(a) └── project - ├── columns: a:22!null + ├── columns: a:25 └── semi-join (hash) - ├── columns: k:21!null a:22!null b:23!null + ├── columns: k:24 a:25 b:26!null ├── select - │ ├── columns: k:21!null a:22!null b:23!null + │ ├── columns: k:24 a:25 b:26!null │ ├── with-scan &1 - │ │ ├── columns: k:21!null a:22!null b:23!null + │ │ ├── columns: k:24 a:25 b:26 │ │ └── mapping: - │ │ ├── column1:6 => k:21 - │ │ ├── column2:7 => a:22 - │ │ └── column3:8 => b:23 + │ │ ├── column1:9 => k:24 + │ │ ├── column2:10 => a:25 + │ │ └── column3:11 => b:26 │ └── filters - │ └── b:23 > 10 + │ └── b:26 > 10 ├── select - │ ├── columns: uniq_partial_constraint_and_index.k:16!null uniq_partial_constraint_and_index.a:17 uniq_partial_constraint_and_index.b:18!null + │ ├── columns: uniq_partial_constraint_and_index.k:19!null uniq_partial_constraint_and_index.a:20 uniq_partial_constraint_and_index.b:21!null │ ├── scan uniq_partial_constraint_and_index - │ │ ├── columns: uniq_partial_constraint_and_index.k:16!null uniq_partial_constraint_and_index.a:17 uniq_partial_constraint_and_index.b:18 + │ │ ├── columns: uniq_partial_constraint_and_index.k:19!null uniq_partial_constraint_and_index.a:20 uniq_partial_constraint_and_index.b:21 │ │ └── partial index predicates │ │ └── uniq_partial_constraint_and_index_a_key: filters (true) │ └── filters - │ └── uniq_partial_constraint_and_index.b:18 > 10 + │ └── uniq_partial_constraint_and_index.b:21 > 10 └── filters - ├── a:22 = uniq_partial_constraint_and_index.a:17 - └── k:21 != uniq_partial_constraint_and_index.k:16 + ├── a:25 = uniq_partial_constraint_and_index.a:20 + └── k:24 != uniq_partial_constraint_and_index.k:19 exec-ddl CREATE TABLE uniq_constraint_and_partial_index ( @@ -1383,29 +1766,46 @@ insert uniq_constraint_and_partial_index ├── columns: ├── arbiter constraints: unique_a ├── insert-mapping: - │ ├── column1:6 => k:1 - │ ├── column2:7 => a:2 - │ └── column3:8 => b:3 - ├── partial index put columns: partial_index_put1:15 + │ ├── column1:9 => k:1 + │ ├── column2:10 => a:2 + │ └── column3:11 => b:3 + ├── partial index put columns: partial_index_put1:18 └── project - ├── columns: partial_index_put1:15!null column1:6!null column2:7!null column3:8!null - ├── anti-join (cross) - │ ├── columns: column1:6!null column2:7!null column3:8!null - │ ├── values - │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ └── (1, 1, 1) - │ ├── select - │ │ ├── columns: a:10!null - │ │ ├── scan uniq_constraint_and_partial_index - │ │ │ ├── columns: a:10 - │ │ │ └── partial index predicates - │ │ │ └── uniq_constraint_and_partial_index_a_key: filters - │ │ │ └── b:11 > 0 - │ │ └── filters - │ │ └── a:10 = 1 - │ └── filters (true) + ├── columns: partial_index_put1:18 column1:9 column2:10 column3:11 + ├── upsert-distinct-on + │ ├── columns: column1:9 column2:10 column3:11 arbiter_unique_a_distinct:17!null + │ ├── grouping columns: column2:10 + │ ├── project + │ │ ├── columns: arbiter_unique_a_distinct:17!null column1:9 column2:10 column3:11 + │ │ ├── anti-join (hash) + │ │ │ ├── columns: column1:9 column2:10 column3:11 + │ │ │ ├── values + │ │ │ │ ├── columns: column1:9 column2:10 column3:11 + │ │ │ │ └── tuple + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 1 + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 1 + │ │ │ │ └── assignment-cast: INT8 + │ │ │ │ └── 1 + │ │ │ ├── scan uniq_constraint_and_partial_index + │ │ │ │ ├── columns: a:13 + │ │ │ │ └── partial index predicates + │ │ │ │ └── uniq_constraint_and_partial_index_a_key: filters + │ │ │ │ └── b:14 > 0 + │ │ │ └── filters + │ │ │ └── column2:10 = a:13 + │ │ └── projections + │ │ └── true [as=arbiter_unique_a_distinct:17] + │ └── aggregations + │ ├── first-agg [as=column1:9] + │ │ └── column1:9 + │ ├── first-agg [as=column3:11] + │ │ └── column3:11 + │ └── const-agg [as=arbiter_unique_a_distinct:17] + │ └── arbiter_unique_a_distinct:17 └── projections - └── column3:8 > 0 [as=partial_index_put1:15] + └── column3:11 > 0 [as=partial_index_put1:18] exec-ddl CREATE TABLE uniq_partial_constraint_and_partial_index ( @@ -1428,73 +1828,82 @@ insert uniq_partial_constraint_and_partial_index ├── arbiter indexes: uniq_partial_constraint_and_partial_index_a_key ├── arbiter constraints: unique_a ├── insert-mapping: - │ ├── column1:6 => k:1 - │ ├── column2:7 => a:2 - │ └── column3:8 => b:3 - ├── partial index put columns: partial_index_put1:21 + │ ├── column1:9 => k:1 + │ ├── column2:10 => a:2 + │ └── column3:11 => b:3 + ├── partial index put columns: partial_index_put1:24 └── project - ├── columns: partial_index_put1:21!null column1:6!null column2:7!null column3:8!null + ├── columns: partial_index_put1:24!null column1:9!null column2:10!null column3:11!null ├── project - │ ├── columns: column1:6!null column2:7!null column3:8!null + │ ├── columns: column1:9!null column2:10!null column3:11!null │ └── upsert-distinct-on - │ ├── columns: column1:6!null column2:7!null column3:8!null arbiter_unique_a_distinct:20 - │ ├── grouping columns: column2:7!null arbiter_unique_a_distinct:20 + │ ├── columns: column1:9!null column2:10!null column3:11!null arbiter_unique_a_distinct:23 + │ ├── grouping columns: column2:10!null arbiter_unique_a_distinct:23 │ ├── project - │ │ ├── columns: arbiter_unique_a_distinct:20 column1:6!null column2:7!null column3:8!null + │ │ ├── columns: arbiter_unique_a_distinct:23 column1:9!null column2:10!null column3:11!null │ │ ├── project - │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null │ │ │ └── upsert-distinct-on - │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null arbiter_uniq_partial_constraint_and_partial_index_a_key_distinct:19 - │ │ │ ├── grouping columns: column2:7!null arbiter_uniq_partial_constraint_and_partial_index_a_key_distinct:19 + │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null arbiter_uniq_partial_constraint_and_partial_index_a_key_distinct:22 + │ │ │ ├── grouping columns: column2:10!null arbiter_uniq_partial_constraint_and_partial_index_a_key_distinct:22 │ │ │ ├── project - │ │ │ │ ├── columns: arbiter_uniq_partial_constraint_and_partial_index_a_key_distinct:19 column1:6!null column2:7!null column3:8!null + │ │ │ │ ├── columns: arbiter_uniq_partial_constraint_and_partial_index_a_key_distinct:22 column1:9!null column2:10!null column3:11!null │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null │ │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ │ │ ├── values - │ │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ │ │ │ └── (1, 1, 1) + │ │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ │ │ ├── project + │ │ │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ │ │ │ ├── values + │ │ │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ │ │ │ │ └── (1, 1, 1) + │ │ │ │ │ │ │ └── projections + │ │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column1:9] + │ │ │ │ │ │ │ │ └── column1:6 + │ │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column2:10] + │ │ │ │ │ │ │ │ └── column2:7 + │ │ │ │ │ │ │ └── assignment-cast: INT8 [as=column3:11] + │ │ │ │ │ │ │ └── column3:8 │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ ├── columns: k:9!null a:10 b:11!null + │ │ │ │ │ │ │ ├── columns: k:12!null a:13 b:14!null │ │ │ │ │ │ │ ├── scan uniq_partial_constraint_and_partial_index - │ │ │ │ │ │ │ │ ├── columns: k:9!null a:10 b:11 + │ │ │ │ │ │ │ │ ├── columns: k:12!null a:13 b:14 │ │ │ │ │ │ │ │ └── partial index predicates │ │ │ │ │ │ │ │ └── uniq_partial_constraint_and_partial_index_a_key: filters - │ │ │ │ │ │ │ │ └── b:11 > 0 + │ │ │ │ │ │ │ │ └── b:14 > 0 │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ └── b:11 > 0 + │ │ │ │ │ │ │ └── b:14 > 0 │ │ │ │ │ │ └── filters - │ │ │ │ │ │ ├── column2:7 = a:10 - │ │ │ │ │ │ └── column3:8 > 0 + │ │ │ │ │ │ ├── column2:10 = a:13 + │ │ │ │ │ │ └── column3:11 > 0 │ │ │ │ │ ├── select - │ │ │ │ │ │ ├── columns: k:14!null a:15 b:16!null + │ │ │ │ │ │ ├── columns: k:17!null a:18 b:19!null │ │ │ │ │ │ ├── scan uniq_partial_constraint_and_partial_index - │ │ │ │ │ │ │ ├── columns: k:14!null a:15 b:16 + │ │ │ │ │ │ │ ├── columns: k:17!null a:18 b:19 │ │ │ │ │ │ │ └── partial index predicates │ │ │ │ │ │ │ └── uniq_partial_constraint_and_partial_index_a_key: filters - │ │ │ │ │ │ │ └── b:16 > 0 + │ │ │ │ │ │ │ └── b:19 > 0 │ │ │ │ │ │ └── filters - │ │ │ │ │ │ └── b:16 > 10 + │ │ │ │ │ │ └── b:19 > 10 │ │ │ │ │ └── filters - │ │ │ │ │ ├── column2:7 = a:15 - │ │ │ │ │ └── column3:8 > 10 + │ │ │ │ │ ├── column2:10 = a:18 + │ │ │ │ │ └── column3:11 > 10 │ │ │ │ └── projections - │ │ │ │ └── (column3:8 > 0) OR NULL::BOOL [as=arbiter_uniq_partial_constraint_and_partial_index_a_key_distinct:19] + │ │ │ │ └── (column3:11 > 0) OR NULL::BOOL [as=arbiter_uniq_partial_constraint_and_partial_index_a_key_distinct:22] │ │ │ └── aggregations - │ │ │ ├── first-agg [as=column1:6] - │ │ │ │ └── column1:6 - │ │ │ └── first-agg [as=column3:8] - │ │ │ └── column3:8 + │ │ │ ├── first-agg [as=column1:9] + │ │ │ │ └── column1:9 + │ │ │ └── first-agg [as=column3:11] + │ │ │ └── column3:11 │ │ └── projections - │ │ └── (column3:8 > 10) OR NULL::BOOL [as=arbiter_unique_a_distinct:20] + │ │ └── (column3:11 > 10) OR NULL::BOOL [as=arbiter_unique_a_distinct:23] │ └── aggregations - │ ├── first-agg [as=column1:6] - │ │ └── column1:6 - │ └── first-agg [as=column3:8] - │ └── column3:8 + │ ├── first-agg [as=column1:9] + │ │ └── column1:9 + │ └── first-agg [as=column3:11] + │ └── column3:11 └── projections - └── column3:8 > 0 [as=partial_index_put1:21] + └── column3:11 > 0 [as=partial_index_put1:24] exec-ddl CREATE TABLE uniq_computed_pk ( @@ -1523,54 +1932,63 @@ INSERT INTO uniq_computed_pk (i, s, d) VALUES (1, 'a', 1.0), (2, 'b', 2.0) insert uniq_computed_pk ├── columns: ├── insert-mapping: - │ ├── column1:10 => uniq_computed_pk.i:1 - │ ├── column2:11 => uniq_computed_pk.s:2 - │ ├── column3:12 => uniq_computed_pk.d:3 - │ ├── c_i_expr_comp:13 => uniq_computed_pk.c_i_expr:4 - │ ├── column2:11 => uniq_computed_pk.c_s:5 - │ ├── column3:12 => uniq_computed_pk.c_d:6 - │ └── c_d_expr_comp:14 => uniq_computed_pk.c_d_expr:7 + │ ├── column1:13 => uniq_computed_pk.i:1 + │ ├── column2:14 => uniq_computed_pk.s:2 + │ ├── column3:15 => uniq_computed_pk.d:3 + │ ├── c_i_expr_comp:16 => uniq_computed_pk.c_i_expr:4 + │ ├── column2:14 => uniq_computed_pk.c_s:5 + │ ├── column3:15 => uniq_computed_pk.c_d:6 + │ └── c_d_expr_comp:17 => uniq_computed_pk.c_d_expr:7 ├── input binding: &1 ├── project - │ ├── columns: c_i_expr_comp:13!null c_d_expr_comp:14!null column1:10!null column2:11!null column3:12!null - │ ├── values - │ │ ├── columns: column1:10!null column2:11!null column3:12!null - │ │ ├── (1, 'a', 1.0) - │ │ └── (2, 'b', 2.0) + │ ├── columns: c_i_expr_comp:16!null c_d_expr_comp:17!null column1:13!null column2:14!null column3:15!null + │ ├── project + │ │ ├── columns: column1:13!null column2:14!null column3:15!null + │ │ ├── values + │ │ │ ├── columns: column1:10!null column2:11!null column3:12!null + │ │ │ ├── (1, 'a', 1.0) + │ │ │ └── (2, 'b', 2.0) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:13] + │ │ │ └── column1:10 + │ │ ├── assignment-cast: STRING [as=column2:14] + │ │ │ └── column2:11 + │ │ └── assignment-cast: DECIMAL [as=column3:15] + │ │ └── column3:12 │ └── projections - │ ├── CASE WHEN column1:10 < 0 THEN 'foo' ELSE 'bar' END [as=c_i_expr_comp:13] - │ └── column3:12::STRING [as=c_d_expr_comp:14] + │ ├── CASE WHEN column1:13 < 0 THEN 'foo' ELSE 'bar' END [as=c_i_expr_comp:16] + │ └── column3:15::STRING [as=c_d_expr_comp:17] └── unique-checks └── unique-checks-item: uniq_computed_pk(d) └── project - ├── columns: d:44!null + ├── columns: d:47!null └── semi-join (hash) - ├── columns: i:42!null s:43!null d:44!null c_i_expr:45!null c_s:46!null c_d:47!null c_d_expr:48!null + ├── columns: i:45!null s:46!null d:47!null c_i_expr:48!null c_s:49!null c_d:50!null c_d_expr:51!null ├── with-scan &1 - │ ├── columns: i:42!null s:43!null d:44!null c_i_expr:45!null c_s:46!null c_d:47!null c_d_expr:48!null + │ ├── columns: i:45!null s:46!null d:47!null c_i_expr:48!null c_s:49!null c_d:50!null c_d_expr:51!null │ └── mapping: - │ ├── column1:10 => i:42 - │ ├── column2:11 => s:43 - │ ├── column3:12 => d:44 - │ ├── c_i_expr_comp:13 => c_i_expr:45 - │ ├── column2:11 => c_s:46 - │ ├── column3:12 => c_d:47 - │ └── c_d_expr_comp:14 => c_d_expr:48 + │ ├── column1:13 => i:45 + │ ├── column2:14 => s:46 + │ ├── column3:15 => d:47 + │ ├── c_i_expr_comp:16 => c_i_expr:48 + │ ├── column2:14 => c_s:49 + │ ├── column3:15 => c_d:50 + │ └── c_d_expr_comp:17 => c_d_expr:51 ├── project - │ ├── columns: uniq_computed_pk.c_s:37 uniq_computed_pk.i:33!null uniq_computed_pk.s:34 uniq_computed_pk.d:35 uniq_computed_pk.c_i_expr:36!null uniq_computed_pk.c_d:38 uniq_computed_pk.c_d_expr:39 + │ ├── columns: uniq_computed_pk.c_s:40 uniq_computed_pk.i:36!null uniq_computed_pk.s:37 uniq_computed_pk.d:38 uniq_computed_pk.c_i_expr:39!null uniq_computed_pk.c_d:41 uniq_computed_pk.c_d_expr:42 │ ├── scan uniq_computed_pk - │ │ ├── columns: uniq_computed_pk.i:33!null uniq_computed_pk.s:34 uniq_computed_pk.d:35 uniq_computed_pk.c_i_expr:36!null uniq_computed_pk.c_d:38 uniq_computed_pk.c_d_expr:39 + │ │ ├── columns: uniq_computed_pk.i:36!null uniq_computed_pk.s:37 uniq_computed_pk.d:38 uniq_computed_pk.c_i_expr:39!null uniq_computed_pk.c_d:41 uniq_computed_pk.c_d_expr:42 │ │ └── computed column expressions - │ │ ├── uniq_computed_pk.c_i_expr:36 - │ │ │ └── CASE WHEN uniq_computed_pk.i:33 < 0 THEN 'foo' ELSE 'bar' END - │ │ ├── uniq_computed_pk.c_s:37 - │ │ │ └── uniq_computed_pk.s:34 - │ │ ├── uniq_computed_pk.c_d:38 - │ │ │ └── uniq_computed_pk.d:35 - │ │ └── uniq_computed_pk.c_d_expr:39 - │ │ └── uniq_computed_pk.d:35::STRING + │ │ ├── uniq_computed_pk.c_i_expr:39 + │ │ │ └── CASE WHEN uniq_computed_pk.i:36 < 0 THEN 'foo' ELSE 'bar' END + │ │ ├── uniq_computed_pk.c_s:40 + │ │ │ └── uniq_computed_pk.s:37 + │ │ ├── uniq_computed_pk.c_d:41 + │ │ │ └── uniq_computed_pk.d:38 + │ │ └── uniq_computed_pk.c_d_expr:42 + │ │ └── uniq_computed_pk.d:38::STRING │ └── projections - │ └── uniq_computed_pk.s:34 [as=uniq_computed_pk.c_s:37] + │ └── uniq_computed_pk.s:37 [as=uniq_computed_pk.c_s:40] └── filters - ├── d:44 = uniq_computed_pk.d:35 - └── (i:42 != uniq_computed_pk.i:33) OR (c_i_expr:45 != uniq_computed_pk.c_i_expr:36) + ├── d:47 = uniq_computed_pk.d:38 + └── (i:45 != uniq_computed_pk.i:36) OR (c_i_expr:48 != uniq_computed_pk.c_i_expr:39) diff --git a/pkg/sql/opt/optbuilder/testdata/upsert b/pkg/sql/opt/optbuilder/testdata/upsert index 114a1d94af2c..9d5141fce1d6 100644 --- a/pkg/sql/opt/optbuilder/testdata/upsert +++ b/pkg/sql/opt/optbuilder/testdata/upsert @@ -558,53 +558,62 @@ insert xyz ├── columns: ├── arbiter indexes: xyz_pkey xyz_y_z_key xyz_z_y_key ├── insert-mapping: - │ ├── column1:6 => x:1 - │ ├── column2:7 => y:2 - │ └── column3:8 => z:3 + │ ├── column1:9 => x:1 + │ ├── column2:10 => y:2 + │ └── column3:11 => z:3 └── upsert-distinct-on - ├── columns: column1:6!null column2:7!null column3:8!null - ├── grouping columns: column2:7!null column3:8!null + ├── columns: column1:9!null column2:10!null column3:11!null + ├── grouping columns: column2:10!null column3:11!null ├── upsert-distinct-on - │ ├── columns: column1:6!null column2:7!null column3:8!null - │ ├── grouping columns: column2:7!null column3:8!null + │ ├── columns: column1:9!null column2:10!null column3:11!null + │ ├── grouping columns: column2:10!null column3:11!null │ ├── upsert-distinct-on - │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ ├── grouping columns: column1:6!null + │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ ├── grouping columns: column1:9!null │ │ ├── anti-join (hash) - │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null │ │ │ ├── anti-join (hash) - │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ │ ├── values - │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ │ │ ├── (1, 2, 3) - │ │ │ │ │ │ └── (4, 5, 6) + │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ │ ├── project + │ │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ │ │ ├── values + │ │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ │ │ │ ├── (1, 2, 3) + │ │ │ │ │ │ │ └── (4, 5, 6) + │ │ │ │ │ │ └── projections + │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column1:9] + │ │ │ │ │ │ │ └── column1:6 + │ │ │ │ │ │ ├── assignment-cast: INT8 [as=column2:10] + │ │ │ │ │ │ │ └── column2:7 + │ │ │ │ │ │ └── assignment-cast: INT8 [as=column3:11] + │ │ │ │ │ │ └── column3:8 │ │ │ │ │ ├── scan xyz - │ │ │ │ │ │ └── columns: x:9!null y:10 z:11 + │ │ │ │ │ │ └── columns: x:12!null y:13 z:14 │ │ │ │ │ └── filters - │ │ │ │ │ └── column1:6 = x:9 + │ │ │ │ │ └── column1:9 = x:12 │ │ │ │ ├── scan xyz - │ │ │ │ │ └── columns: x:14!null y:15 z:16 + │ │ │ │ │ └── columns: x:17!null y:18 z:19 │ │ │ │ └── filters - │ │ │ │ ├── column2:7 = y:15 - │ │ │ │ └── column3:8 = z:16 + │ │ │ │ ├── column2:10 = y:18 + │ │ │ │ └── column3:11 = z:19 │ │ │ ├── scan xyz - │ │ │ │ └── columns: x:19!null y:20 z:21 + │ │ │ │ └── columns: x:22!null y:23 z:24 │ │ │ └── filters - │ │ │ ├── column2:7 = y:20 - │ │ │ └── column3:8 = z:21 + │ │ │ ├── column2:10 = y:23 + │ │ │ └── column3:11 = z:24 │ │ └── aggregations - │ │ ├── first-agg [as=column2:7] - │ │ │ └── column2:7 - │ │ └── first-agg [as=column3:8] - │ │ └── column3:8 + │ │ ├── first-agg [as=column2:10] + │ │ │ └── column2:10 + │ │ └── first-agg [as=column3:11] + │ │ └── column3:11 │ └── aggregations - │ └── first-agg [as=column1:6] - │ └── column1:6 + │ └── first-agg [as=column1:9] + │ └── column1:9 └── aggregations - └── first-agg [as=column1:6] - └── column1:6 + └── first-agg [as=column1:9] + └── column1:9 # Conflict columns are explicitly specified. build @@ -616,26 +625,35 @@ insert xyz ├── columns: ├── arbiter indexes: xyz_y_z_key ├── insert-mapping: - │ ├── column1:6 => x:1 - │ ├── column2:7 => y:2 - │ └── column3:8 => z:3 + │ ├── column1:9 => x:1 + │ ├── column2:10 => y:2 + │ └── column3:11 => z:3 └── upsert-distinct-on - ├── columns: column1:6!null column2:7!null column3:8!null - ├── grouping columns: column2:7!null column3:8!null + ├── columns: column1:9!null column2:10!null column3:11!null + ├── grouping columns: column2:10!null column3:11!null ├── anti-join (hash) - │ ├── columns: column1:6!null column2:7!null column3:8!null - │ ├── values - │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ ├── (1, 2, 3) - │ │ └── (4, 5, 6) + │ ├── columns: column1:9!null column2:10!null column3:11!null + │ ├── project + │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ ├── values + │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ ├── (1, 2, 3) + │ │ │ └── (4, 5, 6) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:9] + │ │ │ └── column1:6 + │ │ ├── assignment-cast: INT8 [as=column2:10] + │ │ │ └── column2:7 + │ │ └── assignment-cast: INT8 [as=column3:11] + │ │ └── column3:8 │ ├── scan xyz - │ │ └── columns: x:9!null y:10 z:11 + │ │ └── columns: x:12!null y:13 z:14 │ └── filters - │ ├── column2:7 = y:10 - │ └── column3:8 = z:11 + │ ├── column2:10 = y:13 + │ └── column3:11 = z:14 └── aggregations - └── first-agg [as=column1:6] - └── column1:6 + └── first-agg [as=column1:9] + └── column1:9 build INSERT INTO uniq VALUES ('x2', 'y1', 'z2'), ('x2', 'y2', 'z2'), ('x2', 'y2', 'z2') @@ -645,56 +663,65 @@ insert uniq ├── columns: ├── arbiter indexes: uniq_pkey uniq_y_key uniq_z_key ├── insert-mapping: - │ ├── column1:6 => x:1 - │ ├── column2:7 => y:2 - │ └── column3:8 => z:3 + │ ├── column1:9 => x:1 + │ ├── column2:10 => y:2 + │ └── column3:11 => z:3 └── upsert-distinct-on - ├── columns: column1:6!null column2:7!null column3:8!null - ├── grouping columns: column3:8!null + ├── columns: column1:9!null column2:10!null column3:11!null + ├── grouping columns: column3:11!null ├── upsert-distinct-on - │ ├── columns: column1:6!null column2:7!null column3:8!null - │ ├── grouping columns: column2:7!null + │ ├── columns: column1:9!null column2:10!null column3:11!null + │ ├── grouping columns: column2:10!null │ ├── upsert-distinct-on - │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ ├── grouping columns: column1:6!null + │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ ├── grouping columns: column1:9!null │ │ ├── anti-join (hash) - │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null │ │ │ ├── anti-join (hash) - │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null │ │ │ │ ├── anti-join (hash) - │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ │ ├── values - │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null - │ │ │ │ │ │ ├── ('x2', 'y1', 'z2') - │ │ │ │ │ │ ├── ('x2', 'y2', 'z2') - │ │ │ │ │ │ └── ('x2', 'y2', 'z2') + │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ │ ├── project + │ │ │ │ │ │ ├── columns: column1:9!null column2:10!null column3:11!null + │ │ │ │ │ │ ├── values + │ │ │ │ │ │ │ ├── columns: column1:6!null column2:7!null column3:8!null + │ │ │ │ │ │ │ ├── ('x2', 'y1', 'z2') + │ │ │ │ │ │ │ ├── ('x2', 'y2', 'z2') + │ │ │ │ │ │ │ └── ('x2', 'y2', 'z2') + │ │ │ │ │ │ └── projections + │ │ │ │ │ │ ├── assignment-cast: STRING [as=column1:9] + │ │ │ │ │ │ │ └── column1:6 + │ │ │ │ │ │ ├── assignment-cast: STRING [as=column2:10] + │ │ │ │ │ │ │ └── column2:7 + │ │ │ │ │ │ └── assignment-cast: STRING [as=column3:11] + │ │ │ │ │ │ └── column3:8 │ │ │ │ │ ├── scan uniq - │ │ │ │ │ │ └── columns: x:9!null y:10 z:11 + │ │ │ │ │ │ └── columns: x:12!null y:13 z:14 │ │ │ │ │ └── filters - │ │ │ │ │ └── column1:6 = x:9 + │ │ │ │ │ └── column1:9 = x:12 │ │ │ │ ├── scan uniq - │ │ │ │ │ └── columns: x:14!null y:15 z:16 + │ │ │ │ │ └── columns: x:17!null y:18 z:19 │ │ │ │ └── filters - │ │ │ │ └── column2:7 = y:15 + │ │ │ │ └── column2:10 = y:18 │ │ │ ├── scan uniq - │ │ │ │ └── columns: x:19!null y:20 z:21 + │ │ │ │ └── columns: x:22!null y:23 z:24 │ │ │ └── filters - │ │ │ └── column3:8 = z:21 + │ │ │ └── column3:11 = z:24 │ │ └── aggregations - │ │ ├── first-agg [as=column2:7] - │ │ │ └── column2:7 - │ │ └── first-agg [as=column3:8] - │ │ └── column3:8 + │ │ ├── first-agg [as=column2:10] + │ │ │ └── column2:10 + │ │ └── first-agg [as=column3:11] + │ │ └── column3:11 │ └── aggregations - │ ├── first-agg [as=column1:6] - │ │ └── column1:6 - │ └── first-agg [as=column3:8] - │ └── column3:8 + │ ├── first-agg [as=column1:9] + │ │ └── column1:9 + │ └── first-agg [as=column3:11] + │ └── column3:11 └── aggregations - ├── first-agg [as=column1:6] - │ └── column1:6 - └── first-agg [as=column2:7] - └── column2:7 + ├── first-agg [as=column1:9] + │ └── column1:9 + └── first-agg [as=column2:10] + └── column2:10 # ------------------------------------------------------------------------------ # Test excluded columns. @@ -1451,48 +1478,55 @@ insert checks ├── columns: ├── arbiter indexes: checks_pkey ├── insert-mapping: - │ ├── column1:7 => a:1 - │ ├── column2:8 => b:2 - │ ├── c_default:9 => c:3 - │ └── d_comp:10 => d:4 - ├── check columns: check1:17 check2:18 + │ ├── column1:9 => a:1 + │ ├── column2:10 => b:2 + │ ├── c_default:11 => c:3 + │ └── d_comp:12 => d:4 + ├── check columns: check1:19 check2:20 └── project - ├── columns: check1:17 check2:18!null column1:7!null column2:8!null c_default:9 d_comp:10 + ├── columns: check1:19 check2:20!null column1:9!null column2:10!null c_default:11 d_comp:12 ├── upsert-distinct-on - │ ├── columns: column1:7!null column2:8!null c_default:9 d_comp:10 - │ ├── grouping columns: column1:7!null + │ ├── columns: column1:9!null column2:10!null c_default:11 d_comp:12 + │ ├── grouping columns: column1:9!null │ ├── anti-join (hash) - │ │ ├── columns: column1:7!null column2:8!null c_default:9 d_comp:10 + │ │ ├── columns: column1:9!null column2:10!null c_default:11 d_comp:12 │ │ ├── project - │ │ │ ├── columns: d_comp:10 column1:7!null column2:8!null c_default:9 + │ │ │ ├── columns: d_comp:12 column1:9!null column2:10!null c_default:11 │ │ │ ├── project - │ │ │ │ ├── columns: c_default:9 column1:7!null column2:8!null - │ │ │ │ ├── values - │ │ │ │ │ ├── columns: column1:7!null column2:8!null - │ │ │ │ │ └── (1, 2) + │ │ │ │ ├── columns: c_default:11 column1:9!null column2:10!null + │ │ │ │ ├── project + │ │ │ │ │ ├── columns: column1:9!null column2:10!null + │ │ │ │ │ ├── values + │ │ │ │ │ │ ├── columns: column1:7!null column2:8!null + │ │ │ │ │ │ └── (1, 2) + │ │ │ │ │ └── projections + │ │ │ │ │ ├── assignment-cast: INT8 [as=column1:9] + │ │ │ │ │ │ └── column1:7 + │ │ │ │ │ └── assignment-cast: INT8 [as=column2:10] + │ │ │ │ │ └── column2:8 │ │ │ │ └── projections - │ │ │ │ └── NULL::INT8 [as=c_default:9] + │ │ │ │ └── NULL::INT8 [as=c_default:11] │ │ │ └── projections - │ │ │ └── c_default:9 + 1 [as=d_comp:10] + │ │ │ └── c_default:11 + 1 [as=d_comp:12] │ │ ├── scan checks - │ │ │ ├── columns: a:11!null b:12 c:13 d:14 + │ │ │ ├── columns: a:13!null b:14 c:15 d:16 │ │ │ ├── check constraint expressions - │ │ │ │ └── a:11 > 0 + │ │ │ │ └── a:13 > 0 │ │ │ └── computed column expressions - │ │ │ └── d:14 - │ │ │ └── c:13 + 1 + │ │ │ └── d:16 + │ │ │ └── c:15 + 1 │ │ └── filters - │ │ └── column1:7 = a:11 + │ │ └── column1:9 = a:13 │ └── aggregations - │ ├── first-agg [as=column2:8] - │ │ └── column2:8 - │ ├── first-agg [as=c_default:9] - │ │ └── c_default:9 - │ └── first-agg [as=d_comp:10] - │ └── d_comp:10 + │ ├── first-agg [as=column2:10] + │ │ └── column2:10 + │ ├── first-agg [as=c_default:11] + │ │ └── c_default:11 + │ └── first-agg [as=d_comp:12] + │ └── d_comp:12 └── projections - ├── column2:8 < d_comp:10 [as=check1:17] - └── column1:7 > 0 [as=check2:18] + ├── column2:10 < d_comp:12 [as=check1:19] + └── column1:9 > 0 [as=check2:20] # UPSERT build diff --git a/pkg/sql/opt/optbuilder/testdata/virtual-columns b/pkg/sql/opt/optbuilder/testdata/virtual-columns index bcef0429f59b..275043a7d8d5 100644 --- a/pkg/sql/opt/optbuilder/testdata/virtual-columns +++ b/pkg/sql/opt/optbuilder/testdata/virtual-columns @@ -95,16 +95,23 @@ INSERT INTO t VALUES (1, 1) insert t ├── columns: ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => b:2 - │ └── v_comp:8 => v:3 + │ ├── column1:8 => a:1 + │ ├── column2:9 => b:2 + │ └── v_comp:10 => v:3 └── project - ├── columns: v_comp:8!null column1:6!null column2:7!null - ├── values - │ ├── columns: column1:6!null column2:7!null - │ └── (1, 1) + ├── columns: v_comp:10!null column1:8!null column2:9!null + ├── project + │ ├── columns: column1:8!null column2:9!null + │ ├── values + │ │ ├── columns: column1:6!null column2:7!null + │ │ └── (1, 1) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:8] + │ │ └── column1:6 + │ └── assignment-cast: INT8 [as=column2:9] + │ └── column2:7 └── projections - └── column1:6 + column2:7 [as=v_comp:8] + └── column1:8 + column2:9 [as=v_comp:10] build INSERT INTO t(a) VALUES (1) @@ -112,20 +119,25 @@ INSERT INTO t(a) VALUES (1) insert t ├── columns: ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── b_default:7 => b:2 - │ └── v_comp:8 => v:3 + │ ├── column1:7 => a:1 + │ ├── b_default:8 => b:2 + │ └── v_comp:9 => v:3 └── project - ├── columns: v_comp:8 column1:6!null b_default:7 + ├── columns: v_comp:9 column1:7!null b_default:8 ├── project - │ ├── columns: b_default:7 column1:6!null - │ ├── values - │ │ ├── columns: column1:6!null - │ │ └── (1,) + │ ├── columns: b_default:8 column1:7!null + │ ├── project + │ │ ├── columns: column1:7!null + │ │ ├── values + │ │ │ ├── columns: column1:6!null + │ │ │ └── (1,) + │ │ └── projections + │ │ └── assignment-cast: INT8 [as=column1:7] + │ │ └── column1:6 │ └── projections - │ └── NULL::INT8 [as=b_default:7] + │ └── NULL::INT8 [as=b_default:8] └── projections - └── column1:6 + b_default:7 [as=v_comp:8] + └── column1:7 + b_default:8 [as=v_comp:9] build INSERT INTO t(a, b, v) VALUES (1, 1, 1) @@ -140,16 +152,23 @@ project └── insert t ├── columns: a:1!null b:2!null v:3!null ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => b:2 - │ └── v_comp:8 => v:3 + │ ├── column1:8 => a:1 + │ ├── column2:9 => b:2 + │ └── v_comp:10 => v:3 └── project - ├── columns: v_comp:8!null column1:6!null column2:7!null - ├── values - │ ├── columns: column1:6!null column2:7!null - │ └── (1, 1) + ├── columns: v_comp:10!null column1:8!null column2:9!null + ├── project + │ ├── columns: column1:8!null column2:9!null + │ ├── values + │ │ ├── columns: column1:6!null column2:7!null + │ │ └── (1, 1) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:8] + │ │ └── column1:6 + │ └── assignment-cast: INT8 [as=column2:9] + │ └── column2:7 └── projections - └── column1:6 + column2:7 [as=v_comp:8] + └── column1:8 + column2:9 [as=v_comp:10] build INSERT INTO t_idx VALUES (1, 1) @@ -157,16 +176,23 @@ INSERT INTO t_idx VALUES (1, 1) insert t_idx ├── columns: ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => b:2 - │ └── v_comp:8 => v:3 + │ ├── column1:8 => a:1 + │ ├── column2:9 => b:2 + │ └── v_comp:10 => v:3 └── project - ├── columns: v_comp:8!null column1:6!null column2:7!null - ├── values - │ ├── columns: column1:6!null column2:7!null - │ └── (1, 1) + ├── columns: v_comp:10!null column1:8!null column2:9!null + ├── project + │ ├── columns: column1:8!null column2:9!null + │ ├── values + │ │ ├── columns: column1:6!null column2:7!null + │ │ └── (1, 1) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:8] + │ │ └── column1:6 + │ └── assignment-cast: INT8 [as=column2:9] + │ └── column2:7 └── projections - └── column1:6 + column2:7 [as=v_comp:8] + └── column1:8 + column2:9 [as=v_comp:10] build INSERT INTO t_check VALUES (1, 1) @@ -174,24 +200,31 @@ INSERT INTO t_check VALUES (1, 1) insert t_check ├── columns: ├── insert-mapping: - │ ├── column1:7 => a:1 - │ ├── column2:8 => b:2 - │ ├── v_comp:9 => v:3 - │ └── w_comp:10 => w:4 - ├── check columns: check1:11 check2:12 + │ ├── column1:9 => a:1 + │ ├── column2:10 => b:2 + │ ├── v_comp:11 => v:3 + │ └── w_comp:12 => w:4 + ├── check columns: check1:13 check2:14 └── project - ├── columns: check1:11!null check2:12!null column1:7!null column2:8!null v_comp:9!null w_comp:10!null + ├── columns: check1:13!null check2:14!null column1:9!null column2:10!null v_comp:11!null w_comp:12!null ├── project - │ ├── columns: v_comp:9!null w_comp:10!null column1:7!null column2:8!null - │ ├── values - │ │ ├── columns: column1:7!null column2:8!null - │ │ └── (1, 1) + │ ├── columns: v_comp:11!null w_comp:12!null column1:9!null column2:10!null + │ ├── project + │ │ ├── columns: column1:9!null column2:10!null + │ │ ├── values + │ │ │ ├── columns: column1:7!null column2:8!null + │ │ │ └── (1, 1) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:9] + │ │ │ └── column1:7 + │ │ └── assignment-cast: INT8 [as=column2:10] + │ │ └── column2:8 │ └── projections - │ ├── column1:7 + column2:8 [as=v_comp:9] - │ └── column1:7 * column2:8 [as=w_comp:10] + │ ├── column1:9 + column2:10 [as=v_comp:11] + │ └── column1:9 * column2:10 [as=w_comp:12] └── projections - ├── v_comp:9 < w_comp:10 [as=check1:11] - └── v_comp:9 >= 10 [as=check2:12] + ├── v_comp:11 < w_comp:12 [as=check1:13] + └── v_comp:11 >= 10 [as=check2:14] # -- DELETE tests -- @@ -822,37 +855,44 @@ project ├── columns: a:1!null b:2!null v:3!null ├── arbiter indexes: t_pkey ├── insert-mapping: - │ ├── column1:6 => a:1 - │ ├── column2:7 => b:2 - │ └── v_comp:8 => v:3 + │ ├── column1:8 => a:1 + │ ├── column2:9 => b:2 + │ └── v_comp:10 => v:3 └── upsert-distinct-on - ├── columns: column1:6!null column2:7!null v_comp:8!null - ├── grouping columns: column1:6!null + ├── columns: column1:8!null column2:9!null v_comp:10!null + ├── grouping columns: column1:8!null ├── anti-join (hash) - │ ├── columns: column1:6!null column2:7!null v_comp:8!null + │ ├── columns: column1:8!null column2:9!null v_comp:10!null │ ├── project - │ │ ├── columns: v_comp:8!null column1:6!null column2:7!null - │ │ ├── values - │ │ │ ├── columns: column1:6!null column2:7!null - │ │ │ └── (1, 1) + │ │ ├── columns: v_comp:10!null column1:8!null column2:9!null + │ │ ├── project + │ │ │ ├── columns: column1:8!null column2:9!null + │ │ │ ├── values + │ │ │ │ ├── columns: column1:6!null column2:7!null + │ │ │ │ └── (1, 1) + │ │ │ └── projections + │ │ │ ├── assignment-cast: INT8 [as=column1:8] + │ │ │ │ └── column1:6 + │ │ │ └── assignment-cast: INT8 [as=column2:9] + │ │ │ └── column2:7 │ │ └── projections - │ │ └── column1:6 + column2:7 [as=v_comp:8] + │ │ └── column1:8 + column2:9 [as=v_comp:10] │ ├── project - │ │ ├── columns: v:11 a:9!null b:10 + │ │ ├── columns: v:13 a:11!null b:12 │ │ ├── scan t - │ │ │ ├── columns: a:9!null b:10 + │ │ │ ├── columns: a:11!null b:12 │ │ │ └── computed column expressions - │ │ │ └── v:11 - │ │ │ └── a:9 + b:10 + │ │ │ └── v:13 + │ │ │ └── a:11 + b:12 │ │ └── projections - │ │ └── a:9 + b:10 [as=v:11] + │ │ └── a:11 + b:12 [as=v:13] │ └── filters - │ └── column1:6 = a:9 + │ └── column1:8 = a:11 └── aggregations - ├── first-agg [as=column2:7] - │ └── column2:7 - └── first-agg [as=v_comp:8] - └── v_comp:8 + ├── first-agg [as=column2:9] + │ └── column2:9 + └── first-agg [as=v_comp:10] + └── v_comp:10 build INSERT INTO t_idx2 VALUES (1, 1, 1) ON CONFLICT (w) DO NOTHING @@ -861,47 +901,56 @@ insert t_idx2 ├── columns: ├── arbiter indexes: t_idx2_w_key ├── insert-mapping: - │ ├── column1:8 => a:1 - │ ├── column2:9 => b:2 - │ ├── column3:10 => c:3 - │ ├── v_comp:11 => v:4 - │ └── w_comp:12 => w:5 + │ ├── column1:11 => a:1 + │ ├── column2:12 => b:2 + │ ├── column3:13 => c:3 + │ ├── v_comp:14 => v:4 + │ └── w_comp:15 => w:5 └── upsert-distinct-on - ├── columns: column1:8!null column2:9!null column3:10!null v_comp:11!null w_comp:12!null - ├── grouping columns: w_comp:12!null + ├── columns: column1:11!null column2:12!null column3:13!null v_comp:14!null w_comp:15!null + ├── grouping columns: w_comp:15!null ├── anti-join (hash) - │ ├── columns: column1:8!null column2:9!null column3:10!null v_comp:11!null w_comp:12!null + │ ├── columns: column1:11!null column2:12!null column3:13!null v_comp:14!null w_comp:15!null │ ├── project - │ │ ├── columns: v_comp:11!null w_comp:12!null column1:8!null column2:9!null column3:10!null - │ │ ├── values - │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null - │ │ │ └── (1, 1, 1) + │ │ ├── columns: v_comp:14!null w_comp:15!null column1:11!null column2:12!null column3:13!null + │ │ ├── project + │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null + │ │ │ ├── values + │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null + │ │ │ │ └── (1, 1, 1) + │ │ │ └── projections + │ │ │ ├── assignment-cast: INT8 [as=column1:11] + │ │ │ │ └── column1:8 + │ │ │ ├── assignment-cast: INT8 [as=column2:12] + │ │ │ │ └── column2:9 + │ │ │ └── assignment-cast: INT8 [as=column3:13] + │ │ │ └── column3:10 │ │ └── projections - │ │ ├── column1:8 + column2:9 [as=v_comp:11] - │ │ └── column3:10 + 1 [as=w_comp:12] + │ │ ├── column1:11 + column2:12 [as=v_comp:14] + │ │ └── column3:13 + 1 [as=w_comp:15] │ ├── project - │ │ ├── columns: v:16 w:17 a:13!null b:14 c:15 + │ │ ├── columns: v:19 w:20 a:16!null b:17 c:18 │ │ ├── scan t_idx2 - │ │ │ ├── columns: a:13!null b:14 c:15 + │ │ │ ├── columns: a:16!null b:17 c:18 │ │ │ └── computed column expressions - │ │ │ ├── v:16 - │ │ │ │ └── a:13 + b:14 - │ │ │ └── w:17 - │ │ │ └── c:15 + 1 + │ │ │ ├── v:19 + │ │ │ │ └── a:16 + b:17 + │ │ │ └── w:20 + │ │ │ └── c:18 + 1 │ │ └── projections - │ │ ├── a:13 + b:14 [as=v:16] - │ │ └── c:15 + 1 [as=w:17] + │ │ ├── a:16 + b:17 [as=v:19] + │ │ └── c:18 + 1 [as=w:20] │ └── filters - │ └── w_comp:12 = w:17 + │ └── w_comp:15 = w:20 └── aggregations - ├── first-agg [as=column1:8] - │ └── column1:8 - ├── first-agg [as=column2:9] - │ └── column2:9 - ├── first-agg [as=column3:10] - │ └── column3:10 - └── first-agg [as=v_comp:11] - └── v_comp:11 + ├── first-agg [as=column1:11] + │ └── column1:11 + ├── first-agg [as=column2:12] + │ └── column2:12 + ├── first-agg [as=column3:13] + │ └── column3:13 + └── first-agg [as=v_comp:14] + └── v_comp:14 build INSERT INTO t_idx2 VALUES (1, 1, 1) ON CONFLICT DO NOTHING @@ -910,75 +959,84 @@ insert t_idx2 ├── columns: ├── arbiter indexes: t_idx2_pkey t_idx2_w_key ├── insert-mapping: - │ ├── column1:8 => a:1 - │ ├── column2:9 => b:2 - │ ├── column3:10 => c:3 - │ ├── v_comp:11 => v:4 - │ └── w_comp:12 => w:5 + │ ├── column1:11 => a:1 + │ ├── column2:12 => b:2 + │ ├── column3:13 => c:3 + │ ├── v_comp:14 => v:4 + │ └── w_comp:15 => w:5 └── upsert-distinct-on - ├── columns: column1:8!null column2:9!null column3:10!null v_comp:11!null w_comp:12!null - ├── grouping columns: w_comp:12!null + ├── columns: column1:11!null column2:12!null column3:13!null v_comp:14!null w_comp:15!null + ├── grouping columns: w_comp:15!null ├── upsert-distinct-on - │ ├── columns: column1:8!null column2:9!null column3:10!null v_comp:11!null w_comp:12!null - │ ├── grouping columns: column1:8!null + │ ├── columns: column1:11!null column2:12!null column3:13!null v_comp:14!null w_comp:15!null + │ ├── grouping columns: column1:11!null │ ├── anti-join (hash) - │ │ ├── columns: column1:8!null column2:9!null column3:10!null v_comp:11!null w_comp:12!null + │ │ ├── columns: column1:11!null column2:12!null column3:13!null v_comp:14!null w_comp:15!null │ │ ├── anti-join (hash) - │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null v_comp:11!null w_comp:12!null + │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null v_comp:14!null w_comp:15!null │ │ │ ├── project - │ │ │ │ ├── columns: v_comp:11!null w_comp:12!null column1:8!null column2:9!null column3:10!null - │ │ │ │ ├── values - │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null - │ │ │ │ │ └── (1, 1, 1) + │ │ │ │ ├── columns: v_comp:14!null w_comp:15!null column1:11!null column2:12!null column3:13!null + │ │ │ │ ├── project + │ │ │ │ │ ├── columns: column1:11!null column2:12!null column3:13!null + │ │ │ │ │ ├── values + │ │ │ │ │ │ ├── columns: column1:8!null column2:9!null column3:10!null + │ │ │ │ │ │ └── (1, 1, 1) + │ │ │ │ │ └── projections + │ │ │ │ │ ├── assignment-cast: INT8 [as=column1:11] + │ │ │ │ │ │ └── column1:8 + │ │ │ │ │ ├── assignment-cast: INT8 [as=column2:12] + │ │ │ │ │ │ └── column2:9 + │ │ │ │ │ └── assignment-cast: INT8 [as=column3:13] + │ │ │ │ │ └── column3:10 │ │ │ │ └── projections - │ │ │ │ ├── column1:8 + column2:9 [as=v_comp:11] - │ │ │ │ └── column3:10 + 1 [as=w_comp:12] + │ │ │ │ ├── column1:11 + column2:12 [as=v_comp:14] + │ │ │ │ └── column3:13 + 1 [as=w_comp:15] │ │ │ ├── project - │ │ │ │ ├── columns: v:16 w:17 a:13!null b:14 c:15 + │ │ │ │ ├── columns: v:19 w:20 a:16!null b:17 c:18 │ │ │ │ ├── scan t_idx2 - │ │ │ │ │ ├── columns: a:13!null b:14 c:15 + │ │ │ │ │ ├── columns: a:16!null b:17 c:18 │ │ │ │ │ └── computed column expressions - │ │ │ │ │ ├── v:16 - │ │ │ │ │ │ └── a:13 + b:14 - │ │ │ │ │ └── w:17 - │ │ │ │ │ └── c:15 + 1 + │ │ │ │ │ ├── v:19 + │ │ │ │ │ │ └── a:16 + b:17 + │ │ │ │ │ └── w:20 + │ │ │ │ │ └── c:18 + 1 │ │ │ │ └── projections - │ │ │ │ ├── a:13 + b:14 [as=v:16] - │ │ │ │ └── c:15 + 1 [as=w:17] + │ │ │ │ ├── a:16 + b:17 [as=v:19] + │ │ │ │ └── c:18 + 1 [as=w:20] │ │ │ └── filters - │ │ │ └── column1:8 = a:13 + │ │ │ └── column1:11 = a:16 │ │ ├── project - │ │ │ ├── columns: v:23 w:24 a:20!null b:21 c:22 + │ │ │ ├── columns: v:26 w:27 a:23!null b:24 c:25 │ │ │ ├── scan t_idx2 - │ │ │ │ ├── columns: a:20!null b:21 c:22 + │ │ │ │ ├── columns: a:23!null b:24 c:25 │ │ │ │ └── computed column expressions - │ │ │ │ ├── v:23 - │ │ │ │ │ └── a:20 + b:21 - │ │ │ │ └── w:24 - │ │ │ │ └── c:22 + 1 + │ │ │ │ ├── v:26 + │ │ │ │ │ └── a:23 + b:24 + │ │ │ │ └── w:27 + │ │ │ │ └── c:25 + 1 │ │ │ └── projections - │ │ │ ├── a:20 + b:21 [as=v:23] - │ │ │ └── c:22 + 1 [as=w:24] + │ │ │ ├── a:23 + b:24 [as=v:26] + │ │ │ └── c:25 + 1 [as=w:27] │ │ └── filters - │ │ └── w_comp:12 = w:24 + │ │ └── w_comp:15 = w:27 │ └── aggregations - │ ├── first-agg [as=column2:9] - │ │ └── column2:9 - │ ├── first-agg [as=column3:10] - │ │ └── column3:10 - │ ├── first-agg [as=v_comp:11] - │ │ └── v_comp:11 - │ └── first-agg [as=w_comp:12] - │ └── w_comp:12 + │ ├── first-agg [as=column2:12] + │ │ └── column2:12 + │ ├── first-agg [as=column3:13] + │ │ └── column3:13 + │ ├── first-agg [as=v_comp:14] + │ │ └── v_comp:14 + │ └── first-agg [as=w_comp:15] + │ └── w_comp:15 └── aggregations - ├── first-agg [as=column1:8] - │ └── column1:8 - ├── first-agg [as=column2:9] - │ └── column2:9 - ├── first-agg [as=column3:10] - │ └── column3:10 - └── first-agg [as=v_comp:11] - └── v_comp:11 + ├── first-agg [as=column1:11] + │ └── column1:11 + ├── first-agg [as=column2:12] + │ └── column2:12 + ├── first-agg [as=column3:13] + │ └── column3:13 + └── first-agg [as=v_comp:14] + └── v_comp:14 build INSERT INTO t VALUES (1, 1) ON CONFLICT (a) DO UPDATE SET a=t.v+1 diff --git a/pkg/sql/opt/optbuilder/testdata/with b/pkg/sql/opt/optbuilder/testdata/with index 99e3f487dc7b..808f6110e6d0 100644 --- a/pkg/sql/opt/optbuilder/testdata/with +++ b/pkg/sql/opt/optbuilder/testdata/with @@ -660,22 +660,27 @@ with &1 (t) └── insert x ├── columns: x.a:6 b:7 rowid:8!null ├── insert-mapping: - │ ├── "?column?":12 => x.a:6 - │ ├── b_default:13 => b:7 - │ └── rowid_default:14 => rowid:8 + │ ├── "?column?":13 => x.a:6 + │ ├── b_default:14 => b:7 + │ └── rowid_default:15 => rowid:8 └── project - ├── columns: b_default:13 rowid_default:14 "?column?":12 + ├── columns: b_default:14 rowid_default:15 "?column?":13 ├── project - │ ├── columns: "?column?":12 - │ ├── with-scan &1 (t) - │ │ ├── columns: a:11 - │ │ └── mapping: - │ │ └── x.a:1 => a:11 + │ ├── columns: "?column?":13 + │ ├── project + │ │ ├── columns: "?column?":12 + │ │ ├── with-scan &1 (t) + │ │ │ ├── columns: a:11 + │ │ │ └── mapping: + │ │ │ └── x.a:1 => a:11 + │ │ └── projections + │ │ └── a:11 + 20 [as="?column?":12] │ └── projections - │ └── a:11 + 20 [as="?column?":12] + │ └── assignment-cast: INT8 [as="?column?":13] + │ └── "?column?":12 └── projections - ├── NULL::INT8 [as=b_default:13] - └── unique_rowid() [as=rowid_default:14] + ├── NULL::INT8 [as=b_default:14] + └── unique_rowid() [as=rowid_default:15] build WITH t AS (SELECT a FROM x) UPDATE x SET a = (SELECT * FROM t) RETURNING * @@ -1435,30 +1440,37 @@ WITH RECURSIVE cte(x, y) AS ( ) SELECT * FROM cte; ---- with &2 - ├── columns: x:19 y:20 + ├── columns: x:21 y:22 ├── project │ ├── columns: x.a:7!null x.b:8!null │ └── insert x │ ├── columns: x.a:7!null x.b:8!null rowid:9!null │ ├── insert-mapping: - │ │ ├── column1:12 => x.a:7 - │ │ ├── column2:13 => x.b:8 - │ │ └── rowid_default:14 => rowid:9 + │ │ ├── column1:14 => x.a:7 + │ │ ├── column2:15 => x.b:8 + │ │ └── rowid_default:16 => rowid:9 │ └── project - │ ├── columns: rowid_default:14 column1:12!null column2:13!null - │ ├── values - │ │ ├── columns: column1:12!null column2:13!null - │ │ ├── (1, 1) - │ │ └── (2, 2) + │ ├── columns: rowid_default:16 column1:14!null column2:15!null + │ ├── project + │ │ ├── columns: column1:14!null column2:15!null + │ │ ├── values + │ │ │ ├── columns: column1:12!null column2:13!null + │ │ │ ├── (1, 1) + │ │ │ └── (2, 2) + │ │ └── projections + │ │ ├── assignment-cast: INT8 [as=column1:14] + │ │ │ └── column1:12 + │ │ └── assignment-cast: INT8 [as=column2:15] + │ │ └── column2:13 │ └── projections - │ └── unique_rowid() [as=rowid_default:14] + │ └── unique_rowid() [as=rowid_default:16] └── with &3 (cte) - ├── columns: x:19 y:20 + ├── columns: x:21 y:22 ├── recursive-c-t-e │ ├── columns: x:3 y:4 │ ├── working table binding: &1 │ ├── initial columns: "?column?":1 "?column?":2 - │ ├── recursive columns: "?column?":17 "?column?":18 + │ ├── recursive columns: "?column?":19 "?column?":20 │ ├── fake-rel │ │ └── columns: x:3 y:4 │ ├── project @@ -1469,28 +1481,28 @@ with &2 │ │ ├── 1 [as="?column?":1] │ │ └── 2 [as="?column?":2] │ └── project - │ ├── columns: "?column?":17 "?column?":18 + │ ├── columns: "?column?":19 "?column?":20 │ ├── inner-join (cross) - │ │ ├── columns: x:5 y:6 a:15!null b:16!null + │ │ ├── columns: x:5 y:6 a:17!null b:18!null │ │ ├── with-scan &1 (cte) │ │ │ ├── columns: x:5 y:6 │ │ │ └── mapping: │ │ │ ├── x:3 => x:5 │ │ │ └── y:4 => y:6 │ │ ├── with-scan &2 - │ │ │ ├── columns: a:15!null b:16!null + │ │ │ ├── columns: a:17!null b:18!null │ │ │ └── mapping: - │ │ │ ├── x.a:7 => a:15 - │ │ │ └── x.b:8 => b:16 + │ │ │ ├── x.a:7 => a:17 + │ │ │ └── x.b:8 => b:18 │ │ └── filters (true) │ └── projections - │ ├── a:15 + x:5 [as="?column?":17] - │ └── b:16 + y:6 [as="?column?":18] + │ ├── a:17 + x:5 [as="?column?":19] + │ └── b:18 + y:6 [as="?column?":20] └── with-scan &3 (cte) - ├── columns: x:19 y:20 + ├── columns: x:21 y:22 └── mapping: - ├── x:3 => x:19 - └── y:4 => y:20 + ├── x:3 => x:21 + └── y:4 => y:22 # Veryify use of WITH inside the initial statement. build @@ -1659,27 +1671,32 @@ build EXPLAIN WITH foo AS (INSERT INTO y VALUES (1) RETURNING *) SELECT * FROM foo ---- explain - ├── columns: info:8 + ├── columns: info:9 └── with &1 (foo) - ├── columns: a:7!null + ├── columns: a:8!null ├── project │ ├── columns: y.a:1!null │ └── insert y │ ├── columns: y.a:1!null rowid:2!null │ ├── insert-mapping: - │ │ ├── column1:5 => y.a:1 - │ │ └── rowid_default:6 => rowid:2 + │ │ ├── column1:6 => y.a:1 + │ │ └── rowid_default:7 => rowid:2 │ └── project - │ ├── columns: rowid_default:6 column1:5!null - │ ├── values - │ │ ├── columns: column1:5!null - │ │ └── (1,) + │ ├── columns: rowid_default:7 column1:6!null + │ ├── project + │ │ ├── columns: column1:6!null + │ │ ├── values + │ │ │ ├── columns: column1:5!null + │ │ │ └── (1,) + │ │ └── projections + │ │ └── assignment-cast: INT8 [as=column1:6] + │ │ └── column1:5 │ └── projections - │ └── unique_rowid() [as=rowid_default:6] + │ └── unique_rowid() [as=rowid_default:7] └── with-scan &1 (foo) - ├── columns: a:7!null + ├── columns: a:8!null └── mapping: - └── y.a:1 => a:7 + └── y.a:1 => a:8 exec-ddl CREATE TABLE a(x INT); @@ -1698,20 +1715,25 @@ with &1 (b) └── insert a ├── columns: ├── insert-mapping: - │ ├── w:7 => x:1 - │ └── rowid_default:8 => rowid:2 + │ ├── w:8 => x:1 + │ └── rowid_default:9 => rowid:2 └── project - ├── columns: rowid_default:8 w:7!null + ├── columns: rowid_default:9 w:8!null ├── project - │ ├── columns: w:7!null - │ ├── with-scan &1 (b) - │ │ ├── columns: z:6!null - │ │ └── mapping: - │ │ └── column1:5 => z:6 + │ ├── columns: w:8!null + │ ├── project + │ │ ├── columns: w:7!null + │ │ ├── with-scan &1 (b) + │ │ │ ├── columns: z:6!null + │ │ │ └── mapping: + │ │ │ └── column1:5 => z:6 + │ │ └── projections + │ │ └── z:6 + 1 [as=w:7] │ └── projections - │ └── z:6 + 1 [as=w:7] + │ └── assignment-cast: INT8 [as=w:8] + │ └── w:7 └── projections - └── unique_rowid() [as=rowid_default:8] + └── unique_rowid() [as=rowid_default:9] # Subquery as a whole is correlated, but the WITH is not. build diff --git a/pkg/sql/opt/optgen/lang/support/textmate/OptGen.tmbundle/Syntaxes/optgen.tmLanguage b/pkg/sql/opt/optgen/lang/support/textmate/OptGen.tmbundle/Syntaxes/optgen.tmLanguage index d78318c7b45b..8f98cde91f6a 100644 --- a/pkg/sql/opt/optgen/lang/support/textmate/OptGen.tmbundle/Syntaxes/optgen.tmLanguage +++ b/pkg/sql/opt/optgen/lang/support/textmate/OptGen.tmbundle/Syntaxes/optgen.tmLanguage @@ -175,6 +175,7 @@ UnaryMinus | UnaryComplement | Cast | + AssignmentCast | Case | When | Array | diff --git a/pkg/sql/opt/optgen/lang/support/vim/cropt.vim b/pkg/sql/opt/optgen/lang/support/vim/cropt.vim index 64f3bceedf8e..9b308345d2ac 100644 --- a/pkg/sql/opt/optgen/lang/support/vim/cropt.vim +++ b/pkg/sql/opt/optgen/lang/support/vim/cropt.vim @@ -41,7 +41,7 @@ syn keyword operator Like NotLike ILike NotILike SimilarTo NotSimilarTo RegMatch syn keyword operator RegIMatch NotRegIMatch Is IsNot Contains JsonExists JsonAllExists syn keyword operator JsonSomeExists AnyScalar Bitand Bitor Bitxor Plus Minus Mult Div FloorDiv syn keyword operator Mod Pow Concat LShift RShift FetchVal FetchText FetchValPath FetchTextPath -syn keyword operator UnaryMinus UnaryComplement Cast Case When Array Indirection +syn keyword operator UnaryMinus UnaryComplement Cast AssignmentCast Case When Array Indirection syn keyword operator Function FunctionPrivate Coalesce ColumnAccess syn keyword operator Avg BoolAnd BoolOr ConcatAgg Count CountRows Max Min SumInt Sum SqrDiff syn keyword operator Variance StdDev XorAgg JsonAgg JsonbAgg ConstAgg ConstNotNullAgg diff --git a/pkg/sql/opt/optgen/lang/support/vscode/cockroachdb.optgen-1.0.0/syntaxes/optgen.tmLanguage b/pkg/sql/opt/optgen/lang/support/vscode/cockroachdb.optgen-1.0.0/syntaxes/optgen.tmLanguage index d78318c7b45b..8f98cde91f6a 100644 --- a/pkg/sql/opt/optgen/lang/support/vscode/cockroachdb.optgen-1.0.0/syntaxes/optgen.tmLanguage +++ b/pkg/sql/opt/optgen/lang/support/vscode/cockroachdb.optgen-1.0.0/syntaxes/optgen.tmLanguage @@ -175,6 +175,7 @@ UnaryMinus | UnaryComplement | Cast | + AssignmentCast | Case | When | Array | diff --git a/pkg/sql/opt/xform/testdata/coster/join b/pkg/sql/opt/xform/testdata/coster/join index 0fadb01d4531..0e65e4594e71 100644 --- a/pkg/sql/opt/xform/testdata/coster/join +++ b/pkg/sql/opt/xform/testdata/coster/join @@ -776,35 +776,46 @@ INSERT INTO c VALUES (1,1), (2,2) insert c ├── columns: ├── insert-mapping: - │ ├── column1:5 => c:1 - │ └── column2:6 => c.p:2 + │ ├── column1:7 => c:1 + │ └── column2:8 => c.p:2 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── stats: [rows=0] - ├── cost: 12.12 - ├── values - │ ├── columns: column1:5!null column2:6!null + ├── cost: 12.19 + ├── project + │ ├── columns: column1:7!null column2:8!null │ ├── cardinality: [2 - 2] - │ ├── stats: [rows=2, distinct(6)=2, null(6)=0] - │ ├── cost: 0.03 - │ ├── (1, 1) - │ └── (2, 2) + │ ├── immutable + │ ├── stats: [rows=2, distinct(8)=2, null(8)=0] + │ ├── cost: 0.1 + │ ├── values + │ │ ├── columns: column1:5!null column2:6!null + │ │ ├── cardinality: [2 - 2] + │ │ ├── stats: [rows=2, distinct(6)=2, null(6)=0] + │ │ ├── cost: 0.03 + │ │ ├── (1, 1) + │ │ └── (2, 2) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:7, outer=(5), immutable] + │ │ └── column1:5 + │ └── assignment-cast: INT8 [as=column2:8, outer=(6), immutable] + │ └── column2:6 └── f-k-checks └── f-k-checks-item: c(p) -> p(p) └── anti-join (lookup p) - ├── columns: p:7!null - ├── key columns: [7] = [8] + ├── columns: p:9!null + ├── key columns: [9] = [10] ├── lookup columns are key ├── cardinality: [0 - 2] ├── stats: [rows=1e-10] ├── cost: 12.08 ├── with-scan &1 - │ ├── columns: p:7!null + │ ├── columns: p:9!null │ ├── mapping: - │ │ └── column2:6 => p:7 + │ │ └── column2:8 => p:9 │ ├── cardinality: [2 - 2] - │ ├── stats: [rows=2, distinct(7)=2, null(7)=0] + │ ├── stats: [rows=2, distinct(9)=2, null(9)=0] │ └── cost: 0.01 └── filters (true) @@ -815,36 +826,47 @@ INSERT INTO c VALUES (1,1), (2,2) insert c ├── columns: ├── insert-mapping: - │ ├── column1:5 => c:1 - │ └── column2:6 => c.p:2 + │ ├── column1:7 => c:1 + │ └── column2:8 => c.p:2 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── stats: [rows=0] - ├── cost: 0.06001206 - ├── values - │ ├── columns: column1:5!null column2:6!null + ├── cost: 0.13001206 + ├── project + │ ├── columns: column1:7!null column2:8!null │ ├── cardinality: [2 - 2] - │ ├── stats: [rows=2, distinct(6)=2, null(6)=0] - │ ├── cost: 0.03 - │ ├── (1, 1) - │ └── (2, 2) + │ ├── immutable + │ ├── stats: [rows=2, distinct(8)=2, null(8)=0] + │ ├── cost: 0.1 + │ ├── values + │ │ ├── columns: column1:5!null column2:6!null + │ │ ├── cardinality: [2 - 2] + │ │ ├── stats: [rows=2, distinct(6)=2, null(6)=0] + │ │ ├── cost: 0.03 + │ │ ├── (1, 1) + │ │ └── (2, 2) + │ └── projections + │ ├── assignment-cast: INT8 [as=column1:7, outer=(5), immutable] + │ │ └── column1:5 + │ └── assignment-cast: INT8 [as=column2:8, outer=(6), immutable] + │ └── column2:6 └── f-k-checks └── f-k-checks-item: c(p) -> p(p) └── anti-join (lookup p) - ├── columns: p:7!null + ├── columns: p:9!null ├── flags: prefer lookup join (into right side) - ├── key columns: [7] = [8] + ├── key columns: [9] = [10] ├── lookup columns are key ├── cardinality: [0 - 2] ├── stats: [rows=1e-10] ├── cost: 0.02001206 ├── with-scan &1 - │ ├── columns: p:7!null + │ ├── columns: p:9!null │ ├── mapping: - │ │ └── column2:6 => p:7 + │ │ └── column2:8 => p:9 │ ├── cardinality: [2 - 2] - │ ├── stats: [rows=2, distinct(7)=2, null(7)=0] + │ ├── stats: [rows=2, distinct(9)=2, null(9)=0] │ └── cost: 0.01 └── filters (true) @@ -867,41 +889,55 @@ INSERT INTO c VALUES (1, 1) insert c ├── columns: ├── insert-mapping: - │ ├── column1:5 => c:1 - │ └── column2:6 => c.p:2 + │ ├── column1:7 => c:1 + │ └── column2:8 => c.p:2 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── stats: [rows=0] - ├── cost: 6.08 + ├── cost: 6.11 ├── values - │ ├── columns: column1:5!null column2:6!null + │ ├── columns: column1:7 column2:8 │ ├── cardinality: [1 - 1] - │ ├── stats: [rows=1, distinct(6)=1, null(6)=0] + │ ├── immutable + │ ├── stats: [rows=1, distinct(8)=1, null(8)=0] │ ├── cost: 0.02 │ ├── key: () - │ ├── fd: ()-->(5,6) - │ └── (1, 1) + │ ├── fd: ()-->(7,8) + │ └── tuple + │ ├── assignment-cast: INT8 + │ │ └── 1 + │ └── assignment-cast: INT8 + │ └── 1 └── f-k-checks └── f-k-checks-item: c(p) -> p(p) └── anti-join (lookup p) - ├── columns: p:7!null - ├── key columns: [7] = [8] + ├── columns: p:9!null + ├── key columns: [9] = [10] ├── lookup columns are key ├── cardinality: [0 - 1] ├── stats: [rows=1e-10] - ├── cost: 6.05 + ├── cost: 6.08 ├── key: () - ├── fd: ()-->(7) - ├── with-scan &1 - │ ├── columns: p:7!null - │ ├── mapping: - │ │ └── column2:6 => p:7 - │ ├── cardinality: [1 - 1] - │ ├── stats: [rows=1, distinct(7)=1, null(7)=0] - │ ├── cost: 0.01 + ├── fd: ()-->(9) + ├── select + │ ├── columns: p:9!null + │ ├── cardinality: [0 - 1] + │ ├── stats: [rows=1, distinct(9)=1, null(9)=0] + │ ├── cost: 0.04 │ ├── key: () - │ └── fd: ()-->(7) + │ ├── fd: ()-->(9) + │ ├── with-scan &1 + │ │ ├── columns: p:9 + │ │ ├── mapping: + │ │ │ └── column2:8 => p:9 + │ │ ├── cardinality: [1 - 1] + │ │ ├── stats: [rows=1, distinct(9)=1, null(9)=0] + │ │ ├── cost: 0.01 + │ │ ├── key: () + │ │ └── fd: ()-->(9) + │ └── filters + │ └── p:9 IS NOT NULL [outer=(9), constraints=(/9: (/NULL - ]; tight)] └── filters (true) # Avoid performing a lookup join with virtual tables if the filter is diff --git a/pkg/sql/opt/xform/testdata/external/tpcc b/pkg/sql/opt/xform/testdata/external/tpcc index 923f53368df7..26f9828334ea 100644 --- a/pkg/sql/opt/xform/testdata/external/tpcc +++ b/pkg/sql/opt/xform/testdata/external/tpcc @@ -141,41 +141,64 @@ VALUES (100, 5, 10, 50, '2019-08-26 16:50:41', 10, 1) insert order ├── columns: ├── insert-mapping: - │ ├── column1:11 => o_id:1 - │ ├── column2:12 => "order".o_d_id:2 - │ ├── column3:13 => "order".o_w_id:3 - │ ├── column4:14 => "order".o_c_id:4 - │ ├── column5:15 => o_entry_d:5 - │ ├── o_carrier_id_default:18 => o_carrier_id:6 - │ ├── column6:16 => o_ol_cnt:7 - │ └── column7:17 => o_all_local:8 + │ ├── column1:18 => o_id:1 + │ ├── column2:19 => "order".o_d_id:2 + │ ├── column3:20 => "order".o_w_id:3 + │ ├── column4:21 => "order".o_c_id:4 + │ ├── column5:22 => o_entry_d:5 + │ ├── o_carrier_id_default:25 => o_carrier_id:6 + │ ├── column6:23 => o_ol_cnt:7 + │ └── column7:24 => o_all_local:8 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── values - │ ├── columns: column1:11!null column2:12!null column3:13!null column4:14!null column5:15!null column6:16!null column7:17!null o_carrier_id_default:18 + │ ├── columns: column1:18 column2:19 column3:20 column4:21 column5:22 column6:23 column7:24 o_carrier_id_default:25 │ ├── cardinality: [1 - 1] + │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(11-18) - │ └── (100, 5, 10, 50, '2019-08-26 16:50:41', 10, 1, NULL) + │ ├── fd: ()-->(18-25) + │ └── tuple + │ ├── assignment-cast: INT8 + │ │ └── 100 + │ ├── assignment-cast: INT8 + │ │ └── 5 + │ ├── assignment-cast: INT8 + │ │ └── 10 + │ ├── assignment-cast: INT8 + │ │ └── 50 + │ ├── assignment-cast: TIMESTAMP + │ │ └── '2019-08-26 16:50:41' + │ ├── assignment-cast: INT8 + │ │ └── 10 + │ ├── assignment-cast: INT8 + │ │ └── 1 + │ └── CAST(NULL AS INT8) └── f-k-checks └── f-k-checks-item: order(o_w_id,o_d_id,o_c_id) -> customer(c_w_id,c_d_id,c_id) └── anti-join (lookup customer) - ├── columns: o_w_id:19!null o_d_id:20!null o_c_id:21!null - ├── key columns: [19 20 21] = [24 23 22] + ├── columns: o_w_id:26 o_d_id:27 o_c_id:28!null + ├── key columns: [26 27 28] = [31 30 29] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(19-21) - ├── with-scan &1 - │ ├── columns: o_w_id:19!null o_d_id:20!null o_c_id:21!null - │ ├── mapping: - │ │ ├── column3:13 => o_w_id:19 - │ │ ├── column2:12 => o_d_id:20 - │ │ └── column4:14 => o_c_id:21 - │ ├── cardinality: [1 - 1] + ├── fd: ()-->(26-28) + ├── select + │ ├── columns: o_w_id:26 o_d_id:27 o_c_id:28!null + │ ├── cardinality: [0 - 1] │ ├── key: () - │ └── fd: ()-->(19-21) + │ ├── fd: ()-->(26-28) + │ ├── with-scan &1 + │ │ ├── columns: o_w_id:26 o_d_id:27 o_c_id:28 + │ │ ├── mapping: + │ │ │ ├── column3:20 => o_w_id:26 + │ │ │ ├── column2:19 => o_d_id:27 + │ │ │ └── column4:21 => o_c_id:28 + │ │ ├── cardinality: [1 - 1] + │ │ ├── key: () + │ │ └── fd: ()-->(26-28) + │ └── filters + │ └── o_c_id:28 IS NOT NULL [outer=(28), constraints=(/28: (/NULL - ]; tight)] └── filters (true) opt format=hide-qual @@ -184,36 +207,43 @@ INSERT INTO new_order (no_o_id, no_d_id, no_w_id) VALUES (2000, 100, 10) insert new_order ├── columns: ├── insert-mapping: - │ ├── column1:6 => new_order.no_o_id:1 - │ ├── column2:7 => new_order.no_d_id:2 - │ └── column3:8 => new_order.no_w_id:3 + │ ├── column1:9 => new_order.no_o_id:1 + │ ├── column2:10 => new_order.no_d_id:2 + │ └── column3:11 => new_order.no_w_id:3 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── values - │ ├── columns: column1:6!null column2:7!null column3:8!null + │ ├── columns: column1:9 column2:10 column3:11 │ ├── cardinality: [1 - 1] + │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(6-8) - │ └── (2000, 100, 10) + │ ├── fd: ()-->(9-11) + │ └── tuple + │ ├── assignment-cast: INT8 + │ │ └── 2000 + │ ├── assignment-cast: INT8 + │ │ └── 100 + │ └── assignment-cast: INT8 + │ └── 10 └── f-k-checks └── f-k-checks-item: new_order(no_w_id,no_d_id,no_o_id) -> order(o_w_id,o_d_id,o_id) └── anti-join (lookup order) - ├── columns: no_w_id:9!null no_d_id:10!null no_o_id:11!null - ├── key columns: [9 10 11] = [14 13 12] + ├── columns: no_w_id:12 no_d_id:13 no_o_id:14 + ├── key columns: [12 13 14] = [17 16 15] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(9-11) + ├── fd: ()-->(12-14) ├── with-scan &1 - │ ├── columns: no_w_id:9!null no_d_id:10!null no_o_id:11!null + │ ├── columns: no_w_id:12 no_d_id:13 no_o_id:14 │ ├── mapping: - │ │ ├── column3:8 => no_w_id:9 - │ │ ├── column2:7 => no_d_id:10 - │ │ └── column1:6 => no_o_id:11 + │ │ ├── column3:11 => no_w_id:12 + │ │ ├── column2:10 => no_d_id:13 + │ │ └── column1:9 => no_o_id:14 │ ├── cardinality: [1 - 1] │ ├── key: () - │ └── fd: ()-->(9-11) + │ └── fd: ()-->(12-14) └── filters (true) opt format=hide-qual @@ -358,24 +388,24 @@ VALUES insert order_line ├── columns: ├── insert-mapping: - │ ├── column1:13 => order_line.ol_o_id:1 - │ ├── column2:14 => order_line.ol_d_id:2 - │ ├── column3:15 => order_line.ol_w_id:3 - │ ├── column4:16 => ol_number:4 - │ ├── column5:17 => order_line.ol_i_id:5 - │ ├── column6:18 => order_line.ol_supply_w_id:6 - │ ├── ol_delivery_d_default:24 => ol_delivery_d:7 - │ ├── column7:19 => ol_quantity:8 - │ ├── column8:22 => ol_amount:9 - │ └── column9:23 => ol_dist_info:10 + │ ├── column1:22 => order_line.ol_o_id:1 + │ ├── column2:23 => order_line.ol_d_id:2 + │ ├── column3:24 => order_line.ol_w_id:3 + │ ├── column4:25 => ol_number:4 + │ ├── column5:26 => order_line.ol_i_id:5 + │ ├── column6:27 => order_line.ol_supply_w_id:6 + │ ├── ol_delivery_d_default:31 => ol_delivery_d:7 + │ ├── column7:28 => ol_quantity:8 + │ ├── column8:29 => ol_amount:9 + │ └── column9:30 => ol_dist_info:10 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── project - │ ├── columns: ol_delivery_d_default:24 column8:22 column9:23 column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null column6:18!null column7:19!null + │ ├── columns: ol_delivery_d_default:31 column1:22!null column2:23!null column3:24!null column4:25!null column5:26!null column6:27!null column7:28!null column8:29!null column9:30!null │ ├── cardinality: [6 - 6] │ ├── immutable - │ ├── fd: ()-->(24) + │ ├── fd: ()-->(31) │ ├── values │ │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null column6:18!null column7:19!null column8:20!null column9:21!null │ │ ├── cardinality: [6 - 6] @@ -386,37 +416,51 @@ insert order_line │ │ ├── (3045, 2, 10, 4, 56624, 0, 6, 273.360000, 'RsaCXoEzmssaF9m9cdLXe0Yh') │ │ └── (3045, 2, 10, 6, 92966, 0, 4, 366.760000, 'saCXoEzmssaF9m9cdLXe0Yhg') │ └── projections - │ ├── CAST(NULL AS TIMESTAMP) [as=ol_delivery_d_default:24] - │ ├── assignment-cast: DECIMAL(6,2) [as=column8:22, outer=(20), immutable] + │ ├── CAST(NULL AS TIMESTAMP) [as=ol_delivery_d_default:31] + │ ├── assignment-cast: INT8 [as=column1:22, outer=(13), immutable] + │ │ └── column1:13 + │ ├── assignment-cast: INT8 [as=column2:23, outer=(14), immutable] + │ │ └── column2:14 + │ ├── assignment-cast: INT8 [as=column3:24, outer=(15), immutable] + │ │ └── column3:15 + │ ├── assignment-cast: INT8 [as=column4:25, outer=(16), immutable] + │ │ └── column4:16 + │ ├── assignment-cast: INT8 [as=column5:26, outer=(17), immutable] + │ │ └── column5:17 + │ ├── assignment-cast: INT8 [as=column6:27, outer=(18), immutable] + │ │ └── column6:18 + │ ├── assignment-cast: INT8 [as=column7:28, outer=(19), immutable] + │ │ └── column7:19 + │ ├── assignment-cast: DECIMAL(6,2) [as=column8:29, outer=(20), immutable] │ │ └── column8:20 - │ └── assignment-cast: CHAR(24) [as=column9:23, outer=(21), immutable] + │ └── assignment-cast: CHAR(24) [as=column9:30, outer=(21), immutable] │ └── column9:21 └── f-k-checks ├── f-k-checks-item: order_line(ol_w_id,ol_d_id,ol_o_id) -> order(o_w_id,o_d_id,o_id) │ └── anti-join (lookup order) - │ ├── columns: ol_w_id:25!null ol_d_id:26!null ol_o_id:27!null - │ ├── key columns: [25 26 27] = [30 29 28] + │ ├── columns: ol_w_id:32!null ol_d_id:33!null ol_o_id:34!null + │ ├── key columns: [32 33 34] = [37 36 35] │ ├── lookup columns are key │ ├── cardinality: [0 - 6] │ ├── with-scan &1 - │ │ ├── columns: ol_w_id:25!null ol_d_id:26!null ol_o_id:27!null + │ │ ├── columns: ol_w_id:32!null ol_d_id:33!null ol_o_id:34!null │ │ ├── mapping: - │ │ │ ├── column3:15 => ol_w_id:25 - │ │ │ ├── column2:14 => ol_d_id:26 - │ │ │ └── column1:13 => ol_o_id:27 + │ │ │ ├── column3:24 => ol_w_id:32 + │ │ │ ├── column2:23 => ol_d_id:33 + │ │ │ └── column1:22 => ol_o_id:34 │ │ └── cardinality: [6 - 6] │ └── filters (true) └── f-k-checks-item: order_line(ol_supply_w_id,ol_i_id) -> stock(s_w_id,s_i_id) └── anti-join (lookup stock) - ├── columns: ol_supply_w_id:38!null ol_i_id:39!null - ├── key columns: [38 39] = [41 40] + ├── columns: ol_supply_w_id:45!null ol_i_id:46!null + ├── key columns: [45 46] = [48 47] ├── lookup columns are key ├── cardinality: [0 - 6] ├── with-scan &1 - │ ├── columns: ol_supply_w_id:38!null ol_i_id:39!null + │ ├── columns: ol_supply_w_id:45!null ol_i_id:46!null │ ├── mapping: - │ │ ├── column6:18 => ol_supply_w_id:38 - │ │ └── column5:17 => ol_i_id:39 + │ │ ├── column6:27 => ol_supply_w_id:45 + │ │ └── column5:26 => ol_i_id:46 │ └── cardinality: [6 - 6] └── filters (true) @@ -603,71 +647,77 @@ VALUES insert history ├── columns: ├── insert-mapping: - │ ├── rowid_default:22 => rowid:1 - │ ├── column1:12 => history.h_c_id:2 - │ ├── column2:13 => history.h_c_d_id:3 - │ ├── column3:14 => history.h_c_w_id:4 - │ ├── column4:15 => history.h_d_id:5 - │ ├── column5:16 => history.h_w_id:6 - │ ├── column7:18 => h_date:7 - │ ├── column6:20 => h_amount:8 - │ └── column8:21 => h_data:9 + │ ├── rowid_default:28 => rowid:1 + │ ├── column1:20 => history.h_c_id:2 + │ ├── column2:21 => history.h_c_d_id:3 + │ ├── column3:22 => history.h_c_w_id:4 + │ ├── column4:23 => history.h_d_id:5 + │ ├── column5:24 => history.h_w_id:6 + │ ├── column7:26 => h_date:7 + │ ├── column6:25 => h_amount:8 + │ └── column8:27 => h_data:9 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── values - │ ├── columns: column1:12!null column2:13!null column3:14!null column4:15!null column5:16!null column7:18!null column6:20 column8:21 rowid_default:22 + │ ├── columns: column1:20 column2:21 column3:22 column4:23 column5:24 column6:25 column7:26 column8:27 rowid_default:28 │ ├── cardinality: [1 - 1] │ ├── volatile │ ├── key: () - │ ├── fd: ()-->(12-16,18,20-22) + │ ├── fd: ()-->(20-28) │ └── tuple - │ ├── 1343 - │ ├── 5 - │ ├── 10 - │ ├── 5 - │ ├── 10 - │ ├── '2019-08-26 16:50:41' + │ ├── assignment-cast: INT8 + │ │ └── 1343 + │ ├── assignment-cast: INT8 + │ │ └── 5 + │ ├── assignment-cast: INT8 + │ │ └── 10 + │ ├── assignment-cast: INT8 + │ │ └── 5 + │ ├── assignment-cast: INT8 + │ │ └── 10 │ ├── assignment-cast: DECIMAL(6,2) │ │ └── 3860.61 + │ ├── assignment-cast: TIMESTAMP + │ │ └── '2019-08-26 16:50:41' │ ├── assignment-cast: VARCHAR(24) │ │ └── '8 Kdcgphy3' │ └── gen_random_uuid() └── f-k-checks ├── f-k-checks-item: history(h_c_w_id,h_c_d_id,h_c_id) -> customer(c_w_id,c_d_id,c_id) │ └── anti-join (lookup customer) - │ ├── columns: h_c_w_id:23!null h_c_d_id:24!null h_c_id:25!null - │ ├── key columns: [23 24 25] = [28 27 26] + │ ├── columns: h_c_w_id:29 h_c_d_id:30 h_c_id:31 + │ ├── key columns: [29 30 31] = [34 33 32] │ ├── lookup columns are key │ ├── cardinality: [0 - 1] │ ├── key: () - │ ├── fd: ()-->(23-25) + │ ├── fd: ()-->(29-31) │ ├── with-scan &1 - │ │ ├── columns: h_c_w_id:23!null h_c_d_id:24!null h_c_id:25!null + │ │ ├── columns: h_c_w_id:29 h_c_d_id:30 h_c_id:31 │ │ ├── mapping: - │ │ │ ├── column3:14 => h_c_w_id:23 - │ │ │ ├── column2:13 => h_c_d_id:24 - │ │ │ └── column1:12 => h_c_id:25 + │ │ │ ├── column3:22 => h_c_w_id:29 + │ │ │ ├── column2:21 => h_c_d_id:30 + │ │ │ └── column1:20 => h_c_id:31 │ │ ├── cardinality: [1 - 1] │ │ ├── key: () - │ │ └── fd: ()-->(23-25) + │ │ └── fd: ()-->(29-31) │ └── filters (true) └── f-k-checks-item: history(h_w_id,h_d_id) -> district(d_w_id,d_id) └── anti-join (lookup district) - ├── columns: h_w_id:49!null h_d_id:50!null - ├── key columns: [49 50] = [52 51] + ├── columns: h_w_id:55 h_d_id:56 + ├── key columns: [55 56] = [58 57] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(49,50) + ├── fd: ()-->(55,56) ├── with-scan &1 - │ ├── columns: h_w_id:49!null h_d_id:50!null + │ ├── columns: h_w_id:55 h_d_id:56 │ ├── mapping: - │ │ ├── column5:16 => h_w_id:49 - │ │ └── column4:15 => h_d_id:50 + │ │ ├── column5:24 => h_w_id:55 + │ │ └── column4:23 => h_d_id:56 │ ├── cardinality: [1 - 1] │ ├── key: () - │ └── fd: ()-->(49,50) + │ └── fd: ()-->(55,56) └── filters (true) # -------------------------------------------------- diff --git a/pkg/sql/opt/xform/testdata/external/tpcc-later-stats b/pkg/sql/opt/xform/testdata/external/tpcc-later-stats index 92ea17f63b95..ea3904c62a14 100644 --- a/pkg/sql/opt/xform/testdata/external/tpcc-later-stats +++ b/pkg/sql/opt/xform/testdata/external/tpcc-later-stats @@ -144,41 +144,64 @@ VALUES (100, 5, 10, 50, '2019-08-26 16:50:41', 10, 1) insert order ├── columns: ├── insert-mapping: - │ ├── column1:11 => o_id:1 - │ ├── column2:12 => "order".o_d_id:2 - │ ├── column3:13 => "order".o_w_id:3 - │ ├── column4:14 => "order".o_c_id:4 - │ ├── column5:15 => o_entry_d:5 - │ ├── o_carrier_id_default:18 => o_carrier_id:6 - │ ├── column6:16 => o_ol_cnt:7 - │ └── column7:17 => o_all_local:8 + │ ├── column1:18 => o_id:1 + │ ├── column2:19 => "order".o_d_id:2 + │ ├── column3:20 => "order".o_w_id:3 + │ ├── column4:21 => "order".o_c_id:4 + │ ├── column5:22 => o_entry_d:5 + │ ├── o_carrier_id_default:25 => o_carrier_id:6 + │ ├── column6:23 => o_ol_cnt:7 + │ └── column7:24 => o_all_local:8 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── values - │ ├── columns: column1:11!null column2:12!null column3:13!null column4:14!null column5:15!null column6:16!null column7:17!null o_carrier_id_default:18 + │ ├── columns: column1:18 column2:19 column3:20 column4:21 column5:22 column6:23 column7:24 o_carrier_id_default:25 │ ├── cardinality: [1 - 1] + │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(11-18) - │ └── (100, 5, 10, 50, '2019-08-26 16:50:41', 10, 1, NULL) + │ ├── fd: ()-->(18-25) + │ └── tuple + │ ├── assignment-cast: INT8 + │ │ └── 100 + │ ├── assignment-cast: INT8 + │ │ └── 5 + │ ├── assignment-cast: INT8 + │ │ └── 10 + │ ├── assignment-cast: INT8 + │ │ └── 50 + │ ├── assignment-cast: TIMESTAMP + │ │ └── '2019-08-26 16:50:41' + │ ├── assignment-cast: INT8 + │ │ └── 10 + │ ├── assignment-cast: INT8 + │ │ └── 1 + │ └── CAST(NULL AS INT8) └── f-k-checks └── f-k-checks-item: order(o_w_id,o_d_id,o_c_id) -> customer(c_w_id,c_d_id,c_id) └── anti-join (lookup customer) - ├── columns: o_w_id:19!null o_d_id:20!null o_c_id:21!null - ├── key columns: [19 20 21] = [24 23 22] + ├── columns: o_w_id:26 o_d_id:27 o_c_id:28!null + ├── key columns: [26 27 28] = [31 30 29] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(19-21) - ├── with-scan &1 - │ ├── columns: o_w_id:19!null o_d_id:20!null o_c_id:21!null - │ ├── mapping: - │ │ ├── column3:13 => o_w_id:19 - │ │ ├── column2:12 => o_d_id:20 - │ │ └── column4:14 => o_c_id:21 - │ ├── cardinality: [1 - 1] + ├── fd: ()-->(26-28) + ├── select + │ ├── columns: o_w_id:26 o_d_id:27 o_c_id:28!null + │ ├── cardinality: [0 - 1] │ ├── key: () - │ └── fd: ()-->(19-21) + │ ├── fd: ()-->(26-28) + │ ├── with-scan &1 + │ │ ├── columns: o_w_id:26 o_d_id:27 o_c_id:28 + │ │ ├── mapping: + │ │ │ ├── column3:20 => o_w_id:26 + │ │ │ ├── column2:19 => o_d_id:27 + │ │ │ └── column4:21 => o_c_id:28 + │ │ ├── cardinality: [1 - 1] + │ │ ├── key: () + │ │ └── fd: ()-->(26-28) + │ └── filters + │ └── o_c_id:28 IS NOT NULL [outer=(28), constraints=(/28: (/NULL - ]; tight)] └── filters (true) opt format=hide-qual @@ -187,36 +210,43 @@ INSERT INTO new_order (no_o_id, no_d_id, no_w_id) VALUES (2000, 100, 10) insert new_order ├── columns: ├── insert-mapping: - │ ├── column1:6 => new_order.no_o_id:1 - │ ├── column2:7 => new_order.no_d_id:2 - │ └── column3:8 => new_order.no_w_id:3 + │ ├── column1:9 => new_order.no_o_id:1 + │ ├── column2:10 => new_order.no_d_id:2 + │ └── column3:11 => new_order.no_w_id:3 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── values - │ ├── columns: column1:6!null column2:7!null column3:8!null + │ ├── columns: column1:9 column2:10 column3:11 │ ├── cardinality: [1 - 1] + │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(6-8) - │ └── (2000, 100, 10) + │ ├── fd: ()-->(9-11) + │ └── tuple + │ ├── assignment-cast: INT8 + │ │ └── 2000 + │ ├── assignment-cast: INT8 + │ │ └── 100 + │ └── assignment-cast: INT8 + │ └── 10 └── f-k-checks └── f-k-checks-item: new_order(no_w_id,no_d_id,no_o_id) -> order(o_w_id,o_d_id,o_id) └── anti-join (lookup order) - ├── columns: no_w_id:9!null no_d_id:10!null no_o_id:11!null - ├── key columns: [9 10 11] = [14 13 12] + ├── columns: no_w_id:12 no_d_id:13 no_o_id:14 + ├── key columns: [12 13 14] = [17 16 15] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(9-11) + ├── fd: ()-->(12-14) ├── with-scan &1 - │ ├── columns: no_w_id:9!null no_d_id:10!null no_o_id:11!null + │ ├── columns: no_w_id:12 no_d_id:13 no_o_id:14 │ ├── mapping: - │ │ ├── column3:8 => no_w_id:9 - │ │ ├── column2:7 => no_d_id:10 - │ │ └── column1:6 => no_o_id:11 + │ │ ├── column3:11 => no_w_id:12 + │ │ ├── column2:10 => no_d_id:13 + │ │ └── column1:9 => no_o_id:14 │ ├── cardinality: [1 - 1] │ ├── key: () - │ └── fd: ()-->(9-11) + │ └── fd: ()-->(12-14) └── filters (true) opt format=hide-qual @@ -361,24 +391,24 @@ VALUES insert order_line ├── columns: ├── insert-mapping: - │ ├── column1:13 => order_line.ol_o_id:1 - │ ├── column2:14 => order_line.ol_d_id:2 - │ ├── column3:15 => order_line.ol_w_id:3 - │ ├── column4:16 => ol_number:4 - │ ├── column5:17 => order_line.ol_i_id:5 - │ ├── column6:18 => order_line.ol_supply_w_id:6 - │ ├── ol_delivery_d_default:24 => ol_delivery_d:7 - │ ├── column7:19 => ol_quantity:8 - │ ├── column8:22 => ol_amount:9 - │ └── column9:23 => ol_dist_info:10 + │ ├── column1:22 => order_line.ol_o_id:1 + │ ├── column2:23 => order_line.ol_d_id:2 + │ ├── column3:24 => order_line.ol_w_id:3 + │ ├── column4:25 => ol_number:4 + │ ├── column5:26 => order_line.ol_i_id:5 + │ ├── column6:27 => order_line.ol_supply_w_id:6 + │ ├── ol_delivery_d_default:31 => ol_delivery_d:7 + │ ├── column7:28 => ol_quantity:8 + │ ├── column8:29 => ol_amount:9 + │ └── column9:30 => ol_dist_info:10 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── project - │ ├── columns: ol_delivery_d_default:24 column8:22 column9:23 column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null column6:18!null column7:19!null + │ ├── columns: ol_delivery_d_default:31 column1:22!null column2:23!null column3:24!null column4:25!null column5:26!null column6:27!null column7:28!null column8:29!null column9:30!null │ ├── cardinality: [6 - 6] │ ├── immutable - │ ├── fd: ()-->(24) + │ ├── fd: ()-->(31) │ ├── values │ │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null column6:18!null column7:19!null column8:20!null column9:21!null │ │ ├── cardinality: [6 - 6] @@ -389,37 +419,51 @@ insert order_line │ │ ├── (3045, 2, 10, 4, 56624, 0, 6, 273.360000, 'RsaCXoEzmssaF9m9cdLXe0Yh') │ │ └── (3045, 2, 10, 6, 92966, 0, 4, 366.760000, 'saCXoEzmssaF9m9cdLXe0Yhg') │ └── projections - │ ├── CAST(NULL AS TIMESTAMP) [as=ol_delivery_d_default:24] - │ ├── assignment-cast: DECIMAL(6,2) [as=column8:22, outer=(20), immutable] + │ ├── CAST(NULL AS TIMESTAMP) [as=ol_delivery_d_default:31] + │ ├── assignment-cast: INT8 [as=column1:22, outer=(13), immutable] + │ │ └── column1:13 + │ ├── assignment-cast: INT8 [as=column2:23, outer=(14), immutable] + │ │ └── column2:14 + │ ├── assignment-cast: INT8 [as=column3:24, outer=(15), immutable] + │ │ └── column3:15 + │ ├── assignment-cast: INT8 [as=column4:25, outer=(16), immutable] + │ │ └── column4:16 + │ ├── assignment-cast: INT8 [as=column5:26, outer=(17), immutable] + │ │ └── column5:17 + │ ├── assignment-cast: INT8 [as=column6:27, outer=(18), immutable] + │ │ └── column6:18 + │ ├── assignment-cast: INT8 [as=column7:28, outer=(19), immutable] + │ │ └── column7:19 + │ ├── assignment-cast: DECIMAL(6,2) [as=column8:29, outer=(20), immutable] │ │ └── column8:20 - │ └── assignment-cast: CHAR(24) [as=column9:23, outer=(21), immutable] + │ └── assignment-cast: CHAR(24) [as=column9:30, outer=(21), immutable] │ └── column9:21 └── f-k-checks ├── f-k-checks-item: order_line(ol_w_id,ol_d_id,ol_o_id) -> order(o_w_id,o_d_id,o_id) │ └── anti-join (lookup order) - │ ├── columns: ol_w_id:25!null ol_d_id:26!null ol_o_id:27!null - │ ├── key columns: [25 26 27] = [30 29 28] + │ ├── columns: ol_w_id:32!null ol_d_id:33!null ol_o_id:34!null + │ ├── key columns: [32 33 34] = [37 36 35] │ ├── lookup columns are key │ ├── cardinality: [0 - 6] │ ├── with-scan &1 - │ │ ├── columns: ol_w_id:25!null ol_d_id:26!null ol_o_id:27!null + │ │ ├── columns: ol_w_id:32!null ol_d_id:33!null ol_o_id:34!null │ │ ├── mapping: - │ │ │ ├── column3:15 => ol_w_id:25 - │ │ │ ├── column2:14 => ol_d_id:26 - │ │ │ └── column1:13 => ol_o_id:27 + │ │ │ ├── column3:24 => ol_w_id:32 + │ │ │ ├── column2:23 => ol_d_id:33 + │ │ │ └── column1:22 => ol_o_id:34 │ │ └── cardinality: [6 - 6] │ └── filters (true) └── f-k-checks-item: order_line(ol_supply_w_id,ol_i_id) -> stock(s_w_id,s_i_id) └── anti-join (lookup stock) - ├── columns: ol_supply_w_id:38!null ol_i_id:39!null - ├── key columns: [38 39] = [41 40] + ├── columns: ol_supply_w_id:45!null ol_i_id:46!null + ├── key columns: [45 46] = [48 47] ├── lookup columns are key ├── cardinality: [0 - 6] ├── with-scan &1 - │ ├── columns: ol_supply_w_id:38!null ol_i_id:39!null + │ ├── columns: ol_supply_w_id:45!null ol_i_id:46!null │ ├── mapping: - │ │ ├── column6:18 => ol_supply_w_id:38 - │ │ └── column5:17 => ol_i_id:39 + │ │ ├── column6:27 => ol_supply_w_id:45 + │ │ └── column5:26 => ol_i_id:46 │ └── cardinality: [6 - 6] └── filters (true) @@ -606,71 +650,77 @@ VALUES insert history ├── columns: ├── insert-mapping: - │ ├── rowid_default:22 => rowid:1 - │ ├── column1:12 => history.h_c_id:2 - │ ├── column2:13 => history.h_c_d_id:3 - │ ├── column3:14 => history.h_c_w_id:4 - │ ├── column4:15 => history.h_d_id:5 - │ ├── column5:16 => history.h_w_id:6 - │ ├── column7:18 => h_date:7 - │ ├── column6:20 => h_amount:8 - │ └── column8:21 => h_data:9 + │ ├── rowid_default:28 => rowid:1 + │ ├── column1:20 => history.h_c_id:2 + │ ├── column2:21 => history.h_c_d_id:3 + │ ├── column3:22 => history.h_c_w_id:4 + │ ├── column4:23 => history.h_d_id:5 + │ ├── column5:24 => history.h_w_id:6 + │ ├── column7:26 => h_date:7 + │ ├── column6:25 => h_amount:8 + │ └── column8:27 => h_data:9 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── values - │ ├── columns: column1:12!null column2:13!null column3:14!null column4:15!null column5:16!null column7:18!null column6:20 column8:21 rowid_default:22 + │ ├── columns: column1:20 column2:21 column3:22 column4:23 column5:24 column6:25 column7:26 column8:27 rowid_default:28 │ ├── cardinality: [1 - 1] │ ├── volatile │ ├── key: () - │ ├── fd: ()-->(12-16,18,20-22) + │ ├── fd: ()-->(20-28) │ └── tuple - │ ├── 1343 - │ ├── 5 - │ ├── 10 - │ ├── 5 - │ ├── 10 - │ ├── '2019-08-26 16:50:41' + │ ├── assignment-cast: INT8 + │ │ └── 1343 + │ ├── assignment-cast: INT8 + │ │ └── 5 + │ ├── assignment-cast: INT8 + │ │ └── 10 + │ ├── assignment-cast: INT8 + │ │ └── 5 + │ ├── assignment-cast: INT8 + │ │ └── 10 │ ├── assignment-cast: DECIMAL(6,2) │ │ └── 3860.61 + │ ├── assignment-cast: TIMESTAMP + │ │ └── '2019-08-26 16:50:41' │ ├── assignment-cast: VARCHAR(24) │ │ └── '8 Kdcgphy3' │ └── gen_random_uuid() └── f-k-checks ├── f-k-checks-item: history(h_c_w_id,h_c_d_id,h_c_id) -> customer(c_w_id,c_d_id,c_id) │ └── anti-join (lookup customer) - │ ├── columns: h_c_w_id:23!null h_c_d_id:24!null h_c_id:25!null - │ ├── key columns: [23 24 25] = [28 27 26] + │ ├── columns: h_c_w_id:29 h_c_d_id:30 h_c_id:31 + │ ├── key columns: [29 30 31] = [34 33 32] │ ├── lookup columns are key │ ├── cardinality: [0 - 1] │ ├── key: () - │ ├── fd: ()-->(23-25) + │ ├── fd: ()-->(29-31) │ ├── with-scan &1 - │ │ ├── columns: h_c_w_id:23!null h_c_d_id:24!null h_c_id:25!null + │ │ ├── columns: h_c_w_id:29 h_c_d_id:30 h_c_id:31 │ │ ├── mapping: - │ │ │ ├── column3:14 => h_c_w_id:23 - │ │ │ ├── column2:13 => h_c_d_id:24 - │ │ │ └── column1:12 => h_c_id:25 + │ │ │ ├── column3:22 => h_c_w_id:29 + │ │ │ ├── column2:21 => h_c_d_id:30 + │ │ │ └── column1:20 => h_c_id:31 │ │ ├── cardinality: [1 - 1] │ │ ├── key: () - │ │ └── fd: ()-->(23-25) + │ │ └── fd: ()-->(29-31) │ └── filters (true) └── f-k-checks-item: history(h_w_id,h_d_id) -> district(d_w_id,d_id) └── anti-join (lookup district) - ├── columns: h_w_id:49!null h_d_id:50!null - ├── key columns: [49 50] = [52 51] + ├── columns: h_w_id:55 h_d_id:56 + ├── key columns: [55 56] = [58 57] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(49,50) + ├── fd: ()-->(55,56) ├── with-scan &1 - │ ├── columns: h_w_id:49!null h_d_id:50!null + │ ├── columns: h_w_id:55 h_d_id:56 │ ├── mapping: - │ │ ├── column5:16 => h_w_id:49 - │ │ └── column4:15 => h_d_id:50 + │ │ ├── column5:24 => h_w_id:55 + │ │ └── column4:23 => h_d_id:56 │ ├── cardinality: [1 - 1] │ ├── key: () - │ └── fd: ()-->(49,50) + │ └── fd: ()-->(55,56) └── filters (true) # -------------------------------------------------- diff --git a/pkg/sql/opt/xform/testdata/external/tpcc-no-stats b/pkg/sql/opt/xform/testdata/external/tpcc-no-stats index 9f10a492344a..99df429e1932 100644 --- a/pkg/sql/opt/xform/testdata/external/tpcc-no-stats +++ b/pkg/sql/opt/xform/testdata/external/tpcc-no-stats @@ -138,41 +138,64 @@ VALUES (100, 5, 10, 50, '2019-08-26 16:50:41', 10, 1) insert order ├── columns: ├── insert-mapping: - │ ├── column1:11 => o_id:1 - │ ├── column2:12 => "order".o_d_id:2 - │ ├── column3:13 => "order".o_w_id:3 - │ ├── column4:14 => "order".o_c_id:4 - │ ├── column5:15 => o_entry_d:5 - │ ├── o_carrier_id_default:18 => o_carrier_id:6 - │ ├── column6:16 => o_ol_cnt:7 - │ └── column7:17 => o_all_local:8 + │ ├── column1:18 => o_id:1 + │ ├── column2:19 => "order".o_d_id:2 + │ ├── column3:20 => "order".o_w_id:3 + │ ├── column4:21 => "order".o_c_id:4 + │ ├── column5:22 => o_entry_d:5 + │ ├── o_carrier_id_default:25 => o_carrier_id:6 + │ ├── column6:23 => o_ol_cnt:7 + │ └── column7:24 => o_all_local:8 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── values - │ ├── columns: column1:11!null column2:12!null column3:13!null column4:14!null column5:15!null column6:16!null column7:17!null o_carrier_id_default:18 + │ ├── columns: column1:18 column2:19 column3:20 column4:21 column5:22 column6:23 column7:24 o_carrier_id_default:25 │ ├── cardinality: [1 - 1] + │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(11-18) - │ └── (100, 5, 10, 50, '2019-08-26 16:50:41', 10, 1, NULL) + │ ├── fd: ()-->(18-25) + │ └── tuple + │ ├── assignment-cast: INT8 + │ │ └── 100 + │ ├── assignment-cast: INT8 + │ │ └── 5 + │ ├── assignment-cast: INT8 + │ │ └── 10 + │ ├── assignment-cast: INT8 + │ │ └── 50 + │ ├── assignment-cast: TIMESTAMP + │ │ └── '2019-08-26 16:50:41' + │ ├── assignment-cast: INT8 + │ │ └── 10 + │ ├── assignment-cast: INT8 + │ │ └── 1 + │ └── CAST(NULL AS INT8) └── f-k-checks └── f-k-checks-item: order(o_w_id,o_d_id,o_c_id) -> customer(c_w_id,c_d_id,c_id) └── anti-join (lookup customer) - ├── columns: o_w_id:19!null o_d_id:20!null o_c_id:21!null - ├── key columns: [19 20 21] = [24 23 22] + ├── columns: o_w_id:26 o_d_id:27 o_c_id:28!null + ├── key columns: [26 27 28] = [31 30 29] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(19-21) - ├── with-scan &1 - │ ├── columns: o_w_id:19!null o_d_id:20!null o_c_id:21!null - │ ├── mapping: - │ │ ├── column3:13 => o_w_id:19 - │ │ ├── column2:12 => o_d_id:20 - │ │ └── column4:14 => o_c_id:21 - │ ├── cardinality: [1 - 1] + ├── fd: ()-->(26-28) + ├── select + │ ├── columns: o_w_id:26 o_d_id:27 o_c_id:28!null + │ ├── cardinality: [0 - 1] │ ├── key: () - │ └── fd: ()-->(19-21) + │ ├── fd: ()-->(26-28) + │ ├── with-scan &1 + │ │ ├── columns: o_w_id:26 o_d_id:27 o_c_id:28 + │ │ ├── mapping: + │ │ │ ├── column3:20 => o_w_id:26 + │ │ │ ├── column2:19 => o_d_id:27 + │ │ │ └── column4:21 => o_c_id:28 + │ │ ├── cardinality: [1 - 1] + │ │ ├── key: () + │ │ └── fd: ()-->(26-28) + │ └── filters + │ └── o_c_id:28 IS NOT NULL [outer=(28), constraints=(/28: (/NULL - ]; tight)] └── filters (true) opt format=hide-qual @@ -181,36 +204,43 @@ INSERT INTO new_order (no_o_id, no_d_id, no_w_id) VALUES (2000, 100, 10) insert new_order ├── columns: ├── insert-mapping: - │ ├── column1:6 => new_order.no_o_id:1 - │ ├── column2:7 => new_order.no_d_id:2 - │ └── column3:8 => new_order.no_w_id:3 + │ ├── column1:9 => new_order.no_o_id:1 + │ ├── column2:10 => new_order.no_d_id:2 + │ └── column3:11 => new_order.no_w_id:3 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── values - │ ├── columns: column1:6!null column2:7!null column3:8!null + │ ├── columns: column1:9 column2:10 column3:11 │ ├── cardinality: [1 - 1] + │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(6-8) - │ └── (2000, 100, 10) + │ ├── fd: ()-->(9-11) + │ └── tuple + │ ├── assignment-cast: INT8 + │ │ └── 2000 + │ ├── assignment-cast: INT8 + │ │ └── 100 + │ └── assignment-cast: INT8 + │ └── 10 └── f-k-checks └── f-k-checks-item: new_order(no_w_id,no_d_id,no_o_id) -> order(o_w_id,o_d_id,o_id) └── anti-join (lookup order) - ├── columns: no_w_id:9!null no_d_id:10!null no_o_id:11!null - ├── key columns: [9 10 11] = [14 13 12] + ├── columns: no_w_id:12 no_d_id:13 no_o_id:14 + ├── key columns: [12 13 14] = [17 16 15] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(9-11) + ├── fd: ()-->(12-14) ├── with-scan &1 - │ ├── columns: no_w_id:9!null no_d_id:10!null no_o_id:11!null + │ ├── columns: no_w_id:12 no_d_id:13 no_o_id:14 │ ├── mapping: - │ │ ├── column3:8 => no_w_id:9 - │ │ ├── column2:7 => no_d_id:10 - │ │ └── column1:6 => no_o_id:11 + │ │ ├── column3:11 => no_w_id:12 + │ │ ├── column2:10 => no_d_id:13 + │ │ └── column1:9 => no_o_id:14 │ ├── cardinality: [1 - 1] │ ├── key: () - │ └── fd: ()-->(9-11) + │ └── fd: ()-->(12-14) └── filters (true) opt format=hide-qual @@ -355,24 +385,24 @@ VALUES insert order_line ├── columns: ├── insert-mapping: - │ ├── column1:13 => order_line.ol_o_id:1 - │ ├── column2:14 => order_line.ol_d_id:2 - │ ├── column3:15 => order_line.ol_w_id:3 - │ ├── column4:16 => ol_number:4 - │ ├── column5:17 => order_line.ol_i_id:5 - │ ├── column6:18 => order_line.ol_supply_w_id:6 - │ ├── ol_delivery_d_default:24 => ol_delivery_d:7 - │ ├── column7:19 => ol_quantity:8 - │ ├── column8:22 => ol_amount:9 - │ └── column9:23 => ol_dist_info:10 + │ ├── column1:22 => order_line.ol_o_id:1 + │ ├── column2:23 => order_line.ol_d_id:2 + │ ├── column3:24 => order_line.ol_w_id:3 + │ ├── column4:25 => ol_number:4 + │ ├── column5:26 => order_line.ol_i_id:5 + │ ├── column6:27 => order_line.ol_supply_w_id:6 + │ ├── ol_delivery_d_default:31 => ol_delivery_d:7 + │ ├── column7:28 => ol_quantity:8 + │ ├── column8:29 => ol_amount:9 + │ └── column9:30 => ol_dist_info:10 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── project - │ ├── columns: ol_delivery_d_default:24 column8:22 column9:23 column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null column6:18!null column7:19!null + │ ├── columns: ol_delivery_d_default:31 column1:22!null column2:23!null column3:24!null column4:25!null column5:26!null column6:27!null column7:28!null column8:29!null column9:30!null │ ├── cardinality: [6 - 6] │ ├── immutable - │ ├── fd: ()-->(24) + │ ├── fd: ()-->(31) │ ├── values │ │ ├── columns: column1:13!null column2:14!null column3:15!null column4:16!null column5:17!null column6:18!null column7:19!null column8:20!null column9:21!null │ │ ├── cardinality: [6 - 6] @@ -383,37 +413,51 @@ insert order_line │ │ ├── (3045, 2, 10, 4, 56624, 0, 6, 273.360000, 'RsaCXoEzmssaF9m9cdLXe0Yh') │ │ └── (3045, 2, 10, 6, 92966, 0, 4, 366.760000, 'saCXoEzmssaF9m9cdLXe0Yhg') │ └── projections - │ ├── CAST(NULL AS TIMESTAMP) [as=ol_delivery_d_default:24] - │ ├── assignment-cast: DECIMAL(6,2) [as=column8:22, outer=(20), immutable] + │ ├── CAST(NULL AS TIMESTAMP) [as=ol_delivery_d_default:31] + │ ├── assignment-cast: INT8 [as=column1:22, outer=(13), immutable] + │ │ └── column1:13 + │ ├── assignment-cast: INT8 [as=column2:23, outer=(14), immutable] + │ │ └── column2:14 + │ ├── assignment-cast: INT8 [as=column3:24, outer=(15), immutable] + │ │ └── column3:15 + │ ├── assignment-cast: INT8 [as=column4:25, outer=(16), immutable] + │ │ └── column4:16 + │ ├── assignment-cast: INT8 [as=column5:26, outer=(17), immutable] + │ │ └── column5:17 + │ ├── assignment-cast: INT8 [as=column6:27, outer=(18), immutable] + │ │ └── column6:18 + │ ├── assignment-cast: INT8 [as=column7:28, outer=(19), immutable] + │ │ └── column7:19 + │ ├── assignment-cast: DECIMAL(6,2) [as=column8:29, outer=(20), immutable] │ │ └── column8:20 - │ └── assignment-cast: CHAR(24) [as=column9:23, outer=(21), immutable] + │ └── assignment-cast: CHAR(24) [as=column9:30, outer=(21), immutable] │ └── column9:21 └── f-k-checks ├── f-k-checks-item: order_line(ol_w_id,ol_d_id,ol_o_id) -> order(o_w_id,o_d_id,o_id) │ └── anti-join (lookup order) - │ ├── columns: ol_w_id:25!null ol_d_id:26!null ol_o_id:27!null - │ ├── key columns: [25 26 27] = [30 29 28] + │ ├── columns: ol_w_id:32!null ol_d_id:33!null ol_o_id:34!null + │ ├── key columns: [32 33 34] = [37 36 35] │ ├── lookup columns are key │ ├── cardinality: [0 - 6] │ ├── with-scan &1 - │ │ ├── columns: ol_w_id:25!null ol_d_id:26!null ol_o_id:27!null + │ │ ├── columns: ol_w_id:32!null ol_d_id:33!null ol_o_id:34!null │ │ ├── mapping: - │ │ │ ├── column3:15 => ol_w_id:25 - │ │ │ ├── column2:14 => ol_d_id:26 - │ │ │ └── column1:13 => ol_o_id:27 + │ │ │ ├── column3:24 => ol_w_id:32 + │ │ │ ├── column2:23 => ol_d_id:33 + │ │ │ └── column1:22 => ol_o_id:34 │ │ └── cardinality: [6 - 6] │ └── filters (true) └── f-k-checks-item: order_line(ol_supply_w_id,ol_i_id) -> stock(s_w_id,s_i_id) └── anti-join (lookup stock) - ├── columns: ol_supply_w_id:38!null ol_i_id:39!null - ├── key columns: [38 39] = [41 40] + ├── columns: ol_supply_w_id:45!null ol_i_id:46!null + ├── key columns: [45 46] = [48 47] ├── lookup columns are key ├── cardinality: [0 - 6] ├── with-scan &1 - │ ├── columns: ol_supply_w_id:38!null ol_i_id:39!null + │ ├── columns: ol_supply_w_id:45!null ol_i_id:46!null │ ├── mapping: - │ │ ├── column6:18 => ol_supply_w_id:38 - │ │ └── column5:17 => ol_i_id:39 + │ │ ├── column6:27 => ol_supply_w_id:45 + │ │ └── column5:26 => ol_i_id:46 │ └── cardinality: [6 - 6] └── filters (true) @@ -600,71 +644,77 @@ VALUES insert history ├── columns: ├── insert-mapping: - │ ├── rowid_default:22 => rowid:1 - │ ├── column1:12 => history.h_c_id:2 - │ ├── column2:13 => history.h_c_d_id:3 - │ ├── column3:14 => history.h_c_w_id:4 - │ ├── column4:15 => history.h_d_id:5 - │ ├── column5:16 => history.h_w_id:6 - │ ├── column7:18 => h_date:7 - │ ├── column6:20 => h_amount:8 - │ └── column8:21 => h_data:9 + │ ├── rowid_default:28 => rowid:1 + │ ├── column1:20 => history.h_c_id:2 + │ ├── column2:21 => history.h_c_d_id:3 + │ ├── column3:22 => history.h_c_w_id:4 + │ ├── column4:23 => history.h_d_id:5 + │ ├── column5:24 => history.h_w_id:6 + │ ├── column7:26 => h_date:7 + │ ├── column6:25 => h_amount:8 + │ └── column8:27 => h_data:9 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── values - │ ├── columns: column1:12!null column2:13!null column3:14!null column4:15!null column5:16!null column7:18!null column6:20 column8:21 rowid_default:22 + │ ├── columns: column1:20 column2:21 column3:22 column4:23 column5:24 column6:25 column7:26 column8:27 rowid_default:28 │ ├── cardinality: [1 - 1] │ ├── volatile │ ├── key: () - │ ├── fd: ()-->(12-16,18,20-22) + │ ├── fd: ()-->(20-28) │ └── tuple - │ ├── 1343 - │ ├── 5 - │ ├── 10 - │ ├── 5 - │ ├── 10 - │ ├── '2019-08-26 16:50:41' + │ ├── assignment-cast: INT8 + │ │ └── 1343 + │ ├── assignment-cast: INT8 + │ │ └── 5 + │ ├── assignment-cast: INT8 + │ │ └── 10 + │ ├── assignment-cast: INT8 + │ │ └── 5 + │ ├── assignment-cast: INT8 + │ │ └── 10 │ ├── assignment-cast: DECIMAL(6,2) │ │ └── 3860.61 + │ ├── assignment-cast: TIMESTAMP + │ │ └── '2019-08-26 16:50:41' │ ├── assignment-cast: VARCHAR(24) │ │ └── '8 Kdcgphy3' │ └── gen_random_uuid() └── f-k-checks ├── f-k-checks-item: history(h_c_w_id,h_c_d_id,h_c_id) -> customer(c_w_id,c_d_id,c_id) │ └── anti-join (lookup customer) - │ ├── columns: h_c_w_id:23!null h_c_d_id:24!null h_c_id:25!null - │ ├── key columns: [23 24 25] = [28 27 26] + │ ├── columns: h_c_w_id:29 h_c_d_id:30 h_c_id:31 + │ ├── key columns: [29 30 31] = [34 33 32] │ ├── lookup columns are key │ ├── cardinality: [0 - 1] │ ├── key: () - │ ├── fd: ()-->(23-25) + │ ├── fd: ()-->(29-31) │ ├── with-scan &1 - │ │ ├── columns: h_c_w_id:23!null h_c_d_id:24!null h_c_id:25!null + │ │ ├── columns: h_c_w_id:29 h_c_d_id:30 h_c_id:31 │ │ ├── mapping: - │ │ │ ├── column3:14 => h_c_w_id:23 - │ │ │ ├── column2:13 => h_c_d_id:24 - │ │ │ └── column1:12 => h_c_id:25 + │ │ │ ├── column3:22 => h_c_w_id:29 + │ │ │ ├── column2:21 => h_c_d_id:30 + │ │ │ └── column1:20 => h_c_id:31 │ │ ├── cardinality: [1 - 1] │ │ ├── key: () - │ │ └── fd: ()-->(23-25) + │ │ └── fd: ()-->(29-31) │ └── filters (true) └── f-k-checks-item: history(h_w_id,h_d_id) -> district(d_w_id,d_id) └── anti-join (lookup district) - ├── columns: h_w_id:49!null h_d_id:50!null - ├── key columns: [49 50] = [52 51] + ├── columns: h_w_id:55 h_d_id:56 + ├── key columns: [55 56] = [58 57] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(49,50) + ├── fd: ()-->(55,56) ├── with-scan &1 - │ ├── columns: h_w_id:49!null h_d_id:50!null + │ ├── columns: h_w_id:55 h_d_id:56 │ ├── mapping: - │ │ ├── column5:16 => h_w_id:49 - │ │ └── column4:15 => h_d_id:50 + │ │ ├── column5:24 => h_w_id:55 + │ │ └── column4:23 => h_d_id:56 │ ├── cardinality: [1 - 1] │ ├── key: () - │ └── fd: ()-->(49,50) + │ └── fd: ()-->(55,56) └── filters (true) # -------------------------------------------------- diff --git a/pkg/sql/opt/xform/testdata/external/tpce b/pkg/sql/opt/xform/testdata/external/tpce index 538970abe435..93b30f610894 100644 --- a/pkg/sql/opt/xform/testdata/external/tpce +++ b/pkg/sql/opt/xform/testdata/external/tpce @@ -552,10 +552,10 @@ update_trade_submitted AS ( SELECT * FROM request_list; ---- with &2 (update_last_trade) - ├── columns: tr_t_id:138!null tr_bid_price:139!null tr_tt_id:140!null tr_qty:141!null + ├── columns: tr_t_id:140!null tr_bid_price:141!null tr_tt_id:142!null tr_qty:143!null ├── volatile, mutations - ├── key: (138) - ├── fd: (138)-->(139-141) + ├── key: (140) + ├── fd: (140)-->(141-143) ├── project │ ├── columns: "?column?":19 │ ├── cardinality: [0 - 1] @@ -592,10 +592,10 @@ with &2 (update_last_trade) │ └── projections │ └── NULL [as="?column?":19] └── with &3 (request_list) - ├── columns: tr_t_id:138!null tr_bid_price:139!null tr_tt_id:140!null tr_qty:141!null + ├── columns: tr_t_id:140!null tr_bid_price:141!null tr_tt_id:142!null tr_qty:143!null ├── volatile, mutations - ├── key: (138) - ├── fd: (138)-->(139-141) + ├── key: (140) + ├── fd: (140)-->(141-143) ├── project │ ├── columns: tr_bid_price:28!null trade_request.tr_t_id:20!null trade_request.tr_tt_id:21!null trade_request.tr_qty:23!null │ ├── immutable @@ -622,10 +622,10 @@ with &2 (update_last_trade) │ └── projections │ └── trade_request.tr_bid_price:24::FLOAT8 [as=tr_bid_price:28, outer=(24), immutable] └── with &4 (delete_trade_request) - ├── columns: tr_t_id:138!null tr_bid_price:139!null tr_tt_id:140!null tr_qty:141!null + ├── columns: tr_t_id:140!null tr_bid_price:141!null tr_tt_id:142!null tr_qty:143!null ├── volatile, mutations - ├── key: (138) - ├── fd: (138)-->(139-141) + ├── key: (140) + ├── fd: (140)-->(141-143) ├── project │ ├── columns: "?column?":50 │ ├── volatile, mutations @@ -661,130 +661,129 @@ with &2 (update_last_trade) │ └── projections │ └── NULL [as="?column?":50] └── with &6 (insert_trade_history) - ├── columns: tr_t_id:138!null tr_bid_price:139!null tr_tt_id:140!null tr_qty:141!null + ├── columns: tr_t_id:140!null tr_bid_price:141!null tr_tt_id:142!null tr_qty:143!null ├── volatile, mutations - ├── key: (138) - ├── fd: (138)-->(139-141) + ├── key: (140) + ├── fd: (140)-->(141-143) ├── project - │ ├── columns: "?column?":86 + │ ├── columns: "?column?":88 │ ├── volatile, mutations - │ ├── fd: ()-->(86) + │ ├── fd: ()-->(88) │ ├── insert trade_history │ │ ├── columns: trade_history.th_t_id:51!null trade_history.th_st_id:53!null │ │ ├── insert-mapping: - │ │ │ ├── tr_t_id:56 => trade_history.th_t_id:51 - │ │ │ ├── timestamp:61 => th_dts:52 - │ │ │ └── "?column?":62 => trade_history.th_st_id:53 + │ │ │ ├── tr_t_id:62 => trade_history.th_t_id:51 + │ │ │ ├── timestamp:64 => th_dts:52 + │ │ │ └── "?column?":63 => trade_history.th_st_id:53 │ │ ├── input binding: &5 │ │ ├── volatile, mutations - │ │ ├── key: (51) │ │ ├── fd: ()-->(53) │ │ ├── project - │ │ │ ├── columns: "?column?":62 timestamp:61!null tr_t_id:56!null + │ │ │ ├── columns: tr_t_id:62!null "?column?":63!null timestamp:64!null │ │ │ ├── immutable - │ │ │ ├── key: (56) - │ │ │ ├── fd: ()-->(61,62) + │ │ │ ├── fd: ()-->(63,64) │ │ │ ├── with-scan &3 (request_list) │ │ │ │ ├── columns: tr_t_id:56!null │ │ │ │ ├── mapping: │ │ │ │ │ └── trade_request.tr_t_id:20 => tr_t_id:56 │ │ │ │ └── key: (56) │ │ │ └── projections - │ │ │ ├── assignment-cast: VARCHAR(4) [as="?column?":62, immutable] + │ │ │ ├── assignment-cast: INT8 [as=tr_t_id:62, outer=(56), immutable] + │ │ │ │ └── tr_t_id:56 + │ │ │ ├── assignment-cast: VARCHAR(4) [as="?column?":63, immutable] │ │ │ │ └── 'SBMT' - │ │ │ └── '2020-06-15 22:27:42.148484' [as=timestamp:61] + │ │ │ └── assignment-cast: TIMESTAMP [as=timestamp:64, immutable] + │ │ │ └── '2020-06-15 22:27:42.148484' │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade_history(th_t_id) -> trade(t_id) │ │ │ └── anti-join (lookup trade) - │ │ │ ├── columns: th_t_id:63!null - │ │ │ ├── key columns: [63] = [64] + │ │ │ ├── columns: th_t_id:65!null + │ │ │ ├── key columns: [65] = [66] │ │ │ ├── lookup columns are key - │ │ │ ├── key: (63) │ │ │ ├── with-scan &5 - │ │ │ │ ├── columns: th_t_id:63!null - │ │ │ │ ├── mapping: - │ │ │ │ │ └── tr_t_id:56 => th_t_id:63 - │ │ │ │ └── key: (63) + │ │ │ │ ├── columns: th_t_id:65!null + │ │ │ │ └── mapping: + │ │ │ │ └── tr_t_id:62 => th_t_id:65 │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade_history(th_st_id) -> status_type(st_id) │ │ └── anti-join (lookup status_type) - │ │ ├── columns: th_st_id:81 - │ │ ├── key columns: [81] = [82] + │ │ ├── columns: th_st_id:83!null + │ │ ├── key columns: [83] = [84] │ │ ├── lookup columns are key - │ │ ├── fd: ()-->(81) + │ │ ├── fd: ()-->(83) │ │ ├── with-scan &5 - │ │ │ ├── columns: th_st_id:81 + │ │ │ ├── columns: th_st_id:83!null │ │ │ ├── mapping: - │ │ │ │ └── "?column?":62 => th_st_id:81 - │ │ │ └── fd: ()-->(81) + │ │ │ │ └── "?column?":63 => th_st_id:83 + │ │ │ └── fd: ()-->(83) │ │ └── filters (true) │ └── projections - │ └── NULL [as="?column?":86] + │ └── NULL [as="?column?":88] └── with &8 (update_trade_submitted) - ├── columns: tr_t_id:138!null tr_bid_price:139!null tr_tt_id:140!null tr_qty:141!null + ├── columns: tr_t_id:140!null tr_bid_price:141!null tr_tt_id:142!null tr_qty:143!null ├── volatile, mutations - ├── key: (138) - ├── fd: (138)-->(139-141) + ├── key: (140) + ├── fd: (140)-->(141-143) ├── project - │ ├── columns: "?column?":137 + │ ├── columns: "?column?":139 │ ├── volatile, mutations - │ ├── fd: ()-->(137) + │ ├── fd: ()-->(139) │ ├── update trade - │ │ ├── columns: t_id:87!null - │ │ ├── fetch columns: t_id:104 t_dts:105 trade.t_st_id:106 t_tt_id:107 t_is_cash:108 t_s_symb:109 t_qty:110 t_bid_price:111 t_ca_id:112 t_exec_name:113 t_trade_price:114 t_chrg:115 t_comm:116 t_lifo:118 + │ │ ├── columns: t_id:89!null + │ │ ├── fetch columns: t_id:106 t_dts:107 trade.t_st_id:108 t_tt_id:109 t_is_cash:110 t_s_symb:111 t_qty:112 t_bid_price:113 t_ca_id:114 t_exec_name:115 t_trade_price:116 t_chrg:117 t_comm:118 t_lifo:120 │ │ ├── update-mapping: - │ │ │ ├── t_dts_new:126 => t_dts:88 - │ │ │ └── t_st_id_new:125 => trade.t_st_id:89 + │ │ │ ├── t_dts_new:128 => t_dts:90 + │ │ │ └── t_st_id_new:127 => trade.t_st_id:91 │ │ ├── input binding: &7 │ │ ├── volatile, mutations - │ │ ├── key: (87) + │ │ ├── key: (89) │ │ ├── project - │ │ │ ├── columns: t_st_id_new:125!null t_dts_new:126!null t_id:104!null t_dts:105!null trade.t_st_id:106!null t_tt_id:107!null t_is_cash:108!null t_s_symb:109!null t_qty:110!null t_bid_price:111!null t_ca_id:112!null t_exec_name:113!null t_trade_price:114 t_chrg:115!null t_comm:116!null t_lifo:118!null - │ │ │ ├── key: (104) - │ │ │ ├── fd: ()-->(125,126), (104)-->(105-116,118) + │ │ │ ├── columns: t_st_id_new:127!null t_dts_new:128!null t_id:106!null t_dts:107!null trade.t_st_id:108!null t_tt_id:109!null t_is_cash:110!null t_s_symb:111!null t_qty:112!null t_bid_price:113!null t_ca_id:114!null t_exec_name:115!null t_trade_price:116 t_chrg:117!null t_comm:118!null t_lifo:120!null + │ │ │ ├── key: (106) + │ │ │ ├── fd: ()-->(127,128), (106)-->(107-118,120) │ │ │ ├── project - │ │ │ │ ├── columns: t_id:104!null t_dts:105!null trade.t_st_id:106!null t_tt_id:107!null t_is_cash:108!null t_s_symb:109!null t_qty:110!null t_bid_price:111!null t_ca_id:112!null t_exec_name:113!null t_trade_price:114 t_chrg:115!null t_comm:116!null t_lifo:118!null - │ │ │ │ ├── key: (104) - │ │ │ │ ├── fd: (104)-->(105-116,118) + │ │ │ │ ├── columns: t_id:106!null t_dts:107!null trade.t_st_id:108!null t_tt_id:109!null t_is_cash:110!null t_s_symb:111!null t_qty:112!null t_bid_price:113!null t_ca_id:114!null t_exec_name:115!null t_trade_price:116 t_chrg:117!null t_comm:118!null t_lifo:120!null + │ │ │ │ ├── key: (106) + │ │ │ │ ├── fd: (106)-->(107-118,120) │ │ │ │ └── inner-join (lookup trade) - │ │ │ │ ├── columns: t_id:104!null t_dts:105!null trade.t_st_id:106!null t_tt_id:107!null t_is_cash:108!null t_s_symb:109!null t_qty:110!null t_bid_price:111!null t_ca_id:112!null t_exec_name:113!null t_trade_price:114 t_chrg:115!null t_comm:116!null t_lifo:118!null tr_t_id:121!null - │ │ │ │ ├── key columns: [121] = [104] + │ │ │ │ ├── columns: t_id:106!null t_dts:107!null trade.t_st_id:108!null t_tt_id:109!null t_is_cash:110!null t_s_symb:111!null t_qty:112!null t_bid_price:113!null t_ca_id:114!null t_exec_name:115!null t_trade_price:116 t_chrg:117!null t_comm:118!null t_lifo:120!null tr_t_id:123!null + │ │ │ │ ├── key columns: [123] = [106] │ │ │ │ ├── lookup columns are key - │ │ │ │ ├── key: (121) - │ │ │ │ ├── fd: (104)-->(105-116,118), (104)==(121), (121)==(104) + │ │ │ │ ├── key: (123) + │ │ │ │ ├── fd: (106)-->(107-118,120), (106)==(123), (123)==(106) │ │ │ │ ├── with-scan &3 (request_list) - │ │ │ │ │ ├── columns: tr_t_id:121!null + │ │ │ │ │ ├── columns: tr_t_id:123!null │ │ │ │ │ ├── mapping: - │ │ │ │ │ │ └── trade_request.tr_t_id:20 => tr_t_id:121 - │ │ │ │ │ └── key: (121) + │ │ │ │ │ │ └── trade_request.tr_t_id:20 => tr_t_id:123 + │ │ │ │ │ └── key: (123) │ │ │ │ └── filters (true) │ │ │ └── projections - │ │ │ ├── 'SBMT' [as=t_st_id_new:125] - │ │ │ └── '2020-06-15 22:27:42.148484' [as=t_dts_new:126] + │ │ │ ├── 'SBMT' [as=t_st_id_new:127] + │ │ │ └── '2020-06-15 22:27:42.148484' [as=t_dts_new:128] │ │ └── f-k-checks │ │ └── f-k-checks-item: trade(t_st_id) -> status_type(st_id) │ │ └── anti-join (lookup status_type) - │ │ ├── columns: t_st_id:132!null - │ │ ├── key columns: [132] = [133] + │ │ ├── columns: t_st_id:134!null + │ │ ├── key columns: [134] = [135] │ │ ├── lookup columns are key - │ │ ├── fd: ()-->(132) + │ │ ├── fd: ()-->(134) │ │ ├── with-scan &7 - │ │ │ ├── columns: t_st_id:132!null + │ │ │ ├── columns: t_st_id:134!null │ │ │ ├── mapping: - │ │ │ │ └── t_st_id_new:125 => t_st_id:132 - │ │ │ └── fd: ()-->(132) + │ │ │ │ └── t_st_id_new:127 => t_st_id:134 + │ │ │ └── fd: ()-->(134) │ │ └── filters (true) │ └── projections - │ └── NULL [as="?column?":137] + │ └── NULL [as="?column?":139] └── with-scan &3 (request_list) - ├── columns: tr_t_id:138!null tr_bid_price:139!null tr_tt_id:140!null tr_qty:141!null + ├── columns: tr_t_id:140!null tr_bid_price:141!null tr_tt_id:142!null tr_qty:143!null ├── mapping: - │ ├── trade_request.tr_t_id:20 => tr_t_id:138 - │ ├── tr_bid_price:28 => tr_bid_price:139 - │ ├── trade_request.tr_tt_id:21 => tr_tt_id:140 - │ └── trade_request.tr_qty:23 => tr_qty:141 - ├── key: (138) - └── fd: (138)-->(139-141) + │ ├── trade_request.tr_t_id:20 => tr_t_id:140 + │ ├── tr_bid_price:28 => tr_bid_price:141 + │ ├── trade_request.tr_tt_id:21 => tr_tt_id:142 + │ └── trade_request.tr_qty:23 => tr_qty:143 + ├── key: (140) + └── fd: (140)-->(141-143) # -------------------------------------------------- # T4 @@ -2923,225 +2922,233 @@ insert_trade_history AS ( SELECT 1; ---- with &2 (insert_trade) - ├── columns: "?column?":121!null + ├── columns: "?column?":129!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(121) + ├── fd: ()-->(129) ├── project - │ ├── columns: "?column?":87!null + │ ├── columns: "?column?":93!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(87) + │ ├── fd: ()-->(93) │ ├── insert trade │ │ ├── columns: t_id:1!null │ │ ├── insert-mapping: - │ │ │ ├── column1:18 => t_id:1 - │ │ │ ├── column2:19 => t_dts:2 - │ │ │ ├── column3:33 => trade.t_st_id:3 - │ │ │ ├── column4:34 => trade.t_tt_id:4 - │ │ │ ├── column5:22 => t_is_cash:5 - │ │ │ ├── column6:35 => trade.t_s_symb:6 - │ │ │ ├── column7:36 => t_qty:7 - │ │ │ ├── column8:37 => t_bid_price:8 - │ │ │ ├── column9:26 => trade.t_ca_id:9 - │ │ │ ├── column10:38 => t_exec_name:10 - │ │ │ ├── column11:28 => t_trade_price:11 - │ │ │ ├── column12:39 => t_chrg:12 - │ │ │ ├── column13:40 => t_comm:13 - │ │ │ ├── column14:41 => t_tax:14 - │ │ │ └── column15:32 => t_lifo:15 - │ │ ├── check columns: check1:42 check2:43 check3:44 check4:45 check5:46 + │ │ │ ├── column1:33 => t_id:1 + │ │ │ ├── column2:34 => t_dts:2 + │ │ │ ├── column3:35 => trade.t_st_id:3 + │ │ │ ├── column4:36 => trade.t_tt_id:4 + │ │ │ ├── column5:37 => t_is_cash:5 + │ │ │ ├── column6:38 => trade.t_s_symb:6 + │ │ │ ├── column7:39 => t_qty:7 + │ │ │ ├── column8:40 => t_bid_price:8 + │ │ │ ├── column9:41 => trade.t_ca_id:9 + │ │ │ ├── column10:42 => t_exec_name:10 + │ │ │ ├── column11:43 => t_trade_price:11 + │ │ │ ├── column12:44 => t_chrg:12 + │ │ │ ├── column13:45 => t_comm:13 + │ │ │ ├── column14:46 => t_tax:14 + │ │ │ └── column15:47 => t_lifo:15 + │ │ ├── check columns: check1:48 check2:49 check3:50 check4:51 check5:52 │ │ ├── input binding: &1 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () │ │ ├── fd: ()-->(1) │ │ ├── project - │ │ │ ├── columns: check1:42 check2:43 check3:44 check4:45 check5:46 column1:18!null column2:19!null column5:22!null column9:26!null column11:28 column15:32!null column3:33 column4:34 column6:35 column7:36 column8:37 column10:38 column12:39 column13:40 column14:41 + │ │ │ ├── columns: check1:48 check2:49 check3:50 check4:51 check5:52 column1:33 column2:34 column3:35 column4:36 column5:37 column6:38 column7:39 column8:40 column9:41 column10:42 column11:43 column12:44 column13:45 column14:46 column15:47 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(18,19,22,26,28,32-46) + │ │ │ ├── fd: ()-->(33-52) │ │ │ ├── values - │ │ │ │ ├── columns: column1:18!null column2:19!null column5:22!null column9:26!null column11:28 column15:32!null column3:33 column4:34 column6:35 column7:36 column8:37 column10:38 column12:39 column13:40 column14:41 + │ │ │ │ ├── columns: column1:33 column2:34 column3:35 column4:36 column5:37 column6:38 column7:39 column8:40 column9:41 column10:42 column11:43 column12:44 column13:45 column14:46 column15:47 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── immutable │ │ │ │ ├── key: () - │ │ │ │ ├── fd: ()-->(18,19,22,26,28,32-41) + │ │ │ │ ├── fd: ()-->(33-47) │ │ │ │ └── tuple - │ │ │ │ ├── 0 - │ │ │ │ ├── '2020-06-17 22:27:42.148484' - │ │ │ │ ├── true - │ │ │ │ ├── 0 - │ │ │ │ ├── CAST(NULL AS DECIMAL(8,2)) - │ │ │ │ ├── true + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 0 + │ │ │ │ ├── assignment-cast: TIMESTAMP + │ │ │ │ │ └── '2020-06-17 22:27:42.148484' │ │ │ │ ├── assignment-cast: VARCHAR(4) │ │ │ │ │ └── 'SBMT' │ │ │ │ ├── assignment-cast: VARCHAR(3) │ │ │ │ │ └── 'TMB' + │ │ │ │ ├── assignment-cast: BOOL + │ │ │ │ │ └── true │ │ │ │ ├── assignment-cast: VARCHAR(15) │ │ │ │ │ └── 'SYMB' │ │ │ │ ├── assignment-cast: INT4 │ │ │ │ │ └── 10 │ │ │ │ ├── assignment-cast: DECIMAL(8,2) │ │ │ │ │ └── 1E+2 + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 0 │ │ │ │ ├── assignment-cast: VARCHAR(49) │ │ │ │ │ └── 'Name' + │ │ │ │ ├── assignment-cast: DECIMAL(8,2) + │ │ │ │ │ └── CAST(NULL AS DECIMAL(8,2)) │ │ │ │ ├── assignment-cast: DECIMAL(10,2) │ │ │ │ │ └── 1 │ │ │ │ ├── assignment-cast: DECIMAL(10,2) │ │ │ │ │ └── 0 - │ │ │ │ └── assignment-cast: DECIMAL(10,2) - │ │ │ │ └── 0 + │ │ │ │ ├── assignment-cast: DECIMAL(10,2) + │ │ │ │ │ └── 0 + │ │ │ │ └── assignment-cast: BOOL + │ │ │ │ └── true │ │ │ └── projections - │ │ │ ├── column7:36 > 0 [as=check1:42, outer=(36)] - │ │ │ ├── column8:37 > 0 [as=check2:43, outer=(37), immutable] - │ │ │ ├── column12:39 >= 0 [as=check3:44, outer=(39), immutable] - │ │ │ ├── column13:40 >= 0 [as=check4:45, outer=(40), immutable] - │ │ │ └── column14:41 >= 0 [as=check5:46, outer=(41), immutable] + │ │ │ ├── column7:39 > 0 [as=check1:48, outer=(39)] + │ │ │ ├── column8:40 > 0 [as=check2:49, outer=(40), immutable] + │ │ │ ├── column12:44 >= 0 [as=check3:50, outer=(44), immutable] + │ │ │ ├── column13:45 >= 0 [as=check4:51, outer=(45), immutable] + │ │ │ └── column14:46 >= 0 [as=check5:52, outer=(46), immutable] │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade(t_st_id) -> status_type(st_id) │ │ │ └── anti-join (lookup status_type) - │ │ │ ├── columns: t_st_id:47 - │ │ │ ├── key columns: [47] = [48] + │ │ │ ├── columns: t_st_id:53 + │ │ │ ├── key columns: [53] = [54] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(47) + │ │ │ ├── fd: ()-->(53) │ │ │ ├── with-scan &1 - │ │ │ │ ├── columns: t_st_id:47 + │ │ │ │ ├── columns: t_st_id:53 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column3:33 => t_st_id:47 + │ │ │ │ │ └── column3:35 => t_st_id:53 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(47) + │ │ │ │ └── fd: ()-->(53) │ │ │ └── filters (true) │ │ ├── f-k-checks-item: trade(t_tt_id) -> trade_type(tt_id) │ │ │ └── anti-join (lookup trade_type) - │ │ │ ├── columns: t_tt_id:52 - │ │ │ ├── key columns: [52] = [53] + │ │ │ ├── columns: t_tt_id:58 + │ │ │ ├── key columns: [58] = [59] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(52) + │ │ │ ├── fd: ()-->(58) │ │ │ ├── with-scan &1 - │ │ │ │ ├── columns: t_tt_id:52 + │ │ │ │ ├── columns: t_tt_id:58 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column4:34 => t_tt_id:52 + │ │ │ │ │ └── column4:36 => t_tt_id:58 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(52) + │ │ │ │ └── fd: ()-->(58) │ │ │ └── filters (true) │ │ ├── f-k-checks-item: trade(t_s_symb) -> security(s_symb) │ │ │ └── anti-join (lookup security) - │ │ │ ├── columns: t_s_symb:59 - │ │ │ ├── key columns: [59] = [60] + │ │ │ ├── columns: t_s_symb:65 + │ │ │ ├── key columns: [65] = [66] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(59) + │ │ │ ├── fd: ()-->(65) │ │ │ ├── with-scan &1 - │ │ │ │ ├── columns: t_s_symb:59 + │ │ │ │ ├── columns: t_s_symb:65 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column6:35 => t_s_symb:59 + │ │ │ │ │ └── column6:38 => t_s_symb:65 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(59) + │ │ │ │ └── fd: ()-->(65) │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade(t_ca_id) -> customer_account(ca_id) │ │ └── anti-join (lookup customer_account) - │ │ ├── columns: t_ca_id:78!null - │ │ ├── key columns: [78] = [79] + │ │ ├── columns: t_ca_id:84 + │ │ ├── key columns: [84] = [85] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(78) + │ │ ├── fd: ()-->(84) │ │ ├── with-scan &1 - │ │ │ ├── columns: t_ca_id:78!null + │ │ │ ├── columns: t_ca_id:84 │ │ │ ├── mapping: - │ │ │ │ └── column9:26 => t_ca_id:78 + │ │ │ │ └── column9:41 => t_ca_id:84 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(78) + │ │ │ └── fd: ()-->(84) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":87] + │ └── 1 [as="?column?":93] └── with &4 (insert_trade_history) - ├── columns: "?column?":121!null + ├── columns: "?column?":129!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(121) + ├── fd: ()-->(129) ├── project - │ ├── columns: "?column?":120!null + │ ├── columns: "?column?":128!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(120) + │ ├── fd: ()-->(128) │ ├── insert trade_history - │ │ ├── columns: trade_history.th_t_id:88!null trade_history.th_st_id:90!null + │ │ ├── columns: trade_history.th_t_id:94!null trade_history.th_st_id:96!null │ │ ├── insert-mapping: - │ │ │ ├── column1:93 => trade_history.th_t_id:88 - │ │ │ ├── column2:94 => th_dts:89 - │ │ │ └── column3:96 => trade_history.th_st_id:90 + │ │ │ ├── column1:102 => trade_history.th_t_id:94 + │ │ │ ├── column2:103 => th_dts:95 + │ │ │ └── column3:104 => trade_history.th_st_id:96 │ │ ├── input binding: &3 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () - │ │ ├── fd: ()-->(88,90) + │ │ ├── fd: ()-->(94,96) │ │ ├── values - │ │ │ ├── columns: column1:93!null column2:94!null column3:96 + │ │ │ ├── columns: column1:102 column2:103 column3:104 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(93,94,96) + │ │ │ ├── fd: ()-->(102-104) │ │ │ └── tuple - │ │ │ ├── 0 - │ │ │ ├── '2020-06-15 22:27:42.148484' + │ │ │ ├── assignment-cast: INT8 + │ │ │ │ └── 0 + │ │ │ ├── assignment-cast: TIMESTAMP + │ │ │ │ └── '2020-06-15 22:27:42.148484' │ │ │ └── assignment-cast: VARCHAR(4) │ │ │ └── 'SBMT' │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade_history(th_t_id) -> trade(t_id) │ │ │ └── anti-join (lookup trade) - │ │ │ ├── columns: th_t_id:97!null - │ │ │ ├── key columns: [97] = [98] + │ │ │ ├── columns: th_t_id:105 + │ │ │ ├── key columns: [105] = [106] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(97) + │ │ │ ├── fd: ()-->(105) │ │ │ ├── with-scan &3 - │ │ │ │ ├── columns: th_t_id:97!null + │ │ │ │ ├── columns: th_t_id:105 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column1:93 => th_t_id:97 + │ │ │ │ │ └── column1:102 => th_t_id:105 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(97) + │ │ │ │ └── fd: ()-->(105) │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade_history(th_st_id) -> status_type(st_id) │ │ └── anti-join (lookup status_type) - │ │ ├── columns: th_st_id:115 - │ │ ├── key columns: [115] = [116] + │ │ ├── columns: th_st_id:123 + │ │ ├── key columns: [123] = [124] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(115) + │ │ ├── fd: ()-->(123) │ │ ├── with-scan &3 - │ │ │ ├── columns: th_st_id:115 + │ │ │ ├── columns: th_st_id:123 │ │ │ ├── mapping: - │ │ │ │ └── column3:96 => th_st_id:115 + │ │ │ │ └── column3:104 => th_st_id:123 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(115) + │ │ │ └── fd: ()-->(123) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":120] + │ └── 1 [as="?column?":128] └── values - ├── columns: "?column?":121!null + ├── columns: "?column?":129!null ├── cardinality: [1 - 1] ├── key: () - ├── fd: ()-->(121) + ├── fd: ()-->(129) └── (1,) # Q12 @@ -3215,347 +3222,357 @@ insert_trade_request AS ( SELECT 1; ---- with &2 (insert_trade) - ├── columns: "?column?":195!null + ├── columns: "?column?":205!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(195) + ├── fd: ()-->(205) ├── project - │ ├── columns: "?column?":87!null + │ ├── columns: "?column?":93!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(87) + │ ├── fd: ()-->(93) │ ├── insert trade │ │ ├── columns: t_id:1!null │ │ ├── insert-mapping: - │ │ │ ├── column1:18 => t_id:1 - │ │ │ ├── column2:19 => t_dts:2 - │ │ │ ├── column3:33 => trade.t_st_id:3 - │ │ │ ├── column4:34 => trade.t_tt_id:4 - │ │ │ ├── column5:22 => t_is_cash:5 - │ │ │ ├── column6:35 => trade.t_s_symb:6 - │ │ │ ├── column7:36 => t_qty:7 - │ │ │ ├── column8:37 => t_bid_price:8 - │ │ │ ├── column9:26 => trade.t_ca_id:9 - │ │ │ ├── column10:38 => t_exec_name:10 - │ │ │ ├── column11:28 => t_trade_price:11 - │ │ │ ├── column12:39 => t_chrg:12 - │ │ │ ├── column13:40 => t_comm:13 - │ │ │ ├── column14:41 => t_tax:14 - │ │ │ └── column15:32 => t_lifo:15 - │ │ ├── check columns: check1:42 check2:43 check3:44 check4:45 check5:46 + │ │ │ ├── column1:33 => t_id:1 + │ │ │ ├── column2:34 => t_dts:2 + │ │ │ ├── column3:35 => trade.t_st_id:3 + │ │ │ ├── column4:36 => trade.t_tt_id:4 + │ │ │ ├── column5:37 => t_is_cash:5 + │ │ │ ├── column6:38 => trade.t_s_symb:6 + │ │ │ ├── column7:39 => t_qty:7 + │ │ │ ├── column8:40 => t_bid_price:8 + │ │ │ ├── column9:41 => trade.t_ca_id:9 + │ │ │ ├── column10:42 => t_exec_name:10 + │ │ │ ├── column11:43 => t_trade_price:11 + │ │ │ ├── column12:44 => t_chrg:12 + │ │ │ ├── column13:45 => t_comm:13 + │ │ │ ├── column14:46 => t_tax:14 + │ │ │ └── column15:47 => t_lifo:15 + │ │ ├── check columns: check1:48 check2:49 check3:50 check4:51 check5:52 │ │ ├── input binding: &1 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () │ │ ├── fd: ()-->(1) │ │ ├── project - │ │ │ ├── columns: check1:42 check2:43 check3:44 check4:45 check5:46 column1:18!null column2:19!null column5:22!null column9:26!null column11:28 column15:32!null column3:33 column4:34 column6:35 column7:36 column8:37 column10:38 column12:39 column13:40 column14:41 + │ │ │ ├── columns: check1:48 check2:49 check3:50 check4:51 check5:52 column1:33 column2:34 column3:35 column4:36 column5:37 column6:38 column7:39 column8:40 column9:41 column10:42 column11:43 column12:44 column13:45 column14:46 column15:47 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(18,19,22,26,28,32-46) + │ │ │ ├── fd: ()-->(33-52) │ │ │ ├── values - │ │ │ │ ├── columns: column1:18!null column2:19!null column5:22!null column9:26!null column11:28 column15:32!null column3:33 column4:34 column6:35 column7:36 column8:37 column10:38 column12:39 column13:40 column14:41 + │ │ │ │ ├── columns: column1:33 column2:34 column3:35 column4:36 column5:37 column6:38 column7:39 column8:40 column9:41 column10:42 column11:43 column12:44 column13:45 column14:46 column15:47 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── immutable │ │ │ │ ├── key: () - │ │ │ │ ├── fd: ()-->(18,19,22,26,28,32-41) + │ │ │ │ ├── fd: ()-->(33-47) │ │ │ │ └── tuple - │ │ │ │ ├── 0 - │ │ │ │ ├── '2020-06-17 22:27:42.148484' - │ │ │ │ ├── true - │ │ │ │ ├── 0 - │ │ │ │ ├── CAST(NULL AS DECIMAL(8,2)) - │ │ │ │ ├── true + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 0 + │ │ │ │ ├── assignment-cast: TIMESTAMP + │ │ │ │ │ └── '2020-06-17 22:27:42.148484' │ │ │ │ ├── assignment-cast: VARCHAR(4) │ │ │ │ │ └── 'SBMT' │ │ │ │ ├── assignment-cast: VARCHAR(3) │ │ │ │ │ └── 'TMB' + │ │ │ │ ├── assignment-cast: BOOL + │ │ │ │ │ └── true │ │ │ │ ├── assignment-cast: VARCHAR(15) │ │ │ │ │ └── 'SYMB' │ │ │ │ ├── assignment-cast: INT4 │ │ │ │ │ └── 10 │ │ │ │ ├── assignment-cast: DECIMAL(8,2) │ │ │ │ │ └── 1E+2 + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 0 │ │ │ │ ├── assignment-cast: VARCHAR(49) │ │ │ │ │ └── 'Name' + │ │ │ │ ├── assignment-cast: DECIMAL(8,2) + │ │ │ │ │ └── CAST(NULL AS DECIMAL(8,2)) │ │ │ │ ├── assignment-cast: DECIMAL(10,2) │ │ │ │ │ └── 1 │ │ │ │ ├── assignment-cast: DECIMAL(10,2) │ │ │ │ │ └── 0 - │ │ │ │ └── assignment-cast: DECIMAL(10,2) - │ │ │ │ └── 0 + │ │ │ │ ├── assignment-cast: DECIMAL(10,2) + │ │ │ │ │ └── 0 + │ │ │ │ └── assignment-cast: BOOL + │ │ │ │ └── true │ │ │ └── projections - │ │ │ ├── column7:36 > 0 [as=check1:42, outer=(36)] - │ │ │ ├── column8:37 > 0 [as=check2:43, outer=(37), immutable] - │ │ │ ├── column12:39 >= 0 [as=check3:44, outer=(39), immutable] - │ │ │ ├── column13:40 >= 0 [as=check4:45, outer=(40), immutable] - │ │ │ └── column14:41 >= 0 [as=check5:46, outer=(41), immutable] + │ │ │ ├── column7:39 > 0 [as=check1:48, outer=(39)] + │ │ │ ├── column8:40 > 0 [as=check2:49, outer=(40), immutable] + │ │ │ ├── column12:44 >= 0 [as=check3:50, outer=(44), immutable] + │ │ │ ├── column13:45 >= 0 [as=check4:51, outer=(45), immutable] + │ │ │ └── column14:46 >= 0 [as=check5:52, outer=(46), immutable] │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade(t_st_id) -> status_type(st_id) │ │ │ └── anti-join (lookup status_type) - │ │ │ ├── columns: t_st_id:47 - │ │ │ ├── key columns: [47] = [48] + │ │ │ ├── columns: t_st_id:53 + │ │ │ ├── key columns: [53] = [54] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(47) + │ │ │ ├── fd: ()-->(53) │ │ │ ├── with-scan &1 - │ │ │ │ ├── columns: t_st_id:47 + │ │ │ │ ├── columns: t_st_id:53 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column3:33 => t_st_id:47 + │ │ │ │ │ └── column3:35 => t_st_id:53 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(47) + │ │ │ │ └── fd: ()-->(53) │ │ │ └── filters (true) │ │ ├── f-k-checks-item: trade(t_tt_id) -> trade_type(tt_id) │ │ │ └── anti-join (lookup trade_type) - │ │ │ ├── columns: t_tt_id:52 - │ │ │ ├── key columns: [52] = [53] + │ │ │ ├── columns: t_tt_id:58 + │ │ │ ├── key columns: [58] = [59] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(52) + │ │ │ ├── fd: ()-->(58) │ │ │ ├── with-scan &1 - │ │ │ │ ├── columns: t_tt_id:52 + │ │ │ │ ├── columns: t_tt_id:58 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column4:34 => t_tt_id:52 + │ │ │ │ │ └── column4:36 => t_tt_id:58 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(52) + │ │ │ │ └── fd: ()-->(58) │ │ │ └── filters (true) │ │ ├── f-k-checks-item: trade(t_s_symb) -> security(s_symb) │ │ │ └── anti-join (lookup security) - │ │ │ ├── columns: t_s_symb:59 - │ │ │ ├── key columns: [59] = [60] + │ │ │ ├── columns: t_s_symb:65 + │ │ │ ├── key columns: [65] = [66] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(59) + │ │ │ ├── fd: ()-->(65) │ │ │ ├── with-scan &1 - │ │ │ │ ├── columns: t_s_symb:59 + │ │ │ │ ├── columns: t_s_symb:65 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column6:35 => t_s_symb:59 + │ │ │ │ │ └── column6:38 => t_s_symb:65 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(59) + │ │ │ │ └── fd: ()-->(65) │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade(t_ca_id) -> customer_account(ca_id) │ │ └── anti-join (lookup customer_account) - │ │ ├── columns: t_ca_id:78!null - │ │ ├── key columns: [78] = [79] + │ │ ├── columns: t_ca_id:84 + │ │ ├── key columns: [84] = [85] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(78) + │ │ ├── fd: ()-->(84) │ │ ├── with-scan &1 - │ │ │ ├── columns: t_ca_id:78!null + │ │ │ ├── columns: t_ca_id:84 │ │ │ ├── mapping: - │ │ │ │ └── column9:26 => t_ca_id:78 + │ │ │ │ └── column9:41 => t_ca_id:84 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(78) + │ │ │ └── fd: ()-->(84) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":87] + │ └── 1 [as="?column?":93] └── with &4 (insert_trade_history) - ├── columns: "?column?":195!null + ├── columns: "?column?":205!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(195) + ├── fd: ()-->(205) ├── project - │ ├── columns: "?column?":120!null + │ ├── columns: "?column?":128!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(120) + │ ├── fd: ()-->(128) │ ├── insert trade_history - │ │ ├── columns: trade_history.th_t_id:88!null trade_history.th_st_id:90!null + │ │ ├── columns: trade_history.th_t_id:94!null trade_history.th_st_id:96!null │ │ ├── insert-mapping: - │ │ │ ├── column1:93 => trade_history.th_t_id:88 - │ │ │ ├── column2:94 => th_dts:89 - │ │ │ └── column3:96 => trade_history.th_st_id:90 + │ │ │ ├── column1:102 => trade_history.th_t_id:94 + │ │ │ ├── column2:103 => th_dts:95 + │ │ │ └── column3:104 => trade_history.th_st_id:96 │ │ ├── input binding: &3 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () - │ │ ├── fd: ()-->(88,90) + │ │ ├── fd: ()-->(94,96) │ │ ├── values - │ │ │ ├── columns: column1:93!null column2:94!null column3:96 + │ │ │ ├── columns: column1:102 column2:103 column3:104 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(93,94,96) + │ │ │ ├── fd: ()-->(102-104) │ │ │ └── tuple - │ │ │ ├── 0 - │ │ │ ├── '2020-06-15 22:27:42.148484' + │ │ │ ├── assignment-cast: INT8 + │ │ │ │ └── 0 + │ │ │ ├── assignment-cast: TIMESTAMP + │ │ │ │ └── '2020-06-15 22:27:42.148484' │ │ │ └── assignment-cast: VARCHAR(4) │ │ │ └── 'SBMT' │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade_history(th_t_id) -> trade(t_id) │ │ │ └── anti-join (lookup trade) - │ │ │ ├── columns: th_t_id:97!null - │ │ │ ├── key columns: [97] = [98] + │ │ │ ├── columns: th_t_id:105 + │ │ │ ├── key columns: [105] = [106] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(97) + │ │ │ ├── fd: ()-->(105) │ │ │ ├── with-scan &3 - │ │ │ │ ├── columns: th_t_id:97!null + │ │ │ │ ├── columns: th_t_id:105 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column1:93 => th_t_id:97 + │ │ │ │ │ └── column1:102 => th_t_id:105 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(97) + │ │ │ │ └── fd: ()-->(105) │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade_history(th_st_id) -> status_type(st_id) │ │ └── anti-join (lookup status_type) - │ │ ├── columns: th_st_id:115 - │ │ ├── key columns: [115] = [116] + │ │ ├── columns: th_st_id:123 + │ │ ├── key columns: [123] = [124] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(115) + │ │ ├── fd: ()-->(123) │ │ ├── with-scan &3 - │ │ │ ├── columns: th_st_id:115 + │ │ │ ├── columns: th_st_id:123 │ │ │ ├── mapping: - │ │ │ │ └── column3:96 => th_st_id:115 + │ │ │ │ └── column3:104 => th_st_id:123 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(115) + │ │ │ └── fd: ()-->(123) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":120] + │ └── 1 [as="?column?":128] └── with &6 (insert_trade_request) - ├── columns: "?column?":195!null + ├── columns: "?column?":205!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(195) + ├── fd: ()-->(205) ├── project - │ ├── columns: "?column?":194!null + │ ├── columns: "?column?":204!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(194) + │ ├── fd: ()-->(204) │ ├── insert trade_request - │ │ ├── columns: trade_request.tr_t_id:121!null + │ │ ├── columns: trade_request.tr_t_id:129!null │ │ ├── insert-mapping: - │ │ │ ├── column1:129 => trade_request.tr_t_id:121 - │ │ │ ├── column2:135 => trade_request.tr_tt_id:122 - │ │ │ ├── column3:136 => trade_request.tr_s_symb:123 - │ │ │ ├── column4:137 => tr_qty:124 - │ │ │ ├── column5:138 => tr_bid_price:125 - │ │ │ └── column6:134 => trade_request.tr_b_id:126 - │ │ ├── check columns: check1:139 check2:140 - │ │ ├── partial index put columns: partial_index_put1:141 + │ │ │ ├── column1:143 => trade_request.tr_t_id:129 + │ │ │ ├── column2:144 => trade_request.tr_tt_id:130 + │ │ │ ├── column3:145 => trade_request.tr_s_symb:131 + │ │ │ ├── column4:146 => tr_qty:132 + │ │ │ ├── column5:147 => tr_bid_price:133 + │ │ │ └── column6:148 => trade_request.tr_b_id:134 + │ │ ├── check columns: check1:149 check2:150 + │ │ ├── partial index put columns: partial_index_put1:151 │ │ ├── input binding: &5 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () - │ │ ├── fd: ()-->(121) + │ │ ├── fd: ()-->(129) │ │ ├── project - │ │ │ ├── columns: partial_index_put1:141 check1:139 check2:140 column1:129!null column6:134!null column2:135 column3:136 column4:137 column5:138 + │ │ │ ├── columns: partial_index_put1:151 check1:149 check2:150 column1:143 column2:144 column3:145 column4:146 column5:147 column6:148 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(129,134-141) + │ │ │ ├── fd: ()-->(143-151) │ │ │ ├── values - │ │ │ │ ├── columns: column1:129!null column6:134!null column2:135 column3:136 column4:137 column5:138 + │ │ │ │ ├── columns: column1:143 column2:144 column3:145 column4:146 column5:147 column6:148 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── immutable │ │ │ │ ├── key: () - │ │ │ │ ├── fd: ()-->(129,134-138) + │ │ │ │ ├── fd: ()-->(143-148) │ │ │ │ └── tuple - │ │ │ │ ├── 0 - │ │ │ │ ├── 0 + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 0 │ │ │ │ ├── assignment-cast: VARCHAR(3) │ │ │ │ │ └── 'TMB' │ │ │ │ ├── assignment-cast: VARCHAR(15) │ │ │ │ │ └── 'SYMB' │ │ │ │ ├── assignment-cast: INT4 │ │ │ │ │ └── 10 - │ │ │ │ └── assignment-cast: DECIMAL(8,2) - │ │ │ │ └── 1E+2 + │ │ │ │ ├── assignment-cast: DECIMAL(8,2) + │ │ │ │ │ └── 1E+2 + │ │ │ │ └── assignment-cast: INT8 + │ │ │ │ └── 0 │ │ │ └── projections - │ │ │ ├── column2:135 IN ('TLB', 'TLS', 'TSL') [as=partial_index_put1:141, outer=(135)] - │ │ │ ├── column4:137 > 0 [as=check1:139, outer=(137)] - │ │ │ └── column5:138 > 0 [as=check2:140, outer=(138), immutable] + │ │ │ ├── column2:144 IN ('TLB', 'TLS', 'TSL') [as=partial_index_put1:151, outer=(144)] + │ │ │ ├── column4:146 > 0 [as=check1:149, outer=(146)] + │ │ │ └── column5:147 > 0 [as=check2:150, outer=(147), immutable] │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade_request(tr_t_id) -> trade(t_id) │ │ │ └── anti-join (lookup trade) - │ │ │ ├── columns: tr_t_id:142!null - │ │ │ ├── key columns: [142] = [143] + │ │ │ ├── columns: tr_t_id:152 + │ │ │ ├── key columns: [152] = [153] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(142) + │ │ │ ├── fd: ()-->(152) │ │ │ ├── with-scan &5 - │ │ │ │ ├── columns: tr_t_id:142!null + │ │ │ │ ├── columns: tr_t_id:152 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column1:129 => tr_t_id:142 + │ │ │ │ │ └── column1:143 => tr_t_id:152 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(142) + │ │ │ │ └── fd: ()-->(152) │ │ │ └── filters (true) │ │ ├── f-k-checks-item: trade_request(tr_tt_id) -> trade_type(tt_id) │ │ │ └── anti-join (lookup trade_type) - │ │ │ ├── columns: tr_tt_id:160 - │ │ │ ├── key columns: [160] = [161] + │ │ │ ├── columns: tr_tt_id:170 + │ │ │ ├── key columns: [170] = [171] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(160) + │ │ │ ├── fd: ()-->(170) │ │ │ ├── with-scan &5 - │ │ │ │ ├── columns: tr_tt_id:160 + │ │ │ │ ├── columns: tr_tt_id:170 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column2:135 => tr_tt_id:160 + │ │ │ │ │ └── column2:144 => tr_tt_id:170 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(160) + │ │ │ │ └── fd: ()-->(170) │ │ │ └── filters (true) │ │ ├── f-k-checks-item: trade_request(tr_s_symb) -> security(s_symb) │ │ │ └── anti-join (lookup security) - │ │ │ ├── columns: tr_s_symb:167 - │ │ │ ├── key columns: [167] = [168] + │ │ │ ├── columns: tr_s_symb:177 + │ │ │ ├── key columns: [177] = [178] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(167) + │ │ │ ├── fd: ()-->(177) │ │ │ ├── with-scan &5 - │ │ │ │ ├── columns: tr_s_symb:167 + │ │ │ │ ├── columns: tr_s_symb:177 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column3:136 => tr_s_symb:167 + │ │ │ │ │ └── column3:145 => tr_s_symb:177 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(167) + │ │ │ │ └── fd: ()-->(177) │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade_request(tr_b_id) -> broker(b_id) │ │ └── anti-join (lookup broker) - │ │ ├── columns: tr_b_id:186!null - │ │ ├── key columns: [186] = [187] + │ │ ├── columns: tr_b_id:196 + │ │ ├── key columns: [196] = [197] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(186) + │ │ ├── fd: ()-->(196) │ │ ├── with-scan &5 - │ │ │ ├── columns: tr_b_id:186!null + │ │ │ ├── columns: tr_b_id:196 │ │ │ ├── mapping: - │ │ │ │ └── column6:134 => tr_b_id:186 + │ │ │ │ └── column6:148 => tr_b_id:196 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(186) + │ │ │ └── fd: ()-->(196) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":194] + │ └── 1 [as="?column?":204] └── values - ├── columns: "?column?":195!null + ├── columns: "?column?":205!null ├── cardinality: [1 - 1] ├── key: () - ├── fd: ()-->(195) + ├── fd: ()-->(205) └── (1,) # -------------------------------------------------- @@ -3705,20 +3722,21 @@ INSERT INTO holding_summary (hs_ca_id, hs_s_symb, hs_qty) VALUES (0, 'ROACH', 10 insert holding_summary ├── columns: ├── insert-mapping: - │ ├── column1:6 => holding_summary.hs_ca_id:1 - │ ├── column2:9 => holding_summary.hs_s_symb:2 - │ └── column3:10 => hs_qty:3 + │ ├── column1:9 => holding_summary.hs_ca_id:1 + │ ├── column2:10 => holding_summary.hs_s_symb:2 + │ └── column3:11 => hs_qty:3 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── values - │ ├── columns: column1:6!null column2:9 column3:10 + │ ├── columns: column1:9 column2:10 column3:11 │ ├── cardinality: [1 - 1] │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(6,9,10) + │ ├── fd: ()-->(9-11) │ └── tuple - │ ├── 0 + │ ├── assignment-cast: INT8 + │ │ └── 0 │ ├── assignment-cast: VARCHAR(15) │ │ └── 'ROACH' │ └── assignment-cast: INT4 @@ -3726,35 +3744,35 @@ insert holding_summary └── f-k-checks ├── f-k-checks-item: holding_summary(hs_ca_id) -> customer_account(ca_id) │ └── anti-join (lookup customer_account) - │ ├── columns: hs_ca_id:11!null - │ ├── key columns: [11] = [12] + │ ├── columns: hs_ca_id:12 + │ ├── key columns: [12] = [13] │ ├── lookup columns are key │ ├── cardinality: [0 - 1] │ ├── key: () - │ ├── fd: ()-->(11) + │ ├── fd: ()-->(12) │ ├── with-scan &1 - │ │ ├── columns: hs_ca_id:11!null + │ │ ├── columns: hs_ca_id:12 │ │ ├── mapping: - │ │ │ └── column1:6 => hs_ca_id:11 + │ │ │ └── column1:9 => hs_ca_id:12 │ │ ├── cardinality: [1 - 1] │ │ ├── key: () - │ │ └── fd: ()-->(11) + │ │ └── fd: ()-->(12) │ └── filters (true) └── f-k-checks-item: holding_summary(hs_s_symb) -> security(s_symb) └── anti-join (lookup security) - ├── columns: hs_s_symb:20 - ├── key columns: [20] = [21] + ├── columns: hs_s_symb:21 + ├── key columns: [21] = [22] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(20) + ├── fd: ()-->(21) ├── with-scan &1 - │ ├── columns: hs_s_symb:20 + │ ├── columns: hs_s_symb:21 │ ├── mapping: - │ │ └── column2:9 => hs_s_symb:20 + │ │ └── column2:10 => hs_s_symb:21 │ ├── cardinality: [1 - 1] │ ├── key: () - │ └── fd: ()-->(20) + │ └── fd: ()-->(21) └── filters (true) # Q4 @@ -3842,17 +3860,18 @@ INSERT INTO holding_history (hh_h_t_id, hh_t_id, hh_before_qty, hh_after_qty) insert holding_history ├── columns: ├── insert-mapping: - │ ├── unnest:7 => holding_history.hh_h_t_id:1 - │ ├── "?column?":10 => holding_history.hh_t_id:2 - │ ├── unnest:8 => hh_before_qty:3 - │ └── unnest:9 => hh_after_qty:4 + │ ├── unnest:11 => holding_history.hh_h_t_id:1 + │ ├── "?column?":12 => holding_history.hh_t_id:2 + │ ├── unnest:13 => hh_before_qty:3 + │ └── unnest:14 => hh_after_qty:4 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── project - │ ├── columns: "?column?":10!null unnest:7!null unnest:8!null unnest:9!null + │ ├── columns: unnest:11!null "?column?":12!null unnest:13!null unnest:14!null │ ├── cardinality: [3 - 3] - │ ├── fd: ()-->(10) + │ ├── immutable + │ ├── fd: ()-->(12) │ ├── values │ │ ├── columns: unnest:7!null unnest:8!null unnest:9!null │ │ ├── cardinality: [3 - 3] @@ -3860,33 +3879,40 @@ insert holding_history │ │ ├── (2, 20, 30) │ │ └── (3, 30, 40) │ └── projections - │ └── 0 [as="?column?":10] + │ ├── assignment-cast: INT8 [as=unnest:11, outer=(7), immutable] + │ │ └── unnest:7 + │ ├── assignment-cast: INT8 [as="?column?":12, immutable] + │ │ └── 0 + │ ├── assignment-cast: INT4 [as=unnest:13, outer=(8), immutable] + │ │ └── unnest:8 + │ └── assignment-cast: INT4 [as=unnest:14, outer=(9), immutable] + │ └── unnest:9 └── f-k-checks ├── f-k-checks-item: holding_history(hh_h_t_id) -> trade(t_id) │ └── anti-join (lookup trade) - │ ├── columns: hh_h_t_id:11!null - │ ├── key columns: [11] = [12] + │ ├── columns: hh_h_t_id:15!null + │ ├── key columns: [15] = [16] │ ├── lookup columns are key │ ├── cardinality: [0 - 3] │ ├── with-scan &1 - │ │ ├── columns: hh_h_t_id:11!null + │ │ ├── columns: hh_h_t_id:15!null │ │ ├── mapping: - │ │ │ └── unnest:7 => hh_h_t_id:11 + │ │ │ └── unnest:11 => hh_h_t_id:15 │ │ └── cardinality: [3 - 3] │ └── filters (true) └── f-k-checks-item: holding_history(hh_t_id) -> trade(t_id) └── anti-join (lookup trade) - ├── columns: hh_t_id:29!null - ├── key columns: [29] = [30] + ├── columns: hh_t_id:33!null + ├── key columns: [33] = [34] ├── lookup columns are key ├── cardinality: [0 - 3] - ├── fd: ()-->(29) + ├── fd: ()-->(33) ├── with-scan &1 - │ ├── columns: hh_t_id:29!null + │ ├── columns: hh_t_id:33!null │ ├── mapping: - │ │ └── "?column?":10 => hh_t_id:29 + │ │ └── "?column?":12 => hh_t_id:33 │ ├── cardinality: [3 - 3] - │ └── fd: ()-->(29) + │ └── fd: ()-->(33) └── filters (true) # Q8 @@ -3948,73 +3974,76 @@ VALUES insert holding ├── columns: ├── insert-mapping: - │ ├── column1:9 => holding.h_t_id:1 - │ ├── column2:10 => holding.h_ca_id:2 - │ ├── column3:15 => holding.h_s_symb:3 - │ ├── column4:12 => h_dts:4 - │ ├── column5:16 => h_price:5 - │ └── column6:17 => h_qty:6 - ├── check columns: check1:18 + │ ├── column1:15 => holding.h_t_id:1 + │ ├── column2:16 => holding.h_ca_id:2 + │ ├── column3:17 => holding.h_s_symb:3 + │ ├── column4:18 => h_dts:4 + │ ├── column5:19 => h_price:5 + │ └── column6:20 => h_qty:6 + ├── check columns: check1:21 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── project - │ ├── columns: check1:18 column1:9!null column2:10!null column4:12!null column3:15 column5:16 column6:17 + │ ├── columns: check1:21 column1:15 column2:16 column3:17 column4:18 column5:19 column6:20 │ ├── cardinality: [1 - 1] │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(9,10,12,15-18) + │ ├── fd: ()-->(15-21) │ ├── values - │ │ ├── columns: column1:9!null column2:10!null column4:12!null column3:15 column5:16 column6:17 + │ │ ├── columns: column1:15 column2:16 column3:17 column4:18 column5:19 column6:20 │ │ ├── cardinality: [1 - 1] │ │ ├── immutable │ │ ├── key: () - │ │ ├── fd: ()-->(9,10,12,15-17) + │ │ ├── fd: ()-->(15-20) │ │ └── tuple - │ │ ├── 0 - │ │ ├── 0 - │ │ ├── '2020-06-15 22:27:42.148484' + │ │ ├── assignment-cast: INT8 + │ │ │ └── 0 + │ │ ├── assignment-cast: INT8 + │ │ │ └── 0 │ │ ├── assignment-cast: VARCHAR(15) │ │ │ └── 'ROACH' + │ │ ├── assignment-cast: TIMESTAMP + │ │ │ └── '2020-06-15 22:27:42.148484' │ │ ├── assignment-cast: DECIMAL(8,2) │ │ │ └── 1E+2 │ │ └── assignment-cast: INT4 │ │ └── 10 │ └── projections - │ └── column5:16 > 0 [as=check1:18, outer=(16), immutable] + │ └── column5:19 > 0 [as=check1:21, outer=(19), immutable] └── f-k-checks ├── f-k-checks-item: holding(h_t_id) -> trade(t_id) │ └── anti-join (lookup trade) - │ ├── columns: h_t_id:19!null - │ ├── key columns: [19] = [20] + │ ├── columns: h_t_id:22 + │ ├── key columns: [22] = [23] │ ├── lookup columns are key │ ├── cardinality: [0 - 1] │ ├── key: () - │ ├── fd: ()-->(19) + │ ├── fd: ()-->(22) │ ├── with-scan &1 - │ │ ├── columns: h_t_id:19!null + │ │ ├── columns: h_t_id:22 │ │ ├── mapping: - │ │ │ └── column1:9 => h_t_id:19 + │ │ │ └── column1:15 => h_t_id:22 │ │ ├── cardinality: [1 - 1] │ │ ├── key: () - │ │ └── fd: ()-->(19) + │ │ └── fd: ()-->(22) │ └── filters (true) └── f-k-checks-item: holding(h_ca_id,h_s_symb) -> holding_summary(hs_ca_id,hs_s_symb) └── anti-join (lookup holding_summary) - ├── columns: h_ca_id:37!null h_s_symb:38 - ├── key columns: [37 38] = [39 40] + ├── columns: h_ca_id:40 h_s_symb:41 + ├── key columns: [40 41] = [42 43] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(37,38) + ├── fd: ()-->(40,41) ├── with-scan &1 - │ ├── columns: h_ca_id:37!null h_s_symb:38 + │ ├── columns: h_ca_id:40 h_s_symb:41 │ ├── mapping: - │ │ ├── column2:10 => h_ca_id:37 - │ │ └── column3:15 => h_s_symb:38 + │ │ ├── column2:16 => h_ca_id:40 + │ │ └── column3:17 => h_s_symb:41 │ ├── cardinality: [1 - 1] │ ├── key: () - │ └── fd: ()-->(37,38) + │ └── fd: ()-->(40,41) └── filters (true) # Q11 @@ -4288,11 +4317,11 @@ insert_trade_history AS ( SELECT 1 ---- with &2 (update_trade_commission) - ├── columns: "?column?":103!null + ├── columns: "?column?":105!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(103) + ├── fd: ()-->(105) ├── project │ ├── columns: "?column?":51!null │ ├── cardinality: [0 - 1] @@ -4350,11 +4379,11 @@ with &2 (update_trade_commission) │ └── projections │ └── 1 [as="?column?":51] └── with &4 (update_broker_commission) - ├── columns: "?column?":103!null + ├── columns: "?column?":105!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(103) + ├── fd: ()-->(105) ├── project │ ├── columns: "?column?":69!null │ ├── cardinality: [0 - 1] @@ -4389,79 +4418,81 @@ with &2 (update_trade_commission) │ └── projections │ └── 1 [as="?column?":69] └── with &6 (insert_trade_history) - ├── columns: "?column?":103!null + ├── columns: "?column?":105!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(103) + ├── fd: ()-->(105) ├── project - │ ├── columns: "?column?":102!null + │ ├── columns: "?column?":104!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(102) + │ ├── fd: ()-->(104) │ ├── insert trade_history │ │ ├── columns: trade_history.th_t_id:70!null trade_history.th_st_id:72!null │ │ ├── insert-mapping: - │ │ │ ├── column1:75 => trade_history.th_t_id:70 - │ │ │ ├── column2:76 => th_dts:71 - │ │ │ └── column3:78 => trade_history.th_st_id:72 + │ │ │ ├── column1:78 => trade_history.th_t_id:70 + │ │ │ ├── column2:79 => th_dts:71 + │ │ │ └── column3:80 => trade_history.th_st_id:72 │ │ ├── input binding: &5 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () │ │ ├── fd: ()-->(70,72) │ │ ├── values - │ │ │ ├── columns: column1:75!null column2:76!null column3:78 + │ │ │ ├── columns: column1:78 column2:79 column3:80 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(75,76,78) + │ │ │ ├── fd: ()-->(78-80) │ │ │ └── tuple - │ │ │ ├── 0 - │ │ │ ├── '2020-06-15 22:27:42.148484' + │ │ │ ├── assignment-cast: INT8 + │ │ │ │ └── 0 + │ │ │ ├── assignment-cast: TIMESTAMP + │ │ │ │ └── '2020-06-15 22:27:42.148484' │ │ │ └── assignment-cast: VARCHAR(4) │ │ │ └── 'ACTV' │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade_history(th_t_id) -> trade(t_id) │ │ │ └── anti-join (lookup trade) - │ │ │ ├── columns: th_t_id:79!null - │ │ │ ├── key columns: [79] = [80] + │ │ │ ├── columns: th_t_id:81 + │ │ │ ├── key columns: [81] = [82] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(79) + │ │ │ ├── fd: ()-->(81) │ │ │ ├── with-scan &5 - │ │ │ │ ├── columns: th_t_id:79!null + │ │ │ │ ├── columns: th_t_id:81 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column1:75 => th_t_id:79 + │ │ │ │ │ └── column1:78 => th_t_id:81 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(79) + │ │ │ │ └── fd: ()-->(81) │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade_history(th_st_id) -> status_type(st_id) │ │ └── anti-join (lookup status_type) - │ │ ├── columns: th_st_id:97 - │ │ ├── key columns: [97] = [98] + │ │ ├── columns: th_st_id:99 + │ │ ├── key columns: [99] = [100] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(97) + │ │ ├── fd: ()-->(99) │ │ ├── with-scan &5 - │ │ │ ├── columns: th_st_id:97 + │ │ │ ├── columns: th_st_id:99 │ │ │ ├── mapping: - │ │ │ │ └── column3:78 => th_st_id:97 + │ │ │ │ └── column3:80 => th_st_id:99 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(97) + │ │ │ └── fd: ()-->(99) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":102] + │ └── 1 [as="?column?":104] └── values - ├── columns: "?column?":103!null + ├── columns: "?column?":105!null ├── cardinality: [1 - 1] ├── key: () - ├── fd: ()-->(103) + ├── fd: ()-->(105) └── (1,) @@ -4491,94 +4522,98 @@ WHERE ca_id = 0 RETURNING ca_bal::FLOAT8; ---- with &2 (insert_settlement) - ├── columns: ca_bal:82!null + ├── columns: ca_bal:86!null ├── cardinality: [0 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(82) + ├── fd: ()-->(86) ├── project - │ ├── columns: "?column?":31!null + │ ├── columns: "?column?":33!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(31) + │ ├── fd: ()-->(33) │ ├── insert settlement │ │ ├── columns: settlement.se_t_id:1!null │ │ ├── insert-mapping: - │ │ │ ├── column1:7 => settlement.se_t_id:1 - │ │ │ ├── column2:11 => se_cash_type:2 - │ │ │ ├── column3:9 => se_cash_due_date:3 - │ │ │ └── column4:12 => se_amt:4 + │ │ │ ├── column1:11 => settlement.se_t_id:1 + │ │ │ ├── column2:12 => se_cash_type:2 + │ │ │ ├── column3:13 => se_cash_due_date:3 + │ │ │ └── column4:14 => se_amt:4 │ │ ├── input binding: &1 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () │ │ ├── fd: ()-->(1) │ │ ├── values - │ │ │ ├── columns: column1:7!null column3:9!null column2:11 column4:12 + │ │ │ ├── columns: column1:11 column2:12 column3:13 column4:14 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(7,9,11,12) + │ │ │ ├── fd: ()-->(11-14) │ │ │ └── tuple - │ │ │ ├── 0 - │ │ │ ├── '2020-06-15' + │ │ │ ├── assignment-cast: INT8 + │ │ │ │ └── 0 │ │ │ ├── assignment-cast: VARCHAR(40) │ │ │ │ └── 'Margin' + │ │ │ ├── assignment-cast: DATE + │ │ │ │ └── '2020-06-15' │ │ │ └── assignment-cast: DECIMAL(10,2) │ │ │ └── 1E+2 │ │ └── f-k-checks │ │ └── f-k-checks-item: settlement(se_t_id) -> trade(t_id) │ │ └── anti-join (lookup trade) - │ │ ├── columns: se_t_id:13!null - │ │ ├── key columns: [13] = [14] + │ │ ├── columns: se_t_id:15 + │ │ ├── key columns: [15] = [16] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(13) + │ │ ├── fd: ()-->(15) │ │ ├── with-scan &1 - │ │ │ ├── columns: se_t_id:13!null + │ │ │ ├── columns: se_t_id:15 │ │ │ ├── mapping: - │ │ │ │ └── column1:7 => se_t_id:13 + │ │ │ │ └── column1:11 => se_t_id:15 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(13) + │ │ │ └── fd: ()-->(15) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":31] + │ └── 1 [as="?column?":33] └── with &4 (insert_cash_transaction) - ├── columns: ca_bal:82!null + ├── columns: ca_bal:86!null ├── cardinality: [0 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(82) + ├── fd: ()-->(86) ├── project - │ ├── columns: "?column?":62!null + │ ├── columns: "?column?":66!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(62) + │ ├── fd: ()-->(66) │ ├── insert cash_transaction - │ │ ├── columns: cash_transaction.ct_t_id:32!null + │ │ ├── columns: cash_transaction.ct_t_id:34!null │ │ ├── insert-mapping: - │ │ │ ├── column1:38 => cash_transaction.ct_t_id:32 - │ │ │ ├── column2:39 => ct_dts:33 - │ │ │ ├── column3:42 => ct_amt:34 - │ │ │ └── column4:43 => ct_name:35 + │ │ │ ├── column1:44 => cash_transaction.ct_t_id:34 + │ │ │ ├── column2:45 => ct_dts:35 + │ │ │ ├── column3:46 => ct_amt:36 + │ │ │ └── column4:47 => ct_name:37 │ │ ├── input binding: &3 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () - │ │ ├── fd: ()-->(32) + │ │ ├── fd: ()-->(34) │ │ ├── values - │ │ │ ├── columns: column1:38!null column2:39!null column3:42 column4:43 + │ │ │ ├── columns: column1:44 column2:45 column3:46 column4:47 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(38,39,42,43) + │ │ │ ├── fd: ()-->(44-47) │ │ │ └── tuple - │ │ │ ├── 0 - │ │ │ ├── '2020-06-10 22:27:42.148484' + │ │ │ ├── assignment-cast: INT8 + │ │ │ │ └── 0 + │ │ │ ├── assignment-cast: TIMESTAMP + │ │ │ │ └── '2020-06-10 22:27:42.148484' │ │ │ ├── assignment-cast: DECIMAL(10,2) │ │ │ │ └── 1E+2 │ │ │ └── assignment-cast: VARCHAR(100) @@ -4586,53 +4621,53 @@ with &2 (insert_settlement) │ │ └── f-k-checks │ │ └── f-k-checks-item: cash_transaction(ct_t_id) -> trade(t_id) │ │ └── anti-join (lookup trade) - │ │ ├── columns: ct_t_id:44!null - │ │ ├── key columns: [44] = [45] + │ │ ├── columns: ct_t_id:48 + │ │ ├── key columns: [48] = [49] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(44) + │ │ ├── fd: ()-->(48) │ │ ├── with-scan &3 - │ │ │ ├── columns: ct_t_id:44!null + │ │ │ ├── columns: ct_t_id:48 │ │ │ ├── mapping: - │ │ │ │ └── column1:38 => ct_t_id:44 + │ │ │ │ └── column1:44 => ct_t_id:48 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(44) + │ │ │ └── fd: ()-->(48) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":62] + │ └── 1 [as="?column?":66] └── project - ├── columns: ca_bal:82!null + ├── columns: ca_bal:86!null ├── cardinality: [0 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(82) + ├── fd: ()-->(86) ├── update customer_account - │ ├── columns: ca_id:63!null customer_account.ca_bal:68!null - │ ├── fetch columns: ca_id:71 ca_b_id:72 ca_c_id:73 ca_name:74 ca_tax_st:75 customer_account.ca_bal:76 + │ ├── columns: ca_id:67!null customer_account.ca_bal:72!null + │ ├── fetch columns: ca_id:75 ca_b_id:76 ca_c_id:77 ca_name:78 ca_tax_st:79 customer_account.ca_bal:80 │ ├── update-mapping: - │ │ └── ca_bal_new:80 => customer_account.ca_bal:68 + │ │ └── ca_bal_new:84 => customer_account.ca_bal:72 │ ├── cardinality: [0 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(63,68) + │ ├── fd: ()-->(67,72) │ └── project - │ ├── columns: ca_bal_new:80 ca_id:71!null ca_b_id:72!null ca_c_id:73!null ca_name:74 ca_tax_st:75!null customer_account.ca_bal:76!null + │ ├── columns: ca_bal_new:84 ca_id:75!null ca_b_id:76!null ca_c_id:77!null ca_name:78 ca_tax_st:79!null customer_account.ca_bal:80!null │ ├── cardinality: [0 - 1] │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(71-76,80) + │ ├── fd: ()-->(75-80,84) │ ├── scan customer_account - │ │ ├── columns: ca_id:71!null ca_b_id:72!null ca_c_id:73!null ca_name:74 ca_tax_st:75!null customer_account.ca_bal:76!null - │ │ ├── constraint: /71: [/0 - /0] + │ │ ├── columns: ca_id:75!null ca_b_id:76!null ca_c_id:77!null ca_name:78 ca_tax_st:79!null customer_account.ca_bal:80!null + │ │ ├── constraint: /75: [/0 - /0] │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ └── fd: ()-->(71-76) + │ │ └── fd: ()-->(75-80) │ └── projections - │ └── crdb_internal.round_decimal_values(customer_account.ca_bal:76::DECIMAL + 1E+2, 2) [as=ca_bal_new:80, outer=(76), immutable] + │ └── crdb_internal.round_decimal_values(customer_account.ca_bal:80::DECIMAL + 1E+2, 2) [as=ca_bal_new:84, outer=(80), immutable] └── projections - └── customer_account.ca_bal:68::FLOAT8 [as=ca_bal:82, outer=(68), immutable] + └── customer_account.ca_bal:72::FLOAT8 [as=ca_bal:86, outer=(72), immutable] # Q16 opt @@ -4646,75 +4681,77 @@ insert_settlement AS ( SELECT ca_bal::FLOAT8 FROM customer_account WHERE ca_id = 0; ---- with &2 (insert_settlement) - ├── columns: ca_bal:40!null + ├── columns: ca_bal:42!null ├── cardinality: [0 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(40) + ├── fd: ()-->(42) ├── project - │ ├── columns: "?column?":31!null + │ ├── columns: "?column?":33!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(31) + │ ├── fd: ()-->(33) │ ├── insert settlement │ │ ├── columns: settlement.se_t_id:1!null │ │ ├── insert-mapping: - │ │ │ ├── column1:7 => settlement.se_t_id:1 - │ │ │ ├── column2:11 => se_cash_type:2 - │ │ │ ├── column3:9 => se_cash_due_date:3 - │ │ │ └── column4:12 => se_amt:4 + │ │ │ ├── column1:11 => settlement.se_t_id:1 + │ │ │ ├── column2:12 => se_cash_type:2 + │ │ │ ├── column3:13 => se_cash_due_date:3 + │ │ │ └── column4:14 => se_amt:4 │ │ ├── input binding: &1 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () │ │ ├── fd: ()-->(1) │ │ ├── values - │ │ │ ├── columns: column1:7!null column3:9!null column2:11 column4:12 + │ │ │ ├── columns: column1:11 column2:12 column3:13 column4:14 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(7,9,11,12) + │ │ │ ├── fd: ()-->(11-14) │ │ │ └── tuple - │ │ │ ├── 0 - │ │ │ ├── '2020-06-15' + │ │ │ ├── assignment-cast: INT8 + │ │ │ │ └── 0 │ │ │ ├── assignment-cast: VARCHAR(40) │ │ │ │ └── 'Margin' + │ │ │ ├── assignment-cast: DATE + │ │ │ │ └── '2020-06-15' │ │ │ └── assignment-cast: DECIMAL(10,2) │ │ │ └── 1E+2 │ │ └── f-k-checks │ │ └── f-k-checks-item: settlement(se_t_id) -> trade(t_id) │ │ └── anti-join (lookup trade) - │ │ ├── columns: se_t_id:13!null - │ │ ├── key columns: [13] = [14] + │ │ ├── columns: se_t_id:15 + │ │ ├── key columns: [15] = [16] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(13) + │ │ ├── fd: ()-->(15) │ │ ├── with-scan &1 - │ │ │ ├── columns: se_t_id:13!null + │ │ │ ├── columns: se_t_id:15 │ │ │ ├── mapping: - │ │ │ │ └── column1:7 => se_t_id:13 + │ │ │ │ └── column1:11 => se_t_id:15 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(13) + │ │ │ └── fd: ()-->(15) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":31] + │ └── 1 [as="?column?":33] └── project - ├── columns: ca_bal:40!null + ├── columns: ca_bal:42!null ├── cardinality: [0 - 1] ├── immutable ├── key: () - ├── fd: ()-->(40) + ├── fd: ()-->(42) ├── scan customer_account - │ ├── columns: ca_id:32!null customer_account.ca_bal:37!null - │ ├── constraint: /32: [/0 - /0] + │ ├── columns: ca_id:34!null customer_account.ca_bal:39!null + │ ├── constraint: /34: [/0 - /0] │ ├── cardinality: [0 - 1] │ ├── key: () - │ └── fd: ()-->(32,37) + │ └── fd: ()-->(34,39) └── projections - └── customer_account.ca_bal:37::FLOAT8 [as=ca_bal:40, outer=(37), immutable] + └── customer_account.ca_bal:39::FLOAT8 [as=ca_bal:42, outer=(39), immutable] # -------------------------------------------------- # T9 diff --git a/pkg/sql/opt/xform/testdata/external/tpce-no-stats b/pkg/sql/opt/xform/testdata/external/tpce-no-stats index 1a098087d3c6..433466d090a6 100644 --- a/pkg/sql/opt/xform/testdata/external/tpce-no-stats +++ b/pkg/sql/opt/xform/testdata/external/tpce-no-stats @@ -570,10 +570,10 @@ update_trade_submitted AS ( SELECT * FROM request_list; ---- with &2 (update_last_trade) - ├── columns: tr_t_id:138!null tr_bid_price:139!null tr_tt_id:140!null tr_qty:141!null + ├── columns: tr_t_id:140!null tr_bid_price:141!null tr_tt_id:142!null tr_qty:143!null ├── volatile, mutations - ├── key: (138) - ├── fd: (138)-->(139-141) + ├── key: (140) + ├── fd: (140)-->(141-143) ├── project │ ├── columns: "?column?":19 │ ├── cardinality: [0 - 1] @@ -610,10 +610,10 @@ with &2 (update_last_trade) │ └── projections │ └── NULL [as="?column?":19] └── with &3 (request_list) - ├── columns: tr_t_id:138!null tr_bid_price:139!null tr_tt_id:140!null tr_qty:141!null + ├── columns: tr_t_id:140!null tr_bid_price:141!null tr_tt_id:142!null tr_qty:143!null ├── volatile, mutations - ├── key: (138) - ├── fd: (138)-->(139-141) + ├── key: (140) + ├── fd: (140)-->(141-143) ├── project │ ├── columns: tr_bid_price:28!null trade_request.tr_t_id:20!null trade_request.tr_tt_id:21!null trade_request.tr_qty:23!null │ ├── immutable @@ -640,10 +640,10 @@ with &2 (update_last_trade) │ └── projections │ └── trade_request.tr_bid_price:24::FLOAT8 [as=tr_bid_price:28, outer=(24), immutable] └── with &4 (delete_trade_request) - ├── columns: tr_t_id:138!null tr_bid_price:139!null tr_tt_id:140!null tr_qty:141!null + ├── columns: tr_t_id:140!null tr_bid_price:141!null tr_tt_id:142!null tr_qty:143!null ├── volatile, mutations - ├── key: (138) - ├── fd: (138)-->(139-141) + ├── key: (140) + ├── fd: (140)-->(141-143) ├── project │ ├── columns: "?column?":50 │ ├── volatile, mutations @@ -679,130 +679,129 @@ with &2 (update_last_trade) │ └── projections │ └── NULL [as="?column?":50] └── with &6 (insert_trade_history) - ├── columns: tr_t_id:138!null tr_bid_price:139!null tr_tt_id:140!null tr_qty:141!null + ├── columns: tr_t_id:140!null tr_bid_price:141!null tr_tt_id:142!null tr_qty:143!null ├── volatile, mutations - ├── key: (138) - ├── fd: (138)-->(139-141) + ├── key: (140) + ├── fd: (140)-->(141-143) ├── project - │ ├── columns: "?column?":86 + │ ├── columns: "?column?":88 │ ├── volatile, mutations - │ ├── fd: ()-->(86) + │ ├── fd: ()-->(88) │ ├── insert trade_history │ │ ├── columns: trade_history.th_t_id:51!null trade_history.th_st_id:53!null │ │ ├── insert-mapping: - │ │ │ ├── tr_t_id:56 => trade_history.th_t_id:51 - │ │ │ ├── timestamp:61 => th_dts:52 - │ │ │ └── "?column?":62 => trade_history.th_st_id:53 + │ │ │ ├── tr_t_id:62 => trade_history.th_t_id:51 + │ │ │ ├── timestamp:64 => th_dts:52 + │ │ │ └── "?column?":63 => trade_history.th_st_id:53 │ │ ├── input binding: &5 │ │ ├── volatile, mutations - │ │ ├── key: (51) │ │ ├── fd: ()-->(53) │ │ ├── project - │ │ │ ├── columns: "?column?":62 timestamp:61!null tr_t_id:56!null + │ │ │ ├── columns: tr_t_id:62!null "?column?":63!null timestamp:64!null │ │ │ ├── immutable - │ │ │ ├── key: (56) - │ │ │ ├── fd: ()-->(61,62) + │ │ │ ├── fd: ()-->(63,64) │ │ │ ├── with-scan &3 (request_list) │ │ │ │ ├── columns: tr_t_id:56!null │ │ │ │ ├── mapping: │ │ │ │ │ └── trade_request.tr_t_id:20 => tr_t_id:56 │ │ │ │ └── key: (56) │ │ │ └── projections - │ │ │ ├── assignment-cast: VARCHAR(4) [as="?column?":62, immutable] + │ │ │ ├── assignment-cast: INT8 [as=tr_t_id:62, outer=(56), immutable] + │ │ │ │ └── tr_t_id:56 + │ │ │ ├── assignment-cast: VARCHAR(4) [as="?column?":63, immutable] │ │ │ │ └── 'SBMT' - │ │ │ └── '2020-06-15 22:27:42.148484' [as=timestamp:61] + │ │ │ └── assignment-cast: TIMESTAMP [as=timestamp:64, immutable] + │ │ │ └── '2020-06-15 22:27:42.148484' │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade_history(th_t_id) -> trade(t_id) │ │ │ └── anti-join (lookup trade) - │ │ │ ├── columns: th_t_id:63!null - │ │ │ ├── key columns: [63] = [64] + │ │ │ ├── columns: th_t_id:65!null + │ │ │ ├── key columns: [65] = [66] │ │ │ ├── lookup columns are key - │ │ │ ├── key: (63) │ │ │ ├── with-scan &5 - │ │ │ │ ├── columns: th_t_id:63!null - │ │ │ │ ├── mapping: - │ │ │ │ │ └── tr_t_id:56 => th_t_id:63 - │ │ │ │ └── key: (63) + │ │ │ │ ├── columns: th_t_id:65!null + │ │ │ │ └── mapping: + │ │ │ │ └── tr_t_id:62 => th_t_id:65 │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade_history(th_st_id) -> status_type(st_id) │ │ └── anti-join (lookup status_type) - │ │ ├── columns: th_st_id:81 - │ │ ├── key columns: [81] = [82] + │ │ ├── columns: th_st_id:83!null + │ │ ├── key columns: [83] = [84] │ │ ├── lookup columns are key - │ │ ├── fd: ()-->(81) + │ │ ├── fd: ()-->(83) │ │ ├── with-scan &5 - │ │ │ ├── columns: th_st_id:81 + │ │ │ ├── columns: th_st_id:83!null │ │ │ ├── mapping: - │ │ │ │ └── "?column?":62 => th_st_id:81 - │ │ │ └── fd: ()-->(81) + │ │ │ │ └── "?column?":63 => th_st_id:83 + │ │ │ └── fd: ()-->(83) │ │ └── filters (true) │ └── projections - │ └── NULL [as="?column?":86] + │ └── NULL [as="?column?":88] └── with &8 (update_trade_submitted) - ├── columns: tr_t_id:138!null tr_bid_price:139!null tr_tt_id:140!null tr_qty:141!null + ├── columns: tr_t_id:140!null tr_bid_price:141!null tr_tt_id:142!null tr_qty:143!null ├── volatile, mutations - ├── key: (138) - ├── fd: (138)-->(139-141) + ├── key: (140) + ├── fd: (140)-->(141-143) ├── project - │ ├── columns: "?column?":137 + │ ├── columns: "?column?":139 │ ├── volatile, mutations - │ ├── fd: ()-->(137) + │ ├── fd: ()-->(139) │ ├── update trade - │ │ ├── columns: t_id:87!null - │ │ ├── fetch columns: t_id:104 t_dts:105 trade.t_st_id:106 t_tt_id:107 t_is_cash:108 t_s_symb:109 t_qty:110 t_bid_price:111 t_ca_id:112 t_exec_name:113 t_trade_price:114 t_chrg:115 t_comm:116 t_lifo:118 + │ │ ├── columns: t_id:89!null + │ │ ├── fetch columns: t_id:106 t_dts:107 trade.t_st_id:108 t_tt_id:109 t_is_cash:110 t_s_symb:111 t_qty:112 t_bid_price:113 t_ca_id:114 t_exec_name:115 t_trade_price:116 t_chrg:117 t_comm:118 t_lifo:120 │ │ ├── update-mapping: - │ │ │ ├── t_dts_new:126 => t_dts:88 - │ │ │ └── t_st_id_new:125 => trade.t_st_id:89 + │ │ │ ├── t_dts_new:128 => t_dts:90 + │ │ │ └── t_st_id_new:127 => trade.t_st_id:91 │ │ ├── input binding: &7 │ │ ├── volatile, mutations - │ │ ├── key: (87) + │ │ ├── key: (89) │ │ ├── project - │ │ │ ├── columns: t_st_id_new:125!null t_dts_new:126!null t_id:104!null t_dts:105!null trade.t_st_id:106!null t_tt_id:107!null t_is_cash:108!null t_s_symb:109!null t_qty:110!null t_bid_price:111!null t_ca_id:112!null t_exec_name:113!null t_trade_price:114 t_chrg:115!null t_comm:116!null t_lifo:118!null - │ │ │ ├── key: (104) - │ │ │ ├── fd: ()-->(125,126), (104)-->(105-116,118) + │ │ │ ├── columns: t_st_id_new:127!null t_dts_new:128!null t_id:106!null t_dts:107!null trade.t_st_id:108!null t_tt_id:109!null t_is_cash:110!null t_s_symb:111!null t_qty:112!null t_bid_price:113!null t_ca_id:114!null t_exec_name:115!null t_trade_price:116 t_chrg:117!null t_comm:118!null t_lifo:120!null + │ │ │ ├── key: (106) + │ │ │ ├── fd: ()-->(127,128), (106)-->(107-118,120) │ │ │ ├── project - │ │ │ │ ├── columns: t_id:104!null t_dts:105!null trade.t_st_id:106!null t_tt_id:107!null t_is_cash:108!null t_s_symb:109!null t_qty:110!null t_bid_price:111!null t_ca_id:112!null t_exec_name:113!null t_trade_price:114 t_chrg:115!null t_comm:116!null t_lifo:118!null - │ │ │ │ ├── key: (104) - │ │ │ │ ├── fd: (104)-->(105-116,118) + │ │ │ │ ├── columns: t_id:106!null t_dts:107!null trade.t_st_id:108!null t_tt_id:109!null t_is_cash:110!null t_s_symb:111!null t_qty:112!null t_bid_price:113!null t_ca_id:114!null t_exec_name:115!null t_trade_price:116 t_chrg:117!null t_comm:118!null t_lifo:120!null + │ │ │ │ ├── key: (106) + │ │ │ │ ├── fd: (106)-->(107-118,120) │ │ │ │ └── inner-join (lookup trade) - │ │ │ │ ├── columns: t_id:104!null t_dts:105!null trade.t_st_id:106!null t_tt_id:107!null t_is_cash:108!null t_s_symb:109!null t_qty:110!null t_bid_price:111!null t_ca_id:112!null t_exec_name:113!null t_trade_price:114 t_chrg:115!null t_comm:116!null t_lifo:118!null tr_t_id:121!null - │ │ │ │ ├── key columns: [121] = [104] + │ │ │ │ ├── columns: t_id:106!null t_dts:107!null trade.t_st_id:108!null t_tt_id:109!null t_is_cash:110!null t_s_symb:111!null t_qty:112!null t_bid_price:113!null t_ca_id:114!null t_exec_name:115!null t_trade_price:116 t_chrg:117!null t_comm:118!null t_lifo:120!null tr_t_id:123!null + │ │ │ │ ├── key columns: [123] = [106] │ │ │ │ ├── lookup columns are key - │ │ │ │ ├── key: (121) - │ │ │ │ ├── fd: (104)-->(105-116,118), (104)==(121), (121)==(104) + │ │ │ │ ├── key: (123) + │ │ │ │ ├── fd: (106)-->(107-118,120), (106)==(123), (123)==(106) │ │ │ │ ├── with-scan &3 (request_list) - │ │ │ │ │ ├── columns: tr_t_id:121!null + │ │ │ │ │ ├── columns: tr_t_id:123!null │ │ │ │ │ ├── mapping: - │ │ │ │ │ │ └── trade_request.tr_t_id:20 => tr_t_id:121 - │ │ │ │ │ └── key: (121) + │ │ │ │ │ │ └── trade_request.tr_t_id:20 => tr_t_id:123 + │ │ │ │ │ └── key: (123) │ │ │ │ └── filters (true) │ │ │ └── projections - │ │ │ ├── 'SBMT' [as=t_st_id_new:125] - │ │ │ └── '2020-06-15 22:27:42.148484' [as=t_dts_new:126] + │ │ │ ├── 'SBMT' [as=t_st_id_new:127] + │ │ │ └── '2020-06-15 22:27:42.148484' [as=t_dts_new:128] │ │ └── f-k-checks │ │ └── f-k-checks-item: trade(t_st_id) -> status_type(st_id) │ │ └── anti-join (lookup status_type) - │ │ ├── columns: t_st_id:132!null - │ │ ├── key columns: [132] = [133] + │ │ ├── columns: t_st_id:134!null + │ │ ├── key columns: [134] = [135] │ │ ├── lookup columns are key - │ │ ├── fd: ()-->(132) + │ │ ├── fd: ()-->(134) │ │ ├── with-scan &7 - │ │ │ ├── columns: t_st_id:132!null + │ │ │ ├── columns: t_st_id:134!null │ │ │ ├── mapping: - │ │ │ │ └── t_st_id_new:125 => t_st_id:132 - │ │ │ └── fd: ()-->(132) + │ │ │ │ └── t_st_id_new:127 => t_st_id:134 + │ │ │ └── fd: ()-->(134) │ │ └── filters (true) │ └── projections - │ └── NULL [as="?column?":137] + │ └── NULL [as="?column?":139] └── with-scan &3 (request_list) - ├── columns: tr_t_id:138!null tr_bid_price:139!null tr_tt_id:140!null tr_qty:141!null + ├── columns: tr_t_id:140!null tr_bid_price:141!null tr_tt_id:142!null tr_qty:143!null ├── mapping: - │ ├── trade_request.tr_t_id:20 => tr_t_id:138 - │ ├── tr_bid_price:28 => tr_bid_price:139 - │ ├── trade_request.tr_tt_id:21 => tr_tt_id:140 - │ └── trade_request.tr_qty:23 => tr_qty:141 - ├── key: (138) - └── fd: (138)-->(139-141) + │ ├── trade_request.tr_t_id:20 => tr_t_id:140 + │ ├── tr_bid_price:28 => tr_bid_price:141 + │ ├── trade_request.tr_tt_id:21 => tr_tt_id:142 + │ └── trade_request.tr_qty:23 => tr_qty:143 + ├── key: (140) + └── fd: (140)-->(141-143) # -------------------------------------------------- # T4 @@ -2954,225 +2953,233 @@ insert_trade_history AS ( SELECT 1; ---- with &2 (insert_trade) - ├── columns: "?column?":121!null + ├── columns: "?column?":129!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(121) + ├── fd: ()-->(129) ├── project - │ ├── columns: "?column?":87!null + │ ├── columns: "?column?":93!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(87) + │ ├── fd: ()-->(93) │ ├── insert trade │ │ ├── columns: t_id:1!null │ │ ├── insert-mapping: - │ │ │ ├── column1:18 => t_id:1 - │ │ │ ├── column2:19 => t_dts:2 - │ │ │ ├── column3:33 => trade.t_st_id:3 - │ │ │ ├── column4:34 => trade.t_tt_id:4 - │ │ │ ├── column5:22 => t_is_cash:5 - │ │ │ ├── column6:35 => trade.t_s_symb:6 - │ │ │ ├── column7:36 => t_qty:7 - │ │ │ ├── column8:37 => t_bid_price:8 - │ │ │ ├── column9:26 => trade.t_ca_id:9 - │ │ │ ├── column10:38 => t_exec_name:10 - │ │ │ ├── column11:28 => t_trade_price:11 - │ │ │ ├── column12:39 => t_chrg:12 - │ │ │ ├── column13:40 => t_comm:13 - │ │ │ ├── column14:41 => t_tax:14 - │ │ │ └── column15:32 => t_lifo:15 - │ │ ├── check columns: check1:42 check2:43 check3:44 check4:45 check5:46 + │ │ │ ├── column1:33 => t_id:1 + │ │ │ ├── column2:34 => t_dts:2 + │ │ │ ├── column3:35 => trade.t_st_id:3 + │ │ │ ├── column4:36 => trade.t_tt_id:4 + │ │ │ ├── column5:37 => t_is_cash:5 + │ │ │ ├── column6:38 => trade.t_s_symb:6 + │ │ │ ├── column7:39 => t_qty:7 + │ │ │ ├── column8:40 => t_bid_price:8 + │ │ │ ├── column9:41 => trade.t_ca_id:9 + │ │ │ ├── column10:42 => t_exec_name:10 + │ │ │ ├── column11:43 => t_trade_price:11 + │ │ │ ├── column12:44 => t_chrg:12 + │ │ │ ├── column13:45 => t_comm:13 + │ │ │ ├── column14:46 => t_tax:14 + │ │ │ └── column15:47 => t_lifo:15 + │ │ ├── check columns: check1:48 check2:49 check3:50 check4:51 check5:52 │ │ ├── input binding: &1 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () │ │ ├── fd: ()-->(1) │ │ ├── project - │ │ │ ├── columns: check1:42 check2:43 check3:44 check4:45 check5:46 column1:18!null column2:19!null column5:22!null column9:26!null column11:28 column15:32!null column3:33 column4:34 column6:35 column7:36 column8:37 column10:38 column12:39 column13:40 column14:41 + │ │ │ ├── columns: check1:48 check2:49 check3:50 check4:51 check5:52 column1:33 column2:34 column3:35 column4:36 column5:37 column6:38 column7:39 column8:40 column9:41 column10:42 column11:43 column12:44 column13:45 column14:46 column15:47 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(18,19,22,26,28,32-46) + │ │ │ ├── fd: ()-->(33-52) │ │ │ ├── values - │ │ │ │ ├── columns: column1:18!null column2:19!null column5:22!null column9:26!null column11:28 column15:32!null column3:33 column4:34 column6:35 column7:36 column8:37 column10:38 column12:39 column13:40 column14:41 + │ │ │ │ ├── columns: column1:33 column2:34 column3:35 column4:36 column5:37 column6:38 column7:39 column8:40 column9:41 column10:42 column11:43 column12:44 column13:45 column14:46 column15:47 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── immutable │ │ │ │ ├── key: () - │ │ │ │ ├── fd: ()-->(18,19,22,26,28,32-41) + │ │ │ │ ├── fd: ()-->(33-47) │ │ │ │ └── tuple - │ │ │ │ ├── 0 - │ │ │ │ ├── '2020-06-17 22:27:42.148484' - │ │ │ │ ├── true - │ │ │ │ ├── 0 - │ │ │ │ ├── CAST(NULL AS DECIMAL(8,2)) - │ │ │ │ ├── true + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 0 + │ │ │ │ ├── assignment-cast: TIMESTAMP + │ │ │ │ │ └── '2020-06-17 22:27:42.148484' │ │ │ │ ├── assignment-cast: VARCHAR(4) │ │ │ │ │ └── 'SBMT' │ │ │ │ ├── assignment-cast: VARCHAR(3) │ │ │ │ │ └── 'TMB' + │ │ │ │ ├── assignment-cast: BOOL + │ │ │ │ │ └── true │ │ │ │ ├── assignment-cast: VARCHAR(15) │ │ │ │ │ └── 'SYMB' │ │ │ │ ├── assignment-cast: INT4 │ │ │ │ │ └── 10 │ │ │ │ ├── assignment-cast: DECIMAL(8,2) │ │ │ │ │ └── 1E+2 + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 0 │ │ │ │ ├── assignment-cast: VARCHAR(49) │ │ │ │ │ └── 'Name' + │ │ │ │ ├── assignment-cast: DECIMAL(8,2) + │ │ │ │ │ └── CAST(NULL AS DECIMAL(8,2)) │ │ │ │ ├── assignment-cast: DECIMAL(10,2) │ │ │ │ │ └── 1 │ │ │ │ ├── assignment-cast: DECIMAL(10,2) │ │ │ │ │ └── 0 - │ │ │ │ └── assignment-cast: DECIMAL(10,2) - │ │ │ │ └── 0 + │ │ │ │ ├── assignment-cast: DECIMAL(10,2) + │ │ │ │ │ └── 0 + │ │ │ │ └── assignment-cast: BOOL + │ │ │ │ └── true │ │ │ └── projections - │ │ │ ├── column7:36 > 0 [as=check1:42, outer=(36)] - │ │ │ ├── column8:37 > 0 [as=check2:43, outer=(37), immutable] - │ │ │ ├── column12:39 >= 0 [as=check3:44, outer=(39), immutable] - │ │ │ ├── column13:40 >= 0 [as=check4:45, outer=(40), immutable] - │ │ │ └── column14:41 >= 0 [as=check5:46, outer=(41), immutable] + │ │ │ ├── column7:39 > 0 [as=check1:48, outer=(39)] + │ │ │ ├── column8:40 > 0 [as=check2:49, outer=(40), immutable] + │ │ │ ├── column12:44 >= 0 [as=check3:50, outer=(44), immutable] + │ │ │ ├── column13:45 >= 0 [as=check4:51, outer=(45), immutable] + │ │ │ └── column14:46 >= 0 [as=check5:52, outer=(46), immutable] │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade(t_st_id) -> status_type(st_id) │ │ │ └── anti-join (lookup status_type) - │ │ │ ├── columns: t_st_id:47 - │ │ │ ├── key columns: [47] = [48] + │ │ │ ├── columns: t_st_id:53 + │ │ │ ├── key columns: [53] = [54] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(47) + │ │ │ ├── fd: ()-->(53) │ │ │ ├── with-scan &1 - │ │ │ │ ├── columns: t_st_id:47 + │ │ │ │ ├── columns: t_st_id:53 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column3:33 => t_st_id:47 + │ │ │ │ │ └── column3:35 => t_st_id:53 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(47) + │ │ │ │ └── fd: ()-->(53) │ │ │ └── filters (true) │ │ ├── f-k-checks-item: trade(t_tt_id) -> trade_type(tt_id) │ │ │ └── anti-join (lookup trade_type) - │ │ │ ├── columns: t_tt_id:52 - │ │ │ ├── key columns: [52] = [53] + │ │ │ ├── columns: t_tt_id:58 + │ │ │ ├── key columns: [58] = [59] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(52) + │ │ │ ├── fd: ()-->(58) │ │ │ ├── with-scan &1 - │ │ │ │ ├── columns: t_tt_id:52 + │ │ │ │ ├── columns: t_tt_id:58 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column4:34 => t_tt_id:52 + │ │ │ │ │ └── column4:36 => t_tt_id:58 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(52) + │ │ │ │ └── fd: ()-->(58) │ │ │ └── filters (true) │ │ ├── f-k-checks-item: trade(t_s_symb) -> security(s_symb) │ │ │ └── anti-join (lookup security) - │ │ │ ├── columns: t_s_symb:59 - │ │ │ ├── key columns: [59] = [60] + │ │ │ ├── columns: t_s_symb:65 + │ │ │ ├── key columns: [65] = [66] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(59) + │ │ │ ├── fd: ()-->(65) │ │ │ ├── with-scan &1 - │ │ │ │ ├── columns: t_s_symb:59 + │ │ │ │ ├── columns: t_s_symb:65 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column6:35 => t_s_symb:59 + │ │ │ │ │ └── column6:38 => t_s_symb:65 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(59) + │ │ │ │ └── fd: ()-->(65) │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade(t_ca_id) -> customer_account(ca_id) │ │ └── anti-join (lookup customer_account) - │ │ ├── columns: t_ca_id:78!null - │ │ ├── key columns: [78] = [79] + │ │ ├── columns: t_ca_id:84 + │ │ ├── key columns: [84] = [85] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(78) + │ │ ├── fd: ()-->(84) │ │ ├── with-scan &1 - │ │ │ ├── columns: t_ca_id:78!null + │ │ │ ├── columns: t_ca_id:84 │ │ │ ├── mapping: - │ │ │ │ └── column9:26 => t_ca_id:78 + │ │ │ │ └── column9:41 => t_ca_id:84 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(78) + │ │ │ └── fd: ()-->(84) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":87] + │ └── 1 [as="?column?":93] └── with &4 (insert_trade_history) - ├── columns: "?column?":121!null + ├── columns: "?column?":129!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(121) + ├── fd: ()-->(129) ├── project - │ ├── columns: "?column?":120!null + │ ├── columns: "?column?":128!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(120) + │ ├── fd: ()-->(128) │ ├── insert trade_history - │ │ ├── columns: trade_history.th_t_id:88!null trade_history.th_st_id:90!null + │ │ ├── columns: trade_history.th_t_id:94!null trade_history.th_st_id:96!null │ │ ├── insert-mapping: - │ │ │ ├── column1:93 => trade_history.th_t_id:88 - │ │ │ ├── column2:94 => th_dts:89 - │ │ │ └── column3:96 => trade_history.th_st_id:90 + │ │ │ ├── column1:102 => trade_history.th_t_id:94 + │ │ │ ├── column2:103 => th_dts:95 + │ │ │ └── column3:104 => trade_history.th_st_id:96 │ │ ├── input binding: &3 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () - │ │ ├── fd: ()-->(88,90) + │ │ ├── fd: ()-->(94,96) │ │ ├── values - │ │ │ ├── columns: column1:93!null column2:94!null column3:96 + │ │ │ ├── columns: column1:102 column2:103 column3:104 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(93,94,96) + │ │ │ ├── fd: ()-->(102-104) │ │ │ └── tuple - │ │ │ ├── 0 - │ │ │ ├── '2020-06-15 22:27:42.148484' + │ │ │ ├── assignment-cast: INT8 + │ │ │ │ └── 0 + │ │ │ ├── assignment-cast: TIMESTAMP + │ │ │ │ └── '2020-06-15 22:27:42.148484' │ │ │ └── assignment-cast: VARCHAR(4) │ │ │ └── 'SBMT' │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade_history(th_t_id) -> trade(t_id) │ │ │ └── anti-join (lookup trade) - │ │ │ ├── columns: th_t_id:97!null - │ │ │ ├── key columns: [97] = [98] + │ │ │ ├── columns: th_t_id:105 + │ │ │ ├── key columns: [105] = [106] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(97) + │ │ │ ├── fd: ()-->(105) │ │ │ ├── with-scan &3 - │ │ │ │ ├── columns: th_t_id:97!null + │ │ │ │ ├── columns: th_t_id:105 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column1:93 => th_t_id:97 + │ │ │ │ │ └── column1:102 => th_t_id:105 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(97) + │ │ │ │ └── fd: ()-->(105) │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade_history(th_st_id) -> status_type(st_id) │ │ └── anti-join (lookup status_type) - │ │ ├── columns: th_st_id:115 - │ │ ├── key columns: [115] = [116] + │ │ ├── columns: th_st_id:123 + │ │ ├── key columns: [123] = [124] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(115) + │ │ ├── fd: ()-->(123) │ │ ├── with-scan &3 - │ │ │ ├── columns: th_st_id:115 + │ │ │ ├── columns: th_st_id:123 │ │ │ ├── mapping: - │ │ │ │ └── column3:96 => th_st_id:115 + │ │ │ │ └── column3:104 => th_st_id:123 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(115) + │ │ │ └── fd: ()-->(123) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":120] + │ └── 1 [as="?column?":128] └── values - ├── columns: "?column?":121!null + ├── columns: "?column?":129!null ├── cardinality: [1 - 1] ├── key: () - ├── fd: ()-->(121) + ├── fd: ()-->(129) └── (1,) # Q12 @@ -3246,347 +3253,357 @@ insert_trade_request AS ( SELECT 1; ---- with &2 (insert_trade) - ├── columns: "?column?":195!null + ├── columns: "?column?":205!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(195) + ├── fd: ()-->(205) ├── project - │ ├── columns: "?column?":87!null + │ ├── columns: "?column?":93!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(87) + │ ├── fd: ()-->(93) │ ├── insert trade │ │ ├── columns: t_id:1!null │ │ ├── insert-mapping: - │ │ │ ├── column1:18 => t_id:1 - │ │ │ ├── column2:19 => t_dts:2 - │ │ │ ├── column3:33 => trade.t_st_id:3 - │ │ │ ├── column4:34 => trade.t_tt_id:4 - │ │ │ ├── column5:22 => t_is_cash:5 - │ │ │ ├── column6:35 => trade.t_s_symb:6 - │ │ │ ├── column7:36 => t_qty:7 - │ │ │ ├── column8:37 => t_bid_price:8 - │ │ │ ├── column9:26 => trade.t_ca_id:9 - │ │ │ ├── column10:38 => t_exec_name:10 - │ │ │ ├── column11:28 => t_trade_price:11 - │ │ │ ├── column12:39 => t_chrg:12 - │ │ │ ├── column13:40 => t_comm:13 - │ │ │ ├── column14:41 => t_tax:14 - │ │ │ └── column15:32 => t_lifo:15 - │ │ ├── check columns: check1:42 check2:43 check3:44 check4:45 check5:46 + │ │ │ ├── column1:33 => t_id:1 + │ │ │ ├── column2:34 => t_dts:2 + │ │ │ ├── column3:35 => trade.t_st_id:3 + │ │ │ ├── column4:36 => trade.t_tt_id:4 + │ │ │ ├── column5:37 => t_is_cash:5 + │ │ │ ├── column6:38 => trade.t_s_symb:6 + │ │ │ ├── column7:39 => t_qty:7 + │ │ │ ├── column8:40 => t_bid_price:8 + │ │ │ ├── column9:41 => trade.t_ca_id:9 + │ │ │ ├── column10:42 => t_exec_name:10 + │ │ │ ├── column11:43 => t_trade_price:11 + │ │ │ ├── column12:44 => t_chrg:12 + │ │ │ ├── column13:45 => t_comm:13 + │ │ │ ├── column14:46 => t_tax:14 + │ │ │ └── column15:47 => t_lifo:15 + │ │ ├── check columns: check1:48 check2:49 check3:50 check4:51 check5:52 │ │ ├── input binding: &1 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () │ │ ├── fd: ()-->(1) │ │ ├── project - │ │ │ ├── columns: check1:42 check2:43 check3:44 check4:45 check5:46 column1:18!null column2:19!null column5:22!null column9:26!null column11:28 column15:32!null column3:33 column4:34 column6:35 column7:36 column8:37 column10:38 column12:39 column13:40 column14:41 + │ │ │ ├── columns: check1:48 check2:49 check3:50 check4:51 check5:52 column1:33 column2:34 column3:35 column4:36 column5:37 column6:38 column7:39 column8:40 column9:41 column10:42 column11:43 column12:44 column13:45 column14:46 column15:47 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(18,19,22,26,28,32-46) + │ │ │ ├── fd: ()-->(33-52) │ │ │ ├── values - │ │ │ │ ├── columns: column1:18!null column2:19!null column5:22!null column9:26!null column11:28 column15:32!null column3:33 column4:34 column6:35 column7:36 column8:37 column10:38 column12:39 column13:40 column14:41 + │ │ │ │ ├── columns: column1:33 column2:34 column3:35 column4:36 column5:37 column6:38 column7:39 column8:40 column9:41 column10:42 column11:43 column12:44 column13:45 column14:46 column15:47 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── immutable │ │ │ │ ├── key: () - │ │ │ │ ├── fd: ()-->(18,19,22,26,28,32-41) + │ │ │ │ ├── fd: ()-->(33-47) │ │ │ │ └── tuple - │ │ │ │ ├── 0 - │ │ │ │ ├── '2020-06-17 22:27:42.148484' - │ │ │ │ ├── true - │ │ │ │ ├── 0 - │ │ │ │ ├── CAST(NULL AS DECIMAL(8,2)) - │ │ │ │ ├── true + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 0 + │ │ │ │ ├── assignment-cast: TIMESTAMP + │ │ │ │ │ └── '2020-06-17 22:27:42.148484' │ │ │ │ ├── assignment-cast: VARCHAR(4) │ │ │ │ │ └── 'SBMT' │ │ │ │ ├── assignment-cast: VARCHAR(3) │ │ │ │ │ └── 'TMB' + │ │ │ │ ├── assignment-cast: BOOL + │ │ │ │ │ └── true │ │ │ │ ├── assignment-cast: VARCHAR(15) │ │ │ │ │ └── 'SYMB' │ │ │ │ ├── assignment-cast: INT4 │ │ │ │ │ └── 10 │ │ │ │ ├── assignment-cast: DECIMAL(8,2) │ │ │ │ │ └── 1E+2 + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 0 │ │ │ │ ├── assignment-cast: VARCHAR(49) │ │ │ │ │ └── 'Name' + │ │ │ │ ├── assignment-cast: DECIMAL(8,2) + │ │ │ │ │ └── CAST(NULL AS DECIMAL(8,2)) │ │ │ │ ├── assignment-cast: DECIMAL(10,2) │ │ │ │ │ └── 1 │ │ │ │ ├── assignment-cast: DECIMAL(10,2) │ │ │ │ │ └── 0 - │ │ │ │ └── assignment-cast: DECIMAL(10,2) - │ │ │ │ └── 0 + │ │ │ │ ├── assignment-cast: DECIMAL(10,2) + │ │ │ │ │ └── 0 + │ │ │ │ └── assignment-cast: BOOL + │ │ │ │ └── true │ │ │ └── projections - │ │ │ ├── column7:36 > 0 [as=check1:42, outer=(36)] - │ │ │ ├── column8:37 > 0 [as=check2:43, outer=(37), immutable] - │ │ │ ├── column12:39 >= 0 [as=check3:44, outer=(39), immutable] - │ │ │ ├── column13:40 >= 0 [as=check4:45, outer=(40), immutable] - │ │ │ └── column14:41 >= 0 [as=check5:46, outer=(41), immutable] + │ │ │ ├── column7:39 > 0 [as=check1:48, outer=(39)] + │ │ │ ├── column8:40 > 0 [as=check2:49, outer=(40), immutable] + │ │ │ ├── column12:44 >= 0 [as=check3:50, outer=(44), immutable] + │ │ │ ├── column13:45 >= 0 [as=check4:51, outer=(45), immutable] + │ │ │ └── column14:46 >= 0 [as=check5:52, outer=(46), immutable] │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade(t_st_id) -> status_type(st_id) │ │ │ └── anti-join (lookup status_type) - │ │ │ ├── columns: t_st_id:47 - │ │ │ ├── key columns: [47] = [48] + │ │ │ ├── columns: t_st_id:53 + │ │ │ ├── key columns: [53] = [54] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(47) + │ │ │ ├── fd: ()-->(53) │ │ │ ├── with-scan &1 - │ │ │ │ ├── columns: t_st_id:47 + │ │ │ │ ├── columns: t_st_id:53 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column3:33 => t_st_id:47 + │ │ │ │ │ └── column3:35 => t_st_id:53 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(47) + │ │ │ │ └── fd: ()-->(53) │ │ │ └── filters (true) │ │ ├── f-k-checks-item: trade(t_tt_id) -> trade_type(tt_id) │ │ │ └── anti-join (lookup trade_type) - │ │ │ ├── columns: t_tt_id:52 - │ │ │ ├── key columns: [52] = [53] + │ │ │ ├── columns: t_tt_id:58 + │ │ │ ├── key columns: [58] = [59] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(52) + │ │ │ ├── fd: ()-->(58) │ │ │ ├── with-scan &1 - │ │ │ │ ├── columns: t_tt_id:52 + │ │ │ │ ├── columns: t_tt_id:58 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column4:34 => t_tt_id:52 + │ │ │ │ │ └── column4:36 => t_tt_id:58 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(52) + │ │ │ │ └── fd: ()-->(58) │ │ │ └── filters (true) │ │ ├── f-k-checks-item: trade(t_s_symb) -> security(s_symb) │ │ │ └── anti-join (lookup security) - │ │ │ ├── columns: t_s_symb:59 - │ │ │ ├── key columns: [59] = [60] + │ │ │ ├── columns: t_s_symb:65 + │ │ │ ├── key columns: [65] = [66] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(59) + │ │ │ ├── fd: ()-->(65) │ │ │ ├── with-scan &1 - │ │ │ │ ├── columns: t_s_symb:59 + │ │ │ │ ├── columns: t_s_symb:65 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column6:35 => t_s_symb:59 + │ │ │ │ │ └── column6:38 => t_s_symb:65 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(59) + │ │ │ │ └── fd: ()-->(65) │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade(t_ca_id) -> customer_account(ca_id) │ │ └── anti-join (lookup customer_account) - │ │ ├── columns: t_ca_id:78!null - │ │ ├── key columns: [78] = [79] + │ │ ├── columns: t_ca_id:84 + │ │ ├── key columns: [84] = [85] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(78) + │ │ ├── fd: ()-->(84) │ │ ├── with-scan &1 - │ │ │ ├── columns: t_ca_id:78!null + │ │ │ ├── columns: t_ca_id:84 │ │ │ ├── mapping: - │ │ │ │ └── column9:26 => t_ca_id:78 + │ │ │ │ └── column9:41 => t_ca_id:84 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(78) + │ │ │ └── fd: ()-->(84) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":87] + │ └── 1 [as="?column?":93] └── with &4 (insert_trade_history) - ├── columns: "?column?":195!null + ├── columns: "?column?":205!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(195) + ├── fd: ()-->(205) ├── project - │ ├── columns: "?column?":120!null + │ ├── columns: "?column?":128!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(120) + │ ├── fd: ()-->(128) │ ├── insert trade_history - │ │ ├── columns: trade_history.th_t_id:88!null trade_history.th_st_id:90!null + │ │ ├── columns: trade_history.th_t_id:94!null trade_history.th_st_id:96!null │ │ ├── insert-mapping: - │ │ │ ├── column1:93 => trade_history.th_t_id:88 - │ │ │ ├── column2:94 => th_dts:89 - │ │ │ └── column3:96 => trade_history.th_st_id:90 + │ │ │ ├── column1:102 => trade_history.th_t_id:94 + │ │ │ ├── column2:103 => th_dts:95 + │ │ │ └── column3:104 => trade_history.th_st_id:96 │ │ ├── input binding: &3 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () - │ │ ├── fd: ()-->(88,90) + │ │ ├── fd: ()-->(94,96) │ │ ├── values - │ │ │ ├── columns: column1:93!null column2:94!null column3:96 + │ │ │ ├── columns: column1:102 column2:103 column3:104 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(93,94,96) + │ │ │ ├── fd: ()-->(102-104) │ │ │ └── tuple - │ │ │ ├── 0 - │ │ │ ├── '2020-06-15 22:27:42.148484' + │ │ │ ├── assignment-cast: INT8 + │ │ │ │ └── 0 + │ │ │ ├── assignment-cast: TIMESTAMP + │ │ │ │ └── '2020-06-15 22:27:42.148484' │ │ │ └── assignment-cast: VARCHAR(4) │ │ │ └── 'SBMT' │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade_history(th_t_id) -> trade(t_id) │ │ │ └── anti-join (lookup trade) - │ │ │ ├── columns: th_t_id:97!null - │ │ │ ├── key columns: [97] = [98] + │ │ │ ├── columns: th_t_id:105 + │ │ │ ├── key columns: [105] = [106] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(97) + │ │ │ ├── fd: ()-->(105) │ │ │ ├── with-scan &3 - │ │ │ │ ├── columns: th_t_id:97!null + │ │ │ │ ├── columns: th_t_id:105 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column1:93 => th_t_id:97 + │ │ │ │ │ └── column1:102 => th_t_id:105 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(97) + │ │ │ │ └── fd: ()-->(105) │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade_history(th_st_id) -> status_type(st_id) │ │ └── anti-join (lookup status_type) - │ │ ├── columns: th_st_id:115 - │ │ ├── key columns: [115] = [116] + │ │ ├── columns: th_st_id:123 + │ │ ├── key columns: [123] = [124] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(115) + │ │ ├── fd: ()-->(123) │ │ ├── with-scan &3 - │ │ │ ├── columns: th_st_id:115 + │ │ │ ├── columns: th_st_id:123 │ │ │ ├── mapping: - │ │ │ │ └── column3:96 => th_st_id:115 + │ │ │ │ └── column3:104 => th_st_id:123 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(115) + │ │ │ └── fd: ()-->(123) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":120] + │ └── 1 [as="?column?":128] └── with &6 (insert_trade_request) - ├── columns: "?column?":195!null + ├── columns: "?column?":205!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(195) + ├── fd: ()-->(205) ├── project - │ ├── columns: "?column?":194!null + │ ├── columns: "?column?":204!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(194) + │ ├── fd: ()-->(204) │ ├── insert trade_request - │ │ ├── columns: trade_request.tr_t_id:121!null + │ │ ├── columns: trade_request.tr_t_id:129!null │ │ ├── insert-mapping: - │ │ │ ├── column1:129 => trade_request.tr_t_id:121 - │ │ │ ├── column2:135 => trade_request.tr_tt_id:122 - │ │ │ ├── column3:136 => trade_request.tr_s_symb:123 - │ │ │ ├── column4:137 => tr_qty:124 - │ │ │ ├── column5:138 => tr_bid_price:125 - │ │ │ └── column6:134 => trade_request.tr_b_id:126 - │ │ ├── check columns: check1:139 check2:140 - │ │ ├── partial index put columns: partial_index_put1:141 + │ │ │ ├── column1:143 => trade_request.tr_t_id:129 + │ │ │ ├── column2:144 => trade_request.tr_tt_id:130 + │ │ │ ├── column3:145 => trade_request.tr_s_symb:131 + │ │ │ ├── column4:146 => tr_qty:132 + │ │ │ ├── column5:147 => tr_bid_price:133 + │ │ │ └── column6:148 => trade_request.tr_b_id:134 + │ │ ├── check columns: check1:149 check2:150 + │ │ ├── partial index put columns: partial_index_put1:151 │ │ ├── input binding: &5 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () - │ │ ├── fd: ()-->(121) + │ │ ├── fd: ()-->(129) │ │ ├── project - │ │ │ ├── columns: partial_index_put1:141 check1:139 check2:140 column1:129!null column6:134!null column2:135 column3:136 column4:137 column5:138 + │ │ │ ├── columns: partial_index_put1:151 check1:149 check2:150 column1:143 column2:144 column3:145 column4:146 column5:147 column6:148 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(129,134-141) + │ │ │ ├── fd: ()-->(143-151) │ │ │ ├── values - │ │ │ │ ├── columns: column1:129!null column6:134!null column2:135 column3:136 column4:137 column5:138 + │ │ │ │ ├── columns: column1:143 column2:144 column3:145 column4:146 column5:147 column6:148 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── immutable │ │ │ │ ├── key: () - │ │ │ │ ├── fd: ()-->(129,134-138) + │ │ │ │ ├── fd: ()-->(143-148) │ │ │ │ └── tuple - │ │ │ │ ├── 0 - │ │ │ │ ├── 0 + │ │ │ │ ├── assignment-cast: INT8 + │ │ │ │ │ └── 0 │ │ │ │ ├── assignment-cast: VARCHAR(3) │ │ │ │ │ └── 'TMB' │ │ │ │ ├── assignment-cast: VARCHAR(15) │ │ │ │ │ └── 'SYMB' │ │ │ │ ├── assignment-cast: INT4 │ │ │ │ │ └── 10 - │ │ │ │ └── assignment-cast: DECIMAL(8,2) - │ │ │ │ └── 1E+2 + │ │ │ │ ├── assignment-cast: DECIMAL(8,2) + │ │ │ │ │ └── 1E+2 + │ │ │ │ └── assignment-cast: INT8 + │ │ │ │ └── 0 │ │ │ └── projections - │ │ │ ├── column2:135 IN ('TLB', 'TLS', 'TSL') [as=partial_index_put1:141, outer=(135)] - │ │ │ ├── column4:137 > 0 [as=check1:139, outer=(137)] - │ │ │ └── column5:138 > 0 [as=check2:140, outer=(138), immutable] + │ │ │ ├── column2:144 IN ('TLB', 'TLS', 'TSL') [as=partial_index_put1:151, outer=(144)] + │ │ │ ├── column4:146 > 0 [as=check1:149, outer=(146)] + │ │ │ └── column5:147 > 0 [as=check2:150, outer=(147), immutable] │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade_request(tr_t_id) -> trade(t_id) │ │ │ └── anti-join (lookup trade) - │ │ │ ├── columns: tr_t_id:142!null - │ │ │ ├── key columns: [142] = [143] + │ │ │ ├── columns: tr_t_id:152 + │ │ │ ├── key columns: [152] = [153] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(142) + │ │ │ ├── fd: ()-->(152) │ │ │ ├── with-scan &5 - │ │ │ │ ├── columns: tr_t_id:142!null + │ │ │ │ ├── columns: tr_t_id:152 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column1:129 => tr_t_id:142 + │ │ │ │ │ └── column1:143 => tr_t_id:152 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(142) + │ │ │ │ └── fd: ()-->(152) │ │ │ └── filters (true) │ │ ├── f-k-checks-item: trade_request(tr_tt_id) -> trade_type(tt_id) │ │ │ └── anti-join (lookup trade_type) - │ │ │ ├── columns: tr_tt_id:160 - │ │ │ ├── key columns: [160] = [161] + │ │ │ ├── columns: tr_tt_id:170 + │ │ │ ├── key columns: [170] = [171] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(160) + │ │ │ ├── fd: ()-->(170) │ │ │ ├── with-scan &5 - │ │ │ │ ├── columns: tr_tt_id:160 + │ │ │ │ ├── columns: tr_tt_id:170 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column2:135 => tr_tt_id:160 + │ │ │ │ │ └── column2:144 => tr_tt_id:170 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(160) + │ │ │ │ └── fd: ()-->(170) │ │ │ └── filters (true) │ │ ├── f-k-checks-item: trade_request(tr_s_symb) -> security(s_symb) │ │ │ └── anti-join (lookup security) - │ │ │ ├── columns: tr_s_symb:167 - │ │ │ ├── key columns: [167] = [168] + │ │ │ ├── columns: tr_s_symb:177 + │ │ │ ├── key columns: [177] = [178] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(167) + │ │ │ ├── fd: ()-->(177) │ │ │ ├── with-scan &5 - │ │ │ │ ├── columns: tr_s_symb:167 + │ │ │ │ ├── columns: tr_s_symb:177 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column3:136 => tr_s_symb:167 + │ │ │ │ │ └── column3:145 => tr_s_symb:177 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(167) + │ │ │ │ └── fd: ()-->(177) │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade_request(tr_b_id) -> broker(b_id) │ │ └── anti-join (lookup broker) - │ │ ├── columns: tr_b_id:186!null - │ │ ├── key columns: [186] = [187] + │ │ ├── columns: tr_b_id:196 + │ │ ├── key columns: [196] = [197] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(186) + │ │ ├── fd: ()-->(196) │ │ ├── with-scan &5 - │ │ │ ├── columns: tr_b_id:186!null + │ │ │ ├── columns: tr_b_id:196 │ │ │ ├── mapping: - │ │ │ │ └── column6:134 => tr_b_id:186 + │ │ │ │ └── column6:148 => tr_b_id:196 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(186) + │ │ │ └── fd: ()-->(196) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":194] + │ └── 1 [as="?column?":204] └── values - ├── columns: "?column?":195!null + ├── columns: "?column?":205!null ├── cardinality: [1 - 1] ├── key: () - ├── fd: ()-->(195) + ├── fd: ()-->(205) └── (1,) # -------------------------------------------------- @@ -3736,20 +3753,21 @@ INSERT INTO holding_summary (hs_ca_id, hs_s_symb, hs_qty) VALUES (0, 'ROACH', 10 insert holding_summary ├── columns: ├── insert-mapping: - │ ├── column1:6 => holding_summary.hs_ca_id:1 - │ ├── column2:9 => holding_summary.hs_s_symb:2 - │ └── column3:10 => hs_qty:3 + │ ├── column1:9 => holding_summary.hs_ca_id:1 + │ ├── column2:10 => holding_summary.hs_s_symb:2 + │ └── column3:11 => hs_qty:3 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── values - │ ├── columns: column1:6!null column2:9 column3:10 + │ ├── columns: column1:9 column2:10 column3:11 │ ├── cardinality: [1 - 1] │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(6,9,10) + │ ├── fd: ()-->(9-11) │ └── tuple - │ ├── 0 + │ ├── assignment-cast: INT8 + │ │ └── 0 │ ├── assignment-cast: VARCHAR(15) │ │ └── 'ROACH' │ └── assignment-cast: INT4 @@ -3757,35 +3775,35 @@ insert holding_summary └── f-k-checks ├── f-k-checks-item: holding_summary(hs_ca_id) -> customer_account(ca_id) │ └── anti-join (lookup customer_account) - │ ├── columns: hs_ca_id:11!null - │ ├── key columns: [11] = [12] + │ ├── columns: hs_ca_id:12 + │ ├── key columns: [12] = [13] │ ├── lookup columns are key │ ├── cardinality: [0 - 1] │ ├── key: () - │ ├── fd: ()-->(11) + │ ├── fd: ()-->(12) │ ├── with-scan &1 - │ │ ├── columns: hs_ca_id:11!null + │ │ ├── columns: hs_ca_id:12 │ │ ├── mapping: - │ │ │ └── column1:6 => hs_ca_id:11 + │ │ │ └── column1:9 => hs_ca_id:12 │ │ ├── cardinality: [1 - 1] │ │ ├── key: () - │ │ └── fd: ()-->(11) + │ │ └── fd: ()-->(12) │ └── filters (true) └── f-k-checks-item: holding_summary(hs_s_symb) -> security(s_symb) └── anti-join (lookup security) - ├── columns: hs_s_symb:20 - ├── key columns: [20] = [21] + ├── columns: hs_s_symb:21 + ├── key columns: [21] = [22] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(20) + ├── fd: ()-->(21) ├── with-scan &1 - │ ├── columns: hs_s_symb:20 + │ ├── columns: hs_s_symb:21 │ ├── mapping: - │ │ └── column2:9 => hs_s_symb:20 + │ │ └── column2:10 => hs_s_symb:21 │ ├── cardinality: [1 - 1] │ ├── key: () - │ └── fd: ()-->(20) + │ └── fd: ()-->(21) └── filters (true) # Q4 @@ -3873,17 +3891,18 @@ INSERT INTO holding_history (hh_h_t_id, hh_t_id, hh_before_qty, hh_after_qty) insert holding_history ├── columns: ├── insert-mapping: - │ ├── unnest:7 => holding_history.hh_h_t_id:1 - │ ├── "?column?":10 => holding_history.hh_t_id:2 - │ ├── unnest:8 => hh_before_qty:3 - │ └── unnest:9 => hh_after_qty:4 + │ ├── unnest:11 => holding_history.hh_h_t_id:1 + │ ├── "?column?":12 => holding_history.hh_t_id:2 + │ ├── unnest:13 => hh_before_qty:3 + │ └── unnest:14 => hh_after_qty:4 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── project - │ ├── columns: "?column?":10!null unnest:7!null unnest:8!null unnest:9!null + │ ├── columns: unnest:11!null "?column?":12!null unnest:13!null unnest:14!null │ ├── cardinality: [3 - 3] - │ ├── fd: ()-->(10) + │ ├── immutable + │ ├── fd: ()-->(12) │ ├── values │ │ ├── columns: unnest:7!null unnest:8!null unnest:9!null │ │ ├── cardinality: [3 - 3] @@ -3891,33 +3910,40 @@ insert holding_history │ │ ├── (2, 20, 30) │ │ └── (3, 30, 40) │ └── projections - │ └── 0 [as="?column?":10] + │ ├── assignment-cast: INT8 [as=unnest:11, outer=(7), immutable] + │ │ └── unnest:7 + │ ├── assignment-cast: INT8 [as="?column?":12, immutable] + │ │ └── 0 + │ ├── assignment-cast: INT4 [as=unnest:13, outer=(8), immutable] + │ │ └── unnest:8 + │ └── assignment-cast: INT4 [as=unnest:14, outer=(9), immutable] + │ └── unnest:9 └── f-k-checks ├── f-k-checks-item: holding_history(hh_h_t_id) -> trade(t_id) │ └── anti-join (lookup trade) - │ ├── columns: hh_h_t_id:11!null - │ ├── key columns: [11] = [12] + │ ├── columns: hh_h_t_id:15!null + │ ├── key columns: [15] = [16] │ ├── lookup columns are key │ ├── cardinality: [0 - 3] │ ├── with-scan &1 - │ │ ├── columns: hh_h_t_id:11!null + │ │ ├── columns: hh_h_t_id:15!null │ │ ├── mapping: - │ │ │ └── unnest:7 => hh_h_t_id:11 + │ │ │ └── unnest:11 => hh_h_t_id:15 │ │ └── cardinality: [3 - 3] │ └── filters (true) └── f-k-checks-item: holding_history(hh_t_id) -> trade(t_id) └── anti-join (lookup trade) - ├── columns: hh_t_id:29!null - ├── key columns: [29] = [30] + ├── columns: hh_t_id:33!null + ├── key columns: [33] = [34] ├── lookup columns are key ├── cardinality: [0 - 3] - ├── fd: ()-->(29) + ├── fd: ()-->(33) ├── with-scan &1 - │ ├── columns: hh_t_id:29!null + │ ├── columns: hh_t_id:33!null │ ├── mapping: - │ │ └── "?column?":10 => hh_t_id:29 + │ │ └── "?column?":12 => hh_t_id:33 │ ├── cardinality: [3 - 3] - │ └── fd: ()-->(29) + │ └── fd: ()-->(33) └── filters (true) # Q8 @@ -3979,73 +4005,76 @@ VALUES insert holding ├── columns: ├── insert-mapping: - │ ├── column1:9 => holding.h_t_id:1 - │ ├── column2:10 => holding.h_ca_id:2 - │ ├── column3:15 => holding.h_s_symb:3 - │ ├── column4:12 => h_dts:4 - │ ├── column5:16 => h_price:5 - │ └── column6:17 => h_qty:6 - ├── check columns: check1:18 + │ ├── column1:15 => holding.h_t_id:1 + │ ├── column2:16 => holding.h_ca_id:2 + │ ├── column3:17 => holding.h_s_symb:3 + │ ├── column4:18 => h_dts:4 + │ ├── column5:19 => h_price:5 + │ └── column6:20 => h_qty:6 + ├── check columns: check1:21 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── project - │ ├── columns: check1:18 column1:9!null column2:10!null column4:12!null column3:15 column5:16 column6:17 + │ ├── columns: check1:21 column1:15 column2:16 column3:17 column4:18 column5:19 column6:20 │ ├── cardinality: [1 - 1] │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(9,10,12,15-18) + │ ├── fd: ()-->(15-21) │ ├── values - │ │ ├── columns: column1:9!null column2:10!null column4:12!null column3:15 column5:16 column6:17 + │ │ ├── columns: column1:15 column2:16 column3:17 column4:18 column5:19 column6:20 │ │ ├── cardinality: [1 - 1] │ │ ├── immutable │ │ ├── key: () - │ │ ├── fd: ()-->(9,10,12,15-17) + │ │ ├── fd: ()-->(15-20) │ │ └── tuple - │ │ ├── 0 - │ │ ├── 0 - │ │ ├── '2020-06-15 22:27:42.148484' + │ │ ├── assignment-cast: INT8 + │ │ │ └── 0 + │ │ ├── assignment-cast: INT8 + │ │ │ └── 0 │ │ ├── assignment-cast: VARCHAR(15) │ │ │ └── 'ROACH' + │ │ ├── assignment-cast: TIMESTAMP + │ │ │ └── '2020-06-15 22:27:42.148484' │ │ ├── assignment-cast: DECIMAL(8,2) │ │ │ └── 1E+2 │ │ └── assignment-cast: INT4 │ │ └── 10 │ └── projections - │ └── column5:16 > 0 [as=check1:18, outer=(16), immutable] + │ └── column5:19 > 0 [as=check1:21, outer=(19), immutable] └── f-k-checks ├── f-k-checks-item: holding(h_t_id) -> trade(t_id) │ └── anti-join (lookup trade) - │ ├── columns: h_t_id:19!null - │ ├── key columns: [19] = [20] + │ ├── columns: h_t_id:22 + │ ├── key columns: [22] = [23] │ ├── lookup columns are key │ ├── cardinality: [0 - 1] │ ├── key: () - │ ├── fd: ()-->(19) + │ ├── fd: ()-->(22) │ ├── with-scan &1 - │ │ ├── columns: h_t_id:19!null + │ │ ├── columns: h_t_id:22 │ │ ├── mapping: - │ │ │ └── column1:9 => h_t_id:19 + │ │ │ └── column1:15 => h_t_id:22 │ │ ├── cardinality: [1 - 1] │ │ ├── key: () - │ │ └── fd: ()-->(19) + │ │ └── fd: ()-->(22) │ └── filters (true) └── f-k-checks-item: holding(h_ca_id,h_s_symb) -> holding_summary(hs_ca_id,hs_s_symb) └── anti-join (lookup holding_summary) - ├── columns: h_ca_id:37!null h_s_symb:38 - ├── key columns: [37 38] = [39 40] + ├── columns: h_ca_id:40 h_s_symb:41 + ├── key columns: [40 41] = [42 43] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(37,38) + ├── fd: ()-->(40,41) ├── with-scan &1 - │ ├── columns: h_ca_id:37!null h_s_symb:38 + │ ├── columns: h_ca_id:40 h_s_symb:41 │ ├── mapping: - │ │ ├── column2:10 => h_ca_id:37 - │ │ └── column3:15 => h_s_symb:38 + │ │ ├── column2:16 => h_ca_id:40 + │ │ └── column3:17 => h_s_symb:41 │ ├── cardinality: [1 - 1] │ ├── key: () - │ └── fd: ()-->(37,38) + │ └── fd: ()-->(40,41) └── filters (true) # Q11 @@ -4317,11 +4346,11 @@ insert_trade_history AS ( SELECT 1 ---- with &2 (update_trade_commission) - ├── columns: "?column?":103!null + ├── columns: "?column?":105!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(103) + ├── fd: ()-->(105) ├── project │ ├── columns: "?column?":51!null │ ├── cardinality: [0 - 1] @@ -4379,11 +4408,11 @@ with &2 (update_trade_commission) │ └── projections │ └── 1 [as="?column?":51] └── with &4 (update_broker_commission) - ├── columns: "?column?":103!null + ├── columns: "?column?":105!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(103) + ├── fd: ()-->(105) ├── project │ ├── columns: "?column?":69!null │ ├── cardinality: [0 - 1] @@ -4418,79 +4447,81 @@ with &2 (update_trade_commission) │ └── projections │ └── 1 [as="?column?":69] └── with &6 (insert_trade_history) - ├── columns: "?column?":103!null + ├── columns: "?column?":105!null ├── cardinality: [1 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(103) + ├── fd: ()-->(105) ├── project - │ ├── columns: "?column?":102!null + │ ├── columns: "?column?":104!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(102) + │ ├── fd: ()-->(104) │ ├── insert trade_history │ │ ├── columns: trade_history.th_t_id:70!null trade_history.th_st_id:72!null │ │ ├── insert-mapping: - │ │ │ ├── column1:75 => trade_history.th_t_id:70 - │ │ │ ├── column2:76 => th_dts:71 - │ │ │ └── column3:78 => trade_history.th_st_id:72 + │ │ │ ├── column1:78 => trade_history.th_t_id:70 + │ │ │ ├── column2:79 => th_dts:71 + │ │ │ └── column3:80 => trade_history.th_st_id:72 │ │ ├── input binding: &5 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () │ │ ├── fd: ()-->(70,72) │ │ ├── values - │ │ │ ├── columns: column1:75!null column2:76!null column3:78 + │ │ │ ├── columns: column1:78 column2:79 column3:80 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(75,76,78) + │ │ │ ├── fd: ()-->(78-80) │ │ │ └── tuple - │ │ │ ├── 0 - │ │ │ ├── '2020-06-15 22:27:42.148484' + │ │ │ ├── assignment-cast: INT8 + │ │ │ │ └── 0 + │ │ │ ├── assignment-cast: TIMESTAMP + │ │ │ │ └── '2020-06-15 22:27:42.148484' │ │ │ └── assignment-cast: VARCHAR(4) │ │ │ └── 'ACTV' │ │ └── f-k-checks │ │ ├── f-k-checks-item: trade_history(th_t_id) -> trade(t_id) │ │ │ └── anti-join (lookup trade) - │ │ │ ├── columns: th_t_id:79!null - │ │ │ ├── key columns: [79] = [80] + │ │ │ ├── columns: th_t_id:81 + │ │ │ ├── key columns: [81] = [82] │ │ │ ├── lookup columns are key │ │ │ ├── cardinality: [0 - 1] │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(79) + │ │ │ ├── fd: ()-->(81) │ │ │ ├── with-scan &5 - │ │ │ │ ├── columns: th_t_id:79!null + │ │ │ │ ├── columns: th_t_id:81 │ │ │ │ ├── mapping: - │ │ │ │ │ └── column1:75 => th_t_id:79 + │ │ │ │ │ └── column1:78 => th_t_id:81 │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(79) + │ │ │ │ └── fd: ()-->(81) │ │ │ └── filters (true) │ │ └── f-k-checks-item: trade_history(th_st_id) -> status_type(st_id) │ │ └── anti-join (lookup status_type) - │ │ ├── columns: th_st_id:97 - │ │ ├── key columns: [97] = [98] + │ │ ├── columns: th_st_id:99 + │ │ ├── key columns: [99] = [100] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(97) + │ │ ├── fd: ()-->(99) │ │ ├── with-scan &5 - │ │ │ ├── columns: th_st_id:97 + │ │ │ ├── columns: th_st_id:99 │ │ │ ├── mapping: - │ │ │ │ └── column3:78 => th_st_id:97 + │ │ │ │ └── column3:80 => th_st_id:99 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(97) + │ │ │ └── fd: ()-->(99) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":102] + │ └── 1 [as="?column?":104] └── values - ├── columns: "?column?":103!null + ├── columns: "?column?":105!null ├── cardinality: [1 - 1] ├── key: () - ├── fd: ()-->(103) + ├── fd: ()-->(105) └── (1,) @@ -4520,94 +4551,98 @@ WHERE ca_id = 0 RETURNING ca_bal::FLOAT8; ---- with &2 (insert_settlement) - ├── columns: ca_bal:82!null + ├── columns: ca_bal:86!null ├── cardinality: [0 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(82) + ├── fd: ()-->(86) ├── project - │ ├── columns: "?column?":31!null + │ ├── columns: "?column?":33!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(31) + │ ├── fd: ()-->(33) │ ├── insert settlement │ │ ├── columns: settlement.se_t_id:1!null │ │ ├── insert-mapping: - │ │ │ ├── column1:7 => settlement.se_t_id:1 - │ │ │ ├── column2:11 => se_cash_type:2 - │ │ │ ├── column3:9 => se_cash_due_date:3 - │ │ │ └── column4:12 => se_amt:4 + │ │ │ ├── column1:11 => settlement.se_t_id:1 + │ │ │ ├── column2:12 => se_cash_type:2 + │ │ │ ├── column3:13 => se_cash_due_date:3 + │ │ │ └── column4:14 => se_amt:4 │ │ ├── input binding: &1 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () │ │ ├── fd: ()-->(1) │ │ ├── values - │ │ │ ├── columns: column1:7!null column3:9!null column2:11 column4:12 + │ │ │ ├── columns: column1:11 column2:12 column3:13 column4:14 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(7,9,11,12) + │ │ │ ├── fd: ()-->(11-14) │ │ │ └── tuple - │ │ │ ├── 0 - │ │ │ ├── '2020-06-15' + │ │ │ ├── assignment-cast: INT8 + │ │ │ │ └── 0 │ │ │ ├── assignment-cast: VARCHAR(40) │ │ │ │ └── 'Margin' + │ │ │ ├── assignment-cast: DATE + │ │ │ │ └── '2020-06-15' │ │ │ └── assignment-cast: DECIMAL(10,2) │ │ │ └── 1E+2 │ │ └── f-k-checks │ │ └── f-k-checks-item: settlement(se_t_id) -> trade(t_id) │ │ └── anti-join (lookup trade) - │ │ ├── columns: se_t_id:13!null - │ │ ├── key columns: [13] = [14] + │ │ ├── columns: se_t_id:15 + │ │ ├── key columns: [15] = [16] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(13) + │ │ ├── fd: ()-->(15) │ │ ├── with-scan &1 - │ │ │ ├── columns: se_t_id:13!null + │ │ │ ├── columns: se_t_id:15 │ │ │ ├── mapping: - │ │ │ │ └── column1:7 => se_t_id:13 + │ │ │ │ └── column1:11 => se_t_id:15 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(13) + │ │ │ └── fd: ()-->(15) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":31] + │ └── 1 [as="?column?":33] └── with &4 (insert_cash_transaction) - ├── columns: ca_bal:82!null + ├── columns: ca_bal:86!null ├── cardinality: [0 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(82) + ├── fd: ()-->(86) ├── project - │ ├── columns: "?column?":62!null + │ ├── columns: "?column?":66!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(62) + │ ├── fd: ()-->(66) │ ├── insert cash_transaction - │ │ ├── columns: cash_transaction.ct_t_id:32!null + │ │ ├── columns: cash_transaction.ct_t_id:34!null │ │ ├── insert-mapping: - │ │ │ ├── column1:38 => cash_transaction.ct_t_id:32 - │ │ │ ├── column2:39 => ct_dts:33 - │ │ │ ├── column3:42 => ct_amt:34 - │ │ │ └── column4:43 => ct_name:35 + │ │ │ ├── column1:44 => cash_transaction.ct_t_id:34 + │ │ │ ├── column2:45 => ct_dts:35 + │ │ │ ├── column3:46 => ct_amt:36 + │ │ │ └── column4:47 => ct_name:37 │ │ ├── input binding: &3 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () - │ │ ├── fd: ()-->(32) + │ │ ├── fd: ()-->(34) │ │ ├── values - │ │ │ ├── columns: column1:38!null column2:39!null column3:42 column4:43 + │ │ │ ├── columns: column1:44 column2:45 column3:46 column4:47 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(38,39,42,43) + │ │ │ ├── fd: ()-->(44-47) │ │ │ └── tuple - │ │ │ ├── 0 - │ │ │ ├── '2020-06-10 22:27:42.148484' + │ │ │ ├── assignment-cast: INT8 + │ │ │ │ └── 0 + │ │ │ ├── assignment-cast: TIMESTAMP + │ │ │ │ └── '2020-06-10 22:27:42.148484' │ │ │ ├── assignment-cast: DECIMAL(10,2) │ │ │ │ └── 1E+2 │ │ │ └── assignment-cast: VARCHAR(100) @@ -4615,53 +4650,53 @@ with &2 (insert_settlement) │ │ └── f-k-checks │ │ └── f-k-checks-item: cash_transaction(ct_t_id) -> trade(t_id) │ │ └── anti-join (lookup trade) - │ │ ├── columns: ct_t_id:44!null - │ │ ├── key columns: [44] = [45] + │ │ ├── columns: ct_t_id:48 + │ │ ├── key columns: [48] = [49] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(44) + │ │ ├── fd: ()-->(48) │ │ ├── with-scan &3 - │ │ │ ├── columns: ct_t_id:44!null + │ │ │ ├── columns: ct_t_id:48 │ │ │ ├── mapping: - │ │ │ │ └── column1:38 => ct_t_id:44 + │ │ │ │ └── column1:44 => ct_t_id:48 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(44) + │ │ │ └── fd: ()-->(48) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":62] + │ └── 1 [as="?column?":66] └── project - ├── columns: ca_bal:82!null + ├── columns: ca_bal:86!null ├── cardinality: [0 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(82) + ├── fd: ()-->(86) ├── update customer_account - │ ├── columns: ca_id:63!null customer_account.ca_bal:68!null - │ ├── fetch columns: ca_id:71 ca_b_id:72 ca_c_id:73 ca_name:74 ca_tax_st:75 customer_account.ca_bal:76 + │ ├── columns: ca_id:67!null customer_account.ca_bal:72!null + │ ├── fetch columns: ca_id:75 ca_b_id:76 ca_c_id:77 ca_name:78 ca_tax_st:79 customer_account.ca_bal:80 │ ├── update-mapping: - │ │ └── ca_bal_new:80 => customer_account.ca_bal:68 + │ │ └── ca_bal_new:84 => customer_account.ca_bal:72 │ ├── cardinality: [0 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(63,68) + │ ├── fd: ()-->(67,72) │ └── project - │ ├── columns: ca_bal_new:80 ca_id:71!null ca_b_id:72!null ca_c_id:73!null ca_name:74 ca_tax_st:75!null customer_account.ca_bal:76!null + │ ├── columns: ca_bal_new:84 ca_id:75!null ca_b_id:76!null ca_c_id:77!null ca_name:78 ca_tax_st:79!null customer_account.ca_bal:80!null │ ├── cardinality: [0 - 1] │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(71-76,80) + │ ├── fd: ()-->(75-80,84) │ ├── scan customer_account - │ │ ├── columns: ca_id:71!null ca_b_id:72!null ca_c_id:73!null ca_name:74 ca_tax_st:75!null customer_account.ca_bal:76!null - │ │ ├── constraint: /71: [/0 - /0] + │ │ ├── columns: ca_id:75!null ca_b_id:76!null ca_c_id:77!null ca_name:78 ca_tax_st:79!null customer_account.ca_bal:80!null + │ │ ├── constraint: /75: [/0 - /0] │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ └── fd: ()-->(71-76) + │ │ └── fd: ()-->(75-80) │ └── projections - │ └── crdb_internal.round_decimal_values(customer_account.ca_bal:76::DECIMAL + 1E+2, 2) [as=ca_bal_new:80, outer=(76), immutable] + │ └── crdb_internal.round_decimal_values(customer_account.ca_bal:80::DECIMAL + 1E+2, 2) [as=ca_bal_new:84, outer=(80), immutable] └── projections - └── customer_account.ca_bal:68::FLOAT8 [as=ca_bal:82, outer=(68), immutable] + └── customer_account.ca_bal:72::FLOAT8 [as=ca_bal:86, outer=(72), immutable] # Q16 opt @@ -4675,75 +4710,77 @@ insert_settlement AS ( SELECT ca_bal::FLOAT8 FROM customer_account WHERE ca_id = 0; ---- with &2 (insert_settlement) - ├── columns: ca_bal:40!null + ├── columns: ca_bal:42!null ├── cardinality: [0 - 1] ├── volatile, mutations ├── key: () - ├── fd: ()-->(40) + ├── fd: ()-->(42) ├── project - │ ├── columns: "?column?":31!null + │ ├── columns: "?column?":33!null │ ├── cardinality: [1 - 1] │ ├── volatile, mutations │ ├── key: () - │ ├── fd: ()-->(31) + │ ├── fd: ()-->(33) │ ├── insert settlement │ │ ├── columns: settlement.se_t_id:1!null │ │ ├── insert-mapping: - │ │ │ ├── column1:7 => settlement.se_t_id:1 - │ │ │ ├── column2:11 => se_cash_type:2 - │ │ │ ├── column3:9 => se_cash_due_date:3 - │ │ │ └── column4:12 => se_amt:4 + │ │ │ ├── column1:11 => settlement.se_t_id:1 + │ │ │ ├── column2:12 => se_cash_type:2 + │ │ │ ├── column3:13 => se_cash_due_date:3 + │ │ │ └── column4:14 => se_amt:4 │ │ ├── input binding: &1 │ │ ├── cardinality: [1 - 1] │ │ ├── volatile, mutations │ │ ├── key: () │ │ ├── fd: ()-->(1) │ │ ├── values - │ │ │ ├── columns: column1:7!null column3:9!null column2:11 column4:12 + │ │ │ ├── columns: column1:11 column2:12 column3:13 column4:14 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── immutable │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(7,9,11,12) + │ │ │ ├── fd: ()-->(11-14) │ │ │ └── tuple - │ │ │ ├── 0 - │ │ │ ├── '2020-06-15' + │ │ │ ├── assignment-cast: INT8 + │ │ │ │ └── 0 │ │ │ ├── assignment-cast: VARCHAR(40) │ │ │ │ └── 'Margin' + │ │ │ ├── assignment-cast: DATE + │ │ │ │ └── '2020-06-15' │ │ │ └── assignment-cast: DECIMAL(10,2) │ │ │ └── 1E+2 │ │ └── f-k-checks │ │ └── f-k-checks-item: settlement(se_t_id) -> trade(t_id) │ │ └── anti-join (lookup trade) - │ │ ├── columns: se_t_id:13!null - │ │ ├── key columns: [13] = [14] + │ │ ├── columns: se_t_id:15 + │ │ ├── key columns: [15] = [16] │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(13) + │ │ ├── fd: ()-->(15) │ │ ├── with-scan &1 - │ │ │ ├── columns: se_t_id:13!null + │ │ │ ├── columns: se_t_id:15 │ │ │ ├── mapping: - │ │ │ │ └── column1:7 => se_t_id:13 + │ │ │ │ └── column1:11 => se_t_id:15 │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () - │ │ │ └── fd: ()-->(13) + │ │ │ └── fd: ()-->(15) │ │ └── filters (true) │ └── projections - │ └── 1 [as="?column?":31] + │ └── 1 [as="?column?":33] └── project - ├── columns: ca_bal:40!null + ├── columns: ca_bal:42!null ├── cardinality: [0 - 1] ├── immutable ├── key: () - ├── fd: ()-->(40) + ├── fd: ()-->(42) ├── scan customer_account - │ ├── columns: ca_id:32!null customer_account.ca_bal:37!null - │ ├── constraint: /32: [/0 - /0] + │ ├── columns: ca_id:34!null customer_account.ca_bal:39!null + │ ├── constraint: /34: [/0 - /0] │ ├── cardinality: [0 - 1] │ ├── key: () - │ └── fd: ()-->(32,37) + │ └── fd: ()-->(34,39) └── projections - └── customer_account.ca_bal:37::FLOAT8 [as=ca_bal:40, outer=(37), immutable] + └── customer_account.ca_bal:39::FLOAT8 [as=ca_bal:42, outer=(39), immutable] # -------------------------------------------------- # T9 diff --git a/pkg/sql/opt/xform/testdata/external/trading b/pkg/sql/opt/xform/testdata/external/trading index 278e7d378d3a..86e0b23e313b 100644 --- a/pkg/sql/opt/xform/testdata/external/trading +++ b/pkg/sql/opt/xform/testdata/external/trading @@ -1242,30 +1242,34 @@ VALUES (1, FALSE, '2020-03-01', 'the-account', 'the-customer', '70F03EB1-4F58-4C insert transactions ├── columns: ├── insert-mapping: - │ ├── column1:10 => dealerid:1 - │ ├── column2:11 => isbuy:2 - │ ├── column3:12 => date:3 - │ ├── column4:16 => accountname:4 - │ ├── column5:17 => customername:5 - │ ├── column6:15 => operationid:6 - │ └── version_default:18 => version:7 + │ ├── column1:16 => dealerid:1 + │ ├── column2:17 => isbuy:2 + │ ├── column3:18 => date:3 + │ ├── column4:19 => accountname:4 + │ ├── column5:20 => customername:5 + │ ├── column6:21 => operationid:6 + │ └── version_default:22 => version:7 ├── cardinality: [0 - 0] - ├── volatile, mutations + ├── stable+volatile, mutations └── values - ├── columns: column1:10!null column2:11!null column3:12!null column6:15!null column4:16 column5:17 version_default:18 + ├── columns: column1:16 column2:17 column3:18 column4:19 column5:20 column6:21 version_default:22 ├── cardinality: [1 - 1] - ├── volatile + ├── stable+volatile ├── key: () - ├── fd: ()-->(10-12,15-18) + ├── fd: ()-->(16-22) └── tuple - ├── 1 - ├── false - ├── '2020-03-01 00:00:00+00:00' - ├── '70f03eb1-4f58-4c26-b72d-c524a9d537dd' + ├── assignment-cast: OID + │ └── 1 + ├── assignment-cast: BOOL + │ └── false + ├── assignment-cast: TIMESTAMPTZ + │ └── '2020-03-01 00:00:00+00:00' ├── assignment-cast: VARCHAR(128) │ └── 'the-account' ├── assignment-cast: VARCHAR(128) │ └── 'the-customer' + ├── assignment-cast: UUID + │ └── '70f03eb1-4f58-4c26-b72d-c524a9d537dd' └── cluster_logical_timestamp() # Upsert buy or sell transaction. diff --git a/pkg/sql/opt/xform/testdata/external/trading-mutation b/pkg/sql/opt/xform/testdata/external/trading-mutation index 24e03d7a303b..eeb07e18821f 100644 --- a/pkg/sql/opt/xform/testdata/external/trading-mutation +++ b/pkg/sql/opt/xform/testdata/external/trading-mutation @@ -1246,31 +1246,35 @@ VALUES (1, FALSE, '2020-03-01', 'the-account', 'the-customer', '70F03EB1-4F58-4C insert transactions ├── columns: ├── insert-mapping: - │ ├── column1:12 => dealerid:1 - │ ├── column2:13 => isbuy:2 - │ ├── column3:14 => date:3 - │ ├── column4:18 => accountname:4 - │ ├── column5:19 => customername:5 - │ ├── column6:17 => operationid:6 - │ ├── version_default:20 => version:7 - │ └── olddate_default:21 => olddate:8 + │ ├── column1:18 => dealerid:1 + │ ├── column2:19 => isbuy:2 + │ ├── column3:20 => date:3 + │ ├── column4:21 => accountname:4 + │ ├── column5:22 => customername:5 + │ ├── column6:23 => operationid:6 + │ ├── version_default:24 => version:7 + │ └── olddate_default:25 => olddate:8 ├── cardinality: [0 - 0] - ├── volatile, mutations + ├── stable+volatile, mutations └── values - ├── columns: column1:12!null column2:13!null column3:14!null column6:17!null column4:18 column5:19 version_default:20 olddate_default:21!null + ├── columns: column1:18 column2:19 column3:20 column4:21 column5:22 column6:23 version_default:24 olddate_default:25!null ├── cardinality: [1 - 1] - ├── volatile + ├── stable+volatile ├── key: () - ├── fd: ()-->(12-14,17-21) + ├── fd: ()-->(18-25) └── tuple - ├── 1 - ├── false - ├── '2020-03-01 00:00:00+00:00' - ├── '70f03eb1-4f58-4c26-b72d-c524a9d537dd' + ├── assignment-cast: OID + │ └── 1 + ├── assignment-cast: BOOL + │ └── false + ├── assignment-cast: TIMESTAMPTZ + │ └── '2020-03-01 00:00:00+00:00' ├── assignment-cast: VARCHAR(128) │ └── 'the-account' ├── assignment-cast: VARCHAR(128) │ └── 'the-customer' + ├── assignment-cast: UUID + │ └── '70f03eb1-4f58-4c26-b72d-c524a9d537dd' ├── cluster_logical_timestamp() └── '0001-01-01 00:00:00' diff --git a/pkg/sql/opt/xform/testdata/external/ycsb b/pkg/sql/opt/xform/testdata/external/ycsb index 33ac1816a25b..219b28026f8c 100644 --- a/pkg/sql/opt/xform/testdata/external/ycsb +++ b/pkg/sql/opt/xform/testdata/external/ycsb @@ -94,37 +94,47 @@ insert usertable ├── columns: ├── insert-mapping: │ ├── column1:25 => ycsb_key:1 - │ ├── column2:15 => field0:2 - │ ├── column3:16 => field1:3 - │ ├── column4:17 => field2:4 - │ ├── column5:18 => field3:5 - │ ├── column6:19 => field4:6 - │ ├── column7:20 => field5:7 - │ ├── column8:21 => field6:8 - │ ├── column9:22 => field7:9 - │ ├── column10:23 => field8:10 - │ └── column11:24 => field9:11 + │ ├── column2:26 => field0:2 + │ ├── column3:27 => field1:3 + │ ├── column4:28 => field2:4 + │ ├── column5:29 => field3:5 + │ ├── column6:30 => field4:6 + │ ├── column7:31 => field5:7 + │ ├── column8:32 => field6:8 + │ ├── column9:33 => field7:9 + │ ├── column10:34 => field8:10 + │ └── column11:35 => field9:11 ├── cardinality: [0 - 0] ├── volatile, mutations └── values - ├── columns: column2:15!null column3:16!null column4:17!null column5:18!null column6:19!null column7:20!null column8:21!null column9:22!null column10:23!null column11:24!null column1:25 + ├── columns: column1:25 column2:26 column3:27 column4:28 column5:29 column6:30 column7:31 column8:32 column9:33 column10:34 column11:35 ├── cardinality: [1 - 1] ├── immutable ├── key: () - ├── fd: ()-->(15-25) + ├── fd: ()-->(25-35) └── tuple - ├── 'field0data' - ├── 'field1data' - ├── 'field2data' - ├── 'field3data' - ├── 'field4data' - ├── 'field5data' - ├── 'field6data' - ├── 'field7data' - ├── 'field8data' - ├── 'field9data' - └── assignment-cast: VARCHAR(255) - └── 'user123' + ├── assignment-cast: VARCHAR(255) + │ └── 'user123' + ├── assignment-cast: STRING + │ └── 'field0data' + ├── assignment-cast: STRING + │ └── 'field1data' + ├── assignment-cast: STRING + │ └── 'field2data' + ├── assignment-cast: STRING + │ └── 'field3data' + ├── assignment-cast: STRING + │ └── 'field4data' + ├── assignment-cast: STRING + │ └── 'field5data' + ├── assignment-cast: STRING + │ └── 'field6data' + ├── assignment-cast: STRING + │ └── 'field7data' + ├── assignment-cast: STRING + │ └── 'field8data' + └── assignment-cast: STRING + └── 'field9data' # -------------------------------------------------- # Workload E: Short ranges diff --git a/pkg/sql/opt/xform/testdata/physprops/ordering b/pkg/sql/opt/xform/testdata/physprops/ordering index d681e6a1b7c5..0bafb91b8f83 100644 --- a/pkg/sql/opt/xform/testdata/physprops/ordering +++ b/pkg/sql/opt/xform/testdata/physprops/ordering @@ -1756,42 +1756,49 @@ opt SELECT * FROM [INSERT INTO abc SELECT * FROM xyz ORDER BY y, z LIMIT 2 RETURNING *] ORDER BY b ---- sort - ├── columns: a:11!null b:12!null c:13!null + ├── columns: a:14!null b:15!null c:16!null ├── cardinality: [0 - 2] ├── volatile, mutations - ├── key: (11-13) - ├── ordering: +12 + ├── ordering: +15 └── with &1 - ├── columns: a:11!null b:12!null c:13!null + ├── columns: a:14!null b:15!null c:16!null ├── cardinality: [0 - 2] ├── volatile, mutations - ├── key: (11-13) ├── insert abc │ ├── columns: abc.a:1!null abc.b:2!null abc.c:3!null │ ├── insert-mapping: - │ │ ├── x:6 => abc.a:1 - │ │ ├── y:7 => abc.b:2 - │ │ └── z:8 => abc.c:3 + │ │ ├── x:11 => abc.a:1 + │ │ ├── y:12 => abc.b:2 + │ │ └── z:13 => abc.c:3 │ ├── cardinality: [0 - 2] │ ├── volatile, mutations - │ ├── key: (1-3) - │ └── top-k - │ ├── columns: x:6!null y:7!null z:8!null - │ ├── internal-ordering: +7,+8 - │ ├── k: 2 + │ └── project + │ ├── columns: x:11!null y:12!null z:13!null │ ├── cardinality: [0 - 2] - │ ├── key: (6-8) - │ └── scan xyz - │ ├── columns: x:6!null y:7!null z:8!null - │ └── key: (6-8) + │ ├── immutable + │ ├── top-k + │ │ ├── columns: xyz.x:6!null xyz.y:7!null xyz.z:8!null + │ │ ├── internal-ordering: +7,+8 + │ │ ├── k: 2 + │ │ ├── cardinality: [0 - 2] + │ │ ├── key: (6-8) + │ │ └── scan xyz + │ │ ├── columns: xyz.x:6!null xyz.y:7!null xyz.z:8!null + │ │ └── key: (6-8) + │ └── projections + │ ├── assignment-cast: INT8 [as=x:11, outer=(6), immutable] + │ │ └── xyz.x:6 + │ ├── assignment-cast: INT8 [as=y:12, outer=(7), immutable] + │ │ └── xyz.y:7 + │ └── assignment-cast: INT8 [as=z:13, outer=(8), immutable] + │ └── xyz.z:8 └── with-scan &1 - ├── columns: a:11!null b:12!null c:13!null + ├── columns: a:14!null b:15!null c:16!null ├── mapping: - │ ├── abc.a:1 => a:11 - │ ├── abc.b:2 => b:12 - │ └── abc.c:3 => c:13 - ├── cardinality: [0 - 2] - └── key: (11-13) + │ ├── abc.a:1 => a:14 + │ ├── abc.b:2 => b:15 + │ └── abc.c:3 => c:16 + └── cardinality: [0 - 2] # Verify that provided orderings are derived correctly. opt @@ -1800,31 +1807,42 @@ FROM [INSERT INTO xyz SELECT b, c, d FROM abcd ORDER BY c, d LIMIT 2 RETURNING * ORDER BY y ---- sort - ├── columns: x:13!null y:14!null z:15!null + ├── columns: x:16!null y:17!null z:18!null ├── cardinality: [0 - 2] ├── volatile, mutations - ├── ordering: +14 + ├── ordering: +17 └── with &1 - ├── columns: x:13!null y:14!null z:15!null + ├── columns: x:16!null y:17!null z:18!null ├── cardinality: [0 - 2] ├── volatile, mutations ├── insert xyz │ ├── columns: xyz.x:1!null xyz.y:2!null xyz.z:3!null │ ├── insert-mapping: - │ │ ├── b:7 => xyz.x:1 - │ │ ├── c:8 => xyz.y:2 - │ │ └── d:9 => xyz.z:3 + │ │ ├── b:13 => xyz.x:1 + │ │ ├── c:14 => xyz.y:2 + │ │ └── d:15 => xyz.z:3 │ ├── cardinality: [0 - 2] │ ├── volatile, mutations - │ └── scan abcd@cd - │ ├── columns: b:7 c:8 d:9 - │ └── limit: 2 + │ └── project + │ ├── columns: b:13 c:14 d:15 + │ ├── cardinality: [0 - 2] + │ ├── immutable + │ ├── scan abcd@cd + │ │ ├── columns: abcd.b:7 abcd.c:8 abcd.d:9 + │ │ └── limit: 2 + │ └── projections + │ ├── assignment-cast: INT8 [as=b:13, outer=(7), immutable] + │ │ └── abcd.b:7 + │ ├── assignment-cast: INT8 [as=c:14, outer=(8), immutable] + │ │ └── abcd.c:8 + │ └── assignment-cast: INT8 [as=d:15, outer=(9), immutable] + │ └── abcd.d:9 └── with-scan &1 - ├── columns: x:13!null y:14!null z:15!null + ├── columns: x:16!null y:17!null z:18!null ├── mapping: - │ ├── xyz.x:1 => x:13 - │ ├── xyz.y:2 => y:14 - │ └── xyz.z:3 => z:15 + │ ├── xyz.x:1 => x:16 + │ ├── xyz.y:2 => y:17 + │ └── xyz.z:3 => z:18 └── cardinality: [0 - 2] # Verify that provided orderings are derived correctly with equivalence FD. @@ -1836,67 +1854,85 @@ WHERE x=y ORDER BY y ---- sort - ├── columns: x:13!null y:14!null z:15!null + ├── columns: x:16!null y:17!null z:18!null ├── cardinality: [0 - 2] ├── volatile, mutations - ├── fd: (13)==(14), (14)==(13) - ├── ordering: +(13|14) [actual: +13] + ├── fd: (16)==(17), (17)==(16) + ├── ordering: +(16|17) [actual: +16] └── with &1 - ├── columns: x:13!null y:14!null z:15!null + ├── columns: x:16!null y:17!null z:18!null ├── cardinality: [0 - 2] ├── volatile, mutations - ├── fd: (13)==(14), (14)==(13) + ├── fd: (16)==(17), (17)==(16) ├── insert xyz │ ├── columns: xyz.x:1!null xyz.y:2!null xyz.z:3!null │ ├── insert-mapping: - │ │ ├── b:7 => xyz.x:1 - │ │ ├── c:8 => xyz.y:2 - │ │ └── d:9 => xyz.z:3 + │ │ ├── b:13 => xyz.x:1 + │ │ ├── c:14 => xyz.y:2 + │ │ └── d:15 => xyz.z:3 │ ├── cardinality: [0 - 2] │ ├── volatile, mutations - │ └── scan abcd@cd - │ ├── columns: b:7 c:8 d:9 - │ └── limit: 2 + │ └── project + │ ├── columns: b:13 c:14 d:15 + │ ├── cardinality: [0 - 2] + │ ├── immutable + │ ├── scan abcd@cd + │ │ ├── columns: abcd.b:7 abcd.c:8 abcd.d:9 + │ │ └── limit: 2 + │ └── projections + │ ├── assignment-cast: INT8 [as=b:13, outer=(7), immutable] + │ │ └── abcd.b:7 + │ ├── assignment-cast: INT8 [as=c:14, outer=(8), immutable] + │ │ └── abcd.c:8 + │ └── assignment-cast: INT8 [as=d:15, outer=(9), immutable] + │ └── abcd.d:9 └── select - ├── columns: x:13!null y:14!null z:15!null + ├── columns: x:16!null y:17!null z:18!null ├── cardinality: [0 - 2] - ├── fd: (13)==(14), (14)==(13) + ├── fd: (16)==(17), (17)==(16) ├── with-scan &1 - │ ├── columns: x:13!null y:14!null z:15!null + │ ├── columns: x:16!null y:17!null z:18!null │ ├── mapping: - │ │ ├── xyz.x:1 => x:13 - │ │ ├── xyz.y:2 => y:14 - │ │ └── xyz.z:3 => z:15 + │ │ ├── xyz.x:1 => x:16 + │ │ ├── xyz.y:2 => y:17 + │ │ └── xyz.z:3 => z:18 │ └── cardinality: [0 - 2] └── filters - └── x:13 = y:14 [outer=(13,14), fd=(13)==(14), (14)==(13)] + └── x:16 = y:17 [outer=(16,17), fd=(16)==(17), (17)==(16)] # Ignore internal ordering. opt SELECT * FROM [INSERT INTO abc SELECT * FROM xyz ORDER BY y, z RETURNING *] ---- with &1 - ├── columns: a:11!null b:12!null c:13!null + ├── columns: a:14!null b:15!null c:16!null ├── volatile, mutations - ├── key: (11-13) ├── insert abc │ ├── columns: abc.a:1!null abc.b:2!null abc.c:3!null │ ├── insert-mapping: - │ │ ├── x:6 => abc.a:1 - │ │ ├── y:7 => abc.b:2 - │ │ └── z:8 => abc.c:3 + │ │ ├── x:11 => abc.a:1 + │ │ ├── y:12 => abc.b:2 + │ │ └── z:13 => abc.c:3 │ ├── volatile, mutations - │ ├── key: (1-3) - │ └── scan xyz - │ ├── columns: x:6!null y:7!null z:8!null - │ └── key: (6-8) + │ └── project + │ ├── columns: x:11!null y:12!null z:13!null + │ ├── immutable + │ ├── scan xyz + │ │ ├── columns: xyz.x:6!null xyz.y:7!null xyz.z:8!null + │ │ └── key: (6-8) + │ └── projections + │ ├── assignment-cast: INT8 [as=x:11, outer=(6), immutable] + │ │ └── xyz.x:6 + │ ├── assignment-cast: INT8 [as=y:12, outer=(7), immutable] + │ │ └── xyz.y:7 + │ └── assignment-cast: INT8 [as=z:13, outer=(8), immutable] + │ └── xyz.z:8 └── with-scan &1 - ├── columns: a:11!null b:12!null c:13!null - ├── mapping: - │ ├── abc.a:1 => a:11 - │ ├── abc.b:2 => b:12 - │ └── abc.c:3 => c:13 - └── key: (11-13) + ├── columns: a:14!null b:15!null c:16!null + └── mapping: + ├── abc.a:1 => a:14 + ├── abc.b:2 => b:15 + └── abc.c:3 => c:16 # -------------------------------------------------- # Update operator. diff --git a/pkg/sql/opt/xform/testdata/rules/groupby b/pkg/sql/opt/xform/testdata/rules/groupby index ea040625bd47..74daa5eebd7e 100644 --- a/pkg/sql/opt/xform/testdata/rules/groupby +++ b/pkg/sql/opt/xform/testdata/rules/groupby @@ -2250,53 +2250,46 @@ memo (optimized, ~21KB, required=[]) ├── G1: (insert G2 G3 G4 xyz) │ └── [] │ ├── best: (insert G2 G3 G4 xyz) - │ └── cost: 2188.92 - ├── G2: (upsert-distinct-on G5 G6 cols=(8)) (upsert-distinct-on G5 G6 cols=(8),ordering=+8 opt(12)) + │ └── cost: 2219.17 + ├── G2: (upsert-distinct-on G5 G6 cols=(13)) │ └── [] - │ ├── best: (upsert-distinct-on G5 G6 cols=(8)) - │ └── cost: 2188.91 + │ ├── best: (upsert-distinct-on G5 G6 cols=(13)) + │ └── cost: 2219.16 ├── G3: (unique-checks) ├── G4: (f-k-checks) - ├── G5: (anti-join G7 G8 G9) (merge-join G7 G8 G10 anti-join,+8,+13) (lookup-join G7 G10 xyz,keyCols=[8],outCols=(8,9,12,13)) (lookup-join G7 G10 xyz@xy,keyCols=[8],outCols=(8,9,12,13)) - │ ├── [ordering: +8 opt(12)] - │ │ ├── best: (merge-join G7="[ordering: +8 opt(12)]" G8="[ordering: +13]" G10 anti-join,+8,+13) - │ │ └── cost: 2188.88 + ├── G5: (anti-join G7 G8 G9) (lookup-join G7 G10 xyz,keyCols=[13],outCols=(13-16)) (lookup-join G7 G10 xyz@xy,keyCols=[13],outCols=(13-16)) │ └── [] - │ ├── best: (merge-join G7="[ordering: +8 opt(12)]" G8="[ordering: +13]" G10 anti-join,+8,+13) - │ └── cost: 2188.88 + │ ├── best: (anti-join G7 G8 G9) + │ └── cost: 2219.13 ├── G6: (aggregations G11 G12) - ├── G7: (project G13 G14 v w) - │ ├── [ordering: +8 opt(12)] - │ │ ├── best: (project G13="[ordering: +8]" G14 v w) - │ │ └── cost: 1104.64 + ├── G7: (project G13 G14) │ └── [] - │ ├── best: (project G13 G14 v w) - │ └── cost: 1104.64 - ├── G8: (scan xyz,cols=(13)) (scan xyz@xy,cols=(13)) (scan xyz@zyx,cols=(13)) (scan xyz@yy,cols=(13)) - │ ├── [ordering: +13] - │ │ ├── best: (scan xyz@xy,cols=(13)) - │ │ └── cost: 1054.32 + │ ├── best: (project G13 G14) + │ └── cost: 1124.64 + ├── G8: (scan xyz,cols=(16)) (scan xyz@xy,cols=(16)) (scan xyz@zyx,cols=(16)) (scan xyz@yy,cols=(16)) │ └── [] - │ ├── best: (scan xyz@xy,cols=(13)) + │ ├── best: (scan xyz@xy,cols=(16)) │ └── cost: 1054.32 ├── G9: (filters G15) ├── G10: (filters) ├── G11: (first-agg G16) ├── G12: (first-agg G17) ├── G13: (scan kuvw,cols=(8,9)) (scan kuvw@uvw,cols=(8,9)) (scan kuvw@wvu,cols=(8,9)) (scan kuvw@vw,cols=(8,9)) (scan kuvw@w,cols=(8,9)) - │ ├── [ordering: +8] - │ │ ├── best: (scan kuvw@vw,cols=(8,9)) - │ │ └── cost: 1084.62 │ └── [] │ ├── best: (scan kuvw,cols=(8,9)) │ └── cost: 1084.62 - ├── G14: (projections G18) - ├── G15: (eq G19 G20) + ├── G14: (projections G18 G19 G20) + ├── G15: (eq G21 G22) ├── G16: (variable w) ├── G17: (variable "?column?") - ├── G18: (const 1.0) - ├── G19: (variable v) - └── G20: (variable x) + ├── G18: (assignment-cast G23) + ├── G19: (assignment-cast G24) + ├── G20: (assignment-cast G25) + ├── G21: (variable v) + ├── G22: (variable x) + ├── G23: (variable kuvw.v) + ├── G24: (variable kuvw.w) + └── G25: (const 1.0) # Ensure that streaming ensure-upsert-distinct-on will be used. memo diff --git a/pkg/sql/opt/xform/testdata/rules/join b/pkg/sql/opt/xform/testdata/rules/join index 525f45f7d2f9..93c5f6b617d9 100644 --- a/pkg/sql/opt/xform/testdata/rules/join +++ b/pkg/sql/opt/xform/testdata/rules/join @@ -8257,39 +8257,40 @@ FROM abc AS x JOIN [INSERT INTO abc (a) SELECT 1 FROM abc RETURNING 1] JOIN abc AS y ON true ON false ---- with &1 - ├── columns: bool:30!null + ├── columns: bool:31!null ├── cardinality: [0 - 0] ├── volatile, mutations ├── key: () - ├── fd: ()-->(30) + ├── fd: ()-->(31) ├── project - │ ├── columns: "?column?":22!null + │ ├── columns: "?column?":23!null │ ├── volatile, mutations - │ ├── fd: ()-->(22) + │ ├── fd: ()-->(23) │ ├── insert abc │ │ ├── columns: abc.rowid:10!null │ │ ├── insert-mapping: - │ │ │ ├── "?column?":19 => abc.a:7 - │ │ │ ├── b_default:20 => abc.b:8 - │ │ │ ├── b_default:20 => abc.c:9 - │ │ │ └── rowid_default:21 => abc.rowid:10 + │ │ │ ├── "?column?":20 => abc.a:7 + │ │ │ ├── b_default:21 => abc.b:8 + │ │ │ ├── b_default:21 => abc.c:9 + │ │ │ └── rowid_default:22 => abc.rowid:10 │ │ ├── volatile, mutations │ │ └── project - │ │ ├── columns: b_default:20 rowid_default:21 "?column?":19!null + │ │ ├── columns: b_default:21 rowid_default:22 "?column?":20!null │ │ ├── volatile - │ │ ├── fd: ()-->(19,20) + │ │ ├── fd: ()-->(20,21) │ │ ├── scan abc │ │ └── projections - │ │ ├── CAST(NULL AS INT8) [as=b_default:20] - │ │ ├── unique_rowid() [as=rowid_default:21, volatile] - │ │ └── 1 [as="?column?":19] + │ │ ├── CAST(NULL AS INT8) [as=b_default:21] + │ │ ├── unique_rowid() [as=rowid_default:22, volatile] + │ │ └── assignment-cast: INT8 [as="?column?":20, immutable] + │ │ └── 1 │ └── projections - │ └── 1 [as="?column?":22] + │ └── 1 [as="?column?":23] └── values - ├── columns: bool:30!null + ├── columns: bool:31!null ├── cardinality: [0 - 0] ├── key: () - └── fd: ()-->(30) + └── fd: ()-->(31) opt join-limit=3 SELECT 1 FROM ((VALUES (1), (1)) JOIN ((VALUES (1), (1), (1)) JOIN (VALUES (1), (1), (1), (1)) ON true) ON true) diff --git a/pkg/sql/opt/xform/testdata/rules/scan b/pkg/sql/opt/xform/testdata/rules/scan index 9f412475f4ab..535123139aee 100644 --- a/pkg/sql/opt/xform/testdata/rules/scan +++ b/pkg/sql/opt/xform/testdata/rules/scan @@ -395,33 +395,38 @@ INSERT INTO fk_b (b,a) VALUES (1,1) insert fk_b ├── columns: ├── insert-mapping: - │ ├── column1:5 => b:1 - │ └── column2:6 => fk_b.a:2 + │ ├── column1:7 => b:1 + │ └── column2:8 => fk_b.a:2 ├── input binding: &1 ├── cardinality: [0 - 0] ├── volatile, mutations ├── values - │ ├── columns: column1:5!null column2:6!null + │ ├── columns: column1:7 column2:8 │ ├── cardinality: [1 - 1] + │ ├── immutable │ ├── key: () - │ ├── fd: ()-->(5,6) - │ └── (1, 1) + │ ├── fd: ()-->(7,8) + │ └── tuple + │ ├── assignment-cast: INT8 + │ │ └── 1 + │ └── assignment-cast: INT8 + │ └── 1 └── f-k-checks └── f-k-checks-item: fk_b(a) -> fk_a(a) └── anti-join (lookup fk_a) - ├── columns: a:7!null - ├── key columns: [7] = [8] + ├── columns: a:9 + ├── key columns: [9] = [10] ├── lookup columns are key ├── cardinality: [0 - 1] ├── key: () - ├── fd: ()-->(7) + ├── fd: ()-->(9) ├── with-scan &1 - │ ├── columns: a:7!null + │ ├── columns: a:9 │ ├── mapping: - │ │ └── column2:6 => a:7 + │ │ └── column2:8 => a:9 │ ├── cardinality: [1 - 1] │ ├── key: () - │ └── fd: ()-->(7) + │ └── fd: ()-->(9) └── filters (true) # -------------------------------------------------- diff --git a/pkg/sql/pgwire/testdata/pgtest/char b/pkg/sql/pgwire/testdata/pgtest/char index 70f4ba232855..d0f0f873f672 100644 --- a/pkg/sql/pgwire/testdata/pgtest/char +++ b/pkg/sql/pgwire/testdata/pgtest/char @@ -62,7 +62,7 @@ until ReadyForQuery ---- {"Type":"ParseComplete"} -{"Type":"ParameterDescription","ParameterOIDs":[20,25]} +{"Type":"ParameterDescription","ParameterOIDs":[23,18]} {"Type":"NoData"} {"Type":"BindComplete"} {"Type":"CommandComplete","CommandTag":"INSERT 0 1"} @@ -110,7 +110,7 @@ ReadyForQuery # Use the binary format for the "char" parameter. # ParameterFormatCodes = [1] for binary format send -Bind {"PreparedStatement": "s1", "ParameterFormatCodes": [1,1], "ResultFormatCodes": [0], "Parameters":[{"binary":"0000000000000004"}, {"binary":"46"}]} +Bind {"PreparedStatement": "s1", "ParameterFormatCodes": [1,1], "ResultFormatCodes": [0], "Parameters":[{"binary":"00000004"}, {"binary":"46"}]} Execute Sync ---- @@ -164,7 +164,7 @@ ReadyForQuery # Pass in a null byte. # ParameterFormatCodes = [1] for binary format send -Bind {"PreparedStatement": "s1", "ParameterFormatCodes": [1,1], "ResultFormatCodes": [0], "Parameters":[{"binary":"0000000000000006"}, {"binary":"00"}]} +Bind {"PreparedStatement": "s1", "ParameterFormatCodes": [1,1], "ResultFormatCodes": [0], "Parameters":[{"binary":"00000006"}, {"binary":"00"}]} Execute Sync ---- @@ -184,7 +184,7 @@ until ignore_table_oids ReadyForQuery ---- {"Type":"RowDescription","Fields":[{"Name":"a","TableOID":0,"TableAttributeNumber":1,"DataTypeOID":23,"DataTypeSize":4,"TypeModifier":-1,"Format":0},{"Name":"b","TableOID":0,"TableAttributeNumber":2,"DataTypeOID":18,"DataTypeSize":1,"TypeModifier":-1,"Format":0}]} -{"Type":"DataRow","Values":[{"text":"6"},{"binary":"00"}]} +{"Type":"DataRow","Values":[{"text":"6"},null]} {"Type":"CommandComplete","CommandTag":"SELECT 1"} {"Type":"ReadyForQuery","TxStatus":"I"} diff --git a/pkg/sql/sem/tree/cast.go b/pkg/sql/sem/tree/cast.go index bd0d59357bda..7495167f5ac7 100644 --- a/pkg/sql/sem/tree/cast.go +++ b/pkg/sql/sem/tree/cast.go @@ -1308,10 +1308,12 @@ func PerformCast(ctx *EvalContext, d Datum, t *types.T) (Datum, error) { // PerformAssignmentCast performs an assignment cast from the provided Datum to // the specified type. The original datum is returned if its type is identical -// to the specified type. It is similar to PerformCast, but differs because it -// errors in more cases than PerformCast if the datum's width is too wide for -// the given type rather than silently truncating. The one exception is casts to -// the special "char" type which are truncated. +// to the specified type. +// +// It is similar to PerformCast, but differs because it errors when a bit-array +// or string values are too wide for the given type, rather than truncating the +// value. The one exception to this is casts to the special "char" type which +// are truncated. func PerformAssignmentCast(ctx *EvalContext, d Datum, t *types.T) (Datum, error) { if !ValidCast(d.ResolvedType(), t, CastContextAssignment) { return nil, pgerror.Newf( diff --git a/pkg/sql/sem/tree/type_check.go b/pkg/sql/sem/tree/type_check.go index b1e45a387ae7..ed9f3b302975 100644 --- a/pkg/sql/sem/tree/type_check.go +++ b/pkg/sql/sem/tree/type_check.go @@ -1591,12 +1591,6 @@ func (expr *ArrayFlatten) TypeCheck( func (expr *Placeholder) TypeCheck( ctx context.Context, semaCtx *SemaContext, desired *types.T, ) (TypedExpr, error) { - // When we populate placeholder values from pgwire, there is no special - // handling of type details like widths. Therefore, we infer the types of - // placeholders as only canonical types. This is safe to do because a value - // can always be losslessly converted to its canonical type. - canonicalDesired := desired.CanonicalType() - // Perform placeholder typing. This function is only called during Prepare, // when there are no available values for the placeholders yet, because // during Execute all placeholders are replaced from the AST before type @@ -1614,7 +1608,7 @@ func (expr *Placeholder) TypeCheck( // the type system expects. Then, when the value is actually sent to us // later, we cast the input value (whose type is the expected type) to the // desired type here. - typ = canonicalDesired + typ = desired } // We call SetType regardless of the above condition to inform the // placeholder struct that this placeholder is locked to its type and cannot @@ -1628,10 +1622,10 @@ func (expr *Placeholder) TypeCheck( if desired.IsAmbiguous() { return nil, placeholderTypeAmbiguityError(expr.Idx) } - if err := semaCtx.Placeholders.SetType(expr.Idx, canonicalDesired); err != nil { + if err := semaCtx.Placeholders.SetType(expr.Idx, desired); err != nil { return nil, err } - expr.typ = canonicalDesired + expr.typ = desired return expr, nil } diff --git a/pkg/sql/sem/tree/type_check_test.go b/pkg/sql/sem/tree/type_check_test.go index e30c0b7abceb..51d0d3f2cccf 100644 --- a/pkg/sql/sem/tree/type_check_test.go +++ b/pkg/sql/sem/tree/type_check_test.go @@ -123,8 +123,8 @@ func TestTypeCheck(t *testing.T) { {`1 + $1`, `1:::INT8 + $1:::INT8`}, {`1:::DECIMAL + $1`, `1:::DECIMAL + $1:::DECIMAL`}, {`$1:::INT8`, `$1:::INT8`}, - {`2::DECIMAL(10,2) + $1`, `2:::DECIMAL::DECIMAL(10,2) + $1:::DECIMAL`}, - {`2::DECIMAL(10,0) + $1`, `2:::DECIMAL::DECIMAL(10) + $1:::DECIMAL`}, + {`2::DECIMAL(10,2) + $1`, `2:::DECIMAL::DECIMAL(10,2) + $1:::DECIMAL(10,2)`}, + {`2::DECIMAL(10,0) + $1`, `2:::DECIMAL::DECIMAL(10) + $1:::DECIMAL(10)`}, // Tuples with labels {`(ROW (1) AS a)`, `((1:::INT8,) AS a)`}, diff --git a/pkg/sql/types/types.go b/pkg/sql/types/types.go index 8953ea5942db..0931f146857a 100644 --- a/pkg/sql/types/types.go +++ b/pkg/sql/types/types.go @@ -1325,90 +1325,6 @@ func (f Family) Name() string { return ret } -// CanonicalType returns the canonical type of the given type's family. The -// original type is returned for some types that do not have a canonical type. -// For array and tuple types, a new type is returned where the content types -// have been set to their canonical types. -func (t *T) CanonicalType() *T { - switch t.Family() { - case BoolFamily: - return Bool - case IntFamily: - return Int - case FloatFamily: - return Float - case DecimalFamily: - return Decimal - case DateFamily: - return Date - case TimestampFamily: - return Timestamp - case IntervalFamily: - return Interval - case StringFamily: - return String - case BytesFamily: - return Bytes - case TimestampTZFamily: - return TimestampTZ - case CollatedStringFamily: - // CollatedStringFamily has no canonical type. - return t - case OidFamily: - return Oid - case UnknownFamily: - return Unknown - case UuidFamily: - return Uuid - case ArrayFamily: - newContents := t.ArrayContents().CanonicalType() - if newContents == t.ArrayContents() { - return t - } - return MakeArray(newContents) - case INetFamily: - return INet - case TimeFamily: - return Time - case JsonFamily: - return Jsonb - case TimeTZFamily: - return TimeTZ - case TupleFamily: - isCanonical := true - oldContents := t.TupleContents() - for i := range oldContents { - if oldContents[i].CanonicalType() != oldContents[i] { - isCanonical = false - break - } - } - if isCanonical { - return t - } - newContents := make([]*T, len(oldContents)) - for i := range newContents { - newContents[i] = oldContents[i].CanonicalType() - } - return MakeTuple(newContents) - case BitFamily: - return VarBit - case GeometryFamily: - return Geometry - case GeographyFamily: - return Geography - case EnumFamily: - // EnumFamily has no canonical type. - return t - case Box2DFamily: - return Box2D - case AnyFamily: - return Any - default: - panic(errors.AssertionFailedf("unexpected type family: %v", errors.Safe(t.Family()))) - } -} - // Name returns a single word description of the type that describes it // succinctly, but without all the details, such as width, locale, etc. The name // is sometimes the same as the name returned by SQLStandardName, but is more diff --git a/pkg/sql/types/types_test.go b/pkg/sql/types/types_test.go index dc71875662ec..37dc54fe70ed 100644 --- a/pkg/sql/types/types_test.go +++ b/pkg/sql/types/types_test.go @@ -979,116 +979,3 @@ func TestSQLStandardName(t *testing.T) { }) } } - -func TestCanonicalType(t *testing.T) { - testCases := []struct { - typ *T - expected *T - }{ - // BOOL - {Bool, Bool}, - - // INT - {Int, Int}, - {Int4, Int}, - {Int2, Int}, - - // FLOAT - {Float, Float}, - {Float4, Float}, - - // DECIMAL - {Decimal, Decimal}, - {MakeDecimal(10, 0), Decimal}, - {MakeDecimal(5, 1), Decimal}, - - // DATE - {Date, Date}, - - // TIMESTAMP - {Timestamp, Timestamp}, - {MakeTimestamp(10), Timestamp}, - - // TIMESTAMPTZ - {TimestampTZ, TimestampTZ}, - {MakeTimestampTZ(10), TimestampTZ}, - - // TIME - {Time, Time}, - {MakeTime(10), Time}, - - // TIMETZ - {TimeTZ, TimeTZ}, - {MakeTimeTZ(10), TimeTZ}, - - // INTERVAL - {Interval, Interval}, - {MakeInterval(IntervalTypeMetadata{Precision: 10, PrecisionIsSet: true}), Interval}, - - // STRING - {String, String}, - {MakeString(10), String}, - - // BYTES - {Bytes, Bytes}, - - // COLLATEDSTRING - // Collated strings do not have a canonical type. - {MakeCollatedString(String, "en-US"), MakeCollatedString(String, "en-US")}, - - // OID - {Oid, Oid}, - - // UNKNOWN - {Unknown, Unknown}, - - // UUID - {Uuid, Uuid}, - - // INET - {INet, INet}, - - // JSON - {Jsonb, Jsonb}, - - // BIT - {VarBit, VarBit}, - {MakeVarBit(10), VarBit}, - {MakeBit(10), VarBit}, - - // GEOMETRY - {Geometry, Geometry}, - {MakeGeometry(geopb.ShapeType_MultiPoint, 4325), Geometry}, - - // GEOGRAPHY - {Geography, Geography}, - {MakeGeography(geopb.ShapeType_MultiPoint, 4325), Geography}, - - // ENUM - // Enums do not have a canonical type. - {MakeEnum(15210, 15213), MakeEnum(15210, 15213)}, - - // BOX2D - {Box2D, Box2D}, - - // ANY - {Any, Any}, - - // ARRAY - {IntArray, IntArray}, - {MakeArray(Int4), IntArray}, - {DecimalArray, DecimalArray}, - {MakeArray(MakeDecimal(10, 2)), DecimalArray}, - - // TUPLE - {MakeTuple([]*T{Int, Decimal}), MakeTuple([]*T{Int, Decimal})}, - {MakeTuple([]*T{Int4, MakeDecimal(10, 2)}), MakeTuple([]*T{Int, Decimal})}, - } - - for _, tc := range testCases { - actual := tc.typ.CanonicalType() - if !actual.Identical(tc.expected) { - t.Errorf("expect <%v>, got <%v>", tc.expected.DebugString(), actual.DebugString()) - } - } -}