diff --git a/go.mod b/go.mod index 50052a64c2..dc781e6fd1 100644 --- a/go.mod +++ b/go.mod @@ -55,6 +55,8 @@ require ( github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/gonuts/commander v0.1.0 // indirect + github.com/gonuts/flag v0.1.0 // indirect github.com/google/flatbuffers v2.0.8+incompatible // indirect github.com/klauspost/asmfmt v1.3.2 // indirect github.com/klauspost/compress v1.16.3 // indirect diff --git a/go.sum b/go.sum index 992c943199..8fc87c1d14 100644 --- a/go.sum +++ b/go.sum @@ -173,6 +173,10 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gonuts/commander v0.1.0 h1:EcDTiVw9oAVORFjQOEOuHQqcl6OXMyTgELocTq6zJ0I= +github.com/gonuts/commander v0.1.0/go.mod h1:qkb5mSlcWodYgo7vs8ulLnXhfinhZsZcm6+H/z1JjgY= +github.com/gonuts/flag v0.1.0 h1:fqMv/MZ+oNGu0i9gp0/IQ/ZaPIDoAZBOBaJoV7viCWM= +github.com/gonuts/flag v0.1.0/go.mod h1:ZTmTGtrSPejTo/SRNhCqwLTmiAgyBdCkLYhHrAoBdz4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/flatbuffers v2.0.5+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= diff --git a/sdk/python/feast/infra/registry/sql.py b/sdk/python/feast/infra/registry/sql.py index 80818acdac..a30b4996a0 100644 --- a/sdk/python/feast/infra/registry/sql.py +++ b/sdk/python/feast/infra/registry/sql.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import concurrent.futures import logging import threading @@ -919,6 +921,7 @@ def get_user_metadata( def proto(self) -> RegistryProto: r = RegistryProto() + # last_updated_timestamps = [] def process_project(project): @@ -1063,6 +1066,80 @@ def create_project_if_not_exists(self, project): if new_project: self._set_last_updated_metadata(update_datetime, project) + def search( + self, + name="", + application="", + owning_team="", + created_at=datetime.min, + updated_at=datetime.min, + online=False, + ) -> List[Union[FeatureView, ProjectMetadataModel]]: + """ + Search for feature views or projects based on the provided search + parameters. Since the SQL database stores only metadata and protos, we + have to pull all potentially matching objects and filter in memory. + """ + fv_list = [] + with self.engine.connect() as conn: + stmt = select(feature_views) + if name: + stmt = stmt.where(feature_views.c.feature_view_name == name) + + rows = conn.execute(stmt).all() + + if rows: + fv_list = [ + FeatureView.from_proto( + FeatureViewProto.FromString(row["feature_view_proto"]) + ) + for row in rows + ] + + fv_list = [ + view + for view in fv_list + if view.created_timestamp is None + or view.created_timestamp >= created_at + ] + + fv_list = [ + view + for view in fv_list + if view.last_updated_timestamp is None + or view.last_updated_timestamp >= updated_at + ] + + if owning_team: + fv_list = [ + view for view in fv_list if view.tags.get("team") == owning_team + ] + if application: + fv_list = [ + view + for view in fv_list + if view.tags.get("application") == application + ] + if online is not None: + fv_list = [view for view in fv_list if view.online == online] + + project_list = self.get_all_project_metadata() + + project_list = [ + project for project in project_list if project.project_name == name + ] + project_list = [ + project + for project in project_list + if project.last_updated_timestamp is None + or project.last_updated_timestamp >= updated_at + ] + + final_list: List[FeatureView | ProjectMetadataModel] = [] + final_list.extend(project_list) + final_list.extend(fv_list) + return final_list + def _delete_object( self, table: Table, diff --git a/sdk/python/requirements/py3.10-ci-requirements.txt b/sdk/python/requirements/py3.10-ci-requirements.txt index 0ef7d35489..df5e7fcd51 100644 --- a/sdk/python/requirements/py3.10-ci-requirements.txt +++ b/sdk/python/requirements/py3.10-ci-requirements.txt @@ -534,7 +534,7 @@ mypy-extensions==1.0.0 # mypy mypy-protobuf==3.1.0 # via eg-feast (setup.py) -mysqlclient==2.2.0 +mysqlclient==2.2.4 # via eg-feast (setup.py) nbclient==0.8.0 # via nbconvert diff --git a/sdk/python/requirements/py3.8-ci-requirements.txt b/sdk/python/requirements/py3.8-ci-requirements.txt index 5a8ca76192..a4ffddc908 100644 --- a/sdk/python/requirements/py3.8-ci-requirements.txt +++ b/sdk/python/requirements/py3.8-ci-requirements.txt @@ -216,7 +216,7 @@ executing==1.2.0 # via stack-data fastapi==0.95.2 # via feast (setup.py) -fastavro==1.7.4 +fastavro==1.8.2 # via # feast (setup.py) # pandavro @@ -529,7 +529,7 @@ mypy-extensions==1.0.0 # mypy mypy-protobuf==3.1 # via feast (setup.py) -mysqlclient==2.1.1 +mysqlclient==2.2.4 # via feast (setup.py) nbclassic==1.0.0 # via notebook @@ -732,7 +732,7 @@ pyjwt[crypto]==2.7.0 # snowflake-connector-python pymilvus==2.2.14 # via eg-feast (setup.py) -pymssql==2.2.7 +pymssql==2.2.8 # via feast (setup.py) pymysql==1.0.3 # via feast (setup.py) @@ -798,7 +798,7 @@ pytz==2023.3 # pandas # snowflake-connector-python # trino -pyyaml==6.0 +pyyaml==6.0.1 # via # dask # feast (setup.py)