Vous n'êtes pas identifié(e).
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
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
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
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
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