[IMP] core: introduce subqueries in search
Make the method `_search` return a `Query` object, and make that object generate a subquery when used on the right-hand side of a condition. closes odoo/odoo#52403 Related: odoo/enterprise#10945 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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='<p>Test Post Performances with an email ping</p>',
|
||||
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='<p>Test Post Performances</p>',
|
||||
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, '<p>Adding stuff on %s</p>' % 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='<p>Test body <img src="cid:cid1"> <img src="cid:cid2"></p>',
|
||||
|
||||
@@ -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',
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
''']):
|
||||
|
||||
@@ -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())
|
||||
|
||||
+5
-8
@@ -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):
|
||||
|
||||
+26
-11
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user