use of org.apache.phoenix.parse.ParseNode in project phoenix by apache.
the class ExpressionCompiler method visitLeave.
@Override
public Expression visitLeave(CastParseNode node, List<Expression> children) throws SQLException {
ParseNode childNode = node.getChildren().get(0);
PDataType targetDataType = node.getDataType();
Expression childExpr = children.get(0);
PDataType fromDataType = childExpr.getDataType();
if (childNode instanceof BindParseNode) {
context.getBindManager().addParamMetaData((BindParseNode) childNode, childExpr);
}
Expression expr = childExpr;
if (fromDataType != null) {
/*
* IndexStatementRewriter creates a CAST parse node when rewriting the query to use
* indexed columns. Without this check present we wrongly and unnecessarily
* end up creating a RoundExpression.
*/
if (context.getCurrentTable().getTable().getType() != PTableType.INDEX) {
expr = convertToRoundExpressionIfNeeded(fromDataType, targetDataType, children);
}
}
boolean rowKeyOrderOptimizable = context.getCurrentTable().getTable().rowKeyOrderOptimizable();
return wrapGroupByExpression(CoerceExpression.create(expr, targetDataType, SortOrder.getDefault(), expr.getMaxLength(), rowKeyOrderOptimizable));
}
use of org.apache.phoenix.parse.ParseNode in project phoenix by apache.
the class ExpressionCompiler method visitLeave.
@Override
public Expression visitLeave(IsNullParseNode node, List<Expression> children) throws SQLException {
ParseNode childNode = node.getChildren().get(0);
Expression child = children.get(0);
if (childNode instanceof BindParseNode) {
// TODO: valid/possibe?
context.getBindManager().addParamMetaData((BindParseNode) childNode, child);
}
return wrapGroupByExpression(IsNullExpression.create(child, node.isNegate(), context.getTempPtr()));
}
use of org.apache.phoenix.parse.ParseNode in project phoenix by apache.
the class GroupByCompiler method compile.
/**
* Get list of columns in the GROUP BY clause.
* @param context query context kept between compilation of different query clauses
* @param statement SQL statement being compiled
* @return the {@link GroupBy} instance encapsulating the group by clause
* @throws ColumnNotFoundException if column name could not be resolved
* @throws AmbiguousColumnException if an unaliased column name is ambiguous across multiple tables
*/
public static GroupBy compile(StatementContext context, SelectStatement statement, boolean isOrderPreserving) throws SQLException {
List<ParseNode> groupByNodes = statement.getGroupBy();
/**
* Distinct can use an aggregate plan if there's no group by.
* Otherwise, we need to insert a step after the Merge that dedups.
* Order by only allowed on columns in the select distinct
*/
boolean isUngroupedAggregate = false;
if (groupByNodes.isEmpty()) {
if (statement.isAggregate()) {
// TODO: PHOENIX-2989 suggests some ways to optimize the latter case
if (statement.getHint().hasHint(Hint.RANGE_SCAN) || statement.getHaving() != null) {
return GroupBy.UNGROUPED_GROUP_BY;
}
groupByNodes = Lists.newArrayListWithExpectedSize(statement.getSelect().size());
for (AliasedNode aliasedNode : statement.getSelect()) {
if (aliasedNode.getNode() instanceof DistinctCountParseNode) {
// only add children of DistinctCount nodes
groupByNodes.addAll(aliasedNode.getNode().getChildren());
} else {
// if we found anything else, do not attempt any further optimization
return GroupBy.UNGROUPED_GROUP_BY;
}
}
isUngroupedAggregate = true;
} else if (statement.isDistinct()) {
groupByNodes = Lists.newArrayListWithExpectedSize(statement.getSelect().size());
for (AliasedNode aliasedNode : statement.getSelect()) {
// for distinct at all select expression as group by conditions
groupByNodes.add(aliasedNode.getNode());
}
} else {
return GroupBy.EMPTY_GROUP_BY;
}
}
// Accumulate expressions in GROUP BY
ExpressionCompiler compiler = new ExpressionCompiler(context, GroupBy.EMPTY_GROUP_BY);
List<Expression> expressions = Lists.newArrayListWithExpectedSize(groupByNodes.size());
for (int i = 0; i < groupByNodes.size(); i++) {
ParseNode node = groupByNodes.get(i);
Expression expression = node.accept(compiler);
if (!expression.isStateless()) {
if (compiler.isAggregate()) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.AGGREGATE_IN_GROUP_BY).setMessage(expression.toString()).build().buildException();
}
expressions.add(expression);
}
compiler.reset();
}
if (expressions.isEmpty()) {
return GroupBy.EMPTY_GROUP_BY;
}
GroupBy groupBy = new GroupBy.GroupByBuilder().setIsOrderPreserving(isOrderPreserving).setExpressions(expressions).setKeyExpressions(expressions).setIsUngroupedAggregate(isUngroupedAggregate).build();
return groupBy;
}
use of org.apache.phoenix.parse.ParseNode in project phoenix by apache.
the class HavingCompiler method compile.
public static Expression compile(StatementContext context, SelectStatement statement, GroupBy groupBy) throws SQLException {
ParseNode having = statement.getHaving();
if (having == null) {
return null;
}
ExpressionCompiler expressionBuilder = new ExpressionCompiler(context, groupBy);
Expression expression = having.accept(expressionBuilder);
if (expression.getDataType() != PBoolean.INSTANCE) {
throw TypeMismatchException.newException(PBoolean.INSTANCE, expression.getDataType(), expression.toString());
}
if (LiteralExpression.isBooleanFalseOrNull(expression)) {
context.setScanRanges(ScanRanges.NOTHING);
return null;
} else if (LiteralExpression.isTrue(expression)) {
return null;
}
if (!expressionBuilder.isAggregate()) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.ONLY_AGGREGATE_IN_HAVING_CLAUSE).build().buildException();
}
return expression;
}
use of org.apache.phoenix.parse.ParseNode in project phoenix by apache.
the class IndexStatementRewriter method visit.
@Override
public ParseNode visit(ColumnParseNode node) throws SQLException {
ColumnRef dataColRef = getResolver().resolveColumn(node.getSchemaName(), node.getTableName(), node.getName());
PColumn dataCol = dataColRef.getColumn();
TableRef dataTableRef = dataColRef.getTableRef();
// view constants if based on an UPDATABLE view
if (dataCol.getViewConstant() != null) {
byte[] viewConstant = dataCol.getViewConstant();
// Ignore last byte, as it's only there so we can have a way to differentiate null
// from the absence of a value.
ptr.set(viewConstant, 0, viewConstant.length - 1);
Object literal = dataCol.getDataType().toObject(ptr);
return new LiteralParseNode(literal, dataCol.getDataType());
}
TableName tName = getReplacedTableName(dataTableRef);
if (multiTableRewriteMap != null && tName == null)
return node;
String indexColName = IndexUtil.getIndexColumnName(dataCol);
ParseNode indexColNode = new ColumnParseNode(tName, '"' + indexColName + '"', node.getAlias());
PDataType indexColType = IndexUtil.getIndexColumnDataType(dataCol);
PDataType dataColType = dataColRef.getColumn().getDataType();
// TODO: test case for this
if (!isTopLevel() && indexColType != dataColType) {
indexColNode = FACTORY.cast(indexColNode, dataColType, null, null);
}
return indexColNode;
}
Aggregations