UNPKG

@prestodb/presto-js-client

Version:

This is a Presto JavaScript client that connects to Presto via Presto's REST API to run queries.

285 lines (200 loc) 8.9 kB
# Presto JS Client This is a Presto JavaScript client that connects to Presto via Presto's REST API to run queries. ## Installation ```sh npm install @prestodb/presto-js-client ``` ## Usage Import the PrestoClient class from `@prestodb/presto-js-client`. Create a new instance by passing the connection parameters. ### Example Import the Client class: ```typescript import PrestoClient from '@prestodb/presto-js-client' ``` Instantiate a client with connection parameters: ```typescript const client = PrestoClient({ catalog: 'tpcs', host: 'localhost', port: 8080, schema: 'tiny', timezone: 'America/Costa_Rica', user: 'root', }) ``` ### Parameters The Presto client can be configured with the following parameters: - `host`: The hostname or IP address of the Presto coordinator. (Default: `http://localhost`) - `port`: The port number of the Presto coordinator. (Default: `8080`) - `user`: The username to use for authentication. (Default: `undefined`) - `catalog`: The default catalog to use for queries. (Default: `undefined`) - `schema`: The default schema to use for queries. (Default: `undefined`) - `source`: The name of the source you want to use for reporting purposes (Default: `presto-js-client`) - `timezone`: The timezone to use for queries. (Default: `undefined`) - `authorizationToken`: The value to send as-is in the Authorization header. _Note_: The `Bearer` scheme is automatically added. (Default: `undefined`) - `basicAuthentication`: An object with a user and password inside, to be used for basic authentication. (Default: `undefined`) - `extraHeaders`: An dictionary of key-values to send as extra headers in all requests to the API. (Default: `undefined`) - `interval`: (DEPRECATED) The interval in milliseconds between checks for the status of a running query. (Default: `100`) ## Querying The `query` method takes a single `string` parameter, which is the SQL query to be executed. The method returns a PrestoQuery object, which contains the results of the query, including the columns, data, and query ID. If the query fails, the `query` method will throw an error. The `string` parameter to the `query` method must be a valid SQL query. The query can be any type of SQL query, including `SELECT`, `INSERT`, `UPDATE`, and `DELETE` statements. ### Return data structure (or error state) The `query` method returns a PrestoQuery object, which contains the results of the query, including the columns, data, and query ID. If the query succeeds, the PrestoQuery object will have the following properties: - `columns`: An array of objects that describe the columns in the results. - `data`: An array of arrays that contain the actual data for the results. - `queryId`: The ID of the query. If the query fails, you can catch the error as a PrestoError which contains all information returned by Presto. ### Example usage The following example shows how to use the query() method to execute a SELECT statement: ```typescript const client = new PrestoClient({ catalog: 'tpcds', host: 'http://localhost', port: 8080, schema: 'sf1', user: 'root', }) const query = `SELECT * FROM my_table` try { const prestoQuery = await client.query(query) const results = prestoQuery.data } catch (error) { if (error instanceof PrestoError) { // Handle the error. console.error(error.errorCode) } } ``` ### Additional notes Additional notes on the `query` method: - It's asynchronous and will return a promise that resolves to a PrestoQuery object. - It will automatically retry the query if it fails due to a transient error. - It will cancel the query if the client is destroyed. - \*It parses big numbers with the BigInt JavaScript primitive. If your Presto response includes a number bigger than `Number.MAX_SAFE_INTEGER`, it will be parsed into a bigint, so you may need to consider that when handling the response, or serializing it. \* Only if the current JavaScript environment supports the reviver with context in the JSON.parse callback. Check compatibility here: - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#browser_compatibility Otherwise, bigger numbers will lose precision due to the default JavaScript JSON parsing. ## Get Query metadata information ### Get Query Information The `getQueryInfo` method retrieves comprehensive information about a specific query, based on its identifier. It returns metadata including status, execution details, statistics, and more, encapsulated within a `QueryInfo` object or undefined if the query does not exist. #### Parameters - `queryId`: The unique identifier string of the query for which information is being retrieved. #### Example usage ```typescript const queryInfo = await prestoClient.getQueryInfo('your_query_id') console.log(queryInfo) ``` ## Query catalog, schema, table and column metadata ### Get Catalogs The `getCatalogs` method retrieves all available database catalogs, returning them as an array of strings. #### Example usage ```typescript const catalogs = await prestoClient.getCatalogs() console.log(catalogs) ``` ### Get Schemas The `getSchemas` method retrieves all schemas within a given catalog. It accepts a catalog parameter, which is a string representing the name of the catalog. Parameters - `catalog`: The name of the catalog for which to retrieve schemas. #### Example usage ```typescript const schemas = await prestoClient.getSchemas('tpch') console.log(schemas) ``` ### Get Tables The `getTables` method retrieves a list of tables (of type `Table`) filtered by the given catalog and, optionally, the schema. It accepts an object containing `catalog` and optional `schema` parameters. Parameters - `catalog`: The catalog name. - `schema` (optional): The schema name. #### Example usage ```typescript const tables: Table[] = await prestoClient.getTables({ catalog: 'tpch', schema: 'sf100' }) console.log(tables) ``` ### Get Columns The `getColumns` method retrieves a list of columns (of type `Column`) filtered for the given catalog and optional schema and table filters. It accepts an object with `catalog`, and optional `schema` and `table` parameters. Parameters - `catalog`: The catalog name. - `schema` (optional): The schema name. - `table` (optional): The table name. #### Example usage ```typescript const columns: Column[] = await prestoClient.getColumns({ catalog: 'tpch', schema: 'sf100', table: 'orders', }) console.log(columns) ``` ## Authentication When creating the client instance, you optionally pass one of two authentication methods. ### Basic authentication You can send a basic authorization user and password in this way: ```typescript const client = new PrestoClient({ basicAuthentication: { user: 'my-user', password: 'my-password', }, catalog: 'tpcds', host: 'http://localhost', port: 8080, schema: 'sf1', user: 'root', }) ``` ### Auth token You can send an authorization token in the following way: ```typescript const client = new PrestoClient({ // Do not include `Bearer` here, it is automatically added by the client authorizationToken: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`, catalog: 'tpcds', host: 'http://localhost', port: 8080, schema: 'sf1', user: 'root', }) ``` ## Extra headers You can pass any extra custom headers to the Presto client to be send on all requests performed against the host: ```typescript const client = new PrestoClient({ catalog: 'tpcds', extraHeaders: { 'X-My-Custom-Header-1': 'value', 'X-My-Custom-Header-2': 'value', }, host: 'http://localhost', port: 8080, schema: 'sf1', user: 'root', }) ``` ## Troubleshooting ### Do not know how to serialize a BigInt Example error message: ``` Do not know how to serialize a BigInt TypeError: Do not know how to serialize a BigInt at JSON.stringify (<anonymous>) ``` Make sure to write a custom replacer and handle the serialization of BigInts if your Presto query returns a number bigger than `Number.MAX_SAFE_INTEGER`. Example JSON.stringify replacer: ```javascript const results = await client.query(`SELECT 1234567890123456623`) return { columns: results.columns, rows: JSON.stringify(results.data, (key, value) => { if (typeof value !== 'bigint') return value return value.toString() }), } ``` ### Numbers lose precision Known issue: If working with numbers bigger than `Number.MAX_SAFE_INTEGER`, and your environment does not support the `JSON.parse` with the context in the reviver (Node.js > 21.0.0, and certain browser versions), the default JSON.parse will make the number lose precision. Check compatibility here: - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#browser_compatibility