Behaviour for database-specific implementations.
Recollect supports multiple database backends through this adapter pattern. Currently supported:
- PostgreSQL with pgvector extension
- libSQL (SQLite with native vector support)
Configure the adapter in your config.exs:
config :recollect, :database_adapter, Recollect.DatabaseAdapter.LibSQL
# or
config :recollect, :database_adapter, Recollect.DatabaseAdapter.PostgresThe adapter is used internally by Recollect to generate database-specific SQL, handle type mappings, and manage vector operations.
Summary
Callbacks
Returns SQL for creating the vector extension, or nil if not needed.
Returns the SQL dialect name.
Formats an embedding list for database insertion.
Formats a UUID for database insertion.
Converts an embedding from database format to Elixir list.
Returns SQL placeholder for parameterized queries.
Returns the module name for the Repo adapter.
Returns true if the adapter requires the pgvector package.
Returns true if the database supports recursive CTEs.
Returns true if the database supports vector indexes.
Returns SQL for approximate top-k vector search using index.
Returns the Ecto type for UUID fields.
Returns SQL expression for calculating cosine distance.
Returns the Ecto type atom for embedding fields.
Returns SQL for creating a vector index.
Returns SQL expression for calculating cosine similarity (1 - distance).
Returns the SQL type definition for a vector column.
Callbacks
@callback create_vector_extension_sql() :: String.t() | nil
Returns SQL for creating the vector extension, or nil if not needed.
@callback dialect() :: :postgres | :sqlite | :libsql
Returns the SQL dialect name.
Formats an embedding list for database insertion.
Examples
iex> adapter.format_embedding([0.1, 0.2, 0.3])
"[0.1,0.2,0.3]" # for libSQL
[0.1, 0.2, 0.3] # for PostgreSQL (as Pgvector.Ecto.Vector)
Formats a UUID for database insertion.
Converts an embedding from database format to Elixir list.
@callback placeholder(position :: pos_integer()) :: String.t()
Returns SQL placeholder for parameterized queries.
PostgreSQL uses numbered parameters ($1, $2), while SQLite uses ?.
@callback repo_adapter() :: module()
Returns the module name for the Repo adapter.
Examples
iex> adapter.repo_adapter()
Ecto.Adapters.LibSQL # for libSQL
Ecto.Adapters.Postgres # for PostgreSQL
@callback requires_pgvector?() :: boolean()
Returns true if the adapter requires the pgvector package.
@callback supports_recursive_ctes?() :: boolean()
Returns true if the database supports recursive CTEs.
@callback supports_vector_index?() :: boolean()
Returns true if the database supports vector indexes.
@callback top_k_sql( table :: atom(), index_name :: String.t(), query_vector :: String.t(), k :: pos_integer() ) :: String.t() | nil
Returns SQL for approximate top-k vector search using index.
Returns nil if not supported by the database.
@callback uuid_type() :: atom()
Returns the Ecto type for UUID fields.
Examples
iex> adapter.uuid_type()
:binary_id # libSQL uses binary IDs by default
:uuid # PostgreSQL has native UUID
Returns SQL expression for calculating cosine distance.
Examples
iex> adapter.vector_distance_sql("embedding", "query_vector")
"embedding <=> query_vector" # PostgreSQL
"vector_distance_cos(embedding, query_vector)" # libSQL
@callback vector_ecto_type() :: atom()
Returns the Ecto type atom for embedding fields.
Examples
iex> adapter.vector_ecto_type()
:string # for libSQL (vectors stored as text representation)
Pgvector.Ecto.Vector # for PostgreSQL
Returns SQL for creating a vector index.
Examples
iex> adapter.vector_index_sql(:recollect_entries, :embedding, dimensions: 768)
"CREATE INDEX ... USING hnsw ..." # PostgreSQL
"CREATE INDEX ... (libsql_vector_idx(embedding))" # libSQL
Returns SQL expression for calculating cosine similarity (1 - distance).
@callback vector_type(dimensions :: pos_integer()) :: String.t()
Returns the SQL type definition for a vector column.
Examples
iex> adapter.vector_type(768)
"F32_BLOB(768)" # for libSQL
"vector(768)" # for PostgreSQL