JavaScript UDF の制限

Snowflake環境内での安定性を確保するため、Snowflakeは JavaScript UDFs に以下の制限を設けています。これらの制限は、 UDF の作成時ではなく、 UDF が呼び出され、実行された時に適用されます。このトピックでは、一般的な JavaScript UDF (ユーザー定義関数)要件と使用方法の詳細、および JavaScript UDFs に固有の制限について説明します。

このトピックの内容:

JavaScript ソースコードの最大サイズ

Snowflakeは、 JavaScript UDF の本文にある JavaScript ソースコードの最大サイズを制限します。Snowflakeは、サイズを100 KB に制限することをお勧めします。(コードは圧縮された形式で保存され、正確な制限はコードの圧縮率によって異なります。)

メモリの過剰消費により、 UDF が失敗する

JavaScript UDFs は、メモリを過剰消費すると失敗します。具体的な上限は変更される可能性があります。メモリの使用量が多すぎると、エラーが返されます。

完了までに時間がかかりすぎると、 UDF は強制終了してエラーを返す

完了するのに時間がかかりすぎる JavaScript UDFs は強制終了され、ユーザーにエラーが返されます。加えて、無限ループに入る JavaScript UDFs はエラーになります。

スタック深度を超過するとエラーになる

再帰による過度のスタック深度はエラーになります。

グローバルステート

Snowflakeは通常、 UDF の反復間で JavaScript グローバル状態を維持します。ただし、関数呼び出し間で利用可能なグローバル状態に対する以前の変更には依存しないでください。さらに、すべての行が同じ JavaScript 環境内で実行されると決めてかからないようにしてください。

実際には、グローバル状態は次に関連しています。

  • 複雑/高価な初期化ロジック。デフォルトでは、プロバイダーから提供された UDF コードが、行の処理ごとに評価されます。そのコードに複雑なロジックが含まれている場合は、非効率的になる可能性があります。

  • べき等ではないコードを含む関数。典型的なパターンは次のとおりです。

    Date.prototype._originalToString = Date.prototype.toString;
    Date.prototype.toString = function() {
      /* ... SOME CUSTOM CODE ... */
      this._originalToString()
      }
    
    Copy

    このコードが初めて実行されると、 toString_originalToString の状態が変更されます。これらの変更は、グローバル状態で保持され、このコードが2回目に実行されると、値が再帰を作成する方法で再び変更されます。2回目に toString が呼び出されると、コードは無限に再帰します(スタック領域がなくなるまで)。

これらの状況で推奨されるパターンは、 JavaScript のグローバル変数セマンティクスを使用して、関連するコードが1回だけ評価されることを保証することです。たとえば、

var setup = function() {
/* SETUP LOGIC */
};

if (typeof(setup_done) === "undefined") {
  setup();
  setup_done = true;  // setting global variable to true
}
Copy

このメカニズムは、コード評価の効果をキャッシュする場合にのみ安全であることに注意してください。初期化後、すべての行でグローバルコンテキストが保持されることは保証されず、いずれのビジネスロジックもこれに依存すべきではありません。

JavaScript ライブラリ

JavaScript UDFs ストアドプロシージャは、標準 JavaScript ライブラリへのアクセスをサポートします。これにより、ブラウザーが通常提供する多くのオブジェクトとメソッドが除外されます。追加のライブラリをインポートしたり、含めたり、呼び出したりするメカニズムはありません。すべての必要なコードは UDF 内に埋め込まれている必要があります。

また、組み込みの JavaScript eval() 関数は無効になっています。

返されるバリアントのサイズと深度

返されるバリアントオブジェクトには、サイズと入れ子の深度の制限があります。

サイズ:

現在、数メガバイトに制限されていますが、変更される可能性があります。

深度:

現在、ネストの深度は1000に制限されていますが、変更される可能性があります。

オブジェクトが大きすぎるか深すぎる場合、 UDF が呼び出されたときにエラーが返されます。

引数および戻り型の制約が無視される場合がある

引数や戻り値に対して宣言された特定の型特性は、 UDF が呼び出されたときに無視されます。こうした場合は、宣言で指定された制約に適合しているか否かにかかわらず、受信した値をそのまま使用することができます。

JavaScript でロジックが記述されている UDFs については、以下が無視されます。

  • VARCHAR 型の引数の長さ

次の例のコードでは 、 arg1 引数と戻り値は、1文字以下の VARCHAR でなければならないと宣言しています。ただし、 arg1 の値が1文字よりも長い場合にこの関数を呼び出すと、制約が指定されていないかのように成功します。

CREATE OR REPLACE FUNCTION tf (arg1 VARCHAR(1))
RETURNS VARCHAR(1)
LANGUAGE JAVASCRIPT AS 'return A.substr(3, 3);';
Copy