def name_search(self, cr, uid, name, args=None,
                    operator='ilike', context=None, limit=100):
        if not args:
            args = []
        if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'):

            self.check_access_rights(cr, uid, 'read')
            where_query = self._where_calc(cr, uid, args, context=context)
            self._apply_ir_rules(cr, uid, where_query, 'read', context=context)
            from_clause, where_clause, where_clause_params =\
                where_query.get_sql()
            where_str =\
                where_clause and (" WHERE %s AND " % where_clause) or ' WHERE '

            # search on the name of the contacts and of its company
            search_name = name
            if operator in ('ilike', 'like'):
                search_name = '%%%s%%' % name
            if operator in ('=ilike', '=like'):
                operator = operator[1:]

            unaccent = get_unaccent_wrapper(cr)

            query = """SELECT id
                         FROM res_partner
                      {where} ({email} {operator} {percent}
                           OR {display_name} {operator} {percent})
                     ORDER BY {display_name}
                    """.format(where=where_str, operator=operator,
                               email=unaccent('email'),
                               display_name=unaccent('display_name'),
                               percent=unaccent('%s'))

            where_clause_params += [search_name, search_name]
            if limit:
                query += ' limit %s'
                where_clause_params.append(limit)
            cr.execute(query, where_clause_params)
            ids = map(lambda x: x[0], cr.fetchall())
            # patch for record from translation
            translation_obj = self.pool.get('ir.translation')
            trans_name = '%s,%s' % (self._model, 'name')
            translation_ids =\
                translation_obj.search(cr, uid, [('value', 'ilike', name),
                                                 ('name', '=', trans_name)],
                                       limit=limit, context=context)
            translations = translation_obj.browse(cr, uid,
                                                  translation_ids,
                                                  context=context)
            record_ids = [t.res_id for t in translations]
            ids = list(set(ids) | set(record_ids))
            # patch over
            if ids:
                return self.name_get(cr, uid, ids, context)
            else:
                return []
        return super(ResPartner, self).name_search(cr, uid, name, args,
                                                   operator=operator,
                                                   context=context,
                                                   limit=limit)
Beispiel #2
0
    def name_search(self,
                    cr,
                    uid,
                    name,
                    args=None,
                    operator='ilike',
                    context=None,
                    limit=100):
        if not args:
            args = []
        if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'):

            self.check_access_rights(cr, uid, 'read')
            where_query = self._where_calc(cr, uid, args, context=context)
            self._apply_ir_rules(cr, uid, where_query, 'read', context=context)
            from_clause, where_clause, where_clause_params = where_query.get_sql(
            )
            where_str = where_clause and (" WHERE %s AND " %
                                          where_clause) or ' WHERE '

            # search on the name of the contacts and of its company
            search_name = name
            if operator in ('ilike', 'like'):
                search_name = '%%%s%%' % name
            if operator in ('=ilike', '=like'):
                operator = operator[1:]

            unaccent = get_unaccent_wrapper(cr)

            query = """SELECT id
                         FROM res_partner
                      {where} ({email} {operator} {percent}
                           OR {display_name} {operator} {percent}
                           OR {city} {operator} {percent})
                     ORDER BY {display_name}
                    """.format(where=where_str,
                               operator=operator,
                               email=unaccent('email'),
                               display_name=unaccent('display_name'),
                               city=unaccent('city'),
                               percent=unaccent('%s'))

            where_clause_params += [search_name, search_name, search_name]
            if limit:
                query += ' limit %s'
                where_clause_params.append(limit)
            cr.execute(query, where_clause_params)
            ids = map(lambda x: x[0], cr.fetchall())

            if ids:
                return self.name_get(cr, uid, ids, context)
            else:
                return []
        return super(res_partner, self).name_search(cr,
                                                    uid,
                                                    name,
                                                    args,
                                                    operator=operator,
                                                    context=context,
                                                    limit=limit)
Beispiel #3
0
    def name_search(
            self, cr, uid, name, args=None, operator='ilike', context=None,
            limit=100):
        if not args:
            args = []
        if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'):
            unaccent = get_unaccent_wrapper(cr)
            self.check_access_rights(cr, uid, 'read')
            where_query = self._where_calc(cr, uid, args, context=context)
            self._apply_ir_rules(cr, uid, where_query, 'read', context=context)
            from_clause, where_clause, where_clause_params =\
                where_query.get_sql()
            where_str = where_clause\
                and (" WHERE %s AND " % where_clause) or ' WHERE '

            if "product_product__product_tmpl_id" not in from_clause:
                from_clause +=\
                    ',"product_template" as "product_product__product_tmpl_id"'
            if operator in ('ilike', 'like'):
                percent = True
            if operator in ('=ilike', '=like'):
                operator = operator[1:]

            names = name.split(self._SEPARATOR)
            pwc = ""
            for n in names:
                search_name = '%%%s%%' % n if percent else n
                pwc += """ AND ({display_name} {operator} {percent})
                """.format(
                    operator=operator, percent=unaccent('%s'),
                    display_name=unaccent(
                        'product_product__product_tmpl_id.name'))
                where_clause_params += [search_name]
            pwc = pwc[5:]

            query = """SELECT product_product.id
                         FROM {from_clause}
                      {where} ({pwc})
                     ORDER BY {display_name}
                    """.format(
                    from_clause=from_clause, where=where_str, pwc=pwc,
                    display_name=unaccent(
                        'product_product__product_tmpl_id.name'))

            if limit:
                query += ' limit %s'
                where_clause_params.append(limit)

            cr.execute(query, where_clause_params)
            ids = map(lambda x: x[0], cr.fetchall())

            if ids:
                return self.name_get(cr, uid, ids, context)
            else:
                return []
        return super(product_product, self).name_search(
            cr, uid, name, args, operator=operator, context=context,
            limit=limit)
Beispiel #4
0
    def name_search(self,
                    cr,
                    uid,
                    name,
                    args=None,
                    operator='ilike',
                    context=None,
                    limit=100):
        if not args:
            args = []
        if name and operator in ('=', 'ilike', '=ilike', 'like',
                                 '=like') and len(name) >= 3:
            self.check_access_rights(cr, uid, 'read')
            where_query = self._where_calc(cr, uid, args, context=context)
            self._apply_ir_rules(cr, uid, where_query, 'read', context=context)
            from_clause, where_clause, where_clause_params = where_query.get_sql(
            )
            where_str = where_clause and (" WHERE %s AND " %
                                          where_clause) or ' WHERE '

            # search on the name of the contacts and of its company
            search_name = name
            operator = 'like'
            if operator in ('ilike', 'like'):
                search_name = '%%%s%%' % name
            if operator in ('=ilike', '=like'):
                operator = operator[1:]
            unaccent = get_unaccent_wrapper(cr)
            where_str = where_str.replace('"res_partner"', 'p')
            query = """SELECT p.id
                         FROM res_partner p
                      {where} (upper(p.{display_name}) {operator} {percent}
                           OR upper(p.{default_code}) {operator} {percent}
                           OR upper(p.{member}) {operator} {percent})
                     ORDER BY p.{display_name}, p.{default_code}
                    """.format(where=where_str,
                               operator=operator,
                               display_name=unaccent('display_name'),
                               default_code=unaccent('default_code'),
                               member=unaccent('member'),
                               percent=unaccent('%s'))
            where_clause_params += [
                search_name.upper(),
                search_name.upper(),
                search_name.upper()
            ]
            if limit:
                query += ' limit %s'
                where_clause_params.append(limit)
            cr.execute(query, where_clause_params)
            ids = map(lambda x: x[0], cr.fetchall())

            if ids:
                return self.name_get(cr, uid, ids, context)
            else:
                return []
        return []
    def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
        if not args:
            args = []
        if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'):

            self.check_access_rights(cr, uid, 'read')
            where_query = self._where_calc(cr, uid, args, context=context)
            self._apply_ir_rules(cr, uid, where_query, 'read', context=context)
            from_clause, where_clause, where_clause_params = where_query.get_sql()
            where_str = where_clause and (" WHERE %s AND " % where_clause) or ' WHERE '

            # search on the name of the contacts and of its company
            search_name = name
            if operator in ('ilike', 'like'):
                search_name = '%%%s%%' % name
            if operator in ('=ilike', '=like'):
                operator = operator[1:]

            unaccent = get_unaccent_wrapper(cr)

            # TODO: simplify this in trunk with `display_name`, once it is stored
            # Perf note: a CTE expression (WITH ...) seems to have an even higher cost
            #            than this query with duplicated CASE expressions. The bulk of
            #            the cost is the ORDER BY, and it is inevitable if we want
            #            relevant results for the next step, otherwise we'd return
            #            a random selection of `limit` results.

            display_name = """CASE WHEN company.id IS NULL OR res_partner.is_company
                                   THEN {partner_name}
                                   ELSE {company_name} || ', ' || {partner_name}
                               END""".format(partner_name=unaccent('res_partner.name'),
                                             company_name=unaccent('company.name'))

            query = """SELECT res_partner.id
                         FROM res_partner
                    LEFT JOIN res_partner company
                           ON res_partner.parent_id = company.id
                      {where} ({email} {operator} {percent}
                           OR {display_name} {operator} {percent})
                     ORDER BY {display_name}
                    """.format(where=where_str, operator=operator,
                               email=unaccent('res_partner.email'),
                               percent=unaccent('%s'),
                               display_name=display_name)

            where_clause_params += [search_name, search_name]
            if limit:
                query += ' limit %s'
                where_clause_params.append(limit)
            cr.execute(query, where_clause_params)
            ids = map(lambda x: x[0], cr.fetchall())

            if ids:
                return self.name_get(cr, uid, ids, context)
            else:
                return []
        return super(res_partner,self).name_search(cr, uid, name, args, operator=operator, context=context, limit=limit)
Beispiel #6
0
    def name_search(self, cr, uid, name, args=None, operator="ilike", context=None, limit=100):
        if not args:
            args = []
        if name and operator in ("=", "ilike", "=ilike", "like", "=like"):

            self.check_access_rights(cr, uid, "read")
            where_query = self._where_calc(cr, uid, args, context=context)
            self._apply_ir_rules(cr, uid, where_query, "read", context=context)
            from_clause, where_clause, where_clause_params = where_query.get_sql()
            where_str = where_clause and (" WHERE %s AND " % where_clause) or " WHERE "

            # search on the name of the contacts and of its company
            search_name = name
            if operator in ("ilike", "like"):
                search_name = "%%%s%%" % name
            if operator in ("=ilike", "=like"):
                operator = operator[1:]

            unaccent = get_unaccent_wrapper(cr)

            query = """SELECT id
                         FROM res_partner
                      {where} ({email} {operator} {percent}
                           OR {display_name} {operator} {percent}
                           OR {reference} {operator} {percent})
                           -- don't panic, trust postgres bitmap
                     ORDER BY {display_name} {operator} {percent} desc,
                              {display_name}
                    """.format(
                where=where_str,
                operator=operator,
                email=unaccent("email"),
                display_name=unaccent("display_name"),
                reference=unaccent("ref"),
                percent=unaccent("%s"),
            )

            where_clause_params += [search_name] * 4
            if limit:
                query += " limit %s"
                where_clause_params.append(limit)
            cr.execute(query, where_clause_params)
            ids = map(lambda x: x[0], cr.fetchall())

            if ids:
                return self.name_get(cr, uid, ids, context)
            else:
                return []
        return super(res_partner, self).name_search(
            cr, uid, name, args, operator=operator, context=context, limit=limit
        )
Beispiel #7
0
    def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
        if not args:
            args = []
        if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'):
            unaccent = get_unaccent_wrapper(cr)
            self.check_access_rights(cr, uid, 'read')
            where_query = self._where_calc(cr, uid, args, context=context)
            self._apply_ir_rules(cr, uid, where_query, 'read', context=context)
            from_clause, where_clause, where_clause_params = where_query.get_sql()
            where_str = where_clause and (" WHERE %s AND " % where_clause) or ' WHERE '

            if "product_product__product_tmpl_id" not in from_clause:
                from_clause += ",\"product_template\" as \"product_product__product_tmpl_id\""
            if operator in ('ilike', 'like'):
                percent = True
            if operator in ('=ilike', '=like'):
                operator = operator[1:]

            names = name.split(self._SEPARATOR)
            pwc = ""
            for n in names:
                search_name = '%%%s%%' % n if percent else n
                pwc += """ AND ({display_name} {operator} {percent})
                """.format(operator=operator, percent=unaccent('%s'),
                display_name=unaccent('product_product__product_tmpl_id.name'))
                where_clause_params += [search_name]
            pwc = pwc[5:]

            query = """SELECT product_product.id
                         FROM {from_clause}
                      {where} ({pwc})
                     ORDER BY {display_name}
                    """.format(from_clause=from_clause, where=where_str, pwc=pwc, 
                               display_name=unaccent('product_product__product_tmpl_id.name'))

            if limit:
                query += ' limit %s'
                where_clause_params.append(limit)

            cr.execute(query, where_clause_params)
            ids = map(lambda x: x[0], cr.fetchall())

            if ids:
                return self.name_get(cr, uid, ids, context)
            else:
                return []
        return super(product_product,self).name_search(cr, uid, name, args, operator=operator, context=context, limit=limit)
    def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
        if not args:
            args = []
        if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'):

            self.check_access_rights(cr, uid, 'read')
            where_query = self._where_calc(cr, uid, args, context=context)
            self._apply_ir_rules(cr, uid, where_query, 'read', context=context)
            from_clause, where_clause, where_clause_params = where_query.get_sql()
            where_str = where_clause and (" WHERE %s AND " % where_clause) or ' WHERE '

            # search on the name of the contacts and of its company
            search_name = name
            if operator in ('ilike', 'like'):
                search_name = '%%%s%%' % name
            if operator in ('=ilike', '=like'):
                operator = operator[1:]

            unaccent = get_unaccent_wrapper(cr)

            display_name = self._get_display_name(unaccent)

            query = """SELECT res_partner.id
                         FROM res_partner
                    LEFT JOIN res_partner company
                           ON res_partner.parent_id = company.id
                      {where} ({email} {operator} {percent}
                           OR {display_name} {operator} {percent})
                     ORDER BY {display_name}
                    """.format(where=where_str, operator=operator,
                               email=unaccent('res_partner.email'),
                               percent=unaccent('%s'),
                               display_name=display_name)

            where_clause_params += [search_name, search_name]
            if limit:
                query += ' limit %s'
                where_clause_params.append(limit)
            cr.execute(query, where_clause_params)
            ids = map(lambda x: x[0], cr.fetchall())

            if ids:
                return self.name_get(cr, uid, ids, context)
            else:
                return []
        return super(res_partner,self).name_search(cr, uid, name, args, operator=operator, context=context, limit=limit)
Beispiel #9
0
    def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
        if not args:
            args = []
        if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'):

            self.check_access_rights(cr, uid, 'read') # 产看当前用户是否有对res.partner的读权限
            where_query = self._where_calc(cr, uid, args, context=context)
            self._apply_ir_rules(cr, uid, where_query, 'read', context=context)
            from_clause, where_clause, where_clause_params = where_query.get_sql()
            where_str = where_clause and (" WHERE %s AND " % where_clause) or ' WHERE '

            # search on the name of the contacts and of its company
            search_name = name
            if operator in ('ilike', 'like'):
                search_name = '%%%s%%' % name
            if operator in ('=ilike', '=like'):
                operator = operator[1:]

            unaccent = get_unaccent_wrapper(cr)

            query = """SELECT id
                         FROM res_partner
                      {where} ({email} {operator} {percent}
                           OR {display_name} {operator} {percent}
                           OR {py} {operator} {percent}
                           OR {pinyin} {operator} {percent})
                     ORDER BY {display_name}
                    """.format(where=where_str, operator=operator,
                               email=unaccent('email'),
                               display_name=unaccent('display_name'),
                               py=unaccent('py'),
                               pinyin=unaccent('pinyin'),
                               percent=unaccent('%s'))

            where_clause_params += [search_name, search_name, search_name, search_name]
            if limit:
                query += ' limit %s'
                where_clause_params.append(limit)
            cr.execute(query, where_clause_params)
            ids = map(lambda x: x[0], cr.fetchall())

            if ids:
                return self.name_get(cr, uid, ids, context) # 根据一个partner所属国家的address格式对该partner的名称进行格式化
            else:
                return []
        return super(WithPinyinPartner,self).name_search(cr, uid, name, args, operator=operator, context=context, limit=limit)
    def name_search(self, name, args=None, operator='ilike', limit=100):
        if not args:
            args = []
        if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'):

            self.check_access_rights('read')
            where_query = self._where_calc(args)
            self._apply_ir_rules(where_query, 'read')
            from_clause, where_clause, where_clause_params = where_query.get_sql()
            where_str = where_clause and (" WHERE %s AND " % where_clause) or ' WHERE '

            # search on the name of the contacts and of its company
            search_name = name
            if operator in ('ilike', 'like'):
                search_name = '%%%s%%' % name
            if operator in ('=ilike', '=like'):
                operator = operator[1:]

            unaccent = get_unaccent_wrapper(self.env.cr)

            query = """SELECT id
                         FROM res_partner
                      {where} ({email} {operator} {percent}
                           OR {display_name} {operator} {percent}
                           OR {comercial} {operator} {percent})
                     ORDER BY {display_name}
                    """.format(where=where_str, operator=operator,
                               email=unaccent('email'),
                               display_name=unaccent('display_name'),
                               comercial=unaccent('comercial'),
                               percent=unaccent('%s'))

            where_clause_params += [search_name, search_name, search_name]
            if limit:
                query += ' limit %s'
                where_clause_params.append(limit)
            self.env.cr.execute(query, where_clause_params)
            ids = map(lambda x: x[0], self.env.cr.fetchall())

            if ids:
                return self.browse(ids).name_get()
            else:
                return []
        return super(ResPartner,self).name_search(name, args, operator=operator, limit=limit)
Beispiel #11
0
    def extended_init(self, cr, uid, exp, table, context):

        self._unaccent = expression.get_unaccent_wrapper(cr)
        self.joins = []
        self.root_model = table

        # normalize and prepare the expression for parsing
        self.expression = expression.distribute_not(
            expression.normalize_domain(exp))

        # look for real lang from context before parse
        parse_ctx = context.copy()
        if parse_ctx.get('lang', False) and exists_short_code(cr):
            cr.execute("select code from res_lang where short_code = '%s'" %
                       parse_ctx['lang'])
            res = cr.fetchall()
            if res and res[0]:
                parse_ctx.update({'lang': res[0][0]})

        # parse the domain expression
        self.parse(cr, uid, context=parse_ctx)
Beispiel #12
0
    def __init__(self, cr, uid, exp, table, context):
        """ Initialize expression object and automatically parse the expression
            right after initialization.

            :param exp: expression (using domain ('foo', '=', 'bar' format))
            :param table: root model

            :attr list result: list that will hold the result of the parsing
                as a list of ExtendedLeaf
            :attr list joins: list of join conditions, such as
                (res_country_state."id" = res_partner."state_id")
            :attr root_model: base model for the query
            :attr list expression: the domain expression, that will be
                normalized
                and prepared
        """
        self._unaccent = get_unaccent_wrapper(cr)
        self.joins = []
        self.root_model = table

        # normalize and prepare the expression for parsing
        self.expression = distribute_not(normalize_domain(exp))

        # Keep a dict of table aliases to ensure that no alias
        # of lenght > 64 char are created
        self.table_aliases = {}
        # aliases are of the following form
        # a1, a2, a3 ... a10 ... a999 ...
        self.next_alias_int = 1

        self.cr = cr
        self.uid = uid
        self.context = context

        # parse the domain expression
        self.parse(cr, uid, context=context)
    def test_20_auto_join(self):
        registry, cr, uid = self.registry, self.cr, self.uid
        unaccent = get_unaccent_wrapper(cr)

        # Get models
        partner_obj = registry('res.partner')
        state_obj = registry('res.country.state')
        bank_obj = registry('res.partner.bank')

        # Get test columns
        partner_state_id_col = partner_obj._columns.get('state_id')  # many2one on res.partner to res.country.state
        partner_parent_id_col = partner_obj._columns.get('parent_id')  # many2one on res.partner to res.partner
        state_country_id_col = state_obj._columns.get('country_id')  # many2one on res.country.state on res.country
        partner_child_ids_col = partner_obj._columns.get('child_ids')  # one2many on res.partner to res.partner
        partner_bank_ids_col = partner_obj._columns.get('bank_ids')  # one2many on res.partner to res.partner.bank
        category_id_col = partner_obj._columns.get('category_id')  # many2many on res.partner to res.partner.category

        # Get the first bank account type to be able to create a res.partner.bank
        bank_type = bank_obj._bank_type_get(cr, uid)[0]
        # Get country/state data
        country_us_id = registry('res.country').search(cr, uid, [('code', 'like', 'US')])[0]
        state_ids = registry('res.country.state').search(cr, uid, [('country_id', '=', country_us_id)], limit=2)

        # Create demo data: partners and bank object
        p_a = partner_obj.create(cr, uid, {'name': 'test__A', 'state_id': state_ids[0]})
        p_b = partner_obj.create(cr, uid, {'name': 'test__B', 'state_id': state_ids[1]})
        p_aa = partner_obj.create(cr, uid, {'name': 'test__AA', 'parent_id': p_a, 'state_id': state_ids[0]})
        p_ab = partner_obj.create(cr, uid, {'name': 'test__AB', 'parent_id': p_a, 'state_id': state_ids[1]})
        p_ba = partner_obj.create(cr, uid, {'name': 'test__BA', 'parent_id': p_b, 'state_id': state_ids[0]})
        b_aa = bank_obj.create(cr, uid, {'name': '__bank_test_a', 'state': bank_type[0], 'partner_id': p_aa, 'acc_number': '1234'})
        b_ab = bank_obj.create(cr, uid, {'name': '__bank_test_b', 'state': bank_type[0], 'partner_id': p_ab, 'acc_number': '5678'})
        b_ba = bank_obj.create(cr, uid, {'name': '__bank_test_b', 'state': bank_type[0], 'partner_id': p_ba, 'acc_number': '9876'})

        # --------------------------------------------------
        # Test1: basics about the attribute
        # --------------------------------------------------

        category_id_col._auto_join = True
        self.assertRaises(NotImplementedError, partner_obj.search, cr, uid, [('category_id.name', '=', 'foo')])
        category_id_col._auto_join = False

        # --------------------------------------------------
        # Test2: one2many
        # --------------------------------------------------

        name_test = 'test_a'

        # Do: one2many without _auto_join
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [('bank_ids.name', 'like', name_test)])
        # Test result
        self.assertEqual(set(partner_ids), set([p_aa]),
            "_auto_join off: ('bank_ids.name', 'like', '..'): incorrect result")
        # Test produced queries
        self.assertEqual(len(self.query_list), 3,
            "_auto_join off: ('bank_ids.name', 'like', '..') should produce 3 queries (1 in res_partner_bank, 2 on res_partner)")
        sql_query = self.query_list[0].get_sql()
        self.assertIn('res_partner_bank', sql_query[0],
            "_auto_join off: ('bank_ids.name', 'like', '..') first query incorrect main table")

        expected = "%s::text like %s" % (unaccent('"res_partner_bank"."name"'), unaccent('%s'))
        self.assertIn(expected, sql_query[1],
            "_auto_join off: ('bank_ids.name', 'like', '..') first query incorrect where condition")
        
        self.assertEqual(set(['%' + name_test + '%']), set(sql_query[2]),
            "_auto_join off: ('bank_ids.name', 'like', '..') first query incorrect parameter")
        sql_query = self.query_list[2].get_sql()
        self.assertIn('res_partner', sql_query[0],
            "_auto_join off: ('bank_ids.name', 'like', '..') third query incorrect main table")
        self.assertIn('"res_partner"."id" in (%s)', sql_query[1],
            "_auto_join off: ('bank_ids.name', 'like', '..') third query incorrect where condition")
        self.assertEqual(set([p_aa]), set(sql_query[2]),
            "_auto_join off: ('bank_ids.name', 'like', '..') third query incorrect parameter")

        # Do: cascaded one2many without _auto_join
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [('child_ids.bank_ids.id', 'in', [b_aa, b_ba])])
        # Test result
        self.assertEqual(set(partner_ids), set([p_a, p_b]),
            "_auto_join off: ('child_ids.bank_ids.id', 'in', [..]): incorrect result")
        # Test produced queries
        self.assertEqual(len(self.query_list), 5,
            "_auto_join off: ('child_ids.bank_ids.id', 'in', [..]) should produce 5 queries (1 in res_partner_bank, 4 on res_partner)")

        # Do: one2many with _auto_join
        partner_bank_ids_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [('bank_ids.name', 'like', 'test_a')])
        # Test result
        self.assertEqual(set(partner_ids), set([p_aa]),
            "_auto_join on: ('bank_ids.name', 'like', '..') incorrect result")
        # Test produced queries
        self.assertEqual(len(self.query_list), 1,
            "_auto_join on: ('bank_ids.name', 'like', '..') should produce 1 query")
        sql_query = self.query_list[0].get_sql()
        self.assertIn('"res_partner"', sql_query[0],
            "_auto_join on: ('bank_ids.name', 'like', '..') query incorrect main table")
        self.assertIn('"res_partner_bank" as "res_partner__bank_ids"', sql_query[0],
            "_auto_join on: ('bank_ids.name', 'like', '..') query incorrect join")

        expected = "%s::text like %s" % (unaccent('"res_partner__bank_ids"."name"'), unaccent('%s'))
        self.assertIn(expected, sql_query[1],
            "_auto_join on: ('bank_ids.name', 'like', '..') query incorrect where condition")
        
        self.assertIn('"res_partner"."id"="res_partner__bank_ids"."partner_id"', sql_query[1],
            "_auto_join on: ('bank_ids.name', 'like', '..') query incorrect join condition")
        self.assertEqual(set(['%' + name_test + '%']), set(sql_query[2]),
            "_auto_join on: ('bank_ids.name', 'like', '..') query incorrect parameter")

        # Do: one2many with _auto_join, test final leaf is an id
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [('bank_ids.id', 'in', [b_aa, b_ab])])
        # Test result
        self.assertEqual(set(partner_ids), set([p_aa, p_ab]),
            "_auto_join on: ('bank_ids.id', 'in', [..]) incorrect result")
        # Test produced queries
        self.assertEqual(len(self.query_list), 1,
            "_auto_join on: ('bank_ids.id', 'in', [..]) should produce 1 query")
        sql_query = self.query_list[0].get_sql()
        self.assertIn('"res_partner"', sql_query[0],
            "_auto_join on: ('bank_ids.id', 'in', [..]) query incorrect main table")
        self.assertIn('"res_partner__bank_ids"."id" in (%s,%s)', sql_query[1],
            "_auto_join on: ('bank_ids.id', 'in', [..]) query incorrect where condition")
        self.assertEqual(set([b_aa, b_ab]), set(sql_query[2]),
            "_auto_join on: ('bank_ids.id', 'in', [..]) query incorrect parameter")

        # Do: 2 cascaded one2many with _auto_join, test final leaf is an id
        partner_child_ids_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [('child_ids.bank_ids.id', 'in', [b_aa, b_ba])])
        # Test result
        self.assertEqual(set(partner_ids), set([p_a, p_b]),
            "_auto_join on: ('child_ids.bank_ids.id', 'not in', [..]): incorrect result")
        # # Test produced queries
        self.assertEqual(len(self.query_list), 1,
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) should produce 1 query")
        sql_query = self.query_list[0].get_sql()
        self.assertIn('"res_partner"', sql_query[0],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) incorrect main table")
        self.assertIn('"res_partner" as "res_partner__child_ids"', sql_query[0],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join")
        self.assertIn('"res_partner_bank" as "res_partner__child_ids__bank_ids"', sql_query[0],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join")
        self.assertIn('"res_partner__child_ids__bank_ids"."id" in (%s,%s)', sql_query[1],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect where condition")
        self.assertIn('"res_partner"."id"="res_partner__child_ids"."parent_id"', sql_query[1],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join condition")
        self.assertIn('"res_partner__child_ids"."id"="res_partner__child_ids__bank_ids"."partner_id"', sql_query[1],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join condition")
        self.assertEqual(set([b_aa, b_ba]), set(sql_query[2][-2:]),
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect parameter")

        # --------------------------------------------------
        # Test3: many2one
        # --------------------------------------------------

        name_test = 'US'

        # Do: many2one without _auto_join
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [('state_id.country_id.code', 'like', name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
            "_auto_join off: ('state_id.country_id.code', 'like', '..') incorrect result")
        # Test produced queries
        self.assertEqual(len(self.query_list), 3,
            "_auto_join off: ('state_id.country_id.code', 'like', '..') should produce 3 queries (1 on res_country, 1 on res_country_state, 1 on res_partner)")

        # Do: many2one with 1 _auto_join on the first many2one
        partner_state_id_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [('state_id.country_id.code', 'like', name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') incorrect result")
        # Test produced queries
        self.assertEqual(len(self.query_list), 2,
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') should produce 2 query")
        sql_query = self.query_list[0].get_sql()
        self.assertIn('"res_country"', sql_query[0],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect main table")

        expected = "%s::text like %s" % (unaccent('"res_country"."code"'), unaccent('%s'))
        self.assertIn(expected, sql_query[1],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect where condition")

        self.assertEqual(['%' + name_test + '%'], sql_query[2],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect parameter")
        sql_query = self.query_list[1].get_sql()
        self.assertIn('"res_partner"', sql_query[0],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect main table")
        self.assertIn('"res_country_state" as "res_partner__state_id"', sql_query[0],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect join")
        self.assertIn('"res_partner__state_id"."country_id" in (%s)', sql_query[1],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect where condition")
        self.assertIn('"res_partner"."state_id"="res_partner__state_id"."id"', sql_query[1],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect join condition")

        # Do: many2one with 1 _auto_join on the second many2one
        partner_state_id_col._auto_join = False
        state_country_id_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [('state_id.country_id.code', 'like', name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') incorrect result")
        # Test produced queries
        self.assertEqual(len(self.query_list), 2,
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') should produce 2 query")
        # -- first query
        sql_query = self.query_list[0].get_sql()
        self.assertIn('"res_country_state"', sql_query[0],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect main table")
        self.assertIn('"res_country" as "res_country_state__country_id"', sql_query[0],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect join")

        expected = "%s::text like %s" % (unaccent('"res_country_state__country_id"."code"'), unaccent('%s'))
        self.assertIn(expected, sql_query[1],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect where condition")
        
        self.assertIn('"res_country_state"."country_id"="res_country_state__country_id"."id"', sql_query[1],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect join condition")
        self.assertEqual(['%' + name_test + '%'], sql_query[2],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect parameter")
        # -- second query
        sql_query = self.query_list[1].get_sql()
        self.assertIn('"res_partner"', sql_query[0],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect main table")
        self.assertIn('"res_partner"."state_id" in', sql_query[1],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect where condition")

        # Do: many2one with 2 _auto_join
        partner_state_id_col._auto_join = True
        state_country_id_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [('state_id.country_id.code', 'like', name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
            "_auto_join on: ('state_id.country_id.code', 'like', '..') incorrect result")
        # Test produced queries
        self.assertEqual(len(self.query_list), 1,
            "_auto_join on: ('state_id.country_id.code', 'like', '..') should produce 1 query")
        sql_query = self.query_list[0].get_sql()
        self.assertIn('"res_partner"', sql_query[0],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect main table")
        self.assertIn('"res_country_state" as "res_partner__state_id"', sql_query[0],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join")
        self.assertIn('"res_country" as "res_partner__state_id__country_id"', sql_query[0],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join")

        expected = "%s::text like %s" % (unaccent('"res_partner__state_id__country_id"."code"'), unaccent('%s'))
        self.assertIn(expected, sql_query[1],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect where condition")
        
        self.assertIn('"res_partner"."state_id"="res_partner__state_id"."id"', sql_query[1],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join condition")
        self.assertIn('"res_partner__state_id"."country_id"="res_partner__state_id__country_id"."id"', sql_query[1],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join condition")
        self.assertEqual(['%' + name_test + '%'], sql_query[2],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect parameter")

        # --------------------------------------------------
        # Test4: domain attribute on one2many fields
        # --------------------------------------------------

        partner_child_ids_col._auto_join = True
        partner_bank_ids_col._auto_join = True
        partner_child_ids_col._domain = lambda self: ['!', ('name', '=', self._name)]
        partner_bank_ids_col._domain = [('acc_number', 'like', '1')]
        # Do: 2 cascaded one2many with _auto_join, test final leaf is an id
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, ['&', (1, '=', 1), ('child_ids.bank_ids.id', 'in', [b_aa, b_ba])])
        # Test result: at least one of our added data
        self.assertTrue(set([p_a]).issubset(set(partner_ids)),
            "_auto_join on one2many with domains incorrect result")
        self.assertTrue(set([p_ab, p_ba]) not in set(partner_ids),
            "_auto_join on one2many with domains incorrect result")
        # Test produced queries that domains effectively present
        sql_query = self.query_list[0].get_sql()
        
        expected = "%s::text like %s" % (unaccent('"res_partner__child_ids__bank_ids"."acc_number"'), unaccent('%s'))
        self.assertIn(expected, sql_query[1],
            "_auto_join on one2many with domains incorrect result")
        # TDE TODO: check first domain has a correct table name
        self.assertIn('"res_partner__child_ids"."name" = %s', sql_query[1],
            "_auto_join on one2many with domains incorrect result")

        partner_child_ids_col._domain = lambda self: [('name', '=', '__%s' % self._name)]
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, ['&', (1, '=', 1), ('child_ids.bank_ids.id', 'in', [b_aa, b_ba])])
        # Test result: no one
        self.assertFalse(partner_ids,
            "_auto_join on one2many with domains incorrect result")

        # ----------------------------------------
        # Test5: result-based tests
        # ----------------------------------------

        partner_bank_ids_col._auto_join = False
        partner_child_ids_col._auto_join = False
        partner_state_id_col._auto_join = False
        partner_parent_id_col._auto_join = False
        state_country_id_col._auto_join = False
        partner_child_ids_col._domain = []
        partner_bank_ids_col._domain = []

        # Do: ('child_ids.state_id.country_id.code', 'like', '..') without _auto_join
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [('child_ids.state_id.country_id.code', 'like', name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(set([p_a, p_b]).issubset(set(partner_ids)),
            "_auto_join off: ('child_ids.state_id.country_id.code', 'like', '..') incorrect result")
        # Test produced queries
        self.assertEqual(len(self.query_list), 5,
            "_auto_join off: ('child_ids.state_id.country_id.code', 'like', '..') number of queries incorrect")

        # Do: ('child_ids.state_id.country_id.code', 'like', '..') with _auto_join
        partner_child_ids_col._auto_join = True
        partner_state_id_col._auto_join = True
        state_country_id_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [('child_ids.state_id.country_id.code', 'like', name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(set([p_a, p_b]).issubset(set(partner_ids)),
            "_auto_join on: ('child_ids.state_id.country_id.code', 'like', '..') incorrect result")
        # Test produced queries
        self.assertEqual(len(self.query_list), 1,
            "_auto_join on: ('child_ids.state_id.country_id.code', 'like', '..') number of queries incorrect")

        # Remove mocks and modifications
        partner_bank_ids_col._auto_join = False
        partner_child_ids_col._auto_join = False
        partner_state_id_col._auto_join = False
        partner_parent_id_col._auto_join = False
        state_country_id_col._auto_join = False
Beispiel #14
0
    def name_search(self,
                    cr,
                    uid,
                    name,
                    args=None,
                    operator='ilike',
                    context=None,
                    limit=100):
        if not args:
            args = []
        if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'):

            self.check_access_rights(cr, uid, 'read')
            where_query = self._where_calc(cr, uid, args, context=context)
            self._apply_ir_rules(cr, uid, where_query, 'read', context=context)
            from_clause, where_clause, where_clause_params = where_query.get_sql(
            )
            where_str = where_clause and (" WHERE %s AND " %
                                          where_clause) or ' WHERE '

            # search on the name of the contacts and of its company
            search_name = name
            if operator in ('ilike', 'like'):
                search_name = '%%%s%%' % name
            if operator in ('=ilike', '=like'):
                operator = operator[1:]

            unaccent = get_unaccent_wrapper(cr)

            # TODO: simplify this in trunk with `display_name`, once it is stored
            # Perf note: a CTE expression (WITH ...) seems to have an even higher cost
            #            than this query with duplicated CASE expressions. The bulk of
            #            the cost is the ORDER BY, and it is inevitable if we want
            #            relevant results for the next step, otherwise we'd return
            #            a random selection of `limit` results.

            display_name = """CASE WHEN company.id IS NULL OR res_partner.is_company
                                   THEN {partner_name}
                                   ELSE {company_name} || ', ' || {partner_name}
                               END""".format(
                partner_name=unaccent('res_partner.name'),
                company_name=unaccent('company.name'))

            query = """SELECT res_partner.id
                         FROM res_partner
                    LEFT JOIN res_partner company
                           ON res_partner.parent_id = company.id
                      {where} ({email} {operator} {percent}
                           OR {display_name} {operator} {percent})
                     ORDER BY {display_name}
                    """.format(where=where_str,
                               operator=operator,
                               email=unaccent('res_partner.email'),
                               percent=unaccent('%s'),
                               display_name=display_name)

            where_clause_params += [search_name, search_name]
            if limit:
                query += ' limit %s'
                where_clause_params.append(limit)
            cr.execute(query, where_clause_params)
            ids = map(lambda x: x[0], cr.fetchall())

            if ids:
                return self.name_get(cr, uid, ids, context)
            else:
                return []
        return super(res_partner, self).name_search(cr,
                                                    uid,
                                                    name,
                                                    args,
                                                    operator=operator,
                                                    context=context,
                                                    limit=limit)
Beispiel #15
0
    def test_20_auto_join(self):
        registry, cr, uid = self.registry, self.cr, self.uid
        unaccent = get_unaccent_wrapper(cr)

        # Get models
        partner_obj = registry('res.partner')
        state_obj = registry('res.country.state')
        bank_obj = registry('res.partner.bank')

        # Get test columns
        partner_state_id_col = partner_obj._columns.get(
            'state_id')  # many2one on res.partner to res.country.state
        partner_parent_id_col = partner_obj._columns.get(
            'parent_id')  # many2one on res.partner to res.partner
        state_country_id_col = state_obj._columns.get(
            'country_id')  # many2one on res.country.state on res.country
        partner_child_ids_col = partner_obj._columns.get(
            'child_ids')  # one2many on res.partner to res.partner
        partner_bank_ids_col = partner_obj._columns.get(
            'bank_ids')  # one2many on res.partner to res.partner.bank
        category_id_col = partner_obj._columns.get(
            'category_id')  # many2many on res.partner to res.partner.category

        # Get country/state data
        country_us_id = registry('res.country').search(
            cr, uid, [('code', 'like', 'US')])[0]
        state_ids = registry('res.country.state').search(
            cr, uid, [('country_id', '=', country_us_id)], limit=2)

        # Create demo data: partners and bank object
        p_a = partner_obj.create(cr, uid, {
            'name': 'test__A',
            'state_id': state_ids[0]
        })
        p_b = partner_obj.create(cr, uid, {
            'name': 'test__B',
            'state_id': state_ids[1]
        })
        p_aa = partner_obj.create(cr, uid, {
            'name': 'test__AA',
            'parent_id': p_a,
            'state_id': state_ids[0]
        })
        p_ab = partner_obj.create(cr, uid, {
            'name': 'test__AB',
            'parent_id': p_a,
            'state_id': state_ids[1]
        })
        p_ba = partner_obj.create(cr, uid, {
            'name': 'test__BA',
            'parent_id': p_b,
            'state_id': state_ids[0]
        })
        b_aa = bank_obj.create(cr, uid, {
            'acc_number': '123',
            'acc_type': 'bank',
            'partner_id': p_aa
        })
        b_ab = bank_obj.create(cr, uid, {
            'acc_number': '456',
            'acc_type': 'bank',
            'partner_id': p_ab
        })
        b_ba = bank_obj.create(cr, uid, {
            'acc_number': '789',
            'acc_type': 'bank',
            'partner_id': p_ba
        })

        # --------------------------------------------------
        # Test1: basics about the attribute
        # --------------------------------------------------

        category_id_col._auto_join = True
        self.assertRaises(NotImplementedError, partner_obj.search, cr, uid,
                          [('category_id.name', '=', 'foo')])
        category_id_col._auto_join = False

        # --------------------------------------------------
        # Test2: one2many
        # --------------------------------------------------

        name_test = '12'

        # Do: one2many without _auto_join
        self._reinit_mock()
        partner_ids = partner_obj.search(
            cr, uid, [('bank_ids.sanitized_acc_number', 'like', name_test)])
        # Test result
        self.assertEqual(
            set(partner_ids), set([p_aa]),
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..'): incorrect result"
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list), 3,
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') should produce 3 queries (1 in res_partner_bank, 2 on res_partner)"
        )
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            'res_partner_bank', sql_query[0],
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') first query incorrect main table"
        )

        expected = "%s::text like %s" % (unaccent(
            '"res_partner_bank"."sanitized_acc_number"'), unaccent('%s'))
        self.assertIn(
            expected, sql_query[1],
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') first query incorrect where condition"
        )

        self.assertEqual(
            set(['%' + name_test + '%']), set(sql_query[2]),
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') first query incorrect parameter"
        )
        sql_query = self.query_list[2].get_sql()
        self.assertIn(
            'res_partner', sql_query[0],
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') third query incorrect main table"
        )
        self.assertIn(
            '"res_partner"."id" in (%s)', sql_query[1],
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') third query incorrect where condition"
        )
        self.assertEqual(
            set([p_aa]), set(sql_query[2]),
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') third query incorrect parameter"
        )

        # Do: cascaded one2many without _auto_join
        self._reinit_mock()
        partner_ids = partner_obj.search(
            cr, uid, [('child_ids.bank_ids.id', 'in', [b_aa, b_ba])])
        # Test result
        self.assertEqual(
            set(partner_ids), set([p_a, p_b]),
            "_auto_join off: ('child_ids.bank_ids.id', 'in', [..]): incorrect result"
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list), 5,
            "_auto_join off: ('child_ids.bank_ids.id', 'in', [..]) should produce 5 queries (1 in res_partner_bank, 4 on res_partner)"
        )

        # Do: one2many with _auto_join
        partner_bank_ids_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(
            cr, uid, [('bank_ids.sanitized_acc_number', 'like', '12')])
        # Test result
        self.assertEqual(
            set(partner_ids), set([p_aa]),
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') incorrect result"
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list), 1,
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') should produce 1 query"
        )
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            '"res_partner"', sql_query[0],
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') query incorrect main table"
        )
        self.assertIn(
            '"res_partner_bank" as "res_partner__bank_ids"', sql_query[0],
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') query incorrect join"
        )

        expected = "%s::text like %s" % (unaccent(
            '"res_partner__bank_ids"."sanitized_acc_number"'), unaccent('%s'))
        self.assertIn(
            expected, sql_query[1],
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') query incorrect where condition"
        )

        self.assertIn(
            '"res_partner"."id"="res_partner__bank_ids"."partner_id"',
            sql_query[1],
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') query incorrect join condition"
        )
        self.assertEqual(
            set(['%' + name_test + '%']), set(sql_query[2]),
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') query incorrect parameter"
        )

        # Do: one2many with _auto_join, test final leaf is an id
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid,
                                         [('bank_ids.id', 'in', [b_aa, b_ab])])
        # Test result
        self.assertEqual(
            set(partner_ids), set([p_aa, p_ab]),
            "_auto_join on: ('bank_ids.id', 'in', [..]) incorrect result")
        # Test produced queries
        self.assertEqual(
            len(self.query_list), 1,
            "_auto_join on: ('bank_ids.id', 'in', [..]) should produce 1 query"
        )
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            '"res_partner"', sql_query[0],
            "_auto_join on: ('bank_ids.id', 'in', [..]) query incorrect main table"
        )
        self.assertIn(
            '"res_partner__bank_ids"."id" in (%s,%s)', sql_query[1],
            "_auto_join on: ('bank_ids.id', 'in', [..]) query incorrect where condition"
        )
        self.assertEqual(
            set([b_aa, b_ab]), set(sql_query[2]),
            "_auto_join on: ('bank_ids.id', 'in', [..]) query incorrect parameter"
        )

        # Do: 2 cascaded one2many with _auto_join, test final leaf is an id
        partner_child_ids_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(
            cr, uid, [('child_ids.bank_ids.id', 'in', [b_aa, b_ba])])
        # Test result
        self.assertEqual(
            set(partner_ids), set([p_a, p_b]),
            "_auto_join on: ('child_ids.bank_ids.id', 'not in', [..]): incorrect result"
        )
        # # Test produced queries
        self.assertEqual(
            len(self.query_list), 1,
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) should produce 1 query"
        )
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            '"res_partner"', sql_query[0],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) incorrect main table"
        )
        self.assertIn(
            '"res_partner" as "res_partner__child_ids"', sql_query[0],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join"
        )
        self.assertIn(
            '"res_partner_bank" as "res_partner__child_ids__bank_ids"',
            sql_query[0],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join"
        )
        self.assertIn(
            '"res_partner__child_ids__bank_ids"."id" in (%s,%s)', sql_query[1],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect where condition"
        )
        self.assertIn(
            '"res_partner"."id"="res_partner__child_ids"."parent_id"',
            sql_query[1],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join condition"
        )
        self.assertIn(
            '"res_partner__child_ids"."id"="res_partner__child_ids__bank_ids"."partner_id"',
            sql_query[1],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join condition"
        )
        self.assertEqual(
            set([b_aa, b_ba]), set(sql_query[2][-2:]),
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect parameter"
        )

        # --------------------------------------------------
        # Test3: many2one
        # --------------------------------------------------

        name_test = 'US'

        # Do: many2one without _auto_join
        self._reinit_mock()
        partner_ids = partner_obj.search(
            cr, uid, [('state_id.country_id.code', 'like', name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(
            set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
            "_auto_join off: ('state_id.country_id.code', 'like', '..') incorrect result"
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list), 3,
            "_auto_join off: ('state_id.country_id.code', 'like', '..') should produce 3 queries (1 on res_country, 1 on res_country_state, 1 on res_partner)"
        )

        # Do: many2one with 1 _auto_join on the first many2one
        partner_state_id_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(
            cr, uid, [('state_id.country_id.code', 'like', name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(
            set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') incorrect result"
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list), 2,
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') should produce 2 query"
        )
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            '"res_country"', sql_query[0],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect main table"
        )

        expected = "%s::text like %s" % (unaccent('"res_country"."code"'),
                                         unaccent('%s'))
        self.assertIn(
            expected, sql_query[1],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect where condition"
        )

        self.assertEqual(
            ['%' + name_test + '%'], sql_query[2],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect parameter"
        )
        sql_query = self.query_list[1].get_sql()
        self.assertIn(
            '"res_partner"', sql_query[0],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect main table"
        )
        self.assertIn(
            '"res_country_state" as "res_partner__state_id"', sql_query[0],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect join"
        )
        self.assertIn(
            '"res_partner__state_id"."country_id" in (%s)', sql_query[1],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect where condition"
        )
        self.assertIn(
            '"res_partner"."state_id"="res_partner__state_id"."id"',
            sql_query[1],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect join condition"
        )

        # Do: many2one with 1 _auto_join on the second many2one
        partner_state_id_col._auto_join = False
        state_country_id_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(
            cr, uid, [('state_id.country_id.code', 'like', name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(
            set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') incorrect result"
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list), 2,
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') should produce 2 query"
        )
        # -- first query
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            '"res_country_state"', sql_query[0],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect main table"
        )
        self.assertIn(
            '"res_country" as "res_country_state__country_id"', sql_query[0],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect join"
        )

        expected = "%s::text like %s" % (
            unaccent('"res_country_state__country_id"."code"'), unaccent('%s'))
        self.assertIn(
            expected, sql_query[1],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect where condition"
        )

        self.assertIn(
            '"res_country_state"."country_id"="res_country_state__country_id"."id"',
            sql_query[1],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect join condition"
        )
        self.assertEqual(
            ['%' + name_test + '%'], sql_query[2],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect parameter"
        )
        # -- second query
        sql_query = self.query_list[1].get_sql()
        self.assertIn(
            '"res_partner"', sql_query[0],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect main table"
        )
        self.assertIn(
            '"res_partner"."state_id" in', sql_query[1],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect where condition"
        )

        # Do: many2one with 2 _auto_join
        partner_state_id_col._auto_join = True
        state_country_id_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(
            cr, uid, [('state_id.country_id.code', 'like', name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(
            set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
            "_auto_join on: ('state_id.country_id.code', 'like', '..') incorrect result"
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list), 1,
            "_auto_join on: ('state_id.country_id.code', 'like', '..') should produce 1 query"
        )
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            '"res_partner"', sql_query[0],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect main table"
        )
        self.assertIn(
            '"res_country_state" as "res_partner__state_id"', sql_query[0],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join"
        )
        self.assertIn(
            '"res_country" as "res_partner__state_id__country_id"',
            sql_query[0],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join"
        )

        expected = "%s::text like %s" % (unaccent(
            '"res_partner__state_id__country_id"."code"'), unaccent('%s'))
        self.assertIn(
            expected, sql_query[1],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect where condition"
        )

        self.assertIn(
            '"res_partner"."state_id"="res_partner__state_id"."id"',
            sql_query[1],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join condition"
        )
        self.assertIn(
            '"res_partner__state_id"."country_id"="res_partner__state_id__country_id"."id"',
            sql_query[1],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join condition"
        )
        self.assertEqual(
            ['%' + name_test + '%'], sql_query[2],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect parameter"
        )

        # --------------------------------------------------
        # Test4: domain attribute on one2many fields
        # --------------------------------------------------

        partner_child_ids_col._auto_join = True
        partner_bank_ids_col._auto_join = True
        partner_child_ids_col._domain = lambda self: [
            '!', ('name', '=', self._name)
        ]
        partner_bank_ids_col._domain = [('sanitized_acc_number', 'like', '2')]
        # Do: 2 cascaded one2many with _auto_join, test final leaf is an id
        self._reinit_mock()
        partner_ids = partner_obj.search(
            cr, uid,
            ['&', (1, '=', 1), ('child_ids.bank_ids.id', 'in', [b_aa, b_ba])])
        # Test result: at least one of our added data
        self.assertTrue(
            set([p_a]).issubset(set(partner_ids)),
            "_auto_join on one2many with domains incorrect result")
        self.assertTrue(
            set([p_ab, p_ba]) not in set(partner_ids),
            "_auto_join on one2many with domains incorrect result")
        # Test produced queries that domains effectively present
        sql_query = self.query_list[0].get_sql()

        expected = "%s::text like %s" % (unaccent(
            '"res_partner__child_ids__bank_ids"."sanitized_acc_number"'),
                                         unaccent('%s'))
        self.assertIn(expected, sql_query[1],
                      "_auto_join on one2many with domains incorrect result")
        # TDE TODO: check first domain has a correct table name
        self.assertIn('"res_partner__child_ids"."name" = %s', sql_query[1],
                      "_auto_join on one2many with domains incorrect result")

        partner_child_ids_col._domain = lambda self: [('name', '=', '__%s' %
                                                       self._name)]
        self._reinit_mock()
        partner_ids = partner_obj.search(
            cr, uid,
            ['&', (1, '=', 1), ('child_ids.bank_ids.id', 'in', [b_aa, b_ba])])
        # Test result: no one
        self.assertFalse(
            partner_ids,
            "_auto_join on one2many with domains incorrect result")

        # ----------------------------------------
        # Test5: result-based tests
        # ----------------------------------------

        partner_bank_ids_col._auto_join = False
        partner_child_ids_col._auto_join = False
        partner_state_id_col._auto_join = False
        partner_parent_id_col._auto_join = False
        state_country_id_col._auto_join = False
        partner_child_ids_col._domain = []
        partner_bank_ids_col._domain = []

        # Do: ('child_ids.state_id.country_id.code', 'like', '..') without _auto_join
        self._reinit_mock()
        partner_ids = partner_obj.search(
            cr, uid,
            [('child_ids.state_id.country_id.code', 'like', name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(
            set([p_a, p_b]).issubset(set(partner_ids)),
            "_auto_join off: ('child_ids.state_id.country_id.code', 'like', '..') incorrect result"
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list), 5,
            "_auto_join off: ('child_ids.state_id.country_id.code', 'like', '..') number of queries incorrect"
        )

        # Do: ('child_ids.state_id.country_id.code', 'like', '..') with _auto_join
        partner_child_ids_col._auto_join = True
        partner_state_id_col._auto_join = True
        state_country_id_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(
            cr, uid,
            [('child_ids.state_id.country_id.code', 'like', name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(
            set([p_a, p_b]).issubset(set(partner_ids)),
            "_auto_join on: ('child_ids.state_id.country_id.code', 'like', '..') incorrect result"
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list), 1,
            "_auto_join on: ('child_ids.state_id.country_id.code', 'like', '..') number of queries incorrect"
        )

        # Remove mocks and modifications
        partner_bank_ids_col._auto_join = False
        partner_child_ids_col._auto_join = False
        partner_state_id_col._auto_join = False
        partner_parent_id_col._auto_join = False
        state_country_id_col._auto_join = False
    def test_20_auto_join(self):
        registry, cr, uid = self.registry, self.cr, self.uid
        unaccent = get_unaccent_wrapper(cr)

        # Get models
        partner_obj = registry("res.partner")
        state_obj = registry("res.country.state")
        bank_obj = registry("res.partner.bank")

        # Get test columns
        partner_state_id_col = partner_obj._columns.get("state_id")  # many2one on res.partner to res.country.state
        partner_parent_id_col = partner_obj._columns.get("parent_id")  # many2one on res.partner to res.partner
        state_country_id_col = state_obj._columns.get("country_id")  # many2one on res.country.state on res.country
        partner_child_ids_col = partner_obj._columns.get("child_ids")  # one2many on res.partner to res.partner
        partner_bank_ids_col = partner_obj._columns.get("bank_ids")  # one2many on res.partner to res.partner.bank
        category_id_col = partner_obj._columns.get("category_id")  # many2many on res.partner to res.partner.category

        # Get country/state data
        country_us_id = registry("res.country").search(cr, uid, [("code", "like", "US")])[0]
        state_ids = registry("res.country.state").search(cr, uid, [("country_id", "=", country_us_id)], limit=2)

        # Create demo data: partners and bank object
        p_a = partner_obj.create(cr, uid, {"name": "test__A", "state_id": state_ids[0]})
        p_b = partner_obj.create(cr, uid, {"name": "test__B", "state_id": state_ids[1]})
        p_aa = partner_obj.create(cr, uid, {"name": "test__AA", "parent_id": p_a, "state_id": state_ids[0]})
        p_ab = partner_obj.create(cr, uid, {"name": "test__AB", "parent_id": p_a, "state_id": state_ids[1]})
        p_ba = partner_obj.create(cr, uid, {"name": "test__BA", "parent_id": p_b, "state_id": state_ids[0]})
        b_aa = bank_obj.create(cr, uid, {"acc_number": "123", "acc_type": "bank", "partner_id": p_aa})
        b_ab = bank_obj.create(cr, uid, {"acc_number": "456", "acc_type": "bank", "partner_id": p_ab})
        b_ba = bank_obj.create(cr, uid, {"acc_number": "789", "acc_type": "bank", "partner_id": p_ba})

        # --------------------------------------------------
        # Test1: basics about the attribute
        # --------------------------------------------------

        category_id_col._auto_join = True
        self.assertRaises(NotImplementedError, partner_obj.search, cr, uid, [("category_id.name", "=", "foo")])
        category_id_col._auto_join = False

        # --------------------------------------------------
        # Test2: one2many
        # --------------------------------------------------

        name_test = "12"

        # Do: one2many without _auto_join
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [("bank_ids.sanitized_acc_number", "like", name_test)])
        # Test result
        self.assertEqual(
            set(partner_ids),
            set([p_aa]),
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..'): incorrect result",
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list),
            3,
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') should produce 3 queries (1 in res_partner_bank, 2 on res_partner)",
        )
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            "res_partner_bank",
            sql_query[0],
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') first query incorrect main table",
        )

        expected = "%s::text like %s" % (unaccent('"res_partner_bank"."sanitized_acc_number"'), unaccent("%s"))
        self.assertIn(
            expected,
            sql_query[1],
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') first query incorrect where condition",
        )

        self.assertEqual(
            set(["%" + name_test + "%"]),
            set(sql_query[2]),
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') first query incorrect parameter",
        )
        sql_query = self.query_list[2].get_sql()
        self.assertIn(
            "res_partner",
            sql_query[0],
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') third query incorrect main table",
        )
        self.assertIn(
            '"res_partner"."id" in (%s)',
            sql_query[1],
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') third query incorrect where condition",
        )
        self.assertEqual(
            set([p_aa]),
            set(sql_query[2]),
            "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') third query incorrect parameter",
        )

        # Do: cascaded one2many without _auto_join
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [("child_ids.bank_ids.id", "in", [b_aa, b_ba])])
        # Test result
        self.assertEqual(
            set(partner_ids), set([p_a, p_b]), "_auto_join off: ('child_ids.bank_ids.id', 'in', [..]): incorrect result"
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list),
            5,
            "_auto_join off: ('child_ids.bank_ids.id', 'in', [..]) should produce 5 queries (1 in res_partner_bank, 4 on res_partner)",
        )

        # Do: one2many with _auto_join
        partner_bank_ids_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [("bank_ids.sanitized_acc_number", "like", "12")])
        # Test result
        self.assertEqual(
            set(partner_ids),
            set([p_aa]),
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') incorrect result",
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list),
            1,
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') should produce 1 query",
        )
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            '"res_partner"',
            sql_query[0],
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') query incorrect main table",
        )
        self.assertIn(
            '"res_partner_bank" as "res_partner__bank_ids"',
            sql_query[0],
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') query incorrect join",
        )

        expected = "%s::text like %s" % (unaccent('"res_partner__bank_ids"."sanitized_acc_number"'), unaccent("%s"))
        self.assertIn(
            expected,
            sql_query[1],
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') query incorrect where condition",
        )

        self.assertIn(
            '"res_partner"."id"="res_partner__bank_ids"."partner_id"',
            sql_query[1],
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') query incorrect join condition",
        )
        self.assertEqual(
            set(["%" + name_test + "%"]),
            set(sql_query[2]),
            "_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') query incorrect parameter",
        )

        # Do: one2many with _auto_join, test final leaf is an id
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [("bank_ids.id", "in", [b_aa, b_ab])])
        # Test result
        self.assertEqual(
            set(partner_ids), set([p_aa, p_ab]), "_auto_join on: ('bank_ids.id', 'in', [..]) incorrect result"
        )
        # Test produced queries
        self.assertEqual(len(self.query_list), 1, "_auto_join on: ('bank_ids.id', 'in', [..]) should produce 1 query")
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            '"res_partner"', sql_query[0], "_auto_join on: ('bank_ids.id', 'in', [..]) query incorrect main table"
        )
        self.assertIn(
            '"res_partner__bank_ids"."id" in (%s,%s)',
            sql_query[1],
            "_auto_join on: ('bank_ids.id', 'in', [..]) query incorrect where condition",
        )
        self.assertEqual(
            set([b_aa, b_ab]), set(sql_query[2]), "_auto_join on: ('bank_ids.id', 'in', [..]) query incorrect parameter"
        )

        # Do: 2 cascaded one2many with _auto_join, test final leaf is an id
        partner_child_ids_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [("child_ids.bank_ids.id", "in", [b_aa, b_ba])])
        # Test result
        self.assertEqual(
            set(partner_ids),
            set([p_a, p_b]),
            "_auto_join on: ('child_ids.bank_ids.id', 'not in', [..]): incorrect result",
        )
        # # Test produced queries
        self.assertEqual(
            len(self.query_list), 1, "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) should produce 1 query"
        )
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            '"res_partner"', sql_query[0], "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) incorrect main table"
        )
        self.assertIn(
            '"res_partner" as "res_partner__child_ids"',
            sql_query[0],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join",
        )
        self.assertIn(
            '"res_partner_bank" as "res_partner__child_ids__bank_ids"',
            sql_query[0],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join",
        )
        self.assertIn(
            '"res_partner__child_ids__bank_ids"."id" in (%s,%s)',
            sql_query[1],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect where condition",
        )
        self.assertIn(
            '"res_partner"."id"="res_partner__child_ids"."parent_id"',
            sql_query[1],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join condition",
        )
        self.assertIn(
            '"res_partner__child_ids"."id"="res_partner__child_ids__bank_ids"."partner_id"',
            sql_query[1],
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join condition",
        )
        self.assertEqual(
            set([b_aa, b_ba]),
            set(sql_query[2][-2:]),
            "_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect parameter",
        )

        # --------------------------------------------------
        # Test3: many2one
        # --------------------------------------------------

        name_test = "US"

        # Do: many2one without _auto_join
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [("state_id.country_id.code", "like", name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(
            set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
            "_auto_join off: ('state_id.country_id.code', 'like', '..') incorrect result",
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list),
            3,
            "_auto_join off: ('state_id.country_id.code', 'like', '..') should produce 3 queries (1 on res_country, 1 on res_country_state, 1 on res_partner)",
        )

        # Do: many2one with 1 _auto_join on the first many2one
        partner_state_id_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [("state_id.country_id.code", "like", name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(
            set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') incorrect result",
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list),
            2,
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') should produce 2 query",
        )
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            '"res_country"',
            sql_query[0],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect main table",
        )

        expected = "%s::text like %s" % (unaccent('"res_country"."code"'), unaccent("%s"))
        self.assertIn(
            expected,
            sql_query[1],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect where condition",
        )

        self.assertEqual(
            ["%" + name_test + "%"],
            sql_query[2],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect parameter",
        )
        sql_query = self.query_list[1].get_sql()
        self.assertIn(
            '"res_partner"',
            sql_query[0],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect main table",
        )
        self.assertIn(
            '"res_country_state" as "res_partner__state_id"',
            sql_query[0],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect join",
        )
        self.assertIn(
            '"res_partner__state_id"."country_id" in (%s)',
            sql_query[1],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect where condition",
        )
        self.assertIn(
            '"res_partner"."state_id"="res_partner__state_id"."id"',
            sql_query[1],
            "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect join condition",
        )

        # Do: many2one with 1 _auto_join on the second many2one
        partner_state_id_col._auto_join = False
        state_country_id_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [("state_id.country_id.code", "like", name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(
            set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') incorrect result",
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list),
            2,
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') should produce 2 query",
        )
        # -- first query
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            '"res_country_state"',
            sql_query[0],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect main table",
        )
        self.assertIn(
            '"res_country" as "res_country_state__country_id"',
            sql_query[0],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect join",
        )

        expected = "%s::text like %s" % (unaccent('"res_country_state__country_id"."code"'), unaccent("%s"))
        self.assertIn(
            expected,
            sql_query[1],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect where condition",
        )

        self.assertIn(
            '"res_country_state"."country_id"="res_country_state__country_id"."id"',
            sql_query[1],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect join condition",
        )
        self.assertEqual(
            ["%" + name_test + "%"],
            sql_query[2],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect parameter",
        )
        # -- second query
        sql_query = self.query_list[1].get_sql()
        self.assertIn(
            '"res_partner"',
            sql_query[0],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect main table",
        )
        self.assertIn(
            '"res_partner"."state_id" in',
            sql_query[1],
            "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect where condition",
        )

        # Do: many2one with 2 _auto_join
        partner_state_id_col._auto_join = True
        state_country_id_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [("state_id.country_id.code", "like", name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(
            set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
            "_auto_join on: ('state_id.country_id.code', 'like', '..') incorrect result",
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list), 1, "_auto_join on: ('state_id.country_id.code', 'like', '..') should produce 1 query"
        )
        sql_query = self.query_list[0].get_sql()
        self.assertIn(
            '"res_partner"',
            sql_query[0],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect main table",
        )
        self.assertIn(
            '"res_country_state" as "res_partner__state_id"',
            sql_query[0],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join",
        )
        self.assertIn(
            '"res_country" as "res_partner__state_id__country_id"',
            sql_query[0],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join",
        )

        expected = "%s::text like %s" % (unaccent('"res_partner__state_id__country_id"."code"'), unaccent("%s"))
        self.assertIn(
            expected,
            sql_query[1],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect where condition",
        )

        self.assertIn(
            '"res_partner"."state_id"="res_partner__state_id"."id"',
            sql_query[1],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join condition",
        )
        self.assertIn(
            '"res_partner__state_id"."country_id"="res_partner__state_id__country_id"."id"',
            sql_query[1],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join condition",
        )
        self.assertEqual(
            ["%" + name_test + "%"],
            sql_query[2],
            "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect parameter",
        )

        # --------------------------------------------------
        # Test4: domain attribute on one2many fields
        # --------------------------------------------------

        partner_child_ids_col._auto_join = True
        partner_bank_ids_col._auto_join = True
        partner_child_ids_col._domain = lambda self: ["!", ("name", "=", self._name)]
        partner_bank_ids_col._domain = [("sanitized_acc_number", "like", "2")]
        # Do: 2 cascaded one2many with _auto_join, test final leaf is an id
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, ["&", (1, "=", 1), ("child_ids.bank_ids.id", "in", [b_aa, b_ba])])
        # Test result: at least one of our added data
        self.assertTrue(set([p_a]).issubset(set(partner_ids)), "_auto_join on one2many with domains incorrect result")
        self.assertTrue(
            set([p_ab, p_ba]) not in set(partner_ids), "_auto_join on one2many with domains incorrect result"
        )
        # Test produced queries that domains effectively present
        sql_query = self.query_list[0].get_sql()

        expected = "%s::text like %s" % (
            unaccent('"res_partner__child_ids__bank_ids"."sanitized_acc_number"'),
            unaccent("%s"),
        )
        self.assertIn(expected, sql_query[1], "_auto_join on one2many with domains incorrect result")
        # TDE TODO: check first domain has a correct table name
        self.assertIn(
            '"res_partner__child_ids"."name" = %s', sql_query[1], "_auto_join on one2many with domains incorrect result"
        )

        partner_child_ids_col._domain = lambda self: [("name", "=", "__%s" % self._name)]
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, ["&", (1, "=", 1), ("child_ids.bank_ids.id", "in", [b_aa, b_ba])])
        # Test result: no one
        self.assertFalse(partner_ids, "_auto_join on one2many with domains incorrect result")

        # ----------------------------------------
        # Test5: result-based tests
        # ----------------------------------------

        partner_bank_ids_col._auto_join = False
        partner_child_ids_col._auto_join = False
        partner_state_id_col._auto_join = False
        partner_parent_id_col._auto_join = False
        state_country_id_col._auto_join = False
        partner_child_ids_col._domain = []
        partner_bank_ids_col._domain = []

        # Do: ('child_ids.state_id.country_id.code', 'like', '..') without _auto_join
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [("child_ids.state_id.country_id.code", "like", name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(
            set([p_a, p_b]).issubset(set(partner_ids)),
            "_auto_join off: ('child_ids.state_id.country_id.code', 'like', '..') incorrect result",
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list),
            5,
            "_auto_join off: ('child_ids.state_id.country_id.code', 'like', '..') number of queries incorrect",
        )

        # Do: ('child_ids.state_id.country_id.code', 'like', '..') with _auto_join
        partner_child_ids_col._auto_join = True
        partner_state_id_col._auto_join = True
        state_country_id_col._auto_join = True
        self._reinit_mock()
        partner_ids = partner_obj.search(cr, uid, [("child_ids.state_id.country_id.code", "like", name_test)])
        # Test result: at least our added data + demo data
        self.assertTrue(
            set([p_a, p_b]).issubset(set(partner_ids)),
            "_auto_join on: ('child_ids.state_id.country_id.code', 'like', '..') incorrect result",
        )
        # Test produced queries
        self.assertEqual(
            len(self.query_list),
            1,
            "_auto_join on: ('child_ids.state_id.country_id.code', 'like', '..') number of queries incorrect",
        )

        # Remove mocks and modifications
        partner_bank_ids_col._auto_join = False
        partner_child_ids_col._auto_join = False
        partner_state_id_col._auto_join = False
        partner_parent_id_col._auto_join = False
        state_country_id_col._auto_join = False