# `DDD.Query`
[🔗](https://github.com/blackuprise/vicander/blob/v0.1.1/lib/ddd/use_cases/query.ex#L1)

A query is the input of one read use case, and it carries its own handler.

Like a `DDD.Command` it declares fields (validated on construction) and implements
`execute/1`, but it only reads: it never saves an aggregate or emits an event.

    defmodule MyApp.Queries.OpenItems do
      use DDD.Query

      query do
        description "The items of a list that are not done yet"
        field :list_id, :uuid, required: true, description: "The list to read"
      end

      @impl DDD.Query
      def execute(%__MODULE__{list_id: id}) do
        with {:ok, list} <- MyApp.ListRepository.impl().find_by_id(id) do
          {:ok, for(item <- list.items, item.status == :open, do: %{id: item.id})}
        end
      end
    end

    MyApp.Queries.OpenItems.call(%{list_id: id})   # => {:ok, [%{id: ...}]}

`new/1`, `call/1` and `call!/1` work as for commands, and an error comes back as a
`DDD.Error` whose `context` has `:query` set to the query module.

## Read-only transaction

`execute/1` runs in a **read-only database transaction** by default. Postgres refuses any
write inside it, so "this cannot change data" is enforced by the database. The transaction
also gives the query one consistent snapshot, and it is always rolled back, never committed.

    use DDD.Query                          # read-only transaction on the configured repo
    use DDD.Query, repo: MyApp.Repo        # another repo
    use DDD.Query, transaction: false      # no transaction (in-memory repositories, APIs)

A query called from inside an open transaction (for example from a command) joins it and
cannot make it read-only.

# `execute`

```elixir
@callback execute(query :: struct()) :: {:ok, any()} | {:error, any()}
```

# `query`
*macro* 

---

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