예제 #1
0
func (ts *testMemoryTableSuite) SetUpSuite(c *C) {
	driver := localstore.Driver{Driver: goleveldb.MemoryDriver{}}
	store, err := driver.Open("memory")
	c.Check(err, IsNil)
	ts.store = store
	ts.se, err = tidb.CreateSession(ts.store)
	c.Assert(err, IsNil)

	// create table
	tp1 := types.NewFieldType(mysql.TypeLong)
	col1 := &model.ColumnInfo{
		ID:        1,
		Name:      model.NewCIStr("a"),
		Offset:    0,
		FieldType: *tp1,
	}
	tp2 := types.NewFieldType(mysql.TypeVarchar)
	tp2.Flen = 255
	col2 := &model.ColumnInfo{
		ID:        2,
		Name:      model.NewCIStr("b"),
		Offset:    1,
		FieldType: *tp2,
	}

	tblInfo := &model.TableInfo{
		ID:      100,
		Name:    model.NewCIStr("t"),
		Columns: []*model.ColumnInfo{col1, col2},
	}
	alloc := autoid.NewMemoryAllocator(int64(10))
	ts.tbl, _ = tables.MemoryTableFromMeta(alloc, tblInfo)
}
예제 #2
0
파일: cast_test.go 프로젝트: ninefive/tidb
func (s *testCastSuite) TestCast(c *C) {
	f := types.NewFieldType(mysql.TypeLonglong)

	expr := &FunctionCast{
		Expr: Value{1},
		Tp:   f,
	}

	f.Flag |= mysql.UnsignedFlag
	c.Assert(len(expr.String()), Greater, 0)
	f.Flag = 0
	c.Assert(len(expr.String()), Greater, 0)
	f.Tp = mysql.TypeDatetime
	c.Assert(len(expr.String()), Greater, 0)

	f.Tp = mysql.TypeLonglong
	_, err := expr.Clone()
	c.Assert(err, IsNil)

	c.Assert(expr.IsStatic(), IsTrue)

	v, err := expr.Eval(nil, nil)
	c.Assert(err, IsNil)
	c.Assert(v, Equals, int64(1))

	f.Flag |= mysql.UnsignedFlag
	v, err = expr.Eval(nil, nil)
	c.Assert(err, IsNil)
	c.Assert(v, Equals, uint64(1))

	f.Tp = mysql.TypeString
	f.Charset = charset.CharsetBin
	v, err = expr.Eval(nil, nil)
	c.Assert(err, IsNil)
	c.Assert(v, DeepEquals, []byte("1"))

	expr.Expr = Value{nil}
	v, err = expr.Eval(nil, nil)
	c.Assert(err, IsNil)
	c.Assert(v, Equals, nil)

	expr.Expr = mockExpr{err: errors.New("must error")}
	_, err = expr.Clone()
	c.Assert(err, NotNil)

	_, err = expr.Eval(nil, nil)
	c.Assert(err, NotNil)

	// For String()
	f = types.NewFieldType(mysql.TypeLonglong)
	expr = &FunctionCast{
		Expr: Value{1},
		Tp:   f,
	}
	str := expr.String()
	c.Assert(str, Equals, "CAST(1 AS SIGNED)")
	expr.IsConvert = true
	str = expr.String()
	c.Assert(str, Equals, "CONVERT(1, SIGNED)")
}
예제 #3
0
파일: planbuilder.go 프로젝트: pingcap/tidb
func (b *planBuilder) buildExplain(explain *ast.ExplainStmt) Plan {
	if show, ok := explain.Stmt.(*ast.ShowStmt); ok {
		return b.buildShow(show)
	}
	targetPlan, err := Optimize(b.ctx, explain.Stmt, b.is)
	if err != nil {
		b.err = errors.Trace(err)
		return nil
	}
	p := &Explain{StmtPlan: targetPlan}
	addChild(p, targetPlan)
	schema := make(expression.Schema, 0, 3)
	schema = append(schema, &expression.Column{
		ColName: model.NewCIStr("ID"),
		RetType: types.NewFieldType(mysql.TypeString),
	})
	schema = append(schema, &expression.Column{
		ColName: model.NewCIStr("Json"),
		RetType: types.NewFieldType(mysql.TypeString),
	})
	schema = append(schema, &expression.Column{
		ColName: model.NewCIStr("ParentID"),
		RetType: types.NewFieldType(mysql.TypeString),
	})
	p.SetSchema(schema)
	return p
}
예제 #4
0
func (v *typeInferrer) aggregateFunc(x *ast.AggregateFuncExpr) {
	name := strings.ToLower(x.F)
	switch name {
	case ast.AggFuncCount:
		ft := types.NewFieldType(mysql.TypeLonglong)
		ft.Flen = 21
		ft.Charset = charset.CharsetBin
		ft.Collate = charset.CollationBin
		x.SetType(ft)
	case ast.AggFuncMax, ast.AggFuncMin:
		x.SetType(x.Args[0].GetType())
	case ast.AggFuncSum, ast.AggFuncAvg:
		ft := types.NewFieldType(mysql.TypeNewDecimal)
		ft.Charset = charset.CharsetBin
		ft.Collate = charset.CollationBin
		x.SetType(ft)
	case ast.AggFuncGroupConcat:
		ft := types.NewFieldType(mysql.TypeVarString)
		ft.Charset = v.defaultCharset
		cln, err := charset.GetDefaultCollation(v.defaultCharset)
		if err != nil {
			v.err = err
		}
		ft.Collate = cln
		x.SetType(ft)
	}
}
예제 #5
0
파일: field_test.go 프로젝트: lovedboy/tidb
func (*testFieldSuite) TestField(c *C) {
	f := &field.Field{
		Expr:   expression.Value{Val: "c1+1"},
		AsName: "a",
	}
	s := f.String()
	c.Assert(len(s), Greater, 0)

	ft := types.NewFieldType(mysql.TypeLong)
	ft.Flen = 20
	ft.Flag |= mysql.UnsignedFlag | mysql.ZerofillFlag
	c.Assert(ft.String(), Equals, "int(20) UNSIGNED ZEROFILL")

	ft = types.NewFieldType(mysql.TypeFloat)
	ft.Flen = 20
	ft.Decimal = 10
	c.Assert(ft.String(), Equals, "float(20,10)")

	ft = types.NewFieldType(mysql.TypeTimestamp)
	ft.Decimal = 8
	c.Assert(ft.String(), Equals, "timestamp(8)")

	ft = types.NewFieldType(mysql.TypeVarchar)
	ft.Flag |= mysql.BinaryFlag
	ft.Charset = "utf8"
	ft.Collate = "utf8_unicode_gi"
	c.Assert(ft.String(), Equals, "varchar BINARY CHARACTER SET utf8 COLLATE utf8_unicode_gi")
}
예제 #6
0
func (p *physicalTableSource) addAggregation(agg *PhysicalAggregation) expression.Schema {
	if p.client == nil {
		return nil
	}
	for _, f := range agg.AggFuncs {
		pb := aggFuncToPBExpr(p.client, f)
		if pb == nil {
			p.clear()
			return nil
		}
		p.AggFuncs = append(p.AggFuncs, pb)
	}
	for _, item := range agg.GroupByItems {
		pb := groupByItemToPB(p.client, item)
		if pb == nil {
			p.clear()
			return nil
		}
		p.GbyItems = append(p.GbyItems, pb)
	}
	p.Aggregated = true
	gk := types.NewFieldType(mysql.TypeBlob)
	gk.Charset = charset.CharsetBin
	gk.Collate = charset.CollationBin
	p.AggFields = append(p.AggFields, gk)
	var schema expression.Schema
	cursor := 0
	schema = append(schema, &expression.Column{Index: cursor, ColName: model.NewCIStr(fmt.Sprint(agg.GroupByItems))})
	agg.GroupByItems = []expression.Expression{schema[cursor]}
	newAggFuncs := make([]expression.AggregationFunction, len(agg.AggFuncs))
	for i, aggFun := range agg.AggFuncs {
		fun := expression.NewAggFunction(aggFun.GetName(), nil, false)
		var args []expression.Expression
		colName := model.NewCIStr(fmt.Sprint(aggFun.GetArgs()))
		if needCount(fun) {
			cursor++
			schema = append(schema, &expression.Column{Index: cursor, ColName: colName})
			args = append(args, schema[cursor])
			ft := types.NewFieldType(mysql.TypeLonglong)
			ft.Flen = 21
			ft.Charset = charset.CharsetBin
			ft.Collate = charset.CollationBin
			p.AggFields = append(p.AggFields, ft)
		}
		if needValue(fun) {
			cursor++
			schema = append(schema, &expression.Column{Index: cursor, ColName: colName})
			args = append(args, schema[cursor])
			p.AggFields = append(p.AggFields, agg.schema[i].GetType())
		}
		fun.SetArgs(args)
		fun.SetMode(expression.FinalMode)
		newAggFuncs[i] = fun
	}
	agg.AggFuncs = newAggFuncs
	return schema
}
예제 #7
0
파일: alter_test.go 프로젝트: lovedboy/tidb
func (s *testDDLSuite) TestAlterSpecification(c *C) {
	tbl := []*AlterSpecification{
		{
			Action: AlterTableOpt,
		},
		{
			Action: AlterDropColumn,
			Name:   "c1",
		},
		{Action: AlterDropPrimaryKey},
		{Action: AlterDropForeignKey,
			Name: "c"},
		{Action: AlterDropIndex,
			Name: "index_c"},
		{Action: AlterAddConstr,
			Constraint: nil},
		{Action: AlterAddConstr,
			Constraint: &coldef.TableConstraint{
				Tp: coldef.ConstrPrimaryKey,
				Keys: []*coldef.IndexColName{
					{
						ColumnName: "a",
						Length:     10,
					},
				},
			}},
		{Action: AlterAddColumn,
			Column: &coldef.ColumnDef{
				Name: "c",
				Tp:   types.NewFieldType(mysql.TypeLong),
			},
			Position: &ColumnPosition{}},
		{Action: AlterAddColumn,
			Column: &coldef.ColumnDef{
				Name: "c",
				Tp:   types.NewFieldType(mysql.TypeLong),
			},
			Position: &ColumnPosition{Type: ColumnPositionFirst}},
		{Action: AlterAddColumn,
			Column: &coldef.ColumnDef{
				Name: "c",
				Tp:   types.NewFieldType(mysql.TypeLong),
			},
			Position: &ColumnPosition{Type: ColumnPositionAfter,
				RelativeColumn: "c"}},

		// Invalid action returns empty string
		{Action: -1},
	}

	for _, spec := range tbl {
		c.Assert(len(spec.String()), GreaterEqual, 0)
	}
}
예제 #8
0
func (v *typeInferrer) handleFuncCallExpr(x *ast.FuncCallExpr) {
	var (
		tp  *types.FieldType
		chs = charset.CharsetBin
	)
	switch x.FnName.L {
	case "abs", "ifnull", "nullif":
		tp = x.Args[0].GetType()
	case "pow", "power", "rand":
		tp = types.NewFieldType(mysql.TypeDouble)
	case "curdate", "current_date", "date":
		tp = types.NewFieldType(mysql.TypeDate)
	case "curtime", "current_time":
		tp = types.NewFieldType(mysql.TypeDuration)
		tp.Decimal = v.getFsp(x)
	case "current_timestamp":
		tp = types.NewFieldType(mysql.TypeDatetime)
	case "microsecond", "second", "minute", "hour", "day", "week", "month", "year",
		"dayofweek", "dayofmonth", "dayofyear", "weekday", "weekofyear", "yearweek",
		"found_rows", "length":
		tp = types.NewFieldType(mysql.TypeLonglong)
	case "now", "sysdate":
		tp = types.NewFieldType(mysql.TypeDatetime)
		tp.Decimal = v.getFsp(x)
	case "dayname", "version", "database", "user", "current_user",
		"concat", "concat_ws", "left", "lower", "repeat", "replace", "upper":
		tp = types.NewFieldType(mysql.TypeVarString)
		chs = v.defaultCharset
	case "connection_id":
		tp = types.NewFieldType(mysql.TypeLonglong)
		tp.Flag |= mysql.UnsignedFlag
	case "if":
		// TODO: fix this
		// See: https://dev.mysql.com/doc/refman/5.5/en/control-flow-functions.html#function_if
		// The default return type of IF() (which may matter when it is stored into a temporary table) is calculated as follows.
		// Expression	Return Value
		// expr2 or expr3 returns a string	string
		// expr2 or expr3 returns a floating-point value	floating-point
		// expr2 or expr3 returns an integer	integer
		tp = x.Args[1].GetType()
	default:
		tp = types.NewFieldType(mysql.TypeUnspecified)
	}
	// If charset is unspecified.
	if len(tp.Charset) == 0 {
		tp.Charset = chs
		cln := charset.CollationBin
		if chs != charset.CharsetBin {
			var err error
			cln, err = charset.GetDefaultCollation(chs)
			if err != nil {
				v.err = err
			}
		}
		tp.Collate = cln
	}
	x.SetType(tp)
}
예제 #9
0
파일: expressions.go 프로젝트: yzl11/vessel
// NewValueExpr creates a ValueExpr with value, and sets default field type.
func NewValueExpr(value interface{}) *ValueExpr {
	ve := &ValueExpr{}
	ve.Data = types.RawData(value)
	// TODO: make it more precise.
	switch value.(type) {
	case nil:
		ve.Type = types.NewFieldType(mysql.TypeNull)
	case bool, int64:
		ve.Type = types.NewFieldType(mysql.TypeLonglong)
	case uint64:
		ve.Type = types.NewFieldType(mysql.TypeLonglong)
		ve.Type.Flag |= mysql.UnsignedFlag
	case string, UnquoteString:
		ve.Type = types.NewFieldType(mysql.TypeVarchar)
		ve.Type.Charset = mysql.DefaultCharset
		ve.Type.Collate = mysql.DefaultCollationName
	case float64:
		ve.Type = types.NewFieldType(mysql.TypeDouble)
	case []byte:
		ve.Type = types.NewFieldType(mysql.TypeBlob)
		ve.Type.Charset = "binary"
		ve.Type.Collate = "binary"
	case mysql.Bit:
		ve.Type = types.NewFieldType(mysql.TypeBit)
	case mysql.Hex:
		ve.Type = types.NewFieldType(mysql.TypeVarchar)
		ve.Type.Charset = "binary"
		ve.Type.Collate = "binary"
	case *types.DataItem:
		ve.Type = value.(*types.DataItem).Type
	default:
		panic(fmt.Sprintf("illegal literal value type:%T", value))
	}
	return ve
}
예제 #10
0
func (b *planBuilder) buildApply(p, inner LogicalPlan, schema expression.Schema, checker *ApplyConditionChecker) LogicalPlan {
	ap := &Apply{
		InnerPlan:       inner,
		OuterSchema:     schema,
		Checker:         checker,
		baseLogicalPlan: newBaseLogicalPlan(App, b.allocator),
	}
	ap.initID()
	addChild(ap, p)
	innerSchema := inner.GetSchema().DeepCopy()
	if checker == nil {
		for _, col := range innerSchema {
			col.IsAggOrSubq = true
		}
		ap.SetSchema(append(p.GetSchema().DeepCopy(), innerSchema...))
	} else {
		ap.SetSchema(append(p.GetSchema().DeepCopy(), &expression.Column{
			FromID:      ap.id,
			ColName:     model.NewCIStr("exists_row"),
			RetType:     types.NewFieldType(mysql.TypeTiny),
			IsAggOrSubq: true,
		}))
	}
	ap.correlated = p.IsCorrelated()
	return ap
}
예제 #11
0
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)
}
예제 #12
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
}
예제 #13
0
파일: aggregation.go 프로젝트: pingcap/tidb
// GetType implements AggregationFunction interface.
func (af *avgFunction) GetType() *types.FieldType {
	ft := types.NewFieldType(mysql.TypeNewDecimal)
	ft.Charset = charset.CharsetBin
	ft.Collate = charset.CollationBin
	ft.Decimal = af.Args[0].GetType().Decimal
	return ft
}
예제 #14
0
파일: aggregation.go 프로젝트: pingcap/tidb
// GetType implements AggregationFunction interface.
func (cf *countFunction) GetType() *types.FieldType {
	ft := types.NewFieldType(mysql.TypeLonglong)
	ft.Flen = 21
	ft.Charset = charset.CharsetBin
	ft.Collate = charset.CollationBin
	return ft
}
예제 #15
0
func (b *planBuilder) buildExists(p LogicalPlan) LogicalPlan {
out:
	for {
		switch p.(type) {
		// This can be removed when in exists clause,
		// e.g. exists(select count(*) from t order by a) is equal to exists t.
		case *Trim, *Projection, *Sort, *Aggregation:
			p = p.GetChildByIndex(0).(LogicalPlan)
			p.SetParents()
		default:
			break out
		}
	}
	exists := &Exists{baseLogicalPlan: newBaseLogicalPlan(Ext, b.allocator)}
	exists.self = exists
	exists.initID()
	addChild(exists, p)
	newCol := &expression.Column{
		FromID:  exists.id,
		RetType: types.NewFieldType(mysql.TypeTiny),
		ColName: model.NewCIStr("exists_col")}
	exists.SetSchema([]*expression.Column{newCol})
	exists.correlated = p.IsCorrelated()
	return exists
}
예제 #16
0
// buildApply builds apply plan with outerPlan and innerPlan. Everytime we fetch a record from outerPlan and apply it to
// innerPlan. This way is the so-called correlated execution.
func (b *planBuilder) buildApply(outerPlan, innerPlan LogicalPlan, checker *ApplyConditionChecker) LogicalPlan {
	ap := &Apply{
		Checker:         checker,
		baseLogicalPlan: newBaseLogicalPlan(App, b.allocator),
	}
	ap.self = ap
	ap.initIDAndContext(b.ctx)
	addChild(ap, outerPlan)
	addChild(ap, innerPlan)
	corColumns := innerPlan.extractCorrelatedCols()
	ap.correlated = outerPlan.IsCorrelated()
	for _, corCol := range corColumns {
		// If the outer column can't be resolved from this outer schema, it should be resolved by outer schema.
		if idx := outerPlan.GetSchema().GetIndex(&corCol.Column); idx == -1 {
			ap.correlated = true
			break
		}
	}
	innerSchema := innerPlan.GetSchema().Clone()
	if checker == nil {
		for _, col := range innerSchema {
			col.IsAggOrSubq = true
		}
		ap.SetSchema(append(outerPlan.GetSchema().Clone(), innerSchema...))
	} else {
		ap.SetSchema(append(outerPlan.GetSchema().Clone(), &expression.Column{
			FromID:      ap.id,
			ColName:     model.NewCIStr("exists_row"),
			RetType:     types.NewFieldType(mysql.TypeTiny),
			IsAggOrSubq: true,
		}))
	}
	return ap
}
예제 #17
0
func (b *planBuilder) buildExplain(explain *ast.ExplainStmt) Plan {
	if show, ok := explain.Stmt.(*ast.ShowStmt); ok {
		return b.buildShow(show)
	}
	targetPlan := b.build(explain.Stmt)
	if b.err != nil {
		return nil
	}
	if logic, ok := targetPlan.(LogicalPlan); ok {
		var err error
		_, logic, err = logic.PredicatePushDown(nil)
		if err != nil {
			b.err = errors.Trace(err)
			return nil
		}
		_, err = logic.PruneColumnsAndResolveIndices(logic.GetSchema())
		if err != nil {
			b.err = errors.Trace(err)
			return nil
		}
		_, res, _, err := logic.convert2PhysicalPlan(nil)
		if err != nil {
			b.err = errors.Trace(err)
			return nil
		}
		targetPlan = res.p.PushLimit(nil)
	}
	p := &Explain{StmtPlan: targetPlan}
	addChild(p, targetPlan)
	col := &expression.Column{
		RetType: types.NewFieldType(mysql.TypeString),
	}
	p.SetSchema([]*expression.Column{col, col})
	return p
}
예제 #18
0
파일: typeinferer.go 프로젝트: losas/tidb
func (v *typeInferrer) aggregateFunc(x *ast.AggregateFuncExpr) {
	name := strings.ToLower(x.F)
	switch name {
	case "count":
		ft := types.NewFieldType(mysql.TypeLonglong)
		ft.Flen = 21
		ft.Charset = charset.CharsetBin
		ft.Collate = charset.CollationBin
		x.SetType(ft)
	case "sum":
		ft := types.NewFieldType(mysql.TypeNewDecimal)
		ft.Charset = charset.CharsetBin
		ft.Collate = charset.CollationBin
		x.SetType(ft)
	}
}
예제 #19
0
// See http://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_unhex
func builtinUnHex(args []types.Datum, ctx context.Context) (d types.Datum, err error) {
	switch args[0].Kind() {
	case types.KindNull:
		return d, nil
	case types.KindString:
		x, err := args[0].ToString()
		if err != nil {
			return d, errors.Trace(err)
		}
		bytes, err := hex.DecodeString(x)
		if err != nil {
			return d, nil
		}
		d.SetString(string(bytes))
		return d, nil
	case types.KindInt64, types.KindUint64, types.KindMysqlHex, types.KindFloat32, types.KindFloat64, types.KindMysqlDecimal:
		x, _ := args[0].Cast(ctx.GetSessionVars().StmtCtx, types.NewFieldType(mysql.TypeString))
		if x.IsNull() {
			return d, nil
		}
		bytes, err := hex.DecodeString(x.GetString())
		if err != nil {
			return d, nil
		}
		d.SetString(string(bytes))
		return d, nil
	default:
		return d, errors.Errorf("Unhex invalid args, need int or string but get %T", args[0].GetValue())
	}
}
예제 #20
0
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_extract
func builtinExtract(args []types.Datum, _ context.Context) (d types.Datum, err error) {
	unit := args[0].GetString()
	vd := args[1]

	if vd.Kind() == types.KindNull {
		d.SetNull()
		return d, nil
	}

	f := types.NewFieldType(mysql.TypeDatetime)
	f.Decimal = mysql.MaxFsp
	val, err := vd.ConvertTo(f)
	if err != nil {
		d.SetNull()
		return d, errors.Trace(err)
	}
	if val.Kind() == types.KindNull {
		d.SetNull()
		return d, nil
	}

	if val.Kind() != types.KindMysqlTime {
		err = errors.Errorf("need time type, but got %T", val)
		d.SetNull()
		return d, err
	}
	t := val.GetMysqlTime()
	n, err1 := mysql.ExtractTimeNum(unit, t)
	if err1 != nil {
		d.SetNull()
		return d, errors.Trace(err1)
	}
	d.SetInt64(n)
	return d, nil
}
예제 #21
0
파일: evaluator.go 프로젝트: mrtoms/tidb
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
}
예제 #22
0
func (s *testEvaluatorSuite) TestCast(c *C) {
	f := types.NewFieldType(mysql.TypeLonglong)

	expr := &ast.FuncCastExpr{
		Expr: ast.NewValueExpr(1),
		Tp:   f,
	}
	ctx := mock.NewContext()
	v, err := Eval(ctx, expr)
	c.Assert(err, IsNil)
	c.Assert(v, Equals, int64(1))

	f.Flag |= mysql.UnsignedFlag
	v, err = Eval(ctx, expr)
	c.Assert(err, IsNil)
	c.Assert(v, Equals, uint64(1))

	f.Tp = mysql.TypeString
	f.Charset = charset.CharsetBin
	v, err = Eval(ctx, expr)
	c.Assert(err, IsNil)
	c.Assert(v, DeepEquals, []byte("1"))

	f.Tp = mysql.TypeString
	f.Charset = "utf8"
	v, err = Eval(ctx, expr)
	c.Assert(err, IsNil)
	c.Assert(v, DeepEquals, "1")

	expr.Expr = ast.NewValueExpr(nil)
	v, err = Eval(ctx, expr)
	c.Assert(err, IsNil)
	c.Assert(v, IsNil)
}
예제 #23
0
파일: typeinferer.go 프로젝트: pingcap/tidb
// regexp expression expects the target expression and pattern to be a string, if it's not, we add a cast function.
func (v *typeInferrer) handleRegexpExpr(x *ast.PatternRegexpExpr) {
	x.SetType(types.NewFieldType(mysql.TypeLonglong))
	x.Type.Charset = charset.CharsetBin
	x.Type.Collate = charset.CollationBin
	x.Expr = v.addCastToString(x.Expr)
	x.Pattern = v.addCastToString(x.Pattern)
}
예제 #24
0
파일: extract.go 프로젝트: Brian110/tidb
// 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
}
예제 #25
0
func (b *planBuilder) buildSemiJoin(outerPlan, innerPlan LogicalPlan, onCondition []expression.Expression, asScalar bool, not bool) LogicalPlan {
	joinPlan := &Join{baseLogicalPlan: newBaseLogicalPlan(Jn, b.allocator)}
	joinPlan.initID()
	joinPlan.correlated = outerPlan.IsCorrelated() || innerPlan.IsCorrelated()
	for _, expr := range onCondition {
		joinPlan.correlated = joinPlan.correlated || tryDecorrelated(expr, outerPlan)
	}
	eqCond, leftCond, rightCond, otherCond := extractOnCondition(onCondition, outerPlan, innerPlan)
	joinPlan.EqualConditions = eqCond
	joinPlan.LeftConditions = leftCond
	joinPlan.RightConditions = rightCond
	joinPlan.OtherConditions = otherCond
	if asScalar {
		joinPlan.SetSchema(append(outerPlan.GetSchema().DeepCopy(), &expression.Column{
			FromID:      joinPlan.id,
			ColName:     model.NewCIStr(fmt.Sprintf("%s_aux_0", joinPlan.id)),
			RetType:     types.NewFieldType(mysql.TypeTiny),
			IsAggOrSubq: true,
		}))
		joinPlan.JoinType = SemiJoinWithAux
	} else {
		joinPlan.SetSchema(outerPlan.GetSchema().DeepCopy())
		joinPlan.JoinType = SemiJoin
	}
	joinPlan.anti = not
	joinPlan.SetChildren(outerPlan, innerPlan)
	outerPlan.SetParents(joinPlan)
	innerPlan.SetParents(joinPlan)
	return joinPlan
}
예제 #26
0
파일: new_builder.go 프로젝트: c4pt0r/tidb
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
}
예제 #27
0
파일: conversion.go 프로젝트: npk/tidb
// 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)
}
예제 #28
0
func (v *typeInferrer) handleFuncCallExpr(x *ast.FuncCallExpr) {
	var (
		tp  *types.FieldType
		chs = charset.CharsetBin
	)
	switch x.FnName.L {
	case "abs", "ifnull", "nullif":
		tp = x.Args[0].GetType()
	case "pow", "power", "rand":
		tp = types.NewFieldType(mysql.TypeDouble)
	case "curdate", "current_date", "date":
		tp = types.NewFieldType(mysql.TypeDate)
	case "curtime", "current_time":
		tp = types.NewFieldType(mysql.TypeDuration)
		tp.Decimal = v.getFsp(x)
	case "current_timestamp":
		tp = types.NewFieldType(mysql.TypeDatetime)
	case "microsecond", "second", "minute", "hour", "day", "week", "month", "year",
		"dayofweek", "dayofmonth", "dayofyear", "weekday", "weekofyear", "yearweek",
		"found_rows", "length":
		tp = types.NewFieldType(mysql.TypeLonglong)
	case "now", "sysdate":
		tp = types.NewFieldType(mysql.TypeDatetime)
		tp.Decimal = v.getFsp(x)
	case "dayname", "version", "database", "user", "current_user",
		"concat", "concat_ws", "left", "lower", "repeat", "replace", "upper":
		tp = types.NewFieldType(mysql.TypeVarString)
		chs = v.defaultCharset
	case "connection_id":
		tp = types.NewFieldType(mysql.TypeLonglong)
		tp.Flag |= mysql.UnsignedFlag
	case "if":
		tp = x.Args[1].GetType()
	default:
		tp = types.NewFieldType(mysql.TypeUnspecified)
	}
	// If charset is unspecified.
	if len(tp.Charset) == 0 {
		tp.Charset = chs
		cln := charset.CollationBin
		if chs != charset.CharsetBin {
			var err error
			cln, err = charset.GetDefaultCollation(chs)
			if err != nil {
				v.err = err
			}
		}
		tp.Collate = cln
	}
	x.SetType(tp)
}
예제 #29
0
func getRowArg(e expression.Expression, idx int) expression.Expression {
	if f, ok := e.(*expression.ScalarFunction); ok {
		return f.Args[idx]
	}
	c, _ := e.(*expression.Constant)
	d := c.Value.GetRow()[idx]
	return &expression.Constant{Value: d, RetType: types.NewFieldType(d.Kind())}
}
예제 #30
0
func (b *planBuilder) buildExists(p Plan) Plan {
	exists := &Exists{}
	exists.id = b.allocID(exists)
	addChild(exists, p)
	newCol := &expression.Column{FromID: exists.id, RetType: types.NewFieldType(mysql.TypeTiny), ColName: model.NewCIStr("exists_col")}
	exists.SetSchema([]*expression.Column{newCol})
	exists.correlated = p.IsCorrelated()
	return exists
}