Java UDFs での一般的な操作

このトピックでは、Java UDFs がファイル(例: 構成ファイル)からの読み取りなどの一般的な操作を実行する方法を示します。

このトピックの内容:

Java UDF 内からのファイルの読み取り

ファイルを読み取るためのサンプルコード

Java UDF は、 ステージ に保存されているファイル(例: 構成ファイル)を読み取ることができます。ファイル名とステージ名は、 CREATE FUNCTION コマンドの IMPORTS 句で指定されている必要があります。

UDF の IMPORTS 句でファイルが指定されている場合、Snowflakeはそのファイルをステージから UDF の ホームディレクトリ (別称 インポートディレクトリ)にコピーします。UDF は、ホームディレクトリから実際にファイルを読み取ります。

インポートされたファイルは単一のディレクトリにコピーされ、そのディレクトリ内で一意の名前を付ける必要があるため、ファイルが異なるステージまたはステージ内の異なるサブディレクトリで開始された場合でも、 IMPORTS 句の各ファイルに異なる名前を付ける必要があります。

次の例では、ファイルを読み取るJava UDF を作成して呼び出します。

以下のJavaソースコードは、 read_file() という名前の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 read_file(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.txtmy_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.read_file';

このコードは 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 すると、ファイルは2回圧縮されます。スマート解凍では1回だけ解凍されるため、データ(または JAR)ファイルが UDF ホームディレクトリに保存されるときには、引き続き圧縮されたままになります。

  • 将来、Snowflakeは、スマート解凍を GZIP 以外の圧縮アルゴリズムに拡張する可能性があります。将来の互換性の問題を防ぐために、これらのベストプラクティスを任意のタイプの圧縮を使用するファイルに適用してください。

注釈

JAR ファイルは、圧縮または非圧縮形式でステージに保存することもできます。Snowflakeは、圧縮されたすべての JAR ファイルを自動的に解凍してから、Java UDF で使用できるようにします。