PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 04/06/2010 17:52:28

FrViPofm
Membre

Parsing

Bonjour,
Je découvre Postgres. Je ne suis pas très fort en SQL. Et je suis confronté à un problème :
Créer une fonction(s) pour parser la ligne (1) :

FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;BYMINUTE=30

et la faire entrer dans un type 'rule' maison (2) :

CREATE TYPE ch_rule AS (
    "freq"          ch_enum_freq,
    "until"         timestamp,
    "count"         integer,
    "interval"      integer,
    "bymonth"       text,
    "byday"         text
    ...
);

J'arrive bien avec (3) :

SELECT *
FROM
    (SELECT
        lower(split_part( l, '=', 1)) AS k,
        lower(split_part( l, '=', 2)) AS v
    FROM (SELECT regexp_split_to_table ('FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;BYMINUTE=30', ';')) AS r("l")
    ) AS t

à obtenir un tableau du genre (4)

     k     |     v     
---------------------
 freq      | yearly
 interval  | 2
 bymonth   | 1

mais pas quelque chose du genre (5)

 freq      | interval | bymonth | ...
--------------------------------------
 yearly    | 2        | 1       | ...

J'ai essayé (un peu) avec crosstab. Je ne suis pas sur que ça corresponde à mon besoin. Il semble que crosstab interroge une 'table en dur'.
J'obtiens des messages du genre "la relation t n'existe pas."
Une piste ?
Merci d'avance.
--
Vincent
(postgres 8.4)

Hors ligne

#2 05/06/2010 10:02:45

gleu
Administrateur

Re : Parsing

Je ne comprends pas l'idée de le faire « entrer dans un type ». Vous ne voulez pas plutôt dire l'enregistrer dans une table composée de ces colonnes ?


Guillaume.

Hors ligne

#3 07/06/2010 13:18:19

ioguix
Administrateur

Re : Parsing

Bonjour,

Je pense que dans votre cas d'utilisation, l'utilisation de pl/perl serait 1/ plus simple, 2/ plus performante... si vous en avez la possibilité.

Hors ligne

#4 07/06/2010 14:02:08

Marc Cousin
Membre

Re : Parsing

Ou bien un ETL ou script en amont : convertir une chaine de caractère brute en données n'est pas le travail 'habituel' d'une base de données.


Marc.

Hors ligne

#5 07/06/2010 19:53:14

FrViPofm
Membre

Re : Parsing

Merci pour les réponses,
J'ai fait une fonction qui me retourne le type ch_rule :

CREATE OR REPLACE FUNCTION ch_rule_in(text)
  RETURNS ch_rule AS
$BODY$
WITH p AS (
    SELECT
        lower(split_part( l, '=', 1)) AS k,
        lower(split_part( l, '=', 2)) AS v
    FROM (SELECT regexp_split_to_table ($1, ';')) AS r("l")
    )
SELECT
    (SELECT p.v FROM p WHERE p.k='freq'      )::ch_freq_enum  AS "freq",
    (SELECT p.v FROM p WHERE p.k='interval'  )::int           AS "interval",
    (SELECT p.v FROM p WHERE p.k='until'     )::timestamp     AS "until",
    (SELECT p.v FROM p WHERE p.k='count'     )::int           AS "count",
    (SELECT p.v FROM p WHERE p.k='bysecond'  )::int           AS "bysecond",
    (SELECT p.v FROM p WHERE p.k='byminute'  )::int           AS "byminute",
    (SELECT p.v FROM p WHERE p.k='byhour'    )::int           AS "byhour",
    (SELECT (p.v)::ch_byday_type FROM p WHERE p.k='byday')    AS "byday",
    (SELECT p.v FROM p WHERE p.k='bymonthday')::int           AS "bymonthday",
    (SELECT p.v FROM p WHERE p.k='byyearday' )::int           AS "byyearday",
    (SELECT p.v FROM p WHERE p.k='byweekno'  )::int           AS "byweekno",
    (SELECT p.v FROM p WHERE p.k='bymonth'   )::int           AS "bymonth",
    (SELECT p.v FROM p WHERE p.k='bysetpos'  )::int           AS "bysetpos"
$BODY$
  LANGUAGE 'sql' IMMUTABLE

@ioguix : Merci pour la suggestion. Mais je n'en suis pas encore là : je ne connais pas perl (un peu python), quand à faire dialoguer postgres et perl... Peut-être un jour...

@Marc Cousin : ETL ? Si je connaissais un peu le C, je m'essaierai avec des fonctions appelant la libical. Mais je fais avec ce que je connais. Il y a deux mois, je ne connaissais pas postgres...

Je cherche à faire des requêtes sur une table du genre :

SELECT evt.name, evt.occurence FROM event AS evt WHERE date1 < evt.occurence < date2 AND st_intersect(evt.way, bbox)

C'est postGIS qui s'occupe du spatial, mais je n'ai pas trouvé d'extension postgres pour traiter iCal.
Donc j'essaie...
Je commence à arriver à quelques résultats simples et grossiers... mais j'avance...

Encore merci.

Hors ligne

Pied de page des forums