Commit ad2ba598 authored by Aurélien Campéas's avatar Aurélien Campéas
Browse files

util: also provide a `sqlq` utility to forge sql queries

It will help to seamlessly assemble queries out of
* plain string
* query parameters
* pre-built `sqlp` string + parameters elements
parent 9c5c707d43e6
......@@ -10,6 +10,7 @@ from tshistory.util import (
SeriesServices,
sqlfile,
sqlp,
sqlq
)
SCHEMA = Path(__file__).parent / 'snapshot.sql'
......@@ -211,33 +212,29 @@ class Snapshot(SeriesServices):
def cset_heads_query(self, csetfilter=(), order='desc'):
tablename = self.tsh._serie_to_tablename(self.cn, self.seriename)
sql = [
q = sqlq(
'select ts.cset, ts.snapshot '
f'from "{self.tsh.namespace}.timeserie"."{tablename}" as ts, '
f' "{self.tsh.namespace}".changeset as cset'
' where cset.id = ts.cset '
]
params = {}
' where cset.id = ts.cset'
)
if csetfilter:
sql.append('and ts.cset <= cset.id ')
q.append('and ts.cset <= cset.id')
for filtercb in csetfilter:
sql.append('and ' + filtercb.sql)
params.update(filtercb.kw)
q.append('and ', filtercb)
sql.append(f'order by ts.id {order} ')
return sql, params
q.append(f'order by ts.id {order}')
return q
def find(self, csetfilter=(),
from_value_date=None, to_value_date=None):
sql, params = self.cset_heads_query(csetfilter)
sql.append('limit 1')
sql = ''.join(sql)
q = self.cset_heads_query(csetfilter)
q.append('limit 1')
try:
csid, cid = self.cn.execute(sql, **params).fetchone()
csid, cid = q.do(self.cn).fetchone()
except TypeError:
# this happens *only* because of the from/to restriction
return None, None
......@@ -265,18 +262,17 @@ class Snapshot(SeriesServices):
csets = [rev for rev, _ in revs if rev is not None]
# csid -> heads
sql, params = self.cset_heads_query(
q = self.cset_heads_query(
(
sqlp('cset.id >= %(mincset)s', mincset=min(csets)),
sqlp('cset.id <= %(maxcset)s', maxcset=max(csets))
),
order='asc'
)
sql = ''.join(sql)
cset_snap_map = {
row.cset: row.snapshot
for row in self.cn.execute(sql, **params).fetchall()
for row in q.do(self.cn).fetchall()
}
rawchunks = self.allchunks(
sorted(cset_snap_map.values()),
......
......@@ -22,13 +22,40 @@ def sqlfile(path, **kw):
class sqlp:
"""utility to carry an sql fragment plus the potenially needed
parameters
"""
__slots__ = ('sql', 'kw')
def __init__(self, sql, **kw):
self.sql = f'{sql.strip()} '
self.sql = sql
self.kw = kw
class sqlq:
"""utility to incremntally build an sql query string along with its
parameters
"""
__slots__ = ('sql', 'kw')
def __init__(self, sql, **kw):
self.sql = [sql]
self.kw = kw
def append(self, *sql, **kw):
self.kw.update(kw)
for block in sql:
if isinstance(block, sqlp):
self.kw.update(block.kw)
block = block.sql
self.sql.append(block)
def do(self, cn):
return cn.execute(
' '.join(self.sql), **self.kw
)
@contextmanager
def tempdir(suffix='', prefix='tmp'):
tmp = tempfile.mkdtemp(suffix=suffix, prefix=prefix)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment