Compile BigInteger to INTEGER for sqlite

Ensure BigInteger does not map to BIGINT for an auto-created
sqlite registry DB, as this type is not supported by sqlite.

Refactoring a test to use generic unsupported column type

Fixes bug 1147879

Change-Id: I590c798dd470def286802bc6e00bb4b621332b8d
This commit is contained in:
Kaushik Chandrashekar 2013-03-07 19:17:00 -06:00
parent 6a080df6bd
commit 4ed4c848b6
3 changed files with 82 additions and 4 deletions

View File

@ -15,3 +15,11 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from sqlalchemy import BigInteger
from sqlalchemy.ext.compiler import compiles
@compiles(BigInteger, 'sqlite')
def compile_big_int_sqlite(type_, compiler, **kw):
return 'INTEGER'

View File

@ -0,0 +1,60 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# Copyright 2010 OpenStack Foundation
# All Rights Reserved.
#
# 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.
"""Test cases for sqlite-specific logic"""
from nova import test
import os
from sqlalchemy import create_engine
from sqlalchemy import Column, BigInteger, String
from sqlalchemy.ext.declarative import declarative_base
import subprocess
class TestSqlite(test.TestCase):
"""Tests for sqlite-specific logic."""
def setUp(self):
super(TestSqlite, self).setUp()
self.db_file = "test_bigint.sqlite"
if os.path.exists(self.db_file):
os.remove(self.db_file)
def test_big_int_mapping(self):
base_class = declarative_base()
class User(base_class):
"""Dummy class with a BigInteger column for testing."""
__tablename__ = "users"
id = Column(BigInteger, primary_key=True)
name = Column(String)
get_schema_cmd = "sqlite3 %s '.schema'" % self.db_file
engine = create_engine("sqlite:///%s" % self.db_file)
base_class.metadata.create_all(engine)
process = subprocess.Popen(get_schema_cmd, shell=True,
stdout=subprocess.PIPE)
output, _ = process.communicate()
self.assertFalse('BIGINT' in output, msg="column type BIGINT "
"not converted to INTEGER in schema")
def tearDown(self):
if os.path.exists(self.db_file):
os.remove(self.db_file)
super(TestSqlite, self).tearDown()

View File

@ -16,13 +16,16 @@
# under the License. # under the License.
from migrate.changeset import UniqueConstraint from migrate.changeset import UniqueConstraint
from sqlalchemy import Integer, BigInteger, DateTime, String from sqlalchemy import Integer, DateTime, String
from sqlalchemy import MetaData, Table, Column from sqlalchemy import MetaData, Table, Column
from sqlalchemy.exc import SAWarning
from sqlalchemy.sql import select from sqlalchemy.sql import select
from sqlalchemy.types import UserDefinedType
from nova.db.sqlalchemy import utils from nova.db.sqlalchemy import utils
from nova import exception from nova import exception
from nova.tests import test_migrations from nova.tests import test_migrations
import warnings
class TestMigrationUtils(test_migrations.BaseMigrationTestCase): class TestMigrationUtils(test_migrations.BaseMigrationTestCase):
@ -71,6 +74,12 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase):
test_table.drop() test_table.drop()
def test_util_drop_unique_constraint_with_not_supported_sqlite_type(self): def test_util_drop_unique_constraint_with_not_supported_sqlite_type(self):
class CustomType(UserDefinedType):
"""Dummy column type for testing unsupported types."""
def get_col_spec(self):
return "CustomType"
table_name = "__test_tmp_table__" table_name = "__test_tmp_table__"
uc_name = 'uniq_foo' uc_name = 'uniq_foo'
values = [ values = [
@ -86,15 +95,16 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase):
Column('id', Integer, primary_key=True, Column('id', Integer, primary_key=True,
nullable=False), nullable=False),
Column('a', Integer), Column('a', Integer),
Column('foo', BigInteger, default=0), Column('foo', CustomType, default=0),
UniqueConstraint('a', name='uniq_a'), UniqueConstraint('a', name='uniq_a'),
UniqueConstraint('foo', name=uc_name)) UniqueConstraint('foo', name=uc_name))
test_table.create() test_table.create()
engine.execute(test_table.insert(), values) engine.execute(test_table.insert(), values)
if key == "sqlite": if key == "sqlite":
warnings.simplefilter("ignore", SAWarning)
# NOTE(boris-42): Missing info about column `foo` that has # NOTE(boris-42): Missing info about column `foo` that has
# unsupported type BigInteger. # unsupported type CustomType.
self.assertRaises(exception.NovaException, self.assertRaises(exception.NovaException,
utils.drop_unique_constraint, utils.drop_unique_constraint,
engine, table_name, uc_name, 'foo') engine, table_name, uc_name, 'foo')
@ -106,7 +116,7 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase):
engine, table_name, uc_name, 'foo', engine, table_name, uc_name, 'foo',
foo=Integer()) foo=Integer())
foo = Column('foo', BigInteger, default=0) foo = Column('foo', CustomType, default=0)
utils.drop_unique_constraint(engine, table_name, uc_name, 'foo', utils.drop_unique_constraint(engine, table_name, uc_name, 'foo',
foo=foo) foo=foo)