@@ -14,6 +14,7 @@ import (
14
14
"github.com/cockroachdb/cockroach/pkg/sql/sem/volatility"
15
15
"github.com/cockroachdb/cockroach/pkg/sql/sessiondatapb"
16
16
"github.com/cockroachdb/cockroach/pkg/sql/types"
17
+ "github.com/cockroachdb/errors"
17
18
)
18
19
19
20
// GenericRulesEnabled returns true if rules for optimizing generic query plans
@@ -124,3 +125,64 @@ func (c *CustomFuncs) ParameterizedJoinPrivate() *memo.JoinPrivate {
124
125
SkipReorderJoins : true ,
125
126
}
126
127
}
128
+
129
+ // PlaceholderScanSpanAndPrivate returns a span and scan private for a
130
+ // PlaceholderScan expression that is semantically equivalent to the given
131
+ // lookup join with input values. See
132
+ // ConvertParameterizedLookupJoinToPlaceholderScan for more details.
133
+ func (c * CustomFuncs ) PlaceholderScanSpanAndPrivate (
134
+ lookupPrivate * memo.LookupJoinPrivate ,
135
+ values * memo.ValuesExpr ,
136
+ row memo.ScalarListExpr ,
137
+ outputCols opt.ColSet ,
138
+ ) (span memo.ScalarListExpr , scanPrivate * memo.ScanPrivate , ok bool ) {
139
+ // The lookup join must be an inner join.
140
+ if lookupPrivate .JoinType != opt .InnerJoinOp {
141
+ return nil , nil , false
142
+ }
143
+ // The lookup join must only have key columns, no lookup expressions.
144
+ if len (lookupPrivate .KeyCols ) == 0 ||
145
+ lookupPrivate .LookupExpr != nil ||
146
+ lookupPrivate .RemoteLookupExpr != nil {
147
+ return nil , nil , false
148
+ }
149
+ // The lookup join must not be part of a paired join.
150
+ if lookupPrivate .IsFirstJoinInPairedJoiner || lookupPrivate .IsSecondJoinInPairedJoiner {
151
+ return nil , nil , false
152
+ }
153
+ // The index must be able to produce all the output columns.
154
+ md := c .e .f .Metadata ()
155
+ indexCols := md .TableMeta (lookupPrivate .Table ).IndexColumns (lookupPrivate .Index )
156
+ if ! outputCols .SubsetOf (indexCols ) {
157
+ return nil , nil , false
158
+ }
159
+
160
+ // Map columns in the input Values expression to the key columns.
161
+ span = make (memo.ScalarListExpr , len (lookupPrivate .KeyCols ))
162
+ for i , keyCol := range lookupPrivate .KeyCols {
163
+ for j , valCol := range values .Cols {
164
+ if keyCol == valCol {
165
+ if ! verifyType (md , keyCol , row [j ].DataType ()) {
166
+ // TODO(mgartner): This was added to copy the same check
167
+ // made while planning the the placeholder fast-path, but it
168
+ // may not be necessary here because the lookup join may
169
+ // have already checked this.
170
+ return nil , nil , false
171
+ }
172
+ span [i ] = row [j ]
173
+ break
174
+ }
175
+ }
176
+ if span [i ] == nil {
177
+ panic (errors .AssertionFailedf ("no value found for key column %d" , keyCol ))
178
+ }
179
+ }
180
+
181
+ scanPrivate = & memo.ScanPrivate {
182
+ Table : lookupPrivate .Table ,
183
+ Index : lookupPrivate .Index ,
184
+ Cols : outputCols .Copy (),
185
+ Locking : lookupPrivate .Locking ,
186
+ }
187
+ return span , scanPrivate , true
188
+ }
0 commit comments