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


Драйвер 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 для пользователей рабочей области.

Чтобы проверить подлинность драйвера 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. Запишите значение 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 ID

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

Токены идентификации 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 в схеме nyctaxi каталога samples.

Примечание.

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

В этом примере кода извлекаются значения переменных подключения token, server_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 Методы помещают операции в очередь и возвращаются как можно быстрее. Текущее состояние возвращаемого объекта может отличаться, и клиент отвечает за проверку состояния перед использованием возвращаемого IOperationIOperationобъекта. См . статью "Операции". Значение параметра runAsyncfalse означает, что IDBSQLSession методы ожидают завершения операций. Databricks рекомендует всегда задавать значение runAsynctrue.
  • Если задать maxRows значение, отличное от NULL, можно получить прямые результаты. Когда используются прямые результаты, сервер ожидает завершения операций, а затем забирает часть данных. В зависимости от того, сколько работы сервера удалось выполнить в течение определенного времени, IOperation объекты возвращаются в некотором промежуточном состоянии вместо некоторого ожидающего состояния. Часто все метаданные и результаты запроса возвращаются в рамках одного запроса на сервер. Сервер использует maxRows для определения количества записей, которые он может возвращать немедленно. Однако фактический блок может иметь другой размер; см. раздел IDBSQLSession.fetchChunk. Прямые результаты включены по умолчанию. Databricks не рекомендует отключать прямые результаты.

Операции

Как описано в Sessions, объекты, возвращаемые методами сессии в справочнике API, не полностью заполнены. Связанная операция сервера может по-прежнему выполняться, например ожидание запуска хранилища SQL Databricks, выполнение запроса или получение данных. Класс IOperation скрывает эти сведения от пользователей. Например, такие методы, как fetchAll, fetchChunk и 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 в схеме каталога samplesnyctaxi); и функция 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, getAllColumnsFromTable и printResults:

// 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 и могут использоваться для получения результатов инструкций и проверки их выполнения. Данные извлекаются с помощью функций fetchChunk и fetchAll.

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

Возвращает идентификатор GUID операции.

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

Возврат: str

fetchAllМетод

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

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

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

fetchChunkМетод

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

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

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

closeМетод

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

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

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