@cubejs-backend/dremio-driver 1.6.68 → 1.6.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/driver/DremioDriver.js +4 -8
- package/package.json +9 -9
- package/test/unit/params-escaping.test.ts +88 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.6.70](https://github.com/cube-js/cube/compare/v1.6.69...v1.6.70) (2026-07-28)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **pinot/dremio/ksql/databriks/hive/jdbc-driver:** Сorrect SQL parameter escaping ([#11374](https://github.com/cube-js/cube/issues/11374)) ([e77c444](https://github.com/cube-js/cube/commit/e77c44471a720d31b29c7741a8a6040ec5836739))
|
|
11
|
+
|
|
12
|
+
## [1.6.69](https://github.com/cube-js/cube/compare/v1.6.68...v1.6.69) (2026-07-10)
|
|
13
|
+
|
|
14
|
+
**Note:** Version bump only for package @cubejs-backend/dremio-driver
|
|
15
|
+
|
|
6
16
|
## [1.6.68](https://github.com/cube-js/cube/compare/v1.6.67...v1.6.68) (2026-07-07)
|
|
7
17
|
|
|
8
18
|
**Note:** Version bump only for package @cubejs-backend/dremio-driver
|
package/driver/DremioDriver.js
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
const {
|
|
8
8
|
getEnv,
|
|
9
9
|
assertDataSource,
|
|
10
|
+
formatAnsi,
|
|
10
11
|
pausePromise,
|
|
11
12
|
} = require('@cubejs-backend/shared');
|
|
12
13
|
const axios = require('axios');
|
|
13
|
-
const SqlString = require('sqlstring');
|
|
14
14
|
const { BaseDriver } = require('@cubejs-backend/base-driver');
|
|
15
15
|
const DremioQuery = require('./DremioQuery');
|
|
16
16
|
|
|
@@ -18,7 +18,7 @@ const DremioQuery = require('./DremioQuery');
|
|
|
18
18
|
// @see https://docs.dremio.com/rest-api/jobs/get-job.html
|
|
19
19
|
const DREMIO_JOB_LIMIT = 500;
|
|
20
20
|
|
|
21
|
-
const applyParams = (query, params) =>
|
|
21
|
+
const applyParams = (query, params) => formatAnsi(query, params);
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Dremio driver class.
|
|
@@ -208,12 +208,7 @@ class DremioDriver extends BaseDriver {
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
async query(query, values) {
|
|
211
|
-
const queryString = applyParams(
|
|
212
|
-
query,
|
|
213
|
-
(values || []).map(s => (typeof s === 'string' ? {
|
|
214
|
-
toSqlString: () => SqlString.escape(s).replace(/\\\\([_%])/g, '\\$1').replace(/\\'/g, '\'\'')
|
|
215
|
-
} : s))
|
|
216
|
-
);
|
|
211
|
+
const queryString = applyParams(query, values || []);
|
|
217
212
|
|
|
218
213
|
await this.getToken();
|
|
219
214
|
const jobId = await this.executeQuery(queryString);
|
|
@@ -281,3 +276,4 @@ class DremioDriver extends BaseDriver {
|
|
|
281
276
|
}
|
|
282
277
|
|
|
283
278
|
module.exports = DremioDriver;
|
|
279
|
+
module.exports.applyParams = applyParams;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@cubejs-backend/dremio-driver",
|
|
3
3
|
"description": "Cube.js Dremio driver",
|
|
4
4
|
"author": "Cube Dev, Inc.",
|
|
5
|
-
"version": "1.6.
|
|
5
|
+
"version": "1.6.70",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/cube-js/cube.git",
|
|
@@ -16,21 +16,21 @@
|
|
|
16
16
|
"tsc": "tsc",
|
|
17
17
|
"watch": "tsc -w",
|
|
18
18
|
"test": "yarn integration",
|
|
19
|
+
"unit": "jest --verbose dist/test/unit",
|
|
19
20
|
"integration": "npm run integration:dremio",
|
|
20
21
|
"integration:dremio": "jest --verbose dist/test",
|
|
21
22
|
"lint": "eslint driver/*.js",
|
|
22
23
|
"lint:fix": "eslint driver/*.js"
|
|
23
24
|
},
|
|
24
25
|
"dependencies": {
|
|
25
|
-
"@cubejs-backend/base-driver": "1.6.
|
|
26
|
-
"@cubejs-backend/schema-compiler": "1.6.
|
|
27
|
-
"@cubejs-backend/shared": "1.6.
|
|
28
|
-
"axios": "^1.8.3"
|
|
29
|
-
"sqlstring": "^2.3.1"
|
|
26
|
+
"@cubejs-backend/base-driver": "1.6.70",
|
|
27
|
+
"@cubejs-backend/schema-compiler": "1.6.70",
|
|
28
|
+
"@cubejs-backend/shared": "1.6.70",
|
|
29
|
+
"axios": "^1.8.3"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@cubejs-backend/linter": "1.6.
|
|
33
|
-
"@cubejs-backend/testing-shared": "1.6.
|
|
32
|
+
"@cubejs-backend/linter": "1.6.70",
|
|
33
|
+
"@cubejs-backend/testing-shared": "1.6.70",
|
|
34
34
|
"jest": "^29"
|
|
35
35
|
},
|
|
36
36
|
"license": "Apache-2.0",
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"eslintConfig": {
|
|
41
41
|
"extends": "../cubejs-linter"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "e6666359d37b223362d83cf745bcd0a1c1fdf4b2"
|
|
44
44
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/* eslint-disable quotes */
|
|
2
|
+
const { applyParams } = require('../../../driver/DremioDriver');
|
|
3
|
+
|
|
4
|
+
// Dremio is a Calcite-based, standard-SQL engine: a quote inside a string
|
|
5
|
+
// literal is escaped by doubling it and a backslash is plain data.
|
|
6
|
+
describe('DremioDriver SQL parameter escaping', () => {
|
|
7
|
+
it('preserves LIKE escape sequences emitted by the schema compiler', () => {
|
|
8
|
+
const sql = applyParams(
|
|
9
|
+
`SELECT * FROM orders WHERE LOWER(name) LIKE '%' || LOWER(?) || '%' ESCAPE '\\'`,
|
|
10
|
+
['new\\_order\\%'],
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
expect(sql).toBe(
|
|
14
|
+
`SELECT * FROM orders WHERE LOWER(name) LIKE '%' || LOWER('new\\_order\\%') || '%' ESCAPE '\\'`
|
|
15
|
+
);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('does not double literal backslashes in LIKE parameters', () => {
|
|
19
|
+
const sql = applyParams(
|
|
20
|
+
`SELECT * FROM orders WHERE LOWER(name) LIKE '%' || LOWER(?) || '%' ESCAPE '\\'`,
|
|
21
|
+
['folder\\\\name'],
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
expect(sql).toBe(
|
|
25
|
+
`SELECT * FROM orders WHERE LOWER(name) LIKE '%' || LOWER('folder\\\\name') || '%' ESCAPE '\\'`
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('doubles quotes so a value cannot break out of the literal', () => {
|
|
30
|
+
const sql = applyParams(
|
|
31
|
+
'SELECT * FROM orders WHERE name = ?',
|
|
32
|
+
[`o'reilly'); DROP TABLE orders; --`],
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
expect(sql).toBe(
|
|
36
|
+
`SELECT * FROM orders WHERE name = 'o''reilly''); DROP TABLE orders; --'`
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('keeps the literal closed for a backslash-then-quote payload', () => {
|
|
41
|
+
// In a backslash-escaping dialect `\'` would smuggle a quote through; on
|
|
42
|
+
// Dremio the backslash is data and only the quote needs doubling.
|
|
43
|
+
const sql = applyParams(
|
|
44
|
+
'SELECT * FROM orders WHERE name = ?',
|
|
45
|
+
[`foo\\' OR 1=1 --`],
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
expect(sql).toBe(`SELECT * FROM orders WHERE name = 'foo\\'' OR 1=1 --'`);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('keeps the literal closed for a value ending in a backslash', () => {
|
|
52
|
+
const sql = applyParams(
|
|
53
|
+
'SELECT * FROM orders WHERE name = ? AND status = ?',
|
|
54
|
+
['payload\\', 'new'],
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
expect(sql).toBe(`SELECT * FROM orders WHERE name = 'payload\\' AND status = 'new'`);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('keeps a literal percent sign in an equality parameter verbatim', () => {
|
|
61
|
+
const sql = applyParams(
|
|
62
|
+
'SELECT * FROM orders WHERE discount_label = ?',
|
|
63
|
+
['100% cotton'],
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
expect(sql).toBe(`SELECT * FROM orders WHERE discount_label = '100% cotton'`);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('escapes every element of an array parameter', () => {
|
|
70
|
+
const sql = applyParams(
|
|
71
|
+
'SELECT * FROM orders WHERE status IN (?)',
|
|
72
|
+
[[`it's`, 'b']],
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
expect(sql).toBe(`SELECT * FROM orders WHERE status IN ('it''s', 'b')`);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('substitutes multiple placeholders in order', () => {
|
|
79
|
+
const sql = applyParams(
|
|
80
|
+
`SELECT * FROM orders WHERE LOWER(name) LIKE '%' || LOWER(?) || '%' ESCAPE '\\' AND status = ? AND amount > ?`,
|
|
81
|
+
['pending\\_review', 'new', 100],
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
expect(sql).toBe(
|
|
85
|
+
`SELECT * FROM orders WHERE LOWER(name) LIKE '%' || LOWER('pending\\_review') || '%' ESCAPE '\\' AND status = 'new' AND amount > 100`
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
});
|