Beispiel #1
0
 def test_alter_column_default(self, registry):
     t = registry.migration.table('test')
     c = t.column('other').alter(server_default='test')
     if sgdb_in(['PostgreSQL']):
         assert c.server_default == "'test'::character varying"
     else:
         assert str(c.server_default) == "'test'"
Beispiel #2
0
class TestJsonRelated2:
    @pytest.fixture(autouse=True)
    def transact(self, request, registry_json_related2):
        transaction = registry_json_related2.begin_nested()
        request.addfinalizer(transaction.rollback)
        return

    def test_field_json_related_get_4(self, registry_json_related2):
        registry = registry_json_related2
        t = registry.Test.insert(properties={'sub': {'name': 'jssuzanne'}})
        assert t.name == 'jssuzanne'

    def test_field_json_related_del_2(self, registry_json_related2):
        registry = registry_json_related2
        t = registry.Test.insert()
        del t.name
        assert t.name is None
        assert t.properties == {'sub': {'name': None}}

    def test_field_json_related_set_4(self, registry_json_related2):
        registry = registry_json_related2
        t = registry.Test.insert(properties={'sub': {'name': 'other'}})
        t.name = 'jssuzanne'
        assert t.properties == {'sub': {'name': 'jssuzanne'}}

    @pytest.mark.skipif(sgdb_in(['MariaDB', 'MsSQL']),
                        reason='JSON is not existing in this SGDB')
    def test_field_json_related_exp_4(self, registry_json_related2):
        registry = registry_json_related2
        Test = registry.Test
        Test.insert(properties={'sub': {'name': 'jssuzanne'}})
        query = registry.Test.query().filter(
            Test.name.cast(types.String) == '"jssuzanne"')
        assert query.count()
Beispiel #3
0
class TestSimpleView:

    @pytest.fixture(autouse=True)
    def transact(self, request, registry_simple_view):
        transaction = registry_simple_view.begin_nested()
        request.addfinalizer(transaction.rollback)

    def test_has_a_mapper(self, registry_simple_view):
        registry = registry_simple_view
        assert registry.TestView.__mapper__ is not None

    def test_ok(self, registry_simple_view):
        registry = registry_simple_view
        TestView = registry.TestView
        v1 = TestView.query().filter(TestView.code == 'test1').first()
        v2 = TestView.query().filter(TestView.code == 'test2').first()
        assert v1.val1 == 1
        assert v1.val2 == 2
        assert v2.val1 == 3
        assert v2.val2 == 4

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason="View must be in RO issue #95")
    def test_view_update_method(self, registry_simple_view):
        registry = registry_simple_view
        with pytest.raises(OperationalError):
            registry.TestView.query().update({'val2': 3})

    def test_view_delete_method(self, registry_simple_view):
        registry = registry_simple_view
        with pytest.raises((OperationalError, ProgrammingError)):
            registry.TestView.query().delete()
Beispiel #4
0
def add_in_registry():
    register = Declarations.register
    Model = Declarations.Model

    @register(Model)
    class Test:
        __db_schema__ = 'test_db_schema'

        integer = Int(primary_key=True)
        other = Str()

    @register(Model)
    class TestUnique:
        __db_schema__ = 'test_db_schema'

        integer = Int(primary_key=True)
        other = Str(unique=True)

    @register(Model)
    class TestIndex:
        __db_schema__ = 'test_db_schema'

        integer = Int(primary_key=True)
        other = Str(index=True)

    if not sgdb_in(['MySQL', 'MariaDB']):
        @register(Model)
        class TestCheck:
            __db_schema__ = 'test_db_schema'

            integer = Int(primary_key=True)

            @classmethod
            def define_table_args(cls):
                table_args = super(TestCheck, cls).define_table_args()
                return table_args + (
                    CheckConstraint('integer > 0', name='test'),)

    @register(Model)
    class TestFKTarget:
        __db_schema__ = 'test_db_schema'

        integer = Int(primary_key=True)

    @register(Model)
    class TestFK:
        __db_schema__ = 'test_db_schema'

        integer = Int(primary_key=True)
        other = Int(
            foreign_key=Model.TestFKTarget.use('integer'))

    @register(Model)
    class TestFK2:
        __db_schema__ = 'test_db_schema'

        integer = Int(primary_key=True)
        other = Int(
            foreign_key=Model.TestFKTarget.use('integer').options(
                ondelete='cascade'))
Beispiel #5
0
def reset_db():
    if sgdb_in(['MySQL', 'MariaDB']):
        url = Configuration.get('get_url')()
        if database_exists(url):
            drop_database(url)

        db_template_name = Configuration.get('db_template_name', None)
        create_database(url, template=db_template_name)
def clean_db(request, configuration_loaded):
    def clean():
        url = Configuration.get('get_url')()
        drop_database(url)
        db_template_name = Configuration.get('db_template_name', None)
        create_database(url, template=db_template_name)

    if sgdb_in(['MySQL', 'MariaDB']):
        clean()

    request.addfinalizer(clean)
Beispiel #7
0
def base_loaded(request, configuration_loaded):
    if sgdb_in(['MySQL', 'MariaDB']):
        return

    url = Configuration.get('get_url')()
    if not database_exists(url):
        db_template_name = Configuration.get('db_template_name', None)
        create_database(url, template=db_template_name)

    BlokManager.load()
    registry = init_registry_with_bloks([], None)
    registry.commit()
    registry.close()
    BlokManager.unload()
    def test_drop_schema(self, registry):
        schema = registry.migration.schema('test_db_schema')
        schema.table('test').drop()
        schema.table('testfk').drop()
        schema.table('testunique').drop()
        schema.table('testfk2').drop()
        schema.table('testfktarget').drop()
        schema.table('testindex').drop()
        if not sgdb_in(['MySQL', 'MariaDB']):
            schema.table('testcheck').drop()

        schema.drop()
        with pytest.raises(MigrationException):
            registry.migration.schema('test_db_schema')

        # MySQL waiting that this schema exist for the next test
        registry.migration.schema().add('test_db_schema')
    def test_detect_schema_added(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.TestFK.__table__.drop(bind=conn)
            registry.TestUnique.__table__.drop(bind=conn)
            registry.TestFK2.__table__.drop(bind=conn)
            registry.TestFKTarget.__table__.drop(bind=conn)
            registry.TestIndex.__table__.drop(bind=conn)
            if not sgdb_in(['MySQL', 'MariaDB']):
                registry.TestCheck.__table__.drop(bind=conn)

            conn.execute(DropSchema('test_db_schema'))

        report = registry.migration.detect_changed(schema_only=True)
        assert report.log_has("Add schema test_db_schema")
        report.apply_change()
        report = registry.migration.detect_changed(schema_only=True)
        assert not report.log_has("Add schema test_db_schema")
    def test_detect_drop_column_with_foreign_key(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            meta = MetaData(naming_convention=naming_convention)
            meta._add_table('system_blok', None,
                            registry.System.Blok.__table__)
            registry.Test.__table__ = Table(
                'test',
                meta,
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
                Column('other2', String(64), ForeignKey('system_blok.name')),
                schema='test_db_schema')
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        message = ("Drop Foreign keys on test.other2 => %ssystem_blok.name"
                   ) % ('dbo.' if sgdb_in(['MsSQL']) else '')
        assert report.log_has(message)
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not report.log_has(message)
class TestMigration:
    def test_detect_column_added_with_protected_table(self, registry):
        # Remove a column on the table force the detection to found new column
        # which is existing in metadata but not in table
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test', MetaData(), Column('integer',
                                           Integer,
                                           primary_key=True))
            registry.Test.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'test': True}
        report = registry.migration.detect_changed()
        assert not report.log_has("Add test.other")

    def test_detect_column_added_with_protected_column(self, registry):
        # Remove a column on the table force the detection to found new column
        # which is existing in metadata but not in table
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test', MetaData(), Column('integer',
                                           Integer,
                                           primary_key=True))
            registry.Test.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'test': ['other']}
        report = registry.migration.detect_changed()
        assert report.log_has("Add test.other")

    def test_detect_column_removed(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
                Column('other2', String(64)),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'test': True}
        report = registry.migration.detect_changed()
        assert not report.log_has("Drop Column test.other2")

    def test_detect_nullable_with_protected_table(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), nullable=False),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'test': True}
        report = registry.migration.detect_changed()
        assert not report.log_has("Alter test.other")

    def test_detect_nullable_with_protected_column(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), nullable=False),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'test': ['other']}
        report = registry.migration.detect_changed()
        assert not report.log_has("Alter test.other")

    def test_detect_server_default_with_protected_table(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), server_default='9.99'),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'test': True}
        report = registry.migration.detect_changed()
        assert not report.log_has("Alter test.other")

    def test_detect_server_default_with_protected_column(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), server_default='9.99'),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'test': ['other']}
        report = registry.migration.detect_changed()
        assert not report.log_has("Alter test.other")

    def test_detect_drop_anyblok_index(self, registry):
        with cnx(registry) as conn:
            conn.execute(
                """CREATE INDEX anyblok_ix_test__other ON test (other);""")

        registry.migration.ignore_migration_for = {'test': True}
        report = registry.migration.detect_changed()
        assert not report.log_has("Drop index anyblok_ix_test__other on test")

    def test_detect_type_with_protected_table(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', Integer),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'test': True}
        report = registry.migration.detect_changed()
        assert not report.log_has("Alter test.other")

    def test_detect_type_with_protected_column(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', Integer),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'test': ['other']}
        report = registry.migration.detect_changed()
        assert not report.log_has("Alter test.other")

    def test_detect_add_foreign_key_with_protected_table(self, registry):
        with cnx(registry) as conn:
            registry.TestFK.__table__.drop(bind=conn)
            registry.TestFK.__table__ = Table(
                'testfk',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', Integer),
            )
            registry.TestFK.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'testfk': True}
        report = registry.migration.detect_changed()
        assert not report.log_has(
            "Add Foreign keys on (testfk.other) => (testfktarget.integer)")

    def test_detect_add_foreign_key_with_protected_column(self, registry):
        with cnx(registry) as conn:
            registry.TestFK.__table__.drop(bind=conn)
            registry.TestFK.__table__ = Table(
                'testfk',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', Integer),
            )
            registry.TestFK.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'testfk': ['other']}
        report = registry.migration.detect_changed()
        assert not report.log_has(
            "Add Foreign keys on (testfk.other) => (testfktarget.integer)")

    def test_detect_drop_foreign_key_with_protected_table(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            meta = MetaData(naming_convention=naming_convention)
            meta._add_table('system_blok', None,
                            registry.System.Blok.__table__)
            registry.Test.__table__ = Table(
                'test',
                meta,
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), ForeignKey('system_blok.name')),
            )
            registry.Test.__table__.create(bind=conn)
            # anyblok_fk_test__other_on_system_blok__name

        registry.migration.ignore_migration_for = {'test': True}
        report = registry.migration.detect_changed()
        assert not report.log_has(
            "Drop Foreign keys on test.other => system_blok.name")

    def test_detect_drop_foreign_key_with_protected_column(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            meta = MetaData(naming_convention=naming_convention)
            meta._add_table('system_blok', None,
                            registry.System.Blok.__table__)
            registry.Test.__table__ = Table(
                'test',
                meta,
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), ForeignKey('system_blok.name')),
            )
            registry.Test.__table__.create(bind=conn)
            # anyblok_fk_test__other_on_system_blok__name

        registry.migration.ignore_migration_for = {'test': ['other']}
        report = registry.migration.detect_changed()
        assert not report.log_has(
            "Drop Foreign keys on test.other => system_blok.name")

    @pytest.mark.skipif(sgdb_in(['MsSQL']),
                        reason="MsSQL does not add unique #121")
    def test_detect_add_unique_constraint_with_protected_table(self, registry):
        with cnx(registry) as conn:
            registry.TestUnique.__table__.drop(bind=conn)
            registry.TestUnique.__table__ = Table(
                'testunique',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
            )
            registry.TestUnique.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'testunique': True}
        report = registry.migration.detect_changed()
        assert not report.log_has(
            "Add unique constraint on testunique (other)")

    @pytest.mark.skipif(sgdb_in(['MsSQL']),
                        reason="MsSQL does not add unique #121")
    def test_detect_add_unique_constraint_with_protected_column(
            self, registry):
        with cnx(registry) as conn:
            registry.TestUnique.__table__.drop(bind=conn)
            registry.TestUnique.__table__ = Table(
                'testunique',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
            )
            registry.TestUnique.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'testunique': ['other']}
        report = registry.migration.detect_changed()
        assert not report.log_has(
            "Add unique constraint on testunique (other)")

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="MySQL transform unique constraint on index")
    @pytest.mark.skipif(sgdb_in(['MsSQL']),
                        reason="MsSQL does not drop unique #121")
    def test_detect_drop_unique_anyblok_constraint(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(naming_convention=naming_convention),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), unique=True),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'test': True}
        report = registry.migration.detect_changed()
        assert not report.log_has(
            "Drop constraint anyblok_uq_test__other on test")

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason="No CheckConstraint works #90")
    def test_detect_add_check_constraint(self, registry):
        with cnx(registry) as conn:
            registry.TestCheck.__table__.drop(bind=conn)
            registry.TestCheck.__table__ = Table(
                'testcheck',
                MetaData(naming_convention=naming_convention),
                Column('integer', Integer, primary_key=True),
            )
            registry.TestCheck.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'testcheck': True}
        report = registry.migration.detect_changed()
        assert not report.log_has(
            "Add check constraint anyblok_ck_testcheck__test on testcheck")

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason="No CheckConstraint works #90")
    def test_detect_drop_check_anyblok_constraint(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test', MetaData(naming_convention=naming_convention),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
                CheckConstraint("other != 'test'", name='check'))
            registry.Test.__table__.create(bind=conn)

        registry.migration.ignore_migration_for = {'test': True}
        report = registry.migration.detect_changed()
        assert not report.log_has(
            "Drop check constraint anyblok_ck__test__check on test")
Beispiel #12
0
        view_with_relationship_on_self_2,
    ]
)
def registry_view_with_relationship_on_self(request, bloks_loaded):
    reset_db()
    registry = init_registry_with_bloks(
        [], request.param)
    request.addfinalizer(registry.close)
    parent = registry.T1.insert(code='test1', val=1)
    registry.T2.insert(code='test1', val=2)
    registry.T1.insert(code='test2', val=3, parent=parent)
    registry.T2.insert(code='test2', val=4)
    return registry


@pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']), reason="No sub query")
class TestViewWithRelationShipOnSelf:

    @pytest.fixture(autouse=True)
    def transact(self, request, registry_view_with_relationship_on_self):
        transaction = registry_view_with_relationship_on_self.begin_nested()
        request.addfinalizer(transaction.rollback)
        return

    def test_ok(self, registry_view_with_relationship_on_self):
        registry = registry_view_with_relationship_on_self
        TestView = registry.TestView
        v1 = TestView.query().filter(TestView.code == 'test1').first()
        v2 = TestView.query().filter(TestView.code == 'test2').first()
        assert v1.val1 == 1
        assert v1.val2 == 2
Beispiel #13
0
class TestColumns:

    @pytest.fixture(autouse=True)
    def close_registry(self, request, bloks_loaded):

        def close():
            if hasattr(self, 'registry'):
                self.registry.close()

        request.addfinalizer(close)

    def init_registry(self, *args, **kwargs):
        reset_db()
        self.registry = init_registry(*args, **kwargs)
        return self.registry

    def test_insert_columns(self, column_definition):
        column, value, kwargs = column_definition
        registry = self.init_registry(simple_column, ColumnType=column,
                                      **kwargs)
        test = registry.Test.insert(col=value)
        assert test.col == value

    def test_column_with_type_in_kwargs(self):
        self.init_registry(
            simple_column, ColumnType=Integer, type_=Integer)

    def test_column_with_db_column_name_in_kwargs(self):
        registry = self.init_registry(simple_column, ColumnType=Integer,
                                      db_column_name='another_name')
        test = registry.Test.insert(col=1)
        assert test.col == 1
        res = registry.execute('select id from test where another_name=1')
        assert res.fetchone()[0] == test.id

    def test_column_with_foreign_key(self):
        registry = self.init_registry(column_with_foreign_key)
        registry.Test.insert(name='test')
        registry.Test2.insert(test='test')

    def test_column_with_foreign_key_with_schema(self, db_schema):
        registry = self.init_registry(column_with_foreign_key_with_schema)
        registry.Test.insert(name='test')
        registry.Test2.insert(test='test')

    def test_column_with_foreign_key_with_diff_schema1(self, db_schema):
        registry = self.init_registry(column_with_foreign_key_with_diff_schema1)
        registry.Test.insert(name='test')
        registry.Test2.insert(test='test')

    def test_column_with_foreign_key_with_diff_schema2(self, db_schema):
        registry = self.init_registry(column_with_foreign_key_with_diff_schema2)
        registry.Test.insert(name='test')
        registry.Test2.insert(test='test')

    def test_integer_str_foreign_key(self):
        registry = self.init_registry(
            simple_column, ColumnType=Integer, foreign_key='Model.Test=>id')
        test = registry.Test.insert()
        test2 = registry.Test.insert(col=test.id)
        assert test2.col == test.id

    def test_setter_decimal(self):
        registry = self.init_registry(simple_column, ColumnType=Decimal)
        test = registry.Test.insert()
        test.col = '1.0'
        assert test.col == D('1.0')

    def test_boolean_with_default(self):
        registry = self.init_registry(simple_column, ColumnType=Boolean,
                                      default=False)
        test = registry.Test.insert()
        assert test.col is False

    def test_string_with_False(self):
        registry = self.init_registry(simple_column, ColumnType=String)
        test = registry.Test.insert(col=False)
        assert test.col is False
        self.registry.flush()
        self.registry.expire(test, ['col'])
        assert test.col == ''

    def test_string_set_False(self):
        registry = self.init_registry(simple_column, ColumnType=String)
        test = registry.Test.insert()
        test.col = False
        assert test.col is False
        self.registry.flush()
        self.registry.expire(test, ['col'])
        assert test.col == ''

    def test_string_query_False(self):
        registry = self.init_registry(simple_column, ColumnType=String)
        test = registry.Test.insert()
        self.registry.Test.query().filter_by(id=test.id).update({'col': False})
        assert test.col is False
        self.registry.expire(test, ['col'])
        assert test.col == ''

    @pytest.mark.skipif(not has_cryptography,
                        reason="cryptography is not installed")
    def test_string_with_encrypt_key_defined_by_configuration(self):
        Configuration.set('default_encrypt_key', 'secretkey')
        registry = self.init_registry(simple_column, ColumnType=String,
                                      encrypt_key=True)
        test = registry.Test.insert(col='col')
        registry.session.commit()
        assert test.col == 'col'
        res = registry.execute('select col from test where id = %s' % test.id)
        res = res.fetchall()[0][0]
        assert res != 'col'
        del Configuration.configuration['default_encrypt_key']

    def test_string_with_size(self):
        registry = self.init_registry(
            simple_column, ColumnType=String, size=100)
        test = registry.Test.insert(col='col')
        assert test.col == 'col'

    @pytest.mark.skipif(not has_passlib,
                        reason="passlib is not installed")
    def test_password(self):
        registry = self.init_registry(simple_column, ColumnType=Password,
                                      crypt_context={'schemes': ['md5_crypt']})
        test = registry.Test.insert(col='col')
        assert test.col == 'col'
        assert registry.execute('Select col from test').fetchone()[0] != 'col'

    def test_text_with_False(self):
        registry = self.init_registry(simple_column, ColumnType=Text)
        test = registry.Test.insert(col=False)
        assert test.col is False
        self.registry.flush()
        self.registry.expire(test, ['col'])
        assert test.col == ''

    def test_text_set_False(self):
        registry = self.init_registry(simple_column, ColumnType=Text)
        test = registry.Test.insert()
        test.col = False
        assert test.col is False
        self.registry.flush()
        self.registry.expire(test, ['col'])
        assert test.col == ''

    def test_text_query_False(self):
        registry = self.init_registry(simple_column, ColumnType=Text)
        test = registry.Test.insert()
        self.registry.Test.query().filter_by(id=test.id).update({'col': False})
        assert test.col is False
        self.registry.expire(test, ['col'])
        assert test.col == ''

    def test_datetime_none_value(self, dt_column_type):
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert(col=None)
        assert test.col is None

    def test_datetime_str_conversion_1(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = datetime.datetime.now().replace(tzinfo=timezone)
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert(col=now.strftime('%Y-%m-%d %H:%M:%S.%f%z'))
        assert test.col == now

    def test_datetime_str_conversion_2(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = timezone.localize(datetime.datetime.now())
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert(col=now.strftime('%Y-%m-%d %H:%M:%S.%f%Z'))
        assert test.col == now

    def test_datetime_str_conversion_3(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = timezone.localize(datetime.datetime.now())
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert(col=now.strftime('%Y-%m-%d %H:%M:%S.%f'))
        assert test.col == now

    def test_datetime_str_conversion_4(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = timezone.localize(datetime.datetime.now())
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert(col=now.strftime('%Y-%m-%d %H:%M:%S'))
        assert test.col == now.replace(microsecond=0)

    def test_datetime_by_property(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = datetime.datetime.now().replace(tzinfo=timezone)
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert()
        test.col = now
        assert test.col == now

    def test_datetime_by_property_none_value(self, dt_column_type):
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert()
        test.col = None
        assert test.col is None

    def test_datetime_str_conversion_1_by_property(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = datetime.datetime.now().replace(tzinfo=timezone)
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert()
        test.col = now.strftime('%Y-%m-%d %H:%M:%S.%f%z')
        assert test.col == now

    def test_datetime_str_conversion_2_by_property(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = timezone.localize(datetime.datetime.now())
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert()
        test.col = now.strftime('%Y-%m-%d %H:%M:%S.%f%Z')
        assert test.col == now

    def test_datetime_str_conversion_3_by_property(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = timezone.localize(datetime.datetime.now())
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert()
        test.col = now.strftime('%Y-%m-%d %H:%M:%S.%f')
        assert test.col == now

    def test_datetime_str_conversion_4_by_property(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = timezone.localize(datetime.datetime.now())
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert()
        test.col = now.strftime('%Y-%m-%d %H:%M:%S')
        assert test.col == now.replace(microsecond=0)

    def test_datetime_by_query(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = datetime.datetime.now().replace(tzinfo=timezone)
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert()
        registry.Test.query().update(dict(col=now))
        assert test.col == now

    def test_datetime_by_query_none_value(self, dt_column_type):
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert()
        registry.Test.query().update(dict(col=None))
        assert test.col is None

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason='ISSUE #87')
    def test_datetime_str_conversion_1_by_query(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = datetime.datetime.now().replace(tzinfo=timezone)
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert()
        registry.Test.query().update(
            dict(col=now.strftime('%Y-%m-%d %H:%M:%S.%f%z')))
        registry.expire(test, ['col'])
        assert test.col == now

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason='ISSUE #87')
    def test_datetime_str_conversion_2_by_query(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = timezone.localize(datetime.datetime.now())
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert()
        registry.Test.query().update(
            dict(col=now.strftime('%Y-%m-%d %H:%M:%S.%f%Z')))
        registry.expire(test, ['col'])
        assert test.col == now

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason='ISSUE #87')
    def test_datetime_str_conversion_3_by_query(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = timezone.localize(datetime.datetime.now())
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert()
        registry.Test.query().update(
            dict(col=now.strftime('%Y-%m-%d %H:%M:%S.%f')))
        registry.expire(test, ['col'])
        assert test.col == now

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason='ISSUE #87')
    def test_datetime_str_conversion_4_by_query(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = timezone.localize(datetime.datetime.now())
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert()
        registry.Test.query().update(
            dict(col=now.strftime('%Y-%m-%d %H:%M:%S')))
        registry.expire(test, ['col'])
        assert test.col == now.replace(microsecond=0)

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason='ISSUE #87')
    def test_datetime_by_query_filter(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = datetime.datetime.now().replace(tzinfo=timezone)
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert(col=now)
        Test = registry.Test
        assert Test.query().filter(Test.col == now).one() is test

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason='ISSUE #87')
    def test_datetime_str_conversion_1_by_query_filter(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = datetime.datetime.now().replace(tzinfo=timezone)
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert(col=now)
        Test = registry.Test
        assert Test.query().filter(
            Test.col == now.strftime('%Y-%m-%d %H:%M:%S.%f%z')).one() is test

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason='ISSUE #87')
    def test_datetime_str_conversion_2_by_query_filter(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = timezone.localize(datetime.datetime.now())
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert(col=now)
        Test = registry.Test
        assert Test.query().filter(
            Test.col == now.strftime('%Y-%m-%d %H:%M:%S.%f%Z')).one() is test

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason='ISSUE #87')
    def test_datetime_str_conversion_3_by_query_filter(self, dt_column_type):
        timezone = pytz.timezone(time.tzname[0])
        now = timezone.localize(datetime.datetime.now())
        registry = self.init_registry(simple_column, ColumnType=dt_column_type)
        test = registry.Test.insert(col=now)
        Test = registry.Test
        assert Test.query().filter(
            Test.col == now.strftime('%Y-%m-%d %H:%M:%S.%f')).one() is test

    def test_datetime_without_auto_update_1(self, dt_column_type):

        def add_in_registry():

            from anyblok import Declarations

            @Declarations.register(Declarations.Model)
            class Test:
                id = Integer(primary_key=True)
                update_at = DateTime()
                val = String()

        registry = self.init_registry(add_in_registry)
        test = registry.Test.insert(val='first add')
        assert test.update_at is None
        test.val = 'other'
        registry.flush()
        assert test.update_at is None

    def test_datetime_without_auto_update_2(self, dt_column_type):

        def add_in_registry():

            from anyblok import Declarations

            @Declarations.register(Declarations.Model)
            class Test:
                id = Integer(primary_key=True)
                update_at = DateTime(auto_update=False)
                val = String()

        registry = self.init_registry(add_in_registry)
        test = registry.Test.insert(val='first add')
        assert test.update_at is None
        test.val = 'other'
        registry.flush()
        assert test.update_at is None

    def test_datetime_with_auto_update(self, dt_column_type):

        def add_in_registry():

            from anyblok import Declarations

            @Declarations.register(Declarations.Model)
            class Test:
                id = Integer(primary_key=True)
                update_at = DateTime(auto_update=True)
                val = String()

        registry = self.init_registry(add_in_registry)
        test = registry.Test.insert(val='first add')
        assert test.update_at is None
        test.val = 'other'
        registry.flush()
        assert test.update_at is not None

    def test_datetime_with_default_timezone_tz(self, dt_column_type):
        import datetime
        import pytz

        timezone = pytz.timezone('Asia/Tokyo')
        now = datetime.datetime.now()
        registry = self.init_registry(
            simple_column, ColumnType=dt_column_type,
            default_timezone=timezone)
        field = registry.loaded_namespaces_first_step['Model.Test']['col']
        assert field.default_timezone is timezone

        test = registry.Test.insert(col=now)
        assert test.col.tzinfo.zone is timezone.zone

    def test_datetime_with_default_timezone_str(self, dt_column_type):
        import datetime
        import pytz

        timezone = pytz.timezone('Asia/Tokyo')
        now = datetime.datetime.now()
        registry = self.init_registry(
            simple_column, ColumnType=dt_column_type,
            default_timezone='Asia/Tokyo')
        field = registry.loaded_namespaces_first_step['Model.Test']['col']
        assert field.default_timezone == timezone

        test = registry.Test.insert(col=now)
        assert test.col.tzinfo.zone == timezone.zone

    def test_datetime_with_default_global_timezone_str(self, dt_column_type):
        import datetime
        import pytz

        timezone = pytz.timezone('Asia/Tokyo')
        now = datetime.datetime.now()
        with tmp_configuration(default_timezone='Asia/Tokyo'):
            registry = self.init_registry(simple_column,
                                          ColumnType=dt_column_type)

        field = registry.loaded_namespaces_first_step['Model.Test']['col']
        assert field.default_timezone is timezone

        test = registry.Test.insert(col=now)
        assert test.col.tzinfo.zone is timezone.zone

    def test_selection(self):
        SELECTIONS = [
            ('admin', 'Admin'),
            ('regular-user', 'Regular user')
        ]

        registry = self.init_registry(
            simple_column, ColumnType=Selection, selections=SELECTIONS)
        test = registry.Test.insert(col=SELECTIONS[0][0])
        assert test.col == SELECTIONS[0][0]
        assert test.col.label == SELECTIONS[0][1]
        test = registry.Test.query().first()
        assert test.col == SELECTIONS[0][0]
        assert test.col.label == SELECTIONS[0][1]
        with pytest.raises(FieldException):
            test.col = 'bad value'

    def test_selection_with_only_one_value(self):
        SELECTIONS = [
            ('admin', 'Admin'),
        ]

        registry = self.init_registry(
            simple_column, ColumnType=Selection, selections=SELECTIONS)
        test = registry.Test.insert(col=SELECTIONS[0][0])
        assert test.col == SELECTIONS[0][0]
        assert test.col.label == SELECTIONS[0][1]
        test = registry.Test.query().first()
        assert test.col == SELECTIONS[0][0]
        assert test.col.label == SELECTIONS[0][1]
        with pytest.raises(FieldException):
            test.col = 'bad value'

    def test_selection_without_value(self):
        self.init_registry(simple_column, ColumnType=Selection, selections=[])

    def test_selection_autodoc(self):
        SELECTIONS = [
            ('admin', 'Admin'),
        ]

        registry = self.init_registry(
            simple_column, ColumnType=Selection, selections=SELECTIONS)
        column = registry.System.Column.query().filter_by(
            model='Model.Test', name='col').one()
        assert column._description() == {
                'id': 'col',
                'label': 'Col',
                'model': None,
                'nullable': True,
                'primary_key': False,
                'selections': [
                    ('admin', 'Admin'),
                ],
                'type': 'Selection',
            }

    def test_selection_with_none_value(self):
        SELECTIONS = [
            ('admin', 'Admin'),
            ('regular-user', 'Regular user')
        ]

        registry = self.init_registry(
            simple_column, ColumnType=Selection, selections=SELECTIONS)
        t = registry.Test.insert()
        assert t.col is None

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason='ISSUE #90')
    def test_selection_change_by_query(self):
        SELECTIONS = [
            ('admin', 'Admin'),
            ('regular-user', 'Regular user')
        ]

        registry = self.init_registry(
            simple_column, ColumnType=Selection, selections=SELECTIONS)
        registry.Test.insert(col=SELECTIONS[0][0])
        with pytest.raises(StatementError):
            registry.Test.query().update({'col': 'bad value'})

    def test_selection_like_comparator(self):
        SELECTIONS = [
            ('admin', 'Admin'),
            ('regular-user', 'Regular user')
        ]

        registry = self.init_registry(
            simple_column, ColumnType=Selection, selections=SELECTIONS)
        Test = registry.Test
        t = Test.insert(col=SELECTIONS[0][0])
        t1 = Test.query().filter(Test.col.like('%admin%')).one()
        assert t is t1

    def test_selection_key_other_than_str(self):
        SELECTIONS = [
            (0, 'Admin'),
            (1, 'Regular user')
        ]

        with pytest.raises(FieldException):
            self.init_registry(
                simple_column, ColumnType=Selection, selections=SELECTIONS)

    def test_selection_comparator(self):
        SELECTIONS = [
            ('admin', 'Admin'),
            ('regular-user', 'Regular user')
        ]

        registry = self.init_registry(
            simple_column, ColumnType=Selection, selections=SELECTIONS)
        registry.Test.insert(col=SELECTIONS[0][0])
        registry.Test.query().filter(
            registry.Test.col.in_(['admin', 'regular-user'])).first()

    def test_selection_use_method(self):
        SELECTIONS = [
            ('admin', 'Admin'),
            ('regular-user', 'Regular user')
        ]

        def add_selection():

            @register(Model)
            class Test:

                id = Integer(primary_key=True)
                col = Selection(selections='get_selection')

                @classmethod
                def get_selection(cls):
                    return SELECTIONS

        registry = self.init_registry(add_selection)
        registry.Test.insert(col=SELECTIONS[0][0])
        registry.Test.query().filter(
            registry.Test.col.in_(['admin', 'regular-user'])).first()

    def test_json_update(self):
        registry = self.init_registry(simple_column, ColumnType=Json)
        test = registry.Test.insert(col={'a': 'test'})
        test.col['b'] = 'test'
        assert test.col == {'a': 'test', 'b': 'test'}

    @pytest.mark.skipif(sgdb_in(['MariaDB', 'MsSQL']),
                        reason='JSON is not existing in this SGDB')
    def test_json_simple_filter(self):
        registry = self.init_registry(simple_column, ColumnType=Json)
        Test = registry.Test
        Test.insert(col={'a': 'test'})
        Test.insert(col={'a': 'test'})
        Test.insert(col={'b': 'test'})
        assert Test.query().filter(
            Test.col['a'].cast(SA_String) == '"test"').count() == 2

    def test_json_null(self):
        registry = self.init_registry(simple_column, ColumnType=Json)
        Test = registry.Test
        Test.insert(col=None)
        Test.insert(col=None)
        Test.insert(col={'a': 'test'})
        assert Test.query().filter(Test.col.is_(None)).count() == 2
        assert Test.query().filter(Test.col.isnot(None)).count() == 1

    def test_add_default_classmethod(self):
        val = 'test'

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True)
                val = String(default="get_val")

                @classmethod
                def get_val(cls):
                    return val

        registry = self.init_registry(add_in_registry)
        t = registry.Test.insert()
        assert t.val == val

    def test_add_default_without_classmethod(self):
        value = 'test'

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True)
                val = String(default="get_val")

                def get_val(cls):
                    return value

        registry = self.init_registry(add_in_registry)
        t = registry.Test.insert()
        assert t.val == "get_val"

    def test_add_default_by_var(self):
        value = 'test'

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True)
                val = String(default=value)

        registry = self.init_registry(add_in_registry)
        t = registry.Test.insert()
        assert t.val == value

    def test_add_default(self):

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True)
                val = String(default='value')

        registry = self.init_registry(add_in_registry)
        t = registry.Test.insert()
        assert t.val == 'value'

    def test_add_field_as_default(self):

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True)
                val = String(default='val')

        registry = self.init_registry(add_in_registry)
        t = registry.Test.insert()
        assert t.val == 'val'

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason='ISSUE #89')
    def test_sequence(self):
        registry = self.init_registry(simple_column, ColumnType=Sequence)
        assert registry.Test.insert().col == "1"
        assert registry.Test.insert().col == "2"
        assert registry.Test.insert().col == "3"
        assert registry.Test.insert().col == "4"
        Seq = registry.System.Sequence
        assert Seq.query().filter(Seq.code == 'Model.Test=>col').count() == 1

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason='ISSUE #89')
    def test_sequence_with_primary_key(self):
        registry = self.init_registry(simple_column, ColumnType=Sequence,
                                      primary_key=True)
        assert registry.Test.insert().col == "1"
        assert registry.Test.insert().col == "2"

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason='ISSUE #89')
    def test_sequence_with_code_and_formater(self):
        registry = self.init_registry(simple_column, ColumnType=Sequence,
                                      code="SO", formater="{code}-{seq:06d}")
        assert registry.Test.insert().col == "SO-000001"
        assert registry.Test.insert().col == "SO-000002"
        assert registry.Test.insert().col == "SO-000003"
        assert registry.Test.insert().col == "SO-000004"
        Seq = registry.System.Sequence
        assert Seq.query().filter(Seq.code == 'SO').count() == 1

    def test_sequence_with_foreign_key(self):
        with pytest.raises(FieldException):
            self.init_registry(simple_column, ColumnType=Sequence,
                               foreign_key=Model.System.Model.use('name'))

    def test_sequence_with_default(self):
        with pytest.raises(FieldException):
            self.init_registry(simple_column, ColumnType=Sequence,
                               default='default value')

    @pytest.mark.skipif(not has_colour,
                        reason="colour is not installed")
    def test_color(self):
        color = '#F5F5F5'
        registry = self.init_registry(simple_column, ColumnType=Color)
        test = registry.Test.insert(col=color)
        assert test.col.hex == colour.Color(color).hex

    @pytest.mark.skipif(not has_colour,
                        reason="colour is not installed")
    def test_setter_color(self):
        color = '#F5F5F5'
        registry = self.init_registry(simple_column, ColumnType=Color)
        test = registry.Test.insert()
        test.col = color
        assert test.col.hex == colour.Color(color).hex

    def test_uuid_binary_3(self):
        from uuid import uuid3, NAMESPACE_DNS
        uuid = uuid3(NAMESPACE_DNS, 'python.org')
        registry = self.init_registry(simple_column, ColumnType=UUID)
        test = registry.Test.insert(col=uuid)
        assert test.col is uuid

    def test_uuid_binary_4(self):
        from uuid import uuid4
        uuid = uuid4()
        registry = self.init_registry(simple_column, ColumnType=UUID)
        test = registry.Test.insert(col=uuid)
        assert test.col is uuid

    def test_uuid_binary_5(self):
        from uuid import uuid5, NAMESPACE_DNS
        uuid = uuid5(NAMESPACE_DNS, 'python.org')
        registry = self.init_registry(simple_column, ColumnType=UUID)
        test = registry.Test.insert(col=uuid)
        assert test.col is uuid

    def test_uuid_char32(self):
        uuid = uuid1()
        registry = self.init_registry(simple_column, ColumnType=UUID,
                                      binary=False)
        test = registry.Test.insert(col=uuid)
        assert test.col is uuid

    @pytest.mark.skipif(not has_furl, reason="furl is not installed")
    def test_setter_URL(self):
        f = 'http://doc.anyblok.org'
        registry = self.init_registry(simple_column, ColumnType=URL)
        test = registry.Test.insert()
        test.col = f
        assert test.col.url == f

    @pytest.mark.skipif(not has_furl, reason="furl is not installed")
    def test_URL_2(self):
        f = 'http://doc.anyblok.org'
        registry = self.init_registry(simple_column, ColumnType=URL)
        test = registry.Test.insert(col=f)
        assert test.col.url == f

    @pytest.mark.skipif(not has_furl, reason="furl is not installed")
    def test_URL_3(self):
        f = 'http://doc.anyblok.org'
        registry = self.init_registry(simple_column, ColumnType=URL)
        registry.Test.insert(col=f)
        Test = registry.Test
        test = Test.query().filter(Test.col == f).one()
        assert test.col.url == f

    @pytest.mark.skipif(not has_furl, reason="furl is not installed")
    def test_URL_4(self):
        f = furl.furl('http://doc.anyblok.org')
        registry = self.init_registry(simple_column, ColumnType=URL)
        registry.Test.insert(col=f)
        Test = registry.Test
        test = Test.query().filter(Test.col == f).one()
        assert test.col.url == f.url

    @pytest.mark.skipif(not has_phonenumbers,
                        reason="phonenumbers is not installed")
    def test_phonenumbers_at_insert(self):
        registry = self.init_registry(simple_column, ColumnType=PhoneNumber)
        test = registry.Test.insert(col='+120012301')
        assert test.col.national == '20012301'
        getted = registry.execute('Select col from test').fetchone()[0]
        assert getted == '+120012301'

    @pytest.mark.skipif(not has_phonenumbers,
                        reason="phonenumbers is not installed")
    def test_phonenumbers_at_setter(self):
        registry = self.init_registry(simple_column, ColumnType=PhoneNumber)
        test = registry.Test.insert()
        test.col = '+120012301'
        assert test.col.national == '20012301'
        registry.flush()
        getted = registry.execute('Select col from test').fetchone()[0]
        assert getted == '+120012301'

    @pytest.mark.skipif(not has_phonenumbers,
                        reason="phonenumbers is not installed")
    def test_phonenumbers_obj_at_insert(self):
        registry = self.init_registry(simple_column, ColumnType=PhoneNumber)
        col = PN("+120012301", None)
        test = registry.Test.insert(col=col)
        assert test.col == col
        getted = registry.execute('Select col from test').fetchone()[0]
        assert getted == '+120012301'

    @pytest.mark.skipif(not has_phonenumbers,
                        reason="phonenumbers is not installed")
    def test_phonenumbers_obj_at_setter(self):
        registry = self.init_registry(simple_column, ColumnType=PhoneNumber)
        test = registry.Test.insert()
        test.col = PN("+120012301", None)
        assert test.col.national == '20012301'
        registry.flush()
        getted = registry.execute('Select col from test').fetchone()[0]
        assert getted == '+120012301'

    @pytest.mark.skipif(not has_phonenumbers,
                        reason="phonenumbers is not installed")
    def test_phonenumbers_obj_at_setter_with_empty_value(self):
        registry = self.init_registry(simple_column, ColumnType=PhoneNumber)
        test = registry.Test.insert()
        test.col = ""
        assert test.col == ''
        registry.flush()
        assert registry.execute('Select col from test').fetchone()[0] == ''

    def test_email_at_setter(self):
        registry = self.init_registry(simple_column, ColumnType=Email)
        test = registry.Test.insert()
        test.col = '*****@*****.**'
        assert test.col == '*****@*****.**'
        assert registry.Test.query().filter_by(
            col='*****@*****.**').count() == 1

    @pytest.mark.skipif(not has_pycountry, reason="pycountry is not installed")
    def test_pycoundtry_at_insert(self):
        registry = self.init_registry(simple_column, ColumnType=Country)
        test = registry.Test.insert(col='FR')
        assert test.col is pycountry.countries.get(alpha_2='FR')
        assert test.col.name == 'France'
        assert registry.execute('Select col from test').fetchone()[0] == 'FRA'

    @pytest.mark.skipif(not has_pycountry, reason="pycountry is not installed")
    def test_pycoundtry_at_insert_with_alpha_3(self):
        registry = self.init_registry(
            simple_column, ColumnType=Country, mode='alpha_3')
        test = registry.Test.insert(col='FRA')
        assert test.col is pycountry.countries.get(alpha_2='FR')
        assert test.col.name == 'France'
        assert registry.execute('Select col from test').fetchone()[0] == 'FRA'

    @pytest.mark.skipif(not has_pycountry, reason="pycountry is not installed")
    def test_pycoundtry_at_insert_with_object(self):
        registry = self.init_registry(simple_column, ColumnType=Country)
        fr = pycountry.countries.get(alpha_2='FR')
        test = registry.Test.insert(col=fr)
        assert test.col is fr
        assert test.col.name == 'France'
        assert registry.execute('Select col from test').fetchone()[0] == 'FRA'

    @pytest.mark.skipif(not has_pycountry, reason="pycountry is not installed")
    def test_pycoundtry_at_update(self):
        registry = self.init_registry(simple_column, ColumnType=Country)
        test = registry.Test.insert()
        test.col = 'FR'
        registry.flush()
        assert test.col is pycountry.countries.get(alpha_2='FR')
        assert test.col.name == 'France'
        assert registry.execute('Select col from test').fetchone()[0] == 'FRA'

    @pytest.mark.skipif(not has_pycountry, reason="pycountry is not installed")
    def test_pycoundtry_at_update_with_alpha_3(self):
        registry = self.init_registry(
            simple_column, ColumnType=Country, mode='alpha_3')
        test = registry.Test.insert()
        test.col = 'FRA'
        registry.flush()
        assert test.col is pycountry.countries.get(alpha_2='FR')
        assert test.col.name == 'France'
        assert registry.execute('Select col from test').fetchone()[0] == 'FRA'

    @pytest.mark.skipif(not has_pycountry, reason="pycountry is not installed")
    def test_pycoundtry_at_update_with_object(self):
        registry = self.init_registry(simple_column, ColumnType=Country)
        fr = pycountry.countries.get(alpha_2='FR')
        test = registry.Test.insert()
        test.col = fr
        registry.flush()
        assert test.col is fr
        assert test.col.name == 'France'
        assert registry.execute('Select col from test').fetchone()[0] == 'FRA'

    @pytest.mark.skipif(not has_pycountry, reason="pycountry is not installed")
    def test_pycoundtry_query_is_with_object(self):
        registry = self.init_registry(simple_column, ColumnType=Country)
        Test = registry.Test
        fr = pycountry.countries.get(alpha_2='FR')
        Test.insert(col='FR')
        assert Test.query().filter(Test.col == fr).count() == 1

    @pytest.mark.skipif(not has_pycountry, reason="pycountry is not installed")
    def test_pycoundtry_query_is_with_alpha_3(self):
        registry = self.init_registry(simple_column, ColumnType=Country)
        Test = registry.Test
        Test.insert(col='FR')
        assert Test.query().filter(Test.col == 'FRA').count() == 1

    @pytest.mark.skipif(not has_pycountry, reason="pycountry is not installed")
    def test_pycoundtry_query_insert_wrong(self):
        registry = self.init_registry(simple_column, ColumnType=Country)
        with pytest.raises(LookupError):
            registry.Test.insert(col='WG')

    @pytest.mark.skipif(not has_pycountry, reason="pycountry is not installed")
    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason='ISSUE #90')
    def test_pycoundtry_query_insert_by_wrong_query(self):
        registry = self.init_registry(simple_column, ColumnType=Country)
        with pytest.raises(Exception):
            registry.execute("insert into test (col) values ('WG2')")

    @pytest.mark.skipif(not has_cryptography,
                        reason="cryptography is not installed")
    def test_insert_encrypt_key_columns(self, column_definition):
        column, value, kwargs = column_definition
        registry = self.init_registry(simple_column, ColumnType=column,
                                      encrypt_key='secretkey', **kwargs)
        test = registry.Test.insert(col=value)
        registry.session.commit()
        assert test.col == value
        res = registry.execute('select col from test where id = %s' % test.id)
        res = res.fetchall()[0][0]
        assert res != test.col

    def test_foreign_key_on_mapper_issue_112(self):

        def add_in_registry():

            @Declarations.register(Declarations.Model)
            class Template:
                code = String(primary_key=True, db_column_name='ProductId')

            @Declarations.register(Declarations.Model)
            class Item:
                id = Integer(primary_key=True, db_column_name='ProductDetailId')
                template_code = String(
                    db_column_name='ProductId',
                    foreign_key=Model.Template.use('code'))

        registry = self.init_registry(add_in_registry)
        registry.Template.insert(code='test')
        registry.Item.insert(template_code='test')

        with pytest.raises(Exception):
            registry.Item.insert(template_code='other')

    def test_foreign_key_on_mapper_issue_112_with_schema(self, db_schema):

        def add_in_registry():

            @Declarations.register(Declarations.Model)
            class Template:
                __db_schema__ = 'test_db_column_schema'

                code = String(primary_key=True, db_column_name='ProductId')

            @Declarations.register(Declarations.Model)
            class Item:
                __db_schema__ = 'test_db_column_schema'

                id = Integer(primary_key=True, db_column_name='ProductDetailId')
                template_code = String(
                    db_column_name='ProductId',
                    foreign_key=Model.Template.use('code'))

        registry = self.init_registry(add_in_registry)
        registry.Template.insert(code='test')
        registry.Item.insert(template_code='test')

        with pytest.raises(Exception):
            registry.Item.insert(template_code='other')
Beispiel #14
0
from anyblok.config import Configuration
from anyblok.testing import tmp_configuration
from sqlalchemy import Integer as SA_Integer, String as SA_String
from sqlalchemy.exc import StatementError
from anyblok import Declarations
from anyblok.field import FieldException
from .conftest import init_registry, reset_db
from anyblok.column import (
    Column, Boolean, Json, String, BigInteger, Text, Selection, Date, DateTime,
    Time, Interval, Decimal, Float, LargeBinary, Integer, Sequence, Color,
    Password, UUID, URL, PhoneNumber, Email, Country, TimeStamp)


time_params = [DateTime]

if not sgdb_in(['MsSQL']):
    time_params.append(TimeStamp)


@pytest.fixture(params=time_params)
def dt_column_type(request):
    return request.param


COLUMNS = [
    (Selection, 'test', {'selections': {'test': 'test'}}),
    (Boolean, True, {}),
    (Boolean, False, {}),
    (String, 'test', {}),
    (BigInteger, 1, {}),
    (Text, 'Test', {}),
# This file is a part of the AnyBlok project
#
#    Copyright (C) 2015 Jean-Sebastien SUZANNE <*****@*****.**>
#    Copyright (C) 2020 Jean-Sebastien SUZANNE <*****@*****.**>
#
# This Source Code Form is subject to the terms of the Mozilla Public License,
# v. 2.0. If a copy of the MPL was not distributed with this file,You can
# obtain one at http://mozilla.org/MPL/2.0/.
import pytest
from anyblok.testing import sgdb_in


@pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']), reason='ISSUE #89')
@pytest.mark.usefixtures('rollback_registry')
class TestSystemSequence:
    def test_nextval_without_prefix_without_suffix(self, rollback_registry):
        registry = rollback_registry
        Sequence = registry.System.Sequence
        seq = Sequence.insert(code='test.sequence')
        assert seq.current is None
        assert seq.nextval() == '1'
        assert seq.nextval() == '2'
        assert seq.nextval() == '3'
        assert seq.current == 3

    def test_nextval_with_start_value(self, rollback_registry):
        registry = rollback_registry
        Sequence = registry.System.Sequence
        seq = Sequence.insert(code='test.sequence', start=10)
        assert seq.current is None
        assert seq.nextval() == '10'
class TestMigrationDbSchema:
    def test_add_schema(self, registry):
        registry.migration.schema().add('other_schema')
        registry.migration.schema('other_schema')
        registry.migration.schema('other_schema').drop()

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason="Can't create empty table")
    def test_add_table_from_schema(self, registry):
        schema = registry.migration.schema('test_db_schema')
        schema.table().add('test2')
        table = schema.table('test2')
        assert table.schema == 'test_db_schema'

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason="Can't create empty table")
    def test_add_table(self, registry):
        registry.migration.table(schema='test_db_schema').add('test2')
        table = registry.migration.table('test2', schema='test_db_schema')
        assert table.schema == 'test_db_schema'

    def test_add_column(self, registry):
        t = registry.migration.table('test', schema='test_db_schema')
        t.column().add(Column('new_column', Integer))
        t.column('new_column')

    def test_add_unique_constraint(self, registry):
        t = registry.migration.table('test', schema='test_db_schema')
        t.unique('unique_constraint').add(t.column('other'))
        registry.Test.insert(other='One entry')
        with pytest.raises(IntegrityError):
            registry.Test.insert(other='One entry')

    def test_drop_schema(self, registry):
        schema = registry.migration.schema('test_db_schema')
        schema.table('test').drop()
        schema.table('testfk').drop()
        schema.table('testunique').drop()
        schema.table('testfk2').drop()
        schema.table('testfktarget').drop()
        schema.table('testindex').drop()
        if not sgdb_in(['MySQL', 'MariaDB']):
            schema.table('testcheck').drop()

        schema.drop()
        with pytest.raises(MigrationException):
            registry.migration.schema('test_db_schema')

        # MySQL waiting that this schema exist for the next test
        registry.migration.schema().add('test_db_schema')

    def test_drop_table(self, registry):
        registry.migration.table('test', schema='test_db_schema').drop()
        with pytest.raises(MigrationException):
            registry.migration.table('Test', schema='test_db_schema')

    def test_drop_column(self, registry):
        t = registry.migration.table('test', schema='test_db_schema')
        t.column('other').drop()
        with pytest.raises(MigrationException):
            t.column('other')

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason="Can't rename schema #122")
    def test_alter_schema_name(self, registry):
        registry.migration.schema('test_db_schema').alter(name='test_db_other')
        with pytest.raises(MigrationException):
            registry.migration.schema('test_db_schema')

        registry.migration.schema('test_db_other')
        registry.migration.schema('test_db_other').table('test')

    def test_alter_table_name(self, registry):
        t = registry.migration.table('test', schema='test_db_schema')
        t.alter(name='othername')
        registry.migration.table('othername', schema='test_db_schema')
        with pytest.raises(MigrationException):
            registry.migration.table('test')

    def test_alter_column_name(self, registry):
        t = registry.migration.table('test', schema='test_db_schema')
        t.column('other').alter(name='othername')
        t.column('othername')
        with pytest.raises(MigrationException):
            t.column('other')

    def test_index(self, registry):
        t = registry.migration.table('test', schema='test_db_schema')
        t.index().add(t.column('integer'))
        t.index(t.column('integer')).drop()

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="FIXME: can't create foreign key")
    def test_alter_column_foreign_key(self, registry):
        t = registry.migration.table('test', schema='test_db_schema')
        t.foreign_key('my_fk').add(['other'], [registry.System.Blok.name])
        t.foreign_key('my_fk').drop()

    def test_constraint_unique(self, registry):
        t = registry.migration.table('test', schema='test_db_schema')
        t.unique(name='test_unique_constraint').add(t.column('other'))
        t.unique(name='test_unique_constraint').drop()

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason="Can't drop check constraint issue #93")
    def test_constraint_check(self, registry):
        t = registry.migration.table('test', schema='test_db_schema')
        Test = registry.Test
        t.check('test').add(Test.other != 'test')
        # particuliar case of check constraint
        t.check('anyblok_ck_test__test').drop()

    def test_detect_schema_added(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.TestFK.__table__.drop(bind=conn)
            registry.TestUnique.__table__.drop(bind=conn)
            registry.TestFK2.__table__.drop(bind=conn)
            registry.TestFKTarget.__table__.drop(bind=conn)
            registry.TestIndex.__table__.drop(bind=conn)
            if not sgdb_in(['MySQL', 'MariaDB']):
                registry.TestCheck.__table__.drop(bind=conn)

            conn.execute(DropSchema('test_db_schema'))

        report = registry.migration.detect_changed(schema_only=True)
        assert report.log_has("Add schema test_db_schema")
        report.apply_change()
        report = registry.migration.detect_changed(schema_only=True)
        assert not report.log_has("Add schema test_db_schema")

    def test_detect_table_added(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Add table test_db_schema.test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not report.log_has("Add table test_db_schema.test")

    def test_detect_column_added(self, registry):
        # Remove a column on the table force the detection to found new column
        # which is existing in metadata but not in table
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table('test',
                                            MetaData(),
                                            Column('integer',
                                                   Integer,
                                                   primary_key=True),
                                            schema='test_db_schema')
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Add test.other")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not report.log_has("Add test.other")

    def test_detect_table_removed(self, registry):
        with cnx(registry) as conn:
            Table('test2',
                  MetaData(),
                  Column('integer', Integer, primary_key=True),
                  Column('other', String(64)),
                  Column('other2', String(64)),
                  schema='test_db_schema').create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Drop Table test_db_schema.test2")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert report.log_has("Drop Table test_db_schema.test2")

    def test_detect_column_removed(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table('test',
                                            MetaData(),
                                            Column('integer',
                                                   Integer,
                                                   primary_key=True),
                                            Column('other', String(64)),
                                            Column('other2', String(64)),
                                            schema='test_db_schema')
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Drop Column test.other2")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert report.log_has("Drop Column test.other2")

    def test_detect_nullable(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table('test',
                                            MetaData(),
                                            Column('integer',
                                                   Integer,
                                                   primary_key=True),
                                            Column('other',
                                                   String(64),
                                                   nullable=False),
                                            schema='test_db_schema')
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Alter test.other")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Alter test.other"))

    def test_detect_add_index_constraint(self, registry):
        with cnx(registry) as conn:
            registry.TestIndex.__table__.drop(bind=conn)
            registry.TestIndex.__table__ = Table('testindex',
                                                 MetaData(),
                                                 Column('integer',
                                                        Integer,
                                                        primary_key=True),
                                                 Column('other', String(64)),
                                                 schema='test_db_schema')
            registry.TestIndex.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Add index constraint on testindex (other)")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (
            report.log_has("Add index constraint on testindex (other)"))

    def test_detect_add_column_with_index_constraint(self, registry):
        with cnx(registry) as conn:
            registry.TestIndex.__table__.drop(bind=conn)
            registry.TestIndex.__table__ = Table('testindex',
                                                 MetaData(),
                                                 Column('integer',
                                                        Integer,
                                                        primary_key=True),
                                                 schema='test_db_schema')
            registry.TestIndex.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Add testindex.other")
        assert report.log_has("Add index constraint on testindex (other)")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Add testindex.other"))
        assert not (
            report.log_has("Add index constraint on testindex (other)"))

    def test_detect_drop_anyblok_index(self, registry):
        with cnx(registry) as conn:
            conn.execute(
                text("""CREATE INDEX anyblok_ix_test__other
                   ON test_db_schema.test (other);"""))
        report = registry.migration.detect_changed()
        assert report.log_has(
            "Drop index anyblok_ix_test__other on test_db_schema.test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has(
            "Drop index anyblok_ix_test__other on test_db_schema.test"))

    def test_detect_type(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table('test',
                                            MetaData(),
                                            Column('integer',
                                                   Integer,
                                                   primary_key=True),
                                            Column('other', Integer),
                                            schema='test_db_schema')
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Alter test.other")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Alter test.other"))

    def test_detect_primary_key(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table('test',
                                            MetaData(),
                                            Column('integer',
                                                   Integer,
                                                   nullable=False),
                                            Column('other',
                                                   String(64),
                                                   primary_key=True),
                                            schema='test_db_schema')
            registry.Test.__table__.create(bind=conn)

        with pytest.raises(MigrationException):
            registry.migration.detect_changed()

    def test_detect_add_foreign_key(self, registry):
        with cnx(registry) as conn:
            registry.TestFK.__table__.drop(bind=conn)
            registry.TestFK.__table__ = Table('testfk',
                                              MetaData(),
                                              Column('integer',
                                                     Integer,
                                                     primary_key=True),
                                              Column('other', Integer),
                                              schema='test_db_schema')
            registry.TestFK.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Add Foreign keys on (testfk.other) => "
                              "(test_db_schema.testfktarget.integer)")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not report.log_has("Add Foreign keys on (testfk.other) => "
                                  "(test_db_schema.testfktarget.integer)")

    @pytest.mark.skipif(sgdb_in(['MsSQL']), reason="MsSQL does not change fk")
    def test_detect_foreign_key_options_changed(self, registry):
        with cnx(registry) as conn:
            registry.TestFK2.__table__.drop(bind=conn)
            meta = MetaData()
            meta._add_table('testfktarget', None,
                            registry.TestFKTarget.__table__)
            registry.TestFK2.__table__ = Table(
                'testfk2',
                meta,
                Column('integer', Integer, primary_key=True),
                Column('other', Integer, ForeignKey('testfktarget.integer')),
                schema='test_db_schema')
            registry.TestFK2.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Drop Foreign keys on testfk2.other => "
                              "test_db_schema.testfktarget.integer")
        assert report.log_has("Add Foreign keys on (testfk2.other) => "
                              "(test_db_schema.testfktarget.integer)")

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="FIXME: can't create foreign key")
    def test_detect_drop_anyblok_foreign_key(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            meta = MetaData(naming_convention=naming_convention)
            meta._add_table('system_blok', None,
                            registry.System.Blok.__table__)
            registry.Test.__table__ = Table(
                'test',
                meta,
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), ForeignKey('system_blok.name')),
                schema='test_db_schema')
            registry.Test.__table__.create(bind=conn)
            # anyblok_fk_test__other_on_system_blok__name

        report = registry.migration.detect_changed()

        message = ("Drop Foreign keys on test.other => %ssystem_blok.name") % (
            'dbo.' if sgdb_in(['MsSQL']) else '')
        assert report.log_has(message)
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not report.log_has(message)

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="FIXME: can't create foreign key")
    def test_detect_drop_column_with_foreign_key(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            meta = MetaData(naming_convention=naming_convention)
            meta._add_table('system_blok', None,
                            registry.System.Blok.__table__)
            registry.Test.__table__ = Table(
                'test',
                meta,
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
                Column('other2', String(64), ForeignKey('system_blok.name')),
                schema='test_db_schema')
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        message = ("Drop Foreign keys on test.other2 => %ssystem_blok.name"
                   ) % ('dbo.' if sgdb_in(['MsSQL']) else '')
        assert report.log_has(message)
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not report.log_has(message)

    @pytest.mark.skipif(sgdb_in(['MsSQL']),
                        reason="MsSQL does not add unique #121")
    def test_detect_add_unique_constraint(self, registry):
        with cnx(registry) as conn:
            registry.TestUnique.__table__.drop(bind=conn)
            registry.TestUnique.__table__ = Table('testunique',
                                                  MetaData(),
                                                  Column('integer',
                                                         Integer,
                                                         primary_key=True),
                                                  Column('other', String(64)),
                                                  schema='test_db_schema')
            registry.TestUnique.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Add unique constraint on testunique (other)")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (
            report.log_has("Add unique constraint on testunique (other)"))

    @pytest.mark.skipif(sgdb_in(['MsSQL']),
                        reason="MsSQL does not add unique #121")
    def test_detect_add_column_with_unique_constraint(self, registry):
        with cnx(registry) as conn:
            registry.TestUnique.__table__.drop(bind=conn)
            registry.TestUnique.__table__ = Table('testunique',
                                                  MetaData(),
                                                  Column('integer',
                                                         Integer,
                                                         primary_key=True),
                                                  schema='test_db_schema')
            registry.TestUnique.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Add unique constraint on testunique (other)")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (
            report.log_has("Add unique constraint on testunique (other)"))

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="MySQL transform unique constraint on index")
    @pytest.mark.skipif(sgdb_in(['MsSQL']),
                        reason="MsSQL does not drop unique #121")
    def test_detect_drop_unique_anyblok_constraint(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(naming_convention=naming_convention),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), unique=True),
                schema='test_db_schema')
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has(
            "Drop constraint anyblok_uq_test__other on test_db_schema.test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not report.log_has(
            "Drop constraint anyblok_uq_test__other on test_db_schema.test")

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason="No CheckConstraint works #90")
    def test_detect_add_check_constraint(self, registry):
        with cnx(registry) as conn:
            registry.TestCheck.__table__.drop(bind=conn)
            registry.TestCheck.__table__ = Table(
                'testcheck',
                MetaData(naming_convention=naming_convention),
                Column('integer', Integer, primary_key=True),
                schema='test_db_schema')
            registry.TestCheck.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has(
            "Add check constraint anyblok_ck_testcheck__test "
            "on test_db_schema.testcheck")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not report.log_has(
            "Add check constraint anyblok_ck_testcheck__test "
            "on test_db_schema.testcheck")

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB', 'MsSQL']),
                        reason="No CheckConstraint works #90")
    def test_detect_drop_check_anyblok_constraint(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(naming_convention=naming_convention),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64),
                       CheckConstraint("other != 'test'", name='check')),
                schema='test_db_schema')
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Drop check constraint anyblok_ck_test__check "
                              "on test_db_schema.test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has(
            "Drop check constraint anyblok_ck_test__check "
            "on test_db_schema.test"))
Beispiel #17
0
# -*- coding: utf-8 -*-
# This file is a part of the AnyBlok project
#
#    Copyright (C) 2014 Jean-Sebastien SUZANNE <*****@*****.**>
#    Copyright (C) 2019 Jean-Sebastien SUZANNE <*****@*****.**>
#
# This Source Code Form is subject to the terms of the Mozilla Public License,
# v. 2.0. If a copy of the MPL was not distributed with this file,You can
# obtain one at http://mozilla.org/MPL/2.0/.
import pytest
from anyblok.testing import sgdb_in
from anyblok.blok import BlokManager
from anyblok.registry import RegistryException, RegistryConflictingException


@pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                    reason='Not for MySQL and MariaDB')
class TestBlok:
    @pytest.fixture(autouse=True)
    def transact(self, request, registry_testblok):
        transaction = registry_testblok.begin_nested()
        request.addfinalizer(transaction.rollback)
        return

    def test_blok_exist(self, registry_testblok):
        registry = registry_testblok
        Blok = registry.System.Blok
        query = Blok.query().filter(Blok.name == 'test-blok1')
        if not query.count():
            pytest.fail('No blok found')
Beispiel #18
0
class TestField2:
    @pytest.fixture(autouse=True)
    def close_registry(self, request, bloks_loaded):
        def close():
            if hasattr(self, 'registry'):
                self.registry.close()

        request.addfinalizer(close)

    def init_registry(self, *args, **kwargs):
        self.registry = init_registry(*args, **kwargs)
        return self.registry

    def test_field_without_name(self):
        self.init_registry(field_without_name)

    def test_field_function_fset(self):
        def add_in_registry():
            @register(Model)
            class Test:

                id = Integer(primary_key=True)
                _name = String()
                name = Function(fget='fget',
                                fset='fset',
                                fdel='fdel',
                                fexpr='fexpr')

                def fget(self):
                    return self._name

                def fset(self, value):
                    self._name = value

                def fdel(self):
                    self._name = None

                @classmethod
                def fexpr(cls):
                    return cls._name

        registry = self.init_registry(add_in_registry)
        t = registry.Test.insert(name='Jean-Sebastien SUZANNE')
        assert t._name == 'Jean-Sebastien SUZANNE'
        t = registry.Test.query().first()
        t.name = 'Mister ANYBLOK'
        assert t._name == 'Mister ANYBLOK'
        t.update(name='Jean-Sebastien SUZANNE')
        assert t._name == 'Jean-Sebastien SUZANNE'

    def test_class_hasattr(self):
        def add_in_registry():
            @register(Model)
            class Test:

                id = Integer(primary_key=True)
                val1 = Integer()
                val2 = Function(fget='fget', fset='fset')

                def fget(self):
                    return 2 * self.val1

        registry = self.init_registry(add_in_registry)
        registry.Test.val2

    @pytest.mark.skipif(sgdb_in(['MariaDB']),
                        reason='JSON is not existing in this SGDB')
    def test_field_json_related_with_missing_json_column(self):
        def add_in_registry():
            @register(Model)
            class Test:

                id = Integer(primary_key=True)
                properties = Json()
                name = JsonRelated(keys=['name'])

        with pytest.raises(FieldException):
            self.init_registry(add_in_registry)

    @pytest.mark.skipif(sgdb_in(['MariaDB']),
                        reason='JSON is not existing in this SGDB')
    def test_field_json_related_with_missing_keys(self):
        def add_in_registry():
            @register(Model)
            class Test:

                id = Integer(primary_key=True)
                properties = Json()
                name = JsonRelated(json_column='properties')

        with pytest.raises(FieldException):
            self.init_registry(add_in_registry)

    @pytest.mark.skipif(sgdb_in(['MariaDB']),
                        reason='JSON is not existing in this SGDB')
    def test_field_json_related_with_adapter(self):
        def add_in_registry():
            @register(Model)
            class Test:

                id = Integer(primary_key=True)
                properties = Json()
                name = JsonRelated(json_column='properties',
                                   keys=['name'],
                                   set_adapter=str,
                                   get_adapter=int)

        registry = self.init_registry(add_in_registry)
        t = registry.Test.insert()
        assert t.name is None
        t.name = 1
        assert t.properties == {'name': '1'}
        t.properties['name'] = '2'
        assert t.name == 2

    @pytest.mark.skipif(sgdb_in(['MariaDB']),
                        reason='JSON is not existing in this SGDB')
    def test_field_json_related_with_adapter_with_method(self):
        def add_in_registry():
            @register(Model)
            class Test:

                id = Integer(primary_key=True)
                properties = Json()
                name = JsonRelated(json_column='properties',
                                   keys=['name'],
                                   set_adapter='fromint',
                                   get_adapter='toint')

                def fromint(self, value):
                    if value:
                        return str(value)

                    return value

                def toint(self, value):
                    if value:
                        return int(value)

                    return value

        registry = self.init_registry(add_in_registry)
        t = registry.Test.insert()
        assert t.name is None
        t.name = 1
        assert t.properties == {'name': '1'}
        t.properties['name'] = '2'
        assert t.name == 2
Beispiel #19
0
class TestJsonRelated:
    @pytest.fixture(autouse=True)
    def transact(self, request, registry_json_related):
        transaction = registry_json_related.begin_nested()
        request.addfinalizer(transaction.rollback)
        return

    @pytest.mark.skipif(sgdb_in(['MariaDB', 'MsSQL']),
                        reason='JSON is not existing in this SGDB')
    def test_field_json_related_hasattr(self, registry_json_related):
        registry = registry_json_related
        registry.Test.name

    def test_field_json_related_autodoc(self, registry_json_related):
        registry = registry_json_related
        registry.loaded_namespaces_first_step['Model.Test'][
            'name'].autodoc_get_properties()

    def test_field_json_related_get_1(self, registry_json_related):
        registry = registry_json_related
        t = registry.Test.insert()
        assert t.name is None

    def test_field_json_related_get_2(self, registry_json_related):
        registry = registry_json_related
        t = registry.Test.insert(properties={})
        assert t.name is None

    def test_field_json_related_get_3(self, registry_json_related):
        registry = registry_json_related
        t = registry.Test.insert(properties={'name': 'jssuzanne'})
        assert t.name == 'jssuzanne'

    def test_field_json_related_del_1(self, registry_json_related):
        registry = registry_json_related
        t = registry.Test.insert(properties={'name': 'jssuzanne'})
        del t.name
        assert t.name is None
        assert t.properties == {'name': None}

    def test_field_json_related_set_1(self, registry_json_related):
        registry = registry_json_related
        t = registry.Test.insert()
        t.name = 'jssuzanne'
        assert t.properties == {'name': 'jssuzanne'}

    def test_field_json_related_set_2(self, registry_json_related):
        registry = registry_json_related
        t = registry.Test.insert(properties={})
        t.name = 'jssuzanne'
        assert t.properties == {'name': 'jssuzanne'}

    def test_field_json_related_set_3(self, registry_json_related):
        registry = registry_json_related
        t = registry.Test.insert(properties={'name': 'other'})
        t.name = 'jssuzanne'
        assert t.properties == {'name': 'jssuzanne'}

    @pytest.mark.skipif(sgdb_in(['MariaDB', 'MsSQL']),
                        reason='JSON is not existing in this SGDB')
    def test_field_json_related_exp_1(self, registry_json_related):
        registry = registry_json_related
        Test = registry.Test
        Test.insert()
        query = registry.Test.query().filter(
            Test.name.cast(types.String) == '"jssuzanne"')
        assert not (query.count())

    @pytest.mark.skipif(sgdb_in(['MariaDB', 'MsSQL']),
                        reason='JSON is not existing in this SGDB')
    def test_field_json_related_exp_2(self, registry_json_related):
        registry = registry_json_related
        Test = registry.Test
        Test.insert(properties={})
        query = registry.Test.query().filter(
            Test.name.cast(types.String) == '"jssuzanne"')
        assert not (query.count())

    @pytest.mark.skipif(sgdb_in(['MariaDB', 'MsSQL']),
                        reason='JSON is not existing in this SGDB')
    def test_field_json_related_exp_3(self, registry_json_related):
        registry = registry_json_related
        Test = registry.Test
        Test.insert(properties={'name': 'jssuzanne'})
        query = registry.Test.query().filter(
            Test.name.cast(types.String) == '"jssuzanne"')
        assert query.count()
Beispiel #20
0
class TestMigration:
    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="Can't create empty table")
    def test_add_table(self, registry):
        registry.migration.table().add('test2')
        registry.migration.table('test2')

    def fill_test_table(self, registry):
        Test = registry.Test
        vals = [{'other': 'test %d' % x} for x in range(10)]
        Test.multi_insert(*vals)

    def test_add_column(self, registry):
        t = registry.migration.table('test')
        t.column().add(Column('new_column', Integer))
        t.column('new_column')

    def test_add_column_in_filled_table(self, registry):
        self.fill_test_table(registry)
        t = registry.migration.table('test')
        t.column().add(Column('new_column', Integer))
        t.column('new_column')

    def test_add_not_null_column(self, registry):
        t = registry.migration.table('test')
        t.column().add(Column('new_column', Integer, nullable=False))
        t.column('new_column')

    def test_add_not_null_column_in_filled_table(self, registry):
        self.fill_test_table(registry)
        t = registry.migration.table('test')
        t.column().add(Column('new_column', Integer, nullable=False))
        t.column('new_column')

    def test_add_column_with_default_value(self, registry):
        t = registry.migration.table('test')
        t.column().add(Column('new_column', Integer, default=100))
        t.column('new_column')

    def test_add_column_with_default_str_value(self, registry):
        t = registry.migration.table('test')
        t.column().add(Column('new_column', Integer, default='100'))
        t.column('new_column')

    def test_add_column_in_filled_table_with_default_value(self, registry):
        self.fill_test_table(registry)
        t = registry.migration.table('test')
        t.column().add(Column('new_column', Integer, default=100))
        t.column('new_column')
        res = [
            x for x in registry.execute(
                "select count(*) from test where new_column is null")
        ][0][0]
        assert res == 0

    def test_add_not_null_column_in_filled_table_with_default_value(
            self, registry):
        self.fill_test_table(registry)
        t = registry.migration.table('test')
        t.column().add(
            Column('new_column', Integer, nullable=False, server_default="1"))
        t.column('new_column')

    def test_add_unique_constraint_on_good_table(self, registry):
        self.fill_test_table(registry)
        t = registry.migration.table('test')
        t.unique('unique_constraint').add(t.column('other'))
        registry.Test.insert(other='One entry')
        with pytest.raises(IntegrityError):
            registry.Test.insert(other='One entry')

    def test_add_unique_constraint_on_not_unique_column(self, registry):
        Test = registry.Test
        vals = [{'other': 'test'} for x in range(10)]
        Test.multi_insert(*vals)
        t = registry.migration.table('test')
        t.unique(None).add(t.column('other'))
        registry.Test.insert(other='One entry')
        registry.Test.insert(other='One entry')

    def test_drop_table(self, registry):
        registry.migration.table('test').drop()
        with pytest.raises(MigrationException):
            registry.migration.table('Test')

    def test_drop_column(self, registry):
        t = registry.migration.table('test')
        t.column('other').drop()
        with pytest.raises(MigrationException):
            t.column('other')

    def test_alter_table_name(self, registry):
        t = registry.migration.table('test')
        t.alter(name='othername')
        registry.migration.table('othername')
        with pytest.raises(MigrationException):
            registry.migration.table('test')

    def test_alter_column_name(self, registry):
        t = registry.migration.table('test')
        t.column('other').alter(name='othername')
        t.column('othername')
        with pytest.raises(MigrationException):
            t.column('other')

    def test_alter_column_nullable(self, registry):
        t = registry.migration.table('test')
        c = t.column('other').alter(nullable=False)
        assert not c.nullable

    def test_alter_column_nullable_in_filled_table(self, registry):
        t = registry.migration.table('test')
        t.column().add(Column('new_column', Integer))
        self.fill_test_table(registry)
        c = t.column('new_column').alter(nullable=False)
        # the column doesn't change of nullable to not lock the migration
        assert c.nullable

    def test_alter_column_default(self, registry):
        t = registry.migration.table('test')
        c = t.column('other').alter(server_default='test')
        if sgdb_in(['PostgreSQL']):
            assert c.server_default == "'test'::character varying"
        else:
            assert str(c.server_default) == "'test'"

    def test_index(self, registry):
        t = registry.migration.table('test')
        t.index().add(t.column('integer'))
        t.index(t.column('integer')).drop()

    def test_alter_column_type(self, registry):
        t = registry.migration.table('test')
        c = t.column('other').alter(type_=TEXT)
        assert isinstance(c.type, TEXT)

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="Can't drop primary key issue #92")
    def test_alter_column_primary_key(self, registry):
        t = registry.migration.table('test')
        t.primarykey().drop().add(t.column('other'))

    def test_alter_column_foreign_key(self, registry):
        t = registry.migration.table('test')
        t.foreign_key('my_fk').add(['other'], [registry.System.Blok.name])
        t.foreign_key('my_fk').drop()

    def test_constraint_unique(self, registry):
        t = registry.migration.table('test')
        t.unique(name='test_unique_constraint').add(t.column('other'))
        t.unique(name='test_unique_constraint').drop()

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="Can't drop check constraint issue #93")
    def test_constraint_check(self, registry):
        t = registry.migration.table('test')
        Test = registry.Test
        t.check('test').add(Test.other != 'test')
        # particuliar case of check constraint
        t.check('anyblok_ck_test__test').drop()

    def test_detect_under_noautocommit_flag(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), nullable=False),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.detect_changed()
        registry.migration.withoutautomigration = True
        with pytest.raises(MigrationException):
            registry.migration.detect_changed()

    def test_detect_column_added(self, registry):
        # Remove a column on the table force the detection to found new column
        # which is existing in metadata but not in table
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test', MetaData(), Column('integer',
                                           Integer,
                                           primary_key=True))
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Add test.other")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not report.log_has("Add test.other")

    def test_detect_table_removed(self, registry):
        with cnx(registry) as conn:
            Table(
                'test2',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
                Column('other2', String(64)),
            ).create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Drop Table test2")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert report.log_has("Drop Table test2")

    def test_detect_table_removed_with_reinit_column(self, registry):
        with cnx(registry) as conn:
            Table(
                'test2',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
                Column('other2', String(64)),
            ).create(bind=conn)

        registry.migration.reinit_tables = True
        report = registry.migration.detect_changed()
        assert report.log_has("Drop Table test2")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Drop Table test2"))

    def test_detect_table_removed_with_reinit_all(self, registry):
        with cnx(registry) as conn:
            Table(
                'test2',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
                Column('other2', String(64)),
            ).create(bind=conn)

        registry.migration.reinit_all = True
        report = registry.migration.detect_changed()
        assert report.log_has("Drop Table test2")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Drop Table test2"))

    def test_detect_column_removed(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
                Column('other2', String(64)),
            )
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Drop Column test.other2")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert report.log_has("Drop Column test.other2")

    def test_detect_column_removed_with_reinit_column(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
                Column('other2', String(64)),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.reinit_columns = True
        report = registry.migration.detect_changed()
        assert report.log_has("Drop Column test.other2")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Drop Column test.other2"))

    def test_detect_column_removed_with_reinit_all(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
                Column('other2', String(64)),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.reinit_all = True
        report = registry.migration.detect_changed()
        assert report.log_has("Drop Column test.other2")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Drop Column test.other2"))

    def test_detect_not_nullable_column_removed(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
                Column('other2', String(64), nullable=False),
            )
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert not (report.log_has("Drop Column test.other2"))
        assert report.log_has("Drop Column test.other2 (not null)")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert report.log_has("Drop Column test.other2")
        assert not (report.log_has("Drop Column test.other2 (not null)"))

    def test_detect_nullable(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), nullable=False),
            )
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Alter test.other")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Alter test.other"))

    def test_detect_m2m_primary_key(self, registry):
        with cnx(registry) as conn:
            conn.execute("DROP TABLE reltable")
            conn.execute("""CREATE TABLE reltable (
                    idmodel1 INT,
                    idmodel2 INT,
                    FOREIGN KEY (idmodel1) REFERENCES testm2m1 (idmodel1),
                    FOREIGN KEY (idmodel2) REFERENCES testm2m2 (idmodel2)
                );""")

        with pytest.raises(MigrationException):
            registry.migration.detect_changed()

    def test_detect_server_default(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), server_default='9.99'),
            )
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Alter test.other")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Alter test.other"))

    def test_detect_add_index_constraint(self, registry):
        with cnx(registry) as conn:
            registry.TestIndex.__table__.drop(bind=conn)
            registry.TestIndex.__table__ = Table(
                'testindex',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
            )
            registry.TestIndex.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Add index constraint on testindex (other)")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (
            report.log_has("Add index constraint on testindex (other)"))

    def test_detect_add_column_with_index_constraint(self, registry):
        with cnx(registry) as conn:
            registry.TestIndex.__table__.drop(bind=conn)
            registry.TestIndex.__table__ = Table(
                'testindex',
                MetaData(),
                Column('integer', Integer, primary_key=True),
            )
            registry.TestIndex.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Add testindex.other")
        assert report.log_has("Add index constraint on testindex (other)")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Add testindex.other"))
        assert not (
            report.log_has("Add index constraint on testindex (other)"))

    def test_detect_drop_index(self, registry):
        with cnx(registry) as conn:
            conn.execute("""CREATE INDEX other_idx ON test (other);""")
        report = registry.migration.detect_changed()
        assert report.log_has("Drop index other_idx on test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert report.log_has("Drop index other_idx on test")

    def test_detect_drop_anyblok_index(self, registry):
        with cnx(registry) as conn:
            conn.execute(
                """CREATE INDEX anyblok_ix_test__other ON test (other);""")
        report = registry.migration.detect_changed()
        assert report.log_has("Drop index anyblok_ix_test__other on test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (
            report.log_has("Drop index anyblok_ix_test__other on test"))

    def test_detect_drop_index_with_reinit_indexes(self, registry):
        with cnx(registry) as conn:
            conn.execute("""CREATE INDEX other_idx ON test (other);""")
        registry.migration.reinit_indexes = True
        report = registry.migration.detect_changed()
        assert report.log_has("Drop index other_idx on test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Drop index other_idx on test"))

    def test_detect_drop_index_with_reinit_all(self, registry):
        with cnx(registry) as conn:
            conn.execute("""CREATE INDEX other_idx ON test (other);""")
        registry.migration.reinit_all = True
        report = registry.migration.detect_changed()
        assert report.log_has("Drop index other_idx on test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Drop index other_idx on test"))

    def test_detect_type(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', Integer),
            )
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Alter test.other")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Alter test.other"))

    def test_detect_primary_key(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, nullable=False),
                Column('other', String(64), primary_key=True),
            )
            registry.Test.__table__.create(bind=conn)

        with pytest.raises(MigrationException):
            registry.migration.detect_changed()

    def test_detect_add_foreign_key(self, registry):
        with cnx(registry) as conn:
            registry.TestFK.__table__.drop(bind=conn)
            registry.TestFK.__table__ = Table(
                'testfk',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', Integer),
            )
            registry.TestFK.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has(
            "Add Foreign keys on (testfk.other) => (testfktarget.integer)")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has(
            "Add Foreign keys on (testfk.other) => (testfktarget.integer)"))

    def test_detect_foreign_key_options_changed(self, registry):
        with cnx(registry) as conn:
            registry.TestFK2.__table__.drop(bind=conn)
            meta = MetaData()
            meta._add_table('testfktarget', None,
                            registry.TestFKTarget.__table__)
            registry.TestFK2.__table__ = Table(
                'testfk2',
                meta,
                Column('integer', Integer, primary_key=True),
                Column('other', Integer, ForeignKey('testfktarget.integer')),
            )
            registry.TestFK2.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has(
            "Drop Foreign keys on testfk2.other => testfktarget.integer")
        assert report.log_has(
            "Add Foreign keys on (testfk2.other) => (testfktarget.integer)")

    def test_detect_drop_foreign_key(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            meta = MetaData()
            meta._add_table('system_blok', None,
                            registry.System.Blok.__table__)
            registry.Test.__table__ = Table(
                'test',
                meta,
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), ForeignKey('system_blok.name')),
            )
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has(
            "Drop Foreign keys on test.other => system_blok.name")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert report.log_has(
            "Drop Foreign keys on test.other => system_blok.name")

    def test_detect_drop_anyblok_foreign_key(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            meta = MetaData(naming_convention=naming_convention)
            meta._add_table('system_blok', None,
                            registry.System.Blok.__table__)
            registry.Test.__table__ = Table(
                'test',
                meta,
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), ForeignKey('system_blok.name')),
            )
            registry.Test.__table__.create(bind=conn)
            # anyblok_fk_test__other_on_system_blok__name

        report = registry.migration.detect_changed()
        assert report.log_has(
            "Drop Foreign keys on test.other => system_blok.name")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has(
            "Drop Foreign keys on test.other => system_blok.name"))

    def test_detect_drop_foreign_key_with_reinit_constraint(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            meta = MetaData()
            meta._add_table('system_blok', None,
                            registry.System.Blok.__table__)
            registry.Test.__table__ = Table(
                'test',
                meta,
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), ForeignKey('system_blok.name')),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.reinit_constraints = True
        report = registry.migration.detect_changed()
        assert report.log_has(
            "Drop Foreign keys on test.other => system_blok.name")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has(
            "Drop Foreign keys on test.other => system_blok.name"))

    def test_detect_drop_foreign_key_with_reinit_all(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            meta = MetaData()
            meta._add_table('system_blok', None,
                            registry.System.Blok.__table__)
            registry.Test.__table__ = Table(
                'test',
                meta,
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), ForeignKey('system_blok.name')),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.reinit_all = True
        report = registry.migration.detect_changed()
        assert report.log_has(
            "Drop Foreign keys on test.other => system_blok.name")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has(
            "Drop Foreign keys on test.other => system_blok.name"))

    def test_detect_drop_column_with_foreign_key(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            meta = MetaData(naming_convention=naming_convention)
            meta._add_table('system_blok', None,
                            registry.System.Blok.__table__)
            registry.Test.__table__ = Table(
                'test',
                meta,
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
                Column('other2', String(64), ForeignKey('system_blok.name')),
            )
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has(
            "Drop Foreign keys on test.other2 => system_blok.name")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has(
            "Drop Foreign keys on test.other2 => system_blok.name"))

    def test_detect_add_unique_constraint(self, registry):
        with cnx(registry) as conn:
            registry.TestUnique.__table__.drop(bind=conn)
            registry.TestUnique.__table__ = Table(
                'testunique',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64)),
            )
            registry.TestUnique.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Add unique constraint on testunique (other)")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (
            report.log_has("Add unique constraint on testunique (other)"))

    def test_detect_add_column_with_unique_constraint(self, registry):
        with cnx(registry) as conn:
            registry.TestUnique.__table__.drop(bind=conn)
            registry.TestUnique.__table__ = Table(
                'testunique',
                MetaData(),
                Column('integer', Integer, primary_key=True),
            )
            registry.TestUnique.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Add unique constraint on testunique (other)")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (
            report.log_has("Add unique constraint on testunique (other)"))

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="MySQL transform unique constraint on index")
    def test_detect_drop_unique_constraint(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), unique=True),
            )
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Drop constraint test_other_key on test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert report.log_has("Drop constraint test_other_key on test")

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="MySQL transform unique constraint on index")
    def test_detect_drop_unique_anyblok_constraint(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(naming_convention=naming_convention),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), unique=True),
            )
            registry.Test.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has("Drop constraint anyblok_uq_test__other on test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (
            report.log_has("Drop constraint anyblok_uq_test__other on test"))

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="MySQL transform unique constraint on index")
    def test_detect_drop_unique_constraint_with_reinit_constraints(
            self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), unique=True),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.reinit_constraints = True
        report = registry.migration.detect_changed()
        assert report.log_has("Drop constraint test_other_key on test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Drop constraint test_other_key on test"))

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="MySQL transform unique constraint on index")
    def test_detect_drop_unique_constraint_with_reinit_all(self, registry):
        with cnx(registry) as conn:
            registry.Test.__table__.drop(bind=conn)
            registry.Test.__table__ = Table(
                'test',
                MetaData(),
                Column('integer', Integer, primary_key=True),
                Column('other', String(64), unique=True),
            )
            registry.Test.__table__.create(bind=conn)

        registry.migration.reinit_all = True
        report = registry.migration.detect_changed()
        assert report.log_has("Drop constraint test_other_key on test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Drop constraint test_other_key on test"))

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="No CheckConstraint works #90")
    def test_no_detect_drop_and_add_check_constraint_with_long_name(
            self, registry):
        report = registry.migration.detect_changed()
        assert not (report.log_has(
            "Drop check constraint anyblok_ck_testchecklongconstraintname"
            "__long_long_long_long_lon on testchecklongconstraintname"))
        assert not (report.log_has(
            "Add check constraint anyblok_ck_testchecklongconstraintname__"
            "long_long_long_long_long_long_long_long_long_long_long_long_"
            "long_long_long_long_long_long_test on "
            "testchecklongconstraintname"))

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="No CheckConstraint works #90")
    def test_detect_add_check_constraint(self, registry):
        with cnx(registry) as conn:
            registry.TestCheck.__table__.drop(bind=conn)
            registry.TestCheck.__table__ = Table(
                'testcheck',
                MetaData(naming_convention=naming_convention),
                Column('integer', Integer, primary_key=True),
            )
            registry.TestCheck.__table__.create(bind=conn)

        report = registry.migration.detect_changed()
        assert report.log_has(
            "Add check constraint anyblok_ck_testcheck__test on testcheck")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has(
            "Add check constraint anyblok_ck_testcheck__test on testcheck"))

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="No CheckConstraint works #90")
    def test_detect_drop_check_constraint(self, registry):
        with cnx(registry) as conn:
            conn.execute("DROP TABLE test")
            conn.execute("""CREATE TABLE test(
                    integer INT PRIMARY KEY NOT NULL,
                    other CHAR(64) CONSTRAINT ck_other CHECK (other != 'test')
                );""")
        report = registry.migration.detect_changed()
        assert report.log_has("Drop check constraint ck_other on test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert report.log_has("Drop check constraint ck_other on test")

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="No CheckConstraint works #90")
    def test_detect_drop_check_anyblok_constraint(self, registry):
        with cnx(registry) as conn:
            conn.execute("DROP TABLE test")
            conn.execute("""CREATE TABLE test(
                    integer INT PRIMARY KEY NOT NULL,
                    other CHAR(64) CONSTRAINT anyblok_ck__test__check
                        CHECK (other != 'test')
                );""")
        report = registry.migration.detect_changed()
        assert report.log_has(
            "Drop check constraint anyblok_ck__test__check on test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has(
            "Drop check constraint anyblok_ck__test__check on test"))

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="No CheckConstraint works #90")
    def test_detect_drop_check_constraint_with_reinit_constraint(
            self, registry):
        with cnx(registry) as conn:
            conn.execute("DROP TABLE test")
            conn.execute("""CREATE TABLE test(
                    integer INT PRIMARY KEY NOT NULL,
                    other CHAR(64) CONSTRAINT ck_other CHECK (other != 'test')
                );""")
        registry.migration.reinit_constraints = True
        report = registry.migration.detect_changed()
        assert report.log_has("Drop check constraint ck_other on test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Drop check constraint ck_other on test"))

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason="No CheckConstraint works #90")
    def test_detect_drop_check_constraint_with_reinit_all(self, registry):
        with cnx(registry) as conn:
            conn.execute("DROP TABLE test")
            conn.execute("""CREATE TABLE test(
                    integer INT PRIMARY KEY NOT NULL,
                    other CHAR(64) CONSTRAINT ck_other CHECK (other != 'test')
                );""")
        registry.migration.reinit_all = True
        report = registry.migration.detect_changed()
        assert report.log_has("Drop check constraint ck_other on test")
        report.apply_change()
        report = registry.migration.detect_changed()
        assert not (report.log_has("Drop check constraint ck_other on test"))

    def test_savepoint(self, registry):
        Test = registry.Test
        self.fill_test_table(registry)
        registry.migration.savepoint('test')
        self.fill_test_table(registry)
        assert Test.query().count() == 20
        registry.migration.rollback_savepoint('test')
        assert Test.query().count() == 10
        registry.migration.release_savepoint('test')

    def test_savepoint_without_rollback(self, registry):
        registry.migration.savepoint('test')
        registry.migration.release_savepoint('test')
        with pytest.raises((InternalError, OperationalError)):
            registry.migration.rollback_savepoint('test')
Beispiel #21
0
class TestMany2OneOld:

    @pytest.fixture(autouse=True)
    def close_registry(self, request, bloks_loaded):

        def close():
            if hasattr(self, 'registry'):
                self.registry.close()

        request.addfinalizer(close)

    def init_registry(self, *args, **kwargs):
        reset_db()
        self.registry = init_registry(*args, **kwargs)
        return self.registry

    def test_2_many2one(self):
        with pytest.raises(FieldException):
            self.init_registry(_many2one_with_same_name_for_column_names)

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']), reason='ISSUE #89')
    def test_minimum_many2one_on_sequence(self):

        def add_in_registry():

            @register(Model)
            class Test:
                id = Integer(primary_key=True)
                seq = Sequence(primary_key=True, formater="V-{seq}")

            @register(Model)
            class Test2:

                seq = Sequence(primary_key=True)
                test = Many2One(model=Model.Test)

        registry = self.init_registry(add_in_registry)
        test = registry.Test.insert()
        test2 = registry.Test2.insert(test=test)
        assert test is test2.test

    def test_minimum_many2one_without_model(self):
        with pytest.raises(FieldException):
            self.init_registry(_minimum_many2one_without_model)

    def test_same_model(self):
        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True)
                parent = Many2One(model='Model.Test', one2many='children')

        registry = self.init_registry(add_in_registry)
        t1 = registry.Test.insert()
        t2 = registry.Test.insert(parent=t1)
        assert t2.parent is t1
        assert t1.children[0] is t2

    def test_same_model_pk_by_inherit(self):
        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True)

            @register(Model)  # noqa
            class Test:

                parent = Many2One(model='Model.Test', one2many='children')

        registry = self.init_registry(add_in_registry)
        t1 = registry.Test.insert()
        t2 = registry.Test.insert(parent=t1)
        assert t2.parent is t1
        assert t1.children[0] is t2

    def test_same_model_pk_by_mixin(self):
        def add_in_registry():

            @register(Mixin)
            class MTest:

                id = Integer(primary_key=True)

            @register(Model)  # noqa
            class Test(Mixin.MTest):

                parent = Many2One(model='Model.Test', one2many='children')

        registry = self.init_registry(add_in_registry)
        t1 = registry.Test.insert()
        t2 = registry.Test.insert(parent=t1)
        assert t2.parent is t1
        assert t1.children[0] is t2

    def test_add_unique_constraint(self):
        def add_in_registry():

            @register(Model)
            class Address:

                id = Integer(primary_key=True)

            @register(Model)
            class Person:

                name = String(primary_key=True)
                address = Many2One(model=Model.Address, unique=True)

        registry = self.init_registry(add_in_registry)
        address = registry.Address.insert()
        registry.Person.insert(
            name="Jean-sébastien SUZANNE", address=address)

        with pytest.raises(IntegrityError):
            registry.Person.insert(name="Other", address=address)

    def test_add_index_constraint(self):
        def add_in_registry():

            @register(Model)
            class Address:

                id = Integer(primary_key=True)

            @register(Model)
            class Person:

                name = String(primary_key=True)
                address = Many2One(model=Model.Address, index=True)

        registry = self.init_registry(add_in_registry)
        inspector = Inspector(registry.session.connection())
        indexes = inspector.get_indexes(registry.Person.__tablename__)
        assert len(indexes) == 1

    def test_add_primary_keys_constraint(self):
        def add_in_registry():

            @register(Model)
            class Address:

                id = Integer(primary_key=True)

            @register(Model)
            class Person:

                name = String(primary_key=True)
                address = Many2One(model=Model.Address, primary_key=True)

        registry = self.init_registry(add_in_registry)
        inspector = Inspector(registry.session.connection())
        pks = inspector.get_primary_keys(registry.Person.__tablename__)
        assert 'address_id'in pks

    def test_complet_with_multi_foreign_key(self):

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True, unique=True)
                id2 = String(primary_key=True, unique=True)

            @register(Model)
            class Test2:

                @classmethod
                def define_table_args(cls):
                    table_args = super(Test2, cls).define_table_args()
                    return table_args + (ForeignKeyConstraint(
                        [cls.test_id, cls.test_id2], ['test.id', 'test.id2']),)

                id = Integer(primary_key=True)
                test_id = Integer(
                    foreign_key=Model.Test.use('id'), nullable=False)
                test_id2 = String(
                    foreign_key=Model.Test.use('id2'), nullable=False)
                test = Many2One(model=Model.Test,
                                remote_columns=('id', 'id2'),
                                column_names=('test_id', 'test_id2'))

        registry = self.init_registry(add_in_registry)
        test = registry.Test.insert(id2="10")
        test2 = registry.Test2.insert(test=test)
        assert test.id == test2.test_id
        assert test.id2 is test2.test_id2

    def test_complet_with_multi_foreign_key_without_constraint(self):

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True, unique=True)
                id2 = String(primary_key=True, unique=True)

            @register(Model)
            class Test2:

                id = Integer(primary_key=True)
                test_id = Integer(
                    foreign_key=Model.Test.use('id'), nullable=False)
                test_id2 = String(
                    foreign_key=Model.Test.use('id2'), nullable=False)
                test = Many2One(model=Model.Test,
                                remote_columns=('id', 'id2'),
                                column_names=('test_id', 'test_id2'))

        registry = self.init_registry(add_in_registry)
        test = registry.Test.insert(id2="10")
        test2 = registry.Test2.insert(test=test)
        assert test.id == test2.test_id
        assert test.id2 is test2.test_id2

    def test_with_multi_foreign_key_on_existing_column(self):

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True, unique=True)
                id2 = String(primary_key=True, unique=True)

            @register(Model)
            class Test2:

                id = Integer(primary_key=True)
                test_id = Integer(
                    foreign_key=Model.Test.use('id'), nullable=False)
                test_id2 = String(
                    foreign_key=Model.Test.use('id2'), nullable=False)
                test = Many2One(model=Model.Test)

        registry = self.init_registry(add_in_registry)
        test = registry.Test.insert(id2="10")
        test2 = registry.Test2.insert(test=test)
        assert test.id == test2.test_id
        assert test.id2 is test2.test_id2

    def test_with_multi_foreign_key_on_existing_column2(self):

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True, unique=True)
                id2 = String(primary_key=True, unique=True)

            @register(Model)
            class Test2:

                id = Integer(primary_key=True)
                other_test_id = Integer(
                    foreign_key=Model.Test.use('id'), nullable=False)
                other_test_id2 = String(
                    foreign_key=Model.Test.use('id2'), nullable=False)
                test = Many2One(model=Model.Test)

        registry = self.init_registry(add_in_registry)
        test = registry.Test.insert(id2="10")
        test2 = registry.Test2.insert(test=test)
        assert test.id == test2.other_test_id
        assert test.id2 is test2.other_test_id2

    def test_with_multi_foreign_key_on_unexisting_column(self):
        registry = self.init_registry(_two_remote_primary_keys)
        test = registry.Test.insert(id2="10")
        test2 = registry.Test2.insert(test=test)
        assert test.id == test2.test_id
        assert test.id2 is test2.test_id2

    def test_many2one_with_multi_fk_expire_field(self):
        registry = self.init_registry(_two_remote_primary_keys)
        assert('test',) in registry.expire_attributes['Model.Test2']['test_id']
        assert ('test',) in registry.expire_attributes[
            'Model.Test2']['test_id2']

    def test_with_multi_foreign_key_on_unexisting_named_column(self):

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True, unique=True)
                id2 = String(primary_key=True, unique=True)

            @register(Model)
            class Test2:

                id = Integer(primary_key=True)
                test = Many2One(model=Model.Test,
                                column_names=('test_id', 'test_id2'))

        registry = self.init_registry(add_in_registry)
        test = registry.Test.insert(id2="10")
        test2 = registry.Test2.insert(test=test)
        assert test.id == test2.test_id
        assert test.id2 is test2.test_id2

    def test_with_multi_foreign_key_on_unexisting_named_column2(self):

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True, unique=True)
                id2 = Integer(primary_key=True, unique=True)

            @register(Model)
            class Test2:

                id = Integer(primary_key=True)
                test = Many2One(model=Model.Test, column_names=(
                    'other_test_id', 'other_test_id2'))

        with pytest.raises(FieldException):
            self.init_registry(add_in_registry)

    def test_m2o_in_mixin(self):

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True)

            @register(Mixin)
            class MTest:

                test = Many2One(model=Model.Test)

            @register(Model)
            class Test1(Mixin.MTest):

                id = Integer(primary_key=True)

            @register(Model)
            class Test2(Mixin.MTest):

                id = Integer(primary_key=True)

        registry = self.init_registry(add_in_registry)
        test = registry.Test.insert()
        test1 = registry.Test1.insert(test=test)
        test2 = registry.Test2.insert(test=test)
        assert test1.test_id == test2.test_id

    def test_delete_m2o_without_fk_options_on_delete_cascade(self):

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True)

            @register(Model)
            class TestM2O:

                id = Integer(primary_key=True)
                test = Many2One(model=Model.Test, nullable=True)

        registry = self.init_registry(add_in_registry)
        test = registry.Test.insert()
        testM2O = registry.TestM2O.insert(test=test)
        assert testM2O.test is test
        with pytest.raises(IntegrityError):
            test.delete()

    def test_delete_m2o_with_fk_options_on_delete_cascade(self):

        def add_in_registry():

            @register(Model)
            class Test:

                id = Integer(primary_key=True)

            @register(Model)
            class TestM2O:

                id = Integer(primary_key=True)
                test = Many2One(model=Model.Test, nullable=True,
                                foreign_key_options={'ondelete': 'cascade'})

        registry = self.init_registry(add_in_registry)
        test = registry.Test.insert()
        testM2O = registry.TestM2O.insert(test=test)
        assert testM2O.test is test
        test.delete()
        assert not (registry.TestM2O.query().count())

    def test_2_simple_many2one_on_the_same_model(self):

        def add_in_registry():

            @register(Model)
            class Address:

                id = Integer(primary_key=True)

            @register(Model)
            class Person:

                name = String(primary_key=True)
                address_1 = Many2One(model=Model.Address)
                address_2 = Many2One(model=Model.Address)

        registry = self.init_registry(add_in_registry)
        address_1 = registry.Address.insert()
        address_2 = registry.Address.insert()
        person = registry.Person.insert(
            name='test', address_1=address_1, address_2=address_2)
        assert person.address_1 is address_1
        assert person.address_2 is address_2
        assert person.address_1 is not person.address_2
Beispiel #22
0
def add_in_registry():
    register = Declarations.register
    Model = Declarations.Model

    @register(Model)
    class Test:
        integer = Int(primary_key=True)
        other = Str()

    @register(Model)
    class TestUnique:
        integer = Int(primary_key=True)
        other = Str(unique=True)

    @register(Model)
    class TestIndex:
        integer = Int(primary_key=True)
        other = Str(index=True)

    if not sgdb_in(['MySQL', 'MariaDB']):

        @register(Model)
        class TestCheck:
            integer = Int(primary_key=True)

            @classmethod
            def define_table_args(cls):
                table_args = super(TestCheck, cls).define_table_args()
                return table_args + (CheckConstraint('integer > 0',
                                                     name='test'), )

        @register(Model)
        class TestCheckLongConstraintName:
            integer = Int(primary_key=True)

            @classmethod
            def define_table_args(cls):
                table_args = super(TestCheckLongConstraintName,
                                   cls).define_table_args()
                return table_args + (CheckConstraint(
                    'integer > 0',
                    name=('long_long_long_long_long_long_long_long_long_long_'
                          'long_long_long_long_long_long_long_long_test')), )

    @register(Model)
    class TestFKTarget:
        integer = Int(primary_key=True)

    @register(Model)
    class TestFK:
        integer = Int(primary_key=True)
        other = Int(foreign_key=Model.TestFKTarget.use('integer'))

    @register(Model)
    class TestFK2:
        integer = Int(primary_key=True)
        other = Int(foreign_key=Model.TestFKTarget.use('integer').options(
            ondelete='cascade'))

    @register(Model)
    class TestM2M1:
        idmodel1 = Int(primary_key=True)

    @register(Model)
    class TestM2M2:
        idmodel2 = Int(primary_key=True)
        rel_m2m = Many2Many(label="Rel",
                            model=Model.TestM2M1,
                            join_table='reltable',
                            remote_columns='idmodel1',
                            m2m_remote_columns='idmodel1',
                            local_columns='idmodel2',
                            m2m_local_columns='idmodel2',
                            many2many='rel_m2m_inv')
Beispiel #23
0
class TestMigrationPlugin:
    @pytest.mark.skipif(not sgdb_in(['MySQL', 'MariaDB']),
                        reason='Plugin for MySQL only')
    def test_boolean_with_mysql(self, registry_plugin):
        report = MigrationReport(registry_plugin.migration, [])
        res = report.init_modify_type(
            [None, None, 'test', 'other', {},
             TINYINT(), Boolean()])
        assert res is True

    @pytest.mark.skipif(not sgdb_in(['MySQL', 'MariaDB']),
                        reason='Plugin for MySQL only')
    def test_datetime_with_mysql(self, registry_plugin):
        report = MigrationReport(registry_plugin.migration, [])
        res = report.init_modify_type(
            [None, None, 'test', 'other', {},
             DATETIME(),
             DATETIME()])
        assert res is True

    @pytest.mark.skipif(not sgdb_in(['MsSQL']), reason='Plugin for MsSQL only')
    def test_boolean_with_mssql(self, registry_plugin):
        report = MigrationReport(registry_plugin.migration, [])
        res = report.init_modify_type(
            [None, None, 'test', 'other', {},
             BIT(), Boolean()])
        assert res is True

    @pytest.mark.skipif(not sgdb_in(['PostgreSQL']),
                        reason='Plugin for MsSQL only')
    def test_boolean_with_postgres(self, registry_plugin):
        report = MigrationReport(registry_plugin.migration, [])
        res = report.init_modify_type(
            [None, None, 'test', 'other', {},
             Integer(), Boolean()])
        assert res is False

    def test_alter_column_type_with_plugin_1(self, registry_plugin):
        report = MigrationReport(registry_plugin.migration, [])
        report.plugins = [
            MockMigrationColumnTypePluginInteger2String,
        ]
        with patch('anyblok.tests.test_migration.'
                   'MockMigrationColumnTypePluginInteger2String.apply'
                   ) as mockapply:
            report.apply_change_modify_type(
                [None, None, 'test', 'other', {},
                 Integer(),
                 String()])
            mockapply.assert_called()

    def test_alter_column_type_with_plugin_2(self, registry_plugin):
        report = MigrationReport(registry_plugin.migration, [])
        report.plugins = [
            MockMigrationColumnTypePluginInteger2String,
        ]
        with patch('anyblok.migration.MigrationColumn.alter') as mockapply:
            report.apply_change_modify_type(
                [None, None, 'test', 'other', {},
                 String(),
                 Integer()])
            mockapply.assert_called()

    @pytest.mark.skipif(not sgdb_in(['MySQL', 'MariaDB']),
                        reason='Plugin for MySQL only')
    def test_alter_column_type_with_plugin_3(self, registry_plugin):
        report = MigrationReport(registry_plugin.migration, [])
        report.plugins = [
            MockMigrationColumnTypePluginInteger2StringMySQL,
        ]
        with patch('anyblok.tests.test_migration.'
                   'MockMigrationColumnTypePluginInteger2StringMySQL.apply'
                   ) as mockapply:
            report.apply_change_modify_type(
                [None, None, 'test', 'other', {},
                 Integer(),
                 String()])
            mockapply.assert_called()

    @pytest.mark.skipif(sgdb_in(['MySQL', 'MariaDB']),
                        reason='Plugin for MySQL only')
    def test_alter_column_type_with_plugin_4(self, registry_plugin):
        report = MigrationReport(registry_plugin.migration, [])
        report.plugins = [
            MockMigrationColumnTypePluginInteger2StringMySQL,
        ]
        with patch('anyblok.migration.MigrationColumn.alter') as mockapply:
            report.apply_change_modify_type(
                [None, None, 'test', 'other', {},
                 Integer(),
                 String()])
            mockapply.assert_called()