示例#1
0
def get_trigger_tables():
    """Determines which tables need to have triggers set on them.

    Returns a dictionary of table names (key) with a dictionary (value) that
    provides additional information about a table:

        * list of primary keys for each table.
        * whether it's an entity table
    """
    tables = collections.OrderedDict()  # mapping of table names to their models and their "kind" (direct or not)
    for _, entity in SCHEMA.items():
        # Entity table itself
        mapped_class = class_mapper(entity.model)
        tables[mapped_class.mapped_table.name] = {
            "model": entity.model,
            "is_direct": True,
            "has_gid": mapped_class.has_property('gid'),
        }
        # Tables that contain the referenced column
        # TODO(roman): maybe come up with a better description above
        for path in unique_split_paths([path for field in entity.fields
                                             for path in field.paths if field.trigger]):
            model = last_model_in_path(entity.model, path)
            if model is not None:
                table_name = class_mapper(model).mapped_table.name
                if table_name not in tables:
                    tables[table_name] = {
                        "model": model,
                        "is_direct": False,
                    }

    return tables
示例#2
0
def get_trigger_tables():
    """Determines which tables need to have triggers set on them.

    Returns a dictionary of table names (key) with a dictionary (value) that
    provides additional information about a table:

        * list of primary keys for each table.
        * whether it's an entity table
    """
    tables = collections.OrderedDict(
    )  # mapping of table names to their models and their "kind" (direct or not)
    for _, entity in SCHEMA.items():
        # Entity table itself
        mapped_class = class_mapper(entity.model)
        tables[mapped_class.mapped_table.name] = {
            "model": entity.model,
            "is_direct": True,
            "has_gid": mapped_class.has_property('gid'),
        }
        # Tables that contain the referenced column
        # TODO(roman): maybe come up with a better description above
        for path in unique_split_paths(
            [path for field in entity.fields for path in field.paths]):
            model = last_model_in_path(entity.model, path)
            if model is not None:
                table_name = class_mapper(model).mapped_table.name
                if table_name not in tables:
                    tables[table_name] = {
                        "model": model,
                        "is_direct": False,
                    }

    return tables
示例#3
0
def generate_update_map():
    """
    Generates mapping from tables to Solr cores (entities) that depend on
    these tables and the columns of those tables. In addition provides a
    path along which data of an entity can be retrieved by performing a set
    of JOINs and a map of table names to SQLAlchemy ORM models

    Uses paths to determine the dependency.

    :rtype (dict, dict, dict)
    """
    from sir.trigger_generation.paths import (unique_split_paths, last_model_in_path,
                                             second_last_model_in_path)

    paths = defaultdict(set)
    models = {}
    column_map = defaultdict(set)
    for core_name, entity in SCHEMA.items():
        # Entity itself:
        # TODO(roman): See if the line below is necessary, if there is a better way to implement this.
        mapped_table = class_mapper(entity.model).mapped_table.name
        paths[mapped_table].add((core_name, None))
        models[mapped_table] = entity.model
        # Related tables:
        for path in unique_split_paths([path for field in entity.fields
                                        for path in field.paths] + [path for path in entity.extrapaths or []]):
            model = last_model_in_path(entity.model, path)
            if model is not None:
                name = class_mapper(model).mapped_table.name
                paths[name].add((core_name, path))
                if name not in models:
                    models[name] = model

            # For generating column map
            model, _ = second_last_model_in_path(entity.model, path)
            prop_name = path.split(".")[-1]
            actual_columns = [col.name for col in class_mapper(model).columns]
            try:
                prop = getattr(model, prop_name).prop
                # We only care about columns, not relations
                if isinstance(prop, (ColumnProperty, CompositeProperty)):
                    # In case of Composite properties, there might be more
                    # than 1 columns involved
                    column_names = [col.name for col in prop.columns if col.name in actual_columns]
                    column_map[model.__table__.name].update(column_names)
                elif isinstance(prop, RelationshipProperty):
                    if prop.direction.name == 'MANYTOONE':
                        if prop.key in actual_columns:
                            column_map[model.__table__.name].add(prop.key)
            # This happens in case of annotation and url paths
            # which have path to figure out the table name via transform funcs
            except AttributeError:
                pass
    return dict(paths), dict(column_map), models
示例#4
0
def generate_update_map():
    """
    Generates mapping from tables to Solr cores (entities) that depend on
    these tables and the columns of those tables. In addition provides a
    path along which data of an entity can be retrieved by performing a set
    of JOINs and a map of table names to SQLAlchemy ORM models and other useful
    mappings.

    Uses paths to determine the dependency.

    :rtype (dict, dict, dict, dict)
    """
    from sir.trigger_generation.paths import (unique_split_paths, last_model_in_path,
                                             second_last_model_in_path)

    paths = defaultdict(set)
    column_map = defaultdict(set)

    # Used to map table names to mbdata.models for indexing.
    models = {}
    # Used to map table names to core names while handling entity deletion.
    core_map = {}

    for core_name, entity in SCHEMA.items():
        # Entity itself:
        # TODO(roman): See if the line below is necessary, if there is a better way to implement this.
        mapped_table = class_mapper(entity.model).mapped_table.name
        core_map[mapped_table] = core_name
        paths[mapped_table].add((core_name, None))
        models[mapped_table] = entity.model
        # Related tables:
        for path in unique_split_paths([path for field in entity.fields
                                        for path in field.paths if field.trigger] + [path for path in entity.extrapaths or []]):
            model = last_model_in_path(entity.model, path)
            if model is not None:
                name = class_mapper(model).mapped_table.name
                paths[name].add((core_name, path))
                if name not in models:
                    models[name] = model

            # For generating column map
            model, _ = second_last_model_in_path(entity.model, path)
            prop_name = path.split(".")[-1]
            try:
                prop = getattr(model, prop_name).prop
                # We only care about columns, not relations
                if isinstance(prop, (ColumnProperty, CompositeProperty)):
                    # In case of Composite properties, there might be more
                    # than 1 columns involved
                    column_names = [col.name for col in prop.columns]
                    column_map[model.__table__.name].update(column_names)
                elif isinstance(prop, RelationshipProperty):
                    if prop.direction.name == 'MANYTOONE':
                        # We are assuming MB-DB uses only non-composite FKs.
                        # In case this changes in the future, `test.DBTest.test_non_composite_fk`
                        # will fail.
                        column_map[model.__table__.name].add(list(prop.local_columns)[0].name)
            # This happens in case of annotation and url paths
            # which have path to figure out the table name via transform funcs
            except AttributeError:
                pass
    return dict(paths), dict(column_map), models, core_map