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

sql: add support for DELETE FROM ... USING #88974

Merged
merged 3 commits into from
Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/generated/sql/bnf/delete_stmt.bnf
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
delete_stmt ::=
( ( 'WITH' ( ( common_table_expr ) ( ( ',' common_table_expr ) )* ) | 'WITH' 'RECURSIVE' ( ( common_table_expr ) ( ( ',' common_table_expr ) )* ) ) | ) 'DELETE' 'FROM' ( ( ( 'ONLY' | ) table_name opt_index_flags ( '*' | ) ) | ( ( 'ONLY' | ) table_name opt_index_flags ( '*' | ) ) table_alias_name | ( ( 'ONLY' | ) table_name opt_index_flags ( '*' | ) ) 'AS' table_alias_name ) ( ( 'WHERE' a_expr ) | ) ( sort_clause | ) ( limit_clause | ) ( 'RETURNING' target_list | 'RETURNING' 'NOTHING' | )
( ( 'WITH' ( ( common_table_expr ) ( ( ',' common_table_expr ) )* ) | 'WITH' 'RECURSIVE' ( ( common_table_expr ) ( ( ',' common_table_expr ) )* ) ) | ) 'DELETE' 'FROM' ( ( ( 'ONLY' | ) table_name opt_index_flags ( '*' | ) ) | ( ( 'ONLY' | ) table_name opt_index_flags ( '*' | ) ) table_alias_name | ( ( 'ONLY' | ) table_name opt_index_flags ( '*' | ) ) 'AS' table_alias_name ) opt_using_clause ( ( 'WHERE' a_expr ) | ) ( sort_clause | ) ( limit_clause | ) ( 'RETURNING' target_list | 'RETURNING' 'NOTHING' | )
166 changes: 85 additions & 81 deletions docs/generated/sql/bnf/stmt_block.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ create_stmt ::=
| create_external_connection_stmt

delete_stmt ::=
opt_with_clause 'DELETE' 'FROM' table_expr_opt_alias_idx opt_where_clause opt_sort_clause opt_limit_clause returning_clause
opt_with_clause 'DELETE' 'FROM' table_expr_opt_alias_idx opt_using_clause opt_where_clause opt_sort_clause opt_limit_clause returning_clause

drop_stmt ::=
drop_ddl_stmt
Expand Down Expand Up @@ -597,6 +597,10 @@ table_expr_opt_alias_idx ::=
| table_name_opt_idx table_alias_name
| table_name_opt_idx 'AS' table_alias_name

opt_using_clause ::=
'USING' from_list
|

opt_sort_clause ::=
sort_clause
|
Expand Down Expand Up @@ -1769,6 +1773,9 @@ with_clause ::=
table_name_opt_idx ::=
opt_only table_name opt_index_flags opt_descendant

from_list ::=
( table_ref ) ( ( ',' table_ref ) )*

sort_clause ::=
'ORDER' 'BY' sortby_list

Expand Down Expand Up @@ -1969,9 +1976,6 @@ set_clause ::=
single_set_clause
| multiple_set_clause

from_list ::=
( table_ref ) ( ( ',' table_ref ) )*

simple_db_object_name ::=
db_object_name_component

Expand Down Expand Up @@ -2485,6 +2489,16 @@ opt_descendant ::=
'*'
|

table_ref ::=
relation_expr opt_index_flags opt_ordinality opt_alias_clause
| select_with_parens opt_ordinality opt_alias_clause
| 'LATERAL' select_with_parens opt_ordinality opt_alias_clause
| joined_table
| '(' joined_table ')' opt_ordinality alias_clause
| func_table opt_ordinality opt_func_alias_clause
| 'LATERAL' func_table opt_ordinality opt_alias_clause
| '[' row_source_extension_stmt ']' opt_ordinality opt_alias_clause

sortby_list ::=
( sortby ) ( ( ',' sortby ) )*

Expand Down Expand Up @@ -2600,16 +2614,6 @@ single_set_clause ::=
multiple_set_clause ::=
'(' insert_column_list ')' '=' in_expr

table_ref ::=
relation_expr opt_index_flags opt_ordinality opt_alias_clause
| select_with_parens opt_ordinality opt_alias_clause
| 'LATERAL' select_with_parens opt_ordinality opt_alias_clause
| joined_table
| '(' joined_table ')' opt_ordinality alias_clause
| func_table opt_ordinality opt_func_alias_clause
| 'LATERAL' func_table opt_ordinality opt_alias_clause
| '[' row_source_extension_stmt ']' opt_ordinality opt_alias_clause

type_func_name_crdb_extra_keyword ::=
'FAMILY'

Expand Down Expand Up @@ -3058,6 +3062,43 @@ common_table_expr ::=
index_flags_param_list ::=
( index_flags_param ) ( ( ',' index_flags_param ) )*

opt_ordinality ::=
'WITH' 'ORDINALITY'
|

opt_alias_clause ::=
alias_clause
|

joined_table ::=
'(' joined_table ')'
| table_ref 'CROSS' opt_join_hint 'JOIN' table_ref
| table_ref join_type opt_join_hint 'JOIN' table_ref join_qual
| table_ref 'JOIN' table_ref join_qual
| table_ref 'NATURAL' join_type opt_join_hint 'JOIN' table_ref
| table_ref 'NATURAL' 'JOIN' table_ref

alias_clause ::=
'AS' table_alias_name opt_col_def_list_no_types
| table_alias_name opt_col_def_list_no_types

func_table ::=
func_expr_windowless
| 'ROWS' 'FROM' '(' rowsfrom_list ')'

opt_func_alias_clause ::=
func_alias_clause
|

row_source_extension_stmt ::=
delete_stmt
| explain_stmt
| insert_stmt
| select_stmt
| show_stmt
| update_stmt
| upsert_stmt

sortby ::=
a_expr opt_asc_desc opt_nulls_order
| 'PRIMARY' 'KEY' table_name opt_asc_desc
Expand Down Expand Up @@ -3117,43 +3158,6 @@ var_list ::=
schema_wildcard ::=
wildcard_pattern

opt_ordinality ::=
'WITH' 'ORDINALITY'
|

opt_alias_clause ::=
alias_clause
|

joined_table ::=
'(' joined_table ')'
| table_ref 'CROSS' opt_join_hint 'JOIN' table_ref
| table_ref join_type opt_join_hint 'JOIN' table_ref join_qual
| table_ref 'JOIN' table_ref join_qual
| table_ref 'NATURAL' join_type opt_join_hint 'JOIN' table_ref
| table_ref 'NATURAL' 'JOIN' table_ref

alias_clause ::=
'AS' table_alias_name opt_col_def_list_no_types
| table_alias_name opt_col_def_list_no_types

func_table ::=
func_expr_windowless
| 'ROWS' 'FROM' '(' rowsfrom_list ')'

opt_func_alias_clause ::=
func_alias_clause
|

row_source_extension_stmt ::=
delete_stmt
| explain_stmt
| insert_stmt
| select_stmt
| show_stmt
| update_stmt
| upsert_stmt

type_func_name_no_crdb_extra_keyword ::=
'AUTHORIZATION'
| 'COLLATION'
Expand Down Expand Up @@ -3483,6 +3487,30 @@ index_flags_param ::=
| 'FORCE_ZIGZAG'
| 'FORCE_ZIGZAG' '=' index_name

opt_join_hint ::=
'HASH'
| 'MERGE'
| 'LOOKUP'
| 'INVERTED'
|

join_type ::=
'FULL' join_outer
| 'LEFT' join_outer
| 'RIGHT' join_outer
| 'INNER'

join_qual ::=
'USING' '(' name_list ')'
| 'ON' a_expr

rowsfrom_list ::=
( rowsfrom_item ) ( ( ',' rowsfrom_item ) )*

func_alias_clause ::=
'AS' table_alias_name opt_col_def_list
| table_alias_name opt_col_def_list

opt_asc_desc ::=
'ASC'
| 'DESC'
Expand Down Expand Up @@ -3515,30 +3543,6 @@ opt_nowait_or_skip ::=
wildcard_pattern ::=
name '.' '*'

opt_join_hint ::=
'HASH'
| 'MERGE'
| 'LOOKUP'
| 'INVERTED'
|

join_type ::=
'FULL' join_outer
| 'LEFT' join_outer
| 'RIGHT' join_outer
| 'INNER'

join_qual ::=
'USING' '(' name_list ')'
| 'ON' a_expr

rowsfrom_list ::=
( rowsfrom_item ) ( ( ',' rowsfrom_item ) )*

func_alias_clause ::=
'AS' table_alias_name opt_col_def_list
| table_alias_name opt_col_def_list

func_arg ::=
func_arg_class param_name func_arg_type
| param_name func_arg_class func_arg_type
Expand Down Expand Up @@ -3752,12 +3756,6 @@ func_as ::=
col_def_list_no_types ::=
( name ) ( ( ',' name ) )*

group_by_item ::=
a_expr

window_definition ::=
window_name 'AS' window_specification

join_outer ::=
'OUTER'
|
Expand All @@ -3768,6 +3766,12 @@ rowsfrom_item ::=
opt_col_def_list ::=
'(' col_def_list ')'

group_by_item ::=
a_expr

window_definition ::=
window_name 'AS' window_specification

func_arg_class ::=
'IN'

Expand Down
31 changes: 28 additions & 3 deletions pkg/sql/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ type deleteRun struct {
traceKV bool

// partialIndexDelValsOffset is the offset of partial index delete
// indicators in the source values. It is equal to the number of fetched
// columns.
// indicators in the source values. It is equal to the sum of the number
// of fetched columns and the number of passthrough columns.
partialIndexDelValsOffset int

// rowIdxToRetIdx is the mapping from the columns returned by the deleter
Expand All @@ -60,6 +60,11 @@ type deleteRun struct {
// of the mutation. Otherwise, the value at the i-th index refers to the
// index of the resultRowBuffer where the i-th column is to be returned.
rowIdxToRetIdx []int

// numPassthrough is the number of columns in addition to the set of columns
// of the target table being returned, that must be passed through from the
// input node.
numPassthrough int
}

var _ mutationPlanNode = &deleteNode{}
Expand Down Expand Up @@ -184,12 +189,32 @@ func (d *deleteNode) processSourceRow(params runParams, sourceVals tree.Datums)
// d.run.rows.NumCols() is guaranteed to only contain the requested
// public columns.
resultValues := make(tree.Datums, d.run.td.rows.NumCols())
for i, retIdx := range d.run.rowIdxToRetIdx {
largestRetIdx := -1
for i := range d.run.rowIdxToRetIdx {
retIdx := d.run.rowIdxToRetIdx[i]
if retIdx >= 0 {
if retIdx >= largestRetIdx {
largestRetIdx = retIdx
}
resultValues[retIdx] = sourceVals[i]
}
}

// At this point we've extracted all the RETURNING values that are part
// of the target table. We must now extract the columns in the RETURNING
// clause that refer to other tables (from the USING clause of the delete).
if d.run.numPassthrough > 0 {
passthroughBegin := len(d.run.td.rd.FetchCols)
passthroughEnd := passthroughBegin + d.run.numPassthrough
passthroughValues := sourceVals[passthroughBegin:passthroughEnd]

for i := 0; i < d.run.numPassthrough; i++ {
largestRetIdx++
resultValues[largestRetIdx] = passthroughValues[i]
}

}

if _, err := d.run.td.rows.AddRow(params.ctx, resultValues); err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/distsql_spec_exec_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,7 @@ func (e *distSQLSpecExecFactory) ConstructDelete(
table cat.Table,
fetchCols exec.TableColumnOrdinalSet,
returnCols exec.TableColumnOrdinalSet,
passthrough colinfo.ResultColumns,
autoCommit bool,
) (exec.Node, error) {
return nil, unimplemented.NewWithIssue(47473, "experimental opt-driven distsql planning: delete")
Expand Down
1 change: 0 additions & 1 deletion pkg/sql/logictest/testdata/logic_test/cursor
Original file line number Diff line number Diff line change
Expand Up @@ -598,4 +598,3 @@ FETCH 1 a b;

statement ok
COMMIT;

Loading