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

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

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

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 = 0

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 > 0

Nombre

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

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

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

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

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
Copy

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'})
    
    Copy
  • Niveau d’instruction

    connection.execute({
      sqlText: sql,
      rowMode: 'array',
      ...
      )}
    
    Copy

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 => eval("(" + rawColumnValue + ")")
    })
    
    Copy
  • 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)
    })
    
    Copy
  • 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)
    })
    
    Copy