33from unittest .mock import MagicMock , patch
44
55import pandas as pd
6+ import sqlglot
67
78from feast .entity import Entity
8- from feast .feature_view import FeatureView , Field
9+ from feast .feature_view import FeatureView , FeatureViewProjection , Field
910from feast .infra .offline_stores .contrib .postgres_offline_store .postgres import (
1011 PostgreSQLOfflineStore ,
1112 PostgreSQLOfflineStoreConfig ,
1415 PostgreSQLSource ,
1516)
1617from feast .infra .offline_stores .offline_store import RetrievalJob
18+ from feast .on_demand_feature_view import OnDemandFeatureView
1719from feast .repo_config import RepoConfig
18- from feast .types import Float32
20+ from feast .types import Float32 , ValueType
1921
2022logging .basicConfig (level = logging .DEBUG )
2123logger = logging .getLogger (__name__ )
@@ -30,15 +32,7 @@ def test_pull_latest_from_table_with_nested_timestamp_or_query(mock_get_conn):
3032 project = "test_project" ,
3133 registry = "test_registry" ,
3234 provider = "local" ,
33- offline_store = PostgreSQLOfflineStoreConfig (
34- type = "postgres" ,
35- host = "localhost" ,
36- port = 5432 ,
37- database = "test_db" ,
38- db_schema = "public" ,
39- user = "test_user" ,
40- password = "test_password" ,
41- ),
35+ offline_store = _mock_offline_store_config (),
4236 )
4337
4438 test_data_source = PostgreSQLSource (
@@ -100,15 +94,7 @@ def test_pull_latest_from_table_without_nested_timestamp_or_query(mock_get_conn)
10094 project = "test_project" ,
10195 registry = "test_registry" ,
10296 provider = "local" ,
103- offline_store = PostgreSQLOfflineStoreConfig (
104- type = "postgres" ,
105- host = "localhost" ,
106- port = 5432 ,
107- database = "test_db" ,
108- db_schema = "public" ,
109- user = "test_user" ,
110- password = "test_password" ,
111- ),
97+ offline_store = _mock_offline_store_config (),
11298 )
11399
114100 test_data_source = PostgreSQLSource (
@@ -167,15 +153,7 @@ def test_pull_all_from_table_or_query(mock_get_conn):
167153 project = "test_project" ,
168154 registry = "test_registry" ,
169155 provider = "local" ,
170- offline_store = PostgreSQLOfflineStoreConfig (
171- type = "postgres" ,
172- host = "localhost" ,
173- port = 5432 ,
174- database = "test_db" ,
175- db_schema = "public" ,
176- user = "test_user" ,
177- password = "test_password" ,
178- ),
156+ offline_store = _mock_offline_store_config (),
179157 )
180158
181159 test_data_source = PostgreSQLSource (
@@ -239,15 +217,7 @@ def test_get_historical_features_entity_select_modes(
239217 project = "test_project" ,
240218 registry = "test_registry" ,
241219 provider = "local" ,
242- offline_store = PostgreSQLOfflineStoreConfig (
243- type = "postgres" ,
244- host = "localhost" ,
245- port = 5432 ,
246- database = "test_db" ,
247- db_schema = "public" ,
248- user = "test_user" ,
249- password = "test_password" ,
250- ),
220+ offline_store = _mock_offline_store_config (),
251221 )
252222
253223 test_data_source = PostgreSQLSource (
@@ -259,13 +229,7 @@ def test_get_historical_features_entity_select_modes(
259229
260230 test_feature_view = FeatureView (
261231 name = "test_feature_view" ,
262- entities = [
263- Entity (
264- name = "driver_id" ,
265- join_keys = ["driver_id" ],
266- description = "Driver ID" ,
267- )
268- ],
232+ entities = _mock_entity (),
269233 schema = [
270234 Field (name = "feature1" , dtype = Float32 ),
271235 ],
@@ -300,6 +264,9 @@ def test_get_historical_features_entity_select_modes(
300264 all the logic as the field to GROUP BY the data
301265*/""" )
302266
267+ sqlglot .parse (actual_query )
268+ assert True
269+
303270
304271@patch ("feast.infra.offline_stores.contrib.postgres_offline_store.postgres._get_conn" )
305272@patch (
@@ -345,13 +312,7 @@ def test_get_historical_features_entity_select_modes_embed_query(
345312
346313 test_feature_view = FeatureView (
347314 name = "test_feature_view" ,
348- entities = [
349- Entity (
350- name = "driver_id" ,
351- join_keys = ["driver_id" ],
352- description = "Driver ID" ,
353- )
354- ],
315+ entities = _mock_entity (),
355316 schema = [
356317 Field (name = "feature1" , dtype = Float32 ),
357318 ],
@@ -388,3 +349,103 @@ def test_get_historical_features_entity_select_modes_embed_query(
388349 assert actual_query .startswith ("""WITH
389350
390351 entity_query AS (""" )
352+
353+ # Verify the SQL is valid by parsing it
354+ sqlglot .parse (actual_query ) # This will raise ParseError if SQL is invalid
355+ assert True # If we get here, the SQL is valid
356+
357+
358+ @patch ("feast.infra.offline_stores.contrib.postgres_offline_store.postgres._get_conn" )
359+ @patch (
360+ "feast.infra.offline_stores.contrib.postgres_offline_store.postgres.df_to_postgres_table"
361+ )
362+ @patch (
363+ "feast.infra.offline_stores.contrib.postgres_offline_store.postgres.get_query_schema"
364+ )
365+ @patch ("feast.on_demand_feature_view.OnDemandFeatureView.get_requested_odfvs" )
366+ def test_get_historical_features_no_feature_view (
367+ mock_get_requested_odfvs ,
368+ mock_get_query_schema ,
369+ mock_df_to_postgres_table ,
370+ mock_get_conn ,
371+ ):
372+ mock_conn = MagicMock ()
373+ mock_get_conn .return_value .__enter__ .return_value = mock_conn
374+
375+ # Create a mock OnDemandFeatureView
376+ mock_odfv = MagicMock (spec = OnDemandFeatureView )
377+ mock_odfv .name = "test_odfv"
378+ mock_odfv .features = [Field (name = "feature1" , dtype = Float32 )]
379+ mock_odfv .projection = FeatureViewProjection (
380+ name = "test_odfv" ,
381+ name_alias = "test_odfv" ,
382+ features = [Field (name = "feature1" , dtype = Float32 )],
383+ desired_features = [],
384+ )
385+ mock_get_requested_odfvs .return_value = [mock_odfv ]
386+
387+ test_repo_config = RepoConfig (
388+ project = "test_project" ,
389+ registry = "test_registry" ,
390+ provider = "local" ,
391+ offline_store = _mock_offline_store_config (),
392+ )
393+
394+ test_data_source = PostgreSQLSource (
395+ name = "test_batch_source" ,
396+ description = "test_batch_source" ,
397+ table = "offline_store_database_name.offline_store_table_name" ,
398+ timestamp_field = "event_published_datetime_utc" ,
399+ )
400+
401+ test_feature_view = FeatureView (
402+ name = "test_feature_view" ,
403+ entities = _mock_entity (),
404+ schema = [
405+ Field (name = "feature1" , dtype = Float32 ),
406+ ],
407+ source = test_data_source ,
408+ )
409+
410+ mock_registry = MagicMock ()
411+ mock_registry .get_on_demand_feature_view .return_value = test_feature_view
412+ mock_registry .list_on_demand_feature_views .return_value = [mock_odfv ]
413+
414+ entity_df = pd .DataFrame (
415+ {"event_timestamp" : [datetime (2021 , 1 , 1 )], "driver_id" : [1 ]}
416+ )
417+
418+ retrieval_job = PostgreSQLOfflineStore .get_historical_features (
419+ config = test_repo_config ,
420+ feature_views = [],
421+ feature_refs = ["test_odfv:feature1" ],
422+ entity_df = entity_df ,
423+ registry = mock_registry ,
424+ project = "test_project" ,
425+ )
426+
427+ sqlglot .parse (retrieval_job .to_sql ().strip (), dialect = "postgres" )
428+ assert True
429+
430+
431+ def _mock_offline_store_config ():
432+ return PostgreSQLOfflineStoreConfig (
433+ type = "postgres" ,
434+ host = "localhost" ,
435+ port = 5432 ,
436+ database = "test_db" ,
437+ db_schema = "public" ,
438+ user = "test_user" ,
439+ password = "test_password" ,
440+ )
441+
442+
443+ def _mock_entity ():
444+ return [
445+ Entity (
446+ name = "driver_id" ,
447+ join_keys = ["driver_id" ],
448+ description = "Driver ID" ,
449+ value_type = ValueType .INT64 ,
450+ )
451+ ]
0 commit comments