par , 23/08/2016 � 00h28 (1313 Affichages)
PostgreSQL permet la cr�ation d'un type personnalis� de donn�e.
Dans notre exemple nous cr�erons le type � fraction � et mettrons en place la possibilit� de d�finir un index sur notre type.
La commande CREATE TYPE permet de cr�er votre type.
Dans notre cas (fraction) nous devons tenir compte des contraintes�
- le d�nominateur ne peut �tre nul (z�ro !)
- ni le num�rateur et ni le d�nominateur ne peuvent �tre NULL (absence de valeur !)
Le deuxi�me point peut amener une confusion : la fraction (globalement) peut �tre NULL (fraction non d�finie) mais si une fraction est d�finie (non NULL) alors le deuxi�me point ci-dessous s�applique.
Pour cela nous cr�erons deux DOMAINEs (un type existant avec contrainte)
Cr�ation des Domaines
d�nominateur�
1 2 3 4
| CREATE DOMAIN ddenominateur
AS INTEGER
DEFAULT 1 --la contrainte de NOT NULL prend le dessus sur DEFAULT!!!
CHECK (VALUE IS NOT NULL AND VALUE <> 0); |
num�rateur
1 2 3 4
| CREATE DOMAIN dnumerateur
AS INTEGER
DEFAULT 0 --la contrainte de NOT NULL prend le dessus sur DEFAULT!!!
CHECK (VALUE IS NOT NULL); |
Creation du type fraction�
1 2
| CREATE TYPE fraction
AS (numerateur dnumerateur, denominateur ddenominateur) |
Les functions outis pour la simplification
Le pgcd (plus grand commun diviseur)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| CREATE OR REPLACE FUNCTION public.pgcd(
a integer,
b integer)
RETURNS integer AS
$BODY$
declare
t integer;
begin
a=abs(a);
b=abs(b);
if(a=0 and b=0) then
raise EXCEPTION 'Les deux valeurs ne peuvent être nulles';
elsif(a=0 or b=0) then
return a+b;
else
if(a<b) then
t=a;
a=b;
b=t;
end if;
t=a-b;
if(t=0) then
return a;
else
return pgcd(b,t);
end if;
end if;
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
La simplification
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| CREATE OR REPLACE FUNCTION public.simplifie_fraction(a fraction)
RETURNS fraction AS
$BODY$
declare
p integer;
begin
p=pgcd(a.numerateur, a.denominateur);
a.numerateur=a.numerateur/p;
a.denominateur=a.denominateur/p;
return a;
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
Les op�rateurs arithm�tiques (+, -, /, *)
Pour chaque op�rateur on d�fini une function et la dite op�rateur.
Remarque : il est possible de definir ces fonctions en C, nous utiliserons plpgsql.
Addition
Fonction |
Op�rateur |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| CREATE OR REPLACE FUNCTION public.add_fraction(
gauche fraction,
droite fraction)
RETURNS fraction AS
$BODY$
declare
n integer;
d integer;
begin
n=gauche.numerateur*droite.denominateur+gauche.denominateur*droite.numerateur;
d=gauche.denominateur*droite.denominateur;
return simplifie_fraction((n,d)::fraction);
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
|
1 2 3 4 5
| CREATE OPERATOR public.+(
PROCEDURE = add_fraction,
LEFTARG = fraction,
RIGHTARG = fraction,
COMMUTATOR = +); |
|
Soustraction
Fonction |
Op�rateur |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| CREATE OR REPLACE FUNCTION public.sous_fraction(
gauche fraction,
droite fraction)
RETURNS fraction AS
$BODY$
declare
n integer;
d integer;
begin
n=gauche.numerateur*droite.denominateur-gauche.denominateur*droite.numerateur;
d=gauche.denominateur*droite.denominateur;
return simplifie_fraction((n,d)::fraction);
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
|
1 2 3 4
| CREATE OPERATOR public.-(
PROCEDURE = sous_fraction,
LEFTARG = fraction,
RIGHTARG = fraction); |
|
Multiplication
Fonction |
Op�rateur |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| CREATE OR REPLACE FUNCTION public.mult_fraction(
gauche fraction,
droite fraction)
RETURNS fraction AS
$BODY$
declare
n integer;
d integer;
begin
n=gauche.numerateur*droite.numerateur;
d=gauche.denominateur*droite.denominateur;
return simplifie_fraction((n,d)::fraction);
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
|
1 2 3 4 5
| CREATE OPERATOR public.*(
PROCEDURE = mult_fraction,
LEFTARG = fraction,
RIGHTARG = fraction,
COMMUTATOR = *); |
|
Division
Fonction |
Op�rateur |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| CREATE OR REPLACE FUNCTION public.div_fraction(
gauche fraction,
droite fraction)
RETURNS fraction AS
$BODY$
declare
n integer;
d integer;
begin
n=gauche.numerateur*droite.denominateur;
d=gauche.denominateur*droite.numerateur;
return simplifie_fraction((n,d)::fraction);
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
|
1 2 3 4
| CREATE OPERATOR public./(
PROCEDURE = div_fraction,
LEFTARG = fraction,
RIGHTARG = fraction); |
|
Les converstions: INTEGER � fraction et fraction � NUMERIC
Une conversion est r�alis�e par une fonction et objet CAST
INTEGER � fraction
Fonction |
CAST |
1 2 3 4 5 6 7 8 9 10 11
| CREATE OR REPLACE FUNCTION public.inttofraction(intsrc integer)
RETURNS fraction AS
$BODY$
declare resultat fraction;
begin
resultat.numerateur=$1::dnumerateur;
resultat.denominateur=1::ddenominateur;
return resultat;
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
|
1 2 3
| CREATE CAST (integer AS fraction)
WITH FUNCTION public.inttofraction(integer)
AS ASSIGNMENT; |
|
fraction � NUMERIC
Fonction |
CAST |
1 2 3 4 5 6 7 8 9 10
| CREATE OR REPLACE FUNCTION public.fractiontonumeric(fractionsrc fraction)
RETURNS numeric AS
$BODY$
declare resultat numeric;
begin
resultat=(fractionsrc.numerateur::numeric/fractionsrc.denominateur::numeric)::numeric;
return resultat;
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
|
1 2 3
| CREATE CAST (fraction AS numeric)
WITH FUNCTION public.fractiontonumeric(fraction)
AS ASSIGNMENT; |
|
Les op�rateurs de comparaison:=, >, < >=, <=
L'�galit� =
Fonction |
Op�rateur |
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| CREATE OR REPLACE FUNCTION public.egal_fraction(
gauche fraction,
droite fraction)
RETURNS boolean AS
$BODY$
begin
if $1.numerateur*$2.denominateur=$2.numerateur*$1.denominateur
then return true;
else
return false;
end if;
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
|
1 2 3 4 5
| CREATE OPERATOR public.=(
PROCEDURE = egal_fraction,
LEFTARG = fraction,
RIGHTARG = fraction,
COMMUTATOR = =); |
|
Sup�rieur >
Fonction |
Op�rateur |
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| CREATE OR REPLACE FUNCTION public.supp_fraction(
gauche fraction,
droite fraction)
RETURNS boolean AS
$BODY$
begin
if $1::numeric>$2::numeric
then return true;
else
return false;
end if;
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
|
1 2 3 4 5
| CREATE OPERATOR public.>(
PROCEDURE = supp_fraction,
LEFTARG = fraction,
RIGHTARG = fraction,
COMMUTATOR = <); |
|
Sup�rieur ou �gal>=
Fonction |
Op�rateur |
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| CREATE OR REPLACE FUNCTION public.suppouegal_fraction(
gauche fraction,
droite fraction)
RETURNS boolean AS
$BODY$
begin
if (supp_fraction($1,$2)=true) or (egal_fraction($1,$2)=true)
then return true;
else
return false;
end if;
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
|
1 2 3 4 5
| CREATE OPERATOR public.>=(
PROCEDURE = suppouegal_fraction,
LEFTARG = fraction,
RIGHTARG = fraction,
COMMUTATOR = <=); |
|
Inf�rieur <
Fonction |
Op�rateur |
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| CREATE OR REPLACE FUNCTION public.inf_fraction(
gauche fraction,
droite fraction)
RETURNS boolean AS
$BODY$
begin
if $1::numeric<$2::numeric
then return true;
else
return false;
end if;
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
|
1 2 3 4 5
| CREATE OPERATOR public.<(
PROCEDURE = inf_fraction,
LEFTARG = fraction,
RIGHTARG = fraction,
COMMUTATOR = >); |
|
Inf�rieur ou �gal>=
Fonction |
Op�rateur |
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| CREATE OR REPLACE FUNCTION public.infouegal_fraction(
gauche fraction,
droite fraction)
RETURNS boolean AS
$BODY$
begin
if (inf_fraction($1,$2)=true) or (egal_fraction($1,$2)=true)
then return true;
else
return false;
end if;
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
|
1 2 3 4 5
| CREATE OPERATOR public.<=(
PROCEDURE = infouegal_fraction,
LEFTARG = fraction,
RIGHTARG = fraction,
COMMUTATOR = >=); |
|
Classe et famille d�op�rateurs
Pour un d�finir un index sur notre type nous avons besoin de cr�er une classe d�op�rateur
La classe
1 2 3 4 5 6 7 8
| CREATE OPERATOR CLASS public.fraction_ops DEFAULT
FOR TYPE fraction USING btree AS
OPERATOR 1 <,
OPERATOR 2 <=,
OPERATOR 3 =,
OPERATOR 4 >=,
OPERATOR 5 >,
FUNCTION 1 public.compare_fraction(fraction, fraction); |
... la fonction de comparaison
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| CREATE OR REPLACE FUNCTION public.compare_fraction(
gauche fraction,
droite fraction)
RETURNS integer AS
$BODY$
begin
if $1>$2
then return 1;
elsif $1<$2
then return -1;
else
return 0;
end if;
end
$BODY$
LANGUAGE plpgsql IMMUTABLE |
La famille (automatiquement cr��e)
CREATE OPERATOR FAMILY public.fraction_ops USING btree;
Cr�ation d'une table avec index
1 2 3 4 5 6 7 8 9 10
| CREATE TABLE public.lesfractions
(
idfraction serial NOT NULL,
unevaleur fraction,
CONSTRAINT lesfractions_pkey PRIMARY KEY (idfraction)
);
CREATE INDEX ind2
ON public.lesfractions
USING btree
(unevaleur); |