An Ecto SQLite3 adapter.
0

Configure Feed

Select the types of activity you want to include in your feed.

Introduce Ecto.Adapters.SQLite3.Extension (#167)

This allows type extensions to be registered at runtime via the
`:ecto_sqlite3, extensions:` configuration key, which takes a list
of modules that implement the `Extension` behaviour.

authored by

Aaron Seigo and committed by
GitHub
(Jun 24, 2025, 10:44 AM -0500) 2fa7fb2b c80241fe

+79 -4
+14
README.md
··· 45 45 database: "path/to/my/database.db" 46 46 ``` 47 47 48 + ## Type Extensions 49 + 50 + Type extensions allow custom data types to be stored and retrieved from an SQLite3 database. 51 + 52 + This is done by implementing a module with the `Ecto.Adapters.SQLite3.TypeExtension` behaviour which maps types to encoder and decoder functions. Type extensions are activated by adding them to the `ecto_sqlite3` configuration as a list of type extention modules assigned to the `type_extensions` key: 53 + 54 + ```elixir 55 + config :exqlite: 56 + type_extensions: [MyApp.TypeExtension] 57 + 58 + config :ecto_sqlite3, 59 + type_extensions: [MyApp.TypeExtension] 60 + ``` 61 + 48 62 ## Database Encryption 49 63 50 64 As of version 0.9, `exqlite` supports loading database engines at runtime rather than compiling `sqlite3.c` itself.
+34 -4
lib/ecto/adapters/sqlite3.ex
··· 444 444 end 445 445 446 446 @impl Ecto.Adapter 447 - def loaders(_, type) do 448 - [type] 447 + def loaders(primitive_type, ecto_type) do 448 + loader_from_extension(primitive_type, ecto_type) 449 449 end 450 450 451 451 ## ··· 528 528 end 529 529 530 530 @impl Ecto.Adapter 531 - def dumpers(_primitive, type) do 532 - [type] 531 + def dumpers(primitive_type, ecto_type) do 532 + dumper_from_extension(primitive_type, ecto_type) 533 533 end 534 534 535 535 ## ··· 568 568 cmd_opts = Keyword.put_new(cmd_opts, :stderr_to_stdout, true) 569 569 570 570 System.cmd(cmd, args, cmd_opts) 571 + end 572 + 573 + defp extensions do 574 + Application.get_env(:ecto_sqlite3, :type_extensions, []) 575 + end 576 + 577 + defp loader_from_extension(primitive_type, ecto_type) do 578 + loader_from_extension(extensions(), primitive_type, ecto_type) 579 + end 580 + 581 + defp loader_from_extension([], _primitive_type, ecto_type), do: [ecto_type] 582 + 583 + defp loader_from_extension([extension | other_extensions], primitive_type, ecto_type) do 584 + case extension.loaders(primitive_type, ecto_type) do 585 + nil -> loader_from_extension(other_extensions, primitive_type, ecto_type) 586 + loader -> loader 587 + end 588 + end 589 + 590 + defp dumper_from_extension(primitive_type, ecto_type) do 591 + dumper_from_extension(extensions(), primitive_type, ecto_type) 592 + end 593 + 594 + defp dumper_from_extension([], _primitive_type, ecto_type), do: [ecto_type] 595 + 596 + defp dumper_from_extension([extension | other_extensions], primitive_type, ecto_type) do 597 + case extension.dumpers(primitive_type, ecto_type) do 598 + nil -> dumper_from_extension(other_extensions, primitive_type, ecto_type) 599 + dumper -> dumper 600 + end 571 601 end 572 602 end
+31
lib/ecto/adapters/sqlite3/type_extension.ex
··· 1 + defmodule Ecto.Adapters.SQLite3.TypeExtension do 2 + @moduledoc """ 3 + A behaviour that defines the API for extensions providing custom data loaders and dumpers 4 + for Ecto schemas. 5 + """ 6 + 7 + @type primitive_type :: atom | {:map, type :: atom} 8 + @type ecto_type :: atom 9 + 10 + @doc """ 11 + Takes a primitive type and, if it knows how to decode it into an 12 + appropriate Elixir data structure, reutrns a two-element list in 13 + the form `[(db_data :: any -> term), elixir_type :: atom]`. 14 + 15 + The function that is the first element will be called whenever 16 + the `primitive_type` appears in a schema and data is fetched from 17 + the database for it. 18 + """ 19 + @callback loaders(primitive_type, ecto_type) :: list | nil 20 + 21 + @doc """ 22 + Takes a primitive type and, if it knows how to encode it for storage 23 + in the database, returns a two-element list in 24 + the form `[elixir_type :: atom, (term -> db_data :: any)]`. 25 + 26 + The function that is the second element will be called whenever 27 + the `primitive_type` appears in a schema and data is about to be 28 + sent to the database for storage. 29 + """ 30 + @callback dumpers(ecto_type, primitive_type) :: list | nil 31 + end