-
Notifications
You must be signed in to change notification settings - Fork 900
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b11247f
commit f4e6b48
Showing
8 changed files
with
493 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
""" | ||
The `user` module within the `queries` package provides SQL query functions for managing users | ||
in the TimescaleDB database. This includes operations for: | ||
- Creating new users | ||
- Updating existing users | ||
- Retrieving user details | ||
- Listing users with filtering and pagination | ||
- Deleting users | ||
""" | ||
|
||
from .create_user import create_user | ||
from .create_or_update_user import create_or_update_user_query | ||
from .delete_user import delete_user_query | ||
from .get_user import get_user_query | ||
from .list_users import list_users_query | ||
from .patch_user import patch_user_query | ||
from .update_user import update_user_query | ||
|
||
__all__ = [ | ||
"create_user", | ||
"create_or_update_user_query", | ||
"delete_user_query", | ||
"get_user_query", | ||
"list_users_query", | ||
"patch_user_query", | ||
"update_user_query", | ||
] |
72 changes: 72 additions & 0 deletions
72
agents-api/agents_api/queries/users/create_or_update_user.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
from typing import Any | ||
from uuid import UUID | ||
|
||
from beartype import beartype | ||
from fastapi import HTTPException | ||
from asyncpg import exceptions as asyncpg_exceptions | ||
from sqlglot import parse_one | ||
|
||
from ...autogen.openapi_model import CreateUserRequest, User | ||
from ...metrics.counters import increase_counter | ||
from ..utils import partialclass, pg_query, rewrap_exceptions, wrap_in_class | ||
|
||
|
||
@rewrap_exceptions({ | ||
asyncpg_exceptions.ForeignKeyViolationError: partialclass( | ||
HTTPException, | ||
status_code=404, | ||
detail="The specified developer does not exist.", | ||
) | ||
}) | ||
@wrap_in_class(User) | ||
@increase_counter("create_or_update_user") | ||
@pg_query | ||
@beartype | ||
def create_or_update_user_query( | ||
*, | ||
developer_id: UUID, | ||
user_id: UUID, | ||
data: CreateUserRequest | ||
) -> tuple[str, dict]: | ||
""" | ||
Constructs an SQL query to create or update a user. | ||
Args: | ||
developer_id (UUID): The UUID of the developer. | ||
user_id (UUID): The UUID of the user. | ||
data (CreateUserRequest): The user data to insert or update. | ||
Returns: | ||
tuple[str, dict]: SQL query and parameters. | ||
""" | ||
query = parse_one(""" | ||
INSERT INTO users ( | ||
developer_id, | ||
user_id, | ||
name, | ||
about, | ||
metadata | ||
) | ||
VALUES ( | ||
%(developer_id)s, | ||
%(user_id)s, | ||
%(name)s, | ||
%(about)s, | ||
%(metadata)s | ||
) | ||
ON CONFLICT (developer_id, user_id) DO UPDATE SET | ||
name = EXCLUDED.name, | ||
about = EXCLUDED.about, | ||
metadata = EXCLUDED.metadata | ||
RETURNING *; | ||
""").sql() | ||
|
||
params = { | ||
"developer_id": developer_id, | ||
"user_id": user_id, | ||
"name": data.name, | ||
"about": data.about, | ||
"metadata": data.metadata or {}, | ||
} | ||
|
||
return query, params |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from typing import Any | ||
from uuid import UUID | ||
|
||
from beartype import beartype | ||
from fastapi import HTTPException | ||
from psycopg import errors as psycopg_errors | ||
from sqlglot import parse_one | ||
from pydantic import ValidationError | ||
from uuid_extensions import uuid7 | ||
|
||
from ...autogen.openapi_model import CreateUserRequest, User | ||
from ...metrics.counters import increase_counter | ||
from ..utils import partialclass, pg_query, rewrap_exceptions, wrap_in_class | ||
|
||
@rewrap_exceptions({ | ||
psycopg_errors.ForeignKeyViolation: partialclass( | ||
HTTPException, | ||
status_code=404, | ||
detail="The specified developer does not exist.", | ||
), | ||
ValidationError: partialclass( | ||
HTTPException, | ||
status_code=400, | ||
detail="Input validation failed. Please check the provided data.", | ||
), | ||
}) | ||
@wrap_in_class(User) | ||
@increase_counter("create_user") | ||
@pg_query | ||
@beartype | ||
def create_user( | ||
*, | ||
developer_id: UUID, | ||
user_id: UUID | None = None, | ||
data: CreateUserRequest, | ||
) -> tuple[str, dict]: | ||
""" | ||
Constructs the SQL query to create a new user. | ||
Args: | ||
developer_id (UUID): The UUID of the developer creating the user. | ||
user_id (UUID, optional): The UUID for the new user. If None, one will be generated. | ||
data (CreateUserRequest): The user data to insert. | ||
Returns: | ||
tuple[str, dict]: A tuple containing the SQL query and its parameters. | ||
""" | ||
user_id = user_id or uuid7() | ||
|
||
query = parse_one(""" | ||
INSERT INTO users ( | ||
developer_id, | ||
user_id, | ||
name, | ||
about, | ||
metadata | ||
) | ||
VALUES ( | ||
%(developer_id)s, | ||
%(user_id)s, | ||
%(name)s, | ||
%(about)s, | ||
%(metadata)s | ||
) | ||
RETURNING *; | ||
""").sql() | ||
|
||
params = { | ||
"developer_id": developer_id, | ||
"user_id": user_id, | ||
"name": data.name, | ||
"about": data.about, | ||
"metadata": data.metadata or {}, | ||
} | ||
|
||
return query, params |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
from typing import Any | ||
from uuid import UUID | ||
|
||
from beartype import beartype | ||
from fastapi import HTTPException | ||
from psycopg import errors as psycopg_errors | ||
from sqlglot import parse_one | ||
|
||
from ...autogen.openapi_model import ResourceDeletedResponse | ||
from ...metrics.counters import increase_counter | ||
from ..utils import partialclass, pg_query, rewrap_exceptions, wrap_in_class | ||
|
||
@rewrap_exceptions({ | ||
psycopg_errors.ForeignKeyViolation: partialclass( | ||
HTTPException, | ||
status_code=404, | ||
detail="The specified developer does not exist.", | ||
) | ||
}) | ||
@wrap_in_class(ResourceDeletedResponse, one=True) | ||
@increase_counter("delete_user") | ||
@pg_query | ||
@beartype | ||
def delete_user_query(*, developer_id: UUID, user_id: UUID) -> tuple[list[str], dict]: | ||
""" | ||
Constructs optimized SQL queries to delete a user and related data. | ||
Uses primary key for efficient deletion. | ||
Args: | ||
developer_id (UUID): The developer's UUID | ||
user_id (UUID): The user's UUID | ||
Returns: | ||
tuple[list[str], dict]: List of SQL queries and parameters | ||
""" | ||
query = parse_one(""" | ||
BEGIN; | ||
DELETE FROM user_files WHERE developer_id = %(developer_id)s AND user_id = %(user_id)s; | ||
DELETE FROM user_docs WHERE developer_id = %(developer_id)s AND user_id = %(user_id)s; | ||
DELETE FROM users WHERE developer_id = %(developer_id)s AND user_id = %(user_id)s | ||
RETURNING user_id as id, developer_id; | ||
COMMIT; | ||
""").sql() | ||
|
||
return [query], {"developer_id": developer_id, "user_id": user_id} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
from typing import Any | ||
from uuid import UUID | ||
|
||
from beartype import beartype | ||
from fastapi import HTTPException | ||
from psycopg import errors as psycopg_errors | ||
from sqlglot import parse_one | ||
|
||
from ...autogen.openapi_model import User | ||
from ...metrics.counters import increase_counter | ||
from ..utils import partialclass, pg_query, rewrap_exceptions, wrap_in_class | ||
|
||
@rewrap_exceptions({ | ||
psycopg_errors.ForeignKeyViolation: partialclass( | ||
HTTPException, | ||
status_code=404, | ||
detail="The specified developer does not exist.", | ||
) | ||
}) | ||
@wrap_in_class(User, one=True) | ||
@increase_counter("get_user") | ||
@pg_query | ||
@beartype | ||
def get_user_query(*, developer_id: UUID, user_id: UUID) -> tuple[str, dict]: | ||
""" | ||
Constructs an optimized SQL query to retrieve a user's details. | ||
Uses the primary key index (developer_id, user_id) for efficient lookup. | ||
Args: | ||
developer_id (UUID): The UUID of the developer. | ||
user_id (UUID): The UUID of the user to retrieve. | ||
Returns: | ||
tuple[str, dict]: SQL query and parameters. | ||
""" | ||
query = parse_one(""" | ||
SELECT | ||
user_id as id, | ||
developer_id, | ||
name, | ||
about, | ||
metadata, | ||
created_at, | ||
updated_at | ||
FROM users | ||
WHERE developer_id = %(developer_id)s | ||
AND user_id = %(user_id)s; | ||
""").sql() | ||
|
||
return query, {"developer_id": developer_id, "user_id": user_id} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
from typing import Any, Literal | ||
from uuid import UUID | ||
|
||
from beartype import beartype | ||
from fastapi import HTTPException | ||
from psycopg import errors as psycopg_errors | ||
from sqlglot import parse_one | ||
|
||
from ...autogen.openapi_model import User | ||
from ...metrics.counters import increase_counter | ||
from ..utils import partialclass, pg_query, rewrap_exceptions, wrap_in_class | ||
|
||
@rewrap_exceptions({ | ||
psycopg_errors.ForeignKeyViolation: partialclass( | ||
HTTPException, | ||
status_code=404, | ||
detail="The specified developer does not exist.", | ||
) | ||
}) | ||
@wrap_in_class(User) | ||
@increase_counter("list_users") | ||
@pg_query | ||
@beartype | ||
def list_users_query( | ||
*, | ||
developer_id: UUID, | ||
limit: int = 100, | ||
offset: int = 0, | ||
sort_by: Literal["created_at", "updated_at"] = "created_at", | ||
direction: Literal["asc", "desc"] = "desc", | ||
metadata_filter: dict | None = None, | ||
) -> tuple[str, dict]: | ||
""" | ||
Constructs an optimized SQL query for listing users with pagination and filtering. | ||
Uses indexes on developer_id and metadata for efficient querying. | ||
Args: | ||
developer_id (UUID): The developer's UUID | ||
limit (int): Maximum number of records to return | ||
offset (int): Number of records to skip | ||
sort_by (str): Field to sort by | ||
direction (str): Sort direction | ||
metadata_filter (dict, optional): Metadata-based filters | ||
Returns: | ||
tuple[str, dict]: SQL query and parameters | ||
""" | ||
if limit < 1 or limit > 1000: | ||
raise HTTPException(status_code=400, detail="Limit must be between 1 and 1000") | ||
if offset < 0: | ||
raise HTTPException(status_code=400, detail="Offset must be non-negative") | ||
|
||
metadata_clause = "" | ||
params = { | ||
"developer_id": developer_id, | ||
"limit": limit, | ||
"offset": offset | ||
} | ||
|
||
if metadata_filter: | ||
metadata_clause = "AND metadata @> %(metadata_filter)s" | ||
params["metadata_filter"] = metadata_filter | ||
|
||
query = parse_one(f""" | ||
SELECT | ||
user_id as id, | ||
developer_id, | ||
name, | ||
about, | ||
metadata, | ||
created_at, | ||
updated_at | ||
FROM users | ||
WHERE developer_id = %(developer_id)s | ||
{metadata_clause} | ||
ORDER BY {sort_by} {direction} | ||
LIMIT %(limit)s | ||
OFFSET %(offset)s; | ||
""").sql() | ||
|
||
return query, params |
Oops, something went wrong.