Skip to content

Commit

Permalink
feat: Pluggable dialects support
Browse files Browse the repository at this point in the history
Fixes #590
  • Loading branch information
paveltiunov committed Jul 3, 2020
1 parent b38d1be commit f786fdd
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 11 deletions.
7 changes: 4 additions & 3 deletions packages/cubejs-schema-compiler/adapter/QueryBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@ const ADAPTERS = {
elasticsearch
};
exports.query = (compilers, dbType, queryOptions) => {
if (!ADAPTERS[dbType]) {
if (!queryOptions.dialectClass && !ADAPTERS[dbType]) {
return null;
}

return new (ADAPTERS[dbType])(compilers, {
return new (queryOptions.dialectClass || ADAPTERS[dbType])(compilers, {
...queryOptions,
externalQueryClass: queryOptions.externalDbType && ADAPTERS[queryOptions.externalDbType]
externalQueryClass: queryOptions.externalDialectClass ||
queryOptions.externalDbType && ADAPTERS[queryOptions.externalDbType]
});
};
19 changes: 16 additions & 3 deletions packages/cubejs-server-core/core/CompilerApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class CompilerApi {
constructor(repository, dbType, options) {
this.repository = repository;
this.dbType = dbType;
this.dialectClass = options.dialectClass;
this.options = options || {};
this.allowNodeRequire = options.allowNodeRequire == null ? true : options.allowNodeRequire;
this.logger = this.options.logger;
Expand Down Expand Up @@ -47,12 +48,17 @@ class CompilerApi {
return this.dbType;
}

getDialectClass(dataSource) {
return this.dialectClass && this.dialectClass({ dataSource: dataSource || 'default' });
}

async getSql(query, options) {
options = options || {};
const { includeDebugInfo } = options;
const dbType = this.getDbType('default');
const dialectClass = this.getDialectClass('default');
const compilers = await this.getCompilers({ requestId: query.requestId });
let sqlGenerator = this.createQuery(compilers, dbType, query);
let sqlGenerator = this.createQuery(compilers, dbType, dialectClass, query);
if (!sqlGenerator) {
throw new Error(`Unknown dbType: ${dbType}`);
}
Expand All @@ -61,7 +67,12 @@ class CompilerApi {

if (dataSource !== 'default' && dbType !== this.getDbType(dataSource)) {
// TODO consider more efficient way than instantiating query
sqlGenerator = this.createQuery(compilers, this.getDbType(dataSource), query);
sqlGenerator = this.createQuery(
compilers,
this.getDbType(dataSource),
this.getDialectClass(dataSource),
query
);
}

return compilers.compiler.withQuery(sqlGenerator, () => ({
Expand All @@ -85,11 +96,13 @@ class CompilerApi {
return cubeEvaluator.scheduledPreAggregations();
}

createQuery(compilers, dbType, query) {
createQuery(compilers, dbType, dialectClass, query) {
return QueryBuilder.query(
compilers,
dbType, {
...query,
dialectClass,
externalDialectClass: this.options.externalDialectClass,
externalDbType: this.options.externalDbType,
preAggregationsSchema: this.preAggregationsSchema,
allowUngroupedWithoutPrimaryKey: this.allowUngroupedWithoutPrimaryKey
Expand Down
25 changes: 20 additions & 5 deletions packages/cubejs-server-core/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ class CubejsServerCore {
options = options || {};
options = {
driverFactory: () => CubejsServerCore.createDriver(options.dbType),
dialectFactory: () => CubejsServerCore.lookupDriverClass(options.dbType).dialectClass &&
CubejsServerCore.lookupDriverClass(options.dbType).dialectClass(),
apiSecret: process.env.CUBEJS_API_SECRET,
dbType: process.env.CUBEJS_DB_TYPE,
devServer: process.env.NODE_ENV !== 'production',
Expand All @@ -188,6 +190,8 @@ class CubejsServerCore {
this.options = options;
this.driverFactory = options.driverFactory;
this.externalDriverFactory = options.externalDriverFactory;
this.dialectFactory = options.dialectFactory;
this.externalDialectFactory = options.externalDialectFactory;
this.apiSecret = options.apiSecret;
this.schemaPath = options.schemaPath || process.env.CUBEJS_SCHEMA_PATH || 'schema';
this.dbType = options.dbType;
Expand Down Expand Up @@ -419,6 +423,9 @@ class CubejsServerCore {
this.repositoryFactory(context), {
dbType: (dataSourceContext) => this.contextToDbType({ ...context, ...dataSourceContext }),
externalDbType: this.contextToExternalDbType(context),
dialectClass: (dataSourceContext) => this.dialectFactory &&
this.dialectFactory({ ...context, ...dataSourceContext }),
externalDialectClass: this.externalDialectFactory && this.externalDialectFactory(context),
schemaVersion: currentSchemaVersion,
preAggregationsSchema: this.preAggregationsSchema(context),
context
Expand Down Expand Up @@ -477,7 +484,9 @@ class CubejsServerCore {
externalDbType: options.externalDbType,
preAggregationsSchema: options.preAggregationsSchema,
allowUngroupedWithoutPrimaryKey: this.options.allowUngroupedWithoutPrimaryKey,
compileContext: options.context
compileContext: options.context,
dialectClass: options.dialectClass,
externalDialectClass: options.externalDialectClass,
});
}

Expand Down Expand Up @@ -506,15 +515,21 @@ class CubejsServerCore {

static createDriver(dbType) {
checkEnvForPlaceholders();
return new (CubejsServerCore.lookupDriverClass(dbType))();
}

static lookupDriverClass(dbType) {
// eslint-disable-next-line global-require,import/no-dynamic-require
return new (require(CubejsServerCore.driverDependencies(dbType || process.env.CUBEJS_DB_TYPE)))();
return require(CubejsServerCore.driverDependencies(dbType || process.env.CUBEJS_DB_TYPE));
}

static driverDependencies(dbType) {
if (!DriverDependencies[dbType]) {
throw new Error(`Unsupported db type: ${dbType}`);
if (DriverDependencies[dbType]) {
return DriverDependencies[dbType];
} else if (fs.existsSync(path.join('node_modules', `${dbType}-cubejs-driver`))) {
return `${dbType}-cubejs-driver`;
}
return DriverDependencies[dbType];
throw new Error(`Unsupported db type: ${dbType}`);
}

testConnections() {
Expand Down

0 comments on commit f786fdd

Please sign in to comment.