2016-05-04 15 views
0

Diese Abfrage mit einer kryptischen Auswertung Fehler versagt:Warum schlägt dieser Hive-QL-Ausdruck fehl?

select printf("%08x", reflect('java.lang.Integer', 'reverseBytes', mhash3('123', 0))); 

(Hier ist die Ausnahme)
Failed with exception java.io.IOException:org.apache.hadoop.hive.ql.metadata.HiveException: Error evaluating printf('%08x', reflect('java.lang.Integer','reverseBytes',1)) 

Was ich versuche, konsequent eine Java-Implementierung eines murmur3 Hash-hex zu reproduzieren ist zu erreichen Wert, der die Hash-Methode getBytes verwendet, die sie im Big-Endian-Format zurückgibt (und Dezimalziffern werden in Little-Endian geschrieben), wodurch das Byte in der Ganzzahl getauscht wird.

jeden Teil der separate Abfrage Doing funktioniert perfekt, es ist die printf Mischen und das widerspiegelt, was nicht ... Und nur, wenn die Formatierung ist eine Zahl, Art, so funktioniert das:

select printf("%s", reflect('java.lang.Integer', 'reverseBytes', mhash3('123', 0))); 

aber auch

select printf("%d", reflect('java.lang.Integer', 'reverseBytes', mhash3('123', 0))); 

versagt und ich habe dafür gesorgt, dass das Ergebnis ein numerischer Typ ist und kein String, da ich es arithmetische Operationen tun, wie:

select printf("%s", 10 * reflect('java.lang.Integer', 'reverseBytes', mhash3('123', 0))); 

Bisher musste ich keine benutzerdefinierten UDFs hinzufügen. Wenn es eine Abhilfe gibt, möchte ich das so behalten.

+0

Es gibt eine große Lücke zwischen * sein könnte: „Ich kann auf sie Arithmetik tun, weil irgendwie funktioniert die JVM etwas Magie auf doof Objekt-Wrapper“ * und * "es ist eine Basis numerischer Typ, dass' printf' verarbeiten kann direkt"*. Haben Sie versucht, dieses böse Integer-Objekt in eine altmodische IEEE-Ganzzahl (a.k.a.. "int") zu "werfen", bevor Sie es in "printf()" eingeben? –

+0

Um genau zu sein, meine ich die SQL-Syntax 'cast (' _expr_ 'as int)' –

+0

oh Mist, das funktioniert! Wenn du diesen Kommentar als Antwort schreibst, kann ich das akzeptieren :) – fortran

Antwort

1

Hive ist im Grunde ein Java-Programm, das SQL-ähnliche Datentypen und Ausdrücke in Java-Datentypen und Java/Hadoop-Ausdrücke/Jobs übersetzt.
In den meisten Fällen ist es kompliziert genug. Aber wenn Sie einen benutzerdefinierten Java-Ausdruck in den Mix werfen - und das ist es, was reflect() dreht - dann können Sie in einen Randfall fallen.

In Ihrem spezifischen Problem, statische java.lang.Integer.reverseBytes(int) soll einen primitiven Typ int Wert zurückgeben. Aber ich bin nicht sicher, wie Hive intern generische Integer-Werte behandelt - vielleicht mit einem long? vielleicht mit einem benutzerdefinierten Objekttyp ??
Wie auch immer sieht es so aus, als könnte der Rückgabewert nicht direkt in Hive printf() Funktion als numerischer Typ zugeführt werden. Vielleicht ist die int auf eine String standardmäßig werfen ... vielleicht wäre es stattdessen mit einem long gearbeitet ...

ich zwei mögliche Abhilfen siehe:

  1. den Anruf zu reflect() in einer sub- wickeln abfragen, so dass Hive eine implizite Konvertierung in einen von Hive unterstützten Typ vornimmt (Unterabfrage wird zur Kompilierungszeit zusammengeführt, kein zusätzlicher MR-Schritt erforderlich) - mit dem Risiko, dass der Hive-Typ immer noch eine 0 ist Explizite Konvertierung in den numerischen Typ Hive Ihrer Wahl
    select printf("%d", cast(reflect(.......) as int)) from ...