Skip to content

Commit

Permalink
feat(cubejs-databricks-jdbc-driver): read-only mode (#8440)
Browse files Browse the repository at this point in the history
* Add .editorconfig for DX convenience

* feat(cubejs-databricks-jdbc-driver): set readonly mode if no exportBicket options provided

* chore(cubejs-databricks-jdbc-driver): polish driver interfaces/implementation

* Update docs

* docs(jdbc-driver): update driver installation on macos

---------

Co-authored-by: Igor Lukanin <[email protected]>
  • Loading branch information
KSDaemon and igorlukanin authored Jul 12, 2024
1 parent 2b3bdcd commit 6d2f97a
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 24 deletions.
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ here][ref-caching-using-preaggs-build-strats].

| Feature | Works with read-only mode? | Is default? |
| ------------- | :------------------------: | :---------: |
| Simple | ||
| Simple | ||
| Export Bucket |||

By default, Databricks JDBC uses a [simple][self-preaggs-simple] strategy to
Expand Down
5 changes: 3 additions & 2 deletions packages/cubejs-base-driver/src/driver.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ export interface DriverInterface {
queryColumnTypes: (sql: string, params: unknown[]) => Promise<{ name: any; type: string; }[]>;
//
getSchemas: () => Promise<QuerySchemasResult[]>;
tablesSchema: () => Promise<any>;
getTablesForSpecificSchemas: (schemas: QuerySchemasResult[]) => Promise<QueryTablesResult[]>;
getColumnsForSpecificTables: (tables: QueryTablesResult[]) => Promise<QueryColumnsResult[]>;
// eslint-disable-next-line camelcase
Expand All @@ -246,7 +247,7 @@ export interface DriverInterface {
* queried fields types.
*/
stream?: (table: string, values: unknown[], options: StreamOptions) => Promise<StreamTableData>;

/**
* Returns to the Cubestore an object with links to unloaded to an
* export bucket data.
Expand All @@ -258,7 +259,7 @@ export interface DriverInterface {
* Determines whether export bucket feature is configured or not.
*/
isUnloadSupported?: (options: UnloadOptions) => Promise<boolean>;

// Current timestamp, defaults to new Date().getTime()
nowTimestamp(): number;
// Shutdown the driver
Expand Down
34 changes: 20 additions & 14 deletions packages/cubejs-databricks-jdbc-driver/src/DatabricksDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export type DatabricksDriverConfiguration = JDBCDriverConfiguration &
* Export bucket AWS account region.
*/
awsRegion?: string,

/**
* Export bucket Azure account key.
*/
Expand Down Expand Up @@ -119,7 +119,7 @@ export class DatabricksDriver extends JDBCDriver {
private showSparkProtocolWarn: boolean;

/**
* Read-only mode flag.
* Driver Configuration.
*/
protected readonly config: DatabricksDriverConfiguration;

Expand Down Expand Up @@ -221,6 +221,11 @@ export class DatabricksDriver extends JDBCDriver {
exportBucketCsvEscapeSymbol:
getEnv('dbExportBucketCsvEscapeSymbol', { dataSource }),
};
if (config.readOnly === undefined) {
// we can set readonly to true if there is no bucket config provided
config.readOnly = !config.exportBucket;
}

super(config);
this.config = config;
this.showSparkProtocolWarn = showSparkProtocolWarn;
Expand Down Expand Up @@ -289,10 +294,11 @@ export class DatabricksDriver extends JDBCDriver {
values: unknown[],
): Promise<R[]> {
if (this.config.catalog) {
const preAggSchemaName = this.getPreAggrSchemaName();
return super.query(
query.replace(
new RegExp(`(?<=\\s)${this.getPreaggsSchemaName()}\\.(?=[^\\s]+)`, 'g'),
`${this.config.catalog}.${this.getPreaggsSchemaName()}.`
new RegExp(`(?<=\\s)${preAggSchemaName}\\.(?=[^\\s]+)`, 'g'),
`${this.config.catalog}.${preAggSchemaName}.`
),
values,
);
Expand All @@ -304,7 +310,7 @@ export class DatabricksDriver extends JDBCDriver {
/**
* Returns pre-aggregation schema name.
*/
public getPreaggsSchemaName(): string {
protected getPreAggrSchemaName(): string {
const schema = getEnv('preAggregationsSchema');
if (schema) {
return schema;
Expand All @@ -327,7 +333,7 @@ export class DatabricksDriver extends JDBCDriver {
return super.dropTable(tableFullName, options);
}

public showDeprecations() {
private showDeprecations() {
if (this.config.url) {
const result = this.config.url
.split(';')
Expand Down Expand Up @@ -387,7 +393,7 @@ export class DatabricksDriver extends JDBCDriver {
/**
* Returns tables meta data object.
*/
public async tablesSchema(): Promise<Record<string, Record<string, object>>> {
public override async tablesSchema(): Promise<Record<string, Record<string, object>>> {
const tables = await this.getTables();

const metadata: Record<string, Record<string, object>> = {};
Expand All @@ -407,7 +413,7 @@ export class DatabricksDriver extends JDBCDriver {
/**
* Returns list of accessible tables.
*/
public async getTables(): Promise<ShowTableRow[]> {
private async getTables(): Promise<ShowTableRow[]> {
if (this.config.database) {
return <any> this.query<ShowTableRow>(
`SHOW TABLES IN ${
Expand Down Expand Up @@ -492,7 +498,7 @@ export class DatabricksDriver extends JDBCDriver {
/**
* Returns table columns types.
*/
public async tableColumnTypes(table: string): Promise<{ name: any; type: string; }[]> {
public override async tableColumnTypes(table: string): Promise<{ name: any; type: string; }[]> {
let tableFullName = '';
const tableArray = table.split('.');

Expand Down Expand Up @@ -567,7 +573,7 @@ export class DatabricksDriver extends JDBCDriver {
/**
* Returns schema full name.
*/
public getSchemaFullName(schema: string): string {
private getSchemaFullName(schema: string): string {
if (this.config?.catalog) {
return `${
this.quoteIdentifier(this.config.catalog)
Expand All @@ -582,14 +588,14 @@ export class DatabricksDriver extends JDBCDriver {
/**
* Returns quoted string.
*/
public quoteIdentifier(identifier: string): string {
protected quoteIdentifier(identifier: string): string {
return `\`${identifier}\``;
}

/**
* Returns the JS type by the Databricks type.
*/
public toGenericType(columnType: string): string {
protected toGenericType(columnType: string): string {
return DatabricksToGenericType[columnType.toLowerCase()] || super.toGenericType(columnType);
}

Expand Down Expand Up @@ -639,7 +645,7 @@ export class DatabricksDriver extends JDBCDriver {
const types = await this.queryColumnTypes(sql, params);

await this.createExternalTableFromSql(tableFullName, sql, params, types);

return types;
}

Expand All @@ -650,7 +656,7 @@ export class DatabricksDriver extends JDBCDriver {
const types = await this.tableColumnTypes(tableFullName);

await this.createExternalTableFromTable(tableFullName, types);

return types;
}

Expand Down
29 changes: 22 additions & 7 deletions packages/cubejs-jdbc-driver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,37 @@ JDBC driver.

## Support

This package is **community supported** and should be used at your own risk.
This package is **community supported** and should be used at your own risk.

While the Cube Dev team is happy to review and accept future community contributions, we don't have active plans for further development. This includes bug fixes unless they affect different parts of Cube.js. **We're looking for maintainers for this package.** If you'd like to become a maintainer, please contact us in Cube.js Slack.
While the Cube Dev team is happy to review and accept future community contributions, we don't have active plans for
further development. This includes bug fixes unless they affect different parts of Cube.js. **We're looking for
maintainers for this package.** If you'd like to become a maintainer, please contact us in Cube.js Slack.

## Java installation

### macOS

```sh
brew install openjdk@8
sudo ln -sfn /usr/local/opt/openjdk@8/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-8.jdk
brew install openjdk
# At the moment of writing, openjdk 22.0.1 is the latest and proven to work on Intel/M1 Mac's
# Follow the brew suggested advice at the end of installation:
# For the system Java wrappers to find this JDK, symlink it with
sudo ln -sfn /usr/local/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk

# Ensure that newly installed jdk is visible
/usr/libexec/java_home -V
# You should see installed jdk among others, something like this:
Matching Java Virtual Machines (3):
22.0.1 (x86_64) "Homebrew" - "OpenJDK 22.0.1" /usr/local/Cellar/openjdk/22.0.1/libexec/openjdk.jdk/Contents/Home
1.8.0_40 (x86_64) "Oracle Corporation" - "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home

# Set JAVA_HOME environment variable before running yarn in the Cube repo
export JAVA_HOME=`/usr/libexec/java_home -v 22.0.1`
```

If this doesn't work, please run commands from `$ brew info openjdk@8`.
**Note:** It's important to set `JAVA_HOME` prior to running `yarn/npm install` in Cube repo as Java Bridge npm package
uses is to locate JAVA and caches it internally. In case you already run package installation you have to rebuild
all native packages or just delete `node_modules` and run `yarn` again.

### Debian, Ubuntu, etc.

Expand All @@ -46,8 +63,6 @@ If you have Chocolatey packet manager:
choco install openjdk
```

Or download it from

## License

Cube.js JDBC Database Driver is [Apache 2.0 licensed](./LICENSE).

0 comments on commit 6d2f97a

Please sign in to comment.