SnowConvert AI :Oracle HELPERS¶
このセクションでは、Snowflakeスクリプトでネイティブにサポートされていない一部のOracle機能と同等の機能を実現するために使用されるヘルパー関数やプロシージャを紹介します。
一括カーソルヘルパー¶
注釈
また、[デフォルト FORALL 変換](README.md#forall)にも興味深いかもしれません。
カーソルは、カーソルの状態に関するさまざまな情報を持つ OBJECT でシミュレートされます。カーソルのクエリの結果セットを格納する仮テーブルが作成されます。
これらのプロシージャのほとんどは、カーソルの状態を更新した新しいオブジェクトを返します。
INIT_CURSOR¶
この関数は、基本的なカーソル情報を持つ新しいオブジェクトを初期化します
CREATE OR REPLACE FUNCTION INIT_CURSOR(NAME VARCHAR, QUERY VARCHAR)
RETURNS OBJECT
AS
$$
SELECT OBJECT_CONSTRUCT('NAME', NAME, 'ROWCOUNT', -1, 'QUERY', QUERY, 'ISOPEN', FALSE, 'FOUND', NULL, 'NOTFOUND', NULL)
$$;
OPEN_BULK_CURSOR¶
これらのプロシージャは、カーソルのクエリで仮テーブルを作成します。バインディングをサポートするオプションのオーバーロードがあります。
CREATE OR REPLACE PROCEDURE OPEN_BULK_CURSOR(CURSOR OBJECT, BINDINGS ARRAY)
RETURNS OBJECT
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
var query = `CREATE OR REPLACE TEMPORARY TABLE ${CURSOR.NAME}_TEMP_TABLE AS ${CURSOR.QUERY}`;
snowflake.execute({ sqlText: query, binds: BINDINGS });
CURSOR.ROWCOUNT = 0;
CURSOR.ISOPEN = true;
return CURSOR;
$$;
CREATE OR REPLACE PROCEDURE OPEN_BULK_CURSOR(CURSOR OBJECT)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
RESULT OBJECT;
BEGIN
RESULT := (CALL OPEN_BULK_CURSOR(:CURSOR, NULL));
RETURN :RESULT;
END;
$$;
CLOSE_BULK_CURSOR¶
このプロシージャは、カーソルの結果セットを格納していた仮テーブルを削除し、カーソルのプロパティを初期状態にリセットします。
CREATE OR REPLACE PROCEDURE CLOSE_BULK_CURSOR(CURSOR OBJECT)
RETURNS OBJECT
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
var query = `DROP TABLE ${CURSOR.NAME}_TEMP_TABLE`;
snowflake.execute({ sqlText: query });
CURSOR.ROWCOUNT = -1;
CURSOR.ISOPEN = false;
CURSOR.FOUND = null;
CURSOR.NOTFOUND = null;
return CURSOR;
$$;
FETCH ヘルパー¶
Oracleは様々な種類のシナリオに対して FETCH ステートメントを実行することができるため、それぞれのケースを処理するためにオーバーロードを持つ複数のプロシージャが作成されました。これらのヘルパーは、取得した値を CURSOR オブジェクトの RESULT プロパティに保存します。
オーバーロードの中には、 LIMIT 句を使用した場合と使用しなかった場合のバリエーションがあります。他のオーバーロードは、 FETCH ステートメントが、クエリの列名と異なる列名の記録を持つ、または含む変数に対して実行される場合に必要な、 COLUMN_NAMES 引数を持ちます。
FETCH_BULK_COLLECTION_RECORDS¶
これらのプロシージャは、 FETCH BULK が記録のコレクションに行われる場合に使用されます。
CREATE OR REPLACE PROCEDURE FETCH_BULK_COLLECTION_RECORDS(CURSOR OBJECT, LIMIT FLOAT, COLUMN_NAMES ARRAY)
RETURNS OBJECT
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
var objectConstructArgs = [];
if (COLUMN_NAMES) {
for (let i = 0 ; i < COLUMN_NAMES.length ; i++) {
objectConstructArgs.push("'" + COLUMN_NAMES[i] + "'");
objectConstructArgs.push('$' + (i + 1));
}
} else {
objectConstructArgs.push('*');
}
var limitValue = LIMIT ?? 'NULL';
var query = `SELECT ARRAY_AGG(OBJECT_CONSTRUCT(${objectConstructArgs.join(', ')})) FROM (SELECT * FROM ${CURSOR.NAME}_TEMP_TABLE LIMIT ${limitValue} OFFSET ${CURSOR.ROWCOUNT})`;
var stmt = snowflake.createStatement({ sqlText: query});
var resultSet = stmt.execute();
resultSet.next();
CURSOR.RESULT = resultSet.getColumnValue(1);
CURSOR.ROWCOUNT += CURSOR.RESULT.length;
CURSOR.FOUND = CURSOR.RESULT.length > 0;
CURSOR.NOTFOUND = !CURSOR.FOUND;
return CURSOR;
$$;
CREATE OR REPLACE PROCEDURE FETCH_BULK_COLLECTION_RECORDS(CURSOR OBJECT)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
RESULT OBJECT;
BEGIN
RESULT := (CALL FETCH_BULK_COLLECTION_RECORDS(:CURSOR, NULL, NULL));
RETURN :RESULT;
END;
$$;
CREATE OR REPLACE PROCEDURE FETCH_BULK_COLLECTION_RECORDS(CURSOR OBJECT, LIMIT INTEGER)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
RESULT OBJECT;
BEGIN
RESULT := (CALL FETCH_BULK_COLLECTION_RECORDS(:CURSOR, :LIMIT, NULL));
RETURN :RESULT;
END;
$$;
CREATE OR REPLACE PROCEDURE FETCH_BULK_COLLECTION_RECORDS(CURSOR OBJECT, COLUMN_NAMES ARRAY)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
RESULT OBJECT;
BEGIN
RESULT := (CALL FETCH_BULK_COLLECTION_RECORDS(:CURSOR, NULL, :COLUMN_NAMES));
RETURN :RESULT;
END;
$$;
FETCH_BULK_COLLECTIONS¶
これらのプロシージャは、 FETCH ステートメントが1つまたは複数のコレクションに行われる場合に使用されます。列はこの FETCH 操作で指定されるので、特定の COLUMN_NAMES に対するオーバーライドは必要ありません。
CREATE OR REPLACE PROCEDURE FETCH_BULK_COLLECTIONS(CURSOR OBJECT, LIMIT FLOAT)
RETURNS OBJECT
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
var limitClause = '';
var limitValue = LIMIT ?? 'NULL';
var query = `SELECT * FROM ${CURSOR.NAME}_TEMP_TABLE LIMIT ${limitValue} OFFSET ${CURSOR.ROWCOUNT}`;
var stmt = snowflake.createStatement({ sqlText: query});
var resultSet = stmt.execute();
var column_count = stmt.getColumnCount();
CURSOR.RESULT = [];
for (let i = 0 ; i < column_count ; i++) {
CURSOR.RESULT[i] = [];
}
while (resultSet.next()) {
for (let i = 1 ; i <= column_count ; i++) {
let columnName = stmt.getColumnName(i);
CURSOR.RESULT[i - 1].push(resultSet.getColumnValue(columnName));
}
}
CURSOR.ROWCOUNT += stmt.getRowCount();
CURSOR.FOUND = stmt.getRowCount() > 0;
CURSOR.NOTFOUND = !CURSOR.FOUND;
return CURSOR;
$$;
CREATE OR REPLACE PROCEDURE FETCH_BULK_COLLECTIONS(CURSOR OBJECT)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
RESULT OBJECT;
BEGIN
RESULT := (CALL FETCH_BULK_COLLECTIONS(:CURSOR, NULL));
RETURN :RESULT;
END;
$$;
FETCH_BULK_RECORD_COLLECTIONS¶
これらのプロシージャは、 FETCH BULK がコレクションの記録に行われる場合に使用されます。
CREATE OR REPLACE PROCEDURE FETCH_BULK_RECORD_COLLECTIONS(CURSOR OBJECT, LIMIT FLOAT, COLUMN_NAMES ARRAY)
RETURNS OBJECT
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
var limitValue = LIMIT ?? 'NULL';
var query = `SELECT * FROM ${CURSOR.NAME}_TEMP_TABLE LIMIT ${limitValue} OFFSET ${CURSOR.ROWCOUNT}`;
var stmt = snowflake.createStatement({ sqlText: query});
var resultSet = stmt.execute();
var column_count = stmt.getColumnCount();
CURSOR.RESULT = {};
if (COLUMN_NAMES)
{
for (let i = 0 ; i < COLUMN_NAMES.length ; i++) {
CURSOR.RESULT[COLUMN_NAMES[i]] = [];
}
} else {
for (let i = 1 ; i <= column_count ; i++) {
let columnName = stmt.getColumnName(i);
CURSOR.RESULT[columnName] = [];
}
}
while (resultSet.next()) {
for (let i = 1 ; i <= column_count ; i++) {
let columnName = stmt.getColumnName(i);
let fieldName = COLUMN_NAMES ? COLUMN_NAMES[i - 1] : columnName;
CURSOR.RESULT[fieldName].push(resultSet.getColumnValue(columnName));
}
}
CURSOR.ROWCOUNT += stmt.getRowCount();
CURSOR.FOUND = stmt.getRowCount() > 0;
CURSOR.NOTFOUND = !CURSOR.FOUND;
return CURSOR;
$$;
CREATE OR REPLACE PROCEDURE FETCH_BULK_RECORD_COLLECTIONS(CURSOR OBJECT)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
RESULT OBJECT;
BEGIN
RESULT := (CALL FETCH_BULK_RECORD_COLLECTIONS(:CURSOR, NULL, NULL));
RETURN :RESULT;
END;
$$;
CREATE OR REPLACE PROCEDURE FETCH_BULK_RECORD_COLLECTIONS(CURSOR OBJECT, LIMIT INTEGER)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
RESULT OBJECT;
BEGIN
RESULT := (CALL FETCH_BULK_RECORD_COLLECTIONS(:CURSOR, :LIMIT, NULL));
RETURN :RESULT;
END;
$$;
CREATE OR REPLACE PROCEDURE FETCH_BULK_RECORD_COLLECTIONS(CURSOR OBJECT, COLUMN_NAMES ARRAY)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
RESULT OBJECT;
BEGIN
RESULT := (CALL FETCH_BULK_RECORD_COLLECTIONS(:CURSOR, NULL, :COLUMN_NAMES));
RETURN :RESULT;
END;
$$;