use of org.apache.calcite.sql.SqlInsert in project calcite by apache.
the class RelToSqlConverter method visit.
/**
* @see #dispatch
*/
public Result visit(TableModify modify) {
final Map<String, RelDataType> pairs = ImmutableMap.of();
final Context context = aliasContext(pairs, false);
// Target Table Name
final SqlIdentifier sqlTargetTable = new SqlIdentifier(modify.getTable().getQualifiedName(), POS);
switch(modify.getOperation()) {
case INSERT:
{
// Convert the input to a SELECT query or keep as VALUES. Not all
// dialects support naked VALUES, but all support VALUES inside INSERT.
final SqlNode sqlSource = visitChild(0, modify.getInput()).asQueryOrValues();
final SqlInsert sqlInsert = new SqlInsert(POS, SqlNodeList.EMPTY, sqlTargetTable, sqlSource, identifierList(modify.getInput().getRowType().getFieldNames()));
return result(sqlInsert, ImmutableList.<Clause>of(), modify, null);
}
case UPDATE:
{
final Result input = visitChild(0, modify.getInput());
final SqlUpdate sqlUpdate = new SqlUpdate(POS, sqlTargetTable, identifierList(modify.getUpdateColumnList()), exprList(context, modify.getSourceExpressionList()), ((SqlSelect) input.node).getWhere(), input.asSelect(), null);
return result(sqlUpdate, input.clauses, modify, null);
}
case DELETE:
{
final Result input = visitChild(0, modify.getInput());
final SqlDelete sqlDelete = new SqlDelete(POS, sqlTargetTable, input.asSelect().getWhere(), input.asSelect(), null);
return result(sqlDelete, input.clauses, modify, null);
}
case MERGE:
default:
throw new AssertionError("not implemented: " + modify);
}
}
use of org.apache.calcite.sql.SqlInsert in project calcite by apache.
the class SqlValidatorImpl method registerQuery.
/**
* Registers a query in a parent scope.
*
* @param parentScope Parent scope which this scope turns to in order to
* resolve objects
* @param usingScope Scope whose child list this scope should add itself to
* @param node Query node
* @param alias Name of this query within its parent. Must be specified
* if usingScope != null
* @param checkUpdate if true, validate that the update feature is supported
* if validating the update statement
*/
private void registerQuery(SqlValidatorScope parentScope, SqlValidatorScope usingScope, SqlNode node, SqlNode enclosingNode, String alias, boolean forceNullable, boolean checkUpdate) {
Preconditions.checkNotNull(node);
Preconditions.checkNotNull(enclosingNode);
Preconditions.checkArgument(usingScope == null || alias != null);
SqlCall call;
List<SqlNode> operands;
switch(node.getKind()) {
case SELECT:
final SqlSelect select = (SqlSelect) node;
final SelectNamespace selectNs = createSelectNamespace(select, enclosingNode);
registerNamespace(usingScope, alias, selectNs, forceNullable);
final SqlValidatorScope windowParentScope = (usingScope != null) ? usingScope : parentScope;
SelectScope selectScope = new SelectScope(parentScope, windowParentScope, select);
scopes.put(select, selectScope);
// Start by registering the WHERE clause
whereScopes.put(select, selectScope);
registerOperandSubQueries(selectScope, select, SqlSelect.WHERE_OPERAND);
// Register FROM with the inherited scope 'parentScope', not
// 'selectScope', otherwise tables in the FROM clause would be
// able to see each other.
final SqlNode from = select.getFrom();
if (from != null) {
final SqlNode newFrom = registerFrom(parentScope, selectScope, from, from, null, null, false);
if (newFrom != from) {
select.setFrom(newFrom);
}
}
// If this is an aggregating query, the SELECT list and HAVING
// clause use a different scope, where you can only reference
// columns which are in the GROUP BY clause.
SqlValidatorScope aggScope = selectScope;
if (isAggregate(select)) {
aggScope = new AggregatingSelectScope(selectScope, select, false);
selectScopes.put(select, aggScope);
} else {
selectScopes.put(select, selectScope);
}
if (select.getGroup() != null) {
GroupByScope groupByScope = new GroupByScope(selectScope, select.getGroup(), select);
groupByScopes.put(select, groupByScope);
registerSubQueries(groupByScope, select.getGroup());
}
registerOperandSubQueries(aggScope, select, SqlSelect.HAVING_OPERAND);
registerSubQueries(aggScope, select.getSelectList());
final SqlNodeList orderList = select.getOrderList();
if (orderList != null) {
// available to the ORDER BY clause.
if (select.isDistinct()) {
aggScope = new AggregatingSelectScope(selectScope, select, true);
}
OrderByScope orderScope = new OrderByScope(aggScope, orderList, select);
orderScopes.put(select, orderScope);
registerSubQueries(orderScope, orderList);
if (!isAggregate(select)) {
// Since this is not an aggregating query,
// there cannot be any aggregates in the ORDER BY clause.
SqlNode agg = aggFinder.findAgg(orderList);
if (agg != null) {
throw newValidationError(agg, RESOURCE.aggregateIllegalInOrderBy());
}
}
}
break;
case INTERSECT:
validateFeature(RESOURCE.sQLFeature_F302(), node.getParserPosition());
registerSetop(parentScope, usingScope, node, node, alias, forceNullable);
break;
case EXCEPT:
validateFeature(RESOURCE.sQLFeature_E071_03(), node.getParserPosition());
registerSetop(parentScope, usingScope, node, node, alias, forceNullable);
break;
case UNION:
registerSetop(parentScope, usingScope, node, node, alias, forceNullable);
break;
case WITH:
registerWith(parentScope, usingScope, (SqlWith) node, enclosingNode, alias, forceNullable, checkUpdate);
break;
case VALUES:
call = (SqlCall) node;
scopes.put(call, parentScope);
final TableConstructorNamespace tableConstructorNamespace = new TableConstructorNamespace(this, call, parentScope, enclosingNode);
registerNamespace(usingScope, alias, tableConstructorNamespace, forceNullable);
operands = call.getOperandList();
for (int i = 0; i < operands.size(); ++i) {
assert operands.get(i).getKind() == SqlKind.ROW;
// FIXME jvs 9-Feb-2005: Correlation should
// be illegal in these sub-queries. Same goes for
// any non-lateral SELECT in the FROM list.
registerOperandSubQueries(parentScope, call, i);
}
break;
case INSERT:
SqlInsert insertCall = (SqlInsert) node;
InsertNamespace insertNs = new InsertNamespace(this, insertCall, enclosingNode, parentScope);
registerNamespace(usingScope, null, insertNs, forceNullable);
registerQuery(parentScope, usingScope, insertCall.getSource(), enclosingNode, null, false);
break;
case DELETE:
SqlDelete deleteCall = (SqlDelete) node;
DeleteNamespace deleteNs = new DeleteNamespace(this, deleteCall, enclosingNode, parentScope);
registerNamespace(usingScope, null, deleteNs, forceNullable);
registerQuery(parentScope, usingScope, deleteCall.getSourceSelect(), enclosingNode, null, false);
break;
case UPDATE:
if (checkUpdate) {
validateFeature(RESOURCE.sQLFeature_E101_03(), node.getParserPosition());
}
SqlUpdate updateCall = (SqlUpdate) node;
UpdateNamespace updateNs = new UpdateNamespace(this, updateCall, enclosingNode, parentScope);
registerNamespace(usingScope, null, updateNs, forceNullable);
registerQuery(parentScope, usingScope, updateCall.getSourceSelect(), enclosingNode, null, false);
break;
case MERGE:
validateFeature(RESOURCE.sQLFeature_F312(), node.getParserPosition());
SqlMerge mergeCall = (SqlMerge) node;
MergeNamespace mergeNs = new MergeNamespace(this, mergeCall, enclosingNode, parentScope);
registerNamespace(usingScope, null, mergeNs, forceNullable);
registerQuery(parentScope, usingScope, mergeCall.getSourceSelect(), enclosingNode, null, false);
// validation check
if (mergeCall.getUpdateCall() != null) {
registerQuery(whereScopes.get(mergeCall.getSourceSelect()), null, mergeCall.getUpdateCall(), enclosingNode, null, false, false);
}
if (mergeCall.getInsertCall() != null) {
registerQuery(parentScope, null, mergeCall.getInsertCall(), enclosingNode, null, false);
}
break;
case UNNEST:
call = (SqlCall) node;
final UnnestNamespace unnestNs = new UnnestNamespace(this, call, parentScope, enclosingNode);
registerNamespace(usingScope, alias, unnestNs, forceNullable);
registerOperandSubQueries(parentScope, call, 0);
scopes.put(node, parentScope);
break;
case OTHER_FUNCTION:
call = (SqlCall) node;
ProcedureNamespace procNs = new ProcedureNamespace(this, parentScope, call, enclosingNode);
registerNamespace(usingScope, alias, procNs, forceNullable);
registerSubQueries(parentScope, call);
break;
case MULTISET_QUERY_CONSTRUCTOR:
case MULTISET_VALUE_CONSTRUCTOR:
validateFeature(RESOURCE.sQLFeature_S271(), node.getParserPosition());
call = (SqlCall) node;
CollectScope cs = new CollectScope(parentScope, usingScope, call);
final CollectNamespace tableConstructorNs = new CollectNamespace(call, cs, enclosingNode);
final String alias2 = deriveAlias(node, nextGeneratedId++);
registerNamespace(usingScope, alias2, tableConstructorNs, forceNullable);
operands = call.getOperandList();
for (int i = 0; i < operands.size(); i++) {
registerOperandSubQueries(parentScope, call, i);
}
break;
default:
throw Util.unexpected(node.getKind());
}
}
use of org.apache.calcite.sql.SqlInsert in project calcite by apache.
the class SqlToRelConverter method convertMerge.
private RelNode convertMerge(SqlMerge call) {
RelOptTable targetTable = getTargetTable(call);
// convert update column list from SqlIdentifier to String
final List<String> targetColumnNameList = new ArrayList<>();
final RelDataType targetRowType = targetTable.getRowType();
SqlUpdate updateCall = call.getUpdateCall();
if (updateCall != null) {
for (SqlNode targetColumn : updateCall.getTargetColumnList()) {
SqlIdentifier id = (SqlIdentifier) targetColumn;
RelDataTypeField field = SqlValidatorUtil.getTargetField(targetRowType, typeFactory, id, catalogReader, targetTable);
assert field != null : "column " + id.toString() + " not found";
targetColumnNameList.add(field.getName());
}
}
// replace the projection of the source select with a
// projection that contains the following:
// 1) the expressions corresponding to the new insert row (if there is
// an insert)
// 2) all columns from the target table (if there is an update)
// 3) the set expressions in the update call (if there is an update)
// first, convert the merge's source select to construct the columns
// from the target table and the set expressions in the update call
RelNode mergeSourceRel = convertSelect(call.getSourceSelect(), false);
// then, convert the insert statement so we can get the insert
// values expressions
SqlInsert insertCall = call.getInsertCall();
int nLevel1Exprs = 0;
List<RexNode> level1InsertExprs = null;
List<RexNode> level2InsertExprs = null;
if (insertCall != null) {
RelNode insertRel = convertInsert(insertCall);
// if there are 2 level of projections in the insert source, combine
// them into a single project; level1 refers to the topmost project;
// the level1 projection contains references to the level2
// expressions, except in the case where no target expression was
// provided, in which case, the expression is the default value for
// the column; or if the expressions directly map to the source
// table
level1InsertExprs = ((LogicalProject) insertRel.getInput(0)).getProjects();
if (insertRel.getInput(0).getInput(0) instanceof LogicalProject) {
level2InsertExprs = ((LogicalProject) insertRel.getInput(0).getInput(0)).getProjects();
}
nLevel1Exprs = level1InsertExprs.size();
}
LogicalJoin join = (LogicalJoin) mergeSourceRel.getInput(0);
int nSourceFields = join.getLeft().getRowType().getFieldCount();
final List<RexNode> projects = new ArrayList<>();
for (int level1Idx = 0; level1Idx < nLevel1Exprs; level1Idx++) {
if ((level2InsertExprs != null) && (level1InsertExprs.get(level1Idx) instanceof RexInputRef)) {
int level2Idx = ((RexInputRef) level1InsertExprs.get(level1Idx)).getIndex();
projects.add(level2InsertExprs.get(level2Idx));
} else {
projects.add(level1InsertExprs.get(level1Idx));
}
}
if (updateCall != null) {
final LogicalProject project = (LogicalProject) mergeSourceRel;
projects.addAll(Util.skip(project.getProjects(), nSourceFields));
}
relBuilder.push(join).project(projects);
return LogicalTableModify.create(targetTable, catalogReader, relBuilder.build(), LogicalTableModify.Operation.MERGE, targetColumnNameList, null, false);
}
use of org.apache.calcite.sql.SqlInsert in project samza by apache.
the class SamzaSqlQueryParser method parseQuery.
public static QueryInfo parseQuery(String sql) {
Planner planner = createPlanner();
SqlNode sqlNode;
// Having semi-colons at the end of sql statement is a valid syntax in standard sql but not for Calcite parser.
// Hence, removing trailing semi-colon before passing sql statement to Calcite parser.
sql = sql.replaceAll(TRAILING_SEMI_COLON_REGEX, "");
try {
sqlNode = planner.parse(sql);
} catch (SqlParseException e) {
String errorMsg = SamzaSqlValidator.formatErrorString(sql, e);
LOG.error(errorMsg, e);
throw new SamzaException(errorMsg, e);
}
String sink;
String selectQuery;
ArrayList<String> sources;
if (sqlNode instanceof SqlInsert) {
SqlInsert sqlInsert = (SqlInsert) sqlNode;
sink = sqlInsert.getTargetTable().toString();
if (sqlInsert.getSource() instanceof SqlSelect) {
SqlSelect sqlSelect = (SqlSelect) sqlInsert.getSource();
selectQuery = sqlSelect.toString();
LOG.info("Parsed select query {} from sql {}", selectQuery, sql);
sources = getSourcesFromSelectQuery(sqlSelect);
} else {
String msg = String.format("Sql query is not of the expected format. Select node expected, found %s", sqlInsert.getSource().getClass().toString());
LOG.error(msg);
throw new SamzaException(msg);
}
} else {
String msg = String.format("Sql query is not of the expected format. Insert node expected, found %s", sqlNode.getClass().toString());
LOG.error(msg);
throw new SamzaException(msg);
}
return new QueryInfo(selectQuery, sources, sink, sql);
}
use of org.apache.calcite.sql.SqlInsert in project flink by apache.
the class SqlValidatorImpl method rewriteMerge.
private void rewriteMerge(SqlMerge call) {
SqlNodeList selectList;
SqlUpdate updateStmt = call.getUpdateCall();
if (updateStmt != null) {
// if we have an update statement, just clone the select list
// from the update statement's source since it's the same as
// what we want for the select list of the merge source -- '*'
// followed by the update set expressions
selectList = SqlNode.clone(updateStmt.getSourceSelect().getSelectList());
} else {
// otherwise, just use select *
selectList = new SqlNodeList(SqlParserPos.ZERO);
selectList.add(SqlIdentifier.star(SqlParserPos.ZERO));
}
SqlNode targetTable = call.getTargetTable();
if (call.getAlias() != null) {
targetTable = SqlValidatorUtil.addAlias(targetTable, call.getAlias().getSimple());
}
// Provided there is an insert substatement, the source select for
// the merge is a left outer join between the source in the USING
// clause and the target table; otherwise, the join is just an
// inner join. Need to clone the source table reference in order
// for validation to work
SqlNode sourceTableRef = call.getSourceTableRef();
SqlInsert insertCall = call.getInsertCall();
JoinType joinType = (insertCall == null) ? JoinType.INNER : JoinType.LEFT;
final SqlNode leftJoinTerm = SqlNode.clone(sourceTableRef);
SqlNode outerJoin = new SqlJoin(SqlParserPos.ZERO, leftJoinTerm, SqlLiteral.createBoolean(false, SqlParserPos.ZERO), joinType.symbol(SqlParserPos.ZERO), targetTable, JoinConditionType.ON.symbol(SqlParserPos.ZERO), call.getCondition());
SqlSelect select = new SqlSelect(SqlParserPos.ZERO, null, selectList, outerJoin, null, null, null, null, null, null, null, null);
call.setSourceSelect(select);
// that via the from clause on the select
if (insertCall != null) {
SqlCall valuesCall = (SqlCall) insertCall.getSource();
SqlCall rowCall = valuesCall.operand(0);
selectList = new SqlNodeList(rowCall.getOperandList(), SqlParserPos.ZERO);
final SqlNode insertSource = SqlNode.clone(sourceTableRef);
select = new SqlSelect(SqlParserPos.ZERO, null, selectList, insertSource, null, null, null, null, null, null, null, null);
insertCall.setSource(select);
}
}
Aggregations