From 27665c3538a4544114513842ad7cd9040f0f4357 Mon Sep 17 00:00:00 2001 From: Igor Lukanin Date: Wed, 11 Dec 2024 14:51:59 +0100 Subject: [PATCH 01/21] docs: Add data ingestion timeout for Cube Store --- .../reference/configuration/environment-variables.mdx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/pages/reference/configuration/environment-variables.mdx b/docs/pages/reference/configuration/environment-variables.mdx index 6952c6f1025ed..044efede3b1e6 100644 --- a/docs/pages/reference/configuration/environment-variables.mdx +++ b/docs/pages/reference/configuration/environment-variables.mdx @@ -560,6 +560,14 @@ The timeout value for any queries made to the database by Cube. | ---------------------------------------- | ---------------------- | --------------------- | | A number in seconds or a duration string | `10m` | `10m` | + + +There's a hard limit of 20 minutes for queries that ingest data into Cube Store +when pre-aggregations are built. If you bump into this limit, consider using an +export bucket and splitting pre-aggregations into partitions. + + + ## `CUBEJS_DB_FETCH_COLUMNS_BY_ORDINAL_POSITION` Force fetching of columns by ordinal positions. Certain data-providers (e.g., Redshift) do not guarantee columns in the From 9327f703b6cf66b2340f0e0a4a0a72456f0b1e3a Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Wed, 11 Dec 2024 16:51:31 +0100 Subject: [PATCH 02/21] chore(cubesql): Convert properly DataType::Timestamp into ColumnType::Timestamp (#9031) Co-authored-by: Dmitry Patsura --- .../cubejs-testing/test/smoke-cubesql.test.ts | 2 +- rust/cubesql/cubesql/src/sql/dataframe.rs | 39 ++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/packages/cubejs-testing/test/smoke-cubesql.test.ts b/packages/cubejs-testing/test/smoke-cubesql.test.ts index 1e8e5583b4e28..0833ed85b40c3 100644 --- a/packages/cubejs-testing/test/smoke-cubesql.test.ts +++ b/packages/cubejs-testing/test/smoke-cubesql.test.ts @@ -119,7 +119,7 @@ describe('SQL API', () => { expect(JSON.parse(chunk.toString()).schema).toEqual([ { name: 'orderDate', - column_type: 'String', + column_type: 'Timestamp', }, ]); } else { diff --git a/rust/cubesql/cubesql/src/sql/dataframe.rs b/rust/cubesql/cubesql/src/sql/dataframe.rs index aa9bc341ee16c..d932fe75a6212 100644 --- a/rust/cubesql/cubesql/src/sql/dataframe.rs +++ b/rust/cubesql/cubesql/src/sql/dataframe.rs @@ -404,7 +404,7 @@ pub fn arrow_to_column_type(arrow_type: DataType) -> Result Ok(ColumnType::String), DataType::Date32 => Ok(ColumnType::Date(false)), DataType::Date64 => Ok(ColumnType::Date(true)), - DataType::Timestamp(_, _) => Ok(ColumnType::String), + DataType::Timestamp(_, _) => Ok(ColumnType::Timestamp), DataType::Interval(unit) => Ok(ColumnType::Interval(unit)), DataType::Float16 | DataType::Float32 | DataType::Float64 => Ok(ColumnType::Double), DataType::Boolean => Ok(ColumnType::Boolean), @@ -794,4 +794,41 @@ mod tests { serde_json::to_string(&frame.data).unwrap() ); } + + #[test] + fn test_arrow_to_column_type() { + let cases = vec![ + (DataType::Binary, ColumnType::Blob), + (DataType::Utf8, ColumnType::String), + (DataType::LargeUtf8, ColumnType::String), + (DataType::Date32, ColumnType::Date(false)), + (DataType::Date64, ColumnType::Date(true)), + ( + DataType::Timestamp(TimeUnit::Second, None), + ColumnType::Timestamp, + ), + ( + DataType::Interval(IntervalUnit::YearMonth), + ColumnType::Interval(IntervalUnit::YearMonth), + ), + (DataType::Float16, ColumnType::Double), + (DataType::Float32, ColumnType::Double), + (DataType::Float64, ColumnType::Double), + (DataType::Boolean, ColumnType::Boolean), + (DataType::Int32, ColumnType::Int32), + (DataType::UInt32, ColumnType::Int32), + (DataType::Int8, ColumnType::Int64), + (DataType::Int16, ColumnType::Int64), + (DataType::Int64, ColumnType::Int64), + (DataType::UInt8, ColumnType::Int64), + (DataType::UInt16, ColumnType::Int64), + (DataType::UInt64, ColumnType::Int64), + (DataType::Null, ColumnType::String), + ]; + + for (arrow_type, expected_column_type) in cases { + let result = arrow_to_column_type(arrow_type.clone()).unwrap(); + assert_eq!(result, expected_column_type, "Failed for {:?}", arrow_type); + } + } } From 849790f965dd0d9fddba11e3d8d124b84397ca9b Mon Sep 17 00:00:00 2001 From: Maxim Date: Wed, 11 Dec 2024 18:25:11 -0800 Subject: [PATCH 03/21] fix(schema-compiler): fix DAP with query_rewrite and python config (#9033) --- packages/cubejs-api-gateway/src/gateway.ts | 8 +- .../src/core/CompilerApi.js | 4 +- .../birdbox-fixtures/rbac-python/cube.py | 62 ++++++++++ .../rbac-python/model/cubes/users.yaml | 54 ++++++++ packages/cubejs-testing/src/birdbox.ts | 10 +- .../__snapshots__/smoke-rbac.test.ts.snap | 8 ++ .../cubejs-testing/test/smoke-rbac.test.ts | 117 +++++++++++++----- 7 files changed, 226 insertions(+), 37 deletions(-) create mode 100644 packages/cubejs-testing/birdbox-fixtures/rbac-python/cube.py create mode 100644 packages/cubejs-testing/birdbox-fixtures/rbac-python/model/cubes/users.yaml diff --git a/packages/cubejs-api-gateway/src/gateway.ts b/packages/cubejs-api-gateway/src/gateway.ts index 6737ca6fef35c..009d5b25ad752 100644 --- a/packages/cubejs-api-gateway/src/gateway.ts +++ b/packages/cubejs-api-gateway/src/gateway.ts @@ -1196,18 +1196,20 @@ class ApiGateway { currentQuery = this.parseMemberExpressionsInQuery(currentQuery); } - let normalizedQuery = normalizeQuery(currentQuery, persistent); + const normalizedQuery = normalizeQuery(currentQuery, persistent); + let evaluatedQuery = normalizedQuery; if (hasExpressionsInQuery) { // We need to parse/eval all member expressions early as applyRowLevelSecurity // needs to access the full SQL query in order to evaluate rules - normalizedQuery = + evaluatedQuery = this.evalMemberExpressionsInQuery(normalizedQuery); } // First apply cube/view level security policies const queryWithRlsFilters = await compilerApi.applyRowLevelSecurity( normalizedQuery, + evaluatedQuery, context ); // Then apply user-supplied queryRewrite @@ -1219,7 +1221,7 @@ class ApiGateway { // applyRowLevelSecurity may add new filters which may contain raw member expressions // if that's the case, we should run an extra pass of parsing here to make sure // nothing breaks down the road - if (this.hasExpressionsInQuery(rewrittenQuery)) { + if (hasExpressionsInQuery || this.hasExpressionsInQuery(rewrittenQuery)) { rewrittenQuery = this.parseMemberExpressionsInQuery(rewrittenQuery); rewrittenQuery = this.evalMemberExpressionsInQuery(rewrittenQuery); } diff --git a/packages/cubejs-server-core/src/core/CompilerApi.js b/packages/cubejs-server-core/src/core/CompilerApi.js index 6e3689491a314..64dd7e9fa9da8 100644 --- a/packages/cubejs-server-core/src/core/CompilerApi.js +++ b/packages/cubejs-server-core/src/core/CompilerApi.js @@ -271,7 +271,7 @@ export class CompilerApi { * - combining all filters for different roles with OR * - combining cube and view filters with AND */ - async applyRowLevelSecurity(query, context) { + async applyRowLevelSecurity(query, evaluatedQuery, context) { const compilers = await this.getCompilers({ requestId: context.requestId }); const { cubeEvaluator } = compilers; @@ -279,7 +279,7 @@ export class CompilerApi { return query; } - const queryCubes = await this.getCubesFromQuery(query, context); + const queryCubes = await this.getCubesFromQuery(evaluatedQuery, context); // We collect Cube and View filters separately because they have to be // applied in "two layers": first Cube filters, then View filters on top diff --git a/packages/cubejs-testing/birdbox-fixtures/rbac-python/cube.py b/packages/cubejs-testing/birdbox-fixtures/rbac-python/cube.py new file mode 100644 index 0000000000000..ca5e668d0c81a --- /dev/null +++ b/packages/cubejs-testing/birdbox-fixtures/rbac-python/cube.py @@ -0,0 +1,62 @@ +# Cube configuration options: https://cube.dev/docs/config + +from cube import config + + +@config('context_to_roles') +def context_to_roles(context): + return context.get("securityContext", {}).get("auth", {}).get("roles", []) + + +def extract_matching_dicts(data): + matching_dicts = [] + keys = ['values', 'member', 'operator'] + + # Recursive function to traverse through the list or dictionary + def traverse(element): + if isinstance(element, dict): + # Check if any of the specified keys are in the dictionary + if any(key in element for key in keys): + matching_dicts.append(element) + # Traverse the dictionary values + for value in element.values(): + traverse(value) + elif isinstance(element, list): + # Traverse the list items + for item in element: + traverse(item) + + traverse(data) + return matching_dicts + + +@config('query_rewrite') +def query_rewrite(query: dict, ctx: dict) -> dict: + filters = extract_matching_dicts(query.get('filters')) + + for value in range(len(query['timeDimensions'])): + filters.append(query['timeDimensions'][value]['dateRange']) + + if not filters or None in filters: + raise Exception("Queries can't be run without a filter") + return query + + +@config('check_sql_auth') +def check_sql_auth(query: dict, username: str, password: str) -> dict: + if username == 'admin': + return { + 'username': 'admin', + 'password': password, + 'securityContext': { + 'auth': { + 'username': 'admin', + 'userAttributes': { + 'canHaveAdmin': True, + 'city': 'New York' + }, + 'roles': ['admin'] + } + } + } + raise Exception("Invalid username or password") diff --git a/packages/cubejs-testing/birdbox-fixtures/rbac-python/model/cubes/users.yaml b/packages/cubejs-testing/birdbox-fixtures/rbac-python/model/cubes/users.yaml new file mode 100644 index 0000000000000..7904a2199dee2 --- /dev/null +++ b/packages/cubejs-testing/birdbox-fixtures/rbac-python/model/cubes/users.yaml @@ -0,0 +1,54 @@ +cubes: + - name: users + sql_table: users + + measures: + - name: count + sql: id + type: count + + dimensions: + - name: city + sql: city + type: string + + - name: id + sql: id + type: number + primary_key: true + + access_policy: + - role: "*" + row_level: + filters: + - member: "{CUBE}.city" + operator: equals + values: ["{ security_context.auth.userAttributes.city }"] + - role: admin + conditions: + # This thing will fail if there's no auth info in the context + # Unfortunately, as of now, there's no way to write more complex expressions + # that would allow us to check for the existence of the auth object + - if: "{ security_context.auth.userAttributes.canHaveAdmin }" + row_level: + filters: + - or: + - and: + - member: "{CUBE}.city" + operator: notStartsWith + values: + - London + - "{ security_context.auth.userAttributes.city }" + # mixing string, dynamic values, integers and bools should not + # cause any compilation issues + - 4 + - true + - member: "city" + operator: notEquals + values: + - 'San Francisco' + - member: "{CUBE}.city" + operator: equals + values: + - "New York" + diff --git a/packages/cubejs-testing/src/birdbox.ts b/packages/cubejs-testing/src/birdbox.ts index b357abab4dd18..23810105e673f 100644 --- a/packages/cubejs-testing/src/birdbox.ts +++ b/packages/cubejs-testing/src/birdbox.ts @@ -262,7 +262,7 @@ export async function startBirdBoxFromContainer( if (pid !== null) { process.kill(pid, signal); } else { - process.stdout.write(`[Birdbox] Cannot kill Cube instance running in TEST_CUBE_HOST mode without TEST_CUBE_PID defined\n`); + process.stdout.write('[Birdbox] Cannot kill Cube instance running in TEST_CUBE_HOST mode without TEST_CUBE_PID defined\n'); throw new Error('Attempted to use killCube while running with TEST_CUBE_HOST'); } }, @@ -541,9 +541,15 @@ export async function startBirdBoxFromCli( } if (options.cubejsConfig) { + const configType = options.cubejsConfig.split('.').at(-1); + for (const configFile of ['cube.js', 'cube.py']) { + if (fs.existsSync(path.join(testDir, configFile))) { + fs.removeSync(path.join(testDir, configFile)); + } + } fs.copySync( path.join(process.cwd(), 'birdbox-fixtures', options.cubejsConfig), - path.join(testDir, 'cube.js') + path.join(testDir, `cube.${configType}`) ); } diff --git a/packages/cubejs-testing/test/__snapshots__/smoke-rbac.test.ts.snap b/packages/cubejs-testing/test/__snapshots__/smoke-rbac.test.ts.snap index 6543d2eeb65cb..43a7d007d863f 100644 --- a/packages/cubejs-testing/test/__snapshots__/smoke-rbac.test.ts.snap +++ b/packages/cubejs-testing/test/__snapshots__/smoke-rbac.test.ts.snap @@ -1,5 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Cube RBAC Engine [Python config] RBAC via SQL API [python config] SELECT * from users: users_python 1`] = ` +Array [ + Object { + "count": "551", + }, +] +`; + exports[`Cube RBAC Engine RBAC via REST API line_items hidden price_dim: line_items_view_no_policy_rest 1`] = ` Array [ Object { diff --git a/packages/cubejs-testing/test/smoke-rbac.test.ts b/packages/cubejs-testing/test/smoke-rbac.test.ts index 95e7dc5cbf723..36bf86514f2fc 100644 --- a/packages/cubejs-testing/test/smoke-rbac.test.ts +++ b/packages/cubejs-testing/test/smoke-rbac.test.ts @@ -13,40 +13,40 @@ import { JEST_BEFORE_ALL_DEFAULT_TIMEOUT, } from './smoke-tests'; +const PG_PORT = 5656; +let connectionId = 0; + +async function createPostgresClient(user: string, password: string) { + connectionId++; + const currentConnId = connectionId; + + console.debug(`[pg] new connection ${currentConnId}`); + + const conn = new PgClient({ + database: 'db', + port: PG_PORT, + host: '127.0.0.1', + user, + password, + ssl: false, + }); + conn.on('error', (err) => { + console.log(err); + }); + conn.on('end', () => { + console.debug(`[pg] end ${currentConnId}`); + }); + + await conn.connect(); + + return conn; +} + describe('Cube RBAC Engine', () => { jest.setTimeout(60 * 5 * 1000); let db: StartedTestContainer; let birdbox: BirdBox; - const pgPort = 5656; - let connectionId = 0; - - async function createPostgresClient(user: string, password: string) { - connectionId++; - const currentConnId = connectionId; - - console.debug(`[pg] new connection ${currentConnId}`); - - const conn = new PgClient({ - database: 'db', - port: pgPort, - host: '127.0.0.1', - user, - password, - ssl: false, - }); - conn.on('error', (err) => { - console.log(err); - }); - conn.on('end', () => { - console.debug(`[pg] end ${currentConnId}`); - }); - - await conn.connect(); - - return conn; - } - beforeAll(async () => { db = await PostgresDBRunner.startContainer({}); await PostgresDBRunner.loadEcom(db); @@ -64,7 +64,7 @@ describe('Cube RBAC Engine', () => { CUBEJS_DB_USER: 'test', CUBEJS_DB_PASS: 'test', // - CUBEJS_PG_SQL_PORT: `${pgPort}`, + CUBEJS_PG_SQL_PORT: `${PG_PORT}`, }, { schemaDir: 'rbac/model', @@ -345,3 +345,60 @@ describe('Cube RBAC Engine [dev mode]', () => { } }); }); + +describe('Cube RBAC Engine [Python config]', () => { + jest.setTimeout(60 * 5 * 1000); + let db: StartedTestContainer; + let birdbox: BirdBox; + + beforeAll(async () => { + db = await PostgresDBRunner.startContainer({}); + await PostgresDBRunner.loadEcom(db); + birdbox = await getBirdbox( + 'postgres', + { + ...DEFAULT_CONFIG, + CUBEJS_DEV_MODE: 'false', + NODE_ENV: 'production', + // + CUBEJS_DB_TYPE: 'postgres', + CUBEJS_DB_HOST: db.getHost(), + CUBEJS_DB_PORT: `${db.getMappedPort(5432)}`, + CUBEJS_DB_NAME: 'test', + CUBEJS_DB_USER: 'test', + CUBEJS_DB_PASS: 'test', + // + CUBEJS_PG_SQL_PORT: `${PG_PORT}`, + }, + { + schemaDir: 'rbac-python/model', + cubejsConfig: 'rbac-python/cube.py', + } + ); + }, JEST_BEFORE_ALL_DEFAULT_TIMEOUT); + + afterAll(async () => { + await birdbox.stop(); + await db.stop(); + }, JEST_AFTER_ALL_DEFAULT_TIMEOUT); + + describe('RBAC via SQL API [python config]', () => { + let connection: PgClient; + + beforeAll(async () => { + connection = await createPostgresClient('admin', 'admin_password'); + }); + + afterAll(async () => { + await connection.end(); + }, JEST_AFTER_ALL_DEFAULT_TIMEOUT); + + test('SELECT * from users', async () => { + const res = await connection.query('SELECT COUNT(city) as count from "users" HAVING (COUNT(1) > 0)'); + // const res = await connection.query('SELECT * FROM users limit 10'); + // This query should return all rows because of the `allow_all` statement + // It should also exclude the `created_at` dimension as per memberLevel policy + expect(res.rows).toMatchSnapshot('users_python'); + }); + }); +}); From 222cab897c289bfc929f217483e4905204bac12f Mon Sep 17 00:00:00 2001 From: Dmitriy Rusov Date: Thu, 12 Dec 2024 09:51:53 +0100 Subject: [PATCH 04/21] fix(cubestore): Allow create an index from expressions (#9006) --- .../src/streaming/kafka_post_processing.rs | 33 +++++++++++++++++-- rust/cubestore/cubestore/src/streaming/mod.rs | 18 ++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/rust/cubestore/cubestore/src/streaming/kafka_post_processing.rs b/rust/cubestore/cubestore/src/streaming/kafka_post_processing.rs index 4f47517e62e9e..79eb7f47d3592 100644 --- a/rust/cubestore/cubestore/src/streaming/kafka_post_processing.rs +++ b/rust/cubestore/cubestore/src/streaming/kafka_post_processing.rs @@ -470,16 +470,45 @@ impl KafkaPostProcessPlanner { } fn get_source_unique_column(&self, expr: &Expr) -> Result { + fn find_column_name(expr: &Expr) -> Result, CubeError> { + match expr { + Expr::Column(c) => Ok(Some(c.name.clone())), + Expr::Alias(e, _) => find_column_name(&**e), + Expr::ScalarUDF { args, .. } => { + let mut column_name: Option = None; + for arg in args { + if let Some(name) = find_column_name(arg)? { + if let Some(existing_name) = &column_name { + if existing_name != &name { + return Err(CubeError::user( + format!("Scalar function can only use a single column, expression: {:?}", expr), + )); + } + } else { + column_name = Some(name); + } + } + } + Ok(column_name) + } + _ => Ok(None), + } + } + let source_name = match expr { Expr::Column(c) => Ok(c.name.clone()), Expr::Alias(e, _) => match &**e { Expr::Column(c) => Ok(c.name.clone()), + Expr::ScalarUDF { .. } => find_column_name(expr)?.ok_or_else(|| { + CubeError::user(format!("Scalar function must contain at least one column, expression: {:?}", expr)) + }), _ => Err(CubeError::user(format!( - "Unique key can't be an expression in kafka streaming queries" + "Unique key can't be an expression in kafka streaming queries, expression: {:?}", + expr ))), }, _ => Err(CubeError::user( - "All expressions must have aliases in kafka streaming queries".to_string(), + format!("All expressions must have aliases in kafka streaming queries, expression: {:?}", expr), )), }?; diff --git a/rust/cubestore/cubestore/src/streaming/mod.rs b/rust/cubestore/cubestore/src/streaming/mod.rs index f73426df12b33..90c90ba0d59d1 100644 --- a/rust/cubestore/cubestore/src/streaming/mod.rs +++ b/rust/cubestore/cubestore/src/streaming/mod.rs @@ -1710,6 +1710,24 @@ mod tests { unique key (`message_id`, `an_id`) INDEX by_anonymous(`message_id`) location 'stream://kafka/EVENTS_BY_TYPE/0', 'stream://kafka/EVENTS_BY_TYPE/1'") .await .expect_err("Validation should fail"); + + service + .exec_query("CREATE TABLE test.events_by_type_6 (`ANONYMOUSID` text, `MESSAGEID` text, `FILTER_ID` int, `TIMESTAMP` timestamp, `TIMESTAMP_SECOND` timestamp) \ + WITH (\ + stream_offset = 'earliest', + select_statement = 'SELECT \ + ANONYMOUSID, MESSAGEID, FILTER_ID, TIMESTAMP, \ + PARSE_TIMESTAMP(FORMAT_TIMESTAMP(CONVERT_TZ(TIMESTAMP, \\'UTC\\', \\'UTC\\'), \\'yyyy-MM-dd\\'\\'T\\'\\'HH:mm:ss.000\\'), \\'yyyy-MM-dd\\'\\'T\\'\\'HH:mm:ss.SSS\\', \\'UTC\\') `TIMESTAMP_SECOND` \ + FROM EVENTS_BY_TYPE \ + WHERE PARSE_TIMESTAMP(TIMESTAMP, \\'yyyy-MM-dd\\'\\'T\\'\\'HH:mm:ss.SSSX\\', \\'UTC\\') >= PARSE_TIMESTAMP(\\'1970-01-01T01:00:00.000Z\\', \\'yyyy-MM-dd\\'\\'T\\'\\'HH:mm:ss.SSSX\\', \\'UTC\\') \ + AND + PARSE_TIMESTAMP(TIMESTAMP, \\'yyyy-MM-dd\\'\\'T\\'\\'HH:mm:ss.SSSX\\', \\'UTC\\') < PARSE_TIMESTAMP(\\'1970-01-01T01:10:00.000Z\\', \\'yyyy-MM-dd\\'\\'T\\'\\'HH:mm:ss.SSSX\\', \\'UTC\\') \ + \ + '\ + ) \ + unique key (`ANONYMOUSID`, `MESSAGEID`, `FILTER_ID`, `TIMESTAMP`, `TIMESTAMP_SECOND`) INDEX by_anonymous(`ANONYMOUSID`, `TIMESTAMP_SECOND`,`TIMESTAMP`) location 'stream://kafka/EVENTS_BY_TYPE/0', 'stream://kafka/EVENTS_BY_TYPE/1'") + .await + .unwrap(); }) .await; } From fd4ccff8a031d81e12f03d6b8c2bd0c65612c9c8 Mon Sep 17 00:00:00 2001 From: Konstantin Burkalev Date: Thu, 12 Dec 2024 14:33:33 +0200 Subject: [PATCH 05/21] chore(ci): fix broken integration-smoke tests (#9039) --- .github/workflows/push.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 7431cda4d106d..4f3c47359f3c6 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -396,6 +396,7 @@ jobs: strategy: matrix: node-version: [ 20.x ] + python-version: [ 3.11 ] fail-fast: false steps: @@ -421,6 +422,10 @@ jobs: uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "dir=$(yarn cache dir)" >> "$GITHUB_OUTPUT" @@ -448,6 +453,11 @@ jobs: uses: GoodManWEN/oracle-client-action@main - name: Build client run: yarn build + - name: Build cubejs-backend-native (with Python) + run: yarn run native:build-release-python + working-directory: ./packages/cubejs-backend-native + env: + PYO3_PYTHON: python${{ matrix.python-version }} - name: Lerna tsc run: yarn tsc - name: Download cubestored-x86_64-unknown-linux-gnu-release artifact From 546086fb3c979b3605a68f910670b91bf662f1f5 Mon Sep 17 00:00:00 2001 From: Igor Lukanin Date: Thu, 12 Dec 2024 16:51:55 +0100 Subject: [PATCH 06/21] =?UTF-8?q?docs:=20Fix=20broken=20build=20?= =?UTF-8?q?=F0=9F=A4=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://mdxjs.com/docs/troubleshooting-mdx/#could-not-parse-importexports-with-acorn-error --- docs/pages/reference/configuration/environment-variables.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/reference/configuration/environment-variables.mdx b/docs/pages/reference/configuration/environment-variables.mdx index 044efede3b1e6..dba5d5f3074f7 100644 --- a/docs/pages/reference/configuration/environment-variables.mdx +++ b/docs/pages/reference/configuration/environment-variables.mdx @@ -563,8 +563,8 @@ The timeout value for any queries made to the database by Cube. There's a hard limit of 20 minutes for queries that ingest data into Cube Store -when pre-aggregations are built. If you bump into this limit, consider using an -export bucket and splitting pre-aggregations into partitions. +when pre-aggregations are built. If you bump into this limit, consider using +an export bucket and splitting pre-aggregations into partitions. From 6ea1d0f86a88f31008c4fedab197310eccb39b78 Mon Sep 17 00:00:00 2001 From: morgan-at-cube <153563892+morgan-at-cube@users.noreply.github.com> Date: Thu, 12 Dec 2024 09:42:28 -0800 Subject: [PATCH 07/21] Update caching.mdx (#7759) Rewording caching types, especially clarifying in-memory cache --- docs/pages/product/caching.mdx | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/docs/pages/product/caching.mdx b/docs/pages/product/caching.mdx index 87a177e6e15de..a9f2b6f73f6e1 100644 --- a/docs/pages/product/caching.mdx +++ b/docs/pages/product/caching.mdx @@ -257,21 +257,26 @@ versions. Any query that is fulfilled by Cube will use one of the following cache types: -- **[Pre-aggregations](#pre-aggregations) in Cube Store.** This is the most -advantageous and performant option. +- **[Pre-aggregations](#pre-aggregations) in Cube Store.** This cache type +indicates that the query utilized existing pre-aggregations in Cube Store, +so it did not need to go to the database for processing. - **Pre-aggregations in Cube Store with a suboptimal query plan.** This cache -type indicates that queries still benefit from pre-aggregations in Cube Store -but it's possible to get a performance boost by [using indexes][ref-indexes]. +type indicates that the query ultilized pre-aggregations in Cube Store, +but that it's possible to get a performance boost by [using indexes][ref-indexes]. - **Pre-aggregations in the data source.** This cache type indicates that -queries don't benefit from pre-aggregations in Cube Store and it's possible -to get a massive performance boost by using Cube Store as [pre-aggregation +the query utilized pre-aggregations from in the upstream data source. +These queries could gain a performance boost by using Cube Store as [pre-aggregation storage][ref-storage]. -- **[In-memory cache.](#in-memory-cache)** This cache type indicates that -queries don't benefit from pre-aggregations at all. Queries directly hit the -upstream data source and in-memory cache is used to speed up the execution of -identical queries that arrive within a short period of time. -- **No cache.** This cache type indicates queries that directly hit the -upstream data source and have the worst performance possible. +- **[In-memory cache.](#in-memory-cache)** This cache type indicates that the +results were retrieved from Cube's in-memory cache. All query results +are stored in Cube's in-memory cache, and if the same query is +run within a certain time frame, the results will be retrieved from in-memory +cache instead of being processed on the database or in Cube Store. This is the +fastest query retrieval method, but it requires that the exact same query was +run very recently. +- **No cache.** This cache type indicates that the query was processed in the upstream +data source and was not accelrated using pre-aggregations. These queries could have +a significant performance boost if pre-aggregations and Cube Store were utilized. In [Query History][ref-query-history] and throughout Cube Cloud, colored bolt icons are used to indicate the cache type. Also, [Performance From 369b02e7966597e089493012169ce83f3d4eeacd Mon Sep 17 00:00:00 2001 From: morgan-at-cube <153563892+morgan-at-cube@users.noreply.github.com> Date: Thu, 12 Dec 2024 09:44:23 -0800 Subject: [PATCH 08/21] docs: Update pre-aggregations.mdx (#8219) Mention that you can use CRON to trigger a pre-agg at a specific time, and put that info next to the exisitng link to the refresh_key reference docs. --- docs/pages/reference/data-model/pre-aggregations.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/reference/data-model/pre-aggregations.mdx b/docs/pages/reference/data-model/pre-aggregations.mdx index 986076437d94c..941d7a2b5d6f6 100644 --- a/docs/pages/reference/data-model/pre-aggregations.mdx +++ b/docs/pages/reference/data-model/pre-aggregations.mdx @@ -921,7 +921,7 @@ cubes: -For possible `every` parameter values please refer to +To have a pre-aggregation rebuild at a specific time of day, you can use a CRON string with some limitations. For more details about values that can be used with the `every` parameter, please refer to the [`refreshKey`][ref-cube-refreshkey] documentation. You can also use `every` with `sql`: From f8c3d3ac87282004d8ccc028a4ffb0f2409e318c Mon Sep 17 00:00:00 2001 From: morgan-at-cube <153563892+morgan-at-cube@users.noreply.github.com> Date: Thu, 12 Dec 2024 09:45:09 -0800 Subject: [PATCH 09/21] docs: Update context.mdx (#8900) --- docs/pages/product/auth/context.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/product/auth/context.mdx b/docs/pages/product/auth/context.mdx index 3b14eb867e58a..641497f7aee37 100644 --- a/docs/pages/product/auth/context.mdx +++ b/docs/pages/product/auth/context.mdx @@ -220,7 +220,7 @@ def masked(sql, security_context): if is_trusted_team: return sql else: - return "\"'--- masked ---'\"" + return "'--- masked ---'" ``` From a69c28f524fa0625b825b98a38e7f5a211a98f74 Mon Sep 17 00:00:00 2001 From: Maxim Date: Thu, 12 Dec 2024 09:58:16 -0800 Subject: [PATCH 10/21] fix(api-gateway): allow switch sql user when the new user is the same (#9037) --- packages/cubejs-api-gateway/src/sql-server.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/cubejs-api-gateway/src/sql-server.ts b/packages/cubejs-api-gateway/src/sql-server.ts index 5ab0318b29f55..32e7d37e1e19c 100644 --- a/packages/cubejs-api-gateway/src/sql-server.ts +++ b/packages/cubejs-api-gateway/src/sql-server.ts @@ -301,7 +301,11 @@ export class SQLServer { protected createDefaultCanSwitchSqlUserFn(options: SQLServerOptions): CanSwitchSQLUserFn { const superUser = options.sqlSuperUser || getEnv('sqlSuperUser'); - return async (current: string | null, _user: string) => { + return async (current: string | null, newUser: string) => { + if (current === newUser) { + return true; + } + if (superUser) { return current === superUser; } From 368671fd1b53b2ed5ad8df6af113492982f23c0c Mon Sep 17 00:00:00 2001 From: Alex Qyoun-ae <4062971+MazterQyou@users.noreply.github.com> Date: Fri, 13 Dec 2024 02:08:46 +0400 Subject: [PATCH 11/21] feat(cubesql): Basic VALUES support in rewrite engine (#9041) --- rust/cubesql/cubesql/src/compile/mod.rs | 15 +++++++++++++++ .../cubesql/src/compile/rewrite/converter.rs | 14 ++++++++++---- rust/cubesql/cubesql/src/compile/rewrite/mod.rs | 3 +++ ...sql__compile__tests__values_literal_table.snap | 11 +++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__values_literal_table.snap diff --git a/rust/cubesql/cubesql/src/compile/mod.rs b/rust/cubesql/cubesql/src/compile/mod.rs index e0b4974a99166..2da928a683930 100644 --- a/rust/cubesql/cubesql/src/compile/mod.rs +++ b/rust/cubesql/cubesql/src/compile/mod.rs @@ -16333,4 +16333,19 @@ LIMIT {{ limit }}{% endif %}"#.to_string(), .sql; assert!(sql.contains(" IS NULL DESC, ")); } + + #[tokio::test] + async fn test_values_literal_table() -> Result<(), CubeError> { + insta::assert_snapshot!( + "values_literal_table", + execute_query( + r#"SELECT a AS a, b AS b FROM (VALUES (1, 2), (3, 4), (5, 6)) AS t(a, b)"# + .to_string(), + DatabaseProtocol::PostgreSQL + ) + .await? + ); + + Ok(()) + } } diff --git a/rust/cubesql/cubesql/src/compile/rewrite/converter.rs b/rust/cubesql/cubesql/src/compile/rewrite/converter.rs index 99d5057e706f3..5b028b24d37fd 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/converter.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/converter.rs @@ -26,7 +26,7 @@ use crate::{ SortExprAsc, SortExprNullsFirst, SubqueryTypes, TableScanFetch, TableScanProjection, TableScanSourceTableName, TableScanTableName, TableUDFExprFun, TimeDimensionDateRange, TimeDimensionGranularity, TimeDimensionName, TryCastExprDataType, UnionAlias, - WindowFunctionExprFun, WindowFunctionExprWindowFrame, WrappedSelectAlias, + ValuesValues, WindowFunctionExprFun, WindowFunctionExprWindowFrame, WrappedSelectAlias, WrappedSelectDistinct, WrappedSelectJoinJoinType, WrappedSelectLimit, WrappedSelectOffset, WrappedSelectPushToCube, WrappedSelectSelectType, WrappedSelectType, @@ -772,12 +772,13 @@ impl LogicalPlanToLanguageConverter { self.graph .add(LogicalPlanLanguage::Limit([skip, fetch, input])) } + LogicalPlan::Values(values) => { + let values = add_data_node!(self, values.values, ValuesValues); + self.graph.add(LogicalPlanLanguage::Values([values])) + } LogicalPlan::CreateExternalTable { .. } => { panic!("CreateExternalTable is not supported"); } - LogicalPlan::Values { .. } => { - panic!("Values is not supported"); - } LogicalPlan::Explain { .. } => { panic!("Explain is not supported"); } @@ -2283,6 +2284,11 @@ impl LanguageToLogicalPlanConverter { LogicalPlan::Distinct(Distinct { input }) } + LogicalPlanLanguage::Values(values) => { + let values = match_data_node!(node_by_id, values[0], ValuesValues); + + LogicalPlanBuilder::values(values)?.build()? + } x => panic!("Unexpected logical plan node: {:?}", x), }) } diff --git a/rust/cubesql/cubesql/src/compile/rewrite/mod.rs b/rust/cubesql/cubesql/src/compile/rewrite/mod.rs index 5473a4548f29a..c368ef8c1f4c1 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/mod.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/mod.rs @@ -157,6 +157,9 @@ crate::plan_to_language! { location: String, has_header: bool, }, + Values { + values: Vec>, + }, Extension { node: Arc, }, diff --git a/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__values_literal_table.snap b/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__values_literal_table.snap new file mode 100644 index 0000000000000..511bbe78035cf --- /dev/null +++ b/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__values_literal_table.snap @@ -0,0 +1,11 @@ +--- +source: cubesql/src/compile/mod.rs +expression: "execute_query(r#\"SELECT a AS a, b AS b FROM (VALUES (1, 2), (3, 4), (5, 6)) AS t(a, b)\"#.to_string(),\nDatabaseProtocol::PostgreSQL).await?" +--- ++---+---+ +| a | b | ++---+---+ +| 1 | 2 | +| 3 | 4 | +| 5 | 6 | ++---+---+ From 3fbae301afdf55802ee0dff6d279b3e236e5e143 Mon Sep 17 00:00:00 2001 From: Pavel Tiunov Date: Thu, 12 Dec 2024 16:18:39 -0800 Subject: [PATCH 12/21] docs: Chasm and fan traps --- docs/pages/reference/data-model/joins.mdx | 110 ++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/docs/pages/reference/data-model/joins.mdx b/docs/pages/reference/data-model/joins.mdx index 295dd476082e7..656d15d83f4e0 100644 --- a/docs/pages/reference/data-model/joins.mdx +++ b/docs/pages/reference/data-model/joins.mdx @@ -404,6 +404,116 @@ cubes: +## Chasm and fan traps + +Cube automatically detects chasm and fan traps based on the `many_to_one` and `one_to_many` relationships defined in join. +When detected, Cube generates a deduplication query that evaluates all distinct primary keys within the multiplied measure's cube and then joins distinct primary keys to this cube on itself to calculate the aggregation result. +If there's more than one multiplied measure in a query, then such query is generated for every such multiplied measure, and results are joined. + +Let's consider an example data model: + + + +```javascript +cube(`orders`, { + sql_table: `orders` + + dimensions: { + id: { + sql: `id`, + type: `number`, + primary_key: true + }, + city: { + sql: `city`, + type: `string` + } + }, + + joins: { + customers: { + relationship: `many_to_one`, + sql: `${CUBE}.customer_id = ${customers.id}`, + }, + }, +}); + +cube(`customers`, { + sql_table: `customers` + + measures: { + count: { + type: `count`, + } + }, + + dimensions: { + id: { + sql: `id`, + type: `number`, + primary_key: true + } + } +}); +``` + +```yaml +cubes: + - name: orders + sql_table: orders + + dimensions: + - name: id + sql: id + type: number + primary_key: true + - name: city + sql: city + type: string + + joins: + - name: customers + relationship: many_to_one + sql: "{orders}.customer_id = {customers.id}" + +- name: customers + sql_table: customers + + dimensions: + - name: id + sql: id + type: number + primary_key: true + + measures: + - name: average_age + sql: age + type: avg + +``` + + + +If we try to query `customers.average_age` by `orders.city`, the Cube detects that the `average_age` measure in the `customers` cube would be multiplied by `orders` to `customers` and would generate SQL similar to: + +```sql +SELECT + "keys"."orders__city", + avg("customers_key__customers".age) "customers__average_age" +FROM + ( + SELECT + DISTINCT "customers_key__orders".city "orders__city", + "customers_key__customers".id "customers__id" + FROM + orders AS "customers_key__orders" + LEFT JOIN customers AS "customers_key__customers" ON "customers_key__orders".customer_id = "customers_key__customers".id + ) AS "keys" + LEFT JOIN customers AS "customers_key__customers" ON "keys"."customers__id" = "customers_key__customers".id +GROUP BY + 1 +``` + ## CUBE reference When you have several joined cubes, you should accurately use columns’ names to From ad4e8e3872307ab77e035709e5208b0191f87f5b Mon Sep 17 00:00:00 2001 From: Alex Vasilev Date: Thu, 12 Dec 2024 17:11:50 -0800 Subject: [PATCH 13/21] fix(schema-compiler): join relationship aliases --- .../src/scaffolding/formatters/BaseSchemaFormatter.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/cubejs-schema-compiler/src/scaffolding/formatters/BaseSchemaFormatter.ts b/packages/cubejs-schema-compiler/src/scaffolding/formatters/BaseSchemaFormatter.ts index d1981ffed2ffe..02227ed87dcbd 100644 --- a/packages/cubejs-schema-compiler/src/scaffolding/formatters/BaseSchemaFormatter.ts +++ b/packages/cubejs-schema-compiler/src/scaffolding/formatters/BaseSchemaFormatter.ts @@ -13,8 +13,11 @@ import { toSnakeCase } from '../utils'; const JOIN_RELATIONSHIP_MAP = { hasOne: 'one_to_one', + has_one: 'one_to_one', hasMany: 'one_to_many', + has_many: 'one_to_many', belongsTo: 'many_to_one', + belongs_to: 'many_to_one', }; export type SchemaFile = { @@ -107,7 +110,7 @@ export abstract class BaseSchemaFormatter { let table = `${ tableSchema.schema?.length ? `${this.escapeName(tableSchema.schema)}.` : '' }${this.escapeName(tableSchema.table)}`; - + if (this.options.catalog) { table = `${this.escapeName(this.options.catalog)}.${table}`; } @@ -126,7 +129,7 @@ export abstract class BaseSchemaFormatter { : { sql: `SELECT * FROM ${table}`, }; - + return { cube: tableSchema.cube, ...sqlOption, @@ -139,7 +142,7 @@ export abstract class BaseSchemaFormatter { j.thisTableColumn )} = ${this.cubeReference(j.cubeToJoin)}.${this.escapeName(j.columnToJoin)}`, relationship: this.options.snakeCase - ? JOIN_RELATIONSHIP_MAP[j.relationship] + ? (JOIN_RELATIONSHIP_MAP[j.relationship] ?? j.relationship) : j.relationship, }, })) From d2c2fcdaf8944ea7dd27e73b63c0b151c317022e Mon Sep 17 00:00:00 2001 From: Ian Weller Date: Fri, 13 Dec 2024 06:26:30 -0500 Subject: [PATCH 14/21] feat(dremio-driver): Add Dremio Cloud Support (#8956) * feat: Add Dremio Cloud Support - Adds support to cubejs-dremio-driver for Dremio Cloud - Adds support for personal access tokens for Dremio Server * feat: Introduce dremioAuthToken config - Adds the dremioAuthToken config to support the dremio cloud driver --------- Co-authored-by: Konstantin Burkalev --- packages/cubejs-backend-shared/src/env.ts | 17 +++++++ packages/cubejs-dremio-driver/README.md | 19 ++++++- .../driver/DremioDriver.js | 51 +++++++++++++++---- 3 files changed, 75 insertions(+), 12 deletions(-) diff --git a/packages/cubejs-backend-shared/src/env.ts b/packages/cubejs-backend-shared/src/env.ts index a8f5563555bb9..3096fefae7796 100644 --- a/packages/cubejs-backend-shared/src/env.ts +++ b/packages/cubejs-backend-shared/src/env.ts @@ -1647,6 +1647,23 @@ const variables: Record any> = { ] ), + /** **************************************************************** + * Dremio Driver * + ***************************************************************** */ + + /** + * Dremio Auth Token + */ + dremioAuthToken: ({ + dataSource, + }: { + dataSource: string, + }) => ( + process.env[ + keyByDataSource('CUBEJS_DB_DREMIO_AUTH_TOKEN', dataSource) + ] + ), + /** **************************************************************** * Cube Store Driver * ***************************************************************** */ diff --git a/packages/cubejs-dremio-driver/README.md b/packages/cubejs-dremio-driver/README.md index c8a50533b08fb..c534901156385 100644 --- a/packages/cubejs-dremio-driver/README.md +++ b/packages/cubejs-dremio-driver/README.md @@ -9,11 +9,26 @@ Pure Javascript Dremio driver. +## Dremio Cloud + +To use this driver with [Dremio Cloud](https://docs.dremio.com/cloud/reference/api/), use the following setup: + +| Environment Variable | Value | +| --------------------------- | -------------------------------------------------- | +| CUBEJS_DB_TYPE | dremio | +| CUBEJS_DB_URL | https://api.dremio.cloud/v0/projects/${PROJECT_ID} | +| CUBEJS_DB_NAME | ${DB_NAME} | +| CUBEJS_DB_DREMIO_AUTH_TOKEN | ${PERSONAL_ACCESS_TOKEN} | + +> [!NOTE] +> When `CUBEJS_DB_URL` is set it takes precedence over `CUBEJS_DB_HOST` and it +> is assumed that the driver is connecting to the Dremio Cloud API. + ## Support -This package is **community supported** and should be used at your own risk. +This package is **community supported** and should be used at your own risk. -While the Cube Dev team is happy to review and accept future community contributions, we don't have active plans for further development. This includes bug fixes unless they affect different parts of Cube.js. **We're looking for maintainers for this package.** If you'd like to become a maintainer, please contact us in Cube.js Slack. +While the Cube Dev team is happy to review and accept future community contributions, we don't have active plans for further development. This includes bug fixes unless they affect different parts of Cube.js. **We're looking for maintainers for this package.** If you'd like to become a maintainer, please contact us in Cube.js Slack. ## License diff --git a/packages/cubejs-dremio-driver/driver/DremioDriver.js b/packages/cubejs-dremio-driver/driver/DremioDriver.js index b825f570586bf..300f9dc795d41 100644 --- a/packages/cubejs-dremio-driver/driver/DremioDriver.js +++ b/packages/cubejs-dremio-driver/driver/DremioDriver.js @@ -49,6 +49,14 @@ class DremioDriver extends BaseDriver { assertDataSource('default'); this.config = { + dbUrl: + config.dbUrl || + getEnv('dbUrl', { dataSource }) || + '', + dremioAuthToken: + config.dremioAuthToken || + getEnv('dremioAuthToken', { dataSource }) || + '', host: config.host || getEnv('dbHost', { dataSource }) || @@ -80,11 +88,20 @@ class DremioDriver extends BaseDriver { getEnv('dbPollMaxInterval', { dataSource }) ) * 1000, }; - const protocol = (this.config.ssl === true || this.config.ssl === 'true') - ? 'https' - : 'http'; - this.config.url = - `${protocol}://${this.config.host}:${this.config.port}`; + + if (this.config.dbUrl) { + this.config.url = this.config.dbUrl; + this.config.apiVersion = ''; + if (this.config.dremioAuthToken === '') { + throw new Error('dremioAuthToken is blank'); + } + } else { + const protocol = (this.config.ssl === true || this.config.ssl === 'true') + ? 'https' + : 'http'; + this.config.url = `${protocol}://${this.config.host}:${this.config.port}`; + this.config.apiVersion = '/api/v3'; + } } /** @@ -103,6 +120,20 @@ class DremioDriver extends BaseDriver { * @protected */ async getToken() { + if (this.config.dremioAuthToken) { + const bearerToken = `Bearer ${this.config.dremioAuthToken}`; + await axios.get( + `${this.config.url}${this.config.apiVersion}/catalog`, + { + headers: { + Authorization: bearerToken + }, + }, + ); + + return bearerToken; + } + if (this.authToken && this.authToken.expires > new Date().getTime()) { return `_dremio${this.authToken.token}`; } @@ -129,7 +160,7 @@ class DremioDriver extends BaseDriver { return axios.request({ method, - url: `${this.config.url}${url}`, + url: `${this.config.url}${this.config.apiVersion}${url}`, headers: { Authorization: token }, @@ -141,7 +172,7 @@ class DremioDriver extends BaseDriver { * @protected */ async getJobStatus(jobId) { - const { data } = await this.restDremioQuery('get', `/api/v3/job/${jobId}`); + const { data } = await this.restDremioQuery('get', `/job/${jobId}`); if (data.jobState === 'FAILED') { throw new Error(data.errorMessage); @@ -162,7 +193,7 @@ class DremioDriver extends BaseDriver { * @protected */ async getJobResults(jobId, limit = 500, offset = 0) { - return this.restDremioQuery('get', `/api/v3/job/${jobId}/results?offset=${offset}&limit=${limit}`); + return this.restDremioQuery('get', `/job/${jobId}/results?offset=${offset}&limit=${limit}`); } /** @@ -171,7 +202,7 @@ class DremioDriver extends BaseDriver { * @return {Promise<*>} */ async executeQuery(sql) { - const { data } = await this.restDremioQuery('post', '/api/v3/sql', { sql }); + const { data } = await this.restDremioQuery('post', '/sql', { sql }); return data.id; } @@ -216,7 +247,7 @@ class DremioDriver extends BaseDriver { } async refreshTablesSchema(path) { - const { data } = await this.restDremioQuery('get', `/api/v3/catalog/by-path/${path}`); + const { data } = await this.restDremioQuery('get', `/catalog/by-path/${path}`); if (!data || !data.children) { return true; } From 0bba1b97fa29d9c7f95f81af2ef00ccc538273b5 Mon Sep 17 00:00:00 2001 From: Mikhail Cheshkov Date: Fri, 13 Dec 2024 16:04:21 +0200 Subject: [PATCH 15/21] test: Bump default PostgreSQL image to 12.22 (#9045) --- .../test/integration/postgres/PostgresDBRunner.js | 2 +- .../cubejs-testing-shared/src/db-container-runners/postgres.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cubejs-schema-compiler/test/integration/postgres/PostgresDBRunner.js b/packages/cubejs-schema-compiler/test/integration/postgres/PostgresDBRunner.js index 5e8ded3aec0f3..84dc36df77372 100644 --- a/packages/cubejs-schema-compiler/test/integration/postgres/PostgresDBRunner.js +++ b/packages/cubejs-schema-compiler/test/integration/postgres/PostgresDBRunner.js @@ -125,7 +125,7 @@ export class PostgresDBRunner extends BaseDbRunner { } async containerLazyInit() { - const version = process.env.TEST_PGSQL_VERSION || '9.6.8'; + const version = process.env.TEST_PGSQL_VERSION || '12.22'; return new GenericContainer(`postgres:${version}`) .withEnvironment({ diff --git a/packages/cubejs-testing-shared/src/db-container-runners/postgres.ts b/packages/cubejs-testing-shared/src/db-container-runners/postgres.ts index 255fc1bdd1ef1..8fc359792d275 100644 --- a/packages/cubejs-testing-shared/src/db-container-runners/postgres.ts +++ b/packages/cubejs-testing-shared/src/db-container-runners/postgres.ts @@ -5,7 +5,7 @@ import { DbRunnerAbstract, DBRunnerContainerOptions } from './db-runner.abstract export class PostgresDBRunner extends DbRunnerAbstract { public static startContainer(options: DBRunnerContainerOptions) { - const version = process.env.TEST_PGSQL_VERSION || options.version || '9.6.8'; + const version = process.env.TEST_PGSQL_VERSION || options.version || '12.22'; const container = new GenericContainer(`postgres:${version}`) .withEnvironment({ From fc7e0c52b0cfc462cbdabfb5d519b092a0d8055d Mon Sep 17 00:00:00 2001 From: Pavel Tiunov Date: Fri, 13 Dec 2024 08:19:02 -0800 Subject: [PATCH 16/21] docs: Chasm and fan traps --- docs/pages/reference/data-model/joins.mdx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/pages/reference/data-model/joins.mdx b/docs/pages/reference/data-model/joins.mdx index 656d15d83f4e0..c34d6f8dab133 100644 --- a/docs/pages/reference/data-model/joins.mdx +++ b/docs/pages/reference/data-model/joins.mdx @@ -409,6 +409,9 @@ cubes: Cube automatically detects chasm and fan traps based on the `many_to_one` and `one_to_many` relationships defined in join. When detected, Cube generates a deduplication query that evaluates all distinct primary keys within the multiplied measure's cube and then joins distinct primary keys to this cube on itself to calculate the aggregation result. If there's more than one multiplied measure in a query, then such query is generated for every such multiplied measure, and results are joined. +Cube solves for chasm and fan traps during query time. +If there's pre-aggregregation that fits measure multiplication requirements it'd be leveraged to serve such a query. +Such pre-aggregations and queries are always considered non-additive for the purpose of pre-aggregation matching. Let's consider an example data model: From a56462e9637048f934440ab058c29016c5d45ed9 Mon Sep 17 00:00:00 2001 From: waralexrom <108349432+waralexrom@users.noreply.github.com> Date: Sat, 14 Dec 2024 22:08:22 +0100 Subject: [PATCH 17/21] chore(sqlplanner): Sql planner another schema refactoring (#9038) * template engine * in work * in work * multi stage and running total pass tests * update * update * fix(cubeplanner): Fixes to pass the tests * some fixes * views support * evaluation_node refactoring * in work * in work * in work * update * update --- .../src/adapter/BaseQuery.js | 41 +- .../src/adapter/ParamAllocator.ts | 4 + .../src/compiler/CubeSymbols.js | 2 +- .../clickhouse/ClickHouseDbRunner.ts | 2 +- .../postgres/sql-generation-logic.test.ts | 4 +- .../postgres/sql-generation.test.ts | 10 +- .../test/unit/base-query.test.ts | 4 +- .../test/unit/pre-aggregations.test.ts | 4 +- .../src/cube_bridge/base_query_options.rs | 1 + .../src/cube_bridge/base_tools.rs | 7 + .../src/cube_bridge/measure_definition.rs | 9 + .../src/cube_bridge/memeber_sql.rs | 57 +-- .../cubesqlplanner/src/plan/builder/select.rs | 90 ++++- .../cubesqlplanner/src/plan/cte.rs | 6 +- .../cubesqlplanner/src/plan/expression.rs | 31 +- .../cubesqlplanner/src/plan/filter.rs | 34 +- .../cubesqlplanner/src/plan/from.rs | 49 +-- .../cubesqlplanner/src/plan/join.rs | 196 ++++++---- .../cubesqlplanner/src/plan/mod.rs | 6 +- .../cubesqlplanner/src/plan/query_plan.rs | 11 +- .../cubesqlplanner/src/plan/schema.rs | 146 ------- .../cubesqlplanner/src/plan/schema/column.rs | 57 +++ .../cubesqlplanner/src/plan/schema/mod.rs | 5 + .../cubesqlplanner/src/plan/schema/schema.rs | 67 ++++ .../cubesqlplanner/src/plan/select.rs | 46 +-- .../cubesqlplanner/src/plan/time_series.rs | 43 +++ .../cubesqlplanner/src/plan/union.rs | 18 +- .../cubesqlplanner/src/planner/base_cube.rs | 32 +- .../src/planner/base_dimension.rs | 29 +- .../src/planner/base_join_condition.rs | 22 +- .../src/planner/base_measure.rs | 49 ++- .../cubesqlplanner/src/planner/base_member.rs | 15 +- .../cubesqlplanner/src/planner/base_query.rs | 12 +- .../src/planner/base_time_dimension.rs | 55 ++- .../src/planner/filter/base_filter.rs | 166 ++++++-- .../src/planner/filter/compiler.rs | 6 +- .../src/planner/filter/filter_operator.rs | 15 + .../cubesqlplanner/src/planner/filter/mod.rs | 1 + .../src/planner/granularity_helper.rs | 149 ++++++++ .../cubesqlplanner/src/planner/mod.rs | 4 +- .../src/planner/params_allocator.rs | 45 ++- .../full_key_query_aggregate_planner.rs | 129 ++++--- .../src/planner/planners/join_planner.rs | 38 +- .../planners/multi_stage/applied_state.rs | 187 +++++++-- .../planner/planners/multi_stage/member.rs | 174 +++++++++ .../multi_stage/member_query_planner.rs | 356 +++++++++++++----- .../src/planner/planners/multi_stage/mod.rs | 2 + .../planners/multi_stage/query_description.rs | 24 +- .../planners/multi_stage_query_planner.rs | 342 ++++++++++++++--- .../multiplied_measures_query_planner.rs | 222 ++++++++--- .../src/planner/planners/order_planner.rs | 2 +- .../planner/planners/simple_query_planer.rs | 23 +- .../src/planner/query_properties.rs | 98 ++--- .../cubesqlplanner/src/planner/query_tools.rs | 24 +- .../collectors/cube_names_collector.rs | 61 +++ .../collectors/has_cumulative_members.rs | 48 +++ .../collectors/has_multi_stage_members.rs | 45 ++- .../collectors/join_hints_collector.rs | 68 ++-- .../collectors/member_childs_collector.rs | 60 +-- .../planner/sql_evaluator/collectors/mod.rs | 8 +- .../multiplied_measures_collector.rs | 116 ++++-- .../src/planner/sql_evaluator/compiler.rs | 72 ++-- .../src/planner/sql_evaluator/dependecy.rs | 144 ++++--- .../planner/sql_evaluator/evaluation_node.rs | 71 ---- .../src/planner/sql_evaluator/mod.rs | 11 +- .../sql_evaluator/references_builder.rs | 310 +++++++++++++++ .../src/planner/sql_evaluator/sql_call.rs | 158 ++++++++ .../sql_node_transformers/mod.rs | 3 - .../sql_node_transformers/set_schema.rs | 86 ----- .../sql_evaluator/sql_nodes/auto_prefix.rs | 49 ++- .../sql_evaluator/sql_nodes/evaluate_sql.rs | 26 +- .../sql_evaluator/sql_nodes/factory.rs | 197 +++++++--- .../sql_evaluator/sql_nodes/final_measure.rs | 18 +- .../sql_nodes/leaf_time_dimension.rs | 55 +++ .../sql_evaluator/sql_nodes/measure_filter.rs | 16 +- .../planner/sql_evaluator/sql_nodes/mod.rs | 7 + .../sql_nodes/multi_stage_rank.rs | 17 +- .../sql_nodes/multi_stage_window.rs | 10 +- .../sql_nodes/render_references.rs | 42 +-- .../sql_evaluator/sql_nodes/rolling_window.rs | 66 ++++ .../sql_evaluator/sql_nodes/root_processor.rs | 14 +- .../sql_evaluator/sql_nodes/sql_node.rs | 10 +- .../sql_evaluator/sql_nodes/time_shift.rs | 10 +- .../sql_nodes/ungroupped_measure.rs | 62 +++ .../ungroupped_query_final_measure.rs | 69 ++++ .../src/planner/sql_evaluator/sql_visitor.rs | 76 +--- .../sql_evaluator/symbols/cube_symbol.rs | 50 +-- .../sql_evaluator/symbols/dimension_symbol.rs | 49 ++- .../sql_evaluator/symbols/measure_symbol.rs | 136 +++++-- .../sql_evaluator/symbols/member_symbol.rs | 82 +++- .../symbols/member_symbol_type.rs | 26 -- .../src/planner/sql_evaluator/symbols/mod.rs | 4 - .../sql_evaluator/symbols/simple_sql.rs | 74 ---- .../sql_evaluator/symbols/symbol_factory.rs | 10 +- .../src/planner/sql_evaluator/visitor.rs | 53 +-- .../src/planner/sql_templates/filter.rs | 49 ++- .../src/planner/sql_templates/plan.rs | 69 +--- .../src/planner/visitor_context.rs | 45 +-- 98 files changed, 4037 insertions(+), 1786 deletions(-) delete mode 100644 rust/cubesqlplanner/cubesqlplanner/src/plan/schema.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/plan/schema/column.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/plan/schema/mod.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/plan/schema/schema.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/plan/time_series.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/granularity_helper.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multi_stage/member.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/cube_names_collector.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/has_cumulative_members.rs delete mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/evaluation_node.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/references_builder.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_call.rs delete mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_node_transformers/mod.rs delete mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_node_transformers/set_schema.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/leaf_time_dimension.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/rolling_window.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/ungroupped_measure.rs create mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/ungroupped_query_final_measure.rs delete mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/member_symbol_type.rs delete mode 100644 rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/simple_sql.rs diff --git a/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js b/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js index 9cb9323a0b885..34a9d2587ba26 100644 --- a/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js +++ b/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js @@ -11,7 +11,7 @@ import cronParser from 'cron-parser'; import moment from 'moment-timezone'; import inflection from 'inflection'; -import { FROM_PARTITION_RANGE, inDbTimeZone, MAX_SOURCE_ROW_LIMIT, QueryAlias, getEnv } from '@cubejs-backend/shared'; +import { FROM_PARTITION_RANGE, inDbTimeZone, MAX_SOURCE_ROW_LIMIT, QueryAlias, getEnv, timeSeries as timeSeriesBase } from '@cubejs-backend/shared'; import { buildSqlAndParams as nativeBuildSqlAndParams, @@ -606,6 +606,11 @@ export class BaseQuery { } buildSqlAndParamsRust(exportAnnotatedSql) { + const order = this.options.order && R.pipe( + R.map((hash) => ((!hash || !hash.id) ? null : hash)), + R.reject(R.isNil), + )(this.options.order); + const queryParams = { measures: this.options.measures, dimensions: this.options.dimensions, @@ -614,12 +619,13 @@ export class BaseQuery { joinRoot: this.join.root, joinGraph: this.joinGraph, cubeEvaluator: this.cubeEvaluator, - order: this.options.order, + order, filters: this.options.filters, limit: this.options.limit ? this.options.limit.toString() : null, rowLimit: this.options.rowLimit ? this.options.rowLimit.toString() : null, offset: this.options.offset ? this.options.offset.toString() : null, baseTools: this, + ungrouped: this.options.ungrouped }; const res = nativeBuildSqlAndParams(queryParams); @@ -628,6 +634,21 @@ export class BaseQuery { return res; } + allCubeMembers(path) { + const fromPath = this.cubeEvaluator.cubeFromPath(path); + + return Object.keys(fromPath.measures).concat(Object.keys(fromPath.dimensions)); + } + + getAllocatedParams() { + return this.paramAllocator.getParams(); + } + + // FIXME helper for native generator, maybe should be moved entire to rust + generateTimeSeries(granularity, dateRange) { + return timeSeriesBase(granularity, dateRange); + } + get shouldReuseParams() { return false; } @@ -3236,7 +3257,16 @@ export class BaseQuery { '{% if offset is not none %}\nOFFSET {{ offset }}{% endif %}', group_by_exprs: '{{ group_by | map(attribute=\'index\') | join(\', \') }}', join: '{{ join_type }} JOIN {{ source }} ON {{ condition }}', - cte: '{{ alias }} AS ({{ query | indent(2, true) }})' + cte: '{{ alias }} AS ({{ query | indent(2, true) }})', + time_series_select: 'SELECT date_from::timestamp AS "date_from",\n' + + 'date_to::timestamp AS "date_to" \n' + + 'FROM(\n' + + ' VALUES ' + + '{% for time_item in seria %}' + + '(\'{{ time_item | join(\'\\\', \\\'\') }}\')' + + '{% if not loop.last %}, {% endif %}' + + '{% endfor %}' + + ') AS dates (date_from, date_to)' }, expressions: { column_reference: '{% if table_name %}{{ table_name }}.{% endif %}{{ name }}', @@ -3257,6 +3287,8 @@ export class BaseQuery { cube: 'CUBE({{ exprs_concat }})', negative: '-({{ expr }})', not: 'NOT ({{ expr }})', + add_interval: '{{ date }} + interval \'{{ interval }}\'', + sub_interval: '{{ date }} - interval \'{{ interval }}\'', true: 'TRUE', false: 'FALSE', like: '{{ expr }} {% if negated %}NOT {% endif %}LIKE {{ pattern }}', @@ -3276,7 +3308,8 @@ export class BaseQuery { gte: '{{ column }} >= {{ param }}', lt: '{{ column }} < {{ param }}', lte: '{{ column }} <= {{ param }}', - always_true: '1 == 1' + like_pattern: '{% if start_wild %}\'%\' || {% endif %}{{ value }}{% if end_wild %}|| \'%\'{% endif %}', + always_true: '1 = 1' }, quotes: { diff --git a/packages/cubejs-schema-compiler/src/adapter/ParamAllocator.ts b/packages/cubejs-schema-compiler/src/adapter/ParamAllocator.ts index 5dd8ae43d2c87..360dd90eecb35 100644 --- a/packages/cubejs-schema-compiler/src/adapter/ParamAllocator.ts +++ b/packages/cubejs-schema-compiler/src/adapter/ParamAllocator.ts @@ -51,6 +51,10 @@ export class ParamAllocator { return `$${paramIndex}$`; } + public getParams() { + return this.params; + } + // eslint-disable-next-line no-unused-vars protected paramPlaceHolder(paramIndex) { return '?'; diff --git a/packages/cubejs-schema-compiler/src/compiler/CubeSymbols.js b/packages/cubejs-schema-compiler/src/compiler/CubeSymbols.js index 28c99383ae1fc..754f340fd609c 100644 --- a/packages/cubejs-schema-compiler/src/compiler/CubeSymbols.js +++ b/packages/cubejs-schema-compiler/src/compiler/CubeSymbols.js @@ -106,7 +106,7 @@ export class CubeSymbols { }, set segments(v) { // Dont allow to modify - } + }, }, cubeDefinition); if (cubeDefinition.extends) { diff --git a/packages/cubejs-schema-compiler/test/integration/clickhouse/ClickHouseDbRunner.ts b/packages/cubejs-schema-compiler/test/integration/clickhouse/ClickHouseDbRunner.ts index f399bcfa72a7b..296a224446a57 100644 --- a/packages/cubejs-schema-compiler/test/integration/clickhouse/ClickHouseDbRunner.ts +++ b/packages/cubejs-schema-compiler/test/integration/clickhouse/ClickHouseDbRunner.ts @@ -5,7 +5,7 @@ import type { StartedTestContainer } from 'testcontainers'; import { format as formatSql } from 'sqlstring'; import { v4 as uuidv4 } from 'uuid'; import { ClickHouseQuery } from '../../../src/adapter/ClickHouseQuery'; -import { BaseDbRunner } from "../utils/BaseDbRunner"; +import { BaseDbRunner } from '../utils/BaseDbRunner'; process.env.TZ = 'GMT'; diff --git a/packages/cubejs-schema-compiler/test/integration/postgres/sql-generation-logic.test.ts b/packages/cubejs-schema-compiler/test/integration/postgres/sql-generation-logic.test.ts index e8d6d6e4b2aac..c902b7d1faf37 100644 --- a/packages/cubejs-schema-compiler/test/integration/postgres/sql-generation-logic.test.ts +++ b/packages/cubejs-schema-compiler/test/integration/postgres/sql-generation-logic.test.ts @@ -453,7 +453,7 @@ describe('SQL Generation', () => { } }); - it('having filter with operator OR', async () => { + it('having filter with operator OR 1', async () => { await compiler.compile(); const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, { @@ -648,7 +648,7 @@ describe('SQL Generation', () => { }); }); - it('where filter with operators OR & AND', async () => { + it('where filter with operators OR & AND 1', async () => { await compiler.compile(); const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, { diff --git a/packages/cubejs-schema-compiler/test/integration/postgres/sql-generation.test.ts b/packages/cubejs-schema-compiler/test/integration/postgres/sql-generation.test.ts index 06f676a655b14..4d80e89185391 100644 --- a/packages/cubejs-schema-compiler/test/integration/postgres/sql-generation.test.ts +++ b/packages/cubejs-schema-compiler/test/integration/postgres/sql-generation.test.ts @@ -64,7 +64,7 @@ describe('SQL Generation', () => { offset: 'start' } }, - revenueRolling3day: { + revenueRollingThreeDay: { type: 'sum', sql: 'amount', rollingWindow: { @@ -780,7 +780,7 @@ describe('SQL Generation', () => { it('rolling month', async () => runQueryTest({ measures: [ - 'visitors.revenueRolling3day' + 'visitors.revenueRollingThreeDay' ], timeDimensions: [{ dimension: 'visitors.created_at', @@ -792,7 +792,7 @@ describe('SQL Generation', () => { }], timezone: 'America/Los_Angeles' }, [ - { visitors__created_at_week: '2017-01-09T00:00:00.000Z', visitors__revenue_rolling3day: '900' } + { visitors__created_at_week: '2017-01-09T00:00:00.000Z', visitors__revenue_rolling_three_day: '900' } ])); it('rolling count', async () => runQueryTest({ @@ -1791,7 +1791,7 @@ describe('SQL Generation', () => { ])); it( - 'contains filter', + 'contains filter 1', () => runQueryTest({ measures: [], dimensions: [ @@ -2583,7 +2583,7 @@ describe('SQL Generation', () => { ] )); - it('rank measure', async () => runQueryTest( + it('rank measure 1', async () => runQueryTest( { measures: ['visitors.revenue_rank'], }, diff --git a/packages/cubejs-schema-compiler/test/unit/base-query.test.ts b/packages/cubejs-schema-compiler/test/unit/base-query.test.ts index b25e0c4fd7a45..6a4752d600765 100644 --- a/packages/cubejs-schema-compiler/test/unit/base-query.test.ts +++ b/packages/cubejs-schema-compiler/test/unit/base-query.test.ts @@ -1596,7 +1596,7 @@ describe('SQL Generation', () => { sql: 'product_id', type: 'avg', filters: [ - { sql: `{FILTER_PARAMS.Order.category.filter('category')}` } + { sql: '{FILTER_PARAMS.Order.category.filter(\'category\')}' } ] } ], @@ -1613,7 +1613,7 @@ describe('SQL Generation', () => { }, { name: 'proxied', - sql: `{FILTER_PARAMS.Order.type.filter("x => type = 'online'")}`, + sql: '{FILTER_PARAMS.Order.type.filter("x => type = \'online\'")}', type: 'boolean', } ] diff --git a/packages/cubejs-schema-compiler/test/unit/pre-aggregations.test.ts b/packages/cubejs-schema-compiler/test/unit/pre-aggregations.test.ts index cb6d653b4b23c..641f2aea699d5 100644 --- a/packages/cubejs-schema-compiler/test/unit/pre-aggregations.test.ts +++ b/packages/cubejs-schema-compiler/test/unit/pre-aggregations.test.ts @@ -217,8 +217,8 @@ describe('pre-aggregations', () => { console.log(JSON.stringify(preAggregationsDescription, null, 2)); expect(preAggregationsDescription.length).toEqual(2); - expect(preAggregationsDescription[0].preAggregationId).toEqual("Orders.simple1"); - expect(preAggregationsDescription[1].preAggregationId).toEqual("Orders.simple2"); + expect(preAggregationsDescription[0].preAggregationId).toEqual('Orders.simple1'); + expect(preAggregationsDescription[1].preAggregationId).toEqual('Orders.simple2'); }); // @link https://github.com/cube-js/cube/issues/6623 diff --git a/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/base_query_options.rs b/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/base_query_options.rs index f08447d48c81f..2e0571cfa0fb5 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/base_query_options.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/base_query_options.rs @@ -60,6 +60,7 @@ pub struct BaseQueryOptionsStatic { #[serde(rename = "rowLimit")] pub row_limit: Option, pub offset: Option, + pub ungrouped: Option, } #[nativebridge::native_bridge(BaseQueryOptionsStatic)] diff --git a/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/base_tools.rs b/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/base_tools.rs index d5aef3c6d812d..ded10dda2e5d4 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/base_tools.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/base_tools.rs @@ -38,4 +38,11 @@ pub trait BaseTools { fn filter_group_function(&self) -> Result, CubeError>; fn timestamp_precision(&self) -> Result; fn in_db_time_zone(&self, date: String) -> Result; + fn generate_time_series( + &self, + granularity: String, + date_range: Vec, + ) -> Result>, CubeError>; + fn get_allocated_params(&self) -> Result, CubeError>; + fn all_cube_members(&self, path: String) -> Result, CubeError>; } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/measure_definition.rs b/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/measure_definition.rs index 5b23f4e971e4e..4c1cdb21f2596 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/measure_definition.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/measure_definition.rs @@ -21,6 +21,13 @@ pub struct TimeShiftReference { pub time_dimension: String, } +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +pub struct RollingWindow { + pub trailing: Option, + pub leading: Option, + pub offset: Option, +} + #[derive(Serialize, Deserialize, Debug)] pub struct MeasureDefinitionStatic { #[serde(rename = "type")] @@ -37,6 +44,8 @@ pub struct MeasureDefinitionStatic { pub group_by_references: Option>, #[serde(rename = "timeShiftReferences")] pub time_shift_references: Option>, + #[serde(rename = "rollingWindow")] + pub rolling_window: Option, } #[nativebridge::native_bridge(MeasureDefinitionStatic)] diff --git a/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/memeber_sql.rs b/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/memeber_sql.rs index bb18007581a10..3dbf3a967f713 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/memeber_sql.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/memeber_sql.rs @@ -19,7 +19,7 @@ use std::rc::Rc; pub struct MemberSqlStruct { pub sql_fn: Option, pub to_string_fn: Option, - pub properties: HashMap, + pub properties: HashMap, } pub enum ContextSymbolArg { @@ -64,6 +64,39 @@ impl NativeSerialize for MemberSqlStruct { } } +impl NativeSerialize for MemberSqlArg { + fn to_native( + &self, + context_holder: NativeContextHolder, + ) -> Result, CubeError> { + let res = match self { + MemberSqlArg::String(s) => s.to_native(context_holder.clone()), + MemberSqlArg::Struct(s) => s.to_native(context_holder.clone()), + MemberSqlArg::ContextSymbol(symbol) => match symbol { + ContextSymbolArg::SecurityContext(context) => context + .clone() + .as_any() + .downcast::>() + .unwrap() + .to_native(context_holder.clone()), + ContextSymbolArg::FilterParams(params) => params + .clone() + .as_any() + .downcast::>() + .unwrap() + .to_native(context_holder.clone()), + ContextSymbolArg::FilterGroup(group) => group + .clone() + .as_any() + .downcast::>() + .unwrap() + .to_native(context_holder.clone()), + }, + }?; + Ok(NativeObjectHandle::new(res.into_object())) + } +} + impl NativeMemberSql { pub fn try_new(native_object: NativeObjectHandle) -> Result { let args_names = native_object.to_function()?.args_names()?; @@ -89,27 +122,7 @@ impl MemberSql for NativeMemberSql { let context_holder = NativeContextHolder::::new(self.native_object.get_context()); let native_args = args .into_iter() - .map(|a| match a { - MemberSqlArg::String(s) => s.to_native(context_holder.clone()), - MemberSqlArg::Struct(s) => s.to_native(context_holder.clone()), - MemberSqlArg::ContextSymbol(symbol) => match symbol { - ContextSymbolArg::SecurityContext(context) => context - .as_any() - .downcast::>() - .unwrap() - .to_native(context_holder.clone()), - ContextSymbolArg::FilterParams(params) => params - .as_any() - .downcast::>() - .unwrap() - .to_native(context_holder.clone()), - ContextSymbolArg::FilterGroup(group) => group - .as_any() - .downcast::>() - .unwrap() - .to_native(context_holder.clone()), - }, - }) + .map(|a| a.to_native(context_holder.clone())) .collect::, _>>()?; let res = self.native_object.to_function()?.call(native_args)?; diff --git a/rust/cubesqlplanner/cubesqlplanner/src/plan/builder/select.rs b/rust/cubesqlplanner/cubesqlplanner/src/plan/builder/select.rs index cf5c00864b6ff..4e143cb86f703 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/plan/builder/select.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/plan/builder/select.rs @@ -1,27 +1,29 @@ use crate::plan::{ - AliasedExpr, Cte, Expr, Filter, From, MemberExpression, OrderBy, Schema, Select, + AliasedExpr, Cte, Expr, Filter, From, MemberExpression, OrderBy, Schema, SchemaColumn, Select, + SingleAliasedSource, SingleSource, }; + +use crate::planner::sql_evaluator::sql_nodes::SqlNodesFactory; use crate::planner::{BaseMember, VisitorContext}; +use std::collections::HashMap; use std::rc::Rc; pub struct SelectBuilder { projection_columns: Vec, - from: From, + from: Rc, filter: Option, group_by: Vec, having: Option, order_by: Vec, - context: Rc, ctes: Vec>, is_distinct: bool, limit: Option, offset: Option, - input_schema: Rc, + result_schema: Schema, } impl SelectBuilder { - pub fn new(from: From, context: VisitorContext) -> Self { - let input_schema = from.schema.clone(); + pub fn new(from: Rc) -> Self { Self { projection_columns: vec![], from, @@ -29,33 +31,30 @@ impl SelectBuilder { group_by: vec![], having: None, order_by: vec![], - context: Rc::new(context), ctes: vec![], is_distinct: false, limit: None, offset: None, - input_schema, + result_schema: Schema::empty(), } } - pub fn add_projection_member( - &mut self, - member: &Rc, - source: Option, - alias: Option, - ) { + pub fn add_projection_member(&mut self, member: &Rc, alias: Option) { let alias = if let Some(alias) = alias { alias } else { - self.input_schema.resolve_member_alias(&member, &source) + member.alias_name() }; - let expr = Expr::Member(MemberExpression::new(member.clone(), source)); + + let expr = Expr::Member(MemberExpression::new(member.clone())); let aliased_expr = AliasedExpr { expr, alias: alias.clone(), }; self.projection_columns.push(aliased_expr); + self.result_schema + .add_column(SchemaColumn::new(alias.clone(), Some(member.full_name()))); } pub fn set_filter(&mut self, filter: Option) { @@ -85,11 +84,65 @@ impl SelectBuilder { pub fn set_offset(&mut self, offset: Option) { self.offset = offset; } + pub fn set_ctes(&mut self, ctes: Vec>) { self.ctes = ctes; } - pub fn build(self) -> Select { + fn make_cube_references(&self) -> HashMap { + let mut refs = HashMap::new(); + match &self.from.source { + crate::plan::FromSource::Single(source) => { + self.add_cube_reference_if_needed(source, &mut refs) + } + crate::plan::FromSource::Join(join) => { + self.add_cube_reference_if_needed(&join.root, &mut refs); + for join_item in join.joins.iter() { + self.add_cube_reference_if_needed(&join_item.from, &mut refs); + } + } + crate::plan::FromSource::Empty => {} + } + refs + } + + fn add_cube_reference_if_needed( + &self, + source: &SingleAliasedSource, + refs: &mut HashMap, + ) { + match &source.source { + SingleSource::Cube(cube) => { + refs.insert(cube.name().clone(), source.alias.clone()); + } + _ => {} + } + } + + fn make_asteriks_schema(&self) -> Rc { + let schema = match &self.from.source { + crate::plan::FromSource::Empty => Rc::new(Schema::empty()), + crate::plan::FromSource::Single(source) => source.source.schema(), + crate::plan::FromSource::Join(join) => { + let mut schema = Schema::empty(); + schema.merge(join.root.source.schema().as_ref()); + for itm in join.joins.iter() { + schema.merge(itm.from.source.schema().as_ref()) + } + Rc::new(schema) + } + }; + schema + } + + pub fn build(self, mut nodes_factory: SqlNodesFactory) -> Select { + let cube_references = self.make_cube_references(); + nodes_factory.set_cube_name_references(cube_references); + let schema = if self.projection_columns.is_empty() { + self.make_asteriks_schema() + } else { + Rc::new(self.result_schema) + }; Select { projection_columns: self.projection_columns, from: self.from, @@ -97,11 +150,12 @@ impl SelectBuilder { group_by: self.group_by, having: self.having, order_by: self.order_by, - context: self.context.clone(), + context: Rc::new(VisitorContext::new(&nodes_factory)), ctes: self.ctes, is_distinct: self.is_distinct, limit: self.limit, offset: self.offset, + schema, } } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/plan/cte.rs b/rust/cubesqlplanner/cubesqlplanner/src/plan/cte.rs index dba7dd3a9c7a3..4d3ee55a6fceb 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/plan/cte.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/plan/cte.rs @@ -1,4 +1,4 @@ -use super::{QueryPlan, Schema, Select}; +use super::{QueryPlan, Select}; use crate::planner::sql_templates::PlanSqlTemplates; use cubenativeutils::CubeError; @@ -22,10 +22,6 @@ impl Cte { } } - pub fn make_schema(&self) -> Schema { - self.query.make_schema(Some(self.name().clone())) - } - pub fn query(&self) -> &Rc { &self.query } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/plan/expression.rs b/rust/cubesqlplanner/cubesqlplanner/src/plan/expression.rs index 69e99cbcd2a30..be13ad59816e7 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/plan/expression.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/plan/expression.rs @@ -1,4 +1,4 @@ -use super::Schema; +use super::QualifiedColumnName; use crate::planner::sql_templates::PlanSqlTemplates; use crate::planner::{BaseMember, VisitorContext}; use cubenativeutils::CubeError; @@ -7,44 +7,45 @@ use std::rc::Rc; #[derive(Clone)] pub struct MemberExpression { pub member: Rc, - pub source: Option, } impl MemberExpression { - pub fn new(member: Rc, source: Option) -> Self { - Self { member, source } + pub fn new(member: Rc) -> Self { + Self { member } } pub fn to_sql( &self, - templates: &PlanSqlTemplates, + _templates: &PlanSqlTemplates, context: Rc, - schema: Rc, ) -> Result { - if let Some(reference_column) = - schema.find_column_for_member(&self.member.full_name(), &self.source) - { - templates.column_reference(&reference_column.table_name, &reference_column.alias) - } else { - self.member.to_sql(context, schema) - } + self.member.to_sql(context) } } #[derive(Clone)] pub enum Expr { Member(MemberExpression), + Reference(QualifiedColumnName), } impl Expr { + pub fn new_member(member: Rc) -> Self { + Self::Member(MemberExpression::new(member)) + } + pub fn new_reference(source: Option, reference: String) -> Self { + Self::Reference(QualifiedColumnName::new(source, reference)) + } pub fn to_sql( &self, templates: &PlanSqlTemplates, context: Rc, - schema: Rc, ) -> Result { match self { - Expr::Member(member) => member.to_sql(templates, context, schema), + Self::Member(member) => member.to_sql(templates, context), + Self::Reference(reference) => { + templates.column_reference(reference.source(), &reference.name()) + } } } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/plan/filter.rs b/rust/cubesqlplanner/cubesqlplanner/src/plan/filter.rs index f118aefe5d8e5..b7e59049cb373 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/plan/filter.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/plan/filter.rs @@ -1,4 +1,3 @@ -use super::Schema; use crate::planner::filter::BaseFilter; use crate::planner::sql_templates::PlanSqlTemplates; use crate::planner::VisitorContext; @@ -6,7 +5,7 @@ use cubenativeutils::CubeError; use std::fmt; use std::rc::Rc; -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub enum FilterGroupOperator { Or, And, @@ -18,13 +17,19 @@ pub struct FilterGroup { pub items: Vec, } +impl PartialEq for FilterGroup { + fn eq(&self, other: &Self) -> bool { + self.operator == other.operator && self.items == other.items + } +} + impl FilterGroup { pub fn new(operator: FilterGroupOperator, items: Vec) -> Self { Self { operator, items } } } -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub enum FilterItem { Group(Rc), Item(Rc), @@ -48,7 +53,6 @@ impl FilterItem { &self, templates: &PlanSqlTemplates, context: Rc, - schema: Rc, ) -> Result { let res = match self { FilterItem::Group(group) => { @@ -56,17 +60,20 @@ impl FilterItem { let items_sql = group .items .iter() - .map(|itm| itm.to_sql(templates, context.clone(), schema.clone())) - .collect::, _>>()?; - let result = if items_sql.is_empty() { - templates.always_true()? + .map(|itm| itm.to_sql(templates, context.clone())) + .collect::, _>>()? + .into_iter() + .filter(|itm| !itm.is_empty()) + .collect::>(); + if items_sql.is_empty() { + "".to_string() } else { - items_sql.join(&operator) - }; - format!("({})", result) + let result = items_sql.join(&operator); + format!("({})", result) + } } FilterItem::Item(item) => { - let sql = item.to_sql(context.clone(), schema)?; + let sql = item.to_sql(context.clone())?; format!("({})", sql) } }; @@ -79,12 +86,11 @@ impl Filter { &self, templates: &PlanSqlTemplates, context: Rc, - schema: Rc, ) -> Result { let res = self .items .iter() - .map(|itm| itm.to_sql(templates, context.clone(), schema.clone())) + .map(|itm| itm.to_sql(templates, context.clone())) .collect::, _>>()? .join(" AND "); Ok(res) diff --git a/rust/cubesqlplanner/cubesqlplanner/src/plan/from.rs b/rust/cubesqlplanner/cubesqlplanner/src/plan/from.rs index 7da4fb0dbcf39..175fb662ca89b 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/plan/from.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/plan/from.rs @@ -1,4 +1,4 @@ -use super::{Join, QueryPlan, Schema, SchemaCube, Select}; +use super::{Join, QueryPlan, Schema, Select}; use crate::planner::sql_templates::PlanSqlTemplates; use crate::planner::{BaseCube, VisitorContext}; use cubenativeutils::CubeError; @@ -27,6 +27,14 @@ impl SingleSource { }; Ok(sql) } + + pub fn schema(&self) -> Rc { + match self { + SingleSource::Subquery(subquery) => subquery.schema(), + SingleSource::Cube(_) => Rc::new(Schema::empty()), + SingleSource::TableReference(_, schema) => schema.clone(), + } + } } #[derive(Clone)] @@ -72,18 +80,6 @@ impl SingleAliasedSource { templates.query_aliased(&sql, &self.alias) } - - pub fn make_schema(&self) -> Schema { - match &self.source { - SingleSource::Subquery(query) => query.make_schema(Some(self.alias.clone())), - SingleSource::Cube(cube) => { - let mut schema = Schema::empty(); - schema.add_cube(SchemaCube::new(cube.name().clone(), self.alias.clone())); - schema - } - SingleSource::TableReference(_, schema) => schema.move_to_source(&self.alias), - } - } } #[derive(Clone)] @@ -93,30 +89,17 @@ pub enum FromSource { Join(Rc), } -impl FromSource { - pub fn get_schema(&self) -> Rc { - let schema = match self { - FromSource::Empty => Schema::empty(), - FromSource::Single(source) => source.make_schema(), - FromSource::Join(join) => join.make_schema(), - }; - Rc::new(schema) - } -} - #[derive(Clone)] pub struct From { pub source: FromSource, - pub schema: Rc, } impl From { - pub fn new(source: FromSource) -> Self { - let schema = source.get_schema(); - Self { source, schema } + pub fn new(source: FromSource) -> Rc { + Rc::new(Self { source }) } - pub fn new_from_cube(cube: Rc, alias: Option) -> Self { + pub fn new_from_cube(cube: Rc, alias: Option) -> Rc { Self::new(FromSource::Single(SingleAliasedSource::new_from_cube( cube, alias, ))) @@ -126,23 +109,23 @@ impl From { reference: String, schema: Rc, alias: Option, - ) -> Self { + ) -> Rc { Self::new(FromSource::Single( SingleAliasedSource::new_from_table_reference(reference, schema, alias), )) } - pub fn new_from_join(join: Rc) -> Self { + pub fn new_from_join(join: Rc) -> Rc { Self::new(FromSource::Join(join)) } - pub fn new_from_subquery(plan: Rc, alias: String) -> Self { + pub fn new_from_subquery(plan: Rc, alias: String) -> Rc { Self::new(FromSource::Single(SingleAliasedSource::new_from_subquery( plan, alias, ))) } - pub fn new_from_subselect(plan: Rc, alias: String) -> Rc { Self::new(FromSource::Single(SingleAliasedSource::new_from_subquery( Rc::new(QueryPlan::Select(plan)), alias, diff --git a/rust/cubesqlplanner/cubesqlplanner/src/plan/join.rs b/rust/cubesqlplanner/cubesqlplanner/src/plan/join.rs index 19e8283bc5e68..3a19170443d80 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/plan/join.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/plan/join.rs @@ -1,28 +1,101 @@ -use super::{Schema, SingleAliasedSource}; +use super::{Expr, SingleAliasedSource}; use crate::planner::sql_templates::PlanSqlTemplates; -use crate::planner::{BaseJoinCondition, BaseMember, VisitorContext}; +use crate::planner::{BaseJoinCondition, VisitorContext}; use cubenativeutils::CubeError; +use lazy_static::lazy_static; use std::rc::Rc; +pub struct RollingWindowJoinCondition { + time_series_source: String, + trailing_interval: Option, + leading_interval: Option, + offset: String, + time_dimension: Expr, +} + +impl RollingWindowJoinCondition { + pub fn new( + time_series_source: String, + trailing_interval: Option, + leading_interval: Option, + offset: String, + time_dimension: Expr, + ) -> Self { + Self { + time_series_source, + trailing_interval, + leading_interval, + offset, + time_dimension, + } + } + + pub fn to_sql( + &self, + templates: &PlanSqlTemplates, + context: Rc, + ) -> Result { + let mut conditions = vec![]; + let date_column = self.time_dimension.to_sql(templates, context)?; + + lazy_static! { + static ref UNBOUNDED: Option = Some("unbounded".to_string()); + } + + if self.trailing_interval != *UNBOUNDED { + let start_date = if self.offset == "start" { + templates.column_reference(&Some(self.time_series_source.clone()), "date_from")? + } else { + templates.column_reference(&Some(self.time_series_source.clone()), "date_to")? + }; + + let trailing_start = if let Some(trailing_interval) = &self.trailing_interval { + format!("{start_date} - interval '{trailing_interval}'") + } else { + start_date + }; + + let sign = if self.offset == "start" { ">=" } else { ">" }; + + conditions.push(format!("{date_column} {sign} {trailing_start}")); + } + + if self.leading_interval != *UNBOUNDED { + let end_date = if self.offset == "end" { + templates.column_reference(&Some(self.time_series_source.clone()), "date_to")? + } else { + templates.column_reference(&Some(self.time_series_source.clone()), "date_from")? + }; + + let leading_end = if let Some(leading_interval) = &self.leading_interval { + format!("{end_date} + interval '{leading_interval}'") + } else { + end_date + }; + + let sign = if self.offset == "end" { "<=" } else { "<" }; + + conditions.push(format!("{date_column} {sign} {leading_end}")); + } + let result = if conditions.is_empty() { + templates.always_true()? + } else { + conditions.join(" AND ") + }; + Ok(result) + } +} + pub struct DimensionJoinCondition { - left_source: String, - right_source: String, - dimensions: Vec>, + conditions: Vec<(Expr, Expr)>, null_check: bool, } impl DimensionJoinCondition { - pub fn new( - left_source: String, - right_source: String, - dimensions: Vec>, - null_check: bool, - ) -> Self { + pub fn new(conditions: Vec<(Expr, Expr)>, null_check: bool) -> Self { Self { - left_source, - right_source, - dimensions, + conditions, null_check, } } @@ -31,15 +104,14 @@ impl DimensionJoinCondition { &self, templates: &PlanSqlTemplates, context: Rc, - schema: Rc, ) -> Result { - let result = if self.dimensions.is_empty() { + let result = if self.conditions.is_empty() { format!("1 = 1") } else { - self.dimensions + self.conditions .iter() - .map(|dim| -> Result { - self.dimension_condition(templates, context.clone(), dim, schema.clone()) + .map(|(left, right)| -> Result { + self.dimension_condition(templates, context.clone(), left, right) }) .collect::, _>>()? .join(" AND ") @@ -51,61 +123,39 @@ impl DimensionJoinCondition { &self, templates: &PlanSqlTemplates, context: Rc, - dimension: &Rc, - schema: Rc, - ) -> Result { - let left_column = self.resolve_member_alias( - templates, - context.clone(), - &self.left_source, - dimension, - schema.clone(), - )?; - let right_column = self.resolve_member_alias( - templates, - context.clone(), - &self.right_source, - dimension, - schema.clone(), - )?; - templates.join_by_dimension_conditions(&left_column, &right_column, self.null_check) - } - - fn resolve_member_alias( - &self, - templates: &PlanSqlTemplates, - context: Rc, - source: &String, - dimension: &Rc, - schema: Rc, + left_expr: &Expr, + right_expr: &Expr, ) -> Result { - let schema = schema.extract_source_schema(source); - let source = Some(source.clone()); - if let Some(column) = schema.find_column_for_member(&dimension.full_name(), &source) { - templates.column_reference(&source, &column.alias.clone()) - } else { - dimension.to_sql(context.clone(), schema.clone()) - } + let left_sql = left_expr.to_sql(templates, context.clone())?; + let right_sql = right_expr.to_sql(templates, context.clone())?; + templates.join_by_dimension_conditions(&left_sql, &right_sql, self.null_check) } } pub enum JoinCondition { DimensionJoinCondition(DimensionJoinCondition), BaseJoinCondition(Rc), + RollingWindowJoinCondition(RollingWindowJoinCondition), } impl JoinCondition { - pub fn new_dimension_join( - left_source: String, - right_source: String, - dimensions: Vec>, - null_check: bool, + pub fn new_dimension_join(conditions: Vec<(Expr, Expr)>, null_check: bool) -> Self { + Self::DimensionJoinCondition(DimensionJoinCondition::new(conditions, null_check)) + } + + pub fn new_rolling_join( + time_series_source: String, + trailing_interval: Option, + leading_interval: Option, + offset: String, + time_dimension: Expr, ) -> Self { - Self::DimensionJoinCondition(DimensionJoinCondition::new( - left_source, - right_source, - dimensions, - null_check, + Self::RollingWindowJoinCondition(RollingWindowJoinCondition::new( + time_series_source, + trailing_interval, + leading_interval, + offset, + time_dimension, )) } @@ -117,11 +167,11 @@ impl JoinCondition { &self, templates: &PlanSqlTemplates, context: Rc, - schema: Rc, ) -> Result { match &self { - JoinCondition::DimensionJoinCondition(cond) => cond.to_sql(templates, context, schema), - JoinCondition::BaseJoinCondition(cond) => cond.to_sql(context, schema), + JoinCondition::DimensionJoinCondition(cond) => cond.to_sql(templates, context), + JoinCondition::BaseJoinCondition(cond) => cond.to_sql(context), + JoinCondition::RollingWindowJoinCondition(cond) => cond.to_sql(templates, context), } } } @@ -142,9 +192,8 @@ impl JoinItem { &self, templates: &PlanSqlTemplates, context: Rc, - schema: Rc, ) -> Result { - let on_sql = self.on.to_sql(templates, context.clone(), schema)?; + let on_sql = self.on.to_sql(templates, context.clone())?; let result = templates.join( &self.from.to_sql(templates, context)?, &on_sql, @@ -155,24 +204,15 @@ impl JoinItem { } impl Join { - pub fn make_schema(&self) -> Schema { - let mut schema = self.root.make_schema(); - for itm in self.joins.iter() { - schema.merge(itm.from.make_schema()); - } - schema - } - pub fn to_sql( &self, templates: &PlanSqlTemplates, context: Rc, ) -> Result { - let schema = Rc::new(self.make_schema()); let joins_sql = self .joins .iter() - .map(|j| j.to_sql(templates, context.clone(), schema.clone())) + .map(|j| j.to_sql(templates, context.clone())) .collect::, _>>()?; let res = format!( "{}\n{}", diff --git a/rust/cubesqlplanner/cubesqlplanner/src/plan/mod.rs b/rust/cubesqlplanner/cubesqlplanner/src/plan/mod.rs index 5d98909183278..3799935638bd2 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/plan/mod.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/plan/mod.rs @@ -8,6 +8,7 @@ pub mod order; pub mod query_plan; pub mod schema; pub mod select; +pub mod time_series; pub mod union; pub use builder::{JoinBuilder, SelectBuilder}; @@ -15,9 +16,10 @@ pub use cte::Cte; pub use expression::{Expr, MemberExpression}; pub use filter::{Filter, FilterGroup, FilterItem}; pub use from::{From, FromSource, SingleAliasedSource, SingleSource}; -pub use join::{Join, JoinCondition, JoinItem}; +pub use join::{Join, JoinCondition, JoinItem, RollingWindowJoinCondition}; pub use order::OrderBy; pub use query_plan::QueryPlan; -pub use schema::{Schema, SchemaColumn, SchemaCube}; +pub use schema::{QualifiedColumnName, Schema, SchemaColumn}; pub use select::{AliasedExpr, Select}; +pub use time_series::TimeSeries; pub use union::Union; diff --git a/rust/cubesqlplanner/cubesqlplanner/src/plan/query_plan.rs b/rust/cubesqlplanner/cubesqlplanner/src/plan/query_plan.rs index e8224fb74aebf..8957321274111 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/plan/query_plan.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/plan/query_plan.rs @@ -1,4 +1,4 @@ -use super::{Schema, Select, Union}; +use super::{Schema, Select, TimeSeries, Union}; use crate::planner::sql_templates::PlanSqlTemplates; use cubenativeutils::CubeError; use std::rc::Rc; @@ -6,19 +6,22 @@ use std::rc::Rc; pub enum QueryPlan { Select(Rc { let schema = cte_schemas.get(alias).unwrap().clone(); - let select_builder = SelectBuilder::new( - From::new_from_table_reference(alias.clone(), schema, None), - VisitorContext::default(SqlNodesFactory::new()), + let select_builder = + SelectBuilder::new(From::new_from_table_reference(alias.clone(), schema, None)); + + Rc::new(select_builder.build(SqlNodesFactory::new())) + } + + fn create_multi_stage_inode_member( + &self, + base_member: Rc, + ) -> Result { + let inode = if let Some(measure) = + BaseMeasure::try_new(base_member.clone(), self.query_tools.clone())? + { + let member_type = if measure.measure_type() == "rank" { + MultiStageInodeMemberType::Rank + } else if !measure.is_calculated() { + MultiStageInodeMemberType::Aggregate + } else { + MultiStageInodeMemberType::Calculate + }; + + let time_shifts = if let Some(refs) = measure.time_shift_references() { + let time_shifts = refs + .iter() + .map(|r| MultiStageTimeShift::try_from_reference(r)) + .collect::, _>>()?; + time_shifts + } else { + vec![] + }; + let is_ungrupped = match &member_type { + MultiStageInodeMemberType::Rank | MultiStageInodeMemberType::Calculate => true, + _ => false, + }; + MultiStageInodeMember::new( + member_type, + measure.reduce_by().clone().unwrap_or_default(), + measure.add_group_by().clone().unwrap_or_default(), + measure.group_by().clone(), + time_shifts, + is_ungrupped, + ) + } else { + MultiStageInodeMember::new( + MultiStageInodeMemberType::Calculate, + vec![], + vec![], + None, + vec![], + false, + ) + }; + Ok(inode) + } + + fn add_time_series( + &self, + time_dimension: Rc, + state: Rc, + descriptions: &mut Vec>, + ) -> Result, CubeError> { + let description = + if let Some(description) = descriptions.iter().find(|d| d.alias() == "time_series") { + description.clone() + } else { + let time_series_node = MultiStageQueryDescription::new( + MultiStageMember::new( + MultiStageMemberType::Leaf(MultiStageLeafMemberType::TimeSeries( + time_dimension.clone(), + )), + time_dimension.member_evaluator(), + ), + state.clone(), + vec![], + "time_series".to_string(), + ); + descriptions.push(time_series_node.clone()); + time_series_node + }; + Ok(description) + } + + fn add_rolling_window_base( + &self, + member: Rc, + state: Rc, + descriptions: &mut Vec>, + ) -> Result, CubeError> { + let alias = format!("cte_{}", descriptions.len()); + let description = MultiStageQueryDescription::new( + MultiStageMember::new( + MultiStageMemberType::Leaf(MultiStageLeafMemberType::Measure), + member, + ), + state, + vec![], + alias.clone(), ); + descriptions.push(description.clone()); + Ok(description) + } + + fn make_rolling_base_state( + &self, + time_dimension: Rc, + rolling_window: &RollingWindow, + state: Rc, + ) -> Result, CubeError> { + let time_dimension_name = time_dimension.member_evaluator().full_name(); + let mut new_state = state.clone_state(); + let trailing_granularity = + GranularityHelper::granularity_from_interval(&rolling_window.trailing); + let leading_granularity = + GranularityHelper::granularity_from_interval(&rolling_window.leading); + let window_granularity = + GranularityHelper::min_granularity(&trailing_granularity, &leading_granularity)?; + let result_granularity = GranularityHelper::min_granularity( + &window_granularity, + &time_dimension.get_granularity(), + )?; + + new_state.change_time_dimension_granularity(&time_dimension_name, result_granularity); + + new_state.expand_date_range_filter( + &time_dimension_name, + rolling_window.trailing.clone(), + rolling_window.leading.clone(), + ); + + Ok(Rc::new(new_state)) + } - Rc::new(select_builder.build()) + fn try_make_rolling_window( + &self, + member: Rc, + state: Rc, + descriptions: &mut Vec>, + ) -> Result>, CubeError> { + if let Some(measure) = BaseMeasure::try_new(member.clone(), self.query_tools.clone())? { + if measure.is_cumulative() { + let rolling_window = if let Some(rolling_window) = measure.rolling_window() { + rolling_window.clone() + } else { + RollingWindow { + trailing: Some("unbounded".to_string()), + leading: None, + offset: None, + } + }; + let time_dimensions = self.query_properties.time_dimensions(); + if time_dimensions.len() == 0 { + let rolling_base = + self.add_rolling_window_base(member.clone(), state.clone(), descriptions)?; + return Ok(Some(rolling_base)); + } + if time_dimensions.len() != 1 { + return Err(CubeError::internal( + "Rolling window requires one time dimension".to_string(), + )); + } + let time_dimension = time_dimensions[0].clone(); + + let input = vec![ + self.add_time_series(time_dimension.clone(), state.clone(), descriptions)?, + self.add_rolling_window_base( + member.clone(), + self.make_rolling_base_state( + time_dimension.clone(), + &rolling_window, + state.clone(), + )?, + descriptions, + )?, + ]; + + let time_dimension = time_dimensions[0].clone(); + + let alias = format!("cte_{}", descriptions.len()); + + let rolling_window_descr = RollingWindowDescription { + time_dimension: time_dimension.clone(), + trailing: rolling_window.trailing.clone(), + leading: rolling_window.leading.clone(), + offset: rolling_window.offset.clone().unwrap_or("end".to_string()), + }; + + let inode_member = MultiStageInodeMember::new( + MultiStageInodeMemberType::RollingWindow(rolling_window_descr), + vec![], + vec![], + None, + vec![], + false, + ); + + let description = MultiStageQueryDescription::new( + MultiStageMember::new(MultiStageMemberType::Inode(inode_member), member), + state.clone(), + input, + alias.clone(), + ); + descriptions.push(description.clone()); + Ok(Some(description)) + } else { + Ok(None) + } + } else { + Ok(None) + } } fn make_queries_descriptions( &self, - member: Rc, + member: Rc, state: Rc, descriptions: &mut Vec>, ) -> Result, CubeError> { @@ -113,54 +322,77 @@ impl MultiStageQueryPlanner { return Ok(exists.clone()); }; - let (dimensions_to_add, time_shifts) = if let Some(measure) = - BaseMeasure::try_new(member.clone(), self.query_tools.clone())? + if let Some(rolling_window_query) = + self.try_make_rolling_window(member.clone(), state.clone(), descriptions)? { - let dimensions_to_add = if let Some(add_group_by) = measure.add_group_by() { - add_group_by - .iter() - .map(|name| self.compile_dimension(name)) - .collect::, _>>()? - } else { - vec![] - }; + return Ok(rolling_window_query); + } - (dimensions_to_add, measure.time_shifts().clone()) - } else { - (vec![], vec![]) - }; + let childs = member_childs(&member)?; - let new_state = if !dimensions_to_add.is_empty() - || !time_shifts.is_empty() - || state.is_filter_allowed(&member_name) - { - let mut new_state = state.clone_state(); - if !dimensions_to_add.is_empty() { - new_state.add_dimensions(dimensions_to_add); - } - if !time_shifts.is_empty() { - new_state.add_time_shifts(time_shifts); - } - if state.is_filter_allowed(&member_name) { - new_state.disallow_filter(&member_name); + let description = if childs.is_empty() { + if has_multi_stage_members(&member, false)? { + return Err(CubeError::internal(format!( + "Leaf multi stage query cannot contain multi stage member" + ))); } - Rc::new(new_state) + + let alias = format!("cte_{}", descriptions.len()); + MultiStageQueryDescription::new( + MultiStageMember::new( + MultiStageMemberType::Leaf(MultiStageLeafMemberType::Measure), + member.clone(), + ), + state.clone(), + vec![], + alias.clone(), + ) } else { - state.clone() - }; + let multi_stage_member = self.create_multi_stage_inode_member(member.clone())?; - let childs = member_childs(&member)?; - let input = childs - .into_iter() - .map( - |child| -> Result, CubeError> { - self.make_queries_descriptions(child, new_state.clone(), descriptions) - }, + let dimensions_to_add = multi_stage_member + .add_group_by() + .iter() + .map(|name| self.compile_dimension(name)) + .collect::, _>>()?; + + let new_state = if !dimensions_to_add.is_empty() + || !multi_stage_member.time_shifts().is_empty() + || state.has_filters_for_member(&member_name) + { + let mut new_state = state.clone_state(); + if !dimensions_to_add.is_empty() { + new_state.add_dimensions(dimensions_to_add); + } + if !multi_stage_member.time_shifts().is_empty() { + new_state.add_time_shifts(multi_stage_member.time_shifts().clone()); + } + if state.has_filters_for_member(&member_name) { + new_state.remove_filter_for_member(&member_name); + } + Rc::new(new_state) + } else { + state.clone() + }; + + let input = childs + .into_iter() + .map( + |child| -> Result, CubeError> { + self.make_queries_descriptions(child, new_state.clone(), descriptions) + }, + ) + .collect::, _>>()?; + + let alias = format!("cte_{}", descriptions.len()); + MultiStageQueryDescription::new( + MultiStageMember::new(MultiStageMemberType::Inode(multi_stage_member), member), + state.clone(), + input, + alias.clone(), ) - .collect::, _>>()?; - let alias = format!("cte_{}", descriptions.len()); - let description = - MultiStageQueryDescription::new(member, state.clone(), input, alias.clone()); + }; + descriptions.push(description.clone()); Ok(description) } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multiplied_measures_query_planner.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multiplied_measures_query_planner.rs index 6ac49c628cea6..1d1152d276e91 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multiplied_measures_query_planner.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multiplied_measures_query_planner.rs @@ -1,28 +1,36 @@ use super::{CommonUtils, JoinPlanner}; -use crate::plan::{From, JoinBuilder, JoinCondition, Select, SelectBuilder}; +use crate::plan::{ + Expr, From, JoinBuilder, JoinCondition, MemberExpression, QualifiedColumnName, Select, + SelectBuilder, +}; use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::collectors::{ + collect_cube_names, collect_join_hints, collect_join_hints_for_measures, +}; use crate::planner::sql_evaluator::sql_nodes::SqlNodesFactory; -use crate::planner::BaseMember; -use crate::planner::QueryProperties; -use crate::planner::{BaseMeasure, VisitorContext}; +use crate::planner::sql_evaluator::ReferencesBuilder; +use crate::planner::{BaseMeasure, BaseMember, BaseMemberHelper, QueryProperties}; use cubenativeutils::CubeError; use itertools::Itertools; +use std::collections::HashMap; use std::rc::Rc; pub struct MultipliedMeasuresQueryPlanner { + query_tools: Rc, query_properties: Rc, join_planner: JoinPlanner, common_utils: CommonUtils, - context_factory: Rc, + context_factory: SqlNodesFactory, } impl MultipliedMeasuresQueryPlanner { pub fn new( query_tools: Rc, query_properties: Rc, - context_factory: Rc, + context_factory: SqlNodesFactory, ) -> Self { Self { + query_tools: query_tools.clone(), join_planner: JoinPlanner::new(query_tools.clone()), common_utils: CommonUtils::new(query_tools.clone()), query_properties, @@ -66,40 +74,157 @@ impl MultipliedMeasuresQueryPlanner { let primary_keys_dimensions = self.common_utils.primary_keys_dimensions(key_cube_name)?; let keys_query = self.key_query(&primary_keys_dimensions, key_cube_name)?; let keys_query_alias = format!("keys"); + let should_build_join_for_measure_select = + self.check_should_build_join_for_measure_select(measures, key_cube_name)?; let mut join_builder = - JoinBuilder::new_from_subselect(keys_query, keys_query_alias.clone()); + JoinBuilder::new_from_subselect(keys_query.clone(), keys_query_alias.clone()); let pk_cube = self.common_utils.cube_from_path(key_cube_name.clone())?; let pk_cube_alias = pk_cube.default_alias_with_prefix(&Some(format!("{key_cube_name}_key"))); - join_builder.left_join_cube( - pk_cube.clone(), - Some(pk_cube_alias.clone()), - JoinCondition::new_dimension_join( - keys_query_alias, - pk_cube_alias, - primary_keys_dimensions, - false, - ), - ); - - let mut select_builder = SelectBuilder::new( - From::new_from_join(join_builder.build()), - VisitorContext::new_with_cube_alias_prefix( - self.context_factory.clone(), - format!("{}_key", key_cube_name), - ), - ); + let mut ungrouped_measure_references = HashMap::new(); + if should_build_join_for_measure_select { + let subquery = self.aggregate_subquery_measure_join( + key_cube_name, + &measures, + &primary_keys_dimensions, + )?; + + let conditions = primary_keys_dimensions + .iter() + .map(|dim| { + let alias_in_keys_query = keys_query.schema().resolve_member_alias(dim); + let keys_query_ref = Expr::Reference(QualifiedColumnName::new( + Some(keys_query_alias.clone()), + alias_in_keys_query, + )); + let alias_in_subquery = subquery.schema().resolve_member_alias(dim); + let subquery_ref = Expr::Reference(QualifiedColumnName::new( + Some(pk_cube_alias.clone()), + alias_in_subquery, + )); + (keys_query_ref, subquery_ref) + }) + .collect_vec(); + + for meas in measures.iter() { + ungrouped_measure_references.insert( + meas.full_name(), + QualifiedColumnName::new( + Some(pk_cube_alias.clone()), + subquery + .schema() + .resolve_member_alias(&meas.clone().as_base_member()), + ), + ); + } + + join_builder.left_join_subselect( + subquery, + pk_cube_alias.clone(), + JoinCondition::new_dimension_join(conditions, false), + ); + } else { + let conditions = primary_keys_dimensions + .iter() + .map(|dim| { + let alias_in_keys_query = keys_query.schema().resolve_member_alias(dim); + let keys_query_ref = Expr::Reference(QualifiedColumnName::new( + Some(keys_query_alias.clone()), + alias_in_keys_query, + )); + let pk_cube_expr = Expr::Member(MemberExpression::new(dim.clone())); + (keys_query_ref, pk_cube_expr) + }) + .collect_vec(); + join_builder.left_join_cube( + pk_cube.clone(), + Some(pk_cube_alias.clone()), + JoinCondition::new_dimension_join(conditions, false), + ); + }; + + let from = From::new_from_join(join_builder.build()); + let references_builder = ReferencesBuilder::new(from.clone()); + let mut select_builder = SelectBuilder::new(from.clone()); + let mut render_references = HashMap::new(); for member in self .query_properties - .all_dimensions_and_measures(&measures)? + .all_dimensions_and_measures(&vec![])? .iter() { - select_builder.add_projection_member(member, None, None); + references_builder.resolve_references_for_member( + member.member_evaluator(), + &None, + &mut render_references, + )?; + let alias = references_builder.resolve_alias_for_member(&member.full_name(), &None); + select_builder.add_projection_member(member, alias); + } + for member in BaseMemberHelper::iter_as_base_member(&measures) { + let alias = if !should_build_join_for_measure_select { + references_builder.resolve_references_for_member( + member.member_evaluator(), + &None, + &mut render_references, + )?; + references_builder.resolve_alias_for_member(&member.full_name(), &None) + } else { + None + }; + select_builder.add_projection_member(&member, alias); } select_builder.set_group_by(self.query_properties.group_by()); - Ok(Rc::new(select_builder.build())) + let mut context_factory = self.context_factory.clone(); + context_factory.set_render_references(render_references); + context_factory.set_ungrouped_measure_references(ungrouped_measure_references); + Ok(Rc::new(select_builder.build(context_factory))) + } + + fn check_should_build_join_for_measure_select( + &self, + measures: &Vec>, + key_cube_name: &String, + ) -> Result { + for measure in measures.iter() { + let cubes = collect_cube_names(measure.member_evaluator())?; + let join_hints = collect_join_hints(measure.member_evaluator())?; + if cubes.iter().any(|cube| cube != key_cube_name) { + let measures_join = self.query_tools.join_graph().build_join(join_hints)?; + if *measures_join + .static_data() + .multiplication_factor + .get(key_cube_name) + .unwrap_or(&false) + { + return Err(CubeError::user(format!("{}' references cubes that lead to row multiplication. Please rewrite it using sub query.", measure.full_name()))); + } + return Ok(true); + } + } + Ok(false) + } + fn aggregate_subquery_measure_join( + &self, + _key_cube_name: &String, + measures: &Vec>, + primary_keys_dimensions: &Vec>, + ) -> Result, CubeError> { + let join_hints = collect_join_hints_for_measures(measures)?; + let from = self + .join_planner + .make_join_node_with_prefix_and_join_hints(&None, join_hints)?; + let mut context_factory = self.context_factory.clone(); + context_factory.set_ungrouped_measure(true); + let mut select_builder = SelectBuilder::new(from); + for dim in primary_keys_dimensions.iter() { + select_builder.add_projection_member(dim, None); + } + for meas in measures.iter() { + select_builder.add_projection_member(&meas.clone().as_base_member(), None); + } + Ok(Rc::new(select_builder.build(context_factory))) } fn regular_measures_subquery( @@ -109,23 +234,26 @@ impl MultipliedMeasuresQueryPlanner { let source = self .join_planner .make_join_node_with_prefix(&Some(format!("main")))?; - let mut select_builder = SelectBuilder::new( - source, - VisitorContext::new_with_cube_alias_prefix( - self.context_factory.clone(), - "main".to_string(), - ), - ); + + let mut select_builder = SelectBuilder::new(source.clone()); + let mut context_factory = self.context_factory.clone(); + for time_dim in self.query_properties.time_dimensions() { + if let Some(granularity) = time_dim.get_granularity() { + context_factory.add_leaf_time_dimension(&time_dim.full_name(), &granularity); + } + } + for member in self .query_properties .all_dimensions_and_measures(&measures)? .iter() { - select_builder.add_projection_member(member, None, None); + select_builder.add_projection_member(member, None); } - select_builder.set_filter(self.query_properties.all_filters()); + let filter = self.query_properties.all_filters(); + select_builder.set_filter(filter); select_builder.set_group_by(self.query_properties.group_by()); - Ok(Rc::new(select_builder.build())) + Ok(Rc::new(select_builder.build(context_factory))) } fn key_query( @@ -140,19 +268,19 @@ impl MultipliedMeasuresQueryPlanner { .query_properties .dimensions_for_select_append(dimensions); - let mut select_builder = SelectBuilder::new( - source, - VisitorContext::new_with_cube_alias_prefix( - self.context_factory.clone(), - format!("{}_key", key_cube_name), - ), - ); + let mut select_builder = SelectBuilder::new(source); + let mut context_factory = self.context_factory.clone(); + for time_dim in self.query_properties.time_dimensions() { + if let Some(granularity) = time_dim.get_granularity() { + context_factory.add_leaf_time_dimension(&time_dim.full_name(), &granularity); + } + } for member in dimensions.iter() { - select_builder.add_projection_member(&member, None, None); + select_builder.add_projection_member(&member, None); } select_builder.set_distinct(); select_builder.set_filter(self.query_properties.all_filters()); - Ok(Rc::new(select_builder.build())) + Ok(Rc::new(select_builder.build(context_factory))) } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/order_planner.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/order_planner.rs index ada3ec3df38f9..b5e9d6e2aa856 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/order_planner.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/order_planner.rs @@ -30,7 +30,7 @@ impl OrderPlanner { .find(|(_, m)| m.full_name().to_lowercase() == itm.name().to_lowercase()) { result.push(OrderBy::new( - Expr::Member(MemberExpression::new(member.clone(), None)), + Expr::Member(MemberExpression::new(member.clone())), pos + 1, itm.desc(), )); diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/simple_query_planer.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/simple_query_planer.rs index 981bd6ad4dcfa..9229314a0cc51 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/simple_query_planer.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/simple_query_planer.rs @@ -2,8 +2,7 @@ use super::{JoinPlanner, OrderPlanner}; use crate::plan::{Filter, Select, SelectBuilder}; use crate::planner::query_tools::QueryTools; use crate::planner::sql_evaluator::sql_nodes::SqlNodesFactory; -use crate::planner::QueryProperties; -use crate::planner::VisitorContext; +use crate::planner::{BaseMember, QueryProperties}; use cubenativeutils::CubeError; use std::rc::Rc; @@ -11,13 +10,13 @@ pub struct SimpleQueryPlanner { query_properties: Rc, join_planner: JoinPlanner, order_planner: OrderPlanner, - context_factory: Rc, + context_factory: SqlNodesFactory, } impl SimpleQueryPlanner { pub fn new( query_tools: Rc, query_properties: Rc, - context_factory: Rc, + context_factory: SqlNodesFactory, ) -> Self { Self { join_planner: JoinPlanner::new(query_tools.clone()), @@ -36,16 +35,20 @@ impl SimpleQueryPlanner { items: self.query_properties.measures_filters().clone(), }) }; - let mut select_builder = SelectBuilder::new( - self.join_planner.make_join_node()?, - VisitorContext::default(self.context_factory.clone()), - ); + let mut context_factory = self.context_factory.clone(); + let from = self.join_planner.make_join_node()?; + let mut select_builder = SelectBuilder::new(from.clone()); + for time_dim in self.query_properties.time_dimensions() { + if let Some(granularity) = time_dim.get_granularity() { + context_factory.add_leaf_time_dimension(&time_dim.full_name(), &granularity); + } + } for member in self .query_properties .all_dimensions_and_measures(self.query_properties.measures())? .iter() { - select_builder.add_projection_member(member, None, None); + select_builder.add_projection_member(member, None); } select_builder.set_filter(filter); select_builder.set_group_by(self.query_properties.group_by()); @@ -53,7 +56,7 @@ impl SimpleQueryPlanner { select_builder.set_having(having); select_builder.set_limit(self.query_properties.row_limit()); select_builder.set_offset(self.query_properties.offset()); - let res = select_builder.build(); + let res = select_builder.build(context_factory); Ok(res) } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/query_properties.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/query_properties.rs index 384ff238c12f2..54b31fa40ed20 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/query_properties.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/query_properties.rs @@ -4,9 +4,8 @@ use super::{BaseDimension, BaseMeasure, BaseMember, BaseMemberHelper, BaseTimeDi use crate::cube_bridge::base_query_options::BaseQueryOptions; use crate::plan::{Expr, Filter, FilterItem, MemberExpression}; use crate::planner::sql_evaluator::collectors::{ - collect_multiplied_measures, has_multi_stage_members, + collect_multiplied_measures, has_cumulative_members, has_multi_stage_members, }; -use crate::planner::sql_evaluator::EvaluationNode; use cubenativeutils::CubeError; use itertools::Itertools; use std::collections::HashSet; @@ -32,12 +31,6 @@ impl OrderByItem { } } -enum SymbolAggregateType { - Regular, - Multiplied, - MultiStage, -} - #[derive(Default, Clone)] pub struct FullKeyAggregateMeasures { pub multiplied_measures: Vec>, @@ -67,6 +60,8 @@ pub struct QueryProperties { row_limit: Option, offset: Option, query_tools: Rc, + ignore_cumulative: bool, + ungrouped: bool, } impl QueryProperties { @@ -160,6 +155,7 @@ impl QueryProperties { } else { None }; + let ungrouped = options.static_data().ungrouped.unwrap_or(false); Ok(Rc::new(Self { measures, @@ -172,6 +168,8 @@ impl QueryProperties { row_limit, offset, query_tools, + ignore_cumulative: false, + ungrouped, })) } @@ -186,6 +184,8 @@ impl QueryProperties { order_by: Vec, row_limit: Option, offset: Option, + ignore_cumulative: bool, + ungrouped: bool, ) -> Result, CubeError> { let order_by = if order_by.is_empty() { Self::default_order(&dimensions, &time_dimensions, &measures) @@ -204,6 +204,8 @@ impl QueryProperties { row_limit, offset, query_tools, + ignore_cumulative, + ungrouped, })) } @@ -248,6 +250,10 @@ impl QueryProperties { Self::default_order(&self.dimensions, &self.time_dimensions, &self.measures); } + pub fn ungrouped(&self) -> bool { + self.ungrouped + } + pub fn all_filters(&self) -> Option { let items = self .time_dimensions_filters @@ -322,15 +328,19 @@ impl QueryProperties { } pub fn group_by(&self) -> Vec { - self.dimensions - .iter() - .map(|f| Expr::Member(MemberExpression::new(f.clone(), None))) - .chain( - self.time_dimensions - .iter() - .map(|f| Expr::Member(MemberExpression::new(f.clone(), None))), - ) - .collect() + if self.ungrouped { + vec![] + } else { + self.dimensions + .iter() + .map(|f| Expr::Member(MemberExpression::new(f.clone()))) + .chain( + self.time_dimensions + .iter() + .map(|f| Expr::Member(MemberExpression::new(f.clone()))), + ) + .collect() + } } pub fn default_order( @@ -377,46 +387,44 @@ impl QueryProperties { } pub fn is_simple_query(&self) -> Result { + let full_aggregate_measure = self.full_key_aggregate_measures()?; + if full_aggregate_measure.multiplied_measures.is_empty() + && full_aggregate_measure.multi_stage_measures.is_empty() + { + Ok(true) + } else { + Ok(false) + } + } + + pub fn should_use_time_series(&self) -> Result { for member in self.all_members(false) { - match self.get_symbol_aggregate_type(&member.member_evaluator())? { - SymbolAggregateType::Regular => {} - _ => return Ok(false), + if has_cumulative_members(&member.member_evaluator())? { + return Ok(true); } } - Ok(true) + Ok(false) } pub fn full_key_aggregate_measures(&self) -> Result { let mut result = FullKeyAggregateMeasures::default(); let measures = self.measures(); for m in measures.iter() { - match self.get_symbol_aggregate_type(m.member_evaluator())? { - SymbolAggregateType::Regular => result.regular_measures.push(m.clone()), - SymbolAggregateType::Multiplied => result.multiplied_measures.push(m.clone()), - SymbolAggregateType::MultiStage => result.multi_stage_measures.push(m.clone()), + if has_multi_stage_members(m.member_evaluator(), self.ignore_cumulative)? { + result.multi_stage_measures.push(m.clone()) + } else { + for item in + collect_multiplied_measures(self.query_tools.clone(), m.member_evaluator())? + { + if item.multiplied { + result.multiplied_measures.push(item.measure.clone()); + } else { + result.regular_measures.push(item.measure.clone()); + } + } } } Ok(result) } - - fn get_symbol_aggregate_type( - &self, - symbol: &Rc, - ) -> Result { - let symbol_type = if has_multi_stage_members(symbol)? { - SymbolAggregateType::MultiStage - } else if let Some(multiple) = - collect_multiplied_measures(self.query_tools.clone(), symbol)? - { - if multiple.multiplied { - SymbolAggregateType::Multiplied - } else { - SymbolAggregateType::Regular - } - } else { - SymbolAggregateType::Regular - }; - Ok(symbol_type) - } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/query_tools.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/query_tools.rs index d20896c4bec23..b2cb0497606c8 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/query_tools.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/query_tools.rs @@ -8,6 +8,7 @@ use crate::cube_bridge::sql_templates_render::SqlTemplatesRender; use chrono_tz::Tz; use convert_case::{Case, Casing}; use cubenativeutils::CubeError; +use itertools::Itertools; use lazy_static::lazy_static; use regex::Regex; use std::cell::{Ref, RefCell, RefMut}; @@ -118,6 +119,18 @@ impl QueryTools { } } + pub fn parse_member_path(&self, name: &str) -> Result<(String, String), CubeError> { + let path = name.split('.').collect_vec(); + if path.len() == 2 { + Ok((path[0].to_string(), path[1].to_string())) + } else { + Err(CubeError::internal(format!( + "Invalid member name: '{}'", + name + ))) + } + } + pub fn auto_prefix_with_cube_name(&self, cube_name: &str, sql: &str) -> String { lazy_static! { static ref SINGLE_MEMBER_RE: Regex = Regex::new(r"^[_a-zA-Z][_a-zA-Z0-9]*$").unwrap(); @@ -141,7 +154,7 @@ impl QueryTools { self.templates_render.clone() } - pub fn allocaate_param(&self, name: &str) -> usize { + pub fn allocate_param(&self, name: &str) -> String { self.params_allocator.borrow_mut().allocate_param(name) } pub fn get_allocated_params(&self) -> Vec { @@ -152,8 +165,11 @@ impl QueryTools { sql: &str, should_reuse_params: bool, ) -> Result<(String, Vec), CubeError> { - self.params_allocator - .borrow() - .build_sql_and_params(sql, should_reuse_params) + let native_allocated_params = self.base_tools.get_allocated_params()?; + self.params_allocator.borrow().build_sql_and_params( + sql, + native_allocated_params, + should_reuse_params, + ) } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/cube_names_collector.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/cube_names_collector.rs new file mode 100644 index 0000000000000..73f875a07adc1 --- /dev/null +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/cube_names_collector.rs @@ -0,0 +1,61 @@ +use crate::planner::sql_evaluator::{MemberSymbol, TraversalVisitor}; +use cubenativeutils::CubeError; +use std::collections::HashSet; +use std::rc::Rc; + +pub struct CubeNamesCollector { + names: HashSet, +} + +impl CubeNamesCollector { + pub fn new() -> Self { + Self { + names: HashSet::new(), + } + } + + pub fn extract_result(self) -> Vec { + self.names.into_iter().collect() + } +} + +impl TraversalVisitor for CubeNamesCollector { + type State = (); + fn on_node_traverse( + &mut self, + node: &Rc, + _: &Self::State, + ) -> Result, CubeError> { + match node.as_ref() { + MemberSymbol::Dimension(e) => { + if e.owned_by_cube() { + self.names.insert(e.cube_name().clone()); + } + for name in e.get_dependent_cubes().into_iter() { + self.names.insert(name); + } + } + MemberSymbol::Measure(e) => { + if e.owned_by_cube() { + self.names.insert(e.cube_name().clone()); + } + for name in e.get_dependent_cubes().into_iter() { + self.names.insert(name); + } + } + MemberSymbol::CubeName(e) => { + self.names.insert(e.cube_name().clone()); + } + MemberSymbol::CubeTable(e) => { + self.names.insert(e.cube_name().clone()); + } + }; + Ok(Some(())) + } +} + +pub fn collect_cube_names(node: &Rc) -> Result, CubeError> { + let mut visitor = CubeNamesCollector::new(); + visitor.apply(node, &())?; + Ok(visitor.extract_result()) +} diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/has_cumulative_members.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/has_cumulative_members.rs new file mode 100644 index 0000000000000..deec7e9cbda2c --- /dev/null +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/has_cumulative_members.rs @@ -0,0 +1,48 @@ +use crate::planner::sql_evaluator::{MemberSymbol, TraversalVisitor}; +use cubenativeutils::CubeError; +use std::rc::Rc; + +pub struct HasCumulativeMembersCollector { + pub has_cumulative_members: bool, +} + +impl HasCumulativeMembersCollector { + pub fn new() -> Self { + Self { + has_cumulative_members: false, + } + } + + pub fn extract_result(self) -> bool { + self.has_cumulative_members + } +} + +impl TraversalVisitor for HasCumulativeMembersCollector { + type State = (); + fn on_node_traverse( + &mut self, + node: &Rc, + _: &Self::State, + ) -> Result, CubeError> { + match node.as_ref() { + MemberSymbol::Measure(s) => { + if s.is_rolling_window() { + self.has_cumulative_members = true; + } + } + _ => {} + }; + if self.has_cumulative_members { + Ok(None) + } else { + Ok(Some(())) + } + } +} + +pub fn has_cumulative_members(node: &Rc) -> Result { + let mut visitor = HasCumulativeMembersCollector::new(); + visitor.apply(node, &())?; + Ok(visitor.extract_result()) +} diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/has_multi_stage_members.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/has_multi_stage_members.rs index aedeaf794b7a3..7190d39c469d7 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/has_multi_stage_members.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/has_multi_stage_members.rs @@ -1,14 +1,16 @@ -use crate::planner::sql_evaluator::{EvaluationNode, MemberSymbolType, TraversalVisitor}; +use crate::planner::sql_evaluator::{MemberSymbol, TraversalVisitor}; use cubenativeutils::CubeError; use std::rc::Rc; pub struct HasMultiStageMembersCollector { + pub ignore_cumulative: bool, pub has_multi_stage: bool, } impl HasMultiStageMembersCollector { - pub fn new() -> Self { + pub fn new(ignore_cumulative: bool) -> Self { Self { + ignore_cumulative, has_multi_stage: false, } } @@ -19,33 +21,42 @@ impl HasMultiStageMembersCollector { } impl TraversalVisitor for HasMultiStageMembersCollector { - fn on_node_traverse(&mut self, node: &Rc) -> Result { - match node.symbol() { - MemberSymbolType::Measure(s) => { + type State = (); + fn on_node_traverse( + &mut self, + node: &Rc, + _: &Self::State, + ) -> Result, CubeError> { + match node.as_ref() { + MemberSymbol::Measure(s) => { if s.is_multi_stage() { self.has_multi_stage = true; - } else { - for filter_node in s.measure_filters() { - self.apply(filter_node)? - } - for order_by in s.measure_order_by() { - self.apply(order_by.evaluation_node())? - } + } else if !self.ignore_cumulative + && (s.is_rolling_window() || s.measure_type() == "runningTotal") + { + self.has_multi_stage = true; } } - MemberSymbolType::Dimension(s) => { + MemberSymbol::Dimension(s) => { if s.is_multi_stage() { self.has_multi_stage = true; } } _ => {} }; - Ok(!self.has_multi_stage) + if self.has_multi_stage { + Ok(None) + } else { + Ok(Some(())) + } } } -pub fn has_multi_stage_members(node: &Rc) -> Result { - let mut visitor = HasMultiStageMembersCollector::new(); - visitor.apply(node)?; +pub fn has_multi_stage_members( + node: &Rc, + ignore_cumulative: bool, +) -> Result { + let mut visitor = HasMultiStageMembersCollector::new(ignore_cumulative); + visitor.apply(node, &())?; Ok(visitor.extract_result()) } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/join_hints_collector.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/join_hints_collector.rs index 09e332098364e..b33ea186c6083 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/join_hints_collector.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/join_hints_collector.rs @@ -1,51 +1,69 @@ -use crate::planner::sql_evaluator::{ - EvaluationNode, MemberSymbol, MemberSymbolType, TraversalVisitor, -}; +use crate::planner::sql_evaluator::{MemberSymbol, TraversalVisitor}; +use crate::planner::BaseMeasure; use cubenativeutils::CubeError; -use std::collections::HashSet; use std::rc::Rc; pub struct JoinHintsCollector { - hints: HashSet, + hints: Vec, } impl JoinHintsCollector { pub fn new() -> Self { - Self { - hints: HashSet::new(), - } + Self { hints: Vec::new() } } pub fn extract_result(self) -> Vec { - self.hints.into_iter().collect() + self.hints } } impl TraversalVisitor for JoinHintsCollector { - fn on_node_traverse(&mut self, node: &Rc) -> Result { - let res = match node.symbol() { - MemberSymbolType::Dimension(e) => { + type State = (); + fn on_node_traverse( + &mut self, + node: &Rc, + _: &Self::State, + ) -> Result, CubeError> { + match node.as_ref() { + MemberSymbol::Dimension(e) => { if e.owned_by_cube() { - self.hints.insert(e.cube_name().clone()); + self.hints.push(e.cube_name().clone()); + } + for name in e.get_dependent_cubes().into_iter() { + self.hints.push(name); } - true } - MemberSymbolType::Measure(e) => { + MemberSymbol::Measure(e) => { if e.owned_by_cube() { - self.hints.insert(e.cube_name().clone()); + self.hints.push(e.cube_name().clone()); + } + for name in e.get_dependent_cubes().into_iter() { + self.hints.push(name); } - true } - MemberSymbolType::CubeName(e) => { - self.hints.insert(e.cube_name().clone()); - true + MemberSymbol::CubeName(e) => { + self.hints.push(e.cube_name().clone()); } - MemberSymbolType::CubeTable(e) => { - self.hints.insert(e.cube_name().clone()); - true + MemberSymbol::CubeTable(e) => { + self.hints.push(e.cube_name().clone()); } - _ => false, }; - Ok(res) + Ok(Some(())) + } +} + +pub fn collect_join_hints(node: &Rc) -> Result, CubeError> { + let mut visitor = JoinHintsCollector::new(); + visitor.apply(node, &())?; + Ok(visitor.extract_result()) +} + +pub fn collect_join_hints_for_measures( + measures: &Vec>, +) -> Result, CubeError> { + let mut visitor = JoinHintsCollector::new(); + for meas in measures.iter() { + visitor.apply(&meas.member_evaluator(), &())?; } + Ok(visitor.extract_result()) } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/member_childs_collector.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/member_childs_collector.rs index a2f4de39ddd23..8bb049ee48b6a 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/member_childs_collector.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/member_childs_collector.rs @@ -1,56 +1,60 @@ -use crate::planner::sql_evaluator::{EvaluationNode, MemberSymbolType, TraversalVisitor}; +use crate::planner::sql_evaluator::{MemberSymbol, TraversalVisitor}; use cubenativeutils::CubeError; use std::rc::Rc; pub struct MemberChildsCollector { + pub childs: Vec>, +} + +#[derive(Clone)] +pub struct MemberChildsCollectorState { pub is_root: bool, - pub childs: Vec>, +} + +impl MemberChildsCollectorState { + pub fn new(is_root: bool) -> Self { + Self { is_root } + } } impl MemberChildsCollector { pub fn new() -> Self { - Self { - is_root: true, - childs: vec![], - } + Self { childs: vec![] } } - pub fn extract_result(self) -> Vec> { + pub fn extract_result(self) -> Vec> { self.childs } } impl TraversalVisitor for MemberChildsCollector { - fn on_node_traverse(&mut self, node: &Rc) -> Result { - if self.is_root { - self.is_root = false; - match node.symbol() { - MemberSymbolType::Measure(s) => { - for filter_node in s.measure_filters() { - self.apply(filter_node)? - } - for order_by in s.measure_order_by() { - self.apply(order_by.evaluation_node())? - } - Ok(true) - } - MemberSymbolType::Dimension(_) => Ok(true), - _ => Ok(false), + type State = MemberChildsCollectorState; + fn on_node_traverse( + &mut self, + node: &Rc, + state: &Self::State, + ) -> Result, CubeError> { + if state.is_root { + let new_state = MemberChildsCollectorState::new(false); + match node.as_ref() { + MemberSymbol::Measure(_) => Ok(Some(new_state)), + MemberSymbol::Dimension(_) => Ok(Some(new_state)), + _ => Ok(None), } } else { - match node.symbol() { - MemberSymbolType::Measure(_) | MemberSymbolType::Dimension(_) => { + match node.as_ref() { + MemberSymbol::Measure(_) | MemberSymbol::Dimension(_) => { self.childs.push(node.clone()); - Ok(false) + Ok(None) } - _ => Ok(true), + _ => Ok(Some(state.clone())), } } } } -pub fn member_childs(node: &Rc) -> Result>, CubeError> { +pub fn member_childs(node: &Rc) -> Result>, CubeError> { let mut visitor = MemberChildsCollector::new(); - visitor.apply(node)?; + visitor.apply(node, &MemberChildsCollectorState::new(true))?; Ok(visitor.extract_result()) } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/mod.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/mod.rs index d276385a25241..1a3241bf740c4 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/mod.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/mod.rs @@ -1,9 +1,15 @@ +mod cube_names_collector; +mod has_cumulative_members; mod has_multi_stage_members; mod join_hints_collector; mod member_childs_collector; mod multiplied_measures_collector; +pub use cube_names_collector::collect_cube_names; +pub use has_cumulative_members::{has_cumulative_members, HasCumulativeMembersCollector}; pub use has_multi_stage_members::{has_multi_stage_members, HasMultiStageMembersCollector}; -pub use join_hints_collector::JoinHintsCollector; +pub use join_hints_collector::{ + collect_join_hints, collect_join_hints_for_measures, JoinHintsCollector, +}; pub use member_childs_collector::{member_childs, MemberChildsCollector}; pub use multiplied_measures_collector::{collect_multiplied_measures, MultipliedMeasuresCollector}; diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/multiplied_measures_collector.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/multiplied_measures_collector.rs index 8ee83c026ec8e..c285bff19379f 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/multiplied_measures_collector.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/multiplied_measures_collector.rs @@ -1,39 +1,95 @@ use crate::planner::query_tools::QueryTools; -use crate::planner::sql_evaluator::{ - EvaluationNode, MemberSymbol, MemberSymbolType, TraversalVisitor, -}; +use crate::planner::sql_evaluator::{MemberSymbol, TraversalVisitor}; +use crate::planner::BaseMeasure; use cubenativeutils::CubeError; +use std::collections::HashSet; use std::rc::Rc; -pub struct RootMeasureResult { +struct CompositeMeasuresCollector { + composite_measures: HashSet, +} + +struct CompositeMeasureCollectorState { + pub parent_measure: Option>, +} + +impl CompositeMeasureCollectorState { + pub fn new(parent_measure: Option>) -> Self { + Self { parent_measure } + } +} + +impl CompositeMeasuresCollector { + pub fn new() -> Self { + Self { + composite_measures: HashSet::new(), + } + } + + pub fn extract_result(self) -> HashSet { + self.composite_measures + } +} + +impl TraversalVisitor for CompositeMeasuresCollector { + type State = CompositeMeasureCollectorState; + fn on_node_traverse( + &mut self, + node: &Rc, + state: &Self::State, + ) -> Result, CubeError> { + let res = match node.as_ref() { + MemberSymbol::Measure(_) => { + if let Some(parent) = &state.parent_measure { + if parent.cube_name() != node.cube_name() { + self.composite_measures.insert(parent.full_name()); + } + } + + let new_state = CompositeMeasureCollectorState::new(Some(node.clone())); + Some(new_state) + } + MemberSymbol::Dimension(_) => None, + _ => None, + }; + Ok(res) + } +} + +pub struct MeasureResult { pub multiplied: bool, - pub measure: String, + pub measure: Rc, } pub struct MultipliedMeasuresCollector { query_tools: Rc, - parent_measure: Option, - root_measure: Option, + composite_measures: HashSet, + colllected_measures: Vec, } impl MultipliedMeasuresCollector { - pub fn new(query_tools: Rc) -> Self { + pub fn new(query_tools: Rc, composite_measures: HashSet) -> Self { Self { query_tools, - parent_measure: None, - root_measure: None, + composite_measures, + colllected_measures: vec![], } } - pub fn extract_result(self) -> Option { - self.root_measure + pub fn extract_result(self) -> Vec { + self.colllected_measures } } impl TraversalVisitor for MultipliedMeasuresCollector { - fn on_node_traverse(&mut self, node: &Rc) -> Result { - let res = match node.symbol() { - MemberSymbolType::Measure(e) => { + type State = (); + fn on_node_traverse( + &mut self, + node: &Rc, + _: &Self::State, + ) -> Result, CubeError> { + let res = match node.as_ref() { + MemberSymbol::Measure(e) => { let full_name = e.full_name(); let join = self.query_tools.cached_data().join()?; let multiplied = join @@ -43,17 +99,22 @@ impl TraversalVisitor for MultipliedMeasuresCollector { .unwrap_or(&false) .clone(); - if self.parent_measure.is_none() { - self.root_measure = Some(RootMeasureResult { + if !self.composite_measures.contains(&full_name) { + self.colllected_measures.push(MeasureResult { multiplied, - measure: full_name.clone(), + measure: BaseMeasure::try_new(node.clone(), self.query_tools.clone())? + .unwrap(), }) } - self.parent_measure = Some(full_name); - true + + if self.composite_measures.contains(&full_name) { + Some(()) + } else { + None + } } - MemberSymbolType::Dimension(_) => true, - _ => false, + MemberSymbol::Dimension(_) => None, + _ => None, }; Ok(res) } @@ -61,9 +122,12 @@ impl TraversalVisitor for MultipliedMeasuresCollector { pub fn collect_multiplied_measures( query_tools: Rc, - node: &Rc, -) -> Result, CubeError> { - let mut visitor = MultipliedMeasuresCollector::new(query_tools); - visitor.apply(node)?; + node: &Rc, +) -> Result, CubeError> { + let mut composite_collector = CompositeMeasuresCollector::new(); + composite_collector.apply(node, &CompositeMeasureCollectorState::new(None))?; + let composite_measures = composite_collector.extract_result(); + let mut visitor = MultipliedMeasuresCollector::new(query_tools, composite_measures); + visitor.apply(node, &())?; Ok(visitor.extract_result()) } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/compiler.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/compiler.rs index 97c9eac59b4e3..c23f085fbee99 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/compiler.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/compiler.rs @@ -1,8 +1,9 @@ use super::collectors::JoinHintsCollector; use super::dependecy::DependenciesBuilder; +use super::symbols::MemberSymbol; use super::{ - CubeNameSymbolFactory, CubeTableSymbolFactory, DimensionSymbolFactory, EvaluationNode, - MeasureSymbolFactory, SimpleSqlSymbolFactory, SymbolFactory, TraversalVisitor, + CubeNameSymbolFactory, CubeTableSymbolFactory, DimensionSymbolFactory, MeasureSymbolFactory, + SqlCall, SymbolFactory, TraversalVisitor, }; use crate::cube_bridge::evaluator::CubeEvaluator; use crate::cube_bridge::memeber_sql::MemberSql; @@ -11,7 +12,7 @@ use std::collections::HashMap; use std::rc::Rc; pub struct Compiler { cube_evaluator: Rc, - members: HashMap<(String, String), Rc>, + members: HashMap<(String, String), Rc>, } impl Compiler { @@ -22,22 +23,10 @@ impl Compiler { } } - pub fn add_evaluator( - &mut self, - full_name: &String, - factory: T, - ) -> Result, CubeError> { - if let Some(exists) = self.exists_member::(full_name) { - Ok(exists.clone()) - } else { - self.add_evaluator_impl(full_name, factory) - } - } - pub fn add_measure_evaluator( &mut self, measure: String, - ) -> Result, CubeError> { + ) -> Result, CubeError> { if let Some(exists) = self.exists_member::(&measure) { Ok(exists.clone()) } else { @@ -51,7 +40,7 @@ impl Compiler { pub fn add_dimension_evaluator( &mut self, dimension: String, - ) -> Result, CubeError> { + ) -> Result, CubeError> { if let Some(exists) = self.exists_member::(&dimension) { Ok(exists.clone()) } else { @@ -65,7 +54,7 @@ impl Compiler { pub fn add_cube_name_evaluator( &mut self, cube_name: String, - ) -> Result, CubeError> { + ) -> Result, CubeError> { if let Some(exists) = self.exists_member::(&cube_name) { Ok(exists.clone()) } else { @@ -79,7 +68,7 @@ impl Compiler { pub fn add_cube_table_evaluator( &mut self, cube_name: String, - ) -> Result, CubeError> { + ) -> Result, CubeError> { if let Some(exists) = self.exists_member::(&cube_name) { Ok(exists.clone()) } else { @@ -90,37 +79,26 @@ impl Compiler { } } - pub fn add_join_condition_evaluator( - &mut self, - cube_name: String, - sql: Rc, - ) -> Result, CubeError> { - self.add_evaluator_impl( - &cube_name, - SimpleSqlSymbolFactory::try_new(&cube_name, sql)?, - ) - } - - pub fn add_simple_sql_evaluator( - &mut self, - cube_name: String, - sql: Rc, - ) -> Result, CubeError> { - self.add_evaluator_impl( - &cube_name, - SimpleSqlSymbolFactory::try_new(&cube_name, sql)?, - ) - } - pub fn join_hints(&self) -> Result, CubeError> { let mut collector = JoinHintsCollector::new(); for member in self.members.values() { - collector.apply(member)?; + collector.apply(member, &())?; } Ok(collector.extract_result()) } - fn exists_member(&self, full_name: &String) -> Option> { + pub fn compile_sql_call( + &mut self, + cube_name: &String, + member_sql: Rc, + ) -> Result, CubeError> { + let dep_builder = DependenciesBuilder::new(self, self.cube_evaluator.clone()); + let deps = dep_builder.build(cube_name.clone(), member_sql.clone())?; + let sql_call = SqlCall::new(member_sql, deps); + Ok(Rc::new(sql_call)) + } + + fn exists_member(&self, full_name: &String) -> Option> { if T::is_cachable() { let key = (T::symbol_name(), full_name.clone()); self.members.get(&key).cloned() @@ -133,12 +111,8 @@ impl Compiler { &mut self, full_name: &String, factory: T, - ) -> Result, CubeError> { - let cube_name = factory.cube_name(); - let dep_builder = DependenciesBuilder::new(self, self.cube_evaluator.clone()); - let deps = dep_builder.build(cube_name.clone(), factory.member_sql())?; - - let node = factory.build(deps, self)?; + ) -> Result, CubeError> { + let node = factory.build(self)?; let key = (T::symbol_name().to_string(), full_name.clone()); if T::is_cachable() { self.members.insert(key, node.clone()); diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/dependecy.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/dependecy.rs index a9ac62c42aba6..ce284b26387b3 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/dependecy.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/dependecy.rs @@ -1,23 +1,34 @@ -use super::{Compiler, EvaluationNode}; -use crate::cube_bridge::evaluator::CubeEvaluator; +use super::symbols::MemberSymbol; +use super::Compiler; +use crate::cube_bridge::evaluator::{CallDep, CubeEvaluator}; use crate::cube_bridge::memeber_sql::MemberSql; use cubenativeutils::CubeError; use std::collections::HashMap; use std::rc::Rc; -pub struct StructDependency { - pub sql_fn: Option>, - pub to_string_fn: Option>, - pub properties: HashMap, +#[derive(Clone)] +pub enum CubeDepProperty { + CubeDependency(CubeDependency), + SymbolDependency(Rc), } -impl StructDependency { +#[derive(Clone)] +pub struct CubeDependency { + pub cube_symbol: Rc, + pub sql_fn: Option>, + pub to_string_fn: Option>, + pub properties: HashMap, +} + +impl CubeDependency { pub fn new( - sql_fn: Option>, - to_string_fn: Option>, - properties: HashMap, + cube_symbol: Rc, + sql_fn: Option>, + to_string_fn: Option>, + properties: HashMap, ) -> Self { - StructDependency { + CubeDependency { + cube_symbol, sql_fn, to_string_fn, properties, @@ -25,15 +36,17 @@ impl StructDependency { } } +#[derive(Clone)] pub enum ContextSymbolDep { SecurityContext, FilterParams, FilterGroup, } +#[derive(Clone)] pub enum Dependency { - SingleDependency(Rc), - StructDependency(StructDependency), + SymbolDependency(Rc), + CubeDependency(CubeDependency), ContextDependency(ContextSymbolDep), } @@ -53,14 +66,11 @@ impl<'a> DependenciesBuilder<'a> { pub fn build( mut self, cube_name: String, - member_sql: Option>, + member_sql: Rc, ) -> Result, CubeError> { - let call_deps = if let Some(member_sql) = member_sql { - self.cube_evaluator - .resolve_symbols_call_deps(cube_name.clone(), member_sql)? - } else { - vec![] - }; + let call_deps = self + .cube_evaluator + .resolve_symbols_call_deps(cube_name.clone(), member_sql)?; let mut childs = Vec::new(); for (i, dep) in call_deps.iter().enumerate() { @@ -69,6 +79,7 @@ impl<'a> DependenciesBuilder<'a> { childs[parent].push(i); } } + let mut result = Vec::new(); for (i, dep) in call_deps.iter().enumerate() { @@ -80,50 +91,71 @@ impl<'a> DependenciesBuilder<'a> { continue; } if childs[i].is_empty() { - result.push(Dependency::SingleDependency( + result.push(Dependency::SymbolDependency( self.build_evaluator(&cube_name, &dep.name)?, )); } else { - let new_cube_name = if self.is_current_cube(&dep.name) { - cube_name.clone() - } else { - dep.name.clone() - }; - let mut sql_fn = None; - let mut to_string_fn: Option> = None; - let mut properties = HashMap::new(); - for child_ind in childs[i].iter() { - let name = &call_deps[*child_ind].name; - if name.as_str() == "sql" { - sql_fn = Some( - self.compiler - .add_cube_table_evaluator(new_cube_name.clone())?, - ); - } else if name.as_str() == "toString" { - to_string_fn = Some( - self.compiler - .add_cube_name_evaluator(new_cube_name.clone())?, - ); - } else { - properties.insert( - name.clone(), - Dependency::SingleDependency( - self.build_evaluator(&new_cube_name, &name)?, - ), - ); - } - } - result.push(Dependency::StructDependency(StructDependency::new( - sql_fn, - to_string_fn, - properties, - ))); + let dep = self.build_cube_dependency(&cube_name, i, &call_deps, &childs)?; + result.push(Dependency::CubeDependency(dep)); } } Ok(result) } + fn build_cube_dependency( + &mut self, + cube_name: &String, + dep_index: usize, + call_deps: &Vec, + call_childs: &Vec>, + ) -> Result { + let dep = &call_deps[dep_index]; + let new_cube_name = if self.is_current_cube(&dep.name) { + cube_name.clone() + } else { + dep.name.clone() + }; + let mut sql_fn = None; + let mut to_string_fn: Option> = None; + let mut properties = HashMap::new(); + let cube_symbol = self + .compiler + .add_cube_table_evaluator(new_cube_name.clone())?; + for child_ind in call_childs[dep_index].iter() { + let name = &call_deps[*child_ind].name; + if name.as_str() == "sql" { + sql_fn = Some( + self.compiler + .add_cube_table_evaluator(new_cube_name.clone())?, + ); + } else if name.as_str() == "toString" { + to_string_fn = Some( + self.compiler + .add_cube_name_evaluator(new_cube_name.clone())?, + ); + } else { + let child_dep = if call_childs[*child_ind].is_empty() { + CubeDepProperty::SymbolDependency(self.build_evaluator(&new_cube_name, &name)?) + } else { + CubeDepProperty::CubeDependency(self.build_cube_dependency( + &new_cube_name, + *child_ind, + call_deps, + call_childs, + )?) + }; + properties.insert(name.clone(), child_dep); + } + } + Ok(CubeDependency::new( + cube_symbol, + sql_fn, + to_string_fn, + properties, + )) + } + fn build_context_dep(&self, name: &str) -> Option { match name { "USER_CONTEXT" | "SECURITY_CONTEXT" => Some(Dependency::ContextDependency( @@ -149,7 +181,7 @@ impl<'a> DependenciesBuilder<'a> { &mut self, cube_name: &String, name: &String, - ) -> Result, CubeError> { + ) -> Result, CubeError> { let dep_full_name = format!("{}.{}", cube_name, name); //FIXME avoid cloning let dep_path = vec![cube_name.clone(), name.clone()]; diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/evaluation_node.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/evaluation_node.rs deleted file mode 100644 index 02355626a2c28..0000000000000 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/evaluation_node.rs +++ /dev/null @@ -1,71 +0,0 @@ -use super::dependecy::Dependency; -use super::{ - CubeNameSymbol, CubeTableSymbol, DimensionSymbol, MeasureSymbol, MemberSymbolType, - SimpleSqlSymbol, -}; -use std::rc::Rc; - -pub struct EvaluationNode { - symbol: MemberSymbolType, - deps: Vec, -} - -impl EvaluationNode { - pub fn new(symbol: MemberSymbolType, deps: Vec) -> Rc { - Rc::new(Self { symbol, deps }) - } - - pub fn new_measure(symbol: MeasureSymbol, deps: Vec) -> Rc { - Rc::new(Self { - symbol: MemberSymbolType::Measure(symbol), - deps, - }) - } - - pub fn new_dimension(symbol: DimensionSymbol, deps: Vec) -> Rc { - Rc::new(Self { - symbol: MemberSymbolType::Dimension(symbol), - deps, - }) - } - - pub fn new_cube_name(symbol: CubeNameSymbol) -> Rc { - Rc::new(Self { - symbol: MemberSymbolType::CubeName(symbol), - deps: vec![], - }) - } - - pub fn new_cube_table(symbol: CubeTableSymbol, deps: Vec) -> Rc { - Rc::new(Self { - symbol: MemberSymbolType::CubeTable(symbol), - deps, - }) - } - - pub fn new_simple_sql(symbol: SimpleSqlSymbol, deps: Vec) -> Rc { - Rc::new(Self { - symbol: MemberSymbolType::SimpleSql(symbol), - deps, - }) - } - - pub fn deps(&self) -> &Vec { - &self.deps - } - - pub fn symbol(&self) -> &MemberSymbolType { - &self.symbol - } - - pub fn full_name(&self) -> String { - self.symbol.full_name() - } - - pub fn is_measure(&self) -> bool { - self.symbol.is_measure() - } - pub fn is_dimension(&self) -> bool { - self.symbol.is_dimension() - } -} diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/mod.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/mod.rs index 40a62074f3962..df22f8bc00b64 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/mod.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/mod.rs @@ -1,20 +1,21 @@ pub mod collectors; pub mod compiler; mod dependecy; -pub mod evaluation_node; -pub mod sql_node_transformers; +pub mod references_builder; +pub mod sql_call; pub mod sql_nodes; pub mod sql_visitor; pub mod symbols; pub mod visitor; pub use compiler::Compiler; -pub use dependecy::Dependency; -pub use evaluation_node::EvaluationNode; +pub use dependecy::{CubeDepProperty, Dependency}; +pub use references_builder::ReferencesBuilder; +pub use sql_call::SqlCall; pub use sql_visitor::SqlEvaluatorVisitor; pub use symbols::{ CubeNameSymbol, CubeNameSymbolFactory, CubeTableSymbol, CubeTableSymbolFactory, DimensionSymbol, DimensionSymbolFactory, MeasureSymbol, MeasureSymbolFactory, MemberSymbol, - MemberSymbolType, SimpleSqlSymbol, SimpleSqlSymbolFactory, SymbolFactory, + SymbolFactory, }; pub use visitor::TraversalVisitor; diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/references_builder.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/references_builder.rs new file mode 100644 index 0000000000000..f14f6f15e500d --- /dev/null +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/references_builder.rs @@ -0,0 +1,310 @@ +use crate::plan::{ + Filter, FilterItem, From, Join, QualifiedColumnName, SingleAliasedSource, SingleSource, +}; +use cubenativeutils::CubeError; +use std::collections::HashMap; +use std::rc::Rc; + +use super::MemberSymbol; + +pub struct ReferencesBuilder { + source: Rc, +} + +impl ReferencesBuilder { + pub fn new(source: Rc) -> Self { + Self { source } + } + + pub fn validate_member( + &self, + member: Rc, + strict_source: &Option, + ) -> Result<(), CubeError> { + let member_name = member.full_name(); + if self + .find_reference_for_member(&member_name, strict_source) + .is_some() + { + return Ok(()); + } + + let dependencies = member.get_dependencies(); + if !dependencies.is_empty() { + for dep in dependencies.iter() { + self.validate_member(dep.clone(), strict_source)?; + } + } else { + if !self.has_source_for_leaf_memeber(&member, strict_source) { + return Err(CubeError::internal(format!( + "Planning error: member {} has no source", + member_name + ))); + } + } + Ok(()) + } + + pub fn resolve_references_for_member( + &self, + member: Rc, + strict_source: &Option, + references: &mut HashMap, + ) -> Result<(), CubeError> { + let member_name = member.full_name(); + if let Some(reference) = self.find_reference_for_member(&member_name, strict_source) { + references.insert(member_name.clone(), reference); + return Ok(()); + } + + let dependencies = member.get_dependencies(); + if !dependencies.is_empty() { + for dep in dependencies.iter() { + self.resolve_references_for_member(dep.clone(), strict_source, references)? + } + } else { + if !self.has_source_for_leaf_memeber(&member, strict_source) { + return Err(CubeError::internal(format!( + "Planning error: member {} has no source", + member_name + ))); + } + } + + Ok(()) + } + + pub fn validete_member_for_leaf_query( + &self, + member: Rc, + strict_source: &Option, + ) -> Result<(), CubeError> { + let dependencies = member.get_dependencies(); + if !dependencies.is_empty() { + for dep in dependencies.iter() { + self.validete_member_for_leaf_query(dep.clone(), strict_source)? + } + } else { + if !self.has_source_for_leaf_memeber(&member, strict_source) { + return Err(CubeError::internal(format!( + "Planning error: member {} has no source", + member.full_name() + ))); + } + } + Ok(()) + } + + pub fn validate_filter(&self, filter: &Filter) -> Result<(), CubeError> { + for itm in filter.items.iter() { + self.validate_filter_item(itm)?; + } + Ok(()) + } + + pub fn resolve_references_for_filter( + &self, + filter: &Filter, + references: &mut HashMap, + ) -> Result<(), CubeError> { + for itm in filter.items.iter() { + self.resolve_references_for_filter_item(itm, references)?; + } + Ok(()) + } + + fn validate_filter_item(&self, item: &FilterItem) -> Result<(), CubeError> { + match item { + FilterItem::Item(item) => { + self.validate_member(item.member_evaluator().clone(), &None)? + } + FilterItem::Group(group) => { + for itm in group.items.iter() { + self.validate_filter_item(itm)? + } + } + } + Ok(()) + } + + fn resolve_references_for_filter_item( + &self, + item: &FilterItem, + references: &mut HashMap, + ) -> Result<(), CubeError> { + match item { + FilterItem::Item(item) => self.resolve_references_for_member( + item.member_evaluator().clone(), + &None, + references, + )?, + FilterItem::Group(group) => { + for itm in group.items.iter() { + self.resolve_references_for_filter_item(itm, references)? + } + } + } + Ok(()) + } + + fn has_source_for_leaf_memeber( + &self, + member: &Rc, + strict_source: &Option, + ) -> bool { + match &self.source.source { + crate::plan::FromSource::Empty => false, + crate::plan::FromSource::Single(source) => { + self.is_single_source_has_leaf_member(&source, member, strict_source) + } + crate::plan::FromSource::Join(join) => { + self.is_single_source_has_leaf_member(&join.root, member, strict_source) + || join.joins.iter().any(|itm| { + self.is_single_source_has_leaf_member(&itm.from, member, strict_source) + }) + } + } + } + + fn is_single_source_has_leaf_member( + &self, + source: &SingleAliasedSource, + member: &Rc, + strict_source: &Option, + ) -> bool { + if let Some(strict_source) = strict_source { + if strict_source != &source.alias { + return false; + } + } + + match &source.source { + SingleSource::Cube(cube) => { + cube.name() == &member.cube_name() && cube.has_member(&member.name()) + } + _ => false, + } + } + + pub fn resolve_alias_for_member( + &self, + member_name: &String, + strict_source: &Option, + ) -> Option { + if let Some(reference) = self.find_reference_for_member(member_name, strict_source) { + Some(reference.name().clone()) + } else { + None + } + } + + pub fn find_reference_for_member( + &self, + member_name: &String, + strict_source: &Option, + ) -> Option { + match &self.source.source { + crate::plan::FromSource::Empty => None, + crate::plan::FromSource::Single(source) => self + .find_reference_column_for_member_in_single_source( + &source, + member_name, + strict_source, + ), + crate::plan::FromSource::Join(join) => { + self.find_reference_column_for_member_in_join(&join, member_name, strict_source) + } + } + } + + fn find_reference_column_for_member_in_single_source( + &self, + source: &SingleAliasedSource, + member_name: &String, + strict_source: &Option, + ) -> Option { + if let Some(strict_source) = strict_source { + if strict_source != &source.alias { + return None; + } + } + let column_name = match &source.source { + SingleSource::Subquery(query_plan) => { + query_plan.schema().resolve_member_reference(member_name) + } + SingleSource::Cube(_) => None, + SingleSource::TableReference(_, schema) => schema.resolve_member_reference(member_name), + }; + column_name.map(|col| QualifiedColumnName::new(Some(source.alias.clone()), col)) + } + + fn find_reference_column_for_member_in_join( + &self, + join: &Rc, + member_name: &String, + strict_source: &Option, + ) -> Option { + if let Some(root_ref) = self.find_reference_column_for_member_in_single_source( + &join.root, + member_name, + strict_source, + ) { + return Some(root_ref); + } + join.joins.iter().find_map(|item| { + self.find_reference_column_for_member_in_single_source( + &item.from, + member_name, + strict_source, + ) + }) + } + + /* fn validate_reference(&self, reference: &QualifiedColumnName) -> Result<(), CubeError> { + if self.is_source_has_reference(reference) { + Ok(()) + } else { + Err(CubeError::internal(format!( + "Error while planning: schema does not have reference {}", + reference + ))) + } + } + + fn is_source_has_reference(&self, reference: &QualifiedColumnName) -> bool { + match &self.source.source { + crate::plan::FromSource::Empty => false, + crate::plan::FromSource::Single(source) => { + self.is_single_source_has_reference(&source, reference) + } + crate::plan::FromSource::Join(join) => self.is_join_has_reference(&join, reference), + } + } + + fn is_join_has_reference(&self, join: &Rc, reference: &QualifiedColumnName) -> bool { + if self.is_single_source_has_reference(&join.root, reference) { + return true; + } + join.joins + .iter() + .any(|item| self.is_single_source_has_reference(&item.from, reference)) + } + + fn is_single_source_has_reference( + &self, + source: &SingleAliasedSource, + reference: &QualifiedColumnName, + ) -> bool { + if let Some(reference_source) = &reference.source() { + if reference_source != &source.alias { + return false; + } + } + + match &source.source { + SingleSource::Subquery(query_plan) => query_plan.schema().has_column(reference.name()), + SingleSource::Cube(_) => false, + SingleSource::TableReference(_, schema) => schema.has_column(reference.name()), + } + } */ +} diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_call.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_call.rs new file mode 100644 index 0000000000000..35fed31484c9a --- /dev/null +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_call.rs @@ -0,0 +1,158 @@ +use super::dependecy::{ContextSymbolDep, CubeDepProperty, CubeDependency, Dependency}; +use super::sql_nodes::SqlNode; +use super::{symbols::MemberSymbol, SqlEvaluatorVisitor}; +use crate::cube_bridge::memeber_sql::{ContextSymbolArg, MemberSql, MemberSqlArg, MemberSqlStruct}; +use crate::planner::query_tools::QueryTools; +use cubenativeutils::CubeError; +use std::rc::Rc; + +pub struct SqlCall { + member_sql: Rc, + deps: Vec, +} + +impl SqlCall { + pub fn new(member_sql: Rc, deps: Vec) -> Self { + Self { member_sql, deps } + } + + pub fn eval( + &self, + visitor: &SqlEvaluatorVisitor, + node_processor: Rc, + query_tools: Rc, + ) -> Result { + let args = self + .deps + .iter() + .map(|d| { + self.evaluate_single_dep(&d, visitor, node_processor.clone(), query_tools.clone()) + }) + .collect::, _>>()?; + self.member_sql.call(args) + } + + pub fn extract_symbol_deps(&self, result: &mut Vec>) { + for dep in self.deps.iter() { + match dep { + Dependency::SymbolDependency(dep) => result.push(dep.clone()), + Dependency::CubeDependency(cube_dep) => { + self.extract_symbol_deps_from_cube_dep(cube_dep, result) + } + Dependency::ContextDependency(_) => {} + } + } + } + + pub fn extract_cube_deps(&self, result: &mut Vec) { + for dep in self.deps.iter() { + match dep { + Dependency::SymbolDependency(_) => {} + Dependency::CubeDependency(cube_dep) => { + self.extract_cube_deps_from_cube_dep(cube_dep, result) + } + Dependency::ContextDependency(_) => {} + } + } + } + + fn extract_symbol_deps_from_cube_dep( + &self, + cube_dep: &CubeDependency, + result: &mut Vec>, + ) { + for (_, v) in cube_dep.properties.iter() { + match v { + CubeDepProperty::SymbolDependency(dep) => result.push(dep.clone()), + CubeDepProperty::CubeDependency(cube_dep) => { + self.extract_symbol_deps_from_cube_dep(cube_dep, result) + } + }; + } + } + + fn extract_cube_deps_from_cube_dep(&self, cube_dep: &CubeDependency, result: &mut Vec) { + result.push(cube_dep.cube_symbol.name()); + + for (_, v) in cube_dep.properties.iter() { + match v { + CubeDepProperty::CubeDependency(cube_dep) => { + self.extract_cube_deps_from_cube_dep(cube_dep, result) + } + _ => {} + }; + } + } + + fn evaluate_single_dep( + &self, + dep: &Dependency, + visitor: &SqlEvaluatorVisitor, + node_processor: Rc, + query_tools: Rc, + ) -> Result { + match dep { + Dependency::SymbolDependency(dep) => Ok(MemberSqlArg::String( + visitor.apply(dep, node_processor.clone())?, + )), + Dependency::CubeDependency(dep) => { + self.evaluate_cube_dep(dep, visitor, node_processor.clone(), query_tools.clone()) + } + Dependency::ContextDependency(contex_symbol) => { + self.apply_context_symbol(contex_symbol, query_tools.clone()) + } + } + } + + fn evaluate_cube_dep( + &self, + dep: &CubeDependency, + visitor: &SqlEvaluatorVisitor, + node_processor: Rc, + query_tools: Rc, + ) -> Result { + let mut res = MemberSqlStruct::default(); + if let Some(sql_fn) = &dep.sql_fn { + res.sql_fn = Some(visitor.apply(sql_fn, node_processor.clone())?); + } + if let Some(to_string_fn) = &dep.to_string_fn { + res.to_string_fn = Some(visitor.apply(to_string_fn, node_processor.clone())?); + } + for (k, v) in dep.properties.iter() { + let prop_res = match v { + CubeDepProperty::SymbolDependency(dep) => { + MemberSqlArg::String(visitor.apply(&dep, node_processor.clone())?) + } + CubeDepProperty::CubeDependency(dep) => self.evaluate_cube_dep( + &dep, + visitor, + node_processor.clone(), + query_tools.clone(), + )?, + }; + res.properties.insert(k.clone(), prop_res); + } + Ok(MemberSqlArg::Struct(res)) + } + + pub fn apply_context_symbol( + &self, + context_symbol: &ContextSymbolDep, + query_tools: Rc, + ) -> Result { + let res = match context_symbol { + ContextSymbolDep::SecurityContext => { + MemberSqlArg::ContextSymbol(ContextSymbolArg::SecurityContext( + query_tools.base_tools().security_context_for_rust()?, + )) + } + ContextSymbolDep::FilterParams => MemberSqlArg::ContextSymbol( + ContextSymbolArg::FilterParams(query_tools.base_tools().filters_proxy()?), + ), + ContextSymbolDep::FilterGroup => MemberSqlArg::ContextSymbol( + ContextSymbolArg::FilterGroup(query_tools.base_tools().filter_group_function()?), + ), + }; + Ok(res) + } +} diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_node_transformers/mod.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_node_transformers/mod.rs deleted file mode 100644 index 1c0aeef099360..0000000000000 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_node_transformers/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod set_schema; - -pub use set_schema::set_schema; diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_node_transformers/set_schema.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_node_transformers/set_schema.rs deleted file mode 100644 index d7e580edcac19..0000000000000 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_node_transformers/set_schema.rs +++ /dev/null @@ -1,86 +0,0 @@ -use crate::plan::schema::Schema; -use crate::planner::sql_evaluator::sql_nodes::final_measure::FinalMeasureSqlNode; -use crate::planner::sql_evaluator::sql_nodes::{ - AutoPrefixSqlNode, EvaluateSqlNode, MeasureFilterSqlNode, MultiStageRankNode, - MultiStageWindowNode, RenderReferencesSqlNode, RootSqlNode, SqlNode, TimeShiftSqlNode, -}; -use std::rc::Rc; - -pub fn set_schema(node_processors: Rc, schema: Rc) -> Rc { - set_schema_impl(node_processors, schema) -} - -pub fn set_schema_impl(sql_node: Rc, schema: Rc) -> Rc { - if let Some(auto_prefix) = sql_node - .clone() - .as_any() - .downcast_ref::() - { - let input = set_schema_impl(auto_prefix.input().clone(), schema.clone()); - AutoPrefixSqlNode::new_with_schema(input, schema) - } else if let Some(_) = sql_node.clone().as_any().downcast_ref::() { - sql_node - } else if let Some(final_measure) = sql_node - .clone() - .as_any() - .downcast_ref::() - { - let input = set_schema_impl(final_measure.input().clone(), schema.clone()); - FinalMeasureSqlNode::new(input) - } else if let Some(measure_filter) = sql_node - .clone() - .as_any() - .downcast_ref::() - { - let input = set_schema_impl(measure_filter.input().clone(), schema.clone()); - MeasureFilterSqlNode::new(input) - } else if let Some(multi_stage_rank) = sql_node - .clone() - .as_any() - .downcast_ref::() - { - let else_processor = - set_schema_impl(multi_stage_rank.else_processor().clone(), schema.clone()); - MultiStageRankNode::new(else_processor, multi_stage_rank.partition().clone()) - } else if let Some(multi_stage_window) = sql_node - .clone() - .as_any() - .downcast_ref::() - { - let input = set_schema_impl(multi_stage_window.input().clone(), schema.clone()); - let else_processor = - set_schema_impl(multi_stage_window.else_processor().clone(), schema.clone()); - MultiStageWindowNode::new( - input, - else_processor, - multi_stage_window.partition().clone(), - ) - } else if let Some(render_references) = sql_node - .clone() - .as_any() - .downcast_ref::() - { - let input = set_schema_impl(render_references.input().clone(), schema.clone()); - RenderReferencesSqlNode::new_with_schema(input, schema) - } else if let Some(root_node) = sql_node.clone().as_any().downcast_ref::() { - let dimension_processor = - set_schema_impl(root_node.dimension_processor().clone(), schema.clone()); - let measure_processor = - set_schema_impl(root_node.measure_processor().clone(), schema.clone()); - let cube_name_processor = - set_schema_impl(root_node.cube_name_processor().clone(), schema.clone()); - let default_processor = - set_schema_impl(root_node.default_processor().clone(), schema.clone()); - RootSqlNode::new( - dimension_processor, - measure_processor, - cube_name_processor, - default_processor, - ) - } else if let Some(time_shift) = sql_node.clone().as_any().downcast_ref::() { - let input = set_schema_impl(time_shift.input().clone(), schema.clone()); - TimeShiftSqlNode::new(time_shift.shifts().clone(), input) - } else { - unreachable!("Not all nodes are implemented"); - } -} diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/auto_prefix.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/auto_prefix.rs index e0ce9d3093ab9..708242bb1bcdc 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/auto_prefix.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/auto_prefix.rs @@ -1,27 +1,38 @@ use super::SqlNode; use crate::plan::Schema; use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::MemberSymbol; use crate::planner::sql_evaluator::SqlEvaluatorVisitor; -use crate::planner::sql_evaluator::{EvaluationNode, MemberSymbol, MemberSymbolType}; use cubenativeutils::CubeError; use std::any::Any; +use std::collections::HashMap; use std::rc::Rc; pub struct AutoPrefixSqlNode { input: Rc, + cube_references: HashMap, schema: Rc, } impl AutoPrefixSqlNode { - pub fn new(input: Rc) -> Rc { + pub fn new(input: Rc, cube_references: HashMap) -> Rc { Rc::new(Self { input, + cube_references, schema: Rc::new(Schema::empty()), }) } - pub fn new_with_schema(input: Rc, schema: Rc) -> Rc { - Rc::new(Self { input, schema }) + pub fn new_with_schema( + input: Rc, + cube_references: HashMap, + schema: Rc, + ) -> Rc { + Rc::new(Self { + input, + schema, + cube_references, + }) } pub fn input(&self) -> &Rc { @@ -31,30 +42,42 @@ impl AutoPrefixSqlNode { pub fn schema(&self) -> &Rc { &self.schema } + + pub fn cube_references(&self) -> &HashMap { + &self.cube_references + } + + fn resolve_cube_alias(&self, name: &String) -> String { + if let Some(alias) = self.cube_references.get(name) { + alias.clone() + } else { + name.clone() + } + } } impl SqlNode for AutoPrefixSqlNode { fn to_sql( &self, - visitor: &mut SqlEvaluatorVisitor, - node: &Rc, + visitor: &SqlEvaluatorVisitor, + node: &Rc, query_tools: Rc, node_processor: Rc, ) -> Result { let input = self.input .to_sql(visitor, node, query_tools.clone(), node_processor.clone())?; - let res = match node.symbol() { - MemberSymbolType::Dimension(ev) => { - let cube_alias = self.schema.resolve_cube_alias(&ev.cube_name()); + let res = match node.as_ref() { + MemberSymbol::Dimension(ev) => { + let cube_alias = self.resolve_cube_alias(&ev.cube_name()); query_tools.auto_prefix_with_cube_name(&cube_alias, &input) } - MemberSymbolType::Measure(ev) => { - let cube_alias = self.schema.resolve_cube_alias(&ev.cube_name()); + MemberSymbol::Measure(ev) => { + let cube_alias = self.resolve_cube_alias(&ev.cube_name()); query_tools.auto_prefix_with_cube_name(&cube_alias, &input) } - MemberSymbolType::CubeName(_) => { - let cube_alias = self.schema.resolve_cube_alias(&input); + MemberSymbol::CubeName(_) => { + let cube_alias = self.resolve_cube_alias(&input); query_tools.escape_column_name(&cube_alias) } _ => input, diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/evaluate_sql.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/evaluate_sql.rs index 0acd90c5f868d..63587cb9289ed 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/evaluate_sql.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/evaluate_sql.rs @@ -1,7 +1,7 @@ use super::SqlNode; use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::MemberSymbol; use crate::planner::sql_evaluator::SqlEvaluatorVisitor; -use crate::planner::sql_evaluator::{EvaluationNode, MemberSymbolType}; use cubenativeutils::CubeError; use std::any::Any; use std::rc::Rc; @@ -17,18 +17,22 @@ impl EvaluateSqlNode { impl SqlNode for EvaluateSqlNode { fn to_sql( &self, - visitor: &mut SqlEvaluatorVisitor, - node: &Rc, - _query_tools: Rc, + visitor: &SqlEvaluatorVisitor, + node: &Rc, + query_tools: Rc, node_processor: Rc, ) -> Result { - let args = visitor.evaluate_deps(node, node_processor.clone())?; - match node.symbol() { - MemberSymbolType::Dimension(ev) => ev.evaluate_sql(args), - MemberSymbolType::Measure(ev) => ev.evaluate_sql(args), - MemberSymbolType::CubeTable(ev) => ev.evaluate_sql(args), - MemberSymbolType::CubeName(ev) => ev.evaluate_sql(args), - MemberSymbolType::SimpleSql(ev) => ev.evaluate_sql(args), + match node.as_ref() { + MemberSymbol::Dimension(ev) => { + ev.evaluate_sql(visitor, node_processor.clone(), query_tools.clone()) + } + MemberSymbol::Measure(ev) => { + ev.evaluate_sql(visitor, node_processor.clone(), query_tools.clone()) + } + MemberSymbol::CubeTable(ev) => { + ev.evaluate_sql(visitor, node_processor.clone(), query_tools.clone()) + } + MemberSymbol::CubeName(ev) => ev.evaluate_sql(), } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/factory.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/factory.rs index 9d8729896e84d..a288558b292e8 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/factory.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/factory.rs @@ -1,83 +1,184 @@ +use super::leaf_time_dimension::LeafTimeDimensionNode; use super::{ AutoPrefixSqlNode, EvaluateSqlNode, FinalMeasureSqlNode, MeasureFilterSqlNode, - MultiStageRankNode, MultiStageWindowNode, RenderReferencesSqlNode, RootSqlNode, SqlNode, - TimeShiftSqlNode, + MultiStageRankNode, MultiStageWindowNode, RenderReferencesSqlNode, RollingWindowNode, + RootSqlNode, SqlNode, TimeShiftSqlNode, UngroupedMeasureSqlNode, + UngroupedQueryFinalMeasureSqlNode, }; +use crate::plan::schema::QualifiedColumnName; use std::collections::HashMap; use std::rc::Rc; +#[derive(Clone)] pub struct SqlNodesFactory { - time_shifts: Option>, + time_shifts: HashMap, + ungrouped: bool, + ungrouped_measure: bool, + render_references: HashMap, + ungrouped_measure_references: HashMap, + leaf_time_dimensions: HashMap, + cube_name_references: HashMap, + multi_stage_rank: Option>, //partition_by + multi_stage_window: Option>, //partition_by + rolling_window: bool, } impl SqlNodesFactory { - pub fn new() -> Rc { - Rc::new(Self { time_shifts: None }) + pub fn new() -> Self { + Self { + time_shifts: HashMap::new(), + ungrouped: false, + ungrouped_measure: false, + render_references: HashMap::new(), + ungrouped_measure_references: HashMap::new(), + cube_name_references: HashMap::new(), + leaf_time_dimensions: HashMap::new(), + multi_stage_rank: None, + multi_stage_window: None, + rolling_window: false, + } + } + + pub fn set_time_shifts(&mut self, time_shifts: HashMap) { + self.time_shifts = time_shifts; + } + + pub fn set_ungrouped(&mut self, value: bool) { + self.ungrouped = value; + } + + pub fn set_ungrouped_measure(&mut self, value: bool) { + self.ungrouped_measure = value; + } + + pub fn set_render_references(&mut self, value: HashMap) { + self.render_references = value; + } + + pub fn render_references(&self) -> &HashMap { + &self.render_references + } + + pub fn add_render_reference(&mut self, key: String, value: QualifiedColumnName) { + self.render_references.insert(key, value); + } + + pub fn set_multi_stage_rank(&mut self, partition_by: Vec) { + self.multi_stage_rank = Some(partition_by); } - pub fn new_with_time_shifts(time_shifts: HashMap) -> Rc { - Rc::new(Self { - time_shifts: Some(time_shifts), - }) + + pub fn add_leaf_time_dimension(&mut self, dimension_name: &String, granularity: &String) { + self.leaf_time_dimensions + .insert(dimension_name.clone(), granularity.clone()); + } + + pub fn set_multi_stage_window(&mut self, partition_by: Vec) { + self.multi_stage_window = Some(partition_by); + } + + pub fn set_rolling_window(&mut self, value: bool) { + self.rolling_window = value; + } + + pub fn set_ungrouped_measure_references( + &mut self, + value: HashMap, + ) { + self.ungrouped_measure_references = value; } + + pub fn add_ungrouped_measure_reference(&mut self, key: String, value: QualifiedColumnName) { + self.ungrouped_measure_references.insert(key, value); + } + + pub fn set_cube_name_references(&mut self, value: HashMap) { + self.cube_name_references = value; + } + + pub fn add_cube_name_reference(&mut self, key: String, value: String) { + self.cube_name_references.insert(key, value); + } + pub fn default_node_processor(&self) -> Rc { let evaluate_sql_processor = EvaluateSqlNode::new(); - let auto_prefix_processor = AutoPrefixSqlNode::new(evaluate_sql_processor.clone()); - let measure_filter_processor = MeasureFilterSqlNode::new(auto_prefix_processor.clone()); - let final_measure_processor = FinalMeasureSqlNode::new(measure_filter_processor.clone()); - let root_node = RootSqlNode::new( - self.dimension_processor(auto_prefix_processor.clone()), - final_measure_processor.clone(), - auto_prefix_processor.clone(), + let auto_prefix_processor = AutoPrefixSqlNode::new( evaluate_sql_processor.clone(), + self.cube_name_references.clone(), ); - RenderReferencesSqlNode::new(root_node) - } - pub fn multi_stage_rank_node_processor(&self, partition: Vec) -> Rc { - let evaluate_sql_processor = EvaluateSqlNode::new(); - let auto_prefix_processor = AutoPrefixSqlNode::new(evaluate_sql_processor.clone()); let measure_filter_processor = MeasureFilterSqlNode::new(auto_prefix_processor.clone()); - let final_measure_processor = FinalMeasureSqlNode::new(measure_filter_processor.clone()); - let rank_processor = MultiStageRankNode::new(final_measure_processor.clone(), partition); + let measure_processor = + self.add_ungrouped_measure_reference_if_needed(measure_filter_processor.clone()); + let measure_processor = self.final_measure_node_processor(measure_processor); + let measure_processor = self + .add_multi_stage_window_if_needed(measure_processor, measure_filter_processor.clone()); + let measure_processor = self.add_multi_stage_rank_if_needed(measure_processor); - let root_processor = RootSqlNode::new( + let root_node = RootSqlNode::new( self.dimension_processor(auto_prefix_processor.clone()), - rank_processor.clone(), + measure_processor.clone(), auto_prefix_processor.clone(), evaluate_sql_processor.clone(), ); - let references_processor = RenderReferencesSqlNode::new(root_processor); - references_processor + RenderReferencesSqlNode::new(root_node, self.render_references.clone()) } - pub fn multi_stage_window_node_processor(&self, partition: Vec) -> Rc { - let evaluate_sql_processor = EvaluateSqlNode::new(); - let auto_prefix_processor = AutoPrefixSqlNode::new(evaluate_sql_processor.clone()); - let measure_filter_processor = MeasureFilterSqlNode::new(auto_prefix_processor.clone()); - let final_measure_processor = FinalMeasureSqlNode::new(measure_filter_processor.clone()); + fn add_ungrouped_measure_reference_if_needed( + &self, + default: Rc, + ) -> Rc { + if !self.ungrouped_measure_references.is_empty() { + RenderReferencesSqlNode::new(default, self.ungrouped_measure_references.clone()) + } else { + default + } + } - let window_processor = MultiStageWindowNode::new( - evaluate_sql_processor.clone(), - final_measure_processor.clone(), - partition, - ); + fn add_multi_stage_rank_if_needed(&self, default: Rc) -> Rc { + if let Some(partition_by) = &self.multi_stage_rank { + MultiStageRankNode::new(default, partition_by.clone()) + } else { + default + } + } - let root_processor = RootSqlNode::new( - self.dimension_processor(auto_prefix_processor.clone()), - window_processor.clone(), - auto_prefix_processor.clone(), - evaluate_sql_processor.clone(), - ); - let references_processor = RenderReferencesSqlNode::new(root_processor); - references_processor + fn add_multi_stage_window_if_needed( + &self, + default: Rc, + multi_stage_input: Rc, + ) -> Rc { + if let Some(partition_by) = &self.multi_stage_window { + MultiStageWindowNode::new(multi_stage_input, default, partition_by.clone()) + } else { + default + } + } + + fn final_measure_node_processor(&self, input: Rc) -> Rc { + if self.ungrouped_measure { + UngroupedMeasureSqlNode::new(input) + } else if self.ungrouped { + UngroupedQueryFinalMeasureSqlNode::new(input) + } else if self.rolling_window { + RollingWindowNode::new(input) + } else { + FinalMeasureSqlNode::new(input) + } } fn dimension_processor(&self, input: Rc) -> Rc { - if let Some(time_shifts) = &self.time_shifts { - TimeShiftSqlNode::new(time_shifts.clone(), input) + let input = if !&self.time_shifts.is_empty() { + TimeShiftSqlNode::new(self.time_shifts.clone(), input) } else { input - } + }; + + let input = if !&self.leaf_time_dimensions.is_empty() { + LeafTimeDimensionNode::new(input, self.leaf_time_dimensions.clone()) + } else { + input + }; + input } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/final_measure.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/final_measure.rs index 2fd786a986f9e..c844c2a786de4 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/final_measure.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/final_measure.rs @@ -1,7 +1,7 @@ use super::SqlNode; use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::MemberSymbol; use crate::planner::sql_evaluator::SqlEvaluatorVisitor; -use crate::planner::sql_evaluator::{EvaluationNode, MemberSymbolType}; use cubenativeutils::CubeError; use std::any::Any; use std::rc::Rc; @@ -23,24 +23,30 @@ impl FinalMeasureSqlNode { impl SqlNode for FinalMeasureSqlNode { fn to_sql( &self, - visitor: &mut SqlEvaluatorVisitor, - node: &Rc, + visitor: &SqlEvaluatorVisitor, + node: &Rc, query_tools: Rc, node_processor: Rc, ) -> Result { - let res = match node.symbol() { - MemberSymbolType::Measure(ev) => { + let res = match node.as_ref() { + MemberSymbol::Measure(ev) => { let input = self.input.to_sql( visitor, node, query_tools.clone(), node_processor.clone(), )?; + //}; if ev.is_calculated() { input } else { - let measure_type = ev.measure_type(); + let measure_type = if ev.measure_type() == "runningTotal" { + "sum" + } else { + &ev.measure_type() + }; + format!("{}({})", measure_type, input) } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/leaf_time_dimension.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/leaf_time_dimension.rs new file mode 100644 index 0000000000000..92c06ec1e6ea1 --- /dev/null +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/leaf_time_dimension.rs @@ -0,0 +1,55 @@ +use super::SqlNode; +use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::MemberSymbol; +use crate::planner::sql_evaluator::SqlEvaluatorVisitor; +use cubenativeutils::CubeError; +use std::any::Any; +use std::collections::HashMap; +use std::rc::Rc; + +pub struct LeafTimeDimensionNode { + input: Rc, + leaf_time_dimensions: HashMap, +} + +impl LeafTimeDimensionNode { + pub fn new(input: Rc, leaf_time_dimensions: HashMap) -> Rc { + Rc::new(Self { + input, + leaf_time_dimensions, + }) + } +} + +impl SqlNode for LeafTimeDimensionNode { + fn to_sql( + &self, + visitor: &SqlEvaluatorVisitor, + node: &Rc, + query_tools: Rc, + node_processor: Rc, + ) -> Result { + let full_name = node.full_name(); + let input_sql = self + .input + .to_sql(visitor, node, query_tools.clone(), node_processor)?; + + let res = if let Some(granularity) = self.leaf_time_dimensions.get(&full_name) { + let converted_tz = query_tools.base_tools().convert_tz(input_sql)?; + query_tools + .base_tools() + .time_grouped_column(granularity.clone(), converted_tz)? + } else { + input_sql + }; + Ok(res) + } + + fn as_any(self: Rc) -> Rc { + self.clone() + } + + fn childs(&self) -> Vec> { + vec![self.input.clone()] + } +} diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/measure_filter.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/measure_filter.rs index 52a6683190fea..e9f7c771c77e6 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/measure_filter.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/measure_filter.rs @@ -1,7 +1,7 @@ use super::SqlNode; use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::MemberSymbol; use crate::planner::sql_evaluator::SqlEvaluatorVisitor; -use crate::planner::sql_evaluator::{EvaluationNode, MemberSymbolType}; use cubenativeutils::CubeError; use std::any::Any; use std::rc::Rc; @@ -23,16 +23,16 @@ impl MeasureFilterSqlNode { impl SqlNode for MeasureFilterSqlNode { fn to_sql( &self, - visitor: &mut SqlEvaluatorVisitor, - node: &Rc, + visitor: &SqlEvaluatorVisitor, + node: &Rc, query_tools: Rc, node_processor: Rc, ) -> Result { let input = self.input .to_sql(visitor, node, query_tools.clone(), node_processor.clone())?; - let res = match node.symbol() { - MemberSymbolType::Measure(ev) => { + let res = match node.as_ref() { + MemberSymbol::Measure(ev) => { let measure_filters = ev.measure_filters(); if !measure_filters.is_empty() { let filters = measure_filters @@ -40,7 +40,11 @@ impl SqlNode for MeasureFilterSqlNode { .map(|filter| -> Result { Ok(format!( "({})", - visitor.apply(filter, node_processor.clone())? + filter.eval( + &visitor, + node_processor.clone(), + query_tools.clone() + )? )) }) .collect::, _>>()? diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/mod.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/mod.rs index 9cb6190581a9d..346fb326cc689 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/mod.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/mod.rs @@ -2,13 +2,17 @@ pub mod auto_prefix; pub mod evaluate_sql; pub mod factory; pub mod final_measure; +pub mod leaf_time_dimension; pub mod measure_filter; pub mod multi_stage_rank; pub mod multi_stage_window; pub mod render_references; +pub mod rolling_window; pub mod root_processor; pub mod sql_node; pub mod time_shift; +pub mod ungroupped_measure; +pub mod ungroupped_query_final_measure; pub use auto_prefix::AutoPrefixSqlNode; pub use evaluate_sql::EvaluateSqlNode; @@ -18,6 +22,9 @@ pub use measure_filter::MeasureFilterSqlNode; pub use multi_stage_rank::MultiStageRankNode; pub use multi_stage_window::MultiStageWindowNode; pub use render_references::RenderReferencesSqlNode; +pub use rolling_window::RollingWindowNode; pub use root_processor::RootSqlNode; pub use sql_node::SqlNode; pub use time_shift::TimeShiftSqlNode; +pub use ungroupped_measure::UngroupedMeasureSqlNode; +pub use ungroupped_query_final_measure::UngroupedQueryFinalMeasureSqlNode; diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/multi_stage_rank.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/multi_stage_rank.rs index 79780132b46a5..493de8228d6c9 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/multi_stage_rank.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/multi_stage_rank.rs @@ -1,7 +1,7 @@ use super::SqlNode; use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::MemberSymbol; use crate::planner::sql_evaluator::SqlEvaluatorVisitor; -use crate::planner::sql_evaluator::{EvaluationNode, MemberSymbolType}; use cubenativeutils::CubeError; use std::any::Any; use std::rc::Rc; @@ -31,21 +31,24 @@ impl MultiStageRankNode { impl SqlNode for MultiStageRankNode { fn to_sql( &self, - visitor: &mut SqlEvaluatorVisitor, - node: &Rc, + visitor: &SqlEvaluatorVisitor, + node: &Rc, query_tools: Rc, node_processor: Rc, ) -> Result { - let res = match node.symbol() { - MemberSymbolType::Measure(m) => { + let res = match node.as_ref() { + MemberSymbol::Measure(m) => { if m.is_multi_stage() && m.measure_type() == "rank" { let order_by = if !m.measure_order_by().is_empty() { let sql = m .measure_order_by() .iter() .map(|item| -> Result { - let sql = visitor - .apply(item.evaluation_node(), node_processor.clone())?; + let sql = item.sql_call().eval( + visitor, + node_processor.clone(), + query_tools.clone(), + )?; Ok(format!("{} {}", sql, item.direction())) }) .collect::, _>>()? diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/multi_stage_window.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/multi_stage_window.rs index 5007ccc7a0b95..4d1fc74c6b2b0 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/multi_stage_window.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/multi_stage_window.rs @@ -1,6 +1,6 @@ use super::SqlNode; use crate::planner::query_tools::QueryTools; -use crate::planner::sql_evaluator::{EvaluationNode, MemberSymbolType, SqlEvaluatorVisitor}; +use crate::planner::sql_evaluator::{MemberSymbol, SqlEvaluatorVisitor}; use cubenativeutils::CubeError; use std::any::Any; use std::rc::Rc; @@ -40,13 +40,13 @@ impl MultiStageWindowNode { impl SqlNode for MultiStageWindowNode { fn to_sql( &self, - visitor: &mut SqlEvaluatorVisitor, - node: &Rc, + visitor: &SqlEvaluatorVisitor, + node: &Rc, query_tools: Rc, node_processor: Rc, ) -> Result { - let res = match node.symbol() { - MemberSymbolType::Measure(m) => { + let res = match node.as_ref() { + MemberSymbol::Measure(m) => { if m.is_multi_stage() && !m.is_calculated() { let input_sql = self.input.to_sql( visitor, diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/render_references.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/render_references.rs index 6f6a94ec01070..9d4e17a8687ce 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/render_references.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/render_references.rs @@ -1,27 +1,24 @@ use super::SqlNode; -use crate::plan::Schema; +use crate::plan::QualifiedColumnName; use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::MemberSymbol; use crate::planner::sql_evaluator::SqlEvaluatorVisitor; -use crate::planner::sql_evaluator::{EvaluationNode, MemberSymbolType}; use cubenativeutils::CubeError; use std::any::Any; +use std::collections::HashMap; use std::rc::Rc; pub struct RenderReferencesSqlNode { input: Rc, - schema: Rc, + references: HashMap, } impl RenderReferencesSqlNode { - pub fn new(input: Rc) -> Rc { - Rc::new(Self { - input, - schema: Rc::new(Schema::empty()), - }) - } - - pub fn new_with_schema(input: Rc, schema: Rc) -> Rc { - Rc::new(Self { input, schema }) + pub fn new( + input: Rc, + references: HashMap, + ) -> Rc { + Rc::new(Self { input, references }) } pub fn input(&self) -> &Rc { @@ -32,30 +29,21 @@ impl RenderReferencesSqlNode { impl SqlNode for RenderReferencesSqlNode { fn to_sql( &self, - visitor: &mut SqlEvaluatorVisitor, - node: &Rc, + visitor: &SqlEvaluatorVisitor, + node: &Rc, query_tools: Rc, node_processor: Rc, ) -> Result { - let reference_column = match node.symbol() { - MemberSymbolType::Dimension(ev) => { - self.schema.find_column_for_member(&ev.full_name(), &None) - } - MemberSymbolType::Measure(ev) => { - self.schema.find_column_for_member(&ev.full_name(), &None) - } - _ => None, - }; - - if let Some(reference_column) = reference_column { - let table_ref = reference_column.table_name.as_ref().map_or_else( + let full_name = node.full_name(); + if let Some(reference) = self.references.get(&full_name) { + let table_ref = reference.source().as_ref().map_or_else( || format!(""), |table_name| format!("{}.", query_tools.escape_column_name(table_name)), ); Ok(format!( "{}{}", table_ref, - query_tools.escape_column_name(&reference_column.alias) + query_tools.escape_column_name(&reference.name()) )) } else { self.input diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/rolling_window.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/rolling_window.rs new file mode 100644 index 0000000000000..b6bcc87431855 --- /dev/null +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/rolling_window.rs @@ -0,0 +1,66 @@ +use super::SqlNode; +use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::{MemberSymbol, SqlEvaluatorVisitor}; +use cubenativeutils::CubeError; +use std::any::Any; +use std::rc::Rc; + +pub struct RollingWindowNode { + input: Rc, +} + +impl RollingWindowNode { + pub fn new(input: Rc) -> Rc { + Rc::new(Self { input }) + } + + pub fn input(&self) -> &Rc { + &self.input + } +} + +impl SqlNode for RollingWindowNode { + fn to_sql( + &self, + visitor: &SqlEvaluatorVisitor, + node: &Rc, + query_tools: Rc, + node_processor: Rc, + ) -> Result { + let res = match node.as_ref() { + MemberSymbol::Measure(m) => { + let input = + self.input + .to_sql(visitor, node, query_tools.clone(), node_processor)?; + if m.is_cumulative() { + let aggregate_function = if m.measure_type() == "sum" + || m.measure_type() == "count" + || m.measure_type() == "runningTotal" + { + "sum" + } else { + m.measure_type() + }; + + format!("{}({})", aggregate_function, input) + } else { + input + } + } + _ => { + return Err(CubeError::internal(format!( + "Unexpected evaluation node type for RollingWindowNode" + ))); + } + }; + Ok(res) + } + + fn as_any(self: Rc) -> Rc { + self.clone() + } + + fn childs(&self) -> Vec> { + vec![self.input.clone()] + } +} diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/root_processor.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/root_processor.rs index 6788f7115000c..16696687864aa 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/root_processor.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/root_processor.rs @@ -1,7 +1,7 @@ use super::SqlNode; use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::MemberSymbol; use crate::planner::sql_evaluator::SqlEvaluatorVisitor; -use crate::planner::sql_evaluator::{EvaluationNode, MemberSymbolType}; use cubenativeutils::CubeError; use std::any::Any; use std::rc::Rc; @@ -48,25 +48,25 @@ impl RootSqlNode { impl SqlNode for RootSqlNode { fn to_sql( &self, - visitor: &mut SqlEvaluatorVisitor, - node: &Rc, + visitor: &SqlEvaluatorVisitor, + node: &Rc, query_tools: Rc, node_processor: Rc, ) -> Result { - let res = match node.symbol() { - MemberSymbolType::Dimension(_) => self.dimension_processor.to_sql( + let res = match node.as_ref() { + MemberSymbol::Dimension(_) => self.dimension_processor.to_sql( visitor, node, query_tools.clone(), node_processor.clone(), )?, - MemberSymbolType::Measure(_) => self.measure_processor.to_sql( + MemberSymbol::Measure(_) => self.measure_processor.to_sql( visitor, node, query_tools.clone(), node_processor.clone(), )?, - MemberSymbolType::CubeName(_) => self.cube_name_processor.to_sql( + MemberSymbol::CubeName(_) => self.cube_name_processor.to_sql( visitor, node, query_tools.clone(), diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/sql_node.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/sql_node.rs index 1415f1d24bfc8..1755c36e2817d 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/sql_node.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/sql_node.rs @@ -1,5 +1,5 @@ use crate::planner::query_tools::QueryTools; -use crate::planner::sql_evaluator::{EvaluationNode, SqlEvaluatorVisitor}; +use crate::planner::sql_evaluator::{MemberSymbol, SqlEvaluatorVisitor}; use cubenativeutils::CubeError; use std::any::Any; use std::rc::Rc; @@ -7,8 +7,8 @@ use std::rc::Rc; pub trait SqlNode { fn to_sql( &self, - visitor: &mut SqlEvaluatorVisitor, - node: &Rc, + visitor: &SqlEvaluatorVisitor, + node: &Rc, query_tools: Rc, node_processor: Rc, ) -> Result; @@ -17,3 +17,7 @@ pub trait SqlNode { fn childs(&self) -> Vec>; } + +pub trait CubeNameNode { + fn to_sql(&self, cube_name: &String) -> Result; +} diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/time_shift.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/time_shift.rs index 677095ded21ef..f3b30dd7f1819 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/time_shift.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/time_shift.rs @@ -1,7 +1,7 @@ use super::SqlNode; use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::MemberSymbol; use crate::planner::sql_evaluator::SqlEvaluatorVisitor; -use crate::planner::sql_evaluator::{EvaluationNode, MemberSymbolType}; use cubenativeutils::CubeError; use std::any::Any; use std::collections::HashMap; @@ -29,16 +29,16 @@ impl TimeShiftSqlNode { impl SqlNode for TimeShiftSqlNode { fn to_sql( &self, - visitor: &mut SqlEvaluatorVisitor, - node: &Rc, + visitor: &SqlEvaluatorVisitor, + node: &Rc, query_tools: Rc, node_processor: Rc, ) -> Result { let input = self.input .to_sql(visitor, node, query_tools.clone(), node_processor.clone())?; - let res = match node.symbol() { - MemberSymbolType::Dimension(ev) => { + let res = match node.as_ref() { + MemberSymbol::Dimension(ev) => { if let Some(shift) = self.shifts.get(&ev.full_name()) { format!("({input} + interval '{shift}')") } else { diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/ungroupped_measure.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/ungroupped_measure.rs new file mode 100644 index 0000000000000..1b2f9675a7492 --- /dev/null +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/ungroupped_measure.rs @@ -0,0 +1,62 @@ +use super::SqlNode; +use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::MemberSymbol; +use crate::planner::sql_evaluator::SqlEvaluatorVisitor; +use cubenativeutils::CubeError; +use std::any::Any; +use std::rc::Rc; + +pub struct UngroupedMeasureSqlNode { + input: Rc, +} + +impl UngroupedMeasureSqlNode { + pub fn new(input: Rc) -> Rc { + Rc::new(Self { input }) + } + + pub fn input(&self) -> &Rc { + &self.input + } +} + +impl SqlNode for UngroupedMeasureSqlNode { + fn to_sql( + &self, + visitor: &SqlEvaluatorVisitor, + node: &Rc, + query_tools: Rc, + node_processor: Rc, + ) -> Result { + let res = match node.as_ref() { + MemberSymbol::Measure(_) => { + let input = self.input.to_sql( + visitor, + node, + query_tools.clone(), + node_processor.clone(), + )?; + + if input == "*" { + "1".to_string() + } else { + input + } + } + _ => { + return Err(CubeError::internal(format!( + "Measure filter node processor called for wrong node", + ))); + } + }; + Ok(res) + } + + fn as_any(self: Rc) -> Rc { + self.clone() + } + + fn childs(&self) -> Vec> { + vec![self.input.clone()] + } +} diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/ungroupped_query_final_measure.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/ungroupped_query_final_measure.rs new file mode 100644 index 0000000000000..c77afa191b65c --- /dev/null +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/ungroupped_query_final_measure.rs @@ -0,0 +1,69 @@ +use super::SqlNode; +use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::MemberSymbol; +use crate::planner::sql_evaluator::SqlEvaluatorVisitor; +use cubenativeutils::CubeError; +use std::any::Any; +use std::rc::Rc; + +pub struct UngroupedQueryFinalMeasureSqlNode { + input: Rc, +} + +impl UngroupedQueryFinalMeasureSqlNode { + pub fn new(input: Rc) -> Rc { + Rc::new(Self { input }) + } + + pub fn input(&self) -> &Rc { + &self.input + } +} + +impl SqlNode for UngroupedQueryFinalMeasureSqlNode { + fn to_sql( + &self, + visitor: &SqlEvaluatorVisitor, + node: &Rc, + query_tools: Rc, + node_processor: Rc, + ) -> Result { + let res = match node.as_ref() { + MemberSymbol::Measure(ev) => { + let input = self.input.to_sql( + visitor, + node, + query_tools.clone(), + node_processor.clone(), + )?; + + if input == "*" { + "1".to_string() + } else { + if ev.measure_type() == "count" + || ev.measure_type() == "countDistinct" + || ev.measure_type() == "countDistinctApprox" + { + format!("CASE WHEN ({}) IS NOT NULL THEN 1 END", input) //TODO templates!! + } else { + input + } + } + } + _ => { + return Err(CubeError::internal(format!( + "Measure filter node processor called for wrong node", + ))); + } + }; + Ok(res) + } + + fn as_any(self: Rc) -> Rc { + self.clone() + } + + fn childs(&self) -> Vec> { + vec![self.input.clone()] + } +} diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_visitor.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_visitor.rs index 9c1a83574ea91..6a583bd86a135 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_visitor.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_visitor.rs @@ -1,7 +1,5 @@ -use super::dependecy::{ContextSymbolDep, Dependency}; use super::sql_nodes::SqlNode; -use super::EvaluationNode; -use crate::cube_bridge::memeber_sql::{ContextSymbolArg, MemberSqlArg, MemberSqlStruct}; +use super::MemberSymbol; use crate::planner::query_tools::QueryTools; use cubenativeutils::CubeError; use std::rc::Rc; @@ -17,80 +15,12 @@ impl SqlEvaluatorVisitor { } pub fn apply( - &mut self, - node: &Rc, + &self, + node: &Rc, node_processor: Rc, ) -> Result { let result = node_processor.to_sql(self, node, self.query_tools.clone(), node_processor.clone())?; Ok(result) } - - pub fn apply_context_symbol( - &mut self, - context_symbol: &ContextSymbolDep, - ) -> Result { - let res = match context_symbol { - ContextSymbolDep::SecurityContext => { - MemberSqlArg::ContextSymbol(ContextSymbolArg::SecurityContext( - self.query_tools.base_tools().security_context_for_rust()?, - )) - } - ContextSymbolDep::FilterParams => MemberSqlArg::ContextSymbol( - ContextSymbolArg::FilterParams(self.query_tools.base_tools().filters_proxy()?), - ), - ContextSymbolDep::FilterGroup => { - MemberSqlArg::ContextSymbol(ContextSymbolArg::FilterGroup( - self.query_tools.base_tools().filter_group_function()?, - )) - } - }; - Ok(res) - } - - pub fn evaluate_deps( - &mut self, - node: &Rc, - node_processor: Rc, - ) -> Result, CubeError> { - node.deps() - .iter() - .map(|d| self.evaluate_single_dep(&d, node_processor.clone())) - .collect() - } - - fn evaluate_single_dep( - &mut self, - dep: &Dependency, - node_processor: Rc, - ) -> Result { - match dep { - Dependency::SingleDependency(dep) => Ok(MemberSqlArg::String( - self.apply(dep, node_processor.clone())?, - )), - Dependency::StructDependency(dep) => { - let mut res = MemberSqlStruct::default(); - if let Some(sql_fn) = &dep.sql_fn { - res.sql_fn = Some(self.apply(sql_fn, node_processor.clone())?); - } - if let Some(to_string_fn) = &dep.to_string_fn { - res.to_string_fn = Some(self.apply(to_string_fn, node_processor.clone())?); - } - for (k, v) in dep.properties.iter() { - match v { - Dependency::SingleDependency(dep) => { - res.properties - .insert(k.clone(), self.apply(dep, node_processor.clone())?); - } - Dependency::StructDependency(_) => unimplemented!(), - Dependency::ContextDependency(_) => unimplemented!(), - } - } - Ok(MemberSqlArg::Struct(res)) - } - Dependency::ContextDependency(contex_symbol) => { - self.apply_context_symbol(contex_symbol) - } - } - } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/cube_symbol.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/cube_symbol.rs index d6a24c0cc56c2..263d28e88c7b6 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/cube_symbol.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/cube_symbol.rs @@ -1,8 +1,9 @@ -use super::SymbolFactory; +use super::{MemberSymbol, SymbolFactory}; use crate::cube_bridge::cube_definition::CubeDefinition; use crate::cube_bridge::evaluator::CubeEvaluator; -use crate::cube_bridge::memeber_sql::{MemberSql, MemberSqlArg}; -use crate::planner::sql_evaluator::{dependecy::Dependency, Compiler, EvaluationNode}; +use crate::cube_bridge::memeber_sql::MemberSql; +use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::{sql_nodes::SqlNode, Compiler, SqlCall, SqlEvaluatorVisitor}; use cubenativeutils::CubeError; use lazy_static::lazy_static; use regex::Regex; @@ -17,7 +18,7 @@ impl CubeNameSymbol { Self { cube_name } } - pub fn evaluate_sql(&self, _args: Vec) -> Result { + pub fn evaluate_sql(&self) -> Result { Ok(self.cube_name.clone()) } pub fn cube_name(&self) -> &String { @@ -58,21 +59,15 @@ impl SymbolFactory for CubeNameSymbolFactory { Ok(vec![]) } - fn build( - self, - _deps: Vec, - _compiler: &mut Compiler, - ) -> Result, CubeError> { + fn build(self, _compiler: &mut Compiler) -> Result, CubeError> { let Self { cube_name } = self; - Ok(EvaluationNode::new_cube_name(CubeNameSymbol::new( - cube_name, - ))) + Ok(MemberSymbol::new_cube_name(CubeNameSymbol::new(cube_name))) } } pub struct CubeTableSymbol { cube_name: String, - member_sql: Rc, + member_sql: Rc, #[allow(dead_code)] definition: Rc, is_table_sql: bool, @@ -81,7 +76,7 @@ pub struct CubeTableSymbol { impl CubeTableSymbol { pub fn new( cube_name: String, - member_sql: Rc, + member_sql: Rc, definition: Rc, is_table_sql: bool, ) -> Self { @@ -92,12 +87,18 @@ impl CubeTableSymbol { is_table_sql, } } - pub fn evaluate_sql(&self, args: Vec) -> Result { + + pub fn evaluate_sql( + &self, + visitor: &SqlEvaluatorVisitor, + node_processor: Rc, + query_tools: Rc, + ) -> Result { lazy_static! { static ref SIMPLE_ASTERIX_RE: Regex = Regex::new(r#"(?i)^\s*select\s+\*\s+from\s+([a-zA-Z0-9_\-`".*]+)\s*$"#).unwrap(); } - let sql = self.member_sql.call(args)?; + let sql = self.member_sql.eval(visitor, node_processor, query_tools)?; let res = if self.is_table_sql { sql } else { @@ -169,20 +170,19 @@ impl SymbolFactory for CubeTableSymbolFactory { Some(self.sql.clone()) } - fn build( - self, - deps: Vec, - _compiler: &mut Compiler, - ) -> Result, CubeError> { + fn build(self, compiler: &mut Compiler) -> Result, CubeError> { let Self { cube_name, sql, definition, is_table_sql, } = self; - Ok(EvaluationNode::new_cube_table( - CubeTableSymbol::new(cube_name, sql, definition, is_table_sql), - deps, - )) + let sql = compiler.compile_sql_call(&cube_name, sql)?; + Ok(MemberSymbol::new_cube_table(CubeTableSymbol::new( + cube_name, + sql, + definition, + is_table_sql, + ))) } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/dimension_symbol.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/dimension_symbol.rs index 8286888a6a7f6..40ec863b6e8ff 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/dimension_symbol.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/dimension_symbol.rs @@ -1,15 +1,16 @@ use super::{MemberSymbol, SymbolFactory}; use crate::cube_bridge::dimension_definition::DimensionDefinition; use crate::cube_bridge::evaluator::CubeEvaluator; -use crate::cube_bridge::memeber_sql::{MemberSql, MemberSqlArg}; -use crate::planner::sql_evaluator::{Compiler, Dependency, EvaluationNode}; +use crate::cube_bridge::memeber_sql::MemberSql; +use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::{sql_nodes::SqlNode, Compiler, SqlCall, SqlEvaluatorVisitor}; use cubenativeutils::CubeError; use std::rc::Rc; pub struct DimensionSymbol { cube_name: String, name: String, - member_sql: Rc, + member_sql: Rc, #[allow(dead_code)] definition: Rc, } @@ -18,7 +19,7 @@ impl DimensionSymbol { pub fn new( cube_name: String, name: String, - member_sql: Rc, + member_sql: Rc, definition: Rc, ) -> Self { Self { @@ -29,8 +30,13 @@ impl DimensionSymbol { } } - pub fn evaluate_sql(&self, args: Vec) -> Result { - let sql = self.member_sql.call(args)?; + pub fn evaluate_sql( + &self, + visitor: &SqlEvaluatorVisitor, + node_processor: Rc, + query_tools: Rc, + ) -> Result { + let sql = self.member_sql.eval(visitor, node_processor, query_tools)?; Ok(sql) } @@ -45,14 +51,23 @@ impl DimensionSymbol { pub fn is_multi_stage(&self) -> bool { self.definition.static_data().multi_stage.unwrap_or(false) } -} + pub fn get_dependencies(&self) -> Vec> { + let mut deps = vec![]; + self.member_sql.extract_symbol_deps(&mut deps); + deps + } -impl MemberSymbol for DimensionSymbol { - fn cube_name(&self) -> &String { + pub fn get_dependent_cubes(&self) -> Vec { + let mut cubes = vec![]; + self.member_sql.extract_cube_deps(&mut cubes); + cubes + } + + pub fn cube_name(&self) -> &String { &self.cube_name } - fn name(&self) -> &String { + pub fn name(&self) -> &String { &self.name } } @@ -101,20 +116,16 @@ impl SymbolFactory for DimensionSymbolFactory { Some(self.sql.clone()) } - fn build( - self, - deps: Vec, - _compiler: &mut Compiler, - ) -> Result, CubeError> { + fn build(self, compiler: &mut Compiler) -> Result, CubeError> { let Self { cube_name, name, sql, definition, } = self; - Ok(EvaluationNode::new_dimension( - DimensionSymbol::new(cube_name, name, sql, definition), - deps, - )) + let sql = compiler.compile_sql_call(&cube_name, sql)?; + Ok(MemberSymbol::new_dimension(DimensionSymbol::new( + cube_name, name, sql, definition, + ))) } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/measure_symbol.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/measure_symbol.rs index e6ecf3db0e0c5..7ef7024e700c6 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/measure_symbol.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/measure_symbol.rs @@ -1,26 +1,30 @@ use super::{MemberSymbol, SymbolFactory}; use crate::cube_bridge::evaluator::CubeEvaluator; -use crate::cube_bridge::measure_definition::{MeasureDefinition, TimeShiftReference}; -use crate::cube_bridge::memeber_sql::{MemberSql, MemberSqlArg}; -use crate::planner::sql_evaluator::{Compiler, Dependency, EvaluationNode}; +use crate::cube_bridge::measure_definition::{ + MeasureDefinition, RollingWindow, TimeShiftReference, +}; +use crate::cube_bridge::memeber_sql::MemberSql; +use crate::planner::query_tools::QueryTools; +use crate::planner::sql_evaluator::{sql_nodes::SqlNode, Compiler, SqlCall, SqlEvaluatorVisitor}; use cubenativeutils::CubeError; use std::rc::Rc; +#[derive(Clone)] pub struct MeasureOrderBy { - evaluation_node: Rc, + sql_call: Rc, direction: String, } impl MeasureOrderBy { - pub fn new(evaluation_node: Rc, direction: String) -> Self { + pub fn new(sql_call: Rc, direction: String) -> Self { Self { - evaluation_node, + sql_call, direction, } } - pub fn evaluation_node(&self) -> &Rc { - &self.evaluation_node + pub fn sql_call(&self) -> &Rc { + &self.sql_call } pub fn direction(&self) -> &String { @@ -28,22 +32,24 @@ impl MeasureOrderBy { } } +#[derive(Clone)] pub struct MeasureSymbol { cube_name: String, name: String, definition: Rc, - measure_filters: Vec>, + measure_filters: Vec>, measure_order_by: Vec, - member_sql: Rc, + member_sql: Rc, + is_splitted_source: bool, } impl MeasureSymbol { pub fn new( cube_name: String, name: String, - member_sql: Rc, + member_sql: Rc, definition: Rc, - measure_filters: Vec>, + measure_filters: Vec>, measure_order_by: Vec, ) -> Self { Self { @@ -53,6 +59,7 @@ impl MeasureSymbol { definition, measure_filters, measure_order_by, + is_splitted_source: false, } } @@ -60,6 +67,24 @@ impl MeasureSymbol { format!("{}.{}", self.cube_name, self.name) } + pub fn is_splitted_source(&self) -> bool { + self.is_splitted_source + } + + pub fn split_with_source(&self, source_name: String) -> (Self, Self) { + let mut measure_with_source = self.clone(); + measure_with_source.is_splitted_source = true; + let source = Self::new( + self.cube_name.clone(), + source_name.clone(), + self.member_sql.clone(), + self.definition().clone(), + self.measure_filters.clone(), + self.measure_order_by.clone(), + ); + (measure_with_source, source) + } + pub fn is_calculated(&self) -> bool { match self.definition.static_data().measure_type.as_str() { "number" | "string" | "time" | "boolean" => true, @@ -67,11 +92,40 @@ impl MeasureSymbol { } } - pub fn evaluate_sql(&self, args: Vec) -> Result { - let sql = self.member_sql.call(args)?; + pub fn evaluate_sql( + &self, + visitor: &SqlEvaluatorVisitor, + node_processor: Rc, + query_tools: Rc, + ) -> Result { + let sql = self.member_sql.eval(visitor, node_processor, query_tools)?; Ok(sql) } + pub fn get_dependencies(&self) -> Vec> { + let mut deps = vec![]; + self.member_sql.extract_symbol_deps(&mut deps); + for filter in self.measure_filters.iter() { + filter.extract_symbol_deps(&mut deps); + } + for order in self.measure_order_by.iter() { + order.sql_call().extract_symbol_deps(&mut deps); + } + deps + } + + pub fn get_dependent_cubes(&self) -> Vec { + let mut cubes = vec![]; + self.member_sql.extract_cube_deps(&mut cubes); + for filter in self.measure_filters.iter() { + filter.extract_cube_deps(&mut cubes); + } + for order in self.measure_order_by.iter() { + order.sql_call().extract_cube_deps(&mut cubes); + } + cubes + } + pub fn owned_by_cube(&self) -> bool { self.definition() .static_data() @@ -83,7 +137,23 @@ impl MeasureSymbol { &self.definition.static_data().measure_type } - pub fn measure_filters(&self) -> &Vec> { + pub fn rolling_window(&self) -> &Option { + &self.definition.static_data().rolling_window + } + + pub fn is_rolling_window(&self) -> bool { + self.rolling_window().is_some() + } + + pub fn is_running_total(&self) -> bool { + self.measure_type() == "runningTotal" + } + + pub fn is_cumulative(&self) -> bool { + self.is_rolling_window() || self.is_running_total() + } + + pub fn measure_filters(&self) -> &Vec> { &self.measure_filters } @@ -102,13 +172,11 @@ impl MeasureSymbol { pub fn is_multi_stage(&self) -> bool { self.definition.static_data().multi_stage.unwrap_or(false) } -} -impl MemberSymbol for MeasureSymbol { - fn cube_name(&self) -> &String { + pub fn cube_name(&self) -> &String { &self.cube_name } - fn name(&self) -> &String { + pub fn name(&self) -> &String { &self.name } } @@ -173,11 +241,7 @@ impl SymbolFactory for MeasureSymbolFactory { } } - fn build( - self, - deps: Vec, - compiler: &mut Compiler, - ) -> Result, CubeError> { + fn build(self, compiler: &mut Compiler) -> Result, CubeError> { let Self { cube_name, name, @@ -187,7 +251,7 @@ impl SymbolFactory for MeasureSymbolFactory { let mut measure_filters = vec![]; if let Some(filters) = definition.filters()? { for filter in filters.items().iter() { - let node = compiler.add_simple_sql_evaluator(cube_name.clone(), filter.sql()?)?; + let node = compiler.compile_sql_call(&cube_name, filter.sql()?)?; measure_filters.push(node); } } @@ -195,21 +259,19 @@ impl SymbolFactory for MeasureSymbolFactory { let mut measure_order_by = vec![]; if let Some(group_by) = definition.order_by()? { for item in group_by.items().iter() { - let node = compiler.add_simple_sql_evaluator(cube_name.clone(), item.sql()?)?; + let node = compiler.compile_sql_call(&cube_name, item.sql()?)?; measure_order_by.push(MeasureOrderBy::new(node, item.dir()?)); } } + let sql = compiler.compile_sql_call(&cube_name, sql)?; - Ok(EvaluationNode::new_measure( - MeasureSymbol::new( - cube_name, - name, - sql, - definition, - measure_filters, - measure_order_by, - ), - deps, - )) + Ok(MemberSymbol::new_measure(MeasureSymbol::new( + cube_name, + name, + sql, + definition, + measure_filters, + measure_order_by, + ))) } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/member_symbol.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/member_symbol.rs index b8137abda10cb..ac62b640e580e 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/member_symbol.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/member_symbol.rs @@ -1,4 +1,80 @@ -pub trait MemberSymbol { - fn cube_name(&self) -> &String; - fn name(&self) -> &String; +use super::{CubeNameSymbol, CubeTableSymbol, DimensionSymbol, MeasureSymbol}; +use std::rc::Rc; + +pub enum MemberSymbol { + Dimension(DimensionSymbol), + Measure(MeasureSymbol), + CubeName(CubeNameSymbol), + CubeTable(CubeTableSymbol), +} + +impl MemberSymbol { + pub fn new_measure(symbol: MeasureSymbol) -> Rc { + Rc::new(Self::Measure(symbol)) + } + + pub fn new_dimension(symbol: DimensionSymbol) -> Rc { + Rc::new(Self::Dimension(symbol)) + } + + pub fn new_cube_name(symbol: CubeNameSymbol) -> Rc { + Rc::new(Self::CubeName(symbol)) + } + + pub fn new_cube_table(symbol: CubeTableSymbol) -> Rc { + Rc::new(Self::CubeTable(symbol)) + } + + pub fn full_name(&self) -> String { + match self { + Self::Dimension(d) => d.full_name(), + Self::Measure(m) => m.full_name(), + Self::CubeName(c) => c.cube_name().clone(), + Self::CubeTable(c) => c.cube_name().clone(), + } + } + pub fn name(&self) -> String { + match self { + Self::Dimension(d) => d.name().clone(), + Self::Measure(m) => m.name().clone(), + Self::CubeName(c) => c.cube_name().clone(), + Self::CubeTable(c) => c.cube_name().clone(), + } + } + + pub fn cube_name(&self) -> String { + match self { + Self::Dimension(d) => d.cube_name().clone(), + Self::Measure(m) => m.cube_name().clone(), + Self::CubeName(c) => c.cube_name().clone(), + Self::CubeTable(c) => c.cube_name().clone(), + } + } + pub fn is_measure(&self) -> bool { + matches!(self, Self::Measure(_)) + } + pub fn is_dimension(&self) -> bool { + matches!(self, Self::Dimension(_)) + } + pub fn get_dependencies(&self) -> Vec> { + match self { + Self::Dimension(d) => d.get_dependencies(), + Self::Measure(m) => m.get_dependencies(), + Self::CubeName(_) => vec![], + Self::CubeTable(_) => vec![], + } + } + + pub fn get_dependent_cubes(&self) -> Vec { + match self { + Self::Dimension(d) => d.get_dependent_cubes(), + Self::Measure(m) => m.get_dependent_cubes(), + Self::CubeName(_) => vec![], + Self::CubeTable(_) => vec![], + } + } + + pub fn is_leaf(&self) -> bool { + self.get_dependencies().is_empty() + } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/member_symbol_type.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/member_symbol_type.rs deleted file mode 100644 index 830c8e7f4e367..0000000000000 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/member_symbol_type.rs +++ /dev/null @@ -1,26 +0,0 @@ -use super::{CubeNameSymbol, CubeTableSymbol, DimensionSymbol, MeasureSymbol, SimpleSqlSymbol}; -pub enum MemberSymbolType { - Dimension(DimensionSymbol), - Measure(MeasureSymbol), - CubeName(CubeNameSymbol), - CubeTable(CubeTableSymbol), - SimpleSql(SimpleSqlSymbol), -} - -impl MemberSymbolType { - pub fn full_name(&self) -> String { - match self { - MemberSymbolType::Dimension(d) => d.full_name(), - MemberSymbolType::Measure(m) => m.full_name(), - MemberSymbolType::CubeName(c) => c.cube_name().clone(), - MemberSymbolType::CubeTable(c) => c.cube_name().clone(), - MemberSymbolType::SimpleSql(_) => "".to_string(), - } - } - pub fn is_measure(&self) -> bool { - matches!(self, Self::Measure(_)) - } - pub fn is_dimension(&self) -> bool { - matches!(self, Self::Dimension(_)) - } -} diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/mod.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/mod.rs index 7b8ba1e7e42f2..ddb631648d6f1 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/mod.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/mod.rs @@ -2,8 +2,6 @@ mod cube_symbol; mod dimension_symbol; mod measure_symbol; mod member_symbol; -mod member_symbol_type; -mod simple_sql; mod symbol_factory; pub use cube_symbol::{ @@ -12,6 +10,4 @@ pub use cube_symbol::{ pub use dimension_symbol::{DimensionSymbol, DimensionSymbolFactory}; pub use measure_symbol::{MeasureSymbol, MeasureSymbolFactory}; pub use member_symbol::MemberSymbol; -pub use member_symbol_type::MemberSymbolType; -pub use simple_sql::{SimpleSqlSymbol, SimpleSqlSymbolFactory}; pub use symbol_factory::SymbolFactory; diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/simple_sql.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/simple_sql.rs deleted file mode 100644 index 52d21e298ad5c..0000000000000 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/simple_sql.rs +++ /dev/null @@ -1,74 +0,0 @@ -use super::SymbolFactory; -use crate::cube_bridge::memeber_sql::{MemberSql, MemberSqlArg}; -use crate::planner::sql_evaluator::{Compiler, Dependency, EvaluationNode}; -use cubenativeutils::CubeError; -use std::rc::Rc; - -pub struct SimpleSqlSymbol { - cube_name: String, - member_sql: Rc, -} - -impl SimpleSqlSymbol { - pub fn new(cube_name: String, member_sql: Rc) -> Self { - Self { - cube_name, - member_sql, - } - } - - pub fn full_name(&self) -> String { - format!("{}.simple_sql", self.cube_name) - } - - pub fn evaluate_sql(&self, args: Vec) -> Result { - let sql = self.member_sql.call(args)?; - Ok(sql) - } -} - -pub struct SimpleSqlSymbolFactory { - cube_name: String, - sql: Rc, -} - -impl SimpleSqlSymbolFactory { - pub fn try_new(cube_name: &String, sql: Rc) -> Result { - Ok(Self { - cube_name: cube_name.clone(), - sql, - }) - } -} - -impl SymbolFactory for SimpleSqlSymbolFactory { - fn is_cachable() -> bool { - false - } - fn symbol_name() -> String { - "simple_sql".to_string() - } - fn cube_name(&self) -> &String { - &self.cube_name - } - - fn member_sql(&self) -> Option> { - Some(self.sql.clone()) - } - - fn deps_names(&self) -> Result, CubeError> { - Ok(self.sql.args_names().clone()) - } - - fn build( - self, - deps: Vec, - _compiler: &mut Compiler, - ) -> Result, CubeError> { - let Self { cube_name, sql } = self; - Ok(EvaluationNode::new_simple_sql( - SimpleSqlSymbol::new(cube_name, sql), - deps, - )) - } -} diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/symbol_factory.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/symbol_factory.rs index 198bcd85c6710..c0e681412ccfb 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/symbol_factory.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/symbol_factory.rs @@ -1,6 +1,6 @@ +use super::MemberSymbol; use crate::cube_bridge::memeber_sql::MemberSql; -use crate::planner::sql_evaluator::dependecy::Dependency; -use crate::planner::sql_evaluator::{Compiler, EvaluationNode}; +use crate::planner::sql_evaluator::Compiler; use cubenativeutils::CubeError; use std::rc::Rc; @@ -12,9 +12,5 @@ pub trait SymbolFactory: Sized { fn cube_name(&self) -> &String; fn deps_names(&self) -> Result, CubeError>; fn member_sql(&self) -> Option>; - fn build( - self, - deps: Vec, - compiler: &mut Compiler, - ) -> Result, CubeError>; + fn build(self, compiler: &mut Compiler) -> Result, CubeError>; } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/visitor.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/visitor.rs index 0a9a49b14f681..abef52ceeaa02 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/visitor.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/visitor.rs @@ -1,50 +1,21 @@ -use super::{dependecy::Dependency, EvaluationNode}; +use super::MemberSymbol; use cubenativeutils::CubeError; use std::rc::Rc; pub trait TraversalVisitor { - fn on_node_traverse(&mut self, node: &Rc) -> Result; - - fn apply(&mut self, node: &Rc) -> Result<(), CubeError> { - if self.on_node_traverse(node)? { - self.travese_deps(node)?; - } - Ok(()) - } - - fn travese_deps(&mut self, node: &Rc) -> Result<(), CubeError> { - for dep in node.deps() { - self.traverse_single_dep(dep, node)?; - } - Ok(()) - } - - fn traverse_single_dep( + type State; + fn on_node_traverse( &mut self, - dep: &Dependency, - node: &Rc, - ) -> Result<(), CubeError> { - match dep { - Dependency::SingleDependency(dep) => self.apply(dep), - Dependency::StructDependency(dep) => { - if dep.sql_fn.is_some() { - self.apply(node)?; - } - if let Some(to_string_fn) = &dep.to_string_fn { - self.apply(to_string_fn)?; - } - for (_, v) in dep.properties.iter() { - match v { - Dependency::SingleDependency(dep) => { - self.apply(dep)?; - } - Dependency::StructDependency(_) => unimplemented!(), - Dependency::ContextDependency(_) => {} - } - } - Ok(()) + node: &Rc, + state: &Self::State, + ) -> Result, CubeError>; + + fn apply(&mut self, node: &Rc, state: &Self::State) -> Result<(), CubeError> { + if let Some(state) = self.on_node_traverse(node, state)? { + for dep in node.get_dependencies() { + self.apply(&dep, &state)? } - Dependency::ContextDependency(_) => Ok(()), } + Ok(()) } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_templates/filter.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_templates/filter.rs index f0d23de97e232..6ee5d9a3f66d6 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_templates/filter.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_templates/filter.rs @@ -3,6 +3,7 @@ use cubenativeutils::CubeError; use minijinja::context; use std::rc::Rc; +#[derive(Clone)] pub struct FilterTemplates { render: Rc, } @@ -103,6 +104,26 @@ impl FilterTemplates { ) } + pub fn add_interval(&self, date: String, interval: String) -> Result { + self.render.render_template( + &"expressions/add_interval", + context! { + date => date, + interval => interval + }, + ) + } + + pub fn sub_interval(&self, date: String, interval: String) -> Result { + self.render.render_template( + &"expressions/sub_interval", + context! { + date => date, + interval => interval + }, + ) + } + pub fn set_where(&self, column: String) -> Result { self.render.render_template( &"filters/set_where", @@ -161,11 +182,37 @@ impl FilterTemplates { ) } - fn additional_null_check(&self, need: bool, column: &String) -> Result { + pub fn additional_null_check(&self, need: bool, column: &String) -> Result { if need { self.or_is_null_check(column.clone()) } else { Ok(String::default()) } } + + pub fn ilike( + &self, + column: &str, + value: &str, + start_wild: bool, + end_wild: bool, + not: bool, + ) -> Result { + let pattern = self.render.render_template( + &"filters/like_pattern", + context! { + start_wild => start_wild, + value => value, + end_wild => end_wild + }, + )?; + self.render.render_template( + &"expressions/ilike", + context! { + expr => column, + negated => not, + pattern => pattern + }, + ) + } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_templates/plan.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_templates/plan.rs index aca5695ef8544..26b12acacd25a 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_templates/plan.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_templates/plan.rs @@ -121,6 +121,22 @@ impl PlanSqlTemplates { ) } + pub fn time_series_select( + &self, + from_date: Option, + to_date: Option, + seria: Vec>, + ) -> Result { + self.render.render_template( + "statements/time_series_select", + context! { + from_date => from_date, + to_date => to_date, + seria => seria + }, + ) + } + pub fn select( &self, ctes: Vec, @@ -152,59 +168,6 @@ impl PlanSqlTemplates { ) } - /* pub fn select( - &self, - from: String, - projection: Vec, - group_by: Vec, - group_descs: Vec>, - aggregate: Vec, - alias: String, - filter: Option, - _having: Option, - order_by: Vec, - limit: Option, - offset: Option, - distinct: bool, - ) -> Result { - let group_by = self.to_template_columns(group_by)?; - let aggregate = self.to_template_columns(aggregate)?; - let projection = self.to_template_columns(projection)?; - let order_by = self.to_template_columns(order_by)?; - let select_concat = group_by - .iter() - .chain(aggregate.iter()) - .chain(projection.iter()) - .map(|c| c.clone()) - .collect::>(); - let quoted_from_alias = self.quote_identifier(&alias)?; - let has_grouping_sets = group_descs.iter().any(|d| d.is_some()); - let group_by_expr = if has_grouping_sets { - self.group_by_with_grouping_sets(&group_by, &group_descs)? - } else { - self.render_template( - "statements/group_by_exprs", - context! { group_by => group_by }, - )? - }; - self.render.render_template( - "statements/select", - context! { - from => from, - select_concat => select_concat, - group_by => group_by_expr, - aggregate => aggregate, - projection => projection, - order_by => order_by, - filter => filter, - from_alias => quoted_from_alias, - limit => limit, - offset => offset, - distinct => distinct, - }, - ) - } */ - pub fn join(&self, source: &str, condition: &str, is_inner: bool) -> Result { let join_type = if is_inner { self.render.get_template("join_types/inner")? diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/visitor_context.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/visitor_context.rs index 378e869c14be3..7e4cf9137d9f8 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/visitor_context.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/visitor_context.rs @@ -1,39 +1,21 @@ use super::query_tools::QueryTools; use super::sql_evaluator::sql_nodes::{SqlNode, SqlNodesFactory}; -use super::sql_evaluator::EvaluationNode; -use crate::plan::Schema; -use crate::planner::sql_evaluator::sql_node_transformers::set_schema; +use super::sql_evaluator::{MemberSymbol, SqlCall}; use crate::planner::sql_evaluator::SqlEvaluatorVisitor; use cubenativeutils::CubeError; use std::rc::Rc; pub struct VisitorContext { - cube_alias_prefix: Option, node_processor: Rc, } impl VisitorContext { - pub fn new(cube_alias_prefix: Option, node_processor: Rc) -> Self { + pub fn new(nodes_factory: &SqlNodesFactory) -> Self { Self { - cube_alias_prefix, - node_processor, + node_processor: nodes_factory.default_node_processor(), } } - pub fn new_with_cube_alias_prefix( - nodes_factory: Rc, - cube_alias_prefix: String, - ) -> Self { - Self::new( - Some(cube_alias_prefix), - nodes_factory.default_node_processor(), - ) - } - - pub fn default(nodes_factory: Rc) -> Self { - Self::new(Default::default(), nodes_factory.default_node_processor()) - } - pub fn make_visitor(&self, query_tools: Rc) -> SqlEvaluatorVisitor { SqlEvaluatorVisitor::new(query_tools) } @@ -41,20 +23,25 @@ impl VisitorContext { pub fn node_processor(&self) -> Rc { self.node_processor.clone() } - - pub fn cube_alias_prefix(&self) -> &Option { - &self.cube_alias_prefix - } } pub fn evaluate_with_context( - node: &Rc, + node: &Rc, query_tools: Rc, context: Rc, - source_schema: Rc, ) -> Result { - let mut visitor = context.make_visitor(query_tools); - let node_processor = set_schema(context.node_processor(), source_schema); + let visitor = context.make_visitor(query_tools); + let node_processor = context.node_processor(); visitor.apply(node, node_processor) } + +pub fn evaluate_sql_call_with_context( + sql_call: &Rc, + query_tools: Rc, + context: Rc, +) -> Result { + let visitor = context.make_visitor(query_tools.clone()); + let node_processor = context.node_processor(); + sql_call.eval(&visitor, node_processor, query_tools) +} From b62446e3c3893068f8dd8aa32d7204ea06a16f98 Mon Sep 17 00:00:00 2001 From: Pavel Tiunov Date: Sun, 15 Dec 2024 17:49:03 -0800 Subject: [PATCH 18/21] feat(tesseract): Support multiple join paths within single query (#9047) * feat(tesseract): Support multiple join paths within single query * Linter * Fix join key doesn't respect root --- .../src/adapter/BaseQuery.js | 13 +- .../src/adapter/BigqueryQuery.ts | 1 + .../src/adapter/PostgresQuery.ts | 1 + .../src/adapter/SnowflakeQuery.ts | 1 + .../postgres/multi-fact-join.test.ts | 134 +++++++++++++++ .../src/cube_bridge/join_item.rs | 2 +- .../cubesqlplanner/src/plan/builder/join.rs | 41 +++-- .../cubesqlplanner/src/plan/filter.rs | 18 ++ .../cubesqlplanner/src/plan/join.rs | 10 +- .../src/planner/base_measure.rs | 10 ++ .../cubesqlplanner/src/planner/base_query.rs | 16 +- .../full_key_query_aggregate_planner.rs | 18 +- .../src/planner/planners/join_planner.rs | 14 +- .../multi_stage/member_query_planner.rs | 3 + .../multiplied_measures_query_planner.rs | 46 ++++- .../planner/planners/simple_query_planer.rs | 4 +- .../src/planner/query_properties.rs | 157 +++++++++++++++++- .../cubesqlplanner/src/planner/query_tools.rs | 101 +++++++++-- .../multiplied_measures_collector.rs | 16 +- .../src/planner/sql_evaluator/compiler.rs | 1 + .../src/planner/sql_templates/plan.rs | 37 ++++- 21 files changed, 571 insertions(+), 73 deletions(-) create mode 100644 packages/cubejs-schema-compiler/test/integration/postgres/multi-fact-join.test.ts diff --git a/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js b/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js index 34a9d2587ba26..2c71d23778ea3 100644 --- a/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js +++ b/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js @@ -261,7 +261,10 @@ export class BaseQuery { }).filter(R.identity).map(this.newTimeDimension.bind(this)); this.allFilters = this.timeDimensions.concat(this.segments).concat(this.filters); - this.join = this.joinGraph.buildJoin(this.allJoinHints); + if (!getEnv('nativeSqlPlanner')) { + // Tesseract doesn't require join to be prebuilt and there's a case where single join can't be built for multi-fact query + this.join = this.joinGraph.buildJoin(this.allJoinHints); + } this.cubeAliasPrefix = this.options.cubeAliasPrefix; this.preAggregationsSchemaOption = this.options.preAggregationsSchema ?? DEFAULT_PREAGGREGATIONS_SCHEMA; this.externalQueryClass = this.options.externalQueryClass; @@ -349,7 +352,8 @@ export class BaseQuery { initUngrouped() { this.ungrouped = this.options.ungrouped; if (this.ungrouped) { - if (!this.options.allowUngroupedWithoutPrimaryKey) { + // this.join is not defined for Tesseract + if (!this.options.allowUngroupedWithoutPrimaryKey && !getEnv('nativeSqlPlanner')) { const cubes = R.uniq([this.join.root].concat(this.join.joins.map(j => j.originalTo))); const primaryKeyNames = cubes.flatMap(c => this.primaryKeyNames(c)); const missingPrimaryKeys = primaryKeyNames.filter(key => !this.dimensions.find(d => d.dimension === key)); @@ -616,7 +620,6 @@ export class BaseQuery { dimensions: this.options.dimensions, timeDimensions: this.options.timeDimensions, timezone: this.options.timezone, - joinRoot: this.join.root, joinGraph: this.joinGraph, cubeEvaluator: this.cubeEvaluator, order, @@ -3312,6 +3315,7 @@ export class BaseQuery { always_true: '1 = 1' }, + operators: {}, quotes: { identifiers: '"', escape: '""' @@ -3321,7 +3325,8 @@ export class BaseQuery { }, join_types: { inner: 'INNER', - left: 'LEFT' + left: 'LEFT', + full: 'FULL', }, window_frame_types: { rows: 'ROWS', diff --git a/packages/cubejs-schema-compiler/src/adapter/BigqueryQuery.ts b/packages/cubejs-schema-compiler/src/adapter/BigqueryQuery.ts index 7c34a4a0d8e9a..07cc1759f6a2d 100644 --- a/packages/cubejs-schema-compiler/src/adapter/BigqueryQuery.ts +++ b/packages/cubejs-schema-compiler/src/adapter/BigqueryQuery.ts @@ -256,6 +256,7 @@ export class BigqueryQuery extends BaseQuery { templates.types.double = 'FLOAT64'; templates.types.decimal = 'BIGDECIMAL({{ precision }},{{ scale }})'; templates.types.binary = 'BYTES'; + templates.operators.is_not_distinct_from = 'IS NOT DISTINCT FROM'; return templates; } } diff --git a/packages/cubejs-schema-compiler/src/adapter/PostgresQuery.ts b/packages/cubejs-schema-compiler/src/adapter/PostgresQuery.ts index 01f763e4339dd..818a2f3c92d09 100644 --- a/packages/cubejs-schema-compiler/src/adapter/PostgresQuery.ts +++ b/packages/cubejs-schema-compiler/src/adapter/PostgresQuery.ts @@ -81,6 +81,7 @@ export class PostgresQuery extends BaseQuery { templates.types.float = 'REAL'; templates.types.double = 'DOUBLE PRECISION'; templates.types.binary = 'BYTEA'; + templates.operators.is_not_distinct_from = 'IS NOT DISTINCT FROM'; return templates; } diff --git a/packages/cubejs-schema-compiler/src/adapter/SnowflakeQuery.ts b/packages/cubejs-schema-compiler/src/adapter/SnowflakeQuery.ts index 8d3e5a63dc85a..a59e139f9a2df 100644 --- a/packages/cubejs-schema-compiler/src/adapter/SnowflakeQuery.ts +++ b/packages/cubejs-schema-compiler/src/adapter/SnowflakeQuery.ts @@ -115,6 +115,7 @@ export class SnowflakeQuery extends BaseQuery { templates.expressions.extract = 'EXTRACT({{ date_part }} FROM {{ expr }})'; templates.expressions.interval = 'INTERVAL \'{{ interval }}\''; templates.expressions.timestamp_literal = '\'{{ value }}\'::timestamp_tz'; + templates.operators.is_not_distinct_from = 'IS NOT DISTINCT FROM'; delete templates.types.interval; return templates; } diff --git a/packages/cubejs-schema-compiler/test/integration/postgres/multi-fact-join.test.ts b/packages/cubejs-schema-compiler/test/integration/postgres/multi-fact-join.test.ts new file mode 100644 index 0000000000000..bd3f795803b38 --- /dev/null +++ b/packages/cubejs-schema-compiler/test/integration/postgres/multi-fact-join.test.ts @@ -0,0 +1,134 @@ +import { + getEnv, +} from '@cubejs-backend/shared'; +import { PostgresQuery } from '../../../src/adapter/PostgresQuery'; +import { prepareCompiler } from '../../unit/PrepareCompiler'; +import { dbRunner } from './PostgresDBRunner'; + +describe('Multi-fact join', () => { + jest.setTimeout(200000); + + const { compiler, joinGraph, cubeEvaluator } = prepareCompiler(` +cube(\`orders\`, { + sql: \` + SELECT 79 AS id, 1 AS amount, 1 AS city_id UNION ALL + SELECT 80 AS id, 2 AS amount, 1 AS city_id UNION ALL + SELECT 81 AS id, 3 AS amount, 1 AS city_id UNION ALL + SELECT 82 AS id, 4 AS amount, 2 AS city_id UNION ALL + SELECT 83 AS id, 5 AS amount, 2 AS city_id UNION ALL + SELECT 84 AS id, 6 AS amount, 3 AS city_id + \`, + + joins: { + city: { + relationship: \`many_to_one\`, + sql: \`\${orders}.city_id = \${city}.id\`, + }, + }, + + measures: { + amount: { + sql: \`amount\`, + type: 'sum' + } + }, + + dimensions: { + id: { + sql: \`id\`, + type: \`number\`, + primaryKey: true, + }, + }, +}); + +cube(\`shipments\`, { + sql: \` + SELECT 100 AS id, 1 AS foo_id, 1 AS city_id UNION ALL + SELECT 101 AS id, 2 AS foo_id, 2 AS city_id UNION ALL + SELECT 102 AS id, 3 AS foo_id, 2 AS city_id UNION ALL + SELECT 103 AS id, 4 AS foo_id, 2 AS city_id UNION ALL + SELECT 104 AS id, 5 AS foo_id, 4 AS city_id + \`, + + joins: { + city: { + relationship: \`many_to_one\`, + sql: \`\${shipments}.city_id = \${city}.id\`, + }, + }, + + measures: { + count: { + type: \`count\` + }, + }, + + dimensions: { + id: { + sql: \`id\`, + type: \`number\`, + primaryKey: true, + shown: true + }, + } +}); + +cube(\`city\`, { + sql: \` + SELECT 1 AS id, 'San Francisco' AS name UNION ALL + SELECT 2 AS id, 'New York City' AS name + \`, + + dimensions: { + id: { + sql: \`id\`, + type: \`number\`, + primaryKey: true, + }, + + name: { + sql: \`\${CUBE}.name\`, + type: \`string\`, + }, + }, +}); + `); + + async function runQueryTest(q, expectedResult) { + if (!getEnv('nativeSqlPlanner')) { + return; + } + await compiler.compile(); + const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, q); + + console.log(query.buildSqlAndParams()); + + const res = await dbRunner.testQuery(query.buildSqlAndParams()); + console.log(JSON.stringify(res)); + + expect(res).toEqual( + expectedResult + ); + } + + it('two regular sub-queries', async () => runQueryTest({ + measures: ['orders.amount', 'shipments.count'], + dimensions: [ + 'city.name' + ], + order: [{ id: 'city.name' }] + }, [{ + city__name: 'New York City', + orders__amount: '9', + shipments__count: '3', + }, { + city__name: 'San Francisco', + orders__amount: '6', + shipments__count: '1', + }, { + city__name: null, + orders__amount: '6', + shipments__count: '1', + }])); +}); diff --git a/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/join_item.rs b/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/join_item.rs index 2cdcd912f2b44..f3130d0ec7f6f 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/join_item.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/cube_bridge/join_item.rs @@ -11,7 +11,7 @@ use std::any::Any; use std::marker::PhantomData; use std::rc::Rc; -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Hash)] pub struct JoinItemStatic { pub from: String, pub to: String, diff --git a/rust/cubesqlplanner/cubesqlplanner/src/plan/builder/join.rs b/rust/cubesqlplanner/cubesqlplanner/src/plan/builder/join.rs index 8b2abcb1cf587..22ea6911dcf07 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/plan/builder/join.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/plan/builder/join.rs @@ -1,3 +1,4 @@ +use crate::plan::join::JoinType; use crate::plan::{Join, JoinCondition, JoinItem, QueryPlan, Schema, Select, SingleAliasedSource}; use crate::planner::BaseCube; use std::rc::Rc; @@ -41,15 +42,19 @@ impl JoinBuilder { } pub fn left_join_subselect(&mut self, subquery: Rc, alias: String, on: JoinCondition) { - self.join_subselect(subquery, alias, on, true) + self.join_subselect(subquery, alias, on, JoinType::Inner) + } + + pub fn full_join_subselect(&mut self, subquery: Rc, alias: String, on: JoinCondition, - is_inner: bool, + join_type: JoinType, ) { let subquery = Rc::new(QueryPlan::Select(subquery)); let from = SingleAliasedSource::new_from_subquery(subquery, alias); - self.joins.push(JoinItem { from, on, is_inner }) + self.joins.push(JoinItem { + from, + on, + join_type, + }) } fn join_cube( @@ -105,10 +114,14 @@ impl JoinBuilder { cube: Rc, alias: Option, on: JoinCondition, - is_inner: bool, + join_type: JoinType, ) { let from = SingleAliasedSource::new_from_cube(cube, alias); - self.joins.push(JoinItem { from, on, is_inner }) + self.joins.push(JoinItem { + from, + on, + join_type, + }) } fn join_table_reference( @@ -117,9 +130,13 @@ impl JoinBuilder { schema: Rc, alias: Option, on: JoinCondition, - is_inner: bool, + join_type: JoinType, ) { let from = SingleAliasedSource::new_from_table_reference(reference, schema, alias); - self.joins.push(JoinItem { from, on, is_inner }) + self.joins.push(JoinItem { + from, + on, + join_type, + }) } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/plan/filter.rs b/rust/cubesqlplanner/cubesqlplanner/src/plan/filter.rs index b7e59049cb373..123463e24075f 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/plan/filter.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/plan/filter.rs @@ -1,4 +1,5 @@ use crate::planner::filter::BaseFilter; +use crate::planner::sql_evaluator::MemberSymbol; use crate::planner::sql_templates::PlanSqlTemplates; use crate::planner::VisitorContext; use cubenativeutils::CubeError; @@ -79,6 +80,23 @@ impl FilterItem { }; Ok(res) } + + pub fn all_member_evaluators(&self) -> Vec> { + let mut result = Vec::new(); + self.find_all_member_evaluators(&mut result); + result + } + + pub fn find_all_member_evaluators(&self, result: &mut Vec>) { + match self { + FilterItem::Group(group) => { + for item in group.items.iter() { + item.find_all_member_evaluators(result) + } + } + FilterItem::Item(item) => result.push(item.member_evaluator().clone()), + } + } } impl Filter { diff --git a/rust/cubesqlplanner/cubesqlplanner/src/plan/join.rs b/rust/cubesqlplanner/cubesqlplanner/src/plan/join.rs index 3a19170443d80..96d7355544c66 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/plan/join.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/plan/join.rs @@ -179,7 +179,7 @@ impl JoinCondition { pub struct JoinItem { pub from: SingleAliasedSource, pub on: JoinCondition, - pub is_inner: bool, + pub join_type: JoinType, } pub struct Join { @@ -187,6 +187,12 @@ pub struct Join { pub joins: Vec, } +pub enum JoinType { + Inner, + Left, + Full, +} + impl JoinItem { pub fn to_sql( &self, @@ -197,7 +203,7 @@ impl JoinItem { let result = templates.join( &self.from.to_sql(templates, context)?, &on_sql, - self.is_inner, + &self.join_type, )?; Ok(result) } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/base_measure.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/base_measure.rs index 89e832620af1d..db215ec1eeaf1 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/base_measure.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/base_measure.rs @@ -7,6 +7,7 @@ use crate::cube_bridge::measure_definition::{ use cubenativeutils::CubeError; use lazy_static::lazy_static; use regex::Regex; +use std::fmt::{Debug, Formatter}; use std::rc::Rc; #[derive(Clone, Debug)] @@ -71,6 +72,15 @@ pub struct BaseMeasure { name: String, } +impl Debug for BaseMeasure { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("BaseMeasure") + .field("measure", &self.measure) + .field("time_shifts", &self.time_shifts) + .finish() + } +} + impl BaseMember for BaseMeasure { fn to_sql(&self, context: Rc) -> Result { evaluate_with_context(&self.member_evaluator, self.query_tools.clone(), context) diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/base_query.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/base_query.rs index 38a5001baa149..6e59585e4fbbf 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/base_query.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/base_query.rs @@ -44,8 +44,8 @@ impl BaseQuery { } pub fn build_sql_and_params(&self) -> Result, CubeError> { - let plan = self.build_sql_and_params_impl()?; let templates = PlanSqlTemplates::new(self.query_tools.templates_render()); + let plan = self.build_sql_and_params_impl(templates.clone())?; let sql = plan.to_sql(&templates)?; let (result_sql, params) = self.query_tools.build_sql_and_params(&sql, true)?; @@ -58,7 +58,7 @@ impl BaseQuery { Ok(result) } - fn build_sql_and_params_impl(&self) -> Result { + fn build_sql_and_params_impl(&self, templates: PlanSqlTemplates) -> Result { let mut nodes_factory = SqlNodesFactory::new(); if self.request.ungrouped() { @@ -73,15 +73,19 @@ impl BaseQuery { ); planner.plan() } else { + let request = self.request.clone(); let multiplied_measures_query_planner = MultipliedMeasuresQueryPlanner::new( self.query_tools.clone(), - self.request.clone(), + request.clone(), nodes_factory.clone(), ); let multi_stage_query_planner = - MultiStageQueryPlanner::new(self.query_tools.clone(), self.request.clone()); - let full_key_aggregate_planner = - FullKeyAggregateQueryPlanner::new(self.request.clone(), nodes_factory.clone()); + MultiStageQueryPlanner::new(self.query_tools.clone(), request.clone()); + let full_key_aggregate_planner = FullKeyAggregateQueryPlanner::new( + request.clone(), + nodes_factory.clone(), + templates, + ); let mut subqueries = multiplied_measures_query_planner.plan_queries()?; let (multi_stage_ctes, multi_stage_subqueries) = multi_stage_query_planner.plan_queries()?; diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/full_key_query_aggregate_planner.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/full_key_query_aggregate_planner.rs index 99ea934db4da5..4ec591e1baffc 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/full_key_query_aggregate_planner.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/full_key_query_aggregate_planner.rs @@ -4,6 +4,7 @@ use crate::plan::{ }; use crate::planner::sql_evaluator::sql_nodes::SqlNodesFactory; use crate::planner::sql_evaluator::ReferencesBuilder; +use crate::planner::sql_templates::PlanSqlTemplates; use crate::planner::BaseMeasure; use crate::planner::BaseMemberHelper; use crate::planner::QueryProperties; @@ -16,14 +17,21 @@ pub struct FullKeyAggregateQueryPlanner { query_properties: Rc, order_planner: OrderPlanner, context_factory: SqlNodesFactory, + plan_sql_templates: PlanSqlTemplates, } impl FullKeyAggregateQueryPlanner { - pub fn new(query_properties: Rc, context_factory: SqlNodesFactory) -> Self { + pub fn new( + query_properties: Rc, + context_factory: SqlNodesFactory, + // TODO get rid of this dependency + plan_sql_templates: PlanSqlTemplates, + ) -> Self { Self { order_planner: OrderPlanner::new(query_properties.clone()), query_properties, context_factory, + plan_sql_templates, } } @@ -56,6 +64,7 @@ impl FullKeyAggregateQueryPlanner { let right_alias = format!("q_{}", i); let left_schema = joins[i - 1].schema(); let right_schema = joins[i].schema(); + // TODO every next join should join to all previous dimensions through OR: q_0.a = q_1.a, q_0.a = q_2.a OR q_1.a = q_2.a, ... let conditions = dimensions_to_select .iter() .map(|dim| { @@ -73,7 +82,12 @@ impl FullKeyAggregateQueryPlanner { }) .collect_vec(); let on = JoinCondition::new_dimension_join(conditions, true); - join_builder.inner_join_subselect(join.clone(), format!("q_{}", i), on); + let next_alias = format!("q_{}", i); + if self.plan_sql_templates.supports_is_not_distinct_from() { + join_builder.inner_join_subselect(join.clone(), next_alias, on); + } else { + join_builder.full_join_subselect(join.clone(), next_alias, on); + } } let from = From::new_from_join(join_builder.build()); diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/join_planner.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/join_planner.rs index d087448a73743..6a0bab5378db3 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/join_planner.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/join_planner.rs @@ -21,14 +21,6 @@ impl JoinPlanner { } } - pub fn make_join_node_with_prefix( - &self, - alias_prefix: &Option, /*TODO dimensions for subqueries*/ - ) -> Result, CubeError> { - let join = self.query_tools.cached_data().join()?.clone(); - self.make_join_node_impl(alias_prefix, join) - } - pub fn make_join_node_with_prefix_and_join_hints( &self, alias_prefix: &Option, /*TODO dimensions for subqueries*/ @@ -38,11 +30,7 @@ impl JoinPlanner { self.make_join_node_impl(alias_prefix, join) } - pub fn make_join_node(&self) -> Result, CubeError> { - self.make_join_node_with_prefix(&None) - } - - fn make_join_node_impl( + pub fn make_join_node_impl( &self, alias_prefix: &Option, join: Rc, diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multi_stage/member_query_planner.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multi_stage/member_query_planner.rs index 461fbcc50bbae..5d906ecb83552 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multi_stage/member_query_planner.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multi_stage/member_query_planner.rs @@ -12,12 +12,14 @@ use crate::planner::planners::{ use crate::planner::query_tools::QueryTools; use crate::planner::sql_evaluator::sql_nodes::SqlNodesFactory; use crate::planner::sql_evaluator::ReferencesBuilder; +use crate::planner::sql_templates::PlanSqlTemplates; use crate::planner::QueryProperties; use crate::planner::{BaseDimension, BaseMeasure, BaseMember, BaseMemberHelper, BaseTimeDimension}; use cubenativeutils::CubeError; use itertools::Itertools; use std::collections::HashMap; use std::rc::Rc; + pub struct MultiStageMemberQueryPlanner { query_tools: Rc, _query_properties: Rc, @@ -381,6 +383,7 @@ impl MultiStageMemberQueryPlanner { let full_key_aggregate_planner = FullKeyAggregateQueryPlanner::new( cte_query_properties.clone(), node_factory.clone(), + PlanSqlTemplates::new(self.query_tools.templates_render()), ); let subqueries = multiplied_measures_query_planner.plan_queries()?; let result = full_key_aggregate_planner.plan(subqueries, vec![])?; diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multiplied_measures_query_planner.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multiplied_measures_query_planner.rs index 1d1152d276e91..5e4dcce5ab367 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multiplied_measures_query_planner.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multiplied_measures_query_planner.rs @@ -1,4 +1,5 @@ use super::{CommonUtils, JoinPlanner}; +use crate::cube_bridge::join_definition::JoinDefinition; use crate::plan::{ Expr, From, JoinBuilder, JoinCondition, MemberExpression, QualifiedColumnName, Select, SelectBuilder, @@ -50,8 +51,21 @@ impl MultipliedMeasuresQueryPlanner { let mut joins = Vec::new(); if !measures.regular_measures.is_empty() { - let regular_subquery = self.regular_measures_subquery(&measures.regular_measures)?; - joins.push(regular_subquery); + let join_multi_fact_groups = self + .query_properties + .compute_join_multi_fact_groups_with_measures(&measures.regular_measures)?; + for (i, (join, measures)) in join_multi_fact_groups.iter().enumerate() { + let regular_subquery = self.regular_measures_subquery( + measures, + join.clone(), + if i == 0 { + "main".to_string() + } else { + format!("main_{}", i) + }, + )?; + joins.push(regular_subquery); + } } for (cube_name, measures) in measures @@ -60,7 +74,22 @@ impl MultipliedMeasuresQueryPlanner { .into_iter() .into_group_map_by(|m| m.cube_name().clone()) { - let aggregate_subquery = self.aggregate_subquery(&cube_name, &measures)?; + let join_multi_fact_groups = self + .query_properties + .compute_join_multi_fact_groups_with_measures(&measures)?; + if join_multi_fact_groups.len() != 1 { + return Err(CubeError::internal( + format!( + "Expected just one multi-fact join group for aggregate measures but got multiple: {}", + join_multi_fact_groups.into_iter().map(|(_, measures)| format!("({})", measures.iter().map(|m| m.full_name()).join(", "))).join(", ") + ) + )); + } + let aggregate_subquery = self.aggregate_subquery( + &cube_name, + &measures, + join_multi_fact_groups.into_iter().next().unwrap().0, + )?; joins.push(aggregate_subquery); } Ok(joins) @@ -70,9 +99,10 @@ impl MultipliedMeasuresQueryPlanner { &self, key_cube_name: &String, measures: &Vec>, + key_join: Rc, ) -> Result, CubeError> { let primary_keys_dimensions = self.common_utils.primary_keys_dimensions(key_cube_name)?; - let keys_query = self.key_query(&primary_keys_dimensions, key_cube_name)?; + let keys_query = self.key_query(&primary_keys_dimensions, key_join, key_cube_name)?; let keys_query_alias = format!("keys"); let should_build_join_for_measure_select = self.check_should_build_join_for_measure_select(measures, key_cube_name)?; @@ -205,6 +235,7 @@ impl MultipliedMeasuresQueryPlanner { } Ok(false) } + fn aggregate_subquery_measure_join( &self, _key_cube_name: &String, @@ -230,10 +261,12 @@ impl MultipliedMeasuresQueryPlanner { fn regular_measures_subquery( &self, measures: &Vec>, + join: Rc, + alias_prefix: String, ) -> Result, CubeError> { let source = self .join_planner - .make_join_node_with_prefix(&Some(format!("main")))?; + .make_join_node_impl(&Some(alias_prefix), join)?; let mut select_builder = SelectBuilder::new(source.clone()); let mut context_factory = self.context_factory.clone(); @@ -259,11 +292,12 @@ impl MultipliedMeasuresQueryPlanner { fn key_query( &self, dimensions: &Vec>, + key_join: Rc, key_cube_name: &String, ) -> Result, CubeError> { let source = self .join_planner - .make_join_node_with_prefix(&Some(format!("{}_key", key_cube_name)))?; + .make_join_node_impl(&Some(format!("{}_key", key_cube_name)), key_join)?; let dimensions = self .query_properties .dimensions_for_select_append(dimensions); diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/simple_query_planer.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/simple_query_planer.rs index 9229314a0cc51..9ed024a96dd04 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/simple_query_planer.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/planners/simple_query_planer.rs @@ -36,7 +36,9 @@ impl SimpleQueryPlanner { }) }; let mut context_factory = self.context_factory.clone(); - let from = self.join_planner.make_join_node()?; + let from = self + .join_planner + .make_join_node_impl(&None, self.query_properties.simple_query_join()?)?; let mut select_builder = SelectBuilder::new(from.clone()); for time_dim in self.query_properties.time_dimensions() { if let Some(granularity) = time_dim.get_granularity() { diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/query_properties.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/query_properties.rs index 54b31fa40ed20..b14e1fc882b84 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/query_properties.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/query_properties.rs @@ -2,6 +2,7 @@ use super::filter::compiler::FilterCompiler; use super::query_tools::QueryTools; use super::{BaseDimension, BaseMeasure, BaseMember, BaseMemberHelper, BaseTimeDimension}; use crate::cube_bridge::base_query_options::BaseQueryOptions; +use crate::cube_bridge::join_definition::JoinDefinition; use crate::plan::{Expr, Filter, FilterItem, MemberExpression}; use crate::planner::sql_evaluator::collectors::{ collect_multiplied_measures, has_cumulative_members, has_multi_stage_members, @@ -31,7 +32,7 @@ impl OrderByItem { } } -#[derive(Default, Clone)] +#[derive(Default, Clone, Debug)] pub struct FullKeyAggregateMeasures { pub multiplied_measures: Vec>, pub regular_measures: Vec>, @@ -62,6 +63,7 @@ pub struct QueryProperties { query_tools: Rc, ignore_cumulative: bool, ungrouped: bool, + multi_fact_join_groups: Vec<(Rc, Vec>)>, } impl QueryProperties { @@ -127,9 +129,6 @@ impl QueryProperties { let (dimensions_filters, time_dimensions_filters, measures_filters) = filter_compiler.extract_result(); - let all_join_hints = evaluator_compiler.join_hints()?; - let join = query_tools.join_graph().build_join(all_join_hints)?; - query_tools.cached_data_mut().set_join(join); //FIXME may be this filter should be applied on other place let time_dimensions = time_dimensions .into_iter() @@ -157,6 +156,16 @@ impl QueryProperties { }; let ungrouped = options.static_data().ungrouped.unwrap_or(false); + let multi_fact_join_groups = Self::compute_join_multi_fact_groups( + query_tools.clone(), + &measures, + &dimensions, + &time_dimensions, + &time_dimensions_filters, + &dimensions_filters, + &measures_filters, + )?; + Ok(Rc::new(Self { measures, dimensions, @@ -170,6 +179,7 @@ impl QueryProperties { query_tools, ignore_cumulative: false, ungrouped, + multi_fact_join_groups, })) } @@ -193,6 +203,16 @@ impl QueryProperties { order_by }; + let multi_fact_join_groups = Self::compute_join_multi_fact_groups( + query_tools.clone(), + &measures, + &dimensions, + &time_dimensions, + &time_dimensions_filters, + &dimensions_filters, + &measures_filters, + )?; + Ok(Rc::new(Self { measures, dimensions, @@ -206,9 +226,122 @@ impl QueryProperties { query_tools, ignore_cumulative, ungrouped, + multi_fact_join_groups, })) } + pub fn compute_join_multi_fact_groups_with_measures( + &self, + measures: &Vec>, + ) -> Result, Vec>)>, CubeError> { + Self::compute_join_multi_fact_groups( + self.query_tools.clone(), + measures, + &self.dimensions, + &self.time_dimensions, + &self.time_dimensions_filters, + &self.dimensions_filters, + &self.measures_filters, + ) + } + + pub fn compute_join_multi_fact_groups( + query_tools: Rc, + measures: &Vec>, + dimensions: &Vec>, + time_dimensions: &Vec>, + time_dimensions_filters: &Vec, + dimensions_filters: &Vec, + measures_filters: &Vec, + ) -> Result, Vec>)>, CubeError> { + let dimensions_join_hints = query_tools + .cached_data_mut() + .join_hints_for_base_member_vec(&dimensions)?; + let time_dimensions_join_hints = query_tools + .cached_data_mut() + .join_hints_for_base_member_vec(&time_dimensions)?; + let time_dimensions_filters_join_hints = query_tools + .cached_data_mut() + .join_hints_for_filter_item_vec(&time_dimensions_filters)?; + let dimensions_filters_join_hints = query_tools + .cached_data_mut() + .join_hints_for_filter_item_vec(&dimensions_filters)?; + let measures_filters_join_hints = query_tools + .cached_data_mut() + .join_hints_for_filter_item_vec(&measures_filters)?; + + let mut dimension_and_filter_join_hints_concat = Vec::new(); + + dimension_and_filter_join_hints_concat.extend(dimensions_join_hints.into_iter()); + dimension_and_filter_join_hints_concat.extend(time_dimensions_join_hints.into_iter()); + dimension_and_filter_join_hints_concat + .extend(time_dimensions_filters_join_hints.into_iter()); + dimension_and_filter_join_hints_concat.extend(dimensions_filters_join_hints.into_iter()); + // TODO This is not quite correct. Decide on how to handle it. Keeping it here just to blow up on unsupported case + dimension_and_filter_join_hints_concat.extend(measures_filters_join_hints.into_iter()); + + let measures_to_join = if measures.is_empty() { + let join = query_tools + .cached_data_mut() + .join_by_hints(dimension_and_filter_join_hints_concat.clone(), |hints| { + query_tools.join_graph().build_join(hints) + })?; + vec![(Vec::new(), join)] + } else { + measures + .iter() + .map(|m| -> Result<_, CubeError> { + let measure_join_hints = query_tools + .cached_data_mut() + .join_hints_for_member(m.member_evaluator())?; + let join = query_tools.cached_data_mut().join_by_hints( + dimension_and_filter_join_hints_concat + .clone() + .into_iter() + .chain(vec![measure_join_hints].into_iter()) + .collect::>(), + |hints| query_tools.join_graph().build_join(hints), + )?; + Ok((vec![m.clone()], join)) + }) + .collect::, _>>()? + }; + Ok(measures_to_join + .into_iter() + .into_group_map_by(|(_, (key, _))| key.clone()) + .into_values() + .map(|measures_and_join| { + ( + measures_and_join.iter().next().unwrap().1 .1.clone(), + measures_and_join + .into_iter() + .flat_map(|m| m.0) + .collect::>(), + ) + }) + .collect()) + } + + pub fn is_multi_fact_join(&self) -> bool { + self.multi_fact_join_groups.len() > 1 + } + + pub fn simple_query_join(&self) -> Result, CubeError> { + if self.multi_fact_join_groups.len() != 1 { + return Err(CubeError::internal(format!( + "Expected just one multi-fact join group for simple query but got multiple: {}", + self.multi_fact_join_groups + .iter() + .map(|(_, measures)| format!( + "({})", + measures.iter().map(|m| m.full_name()).join(", ") + )) + .join(", ") + ))); + } + Ok(self.multi_fact_join_groups.iter().next().unwrap().0.clone()) + } + pub fn measures(&self) -> &Vec> { &self.measures } @@ -390,6 +523,7 @@ impl QueryProperties { let full_aggregate_measure = self.full_key_aggregate_measures()?; if full_aggregate_measure.multiplied_measures.is_empty() && full_aggregate_measure.multi_stage_measures.is_empty() + && !self.is_multi_fact_join() { Ok(true) } else { @@ -413,9 +547,18 @@ impl QueryProperties { if has_multi_stage_members(m.member_evaluator(), self.ignore_cumulative)? { result.multi_stage_measures.push(m.clone()) } else { - for item in - collect_multiplied_measures(self.query_tools.clone(), m.member_evaluator())? - { + let join = self + .compute_join_multi_fact_groups_with_measures(&vec![m.clone()])? + .iter() + .next() + .expect("No join groups returned for single measure multi-fact join group") + .0 + .clone(); + for item in collect_multiplied_measures( + self.query_tools.clone(), + m.member_evaluator(), + join, + )? { if item.multiplied { result.multiplied_measures.push(item.measure.clone()); } else { diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/query_tools.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/query_tools.rs index b2cb0497606c8..ff1dfb9244ab0 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/query_tools.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/query_tools.rs @@ -1,10 +1,13 @@ -use super::sql_evaluator::Compiler; -use super::ParamsAllocator; +use super::sql_evaluator::{Compiler, MemberSymbol}; +use super::{BaseMember, ParamsAllocator}; use crate::cube_bridge::base_tools::BaseTools; use crate::cube_bridge::evaluator::CubeEvaluator; use crate::cube_bridge::join_definition::JoinDefinition; use crate::cube_bridge::join_graph::JoinGraph; +use crate::cube_bridge::join_item::JoinItemStatic; use crate::cube_bridge::sql_templates_render::SqlTemplatesRender; +use crate::plan::FilterItem; +use crate::planner::sql_evaluator::collectors::collect_join_hints; use chrono_tz::Tz; use convert_case::{Case, Casing}; use cubenativeutils::CubeError; @@ -12,25 +15,103 @@ use itertools::Itertools; use lazy_static::lazy_static; use regex::Regex; use std::cell::{Ref, RefCell, RefMut}; +use std::collections::HashMap; use std::rc::Rc; pub struct QueryToolsCachedData { - join: Option>, + join_hints: HashMap>>, + join_hints_to_join_key: HashMap>>, Rc>, + join_key_to_join: HashMap, Rc>, +} + +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct JoinKey { + root: String, + joins: Vec, } impl QueryToolsCachedData { pub fn new() -> Self { - Self { join: None } + Self { + join_hints: HashMap::new(), + join_hints_to_join_key: HashMap::new(), + join_key_to_join: HashMap::new(), + } + } + + pub fn join_hints_for_member( + &mut self, + node: &Rc, + ) -> Result>, CubeError> { + let full_name = node.full_name(); + if let Some(val) = self.join_hints.get(&full_name) { + Ok(val.clone()) + } else { + let join_hints = Rc::new(collect_join_hints(node)?); + self.join_hints.insert(full_name, join_hints.clone()); + Ok(join_hints) + } } - pub fn join(&self) -> Result, CubeError> { - self.join.clone().ok_or(CubeError::internal( - "Join not set in QueryToolsCachedData".to_string(), - )) + pub fn join_hints_for_base_member_vec( + &mut self, + vec: &Vec>, + ) -> Result>>, CubeError> { + vec.iter() + .map(|b| self.join_hints_for_member(&b.member_evaluator())) + .collect::, _>>() } - pub fn set_join(&mut self, join: Rc) { - self.join = Some(join); + pub fn join_hints_for_member_symbol_vec( + &mut self, + vec: &Vec>, + ) -> Result>>, CubeError> { + vec.iter() + .map(|b| self.join_hints_for_member(b)) + .collect::, _>>() + } + + pub fn join_hints_for_filter_item_vec( + &mut self, + vec: &Vec, + ) -> Result>>, CubeError> { + let mut member_symbols = Vec::new(); + for i in vec.iter() { + i.find_all_member_evaluators(&mut member_symbols); + } + member_symbols + .iter() + .map(|b| self.join_hints_for_member(b)) + .collect::, _>>() + } + + pub fn join_by_hints( + &mut self, + hints: Vec>>, + join_fn: impl FnOnce(Vec) -> Result, CubeError>, + ) -> Result<(Rc, Rc), CubeError> { + if let Some(key) = self.join_hints_to_join_key.get(&hints) { + Ok((key.clone(), self.join_key_to_join.get(key).unwrap().clone())) + } else { + let join = join_fn( + hints + .iter() + .flat_map(|h| h.as_ref().iter().cloned()) + .collect(), + )?; + let join_key = Rc::new(JoinKey { + root: join.static_data().root.to_string(), + joins: join + .joins()? + .items() + .iter() + .map(|i| i.static_data().clone()) + .collect(), + }); + self.join_hints_to_join_key.insert(hints, join_key.clone()); + self.join_key_to_join.insert(join_key.clone(), join.clone()); + Ok((join_key, join)) + } } } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/multiplied_measures_collector.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/multiplied_measures_collector.rs index c285bff19379f..62de3b9914d73 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/multiplied_measures_collector.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/collectors/multiplied_measures_collector.rs @@ -1,3 +1,4 @@ +use crate::cube_bridge::join_definition::JoinDefinition; use crate::planner::query_tools::QueryTools; use crate::planner::sql_evaluator::{MemberSymbol, TraversalVisitor}; use crate::planner::BaseMeasure; @@ -65,13 +66,19 @@ pub struct MultipliedMeasuresCollector { query_tools: Rc, composite_measures: HashSet, colllected_measures: Vec, + join: Rc, } impl MultipliedMeasuresCollector { - pub fn new(query_tools: Rc, composite_measures: HashSet) -> Self { + pub fn new( + query_tools: Rc, + composite_measures: HashSet, + join: Rc, + ) -> Self { Self { query_tools, composite_measures, + join, colllected_measures: vec![], } } @@ -91,8 +98,8 @@ impl TraversalVisitor for MultipliedMeasuresCollector { let res = match node.as_ref() { MemberSymbol::Measure(e) => { let full_name = e.full_name(); - let join = self.query_tools.cached_data().join()?; - let multiplied = join + let multiplied = self + .join .static_data() .multiplication_factor .get(e.cube_name()) @@ -123,11 +130,12 @@ impl TraversalVisitor for MultipliedMeasuresCollector { pub fn collect_multiplied_measures( query_tools: Rc, node: &Rc, + join: Rc, ) -> Result, CubeError> { let mut composite_collector = CompositeMeasuresCollector::new(); composite_collector.apply(node, &CompositeMeasureCollectorState::new(None))?; let composite_measures = composite_collector.extract_result(); - let mut visitor = MultipliedMeasuresCollector::new(query_tools, composite_measures); + let mut visitor = MultipliedMeasuresCollector::new(query_tools, composite_measures, join); visitor.apply(node, &())?; Ok(visitor.extract_result()) } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/compiler.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/compiler.rs index c23f085fbee99..9e87582b8c7d1 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/compiler.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/compiler.rs @@ -12,6 +12,7 @@ use std::collections::HashMap; use std::rc::Rc; pub struct Compiler { cube_evaluator: Rc, + /* (type, name) */ members: HashMap<(String, String), Rc>, } diff --git a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_templates/plan.rs b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_templates/plan.rs index 26b12acacd25a..d00ebafa4caba 100644 --- a/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_templates/plan.rs +++ b/rust/cubesqlplanner/cubesqlplanner/src/planner/sql_templates/plan.rs @@ -1,10 +1,12 @@ use super::{TemplateGroupByColumn, TemplateOrderByColumn, TemplateProjectionColumn}; use crate::cube_bridge::sql_templates_render::SqlTemplatesRender; +use crate::plan::join::JoinType; use convert_case::{Case, Casing}; use cubenativeutils::CubeError; use minijinja::context; use std::rc::Rc; +#[derive(Clone)] pub struct PlanSqlTemplates { render: Rc, } @@ -74,6 +76,7 @@ impl PlanSqlTemplates { context! { expr => expr, negate => negate }, ) } + pub fn always_true(&self) -> Result { Ok(self.render.get_template("filters/always_true")?.clone()) } @@ -168,11 +171,16 @@ impl PlanSqlTemplates { ) } - pub fn join(&self, source: &str, condition: &str, is_inner: bool) -> Result { - let join_type = if is_inner { - self.render.get_template("join_types/inner")? - } else { - self.render.get_template("join_types/left")? + pub fn join( + &self, + source: &str, + condition: &str, + join_type: &JoinType, + ) -> Result { + let join_type = match join_type { + JoinType::Full => self.render.get_template("join_types/full")?, + JoinType::Inner => self.render.get_template("join_types/inner")?, + JoinType::Left => self.render.get_template("join_types/left")?, }; self.render.render_template( "statements/join", @@ -180,6 +188,13 @@ impl PlanSqlTemplates { ) } + pub fn binary_expr(&self, left: &str, op: &str, right: &str) -> Result { + self.render.render_template( + "expressions/binary", + context! { left => left, op => op, right => right }, + ) + } + pub fn join_by_dimension_conditions( &self, left_column: &String, @@ -187,6 +202,13 @@ impl PlanSqlTemplates { null_check: bool, ) -> Result { let null_check = if null_check { + if self.supports_is_not_distinct_from() { + let is_not_distinct_from_op = self + .render + .render_template("operators/is_not_distinct_from", context! {})?; + + return self.binary_expr(left_column, &is_not_distinct_from_op, right_column); + } format!( " OR ({} AND {})", self.is_null_expr(&left_column, false)?, @@ -201,4 +223,9 @@ impl PlanSqlTemplates { left_column, right_column, null_check )) } + + pub fn supports_is_not_distinct_from(&self) -> bool { + self.render + .contains_template("operators/is_not_distinct_from") + } } From 8ff2eca3b6424510c1fad8f30079031f6445110d Mon Sep 17 00:00:00 2001 From: Pavel Tiunov Date: Sun, 15 Dec 2024 18:21:03 -0800 Subject: [PATCH 19/21] v1.1.10 --- CHANGELOG.md | 22 +++++++ lerna.json | 2 +- packages/cubejs-api-gateway/CHANGELOG.md | 13 +++++ packages/cubejs-api-gateway/package.json | 6 +- packages/cubejs-athena-driver/CHANGELOG.md | 8 +++ packages/cubejs-athena-driver/package.json | 8 +-- packages/cubejs-backend-cloud/CHANGELOG.md | 8 +++ packages/cubejs-backend-cloud/package.json | 4 +- packages/cubejs-backend-maven/CHANGELOG.md | 8 +++ packages/cubejs-backend-maven/package.json | 4 +- packages/cubejs-backend-native/CHANGELOG.md | 8 +++ packages/cubejs-backend-native/package.json | 6 +- packages/cubejs-backend-shared/CHANGELOG.md | 11 ++++ packages/cubejs-backend-shared/package.json | 2 +- packages/cubejs-base-driver/CHANGELOG.md | 8 +++ packages/cubejs-base-driver/package.json | 4 +- packages/cubejs-bigquery-driver/CHANGELOG.md | 8 +++ packages/cubejs-bigquery-driver/package.json | 8 +-- packages/cubejs-cli/CHANGELOG.md | 8 +++ packages/cubejs-cli/package.json | 8 +-- .../cubejs-clickhouse-driver/CHANGELOG.md | 8 +++ .../cubejs-clickhouse-driver/package.json | 8 +-- packages/cubejs-crate-driver/CHANGELOG.md | 8 +++ packages/cubejs-crate-driver/package.json | 8 +-- packages/cubejs-cubestore-driver/CHANGELOG.md | 8 +++ packages/cubejs-cubestore-driver/package.json | 8 +-- .../CHANGELOG.md | 8 +++ .../package.json | 10 ++-- .../cubejs-dbt-schema-extension/CHANGELOG.md | 8 +++ .../cubejs-dbt-schema-extension/package.json | 6 +- packages/cubejs-docker/CHANGELOG.md | 8 +++ packages/cubejs-docker/package.json | 58 +++++++++---------- packages/cubejs-dremio-driver/CHANGELOG.md | 11 ++++ packages/cubejs-dremio-driver/package.json | 8 +-- packages/cubejs-druid-driver/CHANGELOG.md | 8 +++ packages/cubejs-druid-driver/package.json | 8 +-- packages/cubejs-duckdb-driver/CHANGELOG.md | 8 +++ packages/cubejs-duckdb-driver/package.json | 10 ++-- .../cubejs-elasticsearch-driver/CHANGELOG.md | 8 +++ .../cubejs-elasticsearch-driver/package.json | 6 +- packages/cubejs-firebolt-driver/CHANGELOG.md | 8 +++ packages/cubejs-firebolt-driver/package.json | 10 ++-- packages/cubejs-hive-driver/CHANGELOG.md | 8 +++ packages/cubejs-hive-driver/package.json | 6 +- packages/cubejs-jdbc-driver/CHANGELOG.md | 8 +++ packages/cubejs-jdbc-driver/package.json | 6 +- packages/cubejs-ksql-driver/CHANGELOG.md | 8 +++ packages/cubejs-ksql-driver/package.json | 8 +-- .../cubejs-materialize-driver/CHANGELOG.md | 8 +++ .../cubejs-materialize-driver/package.json | 10 ++-- packages/cubejs-mongobi-driver/CHANGELOG.md | 8 +++ packages/cubejs-mongobi-driver/package.json | 6 +- packages/cubejs-mssql-driver/CHANGELOG.md | 8 +++ packages/cubejs-mssql-driver/package.json | 4 +- .../CHANGELOG.md | 8 +++ .../package.json | 6 +- packages/cubejs-mysql-driver/CHANGELOG.md | 8 +++ packages/cubejs-mysql-driver/package.json | 8 +-- packages/cubejs-oracle-driver/CHANGELOG.md | 8 +++ packages/cubejs-oracle-driver/package.json | 4 +- packages/cubejs-pinot-driver/CHANGELOG.md | 8 +++ packages/cubejs-pinot-driver/package.json | 8 +-- packages/cubejs-postgres-driver/CHANGELOG.md | 8 +++ packages/cubejs-postgres-driver/package.json | 8 +-- packages/cubejs-prestodb-driver/CHANGELOG.md | 8 +++ packages/cubejs-prestodb-driver/package.json | 6 +- .../cubejs-query-orchestrator/CHANGELOG.md | 8 +++ .../cubejs-query-orchestrator/package.json | 8 +-- packages/cubejs-questdb-driver/CHANGELOG.md | 8 +++ packages/cubejs-questdb-driver/package.json | 10 ++-- packages/cubejs-redshift-driver/CHANGELOG.md | 8 +++ packages/cubejs-redshift-driver/package.json | 8 +-- packages/cubejs-schema-compiler/CHANGELOG.md | 16 +++++ packages/cubejs-schema-compiler/package.json | 8 +-- packages/cubejs-server-core/CHANGELOG.md | 11 ++++ packages/cubejs-server-core/package.json | 18 +++--- packages/cubejs-server/CHANGELOG.md | 8 +++ packages/cubejs-server/package.json | 12 ++-- packages/cubejs-snowflake-driver/CHANGELOG.md | 8 +++ packages/cubejs-snowflake-driver/package.json | 6 +- packages/cubejs-sqlite-driver/CHANGELOG.md | 8 +++ packages/cubejs-sqlite-driver/package.json | 6 +- packages/cubejs-templates/CHANGELOG.md | 8 +++ packages/cubejs-templates/package.json | 4 +- packages/cubejs-testing-drivers/CHANGELOG.md | 8 +++ packages/cubejs-testing-drivers/package.json | 30 +++++----- packages/cubejs-testing-shared/CHANGELOG.md | 8 +++ packages/cubejs-testing-shared/package.json | 8 +-- packages/cubejs-testing/CHANGELOG.md | 12 ++++ packages/cubejs-testing/package.json | 16 ++--- packages/cubejs-trino-driver/CHANGELOG.md | 8 +++ packages/cubejs-trino-driver/package.json | 10 ++-- rust/cubesql/CHANGELOG.md | 11 ++++ rust/cubesql/package.json | 2 +- rust/cubestore/CHANGELOG.md | 11 ++++ rust/cubestore/package.json | 4 +- 96 files changed, 641 insertions(+), 211 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 466c045f271d2..7300879c72781 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,28 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + + +### Bug Fixes + +* **api-gateway:** allow switch sql user when the new user is the same ([#9037](https://github.com/cube-js/cube/issues/9037)) ([a69c28f](https://github.com/cube-js/cube/commit/a69c28f524fa0625b825b98a38e7f5a211a98f74)) +* **api-gateway:** make sure DAP works sql pushdown ([#9021](https://github.com/cube-js/cube/issues/9021)) ([23695b2](https://github.com/cube-js/cube/commit/23695b2b5e886b5b7daf8b3f74003bb04e5b2e0b)) +* **cubestore:** Allow create an index from expressions ([#9006](https://github.com/cube-js/cube/issues/9006)) ([222cab8](https://github.com/cube-js/cube/commit/222cab897c289bfc929f217483e4905204bac12f)) +* **schema-compiler:** fix DAP with query_rewrite and python config ([#9033](https://github.com/cube-js/cube/issues/9033)) ([849790f](https://github.com/cube-js/cube/commit/849790f965dd0d9fddba11e3d8d124b84397ca9b)) +* **schema-compiler:** join relationship aliases ([ad4e8e3](https://github.com/cube-js/cube/commit/ad4e8e3872307ab77e035709e5208b0191f87f5b)) + + +### Features + +* **cubesql:** Basic VALUES support in rewrite engine ([#9041](https://github.com/cube-js/cube/issues/9041)) ([368671f](https://github.com/cube-js/cube/commit/368671fd1b53b2ed5ad8df6af113492982f23c0c)) +* **dremio-driver:** Add Dremio Cloud Support ([#8956](https://github.com/cube-js/cube/issues/8956)) ([d2c2fcd](https://github.com/cube-js/cube/commit/d2c2fcdaf8944ea7dd27e73b63c0b151c317022e)) +* **tesseract:** Support multiple join paths within single query ([#9047](https://github.com/cube-js/cube/issues/9047)) ([b62446e](https://github.com/cube-js/cube/commit/b62446e3c3893068f8dd8aa32d7204ea06a16f98)) + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) diff --git a/lerna.json b/lerna.json index 147bccb662d68..35f7698b421c9 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.1.9", + "version": "1.1.10", "npmClient": "yarn", "useWorkspaces": true, "packages": [ diff --git a/packages/cubejs-api-gateway/CHANGELOG.md b/packages/cubejs-api-gateway/CHANGELOG.md index 3419e7095a47c..a7da43201cb4c 100644 --- a/packages/cubejs-api-gateway/CHANGELOG.md +++ b/packages/cubejs-api-gateway/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + + +### Bug Fixes + +* **api-gateway:** allow switch sql user when the new user is the same ([#9037](https://github.com/cube-js/cube/issues/9037)) ([a69c28f](https://github.com/cube-js/cube/commit/a69c28f524fa0625b825b98a38e7f5a211a98f74)) +* **api-gateway:** make sure DAP works sql pushdown ([#9021](https://github.com/cube-js/cube/issues/9021)) ([23695b2](https://github.com/cube-js/cube/commit/23695b2b5e886b5b7daf8b3f74003bb04e5b2e0b)) +* **schema-compiler:** fix DAP with query_rewrite and python config ([#9033](https://github.com/cube-js/cube/issues/9033)) ([849790f](https://github.com/cube-js/cube/commit/849790f965dd0d9fddba11e3d8d124b84397ca9b)) + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/api-gateway diff --git a/packages/cubejs-api-gateway/package.json b/packages/cubejs-api-gateway/package.json index 1890a221a4af1..be6e40466c398 100644 --- a/packages/cubejs-api-gateway/package.json +++ b/packages/cubejs-api-gateway/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/api-gateway", "description": "Cube.js API Gateway", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -27,8 +27,8 @@ "dist/src/*" ], "dependencies": { - "@cubejs-backend/native": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/native": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "@ungap/structured-clone": "^0.3.4", "body-parser": "^1.19.0", "chrono-node": "^2.6.2", diff --git a/packages/cubejs-athena-driver/CHANGELOG.md b/packages/cubejs-athena-driver/CHANGELOG.md index 54c9e9a5b26b2..4b41e7ee955de 100644 --- a/packages/cubejs-athena-driver/CHANGELOG.md +++ b/packages/cubejs-athena-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/athena-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/athena-driver diff --git a/packages/cubejs-athena-driver/package.json b/packages/cubejs-athena-driver/package.json index bb032f9c02faf..87c0f532fecab 100644 --- a/packages/cubejs-athena-driver/package.json +++ b/packages/cubejs-athena-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/athena-driver", "description": "Cube.js Athena database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -29,13 +29,13 @@ "types": "dist/src/index.d.ts", "dependencies": { "@aws-sdk/client-athena": "^3.22.0", - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "sqlstring": "^2.3.1" }, "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.9", + "@cubejs-backend/testing-shared": "1.1.10", "@types/ramda": "^0.27.40", "typescript": "~5.2.2" }, diff --git a/packages/cubejs-backend-cloud/CHANGELOG.md b/packages/cubejs-backend-cloud/CHANGELOG.md index fd85329452169..67055d0d53e1c 100644 --- a/packages/cubejs-backend-cloud/CHANGELOG.md +++ b/packages/cubejs-backend-cloud/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/cloud + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/cloud diff --git a/packages/cubejs-backend-cloud/package.json b/packages/cubejs-backend-cloud/package.json index 741999795eeb2..fc22a65095539 100644 --- a/packages/cubejs-backend-cloud/package.json +++ b/packages/cubejs-backend-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/cloud", - "version": "1.1.8", + "version": "1.1.10", "description": "Cube Cloud package", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", @@ -32,7 +32,7 @@ }, "dependencies": { "@cubejs-backend/dotenv": "^9.0.2", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/shared": "1.1.10", "chokidar": "^3.5.1", "env-var": "^6.3.0", "fs-extra": "^9.1.0", diff --git a/packages/cubejs-backend-maven/CHANGELOG.md b/packages/cubejs-backend-maven/CHANGELOG.md index 2d3591aaa267e..36e6286575186 100644 --- a/packages/cubejs-backend-maven/CHANGELOG.md +++ b/packages/cubejs-backend-maven/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/maven + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/maven diff --git a/packages/cubejs-backend-maven/package.json b/packages/cubejs-backend-maven/package.json index 55c5de037dfa5..e1ed0991f725e 100644 --- a/packages/cubejs-backend-maven/package.json +++ b/packages/cubejs-backend-maven/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/maven", "description": "Cube.js Maven Wrapper for java dependencies downloading", "author": "Cube Dev, Inc.", - "version": "1.1.8", + "version": "1.1.10", "license": "Apache-2.0", "repository": { "type": "git", @@ -31,7 +31,7 @@ "dist/src/*" ], "dependencies": { - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/shared": "1.1.10", "source-map-support": "^0.5.19", "xmlbuilder2": "^2.4.0" }, diff --git a/packages/cubejs-backend-native/CHANGELOG.md b/packages/cubejs-backend-native/CHANGELOG.md index e7a57f3b44709..b952f65eabd37 100644 --- a/packages/cubejs-backend-native/CHANGELOG.md +++ b/packages/cubejs-backend-native/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/native + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/native diff --git a/packages/cubejs-backend-native/package.json b/packages/cubejs-backend-native/package.json index 153c99c3fefb8..68ec83e906cb6 100644 --- a/packages/cubejs-backend-native/package.json +++ b/packages/cubejs-backend-native/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/native", - "version": "1.1.9", + "version": "1.1.10", "author": "Cube Dev, Inc.", "description": "Native module for Cube.js (binding to Rust codebase)", "main": "dist/js/index.js", @@ -43,8 +43,8 @@ "uuid": "^8.3.2" }, "dependencies": { - "@cubejs-backend/cubesql": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/cubesql": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "@cubejs-infra/post-installer": "^0.0.7" }, "resources": { diff --git a/packages/cubejs-backend-shared/CHANGELOG.md b/packages/cubejs-backend-shared/CHANGELOG.md index baebb91db2d67..3029356faaf29 100644 --- a/packages/cubejs-backend-shared/CHANGELOG.md +++ b/packages/cubejs-backend-shared/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + + +### Features + +* **dremio-driver:** Add Dremio Cloud Support ([#8956](https://github.com/cube-js/cube/issues/8956)) ([d2c2fcd](https://github.com/cube-js/cube/commit/d2c2fcdaf8944ea7dd27e73b63c0b151c317022e)) + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) diff --git a/packages/cubejs-backend-shared/package.json b/packages/cubejs-backend-shared/package.json index 0fceeb421f6d8..88530184258be 100644 --- a/packages/cubejs-backend-shared/package.json +++ b/packages/cubejs-backend-shared/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/shared", - "version": "1.1.8", + "version": "1.1.10", "description": "Shared code for Cube.js backend packages", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", diff --git a/packages/cubejs-base-driver/CHANGELOG.md b/packages/cubejs-base-driver/CHANGELOG.md index 0397935a5a325..10120caa43c56 100644 --- a/packages/cubejs-base-driver/CHANGELOG.md +++ b/packages/cubejs-base-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/base-driver + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/base-driver diff --git a/packages/cubejs-base-driver/package.json b/packages/cubejs-base-driver/package.json index 256ad550d4c5a..0085c0595560d 100644 --- a/packages/cubejs-base-driver/package.json +++ b/packages/cubejs-base-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/base-driver", "description": "Cube.js Base Driver", "author": "Cube Dev, Inc.", - "version": "1.1.8", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -33,7 +33,7 @@ "@aws-sdk/s3-request-presigner": "^3.49.0", "@azure/identity": "^4.4.1", "@azure/storage-blob": "^12.9.0", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/shared": "1.1.10", "@google-cloud/storage": "^7.13.0" }, "devDependencies": { diff --git a/packages/cubejs-bigquery-driver/CHANGELOG.md b/packages/cubejs-bigquery-driver/CHANGELOG.md index e591d7f86dc39..22130088affac 100644 --- a/packages/cubejs-bigquery-driver/CHANGELOG.md +++ b/packages/cubejs-bigquery-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/bigquery-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/bigquery-driver diff --git a/packages/cubejs-bigquery-driver/package.json b/packages/cubejs-bigquery-driver/package.json index 9b43b58199842..f5fbadd2d2f17 100644 --- a/packages/cubejs-bigquery-driver/package.json +++ b/packages/cubejs-bigquery-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/bigquery-driver", "description": "Cube.js BigQuery database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -28,15 +28,15 @@ "main": "index.js", "types": "dist/src/index.d.ts", "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", "@cubejs-backend/dotenv": "^9.0.2", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/shared": "1.1.10", "@google-cloud/bigquery": "^7.7.0", "@google-cloud/storage": "^7.13.0", "ramda": "^0.27.2" }, "devDependencies": { - "@cubejs-backend/testing-shared": "1.1.9", + "@cubejs-backend/testing-shared": "1.1.10", "@types/big.js": "^6.2.2", "@types/dedent": "^0.7.0", "@types/jest": "^27", diff --git a/packages/cubejs-cli/CHANGELOG.md b/packages/cubejs-cli/CHANGELOG.md index 5e94fd74d369b..84be1e92ae039 100644 --- a/packages/cubejs-cli/CHANGELOG.md +++ b/packages/cubejs-cli/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package cubejs-cli + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package cubejs-cli diff --git a/packages/cubejs-cli/package.json b/packages/cubejs-cli/package.json index c3e7191f06b9c..0185fb7cef8ae 100644 --- a/packages/cubejs-cli/package.json +++ b/packages/cubejs-cli/package.json @@ -2,7 +2,7 @@ "name": "cubejs-cli", "description": "Cube.js Command Line Interface", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -31,8 +31,8 @@ ], "dependencies": { "@cubejs-backend/dotenv": "^9.0.2", - "@cubejs-backend/schema-compiler": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "chalk": "^2.4.2", "cli-progress": "^3.10", "commander": "^2.19.0", @@ -50,7 +50,7 @@ }, "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/server": "1.1.9", + "@cubejs-backend/server": "1.1.10", "@oclif/command": "^1.8.0", "@types/cli-progress": "^3.8.0", "@types/cross-spawn": "^6.0.2", diff --git a/packages/cubejs-clickhouse-driver/CHANGELOG.md b/packages/cubejs-clickhouse-driver/CHANGELOG.md index 21d7c465fe932..a836f1a921a8d 100644 --- a/packages/cubejs-clickhouse-driver/CHANGELOG.md +++ b/packages/cubejs-clickhouse-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/clickhouse-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/clickhouse-driver diff --git a/packages/cubejs-clickhouse-driver/package.json b/packages/cubejs-clickhouse-driver/package.json index 564815c89b0fb..081c0565b9428 100644 --- a/packages/cubejs-clickhouse-driver/package.json +++ b/packages/cubejs-clickhouse-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/clickhouse-driver", "description": "Cube.js ClickHouse database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -28,8 +28,8 @@ }, "dependencies": { "@clickhouse/client": "^1.7.0", - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "moment": "^2.24.0", "sqlstring": "^2.3.1", "uuid": "^8.3.2" @@ -37,7 +37,7 @@ "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.9", + "@cubejs-backend/testing-shared": "1.1.10", "@types/jest": "^27", "jest": "27", "typescript": "~5.2.2" diff --git a/packages/cubejs-crate-driver/CHANGELOG.md b/packages/cubejs-crate-driver/CHANGELOG.md index 331e0b92cecbd..4e4b984adf040 100644 --- a/packages/cubejs-crate-driver/CHANGELOG.md +++ b/packages/cubejs-crate-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/crate-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/crate-driver diff --git a/packages/cubejs-crate-driver/package.json b/packages/cubejs-crate-driver/package.json index 7093ce2f89bcc..45c1fc5649428 100644 --- a/packages/cubejs-crate-driver/package.json +++ b/packages/cubejs-crate-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/crate-driver", "description": "Cube.js Crate database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -28,14 +28,14 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/postgres-driver": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/postgres-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "pg": "^8.7.1" }, "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.9", + "@cubejs-backend/testing-shared": "1.1.10", "testcontainers": "^10.10.4", "typescript": "~5.2.2" }, diff --git a/packages/cubejs-cubestore-driver/CHANGELOG.md b/packages/cubejs-cubestore-driver/CHANGELOG.md index 76b725a1647dc..d75fef146450a 100644 --- a/packages/cubejs-cubestore-driver/CHANGELOG.md +++ b/packages/cubejs-cubestore-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/cubestore-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/cubestore-driver diff --git a/packages/cubejs-cubestore-driver/package.json b/packages/cubejs-cubestore-driver/package.json index f02fe3aeaa1ac..3b36173411629 100644 --- a/packages/cubejs-cubestore-driver/package.json +++ b/packages/cubejs-cubestore-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/cubestore-driver", "description": "Cube Store driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -26,9 +26,9 @@ "lint:fix": "eslint --fix src/*.ts" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/cubestore": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/cubestore": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "csv-write-stream": "^2.0.0", "flatbuffers": "23.3.3", "fs-extra": "^9.1.0", diff --git a/packages/cubejs-databricks-jdbc-driver/CHANGELOG.md b/packages/cubejs-databricks-jdbc-driver/CHANGELOG.md index ffd198bcf7bf0..b3e202f7d00ea 100644 --- a/packages/cubejs-databricks-jdbc-driver/CHANGELOG.md +++ b/packages/cubejs-databricks-jdbc-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/databricks-jdbc-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/databricks-jdbc-driver diff --git a/packages/cubejs-databricks-jdbc-driver/package.json b/packages/cubejs-databricks-jdbc-driver/package.json index 3654cef0ab2c1..6b320fc9e5bbe 100644 --- a/packages/cubejs-databricks-jdbc-driver/package.json +++ b/packages/cubejs-databricks-jdbc-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/databricks-jdbc-driver", "description": "Cube.js Databricks database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "license": "Apache-2.0", "repository": { "type": "git", @@ -28,10 +28,10 @@ "bin" ], "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/jdbc-driver": "1.1.8", - "@cubejs-backend/schema-compiler": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/jdbc-driver": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "node-fetch": "^2.6.1", "ramda": "^0.27.2", "source-map-support": "^0.5.19", diff --git a/packages/cubejs-dbt-schema-extension/CHANGELOG.md b/packages/cubejs-dbt-schema-extension/CHANGELOG.md index 94c4974fe9f3c..44d5565e00f56 100644 --- a/packages/cubejs-dbt-schema-extension/CHANGELOG.md +++ b/packages/cubejs-dbt-schema-extension/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/dbt-schema-extension + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/dbt-schema-extension diff --git a/packages/cubejs-dbt-schema-extension/package.json b/packages/cubejs-dbt-schema-extension/package.json index 660fa22a65ab7..d2df9a118b0da 100644 --- a/packages/cubejs-dbt-schema-extension/package.json +++ b/packages/cubejs-dbt-schema-extension/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/dbt-schema-extension", "description": "Cube.js dbt Schema Extension", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -25,14 +25,14 @@ "lint:fix": "eslint --fix src/* --ext .ts,.js" }, "dependencies": { - "@cubejs-backend/schema-compiler": "1.1.9", + "@cubejs-backend/schema-compiler": "1.1.10", "fs-extra": "^9.1.0", "inflection": "^1.12.0", "node-fetch": "^2.6.1" }, "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing": "1.1.9", + "@cubejs-backend/testing": "1.1.10", "@types/generic-pool": "^3.1.9", "@types/jest": "^27", "jest": "^27", diff --git a/packages/cubejs-docker/CHANGELOG.md b/packages/cubejs-docker/CHANGELOG.md index b8de3333fe99a..22d418b1dccd7 100644 --- a/packages/cubejs-docker/CHANGELOG.md +++ b/packages/cubejs-docker/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/docker + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/docker diff --git a/packages/cubejs-docker/package.json b/packages/cubejs-docker/package.json index 5c3dd4f65e14f..266963e9fbdd2 100644 --- a/packages/cubejs-docker/package.json +++ b/packages/cubejs-docker/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/docker", - "version": "1.1.9", + "version": "1.1.10", "description": "Cube.js In Docker (virtual package)", "author": "Cube Dev, Inc.", "license": "Apache-2.0", @@ -9,34 +9,34 @@ "node": "^14.0.0 || ^16.0.0 || >=17.0.0" }, "dependencies": { - "@cubejs-backend/athena-driver": "1.1.9", - "@cubejs-backend/bigquery-driver": "1.1.9", - "@cubejs-backend/clickhouse-driver": "1.1.9", - "@cubejs-backend/crate-driver": "1.1.9", - "@cubejs-backend/databricks-jdbc-driver": "1.1.9", - "@cubejs-backend/dbt-schema-extension": "1.1.9", - "@cubejs-backend/dremio-driver": "1.1.9", - "@cubejs-backend/druid-driver": "1.1.9", - "@cubejs-backend/duckdb-driver": "1.1.9", - "@cubejs-backend/elasticsearch-driver": "1.1.8", - "@cubejs-backend/firebolt-driver": "1.1.9", - "@cubejs-backend/hive-driver": "1.1.8", - "@cubejs-backend/ksql-driver": "1.1.9", - "@cubejs-backend/materialize-driver": "1.1.9", - "@cubejs-backend/mongobi-driver": "1.1.8", - "@cubejs-backend/mssql-driver": "1.1.8", - "@cubejs-backend/mysql-driver": "1.1.9", - "@cubejs-backend/oracle-driver": "1.1.8", - "@cubejs-backend/pinot-driver": "1.1.9", - "@cubejs-backend/postgres-driver": "1.1.9", - "@cubejs-backend/prestodb-driver": "1.1.8", - "@cubejs-backend/questdb-driver": "1.1.9", - "@cubejs-backend/redshift-driver": "1.1.9", - "@cubejs-backend/server": "1.1.9", - "@cubejs-backend/snowflake-driver": "1.1.8", - "@cubejs-backend/sqlite-driver": "1.1.8", - "@cubejs-backend/trino-driver": "1.1.9", - "cubejs-cli": "1.1.9", + "@cubejs-backend/athena-driver": "1.1.10", + "@cubejs-backend/bigquery-driver": "1.1.10", + "@cubejs-backend/clickhouse-driver": "1.1.10", + "@cubejs-backend/crate-driver": "1.1.10", + "@cubejs-backend/databricks-jdbc-driver": "1.1.10", + "@cubejs-backend/dbt-schema-extension": "1.1.10", + "@cubejs-backend/dremio-driver": "1.1.10", + "@cubejs-backend/druid-driver": "1.1.10", + "@cubejs-backend/duckdb-driver": "1.1.10", + "@cubejs-backend/elasticsearch-driver": "1.1.10", + "@cubejs-backend/firebolt-driver": "1.1.10", + "@cubejs-backend/hive-driver": "1.1.10", + "@cubejs-backend/ksql-driver": "1.1.10", + "@cubejs-backend/materialize-driver": "1.1.10", + "@cubejs-backend/mongobi-driver": "1.1.10", + "@cubejs-backend/mssql-driver": "1.1.10", + "@cubejs-backend/mysql-driver": "1.1.10", + "@cubejs-backend/oracle-driver": "1.1.10", + "@cubejs-backend/pinot-driver": "1.1.10", + "@cubejs-backend/postgres-driver": "1.1.10", + "@cubejs-backend/prestodb-driver": "1.1.10", + "@cubejs-backend/questdb-driver": "1.1.10", + "@cubejs-backend/redshift-driver": "1.1.10", + "@cubejs-backend/server": "1.1.10", + "@cubejs-backend/snowflake-driver": "1.1.10", + "@cubejs-backend/sqlite-driver": "1.1.10", + "@cubejs-backend/trino-driver": "1.1.10", + "cubejs-cli": "1.1.10", "typescript": "~5.2.2" }, "resolutions": { diff --git a/packages/cubejs-dremio-driver/CHANGELOG.md b/packages/cubejs-dremio-driver/CHANGELOG.md index 924881354fdad..59bbe8f047fe2 100644 --- a/packages/cubejs-dremio-driver/CHANGELOG.md +++ b/packages/cubejs-dremio-driver/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + + +### Features + +* **dremio-driver:** Add Dremio Cloud Support ([#8956](https://github.com/cube-js/cube/issues/8956)) ([d2c2fcd](https://github.com/cube-js/cube/commit/d2c2fcdaf8944ea7dd27e73b63c0b151c317022e)) + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/dremio-driver diff --git a/packages/cubejs-dremio-driver/package.json b/packages/cubejs-dremio-driver/package.json index e4fe8eeca2bb2..b0517f2a1cd31 100644 --- a/packages/cubejs-dremio-driver/package.json +++ b/packages/cubejs-dremio-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/dremio-driver", "description": "Cube.js Dremio driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -17,9 +17,9 @@ "lint:fix": "eslint driver/*.js" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/schema-compiler": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "axios": "^0.21.1", "moment-timezone": "^0.5.31", "sqlstring": "^2.3.1" diff --git a/packages/cubejs-druid-driver/CHANGELOG.md b/packages/cubejs-druid-driver/CHANGELOG.md index a0396272f441b..71e27a6d599a7 100644 --- a/packages/cubejs-druid-driver/CHANGELOG.md +++ b/packages/cubejs-druid-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/druid-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/druid-driver diff --git a/packages/cubejs-druid-driver/package.json b/packages/cubejs-druid-driver/package.json index 7395b797a4b56..5f40777f18bb6 100644 --- a/packages/cubejs-druid-driver/package.json +++ b/packages/cubejs-druid-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/druid-driver", "description": "Cube.js Druid database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "license": "Apache-2.0", "repository": { "type": "git", @@ -28,9 +28,9 @@ "dist/src/*" ], "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/schema-compiler": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "axios": "^0.21.1", "moment-timezone": "^0.5.31" }, diff --git a/packages/cubejs-duckdb-driver/CHANGELOG.md b/packages/cubejs-duckdb-driver/CHANGELOG.md index 3e4c01bda4355..0dbf7760c030a 100644 --- a/packages/cubejs-duckdb-driver/CHANGELOG.md +++ b/packages/cubejs-duckdb-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/duckdb-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/duckdb-driver diff --git a/packages/cubejs-duckdb-driver/package.json b/packages/cubejs-duckdb-driver/package.json index 34ca687d22613..7ec1fd197b691 100644 --- a/packages/cubejs-duckdb-driver/package.json +++ b/packages/cubejs-duckdb-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/duckdb-driver", "description": "Cube DuckDB database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -27,15 +27,15 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/schema-compiler": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "duckdb": "^1.0.0" }, "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.9", + "@cubejs-backend/testing-shared": "1.1.10", "@types/jest": "^27", "@types/node": "^18", "jest": "^27", diff --git a/packages/cubejs-elasticsearch-driver/CHANGELOG.md b/packages/cubejs-elasticsearch-driver/CHANGELOG.md index 880aef4c833d6..b5f4832e1a4a7 100644 --- a/packages/cubejs-elasticsearch-driver/CHANGELOG.md +++ b/packages/cubejs-elasticsearch-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/elasticsearch-driver + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/elasticsearch-driver diff --git a/packages/cubejs-elasticsearch-driver/package.json b/packages/cubejs-elasticsearch-driver/package.json index 796e77c82dabc..a4d9b0e6e9811 100644 --- a/packages/cubejs-elasticsearch-driver/package.json +++ b/packages/cubejs-elasticsearch-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/elasticsearch-driver", "description": "Cube.js elasticsearch database driver", "author": "Cube Dev, Inc.", - "version": "1.1.8", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -23,8 +23,8 @@ "driver" ], "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "@elastic/elasticsearch": "7.12.0", "sqlstring": "^2.3.1" }, diff --git a/packages/cubejs-firebolt-driver/CHANGELOG.md b/packages/cubejs-firebolt-driver/CHANGELOG.md index ed36131143d13..24b0611e5ba5d 100644 --- a/packages/cubejs-firebolt-driver/CHANGELOG.md +++ b/packages/cubejs-firebolt-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/firebolt-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/firebolt-driver diff --git a/packages/cubejs-firebolt-driver/package.json b/packages/cubejs-firebolt-driver/package.json index 7644959233f6d..4f7f6cf1faa36 100644 --- a/packages/cubejs-firebolt-driver/package.json +++ b/packages/cubejs-firebolt-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/firebolt-driver", "description": "Cube.js Firebolt database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -28,15 +28,15 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/schema-compiler": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "firebolt-sdk": "^1.8.0" }, "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.9", + "@cubejs-backend/testing-shared": "1.1.10", "typescript": "~5.2.2" }, "publishConfig": { diff --git a/packages/cubejs-hive-driver/CHANGELOG.md b/packages/cubejs-hive-driver/CHANGELOG.md index eca7db9c243e6..9fa08e1263c23 100644 --- a/packages/cubejs-hive-driver/CHANGELOG.md +++ b/packages/cubejs-hive-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/hive-driver + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/hive-driver diff --git a/packages/cubejs-hive-driver/package.json b/packages/cubejs-hive-driver/package.json index ef57625d4cd12..2cd6d7c97c514 100644 --- a/packages/cubejs-hive-driver/package.json +++ b/packages/cubejs-hive-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/hive-driver", "description": "Cube.js Hive database driver", "author": "Cube Dev, Inc.", - "version": "1.1.8", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -17,8 +17,8 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "generic-pool": "^3.6.0", "jshs2": "^0.4.4", "sasl-plain": "^0.1.0", diff --git a/packages/cubejs-jdbc-driver/CHANGELOG.md b/packages/cubejs-jdbc-driver/CHANGELOG.md index ac425025ba23a..52b1a09af4b1e 100644 --- a/packages/cubejs-jdbc-driver/CHANGELOG.md +++ b/packages/cubejs-jdbc-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/jdbc-driver + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/jdbc-driver diff --git a/packages/cubejs-jdbc-driver/package.json b/packages/cubejs-jdbc-driver/package.json index 5ae02b73e69a4..cacd185c1645a 100644 --- a/packages/cubejs-jdbc-driver/package.json +++ b/packages/cubejs-jdbc-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/jdbc-driver", "description": "Cube.js JDBC database driver", "author": "Cube Dev, Inc.", - "version": "1.1.8", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -25,8 +25,8 @@ "index.js" ], "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "generic-pool": "^3.1.7", "node-java-maven": "^0.1.2", "sqlstring": "^2.3.0" diff --git a/packages/cubejs-ksql-driver/CHANGELOG.md b/packages/cubejs-ksql-driver/CHANGELOG.md index 28ed8152e0af4..b4812ec2dcf20 100644 --- a/packages/cubejs-ksql-driver/CHANGELOG.md +++ b/packages/cubejs-ksql-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/ksql-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) diff --git a/packages/cubejs-ksql-driver/package.json b/packages/cubejs-ksql-driver/package.json index 7c077cea390c0..b2bb0ff886a16 100644 --- a/packages/cubejs-ksql-driver/package.json +++ b/packages/cubejs-ksql-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/ksql-driver", "description": "Cube.js ksql database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -25,9 +25,9 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/schema-compiler": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "async-mutex": "0.3.2", "axios": "^0.21.1", "kafkajs": "^2.2.3", diff --git a/packages/cubejs-materialize-driver/CHANGELOG.md b/packages/cubejs-materialize-driver/CHANGELOG.md index 41977594f2e27..5b0f1d01f8662 100644 --- a/packages/cubejs-materialize-driver/CHANGELOG.md +++ b/packages/cubejs-materialize-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/materialize-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/materialize-driver diff --git a/packages/cubejs-materialize-driver/package.json b/packages/cubejs-materialize-driver/package.json index 91f4016ff79fb..4ec13ce8386f6 100644 --- a/packages/cubejs-materialize-driver/package.json +++ b/packages/cubejs-materialize-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/materialize-driver", "description": "Cube.js Materialize database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -27,9 +27,9 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/postgres-driver": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/postgres-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "@types/pg": "^8.6.0", "pg": "^8.6.0", "semver": "7.3.7" @@ -37,7 +37,7 @@ "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing": "1.1.9", + "@cubejs-backend/testing": "1.1.10", "typescript": "~5.2.2" }, "publishConfig": { diff --git a/packages/cubejs-mongobi-driver/CHANGELOG.md b/packages/cubejs-mongobi-driver/CHANGELOG.md index 20561cc5385ad..47e69f52cb274 100644 --- a/packages/cubejs-mongobi-driver/CHANGELOG.md +++ b/packages/cubejs-mongobi-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/mongobi-driver + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/mongobi-driver diff --git a/packages/cubejs-mongobi-driver/package.json b/packages/cubejs-mongobi-driver/package.json index 30cae5ca6d87f..5af7545c022ea 100644 --- a/packages/cubejs-mongobi-driver/package.json +++ b/packages/cubejs-mongobi-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/mongobi-driver", "description": "Cube.js MongoBI driver", "author": "krunalsabnis@gmail.com", - "version": "1.1.8", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -27,8 +27,8 @@ "integration:mongobi": "jest dist/test" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "@types/node": "^18", "generic-pool": "^3.6.0", "moment": "^2.29.1", diff --git a/packages/cubejs-mssql-driver/CHANGELOG.md b/packages/cubejs-mssql-driver/CHANGELOG.md index 15a6d97e78cbe..fabfdb085120e 100644 --- a/packages/cubejs-mssql-driver/CHANGELOG.md +++ b/packages/cubejs-mssql-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/mssql-driver + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/mssql-driver diff --git a/packages/cubejs-mssql-driver/package.json b/packages/cubejs-mssql-driver/package.json index 66743991812be..37829f9b938db 100644 --- a/packages/cubejs-mssql-driver/package.json +++ b/packages/cubejs-mssql-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/mssql-driver", "description": "Cube.js MS SQL database driver", "author": "Cube Dev, Inc.", - "version": "1.1.8", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -13,7 +13,7 @@ }, "main": "driver/MSSqlDriver.js", "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", "mssql": "^10.0.2" }, "devDependencies": { diff --git a/packages/cubejs-mysql-aurora-serverless-driver/CHANGELOG.md b/packages/cubejs-mysql-aurora-serverless-driver/CHANGELOG.md index 2d4fe95f4ad98..823631edefad3 100644 --- a/packages/cubejs-mysql-aurora-serverless-driver/CHANGELOG.md +++ b/packages/cubejs-mysql-aurora-serverless-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/mysql-aurora-serverless-driver + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/mysql-aurora-serverless-driver diff --git a/packages/cubejs-mysql-aurora-serverless-driver/package.json b/packages/cubejs-mysql-aurora-serverless-driver/package.json index ffdbdb5b75f71..675cf8d18f6ea 100644 --- a/packages/cubejs-mysql-aurora-serverless-driver/package.json +++ b/packages/cubejs-mysql-aurora-serverless-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/mysql-aurora-serverless-driver", "description": "Cube.js Aurora Serverless Mysql database driver", "author": "Cube Dev, Inc.", - "version": "1.1.8", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -21,8 +21,8 @@ "lint": "eslint driver/*.js test/*.js" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "@types/mysql": "^2.15.15", "aws-sdk": "^2.787.0", "data-api-client": "^1.1.0" diff --git a/packages/cubejs-mysql-driver/CHANGELOG.md b/packages/cubejs-mysql-driver/CHANGELOG.md index ce093197da443..ca8436028c3f9 100644 --- a/packages/cubejs-mysql-driver/CHANGELOG.md +++ b/packages/cubejs-mysql-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/mysql-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/mysql-driver diff --git a/packages/cubejs-mysql-driver/package.json b/packages/cubejs-mysql-driver/package.json index 4e18691eac0e3..f7211cf12768c 100644 --- a/packages/cubejs-mysql-driver/package.json +++ b/packages/cubejs-mysql-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/mysql-driver", "description": "Cube.js Mysql database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -27,15 +27,15 @@ "lint:fix": "eslint --fix src/* test/* --ext .ts,.js" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "@types/mysql": "^2.15.21", "generic-pool": "^3.6.0", "mysql": "^2.18.1" }, "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.9", + "@cubejs-backend/testing-shared": "1.1.10", "@types/generic-pool": "^3.1.9", "@types/jest": "^27", "jest": "^27", diff --git a/packages/cubejs-oracle-driver/CHANGELOG.md b/packages/cubejs-oracle-driver/CHANGELOG.md index 36601518d74d3..94d65da829475 100644 --- a/packages/cubejs-oracle-driver/CHANGELOG.md +++ b/packages/cubejs-oracle-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/oracle-driver + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/oracle-driver diff --git a/packages/cubejs-oracle-driver/package.json b/packages/cubejs-oracle-driver/package.json index 252d234587d7d..685f22b0e6c77 100644 --- a/packages/cubejs-oracle-driver/package.json +++ b/packages/cubejs-oracle-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/oracle-driver", "description": "Cube.js oracle database driver", "author": "Cube Dev, Inc.", - "version": "1.1.8", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -13,7 +13,7 @@ }, "main": "driver/OracleDriver.js", "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", "ramda": "^0.27.0" }, "optionalDependencies": { diff --git a/packages/cubejs-pinot-driver/CHANGELOG.md b/packages/cubejs-pinot-driver/CHANGELOG.md index cfb3ad3639b6f..317b584fdf68e 100644 --- a/packages/cubejs-pinot-driver/CHANGELOG.md +++ b/packages/cubejs-pinot-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/pinot-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/pinot-driver diff --git a/packages/cubejs-pinot-driver/package.json b/packages/cubejs-pinot-driver/package.json index dbd920316d37f..3dcbe457f62e7 100644 --- a/packages/cubejs-pinot-driver/package.json +++ b/packages/cubejs-pinot-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/pinot-driver", "description": "Cube.js Pinot database driver", "author": "Julian Ronsse, InTheMemory, Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -27,9 +27,9 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/schema-compiler": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "node-fetch": "^2.6.1", "ramda": "^0.27.2", "sqlstring": "^2.3.3" diff --git a/packages/cubejs-postgres-driver/CHANGELOG.md b/packages/cubejs-postgres-driver/CHANGELOG.md index b0247045dd526..e11285b675523 100644 --- a/packages/cubejs-postgres-driver/CHANGELOG.md +++ b/packages/cubejs-postgres-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/postgres-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/postgres-driver diff --git a/packages/cubejs-postgres-driver/package.json b/packages/cubejs-postgres-driver/package.json index 6b885e1da4034..6c76a7d6fc2a5 100644 --- a/packages/cubejs-postgres-driver/package.json +++ b/packages/cubejs-postgres-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/postgres-driver", "description": "Cube.js Postgres database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -27,8 +27,8 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "@types/pg": "^8.6.0", "@types/pg-query-stream": "^1.0.3", "moment": "^2.24.0", @@ -38,7 +38,7 @@ "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.9", + "@cubejs-backend/testing-shared": "1.1.10", "testcontainers": "^10.10.4", "typescript": "~5.2.2" }, diff --git a/packages/cubejs-prestodb-driver/CHANGELOG.md b/packages/cubejs-prestodb-driver/CHANGELOG.md index 7bc63f78c99c3..6c9bdca315edc 100644 --- a/packages/cubejs-prestodb-driver/CHANGELOG.md +++ b/packages/cubejs-prestodb-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/prestodb-driver + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/prestodb-driver diff --git a/packages/cubejs-prestodb-driver/package.json b/packages/cubejs-prestodb-driver/package.json index e4401f9d31695..ce39c65cd9e16 100644 --- a/packages/cubejs-prestodb-driver/package.json +++ b/packages/cubejs-prestodb-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/prestodb-driver", "description": "Cube.js Presto database driver", "author": "Cube Dev, Inc.", - "version": "1.1.8", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -27,8 +27,8 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "presto-client": "^0.12.2", "ramda": "^0.27.0", "sqlstring": "^2.3.1" diff --git a/packages/cubejs-query-orchestrator/CHANGELOG.md b/packages/cubejs-query-orchestrator/CHANGELOG.md index 02c60895258bd..1d96d41120c63 100644 --- a/packages/cubejs-query-orchestrator/CHANGELOG.md +++ b/packages/cubejs-query-orchestrator/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/query-orchestrator + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/query-orchestrator diff --git a/packages/cubejs-query-orchestrator/package.json b/packages/cubejs-query-orchestrator/package.json index 7f7a9ef14e099..bfc6c1a478554 100644 --- a/packages/cubejs-query-orchestrator/package.json +++ b/packages/cubejs-query-orchestrator/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/query-orchestrator", "description": "Cube.js Query Orchestrator and Cache", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -29,9 +29,9 @@ "dist/src/*" ], "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/cubestore-driver": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/cubestore-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "csv-write-stream": "^2.0.0", "es5-ext": "0.10.53", "generic-pool": "^3.7.1", diff --git a/packages/cubejs-questdb-driver/CHANGELOG.md b/packages/cubejs-questdb-driver/CHANGELOG.md index 1448c179c8d31..8352c554fc18c 100644 --- a/packages/cubejs-questdb-driver/CHANGELOG.md +++ b/packages/cubejs-questdb-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/questdb-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/questdb-driver diff --git a/packages/cubejs-questdb-driver/package.json b/packages/cubejs-questdb-driver/package.json index b7123c748772c..efdc5df861b94 100644 --- a/packages/cubejs-questdb-driver/package.json +++ b/packages/cubejs-questdb-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/questdb-driver", "description": "Cube.js QuestDB database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -27,9 +27,9 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/schema-compiler": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "@types/pg": "^8.6.0", "moment": "^2.24.0", "pg": "^8.7.0", @@ -38,7 +38,7 @@ "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.9", + "@cubejs-backend/testing-shared": "1.1.10", "testcontainers": "^10.10.4", "typescript": "~5.2.2" }, diff --git a/packages/cubejs-redshift-driver/CHANGELOG.md b/packages/cubejs-redshift-driver/CHANGELOG.md index ceca6e4d841f1..795eb640a097d 100644 --- a/packages/cubejs-redshift-driver/CHANGELOG.md +++ b/packages/cubejs-redshift-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/redshift-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/redshift-driver diff --git a/packages/cubejs-redshift-driver/package.json b/packages/cubejs-redshift-driver/package.json index 76a6395634baa..4b3be1e903047 100644 --- a/packages/cubejs-redshift-driver/package.json +++ b/packages/cubejs-redshift-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/redshift-driver", "description": "Cube.js Redshift database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -25,9 +25,9 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/postgres-driver": "1.1.9", - "@cubejs-backend/shared": "1.1.8" + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/postgres-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10" }, "license": "Apache-2.0", "devDependencies": { diff --git a/packages/cubejs-schema-compiler/CHANGELOG.md b/packages/cubejs-schema-compiler/CHANGELOG.md index a0e54cfe1cc0f..d37095475c607 100644 --- a/packages/cubejs-schema-compiler/CHANGELOG.md +++ b/packages/cubejs-schema-compiler/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + + +### Bug Fixes + +* **schema-compiler:** join relationship aliases ([ad4e8e3](https://github.com/cube-js/cube/commit/ad4e8e3872307ab77e035709e5208b0191f87f5b)) + + +### Features + +* **tesseract:** Support multiple join paths within single query ([#9047](https://github.com/cube-js/cube/issues/9047)) ([b62446e](https://github.com/cube-js/cube/commit/b62446e3c3893068f8dd8aa32d7204ea06a16f98)) + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) diff --git a/packages/cubejs-schema-compiler/package.json b/packages/cubejs-schema-compiler/package.json index c1b2fb99eaa3b..62be9dbfc97a3 100644 --- a/packages/cubejs-schema-compiler/package.json +++ b/packages/cubejs-schema-compiler/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/schema-compiler", "description": "Cube schema compiler", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -40,8 +40,8 @@ "@babel/standalone": "^7.24", "@babel/traverse": "^7.24", "@babel/types": "^7.24", - "@cubejs-backend/native": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/native": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "antlr4ts": "0.5.0-alpha.4", "camelcase": "^6.2.0", "cron-parser": "^4.9.0", @@ -59,7 +59,7 @@ "devDependencies": { "@clickhouse/client": "^1.7.0", "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/query-orchestrator": "1.1.9", + "@cubejs-backend/query-orchestrator": "1.1.10", "@types/babel__code-frame": "^7.0.6", "@types/babel__generator": "^7.6.8", "@types/babel__traverse": "^7.20.5", diff --git a/packages/cubejs-server-core/CHANGELOG.md b/packages/cubejs-server-core/CHANGELOG.md index 881eb4d9f1208..461556f8d1b5c 100644 --- a/packages/cubejs-server-core/CHANGELOG.md +++ b/packages/cubejs-server-core/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + + +### Bug Fixes + +* **schema-compiler:** fix DAP with query_rewrite and python config ([#9033](https://github.com/cube-js/cube/issues/9033)) ([849790f](https://github.com/cube-js/cube/commit/849790f965dd0d9fddba11e3d8d124b84397ca9b)) + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) diff --git a/packages/cubejs-server-core/package.json b/packages/cubejs-server-core/package.json index 8957d4c212293..9516b410bd997 100644 --- a/packages/cubejs-server-core/package.json +++ b/packages/cubejs-server-core/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/server-core", "description": "Cube.js base component to wire all backend components together", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -29,14 +29,14 @@ "unit": "jest --runInBand --forceExit --coverage dist/test" }, "dependencies": { - "@cubejs-backend/api-gateway": "1.1.9", - "@cubejs-backend/cloud": "1.1.8", + "@cubejs-backend/api-gateway": "1.1.10", + "@cubejs-backend/cloud": "1.1.10", "@cubejs-backend/dotenv": "^9.0.2", - "@cubejs-backend/native": "1.1.9", - "@cubejs-backend/query-orchestrator": "1.1.9", - "@cubejs-backend/schema-compiler": "1.1.9", - "@cubejs-backend/shared": "1.1.8", - "@cubejs-backend/templates": "1.1.8", + "@cubejs-backend/native": "1.1.10", + "@cubejs-backend/query-orchestrator": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/shared": "1.1.10", + "@cubejs-backend/templates": "1.1.10", "codesandbox-import-utils": "^2.1.12", "cross-spawn": "^7.0.1", "fs-extra": "^8.1.0", @@ -57,7 +57,7 @@ "ws": "^7.5.3" }, "devDependencies": { - "@cubejs-backend/cubestore-driver": "1.1.9", + "@cubejs-backend/cubestore-driver": "1.1.10", "@cubejs-backend/linter": "^1.0.0", "@cubejs-client/playground": "1.1.6", "@types/cross-spawn": "^6.0.2", diff --git a/packages/cubejs-server/CHANGELOG.md b/packages/cubejs-server/CHANGELOG.md index 60921b5994126..3d21f81a81ce2 100644 --- a/packages/cubejs-server/CHANGELOG.md +++ b/packages/cubejs-server/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/server + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/server diff --git a/packages/cubejs-server/package.json b/packages/cubejs-server/package.json index 608f40b384dc1..5307af3cc277c 100644 --- a/packages/cubejs-server/package.json +++ b/packages/cubejs-server/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/server", "description": "Cube.js all-in-one server", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "types": "index.d.ts", "repository": { "type": "git", @@ -40,11 +40,11 @@ "jest:shapshot": "jest --updateSnapshot test" }, "dependencies": { - "@cubejs-backend/cubestore-driver": "1.1.9", + "@cubejs-backend/cubestore-driver": "1.1.10", "@cubejs-backend/dotenv": "^9.0.2", - "@cubejs-backend/native": "1.1.9", - "@cubejs-backend/server-core": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/native": "1.1.10", + "@cubejs-backend/server-core": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "@oclif/color": "^1.0.0", "@oclif/command": "^1.8.13", "@oclif/config": "^1.18.2", @@ -62,7 +62,7 @@ }, "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/query-orchestrator": "1.1.9", + "@cubejs-backend/query-orchestrator": "1.1.10", "@oclif/dev-cli": "^1.23.1", "@types/body-parser": "^1.19.0", "@types/cors": "^2.8.8", diff --git a/packages/cubejs-snowflake-driver/CHANGELOG.md b/packages/cubejs-snowflake-driver/CHANGELOG.md index ff2db4cb1ebe6..a89efed2e1547 100644 --- a/packages/cubejs-snowflake-driver/CHANGELOG.md +++ b/packages/cubejs-snowflake-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/snowflake-driver + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/snowflake-driver diff --git a/packages/cubejs-snowflake-driver/package.json b/packages/cubejs-snowflake-driver/package.json index f8715e6ced8ad..d5df1dc3b26d0 100644 --- a/packages/cubejs-snowflake-driver/package.json +++ b/packages/cubejs-snowflake-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/snowflake-driver", "description": "Cube.js Snowflake database driver", "author": "Cube Dev, Inc.", - "version": "1.1.8", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -25,8 +25,8 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "date-fns-timezone": "^0.1.4", "snowflake-sdk": "^1.13.1" }, diff --git a/packages/cubejs-sqlite-driver/CHANGELOG.md b/packages/cubejs-sqlite-driver/CHANGELOG.md index dab1919e98f43..e30523bc8b266 100644 --- a/packages/cubejs-sqlite-driver/CHANGELOG.md +++ b/packages/cubejs-sqlite-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/sqlite-driver + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/sqlite-driver diff --git a/packages/cubejs-sqlite-driver/package.json b/packages/cubejs-sqlite-driver/package.json index d5fba86fd4a7d..4cb62865e8c83 100644 --- a/packages/cubejs-sqlite-driver/package.json +++ b/packages/cubejs-sqlite-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/sqlite-driver", "description": "Cube.js Sqlite database driver", "author": "Cube Dev, Inc.", - "version": "1.1.8", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -17,8 +17,8 @@ "lint": "eslint **/*.js" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "sqlite3": "^5.1.7" }, "license": "Apache-2.0", diff --git a/packages/cubejs-templates/CHANGELOG.md b/packages/cubejs-templates/CHANGELOG.md index 2e7b5867db120..1b6fe5d6f34f8 100644 --- a/packages/cubejs-templates/CHANGELOG.md +++ b/packages/cubejs-templates/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/templates + + + + + ## [1.1.8](https://github.com/cube-js/cube/compare/v1.1.7...v1.1.8) (2024-12-05) **Note:** Version bump only for package @cubejs-backend/templates diff --git a/packages/cubejs-templates/package.json b/packages/cubejs-templates/package.json index e6e7c8bd4b8f4..4475d1991bbc6 100644 --- a/packages/cubejs-templates/package.json +++ b/packages/cubejs-templates/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/templates", - "version": "1.1.8", + "version": "1.1.10", "description": "Cube.js Templates helpers", "author": "Cube Dev, Inc.", "license": "Apache-2.0", @@ -26,7 +26,7 @@ "extends": "../cubejs-linter" }, "dependencies": { - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/shared": "1.1.10", "cross-spawn": "^7.0.3", "decompress": "^4.2.1", "decompress-targz": "^4.1.1", diff --git a/packages/cubejs-testing-drivers/CHANGELOG.md b/packages/cubejs-testing-drivers/CHANGELOG.md index 0657f5f25c5e6..739c3d7297a53 100644 --- a/packages/cubejs-testing-drivers/CHANGELOG.md +++ b/packages/cubejs-testing-drivers/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/testing-drivers + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/testing-drivers diff --git a/packages/cubejs-testing-drivers/package.json b/packages/cubejs-testing-drivers/package.json index 1c7e73de9dd05..4565d23089c2c 100644 --- a/packages/cubejs-testing-drivers/package.json +++ b/packages/cubejs-testing-drivers/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/testing-drivers", - "version": "1.1.9", + "version": "1.1.10", "description": "Cube.js drivers test suite", "author": "Cube Dev, Inc.", "license": "MIT", @@ -56,22 +56,22 @@ "dist/src" ], "dependencies": { - "@cubejs-backend/athena-driver": "1.1.9", - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/bigquery-driver": "1.1.9", - "@cubejs-backend/clickhouse-driver": "1.1.9", - "@cubejs-backend/cubestore-driver": "1.1.9", - "@cubejs-backend/databricks-jdbc-driver": "1.1.9", + "@cubejs-backend/athena-driver": "1.1.10", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/bigquery-driver": "1.1.10", + "@cubejs-backend/clickhouse-driver": "1.1.10", + "@cubejs-backend/cubestore-driver": "1.1.10", + "@cubejs-backend/databricks-jdbc-driver": "1.1.10", "@cubejs-backend/dotenv": "^9.0.2", "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/mssql-driver": "1.1.8", - "@cubejs-backend/mysql-driver": "1.1.9", - "@cubejs-backend/postgres-driver": "1.1.9", - "@cubejs-backend/query-orchestrator": "1.1.9", - "@cubejs-backend/server-core": "1.1.9", - "@cubejs-backend/shared": "1.1.8", - "@cubejs-backend/snowflake-driver": "1.1.8", - "@cubejs-backend/testing-shared": "1.1.9", + "@cubejs-backend/mssql-driver": "1.1.10", + "@cubejs-backend/mysql-driver": "1.1.10", + "@cubejs-backend/postgres-driver": "1.1.10", + "@cubejs-backend/query-orchestrator": "1.1.10", + "@cubejs-backend/server-core": "1.1.10", + "@cubejs-backend/shared": "1.1.10", + "@cubejs-backend/snowflake-driver": "1.1.10", + "@cubejs-backend/testing-shared": "1.1.10", "@cubejs-client/core": "^1.0.0", "@cubejs-client/ws-transport": "^1.0.0", "@jest/globals": "^27", diff --git a/packages/cubejs-testing-shared/CHANGELOG.md b/packages/cubejs-testing-shared/CHANGELOG.md index 4b8b514c8aa23..092c1de792be3 100644 --- a/packages/cubejs-testing-shared/CHANGELOG.md +++ b/packages/cubejs-testing-shared/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/testing-shared + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/testing-shared diff --git a/packages/cubejs-testing-shared/package.json b/packages/cubejs-testing-shared/package.json index 78e75db990718..defff64fa79c4 100644 --- a/packages/cubejs-testing-shared/package.json +++ b/packages/cubejs-testing-shared/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/testing-shared", - "version": "1.1.9", + "version": "1.1.10", "description": "Cube.js Testing Helpers", "author": "Cube Dev, Inc.", "license": "Apache-2.0", @@ -21,9 +21,9 @@ ], "dependencies": { "@cubejs-backend/dotenv": "^9.0.2", - "@cubejs-backend/query-orchestrator": "1.1.9", - "@cubejs-backend/schema-compiler": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/query-orchestrator": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "@testcontainers/kafka": "~10.13.0", "dedent": "^0.7.0", "node-fetch": "^2.6.7", diff --git a/packages/cubejs-testing/CHANGELOG.md b/packages/cubejs-testing/CHANGELOG.md index eb5905299f73b..9586a78b449df 100644 --- a/packages/cubejs-testing/CHANGELOG.md +++ b/packages/cubejs-testing/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + + +### Bug Fixes + +* **api-gateway:** make sure DAP works sql pushdown ([#9021](https://github.com/cube-js/cube/issues/9021)) ([23695b2](https://github.com/cube-js/cube/commit/23695b2b5e886b5b7daf8b3f74003bb04e5b2e0b)) +* **schema-compiler:** fix DAP with query_rewrite and python config ([#9033](https://github.com/cube-js/cube/issues/9033)) ([849790f](https://github.com/cube-js/cube/commit/849790f965dd0d9fddba11e3d8d124b84397ca9b)) + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/testing diff --git a/packages/cubejs-testing/package.json b/packages/cubejs-testing/package.json index bfc6513c0c7a0..9abf54d8020b2 100644 --- a/packages/cubejs-testing/package.json +++ b/packages/cubejs-testing/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/testing", - "version": "1.1.9", + "version": "1.1.10", "description": "Cube.js e2e tests", "author": "Cube Dev, Inc.", "license": "Apache-2.0", @@ -90,14 +90,14 @@ "birdbox-fixtures" ], "dependencies": { - "@cubejs-backend/cubestore-driver": "1.1.9", + "@cubejs-backend/cubestore-driver": "1.1.10", "@cubejs-backend/dotenv": "^9.0.2", - "@cubejs-backend/ksql-driver": "1.1.9", - "@cubejs-backend/postgres-driver": "1.1.9", - "@cubejs-backend/query-orchestrator": "1.1.9", - "@cubejs-backend/schema-compiler": "1.1.9", - "@cubejs-backend/shared": "1.1.8", - "@cubejs-backend/testing-shared": "1.1.9", + "@cubejs-backend/ksql-driver": "1.1.10", + "@cubejs-backend/postgres-driver": "1.1.10", + "@cubejs-backend/query-orchestrator": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/shared": "1.1.10", + "@cubejs-backend/testing-shared": "1.1.10", "@cubejs-client/ws-transport": "^1.0.0", "dedent": "^0.7.0", "fs-extra": "^8.1.0", diff --git a/packages/cubejs-trino-driver/CHANGELOG.md b/packages/cubejs-trino-driver/CHANGELOG.md index 8ff94e0b3c44b..dbc20f5fe0815 100644 --- a/packages/cubejs-trino-driver/CHANGELOG.md +++ b/packages/cubejs-trino-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/trino-driver + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/trino-driver diff --git a/packages/cubejs-trino-driver/package.json b/packages/cubejs-trino-driver/package.json index 3fe1b6075ff83..a38f17c163d0a 100644 --- a/packages/cubejs-trino-driver/package.json +++ b/packages/cubejs-trino-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/trino-driver", "description": "Cube.js Trino database driver", "author": "Cube Dev, Inc.", - "version": "1.1.9", + "version": "1.1.10", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -25,10 +25,10 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/base-driver": "1.1.8", - "@cubejs-backend/prestodb-driver": "1.1.8", - "@cubejs-backend/schema-compiler": "1.1.9", - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/base-driver": "1.1.10", + "@cubejs-backend/prestodb-driver": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/shared": "1.1.10", "presto-client": "^0.12.2", "sqlstring": "^2.3.1" }, diff --git a/rust/cubesql/CHANGELOG.md b/rust/cubesql/CHANGELOG.md index 65262c79701e9..a3330116ebda5 100644 --- a/rust/cubesql/CHANGELOG.md +++ b/rust/cubesql/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + + +### Features + +* **cubesql:** Basic VALUES support in rewrite engine ([#9041](https://github.com/cube-js/cube/issues/9041)) ([368671f](https://github.com/cube-js/cube/commit/368671fd1b53b2ed5ad8df6af113492982f23c0c)) + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) diff --git a/rust/cubesql/package.json b/rust/cubesql/package.json index c12ce50e9d2cd..b9fe2739a1c76 100644 --- a/rust/cubesql/package.json +++ b/rust/cubesql/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/cubesql", - "version": "1.1.9", + "version": "1.1.10", "description": "SQL API for Cube as proxy over MySQL protocol.", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" diff --git a/rust/cubestore/CHANGELOG.md b/rust/cubestore/CHANGELOG.md index 69df8e7680a25..4b02e559be11f 100644 --- a/rust/cubestore/CHANGELOG.md +++ b/rust/cubestore/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) + + +### Bug Fixes + +* **cubestore:** Allow create an index from expressions ([#9006](https://github.com/cube-js/cube/issues/9006)) ([222cab8](https://github.com/cube-js/cube/commit/222cab897c289bfc929f217483e4905204bac12f)) + + + + + ## [1.1.9](https://github.com/cube-js/cube/compare/v1.1.8...v1.1.9) (2024-12-08) **Note:** Version bump only for package @cubejs-backend/cubestore diff --git a/rust/cubestore/package.json b/rust/cubestore/package.json index e8533eb588784..bf031fd75b9d1 100644 --- a/rust/cubestore/package.json +++ b/rust/cubestore/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/cubestore", - "version": "1.1.9", + "version": "1.1.10", "description": "Cube.js pre-aggregation storage layer.", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", @@ -37,7 +37,7 @@ "access": "public" }, "dependencies": { - "@cubejs-backend/shared": "1.1.8", + "@cubejs-backend/shared": "1.1.10", "@octokit/core": "^3.2.5", "source-map-support": "^0.5.19" }, From 14adaebdd1c3d398bcd2997012da070999e47d9d Mon Sep 17 00:00:00 2001 From: Pavel Tiunov Date: Sun, 15 Dec 2024 20:29:05 -0800 Subject: [PATCH 20/21] fix: TypeError: Cannot read properties of undefined (reading 'joins') --- .../cubejs-schema-compiler/src/adapter/PreAggregations.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/cubejs-schema-compiler/src/adapter/PreAggregations.js b/packages/cubejs-schema-compiler/src/adapter/PreAggregations.js index 5e15e22ca5dea..efc642af9d727 100644 --- a/packages/cubejs-schema-compiler/src/adapter/PreAggregations.js +++ b/packages/cubejs-schema-compiler/src/adapter/PreAggregations.js @@ -1,5 +1,5 @@ import R from 'ramda'; -import { FROM_PARTITION_RANGE, TO_PARTITION_RANGE } from '@cubejs-backend/shared'; +import { FROM_PARTITION_RANGE, getEnv, TO_PARTITION_RANGE } from '@cubejs-backend/shared'; import { UserError } from '../compiler/UserError'; @@ -57,6 +57,10 @@ export class PreAggregations { } preAggregationCubes() { + if (getEnv('nativeSqlPlanner')) { + // No join defined in Tesseract + return []; + } const { join } = this.query; return join.joins.map(j => j.originalTo).concat([join.root]); } From b8afc8466fabcd50e95aad595675aa505ff48293 Mon Sep 17 00:00:00 2001 From: Pavel Tiunov Date: Sun, 15 Dec 2024 22:35:29 -0800 Subject: [PATCH 21/21] v1.1.11 --- CHANGELOG.md | 11 +++++ lerna.json | 2 +- packages/cubejs-athena-driver/CHANGELOG.md | 8 ++++ packages/cubejs-athena-driver/package.json | 4 +- packages/cubejs-bigquery-driver/CHANGELOG.md | 8 ++++ packages/cubejs-bigquery-driver/package.json | 4 +- packages/cubejs-cli/CHANGELOG.md | 8 ++++ packages/cubejs-cli/package.json | 6 +-- .../cubejs-clickhouse-driver/CHANGELOG.md | 8 ++++ .../cubejs-clickhouse-driver/package.json | 4 +- packages/cubejs-crate-driver/CHANGELOG.md | 8 ++++ packages/cubejs-crate-driver/package.json | 6 +-- .../CHANGELOG.md | 8 ++++ .../package.json | 4 +- .../cubejs-dbt-schema-extension/CHANGELOG.md | 8 ++++ .../cubejs-dbt-schema-extension/package.json | 6 +-- packages/cubejs-docker/CHANGELOG.md | 8 ++++ packages/cubejs-docker/package.json | 42 +++++++++---------- packages/cubejs-dremio-driver/CHANGELOG.md | 8 ++++ packages/cubejs-dremio-driver/package.json | 4 +- packages/cubejs-druid-driver/CHANGELOG.md | 8 ++++ packages/cubejs-druid-driver/package.json | 4 +- packages/cubejs-duckdb-driver/CHANGELOG.md | 8 ++++ packages/cubejs-duckdb-driver/package.json | 6 +-- packages/cubejs-firebolt-driver/CHANGELOG.md | 8 ++++ packages/cubejs-firebolt-driver/package.json | 6 +-- packages/cubejs-ksql-driver/CHANGELOG.md | 8 ++++ packages/cubejs-ksql-driver/package.json | 4 +- .../cubejs-materialize-driver/CHANGELOG.md | 8 ++++ .../cubejs-materialize-driver/package.json | 6 +-- packages/cubejs-mysql-driver/CHANGELOG.md | 8 ++++ packages/cubejs-mysql-driver/package.json | 4 +- packages/cubejs-pinot-driver/CHANGELOG.md | 8 ++++ packages/cubejs-pinot-driver/package.json | 4 +- packages/cubejs-postgres-driver/CHANGELOG.md | 8 ++++ packages/cubejs-postgres-driver/package.json | 4 +- packages/cubejs-questdb-driver/CHANGELOG.md | 8 ++++ packages/cubejs-questdb-driver/package.json | 6 +-- packages/cubejs-redshift-driver/CHANGELOG.md | 8 ++++ packages/cubejs-redshift-driver/package.json | 4 +- packages/cubejs-schema-compiler/CHANGELOG.md | 11 +++++ packages/cubejs-schema-compiler/package.json | 2 +- packages/cubejs-server-core/CHANGELOG.md | 8 ++++ packages/cubejs-server-core/package.json | 4 +- packages/cubejs-server/CHANGELOG.md | 8 ++++ packages/cubejs-server/package.json | 4 +- packages/cubejs-testing-drivers/CHANGELOG.md | 8 ++++ packages/cubejs-testing-drivers/package.json | 18 ++++---- packages/cubejs-testing-shared/CHANGELOG.md | 8 ++++ packages/cubejs-testing-shared/package.json | 4 +- packages/cubejs-testing/CHANGELOG.md | 8 ++++ packages/cubejs-testing/package.json | 10 ++--- packages/cubejs-trino-driver/CHANGELOG.md | 8 ++++ packages/cubejs-trino-driver/package.json | 4 +- 54 files changed, 310 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7300879c72781..08c9caddec2a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + + +### Bug Fixes + +* TypeError: Cannot read properties of undefined (reading 'joins') ([14adaeb](https://github.com/cube-js/cube/commit/14adaebdd1c3d398bcd2997012da070999e47d9d)) + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) diff --git a/lerna.json b/lerna.json index 35f7698b421c9..1cc3b55e1971a 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.1.10", + "version": "1.1.11", "npmClient": "yarn", "useWorkspaces": true, "packages": [ diff --git a/packages/cubejs-athena-driver/CHANGELOG.md b/packages/cubejs-athena-driver/CHANGELOG.md index 4b41e7ee955de..999a08186483f 100644 --- a/packages/cubejs-athena-driver/CHANGELOG.md +++ b/packages/cubejs-athena-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/athena-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/athena-driver diff --git a/packages/cubejs-athena-driver/package.json b/packages/cubejs-athena-driver/package.json index 87c0f532fecab..ad11a01eb45e7 100644 --- a/packages/cubejs-athena-driver/package.json +++ b/packages/cubejs-athena-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/athena-driver", "description": "Cube.js Athena database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -35,7 +35,7 @@ }, "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.10", + "@cubejs-backend/testing-shared": "1.1.11", "@types/ramda": "^0.27.40", "typescript": "~5.2.2" }, diff --git a/packages/cubejs-bigquery-driver/CHANGELOG.md b/packages/cubejs-bigquery-driver/CHANGELOG.md index 22130088affac..9f82f514ecc1e 100644 --- a/packages/cubejs-bigquery-driver/CHANGELOG.md +++ b/packages/cubejs-bigquery-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/bigquery-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/bigquery-driver diff --git a/packages/cubejs-bigquery-driver/package.json b/packages/cubejs-bigquery-driver/package.json index f5fbadd2d2f17..38db27f243b2d 100644 --- a/packages/cubejs-bigquery-driver/package.json +++ b/packages/cubejs-bigquery-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/bigquery-driver", "description": "Cube.js BigQuery database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -36,7 +36,7 @@ "ramda": "^0.27.2" }, "devDependencies": { - "@cubejs-backend/testing-shared": "1.1.10", + "@cubejs-backend/testing-shared": "1.1.11", "@types/big.js": "^6.2.2", "@types/dedent": "^0.7.0", "@types/jest": "^27", diff --git a/packages/cubejs-cli/CHANGELOG.md b/packages/cubejs-cli/CHANGELOG.md index 84be1e92ae039..c0600ebb66829 100644 --- a/packages/cubejs-cli/CHANGELOG.md +++ b/packages/cubejs-cli/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package cubejs-cli + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package cubejs-cli diff --git a/packages/cubejs-cli/package.json b/packages/cubejs-cli/package.json index 0185fb7cef8ae..bfef4edfc1ba9 100644 --- a/packages/cubejs-cli/package.json +++ b/packages/cubejs-cli/package.json @@ -2,7 +2,7 @@ "name": "cubejs-cli", "description": "Cube.js Command Line Interface", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -31,7 +31,7 @@ ], "dependencies": { "@cubejs-backend/dotenv": "^9.0.2", - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "@cubejs-backend/shared": "1.1.10", "chalk": "^2.4.2", "cli-progress": "^3.10", @@ -50,7 +50,7 @@ }, "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/server": "1.1.10", + "@cubejs-backend/server": "1.1.11", "@oclif/command": "^1.8.0", "@types/cli-progress": "^3.8.0", "@types/cross-spawn": "^6.0.2", diff --git a/packages/cubejs-clickhouse-driver/CHANGELOG.md b/packages/cubejs-clickhouse-driver/CHANGELOG.md index a836f1a921a8d..a5bfb6933b9c8 100644 --- a/packages/cubejs-clickhouse-driver/CHANGELOG.md +++ b/packages/cubejs-clickhouse-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/clickhouse-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/clickhouse-driver diff --git a/packages/cubejs-clickhouse-driver/package.json b/packages/cubejs-clickhouse-driver/package.json index 081c0565b9428..613e081512963 100644 --- a/packages/cubejs-clickhouse-driver/package.json +++ b/packages/cubejs-clickhouse-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/clickhouse-driver", "description": "Cube.js ClickHouse database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -37,7 +37,7 @@ "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.10", + "@cubejs-backend/testing-shared": "1.1.11", "@types/jest": "^27", "jest": "27", "typescript": "~5.2.2" diff --git a/packages/cubejs-crate-driver/CHANGELOG.md b/packages/cubejs-crate-driver/CHANGELOG.md index 4e4b984adf040..16c6d3874c9aa 100644 --- a/packages/cubejs-crate-driver/CHANGELOG.md +++ b/packages/cubejs-crate-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/crate-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/crate-driver diff --git a/packages/cubejs-crate-driver/package.json b/packages/cubejs-crate-driver/package.json index 45c1fc5649428..966129cc8a8d5 100644 --- a/packages/cubejs-crate-driver/package.json +++ b/packages/cubejs-crate-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/crate-driver", "description": "Cube.js Crate database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -28,14 +28,14 @@ "lint:fix": "eslint --fix src/* --ext .ts" }, "dependencies": { - "@cubejs-backend/postgres-driver": "1.1.10", + "@cubejs-backend/postgres-driver": "1.1.11", "@cubejs-backend/shared": "1.1.10", "pg": "^8.7.1" }, "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.10", + "@cubejs-backend/testing-shared": "1.1.11", "testcontainers": "^10.10.4", "typescript": "~5.2.2" }, diff --git a/packages/cubejs-databricks-jdbc-driver/CHANGELOG.md b/packages/cubejs-databricks-jdbc-driver/CHANGELOG.md index b3e202f7d00ea..c53baf3e402c6 100644 --- a/packages/cubejs-databricks-jdbc-driver/CHANGELOG.md +++ b/packages/cubejs-databricks-jdbc-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/databricks-jdbc-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/databricks-jdbc-driver diff --git a/packages/cubejs-databricks-jdbc-driver/package.json b/packages/cubejs-databricks-jdbc-driver/package.json index 6b320fc9e5bbe..05e4b0560bcb4 100644 --- a/packages/cubejs-databricks-jdbc-driver/package.json +++ b/packages/cubejs-databricks-jdbc-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/databricks-jdbc-driver", "description": "Cube.js Databricks database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "license": "Apache-2.0", "repository": { "type": "git", @@ -30,7 +30,7 @@ "dependencies": { "@cubejs-backend/base-driver": "1.1.10", "@cubejs-backend/jdbc-driver": "1.1.10", - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "@cubejs-backend/shared": "1.1.10", "node-fetch": "^2.6.1", "ramda": "^0.27.2", diff --git a/packages/cubejs-dbt-schema-extension/CHANGELOG.md b/packages/cubejs-dbt-schema-extension/CHANGELOG.md index 44d5565e00f56..61640e63904ab 100644 --- a/packages/cubejs-dbt-schema-extension/CHANGELOG.md +++ b/packages/cubejs-dbt-schema-extension/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/dbt-schema-extension + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/dbt-schema-extension diff --git a/packages/cubejs-dbt-schema-extension/package.json b/packages/cubejs-dbt-schema-extension/package.json index d2df9a118b0da..a59e350eb6cb0 100644 --- a/packages/cubejs-dbt-schema-extension/package.json +++ b/packages/cubejs-dbt-schema-extension/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/dbt-schema-extension", "description": "Cube.js dbt Schema Extension", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -25,14 +25,14 @@ "lint:fix": "eslint --fix src/* --ext .ts,.js" }, "dependencies": { - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "fs-extra": "^9.1.0", "inflection": "^1.12.0", "node-fetch": "^2.6.1" }, "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing": "1.1.10", + "@cubejs-backend/testing": "1.1.11", "@types/generic-pool": "^3.1.9", "@types/jest": "^27", "jest": "^27", diff --git a/packages/cubejs-docker/CHANGELOG.md b/packages/cubejs-docker/CHANGELOG.md index 22d418b1dccd7..22b1532740212 100644 --- a/packages/cubejs-docker/CHANGELOG.md +++ b/packages/cubejs-docker/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/docker + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/docker diff --git a/packages/cubejs-docker/package.json b/packages/cubejs-docker/package.json index 266963e9fbdd2..b54a9609d7078 100644 --- a/packages/cubejs-docker/package.json +++ b/packages/cubejs-docker/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/docker", - "version": "1.1.10", + "version": "1.1.11", "description": "Cube.js In Docker (virtual package)", "author": "Cube Dev, Inc.", "license": "Apache-2.0", @@ -9,34 +9,34 @@ "node": "^14.0.0 || ^16.0.0 || >=17.0.0" }, "dependencies": { - "@cubejs-backend/athena-driver": "1.1.10", - "@cubejs-backend/bigquery-driver": "1.1.10", - "@cubejs-backend/clickhouse-driver": "1.1.10", - "@cubejs-backend/crate-driver": "1.1.10", - "@cubejs-backend/databricks-jdbc-driver": "1.1.10", - "@cubejs-backend/dbt-schema-extension": "1.1.10", - "@cubejs-backend/dremio-driver": "1.1.10", - "@cubejs-backend/druid-driver": "1.1.10", - "@cubejs-backend/duckdb-driver": "1.1.10", + "@cubejs-backend/athena-driver": "1.1.11", + "@cubejs-backend/bigquery-driver": "1.1.11", + "@cubejs-backend/clickhouse-driver": "1.1.11", + "@cubejs-backend/crate-driver": "1.1.11", + "@cubejs-backend/databricks-jdbc-driver": "1.1.11", + "@cubejs-backend/dbt-schema-extension": "1.1.11", + "@cubejs-backend/dremio-driver": "1.1.11", + "@cubejs-backend/druid-driver": "1.1.11", + "@cubejs-backend/duckdb-driver": "1.1.11", "@cubejs-backend/elasticsearch-driver": "1.1.10", - "@cubejs-backend/firebolt-driver": "1.1.10", + "@cubejs-backend/firebolt-driver": "1.1.11", "@cubejs-backend/hive-driver": "1.1.10", - "@cubejs-backend/ksql-driver": "1.1.10", - "@cubejs-backend/materialize-driver": "1.1.10", + "@cubejs-backend/ksql-driver": "1.1.11", + "@cubejs-backend/materialize-driver": "1.1.11", "@cubejs-backend/mongobi-driver": "1.1.10", "@cubejs-backend/mssql-driver": "1.1.10", - "@cubejs-backend/mysql-driver": "1.1.10", + "@cubejs-backend/mysql-driver": "1.1.11", "@cubejs-backend/oracle-driver": "1.1.10", - "@cubejs-backend/pinot-driver": "1.1.10", - "@cubejs-backend/postgres-driver": "1.1.10", + "@cubejs-backend/pinot-driver": "1.1.11", + "@cubejs-backend/postgres-driver": "1.1.11", "@cubejs-backend/prestodb-driver": "1.1.10", - "@cubejs-backend/questdb-driver": "1.1.10", - "@cubejs-backend/redshift-driver": "1.1.10", - "@cubejs-backend/server": "1.1.10", + "@cubejs-backend/questdb-driver": "1.1.11", + "@cubejs-backend/redshift-driver": "1.1.11", + "@cubejs-backend/server": "1.1.11", "@cubejs-backend/snowflake-driver": "1.1.10", "@cubejs-backend/sqlite-driver": "1.1.10", - "@cubejs-backend/trino-driver": "1.1.10", - "cubejs-cli": "1.1.10", + "@cubejs-backend/trino-driver": "1.1.11", + "cubejs-cli": "1.1.11", "typescript": "~5.2.2" }, "resolutions": { diff --git a/packages/cubejs-dremio-driver/CHANGELOG.md b/packages/cubejs-dremio-driver/CHANGELOG.md index 59bbe8f047fe2..9bfe9eae563d4 100644 --- a/packages/cubejs-dremio-driver/CHANGELOG.md +++ b/packages/cubejs-dremio-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/dremio-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) diff --git a/packages/cubejs-dremio-driver/package.json b/packages/cubejs-dremio-driver/package.json index b0517f2a1cd31..02a8cfe795200 100644 --- a/packages/cubejs-dremio-driver/package.json +++ b/packages/cubejs-dremio-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/dremio-driver", "description": "Cube.js Dremio driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -18,7 +18,7 @@ }, "dependencies": { "@cubejs-backend/base-driver": "1.1.10", - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "@cubejs-backend/shared": "1.1.10", "axios": "^0.21.1", "moment-timezone": "^0.5.31", diff --git a/packages/cubejs-druid-driver/CHANGELOG.md b/packages/cubejs-druid-driver/CHANGELOG.md index 71e27a6d599a7..60ed6c6d9d1a1 100644 --- a/packages/cubejs-druid-driver/CHANGELOG.md +++ b/packages/cubejs-druid-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/druid-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/druid-driver diff --git a/packages/cubejs-druid-driver/package.json b/packages/cubejs-druid-driver/package.json index 5f40777f18bb6..8bf93f69a6bd4 100644 --- a/packages/cubejs-druid-driver/package.json +++ b/packages/cubejs-druid-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/druid-driver", "description": "Cube.js Druid database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "license": "Apache-2.0", "repository": { "type": "git", @@ -29,7 +29,7 @@ ], "dependencies": { "@cubejs-backend/base-driver": "1.1.10", - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "@cubejs-backend/shared": "1.1.10", "axios": "^0.21.1", "moment-timezone": "^0.5.31" diff --git a/packages/cubejs-duckdb-driver/CHANGELOG.md b/packages/cubejs-duckdb-driver/CHANGELOG.md index 0dbf7760c030a..310b1dd904990 100644 --- a/packages/cubejs-duckdb-driver/CHANGELOG.md +++ b/packages/cubejs-duckdb-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/duckdb-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/duckdb-driver diff --git a/packages/cubejs-duckdb-driver/package.json b/packages/cubejs-duckdb-driver/package.json index 7ec1fd197b691..896b35c49a483 100644 --- a/packages/cubejs-duckdb-driver/package.json +++ b/packages/cubejs-duckdb-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/duckdb-driver", "description": "Cube DuckDB database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -28,14 +28,14 @@ }, "dependencies": { "@cubejs-backend/base-driver": "1.1.10", - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "@cubejs-backend/shared": "1.1.10", "duckdb": "^1.0.0" }, "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.10", + "@cubejs-backend/testing-shared": "1.1.11", "@types/jest": "^27", "@types/node": "^18", "jest": "^27", diff --git a/packages/cubejs-firebolt-driver/CHANGELOG.md b/packages/cubejs-firebolt-driver/CHANGELOG.md index 24b0611e5ba5d..57601f2ac6101 100644 --- a/packages/cubejs-firebolt-driver/CHANGELOG.md +++ b/packages/cubejs-firebolt-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/firebolt-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/firebolt-driver diff --git a/packages/cubejs-firebolt-driver/package.json b/packages/cubejs-firebolt-driver/package.json index 4f7f6cf1faa36..7cedb7132888d 100644 --- a/packages/cubejs-firebolt-driver/package.json +++ b/packages/cubejs-firebolt-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/firebolt-driver", "description": "Cube.js Firebolt database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -29,14 +29,14 @@ }, "dependencies": { "@cubejs-backend/base-driver": "1.1.10", - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "@cubejs-backend/shared": "1.1.10", "firebolt-sdk": "^1.8.0" }, "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.10", + "@cubejs-backend/testing-shared": "1.1.11", "typescript": "~5.2.2" }, "publishConfig": { diff --git a/packages/cubejs-ksql-driver/CHANGELOG.md b/packages/cubejs-ksql-driver/CHANGELOG.md index b4812ec2dcf20..608f9ed072c3d 100644 --- a/packages/cubejs-ksql-driver/CHANGELOG.md +++ b/packages/cubejs-ksql-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/ksql-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/ksql-driver diff --git a/packages/cubejs-ksql-driver/package.json b/packages/cubejs-ksql-driver/package.json index b2bb0ff886a16..6121f65895098 100644 --- a/packages/cubejs-ksql-driver/package.json +++ b/packages/cubejs-ksql-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/ksql-driver", "description": "Cube.js ksql database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -26,7 +26,7 @@ }, "dependencies": { "@cubejs-backend/base-driver": "1.1.10", - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "@cubejs-backend/shared": "1.1.10", "async-mutex": "0.3.2", "axios": "^0.21.1", diff --git a/packages/cubejs-materialize-driver/CHANGELOG.md b/packages/cubejs-materialize-driver/CHANGELOG.md index 5b0f1d01f8662..d0165352c97aa 100644 --- a/packages/cubejs-materialize-driver/CHANGELOG.md +++ b/packages/cubejs-materialize-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/materialize-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/materialize-driver diff --git a/packages/cubejs-materialize-driver/package.json b/packages/cubejs-materialize-driver/package.json index 4ec13ce8386f6..3b09d895ac612 100644 --- a/packages/cubejs-materialize-driver/package.json +++ b/packages/cubejs-materialize-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/materialize-driver", "description": "Cube.js Materialize database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -28,7 +28,7 @@ }, "dependencies": { "@cubejs-backend/base-driver": "1.1.10", - "@cubejs-backend/postgres-driver": "1.1.10", + "@cubejs-backend/postgres-driver": "1.1.11", "@cubejs-backend/shared": "1.1.10", "@types/pg": "^8.6.0", "pg": "^8.6.0", @@ -37,7 +37,7 @@ "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing": "1.1.10", + "@cubejs-backend/testing": "1.1.11", "typescript": "~5.2.2" }, "publishConfig": { diff --git a/packages/cubejs-mysql-driver/CHANGELOG.md b/packages/cubejs-mysql-driver/CHANGELOG.md index ca8436028c3f9..ee9e5a3f26784 100644 --- a/packages/cubejs-mysql-driver/CHANGELOG.md +++ b/packages/cubejs-mysql-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/mysql-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/mysql-driver diff --git a/packages/cubejs-mysql-driver/package.json b/packages/cubejs-mysql-driver/package.json index f7211cf12768c..db569dd37622a 100644 --- a/packages/cubejs-mysql-driver/package.json +++ b/packages/cubejs-mysql-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/mysql-driver", "description": "Cube.js Mysql database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -35,7 +35,7 @@ }, "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.10", + "@cubejs-backend/testing-shared": "1.1.11", "@types/generic-pool": "^3.1.9", "@types/jest": "^27", "jest": "^27", diff --git a/packages/cubejs-pinot-driver/CHANGELOG.md b/packages/cubejs-pinot-driver/CHANGELOG.md index 317b584fdf68e..0b933a30b10a9 100644 --- a/packages/cubejs-pinot-driver/CHANGELOG.md +++ b/packages/cubejs-pinot-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/pinot-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/pinot-driver diff --git a/packages/cubejs-pinot-driver/package.json b/packages/cubejs-pinot-driver/package.json index 3dcbe457f62e7..0fe32f71f03d4 100644 --- a/packages/cubejs-pinot-driver/package.json +++ b/packages/cubejs-pinot-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/pinot-driver", "description": "Cube.js Pinot database driver", "author": "Julian Ronsse, InTheMemory, Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -28,7 +28,7 @@ }, "dependencies": { "@cubejs-backend/base-driver": "1.1.10", - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "@cubejs-backend/shared": "1.1.10", "node-fetch": "^2.6.1", "ramda": "^0.27.2", diff --git a/packages/cubejs-postgres-driver/CHANGELOG.md b/packages/cubejs-postgres-driver/CHANGELOG.md index e11285b675523..a3779033e7ebd 100644 --- a/packages/cubejs-postgres-driver/CHANGELOG.md +++ b/packages/cubejs-postgres-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/postgres-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/postgres-driver diff --git a/packages/cubejs-postgres-driver/package.json b/packages/cubejs-postgres-driver/package.json index 6c76a7d6fc2a5..90d85d7bffc74 100644 --- a/packages/cubejs-postgres-driver/package.json +++ b/packages/cubejs-postgres-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/postgres-driver", "description": "Cube.js Postgres database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -38,7 +38,7 @@ "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.10", + "@cubejs-backend/testing-shared": "1.1.11", "testcontainers": "^10.10.4", "typescript": "~5.2.2" }, diff --git a/packages/cubejs-questdb-driver/CHANGELOG.md b/packages/cubejs-questdb-driver/CHANGELOG.md index 8352c554fc18c..b91d4cfd90d51 100644 --- a/packages/cubejs-questdb-driver/CHANGELOG.md +++ b/packages/cubejs-questdb-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/questdb-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/questdb-driver diff --git a/packages/cubejs-questdb-driver/package.json b/packages/cubejs-questdb-driver/package.json index efdc5df861b94..0b08f3cbb5088 100644 --- a/packages/cubejs-questdb-driver/package.json +++ b/packages/cubejs-questdb-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/questdb-driver", "description": "Cube.js QuestDB database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -28,7 +28,7 @@ }, "dependencies": { "@cubejs-backend/base-driver": "1.1.10", - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "@cubejs-backend/shared": "1.1.10", "@types/pg": "^8.6.0", "moment": "^2.24.0", @@ -38,7 +38,7 @@ "license": "Apache-2.0", "devDependencies": { "@cubejs-backend/linter": "^1.0.0", - "@cubejs-backend/testing-shared": "1.1.10", + "@cubejs-backend/testing-shared": "1.1.11", "testcontainers": "^10.10.4", "typescript": "~5.2.2" }, diff --git a/packages/cubejs-redshift-driver/CHANGELOG.md b/packages/cubejs-redshift-driver/CHANGELOG.md index 795eb640a097d..eab5aa53fa054 100644 --- a/packages/cubejs-redshift-driver/CHANGELOG.md +++ b/packages/cubejs-redshift-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/redshift-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/redshift-driver diff --git a/packages/cubejs-redshift-driver/package.json b/packages/cubejs-redshift-driver/package.json index 4b3be1e903047..c14d71ef83166 100644 --- a/packages/cubejs-redshift-driver/package.json +++ b/packages/cubejs-redshift-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/redshift-driver", "description": "Cube.js Redshift database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -26,7 +26,7 @@ }, "dependencies": { "@cubejs-backend/base-driver": "1.1.10", - "@cubejs-backend/postgres-driver": "1.1.10", + "@cubejs-backend/postgres-driver": "1.1.11", "@cubejs-backend/shared": "1.1.10" }, "license": "Apache-2.0", diff --git a/packages/cubejs-schema-compiler/CHANGELOG.md b/packages/cubejs-schema-compiler/CHANGELOG.md index d37095475c607..5f143a23913bf 100644 --- a/packages/cubejs-schema-compiler/CHANGELOG.md +++ b/packages/cubejs-schema-compiler/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + + +### Bug Fixes + +* TypeError: Cannot read properties of undefined (reading 'joins') ([14adaeb](https://github.com/cube-js/cube/commit/14adaebdd1c3d398bcd2997012da070999e47d9d)) + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) diff --git a/packages/cubejs-schema-compiler/package.json b/packages/cubejs-schema-compiler/package.json index 62be9dbfc97a3..04512626b7be2 100644 --- a/packages/cubejs-schema-compiler/package.json +++ b/packages/cubejs-schema-compiler/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/schema-compiler", "description": "Cube schema compiler", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", diff --git a/packages/cubejs-server-core/CHANGELOG.md b/packages/cubejs-server-core/CHANGELOG.md index 461556f8d1b5c..1d87c0dcd6eeb 100644 --- a/packages/cubejs-server-core/CHANGELOG.md +++ b/packages/cubejs-server-core/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/server-core + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) diff --git a/packages/cubejs-server-core/package.json b/packages/cubejs-server-core/package.json index 9516b410bd997..3241b226f1aad 100644 --- a/packages/cubejs-server-core/package.json +++ b/packages/cubejs-server-core/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/server-core", "description": "Cube.js base component to wire all backend components together", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -34,7 +34,7 @@ "@cubejs-backend/dotenv": "^9.0.2", "@cubejs-backend/native": "1.1.10", "@cubejs-backend/query-orchestrator": "1.1.10", - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "@cubejs-backend/shared": "1.1.10", "@cubejs-backend/templates": "1.1.10", "codesandbox-import-utils": "^2.1.12", diff --git a/packages/cubejs-server/CHANGELOG.md b/packages/cubejs-server/CHANGELOG.md index 3d21f81a81ce2..12536288b6d08 100644 --- a/packages/cubejs-server/CHANGELOG.md +++ b/packages/cubejs-server/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/server + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/server diff --git a/packages/cubejs-server/package.json b/packages/cubejs-server/package.json index 5307af3cc277c..45b2e7df1adfe 100644 --- a/packages/cubejs-server/package.json +++ b/packages/cubejs-server/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/server", "description": "Cube.js all-in-one server", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "types": "index.d.ts", "repository": { "type": "git", @@ -43,7 +43,7 @@ "@cubejs-backend/cubestore-driver": "1.1.10", "@cubejs-backend/dotenv": "^9.0.2", "@cubejs-backend/native": "1.1.10", - "@cubejs-backend/server-core": "1.1.10", + "@cubejs-backend/server-core": "1.1.11", "@cubejs-backend/shared": "1.1.10", "@oclif/color": "^1.0.0", "@oclif/command": "^1.8.13", diff --git a/packages/cubejs-testing-drivers/CHANGELOG.md b/packages/cubejs-testing-drivers/CHANGELOG.md index 739c3d7297a53..6560f106fc2c6 100644 --- a/packages/cubejs-testing-drivers/CHANGELOG.md +++ b/packages/cubejs-testing-drivers/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/testing-drivers + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/testing-drivers diff --git a/packages/cubejs-testing-drivers/package.json b/packages/cubejs-testing-drivers/package.json index 4565d23089c2c..7194dc04713ea 100644 --- a/packages/cubejs-testing-drivers/package.json +++ b/packages/cubejs-testing-drivers/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/testing-drivers", - "version": "1.1.10", + "version": "1.1.11", "description": "Cube.js drivers test suite", "author": "Cube Dev, Inc.", "license": "MIT", @@ -56,22 +56,22 @@ "dist/src" ], "dependencies": { - "@cubejs-backend/athena-driver": "1.1.10", + "@cubejs-backend/athena-driver": "1.1.11", "@cubejs-backend/base-driver": "1.1.10", - "@cubejs-backend/bigquery-driver": "1.1.10", - "@cubejs-backend/clickhouse-driver": "1.1.10", + "@cubejs-backend/bigquery-driver": "1.1.11", + "@cubejs-backend/clickhouse-driver": "1.1.11", "@cubejs-backend/cubestore-driver": "1.1.10", - "@cubejs-backend/databricks-jdbc-driver": "1.1.10", + "@cubejs-backend/databricks-jdbc-driver": "1.1.11", "@cubejs-backend/dotenv": "^9.0.2", "@cubejs-backend/linter": "^1.0.0", "@cubejs-backend/mssql-driver": "1.1.10", - "@cubejs-backend/mysql-driver": "1.1.10", - "@cubejs-backend/postgres-driver": "1.1.10", + "@cubejs-backend/mysql-driver": "1.1.11", + "@cubejs-backend/postgres-driver": "1.1.11", "@cubejs-backend/query-orchestrator": "1.1.10", - "@cubejs-backend/server-core": "1.1.10", + "@cubejs-backend/server-core": "1.1.11", "@cubejs-backend/shared": "1.1.10", "@cubejs-backend/snowflake-driver": "1.1.10", - "@cubejs-backend/testing-shared": "1.1.10", + "@cubejs-backend/testing-shared": "1.1.11", "@cubejs-client/core": "^1.0.0", "@cubejs-client/ws-transport": "^1.0.0", "@jest/globals": "^27", diff --git a/packages/cubejs-testing-shared/CHANGELOG.md b/packages/cubejs-testing-shared/CHANGELOG.md index 092c1de792be3..6a8438bdbbd46 100644 --- a/packages/cubejs-testing-shared/CHANGELOG.md +++ b/packages/cubejs-testing-shared/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/testing-shared + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/testing-shared diff --git a/packages/cubejs-testing-shared/package.json b/packages/cubejs-testing-shared/package.json index defff64fa79c4..ee01d5c176358 100644 --- a/packages/cubejs-testing-shared/package.json +++ b/packages/cubejs-testing-shared/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/testing-shared", - "version": "1.1.10", + "version": "1.1.11", "description": "Cube.js Testing Helpers", "author": "Cube Dev, Inc.", "license": "Apache-2.0", @@ -22,7 +22,7 @@ "dependencies": { "@cubejs-backend/dotenv": "^9.0.2", "@cubejs-backend/query-orchestrator": "1.1.10", - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "@cubejs-backend/shared": "1.1.10", "@testcontainers/kafka": "~10.13.0", "dedent": "^0.7.0", diff --git a/packages/cubejs-testing/CHANGELOG.md b/packages/cubejs-testing/CHANGELOG.md index 9586a78b449df..e61138fa52509 100644 --- a/packages/cubejs-testing/CHANGELOG.md +++ b/packages/cubejs-testing/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/testing + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) diff --git a/packages/cubejs-testing/package.json b/packages/cubejs-testing/package.json index 9abf54d8020b2..c605bbd47c387 100644 --- a/packages/cubejs-testing/package.json +++ b/packages/cubejs-testing/package.json @@ -1,6 +1,6 @@ { "name": "@cubejs-backend/testing", - "version": "1.1.10", + "version": "1.1.11", "description": "Cube.js e2e tests", "author": "Cube Dev, Inc.", "license": "Apache-2.0", @@ -92,12 +92,12 @@ "dependencies": { "@cubejs-backend/cubestore-driver": "1.1.10", "@cubejs-backend/dotenv": "^9.0.2", - "@cubejs-backend/ksql-driver": "1.1.10", - "@cubejs-backend/postgres-driver": "1.1.10", + "@cubejs-backend/ksql-driver": "1.1.11", + "@cubejs-backend/postgres-driver": "1.1.11", "@cubejs-backend/query-orchestrator": "1.1.10", - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "@cubejs-backend/shared": "1.1.10", - "@cubejs-backend/testing-shared": "1.1.10", + "@cubejs-backend/testing-shared": "1.1.11", "@cubejs-client/ws-transport": "^1.0.0", "dedent": "^0.7.0", "fs-extra": "^8.1.0", diff --git a/packages/cubejs-trino-driver/CHANGELOG.md b/packages/cubejs-trino-driver/CHANGELOG.md index dbc20f5fe0815..a96c3ad31846f 100644 --- a/packages/cubejs-trino-driver/CHANGELOG.md +++ b/packages/cubejs-trino-driver/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/cube-js/cube/compare/v1.1.10...v1.1.11) (2024-12-16) + +**Note:** Version bump only for package @cubejs-backend/trino-driver + + + + + ## [1.1.10](https://github.com/cube-js/cube/compare/v1.1.9...v1.1.10) (2024-12-16) **Note:** Version bump only for package @cubejs-backend/trino-driver diff --git a/packages/cubejs-trino-driver/package.json b/packages/cubejs-trino-driver/package.json index a38f17c163d0a..90a5a3449928f 100644 --- a/packages/cubejs-trino-driver/package.json +++ b/packages/cubejs-trino-driver/package.json @@ -2,7 +2,7 @@ "name": "@cubejs-backend/trino-driver", "description": "Cube.js Trino database driver", "author": "Cube Dev, Inc.", - "version": "1.1.10", + "version": "1.1.11", "repository": { "type": "git", "url": "https://github.com/cube-js/cube.git", @@ -27,7 +27,7 @@ "dependencies": { "@cubejs-backend/base-driver": "1.1.10", "@cubejs-backend/prestodb-driver": "1.1.10", - "@cubejs-backend/schema-compiler": "1.1.10", + "@cubejs-backend/schema-compiler": "1.1.11", "@cubejs-backend/shared": "1.1.10", "presto-client": "^0.12.2", "sqlstring": "^2.3.1"