Fix model sync for SQLite

This code fixes the situation when several
models are mismatched for SQLite because of
type inconsistencies between Integer and
BigInteger in sqlalchemy.

Change-Id: I52b3a0158db8e3dc48f19509d1f9f80420ee40ea
Closes-bug: #1526804
Closes-bug: #1526675
This commit is contained in:
Mike Fedosin 2015-12-16 17:05:45 +03:00 committed by Flavio Percoco
parent 4d5330088f
commit 2e2adb3935
4 changed files with 35 additions and 11 deletions

View File

@ -303,6 +303,10 @@ def _get_default_column_value(column_type):
'integer': 0,
'string': ''
}
if isinstance(column_type, sa_sql.type_api.Variant):
return _get_default_column_value(column_type.impl)
return type_schema[column_type.__visit_name__]

View File

@ -26,7 +26,6 @@ from sqlalchemy import BigInteger
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import DateTime
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import ForeignKey
from sqlalchemy import Index
@ -44,11 +43,6 @@ from glance.common import timeutils
BASE = declarative_base()
@compiles(BigInteger, 'sqlite')
def compile_big_int_sqlite(type_, compiler, **kw):
return 'INTEGER'
class JSONEncodedDict(TypeDecorator):
"""Represents an immutable structure as a json-encoded string"""
@ -131,8 +125,8 @@ class Image(BASE, GlanceBase):
name = Column(String(255))
disk_format = Column(String(20))
container_format = Column(String(20))
size = Column(BigInteger)
virtual_size = Column(BigInteger)
size = Column(BigInteger().with_variant(Integer, "sqlite"))
virtual_size = Column(BigInteger().with_variant(Integer, "sqlite"))
status = Column(String(30), nullable=False)
is_public = Column(Boolean, nullable=False, default=False)
checksum = Column(String(32))

View File

@ -109,13 +109,15 @@ class Artifact(BASE, ArtifactBase):
default=lambda: str(uuid.uuid4()))
name = Column(String(255), nullable=False)
type_name = Column(String(255), nullable=False)
type_version_prefix = Column(BigInteger, nullable=False)
type_version_prefix = Column(BigInteger().with_variant(Integer, "sqlite"),
nullable=False)
type_version_suffix = Column(String(255))
type_version_meta = Column(String(255))
type_version = composite(semver_db.DBVersion, type_version_prefix,
type_version_suffix, type_version_meta,
comparator_factory=semver_db.VersionComparator)
version_prefix = Column(BigInteger, nullable=False)
version_prefix = Column(BigInteger().with_variant(Integer, "sqlite"),
nullable=False)
version_suffix = Column(String(255))
version_meta = Column(String(255))
version = composite(semver_db.DBVersion, version_prefix,
@ -294,7 +296,8 @@ class ArtifactBlob(BASE, ArtifactBase):
nullable=False)
name = Column(String(255), nullable=False)
item_key = Column(String(329))
size = Column(BigInteger(), nullable=False)
size = Column(BigInteger().with_variant(Integer, "sqlite"),
nullable=False)
checksum = Column(String(32))
position = Column(Integer)
artifact = relationship(Artifact,

View File

@ -42,6 +42,7 @@ from oslo_utils import uuidutils
from six.moves import range
import sqlalchemy
from sqlalchemy import inspect
import sqlalchemy.types as types
from glance.common import crypt
from glance.common import exception
@ -1887,6 +1888,28 @@ class ModelsMigrationSyncMixin(object):
def db_sync(self, engine):
migration.db_sync(engine=engine)
# TODO(akamyshikova): remove this method as soon as comparison with Variant
# will be implemented in oslo.db or alembic
def compare_type(self, ctxt, insp_col, meta_col, insp_type, meta_type):
if isinstance(meta_type, types.Variant):
meta_orig_type = meta_col.type
insp_orig_type = insp_col.type
meta_col.type = meta_type.impl
insp_col.type = meta_type.impl
try:
return self.compare_type(ctxt, insp_col, meta_col, insp_type,
meta_type.impl)
finally:
meta_col.type = meta_orig_type
insp_col.type = insp_orig_type
else:
ret = super(ModelsMigrationSyncMixin, self).compare_type(
ctxt, insp_col, meta_col, insp_type, meta_type)
if ret is not None:
return ret
return ctxt.impl.compare_type(insp_col, meta_col)
def include_object(self, object_, name, type_, reflected, compare_to):
if name in ['migrate_version'] and type_ == 'table':
return False