Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
#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