@Override protected String visitArithmeticExpression(ArithmeticExpression node, Void context) { if (node.getType().equals(ArithmeticExpression.Type.DIVIDE)) { if (_outputDivideByZeroGuard == true) { if (node.getRight() instanceof FunctionCall) { if (getFunctionName((FunctionCall) node.getRight()).equals("nullifzero")) { // bypass appending nullifzero return formatBinaryExpression(node.getType().getValue(), node.getLeft(), node.getRight()); } } else if (node.getRight() instanceof Literal) { // purely literal return formatBinaryExpression(node.getType().getValue(), node.getLeft(), node.getRight()); } List<Expression> arguments = new ArrayList<Expression>(); arguments.add(node.getRight()); FunctionCall nullifzeroFunc = new FunctionCall(new QualifiedName("nullifzero"), arguments); return formatBinaryExpression(node.getType().getValue(), node.getLeft(), nullifzeroFunc); } else { return formatBinaryExpression(node.getType().getValue(), node.getLeft(), node.getRight()); } } else { return formatBinaryExpression(node.getType().getValue(), node.getLeft(), node.getRight()); } }
public WindowFunctionSupplier getWindowFunctionImplementation(Signature signature) { checkArgument(signature.getKind() == WINDOW || signature.getKind() == AGGREGATE, "%s is not a window function", signature); checkArgument(signature.getTypeParameterRequirements().isEmpty(), "%s has unbound type parameters", signature); Iterable<SqlFunction> candidates = functions.get(QualifiedName.of(signature.getName())); // search for exact match for (SqlFunction operator : candidates) { Type returnType = typeManager.getType(signature.getReturnType()); List<Type> argumentTypes = resolveTypes(signature.getArgumentTypes(), typeManager); Map<String, Type> boundTypeParameters = operator.getSignature().bindTypeParameters(returnType, argumentTypes, false, typeManager); if (boundTypeParameters != null) { try { return specializedWindowCache.getUnchecked(new SpecializedFunctionKey(operator, boundTypeParameters, signature.getArgumentTypes().size())); } catch (UncheckedExecutionException e) { throw Throwables.propagate(e.getCause()); } } } throw new PrestoException(FUNCTION_IMPLEMENTATION_MISSING, format("%s not found", signature)); }
public InternalAggregationFunction getAggregateFunctionImplementation(Signature signature) { checkArgument(signature.getKind() == AGGREGATE || signature.getKind() == APPROXIMATE_AGGREGATE, "%s is not an aggregate function", signature); checkArgument(signature.getTypeParameterRequirements().isEmpty(), "%s has unbound type parameters", signature); Iterable<SqlFunction> candidates = functions.get(QualifiedName.of(signature.getName())); // search for exact match for (SqlFunction operator : candidates) { Type returnType = typeManager.getType(signature.getReturnType()); List<Type> argumentTypes = resolveTypes(signature.getArgumentTypes(), typeManager); Map<String, Type> boundTypeParameters = operator.getSignature().bindTypeParameters(returnType, argumentTypes, false, typeManager); if (boundTypeParameters != null) { try { return specializedAggregationCache.getUnchecked(new SpecializedFunctionKey(operator, boundTypeParameters, signature.getArgumentTypes().size())); } catch (UncheckedExecutionException e) { throw Throwables.propagate(e.getCause()); } } } throw new PrestoException(FUNCTION_IMPLEMENTATION_MISSING, format("%s not found", signature)); }
public Signature resolveOperator(OperatorType operatorType, List<? extends Type> argumentTypes) throws OperatorNotFoundException { try { return resolveFunction(QualifiedName.of(mangleOperatorName(operatorType)), Lists.transform(argumentTypes, Type::getTypeSignature), false); } catch (PrestoException e) { if (e.getErrorCode().getCode() == FUNCTION_NOT_FOUND.toErrorCode().getCode()) { throw new OperatorNotFoundException( operatorType, argumentTypes.stream() .map(Type::getTypeSignature) .collect(toImmutableList())); } else { throw e; } } }
public FunctionMap(FunctionMap map, Iterable<? extends SqlFunction> functions) { this.functions = ImmutableListMultimap.<QualifiedName, SqlFunction>builder() .putAll(map.functions) .putAll(Multimaps.index(functions, function -> QualifiedName.of(function.getSignature().getName()))) .build(); // Make sure all functions with the same name are aggregations or none of them are for (Map.Entry<QualifiedName, Collection<SqlFunction>> entry : this.functions.asMap().entrySet()) { Collection<SqlFunction> values = entry.getValue(); long aggregations = values.stream() .map(function -> function.getSignature().getKind()) .filter(kind -> kind == AGGREGATE || kind == APPROXIMATE_AGGREGATE) .count(); checkState(aggregations == 0 || aggregations == values.size(), "'%s' is both an aggregation and a scalar function", entry.getKey()); } }
@Override protected Object visitArrayConstructor(ArrayConstructor node, Object context) { Type elementType = ((ArrayType) expressionTypes.get(node)).getElementType(); BlockBuilder arrayBlockBuilder = elementType.createBlockBuilder(new BlockBuilderStatus(), node.getValues().size()); for (Expression expression : node.getValues()) { Object value = process(expression, context); if (value instanceof Expression) { return visitFunctionCall(new FunctionCall(QualifiedName.of(ArrayConstructor.ARRAY_CONSTRUCTOR), node.getValues()), context); } writeNativeValue(elementType, arrayBlockBuilder, value); } return arrayBlockBuilder.build(); }
@Override public Expression rewriteCurrentTime(CurrentTime node, Void context, ExpressionTreeRewriter<Void> treeRewriter) { if (node.getPrecision() != null) { throw new UnsupportedOperationException("not yet implemented: non-default precision"); } switch (node.getType()) { case DATE: return new FunctionCall(new QualifiedName("current_date"), ImmutableList.<Expression>of()); case TIME: return new FunctionCall(new QualifiedName("current_time"), ImmutableList.<Expression>of()); case LOCALTIME: return new FunctionCall(new QualifiedName("localtime"), ImmutableList.<Expression>of()); case TIMESTAMP: return new FunctionCall(new QualifiedName("current_timestamp"), ImmutableList.<Expression>of()); case LOCALTIMESTAMP: return new FunctionCall(new QualifiedName("localtimestamp"), ImmutableList.<Expression>of()); default: throw new UnsupportedOperationException("not yet implemented: " + node.getType()); } }
public static boolean isCountConstant(ProjectNode projectNode, FunctionCall functionCall, Signature signature) { if (!"count".equals(signature.getName()) || signature.getArgumentTypes().size() != 1 || !signature.getReturnType().getBase().equals(StandardTypes.BIGINT)) { return false; } Expression argument = functionCall.getArguments().get(0); if (argument instanceof Literal && !(argument instanceof NullLiteral)) { return true; } if (argument instanceof QualifiedNameReference) { QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) argument; QualifiedName qualifiedName = qualifiedNameReference.getName(); Symbol argumentSymbol = Symbol.fromQualifiedName(qualifiedName); Expression argumentExpression = projectNode.getAssignments().get(argumentSymbol); return (argumentExpression instanceof Literal) && (!(argumentExpression instanceof NullLiteral)); } return false; }
@Override public PlanNode visitSample(SampleNode node, RewriteContext<Void> context) { if (node.getSampleType() == SampleNode.Type.BERNOULLI) { PlanNode rewrittenSource = context.rewrite(node.getSource()); ComparisonExpression expression = new ComparisonExpression( ComparisonExpression.Type.LESS_THAN, new FunctionCall(QualifiedName.of("rand"), ImmutableList.<Expression>of()), new DoubleLiteral(Double.toString(node.getSampleRatio()))); return new FilterNode(node.getId(), rewrittenSource, expression); } else if (node.getSampleType() == SampleNode.Type.POISSONIZED || node.getSampleType() == SampleNode.Type.SYSTEM) { return context.defaultRewrite(node); } throw new UnsupportedOperationException("not yet implemented"); }
@Test public void testWith() throws Exception { assertStatement("WITH a (t, u) AS (SELECT * FROM x), b AS (SELECT * FROM y) TABLE z", new Query(Optional.of(new With(false, ImmutableList.of( new WithQuery("a", simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("x"))), ImmutableList.of("t", "u")), new WithQuery("b", simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("y"))), null)))), new Table(QualifiedName.of("z")), ImmutableList.of(), Optional.<String>empty(), Optional.<Approximate>empty())); assertStatement("WITH RECURSIVE a AS (SELECT * FROM x) TABLE y", new Query(Optional.of(new With(true, ImmutableList.of( new WithQuery("a", simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("x"))), null)))), new Table(QualifiedName.of("y")), ImmutableList.of(), Optional.<String>empty(), Optional.<Approximate>empty())); }
@Test public void testExplain() throws Exception { assertStatement("EXPLAIN SELECT * FROM t", new Explain(simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("t"))), ImmutableList.of())); assertStatement("EXPLAIN (TYPE LOGICAL) SELECT * FROM t", new Explain( simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("t"))), ImmutableList.of(new ExplainType(ExplainType.Type.LOGICAL)))); assertStatement("EXPLAIN (TYPE LOGICAL, FORMAT TEXT) SELECT * FROM t", new Explain( simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("t"))), ImmutableList.of( new ExplainType(ExplainType.Type.LOGICAL), new ExplainFormat(ExplainFormat.Type.TEXT)))); }
@Test public void testUnnest() throws Exception { assertStatement("SELECT * FROM t CROSS JOIN UNNEST(a)", simpleQuery( selectList(new AllColumns()), new Join( Join.Type.CROSS, new Table(QualifiedName.of("t")), new Unnest(ImmutableList.of(new QualifiedNameReference(QualifiedName.of("a"))), false), Optional.empty()))); assertStatement("SELECT * FROM t CROSS JOIN UNNEST(a) WITH ORDINALITY", simpleQuery( selectList(new AllColumns()), new Join( Join.Type.CROSS, new Table(QualifiedName.of("t")), new Unnest(ImmutableList.of(new QualifiedNameReference(QualifiedName.of("a"))), true), Optional.empty()))); }
private Relation render(List<ForeignKey> keys) { if (keys.isEmpty()) { return QueryUtil.table(new QualifiedName(baseTable)); } ForeignKey key = keys.get(0); if (keys.size() == 1) { return new Join(Join.Type.INNER, QueryUtil.table(new QualifiedName(key.getSourceTable())), QueryUtil.table(new QualifiedName(key.getDestinationTable())), Optional.of(new JoinOn(new ComparisonExpression( ComparisonExpression.Type.EQUAL, new QualifiedNameReference(QualifiedName.of( key.getSourceTable(), key.getSourceColumn())), new QualifiedNameReference(QualifiedName.of( key.getDestinationTable(), key.getDestinationColumn())))))); } return new Join(Join.Type.INNER, render(keys.subList(1, keys.size())), QueryUtil.table(new QualifiedName(key.getDestinationTable())), Optional.of(new JoinOn(new ComparisonExpression( ComparisonExpression.Type.EQUAL, new QualifiedNameReference(QualifiedName.of( key.getSourceTable(), key.getSourceColumn())), new QualifiedNameReference(QualifiedName.of( key.getDestinationTable(), key.getDestinationColumn())))))); }
private Table qualifiedNameToTable(QualifiedName name, CatalogSchemaContext context) { List<String> nameParts = name.getParts(); String connectorId = context.getCatalog(); String schema = context.getSchema(); String table = null; if (nameParts.size() == 3) { connectorId = nameParts.get(0); schema = nameParts.get(1); table = nameParts.get(2); } else if (nameParts.size() == 2) { schema = nameParts.get(0); table = nameParts.get(1); } else if (nameParts.size() == 1) { table = nameParts.get(0); } return new Table(connectorId, schema, table); }
protected static String processFuncQuarter(Formatter formatter, FunctionCall node) { FunctionCall month = new FunctionCall(new QualifiedName("month"), node.getArguments()); ArithmeticExpression substract = new ArithmeticExpression(ArithmeticExpression.Type.SUBTRACT, month, new LongLiteral("1")); ArithmeticExpression divide = new ArithmeticExpression(ArithmeticExpression.Type.DIVIDE, substract, new LongLiteral("3")); FunctionCall floor = new FunctionCall(new QualifiedName("floor"), Arrays.asList(divide)); ArithmeticExpression add = new ArithmeticExpression(ArithmeticExpression.Type.ADD, floor, new LongLiteral("1")); return formatter.process(add, null); }
protected static String processFuncSinh(Formatter formatter, FunctionCall node) { NegativeExpression negExp = new NegativeExpression(node.getArguments().get(0)); FunctionCall termA = new FunctionCall(new QualifiedName("exp"), node.getArguments()); FunctionCall termB = new FunctionCall(new QualifiedName("exp"), Arrays.asList(negExp)); ArithmeticExpression substract = new ArithmeticExpression(ArithmeticExpression.Type.SUBTRACT, termA, termB); ArithmeticExpression divide = new ArithmeticExpression(ArithmeticExpression.Type.DIVIDE, substract, new LongLiteral("2")); return formatter.process(divide, null); }
protected static String processFuncCosh(Formatter formatter, FunctionCall node) { NegativeExpression negExp = new NegativeExpression(node.getArguments().get(0)); FunctionCall termA = new FunctionCall(new QualifiedName("exp"), node.getArguments()); FunctionCall termB = new FunctionCall(new QualifiedName("exp"), Arrays.asList(negExp)); ArithmeticExpression add = new ArithmeticExpression(ArithmeticExpression.Type.ADD, termA, termB); ArithmeticExpression divide = new ArithmeticExpression(ArithmeticExpression.Type.DIVIDE, add, new LongLiteral("2")); return formatter.process(divide, null); }
protected static String processFuncTanh(Formatter formatter, FunctionCall node, DBType dbType) { /* * if (dbType == DBType.ACCESS) { // 20150803: ToDo Access doesn't like * using iif() to guard against division by 0 so I can only write plain * formula StringBuilder builder = new StringBuilder(); * builder.append("((exp(") * .append(formatter.process(node.getArguments().get(0), * null)).append(")") .append(" - ") .append("exp(-(") * .append(formatter.process(node.getArguments().get(0), * null)).append(")") .append("))") .append(" / ") .append("((exp(") * .append(formatter.process(node.getArguments().get(0), * null)).append(")") .append(" + ") .append("exp(-(") * .append(formatter.process(node.getArguments().get(0), * null)).append(")") .append("))))"); return builder.toString(); } else * { NegativeExpression negExp = new * NegativeExpression(node.getArguments().get(0)); FunctionCall termA = * new FunctionCall(new QualifiedName("exp"), node.getArguments()); * FunctionCall termB = new FunctionCall(new QualifiedName("exp"), * Arrays.asList(negExp)); ArithmeticExpression subtract = new * ArithmeticExpression(ArithmeticExpression.Type.SUBTRACT, termA, * termB); ArithmeticExpression add = new * ArithmeticExpression(ArithmeticExpression.Type.ADD, termA, termB); * ArithmeticExpression divide = new * ArithmeticExpression(ArithmeticExpression.Type.DIVIDE, subtract, * add); return formatter.process(divide, null); } */ NegativeExpression negExp = new NegativeExpression(node.getArguments().get(0)); FunctionCall termA = new FunctionCall(new QualifiedName("exp"), node.getArguments()); FunctionCall termB = new FunctionCall(new QualifiedName("exp"), Arrays.asList(negExp)); ArithmeticExpression subtract = new ArithmeticExpression(ArithmeticExpression.Type.SUBTRACT, termA, termB); ArithmeticExpression add = new ArithmeticExpression(ArithmeticExpression.Type.ADD, termA, termB); ArithmeticExpression divide = new ArithmeticExpression(ArithmeticExpression.Type.DIVIDE, subtract, add); return formatter.process(divide, null); }
protected static String processFuncAsin(Formatter formatter, FunctionCall node, DBType dbType) { /* * if (dbType == DBType.ACCESS) { // 20150803: ToDo Access doesn't like * using iif() to guard against division by 0 so I can only write plain * formula StringBuilder builder = new StringBuilder(); * builder.append("atan(") * .append(formatter.process(node.getArguments().get(0), null)) * .append(" / ") * .append("sqrt(1-power(").append(formatter.process(node.getArguments() * .get(0), null)).append(", 2))") .append(')'); return * builder.toString(); } else { FunctionCall xx = new FunctionCall(new * QualifiedName("power"), Arrays.asList(node.getArguments().get(0), new * LongLiteral("2"))); ArithmeticExpression subtract = new * ArithmeticExpression(ArithmeticExpression.Type.SUBTRACT, new * LongLiteral("1"), xx); FunctionCall sqrt = new FunctionCall(new * QualifiedName("sqrt"), Arrays.asList(subtract)); ArithmeticExpression * divide = new ArithmeticExpression(ArithmeticExpression.Type.DIVIDE, * node.getArguments().get(0), sqrt); FunctionCall atan = new * FunctionCall(new QualifiedName("atan"), Arrays.asList(divide)); * return formatter.process(atan, null); } */ FunctionCall xx = new FunctionCall(new QualifiedName("power"), Arrays.asList(node.getArguments().get(0), new LongLiteral("2"))); ArithmeticExpression subtract = new ArithmeticExpression(ArithmeticExpression.Type.SUBTRACT, new LongLiteral("1"), xx); FunctionCall sqrt = new FunctionCall(new QualifiedName("sqrt"), Arrays.asList(subtract)); ArithmeticExpression divide = new ArithmeticExpression(ArithmeticExpression.Type.DIVIDE, node.getArguments().get( 0), sqrt); FunctionCall atan = new FunctionCall(new QualifiedName("atan"), Arrays.asList(divide)); return formatter.process(atan, null); }
protected static String processFuncAsinh(Formatter formatter, FunctionCall node) { ArithmeticExpression zSquare = new ArithmeticExpression(ArithmeticExpression.Type.MULTIPLY, node.getArguments().get( 0), node.getArguments().get(0)); ArithmeticExpression zSquareAddOne = new ArithmeticExpression(ArithmeticExpression.Type.ADD, zSquare, new LongLiteral("1")); FunctionCall sqrt = new FunctionCall(new QualifiedName("sqrt"), Arrays.asList(zSquareAddOne)); ArithmeticExpression zAddSqrt = new ArithmeticExpression(ArithmeticExpression.Type.ADD, node.getArguments().get( 0), sqrt); FunctionCall ln = new FunctionCall(new QualifiedName("ln"), Arrays.asList(zAddSqrt)); return formatter.process(ln, null); }
protected static String processFuncAcosh(Formatter formatter, FunctionCall node) { ArithmeticExpression zAddOne = new ArithmeticExpression(ArithmeticExpression.Type.ADD, node.getArguments().get( 0), new LongLiteral("1")); FunctionCall sqrtZAddOne = new FunctionCall(new QualifiedName("sqrt"), Arrays.asList(zAddOne)); ArithmeticExpression zSubOne = new ArithmeticExpression(ArithmeticExpression.Type.SUBTRACT, node.getArguments().get( 0), new LongLiteral("1")); FunctionCall sqrtZSubOne = new FunctionCall(new QualifiedName("sqrt"), Arrays.asList(zSubOne)); ArithmeticExpression sqrtMultiply = new ArithmeticExpression(ArithmeticExpression.Type.MULTIPLY, sqrtZAddOne, sqrtZSubOne); ArithmeticExpression zAddSqrtMultiply = new ArithmeticExpression(ArithmeticExpression.Type.ADD, node.getArguments().get( 0), sqrtMultiply); FunctionCall ln = new FunctionCall(new QualifiedName("ln"), Arrays.asList(zAddSqrtMultiply)); return formatter.process(ln, null); }
protected static String processFuncAtanh(Formatter formatter, FunctionCall node) { ArithmeticExpression oneAddZ = new ArithmeticExpression(ArithmeticExpression.Type.ADD, new LongLiteral("1"), node.getArguments().get( 0)); ArithmeticExpression oneSubZ = new ArithmeticExpression(ArithmeticExpression.Type.SUBTRACT, new LongLiteral("1"), node.getArguments().get( 0)); ArithmeticExpression divide = new ArithmeticExpression(ArithmeticExpression.Type.DIVIDE, oneAddZ, oneSubZ); FunctionCall ln = new FunctionCall(new QualifiedName("ln"), Arrays.asList(divide)); ArithmeticExpression multiply = new ArithmeticExpression(ArithmeticExpression.Type.MULTIPLY, new DoubleLiteral("0.5"), ln); return formatter.process(multiply, null); }
protected static String processFuncPower(Formatter formatter, FunctionCall node) { FunctionCall ln = new FunctionCall(new QualifiedName("ln"), Arrays.asList(node.getArguments().get(0))); ArithmeticExpression multiply = new ArithmeticExpression(ArithmeticExpression.Type.MULTIPLY, node.getArguments().get( 1), ln); FunctionCall exp = new FunctionCall(new QualifiedName("exp"), Arrays.asList(multiply)); return formatter.process(exp, null); }
protected static String processFuncAtan2(Formatter formatter, FunctionCall node) { Expression x = node.getArguments().get(0); Expression y = node.getArguments().get(1); FunctionCall xx = new FunctionCall(new QualifiedName("power"), Arrays.asList(x, new LongLiteral("2"))); FunctionCall yy = new FunctionCall(new QualifiedName("power"), Arrays.asList(y, new LongLiteral("2"))); ArithmeticExpression xxAddyy = new ArithmeticExpression(ArithmeticExpression.Type.ADD, xx, yy); FunctionCall sqrt_xxAddyy = new FunctionCall(new QualifiedName("sqrt"), Arrays.asList(xxAddyy)); ArithmeticExpression substract = new ArithmeticExpression(ArithmeticExpression.Type.SUBTRACT, sqrt_xxAddyy, x); ArithmeticExpression divide = new ArithmeticExpression(ArithmeticExpression.Type.DIVIDE, substract, y); FunctionCall arctan = new FunctionCall(new QualifiedName("atan"), Arrays.asList(divide)); ArithmeticExpression multiply = new ArithmeticExpression(ArithmeticExpression.Type.MULTIPLY, new DoubleLiteral("2"), arctan); return formatter.process(multiply, null); }
private String formatQualifiedName(QualifiedName name) { List<String> parts = new ArrayList<>(); for (String part : name.getParts()) { parts.add(formatIdentifier(sqlFormatter.caseSensitivityName(part))); } return Joiner.on('.').join(parts); }
protected String formatQualifiedFunctionName(QualifiedName name) { List<String> parts = new ArrayList<>(); for (String part : name.getParts()) { parts.add(sqlFormatter.caseSensitivityName(part)); } return Joiner.on('.').join(parts); }
private static String formatQualifiedName(QualifiedName name) { List<String> parts = new ArrayList<>(); for (String part : name.getParts()) { parts.add(formatIdentifier(part)); } return Joiner.on('.').join(parts); }
@Override public CompletableFuture<?> execute(SetSession statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine) { Session session = stateMachine.getSession(); QualifiedName propertyName = statement.getName(); if (propertyName.getParts().size() > 2) { throw new SemanticException(INVALID_SESSION_PROPERTY, statement, "Invalid session property '%s'", propertyName); } PropertyMetadata<?> propertyMetadata = metadata.getSessionPropertyManager().getSessionPropertyMetadata(propertyName.toString()); if (propertyName.getParts().size() == 1) { accessControl.checkCanSetSystemSessionProperty(session.getIdentity(), propertyName.getParts().get(0)); } else if (propertyName.getParts().size() == 2) { accessControl.checkCanSetCatalogSessionProperty(session.getIdentity(), propertyName.getParts().get(0), propertyName.getParts().get(1)); } Type type = propertyMetadata.getSqlType(); Object objectValue; try { objectValue = evaluatePropertyValue(statement.getValue(), type, session, metadata); } catch (SemanticException e) { throw new PrestoException(StandardErrorCode.INVALID_SESSION_PROPERTY, format("Unable to set session property '%s' to '%s': %s", propertyName, statement.getValue(), e.getMessage())); } String value = serializeSessionProperty(type, objectValue); // verify the SQL value can be decoded by the property metadata.getSessionPropertyManager().decodeProperty(propertyName.toString(), value, propertyMetadata.getJavaType()); stateMachine.addSetSessionProperties(propertyName.toString(), value); return completedFuture(null); }
public static QualifiedObjectName createQualifiedObjectName(Session session, Node node, QualifiedName name) { requireNonNull(session, "session is null"); requireNonNull(name, "name is null"); checkArgument(name.getParts().size() <= 3, "Too many dots in table name: %s", name); List<String> parts = Lists.reverse(name.getParts()); String objectName = parts.get(0); String schemaName = (parts.size() > 1) ? parts.get(1) : session.getSchema().orElseThrow(() -> new SemanticException(CATALOG_NOT_SPECIFIED, node, "Catalog must be specified when session catalog is not set")); String catalogName = (parts.size() > 2) ? parts.get(2) : session.getCatalog().orElseThrow(() -> new SemanticException(SCHEMA_NOT_SPECIFIED, node, "Schema must be specified when session schema is not set")); return new QualifiedObjectName(catalogName, schemaName, objectName); }
@Override protected Void visitFunctionCall(FunctionCall node, AtomicBoolean deterministic) { // TODO: total hack to figure out if a function is deterministic. martint should fix this when he refactors the planning code if (node.getName().equals(new QualifiedName("rand")) || node.getName().equals(new QualifiedName("random"))) { deterministic.set(false); } return super.visitFunctionCall(node, deterministic); }
@VisibleForTesting @NotNull public static Expression createFailureFunction(RuntimeException exception, Type type) { requireNonNull(exception, "Exception is null"); String failureInfo = JsonCodec.jsonCodec(FailureInfo.class).toJson(Failures.toFailure(exception).toFailureInfo()); FunctionCall jsonParse = new FunctionCall(QualifiedName.of("json_parse"), ImmutableList.of(new StringLiteral(failureInfo))); FunctionCall failureFunction = new FunctionCall(QualifiedName.of("fail"), ImmutableList.of(jsonParse)); return new Cast(failureFunction, type.getTypeSignature().toString()); }
@Override public Expression rewriteExtract(Extract node, Void context, ExpressionTreeRewriter<Void> treeRewriter) { Expression value = treeRewriter.rewrite(node.getExpression(), context); switch (node.getField()) { case YEAR: return new FunctionCall(new QualifiedName("year"), ImmutableList.of(value)); case QUARTER: return new FunctionCall(new QualifiedName("quarter"), ImmutableList.of(value)); case MONTH: return new FunctionCall(new QualifiedName("month"), ImmutableList.of(value)); case WEEK: return new FunctionCall(new QualifiedName("week"), ImmutableList.of(value)); case DAY: case DAY_OF_MONTH: return new FunctionCall(new QualifiedName("day"), ImmutableList.of(value)); case DAY_OF_WEEK: case DOW: return new FunctionCall(new QualifiedName("day_of_week"), ImmutableList.of(value)); case DAY_OF_YEAR: case DOY: return new FunctionCall(new QualifiedName("day_of_year"), ImmutableList.of(value)); case YEAR_OF_WEEK: case YOW: return new FunctionCall(new QualifiedName("year_of_week"), ImmutableList.of(value)); case HOUR: return new FunctionCall(new QualifiedName("hour"), ImmutableList.of(value)); case MINUTE: return new FunctionCall(new QualifiedName("minute"), ImmutableList.of(value)); case SECOND: return new FunctionCall(new QualifiedName("second"), ImmutableList.of(value)); case TIMEZONE_MINUTE: return new FunctionCall(new QualifiedName("timezone_minute"), ImmutableList.of(value)); case TIMEZONE_HOUR: return new FunctionCall(new QualifiedName("timezone_hour"), ImmutableList.of(value)); } throw new UnsupportedOperationException("not yet implemented: " + node.getField()); }
@Override protected Void visitDereferenceExpression(DereferenceExpression node, ImmutableSet.Builder<QualifiedName> builder) { if (columnReferences.contains(node)) { builder.add(DereferenceExpression.getQualifiedName(node)); } else { process(node.getBase(), builder); } return null; }
/** * Returns all unique relations in this tuple. * For detecting duplicate relations in a Join. */ public Set<QualifiedName> getRelationAliases() { return allFields.stream() .map(Field::getRelationAlias) .filter(Optional::isPresent) .map(Optional::get) .collect(toImmutableSet()); }
/** * This method is used for SELECT * or x.* queries */ public List<Field> resolveFieldsWithPrefix(Optional<QualifiedName> prefix) { return visibleFields.stream() .filter(input -> input.matchesPrefix(prefix)) .collect(toImmutableList()); }
/** * Gets the index of all columns matching the specified name */ public List<Field> resolveFields(QualifiedName name) { return allFields.stream() .filter(input -> input.canResolve(name)) .collect(toImmutableList()); }
/** * Creates a new tuple descriptor with the relation, and, optionally, the columns aliased. */ public RelationType withAlias(String relationAlias, List<String> columnAliases) { if (columnAliases != null) { checkArgument(columnAliases.size() == visibleFields.size(), "Column alias list has %s entries but '%s' has %s columns available", columnAliases.size(), relationAlias, visibleFields.size()); } ImmutableList.Builder<Field> fieldsBuilder = ImmutableList.builder(); for (int i = 0; i < allFields.size(); i++) { Field field = allFields.get(i); Optional<String> columnAlias = field.getName(); if (columnAliases == null) { fieldsBuilder.add(Field.newQualified(QualifiedName.of(relationAlias), columnAlias, field.getType(), field.isHidden())); } else if (!field.isHidden()) { // hidden fields are not exposed when there are column aliases columnAlias = Optional.of(columnAliases.get(i)); fieldsBuilder.add(Field.newQualified(QualifiedName.of(relationAlias), columnAlias, field.getType(), false)); } } return new RelationType(fieldsBuilder.build()); }
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)); }
public static Field newQualified(QualifiedName relationAlias, Optional<String> name, Type type, boolean hidden) { requireNonNull(relationAlias, "relationAlias is null"); requireNonNull(name, "name is null"); requireNonNull(type, "type is null"); return new Field(Optional.of(relationAlias), name, type, hidden); }
public Field(Optional<QualifiedName> relationAlias, Optional<String> name, Type type, boolean hidden) { requireNonNull(relationAlias, "relationAlias is null"); requireNonNull(name, "name is null"); requireNonNull(type, "type is null"); this.relationAlias = relationAlias; this.name = name; this.type = type; this.hidden = hidden; }