SnowConvert: Teradata Prozeduren-Hilfsfunktionen

Cursor-Hilfsfunktion

Die Cursor-Hilfsfunktion ist eine Funktion, die die vier wichtigsten Aktionen enthält, die Teradata-Cursor ausführen, z. B. Öffnen, Abrufen, Weiter und Schließen.

  • CURSOR(),_ die Hauptroutine, die die benötigten Variablen und andere Unterprogramme deklariert.

  • OPEN(),_ öffnet den Cursor, der die angegebene Anweisung ausführt, und aktualisiert die erforderlichen Variablen.

  • NEXT(),_ bewegt den Cursor in die nächste Zeile (falls vorhanden) der Anweisung und setzt jeden Spaltenwert auf die aktuelle Zeile.

  • FETCH(),_ holt sich die Werte (falls vorhanden) aus der Antwort der ausgeführten Anweisung.

  • CLOSE(),_ entfernt die temporäre Tabelle aus demOUTQUERIES (wenn sie in der EXEC-Hilfsfunktion hinzugefügt wurde) und setzt die notwendigen Variablen zurück.

Bemerkung

Einige Teile des Ausgabecodes werden aus Gründen der Übersichtlichkeit weggelassen.

Cursor-Verwendungsbeispiel

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

Snowflake-Ausgabe

 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

Definition der Cursor-Hilfsfunktion

 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

Bekannte Probleme

Es wurden keine Probleme gefunden.

Exec-Hilfsfunktion

Syntax

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

Parameter

stmt

Die Zeichenfolge der auszuführenden SQL Anweisung.

Binds (optional)

Ein Array mit den Werten oder den Variablen, die in die Anweisung SQL eingebunden werden sollen.

NoCatch (optional)

Boolescher Wert, um zu wissen, ob ein Fehler nicht abgefangen werden soll.

catchFunction (optional)

Eine Funktion, die ausgeführt wird, wenn bei der Ausführung der exec-Funktion ein Fehler auftritt.

Opts (optional)

Ein JSON-Objekt ({ temp : true }), um zu wissen, ob die Abfrage ID zurückgegeben werden soll.

FixBind- und FormatDate-Funktionen

Die Exec-Hilfsfunktion verwendet eine in den Hilfsfunktionen definierte Funktion namens FixBind. Diese Funktion verwendet die Funktion FormatDate, wenn sie feststellt, dass eine der Bindungsvariablen ein Datumstyp ist. Dies geschieht, um die Datumstypen in Snowflake richtig zu verwalten.

 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

Bemerkung

Einige Teile des Ausgabecodes werden aus Gründen der Übersichtlichkeit weggelassen.

Exec-Verwendungsbeispiel

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

Snowflake-Ausgabe

 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

Definition der Exec-Hilfsfunktion

 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

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

Keine zugehörigen EWIs.

Funktionsäquivalenz-Hilfsfunktion

Je nachdem, was in den einzelnen gespeicherten Prozeduren in Teradata enthalten ist, erstellt SnowConvert eine oder mehrere der folgenden Javascript-Funktionen in ihnen.

CompareDates

Eine Funktion, die Datumsangaben vergleicht, die mit Nullen umgehen. In Javascript ist es erforderlich, .getTime() für Datumsvergleiche aufzurufen.

 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

Eine Funktion zur Handhabung der BETWEEN Anweisung in Teradata.

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

LikeFunction()

Eine Funktion zur Handhabung der LIKE Anweisung in 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()**_

Die wichtigste Routine zur Fehlerbehandlung.

 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**_

Warnung

Diese Hilfsfunktion ist in gespeicherten Prozeduren seit Version 2.0.15 veraltet. _

Eine Funktion zur Erstellung einer temporären Tabelle unter Verwendung des Arguments query mit den angegebenen 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;
};
Copy

IS\NOT_FOUND()**_

Eine Funktion, die validiert, wenn SELECT keine Werte zurückgibt oder ein Satz null Zeilen betrifft. Dies geschieht, um die gleiche Verhaltensweise wie bei Teradata zu emulieren, wenn es Exits oder Continue-Handler für NOT FOUND EXCEPTIONS gibt.

 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()**_

Diese Funktion verwendet die obige IS_NOT_FOUND Funktion, um zu überprüfen, wann ein künstlicher Fehler ‚NOT FOUND‘ ausgelöst wird.

  	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()

Eine Funktion, die null oder mehrere Ausgabeparameter annimmt und sie mit demOUTQUERIES in einem Array verbindet, um zurückgegeben zu werden.

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

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

Keine zugehörigen EWIs.

Into-Hilfsfunktion

Abruffunktion

Die Hilfsfunktion INTO verwendet eine Abruffunktion, um die Zeile aus einer Abfrage abzurufen. Die Definition der Abruffunktion wird im Folgenden beschrieben.

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

Bemerkung

Einige Teile des Ausgabecodes werden aus Gründen der Übersichtlichkeit weggelassen.

Into-Verwendungsbeispiel

Teradata

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

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

Snowflake-Ausgabe

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

Definition der Into-Hilfsfunktion

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

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

Keine zugehörigen EWIs.