Поделиться через


Драйвер SQL Databricks для Node.js

Драйвер SQL Databricks для Node.js — это библиотека Node.js, которая позволяет использовать код JavaScript для выполнения команд SQL в вычислительных ресурсах Azure Databricks.

Требования

  • Компьютер разработки с Node.js версии 14 или более поздней. Чтобы узнать установленную версию Node.js, выполните команду node -v. Чтобы установить другие версии Node.js, можно использовать такие средства, как Node Version Manager (nvm).

  • Node Package Manager (npm). В последних версиях Node.js диспетчер npm уже включен. Чтобы проверить, установлен ли диспетчер npm, выполните команду npm -v. Чтобы при необходимости установить npm, можно выполнить инструкции, например в статье Скачивание и установка npm.

  • Пакет @databricks/sql из npm. Чтобы установить пакет @databricks/sql в проекте Node.js в качестве зависимости, используйте npm для выполнения следующей команды в том же каталоге, где находится ваш проект:

    npm i @databricks/sql
    
  • Если требуется установить и использовать TypeScript в проекте Node.js в качестве devDependencies, используйте npm для выполнения следующей команды в том же каталоге, где находится ваш проект:

    npm i -D typescript
    npm i -D @types/node
    
  • Существующий кластер или хранилище SQL.

  • Значения имени узла сервера и пути HTTP для существующего кластера или хранилища SQL.

Проверка подлинности

Драйвер SQL Databricks для Node.js поддерживает следующие типы проверки подлинности Azure Databricks:

Драйвер SQL Databricks для Node.js пока не поддерживает следующие типы проверки подлинности Azure Databricks:

Примечание.

В качестве рекомендации по обеспечению безопасности в коде не следует жестко изменять значения переменных подключения кода. Вместо этого их следует извлекать из безопасного расположения. Например, фрагменты кода и примеры в этой статье используют переменные среды.

Проверка подлинности маркера личного доступа Databricks

Чтобы использовать драйвер SQL Databricks для Node.js с проверкой подлинности маркера личного доступа Azure Databricks, необходимо сначала создать личный маркер доступа Azure Databricks, как показано ниже.

  1. В рабочей области Azure Databricks щелкните имя пользователя Azure Databricks в верхней строке и выберите "Параметры " в раскрывающемся списке.
  2. Щелкните "Разработчик".
  3. Рядом с маркерами доступа нажмите кнопку "Управление".
  4. Щелкните Generate new token (Создание нового маркера).
  5. (Необязательно) Введите комментарий, который поможет определить этот маркер в будущем и изменить время существования маркера по умолчанию в течение 90 дней. Чтобы создать маркер без времени существования (не рекомендуется), оставьте поле время существования (дни) пустым (пустым).
  6. Щелкните Создать.
  7. Скопируйте отображаемый маркер в безопасное расположение и нажмите кнопку "Готово".

Примечание.

Не забудьте сохранить скопированный маркер в безопасном расположении. Не делитесь скопированным маркером с другими пользователями. Если вы потеряете скопированный маркер, вы не сможете повторно создать тот же маркер. Вместо этого необходимо повторить эту процедуру, чтобы создать новый маркер. Если вы потеряете скопированный маркер или считаете, что маркер скомпрометирован, Databricks настоятельно рекомендует немедленно удалить этот маркер из рабочей области, щелкнув значок корзины (отозвать) рядом с маркером на странице маркеров доступа.

Если вы не можете создавать или использовать маркеры в рабочей области, это может быть связано с тем, что администратор рабочей области отключил маркеры или не предоставил вам разрешение на создание или использование маркеров. Ознакомьтесь с администратором рабочей области или следующими разделами:

Чтобы проверить подлинность драйвера SQL Databricks для Node.js, используйте следующий фрагмент кода. В этом фрагменте предполагается, что вы установили следующие переменные среды:

  • DATABRICKS_SERVER_HOSTNAMEЗадайте для кластера или хранилища SQL значение имени узла сервера.
  • DATABRICKS_HTTP_PATH, установите значение HTTP-пути для кластера или хранилища SQL.
  • 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).

Чтобы проверить подлинность драйвера SQL Databricks для Node.js с проверкой подлинности OAuth U2M, используйте следующий фрагмент кода. В этом фрагменте предполагается, что вы установили следующие переменные среды:

  • DATABRICKS_SERVER_HOSTNAMEЗадайте для кластера или хранилища SQL значение имени узла сервера.
  • DATABRICKS_HTTP_PATH, установите значение HTTP-пути для кластера или хранилища SQL.

Чтобы задать переменные среды, ознакомьтесь с документацией операционной системы.

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

Проверка подлинности на компьютере (M2M) OAuth

Databricks SQL Driver for Node.js версии 1.8.0 и выше поддерживает проверку подлинности OAuth на компьютере (U2M).

Чтобы использовать драйвер SQL Databricks для Node.js с проверкой подлинности OAuth M2M, необходимо выполнить следующее:

  1. Создайте субъект-службу Azure Databricks в рабочей области Azure Databricks и создайте секрет OAuth для этого субъекта-службы.

    Чтобы создать субъект-службу и секрет OAuth, ознакомьтесь с проверкой подлинности доступа к Azure Databricks с помощью субъекта-службы с помощью OAuth (OAuth M2M). Запишите значение UUID или идентификатора приложения субъекта-службы и значение секрета для секрета OAuth субъекта-службы.

  2. Предоставьте субъекту-службе доступ к кластеру или хранилищу. См . сведения о разрешениях вычислений или управлении хранилищем SQL.

Чтобы проверить подлинность драйвера SQL Databricks для Node.js, используйте следующий фрагмент кода. В этом фрагменте предполагается, что вы установили следующие переменные среды:

  • DATABRICKS_SERVER_HOSTNAMEЗадайте для кластера или хранилища SQL значение имени узла сервера.
  • DATABRICKS_HTTP_PATH, установите значение HTTP-пути для кластера или хранилища SQL.
  • DATABRICKS_CLIENT_IDЗначение UUID субъекта-службы или идентификатора приложения.
  • 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

Чтобы использовать драйвер SQL Databricks для Node.js с проверкой подлинности маркера идентификатора Microsoft Entra, необходимо указать драйвер SQL Databricks для Node.js с маркером идентификатора Microsoft Entra ID. Чтобы создать маркер доступа идентификатора Microsoft Entra, сделайте следующее:

Маркеры идентификатора Microsoft Entra имеют время существования по умолчанию около 1 часа. Чтобы создать новый маркер идентификатора Microsoft Entra, повторите этот процесс.

Чтобы проверить подлинность драйвера SQL Databricks для Node.js, используйте следующий фрагмент кода. В этом фрагменте предполагается, что вы установили следующие переменные среды:

  • DATABRICKS_SERVER_HOSTNAMEЗадайте для кластера или хранилища SQL значение имени узла сервера.
  • DATABRICKS_HTTP_PATH, установите значение HTTP-пути для кластера или хранилища SQL.
  • 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 для Node.js с целью выполнения простого SQL-запроса к вычислительному ресурсу Azure Databricks. Эта команда возвращает первые две строки из trips таблицы в схеме samples каталога nyctaxi .

Примечание.

В следующем примере кода показано, как использовать личный маркер доступа Azure Databricks для проверки подлинности. Чтобы использовать другие доступные типы проверки подлинности Azure Databricks, см. статью "Проверка подлинности".

В этом примере кода извлекаются tokenserver_hostname значения переменных подключения из http_path набора переменных среды Azure Databricks. Эти переменные среды имеют следующие имена:

  • DATABRICKS_TOKEN представляет личный маркер доступа Azure Databricks согласно требованиям;
  • DATABRICKS_SERVER_HOSTNAME, которая предоставляет значение Имени узла сервера в соответствии с требованиями.
  • DATABRICKS_HTTP_PATH, которая предоставляет значение Пути HTTP в соответствии с требованиями.

Вы можете использовать другие подходы для получения значений этих переменных подключения. Переменные среды — лишь один из них.

В следующем примере кода показано, как вызвать соединитель SQL Databricks для Node.js для выполнения базовой команды 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' │
└─────────┴─────┴────────┴───────────┴───────┴─────────┴────────┴───────┴───────┴────────┴────────┴────────┘

Сеансы

Все IDBSQLSession методы, возвращающие IOperation объекты в справочнике по API, имеют следующие общие параметры, влияющие на их поведение:

  • Параметр runAsync запуска true асинхронного режима. IDBSQLSession Методы помещают операции в очередь и возвращаются как можно быстрее. Текущее состояние возвращаемого объекта может отличаться, и клиент отвечает за проверку состояния перед использованием возвращаемого IOperation IOperationобъекта. См . статью "Операции". Значение параметра runAsync false означает, что IDBSQLSession методы ожидают завершения операций. Databricks рекомендует всегда задавать значение runAsync true.
  • Если задать maxRows значение, отличное от NULL, можно получить прямые результаты. С прямыми результатами сервер пытается ждать завершения операций, а затем извлекает часть данных. В зависимости от того, сколько работы сервера удалось выполнить в течение определенного времени, IOperation объекты возвращаются в некотором промежуточном состоянии вместо некоторого ожидающего состояния. Часто все метаданные и результаты запроса возвращаются в рамках одного запроса на сервер. Сервер использует maxRows для определения количества записей, которые он может возвращать немедленно. Однако фактический блок может иметь другой размер; см. раздел IDBSQLSession.fetchChunk. Прямые результаты включены по умолчанию. Databricks рекомендует отключить прямые результаты.

Операции

Как описано в разделе "Сеансы", объекты, возвращаемые IDBSQLSession методами сеансов в справочнике по API, IOperation не заполнены полностью. Связанная операция сервера может по-прежнему выполняться, например ожидание запуска хранилища SQL Databricks, выполнение запроса или получение данных. Класс IOperation скрывает эти сведения от пользователей. Например, методы, fetchChunkтакиеfetchAll, и getSchema подождите, пока операции будут завершены, а затем возвращают результаты. Метод можно использовать IOperation.finished() для явного ожидания завершения операций. Эти методы периодически вызывают обратный вызов, ожидая завершения операций. progress Задание параметра для true запроса дополнительных данных хода выполнения с сервера и передачи его обратному вызову.

Методы close и cancel методы можно вызывать в любое время. При вызове они немедленно отменяют IOperation объект; все ожидающие вызовы, такие как fetchAll, fetchChunkи немедленно отменены, и getSchema возвращается ошибка. В некоторых случаях операция сервера, возможно, уже завершена, и cancel метод влияет только на клиента.

Метод fetchAll вызывается fetchChunk внутренне и собирает все данные в массив. Хотя это удобно, это может привести к ошибкам памяти при использовании в больших наборах данных. fetchAll Параметры обычно передаются в fetchChunk.

Получение блоков данных

Получение блоков данных использует следующий шаблон кода:

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

Метод fetchChunk в справочнике по API обрабатывает данные в небольших порциях для уменьшения потребления памяти. fetchChunk сначала ожидает завершения операций, если они еще не завершены, а затем вызывает обратный вызов во время цикла ожидания, а затем извлекает следующий блок данных.

Этот параметр можно использовать maxRows для указания требуемого размера блока. Однако возвращаемый фрагмент может иметь другой размер, меньший или даже иногда больший. fetchChunk не пытается предварительно получить данные внутри системы, чтобы срезать их на запрошенные части. Он отправляет maxRows параметр на сервер и возвращает все, что возвращает сервер. Не путайте этот maxRows параметр с одним из IDBSQLSessionних. maxRows передается для fetchChunk определения размера каждого блока и не делает ничего другого.

Управление файлами в томах каталога Unity

Драйвер SQL Databricks позволяет записывать локальные файлы в тома каталога 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);

Дополнительные примеры см. в папке examples в репозитории databricks/databricks-sql-nodejs на сайте GitHub.

Тестирование

Для тестирования кода можно использовать платформы тестирования JavaScript, такие как Jest. Чтобы протестировать код в имитированных условиях без вызова конечных точек REST API Azure Databricks или изменения состояния учетных записей Или рабочих областей Azure Databricks, можно использовать встроенные платформы макетирования Jest.

Например, учитывая следующий файл с именем helpers.js getDBSQLClientWithPAT функции, которая использует личный маркер доступа Azure Databricks для возврата подключения к рабочей области Azure Databricks, функция, getAllColumnsFromTable которая использует подключение для получения указанного количества строк данных из указанной таблицы (например, trips таблицы в samples схеме каталога nyctaxi ) и 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, который вызывает getDBSQLClientWithPATи getAllColumnsFromTableprintResults функции:

// 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 предыдущий код выглядит примерно так. Для тестирования Jest с помощью TypeScript используйте ts-jest.

Дополнительные ресурсы

Справочник по API

Классы

Класс DBSQLClient

Основная точка входа для взаимодействия с базой данных.

Методы
connectМетод

Открывает подключение к базе данных.

Параметры
options

Тип: ConnectionOptions

Набор параметров, используемых для подключения к базе данных.

Поля host, pathи другие обязательные поля должны быть заполнены. См. раздел Аутентификация.

Пример:


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Метод

Возвращает внутренний объект TCLIService.Client. Необходимо вызвать после подключения DBSQLClient.

Нет параметров

Возвращает TCLIService.Client.

closeМетод

Закрывает соединение с базой данных и освобождает все связанные ресурсы на сервере. Любые дополнительные вызовы этого клиента будут вызывать ошибку.

Без параметров.

Нет возвращаемого значения.

Класс DBSQLSession

DBSQLSessions в основном используются для выполнения инструкций в базе данных, а также для различных операций извлечения метаданных.

Методы
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

Параметры запроса. Поля catalogName и schemaName могут использоваться для фильтрации.

Возвраты: Promise<IOperation>

getTablesМетод

Возвращает список таблиц.

Параметры
request

Тип: TablesRequest

Параметры запроса. Поля catalogName и schemaName
tableName можно использовать для фильтрации.

Возвраты: Promise<IOperation>

getFunctionsМетод

Возвращает список таблиц.

Параметры
request

Тип: FunctionsRequest

Параметры запроса. Поле functionName является обязательным.

Возвраты: Promise<IOperation>

getPrimaryKeysМетод

Возвращает список первичных ключей.

Параметры
request

Тип: PrimaryKeysRequest

Параметры запроса. Поля schemaName и tableName обязательные.

Возвраты: Promise<IOperation>

getCrossReferenceМетод

Получает сведения о внешних ключах между двумя таблицами.

Параметры
request

Тип: CrossReferenceRequest

Параметры запроса. Для обеих таблиц необходимо указать имя схемы, родителя и каталога.

Возвраты: Promise<IOperation>

Класс DBSQLOperation

DBSQLOperations создаются DBSQLSessions и могут использоваться для получения результатов инструкций и проверки их выполнения. Данные извлекается с помощью функций, извлекаемых и извлекаемых.

Методы
getIdМетод

Возвращает GUID операции.

Без параметров.

Возвраты: str

fetchAllМетод

Ожидает завершения операции, а затем извлекает все строки из операции.

Параметры: нет

Возвраты: Promise<Array<object>>

fetchChunkМетод

Ожидает завершения операции, а затем извлекает до указанного количества строк из операции.

Параметры
options

Тип: FetchOptions

Параметры, используемые для получения. В настоящее время единственным вариантом является maxRows, который соответствует максимальному количеству объектов данных, возвращаемых в любом заданном массиве.

Возвраты: Promise<Array<object>>

closeМетод

Закрывает операцию и освобождает все связанные ресурсы. После большего использования операции необходимо выполнить.

Без параметров.

Нет возвращаемого значения.