Example #1
0
def _collect_delete_commands(base_mapper, uowtransaction, table, 
                                states_to_delete):
    """Identify values to use in DELETE statements for a list of 
    states to be deleted."""

    delete = util.defaultdict(list)

    for state, state_dict, mapper, has_identity, connection \
                                        in states_to_delete:
        if not has_identity or table not in mapper._pks_by_table:
            continue

        params = {}
        delete[connection].append(params)
        for col in mapper._pks_by_table[table]:
            params[col.key] = \
                    value = \
                    mapper._get_state_attr_by_column(
                                    state, state_dict, col)
            if value is None:
                raise sa_exc.FlushError(
                            "Can't delete from table "
                            "using NULL for primary "
                            "key value")

        if mapper.version_id_col is not None and \
                    table.c.contains_column(mapper.version_id_col):
            params[mapper.version_id_col.key] = \
                        mapper._get_committed_state_attr_by_column(
                                state, state_dict,
                                mapper.version_id_col)
    return delete
Example #2
0
def _collect_update_commands(base_mapper, uowtransaction, 
                                table, states_to_update):
    """Identify sets of values to use in UPDATE statements for a
    list of states.
    
    This function works intricately with the history system
    to determine exactly what values should be updated
    as well as how the row should be matched within an UPDATE
    statement.  Includes some tricky scenarios where the primary
    key of an object might have been changed.

    """

    update = []
    for state, state_dict, mapper, connection, has_identity, \
                    instance_key, row_switch in states_to_update:
        if table not in mapper._pks_by_table:
            continue

        pks = mapper._pks_by_table[table]

        params = {}
        value_params = {}

        hasdata = hasnull = False
        for col in mapper._cols_by_table[table]:
            if col is mapper.version_id_col:
                params[col._label] = \
                    mapper._get_committed_state_attr_by_column(
                                    row_switch or state, 
                                    row_switch and row_switch.dict 
                                                or state_dict,
                                    col)

                prop = mapper._columntoproperty[col]
                history = attributes.get_state_history(
                    state, prop.key, 
                    attributes.PASSIVE_NO_INITIALIZE
                )
                if history.added:
                    params[col.key] = history.added[0]
                    hasdata = True
                else:
                    params[col.key] = mapper.version_id_generator(
                                                params[col._label])

                    # HACK: check for history, in case the 
                    # history is only
                    # in a different table than the one 
                    # where the version_id_col is.
                    for prop in mapper._columntoproperty.itervalues():
                        history = attributes.get_state_history(
                                state, prop.key, 
                                attributes.PASSIVE_NO_INITIALIZE)
                        if history.added:
                            hasdata = True
            else:
                prop = mapper._columntoproperty[col]
                history = attributes.get_state_history(
                                state, prop.key, 
                                attributes.PASSIVE_NO_INITIALIZE)
                if history.added:
                    if isinstance(history.added[0],
                                    sql.ClauseElement):
                        value_params[col] = history.added[0]
                    else:
                        value = history.added[0]
                        params[col.key] = value

                    if col in pks:
                        if history.deleted and \
                            not row_switch:
                            # if passive_updates and sync detected
                            # this was a  pk->pk sync, use the new
                            # value to locate the row, since the
                            # DB would already have set this
                            if ("pk_cascaded", state, col) in \
                                            uowtransaction.attributes:
                                value = history.added[0]
                                params[col._label] = value
                            else:
                                # use the old value to 
                                # locate the row
                                value = history.deleted[0]
                                params[col._label] = value
                            hasdata = True
                        else:
                            # row switch logic can reach us here
                            # remove the pk from the update params
                            # so the update doesn't
                            # attempt to include the pk in the
                            # update statement
                            del params[col.key]
                            value = history.added[0]
                            params[col._label] = value
                        if value is None:
                            hasnull = True
                    else:
                        hasdata = True
                elif col in pks:
                    value = state.manager[prop.key].impl.get(
                                                    state, state_dict)
                    if value is None:
                        hasnull = True
                    params[col._label] = value
        if hasdata:
            if hasnull:
                raise sa_exc.FlushError(
                            "Can't update table "
                            "using NULL for primary "
                            "key value")
            update.append((state, state_dict, params, mapper, 
                            connection, value_params))
    return update