Changeset: d8c138d5a49c for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=d8c138d5a49c
Modified Files:
        sql/server/sql_atom.c
        sql/server/sql_atom.h
        sql/server/sql_semantic.c
        sql/test/SQLancer/Tests/sqlancer03.sql
        sql/test/SQLancer/Tests/sqlancer03.stable.out
Branch: Jun2020
Log Message:

Making SQLancer happy, handle time related types at atom2sql


diffs (233 lines):

diff --git a/sql/server/sql_atom.c b/sql/server/sql_atom.c
--- a/sql/server/sql_atom.c
+++ b/sql/server/sql_atom.c
@@ -429,7 +429,7 @@ atom2string(sql_allocator *sa, atom *a)
 }
 
 char *
-atom2sql(atom *a)
+atom2sql(atom *a, int timezone)
 {
        sql_class ec = a->tpe.type->eclass;
        char buf[BUFSIZ];
@@ -567,26 +567,110 @@ atom2sql(atom *a)
                        sprintf(buf, "%f", a->data.val.fval);
                break;
        case EC_TIME:
+       case EC_TIME_TZ:
        case EC_DATE:
        case EC_TIMESTAMP:
-               if (a->data.vtype == TYPE_str) {
-                       char *val1 = sql_escape_str(a->tpe.type->sqlname), 
*val2 = sql_escape_str(a->data.val.sval), *res;
+       case EC_TIMESTAMP_TZ: {
+               char val1[64], sbuf[64], *val2 = sbuf, *res;
+               size_t len = sizeof(sbuf);
 
-                       if (!val1 || !val2) {
-                               c_delete(val1);
-                               c_delete(val2);
-                               return NULL;
+               switch (ec) {
+               case EC_TIME:
+               case EC_TIME_TZ: {
+                       char *n = stpcpy(val1, "TIME");
+                       if (a->tpe.digits) {
+                               char str[16];
+                               sprintf(str, "%u", a->tpe.digits);
+                               n = stpcpy(stpcpy(stpcpy(n, " ("), str), ")");
+                       }
+                       if (ec == EC_TIME_TZ)
+                               stpcpy(n, " WITH TIME ZONE");
+               } break;
+               case EC_DATE:
+                       strcpy(val1, "DATE");
+               break;
+               case EC_TIMESTAMP:
+               case EC_TIMESTAMP_TZ: {
+                       char *n = stpcpy(val1, "TIMESTAMP");
+                       if (a->tpe.digits) {
+                               char str[16];
+                               sprintf(str, "%u", a->tpe.digits);
+                               n = stpcpy(stpcpy(stpcpy(n, " ("), str), ")");
                        }
+                       if (ec == EC_TIME_TZ)
+                               stpcpy(n, " WITH TIME ZONE");
+               } break;
+               default:
+                       assert(0);
+               }
+
+               switch (ec) {
+               case EC_TIME:
+               case EC_TIME_TZ: {
+                       daytime dt = a->data.val.lval;
+                       int digits = a->tpe.digits ? a->tpe.digits - 1 : 0;
+                       char *s = val2;
+                       ssize_t lens;
+
+                       if (ec == EC_TIME_TZ)
+                               dt = daytime_add_usec_modulo(dt, timezone * 
1000);
+                       if ((lens = daytime_precision_tostr(&s, &len, dt, 
digits, true)) < 0)
+                               assert(0);
+
+                       if (ec == EC_TIME_TZ) {
+                               lng timezone_hours = llabs(timezone / 60000);
+                               char *end = sbuf + sizeof(sbuf) - 1;
 
-                       if ((res = NEW_ARRAY(char, strlen(val1) + strlen(val2) 
+ 4)))
-                               stpcpy(stpcpy(stpcpy(stpcpy(res, val1)," '"), 
val2), "'");
-                       c_delete(val1);
-                       c_delete(val2);
-                       return res;
-               } else {
-                       snprintf(buf, BUFSIZ, "atom2sql(TYPE_%d) not 
implemented", a->data.vtype);
+                               s += lens;
+                               snprintf(s, end - s, "%c%02d:%02d", (timezone 
>= 0) ? '+' : '-', (int) (timezone_hours / 60), (int) (timezone_hours % 60));
+                       }
+               } break;
+               case EC_DATE: {
+                       date dt = a->data.val.ival;
+                       if (date_tostr(&val2, &len, &dt, false) < 0)
+                               assert(0);
+               } break;
+               case EC_TIMESTAMP:
+               case EC_TIMESTAMP_TZ: {
+                       timestamp ts = a->data.val.lval;
+                       int digits = a->tpe.digits ? a->tpe.digits - 1 : 0;
+                       char *s = val2;
+                       size_t nlen;
+                       ssize_t lens;
+                       date days;
+                       daytime usecs;
+
+                       if (ec == EC_TIMESTAMP_TZ)
+                               ts = timestamp_add_usec(ts, timezone * 1000);
+                       days = timestamp_date(ts);
+                       if ((lens = date_tostr(&s, &len, &days, true)) < 0)
+                               assert(0);
+
+                       s += lens;
+                       *s++ = ' ';
+                       nlen = len - lens - 1;
+                       assert(nlen < len);
+
+                       usecs = timestamp_daytime(ts);
+                       if ((lens = daytime_precision_tostr(&s, &nlen, usecs, 
digits, true)) < 0)
+                               assert(0);
+
+                       if (ec == EC_TIMESTAMP_TZ) {
+                               lng timezone_hours = llabs(timezone / 60000);
+                               char *end = sbuf + sizeof(sbuf) - 1;
+
+                               s += lens;
+                               snprintf(s, end - s, "%c%02d:%02d", (timezone 
>= 0) ? '+' : '-', (int) (timezone_hours / 60), (int) (timezone_hours % 60));
+                       }
+               } break;
+               default:
+                       assert(0);
                }
-               break;
+
+               if ((res = NEW_ARRAY(char, strlen(val1) + strlen(val2) + 4)))
+                       stpcpy(stpcpy(stpcpy(stpcpy(res, val1)," '"), val2), 
"'");
+               return res;
+       } break;
        default:
                snprintf(buf, BUFSIZ, "atom2sql(TYPE_%d) not implemented", 
a->data.vtype);
        }
diff --git a/sql/server/sql_atom.h b/sql/server/sql_atom.h
--- a/sql/server/sql_atom.h
+++ b/sql/server/sql_atom.h
@@ -49,7 +49,7 @@ extern atom *atom_dup( sql_allocator *sa
 extern int atom_cast(sql_allocator *sa, atom *a, sql_subtype *tp);
 
 extern char *atom2string(sql_allocator *sa, atom *a);
-extern char *atom2sql(atom *a);
+extern char *atom2sql(atom *a, int timezone);
 extern sql_subtype *atom_type(atom *a);
 extern void atom_set_type(atom *a, sql_subtype *t);
 
diff --git a/sql/server/sql_semantic.c b/sql/server/sql_semantic.c
--- a/sql/server/sql_semantic.c
+++ b/sql/server/sql_semantic.c
@@ -412,7 +412,7 @@ symbol2string(mvc *sql, symbol *se, int 
        case SQL_ATOM:{
                AtomNode *an = (AtomNode *) se;
                if (an && an->a)
-                       return atom2sql(an->a);
+                       return atom2sql(an->a, sql->timezone);
                else
                        return _STRDUP("NULL");
        }
@@ -434,7 +434,7 @@ symbol2string(mvc *sql, symbol *se, int 
                assert(l->h->type != type_lng);
                if (dlist_length(l) == 1 && l->h->type == type_int) {
                        atom *a = sql_bind_arg(sql, l->h->data.i_val);
-                       return atom2sql(a);
+                       return atom2sql(a, sql->timezone);
                } else if (expression && dlist_length(l) == 1 && l->h->type == 
type_string) {
                        /* when compiling an expression, a column of a table 
might be present in the symbol, so we need this case */
                        const char *op = l->h->data.sval;
diff --git a/sql/test/SQLancer/Tests/sqlancer03.sql 
b/sql/test/SQLancer/Tests/sqlancer03.sql
--- a/sql/test/SQLancer/Tests/sqlancer03.sql
+++ b/sql/test/SQLancer/Tests/sqlancer03.sql
@@ -153,6 +153,13 @@ SELECT 1 FROM t0 WHERE NULL IN (DATE '19
 SELECT ALL DATE '1970-01-01', CAST(COUNT(ALL TIMESTAMP '1970-01-01 01:06:52') 
AS INT) FROM t0 WHERE (NULL) NOT IN (DATE '1970-01-01') GROUP BY ((CAST(0.6 AS 
STRING))||(0.75)), INTERVAL '-13' SECOND;
 ROLLBACK;
 
+START TRANSACTION;
+create table t0 (a time default time '10:15:32', b date default date 
'2010-01-31', c timestamp default timestamp '1980-11-04 08:49:25');
+insert into t0;
+insert into t0 values (default, default, default);
+select a,b,c from t0;
+ROLLBACK;
+
 START TRANSACTION; -- Bug 6924
 CREATE TABLE "sys"."t0" ("a" INTEGER, "b" INTEGER NOT NULL, CONSTRAINT 
"t0_a_b_unique" UNIQUE ("a","b"));
 --This copy into must succeed 
diff --git a/sql/test/SQLancer/Tests/sqlancer03.stable.out 
b/sql/test/SQLancer/Tests/sqlancer03.stable.out
--- a/sql/test/SQLancer/Tests/sqlancer03.stable.out
+++ b/sql/test/SQLancer/Tests/sqlancer03.stable.out
@@ -43,8 +43,8 @@ stdout of test 'sqlancer03` in directory
 #CREATE TABLE "sys"."t0" ("c0" BOOLEAN NOT NULL,"c1" BIGINT,CONSTRAINT 
"t0_c0_pkey" PRIMARY KEY ("c0"),CONSTRAINT "t0_c0_unique" UNIQUE ("c0"));
 #create view v0(c0, c1, c2) as (select all 2.020551048E9, 0.16688174, 
0.3732000026221729 from t0 where t0.c0) with check option;
 #SELECT sql_min(sql_max(NULL, ''), '') FROM v0 LEFT OUTER JOIN t0 ON true;
-% .%12 # table_name
-% %12 # name
+% .%14 # table_name
+% %14 # name
 % char # type
 % 0 # length
 #SELECT sql_min(sql_max(NULL, ''), '');
@@ -55,8 +55,8 @@ stdout of test 'sqlancer03` in directory
 [ NULL ]
 #SELECT ALL length(upper(MIN(ALL CAST(((trim(CAST(r'' AS STRING(659)), 
CAST(r'o3%+i]抔DCöf▟nßOpNbybಜ7' AS STRING)))||(sql_min(sql_max(NULL, r''), 
splitpart(r'x', r',7+.', t0.c1)))) AS STRING(151))))), 0.4179268710155164 
 #FROM v0 LEFT OUTER JOIN t0 ON NOT (t0.c0) WHERE t0.c0 GROUP BY 0.3584962, 
CAST(t0.c1 AS STRING(601)), t0.c1;
-% .%24,        .%25 # table_name
-% %24, %25 # name
+% .%31,        .%32 # table_name
+% %31, %32 # name
 % int, decimal # type
 % 1,   19 # length
 #ROLLBACK;
@@ -258,6 +258,20 @@ stdout of test 'sqlancer03` in directory
 % date,        int # type
 % 10,  1 # length
 #ROLLBACK;
+#START TRANSACTION;
+#create table t0 (a time default time '10:15:32', b date default date 
'2010-01-31', c timestamp default timestamp '1980-11-04 08:49:25');
+#insert into t0;
+[ 1    ]
+#insert into t0 values (default, default, default);
+[ 1    ]
+#select a,b,c from t0;
+% sys.t0,      sys.t0, sys.t0 # table_name
+% a,   b,      c # name
+% time,        date,   timestamp # type
+% 8,   10,     26 # length
+[ 10:15:32,    2010-01-31,     1980-11-04 08:49:25.000000      ]
+[ 10:15:32,    2010-01-31,     1980-11-04 08:49:25.000000      ]
+#ROLLBACK;
 #START TRANSACTION; -- Bug 6924
 #CREATE TABLE "sys"."t0" ("a" INTEGER, "b" INTEGER NOT NULL, CONSTRAINT 
"t0_a_b_unique" UNIQUE ("a","b"));
 #COPY 39 RECORDS INTO "sys"."t0" FROM stdin USING DELIMITERS E'\t',E'\n','"';
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to