def _fetch(
    queryset, model_objs, unique_fields, update_fields, returning, sync,
    ignore_duplicate_updates=True, return_untouched=False
):
    """
    Perfom the upsert and do an optional sync operation
    """
    model = queryset.model
    if (return_untouched or sync) and returning is not True:
        returning = set(returning) if returning else set()
        returning.add(model._meta.pk.name)
    upserted = []
    deleted = []
    # We must return untouched rows when doing a sync operation
    return_untouched = True if sync else return_untouched

    if model_objs:
        sql, sql_args = _get_upsert_sql(queryset, model_objs, unique_fields, update_fields, returning,
                                        ignore_duplicate_updates=ignore_duplicate_updates,
                                        return_untouched=return_untouched)

        with connection.cursor() as cursor:
            cursor.execute(sql, sql_args)
            if cursor.description:
                nt_result = namedtuple('Result', [col[0] for col in cursor.description])
                upserted = [nt_result(*row) for row in cursor.fetchall()]

    pk_field = model._meta.pk.name
    if sync:
        orig_ids = queryset.values_list(pk_field, flat=True)
        deleted = set(orig_ids) - {getattr(r, pk_field) for r in upserted}
        model.objects.filter(pk__in=deleted).delete()

    nt_deleted_result = namedtuple('DeletedResult', [model._meta.pk.name, 'status_'])
    return UpsertResult(
        upserted + [nt_deleted_result(**{pk_field: d, 'status_': 'd'}) for d in deleted]
    )
Perfom the upsert and do an optional sync operation