sqlfluff / sqlfluff

A modular SQL linter and auto-formatter with support for multiple dialects and templated code.
https://www.sqlfluff.com
MIT License
7.87k stars 725 forks source link

unparsable Jinja and/or "Length of templated file mismatch with final slice" error with dbt-templater on Windows #6252

Open carlobehtash opened 1 month ago

carlobehtash commented 1 month ago

Search before asking

What Happened

When trying to sqlfluff lint/fix/parse on a Windows machine with the templater set to dbt, basic Jinja (ex. {{ source('project', 'table') }} ) gives one of the following errors, depending on the specific case:

The behaviour only occurs on Windows machines.

Expected Behaviour

No errors and any linting violations are caught.

Observed Behaviour

sqlfluff-templater-dbt is unable to parse Jinja

How to reproduce

Try linting/fixing/parsing a model:

with src as (
select * from {{ source('project', 'table') }}
)

select * from src

Dialect

BigQuery

Version

dbt-bigquery==1.6.9 sqlfluff==3.0.6 sqlfluff-templater-dbt==3.0.6

(upgrading to 3.2.0 doesn't fix)

Configuration

[sqlfluff]
templater = dbt
dialect = bigquery
exclude_rules = L027
max_line_length = 100

[sqlfluff:templater:dbt]
project_dir = .
profiles_dir = .
profile = data_product
target = dev

[sqlfluff:templater:jinja]
apply_dbt_builtins = True

[sqlfluff:layout:type:alias_expression]
# Documentation is available here: https://docs.sqlfluff.com/en/stable/layout.html#aligned-elements
# We want non-default spacing _before_ the alias expressions.
spacing_before = align
# We want to align them within the next outer select clause.
# This means for example that alias expressions within the FROM
# or JOIN clause would _not_ be aligned with them.
align_within = select_clause
# The point at which to stop searching outward for siblings, which
# in this example would likely be the boundary of a CTE. Stopping
# when we hit brackets is usually a good rule of thumb for this
# configuration.
align_scope = bracketed

[sqlfluff:indentation]
tab_space_size = 4

[sqlfluff:rules:layout.indent]
# Examples available here: https://docs.sqlfluff.com/en/stable/rules.html#sqlfluff.rules.Rule_L004
# Whether to use tabs or spaces to add new indents. Must be one of ['space', 'tab'].
indent_unit = space
# The number of spaces to consider equal to one tab. Used in the fixing step of this rule. Must be one of range(0, 100).

[sqlfluff:rules:capitalisation.keywords]
# Keywords,  Must be one of ['consistent', 'upper', 'lower', 'pascal', 'capitalise']
# Examples available here: https://docs.sqlfluff.com/en/stable/rules.html#sqlfluff.rules.Rule_L010
capitalisation_policy = lower
# Comma separated list of words to ignore for this rule

[sqlfluff:rules:capitalisation.identifiers]
# Unquoted identifiers, Must be one of ['consistent', 'upper', 'lower', 'pascal', 'capitalise']
# Example available here: https://docs.sqlfluff.com/en/stable/rules.html#sqlfluff.rules.Rule_L014
extended_capitalisation_policy = lower

[sqlfluff:rules:capitalisation.functions]
# Function names, Must be one of ['consistent', 'upper', 'lower', 'pascal', 'capitalise']
# Example available here: https://docs.sqlfluff.com/en/stable/rules.html#sqlfluff.rules.Rule_L030
extended_capitalisation_policy = lower

Are you willing to work on and submit a PR to address the issue?

Code of Conduct

alanmcruickshank commented 1 week ago

@carlobehtash - I do most of the development for SQLFluff on a Windows machine but I'm struggling to recreate this bug. You're not the first person to report something similar though, so I'd love to get to the bottom of what's causing it.

There are a few things that would really help debug this, if you're able to provide them:

  1. For a simple model like the one you provided as an example, can you record what the numbers are in the error messages you're getting, i.e. in Line N, Position X: Found unparsable section: & Length of templated file mismatch with final slice: Y != Z, what are the actual values for N, X, Y & Z?
  2. Given it's a Windows specific bug, and it's to do with mismatches in file length, my current leading theory that it's to do with newline characters (i.e. whether it's \r\n or \n for newlines). Could you confirm which style of newlines the file in question uses (LF or CRLF - if you're using VSCode it will be shown in the bottom right of the screen) - and even better would be to try changing the newline character from one to the other and see if that resolves the issue.

What would also be useful would be a set of verbose logs for linting just that file, so if you could run sqlfluff lint /my/file.sql -vvvvvv for a minimal file which exhibits the bug that would be very helpful. If you're right that this always happens, then select * from {{ ref('some_other_table') }} should be enough to trigger it.

If anyone else is watching this issue who has the same problem - more data here would be better to pin down what's going on and be able to recreate the bug.

almutasemykb commented 3 days ago

@carlobehtash - I am facing similar issue and this is the verbose logs

==== sqlfluff ====
sqlfluff:                3.2.5 python:                 3.11.9
implementation:        cpython verbosity:                   6
dialect:            databricks templater:                 dbt
dbt:                 =1.9.0-b2
rules:                                all
== Raw Config:
core:
    dialect:            databricks
    disable_noqa:       False
    encoding:           autodetect
    exclude_rules:      L016,L031,L034,L026,L009
    fix_even_unparsable:False
    ignore:             []
    ignore_templated_areas:True
    large_file_skip_byte_limit:0
    large_file_skip_char_limit:0
    max_line_length:    80
    nocolor:            False
    output_line_length: 80
    processes:          1
    render_variant_limit:1
    rules:              all
    runaway_limit:      10
    sql_file_exts:      .sql,.sql.j2,.dml,.ddl
    templater:          dbt
    verbose:            6
    warn_unused_ignores:False
    warnings:           []
indentation:        
    allow_implicit_indents:True
    ignore_comment_lines:False
    indent_unit:        space
    indented_ctes:      False
    indented_joins:     False
    indented_on_contents:True
    indented_then:      True
    indented_then_contents:True
    indented_using_on:  True
    skip_indentation_in:script_content
    tab_space_size:     2
    template_blocks_indent:True
    trailing_comments:  before
layout:
    type:
        alias_expression:   
            align_scope:        bracketed
            align_within:       select_clause
            spacing_before:     align
        array_accessor:     
            spacing_before:     touch:inline
        array_type:
            spacing_within:     touch:inline
        assignment_operator:
            line_position:      leading
            spacing_within:     touch
        binary_operator:    
            line_position:      leading
            spacing_within:     touch
        bracketed_arguments:
            spacing_before:     touch:inline
        casting_operator:   
            spacing_after:      touch:inline
            spacing_before:     touch
        colon:
            spacing_before:     touch
        colon_delimiter:    
            spacing_after:      touch
            spacing_before:     touch
        comma:
            line_position:      trailing
            spacing_before:     touch
        comment:
            spacing_after:      any
            spacing_before:     any
        common_table_expression:
            spacing_within:     single:inline
        comparison_operator:
            line_position:      leading
            spacing_within:     touch
        dot:
            spacing_after:      touch
            spacing_before:     touch
        end_angle_bracket:  
            spacing_before:     touch
        end_bracket:        
            spacing_before:     touch
        end_of_file:        
            spacing_before:     touch
        end_square_bracket: 
            spacing_before:     touch
        from_clause:        
            line_position:      alone
        function_contents:  
            spacing_before:     touch:inline
        function_name:      
            spacing_within:     touch:inline
        function_parameter_list:
            spacing_before:     touch:inline
        groupby_clause:     
            line_position:      alone
        having_clause:      
            line_position:      alone
        join_clause:        
            line_position:      alone
        limit_clause:       
            line_position:      alone
        match_condition:    
            spacing_within:     touch:inline
        numeric_literal:    
            spacing_within:     touch:inline
        object_reference:   
            spacing_within:     touch:inline
        orderby_clause:     
            line_position:      leading
        path_segment:       
            spacing_within:     touch
        pattern_expression: 
            spacing_within:     any
        placeholder:        
            spacing_after:      any
            spacing_before:     any
        select_clause:      
            line_position:      alone
        semi_structured_expression:
            spacing_before:     touch:inline
            spacing_within:     touch:inline
        set_operator:       
            line_position:      alone:strict
        sign_indicator:     
            spacing_after:      touch:inline
        sized_array_type:   
            spacing_within:     touch
        slash:
            spacing_after:      any
            spacing_before:     any
        slice:
            spacing_after:      touch
            spacing_before:     touch
        sql_conf_option:    
            spacing_within:     touch
        sqlcmd_operator:    
            spacing_before:     touch
        start_angle_bracket:
            spacing_after:      touch
        start_bracket:      
            spacing_after:      touch
        start_square_bracket:
            spacing_after:      touch
        statement_terminator:
            line_position:      trailing
            spacing_before:     touch
        struct_type:        
            spacing_within:     touch:inline
        template_loop:      
            spacing_after:      any
            spacing_before:     any
        tilde:
            spacing_after:      touch:inline
        typed_array_literal:
            spacing_within:     touch
        typed_struct_literal:
            spacing_within:     touch
        where_clause:       
            line_position:      alone
rules:
    allow_scalar:       True
    single_table_references:consistent
    unquoted_identifiers_policy:all
    aliasing.column:    
        aliasing:           explicit
    aliasing.forbid:    
        force_enable:       False
    aliasing.length:    
        min_alias_length:   4
    aliasing.table:     
        aliasing:           explicit
    aliasing.unused:    
        alias_case_check:   dialect
    ambiguous.column_references:
        group_by_and_order_by_style:consistent
    ambiguous.join:     
        fully_qualify_join_types:inner
    capitalisation.functions:
        extended_capitalisation_policy:upper
    capitalisation.identifiers:
        extended_capitalisation_policy:lower
    capitalisation.keywords:
        capitalisation_policy:upper
    capitalisation.literals:
        capitalisation_policy:upper
    capitalisation.types:
        extended_capitalisation_policy:upper
    convention.blocked_words:
        match_source:       False
    convention.casting_style:
        preferred_type_casting_style:consistent
    convention.count_rows:
        prefer_count_0:     False
        prefer_count_1:     False
    convention.not_equal:
        preferred_not_equal_style:consistent
    convention.quoted_literals:
        force_enable:       False
        preferred_quoted_literal_style:consistent
    convention.select_trailing_comma:
        select_clause_trailing_comma:forbid
    convention.terminator:
        multiline_newline:  False
        require_final_semicolon:False
    layout.long_lines:  
        ignore_comment_clauses:False
        ignore_comment_lines:False
    layout.select_targets:
        wildcard_policy:    single
    references.consistent:
        force_enable:       False
    references.from:    
        force_enable:       False
    references.keywords:
        unquoted_identifiers_policy:aliases
    references.qualification:
    references.quoting: 
        case_sensitive:     True
        prefer_quoted_identifiers:False
        prefer_quoted_keywords:False
    references.special_chars:
        additional_allowed_characters:['.','(',')','-','<=>']
        allow_space_in_identifier:True
        quoted_identifiers_policy:all
        unquoted_identifiers_policy:all
    structure.join_condition_order:
        preferred_first_table_in_join_clause:earlier
    structure.subquery: 
        forbid_subquery_in: join
templater:
    unwrap_wrapped_queries:True
    dbt:
        project_dir:        ./

==== readout ====

=== [dbt templater] Sorting Nodes...
INFO       Rendering String [dbt] (src\models\marts\facts\tmp.sql)
=== [dbt templater] Compiling dbt project...
=== [dbt templater] Project Compiled.
DEBUG      _find_node for path 'D:\\path\\to\\model\\tmp.sql' returned object of type <class 'dbt.contracts.graph.nodes.ModelNode'>.
DEBUG          Trailing newline count in source dbt model: 0
DEBUG          Raw SQL before compile: '{{ "SELECT \'lorem\' AS text;" }}'
DEBUG          Node raw SQL: '{{ "SELECT \'lorem\' AS text;" }}'
DEBUG          Node compiled SQL: "SELECT 'lorem' AS text;"
INFO       Slicing File Template
DEBUG          Raw String: '{{ "SELECT \'lorem\' AS text;" }}'
INFO       Rendered 1 variants
INFO       Parse Rendered. Lexing Variant 0
INFO       LEXING RAW (D:\path\to\model\tmp.sql)
INFO       Elements to Segments.
DEBUG        0: TemplateElement(raw='{', template_slice=slice(0, 1, None), matcher=<StringLexer: start_curly_bracket>). [tfs_idx = 0]
DEBUG            0: TemplatedFileSlice(slice_type='templated', source_slice=slice(0, 31, None), templated_slice=slice(0, 31, None))
DEBUG           Contained templated slice.
DEBUG        1: TemplateElement(raw='{', template_slice=slice(1, 2, None), matcher=<StringLexer: start_curly_bracket>). [tfs_idx = 0]
DEBUG            0: TemplatedFileSlice(slice_type='templated', source_slice=slice(0, 31, None), templated_slice=slice(0, 31, None))
DEBUG           Contained templated slice.
DEBUG        2: TemplateElement(raw=' ', template_slice=slice(2, 3, None), matcher=<RegexLexer: whitespace>). [tfs_idx = 0]   
DEBUG            0: TemplatedFileSlice(slice_type='templated', source_slice=slice(0, 31, None), templated_slice=slice(0, 31, None))
DEBUG           Contained templated slice.
DEBUG        3: TemplateElement(raw='"SELECT \'lorem\' AS text;"', template_slice=slice(3, 28, None), matcher=<RegexLexer: double_quote>). [tfs_idx = 0]
DEBUG            0: TemplatedFileSlice(slice_type='templated', source_slice=slice(0, 31, None), templated_slice=slice(0, 31, None))
DEBUG           Contained templated slice.
DEBUG        4: TemplateElement(raw=' ', template_slice=slice(28, 29, None), matcher=<RegexLexer: whitespace>). [tfs_idx = 0] 
DEBUG            0: TemplatedFileSlice(slice_type='templated', source_slice=slice(0, 31, None), templated_slice=slice(0, 31, None))
DEBUG           Contained templated slice.
DEBUG        5: TemplateElement(raw='}', template_slice=slice(29, 30, None), matcher=<StringLexer: end_curly_bracket>). [tfs_idx = 0]
DEBUG            0: TemplatedFileSlice(slice_type='templated', source_slice=slice(0, 31, None), templated_slice=slice(0, 31, None))
DEBUG           Contained templated slice.
DEBUG        6: TemplateElement(raw='}', template_slice=slice(30, 31, None), matcher=<StringLexer: end_curly_bracket>). [tfs_idx = 0]
DEBUG            0: TemplatedFileSlice(slice_type='templated', source_slice=slice(0, 31, None), templated_slice=slice(0, 31, None))
DEBUG           Contained templated slice.
INFO       Lexed segments: ['{', '{', ' ', '"SELECT \'lorem\' AS text;"', ' ', '}', '}', '']
INFO       Parse Rendered. Parsing Variant 0
INFO       Root Match:
Match (None): slice(0, 0, None)
INFO
###
#
# Parsed Tree:
#
###
INFO
[L:  1, P:  1]      |file:
[L:  1, P:  1]      |    unparsable:                                               !! Expected: "<Delimited: [<Ref: 'StatementSegment'>]>"
[L:  1, P:  1]      |        start_curly_bracket:                                  '{'
[L:  1, P:  1]      |        start_curly_bracket:                                  '{'
[L:  1, P:  1]      |        whitespace:                                           ' '
[L:  1, P:  1]      |        double_quote:                                         '"SELECT \'lorem\' AS text;"'
[L:  1, P:  1]      |        whitespace:                                           ' '
[L:  1, P:  1]      |        end_curly_bracket:                                    '}'
[L:  1, P:  1]      |        end_curly_bracket:                                    '}'
[L:  1, P: 32]      |    [META] end_of_file:

INFO       Found unparsable segment...
INFO       [L:  1, P:  1]      |unparsable:                                                   !! Expected: "<Delimited: [<Ref: 'StatementSegment'>]>"
[L:  1, P:  1]      |    start_curly_bracket:                                      '{'
[L:  1, P:  1]      |    start_curly_bracket:                                      '{'
[L:  1, P:  1]      |    whitespace:                                               ' '
[L:  1, P:  1]      |    double_quote:                                             '"SELECT \'lorem\' AS text;"'
[L:  1, P:  1]      |    whitespace:                                               ' '
[L:  1, P:  1]      |    end_curly_bracket:                                        '}'
[L:  1, P:  1]      |    end_curly_bracket:                                        '}'

INFO       Parse Rendered. Variant 0. Lex in 0.01600000006146729. Parse in 0.0.
INFO       lint_parsed - linting root variant (src\models\marts\facts\tmp.sql)
== [src\models\marts\facts\tmp.sql] LINTING (AL01, AL02, AL03, AL04, AL05, AL06, AL08, AL09, AM01, AM02, AM03, AM04, AM05, AM06, AM07, CP01, CP02, CP03, CP04, CP05, CV01, CV02, CV03, CV04, CV05, CV06, CV07, CV08, CV09, CV10, CV11, JJ01, LT01, LT02, LT03, LT04, LT06, LT07, LT08, LT09, LT10, LT11, LT13, RF02, RF03, RF04, RF05, RF06, ST01, ST02, ST03, ST04, ST05, ST07, ST08, ST09, TQ01)
INFO       

Entering linter phase main, loop 1/1

DEBUG      [JJ01] Tag found @ source index 0: '{{ "SELECT \'lorem\' AS text;" }}'
DEBUG      [JJ01] Tag string segments: '{{' | ' ' | '"SELECT \'lorem\' AS text;"' | ' ' | '}}' @ 0 + 0
DEBUG      * Respacing: '' @ None
DEBUG          Inline case. Constraints: single <-> single.
DEBUG          Inserting Single Whitespace.
DEBUG          Not Detected existing fix. Creating new
DEBUG          Modified result buffer: [LintResult(Expected single whitespace between start curly bracket and start curly bracket.: <CodeSegment: ([L:  1, P:  1]) '{'>+1F)]
DEBUG          New Results: [LintResult(Expected single whitespace between start curly bracket and start curly bracket.: <CodeSegment: ([L:  1, P:  1]) '{'>+1F)]
DEBUG      * Respacing: ' ' @ [L:  1, P:  1]
DEBUG          Inline case. Constraints: single <-> single.
DEBUG      * Respacing: ' ' @ [L:  1, P:  1]
DEBUG          Inline case. Constraints: single <-> single.
DEBUG      * Respacing: '' @ None
DEBUG          Inline case. Constraints: single <-> single.
DEBUG          Inserting Single Whitespace.
DEBUG          Not Detected existing fix. Creating new
DEBUG          Modified result buffer: [LintResult(Expected single whitespace between start curly bracket and start curly bracket.: <CodeSegment: ([L:  1, P:  1]) '{'>+1F), LintResult(Expected single whitespace between end curly bracket and end curly bracket.: <CodeSegment: ([L:  1, P:  1]) '}'>+1F)]
DEBUG          New Results: [LintResult(Expected single whitespace between start curly bracket and start curly bracket.: <CodeSegment: ([L:  1, P:  1]) '{'>+1F), LintResult(Expected single whitespace between end curly bracket and end curly bracket.: <CodeSegment: ([L:  1, P:  1]) '}'>+1F)]
DEBUG      * Respacing: '' @ None
INFO             * Discarding fixes that touch templated code: [<LintFix: create_after start_curly_bracket@[L:  1, P:  1] create:' '>]
INFO       Fix skipped due to parent of anchor not passing filter: [<FileSegment: ([L:  1, P:  1])>, <UnparsableSegment: ([L: 
 1, P:  1])>]
INFO             * Discarding fixes that touch templated code: [<LintFix: create_after end_curly_bracket@[L:  1, P:  1] create:' '>]
INFO       Fix skipped due to parent of anchor not passing filter: [<FileSegment: ([L:  1, P:  1])>, <UnparsableSegment: ([L: 
 1, P:  1])>]
INFO       # Evaluating indents.
DEBUG      # Revise skipped source lines.
DEBUG      # Revise templated lines.
DEBUG        Sorted Group UUIDs: []
DEBUG      # Revise comment lines.
DEBUG      # Evaluate lines for indentation.
INFO
###
#
# Fixed Tree:
#
###
INFO
[L:  1, P:  1]      |file:
[L:  1, P:  1]      |    unparsable:                                               !! Expected: "<Delimited: [<Ref: 'StatementSegment'>]>"
[L:  1, P:  1]      |        start_curly_bracket:                                  '{'
[L:  1, P:  1]      |        start_curly_bracket:                                  '{'
[L:  1, P:  1]      |        whitespace:                                           ' '
[L:  1, P:  1]      |        double_quote:                                         '"SELECT \'lorem\' AS text;"'
[L:  1, P:  1]      |        whitespace:                                           ' '
[L:  1, P:  1]      |        end_curly_bracket:                                    '}'
[L:  1, P:  1]      |        end_curly_bracket:                                    '}'
[L:  1, P: 32]      |    [META] end_of_file:

== [src\models\marts\facts\tmp.sql] FAIL
L:   1 | P:   1 |  PRS | Line 1, Position 1: Found unparsable section: '{{
                       | "SELECT \'lorem\' AS text;" }}'
WARNING: Parsing errors found and dialect is set to 'databricks'. Have you configured your dialect correctly?
==== summary ====
files:             1 violations:        1
clean files:       0 unclean files:     1
avg per file:   1.00 unclean rate:   100%
status:         FAIL
All Finished πŸ“œ πŸŽ‰!

With a ref macro

(.venv) D:\path\to\project>sqlfluff lint --templater dbt src\models\marts\facts\tmp.sql -vvvvvv
==== sqlfluff ====
sqlfluff:                3.2.5 python:                 3.11.9
implementation:        cpython verbosity:                   6
dialect:            databricks templater:                 dbt
dbt:                 =1.9.0-b2
rules:                                all
== Raw Config:
core:
    dialect:            databricks
    disable_noqa:       False
    encoding:           autodetect
    exclude_rules:      L016,L031,L034,L026,L009
    fix_even_unparsable:False
    ignore:             []
    ignore_templated_areas:True
    large_file_skip_byte_limit:0
    large_file_skip_char_limit:0
    max_line_length:    80
    nocolor:            False
    output_line_length: 80
    processes:          1
    render_variant_limit:1
    rules:              all
    runaway_limit:      10
    sql_file_exts:      .sql,.sql.j2,.dml,.ddl
    templater:          dbt
    verbose:            6
    warn_unused_ignores:False
    warnings:           []
indentation:        
    allow_implicit_indents:True
    ignore_comment_lines:False
    indent_unit:        space
    indented_ctes:      False
    indented_joins:     False
    indented_on_contents:True
    indented_then:      True
    indented_then_contents:True
    indented_using_on:  True
    skip_indentation_in:script_content      
    tab_space_size:     2
    template_blocks_indent:True
    trailing_comments:  before
layout:
    type:
        alias_expression:   
            align_scope:        bracketed
            align_within:       select_clause
            spacing_before:     align
        array_accessor:     
            spacing_before:     touch:inline
        array_type:
            spacing_within:     touch:inline
        assignment_operator:
            line_position:      leading
            spacing_within:     touch
        binary_operator:    
            line_position:      leading
            spacing_within:     touch
        bracketed_arguments:
            spacing_before:     touch:inline
        casting_operator:   
            spacing_after:      touch:inline
            spacing_before:     touch
        colon:
            spacing_before:     touch
        colon_delimiter:    
            spacing_after:      touch
            spacing_before:     touch
        comma:
            line_position:      trailing
            spacing_before:     touch
        comment:
            spacing_after:      any
            spacing_before:     any
        common_table_expression:
            spacing_within:     single:inline
        comparison_operator:
            line_position:      leading
            spacing_within:     touch
        dot:
            spacing_after:      touch
            spacing_before:     touch
        end_angle_bracket:  
            spacing_before:     touch
        end_bracket:        
            spacing_before:     touch
        end_of_file:        
            spacing_before:     touch
        end_square_bracket: 
            spacing_before:     touch
        from_clause:        
            line_position:      alone
        function_contents:  
            spacing_before:     touch:inline
        function_name:      
            spacing_within:     touch:inline
        function_parameter_list:
            spacing_before:     touch:inline
        groupby_clause:     
            line_position:      alone
        having_clause:      
            line_position:      alone
        join_clause:        
            line_position:      alone
        limit_clause:       
            line_position:      alone
        match_condition:    
            spacing_within:     touch:inline
        numeric_literal:    
            spacing_within:     touch:inline
        object_reference:   
            spacing_within:     touch:inline
        orderby_clause:     
            line_position:      leading
        path_segment:       
            spacing_within:     touch
        pattern_expression: 
            spacing_within:     any
        placeholder:        
            spacing_after:      any
            spacing_before:     any
        select_clause:      
            line_position:      alone
        semi_structured_expression:
            spacing_before:     touch:inline
            spacing_within:     touch:inline
        set_operator:       
            line_position:      alone:strict
        sign_indicator:     
            spacing_after:      touch:inline
        sized_array_type:   
            spacing_within:     touch
        slash:
            spacing_after:      any
            spacing_before:     any
        slice:
            spacing_after:      touch
            spacing_before:     touch
        sql_conf_option:    
            spacing_within:     touch
        sqlcmd_operator:    
            spacing_before:     touch
        start_angle_bracket:
            spacing_after:      touch
        start_bracket:      
            spacing_after:      touch
        start_square_bracket:
            spacing_after:      touch
        statement_terminator:
            line_position:      trailing
            spacing_before:     touch
        struct_type:        
            spacing_within:     touch:inline
        template_loop:      
            spacing_after:      any
            spacing_before:     any
        tilde:
            spacing_after:      touch:inline
        typed_array_literal:
            spacing_within:     touch
        typed_struct_literal:
            spacing_within:     touch
        where_clause:       
            line_position:      alone
rules:
    allow_scalar:       True
    single_table_references:consistent
    unquoted_identifiers_policy:all
    aliasing.column:    
        aliasing:           explicit
    aliasing.forbid:    
        force_enable:       False
    aliasing.length:    
        min_alias_length:   4
    aliasing.table:     
        aliasing:           explicit
    aliasing.unused:    
        alias_case_check:   dialect
    ambiguous.column_references:
        group_by_and_order_by_style:consistent
    ambiguous.join:     
        fully_qualify_join_types:inner
    capitalisation.functions:
        extended_capitalisation_policy:upper
    capitalisation.identifiers:
        extended_capitalisation_policy:lower
    capitalisation.keywords:
        capitalisation_policy:upper
    capitalisation.literals:
        capitalisation_policy:upper
    capitalisation.types:
        extended_capitalisation_policy:upper
    convention.blocked_words:
        match_source:       False
    convention.casting_style:
        preferred_type_casting_style:consistent
    convention.count_rows:
        prefer_count_0:     False
        prefer_count_1:     False
    convention.not_equal:
        preferred_not_equal_style:consistent
    convention.quoted_literals:
        force_enable:       False
        preferred_quoted_literal_style:consistent
    convention.select_trailing_comma:
        select_clause_trailing_comma:forbid
    convention.terminator:
        multiline_newline:  False
        require_final_semicolon:False
    layout.long_lines:  
        ignore_comment_clauses:False
        ignore_comment_lines:False
    layout.select_targets:
        wildcard_policy:    single
    references.consistent:
        force_enable:       False
    references.from:    
        force_enable:       False
    references.keywords:
        unquoted_identifiers_policy:aliases
    references.qualification:
    references.quoting: 
        case_sensitive:     True
        prefer_quoted_identifiers:False
        prefer_quoted_keywords:False
    references.special_chars:
        additional_allowed_characters:['.','(',')','-','<=>']
        allow_space_in_identifier:True
        quoted_identifiers_policy:all
        unquoted_identifiers_policy:all
    structure.join_condition_order:
        preferred_first_table_in_join_clause:earlier
    structure.subquery: 
        forbid_subquery_in: join
templater:
    unwrap_wrapped_queries:True
    dbt:
        project_dir:        D:\path\to\project\./
    jinja:
        apply_dbt_builtins: True
        library_path:       D:\path\to\project\dbt_packages
        load_macros_from_path:D:\path\to\project\./src/macros/

==== readout ====

=== [dbt templater] Sorting Nodes...
INFO       Rendering String [dbt] (src\models\marts\facts\tmp.sql)
=== [dbt templater] Compiling dbt project...
=== [dbt templater] Project Compiled.
DEBUG      _find_node for path 'D:\\path\\to\\model\\tmp.sql' returned object of type <class 'dbt.contracts.graph.nodes.ModelNode'>.
DEBUG          Trailing newline count in source dbt model: 0
DEBUG          Raw SQL before compile: "SELECT * FROM {{ ref('int_user_joined') }}"
DEBUG          Node raw SQL: "SELECT * FROM {{ ref('int_user_joined') }}"
DEBUG          Node compiled SQL: 'SELECT * FROM `catalog_name`.`schema_name`.`int_user_joined`'
INFO       Slicing File Template
DEBUG          Raw String: "SELECT * FROM {{ ref('int_user_joined') }}"
INFO       Rendered 1 variants
INFO       Parse Rendered. Lexing Variant 0
INFO       LEXING RAW (D:\path\to\model\tmp.sql)
INFO       Elements to Segments.
DEBUG        0: TemplateElement(raw='SELECT', template_slice=slice(0, 6, None), matcher=<RegexLexer: word>). [tfs_idx = 0]    
DEBUG            0: TemplatedFileSlice(slice_type='literal', source_slice=slice(0, 14, None), templated_slice=slice(0, 14, None))
DEBUG           Consuming whole from literal. Existing Consumed: 0
DEBUG        1: TemplateElement(raw=' ', template_slice=slice(6, 7, None), matcher=<RegexLexer: whitespace>). [tfs_idx = 0]   
DEBUG            0: TemplatedFileSlice(slice_type='literal', source_slice=slice(0, 14, None), templated_slice=slice(0, 14, None))
DEBUG           Consuming whole from literal. Existing Consumed: 0
DEBUG        2: TemplateElement(raw='*', template_slice=slice(7, 8, None), matcher=<StringLexer: star>). [tfs_idx = 0]        
DEBUG            0: TemplatedFileSlice(slice_type='literal', source_slice=slice(0, 14, None), templated_slice=slice(0, 14, None))
DEBUG           Consuming whole from literal. Existing Consumed: 0
DEBUG        3: TemplateElement(raw=' ', template_slice=slice(8, 9, None), matcher=<RegexLexer: whitespace>). [tfs_idx = 0]   
DEBUG            0: TemplatedFileSlice(slice_type='literal', source_slice=slice(0, 14, None), templated_slice=slice(0, 14, None))
DEBUG           Consuming whole from literal. Existing Consumed: 0
DEBUG        4: TemplateElement(raw='FROM', template_slice=slice(9, 13, None), matcher=<RegexLexer: word>). [tfs_idx = 0]     
DEBUG            0: TemplatedFileSlice(slice_type='literal', source_slice=slice(0, 14, None), templated_slice=slice(0, 14, None))
DEBUG           Consuming whole from literal. Existing Consumed: 0
DEBUG        5: TemplateElement(raw=' ', template_slice=slice(13, 14, None), matcher=<RegexLexer: whitespace>). [tfs_idx = 0] 
DEBUG            0: TemplatedFileSlice(slice_type='literal', source_slice=slice(0, 14, None), templated_slice=slice(0, 14, None))
DEBUG           Consuming whole from literal. Existing Consumed: 0
DEBUG        6: TemplateElement(raw='{', template_slice=slice(14, 15, None), matcher=<StringLexer: start_curly_bracket>). [tfs_idx = 1]
DEBUG            1: TemplatedFileSlice(slice_type='templated', source_slice=slice(14, 42, None), templated_slice=slice(14, 42, None))
DEBUG           Contained templated slice.
DEBUG        7: TemplateElement(raw='{', template_slice=slice(15, 16, None), matcher=<StringLexer: start_curly_bracket>). [tfs_idx = 1]
DEBUG            1: TemplatedFileSlice(slice_type='templated', source_slice=slice(14, 42, None), templated_slice=slice(14, 42, None))
DEBUG           Contained templated slice.
DEBUG        8: TemplateElement(raw=' ', template_slice=slice(16, 17, None), matcher=<RegexLexer: whitespace>). [tfs_idx = 1] 
DEBUG            1: TemplatedFileSlice(slice_type='templated', source_slice=slice(14, 42, None), templated_slice=slice(14, 42, None))
DEBUG           Contained templated slice.
DEBUG        9: TemplateElement(raw='ref', template_slice=slice(17, 20, None), matcher=<RegexLexer: word>). [tfs_idx = 1]
DEBUG            1: TemplatedFileSlice(slice_type='templated', source_slice=slice(14, 42, None), templated_slice=slice(14, 42, None))
DEBUG           Contained templated slice.
DEBUG        10: TemplateElement(raw='(', template_slice=slice(20, 21, None), matcher=<StringLexer: start_bracket>). [tfs_idx 
= 1]
DEBUG            1: TemplatedFileSlice(slice_type='templated', source_slice=slice(14, 42, None), templated_slice=slice(14, 42, None))
DEBUG           Contained templated slice.
DEBUG        11: TemplateElement(raw="'int_user_joined'", template_slice=slice(21, 38, None), matcher=<RegexLexer: single_quote>). [tfs_idx = 1]
DEBUG            1: TemplatedFileSlice(slice_type='templated', source_slice=slice(14, 42, None), templated_slice=slice(14, 42, None))
DEBUG           Contained templated slice.
DEBUG        12: TemplateElement(raw=')', template_slice=slice(38, 39, None), matcher=<StringLexer: end_bracket>). [tfs_idx = 
1]
DEBUG            1: TemplatedFileSlice(slice_type='templated', source_slice=slice(14, 42, None), templated_slice=slice(14, 42, None))
DEBUG           Contained templated slice.
DEBUG        13: TemplateElement(raw=' ', template_slice=slice(39, 40, None), matcher=<RegexLexer: whitespace>). [tfs_idx = 1]DEBUG            1: TemplatedFileSlice(slice_type='templated', source_slice=slice(14, 42, None), templated_slice=slice(14, 42, None))
DEBUG           Contained templated slice.
DEBUG        14: TemplateElement(raw='}', template_slice=slice(40, 41, None), matcher=<StringLexer: end_curly_bracket>). [tfs_idx = 1]
DEBUG            1: TemplatedFileSlice(slice_type='templated', source_slice=slice(14, 42, None), templated_slice=slice(14, 42, None))
DEBUG           Contained templated slice.
DEBUG        15: TemplateElement(raw='}', template_slice=slice(41, 42, None), matcher=<StringLexer: end_curly_bracket>). [tfs_idx = 1]
DEBUG            1: TemplatedFileSlice(slice_type='templated', source_slice=slice(14, 42, None), templated_slice=slice(14, 42, None))
DEBUG           Contained templated slice.
INFO       Lexed segments: ['SELECT', ' ', '*', ' ', 'FROM', ' ', '{', '{', ' ', 'ref', '(', "'int_user_joined'", ')', ' ', '}', '}', '']
INFO       Parse Rendered. Parsing Variant 0
INFO       Root Match:
Match (<class 'sqlfluff.dialects.dialect_databricks.StatementSegment'>): slice(0, 16, None)
  +Match (<class 'sqlfluff.dialects.dialect_sparksql.SelectStatementSegment'>): slice(0, 16, None)
    +Match (<class 'sqlfluff.dialects.dialect_sparksql.SelectClauseSegment'>): slice(0, 3, None)
      +2: <class 'sqlfluff.core.parser.segments.meta.Indent'>
      +3: <class 'sqlfluff.core.parser.segments.meta.Dedent'>
      +Match (<class 'sqlfluff.core.parser.segments.keyword.KeywordSegment'>): slice(0, 1, None)
        -instance_types: ('keyword',)
      +Match (<class 'sqlfluff.dialects.dialect_ansi.SelectClauseElementSegment'>): slice(2, 3, None)
        +Match (<class 'sqlfluff.dialects.dialect_sparksql.WildcardExpressionSegment'>): slice(2, 3, None)
          +Match (<class 'sqlfluff.dialects.dialect_ansi.WildcardIdentifierSegment'>): slice(2, 3, None)
            +Match (<class 'sqlfluff.core.parser.segments.common.SymbolSegment'>): slice(2, 3, None)
              -instance_types: ('star',)
    +Match (<class 'sqlfluff.core.parser.segments.base.UnparsableSegment'>): slice(4, 16, None)
      -expected: 'Nothing here.'
INFO
###
#
# Parsed Tree:
#
###
INFO
[L:  1, P:  1]      |file:
[L:  1, P:  1]      |    statement:
[L:  1, P:  1]      |        select_statement:
[L:  1, P:  1]      |            select_clause:
[L:  1, P:  1]      |                keyword:                                      'SELECT'
[L:  1, P:  7]      |                whitespace:                                   ' '
[L:  1, P:  8]      |                [META] indent:
[L:  1, P:  8]      |                select_clause_element:
[L:  1, P:  8]      |                    wildcard_expression:
[L:  1, P:  8]      |                        wildcard_identifier:
[L:  1, P:  8]      |                            star:                             '*'
[L:  1, P:  9]      |                [META] dedent:
[L:  1, P:  9]      |            whitespace:                                       ' '
[L:  1, P: 10]      |            unparsable:                                       !! Expected: 'Nothing here.'
[L:  1, P: 10]      |                word:                                         'FROM'
[L:  1, P: 14]      |                whitespace:                                   ' '
[L:  1, P: 15]      |                start_curly_bracket:                          '{'
[L:  1, P: 15]      |                start_curly_bracket:                          '{'
[L:  1, P: 15]      |                whitespace:                                   ' '
[L:  1, P: 15]      |                word:                                         'ref'
[L:  1, P: 15]      |                start_bracket:                                '('
[L:  1, P: 15]      |                single_quote:                                 "'int_user_joined'"
[L:  1, P: 15]      |                end_bracket:                                  ')'
[L:  1, P: 15]      |                whitespace:                                   ' '
[L:  1, P: 15]      |                end_curly_bracket:                            '}'
[L:  1, P: 15]      |                end_curly_bracket:                            '}'
[L:  1, P: 43]      |    [META] end_of_file:

INFO       Found unparsable segment...
INFO       [L:  1, P: 10]      |unparsable:                                                   !! Expected: 'Nothing here.'    
[L:  1, P: 10]      |    word:                                                     'FROM'
[L:  1, P: 14]      |    whitespace:                                               ' '
[L:  1, P: 15]      |    start_curly_bracket:                                      '{'
[L:  1, P: 15]      |    start_curly_bracket:                                      '{'
[L:  1, P: 15]      |    whitespace:                                               ' '
[L:  1, P: 15]      |    word:                                                     'ref'
[L:  1, P: 15]      |    start_bracket:                                            '('
[L:  1, P: 15]      |    single_quote:                                             "'int_user_joined'"
[L:  1, P: 15]      |    end_bracket:                                              ')'
[L:  1, P: 15]      |    whitespace:                                               ' '
[L:  1, P: 15]      |    end_curly_bracket:                                        '}'
[L:  1, P: 15]      |    end_curly_bracket:                                        '}'

INFO       Parse Rendered. Variant 0. Lex in 0.014999999897554517. Parse in 0.01600000006146729.
INFO       lint_parsed - linting root variant (src\models\marts\facts\tmp.sql)
== [src\models\marts\facts\tmp.sql] LINTING (AL01, AL02, AL03, AL04, AL05, AL06, AL08, AL09, AM01, AM02, AM03, AM04, AM05, AM06, AM07, CP01, CP02, CP03, CP04, CP05, CV01, CV02, CV03, CV04, CV05, CV06, CV07, CV08, CV09, CV10, CV11, JJ01, LT01, LT02, LT03, LT04, LT06, LT07, LT08, LT09, LT10, LT11, LT13, RF02, RF03, RF04, RF05, RF06, ST01, ST02, ST03, ST04, ST05, ST07, ST08, ST09, TQ01)
INFO       

Entering linter phase main, loop 1/1

DEBUG      [AM04] Analyzing query: SELECT * FROM {{ ref('int_user_joined') }}
DEBUG      [AM04] Query target "SELECT * FROM {{ ref('int_user_joined') }}" has no targets. Generating warning.
INFO       [AM04] !! Violation Found: 'Query produces an unknown number of result columns.'
INFO       [CP01] _handle_segment: <KeywordSegment: ([L:  1, P:  1]) 'SELECT'>, keyword
DEBUG      [CP01] Selected 'capitalisation_policy': 'upper' from options ['upper', 'lower', 'capitalise']
DEBUG      [CP01] Refuted cases after segment 'SELECT': {'pascal', 'snake', 'camel', 'capitalise', 'lower'}
DEBUG      [CP01] Consistent capitalization upper, returning with memory: {'refuted_cases': {'pascal', 'snake', 'camel', 'capitalise', 'lower'}}
DEBUG      [JJ01] Tag found @ source index 14: "{{ ref('int_user_joined') }}"
DEBUG      [JJ01] Tag string segments: '{{' | ' ' | "ref('int_user_joined')" | ' ' | '}}' @ 14 + 0
DEBUG      * Respacing: ' ' @ [L:  1, P:  7]
DEBUG          Inline case. Constraints: single <-> single.
DEBUG      * Respacing: ' ' @ [L:  1, P:  9]
DEBUG          Inline case. Constraints: single <-> single.
DEBUG      * Respacing: ' ' @ [L:  1, P: 14]
DEBUG          Inline case. Constraints: single <-> single.
DEBUG      * Respacing: '' @ None
DEBUG          Inline case. Constraints: single <-> single.
DEBUG          Inserting Single Whitespace.
DEBUG          Not Detected existing fix. Creating new
DEBUG          Modified result buffer: [LintResult(Expected single whitespace between start curly bracket and start curly bracket.: <CodeSegment: ([L:  1, P: 15]) '{'>+1F)]
DEBUG          New Results: [LintResult(Expected single whitespace between start curly bracket and start curly bracket.: <CodeSegment: ([L:  1, P: 15]) '{'>+1F)]
DEBUG      * Respacing: ' ' @ [L:  1, P: 15]
DEBUG          Inline case. Constraints: single <-> single.
DEBUG      * Respacing: '' @ None
DEBUG          Inline case. Constraints: single <-> single.
DEBUG          Inserting Single Whitespace.
DEBUG          Not Detected existing fix. Creating new
DEBUG          Modified result buffer: [LintResult(Expected single whitespace between start curly bracket and start curly bracket.: <CodeSegment: ([L:  1, P: 15]) '{'>+1F), LintResult(Expected single whitespace between word and start bracket.: <CodeSegment: ([L:  1, P: 15]) '('>+1F)]
DEBUG          New Results: [LintResult(Expected single whitespace between start curly bracket and start curly bracket.: <CodeSegment: ([L:  1, P: 15]) '{'>+1F), LintResult(Expected single whitespace between word and start bracket.: <CodeSegment: ([L: 
 1, P: 15]) '('>+1F)]
DEBUG      * Respacing: '' @ None
DEBUG          Inline case. Constraints: touch <-> single.
DEBUG          New Results: [LintResult(Expected single whitespace between start curly bracket and start curly bracket.: <CodeSegment: ([L:  1, P: 15]) '{'>+1F), LintResult(Expected single whitespace between word and start bracket.: <CodeSegment: ([L: 
 1, P: 15]) '('>+1F)]
DEBUG      * Respacing: '' @ None
DEBUG          Inline case. Constraints: single <-> touch.
DEBUG          New Results: [LintResult(Expected single whitespace between start curly bracket and start curly bracket.: <CodeSegment: ([L:  1, P: 15]) '{'>+1F), LintResult(Expected single whitespace between word and start bracket.: <CodeSegment: ([L: 
 1, P: 15]) '('>+1F)]
DEBUG      * Respacing: ' ' @ [L:  1, P: 15]
DEBUG          Inline case. Constraints: single <-> single.
DEBUG      * Respacing: '' @ None
DEBUG          Inline case. Constraints: single <-> single.
DEBUG          Inserting Single Whitespace.
DEBUG          Not Detected existing fix. Creating new
DEBUG          Modified result buffer: [LintResult(Expected single whitespace between start curly bracket and start curly bracket.: <CodeSegment: ([L:  1, P: 15]) '{'>+1F), LintResult(Expected single whitespace between word and start bracket.: <CodeSegment: ([L:  1, P: 15]) '('>+1F), LintResult(Expected single whitespace between end curly bracket and end curly bracket.: <CodeSegment: ([L:  1, P: 15]) '}'>+1F)]
DEBUG          New Results: [LintResult(Expected single whitespace between start curly bracket and start curly bracket.: <CodeSegment: ([L:  1, P: 15]) '{'>+1F), LintResult(Expected single whitespace between word and start bracket.: <CodeSegment: ([L: 
 1, P: 15]) '('>+1F), LintResult(Expected single whitespace between end curly bracket and end curly bracket.: <CodeSegment: ([L:  1, P: 15]) '}'>+1F)]
DEBUG      * Respacing: '' @ None
INFO             * Discarding fixes that touch templated code: [<LintFix: create_after start_curly_bracket@[L:  1, P: 15] create:' '>]
INFO       Fix skipped due to parent of anchor not passing filter: [<FileSegment: ([L:  1, P:  1])>, <StatementSegment: ([L:  
1, P:  1])>, <SelectStatementSegment: ([L:  1, P:  1])>, <UnparsableSegment: ([L:  1, P: 10])>]
INFO             * Discarding fixes that touch templated code: [<LintFix: create_after word@[L:  1, P: 15] create:' '>]       
INFO       Fix skipped due to parent of anchor not passing filter: [<FileSegment: ([L:  1, P:  1])>, <StatementSegment: ([L:  
1, P:  1])>, <SelectStatementSegment: ([L:  1, P:  1])>, <UnparsableSegment: ([L:  1, P: 10])>]
INFO             * Discarding fixes that touch templated code: [<LintFix: create_after end_curly_bracket@[L:  1, P: 15] create:' '>]
INFO       Fix skipped due to parent of anchor not passing filter: [<FileSegment: ([L:  1, P:  1])>, <StatementSegment: ([L:  
1, P:  1])>, <SelectStatementSegment: ([L:  1, P:  1])>, <UnparsableSegment: ([L:  1, P: 10])>]
INFO       # Evaluating indents.
DEBUG      # Revise skipped source lines.
DEBUG      # Revise templated lines.
DEBUG        Sorted Group UUIDs: []
DEBUG      # Revise comment lines.
DEBUG      # Evaluate lines for indentation.
INFO       ## Evaluate Rendered Line #1 [source line #1]. idx=1:21.
DEBUG        Line Content: ["' '", "'*'", "' '", "'FROM'", "' '", "'{'", "''", "'{'", "' '", "'ref'", "''", "'('", "''", '"\'int_user_joined\'"', "''", "')'", "' '", "'}'", "''", "'}'"]
DEBUG        Indent Line: IndentLine(iib=0, ipts=[iPt@1(1, 0, 0, None, False, ()), iPt@3(-1, -1, 1, None, False, (1,)), iPt@21(0, 0, 0, None, False, ())])
DEBUG        Forced Indents: []
DEBUG        Imbalanced Indent Locs: []
DEBUG          Desired Indent Calculation: IB: 0, RUI: [], UIL: (), iII: 1, iIT: 0. = 0
INFO       [LT09] Target at index 3 is already on a single line.
INFO
###
#
# Fixed Tree:
#
###
INFO
[L:  1, P:  1]      |file:
[L:  1, P:  1]      |    statement:
[L:  1, P:  1]      |        select_statement:
[L:  1, P:  1]      |            select_clause:
[L:  1, P:  1]      |                keyword:                                      'SELECT'
[L:  1, P:  7]      |                whitespace:                                   ' '
[L:  1, P:  8]      |                [META] indent:
[L:  1, P:  8]      |                select_clause_element:
[L:  1, P:  8]      |                    wildcard_expression:
[L:  1, P:  8]      |                        wildcard_identifier:
[L:  1, P:  8]      |                            star:                             '*'
[L:  1, P:  9]      |                [META] dedent:
[L:  1, P:  9]      |            whitespace:                                       ' '
[L:  1, P: 10]      |            unparsable:                                       !! Expected: 'Nothing here.'
[L:  1, P: 10]      |                word:                                         'FROM'
[L:  1, P: 14]      |                whitespace:                                   ' '
[L:  1, P: 15]      |                start_curly_bracket:                          '{'
[L:  1, P: 15]      |                start_curly_bracket:                          '{'
[L:  1, P: 15]      |                whitespace:                                   ' '
[L:  1, P: 15]      |                word:                                         'ref'
[L:  1, P: 15]      |                start_bracket:                                '('
[L:  1, P: 15]      |                single_quote:                                 "'int_user_joined'"
[L:  1, P: 15]      |                end_bracket:                                  ')'
[L:  1, P: 15]      |                whitespace:                                   ' '
[L:  1, P: 15]      |                end_curly_bracket:                            '}'
[L:  1, P: 15]      |                end_curly_bracket:                            '}'
[L:  1, P: 43]      |    [META] end_of_file:

== [src\models\marts\facts\tmp.sql] FAIL
L:   1 | P:  10 |  PRS | Line 1, Position 10: Found unparsable section: "FROM {{
                       | ref('int_user_joined') }}"
WARNING: Parsing errors found and dialect is set to 'databricks'. Have you configured your dialect correctly?
==== summary ====
files:             1 violations:        1
clean files:       0 unclean files:     1
avg per file:   1.00 unclean rate:   100%
status:         FAIL
All Finished πŸ“œ πŸŽ‰!