共用方式為


適用於 Node.js 的 Databricks SQL 驅動程式

適用於 Node.js 的 Databricks SQL 驅動程式是一個 Node.js 程式庫,可讓您使用 JavaScript 程式碼,在 Azure Databricks 計算資源上執行 SQL 命令。

需求

  • 執行 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 路徑值。

驗證

適用於 Node.js 的 Databricks SQL 驅動程式支援下列 Azure Databricks 驗證類型:

適用於 Node.js 的 Databricks SQL 驅動程式尚不支援下列 Azure Databricks 驗證類型:

注意

基於安全性最佳做法,您不應該將連線變數值硬式編碼到您的程式碼中。 相反地,您應從安全的位置擷取這些連線變數值。 例如,本文中的程式碼片段和範例會使用環境變數。

Databricks 個人存取權杖驗證

若要搭配 Azure Databricks 個人存取權杖驗證使用適用於 Node.js 的 Databricks SQL 驅動程式,您必須首先建立 Azure Databricks 個人存取權杖,如下所示:

  1. 在 Azure Databricks 工作區中,按一下頂端列中的 Azure Databricks 使用者名稱,然後從下拉式清單中選取 [設定]
  2. 按一下 [開發人員]
  3. 在 [存取權杖] 旁,按一下 [管理]
  4. 按一下 產生新權杖
  5. (選擇性) 輸入可協助您之後識別此權杖的註解,並變更權杖的預設存留期 90 天。 若要建立沒有存留期的權杖 (不建議),請將 [存留期 (天)] 方塊留空 (空白)。
  6. 按一下 產生
  7. 將顯示的權杖複製到安全位置,然後選取 [完成]

注意

請務必將複製的權杖儲存在安全位置。 請勿與其他人共用複製的權杖。 如果您遺失複製的權杖,就無法重新產生完全相同的權杖。 相反地,您必須重複此程序來建立新的權杖。 如果您遺失複製的權杖,或您認為權杖已遭入侵,Databricks 強烈建議您按一下 [存取權杖] 頁面上權杖旁邊的垃圾桶 (撤銷) 圖示,立即從工作區中刪除該權杖。

注意:如果您無法在工作區中建立或使用 PAT,這可能是因為您的工作區系統管理員已停用權杖,或未授與您建立或使用權杖的權限。 請諮詢您的工作區系統管理員或參閱下列主題:

若要驗證適用於 Node.js 的 Databricks SQL 驅動程式,請使用下列程式碼片段。 此片段假設您已設定下列環境變數:

  • 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) 驗證

適用於 Node.js 的 Databricks SQL 驅動程式 1.8.0 版和更新版本支援 OAuth 使用者對機器 (U2M) 驗證

若要使用 OAuth U2M 驗證來驗證適用於 Node.js 的 Databricks SQL 驅動程式,請使用下列程式碼片段。 此片段假設您已設定下列環境變數:

  • 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) 驗證

適用於 Node.js 的 Databricks SQL 驅動程式 1.8.0 版和更新版本支援 OAuth 機器對機器 (U2M) 驗證

若要使用 OAuth M2M 驗證來驗證適用於 Node.js 的 Databricks SQL 驅動程式,您必須執行下列動作:

  1. 在 Azure Databricks 工作區中建立 Azure Databricks 服務主體,並為該服務主體建立 OAuth 祕密。

    若要建立服務主體及其 OAuth 祕密,請參閱使用 OAuth (OAuth M2M) 透過服務主體對 Azure Databricks 的存取進行驗證。 記下服務主體的 [UUID] 或 [應用程式 ID] 值,以及服務主體 OAuth 祕密的 [祕密]值。

  2. 為服務主體提供叢集或倉儲的存取權。 請參閱計算權限管理 SQL 倉儲

若要驗證適用於 Node.js 的 Databricks SQL 驅動程式,請使用下列程式碼片段。 此片段假設您已設定下列環境變數:

  • DATABRICKS_SERVER_HOSTNAME 設定為叢集或 SQL 倉儲的 [伺服器主機名稱] 值。
  • DATABRICKS_HTTP_PATH,設定為叢集或 SQL 倉儲的 HTTP 路徑 值。
  • DATABRICKS_CLIENT_ID,設定為服務主體的 [UUID] 或 [應用程式 ID] 值。
  • DATABRICKS_CLIENT_SECRET,設定為 Azure Databricks 服務主體的 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 權杖驗證

若要使用適用於 Node.js 的 Databricks SQL 驅動程式搭配 Microsoft Entra ID 權杖驗證,您必須提供適用於 Node.js 的 Databricks SQL 驅動程式和 Microsoft Entra ID 權杖。 若要建立 Microsoft Entra ID 存取權杖,請按照下列步驟操作:

Microsoft Entra ID 權杖的預設存留期約為 1 小時。 若要建立新的 Microsoft Entra ID 權杖,請重複此程序。

若要驗證適用於 Node.js 的 Databricks SQL 驅動程式,請使用下列程式碼片段。 此片段假設您已設定下列環境變數:

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

查詢資料

下列程式碼範例示範如何呼叫適用於 Node.js 的 Databricks SQL 驅動程式,在 Azure Databricks 計算資源上執行基本 SQL 查詢。 此命令會從 samples 目錄的 nyctaxi 結構描述中的 trips 資料表傳回前兩個資料列。

注意

下列程式碼範例示範如何使用 Azure Databricks 個人存取權杖進行驗證。 若要改用其他可用的 Azure Databricks 驗證類型,請參閱驗證

此程式碼範例會從一組 Azure Databricks 環境變數擷取 tokenserver_hostnamehttp_path 連線變數值。 這些環境變數具有下列環境變數名稱:

  • DATABRICKS_TOKEN,代表來自需求的 Azure Databricks 個人存取權杖。
  • DATABRICKS_SERVER_HOSTNAME,代表來自需求的 [伺服器主機名稱] 值。
  • DATABRICKS_HTTP_PATH,代表來自需求的 [HTTP 路徑] 值。

您可使用其他方法來擷取這些連線變數值。 使用環境變數只是眾多方法之一。

下列程式碼範例示範如何呼叫適用於 Node.js 的 Databricks SQL 驅動程式,在叢集或 SQL 倉儲上執行基本 SQL 命令。 此命令會從 trips 資料表傳回前兩個資料列。

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 方法都有下列會影響其行為的常見參數:

  • runAsync 設定為 true 啟動異步模式。 IDBSQLSession 方法會將作業放入佇列中,並儘快傳回。 傳回 IOperation 物件的目前狀態可能會有所不同,而且用戶端會負責檢查其狀態,再使用傳回的 IOperation。 請參閱作業。 將 runAsync 設定為 false,表示 IDBSQLSession 方法會等候作業完成。 Databricks 建議一律將 runAsync 設定為 true
  • maxRows 設定為非 Null 值會啟用直接結果。 透過直接結果,伺服器會嘗試等候作業完成,然後擷取部分資料。 根據伺服器能夠在定義的時間內完成多少工作,IOperation 物件會以某些中繼狀態傳回,而不是在某些擱置狀態中傳回。 所有中繼資料和查詢結果通常會在單一要求內傳回給伺服器。 伺服器會使用 maxRows 來判斷可以立即傳回的記錄數量。 不過,實際區塊的大小可能不同;請參閱 IDBSQLSession.fetchChunk。 預設會啟用直接結果。 Databricks 建議禁止停用直接結果。

Operations

工作階段中所述,API 參考中的 IDBSQLSession 工作階段方法所傳回的 IOperation 物件不會完全填入。 相關的伺服器作業可能仍在進行中,例如等候 Databricks SQL 倉儲啟動、執行查詢或擷取資料。 IOperation 類別會向使用者隱藏這些詳細資料。 例如,fetchAllfetchChunkgetSchema 等方法會在內部等候作業完成,然後傳回結果。 您可使用 IOperation.finished() 方法來明確等候作業完成。 這些方法會採用在等候作業完成時,定期呼叫的回呼。 設定 true 選項,以 progress 嘗試向伺服器要求額外的進度資料,並將其傳遞至該回呼。

可以隨時呼叫 closecancel 方法。 呼叫時,它們會立即使 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 中的選項混淆。 傳遞至 fetchChunkmaxRows 定義每個區塊的大小,且不會執行任何其他動作。

管理 Unity 目錄磁碟區中的檔案

Databricks SQL 驅動程式可讓您將本機檔案寫入 Unity 目錄磁碟區、從磁碟區下載檔案,以及從磁碟區刪除檔案,如下列範例所示:

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 存放庫中的範例資料夾。

測試

若要測試程式碼,您可以使用 JavaScript 測試架構,例如 Jest。 若要在不呼叫 Azure Databricks REST API 端點或變更 Azure Databricks 帳戶或工作區的狀態的情況下,在模擬條件下測試程式碼,您可以使用 Jest 的內建模擬架構。

例如,假設下列名為 helpers.js 的檔案,其中包含使用 getDBSQLClientWithPAT Azure Databricks 個人存取權杖傳回 Azure Databricks 工作區連線的函式、使用連線從指定資料表取得指定資料列數目的 getAllColumnsFromTable 函式 (例如 samples 目錄 nyctaxi 結構描述中的 trips 資料表),以及列印資料列內容的 printResults 函式:

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

並假設下列名為 main.js 的檔案,該檔案會呼叫 getDBSQLClientWithPATgetAllColumnsFromTableprintResults 函式:

// 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 類別

DBSQLSession 主要用於對資料庫以及各種中繼資料擷取作業執行陳述式。

方法
executeStatement 方法

使用所提供的選項執行陳述式。

參數
陳述式

類型:str (英文)

要執行的陳述式。
options

類型:ExecuteStatementOptions (英文)

一組選擇性參數,用於判斷查詢逾時、直接結果的資料列上限,以及是否要以異步方式執行查詢。 預設會將 maxRows 設定為 10000。 如果將 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 (英文)

要求參數。 欄位 catalogNameschemaName 可用於篩選目的。

傳回:Promise<IOperation>

getTables 方法

取得資料表清單。

參數
request

類型:TablesRequest (英文)

要求參數。 欄位 catalogNameschemaName
tableName 可用於篩選。

傳回:Promise<IOperation>

getFunctions 方法

取得資料表清單。

參數
request

類型:FunctionsRequest (英文)

要求參數。 欄位 functionName 必填。

傳回:Promise<IOperation>

getPrimaryKeys 方法

取得主索引鍵的清單。

參數
request

類型:PrimaryKeysRequest (英文)

要求參數。 欄位 schemaNametableName 為必填項。

傳回:Promise<IOperation>

getCrossReference 方法

取得兩個資料表之間外部索引鍵的相關資訊。

參數
request

類型:CrossReferenceRequest (英文)

要求參數。 兩個資料表都必須指定結構描述、父系和目錄名稱。

傳回:Promise<IOperation>

DBSQLOperation 類別

DBSQLOperations 由 DBSQLSessions 所建立,可用來擷取陳述式的結果,並檢查其執行。 資料透過函式 fetchChunk 和 fetchAll 來擷取。

方法
getId 方法

傳回作業的 GUID。

無參數。

傳回:str

fetchAll 方法

等候作業完成,然後從作業擷取所有資料列。

參數:無

傳回:Promise<Array<object>>

fetchChunk 方法

等候作業完成,然後從作業擷取最多指定的資料列數目。

參數
options

類型:FetchOptions (英文)

用來擷取的選項。 目前,唯一的選項是 maxRows,其對應於任何指定陣列中要傳回的資料物件數目上限。

傳回:Promise<Array<object>>

close 方法

關閉作業,並釋放所有相關聯的資源。 必須在不再使用作業之後完成。

無參數。

沒有傳回值。