Skip to content

Commit

Permalink
add expand function with until argument; rename some C functions; ver…
Browse files Browse the repository at this point in the history
…sion bump
  • Loading branch information
petropavel13 committed Sep 25, 2014
1 parent ea617c4 commit c7cdc11
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 29 deletions.
2 changes: 1 addition & 1 deletion pg_rrule.control
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# pg_rrule extension
comment = 'RRULE field type for PostgreSQL'
default_version = '0.1.0'
default_version = '0.2.0'
relocatable = true
module_pathname = '$libdir/pg_rrule'
15 changes: 13 additions & 2 deletions sql/pg_rrule.sql
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,23 @@ CREATE CAST (varchar AS rrule)

CREATE OR REPLACE FUNCTION get_occurrences(rrule, timestamp with time zone)
RETURNS timestamp with time zone[]
AS 'MODULE_PATHNAME', 'pg_rrule_get_occurrences_rrule_timestamptz'
AS 'MODULE_PATHNAME', 'pg_rrule_get_occurrences_dtstart_tz'
LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION get_occurrences(rrule, timestamp with time zone, timestamp with time zone)
RETURNS timestamp with time zone[]
AS 'MODULE_PATHNAME', 'pg_rrule_get_occurrences_dtstart_until_tz'
LANGUAGE C IMMUTABLE STRICT;


CREATE OR REPLACE FUNCTION get_occurrences(rrule, timestamp)
RETURNS timestamp[]
AS 'MODULE_PATHNAME', 'pg_rrule_get_occurrences_rrule_timestamp'
AS 'MODULE_PATHNAME', 'pg_rrule_get_occurrences_dtstart'
LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION get_occurrences(rrule, timestamp, timestamp)
RETURNS timestamp[]
AS 'MODULE_PATHNAME', 'pg_rrule_get_occurrences_dtstart_until'
LANGUAGE C IMMUTABLE STRICT;


Expand Down
97 changes: 79 additions & 18 deletions src/pg_rrule.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ Datum pg_rrule_out(PG_FUNCTION_ARGS) {
}


Datum pg_rrule_get_occurrences_rrule_timestamptz(PG_FUNCTION_ARGS) {
Datum pg_rrule_get_occurrences_dtstart_tz(PG_FUNCTION_ARGS) {
struct icalrecurrencetype* recurrence_ref = (struct icalrecurrencetype*)PG_GETARG_POINTER(0);
TimestampTz ts = PG_GETARG_TIMESTAMPTZ(1);
TimestampTz dtstart_ts = PG_GETARG_TIMESTAMPTZ(1);

long int gmtoff = 0;
pg_get_timezone_offset(session_timezone, &gmtoff);

pg_time_t ts_pg_time_t = timestamptz_to_time_t(ts);
pg_time_t dtstart_ts_pg_time_t = timestamptz_to_time_t(dtstart_ts);

icaltimezone* ical_tz = icaltimezone_get_builtin_timezone_from_offset(gmtoff, pg_get_timezone_name(session_timezone));

Expand All @@ -74,24 +74,62 @@ Datum pg_rrule_get_occurrences_rrule_timestamptz(PG_FUNCTION_ARGS) {
ical_tz = icaltimezone_get_utc_timezone();
}

struct icaltimetype dtstart = icaltime_from_timet_with_zone((time_t)ts_pg_time_t, 0, ical_tz); // it's safe ? time_t may be double, float, etc...
struct icaltimetype dtstart = icaltime_from_timet_with_zone((time_t)dtstart_ts_pg_time_t, 0, ical_tz); // it's safe ? time_t may be double, float, etc...

return pg_rrule_get_occurrences_rrule(*recurrence_ref, dtstart, true);
}

Datum pg_rrule_get_occurrences_dtstart_until_tz(PG_FUNCTION_ARGS) {
struct icalrecurrencetype* recurrence_ref = (struct icalrecurrencetype*)PG_GETARG_POINTER(0);
TimestampTz dtstart_ts = PG_GETARG_TIMESTAMPTZ(1);
TimestampTz until_ts = PG_GETARG_TIMESTAMPTZ(2);

long int gmtoff = 0;
pg_get_timezone_offset(session_timezone, &gmtoff);

pg_time_t dtstart_ts_pg_time_t = timestamptz_to_time_t(dtstart_ts);
pg_time_t until_ts_pg_time_t = timestamptz_to_time_t(until_ts);

icaltimezone* ical_tz = icaltimezone_get_builtin_timezone_from_offset(gmtoff, pg_get_timezone_name(session_timezone));

if (ical_tz == NULL) {
elog(WARNING, "Can't get timezone from current session! Fallback to UTC.");
ical_tz = icaltimezone_get_utc_timezone();
}

struct icaltimetype dtstart = icaltime_from_timet_with_zone((time_t)dtstart_ts_pg_time_t, 0, ical_tz); // it's safe ? time_t may be double, float, etc...
struct icaltimetype until = icaltime_from_timet_with_zone((time_t)until_ts_pg_time_t, 0, ical_tz); // it's safe ? time_t may be double, float, etc...

return pg_rrule_get_occurrences_rrule_until(*recurrence_ref, dtstart, until, true);
}

Datum pg_rrule_get_occurrences_rrule_timestamp(PG_FUNCTION_ARGS) {

Datum pg_rrule_get_occurrences_dtstart(PG_FUNCTION_ARGS) {
struct icalrecurrencetype* recurrence_ref = (struct icalrecurrencetype*)PG_GETARG_POINTER(0);
Timestamp ts = PG_GETARG_TIMESTAMP(1);
Timestamp dtstart_ts = PG_GETARG_TIMESTAMP(1);

pg_time_t ts_pg_time_t = timestamptz_to_time_t(ts);
pg_time_t dtstart_ts_pg_time_t = timestamptz_to_time_t(dtstart_ts);

struct icaltimetype dtstart = icaltime_from_timet_with_zone((time_t)ts_pg_time_t, 0, icaltimezone_get_utc_timezone()); // it's safe ? time_t may be double, float, etc...
struct icaltimetype dtstart = icaltime_from_timet_with_zone((time_t)dtstart_ts_pg_time_t, 0, icaltimezone_get_utc_timezone()); // it's safe ? time_t may be double, float, etc...

return pg_rrule_get_occurrences_rrule(*recurrence_ref, dtstart, false);
}


Datum pg_rrule_get_occurrences_dtstart_until(PG_FUNCTION_ARGS) {
struct icalrecurrencetype* recurrence_ref = (struct icalrecurrencetype*)PG_GETARG_POINTER(0);
Timestamp dtstart_ts = PG_GETARG_TIMESTAMP(1);
Timestamp until_ts = PG_GETARG_TIMESTAMPTZ(2);

pg_time_t dtstart_ts_pg_time_t = timestamptz_to_time_t(dtstart_ts);
pg_time_t until_ts_pg_time_t = timestamptz_to_time_t(until_ts);

struct icaltimetype dtstart = icaltime_from_timet_with_zone((time_t)dtstart_ts_pg_time_t, 0, icaltimezone_get_utc_timezone()); // it's safe ? time_t may be double, float, etc...
struct icaltimetype until = icaltime_from_timet_with_zone((time_t)until_ts_pg_time_t, 0, icaltimezone_get_utc_timezone()); // it's safe ? time_t may be double, float, etc...

return pg_rrule_get_occurrences_rrule_until(*recurrence_ref, dtstart, until, false);
}

/* FREQ */
Datum pg_rrule_get_freq_rrule(PG_FUNCTION_ARGS) {
struct icalrecurrencetype* recurrence_ref = (struct icalrecurrencetype*)PG_GETARG_POINTER(0);
Expand Down Expand Up @@ -398,12 +436,19 @@ Datum pg_rrule_get_wkst_rrule(PG_FUNCTION_ARGS) {


Datum pg_rrule_get_occurrences_rrule(struct icalrecurrencetype recurrence,
struct icaltimetype dtstart,
bool use_tz) {
struct icaltimetype dtstart,
bool use_tz) {
return pg_rrule_get_occurrences_rrule_until(recurrence, dtstart, icaltime_null_time(), use_tz);
}

Datum pg_rrule_get_occurrences_rrule_until(struct icalrecurrencetype recurrence,
struct icaltimetype dtstart,
struct icaltimetype until,
bool use_tz) {
time_t* times_array = NULL;
unsigned int cnt = 0;

pg_rrule_to_time_t_array(recurrence, dtstart, &times_array, &cnt);
pg_rrule_rrule_to_time_t_array_until(recurrence, dtstart, until, &times_array, &cnt);
pg_time_t* pg_times_array = palloc(sizeof(pg_time_t) * cnt);

unsigned int i;
Expand Down Expand Up @@ -442,20 +487,36 @@ Datum pg_rrule_get_occurrences_rrule(struct icalrecurrencetype recurrence,
}


void pg_rrule_to_time_t_array(struct icalrecurrencetype recurrence,
struct icaltimetype dtstart,
time_t** const out_array,
unsigned int* const out_count) {
void pg_rrule_rrule_to_time_t_array(struct icalrecurrencetype recurrence,
struct icaltimetype dtstart,
time_t** const out_array,
unsigned int* const out_count) {
pg_rrule_rrule_to_time_t_array_until(recurrence, dtstart, icaltime_null_time(), out_array, out_count);
}

void pg_rrule_rrule_to_time_t_array_until(struct icalrecurrencetype recurrence,
struct icaltimetype dtstart,
struct icaltimetype until,
time_t** const out_array,
unsigned int* const out_count) {

icalrecur_iterator* const recur_iterator = icalrecur_iterator_new(recurrence, dtstart);

icalarray* const icaltimes_list = icalarray_new(sizeof(icaltimetype), 32);

struct icaltimetype ical_time = icalrecur_iterator_next(recur_iterator);

while (!icaltime_is_null_time(ical_time)) {
icalarray_append(icaltimes_list, &ical_time);
ical_time = icalrecur_iterator_next(recur_iterator);
if (icaltime_is_null_time(until)) {
while (icaltime_is_null_time(ical_time) == false) {
icalarray_append(icaltimes_list, &ical_time);
ical_time = icalrecur_iterator_next(recur_iterator);
}
} else {
while (icaltime_is_null_time(ical_time) == false
&& icaltime_compare(ical_time, until) != 1 ) { // while ical_time <= until
icalarray_append(icaltimes_list, &ical_time);
ical_time = icalrecur_iterator_next(recur_iterator);
}
}

icalrecur_iterator_free(recur_iterator);
Expand Down
34 changes: 26 additions & 8 deletions src/pg_rrule.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@ Datum pg_rrule_in(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(pg_rrule_out);
Datum pg_rrule_out(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(pg_rrule_get_occurrences_rrule_timestamptz);
Datum pg_rrule_get_occurrences_rrule_timestamptz(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(pg_rrule_get_occurrences_dtstart_tz);
Datum pg_rrule_get_occurrences_dtstart_tz(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(pg_rrule_get_occurrences_rrule_timestamp);
Datum pg_rrule_get_occurrences_rrule_timestamp(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(pg_rrule_get_occurrences_dtstart_until_tz);
Datum pg_rrule_get_occurrences_dtstart_until_tz(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(pg_rrule_get_occurrences_dtstart);
Datum pg_rrule_get_occurrences_dtstart(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(pg_rrule_get_occurrences_dtstart_until);
Datum pg_rrule_get_occurrences_dtstart_until(PG_FUNCTION_ARGS);

/* FREQ */
PG_FUNCTION_INFO_V1(pg_rrule_get_freq_rrule);
Expand Down Expand Up @@ -85,9 +91,21 @@ Datum pg_rrule_get_occurrences_rrule(struct icalrecurrencetype recurrence,
struct icaltimetype dtstart,
bool use_tz);

void pg_rrule_to_time_t_array(struct icalrecurrencetype recurrence,
struct icaltimetype dtstart,
time_t** const out_array,
unsigned int* const out_count);
Datum pg_rrule_get_occurrences_rrule_until(struct icalrecurrencetype recurrence,
struct icaltimetype dtstart,
struct icaltimetype until,
bool use_tz);


void pg_rrule_rrule_to_time_t_array(struct icalrecurrencetype recurrence,
struct icaltimetype dtstart,
time_t** const out_array,
unsigned int* const out_count);

void pg_rrule_rrule_to_time_t_array_until(struct icalrecurrencetype recurrence,
struct icaltimetype dtstart,
struct icaltimetype until,
time_t** const out_array,
unsigned int* const out_count);

#endif // PG_RRULE_H

0 comments on commit c7cdc11

Please sign in to comment.