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 :

  1. Appelez snowflake.createConnection pour créer un nouvel objet Connection et transmettez un objet JavaScript qui spécifie les options de connexion.

  2. En utilisant l’objet Connection , appelez la méthode connect pour établir une connexion.

    Note

    Si vous attribuez à l’option authenticator la valeur EXTERNALBROWSER (afin d’utiliser SSO basé sur le navigateur) ou https://<nom_compte_okta>.okta.com (afin d’utiliser SSO natif d’Okta), appelez la méthode connectAsync plutôt que la méthode connect .

    Pour gérer les erreurs de connexion, transmettez une fonction de rappel qui a la signature suivante :

    function(err, conn)
    

    où :

    • err est un objet JavaScript Error.

    • conn est l’objet Connection actuel.

    Si une erreur se produit pendant la connexion, la méthode connect transmet un objet Error à votre fonction de rappel. Vous pouvez utiliser cet objet dans votre fonction de rappel pour obtenir des détails sur l’erreur. Si vous avez besoin d’informations sur l’objet Connection actuel, vous pouvez utiliser l’argument conn transmis à votre fonction de rappel.

L’exemple suivant établit une connexion et utilise un mot de passe pour l’authentification. Pour utiliser d’autres méthodes d’authentification, voir Options d’authentification.

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

Définition des options de connexion

Lors de la construction d’un nouvel objet Connection vous transmettez un objet JavaScript qui spécifie les options de la connexion (par exemple votre identificateur de compte, votre nom d’utilisateur, etc.). Les sections suivantes décrivent les options que vous pouvez définir. Pour définir une option, spécifiez le nom de l’option comme nom de propriété dans l’objet JavaScript.

Options de connexion requises

account

Votre identificateur de compte.

username

Le nom de connexion de votre utilisateur Snowflake ou de votre fournisseur d’identité (par exemple, votre nom de connexion pour Okta).

regionObsolète

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

Cette option n’est plus utilisée. Elle n’est documentée ici que pour des raisons de rétrocompatibilité.

En outre, vous devez spécifier les options d’authentification au serveur.

Options d’authentification

authenticator

Spécifie l’authentificateur à utiliser pour vérifier les identifiants de connexion utilisateur. Vous pouvez définir cette option sur l’une des valeurs suivantes :

Valeur

Description

SNOWFLAKE

Utilisez l’authentificateur interne Snowflake. Vous devez également définir l’option password.

EXTERNALBROWSER

Utilisez votre navigateur Web pour vous authentifier avec Okta, des ADFS ou tout autre fournisseur d’identification conforme à SAML 2.0 (IdP) qui a été défini pour votre compte.

https://<nom_compte_okta>.okta.com

Utilisez le SSO natif via Okta.

OAUTH

Utilisez OAuth pour l’authentification. Vous devez également définir l’option token sur le jeton OAuth (voir ci-dessous).

SNOWFLAKE_JWT

Utilisez l’authentification par paire de clés. Voir Utilisation de l’authentification par paires de clés et rotation des paires de clés.

La valeur par défaut est SNOWFLAKE.

Pour plus d’informations sur l’authentification, voir Gestion/utilisation de l’authentification fédérée et OAuth avec les clients, les pilotes et les connecteurs.

password

Mot de passe de l’utilisateur. Définissez cette option si vous définissez l’option authenticator sur SNOWFLAKE ou le point de terminaison de l” URL Okta pour votre compte Okta (par ex. https://<nom_compte_okta>.okta.com) ou si vous avez laissé l’option authenticator non définie.

token

Spécifie le jeton OAuth à utiliser pour l’authentification. Définissez cette option si vous avez défini l’option authenticator sur OAUTH.

privateKey

Spécifie la clé privée (au format PEM) pour l’authentification par paire de clés. Pour plus de détails, voir Utilisation de l’authentification par paires de clés et rotation des paires de clés.

privateKeyPath

Spécifie le chemin local au fichier de clé privée (par exemple, rsa_key.p8). Pour plus de détails, voir Utilisation de l’authentification par paires de clés et rotation des paires de clés.

privateKeyPass

Spécifie le code d’accès pour déchiffrer le fichier de la clé privée, si le fichier est chiffré. Pour plus de détails, voir Utilisation de l’authentification par paires de clés et rotation des paires de clés.

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 l’option clientSessionKeepAlive est définie 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 cette option est false.

Si vous définissez cette option 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

(Cette option ne s’applique que lorsque clientSessionKeepAlive est true)

Cette option 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>.

Authentification à Snowflake

Pour vous authentifier auprès de Snowflake, vous pouvez utiliser l’une des options suivantes :

Utilisation de l’authentification unique (SSO) via un navigateur Web

Si vous avez configuré Snowflake pour utiliser la connexion unique (SSO), vous pouvez configurer votre application cliente pour utiliser SSO sur navigateur pour l’authentification.

Dans le code de votre application :

  1. Définissez l’option authenticator sur EXTERNALBROWSER.

  2. Pour établir une connexion, appelez la méthode connectAsync plutôt que la méthode connect.

Par exemple :

// Use a browser to authenticate via SSO.
var connection = snowflake.createConnection({
  ...,
  authenticator: "EXTERNALBROWSER"
});
// Establish a connection. Use connectAsync, rather than connect.
connection.connectAsync(
  function (err, conn)
  {
    ... // Handle any errors.
  }
).then(() =>
{
  // Execute SQL statements.
  var statement = connection.execute({...});
});

Pour plus d’informations sur l’utilisation de SSO sur navigateur pour l’authentification, voir SSO basé sur le navigateur.

Utilisation de SSO natif via Okta

Si vous avez configuré Snowflake pour utiliser la connexion unique (SSO) via Okta, vous pouvez configurer votre application cliente pour utiliser l’authentification SSO native via Okta.

Dans le code de votre application :

  1. Définissez les options suivantes :

    • Définissez l’option authenticator sur le point de terminaison URL Okta de votre compte Okta (par exemple, https://<nom_compte_okta>.okta.com).

    • Définissez les options username et password sur le nom d’utilisateur et le mot de passe de votre fournisseur d’identité (IdP).

  2. Pour établir une connexion, appelez la méthode connectAsync plutôt que la méthode connect.

Par exemple :

// Use native SSO authentication through Okta.
var connection = snowflake.createConnection({
  ...,
  username: '<user_name_for_okta>',
  password: '<password_for_okta>',
  authenticator: "https://myaccount.okta.com"
});

// Establish a connection.
connection.connectAsync(
  function (err, conn)
  {
    ... // Handle any errors.
  }
);

// Execute SQL statements.
var statement = connection.execute({...});

Pour plus d’informations sur l’utilisation de l’authentification native SSO par Okta, voir SSO natif — Okta seulement.

Utilisation de l’authentification par paires de clés et rotation des paires de clés

Le pilote prend en charge l’authentification par paire de clés et la rotation des clés. Afin de l’utiliser :

  1. Configurez l’authentification par paire de clés, comme expliqué dans Authentification par paires de clés et rotation des paires de clés.

  2. Dans le code de votre application :

    1. Définissez l’option authenticator sur SNOWFLAKE_JWT.

    2. Utilisez la clé privée pour vous authentifier de l’une des manières suivantes :

      • Définissez l’option privateKey sur la clé privée.

      • Définissez l’option privateKeyPath comme le chemin d’accès au fichier de la clé privée.

        Si le fichier est chiffré, vous devez également définir l’option privateKeyPass sur la phrase secrète pour déchiffrer la clé privée.

L’exemple suivant charge la clé privée depuis un fichier et définit l’option privateKey sur la clé privée :

// Read the private key file from the filesystem.
var crypto = require('crypto');
var fs = require('fs');
var privateKeyFile = fs.readFileSync('<path_to_private_key_file>/rsa_key.p8');

// Get the private key from the file as an object.
const privateKeyObject = crypto.createPrivateKey({
  key: privateKeyFile,
  format: 'pem',
  passphrase: 'passphrase'
});

// Extract the private key from the object as a PEM-encoded string.
var privateKey = privateKeyObject.export({
  format: 'pem',
  type: 'pkcs8'
});

// Use the private key for authentication.
var connection = snowflake.createConnection({
  ...
  authenticator: "SNOWFLAKE_JWT",
  privateKey: privateKey
});

// Establish a connection.
connection.connect(
  function (err, conn)
  {
    ... // Handle any errors.
  }
);

// Execute SQL statements.
var statement = connection.execute({...});

L’exemple suivant définit l’option privateKeyPath sur un fichier de clé privée chiffré et définit l’option privateKeyPass sur la phrase secrète utilisée pour déchiffrer la clé privée :

// Use an encrypted private key file for authentication.
// Specify the passphrase for decrypting the key.
var connection = snowflake.createConnection({
  ...
  authenticator: "SNOWFLAKE_JWT",
  privateKeyFile: "<path-to-privatekey>/privatekey.p8",
  privateKeyPass: '<passphrase_to_decrypt_the_private_key>'
});

// Establish a connection.
connection.connect(
  function (err, conn)
  {
    ... // Handle any errors.
  }
);

// Execute SQL statements.
var statement = connection.execute({...});

Utilisation de OAuth

Pour se connecter en utilisant OAuth, définissez l’option authenticator sur OAUTH et l’option token sur le jeton d’accès OAuth. Par exemple :

// Use OAuth for authentication.
var connection = snowflake.createConnection({
  ...
  authenticator: "OAUTH",
  token: "<your_oauth_token>"
});

// Establish a connection.
connection.connect(
  function (err, conn)
  {
    ... // Handle any errors.
  }
);

// Execute SQL statements.
var statement = connection.execute({...});

Pour plus d’informations, voir OAuth avec les clients, les pilotes et les connecteurs.

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_identifier>,
    ...
    }
);

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://myorganization-myaccount.snowflakecomputing.com',
          username: 'fakeusername',
          password: 'fakepassword',
          account: 'fakeaccountidentifier',
          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());
  }
});