示例#1
0
    def test_integer_type_mapping(self, integer_type):
        factory = ColumnFactory()

        _type = factory.get_type(integer_type['id']).__dict__
        assert _type['mapping']['mysql'].unsigned is integer_type['unsigned']
        assert isinstance(_type['mapping']['mysql'], integer_type['mapping'])
        assert isinstance(_type['impl'], integer_type['impl'])
示例#2
0
    def test_attr_type_mapping(self, attr_type):
        factory = ColumnFactory()

        _type = factory.get_type(attr_type['id'], attr_type.get('attrs', {}))
        assert isinstance(_type, attr_type['impl'])

        for key, val in attr_type.get('params', {}).items():
            assert _type.__dict__[key] == val
示例#3
0
 def test_array_type_mapping(self):
     factory = ColumnFactory()
     _type = factory.get_type('array', {
         'arr_type': 'integer',
         'dimensions': 2
     }).__dict__
     assert isinstance(_type['mapping']['postgresql'], ARRAY)
     # assert isinstance(_type['mapping']['postgresql'].__dict__['item_type']['impl'], INTEGER)
     assert _type['mapping']['postgresql'].__dict__['dimensions'] is 2
     assert isinstance(_type['impl'], Integer)
示例#4
0
    def __init__(self, app):
        """Set app and load platform handlers.

        Args:
            app (App): Framework App class.
        """
        self.app = app
        self.platform = Platform()
        self.sqlite_platform = SQLitePlatform()
        self.factory = ColumnFactory()
        self.engine = None
        self.meta = None
        self.session = None
示例#5
0
    def test_double_type_mapping(self):
        factory = ColumnFactory()

        _type = factory.get_type('double', {
            'precision': 10,
            'scale': 2
        }).__dict__
        assert _type['mapping']['sqlite'].precision == 10
        assert _type['mapping']['sqlite'].decimal_return_scale == 2
        assert _type['impl'].precision == 10
        assert _type['impl'].scale == 2
        assert isinstance(_type['mapping']['sqlite'], Float)
        assert isinstance(_type['impl'], DOUBLE)
示例#6
0
class Store(AbstractStore):
    """Concrete Implementation of a data store based on SQLAlchemy.

    Attributes:
        app (App): Framework App class.
        engine (sqlalchemy.engine.Engine): Defaults to None. Database engine.
        meta (sqlqlchemy.schema.MetaData): Defaults to None. Schema Meta Data.
        platform (Platform): Basic SQL Statements because SQLAlchemy could not handle everything.
        sqlite_platform (SQLitePlatform): SQLite specific sql statements.
    """
    def __init__(self, app):
        """Set app and load platform handlers.

        Args:
            app (App): Framework App class.
        """
        self.app = app
        self.platform = Platform()
        self.sqlite_platform = SQLitePlatform()
        self.factory = ColumnFactory()
        self.engine = None
        self.meta = None
        self.session = None

    def set_engine(self, engine):
        """Set database engine, metadata store, and platform specific handlers.

        Args:
            engine (sqlalchemy.engine.Engine): Database engine
        """
        self.engine = engine
        self.meta = MetaData()
        self.meta.bind = self.engine
        self.meta.reflect()  # Reflecting All Tables at Once
        self.platform.set_engine(self.engine, self.meta)
        self.sqlite_platform.set_engine(self.engine, self.meta)

        # Create session
        session = sessionmaker(bind=engine)
        self.session = session()

    def has_table(self, table):
        """Check if the data store has a specific table.

        Args:
            table (str): Name of the Table

        Returns:
            boolean
        """
        inspector = inspect(self.engine)
        return table in inspector.get_table_names()

    def has_column(self, table, column):
        """Check if a table has a specific column.

        Args:
            table (str): Name of the table
            column (str): Name of the column

        Returns:
            boolean
        """
        inspector = inspect(self.engine)
        columns = inspector.get_columns(table)
        for col in columns:
            if col.get('name') == column:
                return True

        return False

    def drop(self, name, checkfirst=False):
        """Drop a table from the data store.

        Notes:
            http://docs.sqlalchemy.org/en/latest/core/metadata.html#creating-and-dropping-database-tables

        Args:
            name (str): Name of the table
            checkfirst (bool, optional): Defaults to False. Whether to check if exists first.
        """
        table = Table(name, self.meta)
        table.drop(self.engine, checkfirst=checkfirst)

    def drop_if_exists(self, name):
        """Drop a table from the datastore if it exists.

        Notes:
            http://docs.sqlalchemy.org/en/latest/core/metadata.html#creating-and-dropping-database-tables

        Args:
            name (str): Name of the table
        """
        table = Table(name, self.meta)
        table.drop(self.engine, checkfirst=True)

    def rename(self, old, new):
        """Rename a table.

        Args:
            old (str): Old table name
            new (str): New table name
        """
        self.engine.execute(self.platform.get_rename_sql(old, new))

    def create(self, blueprint):
        """Create a new Table with Columns and indexes.

        Notes:
            http://docs.sqlalchemy.org/en/latest/core/metadata.html#creating-and-dropping-database-tables

        Args:
            blueprint (Blueprint): The Blueprint to create the table
        """
        # Collection of columns and indexes
        data = self.factory.get_columns_and_indexes(blueprint)
        data['columns'].extend(data['indexes'])

        # Create table
        table = Table(blueprint.table,
                      self.meta,
                      *data['columns'],
                      extend_existing=True)
        table.create(self.engine, checkfirst=True)

    def alter(self, blueprint):
        """Alter Schema of the table.

        Args:
            blueprint (Blueprint): The new blueprint with updated schema.
        """
        # Get columns and indexes
        data = self.factory.get_columns_and_indexes(blueprint)

        # Alter SQLite Database
        if self.platform.is_sqlite():
            data['columns'].extend(data['indexes'])
            self.sqlite_platform.alter_table(blueprint.table, data['columns'],
                                             blueprint.dropped)
            return

        # Alter SQL Database -> Add Columns and keys
        table = Table(blueprint.table, self.meta, extend_existing=True)
        for column in data['columns']:
            if not self.has_column(blueprint.table, column.name):
                table.append_column(column)
                self.engine.execute(
                    self.platform.get_add_column_sql(blueprint.table, column))

            # Foreign Kyes and Primary Keys
            key_sql = self.platform.get_key_sql(blueprint.table, column)
            for sql in key_sql:
                self.engine.execute(sql)

        # Create indexes
        for index in data['indexes']:
            table.append_constraint(index)
            index.create()

        # Drop indexes
        for drop_idx in blueprint.dropped['indexes']:
            self.engine.execute(
                self.platform.get_drop_key_constraint_sql(
                    blueprint.table, table.columns[drop_idx['col']],
                    drop_idx['type'], drop_idx['name']))

        # Drop Columns
        drop_sql = self.platform.get_drop_columns_sql(
            blueprint.table,
            list(
                set(table.columns.keys()) & set(blueprint.dropped['columns'])))
        for sql in drop_sql:
            self.engine.execute(sql)
示例#7
0
 def test_type_mapping(self, column_type):
     factory = ColumnFactory()
     isinstance(factory.get_type(column_type['id']), column_type['impl'])
示例#8
0
    def test_sqlite_variants_mappings(self, variants):
        factory = ColumnFactory()

        _type = factory.get_type(variants['id']).__dict__
        assert isinstance(_type['mapping']['sqlite'], variants['sqlite'])
        assert isinstance(_type['impl'], variants['impl'])
示例#9
0
 def test_invalid_type_mapping(self, invalid_type):
     factory = ColumnFactory()
     assert factory.get_type(invalid_type) is None