Class: Fresco::Db::SQLite

Inherits:
Object
  • Object
show all
Defined in:
lib/fresco/runtime/db_sqlite.rb

Overview

Thin Ruby cover over the Sqlite FFI module. Methods return values straight from the C side — handle ids as Int, cursor ids as Int, status codes as Int (0 success, -1 error), column values as Str or Int. No exceptions on DB errors; callers branch on ‘< 0`.

Spinel-shape constraints worth flagging up front:

- Attribute is named `dbh` (not `handle`) — the latter widens
  poly-dispatch return types across classes that also define
  `handle` (see Tep's same workaround). Keeps every method
  name on this class collision-free across the framework.
- `cursor_id` is returned by #prepare and threaded through
  #step/#bind_*/#col_*/#finalize/#reset. The single-cursor
  pattern works too — just call them with one cursor id at a
  time — but the API allows several open at once (M3+ codegen
  stacks finders inside each other).
- Defaults on every typed parameter pin Spinel's analyzer to
  the right slot type — same rule as Params/Response in this
  file. Required-but-defaultless params collapse to mrb_int
  under Spinel (see [[spinel_initialize_kwargs]]).

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSQLite

Returns a new instance of SQLite.



59
60
61
# File 'lib/fresco/runtime/db_sqlite.rb', line 59

def initialize
  @dbh = -1
end

Instance Attribute Details

#dbhObject

Returns the value of attribute dbh.



57
58
59
# File 'lib/fresco/runtime/db_sqlite.rb', line 57

def dbh
  @dbh
end

Instance Method Details

#bind_int(cid = 0, idx = 0, value = 0) ⇒ Object



103
104
105
# File 'lib/fresco/runtime/db_sqlite.rb', line 103

def bind_int(cid = 0, idx = 0, value = 0)
  Sqlite.fresco_sqlite_bind_int(cid, idx, value)
end

#bind_str(cid = 0, idx = 0, value = "") ⇒ Object



99
100
101
# File 'lib/fresco/runtime/db_sqlite.rb', line 99

def bind_str(cid = 0, idx = 0, value = "")
  Sqlite.fresco_sqlite_bind_str(cid, idx, value)
end

#closeObject



74
75
76
77
78
79
80
# File 'lib/fresco/runtime/db_sqlite.rb', line 74

def close
  if @dbh >= 0
    Sqlite.fresco_sqlite_close(@dbh)
    @dbh = -1
  end
  0
end

#col_count(cid = 0) ⇒ Object



111
# File 'lib/fresco/runtime/db_sqlite.rb', line 111

def col_count(cid = 0);        Sqlite.fresco_sqlite_col_count(cid);       end

#col_int(cid = 0, idx = 0) ⇒ Object



110
# File 'lib/fresco/runtime/db_sqlite.rb', line 110

def col_int(cid = 0, idx = 0); Sqlite.fresco_sqlite_col_int(cid, idx);    end

#col_str(cid = 0, idx = 0) ⇒ Object



109
# File 'lib/fresco/runtime/db_sqlite.rb', line 109

def col_str(cid = 0, idx = 0); Sqlite.fresco_sqlite_col_str(cid, idx);    end

#exec(sql = "") ⇒ Object

Run a no-bind statement (DDL, BEGIN/COMMIT, queries with literal constants). Returns true on success. For any user-supplied value always use prepare + bind + step + finalize.



85
86
87
88
# File 'lib/fresco/runtime/db_sqlite.rb', line 85

def exec(sql = "")
  return false if @dbh < 0
  Sqlite.fresco_sqlite_exec(@dbh, sql) == 0
end

#finalize(cid = 0) ⇒ Object



112
# File 'lib/fresco/runtime/db_sqlite.rb', line 112

def finalize(cid = 0);         Sqlite.fresco_sqlite_finalize(cid);        end

#first_int(sql = "", p1 = "") ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/fresco/runtime/db_sqlite.rb', line 139

def first_int(sql = "", p1 = "")
  return 0 if @dbh < 0
  cid = Sqlite.fresco_sqlite_prepare(@dbh, sql)
  return 0 if cid < 0
  if p1.length > 0
    Sqlite.fresco_sqlite_bind_str(cid, 1, p1)
  end
  result = 0
  if Sqlite.fresco_sqlite_step(cid) == 1
    result = Sqlite.fresco_sqlite_col_int(cid, 0)
  end
  Sqlite.fresco_sqlite_finalize(cid)
  result
end

#first_str(sql = "", p1 = "") ⇒ Object

Convenience: prepare a single-row single-column query with at most one Str bind, step once, return col 0 as Str, finalize. Pass ‘“”` for no bind. Mirrors Tep::SQLite#first_str so M1 smoke tests stay terse.



124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/fresco/runtime/db_sqlite.rb', line 124

def first_str(sql = "", p1 = "")
  return "" if @dbh < 0
  cid = Sqlite.fresco_sqlite_prepare(@dbh, sql)
  return "" if cid < 0
  if p1.length > 0
    Sqlite.fresco_sqlite_bind_str(cid, 1, p1)
  end
  result = ""
  if Sqlite.fresco_sqlite_step(cid) == 1
    result = Sqlite.fresco_sqlite_col_str(cid, 0)
  end
  Sqlite.fresco_sqlite_finalize(cid)
  result
end

#last_rowidObject



115
116
117
118
# File 'lib/fresco/runtime/db_sqlite.rb', line 115

def last_rowid
  return -1 if @dbh < 0
  Sqlite.fresco_sqlite_last_insert_rowid(@dbh)
end

#open(path = "") ⇒ Object

Returns true on success, false on failure. Path may be a real file or ‘:memory:` for an anonymous in-memory database. Calling #open twice on the same instance leaks the prior handle — close first.



67
68
69
70
71
72
# File 'lib/fresco/runtime/db_sqlite.rb', line 67

def open(path = "")
  h = Sqlite.fresco_sqlite_open(path)
  return false if h < 0
  @dbh = h
  true
end

#prepare(sql = "") ⇒ Object

Open a cursor on a parameterised statement. Returns an Int cursor id (>= 1) on success, -1 on failure. Subsequent bind_str/ bind_int/step/col_str/col_int/col_count/finalize/reset calls take this id as their first argument. Always pair with #finalize.



94
95
96
97
# File 'lib/fresco/runtime/db_sqlite.rb', line 94

def prepare(sql = "")
  return -1 if @dbh < 0
  Sqlite.fresco_sqlite_prepare(@dbh, sql)
end

#reset(cid = 0) ⇒ Object



113
# File 'lib/fresco/runtime/db_sqlite.rb', line 113

def reset(cid = 0);            Sqlite.fresco_sqlite_reset(cid);           end

#step(cid = 0) ⇒ Object

1 -> row available, 0 -> done, -1 -> error or invalid cursor.



108
# File 'lib/fresco/runtime/db_sqlite.rb', line 108

def step(cid = 0);             Sqlite.fresco_sqlite_step(cid);            end