# `PhoenixAI.Store.Adapters.Ecto`
[🔗](https://github.com/franciscpd/phoenix-ai-store/blob/v0.1.0/lib/phoenix_ai/store/adapters/ecto.ex#L2)

Ecto/Postgres adapter for `PhoenixAI.Store.Adapter`.

All callbacks receive an `opts` keyword list containing a `:repo` key
pointing to the Ecto.Repo module to use for queries.

This module is only compiled when Ecto is available as a dependency.

# `add_message`

Inserts a message row into the database. Returns `{:error, :not_found}` if the conversation does not exist.

# `conversation_exists?`

Checks whether a conversation exists in the database using `Repo.exists?/1`.

# `count_conversations`

Counts conversation rows matching the given filters using a database `COUNT` query.

# `count_events`

Counts event rows matching the given filters using a database `COUNT` query.

# `count_facts`

Counts fact rows for a user using a database `COUNT` query.

# `delete_conversation`

Deletes a conversation row from the database. Returns `{:error, :not_found}` if absent.

# `delete_fact`

Deletes all fact rows matching `{user_id, key}` from the database.

# `delete_profile`

Deletes all profile rows for a user from the database.

# `get_cost_records`

Queries all cost records for a conversation from the database, ordered by `recorded_at` ascending.

# `get_facts`

Queries all facts for a user from the database, ordered by `inserted_at` ascending.

# `get_messages`

Queries all messages for a conversation from the database, ordered by `inserted_at` ascending.

# `list_conversations`

Queries conversations from the database with optional filters, ordered by `inserted_at` descending.

# `list_events`

Queries a paginated, filtered list of events from the database with an opaque cursor for the next page.

# `load_conversation`

Loads a conversation by ID from the database, preloading messages ordered by `inserted_at`.

# `load_profile`

Loads a user profile from the database. Returns `{:error, :not_found}` if absent.

# `log_event`

Inserts an event row into the database. The event log is append-only — no updates or deletes.

# `save_conversation`

Inserts or updates a conversation row in the database via the configured Repo.

# `save_cost_record`

Inserts a cost record row into the database. Records are immutable once written.

# `save_fact`

Upserts a fact row in the database using `ON CONFLICT DO UPDATE` on `{user_id, key}`.

# `save_profile`

Upserts a profile row in the database using `ON CONFLICT DO UPDATE` on `user_id`.

# `sum_conversation_tokens`

Sums `token_count` for all messages in a conversation using a database `SUM` aggregate.

# `sum_cost`

Sums `total_cost` across cost records matching the given filters using a database `SUM` aggregate.

# `sum_user_tokens`

Sums `token_count` across all messages in all conversations belonging to a user via a database join.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
