Utilisation du pilote Node.js

Le workflow classique d’utilisation du pilote est le suivant :

  1. Établissez une connexion avec Snowflake.

  2. Exécuter des instructions, par exemple des requêtes et des commandes DDL/DML.

  3. Exploitez les résultats.

  4. Mettez fin à la connexion.

Important

Actuellement, le pilote ne prend pas en charge la commande PUT ou GET. Par conséquent, il ne peut pas être utilisé pour télécharger des fichiers dans le cadre du chargement/déchargement de données. Utilisez SnowSQL (client CLI) ou Pilote JDBC à la place.

Dans ce chapitre :

Établissement d’une connexion

Pour exécuter des instructions vis-à-vis de Snowflake, vous devez d’abord établir une connexion.

Par exemple :

// Load the Snowflake Node.js driver.
var snowflake = require('snowflake-sdk');
// Create a Connection object that we can use later to connect.
var connection = snowflake.createConnection( {
    account: account,
    username: user,
    password: password
    }
    );
// Try to connect to Snowflake, and check whether the connection was successful.
connection.connect( 
    function(err, conn) {
        if (err) {
            console.error('Unable to connect: ' + err.message);
            } 
        else {
            console.log('Successfully connected to Snowflake.');
            // Optional: store the connection ID.
            connection_ID = conn.getId();
            }
        }
    );

Lors de la création d’une connexion, vous pouvez définir les options décrites dans la section ci-dessous.

Options de connexion requises

account

Nom complet de votre compte (fourni par Snowflake). Notez que votre nom de compte complet peut inclure des segments supplémentaires identifiant la région et la plate-forme cloud où votre compte est hébergé.

Account name examples by region

Si votre nom de compte est xy12345 :

Plate-forme Cloud/Région

Nom de compte complet

AWS

US Ouest (Oregon)

xy12345

US Est (Ohio)

xy12345.us-east-2.aws

US Est (Virginie du Nord)

xy12345.us-east-1

US Est (Gouvernement commercial - Virginie du Nord)

xy12345.us-east-1-gov.aws

Canada (Centre)

xy12345.ca-central-1.aws

EU (Irlande)

xy12345.eu-west-1

EU (Francfort)

xy12345.eu-central-1

Asie-Pacifique (Tokyo)

xy12345.ap-northeast-1.aws

Asie Pacifique (Mumbai)

xy12345.ap-south-1.aws

Asie-Pacifique (Singapour)

xy12345.ap-southeast-1

Asie-Pacifique (Sydney)

xy12345.ap-southeast-2

GCP

US Central1 (Iowa)

xy12345.us-central1.gcp

Europe Ouest2 (Londres)

xy12345.europe-west2.gcp

Europe Ouest4 (Pays-Bas)

xy12345.europe-west4.gcp

Azure

Ouest US 2 (Washington)

xy12345.west-us-2.azure

Est US 2 (Virginie)

xy12345.east-us-2.azure

US Gov Virginia

xy12345.us-gov-virginia.azure

Canada Central (Toronto)

xy12345.canada-central.azure

Europe de l’Ouest (Pays-Bas)

xy12345.west-europe.azure

Suisse Nord (Zurich)

xy12345.switzerland-north.azure

Asie du Sud-Est (Singapour)

xy12345.southeast-asia.azure

Australie Est (Nouvelle-Galles du Sud)

xy12345.australia-east.azure

Important

Si l’une des conditions suivantes est remplie, le nom de votre compte est différent de la structure décrite dans cet exemple :

  • Si votre édition Snowflake est VPS, contactez le support Snowflake pour obtenir des détails sur le nom de votre compte.

  • Si AWS PrivateLink est activé pour votre compte, le nom de votre compte nécessite un segment privatelink supplémentaire. Pour plus de détails, voir AWS PrivateLink et Snowflake.

username

Nom d’utilisateur Snowflake avec lequel se connecter.

password

Mot de passe de l’utilisateur.

regionObsolète

Spécifie l’ID de la région où se trouve votre compte.

Ce paramètre n’est plus utilisé, car les informations de région, si nécessaires, sont incluses dans le nom de compte complet. Elle n’est documentée ici que pour des raisons de rétrocompatibilité.

Options de connexion supplémentaires

database

La base de données par défaut à utiliser pour la session après la connexion.

schema

Le schéma par défaut à utiliser pour la session après la connexion.

warehouse

L’entrepôt virtuel par défaut à utiliser pour la session après la connexion. Utilisé pour effectuer des requêtes, charger des données, etc.

role

Le rôle de sécurité par défaut à utiliser pour la session après la connexion.

clientSessionKeepAlive

Par défaut, les connexions client expirent généralement environ 3 à 4 heures après l’exécution de la requête la plus récente.

Si le paramètre clientSessionKeepAlive est défini sur true, la connexion du client au serveur sera maintenue indéfiniment, même si aucune requête n’est exécutée.

Le paramètre par défaut de ce paramètre est false.

Si vous définissez ce paramètre sur true, assurez-vous que votre programme se déconnecte explicitement du serveur à la fin du programme. Ne quittez pas sans vous déconnecter.

clientSessionKeepAliveHeartbeatFrequency

(Ce paramètre ne s’applique que lorsque clientSessionKeepAlive est vrai)

Ce paramètre définit la fréquence (l’intervalle en secondes) entre les messages de pulsation.

Vous pouvez vaguement penser qu’un message de pulsation de connexion se substitue à une requête et redémarre le compte à rebours du délai d’attente pour la connexion. En d’autres termes, si la connexion expire après au moins 4 heures d’inactivité, la pulsation réinitialise le chronomètre afin que l’expiration ne se produise pas au moins 4 heures après la dernière pulsation (ou requête).

La valeur par défaut est de 3 600 secondes (une heure). La plage de valeurs valide est 900 - 3600. Comme les expirations surviennent généralement après au moins 4 heures, une pulsation toutes les heures est normalement suffisante pour maintenir la connexion en vie. Des intervalles de pulsation inférieurs à 3 600 secondes sont rarement nécessaires ou utiles.

Certaines options de connexion supposent que l’objet de base de données spécifié (base de données, schéma, entrepôt ou rôle) existe déjà dans le système. Si l’objet spécifié n’existe pas, un réglage par défaut n’est pas défini lors de la connexion.

Après la connexion, toutes les options de connexion optionnelles peuvent également être réglées ou remplacées par la commande USE <objet>.

Vérification de la connexion réseau à Snowflake avec SnowCD

Après avoir configuré votre pilote, vous pouvez évaluer et dépanner votre connectivité réseau à Snowflake en utilisant SnowCD.

Vous pouvez utiliser SnowCD pendant le processus de configuration initiale et à la demande à tout moment pour évaluer et dépanner votre connexion réseau à Snowflake.

OCSP (Online Certificate Status Protocol)

Lorsque le pilote se connecte, Snowflake envoie un certificat confirmant que la connexion est établie avec Snowflake plutôt qu’avec un hôte empruntant l’identité de Snowflake. Le pilote envoie ce certificat à un serveur OCSP (protocole de statut de certificat en ligne) pour vérifier que le certificat n’a pas été révoqué.

Si le pilote ne peut pas atteindre le serveur OCSP pour vérifier le certificat, il peut entrainer un comportement « Fail open » ou « Fail closed ».

Choix du mode Fail-Open ou Fail-Close

Les versions de pilotes Node.js antérieures à la version 1.2.0 activent le mode Fail Close par défaut. Les versions 1.2.0 et ultérieures s’ouvrent avec le mode Fail-Open par défaut. Vous pouvez remplacer le comportement par défaut en définissant le paramètre global ocspFailOpen avant d’appeler la méthode snowflake.createConnection(). Vous pouvez définir le paramètre sur Vrai ou Faux.

snowflake.configure( {ocspFailOpen: false} );
const connection = snowflake.createConnection(
    {
    account: <account>,
    ...
    }
);

Vérification de la version du connecteur ou du pilote OCSP

Pour plus d’informations sur la version du pilote ou du connecteur, la configuration et le comportement OCSP, voir Configuration d’OCSP.

Exécution d’instructions

Les instructions peuvent être exécutées en utilisant la méthode connection.execute(). La méthode execute() accepte un objet options qui peut être utilisé pour spécifier le texte SQL et un rappel complete. Le rappel complete est invoqué lorsqu’une instruction est terminée et que le résultat est prêt à être exploité :

var statement = connection.execute({
  sqlText: 'create database testdb',
  complete: function(err, stmt, rows) {
    if (err) {
      console.error('Failed to execute statement due to the following error: ' + err.message);
    } else {
      console.log('Successfully executed statement: ' + stmt.getSqlText());
    }
  }
});

Paramètres d’instruction de liaison

Il peut arriver que vous souhaitiez lier des données dans une instruction avec un caractère de remplacement. Exécuter des instructions de cette manière est utile car cela aide à prévenir les attaques par injection de commandes SQL. Considérez l’énoncé suivant :

connection.execute({
  sqlText: 'select c1 from (select 1 as c1 union all select 2 as c1) where c1 = 1;'
});

Vous pouvez obtenir le même résultat en utilisant les liaisons suivantes :

connection.execute({
  sqlText: 'select c1 from (select :1 as c1 union all select :2 as c1) where c1 = :1;',
  binds: [1, 2]
});

La syntaxe ? pour les liaisons est également prise en charge :

connection.execute({
  sqlText: 'select c1 from (select ? as c1 union all select ? as c1) where c1 = ?;',
  binds: [1, 2, 1]
});

Note

Il existe une limite supérieure à la taille des données que vous pouvez lier ou que vous pouvez combiner dans un lot. Pour plus de détails, voir Limites de la taille du texte de requête.

Lier un tableau pour une insertion en masse

La liaison d’un tableau de données est prise en charge pour le fonctionnement en masse INSERT. Transmettez un tableau de tableau comme suit :

connection.execute({
  sqlText: 'insert into t(c1, c2, c3) values(?, ?, ?)',
  binds: [[1, 'string1', 2.0], [2, 'string2', 4.0], [3, 'string3', 6.0]]
});

Note

Le fait de lier un grand tableau aura une conséquence sur les performances et pourrait être refusé si la taille des données est trop grande pour être gérée par le serveur.

Annulation d’instructions

Une instruction peut être annulée en utilisant la méthode statement.cancel() :

statement.cancel(function(err, stmt) {
  if (err) {
    console.error('Unable to abort statement due to the following error: ' + err.message);
  } else {
    console.log('Successfully aborted statement');
  }
});

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

Il est également possible d’exploiter un résultat sous forme de flux de lignes. Ceci peut être fait en utilisant la méthode statement.streamRows(). Ceci retourne un flux Node.js Readable qui peut être utilisé pour exploiter les lignes lorsqu’elles sont reçues. Pour plus d’informations sur le flux Readable, voir la documentation Node.js.

Par exemple :

var statement = connection.execute({
  sqlText: 'select * from sometable'
});

var stream = statement.streamRows();

stream.on('error', function(err) {
  console.error('Unable to consume all rows');
});

stream.on('data', function(row) {
  // consume result row...
});

stream.on('end', function() {
  console.log('All rows consumed');
});

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, voir le 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érer 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.

Il y a deux façons de définir ce paramètre :

  • 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(
          {
          accessUrl: 'http://xy12345.snowflakecomputing.com',
          username: 'fakeusername',
          password: 'fakepassword',
          account: 'fakeaccount',
          jsTreatIntegerAsBigInt: true
          }
        );
    

Récupération des types de données sous forme de chaînes

Lorsque connection.execute() est appelé, l’option fetchAsString peut être définie pour forcer tous les nombres ou dates à être retournés sous forme de chaînes. Ceci peut être utilisé pour obtenir les éléments suivants :

  • 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.

Par exemple :

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

Mettre fin à une connexion

Une connexion peut être interrompue en utilisant la méthode connection.destroy(). Ceci met fin immédiatement à la session associée à la connexion sans attendre la fin des instructions en cours d’exécution :

connection.destroy(function(err, conn) {
  if (err) {
    console.error('Unable to disconnect: ' + err.message);
  } else {
    console.log('Disconnected connection with id: ' + connection.getId());
  }
});