Skip to content

Commit

Permalink
feat(FIR-12466): Allow indexes on columns with spaces
Browse files Browse the repository at this point in the history
  • Loading branch information
ptiurin committed Sep 12, 2024
1 parent 624fbcb commit 6b0fb80
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
33 changes: 29 additions & 4 deletions dbt/adapters/firebolt/impl.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import re
import time
from dataclasses import dataclass
from datetime import datetime
from typing import Any, List, Mapping, Optional, Union

import agate
Expand Down Expand Up @@ -29,6 +28,14 @@
from dbt.adapters.firebolt.relation import FireboltRelation


def quote_columns(columns: Union[str, List[str]]) -> Union[str, List[str]]:
if isinstance(columns, str):
return f'"{columns}"'
return [
f'"{col}"' for col in columns if not (col.startswith('"') and col.endswith('"'))
]


@dataclass
class FireboltIndexConfig(dbtClassMixin):
index_type: str
Expand All @@ -38,6 +45,15 @@ class FireboltIndexConfig(dbtClassMixin):
dimension_column: Optional[Union[str, List[str]]] = None
aggregation: Optional[Union[str, List[str]]] = None

def __post_init__(self) -> None:
# quote unquoted columns
if self.join_columns:
self.join_columns = quote_columns(self.join_columns)
if self.key_columns:
self.key_columns = quote_columns(self.key_columns)
if self.dimension_column:
self.dimension_column = quote_columns(self.dimension_column)

def render_name(self, relation: FireboltRelation) -> str:
"""
Name an index according to the following format, joined by `_`:
Expand All @@ -46,22 +62,31 @@ def render_name(self, relation: FireboltRelation) -> str:
"""
if self.index_name:
return self.index_name
now_unix = str(int(time.mktime(datetime.utcnow().timetuple())))
now_unix = str(int(time.time()))
# If column_names is a list with > 1 members, join with _,
# otherwise do not. We were getting index names like
# join__idx__emf_customers__f_i_r_s_t___n_a_m_e__165093112.
column_names = self.key_columns or self.join_columns
spine_col = (
'_'.join(column_names) if isinstance(column_names, list) else column_names
)
# Additional hash to ensure uniqueness after spaces are removed
column_hash = str(hash(spine_col))[:5]
inputs = [
f'{self.index_type}_idx',
relation.identifier,
spine_col,
column_hash,
now_unix,
]
string = '__'.join([x for x in inputs if x is not None])
return string
index_name = '__'.join([x for x in inputs if x is not None])
if len(index_name) > 255:
# Firebolt index names must be <= 255 characters.
# If the index name is too long, hash it.
return f'{self.index_type}_idx_{hash(index_name)}'
# Remove any spaces or quotes from the index name.
index_name = index_name.replace(' ', '_').replace('"', '')
return index_name

@classmethod
def parse(cls, raw_index: Optional[Mapping]) -> Optional['FireboltIndexConfig']:
Expand Down
4 changes: 2 additions & 2 deletions dbt/include/firebolt/macros/relations/table/create.sql
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@
{%- if primary_index %}
primary INDEX {% if primary_index is iterable and primary_index is not string %}
{{ primary_index | join(', ') }}
"{{ primary_index | join('", "') }}"
{%- else -%}
{{ primary_index }}
"{{ primary_index }}"
{%- endif -%}
{%- endif -%}
Expand Down

0 comments on commit 6b0fb80

Please sign in to comment.