@Override protected String visitArithmeticUnary(ArithmeticUnaryExpression node, StackableAstVisitorContext<Integer> indent) { String value = process(node.getValue(), indent); switch (node.getSign()) { case MINUS: // this is to avoid turning a sequence of "-" into a comment (i.e., "-- comment") String separator = value.startsWith("-") ? " " : ""; return "-" + separator + value; case PLUS: return "+" + value; default: throw new UnsupportedOperationException("Unsupported sign: " + node.getSign()); } }
@Override protected RowExpression visitArithmeticUnary(ArithmeticUnaryExpression node, Void context) { RowExpression expression = process(node.getValue(), context); switch (node.getSign()) { case PLUS: return expression; case MINUS: return call( arithmeticNegationSignature(types.get(node), expression.getType()), types.get(node), expression); } throw new UnsupportedOperationException("Unsupported unary operator: " + node.getSign()); }
@Override protected Type visitArithmeticUnary(ArithmeticUnaryExpression node, StackableAstVisitorContext<AnalysisContext> context) { switch (node.getSign()) { case PLUS: Type type = process(node.getValue(), context); if (!type.equals(BIGINT) && !type.equals(DOUBLE)) { // TODO: figure out a type-agnostic way of dealing with this. Maybe add a special unary operator // that types can chose to implement, or piggyback on the existence of the negation operator throw new SemanticException(TYPE_MISMATCH, node, "Unary '+' operator cannot by applied to %s type", type); } expressionTypes.put(node, type); return type; case MINUS: return getOperator(context, node, OperatorType.NEGATION, node.getValue()); } throw new UnsupportedOperationException("Unsupported unary operator: " + node.getSign()); }
@Override protected String visitArithmeticUnary(ArithmeticUnaryExpression node, Boolean unmangleNames) { String value = process(node.getValue(), unmangleNames); switch (node.getSign()) { case MINUS: // this is to avoid turning a sequence of "-" into a comment (i.e., "-- comment") String separator = value.startsWith("-") ? " " : ""; return "-" + separator + value; case PLUS: return "+" + value; default: throw new UnsupportedOperationException("Unsupported sign: " + node.getSign()); } }
/** * 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; }
@Override protected Object visitArithmeticUnary(ArithmeticUnaryExpression node, Object context) { Object value = process(node.getValue(), context); if (value == null) { return null; } if (value instanceof Expression) { return new ArithmeticUnaryExpression(node.getSign(), toExpression(value, expressionTypes.get(node.getValue()))); } switch (node.getSign()) { case PLUS: return value; case MINUS: Signature operatorSignature = metadata.getFunctionRegistry().resolveOperator(OperatorType.NEGATION, types(node.getValue())); MethodHandle handle = metadata.getFunctionRegistry().getScalarFunctionImplementation(operatorSignature).getMethodHandle(); if (handle.type().parameterCount() > 0 && handle.type().parameterType(0) == ConnectorSession.class) { handle = handle.bindTo(session); } try { return handle.invokeWithArguments(value); } catch (Throwable throwable) { Throwables.propagateIfInstanceOf(throwable, RuntimeException.class); Throwables.propagateIfInstanceOf(throwable, Error.class); throw new RuntimeException(throwable.getMessage(), throwable); } } throw new UnsupportedOperationException("Unsupported unary operator: " + node.getSign()); }
@Override public Node visitArithmeticUnary(SqlBaseParser.ArithmeticUnaryContext context) { Expression child = (Expression) visit(context.valueExpression()); switch (context.operator.getType()) { case SqlBaseLexer.MINUS: return ArithmeticUnaryExpression.negative(getLocation(context), child); case SqlBaseLexer.PLUS: return ArithmeticUnaryExpression.positive(getLocation(context), child); default: throw new UnsupportedOperationException("Unsupported sign: " + context.operator.getText()); } }
@Override protected Boolean visitArithmeticUnary(ArithmeticUnaryExpression node, Void context) { return process(node.getValue(), context); }