Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] unit testing a recursive CTE fails #1178

Open
2 tasks done
HarlanH opened this issue Apr 12, 2024 · 8 comments
Open
2 tasks done

[Feature] unit testing a recursive CTE fails #1178

HarlanH opened this issue Apr 12, 2024 · 8 comments
Assignees
Labels
enhancement New feature or request unit tests Issues related to built-in dbt unit testing functionality

Comments

@HarlanH
Copy link

HarlanH commented Apr 12, 2024

Is this a new bug in dbt-bigquery?

  • I believe this is a new bug in dbt-bigquery
  • I have searched the existing issues, and I could not find an existing issue for this bug

Current Behavior

I'm trying to unit test a model with a recursive CTE (a use case specifically called out in the docs), but it's failing with this error in dbt Cloud:

WITH RECURSIVE is only allowed at the top level of the SELECT, CREATE TABLE AS SELECT, CREATE VIEW, INSERT, EXPORT DATA statements.

Examining the generated code, I can confirm that it starts with select * from (WITH RECURSIVE.

Expected Behavior

I expect to be able to use unit tests with recursive CTEs on BigQuery.

Steps To Reproduce

  1. Add the attached 3 files to a BigQuery dbt environment with version 1.8. (I used dbt Cloud.)
  2. dbt build --select +recursive_cte+

Relevant log output

13:32:41 Began running node unit_test.edsights.recursive_cte.test_recursive_cte
13:32:41 2 of 3 START unit_test recursive_cte::test_recursive_cte ....................... [RUN]
13:32:41 Acquiring new bigquery connection 'unit_test.edsights.recursive_cte.test_recursive_cte'
13:32:41 Began compiling node unit_test.edsights.recursive_cte.test_recursive_cte
13:32:41 Timing info for unit_test.edsights.recursive_cte.test_recursive_cte (compile): 13:32:41.383097 => 13:32:41.383103
13:32:41 Began executing node unit_test.edsights.recursive_cte.test_recursive_cte
13:32:41 Opening a new connection, currently in state init
13:32:41 Writing injected SQL for node "unit_test.edsights.recursive_cte.test_recursive_cte"
13:32:41 Writing injected SQL for node "unit_test.edsights.recursive_cte.test_recursive_cte"
13:32:41 On unit_test.edsights.recursive_cte.test_recursive_cte: /* {"app": "dbt", "dbt_version": "2024.0.0", "profile_name": "user", "target_name": "default", "node_id": "unit_test.edsights.recursive_cte.test_recursive_cte"} */

    
  
    

    create or replace table `production-one-405017`.`dbt_harlan`.`test_recursive_cte__dbt_tmp`
      
    
    

    OPTIONS(
      expiration_timestamp=TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL 12 hour)
    )
    as (
      select * from (
        WITH RECURSIVE
 __dbt__cte__recursive_cte_given as (

-- Fixture for recursive_cte_given
select safe_cast('1' as INT64) as x
), asdf AS (
    SELECT *
    FROM __dbt__cte__recursive_cte_given
)

SELECT *
FROM asdf
    ) as __dbt_sbq
    where false and current_timestamp() = current_timestamp()
    limit 0

    );
  
  
13:32:41 BigQuery adapter: https://console.cloud.google.com/bigquery?project=production-one-405017&j=bq:us-central1:a993367b-a621-4a41-8bf7-23d7275b7e5a&page=queryresults
13:32:42 BigQuery adapter: Retry attempt 1 of 1 after error: BadRequest('WITH RECURSIVE is only allowed at the top level of the SELECT, CREATE TABLE AS SELECT, CREATE VIEW, INSERT, EXPORT DATA statements.; reason: invalidQuery, location: query, message: WITH RECURSIVE is only allowed at the top level of the SELECT, CREATE TABLE AS SELECT, CREATE VIEW, INSERT, EXPORT DATA statements.')
13:32:43 BigQuery adapter: https://console.cloud.google.com/bigquery?project=production-one-405017&j=bq:us-central1:16d300ec-588c-4414-aafd-9583fc051629&page=queryresults
13:32:43 BigQuery adapter: https://console.cloud.google.com/bigquery?project=production-one-405017&j=bq:us-central1:16d300ec-588c-4414-aafd-9583fc051629&page=queryresults
13:32:43 Timing info for unit_test.edsights.recursive_cte.test_recursive_cte (execute): 13:32:41.384037 => 13:32:43.609843
13:32:43 Runtime Error in unit_test test_recursive_cte (models/intermediate/recursive_cte.yml)
  An error occurred during execution of unit test 'test_recursive_cte'. There may be an error in the unit test definition: check the data types.
   Database Error
    WITH RECURSIVE is only allowed at the top level of the SELECT, CREATE TABLE AS SELECT, CREATE VIEW, INSERT, EXPORT DATA statements.
13:32:43 2 of 3 ERROR recursive_cte::test_recursive_cte ................................. [�[31mERROR�[0m in 2.23s]
13:32:43 Finished running node unit_test.edsights.recursive_cte.test_recursive_cte
13:32:43   Runtime Error in unit_test test_recursive_cte (models/intermediate/recursive_cte.yml)
  An error occurred during execution of unit test 'test_recursive_cte'. There may be an error in the unit test definition: check the data types.
   Database Error
    WITH RECURSIVE is only allowed at the top level of the SELECT, CREATE TABLE AS SELECT, CREATE VIEW, INSERT, EXPORT DATA statements.

Environment

dbt Cloud with version 1.8

Additional Context

See also dbt Labs support ticket 64761.

@HarlanH HarlanH added bug Something isn't working triage labels Apr 12, 2024
@HarlanH
Copy link
Author

HarlanH commented Apr 12, 2024

recursive_cte.zip

ZIP file includes two SQL files and a YML file.

@graciegoheen
Copy link

graciegoheen commented Apr 12, 2024

Hey - thanks so much for opening! Since this is currently broken, we're going to remove that callout from our docs site. But I will sync with our engineers to see how we can fix this.

  • We should investigate if we can remove the outer select * from ( entirely.
  • We should implement this fix for all adapters that support recursive SQL

mirnawong1 added a commit to dbt-labs/docs.getdbt.com that referenced this issue Apr 16, 2024
## What are you changing in this pull request and why?

Recursion is not currently working for BigQuery
(dbt-labs/dbt-bigquery#1178), so per
@graciegoheen, remove this from the scenarios until it is resolved.

## Checklist
- [x] Review the [Content style
guide](https://github.com/dbt-labs/docs.getdbt.com/blob/current/contributing/content-style-guide.md)
so my content adheres to these guidelines.
@graciegoheen
Copy link

Just adding the reproducible example Harlan shared.

I have a model I want to unit test:

# models/recursive_cte.sql

WITH RECURSIVE
asdf AS (
    SELECT *
    FROM {{ ref('recursive_cte_given') }}
)

SELECT *
FROM asdf

I add a unit test:

unit_tests:
  - name: test_recursive_cte
    model: recursive_cte
    given:
      - input: ref('recursive_cte_given')
        format: csv
        rows: |
          x
          1
    expect:
      format: csv
      rows: |
        x
        1

@graciegoheen graciegoheen changed the title [Bug] unit testing a recursive CTE fails [spike+] unit testing a recursive CTE fails Apr 23, 2024
@graciegoheen graciegoheen changed the title [spike+] unit testing a recursive CTE fails [spike+] [bug] unit testing a recursive CTE fails Apr 23, 2024
@MichelleArk
Copy link
Contributor

It looks like WITH RECURSIVE is supported for most of the dbt Labs supported adapters:

@MichelleArk
Copy link
Contributor

For implementation:

I'm not sure if it's possible to remove the select * but maintain the where false limit 0 filter. If we don't have the where false limit 0 filter, obtaining the column schema of the tested model isn't possible without actually running the query which could be costly...

@MichelleArk
Copy link
Contributor

Additionally, we also expect to be able to wrap the user-provided sql in a subquery when constructing the statement that unions actual and expected results for comparison here.

It seems that being able to wrap the user-provided SQL in a subquery is an assumption held by the unit testing framework in multiple places currently.

@MichelleArk
Copy link
Contributor

It looks like the dbt-unit-testing package also experiences this limitation, which is unsurprising given the CTE-based approach: EqualExperts/dbt-unit-testing#198

I think the only way to solve this generally is to use a seed-based strategy for ephemeral models, similar to what we'd need for being able to test incremental model upsert/merge logic: dbt-labs/dbt-core#8499

@graciegoheen graciegoheen changed the title [spike+] [bug] unit testing a recursive CTE fails [feature] unit testing a recursive CTE fails Apr 24, 2024
@graciegoheen graciegoheen added enhancement New feature or request unit tests Issues related to built-in dbt unit testing functionality and removed bug Something isn't working labels Apr 24, 2024
@graciegoheen
Copy link

We're going to call this out as a known limitation for the 1.8 release. But this is something we will revisit for 1.9 as an outcome of dbt-labs/dbt-core#8499

@amychen1776 amychen1776 changed the title [feature] unit testing a recursive CTE fails [Feature] unit testing a recursive CTE fails Aug 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request unit tests Issues related to built-in dbt unit testing functionality
Projects
None yet
Development

No branches or pull requests

4 participants