rename meter table to sample

as we branch common meter definition data to it's own table,
we rename table containing raw data to more appropriate name:
sample

blueprint: meter-table-sql
Change-Id: I55c86540098225a3d52116df8b27854483921ee9
This commit is contained in:
Gordon Chung
2014-02-06 11:47:52 -05:00
parent 0c51a0a686
commit 461d13f2fc
5 changed files with 260 additions and 131 deletions

View File

@@ -55,9 +55,9 @@ class SQLAlchemyStorage(base.StorageEngine):
- { id: source id }
- project
- { id: project uuid }
- meter
- sample
- the raw incoming data
- { id: meter id
- { id: sample id
counter_name: counter name
user_id: user uuid (->user.id)
project_id: project uuid (->project.id)
@@ -79,7 +79,7 @@ class SQLAlchemyStorage(base.StorageEngine):
}
- sourceassoc
- the relationships
- { meter_id: meter id (->meter.id)
- { sample_id: sample id (->sample.id)
project_id: project uuid (->project.id)
resource_id: resource uuid (->resource.id)
user_id: user uuid (->user.id)
@@ -138,23 +138,24 @@ def make_query_from_filter(session, query, sample_filter, require_meter=True):
"""
if sample_filter.meter:
query = query.filter(models.Meter.counter_name == sample_filter.meter)
query = query.filter(models.Sample.counter_name == sample_filter.meter)
elif require_meter:
raise RuntimeError(_('Missing required meter specifier'))
if sample_filter.source:
query = query.filter(models.Meter.sources.any(id=sample_filter.source))
query = query.filter(models.Sample.sources.any(
id=sample_filter.source))
if sample_filter.start:
ts_start = sample_filter.start
if sample_filter.start_timestamp_op == 'gt':
query = query.filter(models.Meter.timestamp > ts_start)
query = query.filter(models.Sample.timestamp > ts_start)
else:
query = query.filter(models.Meter.timestamp >= ts_start)
query = query.filter(models.Sample.timestamp >= ts_start)
if sample_filter.end:
ts_end = sample_filter.end
if sample_filter.end_timestamp_op == 'le':
query = query.filter(models.Meter.timestamp <= ts_end)
query = query.filter(models.Sample.timestamp <= ts_end)
else:
query = query.filter(models.Meter.timestamp < ts_end)
query = query.filter(models.Sample.timestamp < ts_end)
if sample_filter.user:
query = query.filter_by(user_id=sample_filter.user)
if sample_filter.project:
@@ -270,21 +271,21 @@ class Connection(base.Connection):
user=user, project=project,
resource_metadata=rmetadata)
# Record the raw data for the meter.
meter = models.Meter(counter_type=data['counter_type'],
counter_unit=data['counter_unit'],
counter_name=data['counter_name'],
resource=resource)
session.add(meter)
if not filter(lambda x: x.id == source.id, meter.sources):
meter.sources.append(source)
meter.project = project
meter.user = user
meter.timestamp = data['timestamp']
meter.resource_metadata = rmetadata
meter.counter_volume = data['counter_volume']
meter.message_signature = data['message_signature']
meter.message_id = data['message_id']
# Record the raw data for the sample.
sample = models.Sample(counter_type=data['counter_type'],
counter_unit=data['counter_unit'],
counter_name=data['counter_name'],
resource=resource)
session.add(sample)
if not filter(lambda x: x.id == source.id, sample.sources):
sample.sources.append(source)
sample.project = project
sample.user = user
sample.timestamp = data['timestamp']
sample.resource_metadata = rmetadata
sample.counter_volume = data['counter_volume']
sample.message_signature = data['message_signature']
sample.message_id = data['message_id']
session.flush()
if rmetadata:
@@ -296,7 +297,7 @@ class Connection(base.Connection):
LOG.warn(_("Unknown metadata type. Key (%s) will "
"not be queryable."), key)
else:
session.add(_model(id=meter.id,
session.add(_model(id=sample.id,
meta_key=key,
value=v))
@@ -311,14 +312,14 @@ class Connection(base.Connection):
session = self._get_db_session()
with session.begin():
end = timeutils.utcnow() - datetime.timedelta(seconds=ttl)
meter_query = session.query(models.Meter)\
.filter(models.Meter.timestamp < end)
for meter_obj in meter_query.all():
session.delete(meter_obj)
sample_query = session.query(models.Sample)\
.filter(models.Sample.timestamp < end)
for sample_obj in sample_query.all():
session.delete(sample_obj)
query = session.query(models.User).filter(
~models.User.id.in_(session.query(models.Meter.user_id)
.group_by(models.Meter.user_id)),
~models.User.id.in_(session.query(models.Sample.user_id)
.group_by(models.Sample.user_id)),
~models.User.id.in_(session.query(models.AlarmChange.user_id)
.group_by(models.AlarmChange.user_id))
)
@@ -327,8 +328,8 @@ class Connection(base.Connection):
query = session.query(models.Project)\
.filter(~models.Project.id.in_(
session.query(models.Meter.project_id)
.group_by(models.Meter.project_id)),
session.query(models.Sample.project_id)
.group_by(models.Sample.project_id)),
~models.Project.id.in_(
session.query(models.AlarmChange.project_id)
.group_by(models.AlarmChange.project_id)),
@@ -341,8 +342,8 @@ class Connection(base.Connection):
query = session.query(models.Resource)\
.filter(~models.Resource.id.in_(
session.query(models.Meter.resource_id).group_by(
models.Meter.resource_id)))
session.query(models.Sample.resource_id).group_by(
models.Sample.resource_id)))
for res_obj in query.all():
session.delete(res_obj)
@@ -396,21 +397,21 @@ class Connection(base.Connection):
# most accurate. We also need to filter down in the subquery to
# constrain what we have to JOIN on later.
ts_subquery = session.query(
models.Meter.resource_id,
func.max(models.Meter.timestamp).label("max_ts"),
func.min(models.Meter.timestamp).label("min_ts")
).group_by(models.Meter.resource_id)
models.Sample.resource_id,
func.max(models.Sample.timestamp).label("max_ts"),
func.min(models.Sample.timestamp).label("min_ts")
).group_by(models.Sample.resource_id)
# Here are the basic 'eq' operation filters for the sample data.
for column, value in [(models.Meter.resource_id, resource),
(models.Meter.user_id, user),
(models.Meter.project_id, project)]:
for column, value in [(models.Sample.resource_id, resource),
(models.Sample.user_id, user),
(models.Sample.project_id, project)]:
if value:
ts_subquery = ts_subquery.filter(column == value)
if source:
ts_subquery = ts_subquery.filter(
models.Meter.sources.any(id=source))
models.Sample.sources.any(id=source))
if metaquery:
ts_subquery = apply_metaquery_filter(session,
@@ -422,27 +423,27 @@ class Connection(base.Connection):
if start_timestamp:
if start_timestamp_op == 'gt':
ts_subquery = ts_subquery.filter(
models.Meter.timestamp > start_timestamp)
models.Sample.timestamp > start_timestamp)
else:
ts_subquery = ts_subquery.filter(
models.Meter.timestamp >= start_timestamp)
models.Sample.timestamp >= start_timestamp)
if end_timestamp:
if end_timestamp_op == 'le':
ts_subquery = ts_subquery.filter(
models.Meter.timestamp <= end_timestamp)
models.Sample.timestamp <= end_timestamp)
else:
ts_subquery = ts_subquery.filter(
models.Meter.timestamp < end_timestamp)
models.Sample.timestamp < end_timestamp)
ts_subquery = ts_subquery.subquery()
# Now we need to get the max Meter.id out of the leftover results, to
# Now we need to get the max Sample.id out of the leftover results, to
# break any ties.
agg_subquery = session.query(
func.max(models.Meter.id).label("max_id"),
func.max(models.Sample.id).label("max_id"),
ts_subquery
).filter(
models.Meter.resource_id == ts_subquery.c.resource_id,
models.Meter.timestamp == ts_subquery.c.max_ts
models.Sample.resource_id == ts_subquery.c.resource_id,
models.Sample.timestamp == ts_subquery.c.max_ts
).group_by(
ts_subquery.c.resource_id,
ts_subquery.c.max_ts,
@@ -450,22 +451,22 @@ class Connection(base.Connection):
).subquery()
query = session.query(
models.Meter,
models.Sample,
agg_subquery.c.min_ts,
agg_subquery.c.max_ts
).filter(
models.Meter.id == agg_subquery.c.max_id
models.Sample.id == agg_subquery.c.max_id
)
for meter, first_ts, last_ts in query.all():
for sample, first_ts, last_ts in query.all():
yield api_models.Resource(
resource_id=meter.resource_id,
project_id=meter.project_id,
resource_id=sample.resource_id,
project_id=sample.project_id,
first_sample_timestamp=first_ts,
last_sample_timestamp=last_ts,
source=meter.sources[0].id,
user_id=meter.user_id,
metadata=meter.resource_metadata,
source=sample.sources[0].id,
user_id=sample.user_id,
metadata=sample.resource_metadata,
)
def get_meters(self, user=None, project=None, resource=None, source=None,
@@ -485,35 +486,36 @@ class Connection(base.Connection):
session = self._get_db_session()
# Meter table will store large records and join with resource
# Sample table will store large records and join with resource
# will be very slow.
# subquery_meter is used to reduce meter records
# subquery_sample is used to reduce sample records
# by selecting a record for each (resource_id, counter_name).
# max() is used to choice a meter record, so the latest record
# max() is used to choice a sample record, so the latest record
# is selected for each (resource_id, counter_name).
#
subquery_meter = session.query(func.max(models.Meter.id).label('id'))\
.group_by(models.Meter.resource_id,
models.Meter.counter_name).subquery()
subquery_sample = session.query(
func.max(models.Sample.id).label('id'))\
.group_by(models.Sample.resource_id,
models.Sample.counter_name).subquery()
# The SQL of query_meter is essentially:
# The SQL of query_sample is essentially:
#
# SELECT meter.* FROM meter INNER JOIN
# (SELECT max(meter.id) AS id FROM meter
# GROUP BY meter.resource_id, meter.counter_name) AS anon_2
# ON meter.id = anon_2.id
# SELECT sample.* FROM sample INNER JOIN
# (SELECT max(sample.id) AS id FROM sample
# GROUP BY sample.resource_id, sample.counter_name) AS anon_2
# ON sample.id = anon_2.id
#
query_meter = session.query(models.Meter).\
join(subquery_meter, models.Meter.id == subquery_meter.c.id)
query_sample = session.query(models.Sample).\
join(subquery_sample, models.Sample.id == subquery_sample.c.id)
if metaquery:
query_meter = apply_metaquery_filter(session,
query_meter,
metaquery)
query_sample = apply_metaquery_filter(session,
query_sample,
metaquery)
alias_meter = aliased(models.Meter, query_meter.subquery())
query = session.query(models.Resource, alias_meter).join(
alias_meter, models.Resource.id == alias_meter.resource_id)
alias_sample = aliased(models.Sample, query_sample.subquery())
query = session.query(models.Resource, alias_sample).join(
alias_sample, models.Resource.id == alias_sample.resource_id)
if user is not None:
query = query.filter(models.Resource.user_id == user)
@@ -524,11 +526,11 @@ class Connection(base.Connection):
if project is not None:
query = query.filter(models.Resource.project_id == project)
for resource, meter in query.all():
for resource, sample in query.all():
yield api_models.Meter(
name=meter.counter_name,
type=meter.counter_type,
unit=meter.counter_unit,
name=sample.counter_name,
type=sample.counter_type,
unit=sample.counter_unit,
resource_id=resource.id,
project_id=resource.project_id,
source=resource.sources[0].id,
@@ -549,7 +551,7 @@ class Connection(base.Connection):
# detail that should not leak outside of the driver.
yield api_models.Sample(
# Replace 'sources' with 'source' to meet the caller's
# expectation, Meter.sources contains one and only one
# expectation, Sample.sources contains one and only one
# source in the current implementation.
source=s.sources[0].id,
counter_name=s.counter_name,
@@ -575,7 +577,7 @@ class Connection(base.Connection):
if limit == 0:
return []
table = models.Meter
table = models.Sample
session = self._get_db_session()
query = session.query(table)
query = make_query_from_filter(session, query, sample_filter,
@@ -604,7 +606,7 @@ class Connection(base.Connection):
limit,
table)
retrieve = {models.Meter: self._retrieve_samples,
retrieve = {models.Sample: self._retrieve_samples,
models.Alarm: self._retrieve_alarms,
models.AlarmChange: self._retrieve_alarm_history}
return retrieve[table](query)
@@ -613,7 +615,7 @@ class Connection(base.Connection):
return self._retrieve_data(filter_expr,
orderby,
limit,
models.Meter)
models.Sample)
def _transform_expression(self, expression_tree, table):
@@ -646,20 +648,20 @@ class Connection(base.Connection):
def _make_stats_query(self, sample_filter, groupby):
select = [
models.Meter.counter_unit.label('unit'),
func.min(models.Meter.timestamp).label('tsmin'),
func.max(models.Meter.timestamp).label('tsmax'),
func.avg(models.Meter.counter_volume).label('avg'),
func.sum(models.Meter.counter_volume).label('sum'),
func.min(models.Meter.counter_volume).label('min'),
func.max(models.Meter.counter_volume).label('max'),
func.count(models.Meter.counter_volume).label('count'),
models.Sample.counter_unit.label('unit'),
func.min(models.Sample.timestamp).label('tsmin'),
func.max(models.Sample.timestamp).label('tsmax'),
func.avg(models.Sample.counter_volume).label('avg'),
func.sum(models.Sample.counter_volume).label('sum'),
func.min(models.Sample.counter_volume).label('min'),
func.max(models.Sample.counter_volume).label('max'),
func.count(models.Sample.counter_volume).label('count'),
]
session = self._get_db_session()
if groupby:
group_attributes = [getattr(models.Meter, g) for g in groupby]
group_attributes = [getattr(models.Sample, g) for g in groupby]
select.extend(group_attributes)
query = session.query(*select)
@@ -726,8 +728,8 @@ class Connection(base.Connection):
sample_filter.start or res.tsmin,
sample_filter.end or res.tsmax,
period):
q = query.filter(models.Meter.timestamp >= period_start)
q = q.filter(models.Meter.timestamp < period_end)
q = query.filter(models.Sample.timestamp >= period_start)
q = q.filter(models.Sample.timestamp < period_end)
for r in q.all():
if r.count:
yield self._stats_result_to_model(

View File

@@ -13,18 +13,20 @@
# License for the specific language governing permissions and limitations
# under the License.
from sqlalchemy import Index
from ceilometer.storage.sqlalchemy import models
import sqlalchemy as sa
def upgrade(migrate_engine):
index = Index('idx_meter_rid_cname', models.Meter.resource_id,
models.Meter.counter_name)
meta = sa.MetaData(bind=migrate_engine)
meter = sa.Table('meter', meta, autoload=True)
index = sa.Index('idx_meter_rid_cname', meter.c.resource_id,
meter.c.counter_name)
index.create(bind=migrate_engine)
def downgrade(migrate_engine):
index = Index('idx_meter_rid_cname', models.Meter.resource_id,
models.Meter.counter_name)
meta = sa.MetaData(bind=migrate_engine)
meter = sa.Table('meter', meta, autoload=True)
index = sa.Index('idx_meter_rid_cname', meter.c.resource_id,
meter.c.counter_name)
index.drop(bind=migrate_engine)

View File

@@ -0,0 +1,125 @@
# -*- encoding: utf-8 -*-
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import migrate
import sqlalchemy as sa
def _handle_meter_indices(meta, downgrade=False):
if meta.bind.engine.name == 'sqlite':
return
resource = sa.Table('resource', meta, autoload=True)
project = sa.Table('project', meta, autoload=True)
user = sa.Table('user', meta, autoload=True)
meter = sa.Table('meter', meta, autoload=True)
indices = [(sa.Index('ix_meter_timestamp', meter.c.timestamp),
sa.Index('ix_sample_timestamp', meter.c.timestamp)),
(sa.Index('ix_meter_user_id', meter.c.user_id),
sa.Index('ix_sample_user_id', meter.c.user_id)),
(sa.Index('ix_meter_project_id', meter.c.project_id),
sa.Index('ix_sample_project_id', meter.c.project_id)),
(sa.Index('idx_meter_rid_cname', meter.c.resource_id,
meter.c.counter_name),
sa.Index('idx_sample_rid_cname', meter.c.resource_id,
meter.c.counter_name))]
fk_params = [({'columns': [meter.c.resource_id],
'refcolumns': [resource.c.id]},
'fk_meter_resource_id',
'fk_sample_resource_id'),
({'columns': [meter.c.project_id],
'refcolumns': [project.c.id]},
'fk_meter_project_id',
'fk_sample_project_id'),
({'columns': [meter.c.user_id],
'refcolumns': [user.c.id]},
'fk_meter_user_id',
'fk_sample_user_id')]
for fk in fk_params:
params = fk[0]
if meta.bind.engine.name == 'mysql':
params['name'] = fk[2] if downgrade else fk[1]
migrate.ForeignKeyConstraint(**params).drop()
for meter_ix, sample_ix in indices:
meter_ix.create() if downgrade else meter_ix.drop()
sample_ix.drop() if downgrade else sample_ix.create()
for fk in fk_params:
params = fk[0]
if meta.bind.engine.name == 'mysql':
params['name'] = fk[1] if downgrade else fk[2]
migrate.ForeignKeyConstraint(**params).create()
def _alter_sourceassoc(meta, t_name, ix_name, post_action=False):
if meta.bind.engine.name == 'sqlite':
return
sourceassoc = sa.Table('sourceassoc', meta, autoload=True)
table = sa.Table(t_name, meta, autoload=True)
user = sa.Table('user', meta, autoload=True)
c_name = '%s_id' % t_name
col = getattr(sourceassoc.c, c_name)
uniq_name = 'uniq_sourceassoc0%s0user_id' % c_name
uniq_cols = (c_name, 'user_id')
param = {'columns': [col],
'refcolumns': [table.c.id]}
user_param = {'columns': [sourceassoc.c.user_id],
'refcolumns': [user.c.id]}
if meta.bind.engine.name == 'mysql':
param['name'] = 'fk_sourceassoc_%s' % c_name
user_param['name'] = 'fk_sourceassoc_user_id'
actions = [migrate.ForeignKeyConstraint(**user_param),
migrate.ForeignKeyConstraint(**param),
sa.Index(ix_name, sourceassoc.c.source_id, col),
migrate.UniqueConstraint(*uniq_cols, table=sourceassoc,
name=uniq_name)]
for action in actions:
action.create() if post_action else action.drop()
def upgrade(migrate_engine):
meta = sa.MetaData(bind=migrate_engine)
_handle_meter_indices(meta)
meter = sa.Table('meter', meta, autoload=True)
meter.rename('sample')
_alter_sourceassoc(meta, 'meter', 'idx_sm')
sourceassoc = sa.Table('sourceassoc', meta, autoload=True)
sourceassoc.c.meter_id.alter(name='sample_id')
#re-bind metadata to pick up alter name change
meta = sa.MetaData(bind=migrate_engine)
_alter_sourceassoc(meta, 'sample', 'idx_ss', True)
def downgrade(migrate_engine):
meta = sa.MetaData(bind=migrate_engine)
sample = sa.Table('sample', meta, autoload=True)
sample.rename('meter')
_handle_meter_indices(meta, True)
_alter_sourceassoc(meta, 'sample', 'idx_ss')
sourceassoc = sa.Table('sourceassoc', meta, autoload=True)
sourceassoc.c.sample_id.alter(name='meter_id')
meta = sa.MetaData(bind=migrate_engine)
_alter_sourceassoc(meta, 'meter', 'idx_sm', True)

View File

@@ -116,8 +116,8 @@ Base = declarative_base(cls=CeilometerBase)
sourceassoc = Table('sourceassoc', Base.metadata,
Column('meter_id', Integer,
ForeignKey("meter.id")),
Column('sample_id', Integer,
ForeignKey("sample.id")),
Column('project_id', String(255),
ForeignKey("project.id")),
Column('resource_id', String(255),
@@ -130,10 +130,10 @@ sourceassoc = Table('sourceassoc', Base.metadata,
Index('idx_su', sourceassoc.c['source_id'], sourceassoc.c['user_id']),
Index('idx_sp', sourceassoc.c['source_id'], sourceassoc.c['project_id']),
Index('idx_sr', sourceassoc.c['source_id'], sourceassoc.c['resource_id']),
Index('idx_sm', sourceassoc.c['source_id'], sourceassoc.c['meter_id']),
Index('idx_ss', sourceassoc.c['source_id'], sourceassoc.c['sample_id']),
Index('ix_sourceassoc_source_id', sourceassoc.c['source_id'])
UniqueConstraint(sourceassoc.c['meter_id'], sourceassoc.c['user_id'],
name='uniq_sourceassoc0meter_id0user_id')
UniqueConstraint(sourceassoc.c['sample_id'], sourceassoc.c['user_id'],
name='uniq_sourceassoc0sample_id0user_id')
class Source(Base):
@@ -148,7 +148,7 @@ class MetaText(Base):
__table_args__ = (
Index('ix_meta_text_key', 'meta_key'),
)
id = Column(Integer, ForeignKey('meter.id'), primary_key=True)
id = Column(Integer, ForeignKey('sample.id'), primary_key=True)
meta_key = Column(String(255), primary_key=True)
value = Column(Text)
@@ -160,7 +160,7 @@ class MetaBool(Base):
__table_args__ = (
Index('ix_meta_bool_key', 'meta_key'),
)
id = Column(Integer, ForeignKey('meter.id'), primary_key=True)
id = Column(Integer, ForeignKey('sample.id'), primary_key=True)
meta_key = Column(String(255), primary_key=True)
value = Column(Boolean)
@@ -172,7 +172,7 @@ class MetaBigInt(Base):
__table_args__ = (
Index('ix_meta_int_key', 'meta_key'),
)
id = Column(Integer, ForeignKey('meter.id'), primary_key=True)
id = Column(Integer, ForeignKey('sample.id'), primary_key=True)
meta_key = Column(String(255), primary_key=True)
value = Column(BigInteger, default=False)
@@ -184,20 +184,20 @@ class MetaFloat(Base):
__table_args__ = (
Index('ix_meta_float_key', 'meta_key'),
)
id = Column(Integer, ForeignKey('meter.id'), primary_key=True)
id = Column(Integer, ForeignKey('sample.id'), primary_key=True)
meta_key = Column(String(255), primary_key=True)
value = Column(Float(53), default=False)
class Meter(Base):
class Sample(Base):
"""Metering data."""
__tablename__ = 'meter'
__tablename__ = 'sample'
__table_args__ = (
Index('ix_meter_timestamp', 'timestamp'),
Index('ix_meter_user_id', 'user_id'),
Index('ix_meter_project_id', 'project_id'),
Index('idx_meter_rid_cname', 'resource_id', 'counter_name'),
Index('ix_sample_timestamp', 'timestamp'),
Index('ix_sample_user_id', 'user_id'),
Index('ix_sample_project_id', 'project_id'),
Index('idx_sample_rid_cname', 'resource_id', 'counter_name'),
)
id = Column(Integer, primary_key=True)
counter_name = Column(String(255))
@@ -213,13 +213,13 @@ class Meter(Base):
message_signature = Column(String(1000))
message_id = Column(String(1000))
sources = relationship("Source", secondary=lambda: sourceassoc)
meta_text = relationship("MetaText", backref="meter",
meta_text = relationship("MetaText", backref="sample",
cascade="all, delete-orphan")
meta_float = relationship("MetaFloat", backref="meter",
meta_float = relationship("MetaFloat", backref="sample",
cascade="all, delete-orphan")
meta_int = relationship("MetaBigInt", backref="meter",
meta_int = relationship("MetaBigInt", backref="sample",
cascade="all, delete-orphan")
meta_bool = relationship("MetaBool", backref="meter",
meta_bool = relationship("MetaBool", backref="sample",
cascade="all, delete-orphan")
@@ -228,7 +228,7 @@ class User(Base):
id = Column(String(255), primary_key=True)
sources = relationship("Source", secondary=lambda: sourceassoc)
resources = relationship("Resource", backref='user')
meters = relationship("Meter", backref='user')
samples = relationship("Sample", backref='user')
class Project(Base):
@@ -236,7 +236,7 @@ class Project(Base):
id = Column(String(255), primary_key=True)
sources = relationship("Source", secondary=lambda: sourceassoc)
resources = relationship("Resource", backref='project')
meters = relationship("Meter", backref='project')
samples = relationship("Sample", backref='project')
class Resource(Base):
@@ -251,7 +251,7 @@ class Resource(Base):
resource_metadata = Column(JSONEncodedDict())
user_id = Column(String(255), ForeignKey('user.id'))
project_id = Column(String(255), ForeignKey('project.id'))
meters = relationship("Meter", backref='resource')
samples = relationship("Sample", backref='resource')
class Alarm(Base):

View File

@@ -198,8 +198,8 @@ class RelationshipTest(scenarios.DBTestBase):
for table in meta_tables:
self.assertEqual(session.query(table)
.filter(~table.id.in_(
session.query(sql_models.Meter.id)
.group_by(sql_models.Meter.id)
session.query(sql_models.Sample.id)
.group_by(sql_models.Sample.id)
)).count(), 0)
def test_clear_metering_data_associations(self):
@@ -208,9 +208,9 @@ class RelationshipTest(scenarios.DBTestBase):
session = self.conn._get_db_session()
self.assertEqual(session.query(sql_models.sourceassoc)
.filter(~sql_models.sourceassoc.c.meter_id.in_(
session.query(sql_models.Meter.id)
.group_by(sql_models.Meter.id)
.filter(~sql_models.sourceassoc.c.sample_id.in_(
session.query(sql_models.Sample.id)
.group_by(sql_models.Sample.id)
)).count(), 0)
self.assertEqual(session.query(sql_models.sourceassoc)
.filter(~sql_models.sourceassoc.c.project_id.in_(