From d31a8c1e054cbf7038c331cabc7a2408904940b6 Mon Sep 17 00:00:00 2001 From: whatdoineed2do/Ray Date: Sun, 7 Jul 2019 20:56:47 +0100 Subject: [PATCH 1/6] [smartpl] generate dynamic dates for SMARTPL queries For dates that require context (ie today, yesterday, N days ago etc) we want the underlying SQL to respect the current time when running query; a query that requests items for 'today' should only find matches for the time it was run. Current implementation would generated a fixed date (at the time the SMARTPL is inserted into db) in the playlist table where as this commit understands the context of the date. --- src/SMARTPL2SQL.g | 113 ++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 64 deletions(-) diff --git a/src/SMARTPL2SQL.g b/src/SMARTPL2SQL.g index fb4f3865..fb013720 100644 --- a/src/SMARTPL2SQL.g +++ b/src/SMARTPL2SQL.g @@ -38,19 +38,6 @@ options { } @members { - static time_t startoftoday() - { - struct tm tm; - time_t now; - - time(&now); - localtime_r(&now, &tm); - tm.tm_sec = 0; - tm.tm_min = 0; - tm.tm_hour = 0; - - return mktime(&tm); - } } playlist returns [ pANTLR3_STRING title, pANTLR3_STRING query, pANTLR3_STRING orderby, pANTLR3_STRING having, int limit ] @@ -213,25 +200,19 @@ expression returns [ pANTLR3_STRING result, pANTLR3_STRING orderby, pANTLR3_STRI } | DATETAG AFTER dateval { - char str[15]; - sprintf(str, "\%d", $dateval.result); - $result = $DATETAG.text->factory->newRaw($DATETAG.text->factory); $result->append8($result, "f."); $result->appendS($result, $DATETAG.text->toUTF8($DATETAG.text)); $result->append8($result, " > "); - $result->append8($result, str); + $result->append8($result, (const char*)$dateval.result->chars); } | DATETAG BEFORE dateval { - char str[15]; - sprintf(str, "\%d", $dateval.result); - $result = $DATETAG.text->factory->newRaw($DATETAG.text->factory); $result->append8($result, "f."); $result->appendS($result, $DATETAG.text->toUTF8($DATETAG.text)); $result->append8($result, " < "); - $result->append8($result, str); + $result->append8($result, (const char*)$dateval.result->chars); } | ENUMTAG IS ENUMVAL { @@ -328,118 +309,122 @@ ordertag returns [ pANTLR3_STRING result ] } ; -dateval returns [ int result ] +dateval returns [ pANTLR3_STRING result ] @init { $result = 0; } : DATE { pANTLR3_UINT8 datval; datval = $DATE.text->chars; - + + $result = $DATE.text->factory->newRaw($DATE.text->factory); + if (strcmp((char *)datval, "today") == 0) { - $result = startoftoday(); + $result->append8($result, "strftime('\%s', datetime('now', 'start of day', 'localtime'))"); } else if (strcmp((char *)datval, "yesterday") == 0) { - $result = startoftoday() - 24 * 3600; + $result->append8($result, "strftime('\%s', datetime('now', 'start of day', '-1 day', 'localtime'))"); } else if (strcmp((char *)datval, "last week") == 0) { - $result = startoftoday() - 24 * 3600 * 7; + $result->append8($result, "strftime('\%s', datetime('now', 'start of day', 'weekday 0', '-13 days', 'localtime'))"); } else if (strcmp((char *)datval, "last month") == 0) { - $result = startoftoday() - 24 * 3600 * 30; + $result->append8($result, "strftime('\%s', datetime('now', 'start of month', '-1 month', 'localtime'))"); } else if (strcmp((char *)datval, "last year") == 0) { - $result = startoftoday() - 24 * 3600 * 365; + $result->append8($result, "strftime('\%s', datetime('now', 'start of year', '-1 year', 'localtime'))"); } else { - struct tm tm; - char year[5]; - char month[3]; - char day[3]; - - memset((void*)&tm,0,sizeof(tm)); - memset(year, 0, sizeof(year)); - memset(month, 0, sizeof(month)); - memset(day, 0, sizeof(day)); - - strncpy(year, (const char *)datval, 4); - strncpy(month, (const char *)datval + 5, 2); - strncpy(day, (const char *)datval + 8, 2); - - tm.tm_year = atoi(year) - 1900; - tm.tm_mon = atoi(month) - 1; - tm.tm_mday = atoi(day); - - $result = mktime(&tm); + $result->append8($result, "strftime('\%s', datetime('YYYY-MM-DD', (char*)dateval, 'localtime'))"); } } | interval BEFORE DATE { pANTLR3_UINT8 datval; - + char str[15]; + datval = $DATE.text->chars; + sprintf(str, "\%d", $interval.result); + + $result = $DATE.text->factory->newRaw($DATE.text->factory); if (strcmp((char *)datval, "yesterday") == 0) { - $result = startoftoday() - 24 * 3600; + $result->append8($result, "strftime('\%s', datetime('now', 'start of day', '-1 day', "); } else if (strcmp((char *)datval, "last week") == 0) { - $result = startoftoday() - 24 * 3600 * 7; + $result->append8($result, "strftime('\%s', datetime('now', 'start of day', 'weekday 0', '-13 days', "); } else if (strcmp((char *)datval, "last month") == 0) { - $result = startoftoday() - 24 * 3600 * 30; + $result->append8($result, "strftime('\%s', datetime('now', 'start of month', '-1 month', "); } else if (strcmp((char *)datval, "last year") == 0) { - $result = startoftoday() - 24 * 3600 * 365; + $result->append8($result, "strftime('\%s', datetime('now', 'start of year', '-1 year', "); } else { - $result = startoftoday(NULL); + $result->append8($result, "strftime('\%s', datetime('now', 'start of day', "); } - - $result = $result - $interval.result; - } + + $result->append8($result, "'-"); + $result->append8($result, str); + $result->append8($result, " seconds', 'localtime'))"); + } | interval AFTER DATE { pANTLR3_UINT8 datval; + char str[15]; datval = $DATE.text->chars; + sprintf(str, "\%d", $interval.result); + $result = $DATE.text->factory->newRaw($DATE.text->factory); + if (strcmp((char *)datval, "yesterday") == 0) { - $result = startoftoday() - 24 * 3600; + $result->append8($result, "strftime('\%s', datetime('now', 'start of day', '-1 day', "); } else if (strcmp((char *)datval, "last week") == 0) { - $result = startoftoday() - 24 * 3600 * 7; + $result->append8($result, "strftime('\%s', datetime('now', 'start of day', 'weekday 0', '-13 days', "); } else if (strcmp((char *)datval, "last month") == 0) { - $result = startoftoday() - 24 * 3600 * 30; + $result->append8($result, "strftime('\%s', datetime('now', 'start of month', '-1 month', "); } else if (strcmp((char *)datval, "last year") == 0) { - $result = startoftoday() - 24 * 3600 * 365; + $result->append8($result, "strftime('\%s', datetime('now', 'start of year', '-1 year', "); } else { - $result = startoftoday(); + $result->append8($result, "strftime('\%s', datetime('now', 'start of day', "); } - $result = $result + $interval.result; - } + $result->append8($result, "'+"); + $result->append8($result, str); + $result->append8($result, " seconds', 'localtime'))"); + } | interval AGO { - $result = startoftoday() - $interval.result; + char str[15]; + sprintf(str, "\%d", $interval.result); + + $result = $AGO.text->factory->newRaw($AGO.text->factory); + + $result->append8($result, "strftime('\%s', datetime('now', 'start of day', "); + $result->append8($result, "'-"); + $result->append8($result, str); + $result->append8($result, " seconds', 'localtime'))"); } ; From 3dcd826513f362d9b22f421f6cbdf8f9d4ec2cc1 Mon Sep 17 00:00:00 2001 From: whatdoineed2do/Ray Date: Sun, 7 Jul 2019 23:29:41 +0100 Subject: [PATCH 2/6] [smartpl] date 'interval' handling defered to db/not using potentially inaccurate time_t calcaulations --- src/SMARTPL2SQL.g | 55 ++++++++++++----------------------------------- 1 file changed, 14 insertions(+), 41 deletions(-) diff --git a/src/SMARTPL2SQL.g b/src/SMARTPL2SQL.g index fb013720..65588baa 100644 --- a/src/SMARTPL2SQL.g +++ b/src/SMARTPL2SQL.g @@ -310,7 +310,7 @@ ordertag returns [ pANTLR3_STRING result ] ; dateval returns [ pANTLR3_STRING result ] -@init { $result = 0; } +@init { $result = NULL; } : DATE { pANTLR3_UINT8 datval; @@ -347,10 +347,8 @@ dateval returns [ pANTLR3_STRING result ] | interval BEFORE DATE { pANTLR3_UINT8 datval; - char str[15]; datval = $DATE.text->chars; - sprintf(str, "\%d", $interval.result); $result = $DATE.text->factory->newRaw($DATE.text->factory); @@ -376,16 +374,14 @@ dateval returns [ pANTLR3_STRING result ] } $result->append8($result, "'-"); - $result->append8($result, str); - $result->append8($result, " seconds', 'localtime'))"); + $result->append8($result, (const char *)$interval.result->chars); + $result->append8($result, "', 'localtime'))"); } | interval AFTER DATE { pANTLR3_UINT8 datval; - char str[15]; datval = $DATE.text->chars; - sprintf(str, "\%d", $interval.result); $result = $DATE.text->factory->newRaw($DATE.text->factory); @@ -411,52 +407,29 @@ dateval returns [ pANTLR3_STRING result ] } $result->append8($result, "'+"); - $result->append8($result, str); - $result->append8($result, " seconds', 'localtime'))"); + $result->append8($result, (const char *)$interval.result->chars); + $result->append8($result, "', 'localtime'))"); } | interval AGO { - char str[15]; - sprintf(str, "\%d", $interval.result); - $result = $AGO.text->factory->newRaw($AGO.text->factory); $result->append8($result, "strftime('\%s', datetime('now', 'start of day', "); $result->append8($result, "'-"); - $result->append8($result, str); - $result->append8($result, " seconds', 'localtime'))"); + $result->append8($result, (const char *)$interval.result->chars); + $result->append8($result, "', 'localtime'))"); } ; -interval returns [ int result ] -@init { $result = 0; } +interval returns [ pANTLR3_STRING result ] +@init { $result = NULL; } : INT DATINTERVAL { - pANTLR3_UINT8 interval; - - $result = atoi((const char *)$INT.text->chars); - interval = $DATINTERVAL.text->chars; - - if (strcmp((char *)interval, "days") == 0) - { - $result = $result * 24 * 3600; - } - else if (strcmp((char *)interval, "weeks") == 0) - { - $result = $result * 24 * 3600 * 7; - } - else if (strcmp((char *)interval, "months") == 0) - { - $result = $result * 24 * 3600 * 30; - } - else if (strcmp((char *)interval, "weeks") == 0) - { - $result = $result * 24 * 3600 * 365; - } - else - { - $result = 0; - } + $result = $DATINTERVAL.text->factory->newRaw($DATINTERVAL.text->factory); + $result->append8($result, (const char *)$INT.text->chars); + $result->append8($result, " "); + $result->append8($result, (const char *)$DATINTERVAL.text->chars); + return $result; } ; From 62201e41280770c808bd41b5143807d4ee5cf045 Mon Sep 17 00:00:00 2001 From: whatdoineed2do/Ray Date: Mon, 8 Jul 2019 12:15:11 +0100 Subject: [PATCH 3/6] [smartpl] handle intervals in 'week' as days due to lack of SQLite modifier support --- src/SMARTPL2SQL.g | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/SMARTPL2SQL.g b/src/SMARTPL2SQL.g index 65588baa..c58c9f75 100644 --- a/src/SMARTPL2SQL.g +++ b/src/SMARTPL2SQL.g @@ -425,10 +425,27 @@ interval returns [ pANTLR3_STRING result ] @init { $result = NULL; } : INT DATINTERVAL { + pANTLR3_UINT8 interval; + int intval; + char buf[25]; + $result = $DATINTERVAL.text->factory->newRaw($DATINTERVAL.text->factory); - $result->append8($result, (const char *)$INT.text->chars); - $result->append8($result, " "); - $result->append8($result, (const char *)$DATINTERVAL.text->chars); + + // SQL doesnt have a modifer for 'week' but for day/hr/min/sec/month/yr + interval = $DATINTERVAL.text->chars; + if (strcmp((char *)interval, "weeks") == 0) + { + intval = atoi((const char *)$INT.text->chars) * 7; + snprintf(buf, sizeof(buf), "\%d days", intval); + + $result->append8($result, buf); + } + else + { + $result->append8($result, (const char *)$INT.text->chars); + $result->append8($result, " "); + $result->append8($result, (const char *)$DATINTERVAL.text->chars); + } return $result; } ; From 68e601f7e37b9dec64a3bb5bdb90725a68509ed8 Mon Sep 17 00:00:00 2001 From: whatdoineed2do/Ray Date: Wed, 10 Jul 2019 22:03:26 +0100 Subject: [PATCH 4/6] [README] date handling clarification --- README_SMARTPL.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README_SMARTPL.md b/README_SMARTPL.md index 327a2f1a..b763ab4a 100644 --- a/README_SMARTPL.md +++ b/README_SMARTPL.md @@ -150,6 +150,8 @@ One example of a valid date is a date in yyyy-mm-dd format: There are also some special date keywords: * `today`, `yesterday`, `last week`, `last month`, `last year` +These dates refer to the _start_ of that period; `today` means 00:00hrs of today, `last week` means the previous Monday 00:00hrs, `last month` is the first day of the previous month at 00:00hrs etc. + A valid date can also be made by applying an interval to a date. Intervals can be defined as `days`, `weeks`, `months`, `years`. As an example, a valid date might be: @@ -173,7 +175,11 @@ This matches all songs added in the last 2 weeks. } ``` -This matches all audiobooks played in the last week. +This matches all audiobooks played since the start of the last Monday 00:00AM. + +All dates, except for `YYYY-DD-HH`, are relative to the day of when `forked-daapd` evaluates the smartpl query; `time_added after today` run on a Monday would match against items added since Monday 00:00hrs and evaluating the same smartpl on Friday would only match against added on Friday 00:00hrs. + +Note that `time_added after 4 weeks ago` and `time_added after last month` are subtly different; the former is exactly 4 weeks ago (from today) whereas the latter is the first day of the previous month. ## Differences to mt-daapd smart playlists From 02d4ba1eaa277a47ff6e09e355553150f3b34194 Mon Sep 17 00:00:00 2001 From: whatdoineed2do/Ray Date: Thu, 11 Jul 2019 18:30:37 +0100 Subject: [PATCH 5/6] [smartpl] remove dupl code from interval AFTER/BEFORE DATE --- src/SMARTPL2SQL.g | 88 ++++++++++++++++------------------------------- 1 file changed, 30 insertions(+), 58 deletions(-) diff --git a/src/SMARTPL2SQL.g b/src/SMARTPL2SQL.g index c58c9f75..ef4983b0 100644 --- a/src/SMARTPL2SQL.g +++ b/src/SMARTPL2SQL.g @@ -38,6 +38,34 @@ options { } @members { + static void interval_date(pANTLR3_STRING result, pANTLR3_UINT8 interval, pANTLR3_UINT8 datval, char beforeorafter) + { + if (strcmp((char *)datval, "yesterday") == 0) + { + result->append8(result, "strftime('\%s', datetime('now', 'start of day', '-1 day', "); + } + else if (strcmp((char *)datval, "last week") == 0) + { + result->append8(result, "strftime('\%s', datetime('now', 'start of day', 'weekday 0', '-13 days', "); + } + else if (strcmp((char *)datval, "last month") == 0) + { + result->append8(result, "strftime('\%s', datetime('now', 'start of month', '-1 month', "); + } + else if (strcmp((char *)datval, "last year") == 0) + { + result->append8(result, "strftime('\%s', datetime('now', 'start of year', '-1 year', "); + } + else + { + result->append8(result, "strftime('\%s', datetime('now', 'start of day', "); + } + + result->addc(result, '\''); + result->addc(result, beforeorafter); + result->append8(result, (const char *)interval); + result->append8(result, "', 'localtime'))"); + } } playlist returns [ pANTLR3_STRING title, pANTLR3_STRING query, pANTLR3_STRING orderby, pANTLR3_STRING having, int limit ] @@ -346,69 +374,13 @@ dateval returns [ pANTLR3_STRING result ] } | interval BEFORE DATE { - pANTLR3_UINT8 datval; - - datval = $DATE.text->chars; - $result = $DATE.text->factory->newRaw($DATE.text->factory); - - if (strcmp((char *)datval, "yesterday") == 0) - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of day', '-1 day', "); - } - else if (strcmp((char *)datval, "last week") == 0) - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of day', 'weekday 0', '-13 days', "); - } - else if (strcmp((char *)datval, "last month") == 0) - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of month', '-1 month', "); - } - else if (strcmp((char *)datval, "last year") == 0) - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of year', '-1 year', "); - } - else - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of day', "); - } - - $result->append8($result, "'-"); - $result->append8($result, (const char *)$interval.result->chars); - $result->append8($result, "', 'localtime'))"); + interval_date($result, $interval.result->chars, $DATE.text->chars, '-'); } | interval AFTER DATE { - pANTLR3_UINT8 datval; - - datval = $DATE.text->chars; - $result = $DATE.text->factory->newRaw($DATE.text->factory); - - if (strcmp((char *)datval, "yesterday") == 0) - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of day', '-1 day', "); - } - else if (strcmp((char *)datval, "last week") == 0) - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of day', 'weekday 0', '-13 days', "); - } - else if (strcmp((char *)datval, "last month") == 0) - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of month', '-1 month', "); - } - else if (strcmp((char *)datval, "last year") == 0) - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of year', '-1 year', "); - } - else - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of day', "); - } - - $result->append8($result, "'+"); - $result->append8($result, (const char *)$interval.result->chars); - $result->append8($result, "', 'localtime'))"); + interval_date($result, $interval.result->chars, $DATE.text->chars, '+'); } | interval AGO { From 772b18479defde0defc12146bc7d3536bfeda17d Mon Sep 17 00:00:00 2001 From: chme Date: Sun, 14 Jul 2019 10:02:17 +0200 Subject: [PATCH 6/6] [smartpl] Refactor appending date expression to sql query --- src/SMARTPL2SQL.g | 120 ++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 69 deletions(-) diff --git a/src/SMARTPL2SQL.g b/src/SMARTPL2SQL.g index ef4983b0..b2c151b1 100644 --- a/src/SMARTPL2SQL.g +++ b/src/SMARTPL2SQL.g @@ -38,34 +38,44 @@ options { } @members { - static void interval_date(pANTLR3_STRING result, pANTLR3_UINT8 interval, pANTLR3_UINT8 datval, char beforeorafter) - { - if (strcmp((char *)datval, "yesterday") == 0) - { - result->append8(result, "strftime('\%s', datetime('now', 'start of day', '-1 day', "); - } - else if (strcmp((char *)datval, "last week") == 0) - { - result->append8(result, "strftime('\%s', datetime('now', 'start of day', 'weekday 0', '-13 days', "); - } - else if (strcmp((char *)datval, "last month") == 0) - { - result->append8(result, "strftime('\%s', datetime('now', 'start of month', '-1 month', "); - } - else if (strcmp((char *)datval, "last year") == 0) - { - result->append8(result, "strftime('\%s', datetime('now', 'start of year', '-1 year', "); - } - else - { - result->append8(result, "strftime('\%s', datetime('now', 'start of day', "); - } + static void append_date(pANTLR3_STRING result, const char *datval, char beforeorafter, const char *interval) + { + if (strcmp((char *)datval, "today") == 0) + { + result->append8(result, "strftime('\%s', datetime('now', 'start of day'"); + } + else if (strcmp((char *)datval, "yesterday") == 0) + { + result->append8(result, "strftime('\%s', datetime('now', 'start of day', '-1 day'"); + } + else if (strcmp((char *)datval, "last week") == 0) + { + result->append8(result, "strftime('\%s', datetime('now', 'start of day', 'weekday 0', '-13 days'"); + } + else if (strcmp((char *)datval, "last month") == 0) + { + result->append8(result, "strftime('\%s', datetime('now', 'start of month', '-1 month'"); + } + else if (strcmp((char *)datval, "last year") == 0) + { + result->append8(result, "strftime('\%s', datetime('now', 'start of year', '-1 year'"); + } + else + { + result->append8(result, "strftime('\%s', datetime(\'"); + result->append8(result, datval); + result->append8(result, "\'"); + } - result->addc(result, '\''); - result->addc(result, beforeorafter); - result->append8(result, (const char *)interval); - result->append8(result, "', 'localtime'))"); - } + if (beforeorafter) + { + result->append8(result, ", '"); + result->addc(result, beforeorafter); + result->append8(result, interval); + result->addc(result, '\''); + } + result->append8(result, ", 'utc'))"); + } } playlist returns [ pANTLR3_STRING title, pANTLR3_STRING query, pANTLR3_STRING orderby, pANTLR3_STRING having, int limit ] @@ -344,52 +354,24 @@ dateval returns [ pANTLR3_STRING result ] pANTLR3_UINT8 datval; datval = $DATE.text->chars; - $result = $DATE.text->factory->newRaw($DATE.text->factory); - - if (strcmp((char *)datval, "today") == 0) - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of day', 'localtime'))"); - } - else if (strcmp((char *)datval, "yesterday") == 0) - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of day', '-1 day', 'localtime'))"); - } - else if (strcmp((char *)datval, "last week") == 0) - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of day', 'weekday 0', '-13 days', 'localtime'))"); - } - else if (strcmp((char *)datval, "last month") == 0) - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of month', '-1 month', 'localtime'))"); - } - else if (strcmp((char *)datval, "last year") == 0) - { - $result->append8($result, "strftime('\%s', datetime('now', 'start of year', '-1 year', 'localtime'))"); - } - else - { - $result->append8($result, "strftime('\%s', datetime('YYYY-MM-DD', (char*)dateval, 'localtime'))"); - } + + append_date($result, (const char *)datval, 0, NULL); } | interval BEFORE DATE { $result = $DATE.text->factory->newRaw($DATE.text->factory); - interval_date($result, $interval.result->chars, $DATE.text->chars, '-'); - } + append_date($result, (const char *)$DATE.text->chars, '-', (const char *)$interval.result->chars); + } | interval AFTER DATE { $result = $DATE.text->factory->newRaw($DATE.text->factory); - interval_date($result, $interval.result->chars, $DATE.text->chars, '+'); - } + append_date($result, (const char *)$DATE.text->chars, '+', (const char *)$interval.result->chars); + } | interval AGO { $result = $AGO.text->factory->newRaw($AGO.text->factory); - - $result->append8($result, "strftime('\%s', datetime('now', 'start of day', "); - $result->append8($result, "'-"); - $result->append8($result, (const char *)$interval.result->chars); - $result->append8($result, "', 'localtime'))"); + append_date($result, "today", '-', (const char *)$interval.result->chars); } ; @@ -397,7 +379,7 @@ interval returns [ pANTLR3_STRING result ] @init { $result = NULL; } : INT DATINTERVAL { - pANTLR3_UINT8 interval; + pANTLR3_UINT8 interval; int intval; char buf[25]; @@ -407,16 +389,16 @@ interval returns [ pANTLR3_STRING result ] interval = $DATINTERVAL.text->chars; if (strcmp((char *)interval, "weeks") == 0) { - intval = atoi((const char *)$INT.text->chars) * 7; - snprintf(buf, sizeof(buf), "\%d days", intval); + intval = atoi((const char *)$INT.text->chars) * 7; + snprintf(buf, sizeof(buf), "\%d days", intval); - $result->append8($result, buf); + $result->append8($result, buf); } else { - $result->append8($result, (const char *)$INT.text->chars); - $result->append8($result, " "); - $result->append8($result, (const char *)$DATINTERVAL.text->chars); + $result->append8($result, (const char *)$INT.text->chars); + $result->append8($result, " "); + $result->append8($result, (const char *)$DATINTERVAL.text->chars); } return $result; }