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
1 change: 1 addition & 0 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ jobs:
yarn run smoke:questdb
yarn run smoke:multidb
yarn run smoke:lambda
yarn run smoke:prestodb

docker-image-latest-set-tag:
# At least git should be completed pushed up until this moment
Expand Down
5 changes: 4 additions & 1 deletion packages/cubejs-prestodb-driver/driver/PrestoDriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ class PrestoDriver extends BaseDriver {
}

query(query, values) {
const queryWithParams = SqlString.format(query, values);
const queryWithParams = SqlString.format(query, (values || []).map(value => (typeof s === 'string' ? {
toSqlString: () => SqlString.escape(value).replace(/\\\\([_%])/g, '\\$1')
} : value)));

return this.queryPromised(queryWithParams);
}

Expand Down
1 change: 1 addition & 0 deletions packages/cubejs-testing-shared/src/db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './cubestore';
export * from './questdb';
export * from './materialize';
export * from './crate';
export * from './prestodb';
27 changes: 27 additions & 0 deletions packages/cubejs-testing-shared/src/db/prestodb.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { GenericContainer, Wait } from 'testcontainers';

import { DbRunnerAbstract, DBRunnerContainerOptions } from './db-runner.abstract';

type PrestoStartOptions = DBRunnerContainerOptions & {
version?: string,
};

export class PrestoDbRunner extends DbRunnerAbstract {
public static startContainer(options: PrestoStartOptions) {
const version = process.env.TEST_PRESTO_VERSION || options.version || '0.277';

const container = new GenericContainer(`ahanaio/prestodb-sandbox:${version}`)
.withExposedPorts(8080)
.withWaitStrategy(Wait.forLogMessage("======== SERVER STARTED ========"))
.withStartupTimeout(30 * 1000);

if (options.volumes) {
// eslint-disable-next-line no-restricted-syntax
for (const { source, target, bindMode } of options.volumes) {
container.withBindMount(source, target, bindMode);
}
}

return container.start();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
cube('Orders', {
sql: `
select 1 as id, 100 as amount, 'new' status
UNION ALL
select 2 as id, 200 as amount, 'new' status
UNION ALL
select 3 as id, 300 as amount, 'processed' status
UNION ALL
select 4 as id, 500 as amount, 'processed' status
UNION ALL
select 5 as id, 600 as amount, 'shipped' status
UNION ALL
select 6 as id, 700 as amount, 'cancelled_by_customer' status
`,
measures: {
count: {
type: 'count',
},
totalAmount: {
sql: 'amount',
type: 'sum',
},
},
dimensions: {
status: {
sql: 'status',
type: 'string',
},
},
preAggregations: {
orderStatus: {
measures: [CUBE.count, CUBE.totalAmount],
dimensions: [CUBE.status],
refreshKey: {
every: '1 second',
}
},
},
});
22 changes: 22 additions & 0 deletions packages/cubejs-testing/birdbox-fixtures/prestodb.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: "2.2"

services:
cube:
container_name: birdbox-cube
image: ${BIRDBOX_CUBEJS_REGISTRY_PATH}cubejs/cube:${BIRDBOX_CUBEJS_VERSION:-latest}
environment:
CUBEJS_DB_TYPE: prestodb

CUBEJS_DB_HOST: host.docker.internal
CUBEJS_DB_PORT: ${CUBEJS_DB_PORT:-8080}
CUBEJS_DB_PRESTO_CATALOG: ${CUBEJS_DB_NAME:-memory}
CUBEJS_DB_USER: ${CUBEJS_DB_USER:-presto}

CUBEJS_DEV_MODE: "true"
CUBEJS_WEB_SOCKETS: "true"
CUBEJS_API_SECRET: mysupersecret
volumes:
- ./prestodb/schema:/cube/conf/schema
ports:
- "4000"
restart: always
4 changes: 3 additions & 1 deletion packages/cubejs-testing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@
"smoke:redshift": "jest --verbose -i dist/test/smoke-redshift.test.js",
"smoke:redshift:snapshot": "jest --verbose --updateSnapshot -i dist/test/smoke-redshift.test.js",
"smoke:cubesql": "jest --verbose --forceExit -i dist/test/smoke-cubesql.test.js",
"smoke:cubesql:snapshot": "jest --verbose --forceExit --updateSnapshot -i dist/test/smoke-cubesql.test.js"
"smoke:cubesql:snapshot": "jest --verbose --forceExit --updateSnapshot -i dist/test/smoke-cubesql.test.js",
"smoke:prestodb": "jest --verbose -i dist/test/smoke-prestodb.test.js",
"smoke:prestodb:snapshot": "jest --verbose --forceExit --updateSnapshot -i dist/test/smoke-prestodb.test.js"
},
"files": [
"dist/src",
Expand Down
1 change: 1 addition & 0 deletions packages/cubejs-testing/src/REQUIRED_ENV_VARS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ export const REQUIRED_ENV_VARS: {[key: string]: string[]} = {
'CUBEJS_DB_EXPORT_BUCKET_AWS_SECRET',
'CUBEJS_DB_EXPORT_BUCKET_AWS_REGION',
],
prestodb: []
};
5 changes: 3 additions & 2 deletions packages/cubejs-testing/src/birdbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ interface Args {
log: Log,
}

export type DriverType = 'postgresql' | 'postgres' | 'multidb' | 'materialize' | 'crate' | 'bigquery' | 'athena' | 'postgresql-cubestore' | 'firebolt' | 'questdb' | 'redshift' | 'databricks-jdbc';
export type DriverType = 'postgresql' | 'postgres' | 'multidb' | 'materialize' | 'crate' | 'bigquery' | 'athena' | 'postgresql-cubestore' | 'firebolt' | 'questdb' | 'redshift' | 'databricks-jdbc' | 'prestodb';

export type Schemas = string[];

Expand Down Expand Up @@ -102,7 +102,8 @@ const driverNameToFolderNameMapper: Record<DriverType, string> = {
firebolt: 'postgresql',
questdb: 'postgresql',
redshift: 'postgresql',
'databricks-jdbc': 'databricks-jdbc'
'databricks-jdbc': 'databricks-jdbc',
prestodb: 'postgresql'
};

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

exports[`prestodb query dimensions with underscore filter: dimensions 1`] = `
Array [
Object {
"Orders.status": "cancelled_by_customer",
},
]
`;

exports[`prestodb query dimensions: dimensions 1`] = `
Array [
Object {
"Orders.status": "processed",
"Orders.totalAmount": "800",
},
Object {
"Orders.status": "cancelled_by_customer",
"Orders.totalAmount": "700",
},
Object {
"Orders.status": "shipped",
"Orders.totalAmount": "600",
},
Object {
"Orders.status": "new",
"Orders.totalAmount": "300",
},
]
`;

exports[`prestodb query measure: query 1`] = `
Array [
Object {
"Orders.totalAmount": "2400",
},
]
`;
71 changes: 71 additions & 0 deletions packages/cubejs-testing/test/smoke-prestodb.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import cubejs, { CubejsApi } from '@cubejs-client/core';
// eslint-disable-next-line import/no-extraneous-dependencies
import { afterAll, beforeAll, expect, jest } from '@jest/globals';
import { PrestoDbRunner } from '@cubejs-backend/testing-shared';
import { BirdBox, getBirdbox } from '../src';
import { DEFAULT_CONFIG, testQueryMeasure } from './smoke-tests';

describe('prestodb', () => {
jest.setTimeout(60 * 5 * 1000);
let birdbox: BirdBox;
let client: CubejsApi;

beforeAll(async () => {
const db = await PrestoDbRunner.startContainer({});
birdbox = await getBirdbox(
'prestodb',
{
CUBEJS_DB_TYPE: 'prestodb',

CUBEJS_DB_HOST: db.getHost(),
CUBEJS_DB_PORT: `${db.getMappedPort(8080)}`,
CUBEJS_DB_PRESTO_CATALOG: 'memory',
CUBEJS_DB_USER: 'test',

...DEFAULT_CONFIG,
},
{
schemaDir: 'presto/schema',
}
);
client = cubejs(async () => 'test', {
apiUrl: birdbox.configuration.apiUrl,
});
});

afterAll(async () => {
await birdbox.stop();
});

test('query measure', () => testQueryMeasure(client));

test('query dimensions', async () => {
const response = await client.load({
measures: [
'Orders.totalAmount',
],
dimensions: [
'Orders.status',
],
});

expect(response.rawData()).toMatchSnapshot('dimensions');
});

test('query dimensions with underscore filter', async () => {
const response = await client.load({
filters: [
{
member: 'Orders.status',
operator: 'contains',
values: ['cancelled_']
}
],
dimensions: [
'Orders.status',
],
});

expect(response.rawData()).toMatchSnapshot('dimensions');
});
});