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

schema: radically simplify the handling

parent 4dd6ebab46cf
from pathlib import Path
import logging
from sqlalchemy import create_engine
import pandas as pd
......@@ -15,9 +14,6 @@ from tshistory.snapshot import Snapshot
DATADIR = Path(__file__).parent / 'test' / 'data'
DBURI = 'postgresql://localhost:5433/postgres'
schema.L.addHandler(logging.StreamHandler())
tsio.L.addHandler(logging.StreamHandler())
@pytest.fixture(scope='session')
def engine(request):
......@@ -38,8 +34,7 @@ def datadir():
def tsh(request, engine):
namespace = request.param
sch = schema.tsschema(namespace)
sch.destroy(engine)
schema.init_schemas(engine, namespace)
sch.create(engine)
if namespace == 'z-z':
Snapshot._max_bucket_size = 5
......@@ -49,9 +44,7 @@ def tsh(request, engine):
@pytest.fixture(scope='session')
def ptsh(engine):
sch = schema.tsschema()
sch.destroy(engine)
schema.register_schema(sch)
schema.init_schemas(engine)
sch.create(engine)
return tsio.timeseries()
......
import logging
from threading import Lock
from pathlib import Path
from tshistory.util import unilist, sqlfile
L = logging.getLogger('tshistory.schema')
CREATEFILE = Path(__file__).parent / 'schema.sql'
# schemas registry
_SCHLOCK = Lock()
_SCHEMA_HANDLERS = unilist()
def register_schema(schema):
for meth in ('define', 'exists', 'create', 'destroy'):
getattr(schema, meth)
with _SCHLOCK:
if schema not in _SCHEMA_HANDLERS:
_SCHEMA_HANDLERS.append(schema)
def init_schemas(engine, namespace='tsh'):
for schema in _SCHEMA_HANDLERS:
schema.define()
schema.create(engine)
def reset_schemas(engine):
for schema in reversed(_SCHEMA_HANDLERS):
schema.destroy(engine)
def _delete_schema(engine, ns):
with engine.begin() as cn:
for subns in ('timeserie', 'snapshot'):
cn.execute(
'drop schema if exists "{}.{}" cascade'.format(ns, subns)
)
cn.execute('drop schema if exists "{}" cascade'.format(ns))
CREATEFILE = Path(__file__).parent / 'schema.sql'
class tsschema(object):
namespace = 'tsh'
registry = None
changeset = None
changeset_series = None
SCHEMAS = {}
def __new__(cls, namespace='tsh'):
# singleton-per-namespace handling
with _SCHLOCK:
if namespace in cls.SCHEMAS:
return cls.SCHEMAS[namespace]
return super(tsschema, cls).__new__(cls)
def __init__(self, namespace='tsh'):
self.namespace = namespace
register_schema(self)
def define(self):
with _SCHLOCK:
if self.namespace in self.SCHEMAS:
return
L.info('build schema %s', self.namespace)
with _SCHLOCK:
self.SCHEMAS[self.namespace] = self
def exists(self, engine):
return engine.execute(
'select exists('
' select schema_name '
' from information_schema.schemata '
' where schema_name = %(name)s'
')',
name=self.namespace
).scalar()
def __init__(self, ns='tsh'):
self.namespace = ns
def create(self, engine):
L.info('create schema %s %s', self.namespace, self.exists(engine))
if self.exists(engine):
if self.namespace != 'tsh':
L.warning('cannot create already existing namespace %s',
self.namespace)
return
engine.execute(f'create schema if not exists "{self.namespace}"')
engine.execute(f'create schema if not exists "{self.namespace}.timeserie"')
engine.execute(f'create schema if not exists "{self.namespace}.snapshot"')
engine.execute(sqlfile(CREATEFILE, ns=self.namespace))
def destroy(self, engine):
L.info('destroy schema %s', self.namespace)
_delete_schema(engine, self.namespace)
self.SCHEMAS.pop(self.namespace, None)
with engine.begin() as cn:
cn.execute(f'drop schema if exists "{self.namespace}" cascade')
cn.execute(f'drop schema if exists "{self.namespace}.timeserie" cascade')
cn.execute(f'drop schema if exists "{self.namespace}.snapshot" cascade')
cn.execute(f'create schema "{self.namespace}"')
cn.execute(f'create schema "{self.namespace}.timeserie"')
cn.execute(f'create schema "{self.namespace}.snapshot"')
cn.execute(sqlfile(CREATEFILE, ns=self.namespace))
......@@ -10,7 +10,6 @@ import pandas as pd
from deprecated import deprecated
from tshistory.schema import tsschema
from tshistory.util import (
closed_overlaps,
num2float,
......@@ -45,7 +44,6 @@ class timeseries(SeriesServices):
def __init__(self, namespace='tsh'):
self.namespace = namespace
tsschema(namespace).define()
self.metadatacache = {}
self.registry_map = {}
self.serie_tablename = {}
......
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