SnowConvert : Assistants des procédures Teradata

Assistant de curseur

L’assistant de curseur est une fonction qui contient les quatre principales actions des curseurs Teradata, telles que Open, Fetch, Next et Close.

  • CURSOR(), la routine principale qui déclare les variables nécessaires et les autres sous-programmes.

  • OPEN(), ouvre le curseur qui exécute l’instruction donnée, et met à jour les variables nécessaires.

  • NEXT(), déplace le curseur à la ligne suivante (le cas échéant) de l’instruction et paramètre l’ensemble des valeurs de colonne à la ligne actuelle.

  • FETCH(), obtient les valeurs (le cas échéant) de la réponse de l’instruction exécutée.

  • CLOSE(), supprime la table temporaire de _OUTQUERIES (si elle a été ajoutée dans l’assistant EXEC) et désactive les variables nécessaires.

Note

Certaines parties du code de sortie sont omises pour des raisons de clarté.

Échantillons d’utilisation du curseur

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;
Copy

Sortie 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 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();
$$;
Copy

Définition de la fonction d’assistance du curseur

 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 = '';
	      };
	};
Copy

Problèmes connus

Aucun problème n’a été constaté.

Assistant Exec

Syntaxe

EXEC(stmt)
EXEC(stmt, binds)
EXEC(stmt, binds, noCatch)
EXEC(stmt, binds, noCatch, catchFunction)
EXEC(stmt, binds, noCatch, catchFunction, opts)

Paramètres

stmt

Chaîne de l’instruction SQL à exécuter.

binds (facultatif)

Un tableau contenant les valeurs ou les variables à lier dans l’instruction SQL.

NoCatch (facultatif)

Booléen pour savoir si une erreur ne doit pas être booléenne.

catchFunction (optionnel)

Une fonction à exécuter en cas d’erreur lors de l’exécution de la fonction d’exécution.

opts (optionnel)

Un objet JSON ({ temp : true }) pour savoir si l’ID de requête doit être renvoyée.

Fonctions FixBind et FormatDate

L’assistant Exec utilise une fonction définie dans les assistants appelée FixBind. Cette fonction utilise la fonction FormatDate lorsqu’elle constate que l’une des variables de liaison est un type de date, ceci afin de gérer correctement les types de date dans Snowflake.\Les deux fonctions sont définies comme suit.

 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;
	};
Copy

Note

Certaines parties du code de sortie sont omises pour des raisons de clarté.

Échantillon d’utilisation d’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;
Copy

Sortie 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 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;
  }
$$;
Copy

Définition de l’assistant 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);
	   }
	};
Copy

Problèmes connus

Aucun problème n’a été constaté.

EWIs connexes

Pas d’EWIs connexes.

Assistants d’équivalence fonctionnelle

En fonction du contenu de chaque procédure stockée dans Teradata, SnowConvert créera une ou plusieurs des fonctions javascript suivantes à l’intérieur de celles-ci.

CompareDates

Une fonction qui compare les dates de traitement de la nullité. En Javascript, il est nécessaire d’appeler .getTime() pour les comparaisons de dates.

 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;
}
Copy

BetweenFunc

Une fonction pour gérer l’instruction BETWEEN dans Teradata.

 var BetweenFunc = function (expression,startExpr,endExpr) {
	if ([expression,startExpr,endExpr].some((arg) => arg == null)) {
		  return false;
	}
	return expression >= startExpr && expression <= endExpr;
};
Copy

LikeFunction()

Une fonction pour gérer l’instruction LIKE dans Teradata.

 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;
};
Copy

ERROR\HANDLERS()**_

La principale routine de traitement des erreurs.

 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);
   }
};
Copy

INSERT\TEMP**_

Avertissement

_ Cet assistant est obsolète dans les procédures stockées depuis la version 2.0.15. _

Une fonction pour créer une table temporaire en utilisant l’argument query avec les paramètres donnés.

 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;
};
Copy

IS\NOT_FOUND()**_

Une fonction qui valide lorsque SELECT ne renvoie aucune valeur ou qu’une phrase affecte zéro ligne. Ceci est fait afin d’émuler le même comportement que Teradata, lorsqu’il y a des sorties ou des gestionnaires de continuation pour 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;
	};
Copy

HANDLE\NOTFOUND()**_

Cette fonction utilise la fonction IS_NOT_FOUND ci-dessus pour valider le déclenchement d’une erreur artificielle “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;
	};
Copy

PROCRESULTS()

Une fonction qui prend zéro ou plusieurs paramètres de sortie et les lie avec les _OUTQUERIES dans un tableau afin qu’ils soient renvoyés.

 let PROCRESULTS = (...OUTPARAMS) => JSON.stringify([...OUTPARAMS,[..._OUTQUERIES]]);
Copy

Problèmes connus

Aucun problème n’a été constaté.

EWIs connexes

Pas d’EWIs connexes.

Assistant Into

Fonction de récupération

L’assistant INTO utilise une fonction de récupération pour obtenir la ligne à partir d’une requête résultante. La définition de la fonction Fetch est décrite ci-dessous.

 var fetch = (count,rows,stmt) => 
(count && rows.next() && Array.apply(null,Array(stmt.getColumnCount())).map((_,i)
=> rows.getColumnValue(i + 1))) || [];
Copy

Note

Certaines parties du code de sortie sont omises pour des raisons de clarté.

Échantillon d’utilisation Into

Teradata

 -- Additional Params: -t JavaScript
REPLACE PROCEDURE SubQuerypoc ()
BEGIN

DECLARE monat INTEGER;
SET monat      = (SELECT column1
             FROM table1);
END;
Copy

Sortie 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 Helpers Code section is omitted.
    
    var MONAT;
    EXEC(`(SELECT column1 FROM table1)`,[]);
    var subQueryVariable0;
    [subQueryVariable0] = INTO();
    MONAT = subQueryVariable0;
$$;
Copy

Définition de la fonction d’assistance Into

 var INTO = () => fetch(ROW_COUNT,_ROWS,_RS);
Copy

Problèmes connus

Aucun problème n’a été constaté.

EWIs connexes

Pas d’EWIs connexes.