Changeset: bab274540221 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/bab274540221
Modified Files:
        sql/backends/monet5/rel_bin.c
        sql/backends/monet5/sql.c
        sql/backends/monet5/sql_bincopyconvert.c
        sql/backends/monet5/sql_bincopyconvert.h
        sql/backends/monet5/sql_bincopyfrom.c
Branch: copyintobinary
Log Message:

Validate DECIMAL range in COPY BINARY INTO


diffs (truncated from 348 to 300 lines):

diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c
--- a/sql/backends/monet5/rel_bin.c
+++ b/sql/backends/monet5/rel_bin.c
@@ -1126,6 +1126,18 @@ emit_loadcolumn(backend *be, stmt *impor
        // For the time being we just use the name of the storage type as the 
method
        // name.
        const char *method = ATOMname(data_type);
+       int width;
+
+       switch (subtype->type->eclass) {
+               case EC_DEC:
+               case EC_STRING:
+                       width = subtype->digits;
+                       break;
+               default:
+                       width = 0;
+                       break;
+       }
+
 
        //  
arg("sname",str),arg("tname",str),arg("onclient",int),arg("bswap",bit)
        stmt *onclient_arg = importTable_args[2];
@@ -1139,6 +1151,7 @@ emit_loadcolumn(backend *be, stmt *impor
        p = pushReturn(mb, p, new_count_var);
        //
        p = pushStr(mb, p, method);
+       p = pushInt(mb, p, width);
        p = pushArgument(mb, p, bswap_arg->nr);
        p = pushArgument(mb, p, file_stmt->nr);
        p = pushArgument(mb, p, onclient_arg->nr);
diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c
--- a/sql/backends/monet5/sql.c
+++ b/sql/backends/monet5/sql.c
@@ -5195,7 +5195,7 @@ static mel_func sql_init_funcs[] = {
  pattern("sql", "copy_from", mvc_import_table_wrap, true, "Import a table from 
bstream s with the \ngiven tuple and seperators (sep/rsep)", args(1,13, 
batvarargany("",0),arg("t",ptr),arg("sep",str),arg("rsep",str),arg("ssep",str),arg("ns",str),arg("fname",str),arg("nr",lng),arg("offset",lng),arg("best",int),arg("fwf",str),arg("onclient",int),arg("escape",int))),
  //we use bat.single now
  //pattern("sql", "single", CMDBATsingle, false, "", args(1,2, 
batargany("",2),argany("x",2))),
- pattern("sql", "importColumn", mvc_bin_import_column_wrap, false, "Import a 
column from the given file", args(2, 7, batargany("", 0),arg("", oid), 
arg("method",str),arg("bswap",bit),arg("path",str),arg("onclient",int),arg("nrows",oid))),
+ pattern("sql", "importColumn", mvc_bin_import_column_wrap, false, "Import a 
column from the given file", args(2, 8, batargany("", 0),arg("", oid), 
arg("method",str),arg("width",int),arg("bswap",bit),arg("path",str),arg("onclient",int),arg("nrows",oid))),
  command("aggr", "not_unique", not_unique, false, "check if the tail sorted 
bat b doesn't have unique tail values", args(1,2, arg("",bit),batarg("b",oid))),
  command("sql", "optimizers", getPipeCatalog, false, "", args(3,3, 
batarg("",str),batarg("",str),batarg("",str))),
  pattern("sql", "optimizer_updates", SQLoptimizersUpdate, false, "", noargs),
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
@@ -17,8 +17,9 @@
 #include "mal_interpreter.h"
 
 static str
-validate_bit(void *dst_, void *src_, size_t count, bool byteswap)
+validate_bit(void *dst_, void *src_, size_t count, int width, bool byteswap)
 {
+       (void)width;
        (void)byteswap;
        unsigned char *dst = dst_;
        const unsigned char *src = src_;
@@ -31,55 +32,83 @@ validate_bit(void *dst_, void *src_, siz
        return MAL_SUCCEED;
 }
 
+#define VALIDATE_DECIMAL(TYP) do { \
+               if (width) { \
+                       TYP m = 1; \
+                       for (int i = 0; i < width; i++) \
+                               m *= 10; \
+                       dst = dst_; \
+                       for (size_t i = 0; i < count; i++) { \
+                               if (dst[i] >= m || dst[i] <= -m) \
+                                       throw(SQL, "convert", SQLSTATE(22003) 
"decimal out of range"); \
+                       } \
+               } \
+    } while (0)
+
+
 static str
-byteswap_sht(void *dst_, void *src_, size_t count, bool byteswap)
+byteswap_sht(void *dst_, void *src_, size_t count, int width, bool byteswap)
 {
        assert(byteswap); (void)byteswap; // otherwise, why call us?
        sht *dst = dst_;
        const sht *src = src_;
        for (size_t i = 0; i < count; i++)
                *dst++ = copy_binary_byteswap16(*src++);
+
+       VALIDATE_DECIMAL(sht);
+
        return MAL_SUCCEED;
 }
 
 static str
-byteswap_int(void *dst_, void *src_, size_t count, bool byteswap)
+byteswap_int(void *dst_, void *src_, size_t count, int width, bool byteswap)
 {
        assert(byteswap); (void)byteswap; // otherwise, why call us?
        int *dst = dst_;
        const int *src = src_;
        for (size_t i = 0; i < count; i++)
                *dst++ = copy_binary_byteswap32(*src++);
+
+       VALIDATE_DECIMAL(int);
+
        return MAL_SUCCEED;
 }
 
 static str
-byteswap_lng(void *dst_, void *src_, size_t count, bool byteswap)
+byteswap_lng(void *dst_, void *src_, size_t count, int width, bool byteswap)
 {
        assert(byteswap); (void)byteswap; // otherwise, why call us?
        lng *dst = dst_;
        const lng *src = src_;
        for (size_t i = 0; i < count; i++)
                *dst++ = copy_binary_byteswap64(*src++);
+
+       VALIDATE_DECIMAL(lng);
+
        return MAL_SUCCEED;
 }
 
 #ifdef HAVE_HGE
 static str
-byteswap_hge(void *dst_, void *src_, size_t count, bool byteswap)
+byteswap_hge(void *dst_, void *src_, size_t count, int width, bool byteswap)
 {
        assert(byteswap); (void)byteswap; // otherwise, why call us?
        hge *dst = dst_;
        const hge *src = src_;
        for (size_t i = 0; i < count; i++)
                *dst++ = copy_binary_byteswap128(*src++);
+
+       VALIDATE_DECIMAL(hge);
+
        return MAL_SUCCEED;
 }
 #endif
 
 static str
-byteswap_flt(void *dst_, void *src_, size_t count, bool byteswap)
+byteswap_flt(void *dst_, void *src_, size_t count, int width, bool byteswap)
 {
+       (void)width;
+
        // Verify that size and alignment requirements of flt do not exceed int
        assert(sizeof(uint32_t) == sizeof(flt));
        assert(sizeof(struct { char dummy; uint32_t ui; }) >= sizeof(struct { 
char dummy; flt f; }));
@@ -93,8 +122,10 @@ byteswap_flt(void *dst_, void *src_, siz
 }
 
 static str
-byteswap_dbl(void *dst_, void *src_, size_t count, bool byteswap)
+byteswap_dbl(void *dst_, void *src_, size_t count, int width, bool byteswap)
 {
+       (void)width;
+
        // Verify that size and alignment requirements of dbl do not exceed lng
        assert(sizeof(uint64_t) == sizeof(dbl));
        assert(sizeof(struct { char dummy; uint64_t ui; }) >= sizeof(struct { 
char dummy; dbl f; }));
@@ -109,8 +140,10 @@ byteswap_dbl(void *dst_, void *src_, siz
 
 
 static str
-decode_date(void *dst_, void *src_, size_t count, bool byteswap)
+decode_date(void *dst_, void *src_, size_t count, int width, bool byteswap)
 {
+       (void)width;
+
        date *dst = dst_;
        copy_binary_date *src = src_;
 
@@ -127,8 +160,9 @@ decode_date(void *dst_, void *src_, size
 }
 
 static str
-encode_date(void *dst_, void *src_, size_t count, bool byteswap)
+encode_date(void *dst_, void *src_, size_t count, int width, bool byteswap)
 {
+       (void)width;
        copy_binary_date *dst = dst_;
        date *src = src_;
        for (size_t i = 0; i < count; i++) {
@@ -146,8 +180,10 @@ encode_date(void *dst_, void *src_, size
 }
 
 static str
-decode_time(void *dst_, void *src_, size_t count, bool byteswap)
+decode_time(void *dst_, void *src_, size_t count, int width, bool byteswap)
 {
+       (void)width;
+
        daytime *dst = dst_;
        copy_binary_time *src = src_;
 
@@ -164,8 +200,9 @@ decode_time(void *dst_, void *src_, size
 }
 
 static str
-encode_time(void *dst_, void *src_, size_t count, bool byteswap)
+encode_time(void *dst_, void *src_, size_t count, int width, bool byteswap)
 {
+       (void)width;
        copy_binary_time *dst = dst_;
        daytime *src = src_;
        for (size_t i = 0; i < count; i++) {
@@ -184,8 +221,10 @@ encode_time(void *dst_, void *src_, size
 }
 
 static str
-decode_timestamp(void *dst_, void *src_, size_t count, bool byteswap)
+decode_timestamp(void *dst_, void *src_, size_t count, int width, bool 
byteswap)
 {
+       (void)width;
+
        timestamp *dst = dst_;
        copy_binary_timestamp *src = src_;
 
@@ -205,8 +244,10 @@ decode_timestamp(void *dst_, void *src_,
 
 
 static str
-encode_timestamp(void *dst_, void *src_, size_t count, bool byteswap)
+encode_timestamp(void *dst_, void *src_, size_t count, int width, bool 
byteswap)
 {
+       (void)width;
+
        copy_binary_timestamp *dst = dst_;
        timestamp *src = src_;
        for (size_t i = 0; i < count; i++) {
@@ -289,8 +330,9 @@ bad_utf8:
 // Load items from the stream and put them in the BAT.
 // Because it's text read from a binary stream, we replace \r\n with \n.
 static str
-load_zero_terminated_text(BAT *bat, stream *s, int *eof_reached, bool byteswap)
+load_zero_terminated_text(BAT *bat, stream *s, int *eof_reached, int width, 
bool byteswap)
 {
+       (void)width;
        (void)byteswap;
        const char *mal_operator = "sql.importColumn";
        str msg = MAL_SUCCEED;
diff --git a/sql/backends/monet5/sql_bincopyconvert.h 
b/sql/backends/monet5/sql_bincopyconvert.h
--- a/sql/backends/monet5/sql_bincopyconvert.h
+++ b/sql/backends/monet5/sql_bincopyconvert.h
@@ -35,10 +35,10 @@
 //    the stream and the BAT and does everything necessary to load the data 
into
 //    the BAT.
 
-typedef str (*bincopy_decoder_t)(void *dst,void *src, size_t count, bool 
byteswap);
-typedef str (*bincopy_loader_t)(BAT *bat, stream *s, int *eof_reached, bool 
byteswap);
+typedef str (*bincopy_decoder_t)(void *dst,void *src, size_t count, int width, 
bool byteswap);
+typedef str (*bincopy_loader_t)(BAT *bat, stream *s, int *eof_reached, int 
width, bool byteswap);
 
-typedef str (*bincopy_encoder_t)(void *dst, void *src, size_t count, bool 
byteswap);
+typedef str (*bincopy_encoder_t)(void *dst, void *src, size_t count, int 
width, bool byteswap);
 typedef str (*bincopy_dumper_t)(BAT *bat, stream *s, bool byteswap);
 
 struct type_record_t {
diff --git a/sql/backends/monet5/sql_bincopyfrom.c 
b/sql/backends/monet5/sql_bincopyfrom.c
--- a/sql/backends/monet5/sql_bincopyfrom.c
+++ b/sql/backends/monet5/sql_bincopyfrom.c
@@ -94,7 +94,7 @@ end:
 }
 
 static str
-load_fixed_width(BAT *bat, stream *s, bool byteswap, bincopy_decoder_t 
convert, size_t record_size, int *eof_reached)
+load_fixed_width(BAT *bat, stream *s, int width, bool byteswap, 
bincopy_decoder_t convert, size_t record_size, int *eof_reached)
 {
        const char *mal_operator = "sql.importColumn";
        str msg = MAL_SUCCEED;
@@ -129,7 +129,7 @@ load_fixed_width(BAT *bat, stream *s, bo
                if (BATextend(bat, newCount) != GDK_SUCCEED)
                        bailout("%s", GDK_EXCEPTION);
 
-               msg = convert(Tloc(bat, count), &bs->buf[bs->pos], n, byteswap);
+               msg = convert(Tloc(bat, count), &bs->buf[bs->pos], n, width, 
byteswap);
                if (msg != MAL_SUCCEED)
                        goto end;
                BATsetcount(bat, newCount);
@@ -161,7 +161,7 @@ end:
 
 
 static str
-load_column(type_record_t *rec, const char *name, BAT *bat, stream *s, bool 
byteswap, BUN rows_estimate, int *eof_reached)
+load_column(type_record_t *rec, const char *name, BAT *bat, stream *s, int 
width, bool byteswap, BUN rows_estimate, int *eof_reached)
 {
        const char *mal_operator = "sql.importColumn";
        BUN orig_count, new_count;
@@ -181,9 +181,9 @@ load_column(type_record_t *rec, const ch
        orig_count = BATcount(bat);
 
        if (loader) {
-               msg = loader(bat, s, eof_reached, byteswap);
+               msg = loader(bat, s, eof_reached, width, byteswap);
        } else if (decoder) {
-               msg = load_fixed_width(bat, s, byteswap, rec->decoder, 
rec->record_size, eof_reached);
+               msg = load_fixed_width(bat, s, width, byteswap, rec->decoder, 
rec->record_size, eof_reached);
                // load the bytes directly into the bat, as-is
        } else {
                msg = load_trivial(bat, s, rows_estimate, eof_reached);
@@ -205,7 +205,7 @@ load_column(type_record_t *rec, const ch
 /* Import a single file into a new BAT.
  */
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to