Changeset: 465855d332d1 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/465855d332d1
Modified Files:
clients/examples/C/bincopytemporaldata.c
sql/backends/monet5/sql_bincopyconvert.c
sql/test/bincopy/Tests/bincopy_support.py
Branch: binresultset
Log Message:
When writing binary temporals, use a specific null representation
The spec says every invalid date and time is treated as null. This is
fine when reading but if other applications want to read binary data we
produce it's nice if they can count on a specific encoding.
diffs (196 lines):
diff --git a/clients/examples/C/bincopytemporaldata.c
b/clients/examples/C/bincopytemporaldata.c
--- a/clients/examples/C/bincopytemporaldata.c
+++ b/clients/examples/C/bincopytemporaldata.c
@@ -10,11 +10,32 @@
#include "bincopydata.h"
+static const copy_binary_timestamp binary_nil_timestamp = {
+ .time = {
+ .ms = 0xFFFFFFFF,
+ .seconds = 255,
+ .minutes = 255,
+ .hours = 255,
+ .padding = 255,
+ },
+ .date = {
+ .day = 255,
+ .month = 255,
+ .year =-1,
+ },
+};
+
static copy_binary_timestamp
random_timestamp(struct rng *rng)
{
+ copy_binary_timestamp ts;
+ if (rng_next(rng) % 10 == 9) {
+ ts = binary_nil_timestamp;
+ return ts;
+ }
+
// the % trick gives a little skew but we don't care
- copy_binary_timestamp ts = {
+ ts = (copy_binary_timestamp){
.time = {
.ms = rng_next(rng) % 1000000,
.seconds = rng_next(rng) % 60, // 61 ??
@@ -62,7 +83,7 @@ gen_timestamps(FILE *f, bool byteswap, l
}
}
-#define GEN_TIMESTAMP_FIELD(name, fld) \
+#define GEN_TIMESTAMP_FIELD(name, typ, fld, nilvalue) \
void name \
(FILE *f, bool byteswap, long nrecs) \
{ \
@@ -70,20 +91,22 @@ gen_timestamps(FILE *f, bool byteswap, l
\
for (long i = 0; i < nrecs; i++) { \
copy_binary_timestamp ts = random_timestamp(&rng); \
+ typ *p = &ts.fld; \
+ typ tmp = ts.date.day == 255 ? nilvalue : *p; \
if (byteswap) { \
copy_binary_convert_timestamp(&ts); \
} \
- fwrite(&ts.fld, sizeof(ts.fld), 1, f); \
+ fwrite(&tmp, sizeof(tmp), 1, f); \
} \
}
-GEN_TIMESTAMP_FIELD(gen_timestamp_times, time)
-GEN_TIMESTAMP_FIELD(gen_timestamp_dates, date)
+GEN_TIMESTAMP_FIELD(gen_timestamp_times, copy_binary_time, time,
binary_nil_timestamp.time)
+GEN_TIMESTAMP_FIELD(gen_timestamp_dates, copy_binary_date, date,
binary_nil_timestamp.date)
-GEN_TIMESTAMP_FIELD(gen_timestamp_ms, time.ms)
-GEN_TIMESTAMP_FIELD(gen_timestamp_seconds, time.seconds)
-GEN_TIMESTAMP_FIELD(gen_timestamp_minutes, time.minutes)
-GEN_TIMESTAMP_FIELD(gen_timestamp_hours, time.hours)
-GEN_TIMESTAMP_FIELD(gen_timestamp_days, date.day)
-GEN_TIMESTAMP_FIELD(gen_timestamp_months, date.month)
-GEN_TIMESTAMP_FIELD(gen_timestamp_years, date.year)
+GEN_TIMESTAMP_FIELD(gen_timestamp_ms, uint32_t, time.ms, 0x80)
+GEN_TIMESTAMP_FIELD(gen_timestamp_seconds, uint8_t, time.seconds, 0x80)
+GEN_TIMESTAMP_FIELD(gen_timestamp_minutes, uint8_t, time.minutes, 0x80)
+GEN_TIMESTAMP_FIELD(gen_timestamp_hours, uint8_t, time.hours, 0x80)
+GEN_TIMESTAMP_FIELD(gen_timestamp_days, uint8_t, date.day, 0x80)
+GEN_TIMESTAMP_FIELD(gen_timestamp_months, uint8_t, date.month, 0x80)
+GEN_TIMESTAMP_FIELD(gen_timestamp_years, int16_t, date.year, -1)
diff --git a/sql/backends/monet5/sql_bincopyconvert.c
b/sql/backends/monet5/sql_bincopyconvert.c
--- a/sql/backends/monet5/sql_bincopyconvert.c
+++ b/sql/backends/monet5/sql_bincopyconvert.c
@@ -180,6 +180,14 @@ encode_date(void *dst_, void *src_, size
date *src = src_;
for (size_t i = 0; i < count; i++) {
date dt = *src++;
+ if (is_date_nil(dt)) {
+ *dst++ = (copy_binary_date){
+ .day = 0xFF,
+ .month = 0xFF,
+ .year = -1,
+ };
+ continue;
+ }
int16_t year = date_year(dt);
if (byteswap)
year = copy_binary_byteswap16(year);
@@ -220,6 +228,16 @@ encode_time(void *dst_, void *src_, size
daytime *src = src_;
for (size_t i = 0; i < count; i++) {
daytime tm = *src++;
+ if (is_daytime_nil(tm)) {
+ *dst++ = (copy_binary_time){
+ .ms = 0xFFFFFFFF,
+ .seconds = 0xFF,
+ .minutes = 0xFF,
+ .hours = 0xFF,
+ .padding = 0xFF,
+ };
+ continue;
+ }
uint32_t ms = daytime_usec(tm);
if (byteswap)
ms = copy_binary_byteswap32(ms);
@@ -265,6 +283,23 @@ encode_timestamp(void *dst_, void *src_,
timestamp *src = src_;
for (size_t i = 0; i < count; i++) {
timestamp value = *src++;
+ if (is_timestamp_nil(value)) {
+ *dst++ = (copy_binary_timestamp) {
+ .time = {
+ .ms = 0xFFFFFFFF,
+ .seconds = 0xFF,
+ .minutes = 0xFF,
+ .hours = 0xFF,
+ .padding = 0xFF,
+ },
+ .date = {
+ .day = 0xFF,
+ .month = 0xFF,
+ .year = -1,
+ }
+ };
+ continue;
+ }
date dt = timestamp_date(value);
daytime tm = timestamp_daytime(value);
int16_t year = date_year(dt);
diff --git a/sql/test/bincopy/Tests/bincopy_support.py
b/sql/test/bincopy/Tests/bincopy_support.py
--- a/sql/test/bincopy/Tests/bincopy_support.py
+++ b/sql/test/bincopy/Tests/bincopy_support.py
@@ -269,42 +269,42 @@ INTO BINARY
SELECT * FROM foo
- WHERE EXTRACT(YEAR FROM ts) <> "year"
+ WHERE COALESCE(EXTRACT(YEAR FROM ts), -1) <> COALESCE("year", -1)
LIMIT 4;
SELECT * FROM foo
- WHERE EXTRACT(MONTH FROM ts) <> "month"
+ WHERE COALESCE(EXTRACT(MONTH FROM ts), -1) <> COALESCE("month", -1)
LIMIT 4;
SELECT * FROM foo
- WHERE EXTRACT(DAY FROM ts) <> "day"
+ WHERE COALESCE(EXTRACT(DAY FROM ts), -1) <> COALESCE("day", -1)
LIMIT 4;
SELECT * FROM foo
- WHERE EXTRACT(HOUR FROM ts) <> "hour"
+ WHERE COALESCE(EXTRACT(HOUR FROM ts), -1) <> COALESCE("hour", -1)
LIMIT 4;
SELECT * FROM foo
- WHERE EXTRACT(MINUTE FROM ts) <> "minute"
+ WHERE COALESCE(EXTRACT(MINUTE FROM ts), -1) <> COALESCE("minute", -1)
LIMIT 4;
SELECT * FROM foo
- WHERE 1000000 * CAST(EXTRACT(SECOND FROM ts) AS DECIMAL(13,6)) <> 1000000
* "second" + ms
+ WHERE COALESCE(1000000 * CAST(EXTRACT(SECOND FROM ts) AS DECIMAL(13,6)),
-1) <> COALESCE(1000000 * "second" + ms, -1)
LIMIT 4;
SELECT * FROM foo
- WHERE EXTRACT(YEAR FROM dt) <> "year"
+ WHERE COALESCE(EXTRACT(YEAR FROM dt), -1) <> COALESCE("year", -1)
LIMIT 4;
SELECT * FROM foo
- WHERE EXTRACT(MONTH FROM dt) <> "month"
+ WHERE COALESCE(EXTRACT(MONTH FROM dt), -1) <> COALESCE("month", -1)
LIMIT 4;
SELECT * FROM foo
- WHERE EXTRACT(DAY FROM dt) <> "day"
+ WHERE COALESCE(EXTRACT(DAY FROM dt), -1) <> COALESCE("day", -1)
LIMIT 4;
SELECT * FROM foo
- WHERE EXTRACT(HOUR FROM tm) <> "hour"
+ WHERE COALESCE(EXTRACT(HOUR FROM tm), -1) <> COALESCE("hour", -1)
LIMIT 4;
SELECT * FROM foo
- WHERE EXTRACT(MINUTE FROM tm) <> "minute"
+ WHERE COALESCE(EXTRACT(MINUTE FROM tm), -1) <> COALESCE("minute", -1)
LIMIT 4;
SELECT * FROM foo
- WHERE 1000000 * CAST(EXTRACT(SECOND FROM tm) AS DECIMAL(13,6)) <> 1000000
* "second" + ms
+ WHERE COALESCE(1000000 * CAST(EXTRACT(SECOND FROM tm) AS DECIMAL(13,6)),
-1) <> COALESCE(1000000 * "second" + ms, -1)
LIMIT 4;
""", [])
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]