@SqlNullable
  @Description("extract query parameter from url")
  @ScalarFunction
  @LiteralParameters({"x", "y"})
  @SqlType("varchar(x)")
  public static Slice urlExtractParameter(
      @SqlType("varchar(x)") Slice url, @SqlType("varchar(y)") Slice parameterName) {
    URI uri = parseUrl(url);
    if ((uri == null) || (uri.getQuery() == null)) {
      return null;
    }

    Slice query = slice(uri.getQuery());
    String parameter = parameterName.toStringUtf8();
    Iterable<String> queryArgs = QUERY_SPLITTER.split(query.toStringUtf8());

    for (String queryArg : queryArgs) {
      Iterator<String> arg = ARG_SPLITTER.split(queryArg).iterator();
      if (arg.next().equals(parameter)) {
        if (arg.hasNext()) {
          return utf8Slice(arg.next());
        }
        // first matched key is empty
        return Slices.EMPTY_SLICE;
      }
    }

    // no key matched
    return null;
  }
Beispiel #2
0
 @ScalarFunction(value = "at_time_zone", hidden = true)
 @SqlType(TimestampWithTimeZoneType.class)
 public static long timestampAtTimeZone(
     @SqlType(TimestampWithTimeZoneType.class) long timestampWithTimeZone,
     @SqlType(VarcharType.class) Slice zoneId) {
   return packDateTimeWithZone(unpackMillisUtc(timestampWithTimeZone), zoneId.toStringUtf8());
 }
 @Nullable
 private static URI parseUrl(Slice url) {
   try {
     return new URI(url.toStringUtf8());
   } catch (URISyntaxException e) {
     return null;
   }
 }
 @Description("escape a string for use in URL query parameter names and values")
 @ScalarFunction
 @LiteralParameters({"x", "y"})
 @Constraint(variable = "y", expression = "min(2147483647, x * 12)")
 @SqlType("varchar(y)")
 public static Slice urlEncode(@SqlType("varchar(x)") Slice value) {
   Escaper escaper = UrlEscapers.urlFormParameterEscaper();
   return slice(escaper.escape(value.toStringUtf8()));
 }
Beispiel #5
0
 private static Object nativeContainerToOrcValue(Type type, Object nativeValue) {
   if (nativeValue == null) {
     return null;
   }
   if (type instanceof DecimalType) {
     BigInteger unscaledValue;
     DecimalType decimalType = (DecimalType) type;
     if (decimalType.isShort()) {
       unscaledValue = BigInteger.valueOf((long) nativeValue);
     } else {
       unscaledValue = Decimals.decodeUnscaledValue((Slice) nativeValue);
     }
     return HiveDecimal.create(unscaledValue, decimalType.getScale());
   }
   if (type.getJavaType() == boolean.class) {
     return nativeValue;
   }
   if (type.getJavaType() == long.class) {
     return nativeValue;
   }
   if (type.getJavaType() == double.class) {
     return nativeValue;
   }
   if (type.getJavaType() == Slice.class) {
     Slice slice = (Slice) nativeValue;
     return type instanceof VarcharType ? slice.toStringUtf8() : slice.getBytes();
   }
   if (isArrayType(type)) {
     Block arrayBlock = (Block) nativeValue;
     Type elementType = type.getTypeParameters().get(0);
     List<Object> list = new ArrayList<>();
     for (int i = 0; i < arrayBlock.getPositionCount(); i++) {
       list.add(
           nativeContainerToOrcValue(
               elementType, getNativeContainerValue(elementType, arrayBlock, i)));
     }
     return list;
   }
   if (isMapType(type)) {
     Block mapBlock = (Block) nativeValue;
     Type keyType = type.getTypeParameters().get(0);
     Type valueType = type.getTypeParameters().get(1);
     Map<Object, Object> map = new HashMap<>();
     for (int i = 0; i < mapBlock.getPositionCount(); i += 2) {
       Object key =
           nativeContainerToOrcValue(keyType, getNativeContainerValue(keyType, mapBlock, i));
       Object value =
           nativeContainerToOrcValue(
               valueType, getNativeContainerValue(valueType, mapBlock, i + 1));
       map.put(key, value);
     }
     return map;
   }
   throw new PrestoException(INTERNAL_ERROR, "Unimplemented type: " + type);
 }
 @Description("unescape a URL-encoded string")
 @ScalarFunction
 @LiteralParameters("x")
 @SqlType("varchar(x)")
 public static Slice urlDecode(@SqlType("varchar(x)") Slice value) {
   try {
     return slice(URLDecoder.decode(value.toStringUtf8(), UTF_8.name()));
   } catch (UnsupportedEncodingException e) {
     throw new AssertionError(e);
   } catch (IllegalArgumentException e) {
     throw new PrestoException(INVALID_FUNCTION_ARGUMENT, e);
   }
 }
  public static Expression toExpression(Object object, Type type) {
    requireNonNull(type, "type is null");

    if (object instanceof Expression) {
      return (Expression) object;
    }

    if (object == null) {
      if (type.equals(UNKNOWN)) {
        return new NullLiteral();
      }
      return new Cast(new NullLiteral(), type.getTypeSignature().toString(), false, true);
    }

    checkArgument(
        Primitives.wrap(type.getJavaType()).isInstance(object),
        "object.getClass (%s) and type.getJavaType (%s) do not agree",
        object.getClass(),
        type.getJavaType());

    if (type.equals(BIGINT)) {
      return new LongLiteral(object.toString());
    }

    if (type.equals(DOUBLE)) {
      Double value = (Double) object;
      // WARNING: the ORC predicate code depends on NaN and infinity not appearing in a tuple
      // domain, so
      // if you remove this, you will need to update the TupleDomainOrcPredicate
      if (value.isNaN()) {
        return new FunctionCall(new QualifiedName("nan"), ImmutableList.<Expression>of());
      } else if (value.equals(Double.NEGATIVE_INFINITY)) {
        return ArithmeticUnaryExpression.negative(
            new FunctionCall(new QualifiedName("infinity"), ImmutableList.<Expression>of()));
      } else if (value.equals(Double.POSITIVE_INFINITY)) {
        return new FunctionCall(new QualifiedName("infinity"), ImmutableList.<Expression>of());
      } else {
        return new DoubleLiteral(object.toString());
      }
    }

    if (type instanceof VarcharType) {
      if (object instanceof String) {
        object = Slices.utf8Slice((String) object);
      }

      if (object instanceof Slice) {
        Slice value = (Slice) object;
        int length = SliceUtf8.countCodePoints(value);

        if (length == ((VarcharType) type).getLength()) {
          return new StringLiteral(value.toStringUtf8());
        }

        return new Cast(
            new StringLiteral(value.toStringUtf8()), type.getDisplayName(), false, true);
      }

      throw new IllegalArgumentException(
          "object must be instance of Slice or String when type is VARCHAR");
    }

    if (type.equals(BOOLEAN)) {
      return new BooleanLiteral(object.toString());
    }

    if (object instanceof Block) {
      SliceOutput output = new DynamicSliceOutput(((Block) object).getSizeInBytes());
      BlockSerdeUtil.writeBlock(output, (Block) object);
      object = output.slice();
      // This if condition will evaluate to true: object instanceof Slice && !type.equals(VARCHAR)
    }

    if (object instanceof Slice) {
      // HACK: we need to serialize VARBINARY in a format that can be embedded in an expression to
      // be
      // able to encode it in the plan that gets sent to workers.
      // We do this by transforming the in-memory varbinary into a call to
      // from_base64(<base64-encoded value>)
      FunctionCall fromBase64 =
          new FunctionCall(
              new QualifiedName("from_base64"),
              ImmutableList.of(
                  new StringLiteral(VarbinaryFunctions.toBase64((Slice) object).toStringUtf8())));
      Signature signature = FunctionRegistry.getMagicLiteralFunctionSignature(type);
      return new FunctionCall(new QualifiedName(signature.getName()), ImmutableList.of(fromBase64));
    }

    Signature signature = FunctionRegistry.getMagicLiteralFunctionSignature(type);
    Expression rawLiteral = toExpression(object, FunctionRegistry.typeForMagicLiteral(type));

    return new FunctionCall(new QualifiedName(signature.getName()), ImmutableList.of(rawLiteral));
  }