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

[ADAP-638] [Bug] dbt crashes if for nested fields (e.g. struct) both the parent and subfields are defined in the YAML file #782

Closed
2 tasks done
Tracked by #7372
b-per opened this issue Jun 21, 2023 · 1 comment · Fixed by #806
Assignees
Labels
bug Something isn't working

Comments

@b-per
Copy link
Contributor

b-per commented Jun 21, 2023

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

While testing #738 in 1.5rc2, we managed to crash dbt when adding YML config to a struct, both at the parent and subfield levels at the same time.

The goal was to try:

  • providing constraints at the struct level in addition to the field level (e.g. the struct itself should be not null in addition to some of the subfields being not null
  • adding description at the struct level in addition to the subfield level

(the following was tried with and without data_type at the parent level but both failed, with different errors though. in an ideal situation, we wouldn't have to set the data_type at the parent level but still be allowed to add constraint and documentation)

- name: my_struct
  description: |
    My overall description
  data_type: |
    struct<
      field_1 string,
      field_2 numeric>  
- name: my_struct.field_1
  data_type: string
  description: Desc for field_1
- name: my_struct.field_2
  data_type: numeric
  description: Desc for field_2

We were expecting this to either work or get a config error from dbt but instead dbt crashes. The code dump is listed below.

Expected Behavior

I would expect this config not to crash but instead to:

  • ideally work, allowing config at both levels, parent and subfield
  • or at least raise an error telling me what that having config at both levels is not allowed

Steps To Reproduce

  1. use a struct in a model
  2. configure the struct in YML with constraints and descriptions
    a. at the subfield level
    b. at the struct (e.g. parent level)

Relevant log output

2023-06-20 13:39:06.733916 (Thread-34): �[0m13:39:06  Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/dbt/task/base.py", line 391, in safe_run
    result = self.compile_and_execute(manifest, ctx)
  File "/usr/local/lib/python3.8/dist-packages/dbt/task/base.py", line 340, in compile_and_execute
    result = self.run(ctx.node, manifest)
  File "/usr/local/lib/python3.8/dist-packages/dbt/task/base.py", line 439, in run
    return self.execute(compiled_node, manifest)
  File "/usr/local/lib/python3.8/dist-packages/dbt/task/run.py", line 291, in execute
    result = MacroGenerator(
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 330, in __call__
    return self.call_macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 257, in call_macro
    return macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 763, in __call__
    return self._invoke(arguments, autoescape)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 777, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 108, in macro
  File "/usr/local/lib/python3.8/dist-packages/jinja2/sandbox.py", line 393, in call
    return __context.call(__obj, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 298, in call
    return __obj(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 330, in __call__
    return self.call_macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 257, in call_macro
    return macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 763, in __call__
    return self._invoke(arguments, autoescape)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 777, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 42, in macro
  File "/usr/local/lib/python3.8/dist-packages/jinja2/sandbox.py", line 393, in call
    return __context.call(__obj, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 298, in call
    return __obj(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 763, in __call__
    return self._invoke(arguments, autoescape)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 777, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 104, in macro
  File "/usr/local/lib/python3.8/dist-packages/jinja2/sandbox.py", line 393, in call
    return __context.call(__obj, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 298, in call
    return __obj(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 330, in __call__
    return self.call_macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 257, in call_macro
    return macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 763, in __call__
    return self._invoke(arguments, autoescape)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 777, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 58, in macro
  File "/usr/local/lib/python3.8/dist-packages/jinja2/sandbox.py", line 393, in call
    return __context.call(__obj, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 298, in call
    return __obj(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 330, in __call__
    return self.call_macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 257, in call_macro
    return macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 763, in __call__
    return self._invoke(arguments, autoescape)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 777, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 31, in macro
  File "/usr/local/lib/python3.8/dist-packages/jinja2/sandbox.py", line 393, in call
    return __context.call(__obj, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 298, in call
    return __obj(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 330, in __call__
    return self.call_macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 257, in call_macro
    return macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 763, in __call__
    return self._invoke(arguments, autoescape)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 777, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 62, in macro
  File "/usr/local/lib/python3.8/dist-packages/jinja2/sandbox.py", line 393, in call
    return __context.call(__obj, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 298, in call
    return __obj(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 330, in __call__
    return self.call_macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 257, in call_macro
    return macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 763, in __call__
    return self._invoke(arguments, autoescape)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 777, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 19, in macro
  File "/usr/local/lib/python3.8/dist-packages/jinja2/sandbox.py", line 393, in call
    return __context.call(__obj, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 298, in call
    return __obj(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 330, in __call__
    return self.call_macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 257, in call_macro
    return macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 763, in __call__
    return self._invoke(arguments, autoescape)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 777, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 20, in macro
  File "/usr/local/lib/python3.8/dist-packages/jinja2/sandbox.py", line 393, in call
    return __context.call(__obj, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 298, in call
    return __obj(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 330, in __call__
    return self.call_macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 257, in call_macro
    return macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 763, in __call__
    return self._invoke(arguments, autoescape)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 777, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 31, in macro
  File "/usr/local/lib/python3.8/dist-packages/jinja2/sandbox.py", line 393, in call
    return __context.call(__obj, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 298, in call
    return __obj(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 330, in __call__
    return self.call_macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 257, in call_macro
    return macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 763, in __call__
    return self._invoke(arguments, autoescape)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 777, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 20, in macro
  File "/usr/local/lib/python3.8/dist-packages/jinja2/sandbox.py", line 393, in call
    return __context.call(__obj, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 298, in call
    return __obj(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 330, in __call__
    return self.call_macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/clients/jinja.py", line 257, in call_macro
    return macro(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 763, in __call__
    return self._invoke(arguments, autoescape)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 777, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 20, in macro
  File "/usr/local/lib/python3.8/dist-packages/jinja2/sandbox.py", line 393, in call
    return __context.call(__obj, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/jinja2/runtime.py", line 298, in call
    return __obj(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/dbt/adapters/bigquery/impl.py", line 280, in nest_column_data_types
    return get_nested_column_data_types(columns, constraints)
  File "/usr/local/lib/python3.8/dist-packages/dbt/adapters/bigquery/column.py", line 164, in get_nested_column_data_types
    _update_nested_column_data_types(
  File "/usr/local/lib/python3.8/dist-packages/dbt/adapters/bigquery/column.py", line 231, in _update_nested_column_data_types
    assert isinstance(remaining_column_data_types, dict)  # keeping mypy happy
AssertionError

Environment

- dbt-core: 1.5rc2

Additional Context

No response

@b-per b-per added bug Something isn't working triage labels Jun 21, 2023
@github-actions github-actions bot changed the title [Bug] dbt crashes if for nested fields (e.g. struct) both the parent and subfields are defined in the YAML file [ADAP-638] [Bug] dbt crashes if for nested fields (e.g. struct) both the parent and subfields are defined in the YAML file Jun 21, 2023
@jtcohen6
Copy link
Contributor

@b-per Thanks for testing out, and for opening!

From some quick local testing:

in an ideal situation, we wouldn't have to set the data_type at the parent level but still be allowed to add constraint and documentation

Agree that this is the ideal outcome!

repro case

This works:

-- models/model_a.sql
select struct("blue" as field_1, 100 as field_2) as my_struct
models:
  - name: model_a
    config:
      contract: {enforced: true}
      materialized: table
    columns:
      - name: my_struct.field_1
        data_type: string
        constraints:
          - type: not_null
        description: Desc for field_1
      - name: my_struct.field_2
        data_type: integer
        description: Desc for field_2

Desirable outcome:

models:
  - name: model_a
    config:
      contract: {enforced: true}
    columns:
      - name: my_struct
        description: My overall description
        constraints:
          - type: not_null
      - name: my_struct.field_1
        data_type: string
        description: Desc for field_1
        constraints:
          - type: not_null
      - name: my_struct.field_2
        data_type: integer
        description: Desc for field_2

Should template SQL like:

create or replace table `dbt-test-env`.`dbt_jcohen`.`model_a`      
(
    my_struct struct<field_1 string not null, field_2 integer> not null
)
OPTIONS()
as (
    select my_struct
    from (
        select struct("blue" as field_1, 100 as field_2) as my_struct
    ) as model_subq
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
3 participants