public List<Double> averageColumnSizes(TableScan rel, RelMetadataQuery mq) { final List<RelDataTypeField> fields = rel.getRowType().getFieldList(); final ImmutableList.Builder<Double> list = ImmutableList.builder(); for (RelDataTypeField field : fields) { list.add(averageTypeValueSize(field.getType())); } return list.build(); }
/** * Creates an expression accessing a given field from a record. * * @param expr Expression yielding a record * @param field Field * @return Expression accessing given field */ private RexNode makeFieldAccessInternal(RexNode expr, final RelDataTypeField field) { if (expr instanceof RexRangeRef) { RexRangeRef range = (RexRangeRef) expr; if (field.getIndex() < 0) { return makeCall( field.getType(), GET_OPERATOR, ImmutableList.of(expr, makeLiteral(field.getName()))); } return new RexInputRef(range.getOffset() + field.getIndex(), field.getType()); } return new RexFieldAccess(expr, field); }
public static ImmutableMap<String, Integer> getRowColNameIndxMap( List<RelDataTypeField> rowFields) { Builder<String, Integer> bldr = ImmutableMap.<String, Integer>builder(); int indx = 0; for (RelDataTypeField rdt : rowFields) { bldr.put(rdt.getName(), indx); indx++; } return bldr.build(); }
public static RelDataType createTypeFromProjection( RelDataType type, List<String> columnNameList, RelDataTypeFactory typeFactory, boolean caseSensitive) { // If the names in columnNameList and type have case-sensitive differences, // the resulting type will use those from type. These are presumably more // canonical. final List<RelDataTypeField> fields = new ArrayList<>(columnNameList.size()); for (String name : columnNameList) { RelDataTypeField field = type.getField(name, caseSensitive, false); fields.add(type.getFieldList().get(field.getIndex())); } return typeFactory.createStructType(fields); }
/** Creates a synthetic Java class whose fields have the same names and relational types. */ private Type createSyntheticType(RelRecordType type) { final String name = "Record" + type.getFieldCount() + "_" + syntheticTypes.size(); final SyntheticRecordType syntheticType = new SyntheticRecordType(type, name); for (final RelDataTypeField recordField : type.getFieldList()) { final Type javaClass = getJavaClass(recordField.getType()); syntheticType.fields.add( new RecordFieldImpl( syntheticType, recordField.getName(), javaClass, recordField.getType().isNullable() && !Primitive.is(javaClass), Modifier.PUBLIC)); } return register(syntheticType); }
public List<Double> averageColumnSizes(Values rel, RelMetadataQuery mq) { final List<RelDataTypeField> fields = rel.getRowType().getFieldList(); final ImmutableList.Builder<Double> list = ImmutableList.builder(); for (int i = 0; i < fields.size(); i++) { RelDataTypeField field = fields.get(i); double d; if (rel.getTuples().isEmpty()) { d = averageTypeValueSize(field.getType()); } else { d = 0; for (ImmutableList<RexLiteral> literals : rel.getTuples()) { d += typeValueSize(field.getType(), literals.get(i).getValue()); } d /= rel.getTuples().size(); } list.add(d); } return list.build(); }
/** * Estimates the average size (in bytes) of a value of a type. * * <p>We assume that the proportion of nulls is negligible, even if the type is nullable. */ public Double averageTypeValueSize(RelDataType type) { switch (type.getSqlTypeName()) { case BOOLEAN: case TINYINT: return 1d; case SMALLINT: return 2d; case INTEGER: case REAL: case DECIMAL: case DATE: case TIME: return 4d; case BIGINT: case DOUBLE: case FLOAT: // sic case TIMESTAMP: case INTERVAL_DAY_TIME: case INTERVAL_YEAR_MONTH: return 8d; case BINARY: return (double) type.getPrecision(); case VARBINARY: return Math.min((double) type.getPrecision(), 100d); case CHAR: return (double) type.getPrecision() * BYTES_PER_CHARACTER; case VARCHAR: // Even in large (say VARCHAR(2000)) columns most strings are small return Math.min((double) type.getPrecision() * BYTES_PER_CHARACTER, 100d); case ROW: Double average = 0.0; for (RelDataTypeField field : type.getFieldList()) { average += averageTypeValueSize(field.getType()); } return average; default: return null; } }
private static void addFields( List<RelDataTypeField> fieldList, List<RelDataType> typeList, List<String> nameList, Set<String> uniqueNames) { for (RelDataTypeField field : fieldList) { String name = field.getName(); // Ensure that name is unique from all previous field names if (uniqueNames.contains(name)) { String nameBase = name; for (int j = 0; ; j++) { name = nameBase + j; if (!uniqueNames.contains(name)) { break; } } } nameList.add(name); uniqueNames.add(name); typeList.add(field.getType()); } }
public RexInputRef apply(RelDataTypeField input) { return new RexInputRef(input.getIndex(), input.getType()); }
/** * Push any equi join conditions that are not column references as Projections on top of the * children. * * @param factory Project factory to use. * @param inputRels inputs to a join * @param leftJoinKeys expressions for LHS of join key * @param rightJoinKeys expressions for RHS of join key * @param systemColCount number of system columns, usually zero. These columns are projected at * the leading edge of the output row. * @param leftKeys on return this contains the join key positions from the new project rel on the * LHS. * @param rightKeys on return this contains the join key positions from the new project rel on the * RHS. * @return the join condition after the equi expressions pushed down. */ public static RexNode projectNonColumnEquiConditions( ProjectFactory factory, RelNode[] inputRels, List<RexNode> leftJoinKeys, List<RexNode> rightJoinKeys, int systemColCount, List<Integer> leftKeys, List<Integer> rightKeys) { RelNode leftRel = inputRels[0]; RelNode rightRel = inputRels[1]; RexBuilder rexBuilder = leftRel.getCluster().getRexBuilder(); RexNode outJoinCond = null; int origLeftInputSize = leftRel.getRowType().getFieldCount(); int origRightInputSize = rightRel.getRowType().getFieldCount(); List<RexNode> newLeftFields = new ArrayList<RexNode>(); List<String> newLeftFieldNames = new ArrayList<String>(); List<RexNode> newRightFields = new ArrayList<RexNode>(); List<String> newRightFieldNames = new ArrayList<String>(); int leftKeyCount = leftJoinKeys.size(); int i; for (i = 0; i < origLeftInputSize; i++) { final RelDataTypeField field = leftRel.getRowType().getFieldList().get(i); newLeftFields.add(rexBuilder.makeInputRef(field.getType(), i)); newLeftFieldNames.add(field.getName()); } for (i = 0; i < origRightInputSize; i++) { final RelDataTypeField field = rightRel.getRowType().getFieldList().get(i); newRightFields.add(rexBuilder.makeInputRef(field.getType(), i)); newRightFieldNames.add(field.getName()); } int newKeyCount = 0; List<Pair<Integer, Integer>> origColEqConds = new ArrayList<Pair<Integer, Integer>>(); for (i = 0; i < leftKeyCount; i++) { RexNode leftKey = leftJoinKeys.get(i); RexNode rightKey = rightJoinKeys.get(i); if (leftKey instanceof RexInputRef && rightKey instanceof RexInputRef) { origColEqConds.add( Pair.of(((RexInputRef) leftKey).getIndex(), ((RexInputRef) rightKey).getIndex())); } else { newLeftFields.add(leftKey); newLeftFieldNames.add(null); newRightFields.add(rightKey); newRightFieldNames.add(null); newKeyCount++; } } for (i = 0; i < origColEqConds.size(); i++) { Pair<Integer, Integer> p = origColEqConds.get(i); RexNode leftKey = leftJoinKeys.get(i); RexNode rightKey = rightJoinKeys.get(i); leftKeys.add(p.left); rightKeys.add(p.right); RexNode cond = rexBuilder.makeCall( SqlStdOperatorTable.EQUALS, rexBuilder.makeInputRef(leftKey.getType(), systemColCount + p.left), rexBuilder.makeInputRef( rightKey.getType(), systemColCount + origLeftInputSize + newKeyCount + p.right)); if (outJoinCond == null) { outJoinCond = cond; } else { outJoinCond = rexBuilder.makeCall(SqlStdOperatorTable.AND, outJoinCond, cond); } } if (newKeyCount == 0) { return outJoinCond; } int newLeftOffset = systemColCount + origLeftInputSize; int newRightOffset = systemColCount + origLeftInputSize + origRightInputSize + newKeyCount; for (i = 0; i < newKeyCount; i++) { leftKeys.add(origLeftInputSize + i); rightKeys.add(origRightInputSize + i); RexNode cond = rexBuilder.makeCall( SqlStdOperatorTable.EQUALS, rexBuilder.makeInputRef( newLeftFields.get(origLeftInputSize + i).getType(), newLeftOffset + i), rexBuilder.makeInputRef( newRightFields.get(origRightInputSize + i).getType(), newRightOffset + i)); if (outJoinCond == null) { outJoinCond = cond; } else { outJoinCond = rexBuilder.makeCall(SqlStdOperatorTable.AND, outJoinCond, cond); } } // added project if need to produce new keys than the original input // fields if (newKeyCount > 0) { leftRel = factory.createProject( leftRel, newLeftFields, SqlValidatorUtil.uniquify(newLeftFieldNames)); rightRel = factory.createProject( rightRel, newRightFields, SqlValidatorUtil.uniquify(newRightFieldNames)); } inputRels[0] = leftRel; inputRels[1] = rightRel; return outJoinCond; }
/** * Estimates the average size (in bytes) of a value of a field, knowing nothing more than its * type. * * <p>We assume that the proportion of nulls is negligible, even if the field is nullable. */ protected Double averageFieldValueSize(RelDataTypeField field) { return averageTypeValueSize(field.getType()); }
/** Analyzes a component of a tuple in a GROUPING SETS clause. */ private static ImmutableBitSet analyzeGroupExpr( SqlValidatorScope scope, List<SqlNode> groupExprs, Map<Integer, Integer> groupExprProjection, SqlNode groupExpr) { final SqlNode expandedGroupExpr = scope.getValidator().expand(groupExpr, scope); switch (expandedGroupExpr.getKind()) { case ROW: return ImmutableBitSet.union( analyzeGroupTuple( scope, groupExprs, groupExprProjection, ((SqlCall) expandedGroupExpr).getOperandList())); case OTHER: if (expandedGroupExpr instanceof SqlNodeList && ((SqlNodeList) expandedGroupExpr).size() == 0) { return ImmutableBitSet.of(); } } final int ref = lookupGroupExpr(groupExprs, groupExpr); if (expandedGroupExpr instanceof SqlIdentifier) { // SQL 2003 does not allow expressions of column references SqlIdentifier expr = (SqlIdentifier) expandedGroupExpr; // column references should be fully qualified. assert expr.names.size() == 2; String originalRelName = expr.names.get(0); String originalFieldName = expr.names.get(1); final SqlValidatorScope.ResolvedImpl resolved = new SqlValidatorScope.ResolvedImpl(); scope.resolve(ImmutableList.of(originalRelName), false, resolved); assert resolved.count() == 1; final SqlValidatorScope.Resolve resolve = resolved.only(); final SqlValidatorNamespace foundNs = resolve.namespace; final int childNamespaceIndex = resolve.path.steps().get(0).i; int namespaceOffset = 0; if (childNamespaceIndex > 0) { // If not the first child, need to figure out the width of // output types from all the preceding namespaces final SqlValidatorScope ancestorScope = resolve.scope; assert ancestorScope instanceof ListScope; List<SqlValidatorNamespace> children = ((ListScope) ancestorScope).getChildren(); for (int j = 0; j < childNamespaceIndex; j++) { namespaceOffset += children.get(j).getRowType().getFieldCount(); } } RelDataTypeField field = scope.getValidator().getCatalogReader().field(foundNs.getRowType(), originalFieldName); int origPos = namespaceOffset + field.getIndex(); groupExprProjection.put(origPos, ref); } return ImmutableBitSet.of(ref); }