diff --git a/docs/pages/product/configuration/data-sources/snowflake.mdx b/docs/pages/product/configuration/data-sources/snowflake.mdx index 32d457ee32068..d27de799c56dd 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 36a4bf4e7c41b..4d4a2e97462a3 100644 --- a/packages/cubejs-backend-shared/src/env.ts +++ b/packages/cubejs-backend-shared/src/env.ts @@ -1529,6 +1529,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 false; + } + }, /** **************************************************************** * Presto Driver * ***************************************************************** */ diff --git a/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts b/packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts index ccf19191fa980..99a682ea31388 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, + identIgnoreCase?: 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 }), + identIgnoreCase: getEnv('snowflakeQuotedIdentIgnoreCase', { dataSource }), exportBucketCsvEscapeSymbol: getEnv('dbExportBucketCsvEscapeSymbol', { dataSource }), application: 'CubeDev_Cube', ...config @@ -451,6 +454,11 @@ 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); + // We only want to ignore the case if someone sets the value to true explicitly + // since the default assumption is that casing matters + if (this.config.identIgnoreCase) { + await this.execute(connection, 'ALTER SESSION SET QUOTED_IDENTIFIERS_IGNORE_CASE = TRUE', [], false); + } return connection; } catch (e) { this.connection = null;