Skip to content

Commit

Permalink
[enhencement](planner) update and delete support use alias for target…
Browse files Browse the repository at this point in the history
… table (apache#17914)
  • Loading branch information
morrySnow authored Mar 22, 2023
1 parent b91a3b5 commit 173d684
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ DELETE FROM table_name

<version since="dev">

+ table_alias: alias of table
+ USING additional_tables: If you need to refer to additional tables in the WHERE clause to help identify the rows to be removed, then specify those table names in the USING clause. You can also use the USING clause to specify subqueries that identify the rows to be removed.

</version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ This statement is used to update the data. The UPDATE statement currently only s
#### Syntax

```sql
UPDATE target_table
UPDATE target_table [table_alias]
SET assignment_list
WHERE condition

Expand All @@ -54,7 +54,7 @@ value:
<version since="dev">

```sql
UPDATE target_table
UPDATE target_table [table_alias]
SET assignment_list
[ FROM additional_tables]
WHERE condition
Expand All @@ -72,6 +72,7 @@ UPDATE target_table

<version since="dev">

+ table_alias: alias of table
+ FROM additional_tables: Specifies one or more tables to use for selecting rows to update or for setting new values. Note that if you want use target table here, you should give it a alias explicitly.

</version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ DELETE
语法一:该语法只能指定过滤谓词

```SQL
DELETE FROM table_name [PARTITION partition_name | PARTITIONS (partition_name [, partition_name])]
DELETE FROM table_name [table_alias] [PARTITION partition_name | PARTITIONS (partition_name [, partition_name])]
WHERE
column_name op { value | value_list } [ AND column_name op { value | value_list } ...];
```
Expand All @@ -51,7 +51,7 @@ column_name op { value | value_list } [ AND column_name op { value | value_list
语法二:该语法只能在UNIQUE KEY模型表上使用

```sql
DELETE FROM table_name
DELETE FROM table_name [table_alias]
[PARTITION partition_name | PARTITIONS (partition_name [, partition_name])]
[USING additional_tables]
WHERE condition
Expand Down Expand Up @@ -79,6 +79,7 @@ DELETE FROM table_name

<version since="dev">

+ table_alias: 表的别名
+ USING additional_tables: 如果需要在WHERE语句中使用其他的表来帮助识别需要删除的行,则可以在USING中指定这些表或者查询。

</version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ UPDATE
#### Syntax

```sql
UPDATE target_table
UPDATE target_table [table_alias]
SET assignment_list
WHERE condition

Expand All @@ -54,7 +54,7 @@ value:
<version since="dev">

```sql
UPDATE target_table
UPDATE target_table [table_alias]
SET assignment_list
[ FROM additional_tables]
WHERE condition
Expand All @@ -72,12 +72,11 @@ UPDATE target_table

<version since="dev">

UPDATE_FROM
+ table_alias: 表的别名
+ FROM additional_tables: 指定一个或多个表,用于选中更新的行,或者获取更新的值。注意,如需要在此列表中再次使用目标表,需要为其显式指定别名。

</version>

+ FROM additional_tables: 指定一个或多个表,用于选中更新的行,或者获取更新的值。注意,如需要在此列表中再次使用目标表,需要为其显式指定别名。

#### Note

当前 UPDATE 语句仅支持在 UNIQUE KEY 模型上的行更新。
Expand Down
8 changes: 4 additions & 4 deletions fe/fe-core/src/main/cup/sql_parser.cup
Original file line number Diff line number Diff line change
Expand Up @@ -4187,9 +4187,9 @@ cancel_param ::=

// Delete stmt
delete_stmt ::=
KW_DELETE KW_FROM table_name:table opt_partition_names:partitionNames opt_using_clause:fromClause where_clause:wherePredicate
KW_DELETE KW_FROM table_name:table opt_table_alias:alias opt_partition_names:partitionNames opt_using_clause:fromClause where_clause:wherePredicate
{:
RESULT = new DeleteStmt(table, partitionNames, fromClause, wherePredicate);
RESULT = new DeleteStmt(new TableRef(table, alias), partitionNames, fromClause, wherePredicate);
:}
;

Expand Down Expand Up @@ -4475,9 +4475,9 @@ insert_source ::=

// update stmt
update_stmt ::=
KW_UPDATE table_name:tbl set_clause:setClause opt_from_clause:fromClause where_clause:whereClause
KW_UPDATE table_name:tbl opt_table_alias:alias set_clause:setClause opt_from_clause:fromClause where_clause:whereClause
{:
RESULT = new UpdateStmt(tbl, setClause, fromClause, whereClause);
RESULT = new UpdateStmt(new TableRef(tbl, alias), setClause, fromClause, whereClause);
:}
;

Expand Down
45 changes: 18 additions & 27 deletions fe/fe-core/src/main/java/org/apache/doris/analysis/DeleteStmt.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@

import org.apache.doris.analysis.CompoundPredicate.Operator;
import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.Database;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.KeysType;
import org.apache.doris.catalog.OlapTable;
import org.apache.doris.catalog.Table;
import org.apache.doris.catalog.TableIf;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.Config;
import org.apache.doris.common.ErrorCode;
Expand All @@ -36,31 +36,34 @@

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;

import java.util.LinkedList;
import java.util.List;

public class DeleteStmt extends DdlStmt {
private final TableName tableName;

private TableRef targetTableRef;
private TableName tableName;
private final PartitionNames partitionNames;
private final FromClause fromClause;
private final Expr wherePredicate;

private final List<Predicate> deleteConditions = new LinkedList<>();

private InsertStmt insertStmt;
private Table targetTable;
private TableIf targetTable;
private final List<SelectListItem> selectListItems = Lists.newArrayList();
private final List<String> cols = Lists.newArrayList();

public DeleteStmt(TableName tableName, PartitionNames partitionNames, Expr wherePredicate) {
this(tableName, partitionNames, null, wherePredicate);
this(new TableRef(tableName, null), partitionNames, null, wherePredicate);
}

public DeleteStmt(TableName tableName, PartitionNames partitionNames, FromClause fromClause, Expr wherePredicate) {
this.tableName = tableName;
public DeleteStmt(TableRef targetTableRef, PartitionNames partitionNames,
FromClause fromClause, Expr wherePredicate) {
this.targetTableRef = targetTableRef;
this.tableName = targetTableRef.getName();
this.partitionNames = partitionNames;
this.fromClause = fromClause;
this.wherePredicate = wherePredicate;
Expand Down Expand Up @@ -122,7 +125,7 @@ private void constructInsertStmt() throws AnalysisException {
if (!column.isVisible() && column.getName().equalsIgnoreCase(Column.DELETE_SIGN)) {
expr = new BoolLiteral(true);
} else if (column.isKey() || !column.isVisible() || (!column.isAllowNull() && !column.hasDefaultValue())) {
expr = new SlotRef(tableName, column.getName());
expr = new SlotRef(targetTableRef.getAliasAsName(), column.getName());
} else {
continue;
}
Expand All @@ -131,12 +134,11 @@ private void constructInsertStmt() throws AnalysisException {
}

FromClause fromUsedInInsert;
TableRef tableRef = new TableRef(tableName, null, partitionNames);
if (fromClause == null) {
fromUsedInInsert = new FromClause(Lists.newArrayList(tableRef));
fromUsedInInsert = new FromClause(Lists.newArrayList(targetTableRef));
} else {
fromUsedInInsert = fromClause.clone();
fromUsedInInsert.getTableRefs().add(0, tableRef);
fromUsedInInsert.getTableRefs().add(0, targetTableRef);
}
SelectStmt selectStmt = new SelectStmt(
// select list
Expand All @@ -163,12 +165,14 @@ private void constructInsertStmt() throws AnalysisException {
null);
}

private void analyzeTargetTable(Analyzer analyzer) throws AnalysisException {
private void analyzeTargetTable(Analyzer analyzer) throws UserException {
// step1: analyze table name and origin table alias
if (tableName == null) {
throw new AnalysisException("Table is not set");
}
tableName.analyze(analyzer);
targetTableRef = analyzer.resolveTableRef(targetTableRef);
targetTableRef.analyze(analyzer);
tableName = targetTableRef.getName();
// disallow external catalog
Util.prohibitExternalCatalog(tableName.getCtl(), this.getClass().getSimpleName());
// check load privilege, select privilege will check when analyze insert stmt
Expand All @@ -180,24 +184,11 @@ private void analyzeTargetTable(Analyzer analyzer) throws AnalysisException {
}

// step2: resolve table name with catalog, only unique olap table could be updated with using
String dbName = tableName.getDb();
String targetTableName = tableName.getTbl();
Preconditions.checkNotNull(dbName);
Preconditions.checkNotNull(targetTableName);
Database database = Env.getCurrentInternalCatalog().getDbOrAnalysisException(dbName);
targetTable = database.getTableOrAnalysisException(tableName.getTbl());
targetTable = targetTableRef.getTable();
if (fromClause != null && (targetTable.getType() != Table.TableType.OLAP
|| ((OlapTable) targetTable).getKeysType() != KeysType.UNIQUE_KEYS)) {
throw new AnalysisException("Only unique table could use delete with using.");
}

// step3: register table to ensure we could analyze column name on the left side of set exprs.
targetTable.readLock();
try {
analyzer.registerOlapTable(targetTable, tableName, null);
} finally {
targetTable.readUnlock();
}
}

@VisibleForTesting
Expand Down
43 changes: 16 additions & 27 deletions fe/fe-core/src/main/java/org/apache/doris/analysis/UpdateStmt.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
package org.apache.doris.analysis;

import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.Database;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.KeysType;
import org.apache.doris.catalog.OlapTable;
import org.apache.doris.catalog.Table;
import org.apache.doris.catalog.TableIf;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
Expand All @@ -32,7 +32,6 @@
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.qe.SessionVariable;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;

import java.util.List;
Expand All @@ -59,21 +58,22 @@
*/
public class UpdateStmt extends DdlStmt {

private final TableName tableName;
private TableRef targetTableRef;
private TableName tableName;
private final List<BinaryPredicate> setExprs;
private final Expr whereExpr;
private final FromClause fromClause;
private InsertStmt insertStmt;
private Table targetTable;
private TableIf targetTable;
List<SelectListItem> selectListItems = Lists.newArrayList();
List<String> cols = Lists.newArrayList();

public UpdateStmt(TableName tableName, List<BinaryPredicate> setExprs, FromClause fromClause, Expr whereExpr) {
this.tableName = tableName;
public UpdateStmt(TableRef targetTableRef, List<BinaryPredicate> setExprs, FromClause fromClause, Expr whereExpr) {
this.targetTableRef = targetTableRef;
this.tableName = targetTableRef.getName();
this.setExprs = setExprs;
this.fromClause = fromClause;
this.whereExpr = whereExpr;

}

public InsertStmt getInsertStmt() {
Expand All @@ -96,12 +96,11 @@ public void analyze(Analyzer analyzer) throws UserException {
private void constructInsertStmt() {
// not use origin from clause, because we need to mod it, and this action will affect toSql().
FromClause fromUsedInInsert;
TableRef tableRef = new TableRef(tableName, null);
if (fromClause == null) {
fromUsedInInsert = new FromClause(Lists.newArrayList(tableRef));
fromUsedInInsert = new FromClause(Lists.newArrayList(targetTableRef));
} else {
fromUsedInInsert = fromClause.clone();
fromUsedInInsert.getTableRefs().add(0, tableRef);
fromUsedInInsert.getTableRefs().add(0, targetTableRef);
}
SelectStmt selectStmt = new SelectStmt(
// select list
Expand All @@ -128,9 +127,11 @@ private void constructInsertStmt() {
null);
}

private void analyzeTargetTable(Analyzer analyzer) throws AnalysisException {
private void analyzeTargetTable(Analyzer analyzer) throws UserException {
// step1: analyze table name and origin table alias
tableName.analyze(analyzer);
targetTableRef = analyzer.resolveTableRef(targetTableRef);
targetTableRef.analyze(analyzer);
tableName = targetTableRef.getName();
// disallow external catalog
Util.prohibitExternalCatalog(tableName.getCtl(), this.getClass().getSimpleName());
// check load privilege, select privilege will check when analyze insert stmt
Expand All @@ -140,23 +141,11 @@ private void analyzeTargetTable(Analyzer analyzer) throws AnalysisException {
}

// step2: resolve table name with catalog, only unique olap table could be updated
String dbName = tableName.getDb();
String targetTableName = tableName.getTbl();
Preconditions.checkNotNull(dbName);
Preconditions.checkNotNull(targetTableName);
Database database = Env.getCurrentInternalCatalog().getDbOrAnalysisException(dbName);
targetTable = database.getTableOrAnalysisException(tableName.getTbl());
targetTable = targetTableRef.getTable();
if (targetTable.getType() != Table.TableType.OLAP
|| ((OlapTable) targetTable).getKeysType() != KeysType.UNIQUE_KEYS) {
throw new AnalysisException("Only unique table could be updated.");
}
// register table to ensure we could analyze column name on the left side of set exprs.
targetTable.readLock();
try {
analyzer.registerOlapTable(targetTable, tableName, null);
} finally {
targetTable.readUnlock();
}
}

private void analyzeSetExprs(Analyzer analyzer) throws AnalysisException {
Expand Down Expand Up @@ -198,7 +187,7 @@ private void analyzeSetExprs(Analyzer analyzer) throws AnalysisException {

// step3: generate select list and insert column name list in insert stmt
for (Column column : targetTable.getColumns()) {
Expr expr = new SlotRef(tableName, column.getName());
Expr expr = new SlotRef(targetTableRef.getAliasAsName(), column.getName());
for (BinaryPredicate setExpr : setExprs) {
Expr lhs = setExpr.getChild(0);
if (((SlotRef) lhs).getColumn().equals(column)) {
Expand All @@ -213,7 +202,7 @@ private void analyzeSetExprs(Analyzer analyzer) throws AnalysisException {
@Override
public String toSql() {
StringBuilder sb = new StringBuilder("UPDATE ");
sb.append(tableName.toSql()).append("\n");
sb.append(targetTableRef.toSql()).append("\n");
sb.append(" ").append("SET ");
for (Expr setExpr : setExprs) {
sb.append(setExpr.toSql()).append(", ");
Expand Down
Loading

0 comments on commit 173d684

Please sign in to comment.