Skip to content

Commit 3647fc4

Browse files
committed
improvement: add default implementation for pg_version, and rename to min_pg_version
1 parent c41b7f3 commit 3647fc4

File tree

10 files changed

+90
-73
lines changed

10 files changed

+90
-73
lines changed

.credo.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
{Credo.Check.Refactor.CondStatements, []},
119119
{Credo.Check.Refactor.CyclomaticComplexity, false},
120120
{Credo.Check.Refactor.FunctionArity, [max_arity: 10]},
121-
{Credo.Check.Refactor.LongQuoteBlocks, []},
121+
{Credo.Check.Refactor.LongQuoteBlocks, false},
122122
{Credo.Check.Refactor.MapInto, []},
123123
{Credo.Check.Refactor.MatchInCondition, []},
124124
{Credo.Check.Refactor.NegatedConditionsInUnless, []},

documentation/how_to/upgrade.md

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,9 @@ There are only three breaking changes in this release, one of them is very signi
44

55
# AshPostgres officially supports only postgresql version 14 or higher
66

7-
You will need to configure your repo version in the `pg_version/0` callback in your repo. For example:
7+
A new callback `min_pg_version/0` has been added to the repo, but a default implementation is set up that reads the version from postgres directly, the first time it is required. It is cached until the repo is reinitialized, at which point it is looked up again.
88

9-
```elixir
10-
def pg_version do
11-
Version.parse!("14.0.0")
12-
end
13-
```
14-
15-
While _most_ things will work with versions as low as 11, we are relying on features of newer postgres versions. We will not be testing against versions lower than 14, and we will not be supporting them. If you are using an older version of postgres, you will need to upgrade.
9+
While _most_ things will work with versions as low as 9, we are relying on features of newer postgres versions and intend to do so more in the future. We will not be testing against versions lower than 14, and we will not be supporting them. If you are using an older version of postgres, you will need to upgrade.
1610

1711
If you _must_ use an older version, the only thing that you'll need to change in the short term is to handle the fact that we now use `gen_random_uuid()` as the default for generated uuids (see below), which is only available after postgres _13_. Additionally, if you are on postgres 12 or earlier, you will need to replace `ANYCOMPATIBLE` with `ANYELEMENT` in the `ash-functions` extension migration.
1812

lib/data_layer.ex

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,6 @@ defmodule AshPostgres.DataLayer do
385385
use Spark.Dsl.Extension,
386386
sections: @sections,
387387
verifiers: [
388-
AshPostgres.Verifiers.VerifyPostgresVersion,
389388
AshPostgres.Verifiers.PreventMultidimensionalArrayAggregates,
390389
AshPostgres.Verifiers.ValidateReferences,
391390
AshPostgres.Verifiers.PreventAttributeMultitenancyAndNonFullMatchType,

lib/data_layer/info.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ defmodule AshPostgres.DataLayer.Info do
1717
@doc "Checks a version requirement against the resource's repo's postgres version"
1818
def pg_version_matches?(resource, requirement) do
1919
resource
20-
|> pg_version()
20+
|> min_pg_version()
2121
|> Version.match?(requirement)
2222
end
2323

2424
@doc "Gets the resource's repo's postgres version"
25-
def pg_version(resource) do
26-
case repo(resource, :read).pg_version() do
25+
def min_pg_version(resource) do
26+
case repo(resource, :read).min_pg_version() do
2727
%Version{} = version -> version
2828
string when is_binary(string) -> Version.parse!(string)
2929
end

lib/repo.ex

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ defmodule AshPostgres.Repo do
4545
@callback installed_extensions() :: [String.t() | module()]
4646

4747
@doc "Configure the version of postgres that is being used."
48-
@callback pg_version() :: Version.t()
48+
@callback min_pg_version() :: Version.t()
4949

5050
@doc """
5151
Use this to inform the data layer about the oldest potential postgres version it will be run on.
@@ -86,6 +86,7 @@ defmodule AshPostgres.Repo do
8686
otp_app: otp_app
8787
end
8888

89+
@agent __MODULE__.AshPgVersion
8990
@behaviour AshPostgres.Repo
9091

9192
defoverridable insert: 2, insert: 1, insert!: 2, insert!: 1
@@ -98,7 +99,6 @@ defmodule AshPostgres.Repo do
9899
def create?, do: true
99100
def drop?, do: true
100101

101-
102102
def transaction!(fun) do
103103
case fun.() do
104104
{:ok, value} -> value
@@ -119,7 +119,19 @@ defmodule AshPostgres.Repo do
119119
"""
120120
end
121121

122-
def init(_, config) do
122+
def init(type, config) do
123+
if type == :supervisor do
124+
try do
125+
Agent.stop(@agent)
126+
rescue
127+
_ ->
128+
:ok
129+
catch
130+
_, _ ->
131+
:ok
132+
end
133+
end
134+
123135
new_config =
124136
config
125137
|> Keyword.put(:installed_extensions, installed_extensions())
@@ -193,6 +205,74 @@ defmodule AshPostgres.Repo do
193205
end
194206
end
195207

208+
def min_pg_version do
209+
if version = cached_version() do
210+
version
211+
else
212+
lookup_version()
213+
end
214+
end
215+
216+
defp cached_version do
217+
Agent.start_link(
218+
fn ->
219+
lookup_version()
220+
end,
221+
name: @agent
222+
)
223+
224+
Agent.get(@agent, fn state -> state end)
225+
end
226+
227+
defp lookup_version do
228+
version_string =
229+
try do
230+
query!("SELECT version()").rows |> Enum.at(0) |> Enum.at(0)
231+
rescue
232+
error ->
233+
reraise """
234+
Got an error while trying to read postgres version
235+
236+
Error:
237+
238+
#{inspect(error)}
239+
""",
240+
__STACKTRACE__
241+
end
242+
243+
try do
244+
version_string
245+
|> String.split(" ")
246+
|> Enum.at(1)
247+
|> String.split(".")
248+
|> case do
249+
[major] ->
250+
"#{major}.0.0"
251+
252+
[major, minor] ->
253+
"#{major}.#{minor}.0"
254+
255+
other ->
256+
Enum.join(other, ".")
257+
end
258+
|> Version.parse!()
259+
rescue
260+
error ->
261+
reraise(
262+
"""
263+
Could not parse postgres version from version string: "#{version_string}"
264+
265+
You may need to define the `min_version/0` callback yourself.
266+
267+
Error:
268+
269+
#{inspect(error)}
270+
""",
271+
__STACKTRACE__
272+
)
273+
end
274+
end
275+
196276
def from_ecto(other), do: other
197277

198278
def to_ecto(nil), do: nil
@@ -230,6 +310,7 @@ defmodule AshPostgres.Repo do
230310
defoverridable init: 2,
231311
on_transaction_begin: 1,
232312
installed_extensions: 0,
313+
min_pg_version: 0,
233314
all_tenants: 0,
234315
tenant_migrations_path: 0,
235316
default_prefix: 0,

lib/verifiers/verify_postgres_version.ex

Lines changed: 0 additions & 37 deletions
This file was deleted.

lib/version_agent.ex

Whitespace-only changes.

mix.lock

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@
88
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
99
"deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"},
1010
"dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"},
11-
"earmark": {:hex, :earmark, "1.4.46", "8c7287bd3137e99d26ae4643e5b7ef2129a260e3dcf41f251750cb4563c8fb81", [:mix], [], "hexpm", "798d86db3d79964e759ddc0c077d5eb254968ed426399fbf5a62de2b5ff8910a"},
1211
"earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"},
1312
"ecto": {:hex, :ecto, "3.11.2", "e1d26be989db350a633667c5cda9c3d115ae779b66da567c68c80cfb26a8c9ee", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c38bca2c6f8d8023f2145326cc8a80100c3ffe4dcbd9842ff867f7fc6156c65"},
1413
"ecto_sql": {:hex, :ecto_sql, "3.11.1", "e9abf28ae27ef3916b43545f9578b4750956ccea444853606472089e7d169470", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ce14063ab3514424276e7e360108ad6c2308f6d88164a076aac8a387e1fea634"},
15-
"elixir_make": {:hex, :elixir_make, "0.8.3", "d38d7ee1578d722d89b4d452a3e36bcfdc644c618f0d063b874661876e708683", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "5c99a18571a756d4af7a4d89ca75c28ac899e6103af6f223982f09ce44942cc9"},
1614
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
1715
"ets": {:hex, :ets, "0.9.0", "79c6a6c205436780486f72d84230c6cba2f8a9920456750ddd1e47389107d5fd", [:mix], [], "hexpm", "2861fdfb04bcaeff370f1a5904eec864f0a56dcfebe5921ea9aadf2a481c822b"},
1816
"ex_check": {:hex, :ex_check, "0.15.0", "074b94c02de11c37bba1ca82ae5cc4926e6ccee862e57a485b6ba60fca2d8dc1", [:mix], [], "hexpm", "33848031a0c7e4209c3b4369ce154019788b5219956220c35ca5474299fb6a0e"},
@@ -26,9 +24,7 @@
2624
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},
2725
"makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"},
2826
"makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"},
29-
"nimble_options": {:hex, :nimble_options, "1.1.0", "3b31a57ede9cb1502071fade751ab0c7b8dbe75a9a4c2b5bbb0943a690b63172", [:mix], [], "hexpm", "8bbbb3941af3ca9acc7835f5655ea062111c9c27bcac53e004460dfd19008a99"},
3027
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
31-
"picosat_elixir": {:hex, :picosat_elixir, "0.2.3", "bf326d0f179fbb3b706bb2c15fbc367dacfa2517157d090fdfc32edae004c597", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "f76c9db2dec9d2561ffaa9be35f65403d53e984e8cd99c832383b7ab78c16c66"},
3228
"postgrex": {:hex, :postgrex, "0.17.4", "5777781f80f53b7c431a001c8dad83ee167bcebcf3a793e3906efff680ab62b3", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "6458f7d5b70652bc81c3ea759f91736c16a31be000f306d3c64bcdfe9a18b3cc"},
3329
"reactor": {:hex, :reactor, "0.8.1", "1aec71d16083901277727c8162f6dd0f07e80f5ca98911b6ef4f2c95e6e62758", [:mix], [{:libgraph, "~> 0.16", [hex: :libgraph, repo: "hexpm", optional: false]}, {:spark, "~> 2.0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ae3936d97a3e4a316744f70c77b85345b08b70da334024c26e6b5eb8ede1246b"},
3430
"simple_sat": {:hex, :simple_sat, "0.1.1", "68a5ebe6f6d5956bd806e4881c495692c14580a2f1a4420488985abd0fba2119", [:mix], [], "hexpm", "63571218f92ff029838df7645eb8f0c38df8ed60d2d14578412a8d142a94471e"},

test/support/test_no_sandbox_repo.ex

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,6 @@ defmodule AshPostgres.TestNoSandboxRepo do
77
send(self(), data)
88
end
99

10-
def pg_version do
11-
version =
12-
case System.get_env("PG_VERSION") do
13-
nil -> "16.0.0"
14-
"14" -> "14.0.0"
15-
"15" -> "15.0.0"
16-
"16" -> "16.0.0"
17-
end
18-
19-
Version.parse!(version)
20-
end
21-
2210
def installed_extensions do
2311
["ash-functions", "uuid-ossp", "pg_trgm", "citext", AshPostgres.TestCustomExtension] --
2412
Application.get_env(:ash_postgres, :no_extensions, [])

test/support/test_repo.ex

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@ defmodule AshPostgres.TestRepo do
77
send(self(), data)
88
end
99

10-
def pg_version do
11-
Version.parse!(System.get_env("PG_VERSION") || "16.0.0")
12-
end
13-
1410
def installed_extensions do
1511
["ash-functions", "uuid-ossp", "pg_trgm", "citext", AshPostgres.TestCustomExtension] --
1612
Application.get_env(:ash_postgres, :no_extensions, [])

0 commit comments

Comments
 (0)