Skip to content

Commit 78783e8

Browse files
craig[bot]Mark Sirek
andcommitted
106334: xform: compute distribution of a lookup join with a lookup join as input r=rytaft a=msirek The adjustment to optimizer costing of lookup joins, added in v23.1, to account for non-local input relation distribution (among the regions in a multiregion database) did not account for the case where the input to the lookup join is itself a lookup join. This resulted in an extra distribution cost being added to some best-cost lookup joins, causing the optimizer to no longer select them. The issue is in function `getCRBDRegionColFromInput`, which only looks for scan and locality-optimized scan operations as inputs. It is now updated with a recursive call to itself plus a call to `BuildLookupJoinLookupTableDistribution`, so the proper distribution of a chain of lookup joins, plus the associated `crdb_region` column in the lookup table can be determined. Function `BuildLookupJoinLookupTableDistribution` is updated to return the first lookup index column, when it is matched with the input's crdb_region column, to facilitate this behavior. Fixes: cockroachdb#105942 Release note (bug fix): This patch fixes an optimizer costing bug introduced in v23.1 which may cause a query involving 2 or more joins with REGIONAL BY ROW tables to not pick the most optimal lookup joins. ---- xform: improve detection of local lookup joins with RBR tables This commit improves the optimizer's ability to detect the proper distribution of a string of lookup joins involving REGIONAL BY ROW tables by updating the interfaces which match on the `crdb_region` key column of the join to use a `ColSet` which holds all of the `crdb_region` column ids which have been equated with eachother. Informs: cockroachdb#105942 Release note (bug fix): This patch fixes an optimizer costing bug introduced in v23.1 which may cause a query whose best-cost query plan is a string of lookup joins with REGIONAL BY ROW tables, one after the other in sequence, to not pick the most optimal join plan. ---- execbuilder: use lookup join lookup table distribution in home region checking This commit updates enforce_home_region checking to build the lookup join lookup table's distribution the same as is done in the coster. This can prevent some lookup joins with a home region from being errored out as not having a home region. Informs: cockroachdb#105942 Release note: None ---- memo: print lookup table distribution in EXPLAIN output This commit adds the distribution of the lookup table of lookup join to the EXPLAIN output when it is not empty. Informs: cockroachdb#105942 Release note: None Co-authored-by: Mark Sirek <[email protected]>
2 parents 898c592 + 8d17ae0 commit 78783e8

File tree

20 files changed

+487
-113
lines changed

20 files changed

+487
-113
lines changed

pkg/ccl/logictestccl/testdata/logic_test/multi_region_remote_access_error

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,9 @@ CREATE TABLE customers (
246246
name STRING NOT NULL
247247
) LOCALITY REGIONAL BY ROW;
248248

249+
statement ok
250+
INSERT INTO customers VALUES ('69a1c2c2-5b18-459e-94d2-079dc53a4dd0', 'ACME Sprockets')
251+
249252
statement ok
250253
ALTER TABLE customers INJECT STATISTICS '[
251254
{
@@ -277,6 +280,9 @@ CREATE TABLE orders (
277280
FOREIGN KEY (cust_id, crdb_region) REFERENCES customers (id, crdb_region) ON UPDATE CASCADE
278281
) LOCALITY REGIONAL BY ROW;
279282

283+
statement ok
284+
INSERT INTO orders VALUES ('69a1c2c2-5b18-459e-94d2-079dc53a4dd0', '69a1c2c2-5b18-459e-94d2-079dc53a4dd0', 'Super Deluxe Sprocket')
285+
280286
statement ok
281287
ALTER TABLE orders INJECT STATISTICS '[
282288
{
@@ -636,11 +642,33 @@ locality-optimized-search
636642
├── constraint: /11/10: [/'ca-central-1' - /'us-east-1']
637643
└── limit: 1
638644

639-
# Locality optimized search with lookup join will be supported in phase 2 or 3
640-
# when we can dynamically determine if the lookup will access a remote region.
641-
retry
642-
statement error pq: Query has no home region\. Try adding a filter on o\.crdb_region and/or on key column \(o\.id\)\. For more information, see https://www.cockroachlabs.com/docs/stable/cost-based-optimizer.html#control-whether-queries-are-limited-to-a-single-region
643-
SELECT * FROM customers c JOIN orders o ON c.id = o.cust_id AND
645+
# Static checking should not error this query out, because we now generate a
646+
# plan with a home region for it.
647+
query T retry
648+
EXPLAIN (OPT) SELECT * FROM customers c JOIN orders o ON c.id = o.cust_id AND
649+
(c.crdb_region = o.crdb_region) WHERE c.id = '69a1c2c2-5b18-459e-94d2-079dc53a4dd0'
650+
----
651+
project
652+
└── inner-join (lookup orders [as=o])
653+
├── lookup columns are key
654+
├── inner-join (lookup orders@orders_cust_id_idx [as=o])
655+
│ ├── locality-optimized-search
656+
│ │ ├── scan customers [as=c]
657+
│ │ │ └── constraint: /15/13: [/'ap-southeast-2'/'69a1c2c2-5b18-459e-94d2-079dc53a4dd0' - /'ap-southeast-2'/'69a1c2c2-5b18-459e-94d2-079dc53a4dd0']
658+
│ │ └── scan customers [as=c]
659+
│ │ └── constraint: /20/18
660+
│ │ ├── [/'ca-central-1'/'69a1c2c2-5b18-459e-94d2-079dc53a4dd0' - /'ca-central-1'/'69a1c2c2-5b18-459e-94d2-079dc53a4dd0']
661+
│ │ └── [/'us-east-1'/'69a1c2c2-5b18-459e-94d2-079dc53a4dd0' - /'us-east-1'/'69a1c2c2-5b18-459e-94d2-079dc53a4dd0']
662+
│ └── filters
663+
│ └── cust_id = '69a1c2c2-5b18-459e-94d2-079dc53a4dd0'
664+
└── filters (true)
665+
666+
# This query should error out dynamically during execution, but
667+
# `GetLookupJoinLookupTableDistribution` doesn't currently work in
668+
# the execbuilder phase because `Optimizer.stateMap` is empty.
669+
# TODO(msirek): Fix this test case to not error out statically.
670+
statement error pq: Query has no home region\. Try adding a filter on o\.crdb_region and/or on key column \(o\.cust_id\)\. For more information, see https://www.cockroachlabs.com/docs/stable/cost-based-optimizer.html#control-whether-queries-are-limited-to-a-single-region
671+
SELECT 'a' FROM customers c JOIN orders o ON c.id = o.cust_id AND
644672
(c.crdb_region = o.crdb_region) WHERE c.id = '69a1c2c2-5b18-459e-94d2-079dc53a4dd0'
645673

646674
# Locality optimized lookup join is allowed.
@@ -1052,6 +1080,7 @@ project
10521080
│ ├── fd: ()-->(11), (7)-->(9)
10531081
│ ├── limit hint: 1.00
10541082
│ ├── distribution: ap-southeast-2
1083+
│ ├── lookup table distribution: ap-southeast-2
10551084
│ ├── prune: (7)
10561085
│ ├── inner-join (inverted json_arr1_rbr@j_idx [as=t1])
10571086
│ │ ├── columns: t2.j:3 t1.k:18 crdb_region:22

pkg/ccl/logictestccl/testdata/logic_test/regional_by_row_query_behavior

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3554,3 +3554,205 @@ EXPLAIN (VEC) SELECT * FROM child LEFT JOIN parent ON p_id = c_p_id WHERE c_id =
35543554

35553555
statement ok
35563556
RESET vectorize
3557+
3558+
statement ok
3559+
CREATE TABLE abc (
3560+
id UUID PRIMARY KEY,
3561+
id1 UUID NOT NULL,
3562+
created_at TIMESTAMP NOT NULL,
3563+
updated_at TIMESTAMP NOT NULL,
3564+
id2 UUID NULL,
3565+
INDEX (id1 ASC, id2 ASC)
3566+
) LOCALITY REGIONAL BY ROW;
3567+
3568+
statement ok
3569+
CREATE TABLE xyz (
3570+
id UUID PRIMARY KEY,
3571+
str STRING NOT NULL,
3572+
abc_id UUID NOT NULL,
3573+
id2 UUID NULL,
3574+
FOREIGN KEY (abc_id) REFERENCES abc(id) ON DELETE CASCADE,
3575+
INDEX (abc_id ASC, id2 ASC),
3576+
INDEX (id2 ASC, str ASC, abc_id ASC)
3577+
) LOCALITY REGIONAL BY ROW;
3578+
3579+
statement ok
3580+
ALTER TABLE abc INJECT STATISTICS '[
3581+
{
3582+
"avg_size": 3000,
3583+
"columns": ["id"],
3584+
"distinct_count": 100,
3585+
"row_count": 100,
3586+
"created_at": "2018-01-01 1:00:00.00000+00:00"
3587+
}
3588+
]';
3589+
3590+
statement ok
3591+
ALTER TABLE xyz INJECT STATISTICS '[
3592+
{
3593+
"avg_size": 3000,
3594+
"columns": ["id"],
3595+
"distinct_count": 100,
3596+
"row_count": 100,
3597+
"created_at": "2018-01-01 1:00:00.00000+00:00"
3598+
}
3599+
]';
3600+
3601+
# Regression test for #105942
3602+
# The following should produce 2 lookup joins with a local distribution.
3603+
query T retry
3604+
EXPLAIN SELECT
3605+
xyz.str,
3606+
abc.id,
3607+
abc.id1,
3608+
abc.id2,
3609+
abc.created_at,
3610+
abc.updated_at
3611+
FROM
3612+
abc JOIN xyz ON
3613+
xyz.abc_id = abc.id
3614+
AND xyz.id2 = abc.id2
3615+
AND xyz.crdb_region = abc.crdb_region
3616+
WHERE
3617+
abc.id1 = '6da4f356-e526-4b78-b9f9-bbb1a7fc12d6'
3618+
AND abc.id2 = '68088706-02c6-47d1-b993-a421cd761f2b'
3619+
AND abc.crdb_region = 'ap-southeast-2'
3620+
AND xyz.crdb_region = 'ap-southeast-2';
3621+
----
3622+
distribution: local
3623+
vectorized: true
3624+
·
3625+
• lookup join
3626+
│ estimated row count: 1
3627+
│ table: abc@abc_pkey
3628+
│ equality: (crdb_region, id) = (crdb_region,id)
3629+
│ equality cols are key
3630+
3631+
└── • lookup join
3632+
│ estimated row count: 0
3633+
│ table: abc@abc_id1_id2_idx
3634+
│ equality: (crdb_region, lookup_join_const_col_@2, id2, abc_id) = (crdb_region,id1,id2,id)
3635+
│ equality cols are key
3636+
│ pred: (id2 = '68088706-02c6-47d1-b993-a421cd761f2b') AND (crdb_region = 'ap-southeast-2')
3637+
3638+
└── • render
3639+
3640+
└── • scan
3641+
estimated row count: 4 (3.7% of the table; stats collected <hidden> ago)
3642+
table: xyz@xyz_id2_str_abc_id_idx
3643+
spans: [/'ap-southeast-2'/'68088706-02c6-47d1-b993-a421cd761f2b' - /'ap-southeast-2'/'68088706-02c6-47d1-b993-a421cd761f2b']
3644+
3645+
# The following should use a string of 4 lookup joins with a cost under 200.
3646+
query T retry
3647+
EXPLAIN(opt,verbose) SELECT
3648+
x.str,
3649+
a.id1,
3650+
a.id2,
3651+
a.created_at,
3652+
a.updated_at,
3653+
b.id1,
3654+
b.id2,
3655+
b.created_at,
3656+
b.updated_at
3657+
FROM
3658+
abc a
3659+
INNER JOIN xyz x ON
3660+
x.abc_id = a.id
3661+
AND x.id2 = a.id2
3662+
AND x.crdb_region = a.crdb_region
3663+
INNER JOIN abc b ON
3664+
x.abc_id = b.id
3665+
AND x.id2 = b.id2
3666+
AND x.crdb_region = b.crdb_region
3667+
WHERE
3668+
a.id1 = '6da4f356-e526-4b78-b9f9-bbb1a7fc12d6'
3669+
AND a.id2 = '68088706-02c6-47d1-b993-a421cd761f2b'
3670+
AND a.crdb_region = 'ap-southeast-2'
3671+
AND b.id1 = '6da4f356-e526-4b78-b9f9-bbb1a7fc12d6'
3672+
AND b.id2 = '68088706-02c6-47d1-b993-a421cd761f2b'
3673+
AND b.crdb_region = 'ap-southeast-2'
3674+
AND x.crdb_region = 'ap-southeast-2';
3675+
----
3676+
project
3677+
├── columns: str:10 id1:2 id2:5 created_at:3 updated_at:4 id1:17 id2:20 created_at:18 updated_at:19
3678+
├── immutable
3679+
├── stats: [rows=1.031997]
3680+
├── cost: 112.377461
3681+
├── fd: ()-->(2,5,17,20), (2)==(17), (17)==(2), (3)==(18), (18)==(3), (4)==(19), (19)==(4)
3682+
├── distribution: ap-southeast-2
3683+
├── prune: (2-5,10,17-20)
3684+
└── inner-join (lookup abc [as=a])
3685+
├── columns: a.id:1 a.id1:2 a.created_at:3 a.updated_at:4 a.id2:5 a.crdb_region:6 str:10 abc_id:11 x.id2:12 x.crdb_region:13 b.id:16 b.id1:17 b.created_at:18 b.updated_at:19 b.id2:20 b.crdb_region:21
3686+
├── key columns: [6 1] = [6 1]
3687+
├── lookup columns are key
3688+
├── immutable
3689+
├── stats: [rows=1.031997, distinct(11)=0.936667, null(11)=0, distinct(12)=0.936667, null(12)=0, distinct(13)=0.936667, null(13)=0, distinct(16)=0.936667, null(16)=0, distinct(20)=0.936667, null(20)=0, distinct(21)=0.936667, null(21)=0]
3690+
├── cost: 112.347141
3691+
├── fd: ()-->(2,5,6,12,13,17,20,21), (1)-->(3,4), (1)==(11,16), (11)==(1,16), (5)==(12,20), (12)==(5,20), (6)==(13,21), (13)==(6,21), (16)-->(18,19), (16)==(1,11), (20)==(5,12), (21)==(6,13), (2)==(17), (17)==(2), (3)==(18), (18)==(3), (4)==(19), (19)==(4)
3692+
├── distribution: ap-southeast-2
3693+
├── lookup table distribution: ap-southeast-2,ca-central-1,us-east-1
3694+
├── inner-join (lookup abc@abc_id1_id2_idx [as=a])
3695+
│ ├── columns: a.id:1 a.id1:2 a.id2:5 a.crdb_region:6 str:10 abc_id:11 x.id2:12 x.crdb_region:13 b.id:16 b.id1:17 b.created_at:18 b.updated_at:19 b.id2:20 b.crdb_region:21
3696+
│ ├── key columns: [13 17 12 11] = [6 2 5 1]
3697+
│ ├── lookup columns are key
3698+
│ ├── immutable
3699+
│ ├── stats: [rows=0.01031997, distinct(1)=0.01032, null(1)=0, distinct(2)=0.01032, null(2)=0, distinct(5)=0.01032, null(5)=0, distinct(6)=0.01032, null(6)=0, distinct(10)=0.0102714, null(10)=0, distinct(11)=0.01032, null(11)=0, distinct(12)=0.01032, null(12)=0, distinct(13)=0.01032, null(13)=0, distinct(16)=0.0102638, null(16)=0, distinct(17)=0.01032, null(17)=0, distinct(18)=0.010244, null(18)=0, distinct(19)=0.010244, null(19)=0, distinct(20)=0.0102638, null(20)=0, distinct(21)=0.0102638, null(21)=0, distinct(2,5,6)=0.01032, null(2,5,6)=0]
3700+
│ ├── cost: 112.088874
3701+
│ ├── fd: ()-->(2,5,6,12,13,17,20,21), (16)-->(18,19), (11)==(1,16), (16)==(1,11), (12)==(5,20), (20)==(5,12), (13)==(6,21), (21)==(6,13), (6)==(13,21), (2)==(17), (17)==(2), (5)==(12,20), (1)==(11,16)
3702+
│ ├── distribution: ap-southeast-2
3703+
│ ├── lookup table distribution: ap-southeast-2,ca-central-1,us-east-1
3704+
│ ├── inner-join (lookup abc [as=b])
3705+
│ │ ├── columns: str:10 abc_id:11 x.id2:12 x.crdb_region:13 b.id:16 b.id1:17 b.created_at:18 b.updated_at:19 b.id2:20 b.crdb_region:21
3706+
│ │ ├── key columns: [21 16] = [21 16]
3707+
│ │ ├── lookup columns are key
3708+
│ │ ├── immutable
3709+
│ │ ├── stats: [rows=1.101776, distinct(10)=1.08174, null(10)=0, distinct(11)=0.936667, null(11)=0, distinct(12)=0.936667, null(12)=0, distinct(13)=0.936667, null(13)=0, distinct(16)=0.936667, null(16)=0, distinct(17)=0.709904, null(17)=0, distinct(18)=0.693547, null(18)=0, distinct(19)=0.693547, null(19)=0, distinct(20)=0.936667, null(20)=0, distinct(21)=0.936667, null(21)=0]
3710+
│ │ ├── cost: 107.514948
3711+
│ │ ├── fd: ()-->(12,13,17,20,21), (16)-->(18,19), (11)==(16), (16)==(11), (12)==(20), (20)==(12), (13)==(21), (21)==(13)
3712+
│ │ ├── distribution: ap-southeast-2
3713+
│ │ ├── lookup table distribution: ap-southeast-2,ca-central-1,us-east-1
3714+
│ │ ├── interesting orderings: (+11 opt(12,13)) (+10,+11 opt(12,13)) (+16 opt(17,20,21))
3715+
│ │ ├── inner-join (lookup abc@abc_id1_id2_idx [as=b])
3716+
│ │ │ ├── columns: str:10 abc_id:11 x.id2:12 x.crdb_region:13 b.id:16 b.id1:17 b.id2:20 b.crdb_region:21
3717+
│ │ │ ├── key columns: [13 28 12 11] = [21 17 20 16]
3718+
│ │ │ ├── lookup columns are key
3719+
│ │ │ ├── immutable
3720+
│ │ │ ├── stats: [rows=0.03434444, distinct(11)=0.0343444, null(11)=0, distinct(12)=0.0343444, null(12)=0, distinct(13)=0.0343444, null(13)=0, distinct(16)=0.0343444, null(16)=0, distinct(17)=0.0343444, null(17)=0, distinct(20)=0.0343444, null(20)=0, distinct(21)=0.0343444, null(21)=0, distinct(28)=0.0343444, null(28)=0, distinct(17,20,21)=0.0343444, null(17,20,21)=0]
3721+
│ │ │ ├── cost: 88.4621065
3722+
│ │ │ ├── fd: ()-->(12,13,17,20,21), (13)==(21), (21)==(13), (12)==(20), (20)==(12), (11)==(16), (16)==(11)
3723+
│ │ │ ├── distribution: ap-southeast-2
3724+
│ │ │ ├── lookup table distribution: ap-southeast-2,ca-central-1,us-east-1
3725+
│ │ │ ├── interesting orderings: (+(11|16) opt(12,13,17,20,21,28)) (+10,+(11|16) opt(12,13,17,20,21,28))
3726+
│ │ │ ├── project
3727+
│ │ │ │ ├── columns: "lookup_join_const_col_@17":28 str:10 abc_id:11 x.id2:12 x.crdb_region:13
3728+
│ │ │ │ ├── immutable
3729+
│ │ │ │ ├── stats: [rows=3.666667, distinct(10)=3.11719, null(10)=0, distinct(11)=3.11719, null(11)=0, distinct(12)=1, null(12)=0, distinct(13)=1, null(13)=0, distinct(28)=1, null(28)=0]
3730+
│ │ │ │ ├── cost: 73.3666668
3731+
│ │ │ │ ├── fd: ()-->(12,13,28)
3732+
│ │ │ │ ├── distribution: ap-southeast-2
3733+
│ │ │ │ ├── interesting orderings: (+11 opt(12,13,28)) (+10,+11 opt(12,13,28))
3734+
│ │ │ │ ├── scan xyz@xyz_id2_str_abc_id_idx [as=x]
3735+
│ │ │ │ │ ├── columns: str:10 abc_id:11 x.id2:12 x.crdb_region:13
3736+
│ │ │ │ │ ├── constraint: /13/12/10/11/9: [/'ap-southeast-2'/'68088706-02c6-47d1-b993-a421cd761f2b' - /'ap-southeast-2'/'68088706-02c6-47d1-b993-a421cd761f2b']
3737+
│ │ │ │ │ ├── immutable
3738+
│ │ │ │ │ ├── stats: [rows=3.666667, distinct(10)=3.11719, null(10)=0, distinct(11)=3.11719, null(11)=0, distinct(12)=1, null(12)=0, distinct(13)=1, null(13)=0, distinct(12,13)=1, null(12,13)=0]
3739+
│ │ │ │ │ │ histogram(13)= 0 3.6667
3740+
│ │ │ │ │ │ <--- 'ap-southeast-2'
3741+
│ │ │ │ │ ├── cost: 73.2733335
3742+
│ │ │ │ │ ├── fd: ()-->(12,13)
3743+
│ │ │ │ │ ├── distribution: ap-southeast-2
3744+
│ │ │ │ │ ├── prune: (10,11)
3745+
│ │ │ │ │ └── interesting orderings: (+11 opt(12,13)) (+10,+11 opt(12,13))
3746+
│ │ │ │ └── projections
3747+
│ │ │ │ └── '6da4f356-e526-4b78-b9f9-bbb1a7fc12d6' [as="lookup_join_const_col_@17":28]
3748+
│ │ │ └── filters
3749+
│ │ │ ├── b.id2:20 = '68088706-02c6-47d1-b993-a421cd761f2b' [outer=(20), constraints=(/20: [/'68088706-02c6-47d1-b993-a421cd761f2b' - /'68088706-02c6-47d1-b993-a421cd761f2b']; tight), fd=()-->(20)]
3750+
│ │ │ └── b.crdb_region:21 = 'ap-southeast-2' [outer=(21), immutable, constraints=(/21: [/'ap-southeast-2' - /'ap-southeast-2']; tight), fd=()-->(21)]
3751+
│ │ └── filters (true)
3752+
│ └── filters
3753+
│ ├── a.id2:5 = '68088706-02c6-47d1-b993-a421cd761f2b' [outer=(5), constraints=(/5: [/'68088706-02c6-47d1-b993-a421cd761f2b' - /'68088706-02c6-47d1-b993-a421cd761f2b']; tight), fd=()-->(5)]
3754+
│ ├── a.crdb_region:6 = 'ap-southeast-2' [outer=(6), immutable, constraints=(/6: [/'ap-southeast-2' - /'ap-southeast-2']; tight), fd=()-->(6)]
3755+
│ └── a.id1:2 = '6da4f356-e526-4b78-b9f9-bbb1a7fc12d6' [outer=(2), constraints=(/2: [/'6da4f356-e526-4b78-b9f9-bbb1a7fc12d6' - /'6da4f356-e526-4b78-b9f9-bbb1a7fc12d6']; tight), fd=()-->(2)]
3756+
└── filters
3757+
├── a.created_at:3 = b.created_at:18 [outer=(3,18), constraints=(/3: (/NULL - ]; /18: (/NULL - ]), fd=(3)==(18), (18)==(3)]
3758+
└── a.updated_at:4 = b.updated_at:19 [outer=(4,19), constraints=(/4: (/NULL - ]; /19: (/NULL - ]), fd=(4)==(19), (19)==(4)]

pkg/sql/faketreeeval/evalctx.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,11 @@ func (*DummyEvalPlanner) ExecutorConfig() interface{} {
327327
return nil
328328
}
329329

330+
// Optimizer is part of the cat.Catalog interface.
331+
func (*DummyEvalPlanner) Optimizer() interface{} {
332+
return nil
333+
}
334+
330335
var _ eval.Planner = &DummyEvalPlanner{}
331336

332337
var errEvalPlanner = pgerror.New(pgcode.ScalarOperationCannotRunWithoutFullSessionContext,

pkg/sql/opt/cat/catalog.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,4 +200,8 @@ type Catalog interface {
200200

201201
// RoleExists returns true if the role exists.
202202
RoleExists(ctx context.Context, role username.SQLUsername) (bool, error)
203+
204+
// Optimizer returns the query Optimizer used to optimize SQL statements
205+
// referencing objects in this catalog, if any.
206+
Optimizer() interface{}
203207
}

0 commit comments

Comments
 (0)