SnowConvert: Teradata SQL para JavaScript (procedimentos)¶
GET DIAGNOSTICS EXCEPTION¶
Descrição ¶
GET DIAGNOSTICS recupera informações sobre condições de sucesso, exceção ou conclusão da área de diagnóstico.
Para obter mais informações sobre o Teradata GET DIAGNOSTICS, acesse aqui.
GET DIAGNOSTICS
{
[ EXCEPTION < condition_number >
[ < parameter_name | variable_name > = < information_item > ]...
]
|
[ < parameter_name | variable_name > = < information_item > ]...
}
Nota
Algumas partes do código de saída foram omitidas por motivos de clareza.
Amostra de padrões de origem ¶
Teradata ¶
-- Additional Params: -t JavaScript
CREATE PROCEDURE getDiagnosticsSample ()
BEGIN
DECLARE V_MESSAGE, V_CODE VARCHAR(200);
DECLARE V_Result INTEGER;
SELECT c1 INTO V_Result FROM tab1;
GET DIAGNOSTICS EXCEPTION 1 V_MESSAGE = MESSAGE_TEXT;
END;
Snowflake ¶
CREATE OR REPLACE PROCEDURE getDiagnosticsSample ()
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 V_MESSAGE;
var V_CODE;
var V_RESULT;
EXEC(`SELECT c1 FROM tab1`,[]);
[V_RESULT] = INTO();
V_MESSAGE = MESSAGE_TEXT;
$$;
Problemas conhecidos¶
Instruções de atributos de condição sem suporte
CLASS_ORIGIN
CONDITION_IDENTIFIER
CONDITION_NUMBER
MESSAGE_LENGTH
RETURNED_SQLSTATE
SUBCLASS_ORIGIN
Macros¶
Descrição¶
A instrução MACRO do Teradata é convertida para a sintaxe do Snowflake MACRO.
Para obter mais informações sobre o Teradata MACRO, acesse aqui.
Nota
Algumas partes do código de saída foram omitidas por motivos de clareza.
Amostra de padrões da origem¶
Criar transformação de macro¶
Teradata
-- Additional Params: -t JavaScript
CREATE MACRO new_table (col1 INTEGER, col2 VARCHAR(12))
AS
(
insert into table1 (col1, col2) values (:col1, :col2);
select * from table1 where col1 = :col1;
);
Snowflake
CREATE OR REPLACE PROCEDURE new_table (COL1 FLOAT, COL2 VARCHAR(12))
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.
// ** SSC-EWI-0022 - ONE OR MORE IDENTIFIERS IN THIS STATEMENT WERE CONSIDERED PARAMETERS BY DEFAULT. REFERENCED TABLE NOT FOUND. **
EXEC(`INSERT INTO table1 (col1, col2)
VALUES (:1, :2)`,[COL1,COL2]);
INSERT_TEMP(`SELECT * from table1 where col1 = :1`,[COL1]);
return tablelist;
$$;
Problemas conhecidos¶
1. Macro transform to store procedure¶
A macro do Teradata é transformada em um procedimento armazenado, pois o Snowflake não oferece suporte a macros.
EWIs relacionados¶
SSC-EWI-0022: Um ou mais identificadores nessa instrução foram considerados parâmetros por padrão.
Procedimentos¶
Descrição¶
A instrução PROCEDURE do Teradata é convertida para a sintaxe do Snowflake PROCEDURE.
Para obter mais informações sobre o Teradata PROCEDURE, clique aqui.
Amostra de padrões da origem¶
Criar transformação de procedimento¶
Nota
O código de auxiliares do SnowConvert foi removido do exemplo. Você pode encontrá-los aqui.
Algumas partes do código de saída foram omitidas por motivos de clareza.
Região de auxiliares de procedimentos do SnowConvert¶
Todos os procedimentos contêm uma região chamada código de auxiliares do SnowConvert, que é um conjunto de variáveis e funções que ajudam a emular algumas funcionalidades do Teradata que não são nativas em JavaScript. Para simplificar, no código de exemplos de procedimentos, essa região não será mostrada. Alguns auxiliares são adicionados sempre, como EXEC, e outros, como FETCH, INTO, etc., são adicionados sob demanda.
O código dos auxiliares de região é o seguinte:
// REGION SnowConvert Helpers Code
var HANDLE_NOTFOUND;
var fetch = (count,rows,stmt) => (count && rows.next() && Array.apply(null,Array(stmt.getColumnCount())).map((_,i) => rows.getColumnValue(i + 1))) || [];
var _RS, ROW_COUNT, _ROWS, MESSAGE_TEXT, SQLCODE = 0, SQLSTATE = '00000', ERROR_HANDLERS, ACTIVITY_COUNT = 0, INTO, _OUTQUERIES = [], DYNAMIC_RESULTS = 9;
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;
};
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);
}
};
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 = '';
};
};
let PROCRESULTS = (...OUTPARAMS) => JSON.stringify([...OUTPARAMS,[..._OUTQUERIES]]);
// END REGION
Teradata
-- Additional Params: -t JavaScript
REPLACE PROCEDURE my_procedure (in param1 VARCHAR(10), OUT param2 BLOB)
dynamic result sets 9
SELECT * FROM table1;
Snowflake
CREATE OR REPLACE PROCEDURE my_procedure (PARAM1 STRING, PARAM2 BINARY /*** SSC-FDM-TD0001 - COLUMN CONVERTED FROM BLOB DATA TYPE ***/)
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.
EXEC(`SELECT * FROM table1`,[]);
return PROCRESULTS(PARAM2);
$$;
_Nota: O corpo do procedimento armazenado no Snowflake é executado como funções javascript
If¶
A transformação para a instrução IF é:
Teradata
IF value = 2 THEN
Snowflake
if(value == 2){
}
Case¶
A transformação para a instrução Case é:
Teradata
case value
when 0 then
select * from table1
else
update table1 set name = "SpecificValue" where id = value;
end case
Snowflake
switch(value) {
case 0:EXEC(`SELECT * FROM PUBLIC.table1`,[]);
break;
default:EXEC(`UPDATE PUBLIC.table1 set name = "SpecificValue" where id = value`,[]);
break;
}
Cursor Declare, OPEN, FETCH e CLOSE¶
A transformação para instruções de cursor é a seguinte:
Teradata
-- Additional Params: -t JavaScript
CREATE 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 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();
$$;
While¶
A transformação para a instrução while é:
Teradata
while (counter < 10) do
set counter = counter + 1;
Snowflake¶
while ( counter < 10) {
counter = counter + 1;
}
Segurança¶
A transformação para instruções de segurança é:
Teradata |
Snowflake |
---|---|
SQL SECURITY CREATOR |
EXECUTE AS OWNER |
SQL SECURITY INVOKER |
EXECUTE AS CALLER |
SQL SECURITY DEFINER |
EXECUTE AS OWNER |
Loop FOR-CURSOR-FOR¶
A transformação para loop FOR-CURSOR-FOR é a seguinte:
Teradata
-- Additional Params: -t JavaScript
REPLACE PROCEDURE Database1.Proc1()
BEGIN
DECLARE lNumber INTEGER DEFAULT 1;
FOR class1 AS class2 CURSOR FOR
SELECT COL0,
TRIM(COL1) AS COL1ALIAS,
TRIM(COL2),
COL3
FROM someDb.prefixCol
DO
INSERT INTO TempDB.Table1 (:lgNumber, :lNumber, (',' || :class1.ClassCD || '_Ind CHAR(1) NOT NULL'));
SET lNumber = lNumber + 1;
END FOR;
END;
Snowflake
CREATE OR REPLACE PROCEDURE Database1.Proc1 ()
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 LNUMBER = 1;
/*** SSC-EWI-0023 - PERFORMANCE REVIEW - THIS LOOP CONTAINS AN INSERT, DELETE OR UPDATE STATEMENT ***/
for(var CLASS2 = new CURSOR(`SELECT
COL0,
TRIM(COL1) AS COL1ALIAS,
TRIM(COL2),
COL3
FROM
someDb.prefixCol`,[],false).OPEN();CLASS2.NEXT();) {
let CLASS1 = CLASS2.CURRENT;
EXEC(`INSERT INTO TempDB.Table1
VALUES (:lgNumber, :1, (',' || :
!!!RESOLVE EWI!!! /*** SSC-EWI-0026 - THE VARIABLE class1.ClassCD MAY REQUIRE A CAST TO DATE, TIME OR TIMESTAMP ***/!!!
:2 || '_Ind CHAR(1) NOT NULL'))`,[LNUMBER,CLASS1.CLASSCD]);
LNUMBER = LNUMBER + 1;
}
CLASS2.CLOSE();
$$;
Nota: O loop FOR presente no procedimento Teradata é transformado em um bloco FOR em javascript que emula sua funcionalidade.
Parâmetros de procedimento e variáveis referenciados dentro de instruções¶
A transformação para os parâmetros e variáveis do procedimento que são referenciados dentro das instruções do procedimento é:
Teradata
-- Additional Params: -t JavaScript
REPLACE PROCEDURE PROC1 (param1 INTEGER, param2 VARCHAR(30))
BEGIN
DECLARE var1 VARCHAR(1024);
DECLARE var2 SMALLINT;
DECLARE weekstart date;
set weekstart= '2019-03-03';
set var1 = 'something';
set var2 = 123;
SELECT * FROM TABLE1 WHERE SOMETHING = :param1;
SELECT * FROM TABLE1 WHERE var1 = var1 AND date1 = weekstart AND param2 = :param2;
INSERT INTO TABLE2 (col1, col2, col3, col4, col5) VALUES (:param1, :param2, var1, var2, weekstart);
END;
Snowflake
CREATE OR REPLACE PROCEDURE PROC1 (PARAM1 FLOAT, PARAM2 STRING)
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 VAR1;
var VAR2;
var WEEKSTART;
WEEKSTART = `2019-03-03`;
VAR1 = `something`;
VAR2 = 123;
// ** SSC-EWI-0022 - ONE OR MORE IDENTIFIERS IN THIS STATEMENT WERE CONSIDERED PARAMETERS BY DEFAULT. REFERENCED TABLE NOT FOUND. **
EXEC(`SELECT * FROM TABLE1 WHERE SOMETHING = :1`,[PARAM1]);
// ** SSC-EWI-0022 - ONE OR MORE IDENTIFIERS IN THIS STATEMENT WERE CONSIDERED PARAMETERS BY DEFAULT. REFERENCED TABLE NOT FOUND. **
EXEC(`SELECT * FROM TABLE1 WHERE :1 = :1 AND date1 = :2 AND RTRIM(param2) = :3`,[VAR1,WEEKSTART,PARAM2]);
// ** SSC-EWI-0022 - ONE OR MORE IDENTIFIERS IN THIS STATEMENT WERE CONSIDERED PARAMETERS BY DEFAULT. REFERENCED TABLE NOT FOUND. **
EXEC(`INSERT INTO TABLE2 (col1, col2, col3, col4, col5) VALUES (:1, :2, :3, :4, :5)`,[PARAM1,PARAM2,VAR1,VAR2,WEEKSTART]);
$$;
Nota: Sempre que um parâmetro de procedimento ou uma variável declarada dentro do procedimento for referenciada dentro de uma instrução do Teradata que precisa ser convertida, essa referência é escapada do texto resultante para preservar a funcionalidade da referência original.
Leave¶
Em Javascript, é possível usar break
com um parâmetro adicional, emulando assim o comportamento de um salto do Teradata LEAVE
.
Os rótulos também podem ser emulados com o uso de instruções rotuladas em Javascript.
A transformação para a instruçãoLEAVE é:
Teradata
-- Additional Params: -t JavaScript
REPLACE PROCEDURE PROC1 ()
BEGIN
DECLARE v_propval VARCHAR(1024);
DECLARE Cur1 cursor for
Select
propID
from viewName.viewCol
where propval is not null;
LABEL_WHILE:
WHILE (SQLCODE = 0)
DO
IF (SQLSTATE = '02000' )
THEN LEAVE LABEL_WHILE;
END IF;
LABEL_INNER_WHILE:
WHILE (SQLCODE = 0)
DO
IF (SQLSTATE = '02000' )
THEN LEAVE LABEL_INNER_WHILE;
END IF;
END WHILE LABEL_INNER_WHILE;
SELECT * FROM TABLE1;
END WHILE L1;
END;
Snowflake
CREATE OR REPLACE PROCEDURE PROC1 ()
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 V_PROPVAL;
var CUR1 = new CURSOR(`SELECT propID from viewName.viewCol
where
propval is not null`,[],false);
LABEL_WHILE: {
while ( SQLCODE == 0 ) {
if (SQLSTATE == `02000`) {
break LABEL_WHILE;
}
LABEL_INNER_WHILE: {
while ( SQLCODE == 0 ) {
if (SQLSTATE == `02000`) {
break LABEL_INNER_WHILE;
}
}
}
EXEC(`SELECT * FROM TABLE1`,[]);
}
}
$$;
Obtendo resultados dos procedimentos¶
Descrição da conversão¶
No Teradata, há duas maneiras de retornar dados de um procedimento. O primeiro é por meio de parâmetros de saída e o segundo por meio de Conjuntos de resultados dinâmicos e Cursores. Ambos são mostrados no exemplo a seguir. Cada ponto importante é explicado a seguir.
Exemplo de retorno de dados de um procedimento armazenado¶
Teradata
-- Additional Params: -t JavaScript
REPLACE PROCEDURE Procedure1(OUT P1 INTEGER)
DYNAMIC RESULT SETS 2
BEGIN
DECLARE SQL_CMD,SQL_CMD_1 VARCHAR(20000) DEFAULT ' ';
DECLARE RESULTSET CURSOR WITH RETURN ONLY FOR FIRSTSTATEMENT;
SET SQL_CMD = 'SEL * FROM EMPLOYEE';
PREPARE FIRSTSTATEMENT FROM SQL_CMD;
OPEN RESULTSET;
SET P1 = (SEL CAST(AVG(AGE) AS INTEGER) FROM EMPLOYEE);
END;
Snowflake
CREATE OR REPLACE PROCEDURE Procedure1 (P1 FLOAT)
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 SQL_CMD = ` `;
var SQL_CMD_1 = ` `;
var RESULTSET = new CURSOR(() => FIRSTSTATEMENT,[],true);
SQL_CMD = `SELECT * FROM EMPLOYEE`;
var FIRSTSTATEMENT = SQL_CMD;
RESULTSET.OPEN();
EXEC(`(SELECT CAST(TRUNC(AVG(AGE)) AS INTEGER) FROM EMPLOYEE)`,[]);
var subQueryVariable0;
[subQueryVariable0] = INTO();
P1 = subQueryVariable0;
return PROCRESULTS(P1);
$$;
Nesse SQL convertido, há várias conversões que ocorrem:
A definição
DYNAMIC RESULT SETS 2
é convertida em uma variávelDYNAMIC_RESULTS
.
var DYNAMIC_RESULTS = 2;
Quando um cursor com um atributo
WITH RETURN
é aberto (e, portanto, uma consulta é executada), sua ID de consulta é armazenada na coleção_ OUTQUERIES
para ser retornada posteriormente. O ID da consulta é obtido pela funçãogetQueryId()
fornecida na API JavaScript para procedimentos armazenados do Snowflake.Somente as primeiras k-query-IDs são armazenadas na coleção, em que k é o valor da variável
DYNAMIC_RESULTS
. Isso é feito para imitar o comportamento do Teradata, que retorna apenas os primeiros k-opened-cursors, mesmo que mais sejam abertos no procedimento armazenado.A combinação de
DECLARE CURSOR WITH RETURN
comPREPARE
é convertida para:
var RESULTSET = new CURSOR(() => FIRSTSTATEMENT,[],true);
Os parâmetros de saída são suportados por meio da instrução de retorno do procedimento. É criada uma matriz que contém o valor de cada parâmetro de saída e a coleção
_OUTQUERIES
. A funçãoPROCRESULTS
trata da criação e do preenchimento dessa matriz. Consulte PROCRESULTS() helper para obter mais informações.
return PROCRESULTS(P1);
Exemplo de obtenção de dados de um procedimento armazenado¶
Se os parâmetros de saída e IDs de consulta forem retornados de um procedimento, um segundo procedimento poderá chamar o primeiro para obter esses valores, conforme mostrado abaixo:
Teradata
-- Additional Params: -t JavaScript
CREATE PROCEDURE Procedure2()
BEGIN
DECLARE x INTEGER;
CALL Procedure1(x);
END;
Snowflake
CREATE OR REPLACE PROCEDURE Procedure2 ()
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 X;
EXEC(`CALL Procedure1(:1)`,[X]);
$$;
O valor do argumento
P1
deProcedure1
é retornado e armazenado na variávelX
.O
_OUTQUERIES
retornado doProcedure1
é armazenado na variávelresultset
.
Nota
Esse comportamento também se aplica aos parâmetros de INOUT.
Problemas conhecidos¶
Não foram encontrados problemas.
EWIs relacionados¶
SSC-EWI-0022: Um ou mais identificadores nessa instrução foram considerados parâmetros por padrão.
SSC-EWI-0023: Análise de desempenho - Um loop contém uma instrução de inserção, exclusão ou atualização.
SSC-EWI-0026: A variável pode exigir uma conversão para data, hora ou carimbo de data/hora.
SSC-FDM-TD0001: Essa mensagem é exibida quando SnowConvert encontra um tipo de dados BLOB.