Changeset: d148562e8a06 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/d148562e8a06
Modified Files:
sql/server/sql_datetime.c
sql/server/sql_datetime.h
sql/server/sql_parser.y
sql/server/sql_scan.c
sql/test/odbc-escape-sequences/Tests/time-date-interval-functions.test
Branch: escape-sequences
Log Message:
partial case for timestampadd add
diffs (233 lines):
diff --git a/sql/server/sql_datetime.c b/sql/server/sql_datetime.c
--- a/sql/server/sql_datetime.c
+++ b/sql/server/sql_datetime.c
@@ -329,10 +329,13 @@ int inttype2digits( int sk, int ek )
if(ek == iyear)
return 1;
return 2;
+ case iquarter:
case imonth:
return 3;
+ case iweek:
case iday:
switch(ek) {
+ case iweek:
case iday:
return 4;
case ihour:
@@ -473,3 +476,59 @@ get_timestamp_precision(const char* val)
parse_timestamp(val, &yr, &mt, &dy, &hr, &mn, &sc, &fr, &pr);
return pr;
}
+
+
+int
+process_odbc_interval(mvc *sql, itype interval, int val, sql_subtype *t, lng
*i)
+{
+ assert(sql);
+ int mul = 1;
+ int d = inttype2digits(interval, interval);
+ switch (interval) {
+ case iyear:
+ mul *= 12;
+ /* fall through */
+ case iquarter:
+ mul *= 3;
+ /* fall through */
+ case imonth:
+ break;
+ case iweek:
+ mul *= 7;
+ /* fall through */
+ case iday:
+ mul *= 24;
+ /* fall through */
+ case ihour:
+ mul *= 60;
+ /* fall through */
+ case imin:
+ mul *= 60000;
+ /* fall through */
+ case isec:
+ break;
+ default:
+ snprintf(sql->errstr, ERRSIZE, _("Internal error: bad
interval qualifier (%d)\n"), interval);
+ return -1;
+ }
+
+ // check for overflow
+ if (((lng) abs(val) * mul) > GDK_lng_max) {
+ snprintf(sql->errstr, ERRSIZE, _("Overflow\n"));
+ return -1;
+ }
+ // compute value month or sec interval
+ *i += val * mul;
+
+ int r = 0;
+ if (d < 4){
+ r = sql_find_subtype(t, "month_interval", d, 0);
+ } else if (d == 4) {
+ r = sql_find_subtype(t, "day_interval", d, 0);
+ } else {
+ r = sql_find_subtype(t, "sec_interval", d, 0);
+ }
+ if (!r)
+ return -1;
+ return 0;
+}
diff --git a/sql/server/sql_datetime.h b/sql/server/sql_datetime.h
--- a/sql/server/sql_datetime.h
+++ b/sql/server/sql_datetime.h
@@ -25,7 +25,8 @@ typedef enum inttype {
idoy,
icentury,
idecade,
- iepoch
+ iepoch,
+ insec
} itype;
int parse_interval_qualifier(mvc *sql, struct dlist *pers, int *sk, int *ek,
int *sp, int *ep);
@@ -74,5 +75,7 @@ parse_timestamp(const char* val,
unsigned int* pr);
unsigned int
get_timestamp_precision(const char* val);
+int
+process_odbc_interval(mvc *sql, itype interval, int val, sql_subtype *t, lng
*i);
#endif /*_SQL_DATETIME_H_*/
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -724,7 +724,7 @@ SQLCODE SQLERROR UNDER WHENEVER
%token X_BODY
%token MAX_MEMORY MAX_WORKERS OPTIMIZER
/* odbc tokens */
-%token DAYNAME MONTHNAME
+%token DAYNAME MONTHNAME TIMESTAMPADD TIMESTAMPDIFF
/* odbc data type tokens */
%token <sval>
SQL_BIGINT
@@ -775,7 +775,10 @@ SQLCODE SQLERROR UNDER WHENEVER
SQL_TSI_YEAR
%type <type>
- odbc_data_type
+ odbc_data_type
+
+%type <i_val>
+ odbc_tsi_qualifier
/* odbc escape prefix tokens */
%token <sval>
@@ -796,6 +799,7 @@ SQLCODE SQLERROR UNDER WHENEVER
odbc_scalar_func_escape
odbc_scalar_func
odbc_datetime_func
+
%%
sqlstmt:
@@ -5677,6 +5681,8 @@ non_reserved_word:
| ODBC_OJ_ESCAPE_PREFIX { $$ = sa_strdup(SA, "oj"); }
| DAYNAME { $$ = sa_strdup(SA, "dayname"); }
| MONTHNAME { $$ = sa_strdup(SA, "monthname"); }
+| TIMESTAMPADD { $$ = sa_strdup(SA, "timestampadd"); }
+| TIMESTAMPDIFF { $$ = sa_strdup(SA, "timestampdiff"); }
;
lngval:
@@ -6463,6 +6469,22 @@ odbc_datetime_func:
append_symbol(l, $3);
$$ = _symbol_create_list( SQL_UNOP, l );
}
+ | TIMESTAMPADD '(' odbc_tsi_qualifier ',' intval ',' search_condition ')'
+ { dlist *l = L();
+ // TODO sql_add or custom func ?
+ append_list( l, append_string(L(), sa_strdup(SA, "sql_add")));
+ append_int(l, FALSE); /* ignore distinct */
+ sql_subtype t;
+ lng i = 0;
+ if (process_odbc_interval(m, $3, $5, &t, &i) < 0) {
+ yyerror(m, "incorrect interval");
+ $$ = NULL;
+ YYABORT;
+ }
+ append_symbol(l, _newAtomNode(atom_int(SA, &t, i)));
+ append_symbol(l, $7);
+ $$ = _symbol_create_list( SQL_BINOP, l );
+ }
;
@@ -6579,6 +6601,30 @@ odbc_data_type:
{ sql_find_subtype(&$$, "clob", 0, 0); }
;
+odbc_tsi_qualifier:
+ SQL_TSI_FRAC_SECOND
+ { $$ = insec; }
+ | SQL_TSI_SECOND
+ { $$ = isec; }
+ | SQL_TSI_MINUTE
+ { $$ = imin; }
+ | SQL_TSI_HOUR
+ { $$ = ihour; }
+ | SQL_TSI_DAY
+ { $$ = iday; }
+ | SQL_TSI_WEEK
+ { $$ = iweek; }
+ | SQL_TSI_MONTH
+ { $$ = imonth; }
+ | SQL_TSI_QUARTER
+ { $$ = iquarter; }
+ | SQL_TSI_YEAR
+ { $$ = iyear; }
+
+;
+
+
+
%%
diff --git a/sql/server/sql_scan.c b/sql/server/sql_scan.c
--- a/sql/server/sql_scan.c
+++ b/sql/server/sql_scan.c
@@ -529,6 +529,8 @@ scanner_init_keywords(void)
failed += keywords_insert("oj", ODBC_OJ_ESCAPE_PREFIX);
failed += keywords_insert("DAYNAME", DAYNAME);
failed += keywords_insert("MONTHNAME", MONTHNAME);
+ failed += keywords_insert("TIMESTAMPADD", TIMESTAMPADD);
+ failed += keywords_insert("TIMESTAMPDIFF", TIMESTAMPDIFF);
failed += keywords_insert("SQL_BIGINT", SQL_BIGINT);
failed += keywords_insert("SQL_BINARY", SQL_BINARY);
failed += keywords_insert("SQL_BIT", SQL_BIT);
@@ -566,6 +568,15 @@ scanner_init_keywords(void)
failed += keywords_insert("SQL_WCHAR", SQL_WCHAR);
failed += keywords_insert("SQL_WLONGVARCHAR", SQL_WLONGVARCHAR);
failed += keywords_insert("SQL_WVARCHAR", SQL_WVARCHAR);
+ failed += keywords_insert("SQL_TSI_FRAC_SECOND", SQL_TSI_FRAC_SECOND);
+ failed += keywords_insert("SQL_TSI_SECOND", SQL_TSI_SECOND);
+ failed += keywords_insert("SQL_TSI_MINUTE", SQL_TSI_MINUTE);
+ failed += keywords_insert("SQL_TSI_HOUR", SQL_TSI_HOUR);
+ failed += keywords_insert("SQL_TSI_DAY", SQL_TSI_DAY);
+ failed += keywords_insert("SQL_TSI_WEEK", SQL_TSI_WEEK);
+ failed += keywords_insert("SQL_TSI_MONTH", SQL_TSI_MONTH);
+ failed += keywords_insert("SQL_TSI_QUARTER", SQL_TSI_QUARTER);
+ failed += keywords_insert("SQL_TSI_YEAR", SQL_TSI_YEAR);
return failed;
}
diff --git
a/sql/test/odbc-escape-sequences/Tests/time-date-interval-functions.test
b/sql/test/odbc-escape-sequences/Tests/time-date-interval-functions.test
--- a/sql/test/odbc-escape-sequences/Tests/time-date-interval-functions.test
+++ b/sql/test/odbc-escape-sequences/Tests/time-date-interval-functions.test
@@ -101,3 +101,8 @@ query I rowsort
select { fn year(date'2022-11-14') }
----
2022
+
+query T rowsort
+select { fn timestampadd(SQL_TSI_HOUR, 1, timestamp'2022-11-14 12:12:12') }
+----
+2022-11-14 13:12:12
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]