This is an automated email from the ASF dual-hosted git repository.
krisztiankasa pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/master by this push:
new feda35389dc HIVE-27491: HPL/SQL does not allow variables in update
statements (Dayakar M, reviewed by Krisztian Kasa)
feda35389dc is described below
commit feda35389dc28c8c9bf3c8a3d39de53ba90e41c0
Author: Dayakar M <[email protected]>
AuthorDate: Mon Nov 20 10:22:43 2023 +0530
HIVE-27491: HPL/SQL does not allow variables in update statements (Dayakar
M, reviewed by Krisztian Kasa)
---
.../src/main/java/org/apache/hive/hplsql/Exec.java | 46 +++++++++--
.../src/main/java/org/apache/hive/hplsql/Stmt.java | 91 ++++++++++++++++------
hplsql/src/test/queries/offline/update.sql | 15 ++--
hplsql/src/test/results/offline/update.out.txt | 40 ++++++----
4 files changed, 141 insertions(+), 51 deletions(-)
diff --git a/hplsql/src/main/java/org/apache/hive/hplsql/Exec.java
b/hplsql/src/main/java/org/apache/hive/hplsql/Exec.java
index 12690126374..8d5cab92e13 100644
--- a/hplsql/src/main/java/org/apache/hive/hplsql/Exec.java
+++ b/hplsql/src/main/java/org/apache/hive/hplsql/Exec.java
@@ -206,7 +206,7 @@ public class Exec extends HplsqlBaseVisitor<Integer>
implements Closeable {
else {
var = new Var(value);
var.setName(name);
- if(exec.currentScope != null) {
+ if(exec.currentScope != null && !exec.buildSql) {
exec.currentScope.addVariable(var);
}
}
@@ -216,7 +216,7 @@ public class Exec extends HplsqlBaseVisitor<Integer>
implements Closeable {
public Var setVariable(String name) {
return setVariable(name, Var.Empty);
}
-
+
public Var setVariable(String name, String value) {
return setVariable(name, new Var(value));
}
@@ -1630,6 +1630,18 @@ public class Exec extends HplsqlBaseVisitor<Integer>
implements Closeable {
String name = ctx.ident().getText();
visit(ctx.expr());
Var var = setVariable(name);
+ StringBuilder assignments = new StringBuilder();
+ String previousAssignment = stackPop().toString();
+ if (previousAssignment != null) {
+ assignments.append(previousAssignment);
+ assignments.append(", ");
+ }
+ assignments.append(name);
+ assignments.append(" = ");
+ assignments.append(var.toString());
+ if (exec.buildSql) {
+ stackPush(assignments);
+ }
if (trace) {
trace(ctx, "SET " + name + " = " + var.toSqlString());
}
@@ -1642,17 +1654,30 @@ public class Exec extends HplsqlBaseVisitor<Integer>
implements Closeable {
@Override
public Integer
visitAssignment_stmt_multiple_item(HplsqlParser.Assignment_stmt_multiple_itemContext
ctx) {
int cnt = ctx.ident().size();
- int ecnt = ctx.expr().size();
+ int ecnt = ctx.expr().size();
+ StringBuilder identifiers = new StringBuilder("(");
+ StringBuilder expressions = new StringBuilder("(");
for (int i = 0; i < cnt; i++) {
String name = ctx.ident(i).getText();
if (i < ecnt) {
visit(ctx.expr(i));
- Var var = setVariable(name);
+ Var var = setVariable(name);
+ if (i > 0) {
+ identifiers.append(", ");
+ expressions.append(", ");
+ }
+ identifiers.append(name);
+ expressions.append(var.toString());
if (trace) {
trace(ctx, "SET " + name + " = " + var.toString());
}
}
- }
+ }
+ identifiers.append(")");
+ expressions.append(")");
+ if (exec.buildSql) {
+ stackPush(identifiers.toString() + " = " + expressions.toString());
+ }
return 0;
}
@@ -2775,9 +2800,16 @@ public class Exec extends HplsqlBaseVisitor<Integer>
implements Closeable {
/**
* Get formatted text between 2 tokens
*/
- public static String getFormattedText(ParserRuleContext ctx) {
+ public static String getFormattedText(ParserRuleContext ctx, int startIndex,
int endIndex) {
return ctx.start.getInputStream().getText(
- new org.antlr.v4.runtime.misc.Interval(ctx.start.getStartIndex(),
ctx.stop.getStopIndex()));
+ new org.antlr.v4.runtime.misc.Interval(startIndex, endIndex));
+ }
+
+ /**
+ * Get formatted text between 2 tokens
+ */
+ public static String getFormattedText(ParserRuleContext ctx) {
+ return getFormattedText(ctx, ctx.start.getStartIndex(),
ctx.stop.getStopIndex());
}
/**
diff --git a/hplsql/src/main/java/org/apache/hive/hplsql/Stmt.java
b/hplsql/src/main/java/org/apache/hive/hplsql/Stmt.java
index 17bf0d08928..eac3a6d0d2d 100644
--- a/hplsql/src/main/java/org/apache/hive/hplsql/Stmt.java
+++ b/hplsql/src/main/java/org/apache/hive/hplsql/Stmt.java
@@ -35,6 +35,7 @@ import org.apache.hive.hplsql.executor.QueryException;
import org.apache.hive.hplsql.executor.QueryExecutor;
import org.apache.hive.hplsql.executor.QueryResult;
import org.apache.hive.hplsql.objects.Table;
+import org.jetbrains.annotations.NotNull;
/**
* HPL/SQL statements execution
@@ -665,7 +666,16 @@ public class Stmt {
/**
* Assignment from SELECT statement
*/
- public Integer
assignFromSelect(HplsqlParser.Assignment_stmt_select_itemContext ctx) {
+ public Integer
assignFromSelect(HplsqlParser.Assignment_stmt_select_itemContext ctx) {
+ if (exec.buildSql) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(Exec.getFormattedText(ctx, ctx.start.getStartIndex(),
ctx.select_stmt().getStart().getStartIndex()-1));
+ sb.append(evalPop(ctx.select_stmt()).toString());
+ sb.append(")");
+ exec.stackPush(sb);
+ return 0;
+ }
+
String sql = evalPop(ctx.select_stmt()).toString();
if (trace) {
trace(ctx, sql);
@@ -677,27 +687,7 @@ public class Stmt {
}
exec.setSqlSuccess();
try {
- int cnt = ctx.ident().size();
- if (query.next()) {
- for (int i = 0; i < cnt; i++) {
- Var var = exec.findVariable(ctx.ident(i).getText());
- if (var != null) {
- var.setValue(query, i);
- if (trace) {
- trace(ctx, "COLUMN: " + query.metadata().columnName(i) + ", " +
query.metadata().columnTypeName(i));
- trace(ctx, "SET " + var.getName() + " = " + var.toString());
- }
- }
- else if(trace) {
- trace(ctx, "Variable not found: " + ctx.ident(i).getText());
- }
- }
- exec.incRowCount();
- exec.setSqlSuccess();
- } else {
- exec.setSqlCode(SqlCodes.NO_DATA_FOUND);
- exec.signal(Signal.Type.NOTFOUND);
- }
+ processQueryResult(ctx, query);
} catch (QueryException e) {
exec.signal(query);
return 1;
@@ -706,7 +696,31 @@ public class Stmt {
}
return 0;
}
-
+
+ private void
processQueryResult(HplsqlParser.Assignment_stmt_select_itemContext ctx,
QueryResult query) {
+ int cnt = ctx.ident().size();
+ if (query.next()) {
+ for (int i = 0; i < cnt; i++) {
+ Var var = exec.findVariable(ctx.ident(i).getText());
+ if (var != null) {
+ var.setValue(query, i);
+ if (trace) {
+ trace(ctx, "COLUMN: " + query.metadata().columnName(i) + ", " +
query.metadata().columnTypeName(i));
+ trace(ctx, "SET " + var.getName() + " = " + var.toString());
+ }
+ }
+ else if(trace) {
+ trace(ctx, "Variable not found: " + ctx.ident(i).getText());
+ }
+ }
+ exec.incRowCount();
+ exec.setSqlSuccess();
+ } else {
+ exec.setSqlCode(SqlCodes.NO_DATA_FOUND);
+ exec.signal(Signal.Type.NOTFOUND);
+ }
+ }
+
/**
* SQL INSERT statement
*/
@@ -1152,7 +1166,14 @@ public class Stmt {
*/
public Integer update(HplsqlParser.Update_stmtContext ctx) {
trace(ctx, "UPDATE");
- String sql = exec.getFormattedText(ctx);
+ boolean oldBuildSql = exec.buildSql;
+ String sql = null;
+ try {
+ exec.buildSql = true;
+ sql = generateUpdateQuery(ctx);
+ } finally {
+ exec.buildSql = oldBuildSql;
+ }
trace(ctx, sql);
QueryResult query = queryExecutor.executeQuery(sql, ctx);
if (query.error()) {
@@ -1163,7 +1184,27 @@ public class Stmt {
query.close();
return 0;
}
-
+
+ @NotNull
+ private String generateUpdateQuery(HplsqlParser.Update_stmtContext ctx) {
+ HplsqlParser.Update_assignmentContext updateAssignmentContext =
ctx.update_assignment();
+ StringBuilder sql = new StringBuilder(
+ Exec.getFormattedText(ctx, ctx.start.getStartIndex(),
(updateAssignmentContext.start.getStartIndex() - 1)));
+ sql.append(evalPop(updateAssignmentContext).toString());
+ Token last = updateAssignmentContext.getStop();
+ HplsqlParser.Where_clauseContext whereClauseContext = ctx.where_clause();
+ if (whereClauseContext != null) {
+ exec.append(sql, evalPop(whereClauseContext).toString(), last,
whereClauseContext.getStart());
+ last = whereClauseContext.getStop();
+ }
+ HplsqlParser.Update_upsertContext updateUpsertContext =
ctx.update_upsert();
+ if (updateUpsertContext != null) {
+ exec.append(sql, Exec.getFormattedText(updateUpsertContext,
updateUpsertContext.start.getStartIndex(),
+ updateUpsertContext.stop.getStopIndex()), last,
updateUpsertContext.getStart());
+ }
+ return sql.toString();
+ }
+
/**
* DELETE statement
*/
diff --git a/hplsql/src/test/queries/offline/update.sql
b/hplsql/src/test/queries/offline/update.sql
index f40fb0fe247..0c72c1875ff 100644
--- a/hplsql/src/test/queries/offline/update.sql
+++ b/hplsql/src/test/queries/offline/update.sql
@@ -1,15 +1,15 @@
UPDATE tab T SET (c1) = TRIM(c1) WHERE T.c2 = 'A';
-UPDATE tab T
- SET c1 = TRIM(c1)
+UPDATE tab T
+ SET c1 = TRIM(c1)
WHERE T.c2 = 'A';
-
+
UPDATE tab SET c1 = '0011' WHERE c1 = '0021';
UPDATE tab T SET c1 = TRIM(c1), c3 = TRIM(c3) WHERE T.col2 = 'A';
-UPDATE tab T
- SET (c1, c3) = (TRIM(c1), TRIM(c3))
+UPDATE tab T
+ SET (c1, c3) = (TRIM(c1), TRIM(c3))
WHERE T.col2 = 'A';
UPDATE tab T
@@ -31,3 +31,8 @@ UPDATE tab T
SET c1 =
(SELECT c1 FROM tab2 C WHERE C.c1 = T.c1)
WHERE T.c2 = 'a';
+
+DECLARE var1 STRING;
+var1 := 'var1_value';
+UPDATE tab SET c2 = 'update_value' WHERE c1 = var1;
+UPDATE tab SET c2 = var1 WHERE c1 = 'var1_value';
diff --git a/hplsql/src/test/results/offline/update.out.txt
b/hplsql/src/test/results/offline/update.out.txt
index fadaac043ab..3f053b0dd9f 100644
--- a/hplsql/src/test/results/offline/update.out.txt
+++ b/hplsql/src/test/results/offline/update.out.txt
@@ -1,34 +1,46 @@
Ln:1 UPDATE
-Ln:1 UPDATE tab T SET (c1) = TRIM(c1) WHERE T.c2 = 'A'
+Ln:1 SET c1 = 'TRIM(c1)'
+Ln:1 UPDATE tab T SET c1 = TRIM(c1) WHERE T.c2 = 'A'
Ln:3 UPDATE
-Ln:3 UPDATE tab T
- SET c1 = TRIM(c1)
+Ln:4 SET c1 = 'TRIM(c1)'
+Ln:3 UPDATE tab T
+ SET c1 = TRIM(c1)
WHERE T.c2 = 'A'
Ln:7 UPDATE
+Ln:7 SET c1 = '''0011'''
Ln:7 UPDATE tab SET c1 = '0011' WHERE c1 = '0021'
Ln:9 UPDATE
+Ln:9 SET c1 = 'TRIM(c1)'
+Ln:9 SET c3 = 'TRIM(c3)'
Ln:9 UPDATE tab T SET c1 = TRIM(c1), c3 = TRIM(c3) WHERE T.col2 = 'A'
Ln:11 UPDATE
-Ln:11 UPDATE tab T
- SET (c1, c3) = (TRIM(c1), TRIM(c3))
+Ln:12 SET c1 = TRIM(c1)
+Ln:12 SET c3 = TRIM(c3)
+Ln:11 UPDATE tab T
+ SET (c1, c3) = (TRIM(c1), TRIM(c3))
WHERE T.col2 = 'A'
Ln:15 UPDATE
Ln:15 UPDATE tab T
SET (c1, c2, c3, c4) =
- (SELECT c1,
- c2,
- TRIM(c3),
- c4
+ (SELECT c1, c2, TRIM(c3), c4
FROM tab2 C
WHERE C.c1 = T.c1)
WHERE T.c2 = 'A'
Ln:25 UPDATE
+Ln:26 SET c1 = '(SELECT c1 FROM tab2 C WHERE C.c1 = T.c1)'
Ln:25 UPDATE tab T
- SET (c1) =
- (SELECT c1 FROM tab2 C WHERE C.c1 = T.c1)
+ SET c1 = (SELECT c1 FROM tab2 C WHERE C.c1 = T.c1)
WHERE T.c2 = 'a'
Ln:30 UPDATE
+Ln:31 SET c1 = '(SELECT c1 FROM tab2 C WHERE C.c1 = T.c1)'
Ln:30 UPDATE tab T
- SET c1 =
- (SELECT c1 FROM tab2 C WHERE C.c1 = T.c1)
- WHERE T.c2 = 'a'
\ No newline at end of file
+ SET c1 = (SELECT c1 FROM tab2 C WHERE C.c1 = T.c1)
+ WHERE T.c2 = 'a'
+Ln:35 DECLARE var1 STRING
+Ln:36 SET var1 = 'var1_value'
+Ln:37 UPDATE
+Ln:37 SET c2 = '''update_value'''
+Ln:37 UPDATE tab SET c2 = 'update_value' WHERE c1 = 'var1_value'
+Ln:38 UPDATE
+Ln:38 SET c2 = '''var1_value'''
+Ln:38 UPDATE tab SET c2 = 'var1_value' WHERE c1 = 'var1_value'
\ No newline at end of file