@@ -20,7 +20,9 @@ import (
20
20
"github.com/pingcap/tidb/expression"
21
21
"github.com/pingcap/tidb/expression/aggregation"
22
22
"github.com/pingcap/tidb/kv"
23
+ "github.com/pingcap/tidb/parser/ast"
23
24
"github.com/pingcap/tidb/parser/model"
25
+ "github.com/pingcap/tidb/parser/mysql"
24
26
"github.com/pingcap/tidb/sessionctx"
25
27
"github.com/pingcap/tidb/table"
26
28
"github.com/pingcap/tidb/table/tables"
@@ -29,12 +31,14 @@ import (
29
31
"github.com/pingcap/tidb/types"
30
32
"github.com/pingcap/tidb/util"
31
33
"github.com/pingcap/tidb/util/codec"
34
+ "github.com/pingcap/tidb/util/logutil"
32
35
"github.com/pingcap/tidb/util/ranger"
33
36
"github.com/pingcap/tipb/go-tipb"
37
+ "go.uber.org/zap"
34
38
)
35
39
36
40
// ToSubstraitPB implements PhysicalPlan ToSubstraitPB interface.
37
- func (p * basePhysicalPlan ) ToSubstraitPB (ctx sessionctx.Context ) (_ * substraitgo.Rel , err error ) {
41
+ func (p * basePhysicalPlan ) ToSubstraitPB (ctx sessionctx.Context , ssHandler * SubstraitHandler ) (_ * substraitgo.Rel , err error ) {
38
42
return nil , errors .Errorf ("plan %s fails converts to PB" , p .basePlan .ExplainID ())
39
43
}
40
44
@@ -125,11 +129,239 @@ func (p *PhysicalSelection) ToPB(ctx sessionctx.Context, storeType kv.StoreType)
125
129
}
126
130
return & tipb.Executor {Tp : tipb .ExecType_TypeSelection , Selection : selExec , ExecutorId : & executorID }, nil
127
131
}
132
+ func getSubStraitType (tp byte ) string {
133
+ if tp == mysql .TypeLong {
134
+ return "i32"
135
+ }
136
+ if tp == mysql .TypeLonglong {
137
+ return "i64"
138
+ }
139
+ if tp == mysql .TypeDouble {
140
+ return "fp64"
141
+ }
142
+ panic ("not supproted type" )
143
+ }
144
+
145
+ func getSubstraitPBFunctionArguments (offsets []int32 ) (funcArgs []* substraitgo.FunctionArgument ) {
146
+ getFunctionArgument := func (offset int32 ) * substraitgo.FunctionArgument {
147
+ return & substraitgo.FunctionArgument {
148
+ ArgType : & substraitgo.FunctionArgument_Value {
149
+ Value : & substraitgo.Expression {
150
+ RexType : & substraitgo.Expression_Selection {
151
+ Selection : & substraitgo.Expression_FieldReference {
152
+ ReferenceType : & substraitgo.Expression_FieldReference_DirectReference {
153
+ DirectReference : & substraitgo.Expression_ReferenceSegment {
154
+ ReferenceType : & substraitgo.Expression_ReferenceSegment_StructField_ {
155
+ StructField : & substraitgo.Expression_ReferenceSegment_StructField {
156
+ // col offset from child chunk
157
+ Field : offset ,
158
+ },
159
+ },
160
+ },
161
+ },
162
+ },
163
+ },
164
+ },
165
+ },
166
+ }
167
+ }
168
+ for _ , off := range offsets {
169
+ funcArgs = append (funcArgs , getFunctionArgument (off ))
170
+ }
171
+ return
172
+ }
173
+
174
+ type SubstraitHandler struct {
175
+ autoIncId uint32
176
+ SigMap map [string ]uint32
177
+ }
178
+
179
+ func NewSubstraitHandler () * SubstraitHandler {
180
+ return & SubstraitHandler {
181
+ autoIncId : uint32 (1 ),
182
+ SigMap : map [string ]uint32 {},
183
+ }
184
+ }
185
+
186
+ func (h * SubstraitHandler ) insertSig (sigName string ) uint32 {
187
+ if _ , ok := h .SigMap [sigName ]; ! ok {
188
+ h .SigMap [sigName ] = h .autoIncId
189
+ h .autoIncId ++
190
+ }
191
+ return h .getSigID (sigName )
192
+ }
193
+
194
+ func (h * SubstraitHandler ) getSigID (sigName string ) uint32 {
195
+ return h .SigMap [sigName ]
196
+ }
128
197
129
- //func (p *PhysicalProjection) ToSubstraitPB() (*substraitgo.Rel, error){
130
- // proj := &substraitgo.ProjectRel{}
131
- // proj.Input
132
- //}
198
+ func scalarFuncFieldTypeToSubstraitOutputType (sf * expression.ScalarFunction ) (outputType * substraitgo.Type ) {
199
+ switch sf .GetType ().EvalType () {
200
+ case types .ETInt :
201
+ outputType = & substraitgo.Type {
202
+ Kind : & substraitgo.Type_I64_ {
203
+ I64 : & substraitgo.Type_I64 {},
204
+ },
205
+ }
206
+ case types .ETReal :
207
+ outputType = & substraitgo.Type {
208
+ Kind : & substraitgo.Type_Fp64 {
209
+ Fp64 : & substraitgo.Type_FP64 {},
210
+ },
211
+ }
212
+ }
213
+ switch sf .FuncName .L {
214
+ case "lt" , "lte" , "gt" , "gte" , "and" , "or" , "eq" , "not" :
215
+ outputType = & substraitgo.Type {
216
+ Kind : & substraitgo.Type_Bool {
217
+ Bool : & substraitgo.Type_Boolean {
218
+ Nullability : substraitgo .Type_NULLABILITY_NULLABLE ,
219
+ },
220
+ },
221
+ }
222
+ }
223
+ return
224
+ }
225
+
226
+ func (h * SubstraitHandler ) scalarFuncToSubstraitgoExpr (sf * expression.ScalarFunction ) (* substraitgo.Expression , error ) {
227
+ funcSig := tiDBFuncNameToVeloxFuncName [sf .FuncName .L ]
228
+ var offsets []int32
229
+ for _ , arg := range sf .GetArgs () {
230
+ col , ok := arg .(* expression.Column )
231
+ if ! ok {
232
+ return nil , errors .Errorf ("fail to convert proj to substrait, only support arg of column type" )
233
+ }
234
+ offsets = append (offsets , int32 (col .Index ))
235
+ }
236
+ funcSig = funcSig + ":" + getSubStraitType (sf .GetArgs ()[0 ].GetType ().GetType ()) + "_" + getSubStraitType (sf .GetArgs ()[1 ].GetType ().GetType ())
237
+
238
+ sExpr := & substraitgo.Expression {
239
+ RexType : & substraitgo.Expression_ScalarFunction_ {
240
+ ScalarFunction : & substraitgo.Expression_ScalarFunction {
241
+ // function anchor
242
+ FunctionReference : h .insertSig (funcSig ),
243
+ // function args
244
+ Arguments : getSubstraitPBFunctionArguments (offsets ),
245
+ OutputType : scalarFuncFieldTypeToSubstraitOutputType (sf ),
246
+ },
247
+ },
248
+ }
249
+ return sExpr , nil
250
+ }
251
+
252
+ func (h * SubstraitHandler ) columnToSubstraitgoExpr (col * expression.Column ) * substraitgo.Expression {
253
+ sExpr := & substraitgo.Expression {
254
+ RexType : & substraitgo.Expression_Selection {
255
+ Selection : & substraitgo.Expression_FieldReference {
256
+ ReferenceType : & substraitgo.Expression_FieldReference_DirectReference {
257
+ DirectReference : & substraitgo.Expression_ReferenceSegment {
258
+ ReferenceType : & substraitgo.Expression_ReferenceSegment_StructField_ {
259
+ StructField : & substraitgo.Expression_ReferenceSegment_StructField {
260
+ Field : int32 (col .Index ),
261
+ },
262
+ },
263
+ },
264
+ },
265
+ },
266
+ },
267
+ }
268
+ return sExpr
269
+ }
270
+
271
+ func tidbConstToVeloxExpressionLiteral (cont * expression.Constant ) (el * substraitgo.Expression_Literal ) {
272
+ switch cont .GetType ().GetType () {
273
+ case mysql .TypeLonglong :
274
+ el = & substraitgo.Expression_Literal {
275
+ LiteralType : & substraitgo.Expression_Literal_I64 {
276
+ I64 : cont .Value .GetInt64 (),
277
+ },
278
+ }
279
+ case mysql .TypeFloat :
280
+ el = & substraitgo.Expression_Literal {
281
+ LiteralType : & substraitgo.Expression_Literal_Fp32 {
282
+ Fp32 : cont .Value .GetFloat32 (),
283
+ },
284
+ }
285
+ case mysql .TypeDouble :
286
+ el = & substraitgo.Expression_Literal {
287
+ LiteralType : & substraitgo.Expression_Literal_Fp64 {
288
+ Fp64 : cont .Value .GetFloat64 (),
289
+ },
290
+ }
291
+ }
292
+ return
293
+ }
294
+
295
+ func (h * SubstraitHandler ) constToSubstraitgoExpr (cont * expression.Constant ) * substraitgo.Expression {
296
+ sExpr := & substraitgo.Expression {
297
+ RexType : & substraitgo.Expression_Literal_ {
298
+ Literal : tidbConstToVeloxExpressionLiteral (cont ),
299
+ },
300
+ }
301
+ return sExpr
302
+ }
303
+
304
+ func (h * SubstraitHandler ) buildSubstraitProjExpression (tidbExpr []expression.Expression ) (substraitgoExprs []* substraitgo.Expression , err error ) {
305
+ for _ , expr := range tidbExpr {
306
+ var sExpr * substraitgo.Expression
307
+ var err error
308
+ switch x := expr .(type ) {
309
+ case * expression.Column :
310
+ sExpr = h .columnToSubstraitgoExpr (x )
311
+ case * expression.Constant :
312
+ sExpr = h .constToSubstraitgoExpr (x )
313
+ case * expression.ScalarFunction :
314
+ sExpr , err = h .scalarFuncToSubstraitgoExpr (x )
315
+ if err != nil {
316
+ return nil , err
317
+ }
318
+ }
319
+ substraitgoExprs = append (substraitgoExprs , sExpr )
320
+ }
321
+ return substraitgoExprs , nil
322
+ }
323
+
324
+ var tiDBFuncNameToVeloxFuncName = map [string ]string {
325
+ ast .LE : "lte" ,
326
+ ast .LT : "lt" ,
327
+ ast .GE : "gte" ,
328
+ ast .GT : "gt" ,
329
+ ast .Plus : "plus" ,
330
+ ast .Minus : "minus" ,
331
+ ast .Mul : "multiply" ,
332
+ ast .Mod : "mod" ,
333
+ ast .EQ : "eq" ,
334
+ ast .UnaryNot : "not" ,
335
+ ast .And : "and" ,
336
+ ast .LogicOr : "or" ,
337
+ }
338
+
339
+ // ToSubstraitPB implements the substraitgo interface.
340
+ func (p * PhysicalProjection ) ToSubstraitPB (ctx sessionctx.Context , ssHandler * SubstraitHandler ) (* substraitgo.Rel , error ) {
341
+ childRel , err := p .children [0 ].ToSubstraitPB (ctx , ssHandler )
342
+ if err != nil {
343
+ return nil , err
344
+ }
345
+ sspb := & substraitgo.ProjectRel {
346
+ Common : & substraitgo.RelCommon {
347
+ EmitKind : & substraitgo.RelCommon_Direct_ {
348
+ Direct : & substraitgo.RelCommon_Direct {},
349
+ },
350
+ },
351
+ Input : childRel ,
352
+ }
353
+ sspbExpression , err := ssHandler .buildSubstraitProjExpression (p .Exprs )
354
+ if err != nil {
355
+ logutil .BgLogger ().Error ("error" , zap .Error (err ))
356
+ return nil , err
357
+ }
358
+ sspb .Expressions = sspbExpression
359
+ logutil .BgLogger ().Warn ("expression" , zap .Int ("len" , len (sspb .Expressions )))
360
+ // extract function map (assume there are all simple functions)
361
+ return & substraitgo.Rel {
362
+ RelType : & substraitgo.Rel_Project {Project : sspb },
363
+ }, nil
364
+ }
133
365
134
366
// ToPB implements PhysicalPlan ToPB interface.
135
367
func (p * PhysicalProjection ) ToPB (ctx sessionctx.Context , storeType kv.StoreType ) (* tipb.Executor , error ) {
@@ -195,7 +427,7 @@ func (p *PhysicalLimit) ToPB(ctx sessionctx.Context, storeType kv.StoreType) (*t
195
427
return & tipb.Executor {Tp : tipb .ExecType_TypeLimit , Limit : limitExec , ExecutorId : & executorID }, nil
196
428
}
197
429
198
- func (p * PhysicalTableReader ) ToSubstraitPB (ctx sessionctx.Context ) (rel * substraitgo.Rel , err error ) {
430
+ func (p * PhysicalTableReader ) ToSubstraitPB (ctx sessionctx.Context , ssHandler * SubstraitHandler ) (rel * substraitgo.Rel , err error ) {
199
431
tableScan , ok := p .TablePlans [0 ].(* PhysicalTableScan )
200
432
if ! ok {
201
433
return nil , nil
0 commit comments