Le count d'objets affichés n'est pas identique à ceux en base

Tags: #<Tag:0x00007fe295e6ea40>

Bonjour,

[Platform]
Status=OK
Version=4.0.P24
BuiltOn=2020-04-02 19:06 (revision 40b5a93964a5371a2b394d345f457792bdbe9c91)
Encoding=UTF-8
EndpointIP=172.17.0.4
EndpointURL=http://5880b6f3c801:8080
TimeZone=Europe/Paris
SystemDate=2020-06-29 15:59:02

[Application]
ApplicationVersion=0.16 dev
ContextPath=
ContextURL=https://ope.rfs.ope.aws.renault.com
ActiveSessions=1
TotalUsers=11
EnabledUsers=6
LastLoginDate=

[Server]
ServerInfo=Apache Tomcat/9.0.33
ServerType=WEB
User=root

Concernant le busines object Access Point:

Le nombre d’access points créés est différent entre celui qui figure via l’IHM:

et celui en utilisant une requête sql:

Ceci engendre un écart dans le calcul des pourcentages des données ( par exemple, on calcule le pourcentage des access points ayant un status ACTIVE par rapport au nombre total) Avez vous une explication pour ceci?

Merci d’avance

Vous devez avoir un attribut foreign key obligatoire qui fait que certains records pour lesquels la colonne de cette foreign key est nulle n’apparaissent pas dans le comptage logique.

Pour rappel un attribut foreign key obligatoire se traduit par un inner join SQL (qui exclut donc les null) et un attribut foreign key non obligatoire par un outer join (qui prend les null).

Merci David,
Comment on peut savoir lequel des attributs de l’objet est un foreign key (pour moi et si j’ai bien compris il n’y que les ids qui sont obligatoires pour faire le lien d’un objet à un autre)?
Et y a t il un moyen d’avoir le même comptage logique quand on fait le comptage via la DB?

On parle ici de mécanismes basiques de la plateforme Simplicité qui, visiblement, ne sont pas bien maîtrisés…

Un attribut “ID” (ou “foreign key”) peut, comme tout attribut d’un objet, être obligatoire ou facultatif.
Ce type d’attribut induit une jointure logique entre l’objet et l’objet qu’il référence. Comme rappelé précédement cette jointure logique se traduit au niveau physique par:

  • un inner join si l’attribut ID est obligatoire
  • un outer join si l’attribut est facultatif

Votre différence de comptage logique/physique s’explique donc par un (ou plusieurs) attribut ID obligatoire mais pour lequel il existe des records sur lesquels la colonne est nulle (peut être parce que cet attribut était facultatif à une époque ou pour une raison plus subtile dans vos paramétrages/contraintes/code/…)

Repassez vos attributs ID en facultatifs pour retrouver ces records filtrés par le inner join, corrigez les, et repassez les attributs en obligatoires.

Plus généralement relisez votre paramétrage/code pour voir si le caractère obligatoire/facultatif de ces ID est bien légitime au regard de vos besoins métier, et surtout si vous avez mis en place des règles dynamiques sur le caractère obligatoire ou facultatif d’attributs IDs assurez vous de l’avoir fait d’une manière qui le rende facultatif sur les listes.

De manière générale je recommande de ne pas jouer avec le caractère obligatoire/facultatif des ID dans des contraintes ou le code, à fortiori si vous faites des choses au niveau physique qui ne sont pas cohérentes avec les règles mises en place au niveau logique.

Une autre manière de le dire (et donc d’éviter des différences logiques/physiques) c’est de travailler exclusivement au niveau logique (ex: faire un myObject.count() plutôt qu’un select count(*) en base). Dans Simplicité le recours au SQL en base ne soit se faire que quand justement, pour de bonnes raisons, on souhaite zapper ce qu’il se passe au niveau logique.

Historiquement les bases sont plus performantes avec un “inner join” qu’avec un “outer join”, du coup une FK obligatoire a toujours été interprétée en “inner join” SQL.

Mais c’est vrai que ça a toujours posé des problèmes quand une référence devient obligatoire (suite à un évolution ou dynamiquement…) pour la reprise des données, une erreur d’import…

A l’inverse, les attributs obligatoires et non clés fonctionnelles sont facultatifs physiquement pour permettre de les rendre obligatoires dynamiquement dans la couche logique : la base n’est là que pour assurer une persistance/indexation des données.

Il faudrait refaire un série de tests de performance pour comparer les outer/inner join. Si c’est concluant on pourrait faire sauter la contrainte “inner” physique comme pour un attribut. Même avec un “outer join” si la couche logique est bien respectée, aucun null ne devrait exister/remonter, mais si un pb fonctionnel apparaît l’utilisateur serait moins bloqué et pourrait corriger ses données comme pour un champ devenu obligatoire.

Par ailleurs vous pouvez activer les traces SQL temporairement (param système LOG_SQL_USER=yes) pour debugger le “select count” en question.

Peut être pourrait-on mettre un warning en cas de changement d’une FK de facultatif à obligatoire pour checker s’il existe des valeurs nulles dans les objets qui utilisent cette FK…

Ça ne réglerait bien entendu pas tous les cas, notamment le changement dynamique (via code ou contrainte) qui peut induire des comportements incompréhensibles quand on a pas bien compris l’impact que ça a sur le inner vs outer (en formation on insiste sur ce point car c’est fondamental).

Mais je le redis, pour moi la meilleure chose à faire c’est de rester au niveau logique quand c’est possible. Les accès SQL sont à réserver à des cas très tordus où on veut contourner ce qui se passe au niveau logique pour de bonnes raisons.