org.apache.hive.hplsql.Select Maven / Gradle / Ivy
/*
* 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 java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Stack;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.misc.Interval;
public class Select {
Exec exec = null;
Stack stack = null;
Conf conf;
boolean trace = false;
Select(Exec e) {
exec = e;
stack = exec.getStack();
conf = exec.getConf();
trace = exec.getTrace();
}
/**
* Executing or building SELECT statement
*/
public Integer select(HplsqlParser.Select_stmtContext ctx) {
if (ctx.parent instanceof HplsqlParser.StmtContext) {
exec.stmtConnList.clear();
trace(ctx, "SELECT");
}
boolean oldBuildSql = exec.buildSql;
exec.buildSql = true;
StringBuilder sql = new StringBuilder();
if (ctx.cte_select_stmt() != null) {
sql.append(evalPop(ctx.cte_select_stmt()).toString());
sql.append("\n");
}
sql.append(evalPop(ctx.fullselect_stmt()).toString());
exec.buildSql = oldBuildSql;
if (!(ctx.parent instanceof HplsqlParser.StmtContext)) { // No need to execute at this stage
exec.stackPush(sql);
return 0;
}
if (trace && ctx.parent instanceof HplsqlParser.StmtContext) {
trace(ctx, sql.toString());
}
if (exec.getOffline()) {
trace(ctx, "Not executed - offline mode set");
return 0;
}
String conn = exec.getStatementConnection();
Query query = exec.executeQuery(ctx, sql.toString(), conn);
if (query.error()) {
exec.signal(query);
return 1;
}
trace(ctx, "SELECT completed successfully");
exec.setSqlSuccess();
try {
ResultSet rs = query.getResultSet();
ResultSetMetaData rm = null;
if (rs != null) {
rm = rs.getMetaData();
}
int into_cnt = getIntoCount(ctx);
if (into_cnt > 0) {
trace(ctx, "SELECT INTO statement executed");
if (rs.next()) {
for (int i = 1; i <= into_cnt; i++) {
String into_name = getIntoVariable(ctx, i - 1);
Var var = exec.findVariable(into_name);
if (var != null) {
if (var.type != Var.Type.ROW) {
var.setValue(rs, rm, i);
}
else {
var.setValues(rs, rm);
}
if (trace) {
trace(ctx, var, rs, rm, i);
}
}
else {
trace(ctx, "Variable not found: " + into_name);
}
}
exec.incRowCount();
exec.setSqlSuccess();
}
else {
exec.setSqlCode(100);
exec.signal(Signal.Type.NOTFOUND);
}
}
// Print all results for standalone SELECT statement
else if (ctx.parent instanceof HplsqlParser.StmtContext) {
int cols = rm.getColumnCount();
if (trace) {
trace(ctx, "Standalone SELECT executed: " + cols + " columns in the result set");
}
while (rs.next()) {
for (int i = 1; i <= cols; i++) {
if (i > 1) {
System.out.print("\t");
}
System.out.print(rs.getString(i));
}
System.out.println("");
exec.incRowCount();
}
}
// Scalar subquery
else {
trace(ctx, "Scalar subquery executed, first row and first column fetched only");
if(rs.next()) {
exec.stackPush(new Var().setValue(rs, rm, 1));
exec.setSqlSuccess();
}
else {
evalNull();
exec.setSqlCode(100);
}
}
}
catch (SQLException e) {
exec.signal(query);
exec.closeQuery(query, conn);
return 1;
}
exec.closeQuery(query, conn);
return 0;
}
/**
* Common table expression (WITH clause)
*/
public Integer cte(HplsqlParser.Cte_select_stmtContext ctx) {
int cnt = ctx.cte_select_stmt_item().size();
StringBuilder sql = new StringBuilder();
sql.append("WITH ");
for (int i = 0; i < cnt; i++) {
HplsqlParser.Cte_select_stmt_itemContext c = ctx.cte_select_stmt_item(i);
sql.append(c.ident().getText());
if (c.cte_select_cols() != null) {
sql.append(" " + exec.getFormattedText(c.cte_select_cols()));
}
sql.append(" AS (");
sql.append(evalPop(ctx.cte_select_stmt_item(i).fullselect_stmt()).toString());
sql.append(")");
if (i + 1 != cnt) {
sql.append(",\n");
}
}
exec.stackPush(sql);
return 0;
}
/**
* Part of SELECT
*/
public Integer fullselect(HplsqlParser.Fullselect_stmtContext ctx) {
int cnt = ctx.fullselect_stmt_item().size();
StringBuilder sql = new StringBuilder();
for (int i = 0; i < cnt; i++) {
String part = evalPop(ctx.fullselect_stmt_item(i)).toString();
sql.append(part);
if (i + 1 != cnt) {
sql.append("\n" + getText(ctx.fullselect_set_clause(i)) + "\n");
}
}
exec.stackPush(sql);
return 0;
}
public Integer subselect(HplsqlParser.Subselect_stmtContext ctx) {
StringBuilder sql = new StringBuilder();
sql.append(ctx.start.getText());
exec.append(sql, evalPop(ctx.select_list()).toString(), ctx.start, ctx.select_list().getStart());
Token last = ctx.select_list().stop;
if (ctx.into_clause() != null) {
last = ctx.into_clause().stop;
}
if (ctx.from_clause() != null) {
exec.append(sql, evalPop(ctx.from_clause()).toString(), last, ctx.from_clause().getStart());
last = ctx.from_clause().stop;
}
else if (conf.dualTable != null) {
sql.append(" FROM " + conf.dualTable);
}
if (ctx.where_clause() != null) {
exec.append(sql, evalPop(ctx.where_clause()).toString(), last, ctx.where_clause().getStart());
last = ctx.where_clause().stop;
}
if (ctx.group_by_clause() != null) {
exec.append(sql, getText(ctx.group_by_clause()), last, ctx.group_by_clause().getStart());
last = ctx.group_by_clause().stop;
}
if (ctx.having_clause() != null) {
exec.append(sql, getText(ctx.having_clause()), last, ctx.having_clause().getStart());
last = ctx.having_clause().stop;
}
if (ctx.qualify_clause() != null) {
exec.append(sql, getText(ctx.qualify_clause()), last, ctx.qualify_clause().getStart());
last = ctx.qualify_clause().stop;
}
if (ctx.order_by_clause() != null) {
exec.append(sql, getText(ctx.order_by_clause()), last, ctx.order_by_clause().getStart());
last = ctx.order_by_clause().stop;
}
if (ctx.select_options() != null) {
Var opt = evalPop(ctx.select_options());
if (!opt.isNull()) {
sql.append(" " + opt.toString());
}
}
if (ctx.select_list().select_list_limit() != null) {
sql.append(" LIMIT " + evalPop(ctx.select_list().select_list_limit().expr()));
}
exec.stackPush(sql);
return 0;
}
/**
* SELECT list
*/
public Integer selectList(HplsqlParser.Select_listContext ctx) {
StringBuilder sql = new StringBuilder();
if (ctx.select_list_set() != null) {
sql.append(exec.getText(ctx.select_list_set())).append(" ");
}
int cnt = ctx.select_list_item().size();
for (int i = 0; i < cnt; i++) {
if (ctx.select_list_item(i).select_list_asterisk() == null) {
sql.append(evalPop(ctx.select_list_item(i).expr()));
if (ctx.select_list_item(i).select_list_alias() != null) {
sql.append(" " + exec.getText(ctx.select_list_item(i).select_list_alias()));
}
}
else {
sql.append(exec.getText(ctx.select_list_item(i).select_list_asterisk()));
}
if (i + 1 < cnt) {
sql.append(", ");
}
}
exec.stackPush(sql);
return 0;
}
/**
* FROM clause
*/
public Integer from(HplsqlParser.From_clauseContext ctx) {
StringBuilder sql = new StringBuilder();
sql.append(ctx.T_FROM().getText()).append(" ");
sql.append(evalPop(ctx.from_table_clause()));
int cnt = ctx.from_join_clause().size();
for (int i = 0; i < cnt; i++) {
sql.append(evalPop(ctx.from_join_clause(i)));
}
exec.stackPush(sql);
return 0;
}
/**
* Single table name in FROM
*/
public Integer fromTable(HplsqlParser.From_table_name_clauseContext ctx) {
StringBuilder sql = new StringBuilder();
sql.append(evalPop(ctx.table_name()));
if (ctx.from_alias_clause() != null) {
sql.append(" ").append(exec.getText(ctx.from_alias_clause()));
}
exec.stackPush(sql);
return 0;
}
/**
* Subselect in FROM
*/
public Integer fromSubselect(HplsqlParser.From_subselect_clauseContext ctx) {
StringBuilder sql = new StringBuilder();
sql.append("(");
sql.append(evalPop(ctx.select_stmt()).toString());
sql.append(")");
if (ctx.from_alias_clause() != null) {
sql.append(" ").append(exec.getText(ctx.from_alias_clause()));
}
exec.stackPush(sql);
return 0;
}
/**
* JOIN clause in FROM
*/
public Integer fromJoin(HplsqlParser.From_join_clauseContext ctx) {
StringBuilder sql = new StringBuilder();
if (ctx.T_COMMA() != null) {
sql.append(", ");
sql.append(evalPop(ctx.from_table_clause()));
}
else if (ctx.from_join_type_clause() != null) {
sql.append(" ");
sql.append(exec.getText(ctx.from_join_type_clause()));
sql.append(" ");
sql.append(evalPop(ctx.from_table_clause()));
sql.append(" ");
sql.append(exec.getText(ctx, ctx.T_ON().getSymbol(), ctx.bool_expr().getStop()));
}
exec.stackPush(sql);
return 0;
}
/**
* FROM TABLE (VALUES ...) clause
*/
public Integer fromTableValues(HplsqlParser.From_table_values_clauseContext ctx) {
StringBuilder sql = new StringBuilder();
int rows = ctx.from_table_values_row().size();
sql.append("(");
for (int i = 0; i < rows; i++) {
int cols = ctx.from_table_values_row(i).expr().size();
int cols_as = ctx.from_alias_clause().L_ID().size();
sql.append("SELECT ");
for (int j = 0; j < cols; j++) {
sql.append(evalPop(ctx.from_table_values_row(i).expr(j)));
if (j < cols_as) {
sql.append(" AS ");
sql.append(ctx.from_alias_clause().L_ID(j));
}
if (j + 1 < cols) {
sql.append(", ");
}
}
if (conf.dualTable != null) {
sql.append(" FROM " + conf.dualTable);
}
if (i + 1 < rows) {
sql.append("\nUNION ALL\n");
}
}
sql.append(") ");
if (ctx.from_alias_clause() != null) {
sql.append(ctx.from_alias_clause().ident().getText());
}
exec.stackPush(sql);
return 0;
}
/**
* WHERE clause
*/
public Integer where(HplsqlParser.Where_clauseContext ctx) {
boolean oldBuildSql = exec.buildSql;
exec.buildSql = true;
StringBuilder sql = new StringBuilder();
sql.append(ctx.T_WHERE().getText());
sql.append(" " + evalPop(ctx.bool_expr()));
exec.stackPush(sql);
exec.buildSql = oldBuildSql;
return 0;
}
/**
* Get INTO clause
*/
HplsqlParser.Into_clauseContext getIntoClause(HplsqlParser.Select_stmtContext ctx) {
if (ctx.fullselect_stmt().fullselect_stmt_item(0).subselect_stmt() != null) {
return ctx.fullselect_stmt().fullselect_stmt_item(0).subselect_stmt().into_clause();
}
return null;
}
/**
* Get number of elements in INTO or var=col assignment clause
*/
int getIntoCount(HplsqlParser.Select_stmtContext ctx) {
HplsqlParser.Into_clauseContext into = getIntoClause(ctx);
if (into != null) {
return into.ident().size();
}
List sl = ctx.fullselect_stmt().fullselect_stmt_item(0).subselect_stmt().select_list().select_list_item();
if (sl.get(0).T_EQUAL() != null) {
return sl.size();
}
return 0;
}
/**
* Get variable name assigned in INTO or var=col clause by index
*/
String getIntoVariable(HplsqlParser.Select_stmtContext ctx, int idx) {
HplsqlParser.Into_clauseContext into = getIntoClause(ctx);
if (into != null) {
return into.ident(idx).getText();
}
HplsqlParser.Select_list_itemContext sl = ctx.fullselect_stmt().fullselect_stmt_item(0).subselect_stmt().select_list().select_list_item(idx);
if (sl != null) {
return sl.ident().getText();
}
return null;
}
/**
* SELECT statement options - LIMIT n, WITH UR i.e
*/
public Integer option(HplsqlParser.Select_options_itemContext ctx) {
if (ctx.T_LIMIT() != null) {
exec.stackPush("LIMIT " + evalPop(ctx.expr()));
}
return 0;
}
/**
* Evaluate the expression to NULL
*/
void evalNull() {
exec.stackPush(Var.Null);
}
/**
* Evaluate the expression and pop value from the stack
*/
Var evalPop(ParserRuleContext ctx) {
exec.visit(ctx);
if (!exec.stack.isEmpty()) {
return exec.stackPop();
}
return Var.Empty;
}
/**
* Get node text including spaces
*/
String getText(ParserRuleContext ctx) {
return ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
}
/**
* 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, ResultSet rs, ResultSetMetaData rm, int idx) throws SQLException {
exec.trace(ctx, var, rs, rm, idx);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy