Java UDF ハンドラーの例¶
このトピックには、Javaで記述された UDF ハンドラーコードの簡単な例が含まれています。
Javaを使用して UDF ハンドラーを作成する方法の詳細については、 Java UDF ハンドラーの作成 をご参照ください。
このトピックの内容:
単純なインラインJava UDF の作成と呼び出し¶
次のステートメントは、インラインJava UDF を作成して呼び出します。このコードは、渡された VARCHAR
を返します。
この関数は、オプションの CALLED ON NULL INPUT
句を使用して宣言され、入力の値が NULL であっても関数が呼び出されることを示します。(この関数は、この句の有無にかかわらず NULL を返しますが、たとえば空の文字列を返すように、別の方法で NULL を処理するようにコードを変更できます。)
UDF を作成します。
create or replace function echo_varchar(x varchar)
returns varchar
language java
called on null input
handler='TestFunc.echoVarchar'
target_path='@~/testfunc.jar'
as
'class TestFunc {
public static String echoVarchar(String x) {
return x;
}
}';
UDF を呼び出します。
SELECT echo_varchar('Hello');
+-----------------------+
| ECHO_VARCHAR('HELLO') |
|-----------------------|
| Hello |
+-----------------------+
NULL のインラインJava UDF への引き渡し¶
これは、上記で定義された echo_varchar()
UDF を使用します。SQL NULL
値は暗黙的にJava null
に変換され、そのJava null
が返され、暗黙的に SQL NULL
に変換されます。
UDF を呼び出します。
SELECT echo_varchar(NULL);
+--------------------+
| ECHO_VARCHAR(NULL) |
|--------------------|
| NULL |
+--------------------+
インライン UDF からの明示的な NULL の戻り¶
次のコードは、 NULL 値を明示的に返す方法を示しています。Java値 null
は SQL NULL
に変換されます。
UDF を作成します。
create or replace function return_a_null()
returns varchar
null
language java
handler='TemporaryTestLibrary.returnNull'
target_path='@~/TemporaryTestLibrary.jar'
as
$$
class TemporaryTestLibrary {
public static String returnNull() {
return null;
}
}
$$;
UDF を呼び出します。
SELECT return_a_null();
+-----------------+
| RETURN_A_NULL() |
|-----------------|
| NULL |
+-----------------+
OBJECT のインラインJava UDF への引き渡し¶
次の例では、 SQL OBJECT データ型と対応するJavaデータ型(Map<文字列,文字列>
)を使用し、 OBJECT
から値を抽出します。この例は、Java UDF に複数のパラメーターを渡すことができることも示しています。
タイプ OBJECT の列を含むテーブルを作成してロードします。
CREATE TABLE objectives (o OBJECT);
INSERT INTO objectives SELECT PARSE_JSON('{"outer_key" : {"inner_key" : "inner_value"} }');
UDF を作成します。
create or replace function extract_from_object(x OBJECT, key VARCHAR)
returns variant
language java
handler='VariantLibrary.extract'
target_path='@~/VariantLibrary.jar'
as
$$
import java.util.Map;
class VariantLibrary {
public static String extract(Map<String, String> m, String key) {
return m.get(key);
}
}
$$;
UDF を呼び出します。
SELECT extract_from_object(o, 'outer_key'),
extract_from_object(o, 'outer_key')['inner_key'] FROM objectives;
+-------------------------------------+--------------------------------------------------+
| EXTRACT_FROM_OBJECT(O, 'OUTER_KEY') | EXTRACT_FROM_OBJECT(O, 'OUTER_KEY')['INNER_KEY'] |
|-------------------------------------+--------------------------------------------------|
| { | "inner_value" |
| "inner_key": "inner_value" | |
| } | |
+-------------------------------------+--------------------------------------------------+
ARRAY のインラインJava UDF への引き渡し¶
次の例では、 SQL ARRAY データ型を使用しています。
UDF を作成します。
create or replace function multiple_functions_in_jar(array1 array)
returns varchar
language java
handler='TemporaryTestLibrary.handleStrings'
target_path='@~/TemporaryTestLibrary.jar'
as
$$
class TemporaryTestLibrary {
public static String handleStrings(String[] strings) {
return concatenate(strings);
}
public static String concatenate(String[] strings) {
int numberOfStrings = strings.length;
String concatenated = "";
for (int i = 0; i < numberOfStrings; i++) {
concatenated = concatenated + " " + strings[i];
}
return concatenated;
}
}
$$;
UDF を呼び出します。
SELECT multiple_functions_in_jar(ARRAY_CONSTRUCT('Hello', 'world'));
+--------------------------------------------------------------+
| MULTIPLE_FUNCTIONS_IN_JAR(ARRAY_CONSTRUCT('HELLO', 'WORLD')) |
|--------------------------------------------------------------|
| Hello world |
+--------------------------------------------------------------+
GEOGRAPHY 値のインラインJava UDF への引き渡し¶
次の例では、 SQL GEOGRAPHY データ型を使用しています。
UDF を作成します。
create or replace function geography_equals(x geography, y geography)
returns boolean
language java
packages=('com.snowflake:snowpark:1.2.0')
handler='TestGeography.compute'
as
$$
import com.snowflake.snowpark_java.types.Geography;
class TestGeography {
public static boolean compute(Geography geo1, Geography geo2) {
return geo1.equals(geo2);
}
}
$$;
PACKAGES
句を使用して、 Snowparkパッケージ などのSnowflakeシステムパッケージを指定できます。その場合は、 IMPORTS
句の値としてSnowpark JAR ファイルを含める必要はありません。 PACKAGES
の詳細については、 CREATE FUNCTION オプションのパラメーター をご参照ください。
データを作成し、そのデータを使用して UDF を呼び出します。
create table geocache_table (id INTEGER, g1 GEOGRAPHY, g2 GEOGRAPHY);
insert into geocache_table (id, g1, g2) select
1, TO_GEOGRAPHY('POINT(-122.35 37.55)'), TO_GEOGRAPHY('POINT(-122.35 37.55)');
insert into geocache_table (id, g1, g2) select
2, TO_GEOGRAPHY('POINT(-122.35 37.55)'), TO_GEOGRAPHY('POINT(90.0 45.0)');
select id, g1, g2, geography_equals(g1, g2) as "EQUAL?"
from geocache_table
order by id;
出力は、次と類似したものになります。
+----+--------------------------------------------------------+---------------------------------------------------------+--------+
| ID | G1 | G2 | EQUAL? |
+----+--------------------------------------------------------|---------------------------------------------------------+--------+
| 1 | { "coordinates": [ -122.35, 37.55 ], "type": "Point" } | { "coordinates": [ -122.35, 37.55 ], "type": "Point" } | TRUE |
| 2 | { "coordinates": [ -122.35, 37.55 ], "type": "Point" } | { "coordinates": [ 90.0, 45.0 ], "type": "Point" } | FALSE |
+----+--------------------------------------------------------+---------------------------------------------------------+--------+
VARIANT 値のインラインJava UDF への引き渡し¶
SQL VARIANT 型の値をJava UDF に渡すと、Snowflakeはその値を Snowparkパッケージ で提供される バリアント 型に変換できます。 Variant
は、Snowparkパッケージバージョン1.4.0以降でサポートされていることに注意してください。
Snowpark Variant
型は、 Variant
型と他のタイプの間で値を変換するためのメソッドを提供します。
Snowpark Variant
型を使用するには、 PACKAGES 句を使用して、 UDF を作成するときにSnowparkパッケージを指定します。その場合は、 IMPORTS 句の値としてSnowpark JAR ファイルを含める必要はありません。PACKAGES の詳細については、 CREATE FUNCTION オプションのパラメーター をご参照ください。
次の例のコードは、 VARIANT 型として保存された JSON データを受け取り、Snowparkライブラリの Variant
型を使用して、 JSON から price
値を取得します。受信した JSON は、 例で使用されるサンプルデータ に表示されている JSON と同様の構造になっています。
create or replace function retrieve_price(v variant)
returns integer
language java
packages=('com.snowflake:snowpark:1.4.0')
handler='VariantTest.retrievePrice'
as
$$
import java.util.Map;
import com.snowflake.snowpark_java.types.Variant;
public class VariantTest {
public static Integer retrievePrice(Variant v) throws Exception {
Map<String, Variant> saleMap = v.asMap();
int price = saleMap.get("vehicle").asMap().get("price").asInt();
return price;
}
}
$$;
Java UDF ハンドラーを使用したファイルの読み取り¶
Java UDF ハンドラーコードを使用してファイルの内容を読み取ることができます。ファイルは、ハンドラーが使用できるSnowflakeのステージである必要があります。たとえば、ファイルを読み取って、ハンドラーで非構造化データを処理する場合があります。詳細については、 Java UDFs または UDTFs を使用した非構造化データの処理 をご参照ください。
ステージングされたファイルのコンテンツを読み取るために、Java UDFs または UDTFs は次のことができます。
IMPORTS 句 でファイルのパスと名前を指定し、 UDF のホームディレクトリから読み込む。これは、初期化中など、ファイルに静的にアクセスする場合に役立ちます。
SnowflakeFile
クラスまたはInputStream
クラスのメソッドを呼び出す。コンピューティング中、ファイルに動的にアクセスする必要があるときは、これを実行する場合があります。詳細については、このトピック内の SnowflakeFile クラスを使用したファイルの読み取り または InputStream クラスを使用したファイルの読み取り をご参照ください。SnowflakeFile
は、次のテーブルで説明されているように、InputStream
では利用できない機能を提供します。クラス
入力
メモ
SnowflakeFile
URL フォーマット:
関数の呼び出し元がその所有者でもない場合に、ファイルインジェクション攻撃のリスクを軽減するためのスコープ URL を設定しました。
UDF の呼び出し元が所有者でもある場合のファイル URL またはファイルの文字列パス。
ファイルは、内部または外部ステージに配置する必要があります。
ファイルサイズなど、追加のファイル属性に簡単にアクセスできます。
InputStream
URL フォーマット:
関数の呼び出し元がその所有者でもない場合に、ファイルインジェクション攻撃のリスクを軽減するためのスコープ URL を設定しました。
UDF の呼び出し元が所有者でもある場合のファイル URL またはファイルの文字列パス。
ファイルは、内部または外部ステージに配置する必要があります。
前提条件¶
ファイルをコードで使用できるようにするには、Javaハンドラーコードがステージ上のファイルを読み取る前に、次を実行する必要があります。
ハンドラーが使用できるステージを作成する。
外部ステージまたは内部ステージを使用できます。内部ステージを使用する場合は、ユーザーまたは名前付きステージにする必要があります。Snowflakeは現在、 UDF 依存関係のテーブルステージの使用をサポートしていません。ステージの作成の詳細については、 CREATE STAGE をご参照ください。内部ステージ型の選択の詳細については、 ローカルファイルに対する内部ステージの選択 をご参照ください。
ステージから読み取る SQL アクションを実行するロールには、ステージに対する適切な権限を割り当てる必要があることに注意してください。詳細については、 ユーザー定義関数の権限の付与 をご参照ください。
ステージに、コードで読み取られるファイルをコピーする。
PUT コマンドを使用して、ファイルをローカルドライブからステージにコピーできます。コマンドリファレンスについては、 PUT をご参照ください。PUT を使用したファイルのステージングについては、 ローカルファイルシステムからのデータファイルのステージング をご参照ください。
IMPORTS を使用したファイルの読み取り¶
CREATE FUNCTION コマンドの IMPORTS 句にファイル名とステージ名を指定することで、ファイルを読み込めます。
IMPORTS 句でファイルを指定すると、Snowflakeはそのファイルをステージから UDF の ホームディレクトリ (別称 インポートディレクトリ)にコピーします。UDF は、ホームディレクトリから実際にファイルを読み取ります。
インポートされたファイルは単一のディレクトリにコピーされ、そのディレクトリ内で一意の名前を付ける必要があるため、ファイルが異なるステージまたはステージ内の異なるサブディレクトリで開始された場合でも、 IMPORTS 句の各ファイルに異なる名前を付ける必要があります。
次の例では、ファイルを読み取るJava UDF を作成して呼び出します。
以下のJavaソースコードは、 readFile
という名前のJavaメソッドを作成します。この UDF はこのメソッドを使用します。
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
class TestReadRelativeFile {
public static String readFile(String fileName) throws IOException {
StringBuilder contentBuilder = new StringBuilder();
String importDirectory = System.getProperty("com.snowflake.import_directory");
String fPath = importDirectory + fileName;
Stream<String> stream = Files.lines(Paths.get(fPath), StandardCharsets.UTF_8);
stream.forEach(s -> contentBuilder.append(s).append("\n"));
return contentBuilder.toString();
}
}
次の SQL コードは UDF を作成します。このコードは、Javaソースコードがコンパイルされ、 UDF がインポートする TestReadRelativeFile.jar
という名前の JAR ファイルに配置されていることを前提としています。2番目と3番目のインポートされたファイル my_config_file_1.txt
と my_config_file_2.txt
は、 UDF が読み取ることができる構成ファイルです。
CREATE FUNCTION file_reader(file_name VARCHAR)
RETURNS VARCHAR
LANGUAGE JAVA
IMPORTS = ('@my_stage/my_package/TestReadRelativeFile.jar',
'@my_stage/my_path/my_config_file_1.txt',
'@my_stage/my_path/my_config_file_2.txt')
HANDLER = 'my_package.TestReadRelativeFile.readFile';
このコードは UDF を呼び出します。
SELECT file_reader('my_config_file_1.txt') ...;
...
SELECT file_reader('my_config_file_2.txt') ...;
圧縮形式または非圧縮形式のどちらでファイルにアクセスするかを選択¶
ステージ内のファイルは、圧縮形式または非圧縮形式で保存できます。ユーザーは、ファイルをステージにコピーする前に圧縮するか、 PUT コマンドにファイルを圧縮するように指示できます。
Snowflakeが GZIP 形式で圧縮されたファイルをステージから UDF ホームディレクトリにコピーする場合、Snowflakeはコピーをそのまま書き込むか、Snowflakeはファイルを書き込む前にコンテンツを解凍できます。
ステージ内のファイルが圧縮されていて、 UDF ホームディレクトリのコピーも圧縮する場合は、 IMPORTS 句でファイル名を指定するときに、元のファイル名(例:「MyData.txt.gz」)を IMPORTS サブ句で使用します。例:
... imports = ('@MyStage/MyData.txt.gz', ...)
ステージ内のファイルが GZIP 圧縮されているが、 UDF ホームディレクトリのコピーを解凍したい場合は、 IMPORTS 句でファイル名を指定するときに、「.gz」拡張子を省略します。たとえば、ステージに「MyData.txt.gz」が含まれているが、 UDF に非圧縮形式でファイルを読み取らせたい場合は、 IMPORTS 句に「MyData.txt」を指定します。「MyData.txt」という名前の非圧縮ファイルがまだない場合、Snowflakeは「MyData.txt.gz」を検索し、解凍したコピーを UDF ホームディレクトリの「MyData.txt」に自動で書き込みます。UDF は、圧縮されていないファイル「MyData.txt」を開いて読み取ることができます。
スマート解凍は、 UDF ホームディレクトリ内のコピーにのみ適用されます。ステージ内の元のファイルは変更されません。
圧縮ファイルを処理するための次のベストプラクティスに従ってください。
適切なファイル名の規則に従う。ファイルが GZIP 圧縮形式の場合は、ファイル名の末尾に拡張子「.gz」を含める。ファイルが GZIP 圧縮形式でない場合は、ファイル名を「.gz」拡張子で終わらせない。
拡張子「.gz」だけが異なる名前のファイルは作成しない。たとえば、同じステージとディレクトリに「MyData.txt」と「MyData.txt.gz」の両方を作成することや、「MyData.txt」と「MyData.txt.gz」の両方を CREATE FUNCTION コマンドにインポートすることは避けてください。
ファイルを2回圧縮しない。たとえば、ファイルを手動で圧縮した後、 AUTO_COMPRESS = FALSE を使用せずにそのファイルを PUT すると、ファイルはもう一度圧縮されます。スマート解凍では1回だけ解凍されるため、データ(または JAR)ファイルが UDF ホームディレクトリに保存されるときには、引き続き圧縮されたままになります。
将来、Snowflakeは、スマート解凍を GZIP 以外の圧縮アルゴリズムに拡張する可能性があります。将来の互換性の問題を防ぐために、これらのベストプラクティスを任意のタイプの圧縮を使用するファイルに適用してください。
注釈
JAR ファイルは、圧縮または非圧縮形式でステージに保存することもできます。Snowflakeは、圧縮されたすべての JAR ファイルを自動的に解凍してから、Java UDF で使用できるようにします。
SnowflakeFile
クラスを使用したファイルの読み取り¶
SnowflakeFile
クラスのメソッドを使用すると、Javaハンドラーコードを使用してステージからファイルを読み取ることができます。 SnowflakeFile
クラスは、SnowflakeのJava UDF ハンドラーが使用できるクラスパスに含まれています。
注釈
ファイルインジェクション攻撃に対するコードの回復性を高めるには、ファイルの場所を UDF に渡す場合、特に関数の呼び出し元がその所有者でもない場合に、スコープ URL を常に使用します。組み込み関数 build_scoped_file_url
を使用して、スコープ URL を SQL に作成できます。 build_scoped_file_url
の機能の詳細については、 非構造化データサポートの概要 をご参照ください。
UDF コードをローカルで開発するには、 SnowflakeFile
を含んでいるSnowpark JAR をコードのクラスパスに追加します。 snowpark.jar
については、 Snowpark Javaの開発環境の設定 をご参照ください。Snowparkクライアントアプリケーションでは、このクラスを使用できないことに注意してください。したがって、クラスはSnowparkトピックに文書化されていません。
SnowflakeFile
を使用する場合は、 SQL で CREATE FUNCTION ステートメントを使用する場合のように、 UDF の作成時に、ステージングされたファイル、または SnowflakeFile
を含んでいる JAR のいずれかを IMPORTS 句で指定する必要はありません。
SnowflakeFile
クラスには次のメソッドがあります。
メソッド |
説明 |
---|---|
|
|
|
ファイルのコンテンツを読み取るための |
|
ファイルのサイズを返します。 |
次の例のコードは、 SnowflakeFile
を使用して、指定されたステージの場所からファイルを読み取ります。 getInputStream
メソッドの InputStream
を使用して、ファイルの内容を String
変数に読み込みます。
create or replace function sum_total_sales(file string)
returns INTEGER
language java
handler='SalesSum.sumTotalSales'
target_path='@jar_stage/sales_functions2.jar'
as
$$
import java.io.InputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import com.snowflake.snowpark_java.types.SnowflakeFile;
public class SalesSum {
public static int sumTotalSales(String filePath) throws IOException {
int total = -1;
// Use a SnowflakeFile instance to read sales data from a stage.
SnowflakeFile file = SnowflakeFile.newInstance(filePath);
InputStream stream = file.getInputStream();
String contents = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
// Omitted for brevity: code to retrieve sales data from JSON and assign it to the total variable.
return total;
}
}
$$;
UDF を呼び出してスコープ URL でファイルの場所を渡し、ファイルインジェクション攻撃の可能性を減らします。
select sum_total_sales(build_scoped_file_url('@sales_data_stage', '/car_sales.json'));
InputStream
クラスを使用したファイルの読み取り¶
ハンドラー関数の引数を InputStream
変数にすると、ファイルの内容を直接 java.io.InputStream
に読み込むことができます。これは、関数の呼び出し元が引数としてファイルパスを渡す場合に役立ちます。
注釈
ファイルインジェクション攻撃に対するコードの回復性を高めるには、ファイルの場所を UDF に渡す場合、特に関数の呼び出し元がその所有者でもない場合に、スコープ URL を常に使用します。組み込み関数 build_scoped_file_url
を使用して、スコープ URL を SQL に作成できます。 build_scoped_file_url
の機能の詳細については、 非構造化データサポートの概要 をご参照ください。
次の例のコードには、 InputStream
を受け取り、 int
を返すハンドラー関数 sumTotalSales
があります。実行時に、Snowflakeは file
変数のパスにあるファイルの内容を stream
引数変数に自動で割り当てます。
create or replace function sum_total_sales(file string)
returns INTEGER
language java
handler='SalesSum.sumTotalSales'
target_path='@jar_stage/sales_functions2.jar'
as
$$
import java.io.InputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class SalesSum {
public static int sumTotalSales(InputStream stream) throws IOException {
int total = -1;
String contents = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
// Omitted for brevity: code to retrieve sales data from JSON and assign it to the total variable.
return total;
}
}
$$;
UDF を呼び出してスコープ URL でファイルの場所を渡し、ファイルインジェクション攻撃の可能性を減らします。
select sum_total_sales(build_scoped_file_url('@sales_data_stage', '/car_sales.json'));
ステージングされた簡単なJava UDF の作成と呼び出し¶
次のステートメントは、単純なJava UDF を作成します。このサンプルは通常、 ファイルの整理 で説明されているファイルとディレクトリの構造に従います。
Javaハンドラーコードを作成しコンパイルする¶
プロジェクトのルートディレクトリ(ここでは
my_udf
)に、ソース.javaファイルを保持するsrc
サブディレクトリと、生成された.classファイルを保持するclasses
サブディレクトリを作成します。次のようなディレクトリ階層が必要です。
my_udf/ |-- classes/ |-- src/
src
ディレクトリに、クラスがmypackage
パッケージにある.javaファイルを保持する、mypackage
というディレクトリを作成します。mypackage
ディレクトリに、ソースコードを含むMyUDFHandler.java
ファイルを作成します。package mypackage; public class MyUDFHandler { public static int decrementValue(int i) { return i - 1; } public static void main(String[] argv) { System.out.println("This main() function won't be called."); } }
プロジェクトのルートディレクトリ(ここでは
my_udf
)から、javac
コマンドを使用してソースコードをコンパイルします。次の例の
javac
コマンドは、MyUDFHandler.java
をコンパイルして、classes
ディレクトリにMyUDFHandler.class
ファイルを生成します。javac -d classes src/mypackage/MyUDFHandler.java
この例には、次の引数が含まれています。
-d classes
--- 生成されたクラスファイルを書き込むディレクトリ。src/mypackage/MyUDFHandler.java
--- .javaファイルへのsource_directory/package_directory/Java_file_name
形式のパス。
コンパイルされたコードを JAR ファイルにパッケージ化する¶
オプションで、プロジェクトのルートディレクトリに、次の属性を含む
my_udf.manifest
という名前のマニフェストファイルを作成します。Manifest-Version: 1.0 Main-Class: mypackage.MyUDFHandler
プロジェクトのルートディレクトリから、
jar
コマンドを実行して、.classファイルとマニフェストを含む JAR ファイルを作成します。次の例の
jar
コマンドは、mypackage
パッケージフォルダーに生成されたMyUDFHandler.class
ファイルをmy_udf.jar
という.jarファイルに配置します。-C ./classes
フラグは、.classファイルの場所を指定します。jar cmf my_udf.manifest my_udf.jar -C ./classes mypackage/MyUDFHandler.class
この例には、次の引数が含まれています。
cmf
--- コマンド引数:c
は JAR ファイルを作成し、m
は指定された.manifestファイルを使用し、f
は JAR ファイルに指定された名前を付けます。my_udf.manifest
--- マニフェストファイル。my_udf.jar
--- 作成する JAR ファイルの名前。-C ./classes
--- 生成された.classファイルを含むディレクトリ。mypackage/MyUDFHandler.class
--- JAR に含める.classファイルのパッケージと名前。
コンパイルされたハンドラーを使用して JAR ファイルをステージにアップロードする¶
Snowflakeで、 UDF ハンドラーを含む JAR ファイルを保存するために、
jar_stage
というステージを作成します。ステージの作成の詳細については、 CREATE STAGE をご参照ください。
PUT
コマンドを使用して、 JAR ファイルをローカルファイルシステムからステージにコピーします。
put file:///Users/Me/my_udf/my_udf.jar @jar_stage auto_compress = false overwrite = true ;
PUT
コマンドをスクリプトファイルに保存してから、 SnowSQL を介してそのファイルを実行できます。
snowsql
コマンドは次のようになります。snowsql -a <account_identifier> -w <warehouse> -d <database> -s <schema> -u <user> -f put_command.sqlこの例では、ユーザーのパスワードが SNOWSQL_PWD 環境変数で指定されていることを前提としています。
コンパイルされたコードをハンドラーとして UDF を作成する¶
UDF を作成します。
create function decrement_value(i numeric(9, 0))
returns numeric
language java
imports = ('@jar_stage/my_udf.jar')
handler = 'mypackage.MyUDFHandler.decrementValue'
;
UDF を呼び出します。
select decrement_value(-15);
+----------------------+
| DECREMENT_VALUE(-15) |
|----------------------|
| -16 |
+----------------------+
考慮事項¶
クエリが UDF を呼び出してステージングされたファイルにアクセスする場合に、 SQL ステートメントが いずれか の UDF またはUDTF を呼び出すビューもクエリすると、ビューにある関数がステージングされたファイルにアクセスするかどうかにかかわらず、操作に失敗してユーザーエラーが発生します。
UDTFs 複数のファイルを並行して処理できます。ただし、 UDFs は現在、ファイルをシリアルに処理しています。回避策として、 GROUP BY 句を使用してサブクエリの行をグループ化します。例については、 Java UDTF の例 をご参照ください。
現在、クエリで参照されているステージングされたファイルが、クエリの実行中に変更または削除された場合、関数の呼び出しはエラーを発生して失敗します。