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

schema: put everything into a default `tsh` namespace schema

Hence we have by default two namespaces:
* `tsh` (for the metadata and changesets)
* `tsh.timeserie` (for the series histories)

This opens the door for the coexistence of several distinct
timeseries histories sets.
parent 0c757ef03826
......@@ -28,10 +28,10 @@ def engine(request):
yield e
@pytest.fixture(params=[tsio.TimeSerie],
@pytest.fixture(params=['tsh'],
scope='session')
def tsh(request, engine):
tsh = request.param()
tsh = tsio.TimeSerie(request.param)
yield tsh
# build a ts using the logs from another
......
......@@ -238,35 +238,37 @@ def test_differential(engine, tsh):
2010-01-07 3.0
""", tsh.get(engine, 'ts_mixte'))
hist = pd.read_sql('select id, parent from timeserie.ts_test order by id',
engine)
assert_df("""
with engine.connect() as cn:
cn.execute('set search_path to "tsh.timeserie", tsh, public')
hist = pd.read_sql('select id, parent from ts_test order by id',
cn)
assert_df("""
id parent
0 1 NaN
1 2 1.0
2 3 2.0
""", hist)
hist = pd.read_sql('select id, parent from timeserie.ts_mixte order by id',
engine)
assert_df("""
hist = pd.read_sql('select id, parent from ts_mixte order by id',
cn)
assert_df("""
id parent
0 1 NaN
1 2 1.0
2 3 2.0
""", hist)
allts = pd.read_sql("select name, table_name from registry "
"where name in ('ts_test', 'ts_mixte')",
engine)
allts = pd.read_sql("select name, table_name from registry "
"where name in ('ts_test', 'ts_mixte')",
cn)
assert_df("""
name table_name
0 ts_test timeserie.ts_test
1 ts_mixte timeserie.ts_mixte
assert_df("""
name table_name
0 ts_test tsh.timeserie.ts_test
1 ts_mixte tsh.timeserie.ts_mixte
""", allts)
assert_df("""
assert_df("""
2010-01-01 2.0
2010-01-02 2.0
2010-01-03 2.0
......@@ -274,7 +276,7 @@ def test_differential(engine, tsh):
2010-01-05 2.0
2010-01-06 2.0
2010-01-07 3.0
""", tsh.get(engine, 'ts_mixte',
""", tsh.get(cn, 'ts_mixte',
revision_date=datetime.now()))
......@@ -392,9 +394,11 @@ def test_snapshots(engine, tsh):
diff = tsh.insert(engine, ts, 'growing', 'babar')
assert diff is None
df = pd.read_sql("select id from timeserie.growing where snapshot is not null",
engine)
assert_df("""
with engine.connect() as cn:
cn.execute('set search_path to "tsh.timeserie", tsh, public')
df = pd.read_sql("select id from growing where snapshot is not null",
cn)
assert_df("""
id
0 1
1 4
......@@ -402,8 +406,8 @@ def test_snapshots(engine, tsh):
3 10
""", df)
ts = tsh.get(engine, 'growing')
assert_df("""
ts = tsh.get(cn, 'growing')
assert_df("""
2015-01-01 1.0
2015-01-02 1.0
2015-01-03 1.0
......@@ -416,11 +420,11 @@ def test_snapshots(engine, tsh):
2015-01-10 1.0
""", ts)
df = pd.read_sql("select id, diff, snapshot from timeserie.growing order by id", engine)
for attr in ('diff', 'snapshot'):
df[attr] = df[attr].apply(lambda x: 0 if x is None else len(x))
df = pd.read_sql("select id, diff, snapshot from growing order by id", cn)
for attr in ('diff', 'snapshot'):
df[attr] = df[attr].apply(lambda x: 0 if x is None else len(x))
assert_df("""
assert_df("""
id diff snapshot
0 1 0 35
1 2 36 0
......@@ -889,7 +893,10 @@ def test_bigdata(engine, tracker, tsh):
t1 = time() - t0
tshclass = tsh.__class__.__name__
df = pd.read_sql("select id, diff, snapshot from timeserie.big order by id", engine)
with engine.connect() as cn:
cn.execute('set search_path to "tsh.timeserie"')
df = pd.read_sql('select id, diff, snapshot from big order by id', cn)
for attr in ('diff', 'snapshot'):
df[attr] = df[attr].apply(lambda x: 0 if x is None else len(x))
......@@ -916,8 +923,10 @@ def test_lots_of_diffs(engine, tracker, tsh):
t1 = time() - t0
tshclass = tsh.__class__.__name__
df = pd.read_sql("select id, diff, snapshot from timeserie.manydiffs order by id ",
engine)
with engine.connect() as cn:
cn.execute('set search_path to "tsh.timeserie"')
df = pd.read_sql("select id, diff, snapshot from manydiffs order by id ",
cn)
for attr in ('diff', 'snapshot'):
df[attr] = df[attr].apply(lambda x: 0 if x is None else len(x))
......
......@@ -5,14 +5,15 @@ from sqlalchemy.dialects.postgresql import JSONB
meta = MetaData()
def make_schema(meta):
def make_schema(meta, namespace='tsh'):
registry = Table(
'registry', meta,
Column('id', Integer, primary_key=True),
Column('name', String, index=True, nullable=False, unique=True),
Column('table_name', String, index=True, nullable=False, unique=True),
Column('metadata', JSONB(none_as_null=True))
Column('metadata', JSONB(none_as_null=True)),
schema=namespace
)
......@@ -21,36 +22,37 @@ def make_schema(meta):
Column('id', Integer, primary_key=True),
Column('author', String, index=True, nullable=False),
Column('insertion_date', DateTime, index=True, nullable=False),
Column('metadata', JSONB(none_as_null=True))
Column('metadata', JSONB(none_as_null=True)),
schema=namespace
)
changeset_series = Table(
'changeset_series', meta,
Column('csid', Integer, ForeignKey('changeset.id'),
Column('csid', Integer, ForeignKey('{}.changeset.id'.format(namespace)),
index=True, nullable=False),
Column('serie', String, ForeignKey('registry.name'),
Column('serie', String, ForeignKey('{}.registry.name'.format(namespace)),
index=True, nullable=False),
PrimaryKeyConstraint('csid', 'serie', name='changeset_series_pk'),
PrimaryKeyConstraint('csid', 'serie',
name='{}_changeset_series_pk'.format(namespace)),
schema=namespace
)
return registry, changeset, changeset_series
# default schema
registry, changeset, changeset_series = make_schema(meta)
def init(engine):
def init(engine, namespace='tsh'):
from sqlalchemy.schema import CreateSchema
engine.execute(CreateSchema('timeserie'))
engine.execute(CreateSchema(namespace))
engine.execute(CreateSchema('{}.timeserie'.format(namespace)))
registry.create(engine)
changeset.create(engine)
changeset_series.create(engine)
def reset(engine):
# explicitly cleanup the ts tables
if registry.exists(engine):
engine.execute('drop schema if exists timeserie cascade')
changeset_series.drop(engine)
registry.drop(engine)
changeset.drop(engine)
def reset(engine, namespace='tsh'):
engine.execute('drop schema if exists "{}.timeserie" cascade'.format(namespace))
engine.execute('drop schema if exists {} cascade'.format(namespace))
......@@ -61,6 +61,10 @@ class TimeSerie(object):
_csid = None
_snapshot_interval = 10
_precision = 1e-14
namespace = 'tsh'
def __init__(self, namespace='tsh'):
self.namespace = namespace
# API : changeset, insert, get, delete
@contextmanager
......@@ -220,11 +224,11 @@ class TimeSerie(object):
def info(self, cn):
"""Gather global statistics on the current tshistory repository
"""
sql = 'select count(*) from registry'
sql = 'select count(*) from {}.registry'.format(self.namespace)
stats = {'series count': cn.execute(sql).scalar()}
sql = 'select max(id) from changeset'
sql = 'select max(id) from {}.changeset'.format(self.namespace)
stats['changeset count'] = cn.execute(sql).scalar()
sql = 'select distinct name from registry order by name'
sql = 'select distinct name from {}.registry order by name'.format(self.namespace)
stats['serie names'] = [row for row, in cn.execute(sql).fetchall()]
return stats
......@@ -292,25 +296,27 @@ class TimeSerie(object):
def _ts_table_name(self, seriename):
# namespace.seriename
return 'timeserie.%s' % seriename
return '{}.timeserie.{}'.format(self.namespace, seriename)
def _table_definition_for(self, seriename):
return Table(
seriename, schema.meta,
Column('id', Integer, primary_key=True),
Column('csid', Integer, ForeignKey('changeset.id'),
Column('csid', Integer,
ForeignKey('{}.changeset.id'.format(self.namespace)),
index=True, nullable=False),
# constraint: there is either .diff or .snapshot
Column('diff', BYTEA),
Column('snapshot', BYTEA),
Column('parent',
Integer,
ForeignKey('timeserie.%s.id' % seriename,
ForeignKey('{}.timeserie.{}.id'.format(self.namespace,
seriename),
ondelete='cascade'),
nullable=True,
unique=True,
index=True),
schema='timeserie',
schema='{}.timeserie'.format(self.namespace),
extend_existing=True
)
......
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