Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parser: disallow subquery without table alias (#19102) #20367

Merged
merged 10 commits into from
Nov 12, 2020
2 changes: 2 additions & 0 deletions ddl/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ var (
ErrFunctionalIndexOnField = terror.ClassDDL.New(mysql.ErrFunctionalIndexOnField, mysql.MySQLErrName[mysql.ErrFunctionalIndexOnField])
// ErrInvalidAutoRandom returns when auto_random is used incorrectly.
ErrInvalidAutoRandom = terror.ClassDDL.New(mysql.ErrInvalidAutoRandom, mysql.MySQLErrName[mysql.ErrInvalidAutoRandom])
// ErrDerivedMustHaveAlias returns when a sub select statement does not have a table alias.
ErrDerivedMustHaveAlias = terror.ClassDDL.New(mysql.ErrDerivedMustHaveAlias, mysql.MySQLErrName[mysql.ErrDerivedMustHaveAlias])

// ErrSequenceRunOut returns when the sequence has been run out.
ErrSequenceRunOut = terror.ClassDDL.New(mysql.ErrSequenceRunOut, mysql.MySQLErrName[mysql.ErrSequenceRunOut])
Expand Down
5 changes: 5 additions & 0 deletions errors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ error = '''
The used table type doesn't support FULLTEXT indexes
'''

["ddl:1248"]
error = '''
Every derived table must have its own alias
'''

["ddl:1253"]
error = '''
COLLATION '%s' is not valid for CHARACTER SET '%s'
Expand Down
28 changes: 27 additions & 1 deletion executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3916,7 +3916,33 @@ func (s *testSuite3) TestDoSubquery(c *C) {
c.Assert(r, IsNil, Commentf("result of Do not empty"))
}

func (s *testSuite3) TestTSOFail(c *C) {
func (s *testSuite3) TestSubqueryTableAlias(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec(`use test`)
tk.MustExec(`drop table if exists t`)

tk.MustExec("set sql_mode = ''")
tk.MustGetErrCode("select a, b from (select 1 a) ``, (select 2 b) ``;", mysql.ErrDerivedMustHaveAlias)
tk.MustGetErrCode("select a, b from (select 1 a) `x`, (select 2 b) `x`;", mysql.ErrNonuniqTable)
tk.MustGetErrCode("select a, b from (select 1 a), (select 2 b);", mysql.ErrDerivedMustHaveAlias)
// ambiguous column name
tk.MustGetErrCode("select a from (select 1 a) ``, (select 2 a) ``;", mysql.ErrDerivedMustHaveAlias)
tk.MustGetErrCode("select a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonuniqTable)
tk.MustGetErrCode("select x.a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonuniqTable)
tk.MustGetErrCode("select a from (select 1 a), (select 2 a);", mysql.ErrDerivedMustHaveAlias)

tk.MustExec("set sql_mode = 'oracle';")
tk.MustQuery("select a, b from (select 1 a) ``, (select 2 b) ``;").Check(testkit.Rows("1 2"))
tk.MustQuery("select a, b from (select 1 a) `x`, (select 2 b) `x`;").Check(testkit.Rows("1 2"))
tk.MustQuery("select a, b from (select 1 a), (select 2 b);").Check(testkit.Rows("1 2"))
// ambiguous column name
tk.MustGetErrCode("select a from (select 1 a) ``, (select 2 a) ``;", mysql.ErrNonUniq)
tk.MustGetErrCode("select a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonUniq)
tk.MustGetErrCode("select x.a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonUniq)
tk.MustGetErrCode("select a from (select 1 a), (select 2 a);", mysql.ErrNonUniq)
}

func (s *testSerialSuite1) TestTSOFail(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec(`use test`)
tk.MustExec(`drop table if exists t`)
Expand Down
22 changes: 15 additions & 7 deletions planner/core/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ func (p *preprocessor) Enter(in ast.Node) (out ast.Node, skipChildren bool) {
if node.Kind == ast.BRIEKindRestore {
p.flag |= inCreateOrDropTable
}
case *ast.TableSource:
isModeOracle := p.ctx.GetSessionVars().SQLMode&mysql.ModeOracle != 0
if _, ok := node.Source.(*ast.SelectStmt); ok && !isModeOracle && len(node.AsName.L) == 0 {
p.err = ddl.ErrDerivedMustHaveAlias.GenWithStackByArgs()
}
default:
p.flag &= ^parentIsJoin
}
Expand Down Expand Up @@ -556,13 +561,16 @@ func (p *preprocessor) checkNonUniqTableAlias(stmt *ast.Join) {
p.tableAliasInJoin = append(p.tableAliasInJoin, make(map[string]interface{}))
}
tableAliases := p.tableAliasInJoin[len(p.tableAliasInJoin)-1]
if err := isTableAliasDuplicate(stmt.Left, tableAliases); err != nil {
p.err = err
return
}
if err := isTableAliasDuplicate(stmt.Right, tableAliases); err != nil {
p.err = err
return
isOracleMode := p.ctx.GetSessionVars().SQLMode&mysql.ModeOracle != 0
if !isOracleMode {
if err := isTableAliasDuplicate(stmt.Left, tableAliases); err != nil {
p.err = err
return
}
if err := isTableAliasDuplicate(stmt.Right, tableAliases); err != nil {
p.err = err
return
}
}
p.flag |= parentIsJoin
}
Expand Down