SnowConvert AI : Teradata -SnowConvert AI プロシージャヘルパー¶
このセクションでは、Snowflakeでネイティブにサポートされていない一部のTeradata機能と同等の機能を実現するために使用されるプロシージャ内で仕様されるヘルパー関数について説明します。
Cursorヘルパー¶
このセクションでは、JavaScript におけるTeradataカーソルの機能的等価性を実現するためのさまざまな関数の使用法について説明します。
Cursorヘルパーは、Open、Fetch、Next、CloseのようなTeradataカーソルが実行する主な4つのアクションを含む関数です。
CURSOR(), は、必要な変数と他のサブルーチンを宣言するメインルーチンです。
OPEN(), は、与えられたステートメントを実行するカーソルを開き、必要な変数を更新します。
NEXT(), は、ステートメントの次の行(ある場合)にカーソルを移動し、すべての列の値を現在の行にセットします。
FETCH(), は、実行されたステートメントのレスポンスから値(ある場合)を取得します。
CLOSE(), は、_OUTQUERIES (EXEC ヘルパーで追加された場合)から仮テーブルを削除し、必要な変数をアンセットします。
注釈
わかりやすくするため、出力コードの一部を省略しています。
Cursorサンプル使用¶
Teradata
-- Additional Params: -t JavaScript
Replace procedure procedure1()
dynamic result sets 2
begin
-------- Local variables --------
declare sql_cmd varchar(20000) default ' ';
declare num_cols integer;
------- Declare cursor with return only-------
declare resultset cursor with return only for firststatement;
------- Declare cursor -------
declare cur2 cursor for select count(columnname) from table1;
-------- Set --------
set sql_cmd='sel * from table1';
-------- Prepare cursor --------
prepare firststatement from sql_cmd;
-------- Open cursors --------
open resultset;
open cur1;
-------- Fetch -------------
fetch cur1 into val1, val2;
-------- Close cursor --------
close cur1;
end;
Snowflakeの出力
CREATE OR REPLACE PROCEDURE procedure1 ()
RETURNS STRING
LANGUAGE JAVASCRIPT
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"teradata"}}'
EXECUTE AS CALLER
AS
$$
// SnowConvert AI Helpers Code section is omitted.
//------ Local variables --------
var SQL_CMD = ` `;
var NUM_COLS;
var RESULTSET = new CURSOR(() => FIRSTSTATEMENT,[],true);
//----- Declare cursor -------
var CUR2 = new CURSOR(`SELECT
COUNT(columnname)
from
table1`,[],false);
//------ Set --------
SQL_CMD = `SELECT
* from
table1`;
//------ Prepare cursor --------
var FIRSTSTATEMENT = SQL_CMD;
//------ Open cursors --------
RESULTSET.OPEN();
CUR1.OPEN();
//------ Fetch -------------
CUR1.FETCH() && ([val1,val2] = CUR1.INTO());
//------ Close cursor --------
CUR1.CLOSE();
return PROCRESULTS();
$$;
Cursorヘルパー関数の定義¶
var CURSOR = function (stmt,binds,withReturn) {
var rs, rows, row_count, opened = false, resultsetTable = '', self = this;
this.CURRENT = new Object;
this.INTO = function () {
return self.res;
};
this.OPEN = function (usingParams) {
try {
if (usingParams) binds = usingParams;
if (binds instanceof Function) binds = binds();
var finalBinds = binds && binds.map(fixBind);
var finalStmt = stmt instanceof Function ? stmt() : stmt;
if (withReturn) {
resultsetTable = EXEC(finalStmt,finalBinds,true,null,{
temp : true
});
finalStmt = `SELECT * FROM TABLE(RESULT_SCAN('${resultsetTable}'))`;
finalBinds = [];
}
rs = snowflake.createStatement({
sqlText : finalStmt,
binds : finalBinds
});
rows = rs.execute();
row_count = rs.getRowCount();
ACTIVITY_COUNT = rs.getRowCount();
opened = true;
return this;
} catch(error) {
ERROR_HANDLERS && ERROR_HANDLERS(error);
}
};
this.NEXT = function () {
if (row_count && rows.next()) {
this.CURRENT = new Object;
for(let i = 1;i <= rs.getColumnCount();i++) {
(this.CURRENT)[rs.getColumnName(i)] = rows.getColumnValue(i);
}
return true;
} else return false;
};
this.FETCH = function () {
self.res = [];
self.res = fetch(row_count,rows,rs);
if (opened) if (self.res.length > 0) {
SQLCODE = 0;
SQLSTATE = '00000';
} else {
SQLCODE = 7362;
SQLSTATE = '02000';
var fetchError = new Error('There are not rows in the response');
fetchError.code = SQLCODE;
fetchError.state = SQLSTATE;
if (ERROR_HANDLERS) ERROR_HANDLERS(fetchError);
} else {
SQLCODE = 7631;
SQLSTATE = '24501';
}
return self.res && self.res.length > 0;
};
this.CLOSE = function () {
if (withReturn && _OUTQUERIES.includes(resultsetTable)) {
_OUTQUERIES.splice(_OUTQUERIES.indexOf(resultsetTable),1);
}
rs = rows = row_count = undefined;
opened = false;
resultsetTable = '';
};
};
既知の問題¶
問題は見つかりませんでした。
Execヘルパー¶
execヘルパーは、プロシージャ内の SQL ステートメントを実行するための関数です。
構文¶
EXEC(stmt)
EXEC(stmt, binds)
EXEC(stmt, binds, noCatch)
EXEC(stmt, binds, noCatch, catchFunction)
EXEC(stmt, binds, noCatch, catchFunction, opts)
パラメーター¶
stmt¶
実行する SQL ステートメントの文字列。
binds(オプション)¶
SQL ステートメントにバインドする値または変数を含む配列。
NoCatch (オプション)¶
エラーをキャッチしないかどうかを示すブール。
catchFunction(オプション)¶
exec関数の実行中にエラーが発生した場合に実行する関数。
opts(オプション)¶
クエリ ID が返されるべきかどうかを知るための JSON オブジェクト({ temp : true })。
FixBind および FormatDate 関数¶
Execヘルパーは、 FixBind というヘルパーで定義された関数を使用します。この関数は、バインド変数の1つが日付タイプであることを検出したときに、 FormatDate 関数を使用します。これは、Snowflakeで日付タイプを適切に管理するために行われます。\ 両方の関数は以下のように定義されています。
var formatDate = (arg) => (new Date(arg - (arg.getTimezoneOffset() * 60000))).toISOString().slice(0,-1);
var fixBind = function (arg) {
arg = arg == undefined ? null : arg instanceof Date ? formatDate(arg) : arg;
return arg;
};
注釈
わかりやすくするため、出力コードの一部を省略しています。
Exec使用サンプル¶
Teradata
-- Additional Params: -t JavaScript
REPLACE PROCEDURE ProcedureSample ()
BEGIN
case value
when 0 then
select * from table1
else
update table1 set name = "SpecificValue" where id = value;
end case
END;
Snowflakeの出力
CREATE OR REPLACE PROCEDURE ProcedureSample ()
RETURNS STRING
LANGUAGE JAVASCRIPT
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"teradata"}}'
EXECUTE AS CALLER
AS
$$
// SnowConvert AI Helpers Code section is omitted.
switch(value) {
case 0:EXEC(`SELECT * from table1`,[]);
break;
default:EXEC(`UPDATE table1
set
name = "SpecificValue"
where
id = value`,[]);
break;
}
$$;
Execヘルパーの定義¶
var EXEC = function (stmt,binds,noCatch,catchFunction,opts) {
try {
binds = binds ? binds.map(fixBind) : binds;
_RS = snowflake.createStatement({
sqlText : stmt,
binds : binds
});
_ROWS = _RS.execute();
ROW_COUNT = _RS.getRowCount();
ACTIVITY_COUNT = _RS.getNumRowsAffected();
HANDLE_NOTFOUND && HANDLE_NOTFOUND(_RS);
if (INTO) return {
INTO : function () {
return INTO();
}
};
if (_OUTQUERIES.length < DYNAMIC_RESULTS) _OUTQUERIES.push(_ROWS.getQueryId());
if (opts && opts.temp) return _ROWS.getQueryId();
} catch(error) {
MESSAGE_TEXT = error.message;
SQLCODE = error.code;
SQLSTATE = error.state;
var msg = `ERROR CODE: ${SQLCODE} SQLSTATE: ${SQLSTATE} MESSAGE: ${MESSAGE_TEXT}`;
if (catchFunction) catchFunction(error);
if (!noCatch && ERROR_HANDLERS) ERROR_HANDLERS(error); else throw new Error(msg);
}
};
既知の問題¶
問題は見つかりませんでした。
関連 EWIs ¶
関連 EWIs はありません。
機能的等価性ヘルパー¶
Teradata言語のいくつかの機能をよりよくサポートするために、SnowFlake のプロシージャが使用できる、JavaScript のヘルパー関数のリスト。
Teradataの各ストアドプロシージャの内容に応じて、SnowConvert AI は、その中に以下の一つ以上のjavascript関数を作成します。
CompareDates¶
無効を扱う日付を比較する関数です。Javascriptでは、日付の比較のために .getTime() を呼び出す必要があります。
var CompareDates = function(value1, value2) {
var value1Time = value1 && value1.getTime() || null;
var value2Time = value2 && value2.getTime() || null;
if (value1Time == null && value2Time == null) return null; /*in SQL null == null is equal to null as well as any other comparison */
return value1Time > value2Time? 1 : value1Time<value2Time? -1 : 0;
}
BetweenFunc¶
Teradata の BETWEEN ステートメントを処理する関数です。
var BetweenFunc = function (expression,startExpr,endExpr) {
if ([expression,startExpr,endExpr].some((arg) => arg == null)) {
return false;
}
return expression >= startExpr && expression <= endExpr;
};
LikeFunction()¶
Teradata の LIKE ステートメントを処理する関数です。
var likeFunction = function (leftExpr,rightExpr) {
RegExp.escape = function (text) {
if (!arguments.callee.sRE) {
var specials = ['/','.','*','+','?','|','(',')','[',']','{','}','\\'];
arguments.callee.sRE = new RegExp('(\\' + specials.join('|\\') + ')','g');
}
return text.replace(arguments.callee.sRE,'\\$1');
}
var likeExpr = RegExp.escape(rightExpr);
var likeResult = new RegExp(likeExpr.replace('%','.*').replace('_','.')).exec(leftExpr) != null;
return likeResult;
};
ERROR_HANDLERS()¶
主なエラー処理ルーチン。
var continue_handler_1 = function (error) {
{
V_SQL_VALUE = SQLSTATE;
V_EXCEPTION_FLAG = `Y`;
}
};
// Main error-handling routine
var ERROR_HANDLERS = function (error) {
switch(error.state) {
//Conversion Warning - handlers for the switch default (SQLWARNING/SQLEXCEPTION/NOT FOUND) can be the following
default:continue_handler_1(error);
}
};
INSERT_TEMP¶
警告
_ このヘルパーはバージョン2.0.15以降、ストアドプロシージャでは非推奨となりました。 _
引数 query と与えられた parameters を使用して仮テーブルを作成する関数です。
var procname = `PUBLIC.Procedure1`;
var temptable_prefix, tablelist = [];
var INSERT_TEMP = function (query,parameters) {
if (!temptable_prefix) {
var sql_stmt = `select current_session() || '_' || to_varchar(current_timestamp, 'yyyymmddhh24missss')`;
var rs = snowflake.createStatement({
sqlText : sql_stmt,
binds : []
}).execute();
temptable_prefix = rs.next() && (procname + '_TEMP_' + rs.getColumnValue(1) + '_');
}
var tablename = temptable_prefix + tablelist.length;
tablelist.push(tablename);
var sql_stmt = `CREATE OR REPLACE TEMPORARY TABLE ${tablename} AS ${query}`;
snowflake.execute({
sqlText : sql_stmt,
binds : parameters
});
return tablename;
};
IS_NOT_FOUND()¶
SELECT が値を返さないか、文が0行に影響するかどうかを検証する関数です。これは、Teradataと同じ動作をエミュレートするためで、 NOT FOUND EXCEPTIONS の終了ハンドラーや継続ハンドラーがある場合です。
let IS_NOT_FOUND = (stmt) => {
let n = -1;
let cmd = stmt.getSqlText().replace(new RegExp("\\/\\*.*\\*\\/","gsi"),"").replace(new RegExp("--.*?\\n","gsi"),"");
let matched = cmd.match(new RegExp("\\s*(\\w+)\\s+"),"");
if (matched) {
cmd = matched[1].toUpperCase();
switch(cmd) {
case "CALL":
case "DROP":
case "CREATE":
case "ALTER":
case "SELECT":
n = stmt.getRowCount();
break;
default:n = stmt.getNumRowsAffected();
break;
}
}
return n == 0;
};
HANDLE_NOTFOUND()¶
この関数は、上記の IS_NOT_FOUND 関数を使用して、人為的なエラー'NOT FOUND'がスローされているかどうかを検証します。
let HANDLE_NOTFOUND = (stmt) => {
if (IS_NOT_FOUND(stmt) && (error = new Error('NOT_FOUND')) && (NOT_FOUND = true) && ([error.code,error.state] = ['020000','020000'])) throw error;
};
PROCRESULTS()¶
0個または複数個の出力パラメーターを受け取り、それらを配列の _OUTQUERIES とバインドして返す関数です。
let PROCRESULTS = (...OUTPARAMS) => JSON.stringify([...OUTPARAMS,[..._OUTQUERIES]]);
既知の問題¶
問題は見つかりませんでした。
関連 EWIs ¶
関連 EWIs はありません。
Intoヘルパー¶
into関数は、サブクエリやselect intoステートメントから結果の行を抽出するために使用されます。
Fetch関数¶
INTO ヘルパーは、クエリ結果から行を取得するためにfetch関数を使用します。Fetch関数の定義は以下の通りです。
var fetch = (count,rows,stmt) =>
(count && rows.next() && Array.apply(null,Array(stmt.getColumnCount())).map((_,i)
=> rows.getColumnValue(i + 1))) || [];
注釈
わかりやすくするため、出力コードの一部を省略しています。
Into使用サンプル¶
Teradata
-- Additional Params: -t JavaScript
REPLACE PROCEDURE SubQuerypoc ()
BEGIN
DECLARE monat INTEGER;
SET monat = (SELECT column1
FROM table1);
END;
Snowflakeの出力
CREATE OR REPLACE PROCEDURE SubQuerypoc ()
RETURNS STRING
LANGUAGE JAVASCRIPT
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"teradata"}}'
EXECUTE AS CALLER
AS
$$
// SnowConvert AI Helpers Code section is omitted.
var MONAT;
EXEC(`(SELECT column1 FROM table1)`,[]);
var subQueryVariable0;
[subQueryVariable0] = INTO();
MONAT = subQueryVariable0;
$$;
Intoヘルパー関数の定義¶
var INTO = () => fetch(ROW_COUNT,_ROWS,_RS);
既知の問題¶
問題は見つかりませんでした。
関連 EWIs ¶
関連 EWIs はありません。