From 0d7d2cc7a2a3c9fff5d78b481ffa434affa5e0de Mon Sep 17 00:00:00 2001 From: rimadeodhar Date: Thu, 13 Jul 2023 17:50:55 +0000 Subject: [PATCH 1/3] acceptance: Fix DockerCSharp Test This PR updates the .net framework within the csproj setup to .net 6. Additionally, it also fixes the CS program that we run as a part of this test with the new npgsql DateTime changes made as a part of npgsql 6 version update. The old datetime types have been deprecated and needed to be removed. With these fixes, the test is running successfully and can be unskipped. Epic: none Fixes: https://github.com/cockroachdb/cockroach/issues/86852 Release note: none --- pkg/acceptance/adapter_test.go | 1 - pkg/acceptance/testdata/csharp/Program.cs | 12 ++++++------ pkg/acceptance/testdata/csharp/acceptance.csproj | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/pkg/acceptance/adapter_test.go b/pkg/acceptance/adapter_test.go index 32be85856f7d..daa0aeb5141e 100644 --- a/pkg/acceptance/adapter_test.go +++ b/pkg/acceptance/adapter_test.go @@ -39,7 +39,6 @@ func TestDockerC(t *testing.T) { } func TestDockerCSharp(t *testing.T) { - skip.WithIssue(t, 86852, "test not to up to date anymore") s := log.Scope(t) defer s.Close(t) diff --git a/pkg/acceptance/testdata/csharp/Program.cs b/pkg/acceptance/testdata/csharp/Program.cs index 9b1e7defa929..83edf0ea9291 100644 --- a/pkg/acceptance/testdata/csharp/Program.cs +++ b/pkg/acceptance/testdata/csharp/Program.cs @@ -60,7 +60,7 @@ static void Simple(string connString) using (var cmd = new NpgsqlCommand("SELECT id, balance FROM bank.accounts", conn)) using (var reader = cmd.ExecuteReader()) while (reader.Read()) - Console.Write("\taccount {0}: {1}\n", reader.GetString(0), reader.GetString(1)); + Console.Write("\taccount {0}: {1}\n", reader.GetInt32(0), reader.GetInt32(1)); } } @@ -138,7 +138,7 @@ static void TxnSample(string connString) using (var cmd = new NpgsqlCommand("SELECT id, balance FROM bank.accounts", conn)) using (var reader = cmd.ExecuteReader()) while (reader.Read()) - Console.Write("\taccount {0}: {1}\n", reader.GetString(0), reader.GetString(1)); + Console.Write("\taccount {0}: {1}\n", reader.GetInt32(0), reader.GetInt32(1)); } } @@ -200,8 +200,8 @@ static void UnitTest(string connString) { throw new DataException(String.Format("SELECT can't find inserted value: read {0}, expecting 42", a)); } - var ts = reader.GetTimeStamp(1); - var expectedTs = new NpgsqlTypes.NpgsqlDateTime(2015, 5, 7, 18, 20, 0, DateTimeKind.Unspecified); + var ts = reader.GetDateTime(1); + var expectedTs = new DateTime(2015, 5, 7, 18, 20, 0, DateTimeKind.Unspecified); if (ts != expectedTs) { throw new DataException(String.Format("SELECT unexpected value for ts: read {0}, expecting {1}", ts, expectedTs)); @@ -212,7 +212,7 @@ static void UnitTest(string connString) using (var cmd = new NpgsqlCommand("INSERT INTO test.f VALUES (@x, @ts)", conn)) { cmd.Parameters.Add("x", NpgsqlTypes.NpgsqlDbType.Integer).Value = 1; - cmd.Parameters.Add("ts", NpgsqlTypes.NpgsqlDbType.Timestamp).Value = new NpgsqlTypes.NpgsqlDateTime(DateTime.Now); + cmd.Parameters.Add("ts", NpgsqlTypes.NpgsqlDbType.Timestamp).Value = DateTime.Now; cmd.Prepare(); var rows = cmd.ExecuteNonQuery(); if (rows != 1) @@ -311,7 +311,7 @@ static void UnitTest(string connString) { cmd.Parameters.Add("id", NpgsqlTypes.NpgsqlDbType.Integer).Value = 1; cmd.Parameters.Add("balance", NpgsqlTypes.NpgsqlDbType.Integer).Value = 1000; - cmd.Parameters.Add("cdate", NpgsqlTypes.NpgsqlDbType.Date).Value = new NpgsqlTypes.NpgsqlDate(DateTime.Now); + cmd.Parameters.Add("cdate", NpgsqlTypes.NpgsqlDbType.Date).Value = DateTime.Now; cmd.Prepare(); var rows = cmd.ExecuteNonQuery(); if (rows != 1) diff --git a/pkg/acceptance/testdata/csharp/acceptance.csproj b/pkg/acceptance/testdata/csharp/acceptance.csproj index 58fc56adc9e5..a58168fcc430 100644 --- a/pkg/acceptance/testdata/csharp/acceptance.csproj +++ b/pkg/acceptance/testdata/csharp/acceptance.csproj @@ -1,7 +1,7 @@ Exe - netcoreapp2.0 + net6.0 From 1da63900d94495f8b3d19287b1c42028367d0c9e Mon Sep 17 00:00:00 2001 From: Drew Kimball Date: Sat, 8 Jul 2023 15:15:38 -0600 Subject: [PATCH 2/3] opt: only infer self-join equality with a key over the base table Self-join equality inference was added by #105214, so that the `FuncDeps` for a self-join would include equalities between *every* pair of columns at the same ordinal position in the base table if there was an equality between key columns (also at the same ordinal position). However, the key column check was performed using the FDs of the join inputs rather than the base table's FDs. This could lead to incorrectly adding self-join equality filters. For example, consider the following: ``` CREATE TABLE t106371 (x INT NOT NULL, y INT NOT NULL); INSERT INTO t106371 VALUES (1, 1), (1, 2); SELECT * FROM t106371 a JOIN t106371 b ON a.x = b.x; SELECT * FROM (SELECT * FROM t106371 ORDER BY y DESC LIMIT 1) a JOIN (SELECT DISTINCT ON (x) * FROM t106371) b ON a.x = b.x; ``` In the first query above, `a.x = b.x` does not consitute joining on key columns. But in the second query, one input has one row and the other de-duplicated by the `x` column and so `x` is a key over both inputs. However, the query as written will select different rows for each input - `a` will return the `(1, 2)` row, while `b` will return the `(1, 1)` row. Inferring a `a.y = b.y` filter will incorrectly cause the join to return no rows. This patch fixes the problem by requiring the initial self-join equalities to form a key over the *base* table, not just the inputs of the join. Fixes #106371 Release note: None --- pkg/sql/logictest/testdata/logic_test/join | 12 +++ pkg/sql/opt/memo/logical_props_builder.go | 8 +- pkg/sql/opt/memo/testdata/logprops/join | 12 +-- pkg/sql/opt/norm/testdata/rules/combo | 2 +- pkg/sql/opt/xform/testdata/rules/join_order | 90 +++++++++++++++++++-- 5 files changed, 107 insertions(+), 17 deletions(-) diff --git a/pkg/sql/logictest/testdata/logic_test/join b/pkg/sql/logictest/testdata/logic_test/join index d58ab562eff1..8be6d58e209f 100644 --- a/pkg/sql/logictest/testdata/logic_test/join +++ b/pkg/sql/logictest/testdata/logic_test/join @@ -1205,3 +1205,15 @@ FROM task AS task0_ WHERE EXISTS ( 11 taskWithPatient1WithValidSite1 5 12 taskWithPatient2WithValidSite1 6 13 taskWithPatient3WithValidSite2 7 + +# Regression test for #106371 - only infer self-join equalities if the original +# equality columns form a key over the *base* table, not just the join inputs. +statement ok +CREATE TABLE t106371 (x INT NOT NULL, y INT NOT NULL); +INSERT INTO t106371 VALUES (1, 1), (1, 2); + +query IIII +SELECT * FROM (SELECT * FROM t106371 ORDER BY y DESC LIMIT 1) a +JOIN (SELECT DISTINCT ON (x) * FROM t106371) b ON a.x = b.x; +---- +1 2 1 1 diff --git a/pkg/sql/opt/memo/logical_props_builder.go b/pkg/sql/opt/memo/logical_props_builder.go index 0bbf8f159617..a4dd8a75c59b 100644 --- a/pkg/sql/opt/memo/logical_props_builder.go +++ b/pkg/sql/opt/memo/logical_props_builder.go @@ -2550,14 +2550,15 @@ func (h *joinPropsHelper) addSelfJoinImpliedFDs(rel *props.Relational) { return } for leftTable, leftTableOrds := range leftTables { + baseTabFDs := MakeTableFuncDep(md, leftTable) for rightTable, rightTableOrds := range rightTables { if md.TableMeta(leftTable).Table.ID() != md.TableMeta(rightTable).Table.ID() { continue } // This is a self-join. If there are equalities between columns at the // same ordinal positions in each (meta) table and those columns form a - // key on each input, *every* pair of columns at the same ordinal position - // is equal. + // key on the base table, *every* pair of columns at the same ordinal + // position is equal. var eqCols opt.ColSet colOrds := leftTableOrds.Intersection(rightTableOrds) for colOrd, ok := colOrds.Next(0); ok; colOrd, ok = colOrds.Next(colOrd + 1) { @@ -2567,8 +2568,7 @@ func (h *joinPropsHelper) addSelfJoinImpliedFDs(rel *props.Relational) { eqCols.Add(rightCol) } } - if !eqCols.Empty() && h.leftProps.FuncDeps.ColsAreStrictKey(eqCols) && - h.rightProps.FuncDeps.ColsAreStrictKey(eqCols) { + if !eqCols.Empty() && baseTabFDs.ColsAreStrictKey(eqCols) { // Add equalities between each pair of columns at the same ordinal // position, ignoring those that aren't part of the output. for colOrd, ok := colOrds.Next(0); ok; colOrd, ok = colOrds.Next(colOrd + 1) { diff --git a/pkg/sql/opt/memo/testdata/logprops/join b/pkg/sql/opt/memo/testdata/logprops/join index 637c2c0dd3d5..d7c0b4116ed8 100644 --- a/pkg/sql/opt/memo/testdata/logprops/join +++ b/pkg/sql/opt/memo/testdata/logprops/join @@ -2951,8 +2951,10 @@ inner-join (hash) ├── variable: xyz.x:1 [type=int] └── variable: foo.x:6 [type=int] -# Self-join filters can be inferred even if the join key wasn't a key in the +# Self-join filters can only be inferred even if the join key was a key in the # base table. +# TODO(drewk): if the optimizer could see that the same row is being selected +# from each input, we could still infer equalities. norm SELECT * FROM xyz INNER JOIN xyz foo ON xyz.x = foo.x AND xyz.y = 1 AND foo.y = 1 ---- @@ -2960,7 +2962,7 @@ inner-join (hash) ├── columns: x:1(int!null) y:2(int!null) z:3(int) x:6(int!null) y:7(int!null) z:8(int) ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-one) ├── key: (6) - ├── fd: ()-->(2,7), (1)-->(3), (6)-->(8), (1)==(6), (6)==(1), (2)==(7), (7)==(2), (3)==(8), (8)==(3) + ├── fd: ()-->(2,7), (1)-->(3), (6)-->(8), (1)==(6), (6)==(1) ├── prune: (3,8) ├── interesting orderings: (+1 opt(2)) (+6 opt(7)) ├── select @@ -3002,8 +3004,8 @@ inner-join (hash) ├── variable: xyz.x:1 [type=int] └── variable: foo.x:6 [type=int] -# The optimizer doesn't detect the contradiction here because the "y" filters -# pushed down before the join properties are calculated. +# Self-join filters cannot be inferred here because different rows are selected +# from each input. norm SELECT * FROM xyz INNER JOIN xyz foo ON xyz.x = foo.x AND xyz.y = 1 AND foo.y = 2 ---- @@ -3011,7 +3013,7 @@ inner-join (hash) ├── columns: x:1(int!null) y:2(int!null) z:3(int) x:6(int!null) y:7(int!null) z:8(int) ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-one) ├── key: (6) - ├── fd: ()-->(2,7), (1)-->(3), (6)-->(8), (1)==(6), (6)==(1), (2)==(7), (7)==(2), (3)==(8), (8)==(3) + ├── fd: ()-->(2,7), (1)-->(3), (6)-->(8), (1)==(6), (6)==(1) ├── prune: (3,8) ├── interesting orderings: (+1 opt(2)) (+6 opt(7)) ├── select diff --git a/pkg/sql/opt/norm/testdata/rules/combo b/pkg/sql/opt/norm/testdata/rules/combo index e4ab57e43110..40daf9848844 100644 --- a/pkg/sql/opt/norm/testdata/rules/combo +++ b/pkg/sql/opt/norm/testdata/rules/combo @@ -489,7 +489,7 @@ INNER JOIN a a3 ON a2.k = a3.k INNER JOIN a a4 ON a3.k = a4.k INNER JOIN a a5 ON a4.k = a5.k ---- -https://raduberinde.github.io/optsteps.html#eJzsXV1z20Z3vu-v2OpKKgFaAEiJ4juaceo4U3lU2bX89ib2ZBCJrGFTpEtSadxOM5n8Bl_m1-WXvINvENiPs4sFsIBObmIB2OXifOyefc5zFv93dPsf10fzo9uX1y9fvCP_Qn54-_rfiU985_366ubm5Vvy6vXVTXjBJa9viO-MP5PL6H_l-150343ve9X7k-i-F9-fVO9Po_uT-P50_PnIOrrZbB--D5bLo_mRbdvEf3a1DvaBv3q_Ho1G5Of8z-fPie2QkWNNXfL8-fv16Mt282lxt3-_HpG_vv3517ff__r2O7nbrB4f1rs5-Tx3_nn9uFqRYO6S5dwju_mEfJpPyef5LL1xQZZz55Ts5o5DPs0dN2w0TW86Z-Hd8_DuLLx7QT7PXTfr0yPLuTshu7k7JZ_m7ll49yK9652GP-mQ3dxzyae55x0O8vPi65wcO5Z7cXJ4Y3kfXj-x7fePp6fe4ti1pycWOfasyclvvyXXHMu1oquz_LkL23HDS86p5Tj5ozPrwnJcy5nazoXlurZ7ZrkXtudFj07z5s6Z7VxEF88tZ1Zob0etLefMqnYwO7m8PHamluuG7xH3eHl5PMsvuG7hTTzbPYsuTix3WvmJeICW61nFn3DduMfwV-IeL_IevdPkKc-xPJfRYzxiyzu1kh4v8h7dRPjfEuEH6_Via3_aBGty_NHffYxuR_9RzCv0jtTCfGccGpnvjEM7851xaGq-Mw6tzXfGd9v7n38K1vvFdu2vfnr45e7up33wsNjt_Ycv87Pwib3_82qxCe7n55FzpQbqu-PQRn13HJmp744jS_XdcWSsvsvv2vHCR7K-nUnkmZmF-944MnLfG0d27nvjyNR9bxxZu-_xu3dPw0ey7l0ncuzMRfzJOPISfzKOHMWfjCNf8SfjyF38iaD78_CRvPtZNGFkPuZPx5Gb-dNx5Gn-dBw5mz8dh_4W_p_bvTcJH8m696YUZT88rvbBl1VwF-y_zslqsdzb283_7I4Xv_p3-9VXe7NenFhkG_zXx-TG_y62G3uztR822wXNekp-X7pbdf5zuvPH1w_df8J0__Teob-7DsXfU1dP7sp7-Izi4albp3dFPj2l-HTqwsndqheXRMlz5T_Qow3xaLZStHneHwwHdDkPGeyHh05Y2wM5QgB4EDoS2JGEwtNt8Ay7p6q8J-ZfsH3xSxTN92672e3YTYZkxtCXTO2BI8n2rAI6hN2dvyY--dHfXfrOB1GrltUqOZxEAcJ3T_73TUELKmJ11cXaoVVTZSs2bZpsddpt1nGw2i-2O_7j5LBNbKUJCjN3yI-bx_1ie3kcToh3m_Vuv_WD9X53efzMmZPjZzd_v74mNvlwwtYfTd2eUN1VPXezTtLdh7OaUR1Hcu1hdg7TbFmlkYckwNncmWY6jSKxslpnRbX-jTxzpgd6tsjy_pK2MlI0StP8RGwoucpb3gRQdU2N2GlKlg2Iq70KtFtWa6LNy1ROua8mEXvJX6clzbouRbOxOrMQP1bzB8pOt6jUKUf5uTbbQlHoarzgCfx-Lg8HFLpjKa6ssURPl6ksMo2luMahxg4VFGrsgqKxWEsZpBFr78P7dQxq3wYPX1bB8uut_7D4T3_78r8f_VWwDxa7FObmPBAB39bULWDfJMO-qTo2DfumbsFDS-BHmIh9N4p9Ez72TcpTTa93Rv1GyhqftSvKrgtIVDos-X3prqmgg_nYd0WUPFceEtbRb49mK0Wb5_Gwb9ZDBvuhfuybJQSAB6EjSezpBcLTbfA87FvwrKnmf4h9C16Chn0zmgzJjKEvWcS-YS0axb5hQyhj3_xWrWPfUsPJsW9QMzXsW16srrpYO7RqJvYtL1uddluBYmzO4-SwjX7sm_Yrx0nvV7fk-6vbd1c3L97FvMgX392-O446_e6WXN28m52ckNdvDy__6-vX1yfQgf2N7MO164RtXyxsXnbW7mYdZ2PzQBtRw-YZnVcsj_pc2eTawubLg2Fh8wJDaQ2bF4yjgM2L1KGGzZd7FWi3rNZWsfns51nYPEv5rWHzrAEUsHmmwNWw-YpKyoora6xDbP7VJlj_kKUODlD5g1uIxyMej3i82aAD4vGIxyMejx6NeDzi8ehIiMcjHo94POLxiMcjHi-Px3eClMtz5QHDQ8SeNwEgYo-IPSL2iNgTvuLKGusAsX_zuPsYw_FX6_3m1SZYXy-W-xS0Z909wO3PEbdH3B5xe9PACcTtEbdH3B49GnF7xO3RkRC3R9wecXsY_skDNFXPkMlaLVbJJpH3dF9Qfr6kaqH8Uue0NNi10lFBretPZVSSBwc1r02pU27MAfAx8cQ2EJ0Tr4ZCkGbsQursJnK83z4CYiRMB2E6CNNBmA7CdFCb6aC3i4fNL4ubzf7mcbV6sVnfB_tgs07TQay7STroPEoHnWE6CNNBmA4yDfPCdBCmgzAdhB6N6SBMB6EjYToI00GYDtJaxjGoxI5UM53lG4LsC6ixmUKuJ-ta2Re5NB0EXjcOZVcD2zF1w7auBmuGMAci9m3MgWAOBHMgmANpPwfychU8BGt_v7hNQto4-VG5nGQ9zqKsh4NZD8x6YNbDNGgHsx6Y9cCsB3o0Zj0w64GOhFkPzHpg1kNrEUy6RYQ9PcijrkDoulquRKrrsnRBjVsXssqoJGXdeq4kw7Mb_AI3bErADAZmMDCDgRkMzGBgBuPpZjCuF8v9d7vd5i7w94tXm2C9exvu0tJMBvN2ktFwBpjRsDGj0V1GY6RJ-FYuQjUVlDrRqofonZ1I-s5Z-O9koNHl8_j3on-fRv92on9H64UTdx4HCPH0G7eNu6RiagZqmWDeqi8o99DyVnb5rqmAofl5q9EARNnsVOx4UbwVtXXjPuOFZhJdj9q6cZ8TgxRb8SBMSPZhqu44IVmGA3swK-hPSLKEQPGgMgLaS3kNaP7kqEQiH4fzIARNZaQOusgnC4Ziqjce5pMFL0GzX1jWstdmDH3JYj4Z1sKEfLJKDtOw5KUJxyT2ydHNWnCFIlU797PrIyBlD31sxBoB8WKHmenG4wPYu0qHCcUbkmZACw85EwlOD0jEaJ6IIXUKaEbEEASLZSKGbKDYzdaB7bVAIakRMRidwyrEyeHDrREx5CmIHrSqvHVzkBoVeC7XYxxSp93KfX2xY1OBcryQ4oMUH6T4IMVnoBQfZJmYzDLRyyWysresretCV01o3HK9gtLTvxK9W-6kqPr0z0T7ofoKBpD-mdiAlQw6MYPkz6Il0N6xnlF48Us4SVfJqGP7dafJMGOzdc-ScTnIWjId4kHW0pNjLRkETZlDtakolgf89l_5LS9NqVFY7nnRLpI_U9OwEvUm1mFl2q5vIDVWr_N0rLFJz9LBOZosr2JVEJIDLm2dL21sjhGyvJ4mawnCOROwPtCvNbCWhkYrMstRpPJWYkKMKUwYWQqMHraB6WbIm7WfSgzZXADJtgcgY6dzqg6Yo6PXXeCsnCHRcRoPaAUybIbmQ8nxQRiCOAUOZAos73bErs5oMUCPh75rTc-E_Qj4TBUk4CEBr2UCnryAxUcbdcWkUhAxwCn1MKn4vwE79qhjJhWMKcgkabKYVGBAp2VQkh1liQShxqQq9ypgYJatoFUmlUTZxEShbKKbaF06rNajdxhBkfGcUVYg5FQi7w55d1T9PlHeHTKynjojy-YzspogAFrZwDUZXaHDhkzP8k4PrS-9kBug5TklG0yv5GYYqunQEtMruTEmeirYo5WZEUACmgwzeb-CbSZvUzDPZOwFC81tDDBSdasNG59mI3WT3vKRxu7vuflIY5f3vHyk7lli3TTjr3A3MLnbOcbdeAhW4ZEhH9HMtRkpaYpkSBaDBWe3zmc3tlIGSx17KrNGc1MGDOLkEHk6Z_CAqTs1SQg98JN-bEIKXmR5k5IjJVcKvmQlq1TuTukVretwvd1K7mDpK-U-ZmXLbL2VWdOWJbwyyYcbz13eNB_uIaAL5SR1R0YSs5A0eb7E6ZFDoB_0fTPG0o1mIhMFZufyPHFBwAWhhwsCK7tU5xufODeqHonSDOULfuAKkjGHuBUUKBvJmIB3RTImkjGRjCklYCRjPlEypmC9AR5X1xUDT2aq5sVSehh4jM7VvkXaKgNPwBmtcnFZDDxxTqqt9C8bGmC-rBoDzy6rrky0LWu2VQYepL5xKlPf2DJiBEd49GhTwEUtP2CGbpnuGtEv32wf1xGv8nqx3L_YrHYp8ZJyY8CUy0osjhw45MANhgNHBBy4ysqNLJEnkHZRVzYqz5gDFQfMNzRhMcLUVw9SXwAKEDiCQ6NHo--F0VdWAhEfsHsCkOwvC89aFOE1yicZsXthTSS6PgeNoVXnoVWzCUNA1S_SkXB5GszyhHQkpCMhHQnpSEhHatEzkY6EdCSkIyEdCelIEsaBdKRe0JHKI4Ke99UVaUUwDg4OoIe0Uu5V8uOprZJWKj8vIK1EZ4FRWSuFOwe0lSnSVqpJD6StIG3ladJW-rvB7Dvc3i4NRUoVUoKVEJMG-gbmsTFRMKxEgU7yBsYxGMcYGccQ9lbVAR1NrY8wwdwOSlAdIJ_jFdNPMPbq_BhMvcmIylSe7bK1HsNjWiwHLyZDYgfGa32P1yCf0WUsAbgSaP9gTM0Zu_bnaJDYMURih0DZcFcfoMdD37UZz2TnkGENkNhxyf9MtoDYwW_VDbFDakw5sQPUrAaxQ17AnrqAO3V5VafUQ-wAfgid_oE3M4gdEp-s53zMrytih8xUzYul9BA7YB9QZDxXNoBOz5mBHiPTFbEDFjzTcAA9xI6a33I04qQZyrqCID6C-AaC-KwSQeGh44Q1PfV3D9R3_JurIK3HjxPmmsB9DgFiBIj7ChBzDRs6Ww4QOGp8HwIRZBOTG3ujA3kckeMhIccQjUvOAQOcCqReuEGXZQNXEq0QUk4hZQmhlXFlQNNuwGX5geUIM7xtDZhZUeheTaF3Pz_Ucl490DPgh2BH5JoAQkOWrjISrbRudRgGqoVqeoBp3i9IWEnZPFqFqLl7G_6p2XSD6ujobPpgROiEHtiae0Y2zwDKmjexMvHlKngI1v4-qkH8-_p-sX0TcyCvF8t9WqQoeCipV5xG9YqnfaxXtNkVLsjzNwRLwxRBAykCitm7pRto9mj2ULPvoqi2EtY8hbrMSkFLY3WZ6MNPzIf7snSxHMDFGk10APMWMc7eu48VlZUXyjZ8WusoTVtu4ZQ5JIzhjNKvJZVFzxRWzzDj7_4mPPtOGOMqSGulDzUMo8yItIAMCWPlaQ0JYz0gjHENGzpbDpAl0nLhCl2QTUxu0MoYcASIhLHeEsYgGpecAwY4FUi9cIMuy-acSLRCwtgltQaZKzR-ITK1aTeEMfmBsUqSeW211SWDhV4tTpYTevfzQy3n1UMYA_wQrIrRBMIYZOnily5zja-j-mXumIChmh7CGO8XJKykbB4d1jQTtnFUC5vpBtVRdTN9MCJ0Qg9hjFvGzDOAsuaNqHhWVKABID_7nZg8UsTtEbdvtywbXGQ0yH1iy-Ry3VtPQe-caQYxogFjRAJlw119gB4PfddmPJO9pYQ1QCjoklo7CEWB-K26AYCkxsQqFtQP-8gLuFoiaArYoyBigFPqgXj4vyGo8zED2BGsN_wiwM7hHJmpmhdL6QFxGJ3D7KBsAB3W-uWjSJh5wWbNqlP889BgY3wn2uxbJDVZYTVhMjEnjYO5d5o1voA0jqbzpPVy7jlZa-cU0jxaBZLmu7nn5s0dZvOCo0aLR9L809zz8uYdVdOdkpFjTSaDqaZzsZoOcRijcJiqkSYxBxqpKUbaEMerEVPFSjXJSjUXK9XM8zhcFhjmergfRXM1w1z7tkAQ9s78qVWB9S-bLKgCo52Uj9lkXK66yCYruplUGNiMT4pIG1RcGN0Ml1nKMivOu-IX_xqnWAxBhlWb0putxs8aniCP5ERQa1RjPhukS7byWUMQw4uXq0bmCJA5okYZMYorIksS0c8OUaOFtM4HYaymbOfCj4Xix0KlHA8_FoofCzWEnYUfC2WZgzZ2lh5bY6xKPfgSKYiM1pa9l8VI5aEdPkQOrUnEQxM15vLQRI0FPDRRcwEPjf-JUyEPTcSCq9k8k3pss4rsv3gSUmX_xVOXMvsvnvGU2X_xRNk1-28yISPH8mZDYf8l4QLmzRHQVwH0aVy9mUlUvYr-KwKu6L8i8ar-qzqo6r-qlar-W9ITzeyrVl616aoFH9orEuvkiHWHezMj_ANn3N7NuAzjmhnHgsO5t-G5t6Rs5Kz1iUzD56xRYTwk0-BKkK8ELOt4mmQa4Uu2QQThge-YCgOmwtRyYEYlv2SzXvrTXWp5LsMSXNKZrWZSWmpphq6OGGgzNpKyDrA_iojGtHRTo6ERbmQa3ciwdAnkG5lBNAIzjGrM9aTUI-bvCpkkUXPoORIqCTiw2GgJOLjYqAk4uNioCTh42pOagIOnPZWaZ1KPVxrFtGe8MqmmPeP1TDntGS-DymnPePVUS3u-2T6uF7d3_vrFZrVL05yli3Fa05v1N63JAkONyWpi-NBw-KBHz0ytog4xj9hFHrHy0oezW-kmTnHDdQ-teT2c5zBn10LOTvwm_cOl-DKl4byIS_XXWWUwRpxUDZhU1RJIZuGHCqMQ1sAL01D6yx05PXJ8BSFOhDj1Q5xwsfFrDFQwSrDYaBglXGxUjBIuNipGSW2uHaPMqi7epIFjqRoju36AVMbHL9tZtDmiowY9hi9xu9f_yMQWwFoVEOcpwFpMerx2WAtNv0vTLymyjHSIOb1QpEPApKWEvSpIR-WFjGAnN4V08GUqi3SgIxrgiK3vjoGkWbV9KXcXyfL3g10k94O6ol2kqDF3FylqLNhFipqrFLrDd5FgsdF2kWCx0XaRcLFRd5FwscGJMvBdJFhstF0kWGy0XSRcbNRdJFxs1F0knF9E3UXa5SblXeSIE2KMdEQXlE7ywGJUL6YY0cIJ7qj7F0kw5Tc7od7E-MGs-IGioioxV2vUwO6Oajg1YwWKC5e-y6YWIXDaCb7GphoXcFoKv8GmGg1ApEM_skYtBgBJh3FQjerKD5IOg96qymxVJbWq81nVqayqa_uIs6wfWUcvf_2y2mwX3wfL5dH8KEaL3y422_vF9tUmWGeE1sNrCUo8KaDEDEYZYsO4rnaMDbOxMS2wGBcRq0n7oTJ-BhW4cuMPBL6MdzAA5qUZ7oIgXfpALhG-pQptqaJa6oCWOpalDmOpIliq4JU6bqUOWamjVapAlSpGpQ5PqSNT6qBUrzEnHpgWB9n_tgl2-4R28cN283AVhs9heJ1G3JwHKOG3TQu_R8OoMcNAvP9xQq8DcZuekB5UIM6U3-yEehMDcbMcrLhcUteC-k6mJyORn11LsyjtU7sQW3eA2LpCWAGJLmoGGUPee1Fm7RK3QJVWoMooUCcTqPMI1CkEquwBVeKAOmdAnS6gzhRQJQmo8gPUqQHqrAB1QgCfC1B2bMojjDSfpKvSGggSe9LOSWsiTOVJuyP31bnfm4Bn7aQ9j__q_G9JyCToJJ2M--rcc2ZkcnHS_jRScKQaCTXcvOPewoy9BRHsLTTEzXqSRrnJmbG36D1vR7DFcIBbDPhxCuK9k2B_IQHpCBRn61UcuzsqzqI_b1WO0pj7Km5QzK32hWexpKM0fvzLr-SVSVhJRmncV-dW6crkpqSjNP6r8ytw4WkoySiN_-r86lqZjJN0lHb0___0jwAAAP__VSsNvg== +https://raduberinde.github.io/optsteps.html#eJzsXd1y2ziWvt-nwPrKXlFqEZRsSVOu6t50utYpr5ONM3sz6epiO_I2E1nKSvLs9G7t1NQ8Qy776fpJpvgjiQTxcwCBJKCc3LhCEhSJc86Hg_N9AP_v7P4_bs9mZ_cvb1--eEf-hfzw9vW_k5jE4fvlzd3dy7fk1eubu_QAJa_vSBwOPpHr7A97PsrO0_x8VD8_ys5H-flR_fw4Oz_Kz48Hn86Cs7vV-un75PHxbHbW7_dJ_M3NMtkm8eL9stfrkZ8P__32W9IPSS8MxpR8--37Ze_zevVx_rB9v-yR37_89vuXv_3-5W_kYbV4flpuZuTTLPzn5fNiQZIZJY-ziGxmI_JxNiafZpPdiSl5nIVDspmFIfk4C2naaLw7GV6mZ6_Ss5P07JR8mlG6v2dEHmd0RDYzOiYfZ_QyPTvdnY2G6U-GZDOLKPk4i6LqQ36a_zoj52FApxfVE48f0uMX_f775-Ewmp_T_vgiIOdRMLr461-LY2FAg-zo5HDdtB_SILzsh9OARn16GUTDfhSlF4XDIAwPjSfBNEgvHWeX0vRSOt1dOgbd8CoIJ6UbZheOg_AyqN9xcnF9fR6OA0rTV81_4vr6fHI4MM2uuAxoFETD7IrL9Mi0dGCYXXIV0FEQhfkTZEeGpSNhdmQS0HEQ0exI_tNh6QjNjkyD9GXyN8l_nB6OUArpAToK6LjWA3mHps9d7gFK8xdOOyF7YRrl7xdeFu9HR8XbhFfF29Bx8ezhpHh2elk8aTjdPekU8qRRmN6A_6S5oYJoeLjj_kmzH42G-yelxd0OT0pH2RF6eFKae2p0eFJ6WXj3l8K7k-Vyvu5_XCVLcv5LvPklO53948RvCj-7EI7DQRrFcThIAzkOB2ksx-EgDec4HDysP_z8U7LcztfLePHT058fHn7aJk_zzTZ--jy7TK_Yxj8v5qvkw-wqQ68dAsR0kIJATAcZDsR0kEFBTAcZGsRUfuswSi_Z3zscZdC3h5A4GmQoEkeDDEjiaJBhSRwNMjiJI_nt6TC9ZH97GmbIucegeDTIYCgeDTIkikeDDIzi0SDDo3ikuP1Vesnh9pMMkfcgFo8HGY7F40EGZfF4kKFZPB6kgJb-ld4-GqWX7G8fjTnGfnpebJPPi-Qh2f46I4v547a_Xv3P5nz-l_hhu_i1v1rOLwKyTv7rl-LE_87Xq_5q3X9arec872GAlTlbR9crPrrmx6v4OhKi6e5cCT7Dyz4NOWi5A8rirG_4GGbRTYcBvQqi7KVp_uvR4UiY4RkNAzoJogwTaP7ro9KREs6mkDXhwOoOS3dnmwLSq90LDHevNNk9brh73BLYptg65mDrDkr7-yb20TQ9Mjo8Ls29d3x4XDrhub0Mdv-O6OsI-oqNYg0l_y4ASyq5yGHMrAJmFS2rUMngJAOSDEIy8MhgIwOMDCoykMjgIQOGRyNhFQYZDGQAkEE_BvoY3JP4AwBMEFPAmKLsPNuxL4CAcKy-1lUkKMFACQNKAFCO_nLol-O-HPTliC-HeznWy4FejvJyiKu7tBxMD-vVZiNuckpBBX3JnXdOwN3SoI9CH2HzEC9JTP4Ub67j8EdVq5bNqvk4hQGU7178-WJgBZNupebd2qFXc_tW7dq8vrXpt_sbJ4vtfL2RX06qbXIvLWrFs5D8afW8na-vz1MYfFgtN9t1nCy3m-vzb8IZOf_m7o-3t6RPfrwQ249n7khp7rqduxm1-eEjGVu5gaM5EgpvDrMsa9IsQory_iwc721aJJxVs07KZv0D-SYcV-wckMcP17xxmmNRnuVHakc5mLzl2RnX1typFM_Iunl__a4K67JmLax5veunQ6wWUykmXseMZSnlWDY3Zz73yqcl4bhiW55RxxLjH6zZVimSb8aprMM_zPRLQqXbiQzHWqyw0_WuL_YW2xUHqxarGii12JRjsdxKRQVtWljvx_fLnHq7T54-L5LHX-_jp_l_xuuX__0cL5JtMt_syDjJBRk9F4xpiaEje4aOa2PXGDpubST1BHmGiQwdMnQ-M3REztARFsu9nnr6XSNufFisGfvY-lPthgywMmddrTF5g4_I0HnA0NXcXga7p1T48xt9xUaxhpIyhk50kcOYiQxdgwydyB8AYIKYolHrU3Se7diXMXSKa11FApcZOkWX8hg6QZNTCiroS5YZOliLRhk62COwDJ28VesMndbjHBg6UDMzhk6_W6l5t3bo1UKGTr9vbfptrWDcl1xOqm3sM3S8Xzkv7n5zT76_uX93c_fiXb7G5MV39-_Os5t-d09u7t5NLi7I67fVw__6-vXtBfTB_kC26Uh6IfYvEYOoi9rdZBViBhHoI2YMouDmNc_jXse6XFsMIvswIgZR4SitMYiK5ygxiCpzmDGI7F0V1mXN2iqDuP95EYMoMn5rDKLoAUoMorDDzRjEmklYw7EW65BBfLVKlj_sCc4Kd1g5hawhsobIGiJr6PZ02O-6NbKGyBoia4isIaIvsoY-YCayhsgaeo4pyBoia4isIbKGyBoia-gha9gJn6e_7hDweMgrygAAeUXkFZFXRF6RyA3HWqwDXvHN8-aXnDS8WW5Xr1bJ8nb-uN1Ri6KzFXbxCtlFZBeRXUR20bVps9_1bWQXkV1EdhHZRURfZBd9wExkF5Fd9BxTkF1EdhHZRU_YRRntYrpr6L7VfFGUsmRX-8JFynvqKC5Sa2fOBm9ttDls6_YzeSrNrWKbt6bWvqbu0IxIj4sdxCbwWlhU24xfaO3WS86362dAxoakNZLWSFojaY2kdZuk9dv50-rP87vV9u55sXixWn5ItslquSOtRWcL0voqI60vkbRG0hpJayStXavG-E2bIGmNpDWS1khaI_oiae0DZiJpjaS155iCpDWS1khae0Jawx7htOhnrWY2l8IqOGJQYzc7-bi-Pooj1hMTQEhA57hAM0oQCWaxdzW4_hqZWnVsI1OLTC0ytcjUts_UvlwkT8ky3s7vi5Q2p2hrhwtu9jLjZkPkZpGbRW4WuVnXig5-swPIzSI3i9wscrOIvsjN-oCZyM0iN-s5piA3i9wscrOecLPABcW7Qhbs6pPc3BjEAZoxulq3ZnsX1Lj1TjZ5Ks2-bp3R3bNuekwq7nMNNT3yrMizIs-KPCvyrMizAnjW2_nj9rvNZvWQxNv5q1Wy3LxN54w7vlV4uuBdQ-RdkXdF3hV5VzcLCn5X_pF3Rd4VeVfkXRF9kXf1ATORd22Qd2WLrRIwYUurBqwS4g-kJigogCNHexIcrcK6vGiCMYFeBxX0JcscLayFCxytCS_oGCHowjbOx22i3fV-yro7KDfSdYBxvUNqsvGhFfau2iNs-YSmG4zBDbQZ1ZMdQgVZCTLxYvxocEvtPROvyGxYJl43q-km6xZHLbCTzJh4wc1hGxmQ6sWtMfH6GrQIuvlB6-6g9VRgLLfjHFpbx-t9cL1jV4GKfFDjgRoP1HigxgM1Hqjx4HOYqPFAjYfDpQjUeKDGAzUeqPGQazz6rNvLyrc6fCxCdOcQLebeUQiCQhAnhSAKPhpBxYK6oyK_UFzraqy6zB1pkBRqqt4Vjl6XnLdDLWvS8Z3z8GAC3m73wCn3U-LaG8-eFH3YDIfPKeArrmyXtccsqd1titShLmhxghEPfdcjIxP2I-AV86iuQXWNU_tcmG1c0ZVMwqCLAUFpRyYh_w3YphYdyyRgMiChAkskkwBP4FuugImzLFVHmMkk2Lsq5FWsF7Qqk9DQRI8MNNHdZOvaabUdu8PUR4LrnPICpWAKRTUoquHaF0U1KKpBUU3nopq-XFTTE5yuEbtIvnRek2x8yKzJAVB04xd-oujGd9GNiAJH-O0cfsVGqQhfRBc5DG5I6XQgfAEqATqXAIC5_yNZbSjb3x3Nr-b3LXWBxuY4p0Ds-Z42i2xjWSLAKWCJLmldFIDpMabHtvcdNNY-IDbaW0ncjJgCvk4ZZU6nmBMrjI0yJ8C7oswJZU4oc9LqYJQ5faUyJ8V4A9zlpSttiw5Uy3IpO9oWwc3NvuHUqrZFocaqq9xE2hZ1cb4tok5cGhC-rJm2pc-ajpWwsZZtVdsCWTk01lk51HLFCF7hsWNNhcqLvcAN2wrDNRM2vVk_LzPF0u38cftitdjsJE2cEyhmQjETipk8FDMRhVqpNnIjXf4V0C7mxkbjObO_U2UUq8Wxw-IJPwYjpL48oL5qiHZEBodOj07vhdPXRgKVMKp7AZDuLyu3zFLVa4z3CBHfRQQktj78h6lV56lVs4QhYD0dypFweDqZ4QnlSChHQjkSypFQjtRiZKIcCeVIKEdCORLKkTScA-VIXsiR2CeC7qTTlWhF8RySOoAd0Qp7V81vjrUqWqn9vEK0ku2yw1WtlM5UZCtjlK3USQ-UraBs5euUrfg7wfS93N6uDEXLFFodq9FNFuQbyGMjUXBaRIFN8QbmMZjHOJnHEPFUNQRt-mpPMCGcDmpIHSDfv1PLTzD36nzDQrtkRA3K97Nsq9vwuJbLwReTobAD8zXf8zXIBwkFQwCOBNY_xXAkYh_9oQcUdpyisENhbHion2DEQ9-1mcgUc8iwBijsuJZ_cFQh7JC36kbYofVMB2EHqNkRwg79Do7MO7jTkDcNSjvCDuAnZfmfTnJD2KHx8V_JZ7K6EnboQLUsl7Ij7IB9mkxwHesAne4zA91GpithByx55tUB7Ag7jvxKmhM7zXDGFSziYxHfwSK-aImgctNxIoInf-dAvte_pQayuv04EY4J0uuwQIwFYl8LxFLHhqLlCRaOGp-HQDqyCXATT3Qgl2Pl-JQqxxCLa2LACUKB1gs3GLLiwpVGKywp70rKGp3G1pUBTbspLus_2KHCDG97RJnZsNOjIzu9e3w4KnjtlJ4BPwTbIteFIjRk6JJ_zV_qfB190l_6TMBUzU5hWvYLGl7CukeHn_knYueo75rNd6iOts7mP4yqOmGnbC3dI1vmAKzlXVyZ-HKRPCXLeJutQfzj8sN8_SbXQN7OH7e7RYqKi4r1iuNsveLQx_WKffEKF9T5O1JLQ4qgAYqA4_aUOYFuj24PdfsuFtXW0pqvYV1mbUFLY-syMYa_shj2ZegSBQDFNZoYAO4NYpK5t48rKmsvtJ_wWV1H6dpwC5fMoWAMEcWvIVUkz1SunhHm3_4Snr4LxqQGsrrSh5uGcRCRl5ChYIyFNRSMeSAYkzo2FC1PUCXS8sIVfkc2AW7QlTHgDBAFY94KxiAW18SAE4QCrRduMGTFmhONVigYu-auQZZ2mnwhMrdpN4Ix_QcTLUmWtbW2Lhnc6fXFyXqd3j0-HBW8dgRjgB-CrWJ0QTAGGbrkS5elztfR-mXpMwFTNTuCMdkvaHgJ6x4drmkmYueoL2zmO1RHq5v5D6OqTtgRjEmXMcscgLW8EyueDQ3oQJFf_E5CHSnW7bFu3-6ybPAio5OcJ7YsLrc99VTcXQIzWCM64RqRwtjwUD_BiIe-azORKZ5SwhpgKeiau3YQWgWSt-qmAKT1TKLFgvbLPvodXF8i6Eqxx6CLAUFpp8Qj_w3FOh83CjuK8Ua-CLDzco4OVMtyKTtFHMHNYX7AOkCHa_0OT1Eo85LVUrRO8beqw-b1nWyyH5CdyypXExbAXDROZtFw33gKaZzBedH6cRaF-9bhENI8GwWK5ptZRA_NQ2HzUqBmg0fR_OMsig7NO1pNNyS9MBiNTmY1HcXVdFiHcaoOU3fSIudAJ3XFSRvSeDXiqrhSTXOlGsWVau5FHA4LAnetzkfRXd1wV98GCCKemX9tq8D8Y5MVq8B4O-Ujm4zDVRdssmGYaaWBzcSkSrTBrQtjmOEwyxlm1bwrfvGvcYnFKfRh3afsstX4WcML1JFcKNYaHYFnJxmSrXzWEKTwknHVqBwBKkfMJCNOaUV0RSL21SFmspDW9SCC0VQcXPixUPxYqFbg4cdC8WOhjqiz8GOhInewps6y42uCUcmDL5GCxGht-TvbjVwdWvUiUvUmlQ5N1ViqQ1M1VujQVM0VOjT5J06VOjSVCu7I5vtez33WUP2Xg5Cp-i-HLmP1X454xuq_HCi7Vv-NRqQXBtHkVNR_RbqAvDkW9E0K-jyt3sQlqV7N_rUOrtm_1uN1-9dtULd_3Sp1-7dkJ57b17287tN1D676Kwrr9IR11bmZE_GBiOsd4gqca-KcCg6xt2HsZYyNmjWfxDRyzRq3jIdiGhwJDiOByDu-TjGN8iXbEILIiu9IhQGpMDMOzCnyS5f1sk93mfFcjhFc2sxWM5SWGc3Q1RYDbeZGWt4BjkeV0JhHNzWaGuFEptGJjMiWQL2RG0IjsMLoCKwnzB2RvysxSarm0H0kTAg4cLfxCDh4t3EJOHi3cQk4OO3JJeDgtKdR832v5yONIe2Zj0ymtGc-nhnTnvkwaEx75qOnGe35Zv28nN8_xMsXq8VmR3MyB3NaM5r4S2uKiqHOsJqYPjScPtixs9CqaEPkEbvgEWsvXUU35iRC3OmGh1VeD3EOObsWODv1m_hXl5L3Ka_Oi3Upf4NVp8aIoOoAqJoRSG7VDw2eQrkGXklD2V_uKLmjJFawxIklTvslTni3ydcYmNQowd3Gq1HCu41bo4R3G7dGyW1uvUa5X3XxZpc4Mqsx9scrlcp8--X-Ptvs8asGHpcvcbrnf2bSV5S1akWcr6GsJZTHWy9roet36fqMIdlKh1rTC610KJS0nLTXpNJReyEn1MlNVTrkfapb6cBAdCAQW58dA0WzZvNS6SxSFO-VWaT0g7qqWaSqsXQWqWqsmEWqmpssdIfPIsHdxptFgruNN4uEdxt3FgnvNrhQBj6LBHcbbxYJ7jbeLBLebdxZJLzbuLNIuL6IO4vss03YWWRPkmL0bGQXnJscEovecTlFj5dOSJ_av0xC2H-TC-5JzB_cyh84JqoLc61mDeLbcR3nyFyBE8LMd9nMMgRJO8XX2EzzAklL5TfYTLMBSO_wt6wxywFAvSPYqMZ05Af1jkDeaqpsNRW1mutZzaWspmN7TzKsnwVnL__yebFaz79PHh_PZmd5tfjtfLX-MF-_WiXLvaC1eqyoEo9KVWKBogxrwziudlwbFtfGrJTFpBWxI2U_XMXPSSWu0vwDC1_OBxig5mW53AWpdNkrcqnqW6alLdOqlnlBy7yWZV7GMq1gmRavzOtW5iUr82qVaaHKtEZlXp4yr0yZF6W8rjnJiml5kv1vq2SzLWQXP6xXTzdp-pym17uMW3IBJ_3u89Lv3mmsMcNE3P88wetEvM8npE8qERf23-SCexITcbcCrDxccseC44PMDiNx2LuW51HWoV1ZWw-BtXWDtAKSXRyZZJzy3IuD2oy2wFRWYKooMBcTmOsIzCUEpuoBU-GAuWbAXC5grhQwFQmY6gPMpQHmqgBzQYBcC8AGNucSAc2nGaq8BgpiTzs4eU2UVJ52OEpfXfq9CThrpx158leXf0tCh6DTDDLpq0v3mdHh4rTjqWcQSEcQajh5x7mFG3MLophbWMib7ZBGB5dzY27hvW5HMcUIgVMM-HYK6rmTYn6hUdJRGK5v13Di23HrLPZ5KzZLE86rpEmxdLUvnMXSztLk-a98Ja8OYaWZpUlfXbpKV4eb0s7S5K8uX4ELp6E0szT5q8tX1-owTtpZ2tn__9M_AgAA__9V3MKw # Exploration patterns with varying costs. optsteps diff --git a/pkg/sql/opt/xform/testdata/rules/join_order b/pkg/sql/opt/xform/testdata/rules/join_order index 391b42da23e6..563dbd7ab9ea 100644 --- a/pkg/sql/opt/xform/testdata/rules/join_order +++ b/pkg/sql/opt/xform/testdata/rules/join_order @@ -2948,18 +2948,18 @@ JOIN t88659 AS t4 ON (t3.a) = (t4.b) AND (t2.b) = (t4.a) AND (t2.a) = (t4.a); ---- inner-join (lookup t88659) ├── columns: a:1!null b:2!null c:3!null a:7!null b:8!null c:9!null a:13!null b:14!null c:15!null a:19!null b:20!null c:21 - ├── key columns: [20] = [13] + ├── key columns: [7] = [19] ├── lookup columns are key ├── immutable ├── key: (1) - ├── fd: (1)-->(2,3), (7)-->(9), (7)==(2,8,19), (8)==(2,7,19), (2)==(7,8,19), (13)-->(14,15), (3)==(9,15), (9)==(3,15), (15)==(3,9), (19)-->(20,21), (13)==(20), (20)==(13), (19)==(2,7,8) + ├── fd: (1)-->(2,3), (7)-->(9), (7)==(2,8,13,14,19,20), (8)==(2,7,13,14,19,20), (2)==(7,8,13,14,19,20), (13)-->(15), (3)==(9,15,21), (9)==(3,15,21), (15)==(3,9,21), (19)-->(21), (13)==(2,7,8,14,19,20), (20)==(2,7,8,13,14,19), (19)==(2,7,8,13,14,20), (21)==(3,9,15), (14)==(2,7,8,13,19,20) ├── inner-join (lookup t88659) - │ ├── columns: a:1!null b:2!null c:3!null a:7!null b:8!null c:9!null a:19!null b:20!null c:21 - │ ├── key columns: [7] = [19] + │ ├── columns: a:1!null b:2!null c:3!null a:7!null b:8!null c:9!null a:13!null b:14!null c:15!null + │ ├── key columns: [2] = [13] │ ├── lookup columns are key │ ├── immutable │ ├── key: (1) - │ ├── fd: (1)-->(2,3), (7)-->(9), (7)==(2,8,19,20), (8)==(2,7,19,20), (19)-->(21), (19)==(2,7,8,20), (20)==(2,7,8,19), (9)==(3,21), (21)==(3,9), (2)==(7,8,19,20), (3)==(9,21) + │ ├── fd: (1)-->(2,3), (7)-->(9), (7)==(2,8,13,14), (8)==(2,7,13,14), (13)-->(15), (9)==(3,15), (15)==(3,9), (13)==(2,7,8,14), (14)==(2,7,8,13), (2)==(7,8,13,14), (3)==(9,15) │ ├── inner-join (lookup t88659) │ │ ├── columns: a:1!null b:2!null c:3!null a:7!null b:8!null c:9!null │ │ ├── key columns: [1] = [1] @@ -2988,9 +2988,12 @@ inner-join (lookup t88659) │ │ │ └── filters (true) │ │ └── filters │ │ └── c:3 = c:9 [outer=(3,9), immutable, constraints=(/3: (/NULL - ]; /9: (/NULL - ]), fd=(3)==(9), (9)==(3)] - │ └── filters (true) + │ └── filters + │ ├── c:9 = c:15 [outer=(9,15), immutable, constraints=(/9: (/NULL - ]; /15: (/NULL - ]), fd=(9)==(15), (15)==(9)] + │ └── b:2 = b:14 [outer=(2,14), constraints=(/2: (/NULL - ]; /14: (/NULL - ]), fd=(2)==(14), (14)==(2)] └── filters - └── c:9 = c:15 [outer=(9,15), immutable, constraints=(/9: (/NULL - ]; /15: (/NULL - ]), fd=(9)==(15), (15)==(9)] + ├── a:13 = b:20 [outer=(13,20), constraints=(/13: (/NULL - ]; /20: (/NULL - ]), fd=(13)==(20), (20)==(13)] + └── c:3 = c:21 [outer=(3,21), immutable, constraints=(/3: (/NULL - ]; /21: (/NULL - ]), fd=(3)==(21), (21)==(3)] # Regression test for #90761 - don't drop LeftJoin filter when there are enough # InnerJoin edges to "link" all relations and the LeftJoin doesn't get @@ -3369,3 +3372,76 @@ project │ └── filters │ └── (patient2_.id:11 IS NULL) OR (site3_.id:15 IN (1, 2)) [outer=(11,15)] └── filters (true) + +# Regression test for #106371 - only infer self-join equalities if the original +# equality columns form a key over the *base* table, not just the join inputs. +exec-ddl +CREATE TABLE t106371 (x INT NOT NULL, y INT NOT NULL); +---- + +# Don't add an "a.y = b.y" filter. +reorderjoins +SELECT * FROM (SELECT * FROM t106371 ORDER BY y DESC LIMIT 1) a +JOIN (SELECT DISTINCT ON (x) * FROM t106371) b ON a.x = b.x; +---- +-------------------------------------------------------------------------------- +Join Tree #1 +-------------------------------------------------------------------------------- + inner-join (hash) + ├── limit + │ ├── scan t106371 + │ └── 1 + ├── distinct-on + │ ├── scan t106371 + │ └── aggregations + │ └── first-agg + │ └── y + └── filters + └── x = x +Vertexes + A: + limit + ├── scan t106371 + └── 1 + B: + distinct-on + ├── scan t106371 + └── aggregations + └── first-agg + └── y +Edges + x = x [inner, ses=AB, tes=AB, rules=()] +Joining AB + A B [inner, refs=AB] + B A [inner, refs=AB] +Joins Considered: 2 +================================================================================ +Final Plan +================================================================================ +inner-join (hash) + ├── columns: x:1!null y:2!null x:6!null y:7!null + ├── cardinality: [0 - 1] + ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-one) + ├── key: () + ├── fd: ()-->(1,2,6,7), (6)==(1), (1)==(6) + ├── distinct-on + │ ├── columns: x:6!null y:7!null + │ ├── grouping columns: x:6!null + │ ├── key: (6) + │ ├── fd: (6)-->(7) + │ ├── scan t106371 + │ │ └── columns: x:6!null y:7!null + │ └── aggregations + │ └── first-agg [as=y:7, outer=(7)] + │ └── y:7 + ├── top-k + │ ├── columns: x:1!null y:2!null + │ ├── internal-ordering: -2 + │ ├── k: 1 + │ ├── cardinality: [0 - 1] + │ ├── key: () + │ ├── fd: ()-->(1,2) + │ └── scan t106371 + │ └── columns: x:1!null y:2!null + └── filters + └── x:1 = x:6 [outer=(1,6), constraints=(/1: (/NULL - ]; /6: (/NULL - ]), fd=(1)==(6), (6)==(1)] From be8c5c10a8a05e64a3c2f0cd6b9d545a068b94f8 Mon Sep 17 00:00:00 2001 From: maryliag Date: Tue, 18 Jul 2023 15:07:30 -0400 Subject: [PATCH 3/3] cli: fix debug zip with new columns for cluster settings The addition of new columns on cluster_settings view done on #104449 were causing debug zip fails to add the information from that table, since the query used to gather the information was doing a join and not considering the new columns. This commit updates the query to use the explicit columns, so even if new columns are added it won't be a problem in the future. It also adds tests for all custom querys used to generate the debug zip, so this type of issue would have been caught. The file `crdb_internal.cluster_settings.txt` in debug zips was empty due to this bug on v23.1.5 (only version affected by this bug). Fixes #107103 Release note (bug fix): Debug zip now are properly showing the information from cluster_settings. The file `crdb_internal.cluster_settings.txt` in debug zips was empty due to this bug on v23.1.5 (only version affected by this bug). --- pkg/cli/zip_table_registry.go | 18 +++++++------- pkg/cli/zip_table_registry_test.go | 39 ++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/pkg/cli/zip_table_registry.go b/pkg/cli/zip_table_registry.go index 6050c1d64f49..a20f1c05c84a 100644 --- a/pkg/cli/zip_table_registry.go +++ b/pkg/cli/zip_table_registry.go @@ -217,15 +217,15 @@ var zipInternalTablesPerCluster = DebugZipTableRegistry{ }, }, "crdb_internal.cluster_settings": { - customQueryRedacted: `SELECT * FROM ( - SELECT * - FROM crdb_internal.cluster_settings - WHERE type <> 's' - ) UNION ( - SELECT variable, '' as value, type, public, description - FROM crdb_internal.cluster_settings g - WHERE type = 's' - )`, + customQueryRedacted: `SELECT + variable, + CASE WHEN type = 's' AND value != default_value THEN '' ELSE value END value, + type, + public, + description, + default_value, + origin + FROM crdb_internal.cluster_settings`, }, "crdb_internal.cluster_transactions": { // `last_auto_retry_reason` contains error text that may contain diff --git a/pkg/cli/zip_table_registry_test.go b/pkg/cli/zip_table_registry_test.go index 2596b7001ffd..3718fca41f7f 100644 --- a/pkg/cli/zip_table_registry_test.go +++ b/pkg/cli/zip_table_registry_test.go @@ -11,11 +11,17 @@ package cli import ( + "context" "fmt" "testing" + "github.com/cockroachdb/cockroach/pkg/base" + "github.com/cockroachdb/cockroach/pkg/sql/tests" + "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" + "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" "github.com/cockroachdb/cockroach/pkg/util/leaktest" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestQueryForTable(t *testing.T) { @@ -134,3 +140,36 @@ you must redact them at the SQL level.` } } } + +func executeAllCustomQuerys( + t *testing.T, sqlDB *sqlutils.SQLRunner, tableRegistry DebugZipTableRegistry, +) { + for table, regConfig := range tableRegistry { + if regConfig.customQueryRedacted != "" { + rows := sqlDB.Query(t, regConfig.customQueryRedacted) + require.NoError(t, rows.Err(), "failed to select for table %s redacted", table) + } + + if regConfig.customQueryUnredacted != "" { + rows := sqlDB.Query(t, regConfig.customQueryUnredacted) + require.NoError(t, rows.Err(), "failed to select for table %s unredacted", table) + } + } +} + +func TestCustomQuery(t *testing.T) { + defer leaktest.AfterTest(t)() + ctx := context.Background() + + params, _ := tests.CreateTestServerParams() + cluster := serverutils.StartNewTestCluster(t, 3 /* numNodes */, base.TestClusterArgs{ + ServerArgs: params, + }) + testConn := cluster.ServerConn(0 /* idx */) + sqlDB := sqlutils.MakeSQLRunner(testConn) + defer cluster.Stopper().Stop(ctx) + + executeAllCustomQuerys(t, sqlDB, zipInternalTablesPerCluster) + executeAllCustomQuerys(t, sqlDB, zipInternalTablesPerNode) + executeAllCustomQuerys(t, sqlDB, zipSystemTables) +}