From 25dc6a467c641ccad5cc75f1003548af4f28b4fb Mon Sep 17 00:00:00 2001 From: Matt Riedemann Date: Tue, 20 Nov 2018 13:55:55 -0500 Subject: [PATCH] Remove GROUP BY clause from CellMapping.get_by_project_id Under postgresql, the GROUP BY clause in this query fails with: DBError: (psycopg2.ProgrammingError) column "instance_mappings.created_at" must appear in the GROUP BY clause or be used in an aggregate function And we're getting lucky with using this under mysql because we don't have the ONLY_FULL_GROUP_BY mode set (but we probably should). This change removes the GROUP BY clause and re-writes the query to avoid the joinedload() from the instance_mappings table and simply do a subquery to get the cell_ids and then do a simple IN query with the cell_mappings table. This fixes the GROUP BY issue and should also make the query more efficient since we won't have to load InstanceMappings ORM objects. Change-Id: Idc9b5ad019205f447c82a702dd3391fa5dd20228 Closes-Bug: #1804271 (cherry picked from commit 248750578a938a1eaa2e49004302d14ab7318c5b) --- nova/objects/cell_mapping.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/nova/objects/cell_mapping.py b/nova/objects/cell_mapping.py index d11237022bd1..7739afaa5497 100644 --- a/nova/objects/cell_mapping.py +++ b/nova/objects/cell_mapping.py @@ -13,7 +13,6 @@ from oslo_log import log as logging from oslo_utils import versionutils import six.moves.urllib.parse as urlparse -from sqlalchemy.orm import joinedload from sqlalchemy.sql.expression import asc from sqlalchemy.sql import false from sqlalchemy.sql import true @@ -276,13 +275,14 @@ class CellMappingList(base.ObjectListBase, base.NovaObject): @staticmethod @db_api.api_context_manager.reader def _get_by_project_id_from_db(context, project_id): - mappings = context.session.query( - api_models.InstanceMapping).\ - filter_by(project_id=project_id).\ - group_by(api_models.InstanceMapping.cell_id).\ - options(joinedload('cell_mapping', innerjoin=True)).\ - all() - return (mapping.cell_mapping for mapping in mappings) + # SELECT DISTINCT cell_id FROM instance_mappings \ + # WHERE project_id = $project_id; + cell_ids = context.session.query( + api_models.InstanceMapping.cell_id).filter_by( + project_id=project_id).distinct().subquery() + # SELECT cell_mappings WHERE cell_id IN ($cell_ids); + return context.session.query(api_models.CellMapping).filter( + api_models.CellMapping.id.in_(cell_ids)).all() @classmethod def get_by_project_id(cls, context, project_id):