Driver do Databricks SQL para Node.js
O Driver do Databricks SQL para Node.js é uma biblioteca Node.js que permite usar o código JavaScript para executar comandos SQL em recursos de computação do Azure Databricks.
Requisitos
Um computador de desenvolvimento executando o Node.js 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 Gerenciador de Versões do Node (nvm).Gerenciador de pacotes do Node (
npm
). Versões posteriores do Node.js já incluemnpm
. Para verificar senpm
está instalado, execute o comandonpm -v
. Para instalarnpm
, se necessário, você pode seguir instruções como aquelas em Baixar e instalar o npm.O pacote @databricks/sql do npm. Para instalar o pacote
@databricks/sql
em seu projeto do Node.js como uma dependência, usenpm
para executar o seguinte comando no mesmo diretório que seu projeto:npm i @databricks/sql
Se desejar instalar e usar o TypeScript em seu projeto Node.js como
devDependencies
, usenpm
para executar os seguintes comandos do mesmo diretório que seu projeto:npm i -D typescript npm i -D @types/node
Um cluster ou SQL warehouse existente.
O valor do Nome do host do servidor e do Caminho HTTP para o cluster ou o SQL warehouse existente.
Autenticação
O Driver SQL do Databricks para Node.js dá suporte para os seguintes tipos de autenticação do Azure Databricks:
- Autenticação de token de acesso pessoal do Databricks
- Autenticação de token do Microsoft Entra ID
- Autenticação OAuth máquina a máquina (M2M)
- Autenticação U2M (usuário para computador) do OAuth
O Driver SQL do Databricks para Node.js ainda não dá suporte para os seguintes tipos de autenticação do Azure Databricks:
- Autenticação de identidades gerenciadas do Azure
- Autenticação da entidade de serviço do MS Entra
- Autenticação da CLI do Azure
Observação
Como melhor prática de segurança, você não deve codificar os valores das variáveis de conexão diretamente no seu código. Em vez disso, você deve recuperar esses valores de variável de conexão de um local seguro. Por exemplo, os trechos de código e os exemplos deste artigo usam variáveis de ambiente.
Autenticação de token de acesso pessoal do Databricks
Para usar o Driver SQL do Databricks para Node.js com autenticação, primeiro você deve criar um token de acesso pessoal do Azure Databricks. Para obter detalhes sobre esta etapa, consulte Tokens de acesso pessoal do Azure Databricks para usuários do workspace.
Para autenticar o Driver SQL do Databricks para Node.js, use o seguinte trecho de código. Esse snippet de código pressupõe que você tenha definido as seguintes variáveis de ambiente:
DATABRICKS_SERVER_HOSTNAME
definido como o valor Nome do Host do Servidor do seu cluster ou SQL Warehouse.DATABRICKS_HTTP_PATH
, definido para o valor do Caminho HTTP para seu cluster ou SQL Warehouse.DATABRICKS_TOKEN
, definido como o token de acesso pessoal do Azure Databricks.
Para definir variáveis de ambiente, confira a documentação do sistema operacional.
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)
// ...
Autenticação U2M (usuário para computador) do OAuth
O Driver SQL do Databricks para Node.js, versões 1.8.0 e posteriores, dá suporte à autenticação U2M (usuário para computador) do OAuth.
Para autenticar o Driver SQL do Databricks para Node.js com a autenticação U2M do OAuth, use o trecho de código a seguir. Esse snippet de código pressupõe que você tenha definido as seguintes variáveis de ambiente:
DATABRICKS_SERVER_HOSTNAME
definido como o valor Nome do Host do Servidor do seu cluster ou SQL Warehouse.DATABRICKS_HTTP_PATH
, definido para o valor do Caminho HTTP para seu cluster ou SQL Warehouse.
Para definir variáveis de ambiente, confira a documentação do sistema operacional.
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)
// ...
Autenticação M2M (de computador para computador) do OAuth
O Driver SQL do Databricks para Node.js, versões 1.8.0 e posteriores, dá suporte à autenticação M2M (computador para computador) do OAuth.
Para usar o Driver SQL do Databricks para Node.js com a autenticação OAuth M2M, você precisa fazer o seguinte:
Crie uma entidade de serviço do Azure Databricks em seu workspace do Azure 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 Azure Databricks com uma entidade de serviço usando OAuth (OAuth M2M). Anote o valor do UUID ou da ID do aplicativo da entidade de serviço e o valor do Segredo do segredo OAuth da entidade de serviço.
Conceda à entidade de serviço acesso ao cluster ou ao warehouse. Consulte Permissões de computação ou Gerenciar um SQL warehouse.
Para autenticar o Driver SQL do Databricks para Node.js, use o seguinte trecho de código. Esse snippet de código pressupõe que você tenha definido as seguintes variáveis de ambiente:
DATABRICKS_SERVER_HOSTNAME
definido como o valor Nome do Host do Servidor do seu cluster ou SQL Warehouse.DATABRICKS_HTTP_PATH
, definido para o valor do Caminho HTTP para seu cluster ou SQL Warehouse.DATABRICKS_CLIENT_ID
, definido como o valor do UUID ou da ID do aplicativo da entidade de serviço.DATABRICKS_CLIENT_SECRET
, definido como o valor do Segredo para o segredo OAuth da entidade de serviço.
Para definir variáveis de ambiente, confira a documentação do sistema operacional.
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)
// ...
Autenticação de token do Microsoft Entra ID
Para usar o Driver SQL do Databricks para Node.js com autenticação de token do Microsoft Entra ID, você deve fornecer o Driver SQL do Databricks para Node.js com o token do Microsoft Entra ID. Para criar um token de acesso do Microsoft Entra ID, faça o seguinte:
- Para um usuário do Azure Databricks, você pode usar a CLI do Azure. Confira Obter tokens do Microsoft Entra ID para usuários usando a CLI do Azure.
- Para obter uma entidade de serviço do Microsoft Entra ID, confira Obter um token de acesso do Microsoft Entra ID com a CLI do Azure. Para criar uma entidade de serviço gerenciada do Microsoft Entra ID, consulte Gerenciar entidades de serviço.
Os tokens do Microsoft Entra ID têm um tempo de vida padrão de cerca de 1 hora. Para criar um novo token do Microsoft Entra ID, repita esse processo.
Para autenticar o Driver SQL do Databricks para Node.js, use o seguinte trecho de código. Esse snippet de código pressupõe que você tenha definido as seguintes variáveis de ambiente:
DATABRICKS_SERVER_HOSTNAME
definido como o valor Nome do Host do Servidor do seu cluster ou SQL Warehouse.DATABRICKS_HTTP_PATH
, definido para o valor do Caminho HTTP para seu cluster ou SQL Warehouse.DATABRICKS_TOKEN
, definido como o token do Microsoft Entra ID.
Para definir variáveis de ambiente, confira a documentação do sistema operacional.
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)
// ...
Consultar dados
O exemplo de código a seguir demonstra como chamar o Driver de SQL do Databricks para Node.js para executar uma consulta SQL básica em um recurso de computação do Azure Databricks. Esse comando retorna as duas primeiras linhas da tabela trips
no esquema nyctaxi
do catálogo samples
.
Observação
O exemplo de código a seguir demonstra como usar um token de acesso pessoal do Azure Databricks para autenticação. Para usar outros tipos de autenticação disponíveis do Azure Databricks, confira Autenticação.
Este exemplo de código recupera os valores de variáveis de conexão token
, server_hostname
e http_path
de um conjunto de variáveis de ambiente do Azure Databricks. Essas variáveis de ambiente têm os seguintes nomes de variáveis de ambiente:
DATABRICKS_TOKEN
, que representa o token de acesso pessoal do Azure Databricks dos requisitos.DATABRICKS_SERVER_HOSTNAME
, que representa o valor do Nome do host do servidor nos requisitos.DATABRICKS_HTTP_PATH
, que representa o valor do Caminho HTTP obtido nos requisitos.
Você pode usar outras abordagens para recuperar os valores dessa variável de conexão. Usar variáveis de ambiente é apenas uma abordagem entre muitas.
O exemplo de código a seguir demonstra como chamar o conector do Databricks SQL para Node.js a fim de executar um comando SQL básico em um cluster ou warehouse SQL. Esse comando retorna as duas primeiras linhas da tabela 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);
});
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 IDBSQLSession
métodos que retornam IOperation
objetos na Referência de API têm os seguintes parâmetros comuns que afetam seu comportamento:
- A configuração
runAsync
paratrue
inicia o modo assíncrono.IDBSQLSession
os métodos colocam operações na fila e retornam o mais rápido possível. O estado atual do objeto retornadoIOperation
pode variar e o cliente é responsável por verificar seus status antes de usar o retornadoIOperation
. Consulte Operações. DefinirrunAsync
comofalse
significa queIDBSQLSession
os métodos aguardam a conclusão das operações. O Databricks recomenda que você sempre definarunAsync
comotrue
. - A configuração
maxRows
para um valor não nulo permite resultados diretos. Com os 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,IOperation
os objetos retornam em algum estado intermediário em vez de em algum estado pendente. Muitas vezes, todos os metadados e os resultados da consulta são retornados em uma única solicitação para o servidor. O servidor usamaxRows
para determinar quantos registros ele pode retornar imediatamente. No entanto, a parte real pode ser de um tamanho diferente; consulteIDBSQLSession.fetchChunk
. Os resultados diretos são ativados por padrão. O Databricks recomenda não desabilitar resultados diretos.
Operações
Conforme descrito em Sessões, IOperation
os objetos retornados pelos IDBSQLSession
métodos de sessão na Referência de API não são totalmente preenchidos. A operação de servidor relacionada ainda pode estar em andamento, como aguardar o Databricks SQL warehouse iniciar, executar a consulta ou buscar os dados. A classe IOperation
oculta esses detalhes dos usuários. Por exemplo, métodos como fetchAll
, fetchChunk
e getSchema
esperam internamente que as operações sejam concluídas e, em seguida, retornem 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
para true
tentar solicitar dados de progresso extra do servidor e passá-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, a operação do servidor pode já ter sido concluída 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, isso pode causar erros de memória insuficiente quando usado em grandes conjuntos de dados. fetchAll
as opções normalmente são passadas para fetchChunk
.
Buscar partes de dados
Buscar partes 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 de API processa dados em pequenas partes para reduzir o consumo de memória. fetchChunk
primeiro aguarda a conclusão das operações se elas ainda não foram concluídas, chama um retorno de chamada durante o ciclo de espera e busca a próxima parte de dados.
Você pode usar a opção maxRows
para especificar o tamanho da parte desejada. No entanto, a parte retornada pode ter um tamanho diferente, menor ou até mesmo às vezes maior. fetchChunk
não tenta pré-buscar dados internamente, a fim de segmentá-los nas partes solicitadas. Ele envia a opção maxRows
para o servidor e retorna o que o servidor retorna. Não confunda essa maxRows
opção com a de IDBSQLSession
. maxRows
passado para fetchChunk
define o tamanho de cada parte e não faz mais nada.
Gerenciar arquivos em volumes do Catálogo do Unity
O driver do Databricks SQL permite gravar arquivos locais em volumes do Catálogo do Unity, baixar arquivos de volumes e excluir arquivos de volumes, conforme mostrado no seguinte exemplo:
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);
});
Configurar o registro em log
O agente fornece informações para depurar problemas com o conector. Todos os objetos DBSQLClient
são instanciados com um agente que imprime no console, mas ao transmitir um agente personalizado, é possível enviar essas informações para um arquivo. O exemplo a seguir mostra como configurar um agente e alterar seu nível.
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);
Para obter exemplos adicionais, consulte a pasta de exemplos no repositório databricks/databricks-sql-nodejs no GitHub.
Testando
Para testar o seu código, você pode usar estruturas de teste do JavaScript, como Jest. Para testar o seu código em condições simuladas sem chamar pontos de extremidade da API REST do Azure Databricks ou alterar o estado de suas contas ou workspaces do Azure Databricks, você pode usar as estruturas de simulação internas do Jest.
Por exemplo, dado o seguinte arquivo nomeado helpers.js
contendo uma função getDBSQLClientWithPAT
que usa um token de acesso pessoal do Azure Databricks para retornar uma conexão a um workspace do Azure Databricks, 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 nomeado helpers.test.js
a seguir testa se a função getAllColumnsFromTable
retorna a resposta esperada. Em vez de criar uma conexão real com o workspace de destino, 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 verifica se um dos valores das linhas de dados simuladas 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 TypeScript, o código anterior é semelhante. Para testes Jest com TypeScript, use ts-jest.
Recursos adicionais
- O repositório Databricks SQL Driver para Node.js no GitHub
- Introdução ao Driver SQL do Databricks para Node.js
- Solucionar problemas do Driver SQL do Databricks para Node.js
Referência de API
Classes
Classe DBSQLClient
Ponto de entrada principal para interagir com um banco de dados.
Métodos
método connect
Abre uma conexão com o banco de dados.
Parâmetros |
---|
options Digite: ConnectionOptions O conjunto de opções usado para se conectar ao banco de dados. Os campos host , path e outros campos obrigatórios devem ser preenchidos. Consulte Autenticação.Exemplo: const client: DBSQLClient = new DBSQLClient(); client.connect( { host: serverHostname, path: httpPath, // ... } ) |
Retorna: Promise<IDBSQLClient>
método openSession
Abre a sessão entre o DBSQLClient e o banco de dados.
Parâmetros |
---|
solicitação Digite: OpenSessionRequest 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étodo getClient
Retorna o objeto interno thrift TCLIService.Client. Deve ser chamado após a conexão de DBSQLClient.
Sem parâmetros
Retorna TCLIService.Client
método close
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.
Classe DBSQLSession
DBSQLSessions são usadas principalmente para a execução de instruções no banco de dados, bem como diversas operações de busca de metadados.
Métodos
método executeStatement
Executa uma instrução com as opções fornecidas.
Parâmetros |
---|
instrução Digite: str A instrução a ser executada. |
options Digite: ExecuteStatementOptions Um conjunto de parâmetros opcionais para determinar o tempo limite da consulta, as linhas máximas para resultados diretos e se a consulta deve ser executada de maneira assíncrona. Por padrão, maxRows é definido como 10000. Se maxRows for definido como nulo, a operação será executada com o recurso de resultados diretos desabilitado.Exemplo: const session = await client.openSession( {initialCatalog: 'catalog'} ); queryOperation = await session.executeStatement( 'SELECT "Hello, World!"', { runAsync: true } ); |
Retorna: Promise<IOperation>
método close
Fecha a sessão. Deve ser feito após o uso da sessão.
Sem parâmetros.
Nenhum valor retornado.
método getId
Retorna o GUID da sessão.
Sem parâmetros.
Retorna: str
método getTypeInfo
Retorna informações sobre os tipos de dados compatíveis.
Parâmetros |
---|
solicitação Digite: TypeInfoRequest Solicita os parâmetros. |
Retorna: Promise<IOperation>
método getCatalogs
Obtém a lista de catálogos.
Parâmetros |
---|
solicitação Digite: CatalogsRequest Solicita os parâmetros. |
Retorna: Promise<IOperation>
método getSchemas
Obtém a lista de esquemas.
Parâmetros |
---|
solicitação Digite: SchemasRequest Solicita os parâmetros. Os campos catalogName e schemaName podem ser usados para fins de filtragem. |
Retorna: Promise<IOperation>
método getTables
Obtém a lista de tabelas.
Parâmetros |
---|
solicitação Digite: TablesRequest Solicita os parâmetros. Campos catalogName , schemaName etableName podem ser usados para filtragem. |
Retorna: Promise<IOperation>
método getFunctions
Obtém a lista de tabelas.
Parâmetros |
---|
solicitação Digite: FunctionsRequest Solicita os parâmetros. O campo functionName é obrigatório. |
Retorna: Promise<IOperation>
método getPrimaryKeys
Obtém a lista de chaves primárias.
Parâmetros |
---|
solicitação Digite: PrimaryKeysRequest Solicita os parâmetros. Os campos schemaName e tableName são obrigatórios. |
Retorna: Promise<IOperation>
método getCrossReference
Obtém informações sobre chaves estrangeiras entre duas tabelas.
Parâmetros |
---|
solicitação Digite: CrossReferenceRequest Solicita os parâmetros. Os nomes do esquema, do pai e do catálogo devem ser especificados para ambas as tabelas. |
Retorna: Promise<IOperation>
Classe DBSQLOperation
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étodo getId
Retorna o GUID da operação.
Sem parâmetros.
Retorna: str
método fetchAll
Aguarda a conclusão da operação e, em seguida, busca todas as linhas dela.
Parâmetros: nenhum
Retorna: Promise<Array<object>>
método fetchChunk
Aguarda a conclusão da operação e, em seguida, busca até um número especificado de linhas dela.
Parâmetros |
---|
options Digite: FetchOptions 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 matriz. |
Retorna: Promise<Array<object>>
método close
Encerra a operação e libera todos os recursos associados. Deve ser feito depois de não usar mais a operação.
Sem parâmetros.
Sem valor de retorno.