use of org.voltdb.expressions.ConstantValueExpression in project voltdb by VoltDB.
the class ParsedUnionStmt method parseOrderColumn.
/**
* This is a stripped down version of the ParsedSelectStmt.parseOrderColumn. Since the SET ops
* are not allowed to have aggregate expressions (HAVING, GROUP BY) (except the individual SELECTS)
* all the logic handling the aggregates is omitted here
* @param orderByNode
* @param leftmostSelectChild
*/
private void parseOrderColumn(VoltXMLElement orderByNode, ParsedSelectStmt leftmostSelectChild) {
ParsedColInfo.ExpressionAdjuster adjuster = new ParsedColInfo.ExpressionAdjuster() {
@Override
public AbstractExpression adjust(AbstractExpression expr) {
// Union itself can't have aggregate expression
return expr;
}
};
// Get the display columns from the first child
List<ParsedColInfo> displayColumns = leftmostSelectChild.orderByColumns();
ParsedColInfo order_col = ParsedColInfo.fromOrderByXml(leftmostSelectChild, orderByNode, adjuster);
AbstractExpression order_exp = order_col.expression;
assert (order_exp != null);
// helps later when trying to determine ORDER BY coverage (for determinism).
for (ParsedColInfo col : displayColumns) {
if (col.alias.equals(order_col.alias) || col.expression.equals(order_exp)) {
col.orderBy = true;
col.ascending = order_col.ascending;
order_col.alias = col.alias;
order_col.columnName = col.columnName;
order_col.tableName = col.tableName;
break;
}
}
assert (!(order_exp instanceof ConstantValueExpression));
assert (!(order_exp instanceof ParameterValueExpression));
m_orderColumns.add(order_col);
}
use of org.voltdb.expressions.ConstantValueExpression in project voltdb by VoltDB.
the class ParsedInsertStmt method defaultValueToExpr.
private AbstractExpression defaultValueToExpr(Column column) {
AbstractExpression expr = null;
boolean isConstantValue = true;
if (column.getDefaulttype() == VoltType.TIMESTAMP.getValue()) {
boolean isFunctionFormat = true;
String timeValue = column.getDefaultvalue();
try {
Long.parseLong(timeValue);
isFunctionFormat = false;
} catch (NumberFormatException e) {
}
if (isFunctionFormat) {
try {
java.sql.Timestamp.valueOf(timeValue);
isFunctionFormat = false;
} catch (IllegalArgumentException e) {
}
}
if (isFunctionFormat) {
String name = timeValue.split(":")[0];
int id = Integer.parseInt(timeValue.split(":")[1]);
FunctionExpression funcExpr = new FunctionExpression();
funcExpr.setAttributes(name, null, id);
funcExpr.setValueType(VoltType.TIMESTAMP);
funcExpr.setValueSize(VoltType.TIMESTAMP.getMaxLengthInBytes());
expr = funcExpr;
isConstantValue = false;
}
}
if (isConstantValue) {
// Not Default sql function.
ConstantValueExpression const_expr = new ConstantValueExpression();
expr = const_expr;
if (column.getDefaulttype() != 0) {
const_expr.setValue(column.getDefaultvalue());
const_expr.refineValueType(VoltType.get((byte) column.getDefaulttype()), column.getSize());
} else {
const_expr.setValue(null);
const_expr.refineValueType(VoltType.get((byte) column.getType()), column.getSize());
}
}
assert (expr != null);
return expr;
}
use of org.voltdb.expressions.ConstantValueExpression in project voltdb by VoltDB.
the class ParsedSelectStmt method parseDisplayColumn.
private void parseDisplayColumn(int index, VoltXMLElement child, boolean isDistributed) {
ParsedColInfo col = new ParsedColInfo();
m_aggregationList.clear();
// This index calculation is only used for sanity checking
// materialized views (which use the parsed select statement but
// don't go through the planner pass that does more involved
// column index resolution).
col.index = index;
// Parse the expression. We may substitute for this later
// on, but it's a place to start.
AbstractExpression colExpr = parseExpressionTree(child);
if (colExpr instanceof ConstantValueExpression) {
assert (colExpr.getValueType() != VoltType.NUMERIC);
}
assert (colExpr != null);
if (isDistributed) {
colExpr = colExpr.replaceAVG();
updateAvgExpressions();
}
ExpressionUtil.finalizeValueTypes(colExpr);
if (colExpr.getValueType() == VoltType.BOOLEAN) {
throw new PlanningErrorException("A SELECT clause does not allow a BOOLEAN expression. " + "consider using CASE WHEN to decode the BOOLEAN expression " + "into a value of some other type.");
}
// ENG-6291: If parent is UNION, voltdb wants to make inline varchar to be outlined
if (isParentUnionClause() && AbstractExpression.hasInlineVarType(colExpr)) {
AbstractExpression expr = new OperatorExpression();
;
expr.setExpressionType(ExpressionType.OPERATOR_CAST);
VoltType voltType = colExpr.getValueType();
// We don't support parameterized casting,
// such as specifically to "VARCHAR(3)" vs. VARCHAR,
// so assume max length for variable-length types
// (VARCHAR and VARBINARY).
int size = expr.getInBytes() ? voltType.getMaxLengthInBytes() : VoltType.MAX_VALUE_LENGTH_IN_CHARACTERS;
expr.setValueType(voltType);
expr.setValueSize(size);
expr.setInBytes(colExpr.getInBytes());
expr.setLeft(colExpr);
// switch the new expression for CAST
colExpr = expr;
}
// Remember the column expression.
col.expression = colExpr;
calculateColumnNames(child, col);
insertAggExpressionsToAggResultColumns(m_aggregationList, col);
if (m_aggregationList.size() >= 1) {
m_hasAggregateExpression = true;
for (AbstractExpression agg : m_aggregationList) {
assert (agg instanceof AggregateExpression);
if (!m_hasAggregateDistinct && ((AggregateExpression) agg).isDistinct()) {
m_hasAggregateDistinct = true;
break;
}
}
}
// The differentiator is used when ParsedColInfo is converted to a
// SchemaColumn object, to differentiate between columns that have the
// same name within a table (which can happen for subqueries or joins).
col.differentiator = index;
m_displayColumns.add(col);
}
use of org.voltdb.expressions.ConstantValueExpression in project voltdb by VoltDB.
the class IndexCountPlanNode method createOrNull.
// Create an IndexCountPlanNode that replaces the parent aggregate and child
// indexscan IF the indexscan's end expressions are a form that can be
// modeled with an end key.
// The supported forms for end expression are:
// - null
// - one filter expression per index key component (ANDed together)
// as "combined" for the IndexScan.
// - fewer filter expressions than index key components with one of the
// (the last) being a LT comparison.
// - 1 fewer filter expressions than index key components,
// but all ANDed equality filters
// The LT restriction comes because when index key prefixes are identical
// to the prefix-only end key, the entire index key sorts greater than the
// prefix-only end-key, because it is always longer.
// These prefix-equal cases would be missed in an EQ or LTE filter,
// causing undercounts.
// A prefix-only LT filter discards prefix-equal cases, so it is allowed.
// @return the IndexCountPlanNode or null if one is not possible.
public static IndexCountPlanNode createOrNull(IndexScanPlanNode isp, AggregatePlanNode apn) {
// add support for reverse scan
// for ASC scan, check endExpression;
// for DESC scan (isReverseScan()), check the searchkeys
List<AbstractExpression> endKeys = new ArrayList<>();
// Translate the index scan's end condition into a list of end key
// expressions and note the comparison operand of the last one.
// Initially assume it to be an equality filter.
IndexLookupType endType = IndexLookupType.EQ;
List<AbstractExpression> endComparisons = ExpressionUtil.uncombinePredicate(isp.getEndExpression());
for (AbstractExpression ae : endComparisons) {
// LT or LTE expression that resets the end type.
assert (endType == IndexLookupType.EQ);
ExpressionType exprType = ae.getExpressionType();
if (exprType == ExpressionType.COMPARE_LESSTHAN) {
endType = IndexLookupType.LT;
} else if (exprType == ExpressionType.COMPARE_LESSTHANOREQUALTO) {
endType = IndexLookupType.LTE;
} else {
assert (exprType == ExpressionType.COMPARE_EQUAL || exprType == ExpressionType.COMPARE_NOTDISTINCT);
}
// PlanNodes all need private deep copies of expressions
// so that the resolveColumnIndexes results
// don't get bashed by other nodes or subsequent planner runs
endKeys.add(ae.getRight().clone());
}
int indexSize = 0;
String jsonstring = isp.getCatalogIndex().getExpressionsjson();
List<ColumnRef> indexedColRefs = null;
List<AbstractExpression> indexedExprs = null;
if (jsonstring.isEmpty()) {
indexedColRefs = CatalogUtil.getSortedCatalogItems(isp.getCatalogIndex().getColumns(), "index");
indexSize = indexedColRefs.size();
} else {
try {
indexedExprs = AbstractExpression.fromJSONArrayString(jsonstring, isp.getTableScan());
indexSize = indexedExprs.size();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int searchKeySize = isp.getSearchKeyExpressions().size();
int endKeySize = endKeys.size();
if (!isp.isReverseScan() && endType != IndexLookupType.LT && endKeySize > 0 && endKeySize < indexSize) {
// That is, when a prefix-only key exists and does not use LT.
if (endType != IndexLookupType.EQ || searchKeySize != indexSize || endKeySize < indexSize - 1) {
return null;
}
// To use an index count for an equality search of da compound key,
// both the search key and end key must have a component for each
// index component.
// If the search key is long enough but the end key is one component
// short, it can be patched with a type-appropriate max key value
// (if one exists for the type), but the end key comparison needs to
// change from EQ to LTE to compensate.
VoltType missingEndKeyType;
// and get the missing key component's indexed expression.
if (jsonstring.isEmpty()) {
int lastIndex = indexedColRefs.get(endKeySize).getColumn().getIndex();
for (AbstractExpression expr : endComparisons) {
if (((TupleValueExpression) (expr.getLeft())).getColumnIndex() == lastIndex) {
return null;
}
}
int catalogTypeCode = indexedColRefs.get(endKeySize).getColumn().getType();
missingEndKeyType = VoltType.get((byte) catalogTypeCode);
} else {
AbstractExpression lastIndexedExpr = indexedExprs.get(endKeySize);
for (AbstractExpression expr : endComparisons) {
if (expr.getLeft().bindingToIndexedExpression(lastIndexedExpr) != null) {
return null;
}
}
missingEndKeyType = lastIndexedExpr.getValueType();
}
String maxValueForType = missingEndKeyType.getMaxValueForKeyPadding();
// for which all legal values are less than or equal to it.
if (maxValueForType == null) {
return null;
}
ConstantValueExpression maxKey = new ConstantValueExpression();
maxKey.setValueType(missingEndKeyType);
maxKey.setValue(maxValueForType);
maxKey.setValueSize(missingEndKeyType.getLengthInBytesForFixedTypes());
endType = IndexLookupType.LTE;
endKeys.add(maxKey);
}
// DESC case
if (searchKeySize > 0 && searchKeySize < indexSize) {
return null;
}
return new IndexCountPlanNode(isp, apn, endType, endKeys);
}
use of org.voltdb.expressions.ConstantValueExpression in project voltdb by VoltDB.
the class BranchNode method analyzeJoinExpressions.
@Override
public void analyzeJoinExpressions(List<AbstractExpression> noneList) {
JoinNode leftChild = getLeftNode();
JoinNode rightChild = getRightNode();
leftChild.analyzeJoinExpressions(noneList);
rightChild.analyzeJoinExpressions(noneList);
// At this moment all RIGHT joins are already converted to the LEFT ones
assert (getJoinType() != JoinType.RIGHT);
ArrayList<AbstractExpression> joinList = new ArrayList<>();
ArrayList<AbstractExpression> whereList = new ArrayList<>();
// Collect node's own join and where expressions
joinList.addAll(ExpressionUtil.uncombineAny(getJoinExpression()));
whereList.addAll(ExpressionUtil.uncombineAny(getWhereExpression()));
// Collect children expressions only if a child is a leaf. They are not classified yet
if (!(leftChild instanceof BranchNode)) {
joinList.addAll(leftChild.m_joinInnerList);
leftChild.m_joinInnerList.clear();
whereList.addAll(leftChild.m_whereInnerList);
leftChild.m_whereInnerList.clear();
}
if (!(rightChild instanceof BranchNode)) {
joinList.addAll(rightChild.m_joinInnerList);
rightChild.m_joinInnerList.clear();
whereList.addAll(rightChild.m_whereInnerList);
rightChild.m_whereInnerList.clear();
}
Collection<String> outerTables = leftChild.generateTableJoinOrder();
Collection<String> innerTables = rightChild.generateTableJoinOrder();
// Classify join expressions into the following categories:
// 1. The OUTER-only join conditions. If any are false for a given outer tuple,
// then NO inner tuples should match it (and it can automatically get null-padded by the join
// without even considering the inner table). Testing the outer-only conditions
// COULD be considered as an optimal first step to processing each outer tuple
// 2. The INNER-only join conditions apply to the inner tuples (even prior to considering any outer tuple).
// if true for a given inner tuple, the condition has no effect,
// if false, it prevents the inner tuple from matching ANY outer tuple,
// In case of multi-tables join, they could be pushed down to a child node if this node is a join itself
// 3. The two-sided expressions that get evaluated on each combination of outer and inner tuple
// and either accept or reject that particular combination.
// 4. The TVE expressions where neither inner nor outer tables are involved. This is not possible
// for the currently supported two table joins but could change if number of tables > 2.
// Constant Value Expression may fall into this category.
classifyJoinExpressions(joinList, outerTables, innerTables, m_joinOuterList, m_joinInnerList, m_joinInnerOuterList, noneList);
// Apply implied transitive constant filter to join expressions
// outer.partkey = ? and outer.partkey = inner.partkey is equivalent to
// outer.partkey = ? and inner.partkey = ?
applyTransitiveEquivalence(m_joinOuterList, m_joinInnerList, m_joinInnerOuterList);
// Classify where expressions into the following categories:
// 1. The OUTER-only filter conditions. If any are false for a given outer tuple,
// nothing in the join processing of that outer tuple will get it past this filter,
// so it makes sense to "push this filter down" to pre-qualify the outer tuples before they enter the join.
// 2. The INNER-only join conditions. If these conditions reject NULL inner tuple it make sense to
// move them "up" to the join conditions, otherwise they must remain post-join conditions
// to preserve outer join semantic
// 3. The two-sided expressions. Same as the inner only conditions.
// 4. The TVE expressions where neither inner nor outer tables are involved. Same as for the join expressions
classifyJoinExpressions(whereList, outerTables, innerTables, m_whereOuterList, m_whereInnerList, m_whereInnerOuterList, noneList);
// Apply implied transitive constant filter to where expressions
applyTransitiveEquivalence(m_whereOuterList, m_whereInnerList, m_whereInnerOuterList);
// In case of multi-table joins certain expressions could be pushed down to the children
// to improve join performance.
pushDownExpressions(noneList);
Iterator<AbstractExpression> iter = noneList.iterator();
while (iter.hasNext()) {
AbstractExpression noneExpr = iter.next();
// better with these predicates pushed down to the inner child node.
if (noneExpr instanceof ConstantValueExpression) {
m_whereInnerOuterList.add(noneExpr);
iter.remove();
}
}
}
Aggregations