/** * A normal reduce operator's rowObjectInspector looks like a struct containing nested key/value * structs that contain the column values: { key: { reducesinkkey0:int }, value: { _col0:int, * _col1:int, .. } } * * <p>While the rowObjectInspector looks the same for vectorized queries during compilation time, * within the tasks at query execution the rowObjectInspector has changed to a flatter structure * without nested key/value structs: { 'key.reducesinkkey0':int, 'value._col0':int, * 'value._col1':int, .. } * * <p>Trying to fetch 'key.reducesinkkey0' by name from the list of flattened ObjectInspectors * does not work because the '.' gets interpreted as a field member, even though it is a flattened * list of column values. This workaround converts the column name referenced in the ExprNodeDesc * from a nested field name (key.reducesinkkey0) to key_reducesinkkey0, simply by replacing '.' * with '_'. * * @param source * @return */ public static ExprNodeDesc flattenExpr(ExprNodeDesc source) { if (source instanceof ExprNodeGenericFuncDesc) { // all children expression should be resolved ExprNodeGenericFuncDesc function = (ExprNodeGenericFuncDesc) source.clone(); List<ExprNodeDesc> newChildren = flattenExprList(function.getChildren()); for (ExprNodeDesc newChild : newChildren) { if (newChild == null) { // Could not resolve all of the function children, fail return null; } } function.setChildren(newChildren); return function; } if (source instanceof ExprNodeColumnDesc) { ExprNodeColumnDesc column = (ExprNodeColumnDesc) source; // Create a new ColumnInfo, replacing STRUCT.COLUMN with STRUCT_COLUMN String newColumn = column.getColumn().replace('.', '_'); return new ExprNodeColumnDesc(source.getTypeInfo(), newColumn, column.getTabAlias(), false); } if (source instanceof ExprNodeFieldDesc) { // field expression should be resolved ExprNodeFieldDesc field = (ExprNodeFieldDesc) source.clone(); ExprNodeDesc fieldDesc = flattenExpr(field.getDesc()); if (fieldDesc == null) { return null; } field.setDesc(fieldDesc); return field; } // constant or null expr, just return return source; }
public static ArrayList<ExprNodeDesc> clone(List<ExprNodeDesc> sources) { ArrayList<ExprNodeDesc> result = new ArrayList<ExprNodeDesc>(); for (ExprNodeDesc expr : sources) { result.add(expr.clone()); } return result; }
public static ExprNodeDesc backtrack( ExprNodeDesc source, Operator<?> current, Operator<?> terminal, boolean foldExpr) throws SemanticException { Operator<?> parent = getSingleParent(current, terminal); if (parent == null) { return source; } if (source instanceof ExprNodeGenericFuncDesc) { // all children expression should be resolved ExprNodeGenericFuncDesc function = (ExprNodeGenericFuncDesc) source.clone(); List<ExprNodeDesc> children = backtrack(function.getChildren(), current, terminal, foldExpr); for (ExprNodeDesc child : children) { if (child == null) { // Could not resolve all of the function children, fail return null; } } function.setChildren(children); if (foldExpr) { // fold after replacing, if possible ExprNodeDesc foldedFunction = ConstantPropagateProcFactory.foldExpr(function); if (foldedFunction != null) { return foldedFunction; } } return function; } if (source instanceof ExprNodeColumnDesc) { ExprNodeColumnDesc column = (ExprNodeColumnDesc) source; return backtrack(column, parent, terminal); } if (source instanceof ExprNodeFieldDesc) { // field expression should be resolved ExprNodeFieldDesc field = (ExprNodeFieldDesc) source.clone(); ExprNodeDesc fieldDesc = backtrack(field.getDesc(), current, terminal, foldExpr); if (fieldDesc == null) { return null; } field.setDesc(fieldDesc); return field; } // constant or null expr, just return return source; }