use of io.prestosql.sql.tree.ComparisonExpression in project hetu-core by openlookeng.
the class HeuristicIndexUtils method extractPartitions.
/**
* Given one of these expressions types:
* - partition=1
* - partition=1 or partition=2
* - partition in (1,2)
* - partition=1 or partition in (2)
*
* extract the partitions as a list of key=value pairs
* @param expression
* @return
*/
public static List<String> extractPartitions(Expression expression) {
if (expression instanceof ComparisonExpression) {
ComparisonExpression exp = (ComparisonExpression) expression;
if (exp.getOperator() == ComparisonExpression.Operator.EQUAL) {
return Collections.singletonList(parsePartitionName(exp.getLeft().toString()) + "=" + parsePartitionValue(exp.getRight().toString()));
}
} else if (expression instanceof LogicalBinaryExpression) {
LogicalBinaryExpression exp = (LogicalBinaryExpression) expression;
if (exp.getOperator() == LogicalBinaryExpression.Operator.OR) {
Expression left = exp.getLeft();
Expression right = exp.getRight();
return Stream.concat(extractPartitions(left).stream(), extractPartitions(right).stream()).collect(Collectors.toList());
}
} else if (expression instanceof InPredicate) {
Expression valueList = ((InPredicate) expression).getValueList();
if (valueList instanceof InListExpression) {
InListExpression inListExpression = (InListExpression) valueList;
List<String> res = new LinkedList<>();
for (Expression expr : inListExpression.getValues()) {
res.add(parsePartitionName(((InPredicate) expression).getValue().toString()) + "=" + parsePartitionValue(expr.toString()));
}
if (res.size() > 0) {
return res;
}
}
}
throw new ParsingException("Unsupported WHERE expression. Only in-predicate/equality-expressions are supported " + "e.g. partition=1 or partition=2/partition in (1,2)");
}
use of io.prestosql.sql.tree.ComparisonExpression in project hetu-core by openlookeng.
the class LogicalPlanner method noTruncationCast.
private Expression noTruncationCast(Expression expression, Type fromType, Type toType) {
// cast larger size varchar to small size varchar
if ((fromType instanceof VarcharType || fromType instanceof CharType) && (toType instanceof VarcharType || toType instanceof CharType)) {
int targetLength;
if (toType instanceof VarcharType) {
if (((VarcharType) toType).isUnbounded()) {
return new Cast(expression, toType.getTypeSignature().toString());
}
targetLength = ((VarcharType) toType).getBoundedLength();
} else {
targetLength = ((CharType) toType).getLength();
}
Signature spaceTrimmedLength = metadata.getFunctionAndTypeManager().resolveBuiltInFunction(QualifiedName.of("$space_trimmed_length"), fromTypes(VARCHAR));
Signature fail = metadata.getFunctionAndTypeManager().resolveBuiltInFunction(QualifiedName.of("fail"), fromTypes(VARCHAR));
return new IfExpression(// check if the trimmed value fits in the target type
new ComparisonExpression(GREATER_THAN_OR_EQUAL, new GenericLiteral("BIGINT", Integer.toString(targetLength)), new FunctionCall(QualifiedName.of("$space_trimmed_length"), ImmutableList.of(new Cast(expression, VARCHAR.getTypeSignature().toString())))), new Cast(expression, toType.getTypeSignature().toString()), new Cast(new FunctionCall(QualifiedName.of("fail"), ImmutableList.of(new Cast(new StringLiteral(format("Out of range for insert query type: Table: %s, Query: %s", toType.toString(), fromType.toString())), VARCHAR.getTypeSignature().toString()))), toType.getTypeSignature().toString()));
}
return new Cast(expression, toType.getTypeSignature().toString());
}
use of io.prestosql.sql.tree.ComparisonExpression in project hetu-core by openlookeng.
the class RelationPlanner method visitJoin.
@Override
protected RelationPlan visitJoin(Join node, Void context) {
// TODO: translate the RIGHT join into a mirrored LEFT join when we refactor (@martint)
RelationPlan leftPlan = process(node.getLeft(), context);
Optional<Unnest> unnest = getUnnest(node.getRight());
if (unnest.isPresent()) {
if (node.getType() != Join.Type.CROSS && node.getType() != Join.Type.IMPLICIT) {
throw notSupportedException(unnest.get(), "UNNEST on other than the right side of CROSS JOIN");
}
return planCrossJoinUnnest(leftPlan, node, unnest.get());
}
Optional<Lateral> lateral = getLateral(node.getRight());
if (lateral.isPresent()) {
return planLateralJoin(node, leftPlan, lateral.get());
}
RelationPlan rightPlan = process(node.getRight(), context);
if (node.getCriteria().isPresent() && node.getCriteria().get() instanceof JoinUsing) {
return planJoinUsing(node, leftPlan, rightPlan);
}
PlanBuilder leftPlanBuilder = initializePlanBuilder(leftPlan);
PlanBuilder rightPlanBuilder = initializePlanBuilder(rightPlan);
// NOTE: symbols must be in the same order as the outputDescriptor
List<Symbol> outputSymbols = ImmutableList.<Symbol>builder().addAll(leftPlan.getFieldMappings()).addAll(rightPlan.getFieldMappings()).build();
ImmutableList.Builder<JoinNode.EquiJoinClause> equiClauses = ImmutableList.builder();
List<Expression> complexJoinExpressions = new ArrayList<>();
List<Expression> postInnerJoinConditions = new ArrayList<>();
if (node.getType() != Join.Type.CROSS && node.getType() != Join.Type.IMPLICIT) {
Expression criteria = analysis.getJoinCriteria(node);
RelationType left = analysis.getOutputDescriptor(node.getLeft());
RelationType right = analysis.getOutputDescriptor(node.getRight());
List<Expression> leftComparisonExpressions = new ArrayList<>();
List<Expression> rightComparisonExpressions = new ArrayList<>();
List<ComparisonExpression.Operator> joinConditionComparisonOperators = new ArrayList<>();
for (Expression conjunct : ExpressionUtils.extractConjuncts(criteria)) {
conjunct = ExpressionUtils.normalize(conjunct);
if (!isEqualComparisonExpression(conjunct) && node.getType() != INNER) {
complexJoinExpressions.add(conjunct);
continue;
}
Set<QualifiedName> dependencies = SymbolsExtractor.extractNames(conjunct, analysis.getColumnReferences());
if (dependencies.stream().allMatch(left::canResolve) || dependencies.stream().allMatch(right::canResolve)) {
// If the conjunct can be evaluated entirely with the inputs on either side of the join, add
// it to the list complex expressions and let the optimizers figure out how to push it down later.
complexJoinExpressions.add(conjunct);
} else if (conjunct instanceof ComparisonExpression) {
Expression firstExpression = ((ComparisonExpression) conjunct).getLeft();
Expression secondExpression = ((ComparisonExpression) conjunct).getRight();
ComparisonExpression.Operator comparisonOperator = ((ComparisonExpression) conjunct).getOperator();
Set<QualifiedName> firstDependencies = SymbolsExtractor.extractNames(firstExpression, analysis.getColumnReferences());
Set<QualifiedName> secondDependencies = SymbolsExtractor.extractNames(secondExpression, analysis.getColumnReferences());
if (firstDependencies.stream().allMatch(left::canResolve) && secondDependencies.stream().allMatch(right::canResolve)) {
leftComparisonExpressions.add(firstExpression);
rightComparisonExpressions.add(secondExpression);
joinConditionComparisonOperators.add(comparisonOperator);
} else if (firstDependencies.stream().allMatch(right::canResolve) && secondDependencies.stream().allMatch(left::canResolve)) {
leftComparisonExpressions.add(secondExpression);
rightComparisonExpressions.add(firstExpression);
joinConditionComparisonOperators.add(comparisonOperator.flip());
} else {
// the case when we mix symbols from both left and right join side on either side of condition.
complexJoinExpressions.add(conjunct);
}
} else {
complexJoinExpressions.add(conjunct);
}
}
leftPlanBuilder = subqueryPlanner.handleSubqueries(leftPlanBuilder, leftComparisonExpressions, node);
rightPlanBuilder = subqueryPlanner.handleSubqueries(rightPlanBuilder, rightComparisonExpressions, node);
// Add projections for join criteria
leftPlanBuilder = leftPlanBuilder.appendProjections(leftComparisonExpressions, planSymbolAllocator, idAllocator);
rightPlanBuilder = rightPlanBuilder.appendProjections(rightComparisonExpressions, planSymbolAllocator, idAllocator);
for (int i = 0; i < leftComparisonExpressions.size(); i++) {
if (joinConditionComparisonOperators.get(i) == ComparisonExpression.Operator.EQUAL) {
Symbol leftSymbol = leftPlanBuilder.translate(leftComparisonExpressions.get(i));
Symbol rightSymbol = rightPlanBuilder.translate(rightComparisonExpressions.get(i));
equiClauses.add(new JoinNode.EquiJoinClause(leftSymbol, rightSymbol));
} else {
Expression leftExpression = leftPlanBuilder.rewrite(leftComparisonExpressions.get(i));
Expression rightExpression = rightPlanBuilder.rewrite(rightComparisonExpressions.get(i));
postInnerJoinConditions.add(new ComparisonExpression(joinConditionComparisonOperators.get(i), leftExpression, rightExpression));
}
}
}
PlanNode root = new JoinNode(idAllocator.getNextId(), JoinNodeUtils.typeConvert(node.getType()), leftPlanBuilder.getRoot(), rightPlanBuilder.getRoot(), equiClauses.build(), ImmutableList.<Symbol>builder().addAll(leftPlanBuilder.getRoot().getOutputSymbols()).addAll(rightPlanBuilder.getRoot().getOutputSymbols()).build(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of());
if (node.getType() != INNER) {
for (Expression complexExpression : complexJoinExpressions) {
Set<InPredicate> inPredicates = subqueryPlanner.collectInPredicateSubqueries(complexExpression, node);
if (!inPredicates.isEmpty()) {
InPredicate inPredicate = Iterables.getLast(inPredicates);
throw notSupportedException(inPredicate, "IN with subquery predicate in join condition");
}
}
// subqueries can be applied only to one side of join - left side is selected in arbitrary way
leftPlanBuilder = subqueryPlanner.handleUncorrelatedSubqueries(leftPlanBuilder, complexJoinExpressions, node);
}
RelationPlan intermediateRootRelationPlan = new RelationPlan(root, analysis.getScope(node), outputSymbols);
TranslationMap translationMap = new TranslationMap(intermediateRootRelationPlan, analysis, lambdaDeclarationToSymbolMap);
translationMap.setFieldMappings(outputSymbols);
translationMap.putExpressionMappingsFrom(leftPlanBuilder.getTranslations());
translationMap.putExpressionMappingsFrom(rightPlanBuilder.getTranslations());
if (node.getType() != INNER && !complexJoinExpressions.isEmpty()) {
Expression joinedFilterCondition = ExpressionUtils.and(complexJoinExpressions);
Expression rewrittenFilterCondition = translationMap.rewrite(joinedFilterCondition);
root = new JoinNode(idAllocator.getNextId(), JoinNodeUtils.typeConvert(node.getType()), leftPlanBuilder.getRoot(), rightPlanBuilder.getRoot(), equiClauses.build(), ImmutableList.<Symbol>builder().addAll(leftPlanBuilder.getRoot().getOutputSymbols()).addAll(rightPlanBuilder.getRoot().getOutputSymbols()).build(), Optional.of(castToRowExpression(rewrittenFilterCondition)), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of());
}
if (node.getType() == INNER) {
// rewrite all the other conditions using output symbols from left + right plan node.
PlanBuilder rootPlanBuilder = new PlanBuilder(translationMap, root);
rootPlanBuilder = subqueryPlanner.handleSubqueries(rootPlanBuilder, complexJoinExpressions, node);
for (Expression expression : complexJoinExpressions) {
postInnerJoinConditions.add(rootPlanBuilder.rewrite(expression));
}
root = rootPlanBuilder.getRoot();
Expression postInnerJoinCriteria;
if (!postInnerJoinConditions.isEmpty()) {
postInnerJoinCriteria = ExpressionUtils.and(postInnerJoinConditions);
root = new FilterNode(idAllocator.getNextId(), root, castToRowExpression(postInnerJoinCriteria));
}
}
return new RelationPlan(root, analysis.getScope(node), outputSymbols);
}
use of io.prestosql.sql.tree.ComparisonExpression in project hetu-core by openlookeng.
the class CubeConsole method createCubeCommand.
/**
* Process the Create Cube Query
*
* @param queryRunner queryRunner
* @param outputFormat outputFormat
* @param schemaChanged schemaChanged
* @param usePager usePager
* @param schemaChanged schemaChanged
* @param showProgress showProgress
* @param terminal terminal
* @param out out
* @param errorChannel errorChannel
* @return boolean after processing the create cube query command.
*/
public boolean createCubeCommand(String query, QueryRunner queryRunner, ClientOptions.OutputFormat outputFormat, Runnable schemaChanged, boolean usePager, boolean showProgress, Terminal terminal, PrintStream out, PrintStream errorChannel) {
boolean success = true;
SqlParser parser = new SqlParser();
QualifiedName cubeName = null;
try {
CreateCube createCube = (CreateCube) parser.createStatement(query, new ParsingOptions(ParsingOptions.DecimalLiteralTreatment.AS_DOUBLE));
cubeName = createCube.getCubeName();
QualifiedName sourceTableName = createCube.getSourceTableName();
String whereClause = createCube.getWhere().get().toString();
Set<FunctionCall> aggregations = createCube.getAggregations();
List<Identifier> groupingSet = createCube.getGroupingSet();
List<Property> properties = createCube.getProperties();
boolean notExists = createCube.isNotExists();
CreateCube modifiedCreateCube = new CreateCube(cubeName, sourceTableName, groupingSet, aggregations, notExists, properties, Optional.empty(), createCube.getSourceFilter().orElse(null));
String queryCreateCube = SqlFormatter.formatSql(modifiedCreateCube, Optional.empty());
if (!console.runQuery(queryRunner, queryCreateCube, outputFormat, schemaChanged, usePager, showProgress, terminal, out, errorChannel)) {
return false;
}
// we check whether the create cube expression can be processed
if (isSupportedExpression(createCube, queryRunner, outputFormat, schemaChanged, usePager, showProgress, terminal, out, errorChannel)) {
if (createCube.getWhere().get() instanceof BetweenPredicate) {
// we process the between predicate in the create cube query where clause
success = processBetweenPredicate(createCube, queryRunner, outputFormat, schemaChanged, usePager, showProgress, terminal, out, errorChannel, parser);
}
if (createCube.getWhere().get() instanceof ComparisonExpression) {
// we process the comparison expression in the create cube query where clause
success = processComparisonExpression(createCube, queryRunner, outputFormat, schemaChanged, usePager, showProgress, terminal, out, errorChannel, parser);
}
} else {
// if we donot support processing the create cube query with multiple inserts, then only a single insert is run internally.
String queryInsert = String.format(INSERT_INTO_CUBE_STRING, cubeName, whereClause);
success = console.runQuery(queryRunner, queryInsert, outputFormat, schemaChanged, usePager, showProgress, terminal, out, errorChannel);
}
if (!success) {
// roll back mechanism for unsuccessful create cube query
String dropCubeQuery = String.format(DROP_CUBE_STRING, cubeName);
console.runQuery(queryRunner, dropCubeQuery, outputFormat, schemaChanged, usePager, showProgress, terminal, out, errorChannel);
}
} catch (ParsingException e) {
if (cubeName != null) {
// roll back mechanism for unsuccessful create cube query
String dropCubeQuery = String.format(DROP_CUBE_STRING, cubeName);
console.runQuery(queryRunner, dropCubeQuery, outputFormat, schemaChanged, usePager, showProgress, terminal, out, errorChannel);
}
System.out.println(e.getMessage());
Query.renderErrorLocation(query, new ErrorLocation(e.getLineNumber(), e.getColumnNumber()), errorChannel);
success = false;
} catch (Exception e) {
if (cubeName != null) {
// roll back mechanism for unsuccessful create cube query
String dropCubeQuery = String.format(DROP_CUBE_STRING, cubeName);
console.runQuery(queryRunner, dropCubeQuery, outputFormat, schemaChanged, usePager, showProgress, terminal, out, errorChannel);
}
// Add blank line after progress bar
System.out.println();
System.out.println(e.getMessage());
success = false;
}
return success;
}
use of io.prestosql.sql.tree.ComparisonExpression in project hetu-core by openlookeng.
the class EqualityInference method generateEqualitiesPartitionedBy.
/**
* Dumps the inference equalities as equality expressions that are partitioned by the symbolScope.
* All stored equalities are returned in a compact set and will be classified into three groups as determined by the symbol scope:
* <ol>
* <li>equalities that fit entirely within the symbol scope</li>
* <li>equalities that fit entirely outside of the symbol scope</li>
* <li>equalities that straddle the symbol scope</li>
* </ol>
* <pre>
* Example:
* Stored Equalities:
* a = b = c
* d = e = f = g
*
* Symbol Scope:
* a, b, d, e
*
* Output EqualityPartition:
* Scope Equalities:
* a = b
* d = e
* Complement Scope Equalities
* f = g
* Scope Straddling Equalities
* a = c
* d = f
* </pre>
*/
public EqualityPartition generateEqualitiesPartitionedBy(Predicate<Symbol> symbolScope) {
ImmutableSet.Builder<Expression> scopeEqualities = ImmutableSet.builder();
ImmutableSet.Builder<Expression> scopeComplementEqualities = ImmutableSet.builder();
ImmutableSet.Builder<Expression> scopeStraddlingEqualities = ImmutableSet.builder();
for (Collection<Expression> equalitySet : equalitySets.asMap().values()) {
Set<Expression> scopeExpressions = new LinkedHashSet<>();
Set<Expression> scopeComplementExpressions = new LinkedHashSet<>();
Set<Expression> scopeStraddlingExpressions = new LinkedHashSet<>();
// Try to push each non-derived expression into one side of the scope
for (Expression expression : filter(equalitySet, not(derivedExpressions::contains))) {
Expression scopeRewritten = rewriteExpression(expression, symbolScope, false);
if (scopeRewritten != null) {
scopeExpressions.add(scopeRewritten);
}
Expression scopeComplementRewritten = rewriteExpression(expression, not(symbolScope), false);
if (scopeComplementRewritten != null) {
scopeComplementExpressions.add(scopeComplementRewritten);
}
if (scopeRewritten == null && scopeComplementRewritten == null) {
scopeStraddlingExpressions.add(expression);
}
}
// Compile the equality expressions on each side of the scope
Expression matchingCanonical = getCanonical(scopeExpressions);
if (scopeExpressions.size() >= 2) {
for (Expression expression : filter(scopeExpressions, not(equalTo(matchingCanonical)))) {
scopeEqualities.add(new ComparisonExpression(ComparisonExpression.Operator.EQUAL, matchingCanonical, expression));
}
}
Expression complementCanonical = getCanonical(scopeComplementExpressions);
if (scopeComplementExpressions.size() >= 2) {
for (Expression expression : filter(scopeComplementExpressions, not(equalTo(complementCanonical)))) {
scopeComplementEqualities.add(new ComparisonExpression(ComparisonExpression.Operator.EQUAL, complementCanonical, expression));
}
}
// Compile the scope straddling equality expressions
List<Expression> connectingExpressions = new ArrayList<>();
connectingExpressions.add(matchingCanonical);
connectingExpressions.add(complementCanonical);
connectingExpressions.addAll(scopeStraddlingExpressions);
connectingExpressions = ImmutableList.copyOf(filter(connectingExpressions, Predicates.notNull()));
Expression connectingCanonical = getCanonical(connectingExpressions);
if (connectingCanonical != null) {
for (Expression expression : filter(connectingExpressions, not(equalTo(connectingCanonical)))) {
scopeStraddlingEqualities.add(new ComparisonExpression(ComparisonExpression.Operator.EQUAL, connectingCanonical, expression));
}
}
}
return new EqualityPartition(scopeEqualities.build(), scopeComplementEqualities.build(), scopeStraddlingEqualities.build());
}
Aggregations