From 4ed4c848b66bc5fdd42e05c8b8c726ace2c25704 Mon Sep 17 00:00:00 2001 From: Kaushik Chandrashekar Date: Thu, 7 Mar 2013 19:17:00 -0600 Subject: 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 --- nova/db/sqlalchemy/__init__.py | 8 +++++ nova/tests/db/test_sqlite.py | 60 ++++++++++++++++++++++++++++++++++++++ nova/tests/test_migration_utils.py | 18 +++++++++--- 3 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 nova/tests/db/test_sqlite.py diff --git a/nova/db/sqlalchemy/__init__.py b/nova/db/sqlalchemy/__init__.py index 747015af5..800f11071 100644 --- a/nova/db/sqlalchemy/__init__.py +++ b/nova/db/sqlalchemy/__init__.py @@ -15,3 +15,11 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # 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' diff --git a/nova/tests/db/test_sqlite.py b/nova/tests/db/test_sqlite.py new file mode 100644 index 000000000..0383f058b --- /dev/null +++ b/nova/tests/db/test_sqlite.py @@ -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() diff --git a/nova/tests/test_migration_utils.py b/nova/tests/test_migration_utils.py index ddaaa2552..1096be0d3 100644 --- a/nova/tests/test_migration_utils.py +++ b/nova/tests/test_migration_utils.py @@ -16,13 +16,16 @@ # under the License. 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.exc import SAWarning from sqlalchemy.sql import select +from sqlalchemy.types import UserDefinedType from nova.db.sqlalchemy import utils from nova import exception from nova.tests import test_migrations +import warnings class TestMigrationUtils(test_migrations.BaseMigrationTestCase): @@ -71,6 +74,12 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase): test_table.drop() 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__" uc_name = 'uniq_foo' values = [ @@ -86,15 +95,16 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase): Column('id', Integer, primary_key=True, nullable=False), Column('a', Integer), - Column('foo', BigInteger, default=0), + Column('foo', CustomType, default=0), UniqueConstraint('a', name='uniq_a'), UniqueConstraint('foo', name=uc_name)) test_table.create() engine.execute(test_table.insert(), values) if key == "sqlite": + warnings.simplefilter("ignore", SAWarning) # NOTE(boris-42): Missing info about column `foo` that has - # unsupported type BigInteger. + # unsupported type CustomType. self.assertRaises(exception.NovaException, utils.drop_unique_constraint, engine, table_name, uc_name, 'foo') @@ -106,7 +116,7 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase): engine, table_name, uc_name, 'foo', foo=Integer()) - foo = Column('foo', BigInteger, default=0) + foo = Column('foo', CustomType, default=0) utils.drop_unique_constraint(engine, table_name, uc_name, 'foo', foo=foo) -- cgit