-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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,executor: make load data
support user_var
in column list and set
clause
#7707
Conversation
load data
support set
clause and user_var
in column listload data
support user_var
in column list and set
clause
/run-all-tests |
/run-all-tests tidb-test=pr/627 |
parser/parser.y
Outdated
@@ -593,7 +593,10 @@ import ( | |||
ColumnNameList "column name list" | |||
ColumnList "column list" | |||
ColumnNameListOpt "column name list opt" | |||
ColumnNameListOptWithBrackets "column name list opt with brackets" | |||
ColumnOrVarListOptWithBrackets "column or variable list opt with brackets" | |||
ColumnOrVarList "column or variable list" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep aligning.
planner/core/planbuilder.go
Outdated
@@ -1267,27 +1267,62 @@ func (b *planBuilder) buildSelectPlanOfInsert(insert *ast.InsertStmt, insertPlan | |||
return nil | |||
} | |||
|
|||
func (b *planBuilder) buildSetValuesOfLoadData(ld *ast.LoadDataStmt, ldPlan *LoadData, mockTablePlan *LogicalTableDual) error { | |||
colNames := make([]string, 0, len(ld.SetList)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where to use it?
planner/core/planbuilder.go
Outdated
exprCols = append(exprCols, exprCol) | ||
} | ||
|
||
for i, assign := range ld.SetList { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we merge this loop with the above one?
planner/core/common_plans.go
Outdated
LinesInfo *ast.LinesClause | ||
IgnoreLines uint64 | ||
SetList []*expression.Assignment | ||
tableSchema *expression.Schema | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could remove this empty line now.
parser/parser.y
Outdated
ColumnOrVar: | ||
UserVariable | ||
{ | ||
$$ = &ast.ColNameOrVar{VariableExpr: $1.(*ast.VariableExpr)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keep aligning.
parser/parser.y
Outdated
} | ||
| ColumnName | ||
{ | ||
$$ = &ast.ColNameOrVar{ColumnName: $1.(*ast.ColumnName)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keep aligning.
parser/parser.y
Outdated
} | ||
|
||
LoadDataSetOpt: | ||
/* EMPTY */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keep aligning
/run-all-tests tidb-test=pr/627 |
executor/insert_common.go
Outdated
Columns []*ast.ColumnName | ||
Lists [][]expression.Expression | ||
SetList []*expression.Assignment | ||
ColNameOrVars []*ast.ColNameOrVar |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
emmm... I think this element is used only for load data. Could we move it out?
server/server_test.go
Outdated
dbt.Check(err, IsNil) | ||
dbt.Check(*aa, DeepEquals, 0) | ||
dbt.Check(*bb, DeepEquals, 0) | ||
//dbt.Check(cc, DeepEquals, ([]uint8)(nil)) FIXME: stranger |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should it be fixed?
@coocood |
executor/builder.go
Outdated
} | ||
colsBind, err := table.FindCols(tableCols, columns, e.Table.Meta().PKIsHandle) | ||
if err != nil { | ||
return nil, 0, errors.Errorf("LOAD DATA SET %s: %s", e.Table.Meta().Name.O, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what kind of error will MySQL returned?
planner/core/planbuilder.go
Outdated
return errors.Trace(err) | ||
} | ||
if exprCol == nil { | ||
return errors.Errorf("Can't find column %s", assign.Column) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to return the same error as MySQL does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rest LGTM
PTAL @jackysp |
executor/load_data.go
Outdated
} | ||
} | ||
|
||
mRow := chunk.MutRowFromDatums(row).ToRow() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we skip this if the SetList is nil?
PTAL @jackysp @tiancaiamao |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
ast/dml.go
Outdated
@@ -685,11 +686,20 @@ func (n *LoadDataStmt) Accept(v Visitor) (Node, bool) { | |||
n.Table = node.(*TableName) | |||
} | |||
for i, val := range n.Columns { | |||
node, ok := val.Accept(v) | |||
if colExpr, isCol := val.(*ColumnNameExpr); isCol { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about this
switch val.(type) {
case *ColumnNameExpr:
case *VariableExpr:
}
ast/dml.go
Outdated
@@ -664,10 +664,11 @@ type LoadDataStmt struct { | |||
IsLocal bool | |||
Path string | |||
Table *TableName | |||
Columns []*ColumnName | |||
Columns []ExprNode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename it to ColumnOrVars ?
if colName, isCol := colOrVar.(*ast.ColumnNameExpr); isCol { | ||
columns = append(columns, colName.Name.Name.O) | ||
} else { | ||
columns = append(columns, "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
table.FindCols(tableCols, "", ...)
What's the purpose of this line ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
had added some comments to this line in code :)
executor/builder.go
Outdated
@@ -559,6 +559,55 @@ func (b *executorBuilder) buildInsert(v *plannercore.Insert) Executor { | |||
return insert | |||
} | |||
|
|||
func getColumnInfo4LoadData(e *InsertValues, tableCols []*table.Column, colOrVars []ast.ExprNode) ([]*table.Column, int, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add comment for the returned int value
server/server_test.go
Outdated
t.Assert(outB, Equals, "23:59:59") | ||
}) | ||
} | ||
|
||
func runTestLoadDataWithSet(c *C, server *Server) { | ||
path := "/tmp/load_data_test2.csv" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider this API:
https://godoc.org/io/ioutil#TempFile
bb *int | ||
cc []uint8 | ||
) | ||
rows := dbt.mustQuery("select a, b, c from t") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This kind of code could be simplified with the util/testkit
utilities.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems server_test.go
never use testkit
? 😹 because testkit is kv.Storage
based, and integration test need sql.DB
?
mRow := chunk.MutRowFromDatums(row).ToRow() | ||
for _, setExpr := range e.SetList { | ||
colInfo := e.colInfo[i] | ||
v, err := setExpr.Expr.Eval(mRow) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here need wait #7935 , can reuse one buffer instead renew row by row.
any update? |
What problem does this PR solve?
fixes #7404
from: https://dev.mysql.com/doc/refman/5.7/en/load-data.html
LOAD DATA
supportthis PR, make TiDB support
SET
clause anduser_var
(we are alreay support col_name) which make user have ability to change data during loading data(like exchange column order or call some function to transform), also some type likebinary
's import require this feature(just as mysql-doc said).What is changed and how it works?
set
and@xx
in load dataCheck List
Tests
Code changes
Side effects
Related changes
This change is
Remain question
ignore
/replace
is unsupportenclosed by
still unsupport