Exploitation des résultats¶
Renvoi de résultats en ligne¶
La façon la plus répandue d’exploiter des résultats est d’effectuer un rappel complete
à connection.execute()
. Lorsque l’instruction est terminée et que le résultat est prêt à être exploité, le rappel complete
est invoqué avec les lignes de résultat renvoyées en ligne :
connection.execute({ sqlText: 'SELECT * FROM sometable', complete: function(err, stmt, rows) { if (err) { console.error('Failed to execute statement due to the following error: ' + err.message); } else { console.log('Number of rows produced: ' + rows.length); } } });
Diffusion de résultats¶
Vous pouvez également consommer un résultat sous la forme d’un flux de lignes en définissant le paramètre de connexion streamResult
sur true
dans connection.execute
lors de l’appel de la méthode statement.streamRows()
. L’activation de ce paramètre fait en sorte que la méthode renvoie un flux Node.js Readable
que vous pouvez utiliser pour consommer les lignes au fur et à mesure de leur réception. Pour plus d’informations sur le flux Readable
, reportez-vous à la documentation Node.js.
Important
Pour tout jeu de résultats susceptible de dépasser la mémoire par défaut de Node, Snowflake vous recommande vivement de définir streamResult
sur true
lors de la diffusion des résultats. Avec la valeur par défaut (false
), le connecteur stocke toutes les lignes dans un tableau avant de diffuser les résultats. Avec des jeux de résultats plus petits, ce facteur n’est normalement pas un problème. Cependant, avec des jeux de résultats plus importants, le stockage de tous les résultats en mémoire peut contribuer à une erreur OOM.
Les versions récentes du pilote Node.js de Snowflake (1.6.23 et ultérieures) mettent en œuvre une fonctionnalité de contre-pression pour s’assurer que, lors de la consommation de résultats, les données ne sont pas poussées vers le flux plus rapidement que les données ne sont lues depuis le flux.
Par exemple, la partie de code suivant consomme les résultats à l’aide de l’événement Readable
:
var connection = snowflake.createConnection({ account: process.env.SFACCOUNT, username: process.env.SFUSER, // ... streamResult: true }); // [..rest of the code..] connection.execute({ sqlText: "select L_COMMENT from SNOWFLAKE_SAMPLE_DATA.TPCH_SF100.LINEITEM limit 100000;", streamResult: true, complete: function (err, stmt) { var stream = stmt.streamRows(); // Read data from the stream when it is available stream.on('readable', function (row) { while ((row = this.read()) !== null) { console.log(row); } }).on('end', function () { console.log('done'); }).on('error', function (err) { console.log(err); }); } });
Traitement des résultats par lots¶
Par défaut, la méthode statement.streamRows()
produit un flux qui inclut chaque ligne dans le résultat. Cependant, si vous voulez seulement exploiter un sous-ensemble du résultat, ou si vous voulez exploiter les lignes de résultat par lots, vous pouvez appeler streamRows()
avec les arguments start
et end
. Lorsque ces options supplémentaires sont spécifiées, seules les lignes de la plage demandée sont diffusées :
connection.execute({ sqlText: 'SELECT * FROM sometable', streamResult: true, // prevent rows from being returned inline in the complete callback complete: function(err, stmt, rows) { // no rows returned inline because streamResult was set to true console.log('rows: ' + rows); // 'rows: undefined' // only consume at most the last 5 rows in the result rows = []; stmt.streamRows({ start: Math.max(0, stmt.getNumRows() - 5), end: stmt.getNumRows() - 1, }) .on('error', function(err) { console.error('Unable to consume requested rows'); }) .on('data', function(row) { rows.push(row); }) .on('end', function() { console.log('Number of rows consumed: ' + rows.length); }); } })
Conversion de type de données¶
Lorsque les lignes de résultats sont produites, le pilote mappe automatiquement les types de données SQL à leurs équivalents JavaScript correspondants. Par exemple, les valeurs de type TIMESTAMP et DATE sont retournées sous la forme d’objets Date JavaScript.
Pour le mappage complet des types de données JavaScript à SQL , reportez-vous au tableau ci-dessous :
Type de données SQL
Type de données JavaScript
Remarques
VARCHAR, CHAR, CHARACTER, STRING, TEXT
Chaîne
INT, INTEGER, BIGINT, SMALLINT
Nombre
C’est le mappage par défaut. Utilisez le paramètre de session JS_TREAT_INTEGER_AS_BIGINT pour mapper à JavaScript Bigint.
NUMBER(précision, échelle), DECIMAL(p, s), NUMERIC(p, s) où
scale
= 0Nombre
C’est le mappage par défaut. Utilisez le paramètre de session JS_TREAT_INTEGER_AS_BIGINT pour mapper à JavaScript Bigint.
NUMBER(précision, échelle), DECIMAL(p, s), NUMERIC(p, s) où
scale
> 0Nombre
FLOAT, FLOAT4, FLOAT8, DOUBLE, DOUBLE PRECISION, REAL
Nombre
TIMESTAMP, TIMESTAMP_LTZ, TIMESTAMP_NTZ, TIMESTAMP_TZ
Date
Les valeurs TIMESTAMP_NTZ sont renvoyées dans UTC.
DATE
Date
TIME
Chaîne
Notez que le type de données TIME dans SQL n’a pas d’équivalent dans JavaScript. Il est donc mappé à une chaîne JavaScript.
BOOLEAN
Booléen
VARIANT, ARRAY, OBJECT
JSON
Récupération des types de données entiers en tant que Bigint¶
Par défaut, les colonnes INTEGER Snowflake (y compris BIGINT
, NUMBER(p, 0)
, etc.) sont converties en type de données JavaScript Number
. Toutefois, les plus grandes valeurs légales entières de Snowflake sont supérieures aux plus grandes valeurs légales JavaScript. Pour convertir les colonnes INTEGER
Snowflake au format JavaScript Bigint
, qui peut stocker des valeurs supérieures à JavaScript Number
, définissez le paramètre de session JS_TREAT_INTEGER_AS_BIGINT
.
Vous pouvez utiliser les méthodes suivantes pour définir les valeurs de ces paramètres :
Utilisez l’instruction ALTER SESSION, comme indiqué ci-dessous :
connection.execute( { sqlText: 'ALTER SESSION SET JS_TREAT_INTEGER_AS_BIGINT = TRUE', complete: function ... } );
Spécifiez le paramètre dans les informations de configuration de la connexion :
var connection = snowflake.createConnection( { username: 'fakeusername', password: 'fakepassword', account: 'fakeaccountidentifier', jsTreatIntegerAsBigInt: true } );
Récupération des types de données sous forme de chaînes¶
Lorsque vous appelez connection.execute()
, vous pouvez utiliser l’option fetchAsString
pour renvoyer les types de données suivants sous forme de chaînes : Boolean
, Number
, Date
, Buffer
, et JSON
.
Vous pouvez utiliser cette option, par exemple, pour revenir :
Versions formatées des valeurs de type DATE et TIMESTAMP (ou ses variantes).
Versions de chaîne de types numériques SQL qui ne peuvent pas être converties en numéros JavaScript sans perte de précision.
L’exemple suivant utilise fetchAsString
pour convertir une valeur Number
de haute précision en une chaîne.
connection.execute({
sqlText: 'SELECT 1.123456789123456789123456789 as "c1"',
fetchAsString: ['Number'],
complete: function(err, stmt, rows) {
if (err) {
console.error('Failed to execute statement due to the following error: ' + err.message);
} else {
console.log('c1: ' + rows[0].c1); // c1: 1.123456789123456789123456789
}
}
});
Analyse de données XML¶
À partir de la version 1.7.0 du pilote, vous pouvez utiliser les options de configuration de la bibliothèque fast-xml-parser suivantes pour personnaliser la façon dont le pilote traite les attributs du document XML lors de l’interrogation de colonnes avec du contenu XML. Pour plus d’informations sur ces options prises en charge et sur la manière dont elles affectent l’analyse de données XML, consultez Options xmlParserConfig.
Par défaut, le pilote Node.js ignore les attributs des éléments XML lorsqu’il renvoie des données XML à partir d’une requête. Par exemple, dans le contenu XML suivant, l’élément <piece>
comprend un attribut id
:
<exhibit name="Art Show">
<piece id="000001">
<name>Mona Lisa</name>
<artist>Leonardo da Vinci</artist>
<year>1503</year>
</piece>
<piece id="000002">
<name>The Starry Night</name>
<artist>Vincent van Gogh</artist>
<year>1889</year>
</piece>
</exhibit>
Par défaut, lorsque le pilote Node.js renvoie le jeu de résultats, il ignore l’attribut id
et renvoie la sortie suivante. Vous remarquerez que les noms et les valeurs des attributs ne sont pas inclus.
{
exhibit: {
piece: [
{
"name": "Mona Lisa",
"artist": "Leonardo da Vinci",
"year": "1503",
},
{
"name": "The Starry Night",
"artist": "Vincent van Gogh",
"year": "1889",
}
]
}
}
Pour définir les options fast-xml-parser , créez un élément xmlParserConfig
similaire à l’exemple suivant :
const snowflake = require('snowflake-sdk'); snowflake.configure({ xmlParserConfig: { /* Parameters that you can override * ignoreAttributes - default true, * attributeNamePrefix - default '@_', * attributesGroupName - default unset, * alwaysCreateTextNode - default false */ ignoreAttributes: false, attributesGroupName: '@', attributeNamePrefix: '' } });
Avec ces paramètres, le pilote analyse les données XML et produit ce qui suit :
{
exhibit: {
piece: [
{
"name": "Mona Lisa",
"artist": "Leonardo da Vinci",
"year": "1503",
'@': { id: '000001' }
},
{
"name": "The Starry Night",
"artist": "Vincent van Gogh",
"year": "1889",
'@': { id: '000002' }
}
],
'@': { name: 'Art Show' }
}
Renvoi de jeux de résultats contenant des noms de colonnes dupliqués¶
Dans la version 1.8.0, le pilote Node.js de Snowflake a introduit une nouvelle option de configuration rowMode qui vous permet de spécifier la façon dont vous voulez que le pilote retourne les jeux de résultats qui contiennent des noms de colonnes dupliqués.
Avant la version 1.8.0, le pilote Node.js de Snowflake renvoyait toujours le jeu de résultats d’une commande SELECT sous la forme d’un objet JavaScript. Dans les cas où le jeu de résultats contenait des noms de colonnes et des valeurs en double, certains éléments pouvaient être omis en raison de la manière dont les objets JavaScript gèrent les noms dupliqués.
L’option rowMode
vous permet de spécifier comment les données du jeu de résultats sont renvoyées afin d’éviter toute perte potentielle d’informations, notamment :
array
object
(par défaut)object_with_renamed_duplicated_columns
Pour illustrer ce propos, supposons que vous soumettiez la requête suivante :
select *
from (select 'a' as key, 1 as foo, 3 as name) as table1
join (select 'a' as key, 2 as foo, 3 as name2) as table2 on table1.key = table2.key
join (select 'a' as key, 3 as foo) as table3 on table1.key = table3.key
En fonction de la valeur de rowMode
, le pilote renvoie les jeux de résultats comme suit :
object
(ou non défini){KEY: 'a', FOO: 3, NAME: 3, NAME2: 3};
array
['a', 1, 3, 'a', 2, 3, 'a', 3];
object_with_renamed_duplicated_columns
{KEY: 'a', FOO: 1, NAME: 3, KEY_2: 'a', FOO_2: 2, NAME2: 3, KEY_3: 'a', FOO_3: 3};
Vous pouvez définir le paramètre rowMode
au niveau de la configuration de la connexion ou de l’instruction, comme indiqué ci-dessous. Si elle est définie aux deux endroits, la valeur du niveau de l’instruction est prioritaire.
Niveau de configuration
snowflake.createConnection({ account: account, username: username, ... rowMode: 'array'})
Niveau d’instruction
connection.execute({ sqlText: sql, rowMode: 'array', ... )}
Personnalisation du traitement des données JSON et XML par les jeux de résultats¶
Le pilote Node.js de Snowflake fournit les analyseurs par défaut suivants pour traiter les données JSON et XML dans les jeux de résultats :
JSON : renvoie le résultat d’un nouvel objet
Function
.XML: fast-xml-parser.
Le module
fast-xml-parser
par défaut prend en charge un sous-ensemble d’éléments, comme décrit dans Analyse de données XML.
Si vous préférez utiliser un analyseur personnalisé, vous pouvez utiliser les exemples suivants pour le configurer :
Utiliser l’analyseur JSON d’évaluation , que le pilote utilisait avant la version 1.6.21 :
const snowflake = require('snowflake-sdk'); snowflake.configure({ jsonColumnVariantParser: rawColumnValue => JSON.parse(rawColumnValue) })
Utiliser l’analyseur
fast-xml-parser
avec la possibilité de personnaliser toutes ses options:const snowflake = require('snowflake-sdk'); snowflake.configure({ xmlColumnVariantParser: rawColumnValue => new (require("fast-xml-parser")).XMLParser().parse(rawColumnValue) })
Configurez des analyseurs personnalisés pour les deux dans la même déclaration :
const snowflake = require('snowflake-sdk'); snowflake.configure({ jsonColumnVariantParser: rawColumnValue => JSON.parse(rawColumnValue), xmlColumnVariantParser: rawColumnValue => new (require("fast-xml-parser")).XMLParser().parse(rawColumnValue) })