// The return type of a CASE expression is the compatible aggregated type of all return values, // but also depends on the context in which it is used. // If used in a string context, the result is returned as a string. // If used in a numeric context, the result is returned as a decimal, real, or integer value. func (v *typeInferrer) handleCaseExpr(x *ast.CaseExpr) { var currType *types.FieldType for _, w := range x.WhenClauses { t := w.Result.GetType() if currType == nil { currType = t continue } mtp := types.MergeFieldType(currType.Tp, t.Tp) if mtp == t.Tp && mtp != currType.Tp { currType.Charset = t.Charset currType.Collate = t.Collate } currType.Tp = mtp } if x.ElseClause != nil { t := x.ElseClause.GetType() if currType == nil { currType = t } else { mtp := types.MergeFieldType(currType.Tp, t.Tp) if mtp == t.Tp && mtp != currType.Tp { currType.Charset = t.Charset currType.Collate = t.Collate } currType.Tp = mtp } } x.SetType(currType) // TODO: We need a better way to set charset/collation x.Type.Charset, x.Type.Collate = types.DefaultCharsetForType(x.Type.Tp) }
func (b *executorBuilder) buildSemiJoin(v *plan.PhysicalHashSemiJoin) Executor { var leftHashKey, rightHashKey []*expression.Column var targetTypes []*types.FieldType for _, eqCond := range v.EqualConditions { ln, _ := eqCond.Args[0].(*expression.Column) rn, _ := eqCond.Args[1].(*expression.Column) leftHashKey = append(leftHashKey, ln) rightHashKey = append(rightHashKey, rn) targetTypes = append(targetTypes, types.NewFieldType(types.MergeFieldType(ln.GetType().Tp, rn.GetType().Tp))) } e := &HashSemiJoinExec{ schema: v.GetSchema(), otherFilter: expression.ComposeCNFCondition(v.OtherConditions), bigFilter: expression.ComposeCNFCondition(v.LeftConditions), smallFilter: expression.ComposeCNFCondition(v.RightConditions), bigExec: b.build(v.GetChildByIndex(0)), smallExec: b.build(v.GetChildByIndex(1)), prepared: false, ctx: b.ctx, bigHashKey: leftHashKey, smallHashKey: rightHashKey, withAux: v.WithAux, anti: v.Anti, targetTypes: targetTypes, } return e }
func (b *executorBuilder) buildJoin(v *plan.PhysicalHashJoin) Executor { var leftHashKey, rightHashKey []*expression.Column var targetTypes []*types.FieldType for _, eqCond := range v.EqualConditions { ln, _ := eqCond.Args[0].(*expression.Column) rn, _ := eqCond.Args[1].(*expression.Column) leftHashKey = append(leftHashKey, ln) rightHashKey = append(rightHashKey, rn) targetTypes = append(targetTypes, types.NewFieldType(types.MergeFieldType(ln.GetType().Tp, rn.GetType().Tp))) } e := &HashJoinExec{ schema: v.GetSchema(), otherFilter: expression.ComposeCNFCondition(v.OtherConditions), prepared: false, ctx: b.ctx, targetTypes: targetTypes, concurrency: v.Concurrency, defaultValues: v.DefaultValues, } if v.SmallTable == 1 { e.smallFilter = expression.ComposeCNFCondition(v.RightConditions) e.bigFilter = expression.ComposeCNFCondition(v.LeftConditions) e.smallHashKey = rightHashKey e.bigHashKey = leftHashKey e.leftSmall = false } else { e.leftSmall = true e.smallFilter = expression.ComposeCNFCondition(v.LeftConditions) e.bigFilter = expression.ComposeCNFCondition(v.RightConditions) e.smallHashKey = leftHashKey e.bigHashKey = rightHashKey } if v.JoinType == plan.LeftOuterJoin || v.JoinType == plan.RightOuterJoin { e.outer = true } if e.leftSmall { e.smallExec = b.build(v.GetChildByIndex(0)) e.bigExec = b.build(v.GetChildByIndex(1)) } else { e.smallExec = b.build(v.GetChildByIndex(1)) e.bigExec = b.build(v.GetChildByIndex(0)) } for i := 0; i < e.concurrency; i++ { ctx := &hashJoinCtx{} if e.bigFilter != nil { ctx.bigFilter = e.bigFilter.Clone() } if e.otherFilter != nil { ctx.otherFilter = e.otherFilter.Clone() } ctx.datumBuffer = make([]types.Datum, len(e.bigHashKey)) ctx.hashKeyBuffer = make([]byte, 0, 10000) e.hashJoinContexts = append(e.hashJoinContexts, ctx) } return e }
//TODO: select join algorithm during cbo phase. func (b *executorBuilder) buildJoin(v *plan.PhysicalHashJoin) Executor { var leftHashKey, rightHashKey []*expression.Column var targetTypes []*types.FieldType for _, eqCond := range v.EqualConditions { ln, _ := eqCond.Args[0].(*expression.Column) rn, _ := eqCond.Args[1].(*expression.Column) leftHashKey = append(leftHashKey, ln) rightHashKey = append(rightHashKey, rn) targetTypes = append(targetTypes, types.NewFieldType(types.MergeFieldType(ln.GetType().Tp, rn.GetType().Tp))) } e := &HashJoinExec{ schema: v.GetSchema(), otherFilter: expression.ComposeCNFCondition(v.OtherConditions), prepared: false, ctx: b.ctx, targetTypes: targetTypes, } if v.SmallTable == 1 { e.smallFilter = expression.ComposeCNFCondition(v.RightConditions) e.bigFilter = expression.ComposeCNFCondition(v.LeftConditions) e.smallHashKey = rightHashKey e.bigHashKey = leftHashKey e.leftSmall = false } else { e.leftSmall = true e.smallFilter = expression.ComposeCNFCondition(v.LeftConditions) e.bigFilter = expression.ComposeCNFCondition(v.RightConditions) e.smallHashKey = leftHashKey e.bigHashKey = rightHashKey } if v.JoinType == plan.LeftOuterJoin || v.JoinType == plan.RightOuterJoin { e.outer = true } if e.leftSmall { e.smallExec = b.build(v.GetChildByIndex(0)) e.bigExec = b.build(v.GetChildByIndex(1)) } else { e.smallExec = b.build(v.GetChildByIndex(1)) e.bigExec = b.build(v.GetChildByIndex(0)) } return e }