Skip to content

Commit c55b94a

Browse files
authored
Merge pull request #3 from usernamenotavailablepleasechooseanother/master
Fix linker error on Windows, improve tests
2 parents 8a238d8 + 4649869 commit c55b94a

File tree

5 files changed

+51
-25
lines changed

5 files changed

+51
-25
lines changed

SQLite/FFI.lean

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,14 @@ structure Cursor where
6767
step : IO Bool
6868
bindText : UInt32 → String → IO Unit
6969
bindInt : UInt32 → Int32 → IO Unit
70+
bindInt64 : UInt32 → Int64 → IO Unit
71+
bindDouble : UInt32 → Float → IO Unit
7072
reset : IO Unit
7173
columnsCount : IO UInt32
7274
columnText : UInt32 → IO String
7375
columnInt : UInt32 → IO Int32
76+
columnInt64 : UInt32 → IO Int64
77+
columnDouble : UInt32 → IO Float
7478
cursorExplain : UInt32 → IO Int
7579

7680
structure Connection where
@@ -144,10 +148,14 @@ private def sqlitePrepareWrap (conn : RawConn) (query : String) : IO (Except Str
144148
step := cursorStep c,
145149
bindText := cursorBindText c,
146150
bindInt := cursorBindInt c,
151+
bindInt64 := cursorBindInt64 c,
152+
bindDouble := cursorBindDouble c,
147153
reset := cursorReset c,
148154
columnsCount := cursorColumnsCount c,
149155
columnText := cursorColumnText c,
150156
columnInt := cursorColumnInt c,
157+
columnInt64 := cursorColumnInt64 c,
158+
columnDouble := cursorColumnDouble c,
151159
cursorExplain := cursorExplain c, }
152160
| Except.error e => Except.error e
153161

Tests/SQLite.lean

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ structure TestContext where
1717
def setup (s : String) : IO TestContext := do
1818
let flags := SQLITE_OPEN_READWRITE ||| SQLITE_OPEN_CREATE
1919
let conn ← connect s flags
20-
match ← conn.prepare "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT NOT NULL);" with
20+
match ← conn.prepare "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, height REAL) STRICT;" with
2121
| Except.ok cursor => cursor.step
2222
| Except.error _ => pure false
23-
match ← conn.prepare "INSERT INTO users (id, name) VALUES (1, 'John Doe');" with
23+
match ← conn.prepare "INSERT INTO users (id, name, height) VALUES (1, 'John Doe', 2.3);" with
2424
| Except.ok cursor => cursor.step
2525
| Except.error _ => pure false
2626
return ⟨conn⟩
@@ -43,41 +43,57 @@ def withTest (test : TestContext → IO Bool) : IO Bool := do
4343
cleanup ctx
4444
return false
4545

46-
def testInsertData (ctx : TestContext) : IO Bool := do
47-
match ← ctx.conn.prepare "INSERT INTO users (id, name) VALUES (?, ?);" with
48-
| Except.ok cursor =>
49-
cursor.bindInt 1 2
50-
cursor.bindText 2 "Jane Doe"
51-
let _ ← cursor.step -- This always returns false
52-
return true
53-
| Except.error _ => return false
54-
5546
def testSelectData (ctx : TestContext) : IO Bool := do
5647
match ← ctx.conn.prepare "SELECT * FROM users WHERE id = 1;" with
5748
| Except.ok cursor =>
5849
let hasRow ← cursor.step
5950
if hasRow then
6051
let id ← cursor.columnInt 0
6152
let name ← cursor.columnText 1
62-
return (id = 1 && name == "John Doe")
53+
let height ← cursor.columnDouble 2
54+
return id == 1 && name == "John Doe" && height == 2.3
55+
else
56+
return false
57+
| Except.error err => throw <| .userError err
58+
59+
def testInsertData (ctx : TestContext) : IO Bool := do
60+
let id := -2 ^ 63 |>.toInt64
61+
let name := "Jane Doe"
62+
let height := 20.25
63+
match ← ctx.conn.prepare "INSERT INTO users (id, name, height) VALUES (?, ?, ?);" with
64+
| Except.ok cursor =>
65+
cursor.bindInt64 1 id
66+
cursor.bindText 2 name
67+
cursor.bindDouble 3 height
68+
let _ ← cursor.step -- This always returns false
69+
| Except.error err => throw <| .userError err
70+
match ← ctx.conn.prepare "SELECT * FROM users WHERE id = ?;" with
71+
| Except.ok cursor =>
72+
cursor.bindInt64 1 id
73+
let hasRow ← cursor.step
74+
if hasRow then
75+
let id' ← cursor.columnInt64 0
76+
let name' ← cursor.columnText 1
77+
let height' ← cursor.columnDouble 2
78+
return id == id' && name == name' && height == height'
6379
else
6480
return false
65-
| Except.error _ => return false
81+
| Except.error err => throw <| .userError err
6682

6783
def testParameterBinding (ctx : TestContext) : IO Bool := do
68-
match ← ctx.conn.prepare "SELECT * FROM users WHERE id = ? AND name = ?;" with
84+
match ← ctx.conn.prepare "SELECT * FROM users WHERE id > ? AND name = ?;" with
6985
| Except.ok cursor =>
70-
cursor.bindInt 1 1
86+
cursor.bindInt 1 0
7187
cursor.bindText 2 "John Doe"
7288
return true
73-
| Except.error _ => return false
89+
| Except.error err => throw <| .userError err
7490

7591
def testColumnCount (ctx : TestContext) : IO Bool := do
7692
match ← ctx.conn.prepare "SELECT * FROM users;" with
7793
| Except.ok cursor =>
7894
let count ← cursor.columnsCount
79-
return count = 2
80-
| Except.error _ => return false
95+
return count == 3
96+
| Except.error err => throw <| .userError err
8197

8298
def testInvalidSyntax (ctx : TestContext) : IO Bool :=
8399
return match ← ctx.conn.prepare "INVALID SQL QUERY;" with
@@ -91,8 +107,8 @@ def testNonExistentTable (ctx : TestContext) : IO Bool :=
91107

92108
def main (args : List String) := do
93109
lspecIO (.ofList [("test suite", [
94-
test "can insert data" (← withTest testInsertData),
95110
test "can select data" (← withTest testSelectData),
111+
test "can insert data" (← withTest testInsertData),
96112
test "can bind parameters" (← withTest testParameterBinding),
97113
test "can get column count" (← withTest testColumnCount),
98114
test "handles invalid SQL syntax" (← withTest testInvalidSyntax),

lakefile.lean

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,13 @@ extern_lib libsqlite pkg := do
3232
lean_exe sqlite where
3333
root := `Main
3434
moreLinkObjs := #[libsqlite]
35-
moreLinkArgs := #["-Wl,--unresolved-symbols=ignore-all"] -- TODO: Very gross hack
35+
moreLinkArgs := if !Platform.isWindows then #["-Wl,--unresolved-symbols=ignore-all"] else #[] -- TODO: Very gross hack
3636

3737
@[test_driver]
3838
lean_exe Tests.SQLite where
39+
buildType := .debug
3940
moreLinkObjs := #[libsqlite]
40-
moreLinkArgs := #["-Wl,--unresolved-symbols=ignore-all"] -- Same as above
41+
moreLinkArgs := if !Platform.isWindows then #["-Wl,--unresolved-symbols=ignore-all"] else #[] -- Same as above
4142

4243
require LSpec from git
4344
"https://github.com/argumentcomputer/lspec/" @ "1fc461a9b83eeb68da34df72cec2ef1994e906cb"

lean-toolchain

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
leanprover/lean4:4.24.0
1+
leanprover/lean4:v4.24.0

native/sqliteffi.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@ lean_obj_res lean_sqlite_cursor_column_int(b_lean_obj_arg cursor_box, uint32_t c
154154

155155
const int32_t value = sqlite3_column_int(cursor, col);
156156

157-
/* TODO: int32's do not need to be boxe */
158157
return lean_io_result_mk_ok(lean_box(value));
159158
}
160159

@@ -163,15 +162,17 @@ lean_obj_res lean_sqlite_cursor_column_int64(b_lean_obj_arg cursor_box, uint32_t
163162

164163
const int64_t value = sqlite3_column_int64(cursor, col);
165164

166-
return lean_io_result_mk_ok(lean_box(value));
165+
// There's no lean_box_int64 but this seems to work
166+
// https://github.com/leanprover/lean4/issues/10561
167+
return lean_io_result_mk_ok(lean_box_uint64(value));
167168
}
168169

169170
lean_obj_res lean_sqlite_cursor_column_double(b_lean_obj_arg cursor_box, uint32_t col) {
170171
sqlite3_stmt* cursor = unbox_cursor(cursor_box);
171172

172173
const double value = sqlite3_column_double(cursor, col);
173174

174-
return lean_io_result_mk_ok(lean_box(value));
175+
return lean_io_result_mk_ok(lean_box_float(value));
175176
}
176177

177178
lean_obj_res lean_sqlite_cursor_step(b_lean_obj_arg cursor_box) {

0 commit comments

Comments
 (0)