setDefaultSearchSpec sur un énuméré multiple

Bonjour,
j’essaie d’effectuer une search spec basé sur un énuméré avec une notion de “like” sur le boolean persistant. Après quelques fouilles, j’ai trouvé ce post, qui semble indiqué qu’il n’est pas (encore) possible d’effectuer ce que je cherche à faire.

Pouvez-vous me le confirmer ?
merci,

Ophélie

[Platform]
Status=OK
Version=5.1.11
BuiltOn=2021-10-27 22:36
Git=release/158ceb7b361a6aeef72e052751d1f3678557b2ca
Encoding=UTF-8

Il est tout à fait possible d’écrire un filtre ou une search spec sur un attribut énuméré multiple.

Physiquement un énuméré est stocké sous la forme d’une liste de codes séparés par des point virgules V1;V2;....

Donc pour une search spec il écrire du SQL en like pour matcher ce genre de valeur. L’idéal c’est d’avoir des codes suffisamment différents (et donc uniques) auquel cas c’est plus simple à écrire, genre t.my_column like '%MONCODEUNIQUE%' or t.my_column like '%MONAUTRECODEUNIQUE%' sinon il faut gérer les ; dans les likes en pensant au cas du début et de la fin de valeur, c’est ce que fait le moteur Simplicité quand il traduit un filtre en SQL…

c’est ce que j’avais testé mais sans succès…
Peut-être ai-je omis les ’ ’ entre %.
Je ré-essaierai à l’occasion, merci !

J’ai pas compris ce que vous avez ommis… une search spec c’est du pur SQL (= une where clause additionnelle qui s’ajoute à la where clause générée par Simplicité à partir des filtres courants) il n’y a pas de spécificité syntaxique propre à Simplicité à ce niveau.

Attention une search spec ne doit pas être utilisée pour servir de filtre courant. Une search spec est un filtrage “dur” = statique = qui reste valable tout le temps de la session = ça se paramètre donc soir au niveau de l’objet soit, si ça dépend du profil du user, dans le postLoad. Si vous utilisez ça ailleurs il y a de très fortes chances que ça ne soit pas la bonne approche

J’ai dû oublié les guillemets …

j’ai bien compris le besoin, c’est exactement ce qu’on veut reproduire, un filtrage en dur pour filtrer en fonction du collaborateur qui se connecte sa zone de données.
Je vous confirme qu’on l’utilise dans le post load :

	@Override
	public void postLoad() {
		//user which type is "Investor" or "Manager" can only see their activity
		/**
		 * Commentaire AWH : attention "evlusersipActivity" correspond au nom logique de l'attribut. Un filtre SQL tel qu'une searchSpec doit se faire sur les noms physiques
		 */ 
		if(getGrant().hasResponsibility("EVL_MANAGER") ||getGrant().hasResponsibility("EVL_INVESTOR") )
			//ma solution de contournement
			setDefaultSearchSpec("evl_fnd_activity=(select evl_usersip_activity from m_user where usr_login='"+getGrant().getLogin()+"') or evl_fnd_activity=(select evl_evlusersip_activitybis from m_user where usr_login='"+getGrant().getLogin()+"')"); 
		//	essaie 1 
//setDefaultSearchSpec("evl_fnd_activity in (select evl_usersip_activity from m_user where usr_login='"+getGrant().getLogin()+"')"); 
		//essaie 2
//	setDefaultSearchSpec("(select evl_usersip_activity from m_user where usr_login='"+getGrant().getLogin()+"') like (%"+"evl_fnd_activity"+"%)" ); 
		

Effectivement en regardant mon code, je n’ai pas mis les guillemets au bon endroit (essai 2)

OK.

Idéalement il vaut mieux écrire plutôt des subqueries synchronisées ex: exists (select 1 from xxx x where x.yyy = t.my_column) (t est l’alias de la table de l’objet courant), il y a en effet des bases de données pour lesquelles un t.my_column =/in (select ...) n’exploitera pas bien les indexes. Dans le même ordre d’idée il vaut toujours mieux utiliser le row ID du user getGrant().getUserId() plutôt que le login pour utiliser la clé primaire de la table m_user.

Ce genre de choses a surtout de l’effet quand le volume de données grossit. Avec peu de données la différence est en général négligeable.

Le plus simple est effectivement d’avoir des codes uniques comme A;B;C. Car si vous avez des codes qui se ressemblent au sens du “like” comme A;AA;AAA, une recherche de %A% ramènera tous les AA et AAA. Dans ce cas vous serez obligé de faire une requête plus complexe incluant le séparateur “;” :
x like 'A;%' or x like '%;A' or x like '%;A;%'.

Visiblement vous avez besoin de chercher avec une colonne d’une table et non un code fixe, donc il faut faire une concaténation SQL dont la syntaxe dépend de la base données (concat sur mysql, || sur orcale…), il y a un verbe getDBConcat qui permet d’être indépendant de la base dans votre code :

// concatène '%' + t.evl_fnd_activity + '%' en SQL
String concat = getGrant().getDBConcat(null, "'%'", "t.evl_fnd_activity");
concat = getGrant().getDBConcat(null, concat, "'%'");

setDefaultSearchSpec(
"exists (select 1 from m_user u where u.row_id=" + g.getUserId() +
 " and u.evl_usersip_activity like ("+concat+"))");

sur MySQL concat vaudra concat(concat('%',t.evl_fnd_activity),'%')
sur Oracle ou hsql '%' || t.evl_fnd_activity || '%'
etc

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.