Skip to content

Commit ff1af78

Browse files
jay-choea1tair6p-eyeovr
authored
fix(oracle-driver): Release connection after query execution (#5469)
Co-authored-by: a1tair6 <[email protected]> Co-authored-by: p-eye <[email protected]> Co-authored-by: Dmitry Patsura <[email protected]>
1 parent 42af89a commit ff1af78

File tree

10 files changed

+133
-11
lines changed

10 files changed

+133
-11
lines changed

.github/workflows/push.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@ jobs:
479479
retry_wait_seconds: 15
480480
timeout_minutes: 20
481481
command: yarn install --frozen-lockfile
482+
- name: Install instant client for Oracle
483+
uses: GoodManWEN/oracle-client-action@main
482484
- name: Build client
483485
run: yarn build
484486
- name: Lerna tsc

packages/cubejs-oracle-driver/driver/OracleDriver.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class OracleDriver extends BaseDriver {
6969
this.db.partRows = 100000;
7070
this.db.maxRows = 100000;
7171
this.db.prefetchRows = 500;
72-
this.config = config || {
72+
this.config = {
7373
user: getEnv('dbUser', { dataSource }),
7474
password: getEnv('dbPass', { dataSource }),
7575
db: getEnv('dbName', { dataSource }),
@@ -80,11 +80,9 @@ class OracleDriver extends BaseDriver {
8080
config.maxPoolSize ||
8181
getEnv('dbMaxPoolSize', { dataSource }) ||
8282
50,
83+
...config
8384
};
84-
85-
if (!this.config.connectionString) {
86-
this.config.connectionString = `${this.config.host}/${this.config.db}`
87-
}
85+
this.config.connectionString = this.config.connectionString || `${this.config.host}:${this.config.port}/${this.config.db}`;
8886
}
8987

9088
async tablesSchema() {
@@ -113,22 +111,28 @@ class OracleDriver extends BaseDriver {
113111
if (!this.pool) {
114112
this.pool = await this.db.createPool(this.config);
115113
}
114+
116115
return this.pool.getConnection()
117116
}
118117

119118
async testConnection() {
120-
return (
121-
await this.getConnectionFromPool()
122-
).execute('SELECT 1 FROM DUAL');
119+
await this.query('SELECT 1 FROM DUAL', {});
123120
}
124121

125122
async query(query, values) {
126123
const conn = await this.getConnectionFromPool();
124+
127125
try {
128126
const res = await conn.execute(query, values || {});
129127
return res && res.rows;
130128
} catch (e) {
131129
throw (e);
130+
} finally {
131+
try {
132+
await conn.close();
133+
} catch (e) {
134+
throw e;
135+
}
132136
}
133137
}
134138

packages/cubejs-testing-shared/src/db/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ export * from './crate';
77
export * from './prestodb';
88
export * from './mssql';
99
export * from './trino';
10+
export * from './oracle';
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { GenericContainer } from 'testcontainers';
2+
import { DbRunnerAbstract, DBRunnerContainerOptions } from './db-runner.abstract';
3+
4+
type OracleStartOptions = DBRunnerContainerOptions & {
5+
version?: string,
6+
};
7+
8+
export class OracleDBRunner extends DbRunnerAbstract {
9+
public static startContainer(options: OracleStartOptions) {
10+
const version = process.env.TEST_ORACLE_VERSION || options.version || '21.3.0';
11+
12+
const container = new GenericContainer(`gvenzl/oracle-xe:${version}`)
13+
.withEnv('ORACLE_PASSWORD', 'test')
14+
.withExposedPorts(1521)
15+
.withStartupTimeout(30 * 1000);
16+
17+
if (options.volumes) {
18+
// eslint-disable-next-line no-restricted-syntax
19+
for (const { source, target, bindMode } of options.volumes) {
20+
container.withBindMount(source, target, bindMode);
21+
}
22+
}
23+
24+
return container.start();
25+
}
26+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
cube('Orders', {
2+
sql: `
3+
select 1 as id, 100 as amount, 'new' status from dual
4+
UNION ALL
5+
select 2 as id, 200 as amount, 'new' status from dual
6+
UNION ALL
7+
select 3 as id, 300 as amount, 'processed' status from dual
8+
UNION ALL
9+
select 4 as id, 500 as amount, 'processed' status from dual
10+
UNION ALL
11+
select 5 as id, 600 as amount, 'shipped' status from dual
12+
`,
13+
measures: {
14+
totalAmount: {
15+
sql: 'amount',
16+
type: 'sum',
17+
},
18+
},
19+
dimensions: {
20+
id: {
21+
sql: 'id',
22+
type: 'number'
23+
},
24+
25+
status: {
26+
sql: 'status',
27+
type: 'string',
28+
},
29+
}
30+
});

packages/cubejs-testing/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
"driver:databricks:snap": "jest --verbose --updateSnapshot -i dist/test/driver-databricks.test.js",
4949
"integration:cubestore": "jest --verbose --updateSnapshot -i dist/test/driver-cubestore.test.js",
5050
"rest:postgres": "yarn tsc && clear && jest --verbose -i dist/test/rest-postgres.test.js",
51-
"smoke": "jest --verbose -i 'dist/test/smoke-(?!.*?(redshift|bigquery|firebolt|cubesql))'",
51+
"smoke": "jest --verbose -i 'dist/test/smoke-(?!.*?(redshift|athena|bigquery|firebolt|cubesql|oracle))'",
5252
"smoke:athena": "jest --verbose -i dist/test/smoke-athena.test.js",
5353
"smoke:athena:snapshot": "jest --verbose --updateSnapshot -i dist/test/smoke-athena.test.js",
5454
"smoke:bigquery": "jest --verbose -i dist/test/smoke-bigquery.test.js",
@@ -61,6 +61,8 @@
6161
"smoke:lambda:snapshot": "jest --updateSnapshot --verbose -i dist/test/smoke-lambda.test.js",
6262
"smoke:materialize": "jest --verbose -i dist/test/smoke-materialize.test.js",
6363
"smoke:materialize:snapshot": "jest --verbose --updateSnapshot -i dist/test/smoke-materialize.test.js",
64+
"smoke:oracle": "jest --verbose -i dist/test/smoke-oracle.test.js",
65+
"smoke:oracle:snapshot": "jest --verbose --updateSnapshot -i dist/test/smoke-oracle.test.js",
6466
"smoke:questdb": "jest --verbose -i dist/test/smoke-questdb.test.js",
6567
"smoke:questdb:snapshot": "jest --verbose --updateSnapshot -i dist/test/smoke-questdb.test.js",
6668
"smoke:multidb": "jest --verbose -i dist/test/smoke-multidb.test.js",

packages/cubejs-testing/src/REQUIRED_ENV_VARS.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export const REQUIRED_ENV_VARS: {[key: string]: string[]} = {
2424
],
2525
materialize: [],
2626
multidb: [],
27+
oracle: [],
2728
questdb: [],
2829
postgres: [],
2930
redshift: [

packages/cubejs-testing/src/birdbox.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ interface Args {
4848
log: Log,
4949
}
5050

51-
export type DriverType = 'postgresql' | 'postgres' | 'multidb' | 'materialize' | 'crate' | 'bigquery' | 'athena' | 'postgresql-cubestore' | 'firebolt' | 'questdb' | 'redshift' | 'databricks-jdbc' | 'prestodb' | 'mssql' | 'trino';
51+
export type DriverType = 'postgresql' | 'postgres' | 'multidb' | 'materialize' | 'crate' | 'bigquery' | 'athena' | 'postgresql-cubestore' | 'firebolt' | 'questdb' | 'redshift' | 'databricks-jdbc' | 'prestodb' | 'mssql' | 'trino' | 'oracle';
5252

5353
export type Schemas = string[];
5454

@@ -105,7 +105,8 @@ const driverNameToFolderNameMapper: Record<DriverType, string> = {
105105
'databricks-jdbc': 'databricks-jdbc',
106106
prestodb: 'postgresql',
107107
mssql: 'mssql',
108-
trino: 'postgresql'
108+
trino: 'postgresql',
109+
oracle: 'oracle'
109110
};
110111

111112
/**
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`oracle query measure: query 1`] = `
4+
Array [
5+
Object {
6+
"Orders.totalAmount": 1700,
7+
},
8+
]
9+
`;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { StartedTestContainer } from 'testcontainers';
2+
import { OracleDBRunner } from '@cubejs-backend/testing-shared';
3+
import cubejs, { CubejsApi } from '@cubejs-client/core';
4+
// eslint-disable-next-line import/no-extraneous-dependencies
5+
import { afterAll, beforeAll, expect, jest } from '@jest/globals';
6+
import { pausePromise } from '@cubejs-backend/shared';
7+
import { BirdBox, getBirdbox } from '../src';
8+
import { DEFAULT_CONFIG, testQueryMeasure } from './smoke-tests';
9+
10+
describe('oracle', () => {
11+
jest.setTimeout(60 * 5 * 100000);
12+
let db: StartedTestContainer;
13+
let birdbox: BirdBox;
14+
let client: CubejsApi;
15+
16+
beforeAll(async () => {
17+
db = await OracleDBRunner.startContainer({});
18+
birdbox = await getBirdbox(
19+
'oracle',
20+
{
21+
CUBEJS_DB_TYPE: 'oracle',
22+
23+
CUBEJS_DB_HOST: db.getHost(),
24+
CUBEJS_DB_PORT: `${db.getMappedPort(1521)}`,
25+
CUBEJS_DB_NAME: 'XE',
26+
CUBEJS_DB_USER: 'system',
27+
CUBEJS_DB_PASS: 'test',
28+
29+
...DEFAULT_CONFIG,
30+
},
31+
{
32+
schemaDir: 'oracle/schema',
33+
}
34+
);
35+
client = cubejs(async () => 'test', {
36+
apiUrl: birdbox.configuration.apiUrl,
37+
});
38+
});
39+
40+
afterAll(async () => {
41+
await birdbox.stop();
42+
await db.stop();
43+
});
44+
45+
test('query measure', () => testQueryMeasure(client));
46+
});

0 commit comments

Comments
 (0)