diff --git a/addons/hr/models/res_users.py b/addons/hr/models/res_users.py
index a00e9b1d134..d4fe54e74e2 100644
--- a/addons/hr/models/res_users.py
+++ b/addons/hr/models/res_users.py
@@ -198,13 +198,7 @@ class User(models.Model):
user.employee_id = self.env['hr.employee'].search([('id', 'in', user.employee_ids.ids), ('company_id', '=', self.env.company.id)], limit=1)
def _search_company_employee(self, operator, value):
- employees = self.env['hr.employee'].search([
- ('name', operator, value),
- '|',
- ('company_id', '=', self.env.company.id),
- ('company_id', '=', False)
- ], order='company_id ASC')
- return [('id', 'in', employees.mapped('user_id').ids)]
+ return [('employee_ids', operator, value)]
def action_create_employee(self):
self.ensure_one()
diff --git a/addons/test_mail/tests/test_performance.py b/addons/test_mail/tests/test_performance.py
index 078f8778799..1ffea697f4a 100644
--- a/addons/test_mail/tests/test_performance.py
+++ b/addons/test_mail/tests/test_performance.py
@@ -231,7 +231,7 @@ class TestMailAPIPerformance(BaseMailPerformance):
#voip module read activity_type during create leading to one less query in enterprise on action_feedback
category = activity.activity_type_id.category
- with self.assertQueryCount(__system__=18, emp=22):
+ with self.assertQueryCount(__system__=16, emp=20):
activity.action_feedback(feedback='Zizisse Done !')
@users('__system__', 'emp')
@@ -248,7 +248,7 @@ class TestMailAPIPerformance(BaseMailPerformance):
record.write({'name': 'Dupe write'})
- with self.assertQueryCount(__system__=19, emp=22):
+ with self.assertQueryCount(__system__=17, emp=20):
record.action_close('Dupe feedback')
self.assertEqual(record.activity_ids, self.env['mail.activity'])
@@ -290,7 +290,7 @@ class TestMailAPIPerformance(BaseMailPerformance):
}).create({})
composer.onchange_template_id_wrapper()
- with self.assertQueryCount(__system__=39, emp=42):
+ with self.assertQueryCount(__system__=37, emp=40):
composer.send_mail()
# remove created partner to ensure tests are the same each run
@@ -302,7 +302,7 @@ class TestMailAPIPerformance(BaseMailPerformance):
def test_message_assignation_email(self):
self.user_test.write({'notification_type': 'email'})
record = self.env['mail.test.track'].create({'name': 'Test'})
- with self.assertQueryCount(__system__=39, emp=40):
+ with self.assertQueryCount(__system__=37, emp=38):
record.write({
'user_id': self.user_test.id,
})
@@ -355,7 +355,7 @@ class TestMailAPIPerformance(BaseMailPerformance):
def test_message_post_one_email_notification(self):
record = self.env['mail.test.simple'].create({'name': 'Test'})
- with self.assertQueryCount(__system__=32, emp=33):
+ with self.assertQueryCount(__system__=30, emp=31):
record.message_post(
body='
Test Post Performances with an email ping
',
partner_ids=self.customer.ids,
@@ -494,7 +494,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
self.container.message_subscribe(self.user_portal.partner_id.ids)
record = self.container.with_user(self.env.user)
- with self.assertQueryCount(__system__=68, emp=69):
+ with self.assertQueryCount(__system__=63, emp=64):
record.message_post(
body='Test Post Performances
',
message_type='comment',
@@ -511,7 +511,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
record = self.container.with_user(self.env.user)
template_id = self.env.ref('test_mail.mail_test_container_tpl').id
- with self.assertQueryCount(__system__=78, emp=80):
+ with self.assertQueryCount(__system__=73, emp=75):
record.message_post_with_template(template_id, message_type='comment', composition_mode='comment')
self.assertEqual(record.message_ids[0].body, 'Adding stuff on %s
' % record.name)
@@ -582,7 +582,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
})
rec1 = rec.with_context(active_test=False) # to see inactive records
self.assertEqual(rec1.message_partner_ids, self.partners | self.env.user.partner_id)
- with self.assertQueryCount(__system__=39, emp=40):
+ with self.assertQueryCount(__system__=37, emp=38):
rec.write({'user_id': self.user_portal.id})
self.assertEqual(rec1.message_partner_ids, self.partners | self.env.user.partner_id | self.user_portal.partner_id)
# write tracking message
@@ -602,7 +602,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
customer_id = self.customer.id
user_id = self.user_portal.id
- with self.assertQueryCount(__system__=116, emp=117):
+ with self.assertQueryCount(__system__=109, emp=110):
rec = self.env['mail.test.ticket'].create({
'name': 'Test',
'container_id': container_id,
@@ -631,7 +631,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
rec1 = rec.with_context(active_test=False) # to see inactive records
self.assertEqual(rec1.message_partner_ids, self.user_portal.partner_id | self.env.user.partner_id)
self.assertEqual(len(rec1.message_ids), 1)
- with self.assertQueryCount(__system__=82, emp=82):
+ with self.assertQueryCount(__system__=77, emp=77):
rec.write({
'name': 'Test2',
'container_id': self.container.id,
@@ -668,7 +668,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
rec1 = rec.with_context(active_test=False) # to see inactive records
self.assertEqual(rec1.message_partner_ids, self.user_portal.partner_id | self.env.user.partner_id)
- with self.assertQueryCount(__system__=90, emp=90):
+ with self.assertQueryCount(__system__=85, emp=85):
rec.write({
'name': 'Test2',
'container_id': container_id,
@@ -701,7 +701,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
rec1 = rec.with_context(active_test=False) # to see inactive records
self.assertEqual(rec1.message_partner_ids, self.partners | self.env.user.partner_id | self.user_portal.partner_id)
- with self.assertQueryCount(__system__=32, emp=33):
+ with self.assertQueryCount(__system__=29, emp=30):
rec.write({
'name': 'Test2',
'customer_id': customer_id,
@@ -951,7 +951,7 @@ class TestMailHeavyPerformancePost(BaseMailPerformance):
]
self.attachements = self.env['ir.attachment'].with_user(self.env.user).create(self.vals)
attachement_ids = self.attachements.ids
- with self.assertQueryCount(emp=85):
+ with self.assertQueryCount(emp=81):
self.cr.sql_log = self.warm and self.cr.sql_log_count
record.with_context({}).message_post(
body='Test body

',
diff --git a/addons/test_mail_full/tests/test_sms_performance.py b/addons/test_mail_full/tests/test_sms_performance.py
index 42b6763e30c..8acdf795b6a 100644
--- a/addons/test_mail_full/tests/test_sms_performance.py
+++ b/addons/test_mail_full/tests/test_sms_performance.py
@@ -51,7 +51,7 @@ class TestSMSPerformance(BaseMailPerformance, sms_common.SMSCase):
def test_message_sms_record_1_partner(self):
record = self.test_record.with_user(self.env.user)
pids = self.customer.ids
- with self.mockSMSGateway(), self.assertQueryCount(employee=25): # test_mail_enterprise: 25
+ with self.mockSMSGateway(), self.assertQueryCount(employee=23): # test_mail_enterprise: 25
messages = record._message_sms(
body='Performance Test',
partner_ids=pids,
@@ -66,7 +66,7 @@ class TestSMSPerformance(BaseMailPerformance, sms_common.SMSCase):
def test_message_sms_record_10_partners(self):
record = self.test_record.with_user(self.env.user)
pids = self.partners.ids
- with self.mockSMSGateway(), self.assertQueryCount(employee=43): # test_mail_enterprise: 43
+ with self.mockSMSGateway(), self.assertQueryCount(employee=41): # test_mail_enterprise: 43
messages = record._message_sms(
body='Performance Test',
partner_ids=pids,
@@ -80,7 +80,7 @@ class TestSMSPerformance(BaseMailPerformance, sms_common.SMSCase):
@warmup
def test_message_sms_record_default(self):
record = self.test_record.with_user(self.env.user)
- with self.mockSMSGateway(), self.assertQueryCount(employee=28): # test_mail_enterprise: 28
+ with self.mockSMSGateway(), self.assertQueryCount(employee=26): # test_mail_enterprise: 28
messages = record._message_sms(
body='Performance Test',
)
diff --git a/addons/test_mass_mailing/tests/test_performance.py b/addons/test_mass_mailing/tests/test_performance.py
index b6d784f1723..5ae91d52aa6 100644
--- a/addons/test_mass_mailing/tests/test_performance.py
+++ b/addons/test_mass_mailing/tests/test_performance.py
@@ -51,7 +51,7 @@ class TestMassMailPerformance(TestMassMailPerformanceBase):
})
# runbot needs +50 compared to local
- with self.assertQueryCount(__system__=1914, marketing=1915):
+ with self.assertQueryCount(__system__=1714, marketing=1715):
mailing.action_send_mail()
self.assertEqual(mailing.sent, 50)
@@ -91,7 +91,7 @@ class TestMassMailBlPerformance(TestMassMailPerformanceBase):
})
# runbot needs +62 compared to local
- with self.assertQueryCount(__system__=2241, marketing=2242):
+ with self.assertQueryCount(__system__=1993, marketing=1994):
mailing.action_send_mail()
self.assertEqual(mailing.sent, 50)
diff --git a/odoo/addons/base/tests/test_expression.py b/odoo/addons/base/tests/test_expression.py
index 4e1c6197b10..9cacf15ac5b 100644
--- a/odoo/addons/base/tests/test_expression.py
+++ b/odoo/addons/base/tests/test_expression.py
@@ -1130,14 +1130,14 @@ class TestMany2one(TransactionCase):
self.Partner.search([('company_id', '=', self.company.id)])
with self.assertQueries(['''
- SELECT "res_company".id
- FROM "res_company"
- WHERE ("res_company"."name"::text LIKE %s)
- ORDER BY "res_company"."id"
- ''', '''
SELECT "res_partner".id
FROM "res_partner"
- WHERE ("res_partner"."company_id" IN (%s))
+ WHERE ("res_partner"."company_id" IN (
+ SELECT "res_company".id
+ FROM "res_company"
+ WHERE ("res_company"."name"::text like %s)
+ ORDER BY "res_company"."id"
+ ))
ORDER BY "res_partner"."display_name"
''']):
self.Partner.search([('company_id.name', 'like', self.company.name)])
@@ -1145,35 +1145,35 @@ class TestMany2one(TransactionCase):
with self.assertQueries(['''
SELECT "res_partner".id
FROM "res_partner"
- WHERE ("res_partner"."name"::text LIKE %s)
- ORDER BY "res_partner"."id"
- ''', '''
- SELECT "res_company".id
- FROM "res_company"
- WHERE ("res_company"."partner_id" IN (%s))
- ORDER BY "res_company"."id"
- ''', '''
- SELECT "res_partner".id
- FROM "res_partner"
- WHERE ("res_partner"."company_id" IN (%s))
+ WHERE ("res_partner"."company_id" IN (
+ SELECT "res_company".id
+ FROM "res_company"
+ WHERE ("res_company"."partner_id" IN (
+ SELECT "res_partner".id
+ FROM "res_partner"
+ WHERE ("res_partner"."name"::text LIKE %s)
+ ORDER BY "res_partner"."id"
+ ))
+ ORDER BY "res_company"."id"
+ ))
ORDER BY "res_partner"."display_name"
''']):
self.Partner.search([('company_id.partner_id.name', 'like', self.company.name)])
with self.assertQueries(['''
- SELECT "res_country".id
- FROM "res_country"
- WHERE ("res_country"."code"::text LIKE %s)
- ORDER BY "res_country"."id"
- ''', '''
- SELECT "res_company".id
- FROM "res_company"
- WHERE ("res_company"."name"::text LIKE %s)
- ORDER BY "res_company"."id"
- ''', '''
SELECT "res_partner".id
FROM "res_partner"
- WHERE (("res_partner"."company_id" IN (%s)) OR ("res_partner"."country_id" IN (%s)))
+ WHERE (("res_partner"."company_id" IN (
+ SELECT "res_company".id
+ FROM "res_company"
+ WHERE ("res_company"."name"::text LIKE %s)
+ ORDER BY "res_company"."id"
+ )) OR ("res_partner"."country_id" IN (
+ SELECT "res_country".id
+ FROM "res_country"
+ WHERE ("res_country"."code"::text LIKE %s)
+ ORDER BY "res_country"."id"
+ )))
ORDER BY "res_partner"."display_name"
''']):
self.Partner.search([
@@ -1182,6 +1182,23 @@ class TestMany2one(TransactionCase):
('country_id.code', 'like', 'BE'),
])
+ def test_explicit_subquery(self):
+ self.Partner.search([('company_id.name', 'like', self.company.name)])
+
+ with self.assertQueries(['''
+ SELECT "res_partner".id
+ FROM "res_partner"
+ WHERE ("res_partner"."company_id" IN (
+ SELECT "res_company".id
+ FROM "res_company"
+ WHERE ("res_company"."name"::text like %s)
+ ORDER BY "res_company"."id"
+ ))
+ ORDER BY "res_partner"."display_name"
+ ''']):
+ company_ids = self.company._search([('name', 'like', self.company.name)], order='id')
+ self.Partner.search([('company_id', 'in', company_ids)])
+
def test_autojoin(self):
# auto_join on the first many2one
self.patch(self.Partner._fields['company_id'], 'auto_join', True)
@@ -1199,16 +1216,16 @@ class TestMany2one(TransactionCase):
self.Partner.search([('company_id.name', 'like', self.company.name)])
with self.assertQueries(['''
- SELECT "res_partner".id
- FROM "res_partner"
- WHERE ("res_partner"."name"::text LIKE %s)
- ORDER BY "res_partner"."id"
- ''', '''
SELECT "res_partner".id
FROM "res_partner"
LEFT JOIN "res_company" AS "res_partner__company_id" ON
("res_partner"."company_id" = "res_partner__company_id"."id")
- WHERE ("res_partner__company_id"."partner_id" IN (%s))
+ WHERE ("res_partner__company_id"."partner_id" IN (
+ SELECT "res_partner".id
+ FROM "res_partner"
+ WHERE ("res_partner"."name"::text LIKE %s)
+ ORDER BY "res_partner"."id"
+ ))
ORDER BY "res_partner"."display_name"
''']):
self.Partner.search([('company_id.partner_id.name', 'like', self.company.name)])
@@ -1219,16 +1236,16 @@ class TestMany2one(TransactionCase):
self.Partner.search([('company_id.partner_id.name', 'like', self.company.name)])
with self.assertQueries(['''
- SELECT "res_company".id
- FROM "res_company"
- LEFT JOIN "res_partner" AS "res_company__partner_id" ON
- ("res_company"."partner_id" = "res_company__partner_id"."id")
- WHERE ("res_company__partner_id"."name"::text LIKE %s)
- ORDER BY "res_company"."id"
- ''', '''
SELECT "res_partner".id
FROM "res_partner"
- WHERE ("res_partner"."company_id" IN (%s))
+ WHERE ("res_partner"."company_id" IN (
+ SELECT "res_company".id
+ FROM "res_company"
+ LEFT JOIN "res_partner" AS "res_company__partner_id" ON
+ ("res_company"."partner_id" = "res_company__partner_id"."id")
+ WHERE ("res_company__partner_id"."name"::text LIKE %s)
+ ORDER BY "res_company"."id"
+ ))
ORDER BY "res_partner"."display_name"
''']):
self.Partner.search([('company_id.partner_id.name', 'like', self.company.name)])
@@ -1280,14 +1297,14 @@ class TestMany2one(TransactionCase):
self.Partner.search([('company_id', 'like', self.company.name)])
with self.assertQueries(['''
- SELECT "res_company".id
- FROM "res_company"
- WHERE ("res_company"."name"::text LIKE %s)
- ORDER BY "res_company"."sequence", "res_company"."name"
- ''', '''
SELECT "res_partner".id
FROM "res_partner"
- WHERE ("res_partner"."company_id" IN (%s))
+ WHERE ("res_partner"."company_id" IN (
+ SELECT "res_company".id
+ FROM "res_company"
+ WHERE ("res_company"."name"::text LIKE %s)
+ ORDER BY "res_company"."sequence", "res_company"."name"
+ ))
ORDER BY "res_partner"."display_name"
''']):
self.Partner.search([('company_id', 'like', self.company.name)])
@@ -1322,37 +1339,31 @@ class TestOne2many(TransactionCase):
self.Partner.search([('bank_ids', 'in', self.partner.bank_ids.ids)])
with self.assertQueries(['''
- SELECT "res_partner_bank".id
- FROM "res_partner_bank"
- WHERE ("res_partner_bank"."sanitized_acc_number"::text LIKE %s)
- ORDER BY "res_partner_bank"."id"
- ''', '''
SELECT "res_partner".id
FROM "res_partner"
WHERE ("res_partner"."id" IN (
- SELECT "partner_id" FROM "res_partner_bank" WHERE "id" IN %s
+ SELECT "res_partner_bank"."partner_id"
+ FROM "res_partner_bank"
+ WHERE ("res_partner_bank"."sanitized_acc_number"::text LIKE %s)
+ ORDER BY "res_partner_bank"."id"
))
ORDER BY "res_partner"."display_name"
''']):
self.Partner.search([('bank_ids.sanitized_acc_number', 'like', '12')])
with self.assertQueries(['''
- SELECT "res_partner_bank".id
- FROM "res_partner_bank"
- WHERE ("res_partner_bank"."sanitized_acc_number"::text LIKE %s)
- ORDER BY "res_partner_bank"."id"
- ''', '''
SELECT "res_partner".id
FROM "res_partner"
WHERE ("res_partner"."id" IN (
- SELECT "partner_id" FROM "res_partner_bank" WHERE "id" IN %s
- ))
- ORDER BY "res_partner"."id"
- ''', '''
- SELECT "res_partner".id
- FROM "res_partner"
- WHERE ("res_partner"."id" IN (
- SELECT "parent_id" FROM "res_partner" WHERE "id" IN %s
+ SELECT "res_partner"."parent_id"
+ FROM "res_partner"
+ WHERE ("res_partner"."id" IN (
+ SELECT "res_partner_bank"."partner_id"
+ FROM "res_partner_bank"
+ WHERE ("res_partner_bank"."sanitized_acc_number"::text LIKE %s)
+ ORDER BY "res_partner_bank"."id"
+ ))
+ ORDER BY "res_partner"."id"
))
ORDER BY "res_partner"."display_name"
''']):
@@ -1482,15 +1493,13 @@ class TestOne2many(TransactionCase):
self.Partner.search([('bank_ids', 'like', '12')])
with self.assertQueries(['''
- SELECT "res_partner_bank".id
- FROM "res_partner_bank"
- WHERE ("res_partner_bank"."sanitized_acc_number"::text LIKE %s)
- ORDER BY "res_partner_bank"."sequence", "res_partner_bank"."id"
- ''', '''
SELECT "res_partner".id
FROM "res_partner"
WHERE ("res_partner"."id" IN (
- SELECT "partner_id" FROM "res_partner_bank" WHERE "id" IN %s
+ SELECT "res_partner_bank"."partner_id"
+ FROM "res_partner_bank"
+ WHERE ("res_partner_bank"."sanitized_acc_number"::text LIKE %s)
+ ORDER BY "res_partner_bank"."sequence", "res_partner_bank"."id"
))
ORDER BY "res_partner"."display_name"
''']):
@@ -1522,37 +1531,37 @@ class TestMany2many(TransactionCase):
self.User.search([('groups_id', 'in', group.ids)], order='id')
with self.assertQueries(['''
- SELECT "res_groups".id
- FROM "res_groups"
- WHERE ("res_groups"."color" = %s)
- ORDER BY "res_groups"."id"
- ''', '''
SELECT "res_users".id
FROM "res_users"
WHERE ("res_users"."id" IN (
- SELECT "uid" FROM "res_groups_users_rel" WHERE "gid" IN %s
+ SELECT "uid" FROM "res_groups_users_rel" WHERE "gid" IN (
+ SELECT "res_groups".id
+ FROM "res_groups"
+ WHERE ("res_groups"."color" = %s)
+ ORDER BY "res_groups"."id"
+ )
))
ORDER BY "res_users"."id"
''']):
self.User.search([('groups_id.color', '=', group.color)], order='id')
with self.assertQueries(['''
- SELECT "ir_rule".id
- FROM "ir_rule"
- WHERE ("ir_rule"."name"::text LIKE %s)
- ORDER BY "ir_rule"."id"
- ''', '''
- SELECT "res_groups".id
- FROM "res_groups"
- WHERE ("res_groups"."id" IN (
- SELECT "group_id" FROM "rule_group_rel" WHERE "rule_group_id" IN %s
- ))
- ORDER BY "res_groups"."id"
- ''', '''
SELECT "res_users".id
FROM "res_users"
WHERE ("res_users"."id" IN (
- SELECT "uid" FROM "res_groups_users_rel" WHERE "gid" IN %s
+ SELECT "uid" FROM "res_groups_users_rel" WHERE "gid" IN (
+ SELECT "res_groups".id
+ FROM "res_groups"
+ WHERE ("res_groups"."id" IN (
+ SELECT "group_id" FROM "rule_group_rel" WHERE "rule_group_id" IN (
+ SELECT "ir_rule".id
+ FROM "ir_rule"
+ WHERE ("ir_rule"."name"::text LIKE %s)
+ ORDER BY "ir_rule"."id"
+ )
+ ))
+ ORDER BY "res_groups"."id"
+ )
))
ORDER BY "res_users"."id"
''']):
@@ -1567,15 +1576,15 @@ class TestMany2many(TransactionCase):
self.User.search([('company_ids', 'like', self.company.name)], order='id')
with self.assertQueries(['''
- SELECT "res_company".id
- FROM "res_company"
- WHERE ("res_company"."name"::text LIKE %s)
- ORDER BY "res_company"."sequence", "res_company"."name"
- ''', '''
SELECT "res_users".id
FROM "res_users"
WHERE ("res_users"."id" IN (
- SELECT "user_id" FROM "res_company_users_rel" WHERE "cid" IN %s
+ SELECT "user_id" FROM "res_company_users_rel" WHERE "cid" IN (
+ SELECT "res_company".id
+ FROM "res_company"
+ WHERE ("res_company"."name"::text LIKE %s)
+ ORDER BY "res_company"."sequence", "res_company"."name"
+ )
))
ORDER BY "res_users"."id"
''']):
diff --git a/odoo/addons/test_performance/tests/test_performance.py b/odoo/addons/test_performance/tests/test_performance.py
index 1a34881707c..4e14f6f9f9a 100644
--- a/odoo/addons/test_performance/tests/test_performance.py
+++ b/odoo/addons/test_performance/tests/test_performance.py
@@ -136,12 +136,12 @@ class TestPerformance(SavepointCaseWithUserDemo):
# delete N lines: O(1) queries
rec1.invalidate_cache()
- with self.assertQueryCount(__system__=16, demo=16):
+ with self.assertQueryCount(__system__=14, demo=14):
rec1.write({'line_ids': [(2, line.id) for line in lines[0]]})
self.assertEqual(rec1.line_ids, lines[1:])
rec1.invalidate_cache()
- with self.assertQueryCount(__system__=14, demo=14):
+ with self.assertQueryCount(__system__=12, demo=12):
rec1.write({'line_ids': [(2, line.id) for line in lines[1:]]})
self.assertFalse(rec1.line_ids)
self.assertFalse(lines.exists())
@@ -151,12 +151,12 @@ class TestPerformance(SavepointCaseWithUserDemo):
# unlink N lines: O(1) queries
rec1.invalidate_cache()
- with self.assertQueryCount(__system__=13, demo=13):
+ with self.assertQueryCount(__system__=11, demo=11):
rec1.write({'line_ids': [(3, line.id) for line in lines[0]]})
self.assertEqual(rec1.line_ids, lines[1:])
rec1.invalidate_cache()
- with self.assertQueryCount(__system__=14, demo=14):
+ with self.assertQueryCount(__system__=12, demo=12):
rec1.write({'line_ids': [(3, line.id) for line in lines[1:]]})
self.assertFalse(rec1.line_ids)
self.assertFalse(lines.exists())
@@ -190,7 +190,7 @@ class TestPerformance(SavepointCaseWithUserDemo):
# empty N lines in rec2: O(1) queries
rec1.invalidate_cache()
- with self.assertQueryCount(__system__=15, demo=15):
+ with self.assertQueryCount(__system__=13, demo=13):
rec2.write({'line_ids': [(5,)]})
self.assertFalse(rec2.line_ids)
@@ -262,12 +262,12 @@ class TestPerformance(SavepointCaseWithUserDemo):
# delete N tags: O(1) queries
rec1.invalidate_cache()
- with self.assertQueryCount(__system__=10, demo=10):
+ with self.assertQueryCount(__system__=8, demo=8):
rec1.write({'tag_ids': [(2, tag.id) for tag in tags[0]]})
self.assertEqual(rec1.tag_ids, tags[1:])
rec1.invalidate_cache()
- with self.assertQueryCount(__system__=10, demo=10):
+ with self.assertQueryCount(__system__=8, demo=8):
rec1.write({'tag_ids': [(2, tag.id) for tag in tags[1:]]})
self.assertFalse(rec1.tag_ids)
self.assertFalse(tags.exists())
diff --git a/odoo/models.py b/odoo/models.py
index 5eb58b7aad4..f7e54cd4750 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -4397,14 +4397,11 @@ Fields:
res = self._cr.fetchone()
return res[0]
- order_by = self._generate_order_by(order, query)
- from_clause, where_clause, where_clause_params = query.get_sql()
- where_str = where_clause and (" WHERE %s" % where_clause) or ''
- limit_str = limit and ' limit %d' % limit or ''
- offset_str = offset and ' offset %d' % offset or ''
- query_str = 'SELECT "%s".id FROM ' % self._table + from_clause + where_str + order_by + limit_str + offset_str
- self._cr.execute(query_str, where_clause_params)
- return [row[0] for row in self._cr.fetchall()]
+ query.order = self._generate_order_by(order, query).replace('ORDER BY ', '')
+ query.limit = limit
+ query.offset = offset
+
+ return query
@api.returns(None, lambda value: value[0])
def copy_data(self, default=None):
diff --git a/odoo/osv/expression.py b/odoo/osv/expression.py
index e5733164567..87208bba372 100644
--- a/odoo/osv/expression.py
+++ b/odoo/osv/expression.py
@@ -225,9 +225,9 @@ def is_false(model, domain):
stack.append(+1)
elif token == FALSE_LEAF:
stack.append(-1)
- elif token[1] == 'in' and not token[2]:
+ elif token[1] == 'in' and not (isinstance(token[2], Query) or token[2]):
stack.append(-1)
- elif token[1] == 'not in' and not token[2]:
+ elif token[1] == 'not in' and not (isinstance(token[2], Query) or token[2]):
stack.append(+1)
else:
stack.append(0)
@@ -740,10 +740,14 @@ class expression(object):
ids2 = right
else:
ids2 = [right]
- if ids2 and inverse_is_int and domain:
+ if inverse_is_int and domain:
ids2 = comodel._search([('id', 'in', ids2)] + domain, order='id')
- if ids2 and comodel._fields[field.inverse_name].store:
+ if isinstance(ids2, Query) and comodel._fields[field.inverse_name].store:
+ op1 = 'not inselect' if operator in NEGATIVE_TERM_OPERATORS else 'inselect'
+ subquery, subparams = ids2.select('"%s"."%s"' % (comodel._table, field.inverse_name))
+ push(('id', op1, (subquery, subparams)), model, alias, internal=True)
+ elif ids2 and comodel._fields[field.inverse_name].store:
op1 = 'not inselect' if operator in NEGATIVE_TERM_OPERATORS else 'inselect'
subquery = 'SELECT "%s" FROM "%s" WHERE "id" IN %%s' % (field.inverse_name, comodel._table)
subparams = [tuple(ids2)]
@@ -801,11 +805,18 @@ class expression(object):
else:
ids2 = [right]
- # rewrite condition in terms of ids2
- subop = 'not inselect' if operator in NEGATIVE_TERM_OPERATORS else 'inselect'
- subquery = 'SELECT "%s" FROM "%s" WHERE "%s" IN %%s' % (rel_id1, rel_table, rel_id2)
- ids2 = tuple(it for it in ids2 if it) or (None,)
- push(('id', subop, (subquery, [ids2])), model, alias, internal=True)
+ if isinstance(ids2, Query):
+ # rewrite condition in terms of ids2
+ subop = 'not inselect' if operator in NEGATIVE_TERM_OPERATORS else 'inselect'
+ subquery, subparams = ids2.select()
+ query = 'SELECT "%s" FROM "%s" WHERE "%s" IN (%s)' % (rel_id1, rel_table, rel_id2, subquery)
+ push(('id', subop, (query, subparams)), model, alias, internal=True)
+ else:
+ # rewrite condition in terms of ids2
+ subop = 'not inselect' if operator in NEGATIVE_TERM_OPERATORS else 'inselect'
+ subquery = 'SELECT "%s" FROM "%s" WHERE "%s" IN %%s' % (rel_id1, rel_table, rel_id2)
+ ids2 = tuple(it for it in ids2 if it) or (None,)
+ push(('id', subop, (subquery, [ids2])), model, alias, internal=True)
else:
# rewrite condition to match records with/without relations
@@ -836,11 +847,11 @@ class expression(object):
operator = dict_op[operator]
res_ids = comodel.with_context(active_test=False)._name_search(right, [], operator, limit=None)
if operator in NEGATIVE_TERM_OPERATORS:
- res_ids.append(False) # TODO this should not be appended if False was in 'right'
+ res_ids = list(res_ids) + [False] # TODO this should not be appended if False was in 'right'
return left, 'in', res_ids
# resolve string-based m2o criterion into IDs
if isinstance(right, str) or \
- right and isinstance(right, (tuple, list)) and all(isinstance(item, str) for item in right):
+ isinstance(right, (tuple, list)) and right and all(isinstance(item, str) for item in right):
push(_get_expression(comodel, left, right, operator), model, alias)
else:
# right == [] or right == False and all other cases are handled by __leaf_to_sql()
@@ -954,6 +965,10 @@ class expression(object):
else:
query = '(%s."%s" IS NULL)' % (table_alias, left)
params = []
+ elif isinstance(right, Query):
+ subquery, subparams = right.select()
+ query = '(%s."%s" %s (%s))' % (table_alias, left, operator, subquery)
+ params = subparams
elif isinstance(right, (list, tuple)):
if model._fields[left].type == "boolean":
params = [it for it in (True, False) if it in right]