From 13355e8d84c75577b113469ee6490c31cafc24ff Mon Sep 17 00:00:00 2001 From: robsmith11 Date: Sun, 31 Dec 2023 02:57:15 +0000 Subject: [PATCH] Support and default to UUID for PostgreSQL uuid --- Project.toml | 1 + src/LibPQ.jl | 3 ++- src/parsing.jl | 8 +++++++- test/runtests.jl | 18 +++++++++++++++++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index 4d8c26e1..f345a2d3 100644 --- a/Project.toml +++ b/Project.toml @@ -21,6 +21,7 @@ OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" SQLStrings = "af517c2e-c243-48fa-aab8-efac3db270f5" Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" TimeZones = "f269a46b-ccf7-5d73-abea-4c690281aa53" +UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" UTCDateTimes = "0f7cfa37-7abf-4834-b969-a8aa512401c2" [compat] diff --git a/src/LibPQ.jl b/src/LibPQ.jl index 7403cc21..5eea4e09 100644 --- a/src/LibPQ.jl +++ b/src/LibPQ.jl @@ -16,6 +16,7 @@ using Base.Iterators: zip, product using Base.Threads using Dates +using DBInterface using DocStringExtensions using Decimals using FileWatching @@ -28,8 +29,8 @@ using Memento: Memento, getlogger, warn, info, error, debug using OffsetArrays using SQLStrings using TimeZones +using UUIDs: UUID using UTCDateTimes -using DBInterface const Parameter = Union{String,Missing} const LOGGER = getlogger(@__MODULE__) diff --git a/src/parsing.jl b/src/parsing.jl index 7b0b2e65..2fefb2c7 100644 --- a/src/parsing.jl +++ b/src/parsing.jl @@ -211,6 +211,12 @@ function pqparse(::Type{Vector{UInt8}}, bytes::Array{UInt8,1}) return unescaped_vec end +## uuid +_DEFAULT_TYPE_MAP[:uuid] = UUID +function Base.parse(::Type{UUID}, pqv::PQBinaryValue{PQ_SYSTEM_TYPES[:uuid]}) + return UUID(pqparse(UInt128, data_pointer(pqv))) +end + ## bool # TODO: check whether we ever need this or if PostgreSQL always gives t or f _DEFAULT_TYPE_MAP[:bool] = Bool @@ -692,7 +698,7 @@ function array_size(str) return dims end -for pq_eltype in ("int2", "int4", "int8", "float4", "float8", "oid", "numeric") +for pq_eltype in ("int2", "int4", "int8", "float4", "float8", "oid", "numeric", "uuid") array_oid = PQ_SYSTEM_TYPES[Symbol("_$pq_eltype")] jl_type = _DEFAULT_TYPE_MAP[Symbol(pq_eltype)] jl_missingtype = Union{jl_type,Missing} diff --git a/test/runtests.jl b/test/runtests.jl index 6a018f64..eebcde63 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,6 +14,7 @@ using SQLStrings using DBInterface using TimeZones using Tables +using UUIDs: UUID using UTCDateTimes Memento.config!("critical") @@ -1193,6 +1194,7 @@ end ("'hello '::char(10)", "hello"), ("'hello '::varchar(10)", "hello "), ("'3'::\"char\"", LibPQ.PQChar('3')), + ("'6dc2b682-a411-a51f-ce9e-af63d1ef7c1a'::uuid", UUID("6dc2b682-a411-a51f-ce9e-af63d1ef7c1a")), ("'t'::bool", true), ("'T'::bool", true), ("'true'::bool", true), @@ -1258,6 +1260,7 @@ end ("'{{{NULL,2,3},{4,NULL,6}}}'::float8[]", Array{Union{Float64, Missing}}(reshape(Union{Float64, Missing}[missing 2 3; 4 missing 6], 1, 2, 3))), ("'{{{1,2,3},{4,5,6}}}'::oid[]", Array{Union{LibPQ.Oid, Missing}}(reshape(LibPQ.Oid[1 2 3; 4 5 6], 1, 2, 3))), ("'{{{1,2,3},{4,5,6}}}'::numeric[]", Array{Union{Decimal, Missing}}(reshape(Decimal[1 2 3; 4 5 6], 1, 2, 3))), + ("'{6dc2b682-a411-a51f-ce9e-af63d1ef7c1a}'::uuid[]", Union{UUID, Missing}[UUID("6dc2b682-a411-a51f-ce9e-af63d1ef7c1a")]), ("'[1:1][-2:-1][3:5]={{{1,2,3},{4,5,6}}}'::int2[]", copyto!(OffsetArray{Union{Missing, Int16}}(undef, 1:1, -2:-1, 3:5), [1 2 3; 4 5 6])), ("'[1:1][-2:-1][3:5]={{{1,2,3},{4,5,6}}}'::int4[]", copyto!(OffsetArray{Union{Missing, Int32}}(undef, 1:1, -2:-1, 3:5), [1 2 3; 4 5 6])), ("'[1:1][-2:-1][3:5]={{{1,2,3},{4,5,6}}}'::int8[]", copyto!(OffsetArray{Union{Missing, Int64}}(undef, 1:1, -2:-1, 3:5), [1 2 3; 4 5 6])), @@ -1429,6 +1432,18 @@ end @testset "Parameters" begin conn = LibPQ.Connection("dbname=postgres user=$DATABASE_USER"; throw_error=true) + @testset "UUID" begin + tests = ( + ("'6dc2b682-a411-a51f-ce9e-af63d1ef7c1a'::uuid", UUID("6dc2b682-a411-a51f-ce9e-af63d1ef7c1a")), + ) + + @testset for (pg_str, obj) in tests + result = execute(conn, "SELECT $pg_str = \$1", [obj]) + @test first(first(result)) + close(result) + end + end + @testset "Arrays" begin tests = ( ("SELECT 'foo' = ANY(\$1)", [["bar", "foo"]]), @@ -1441,7 +1456,8 @@ end ("SELECT 'f\\\"oo' = ANY(\$1)", [["b\\\"ar", "f\\\"oo"]]), ("SELECT 'f\"\\oo' = ANY(\$1)", [["b\"\\ar", "f\"\\oo"]]), ("SELECT ARRAY[1, 2] = \$1", [[1, 2]]), - ("SELECT ARRAY[1, 2] = \$1", Any[Any[1, 2]]) + ("SELECT ARRAY[1, 2] = \$1", Any[Any[1, 2]]), + ("SELECT '{6dc2b682-a411-a51f-ce9e-af63d1ef7c1a}'::uuid[] = \$1", [[UUID("6dc2b682-a411-a51f-ce9e-af63d1ef7c1a")]]), ) @testset for (query, arr) in tests