Changeset: 5686c027f964 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/5686c027f964
Added Files:
        sql/backends/monet5/copy_convert_num.h
Modified Files:
        sql/backends/monet5/CMakeLists.txt
        sql/backends/monet5/copy.c
        sql/backends/monet5/copy.h
        sql/backends/monet5/copy_convert.c
        sql/backends/monet5/rel_copy.c
Branch: copyparpipe
Log Message:

It works a little bit for int decimals


diffs (287 lines):

diff --git a/sql/backends/monet5/CMakeLists.txt 
b/sql/backends/monet5/CMakeLists.txt
--- a/sql/backends/monet5/CMakeLists.txt
+++ b/sql/backends/monet5/CMakeLists.txt
@@ -158,7 +158,7 @@ target_sources(sql
   for.c for.h
   dict.c dict.h
   copy.c copy.h
-  copy_convert.c
+  copy_convert.c copy_convert_num.h
   ${MONETDB_CURRENT_SQL_SOURCES}
   PUBLIC
   ${sql_public_headers})
diff --git a/sql/backends/monet5/copy.c b/sql/backends/monet5/copy.c
--- a/sql/backends/monet5/copy.c
+++ b/sql/backends/monet5/copy.c
@@ -772,6 +772,30 @@ end:
        return msg;
 }
 
+
+
+void
+copy_report_error(struct error_handling *restrict admin, int rel_row, _In_z_ 
_Printf_format_string_ const char *restrict format, ...)
+{
+       admin->count++;
+       if (admin->rel_row >= 0)
+               return;
+
+       admin->rel_row = rel_row;
+
+       char *buf = admin->message;
+       size_t buf_size = sizeof(admin->message);
+       va_list ap;
+       va_start(ap, format);
+       int ret = vsnprintf(buf, buf_size, format, ap);
+       va_end(ap);
+       if (ret < 0) {
+               snprintf(buf, buf_size, "an error [%d] occurred during error 
reporting", ret);
+       }
+}
+
+
+
 static str
 COPYpair_assign(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
 {
@@ -917,11 +941,16 @@ static mel_func copy_init_funcs[] = {
        batarg("block", bte), arg("linecount", lng), arg("col_sep", str), 
arg("line_sep", str), arg("quote", str), arg("null_repr", str), arg("escape", 
bit)
  )),
 
- pattern("copy", "parse_generic", COPYparse_generic, false, "Parse as an 
integer", args(1, 4,
+ pattern("copy", "parse_generic", COPYparse_generic, false, "Parse using GDK's 
atomFromStr", args(1, 4,
        batargany("", 1),
        batarg("block", bte), batarg("offsets", int), argany("type", 1)
  )),
 
+ command("copy", "parse_decimal", COPYparse_decimal_int, false, "Parse as a 
decimal", args(1, 6,
+        batarg("", int),
+        batarg("block", bte), batarg("offsets", int), arg("digits", int), 
arg("scale", int), arg("type", int)
+ )),
+
  command("copy", "set_blocksize", COPYset_blocksize, true, "set the COPY block 
size", args(1, 2,
        arg("blocksize", int)
  )),
diff --git a/sql/backends/monet5/copy.h b/sql/backends/monet5/copy.h
--- a/sql/backends/monet5/copy.h
+++ b/sql/backends/monet5/copy.h
@@ -17,7 +17,25 @@
                goto end; \
        } while (0)
 
+
+struct error_handling {
+       int rel_row;
+       int count;
+       char message[512];
+};
+
+void copy_report_error(struct error_handling *restrict admin, int rel_row, 
_In_z_ _Printf_format_string_ const char *restrict format, ...)
+       __attribute__((__format__(__printf__, 3, 4)));
+
+typedef str (*bulk_converter)(struct error_handling*, void *parms, int count, 
void *dest, char *data, int *offsets);
+
+str parse_fixed_width_column(bat *ret, const char *fname, bat block_bat_id, 
bat offsets_bat_id, int tpe, bulk_converter f, void *parms);
+
+
 extern str COPYparse_generic(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci);
 
 
+extern str COPYparse_decimal_int(bat *parsed_bat_id, bat *block_bat_id, bat 
*offsets_bat_id, int *digits_p, int *scale_p, int *dummy);
+
+
 #endif /*_COPY_H_*/
diff --git a/sql/backends/monet5/copy_convert.c 
b/sql/backends/monet5/copy_convert.c
--- a/sql/backends/monet5/copy_convert.c
+++ b/sql/backends/monet5/copy_convert.c
@@ -15,6 +15,7 @@
 
 #include "copy.h"
 
+#define INSIDE_COPY_CONVERT 1
 
 str
 COPYparse_generic(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
@@ -78,3 +79,57 @@ end:
                BBPunfix(indices->batCacheid);
        return msg;
 }
+
+str
+parse_fixed_width_column(
+       bat *ret,
+       const char *fname,
+       bat block_bat_id, bat offsets_bat_id,
+       int tpe,
+       str (*f)(struct error_handling*, void*, int, void*, char*, int*),
+       void *fx)
+{
+       str msg = MAL_SUCCEED;
+       BAT *block_bat;
+       BAT *offsets_bat;
+       BAT *parsed_bat;
+       struct error_handling errors = {
+               .rel_row = -1,
+       };
+
+       block_bat = BATdescriptor(block_bat_id);
+       offsets_bat = BATdescriptor(offsets_bat_id);
+       if (!block_bat || !offsets_bat)
+               bailout(fname, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
+
+       parsed_bat = COLnew(0, tpe, BATcount(offsets_bat), TRANSIENT);
+       if (!parsed_bat)
+               bailout(fname, SQLSTATE(HY013) MAL_MALLOC_FAIL);
+
+       msg = f(&errors, fx, BATcount(offsets_bat), Tloc(parsed_bat, 0), 
Tloc(block_bat, 0), Tloc(offsets_bat, 0));
+       if (msg != MAL_SUCCEED)
+               goto end;
+
+       BATsetcount(parsed_bat, BATcount(offsets_bat));
+
+       if (errors.count > 0)
+               bailout(fname, "At least %d conversion errors, example: %s", 
errors.count, errors.message);
+
+end:
+       if (parsed_bat) {
+               if (msg == MAL_SUCCEED) {
+                       *ret = parsed_bat->batCacheid;
+                       BBPkeepref(parsed_bat->batCacheid);
+               } else {
+                       BBPunfix(parsed_bat->batCacheid);
+               }
+       }
+       if (block_bat)
+               BBPunfix(block_bat->batCacheid);
+       if (offsets_bat)
+               BBPunfix(offsets_bat->batCacheid);
+       return msg;
+}
+
+
+#include "copy_convert_num.h"
diff --git a/sql/backends/monet5/copy_convert_num.h 
b/sql/backends/monet5/copy_convert_num.h
new file mode 100644
--- /dev/null
+++ b/sql/backends/monet5/copy_convert_num.h
@@ -0,0 +1,109 @@
+
+#ifndef INSIDE_COPY_CONVERT
+
+#include "monetdb_config.h"
+#include "gdk.h"
+#include "mal.h"
+#include "mal_exception.h"
+#include "mal_interpreter.h"
+
+#include "copy.h"
+
+#endif
+
+#define TPE int
+#define STRINGIFY(S) #S
+#define GDK_TYPIFY(S) TYPE_##S
+#define TMPL_TYPE int;
+
+struct decimal_parms {
+       int digits;
+       int scale;
+};
+
+
+
+static int
+parse_one_decimal_int(struct error_handling *errors, struct decimal_parms 
*parms, int rel_row, const char *s)
+{
+       int digits = parms->digits;
+       int scale = parms->scale;
+       int integer_digits = digits - scale;
+       bool neg = false;
+       TPE res = 0;
+
+       while(isspace((unsigned char) *s))
+               s++;
+
+       if (*s == '-'){
+               neg = true;
+               s++;
+       } else if (*s == '+'){
+               s++;
+       }
+
+       for (int i = 0; *s && *s != '.' && ((res == 0 && *s == '0') || i < 
integer_digits); s++) {
+               if (!isdigit((unsigned char) *s))
+                       break;
+               res *= 10;
+               res += (*s - '0');
+               if (res)
+                       i++;
+       }
+       if (*s == '.') {
+               s++;
+               while (*s && isdigit((unsigned char) *s) && scale > 0) {
+                       res *= 10;
+                       res += *s++ - '0';
+                       scale--;
+               }
+       }
+       while(*s && isspace((unsigned char) *s))
+               s++;
+       while (scale > 0) {
+               res *= 10;
+               scale--;
+       }
+       if (*s) {
+               copy_report_error(errors, rel_row, "trailing garbage: %s", s);
+               res = int_nil;
+       }
+       if (neg)
+               res = -res;
+       return res;
+}
+
+
+
+static str
+parse_many_decimal_int(struct error_handling *errors, void *parms_, int count, 
void *dest_, char *data, int *offsets)
+{
+       struct decimal_parms *parms = parms_;
+       int *dest = dest_;
+
+       for (int i = 0; i < count; i++) {
+               int offset = offsets[i];
+               if (is_int_nil(offset)) {
+                       dest[i] = int_nil;
+                       continue;
+               }
+               dest[i] = parse_one_decimal_int(errors, parms, i, data + 
offset);
+       }
+
+       return MAL_SUCCEED;
+}
+
+
+str
+COPYparse_decimal_int(
+       bat *parsed_bat_id,
+       bat *block_bat_id, bat *offsets_bat_id,
+       int *digits, int *scale,
+       int *dummy)
+{
+       struct decimal_parms myparms = {
+               .digits = *digits,
+               .scale = *scale,
+       };
+       return parse_fixed_width_column(parsed_bat_id, 
"copy.parse_decimal_int", *block_bat_id, *offsets_bat_id, TYPE_int, 
parse_many_decimal_int, &myparms);
+}
diff --git a/sql/backends/monet5/rel_copy.c b/sql/backends/monet5/rel_copy.c
--- a/sql/backends/monet5/rel_copy.c
+++ b/sql/backends/monet5/rel_copy.c
@@ -304,6 +304,7 @@ rel2bin_copyparpipe(backend *be, sql_rel
                                q = pushArgument(mb, q, var_indices);
                                q = pushInt(mb, q, col->type.digits);
                                q = pushInt(mb, q, col->type.scale);
+                               q = pushNil(mb, q, col->type.type->localtype);
                                break;
                        default:
                                q = newStmt(mb, "copy", "parse_generic");
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to