2019-10-27 21:32:15 +01:00
|
|
|
module sqlite
|
|
|
|
|
|
|
|
#flag -lsqlite3
|
2019-10-29 15:13:56 +01:00
|
|
|
#flag freebsd -I/usr/local/include
|
2019-12-15 04:18:14 +01:00
|
|
|
#flag freebsd -Wl -L/usr/local/lib -lsqlite3
|
2020-06-21 23:09:17 +02:00
|
|
|
//#flag linux -I @VROOT/thirdparty/sqlite
|
|
|
|
//#flag @VROOT/thirdparty/sqlite/sqlite.c
|
|
|
|
|
|
|
|
|
2019-10-27 21:32:15 +01:00
|
|
|
#include "sqlite3.h"
|
|
|
|
|
2020-02-02 02:56:09 +01:00
|
|
|
struct C.sqlite3 {}
|
|
|
|
struct C.sqlite3_stmt {}
|
2019-10-27 21:32:15 +01:00
|
|
|
|
2020-01-16 18:41:34 +01:00
|
|
|
pub struct DB {
|
2019-10-27 21:32:15 +01:00
|
|
|
mut:
|
|
|
|
conn &C.sqlite3
|
|
|
|
}
|
|
|
|
|
2020-01-16 18:41:34 +01:00
|
|
|
pub struct Row {
|
2019-10-27 21:32:15 +01:00
|
|
|
pub mut:
|
|
|
|
vals []string
|
|
|
|
}
|
|
|
|
|
2020-02-02 02:56:09 +01:00
|
|
|
fn C.sqlite3_column_text(voidptr, int) byteptr
|
|
|
|
fn C.sqlite3_column_int(voidptr, int) int
|
|
|
|
fn C.sqlite3_open()
|
|
|
|
fn C.sqlite3_step() int
|
|
|
|
fn C.sqlite3_prepare_v2()
|
|
|
|
fn C.sqlite3_finalize()
|
|
|
|
fn C.sqlite3_column_count(voidptr) int
|
|
|
|
|
|
|
|
// Opens the connection with a database.
|
2020-06-16 12:14:22 +02:00
|
|
|
pub fn connect(path string) ?DB {
|
2019-12-04 11:08:28 +01:00
|
|
|
db := &C.sqlite3(0)
|
2020-06-16 12:14:22 +02:00
|
|
|
if C.sqlite3_open(path.str, &db) != 0 {
|
|
|
|
return error('sqlite db error')
|
|
|
|
}
|
2020-02-02 02:56:09 +01:00
|
|
|
return DB{
|
|
|
|
conn: db
|
|
|
|
}
|
2019-10-27 21:32:15 +01:00
|
|
|
}
|
|
|
|
|
2020-06-17 00:59:33 +02:00
|
|
|
// Only for V ORM
|
|
|
|
fn (db DB) init_stmt(query string) &C.sqlite3_stmt {
|
|
|
|
stmt := &C.sqlite3_stmt(0)
|
|
|
|
C.sqlite3_prepare_v2(db.conn, query.str, -1, &stmt, 0)
|
|
|
|
return stmt
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only for V ORM
|
|
|
|
fn get_int_from_stmt(stmt &C.sqlite3_stmt) int {
|
|
|
|
C.sqlite3_step(stmt)
|
|
|
|
res := C.sqlite3_column_int(stmt, 0)
|
|
|
|
C.sqlite3_finalize(stmt)
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
2020-02-02 02:56:09 +01:00
|
|
|
// Returns a single cell with value int.
|
2019-10-27 21:32:15 +01:00
|
|
|
pub fn (db DB) q_int(query string) int {
|
2019-12-04 11:08:28 +01:00
|
|
|
stmt := &C.sqlite3_stmt(0)
|
2020-02-02 02:56:09 +01:00
|
|
|
C.sqlite3_prepare_v2(db.conn, query.str, -1, &stmt, 0)
|
2019-10-27 21:32:15 +01:00
|
|
|
C.sqlite3_step(stmt)
|
|
|
|
res := C.sqlite3_column_int(stmt, 0)
|
|
|
|
C.sqlite3_finalize(stmt)
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
2020-02-02 02:56:09 +01:00
|
|
|
// Returns a single cell with value string.
|
2019-10-27 21:32:15 +01:00
|
|
|
pub fn (db DB) q_string(query string) string {
|
2019-12-04 11:08:28 +01:00
|
|
|
stmt := &C.sqlite3_stmt(0)
|
2020-02-02 02:56:09 +01:00
|
|
|
C.sqlite3_prepare_v2(db.conn, query.str, -1, &stmt, 0)
|
2019-10-27 21:32:15 +01:00
|
|
|
C.sqlite3_step(stmt)
|
|
|
|
res := tos_clone(C.sqlite3_column_text(stmt, 0))
|
|
|
|
C.sqlite3_finalize(stmt)
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-02 02:56:09 +01:00
|
|
|
// Execute the query on db, return an array of all the results, alongside any result code.
|
|
|
|
// Result codes: https://www.sqlite.org/rescode.html
|
|
|
|
pub fn (db DB) exec(query string) ([]Row,int) {
|
2019-12-04 11:08:28 +01:00
|
|
|
stmt := &C.sqlite3_stmt(0)
|
2020-02-02 02:56:09 +01:00
|
|
|
C.sqlite3_prepare_v2(db.conn, query.str, -1, &stmt, 0)
|
2019-10-27 21:32:15 +01:00
|
|
|
nr_cols := C.sqlite3_column_count(stmt)
|
2020-02-02 02:56:09 +01:00
|
|
|
mut res := 0
|
2020-04-26 16:25:54 +02:00
|
|
|
mut rows := []Row{}
|
2019-10-27 21:32:15 +01:00
|
|
|
for {
|
2020-02-02 02:56:09 +01:00
|
|
|
res = C.sqlite3_step(stmt)
|
2020-04-26 16:25:54 +02:00
|
|
|
// Result Code SQLITE_ROW; Another row is available
|
2020-02-02 02:56:09 +01:00
|
|
|
if res != 100 {
|
2019-10-27 21:32:15 +01:00
|
|
|
break
|
2019-12-04 11:08:28 +01:00
|
|
|
}
|
2019-10-27 21:32:15 +01:00
|
|
|
mut row := Row{}
|
2020-02-02 02:56:09 +01:00
|
|
|
for i in 0 .. nr_cols {
|
2019-10-27 21:32:15 +01:00
|
|
|
val := tos_clone(C.sqlite3_column_text(stmt, i))
|
|
|
|
row.vals << val
|
|
|
|
}
|
|
|
|
rows << row
|
|
|
|
}
|
2020-02-02 02:56:09 +01:00
|
|
|
return rows,res
|
2019-10-27 21:32:15 +01:00
|
|
|
}
|
|
|
|
|
2020-02-02 02:56:09 +01:00
|
|
|
// Execute a query, handle error code
|
|
|
|
// Return the first row from the resulting table
|
2019-10-27 21:32:15 +01:00
|
|
|
pub fn (db DB) exec_one(query string) ?Row {
|
2020-02-02 02:56:09 +01:00
|
|
|
rows,code := db.exec(query)
|
|
|
|
if rows.len == 0 || code != 101 {
|
|
|
|
return error('SQL Error: Rows #$rows.len Return code $code')
|
|
|
|
}
|
2019-10-27 21:32:15 +01:00
|
|
|
return rows[0]
|
|
|
|
}
|
|
|
|
|
2020-02-02 02:56:09 +01:00
|
|
|
// In case you don't expect any result, but still want an error code
|
|
|
|
// e.g. INSERT INTO ... VALUES (...)
|
|
|
|
pub fn (db DB) exec_none(query string) int {
|
|
|
|
_,code := db.exec(query)
|
|
|
|
return code
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO
|
2019-10-27 21:32:15 +01:00
|
|
|
pub fn (db DB) exec_param(query string, param string) []Row {
|
|
|
|
}
|
|
|
|
*/
|
2020-06-17 20:18:48 +02:00
|
|
|
|
|
|
|
pub fn (db DB) insert<T>(x T) {
|
|
|
|
}
|
|
|
|
|