add more methods for statements
This commit is contained in:
1 parent
cf9af57161
commit
dfb8a5b738
3 files changed
+125
-18
No files matched your search
+40
-9
@@ -2,9 +2,9 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import "src" expose sqlite, sql
|
||||
import "src" expose Sqlite, sql
|
||||
|
||||
let db = sqlite("test.db")
|
||||
let db = Sqlite("test.db")
|
||||
|
||||
# Create table if it doesn't exist
|
||||
|
||||
@@ -25,13 +25,14 @@ let some_email = "william@wbell.dev"
|
||||
let some_phone = "573403287534893278537592387958723"
|
||||
|
||||
# Insert rows
|
||||
db.execute(sql`BEGIN TRANSACTION;`)
|
||||
for (i in 0 until 1e2) do
|
||||
db.execute(sql`
|
||||
INSERT INTO contacts (first_name, last_name, email, phone)
|
||||
VALUES ($(some_first_name), $(some_last_name), $(some_email), $(i))
|
||||
`)
|
||||
db.execute(sql`COMMIT;`)
|
||||
# db.execute(sql`BEGIN TRANSACTION;`)
|
||||
# for (i in 0 until 1e2) do
|
||||
# db.execute(sql`
|
||||
# INSERT INTO contacts (first_name, last_name, email, phone)
|
||||
# VALUES ($(some_first_name), $(some_last_name), $(some_email), $(i))
|
||||
# `)
|
||||
# db.execute(sql`COMMIT;`)
|
||||
|
||||
|
||||
for (row in db.execute(sql`
|
||||
SELECT *
|
||||
@@ -40,4 +41,34 @@ for (row in db.execute(sql`
|
||||
`)) do
|
||||
term.log(row)
|
||||
|
||||
term.log(db.execute(sql`
|
||||
SELECT *
|
||||
FROM contacts
|
||||
WHERE email=$(some_email)
|
||||
`).many())
|
||||
term.log(db.execute(sql`
|
||||
SELECT *
|
||||
FROM contacts
|
||||
WHERE email=$(some_email)
|
||||
`))
|
||||
term.log(db.execute(sql`
|
||||
SELECT *
|
||||
FROM contacts
|
||||
WHERE email=$(some_email)
|
||||
`).one())
|
||||
term.log(db.execute(sql`
|
||||
SELECT *
|
||||
FROM contacts
|
||||
WHERE email=$(some_email)
|
||||
`).maybe_one())
|
||||
term.log(db.execute(sql`
|
||||
SELECT *
|
||||
FROM contacts
|
||||
WHERE email=$(some_email)
|
||||
`).one_first())
|
||||
term.log(db.execute(sql`
|
||||
SELECT *
|
||||
FROM contacts
|
||||
WHERE email=$(some_email)
|
||||
`).maybe_one_first())
|
||||
db.close()
|
||||
+26
-9
@@ -8,36 +8,53 @@ let __native__ = load_native_code(`$(program.file.directory)native/bin/$(platfor
|
||||
|
||||
class SqliteError(Exception) null
|
||||
|
||||
class execute do
|
||||
class Statement do
|
||||
this.__init__(self, db, stmt, values) = do
|
||||
self.__db__ = db
|
||||
self.__stmt__ = stmt
|
||||
__native__.execute_statement(db, stmt, values, SqliteError)
|
||||
this.__iter__(self) = self
|
||||
this.__next__(self) = __native__.statement_fetch(self.__db__, self.__stmt__, SqliteError)
|
||||
this.fetch_one(self) = do
|
||||
|
||||
this.one(self) = do
|
||||
try do
|
||||
return self.__next__()
|
||||
catch (StopIteration) do
|
||||
throw SqliteError("out of rows")
|
||||
this.fetch_many(self) = do
|
||||
let result = []
|
||||
for (row in self) do
|
||||
result.append(row)
|
||||
return result
|
||||
this.one_first(self) = do
|
||||
try do
|
||||
return __native__.statement_fetch_first(self.__db__, self.__stmt__, SqliteError)
|
||||
catch (StopIteration) do
|
||||
throw SqliteError("out of rows")
|
||||
|
||||
|
||||
class sqlite do
|
||||
this.maybe_one(self) = do
|
||||
try do
|
||||
return self.__next__()
|
||||
catch (StopIteration) do
|
||||
return null
|
||||
this.maybe_one_first(self) = do
|
||||
try do
|
||||
return __native__.statement_fetch_first(self.__db__, self.__stmt__, SqliteError)
|
||||
catch (StopIteration) do
|
||||
return null
|
||||
|
||||
|
||||
this.many(self) = array(self)
|
||||
|
||||
|
||||
class Sqlite do
|
||||
this.__init__(self, path) = do
|
||||
self.__stmt_cache__ = {}
|
||||
self.__db_path__ = path
|
||||
self.__db__ = __native__.connect_database(path, SqliteError)
|
||||
|
||||
this.execute(self, query) = do
|
||||
if (!is_instance(query, SQL_QUERY)) throw TypeError("expects an sql query object")
|
||||
let stmt
|
||||
if (query.__statement__ in self.__stmt_cache__) stmt = self.__stmt_cache__[query.__statement__]
|
||||
else self.__stmt_cache__[query.__statement__] = stmt = __native__.new_statement(self.__db__, query.__statement__, SqliteError)
|
||||
return execute(self.__db__, stmt, query.__values__)
|
||||
return Statement(self.__db__, stmt, query.__values__)
|
||||
|
||||
this.close(self) = do
|
||||
for (x in self.__stmt_cache__) do
|
||||
|
||||
@@ -290,6 +290,64 @@ ARGON_FUNCTION(statement_fetch, {
|
||||
}
|
||||
return api->throw_argon_signal(err, api->SignalStopIteration);
|
||||
})
|
||||
ARGON_FUNCTION(statement_fetch_first, {
|
||||
if (api->fix_to_arg_size(3, argc, err)) {
|
||||
return api->ARGON_NULL;
|
||||
}
|
||||
|
||||
struct buffer db_buffer = api->argon_buffer_to_buffer(argv[0], err);
|
||||
if (api->is_error(err))
|
||||
return api->ARGON_NULL;
|
||||
|
||||
struct buffer statment = api->argon_buffer_to_buffer(argv[1], err);
|
||||
if (api->is_error(err))
|
||||
return api->ARGON_NULL;
|
||||
sqlite3 **db = (sqlite3 **)db_buffer.data;
|
||||
sqlite3_stmt **stmt = (sqlite3_stmt **)statment.data;
|
||||
|
||||
int rc = sqlite3_step(*stmt);
|
||||
|
||||
if (rc == SQLITE_ROW) {
|
||||
int num_cols = sqlite3_column_count(*stmt);
|
||||
|
||||
if (num_cols) {
|
||||
int col_type = sqlite3_column_type(*stmt, 0);
|
||||
|
||||
switch (col_type) {
|
||||
case SQLITE_INTEGER:
|
||||
return api->i64_to_argon(sqlite3_column_int64(*stmt, 0));
|
||||
case SQLITE_FLOAT:
|
||||
return api->double_to_argon(sqlite3_column_double(*stmt, 0));
|
||||
case SQLITE_TEXT: {
|
||||
char *str = (char *)sqlite3_column_text(*stmt, 0);
|
||||
|
||||
return api->string_to_argon((struct string){str, strlen(str)});
|
||||
}
|
||||
case SQLITE_BLOB: {
|
||||
size_t size = sqlite3_column_bytes(*stmt, 0);
|
||||
ArgonObject *buffer_obj = api->create_argon_buffer(size);
|
||||
struct buffer buf = api->argon_buffer_to_buffer(buffer_obj, err);
|
||||
if (api->is_error(err))
|
||||
break;
|
||||
const void *blob_buf = sqlite3_column_blob(*stmt, 0);
|
||||
memcpy(buf.data, blob_buf, size);
|
||||
|
||||
return buffer_obj;
|
||||
}
|
||||
case SQLITE_NULL:
|
||||
return api->ARGON_NULL;
|
||||
default:
|
||||
return api->throw_argon_error(err, argv[2], "unknown type %d",
|
||||
col_type);
|
||||
}
|
||||
} else {
|
||||
return api->throw_argon_error(err, argv[2], "row has no columns");
|
||||
}
|
||||
} else if (rc != SQLITE_DONE) {
|
||||
return api->throw_argon_error(err, argv[2], "%s", sqlite3_errmsg(*db));
|
||||
}
|
||||
return api->throw_argon_signal(err, api->SignalStopIteration);
|
||||
})
|
||||
|
||||
INIT_ARGON_MODULE({
|
||||
REGISTER_ARGON_FUNCTION(connect_database);
|
||||
@@ -298,4 +356,5 @@ INIT_ARGON_MODULE({
|
||||
REGISTER_ARGON_FUNCTION(finalise_statement);
|
||||
REGISTER_ARGON_FUNCTION(execute_statement);
|
||||
REGISTER_ARGON_FUNCTION(statement_fetch);
|
||||
REGISTER_ARGON_FUNCTION(statement_fetch_first);
|
||||
})
|
||||
Reference in new issue
Block a user