diff --git a/CHANGELOG.md b/CHANGELOG.md index 766ed6a8..1020c101 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,15 +5,25 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - ## Unreleased -[Compare with 0.6.0](https://github.com/edgedb/edgedb-elixir/compare/v0.6.0...HEAD) +[Compare with 0.6.1](https://github.com/edgedb/edgedb-elixir/compare/v0.6.1...HEAD) + +## [0.6.1] - 2023-07-07 + +[Compare with 0.6.0](https://github.com/edgedb/edgedb-elixir/compare/v0.6.0...v0.6.1) ### Added - support for `Elixir v1.15` and `Erlang/OTP 26`. +### Fixed + +- encoding of `t:EdgeDB.Range.t/0` values. +- constructing `t:EdgeDB.Range.t/0` from `EdgeDB.Range.new/3` with `nil` as values. +- examples in the documentation and the `Inspect` implementation of + `t:EdgeDB.DateDuration.t/0` and `t:EdgeDB.Range.t/0`. + ## [0.6.0] - 2023-06-22 [Compare with 0.5.1](https://github.com/edgedb/edgedb-elixir/compare/v0.5.1...v0.6.0) diff --git a/lib/edgedb/protocol/codecs/range.ex b/lib/edgedb/protocol/codecs/range.ex index 8931c60e..71bb005a 100644 --- a/lib/edgedb/protocol/codecs/range.ex +++ b/lib/edgedb/protocol/codecs/range.ex @@ -33,12 +33,17 @@ defimpl EdgeDB.Protocol.Codec, for: EdgeDB.Protocol.Codecs.Range do codec = CodecStorage.get(codec_storage, codec) flags = encode_range_flags(range) - data = [ - Codec.encode(codec, range.lower, codec_storage), - Codec.encode(codec, range.upper, codec_storage) - ] - - [<> | data] + data = + Enum.reject( + [ + <>, + range.lower && Codec.encode(codec, range.lower, codec_storage), + range.upper && Codec.encode(codec, range.upper, codec_storage) + ], + &is_nil/1 + ) + + [<> | data] end @impl Codec @@ -115,6 +120,9 @@ defimpl EdgeDB.Protocol.Codec, for: EdgeDB.Protocol.Codecs.Range do range.inc_lower -> Bitwise.bor(flags, @lb_inc) + + true -> + flags end cond do @@ -123,6 +131,9 @@ defimpl EdgeDB.Protocol.Codec, for: EdgeDB.Protocol.Codecs.Range do range.inc_upper -> Bitwise.bor(flags, @ub_inc) + + true -> + flags end end end diff --git a/lib/edgedb/types/date_duration.ex b/lib/edgedb/types/date_duration.ex index d98f9aa1..58e1b7dd 100644 --- a/lib/edgedb/types/date_duration.ex +++ b/lib/edgedb/types/date_duration.ex @@ -6,7 +6,7 @@ defmodule EdgeDB.DateDuration do ```elixir iex(1)> {:ok, client} = EdgeDB.start_link() iex(2)> EdgeDB.query_required_single!(client, "select '1 year 2 days'") - #EdgeDB.Duration<"P1Y20D"> + #EdgeDB.DateDuration<"P1Y2D"> ``` """ @@ -33,12 +33,12 @@ defimpl Inspect, for: EdgeDB.DateDuration do @impl Inspect def inspect(%EdgeDB.DateDuration{days: 0, months: 0}, _opts) do - concat(["#EdgeDB.RelativeDuration<\"", "P0D", "\">"]) + concat(["#EdgeDB.DateDuration<\"", "P0D", "\">"]) end @impl Inspect def inspect(%EdgeDB.DateDuration{} = duration, _opts) do - concat(["#EdgeDB.RelativeDuration<\"", format_date("P", duration), "\">"]) + concat(["#EdgeDB.DateDuration<\"", format_date("P", duration), "\">"]) end defp format_date(formatted_repr, %EdgeDB.DateDuration{} = duration) do diff --git a/lib/edgedb/types/range.ex b/lib/edgedb/types/range.ex index 786b1049..7c5f54e3 100644 --- a/lib/edgedb/types/range.ex +++ b/lib/edgedb/types/range.ex @@ -18,8 +18,20 @@ defmodule EdgeDB.Range do is_empty: false ] + @typedoc since: "0.6.1" @typedoc """ - A value representing some interval of values. + A type that is acceptable by EdgeDB ranges. + """ + @type value() :: + integer() + | float() + | Decimal.t() + | DateTime.t() + | NaiveDateTime.t() + | Date.t() + + @typedoc """ + A value of `t:value/0` type representing some interval of values. Fields: @@ -38,9 +50,9 @@ defmodule EdgeDB.Range do } @typedoc """ - A value representing some interval of values. + A value of `t:value/0` type representing some interval of values. """ - @type t() :: t(term()) + @type t() :: t(value()) @typedoc """ Options for `EdgeDB.Range.new/3` function. @@ -66,7 +78,7 @@ defmodule EdgeDB.Range do """ @spec empty() :: t() def empty do - new(nil, nil, empty: true, inc_lower: false) + new(nil, nil, empty: true) end @doc """ @@ -77,19 +89,38 @@ defmodule EdgeDB.Range do #EdgeDB.Range<[1.1, 3.3]> ``` """ - @spec new(value, value, list(creation_option())) :: t(value) when value: term() + @spec new(value | nil, value | nil, list(creation_option())) :: t(value) when value: value() def new(lower, upper, opts \\ []) do + empty? = Keyword.get(opts, :empty, false) inc_lower? = Keyword.get(opts, :inc_lower, true) inc_upper? = Keyword.get(opts, :inc_upper, false) - empty? = Keyword.get(opts, :empty, false) - %__MODULE__{ - lower: lower, - upper: upper, - inc_lower: inc_lower?, - inc_upper: inc_upper?, - is_empty: empty? - } + cond do + empty? and (not is_nil(lower) or not is_nil(upper)) -> + raise EdgeDB.InvalidArgumentError.new( + "conflicting arguments to construct range: " <> + ":empty is `true` while the specified bounds " <> + "suggest otherwise" + ) + + empty? -> + %__MODULE__{ + lower: nil, + upper: nil, + inc_lower: false, + inc_upper: false, + is_empty: true + } + + true -> + %__MODULE__{ + lower: lower, + upper: upper, + inc_lower: not is_nil(lower) and inc_lower?, + inc_upper: not is_nil(upper) and inc_upper?, + is_empty: false + } + end end end @@ -107,7 +138,7 @@ defimpl Inspect, for: EdgeDB.Range do "#EdgeDB.Range<", if(range.inc_lower, do: "[", else: "("), if(range.lower, do: Inspect.inspect(range.lower, opts), else: empty()), - ",", + ", ", if(range.upper, do: Inspect.inspect(range.upper, opts), else: empty()), if(range.inc_upper, do: "]", else: ")"), ">" diff --git a/mix.exs b/mix.exs index 1187c62d..1f1f2cad 100644 --- a/mix.exs +++ b/mix.exs @@ -2,7 +2,7 @@ defmodule EdgeDB.MixProject do use Mix.Project @app :edgedb - @version "0.6.0" + @version "0.6.1" @source_url "https://github.com/edgedb/edgedb-elixir" @description "EdgeDB client for Elixir" diff --git a/test/docs/docs_test.exs b/test/docs/docs_test.exs index f234940a..b951c5b7 100644 --- a/test/docs/docs_test.exs +++ b/test/docs/docs_test.exs @@ -19,6 +19,12 @@ defmodule Tests.DocsTest do doctest EdgeDB.RelativeDuration doctest EdgeDB.Set + skip_before(version: 2) + doctest EdgeDB.DateDuration + + skip_before(version: 2) + doctest EdgeDB.Range + defp drop_tickets(client) do EdgeDB.query!(client, "delete Ticket") diff --git a/test/edgedb/protocol/codecs/range_test.exs b/test/edgedb/protocol/codecs/range_test.exs index 97ffc2a2..0e7b0328 100644 --- a/test/edgedb/protocol/codecs/range_test.exs +++ b/test/edgedb/protocol/codecs/range_test.exs @@ -4,12 +4,66 @@ defmodule Tests.EdgeDB.Protocol.Codecs.RangeTest do skip_before(version: 2, scope: :module) @input_ranges %{ + "range" => [ + EdgeDB.Range.new(1, 2), + {EdgeDB.Range.new(1, 2, inc_upper: true), EdgeDB.Range.new(1, 3)}, + EdgeDB.Range.empty(), + {EdgeDB.Range.new(1, 1), EdgeDB.Range.empty()}, + EdgeDB.Range.new(nil, nil) + ], "range" => [ - EdgeDB.Range.new(1, 2, inc_lower: true, inc_upper: false), - {EdgeDB.Range.new(1, 2, inc_lower: true, inc_upper: true), - EdgeDB.Range.new(1, 3, inc_lower: true, inc_upper: false)}, + EdgeDB.Range.new(1, 2), + {EdgeDB.Range.new(1, 2, inc_upper: true), EdgeDB.Range.new(1, 3)}, + EdgeDB.Range.empty(), + {EdgeDB.Range.new(1, 1), EdgeDB.Range.empty()}, + EdgeDB.Range.new(nil, nil) + ], + "range" => [ + EdgeDB.Range.new(1.5, 2.5), + {EdgeDB.Range.new(1.5, 2.5, inc_upper: true), EdgeDB.Range.new(1.5, 2.5, inc_upper: true)}, + EdgeDB.Range.empty(), + {EdgeDB.Range.new(1.5, 1.5), EdgeDB.Range.empty()}, + EdgeDB.Range.new(nil, nil) + ], + "range" => [ + EdgeDB.Range.new(1.5, 2.5), + {EdgeDB.Range.new(1.5, 2.5, inc_upper: true), EdgeDB.Range.new(1.5, 2.5, inc_upper: true)}, + EdgeDB.Range.empty(), + {EdgeDB.Range.new(1.5, 1.5), EdgeDB.Range.empty()}, + EdgeDB.Range.new(nil, nil) + ], + "range" => [ + EdgeDB.Range.new(Decimal.new(1), Decimal.new(2)), + {EdgeDB.Range.new(Decimal.new(1), Decimal.new(2), inc_upper: true), + EdgeDB.Range.new(Decimal.new(1), Decimal.new(2), inc_upper: true)}, + EdgeDB.Range.empty(), + {EdgeDB.Range.new(Decimal.new(1), Decimal.new(1)), EdgeDB.Range.empty()}, + EdgeDB.Range.new(nil, nil) + ], + "range" => [ + EdgeDB.Range.new(~U[2022-07-01 00:00:00Z], ~U[2022-12-01 00:00:00Z]), + {EdgeDB.Range.new(~U[2022-07-01 00:00:00Z], ~U[2022-12-01 00:00:00Z], inc_upper: true), + EdgeDB.Range.new(~U[2022-07-01 00:00:00Z], ~U[2022-12-01 00:00:00Z], inc_upper: true)}, + EdgeDB.Range.empty(), + {EdgeDB.Range.new(~U[2022-07-01 00:00:00Z], ~U[2022-07-01 00:00:00Z]), + EdgeDB.Range.empty()}, + EdgeDB.Range.new(nil, nil) + ], + "range" => [ + EdgeDB.Range.new(~N[2022-07-01 00:00:00Z], ~N[2022-12-01 00:00:00Z]), + {EdgeDB.Range.new(~N[2022-07-01 00:00:00Z], ~N[2022-12-01 00:00:00Z], inc_upper: true), + EdgeDB.Range.new(~N[2022-07-01 00:00:00Z], ~N[2022-12-01 00:00:00Z], inc_upper: true)}, + EdgeDB.Range.empty(), + {EdgeDB.Range.new(~N[2022-07-01 00:00:00Z], ~N[2022-07-01 00:00:00Z]), + EdgeDB.Range.empty()}, + EdgeDB.Range.new(nil, nil) + ], + "range" => [ + EdgeDB.Range.new(~D[2022-07-01], ~D[2022-12-01]), + {EdgeDB.Range.new(~D[2022-07-01], ~D[2022-12-01], inc_upper: true), + EdgeDB.Range.new(~D[2022-07-01], ~D[2022-12-02])}, EdgeDB.Range.empty(), - {EdgeDB.Range.new(1, 1, inc_lower: true, inc_upper: false), EdgeDB.Range.empty()}, + {EdgeDB.Range.new(~D[2022-07-01], ~D[2022-07-01]), EdgeDB.Range.empty()}, EdgeDB.Range.new(nil, nil) ] } @@ -73,10 +127,12 @@ defmodule Tests.EdgeDB.Protocol.Codecs.RangeTest do {value, value} end - test "encoding #{inspect(input)} as #{inspect(type)} with expecting #{inspect(output)} in the end", + test "encoding #{inspect(input)} as #{inspect(type)} with expecting #{inspect(output)} as the result", %{client: client} do - value = "value" - assert ^value = EdgeDB.query_single!(client, "select $0", [value]) + type = unquote(type) + input = unquote(Macro.escape(input)) + output = unquote(Macro.escape(output)) + assert ^output = EdgeDB.query_single!(client, "select <#{type}>$0", [input]) end end end