'create a set of tuples representing column/string pairs for use
in an INSERT or UPDATE statement.
Also generates the Compiled object\'s postfetch, prefetch, and
returning column collections, used for default handling and ultimately
populating the ResultProxy\'s prefetch_cols() and postfetch_cols()
collections.'

def _get_colparams(self, stmt, **kw):

    self.postfetch = []
    self.prefetch = []
    self.returning = []
    if ((self.column_keys is None) and (stmt.parameters is None)):
        return [(c, self._create_crud_bind_param(c, None, required=True)) for c in stmt.table.columns]
    if stmt._has_multi_parameters:
        stmt_parameters = stmt.parameters[0]
    else:
        stmt_parameters = stmt.parameters
    (_column_as_key, _getattr_col_key, _col_bind_name) = self._key_getters_for_crud_column
    if (self.column_keys is None):
        parameters = {}
    else:
        parameters = dict(((_column_as_key(key), REQUIRED) for key in self.column_keys if ((not stmt_parameters) or (key not in stmt_parameters))))
    values = []
    if (stmt_parameters is not None):
        for (k, v) in stmt_parameters.items():
            colkey = _column_as_key(k)
            if (colkey is not None):
                parameters.setdefault(colkey, v)
            else:
                if elements._is_literal(v):
                    v = self.process(elements.BindParameter(None, v, type_=k.type), **kw)
                else:
                    v = self.process(v.self_group(), **kw)
                values.append((k, v))
    need_pks = (self.isinsert and (not self.inline) and (not stmt._returning))
    implicit_returning = (need_pks and self.dialect.implicit_returning and stmt.table.implicit_returning)
    if self.isinsert:
        implicit_return_defaults = (implicit_returning and stmt._return_defaults)
    elif self.isupdate:
        implicit_return_defaults = (self.dialect.implicit_returning and stmt.table.implicit_returning and stmt._return_defaults)
    if implicit_return_defaults:
        if (stmt._return_defaults is True):
            implicit_return_defaults = set(stmt.table.c)
        else:
            implicit_return_defaults = set(stmt._return_defaults)
    postfetch_lastrowid = (need_pks and self.dialect.postfetch_lastrowid)
    check_columns = {}
    if (self.isupdate and stmt._extra_froms and stmt_parameters):
        normalized_params = dict(((elements._clause_element_as_expr(c), param) for (c, param) in stmt_parameters.items()))
        affected_tables = set()
        for t in stmt._extra_froms:
            for c in t.c:
                if (c in normalized_params):
                    affected_tables.add(t)
                    check_columns[_getattr_col_key(c)] = c
                    value = normalized_params[c]
                    if elements._is_literal(value):
                        value = self._create_crud_bind_param(c, value, required=(value is REQUIRED), name=_col_bind_name(c))
                    else:
                        self.postfetch.append(c)
                        value = self.process(value.self_group(), **kw)
                    values.append((c, value))
        for t in affected_tables:
            for c in t.c:
                if (c in normalized_params):
                    continue
                elif ((c.onupdate is not None) and (not c.onupdate.is_sequence)):
                    if c.onupdate.is_clause_element:
                        values.append((c, self.process(c.onupdate.arg.self_group(), **kw)))
                        self.postfetch.append(c)
                    else:
                        values.append((c, self._create_crud_bind_param(c, None, name=_col_bind_name(c))))
                        self.prefetch.append(c)
                elif (c.server_onupdate is not None):
                    self.postfetch.append(c)
    if (self.isinsert and stmt.select_names):
        cols = (stmt.table.c[_column_as_key(name)] for name in stmt.select_names)
    else:
        cols = stmt.table.columns
    for c in cols:
        col_key = _getattr_col_key(c)
        if ((col_key in parameters) and (col_key not in check_columns)):
            value = parameters.pop(col_key)
            if elements._is_literal(value):
                value = self._create_crud_bind_param(c, value, required=(value is REQUIRED), name=(_col_bind_name(c) if (not stmt._has_multi_parameters) else ('%s_0' % _col_bind_name(c))))
            else:
                if (isinstance(value, elements.BindParameter) and value.type._isnull):
                    value = value._clone()
                    value.type = c.type
                if (c.primary_key and implicit_returning):
                    self.returning.append(c)
                    value = self.process(value.self_group(), **kw)
                elif (implicit_return_defaults and (c in implicit_return_defaults)):
                    self.returning.append(c)
                    value = self.process(value.self_group(), **kw)
                else:
                    self.postfetch.append(c)
                    value = self.process(value.self_group(), **kw)
            values.append((c, value))
        elif self.isinsert:
            if (c.primary_key and need_pks and (implicit_returning or (not postfetch_lastrowid) or (c is not stmt.table._autoincrement_column))):
                if implicit_returning:
                    if (c.default is not None):
                        if c.default.is_sequence:
                            if (self.dialect.supports_sequences and ((not c.default.optional) or (not self.dialect.sequences_optional))):
                                proc = self.process(c.default, **kw)
                                values.append((c, proc))
                            self.returning.append(c)
                        elif c.default.is_clause_element:
                            values.append((c, self.process(c.default.arg.self_group(), **kw)))
                            self.returning.append(c)
                        else:
                            values.append((c, self._create_crud_bind_param(c, None)))
                            self.prefetch.append(c)
                    else:
                        self.returning.append(c)
                elif (((c.default is not None) and ((not c.default.is_sequence) or self.dialect.supports_sequences)) or ((c is stmt.table._autoincrement_column) and (self.dialect.supports_sequences or self.dialect.preexecute_autoincrement_sequences))):
                    values.append((c, self._create_crud_bind_param(c, None)))
                    self.prefetch.append(c)
            elif (c.default is not None):
                if c.default.is_sequence:
                    if (self.dialect.supports_sequences and ((not c.default.optional) or (not self.dialect.sequences_optional))):
                        proc = self.process(c.default, **kw)
                        values.append((c, proc))
                        if (implicit_return_defaults and (c in implicit_return_defaults)):
                            self.returning.append(c)
                        elif (not c.primary_key):
                            self.postfetch.append(c)
                elif c.default.is_clause_element:
                    values.append((c, self.process(c.default.arg.self_group(), **kw)))
                    if (implicit_return_defaults and (c in implicit_return_defaults)):
                        self.returning.append(c)
                    elif (not c.primary_key):
                        self.postfetch.append(c)
                else:
                    values.append((c, self._create_crud_bind_param(c, None)))
                    self.prefetch.append(c)
            elif (c.server_default is not None):
                if (implicit_return_defaults and (c in implicit_return_defaults)):
                    self.returning.append(c)
                elif (not c.primary_key):
                    self.postfetch.append(c)
            elif (implicit_return_defaults and (c in implicit_return_defaults)):
                self.returning.append(c)
        elif self.isupdate:
            if ((c.onupdate is not None) and (not c.onupdate.is_sequence)):
                if c.onupdate.is_clause_element:
                    values.append((c, self.process(c.onupdate.arg.self_group(), **kw)))
                    if (implicit_return_defaults and (c in implicit_return_defaults)):
                        self.returning.append(c)
                    else:
                        self.postfetch.append(c)
                else:
                    values.append((c, self._create_crud_bind_param(c, None)))
                    self.prefetch.append(c)
            elif (c.server_onupdate is not None):
                if (implicit_return_defaults and (c in implicit_return_defaults)):
                    self.returning.append(c)
                else:
                    self.postfetch.append(c)
            elif (implicit_return_defaults and (c in implicit_return_defaults)):
                self.returning.append(c)
    if (parameters and stmt_parameters):
        check = set(parameters).intersection((_column_as_key(k) for k in stmt.parameters)).difference(check_columns)
        if check:
            raise exc.CompileError(('Unconsumed    column    names:    %s' % ',    '.join((('%s' % c) for c in check))))
    if stmt._has_multi_parameters:
        values_0 = values
        values = [values]
        values.extend(([(c, (self._create_crud_bind_param(c, row[c.key], name=('%s_%d' % (c.key, (i + 1)))) if (c.key in row) else param)) for (c, param) in values_0] for (i, row) in enumerate(stmt.parameters[1:])))
    return values
