Skip to content

Commit

Permalink
HIVE-24315. Improve validation and error handling in HPL/SQL (amagyar…
Browse files Browse the repository at this point in the history
…) (Attila Magyar via Mustafa Iman)
  • Loading branch information
zeroflag authored Mar 24, 2021
1 parent cc0a707 commit e67126b
Show file tree
Hide file tree
Showing 113 changed files with 847 additions and 705 deletions.
5 changes: 5 additions & 0 deletions hplsql/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
56 changes: 27 additions & 29 deletions hplsql/src/main/antlr4/org/apache/hive/hplsql/Hplsql.g4
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ single_block_stmt : // Single BEGIN END blo
block_end :
{!_input.LT(2).getText().equalsIgnoreCase("TRANSACTION")}? T_END
;

proc_block :
begin_end_block
| stmt+ T_GO?
Expand Down Expand Up @@ -168,7 +168,7 @@ break_stmt :
call_stmt :
T_CALL ident (T_OPEN_P expr_func_params? T_CLOSE_P | expr_func_params)?
;

declare_stmt : // Declaration statement
T_DECLARE declare_stmt_item (T_COMMA declare_stmt_item)*
;
Expand All @@ -177,31 +177,31 @@ declare_block : // Declaration block
T_DECLARE declare_stmt_item T_SEMICOLON (declare_stmt_item T_SEMICOLON)*
;

declare_block_inplace :
declare_block_inplace :
declare_stmt_item T_SEMICOLON (declare_stmt_item T_SEMICOLON)*
;

declare_stmt_item :
declare_cursor_item
| declare_condition_item
| declare_condition_item
| declare_handler_item
| declare_var_item
| declare_var_item
| declare_temporary_table_item
;

declare_var_item :
ident (T_COMMA ident)* T_AS? dtype dtype_len? dtype_attr* dtype_default?
| ident T_CONSTANT T_AS? dtype dtype_len? dtype_default
ident (T_COMMA ident)* T_AS? dtype dtype_len? dtype_attr* dtype_default?
| ident T_CONSTANT T_AS? dtype dtype_len? dtype_default
;

declare_condition_item : // Condition declaration
declare_condition_item : // Condition declaration
ident T_CONDITION
;
declare_cursor_item : // Cursor declaration

declare_cursor_item : // Cursor declaration
(T_CURSOR ident | ident T_CURSOR) (cursor_with_return | cursor_without_return)? (T_IS | T_AS | T_FOR) (select_stmt | expr )
;

cursor_with_return :
T_WITH T_RETURN T_ONLY? (T_TO (T_CALLER | T_CLIENT))?
;
Expand Down Expand Up @@ -360,7 +360,7 @@ alter_table_add_constraint_item :
| T_FOREIGN T_KEY T_OPEN_P ident (T_COMMA ident)* T_CLOSE_P T_REFERENCES table_name T_OPEN_P ident (T_COMMA ident)* T_CLOSE_P create_table_fk_action*
| T_DEFAULT expr T_FOR ident
;

dtype : // Data types
T_CHAR
| T_CHARACTER
Expand Down Expand Up @@ -401,18 +401,18 @@ dtype : // Data types
| T_XML
| ident ('%' (T_TYPE | T_ROWTYPE))? // User-defined or derived data type
;

dtype_len : // Data type length or size specification
T_OPEN_P (L_INT | T_MAX) (T_CHAR | T_BYTE)? (T_COMMA L_INT)? T_CLOSE_P
;

dtype_attr :
T_NOT? T_NULL
| T_CHARACTER T_SET ident
| T_NOT? (T_CASESPECIFIC | T_CS)
;

dtype_default :
dtype_default :
T_COLON? T_EQUAL expr
| T_WITH? T_DEFAULT expr?
;
Expand Down Expand Up @@ -463,7 +463,7 @@ package_body_item :
;

create_procedure_stmt :
(T_ALTER | T_CREATE (T_OR T_REPLACE)? | T_REPLACE)? (T_PROCEDURE | T_PROC) ident create_routine_params? create_routine_options? (T_AS | T_IS)? declare_block_inplace? label? proc_block (ident T_SEMICOLON)?
(T_ALTER | T_CREATE (T_OR T_REPLACE)? | T_REPLACE)? (T_PROCEDURE | T_PROC) ident create_routine_params? create_routine_options? (T_AS | T_IS)? declare_block_inplace? label? proc_block (ident T_SEMICOLON)?
;

create_routine_params :
Expand Down Expand Up @@ -589,7 +589,7 @@ leave_stmt :
;

map_object_stmt :
T_MAP T_OBJECT expr (T_TO expr)? (T_AT expr)?
T_MAP T_OBJECT ident (T_TO ident)? (T_AT ident)?
;

open_stmt : // OPEN cursor statement
Expand Down Expand Up @@ -668,8 +668,8 @@ index_storage_clause :
index_mssql_storage_clause :
T_WITH T_OPEN_P ident T_EQUAL ident (T_COMMA ident T_EQUAL ident)* T_CLOSE_P create_table_options_mssql_item*
;
print_stmt : // PRINT statement

print_stmt : // PRINT statement
T_PRINT expr
| T_PRINT T_OPEN_P expr T_CLOSE_P
;
Expand Down Expand Up @@ -1004,10 +1004,8 @@ bool_expr_binary_operator :

expr :
expr interval_item
| expr T_MUL expr
| expr T_DIV expr
| expr T_ADD expr
| expr T_SUB expr
| expr (T_MUL | T_DIV) expr
| expr (T_ADD | T_SUB) expr
| T_OPEN_P select_stmt T_CLOSE_P
| T_OPEN_P expr T_CLOSE_P
| expr_interval
Expand Down Expand Up @@ -1209,7 +1207,7 @@ bool_literal : // Boolean literal
null_const : // NULL constant
T_NULL
;

non_reserved_words : // Tokens that are not reserved words and can be used as identifiers
T_ACTION
| T_ACTIVITY_COUNT
Expand Down Expand Up @@ -1243,7 +1241,7 @@ non_reserved_words : // Tokens that are not reserved words
| T_CASE
| T_CASESPECIFIC
| T_CAST
| T_CHAR
| T_CHAR
| T_CHARACTER
| T_CHARSET
| T_CLIENT
Expand All @@ -1258,11 +1256,11 @@ non_reserved_words : // Tokens that are not reserved words
| T_CONSTANT
| T_COPY
| T_COMMIT
| T_CONCAT
| T_CONCAT
| T_CONDITION
| T_CONSTRAINT
| T_CONTINUE
| T_COUNT
| T_COUNT
| T_COUNT_BIG
| T_CREATE
| T_CREATION
Expand All @@ -1277,7 +1275,7 @@ non_reserved_words : // Tokens that are not reserved words
| T_CURSOR
| T_DATA
| T_DATABASE
| T_DATE
| T_DATE
| T_DATETIME
| T_DAY
| T_DAYS
Expand Down
28 changes: 28 additions & 0 deletions hplsql/src/main/java/org/apache/hive/hplsql/ArityException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.hive.hplsql;

import org.antlr.v4.runtime.ParserRuleContext;

public class ArityException extends HplValidationException {
public ArityException(ParserRuleContext ctx, String procName, int formalCount, int actualCount) {
super(ctx, "wrong number of arguments in call to '" + procName
+ "'. Expected " + formalCount + " got " + actualCount + ".");
}
}
71 changes: 45 additions & 26 deletions hplsql/src/main/java/org/apache/hive/hplsql/Exec.java
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ Package findPackage(String name) {
if (source.isPresent()) {
HplsqlLexer lexer = new HplsqlLexer(new ANTLRInputStream(source.get()));
CommonTokenStream tokens = new CommonTokenStream(lexer);
HplsqlParser parser = new HplsqlParser(tokens);
HplsqlParser parser = newParser(tokens);
exec.packageLoading = true;
try {
visit(parser.program());
Expand Down Expand Up @@ -754,7 +754,12 @@ public Integer run(String[] args) throws Exception {
if (init(args) != 0) {
return 1;
}
Var result = run();
Var result = null;
try {
result = run();
} catch (HplValidationException e) {
signal(Signal.Type.VALIDATION, e.getMessage(), e);
}
if (result != null) {
console.printLine(result.toString());
}
Expand Down Expand Up @@ -835,7 +840,7 @@ public Integer init(String[] args) throws Exception {
}
HplsqlLexer lexer = new HplsqlLexer(new ANTLRInputStream(input));
CommonTokenStream tokens = new CommonTokenStream(lexer);
HplsqlParser parser = new HplsqlParser(tokens);
HplsqlParser parser = newParser(tokens);
tree = parser.program();
if (trace) {
console.printError("Configuration file: " + conf.getLocation());
Expand All @@ -845,6 +850,14 @@ public Integer init(String[] args) throws Exception {
return 0;
}

private HplsqlParser newParser(CommonTokenStream tokens) {
HplsqlParser parser = new HplsqlParser(tokens);
// the default listener logs into stdout, overwrite it with a custom listener that uses beeline console
parser.removeErrorListeners();
parser.addErrorListener(new SyntaxErrorReporter(console));
return parser;
}

/**
* Parse command line arguments
*/
Expand Down Expand Up @@ -921,7 +934,7 @@ void include(String content) throws Exception {
InputStream input = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
HplsqlLexer lexer = new HplsqlLexer(new ANTLRInputStream(input));
CommonTokenStream tokens = new CommonTokenStream(lexer);
HplsqlParser parser = new HplsqlParser(tokens);
HplsqlParser parser = newParser(tokens);
ParseTree tree = parser.program();
visit(tree);
}
Expand All @@ -948,12 +961,12 @@ public Integer visitBegin_end_block(HplsqlParser.Begin_end_blockContext ctx) {
public Var eval(String source) {
HplsqlLexer lexer = new HplsqlLexer(new ANTLRInputStream(source));
CommonTokenStream tokens = new CommonTokenStream(lexer);
HplsqlParser parser = new HplsqlParser(tokens);
HplsqlParser parser = newParser(tokens);
HplsqlParser.ProgramContext program = parser.program();
visit(program);
return !exec.stack.isEmpty() ? exec.stackPop() : null;
}

/**
* Free resources before exit
*/
Expand All @@ -974,14 +987,18 @@ void cleanup() {
void printExceptions() {
while (!signals.empty()) {
Signal sig = signals.pop();
if (sig.type == Signal.Type.SQLEXCEPTION) {
if (sig.type == Signal.Type.VALIDATION) {
error(((HplValidationException)sig.exception).getCtx(), sig.exception.getMessage());
} else if (sig.type == Signal.Type.SQLEXCEPTION) {
console.printError("Unhandled exception in HPL/SQL");
}
if (sig.exception != null) {
} else if (sig.type == Signal.Type.UNSUPPORTED_OPERATION) {
console.printError(sig.value == null ? "Unsupported operation" : sig.value);
} else if (sig.exception != null) {
sig.exception.printStackTrace();
}
else if (sig.value != null) {
} else if (sig.value != null) {
console.printError(sig.value);
} else {
trace(null, "Signal: " + sig.type);
}
}
}
Expand Down Expand Up @@ -1705,7 +1722,9 @@ public Integer visitExpr_func(HplsqlParser.Expr_funcContext ctx) {
executed = packCallContext.execFunc(name, ctx.expr_func_params());
}
if (!executed) {
exec.functions.exec(name, ctx.expr_func_params());
if (!exec.functions.exec(name, ctx.expr_func_params())) {
throw new UndefinedIdentException(ctx, name);
}
}
}
return 0;
Expand Down Expand Up @@ -1994,19 +2013,19 @@ public Integer visitTruncate_stmt(HplsqlParser.Truncate_stmtContext ctx) {
*/
@Override
public Integer visitMap_object_stmt(HplsqlParser.Map_object_stmtContext ctx) {
String source = evalPop(ctx.expr(0)).toString();
String source = ctx.ident(0).getText();
String target = null;
String conn = null;
if (ctx.T_TO() != null) {
target = evalPop(ctx.expr(1)).toString();
target = ctx.ident(1).getText();
exec.objectMap.put(source.toUpperCase(), target);
}
if (ctx.T_AT() != null) {
if (ctx.T_TO() == null) {
conn = evalPop(ctx.expr(1)).toString();
conn = ctx.ident(1).getText();
}
else {
conn = evalPop(ctx.expr(2)).toString();
conn = ctx.ident(2).getText();
}
exec.objectConnMap.put(source.toUpperCase(), conn);
}
Expand Down Expand Up @@ -2256,24 +2275,24 @@ public Integer visitIdent(HplsqlParser.IdentContext ctx) {
Var var1 = new Var(var);
var1.negate();
exec.stackPush(var1);
}
else {
} else {
exec.stackPush(var);
}
}
else {
} else {
exec.stackPush(new Var(ident, Var.Type.STRING, var.toSqlString()));
}
}
else {
if (!exec.buildSql && !exec.inCallStmt && exec.functions.exec(ident.toUpperCase(), null)) {
return 0;
} else {
} else {
if (exec.buildSql || exec.inCallStmt) {
exec.stackPush(new Var(Var.Type.IDENT, ident));
} else {
ident = ident.toUpperCase();
if (!exec.functions.exec(ident, null)) {
throw new UndefinedIdentException(ctx, ident);
}
}
}
return 0;
}
}

/**
* Single quoted string literal
Expand Down
Loading

0 comments on commit e67126b

Please sign in to comment.