From f23d7af8d7e36b9d52a8c8ccf64355e22f3adb9c Mon Sep 17 00:00:00 2001
From: Ihtisham ul Haq <ihtisham.ul_haq@mail.schwarz>
Date: Mon, 17 Apr 2023 12:23:30 +0200
Subject: [PATCH] Use explicit inner join for networks in port query

This improves the performance of the database when fetching a list of ports
for a project user. This change creates an inner join with the networks
belonging to the ports.

Previous SQL query:
SELECT ports ...
FROM network, ports ...
WHERE ports.project_id = <project>
OR ports.network_id = networks.id
AND networks.project_id = <project>

Current SQL query:
SELECT ports ...
FROM ports
INNER JOIN networks ON networks.id = ports.network_id
WHERE ports.project_id = <project>
OR networks.project_id = <project>

Closes-Bug: #2016704
Change-Id: I9c49a307956ecfbf8bd2e866cefb21a212c38bd6
---
 neutron/db/db_base_plugin_v2.py | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/neutron/db/db_base_plugin_v2.py b/neutron/db/db_base_plugin_v2.py
index ca430b2cd57..f84fb4958a0 100644
--- a/neutron/db/db_base_plugin_v2.py
+++ b/neutron/db/db_base_plugin_v2.py
@@ -110,11 +110,18 @@ def _update_subnetpool_dict(orig_pool, new_pool):
     return updated
 
 
+def _port_query_hook(context, original_model, query):
+    # Apply the port query only in non-admin and non-advsvc context
+    if ndb_utils.model_query_scope_is_project(context, original_model):
+        query = query.join(models_v2.Network,
+                           models_v2.Network.id == models_v2.Port.network_id)
+    return query
+
+
 def _port_filter_hook(context, original_model, conditions):
     # Apply the port filter only in non-admin and non-advsvc context
     if ndb_utils.model_query_scope_is_project(context, original_model):
         conditions |= and_(
-            models_v2.Port.network_id == models_v2.Network.id,
             models_v2.Network.project_id == context.project_id)
     return conditions
 
@@ -150,7 +157,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
         model_query.register_hook(
             models_v2.Port,
             "port",
-            query_hook=None,
+            query_hook=_port_query_hook,
             filter_hook=_port_filter_hook,
             result_filters=None)
         return super(NeutronDbPluginV2, cls).__new__(cls, *args, **kwargs)