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, 'integer': 0,
'string': '' '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__] return type_schema[column_type.__visit_name__]

View File

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

View File

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

View File

@ -42,6 +42,7 @@ from oslo_utils import uuidutils
from six.moves import range from six.moves import range
import sqlalchemy import sqlalchemy
from sqlalchemy import inspect from sqlalchemy import inspect
import sqlalchemy.types as types
from glance.common import crypt from glance.common import crypt
from glance.common import exception from glance.common import exception
@ -1887,6 +1888,28 @@ class ModelsMigrationSyncMixin(object):
def db_sync(self, engine): def db_sync(self, engine):
migration.db_sync(engine=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): def include_object(self, object_, name, type_, reflected, compare_to):
if name in ['migrate_version'] and type_ == 'table': if name in ['migrate_version'] and type_ == 'table':
return False return False