Example #1
0
 /**
  * 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);
 }
 /** 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);
 }
Example #3
0
 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();
 }
Example #4
0
 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();
 }
Example #5
0
 /**
  * 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;
   }
 }
Example #6
0
  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());
    }
  }
Example #7
0
 public RexInputRef apply(RelDataTypeField input) {
   return new RexInputRef(input.getIndex(), input.getType());
 }
Example #8
0
  /**
   * 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;
  }
Example #9
0
 /**
  * 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());
 }