Skip to content

Commit cd46af3

Browse files
authored
Add ∞ support for TimeTypes (JuliaDatabases#185)
* Add ∞ support for TimeTypes * Properly parse InfExtendedTime. Add Tests * Clean up tests * Deprecate infinite conversion for Dates.TimeType * Apply suggestions * Change timetype inf function name and message * Fix missing `end` * Update docs Manifest
1 parent d85ee15 commit cd46af3

File tree

7 files changed

+120
-7
lines changed

7 files changed

+120
-7
lines changed

Project.toml

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
1010
Decimals = "abce61dc-4473-55a0-ba07-351d65e31d42"
1111
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
1212
FileWatching = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
13+
Infinity = "a303e19e-6eb4-11e9-3b09-cd9505f79100"
1314
Intervals = "d8418881-c3e1-53bb-8760-2df7ec849ed5"
1415
IterTools = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
1516
LayerDicts = "6f188dcb-512c-564b-bc01-e0f76e72f166"
@@ -25,6 +26,7 @@ CEnum = "0.2"
2526
DataFrames = "0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20"
2627
Decimals = "0.4.1"
2728
DocStringExtensions = "0.8.0"
29+
Infinity = "0.2"
2830
Intervals = "1.3"
2931
IterTools = "1"
3032
LayerDicts = "1"

docs/Manifest.toml

+20-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# This file is machine-generated - editing it directly is not advised
2+
13
[[ArnoldiMethod]]
24
deps = ["DelimitedFiles", "LinearAlgebra", "Random", "SparseArrays", "StaticArrays", "Test"]
35
git-tree-sha1 = "2b6845cea546604fb4dca4e31414a6a59d39ddcd"
@@ -66,7 +68,7 @@ deps = ["Mmap"]
6668
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"
6769

6870
[[Distributed]]
69-
deps = ["LinearAlgebra", "Random", "Serialization", "Sockets"]
71+
deps = ["Random", "Serialization", "Sockets"]
7072
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
7173

7274
[[DocStringExtensions]]
@@ -99,13 +101,19 @@ uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
99101
deps = ["Random"]
100102
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
101103

104+
[[Infinity]]
105+
deps = ["Dates", "Random", "Requires"]
106+
git-tree-sha1 = "b03a4e0ef454c3a8a309dfe0fbd8bd66ca33bd0c"
107+
uuid = "a303e19e-6eb4-11e9-3b09-cd9505f79100"
108+
version = "0.2.1"
109+
102110
[[Inflate]]
103111
git-tree-sha1 = "f5fc07d4e706b84f72d54eedcc1c13d92fb0871c"
104112
uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
105113
version = "0.1.2"
106114

107115
[[InteractiveUtils]]
108-
deps = ["LinearAlgebra", "Markdown"]
116+
deps = ["Markdown"]
109117
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
110118

111119
[[Intervals]]
@@ -144,10 +152,10 @@ version = "1.0.0"
144152
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
145153

146154
[[LibPQ]]
147-
deps = ["BinaryProvider", "CEnum", "Dates", "Decimals", "DocStringExtensions", "FileWatching", "Intervals", "IterTools", "LayerDicts", "Libdl", "Memento", "OffsetArrays", "Tables", "TimeZones"]
155+
deps = ["BinaryProvider", "CEnum", "Dates", "Decimals", "DocStringExtensions", "FileWatching", "Infinity", "Intervals", "IterTools", "LayerDicts", "Libdl", "Memento", "OffsetArrays", "Tables", "TimeZones"]
148156
path = ".."
149157
uuid = "194296ae-ab2e-5f79-8cd4-7183a0a5a0d1"
150-
version = "1.2.0"
158+
version = "1.3.0"
151159

152160
[[Libdl]]
153161
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
@@ -207,7 +215,7 @@ uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
207215
version = "1.2.0"
208216

209217
[[Pkg]]
210-
deps = ["Dates", "LibGit2", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
218+
deps = ["Dates", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Test", "UUIDs"]
211219
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
212220

213221
[[PooledArrays]]
@@ -239,6 +247,12 @@ git-tree-sha1 = "7b1d07f411bc8ddb7977ec7f377b97b158514fe0"
239247
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
240248
version = "0.2.0"
241249

250+
[[Requires]]
251+
deps = ["UUIDs"]
252+
git-tree-sha1 = "d37400976e98018ee840e0ca4f9d20baa231dc6b"
253+
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
254+
version = "1.0.1"
255+
242256
[[SHA]]
243257
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
244258

@@ -325,7 +339,7 @@ uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53"
325339
version = "1.2.0"
326340

327341
[[UUIDs]]
328-
deps = ["Random"]
342+
deps = ["Random", "SHA"]
329343
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
330344

331345
[[Unicode]]

src/LibPQ.jl

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ using DocStringExtensions
1313
using Decimals
1414
using FileWatching
1515
using Tables
16+
using Infinity: InfExtendedTime, isposinf, ∞
1617
using Intervals
1718
using IterTools: imap
1819
using LayerDicts
@@ -89,4 +90,6 @@ include("tables.jl")
8990

9091
include("asyncresults.jl")
9192

93+
include("deprecated.jl")
94+
9295
end

src/deprecated.jl

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using Base: depwarn
2+
3+
const INF_WARN = Ref(false)
4+
5+
function depwarn_timetype_inf()
6+
if !INF_WARN[]
7+
depwarn("`infinity` support for $(Dates.TimeType) is deprecated. Use `$InfExtendedTime` instead", :depwarn_timetype_inf)
8+
INF_WARN[] = true
9+
end
10+
end

src/parsing.jl

+17
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,10 @@ _DEFAULT_TYPE_MAP[:timestamp] = DateTime
214214
const TIMESTAMP_FORMAT = dateformat"y-m-d HH:MM:SS.s" # .s is optional here
215215
function pqparse(::Type{DateTime}, str::AbstractString)
216216
if str == "infinity"
217+
depwarn_timetype_inf()
217218
return typemax(DateTime)
218219
elseif str == "-infinity"
220+
depwarn_timetype_inf()
219221
return typemin(DateTime)
220222
end
221223

@@ -235,8 +237,10 @@ const TIMESTAMPTZ_FORMATS = (
235237
)
236238
function pqparse(::Type{ZonedDateTime}, str::AbstractString)
237239
if str == "infinity"
240+
depwarn_timetype_inf()
238241
return ZonedDateTime(typemax(DateTime), tz"UTC")
239242
elseif str == "-infinity"
243+
depwarn_timetype_inf()
240244
return ZonedDateTime(typemin(DateTime), tz"UTC")
241245
end
242246

@@ -251,8 +255,10 @@ end
251255
_DEFAULT_TYPE_MAP[:date] = Date
252256
function pqparse(::Type{Date}, str::AbstractString)
253257
if str == "infinity"
258+
depwarn_timetype_inf()
254259
return typemax(Date)
255260
elseif str == "-infinity"
261+
depwarn_timetype_inf()
256262
return typemin(Date)
257263
end
258264

@@ -272,6 +278,17 @@ function pqparse(::Type{Time}, str::AbstractString)
272278
return parse(Time, _trunc_seconds(str))
273279
end
274280

281+
# InfExtendedTime support for Dates.TimeType
282+
function pqparse(::Type{InfExtendedTime{T}}, str::AbstractString) where {T<:Dates.TimeType}
283+
if str == "infinity"
284+
return InfExtendedTime{T}(∞)
285+
elseif str == "-infinity"
286+
return InfExtendedTime{T}(-∞)
287+
end
288+
289+
return InfExtendedTime{T}(pqparse(T, str))
290+
end
291+
275292
# UNIX timestamps
276293
function Base.parse(::Type{DateTime}, pqv::PQValue{PQ_SYSTEM_TYPES[:int8]})
277294
unix2datetime(parse(Int64, pqv))

src/results.jl

+8
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,14 @@ function string_parameter(interval::AbstractInterval)
371371
return String(take!(io))
372372
end
373373

374+
function string_parameter(parameter::InfExtendedTime{T}) where {T<:Dates.TimeType}
375+
if isinf(parameter)
376+
return isposinf(parameter) ? "infinity" : "-infinity"
377+
else
378+
return string_parameter(parameter.finitevalue)
379+
end
380+
end
381+
374382
"""
375383
parameter_pointers(parameters::AbstractVector{<:Parameter}) -> Vector{Ptr{UInt8}}
376384

test/runtests.jl

+60-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ using Dates
44
using DataFrames
55
using DataFrames: eachrow
66
using Decimals
7+
using Infinity
78
using Intervals
89
using IterTools: imap
910
using Memento
@@ -990,6 +991,23 @@ end
990991
end
991992

992993
@testset "Type Conversions" begin
994+
@testset "Deprecations" begin
995+
conn = LibPQ.Connection("dbname=postgres user=$DATABASE_USER"; throw_error=true)
996+
997+
result = execute(conn, "SELECT 'infinity'::timestamp;")
998+
999+
try
1000+
oid = LibPQ.column_oids(result)[1]
1001+
func = result.column_funcs[1]
1002+
1003+
# Parsing this will show a depwarn
1004+
@test (@test_deprecated func(LibPQ.PQValue{oid}(result, 1, 1))) == typemax(DateTime)
1005+
finally
1006+
close(result)
1007+
end
1008+
close(conn)
1009+
end
1010+
9931011
@testset "Automatic" begin
9941012
conn = LibPQ.Connection("dbname=postgres user=$DATABASE_USER"; throw_error=true)
9951013

@@ -1212,7 +1230,13 @@ end
12121230
("'foobar'", Symbol, :foobar),
12131231
("0::int8", DateTime, DateTime(1970, 1, 1, 0)),
12141232
("0::int8", ZonedDateTime, ZonedDateTime(1970, 1, 1, 0, tz"UTC")),
1215-
("'{{{1,2,3},{4,5,6}}}'::int2[]", AbstractArray{Int16}, reshape(Int16[1 2 3; 4 5 6], 1, 2, 3))
1233+
("'{{{1,2,3},{4,5,6}}}'::int2[]", AbstractArray{Int16}, reshape(Int16[1 2 3; 4 5 6], 1, 2, 3)),
1234+
("'infinity'::timestamp", InfExtendedTime{Date}, InfExtendedTime{Date}(∞)),
1235+
("'-infinity'::timestamp", InfExtendedTime{Date}, InfExtendedTime{Date}(-∞)),
1236+
("'infinity'::timestamptz", InfExtendedTime{ZonedDateTime}, InfExtendedTime{ZonedDateTime}(∞)),
1237+
("'-infinity'::timestamptz", InfExtendedTime{ZonedDateTime}, InfExtendedTime{ZonedDateTime}(-∞)),
1238+
("'[2004-10-19 10:23:54-02, infinity)'::tstzrange", Interval{InfExtendedTime{ZonedDateTime}}, Interval{Closed, Open}(ZonedDateTime(2004, 10, 19, 12, 23, 54, tz"UTC"), ∞)),
1239+
("'(-infinity, infinity)'::tstzrange", Interval{InfExtendedTime{ZonedDateTime}}, Interval{InfExtendedTime{ZonedDateTime}, Open, Open}(-∞, ∞)),
12161240
]
12171241

12181242
for (test_str, typ, data) in test_data
@@ -1331,6 +1355,41 @@ end
13311355
end
13321356
end
13331357

1358+
@testset "InfExtendedTime" begin
1359+
tests = (
1360+
("'infinity'::date", InfExtendedTime{Date}(∞)),
1361+
("'-infinity'::date", InfExtendedTime{Date}(-∞)),
1362+
("'infinity'::timestamp", InfExtendedTime{DateTime}(∞)),
1363+
("'-infinity'::timestamp", InfExtendedTime{DateTime}(-∞)),
1364+
("'infinity'::timestamptz", InfExtendedTime{ZonedDateTime}(∞)),
1365+
("'-infinity'::timestamptz", InfExtendedTime{ZonedDateTime}(-∞)),
1366+
("'(-infinity, 2012-01-01]'::daterange", Interval{Open, Closed}(-∞, Date(2012, 1, 1))),
1367+
("'(2012-01-01, infinity]'::daterange", Interval{Open, Closed}(Date(2012, 1, 1), ∞)),
1368+
("'(-infinity, infinity)'::tstzrange", Interval{InfExtendedTime{ZonedDateTime}, Open, Open}(-∞, ∞))
1369+
)
1370+
1371+
@testset for (pg_str, obj) in tests
1372+
result = execute(conn, "SELECT $pg_str = \$1", [obj])
1373+
@test first(first(result))
1374+
close(result)
1375+
end
1376+
end
1377+
1378+
@testset "TimeType" begin
1379+
tests = (
1380+
("'2012-01-01'::date", Date(2012, 1, 1)),
1381+
("'01:01:01.01'::time", Time(1, 1, 1, 10)),
1382+
("'2012-01-01 01:01:01.01'::timestamp", DateTime(2012, 1, 1, 1, 1, 1, 10)),
1383+
("'2012-01-01 01:01:01.01 UTC'::timestamptz", ZonedDateTime(2012, 1, 1, 1, 1, 1, 10, tz"UTC")),
1384+
)
1385+
1386+
@testset for (pg_str, obj) in tests
1387+
result = execute(conn, "SELECT $pg_str = \$1", [obj])
1388+
@test first(first(result))
1389+
close(result)
1390+
end
1391+
end
1392+
13341393
close(conn)
13351394
end
13361395

0 commit comments

Comments
 (0)