зеркало из https://github.com/github/vitess-gh.git
[bug fix] USING planning on information_schema (#12542)
* [planner] Schema information on the information_schema views (#11941) * add info_schema information Signed-off-by: Andres Taylor <andres@planetscale.com> * add SchemaInformation handling for info_schema tables Signed-off-by: Andres Taylor <andres@planetscale.com> * fix bad test query Signed-off-by: Andres Taylor <andres@planetscale.com> * add support for information_schema on mysql 5.7 Signed-off-by: Andres Taylor <andres@planetscale.com> * columns sorted just like mysql, and tests for 5.7 Signed-off-by: Andres Taylor <andres@planetscale.com> * test: skip test that should not run Signed-off-by: Andres Taylor <andres@planetscale.com> Signed-off-by: Andres Taylor <andres@planetscale.com> * Fix for USING when column names not lower cased (#12379) Signed-off-by: Andres Taylor <andres@planetscale.com> --------- Signed-off-by: Andres Taylor <andres@planetscale.com>
This commit is contained in:
Родитель
7ac5c3939b
Коммит
92d2af292b
|
@ -210,97 +210,101 @@ func (ct *ColumnType) DescribeType() string {
|
|||
|
||||
// SQLType returns the sqltypes type code for the given column
|
||||
func (ct *ColumnType) SQLType() querypb.Type {
|
||||
switch strings.ToLower(ct.Type) {
|
||||
case keywordStrings[TINYINT]:
|
||||
if ct.Unsigned {
|
||||
return SQLTypeToQueryType(ct.Type, ct.Unsigned)
|
||||
}
|
||||
|
||||
func SQLTypeToQueryType(typeName string, unsigned bool) querypb.Type {
|
||||
switch keywordVals[strings.ToLower(typeName)] {
|
||||
case TINYINT:
|
||||
if unsigned {
|
||||
return sqltypes.Uint8
|
||||
}
|
||||
return sqltypes.Int8
|
||||
case keywordStrings[SMALLINT]:
|
||||
if ct.Unsigned {
|
||||
case SMALLINT:
|
||||
if unsigned {
|
||||
return sqltypes.Uint16
|
||||
}
|
||||
return sqltypes.Int16
|
||||
case keywordStrings[MEDIUMINT]:
|
||||
if ct.Unsigned {
|
||||
case MEDIUMINT:
|
||||
if unsigned {
|
||||
return sqltypes.Uint24
|
||||
}
|
||||
return sqltypes.Int24
|
||||
case keywordStrings[INT], keywordStrings[INTEGER]:
|
||||
if ct.Unsigned {
|
||||
case INT, INTEGER:
|
||||
if unsigned {
|
||||
return sqltypes.Uint32
|
||||
}
|
||||
return sqltypes.Int32
|
||||
case keywordStrings[BIGINT]:
|
||||
if ct.Unsigned {
|
||||
case BIGINT:
|
||||
if unsigned {
|
||||
return sqltypes.Uint64
|
||||
}
|
||||
return sqltypes.Int64
|
||||
case keywordStrings[BOOL], keywordStrings[BOOLEAN]:
|
||||
case BOOL, BOOLEAN:
|
||||
return sqltypes.Uint8
|
||||
case keywordStrings[TEXT]:
|
||||
case TEXT:
|
||||
return sqltypes.Text
|
||||
case keywordStrings[TINYTEXT]:
|
||||
case TINYTEXT:
|
||||
return sqltypes.Text
|
||||
case keywordStrings[MEDIUMTEXT]:
|
||||
case MEDIUMTEXT:
|
||||
return sqltypes.Text
|
||||
case keywordStrings[LONGTEXT]:
|
||||
case LONGTEXT:
|
||||
return sqltypes.Text
|
||||
case keywordStrings[BLOB]:
|
||||
case BLOB:
|
||||
return sqltypes.Blob
|
||||
case keywordStrings[TINYBLOB]:
|
||||
case TINYBLOB:
|
||||
return sqltypes.Blob
|
||||
case keywordStrings[MEDIUMBLOB]:
|
||||
case MEDIUMBLOB:
|
||||
return sqltypes.Blob
|
||||
case keywordStrings[LONGBLOB]:
|
||||
case LONGBLOB:
|
||||
return sqltypes.Blob
|
||||
case keywordStrings[CHAR]:
|
||||
case CHAR:
|
||||
return sqltypes.Char
|
||||
case keywordStrings[VARCHAR]:
|
||||
case VARCHAR:
|
||||
return sqltypes.VarChar
|
||||
case keywordStrings[BINARY]:
|
||||
case BINARY:
|
||||
return sqltypes.Binary
|
||||
case keywordStrings[VARBINARY]:
|
||||
case VARBINARY:
|
||||
return sqltypes.VarBinary
|
||||
case keywordStrings[DATE]:
|
||||
case DATE:
|
||||
return sqltypes.Date
|
||||
case keywordStrings[TIME]:
|
||||
case TIME:
|
||||
return sqltypes.Time
|
||||
case keywordStrings[DATETIME]:
|
||||
case DATETIME:
|
||||
return sqltypes.Datetime
|
||||
case keywordStrings[TIMESTAMP]:
|
||||
case TIMESTAMP:
|
||||
return sqltypes.Timestamp
|
||||
case keywordStrings[YEAR]:
|
||||
case YEAR:
|
||||
return sqltypes.Year
|
||||
case keywordStrings[FLOAT_TYPE]:
|
||||
case FLOAT_TYPE:
|
||||
return sqltypes.Float32
|
||||
case keywordStrings[DOUBLE]:
|
||||
case DOUBLE:
|
||||
return sqltypes.Float64
|
||||
case keywordStrings[DECIMAL]:
|
||||
case DECIMAL, DECIMAL_TYPE:
|
||||
return sqltypes.Decimal
|
||||
case keywordStrings[BIT]:
|
||||
case BIT:
|
||||
return sqltypes.Bit
|
||||
case keywordStrings[ENUM]:
|
||||
case ENUM:
|
||||
return sqltypes.Enum
|
||||
case keywordStrings[SET]:
|
||||
case SET:
|
||||
return sqltypes.Set
|
||||
case keywordStrings[JSON]:
|
||||
case JSON:
|
||||
return sqltypes.TypeJSON
|
||||
case keywordStrings[GEOMETRY]:
|
||||
case GEOMETRY:
|
||||
return sqltypes.Geometry
|
||||
case keywordStrings[POINT]:
|
||||
case POINT:
|
||||
return sqltypes.Geometry
|
||||
case keywordStrings[LINESTRING]:
|
||||
case LINESTRING:
|
||||
return sqltypes.Geometry
|
||||
case keywordStrings[POLYGON]:
|
||||
case POLYGON:
|
||||
return sqltypes.Geometry
|
||||
case keywordStrings[GEOMETRYCOLLECTION]:
|
||||
case GEOMETRYCOLLECTION:
|
||||
return sqltypes.Geometry
|
||||
case keywordStrings[MULTIPOINT]:
|
||||
case MULTIPOINT:
|
||||
return sqltypes.Geometry
|
||||
case keywordStrings[MULTILINESTRING]:
|
||||
case MULTILINESTRING:
|
||||
return sqltypes.Geometry
|
||||
case keywordStrings[MULTIPOLYGON]:
|
||||
case MULTIPOLYGON:
|
||||
return sqltypes.Geometry
|
||||
}
|
||||
return sqltypes.Null
|
||||
|
|
|
@ -687,6 +687,7 @@ var keywords = []keyword{
|
|||
|
||||
// keywordStrings contains the reverse mapping of token to keyword strings
|
||||
var keywordStrings = map[int]string{}
|
||||
var keywordVals = map[string]int{}
|
||||
|
||||
// keywordLookupTable is a perfect hash map that maps **case insensitive** keyword names to their ids
|
||||
var keywordLookupTable *caseInsensitiveTable
|
||||
|
@ -735,6 +736,7 @@ func init() {
|
|||
panic(fmt.Sprintf("keyword %q must be lowercase in table", kw.name))
|
||||
}
|
||||
keywordStrings[kw.id] = kw.name
|
||||
keywordVals[kw.name] = kw.id
|
||||
}
|
||||
|
||||
keywordLookupTable = buildCaseInsensitiveTable(keywords)
|
||||
|
|
|
@ -31,6 +31,8 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"vitess.io/vitess/go/vt/servenv"
|
||||
|
||||
vtgatepb "vitess.io/vitess/go/vt/proto/vtgate"
|
||||
|
||||
"vitess.io/vitess/go/test/utils"
|
||||
|
@ -252,7 +254,16 @@ func TestPlan(t *testing.T) {
|
|||
testFile(t, "flush_cases_no_default_keyspace.json", testOutputTempDir, vschemaWrapper, false)
|
||||
testFile(t, "show_cases_no_default_keyspace.json", testOutputTempDir, vschemaWrapper, false)
|
||||
testFile(t, "stream_cases.json", testOutputTempDir, vschemaWrapper, false)
|
||||
testFile(t, "systemtables_cases.json", testOutputTempDir, vschemaWrapper, false)
|
||||
testFile(t, "systemtables_cases80.json", testOutputTempDir, vschemaWrapper, false)
|
||||
}
|
||||
|
||||
func TestSystemTables57(t *testing.T) {
|
||||
// first we move everything to use 5.7 logic
|
||||
servenv.SetMySQLServerVersionForTest("5.7")
|
||||
defer servenv.SetMySQLServerVersionForTest("")
|
||||
vschemaWrapper := &vschemaWrapper{v: loadSchema(t, "vschemas/schema.json", true)}
|
||||
testOutputTempDir := makeTestOutput(t)
|
||||
testFile(t, "systemtables_cases57.json", testOutputTempDir, vschemaWrapper, false)
|
||||
}
|
||||
|
||||
func TestSysVarSetDisabled(t *testing.T) {
|
||||
|
|
|
@ -4381,7 +4381,7 @@
|
|||
{
|
||||
"comment": "SelectDBA with uncorrelated subqueries",
|
||||
"query": "select t.table_schema from information_schema.tables as t where t.table_schema in (select c.column_name from information_schema.columns as c)",
|
||||
"plan": {
|
||||
"v3-plan": {
|
||||
"QueryType": "SELECT",
|
||||
"Original": "select t.table_schema from information_schema.tables as t where t.table_schema in (select c.column_name from information_schema.columns as c)",
|
||||
"Instructions": {
|
||||
|
@ -4395,6 +4395,25 @@
|
|||
"Query": "select t.table_schema from information_schema.`tables` as t where t.table_schema in (select c.column_name from information_schema.`columns` as c)",
|
||||
"Table": "information_schema.`tables`"
|
||||
}
|
||||
},
|
||||
"gen4-plan": {
|
||||
"QueryType": "SELECT",
|
||||
"Original": "select t.table_schema from information_schema.tables as t where t.table_schema in (select c.column_name from information_schema.columns as c)",
|
||||
"Instructions": {
|
||||
"OperatorType": "Route",
|
||||
"Variant": "DBA",
|
||||
"Keyspace": {
|
||||
"Name": "main",
|
||||
"Sharded": false
|
||||
},
|
||||
"FieldQuery": "select t.table_schema from information_schema.`tables` as t where 1 != 1",
|
||||
"Query": "select t.table_schema from information_schema.`tables` as t where t.table_schema in (select c.column_name from information_schema.`columns` as c)",
|
||||
"Table": "information_schema.`tables`"
|
||||
},
|
||||
"TablesUsed": [
|
||||
"information_schema.columns",
|
||||
"information_schema.tables"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -587,6 +587,7 @@
|
|||
"plan": "table disabled has been disabled"
|
||||
},
|
||||
{
|
||||
"comment": "select second_user.foo.col from second_user.foo join user on second_user.foo.id = user.id where second_user.foo.col = 42",
|
||||
"query": "select second_user.foo.col from second_user.foo join user on second_user.foo.id = user.id where second_user.foo.col = 42",
|
||||
"v3-plan": {
|
||||
"QueryType": "SELECT",
|
||||
|
@ -623,6 +624,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"comment": "select user.music.foo from user.music join user on user.music.id = user.id where user.music.col = 42",
|
||||
"query": "select user.music.foo from user.music join user on user.music.id = user.id where user.music.col = 42",
|
||||
"v3-plan": {
|
||||
"QueryType": "SELECT",
|
||||
|
@ -3001,6 +3003,7 @@
|
|||
]
|
||||
},
|
||||
"TablesUsed": [
|
||||
"information_schema.a",
|
||||
"main.unsharded"
|
||||
]
|
||||
}
|
||||
|
@ -3076,6 +3079,7 @@
|
|||
]
|
||||
},
|
||||
"TablesUsed": [
|
||||
"information_schema.a",
|
||||
"main.unsharded"
|
||||
]
|
||||
}
|
||||
|
@ -6160,6 +6164,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"comment": "select * from (select bar as push_it from (select foo as bar from (select id as foo from user) as t1) as t2) as t3 where push_it = 12",
|
||||
"query": "select * from (select bar as push_it from (select foo as bar from (select id as foo from user) as t1) as t2) as t3 where push_it = 12",
|
||||
"v3-plan": {
|
||||
"QueryType": "SELECT",
|
||||
|
@ -6203,4 +6208,4 @@
|
|||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
|
|
|
@ -2535,6 +2535,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"comment": "(select id from unsharded) union (select id from unsharded_auto) order by id limit 5",
|
||||
"query": "(select id from unsharded) union (select id from unsharded_auto) order by id limit 5",
|
||||
"v3-plan": {
|
||||
"QueryType": "SELECT",
|
||||
|
@ -3295,6 +3296,7 @@
|
|||
"plan": "syntax error at position 41 near 'into'"
|
||||
},
|
||||
{
|
||||
"comment": "select (select u.id from user as u where u.id = 1), a.id from user as a where a.id = 1",
|
||||
"query": "select (select u.id from user as u where u.id = 1), a.id from user as a where a.id = 1",
|
||||
"v3-plan": {
|
||||
"QueryType": "SELECT",
|
||||
|
@ -3416,6 +3418,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"comment": "((((select 1))))",
|
||||
"query": "((((select 1))))",
|
||||
"v3-plan": {
|
||||
"QueryType": "SELECT",
|
||||
|
@ -3585,6 +3588,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"comment": "select (select col from user limit 1) as a from user join user_extra order by a",
|
||||
"query": "select (select col from user limit 1) as a from user join user_extra order by a",
|
||||
"v3-plan": {
|
||||
"QueryType": "SELECT",
|
||||
|
@ -3716,6 +3720,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"comment": "select t.a from (select (select col from user limit 1) as a from user join user_extra) t",
|
||||
"query": "select t.a from (select (select col from user limit 1) as a from user join user_extra) t",
|
||||
"v3-plan": {
|
||||
"QueryType": "SELECT",
|
||||
|
@ -3860,6 +3865,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"comment": "select (select col from user where user_extra.id = 4 limit 1) as a from user join user_extra",
|
||||
"query": "select (select col from user where user_extra.id = 4 limit 1) as a from user join user_extra",
|
||||
"plan": "unsupported: cross-shard correlated subquery"
|
||||
},
|
||||
|
@ -4462,6 +4468,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"comment": "select user.id, trim(leading 'x' from user.name) from user",
|
||||
"query": "select user.id, trim(leading 'x' from user.name) from user",
|
||||
"v3-plan": {
|
||||
"QueryType": "SELECT",
|
||||
|
@ -4571,6 +4578,7 @@
|
|||
"Table": "dual"
|
||||
},
|
||||
"TablesUsed": [
|
||||
"information_schema.TABLES",
|
||||
"main.dual"
|
||||
]
|
||||
}
|
||||
|
@ -4613,6 +4621,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"comment": "select (select id from user order by id limit 1) from user_extra",
|
||||
"query": "select (select id from user order by id limit 1) from user_extra",
|
||||
"v3-plan": {
|
||||
"QueryType": "SELECT",
|
||||
|
@ -7687,6 +7696,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"comment": "select user.a, t.b from user join (select id, count(*) b, req from user_extra group by req, id) as t on user.id = t.id",
|
||||
"query": "select user.a, t.b from user join (select id, count(*) b, req from user_extra group by req, id) as t on user.id = t.id",
|
||||
"v3-plan": "unsupported: filtering on results of cross-shard subquery",
|
||||
"gen4-plan": {
|
||||
|
@ -7765,6 +7775,7 @@
|
|||
"gen4-plan": "unsupported: JOIN not supported between derived tables"
|
||||
},
|
||||
{
|
||||
"comment": "SELECT music.id FROM (SELECT MAX(id) as maxt FROM music WHERE music.user_id = 5) other JOIN music ON other.maxt = music.id",
|
||||
"query": "SELECT music.id FROM (SELECT MAX(id) as maxt FROM music WHERE music.user_id = 5) other JOIN music ON other.maxt = music.id",
|
||||
"v3-plan": {
|
||||
"QueryType": "SELECT",
|
||||
|
@ -7909,4 +7920,4 @@
|
|||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
|
|
|
@ -69,7 +69,11 @@
|
|||
"Query": "select t.table_schema, t.table_name, c.column_name, c.column_type from information_schema.`tables` as t, information_schema.`columns` as c where t.table_schema = :__vtschemaname and c.table_schema = :__vtschemaname and c.table_schema = t.table_schema and c.table_name = t.table_name order by t.table_schema asc, t.table_name asc, c.column_name asc",
|
||||
"SysTableTableSchema": "[VARCHAR(\"user\"), VARCHAR(\"user\")]",
|
||||
"Table": "information_schema.`columns`, information_schema.`tables`"
|
||||
}
|
||||
},
|
||||
"TablesUsed": [
|
||||
"information_schema.columns",
|
||||
"information_schema.tables"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -107,6 +111,7 @@
|
|||
"Table": "dual"
|
||||
},
|
||||
"TablesUsed": [
|
||||
"information_schema.schemata",
|
||||
"main.dual"
|
||||
]
|
||||
}
|
||||
|
@ -144,7 +149,10 @@
|
|||
"Query": "select x.`1` from (select 1 from information_schema.schemata where schema_name = :__vtschemaname limit 1) as x",
|
||||
"SysTableTableSchema": "[VARCHAR(\"MyDatabase\")]",
|
||||
"Table": "information_schema.schemata"
|
||||
}
|
||||
},
|
||||
"TablesUsed": [
|
||||
"information_schema.schemata"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -660,6 +660,7 @@
|
|||
]
|
||||
},
|
||||
"TablesUsed": [
|
||||
"information_schema.a",
|
||||
"main.unsharded"
|
||||
]
|
||||
}
|
||||
|
@ -739,6 +740,7 @@
|
|||
]
|
||||
},
|
||||
"TablesUsed": [
|
||||
"information_schema.a",
|
||||
"main.unsharded"
|
||||
]
|
||||
}
|
||||
|
@ -2286,6 +2288,7 @@
|
|||
"plan": "can't do ORDER BY on top of UNION"
|
||||
},
|
||||
{
|
||||
"comment": "select 1 from (select id+42 as foo from user union select 1+id as foo from unsharded) as t",
|
||||
"query": "select 1 from (select id+42 as foo from user union select 1+id as foo from unsharded) as t",
|
||||
"v3-plan": "unsupported: expression on results of a cross-shard subquery",
|
||||
"gen4-plan": {
|
||||
|
@ -2340,4 +2343,4 @@
|
|||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
|
|
|
@ -273,26 +273,32 @@
|
|||
"plan": "unsupported: REPLACE INTO with sharded schema"
|
||||
},
|
||||
{
|
||||
"comment": "select keyspace_id from user_index where id = 1 and id = 2",
|
||||
"query": "select keyspace_id from user_index where id = 1 and id = 2",
|
||||
"plan": "unsupported: where clause for vindex function must be of the form id = <val> or id in(<val>,...) (multiple filters)"
|
||||
},
|
||||
{
|
||||
"comment": "select keyspace_id from user_index where func(id)",
|
||||
"query": "select keyspace_id from user_index where func(id)",
|
||||
"plan": "unsupported: where clause for vindex function must be of the form id = <val> or id in(<val>,...) (not a comparison)"
|
||||
},
|
||||
{
|
||||
"comment": "select keyspace_id from user_index where id > 1",
|
||||
"query": "select keyspace_id from user_index where id > 1",
|
||||
"plan": "unsupported: where clause for vindex function must be of the form id = <val> or id in(<val>,...) (not equality)"
|
||||
},
|
||||
{
|
||||
"comment": "select keyspace_id from user_index where 1 = id",
|
||||
"query": "select keyspace_id from user_index where 1 = id",
|
||||
"plan": "unsupported: where clause for vindex function must be of the form id = <val> or id in(<val>,...) (lhs is not a column)"
|
||||
},
|
||||
{
|
||||
"comment": "select keyspace_id from user_index where keyspace_id = 1",
|
||||
"query": "select keyspace_id from user_index where keyspace_id = 1",
|
||||
"plan": "unsupported: where clause for vindex function must be of the form id = <val> or id in(<val>,...) (lhs is not id)"
|
||||
},
|
||||
{
|
||||
"comment": "select keyspace_id from user_index where id = id+1",
|
||||
"query": "select keyspace_id from user_index where id = id+1",
|
||||
"plan": "unsupported: where clause for vindex function must be of the form id = <val> or id in(<val>,...) (rhs is not a value)"
|
||||
},
|
||||
|
@ -307,6 +313,7 @@
|
|||
"plan": "unsupported: where clause for vindex function must be of the form id = <val> or id in(<val>,...) (where clause missing)"
|
||||
},
|
||||
{
|
||||
"comment": "select func(keyspace_id) from user_index where id = :id",
|
||||
"query": "select func(keyspace_id) from user_index where id = :id",
|
||||
"plan": "unsupported: expression on results of a vindex function"
|
||||
},
|
||||
|
@ -392,11 +399,6 @@
|
|||
"query": "select distinct a, b as a from user",
|
||||
"plan": "generating order by clause: ambiguous symbol reference: a"
|
||||
},
|
||||
{
|
||||
"comment": "subquery of information_schema with itself and star expression in outer select",
|
||||
"query": "select a.*, u.id from information_schema.a a, user u where a.id in (select * from information_schema.b)",
|
||||
"plan": "unsupported: '*' expression in cross-shard query"
|
||||
},
|
||||
{
|
||||
"comment": "outer and inner subquery route reference the same \"uu.id\" name\n# but they refer to different things. The first reference is to the outermost query,\n# and the second reference is to the innermost 'from' subquery.\n# This query will never work as the inner derived table is only selecting one of the column",
|
||||
"query": "select id2 from user uu where id in (select id from user where id = uu.id and user.col in (select col from (select id from user_extra where user_id = 5) uu where uu.user_id = uu.id))",
|
||||
|
@ -449,7 +451,7 @@
|
|||
"comment": "systable union query in derived table with constraint on outside (without star projection)",
|
||||
"query": "select id from (select id from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select id from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `id` = 'primary'",
|
||||
"v3-plan": "unsupported: filtering on results of cross-shard subquery",
|
||||
"gen4-plan": "can't push predicates on concatenate"
|
||||
"gen4-plan": "symbol id not found"
|
||||
},
|
||||
{
|
||||
"comment": "insert having subquery in row values",
|
||||
|
@ -471,4 +473,4 @@
|
|||
"query": "select get_lock('xyz', 10), 1 from dual",
|
||||
"plan": "unsupported: lock function and other expression in same select query"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
|
|
@ -63,7 +63,7 @@ func newAnalyzer(dbName string, si SchemaInformation) *analyzer {
|
|||
|
||||
// Analyze analyzes the parsed query.
|
||||
func Analyze(statement sqlparser.Statement, currentDb string, si SchemaInformation) (*SemTable, error) {
|
||||
analyzer := newAnalyzer(currentDb, si)
|
||||
analyzer := newAnalyzer(currentDb, newSchemaInfo(si))
|
||||
|
||||
// Analysis for initial scope
|
||||
err := analyzer.analyze(statement)
|
||||
|
|
|
@ -75,6 +75,17 @@ func TestBindingSingleTablePositive(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestInformationSchemaColumnInfo(t *testing.T) {
|
||||
stmt, semTable := parseAndAnalyze(t, "select table_comment, file_name from information_schema.`TABLES`, information_schema.`FILES`", "d")
|
||||
|
||||
sel, _ := stmt.(*sqlparser.Select)
|
||||
tables := SingleTableSet(0)
|
||||
files := SingleTableSet(1)
|
||||
|
||||
assert.Equal(t, tables, semTable.RecursiveDeps(extract(sel, 0)))
|
||||
assert.Equal(t, files, semTable.DirectDeps(extract(sel, 1)))
|
||||
}
|
||||
|
||||
func TestBindingSingleAliasedTablePositive(t *testing.T) {
|
||||
queries := []string{
|
||||
"select col from tabl as X",
|
||||
|
|
|
@ -17,6 +17,8 @@ limitations under the License.
|
|||
package semantics
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
|
||||
"vitess.io/vitess/go/vt/sqlparser"
|
||||
"vitess.io/vitess/go/vt/vterrors"
|
||||
|
@ -70,7 +72,7 @@ func createDerivedTableForExpressions(expressions sqlparser.SelectExprs, cols sq
|
|||
func (dt *DerivedTable) dependencies(colName string, org originable) (dependencies, error) {
|
||||
directDeps := org.tableSetFor(dt.ASTNode)
|
||||
for i, name := range dt.columnNames {
|
||||
if name != colName {
|
||||
if !strings.EqualFold(name, colName) {
|
||||
continue
|
||||
}
|
||||
_, recursiveDeps, qt := org.depsForExpr(dt.cols[i])
|
||||
|
|
|
@ -18,6 +18,7 @@ package semantics
|
|||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
|
||||
"vitess.io/vitess/go/vt/sqlparser"
|
||||
|
@ -238,7 +239,7 @@ func rewriteJoinUsing(
|
|||
usingCols = map[string]TableSet{}
|
||||
}
|
||||
for _, col := range tbl.getColumns() {
|
||||
_, found := usingCols[col.Name]
|
||||
_, found := usingCols[strings.ToLower(col.Name)]
|
||||
if found {
|
||||
tblName, err := tbl.Name()
|
||||
if err != nil {
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
Copyright 2022 The Vitess Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package semantics
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"vitess.io/vitess/go/vt/sqlparser"
|
||||
)
|
||||
|
||||
func TestGenerateInfoSchemaMap(t *testing.T) {
|
||||
t.Skip("run manually to re-create the content of the getInfoSchema functions")
|
||||
b := new(strings.Builder)
|
||||
|
||||
db, err := sql.Open("mysql", "root@tcp(127.0.0.1:3306)/test")
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
for _, tbl := range informationSchemaTables80 {
|
||||
b.WriteString("cols = []vindexes.Column{}\n")
|
||||
result, err := db.Query(fmt.Sprintf("show columns from information_schema.`%s`", tbl))
|
||||
require.NoError(t, err)
|
||||
defer result.Close()
|
||||
for result.Next() {
|
||||
var r row
|
||||
result.Scan(&r.Field, &r.Type, &r.Null, &r.Key, &r.Default, &r.Extra)
|
||||
allString := re.FindStringSubmatch(r.Type)
|
||||
var typ string
|
||||
if allString == nil {
|
||||
typ = r.Type
|
||||
} else {
|
||||
typ = allString[1]
|
||||
}
|
||||
unsigned := false
|
||||
if idx := strings.Index(typ, "unsigned"); idx > 0 {
|
||||
typ = typ[:idx-1]
|
||||
unsigned = true
|
||||
}
|
||||
i2 := sqlparser.SQLTypeToQueryType(typ, unsigned)
|
||||
if int(i2) == 0 {
|
||||
t.Fatalf("%s %s", tbl, r.Field)
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("cols = append(cols, createCol(\"%s\", %d))\n", r.Field, int(i2)))
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("infSchema[\"%s\"] = cols\n", tbl))
|
||||
}
|
||||
|
||||
fmt.Println(b.String())
|
||||
}
|
||||
|
||||
var (
|
||||
informationSchemaTables57 = []string{
|
||||
"CHARACTER_SETS",
|
||||
"COLLATION_CHARACTER_SET_APPLICABILITY",
|
||||
"COLLATIONS",
|
||||
"COLUMN_PRIVILEGES",
|
||||
"COLUMNS",
|
||||
"ENGINES",
|
||||
"EVENTS",
|
||||
"FILES",
|
||||
"GLOBAL_STATUS",
|
||||
"GLOBAL_VARIABLES",
|
||||
"INNODB_BUFFER_PAGE",
|
||||
"INNODB_BUFFER_PAGE_LRU",
|
||||
"INNODB_BUFFER_POOL_STATS",
|
||||
"INNODB_CMP",
|
||||
"INNODB_CMP_PER_INDEX",
|
||||
"INNODB_CMP_PER_INDEX_RESET",
|
||||
"INNODB_CMP_RESET",
|
||||
"INNODB_CMPMEM",
|
||||
"INNODB_CMPMEM_RESET",
|
||||
"INNODB_FT_BEING_DELETED",
|
||||
"INNODB_FT_CONFIG",
|
||||
"INNODB_FT_DEFAULT_STOPWORD",
|
||||
"INNODB_FT_DELETED",
|
||||
"INNODB_FT_INDEX_CACHE",
|
||||
"INNODB_FT_INDEX_TABLE",
|
||||
"INNODB_LOCK_WAITS",
|
||||
"INNODB_LOCKS",
|
||||
"INNODB_METRICS",
|
||||
"INNODB_SYS_COLUMNS",
|
||||
"INNODB_SYS_DATAFILES",
|
||||
"INNODB_SYS_FIELDS",
|
||||
"INNODB_SYS_FOREIGN",
|
||||
"INNODB_SYS_FOREIGN_COLS",
|
||||
"INNODB_SYS_INDEXES",
|
||||
"INNODB_SYS_TABLES",
|
||||
"INNODB_SYS_TABLESPACES",
|
||||
"INNODB_SYS_TABLESTATS",
|
||||
"INNODB_SYS_VIRTUAL",
|
||||
"INNODB_TEMP_TABLE_INFO",
|
||||
"INNODB_TRX",
|
||||
"KEY_COLUMN_USAGE",
|
||||
"OPTIMIZER_TRACE",
|
||||
"PARAMETERS",
|
||||
"PARTITIONS",
|
||||
"PLUGINS",
|
||||
"PROCESSLIST",
|
||||
"PROFILING",
|
||||
"REFERENTIAL_CONSTRAINTS",
|
||||
"ROUTINES",
|
||||
"SCHEMA_PRIVILEGES",
|
||||
"SCHEMATA",
|
||||
"SESSION_STATUS",
|
||||
"SESSION_VARIABLES",
|
||||
"STATISTICS",
|
||||
"TABLE_CONSTRAINTS",
|
||||
"TABLE_PRIVILEGES",
|
||||
"TABLES",
|
||||
"TABLESPACES",
|
||||
"TRIGGERS",
|
||||
"USER_PRIVILEGES",
|
||||
"VIEWS",
|
||||
}
|
||||
informationSchemaTables80 = []string{
|
||||
"ADMINISTRABLE_ROLE_AUTHORIZATIONS",
|
||||
"APPLICABLE_ROLES",
|
||||
"CHARACTER_SETS",
|
||||
"CHECK_CONSTRAINTS",
|
||||
"COLLATION_CHARACTER_SET_APPLICABILITY",
|
||||
"COLLATIONS",
|
||||
"COLUMN_PRIVILEGES",
|
||||
"COLUMN_STATISTICS",
|
||||
"COLUMNS",
|
||||
"COLUMNS_EXTENSIONS",
|
||||
"ENABLED_ROLES",
|
||||
"ENGINES",
|
||||
"EVENTS",
|
||||
"FILES",
|
||||
"INNODB_BUFFER_PAGE",
|
||||
"INNODB_BUFFER_PAGE_LRU",
|
||||
"INNODB_BUFFER_POOL_STATS",
|
||||
"INNODB_CACHED_INDEXES",
|
||||
"INNODB_CMP",
|
||||
"INNODB_CMP_PER_INDEX",
|
||||
"INNODB_CMP_PER_INDEX_RESET",
|
||||
"INNODB_CMP_RESET",
|
||||
"INNODB_CMPMEM",
|
||||
"INNODB_CMPMEM_RESET",
|
||||
"INNODB_COLUMNS",
|
||||
"INNODB_DATAFILES",
|
||||
"INNODB_FIELDS",
|
||||
"INNODB_FOREIGN",
|
||||
"INNODB_FOREIGN_COLS",
|
||||
"INNODB_FT_BEING_DELETED",
|
||||
"INNODB_FT_CONFIG",
|
||||
"INNODB_FT_DEFAULT_STOPWORD",
|
||||
"INNODB_FT_DELETED",
|
||||
"INNODB_FT_INDEX_CACHE",
|
||||
"INNODB_FT_INDEX_TABLE",
|
||||
"INNODB_INDEXES",
|
||||
"INNODB_METRICS",
|
||||
"INNODB_SESSION_TEMP_TABLESPACES",
|
||||
"INNODB_TABLES",
|
||||
"INNODB_TABLESPACES",
|
||||
"INNODB_TABLESPACES_BRIEF",
|
||||
"INNODB_TABLESTATS",
|
||||
"INNODB_TEMP_TABLE_INFO",
|
||||
"INNODB_TRX",
|
||||
"INNODB_VIRTUAL",
|
||||
"KEY_COLUMN_USAGE",
|
||||
"KEYWORDS",
|
||||
"OPTIMIZER_TRACE",
|
||||
"PARAMETERS",
|
||||
"PARTITIONS",
|
||||
"PLUGINS",
|
||||
"PROCESSLIST",
|
||||
"PROFILING",
|
||||
"REFERENTIAL_CONSTRAINTS",
|
||||
"RESOURCE_GROUPS",
|
||||
"ROLE_COLUMN_GRANTS",
|
||||
"ROLE_ROUTINE_GRANTS",
|
||||
"ROLE_TABLE_GRANTS",
|
||||
"ROUTINES",
|
||||
"SCHEMA_PRIVILEGES",
|
||||
"SCHEMATA",
|
||||
"SCHEMATA_EXTENSIONS",
|
||||
"ST_GEOMETRY_COLUMNS",
|
||||
"ST_SPATIAL_REFERENCE_SYSTEMS",
|
||||
"ST_UNITS_OF_MEASURE",
|
||||
"STATISTICS",
|
||||
"TABLE_CONSTRAINTS",
|
||||
"TABLE_CONSTRAINTS_EXTENSIONS",
|
||||
"TABLE_PRIVILEGES",
|
||||
"TABLES",
|
||||
"TABLES_EXTENSIONS",
|
||||
"TABLESPACES",
|
||||
"TABLESPACES_EXTENSIONS",
|
||||
"TRIGGERS",
|
||||
"USER_ATTRIBUTES",
|
||||
"USER_PRIVILEGES",
|
||||
"VIEW_ROUTINE_USAGE",
|
||||
"VIEW_TABLE_USAGE",
|
||||
"VIEWS",
|
||||
}
|
||||
)
|
||||
|
||||
type row struct {
|
||||
Field string
|
||||
Type string
|
||||
Null string
|
||||
Key any
|
||||
Default any
|
||||
Extra any
|
||||
}
|
||||
|
||||
var re = regexp.MustCompile(`(.*)\((.*)\)`)
|
|
@ -84,19 +84,16 @@ func (tc *tableCollector) up(cursor *sqlparser.Cursor) error {
|
|||
case sqlparser.TableName:
|
||||
var tbl *vindexes.Table
|
||||
var vindex vindexes.Vindex
|
||||
var isInfSchema bool
|
||||
if sqlparser.SystemSchema(t.Qualifier.String()) {
|
||||
isInfSchema = true
|
||||
} else {
|
||||
var err error
|
||||
tbl, vindex, _, _, _, err = tc.si.FindTableOrVindex(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tbl == nil && vindex != nil {
|
||||
tbl = newVindexTable(t.Name)
|
||||
}
|
||||
isInfSchema := sqlparser.SystemSchema(t.Qualifier.String())
|
||||
var err error
|
||||
tbl, vindex, _, _, _, err = tc.si.FindTableOrVindex(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tbl == nil && vindex != nil {
|
||||
tbl = newVindexTable(t.Name)
|
||||
}
|
||||
|
||||
scope := tc.scoper.currentScope()
|
||||
tableInfo := tc.createTable(t, node, tbl, isInfSchema, vindex)
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче