diff --git a/packages/cubejs-backend-native/src/orchestrator.rs b/packages/cubejs-backend-native/src/orchestrator.rs
index 227e8b9970d76..00ab47b16be06 100644
--- a/packages/cubejs-backend-native/src/orchestrator.rs
+++ b/packages/cubejs-backend-native/src/orchestrator.rs
@@ -184,6 +184,9 @@ impl ValueObject for ResultWrapper {
DBResponsePrimitive::String(s) => FieldValue::String(Cow::Borrowed(s)),
DBResponsePrimitive::Number(n) => FieldValue::Number(*n),
DBResponsePrimitive::Boolean(b) => FieldValue::Bool(*b),
+ DBResponsePrimitive::Uncommon(v) => FieldValue::String(Cow::Owned(
+ serde_json::to_string(&v).unwrap_or_else(|_| v.to_string()),
+ )),
DBResponsePrimitive::Null => FieldValue::Null,
})
}
diff --git a/packages/cubejs-testing/birdbox-fixtures/postgresql/schema/unusualDataTypes.js b/packages/cubejs-testing/birdbox-fixtures/postgresql/schema/unusualDataTypes.js
new file mode 100644
index 0000000000000..42849efcb4397
--- /dev/null
+++ b/packages/cubejs-testing/birdbox-fixtures/postgresql/schema/unusualDataTypes.js
@@ -0,0 +1,68 @@
+cube('unusualDataTypes', {
+ sql: `SELECT
+ 1 AS id,
+ 100 AS amount,
+ 'new' AS status,
+ '{"key": "value1", "number": 42}'::json AS json_column,
+ '{"key": "value1", "number": 42}'::jsonb AS jsonb_column,
+ ARRAY[1, 2, 3] AS array_column,
+ '11:22:33:44:55:66'::macaddr AS mac_address,
+ '192.168.0.1'::inet AS inet_column,
+ '192.168.0.0/24'::cidr AS cidr_column,
+ 't'::boolean AS boolean_column,
+ 'Hello, world!'::text AS text_column,
+ '1.0, 1.0'::point AS point_column,
+ '11111111'::bit(8) AS bit_column,
+ 'data'::xml AS xml_column
+ UNION ALL
+ SELECT
+ 2 AS id,
+ 200 AS amount,
+ 'new' AS status,
+ '{"key": "value2", "number": 84}'::json AS json_column,
+ '{"key": "value2", "number": 84}'::jsonb AS jsonb_column,
+ ARRAY[4, 5, 6] AS array_column,
+ '00:11:22:33:44:55'::macaddr AS mac_address,
+ '192.168.0.2'::inet AS inet_column,
+ '192.168.0.0/24'::cidr AS cidr_column,
+ 'f'::boolean AS boolean_column,
+ 'Goodbye, world!'::text AS text_column,
+ '2.0, 2.0'::point AS point_column,
+ '00000001'::bit(8) AS bit_column,
+ 'more data'::xml AS xml_column
+ UNION ALL
+ SELECT
+ 3 AS id,
+ 300 AS amount,
+ 'processed' AS status,
+ '{"key": "value3", "number": 168}'::json AS json_column,
+ '{"key": "value3", "number": 168}'::jsonb AS jsonb_column,
+ ARRAY[7, 8, 9] AS array_column,
+ '22:33:44:55:66:77'::macaddr AS mac_address,
+ '192.168.0.3'::inet AS inet_column,
+ '192.168.0.0/24'::cidr AS cidr_column,
+ 't'::boolean AS boolean_column,
+ 'PostgreSQL is awesome!'::text AS text_column,
+ '3.0, 3.0'::point AS point_column,
+ '11110000'::bit(8) AS bit_column,
+ 'even more data'::xml AS xml_column`,
+ measures: {
+ count: { type: 'count' },
+ total_amount: { type: 'sum', sql: 'amount' }
+ },
+ dimensions: {
+ id: { type: 'number', sql: 'id', primaryKey: true },
+ status: { type: 'string', sql: 'status' },
+ json: { type: 'string', sql: 'json_column' },
+ jsonb: { type: 'string', sql: 'jsonb_column' },
+ array: { type: 'string', sql: 'array_column' },
+ mac_address: { type: 'string', sql: 'mac_address' },
+ inet_column: { type: 'string', sql: 'inet_column' },
+ cidr_column: { type: 'string', sql: 'cidr_column' },
+ boolean_column: { type: 'string', sql: 'boolean_column' },
+ text_column: { type: 'string', sql: 'text_column' },
+ point_column: { type: 'string', sql: 'point_column' },
+ bit_column: { type: 'string', sql: 'bit_column' },
+ xml_column: { type: 'string', sql: 'xml_column' },
+ }
+});
diff --git a/packages/cubejs-testing/test/__snapshots__/cli-postgresql.test.ts.snap b/packages/cubejs-testing/test/__snapshots__/cli-postgresql.test.ts.snap
index ce1dfe7bc3aac..cf99d6660a764 100644
--- a/packages/cubejs-testing/test/__snapshots__/cli-postgresql.test.ts.snap
+++ b/packages/cubejs-testing/test/__snapshots__/cli-postgresql.test.ts.snap
@@ -81,6 +81,95 @@ Array [
]
`;
+exports[`postgresql HTTP Transport Different column data types: Different column data types 1`] = `
+Array [
+ Object {
+ "unusualDataTypes.array": Array [
+ 1,
+ 2,
+ 3,
+ ],
+ "unusualDataTypes.bit_column": "11111111",
+ "unusualDataTypes.boolean_column": true,
+ "unusualDataTypes.cidr_column": "192.168.0.0/24",
+ "unusualDataTypes.id": 1,
+ "unusualDataTypes.inet_column": "192.168.0.1",
+ "unusualDataTypes.json": Object {
+ "key": "value1",
+ "number": 42,
+ },
+ "unusualDataTypes.jsonb": Object {
+ "key": "value1",
+ "number": 42,
+ },
+ "unusualDataTypes.mac_address": "11:22:33:44:55:66",
+ "unusualDataTypes.point_column": Object {
+ "x": 1,
+ "y": 1,
+ },
+ "unusualDataTypes.status": "new",
+ "unusualDataTypes.text_column": "Hello, world!",
+ "unusualDataTypes.xml_column": "data",
+ },
+ Object {
+ "unusualDataTypes.array": Array [
+ 4,
+ 5,
+ 6,
+ ],
+ "unusualDataTypes.bit_column": "00000001",
+ "unusualDataTypes.boolean_column": false,
+ "unusualDataTypes.cidr_column": "192.168.0.0/24",
+ "unusualDataTypes.id": 2,
+ "unusualDataTypes.inet_column": "192.168.0.2",
+ "unusualDataTypes.json": Object {
+ "key": "value2",
+ "number": 84,
+ },
+ "unusualDataTypes.jsonb": Object {
+ "key": "value2",
+ "number": 84,
+ },
+ "unusualDataTypes.mac_address": "00:11:22:33:44:55",
+ "unusualDataTypes.point_column": Object {
+ "x": 2,
+ "y": 2,
+ },
+ "unusualDataTypes.status": "new",
+ "unusualDataTypes.text_column": "Goodbye, world!",
+ "unusualDataTypes.xml_column": "more data",
+ },
+ Object {
+ "unusualDataTypes.array": Array [
+ 7,
+ 8,
+ 9,
+ ],
+ "unusualDataTypes.bit_column": "11110000",
+ "unusualDataTypes.boolean_column": true,
+ "unusualDataTypes.cidr_column": "192.168.0.0/24",
+ "unusualDataTypes.id": 3,
+ "unusualDataTypes.inet_column": "192.168.0.3",
+ "unusualDataTypes.json": Object {
+ "key": "value3",
+ "number": 168,
+ },
+ "unusualDataTypes.jsonb": Object {
+ "key": "value3",
+ "number": 168,
+ },
+ "unusualDataTypes.mac_address": "22:33:44:55:66:77",
+ "unusualDataTypes.point_column": Object {
+ "x": 3,
+ "y": 3,
+ },
+ "unusualDataTypes.status": "processed",
+ "unusualDataTypes.text_column": "PostgreSQL is awesome!",
+ "unusualDataTypes.xml_column": "even more data",
+ },
+]
+`;
+
exports[`postgresql WS Transport #1 Orders.totalAmount: #1 Orders.totalAmount 1`] = `
Array [
Object {
diff --git a/packages/cubejs-testing/test/abstract-test-case.ts b/packages/cubejs-testing/test/abstract-test-case.ts
index 706335b47481d..af511be97cb75 100644
--- a/packages/cubejs-testing/test/abstract-test-case.ts
+++ b/packages/cubejs-testing/test/abstract-test-case.ts
@@ -66,6 +66,32 @@ const asserts: [options: QueryTestOptions, query: Query][] = [
]
}
],
+ [
+ {
+ name: 'Different column data types'
+ },
+ {
+ dimensions: [
+ 'unusualDataTypes.array',
+ 'unusualDataTypes.bit_column',
+ 'unusualDataTypes.boolean_column',
+ 'unusualDataTypes.cidr_column',
+ 'unusualDataTypes.id',
+ 'unusualDataTypes.inet_column',
+ 'unusualDataTypes.json',
+ 'unusualDataTypes.jsonb',
+ 'unusualDataTypes.mac_address',
+ 'unusualDataTypes.point_column',
+ 'unusualDataTypes.status',
+ 'unusualDataTypes.text_column',
+ 'unusualDataTypes.xml_column'
+ ],
+ ungrouped: true,
+ order: {
+ 'unusualDataTypes.id': 'asc'
+ }
+ }
+ ],
];
// eslint-disable-next-line import/prefer-default-export
@@ -152,7 +178,7 @@ export function createBirdBoxTestCase(
let transport: WebSocketTransport;
let http: CubeApi;
let ws: CubeApi;
-
+
beforeAll(async () => {
try {
transport = new WebSocketTransport({
@@ -170,11 +196,11 @@ export function createBirdBoxTestCase(
process.exit(1);
}
});
-
+
afterAll(async () => {
await transport.close();
});
-
+
test('http+responseFormat=default', async () => {
const response = await http.load({
dimensions: ['Orders.status'],
@@ -184,7 +210,7 @@ export function createBirdBoxTestCase(
responses.push(response);
expect(response.rawData()).toMatchSnapshot('result-type');
});
-
+
test('http+responseFormat=compact option#1', async () => {
const response = await http.load({
dimensions: ['Orders.status'],
@@ -195,7 +221,7 @@ export function createBirdBoxTestCase(
responses.push(response);
expect(response.rawData()).toMatchSnapshot('result-type');
});
-
+
test('http+responseFormat=compact option#2', async () => {
const response = await http.load(
{
@@ -210,7 +236,7 @@ export function createBirdBoxTestCase(
responses.push(response);
expect(response.rawData()).toMatchSnapshot('result-type');
});
-
+
test('http+responseFormat=compact option#1+2', async () => {
const response = await http.load(
{
@@ -226,7 +252,7 @@ export function createBirdBoxTestCase(
responses.push(response);
expect(response.rawData()).toMatchSnapshot('result-type');
});
-
+
test('ws+responseFormat=default', async () => {
const response = await ws.load({
dimensions: ['Orders.status'],
@@ -236,7 +262,7 @@ export function createBirdBoxTestCase(
responses.push(response);
expect(response.rawData()).toMatchSnapshot('result-type');
});
-
+
test('ws+responseFormat=compact option#1', async () => {
const response = await ws.load({
dimensions: ['Orders.status'],
@@ -247,7 +273,7 @@ export function createBirdBoxTestCase(
responses.push(response);
expect(response.rawData()).toMatchSnapshot('result-type');
});
-
+
test('ws+responseFormat=compact option#2', async () => {
const response = await ws.load(
{
@@ -262,7 +288,7 @@ export function createBirdBoxTestCase(
responses.push(response);
expect(response.rawData()).toMatchSnapshot('result-type');
});
-
+
test('ws+responseFormat=compact option#1+2', async () => {
const response = await ws.load(
{
@@ -278,7 +304,7 @@ export function createBirdBoxTestCase(
responses.push(response);
expect(response.rawData()).toMatchSnapshot('result-type');
});
-
+
test('responses', () => {
// @ts-ignore
expect(responses[0].rawData()).toEqual(responses[1].rawData());
diff --git a/rust/cubeorchestrator/src/query_result_transform.rs b/rust/cubeorchestrator/src/query_result_transform.rs
index 22e18a889327b..c1165270965e2 100644
--- a/rust/cubeorchestrator/src/query_result_transform.rs
+++ b/rust/cubeorchestrator/src/query_result_transform.rs
@@ -621,6 +621,7 @@ pub enum DBResponsePrimitive {
Boolean(bool),
Number(f64),
String(String),
+ Uncommon(Value),
}
impl Display for DBResponsePrimitive {
@@ -630,6 +631,9 @@ impl Display for DBResponsePrimitive {
DBResponsePrimitive::Boolean(b) => b.to_string(),
DBResponsePrimitive::Number(n) => n.to_string(),
DBResponsePrimitive::String(s) => s.clone(),
+ DBResponsePrimitive::Uncommon(v) => {
+ serde_json::to_string(&v).unwrap_or_else(|_| v.to_string())
+ }
};
write!(f, "{}", str)
}