org.apache.hive.hplsql.Stmt Maven / Gradle / Ivy
The newest version!
/*
* 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 static java.util.stream.IntStream.range;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.UUID;
import java.util.stream.Collectors;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.apache.hive.hplsql.Var.Type;
import org.apache.hive.hplsql.executor.Metadata;
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
*/
public class Stmt {
Exec exec = null;
Stack stack = null;
Conf conf;
Meta meta;
Console console;
boolean trace = false;
private QueryExecutor queryExecutor;
Stmt(Exec e, QueryExecutor queryExecutor) {
exec = e;
stack = exec.getStack();
conf = exec.getConf();
meta = exec.getMeta();
trace = exec.getTrace();
console = exec.console;
this.queryExecutor = queryExecutor;;
}
/**
* ALLOCATE CURSOR statement
*/
public Integer allocateCursor(HplsqlParser.Allocate_cursor_stmtContext ctx) {
trace(ctx, "ALLOCATE CURSOR");
String name = ctx.ident(0).getText();
Var cur = null;
if (ctx.T_PROCEDURE() != null) {
cur = exec.consumeReturnCursor(ctx.ident(1).getText());
} else if (ctx.T_RESULT() != null) {
cur = exec.findVariable(ctx.ident(1).getText());
if (cur != null && cur.type != Type.RS_LOCATOR) {
cur = null;
}
}
if (cur == null) {
trace(ctx, "Cursor for procedure not found: " + name);
exec.signal(Signal.Type.SQLEXCEPTION);
return -1;
}
exec.addVariable(new Var(name, Type.CURSOR, cur.value));
return 0;
}
/**
* ASSOCIATE LOCATOR statement
*/
public Integer associateLocator(HplsqlParser.Associate_locator_stmtContext ctx) {
trace(ctx, "ASSOCIATE LOCATOR");
int cnt = ctx.ident().size();
if (cnt < 2) {
return -1;
}
String procedure = ctx.ident(cnt - 1).getText();
for (int i = 0; i < cnt - 1; i++) {
Var cur = exec.consumeReturnCursor(procedure);
if (cur != null) {
String name = ctx.ident(i).getText();
Var loc = exec.findVariable(name);
if (loc == null) {
loc = new Var(name, Type.RS_LOCATOR, cur.value);
exec.addVariable(loc);
}
else {
loc.setValue(cur.value);
}
}
}
return 0;
}
/**
* DECLARE cursor statement
*/
public Integer declareCursor(HplsqlParser.Declare_cursor_itemContext ctx) {
String name = ctx.ident().getText();
if (trace) {
trace(ctx, "DECLARE CURSOR " + name);
}
Cursor cursor = new Cursor(null);
if (ctx.expr() != null) {
cursor.setExprCtx(ctx.expr());
}
else if (ctx.select_stmt() != null) {
cursor.setSelectCtx(ctx.select_stmt());
}
if (ctx.cursor_with_return() != null) {
cursor.setWithReturn(true);
}
Var var = new Var(name, Type.CURSOR, cursor);
exec.addVariable(var);
return 0;
}
/**
* CREATE TABLE statement
*/
public Integer createTable(HplsqlParser.Create_table_stmtContext ctx) {
trace(ctx, "CREATE TABLE");
StringBuilder sql = new StringBuilder();
exec.append(sql, ctx.T_CREATE(), ctx.T_TABLE());
exec.append(sql, evalPop(ctx.table_name()).toString(), ctx.T_TABLE().getSymbol(), ctx.table_name().getStart());
Token last = ctx.table_name().getStop();
if (ctx.create_table_preoptions() != null) {
String preopt = evalPop(ctx.create_table_preoptions()).toString();
if (preopt != null) {
sql.append(" " + preopt);
}
last = ctx.create_table_preoptions().stop;
}
sql.append(createTableDefinition(ctx.create_table_definition(), last));
trace(ctx, sql.toString());
QueryResult query = queryExecutor.executeQuery(sql.toString(), ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlSuccess();
query.close();
return 0;
}
/**
* Get CREATE TABLE definition (columns or query)
*/
String createTableDefinition(HplsqlParser.Create_table_definitionContext ctx, Token last) {
StringBuilder sql = new StringBuilder();
HplsqlParser.Create_table_columnsContext colCtx = ctx.create_table_columns();
if (colCtx != null) {
int cnt = colCtx.create_table_columns_item().size();
for (int i = 0; i < cnt; i++) {
HplsqlParser.Create_table_columns_itemContext col = colCtx.create_table_columns_item(i);
if (col.create_table_column_cons() != null) {
last = col.getStop();
continue;
}
exec.append(sql, evalPop(col.column_name()).toString(), last, col.column_name().getStop());
exec.append(sql, exec.evalPop(col.dtype(), col.dtype_len()), col.column_name().getStop(), col.dtype().getStart());
last = col.getStop();
}
exec.append(sql, ctx.T_CLOSE_P().getText(), last, ctx.T_CLOSE_P().getSymbol());
}
else if (ctx.T_LIKE() != null) {
sql.append(" ").append(ctx.T_LIKE().getText()).append(" ").append(evalPop(ctx.table_name()));
}
// CREATE TABLE AS SELECT statement
else {
exec.append(sql, evalPop(ctx.select_stmt()).toString(), last, ctx.select_stmt().getStart());
if (ctx.T_CLOSE_P() != null) {
exec.append(sql, ctx.T_CLOSE_P().getText(), ctx.select_stmt().stop, ctx.T_CLOSE_P().getSymbol());
}
}
HplsqlParser.Create_table_optionsContext options = ctx.create_table_options();
if (options != null) {
String opt = evalPop(options).toString();
if (opt != null) {
sql.append(" " + opt);
}
}
return sql.toString();
}
/**
* CREATE TABLE options for Hive
*/
public Integer createTableHiveOptions(HplsqlParser.Create_table_options_hive_itemContext ctx) {
if (ctx.create_table_hive_row_format() != null) {
createTableHiveRowFormat(ctx.create_table_hive_row_format());
}
else if (ctx.T_STORED() != null) {
evalString(exec.getText(ctx));
}
return 0;
}
public Integer createTableHiveRowFormat(HplsqlParser.Create_table_hive_row_formatContext ctx) {
StringBuilder sql = new StringBuilder();
sql.append("ROW FORMAT DELIMITED");
int cnt = ctx.create_table_hive_row_format_fields().size();
for (int i = 0; i < cnt; i++) {
HplsqlParser.Create_table_hive_row_format_fieldsContext c = ctx.create_table_hive_row_format_fields(i);
if (c.T_FIELDS() != null) {
sql.append(" FIELDS TERMINATED BY " + evalPop(c.expr(0)).toSqlString());
}
else if (c.T_LINES() != null) {
sql.append(" LINES TERMINATED BY " + evalPop(c.expr(0)).toSqlString());
}
}
evalString(sql);
return 0;
}
/**
* CREATE TABLE options for MySQL
*/
public Integer createTableMysqlOptions(HplsqlParser.Create_table_options_mysql_itemContext ctx) {
if (ctx.T_COMMENT() != null) {
evalString(ctx.T_COMMENT().getText() + " " + evalPop(ctx.expr()).toSqlString());
}
return 0;
}
/**
* DECLARE TEMPORARY TABLE statement
*/
public Integer declareTemporaryTable(HplsqlParser.Declare_temporary_table_itemContext ctx) {
trace(ctx, "DECLARE TEMPORARY TABLE");
return createTemporaryTable(ctx.qident(), ctx.create_table_definition(), ctx.create_table_preoptions());
}
/**
* CREATE DATABASE | SCHEMA statement
*/
public Integer createDatabase(HplsqlParser.Create_database_stmtContext ctx) {
trace(ctx, "CREATE DATABASE");
StringBuilder sql = new StringBuilder();
sql.append(ctx.T_CREATE().getText() + " ");
if (ctx.T_DATABASE() != null) {
sql.append(ctx.T_DATABASE().getText() + " ");
}
else {
sql.append(ctx.T_SCHEMA().getText() + " ");
}
if (ctx.T_IF() != null) {
sql.append(exec.getText(ctx, ctx.T_IF().getSymbol(), ctx.T_EXISTS().getSymbol()) + " ");
}
boolean oldBuildSql = exec.buildSql;
exec.buildSql = true;
sql.append(evalPop(ctx.expr()).toString());
exec.buildSql = oldBuildSql;
int cnt = ctx.create_database_option().size();
for (int i = 0; i < cnt; i++) {
HplsqlParser.Create_database_optionContext option = ctx.create_database_option(i);
if (option.T_COMMENT() != null) {
sql.append(" " + option.T_COMMENT().getText() + " " + evalPop(option.expr()).toSqlString());
}
else if (option.T_LOCATION() != null) {
sql.append(" " + option.T_LOCATION().getText() + " " + evalPop(option.expr()).toSqlString());
}
}
trace(ctx, sql.toString());
QueryResult query = queryExecutor.executeQuery(sql.toString(), ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlSuccess();
query.close();
return 0;
}
/**
* CREATE LOCAL TEMPORARY | VOLATILE TABLE statement
*/
public Integer createLocalTemporaryTable(HplsqlParser.Create_local_temp_table_stmtContext ctx) {
trace(ctx, "CREATE LOCAL TEMPORARY TABLE");
return createTemporaryTable(ctx.qident(), ctx.create_table_definition(), ctx.create_table_preoptions());
}
/**
* Create a temporary table statement
*/
public Integer createTemporaryTable(HplsqlParser.QidentContext identCtx, HplsqlParser.Create_table_definitionContext defCtx,
HplsqlParser.Create_table_preoptionsContext optCtx) {
StringBuilder sql = new StringBuilder();
String name = identCtx.getText();
String managedName = null;
Token last = identCtx.getStop();
if (optCtx != null) {
last = optCtx.stop;
}
if (conf.tempTables == Conf.TempTables.NATIVE) {
sql.append("CREATE TEMPORARY TABLE " + name);
sql.append(createTableDefinition(defCtx, last));
}
else if (conf.tempTables == Conf.TempTables.MANAGED) {
managedName = name + "_" + UUID.randomUUID().toString().replace("-","");
if (!conf.tempTablesSchema.isEmpty()) {
managedName = conf.tempTablesSchema + "." + managedName;
}
sql.append("CREATE TABLE " + managedName);
sql.append(createTableDefinition(defCtx, last));
if (!conf.tempTablesLocation.isEmpty()) {
sql.append("\nLOCATION '" + conf.tempTablesLocation + "/" + managedName + "'");
}
if (trace) {
trace(null, "Managed table name: " + managedName);
}
}
if (trace) {
trace(null, sql.toString());
}
if (sql != null) {
QueryResult query = queryExecutor.executeQuery(sql.toString(), null);
if (query.error()) {
exec.signal(query);
return 1;
}
if (managedName != null) {
exec.addManagedTable(name, managedName);
}
exec.setSqlSuccess();
query.close();
}
return 0;
}
/**
* DESCRIBE statement
*/
public Integer describe(HplsqlParser.Describe_stmtContext ctx) {
trace(ctx, "DESCRIBE");
String sql = "DESCRIBE " + evalPop(ctx.table_name()).toString();
trace(ctx, sql);
QueryResult query = queryExecutor.executeQuery(sql, ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
try {
while (query.next()) {
for (int i = 0; i < query.columnCount(); i++) {
if (i > 0) {
console.print("\t");
}
console.print(query.column(i, String.class));
}
console.printLine("");
}
} catch (QueryException e) {
exec.signal(query);
query.close();
return 1;
}
exec.setSqlSuccess();
query.close();
return 0;
}
/**
* DROP statement
*/
public Integer drop(HplsqlParser.Drop_stmtContext ctx) {
trace(ctx, "DROP");
String sql = null;
if (ctx.T_TABLE() != null) {
sql = "DROP TABLE ";
if (ctx.T_EXISTS() != null) {
sql += "IF EXISTS ";
}
sql += evalPop(ctx.table_name()).toString();
} else if (ctx.T_PACKAGE() != null) {
exec.dropPackage(ctx, ctx.ident().getText().toUpperCase(), ctx.T_EXISTS() != null);
} else if (ctx.T_PROCEDURE() != null || ctx.T_FUNCTION() != null) {
exec.dropProcedure(ctx, ctx.ident().getText().toUpperCase(), ctx.T_EXISTS() != null);
} else if (ctx.T_DATABASE() != null || ctx.T_SCHEMA() != null) {
sql = "DROP DATABASE ";
if (ctx.T_EXISTS() != null) {
sql += "IF EXISTS ";
}
sql += evalPop(ctx.expr()).toString();
}
if (sql != null) {
trace(ctx, sql);
QueryResult query = queryExecutor.executeQuery(sql, ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlSuccess();
query.close();
}
return 0;
}
/**
* TRUNCATE statement
*/
public Integer truncate(HplsqlParser.Truncate_stmtContext ctx) {
trace(ctx, "TRUNCATE");
String sql = "TRUNCATE TABLE " + evalPop(ctx.table_name()).toString();
trace(ctx, sql);
QueryResult query = queryExecutor.executeQuery(sql, ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlSuccess();
query.close();
return 0;
}
/**
* OPEN cursor statement
*/
public Integer open(HplsqlParser.Open_stmtContext ctx) {
trace(ctx, "OPEN");
Cursor cursor = null;
Var var = null;
String cursorName = ctx.ident().getText();
String sql = null;
if (ctx.T_FOR() != null) { // SELECT statement or dynamic SQL
sql = ctx.expr() != null ? evalPop(ctx.expr()).toString() : evalPop(ctx.select_stmt()).toString();
cursor = new Cursor(sql);
var = exec.findCursor(cursorName); // Can be a ref cursor variable
if (var == null) {
var = new Var(cursorName, Type.CURSOR, cursor);
exec.addVariable(var);
} else {
var.setValue(cursor);
}
} else { // Declared cursor
var = exec.findVariable(cursorName);
if (var != null && var.type == Type.CURSOR) {
cursor = (Cursor) var.value;
if (cursor.getSqlExpr() != null) {
sql = evalPop(cursor.getSqlExpr()).toString();
cursor.setSql(sql);
} else if (cursor.getSqlSelect() != null) {
sql = evalPop(cursor.getSqlSelect()).toString();
cursor.setSql(sql);
}
}
}
if (cursor != null) {
if (trace) {
trace(ctx, cursorName + ": " + sql);
}
cursor.open(queryExecutor, ctx);
QueryResult queryResult = cursor.getQueryResult();
if (queryResult.error()) {
exec.signal(queryResult);
return 1;
} else if (!exec.getOffline()) {
exec.setSqlCode(SqlCodes.SUCCESS);
}
if (cursor.isWithReturn()) {
exec.addReturnCursor(var);
}
} else {
trace(ctx, "Cursor not found: " + cursorName);
exec.setSqlCode(SqlCodes.ERROR);
exec.signal(Signal.Type.SQLEXCEPTION);
return 1;
}
return 0;
}
/**
* FETCH cursor statement
*/
public Integer fetch(HplsqlParser.Fetch_stmtContext ctx) {
trace(ctx, "FETCH");
String name = ctx.ident(0).getText();
Var varCursor = exec.findCursor(name);
if (varCursor == null) {
trace(ctx, "Cursor not found: " + name);
exec.setSqlCode(SqlCodes.ERROR);
exec.signal(Signal.Type.SQLEXCEPTION);
return 1;
} else if (varCursor.value == null) {
trace(ctx, "Cursor not open: " + name);
exec.setSqlCode(SqlCodes.ERROR);
exec.signal(Signal.Type.SQLEXCEPTION);
return 1;
} else if (exec.getOffline()) {
exec.setSqlCode(SqlCodes.NO_DATA_FOUND);
exec.signal(Signal.Type.NOTFOUND);
return 0;
}
// Assign values from the row to local variables
try {
Cursor cursor = (Cursor) varCursor.value;
int cols = ctx.ident().size() - 1;
QueryResult queryResult = cursor.getQueryResult();
if (ctx.bulk_collect_clause() != null) {
long limit = ctx.fetch_limit() != null ? evalPop(ctx.fetch_limit().expr()).longValue() : -1;
long rowIndex = 1;
List tables = exec.intoTables(ctx, intoVariableNames(ctx, cols));
tables.forEach(Table::removeAll);
while (queryResult.next()) {
cursor.setFetch(true);
for (int i = 0; i < cols; i++) {
Table table = tables.get(i);
table.populate(queryResult, rowIndex, i);
}
rowIndex++;
if (limit != -1 && rowIndex -1 >= limit) {
break;
}
}
} else {
if(queryResult.next()) {
cursor.setFetch(true);
for(int i=0; i < cols; i++) {
Var var = exec.findVariable(ctx.ident(i + 1).getText());
if(var != null) {
if (var.type != Var.Type.ROW) {
var.setValue(queryResult, i);
} else {
var.setRowValues(queryResult);
}
if (trace) {
trace(ctx, var, queryResult.metadata(), i);
}
} else if(trace) {
trace(ctx, "Variable not found: " + ctx.ident(i + 1).getText());
}
}
exec.incRowCount();
exec.setSqlSuccess();
} else {
cursor.setFetch(false);
exec.setSqlCode(SqlCodes.NO_DATA_FOUND);
}
}
} catch (QueryException e) {
exec.setSqlCode(e);
exec.signal(Signal.Type.SQLEXCEPTION, e.getMessage(), e);
}
return 0;
}
private List intoVariableNames(HplsqlParser.Fetch_stmtContext ctx, int count) {
return range(0, count)
.mapToObj(i -> ctx.ident(i + 1).getText())
.collect(Collectors.toList());
}
/**
* CLOSE cursor statement
*/
public Integer close(HplsqlParser.Close_stmtContext ctx) {
trace(ctx, "CLOSE");
String name = ctx.L_ID().toString();
Var var = exec.findVariable(name);
if(var != null && var.type == Type.CURSOR) {
((Cursor)var.value).close();
exec.setSqlCode(SqlCodes.SUCCESS);
} else if(trace) {
trace(ctx, "Cursor not found: " + name);
}
return 0;
}
/**
* INCLUDE statement
*/
public Integer include(HplsqlParser.Include_stmtContext ctx) {
String file;
if (ctx.file_name() != null) {
file = ctx.file_name().getText();
}
else {
file = evalPop(ctx.expr()).toString();
}
trace(ctx, "INCLUDE " + file);
exec.includeFile(file, true);
return 0;
}
/**
* IF statement (PL/SQL syntax)
*/
public Integer ifPlsql(HplsqlParser.If_plsql_stmtContext ctx) {
boolean trueExecuted = false;
trace(ctx, "IF");
if (evalPop(ctx.bool_expr()).isTrue()) {
trace(ctx, "IF TRUE executed");
visit(ctx.block());
trueExecuted = true;
}
else if (ctx.elseif_block() != null) {
int cnt = ctx.elseif_block().size();
for (int i = 0; i < cnt; i++) {
if (evalPop(ctx.elseif_block(i).bool_expr()).isTrue()) {
trace(ctx, "ELSE IF executed");
visit(ctx.elseif_block(i).block());
trueExecuted = true;
break;
}
}
}
if (!trueExecuted && ctx.else_block() != null) {
trace(ctx, "ELSE executed");
visit(ctx.else_block());
}
return 0;
}
/**
* IF statement (Transact-SQL syntax)
*/
public Integer ifTsql(HplsqlParser.If_tsql_stmtContext ctx) {
trace(ctx, "IF");
visit(ctx.bool_expr());
if(exec.stackPop().isTrue()) {
trace(ctx, "IF TRUE executed");
visit(ctx.single_block_stmt(0));
}
else if(ctx.T_ELSE() != null) {
trace(ctx, "ELSE executed");
visit(ctx.single_block_stmt(1));
}
return 0;
}
/**
* IF statement (BTEQ syntax)
*/
public Integer ifBteq(HplsqlParser.If_bteq_stmtContext ctx) {
trace(ctx, "IF");
visit(ctx.bool_expr());
if (exec.stackPop().isTrue()) {
trace(ctx, "IF TRUE executed");
visit(ctx.single_block_stmt());
}
return 0;
}
/**
* Assignment from SELECT statement
*/
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);
}
QueryResult query = queryExecutor.executeQuery(sql, ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlSuccess();
try {
processQueryResult(ctx, query);
} catch (QueryException e) {
exec.signal(query);
return 1;
} finally {
query.close();
}
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
*/
public Integer insert(HplsqlParser.Insert_stmtContext ctx) {
exec.stmtConnList.clear();
if (ctx.select_stmt() != null) {
return insertSelect(ctx);
}
return insertValues(ctx);
}
/**
* SQL INSERT SELECT statement
*/
public Integer insertSelect(HplsqlParser.Insert_stmtContext ctx) {
trace(ctx, "INSERT SELECT");
StringBuilder sql = new StringBuilder();
sql.append(ctx.T_INSERT().getText() + " ");
if (ctx.T_OVERWRITE() != null) {
sql.append(ctx.T_OVERWRITE().getText() + " " + ctx.T_TABLE().getText() + " ");
}
else {
sql.append(ctx.T_INTO().getText() + " ");
if (ctx.T_TABLE() != null) {
sql.append(ctx.T_TABLE().getText() + " ");
}
}
sql.append(evalPop(ctx.table_name()).toString() + " ");
sql.append(evalPop(ctx.select_stmt()).toString());
trace(ctx, sql.toString());
QueryResult query = queryExecutor.executeQuery(sql.toString(), ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlSuccess();
query.close();
return 0;
}
/**
* SQL INSERT VALUES statement
*/
public Integer insertValues(HplsqlParser.Insert_stmtContext ctx) {
trace(ctx, "INSERT VALUES");
String table = evalPop(ctx.table_name()).toString();
String conn = exec.getObjectConnection(ctx.table_name().getText());
Conn.Type type = exec.getConnectionType(conn);
StringBuilder sql = new StringBuilder();
if (type == Conn.Type.HIVE) {
sql.append("INSERT INTO TABLE " + table + " ");
if (conf.insertValues == Conf.InsertValues.NATIVE) {
sql.append("VALUES\n(");
}
}
else {
sql.append("INSERT INTO " + table);
if (ctx.insert_stmt_cols() != null) {
sql.append(" " + exec.getFormattedText(ctx.insert_stmt_cols()));
}
sql.append(" VALUES\n(");
}
int rows = ctx.insert_stmt_rows().insert_stmt_row().size();
for (int i = 0; i < rows; i++) {
HplsqlParser.Insert_stmt_rowContext row =ctx.insert_stmt_rows().insert_stmt_row(i);
int cols = row.expr().size();
for (int j = 0; j < cols; j++) {
Var var = evalPop(row.expr(j));
String value = var.toSqlString();
if (j == 0 && type == Conn.Type.HIVE && conf.insertValues == Conf.InsertValues.SELECT ) {
sql.append("SELECT ");
}
sql.append(value);
if (j + 1 != cols) {
sql.append(", ");
}
}
if (type != Conn.Type.HIVE || conf.insertValues == Conf.InsertValues.NATIVE) {
if (i + 1 == rows) {
sql.append(")");
} else {
sql.append("),\n(");
}
}
else if (type == Conn.Type.HIVE && conf.insertValues == Conf.InsertValues.SELECT) {
if (conf.dualTable != null) {
sql.append(" FROM " + conf.dualTable);
}
if (i + 1 < rows) {
sql.append("\nUNION ALL\n");
}
}
}
if (trace) {
trace(ctx, sql.toString());
}
QueryResult query = queryExecutor.executeQuery(sql.toString(), ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlSuccess();
query.close();
return 0;
}
/**
* INSERT DIRECTORY statement
*/
public Integer insertDirectory(HplsqlParser.Insert_directory_stmtContext ctx) {
trace(ctx, "INSERT DIRECTORY");
StringBuilder sql = new StringBuilder();
sql.append(ctx.T_INSERT().getText() + " " + ctx.T_OVERWRITE().getText() + " ");
if (ctx.T_LOCAL() != null) {
sql.append(ctx.T_LOCAL().getText() + " ");
}
sql.append(ctx.T_DIRECTORY().getText() + " " + evalPop(ctx.expr_file()).toSqlString() + " ");
sql.append(evalPop(ctx.expr_select()).toString());
trace(ctx, sql.toString());
QueryResult query = queryExecutor.executeQuery(sql.toString(), ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlSuccess();
query.close();
return 0;
}
/**
* GET DIAGNOSTICS EXCEPTION statement
*/
public Integer getDiagnosticsException(HplsqlParser.Get_diag_stmt_exception_itemContext ctx) {
trace(ctx, "GET DIAGNOSTICS EXCEPTION");
Signal signal = exec.signalPeek();
if (signal == null || (signal != null && signal.type != Signal.Type.SQLEXCEPTION)) {
signal = exec.currentSignal;
}
if (signal != null) {
exec.setVariable(ctx.qident().getText(), signal.getValue());
}
return 0;
}
/**
* GET DIAGNOSTICS ROW_COUNT statement
*/
public Integer getDiagnosticsRowCount(HplsqlParser.Get_diag_stmt_rowcount_itemContext ctx) {
trace(ctx, "GET DIAGNOSTICS ROW_COUNT");
exec.setVariable(ctx.qident().getText(), exec.getRowCount());
return 0;
}
/**
* USE statement
*/
public Integer use(HplsqlParser.Use_stmtContext ctx) {
trace(ctx, "USE");
return use(ctx, ctx.T_USE().toString() + " " + meta.normalizeIdentifierPart(ctx.expr().getText()));
}
public Integer use(ParserRuleContext ctx, String sql) {
if(trace) {
trace(ctx, "SQL statement: " + sql);
}
QueryResult query = queryExecutor.executeQuery(sql, ctx);
if(query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlCode(SqlCodes.SUCCESS);
query.close();
return 0;
}
/**
* VALUES statement
*/
public Integer values(HplsqlParser.Values_into_stmtContext ctx) {
trace(ctx, "VALUES statement");
int cnt = ctx.ident().size(); // Number of variables and assignment expressions
int ecnt = ctx.expr().size();
for (int i = 0; i < cnt; i++) {
String name = ctx.ident(i).getText();
if (i < ecnt) {
visit(ctx.expr(i));
Var var = exec.setVariable(name);
if (trace) {
trace(ctx, "SET " + name + " = " + var.toString());
}
}
}
return 0;
}
/**
* WHILE statement
*/
public Integer while_(HplsqlParser.While_stmtContext ctx) {
trace(ctx, "WHILE - ENTERED");
String label = exec.labelPop();
while (true) {
if (evalPop(ctx.bool_expr()).isTrue()) {
exec.enterScope(Scope.Type.LOOP);
visit(ctx.block());
exec.leaveScope();
if (canContinue(label)) {
continue;
}
}
break;
}
trace(ctx, "WHILE - LEFT");
return 0;
}
/**
* FOR cursor statement
*/
public Integer forCursor(HplsqlParser.For_cursor_stmtContext ctx) {
trace(ctx, "FOR CURSOR - ENTERED");
exec.enterScope(Scope.Type.LOOP);
String cursor = ctx.L_ID().getText();
String sql = evalPop(ctx.select_stmt()).toString();
trace(ctx, sql);
QueryResult query = exec.queryExecutor.executeQuery(sql, ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
trace(ctx, "SELECT completed successfully");
exec.setSqlSuccess();
try {
int cols = query.columnCount();
Row row = new Row();
for (int i = 0; i < cols; i++) {
String columnName = query.metadata().columnName(i);
if (columnName.contains(".")) {
columnName = columnName.substring(columnName.lastIndexOf('.') + 1);
}
row.addColumnDefinition(columnName, query.metadata().columnTypeName(i));
}
Var var = new Var(cursor, row);
exec.addVariable(var);
while (query.next()) {
var.setRowValues(query);
if (trace) {
trace(ctx, var, query.metadata(), 0);
}
visit(ctx.block());
exec.incRowCount();
}
} catch (QueryException e) {
exec.signal(e);
query.close();
return 1;
}
exec.setSqlSuccess();
query.close();
exec.leaveScope();
trace(ctx, "FOR CURSOR - LEFT");
return 0;
}
/**
* FOR (integer range) statement
*/
public Integer forRange(HplsqlParser.For_range_stmtContext ctx) {
trace(ctx, "FOR RANGE - ENTERED");
int start = evalPop(ctx.expr(0)).intValue();
int end = evalPop(ctx.expr(1)).intValue();
int step = evalPop(ctx.expr(2), 1L).intValue();
exec.enterScope(Scope.Type.LOOP);
Var index = setIndex(start, end, ctx);
exec.addVariable(index);
for (int i = start; i <= end; i += step) {
visit(ctx.block());
updateIndex(step, index, ctx);
}
exec.leaveScope();
trace(ctx, "FOR RANGE - LEFT");
return 0;
}
public Integer unconditionalLoop(HplsqlParser.Unconditional_loop_stmtContext ctx) {
trace(ctx, "UNCONDITIONAL LOOP - ENTERED");
String label = exec.labelPop();
while (true) {
exec.enterScope(Scope.Type.LOOP);
visit(ctx.block());
exec.leaveScope();
if (!canContinue(label)) {
break;
}
}
trace(ctx, "UNCONDITIONAL LOOP - LEFT");
return 0;
}
/**
* To set the Value index for FOR Statement
*/
private Var setIndex(int start, int end, HplsqlParser.For_range_stmtContext ctx) {
if (ctx.T_REVERSE() == null)
return new Var(ctx.L_ID().getText(), Long.valueOf(start));
else
return new Var(ctx.L_ID().getText(), Long.valueOf(end));
}
/**
* To update the value of index for FOR Statement
*/
private void updateIndex(int step, Var index, HplsqlParser.For_range_stmtContext ctx) {
if (ctx.T_REVERSE() == null)
index.increment(step);
else
index.decrement(step);
}
/**
* EXEC, EXECUTE and EXECUTE IMMEDIATE statement to execute dynamic SQL or stored procedure
*/
public Integer exec(HplsqlParser.Exec_stmtContext ctx) {
if (execProc(ctx)) {
return 0;
}
trace(ctx, "EXECUTE");
Var vsql = evalPop(ctx.expr());
String sql = vsql.toString();
if (trace) {
trace(ctx, "SQL statement: " + sql);
}
QueryResult query = queryExecutor.executeQuery(sql, ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
try {
if (ctx.T_INTO() != null) {
int cols = ctx.L_ID().size();
if (query.next()) {
for (int i = 0; i < cols; i++) {
Var var = exec.findVariable(ctx.L_ID(i).getText());
if (var != null) {
if (var.type != Type.ROW) {
var.setValue(query, i);
}
else {
var.setRowValues(query);
}
if (trace) {
trace(ctx, var, query.metadata(), i);
}
}
else if (trace) {
trace(ctx, "Variable not found: " + ctx.L_ID(i).getText());
}
}
exec.setSqlCode(SqlCodes.SUCCESS);
}
}
// Print the results
else {
int cols = query.columnCount();
while(query.next()) {
for(int i = 0; i < cols; i++) {
if(i > 1) {
console.print("\t");
}
console.print(query.column(i, String.class));
}
console.printLine("");
}
}
} catch(QueryException e) {
exec.signal(query);
query.close();
return 1;
}
query.close();
return 0;
}
/**
* EXEC to execute a stored procedure
*/
public Boolean execProc(HplsqlParser.Exec_stmtContext ctx) {
String name = evalPop(ctx.expr()).toString().toUpperCase();
if (exec.functions.exec(name, ctx.expr_func_params())) {
return true;
}
return false;
}
/**
* EXIT statement (leave the specified loop with a condition)
*/
public Integer exit(HplsqlParser.Exit_stmtContext ctx) {
trace(ctx, "EXIT");
String label = "";
if (ctx.L_ID() != null) {
label = ctx.L_ID().toString();
}
if (ctx.T_WHEN() != null) {
if (evalPop(ctx.bool_expr()).isTrue()) {
leaveLoop(label);
}
} else {
leaveLoop(label);
}
return 0;
}
/**
* BREAK statement (leave the innermost loop unconditionally)
*/
public Integer break_(HplsqlParser.Break_stmtContext ctx) {
trace(ctx, "BREAK");
leaveLoop("");
return 0;
}
/**
* LEAVE statement (leave the specified loop unconditionally)
*/
public Integer leave(HplsqlParser.Leave_stmtContext ctx) {
trace(ctx, "LEAVE");
String label = "";
if (ctx.L_ID() != null) {
label = ctx.L_ID().toString();
}
leaveLoop(label);
return 0;
}
/**
* Leave the specified or innermost loop unconditionally
*/
public void leaveLoop(String value) {
exec.signal(Signal.Type.LEAVE_LOOP, value);
}
/**
* UPDATE statement
*/
public Integer update(HplsqlParser.Update_stmtContext ctx) {
trace(ctx, "UPDATE");
String sql = null;
if (exec.getOffline()) {
sql = exec.getFormattedText(ctx);
} else {
boolean oldBuildSql = exec.buildSql;
try {
exec.buildSql = true;
sql = generateUpdateQuery(ctx);
} finally {
exec.buildSql = oldBuildSql;
}
}
trace(ctx, sql);
QueryResult query = queryExecutor.executeQuery(sql, ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlSuccess();
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
*/
public Integer delete(HplsqlParser.Delete_stmtContext ctx) {
trace(ctx, "DELETE");
String table = evalPop(ctx.table_name()).toString();
StringBuilder sql = new StringBuilder();
if (ctx.T_ALL() == null) {
sql.append("DELETE FROM " + table);
if (ctx.where_clause() != null) {
boolean oldBuildSql = exec.buildSql;
exec.buildSql = true;
sql.append(" " + evalPop(ctx.where_clause()).toString());
exec.buildSql = oldBuildSql;
}
}
else {
sql.append("TRUNCATE TABLE " + table);
}
trace(ctx, sql.toString());
QueryResult query = queryExecutor.executeQuery(sql.toString(), ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlSuccess();
query.close();
return 0;
}
/**
* MERGE statement
*/
public Integer merge(HplsqlParser.Merge_stmtContext ctx) {
trace(ctx, "MERGE");
String sql = exec.getFormattedText(ctx);
trace(ctx, sql);
QueryResult query = queryExecutor.executeQuery(sql, ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlSuccess();
query.close();
return 0;
}
/**
* PRINT Statement
*/
public Integer print(HplsqlParser.Print_stmtContext ctx) {
trace(ctx, "PRINT");
if (ctx.expr() != null) {
console.printLine(evalPop(ctx.expr()).toString());
}
return 0;
}
/**
* QUIT Statement
*/
public Integer quit(HplsqlParser.Quit_stmtContext ctx) {
trace(ctx, "QUIT");
String rc = null;
if (ctx.expr() != null) {
rc = evalPop(ctx.expr()).toString();
}
exec.signal(Signal.Type.LEAVE_PROGRAM, rc);
return 0;
}
/**
* SET current schema
*/
public Integer setCurrentSchema(HplsqlParser.Set_current_schema_optionContext ctx) {
trace(ctx, "SET CURRENT SCHEMA");
return use(ctx, "USE " + meta.normalizeIdentifierPart(evalPop(ctx.expr()).toString()));
}
/**
* SIGNAL statement
*/
public Integer signal(HplsqlParser.Signal_stmtContext ctx) {
trace(ctx, "SIGNAL");
Signal signal = new Signal(Signal.Type.USERDEFINED, ctx.ident().getText());
exec.signal(signal);
return 0;
}
/**
* SUMMARY statement
*/
public Integer summary(HplsqlParser.Summary_stmtContext ctx) {
trace(ctx, "SUMMARY");
String table = null;
String select = null;
String conn = null;
Row row = null;
if (ctx.table_name() != null) {
table = evalPop(ctx.table_name()).toString();
conn = exec.getObjectConnection(table);
row = meta.getRowDataType(ctx, conn, table);
}
else {
select = evalPop(ctx.select_stmt()).toString();
conn = exec.getStatementConnection();
row = meta.getRowDataTypeForSelect(ctx, conn, select);
}
if (row == null) {
return 1;
}
Conn.Type connType = exec.getConnectionType(conn);
if (ctx.T_TOP() == null) {
return summaryStat(ctx, table, select, row, conn, connType);
}
else {
return summaryTop(ctx, table, select, row, conn, connType);
}
}
// Summary for column statistics
public Integer summaryStat(HplsqlParser.Summary_stmtContext ctx, String table, String select,
Row row, String conn, Conn.Type connType) {
StringBuilder sql = new StringBuilder("SELECT COUNT(*)");
int maxColName = 11;
// Define summary metrics for each column
for(Column c : row.getColumns()) {
String col = c.getName();
if (connType == Conn.Type.HIVE) {
col = '`' + col + '`';
}
sql.append(",COUNT(" + col + "),");
sql.append("COUNT(DISTINCT " + col + "),");
sql.append("AVG(" + col + "),");
sql.append("MIN(" + col + "),");
sql.append("MAX(" + col + "),");
sql.append("STDDEV_SAMP(" + col + "),");
sql.append("PERCENTILE_APPROX(CAST(" + col + " AS DOUBLE),0.05),");
sql.append("PERCENTILE_APPROX(CAST(" + col + " AS DOUBLE),0.25),");
sql.append("PERCENTILE_APPROX(CAST(" + col + " AS DOUBLE),0.5),");
sql.append("PERCENTILE_APPROX(CAST(" + col + " AS DOUBLE),0.75),");
sql.append("PERCENTILE_APPROX(CAST(" + col + " AS DOUBLE),0.95)");
if (col.length() > maxColName) {
maxColName = col.length();
}
}
if (table != null) {
sql.append(" FROM (SELECT * FROM " + table);
if (ctx.where_clause() != null) {
sql.append(" " + evalPop(ctx.where_clause()).toString());
}
if (ctx.T_LIMIT() != null) {
sql.append(" LIMIT ");
int limExp = 0;
if (ctx.T_TOP() != null) {
limExp = 1;
}
sql.append(evalPop(ctx.expr(limExp)).toString());
}
sql.append(") t");
}
else {
sql.append(" FROM (" + select + ") t");
}
QueryResult query = queryExecutor.executeQuery(sql.toString(), ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlSuccess();
try {
System.out.print("\n");
// The summary query returns only one row
if (query.next()) {
int i = 0, cc = 11;
String cntRows = query.column(0, String.class);
// Pad output
String fmt = String.format("%%-%ds\t%%-11s\t%%-11s\t%%-11s\t%%-11s\t%%-11s\t%%-11s\t%%-11s\t%%-11s" +
"\t%%-11s\t%%-11s\t%%-11s\t%%-11s\t%%-11s\n", maxColName + 1);
System.out.print(String.format(fmt, "Column", "Type", "Rows", "NonNull", "Unique", "Avg",
"Min", "Max", "StdDev", "p05", "p25", "p50", "p75", "p95"));
for(Column c : row.getColumns()) {
String avg = String.format("%.2f", query.column(3 + i*cc, Double.class));
String stddev = String.format("%.2f", query.column(6 + i*cc, Double.class));
String p05 = String.format("%.2f", query.column(7 + i*cc, Double.class));
String p25 = String.format("%.2f", query.column(8 + i*cc, Double.class));
String p50 = String.format("%.2f", query.column(9 + i*cc, Double.class));
String p75 = String.format("%.2f", query.column(10 + i*cc, Double.class));
String p95 = String.format("%.2f", query.column(11 + i*cc, Double.class));
System.out.print(String.format(fmt, c.getName(), c.getType(), cntRows, query.column(1 + i*cc, String.class),
query.column(2 + i*cc, String.class), avg, query.column(4 + i*cc, String.class), query.column(5 + i*cc, String.class),
stddev, p05, p25, p50, p75, p95));
i++;
}
}
}
catch (QueryException e) {
exec.signal(e);
query.close();
return 1;
}
query.close();
return 0;
}
// Summary for top column values
public Integer summaryTop(HplsqlParser.Summary_stmtContext ctx, String table, String select,
Row row, String conn, Conn.Type connType) {
StringBuilder sql = new StringBuilder("SELECT id, col, cnt FROM (" +
"SELECT id, col, cnt, ROW_NUMBER() OVER (PARTITION BY id ORDER BY cnt DESC) rn " +
"FROM (SELECT CAST(GROUPING__ID AS DECIMAL) id, COALESCE("); // CAST AS INT does not work as expected (ID is still considered as STRING in ORDER BY for some reason)
int topNum = evalPop(ctx.expr(0)).intValue();
StringBuilder colsList = new StringBuilder();
StringBuilder colsGrList = new StringBuilder();
int i = 0;
for(Column c : row.getColumns()) {
String col = c.getName();
if (connType == Conn.Type.HIVE) {
col = '`' + col + '`';
}
if (i != 0) {
colsList.append(",");
colsGrList.append(",");
}
colsList.append(col);
colsGrList.append("(" + col + ")");
i++;
}
sql.append(colsList);
sql.append(") col, COUNT(*) cnt");
if (table != null) {
sql.append(" FROM (SELECT * FROM " + table);
if (ctx.where_clause() != null) {
sql.append(" " + evalPop(ctx.where_clause()).toString());
}
if (ctx.T_LIMIT() != null) {
sql.append(" LIMIT " + evalPop(ctx.expr(1)).toString());
}
sql.append(") t");
}
else {
sql.append(" FROM (" + select + ") t");
}
sql.append(" GROUP BY ");
sql.append(colsList);
sql.append(" GROUPING SETS (");
sql.append(colsGrList);
sql.append(")) t) t WHERE rn <= " + topNum + " ORDER BY id, cnt DESC");
// Add LIMIT as Order by-s without limit can disabled for safety reasons
sql.append(" LIMIT " + topNum * row.size());
QueryResult query = queryExecutor.executeQuery(sql.toString(), ctx);
if (query.error()) {
exec.signal(query);
return 1;
}
exec.setSqlSuccess();
try {
int prevId = -1;
int grRow = 0;
int colNum = 0;
int maxLen = row.getColumn(colNum).getName().length();
ArrayList outCols = new ArrayList<>();
ArrayList outCnts = new ArrayList<>();
ArrayList outLens = new ArrayList<>();
while (query.next()) {
int id = query.column(0, Integer.class);
String value = query.column(1, String.class);
int cnt = query.column(2, Integer.class);
if (prevId == -1) {
prevId = id;
}
// Still the same column
if (id == prevId) {
outCols.add(value);
outCnts.add(cnt);
if (value != null && value.length() > maxLen) {
maxLen = Math.min(value.length(), 300);
}
grRow++;
}
// First value for next column
else {
// Pad with empty rows if the number of values in group is less than TOP num
for (int j = grRow; j < topNum; j++) {
outCols.add("");
outCnts.add(0);
grRow++;
}
outCols.add(value);
outCnts.add(cnt);
outLens.add(maxLen);
colNum++;
maxLen = row.getColumn(colNum).getName().length();
if (value != null && value.length() > maxLen) {
maxLen = Math.min(value.length(), 300);
}
grRow = 1;
prevId = id;
}
}
for (int j = grRow; j < topNum; j++) {
outCols.add("");
outCnts.add(0);
grRow++;
}
if (maxLen != 0) {
outLens.add(maxLen);
}
System.out.print("\n");
// Output header
i = 0;
for(Column c : row.getColumns()) {
if (i != 0) {
System.out.print("\t");
}
String fmt = String.format("%%-%ds", outLens.get(i) + 11 + 3);
System.out.print(String.format(fmt, c.getName()));
i++;
}
System.out.print("\n");
// Output top values
for (int j = 0; j < topNum; j++) {
for(int k = 0; k < row.size(); k++) {
if (k != 0) {
System.out.print("\t");
}
int cnt = outCnts.get(j + k * topNum);
if (cnt != 0) { // skip padded values
String fmt = String.format("%%-%ds", outLens.get(k));
System.out.print(String.format(fmt, outCols.get(j + k * topNum)));
System.out.print(String.format(" %-11d", cnt));
}
else {
String fmt = String.format("%%-%ds", outLens.get(k) + 11 + 3);
System.out.print(String.format(fmt, ""));
}
}
System.out.print("\n");
}
}
catch (QueryException e) {
exec.signal(e);
query.close();
return 1;
}
query.close();
return 0;
}
/**
* RESIGNAL statement
*/
public Integer resignal(HplsqlParser.Resignal_stmtContext ctx) {
trace(ctx, "RESIGNAL");
if (ctx.T_SQLSTATE() != null) {
String sqlstate = evalPop(ctx.expr(0)).toString();
String text = "";
if (ctx.T_MESSAGE_TEXT() != null) {
text = evalPop(ctx.expr(1)).toString();
}
SQLException exception = new SQLException(text, sqlstate, -1);
Signal signal = new Signal(Signal.Type.SQLEXCEPTION, text, exception);
exec.setSqlCode(exception);
exec.resignal(signal);
}
else {
exec.resignal();
}
return 0;
}
/**
* RETURN statement
*/
public Integer return_(HplsqlParser.Return_stmtContext ctx) {
trace(ctx, "RETURN");
if (ctx.expr() != null) {
eval(ctx.expr());
}
exec.signal(Signal.Type.LEAVE_ROUTINE);
return 0;
}
/**
* Check if an exception is raised or EXIT executed, and we should leave the block
*/
boolean canContinue(String label) {
Signal signal = exec.signalPeek();
if (signal != null && signal.type == Signal.Type.SQLEXCEPTION) {
return false;
}
signal = exec.signalPeek();
if (signal != null && signal.type == Signal.Type.LEAVE_LOOP) {
if (signal.value == null || signal.value.isEmpty() ||
(label != null && label.equalsIgnoreCase(signal.value))) {
exec.signalPop();
}
return false;
}
return true;
}
/**
* Evaluate the expression and push the value to the stack
*/
void eval(ParserRuleContext ctx) {
exec.visit(ctx);
}
/**
* Evaluate the expression to specified String value
*/
void evalString(String string) {
exec.stackPush(new Var(string));
}
void evalString(StringBuilder string) {
evalString(string.toString());
}
/**
* Evaluate the expression and pop value from the stack
*/
Var evalPop(ParserRuleContext ctx) {
visit(ctx);
if (!exec.stack.isEmpty()) {
return exec.stackPop();
}
return Var.Empty;
}
Var evalPop(ParserRuleContext ctx, long def) {
if (ctx != null) {
exec.visit(ctx);
return exec.stackPop();
}
return new Var(def);
}
/**
* Execute rules
*/
Integer visit(ParserRuleContext ctx) {
return exec.visit(ctx);
}
/**
* Execute children rules
*/
Integer visitChildren(ParserRuleContext ctx) {
return exec.visitChildren(ctx);
}
/**
* Trace information
*/
void trace(ParserRuleContext ctx, String message) {
exec.trace(ctx, message);
}
void trace(ParserRuleContext ctx, Var var, Metadata metadata, int idx) {
exec.trace(ctx, var, metadata, idx);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy