-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
Describe the bug
In a multi-datasource configuration, when a cube uses data_source: 'postgres' (or similar) and the driverFactory correctly returns a PostgresDriver instance, the generated SQL still uses MySQL dialect instead of PostgreSQL. As a result, queries fail with syntax errors when executed against PostgreSQL.
Observed MySQL syntax in generated SQL (sent to Postgres):
- Identifier quoting: Backticks (
`) instead of double quotes (") - Functions:
CONVERT_TZ(),convert_tz(),DATE_FORMAT() - Session:
@@session.time_zone - Types/casts:
TIMESTAMP(),CAST(... AS DATETIME),UNIX_TIMESTAMP()
Expected: The schema-compiler / query generator should use the target data source's dialect (here: PostgreSQL) when building SQL, so that:
- Identifiers are quoted with
"instead of` CONVERT_TZ→(... AT TIME ZONE 'tz') AT TIME ZONE 'tz'DATE_FORMAT→TO_CHAR(..., 'format')@@session.time_zone→'UTC'or equivalentTIMESTAMP()/CAST(... AS DATETIME)/UNIX_TIMESTAMP()→ PostgreSQL equivalents
To Reproduce
Environment:
@cubejs-backend/server-core: 1.6.1 (also checked 1.6.4; issue persists)@cubejs-backend/postgres-driver: 1.6.1@cubejs-backend/mysql-driver: 1.6.1
Configuration (cube.js):
driverFactoryreturns:- MySQLDriver for
dataSource === 'default'(or when notpostgres) - PostgresDriver for
dataSource === 'postgres'(orpostgresDataSource)
- MySQLDriver for
- Cubes with
data_source: 'postgres'exist and usesql_table, measures, dimensions, and time dimensions.
Steps:
- Define a cube with
data_source: 'postgres'and atimedimension (e.g.granularities: ['day', 'month']). - Send a
/cubejs-api/v1/load(or equivalent) query that hits that Postgres cube. - Inspect the SQL passed to
PostgresDriver.query()(e.g. via logging or a patch).
Result: The SQL contains MySQL syntax (backticks, CONVERT_TZ, DATE_FORMAT, @@session.time_zone, TIMESTAMP(), CAST(... AS DATETIME), UNIX_TIMESTAMP()), causing PostgreSQL to reject it.
Workaround
We apply a monkey-patch on PostgresDriver.prototype.query and executeQuery to transform the SQL before execution:
- Replace backtick
`with double quote" - Replace
CONVERT_TZ/convert_tz/@@session.time_zonewith PostgreSQLAT TIME ZONEexpressions - Replace
DATE_FORMATwithTO_CHAR - Replace
TIMESTAMP(),CAST(... AS DATETIME),UNIX_TIMESTAMP()with PostgreSQL equivalents
This works but is fragile and must be reapplied when upgrading; we'd prefer an upstream fix.
Related
- Can't find dialect for 'datasource1' data source: undefined #6890 ("Can't find dialect for 'datasource1' data source: undefined"): different symptom (dialect not resolved at all). Our case: dialect/driver is Postgres, but generated SQL uses MySQL dialect.
- Docs say Cube uses
dbType/ connection to choose identifier quoting and dialect; in our multi-datasource + Postgres setup, the compiler appears to use a default (MySQL) dialect for SQL generation.
Root cause hypothesis
The schema-compiler (or the layer that generates SQL for a query) may:
- Use a single, default dialect (e.g. MySQL) when compiling, regardless of the cube's
data_source, or - Resolve
data_sourcefor the driver but not pass the correct dialect into the SQL generator, so identifier quoting and function translation still follow the default.
We have not confirmed the exact call path; the above is inferred from "PostgresDriver receives MySQL-style SQL."
Additional context
- We use both driverFactory and
data_sourceon cubes; the Postgres driver and connection work; the failure is purely from SQL syntax. - The same cube definition works when the default (and only) data source is Postgres; the problem appears in multi-datasource when the default is MySQL and a non-default data source is Postgres.
References: