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

*: improve the column info for client #4770

Merged
merged 9 commits into from
Oct 15, 2017
7 changes: 6 additions & 1 deletion executor/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,15 @@ type recordSet struct {
func (a *recordSet) Fields() ([]*ast.ResultField, error) {
if len(a.fields) == 0 {
for _, col := range a.executor.Schema().Columns {
dbName := col.DBName.O
if dbName == "" && col.TblName.L != "" {
dbName = a.stmt.ctx.GetSessionVars().CurrentDB
}
rf := &ast.ResultField{
ColumnAsName: col.ColName,
TableAsName: col.TblName,
DBName: col.DBName,
DBName: model.NewCIStr(dbName),
Table: &model.TableInfo{Name: col.OrigTblName},
Column: &model.ColumnInfo{
FieldType: *col.RetType,
Name: col.ColName,
Expand Down
20 changes: 20 additions & 0 deletions executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1644,6 +1644,26 @@ func (s *testSuite) TestColumnName(c *C) {
c.Check(len(fields), Equals, 2)
c.Check(fields[0].Column.Name.L, Equals, "d")
c.Check(fields[1].Column.Name.L, Equals, "c")
// Test case for query a column of a table.
// In this case, all attributes have values.
rs, err = tk.Exec("select c as a from t as t2")
c.Check(err, IsNil)
fields, err = rs.Fields()
c.Check(fields[0].Column.Name.L, Equals, "a")
c.Check(fields[0].ColumnAsName.L, Equals, "a")
c.Check(fields[0].Table.Name.L, Equals, "t")
c.Check(fields[0].TableAsName.L, Equals, "t2")
c.Check(fields[0].DBName.L, Equals, "test")
// Test case for query a expression which only using constant inputs.
// In this case, the table, org_table and database attributes will all be empty.
rs, err = tk.Exec("select hour(1) as a from t as t2")
c.Check(err, IsNil)
fields, err = rs.Fields()
c.Check(fields[0].Column.Name.L, Equals, "a")
c.Check(fields[0].ColumnAsName.L, Equals, "a")
c.Check(fields[0].Table.Name.L, Equals, "")
c.Check(fields[0].TableAsName.L, Equals, "")
c.Check(fields[0].DBName.L, Equals, "")
}

func (s *testSuite) TestSelectVar(c *C) {
Expand Down
7 changes: 7 additions & 0 deletions executor/join_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,13 @@ func (s *testSuite) TestSubquery(c *C) {
tk.MustExec("insert into t2 values (1,1),(1,2),(1,3)")
result = tk.MustQuery("select f1,f2 from t1 group by f1,f2 having count(1) >= all (select fb from t2 where fa = f1)")
result.Check(testkit.Rows("1 2"))

tk.MustExec("DROP TABLE IF EXISTS t1, t2")
tk.MustExec("CREATE TABLE t1(a INT)")
tk.MustExec("CREATE TABLE t2 (d BINARY(2), PRIMARY KEY (d(1)), UNIQUE KEY (d))")
tk.MustExec("INSERT INTO t1 values(1)")
result = tk.MustQuery("SELECT 1 FROM test.t1, test.t2 WHERE 1 = (SELECT test.t2.d FROM test.t2 WHERE test.t1.a >= 1) and test.t2.d = 1;")
result.Check(testkit.Rows())
}

func (s *testSuite) TestInSubquery(c *C) {
Expand Down
13 changes: 7 additions & 6 deletions expression/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,13 @@ func (col *CorrelatedColumn) ResolveIndices(_ *Schema) {

// Column represents a column.
type Column struct {
FromID int
ColName model.CIStr
DBName model.CIStr
TblName model.CIStr
RetType *types.FieldType
ID int64
FromID int
ColName model.CIStr
DBName model.CIStr
OrigTblName model.CIStr
TblName model.CIStr
RetType *types.FieldType
ID int64
// Position means the position of this column that appears in the select fields.
// e.g. SELECT name as id , 1 - id as id , 1 + name as id, name as id from src having id = 1;
// There are four ids in the same schema, so you can't identify the column through the FromID and ColName.
Expand Down
10 changes: 9 additions & 1 deletion expression/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,15 @@ func (s *Schema) FindColumnAndIndex(astCol *ast.ColumnName) (*Column, int, error
if idx == -1 {
idx = i
} else {
return nil, -1, errors.Errorf("Column %s is ambiguous", col.String())
// For query like:
// create t1(a int); create t2(d int);
// select 1 from t1, t2 where 1 = (select d from t2 where a > 1) where d = 1;
// we will get an Apply operator whose schema is [test.t1.a, test.t2.d, test.t2.d],
// we check whether the column of the schema comes from a subquery to avoid
// causing the ambiguous error when resolve the column `d` in the Selection.
if !col.IsAggOrSubq {
return nil, -1, errors.Errorf("Column %s is ambiguous", col.String())
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion plan/dag_plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ func (s *testPlanSuite) TestDAGPlanBuilderUnion(c *C) {
// Test TopN + Union.
{
sql: "select a from t union all (select c from t) order by a limit 1",
best: "UnionAll{TableReader(Table(t)->Limit)->IndexReader(Index(t.c_d_e)[[<nil>,+inf]]->Limit)}->TopN([a],0,1)",
best: "UnionAll{TableReader(Table(t)->Limit)->IndexReader(Index(t.c_d_e)[[<nil>,+inf]]->Limit)}->TopN([t.a],0,1)",
},
}
for _, tt := range tests {
Expand Down
1 change: 1 addition & 0 deletions plan/eliminate_projection.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ func eliminatePhysicalProjection(p PhysicalPlan) PhysicalPlan {
newCols[i].DBName = oldCol.DBName
newCols[i].TblName = oldCol.TblName
newCols[i].ColName = oldCol.ColName
newCols[i].OrigTblName = oldCol.OrigTblName
}
}
return newRoot
Expand Down
2 changes: 1 addition & 1 deletion plan/explain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func (s *testExplainSuite) TestExplain(c *C) {
[]string{
"TableScan_4 cop table:t2, range:(-inf,+inf), keep order:false 8000",
"TableReader_5 Sort_3 root data:TableScan_4 8000",
"Sort_3 TableReader_5 root t2.c2:asc 8000",
"Sort_3 TableReader_5 root test.t2.c2:asc 8000",
},
},
{
Expand Down
44 changes: 28 additions & 16 deletions plan/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,9 @@ func (b *planBuilder) buildResultSetNode(node ast.ResultSetNode) LogicalPlan {
if v, ok := p.(*DataSource); ok {
v.TableAsName = &x.AsName
}
if x.AsName.L != "" {
for _, col := range p.Schema().Columns {
for _, col := range p.Schema().Columns {
col.OrigTblName = col.TblName
if x.AsName.L != "" {
col.TblName = x.AsName
col.DBName = model.NewCIStr("")
}
Expand Down Expand Up @@ -412,12 +413,21 @@ func (b *planBuilder) buildSelection(p LogicalPlan, where ast.ExprNode, AggMappe
return selection
}

// buildProjectionFieldNameFromColumns builds the field name and the table name when field expression is a column reference.
func (b *planBuilder) buildProjectionFieldNameFromColumns(field *ast.SelectField, c *expression.Column) (model.CIStr, model.CIStr) {
// buildProjectionFieldNameFromColumns builds the field name, table name and database name when field expression is a column reference.
func (b *planBuilder) buildProjectionFieldNameFromColumns(field *ast.SelectField, c *expression.Column) (colName, tblName, origTblName, dbName model.CIStr) {
if astCol, ok := getInnerFromParentheses(field.Expr).(*ast.ColumnNameExpr); ok {
return astCol.Name.Name, astCol.Name.Table
colName, tblName, dbName = astCol.Name.Name, astCol.Name.Table, astCol.Name.Schema
}
if field.AsName.L != "" {
colName = field.AsName
}
if tblName.L == "" {
tblName = c.TblName
}
return c.ColName, c.TblName
if dbName.L == "" {
dbName = c.DBName
}
return colName, tblName, c.OrigTblName, c.DBName
}

// buildProjectionFieldNameFromExpressions builds the field name when field expression is a normal expression.
Expand Down Expand Up @@ -463,23 +473,25 @@ func (b *planBuilder) buildProjectionFieldNameFromExpressions(field *ast.SelectF

// buildProjectionField builds the field object according to SelectField in projection.
func (b *planBuilder) buildProjectionField(id, position int, field *ast.SelectField, expr expression.Expression) *expression.Column {
var tblName, colName model.CIStr
if field.AsName.L != "" {
var origTblName, tblName, colName, dbName model.CIStr
if c, ok := expr.(*expression.Column); ok && !c.IsAggOrSubq {
// Field is a column reference.
colName, tblName, origTblName, dbName = b.buildProjectionFieldNameFromColumns(field, c)
} else if field.AsName.L != "" {
// Field has alias.
colName = field.AsName
} else if c, ok := expr.(*expression.Column); ok && !c.IsAggOrSubq {
// Field is a column reference.
colName, tblName = b.buildProjectionFieldNameFromColumns(field, c)
} else {
// Other: field is an expression.
colName = b.buildProjectionFieldNameFromExpressions(field)
}
return &expression.Column{
FromID: id,
Position: position,
TblName: tblName,
ColName: colName,
RetType: expr.GetType(),
FromID: id,
Position: position,
TblName: tblName,
OrigTblName: origTblName,
ColName: colName,
DBName: dbName,
RetType: expr.GetType(),
}
}

Expand Down
14 changes: 7 additions & 7 deletions plan/logical_plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ func (s *testPlanSuite) TestPlanBuilder(c *C) {
},
{
sql: "select a from t where a in (select a from t s group by t.b)",
plan: "Join{DataScan(t)->DataScan(s)->Aggr(firstrow(s.a))->Projection}(test.t.a,a)->Projection",
plan: "Join{DataScan(t)->DataScan(s)->Aggr(firstrow(s.a))->Projection}(test.t.a,s.a)->Projection",
},
{
// This will be resolved as in sub query.
Expand Down Expand Up @@ -1190,31 +1190,31 @@ func (s *testPlanSuite) TestUniqueKeyInfo(c *C) {
ans: map[int][][]string{
1: {{"test.t.a"}},
2: {{"test.t.a"}},
3: {{"a"}},
3: {{"test.t.a"}},
},
},
{
sql: "select a, b, sum(f) from t group by b",
ans: map[int][][]string{
1: {{"test.t.f"}, {"test.t.a"}},
2: {{"test.t.a"}, {"test.t.b"}},
3: {{"a"}, {"b"}},
3: {{"test.t.a"}, {"test.t.b"}},
},
},
{
sql: "select c, d, e, sum(a) from t group by c, d, e",
ans: map[int][][]string{
1: {{"test.t.a"}},
2: {{"test.t.c", "test.t.d", "test.t.e"}},
3: {{"c", "d", "e"}},
3: {{"test.t.c", "test.t.d", "test.t.e"}},
},
},
{
sql: "select f, g, sum(a) from t",
ans: map[int][][]string{
1: {{"test.t.f"}, {"test.t.f", "test.t.g"}, {"test.t.a"}},
2: {{"test.t.f"}, {"test.t.f", "test.t.g"}},
3: {{"f"}, {"f", "g"}},
3: {{"test.t.f"}, {"test.t.f", "test.t.g"}},
},
},
{
Expand All @@ -1232,8 +1232,8 @@ func (s *testPlanSuite) TestUniqueKeyInfo(c *C) {
1: {{"test.t.f"}, {"test.t.a"}},
2: {{"test.t.f"}},
6: {{"test.t.f"}},
3: {{"f"}},
5: {{"f"}},
3: {{"test.t.f"}},
5: {{"test.t.f"}},
},
},
{
Expand Down