From 2c36eb12bc1d6ebc35b1e318a1fd20c870f4128f Mon Sep 17 00:00:00 2001 From: "vincent.mathon" Date: Thu, 17 Jul 2025 09:33:08 +0200 Subject: [PATCH] feat(flightsql-jdbc): Add support for Arrow Flight JDBC driver (#8829) --- .github/workflows/drivers-tests.yml | 2 + packages/cubejs-docker/dev.Dockerfile | 5 + .../cubejs-docker/testing-drivers.Dockerfile | 5 + .../cubejs-flightsql-jdbc-driver/.gitignore | 2 + packages/cubejs-flightsql-jdbc-driver/LICENSE | 202 ++++++++++++++++++ .../cubejs-flightsql-jdbc-driver/README.md | 27 +++ .../bin/post-install | 11 + .../jest.config.js | 7 + .../cubejs-flightsql-jdbc-driver/package.json | 55 +++++ .../src/ArrowFlightSQLJdbcDriver.ts | 113 ++++++++++ .../cubejs-flightsql-jdbc-driver/src/index.ts | 4 + .../src/post-install.ts | 12 ++ .../test/ArrowFlightSQLJdbcDriver.test.ts | 49 +++++ .../test/Dockerfile.spiceai | 11 + .../test/spicepod.yaml | 7 + .../test/yellow_tripdata_2024-01_499.parquet | Bin 0 -> 21388 bytes .../tsconfig.json | 12 ++ .../src/core/DriverDependencies.js | 1 + tsconfig.json | 3 + 19 files changed, 528 insertions(+) create mode 100644 packages/cubejs-flightsql-jdbc-driver/.gitignore create mode 100644 packages/cubejs-flightsql-jdbc-driver/LICENSE create mode 100644 packages/cubejs-flightsql-jdbc-driver/README.md create mode 100755 packages/cubejs-flightsql-jdbc-driver/bin/post-install create mode 100644 packages/cubejs-flightsql-jdbc-driver/jest.config.js create mode 100644 packages/cubejs-flightsql-jdbc-driver/package.json create mode 100644 packages/cubejs-flightsql-jdbc-driver/src/ArrowFlightSQLJdbcDriver.ts create mode 100644 packages/cubejs-flightsql-jdbc-driver/src/index.ts create mode 100644 packages/cubejs-flightsql-jdbc-driver/src/post-install.ts create mode 100644 packages/cubejs-flightsql-jdbc-driver/test/ArrowFlightSQLJdbcDriver.test.ts create mode 100644 packages/cubejs-flightsql-jdbc-driver/test/Dockerfile.spiceai create mode 100644 packages/cubejs-flightsql-jdbc-driver/test/spicepod.yaml create mode 100644 packages/cubejs-flightsql-jdbc-driver/test/yellow_tripdata_2024-01_499.parquet create mode 100644 packages/cubejs-flightsql-jdbc-driver/tsconfig.json diff --git a/.github/workflows/drivers-tests.yml b/.github/workflows/drivers-tests.yml index 263a61fbc8045..9f20ec406b606 100644 --- a/.github/workflows/drivers-tests.yml +++ b/.github/workflows/drivers-tests.yml @@ -20,6 +20,7 @@ on: - 'packages/cubejs-bigquery-driver/**' - 'packages/cubejs-clickhouse-driver/**' - 'packages/cubejs-databricks-jdbc-driver/**' + - 'packages/cubejs-flightsql-jdbc-driver/**' - 'packages/cubejs-mssql-driver/**' - 'packages/cubejs-mysql-driver/**' - 'packages/cubejs-postgres-driver/**' @@ -47,6 +48,7 @@ on: - 'packages/cubejs-bigquery-driver/**' - 'packages/cubejs-clickhouse-driver/**' - 'packages/cubejs-databricks-jdbc-driver/**' + - 'packages/cubejs-flightsql-jdbc-driver/**' - 'packages/cubejs-mssql-driver/**' - 'packages/cubejs-mysql-driver/**' - 'packages/cubejs-postgres-driver/**' diff --git a/packages/cubejs-docker/dev.Dockerfile b/packages/cubejs-docker/dev.Dockerfile index 737c3b806d75a..5519da9eb9917 100644 --- a/packages/cubejs-docker/dev.Dockerfile +++ b/packages/cubejs-docker/dev.Dockerfile @@ -100,10 +100,14 @@ FROM base AS prod_base_dependencies COPY packages/cubejs-databricks-jdbc-driver/package.json packages/cubejs-databricks-jdbc-driver/package.json RUN mkdir packages/cubejs-databricks-jdbc-driver/bin RUN echo '#!/usr/bin/env node' > packages/cubejs-databricks-jdbc-driver/bin/post-install +COPY packages/cubejs-flightsql-jdbc-driver/package.json packages/cubejs-flightsql-jdbc-driver/package.json +RUN mkdir packages/cubejs-flightsql-jdbc-driver/bin +RUN echo '#!/usr/bin/env node' > packages/cubejs-flightsql-jdbc-driver/bin/post-install RUN yarn install --prod FROM prod_base_dependencies AS prod_dependencies COPY packages/cubejs-databricks-jdbc-driver/bin packages/cubejs-databricks-jdbc-driver/bin +COPY packages/cubejs-flightsql-jdbc-driver/bin packages/cubejs-flightsql-jdbc-driver/bin RUN yarn install --prod --ignore-scripts FROM base AS build @@ -152,6 +156,7 @@ COPY packages/cubejs-ksql-driver/ packages/cubejs-ksql-driver/ COPY packages/cubejs-dbt-schema-extension/ packages/cubejs-dbt-schema-extension/ COPY packages/cubejs-jdbc-driver/ packages/cubejs-jdbc-driver/ COPY packages/cubejs-databricks-jdbc-driver/ packages/cubejs-databricks-jdbc-driver/ +COPY packages/cubejs-flightsql-jdbc-driver/ packages/cubejs-flightsql-jdbc-driver/ COPY packages/cubejs-vertica-driver/ packages/cubejs-vertica-driver/ # Skip # COPY packages/cubejs-testing/ packages/cubejs-testing/ diff --git a/packages/cubejs-docker/testing-drivers.Dockerfile b/packages/cubejs-docker/testing-drivers.Dockerfile index 1332143538399..c91a004990b19 100644 --- a/packages/cubejs-docker/testing-drivers.Dockerfile +++ b/packages/cubejs-docker/testing-drivers.Dockerfile @@ -92,10 +92,14 @@ FROM base AS prod_base_dependencies COPY packages/cubejs-databricks-jdbc-driver/package.json packages/cubejs-databricks-jdbc-driver/package.json RUN mkdir packages/cubejs-databricks-jdbc-driver/bin RUN echo '#!/usr/bin/env node' > packages/cubejs-databricks-jdbc-driver/bin/post-install +COPY packages/cubejs-flightsql-jdbc-driver/package.json packages/cubejs-flightsql-jdbc-driver/package.json +RUN mkdir packages/cubejs-flightsql-jdbc-driver/bin +RUN echo '#!/usr/bin/env node' > packages/cubejs-flightsql-jdbc-driver/bin/post-install RUN yarn install --prod FROM prod_base_dependencies AS prod_dependencies COPY packages/cubejs-databricks-jdbc-driver/bin packages/cubejs-databricks-jdbc-driver/bin +COPY packages/cubejs-flightsql-jdbc-driver/bin packages/cubejs-flightsql-jdbc-driver/bin RUN yarn install --prod --ignore-scripts ###################################################################### @@ -147,6 +151,7 @@ COPY packages/cubejs-ksql-driver/ packages/cubejs-ksql-driver/ COPY packages/cubejs-dbt-schema-extension/ packages/cubejs-dbt-schema-extension/ COPY packages/cubejs-jdbc-driver/ packages/cubejs-jdbc-driver/ COPY packages/cubejs-databricks-jdbc-driver/ packages/cubejs-databricks-jdbc-driver/ +COPY packages/cubejs-flightsql-jdbc-driver/ packages/cubejs-flightsql-jdbc-driver/ COPY packages/cubejs-vertica-driver/ packages/cubejs-vertica-driver/ # We dont need client libraries diff --git a/packages/cubejs-flightsql-jdbc-driver/.gitignore b/packages/cubejs-flightsql-jdbc-driver/.gitignore new file mode 100644 index 0000000000000..291bc2be5b3a4 --- /dev/null +++ b/packages/cubejs-flightsql-jdbc-driver/.gitignore @@ -0,0 +1,2 @@ +download +dist diff --git a/packages/cubejs-flightsql-jdbc-driver/LICENSE b/packages/cubejs-flightsql-jdbc-driver/LICENSE new file mode 100644 index 0000000000000..da67a9a3301be --- /dev/null +++ b/packages/cubejs-flightsql-jdbc-driver/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2020 Cube Dev, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/packages/cubejs-flightsql-jdbc-driver/README.md b/packages/cubejs-flightsql-jdbc-driver/README.md new file mode 100644 index 0000000000000..89de5362b5e47 --- /dev/null +++ b/packages/cubejs-flightsql-jdbc-driver/README.md @@ -0,0 +1,27 @@ +

Cube.js

+ +[Website](https://cube.dev) • [Docs](https://cube.dev/docs) • [Blog](https://cube.dev/blog) • [Slack](https://slack.cube.dev) • [Twitter](https://twitter.com/the_cube_dev) + +[![npm version](https://badge.fury.io/js/%40cubejs-backend%2Fserver.svg)](https://badge.fury.io/js/%40cubejs-backend%2Fserver) +[![GitHub Actions](https://github.com/cube-js/cube.js/workflows/Build/badge.svg)](https://github.com/cube-js/cube.js/actions?query=workflow%3ABuild+branch%3Amaster) + +# Cube.js Arrow Flight SQL Database Driver + +This driver is based on top of Arrow Flight SQL JDBC driver. + +[Learn more](https://arrow.apache.org/docs/format/FlightSql.html) + +### Testing + +To test follow the following steps + +``` +$ yarn +$ yarn test +``` + +Note: Unit tests requires Java to be installed. + +### License + +Cube.js Databricks Database Driver is [Apache 2.0 licensed](./LICENSE). diff --git a/packages/cubejs-flightsql-jdbc-driver/bin/post-install b/packages/cubejs-flightsql-jdbc-driver/bin/post-install new file mode 100755 index 0000000000000..c569e3bb12802 --- /dev/null +++ b/packages/cubejs-flightsql-jdbc-driver/bin/post-install @@ -0,0 +1,11 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const path = require('path'); + +if (!fs.existsSync(path.join(__dirname, '..', 'dist', 'src', 'post-install.js')) && fs.existsSync(path.join(__dirname, '..', 'tsconfig.json'))) { + console.log('Skipping post-install because it was not compiled'); + return; +} + +require('../dist/src/post-install'); diff --git a/packages/cubejs-flightsql-jdbc-driver/jest.config.js b/packages/cubejs-flightsql-jdbc-driver/jest.config.js new file mode 100644 index 0000000000000..4611f9c2f14da --- /dev/null +++ b/packages/cubejs-flightsql-jdbc-driver/jest.config.js @@ -0,0 +1,7 @@ +const base = require('../../jest.base.config'); + +/** @type {import('jest').Config} */ +module.exports = { + ...base, + rootDir: '.', +}; diff --git a/packages/cubejs-flightsql-jdbc-driver/package.json b/packages/cubejs-flightsql-jdbc-driver/package.json new file mode 100644 index 0000000000000..d1e685fd51603 --- /dev/null +++ b/packages/cubejs-flightsql-jdbc-driver/package.json @@ -0,0 +1,55 @@ +{ + "name": "@cubejs-backend/flightsql-jdbc-driver", + "description": "Cube.js Arrow flight SQL database driver", + "author": "Cube Dev, Inc.", + "version": "1.3.39", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/cube-js/cube.git", + "directory": "packages/cubejs-flightsql-jdbc-driver" + }, + "engines": { + "node": "^14.0.0 || ^16.0.0 || >=17.0.0" + }, + "main": "dist/src/index.js", + "typings": "dist/src/index.d.ts", + "scripts": { + "build": "rm -rf dist && npm run tsc", + "tsc": "tsc", + "watch": "tsc -w", + "test": "npm run unit-tests", + "unit-tests": "jest dist/test --forceExit", + "lint": "eslint src/* test/ --ext .ts", + "lint:fix": "eslint --fix src/* test/ --ext .ts", + "postinstall": "node bin/post-install" + }, + "files": [ + "README.md", + "dist/src/*", + "bin" + ], + "dependencies": { + "@cubejs-backend/base-driver": "1.3.39", + "@cubejs-backend/jdbc-driver": "1.3.39", + "@cubejs-backend/schema-compiler": "1.3.39", + "@cubejs-backend/shared": "1.3.39", + "source-map-support": "^0.5.19", + "node-fetch": "^2.6.1" + }, + "devDependencies": { + "@cubejs-backend/linter": "1.3.39", + "@cubejs-backend/testing-shared": "1.3.39", + "@types/generic-pool": "^3.8.2", + "@types/jest": "^29", + "jest": "^29", + "testcontainers": "^10.28.0", + "typescript": "~5.2.2" + }, + "publishConfig": { + "access": "public" + }, + "eslintConfig": { + "extends": "../cubejs-linter" + } +} diff --git a/packages/cubejs-flightsql-jdbc-driver/src/ArrowFlightSQLJdbcDriver.ts b/packages/cubejs-flightsql-jdbc-driver/src/ArrowFlightSQLJdbcDriver.ts new file mode 100644 index 0000000000000..635753f40e1e6 --- /dev/null +++ b/packages/cubejs-flightsql-jdbc-driver/src/ArrowFlightSQLJdbcDriver.ts @@ -0,0 +1,113 @@ +/** + * @copyright Cube Dev, Inc. + * @license Apache-2.0 + * @fileoverview The `ArrowFlightSQLJdbcDriver`. + */ + +import { JDBCDriver, JDBCDriverConfiguration, } from '@cubejs-backend/jdbc-driver'; +import fs from 'fs'; +import path from 'path'; +import { assertDataSource, downloadAndExtractFile, getEnv } from '@cubejs-backend/shared'; + +export const OSS_DRIVER_VERSION = '18.3.0'; + +async function fileExistsOr( + fsPath: string, + fn: () => Promise, +): Promise { + if (fs.existsSync(fsPath)) { + return fsPath; + } + return fn(); +} + +async function downloadJDBCDriver(): Promise { + await downloadAndExtractFile( + `https://repo1.maven.org/maven2/org/apache/arrow/flight-sql-jdbc-driver/${OSS_DRIVER_VERSION}/flight-sql-jdbc-driver-${OSS_DRIVER_VERSION}.jar`, + { + showProgress: false, + cwd: path.resolve(path.join(__dirname, '..', 'download')), + skipExtract: true, + dstFileName: `flight-sql-jdbc-driver-${OSS_DRIVER_VERSION}.jar`, + } + ); + + return path.resolve(path.join(__dirname, '..', 'download', `flight-sql-jdbc-driver-${OSS_DRIVER_VERSION}.jar`)); +} + +export async function resolveJDBCDriver(): Promise { + return fileExistsOr( + path.join(process.cwd(), `flight-sql-jdbc-driver-${OSS_DRIVER_VERSION}.jar`), + async () => fileExistsOr( + path.join(__dirname, '..', 'download', `flight-sql-jdbc-driver-${OSS_DRIVER_VERSION}.jar`), + async () => { + const pathOrNull = await downloadJDBCDriver(); + if (pathOrNull) { + return pathOrNull; + } + throw new Error( + `Please download and place flight-sql-jdbc-driver-${OSS_DRIVER_VERSION}.jar inside your ` + + 'project directory' + ); + } + ) + ); +} + +/** + * ArrowFlightSQLJdbcDriver driver class. + */ +export class ArrowFlightSQLJdbcDriver extends JDBCDriver { + protected readonly config: JDBCDriverConfiguration; + + public constructor( + conf: Partial & { + /** + * Data source name. + */ + dataSource?: string, + + /** + * Max pool size value for the [cube]<-->[db] pool. + */ + maxPoolSize?: number, + + /** + * Time to wait for a response from a connection after validation + * request before determining it as not valid. Default - 10000 ms. + */ + testConnectionTimeout?: number, + } = {}, + ) { + const dataSource = + conf.dataSource || + assertDataSource('default'); + + const url: string = + conf?.url || + getEnv('jdbcUrl', { dataSource }) || + `jdbc:arrow-flight-sql://${process.env.CUBEJS_DB_HOST}:${process.env.CUBEJS_DB_PORT || '50051'}/${process.env.CUBEJS_DB_NAME}`; + + const config: JDBCDriverConfiguration = { + ...conf, + database: getEnv('dbName', { required: false, dataSource }), + dbType: 'flightsql-jdbc', + url, + drivername: 'org.apache.arrow.driver.jdbc.ArrowFlightJdbcDriver', + customClassPath: undefined, + properties: { + user: '', // user is always empty but part of jdbc API + password: process.env.CUBEJS_FLIGHT_SQL_API_KEY || '', + useEncryption: process.env.CUBEJS_FLIGHT_SQL_USE_ENCRYPTION || 'false', + disableCertificateVerification: process.env.CUBEJS_FLIGHT_SQL_DISABLE_CERT_VERIFICATION || 'true', + } + }; + + super(config); + this.config = config; + } + + protected override async getCustomClassPath() { + return resolveJDBCDriver(); + } +} diff --git a/packages/cubejs-flightsql-jdbc-driver/src/index.ts b/packages/cubejs-flightsql-jdbc-driver/src/index.ts new file mode 100644 index 0000000000000..93b0c22ff9757 --- /dev/null +++ b/packages/cubejs-flightsql-jdbc-driver/src/index.ts @@ -0,0 +1,4 @@ +import { ArrowFlightSQLJdbcDriver } from './ArrowFlightSQLJdbcDriver'; + +export default ArrowFlightSQLJdbcDriver; +export { ArrowFlightSQLJdbcDriver }; diff --git a/packages/cubejs-flightsql-jdbc-driver/src/post-install.ts b/packages/cubejs-flightsql-jdbc-driver/src/post-install.ts new file mode 100644 index 0000000000000..6a25e8c5f0035 --- /dev/null +++ b/packages/cubejs-flightsql-jdbc-driver/src/post-install.ts @@ -0,0 +1,12 @@ +import 'source-map-support/register'; + +import { displayCLIError } from '@cubejs-backend/shared'; +import { resolveJDBCDriver } from './ArrowFlightSQLJdbcDriver'; + +(async () => { + try { + await resolveJDBCDriver(); + } catch (e: any) { + await displayCLIError(e, 'Cube.js Arrow Flight SQL JDBC Installer'); + } +})(); diff --git a/packages/cubejs-flightsql-jdbc-driver/test/ArrowFlightSQLJdbcDriver.test.ts b/packages/cubejs-flightsql-jdbc-driver/test/ArrowFlightSQLJdbcDriver.test.ts new file mode 100644 index 0000000000000..5aea477d44237 --- /dev/null +++ b/packages/cubejs-flightsql-jdbc-driver/test/ArrowFlightSQLJdbcDriver.test.ts @@ -0,0 +1,49 @@ +import { GenericContainer, StartedTestContainer, Wait } from 'testcontainers'; +import { JDBCDriver } from '@cubejs-backend/jdbc-driver'; +import { ArrowFlightSQLJdbcDriver } from '../src'; + +describe('ArrowFlightSQLJdbcDriver', () => { + let container: StartedTestContainer; + let driver: JDBCDriver; + + jest.setTimeout(2 * 60 * 1000); + + beforeAll(async () => { + const containerImage = await GenericContainer + .fromDockerfile('./test', 'Dockerfile.spiceai') + .build(); + container = await containerImage + .withCopyFilesToContainer([{ + source: './test/spicepod.yaml', + target: '/app/spicepod.yaml' + }, { + source: './test/yellow_tripdata_2024-01_499.parquet', + target: '/app/yellow_tripdata_2024-01_499.parquet' + }]) + .withExposedPorts(50051) + .withWaitStrategy(Wait.forLogMessage('All components are loaded. Spice runtime is ready!')) + .withStartupTimeout(10 * 1000) + .start(); + + driver = new ArrowFlightSQLJdbcDriver({ + url: `jdbc:arrow-flight-sql://${container.getHost()}:${container.getMappedPort(50051)}`, + properties: { + password: '' + } + }); + }); + + test('testConnection', async () => { + await driver.testConnection(); + }); + + test('query', async () => { + const count = await driver.query('select count(*) from public.yellow_taxis;', []); + expect(count).toEqual([{ 'count(*)': '499' }]); + }); + + afterAll(async () => { + await driver.release(); + await container.stop(); + }); +}); diff --git a/packages/cubejs-flightsql-jdbc-driver/test/Dockerfile.spiceai b/packages/cubejs-flightsql-jdbc-driver/test/Dockerfile.spiceai new file mode 100644 index 0000000000000..78674e81402f5 --- /dev/null +++ b/packages/cubejs-flightsql-jdbc-driver/test/Dockerfile.spiceai @@ -0,0 +1,11 @@ +FROM spiceai/spiceai:1.4.0 + +# Copy the Spicepod configuration file +COPY spicepod.yaml /app/spicepod.yaml + +# Spice runtime start-up arguments +CMD ["--http","0.0.0.0:8090","--metrics", "0.0.0.0:9090","--flight","0.0.0.0:50051"] + +EXPOSE 8090 +EXPOSE 9090 +EXPOSE 50051 diff --git a/packages/cubejs-flightsql-jdbc-driver/test/spicepod.yaml b/packages/cubejs-flightsql-jdbc-driver/test/spicepod.yaml new file mode 100644 index 0000000000000..29d154af3eabc --- /dev/null +++ b/packages/cubejs-flightsql-jdbc-driver/test/spicepod.yaml @@ -0,0 +1,7 @@ +version: v1 +kind: Spicepod +name: cube-flightsql-test + +datasets: + - from: file://yellow_tripdata_2024-01_499.parquet + name: yellow_taxis diff --git a/packages/cubejs-flightsql-jdbc-driver/test/yellow_tripdata_2024-01_499.parquet b/packages/cubejs-flightsql-jdbc-driver/test/yellow_tripdata_2024-01_499.parquet new file mode 100644 index 0000000000000000000000000000000000000000..4755fea45aa4231bd1a0bfdfc162416e0faec0c1 GIT binary patch literal 21388 zcmcJ%2~-ow6FA(HbYKP&NCJrgLBnanWjI7skO^mkpy5(fRBi!55z)mvARs6zC@S8d zsNjj`;<3B&23K8lJ@D8SP+2@y@kZBmzZ!IRb^pKjz4!m#`=Zq|>FKVjuCA`Gs-B=x zM!1Twh%Yh?g$qK6v>>2l0f>;Of(8GbL>>CjKu@HH&?2I1JR6>M=o2g@9W4@}@Nj`B zI#3iIEeMQ`ijG!tqN1Zj(a}+GA1zV_iUb-F2O7Y)=)gdzj1ojghlg{Zh*ky!Mr#72 zp#tg!ny3Jg2x^I;SR^78{Ad9uN<>6U0;2;pN|AstSD1>F(a`}K8c>Bt1GhSv=zi}| zQ89<%yUNrFU7b8BcA&%`UATORLz1HKGf)nAaRJKeGs~gOb8du^Kk<7gM>Xt+lJj9R zlv^dGP&)f>fU;0~fh>s#ej_~1o~Po{qx z1pIhv8L@Xys)J|L2zd*6?CD8hqS+QGT>YjN`kgjY!?Ux&R3lz{SgjzxubvA1me?PJ zTAN%-NA7qR4Lwpa)ifCyI|pu`xlmcSW)Y>sbNtoCwFPw+x$#><= zWP^My+;()P@o^JZPLtng<^tLTK@_laZ@_m@`Yg)_5<%D0GV*=dLg3_{jXzYF?vq!M zlj1HxZ}ts&7wK|q2Rsulm;hZCZrudsw!Lehq=!w0GJN1hC|5r(fSyC*)1+kmg6+^e zzElU*S7;5C`Nt}utiAdTl#j1uL)kcwQMXHPRzRnH=4qYeq*3M2sn?7xP_ZsduE4y_ z>M9)fI<1vdw$FyqT}+jClBGpy&`R-FF?2q7y$Z^HM}|QUB$Rhz)q6D}U6+goRatrv zWSRS$yq_W!cVg0sW?Oi^K>ObUXLe?Piw&2gXAPxH>r@L zA}{Zs513Pzrvhg8W6*R=qk2Ue1>{ z;z5CRd>nQk2Bz;&CnNP1P2;HW((lqFc1i#l)ufN3Bs@n*#~UIZUz!uL$wzkGpQsMm$j!MylRZP zfjl}q7sggKutY|_%uNQVB$%t~@s^h*61-_OrNF-5sZ+@Y&bGoTyed(x!3G^AByOCp zmXIT@wgQKnswgR57a(uN=}q!ll0SF}hbDcB0y#3W&1^MDp z1q>leDX+!rZ#QM(m>_i{K66CQ$5VEwyU58Vb2$ofPc+y&e0!O?8UGmyQcshsRpczu zHjb3swk;Os)^P5((BM=>S_7$i9tT{LC*+m*mz^c`&kHXOi;$y zHR^8s?Yb~6T1B;zX3GOOUL+m06L9FQXp-S35lB>BTvCQJ=YXs&;!1RQZX?V`_7rtJ z*X43%Y?~KeHcYG_@ef||TwIp}(lo09O*x_i7Fs8c0;U(xPJnOaQHsQ~x5!ESum&Vk z><$a+jn7h!3@?a~OYw(8z~`yOY6X7xPMw7x4FNW9&#jY?&+IZdUU<&n5-mRVphSU< z&jFp%WnkqGW$uCA4|l@~*pLka@+RtFi6500;{=;D1-@e`&%#GX0oq&7s4g5o>mkB| z*Hk_3Q>gC3zrUr*@E?7|sU+65K$jnsFcFS@np8NaLfwgn9Zu`Qw~LyJ@veR)#rStb z#o)hYQ6y>aIGfXe+c!Sc;AwhkEqE5Uqzc#MHg)55LtuazPn%+Jkr7NH71UJB{ju-! zu~s@Sg;DyIxdMNba@dhr!}DkMXG*k@`f`6hk6)=-pEqbqiCCnBuF~eQNuex8SCzLw zpKqexPBm{-L^JEB~`x^8p!mbmji~ zC6?Z^y6c~_ReUS|VpG>_OcmQ2^JSw?)|9O1r%4Dna)Lf@>JYsv_QdkQAH^=?j?W=X zf-Xqhl5;BuEwJb551176B<|<47khgRZ*N@Vzx|TokZ-!YwAEJ2`p9N?mp#1qn{gGL zuP1Ow>TI?Q$lX|_s!0`W2?|qr&B7%meO2YQVd->9L~mlH)8&Q&`HF2}>j%$#j~yy% z!)rpO*2Se?sS|l>wniLU6zyoTXFMlgG;E}H^ueV`b;*y#F2+Z4e!p^N=jy!^rfCO| z_N6Bk3E_*jy3OF;+?b?1ze+GHQajpx;!le%=8MB_d8A+4HSW}^-&eb2-fo!wa@B*| zR95rJyv^2=V{NkgoS)i|^wi>L&ZFyp3eP?b+%n_oukZ3*jmCS=d}(@lan#;*cC+7h zooU)WLclihnRRgH!Dp9B`+n$t{qn7GYi;^98k;s|w$l0T2Ik(yiZ;u_bg`TF)#muh zg?yW*`zM}RIH-h-3bjx@SDr}`_fN=~CQUS4GRgCbhBNe)pTQpj-{P=<8$xR{ZF-J|WKDN71IX20~W6+9iO>6Tq z_G}(V@xEJkH>=}AE;p35A${!^W%{>Lma)W0w)0i$>#Wi32a2-r~nhvEv9!!FZM ziU)NAPP}_Av~;=m8?+f~`VjoAVm;rnR){nY3xdbfW14~S^WTH}GwjJ*=#~CE<74n1 zQ7Ury5+|s*T^#@j?kE{&XXS6>0KqYp-2@_r)OY^__?h})4RCwmV+TCGGFBhTod-uj zIcIPI@aA>%@E3#2jCC( z7<(DXig1Nq1}3+m=C6(5oRF5i!OtWmeI0>Mv)$m+^}ccw44vK{@Jk;5wFSmGZ23w% z1z9!rF!UT63C=AU6|mPX4u|;5b!2!%G?2S`ufUEZbM~sB$t=GcfNF#-_*rv5f+N=B z=wy*Y3dh3z7U^B+zj?Abl$S^&XgFv%xE;i4*dxe~`iy^g(%2fR=l>=5B3E<0p?XRG z=bRXF*D%=pNY`3EG|50_Q10@RL3zK6amGD=P;nZ`%XjOc%{P-gpoVe1ROC5U3e*V9 z7{7Scm~Vj9X?n~EIGk3dSC8iyB|QeRo!EB-)VPH+j+D~98s_4hr6t_E=-+`}>qd6N zj`a9=&qiG|~dfq(tyY$+J1&CzB>QKf%^&-S$1SJlFLYYAoV*K>51iJ(NF2 zPXGm(an&B~Cp75WRgz1*TmajEKPadXZe%ntaocsomK$#tpOfTL#7G3XtxmN3L> z)w$&O@5jLKQg`=d%EOF@vC(!slyUmbP*(0Lf^vB6Jt%wMkA(94AydE@_pz>?JVrrC zLUJuxP;KjN$mu3qD~h3J+4^sxoN`79WuOLJ1M>aOq0p%+0s?}mKc#Xi$vgc;K#v-+ z9@v<-vW~_%+h7wuUI<}Akf94GrEzmTuzxRjAaJ{pV!ZO!nU?`a_&{|op1B6xsX4B} zfa3MjR1S@U=gC#1*jsFzT` z_H_)Wmh{_p6l(5TF+T6Olx`S{&+)o?96I5lrYG9)A_KP9Ku^)UH!zs;iX^yCDW3-< zR!Owe|#RWdUZMYCmxyVD)Jcefo8)uZG+zJ8~4Kf zuPK>8u`Y)R#(I~5P>Ke%KOfHD_+`GC;@^a_zfHe8J zJ3PB(p!On<*}4KB&yspUm-z#FL$&pXCO)}g_H~Yyyf?`a1iV_LZonZ~b-84-^AqT; z>a!f?)w>&J2DjHk^~^FM@bsaXS?z1a4+EP5jz5gc;b1$|a81v^)cZWV4_&jT9Dq)( z`6Z2{;f_vFbA4}hJ!vTfx#K)fn7v7>yrFS(;uv6L>LYa-sb1R&TbXQbodRoD!6M#t zcLMNxHla6A*=O?t?ms^H4jSiQPxHb*Bsb|u10o&}?;6x3A)lALW+pTWCW`bsF%=Ym zNh{EJ&qR3{$(msYT%Yzp(Ap|eoJEqo%Ev%+@%vC{{&B>(Gb%FRNFU(r@qJLP6(?av zHTw;qkN$8-Yhdd~;yBps&XsiGvGz^PWNEb&W}A0b+(MDU`ZDMjWduus{X$%2KpsCf z6c&r-bOAI8E)#3Pc)1Bcw$mNcH00@^Ss|`wDcEWv zzkz^AHc2dnu;Dm_faLhci(!fE-2983l$73B4aDwW6YD6liMs@zZhM;t>S3(c7Y1VM zP!0nOdn1?N0e#aDnJ}~vT8!|04#a|fORK_;3UG$kxQe?VZJ>j7J^oJ)M}t{3FxKY7 z2Z3CZDnMp;U!}E>eFugCDOM)9{d1p`@JTn%Hcl1!Z2l$S@%U;80bY66Kqz)#3>Zc< z1_n!RkFnxNxWkptX%_;*1EMHzEIBWC~E0_C0L1<>d2@G6-0+^%y_x{GeWXx6QSMM9PtUxqd=e29z5 z(CzP_WKkqgG&1A<#2P~~$(K>% z@_aF5g;xHmZo!M@K!kDZX;7pLVZRvyN(P zwhAaQbxye27+x7%X02WuP#0l4Y_%f!%E6Mzej_%~g~9=gqU4d=ndl*1y{6u4Tz9 z`G{>0HLxsB>8oeFM_H+f|DllEd+?l8ZbCqbiG1Y2TtQ;clHP-6yy_Mtsmg8Ct2|~3 zlS5WIjy{}Y_P{Q5BnYs4(2A6>bpxlg?^@+vb!o$pnQuJqz5H!N)wp~E%aDV$m$#@^ zIE*`guhPeZTzxT6cGUY>I#QxncCHXB%U@TcdA zjpcSDw#Dw-|KP_;_esBg$Ts=ylB3UjJk zp#TaYWf>x*h(U+s5^w<7sU64@eCq(xX&Hl5URH89d10w9dmexgoMsOUpa zF22hIU%WsN5Z%+LPf8Pvta!&2!%yTZnzYjTRfz z6vHm?{UIz48S;t|;oQu<@4M`zRT~Jj484PKb@>t>xmi9heAV!sO2s$b!kW=vVNxV^ zE=Ck^(Zq zial)STJ$DN2P1?W*ss274I-UY$RaZiy{4M6*&uZp-sl9RTAVvkC$#O&^K$J**TYok ziF0vyH?jul^dZt>aQG|dEc6fvoAYuJpH~lqk%qUThheQCgL>2zmWs%*N9*Fs$Rp%wz2WHu-AFGi6$@##0u+fvFPsrF z%gjO@pj2II8n59vdm&R8FzGCXS=97!D2Dq7z$FhF3wR39inL<%B2$N6gLJF`UVsFp zycpLQL^*dM6vp32PVGWAyh?Z~LlVd))>^}8KRU;NaLUkc7gN#OFdZ_JcjM{(K`?)Y z)gp1G1Q}5pEW6KZL3hK-P(OJKx-c~t_2O0S>+Iph#JLjbFHynZVETZ010X zMF=Vx$(aHf3mA+8Pg1TzR=`Q18%Wm1My|qx-9Sxe;jl)8oy*YkB~o;O*Zn)f(-ko2 zXJKHeVY)%5pDU0N&@rTPF~=SpK3TW#!>p-YQ)$$92||*vO4JT+VTVi}LpESqSP!up zqthHJ4m-NTa6N#Qm4erZ_^>M5WFRL50U%bG4`q2N^S=AFr-&h(@rpWW-81@qLb!Ey^dPdaXTv$~F#RA)qO0PWY!bKvd zF%7u{JBVxMo_e)@Dm&Q7a!Bs0F375uas7(;@`U^3a@!DVr}!(Un@r66Rt1#16^4i$ zqldnx9RTMxMQ3=8<;QBIZ<4aPNUrT2D7wZ~xJvcMfi;WhXD( zFeLXy=gm{wmu=z*EItrd?aQi^1qQpDTNh}n{fmY2F{eqDP4Iv|7qwAaf^5|*aQKd- zheCV7BsX>Q!IBjP!#57iGqBqcPyp%GcdpY7q8*}l#&E7QpBIt6_RfpCN$8Dq8l5;# zwl;9*Dr&5Ba@!(~T`%Wx$52%(r)t!a7-fL%yZ0QY7UTF+#Ul3^7x4b1^Q&AZbv!XU zn0h6S$ZbzGAK-XR5yPIA$vK>HEBE!Sv%A-QJEisH65%%&Pd8ZKuYLVcb7_6iw9ecb zc9oHCu>O;>YiYkdy_NS(SL>M-1DB2Wnf>-@+aIk~o4%j>$F^LkF7+`T34Ke=2AplA z$=g9oXSF*YREDa8m#y-i<3VJP0FSG0>@n5;8g+0#%Z&QxeD?VYhn>4#9a@+?Y<2(m zd5hEhIzrd3OTV7O4_IKcZs1h0ZutS>zzD++-k0mz%#Uv{kGrWl^Yezrjjz9-yZCDX z!8R`wIfaT07@x;9^lzVs@pE8PLySKITDXxd+D3fo>-`>7RW;joXuE(WteFjhh z@BrWqKmfo9fC2!0An^pQ6#(x5wg6lPa0HkNPy;XqpbTIs0Id8T!90X(HNa+o7=TFt zzXA9HJOWq-pa9qb@D$)Ez|R1`18f6u16U1^4Zr~&7QuBRz+8Y%fMEb6)Q7-z6o4Mw zOW>LW5ClNMcR5^J0Ez*G0F1fN6K&M{Qc{c9uS$r|!qQXHQZA;+!l_a^LU#V7ZCIJb zC3c{pRalY0juRLq&WR8AOgj-2X0ctmp~LFOg~^)jnZlMl!aw)cmFYpb5`Aj}o01A{ zmC7V-<0X-1;gzs)QnS_-cB$`k3eTse=NqxrgNEtvnlRO8+f)l8TXJ&IW@;Ji0=!=!mXyBmxPF5g^GStE!&U#;@%ZT_?^U0RQd^oB2F#Yy7=f(`Yq#B;UP zKBWVr&Br)ht1*k5W~V<`S<~gI+}TpSy4XopdPYwjxPSVtamz29BO@mACxyFKNk}WB zD$7Vmw;z+|JULQ*KF{sa!a*n8h@Ho)aAJV2s_L;pp9{&gvZI^NUL$n3%t*CM(TO=% zOx+eJ-G}+ieRR#LI^V(Xo8q8Re7%HIceh<#IBVk0?Pj(6{4QHto=>s$qJ93TRq6<`B^5a1O6vzGKl8}+|jOXu0In*Lr(`bw=f zj+RM`iVG4>qZa-i;klAcl+0F`XSAhwL6k67 zfeWbvN8*MHqx4o}OQNbpJ0A#>`c(AFI8(AgQ6plv#}KrzFm(SKc`DbBm(_wYmiLa! zUm?%dBT@sKFAg7ac5%C^Yu5S&BQ8t0^9B(0u5lNVjLuLfMC-MwMA}eEnJ*J1Odp&_ z`x*R56r&WXIjbT#dSyWM45|387Fo9K1plyg0DW#bzH-W*KkK|S7o+W zq7?O+_|26vff5HgZW*E|aJZ5|v0Pm*T50xW(_WYCtlVx>il2foTgo4KlJsz3lM=m$ z9o1O~MLKju9&)oazM$VVGdYNra*tJOl(Rs&J7+E@E>CA8kSa$l#Pq;;#i9j^+x$;t ztB$kFC5^%%^1^l^wbJ~Mwec2?nXKlfIH{R4`A7D`A?1prk_%33UEGW+vbeP}bL458 zr~2Wxp5ygw?-lQ=^e!pmTV0Y=s5-PWf9F>0eY&M~y|+WC`}MV^E2_B__h zSr1R&drnW4${Iro6TTQAtVOBFHdI713z6>)%F^?y8DlINZDzI|w&>|subf>V0+`3l zwx?8;^(+V^B{&%@2(mxvH=}bjG~pwfkH|8N@_Dvgq70Fo-h6@&6bLI4x)9zNVM@iP zv6N(S1gMO#wIE?9gFTc_#UWe5Orr%1QbG$_idFT5azBAQr7eV+6C#AnBGR&K2^MD@ zprp#Agvu6{2Xxj#%7GxfRKU=3MDi&n#lUCw#VSKlD_EU_Jyxd~ws#2PZRr$(;C6U3 zK{rXg-*V!S20)407esu8@ZT^jhXU1PBAAXb?EpW`lVW$QJ`xV1 z(1rn@DKKEXMgUUd!RP~FNF6a0AC>aFFra!+3mw6h$yx1yhyyT@+O& zI}pO?5q!*b|2M`+DN~p))yKkesl8CeZbll1lEMdBCz3qY>FJb>Swb?5edYNaI=?J6 zz`@pFYoH!$kgagRxyBqntB4&Z7U>);$CQ)@Ex1h6c$ktu*vZIXR27|T6}PJV!B(X% zVgJo`dhFGV_;BA7~fZ8yOLFk-1B)R+41n!qJ6maypVMqom*DCaM_h= zmDJTpoX9E~?X9X9VJ+HG>ai*i@0p|zeUzF8NmSiQ=`KS8Fa2sO6K^(-)0WH>r&iJx{gcZ`hK>=VP& zWZUTtcxak6=&H-bRp^kWE9h!~=*rHE<_@KY4(C2MT{NjAP*+qNb!Bf3TIu3;E|@QT zHT-zs=0Vw`EyR2j(K|U~ZwB?n0AY!i5u(^ok&v-Qurom(j7xL$Nz~;_kpcqgffhs3 z1$X^GnM2x1W{YV?IS}egGwOjwy04Ovi&(LrEfrQGzCa*g0S-h6;2*&u1p+=nnOX}7 z7ToY4t4Ej!IF5X1M+iAKa8(LSIlTi2zQ6?96A0=BNPq=Oq8}0w7JPvfA37$Q3It;2 z`CwB9u>cX461WJJd_LjKhfdIW24^fZ7{T%8C=`T1B;YGWgdkiX2UEsn<-hl+$Bx;l)fyr_%h-`A7-L4+!639qHx==X+7qVfuVe{fh2U>0y4;umv zYoBYdn52p+DmX~3! z0><$tNNYDTiD^(7FGv@^i4VrFO?j=5TV>Lie2^sx zvTcTx9F066-Nc7FYv)SD4%0##m|o{vB!#w&%(=W;0gZ+NGApVRUywsLLl~`9rUbF& zG@fM!eN8eOASqUy8Hcqt&JB9l9aEOafNaT1Ef+T`S zrUXO^At8JO{rWjfbWHUW>ZPRA1To8&h$c+Dps(d@Dd9bb zfUm^dd4vg!iI^{p@C4~O*f5q{>nRvPm{{cT^A~vcBMN{A)E}NXNDAGG78d6c#E>xP zV&OoPEb>~+cPJ%*7yr4it4LE-ETBRto^v+}_3jgbrogoD*4LJ$NuUkLy#qei6qoK^y( z%p)v5nZ4dL$5^G6(<910Ro{8ARUeXv`|kd_*cqykf@yw#Iu>T&yfPPO>nJ>+4N z{e1nrYYhKVx0n8t>|(*DL7*7~nkR)2l<)`pgz$`DQ1|gRjF(++Eoz4!uWakVT`7PK zm*DE$Xm^4LeMx`zs$J=xp|=fWEI(54BvLP0&YYgf7~=q*scenM=WPIv%KGwmMfL0y z*o`J8kO+KGjjh$tPX}Z5O7IwU%zFv63QltLg22HA=bJ z$#?gJb2?%caskIz>(1kYiR%ahzxDuw!QGapLQa%IhK7FLj0V!gCNk?gIMc!@1EHDO zFt8zVaAn=V8u-)9!JLnQ8*L>fW0%ojuZB|!6v}JGxcFt$0$KJE0npJKtR)j6_`op>>PK_7;~Q?2ggg>JbDm*N z5R6F%Pic7zuJwbsdQIRbRXR5qIPigSObexS{2dx*->^dN5OPF<1$1P*d{?k)QW`9t zdw)Qf;z%pU!*=LRNx51#IM@>)Z*aW}JwT)oo+xmC+RBIw?;fR&!?6S4qzWe8-~IGPIG` zg%5awIPU~8A%zn7=@>*CL8KyxUf*90aj<9Z+T#JIk zy0AMlA`~t`D%c7A8B;AMam+B-Qk|({oH7U$z(1VI!lV7voyfQ{EBQWfXe0xk zAzG1Pmq6fok2Bnz43HON;~3ap20(nJwU_7O&`}_&H7@ch{Ma96#EBv%4O`J2>`wpV@#9sCl)pBxCS}0Cg_T z@hgE}I;os#1VJZqU($)&T&XxRMW)-@jk|_|RMlg6l}H1O+w;0Hl7{8NX5J0{gS)Lx zuFZrY08UUL34S>Y7|;%80%>V*TliBgI8+47-Tn^QFW(L&}`Wt5cSp(FqkzLA!1Di zyf^*Tq^%;9?m61_j|91JLxAR%kwE=nG|(G55EziQTpM1sTZ7GfnWfHz z?vWbk<8Dti;FLb{I5hquDMNO;Po~$d$FKPR{38O90^Xv{5DJnJdNN;J#vst*5 z`4K^`Ya7k7WdHN7kDi5cc|eoUK5TtyF3axxVl%F{X_?yt_DVbWHGy1*hKZf~9L{>! z{=l$Ok#M$bkf!I{YnFwqO-Zk^OW&3nQ?6_>_smRb7~K`Lkn);(|3YbnqVZlyyn9 zW6tcjCLEPJ{=_1?N!NKM2g|PJC;VujC;v7pzHw_nuReW_&FXs53^fzxJ^8>AhqlzS z=NH>GZ?3NF8-I4GU5p3k<`TjD+NApYg}ru)nqs>m4u|UMd@pD{roC}u8>e2b33D$G zKHn$3&yJ?{&2F0WFa@tpk2@wt!Ni1j5|?MPY@nXlZ*zgJndLNmGYh}W3T z_5M->Zy`Ny8J+g+sb7xC?T_jf-_V)%pZW6O9JdqqqE-+SJFneKp3<~^)GT&0ux4A2)?ADo6(Zm1y?8&p z;kSxYCdLyU%pwHE&K@z=As$}~=zoNb7@{@VCl!Pe>%bGKWQn@J@o!P>3Z3TCiEu z@Q;{aN+1pNAO<2n!SRA8rtnhE-#vR+w*EKLg^1Pm!)JHp!)JG;^DAzb65gLe05nh33iUw8vp>%K^=rKOhzt5fBy~(8_S#)p zJT2-MUQtSeo6`zW;KRC#8$ylA&ESc8r%KYQhITx(8Rg4;n2SQ2Lj2N4^}EPPapO9vnsl^MTFJ3yt)ynuxz91%o9lOBGDX+dHEErU*{Gsc$K;$71WZ2T#R%x^LZ?WcACEk`<5J$0RT5eIsU;?fB{$XN!$rU7=fpB2Ej@nt_$? zMY5ldni@1YDtL*<9IFB;!jpOz$xN>H z3rVs|4PlpV%35k=aABc?NX!39AFQ;SgVQ2uiKJj{x~)2mkXm0pQyk$Ys;-F;YOF0h zIzopy3jW%wDtVq5^pwgP6Yyl!`pCNVM+U8&`2NokIm7UTD%O?a>O7W~_s|2Gc}Rt0 zq+Hry3GEiMwM_3a%fnL2vr5p_TZI?|RV0d$N8t`SAFVGk%|IE%a{l7{z%%g%3+RHd z0M}Y+Ym`r3VQC`D`!$GctTF3VX~~L;wxbngqxcGUER5GX85baQu%B5~Pjju*`C_Df z%X2$e_R*_AcQ$;p?Md+#$E*8R8rW!t8+bZ>pLzWM!DHML+>yyzPgP{IOtr!bMD6-?U0O{}dvvffXTEEb|%ITt|R?6yKL5)$19PH>` zf$LR9=381Mc;O(Y5kz}pK29nsjUHT3Jv@LD%T0@Na**EFUo**q+%Ie;{qs_i%dQly zOz=NpRbF|*DgXZEvMkO-8CR?tR1m`p9#b~piJo?{V{;|W>?N4n?IBa^_dER!-_Lb@ zv9)#n)gekJ*%((G7eE~Jgg+udGOqXkln?wVaTJ5)Gxmqi0^#-5j39bw%VojAv!?N_$iv$Lyb}EAc zPr6ciHlFnGv#zx0Wrif&NGIZ4s=G9sJ4?o|NHjOAh_?2(wK(n<7`HQvQzWn@?mFhk zl^uxe)6 znrgUBhV5dvwkS?$dHZluouy?7Ecj+2_>9It!%pC{s8egPg@W8}UE#6F8lAAILP5j{ zEs4d7IK8thBGtmmUYIWnvPFFDDWix5v{C<&8^U))8VOIw-!Zb;z#%SVr$%!3!T$gW#$ zbL+?B8pI;>j95)5=cFI?}^5rSI+GP!xr$FJf)$yv?a z=6_PT^_fx>9&!KV{p>)upqRyi2g@j@Y1X?(Xz!?g;L);VljU(sJnWiW_n^9i9`$6_ zw$fg&`uE;;U}clB`|aTaet&v;+qWxoeWuxc_+?Ajj7`MGp+2OevNLt2Up$&!agIm~ z(XUxuY;)&)nOJd6UQEkwwtL-k7|)K`QpVAw7(gRil+ zyuS2pPVwMg1|}tz+}OTJC8a~PhlgJHF~;;UWp;g_VN|%<;pTwT-gQ} zpI*YqghmZ{PU=sqh9z(%r51zD^S!!G7o}QkSN6Id^Z@c5s^jGiu zJ{R&{Sa)sfFsiOtJbW#suWOVf>sg--Y_x7(k#55lT3#!NdLC#lF1R;$wCdyTGvh`& zE_MkUyE>j*x7+{auIxJ=`zo6o96$aa>f;1HhLp$BL9&>Ir1?k--Uz6V0@TL~;r}#; zw2c&zT2MIfli&g_8u(|-hYMJw;JmQD+N_E$nvr&OIR+uMLc78zxU;o+RceTKxW3I^ zogJ3BkD6#;E{#G@4(09YqIU?L_+dsP(Rw#g5G}nCMd6xrmy4eex;8$C%Xvz&D%QmY zaq!j+#Q`?>O&8RoZZv$rq&edY7k=bKW`Z#N#XWp`8mI}W`@JqR(k9l5La^@)R1!*{Imc1t#z z!QMF3b<}yq%b*f`=*I2FXRdJ%p9e1$eca%-{*Tzxw?oX?u zvp?L+_>EKm(;wN_hJ!#g zF54WIwF>XiZYDL*KOF|Rq2yKqKz;&~pj9AX#6-u9T*>2?C;J`t|=6 zpU@9Z!?b#26^n+5$-n|xA?YFz-~|w>5}E(EIiguC4Ci13vpg|V#`UNh0hLl%+5g!X zh_b3QNw|h4;*=*4nM3K=0i;Sv=@pb9bHYkRr~V?#4{jBlSX~u3EU2?&=}qZe6nD$& zhkpDU0g>06rFXL$yIJYKdtQfgv^=Z}pB05D$_bn#} zdQ{rQ1x)2M7Nwyuta=@@`h(^z?&+hRgbozqDZL zJo7ekU*}pwjl6G(P?ltyUCX|t@|Y!H-xyk)e#R-@ASB(#_T)CSuD!x2x4oj^(9}X< z(QgIg%0s6H)Etbl_z;tGQGnX2w87jv)^1bjBdKHAUF1B|T^yP}!ocjb_WOacd1m_@ z_qeBf%c2q~|4VO2`<2#lb{(ib7iM`tn)Ng7s&l0jw9I;eM?vLuD;By(n^>HzWL06d zxz$eEV1rV~*Xk%WVVksTYCZPSpqSN89uf35b`_>HG0n>&482#`J+S_+ux8GZv9^Os zo-~X%x*^TnVv#hx--e}5q%v=#898c5!x^`b(d8$%wy^t6?VXF$<`FDMc_n2NF(c)X z!>Xg3IUhHl92(f-eW1cNEqhI6{3PoIcbtS5?)*MoLG73wrW}3PblSkz9uCSVMaL35WanW6o(XFTJivl(;tiN59;y?QR*0X2#@AhwSk1F4s{9pCS2Q`sF ztf~O*A`vWBF#A$1AJGs%(}Mp-wJcUov}=o`LI`IOi`f)tcw>i%V{Wus5zFj@=>RxP zOq!lJDJfyXw8Yfp%y^MK60z)9@K;olCnrtGRtMNwBas1AnC4_9XHCdTOPn-4YeG_d zPI69KX7Z;;qMk=d*;BHnq@;ZDjKO1^6+dlS^5luh*%K0{OrMcn&^#wT9H$fB*tHUhxZ-qyPp!G@dz=P40*HC(-m;{ z`A?_-{$lvmy><-9Nv}svP#{2V^yPO3=c;1X*K+z= zS3e;JS>({QLpLAMpQrz)*Mv6#f>_r%C-n^*`Y+#^MT= z{hoRDopXU_5!6kPxFK#Bg8~ zf4XB(z4#Z^C&s>7WuK7jHxQpTu-6t6_W5}PFvq+(E5Tr!7-`P<@;igEc{z*~6!YI1 z;(obCKcOrz5?318S1u>)&o2HyP@X6Li?a*!;(tA0 zC_DuUe>44w#3zIE33(?++=}hHb`kd7JO4%A_iyB=>jywC{2TX|^$hN%YyZRj-}dVh z@}+F?B9{HeeT02W{lCateg8(+${=UfSkLFndItHE|04gw9Dc%o$3lG2)V}$9!oGd~ zKlrsH|6#sIGjy=2^x*&M0Yl*YI*<%Z&%gHKEBpG1Mm-iEX4!Y2BkWh5``zZ8=H9t@m8!-Q=6hs2i;7!up6L0~}sUxEG4?c@`!MQqq3 z>`NcP+IsjeE&Mkvgc(}@O#YYk45_nq{~67fyVEBEpj{VO_MJ}%`(01|CGg=Naeeqo zyS}Vv2-NK8As{~b1GAmklSn2D0EZ;NPdXzxdm3zy(iyHU?k=uUS;F+Rj3lX>!qYt| SDc(KVQ;tr73^ed}IR76#r_Hkf literal 0 HcmV?d00001 diff --git a/packages/cubejs-flightsql-jdbc-driver/tsconfig.json b/packages/cubejs-flightsql-jdbc-driver/tsconfig.json new file mode 100644 index 0000000000000..889114bc38306 --- /dev/null +++ b/packages/cubejs-flightsql-jdbc-driver/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "include": [ + "src", + "test" + ], + "compilerOptions": { + "outDir": "dist", + "rootDir": ".", + "baseUrl": "." + } +} diff --git a/packages/cubejs-server-core/src/core/DriverDependencies.js b/packages/cubejs-server-core/src/core/DriverDependencies.js index 2c500681aa4f4..00416ef79ea32 100644 --- a/packages/cubejs-server-core/src/core/DriverDependencies.js +++ b/packages/cubejs-server-core/src/core/DriverDependencies.js @@ -30,4 +30,5 @@ module.exports = { pinot: '@cubejs-backend/pinot-driver', // List for JDBC drivers 'databricks-jdbc': '@cubejs-backend/databricks-jdbc-driver', + 'flightsql-jdbc': '@cubejs-backend/flightsql-jdbc-driver', }; diff --git a/tsconfig.json b/tsconfig.json index aa6ec37cefcb6..50fb14e16d280 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -103,6 +103,9 @@ { "path": "packages/cubejs-databricks-jdbc-driver" }, + { + "path": "packages/cubejs-flightsql-jdbc-driver" + }, { "path": "packages/cubejs-prestodb-driver" },