Skip to content
postgresqlf edited this page Oct 13, 2011 · 2 revisions

La prise en compte de la notation « post-fixée » définie dans SQL_f pourrait reposer une étape de transformation syntaxique définie dans le parseur de requêtes de PostgreSQL. Cependant, les mots clefs et les opérateurs SQL de PostgreSQL sont définis au sein d’une grammaire Bison figée lors de la compilation du code source. La modification de cette grammaire pour contourner l’usage normal des opérateurs mène à des conflits lors de l’analyse syntaxique de requêtes.

Pour des questions de portabilité, nous avons préféré définir ces opérateurs en dehors de la grammaire Bison à l’aide de la commande CREATE OPERATOR. Le nom de ces opérateurs est restreint à une séquence de caractères spéciaux ( + - * / < > = ~ ! @ # % ^ & | ` ?). A l’égard de cette restriction, nous employons les symboles « ~= », « && », « || » et « ! » pour représenter les opérateurs IS, AND, OR et NOT.

Prédicats flous et modifieurs : notation post-fixée avec IS

L’opérateur SQL ~= emploie une notation post-fixée pour matérialisé par l'opérateur IS : SELECT * FROM employe WHERE age ~= ‘jeune’'

L’opérateur =~ est également capable de prendre en compte l’emploi de modifieurs tels que TRES : SELECT * FROM employe WHERE age is ‘tres jeune’

La fonction ISf définit =~ avec deux arguments : `CREATE OPERATOR ~= (LEFTARG = REAL, RIGHTARG = VARCHAR, PROCEDURE = isF);

FUNCTION ISf(att REAL, funcs VARCHAR) RETURNS REAL `

Dans la fonction ISf, chaque token de la chaîne de caractères est évaluée comme une procédure PL/PLSQL à l’aide de l’instruction EXECUTE (analogue à EVAL dans d’autres langages de programmation). Cette procédure effectue les conversions suivantes :

age ~= 'jeune' -> ISf(age, 'jeune') -> jeune(age) age ~= 'tres jeune' -> ISf(age, 'tres jeune') -> tres(jeune(age))

Conjonctions et disjonctions avec AND et OR

Les scores retournés par chaque condition floue ou booléenne sont combinés suivant l'expression fournie dans la clause where. Notons que d'un point de vue théorique, la sémantique des opérateurs and et or sont définis dans la logique floue comme des normes et co-normes. Comme le montre la requête suivante, nous les avons fait correspondre aux opérateurs SQL && et ||, utilisables comme alternatives aux AND et OR classiques :

SELECT * FROM employes WHERE age ~= ‘jeune’ && salaire ~= ‘eleve’; L’emploi d’éléments de type boolean avec && et || engendre une conversion implicite vers des nombres flottants vers des booléen à l’aide d’un opérateur de CAST qui appelle la procédure bool2fuzzy(BOOLEAN) . SELECT * FROM employes WHERE age ~= ‘jeune’ && salaire > 25000; Par ailleurs, les opérateurs && et || sont associés aux fonctions C fuzzy_and_operator et fuz-zy_or_operator qui réalisent le calcul de la norme/co-norme.

Paramétrage de la norme

Les fonctions C fuzzy_and_operator et fuzzy_or_operator effectuent le calcul des normes/co-normes selon la valeur de la variable C « char * norm ». Elle peut prendre les valeurs ‘zadeh’, ‘probabiliste’, ‘lukasiewicz’ et ‘weber’ et peut être paramétrée à l’aide de set_norm(n) dans la clause FROM d’une requête SQL :

SELECT * FROM set_norm(‘probabiliste’), employes WHERE fuzzy_and_operator(age ~= ‘jeune’, salaire ~= ‘eleve’);

De manière alternative, on aussi peut écrire :

` SELECT set_norm(‘probabiliste’) ;

SELECT * FROM employes WHERE fuzzy_and_operator(age ~= ‘jeune’, salaire ~= ‘eleve’); `

Le calcul des différentes normes est implémenté en langage C, comme par exemple pour la disjonction probabiliste :

float8 or_probabiliste(float8 a, float8 b){ return a + b - a * b; }

Priorité des opérateurs

It is not possible to specify an operator's lexical precedence in CREATE OPERATOR, because the parser's precedence behavior is hard-wired. http://www.postgresql.org/docs/current/static/sql-createoperator.html

L’utilisation d’expressions contenant plusieurs opérateurs nécessite de définir des règles de priorité. Par exemple, des règles doivent être définies pour évaluer correctement l’expression suivante : age ~= ‘jeune’ && salaire ~= ‘elevé’ Sans règles, l’expression pourrait être évaluée comme :

eleve(fuzzy_and_operator(jeune(age), salaire))

Contourner ce comportement, des règles de priorité peuvent être définies à l’aide d’une famille d’opérateurs.

CREATE OPERATOR CLASS sqlf_ops DEFAULT FOR TYPE _int4 USING gist AS OPERATOR 1 ~=, OPERATOR 3 &&, OPERATOR 6 ||;