-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
Describe the bug
There is an example online of using gte with dimensions, but not measures (https://cube.dev/blog/graphql-federation-example-with-apollo-federation-and-apollo-graphos). However, the Playground lets you attempt to filter by measures, but it errors. It creates a misconstructed SQL which results in a bad HAVING clause:
{
"data": null,
"errors": [
{
"message": "Error: unexpected token [HAVING]",
"path": [
"cube"
],
"extensions": {
"code": "DOWNSTREAM_SERVICE_ERROR"
}
}
]
}SELECT
table.publicId,
DATE_TRUNC('hour', table.timestamp),
MEASURE(
table.temperature_status__igbt_temperature__c__max
)
FROM
table
WHERE
()
GROUP BY
1,
2
HAVING
(
MEASURE(
table.temperature_status__igbt_temperature__c__max
) >= '0'
AND MEASURE(
table.temperature_status__igbt_temperature__c__max
) <= '2'
)
LIMIT
10000;query temperature_status__igbt_temperature__c__max($timezone: String!, $fromDate: String!, $toDate: String!, $assets: [String!], $limit: Int!) {
cube(
timezone: $timezone
where: {table: {
id: {in: $assets},
timestamp: {inDateRange: [$fromDate, $toDate]},
temperature_status__igbt_temperature__c__max: {
in: [0, 2]
}
}}
orderBy: {table: {temperature_status__igbt_temperature__c__max: desc}}
limit: $limit
) {
table {
id
temperature_status__igbt_temperature__c__max
}
}
}To Reproduce
Steps to reproduce the behavior:
- Deploy the minimal schema
- Execute the above GraphQL query, or go to the playground and try the non-GraphQL query, results will be the same: http://localhost:4000/#/build?query={%22measures%22:[%22table.temperature_status__igbt_temperature__c__max%22],%22dimensions%22:[%22table.publicId%22],%22filters%22:[{%22values%22:[%220%22],%22member%22:%22table.temperature_status__igbt_temperature__c__max%22,%22operator%22:%22gte%22},{%22values%22:[%222%22],%22member%22:%22table.temperature_status__igbt_temperature__c__max%22,%22operator%22:%22lte%22}]}
- Notice the HAVING error with the malformed SQL statement
Expected behavior
Should be able to filter on measures and not just dimensions. Surprisingly, the Playground lets you attempt this, implying that this should be possible.
Screenshots
Minimally reproducible Cube Schema
In case your bug report is data modelling related please put your minimally reproducible Cube Schema here.
You can use selects without tables in order to achieve that as follows.
const sql_table = `"table"`;
cube("Table", {
data_source: `table`,
sql_table,
pre_aggregations: {
lambda: {
type: `rollup_lambda`,
rollups: [CUBE.batch],
},
batch: {
refresh_key: {
sql: `SELECT MAX(updated_at) FROM ${sql_table}`,
every: `5 minute`,
},
measures: [
CUBE.temperature_status__igbt_temperature__c__max,
],
dimensions: [CUBE.id],
time_dimension: CUBE.timestamp,
granularity: `day`,
partition_granularity: `day`,
build_range_start: {
sql: `SELECT MIN(timestamp) FROM ${sql_table}`,
},
build_range_end: {
sql: `SELECT MAX(timestamp) FROM ${sql_table}`,
},
},
},
measures: {
count: {
type: `count`,
},
temperature_status__igbt_temperature__c__max: {
sql: `ROUND(${CUBE}."temperature_status__igbt_temperature__c__max", 2)`,
type: `max`,
},
},
dimensions: {
id: {
sql: `${CUBE}.id`,
type: `string`,
},
publicId: {
sql: `ltrim(${CUBE}.id)`,
type: `string`,
},
timestamp: {
sql: `${CUBE}.timestamp`,
type: `time`,
},
temperature_status__igbt_temperature_measure__c__max: {
sql: `${CUBE}.temperature_status__igbt_temperature__c__max`,
type: `number`,
},
},
});Version:
Bug is present on both the latest v1.5.3, and v1.3.50
Additional Context
Using the playground, here is what is generated and run using the playground query builder.
Generated SQL
SELECT
ltrim("table".id) "table__public_id",
max(
ROUND(
"table"."temperature_status__igbt_temperature__c__max",
2
)
) "table__temperature_status__igbt_temperature__c__max"
FROM
"jupiter__stgall2__hourly" AS "table"
GROUP BY
"table__public_id"
HAVING
(
max(
ROUND(
"table"."temperature_status__igbt_temperature__c__max",
2
)
) >= $ 1
)
AND (
max(
ROUND(
"table"."temperature_status__igbt_temperature__c__max",
2
)
) <= $ 2
)
ORDER BY
"table__temperature_status__igbt_temperature__c__max" DESC
LIMIT
100000SQL API
SELECT
table.publicId,
MEASURE(
table.temperature_status__igbt_temperature__c__max
)
FROM
table
WHERE
()
GROUP BY
1
HAVING
(
MEASURE(
table.temperature_status__igbt_temperature__c__max
) >= '0'
AND MEASURE(
table.temperature_status__igbt_temperature__c__max
) <= '2'
)
LIMIT
100000;REST API
{
"measures": [
"table.temperature_status__igbt_temperature__c__max"
],
"dimensions": [
"table.publicId"
],
"filters": [
{
"values": [
"0"
],
"member": "table.temperature_status__igbt_temperature__c__max",
"operator": "gte"
},
{
"values": [
"2"
],
"member": "table.temperature_status__igbt_temperature__c__max",
"operator": "lte"
}
]
}GraphQL API
query CubeQuery {
cube(
where: {table: {AND: [{temperature_status__igbt_temperature__c__max: {gte: 0}}, {temperature_status__igbt_temperature__c__max: {lte: 2}}]}}
) {
table {
temperature_status__igbt_temperature__c__max
publicId
}
}
}