Skip to content

Commit 1b70644

Browse files
authored
fix(backend-native): Fix result wrapper parsing (#9361)
* fix(backend-native): Fix result wrapper parsing * add tests * fix tests
1 parent 969508d commit 1b70644

File tree

5 files changed

+201
-11
lines changed

5 files changed

+201
-11
lines changed

packages/cubejs-backend-native/src/orchestrator.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ impl ValueObject for ResultWrapper {
184184
DBResponsePrimitive::String(s) => FieldValue::String(Cow::Borrowed(s)),
185185
DBResponsePrimitive::Number(n) => FieldValue::Number(*n),
186186
DBResponsePrimitive::Boolean(b) => FieldValue::Bool(*b),
187+
DBResponsePrimitive::Uncommon(v) => FieldValue::String(Cow::Owned(
188+
serde_json::to_string(&v).unwrap_or_else(|_| v.to_string()),
189+
)),
187190
DBResponsePrimitive::Null => FieldValue::Null,
188191
})
189192
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
cube('unusualDataTypes', {
2+
sql: `SELECT
3+
1 AS id,
4+
100 AS amount,
5+
'new' AS status,
6+
'{"key": "value1", "number": 42}'::json AS json_column,
7+
'{"key": "value1", "number": 42}'::jsonb AS jsonb_column,
8+
ARRAY[1, 2, 3] AS array_column,
9+
'11:22:33:44:55:66'::macaddr AS mac_address,
10+
'192.168.0.1'::inet AS inet_column,
11+
'192.168.0.0/24'::cidr AS cidr_column,
12+
't'::boolean AS boolean_column,
13+
'Hello, world!'::text AS text_column,
14+
'1.0, 1.0'::point AS point_column,
15+
'11111111'::bit(8) AS bit_column,
16+
'<root><child>data</child></root>'::xml AS xml_column
17+
UNION ALL
18+
SELECT
19+
2 AS id,
20+
200 AS amount,
21+
'new' AS status,
22+
'{"key": "value2", "number": 84}'::json AS json_column,
23+
'{"key": "value2", "number": 84}'::jsonb AS jsonb_column,
24+
ARRAY[4, 5, 6] AS array_column,
25+
'00:11:22:33:44:55'::macaddr AS mac_address,
26+
'192.168.0.2'::inet AS inet_column,
27+
'192.168.0.0/24'::cidr AS cidr_column,
28+
'f'::boolean AS boolean_column,
29+
'Goodbye, world!'::text AS text_column,
30+
'2.0, 2.0'::point AS point_column,
31+
'00000001'::bit(8) AS bit_column,
32+
'<root><child>more data</child></root>'::xml AS xml_column
33+
UNION ALL
34+
SELECT
35+
3 AS id,
36+
300 AS amount,
37+
'processed' AS status,
38+
'{"key": "value3", "number": 168}'::json AS json_column,
39+
'{"key": "value3", "number": 168}'::jsonb AS jsonb_column,
40+
ARRAY[7, 8, 9] AS array_column,
41+
'22:33:44:55:66:77'::macaddr AS mac_address,
42+
'192.168.0.3'::inet AS inet_column,
43+
'192.168.0.0/24'::cidr AS cidr_column,
44+
't'::boolean AS boolean_column,
45+
'PostgreSQL is awesome!'::text AS text_column,
46+
'3.0, 3.0'::point AS point_column,
47+
'11110000'::bit(8) AS bit_column,
48+
'<root><child>even more data</child></root>'::xml AS xml_column`,
49+
measures: {
50+
count: { type: 'count' },
51+
total_amount: { type: 'sum', sql: 'amount' }
52+
},
53+
dimensions: {
54+
id: { type: 'number', sql: 'id', primaryKey: true },
55+
status: { type: 'string', sql: 'status' },
56+
json: { type: 'string', sql: 'json_column' },
57+
jsonb: { type: 'string', sql: 'jsonb_column' },
58+
array: { type: 'string', sql: 'array_column' },
59+
mac_address: { type: 'string', sql: 'mac_address' },
60+
inet_column: { type: 'string', sql: 'inet_column' },
61+
cidr_column: { type: 'string', sql: 'cidr_column' },
62+
boolean_column: { type: 'string', sql: 'boolean_column' },
63+
text_column: { type: 'string', sql: 'text_column' },
64+
point_column: { type: 'string', sql: 'point_column' },
65+
bit_column: { type: 'string', sql: 'bit_column' },
66+
xml_column: { type: 'string', sql: 'xml_column' },
67+
}
68+
});

packages/cubejs-testing/test/__snapshots__/cli-postgresql.test.ts.snap

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,95 @@ Array [
8181
]
8282
`;
8383

84+
exports[`postgresql HTTP Transport Different column data types: Different column data types 1`] = `
85+
Array [
86+
Object {
87+
"unusualDataTypes.array": Array [
88+
1,
89+
2,
90+
3,
91+
],
92+
"unusualDataTypes.bit_column": "11111111",
93+
"unusualDataTypes.boolean_column": true,
94+
"unusualDataTypes.cidr_column": "192.168.0.0/24",
95+
"unusualDataTypes.id": 1,
96+
"unusualDataTypes.inet_column": "192.168.0.1",
97+
"unusualDataTypes.json": Object {
98+
"key": "value1",
99+
"number": 42,
100+
},
101+
"unusualDataTypes.jsonb": Object {
102+
"key": "value1",
103+
"number": 42,
104+
},
105+
"unusualDataTypes.mac_address": "11:22:33:44:55:66",
106+
"unusualDataTypes.point_column": Object {
107+
"x": 1,
108+
"y": 1,
109+
},
110+
"unusualDataTypes.status": "new",
111+
"unusualDataTypes.text_column": "Hello, world!",
112+
"unusualDataTypes.xml_column": "<root><child>data</child></root>",
113+
},
114+
Object {
115+
"unusualDataTypes.array": Array [
116+
4,
117+
5,
118+
6,
119+
],
120+
"unusualDataTypes.bit_column": "00000001",
121+
"unusualDataTypes.boolean_column": false,
122+
"unusualDataTypes.cidr_column": "192.168.0.0/24",
123+
"unusualDataTypes.id": 2,
124+
"unusualDataTypes.inet_column": "192.168.0.2",
125+
"unusualDataTypes.json": Object {
126+
"key": "value2",
127+
"number": 84,
128+
},
129+
"unusualDataTypes.jsonb": Object {
130+
"key": "value2",
131+
"number": 84,
132+
},
133+
"unusualDataTypes.mac_address": "00:11:22:33:44:55",
134+
"unusualDataTypes.point_column": Object {
135+
"x": 2,
136+
"y": 2,
137+
},
138+
"unusualDataTypes.status": "new",
139+
"unusualDataTypes.text_column": "Goodbye, world!",
140+
"unusualDataTypes.xml_column": "<root><child>more data</child></root>",
141+
},
142+
Object {
143+
"unusualDataTypes.array": Array [
144+
7,
145+
8,
146+
9,
147+
],
148+
"unusualDataTypes.bit_column": "11110000",
149+
"unusualDataTypes.boolean_column": true,
150+
"unusualDataTypes.cidr_column": "192.168.0.0/24",
151+
"unusualDataTypes.id": 3,
152+
"unusualDataTypes.inet_column": "192.168.0.3",
153+
"unusualDataTypes.json": Object {
154+
"key": "value3",
155+
"number": 168,
156+
},
157+
"unusualDataTypes.jsonb": Object {
158+
"key": "value3",
159+
"number": 168,
160+
},
161+
"unusualDataTypes.mac_address": "22:33:44:55:66:77",
162+
"unusualDataTypes.point_column": Object {
163+
"x": 3,
164+
"y": 3,
165+
},
166+
"unusualDataTypes.status": "processed",
167+
"unusualDataTypes.text_column": "PostgreSQL is awesome!",
168+
"unusualDataTypes.xml_column": "<root><child>even more data</child></root>",
169+
},
170+
]
171+
`;
172+
84173
exports[`postgresql WS Transport #1 Orders.totalAmount: #1 Orders.totalAmount 1`] = `
85174
Array [
86175
Object {

packages/cubejs-testing/test/abstract-test-case.ts

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,32 @@ const asserts: [options: QueryTestOptions, query: Query][] = [
6666
]
6767
}
6868
],
69+
[
70+
{
71+
name: 'Different column data types'
72+
},
73+
{
74+
dimensions: [
75+
'unusualDataTypes.array',
76+
'unusualDataTypes.bit_column',
77+
'unusualDataTypes.boolean_column',
78+
'unusualDataTypes.cidr_column',
79+
'unusualDataTypes.id',
80+
'unusualDataTypes.inet_column',
81+
'unusualDataTypes.json',
82+
'unusualDataTypes.jsonb',
83+
'unusualDataTypes.mac_address',
84+
'unusualDataTypes.point_column',
85+
'unusualDataTypes.status',
86+
'unusualDataTypes.text_column',
87+
'unusualDataTypes.xml_column'
88+
],
89+
ungrouped: true,
90+
order: {
91+
'unusualDataTypes.id': 'asc'
92+
}
93+
}
94+
],
6995
];
7096

7197
// eslint-disable-next-line import/prefer-default-export
@@ -152,7 +178,7 @@ export function createBirdBoxTestCase(
152178
let transport: WebSocketTransport;
153179
let http: CubeApi;
154180
let ws: CubeApi;
155-
181+
156182
beforeAll(async () => {
157183
try {
158184
transport = new WebSocketTransport({
@@ -170,11 +196,11 @@ export function createBirdBoxTestCase(
170196
process.exit(1);
171197
}
172198
});
173-
199+
174200
afterAll(async () => {
175201
await transport.close();
176202
});
177-
203+
178204
test('http+responseFormat=default', async () => {
179205
const response = await http.load({
180206
dimensions: ['Orders.status'],
@@ -184,7 +210,7 @@ export function createBirdBoxTestCase(
184210
responses.push(response);
185211
expect(response.rawData()).toMatchSnapshot('result-type');
186212
});
187-
213+
188214
test('http+responseFormat=compact option#1', async () => {
189215
const response = await http.load({
190216
dimensions: ['Orders.status'],
@@ -195,7 +221,7 @@ export function createBirdBoxTestCase(
195221
responses.push(response);
196222
expect(response.rawData()).toMatchSnapshot('result-type');
197223
});
198-
224+
199225
test('http+responseFormat=compact option#2', async () => {
200226
const response = await http.load(
201227
{
@@ -210,7 +236,7 @@ export function createBirdBoxTestCase(
210236
responses.push(response);
211237
expect(response.rawData()).toMatchSnapshot('result-type');
212238
});
213-
239+
214240
test('http+responseFormat=compact option#1+2', async () => {
215241
const response = await http.load(
216242
{
@@ -226,7 +252,7 @@ export function createBirdBoxTestCase(
226252
responses.push(response);
227253
expect(response.rawData()).toMatchSnapshot('result-type');
228254
});
229-
255+
230256
test('ws+responseFormat=default', async () => {
231257
const response = await ws.load({
232258
dimensions: ['Orders.status'],
@@ -236,7 +262,7 @@ export function createBirdBoxTestCase(
236262
responses.push(response);
237263
expect(response.rawData()).toMatchSnapshot('result-type');
238264
});
239-
265+
240266
test('ws+responseFormat=compact option#1', async () => {
241267
const response = await ws.load({
242268
dimensions: ['Orders.status'],
@@ -247,7 +273,7 @@ export function createBirdBoxTestCase(
247273
responses.push(response);
248274
expect(response.rawData()).toMatchSnapshot('result-type');
249275
});
250-
276+
251277
test('ws+responseFormat=compact option#2', async () => {
252278
const response = await ws.load(
253279
{
@@ -262,7 +288,7 @@ export function createBirdBoxTestCase(
262288
responses.push(response);
263289
expect(response.rawData()).toMatchSnapshot('result-type');
264290
});
265-
291+
266292
test('ws+responseFormat=compact option#1+2', async () => {
267293
const response = await ws.load(
268294
{
@@ -278,7 +304,7 @@ export function createBirdBoxTestCase(
278304
responses.push(response);
279305
expect(response.rawData()).toMatchSnapshot('result-type');
280306
});
281-
307+
282308
test('responses', () => {
283309
// @ts-ignore
284310
expect(responses[0].rawData()).toEqual(responses[1].rawData());

rust/cubeorchestrator/src/query_result_transform.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,7 @@ pub enum DBResponsePrimitive {
621621
Boolean(bool),
622622
Number(f64),
623623
String(String),
624+
Uncommon(Value),
624625
}
625626

626627
impl Display for DBResponsePrimitive {
@@ -630,6 +631,9 @@ impl Display for DBResponsePrimitive {
630631
DBResponsePrimitive::Boolean(b) => b.to_string(),
631632
DBResponsePrimitive::Number(n) => n.to_string(),
632633
DBResponsePrimitive::String(s) => s.clone(),
634+
DBResponsePrimitive::Uncommon(v) => {
635+
serde_json::to_string(&v).unwrap_or_else(|_| v.to_string())
636+
}
633637
};
634638
write!(f, "{}", str)
635639
}

0 commit comments

Comments
 (0)