Пример #1
0
func (s *testValidatorSuite) TestValidator(c *C) {
	cases := []struct {
		sql       string
		inPrepare bool
		err       error
	}{
		{"select ?", false, parser.ErrSyntax},
		{"select ?", true, nil},
		{"create table t(id int not null auto_increment default 2, key (id))", true,
			errors.New("Invalid default value for 'id'")},
		{"create table t(id int not null default 2 auto_increment, key (id))", true,
			errors.New("Invalid default value for 'id'")},
		{"create table t(id int not null auto_increment)", true,
			errors.New("Incorrect table definition; there can be only one auto column and it must be defined as a key")},
		{"create table t(id int not null auto_increment, c int auto_increment, key (id, c))", true,
			errors.New("Incorrect table definition; there can be only one auto column and it must be defined as a key")},
		{"create table t(id int not null auto_increment, c int, key (c, id))", true,
			errors.New("Incorrect table definition; there can be only one auto column and it must be defined as a key")},
		{"create table t(id decimal auto_increment, key (id))", true,
			errors.New("Incorrect column specifier for column 'id'")},
		{"create table t(id float auto_increment, key (id))", true, nil},
	}
	store, err := tidb.NewStore(tidb.EngineGoLevelDBMemory)
	c.Assert(err, IsNil)
	se, err := tidb.CreateSession(store)
	c.Assert(err, IsNil)
	for _, ca := range cases {
		stmts, err1 := tidb.Parse(se.(context.Context), ca.sql)
		c.Assert(err1, IsNil)
		c.Assert(stmts, HasLen, 1)
		stmt := stmts[0]
		err = optimizer.Validate(stmt, ca.inPrepare)
		c.Assert(terror.ErrorEqual(err, ca.err), IsTrue)
	}
}
Пример #2
0
func (ts *testTypeInferrerSuite) TestInterType(c *C) {
	store, err := tidb.NewStore(tidb.EngineGoLevelDBMemory)
	c.Assert(err, IsNil)
	defer store.Close()
	testKit := testkit.NewTestKit(c, store)
	testKit.MustExec("use test")
	testKit.MustExec("create table t (c1 int, c2 double, c3 text)")
	cases := []struct {
		expr string
		tp   byte
	}{
		{"c1", mysql.TypeLong},
		{"+1", mysql.TypeLonglong},
		{"-1", mysql.TypeLonglong},
		{"-'1'", mysql.TypeDouble},
		{"~1", mysql.TypeLonglong},
		{"!true", mysql.TypeLonglong},

		{"c1 is true", mysql.TypeLonglong},
		{"c2 is null", mysql.TypeLonglong},
		{"cast(1 as decimal)", mysql.TypeNewDecimal},

		{"1 and 1", mysql.TypeLonglong},
		{"1 or 1", mysql.TypeLonglong},
		{"1 xor 1", mysql.TypeLonglong},

		{"'1' & 2", mysql.TypeLonglong},
		{"'1' | 2", mysql.TypeLonglong},
		{"'1' ^ 2", mysql.TypeLonglong},
		{"'1' << 1", mysql.TypeLonglong},
		{"'1' >> 1", mysql.TypeLonglong},

		{"1 + '1'", mysql.TypeDouble},
		{"1 + 1.1", mysql.TypeNewDecimal},
		{"1 div 2", mysql.TypeLonglong},

		{"1 > any (select 1)", mysql.TypeLonglong},
		{"exists (select 1)", mysql.TypeLonglong},
		{"1 in (2, 3)", mysql.TypeLonglong},
		{"'abc' like 'abc'", mysql.TypeLonglong},
		{"'abc' rlike 'abc'", mysql.TypeLonglong},
		{"(1+1)", mysql.TypeLonglong},
	}
	for _, ca := range cases {
		ctx := testKit.Se.(context.Context)
		stmts, err := tidb.Parse(ctx, "select "+ca.expr+" from t")
		c.Assert(err, IsNil)
		c.Assert(stmts, HasLen, 1)
		stmt := stmts[0].(*ast.SelectStmt)
		is := sessionctx.GetDomain(ctx).InfoSchema()
		err = optimizer.ResolveName(stmt, is, ctx)
		c.Assert(err, IsNil)
		optimizer.InferType(stmt)
		tp := stmt.GetResultFields()[0].Column.Tp
		c.Assert(tp, Equals, ca.tp, Commentf("for %s", ca.expr))
	}
}
Пример #3
0
func (s *testValidatorSuite) TestValidator(c *C) {
	defer testleak.AfterTest(c)()
	cases := []struct {
		sql       string
		inPrepare bool
		err       error
	}{
		{"select ?", false, parser.ErrSyntax},
		{"select ?", true, nil},
		{"create table t(id int not null auto_increment default 2, key (id))", true,
			errors.New("Invalid default value for 'id'")},
		{"create table t(id int not null default 2 auto_increment, key (id))", true,
			errors.New("Invalid default value for 'id'")},
		{"create table t(id int not null auto_increment)", true,
			errors.New("Incorrect table definition; there can be only one auto column and it must be defined as a key")},
		{"create table t(id int not null auto_increment, c int auto_increment, key (id, c))", true,
			errors.New("Incorrect table definition; there can be only one auto column and it must be defined as a key")},
		{"create table t(id int not null auto_increment, c int, key (c, id))", true,
			errors.New("Incorrect table definition; there can be only one auto column and it must be defined as a key")},
		{"create table t(id decimal auto_increment, key (id))", true,
			errors.New("Incorrect column specifier for column 'id'")},
		{"create table t(id float auto_increment, key (id))", true, nil},
		{"create table t(id int auto_increment) ENGINE=MYISAM", true, nil},
		{"create table t(a int primary key, b int, c varchar(10), d char(256));", true, errors.New("Column length too big for column 'd' (max = 255); use BLOB or TEXT instead")},
		{"create index ib on t(b,a,b);", true, errors.New("Duplicate column name 'b'")},
		{"create table t(c1 int not null primary key, c2 int not null primary key)", true, errors.New("Multiple primary key defined")},
	}
	store, err := tidb.NewStore(tidb.EngineGoLevelDBMemory)
	c.Assert(err, IsNil)
	defer store.Close()
	se, err := tidb.CreateSession(store)
	c.Assert(err, IsNil)
	for _, ca := range cases {
		stmts, err1 := tidb.Parse(se.(context.Context), ca.sql)
		c.Assert(err1, IsNil)
		c.Assert(stmts, HasLen, 1)
		stmt := stmts[0]
		err = plan.Validate(stmt, ca.inPrepare)
		c.Assert(terror.ErrorEqual(err, ca.err), IsTrue)
	}
}
Пример #4
0
func (s *testValidatorSuite) TestValidator(c *C) {
	cases := []struct {
		sql       string
		inPrepare bool
		err       error
	}{
		{"select ?", false, parser.ErrSyntax},
		{"select ?", true, nil},
	}
	store, err := tidb.NewStore(tidb.EngineGoLevelDBMemory)
	c.Assert(err, IsNil)
	se, err := tidb.CreateSession(store)
	c.Assert(err, IsNil)
	for _, ca := range cases {
		stmts, err1 := tidb.Parse(se.(context.Context), ca.sql)
		c.Assert(err1, IsNil)
		c.Assert(stmts, HasLen, 1)
		stmt := stmts[0]
		err = optimizer.Validate(stmt, ca.inPrepare)
		c.Assert(terror.ErrorEqual(err, ca.err), IsTrue)
	}
}
Пример #5
0
func (ts *testTypeInferrerSuite) TestInferType(c *C) {
	store, err := tidb.NewStore(tidb.EngineGoLevelDBMemory)
	c.Assert(err, IsNil)
	defer store.Close()
	testKit := testkit.NewTestKit(c, store)
	testKit.MustExec("use test")
	testKit.MustExec("create table t (c1 int, c2 double, c3 text)")
	cases := []struct {
		expr string
		tp   byte
		chs  string
	}{
		{"c1", mysql.TypeLong, charset.CharsetBin},
		{"+1", mysql.TypeLonglong, charset.CharsetBin},
		{"-1", mysql.TypeLonglong, charset.CharsetBin},
		{"-'1'", mysql.TypeDouble, charset.CharsetBin},
		{"~1", mysql.TypeLonglong, charset.CharsetBin},
		{"!true", mysql.TypeLonglong, charset.CharsetBin},

		{"c1 is true", mysql.TypeLonglong, charset.CharsetBin},
		{"c2 is null", mysql.TypeLonglong, charset.CharsetBin},
		{"isnull(1/0)", mysql.TypeLonglong, charset.CharsetBin},
		{"cast(1 as decimal)", mysql.TypeNewDecimal, charset.CharsetBin},

		{"1 and 1", mysql.TypeLonglong, charset.CharsetBin},
		{"1 or 1", mysql.TypeLonglong, charset.CharsetBin},
		{"1 xor 1", mysql.TypeLonglong, charset.CharsetBin},

		{"'1' & 2", mysql.TypeLonglong, charset.CharsetBin},
		{"'1' | 2", mysql.TypeLonglong, charset.CharsetBin},
		{"'1' ^ 2", mysql.TypeLonglong, charset.CharsetBin},
		{"'1' << 1", mysql.TypeLonglong, charset.CharsetBin},
		{"'1' >> 1", mysql.TypeLonglong, charset.CharsetBin},

		{"1 + '1'", mysql.TypeDouble, charset.CharsetBin},
		{"1 + 1.1", mysql.TypeNewDecimal, charset.CharsetBin},
		{"1 div 2", mysql.TypeLonglong, charset.CharsetBin},
		{"1 / 2", mysql.TypeNewDecimal, charset.CharsetBin},

		{"1 > any (select 1)", mysql.TypeLonglong, charset.CharsetBin},
		{"exists (select 1)", mysql.TypeLonglong, charset.CharsetBin},
		{"1 in (2, 3)", mysql.TypeLonglong, charset.CharsetBin},
		{"'abc' like 'abc'", mysql.TypeLonglong, charset.CharsetBin},
		{"'abc' rlike 'abc'", mysql.TypeLonglong, charset.CharsetBin},
		{"(1+1)", mysql.TypeLonglong, charset.CharsetBin},

		// Functions
		{"version()", mysql.TypeVarString, "utf8"},
		{"count(c1)", mysql.TypeLonglong, charset.CharsetBin},
		{"abs(1)", mysql.TypeLonglong, charset.CharsetBin},
		{"abs(1.1)", mysql.TypeNewDecimal, charset.CharsetBin},
		{"abs(cast(\"20150817015609\" as DATETIME))", mysql.TypeDouble, charset.CharsetBin},
		{"IF(1>2,2,3)", mysql.TypeLonglong, charset.CharsetBin},
		{"IFNULL(1,0)", mysql.TypeLonglong, charset.CharsetBin},
		{"POW(2,2)", mysql.TypeDouble, charset.CharsetBin},
		{"POWER(2,2)", mysql.TypeDouble, charset.CharsetBin},
		{"rand()", mysql.TypeDouble, charset.CharsetBin},
		{"curdate()", mysql.TypeDate, charset.CharsetBin},
		{"current_date()", mysql.TypeDate, charset.CharsetBin},
		{"DATE('2003-12-31 01:02:03')", mysql.TypeDate, charset.CharsetBin},
		{"curtime()", mysql.TypeDuration, charset.CharsetBin},
		{"current_time()", mysql.TypeDuration, charset.CharsetBin},
		{"curtime()", mysql.TypeDuration, charset.CharsetBin},
		{"current_timestamp()", mysql.TypeDatetime, charset.CharsetBin},
		{"microsecond('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"second('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"minute('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"hour('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"day('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"week('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"month('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"year('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"dayofweek('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"dayofmonth('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"dayofyear('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"weekday('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"weekofyear('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"yearweek('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin},
		{"found_rows()", mysql.TypeLonglong, charset.CharsetBin},
		{"length('tidb')", mysql.TypeLonglong, charset.CharsetBin},
		{"now()", mysql.TypeDatetime, charset.CharsetBin},
		{"sysdate()", mysql.TypeDatetime, charset.CharsetBin},
		{"dayname('2007-02-03')", mysql.TypeVarString, "utf8"},
		{"version()", mysql.TypeVarString, "utf8"},
		{"database()", mysql.TypeVarString, "utf8"},
		{"user()", mysql.TypeVarString, "utf8"},
		{"current_user()", mysql.TypeVarString, "utf8"},
		{"CONCAT('T', 'i', 'DB')", mysql.TypeVarString, "utf8"},
		{"CONCAT_WS('-', 'T', 'i', 'DB')", mysql.TypeVarString, "utf8"},
		{"left('TiDB', 2)", mysql.TypeVarString, "utf8"},
		{"lower('TiDB')", mysql.TypeVarString, "utf8"},
		{"lcase('TiDB')", mysql.TypeVarString, "utf8"},
		{"repeat('TiDB', 3)", mysql.TypeVarString, "utf8"},
		{"replace('TiDB', 'D', 'd')", mysql.TypeVarString, "utf8"},
		{"upper('TiDB')", mysql.TypeVarString, "utf8"},
		{"ucase('TiDB')", mysql.TypeVarString, "utf8"},
		{"trim(' TiDB ')", mysql.TypeVarString, "utf8"},
		{"ltrim(' TiDB')", mysql.TypeVarString, "utf8"},
		{"rtrim('TiDB ')", mysql.TypeVarString, "utf8"},
		{"connection_id()", mysql.TypeLonglong, charset.CharsetBin},
		{"if(1>2, 2, 3)", mysql.TypeLonglong, charset.CharsetBin},
		{"case c1 when null then 2 when 2 then 1.1 else 1 END", mysql.TypeNewDecimal, charset.CharsetBin},
		{"case c1 when null then 2 when 2 then 'tidb' else 1.1 END", mysql.TypeVarchar, "utf8"},
		{"greatest(1, 2, 3)", mysql.TypeLonglong, charset.CharsetBin},
		{"greatest('TiDB', 'D', 'd')", mysql.TypeVarString, "utf8"},
		{"greatest(1.1, 2.2)", mysql.TypeNewDecimal, charset.CharsetBin},
		{"greatest('TiDB', 3)", mysql.TypeVarString, "utf8"},
		{"hex('TiDB')", mysql.TypeVarString, "utf8"},
		{"hex(12)", mysql.TypeVarString, "utf8"},
	}
	for _, ca := range cases {
		ctx := testKit.Se.(context.Context)
		stmts, err := tidb.Parse(ctx, "select "+ca.expr+" from t")
		c.Assert(err, IsNil)
		c.Assert(stmts, HasLen, 1)
		stmt := stmts[0].(*ast.SelectStmt)
		is := sessionctx.GetDomain(ctx).InfoSchema()
		err = plan.ResolveName(stmt, is, ctx)
		c.Assert(err, IsNil)
		plan.InferType(stmt)
		tp := stmt.GetResultFields()[0].Column.Tp
		chs := stmt.GetResultFields()[0].Column.Charset
		c.Assert(tp, Equals, ca.tp, Commentf("Tp for %s", ca.expr))
		c.Assert(chs, Equals, ca.chs, Commentf("Charset for %s", ca.expr))
	}
}