Allgemeine Richtlinien zum Codieren von Scala-UDF-Handlern

Unter diesem Thema werden allgemeine Richtlinien für das Schreiben von Handler-Code in Scala beschrieben. Spezifische Informationen zu Handlern für skalare Funktionen finden Sie unter Schreiben einer skalaren UDF in Scala.

Vorschläge zum Strukturieren Ihres Projekts, zum Packen Ihres Codes und zum Verwalten von Abhängigkeiten finden Sie unter Scala-UDF-Handler – Projekt und Paketerstellung.

Best Practices

  • Schreiben Sie plattformunabhängigen Code.

    • Vermeiden Sie Code, der eine bestimmte CPU-Architektur voraussetzt (z. B. x86).

    • Vermeiden Sie Code, der ein bestimmtes Betriebssystem voraussetzt.

  • Wenn Sie Initialisierungscode ausführen müssen und diesen nicht in die aufgerufene Methode aufnehmen möchten, können Sie den Initialisierungscode in ein Begleitobjekt Ihrer Handler-Klasse einfügen.

Schreiben eines Handlers

Sie können eine skalare UDF mit einem in Scala geschriebenen Handler schreiben.

Der Handler wird für jede an die Scala-UDF übergebene Zeile einmal aufgerufen. Es wird nicht für jede Zeile eine neue Instanz der Klasse erstellt. Snowflake kann die Handler-Methode derselben Instanz mehrmals aufrufen.

Um die Ausführung Ihres Codes zu optimieren, unterscheiden Timeout-Schwellenwerte in Snowflake zwischen der Zeit, die für die Initialisierung Ihrer Handler-Klasse oder Ihres Objekts benötigt wird, und der Zeit, die für die Ausführung der Handler-Methode benötigt wird. Snowflake erlaubt mehr Zeit für die Initialisierung der Handler-Klasse oder des Objekts in der Annahme, dass die Initialisierung länger dauern könnte. Dies beinhaltet die Zeit zum Laden der UDF und die Zeit zum Aufrufen des Konstruktors der Klasse, die die Handler-Methode enthält, falls ein Konstruktor definiert ist.

Fehlerbehandlung

Sie können Ausnahmen mit gängigen Methoden behandeln, um Fehler innerhalb der Handler-Methode abzufangen.

Wenn eine Ausnahme innerhalb der Methode auftritt und nicht von der Methode abgefangen wird, gibt Snowflake einen Fehler aus, der die Stapelüberwachung für die Ausnahme enthält.

Sie können explizit einen Fehler auszulösen, ohne ihn abzufangen, um die Abfrage zu beenden und einen SQL-Fehler zu erzeugen. Beispiel:

if (x < 0) throw new IllegalArgumentException("x must be non-negative.")
Copy

Beim Debugging können Sie in den Text der SQL-Fehlermeldung Werte integrieren. Gehen Sie dabei wie folgt vor:

  • Platzieren Sie einen kompletten Scala-Methodenkörper in einen „try-catch“-Block.

  • Hängen Sie Argumentwerte zur abgefangenen Fehlermeldung hinzu.

  • Lösen Sie eine Ausnahme mit der erweiterten Meldung aus.

Um die Offenlegung sensibler Daten zu verhindern, entfernen Sie die Argumente, bevor Sie die JAR-Dateien in einer Produktionsumgebung bereitstellen.

Auswählen der Datentypen

Wenn Sie Ihren Handler schreiben, müssen Sie für Parameter und Rückgabedaten Datentypen (aus der Sprache des Handlers) deklarieren, die zu den Parameter- und Rückgabedatentypen der UDF (aus SQL) passen.

Wenn die UDF aufgerufen wird, konvertiert Snowflake die Argumente der UDF von den SQL-Parametertypen in die Parametertypen des Handlers. Wenn ein Wert zurückgegeben wird, konvertiert Snowflake den Rückgabewert vom Rückgabetyp des Handlers in den Rückgabetyp der UDF.

Snowflake konvertiert Werte zwischen Typen entsprechend den unterstützten Zuordnungen (Mappings) zwischen SQL-Typen und Scala-Typen. Weitere Informationen zu diesen Zuordnungen finden Sie unter Zuordnung von Datentypen zwischen SQL und Scala.

Berücksichtigen Sie bei der Auswahl der Datentypen von Scala-Variablen die maximal und minimal möglichen Werte der Daten, die von Snowflake gesendet (und an Snowflake zurückgegeben) werden können.

Erstellen der UDF mit CREATE FUNCTION

Sie erstellen einen UDF in SQL mit dem Befehl CREATE FUNCTION und geben den von Ihnen geschriebenen Code als Handler an. Weitere Informationen zu diesem Befehl finden Sie unter CREATE FUNCTION.

CREATE OR REPLACE FUNCTION <name> ( [ <arguments> ] )
  RETURNS <type>
  LANGUAGE SCALA
  [ IMPORTS = ( '<imports>' ) ]
  RUNTIME_VERSION = 2.12
  [ PACKAGES = ( '<package_name>' [, '<package_name>' . . .] ) ]
  [ TARGET_PATH = '<stage_path_and_file_name_to_write>' ]
  HANDLER = '<handler_class>.<handler_method>'
  [ AS '<scala_code>' ]
Copy

Um den von Ihnen geschriebenen Handler-Code mit der UDF zu verknüpfen, müssen Sie beim Ausführen der CREATE FUNCTION Folgendes tun:

  • Setzen Sie LANGUAGE auf SCALA.

  • Setzen Sie den Wert der IMPORTS-Klausel auf den Pfad und den Namen der Handler-Klasse, wenn sich die Klasse an einem externen Speicherort wie z. B. einem Stagingbereich befindet.

  • Setzen Sie RUNTIME_VERSION auf die Version der Scala-Laufzeitumgebung, die von Ihrem Code benötigt wird.

  • Setzen Sie den Wert der PACKAGES-Klausel auf den Namen eines oder mehrerer Pakete, die, falls vorhanden, von der Handler-Klasse benötigt werden.

  • Setzen Sie den Wert der HANDLER-Klausel auf den Namen des Handler-Objekts und der Handler-Methode.

  • Die Klausel AS '<scala_code>' ist erforderlich, wenn der Handler-Code inline mit CREATE FUNCTION angegeben wird.