Skip to content

Commit

Permalink
refactor: single-statement execs
Browse files Browse the repository at this point in the history
Redka aims to support both mattn and modernc SQLite drivers,
but they are incompatible in how they handle parameters in
multi-statement Exec calls.

Creating two separate Exec strategies seems premature at this
point, so I refactored all Exec queries back to single statements
and changed all params to positional. This way, both mattn and
modernc drivers work fine.
  • Loading branch information
nalgeon committed Apr 30, 2024
1 parent bd8208b commit f9f11bd
Show file tree
Hide file tree
Showing 13 changed files with 340 additions and 263 deletions.
55 changes: 27 additions & 28 deletions internal/rhash/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,71 +12,72 @@ const (
sqlCount = `
select count(field)
from rhash
join rkey on key_id = rkey.id and (etime is null or etime > :now)
where key = :key and field in (:fields)`
join rkey on key_id = rkey.id and (etime is null or etime > ?)
where key = ? and field in (:fields)`

sqlDelete = `
delete from rhash
where key_id = (
select id from rkey where key = :key
and (etime is null or etime > :now)
select id from rkey where key = ?
and (etime is null or etime > ?)
) and field in (:fields)`

sqlFields = `
select field
from rhash
join rkey on key_id = rkey.id and (etime is null or etime > :now)
where key = :key`
join rkey on key_id = rkey.id and (etime is null or etime > ?)
where key = ?`

sqlGet = `
select value
from rhash
join rkey on key_id = rkey.id and (etime is null or etime > :now)
where key = :key and field = :field`
join rkey on key_id = rkey.id and (etime is null or etime > ?)
where key = ? and field = ?`

sqlGetMany = `
select field, value
from rhash
join rkey on key_id = rkey.id and (etime is null or etime > :now)
where key = :key and field in (:fields)`
join rkey on key_id = rkey.id and (etime is null or etime > ?)
where key = ? and field in (:fields)`

sqlItems = `
select field, value
from rhash
join rkey on key_id = rkey.id and (etime is null or etime > :now)
where key = :key`
join rkey on key_id = rkey.id and (etime is null or etime > ?)
where key = ?`

sqlLen = `
select count(field)
from rhash
join rkey on key_id = rkey.id and (etime is null or etime > :now)
where key = :key`
join rkey on key_id = rkey.id and (etime is null or etime > ?)
where key = ?`

sqlScan = `
select rhash.rowid, field, value
from rhash
join rkey on key_id = rkey.id and (etime is null or etime > :now)
where key = :key and rhash.rowid > :cursor and field glob :pattern
limit :count`
join rkey on key_id = rkey.id and (etime is null or etime > ?)
where key = ? and rhash.rowid > ? and field glob ?
limit ?`

sqlSet = `
sqlSet1 = `
insert into rkey (key, type, version, mtime)
values (:key, :type, :version, :mtime)
values (?, ?, ?, ?)
on conflict (key) do update set
version = version+1,
type = excluded.type,
mtime = excluded.mtime;
mtime = excluded.mtime`

sqlSet2 = `
insert into rhash (key_id, field, value)
values ((select id from rkey where key = :key), :field, :value)
values ((select id from rkey where key = ?), ?, ?)
on conflict (key_id, field) do update
set value = excluded.value;`

sqlValues = `
select value
from rhash
join rkey on key_id = rkey.id and (etime is null or etime > :now)
where key = :key`
join rkey on key_id = rkey.id and (etime is null or etime > ?)
where key = ?`
)

const scanPageSize = 10
Expand Down Expand Up @@ -443,19 +444,17 @@ func (tx *Tx) count(key string, fields ...string) (int, error) {
// set creates or updates the value of a field in a hash.
func (tx *Tx) set(key string, field string, value any) error {
args := []any{
// insert into rkey
key, // key
core.TypeHash, // type
core.InitialVersion, // version
time.Now().UnixMilli(), // mtime
// insert into rhash
key, field, value,
}
_, err := tx.tx.Exec(sqlSet, args...)
_, err := tx.tx.Exec(sqlSet1, args...)
if err != nil {
return err
}
return nil
_, err = tx.tx.Exec(sqlSet2, key, field, value)
return err
}

// scanValue scans a hash field value the current row.
Expand Down
36 changes: 18 additions & 18 deletions internal/rkey/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import (
const (
sqlCount = `
select count(id) from rkey
where key in (:keys) and (etime is null or etime > :now)`
where key in (:keys) and (etime is null or etime > ?)`

sqlDelete = `
delete from rkey where key in (:keys)
and (etime is null or etime > :now)`
and (etime is null or etime > ?)`

sqlDeleteAll = `
delete from rkey;
Expand All @@ -24,59 +24,59 @@ const (

sqlDeleteAllExpired = `
delete from rkey
where etime <= :now`
where etime <= ?`

sqlDeleteNExpired = `
delete from rkey
where rowid in (
select rowid from rkey
where etime <= :now
limit :n
where etime <= ?
limit ?
)`

sqlExpire = `
update rkey set etime = :at
where key = :key and (etime is null or etime > :now)`
update rkey set etime = ?
where key = ? and (etime is null or etime > ?)`

sqlGet = `
select id, key, type, version, etime, mtime
from rkey
where key = :key and (etime is null or etime > :now)`
where key = ? and (etime is null or etime > ?)`

sqlKeys = `
select id, key, type, version, etime, mtime from rkey
where key glob :pattern and (etime is null or etime > :now)`
where key glob ? and (etime is null or etime > ?)`

sqlPersist = `
update rkey set etime = null
where key = :key and (etime is null or etime > :now)`
where key = ? and (etime is null or etime > ?)`

sqlRandom = `
select id, key, type, version, etime, mtime from rkey
where etime is null or etime > :now
where etime is null or etime > ?
order by random() limit 1`

sqlRename = `
update or replace rkey set
id = old.id,
key = :new_key,
key = ?,
type = old.type,
version = old.version+1,
etime = old.etime,
mtime = :now
mtime = ?
from (
select id, key, type, version, etime, mtime
from rkey
where key = :key and (etime is null or etime > :now)
where key = ? and (etime is null or etime > ?)
) as old
where rkey.key = :key and (
rkey.etime is null or rkey.etime > :now
where rkey.key = ? and (
rkey.etime is null or rkey.etime > ?
)`

sqlScan = `
select id, key, type, version, etime, mtime from rkey
where id > :cursor and key glob :pattern and (etime is null or etime > :now)
limit :count`
where id > ? and key glob ? and (etime is null or etime > ?)
limit ?`
)

const scanPageSize = 10
Expand Down

0 comments on commit f9f11bd

Please sign in to comment.