sql-zig

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

sqlite.zig (3475B)


      1 const std = @import("std");
      2 const sqlite = @cImport({
      3     @cInclude("sqlite3.h");
      4 });
      5 const Db = @import("main.zig");
      6 const OpenError = Db.OpenError;
      7 const PrepareError = Db.PrepareError;
      8 const StepError = Db.StepError;
      9 const ColumnError = Db.ColumnError;
     10 const log = @import("log.zig").scoped_log_t(.sqlite);
     11 
     12 //// Sqlite implementation
     13 pub const Sqlite = @This();
     14 
     15 allocator: std.mem.Allocator,
     16 c_db: *sqlite.sqlite3,
     17 
     18 pub fn open(allocator: std.mem.Allocator, filename: [:0]const u8) OpenError!Db {
     19     var db: ?*sqlite.sqlite3 = null;
     20     const oo = sqlite.SQLITE_OPEN_CREATE | sqlite.SQLITE_OPEN_READWRITE | sqlite.SQLITE_OPEN_FULLMUTEX;
     21     if (sqlite.sqlite3_open_v2(filename.ptr, &db, oo, null) != sqlite.SQLITE_OK) {
     22         log.err("Sqlite#open: sqlite3_open_v2 error {s}", .{sqlite.sqlite3_errmsg(db)});
     23         return OpenError.Failed;
     24     }
     25     var sqlite_db = try allocator.create(Sqlite);
     26     sqlite_db.allocator = allocator;
     27     sqlite_db.c_db = db.?;
     28     return Db{
     29         .ptr = sqlite_db,
     30         .vtable = .{
     31             .prepare = prepare,
     32             .step = step,
     33             .column_i64 = column_i64,
     34             .column_slice_const_u8 = column_slice_const_u8,
     35             .close_stmt = close_stmt,
     36             .close_db = close_db,
     37         },
     38     };
     39 }
     40 
     41 fn prepare(db: *anyopaque, query: [:0]const u8) PrepareError!*anyopaque {
     42     var self: *Sqlite = @alignCast(@ptrCast(db));
     43     var sstmt: ?*sqlite.sqlite3_stmt = null;
     44     if (sqlite.sqlite3_prepare_v2(self.c_db, query.ptr, @intCast(query.len), &sstmt, null) != sqlite.SQLITE_OK) {
     45         log.err("Sqlite#prepare: sqlite3_prepare_v2: {s}", .{sqlite.sqlite3_errmsg(self.c_db)});
     46         return PrepareError.Failed;
     47     }
     48     return sstmt.?;
     49 }
     50 
     51 fn step(db: *anyopaque, stmt: *anyopaque) StepError!bool {
     52     var self: *Sqlite = @alignCast(@ptrCast(db));
     53     var sstmt: *sqlite.sqlite3_stmt = @alignCast(@ptrCast(stmt));
     54     const res = sqlite.sqlite3_step(sstmt);
     55     if (res == sqlite.SQLITE_ROW) {
     56         return true;
     57     } else if (res == sqlite.SQLITE_DONE) {
     58         return false;
     59     } else {
     60         log.err("Sqlite#step: sqlite3_step: {s}", .{sqlite.sqlite3_errmsg(self.c_db)});
     61         return StepError.Failed;
     62     }
     63 }
     64 
     65 fn column_i64(db: *anyopaque, stmt: *anyopaque, idx: u31) ColumnError!?i64 {
     66     _ = db;
     67     var sstmt: *sqlite.sqlite3_stmt = @alignCast(@ptrCast(stmt));
     68     const ct = sqlite.sqlite3_column_type(sstmt, idx);
     69     if (ct == sqlite.SQLITE_NULL) {
     70         return null;
     71     } else if (ct == sqlite.SQLITE_INTEGER) {
     72         return sqlite.sqlite3_column_int64(sstmt, idx);
     73     } else {
     74         return ColumnError.WrongType;
     75     }
     76 }
     77 fn column_slice_const_u8(db: *anyopaque, stmt: *anyopaque, idx: u31) ColumnError!?[:0]const u8 {
     78     _ = db;
     79     var sstmt: *sqlite.sqlite3_stmt = @alignCast(@ptrCast(stmt));
     80     const ct = sqlite.sqlite3_column_type(sstmt, idx);
     81     if (ct == sqlite.SQLITE_NULL) {
     82         return null;
     83     } else if (ct == sqlite.SQLITE_TEXT) {
     84         const value_c = sqlite.sqlite3_column_text(sstmt, idx);
     85         return std.mem.sliceTo(value_c, 0);
     86     } else {
     87         return ColumnError.WrongType;
     88     }
     89 }
     90 
     91 fn close_stmt(db: *anyopaque, stmt: *anyopaque) void {
     92     _ = db;
     93     var sstmt: *sqlite.sqlite3_stmt = @alignCast(@ptrCast(stmt));
     94     _ = sqlite.sqlite3_finalize(sstmt);
     95 }
     96 
     97 fn close_db(db: *anyopaque) void {
     98     var self: *Sqlite = @alignCast(@ptrCast(db));
     99     _ = sqlite.sqlite3_close_v2(self.c_db);
    100     self.allocator.destroy(self);
    101 }