// GetColDefaultValue gets default value of the column. func GetColDefaultValue(ctx context.Context, col *model.ColumnInfo) (types.Datum, bool, error) { // Check no default value flag. if mysql.HasNoDefaultValueFlag(col.Flag) && col.Tp != mysql.TypeEnum { return types.Datum{}, false, errors.Errorf("Field '%s' doesn't have a default value", col.Name) } // Check and get timestamp/datetime default value. if col.Tp == mysql.TypeTimestamp || col.Tp == mysql.TypeDatetime { if col.DefaultValue == nil { return types.Datum{}, true, nil } value, err := evaluator.GetTimeValue(ctx, col.DefaultValue, col.Tp, col.Decimal) if err != nil { return types.Datum{}, true, errors.Errorf("Field '%s' get default value fail - %s", col.Name, errors.Trace(err)) } return types.NewDatum(value), true, nil } else if col.Tp == mysql.TypeEnum { // For enum type, if no default value and not null is set, // the default value is the first element of the enum list if col.DefaultValue == nil && mysql.HasNotNullFlag(col.Flag) { return types.NewDatum(col.FieldType.Elems[0]), true, nil } } return types.NewDatum(col.DefaultValue), true, nil }
func flatten(data types.Datum) (types.Datum, error) { switch data.Kind() { case types.KindMysqlTime: // for mysql datetime, timestamp and date type b, err := data.GetMysqlTime().Marshal() if err != nil { return types.NewDatum(nil), errors.Trace(err) } return types.NewDatum(b), nil case types.KindMysqlDuration: // for mysql time type data.SetInt64(int64(data.GetMysqlDuration().Duration)) return data, nil case types.KindMysqlDecimal: data.SetString(data.GetMysqlDecimal().String()) return data, nil case types.KindMysqlEnum: data.SetUint64(data.GetMysqlEnum().Value) return data, nil case types.KindMysqlSet: data.SetUint64(data.GetMysqlSet().Value) return data, nil case types.KindMysqlBit: data.SetUint64(data.GetMysqlBit().Value) return data, nil case types.KindMysqlHex: data.SetInt64(data.GetMysqlHex().Value) return data, nil default: return data, nil } }
func getRowCountByTableRange(sc *variable.StatementContext, statsTbl *statistics.Table, ranges []TableRange, offset int) (uint64, error) { var rowCount uint64 for _, rg := range ranges { var cnt int64 var err error if rg.LowVal == math.MinInt64 && rg.HighVal == math.MaxInt64 { cnt = statsTbl.Count } else if rg.LowVal == math.MinInt64 { cnt, err = statsTbl.Columns[offset].LessRowCount(sc, types.NewDatum(rg.HighVal)) } else if rg.HighVal == math.MaxInt64 { cnt, err = statsTbl.Columns[offset].GreaterRowCount(sc, types.NewDatum(rg.LowVal)) } else { if rg.LowVal == rg.HighVal { cnt, err = statsTbl.Columns[offset].EqualRowCount(sc, types.NewDatum(rg.LowVal)) } else { cnt, err = statsTbl.Columns[offset].BetweenRowCount(sc, types.NewDatum(rg.LowVal), types.NewDatum(rg.HighVal)) } } if err != nil { return 0, errors.Trace(err) } rowCount += uint64(cnt) } if rowCount > uint64(statsTbl.Count) { rowCount = uint64(statsTbl.Count) } return rowCount, nil }
func (e *Evaluator) evalIn(expr *tipb.Expr) (types.Datum, error) { if len(expr.Children) != 2 { return types.Datum{}, ErrInvalid.Gen("IN need 2 operand, got %d", len(expr.Children)) } target, err := e.Eval(expr.Children[0]) if err != nil { return types.Datum{}, errors.Trace(err) } if target.IsNull() { return types.Datum{}, nil } valueListExpr := expr.Children[1] if valueListExpr.GetTp() != tipb.ExprType_ValueList { return types.Datum{}, ErrInvalid.Gen("the second children should be value list type") } decoded, err := e.decodeValueList(valueListExpr) if err != nil { return types.Datum{}, errors.Trace(err) } in, err := checkIn(target, decoded.values) if err != nil { return types.Datum{}, errors.Trace(err) } if in { return types.NewDatum(1), nil } if decoded.hasNull { return types.Datum{}, nil } return types.NewDatum(0), nil }
func (e *UpdateExec) fetchRows() error { for { row, err := e.SelectExec.Next() if err != nil { return errors.Trace(err) } if row == nil { return nil } data := make([]types.Datum, len(e.SelectExec.Fields())) newData := make([]types.Datum, len(e.SelectExec.Fields())) for i, f := range e.SelectExec.Fields() { data[i] = types.NewDatum(f.Expr.GetValue()) newData[i] = data[i] if e.OrderedList[i] != nil { val, err := evaluator.Eval(e.ctx, e.OrderedList[i].Expr) if err != nil { return errors.Trace(err) } newData[i] = types.NewDatum(val) } } row.Data = data e.rows = append(e.rows, row) e.newRowsData = append(e.newRowsData, newData) } }
func (s *testEvaluatorSuite) TestCast(c *C) { defer testleak.AfterTest(c)() f := types.NewFieldType(mysql.TypeLonglong) expr := &ast.FuncCastExpr{ Expr: ast.NewValueExpr(1), Tp: f, } ast.SetFlag(expr) v, err := Eval(s.ctx, expr) c.Assert(err, IsNil) c.Assert(v, testutil.DatumEquals, types.NewDatum(int64(1))) f.Flag |= mysql.UnsignedFlag v, err = Eval(s.ctx, expr) c.Assert(err, IsNil) c.Assert(v, testutil.DatumEquals, types.NewDatum(uint64(1))) f.Tp = mysql.TypeString f.Charset = charset.CharsetBin v, err = Eval(s.ctx, expr) c.Assert(err, IsNil) c.Assert(v, testutil.DatumEquals, types.NewDatum([]byte("1"))) f.Tp = mysql.TypeString f.Charset = "utf8" v, err = Eval(s.ctx, expr) c.Assert(err, IsNil) c.Assert(v, testutil.DatumEquals, types.NewDatum("1")) expr.Expr = ast.NewValueExpr(nil) v, err = Eval(s.ctx, expr) c.Assert(err, IsNil) c.Assert(v.Kind(), Equals, types.KindNull) }
// getHashKey encodes a requiredProperty to a unique hash code. func (p *requiredProperty) getHashKey() ([]byte, error) { datums := make([]types.Datum, 0, len(p.props)*3+1) datums = append(datums, types.NewDatum(p.sortKeyLen)) for _, c := range p.props { datums = append(datums, types.NewDatum(c.desc), types.NewDatum(c.col.FromID), types.NewDatum(c.col.Index)) } bytes, err := codec.EncodeValue(nil, datums...) return bytes, errors.Trace(err) }
// Next implements the Executor Next interface. func (e *ApplyExec) Next() (*Row, error) { srcRow, err := e.Src.Next() if err != nil { return nil, errors.Trace(err) } if srcRow == nil { return nil, nil } for { for _, col := range e.outerSchema { idx := col.Index *col.Data = srcRow.Data[idx] } innerRow, err := e.innerExec.Next() if err != nil { return nil, errors.Trace(err) } trimLen := len(srcRow.Data) if innerRow != nil { srcRow.Data = append(srcRow.Data, innerRow.Data...) } if e.checker == nil { e.innerExec.Close() return srcRow, nil } if innerRow == nil { // When inner exec finishes, we need to append a result column to true, false or NULL. var result types.Datum if e.checker.all { result = types.NewDatum(true) } else { // If 'any' meets a null value, the result will be null. if e.checker.dataHasNull { result = types.NewDatum(nil) } else { result = types.NewDatum(false) } } srcRow.Data = append(srcRow.Data, result) e.checker.reset() e.innerExec.Close() return srcRow, nil } finished, data, err := e.checker.check(srcRow.Data) if err != nil { return nil, errors.Trace(err) } srcRow.Data = srcRow.Data[:trimLen] if finished { e.checker.reset() e.innerExec.Close() srcRow.Data = append(srcRow.Data, data) return srcRow, nil } } }
func (s *testEvaluatorSuite) TestTrim(c *C) { defer testleak.AfterTest(c)() tbl := []struct { str interface{} remstr interface{} dir ast.TrimDirectionType result interface{} }{ {" bar ", nil, ast.TrimBothDefault, "bar"}, {"xxxbarxxx", "x", ast.TrimLeading, "barxxx"}, {"xxxbarxxx", "x", ast.TrimBoth, "bar"}, {"barxxyz", "xyz", ast.TrimTrailing, "barx"}, {nil, "xyz", ast.TrimBoth, nil}, {1, 2, ast.TrimBoth, "1"}, {" \t\rbar\n ", nil, ast.TrimBothDefault, "bar"}, } ctx := mock.NewContext() for _, v := range tbl { f := &ast.FuncCallExpr{ FnName: model.NewCIStr("TRIM"), Args: []ast.ExprNode{ ast.NewValueExpr(v.str), ast.NewValueExpr(v.remstr), ast.NewValueExpr(v.dir), }, } r, err := Eval(ctx, f) c.Assert(err, IsNil) c.Assert(r, testutil.DatumEquals, types.NewDatum(v.result)) } for _, v := range []struct { str, result interface{} fn string }{ {" ", "", "LTRIM"}, {" ", "", "RTRIM"}, {"foo0", "foo0", "LTRIM"}, {"bar0", "bar0", "RTRIM"}, {" foo1", "foo1", "LTRIM"}, {"bar1 ", "bar1", "RTRIM"}, {spaceChars + "foo2 ", "foo2 ", "LTRIM"}, {" bar2" + spaceChars, " bar2", "RTRIM"}, {nil, nil, "LTRIM"}, {nil, nil, "RTRIM"}, } { f := &ast.FuncCallExpr{ FnName: model.NewCIStr(v.fn), Args: []ast.ExprNode{ast.NewValueExpr(v.str)}, } r, err := Eval(ctx, f) c.Assert(err, IsNil) c.Assert(r, testutil.DatumEquals, types.NewDatum(v.result)) } }
func (s *testEvaluatorSuite) TestCoalesce(c *C) { args := types.MakeDatums(1, nil) v, err := builtinCoalesce(args, nil) c.Assert(err, IsNil) c.Assert(v, DatumEquals, types.NewDatum(1)) args = types.MakeDatums(nil, nil) v, err = builtinCoalesce(args, nil) c.Assert(err, IsNil) c.Assert(v, DatumEquals, types.NewDatum(nil)) }
func (s *testEvaluatorSuite) TestCoalesce(c *C) { defer testleak.AfterTest(c)() args := types.MakeDatums(1, nil) v, err := builtinCoalesce(args, nil) c.Assert(err, IsNil) c.Assert(v, testutil.DatumEquals, types.NewDatum(1)) args = types.MakeDatums(nil, nil) v, err = builtinCoalesce(args, nil) c.Assert(err, IsNil) c.Assert(v, testutil.DatumEquals, types.NewDatum(nil)) }
func inExpr(target interface{}, list ...interface{}) *tipb.Expr { targetDatum := types.NewDatum(target) var listDatums []types.Datum for _, v := range list { listDatums = append(listDatums, types.NewDatum(v)) } types.SortDatums(listDatums) targetExpr := datumExpr(targetDatum) val, _ := codec.EncodeValue(nil, listDatums...) listExpr := &tipb.Expr{Tp: tipb.ExprType_ValueList, Val: val} return &tipb.Expr{Tp: tipb.ExprType_In, Children: []*tipb.Expr{targetExpr, listExpr}} }
// Next implements the Executor Next interface. func (e *HashSemiJoinExec) Next() (*Row, error) { if !e.prepared { if err := e.prepare(); err != nil { return nil, errors.Trace(err) } } for { bigRow, err := e.bigExec.Next() if err != nil { return nil, errors.Trace(err) } if bigRow == nil { e.bigExec.Close() return nil, nil } matched := true if e.bigFilter != nil { matched, err = expression.EvalBool(e.bigFilter, bigRow.Data, e.ctx) if err != nil { return nil, errors.Trace(err) } } isNull := false if matched { matched, isNull, err = e.rowIsMatched(bigRow) if err != nil { return nil, errors.Trace(err) } } if !matched && e.smallTableHasNull { isNull = true } if e.anti && !isNull { matched = !matched } // For the auxMode subquery, we return the row with a Datum indicating if it's a match, // For the non-auxMode subquery, we return the matching row only. if e.auxMode { if isNull { bigRow.Data = append(bigRow.Data, types.NewDatum(nil)) } else { bigRow.Data = append(bigRow.Data, types.NewDatum(matched)) } return bigRow, nil } if matched { return bigRow, nil } } }
// Next implements Executor Next interface. func (e *ApplyExec) Next() (*Row, error) { srcRow, err := e.Src.Next() if err != nil { return nil, errors.Trace(err) } if srcRow == nil { return nil, nil } for { for _, col := range e.outerSchema { idx := col.Index col.SetValue(&srcRow.Data[idx]) } innerRow, err := e.innerExec.Next() if err != nil { return nil, errors.Trace(err) } trimLen := len(srcRow.Data) if innerRow != nil { srcRow.Data = append(srcRow.Data, innerRow.Data...) } if e.checker == nil { e.innerExec.Close() return srcRow, nil } if innerRow == nil { var d types.Datum // If we can't determine the result until the last row comes, the all must be true and any must not be true. // If the any have met a null, the result will be null. if e.checker.dataHasNull && !e.checker.all { d = types.NewDatum(nil) } else { d = types.NewDatum(e.checker.all) } srcRow.Data = append(srcRow.Data, d) e.checker.dataHasNull = false e.innerExec.Close() return srcRow, nil } finished, data, err := e.checker.Check(srcRow.Data) if err != nil { return nil, errors.Trace(err) } srcRow.Data = srcRow.Data[:trimLen] if finished { e.checker.dataHasNull = false e.innerExec.Close() srcRow.Data = append(srcRow.Data, data) return srcRow, nil } } }
// Next implements Executor Next interface. func (e *HashSemiJoinExec) Next() (*Row, error) { if !e.prepared { if err := e.prepare(); err != nil { return nil, errors.Trace(err) } } for { bigRow, err := e.bigExec.Next() if err != nil { return nil, errors.Trace(err) } if bigRow == nil { e.bigExec.Close() return nil, nil } matched := true if e.bigFilter != nil { matched, err = expression.EvalBool(e.bigFilter, bigRow.Data, e.ctx) if err != nil { return nil, errors.Trace(err) } } isNull := false if matched { matched, isNull, err = e.rowIsMatched(bigRow) if err != nil { return nil, errors.Trace(err) } } if !matched && e.smallTableHasNull { isNull = true } if e.anti && !isNull { matched = !matched } if e.withAux { if isNull { bigRow.Data = append(bigRow.Data, types.NewDatum(nil)) } else { bigRow.Data = append(bigRow.Data, types.NewDatum(matched)) } return bigRow, nil } else if matched { return bigRow, nil } } }
func (r *rangeBuilder) buildTableRanges(rangePoints []rangePoint) []TableRange { tableRanges := make([]TableRange, 0, len(rangePoints)/2) for i := 0; i < len(rangePoints); i += 2 { startPoint := rangePoints[i] if startPoint.value.IsNull() || startPoint.value.Kind() == types.KindMinNotNull { startPoint.value.SetInt64(math.MinInt64) } startInt, err := startPoint.value.ToInt64() if err != nil { r.err = errors.Trace(err) return tableRanges } startDatum := types.NewDatum(startInt) cmp, err := startDatum.CompareDatum(startPoint.value) if err != nil { r.err = errors.Trace(err) return tableRanges } if cmp < 0 || (cmp == 0 && startPoint.excl) { startInt++ } endPoint := rangePoints[i+1] if endPoint.value.IsNull() { endPoint.value.SetInt64(math.MinInt64) } else if endPoint.value.Kind() == types.KindMaxValue { endPoint.value.SetInt64(math.MaxInt64) } endInt, err := endPoint.value.ToInt64() if err != nil { r.err = errors.Trace(err) return tableRanges } endDatum := types.NewDatum(endInt) cmp, err = endDatum.CompareDatum(endPoint.value) if err != nil { r.err = errors.Trace(err) return tableRanges } if cmp > 0 || (cmp == 0 && endPoint.excl) { endInt-- } if startInt > endInt { continue } tableRanges = append(tableRanges, TableRange{LowVal: startInt, HighVal: endInt}) } return tableRanges }
func (s *testExpressionSuite) TestExpression(c *C) { defer testleak.AfterTest(c)() var schema Schema for i := 0; i < 3; i++ { schema = append(schema, &Column{ColName: model.NewCIStr("t"), FromID: "mock", Position: i}) } tc1 := &Column{FromID: "t", ColName: model.NewCIStr("c1")} kc1 := &Column{FromID: "k", ColName: model.NewCIStr("c1")} tc2 := &Column{FromID: "t", ColName: model.NewCIStr("c2")} con := &Constant{Value: types.NewDatum(10)} col := &ast.ColumnName{Name: model.NewCIStr("t")} // t.c1 as t, t.c2 as t, 10 as t => error index, err := getColIndex([]Expression{tc1, tc2, con}, schema, col) c.Check(err, NotNil) // t.c1 as t, 10 as t, t.c2 as t => 10 index, err = getColIndex([]Expression{tc1, con, tc2}, schema, col) c.Assert(index, Equals, 1) // t.c1 as t, t.c1 as t, 10 as t => 10 index, err = getColIndex([]Expression{tc1, tc1, con}, schema, col) c.Assert(index, Equals, 2) // t.c1 as t, k.c1 as t, 10 as t => error index, err = getColIndex([]Expression{tc1, kc1, con}, schema, col) c.Check(err, NotNil) }
func (s *testEvaluatorSuite) TestBinopBitop(c *C) { defer testleak.AfterTest(c)() ctx := mock.NewContext() tbl := []struct { lhs interface{} op opcode.Op rhs interface{} ret interface{} }{ {1, opcode.And, 1, 1}, {1, opcode.Or, 1, 1}, {1, opcode.Xor, 1, 0}, {1, opcode.LeftShift, 1, 2}, {2, opcode.RightShift, 1, 1}, {nil, opcode.And, 1, nil}, {1, opcode.And, nil, nil}, {nil, opcode.Or, 1, nil}, {nil, opcode.Xor, 1, nil}, {nil, opcode.LeftShift, 1, nil}, {nil, opcode.RightShift, 1, nil}, } for _, t := range tbl { expr := &ast.BinaryOperationExpr{Op: t.op, L: ast.NewValueExpr(t.lhs), R: ast.NewValueExpr(t.rhs)} v, err := Eval(ctx, expr) c.Assert(err, IsNil) switch x := t.ret.(type) { case nil: c.Assert(v.Kind(), Equals, types.KindNull) case int: c.Assert(v, testutil.DatumEquals, types.NewDatum(uint64(x))) } } }
func genValues(handle int64, tbl *simpleTableInfo) []types.Datum { values := make([]types.Datum, 0, len(tbl.cTypes)) for _, tp := range tbl.cTypes { switch tp { case mysql.TypeLong: values = append(values, types.NewDatum(handle)) case mysql.TypeVarchar: values = append(values, types.NewDatum(fmt.Sprintf("varchar:%d", handle))) case mysql.TypeDouble: values = append(values, types.NewDatum(float64(handle)/10)) default: values = append(values, types.Datum{}) } } return values }
func setRow(txn kv.Transaction, handle int64, tbl *simpleTableInfo, gen genValueFunc) error { rowKey := tablecodec.EncodeRowKey(tbl.tID, codec.EncodeInt(nil, handle)) columnValues := gen(handle, tbl) value, err := tablecodec.EncodeRow(columnValues, tbl.cIDs) if err != nil { return errors.Trace(err) } err = txn.Set(rowKey, value) if err != nil { return errors.Trace(err) } for i, idxCol := range tbl.indices { idxVal := columnValues[idxCol] encoded, err := codec.EncodeKey(nil, idxVal, types.NewDatum(handle)) if err != nil { return errors.Trace(err) } idxKey := tablecodec.EncodeIndexSeekKey(tbl.tID, tbl.iIDs[i], encoded) err = txn.Set(idxKey, []byte{0}) if err != nil { return errors.Trace(err) } } return nil }
func (s *testDecimalSuite) TestDecimalCodec(c *C) { defer testleak.AfterTest(c)() inputs := []struct { Input float64 }{ {float64(123400)}, {float64(1234)}, {float64(12.34)}, {float64(0.1234)}, {float64(0.01234)}, {float64(-0.1234)}, {float64(-0.01234)}, {float64(12.3400)}, {float64(-12.34)}, {float64(0.00000)}, {float64(0)}, {float64(-0.0)}, {float64(-0.000)}, } for _, input := range inputs { v := types.NewDecFromFloatForTest(input.Input) b := EncodeDecimal([]byte{}, types.NewDatum(v)) _, d, err := DecodeDecimal(b) c.Assert(err, IsNil) c.Assert(v.Compare(d.GetMysqlDecimal()), Equals, 0) } }
// tryToPushDownAgg tries to push down an aggregate function into a join path. If all aggFuncs are first row, we won't // process it temporarily. If not, We will add additional group by columns and first row functions. We make a new aggregation // operator. func (a *aggPushDownSolver) tryToPushDownAgg(aggFuncs []expression.AggregationFunction, gbyCols []*expression.Column, join *Join, childIdx int) LogicalPlan { child := join.GetChildByIndex(childIdx).(LogicalPlan) if a.allFirstRow(aggFuncs) { return child } agg := a.makeNewAgg(aggFuncs, gbyCols) child.SetParents(agg) agg.SetChildren(child) agg.correlated = agg.correlated || child.IsCorrelated() // If agg has no group-by item, it will return a default value, which may cause some bugs. // So here we add a group-by item forcely. if len(agg.GroupByItems) == 0 { agg.GroupByItems = []expression.Expression{&expression.Constant{ Value: types.NewDatum(0), RetType: types.NewFieldType(mysql.TypeLong)}} } if (childIdx == 0 && join.JoinType == RightOuterJoin) || (childIdx == 1 && join.JoinType == LeftOuterJoin) { var existsDefaultValues bool join.DefaultValues, existsDefaultValues = a.getDefaultValues(agg) if !existsDefaultValues { return child } } return agg }
func (s *testEvaluatorSuite) TestRegexp(c *C) { defer testleak.AfterTest(c)() tbl := []struct { pattern string input string match int64 }{ {"^$", "a", 0}, {"a", "a", 1}, {"a", "b", 0}, {"aA", "aA", 1}, {".", "a", 1}, {"^.$", "ab", 0}, {"..", "b", 0}, {".ab", "aab", 1}, {".*", "abcd", 1}, } ctx := mock.NewContext() for _, v := range tbl { pattern := &ast.PatternRegexpExpr{ Pattern: ast.NewValueExpr(v.pattern), Expr: ast.NewValueExpr(v.input), } match, err := Eval(ctx, pattern) c.Assert(err, IsNil) c.Assert(match, testutil.DatumEquals, types.NewDatum(v.match), Commentf("%v", v)) } }
// Next implements Executor Next interface. func (e *SelectFieldsExec) Next() (*Row, error) { var rowKeys []*RowKeyEntry if e.Src != nil { srcRow, err := e.Src.Next() if err != nil { return nil, errors.Trace(err) } if srcRow == nil { return nil, nil } rowKeys = srcRow.RowKeys } else { // If Src is nil, only one row should be returned. if e.executed { return nil, nil } } e.executed = true row := &Row{ RowKeys: rowKeys, Data: make([]types.Datum, len(e.ResultFields)), } for i, field := range e.ResultFields { val, err := evaluator.Eval(e.ctx, field.Expr) if err != nil { return nil, errors.Trace(err) } row.Data[i] = types.NewDatum(val) } return row, nil }
func (s *testEvalSuite) TestEvalIfNull(c *C) { colID := int64(1) xevaluator := NewEvaluator(new(variable.StatementContext)) xevaluator.Row[colID] = types.NewDatum(100) null, notNull, expr := types.Datum{}, types.NewStringDatum("left"), types.NewStringDatum("right") cases := []struct { expr *tipb.Expr result types.Datum }{ { expr: buildExpr(tipb.ExprType_IfNull, null, expr), result: expr, }, { expr: buildExpr(tipb.ExprType_IfNull, notNull, expr), result: notNull, }, { expr: buildExpr(tipb.ExprType_IfNull, notNull, null), result: notNull, }, } for _, ca := range cases { result, err := xevaluator.Eval(ca.expr) c.Assert(err, IsNil) c.Assert(result.Kind(), Equals, ca.result.Kind()) cmp, err := result.CompareDatum(xevaluator.sc, ca.result) c.Assert(err, IsNil) c.Assert(cmp, Equals, 0) } }
func (e *Evaluator) caseExpr(v *ast.CaseExpr) bool { tmp := types.NewDatum(boolToInt64(true)) target := &tmp if v.Value != nil { target = v.Value.GetDatum() } if !target.IsNull() { for _, val := range v.WhenClauses { cmp, err := target.CompareDatum(*val.Expr.GetDatum()) if err != nil { e.err = errors.Trace(err) return false } if cmp == 0 { v.SetDatum(*val.Result.GetDatum()) return true } } } if v.ElseClause != nil { v.SetDatum(*v.ElseClause.GetDatum()) } else { v.SetNull() } return true }
// Do the real work to evaluate subquery. func (e *Evaluator) subqueryExec(v ast.SubqueryExec) bool { rowCount := 2 if e.multipleRows { rowCount = -1 } else if e.existRow { rowCount = 1 } rows, err := v.EvalRows(e.ctx, rowCount) if err != nil { e.err = errors.Trace(err) return false } if e.multipleRows || e.existRow { v.GetDatum().SetInterface(types.MakeDatums(rows...)) return true } switch len(rows) { case 0: v.GetDatum().SetNull() case 1: v.SetDatum(types.NewDatum(rows[0])) default: e.err = errors.New("Subquery returns more than 1 row") return false } return true }
// GenIndexKey generates storage key for index values. Returned distinct indicates whether the // indexed values should be distinct in storage (i.e. whether handle is encoded in the key). func (c *index) GenIndexKey(indexedValues []types.Datum, h int64) (key []byte, distinct bool, err error) { if c.unique { // See: https://dev.mysql.com/doc/refman/5.7/en/create-index.html // A UNIQUE index creates a constraint such that all values in the index must be distinct. // An error occurs if you try to add a new row with a key value that matches an existing row. // For all engines, a UNIQUE index permits multiple NULL values for columns that can contain NULL. distinct = true for _, cv := range indexedValues { if cv.IsNull() { distinct = false break } } } key = append(key, c.prefix...) if distinct { key, err = codec.EncodeKey(key, indexedValues...) } else { key, err = codec.EncodeKey(key, append(indexedValues, types.NewDatum(h))...) } if err != nil { return nil, false, errors.Trace(err) } return }
func (s *testColumnSuite) checkPublicColumn(c *C, ctx context.Context, d *ddl, tblInfo *model.TableInfo, handle int64, col *column.Col, row []types.Datum, columnValue interface{}) { t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) _, err := ctx.GetTxn(true) c.Assert(err, IsNil) i := int64(0) oldRow := append(row, types.NewDatum(columnValue)) err = t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { c.Assert(data, DeepEquals, oldRow) i++ return true, nil }) c.Assert(err, IsNil) c.Assert(i, Equals, int64(1)) // Test add a new row. _, err = ctx.GetTxn(true) c.Assert(err, IsNil) newRow := types.MakeDatums(int64(11), int64(22), int64(33), int64(44)) handle, err = t.AddRecord(ctx, newRow) c.Assert(err, IsNil) _, err = ctx.GetTxn(true) c.Assert(err, IsNil) rows := [][]types.Datum{oldRow, newRow} i = int64(0) t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { c.Assert(data, DeepEquals, rows[i]) i++ return true, nil }) c.Assert(i, Equals, int64(2)) // Test remove a row. _, err = ctx.GetTxn(true) c.Assert(err, IsNil) err = t.RemoveRecord(ctx, handle, newRow) c.Assert(err, IsNil) _, err = ctx.GetTxn(true) c.Assert(err, IsNil) i = int64(0) t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { c.Assert(data, DeepEquals, oldRow) i++ return true, nil }) c.Assert(i, Equals, int64(1)) err = ctx.FinishTxn(false) c.Assert(err, IsNil) s.testGetColumn(c, t, col.Name.L, true) }
func composeEncodedData(size int) []byte { values := make([]types.Datum, 0, size) for i := 0; i < size; i++ { values = append(values, types.NewDatum(i)) } bs, _ := EncodeValue(nil, values...) return bs }