From c20b89fb69e892a58e9cfbb9d5192e3785bcd645 Mon Sep 17 00:00:00 2001 From: Jeremiah <4462211+jeremiahpslewis@users.noreply.github.com> Date: Wed, 3 Nov 2021 13:53:41 +0000 Subject: [PATCH 1/9] Add devcontainer --- .devcontainer/Dockerfile | 7 +++++++ .devcontainer/devcontainer.json | 8 ++++++++ 2 files changed, 15 insertions(+) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..c3a8832 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,7 @@ +FROM julia:1.7 + +RUN apt-get update && apt-get install --no-install-recommends -y git && rm -rf /var/lib/apt/lists/* + +COPY Project.toml / + +# RUN julia -e 'using Pkg; Pkg.dev(""); Pkg.instantiate(); Pkg.precompile();' diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..e8a3f51 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,8 @@ + +{ + "extensions": [ + "julialang.language-julia" + ], + "runArgs": ["--privileged"], + "dockerFile": "Dockerfile" +} From 33d5975caaa21581c38e0042a4c2ba8f1bfb2949 Mon Sep 17 00:00:00 2001 From: Jeremiah <4462211+jeremiahpslewis@users.noreply.github.com> Date: Wed, 3 Nov 2021 16:05:21 +0000 Subject: [PATCH 2/9] Run formatter --- test/runtests.jl | 1085 +++++++++++++++++++++++++--------------------- 1 file changed, 595 insertions(+), 490 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 01866ff..b4c4d5d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,10 +2,12 @@ using SQLite using Test, Dates, Random, WeakRefStrings, Tables, DBInterface import Base: +, == + mutable struct Point{T} x::T y::T end + ==(a::Point, b::Point) = a.x == b.x && a.y == b.y mutable struct Point3D{T<:Number} @@ -18,7 +20,7 @@ end triple(x) = 3x function add4(q) - q+4 + q + 4 end mult(args...) = *(args...) str2arr(s) = Vector{UInt8}(s) @@ -30,552 +32,655 @@ sumpoint(p::Point3D, x, y, z) = p + Point3D(x, y, z) dbfile = joinpath(dirname(pathof(SQLite)), "../test/Chinook_Sqlite.sqlite") dbfile2 = joinpath(tempdir(), "test.sqlite") -cp(dbfile, dbfile2; force=true) +cp(dbfile, dbfile2; force = true) chmod(dbfile2, 0o777) @testset "basics" begin -@testset "Julia to SQLite3 type conversion" begin - @test SQLite.sqlitetype(Int) == "INT NOT NULL" - @test SQLite.sqlitetype(Union{Float64, Missing}) == "REAL" - @test SQLite.sqlitetype(String) == "TEXT NOT NULL" - @test SQLite.sqlitetype(Symbol) == "BLOB NOT NULL" - @test SQLite.sqlitetype(Missing) == "NULL" - @test SQLite.sqlitetype(Nothing) == "NULL" - @test SQLite.sqlitetype(Any) == "BLOB" -end + @testset "Julia to SQLite3 type conversion" begin + @test SQLite.sqlitetype(Int) == "INT NOT NULL" + @test SQLite.sqlitetype(Union{Float64,Missing}) == "REAL" + @test SQLite.sqlitetype(String) == "TEXT NOT NULL" + @test SQLite.sqlitetype(Symbol) == "BLOB NOT NULL" + @test SQLite.sqlitetype(Missing) == "NULL" + @test SQLite.sqlitetype(Nothing) == "NULL" + @test SQLite.sqlitetype(Any) == "BLOB" + end -db = SQLite.DB(dbfile2) -db = DBInterface.connect(SQLite.DB, dbfile2) + db = SQLite.DB(dbfile2) + db = DBInterface.connect(SQLite.DB, dbfile2) -# https://github.com/JuliaDatabases/SQLite.jl/issues/207 -ds = DBInterface.execute(db, "SELECT RANDOM() as a FROM Track LIMIT 1") |> columntable -@test ds.a[1] isa Int64 + # https://github.com/JuliaDatabases/SQLite.jl/issues/207 + ds = DBInterface.execute(db, "SELECT RANDOM() as a FROM Track LIMIT 1") |> columntable + @test ds.a[1] isa Int64 -# regular SQLite tests + # regular SQLite tests -@test_throws SQLiteException DBInterface.execute(db, "just some syntax error") -# syntax correct, table missing -@test_throws SQLiteException DBInterface.execute(db, "SELECT name FROM sqlite_nomaster WHERE type='table';") + @test_throws SQLiteException DBInterface.execute(db, "just some syntax error") + # syntax correct, table missing + @test_throws SQLiteException DBInterface.execute( + db, + "SELECT name FROM sqlite_nomaster WHERE type='table';", + ) -@testset "close!(query)" begin - qry = DBInterface.execute(db, "SELECT name FROM sqlite_master WHERE type='table';") - DBInterface.close!(qry) - DBInterface.close!(qry) # test it doesn't throw on double-close -end + @testset "close!(query)" begin + qry = DBInterface.execute(db, "SELECT name FROM sqlite_master WHERE type='table';") + DBInterface.close!(qry) + DBInterface.close!(qry) # test it doesn't throw on double-close + end -ds = DBInterface.execute(db, "SELECT name FROM sqlite_master WHERE type='table';") |> columntable -@test length(ds) == 1 -@test keys(ds) == (:name,) -@test length(ds.name) == 11 - -results1 = SQLite.tables(db) -@test isequal(ds, results1) - -@testset "DBInterface.execute([f])" begin - # pipe approach - results = DBInterface.execute(db, "SELECT * FROM Employee;") |> columntable - @test length(results) == 15 - @test length(results[1]) == 8 - # callable approach - @test isequal(DBInterface.execute(columntable, db, "SELECT * FROM Employee"), results) - employees_stmt = DBInterface.prepare(db, "SELECT * FROM Employee") - @test isequal(columntable(DBInterface.execute(employees_stmt)), results) - @test isequal(DBInterface.execute(columntable, employees_stmt), results) - @testset "throwing from f()" begin - f(::SQLite.Query) = error("I'm throwing!") - @test_throws ErrorException DBInterface.execute(f, employees_stmt) - @test_throws ErrorException DBInterface.execute(f, db, "SELECT * FROM Employee") + ds = + DBInterface.execute(db, "SELECT name FROM sqlite_master WHERE type='table';") |> + columntable + @test length(ds) == 1 + @test keys(ds) == (:name,) + @test length(ds.name) == 11 + + results1 = SQLite.tables(db) + @test isequal(ds, results1) + + @testset "DBInterface.execute([f])" begin + # pipe approach + results = DBInterface.execute(db, "SELECT * FROM Employee;") |> columntable + @test length(results) == 15 + @test length(results[1]) == 8 + # callable approach + @test isequal( + DBInterface.execute(columntable, db, "SELECT * FROM Employee"), + results, + ) + employees_stmt = DBInterface.prepare(db, "SELECT * FROM Employee") + @test isequal(columntable(DBInterface.execute(employees_stmt)), results) + @test isequal(DBInterface.execute(columntable, employees_stmt), results) + @testset "throwing from f()" begin + f(::SQLite.Query) = error("I'm throwing!") + @test_throws ErrorException DBInterface.execute(f, employees_stmt) + @test_throws ErrorException DBInterface.execute(f, db, "SELECT * FROM Employee") + end + DBInterface.close!(employees_stmt) end - DBInterface.close!(employees_stmt) -end -@testset "isempty(::Query)" begin - @test !DBInterface.execute(isempty, db, "SELECT * FROM Employee") - @test DBInterface.execute(isempty, db, "SELECT * FROM Employee WHERE FirstName='Joanne'") -end + @testset "isempty(::Query)" begin + @test !DBInterface.execute(isempty, db, "SELECT * FROM Employee") + @test DBInterface.execute( + isempty, + db, + "SELECT * FROM Employee WHERE FirstName='Joanne'", + ) + end -@testset "empty query has correct schema and return type" begin - empty_scheme = DBInterface.execute(Tables.schema, db, "SELECT * FROM Employee WHERE FirstName='Joanne'") - all_scheme = DBInterface.execute(Tables.schema, db, "SELECT * FROM Employee WHERE FirstName='Joanne'") - @test empty_scheme.names == all_scheme.names - @test all(ea -> ea[1] <: ea[2], zip(empty_scheme.types, all_scheme.types)) + @testset "empty query has correct schema and return type" begin + empty_scheme = DBInterface.execute( + Tables.schema, + db, + "SELECT * FROM Employee WHERE FirstName='Joanne'", + ) + all_scheme = DBInterface.execute( + Tables.schema, + db, + "SELECT * FROM Employee WHERE FirstName='Joanne'", + ) + @test empty_scheme.names == all_scheme.names + @test all(ea -> ea[1] <: ea[2], zip(empty_scheme.types, all_scheme.types)) + + empty_tbl = DBInterface.execute( + columntable, + db, + "SELECT * FROM Employee WHERE FirstName='Joanne'", + ) + all_tbl = DBInterface.execute(columntable, db, "SELECT * FROM Employee") + @test propertynames(empty_tbl) == propertynames(all_tbl) + @test all( + col -> + eltype(empty_tbl[col]) == Missing || + eltype(empty_tbl[col]) >: eltype(all_tbl[col]), + propertynames(all_tbl), + ) + end - empty_tbl = DBInterface.execute(columntable, db, "SELECT * FROM Employee WHERE FirstName='Joanne'") - all_tbl = DBInterface.execute(columntable, db, "SELECT * FROM Employee") - @test propertynames(empty_tbl) == propertynames(all_tbl) - @test all(col -> eltype(empty_tbl[col]) == Missing || eltype(empty_tbl[col]) >: eltype(all_tbl[col]), propertynames(all_tbl)) -end + DBInterface.execute(db, "create table temp as select * from album") + DBInterface.execute(db, "alter table temp add column colyear int") + DBInterface.execute(db, "update temp set colyear = 2014") + r = DBInterface.execute(db, "select * from temp limit 10") |> columntable + @test length(r) == 4 && length(r[1]) == 10 + @test all(==(2014), r[4]) -DBInterface.execute(db, "create table temp as select * from album") -DBInterface.execute(db, "alter table temp add column colyear int") -DBInterface.execute(db, "update temp set colyear = 2014") -r = DBInterface.execute(db, "select * from temp limit 10") |> columntable -@test length(r) == 4 && length(r[1]) == 10 -@test all(==(2014), r[4]) + @testset "commit/rollback tests" begin + @test_throws SQLiteException SQLite.rollback(db) + @test_throws SQLiteException SQLite.commit(db) + + SQLite.transaction(db) + DBInterface.execute(db, "update temp set colyear = 2015") + SQLite.rollback(db) + r = DBInterface.execute(db, "select * from temp limit 10") |> columntable + @test all(==(2014), r[4]) + + SQLite.transaction(db) + DBInterface.execute(db, "update temp set colyear = 2015") + SQLite.commit(db) + r = DBInterface.execute(db, "select * from temp limit 10") |> columntable + @test all(==(2015), r[4]) + end -@testset "commit/rollback tests" begin - @test_throws SQLiteException SQLite.rollback(db) - @test_throws SQLiteException SQLite.commit(db) + DBInterface.execute(db, "alter table temp add column dates blob") + stmt = DBInterface.prepare(db, "update temp set dates = ?") + DBInterface.execute(stmt, (Date(2014, 1, 1),)) - SQLite.transaction(db) - DBInterface.execute(db, "update temp set colyear = 2015") - SQLite.rollback(db) r = DBInterface.execute(db, "select * from temp limit 10") |> columntable - @test all(==(2014), r[4]) + @test length(r) == 5 && length(r[1]) == 10 + @test typeof(r[5][1]) == Date + @test all(Bool[x == Date(2014, 1, 1) for x in r[5]]) + DBInterface.execute(db, "drop table temp") + + rng = Dates.Date(2013):Dates.Day(1):Dates.Date(2013, 1, 5) + dt = (i = collect(rng), j = collect(rng)) + tablename = dt |> SQLite.load!(db, "temp") + r = DBInterface.execute(db, "select * from $tablename") |> columntable + @test length(r) == 2 && length(r[1]) == 5 + @test all([i for i in r[1]] .== collect(rng)) + @test all([typeof(i) for i in r[1]] .== Dates.Date) + SQLite.drop!(db, "$tablename") + + DBInterface.execute(db, "CREATE TABLE temp AS SELECT * FROM Album") + r = DBInterface.execute(db, "SELECT * FROM temp LIMIT ?", [3]) |> columntable + @test length(r) == 3 && length(r[1]) == 3 + r = + DBInterface.execute(db, "SELECT * FROM temp WHERE Title LIKE ?", ["%time%"]) |> + columntable + @test r[1] == [76, 111, 187] + DBInterface.execute(db, "INSERT INTO temp VALUES (?1, ?3, ?2)", [0, 0, "Test Album"]) + r = DBInterface.execute(db, "SELECT * FROM temp WHERE AlbumId = 0") |> columntable + @test r[1][1] == 0 + @test r[2][1] == "Test Album" + @test r[3][1] == 0 + SQLite.drop!(db, "temp") + + DBInterface.execute(db, "CREATE TABLE temp AS SELECT * FROM Album") + r = DBInterface.execute(db, "SELECT * FROM temp LIMIT :a", (a = 3,)) |> columntable + @test length(r) == 3 && length(r[1]) == 3 + r = DBInterface.execute(db, "SELECT * FROM temp LIMIT :a", a = 3) |> columntable + @test length(r) == 3 && length(r[1]) == 3 + r = + DBInterface.execute( + db, + "SELECT * FROM temp WHERE Title LIKE @word", + (word = "%time%",), + ) |> columntable + @test r[1] == [76, 111, 187] + DBInterface.execute( + db, + "INSERT INTO temp VALUES (@lid, :title, \$rid)", + (rid = 1, lid = 0, title = "Test Album"), + ) + DBInterface.execute( + db, + "INSERT INTO temp VALUES (@lid, :title, \$rid)", + rid = 3, + lid = 400, + title = "Test2 Album", + ) + r = + DBInterface.execute(db, "SELECT * FROM temp WHERE AlbumId IN (0, 400)") |> + columntable + @test r[1] == [0, 400] + @test r[2] == ["Test Album", "Test2 Album"] + @test r[3] == [1, 3] + SQLite.drop!(db, "temp") + + SQLite.register(db, SQLite.regexp, nargs = 2, name = "regexp") + r = + DBInterface.execute( + db, + SQLite.@sr_str( + "SELECT LastName FROM Employee WHERE BirthDate REGEXP '^\\d{4}-08'" + ) + ) |> columntable + @test r[1][1] == "Peacock" + + SQLite.register(db, identity, nargs = 1, name = "identity") + r = + DBInterface.execute( + db, + """SELECT identity("abc") as x, "abc" == identity("abc") as cmp""", + ) |> columntable + @test first(r.x) == "abc" + @test first(r.cmp) == 1 + + @test_throws AssertionError SQLite.register(db, triple, nargs = 186) + SQLite.register(db, triple, nargs = 1) + r = + DBInterface.execute( + db, + "SELECT triple(Total) FROM Invoice ORDER BY InvoiceId LIMIT 5", + ) |> columntable + s = + DBInterface.execute(db, "SELECT Total FROM Invoice ORDER BY InvoiceId LIMIT 5") |> + columntable + for (i, j) in zip(r[1], s[1]) + @test abs(i - 3 * j) < 0.02 + end - SQLite.transaction(db) - DBInterface.execute(db, "update temp set colyear = 2015") - SQLite.commit(db) - r = DBInterface.execute(db, "select * from temp limit 10") |> columntable - @test all(==(2015), r[4]) -end + SQLite.@register db add4 + r = DBInterface.execute(db, "SELECT add4(AlbumId) FROM Album") |> columntable + s = DBInterface.execute(db, "SELECT AlbumId FROM Album") |> columntable + @test r[1][1] == s[1][1] + 4 + + SQLite.@register db mult + r = DBInterface.execute(db, "SELECT GenreId, UnitPrice FROM Track") |> columntable + s = DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice) FROM Track") |> columntable + @test (r[1][1] * r[2][1]) == s[1][1] + t = + DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice, 3, 4) FROM Track") |> + columntable + @test (r[1][1] * r[2][1] * 3 * 4) == t[1][1] + + SQLite.@register db sin + u = + DBInterface.execute(db, "select sin(milliseconds) from track limit 5") |> + columntable + @test all(-1 .< convert(Vector{Float64}, u[1]) .< 1) + + SQLite.register(db, hypot; nargs = 2, name = "hypotenuse") + v = + DBInterface.execute( + db, + "select hypotenuse(Milliseconds,bytes) from track limit 5", + ) |> columntable + @test [round(Int, i) for i in v[1]] == [11175621, 5521062, 3997652, 4339106, 6301714] + + SQLite.@register db str2arr + r = + DBInterface.execute(db, "SELECT str2arr(LastName) FROM Employee LIMIT 2") |> + columntable + @test r[1][2] == UInt8[0x45, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73] + + SQLite.@register db big + r = DBInterface.execute(db, "SELECT big(5)") |> columntable + @test r[1][1] == big(5) + @test typeof(r[1][1]) == BigInt + + SQLite.register(db, 0, doublesum_step, doublesum_final, name = "doublesum") + r = DBInterface.execute(db, "SELECT doublesum(UnitPrice) FROM Track") |> columntable + s = DBInterface.execute(db, "SELECT UnitPrice FROM Track") |> columntable + @test abs(r[1][1] - 2 * sum(convert(Vector{Float64}, s[1]))) < 0.02 + + + SQLite.register(db, 0, mycount) + r = DBInterface.execute(db, "SELECT mycount(TrackId) FROM PlaylistTrack") |> columntable + s = DBInterface.execute(db, "SELECT count(TrackId) FROM PlaylistTrack") |> columntable + @test r[1][1] == s[1][1] + + SQLite.register(db, big(0), bigsum) + r = DBInterface.execute(db, "SELECT bigsum(TrackId) FROM PlaylistTrack") |> columntable + s = DBInterface.execute(db, "SELECT TrackId FROM PlaylistTrack") |> columntable + @test r[1][1] == big(sum(convert(Vector{Int}, s[1]))) + + DBInterface.execute(db, "CREATE TABLE points (x INT, y INT, z INT)") + DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (1, 2, 3)) + DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (4, 5, 6)) + DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (7, 8, 9)) + + SQLite.register(db, Point3D(0, 0, 0), sumpoint) + r = DBInterface.execute(db, "SELECT sumpoint(x, y, z) FROM points") |> columntable + @test r[1][1] == Point3D(12, 15, 18) + SQLite.drop!(db, "points") + + db2 = DBInterface.connect(SQLite.DB) + DBInterface.execute(db2, "CREATE TABLE tab1 (r REAL, s INT)") + + @test_throws SQLiteException SQLite.drop!(db2, "nonexistant") + # should not throw anything + SQLite.drop!(db2, "nonexistant", ifexists = true) + # should drop "tab2" + SQLite.drop!(db2, "tab2", ifexists = true) + @test !in("tab2", SQLite.tables(db2)[1]) + + SQLite.drop!(db, "sqlite_stat1", ifexists = true) + tables = SQLite.tables(db) + @test length(tables[1]) == 11 + + #Test removeduplicates! + db = SQLite.DB() #In case the order of tests is changed + dt = (ints = Int64[1, 1, 2, 2, 3], strs = ["A", "A", "B", "C", "C"]) + tablename = dt |> SQLite.load!(db, "temp") + SQLite.removeduplicates!(db, "temp", ["ints", "strs"]) #New format + dt3 = DBInterface.execute(db, "Select * from temp") |> columntable + @test dt3[1][1] == 1 + @test dt3[2][1] == "A" + @test dt3[1][2] == 2 + @test dt3[2][2] == "B" + @test dt3[1][3] == 2 + @test dt3[2][3] == "C" + + # issue #104 + db = SQLite.DB() #In case the order of tests is changed + DBInterface.execute(db, "CREATE TABLE IF NOT EXISTS tbl(a INTEGER);") + stmt = DBInterface.prepare(db, "INSERT INTO tbl (a) VALUES (@a);") + SQLite.bind!(stmt, "@a", 1) + SQLite.clear!(stmt) + + @testset "SQLite to Julia type conversion" begin + binddb = SQLite.DB() + DBInterface.execute( + binddb, + "CREATE TABLE temp (n NULL, i1 INT, i2 integer, + f1 REAL, f2 FLOAT, f3 NUMERIC, + s1 TEXT, s2 CHAR(10), s3 VARCHAR(15), s4 NVARCHAR(5), + d1 DATETIME, ts1 TIMESTAMP, + b BLOB, + x1 UNKNOWN1, x2 UNKNOWN2)", + ) + DBInterface.execute( + binddb, + "INSERT INTO temp VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + [ + missing, + Int64(6), + Int64(4), + 6.4, + 6.3, + Int64(7), + "some long text", + "short text", + "another text", + "short", + "2021-02-21", + "2021-02-12::1532", + b"bytearray", + "actually known", + 435, + ], + ) + rr = (;) # just to have the var declared + @test_logs( + ( + :warn, + "Unsupported SQLite declared type UNKNOWN1, falling back to String type", + ), + ( + :warn, + "Unsupported SQLite declared type UNKNOWN2, falling back to $(Int64) type", + ), + rr = DBInterface.execute(rowtable, binddb, "SELECT * FROM temp") + ) + @test length(rr) == 1 + r = first(rr) + @test typeof.(Tuple(r)) == ( + Missing, + Int64, + Int64, + Float64, + Float64, + Int64, + String, + String, + String, + String, + String, + String, + Base.CodeUnits{UInt8,String}, + String, + Int64, + ) + end -DBInterface.execute(db, "alter table temp add column dates blob") -stmt = DBInterface.prepare(db, "update temp set dates = ?") -DBInterface.execute(stmt, (Date(2014,1,1),)) - -r = DBInterface.execute(db, "select * from temp limit 10") |> columntable -@test length(r) == 5 && length(r[1]) == 10 -@test typeof(r[5][1]) == Date -@test all(Bool[x == Date(2014,1,1) for x in r[5]]) -DBInterface.execute(db, "drop table temp") - -rng = Dates.Date(2013):Dates.Day(1):Dates.Date(2013,1,5) -dt = (i=collect(rng), j=collect(rng)) -tablename = dt |> SQLite.load!(db, "temp") -r = DBInterface.execute(db, "select * from $tablename") |> columntable -@test length(r) == 2 && length(r[1]) == 5 -@test all([i for i in r[1]] .== collect(rng)) -@test all([typeof(i) for i in r[1]] .== Dates.Date) -SQLite.drop!(db, "$tablename") - -DBInterface.execute(db, "CREATE TABLE temp AS SELECT * FROM Album") -r = DBInterface.execute(db, "SELECT * FROM temp LIMIT ?", [3]) |> columntable -@test length(r) == 3 && length(r[1]) == 3 -r = DBInterface.execute(db, "SELECT * FROM temp WHERE Title LIKE ?", ["%time%"]) |> columntable -@test r[1] == [76, 111, 187] -DBInterface.execute(db, "INSERT INTO temp VALUES (?1, ?3, ?2)", [0,0, "Test Album"]) -r = DBInterface.execute(db, "SELECT * FROM temp WHERE AlbumId = 0") |> columntable -@test r[1][1] == 0 -@test r[2][1] == "Test Album" -@test r[3][1] == 0 -SQLite.drop!(db, "temp") - -DBInterface.execute(db, "CREATE TABLE temp AS SELECT * FROM Album") -r = DBInterface.execute(db, "SELECT * FROM temp LIMIT :a", (a=3,)) |> columntable -@test length(r) == 3 && length(r[1]) == 3 -r = DBInterface.execute(db, "SELECT * FROM temp LIMIT :a", a=3) |> columntable -@test length(r) == 3 && length(r[1]) == 3 -r = DBInterface.execute(db, "SELECT * FROM temp WHERE Title LIKE @word", (word="%time%",)) |> columntable -@test r[1] == [76, 111, 187] -DBInterface.execute(db, "INSERT INTO temp VALUES (@lid, :title, \$rid)", (rid=1, lid=0, title="Test Album")) -DBInterface.execute(db, "INSERT INTO temp VALUES (@lid, :title, \$rid)", rid=3, lid=400, title="Test2 Album") -r = DBInterface.execute(db, "SELECT * FROM temp WHERE AlbumId IN (0, 400)") |> columntable -@test r[1] == [0, 400] -@test r[2] == ["Test Album", "Test2 Album"] -@test r[3] == [1, 3] -SQLite.drop!(db, "temp") - -SQLite.register(db, SQLite.regexp, nargs=2, name="regexp") -r = DBInterface.execute(db, SQLite.@sr_str("SELECT LastName FROM Employee WHERE BirthDate REGEXP '^\\d{4}-08'")) |> columntable -@test r[1][1] == "Peacock" - -SQLite.register(db, identity, nargs=1, name="identity") -r = DBInterface.execute(db, """SELECT identity("abc") as x, "abc" == identity("abc") as cmp""") |> columntable -@test first(r.x) == "abc" -@test first(r.cmp) == 1 - -@test_throws AssertionError SQLite.register(db, triple, nargs=186) -SQLite.register(db, triple, nargs=1) -r = DBInterface.execute(db, "SELECT triple(Total) FROM Invoice ORDER BY InvoiceId LIMIT 5") |> columntable -s = DBInterface.execute(db, "SELECT Total FROM Invoice ORDER BY InvoiceId LIMIT 5") |> columntable -for (i, j) in zip(r[1], s[1]) - @test abs(i - 3*j) < 0.02 -end + ############################################ -SQLite.@register db add4 -r = DBInterface.execute(db, "SELECT add4(AlbumId) FROM Album") |> columntable -s = DBInterface.execute(db, "SELECT AlbumId FROM Album") |> columntable -@test r[1][1] == s[1][1] + 4 - -SQLite.@register db mult -r = DBInterface.execute(db, "SELECT GenreId, UnitPrice FROM Track") |> columntable -s = DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice) FROM Track") |> columntable -@test (r[1][1] * r[2][1]) == s[1][1] -t = DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice, 3, 4) FROM Track") |> columntable -@test (r[1][1] * r[2][1] * 3 * 4) == t[1][1] - -SQLite.@register db sin -u = DBInterface.execute(db, "select sin(milliseconds) from track limit 5") |> columntable -@test all(-1 .< convert(Vector{Float64},u[1]) .< 1) - -SQLite.register(db, hypot; nargs=2, name="hypotenuse") -v = DBInterface.execute(db, "select hypotenuse(Milliseconds,bytes) from track limit 5") |> columntable -@test [round(Int,i) for i in v[1]] == [11175621,5521062,3997652,4339106,6301714] - -SQLite.@register db str2arr -r = DBInterface.execute(db, "SELECT str2arr(LastName) FROM Employee LIMIT 2") |> columntable -@test r[1][2] == UInt8[0x45,0x64,0x77,0x61,0x72,0x64,0x73] - -SQLite.@register db big -r = DBInterface.execute(db, "SELECT big(5)") |> columntable -@test r[1][1] == big(5) -@test typeof(r[1][1]) == BigInt - -SQLite.register(db, 0, doublesum_step, doublesum_final, name="doublesum") -r = DBInterface.execute(db, "SELECT doublesum(UnitPrice) FROM Track") |> columntable -s = DBInterface.execute(db, "SELECT UnitPrice FROM Track") |> columntable -@test abs(r[1][1] - 2*sum(convert(Vector{Float64},s[1]))) < 0.02 - - -SQLite.register(db, 0, mycount) -r = DBInterface.execute(db, "SELECT mycount(TrackId) FROM PlaylistTrack") |> columntable -s = DBInterface.execute(db, "SELECT count(TrackId) FROM PlaylistTrack") |> columntable -@test r[1][1] == s[1][1] - -SQLite.register(db, big(0), bigsum) -r = DBInterface.execute(db, "SELECT bigsum(TrackId) FROM PlaylistTrack") |> columntable -s = DBInterface.execute(db, "SELECT TrackId FROM PlaylistTrack") |> columntable -@test r[1][1] == big(sum(convert(Vector{Int},s[1]))) - -DBInterface.execute(db, "CREATE TABLE points (x INT, y INT, z INT)") -DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (1, 2, 3)) -DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (4, 5, 6)) -DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (7, 8, 9)) - -SQLite.register(db, Point3D(0, 0, 0), sumpoint) -r = DBInterface.execute(db, "SELECT sumpoint(x, y, z) FROM points") |> columntable -@test r[1][1] == Point3D(12, 15, 18) -SQLite.drop!(db, "points") - -db2 = DBInterface.connect(SQLite.DB) -DBInterface.execute(db2, "CREATE TABLE tab1 (r REAL, s INT)") - -@test_throws SQLiteException SQLite.drop!(db2, "nonexistant") -# should not throw anything -SQLite.drop!(db2, "nonexistant", ifexists=true) -# should drop "tab2" -SQLite.drop!(db2, "tab2", ifexists=true) -@test !in("tab2", SQLite.tables(db2)[1]) - -SQLite.drop!(db, "sqlite_stat1", ifexists=true) -tables = SQLite.tables(db) -@test length(tables[1]) == 11 - -#Test removeduplicates! -db = SQLite.DB() #In case the order of tests is changed -dt = (ints=Int64[1,1,2,2,3], strs=["A", "A", "B", "C", "C"]) -tablename = dt |> SQLite.load!(db, "temp") -SQLite.removeduplicates!(db, "temp", ["ints", "strs"]) #New format -dt3 = DBInterface.execute(db, "Select * from temp") |> columntable -@test dt3[1][1] == 1 -@test dt3[2][1] == "A" -@test dt3[1][2] == 2 -@test dt3[2][2] == "B" -@test dt3[1][3] == 2 -@test dt3[2][3] == "C" - -# issue #104 -db = SQLite.DB() #In case the order of tests is changed -DBInterface.execute(db, "CREATE TABLE IF NOT EXISTS tbl(a INTEGER);") -stmt = DBInterface.prepare(db, "INSERT INTO tbl (a) VALUES (@a);") -SQLite.bind!(stmt, "@a", 1) -SQLite.clear!(stmt) - -@testset "SQLite to Julia type conversion" begin - binddb = SQLite.DB() - DBInterface.execute(binddb, - "CREATE TABLE temp (n NULL, i1 INT, i2 integer, - f1 REAL, f2 FLOAT, f3 NUMERIC, - s1 TEXT, s2 CHAR(10), s3 VARCHAR(15), s4 NVARCHAR(5), - d1 DATETIME, ts1 TIMESTAMP, - b BLOB, - x1 UNKNOWN1, x2 UNKNOWN2)") - DBInterface.execute(binddb, "INSERT INTO temp VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", - [missing, Int64(6), Int64(4), - 6.4, 6.3, Int64(7), - "some long text", "short text", "another text", "short", - "2021-02-21", "2021-02-12::1532", - b"bytearray", - "actually known", 435]) - rr = (;) # just to have the var declared - @test_logs( - (:warn, "Unsupported SQLite declared type UNKNOWN1, falling back to String type"), - (:warn, "Unsupported SQLite declared type UNKNOWN2, falling back to $(Int64) type"), - rr = DBInterface.execute(rowtable, binddb, "SELECT * FROM temp")) - @test length(rr) == 1 - r = first(rr) - @test typeof.(Tuple(r)) == (Missing, Int64, Int64, - Float64, Float64, Int64, - String, String, String, String, - String, String, - Base.CodeUnits{UInt8, String}, - String, Int64) -end + #test for #158 + @test_throws SQLiteException SQLite.DB("nonexistentdir/not_there.db") -############################################ + #test for #180 (Query) + param = "Hello!" + query = DBInterface.execute(SQLite.DB(), "SELECT ?1 UNION ALL SELECT ?1", [param]) + param = "x" + for row in query + @test row[1] == "Hello!" + GC.gc() # this must NOT garbage collect the "Hello!" bound value + end -#test for #158 -@test_throws SQLiteException SQLite.DB("nonexistentdir/not_there.db") + db = SQLite.DB() + DBInterface.execute(db, "CREATE TABLE T (a TEXT, PRIMARY KEY (a))") -#test for #180 (Query) -param = "Hello!" -query = DBInterface.execute(SQLite.DB(), "SELECT ?1 UNION ALL SELECT ?1", [param]) -param = "x" -for row in query - @test row[1] == "Hello!" - GC.gc() # this must NOT garbage collect the "Hello!" bound value -end + q = DBInterface.prepare(db, "INSERT INTO T VALUES(?)") + DBInterface.execute(q, ["a"]) -db = SQLite.DB() -DBInterface.execute(db, "CREATE TABLE T (a TEXT, PRIMARY KEY (a))") + SQLite.bind!(q, 1, "a") + @test_throws SQLiteException DBInterface.execute(q) -q = DBInterface.prepare(db, "INSERT INTO T VALUES(?)") -DBInterface.execute(q, ["a"]) + @test SQLite.@OK SQLite.enable_load_extension(db) + @testset "show(DB)" begin + io = IOBuffer() + show(io, db) + @test String(take!(io)) == "SQLite.DB(\":memory:\")" + end + DBInterface.close!(db) -SQLite.bind!(q, 1, "a") -@test_throws SQLiteException DBInterface.execute(q) + db = SQLite.DB() -@test SQLite.@OK SQLite.enable_load_extension(db) -@testset "show(DB)" begin - io = IOBuffer() - show(io, db) - @test String(take!(io)) == "SQLite.DB(\":memory:\")" -end -DBInterface.close!(db) + @testset "SQLite.execute()" begin + DBInterface.execute(db, "CREATE TABLE T (x INT UNIQUE)") -db = SQLite.DB() + q = DBInterface.prepare(db, "INSERT INTO T VALUES(?)") + SQLite.execute(q, (1,)) + r = DBInterface.execute(db, "SELECT * FROM T") |> columntable + @test r[1] == [1] -@testset "SQLite.execute()" begin - DBInterface.execute(db, "CREATE TABLE T (x INT UNIQUE)") + SQLite.execute(q, [2]) + r = DBInterface.execute(db, "SELECT * FROM T") |> columntable + @test r[1] == [1, 2] - q = DBInterface.prepare(db, "INSERT INTO T VALUES(?)") - SQLite.execute(q, (1,)) - r = DBInterface.execute(db, "SELECT * FROM T") |> columntable - @test r[1] == [1] + q = DBInterface.prepare(db, "INSERT INTO T VALUES(:x)") + SQLite.execute(q, Dict(:x => 3)) + r = DBInterface.execute(columntable, db, "SELECT * FROM T") + @test r[1] == [1, 2, 3] + + SQLite.execute(q, x = 4) + r = DBInterface.execute(columntable, db, "SELECT * FROM T") + @test r[1] == [1, 2, 3, 4] + + SQLite.execute(db, "INSERT INTO T VALUES(:x)", x = 5) + r = DBInterface.execute(columntable, db, "SELECT * FROM T") + @test r[1] == [1, 2, 3, 4, 5] + end + + r = DBInterface.execute(db, strip(" SELECT * FROM T ")) |> columntable + @test r[1] == [1, 2, 3, 4, 5] + + @test SQLite.esc_id(["1", "2", "3"]) == "\"1\",\"2\",\"3\"" + + SQLite.createindex!(db, "T", "x", "x_index"; unique = false) + inds = SQLite.indices(db) + @test last(inds.name) == "x" + SQLite.dropindex!(db, "x") + @test length(SQLite.indices(db).name) == 1 + + cols = SQLite.columns(db, "T") + @test cols.name == ["x"] + + @test SQLite.last_insert_rowid(db) == 5 + + r = DBInterface.execute(db, "SELECT * FROM T") + @test Tables.istable(r) + @test Tables.rowaccess(r) + @test Tables.rows(r) === r + @test Base.IteratorSize(typeof(r)) == Base.SizeUnknown() + @test eltype(r) == SQLite.Row + row = first(r) + SQLite.reset!(r) + row2 = first(r) + @test row[:x] == row2[:x] + @test propertynames(row) == [:x] + @test DBInterface.lastrowid(r) == 5 - SQLite.execute(q, [2]) r = DBInterface.execute(db, "SELECT * FROM T") |> columntable - @test r[1] == [1, 2] + SQLite.load!(nothing, Tables.rows(r), db, "T2", SQLite.tableinfo(db, "T2")) + r2 = DBInterface.execute(db, "SELECT * FROM T2") |> columntable + @test r == r2 - q = DBInterface.prepare(db, "INSERT INTO T VALUES(:x)") - SQLite.execute(q, Dict(:x => 3)) - r = DBInterface.execute(columntable, db, "SELECT * FROM T") - @test r[1] == [1, 2, 3] + # throw informative error on duplicate column names #193 + @test_throws SQLiteException SQLite.load!((a = [1, 2, 3], A = [1, 2, 3]), db) - SQLite.execute(q, x=4) - r = DBInterface.execute(columntable, db, "SELECT * FROM T") - @test r[1] == [1, 2, 3, 4] + db = SQLite.DB() + # Table should map by name #216 + tbl1 = (a = [1, 2, 3], b = [4, 5, 6]) + tbl2 = (b = [7, 8, 9], a = [4, 5, 6]) + SQLite.load!(tbl1, db, "data") + SQLite.load!(tbl2, db, "data") - SQLite.execute(db, "INSERT INTO T VALUES(:x)", x=5) - r = DBInterface.execute(columntable, db, "SELECT * FROM T") - @test r[1] == [1, 2, 3, 4, 5] -end + res = DBInterface.execute(db, "SELECT * FROM data") |> columntable + expected = (a = [1, 2, 3, 4, 5, 6], b = [4, 5, 6, 7, 8, 9]) + @test res == expected -r = DBInterface.execute(db, strip(" SELECT * FROM T ")) |> columntable -@test r[1] == [1, 2, 3, 4, 5] - -@test SQLite.esc_id(["1", "2", "3"]) == "\"1\",\"2\",\"3\"" - -SQLite.createindex!(db, "T", "x", "x_index"; unique=false) -inds = SQLite.indices(db) -@test last(inds.name) == "x" -SQLite.dropindex!(db, "x") -@test length(SQLite.indices(db).name) == 1 - -cols = SQLite.columns(db, "T") -@test cols.name == ["x"] - -@test SQLite.last_insert_rowid(db) == 5 - -r = DBInterface.execute(db, "SELECT * FROM T") -@test Tables.istable(r) -@test Tables.rowaccess(r) -@test Tables.rows(r) === r -@test Base.IteratorSize(typeof(r)) == Base.SizeUnknown() -@test eltype(r) == SQLite.Row -row = first(r) -SQLite.reset!(r) -row2 = first(r) -@test row[:x] == row2[:x] -@test propertynames(row) == [:x] -@test DBInterface.lastrowid(r) == 5 - -r = DBInterface.execute(db, "SELECT * FROM T") |> columntable -SQLite.load!(nothing, Tables.rows(r), db, "T2", SQLite.tableinfo(db, "T2")) -r2 = DBInterface.execute(db, "SELECT * FROM T2") |> columntable -@test r == r2 - -# throw informative error on duplicate column names #193 -@test_throws SQLiteException SQLite.load!((a=[1,2,3], A=[1,2,3]), db) - -db = SQLite.DB() -# Table should map by name #216 -tbl1 = (a = [1, 2, 3], b = [4, 5, 6]) -tbl2 = (b = [7, 8, 9], a = [4, 5, 6]) -SQLite.load!(tbl1, db, "data") -SQLite.load!(tbl2, db, "data") - -res = DBInterface.execute(db, "SELECT * FROM data") |> columntable -expected = (a=[1, 2, 3, 4, 5, 6], b=[4, 5, 6, 7, 8, 9]) -@test res == expected - -# Table should error if names don't match #216 -tbl3 = (c = [7, 8, 9], a = [4, 5, 6]) -@test_throws SQLiteException SQLite.load!(tbl3, db, "data") - - -# Test busy_timeout -@test SQLite.busy_timeout(db, 300) == 0 - -# 253, ensure query column names are unique by default -db = SQLite.DB() -res = DBInterface.execute(db, "select 1 as x2, 2 as x2, 3 as x2, 4 as x2_2") |> columntable -@test res == (x2 = [1], x2_1 = [2], x2_2 = [3], x2_2_1 = [4]) - -@testset "load!()/drop!() table name escaping" begin - tbl = (a = [1, 2, 3], b = ["a", "b", "c"]) - SQLite.load!(tbl, db, "escape 10.0%") - r = DBInterface.execute(db, "SELECT * FROM $(SQLite.esc_id("escape 10.0%"))") |> columntable - @test r == tbl - SQLite.drop!(db, "escape 10.0%"); -end + # Table should error if names don't match #216 + tbl3 = (c = [7, 8, 9], a = [4, 5, 6]) + @test_throws SQLiteException SQLite.load!(tbl3, db, "data") -@testset "load!() column names escaping" begin - tbl = NamedTuple{(:a, Symbol("50.0%"))}(([1, 2, 3], ["a", "b", "c"])) - SQLite.load!(tbl, db, "escape_colnames") - r = DBInterface.execute(db, "SELECT * FROM escape_colnames") |> columntable - @test r == tbl - SQLite.drop!(db, "escape_colnames"); -end -@testset "Bool column data" begin - tbl = (a = [true, false, false], b = [false, missing, true]) - SQLite.load!(tbl, db, "bool_data") - r = DBInterface.execute(db, "SELECT * FROM bool_data") |> columntable - @test isequal(r, (a = [1, 0, 0], b = [0, missing, 1])) - SQLite.drop!(db, "bool_data"); -end + # Test busy_timeout + @test SQLite.busy_timeout(db, 300) == 0 -@testset "serialization edgecases" begin + # 253, ensure query column names are unique by default db = SQLite.DB() - r = DBInterface.execute(db, "SELECT zeroblob(2) as b") |> columntable - @test first(r.b) == [0, 0] - r = DBInterface.execute(db, "SELECT zeroblob(0) as b") |> columntable - @test first(r.b) == [] -end + res = + DBInterface.execute(db, "select 1 as x2, 2 as x2, 3 as x2, 4 as x2_2") |> + columntable + @test res == (x2 = [1], x2_1 = [2], x2_2 = [3], x2_2_1 = [4]) + + @testset "load!()/drop!() table name escaping" begin + tbl = (a = [1, 2, 3], b = ["a", "b", "c"]) + SQLite.load!(tbl, db, "escape 10.0%") + r = + DBInterface.execute(db, "SELECT * FROM $(SQLite.esc_id("escape 10.0%"))") |> + columntable + @test r == tbl + SQLite.drop!(db, "escape 10.0%") + end -@testset "Stmt scope" begin - dbfile = joinpath(tempdir(), "test_stmt_scope.sqlite") - db = SQLite.DB(dbfile) - tbl = (a = [1, 2, 3], b = ["a", "b", "c"]) - - @testset "explicit finalization by finalize_statements!(db)" begin - SQLite.load!(tbl, db, "test_table") - stmt = SQLite.Stmt(db, "SELECT a, b FROM test_table") - @test SQLite.isready(stmt) - @test SQLite.execute(stmt) == 100 - # test cannot drop the table locked by the statement - @test_throws SQLiteException SQLite.drop!(db, "test_table") - SQLite.finalize_statements!(db) - @test !SQLite.isready(stmt) - SQLite.drop!(db, "test_table") - DBInterface.close!(stmt) # test can call close!() 2nd time + @testset "load!() column names escaping" begin + tbl = NamedTuple{(:a, Symbol("50.0%"))}(([1, 2, 3], ["a", "b", "c"])) + SQLite.load!(tbl, db, "escape_colnames") + r = DBInterface.execute(db, "SELECT * FROM escape_colnames") |> columntable + @test r == tbl + SQLite.drop!(db, "escape_colnames") end - @testset "explicit finalization by close!(stmt)" begin - SQLite.load!(tbl, db, "test_table2") - stmt = SQLite.Stmt(db, "SELECT a, b FROM test_table2") - @test SQLite.isready(stmt) - @test SQLite.execute(stmt) == 100 - # test cannot drop the table locked by the statement - @test_throws SQLiteException SQLite.drop!(db, "test_table2") - DBInterface.close!(stmt) - @test !SQLite.isready(stmt) - SQLite.drop!(db, "test_table2") - DBInterface.close!(stmt) # test can call close!() 2nd time + @testset "Bool column data" begin + tbl = (a = [true, false, false], b = [false, missing, true]) + SQLite.load!(tbl, db, "bool_data") + r = DBInterface.execute(db, "SELECT * FROM bool_data") |> columntable + @test isequal(r, (a = [1, 0, 0], b = [0, missing, 1])) + SQLite.drop!(db, "bool_data") end - @testset "automatic close of implicit prepared statement" begin - @testset "SQLite.execute() call" begin - SQLite.load!(tbl, db, "test_table3") - @test SQLite.execute(db, "SELECT a, b FROM test_table3") == 100 - # test can immediately drop the table, since no locks by the statement - SQLite.drop!(db, "test_table3") + @testset "serialization edgecases" begin + db = SQLite.DB() + r = DBInterface.execute(db, "SELECT zeroblob(2) as b") |> columntable + @test first(r.b) == [0, 0] + r = DBInterface.execute(db, "SELECT zeroblob(0) as b") |> columntable + @test first(r.b) == [] + end + + @testset "Stmt scope" begin + dbfile = joinpath(tempdir(), "test_stmt_scope.sqlite") + db = SQLite.DB(dbfile) + tbl = (a = [1, 2, 3], b = ["a", "b", "c"]) + + @testset "explicit finalization by finalize_statements!(db)" begin + SQLite.load!(tbl, db, "test_table") + stmt = SQLite.Stmt(db, "SELECT a, b FROM test_table") + @test SQLite.isready(stmt) + @test SQLite.execute(stmt) == 100 + # test cannot drop the table locked by the statement + @test_throws SQLiteException SQLite.drop!(db, "test_table") + SQLite.finalize_statements!(db) + @test !SQLite.isready(stmt) + SQLite.drop!(db, "test_table") + DBInterface.close!(stmt) # test can call close!() 2nd time end - @testset "DBInterface.execute() call" begin - SQLite.load!(tbl, db, "test_table4") - @test SQLite.execute(db, "SELECT a, b FROM test_table4") == 100 - GC.gc() # close implicitly created statement - # test can immediately drop the table, since no locks by the GC-ed statement - SQLite.drop!(db, "test_table4") + @testset "explicit finalization by close!(stmt)" begin + SQLite.load!(tbl, db, "test_table2") + stmt = SQLite.Stmt(db, "SELECT a, b FROM test_table2") + @test SQLite.isready(stmt) + @test SQLite.execute(stmt) == 100 + # test cannot drop the table locked by the statement + @test_throws SQLiteException SQLite.drop!(db, "test_table2") + DBInterface.close!(stmt) + @test !SQLite.isready(stmt) + SQLite.drop!(db, "test_table2") + DBInterface.close!(stmt) # test can call close!() 2nd time end - end - close(db) - rm(dbfile) -end + @testset "automatic close of implicit prepared statement" begin + @testset "SQLite.execute() call" begin + SQLite.load!(tbl, db, "test_table3") + @test SQLite.execute(db, "SELECT a, b FROM test_table3") == 100 + # test can immediately drop the table, since no locks by the statement + SQLite.drop!(db, "test_table3") + end + + @testset "DBInterface.execute() call" begin + SQLite.load!(tbl, db, "test_table4") + @test SQLite.execute(db, "SELECT a, b FROM test_table4") == 100 + GC.gc() # close implicitly created statement + # test can immediately drop the table, since no locks by the GC-ed statement + SQLite.drop!(db, "test_table4") + end + end + + close(db) + rm(dbfile) + end end # @testset -struct UnknownSchemaTable -end +struct UnknownSchemaTable end Tables.isrowtable(::Type{UnknownSchemaTable}) = true Tables.rows(x::UnknownSchemaTable) = x Base.length(x::UnknownSchemaTable) = 3 -Base.iterate(::UnknownSchemaTable, st=1) = st == 4 ? nothing : ((a=1, b=2 + st, c=3 + st), st + 1) +Base.iterate(::UnknownSchemaTable, st = 1) = + st == 4 ? nothing : ((a = 1, b = 2 + st, c = 3 + st), st + 1) @testset "misc" begin -# https://github.com/JuliaDatabases/SQLite.jl/issues/259 -db = SQLite.DB() -SQLite.load!(UnknownSchemaTable(), db, "tbl") -tbl = DBInterface.execute(db, "select * from tbl") |> columntable -@test tbl == ( - a = [1, 1, 1], - b = [3, 4, 5], - c = [4, 5, 6] -) - -# https://github.com/JuliaDatabases/SQLite.jl/issues/251 -q = DBInterface.execute(db, "select * from tbl") -row, st = iterate(q) -@test row.a == 1 && row.b == 3 && row.c == 4 -row2, st = iterate(q, st) -@test_throws ArgumentError row.a - -# https://github.com/JuliaDatabases/SQLite.jl/issues/243 -db = SQLite.DB() -DBInterface.execute(db, "create table tmp ( a INTEGER NOT NULL PRIMARY KEY, b INTEGER, c INTEGER )") -@test_throws SQLite.SQLiteException SQLite.load!(UnknownSchemaTable(), db, "tmp") -SQLite.load!(UnknownSchemaTable(), db, "tmp"; replace=true) -tbl = DBInterface.execute(db, "select * from tmp") |> columntable -@test tbl == ( - a = [1], - b = [5], - c = [6] -) - -db = SQLite.DB() -DBInterface.execute(db, "create table tmp ( x TEXT )") -DBInterface.execute(db, "insert into tmp values (?)", (nothing,)) -DBInterface.execute(db, "insert into tmp values (?)", (:a,)) -tbl = DBInterface.execute(db, "select x from tmp") |> columntable -@test isequal(tbl.x, [missing, :a]) - -db = SQLite.DB() -DBInterface.execute(db, "create table tmp (a integer, b integer, c integer)") -stmt = DBInterface.prepare(db, "INSERT INTO tmp VALUES(?, ?, ?)") -tbl = ( - a = [1, 1, 1], - b = [3, 4, 5], - c = [4, 5, 6] -) -DBInterface.executemany(stmt, tbl) -tbl2 = DBInterface.execute(db, "select * from tmp") |> columntable -@test tbl == tbl2 - -end \ No newline at end of file + # https://github.com/JuliaDatabases/SQLite.jl/issues/259 + db = SQLite.DB() + SQLite.load!(UnknownSchemaTable(), db, "tbl") + tbl = DBInterface.execute(db, "select * from tbl") |> columntable + @test tbl == (a = [1, 1, 1], b = [3, 4, 5], c = [4, 5, 6]) + + # https://github.com/JuliaDatabases/SQLite.jl/issues/251 + q = DBInterface.execute(db, "select * from tbl") + row, st = iterate(q) + @test row.a == 1 && row.b == 3 && row.c == 4 + row2, st = iterate(q, st) + @test_throws ArgumentError row.a + + # https://github.com/JuliaDatabases/SQLite.jl/issues/243 + db = SQLite.DB() + DBInterface.execute( + db, + "create table tmp ( a INTEGER NOT NULL PRIMARY KEY, b INTEGER, c INTEGER )", + ) + @test_throws SQLite.SQLiteException SQLite.load!(UnknownSchemaTable(), db, "tmp") + SQLite.load!(UnknownSchemaTable(), db, "tmp"; replace = true) + tbl = DBInterface.execute(db, "select * from tmp") |> columntable + @test tbl == (a = [1], b = [5], c = [6]) + + db = SQLite.DB() + DBInterface.execute(db, "create table tmp ( x TEXT )") + DBInterface.execute(db, "insert into tmp values (?)", (nothing,)) + DBInterface.execute(db, "insert into tmp values (?)", (:a,)) + tbl = DBInterface.execute(db, "select x from tmp") |> columntable + @test isequal(tbl.x, [missing, :a]) + + db = SQLite.DB() + DBInterface.execute(db, "create table tmp (a integer, b integer, c integer)") + stmt = DBInterface.prepare(db, "INSERT INTO tmp VALUES(?, ?, ?)") + tbl = (a = [1, 1, 1], b = [3, 4, 5], c = [4, 5, 6]) + DBInterface.executemany(stmt, tbl) + tbl2 = DBInterface.execute(db, "select * from tmp") |> columntable + @test tbl == tbl2 + +end From 90e7b079672e130ffa7c2fa54ac4f9c364f1b36f Mon Sep 17 00:00:00 2001 From: Jeremiah <4462211+jeremiahpslewis@users.noreply.github.com> Date: Wed, 3 Nov 2021 16:05:27 +0000 Subject: [PATCH 3/9] Fix dockerfile --- .devcontainer/Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index c3a8832..5ebd287 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -2,6 +2,8 @@ FROM julia:1.7 RUN apt-get update && apt-get install --no-install-recommends -y git && rm -rf /var/lib/apt/lists/* -COPY Project.toml / +WORKDIR /app + +# COPY Project.toml . # RUN julia -e 'using Pkg; Pkg.dev(""); Pkg.instantiate(); Pkg.precompile();' From 6587d3cbe8b36eb8cf7ae821f89df34fa806e2f5 Mon Sep 17 00:00:00 2001 From: Jeremiah <4462211+jeremiahpslewis@users.noreply.github.com> Date: Wed, 3 Nov 2021 16:43:00 +0000 Subject: [PATCH 4/9] Move things to testsets --- test/Project.toml | 8 + test/runtests.jl | 671 +++++++++++++++++++++++++--------------------- 2 files changed, 377 insertions(+), 302 deletions(-) create mode 100644 test/Project.toml diff --git a/test/Project.toml b/test/Project.toml new file mode 100644 index 0000000..eee9b17 --- /dev/null +++ b/test/Project.toml @@ -0,0 +1,8 @@ +[deps] +DBInterface = "a10d1c49-ce27-4219-8d33-6db1a4562965" +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +SQLite = "0aa819cd-b072-5ff4-a722-6bc24af294d9" +Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +WeakRefStrings = "ea10d353-3f73-51f8-a26c-33c1cb351aa5" diff --git a/test/runtests.jl b/test/runtests.jl index b4c4d5d..43067b5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -15,13 +15,16 @@ mutable struct Point3D{T<:Number} y::T z::T end + ==(a::Point3D, b::Point3D) = a.x == b.x && a.y == b.y && a.z == b.z +(a::Point3D, b::Point3D) = Point3D(a.x + b.x, a.y + b.y, a.z + b.z) triple(x) = 3x + function add4(q) q + 4 end + mult(args...) = *(args...) str2arr(s) = Vector{UInt8}(s) doublesum_step(persist, current) = persist + current @@ -30,10 +33,21 @@ mycount(p, c) = p + 1 bigsum(p, c) = p + big(c) sumpoint(p::Point3D, x, y, z) = p + Point3D(x, y, z) -dbfile = joinpath(dirname(pathof(SQLite)), "../test/Chinook_Sqlite.sqlite") -dbfile2 = joinpath(tempdir(), "test.sqlite") -cp(dbfile, dbfile2; force = true) -chmod(dbfile2, 0o777) +test_dbfile = joinpath(tempdir(), "test.sqlite") + +""" + setup_clean_test_db() + +Copy test sqlite file to temp directory, path `test.sqlite`, +overwrite file if necessary and set permissions. +""" +function setup_clean_test_db() + dbfile = joinpath(dirname(pathof(SQLite)), "../test/Chinook_Sqlite.sqlite") + cp(dbfile, test_dbfile; force = true) + chmod(test_dbfile, 0o777) + + return SQLite.DB(test_dbfile) +end @testset "basics" begin @@ -47,39 +61,53 @@ chmod(dbfile2, 0o777) @test SQLite.sqlitetype(Any) == "BLOB" end - db = SQLite.DB(dbfile2) - db = DBInterface.connect(SQLite.DB, dbfile2) - - # https://github.com/JuliaDatabases/SQLite.jl/issues/207 - ds = DBInterface.execute(db, "SELECT RANDOM() as a FROM Track LIMIT 1") |> columntable - @test ds.a[1] isa Int64 + @testset "DB Connection" begin + setup_clean_test_db() + @test SQLite.DB(test_dbfile) isa SQLite.DB + @test DBInterface.connect(SQLite.DB, test_dbfile) isa SQLite.DB + end - # regular SQLite tests + @testset "Issue #207: 32 bit integers" begin + setup_clean_test_db() + db = SQLite.DB(test_dbfile) + ds = DBInterface.execute(db, "SELECT RANDOM() as a FROM Track LIMIT 1") |> columntable + @test ds.a[1] isa Int64 + end - @test_throws SQLiteException DBInterface.execute(db, "just some syntax error") - # syntax correct, table missing - @test_throws SQLiteException DBInterface.execute( - db, - "SELECT name FROM sqlite_nomaster WHERE type='table';", - ) + @testset "Regular SQLite Tests" begin + db = setup_clean_test_db() + @test_throws SQLiteException DBInterface.execute(db, "just some syntax error") + # syntax correct, table missing + @test_throws SQLiteException DBInterface.execute( + db, + "SELECT name FROM sqlite_nomaster WHERE type='table';", + ) + end @testset "close!(query)" begin + db = setup_clean_test_db() + qry = DBInterface.execute(db, "SELECT name FROM sqlite_master WHERE type='table';") DBInterface.close!(qry) DBInterface.close!(qry) # test it doesn't throw on double-close end - ds = - DBInterface.execute(db, "SELECT name FROM sqlite_master WHERE type='table';") |> - columntable - @test length(ds) == 1 - @test keys(ds) == (:name,) - @test length(ds.name) == 11 - - results1 = SQLite.tables(db) - @test isequal(ds, results1) + @testset "Query tables" begin + db = setup_clean_test_db() + ds = + DBInterface.execute(db, "SELECT name FROM sqlite_master WHERE type='table';") |> + columntable + @test length(ds) == 1 + @test keys(ds) == (:name,) + @test length(ds.name) == 11 + + results1 = SQLite.tables(db) + @test isequal(ds, results1) + end @testset "DBInterface.execute([f])" begin + db = setup_clean_test_db() + # pipe approach results = DBInterface.execute(db, "SELECT * FROM Employee;") |> columntable @test length(results) == 15 @@ -101,6 +129,8 @@ chmod(dbfile2, 0o777) end @testset "isempty(::Query)" begin + db = setup_clean_test_db() + @test !DBInterface.execute(isempty, db, "SELECT * FROM Employee") @test DBInterface.execute( isempty, @@ -110,6 +140,7 @@ chmod(dbfile2, 0o777) end @testset "empty query has correct schema and return type" begin + db = setup_clean_test_db() empty_scheme = DBInterface.execute( Tables.schema, db, @@ -138,14 +169,15 @@ chmod(dbfile2, 0o777) ) end - DBInterface.execute(db, "create table temp as select * from album") - DBInterface.execute(db, "alter table temp add column colyear int") - DBInterface.execute(db, "update temp set colyear = 2014") - r = DBInterface.execute(db, "select * from temp limit 10") |> columntable - @test length(r) == 4 && length(r[1]) == 10 - @test all(==(2014), r[4]) + @testset "Create table, run commit/rollback tests" begin + db = setup_clean_test_db() + DBInterface.execute(db, "create table temp as select * from album") + DBInterface.execute(db, "alter table temp add column colyear int") + DBInterface.execute(db, "update temp set colyear = 2014") + r = DBInterface.execute(db, "select * from temp limit 10") |> columntable + @test length(r) == 4 && length(r[1]) == 10 + @test all(==(2014), r[4]) - @testset "commit/rollback tests" begin @test_throws SQLiteException SQLite.rollback(db) @test_throws SQLiteException SQLite.commit(db) @@ -162,202 +194,217 @@ chmod(dbfile2, 0o777) @test all(==(2015), r[4]) end - DBInterface.execute(db, "alter table temp add column dates blob") - stmt = DBInterface.prepare(db, "update temp set dates = ?") - DBInterface.execute(stmt, (Date(2014, 1, 1),)) - - r = DBInterface.execute(db, "select * from temp limit 10") |> columntable - @test length(r) == 5 && length(r[1]) == 10 - @test typeof(r[5][1]) == Date - @test all(Bool[x == Date(2014, 1, 1) for x in r[5]]) - DBInterface.execute(db, "drop table temp") - - rng = Dates.Date(2013):Dates.Day(1):Dates.Date(2013, 1, 5) - dt = (i = collect(rng), j = collect(rng)) - tablename = dt |> SQLite.load!(db, "temp") - r = DBInterface.execute(db, "select * from $tablename") |> columntable - @test length(r) == 2 && length(r[1]) == 5 - @test all([i for i in r[1]] .== collect(rng)) - @test all([typeof(i) for i in r[1]] .== Dates.Date) - SQLite.drop!(db, "$tablename") - - DBInterface.execute(db, "CREATE TABLE temp AS SELECT * FROM Album") - r = DBInterface.execute(db, "SELECT * FROM temp LIMIT ?", [3]) |> columntable - @test length(r) == 3 && length(r[1]) == 3 - r = - DBInterface.execute(db, "SELECT * FROM temp WHERE Title LIKE ?", ["%time%"]) |> - columntable - @test r[1] == [76, 111, 187] - DBInterface.execute(db, "INSERT INTO temp VALUES (?1, ?3, ?2)", [0, 0, "Test Album"]) - r = DBInterface.execute(db, "SELECT * FROM temp WHERE AlbumId = 0") |> columntable - @test r[1][1] == 0 - @test r[2][1] == "Test Album" - @test r[3][1] == 0 - SQLite.drop!(db, "temp") - - DBInterface.execute(db, "CREATE TABLE temp AS SELECT * FROM Album") - r = DBInterface.execute(db, "SELECT * FROM temp LIMIT :a", (a = 3,)) |> columntable - @test length(r) == 3 && length(r[1]) == 3 - r = DBInterface.execute(db, "SELECT * FROM temp LIMIT :a", a = 3) |> columntable - @test length(r) == 3 && length(r[1]) == 3 - r = - DBInterface.execute( - db, - "SELECT * FROM temp WHERE Title LIKE @word", - (word = "%time%",), - ) |> columntable - @test r[1] == [76, 111, 187] - DBInterface.execute( - db, - "INSERT INTO temp VALUES (@lid, :title, \$rid)", - (rid = 1, lid = 0, title = "Test Album"), - ) - DBInterface.execute( - db, - "INSERT INTO temp VALUES (@lid, :title, \$rid)", - rid = 3, - lid = 400, - title = "Test2 Album", - ) - r = - DBInterface.execute(db, "SELECT * FROM temp WHERE AlbumId IN (0, 400)") |> - columntable - @test r[1] == [0, 400] - @test r[2] == ["Test Album", "Test2 Album"] - @test r[3] == [1, 3] - SQLite.drop!(db, "temp") - - SQLite.register(db, SQLite.regexp, nargs = 2, name = "regexp") - r = - DBInterface.execute( - db, - SQLite.@sr_str( - "SELECT LastName FROM Employee WHERE BirthDate REGEXP '^\\d{4}-08'" - ) - ) |> columntable - @test r[1][1] == "Peacock" - - SQLite.register(db, identity, nargs = 1, name = "identity") - r = - DBInterface.execute( - db, - """SELECT identity("abc") as x, "abc" == identity("abc") as cmp""", - ) |> columntable - @test first(r.x) == "abc" - @test first(r.cmp) == 1 - - @test_throws AssertionError SQLite.register(db, triple, nargs = 186) - SQLite.register(db, triple, nargs = 1) - r = + @testset "Dates" begin + db = setup_clean_test_db() + DBInterface.execute(db, "create table temp as select * from album") + DBInterface.execute(db, "alter table temp add column dates blob") + stmt = DBInterface.prepare(db, "update temp set dates = ?") + DBInterface.execute(stmt, (Date(2014, 1, 1),)) + + r = DBInterface.execute(db, "select * from temp limit 10") |> columntable + @test length(r) == 4 && length(r[1]) == 10 + @test typeof(r[4][1]) == Date + @test all(Bool[x == Date(2014, 1, 1) for x in r[4]]) + DBInterface.execute(db, "drop table temp") + + rng = Dates.Date(2013):Dates.Day(1):Dates.Date(2013, 1, 5) + dt = (i = collect(rng), j = collect(rng)) + tablename = dt |> SQLite.load!(db, "temp") + r = DBInterface.execute(db, "select * from $tablename") |> columntable + @test length(r) == 2 && length(r[1]) == 5 + @test all([i for i in r[1]] .== collect(rng)) + @test all([typeof(i) for i in r[1]] .== Dates.Date) + SQLite.drop!(db, "$tablename") + end + + @testset "Prepared Statements" begin + db = setup_clean_test_db() + + DBInterface.execute(db, "CREATE TABLE temp AS SELECT * FROM Album") + r = DBInterface.execute(db, "SELECT * FROM temp LIMIT ?", [3]) |> columntable + @test length(r) == 3 && length(r[1]) == 3 + r = + DBInterface.execute(db, "SELECT * FROM temp WHERE Title LIKE ?", ["%time%"]) |> + columntable + @test r[1] == [76, 111, 187] + DBInterface.execute(db, "INSERT INTO temp VALUES (?1, ?3, ?2)", [0, 0, "Test Album"]) + r = DBInterface.execute(db, "SELECT * FROM temp WHERE AlbumId = 0") |> columntable + @test r[1][1] == 0 + @test r[2][1] == "Test Album" + @test r[3][1] == 0 + SQLite.drop!(db, "temp") + + DBInterface.execute(db, "CREATE TABLE temp AS SELECT * FROM Album") + r = DBInterface.execute(db, "SELECT * FROM temp LIMIT :a", (a = 3,)) |> columntable + @test length(r) == 3 && length(r[1]) == 3 + r = DBInterface.execute(db, "SELECT * FROM temp LIMIT :a", a = 3) |> columntable + @test length(r) == 3 && length(r[1]) == 3 + r = + DBInterface.execute( + db, + "SELECT * FROM temp WHERE Title LIKE @word", + (word = "%time%",), + ) |> columntable + @test r[1] == [76, 111, 187] DBInterface.execute( db, - "SELECT triple(Total) FROM Invoice ORDER BY InvoiceId LIMIT 5", - ) |> columntable - s = - DBInterface.execute(db, "SELECT Total FROM Invoice ORDER BY InvoiceId LIMIT 5") |> - columntable - for (i, j) in zip(r[1], s[1]) - @test abs(i - 3 * j) < 0.02 - end - - SQLite.@register db add4 - r = DBInterface.execute(db, "SELECT add4(AlbumId) FROM Album") |> columntable - s = DBInterface.execute(db, "SELECT AlbumId FROM Album") |> columntable - @test r[1][1] == s[1][1] + 4 - - SQLite.@register db mult - r = DBInterface.execute(db, "SELECT GenreId, UnitPrice FROM Track") |> columntable - s = DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice) FROM Track") |> columntable - @test (r[1][1] * r[2][1]) == s[1][1] - t = - DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice, 3, 4) FROM Track") |> - columntable - @test (r[1][1] * r[2][1] * 3 * 4) == t[1][1] - - SQLite.@register db sin - u = - DBInterface.execute(db, "select sin(milliseconds) from track limit 5") |> - columntable - @test all(-1 .< convert(Vector{Float64}, u[1]) .< 1) - - SQLite.register(db, hypot; nargs = 2, name = "hypotenuse") - v = + "INSERT INTO temp VALUES (@lid, :title, \$rid)", + (rid = 1, lid = 0, title = "Test Album"), + ) DBInterface.execute( db, - "select hypotenuse(Milliseconds,bytes) from track limit 5", - ) |> columntable - @test [round(Int, i) for i in v[1]] == [11175621, 5521062, 3997652, 4339106, 6301714] - - SQLite.@register db str2arr - r = - DBInterface.execute(db, "SELECT str2arr(LastName) FROM Employee LIMIT 2") |> - columntable - @test r[1][2] == UInt8[0x45, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73] - - SQLite.@register db big - r = DBInterface.execute(db, "SELECT big(5)") |> columntable - @test r[1][1] == big(5) - @test typeof(r[1][1]) == BigInt - - SQLite.register(db, 0, doublesum_step, doublesum_final, name = "doublesum") - r = DBInterface.execute(db, "SELECT doublesum(UnitPrice) FROM Track") |> columntable - s = DBInterface.execute(db, "SELECT UnitPrice FROM Track") |> columntable - @test abs(r[1][1] - 2 * sum(convert(Vector{Float64}, s[1]))) < 0.02 - - - SQLite.register(db, 0, mycount) - r = DBInterface.execute(db, "SELECT mycount(TrackId) FROM PlaylistTrack") |> columntable - s = DBInterface.execute(db, "SELECT count(TrackId) FROM PlaylistTrack") |> columntable - @test r[1][1] == s[1][1] - - SQLite.register(db, big(0), bigsum) - r = DBInterface.execute(db, "SELECT bigsum(TrackId) FROM PlaylistTrack") |> columntable - s = DBInterface.execute(db, "SELECT TrackId FROM PlaylistTrack") |> columntable - @test r[1][1] == big(sum(convert(Vector{Int}, s[1]))) - - DBInterface.execute(db, "CREATE TABLE points (x INT, y INT, z INT)") - DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (1, 2, 3)) - DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (4, 5, 6)) - DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (7, 8, 9)) - - SQLite.register(db, Point3D(0, 0, 0), sumpoint) - r = DBInterface.execute(db, "SELECT sumpoint(x, y, z) FROM points") |> columntable - @test r[1][1] == Point3D(12, 15, 18) - SQLite.drop!(db, "points") - - db2 = DBInterface.connect(SQLite.DB) - DBInterface.execute(db2, "CREATE TABLE tab1 (r REAL, s INT)") - - @test_throws SQLiteException SQLite.drop!(db2, "nonexistant") - # should not throw anything - SQLite.drop!(db2, "nonexistant", ifexists = true) - # should drop "tab2" - SQLite.drop!(db2, "tab2", ifexists = true) - @test !in("tab2", SQLite.tables(db2)[1]) - - SQLite.drop!(db, "sqlite_stat1", ifexists = true) - tables = SQLite.tables(db) - @test length(tables[1]) == 11 - - #Test removeduplicates! - db = SQLite.DB() #In case the order of tests is changed - dt = (ints = Int64[1, 1, 2, 2, 3], strs = ["A", "A", "B", "C", "C"]) - tablename = dt |> SQLite.load!(db, "temp") - SQLite.removeduplicates!(db, "temp", ["ints", "strs"]) #New format - dt3 = DBInterface.execute(db, "Select * from temp") |> columntable - @test dt3[1][1] == 1 - @test dt3[2][1] == "A" - @test dt3[1][2] == 2 - @test dt3[2][2] == "B" - @test dt3[1][3] == 2 - @test dt3[2][3] == "C" - - # issue #104 - db = SQLite.DB() #In case the order of tests is changed - DBInterface.execute(db, "CREATE TABLE IF NOT EXISTS tbl(a INTEGER);") - stmt = DBInterface.prepare(db, "INSERT INTO tbl (a) VALUES (@a);") - SQLite.bind!(stmt, "@a", 1) - SQLite.clear!(stmt) + "INSERT INTO temp VALUES (@lid, :title, \$rid)", + rid = 3, + lid = 400, + title = "Test2 Album", + ) + r = + DBInterface.execute(db, "SELECT * FROM temp WHERE AlbumId IN (0, 400)") |> + columntable + @test r[1] == [0, 400] + @test r[2] == ["Test Album", "Test2 Album"] + @test r[3] == [1, 3] + SQLite.drop!(db, "temp") + + SQLite.register(db, SQLite.regexp, nargs = 2, name = "regexp") + r = + DBInterface.execute( + db, + SQLite.@sr_str( + "SELECT LastName FROM Employee WHERE BirthDate REGEXP '^\\d{4}-08'" + ) + ) |> columntable + @test r[1][1] == "Peacock" + + SQLite.register(db, identity, nargs = 1, name = "identity") + r = + DBInterface.execute( + db, + """SELECT identity("abc") as x, "abc" == identity("abc") as cmp""", + ) |> columntable + @test first(r.x) == "abc" + @test first(r.cmp) == 1 + + @test_throws AssertionError SQLite.register(db, triple, nargs = 186) + SQLite.register(db, triple, nargs = 1) + r = + DBInterface.execute( + db, + "SELECT triple(Total) FROM Invoice ORDER BY InvoiceId LIMIT 5", + ) |> columntable + s = + DBInterface.execute(db, "SELECT Total FROM Invoice ORDER BY InvoiceId LIMIT 5") |> + columntable + for (i, j) in zip(r[1], s[1]) + @test abs(i - 3 * j) < 0.02 + end + end + + @testset "Register functions" begin + db = setup_clean_test_db() + SQLite.@register db add4 + r = DBInterface.execute(db, "SELECT add4(AlbumId) FROM Album") |> columntable + s = DBInterface.execute(db, "SELECT AlbumId FROM Album") |> columntable + @test r[1][1] == s[1][1] + 4 + + SQLite.@register db mult + r = DBInterface.execute(db, "SELECT GenreId, UnitPrice FROM Track") |> columntable + s = DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice) FROM Track") |> columntable + @test (r[1][1] * r[2][1]) == s[1][1] + t = + DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice, 3, 4) FROM Track") |> + columntable + @test (r[1][1] * r[2][1] * 3 * 4) == t[1][1] + + SQLite.@register db sin + u = + DBInterface.execute(db, "select sin(milliseconds) from track limit 5") |> + columntable + @test all(-1 .< convert(Vector{Float64}, u[1]) .< 1) + + SQLite.register(db, hypot; nargs = 2, name = "hypotenuse") + v = + DBInterface.execute( + db, + "select hypotenuse(Milliseconds,bytes) from track limit 5", + ) |> columntable + @test [round(Int, i) for i in v[1]] == [11175621, 5521062, 3997652, 4339106, 6301714] + + SQLite.@register db str2arr + r = + DBInterface.execute(db, "SELECT str2arr(LastName) FROM Employee LIMIT 2") |> + columntable + @test r[1][2] == UInt8[0x45, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73] + + SQLite.@register db big + r = DBInterface.execute(db, "SELECT big(5)") |> columntable + @test r[1][1] == big(5) + @test typeof(r[1][1]) == BigInt + + SQLite.register(db, 0, doublesum_step, doublesum_final, name = "doublesum") + r = DBInterface.execute(db, "SELECT doublesum(UnitPrice) FROM Track") |> columntable + s = DBInterface.execute(db, "SELECT UnitPrice FROM Track") |> columntable + @test abs(r[1][1] - 2 * sum(convert(Vector{Float64}, s[1]))) < 0.02 + + + SQLite.register(db, 0, mycount) + r = DBInterface.execute(db, "SELECT mycount(TrackId) FROM PlaylistTrack") |> columntable + s = DBInterface.execute(db, "SELECT count(TrackId) FROM PlaylistTrack") |> columntable + @test r[1][1] == s[1][1] + + SQLite.register(db, big(0), bigsum) + r = DBInterface.execute(db, "SELECT bigsum(TrackId) FROM PlaylistTrack") |> columntable + s = DBInterface.execute(db, "SELECT TrackId FROM PlaylistTrack") |> columntable + @test r[1][1] == big(sum(convert(Vector{Int}, s[1]))) + + DBInterface.execute(db, "CREATE TABLE points (x INT, y INT, z INT)") + DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (1, 2, 3)) + DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (4, 5, 6)) + DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (7, 8, 9)) + + SQLite.register(db, Point3D(0, 0, 0), sumpoint) + r = DBInterface.execute(db, "SELECT sumpoint(x, y, z) FROM points") |> columntable + @test r[1][1] == Point3D(12, 15, 18) + SQLite.drop!(db, "points") + + db2 = DBInterface.connect(SQLite.DB) + DBInterface.execute(db2, "CREATE TABLE tab1 (r REAL, s INT)") + + @test_throws SQLiteException SQLite.drop!(db2, "nonexistant") + # should not throw anything + SQLite.drop!(db2, "nonexistant", ifexists = true) + # should drop "tab2" + SQLite.drop!(db2, "tab2", ifexists = true) + @test !in("tab2", SQLite.tables(db2)[1]) + + SQLite.drop!(db, "sqlite_stat1", ifexists = true) + tables = SQLite.tables(db) + @test length(tables[1]) == 11 + end + + @testset "Remove Duplicates" begin + db = setup_clean_test_db() + db = SQLite.DB() #In case the order of tests is changed + dt = (ints = Int64[1, 1, 2, 2, 3], strs = ["A", "A", "B", "C", "C"]) + tablename = dt |> SQLite.load!(db, "temp") + SQLite.removeduplicates!(db, "temp", ["ints", "strs"]) #New format + dt3 = DBInterface.execute(db, "Select * from temp") |> columntable + @test dt3[1][1] == 1 + @test dt3[2][1] == "A" + @test dt3[1][2] == 2 + @test dt3[2][2] == "B" + @test dt3[1][3] == 2 + @test dt3[2][3] == "C" + end + + + @testset "Issue #104: bind!() fails with named parameters" begin + db = SQLite.DB() #In case the order of tests is changed + DBInterface.execute(db, "CREATE TABLE IF NOT EXISTS tbl(a INTEGER);") + stmt = DBInterface.prepare(db, "INSERT INTO tbl (a) VALUES (@a);") + SQLite.bind!(stmt, "@a", 1) + SQLite.clear!(stmt) + end @testset "SQLite to Julia type conversion" begin binddb = SQLite.DB() @@ -424,40 +471,46 @@ chmod(dbfile2, 0o777) ) end - ############################################ - - #test for #158 - @test_throws SQLiteException SQLite.DB("nonexistentdir/not_there.db") - - #test for #180 (Query) - param = "Hello!" - query = DBInterface.execute(SQLite.DB(), "SELECT ?1 UNION ALL SELECT ?1", [param]) - param = "x" - for row in query - @test row[1] == "Hello!" - GC.gc() # this must NOT garbage collect the "Hello!" bound value + @testset "Issue #158: Missing DB File" begin + @test_throws SQLiteException SQLite.DB("nonexistentdir/not_there.db") end - db = SQLite.DB() - DBInterface.execute(db, "CREATE TABLE T (a TEXT, PRIMARY KEY (a))") - - q = DBInterface.prepare(db, "INSERT INTO T VALUES(?)") - DBInterface.execute(q, ["a"]) - - SQLite.bind!(q, 1, "a") - @test_throws SQLiteException DBInterface.execute(q) + @testset "Issue #180, Query" begin + param = "Hello!" + query = DBInterface.execute(SQLite.DB(), "SELECT ?1 UNION ALL SELECT ?1", [param]) + param = "x" + for row in query + @test row[1] == "Hello!" + GC.gc() # this must NOT garbage collect the "Hello!" bound value + end + + db = SQLite.DB() + DBInterface.execute(db, "CREATE TABLE T (a TEXT, PRIMARY KEY (a))") + + q = DBInterface.prepare(db, "INSERT INTO T VALUES(?)") + DBInterface.execute(q, ["a"]) + + SQLite.bind!(q, 1, "a") + @test_throws SQLiteException DBInterface.execute(q) + end - @test SQLite.@OK SQLite.enable_load_extension(db) + @testset "Enable extension" begin + @test SQLite.@OK SQLite.enable_load_extension(db) + end + @testset "show(DB)" begin io = IOBuffer() show(io, db) @test String(take!(io)) == "SQLite.DB(\":memory:\")" + + DBInterface.close!(db) end - DBInterface.close!(db) + - db = SQLite.DB() + @testset "SQLite.execute()" begin + db = SQLite.DB() DBInterface.execute(db, "CREATE TABLE T (x INT UNIQUE)") q = DBInterface.prepare(db, "INSERT INTO T VALUES(?)") @@ -481,70 +534,84 @@ chmod(dbfile2, 0o777) SQLite.execute(db, "INSERT INTO T VALUES(:x)", x = 5) r = DBInterface.execute(columntable, db, "SELECT * FROM T") @test r[1] == [1, 2, 3, 4, 5] - end - - r = DBInterface.execute(db, strip(" SELECT * FROM T ")) |> columntable - @test r[1] == [1, 2, 3, 4, 5] - - @test SQLite.esc_id(["1", "2", "3"]) == "\"1\",\"2\",\"3\"" - - SQLite.createindex!(db, "T", "x", "x_index"; unique = false) - inds = SQLite.indices(db) - @test last(inds.name) == "x" - SQLite.dropindex!(db, "x") - @test length(SQLite.indices(db).name) == 1 - cols = SQLite.columns(db, "T") - @test cols.name == ["x"] - - @test SQLite.last_insert_rowid(db) == 5 + r = DBInterface.execute(db, strip(" SELECT * FROM T ")) |> columntable + @test r[1] == [1, 2, 3, 4, 5] + + SQLite.createindex!(db, "T", "x", "x_index"; unique = false) + inds = SQLite.indices(db) + @test last(inds.name) == "x" + SQLite.dropindex!(db, "x") + @test length(SQLite.indices(db).name) == 1 + + cols = SQLite.columns(db, "T") + @test cols.name == ["x"] + + @test SQLite.last_insert_rowid(db) == 5 + + r = DBInterface.execute(db, "SELECT * FROM T") + @test Tables.istable(r) + @test Tables.rowaccess(r) + @test Tables.rows(r) === r + @test Base.IteratorSize(typeof(r)) == Base.SizeUnknown() + @test eltype(r) == SQLite.Row + row = first(r) + SQLite.reset!(r) + row2 = first(r) + @test row[:x] == row2[:x] + @test propertynames(row) == [:x] + @test DBInterface.lastrowid(r) == 5 + + r = DBInterface.execute(db, "SELECT * FROM T") |> columntable + SQLite.load!(nothing, Tables.rows(r), db, "T2", SQLite.tableinfo(db, "T2")) + r2 = DBInterface.execute(db, "SELECT * FROM T2") |> columntable + @test r == r2 + end - r = DBInterface.execute(db, "SELECT * FROM T") - @test Tables.istable(r) - @test Tables.rowaccess(r) - @test Tables.rows(r) === r - @test Base.IteratorSize(typeof(r)) == Base.SizeUnknown() - @test eltype(r) == SQLite.Row - row = first(r) - SQLite.reset!(r) - row2 = first(r) - @test row[:x] == row2[:x] - @test propertynames(row) == [:x] - @test DBInterface.lastrowid(r) == 5 + @testset "Escaping" begin + @test SQLite.esc_id(["1", "2", "3"]) == "\"1\",\"2\",\"3\"" + end - r = DBInterface.execute(db, "SELECT * FROM T") |> columntable - SQLite.load!(nothing, Tables.rows(r), db, "T2", SQLite.tableinfo(db, "T2")) - r2 = DBInterface.execute(db, "SELECT * FROM T2") |> columntable - @test r == r2 - # throw informative error on duplicate column names #193 - @test_throws SQLiteException SQLite.load!((a = [1, 2, 3], A = [1, 2, 3]), db) - db = SQLite.DB() - # Table should map by name #216 - tbl1 = (a = [1, 2, 3], b = [4, 5, 6]) - tbl2 = (b = [7, 8, 9], a = [4, 5, 6]) - SQLite.load!(tbl1, db, "data") - SQLite.load!(tbl2, db, "data") + @testset "Issue #193: Throw informative error on duplicate column names" begin + db = SQLite.DB() + @test_throws SQLiteException SQLite.load!((a = [1, 2, 3], A = [1, 2, 3]), db) + end + - res = DBInterface.execute(db, "SELECT * FROM data") |> columntable - expected = (a = [1, 2, 3, 4, 5, 6], b = [4, 5, 6, 7, 8, 9]) - @test res == expected + @testset "Issue #216: Table should map by name" begin + db = SQLite.DB() + # Table should map by name #216 + tbl1 = (a = [1, 2, 3], b = [4, 5, 6]) + tbl2 = (b = [7, 8, 9], a = [4, 5, 6]) + SQLite.load!(tbl1, db, "data") + SQLite.load!(tbl2, db, "data") + + res = DBInterface.execute(db, "SELECT * FROM data") |> columntable + expected = (a = [1, 2, 3, 4, 5, 6], b = [4, 5, 6, 7, 8, 9]) + @test res == expected + end - # Table should error if names don't match #216 - tbl3 = (c = [7, 8, 9], a = [4, 5, 6]) - @test_throws SQLiteException SQLite.load!(tbl3, db, "data") + @testset "Issue #216: Table should error if names don't match" begin + db = SQLite.DB() + tbl3 = (c = [7, 8, 9], a = [4, 5, 6]) + @test_throws SQLiteException SQLite.load!(tbl3, db, "data") + end - # Test busy_timeout - @test SQLite.busy_timeout(db, 300) == 0 + @testset "Test busy_timeout" begin + db = SQLite.DB() + @test SQLite.busy_timeout(db, 300) == 0 + end - # 253, ensure query column names are unique by default - db = SQLite.DB() - res = - DBInterface.execute(db, "select 1 as x2, 2 as x2, 3 as x2, 4 as x2_2") |> - columntable - @test res == (x2 = [1], x2_1 = [2], x2_2 = [3], x2_2_1 = [4]) + @testset "Issue #253: Ensure query column names are unique by default" begin + db = SQLite.DB() + res = + DBInterface.execute(db, "select 1 as x2, 2 as x2, 3 as x2, 4 as x2_2") |> + columntable + @test res == (x2 = [1], x2_1 = [2], x2_2 = [3], x2_2_1 = [4]) + end @testset "load!()/drop!() table name escaping" begin tbl = (a = [1, 2, 3], b = ["a", "b", "c"]) From f2c5a9579b792c275502946ab91e1cf71a58b90c Mon Sep 17 00:00:00 2001 From: Jeremiah <4462211+jeremiahpslewis@users.noreply.github.com> Date: Wed, 3 Nov 2021 17:12:49 +0000 Subject: [PATCH 5/9] Test fixes --- test/runtests.jl | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 43067b5..814d235 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -495,11 +495,14 @@ end end @testset "Enable extension" begin + db = SQLite.DB() @test SQLite.@OK SQLite.enable_load_extension(db) end @testset "show(DB)" begin io = IOBuffer() + db = SQLite.DB() + show(io, db) @test String(take!(io)) == "SQLite.DB(\":memory:\")" @@ -582,7 +585,7 @@ end @testset "Issue #216: Table should map by name" begin db = SQLite.DB() - # Table should map by name #216 + tbl1 = (a = [1, 2, 3], b = [4, 5, 6]) tbl2 = (b = [7, 8, 9], a = [4, 5, 6]) SQLite.load!(tbl1, db, "data") @@ -595,6 +598,9 @@ end @testset "Issue #216: Table should error if names don't match" begin db = SQLite.DB() + + tbl1 = (a = [1, 2, 3], b = [4, 5, 6]) + SQLite.load!(tbl1, db, "data") tbl3 = (c = [7, 8, 9], a = [4, 5, 6]) @test_throws SQLiteException SQLite.load!(tbl3, db, "data") end @@ -613,7 +619,8 @@ end @test res == (x2 = [1], x2_1 = [2], x2_2 = [3], x2_2_1 = [4]) end - @testset "load!()/drop!() table name escaping" begin + @testset "load!() / drop!() table name escaping" begin + db = SQLite.DB() tbl = (a = [1, 2, 3], b = ["a", "b", "c"]) SQLite.load!(tbl, db, "escape 10.0%") r = @@ -624,6 +631,7 @@ end end @testset "load!() column names escaping" begin + db = SQLite.DB() tbl = NamedTuple{(:a, Symbol("50.0%"))}(([1, 2, 3], ["a", "b", "c"])) SQLite.load!(tbl, db, "escape_colnames") r = DBInterface.execute(db, "SELECT * FROM escape_colnames") |> columntable @@ -632,6 +640,7 @@ end end @testset "Bool column data" begin + db = SQLite.DB() tbl = (a = [true, false, false], b = [false, missing, true]) SQLite.load!(tbl, db, "bool_data") r = DBInterface.execute(db, "SELECT * FROM bool_data") |> columntable From aa64da428960de419e2945fb73e028ce655062b6 Mon Sep 17 00:00:00 2001 From: Jeremiah <4462211+jeremiahpslewis@users.noreply.github.com> Date: Wed, 3 Nov 2021 17:16:57 +0000 Subject: [PATCH 6/9] Formatting --- test/runtests.jl | 120 +++++++++++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 52 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 814d235..cd98576 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -70,7 +70,9 @@ end @testset "Issue #207: 32 bit integers" begin setup_clean_test_db() db = SQLite.DB(test_dbfile) - ds = DBInterface.execute(db, "SELECT RANDOM() as a FROM Track LIMIT 1") |> columntable + ds = + DBInterface.execute(db, "SELECT RANDOM() as a FROM Track LIMIT 1") |> + columntable @test ds.a[1] isa Int64 end @@ -100,9 +102,9 @@ end @test length(ds) == 1 @test keys(ds) == (:name,) @test length(ds.name) == 11 - + results1 = SQLite.tables(db) - @test isequal(ds, results1) + @test isequal(ds, results1) end @testset "DBInterface.execute([f])" begin @@ -130,7 +132,7 @@ end @testset "isempty(::Query)" begin db = setup_clean_test_db() - + @test !DBInterface.execute(isempty, db, "SELECT * FROM Employee") @test DBInterface.execute( isempty, @@ -200,13 +202,13 @@ end DBInterface.execute(db, "alter table temp add column dates blob") stmt = DBInterface.prepare(db, "update temp set dates = ?") DBInterface.execute(stmt, (Date(2014, 1, 1),)) - + r = DBInterface.execute(db, "select * from temp limit 10") |> columntable @test length(r) == 4 && length(r[1]) == 10 @test typeof(r[4][1]) == Date @test all(Bool[x == Date(2014, 1, 1) for x in r[4]]) DBInterface.execute(db, "drop table temp") - + rng = Dates.Date(2013):Dates.Day(1):Dates.Date(2013, 1, 5) dt = (i = collect(rng), j = collect(rng)) tablename = dt |> SQLite.load!(db, "temp") @@ -214,7 +216,7 @@ end @test length(r) == 2 && length(r[1]) == 5 @test all([i for i in r[1]] .== collect(rng)) @test all([typeof(i) for i in r[1]] .== Dates.Date) - SQLite.drop!(db, "$tablename") + SQLite.drop!(db, "$tablename") end @testset "Prepared Statements" begin @@ -227,13 +229,17 @@ end DBInterface.execute(db, "SELECT * FROM temp WHERE Title LIKE ?", ["%time%"]) |> columntable @test r[1] == [76, 111, 187] - DBInterface.execute(db, "INSERT INTO temp VALUES (?1, ?3, ?2)", [0, 0, "Test Album"]) + DBInterface.execute( + db, + "INSERT INTO temp VALUES (?1, ?3, ?2)", + [0, 0, "Test Album"], + ) r = DBInterface.execute(db, "SELECT * FROM temp WHERE AlbumId = 0") |> columntable @test r[1][1] == 0 @test r[2][1] == "Test Album" @test r[3][1] == 0 SQLite.drop!(db, "temp") - + DBInterface.execute(db, "CREATE TABLE temp AS SELECT * FROM Album") r = DBInterface.execute(db, "SELECT * FROM temp LIMIT :a", (a = 3,)) |> columntable @test length(r) == 3 && length(r[1]) == 3 @@ -265,7 +271,7 @@ end @test r[2] == ["Test Album", "Test2 Album"] @test r[3] == [1, 3] SQLite.drop!(db, "temp") - + SQLite.register(db, SQLite.regexp, nargs = 2, name = "regexp") r = DBInterface.execute( @@ -275,7 +281,7 @@ end ) ) |> columntable @test r[1][1] == "Peacock" - + SQLite.register(db, identity, nargs = 1, name = "identity") r = DBInterface.execute( @@ -284,7 +290,7 @@ end ) |> columntable @test first(r.x) == "abc" @test first(r.cmp) == 1 - + @test_throws AssertionError SQLite.register(db, triple, nargs = 186) SQLite.register(db, triple, nargs = 1) r = @@ -293,35 +299,39 @@ end "SELECT triple(Total) FROM Invoice ORDER BY InvoiceId LIMIT 5", ) |> columntable s = - DBInterface.execute(db, "SELECT Total FROM Invoice ORDER BY InvoiceId LIMIT 5") |> - columntable + DBInterface.execute( + db, + "SELECT Total FROM Invoice ORDER BY InvoiceId LIMIT 5", + ) |> columntable for (i, j) in zip(r[1], s[1]) @test abs(i - 3 * j) < 0.02 - end + end end - + @testset "Register functions" begin db = setup_clean_test_db() SQLite.@register db add4 r = DBInterface.execute(db, "SELECT add4(AlbumId) FROM Album") |> columntable s = DBInterface.execute(db, "SELECT AlbumId FROM Album") |> columntable @test r[1][1] == s[1][1] + 4 - + SQLite.@register db mult r = DBInterface.execute(db, "SELECT GenreId, UnitPrice FROM Track") |> columntable - s = DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice) FROM Track") |> columntable + s = + DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice) FROM Track") |> + columntable @test (r[1][1] * r[2][1]) == s[1][1] t = DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice, 3, 4) FROM Track") |> columntable @test (r[1][1] * r[2][1] * 3 * 4) == t[1][1] - + SQLite.@register db sin u = DBInterface.execute(db, "select sin(milliseconds) from track limit 5") |> columntable @test all(-1 .< convert(Vector{Float64}, u[1]) .< 1) - + SQLite.register(db, hypot; nargs = 2, name = "hypotenuse") v = DBInterface.execute( @@ -329,54 +339,60 @@ end "select hypotenuse(Milliseconds,bytes) from track limit 5", ) |> columntable @test [round(Int, i) for i in v[1]] == [11175621, 5521062, 3997652, 4339106, 6301714] - + SQLite.@register db str2arr r = DBInterface.execute(db, "SELECT str2arr(LastName) FROM Employee LIMIT 2") |> columntable @test r[1][2] == UInt8[0x45, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73] - + SQLite.@register db big r = DBInterface.execute(db, "SELECT big(5)") |> columntable @test r[1][1] == big(5) @test typeof(r[1][1]) == BigInt - + SQLite.register(db, 0, doublesum_step, doublesum_final, name = "doublesum") r = DBInterface.execute(db, "SELECT doublesum(UnitPrice) FROM Track") |> columntable s = DBInterface.execute(db, "SELECT UnitPrice FROM Track") |> columntable @test abs(r[1][1] - 2 * sum(convert(Vector{Float64}, s[1]))) < 0.02 - - + + SQLite.register(db, 0, mycount) - r = DBInterface.execute(db, "SELECT mycount(TrackId) FROM PlaylistTrack") |> columntable - s = DBInterface.execute(db, "SELECT count(TrackId) FROM PlaylistTrack") |> columntable + r = + DBInterface.execute(db, "SELECT mycount(TrackId) FROM PlaylistTrack") |> + columntable + s = + DBInterface.execute(db, "SELECT count(TrackId) FROM PlaylistTrack") |> + columntable @test r[1][1] == s[1][1] - + SQLite.register(db, big(0), bigsum) - r = DBInterface.execute(db, "SELECT bigsum(TrackId) FROM PlaylistTrack") |> columntable + r = + DBInterface.execute(db, "SELECT bigsum(TrackId) FROM PlaylistTrack") |> + columntable s = DBInterface.execute(db, "SELECT TrackId FROM PlaylistTrack") |> columntable @test r[1][1] == big(sum(convert(Vector{Int}, s[1]))) - + DBInterface.execute(db, "CREATE TABLE points (x INT, y INT, z INT)") DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (1, 2, 3)) DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (4, 5, 6)) DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (7, 8, 9)) - + SQLite.register(db, Point3D(0, 0, 0), sumpoint) r = DBInterface.execute(db, "SELECT sumpoint(x, y, z) FROM points") |> columntable @test r[1][1] == Point3D(12, 15, 18) SQLite.drop!(db, "points") - + db2 = DBInterface.connect(SQLite.DB) DBInterface.execute(db2, "CREATE TABLE tab1 (r REAL, s INT)") - + @test_throws SQLiteException SQLite.drop!(db2, "nonexistant") # should not throw anything SQLite.drop!(db2, "nonexistant", ifexists = true) # should drop "tab2" SQLite.drop!(db2, "tab2", ifexists = true) @test !in("tab2", SQLite.tables(db2)[1]) - + SQLite.drop!(db, "sqlite_stat1", ifexists = true) tables = SQLite.tables(db) @test length(tables[1]) == 11 @@ -483,22 +499,22 @@ end @test row[1] == "Hello!" GC.gc() # this must NOT garbage collect the "Hello!" bound value end - + db = SQLite.DB() DBInterface.execute(db, "CREATE TABLE T (a TEXT, PRIMARY KEY (a))") - + q = DBInterface.prepare(db, "INSERT INTO T VALUES(?)") DBInterface.execute(q, ["a"]) - + SQLite.bind!(q, 1, "a") - @test_throws SQLiteException DBInterface.execute(q) + @test_throws SQLiteException DBInterface.execute(q) end @testset "Enable extension" begin db = SQLite.DB() - @test SQLite.@OK SQLite.enable_load_extension(db) + @test SQLite.@OK SQLite.enable_load_extension(db) end - + @testset "show(DB)" begin io = IOBuffer() db = SQLite.DB() @@ -508,9 +524,9 @@ end DBInterface.close!(db) end - - + + @testset "SQLite.execute()" begin db = SQLite.DB() @@ -539,19 +555,19 @@ end @test r[1] == [1, 2, 3, 4, 5] r = DBInterface.execute(db, strip(" SELECT * FROM T ")) |> columntable - @test r[1] == [1, 2, 3, 4, 5] + @test r[1] == [1, 2, 3, 4, 5] SQLite.createindex!(db, "T", "x", "x_index"; unique = false) inds = SQLite.indices(db) @test last(inds.name) == "x" SQLite.dropindex!(db, "x") @test length(SQLite.indices(db).name) == 1 - + cols = SQLite.columns(db, "T") @test cols.name == ["x"] - + @test SQLite.last_insert_rowid(db) == 5 - + r = DBInterface.execute(db, "SELECT * FROM T") @test Tables.istable(r) @test Tables.rowaccess(r) @@ -564,11 +580,11 @@ end @test row[:x] == row2[:x] @test propertynames(row) == [:x] @test DBInterface.lastrowid(r) == 5 - + r = DBInterface.execute(db, "SELECT * FROM T") |> columntable SQLite.load!(nothing, Tables.rows(r), db, "T2", SQLite.tableinfo(db, "T2")) r2 = DBInterface.execute(db, "SELECT * FROM T2") |> columntable - @test r == r2 + @test r == r2 end @testset "Escaping" begin @@ -579,9 +595,9 @@ end @testset "Issue #193: Throw informative error on duplicate column names" begin db = SQLite.DB() - @test_throws SQLiteException SQLite.load!((a = [1, 2, 3], A = [1, 2, 3]), db) + @test_throws SQLiteException SQLite.load!((a = [1, 2, 3], A = [1, 2, 3]), db) end - + @testset "Issue #216: Table should map by name" begin db = SQLite.DB() @@ -590,10 +606,10 @@ end tbl2 = (b = [7, 8, 9], a = [4, 5, 6]) SQLite.load!(tbl1, db, "data") SQLite.load!(tbl2, db, "data") - + res = DBInterface.execute(db, "SELECT * FROM data") |> columntable expected = (a = [1, 2, 3, 4, 5, 6], b = [4, 5, 6, 7, 8, 9]) - @test res == expected + @test res == expected end @testset "Issue #216: Table should error if names don't match" begin From 3a1baed9ef926bac22d4b64d03ba41e020c9c6d0 Mon Sep 17 00:00:00 2001 From: Jeremiah <4462211+jeremiahpslewis@users.noreply.github.com> Date: Fri, 5 Nov 2021 20:07:21 +0000 Subject: [PATCH 7/9] Tweaks --- test/runtests.jl | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index cd98576..d678180 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -33,20 +33,26 @@ mycount(p, c) = p + 1 bigsum(p, c) = p + big(c) sumpoint(p::Point3D, x, y, z) = p + Point3D(x, y, z) -test_dbfile = joinpath(tempdir(), "test.sqlite") - """ setup_clean_test_db() Copy test sqlite file to temp directory, path `test.sqlite`, overwrite file if necessary and set permissions. """ -function setup_clean_test_db() +function setup_clean_test_db(f::Function, args...) dbfile = joinpath(dirname(pathof(SQLite)), "../test/Chinook_Sqlite.sqlite") + tmp_dir = mktempdir() + test_dbfile = joinpath(tmp_dir, "test.sqlite") + cp(dbfile, test_dbfile; force = true) chmod(test_dbfile, 0o777) - return SQLite.DB(test_dbfile) + try + db = SQLite.DB(test_dbfile) + f(db) + finally + close(db) + rm(tmp_dir) end @testset "basics" begin @@ -62,9 +68,11 @@ end end @testset "DB Connection" begin - setup_clean_test_db() - @test SQLite.DB(test_dbfile) isa SQLite.DB - @test DBInterface.connect(SQLite.DB, test_dbfile) isa SQLite.DB + dbfile = joinpath(dirname(pathof(SQLite)), "../test/Chinook_Sqlite.sqlite") + @test SQLite.DB(dbfile) isa SQLite.DB + con = DBInterface.connect(SQLite.DB, dbfile) + @test con isa SQLite.DB + DBInterface.close!(con) end @testset "Issue #207: 32 bit integers" begin From c9ce13046d8dcf97f5e5a722e5bf1f99312cd5c4 Mon Sep 17 00:00:00 2001 From: Jeremiah <4462211+jeremiahpslewis@users.noreply.github.com> Date: Fri, 5 Nov 2021 20:20:53 +0000 Subject: [PATCH 8/9] Use do block --- test/runtests.jl | 598 ++++++++++++++++++++++++----------------------- 1 file changed, 306 insertions(+), 292 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index d678180..4144f47 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -34,7 +34,9 @@ bigsum(p, c) = p + big(c) sumpoint(p::Point3D, x, y, z) = p + Point3D(x, y, z) """ - setup_clean_test_db() + setup_clean_test_db() do db + @test db isa SQLite.DB + end Copy test sqlite file to temp directory, path `test.sqlite`, overwrite file if necessary and set permissions. @@ -47,12 +49,13 @@ function setup_clean_test_db(f::Function, args...) cp(dbfile, test_dbfile; force = true) chmod(test_dbfile, 0o777) + db = SQLite.DB(test_dbfile) try - db = SQLite.DB(test_dbfile) f(db) finally close(db) - rm(tmp_dir) + rm(tmp_dir, recursive = true) + end end @testset "basics" begin @@ -76,338 +79,349 @@ end end @testset "Issue #207: 32 bit integers" begin - setup_clean_test_db() - db = SQLite.DB(test_dbfile) - ds = - DBInterface.execute(db, "SELECT RANDOM() as a FROM Track LIMIT 1") |> - columntable - @test ds.a[1] isa Int64 + setup_clean_test_db() do db + db = SQLite.DB(test_dbfile) + ds = + DBInterface.execute(db, "SELECT RANDOM() as a FROM Track LIMIT 1") |> + columntable + @test ds.a[1] isa Int64 + + end end @testset "Regular SQLite Tests" begin - db = setup_clean_test_db() - @test_throws SQLiteException DBInterface.execute(db, "just some syntax error") - # syntax correct, table missing - @test_throws SQLiteException DBInterface.execute( - db, - "SELECT name FROM sqlite_nomaster WHERE type='table';", - ) + setup_clean_test_db() do db + @test_throws SQLiteException DBInterface.execute(db, "just some syntax error") + # syntax correct, table missing + @test_throws SQLiteException DBInterface.execute( + db, + "SELECT name FROM sqlite_nomaster WHERE type='table';", + ) + end end @testset "close!(query)" begin - db = setup_clean_test_db() - - qry = DBInterface.execute(db, "SELECT name FROM sqlite_master WHERE type='table';") - DBInterface.close!(qry) - DBInterface.close!(qry) # test it doesn't throw on double-close + setup_clean_test_db() do db + qry = DBInterface.execute(db, "SELECT name FROM sqlite_master WHERE type='table';") + DBInterface.close!(qry) + DBInterface.close!(qry) # test it doesn't throw on double-close + end end @testset "Query tables" begin - db = setup_clean_test_db() - ds = - DBInterface.execute(db, "SELECT name FROM sqlite_master WHERE type='table';") |> - columntable - @test length(ds) == 1 - @test keys(ds) == (:name,) - @test length(ds.name) == 11 - - results1 = SQLite.tables(db) - @test isequal(ds, results1) + setup_clean_test_db() do db + ds = + DBInterface.execute(db, "SELECT name FROM sqlite_master WHERE type='table';") |> + columntable + @test length(ds) == 1 + @test keys(ds) == (:name,) + @test length(ds.name) == 11 + + results1 = SQLite.tables(db) + @test isequal(ds, results1) + end end @testset "DBInterface.execute([f])" begin - db = setup_clean_test_db() - - # pipe approach - results = DBInterface.execute(db, "SELECT * FROM Employee;") |> columntable - @test length(results) == 15 - @test length(results[1]) == 8 - # callable approach - @test isequal( - DBInterface.execute(columntable, db, "SELECT * FROM Employee"), - results, - ) - employees_stmt = DBInterface.prepare(db, "SELECT * FROM Employee") - @test isequal(columntable(DBInterface.execute(employees_stmt)), results) - @test isequal(DBInterface.execute(columntable, employees_stmt), results) - @testset "throwing from f()" begin - f(::SQLite.Query) = error("I'm throwing!") - @test_throws ErrorException DBInterface.execute(f, employees_stmt) - @test_throws ErrorException DBInterface.execute(f, db, "SELECT * FROM Employee") + setup_clean_test_db() do db + + # pipe approach + results = DBInterface.execute(db, "SELECT * FROM Employee;") |> columntable + @test length(results) == 15 + @test length(results[1]) == 8 + # callable approach + @test isequal( + DBInterface.execute(columntable, db, "SELECT * FROM Employee"), + results, + ) + employees_stmt = DBInterface.prepare(db, "SELECT * FROM Employee") + @test isequal(columntable(DBInterface.execute(employees_stmt)), results) + @test isequal(DBInterface.execute(columntable, employees_stmt), results) + @testset "throwing from f()" begin + f(::SQLite.Query) = error("I'm throwing!") + @test_throws ErrorException DBInterface.execute(f, employees_stmt) + @test_throws ErrorException DBInterface.execute(f, db, "SELECT * FROM Employee") + end + DBInterface.close!(employees_stmt) end - DBInterface.close!(employees_stmt) end @testset "isempty(::Query)" begin - db = setup_clean_test_db() + setup_clean_test_db() do db - @test !DBInterface.execute(isempty, db, "SELECT * FROM Employee") - @test DBInterface.execute( - isempty, - db, - "SELECT * FROM Employee WHERE FirstName='Joanne'", - ) + @test !DBInterface.execute(isempty, db, "SELECT * FROM Employee") + @test DBInterface.execute( + isempty, + db, + "SELECT * FROM Employee WHERE FirstName='Joanne'", + ) + end end @testset "empty query has correct schema and return type" begin - db = setup_clean_test_db() - empty_scheme = DBInterface.execute( - Tables.schema, - db, - "SELECT * FROM Employee WHERE FirstName='Joanne'", - ) - all_scheme = DBInterface.execute( - Tables.schema, - db, - "SELECT * FROM Employee WHERE FirstName='Joanne'", - ) - @test empty_scheme.names == all_scheme.names - @test all(ea -> ea[1] <: ea[2], zip(empty_scheme.types, all_scheme.types)) + setup_clean_test_db() do db + empty_scheme = DBInterface.execute( + Tables.schema, + db, + "SELECT * FROM Employee WHERE FirstName='Joanne'", + ) + all_scheme = DBInterface.execute( + Tables.schema, + db, + "SELECT * FROM Employee WHERE FirstName='Joanne'", + ) + @test empty_scheme.names == all_scheme.names + @test all(ea -> ea[1] <: ea[2], zip(empty_scheme.types, all_scheme.types)) - empty_tbl = DBInterface.execute( - columntable, - db, - "SELECT * FROM Employee WHERE FirstName='Joanne'", - ) - all_tbl = DBInterface.execute(columntable, db, "SELECT * FROM Employee") - @test propertynames(empty_tbl) == propertynames(all_tbl) - @test all( - col -> - eltype(empty_tbl[col]) == Missing || - eltype(empty_tbl[col]) >: eltype(all_tbl[col]), - propertynames(all_tbl), - ) + empty_tbl = DBInterface.execute( + columntable, + db, + "SELECT * FROM Employee WHERE FirstName='Joanne'", + ) + all_tbl = DBInterface.execute(columntable, db, "SELECT * FROM Employee") + @test propertynames(empty_tbl) == propertynames(all_tbl) + @test all( + col -> + eltype(empty_tbl[col]) == Missing || + eltype(empty_tbl[col]) >: eltype(all_tbl[col]), + propertynames(all_tbl), + ) + end end @testset "Create table, run commit/rollback tests" begin - db = setup_clean_test_db() - DBInterface.execute(db, "create table temp as select * from album") - DBInterface.execute(db, "alter table temp add column colyear int") - DBInterface.execute(db, "update temp set colyear = 2014") - r = DBInterface.execute(db, "select * from temp limit 10") |> columntable - @test length(r) == 4 && length(r[1]) == 10 - @test all(==(2014), r[4]) - - @test_throws SQLiteException SQLite.rollback(db) - @test_throws SQLiteException SQLite.commit(db) - - SQLite.transaction(db) - DBInterface.execute(db, "update temp set colyear = 2015") - SQLite.rollback(db) - r = DBInterface.execute(db, "select * from temp limit 10") |> columntable - @test all(==(2014), r[4]) - - SQLite.transaction(db) - DBInterface.execute(db, "update temp set colyear = 2015") - SQLite.commit(db) - r = DBInterface.execute(db, "select * from temp limit 10") |> columntable - @test all(==(2015), r[4]) + setup_clean_test_db() do db + DBInterface.execute(db, "create table temp as select * from album") + DBInterface.execute(db, "alter table temp add column colyear int") + DBInterface.execute(db, "update temp set colyear = 2014") + r = DBInterface.execute(db, "select * from temp limit 10") |> columntable + @test length(r) == 4 && length(r[1]) == 10 + @test all(==(2014), r[4]) + + @test_throws SQLiteException SQLite.rollback(db) + @test_throws SQLiteException SQLite.commit(db) + + SQLite.transaction(db) + DBInterface.execute(db, "update temp set colyear = 2015") + SQLite.rollback(db) + r = DBInterface.execute(db, "select * from temp limit 10") |> columntable + @test all(==(2014), r[4]) + + SQLite.transaction(db) + DBInterface.execute(db, "update temp set colyear = 2015") + SQLite.commit(db) + r = DBInterface.execute(db, "select * from temp limit 10") |> columntable + @test all(==(2015), r[4]) + end end @testset "Dates" begin - db = setup_clean_test_db() - DBInterface.execute(db, "create table temp as select * from album") - DBInterface.execute(db, "alter table temp add column dates blob") - stmt = DBInterface.prepare(db, "update temp set dates = ?") - DBInterface.execute(stmt, (Date(2014, 1, 1),)) - - r = DBInterface.execute(db, "select * from temp limit 10") |> columntable - @test length(r) == 4 && length(r[1]) == 10 - @test typeof(r[4][1]) == Date - @test all(Bool[x == Date(2014, 1, 1) for x in r[4]]) - DBInterface.execute(db, "drop table temp") - - rng = Dates.Date(2013):Dates.Day(1):Dates.Date(2013, 1, 5) - dt = (i = collect(rng), j = collect(rng)) - tablename = dt |> SQLite.load!(db, "temp") - r = DBInterface.execute(db, "select * from $tablename") |> columntable - @test length(r) == 2 && length(r[1]) == 5 - @test all([i for i in r[1]] .== collect(rng)) - @test all([typeof(i) for i in r[1]] .== Dates.Date) - SQLite.drop!(db, "$tablename") + setup_clean_test_db() do db + DBInterface.execute(db, "create table temp as select * from album") + DBInterface.execute(db, "alter table temp add column dates blob") + stmt = DBInterface.prepare(db, "update temp set dates = ?") + DBInterface.execute(stmt, (Date(2014, 1, 1),)) + + r = DBInterface.execute(db, "select * from temp limit 10") |> columntable + @test length(r) == 4 && length(r[1]) == 10 + @test typeof(r[4][1]) == Date + @test all(Bool[x == Date(2014, 1, 1) for x in r[4]]) + DBInterface.execute(db, "drop table temp") + + rng = Dates.Date(2013):Dates.Day(1):Dates.Date(2013, 1, 5) + dt = (i = collect(rng), j = collect(rng)) + tablename = dt |> SQLite.load!(db, "temp") + r = DBInterface.execute(db, "select * from $tablename") |> columntable + @test length(r) == 2 && length(r[1]) == 5 + @test all([i for i in r[1]] .== collect(rng)) + @test all([typeof(i) for i in r[1]] .== Dates.Date) + SQLite.drop!(db, "$tablename") + end end @testset "Prepared Statements" begin - db = setup_clean_test_db() - - DBInterface.execute(db, "CREATE TABLE temp AS SELECT * FROM Album") - r = DBInterface.execute(db, "SELECT * FROM temp LIMIT ?", [3]) |> columntable - @test length(r) == 3 && length(r[1]) == 3 - r = - DBInterface.execute(db, "SELECT * FROM temp WHERE Title LIKE ?", ["%time%"]) |> - columntable - @test r[1] == [76, 111, 187] - DBInterface.execute( - db, - "INSERT INTO temp VALUES (?1, ?3, ?2)", - [0, 0, "Test Album"], - ) - r = DBInterface.execute(db, "SELECT * FROM temp WHERE AlbumId = 0") |> columntable - @test r[1][1] == 0 - @test r[2][1] == "Test Album" - @test r[3][1] == 0 - SQLite.drop!(db, "temp") - - DBInterface.execute(db, "CREATE TABLE temp AS SELECT * FROM Album") - r = DBInterface.execute(db, "SELECT * FROM temp LIMIT :a", (a = 3,)) |> columntable - @test length(r) == 3 && length(r[1]) == 3 - r = DBInterface.execute(db, "SELECT * FROM temp LIMIT :a", a = 3) |> columntable - @test length(r) == 3 && length(r[1]) == 3 - r = - DBInterface.execute( - db, - "SELECT * FROM temp WHERE Title LIKE @word", - (word = "%time%",), - ) |> columntable - @test r[1] == [76, 111, 187] - DBInterface.execute( - db, - "INSERT INTO temp VALUES (@lid, :title, \$rid)", - (rid = 1, lid = 0, title = "Test Album"), - ) - DBInterface.execute( - db, - "INSERT INTO temp VALUES (@lid, :title, \$rid)", - rid = 3, - lid = 400, - title = "Test2 Album", - ) - r = - DBInterface.execute(db, "SELECT * FROM temp WHERE AlbumId IN (0, 400)") |> - columntable - @test r[1] == [0, 400] - @test r[2] == ["Test Album", "Test2 Album"] - @test r[3] == [1, 3] - SQLite.drop!(db, "temp") - - SQLite.register(db, SQLite.regexp, nargs = 2, name = "regexp") - r = - DBInterface.execute( - db, - SQLite.@sr_str( - "SELECT LastName FROM Employee WHERE BirthDate REGEXP '^\\d{4}-08'" - ) - ) |> columntable - @test r[1][1] == "Peacock" - - SQLite.register(db, identity, nargs = 1, name = "identity") - r = + setup_clean_test_db() do db + + DBInterface.execute(db, "CREATE TABLE temp AS SELECT * FROM Album") + r = DBInterface.execute(db, "SELECT * FROM temp LIMIT ?", [3]) |> columntable + @test length(r) == 3 && length(r[1]) == 3 + r = + DBInterface.execute(db, "SELECT * FROM temp WHERE Title LIKE ?", ["%time%"]) |> + columntable + @test r[1] == [76, 111, 187] DBInterface.execute( db, - """SELECT identity("abc") as x, "abc" == identity("abc") as cmp""", - ) |> columntable - @test first(r.x) == "abc" - @test first(r.cmp) == 1 - - @test_throws AssertionError SQLite.register(db, triple, nargs = 186) - SQLite.register(db, triple, nargs = 1) - r = + "INSERT INTO temp VALUES (?1, ?3, ?2)", + [0, 0, "Test Album"], + ) + r = DBInterface.execute(db, "SELECT * FROM temp WHERE AlbumId = 0") |> columntable + @test r[1][1] == 0 + @test r[2][1] == "Test Album" + @test r[3][1] == 0 + SQLite.drop!(db, "temp") + + DBInterface.execute(db, "CREATE TABLE temp AS SELECT * FROM Album") + r = DBInterface.execute(db, "SELECT * FROM temp LIMIT :a", (a = 3,)) |> columntable + @test length(r) == 3 && length(r[1]) == 3 + r = DBInterface.execute(db, "SELECT * FROM temp LIMIT :a", a = 3) |> columntable + @test length(r) == 3 && length(r[1]) == 3 + r = + DBInterface.execute( + db, + "SELECT * FROM temp WHERE Title LIKE @word", + (word = "%time%",), + ) |> columntable + @test r[1] == [76, 111, 187] DBInterface.execute( db, - "SELECT triple(Total) FROM Invoice ORDER BY InvoiceId LIMIT 5", - ) |> columntable - s = + "INSERT INTO temp VALUES (@lid, :title, \$rid)", + (rid = 1, lid = 0, title = "Test Album"), + ) DBInterface.execute( db, - "SELECT Total FROM Invoice ORDER BY InvoiceId LIMIT 5", - ) |> columntable - for (i, j) in zip(r[1], s[1]) - @test abs(i - 3 * j) < 0.02 + "INSERT INTO temp VALUES (@lid, :title, \$rid)", + rid = 3, + lid = 400, + title = "Test2 Album", + ) + r = + DBInterface.execute(db, "SELECT * FROM temp WHERE AlbumId IN (0, 400)") |> + columntable + @test r[1] == [0, 400] + @test r[2] == ["Test Album", "Test2 Album"] + @test r[3] == [1, 3] + SQLite.drop!(db, "temp") + + SQLite.register(db, SQLite.regexp, nargs = 2, name = "regexp") + r = + DBInterface.execute( + db, + SQLite.@sr_str( + "SELECT LastName FROM Employee WHERE BirthDate REGEXP '^\\d{4}-08'" + ) + ) |> columntable + @test r[1][1] == "Peacock" + + SQLite.register(db, identity, nargs = 1, name = "identity") + r = + DBInterface.execute( + db, + """SELECT identity("abc") as x, "abc" == identity("abc") as cmp""", + ) |> columntable + @test first(r.x) == "abc" + @test first(r.cmp) == 1 + + @test_throws AssertionError SQLite.register(db, triple, nargs = 186) + SQLite.register(db, triple, nargs = 1) + r = + DBInterface.execute( + db, + "SELECT triple(Total) FROM Invoice ORDER BY InvoiceId LIMIT 5", + ) |> columntable + s = + DBInterface.execute( + db, + "SELECT Total FROM Invoice ORDER BY InvoiceId LIMIT 5", + ) |> columntable + for (i, j) in zip(r[1], s[1]) + @test abs(i - 3 * j) < 0.02 + end end end @testset "Register functions" begin - db = setup_clean_test_db() - SQLite.@register db add4 - r = DBInterface.execute(db, "SELECT add4(AlbumId) FROM Album") |> columntable - s = DBInterface.execute(db, "SELECT AlbumId FROM Album") |> columntable - @test r[1][1] == s[1][1] + 4 - - SQLite.@register db mult - r = DBInterface.execute(db, "SELECT GenreId, UnitPrice FROM Track") |> columntable - s = - DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice) FROM Track") |> - columntable - @test (r[1][1] * r[2][1]) == s[1][1] - t = - DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice, 3, 4) FROM Track") |> - columntable - @test (r[1][1] * r[2][1] * 3 * 4) == t[1][1] - - SQLite.@register db sin - u = - DBInterface.execute(db, "select sin(milliseconds) from track limit 5") |> - columntable - @test all(-1 .< convert(Vector{Float64}, u[1]) .< 1) - - SQLite.register(db, hypot; nargs = 2, name = "hypotenuse") - v = - DBInterface.execute( - db, - "select hypotenuse(Milliseconds,bytes) from track limit 5", - ) |> columntable - @test [round(Int, i) for i in v[1]] == [11175621, 5521062, 3997652, 4339106, 6301714] - - SQLite.@register db str2arr - r = - DBInterface.execute(db, "SELECT str2arr(LastName) FROM Employee LIMIT 2") |> - columntable - @test r[1][2] == UInt8[0x45, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73] - - SQLite.@register db big - r = DBInterface.execute(db, "SELECT big(5)") |> columntable - @test r[1][1] == big(5) - @test typeof(r[1][1]) == BigInt - - SQLite.register(db, 0, doublesum_step, doublesum_final, name = "doublesum") - r = DBInterface.execute(db, "SELECT doublesum(UnitPrice) FROM Track") |> columntable - s = DBInterface.execute(db, "SELECT UnitPrice FROM Track") |> columntable - @test abs(r[1][1] - 2 * sum(convert(Vector{Float64}, s[1]))) < 0.02 - - - SQLite.register(db, 0, mycount) - r = - DBInterface.execute(db, "SELECT mycount(TrackId) FROM PlaylistTrack") |> - columntable - s = - DBInterface.execute(db, "SELECT count(TrackId) FROM PlaylistTrack") |> - columntable - @test r[1][1] == s[1][1] - - SQLite.register(db, big(0), bigsum) - r = - DBInterface.execute(db, "SELECT bigsum(TrackId) FROM PlaylistTrack") |> - columntable - s = DBInterface.execute(db, "SELECT TrackId FROM PlaylistTrack") |> columntable - @test r[1][1] == big(sum(convert(Vector{Int}, s[1]))) - - DBInterface.execute(db, "CREATE TABLE points (x INT, y INT, z INT)") - DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (1, 2, 3)) - DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (4, 5, 6)) - DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (7, 8, 9)) - - SQLite.register(db, Point3D(0, 0, 0), sumpoint) - r = DBInterface.execute(db, "SELECT sumpoint(x, y, z) FROM points") |> columntable - @test r[1][1] == Point3D(12, 15, 18) - SQLite.drop!(db, "points") - - db2 = DBInterface.connect(SQLite.DB) - DBInterface.execute(db2, "CREATE TABLE tab1 (r REAL, s INT)") - - @test_throws SQLiteException SQLite.drop!(db2, "nonexistant") - # should not throw anything - SQLite.drop!(db2, "nonexistant", ifexists = true) - # should drop "tab2" - SQLite.drop!(db2, "tab2", ifexists = true) - @test !in("tab2", SQLite.tables(db2)[1]) - - SQLite.drop!(db, "sqlite_stat1", ifexists = true) - tables = SQLite.tables(db) - @test length(tables[1]) == 11 + setup_clean_test_db() do db + SQLite.@register db add4 + r = DBInterface.execute(db, "SELECT add4(AlbumId) FROM Album") |> columntable + s = DBInterface.execute(db, "SELECT AlbumId FROM Album") |> columntable + @test r[1][1] == s[1][1] + 4 + + SQLite.@register db mult + r = DBInterface.execute(db, "SELECT GenreId, UnitPrice FROM Track") |> columntable + s = + DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice) FROM Track") |> + columntable + @test (r[1][1] * r[2][1]) == s[1][1] + t = + DBInterface.execute(db, "SELECT mult(GenreId, UnitPrice, 3, 4) FROM Track") |> + columntable + @test (r[1][1] * r[2][1] * 3 * 4) == t[1][1] + + SQLite.@register db sin + u = + DBInterface.execute(db, "select sin(milliseconds) from track limit 5") |> + columntable + @test all(-1 .< convert(Vector{Float64}, u[1]) .< 1) + + SQLite.register(db, hypot; nargs = 2, name = "hypotenuse") + v = + DBInterface.execute( + db, + "select hypotenuse(Milliseconds,bytes) from track limit 5", + ) |> columntable + @test [round(Int, i) for i in v[1]] == [11175621, 5521062, 3997652, 4339106, 6301714] + + SQLite.@register db str2arr + r = + DBInterface.execute(db, "SELECT str2arr(LastName) FROM Employee LIMIT 2") |> + columntable + @test r[1][2] == UInt8[0x45, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73] + + SQLite.@register db big + r = DBInterface.execute(db, "SELECT big(5)") |> columntable + @test r[1][1] == big(5) + @test typeof(r[1][1]) == BigInt + + SQLite.register(db, 0, doublesum_step, doublesum_final, name = "doublesum") + r = DBInterface.execute(db, "SELECT doublesum(UnitPrice) FROM Track") |> columntable + s = DBInterface.execute(db, "SELECT UnitPrice FROM Track") |> columntable + @test abs(r[1][1] - 2 * sum(convert(Vector{Float64}, s[1]))) < 0.02 + + + SQLite.register(db, 0, mycount) + r = + DBInterface.execute(db, "SELECT mycount(TrackId) FROM PlaylistTrack") |> + columntable + s = + DBInterface.execute(db, "SELECT count(TrackId) FROM PlaylistTrack") |> + columntable + @test r[1][1] == s[1][1] + + SQLite.register(db, big(0), bigsum) + r = + DBInterface.execute(db, "SELECT bigsum(TrackId) FROM PlaylistTrack") |> + columntable + s = DBInterface.execute(db, "SELECT TrackId FROM PlaylistTrack") |> columntable + @test r[1][1] == big(sum(convert(Vector{Int}, s[1]))) + + DBInterface.execute(db, "CREATE TABLE points (x INT, y INT, z INT)") + DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (1, 2, 3)) + DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (4, 5, 6)) + DBInterface.execute(db, "INSERT INTO points VALUES (?, ?, ?)", (7, 8, 9)) + + SQLite.register(db, Point3D(0, 0, 0), sumpoint) + r = DBInterface.execute(db, "SELECT sumpoint(x, y, z) FROM points") |> columntable + @test r[1][1] == Point3D(12, 15, 18) + SQLite.drop!(db, "points") + + db2 = DBInterface.connect(SQLite.DB) + DBInterface.execute(db2, "CREATE TABLE tab1 (r REAL, s INT)") + + @test_throws SQLiteException SQLite.drop!(db2, "nonexistant") + # should not throw anything + SQLite.drop!(db2, "nonexistant", ifexists = true) + # should drop "tab2" + SQLite.drop!(db2, "tab2", ifexists = true) + @test !in("tab2", SQLite.tables(db2)[1]) + + SQLite.drop!(db, "sqlite_stat1", ifexists = true) + tables = SQLite.tables(db) + @test length(tables[1]) == 11 + end end @testset "Remove Duplicates" begin - db = setup_clean_test_db() + setup_clean_test_db() do db db = SQLite.DB() #In case the order of tests is changed dt = (ints = Int64[1, 1, 2, 2, 3], strs = ["A", "A", "B", "C", "C"]) tablename = dt |> SQLite.load!(db, "temp") From 7f53825cf16ffe36e8f3ffb71ed1c468403882d0 Mon Sep 17 00:00:00 2001 From: Jeremiah <4462211+jeremiahpslewis@users.noreply.github.com> Date: Fri, 5 Nov 2021 20:25:15 +0000 Subject: [PATCH 9/9] Fix test --- test/runtests.jl | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 4144f47..6014b0c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -80,7 +80,6 @@ end @testset "Issue #207: 32 bit integers" begin setup_clean_test_db() do db - db = SQLite.DB(test_dbfile) ds = DBInterface.execute(db, "SELECT RANDOM() as a FROM Track LIMIT 1") |> columntable @@ -422,17 +421,18 @@ end @testset "Remove Duplicates" begin setup_clean_test_db() do db - db = SQLite.DB() #In case the order of tests is changed - dt = (ints = Int64[1, 1, 2, 2, 3], strs = ["A", "A", "B", "C", "C"]) - tablename = dt |> SQLite.load!(db, "temp") - SQLite.removeduplicates!(db, "temp", ["ints", "strs"]) #New format - dt3 = DBInterface.execute(db, "Select * from temp") |> columntable - @test dt3[1][1] == 1 - @test dt3[2][1] == "A" - @test dt3[1][2] == 2 - @test dt3[2][2] == "B" - @test dt3[1][3] == 2 - @test dt3[2][3] == "C" + db = SQLite.DB() #In case the order of tests is changed + dt = (ints = Int64[1, 1, 2, 2, 3], strs = ["A", "A", "B", "C", "C"]) + tablename = dt |> SQLite.load!(db, "temp") + SQLite.removeduplicates!(db, "temp", ["ints", "strs"]) #New format + dt3 = DBInterface.execute(db, "Select * from temp") |> columntable + @test dt3[1][1] == 1 + @test dt3[2][1] == "A" + @test dt3[1][2] == 2 + @test dt3[2][2] == "B" + @test dt3[1][3] == 2 + @test dt3[2][3] == "C" + end end