Databricks SQL Driver for Node.js

Databricks SQL Driver for Node.js は、JavaScript コードを使用して Azure Databricks コンピューティング リソースで SQL コマンドを実行できる Node.js ライブラリです。

必要条件

  • Node.js バージョン 14 以降を実行している開発マシン。 インストールされているバージョンの Node.js を印刷するには、コマンド node -v を実行します。 さまざまなバージョンの Node.js をインストールして使用するには、ノード バージョン マネージャー (nvm) などのツールを使用できます。

  • ノード パッケージ マネージャー (npm)。 新しいバージョンの Node.js には npm が既に含まれています。 npm がインストールされているかどうかを確認するには、コマンド npm -v を実行します。 必要に応じて npm をインストールするには、npm のダウンロードとインストールに関連するページにあるような手順に従います。

  • npm@databricks/sql パッケージ。 お使いの Node.js プロジェクトに @databricks/sql パッケージを依存関係としてインストールするには、npm を使用して、プロジェクトと同じディレクトリから次のコマンドを実行します。

    npm i @databricks/sql
    
  • Node.js プロジェクトで TypeScript をインストールして devDependencies として使用する場合は、npm を使用して、プロジェクトと同じディレクトリ内から次のコマンドを実行します。

    npm i -D typescript
    npm i -D @types/node
    
  • 既存のクラスターまたは SQL ウェアハウス

  • 既存のクラスターまたは SQL ウェアハウスの サーバーホスト名HTTP パス の値。

認証

Databricks SQL Driver for Node.js は、次の Azure Databricks 認証の種類をサポートしています。

Databricks SQL Driver for Node.js では、次の Azure Databricks 認証の種類はまだサポートされません。

Note

セキュリティのベスト プラクティスとして、接続変数の値をコードにハード コーディングしないでください。 代わりに、セキュリティで保護された場所からこれらの接続変数の値を取得する必要があります。 たとえば、この記事のコード スニペットと例では環境変数を使います。

Databricks 個人用アクセス トークン認証

Databricks SQL Driver for Node.js を Azure Databricks の個人用アクセス トークン認証で使うには、まず、次のように Azure Databricks 個人用アクセス トークンを作成する必要があります。

  1. Azure Databricks ワークスペースの上部バーで、目的の Azure Databricks ユーザー名をクリックし、次にドロップダウンから [設定] を選択します。
  2. [開発者] をクリックします。
  3. [アクセス トークン] の横にある [管理] をクリックします。
  4. [新しいトークンの生成] をクリックします。
  5. (省略可能) 将来このトークンを識別するのに役立つコメントを入力し、トークンの既定の有効期間 90 日を変更します。 有効期間のないトークンを作成するには (推奨されません)、[有効期間 (日)] ボックスを空のままにします。
  6. [Generate](生成) をクリックします。
  7. 表示されたトークンを安全な場所にコピーし、[完了] をクリックします。

Note

コピーしたトークンは必ず安全な場所に保存してください。 コピーしたトークンは他人に見せないでください。 コピーしたトークンを失った場合、それとまったく同じトークンは再生成できません。 代わりに、この手順を繰り返して新しいトークンを作成する必要があります。 コピーしたトークンを紛失した場合や、トークンが侵害されていると思われる場合、Databricks では、[アクセス トークン] ページのトークンの横にあるごみ箱 ([取り消し]) アイコンをクリックして、ワークスペースからそのトークンをすぐに削除することを強くお勧めします。

ワークスペースでトークンを作成することや使用することができない場合は、ワークスペース管理者によってトークンが無効にされているか、トークンを作成または使用する権限が作業者に付与されていない可能性があります。 ワークスペース管理者に連絡するか、以下のトピックを参照してください。

Databricks SQL Driver for Node.js を認証するには、次のコード スニペットを使います。 このスニペットでは、次の環境変数を設定していることを前提としています。

  • DATABRICKS_SERVER_HOSTNAME は、お使いのクラスターまたは SQL ウェアハウスのサーバー ホスト名の値に設定します。
  • DATABRICKS_HTTP_PATH が、クラスターまたは SQL ウェアハウスの HTTP パスの値に設定されていること。
  • DATABRICKS_TOKEN が、Azure Databricks 個人用アクセス トークンに設定されていること。

環境変数を設定するには、オペレーティング システムのドキュメントを参照してください。

JavaScript

const { DBSQLClient } = require('@databricks/sql');

const serverHostname = process.env.DATABRICKS_SERVER_HOSTNAME;
const httpPath       = process.env.DATABRICKS_HTTP_PATH;
const token          = process.env.DATABRICKS_TOKEN;

if (!token || !serverHostname || !httpPath) {
    throw new Error("Cannot find Server Hostname, HTTP Path, or " +
                    "personal access token. " +
                    "Check the environment variables DATABRICKS_SERVER_HOSTNAME, " +
                    "DATABRICKS_HTTP_PATH, and DATABRICKS_TOKEN.");
  }

  const client = new DBSQLClient();
  const connectOptions = {
    token: token,
    host:  serverHostname,
    path:  httpPath
  };

  client.connect(connectOptions)
  // ...

TypeScript

import { DBSQLClient } from "@databricks/sql";

const serverHostname: string = process.env.DATABRICKS_SERVER_HOSTNAME || '';
const httpPath: string       = process.env.DATABRICKS_HTTP_PATH || '';
const token: string          = process.env.DATABRICKS_TOKEN || '';

if (token == '' || serverHostname == '' || httpPath == '') {
    throw new Error("Cannot find Server Hostname, HTTP Path, or personal access token. " +
                    "Check the environment variables DATABRICKS_SERVER_HOSTNAME, " +
                    "DATABRICKS_HTTP_PATH, and DATABRICKS_TOKEN.");
  }

  const client: DBSQLClient = new DBSQLClient();
  const connectOptions = {
    token: token,
    host:  serverHostname,
    path:  httpPath
  };

  client.connect(connectOptions)
  // ...

OAuth ユーザー対マシン (U2M) 認証

Databricks SQL Driver for Node.js バージョン 1.8.0 以上では、OAuth ユーザー対マシン (U2M) 認証をサポートします。

OAuth U2M 認証で Databricks SQL Driver for Node.js を認証するには、次のコード スニペットを使用します。 このスニペットでは、次の環境変数を設定していることを前提としています。

  • DATABRICKS_SERVER_HOSTNAME は、お使いのクラスターまたは SQL ウェアハウスのサーバー ホスト名の値に設定します。
  • DATABRICKS_HTTP_PATH が、クラスターまたは SQL ウェアハウスの HTTP パスの値に設定されていること。

環境変数を設定するには、オペレーティング システムのドキュメントを参照してください。

JavaScript

const { DBSQLClient } = require('@databricks/sql');

const serverHostname = process.env.DATABRICKS_SERVER_HOSTNAME;
const httpPath       = process.env.DATABRICKS_HTTP_PATH;

if (!serverHostname || !httpPath) {
    throw new Error("Cannot find Server Hostname or HTTP Path. " +
                    "Check the environment variables DATABRICKS_SERVER_HOSTNAME " +
                    "and DATABRICKS_HTTP_PATH.");
  }

  const client = new DBSQLClient();
  const connectOptions = {
    authType:                  "databricks-oauth",
    useDatabricksOAuthInAzure: true,
    host:                      serverHostname,
    path:                      httpPath
  };

  client.connect(connectOptions)
  // ...

TypeScript

import { DBSQLClient } from "@databricks/sql";

const serverHostname: string = process.env.DATABRICKS_SERVER_HOSTNAME || '';
const httpPath: string       = process.env.DATABRICKS_HTTP_PATH || '';

if (serverHostname == '' || httpPath == '') {
    throw new Error("Cannot find Server Hostname or HTTP Path. " +
                    "Check the environment variables DATABRICKS_SERVER_HOSTNAME " +
                    "and DATABRICKS_HTTP_PATH.");
  }

  const client: DBSQLClient = new DBSQLClient();
  const connectOptions = {
    authType:                  "databricks-oauth",
    useDatabricksOAuthInAzure: true,
    host:                      serverHostname,
    path:                      httpPath
  };

  client.connect(connectOptions)
  // ...

OAuth マシン間 (M2M) 認証

Databricks SQL Driver for Node.js バージョン 1.8.0 以上では、OAuth マシン間 (M2M) 認証をサポートします。

OAuth M2M 認証で Databricks SQL Driver for Node.js を使用するには、次を実行する必要があります。

  1. Azure Databricks ワークスペースで Azure Databricks サービス プリンシパルを作成し、そのサービス プリンシパルの OAuth シークレットを作成します。

    サービスプリンシパルと OAuth シークレットを作成するには、「OAuth(OAuth M2M)を使用してサービスプリンシパルで Azure Databricks へのアクセスを認証する」を参照してください。 サービス プリンシパルの UUID またはアプリケーション ID の値と、サービス プリンシパルの OAuth シークレットのシークレットを書き留めておいてください。

  2. サービス プリンシパルにクラスターまたはウェアハウスへのアクセス権を付与します。 「コンピューティングのアクセス許可」または「SQL ウェアハウスを管理する」を参照してください。

Databricks SQL Driver for Node.js を認証するには、次のコード スニペットを使います。 このスニペットでは、次の環境変数を設定していることを前提としています。

  • DATABRICKS_SERVER_HOSTNAME は、お使いのクラスターまたは SQL ウェアハウスのサーバー ホスト名の値に設定します。
  • DATABRICKS_HTTP_PATH が、クラスターまたは SQL ウェアハウスの HTTP パスの値に設定されていること。
  • DATABRICKS_CLIENT_ID。サービス プリンシパルの UUID またはアプリケーション ID の値に設定します。
  • DATABRICKS_CLIENT_SECRET が、サービス プリンシパルの OAuth シークレットの [シークレット] 値に設定されていること。

環境変数を設定するには、オペレーティング システムのドキュメントを参照してください。

JavaScript

const { DBSQLClient } = require('@databricks/sql');

const serverHostname = process.env.DATABRICKS_SERVER_HOSTNAME;
const httpPath       = process.env.DATABRICKS_HTTP_PATH;
const clientId       = process.env.DATABRICKS_CLIENT_ID;
const clientSecret   = process.env.DATABRICKS_CLIENT_SECRET;

if (!serverHostname || !httpPath || !clientId || !clientSecret) {
    throw new Error("Cannot find Server Hostname, HTTP Path, or " +
                    "service principal ID or secret. " +
                    "Check the environment variables DATABRICKS_SERVER_HOSTNAME, " +
                    "DATABRICKS_HTTP_PATH, DATABRICKS_CLIENT_ID, and " +
                    "DATABRICKS_CLIENT_SECRET.");
  }

  const client = new DBSQLClient();
  const connectOptions = {
    authType:                  "databricks-oauth",
    useDatabricksOAuthInAzure: true,
    host:                      serverHostname,
    path:                      httpPath,
    oauthClientId:             clientId,
    oauthClientSecret:         clientSecret
  };

  client.connect(connectOptions)
  // ...

TypeScript

import { DBSQLClient } from "@databricks/sql";

const serverHostname: string = process.env.DATABRICKS_SERVER_HOSTNAME || '';
const httpPath: string       = process.env.DATABRICKS_HTTP_PATH || '';
const clientId: string       = process.env.DATABRICKS_CLIENT_ID || '';
const clientSecret: string   = process.env.DATABRICKS_CLIENT_SECRET || '';

if (serverHostname == '' || httpPath == '' || clientId == '' || clientSecret == '') {
    throw new Error("Cannot find Server Hostname, HTTP Path, or " +
                    "service principal ID or secret. " +
                    "Check the environment variables DATABRICKS_SERVER_HOSTNAME, " +
                    "DATABRICKS_HTTP_PATH, DATABRICKS_CLIENT_ID, and " +
                    "DATABRICKS_CLIENT_SECRET.");
  }

  const client: DBSQLClient = new DBSQLClient();
  const connectOptions = {
    authType:                  "databricks-oauth",
    useDatabricksOAuthInAzure: true,
    host:                      serverHostname,
    path:                      httpPath,
    oauthClientId:             clientId,
    oauthClientSecret:         clientSecret
  };

  client.connect(connectOptions)
  // ...

Microsoft Entra ID トークン認証

Databricks SQL Driver for Node.js を Microsoft Entra ID トークン認証で使うには、Databricks SQL Driver for Node.js に Microsoft Entra ID トークンを指定する必要があります。 Microsoft Entra ID アクセス トークンを作成するには、次の操作を行います。

Microsoft Entra ID トークンの既定の有効期間は約 1 時間です。 新しい Microsoft Entra ID トークンを作成するには、このプロセスを繰り返します。

Databricks SQL Driver for Node.js を認証するには、次のコード スニペットを使います。 このスニペットでは、次の環境変数を設定していることを前提としています。

  • DATABRICKS_SERVER_HOSTNAME は、お使いのクラスターまたは SQL ウェアハウスのサーバー ホスト名の値に設定します。
  • DATABRICKS_HTTP_PATH が、クラスターまたは SQL ウェアハウスの HTTP パスの値に設定されていること。
  • DATABRICKS_TOKEN。Microsoft Entra ID トークンに設定します。

環境変数を設定するには、オペレーティング システムのドキュメントを参照してください。

JavaScript

const { DBSQLClient } = require('@databricks/sql');

const serverHostname = process.env.DATABRICKS_SERVER_HOSTNAME;
const httpPath       = process.env.DATABRICKS_HTTP_PATH;
const token          = process.env.DATABRICKS_TOKEN;

if (!token || !serverHostname || !httpPath) {
    throw new Error("Cannot find Server Hostname, HTTP Path, or " +
                    "<ms-entra-id> token. " +
                    "Check the environment variables DATABRICKS_SERVER_HOSTNAME, " +
                    "DATABRICKS_HTTP_PATH, and DATABRICKS_TOKEN.");
  }

  const client = new DBSQLClient();
  const connectOptions = {
    token: token,
    host:  serverHostname,
    path:  httpPath
  };

  client.connect(connectOptions)
  // ...

TypeScript

import { DBSQLClient } from "@databricks/sql";

const serverHostname: string = process.env.DATABRICKS_SERVER_HOSTNAME || '';
const httpPath: string       = process.env.DATABRICKS_HTTP_PATH || '';
const token: string          = process.env.DATABRICKS_TOKEN || '';

if (token == '' || serverHostname == '' || httpPath == '') {
    throw new Error("Cannot find Server Hostname, HTTP Path, or " +
                    "<ms-entra-id> token. " +
                    "Check the environment variables DATABRICKS_SERVER_HOSTNAME, " +
                    "DATABRICKS_HTTP_PATH, and DATABRICKS_TOKEN.");
  }

  const client: DBSQLClient = new DBSQLClient();
  const connectOptions = {
    token: token,
    host:  serverHostname,
    path:  httpPath
  };

  client.connect(connectOptions)
  // ...

クエリ データ

次のコード例では、Databricks SQL Driver for Node.js を呼び出して、Azure Databricks コンピューティング リソースで基本的な SQL クエリを実行する方法を示します。 このコマンドを使用すると、samples カタログの nyctaxi スキーマの trips テーブルから最初の 2 行が返されます。

Note

以下のコード例は、認証に Azure Databricks 個人用アクセス トークンをどのように使うかを示しています。 代わりに他の種類の使用可能な Azure Databricks 認証を使用するには、「認証」をご覧ください。

このコード例では、一連の Azure Databricks 環境変数から tokenserver_hostnamehttp_path 接続変数の値を取得します。 これらの環境変数には、次の環境変数名があります。

  • DATABRICKS_TOKEN は、要件からの Azure Databricks 個人用アクセス トークンを表します。
  • DATABRICKS_SERVER_HOSTNAME は、要件からのサーバー ホスト名を表します。
  • DATABRICKS_HTTP_PATH は、要件からの HTTP パスを表します。

これらの接続変数の値を取得するには、他の方法を使用できます。 環境変数の使用は、多くのアプローチの 1 つにすぎません。

次のコード例は、Databricks SQL Connector for Node.js を呼び出して、クラスターまたは SQL ウェアハウスで基本的な SQL コマンドを実行する方法を示しています。 このコマンドにより、trips テーブルから最初の 2 行が返されます。

JavaScript

const { DBSQLClient } = require('@databricks/sql');

const token          = process.env.DATABRICKS_TOKEN;
const serverHostname = process.env.DATABRICKS_SERVER_HOSTNAME;
const httpPath       = process.env.DATABRICKS_HTTP_PATH;

if (!token || !serverHostname || !httpPath) {
  throw new Error("Cannot find Server Hostname, HTTP Path, or personal access token. " +
                  "Check the environment variables DATABRICKS_TOKEN, " +
                  "DATABRICKS_SERVER_HOSTNAME, and DATABRICKS_HTTP_PATH.");
}

const client = new DBSQLClient();
const connectOptions = {
  token: token,
  host: serverHostname,
  path: httpPath
};

client.connect(connectOptions)
  .then(async client => {
    const session = await client.openSession();
    const queryOperation = await session.executeStatement(
      'SELECT * FROM samples.nyctaxi.trips LIMIT 2',
      {
        runAsync: true,
        maxRows:  10000 // This option enables the direct results feature.
      }
    );

    const result = await queryOperation.fetchAll();

    await queryOperation.close();

    console.table(result);

    await session.close();
    await client.close();
})
.catch((error) => {
  console.error(error);
});

TypeScript

import { DBSQLClient } from '@databricks/sql';
import IDBSQLSession from '@databricks/sql/dist/contracts/IDBSQLSession';
import IOperation from '@databricks/sql/dist/contracts/IOperation';

const serverHostname: string = process.env.DATABRICKS_SERVER_HOSTNAME || '';
const httpPath: string       = process.env.DATABRICKS_HTTP_PATH || '';
const token: string          = process.env.DATABRICKS_TOKEN || '';

if (serverHostname == '' || httpPath == '' || token == '') {
  throw new Error("Cannot find Server Hostname, HTTP Path, or personal access token. " +
                  "Check the environment variables DATABRICKS_SERVER_HOSTNAME, " +
                  "DATABRICKS_HTTP_PATH, and DATABRICKS_TOKEN.");
}

const client: DBSQLClient = new DBSQLClient();
const connectOptions = {
  host: serverHostname,
  path: httpPath,
  token: token
};

client.connect(connectOptions)
  .then(async client => {
    const session: IDBSQLSession = await client.openSession();

    const queryOperation: IOperation = await session.executeStatement(
      'SELECT * FROM samples.nyctaxi.trips LIMIT 2',
      {
        runAsync: true,
        maxRows: 10000 // This option enables the direct results feature.
      }
    );

    const result = await queryOperation.fetchAll();

    await queryOperation.close();

    console.table(result);

    await session.close();
    client.close();
  })
  .catch((error) => {
    console.error(error);
});

出力:

┌─────────┬─────┬────────┬───────────┬───────┬─────────┬────────┬───────┬───────┬────────┬────────┬────────┐
│ (index) │ _c0 │ carat  │    cut    │ color │ clarity │ depth  │ table │ price │   x    │   y    │   z    │
├─────────┼─────┼────────┼───────────┼───────┼─────────┼────────┼───────┼───────┼────────┼────────┼────────┤
│    0    │ '1' │ '0.23' │  'Ideal'  │  'E'  │  'SI2'  │ '61.5' │ '55'  │ '326' │ '3.95' │ '3.98' │ '2.43' │
│    1    │ '2' │ '0.21' │ 'Premium' │  'E'  │  'SI1'  │ '59.8' │ '61'  │ '326' │ '3.89' │ '3.84' │ '2.31' │
└─────────┴─────┴────────┴───────────┴───────┴─────────┴────────┴───────┴───────┴────────┴────────┴────────┘

セッション

API リファレンスIOperation オブジェクトを返すすべての IDBSQLSession メソッドには、動作に影響を与える次の一般的なパラメーターがあります。

  • runAsynctrue に設定すると、非同期モードが開始されます。 IDBSQLSession メソッドは操作をキューに格納し、可能な限り迅速に return を行います。 返された IOperation オブジェクトの現在の状態はさまざまに異なる可能性があり、クライアントは、返された IOperation を使用する前にその状態を確認する責任があります。 「操作」を参照してください。 runAsyncfalse に設定することは、IDBSQLSession メソッドが操作の完了を待機することを意味します。 Databricks は、常に runAsynctrue に設定することを推奨しています。
  • maxRows を null 以外の値に設定すると、直接の結果が得られます。 直接の結果では、サーバーは操作の完了を待機した後に、データの一部をフェッチしようとします。 定義された時間内にサーバーが完了できた作業量に応じて、IOperation オブジェクトは何らかの保留状態ではなく何らかの中間状態で return を行います。 大多数の場合、サーバーへの単一の要求内で、すべてのメタデータとクエリの結果が返されます。 サーバーは maxRows を使用して、すぐに返すことができるレコードの数を決定します。 ただし、実際のチャンクのサイズは異なる場合があります。IDBSQLSession.fetchChunk を参照してください。 直接の結果は既定で有効になっています。 Databricks は、直接の結果を無効にしないよう推奨しています。

操作

セッション」で説明されているように、API リファレンスIDBSQLSession セッション メソッドによって返される IOperation オブジェクトは完全には設定されていません。 Databricks SQL ウェアハウスの開始の待機、クエリの実行、データのフェッチなど、関連するサーバー操作がまだ進行中である場合があります。 IOperation クラスは、これらの詳細をユーザーから隠します。 たとえば、fetchAllfetchChunkgetSchema などのメソッドは、操作が完了するまで内部的に待機した後、結果を返します。 IOperation.finished() メソッドを使用して、操作の完了を明示的に待機できます。 これらのメソッドは、操作の完了を待機している間に定期的に呼び出されるコールバックを受け取ります。 progress オプションを true に設定すると、サーバーに追加の進行状況データを要求し、それをそのコールバックに渡すことが試みられます。

close および cancel メソッドは、いつでも呼び出すことができます。 呼び出されると、これらは IOperation オブジェクトをすぐに無効にし、fetchAllfetchChunkgetSchema などのすべての保留中の呼び出しはすぐに取り消され、エラーが返されます。 場合によっては、サーバー操作が既に完了していて、cancel メソッドが影響を与えるのはクライアントのみとなります。

fetchAll メソッドは内部的に fetchChunk を呼び出し、すべてのデータを配列へと収集します。 これは便利ですが、大規模なデータセットで使用するとメモリ不足エラーを引き起こす可能性があります。 fetchAll オプションは通常 fetchChunk に渡されます。

データのチャンクをフェッチする

データ チャンクのフェッチは、次のコード パターンを使用します。

do {
  const chunk = await operation.fetchChunk();
  // Process the data chunk.
} while (await operation.hasMoreRows());

API リファレンスfetchChunk メソッドは、メモリ消費を削減するために、データを小さな部分に分けて処理します。 fetchChunk は、操作がまだ完了していない場合は、まず操作の完了を待機し、その後、待機サイクル中にコールバックを呼び出してから、次のデータ チャンクをフェッチします。

maxRows オプションを使用して、目的のチャンク サイズを指定できます。 ただし、返されるチャンクのサイズが異なる場合があります。サイズが小さかったり、大きくなる場合さえあります。 fetchChunk は、要求された部分へとデータをスライスするために、データの内部的なプリフェッチは試みません。 これは maxRows オプションをサーバーに送信し、サーバーが返す内容が何であれ、それを返します。 この maxRows オプションを IDBSQLSession 内のオプションと混同しないでください。 fetchChunk に渡された maxRows は、各チャンクのサイズを定義し、それ以外には何も行いません。

Unity Catalog ボリューム内のファイルを管理する

Databricks SQL Driver を使用すると、次の例に示すように、Unity Catalog ボリュームにローカル ファイルを書き込み、ボリュームからファイルをダウンロードし、ボリュームからファイルを削除できるようになります。

JavaScript

const { DBSQLClient } = require('@databricks/sql');

const serverHostname = process.env.DATABRICKS_SERVER_HOSTNAME;
const httpPath       = process.env.DATABRICKS_HTTP_PATH;
const token          = process.env.DATABRICKS_TOKEN;

if (!token || !serverHostname || !httpPath) {
    throw new Error("Cannot find Server Hostname, HTTP Path, or " +
                    "personal access token. " +
                    "Check the environment variables DATABRICKS_SERVER_HOSTNAME, " +
                    "DATABRICKS_HTTP_PATH, and DATABRICKS_TOKEN.");
}

const client = new DBSQLClient();
const connectOptions = {
  token: token,
  host:  serverHostname,
  path:  httpPath
};

client.connect(connectOptions)
  .then(async client => {
    const session = await client.openSession();

    // Write a local file to a volume in the specified path.
    // For writing local files to volumes, you must first specify the path to the
    // local folder that contains the file to be written.
    // Specify OVERWRITE to overwrite any existing file in that path.
    await session.executeStatement(
      "PUT 'my-data.csv' INTO '/Volumes/main/default/my-volume/my-data.csv' OVERWRITE", {
        stagingAllowedLocalPath: ["/tmp/"]
      }
    );

    // Download a file from a volume in the specified path.
    // For downloading files in volumes, you must first specify the path to the
    // local folder that will contain the downloaded file.
    await session.executeStatement(
      "GET '/Volumes/main/default/my-volume/my-data.csv' TO 'my-downloaded-data.csv'", {
        stagingAllowedLocalPath: ["/Users/paul.cornell/samples/nodejs-sql-driver/"]
      }
    )

      // Delete a file in a volume from the specified path.
      // For deleting files from volumes, you must add stagingAllowedLocalPath,
      // but its value will be ignored. As such, in this example, an empty string is
      // specified.
      await session.executeStatement(
        "REMOVE '/Volumes/main/default/my-volume/my-data.csv'", {
          stagingAllowedLocalPath: [""]
        }
      )

      await session.close();
      await client.close();
  })
  .catch((error) => {
    console.error(error);
  });

TypeScript

import { DBSQLClient } from '@databricks/sql';

const serverHostname: string | undefined = process.env.DATABRICKS_SERVER_HOSTNAME;
const httpPath: string | undefined = process.env.DATABRICKS_HTTP_PATH;
const token: string | undefined = process.env.DATABRICKS_TOKEN;

if (!token || !serverHostname || !httpPath) {
  throw new Error("Cannot find Server Hostname, HTTP Path, or " +
                  "personal access token. " +
                  "Check the environment variables DATABRICKS_SERVER_HOSTNAME, " +
                  "DATABRICKS_HTTP_PATH, and DATABRICKS_TOKEN.");
}

const client: DBSQLClient = new DBSQLClient();
const connectOptions = {
  token: token,
  host: serverHostname,
  path: httpPath
};

client.connect(connectOptions)
  .then(async client => {
    const session = await client.openSession();

    // Write a local file to a volume in the specified path.
    // For writing local files to volumes, you must first specify the path to the
    // local folder that contains the file to be written.
    // Specify OVERWRITE to overwrite any existing file in that path.
    await session.executeStatement(
      "PUT 'my-data.csv' INTO '/Volumes/main/default/my-volume/my-data.csv' OVERWRITE", {
        stagingAllowedLocalPath: ["/tmp/"]
      }
    );

    // Download a file from a volume in the specified path.
    // For downloading files in volumes, you must first specify the path to the
    // local folder that will contain the downloaded file.
    await session.executeStatement(
      "GET '/Volumes/main/default/my-volume/my-data.csv' TO 'my-downloaded-data.csv'", {
        stagingAllowedLocalPath: ["/Users/paul.cornell/samples/nodejs-sql-driver/"]
      }
    )

    // Delete a file in a volume from the specified path.
    // For deleting files from volumes, you must add stagingAllowedLocalPath,
    // but its value will be ignored. As such, in this example, an empty string is
    // specified.
    await session.executeStatement(
      "REMOVE '/Volumes/main/default/my-volume/my-data.csv'", {
        stagingAllowedLocalPath: [""]
      }
    )

    await session.close();
    await client.close();
  })
  .catch((error: any) => {
    console.error(error);
  });

ログの構成

コネクタの問題をデバッグするための情報は、ロガーで提供されます。 すべての DBSQLClient オブジェクトは、コンソールに出力するロガーによってインスタンス化されますが、カスタム ロガーに渡せばこの情報をファイルに送信できます。 次の例は、ロガーを構成して、そのレベルを変更する方法を示しています。

JavaScript

const { DBSQLLogger, LogLevel } = require('@databricks/sql');
const logger = new DBSQLLogger({
  filepath: 'log.txt',
  level: LogLevel.info
});

// Set logger to different level.
logger.setLevel(LogLevel.debug);

TypeScript

import { DBSQLLogger, LogLevel } from '@databricks/sql';
const logger = new DBSQLLogger({
  filepath: 'log.txt',
  level: LogLevel.info,
});

// Set logger to different level.
logger.setLevel(LogLevel.debug);

その他の例については、GitHub の databricks/databricks-sql-nodejs リポジトリの examples フォルダーを参照してください。

テスト

コードをテストするには、Jest などの JavaScript テスト フレームワークを使用することができます。 Azure Databricks REST API エンドポイントを呼び出したり、Azure Databricks アカウントまたはワークスペースの状態を変更したりせずに、シミュレートされた条件下でコードをテストするには、Jest の組み込みのモック フレームワークを使用できます。

たとえば、Azure Databricks 個人用アクセス トークンを使用して Azure Databricks ワークスペースへの接続を返す getDBSQLClientWithPAT 関数と、その接続を使用して指定されたテーブル (samples カタログの nyctaxi スキーマ内の trips テーブル) から指定された数のデータ行を取得する getAllColumnsFromTable 関数と、該当するデータ行の内容を出力する printResults 関数を含む helpers.js という名前の次のようなファイルがあるとします。

// helpers.js

const { DBSQLClient } = require('@databricks/sql');

async function getDBSQLClientWithPAT(token, serverHostname, httpPath) {
  const client = new DBSQLClient();
  const connectOptions = {
    token: token,
    host: serverHostname,
    path: httpPath
  };
  try {
    return await client.connect(connectOptions);
  } catch (error) {
    console.error(error);
    throw error;
  }
}

async function getAllColumnsFromTable(client, tableSpec, rowCount) {
  let session;
  let queryOperation;
  try {
    session = await client.openSession();
    queryOperation = await session.executeStatement(
      `SELECT * FROM ${tableSpec} LIMIT ${rowCount}`,
      {
        runAsync: true,
        maxRows: 10000 // This option enables the direct results feature.
      }
    );
  } catch (error) {
    console.error(error);
    throw error;
  }
  let result;
  try {
    result = await queryOperation.fetchAll();
  } catch (error) {
    console.error(error);
    throw error;
  } finally {
    if (queryOperation) {
      await queryOperation.close();
    }
    if (session) {
      await session.close();
    }
  }
  return result;
}

function printResult(result) {
  console.table(result);
}

module.exports = {
  getDBSQLClientWithPAT,
  getAllColumnsFromTable,
  printResult
};

getDBSQLClientWithPATgetAllColumnsFromTableprintResults 関数を呼び出す main.js という名前の次のファイルを指定します。

// main.js

const { getDBSQLClientWithPAT, getAllColumnsFromTable, printResult } = require('./helpers');

const token          = process.env.DATABRICKS_TOKEN;
const serverHostname = process.env.DATABRICKS_SERVER_HOSTNAME;
const httpPath       = process.env.DATABRICKS_HTTP_PATH;
const tableSpec      = process.env.DATABRICKS_TABLE_SPEC;

if (!token || !serverHostname || !httpPath) {
  throw new Error("Cannot find Server Hostname, HTTP Path, or personal access token. " +
    "Check the environment variables DATABRICKS_TOKEN, " +
    "DATABRICKS_SERVER_HOSTNAME, and DATABRICKS_HTTP_PATH.");
}

if (!tableSpec) {
  throw new Error("Cannot find table spec in the format catalog.schema.table. " +
    "Check the environment variable DATABRICKS_TABLE_SPEC."
  )
}

getDBSQLClientWithPAT(token, serverHostname, httpPath)
  .then(async client => {
    const result = await getAllColumnsFromTable(client, tableSpec, 2);
    printResult(result);
    await client.close();
  })
  .catch((error) => {
    console.error(error);
  });

helpers.test.js という名前の次のファイルは、getAllColumnsFromTable 関数が、想定される応答を返すかどうかをテストします。 このテストでは、ターゲット ワークスペースへの実際の接続を作成するのではなく、DBSQLClient オブジェクトをモックします。 また、このテストでは、実際のデータ内にあるスキーマと値に準拠するデータをモックします。 テストでは、モックされた接続を介してモックされたデータが返され、モックされたデータ行の値のいずれかが期待値と一致するかどうかを確認します。

// helpers.test.js

const { getDBSQLClientWithPAT, getAllColumnsFromTable, printResult} = require('./helpers')

jest.mock('@databricks/sql', () => {
  return {
    DBSQLClient: jest.fn().mockImplementation(() => {
      return {
        connect: jest.fn().mockResolvedValue({ mock: 'DBSQLClient'})
      };
    }),
  };
});

test('getDBSQLClientWithPAT returns mocked Promise<DBSQLClient> object', async() => {
  const result = await getDBSQLClientWithPAT(
    token = 'my-token',
    serverHostname = 'mock-server-hostname',
    httpPath = 'mock-http-path'
  );

  expect(result).toEqual({ mock: 'DBSQLClient' });
});

const data = [
  {
    tpep_pickup_datetime: new Date(2016, 1, 13, 15, 51, 12),
    tpep_dropoff_datetime: new Date(2016, 1, 13, 16, 15, 3),
    trip_distance: 4.94,
    fare_amount: 19.0,
    pickup_zip: 10282,
    dropoff_zip: 10171
  },
  {
    tpep_pickup_datetime: new Date(2016, 1, 3, 17, 43, 18),
    tpep_dropoff_datetime: new Date(2016, 1, 3, 17, 45),
    trip_distance: 0.28,
    fare_amount: 3.5,
    pickup_zip: 10110,
    dropoff_zip: 10110
  }
];

const mockDBSQLClientForSession = {
  openSession: jest.fn().mockResolvedValue({
    executeStatement: jest.fn().mockResolvedValue({
      fetchAll: jest.fn().mockResolvedValue(data),
      close: jest.fn().mockResolvedValue(null)
    }),
    close: jest.fn().mockResolvedValue(null)
  })
};

test('getAllColumnsFromTable returns the correct fare_amount for the second mocked data row', async () => {
  const result = await getAllColumnsFromTable(
    client    = mockDBSQLClientForSession,
    tableSpec = 'mock-table-spec',
    rowCount  = 2);
  expect(result[1].fare_amount).toEqual(3.5);
});

global.console.table = jest.fn();

test('printResult mock prints the correct fare_amount for the second mocked data row', () => {
  printResult(data);
  expect(console.table).toHaveBeenCalledWith(data);
  expect(data[1].fare_amount).toBe(3.5);
});

TypeScript の場合、上記と同様のコードとなります。 TypeScript を使用した Jest テストでは、ts-jest を使用します。

その他のリソース

API リファレンス

クラス

DBSQLClient クラス

データベース操作のためのメイン エントリ ポイント。

メソッド
connect メソッド

データベースへの接続を開きます。

パラメーター
options

次のコマンドを入力します: ConnectionOptions

データベースに接続するために使用されるオプションのセット。

hostpath、その他の必須フィールドに設定する必要があります。 認証に関するページを参照してください。

例:


const client: DBSQLClient = new DBSQLClient();

client.connect(
{
host: serverHostname,
path: httpPath,
// ...
}
)

戻り値: Promise<IDBSQLClient>

openSession メソッド

DBSQLClient とデータベースの間のセッションを開きます。

パラメーター
request

次のコマンドを入力します: OpenSessionRequest

初期スキーマと初期カタログを指定するための省略可能なパラメーターのセット

例:


const session = await client.openSession(
{initialCatalog: 'catalog'}
);

戻り値: Promise<IDBSQLSession>

getClient メソッド

thrift の TCLIService.Client 内部オブジェクトを返します。 DBSQLClient の接続後に呼び出す必要があります。

パラメーターなし

戻り値 TCLIService.Client

close メソッド

データベースへの接続を閉じ、サーバー上のすべての関連リソースを解放します。 このクライアントへの追加呼び出しがあるとエラーがスローされます。

パラメーターはありません。

戻り値はありません。

DBSQLSession クラス

DBSQLSessions は主に、データベースに対するステートメントの実行と、さまざまなメタデータ フェッチ操作に使用されます。

メソッド
executeStatement メソッド

指定されたオプションを使用してステートメントを実行します。

パラメーター
statement

次のコマンドを入力します: str

実行されるステートメント。
options

次のコマンドを入力します: ExecuteStatementOptions

クエリのタイムアウト、直接の結果の最大行数、クエリを非同期的に実行するかどうかを決定する、一連の省略可能なパラメーター。 既定では、maxRows は 10,000 に設定されます。 maxRows が null に設定されている場合、操作は直接の結果の機能がオフの状態で実行されます。

例:


const session = await client.openSession(
{initialCatalog: 'catalog'}
);

queryOperation = await session.executeStatement(
'SELECT "Hello, World!"', { runAsync: true }
);

戻り値: Promise<IOperation>

close メソッド

セッションを閉じます。 セッションの使用後に行う必要があります。

パラメーターはありません。

戻り値はありません。

getId メソッド

セッションの GUID を返します。

パラメーターはありません。

戻り値: str

getTypeInfo メソッド

サポートされているデータ型に関する情報を返します。

パラメーター
request

次のコマンドを入力します: TypeInfoRequest

要求パラメーター。

戻り値: Promise<IOperation>

getCatalogs メソッド

カタログの一覧を取得します。

パラメーター
request

次のコマンドを入力します: CatalogsRequest

要求パラメーター。

戻り値: Promise<IOperation>

getSchemas メソッド

スキーマの一覧を取得します。

パラメーター
request

次のコマンドを入力します: SchemasRequest

要求パラメーター。 フィールド catalogName および schemaName は、フィルター処理の目的で使用できます。

戻り値: Promise<IOperation>

getTables メソッド

テーブルの一覧を取得します。

パラメーター
request

次のコマンドを入力します: TablesRequest

要求パラメーター。 フィールド catalogNameschemaName
tableName は、フィルター処理に使用できます。

戻り値: Promise<IOperation>

getFunctions メソッド

テーブルの一覧を取得します。

パラメーター
request

次のコマンドを入力します: FunctionsRequest

要求パラメーター。 フィールド functionName は必須です。

戻り値: Promise<IOperation>

getPrimaryKeys メソッド

主キーの一覧を取得します。

パラメーター
request

次のコマンドを入力します: PrimaryKeysRequest

要求パラメーター。 フィールド schemaName および tableName は必須です。

戻り値: Promise<IOperation>

getCrossReference メソッド

2 つのテーブル間の外部キーに関する情報を取得します。

パラメーター
request

次のコマンドを入力します: CrossReferenceRequest

要求パラメーター。 スキーマ、親、カタログ名は、両方のテーブルに対して指定する必要があります。

戻り値: Promise<IOperation>

DBSQLOperation クラス

DBSQLOperations は、DBSQLSessions によって作成され、ステートメントの結果をフェッチして、それらの実行を確認するために使用できます。 データは、fetchChunk 関数と fetchAll 関数によってフェッチされます。

メソッド
getId メソッド

操作の GUID を返します。

パラメーターはありません。

戻り値: str

fetchAll メソッド

操作の完了を待機し、その後、すべての行を操作からフェッチします。

パラメーター: なし

戻り値: Promise<Array<object>>

fetchChunk メソッド

操作の完了を待機し、その後、指定した数の行を操作からフェッチします。

パラメーター
options

次のコマンドを入力します: FetchOptions

フェッチに使用されるオプション。 現在のオプションは maxRows のみです。これは、特定の配列で返されるデータ オブジェクトの最大数に対応します。

戻り値: Promise<Array<object>>

close メソッド

接続を閉じ、関連付けられているすべてのリソースを解放します。 操作を使用しなくなった後で実行する必要があります。

パラメーターはありません。

戻り値はありません。