From d3495a09083b1e6a746fff8444f0bbb887d6ac8b Mon Sep 17 00:00:00 2001 From: Dharmisha Doshi Date: Sun, 19 Jan 2025 06:36:26 -0800 Subject: [PATCH] fix: Resolving syntax error while querying a feature view with column name starting with a number and BigQuery as data source (#4908) * Fixing issue https://github.com/feast-dev/feast/issues/4688 Signed-off-by: Dharmisha Doshi * Fixing issue https://github.com/feast-dev/feast/issues/4688 Signed-off-by: Dharmisha Doshi * Fixing issue https://github.com/feast-dev/feast/issues/4688 Signed-off-by: Dharmisha Doshi * resolving PEP 8 warnings Signed-off-by: Dharmisha Doshi * resolving linting issues Signed-off-by: Dharmisha Doshi --------- Signed-off-by: Dharmisha Doshi Co-authored-by: n0g0791 Co-authored-by: nishantgaurav-dev Co-authored-by: dharmishadoshi@gmail.com --- sdk/python/feast/infra/offline_stores/bigquery.py | 9 ++++++--- .../feast/infra/offline_stores/offline_utils.py | 12 +++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/sdk/python/feast/infra/offline_stores/bigquery.py b/sdk/python/feast/infra/offline_stores/bigquery.py index 23f80d79ff2..f0516b594ee 100644 --- a/sdk/python/feast/infra/offline_stores/bigquery.py +++ b/sdk/python/feast/infra/offline_stores/bigquery.py @@ -901,7 +901,10 @@ def arrow_schema_to_bq_schema(arrow_schema: pyarrow.Schema) -> List[SchemaField] {{ featureview.created_timestamp_column ~ ' as created_timestamp,' if featureview.created_timestamp_column else '' }} {{ featureview.entity_selections | join(', ')}}{% if featureview.entity_selections %},{% else %}{% endif %} {% for feature in featureview.features %} - {{ feature }} as {% if full_feature_names %}{{ featureview.name }}__{{featureview.field_mapping.get(feature, feature)}}{% else %}{{ featureview.field_mapping.get(feature, feature) }}{% endif %}{% if loop.last %}{% else %}, {% endif %} + {{ feature | backticks }} as {% if full_feature_names %} + {{ featureview.name }}__{{featureview.field_mapping.get(feature, feature)}}{% else %} + {{ featureview.field_mapping.get(feature, feature) | backticks }}{% endif %} + {% if loop.last %}{% else %}, {% endif %} {% endfor %} FROM {{ featureview.table_subquery }} WHERE {{ featureview.timestamp_field }} <= '{{ featureview.max_event_timestamp }}' @@ -995,14 +998,14 @@ def arrow_schema_to_bq_schema(arrow_schema: pyarrow.Schema) -> List[SchemaField] The entity_dataframe dataset being our source of truth here. */ -SELECT {{ final_output_feature_names | join(', ')}} +SELECT {{ final_output_feature_names | backticks | join(', ')}} FROM entity_dataframe {% for featureview in featureviews %} LEFT JOIN ( SELECT {{featureview.name}}__entity_row_unique_id {% for feature in featureview.features %} - ,{% if full_feature_names %}{{ featureview.name }}__{{featureview.field_mapping.get(feature, feature)}}{% else %}{{ featureview.field_mapping.get(feature, feature) }}{% endif %} + ,{% if full_feature_names %}{{ featureview.name }}__{{featureview.field_mapping.get(feature, feature)}}{% else %}{{ featureview.field_mapping.get(feature, feature) | backticks }}{% endif %} {% endfor %} FROM {{ featureview.name }}__cleaned ) USING ({{featureview.name}}__entity_row_unique_id) diff --git a/sdk/python/feast/infra/offline_stores/offline_utils.py b/sdk/python/feast/infra/offline_stores/offline_utils.py index 2d4fa268e40..2076f977acc 100644 --- a/sdk/python/feast/infra/offline_stores/offline_utils.py +++ b/sdk/python/feast/infra/offline_stores/offline_utils.py @@ -186,7 +186,9 @@ def build_point_in_time_query( full_feature_names: bool = False, ) -> str: """Build point-in-time query between each feature view table and the entity dataframe for Bigquery and Redshift""" - template = Environment(loader=BaseLoader()).from_string(source=query_template) + env = Environment(loader=BaseLoader()) + env.filters["backticks"] = enclose_in_backticks + template = env.from_string(source=query_template) final_output_feature_names = list(entity_df_columns) final_output_feature_names.extend( @@ -252,3 +254,11 @@ def get_pyarrow_schema_from_batch_source( column_names.append(column_name) return pa.schema(pa_schema), column_names + + +def enclose_in_backticks(value): + # Check if the input is a list + if isinstance(value, list): + return [f"`{v}`" for v in value] + else: + return f"`{value}`"