/** * Creates a new tuple descriptor containing only the visible fields. */ public RelationType withOnlyVisibleFields() { return new RelationType(visibleFields); }
for (int i = 0; i < left.getRelationType().getAllFieldCount(); i++) { if (!leftJoinFields.contains(i)) { outputs.add(left.getRelationType().getFieldByIndex(i)); leftFields.add(i); for (int i = 0; i < right.getRelationType().getAllFieldCount(); i++) { if (!rightJoinFields.contains(i)) { outputs.add(right.getRelationType().getFieldByIndex(i)); rightFields.add(i); return createAndAssignScope(node, scope, new RelationType(outputs.build()));
@Override protected RelationPlan visitTable(Table node, Void context) { Query namedQuery = analysis.getNamedQuery(node); Scope scope = analysis.getScope(node); if (namedQuery != null) { RelationPlan subPlan = process(namedQuery, null); // Add implicit coercions if view query produces types that don't match the declared output types // of the view (e.g., if the underlying tables referenced by the view changed) Type[] types = scope.getRelationType().getAllFields().stream().map(Field::getType).toArray(Type[]::new); RelationPlan withCoercions = addCoercions(subPlan, types); return new RelationPlan(withCoercions.getRoot(), scope, withCoercions.getFieldMappings()); } TableHandle handle = analysis.getTableHandle(node); ImmutableList.Builder<Symbol> outputSymbolsBuilder = ImmutableList.builder(); ImmutableMap.Builder<Symbol, ColumnHandle> columns = ImmutableMap.builder(); for (Field field : scope.getRelationType().getAllFields()) { Symbol symbol = symbolAllocator.newSymbol(field.getName().get(), field.getType()); outputSymbolsBuilder.add(symbol); columns.put(symbol, analysis.getColumn(field)); } List<Symbol> outputSymbols = outputSymbolsBuilder.build(); PlanNode root = new TableScanNode(idAllocator.getNextId(), handle, outputSymbols, columns.build()); return new RelationPlan(root, scope, outputSymbols); }
private Optional<ResolvedField> resolveField(Expression node, QualifiedName name, int fieldIndexOffset, boolean local) { List<Field> matches = relation.resolveFields(name); if (matches.size() > 1) { throw ambiguousAttributeException(node, name); } else if (matches.size() == 1) { return Optional.of(asResolvedField(getOnlyElement(matches), fieldIndexOffset, local)); } else { if (isColumnReference(name, relation)) { return Optional.empty(); } if (parent.isPresent()) { return parent.get().resolveField(node, name, fieldIndexOffset + relation.getAllFieldCount(), local && !queryBoundary); } return Optional.empty(); } }
private void validateColumns(Statement node, RelationType descriptor) { // verify that all column names are specified and unique // TODO: collect errors and return them all at once Set<String> names = new HashSet<>(); for (Field field : descriptor.getVisibleFields()) { Optional<String> fieldName = field.getName(); if (!fieldName.isPresent()) { throw new SemanticException(COLUMN_NAME_NOT_SPECIFIED, node, "Column name not specified at position %s", descriptor.indexOf(field) + 1); } if (!names.add(fieldName.get())) { throw new SemanticException(DUPLICATE_COLUMN_NAME, node, "Column name '%s' specified more than once", fieldName.get()); } if (field.getType().equals(UNKNOWN)) { throw new SemanticException(COLUMN_TYPE_UNKNOWN, node, "Column type is unknown: %s", fieldName.get()); } } }
for (Field field : descriptor.getVisibleFields()) { int fieldIndex = descriptor.indexOf(field); Symbol symbol = childOutputSymbols.get(fieldIndex); outputSymbolBuilder.add(symbolAllocator.newSymbol(symbol.getName(), symbolAllocator.getTypes().get(symbol))); checkArgument(descriptor.getVisibleFieldCount() == outputs.size(), "Expected relation to have %s symbols but has %s symbols", descriptor.getVisibleFieldCount(), outputs.size()); for (Field field : descriptor.getVisibleFields()) { int fieldIndex = descriptor.indexOf(field); symbolMapping.put(outputs.get(fieldId), childOutputSymbols.get(fieldIndex)); fieldId++;
private RelationPlan addCoercions(RelationPlan plan, Type[] targetColumnTypes) RelationType oldDescriptor = plan.getDescriptor().withOnlyVisibleFields(); verify(targetColumnTypes.length == oldSymbols.size()); ImmutableList.Builder<Symbol> newSymbols = new ImmutableList.Builder<>(); newSymbols.add(outputSymbol); Field oldField = oldDescriptor.getFieldByIndex(i); newFields[i] = new Field( oldField.getRelationAlias(), return new RelationPlan(projectNode, Scope.builder().withRelationType(RelationId.anonymous(), new RelationType(newFields)).build(), newSymbols.build());
ImmutableMap.Builder<Symbol, ColumnHandle> columns = ImmutableMap.builder(); ImmutableList.Builder<Field> fields = ImmutableList.builder(); for (Field field : descriptor.getAllFields()) { Symbol symbol = symbolAllocator.newSymbol(field.getName().get(), field.getType()); outputSymbols.add(symbol); Scope scope = Scope.builder().withRelationType(RelationId.anonymous(), new RelationType(fields.build())).build(); RelationPlan relationPlan = new RelationPlan(tableScan, scope, outputSymbols.build()); Symbol rowId = builder.translate(new FieldReference(relationPlan.getDescriptor().indexOf(rowIdField))); List<Symbol> outputs = ImmutableList.of( symbolAllocator.newSymbol("partialrows", BIGINT),
.map(relation -> process(relation, context).withOnlyVisibleFields()) .toArray(RelationType[]::new); Type[] outputFieldTypes = descriptors[0].getVisibleFields().stream() .map(Field::getType) .toArray(Type[]::new); for (RelationType descriptor : descriptors) { int outputFieldSize = outputFieldTypes.length; int descFieldSize = descriptor.getVisibleFields().size(); if (outputFieldSize != descFieldSize) { throw new SemanticException(MISMATCHED_SET_COLUMN_TYPES, for (int i = 0; i < descriptor.getVisibleFields().size(); i++) { Type descFieldType = descriptor.getFieldByIndex(i).getType(); Optional<Type> commonSuperType = metadata.getTypeManager().getCommonSuperType(outputFieldTypes[i], descFieldType); if (!commonSuperType.isPresent()) { RelationType firstDescriptor = descriptors[0].withOnlyVisibleFields(); for (int i = 0; i < outputFieldTypes.length; i++) { Field oldField = firstDescriptor.getFieldByIndex(i); outputDescriptorFields[i] = new Field(oldField.getRelationAlias(), oldField.getName(), outputFieldTypes[i], oldField.isHidden()); RelationType outputDescriptor = new RelationType(outputDescriptorFields); analysis.setOutputDescriptor(node, outputDescriptor); Relation relation = node.getRelations().get(i); RelationType descriptor = descriptors[i]; for (int j = 0; j < descriptor.getVisibleFields().size(); j++) { Type outputFieldType = outputFieldTypes[j]; Type descFieldType = descriptor.getFieldByIndex(j).getType();
private Boolean isField(QualifiedName qualifiedName) { List<Field> fields = tupleDescriptor.resolveFields(qualifiedName); checkState(!fields.isEmpty(), "No fields for name '%s'", qualifiedName); checkState(fields.size() <= 1, "Found more than one field for name '%s': %s", qualifiedName, fields); Field field = Iterables.getOnlyElement(fields); return fieldIndexes.contains(tupleDescriptor.indexOf(field)); }
.map(relation -> { Scope relationScope = process(relation, scope); return createAndAssignScope(relation, scope, relationScope.getRelationType().withOnlyVisibleFields()); }) .collect(toImmutableList()); Type[] outputFieldTypes = relationScopes.get(0).getRelationType().getVisibleFields().stream() .map(Field::getType) .toArray(Type[]::new); int outputFieldSize = outputFieldTypes.length; RelationType relationType = relationScope.getRelationType(); int descFieldSize = relationType.getVisibleFields().size(); String setOperationName = node.getClass().getSimpleName().toUpperCase(ENGLISH); if (outputFieldSize != descFieldSize) { Type descFieldType = relationType.getFieldByIndex(i).getType(); Optional<Type> commonSuperType = metadata.getTypeManager().getCommonSuperType(outputFieldTypes[i], descFieldType); if (!commonSuperType.isPresent()) { RelationType firstDescriptor = relationScopes.get(0).getRelationType().withOnlyVisibleFields(); for (int i = 0; i < outputFieldTypes.length; i++) { Field oldField = firstDescriptor.getFieldByIndex(i); outputDescriptorFields[i] = new Field( oldField.getRelationAlias(), Scope relationScope = relationScopes.get(i); RelationType relationType = relationScope.getRelationType(); for (int j = 0; j < relationType.getVisibleFields().size(); j++) {
for (Field field : queryDescriptor.getAllFields()) { fields.add(Field.newQualified(QualifiedName.of(name), field.getName(), field.getType(), false)); RelationType descriptor = new RelationType(fields.build()); analysis.setOutputDescriptor(table, descriptor); return descriptor; RelationType descriptor = analyzeView(query, name, view.getCatalog(), view.getSchema(), view.getOwner(), table); if (isViewStale(view.getColumns(), descriptor.getVisibleFields())) { throw new SemanticException(VIEW_IS_STALE, table, "View '%s' is stale; it must be re-created", name); analysis.setOutputDescriptor(table, new RelationType(outputFields)); return descriptor; RelationType descriptor = new RelationType(fields.build()); analysis.setOutputDescriptor(table, descriptor); return descriptor;
private static List<ColumnMetadata> getOutputTableColumns(RelationPlan plan, Optional<List<Identifier>> columnAliases) { ImmutableList.Builder<ColumnMetadata> columns = ImmutableList.builder(); int aliasPosition = 0; for (Field field : plan.getDescriptor().getVisibleFields()) { String columnName = columnAliases.isPresent() ? columnAliases.get().get(aliasPosition).getValue() : field.getName().get(); columns.add(new ColumnMetadata(columnName, field.getType())); aliasPosition++; } return columns.build(); }
Field inputField = queryDescriptor.getFieldByIndex(field); fieldBuilder.add(Field.newQualified( QualifiedName.of(name), fields = queryDescriptor.getAllFields().stream() .map(field -> Field.newQualified( QualifiedName.of(name), analysis.unregisterTableForView(); if (isViewStale(view.getColumns(), descriptor.getVisibleFields())) { throw new SemanticException(VIEW_IS_STALE, table, "View '%s' is stale; it must be re-created", name);
@Override protected Boolean visitFieldReference(FieldReference node, Void context) { if (orderByScope.isPresent()) { return true; } FieldId fieldId = requireNonNull(columnReferences.get(NodeRef.<Expression>of(node)), "No FieldId for FieldReference"); boolean inGroup = groupingFields.contains(fieldId); if (!inGroup) { Field field = sourceScope.getRelationType().getFieldByIndex(node.getFieldIndex()); String column; if (!field.getName().isPresent()) { column = Integer.toString(node.getFieldIndex() + 1); } else if (field.getRelationAlias().isPresent()) { column = String.format("'%s.%s'", field.getRelationAlias().get(), field.getName().get()); } else { column = "'" + field.getName().get() + "'"; } throw new SemanticException(MUST_BE_AGGREGATE_OR_GROUP_BY, node, "Column %s not in GROUP BY clause", column); } return inGroup; }
@Override protected Scope visitAliasedRelation(AliasedRelation relation, Optional<Scope> scope) { Scope relationScope = process(relation.getRelation(), scope); // todo this check should be inside of TupleDescriptor.withAlias, but the exception needs the node object RelationType relationType = relationScope.getRelationType(); if (relation.getColumnNames() != null) { int totalColumns = relationType.getVisibleFieldCount(); if (totalColumns != relation.getColumnNames().size()) { throw new SemanticException(MISMATCHED_COLUMN_ALIASES, relation, "Column alias list has %s entries but '%s' has %s columns available", relation.getColumnNames().size(), relation.getAlias(), totalColumns); } } List<String> aliases = null; if (relation.getColumnNames() != null) { aliases = relation.getColumnNames().stream() .map(Identifier::getValue) .collect(Collectors.toList()); } RelationType descriptor = relationType.withAlias(relation.getAlias().getValue(), aliases); return createAndAssignScope(relation, scope, descriptor); }
if (queryScope.getRelationType().getVisibleFieldCount() != 1) { throw new SemanticException(MULTIPLE_FIELDS_FROM_SUBQUERY, node, "Multiple columns returned by subquery are not yet supported. Found %s", queryScope.getRelationType().getVisibleFieldCount()); Type type = getOnlyElement(queryScope.getRelationType().getVisibleFields()).getType(); return setExpressionType(node, type);
List<Field> fields = relationType.resolveFieldsWithPrefix(starPrefix); if (fields.isEmpty()) { if (starPrefix.isPresent()) { int fieldIndex = relationType.indexOf(field); FieldReference expression = new FieldReference(fieldIndex); outputExpressionBuilder.add(expression);
for (Field field : inputTupleDescriptor.resolveFieldsWithPrefix(starPrefix)) { outputFields.add(Field.newUnqualified(field.getName(), field.getType())); return new RelationType(outputFields.build());
.collect(toImmutableList()); Iterable<Type> queryTypes = transform(queryDescriptor.getVisibleFields(), Field::getType); return new RelationType(Field.newUnqualified("rows", BIGINT));