Beispiel #1
0
func (e *Evaluator) handleLogicOperation(o *ast.BinaryOperationExpr) bool {
	leftVal, err := types.Convert(o.L.GetValue(), o.GetType())
	if err != nil {
		e.err = err
		return false
	}
	rightVal, err := types.Convert(o.R.GetValue(), o.GetType())
	if err != nil {
		e.err = err
		return false
	}
	if leftVal == nil || rightVal == nil {
		o.SetValue(nil)
		return true
	}
	var boolVal bool
	switch o.Op {
	case opcode.AndAnd:
		boolVal = leftVal != zeroI64 && rightVal != zeroI64
	case opcode.OrOr:
		boolVal = leftVal != zeroI64 || rightVal != zeroI64
	case opcode.LogicXor:
		boolVal = (leftVal == zeroI64 && rightVal != zeroI64) || (leftVal != zeroI64 && rightVal == zeroI64)
	default:
		panic("should never happen")
	}
	if boolVal {
		o.SetValue(oneI64)
	} else {
		o.SetValue(zeroI64)
	}
	return true
}
Beispiel #2
0
// Eval implements the Expression Eval interface.
func (e *Extract) Eval(ctx context.Context, args map[interface{}]interface{}) (interface{}, error) {
	v, err := e.Date.Eval(ctx, args)
	if v == nil || err != nil {
		return nil, errors.Trace(err)
	}

	f := types.NewFieldType(mysql.TypeDatetime)
	f.Decimal = mysql.MaxFsp

	v, err = types.Convert(v, f)
	if v == nil || err != nil {
		return nil, errors.Trace(err)
	}

	t, ok := v.(mysql.Time)
	if !ok {
		return nil, errors.Errorf("need time type, but got %T", v)
	}

	n, err1 := extractTime(e.Unit, t)
	if err1 != nil {
		return nil, errors.Trace(err1)
	}

	return n, nil
}
Beispiel #3
0
func (e *Evaluator) funcExtract(v *ast.FuncExtractExpr) bool {
	val := v.Date.GetValue()
	if val == nil {
		v.SetValue(nil)
		return true
	}

	f := types.NewFieldType(mysql.TypeDatetime)
	f.Decimal = mysql.MaxFsp
	var err error
	val, err = types.Convert(val, f)
	if err != nil {
		e.err = errors.Trace(err)
		return false
	}
	if val == nil {
		v.SetValue(nil)
		return true
	}

	t, ok := val.(mysql.Time)
	if !ok {
		e.err = ErrInvalidOperation.Gen("need time type, but got %T", val)
		return false
	}
	n, err1 := mysql.ExtractTimeNum(v.Unit, t)
	if err1 != nil {
		e.err = errors.Trace(err1)
		return false
	}
	v.SetValue(n)
	return true
}
Beispiel #4
0
// Next implements Executor Next interface.
func (e *IndexRangeExec) Next() (*Row, error) {
	if e.iter == nil {
		seekVals := make([]interface{}, len(e.scan.idx.Columns))
		for i := 0; i < len(e.lowVals); i++ {
			var err error
			if e.lowVals[i] == plan.MinNotNullVal {
				seekVals[i] = []byte{}
			} else {
				seekVals[i], err = types.Convert(e.lowVals[i], e.scan.valueTypes[i])
				if err != nil {
					return nil, errors.Trace(err)
				}
			}
		}
		txn, err := e.scan.ctx.GetTxn(false)
		if err != nil {
			return nil, errors.Trace(err)
		}
		e.iter, _, err = e.scan.idx.X.Seek(txn, seekVals)
		if err != nil {
			return nil, types.EOFAsNil(err)
		}
	}

	for {
		if e.finished {
			return nil, nil
		}
		idxKey, h, err := e.iter.Next()
		if err != nil {
			return nil, types.EOFAsNil(err)
		}
		if !e.skipLowCmp {
			var cmp int
			cmp, err = indexCompare(idxKey, e.lowVals)
			if err != nil {
				return nil, errors.Trace(err)
			}
			if cmp < 0 || (cmp == 0 && e.lowExclude) {
				continue
			}
			e.skipLowCmp = true
		}
		cmp, err := indexCompare(idxKey, e.highVals)
		if err != nil {
			return nil, errors.Trace(err)
		}
		if cmp > 0 || (cmp == 0 && e.highExclude) {
			// This span has finished iteration.
			e.finished = true
			continue
		}
		var row *Row
		row, err = e.lookupRow(h)
		if err != nil {
			return nil, errors.Trace(err)
		}
		return row, nil
	}
}
Beispiel #5
0
// Next implements Executor Next interface.
func (e *UnionExec) Next() (*Row, error) {
	for {
		if e.cursor >= len(e.Sels) {
			return nil, nil
		}
		sel := e.Sels[e.cursor]
		row, err := sel.Next()
		if err != nil {
			return nil, errors.Trace(err)
		}
		if row == nil {
			e.cursor++
			continue
		}
		if e.cursor != 0 {
			for i := range row.Data {
				// The column value should be casted as the same type of the first select statement in corresponding position
				rf := e.fields[i]
				row.Data[i], err = types.Convert(row.Data[i], &rf.Column.FieldType)
				if err != nil {
					return nil, errors.Trace(err)
				}
			}
		}
		for i, v := range row.Data {
			e.fields[i].Expr.SetValue(v)
		}
		return row, nil
	}
}
Beispiel #6
0
// Eval implements the Expression Eval interface.
func (c *Conversion) Eval(ctx context.Context, args map[interface{}]interface{}) (v interface{}, err error) {
	Val, err := c.Val.Eval(ctx, args)
	if err != nil {
		return
	}
	ft := types.NewFieldType(c.Tp)
	return types.Convert(Val, ft)
}
Beispiel #7
0
func (d *ddl) backfillColumnData(t table.Table, columnInfo *model.ColumnInfo, handles []int64, reorgInfo *reorgInfo) error {
	for _, handle := range handles {
		log.Info("[ddl] backfill column...", handle)

		err := kv.RunInNewTxn(d.store, true, func(txn kv.Transaction) error {
			if err := d.isReorgRunnable(txn); err != nil {
				return errors.Trace(err)
			}

			// First check if row exists.
			exist, err := checkRowExist(txn, t, handle)
			if err != nil {
				return errors.Trace(err)
			} else if !exist {
				// If row doesn't exist, skip it.
				return nil
			}

			backfillKey := t.RecordKey(handle, &column.Col{ColumnInfo: *columnInfo})
			backfillValue, err := txn.Get(backfillKey)
			if err != nil && !kv.IsErrNotFound(err) {
				return errors.Trace(err)
			}
			if backfillValue != nil {
				return nil
			}

			value, _, err := tables.GetColDefaultValue(nil, columnInfo)
			if err != nil {
				return errors.Trace(err)
			}

			// must convert to the column field type.
			v, err := types.Convert(value, &columnInfo.FieldType)
			if err != nil {
				return errors.Trace(err)
			}

			err = lockRow(txn, t, handle)
			if err != nil {
				return errors.Trace(err)
			}

			err = t.SetColValue(txn, backfillKey, v)
			if err != nil {
				return errors.Trace(err)
			}

			return errors.Trace(reorgInfo.UpdateHandle(txn, handle))
		})

		if err != nil {
			return errors.Trace(err)
		}
	}

	return nil
}
Beispiel #8
0
func (e *Evaluator) binaryOperation(o *ast.BinaryOperationExpr) bool {
	// all operands must have same column.
	if e.err = hasSameColumnCount(o.L, o.R); e.err != nil {
		return false
	}

	// row constructor only supports comparison operation.
	switch o.Op {
	case opcode.LT, opcode.LE, opcode.GE, opcode.GT, opcode.EQ, opcode.NE, opcode.NullEQ:
	default:
		if !checkAllOneColumn(o.L) {
			e.err = errors.Errorf("Operand should contain 1 column(s)")
			return false
		}
	}

	leftVal, err := types.Convert(o.L.GetValue(), o.GetType())
	if err != nil {
		e.err = err
		return false
	}
	rightVal, err := types.Convert(o.R.GetValue(), o.GetType())
	if err != nil {
		e.err = err
		return false
	}
	if leftVal == nil || rightVal == nil {
		o.SetValue(nil)
		return true
	}

	switch o.Op {
	case opcode.AndAnd, opcode.OrOr, opcode.LogicXor:
		return e.handleLogicOperation(o)
	case opcode.LT, opcode.LE, opcode.GE, opcode.GT, opcode.EQ, opcode.NE, opcode.NullEQ:
		return e.handleComparisonOp(o)
	case opcode.RightShift, opcode.LeftShift, opcode.And, opcode.Or, opcode.Xor:
		// TODO: MySQL doesn't support and not, we should remove it later.
		return e.handleBitOp(o)
	case opcode.Plus, opcode.Minus, opcode.Mod, opcode.Div, opcode.Mul, opcode.IntDiv:
		return e.handleArithmeticOp(o)
	default:
		panic("should never happen")
	}
}
Beispiel #9
0
// castValues casts values based on columns type.
func castValues(rec []interface{}, cols []*model.ColumnInfo) (err error) {
	for _, c := range cols {
		rec[c.Offset], err = types.Convert(rec[c.Offset], &c.FieldType)
		if err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}
Beispiel #10
0
func (r *TableDefaultPlan) filterBinOp(ctx context.Context, x *expression.BinaryOperation) (plan.Plan, bool, error) {
	ok, name, rval, err := x.IsIdentCompareVal()
	if err != nil {
		return r, false, errors.Trace(err)
	}
	if !ok {
		return r, false, nil
	}
	if rval == nil {
		// if nil, any <, <=, >, >=, =, != operator will do nothing
		// any value compared null returns null
		// TODO: if we support <=> later, we must handle null
		return &NullPlan{r.GetFields()}, true, nil
	}

	_, tn, cn := field.SplitQualifiedName(name)
	t := r.T
	if tn != "" && tn != t.TableName().L {
		return r, false, nil
	}
	c := column.FindCol(t.Cols(), cn)
	if c == nil {
		return nil, false, errors.Errorf("No such column: %s", cn)
	}
	var seekVal interface{}
	if seekVal, err = types.Convert(rval, &c.FieldType); err != nil {
		return nil, false, errors.Trace(err)
	}
	spans := toSpans(x.Op, rval, seekVal)
	if c.IsPKHandleColumn(r.T.Meta()) {
		if r.rangeScan {
			spans = filterSpans(r.spans, spans)
		}
		return &TableDefaultPlan{
			T:         r.T,
			Fields:    r.Fields,
			rangeScan: true,
			spans:     spans,
		}, true, nil
	} else if r.rangeScan {
		// Already filtered on PK handle column, should not switch to index plan.
		return r, false, nil
	}

	ix := t.FindIndexByColName(cn)
	if ix == nil { // Column cn has no index.
		return r, false, nil
	}
	return &indexPlan{
		src:     t,
		col:     c,
		unique:  ix.Unique,
		idxName: ix.Name.O,
		idx:     ix.X,
		spans:   spans,
	}, true, nil
}
Beispiel #11
0
// CastValues casts values based on columns type.
func CastValues(ctx context.Context, rec []interface{}, cols []*Col) (err error) {
	for _, c := range cols {
		rec[c.Offset], err = types.Convert(rec[c.Offset], &c.FieldType)
		if err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}
Beispiel #12
0
// Filter implements plan.Plan Filter interface.
// Filter merges BinaryOperations and determines the lower and upper bound.
func (r *indexPlan) Filter(ctx context.Context, expr expression.Expression) (plan.Plan, bool, error) {
	var spans []*indexSpan
	switch x := expr.(type) {
	case *expression.BinaryOperation:
		ok, name, val, err := x.IsIdentCompareVal()
		if err != nil {
			return nil, false, err
		}
		if !ok {
			break
		}
		_, tname, cname := field.SplitQualifiedName(name)
		if tname != "" && r.src.TableName().L != tname {
			break
		}
		if r.col.ColumnInfo.Name.L != cname {
			break
		}
		seekVal, err := types.Convert(val, &r.col.FieldType)
		if err != nil {
			return nil, false, errors.Trace(err)
		}
		spans = filterSpans(r.spans, toSpans(x.Op, val, seekVal))
	case *expression.Ident:
		if r.col.Name.L != x.L {
			break
		}
		spans = filterSpans(r.spans, toSpans(opcode.GE, minNotNullVal, nil))
	case *expression.UnaryOperation:
		if x.Op != '!' {
			break
		}

		cname, ok := x.V.(*expression.Ident)
		if !ok {
			break
		}
		if r.col.Name.L != cname.L {
			break
		}
		spans = filterSpans(r.spans, toSpans(opcode.EQ, nil, nil))
	}

	if spans == nil {
		return r, false, nil
	}

	return &indexPlan{
		src:     r.src,
		col:     r.col,
		unique:  r.unique,
		idxName: r.idxName,
		idx:     r.idx,
		spans:   spans,
	}, true, nil
}
Beispiel #13
0
func (p *UnionPlan) fetchSrc(ctx context.Context, i int, t memkv.Temp) error {
	src := p.Srcs[i+1]
	distinct := p.Distincts[i]

	// Use the ResultFields of the first select statement as the final ResultFields
	rfs := p.Srcs[0].GetFields()
	if len(src.GetFields()) != len(rfs) {
		return errors.New("The used SELECT statements have a different number of columns")
	}
	for {
		row, err := src.Next(ctx)
		if row == nil || err != nil {
			return errors.Trace(err)
		}
		srcRfs := src.GetFields()
		for i := range row.Data {
			// The column value should be casted as the same type of the first select statement in corresponding position
			srcRf := srcRfs[i]
			rf := rfs[i]
			/*
			 * The lengths of the columns in the UNION result take into account the values retrieved by all of the SELECT statements
			 * SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
			 * +---------------+
			 * | REPEAT('a',1) |
			 * +---------------+
			 * | a             |
			 * | bbbbbbbbbb    |
			 * +---------------+
			 */
			if srcRf.Flen > rf.Col.Flen {
				rf.Col.Flen = srcRf.Col.Flen
			}
			row.Data[i], err = types.Convert(row.Data[i], &rf.Col.FieldType)
			if err != nil {
				return errors.Trace(err)
			}
		}
		if distinct {
			// distinct union, check duplicate
			v, getErr := t.Get(row.Data)
			if getErr != nil {
				return errors.Trace(getErr)
			}
			if len(v) > 0 {
				// Find duplicate, ignore it
				continue
			}
		}
		p.rows = append(p.rows, row)
		if err := t.Set(row.Data, []interface{}{true}); err != nil {
			return errors.Trace(err)
		}
	}
}
Beispiel #14
0
// Eval implements the Expression Eval interface.
func (da *DateAdd) Eval(ctx context.Context, args map[interface{}]interface{}) (interface{}, error) {
	dv, err := da.Date.Eval(ctx, args)
	if dv == nil || err != nil {
		return nil, errors.Trace(err)
	}

	sv, err := types.ToString(dv)
	if err != nil {
		return nil, errors.Trace(err)
	}

	f := types.NewFieldType(mysql.TypeDatetime)
	f.Decimal = mysql.MaxFsp

	dv, err = types.Convert(sv, f)
	if dv == nil || err != nil {
		return nil, errors.Trace(err)
	}

	t, ok := dv.(mysql.Time)
	if !ok {
		return nil, errors.Errorf("need time type, but got %T", dv)
	}

	iv, err := da.Interval.Eval(ctx, args)
	if iv == nil || err != nil {
		return nil, errors.Trace(err)
	}

	format, err := types.ToString(iv)
	if err != nil {
		return nil, errors.Trace(err)
	}

	years, months, days, durations, err := mysql.ExtractTimeValue(da.Unit, strings.TrimSpace(format))
	if err != nil {
		return nil, errors.Trace(err)
	}

	t.Time = t.Time.Add(durations)
	t.Time = t.Time.AddDate(int(years), int(months), int(days))

	// "2011-11-11 10:10:20.000000" outputs "2011-11-11 10:10:20".
	if t.Time.Nanosecond() == 0 {
		t.Fsp = 0
	}

	return t, nil
}
Beispiel #15
0
func (da *DateArith) evalArgs(ctx context.Context, args map[interface{}]interface{}) (
	*evalArgsResult, error) {
	ret := &evalArgsResult{time: mysql.ZeroTimestamp}

	dVal, err := da.Date.Eval(ctx, args)
	if dVal == nil || err != nil {
		return ret, errors.Trace(err)
	}
	dValStr, err := types.ToString(dVal)
	if err != nil {
		return ret, errors.Trace(err)
	}
	f := types.NewFieldType(mysql.TypeDatetime)
	f.Decimal = mysql.MaxFsp
	dVal, err = types.Convert(dValStr, f)
	if dVal == nil || err != nil {
		return ret, errors.Trace(err)
	}

	var ok bool
	ret.time, ok = dVal.(mysql.Time)
	if !ok {
		return ret, errors.Errorf("need time type, but got %T", dVal)
	}

	iVal, err := da.Interval.Eval(ctx, args)
	if iVal == nil || err != nil {
		ret.time = mysql.ZeroTimestamp
		return ret, errors.Trace(err)
	}
	// handle adddate(expr,days) or subdate(expr,days) form
	if da.Form == DateArithDaysForm {
		if iVal, err = da.evalDaysForm(iVal); err != nil {
			return ret, errors.Trace(err)
		}
	}

	iValStr, err := types.ToString(iVal)
	if err != nil {
		return ret, errors.Trace(err)
	}
	ret.year, ret.month, ret.day, ret.duration, err = mysql.ExtractTimeValue(da.Unit, strings.TrimSpace(iValStr))
	if err != nil {
		return ret, errors.Trace(err)
	}

	return ret, nil
}
Beispiel #16
0
// Filter implements plan.Plan Filter interface.
// Filter merges BinaryOperations, and determines the lower and upper bound.
func (r *indexPlan) Filter(ctx context.Context, expr expression.Expression) (plan.Plan, bool, error) {
	switch x := expr.(type) {
	case *expression.BinaryOperation:
		ok, cname, val, err := x.IsIdentRelOpVal()
		if err != nil {
			return nil, false, err
		}

		if !ok || r.colName != cname {
			break
		}

		col := column.FindCol(r.src.Cols(), cname)
		if col == nil {
			break
		}

		if val, err = types.Convert(val, &col.FieldType); err != nil {
			return nil, false, err
		}
		r.spans = filterSpans(r.spans, toSpans(x.Op, val))
		return r, true, nil
	case *expression.Ident:
		if r.colName != x.L {
			break
		}
		r.spans = filterSpans(r.spans, toSpans(opcode.GE, minNotNullVal))
		return r, true, nil
	case *expression.UnaryOperation:
		if x.Op != '!' {
			break
		}

		operand, ok := x.V.(*expression.Ident)
		if !ok {
			break
		}

		cname := operand.L
		if r.colName != cname {
			break
		}
		r.spans = filterSpans(r.spans, toSpans(opcode.EQ, nil))
		return r, true, nil
	}

	return r, false, nil
}
Beispiel #17
0
// Eval implements the Expression Eval interface.
func (f *FunctionCast) Eval(ctx context.Context, args map[interface{}]interface{}) (interface{}, error) {
	value, err := f.Expr.Eval(ctx, args)
	if err != nil {
		return nil, err
	}

	// Casting nil to any type returns null
	if value == nil {
		return nil, nil
	}
	nv, err := types.Convert(value, f.Tp)
	if err != nil {
		return nil, err
	}
	return nv, nil
}
Beispiel #18
0
func (r *TableDefaultPlan) filterBinOp(ctx context.Context, x *expression.BinaryOperation) (plan.Plan, bool, error) {
	ok, name, rval, err := x.IsIdentCompareVal()
	if err != nil {
		return r, false, err
	}
	if !ok {
		return r, false, nil
	}
	if rval == nil {
		// if nil, any <, <=, >, >=, =, != operator will do nothing
		// any value compared null returns null
		// TODO: if we support <=> later, we must handle null
		return &NullPlan{r.GetFields()}, true, nil
	}

	_, tn, cn := field.SplitQualifiedName(name)
	t := r.T
	if tn != "" && tn != t.TableName().L {
		return r, false, nil
	}
	c := column.FindCol(t.Cols(), cn)
	if c == nil {
		return nil, false, errors.Errorf("No such column: %s", cn)
	}

	ix := t.FindIndexByColName(cn)
	if ix == nil { // Column cn has no index.
		return r, false, nil
	}

	var seekVal interface{}
	if seekVal, err = types.Convert(rval, &c.FieldType); err != nil {
		return nil, false, err
	}
	return &indexPlan{
		src:     t,
		col:     c,
		idxName: ix.Name.O,
		idx:     ix.X,
		spans:   toSpans(x.Op, rval, seekVal),
	}, true, nil
}
Beispiel #19
0
func convertToDuration(arg interface{}, fsp int) (interface{}, error) {
	f := types.NewFieldType(mysql.TypeDuration)
	f.Decimal = fsp

	v, err := types.Convert(arg, f)
	if err != nil {
		return nil, err
	}

	if types.IsNil(v) {
		return nil, nil
	}

	t, ok := v.(mysql.Duration)
	if !ok {
		return nil, errors.Errorf("need duration type, but got %T", v)
	}

	return t, nil
}
Beispiel #20
0
func convertToTime(arg interface{}, tp byte) (interface{}, error) {
	f := types.NewFieldType(tp)
	f.Decimal = mysql.MaxFsp

	v, err := types.Convert(arg, f)
	if err != nil {
		return nil, err
	}

	if types.IsNil(v) {
		return nil, nil
	}

	t, ok := v.(mysql.Time)
	if !ok {
		return nil, errors.Errorf("need time type, but got %T", v)
	}

	return t, nil
}
Beispiel #21
0
func (s *testColumnSuite) checkColumnKVExist(c *C, ctx context.Context, t table.Table, handle int64, col *column.Col, columnValue interface{}, isExist bool) {
	txn, err := ctx.GetTxn(true)
	c.Assert(err, IsNil)

	key := t.RecordKey(handle, col)
	data, err := txn.Get(key)

	if isExist {
		c.Assert(err, IsNil)
		v, err1 := t.DecodeValue(data, col)
		c.Assert(err1, IsNil)
		value, err1 := types.Convert(v, &col.FieldType)
		c.Assert(err1, IsNil)
		c.Assert(value, Equals, columnValue)
	} else {
		c.Assert(err, NotNil)
	}

	err = ctx.FinishTxn(false)
	c.Assert(err, IsNil)
}
Beispiel #22
0
Datei: cast.go Projekt: npk/tidb
// Eval implements the Expression Eval interface.
func (f *FunctionCast) Eval(ctx context.Context, args map[interface{}]interface{}) (interface{}, error) {
	value, err := f.Expr.Eval(ctx, args)
	if err != nil {
		return nil, err
	}

	// Casting nil to any type returns null
	if value == nil {
		return nil, nil
	}

	// TODO: we need a better function convert between any two types according to FieldType.
	// Not only check Type, but also consider Flen/Decimal/Charset and so on.
	nv, err := types.Convert(value, f.Tp)
	if err != nil {
		return nil, err
	}
	if f.Tp.Tp == mysql.TypeString && f.Tp.Charset == charset.CharsetBin {
		nv = []byte(nv.(string))
	}
	if f.Tp.Flen != types.UnspecifiedLength {
		switch f.Tp.Tp {
		case mysql.TypeString:
			v := nv.(string)
			if len(v) > int(f.Tp.Flen) {
				v = v[:f.Tp.Flen]
			}
			return v, nil
		}
	}
	if f.Tp.Tp == mysql.TypeLonglong {
		if mysql.HasUnsignedFlag(f.Tp.Flag) {
			return uint64(nv.(int64)), nil
		}
	}
	return nv, nil
}
Beispiel #23
0
func (da *DateArith) evalArgs(ctx context.Context, args map[interface{}]interface{}) (
	mysql.Time, int64, int64, int64, time.Duration, error) {
	dVal, err := da.Date.Eval(ctx, args)
	if dVal == nil || err != nil {
		return mysql.ZeroTimestamp, 0, 0, 0, 0, errors.Trace(err)
	}
	dValStr, err := types.ToString(dVal)
	if err != nil {
		return mysql.ZeroTimestamp, 0, 0, 0, 0, errors.Trace(err)
	}
	f := types.NewFieldType(mysql.TypeDatetime)
	f.Decimal = mysql.MaxFsp
	dVal, err = types.Convert(dValStr, f)
	if dVal == nil || err != nil {
		return mysql.ZeroTimestamp, 0, 0, 0, 0, errors.Trace(err)
	}
	t, ok := dVal.(mysql.Time)
	if !ok {
		return mysql.ZeroTimestamp, 0, 0, 0, 0, errors.Errorf("need time type, but got %T", dVal)
	}

	iVal, err := da.Interval.Eval(ctx, args)
	if iVal == nil || err != nil {
		return mysql.ZeroTimestamp, 0, 0, 0, 0, errors.Trace(err)
	}
	iValStr, err := types.ToString(iVal)
	if err != nil {
		return mysql.ZeroTimestamp, 0, 0, 0, 0, errors.Trace(err)
	}
	years, months, days, durations, err := mysql.ExtractTimeValue(da.Unit, strings.TrimSpace(iValStr))
	if err != nil {
		return mysql.ZeroTimestamp, 0, 0, 0, 0, errors.Trace(err)
	}

	return t, years, months, days, durations, nil
}
Beispiel #24
0
func getTimeValue(ctx context.Context, v interface{}, tp byte, fsp int) (interface{}, error) {
	value := mysql.Time{
		Type: tp,
		Fsp:  fsp,
	}

	defaultTime, err := getSystemTimestamp(ctx)
	if err != nil {
		return nil, errors.Trace(err)
	}

	switch x := v.(type) {
	case string:
		if x == CurrentTimestamp {
			value.Time = defaultTime
		} else if x == ZeroTimestamp {
			value, _ = mysql.ParseTimeFromNum(0, tp, fsp)
		} else {
			value, err = mysql.ParseTime(x, tp, fsp)
			if err != nil {
				return nil, errors.Trace(err)
			}
		}
	case Value:
		switch xval := x.Val.(type) {
		case string:
			value, err = mysql.ParseTime(xval, tp, fsp)
			if err != nil {
				return nil, errors.Trace(err)
			}
		case int64:
			value, err = mysql.ParseTimeFromNum(int64(xval), tp, fsp)
			if err != nil {
				return nil, errors.Trace(err)
			}
		case nil:
			return nil, nil
		default:
			return nil, errors.Trace(errDefaultValue)
		}
	case *Ident:
		if x.Equal(CurrentTimeExpr) {
			return CurrentTimestamp, nil
		}

		return nil, errors.Trace(errDefaultValue)
	case *UnaryOperation:
		// support some expression, like `-1`
		m := map[interface{}]interface{}{}
		v := Eval(x, nil, m)
		ft := types.NewFieldType(mysql.TypeLonglong)
		xval, err := types.Convert(v, ft)
		if err != nil {
			return nil, errors.Trace(err)
		}

		value, err = mysql.ParseTimeFromNum(xval.(int64), tp, fsp)
		if err != nil {
			return nil, errors.Trace(err)
		}
	default:
		return nil, nil
	}

	return value, nil
}
Beispiel #25
0
// Do implements plan.Plan Do interface.
// In union plan, we should evaluate each selects from left to right, and union them according to distinct option
// Use the first select ResultFields as the final ResultFields but we should adjust its Flen for the rest Select ResultFields.
func (p *UnionPlan) Do(ctx context.Context, f plan.RowIterFunc) error {
	if len(p.Srcs) == 0 {
		return nil
	}
	t, err := memkv.CreateTemp(true)
	if err != nil {
		return err
	}

	defer func() {
		if derr := t.Drop(); derr != nil && err == nil {
			err = derr
		}
	}()
	// The final result
	var rows [][]interface{}

	// Eval the first select statement
	src := p.Srcs[0]
	src.Do(ctx, func(rid interface{}, in []interface{}) (bool, error) {
		rows = append(rows, in)
		if err := t.Set(in, []interface{}{true}); err != nil {
			return false, err
		}
		return true, nil
	})
	// Use the ResultFields of the first select statement as the final ResultFields
	rfs := src.GetFields()

	// Eval the following select statements
	for i, distinct := range p.Distincts {
		src = p.Srcs[i+1]
		// Eval src
		if len(src.GetFields()) != len(rfs) {
			return errors.New("The used SELECT statements have a different number of columns")
		}
		src.Do(ctx, func(rid interface{}, in []interface{}) (bool, error) {
			srcRfs := src.GetFields()
			for i := range in {
				// The column value should be casted as the same type of the first select statement in corresponding position
				srcRf := srcRfs[i]
				rf := rfs[i]
				/*
				 * The lengths of the columns in the UNION result take into account the values retrieved by all of the SELECT statements
				 * SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
				 * +---------------+
				 * | REPEAT('a',1) |
				 * +---------------+
				 * | a             |
				 * | bbbbbbbbbb    |
				 * +---------------+
				 */
				if srcRf.Flen > rf.Col.Flen {
					rf.Col.Flen = srcRf.Col.Flen
				}
				in[i], err = types.Convert(in[i], &rf.Col.FieldType)
				if err != nil {
					return false, err
				}
			}
			if distinct {
				// distinct union, check duplicate
				v, getErr := t.Get(in)
				if getErr != nil {
					return false, getErr
				}
				if len(v) > 0 {
					// Find duplicate, ignore it
					return true, nil
				}
			}
			rows = append(rows, in)
			if err := t.Set(in, []interface{}{true}); err != nil {
				return false, err
			}
			return true, nil
		})
	}
	var more bool
	for _, row := range rows {
		if more, err = f(nil, row); !more || err != nil {
			break
		}
	}
	return nil
}
Beispiel #26
0
func (e *Evaluator) funcDateArith(v *ast.FuncDateArithExpr) bool {
	// health check for date and interval
	nodeDate := v.Date.GetValue()
	if types.IsNil(nodeDate) {
		v.SetValue(nil)
		return true
	}
	nodeInterval := v.Interval.GetValue()
	if types.IsNil(nodeInterval) {
		v.SetValue(nil)
		return true
	}
	// parse date
	fieldType := mysql.TypeDate
	var resultField *types.FieldType
	switch x := nodeDate.(type) {
	case mysql.Time:
		if (x.Type == mysql.TypeDatetime) || (x.Type == mysql.TypeTimestamp) {
			fieldType = mysql.TypeDatetime
		}
	case string:
		if !mysql.IsDateFormat(x) {
			fieldType = mysql.TypeDatetime
		}
	case int64:
		if t, err := mysql.ParseTimeFromInt64(x); err == nil {
			if (t.Type == mysql.TypeDatetime) || (t.Type == mysql.TypeTimestamp) {
				fieldType = mysql.TypeDatetime
			}
		}
	}
	if mysql.IsClockUnit(v.Unit) {
		fieldType = mysql.TypeDatetime
	}
	resultField = types.NewFieldType(fieldType)
	resultField.Decimal = mysql.MaxFsp
	value, err := types.Convert(nodeDate, resultField)
	if err != nil {
		e.err = ErrInvalidOperation.Gen("DateArith invalid args, need date but get %T", nodeDate)
		return false
	}
	if types.IsNil(value) {
		e.err = ErrInvalidOperation.Gen("DateArith invalid args, need date but get %v", value)
		return false
	}
	result, ok := value.(mysql.Time)
	if !ok {
		e.err = ErrInvalidOperation.Gen("DateArith need time type, but got %T", value)
		return false
	}
	// parse interval
	var interval string
	if strings.ToLower(v.Unit) == "day" {
		day, err2 := parseDayInterval(nodeInterval)
		if err2 != nil {
			e.err = ErrInvalidOperation.Gen("DateArith invalid day interval, need int but got %T", nodeInterval)
			return false
		}
		interval = fmt.Sprintf("%d", day)
	} else {
		interval = fmt.Sprintf("%v", nodeInterval)
	}
	year, month, day, duration, err := mysql.ExtractTimeValue(v.Unit, interval)
	if err != nil {
		e.err = errors.Trace(err)
		return false
	}
	if v.Op == ast.DateSub {
		year, month, day, duration = -year, -month, -day, -duration
	}
	result.Time = result.Time.Add(duration)
	result.Time = result.Time.AddDate(int(year), int(month), int(day))
	if result.Time.Nanosecond() == 0 {
		result.Fsp = 0
	}
	v.SetValue(result)
	return true
}
Beispiel #27
0
func getTimeValue(ctx context.Context, v interface{}, tp byte, fsp int) (interface{}, error) {
	value := mysql.Time{
		Type: tp,
		Fsp:  fsp,
	}

	defaultTime, err := getSystemTimestamp(ctx)
	if err != nil {
		return nil, errors.Trace(err)
	}

	switch x := v.(type) {
	case string:
		upperX := strings.ToUpper(x)
		if upperX == CurrentTimestamp {
			value.Time = defaultTime
		} else if upperX == ZeroTimestamp {
			value, _ = mysql.ParseTimeFromNum(0, tp, fsp)
		} else {
			value, err = mysql.ParseTime(x, tp, fsp)
			if err != nil {
				return nil, errors.Trace(err)
			}
		}
	case *ast.ValueExpr:
		switch x.Kind() {
		case types.KindString:
			value, err = mysql.ParseTime(x.GetString(), tp, fsp)
			if err != nil {
				return nil, errors.Trace(err)
			}
		case types.KindInt64:
			value, err = mysql.ParseTimeFromNum(x.GetInt64(), tp, fsp)
			if err != nil {
				return nil, errors.Trace(err)
			}
		case types.KindNull:
			return nil, nil
		default:
			return nil, errors.Trace(errDefaultValue)
		}
	case *ast.FuncCallExpr:
		if x.FnName.L == currentTimestampL {
			return CurrentTimestamp, nil
		}
		return nil, errors.Trace(errDefaultValue)
	case *ast.UnaryOperationExpr:
		// support some expression, like `-1`
		v, err := Eval(ctx, x)
		if err != nil {
			return nil, errors.Trace(err)
		}
		ft := types.NewFieldType(mysql.TypeLonglong)
		xval, err := types.Convert(v, ft)
		if err != nil {
			return nil, errors.Trace(err)
		}

		value, err = mysql.ParseTimeFromNum(xval.(int64), tp, fsp)
		if err != nil {
			return nil, errors.Trace(err)
		}
	default:
		return nil, nil
	}

	return value, nil
}
Beispiel #28
0
// AddRecord implements table.Table AddRecord interface.
func (t *Table) AddRecord(ctx context.Context, r []interface{}) (recordID int64, err error) {
	var hasRecordID bool
	for _, col := range t.Cols() {
		if col.IsPKHandleColumn(t.meta) {
			recordID, err = types.ToInt64(r[col.Offset])
			if err != nil {
				return 0, errors.Trace(err)
			}
			hasRecordID = true
			break
		}
	}
	if !hasRecordID {
		recordID, err = t.alloc.Alloc(t.ID)
		if err != nil {
			return 0, errors.Trace(err)
		}
	}
	txn, err := ctx.GetTxn(false)
	if err != nil {
		return 0, errors.Trace(err)
	}
	bs := kv.NewBufferStore(txn)
	defer bs.Release()

	// Insert new entries into indices.
	h, err := t.addIndices(ctx, recordID, r, bs)
	if err != nil {
		return h, errors.Trace(err)
	}

	if err = t.LockRow(ctx, recordID); err != nil {
		return 0, errors.Trace(err)
	}

	// Set public and write only column value.
	for _, col := range t.writableCols() {
		if col.IsPKHandleColumn(t.meta) {
			continue
		}
		var value interface{}
		if col.State == model.StateWriteOnly || col.State == model.StateWriteReorganization {
			// if col is in write only or write reorganization state, we must add it with its default value.
			value, _, err = GetColDefaultValue(ctx, &col.ColumnInfo)
			if err != nil {
				return 0, errors.Trace(err)
			}
			value, err = types.Convert(value, &col.FieldType)
			if err != nil {
				return 0, errors.Trace(err)
			}
		} else {
			value = r[col.Offset]
		}

		key := t.RecordKey(recordID, col)
		err = t.SetColValue(txn, key, value)
		if err != nil {
			return 0, errors.Trace(err)
		}
	}

	if err = bs.SaveTo(txn); err != nil {
		return 0, errors.Trace(err)
	}

	variable.GetSessionVars(ctx).AddAffectedRows(1)
	return recordID, nil
}
Beispiel #29
0
// AddRecord implements table.Table AddRecord interface.
func (t *Table) AddRecord(ctx context.Context, r []interface{}) (recordID int64, err error) {
	id := variable.GetSessionVars(ctx).LastInsertID
	// Already have auto increment ID
	if id != 0 {
		recordID = int64(id)
	} else {
		recordID, err = t.alloc.Alloc(t.ID)
		if err != nil {
			return 0, errors.Trace(err)
		}
	}
	txn, err := ctx.GetTxn(false)
	if err != nil {
		return 0, errors.Trace(err)
	}
	for _, v := range t.indices {
		if v == nil || v.State == model.StateDeleteOnly || v.State == model.StateDeleteReorganization {
			// if index is in delete only or delete reorganization state, we can't add it.
			continue
		}
		colVals, _ := v.FetchValues(r)
		if err = v.X.Create(txn, colVals, recordID); err != nil {
			if terror.ErrorEqual(err, kv.ErrKeyExists) {
				// Get the duplicate row handle
				// For insert on duplicate syntax, we should update the row
				iter, _, err1 := v.X.Seek(txn, colVals)
				if err1 != nil {
					return 0, errors.Trace(err1)
				}
				_, h, err1 := iter.Next()
				if err1 != nil {
					return 0, errors.Trace(err1)
				}
				return h, errors.Trace(err)
			}
			return 0, errors.Trace(err)
		}
	}

	if err := t.LockRow(ctx, recordID); err != nil {
		return 0, errors.Trace(err)
	}

	// Set public and write only column value.
	for _, col := range t.writableCols() {
		var value interface{}
		key := t.RecordKey(recordID, col)

		if col.State == model.StateWriteOnly || col.State == model.StateWriteReorganization {
			// if col is in write only or write reorganization state, we must add it with its default value.
			value, _, err = GetColDefaultValue(ctx, &col.ColumnInfo)
			if err != nil {
				return 0, errors.Trace(err)
			}
			value, err = types.Convert(value, &col.FieldType)
			if err != nil {
				return 0, errors.Trace(err)
			}
		} else {
			value = r[col.Offset]
		}

		err = t.SetColValue(txn, key, value)
		if err != nil {
			return 0, errors.Trace(err)
		}
	}

	variable.GetSessionVars(ctx).AddAffectedRows(1)
	return recordID, nil
}
Beispiel #30
0
func (p *UnionPlan) fetchSrc(ctx context.Context, i int, t memkv.Temp) error {
	src := p.Srcs[i+1]
	distinct := p.Distincts[i]

	rfs := p.GetFields()
	if len(src.GetFields()) != len(rfs) {
		return errors.New("The used SELECT statements have a different number of columns")
	}
	for {
		row, err := src.Next(ctx)
		if row == nil || err != nil {
			return errors.Trace(err)
		}

		srcRfs := src.GetFields()
		for i := range row.Data {
			// The column value should be casted as the same type of the first select statement in corresponding position
			srcRf := srcRfs[i]
			rf := rfs[i]
			/*
			 * The lengths of the columns in the UNION result take into account the values retrieved by all of the SELECT statements
			 * SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
			 * +---------------+
			 * | REPEAT('a',1) |
			 * +---------------+
			 * | a             |
			 * | bbbbbbbbbb    |
			 * +---------------+
			 */
			if srcRf.Flen > rf.Col.Flen {
				rf.Col.Flen = srcRf.Col.Flen
			}
			if rf.Col.FieldType.Tp > 0 {
				row.Data[i], err = types.Convert(row.Data[i], &rf.Col.FieldType)
			} else {
				// First select result doesn't contain enough type information, e,g, select null union select 1.
				// We cannot get the proper data type for select null.
				// Now we just use the first correct return data types with following select.
				// TODO: Try to merge all data types for all select like select null union select 1 union select "abc"
				if tp := srcRf.Col.FieldType.Tp; tp > 0 {
					rf.Col.FieldType.Tp = tp
				}
			}

			if err != nil {
				return errors.Trace(err)
			}
		}

		if distinct {
			// distinct union, check duplicate
			v, getErr := t.Get(row.Data)
			if getErr != nil {
				return errors.Trace(getErr)
			}
			if len(v) > 0 {
				// Find duplicate, ignore it
				continue
			}
		}
		p.rows = append(p.rows, row)
		if err := t.Set(row.Data, []interface{}{true}); err != nil {
			return errors.Trace(err)
		}
	}
}