Files
odoo_source/odoo/addons/base/security/base_security.xml
T
Alvaro FuentesandChristophe Simonis c18b9f44be [IMP] *: optimize multi-company rule
When we use the `|` (or) version of this rule the ORM generates two
sub-queries when checking the company. This causes sub-optimal and in
some cases really bad planning for the queries and thus PG takes hours
to complete them.

Example (formatted):
```sql
    SELECT "mrp_routing_workcenter".id
      FROM "mrp_routing_workcenter"
 LEFT JOIN "mrp_bom" AS "mrp_routing_workcenter__bom_id"
        ON "mrp_routing_workcenter"."bom_id" = "mrp_routing_workcenter__bom_id"."id"
     WHERE "mrp_routing_workcenter"."workcenter_id" in (1)
       AND (  ("mrp_routing_workcenter"."bom_id" in (
                    SELECT "mrp_bom".id
                      FROM "mrp_bom"
                     WHERE ("mrp_bom"."company_id" in (1))
                   )
              )
           OR ("mrp_routing_workcenter"."bom_id" in (
                    SELECT "mrp_bom".id
                      FROM "mrp_bom"
                     WHERE "mrp_bom"."company_id" IS NULL
                   )
              )
           )
  ORDER BY "mrp_routing_workcenter__bom_id"."sequence",
           "mrp_routing_workcenter__bom_id"."id",
           "mrp_routing_workcenter"."sequence",
           "mrp_routing_workcenter"."id"
```

If we use the single term version the generated query has only one
sub-query:
```sql
    SELECT "mrp_routing_workcenter".id
      FROM "mrp_routing_workcenter"
 LEFT JOIN "mrp_bom" AS "mrp_routing_workcenter__bom_id"
        ON "mrp_routing_workcenter"."bom_id" = "mrp_routing_workcenter__bom_id"."id"
     WHERE "mrp_routing_workcenter"."workcenter_id" in (1)
       AND (  ("mrp_routing_workcenter"."bom_id" in (
                    SELECT "mrp_bom".id
                      FROM "mrp_bom"
                     WHERE (("mrp_bom"."company_id" in (1))
                        OR  ("mrp_bom"."company_id" IS NULL))
                   )
              )
           )
  ORDER BY "mrp_routing_workcenter__bom_id"."sequence",
           "mrp_routing_workcenter__bom_id"."id",
           "mrp_routing_workcenter"."sequence",
           "mrp_routing_workcenter"."id"
```
In this version PG is able to produce a better query plan resulting in
better execution times.

Also, the `company_id` field is required on some models, so the "= False" comparison is useless.

closes odoo/odoo#159123

X-original-commit: 1b5c41f36801fb886ec591f29dba42787d698526
Related: odoo/enterprise#59378
Signed-off-by: Christophe Simonis (chs) <chs@odoo.com>
Co-authored-by: Christophe Simonis <chs@odoo.com>
2024-03-25 17:50:06 +00:00

208 lines
11 KiB
XML

<?xml version="1.0"?>
<odoo>
<data noupdate="1">
<!-- TODO Remove me? Ony group system -->
<record model="ir.rule" id="res_users_log_rule">
<field name="name">res.users.log per user</field>
<field name="model_id" ref="model_res_users_log"/>
<field name="domain_force">[('create_uid','=', user.id)]</field>
<field name="perm_read" eval="False"/>
</record>
<record model="ir.rule" id="res_partner_rule">
<field name="name">res.partner company</field>
<field name="model_id" ref="base.model_res_partner"/>
<!-- We exclude partners that have internal users (`partner_share` field) from
the multi-company rule because it might interfere with the user's company rule
and make some users unselectable in relational fields. This means that partners
of internal users are always visible, not matter the company setting. -->
<field name="domain_force">['|', ('partner_share', '=', False), ('company_id', 'in', company_ids + [False])]</field>
</record>
<record model="ir.rule" id="res_partner_portal_public_rule">
<field name="name">res_partner: portal/public: read access on my commercial partner</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="domain_force">[('id', 'child_of', user.commercial_partner_id.id)]</field>
<field name="groups" eval="[Command.link(ref('base.group_portal')), Command.link(ref('base.group_public'))]"/>
<field name="perm_create" eval="False"/>
<field name="perm_unlink" eval="False"/>
<field name="perm_write" eval="False"/>
</record>
<record model="ir.rule" id="ir_default_user_rule">
<field name="name">Defaults: alter personal defaults</field>
<field name="model_id" ref="model_ir_default"/>
<field name="domain_force">[('user_id','=',user.id)]</field>
<field name="groups" eval="[Command.link(ref('base.group_user'))]"/>
<field name="perm_read" eval="False"/>
</record>
<record model="ir.rule" id="ir_default_system_rule">
<field name="name">Defaults: alter all defaults</field>
<field name="model_id" ref="model_ir_default"/>
<field name="domain_force">[(1,'=',1)]</field>
<field name="groups" eval="[Command.link(ref('base.group_system'))]"/>
<field name="perm_read" eval="False"/>
</record>
<!-- Used for dashboard customizations, users should only be able to edit their own dashboards -->
<!-- Remove me? users never create those directly -->
<record model="ir.rule" id="ir_ui_view_custom_personal">
<field name="name">ir.ui.view_custom rule</field>
<field name="model_id" ref="model_ir_ui_view_custom"/>
<field name="domain_force">[('user_id','=',user.id)]</field>
</record>
<record id="res_partner_bank_rule" model="ir.rule">
<field name="name">Partner bank company rule</field>
<field name="model_id" ref="model_res_partner_bank"/>
<field name="domain_force">[('company_id', 'in', company_ids + [False])]</field>
</record>
<record id="res_currency_rate_rule" model="ir.rule">
<field name="name">multi-company currency rate rule</field>
<field name="model_id" ref="model_res_currency_rate"/>
<field name="domain_force">[('company_id', 'in', company_ids + [False])]</field>
</record>
<record id="change_password_rule" model="ir.rule">
<field name="name">change user password rule</field>
<field name="model_id" ref="model_change_password_user"/>
<field name="domain_force">[('create_uid', '=', user.id)]</field>
</record>
<!-- Restrict modifications on ir.filters to owner only -->
<record id="ir_filters_admin_all_rights_rule" model="ir.rule">
<field name="name">ir.filters.admin.all.rights</field>
<field name="model_id" ref="model_ir_filters"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[Command.link(ref('base.group_erp_manager'))]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
<record id="ir_filters_employee_rule" model="ir.rule">
<field name="name">ir.filters.owner</field>
<field name="model_id" ref="model_ir_filters"/>
<field name="domain_force">[('user_id','in',[False,user.id])]</field>
<field name="groups" eval="[Command.link(ref('base.group_user'))]"/>
<field name="perm_unlink" eval="False"/>
</record>
<record id="ir_filters_delete_own_rule" model="ir.rule">
<field name="name">ir.filters.own.rule.delete</field>
<field name="model_id" ref="model_ir_filters"/>
<field name="domain_force">[('user_id', '=', user.id)]</field>
<field name="groups" eval="[Command.link(ref('base.group_user'))]"/>
<field name="perm_read" eval="False"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
</record>
<record id="ir_filters_portal_public_rule" model="ir.rule">
<field name="name">ir.filter: portal/public</field>
<field name="model_id" ref="model_ir_filters"/>
<field name="domain_force">[('user_id', '=', user.id)]</field>
<field name="groups" eval="[Command.link(ref('base.group_portal')), Command.link(ref('base.group_public'))]"/>
</record>
<!-- Record Rules For Company -->
<record id="res_company_rule_portal" model="ir.rule">
<field name="name">company rule portal</field>
<field name="model_id" ref="model_res_company"/>
<field eval="False" name="global"/>
<field name="groups" eval="[Command.set([ref('base.group_portal')])]"/>
<field name="domain_force">[('id','in', company_ids)]</field>
</record>
<record id="res_company_rule_employee" model="ir.rule">
<field name="name">company rule employee</field>
<field name="model_id" ref="model_res_company"/>
<field eval="False" name="global"/>
<field name="groups" eval="[Command.set([ref('base.group_user')])]"/>
<field name="domain_force">[('id','in', company_ids)]</field>
</record>
<record id="res_company_rule_public" model="ir.rule">
<field name="name">company rule public</field>
<field name="model_id" ref="model_res_company"/>
<field eval="False" name="global"/>
<field name="groups" eval="[Command.set([ref('base.group_public')])]"/>
<field name="domain_force">[('id','in', company_ids)]</field>
</record>
<record id="res_company_rule_erp_manager" model="ir.rule">
<field name="name">company rule erp manager</field>
<field name="model_id" ref="model_res_company"/>
<field eval="False" name="global"/>
<field name="groups" eval="[Command.set([ref('base.group_erp_manager')])]"/>
<field name="domain_force">[(1,'=',1)]</field>
</record>
<record id="res_users_identity_check" model="ir.rule">
<field name="name">users can only access their own id check</field>
<field name="model_id" ref="model_res_users_identitycheck"/>
<field name="domain_force">[('create_uid', '=', user.id)]</field>
</record>
<!-- Record Rule For User -->
<record id="res_users_rule" model="ir.rule">
<field name="name">user rule</field>
<field name="model_id" ref="model_res_users"/>
<field eval="True" name="global"/>
<field name="domain_force">['|', ('share', '=', False), ('company_ids', 'in', company_ids)]</field>
</record>
<record id="change_password_own_rule" model="ir.rule">
<field name="name">change own password</field>
<field name="model_id" ref="model_change_password_own"/>
<field name="domain_force">[('create_uid', '=', user.id)]</field>
</record>
<!-- Record Rule For User settings -->
<record id="res_users_settings_rule_admin" model="ir.rule">
<field name="name">Administrators can access all User Settings.</field>
<field name="model_id" ref="model_res_users_settings"/>
<field name="groups" eval="[Command.link(ref('base.group_system'))]"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
<record id="res_users_settings_rule_user" model="ir.rule">
<field name="name">res.users.settings: access their own entries</field>
<field name="model_id" ref="model_res_users_settings"/>
<field name="groups" eval="[Command.link(ref('base.group_user'))]"/>
<field name="domain_force">[('user_id', '=', user.id)]</field>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
<!-- rules for API token -->
<record id="api_key_public" model="ir.rule">
<field name="name">Public users can't interact with keys at all</field>
<field name="model_id" ref="model_res_users_apikeys"/>
<field name="domain_force">[(0, '=', 1)]</field>
<field name="groups" eval="[Command.link(ref('base.group_public'))]"/>
</record>
<record id="api_key_user" model="ir.rule">
<field name="name">Users can read and delete their own keys</field>
<field name="model_id" ref="model_res_users_apikeys"/>
<field name="domain_force">[('user_id', '=', user.id)]</field>
<field name="groups" eval="[
Command.link(ref('base.group_portal')),
Command.link(ref('base.group_user')),
]"/>
</record>
<record id="api_key_admin" model="ir.rule">
<field name="name">Administrators can view user keys to revoke them</field>
<field name="model_id" ref="model_res_users_apikeys"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[Command.link(ref('base.group_system'))]"/>
</record>
</data>
</odoo>