Skip to content

Instantly share code, notes, and snippets.

@romul
Last active December 23, 2017 00:56
Show Gist options
  • Save romul/7fd48cb85d77819511f2 to your computer and use it in GitHub Desktop.
Save romul/7fd48cb85d77819511f2 to your computer and use it in GitHub Desktop.
Using Postres hstore with Elixir, Ecto & Postgrex

To use hstore in Ecto schemas you have to create own Ecto type. To do this, follow these steps:

  1. Create files hstore.ex & hstore_extension.ex inside your lib folder
  2. Open your database settings and add the following line

extensions: [{MyApp.HStoreExtension, nil}],, for example

config :my_app, MyApp.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: "postgres",
  password: "",
  database: "database_name",
  extensions: [{MyApp.HStoreExtension, nil}],
  size: 100

P.S. Tested with Ecto 0.12.0-rc, Postgrex 0.8.4 and PostgreSQL 9.4

defmodule MyApp.HStore do
@behaviour Ecto.Type
def type, do: :hstore
def cast(value), do: {:ok, value}
def blank?(_), do: false
def load(value) do
{:ok, value}
end
def dump(value) do
{:ok, value}
end
end
defmodule MyApp.HStoreExtension do
alias Postgrex.TypeInfo
alias Postgrex.Extensions.Binary
@behaviour Postgrex.Extension
def init(_parameters, _opts), do: []
def matching(_), do: [type: "hstore"]
def format(_), do: :binary
def decode(info = %TypeInfo{type: "hstore"}, bin, types, opts) do
Binary.decode %TypeInfo{info | send: "hstore_send"}, bin, types, opts
end
def encode(info = %TypeInfo{type: "hstore"}, map, types, opts) do
Binary.encode %TypeInfo{info | send: "hstore_send"}, map, types, opts
end
end
@gaxunil
Copy link

gaxunil commented Feb 19, 2016

Hi I was wondering if you have any idea how to get the hstore column type working in a migration?
I'd like to add a column in a migration:
add :attrs, :hstore

Adding in the above Ecto type and Postgrex extension don't seem to spill over into working with a migration, unless I'm missing something?
Thanks

@keichan34
Copy link

@gaxunil This worked for me on Ecto 1.1.3

alter table(:some_table) do
  add :metadata, :hstore, default: fragment(~s(''::hstore))
end

Note that you'll need to execute ~s(CREATE EXTENSION IF NOT EXISTS "hstore") in a separate migration if you haven't done so already

@pufe
Copy link

pufe commented Jun 16, 2016

stopped working when I upgraded postgrex to 0.11 mainly because Postgrex.Extensions.Binary was deprecated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment