diff -c -r --new-file pgsql.03/doc/src/sgml/func.sgml pgsql/doc/src/sgml/func.sgml
*** pgsql.03/doc/src/sgml/func.sgml 2005-06-07 00:49:35.000000000 +0200
--- pgsql/doc/src/sgml/func.sgml 2005-06-07 22:51:07.000000000 +0200
***************
*** 5099,5104 ****
--- 5099,5112 ----
+ last_day(date)
+ date
+ Returns last day of the month based on a date value
+ last_day(date '2005-05-24')
+ 2005-05-31
+
+
+
localtime
time
Time of day; see
***************
*** 5117,5122 ****
--- 5125,5138 ----
+ next_day(date, text)
+ date
+ Returns the first weekday that is greather than a date value.
+ next_day(date '2005-05-24', 'monday')
+ 2005-05-30
+
+
+
now()
timestamp with time zone
Current date and time (equivalent to
diff -c -r --new-file pgsql.03/src/backend/utils/adt/oracle_compat.c pgsql/src/backend/utils/adt/oracle_compat.c
*** pgsql.03/src/backend/utils/adt/oracle_compat.c 2005-06-06 15:29:18.000000000 +0200
--- pgsql/src/backend/utils/adt/oracle_compat.c 2005-06-07 22:30:08.000000000 +0200
***************
*** 31,36 ****
--- 31,38 ----
#include "utils/builtins.h"
#include "utils/pg_locale.h"
#include "mb/pg_wchar.h"
+ #include "utils/date.h"
+ #include "utils/nabstime.h"
/*
***************
*** 48,53 ****
--- 50,71 ----
#define USE_WIDE_UPPER_LOWER
#endif
+ /*
+ * External (defined in PgSQL datetime.c (timestamp utils))
+ */
+
+ extern char *days[];
+
+ #define CHECK_SEQ_SEARCH(_l, _s) \
+ do { \
+ if ((_l) < 0) { \
+ ereport(ERROR, \
+ (errcode(ERRCODE_INVALID_DATETIME_FORMAT), \
+ errmsg("invalid value for %s", (_s)))); \
+ } \
+ } while (0)
+
+
static text *dotrim(const char *string, int stringlen,
const char *set, int setlen,
bool doltrim, bool dortrim);
***************
*** 1157,1159 ****
--- 1175,1273 ----
PG_RETURN_TEXT_P(result);
}
+
+ /********************************************************************
+ *
+ * next_day
+ *
+ * Syntax:
+ *
+ * date next_day(date value, text weekday)
+ *
+ * Purpose:
+ *
+ * Returns the first weekday that is greater than a date value.
+ *
+ ********************************************************************/
+
+ /*
+ * Search const value in char array
+ *
+ */
+
+ static int
+ seq_search(char *name, char **array, int max)
+ {
+ char *p, *n, **a;
+ int last, i;
+
+ if (!*name)
+ return -1;
+
+ *name = pg_toupper((unsigned char) *name);
+ for (last = 0, a = array; *a != NULL; a++)
+ {
+ if (*name != **a)
+ continue;
+
+ for (i = 1, p = *a + 1, n = name + 1;; n++, p++, i++)
+ {
+ if (i == max)
+ return a - array;
+ if (*p == '\0')
+ break;
+ if (i > last)
+ {
+ *n = pg_tolower((unsigned char) *n);
+ last = i;
+ }
+
+ if (*n != *p)
+ break;
+ }
+ }
+
+ return -1;
+ }
+
+
+ Datum next_day (PG_FUNCTION_ARGS)
+ {
+
+ DateADT day = PG_GETARG_DATEADT(0);
+ text *day_txt = PG_GETARG_TEXT_P(1);
+ int off;
+
+ int d = seq_search(VARDATA(day_txt), days, VARATT_SIZEP(day_txt) - VARHDRSZ);
+ CHECK_SEQ_SEARCH(d, "DAY/Day/day");
+
+ off = d - j2day(day+POSTGRES_EPOCH_JDATE);
+
+ PG_RETURN_DATEADT((off <= 0) ? day+off+7 : day + off);
+ }
+
+ /********************************************************************
+ *
+ * last_day
+ *
+ * Syntax:
+ *
+ * date last_day(date value)
+ *
+ * Purpose:
+ *
+ * Returns last day of the month based on a date value
+ *
+ ********************************************************************/
+
+
+ Datum last_day (PG_FUNCTION_ARGS)
+ {
+ DateADT day = PG_GETARG_DATEADT(0);
+ DateADT result;
+ int y, m, d;
+ j2date(day + POSTGRES_EPOCH_JDATE, &y, &m, &d);
+ result = date2j(y, m+1, 1) - POSTGRES_EPOCH_JDATE;
+
+ PG_RETURN_DATEADT(result - 1);
+ }
diff -c -r --new-file pgsql.03/src/include/catalog/pg_proc.h pgsql/src/include/catalog/pg_proc.h
*** pgsql.03/src/include/catalog/pg_proc.h 2005-06-06 15:29:40.000000000 +0200
--- pgsql/src/include/catalog/pg_proc.h 2005-06-07 22:19:39.000000000 +0200
***************
*** 2196,2201 ****
--- 2196,2206 ----
DATA(insert OID = 885 ( btrim PGNSP PGUID 12 f f t f i 1 25 "25" _null_ _null_ _null_ btrim1 - _null_ ));
DESCR("trim spaces from both ends of string");
+ DATA(insert OID = 1248 ( next_day PGNSP PGUID 12 f f t f i 2 1082 "1082 25" _null_ _null_ _null_ next_day - _null_ ));
+ DESCR("return the first weekday that is greater than a date value");
+ DATA(insert OID = 1250 ( last_day PGNSP PGUID 12 f f t f i 1 1082 "1082" _null_ _null_ _null_ last_day - _null_ ));
+ DESCR("last day of the month");
+
DATA(insert OID = 936 ( substring PGNSP PGUID 12 f f t f i 3 25 "25 23 23" _null_ _null_ _null_ text_substr - _null_ ));
DESCR("return portion of string");
DATA(insert OID = 937 ( substring PGNSP PGUID 12 f f t f i 2 25 "25 23" _null_ _null_ _null_ text_substr_no_len - _null_ ));
diff -c -r --new-file pgsql.03/src/include/utils/builtins.h pgsql/src/include/utils/builtins.h
*** pgsql.03/src/include/utils/builtins.h 2005-06-06 15:29:46.000000000 +0200
--- pgsql/src/include/utils/builtins.h 2005-06-07 22:31:34.000000000 +0200
***************
*** 649,654 ****
--- 649,656 ----
extern Datum chr (PG_FUNCTION_ARGS);
extern Datum repeat(PG_FUNCTION_ARGS);
extern Datum ascii(PG_FUNCTION_ARGS);
+ extern Datum next_day(PG_FUNCTION_ARGS);
+ extern Datum last_day(PG_FUNCTION_ARGS);
/* inet_net_ntop.c */
extern char *inet_net_ntop(int af, const void *src, int bits,
diff -c -r --new-file pgsql.03/src/test/regress/expected/oracle.out pgsql/src/test/regress/expected/oracle.out
*** pgsql.03/src/test/regress/expected/oracle.out 2005-06-07 00:55:32.000000000 +0200
--- pgsql/src/test/regress/expected/oracle.out 2005-06-07 22:50:54.000000000 +0200
***************
*** 72,74 ****
--- 72,109 ----
b
(1 row)
+ SELECT last_day (to_date('2003/03/15', 'yyyy/mm/dd'));
+ last_day
+ ------------
+ 2003-03-31
+ (1 row)
+
+ SELECT last_day (to_date('2003/02/03', 'yyyy/mm/dd'));
+ last_day
+ ------------
+ 2003-02-28
+ (1 row)
+
+ SELECT last_day (to_date('2004/02/03', 'yyyy/mm/dd'));
+ last_day
+ ------------
+ 2004-02-29
+ (1 row)
+
+ SELECT next_day ('2003-08-01', 'TUESDAY');
+ next_day
+ ------------
+ 2003-08-05
+ (1 row)
+
+ SELECT next_day ('2003-08-06', 'WEDNESDAY');
+ next_day
+ ------------
+ 2003-08-13
+ (1 row)
+
+ SELECT next_day ('2003-08-06', 'SUNDAY');
+ next_day
+ ------------
+ 2003-08-10
+ (1 row)
diff -c -r --new-file pgsql.03/src/test/regress/expected/oracle.out~ pgsql/src/test/regress/expected/oracle.out~
*** pgsql.03/src/test/regress/expected/oracle.out~ 1970-01-01 01:00:00.000000000 +0100
--- pgsql/src/test/regress/expected/oracle.out~ 2005-06-07 00:55:32.000000000 +0200
***************
*** 0 ****
--- 1,74 ----
+ SELECT least(1,10,20,30);
+ least
+ -------
+ 1
+ (1 row)
+
+ SELECT least('a','b','c','d');
+ least
+ -------
+ a
+ (1 row)
+
+ SELECT least('2004-05-22'::date, '2004-05-10'::date);
+ least
+ ------------
+ 2004-05-10
+ (1 row)
+
+ SELECT greatest(1,10,20,30);
+ greatest
+ ----------
+ 30
+ (1 row)
+
+ SELECT greatest('a','b','c','d');
+ greatest
+ ----------
+ d
+ (1 row)
+
+ SELECT greatest('2004-05-22'::date, '2004-05-10'::date);
+ greatest
+ ------------
+ 2004-05-22
+ (1 row)
+
+ SELECT decode('a','n',10,'m',20,'a',30);
+ decode
+ --------
+ 30
+ (1 row)
+
+ SELECT decode('a','n');
+ ERROR: Function Decode needs minimal three arguments
+ SELECT decode('a','n',10,'m',20,'o',30,40);
+ decode
+ --------
+ 40
+ (1 row)
+
+ SELECT decode(2,1,'2004-01-01'::date,2,'2004-04-01'::date,3,'2004-07-01'::date);
+ decode
+ ------------
+ 2004-04-01
+ (1 row)
+
+ SELECT decode(null,1,'2004-01-01'::date,2,'2004-04-01'::date,3,'2004-07-01'::date);
+ decode
+ --------
+
+ (1 row)
+
+ SELECT decode(4,1,'2004-01-01'::date,2,'2004-04-01'::date,3,'2004-07-01'::date);
+ decode
+ --------
+
+ (1 row)
+
+ SELECT decode(null,'a','a',null,'b');
+ decode
+ --------
+ b
+ (1 row)
+
diff -c -r --new-file pgsql.03/src/test/regress/sql/oracle.sql pgsql/src/test/regress/sql/oracle.sql
*** pgsql.03/src/test/regress/sql/oracle.sql 2005-06-07 00:52:13.000000000 +0200
--- pgsql/src/test/regress/sql/oracle.sql 2005-06-07 22:49:53.000000000 +0200
***************
*** 13,15 ****
--- 13,23 ----
SELECT decode(null,1,'2004-01-01'::date,2,'2004-04-01'::date,3,'2004-07-01'::date);
SELECT decode(4,1,'2004-01-01'::date,2,'2004-04-01'::date,3,'2004-07-01'::date);
SELECT decode(null,'a','a',null,'b');
+
+ SELECT last_day (to_date('2003/03/15', 'yyyy/mm/dd'));
+ SELECT last_day (to_date('2003/02/03', 'yyyy/mm/dd'));
+ SELECT last_day (to_date('2004/02/03', 'yyyy/mm/dd'));
+
+ SELECT next_day ('2003-08-01', 'TUESDAY');
+ SELECT next_day ('2003-08-06', 'WEDNESDAY');
+ SELECT next_day ('2003-08-06', 'SUNDAY');
diff -c -r --new-file pgsql.03/src/test/regress/sql/oracle.sql~ pgsql/src/test/regress/sql/oracle.sql~
*** pgsql.03/src/test/regress/sql/oracle.sql~ 1970-01-01 01:00:00.000000000 +0100
--- pgsql/src/test/regress/sql/oracle.sql~ 2005-06-07 00:52:13.000000000 +0200
***************
*** 0 ****
--- 1,15 ----
+ SELECT least(1,10,20,30);
+ SELECT least('a','b','c','d');
+ SELECT least('2004-05-22'::date, '2004-05-10'::date);
+
+ SELECT greatest(1,10,20,30);
+ SELECT greatest('a','b','c','d');
+ SELECT greatest('2004-05-22'::date, '2004-05-10'::date);
+
+ SELECT decode('a','n',10,'m',20,'a',30);
+ SELECT decode('a','n');
+ SELECT decode('a','n',10,'m',20,'o',30,40);
+ SELECT decode(2,1,'2004-01-01'::date,2,'2004-04-01'::date,3,'2004-07-01'::date);
+ SELECT decode(null,1,'2004-01-01'::date,2,'2004-04-01'::date,3,'2004-07-01'::date);
+ SELECT decode(4,1,'2004-01-01'::date,2,'2004-04-01'::date,3,'2004-07-01'::date);
+ SELECT decode(null,'a','a',null,'b');