From c3c1c6c4bdfc0d28ff63ba9663e33559711a481e Mon Sep 17 00:00:00 2001 From: Jean-Pascal MILCENT Date: Fri, 5 Apr 2024 14:15:33 +0200 Subject: [PATCH] fix: modify queries to force the use of indexes Fix #516 --- .../repositories/vmCommunesRepository.py | 153 +++++++++--------- .../repositories/vmObservationsRepository.py | 19 ++- 2 files changed, 90 insertions(+), 82 deletions(-) diff --git a/atlas/modeles/repositories/vmCommunesRepository.py b/atlas/modeles/repositories/vmCommunesRepository.py index bd5c8dcf..3b5cc880 100644 --- a/atlas/modeles/repositories/vmCommunesRepository.py +++ b/atlas/modeles/repositories/vmCommunesRepository.py @@ -1,74 +1,79 @@ -# -*- coding:utf-8 -*- - -import ast - -from flask import current_app -from sqlalchemy import distinct -from sqlalchemy.sql import text -from sqlalchemy.sql.expression import func - -from atlas.modeles.entities.vmCommunes import VmCommunes - - -def getAllCommunes(session): - req = session.query(distinct(VmCommunes.commune_maj), VmCommunes.insee).all() - communeList = list() - for r in req: - temp = {"label": r[0], "value": r[1]} - communeList.append(temp) - return communeList - - -def getCommunesSearch(session, search, limit=50): - req = session.query( - distinct(VmCommunes.commune_maj), VmCommunes.insee, func.length(VmCommunes.commune_maj) - ).filter(VmCommunes.commune_maj.ilike("%" + search + "%")) - - req = req.order_by(VmCommunes.commune_maj) - - req = req.limit(limit).all() - - communeList = list() - for r in req: - temp = {"label": r[0], "value": r[1]} - communeList.append(temp) - return communeList - - -def getCommuneFromInsee(connection, insee): - sql = """ - SELECT c.commune_maj, - c.insee, - c.commune_geojson - FROM atlas.vm_communes c - WHERE c.insee = :thisInsee - """ - req = connection.execute(text(sql), thisInsee=insee) - communeObj = dict() - for r in req: - communeObj = { - "areaName": r.commune_maj, - "areaCode": str(r.insee), - "areaGeoJson": ast.literal_eval(r.commune_geojson), - } - return communeObj - - -def getCommunesObservationsChilds(connection, cd_ref): - sql = """ - SELECT DISTINCT (com.insee) AS insee, com.commune_maj - FROM atlas.vm_communes com - JOIN atlas.vm_observations obs - ON obs.insee = com.insee - WHERE obs.cd_ref IN ( - SELECT * FROM atlas.find_all_taxons_childs(:thiscdref) - ) - OR obs.cd_ref = :thiscdref - ORDER BY com.commune_maj ASC - """ - req = connection.execute(text(sql), thiscdref=cd_ref) - listCommunes = list() - for r in req: - temp = {"insee": r.insee, "commune_maj": r.commune_maj} - listCommunes.append(temp) - return listCommunes +# -*- coding:utf-8 -*- + +import ast + +from flask import current_app +from sqlalchemy import distinct +from sqlalchemy.sql import text +from sqlalchemy.sql.expression import func + +from atlas.modeles.entities.vmCommunes import VmCommunes + + +def getAllCommunes(session): + req = session.query(distinct(VmCommunes.commune_maj), VmCommunes.insee).all() + communeList = list() + for r in req: + temp = {"label": r[0], "value": r[1]} + communeList.append(temp) + return communeList + + +def getCommunesSearch(session, search, limit=50): + req = session.query( + distinct(VmCommunes.commune_maj), VmCommunes.insee, func.length(VmCommunes.commune_maj) + ).filter(VmCommunes.commune_maj.ilike("%" + search + "%")) + + req = req.order_by(VmCommunes.commune_maj) + + req = req.limit(limit).all() + + communeList = list() + for r in req: + temp = {"label": r[0], "value": r[1]} + communeList.append(temp) + return communeList + + +def getCommuneFromInsee(connection, insee): + sql = """ + SELECT c.commune_maj, + c.insee, + c.commune_geojson + FROM atlas.vm_communes c + WHERE c.insee = :thisInsee + """ + req = connection.execute(text(sql), thisInsee=insee) + communeObj = dict() + for r in req: + communeObj = { + "areaName": r.commune_maj, + "areaCode": str(r.insee), + "areaGeoJson": ast.literal_eval(r.commune_geojson), + } + return communeObj + + +def getCommunesObservationsChilds(connection, cd_ref): + sql = "SELECT * FROM atlas.find_all_taxons_childs(:thiscdref) AS taxon_childs(cd_nom)" + results = connection.execute(text(sql), thiscdref=cd_ref) + taxons = [cd_ref] + for r in results: + taxons.append(r.cd_nom) + + sql = """ + SELECT DISTINCT + com.commune_maj, + com.insee + FROM atlas.vm_observations AS obs + JOIN atlas.vm_communes AS com + ON obs.insee = com.insee + WHERE obs.cd_ref = ANY(:taxonsList) + ORDER BY com.commune_maj ASC + """ + results = connection.execute(text(sql), taxonsList=taxons) + municipalities = list() + for r in results: + municipality = {"insee": r.insee, "commune_maj": r.commune_maj} + municipalities.append(municipality) + return municipalities diff --git a/atlas/modeles/repositories/vmObservationsRepository.py b/atlas/modeles/repositories/vmObservationsRepository.py index 18fe3341..95c7cde7 100644 --- a/atlas/modeles/repositories/vmObservationsRepository.py +++ b/atlas/modeles/repositories/vmObservationsRepository.py @@ -180,16 +180,19 @@ def observersParser(req): def getObservers(connection, cd_ref): + sql = "SELECT * FROM atlas.find_all_taxons_childs(:thiscdref) AS taxon_childs(cd_nom)" + results = connection.execute(text(sql), thiscdref=cd_ref) + taxons = [cd_ref] + for r in results: + taxons.append(r.cd_nom) + sql = """ - SELECT DISTINCT observateurs - FROM atlas.vm_observations - WHERE cd_ref IN ( - SELECT * FROM atlas.find_all_taxons_childs(:thiscdref) - ) - OR cd_ref = :thiscdref + SELECT DISTINCT observateurs + FROM atlas.vm_observations + WHERE cd_ref = ANY(:taxonsList) """ - req = connection.execute(text(sql), thiscdref=cd_ref) - return observersParser(req) + results = connection.execute(text(sql), taxonsList=taxons) + return observersParser(results) def getGroupeObservers(connection, groupe):