@Test public void testArraySubscript() throws Exception { assertExpression("ARRAY [1, 2][1]", new SubscriptExpression( new ArrayConstructor(ImmutableList.<Expression>of(new LongLiteral("1"), new LongLiteral("2"))), new LongLiteral("1")) ); try { assertExpression("CASE WHEN TRUE THEN ARRAY[1,2] END[1]", null); fail(); } catch (RuntimeException e) { // Expected } }
@Test public void testLimitAll() { Query valuesQuery = query(values( row(new LongLiteral("1"), new StringLiteral("1")), row(new LongLiteral("2"), new StringLiteral("2")))); assertStatement("SELECT * FROM (VALUES (1, '1'), (2, '2')) LIMIT ALL", simpleQuery(selectList(new AllColumns()), subquery(valuesQuery), Optional.empty(), ImmutableList.of(), Optional.empty(), ImmutableList.of(), Optional.of("ALL"))); }
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 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 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); }
protected static String processFuncNullifzero(Formatter formatter, FunctionCall node) { Expression x = node.getArguments().get(0); List<WhenClause> listWhen = new ArrayList<WhenClause>(); ComparisonExpression ce = new ComparisonExpression(ComparisonExpression.Type.EQUAL, x, new LongLiteral("0")); WhenClause wc = new WhenClause(ce, new NullLiteral()); listWhen.add(wc); SearchedCaseExpression sce = new SearchedCaseExpression(listWhen, x); return formatter.process(sce, null); }
/** * Extracts the literal value from an expression (if expression is supported) * @param expression * @param state * @return a Long, Boolean, Double or String object */ private Object getLiteralValue(Expression expression, QueryState state){ if(expression instanceof LongLiteral) return ((LongLiteral)expression).getValue(); else if(expression instanceof BooleanLiteral) return ((BooleanLiteral)expression).getValue(); else if(expression instanceof DoubleLiteral) return ((DoubleLiteral)expression).getValue(); else if(expression instanceof StringLiteral) return ((StringLiteral)expression).getValue(); else if(expression instanceof ArithmeticUnaryExpression){ ArithmeticUnaryExpression unaryExp = (ArithmeticUnaryExpression)expression; Sign sign = unaryExp.getSign(); Number num = (Number)getLiteralValue(unaryExp.getValue(), state); if(sign == Sign.MINUS){ if(num instanceof Long) return -1*num.longValue(); else if(num instanceof Double) return -1*num.doubleValue(); else { state.addException("Unsupported numeric literal expression encountered : "+num.getClass()); return null; } } return num; } else if(expression instanceof FunctionCall){ FunctionCall fc = (FunctionCall)expression; if(fc.getName().toString().equals("now")) return new Date(); else state.addException("Function '"+fc.getName()+"' is not supported"); }else if(expression instanceof CurrentTime){ CurrentTime ct = (CurrentTime)expression; if(ct.getType() == CurrentTime.Type.DATE) return new LocalDate().toDate(); else if(ct.getType() == CurrentTime.Type.TIME) return new Date(new LocalTime(DateTimeZone.UTC).getMillisOfDay()); else if(ct.getType() == CurrentTime.Type.TIMESTAMP) return new Date(); else if(ct.getType() == CurrentTime.Type.LOCALTIME) return new Date(new LocalTime(DateTimeZone.UTC).getMillisOfDay()); else if(ct.getType() == CurrentTime.Type.LOCALTIMESTAMP) return new Date(); else state.addException("CurrentTime function '"+ct.getType()+"' is not supported"); }else state.addException("Literal type "+expression.getClass().getSimpleName()+" is not supported"); return null; }
private Object getObject(Literal literal){ Object value = null; if(literal instanceof LongLiteral) value = ((LongLiteral)literal).getValue(); else if(literal instanceof BooleanLiteral) value = ((BooleanLiteral)literal).getValue(); else if(literal instanceof DoubleLiteral) value = ((DoubleLiteral)literal).getValue(); else if(literal instanceof StringLiteral) value = ((StringLiteral)literal).getValue(); else if(literal instanceof TimeLiteral) value = ((TimeLiteral)literal).getValue(); else if(literal instanceof TimestampLiteral) value = ((TimestampLiteral)literal).getValue(); return value; }
private Object getLiteralValue(Expression expression) throws SQLException{ if(expression instanceof LongLiteral) return ((LongLiteral)expression).getValue(); else if(expression instanceof BooleanLiteral) return ((BooleanLiteral)expression).getValue(); else if(expression instanceof DoubleLiteral) return ((DoubleLiteral)expression).getValue(); else if(expression instanceof StringLiteral) return ((StringLiteral)expression).getValue(); throw new SQLException("Unsupported literal type: "+expression); }
private static Expression oneIfNull(Optional<Symbol> symbol) { if (symbol.isPresent()) { return new CoalesceExpression(new QualifiedNameReference(symbol.get().toQualifiedName()), new LongLiteral("1")); } else { return new LongLiteral("1"); } }
private RelationPlan addConstantSampleWeight(RelationPlan subPlan) { ImmutableMap.Builder<Symbol, Expression> projections = ImmutableMap.builder(); for (Symbol symbol : subPlan.getOutputSymbols()) { Expression expression = new QualifiedNameReference(symbol.toQualifiedName()); projections.put(symbol, expression); } Expression one = new LongLiteral("1"); Symbol sampleWeightSymbol = symbolAllocator.newSymbol("$sampleWeight", BIGINT); projections.put(sampleWeightSymbol, one); ProjectNode projectNode = new ProjectNode(idAllocator.getNextId(), subPlan.getRoot(), projections.build()); return new RelationPlan(projectNode, subPlan.getDescriptor(), projectNode.getOutputSymbols(), Optional.of(sampleWeightSymbol)); }
private static Expression getHashExpression(List<Symbol> partitioningSymbols) { Expression hashExpression = new LongLiteral(String.valueOf(INITIAL_HASH_VALUE)); for (Symbol symbol : partitioningSymbols) { hashExpression = getHashFunctionCall(hashExpression, symbol); } return hashExpression; }
private List<FieldOrExpression> analyzeGroupingColumns(List<Expression> groupingColumns, QuerySpecification node, RelationType tupleDescriptor, AnalysisContext context, List<FieldOrExpression> outputExpressions) { ImmutableList.Builder<FieldOrExpression> groupingColumnsBuilder = ImmutableList.builder(); for (Expression groupingColumn : groupingColumns) { // first, see if this is an ordinal FieldOrExpression groupByExpression; if (groupingColumn instanceof LongLiteral) { long ordinal = ((LongLiteral) groupingColumn).getValue(); if (ordinal < 1 || ordinal > outputExpressions.size()) { throw new SemanticException(INVALID_ORDINAL, groupingColumn, "GROUP BY position %s is not in select list", ordinal); } groupByExpression = outputExpressions.get((int) (ordinal - 1)); } else { ExpressionAnalysis expressionAnalysis = analyzeExpression(groupingColumn, tupleDescriptor, context); analysis.recordSubqueries(node, expressionAnalysis); groupByExpression = new FieldOrExpression(groupingColumn); } Type type; if (groupByExpression.isExpression()) { Analyzer.verifyNoAggregatesOrWindowFunctions(metadata, groupByExpression.getExpression(), "GROUP BY"); type = analysis.getType(groupByExpression.getExpression()); } else { type = tupleDescriptor.getFieldByIndex(groupByExpression.getFieldIndex()).getType(); } if (!type.isComparable()) { throw new SemanticException(TYPE_MISMATCH, node, "%s is not comparable, and therefore cannot be used in GROUP BY", type); } groupingColumnsBuilder.add(groupByExpression); } return groupingColumnsBuilder.build(); }
@Test public void testArrayConstructor() throws Exception { assertExpression("ARRAY []", new ArrayConstructor(ImmutableList.<Expression>of())); assertExpression("ARRAY [1, 2]", new ArrayConstructor(ImmutableList.<Expression>of(new LongLiteral("1"), new LongLiteral("2")))); assertExpression("ARRAY [1.0, 2.5]", new ArrayConstructor(ImmutableList.<Expression>of(new DoubleLiteral("1.0"), new DoubleLiteral("2.5")))); assertExpression("ARRAY ['hi']", new ArrayConstructor(ImmutableList.<Expression>of(new StringLiteral("hi")))); assertExpression("ARRAY ['hi', 'hello']", new ArrayConstructor(ImmutableList.<Expression>of(new StringLiteral("hi"), new StringLiteral("hello")))); }
@Test public void testArithmeticUnary() { assertExpression("9", new LongLiteral("9")); assertExpression("+9", positive(new LongLiteral("9"))); assertExpression("+ 9", positive(new LongLiteral("9"))); assertExpression("++9", positive(positive(new LongLiteral("9")))); assertExpression("+ +9", positive(positive(new LongLiteral("9")))); assertExpression("+ + 9", positive(positive(new LongLiteral("9")))); assertExpression("+++9", positive(positive(positive(new LongLiteral("9"))))); assertExpression("+ + +9", positive(positive(positive(new LongLiteral("9"))))); assertExpression("+ + + 9", positive(positive(positive(new LongLiteral("9"))))); assertExpression("-9", negative(new LongLiteral("9"))); assertExpression("- 9", negative(new LongLiteral("9"))); assertExpression("- + 9", negative(positive(new LongLiteral("9")))); assertExpression("-+9", negative(positive(new LongLiteral("9")))); assertExpression("+ - + 9", positive(negative(positive(new LongLiteral("9"))))); assertExpression("+-+9", positive(negative(positive(new LongLiteral("9"))))); assertExpression("- -9", negative(negative(new LongLiteral("9")))); assertExpression("- - 9", negative(negative(new LongLiteral("9")))); assertExpression("- + - + 9", negative(positive(negative(positive(new LongLiteral("9")))))); assertExpression("-+-+9", negative(positive(negative(positive(new LongLiteral("9")))))); assertExpression("+ - + - + 9", positive(negative(positive(negative(positive(new LongLiteral("9"))))))); assertExpression("+-+-+9", positive(negative(positive(negative(positive(new LongLiteral("9"))))))); assertExpression("- - -9", negative(negative(negative(new LongLiteral("9"))))); assertExpression("- - - 9", negative(negative(negative(new LongLiteral("9"))))); }
private static QuerySpecification createSelect123() { return new QuerySpecification( selectList(new LongLiteral("123")), Optional.empty(), Optional.empty(), ImmutableList.of(), Optional.empty(), ImmutableList.of(), Optional.empty() ); }
@Test public void testBetween() throws Exception { assertExpression("1 BETWEEN 2 AND 3", new BetweenPredicate(new LongLiteral("1"), new LongLiteral("2"), new LongLiteral("3"))); assertExpression("1 NOT BETWEEN 2 AND 3", new NotExpression(new BetweenPredicate(new LongLiteral("1"), new LongLiteral("2"), new LongLiteral("3")))); }
@Test public void testValues() { Query valuesQuery = query(values( row(new StringLiteral("a"), new LongLiteral("1"), new DoubleLiteral("2.2")), row(new StringLiteral("b"), new LongLiteral("2"), new DoubleLiteral("3.3")))); assertStatement("VALUES ('a', 1, 2.2), ('b', 2, 3.3)", valuesQuery); assertStatement("SELECT * FROM (VALUES ('a', 1, 2.2), ('b', 2, 3.3))", simpleQuery( selectList(new AllColumns()), subquery(valuesQuery))); }
@Test public void testShowPartitions() { assertStatement("SHOW PARTITIONS FROM t", new ShowPartitions(QualifiedName.of("t"), Optional.empty(), ImmutableList.of(), Optional.empty())); assertStatement("SHOW PARTITIONS FROM t WHERE x = 1", new ShowPartitions( QualifiedName.of("t"), Optional.of(new ComparisonExpression(ComparisonExpression.Type.EQUAL, new QualifiedNameReference(QualifiedName.of("x")), new LongLiteral("1"))), ImmutableList.of(), Optional.empty())); assertStatement("SHOW PARTITIONS FROM t WHERE x = 1 ORDER BY y", new ShowPartitions( QualifiedName.of("t"), Optional.of(new ComparisonExpression(ComparisonExpression.Type.EQUAL, new QualifiedNameReference(QualifiedName.of("x")), new LongLiteral("1"))), ImmutableList.of(new SortItem(new QualifiedNameReference(QualifiedName.of("y")), SortItem.Ordering.ASCENDING, SortItem.NullOrdering.UNDEFINED)), Optional.empty())); assertStatement("SHOW PARTITIONS FROM t WHERE x = 1 ORDER BY y LIMIT 10", new ShowPartitions( QualifiedName.of("t"), Optional.of(new ComparisonExpression(ComparisonExpression.Type.EQUAL, new QualifiedNameReference(QualifiedName.of("x")), new LongLiteral("1"))), ImmutableList.of(new SortItem(new QualifiedNameReference(QualifiedName.of("y")), SortItem.Ordering.ASCENDING, SortItem.NullOrdering.UNDEFINED)), Optional.of("10"))); assertStatement("SHOW PARTITIONS FROM t WHERE x = 1 ORDER BY y LIMIT ALL", new ShowPartitions( QualifiedName.of("t"), Optional.of(new ComparisonExpression(ComparisonExpression.Type.EQUAL, new QualifiedNameReference(QualifiedName.of("x")), new LongLiteral("1"))), ImmutableList.of(new SortItem(new QualifiedNameReference(QualifiedName.of("y")), SortItem.Ordering.ASCENDING, SortItem.NullOrdering.UNDEFINED)), Optional.of("ALL"))); }
@Test public void testCall() throws Exception { assertStatement("CALL foo()", new Call(QualifiedName.of("foo"), ImmutableList.of())); assertStatement("CALL foo(123, a => 1, b => 'go', 456)", new Call(QualifiedName.of("foo"), ImmutableList.of( new CallArgument(new LongLiteral("123")), new CallArgument("a", new LongLiteral("1")), new CallArgument("b", new StringLiteral("go")), new CallArgument(new LongLiteral("456"))))); }
@Override protected String visitLongLiteral(LongLiteral node, Void context) { return Long.toString(node.getValue()); }
@Override protected String visitLongLiteral(LongLiteral node, StackableAstVisitorContext<Integer> indent) { return Long.toString(node.getValue()); }
@Override protected IComparison visitExpression(Expression node, QueryState state) { if( node instanceof LogicalBinaryExpression){ LogicalBinaryExpression boolExp = (LogicalBinaryExpression)node; IComparison left = boolExp.getLeft().accept(this, state); IComparison right = boolExp.getRight().accept(this, state); return new BooleanComparison(left, right, boolExp.getType() == Type.AND); }else if( node instanceof ComparisonExpression){ ComparisonExpression compareExp = (ComparisonExpression)node; Column column = new SelectParser().visitExpression(compareExp.getLeft(), state); Column leftCol = state.getHeading().getColumnByLabel(column.getLabel()); if(leftCol == null){ state.addException("Having reference "+column+" not found in SELECT clause"); return null; } // right hand side is a concrete literal to compare with if(compareExp.getRight() instanceof Literal){ Object value; if(compareExp.getRight() instanceof LongLiteral) value = ((LongLiteral)compareExp.getRight()).getValue(); else if(compareExp.getRight() instanceof BooleanLiteral) value = ((BooleanLiteral)compareExp.getRight()).getValue(); else if(compareExp.getRight() instanceof DoubleLiteral) value = ((DoubleLiteral)compareExp.getRight()).getValue(); else if(compareExp.getRight() instanceof StringLiteral) value = ((StringLiteral)compareExp.getRight()).getValue(); else { state.addException("Unable to get value from "+compareExp.getRight()); return null; } return new SimpleComparison(leftCol, compareExp.getType(), (Number)value); // right hand side refers to another column } else if(compareExp.getRight() instanceof DereferenceExpression || compareExp.getRight() instanceof QualifiedNameReference){ String col2; if(compareExp.getLeft() instanceof DereferenceExpression){ // parse columns like 'reference.field' col2 = SelectParser.visitDereferenceExpression((DereferenceExpression)compareExp.getRight()); }else{ col2 = ((QualifiedNameReference)compareExp.getRight()).getName().toString(); } col2 = Heading.findOriginal(state.originalSql(), col2, "having.+", "\\W"); Column rightCol = state.getHeading().getColumnByLabel(col2); if(rightCol == null){ state.addException("column "+col2+" not found in SELECT clause"); return null; } return new SimpleComparison(leftCol, compareExp.getType(), rightCol); }else { // unknown right hand side so state.addException("Unable to get value from "+compareExp.getRight()); return null; } }else if( node instanceof NotExpression){ state.addException("NOT is currently not supported, use '<>' instead"); }else{ state.addException("Unable to parse "+node+" ("+node.getClass().getName()+") is not a supported expression"); } return null; }
@Override protected RowExpression visitLongLiteral(LongLiteral node, Void context) { return constant(node.getValue(), BIGINT); }
@Override protected Long visitLongLiteral(LongLiteral node, ConnectorSession session) { return node.getValue(); }
private static Expression orNullHashCode(Expression expression) { return new CoalesceExpression(expression, new LongLiteral(String.valueOf(TypeUtils.NULL_HASH_CODE))); }
private static Expression coerceDoubleToLongComparison(NormalizedSimpleComparison normalized) { checkArgument(normalized.getValue().getType().equals(DOUBLE), "Value should be of DOUBLE type"); checkArgument(!normalized.getValue().isNull(), "Value should not be null"); QualifiedNameReference reference = normalized.getNameReference(); Double value = (Double) normalized.getValue().getValue(); switch (normalized.getComparisonType()) { case GREATER_THAN_OR_EQUAL: case LESS_THAN: return new ComparisonExpression(normalized.getComparisonType(), reference, toExpression(DoubleMath.roundToLong(value, CEILING), BIGINT)); case GREATER_THAN: case LESS_THAN_OR_EQUAL: return new ComparisonExpression(normalized.getComparisonType(), reference, toExpression(DoubleMath.roundToLong(value, FLOOR), BIGINT)); case EQUAL: Long equalValue = DoubleMath.roundToLong(value, FLOOR); if (equalValue.doubleValue() != value) { // Return something that is false for all non-null values return and(new ComparisonExpression(EQUAL, reference, new LongLiteral("0")), new ComparisonExpression(NOT_EQUAL, reference, new LongLiteral("0"))); } return new ComparisonExpression(normalized.getComparisonType(), reference, toExpression(equalValue, BIGINT)); case NOT_EQUAL: Long notEqualValue = DoubleMath.roundToLong(value, FLOOR); if (notEqualValue.doubleValue() != value) { // Return something that is true for all non-null values return or(new ComparisonExpression(EQUAL, reference, new LongLiteral("0")), new ComparisonExpression(NOT_EQUAL, reference, new LongLiteral("0"))); } return new ComparisonExpression(normalized.getComparisonType(), reference, toExpression(notEqualValue, BIGINT)); case IS_DISTINCT_FROM: Long distinctValue = DoubleMath.roundToLong(value, FLOOR); if (distinctValue.doubleValue() != value) { return TRUE_LITERAL; } return new ComparisonExpression(normalized.getComparisonType(), reference, toExpression(distinctValue, BIGINT)); default: throw new AssertionError("Unhandled type: " + normalized.getComparisonType()); } }
@Override protected Type visitLongLiteral(LongLiteral node, StackableAstVisitorContext<AnalysisContext> context) { expressionTypes.put(node, BIGINT); return BIGINT; }
private void analyzeOrderBy(Query node, RelationType tupleDescriptor, AnalysisContext context) { List<SortItem> items = node.getOrderBy(); ImmutableList.Builder<FieldOrExpression> orderByFieldsBuilder = ImmutableList.builder(); if (!items.isEmpty()) { for (SortItem item : items) { Expression expression = item.getSortKey(); FieldOrExpression orderByField; if (expression instanceof LongLiteral) { // this is an ordinal in the output tuple long ordinal = ((LongLiteral) expression).getValue(); if (ordinal < 1 || ordinal > tupleDescriptor.getVisibleFieldCount()) { throw new SemanticException(INVALID_ORDINAL, expression, "ORDER BY position %s is not in select list", ordinal); } orderByField = new FieldOrExpression(Ints.checkedCast(ordinal - 1)); } else { // otherwise, just use the expression as is orderByField = new FieldOrExpression(expression); ExpressionAnalysis expressionAnalysis = ExpressionAnalyzer.analyzeExpression(session, metadata, accessControl, sqlParser, tupleDescriptor, analysis, experimentalSyntaxEnabled, context, orderByField.getExpression()); analysis.recordSubqueries(node, expressionAnalysis); } orderByFieldsBuilder.add(orderByField); } } analysis.setOrderByExpressions(node, orderByFieldsBuilder.build()); }
private static LongLiteral longLiteral(long value) { return new LongLiteral(Long.toString(value)); }
@Test public void testCountConstantOptimizer() throws Exception { CountConstantOptimizer optimizer = new CountConstantOptimizer(); PlanNodeIdAllocator planNodeIdAllocator = new PlanNodeIdAllocator(); Symbol countAggregationSymbol = new Symbol("count"); Signature countAggregationSignature = new Signature("count", FunctionKind.AGGREGATE, "bigint", "bigint"); ImmutableMap<Symbol, FunctionCall> aggregations = ImmutableMap.of(countAggregationSymbol, new FunctionCall(QualifiedName.of("count"), ImmutableList.of(new QualifiedNameReference(QualifiedName.of("expr"))))); ImmutableMap<Symbol, Signature> functions = ImmutableMap.of(countAggregationSymbol, countAggregationSignature); ValuesNode valuesNode = new ValuesNode(planNodeIdAllocator.getNextId(), ImmutableList.of(new Symbol("col")), ImmutableList.of(ImmutableList.of())); AggregationNode eligiblePlan = new AggregationNode( planNodeIdAllocator.getNextId(), new ProjectNode( planNodeIdAllocator.getNextId(), valuesNode, ImmutableMap.of(new Symbol("expr"), new LongLiteral("42"))), ImmutableList.of(), aggregations, functions, ImmutableMap.of(), AggregationNode.Step.INTERMEDIATE, Optional.empty(), 1.0, Optional.empty()); assertTrue(((AggregationNode) optimizer.optimize(eligiblePlan, TEST_SESSION, ImmutableMap.of(), new SymbolAllocator(), new PlanNodeIdAllocator())) .getAggregations() .get(countAggregationSymbol) .getArguments() .isEmpty()); AggregationNode ineligiblePlan = new AggregationNode( planNodeIdAllocator.getNextId(), new ProjectNode( planNodeIdAllocator.getNextId(), valuesNode, ImmutableMap.of(new Symbol("expr"), new FunctionCall(QualifiedName.of("function"), ImmutableList.of(new QualifiedNameReference(QualifiedName.of("x")))))), ImmutableList.of(), aggregations, functions, ImmutableMap.of(), AggregationNode.Step.INTERMEDIATE, Optional.empty(), 1.0, Optional.empty()); assertFalse(((AggregationNode) optimizer.optimize(ineligiblePlan, TEST_SESSION, ImmutableMap.of(), new SymbolAllocator(), new PlanNodeIdAllocator())) .getAggregations() .get(countAggregationSymbol) .getArguments() .isEmpty()); }
@Override public Node visitIntegerLiteral(SqlBaseParser.IntegerLiteralContext context) { return new LongLiteral(getLocation(context), context.getText()); }
@Override protected String visitLongLiteral(LongLiteral node, Boolean unmangleNames) { return Long.toString(node.getValue()); }
@Test public void testPrecedenceAndAssociativity() throws Exception { assertExpression("1 AND 2 OR 3", new LogicalBinaryExpression(LogicalBinaryExpression.Type.OR, new LogicalBinaryExpression(LogicalBinaryExpression.Type.AND, new LongLiteral("1"), new LongLiteral("2")), new LongLiteral("3"))); assertExpression("1 OR 2 AND 3", new LogicalBinaryExpression(LogicalBinaryExpression.Type.OR, new LongLiteral("1"), new LogicalBinaryExpression(LogicalBinaryExpression.Type.AND, new LongLiteral("2"), new LongLiteral("3")))); assertExpression("NOT 1 AND 2", new LogicalBinaryExpression(LogicalBinaryExpression.Type.AND, new NotExpression(new LongLiteral("1")), new LongLiteral("2"))); assertExpression("NOT 1 OR 2", new LogicalBinaryExpression(LogicalBinaryExpression.Type.OR, new NotExpression(new LongLiteral("1")), new LongLiteral("2"))); assertExpression("-1 + 2", new ArithmeticBinaryExpression(ArithmeticBinaryExpression.Type.ADD, negative(new LongLiteral("1")), new LongLiteral("2"))); assertExpression("1 - 2 - 3", new ArithmeticBinaryExpression(ArithmeticBinaryExpression.Type.SUBTRACT, new ArithmeticBinaryExpression(ArithmeticBinaryExpression.Type.SUBTRACT, new LongLiteral("1"), new LongLiteral("2")), new LongLiteral("3"))); assertExpression("1 / 2 / 3", new ArithmeticBinaryExpression(ArithmeticBinaryExpression.Type.DIVIDE, new ArithmeticBinaryExpression(ArithmeticBinaryExpression.Type.DIVIDE, new LongLiteral("1"), new LongLiteral("2")), new LongLiteral("3"))); assertExpression("1 + 2 * 3", new ArithmeticBinaryExpression(ArithmeticBinaryExpression.Type.ADD, new LongLiteral("1"), new ArithmeticBinaryExpression(ArithmeticBinaryExpression.Type.MULTIPLY, new LongLiteral("2"), new LongLiteral("3")))); }
@Test public void testSelectWithRowType() throws Exception { assertStatement("SELECT col1.f1, col2, col3.f1.f2.f3 FROM table1", new Query( Optional.empty(), new QuerySpecification( selectList( new DereferenceExpression(new QualifiedNameReference(QualifiedName.of("col1")), "f1"), new QualifiedNameReference(QualifiedName.of("col2")), new DereferenceExpression( new DereferenceExpression(new DereferenceExpression(new QualifiedNameReference(QualifiedName.of("col3")), "f1"), "f2"), "f3")), Optional.of(new Table(QualifiedName.of("table1"))), Optional.empty(), ImmutableList.of(), Optional.empty(), ImmutableList.of(), Optional.empty()), ImmutableList.<SortItem>of(), Optional.empty(), Optional.empty())); assertStatement("SELECT col1.f1[0], col2, col3[2].f2.f3, col4[4] FROM table1", new Query( Optional.empty(), new QuerySpecification( selectList( new SubscriptExpression(new DereferenceExpression(new QualifiedNameReference(QualifiedName.of("col1")), "f1"), new LongLiteral("0")), new QualifiedNameReference(QualifiedName.of("col2")), new DereferenceExpression(new DereferenceExpression(new SubscriptExpression(new QualifiedNameReference(QualifiedName.of("col3")), new LongLiteral("2")), "f2"), "f3"), new SubscriptExpression(new QualifiedNameReference(QualifiedName.of("col4")), new LongLiteral("4")) ), Optional.of(new Table(QualifiedName.of("table1"))), Optional.empty(), ImmutableList.of(), Optional.empty(), ImmutableList.of(), Optional.empty()), ImmutableList.<SortItem>of(), Optional.empty(), Optional.empty())); assertStatement("SELECT test_row(11, 12).col0", new Query( Optional.empty(), new QuerySpecification( selectList( new DereferenceExpression(new FunctionCall(QualifiedName.of("test_row"), Lists.newArrayList(new LongLiteral("11"), new LongLiteral("12"))), "col0") ), Optional.empty(), Optional.empty(), ImmutableList.of(), Optional.empty(), ImmutableList.of(), Optional.empty()), ImmutableList.<SortItem>of(), Optional.empty(), Optional.empty())); }