예제 #1
0
def cleanup_entities(entities):
    """
    Try to revert back the list of entities passed as argument to the state
    they had just before their setup phase. It will not work entirely for
    autosetup entities as we need to remove the autosetup triggers.

    As of now, this function is *not* functional in that it doesn't revert to
    the exact same state the entities were before setup. For example, the
    properties do not work yet as those would need to be regenerated (since the
    columns they are based on are regenerated too -- and as such the
    corresponding joins are not correct) but this doesn't happen because of
    the way relationship setup is designed to be called only once (especially
    the backref stuff in create_properties).
    """
    for entity in entities:
        desc = entity._descriptor
        if desc.autosetup:
            _cleanup_autosetup_triggers(entity)

        if hasattr(entity, '_setup_done'):
            del entity._setup_done

        entity.table = None
        entity.mapper = None

        desc._pk_col_done = False
        desc.has_pk = False
        desc._columns = ColumnCollection()
        desc.constraints = []
        desc.properties = {}
예제 #2
0
    def __init__(self, entity):
        self.entity = entity
        self.parent = None

        bases = []
        for base in entity.__bases__:
            if isinstance(base, EntityMeta):
                if is_entity(base) and not is_abstract_entity(base):
                    if self.parent:
                        raise Exception(
                            '%s entity inherits from several entities, '
                            'and this is not supported.'
                            % self.entity.__name__)
                    else:
                        self.parent = base
                        bases.extend(base._descriptor.bases)
                        self.parent._descriptor.children.append(entity)
                else:
                    bases.append(base)
        self.bases = bases
        if not is_entity(entity) or is_abstract_entity(entity):
            return

        # entity.__module__ is not always reliable (eg in mod_python)
        self.module = sys.modules.get(entity.__module__)

        self.builders = []

        #XXX: use entity.__subclasses__ ?
        self.children = []

        # used for multi-table inheritance
        self.join_condition = None
        self.has_pk = False
        self._pk_col_done = False

        # columns and constraints waiting for a table to exist
        self._columns = ColumnCollection()
        self.constraints = []

        # properties (it is only useful for checking dupe properties at the
        # moment, and when adding properties before the mapper is created,
        # which shouldn't happen).
        self.properties = {}

        #
        self.relationships = []

        # set default value for options
        self.table_args = []

        # base class(es) options_defaults
        options_defaults = self.options_defaults()

        complete_defaults = options.options_defaults.copy()
        complete_defaults.update({
            'metadata': elixir.metadata,
            'session': elixir.session,
            'collection': elixir.entities
        })

        # set default value for other options
        for key in options.valid_options:
            value = options_defaults.get(key, complete_defaults[key])
            if isinstance(value, dict):
                value = value.copy()
            setattr(self, key, value)

        # override options with module-level defaults defined
        for key in ('metadata', 'session', 'collection'):
            attr = '__%s__' % key
            if hasattr(self.module, attr):
                setattr(self, key, getattr(self.module, attr))
                
        if (tools.config['ecfserver.dbschema.name'] not in (None, '')):
          self.table_options['schema'] = tools.config['ecfserver.dbschema.name']
        else:
          self.table_options['schema'] = None
예제 #3
0
파일: ddl.py 프로젝트: unicef/datamart-etl
def adapt_schema(source: Engine,
                 destination: Engine,
                 tenant="bolivia",
                 echo=None):  # noqa: C901
    tables = get_all_tables(source, tenant, public=False)
    destMeta = MetaData(destination, schema="public")

    # pk = Column('id', Integer, primary_key=True)
    fks = []
    processed = []
    if echo:
        write = echo.write
    else:
        write = lambda x: True

    constraints = []

    write(f"Start adapting schema {tenant}\n")

    for table, deps in tables:
        if table is None:
            continue
        if table.name in processed:
            continue
        # if table.name not in ['audit_spotcheck', 'audit_engagement']:
        #     continue

        if table.schema and table.schema != 'public':
            write(".")
            table.schema = "public"
            new_columns = ColumnCollection()
            primary_key = {
                c
                for c in table.constraints
                if isinstance(c, PrimaryKeyConstraint)
            }
            table.constraints = {
                c
                for c in table.constraints
                if not isinstance(c, PrimaryKeyConstraint)
            }
            # remove self relation
            # to_remove = []
            # for constraint in table.constraints:
            #     if isinstance(constraint, ForeignKeyConstraint) and constraint.referred_table == table:
            #         self_relations.append({'columns': constraint.column_keys,
            #                                'table': table.name,
            #                                'constraint': constraint}
            #                               )
            #         to_remove.append(constraint)
            # table.constraints = table.constraints.difference(to_remove)
            # if table.name == 'audit_spotcheck':
            #     import pdb; pdb.set_trace()
            for col in table.columns:
                if col.primary_key:
                    _seq = Column('pk',
                                  Integer,
                                  autoincrement=True,
                                  unique=True)
                    pk = Column(col.name, Integer, primary_key=True)
                    country_name = Column('country_name',
                                          String,
                                          default='public',
                                          primary_key=True)

                    new_columns.add(_seq)
                    new_columns.add(pk)
                    new_columns.add(country_name)

                    table.primary_key.columns.add(country_name)
                    if col.foreign_keys:
                        fk = [c for c in col.foreign_keys][0]
                        table.constraints.remove(fk.constraint)
                        fks.append({
                            'columns': (pk.name, country_name.name),
                            'refcolumns':
                            fk.constraint.referred_table.primary_key.columns.
                            keys(),
                            'source':
                            table,
                            'target':
                            fk.constraint.referred_table
                        })

                elif col.foreign_keys:
                    fk = [c for c in col.foreign_keys][0]
                    if fk.constraint.referred_table.schema:
                        _fk = Column(col.name, Integer, nullable=col.nullable)
                        _country_name = Column(
                            get_schema_fieldname(
                                col),  # f'{target}_country_name',
                            String,
                            nullable=col.nullable)
                        table.constraints.remove(fk.constraint)
                        new_columns.add(_fk)
                        new_columns.add(_country_name)
                        fks.append({
                            'columns': (_fk.name, _country_name.name),
                            'refcolumns':
                            fk.constraint.referred_table.primary_key.columns.
                            keys(),
                            'source':
                            table,
                            'target':
                            fk.constraint.referred_table
                        })
                    else:
                        new_columns.add(col)
                else:
                    new_columns.add(col)
            table.columns = new_columns
            constraints.extend(table.constraints)
            table.constraints = primary_key
        else:
            pass
        processed.append(table.name)
        try:
            table.tometadata(destMeta)
        except Exception as e:
            raise Exception(f"Error processing {table.name}") from e

    destMeta.create_all()

    write("\nCreating foreign keys constraints\n")
    for entry in fks:
        clause = f"ALTER TABLE {entry['source'].name} \
ADD CONSTRAINT FK_{entry['target'].name} \
FOREIGN KEY({','.join(entry['columns'])}) \
REFERENCES {entry['target'].name}({','.join(entry['refcolumns'])})"

        try:
            destination.execute(str(clause))
        except Exception as e:
            print(str(e))
            print(CreateTable(entry['source']))
            print(clause)
            raise Exception(clause) from e

    write("Creating remaining constraints\n")
    for constraint in constraints:
        clause = AddConstraint(constraint)
        # if type(constraint.sqltext) is BinaryExpression:
        #     continue
        try:
            destination.execute(str(clause))
        except Exception as e:
            if isinstance(clause.element.columns.values()[0].type, BOOLEAN):
                pass
            else:
                print(e)
                print(CreateTable(constraint.table))
                print(clause)
                raise Exception(clause) from e

    # write("\nCreating self-relations constraint\n")
    # for self_relation in self_relations:
    #     constraint = self_relation['constraint']
    #     clause = f"ALTER TABLE {constraint.table.name} " \
    #              f"ADD CONSTRAINT self_relation_{constraint.table.name} " \
    #              f"FOREIGN KEY({constraint.column_keys[0]}) " \
    #              f"REFERENCES {constraint.table.name}(pk)"
    #     # TODO: remove me
    #     print(111, "ddl.py:167", clause)
    #     destination.execute(clause)
    #
    return tables