Refine search
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()); } } }
private void analyzeGroupingOperations(QuerySpecification node, List<Expression> outputExpressions, List<Expression> orderByExpressions) { List<GroupingOperation> groupingOperations = extractExpressions(Iterables.concat(outputExpressions, orderByExpressions), GroupingOperation.class); boolean isGroupingOperationPresent = !groupingOperations.isEmpty(); if (isGroupingOperationPresent && !node.getGroupBy().isPresent()) { throw new SemanticException( INVALID_PROCEDURE_ARGUMENTS, node, "A GROUPING() operation can only be used with a corresponding GROUPING SET/CUBE/ROLLUP/GROUP BY clause"); } analysis.setGroupingOperations(node, groupingOperations); }
public static CatalogSchemaName createCatalogSchemaName(Session session, Node node, Optional<QualifiedName> schema) { String catalogName = session.getCatalog().orElse(null); String schemaName = session.getSchema().orElse(null); if (schema.isPresent()) { List<String> parts = schema.get().getParts(); if (parts.size() > 2) { throw new SemanticException(INVALID_SCHEMA_NAME, node, "Too many parts in schema name: %s", schema.get()); } if (parts.size() == 2) { catalogName = parts.get(0); } schemaName = schema.get().getSuffix(); } if (catalogName == null) { throw new SemanticException(CATALOG_NOT_SPECIFIED, node, "Catalog must be specified when session catalog is not set"); } if (schemaName == null) { throw new SemanticException(SCHEMA_NOT_SPECIFIED, node, "Schema must be specified when session schema is not set"); } return new CatalogSchemaName(catalogName, schemaName); }
public Boolean visitGroupingOperation(GroupingOperation node, Void context) { // ensure that no output fields are referenced from ORDER BY clause if (orderByScope.isPresent()) { node.getGroupingColumns().forEach(groupingColumn -> verifyNoOrderByReferencesToOutputColumns( groupingColumn, REFERENCE_TO_OUTPUT_ATTRIBUTE_WITHIN_ORDER_BY_GROUPING, "Invalid reference to output of SELECT clause from grouping() expression in ORDER BY")); } Optional<Expression> argumentNotInGroupBy = node.getGroupingColumns().stream() .filter(argument -> !columnReferences.containsKey(NodeRef.of(argument)) || !isGroupingKey(argument)) .findAny(); if (argumentNotInGroupBy.isPresent()) { throw new SemanticException( INVALID_PROCEDURE_ARGUMENTS, node, "The arguments to GROUPING() must be expressions referenced by the GROUP BY at the associated query level. Mismatch due to %s.", argumentNotInGroupBy.get()); } return true; }
private void analyzeHaving(QuerySpecification node, Scope scope) { if (node.getHaving().isPresent()) { Expression predicate = node.getHaving().get(); ExpressionAnalysis expressionAnalysis = analyzeExpression(predicate, scope); expressionAnalysis.getWindowFunctions().stream() .findFirst() .ifPresent(function -> { throw new SemanticException(NESTED_WINDOW, function.getNode(), "HAVING clause cannot contain window functions"); }); analysis.recordSubqueries(node, expressionAnalysis); Type predicateType = expressionAnalysis.getType(predicate); if (!predicateType.equals(BOOLEAN) && !predicateType.equals(UNKNOWN)) { throw new SemanticException(TYPE_MISMATCH, predicate, "HAVING clause must evaluate to a boolean: actual type %s", predicateType); } analysis.setHaving(node, predicate); } }
@Override public Boolean visitWindowFrame(WindowFrame node, Void context) { Optional<Expression> start = node.getStart().getValue(); if (start.isPresent()) { if (!process(start.get(), context)) { throw new SemanticException(MUST_BE_AGGREGATE_OR_GROUP_BY, start.get(), "Window frame start must be an aggregate expression or appear in GROUP BY clause"); } } if (node.getEnd().isPresent() && node.getEnd().get().getValue().isPresent()) { Expression endValue = node.getEnd().get().getValue().get(); if (!process(endValue, context)) { throw new SemanticException(MUST_BE_AGGREGATE_OR_GROUP_BY, endValue, "Window frame end must be an aggregate expression or appear in GROUP BY clause"); } } return true; }
private Type coerceToSingleType(StackableAstVisitorContext<Context> context, String message, List<Expression> expressions) { // determine super type Type superType = UNKNOWN; for (Expression expression : expressions) { Optional<Type> newSuperType = typeManager.getCommonSuperType(superType, process(expression, context)); if (!newSuperType.isPresent()) { throw new SemanticException(TYPE_MISMATCH, expression, message, superType); } superType = newSuperType.get(); } // verify all expressions can be coerced to the superType for (Expression expression : expressions) { Type type = process(expression, context); if (!type.equals(superType)) { if (!typeManager.canCoerce(type, superType)) { throw new SemanticException(TYPE_MISMATCH, expression, message, superType); } addOrReplaceExpressionCoercion(expression, type, superType); } } return superType; }
@Override protected Void visitFunctionCall(FunctionCall functionCall, Analysis analysis) { requireNonNull(analysis, "analysis is null"); Signature signature = analysis.getFunctionSignature(functionCall); if (signature != null && signature.getKind() == WINDOW && !functionCall.getWindow().isPresent()) { throw new SemanticException(WINDOW_REQUIRES_OVER, functionCall, "Window function %s requires an OVER clause", signature.getName()); } return super.visitFunctionCall(functionCall, analysis); } }
@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; }
private Type coerceToSingleType(StackableAstVisitorContext<Context> context, Node node, String message, Expression first, Expression second) { Type firstType = UNKNOWN; if (first != null) { firstType = process(first, context); } Type secondType = UNKNOWN; if (second != null) { secondType = process(second, context); } // coerce types if possible Optional<Type> superTypeOptional = typeManager.getCommonSuperType(firstType, secondType); if (superTypeOptional.isPresent() && typeManager.canCoerce(firstType, superTypeOptional.get()) && typeManager.canCoerce(secondType, superTypeOptional.get())) { Type superType = superTypeOptional.get(); if (!firstType.equals(superType)) { addOrReplaceExpressionCoercion(first, firstType, superType); } if (!secondType.equals(superType)) { addOrReplaceExpressionCoercion(second, secondType, superType); } return superType; } throw new SemanticException(TYPE_MISMATCH, node, message, firstType, secondType); }
@Override public ListenableFuture<?> execute(RenameTable statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); QualifiedObjectName tableName = createQualifiedObjectName(session, statement, statement.getSource()); Optional<TableHandle> tableHandle = metadata.getTableHandle(session, tableName); if (!tableHandle.isPresent()) { throw new SemanticException(MISSING_TABLE, statement, "Table '%s' does not exist", tableName); } QualifiedObjectName target = createQualifiedObjectName(session, statement, statement.getTarget()); if (!metadata.getCatalogHandle(session, target.getCatalogName()).isPresent()) { throw new SemanticException(MISSING_CATALOG, statement, "Target catalog '%s' does not exist", target.getCatalogName()); } if (metadata.getTableHandle(session, target).isPresent()) { throw new SemanticException(TABLE_ALREADY_EXISTS, statement, "Target table '%s' already exists", target); } if (!tableName.getCatalogName().equals(target.getCatalogName())) { throw new SemanticException(NOT_SUPPORTED, statement, "Table rename across catalogs is not supported"); } accessControl.checkCanRenameTable(session.getRequiredTransactionId(), session.getIdentity(), tableName, target); metadata.renameTable(session, tableHandle.get(), target); return immediateFuture(null); } }
@Override public ListenableFuture<?> execute(Use statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); if (!statement.getCatalog().isPresent() && !session.getCatalog().isPresent()) { throw new SemanticException(CATALOG_NOT_SPECIFIED, statement, "Catalog must be specified when session catalog is not set"); } if (statement.getCatalog().isPresent()) { String catalog = statement.getCatalog().get().getValue().toLowerCase(ENGLISH); if (!metadata.getCatalogHandle(session, catalog).isPresent()) { throw new PrestoException(NOT_FOUND, "Catalog does not exist: " + catalog); } stateMachine.setSetCatalog(catalog); } stateMachine.setSetSchema(statement.getSchema().getValue().toLowerCase(ENGLISH)); return immediateFuture(null); } }
@Override protected Type visitNullIfExpression(NullIfExpression node, StackableAstVisitorContext<Context> context) { Type firstType = process(node.getFirst(), context); Type secondType = process(node.getSecond(), context); if (!typeManager.getCommonSuperType(firstType, secondType).isPresent()) { throw new SemanticException(TYPE_MISMATCH, node, "Types are not comparable with NULLIF: %s vs %s", firstType, secondType); } return setExpressionType(node, firstType); }
@Override public ListenableFuture<?> execute(DropTable statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); QualifiedObjectName tableName = createQualifiedObjectName(session, statement, statement.getTableName()); Optional<TableHandle> tableHandle = metadata.getTableHandle(session, tableName); if (!tableHandle.isPresent()) { if (!statement.isExists()) { throw new SemanticException(MISSING_TABLE, statement, "Table '%s' does not exist", tableName); } return immediateFuture(null); } accessControl.checkCanDropTable(session.getRequiredTransactionId(), session.getIdentity(), tableName); metadata.dropTable(session, tableHandle.get()); return immediateFuture(null); } }
if (metadata.getView(session, targetTable).isPresent()) { throw new SemanticException(NOT_SUPPORTED, insert, "Inserting into views is not supported"); if (!targetTableHandle.isPresent()) { throw new SemanticException(MISSING_TABLE, insert, "Table '%s' does not exist", targetTable); if (insert.getColumns().isPresent()) { insertColumns = insert.getColumns().get().stream() .map(Identifier::getValue) for (String insertColumn : insertColumns) { if (!tableColumns.contains(insertColumn)) { throw new SemanticException(MISSING_COLUMN, insert, "Insert column name does not exist in target table: %s", insertColumn); throw new SemanticException(DUPLICATE_COLUMN_NAME, insert, "Insert column name is specified more than once: %s", insertColumn); throw new SemanticException(MISMATCHED_SET_COLUMN_TYPES, insert, "Insert query has mismatched column types: " + "Table: [" + Joiner.on(", ").join(tableTypes) + "], " + "Query: [" + Joiner.on(", ").join(queryTypes) + "]");
for (Identifier column : columns) { if (!seen.add(column)) { throw new SemanticException(DUPLICATE_COLUMN_NAME, column, "Column '%s' appears multiple times in USING clause", column.getValue()); Optional<ResolvedField> rightField = right.tryResolveField(column); if (!leftField.isPresent()) { throw new SemanticException(MISSING_ATTRIBUTE, column, "Column '%s' is missing from left side of join", column.getValue()); if (!rightField.isPresent()) { throw new SemanticException(MISSING_ATTRIBUTE, column, "Column '%s' is missing from right side of join", column.getValue()); throw new SemanticException(TYPE_MISMATCH, column, "%s", e.getMessage());
throw new SemanticException(MISMATCHED_SET_COLUMN_TYPES, node, "Values rows have mismatched types: %s vs %s", if (!commonSuperType.isPresent()) { throw new SemanticException(MISMATCHED_SET_COLUMN_TYPES, node, "Values rows have mismatched types: %s vs %s",
@Override public Boolean visitWindow(Window node, Void context) { for (Expression expression : node.getPartitionBy()) { if (!process(expression, context)) { throw new SemanticException(MUST_BE_AGGREGATE_OR_GROUP_BY, expression, "PARTITION BY expression '%s' must be an aggregate expression or appear in GROUP BY clause", expression); } } for (SortItem sortItem : getSortItemsFromOrderBy(node.getOrderBy())) { Expression expression = sortItem.getSortKey(); if (!process(expression, context)) { throw new SemanticException(MUST_BE_AGGREGATE_OR_GROUP_BY, expression, "ORDER BY expression '%s' must be an aggregate expression or appear in GROUP BY clause", expression); } } if (node.getFrame().isPresent()) { process(node.getFrame().get(), context); } return true; }
if (windowFunction.getFilter().isPresent()) { throw new SemanticException(NOT_SUPPORTED, node, "FILTER is not yet supported for window functions"); if (windowFunction.getOrderBy().isPresent()) { throw new SemanticException(NOT_SUPPORTED, windowFunction, "Window function with ORDER BY is not supported"); throw new SemanticException(NESTED_WINDOW, node, "Cannot nest window functions inside window function '%s': %s", windowFunction, windowFunctions); throw new SemanticException(NOT_SUPPORTED, node, "DISTINCT in window function parameters not yet supported: %s", windowFunction); if (window.getFrame().isPresent()) { analyzeWindowFrame(window.getFrame().get()); throw new SemanticException(MUST_BE_WINDOW_FUNCTION, node, "Not a window function: %s", windowFunction.getName());
if (!node.getWindow().isPresent()) { List<FunctionCall> aggregateFunctions = extractAggregateFunctions(node.getArguments(), metadata.getFunctionRegistry()); List<FunctionCall> windowFunctions = extractWindowFunctions(node.getArguments()); throw new SemanticException(NESTED_AGGREGATION, node, "Cannot nest aggregations inside aggregation '%s': %s", throw new SemanticException(NESTED_WINDOW, node, "Cannot nest window functions inside aggregation '%s': %s", for (Expression sortKey : sortKeys) { if (!node.getArguments().contains(sortKey) && !fieldIds.contains(columnReferences.get(NodeRef.of(sortKey)))) { throw new SemanticException( ORDER_BY_MUST_BE_IN_AGGREGATE, sortKey, if (node.getFilter().isPresent()) { throw new SemanticException(MUST_BE_AGGREGATION_FUNCTION, node, "Filter is only valid for aggregation functions", if (node.getOrderBy().isPresent()) { throw new SemanticException(MUST_BE_AGGREGATION_FUNCTION, node, "ORDER BY is only valid for aggregation functions");