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