<commit_before># -*- coding: utf-8 -*-
# Copyright 2018 Tecnativa - <NAME>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

import logging
import functools
from psycopg2.extensions import AsIs
from .openupgrade import logged_query
from .openupgrade_tools import column_exists, table_exists

logger = logging.getLogger('OpenUpgrade')
logger.setLevel(logging.DEBUG)


def _change_many2one_refs_sql(env, model_name, record_ids, target_record_id):
    cr = env.cr
    cr.execute("""
        SELECT name, model
        FROM ir_model_fields
        WHERE ttype='many2one' AND relation=%s
        """, (model_name, ))
    for row in cr.dictfetchall():
        try:
            model = env[row['model']]
        except KeyError:
            continue
        if not model._auto:  # Discard SQL views
            continue
        table = model._table
        if not table_exists(cr, table):
            continue
        column1 = row['name']
        if not column_exists(cr, table, column1):
            # TODO: It can be a company dependent field
            continue
        logged_query(
            cr, "UPDATE %s SET %s = %s WHERE %s IN %s", (
                AsIs(table), AsIs(column1), target_record_id, AsIs(column1),
                tuple(record_ids),
            ), skip_no_result=True,
        )


def _change_many2one_refs_orm(env, model_name, record_ids, target_record_id):
    fields = env['ir.model.fields'].search([
        ('ttype', '=', 'many2one'),
        ('relation', '=', model_name),
    ])
    for field in fields:
        try:
            model = env[field.model]
        except KeyError:
            continue
        field_name = field.name
        if not model._auto or not model._fields.get(field_name):
            continue  # Discard SQL views + invalid fields
        records = model.search([(field_name, 'in', record_ids)])
        if records:
            records.write({field_name: target_record_id})
            logger.debug(
                "Changed %s record(s) in many2one field '%s' of model '%s'",
                len(records), field_name, field.model,
            )


def _change_many2many_refs_sql(env, model_name, record_ids, target_record_id):
    cr = env.cr
    cr.execute("""
        SELECT name, model
        FROM ir_model_fields
        WHERE ttype='many2many' AND relation=%s
        """, (model_name, ))
    for row in cr.dictfetchall():
        try:
            model = env[row['model']]
            field = model._fields[row['name']]
        except KeyError:
            continue
        if not model._auto:  # Discard SQL views
            continue
        table = field.relation
        if not table or not table_exists(cr, table):
            continue
        column1 = field.column1
        if not column1 or not column_exists(cr, table, column1):
            continue
        column2 = field.column2
        if not column2 or not column_exists(cr, table, column2):
            continue
        # Strategy: Get all possible distinct column2 values, delete entries of
        # "to merge" records, and try to insert again with the target record
        # value
        cr.execute("""SELECT DISTINCT(%s) FROM %s WHERE %s IN %s""", (
            AsIs(column1), AsIs(table), AsIs(column2), tuple(record_ids),
        ))
        column1_ids = [x[0] for x in cr.fetchall()]
        if not column1_ids:
            continue
        logged_query(
            cr, "DELETE FROM %s WHERE %s IN %s", (
                AsIs(table), AsIs(column2), tuple(record_ids),
            ),
        )
        logged_query(
            cr, """
            INSERT INTO %s (%s, %s)
            VALUES (%s, unnest(array%s))
            ON CONFLICT DO NOTHING""", (
                AsIs(table), AsIs(column2), AsIs(column1), target_record_id,
                AsIs(str(column1_ids)),
            ),
        )


def _change_many2many_refs_orm(env, model_name, record_ids, target_record_id):
    fields = env['ir.model.fields'].search([
        ('ttype', '=', 'many2many'),
        ('relation', '=', model_name),
    ])
    for field in fields:
        try:
            model = env[field.model]
        except KeyError:
            continue
        field_name = field.name
        if not model._auto or not model._fields.get(field_name):
            continue  # Discard SQL views + invalid fields
        records = model.search([(field_name, 'in', record_ids)])
        if records:
            records.write({
                field_name: (
                    [(3, x) for x in record_ids] + [(4, target_record_id)]
                ),
            })
            logger.debug(
                "Changed %s record(s) in many2many field '%s' of model '%s'",
                len(records), field_name, field.model,
            )


def _change_reference_refs_sql(env, model_name, record_ids, target_record_id):
    cr = env.cr
    cr.execute("""
        SELECT name, model
        FROM ir_model_fields
        WHERE ttype='reference'
        """, (model_name, ))
    for row in cr.dictfetchall():
        try:
            model = env[row['model']]
        except KeyError:
            continue
        if not model._auto:  # Discard SQL views
            continue
        table = model._table
        if not table_exists(cr, table):
            continue
        column = row['name']
        if not column_exists(cr, table, column):
            continue
        where = ' OR '.join(
            ['%s = %s,%s' % (row['name'], model_name, x) for x in record_ids]
        )
        logged_query(
            cr, """
            UPDATE %s
            SET %s = %s
            WHERE %s
            """, (
                AsIs(table), AsIs(column),
                '%s,%s' % (model_name, target_record_id), AsIs(where)
            ), skip_no_result=True,
        )


def _change_reference_refs_orm(env, model_name, record_ids, target_record_id):
    fields = env['ir.model.fields'].search([('ttype', '=', 'reference')])
    for field in fields:
        try:
            model = env[field.model]
        except KeyError:
            continue
        field_name = field.name
        if not model._auto or not model._fields.get(field_name):
            continue  # Discard SQL views + invalid fields
        expr = ['%s,%s' % (model_name, x) for x in record_ids]<commit_msg>[IMP] openupgrade_merge_records: Don't perform any change on non-stored fields<commit_after># -*- coding: utf-8 -*-
# Copyright 2018 Tecnativa - <NAME>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

import logging
import functools
from psycopg2.extensions import AsIs
from .openupgrade import logged_query
from .openupgrade_tools import column_exists, table_exists

logger = logging.getLogger('OpenUpgrade')
logger.setLevel(logging.DEBUG)


def _change_many2one_refs_sql(env, model_name, record_ids, target_record_id):
    cr = env.cr
    cr.execute("""
        SELECT name, model
        FROM ir_model_fields
        WHERE ttype='many2one' AND relation=%s
        """, (model_name, ))
    for row in cr.dictfetchall():
        try:
            model = env[row['model']]
        except KeyError:
            continue
        if not model._auto:  # Discard SQL views
            continue
        table = model._table
        if not table_exists(cr, table):
            continue
        column1 = row['name']
        if not column_exists(cr, table, column1):
            # TODO: It can be a company dependent field
            continue
        logged_query(
            cr, "UPDATE %s SET %s = %s WHERE %s IN %s", (
                AsIs(table), AsIs(column1), target_record_id, AsIs(column1),
                tuple(record_ids),
            ), skip_no_result=True,
        )


def _change_many2one_refs_orm(env, model_name, record_ids, target_record_id):
    fields = env['ir.model.fields'].search([
        ('ttype', '=', 'many2one'),
        ('relation', '=', model_name),
    ])
    for field in fields:
        try:
            model = env[field.model]
        except KeyError:
            continue
        field_name = field.name
        if (not model._auto or not model._fields.get(field_name) or
                not field.store):
            continue  # Discard SQL views + invalid fields + non-stored fields
        records = model.search([(field_name, 'in', record_ids)])
        if records:
            records.write({field_name: target_record_id})
            logger.debug(
                "Changed %s record(s) in many2one field '%s' of model '%s'",
                len(records), field_name, field.model,
            )


def _change_many2many_refs_sql(env, model_name, record_ids, target_record_id):
    cr = env.cr
    cr.execute("""
        SELECT name, model
        FROM ir_model_fields
        WHERE ttype='many2many' AND relation=%s
        """, (model_name, ))
    for row in cr.dictfetchall():
        try:
            model = env[row['model']]
            field = model._fields[row['name']]
        except KeyError:
            continue
        if not model._auto:  # Discard SQL views
            continue
        table = field.relation
        if not table or not table_exists(cr, table):
            continue
        column1 = field.column1
        if not column1 or not column_exists(cr, table, column1):
            continue
        column2 = field.column2
        if not column2 or not column_exists(cr, table, column2):
            continue
        # Strategy: Get all possible distinct column2 values, delete entries of
        # "to merge" records, and try to insert again with the target record
        # value
        cr.execute("""SELECT DISTINCT(%s) FROM %s WHERE %s IN %s""", (
            AsIs(column1), AsIs(table), AsIs(column2), tuple(record_ids),
        ))
        column1_ids = [x[0] for x in cr.fetchall()]
        if not column1_ids:
            continue
        logged_query(
            cr, "DELETE FROM %s WHERE %s IN %s", (
                AsIs(table), AsIs(column2), tuple(record_ids),
            ),
        )
        logged_query(
            cr, """
            INSERT INTO %s (%s, %s)
            VALUES (%s, unnest(array%s))
            ON CONFLICT DO NOTHING""", (
                AsIs(table), AsIs(column2), AsIs(column1), target_record_id,
                AsIs(str(column1_ids)),
            ),
        )


def _change_many2many_refs_orm(env, model_name, record_ids, target_record_id):
    fields = env['ir.model.fields'].search([
        ('ttype', '=', 'many2many'),
        ('relation', '=', model_name),
    ])
    for field in fields:
        try:
            model = env[field.model]
        except KeyError:
            continue
        field_name = field.name
        if (not model._auto or not model._fields.get(field_name) or
                not field.store):
            continue  # Discard SQL views + invalid fields + non-stored fields
        records = model.search([(field_name, 'in', record_ids)])
        if records:
            records.write({
                field_name: (
                    [(3, x) for x in record_ids] + [(4, target_record_id)]
                ),
            })
            logger.debug(
                "Changed %s record(s) in many2many field '%s' of model '%s'",
                len(records), field_name, field.model,
            )


def _change_reference_refs_sql(env, model_name, record_ids, target_record_id):
    cr = env.cr
    cr.execute("""
        SELECT name, model
        FROM ir_model_fields
        WHERE ttype='reference'
        """, (model_name, ))
    for row in cr.dictfetchall():
        try:
            model = env[row['model']]
        except KeyError:
            continue
        if not model._auto:  # Discard SQL views
            continue
        table = model._table
        if not table_exists(cr, table):
            continue
        column = row['name']
        if not column_exists(cr, table, column):
            continue
        where = ' OR '.join(
            ['%s = %s,%s' % (row['name'], model_name, x) for x in record_ids]
        )
        logged_query(
            cr, """
            UPDATE %s
            SET %s = %s
            WHERE %s
            """, (
                AsIs(table), AsIs(column),
                '%s,%s' % (model_name, target_record_id), AsIs(where)
            ), skip_no_result=True,
        )


def _change_reference_refs_orm(env, model_name, record_ids, target_record_id):
    fields = env['ir.model.fields'].search([('ttype', '=', 'reference')])
    for field in fields:
        try:
            model = env[field.model]
        except KeyError:
            continue
        field_name = field.name
        if (not model._auto or not model._fields.get(field_name) or
                not field.store):
            continue  # Discard SQL views + invalid fields + non-stored fields
        expr = ['%s,%s' % (model_name, x) for x in record_ids]
{'fraction_non_alphanumeric': 0.11067748985326256, 'fraction_numerical': 0.006556353418669997, 'mean_word_length': 1.8871113114015323, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3214978', 'n_tokens_mistral': 3816, 'n_tokens_neox': 3729, 'n_words': 1002}