Merge "Truncate microseconds before DB insertion"

This commit is contained in:
Jenkins 2016-09-01 17:58:22 +00:00 committed by Gerrit Code Review
commit b5f7a53f85
3 changed files with 45 additions and 2 deletions

View File

@ -65,3 +65,19 @@ class MACAddress(types.TypeDecorator):
"type.") % {'type': type(value), "type.") % {'type': type(value),
'value': value}) 'value': value})
return str(value) return str(value)
class TruncatedDateTime(types.TypeDecorator):
"""Truncates microseconds.
Use this for datetime fields so we don't have to worry about DB-specifc
behavior when it comes to rounding/truncating microseconds off of
timestamps.
"""
impl = types.DateTime
def process_bind_param(self, value, dialect):
return value.replace(microsecond=0) if value else value
process_result_value = process_bind_param

View File

@ -13,15 +13,16 @@
# limitations under the License. # limitations under the License.
from neutron_lib.db import model_base from neutron_lib.db import model_base
from oslo_db.sqlalchemy import models from oslo_utils import timeutils
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext import declarative from sqlalchemy.ext import declarative
from neutron.api.v2 import attributes as attr from neutron.api.v2 import attributes as attr
from neutron.db import sqlalchemytypes
class StandardAttribute(model_base.BASEV2, models.TimestampMixin): class StandardAttribute(model_base.BASEV2):
"""Common table to associate all Neutron API resources. """Common table to associate all Neutron API resources.
By having Neutron objects related to this table, we can associate new By having Neutron objects related to this table, we can associate new
@ -54,6 +55,10 @@ class StandardAttribute(model_base.BASEV2, models.TimestampMixin):
revision_number = sa.Column( revision_number = sa.Column(
sa.BigInteger().with_variant(sa.Integer(), 'sqlite'), sa.BigInteger().with_variant(sa.Integer(), 'sqlite'),
server_default='0', nullable=False) server_default='0', nullable=False)
created_at = sa.Column(sqlalchemytypes.TruncatedDateTime,
default=timeutils.utcnow)
updated_at = sa.Column(sqlalchemytypes.TruncatedDateTime,
onupdate=timeutils.utcnow)
__mapper_args__ = { __mapper_args__ = {
# see http://docs.sqlalchemy.org/en/latest/orm/versioning.html for # see http://docs.sqlalchemy.org/en/latest/orm/versioning.html for

View File

@ -15,6 +15,7 @@ import netaddr
from oslo_db import exception from oslo_db import exception
from oslo_db.sqlalchemy import test_base from oslo_db.sqlalchemy import test_base
from oslo_utils import timeutils
from oslo_utils import uuidutils from oslo_utils import uuidutils
import six import six
import sqlalchemy as sa import sqlalchemy as sa
@ -233,3 +234,24 @@ class MACAddressTestCase(SqlAlchemyTypesBaseTestCase):
for mac in wrong_macs: for mac in wrong_macs:
self.assertRaises(exception.DBError, self._add_row, self.assertRaises(exception.DBError, self._add_row,
id=uuidutils.generate_uuid(), mac=mac) id=uuidutils.generate_uuid(), mac=mac)
class TruncatedDateTimeTestCase(SqlAlchemyTypesBaseTestCase):
def _get_test_table(self, meta):
return sa.Table(
'timetable',
meta,
sa.Column('id', sa.String(36), primary_key=True, nullable=False),
sa.Column('thetime', sqlalchemytypes.TruncatedDateTime)
)
def test_microseconds_truncated(self):
tstamp = timeutils.utcnow()
tstamp_low = tstamp.replace(microsecond=111111)
tstamp_high = tstamp.replace(microsecond=999999)
self._add_row(id=1, thetime=tstamp_low)
self._add_row(id=2, thetime=tstamp_high)
rows = self._get_all()
self.assertEqual(2, len(rows))
self.assertEqual(rows[0].thetime, rows[1].thetime)