From 82703ecb293a4e5ffb1e4410f8a2d25a158fadc0 Mon Sep 17 00:00:00 2001 From: Micheal Taylor Date: Fri, 1 Nov 2024 11:39:59 -0600 Subject: [PATCH 1/3] Fixing case statements in snowflake driver --- packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts b/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts index ccf19191fa980..91834f85ee0ea 100644 --- a/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts +++ b/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts @@ -450,6 +450,7 @@ export class SnowflakeDriver extends BaseDriver implements DriverInterface { await this.execute(connection, 'ALTER SESSION SET TIMEZONE = \'UTC\'', [], false); await this.execute(connection, `ALTER SESSION SET STATEMENT_TIMEOUT_IN_SECONDS = ${this.config.executionTimeout}`, [], false); + await this.execute(connection, 'ALTER SESSION SET QUOTED_IDENTIFIRS_IGNORE_CASE = FALSE', [], false); return connection; } catch (e) { From d0bcf1590c1f8679dda04ae983f136b104e198a6 Mon Sep 17 00:00:00 2001 From: Micheal Taylor Date: Wed, 11 Dec 2024 11:20:27 -0700 Subject: [PATCH 2/3] Fixes case sensitivity for snowflake to be default and env driven Adds env var for the snowflake driver to enable or disable the case sensitivity and if not set will default to case insensitive --- .../configuration/data-sources/snowflake.mdx | 6 ++++ packages/cubejs-backend-shared/src/env.ts | 33 +++++++++++++++++++ .../src/SnowflakeDriver.ts | 8 +++-- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/docs/pages/product/configuration/data-sources/snowflake.mdx b/docs/pages/product/configuration/data-sources/snowflake.mdx index 47c716af545d5..d0156397ccb36 100644 --- a/docs/pages/product/configuration/data-sources/snowflake.mdx +++ b/docs/pages/product/configuration/data-sources/snowflake.mdx @@ -12,6 +12,12 @@ redirect_from: - [The region][snowflake-docs-regions] for the [Snowflake][snowflake] warehouse - The username/password for the [Snowflake][snowflake] account +## Snowflake quoted identifiers + +Due to an issue in snowflakes opinion about quoted identifers we set a session value to override +snowflake defaults for users that have set an account value for: QUOTED_IDENTIFIERS_IGNORE_CASE +you can learn more about this here: https://docs.snowflake.com/en/sql-reference/identifiers-syntax#double-quoted-identifiers + ## Setup diff --git a/packages/cubejs-backend-shared/src/env.ts b/packages/cubejs-backend-shared/src/env.ts index a8f5563555bb9..3755afa0b4926 100644 --- a/packages/cubejs-backend-shared/src/env.ts +++ b/packages/cubejs-backend-shared/src/env.ts @@ -1478,6 +1478,39 @@ const variables: Record any> = { ] ), + /** + * Snowflake case sensitivity for identifiers (like database columns). + */ + snowflakeQuotedIdentIgnoreCase: ({ + dataSource + }: { + dataSource: string, + }) => { + const val = process.env[ + keyByDataSource( + 'CUBEJS_DB_SNOWFLAKE_QUOTED_IDENTIFIERS_IGNORE_CASE', + dataSource, + ) + ]; + if (val) { + if (val.toLocaleLowerCase() === 'true') { + return true; + } else if (val.toLowerCase() === 'false') { + return false; + } else { + throw new TypeError( + `The ${ + keyByDataSource( + 'CUBEJS_DB_SNOWFLAKE_QUOTED_IDENTIFIERS_IGNORE_CASE', + dataSource, + ) + } must be either 'true' or 'false'.` + ); + } + } else { + return true; + } + }, /** **************************************************************** * Presto Driver * ***************************************************************** */ diff --git a/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts b/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts index 91834f85ee0ea..66284e8767b03 100644 --- a/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts +++ b/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts @@ -173,6 +173,7 @@ interface SnowflakeDriverOptions { resultPrefetch?: number, exportBucket?: SnowflakeDriverExportBucket, executionTimeout?: number, + caseSensitiveIdentifiers?: boolean, application: string, readOnly?: boolean, @@ -213,6 +214,7 @@ export class SnowflakeDriver extends BaseDriver implements DriverInterface { 'CUBEJS_DB_SNOWFLAKE_PRIVATE_KEY_PATH', 'CUBEJS_DB_SNOWFLAKE_PRIVATE_KEY_PASS', 'CUBEJS_DB_SNOWFLAKE_OAUTH_TOKEN_PATH', + 'CUBEJS_DB_SNOWFLAKE_QUOTED_IDENTIFIERS_IGNORE_CASE', ]; } @@ -279,6 +281,7 @@ export class SnowflakeDriver extends BaseDriver implements DriverInterface { exportBucket: this.getExportBucket(dataSource), resultPrefetch: 1, executionTimeout: getEnv('dbQueryTimeout', { dataSource }), + ignoreCase: getEnv('snowflakeQuotedIdentIgnoreCase', { dataSource }), exportBucketCsvEscapeSymbol: getEnv('dbExportBucketCsvEscapeSymbol', { dataSource }), application: 'CubeDev_Cube', ...config @@ -450,8 +453,9 @@ export class SnowflakeDriver extends BaseDriver implements DriverInterface { await this.execute(connection, 'ALTER SESSION SET TIMEZONE = \'UTC\'', [], false); await this.execute(connection, `ALTER SESSION SET STATEMENT_TIMEOUT_IN_SECONDS = ${this.config.executionTimeout}`, [], false); - await this.execute(connection, 'ALTER SESSION SET QUOTED_IDENTIFIRS_IGNORE_CASE = FALSE', [], false); - + if (this.ignoreCase) { + await this.execute(connection, 'ALTER SESSION SET QUOTED_IDENTIFIERS_IGNORE_CASE = FALSE', [], false); + } return connection; } catch (e) { this.connection = null; From 29bc2fc28f0246048d240335475a5a849fefc82e Mon Sep 17 00:00:00 2001 From: Micheal Taylor Date: Tue, 7 Jan 2025 14:29:12 -0700 Subject: [PATCH 3/3] Updating snowflake driver to respect case by default with added override. --- packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts b/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts index 66284e8767b03..c362028934530 100644 --- a/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts +++ b/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts @@ -453,7 +453,10 @@ export class SnowflakeDriver extends BaseDriver implements DriverInterface { await this.execute(connection, 'ALTER SESSION SET TIMEZONE = \'UTC\'', [], false); await this.execute(connection, `ALTER SESSION SET STATEMENT_TIMEOUT_IN_SECONDS = ${this.config.executionTimeout}`, [], false); - if (this.ignoreCase) { + + // We only want to ignore the case if someone sets the value to false explicitly since the default assumption + // is that casing matters + if (!this.ignoreCase) { await this.execute(connection, 'ALTER SESSION SET QUOTED_IDENTIFIERS_IGNORE_CASE = FALSE', [], false); } return connection;