Databricks SQL Driver para Node.js
O Databricks SQL Driver para Node.js é uma biblioteca Node.js que permite usar o código JavaScript para executar comandos SQL em recursos compute do Databricks.
Requisitos
Uma máquina de desenvolvimento executando Node.js, versão 14 ou superior. Para imprimir a versão instalada do Node.js, execute o comando
node -v
. Para instalar e usar diferentes versões do Node.js, você pode usar ferramentas como o Node Version Manager (nvm).Gerenciador de pacotes de nós (
npm
). Versões posteriores do Node.js já incluemnpm
. Para verificar senpm
está instalado, execute o comandonpm -v
. Para instalar onpm
, se necessário, você pode seguir as instruções em downloads e instalar npm.O pacote @databricks/sql do npm. Para instalar o pacote
@databricks/sql
em seu projeto Node.js como uma dependência, usenpm
para executar o seguinte comando no mesmo diretório de seu projeto:npm i @databricks/sql
Se você deseja instalar e usar o TypeScript em seu projeto Node.js como
devDependencies
, usenpm
para executar os seguintes comandos no mesmo diretório do seu projeto:npm i -D typescript npm i -D @types/node
Uma empresa existente cluster ou SQL warehouse.
O hostnamedo servidor e o valor do caminho HTTP para os clusters existentes ou SQL warehouse.
Autenticação
O Databricks SQL Driver para Node.js dá suporte aos seguintes tipos de autenticação do Databricks:
O Databricks SQL Driver for Node.js ainda não é compatível com os seguintes tipos de autenticação do Databricks:
Observação
Como prática recomendada de segurança, você não deve codificar valores de variáveis de conexão em seu código. Em vez disso, você deve recuperar esses valores de variáveis de conexão de um local seguro. Por exemplo, os trechos de código e exemplos neste artigo usam variável de ambiente.
Autenticação de token de acesso pessoal do Databricks
Para usar o Databricks SQL Driver para Node.js com autenticação access token pessoal do Databricks, você deve primeiro criar um access token pessoal do Databricks, da seguinte maneira:
Em seu Databricks workspace, clique em seu nome de usuário Databricks na barra superior e selecione Settings (Configurações ) no menu suspenso.
Clique em Desenvolvedor.
Ao lado do access token, clique em gerenciar.
Clique em Gerar novos tokens.
(Opcional) Insira um comentário que o ajude a identificar esse token no futuro e altere o tempo de vida padrão do token de 90 dias. Para criar um token sem vida útil (não recomendado), deixe a caixa Duração (dias) vazia (em branco).
Clique em Gerar.
Copie o token exibido em um local seguro e clique em Concluído.
Observação
Certifique-se de salvar os tokens copiados em um local seguro. Não compartilhe seus tokens copiados com outras pessoas. Se você perder os tokens copiados, não poderá regenerar exatamente os mesmos tokens. Em vez disso, você deve repetir este procedimento para criar novos tokens. Se você perder os tokens copiados ou acreditar que os tokens foram comprometidos, o Databricks recomenda fortemente que você exclua imediatamente esses tokens do seu workspace clicando no ícone da lixeira (Revogar) ao lado dos tokens na página access tokens .
Se o senhor não conseguir criar ou usar o site tokens no seu workspace, isso pode ocorrer porque o administrador do workspace desativou o tokens ou não lhe deu permissão para criar ou usar o tokens. Consulte o administrador do site workspace ou os tópicos a seguir:
Para autenticar o driver Databricks SQL para Node.js, use o seguinte trecho de código. Este trecho pressupõe que você definiu a seguinte variável de ambiente:
DATABRICKS_SERVER_HOSTNAME
definido como o valor hostnamedo servidor para seus clusters ou SQL warehouse.DATABRICKS_HTTP_PATH
, defina o valor do Caminho HTTP para seus clusters ou SQL warehouse.DATABRICKS_TOKEN
, defina como o access token pessoal do Databricks.
Para definir variáveis de ambiente, consulte a documentação do sistema operacional.
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)
// ...
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)
// ...
Autenticação de usuário para máquina (U2M) OAuth
As versões 1.8.0 e acima do Databricks SQL Driver for Node.js suportam a autenticação OAuth de usuário para máquina (U2M).
Para autenticar o driver Databricks SQL para Node.js com autenticação OAuth U2M, use o trecho de código a seguir. Este trecho pressupõe que você definiu a seguinte variável de ambiente:
DATABRICKS_SERVER_HOSTNAME
definido como o valor hostnamedo servidor para seus clusters ou SQL warehouse.DATABRICKS_HTTP_PATH
, defina o valor do Caminho HTTP para seus clusters ou SQL warehouse.
Para definir variáveis de ambiente, consulte a documentação do sistema operacional.
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",
host: serverHostname,
path: httpPath
};
client.connect(connectOptions)
// ...
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",
host: serverHostname,
path: httpPath
};
client.connect(connectOptions)
// ...
Autenticação OAuth máquina a máquina (M2M)
O Databricks SQL Driver for Node.js versões 1.8.0 e acima suportam a autenticação OAuth máquina a máquina (U2M).
Para usar o Databricks SQL Driver para Node.js com autenticação OAuth M2M, você deve fazer o seguinte:
Crie uma entidade de serviço do Databricks em seu workspace do Databricks e crie um segredo OAuth para essa entidade de serviço.
Para criar a entidade de serviço e seu segredo OAuth, consulte Autenticar o acesso ao Databricks com uma entidade de serviço usando OAuth (OAuth M2M). Anote o valor do UUID da entidade de serviço ou do ID do aplicativo e o valor do segredo do OAuth da entidade de serviço.
Permitir que a entidade de serviço tenha acesso a seus clusters ou armazéns. Consulte as permissões do sitecompute ou gerenciar a SQL warehouse.
Para autenticar o driver Databricks SQL para Node.js, use o seguinte trecho de código. Este trecho pressupõe que você definiu a seguinte variável de ambiente:
DATABRICKS_SERVER_HOSTNAME
definido como o valor hostnamedo servidor para seus clusters ou SQL warehouse.DATABRICKS_HTTP_PATH
, defina o valor do Caminho HTTP para seus clusters ou SQL warehouse.DATABRICKS_CLIENT_ID
, defina como o valor UUID ou ID do aplicativo da entidade de serviço.DATABRICKS_CLIENT_SECRET
, definido como o valor Secreto para o segredo OAuth da entidade de serviço.
Para definir variáveis de ambiente, consulte a documentação do sistema operacional.
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",
host: serverHostname,
path: httpPath,
oauthClientId: clientId,
oauthClientSecret: clientSecret
};
client.connect(connectOptions)
// ...
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",
host: serverHostname,
path: httpPath,
oauthClientId: clientId,
oauthClientSecret: clientSecret
};
client.connect(connectOptions)
// ...
Consultar dados
O exemplo de código a seguir demonstra como chamar o Databricks SQL Driver para Node.js para executar uma query SQL básica em um recurso compute do Databricks. Este comando retorna as duas primeiras linhas da tabela trips
no esquema nyctaxi
do catálogo samples
.
Este exemplo de código recupera os valores das variáveis de conexão token
, server_hostname
e http_path
de um conjunto de variáveis de ambiente do Databricks. Essas variáveis de ambiente têm os seguintes nomes de variáveis de ambiente:
DATABRICKS_TOKEN
, que representa seus access tokens pessoal do Databricks dos requisitos.DATABRICKS_SERVER_HOSTNAME
, que representa o valor hostnamedo servidor dos requisitos.DATABRICKS_HTTP_PATH
, que representa o valor do Caminho HTTP dos requisitos.
Você pode usar outras abordagens para recuperar esses valores de variável de conexão. Usar a variável de ambiente é apenas uma abordagem entre muitas.
O exemplo de código a seguir demonstra como chamar o Databricks SQL Connector para Node.js para executar um comando SQL básico em clusters ou SQL warehouse. Este comando retorna as duas primeiras linhas da tabela trips
.
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);
});
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);
});
Saída:
┌─────────┬─────┬────────┬───────────┬───────┬─────────┬────────┬───────┬───────┬────────┬────────┬────────┐
│ (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' │
└─────────┴─────┴────────┴───────────┴───────┴─────────┴────────┴───────┴───────┴────────┴────────┴────────┘
Sessões
Todos os métodos IDBSQLSession
que retornam objetos IOperation
na referência da API têm os seguintes parâmetros comuns que afetam seu comportamento:
Definir
runAsync
comotrue
inicia o modo assíncrono. Os métodosIDBSQLSession
colocam as operações na fila e retornam o mais rápido possível. O estado atual do objetoIOperation
retornado pode variar e o cliente é responsável por verificar seu status antes de usar oIOperation
retornado. Veja operações. DefinirrunAsync
comofalse
significa que os métodosIDBSQLSession
aguardam a conclusão das operações. A Databricks recomenda sempre definirrunAsync
comotrue
.Definir
maxRows
como um valor não nulo permite resultados diretos. Com resultados diretos, o servidor tenta aguardar a conclusão das operações e, em seguida, busca uma parte dos dados. Dependendo de quanto trabalho o servidor foi capaz de concluir dentro do tempo definido, os objetosIOperation
retornam em algum estado intermediário em vez de em algum estado pendente. Muitas vezes, todos os metadados e resultados query são retornados em uma única solicitação ao servidor. O servidor usamaxRows
para determinar quantos registros pode retornar imediatamente. No entanto, o bloco real pode ter um tamanho diferente; consulteIDBSQLSession.fetchChunk
. Os resultados diretos são ativados por default. Databricks não recomenda desabilitar resultados diretos.
operações
Conforme descrito em Sessões, os objetos IOperation
retornados pelos métodos de sessão IDBSQLSession
na Referência da API não são totalmente preenchidos. As operações de servidor relacionadas ainda podem estar em andamento, como aguardar o início do armazém Databricks SQL , executar a query ou buscar os dados. A classe IOperation
oculta esses detalhes dos usuários. Por exemplo, métodos como fetchAll
, fetchChunk
e getSchema
aguardam internamente a conclusão das operações e depois retornam resultados. Você pode usar o método IOperation.finished()
para aguardar explicitamente a conclusão das operações. Esses métodos recebem um retorno de chamada que é chamado periodicamente enquanto aguarda a conclusão das operações. Definir a opção progress
como true
tenta solicitar dados extras de progresso do servidor e transmiti-los para esse retorno de chamada.
Os métodos close
e cancel
podem ser chamados a qualquer momento. Quando chamados, eles invalidam imediatamente o objeto IOperation
; todas as chamadas pendentes como fetchAll
, fetchChunk
e getSchema
são imediatamente canceladas e um erro é retornado. Em alguns casos, as operações do servidor podem já ter sido concluídas e o método cancel
afeta apenas o cliente.
O método fetchAll
chama fetchChunk
internamente e coleta todos os dados em uma matriz. Embora isso seja conveniente, pode causar erros de falta de memória quando usado em grandes dataset. As opções fetchAll
normalmente são passadas para fetchChunk
.
Buscar blocos de dados
A busca de blocos de dados usa o seguinte padrão de código:
do {
const chunk = await operation.fetchChunk();
// Process the data chunk.
} while (await operation.hasMoreRows());
O método fetchChunk
na referência da API processa dados em pequenas porções para reduzir o consumo de memória. fetchChunk
primeiro aguarda a conclusão das operações, caso ainda não tenham sido concluídas, depois chama um retorno de chamada durante o ciclo de espera e, em seguida, busca o próximo bloco de dados.
Você pode usar a opção maxRows
para especificar o tamanho do bloco desejado. No entanto, o pedaço retornado pode ter um tamanho diferente, menor ou às vezes até maior. fetchChunk
não tenta pré-buscar dados internamente, para dividi-los nas partes solicitadas. Ele envia a opção maxRows
para o servidor e retorna o que o servidor retornar. Não confunda esta opção maxRows
com a de IDBSQLSession
. maxRows
passado para fetchChunk
define o tamanho de cada bloco e não faz mais nada.
Gerenciar arquivos em Unity Catalog volumes
O Databricks SQL driver permite que o senhor grave arquivos locais em Unity Catalog volumes, download arquivos de volumes e exclua arquivos de volumes, conforme mostrado no exemplo a seguir:
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);
});
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);
});
Configurar registro
O registrador fornece informações para problemas de depuração com o conector. Todos os objetos DBSQLClient
são instanciados com um registrador que imprime no console, mas ao passar um registrador personalizado, você pode enviar esta informação para um arquivo. O exemplo a seguir mostra como configurar um registrador e alterar seu nível.
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);
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);
Para obter exemplos adicionais, consulte a pasta de exemplos no repositório databricks/databricks-sql-nodejs no GitHub.
Testes
Para testar seu código, o senhor pode usar estruturas de teste JavaScript, como o Jest. Para testar seu código em condições simuladas sem chamar o endpoint Databricks REST API ou alterar o estado da sua conta ou espaço de trabalho Databricks, o senhor pode usar os frameworks de simulação integrados do Jest.
Por exemplo, dado o seguinte arquivo denominado helpers.js
contendo uma função getDBSQLClientWithPAT
que usa um Databricks pessoal access token para retornar uma conexão a um Databricks workspace, uma função getAllColumnsFromTable
que usa a conexão para obter o número especificado de linhas de dados da tabela especificada (por exemplo, a tabela trips
no esquema nyctaxi
do catálogo samples
) e uma função printResults
para imprimir o conteúdo das linhas de dados:
// 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
};
E dado o seguinte arquivo chamado main.js
que chama as funções getDBSQLClientWithPAT
, getAllColumnsFromTable
e 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);
});
O arquivo a seguir, denominado helpers.test.js
, testa se a função getAllColumnsFromTable
retorna a resposta esperada. Em vez de criar uma conexão real com o destino workspace, esse teste simula um objeto DBSQLClient
. O teste também simula alguns dados que estão em conformidade com o esquema e os valores que estão nos dados reais. O teste retorna os dados simulados por meio da conexão simulada e, em seguida, verifica se um dos valores das linhas de dados simulados corresponde ao valor esperado.
// 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);
});
Para o TypeScript, o código anterior é semelhante. Para testar o Jest com TypeScript, use o ts-jest.
Recursos adicionais
O repositório Databricks SQL Driver para Node.js no GitHub
Começando a usar o Databricks SQL Driver para Node.js
Solucionando problemas do driver Databricks SQL para Node.js
Referência da API
Aulas
DBSQLClient
classe
Ponto de entrada principal para interagir com um banco de dados.
Métodos
métodoconnect
Abre uma conexão com o banco de dados.
Parâmetros |
---|
opções Tipo: O conjunto de opções usado para se conectar ao banco de dados. Os campos Exemplo: const client: DBSQLClient = new DBSQLClient();
client.connect(
{
host: serverHostname,
path: httpPath,
// ...
}
)
|
Retorna:
Promise<IDBSQLClient>
métodoopenSession
Abre a sessão entre o DBSQLClient e o banco de dados.
Parâmetros |
---|
solicitar Tipo: Um conjunto de parâmetros opcionais para especificar o esquema inicial e o catálogo inicial Exemplo: const session = await client.openSession(
{initialCatalog: 'catalog'}
);
|
Retorna:
Promise<IDBSQLSession>
métodogetClient
Retorna o objeto interno Thrift TCLIService.Client. Deve ser chamado após a conexão de DBSQLClient.
Sem parâmetros
devoluções TCLIService.Client
métodoclose
Fecha a conexão com o banco de dados e libera todos os recursos associados no servidor. Quaisquer chamadas adicionais para este cliente gerarão um erro.
Sem parâmetros.
Sem valor de retorno.
DBSQLSession
classe
DBSQLSessions são usados principalmente para a execução de instruções no banco de dados, bem como várias operações de busca de metadados.
Métodos
métodoexecuteStatement
Executa uma instrução com as opções fornecidas.
Parâmetros |
---|
declaração Tipo: A instrução a ser executada. |
opções Tipo: Um conjunto de parâmetros opcionais para determinar o tempo limite query , o máximo de linhas para resultados diretos e se a query deve ser executada de forma assíncrona. Por default Exemplo: const session = await client.openSession(
{initialCatalog: 'catalog'}
);
queryOperation = await session.executeStatement(
'SELECT "Hello, World!"', { runAsync: true }
);
|
Retorna:
Promise<IOperation>
métodoclose
Fecha a sessão. Deve ser feito após o uso da sessão.
Sem parâmetros.
Sem valor de retorno.
métodogetTypeInfo
Retorna informações sobre os tipos de dados suportados.
Parâmetros |
---|
solicitar Tipo: Parâmetros de solicitação. |
Retorna:
Promise<IOperation>
métodogetCatalogs
Obtém a lista de catálogos.
Parâmetros |
---|
solicitar Tipo: Parâmetros de solicitação. |
Retorna:
Promise<IOperation>
métodogetSchemas
Obtém a lista de esquemas.
Parâmetros |
---|
solicitar Tipo: Parâmetros de solicitação. Os campos |
Retorna:
Promise<IOperation>
métodogetTables
Obtém lista de tabelas.
Parâmetros |
---|
solicitar Tipo: Parâmetros de solicitação. Os campos |
Retorna:
Promise<IOperation>
métodogetFunctions
Obtém lista de tabelas.
Parâmetros |
---|
solicitar Tipo: Parâmetros de solicitação. O campo |
Retorna:
Promise<IOperation>
métodogetPrimaryKeys
Obtém a lista de key primárias.
Parâmetros |
---|
solicitar Tipo: Parâmetros de solicitação. Os campos |
Retorna:
Promise<IOperation>
métodogetCrossReference
Obtém informações sobre key estrangeiras entre duas tabelas.
Parâmetros |
---|
solicitar Tipo: Parâmetros de solicitação. Esquema, pai e nome do catálogo devem ser especificados para ambas as tabelas. |
Retorna:
Promise<IOperation>
DBSQLOperation
classe
DBSQLOperations são criadas por DBSQLSessions e podem ser usadas para buscar os resultados das instruções e verificar sua execução. Os dados são buscados por meio das funções fetchChunk e fetchAll.
Métodos
métodofetchAll
Aguarda a conclusão das operações e, em seguida, busca todas as linhas das operações.
Parâmetros: Nenhum
Retorna:
Promise<Array<object>>
métodofetchChunk
Aguarda a conclusão das operações e, em seguida, busca até um número especificado de linhas de uma operação.
Parâmetros |
---|
opções Tipo: Opções usadas para buscar. Atualmente, a única opção é maxRows, que corresponde ao número máximo de objetos de dados a serem retornados em qualquer array. |
Retorna:
Promise<Array<object>>
métodoclose
Fecha as operações e libera todos os recursos associados. Deve ser feito depois de não usar mais operações.
Sem parâmetros.
Sem valor de retorno.