use of org.apache.calcite.rel.type.RelDataTypeFieldImpl in project calcite by apache.
the class RelBuilder method project.
/**
* Creates a {@link org.apache.calcite.rel.core.Project} of the given list
* of expressions, using the given names.
*
* <p>Names are deduced as follows:
* <ul>
* <li>If the length of {@code fieldNames} is greater than the index of
* the current entry in {@code nodes}, and the entry in
* {@code fieldNames} is not null, uses it; otherwise
* <li>If an expression projects an input field,
* or is a cast an input field,
* uses the input field name; otherwise
* <li>If an expression is a call to
* {@link org.apache.calcite.sql.fun.SqlStdOperatorTable#AS}
* (see {@link #alias}), removes the call but uses the intended alias.
* </ul>
*
* <p>After the field names have been inferred, makes the
* field names unique by appending numeric suffixes.
*
* @param nodes Expressions
* @param fieldNames Suggested field names
* @param force create project even if it is identity
*/
public RelBuilder project(Iterable<? extends RexNode> nodes, Iterable<String> fieldNames, boolean force) {
final List<String> names = new ArrayList<>();
final List<RexNode> exprList = new ArrayList<>();
final Iterator<String> nameIterator = fieldNames.iterator();
for (RexNode node : nodes) {
if (simplify) {
node = simplifier.simplifyPreservingType(node);
}
exprList.add(node);
String name = nameIterator.hasNext() ? nameIterator.next() : null;
names.add(name != null ? name : inferAlias(exprList, node));
}
final Frame frame = stack.peek();
final ImmutableList.Builder<Field> fields = ImmutableList.builder();
final Set<String> uniqueNameList = getTypeFactory().getTypeSystem().isSchemaCaseSensitive() ? new HashSet<String>() : new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
// calculate final names and build field list
for (int i = 0; i < names.size(); ++i) {
RexNode node = exprList.get(i);
String name = names.get(i);
Field field;
if (name == null || uniqueNameList.contains(name)) {
int j = 0;
if (name == null) {
j = i;
}
do {
name = SqlValidatorUtil.F_SUGGESTER.apply(name, j, j++);
} while (uniqueNameList.contains(name));
names.set(i, name);
}
RelDataTypeField fieldType = new RelDataTypeFieldImpl(name, i, node.getType());
switch(node.getKind()) {
case INPUT_REF:
// preserve rel aliases for INPUT_REF fields
final int index = ((RexInputRef) node).getIndex();
field = new Field(frame.fields.get(index).left, fieldType);
break;
default:
field = new Field(ImmutableSet.<String>of(), fieldType);
break;
}
uniqueNameList.add(name);
fields.add(field);
}
final RelDataType inputRowType = peek().getRowType();
if (!force && RexUtil.isIdentity(exprList, inputRowType)) {
if (names.equals(inputRowType.getFieldNames())) {
// Do not create an identity project if it does not rename any fields
return this;
} else {
// create "virtual" row type for project only rename fields
stack.pop();
stack.push(new Frame(frame.rel, fields.build()));
return this;
}
}
final RelNode project = projectFactory.createProject(frame.rel, ImmutableList.copyOf(exprList), names);
stack.pop();
stack.push(new Frame(project, fields.build()));
return this;
}
use of org.apache.calcite.rel.type.RelDataTypeFieldImpl in project calcite by apache.
the class RelBuilder method aggregate.
/**
* Creates an {@link org.apache.calcite.rel.core.Aggregate} with a list of
* calls.
*/
public RelBuilder aggregate(GroupKey groupKey, Iterable<AggCall> aggCalls) {
final Registrar registrar = new Registrar();
registrar.extraNodes.addAll(fields());
registrar.names.addAll(peek().getRowType().getFieldNames());
final GroupKeyImpl groupKey_ = (GroupKeyImpl) groupKey;
final ImmutableBitSet groupSet = ImmutableBitSet.of(registrar.registerExpressions(groupKey_.nodes));
label: if (Iterables.isEmpty(aggCalls) && !groupKey_.indicator) {
final RelMetadataQuery mq = peek().getCluster().getMetadataQuery();
if (groupSet.isEmpty()) {
final Double minRowCount = mq.getMinRowCount(peek());
if (minRowCount == null || minRowCount < 1D) {
// empty.
break label;
}
}
if (registrar.extraNodes.size() == fields().size()) {
final Boolean unique = mq.areColumnsUnique(peek(), groupSet);
if (unique != null && unique) {
// Rel is already unique.
return project(fields(groupSet.asList()));
}
}
final Double maxRowCount = mq.getMaxRowCount(peek());
if (maxRowCount != null && maxRowCount <= 1D) {
// If there is at most one row, rel is already unique.
return this;
}
}
final ImmutableList<ImmutableBitSet> groupSets;
if (groupKey_.nodeLists != null) {
final int sizeBefore = registrar.extraNodes.size();
final SortedSet<ImmutableBitSet> groupSetSet = new TreeSet<>(ImmutableBitSet.ORDERING);
for (ImmutableList<RexNode> nodeList : groupKey_.nodeLists) {
final ImmutableBitSet groupSet2 = ImmutableBitSet.of(registrar.registerExpressions(nodeList));
if (!groupSet.contains(groupSet2)) {
throw new IllegalArgumentException("group set element " + nodeList + " must be a subset of group key");
}
groupSetSet.add(groupSet2);
}
groupSets = ImmutableList.copyOf(groupSetSet);
if (registrar.extraNodes.size() > sizeBefore) {
throw new IllegalArgumentException("group sets contained expressions not in group key: " + registrar.extraNodes.subList(sizeBefore, registrar.extraNodes.size()));
}
} else {
groupSets = ImmutableList.of(groupSet);
}
for (AggCall aggCall : aggCalls) {
if (aggCall instanceof AggCallImpl) {
final AggCallImpl aggCall1 = (AggCallImpl) aggCall;
registrar.registerExpressions(aggCall1.operands);
if (aggCall1.filter != null) {
registrar.registerExpression(aggCall1.filter);
}
}
}
project(registrar.extraNodes);
rename(registrar.names);
final Frame frame = stack.pop();
final RelNode r = frame.rel;
final List<AggregateCall> aggregateCalls = new ArrayList<>();
for (AggCall aggCall : aggCalls) {
final AggregateCall aggregateCall;
if (aggCall instanceof AggCallImpl) {
final AggCallImpl aggCall1 = (AggCallImpl) aggCall;
final List<Integer> args = registrar.registerExpressions(aggCall1.operands);
final int filterArg = aggCall1.filter == null ? -1 : registrar.registerExpression(aggCall1.filter);
if (aggCall1.distinct && !aggCall1.aggFunction.isQuantifierAllowed()) {
throw new IllegalArgumentException("DISTINCT not allowed");
}
if (aggCall1.filter != null && !aggCall1.aggFunction.allowsFilter()) {
throw new IllegalArgumentException("FILTER not allowed");
}
aggregateCall = AggregateCall.create(aggCall1.aggFunction, aggCall1.distinct, aggCall1.approximate, args, filterArg, groupSet.cardinality(), r, null, aggCall1.alias);
} else {
aggregateCall = ((AggCallImpl2) aggCall).aggregateCall;
}
aggregateCalls.add(aggregateCall);
}
assert ImmutableBitSet.ORDERING.isStrictlyOrdered(groupSets) : groupSets;
for (ImmutableBitSet set : groupSets) {
assert groupSet.contains(set);
}
RelNode aggregate = aggregateFactory.createAggregate(r, groupKey_.indicator, groupSet, groupSets, aggregateCalls);
// build field list
final ImmutableList.Builder<Field> fields = ImmutableList.builder();
final List<RelDataTypeField> aggregateFields = aggregate.getRowType().getFieldList();
int i = 0;
// first, group fields
for (Integer groupField : groupSet.asList()) {
RexNode node = registrar.extraNodes.get(groupField);
final SqlKind kind = node.getKind();
switch(kind) {
case INPUT_REF:
fields.add(frame.fields.get(((RexInputRef) node).getIndex()));
break;
default:
String name = aggregateFields.get(i).getName();
RelDataTypeField fieldType = new RelDataTypeFieldImpl(name, i, node.getType());
fields.add(new Field(ImmutableSet.<String>of(), fieldType));
break;
}
i++;
}
// second, indicator fields (copy from aggregate rel type)
if (groupKey_.indicator) {
for (int j = 0; j < groupSet.cardinality(); ++j) {
final RelDataTypeField field = aggregateFields.get(i);
final RelDataTypeField fieldType = new RelDataTypeFieldImpl(field.getName(), i, field.getType());
fields.add(new Field(ImmutableSet.<String>of(), fieldType));
i++;
}
}
// third, aggregate fields. retain `i' as field index
for (int j = 0; j < aggregateCalls.size(); ++j) {
final AggregateCall call = aggregateCalls.get(j);
final RelDataTypeField fieldType = new RelDataTypeFieldImpl(aggregateFields.get(i + j).getName(), i + j, call.getType());
fields.add(new Field(ImmutableSet.<String>of(), fieldType));
}
stack.push(new Frame(aggregate, fields.build()));
return this;
}
use of org.apache.calcite.rel.type.RelDataTypeFieldImpl in project calcite by apache.
the class SqlValidatorUtil method getExtendedColumns.
/**
* Gets a list of extended columns with field indices to the underlying table.
*/
public static List<RelDataTypeField> getExtendedColumns(RelDataTypeFactory typeFactory, SqlValidatorTable table, SqlNodeList extendedColumns) {
final ImmutableList.Builder<RelDataTypeField> extendedFields = ImmutableList.builder();
final ExtensibleTable extTable = table.unwrap(ExtensibleTable.class);
int extendedFieldOffset = extTable == null ? table.getRowType().getFieldCount() : extTable.getExtendedColumnOffset();
for (final Pair<SqlIdentifier, SqlDataTypeSpec> pair : pairs(extendedColumns)) {
final SqlIdentifier identifier = pair.left;
final SqlDataTypeSpec type = pair.right;
extendedFields.add(new RelDataTypeFieldImpl(identifier.toString(), extendedFieldOffset++, type.deriveType(typeFactory)));
}
return extendedFields.build();
}
use of org.apache.calcite.rel.type.RelDataTypeFieldImpl in project calcite by apache.
the class JavaTypeFactoryExtImpl method createPdxType.
public RelDataType createPdxType(PdxInstance pdxInstance) {
final List<RelDataTypeField> list = new ArrayList<>();
for (String fieldName : pdxInstance.getFieldNames()) {
Object field = pdxInstance.getField(fieldName);
Type fieldType;
if (field == null) {
fieldType = String.class;
} else if (field instanceof PdxInstance) {
// Map Nested PDX structures as String. This relates with
// GeodeUtils.convert case when clazz is Null.
fieldType = Map.class;
// RelDataType boza = createPdxType((PdxInstance) field);
} else {
fieldType = field.getClass();
}
list.add(new RelDataTypeFieldImpl(fieldName, list.size(), createType(fieldType)));
}
return canonize(new RelRecordType(list));
}
use of org.apache.calcite.rel.type.RelDataTypeFieldImpl in project calcite by apache.
the class JavaTypeFactoryExtImpl method recursiveCreatePdxType.
private void recursiveCreatePdxType(PdxInstance pdxInstance, List<RelDataTypeField> list, String fieldNamePrefix) {
for (String fieldName : pdxInstance.getFieldNames()) {
Object field = pdxInstance.getField(fieldName);
final Type fieldType = field.getClass();
if (fieldType instanceof PdxInstance) {
recursiveCreatePdxType((PdxInstance) field, list, fieldNamePrefix + fieldName + ".");
} else {
list.add(new RelDataTypeFieldImpl(fieldNamePrefix + fieldName, list.size(), createType(fieldType)));
}
}
}
Aggregations