diff --git a/Project.toml b/Project.toml index 97a803ab..c1adf881 100644 --- a/Project.toml +++ b/Project.toml @@ -20,6 +20,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" [compat] CEnum = "0.2, 0.3, 0.4" diff --git a/src/LibPQ.jl b/src/LibPQ.jl index c9a1321d..e1cfce06 100644 --- a/src/LibPQ.jl +++ b/src/LibPQ.jl @@ -28,6 +28,7 @@ using Memento: Memento, getlogger, warn, info, error, debug using OffsetArrays using SQLStrings using TimeZones +using UUIDs: UUID const Parameter = Union{String,Missing} const LOGGER = getlogger(@__MODULE__) diff --git a/src/parsing.jl b/src/parsing.jl index a2ed7d31..5625e0a8 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 @@ -664,7 +670,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 52a3f984..09ccedc8 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -13,6 +13,7 @@ using OffsetArrays using SQLStrings using TimeZones using Tables +using UUIDs: UUID Memento.config!("critical") @@ -1191,6 +1192,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), @@ -1256,6 +1258,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])), @@ -1416,6 +1419,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"]]), @@ -1428,7 +1443,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