Skip to content

Commit

Permalink
Merge pull request #79 from noaccOS/push-ppztktulqtkz
Browse files Browse the repository at this point in the history
fix: uuid types in data structures
  • Loading branch information
vinniefranco authored Jan 8, 2025
2 parents 199a282 + 60bebfa commit b498c2b
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 6 deletions.
6 changes: 1 addition & 5 deletions lib/exandra.ex
Original file line number Diff line number Diff line change
Expand Up @@ -358,16 +358,12 @@ defmodule Exandra do

@doc false
@impl Ecto.Adapter
def loaders(:binary_id, _type), do: []
def loaders(:exandra_map, type), do: [&Ecto.Type.embedded_load(type, &1, :exandra_map), type]
def loaders(:exandra_set, type), do: [&Ecto.Type.embedded_load(type, &1, :exandra_set), type]
def loaders(:binary_id, type), do: [Ecto.UUID, type]

def loaders({:map, _}, type),
do: [&decode_json/1, &Ecto.Type.embedded_load(type, &1, :map), type]

def loaders(:map, type), do: [&decode_json/1, type]
# Xandra returns UUIDs as strings, so we don't need to do any loading.
def loaders(:uuid, _type), do: []
def loaders(:decimal, type), do: [&decimal_decode/1, type]
def loaders(_, type), do: [type]

Expand Down
7 changes: 6 additions & 1 deletion lib/exandra/connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -997,7 +997,12 @@ defmodule Exandra.Connection do
|> apply_ecto_telemetry_options_to_xandra()

prepare_opts = Keyword.take(opts, @xandra_prepare_opts)
execute_opts = Keyword.take(opts, @xandra_exec_opts)

execute_opts =
opts
|> Keyword.take(@xandra_exec_opts)
|> Keyword.put(:uuid_format, :binary)
|> Keyword.put(:timeuuid_format, :binary)

{prepare_opts, execute_opts}
end
Expand Down
86 changes: 86 additions & 0 deletions test/exandra/integration_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ defmodule Exandra.IntegrationTest do
end
end

defmodule UUIDSchema do
use Ecto.Schema

@primary_key {:id, :binary_id, autogenerate: true}
schema "my_uuid_schema" do
field :my_uuid, Ecto.UUID
field :my_set, Exandra.Set, type: Ecto.UUID
field :my_map, Exandra.Map, key: Ecto.UUID, value: Ecto.UUID
field :my_tuple, Exandra.Tuple, types: [Ecto.UUID]
field :time_uuid, Ecto.UUID
field :time_set, Exandra.Set, type: Ecto.UUID
field :time_map, Exandra.Map, key: Ecto.UUID, value: Ecto.UUID
field :time_tuple, Exandra.Tuple, types: [Ecto.UUID]
end
end

setup_all do
opts = [keyspace: @keyspace, nodes: ["localhost:#{@port}"], sync_connect: 1000]

Expand Down Expand Up @@ -124,6 +140,21 @@ defmodule Exandra.IntegrationTest do
)
""")

Xandra.execute!(conn, """
CREATE TABLE my_uuid_schema (
id uuid,
my_uuid uuid,
my_set set<uuid>,
my_map map<uuid, uuid>,
my_tuple tuple<uuid>,
time_uuid timeuuid,
time_set set<timeuuid>,
time_map map<timeuuid, timeuuid>,
time_tuple tuple<timeuuid>,
PRIMARY KEY (id)
)
""")

Xandra.execute!(conn, """
CREATE TABLE my_counter_schema (
id uuid,
Expand Down Expand Up @@ -445,6 +476,61 @@ defmodule Exandra.IntegrationTest do
assert query |> TestRepo.all() |> is_list()
end

test "UUID types are correctly loaded from the database", %{start_opts: start_opts} do
start_supervised!({TestRepo, start_opts})

uuid = Ecto.UUID.generate()
uuid_set = MapSet.new([Ecto.UUID.generate(), Ecto.UUID.generate()])

uuid_map = %{
Ecto.UUID.generate() => Ecto.UUID.generate(),
Ecto.UUID.generate() => Ecto.UUID.generate()
}

uuid_tuple = {Ecto.UUID.generate()}

timeuuid = "8c8fddf0-6155-11ec-b2e9-8f88a6d02d59"

timeuuid_set =
MapSet.new([
"8c8fddf1-6155-11ec-b2e9-8f88a6d02d59",
"8c8fddf2-6155-11ec-b2e9-8f88a6d02d59"
])

timeuuid_map = %{
"8c8fddf3-6155-11ec-b2e9-8f88a6d02d59" => "8c8fddf4-6155-11ec-b2e9-8f88a6d02d59",
"8c8fddf5-6155-11ec-b2e9-8f88a6d02d59" => "8c8fddf6-6155-11ec-b2e9-8f88a6d02d59"
}

timeuuid_tuple = {"8c8fddf7-6155-11ec-b2e9-8f88a6d02d59"}

uuid_schema = %UUIDSchema{
my_uuid: uuid,
my_set: uuid_set,
my_map: uuid_map,
my_tuple: uuid_tuple,
time_uuid: timeuuid,
time_set: timeuuid_set,
time_map: timeuuid_map,
time_tuple: timeuuid_tuple
}

TestRepo.insert!(uuid_schema)
result = UUIDSchema |> TestRepo.one()

# The id was correctly loaded as a UUID string
assert {:ok, _} = result.id |> Ecto.UUID.dump()

assert result.my_uuid == uuid
assert result.my_set == uuid_set
assert result.my_map == uuid_map
assert result.my_tuple == uuid_tuple
assert result.time_uuid == timeuuid
assert result.time_set == timeuuid_set
assert result.time_map == timeuuid_map
assert result.time_tuple == timeuuid_tuple
end

describe "Telemetry" do
test "can set extra Telemetry metadata through Ecto's :telemetry_options",
%{start_opts: start_opts} do
Expand Down

0 comments on commit b498c2b

Please sign in to comment.