Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 18 additions & 11 deletions packages/cubejs-server-core/src/core/CompilerApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,19 +137,26 @@ export class CompilerApi {
throw new Error(`Unknown dbType: ${dbType}`);
}

// sqlGenerator.dataSource can return undefined for query without members
// Queries like this are used by api-gateway to initialize SQL API
// At the same time, those queries should use concrete dataSource, so we should be good to go with it
dataSource = compilers.compiler.withQuery(sqlGenerator, () => sqlGenerator.dataSource);
const _dbType = await this.getDbType(dataSource);
if (dataSource !== 'default' && dbType !== _dbType) {
// TODO consider more efficient way than instantiating query
sqlGenerator = await this.createQueryByDataSource(
compilers,
query,
dataSource,
_dbType
);
if (dataSource !== undefined) {
const _dbType = await this.getDbType(dataSource);
if (dataSource !== 'default' && dbType !== _dbType) {
// TODO consider more efficient way than instantiating query
sqlGenerator = await this.createQueryByDataSource(
compilers,
query,
dataSource,
_dbType
);

if (!sqlGenerator) {
throw new Error(`Can't find dialect for '${dataSource}' data source: ${_dbType}`);
if (!sqlGenerator) {
throw new Error(
`Can't find dialect for '${dataSource}' data source: ${_dbType}`
);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`multidb SQL pushdown queries to different data sources: Products 1`] = `
Array [
Object {
"name": "apples",
},
]
`;

exports[`multidb SQL pushdown queries to different data sources: Suppliers 1`] = `
Array [
Object {
"company": "Fruits Inc",
},
]
`;

exports[`multidb query: query 1`] = `
Array [
Object {
Expand Down
64 changes: 64 additions & 0 deletions packages/cubejs-testing/test/smoke-multidb.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { MysqlDBRunner, PostgresDBRunner } from '@cubejs-backend/testing-shared'
import cubejs, { CubeApi } from '@cubejs-client/core';
// eslint-disable-next-line import/no-extraneous-dependencies
import { afterAll, beforeAll, expect, jest } from '@jest/globals';
import { Client as PgClient } from 'pg';
import { BirdBox, getBirdbox } from '../src';
import {
DEFAULT_API_TOKEN,
Expand All @@ -11,12 +12,43 @@ import {
JEST_BEFORE_ALL_DEFAULT_TIMEOUT,
} from './smoke-tests';

// TODO: Random port?
const pgPort = 5656;
let connectionId = 0;

async function createPostgresClient(user: string, password: string) {
connectionId++;
const currentConnId = connectionId;

console.debug(`[pg] new connection ${currentConnId}`);

const conn = new PgClient({
database: 'db',
port: pgPort,
host: '127.0.0.1',
user,
password,
ssl: false,
});
conn.on('error', (err) => {
console.log(err);
});
conn.on('end', () => {
console.debug(`[pg] end ${currentConnId}`);
});

await conn.connect();

return conn;
}

describe('multidb', () => {
jest.setTimeout(60 * 5 * 1000);
let db: StartedTestContainer;
let db2: StartedTestContainer;
let birdbox: BirdBox;
let client: CubeApi;
let connection: PgClient;

beforeAll(async () => {
db = await PostgresDBRunner.startContainer({});
Expand All @@ -39,6 +71,9 @@ describe('multidb', () => {
CUBEJS_DB_USER2: 'root',
CUBEJS_DB_PASS2: 'Test1test',

CUBEJS_PG_SQL_PORT: `${pgPort}`,
CUBESQL_SQL_PUSH_DOWN: 'true',

...DEFAULT_CONFIG,
},
{
Expand All @@ -49,6 +84,7 @@ describe('multidb', () => {
client = cubejs(async () => DEFAULT_API_TOKEN, {
apiUrl: birdbox.configuration.apiUrl,
});
connection = await createPostgresClient('admin', 'admin_password');
}, JEST_BEFORE_ALL_DEFAULT_TIMEOUT);

afterAll(async () => {
Expand All @@ -69,4 +105,32 @@ describe('multidb', () => {
});
expect(response.rawData()).toMatchSnapshot('query');
});

test('SQL pushdown queries to different data sources: Products', async () => {
const res = await connection.query(`
SELECT
name
FROM
Products
WHERE
LOWER(name) = 'apples'
GROUP BY
1
`);
expect(res.rows).toMatchSnapshot();
});

test('SQL pushdown queries to different data sources: Suppliers', async () => {
const res = await connection.query(`
SELECT
company
FROM
Suppliers
WHERE
LOWER(company) = 'fruits inc'
GROUP BY
1
`);
expect(res.rows).toMatchSnapshot();
});
});
Loading