Changeset: 3d223c421ad9 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3d223c421ad9
Added Files:
        sql/backends/monet5/UDF/capi/Tests/capi02.sql
Modified Files:
        monetdb5/modules/atoms/mtime.c
        monetdb5/modules/atoms/mtime.h
        sql/backends/monet5/UDF/capi/Tests/All
        sql/backends/monet5/UDF/capi/Tests/capi00.sql
        sql/backends/monet5/UDF/capi/Tests/capi01.sql
        sql/backends/monet5/UDF/capi/capi.c
Branch: jitudf
Log Message:

Working dates, times and timestamps.


diffs (truncated from 882 to 300 lines):

diff --git a/monetdb5/modules/atoms/mtime.c b/monetdb5/modules/atoms/mtime.c
--- a/monetdb5/modules/atoms/mtime.c
+++ b/monetdb5/modules/atoms/mtime.c
@@ -3580,3 +3580,20 @@ MTIMEtimestamp_to_str(str *s, const time
        throw(MAL, "mtime.timestamp_to_str", "strftime support missing");
 #endif
 }
+
+
+date MTIMEtodate(int day, int month, int year) {
+       return todate(day, month, year);
+}
+
+void MTIMEfromdate(date n, int *d, int *m, int *y) {
+       fromdate(n, d, m, y);
+}
+
+daytime MTIMEtotime(int hour, int min, int sec, int msec) {
+       return totime(hour, min, sec, msec);
+}
+
+void MTIMEfromtime(daytime n, int *hour, int *min, int *sec, int *msec) {
+       fromtime(n, hour, min, sec, msec);
+}
diff --git a/monetdb5/modules/atoms/mtime.h b/monetdb5/modules/atoms/mtime.h
--- a/monetdb5/modules/atoms/mtime.h
+++ b/monetdb5/modules/atoms/mtime.h
@@ -264,4 +264,10 @@ mal_export int TYPE_timestamp;
 mal_export int TYPE_tzone;
 mal_export int TYPE_rule;
 
+mal_export date MTIMEtodate(int day, int month, int year);
+mal_export void MTIMEfromdate(date n, int *d, int *m, int *y);
+
+mal_export daytime MTIMEtotime(int hour, int min, int sec, int msec);
+mal_export void MTIMEfromtime(daytime n, int *hour, int *min, int *sec, int 
*msec);
+
 #endif /* _MONETTIME_H_ */
diff --git a/sql/backends/monet5/UDF/capi/Tests/All 
b/sql/backends/monet5/UDF/capi/Tests/All
--- a/sql/backends/monet5/UDF/capi/Tests/All
+++ b/sql/backends/monet5/UDF/capi/Tests/All
@@ -1,3 +1,4 @@
 
 capi00
 capi01
+capi02
diff --git a/sql/backends/monet5/UDF/capi/Tests/capi00.sql 
b/sql/backends/monet5/UDF/capi/Tests/capi00.sql
--- a/sql/backends/monet5/UDF/capi/Tests/capi00.sql
+++ b/sql/backends/monet5/UDF/capi/Tests/capi00.sql
@@ -3,11 +3,7 @@
 START TRANSACTION;
 
 CREATE FUNCTION capi00(inp INTEGER) RETURNS INTEGER LANGUAGE C {
-       result->count = inp.count;
-       result->data = __malloc(result->count * sizeof(result->null_value));
-       if (!result->data) {
-               return "Malloc failure!";
-       }
+       result->initialize(result, inp.count);
        for(size_t i = 0; i < inp.count; i++) {
                result->data[i] = inp.data[i] * 2;
        }
diff --git a/sql/backends/monet5/UDF/capi/Tests/capi01.sql 
b/sql/backends/monet5/UDF/capi/Tests/capi01.sql
--- a/sql/backends/monet5/UDF/capi/Tests/capi01.sql
+++ b/sql/backends/monet5/UDF/capi/Tests/capi01.sql
@@ -7,13 +7,8 @@ language C
 #include <math.h>
 
        size_t count = inp;
-       i->count = count;
-       i->data = __malloc(i->count * sizeof(i->null_value));
-       d->count = count;
-       d->data = __malloc(d->count * sizeof(d->null_value));
-       if (!i->data || !d->data) {
-               return "Malloc failure";
-       }
+       i->initialize(i, count);
+       d->initialize(d, count);
        for(size_t j = 0; j < count; j++) {
                i->data[j] = j;
                d->data[j] = round(j > 0 ? 42.0 / j : 42.0);
diff --git a/sql/backends/monet5/UDF/capi/Tests/capi02.sql 
b/sql/backends/monet5/UDF/capi/Tests/capi02.sql
new file mode 100644
--- /dev/null
+++ b/sql/backends/monet5/UDF/capi/Tests/capi02.sql
@@ -0,0 +1,84 @@
+# Dates, times, timestamps
+START TRANSACTION;
+
+CREATE FUNCTION capi02_increment_year(d DATE) RETURNS DATE
+language C
+{
+       result->initialize(result, d.count);
+       for(size_t i = 0; i < result->count; i++) {
+               if (d.is_null(d.data[i])) {
+                       result->data[i] = result->null_value;
+               } else {
+                       result->data[i].year = d.data[i].year + 1;
+                       result->data[i].month = d.data[i].month;
+                       result->data[i].day = d.data[i].day;
+               }
+       }
+};
+
+
+CREATE TABLE dates(i DATE);
+INSERT INTO dates VALUES ('1992-09-20'), ('2000-03-10'), ('1000-05-03'), 
(NULL);
+
+SELECT capi02_increment_year(i) FROM dates;
+DROP FUNCTION capi02_increment_year;
+DROP TABLE dates;
+
+
+CREATE FUNCTION capi02_randomize_time(d TIME) RETURNS TIME
+language C
+{
+       srand(1234);
+       result->initialize(result, d.count);
+       for(size_t i = 0; i < result->count; i++) {
+               if (d.is_null(d.data[i])) {
+                       result->data[i] = result->null_value;
+               } else {
+                       result->data[i].hours = rand() % 24;
+                       result->data[i].minutes = rand() % 60;
+                       result->data[i].seconds = rand() % 60;
+                       result->data[i].ms = rand() % 1000;
+               }
+       }
+};
+
+
+CREATE TABLE times(i TIME);
+INSERT INTO times VALUES ('03:03:02.0101'), (NULL), ('03:03:02.0101');
+
+SELECT capi02_randomize_time(i) FROM times;
+DROP FUNCTION capi02_randomize_time;
+DROP TABLE times;
+
+
+CREATE FUNCTION capi02_increment_timestamp(d TIMESTAMP) RETURNS TIMESTAMP
+language C
+{
+       srand(1234);
+       result->initialize(result, d.count);
+       for(size_t i = 0; i < result->count; i++) {
+               if (d.is_null(d.data[i])) {
+                       printf("Null value!\n");
+                       result->data[i] = result->null_value;
+               } else {
+                       result->data[i].date.year = d.data[i].date.year + 1;
+                       result->data[i].date.month = d.data[i].date.month;
+                       result->data[i].date.day = d.data[i].date.day;
+
+                       result->data[i].time.hours = rand() % 24;
+                       result->data[i].time.minutes = rand() % 60;
+                       result->data[i].time.seconds = rand() % 60;
+                       result->data[i].time.ms = rand() % 1000;
+               }
+       }
+};
+
+
+CREATE TABLE times(i TIMESTAMP);
+INSERT INTO times VALUES ('1992-09-20 03:03:02.0101'), (NULL), ('2000-03-10 
03:03:02.0101');
+
+SELECT capi02_increment_timestamp(i) FROM times;
+DROP FUNCTION capi02_increment_timestamp;
+DROP TABLE times;
+
+ROLLBACK;
diff --git a/sql/backends/monet5/UDF/capi/capi.c 
b/sql/backends/monet5/UDF/capi/capi.c
--- a/sql/backends/monet5/UDF/capi/capi.c
+++ b/sql/backends/monet5/UDF/capi/capi.c
@@ -10,6 +10,8 @@
 #include "cheader.h"
 #include "cheader.text.h"
 
+#include "mtime.h"
+
 static str
 CUDFeval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, bit grouped);
 
@@ -54,23 +56,62 @@ WriteTextToFile(FILE* f, const char* dat
                goto wrapup; \
        }
 
-#define GENERATE_BAT_INPUT(b, tpe) {\
+
+#define GENERATE_BASE_HEADERS(type, tpename) \
+static int tpename##_is_null(type value); \
+static void tpename##_initialize(struct cudf_data_struct_##tpename* self, 
size_t count) { \
+       self->count = count; \
+       self->data = GDKmalloc(count * sizeof(self->null_value)); \
+       if (!self->data) { \
+               /* FIXME: longjmp */ \
+       } \
+}
+
+#define GENERATE_BASE_FUNCTIONS(tpe) \
+GENERATE_BASE_HEADERS(tpe, tpe); \
+static int tpe##_is_null(tpe value) { \
+       return value == tpe##_nil; \
+}
+
+GENERATE_BASE_FUNCTIONS(bte);
+GENERATE_BASE_FUNCTIONS(sht);
+GENERATE_BASE_FUNCTIONS(int);
+GENERATE_BASE_FUNCTIONS(lng);
+GENERATE_BASE_FUNCTIONS(flt);
+GENERATE_BASE_FUNCTIONS(dbl);
+
+GENERATE_BASE_HEADERS(cudf_data_date, date);
+GENERATE_BASE_HEADERS(cudf_data_time, time);
+GENERATE_BASE_HEADERS(cudf_data_timestamp, timestamp);
+
+
+#define GENERATE_BAT_INPUT_BASE(b, tpe) \
        struct cudf_data_struct_##tpe* bat_data = GDKmalloc(sizeof(struct 
cudf_data_struct_##tpe)); \
        if (!bat_data) { \
                goto wrapup; \
        } \
        inputs[index] = bat_data; \
+       bat_data->is_null = tpe##_is_null;\
+       bat_data->initialize = (void (*)(void*, size_t)) tpe##_initialize;
+
+#define GENERATE_BAT_INPUT(b, tpe) {\
+       GENERATE_BAT_INPUT_BASE(b, tpe); \
        bat_data->count = BATcount(b); \
        bat_data->data = (tpe*) Tloc(b, 0); \
        bat_data->null_value = tpe##_nil;\
 }
 
-#define GENERATE_BAT_OUTPUT(tpe) {\
+#define GENERATE_BAT_OUTPUT_BASE(tpe) \
        struct cudf_data_struct_##tpe* bat_data = GDKmalloc(sizeof(struct 
cudf_data_struct_##tpe)); \
        if (!bat_data) { \
                goto wrapup; \
        } \
        outputs[index] = bat_data; \
+       bat_data->is_null = tpe##_is_null; \
+       bat_data->initialize = (void (*)(void*, size_t)) tpe##_initialize;
+
+#define GENERATE_BAT_OUTPUT(tpe) { \
+       GENERATE_BAT_OUTPUT_BASE(tpe); \
        bat_data->count = 0; \
        bat_data->data = NULL; \
        bat_data->null_value = tpe##_nil;\
@@ -93,12 +134,19 @@ static void* GetTypeData(int type, void*
 static const char* GetTypeDefinition(int type);
 static const char* GetTypeName(int type);
 
+static void data_from_date(date d, cudf_data_date* ptr);
+static date date_from_data(cudf_data_date* ptr);
+static void data_from_time(daytime d, cudf_data_time* ptr);
+static daytime time_from_data(cudf_data_time* ptr);
+static void data_from_timestamp(timestamp d, cudf_data_timestamp* ptr);
+static timestamp timestamp_from_data(cudf_data_timestamp* ptr);
+
 static str
 CUDFeval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, bit grouped) 
{
        sql_func * sqlfun = NULL;
        str exprStr = *getArgReference_str(stk, pci, pci->retc + 1);
 
-       int i = 0, j = 0;
+       size_t i = 0, j = 0;
        char argbuf[64];
        char buf[BUFSIZ];
        char fname[BUFSIZ];
@@ -173,7 +221,7 @@ CUDFeval(Client cntxt, MalBlkPtr mb, Mal
        for(i = 0; i < pci->retc; i++) {
                if (!output_names[i]) {
                        if (pci->retc > 1) {
-                               snprintf(argbuf, sizeof(argbuf), "output%i", i);
+                               snprintf(argbuf, sizeof(argbuf), "output%zu", 
i);
                        } else {
                                // just call it "output" if there is only one
                                snprintf(argbuf, sizeof(argbuf), "output");
@@ -192,7 +240,7 @@ CUDFeval(Client cntxt, MalBlkPtr mb, Mal
                                }
                                seengrp = TRUE;
                        } else {
-                               snprintf(argbuf, sizeof(argbuf), "arg%i", i - 
pci->retc - 1);
+                               snprintf(argbuf, sizeof(argbuf), "arg%zu", i - 
pci->retc - 1);
                                args[i] = GDKstrdup(argbuf);
                                if (!args[i]) {
                                        msg = createException(MAL, "cudf.eval", 
MAL_MALLOC_FAIL);
@@ -263,7 +311,7 @@ CUDFeval(Client cntxt, MalBlkPtr mb, Mal
        // create the actual function
        ATTEMPT_TO_WRITE_TO_FILE(f, "\nchar* ");
        ATTEMPT_TO_WRITE_TO_FILE(f, funcname);
-       ATTEMPT_TO_WRITE_TO_FILE(f, "(void** __inputs, void** __outputs, 
malloc_function_ptr __malloc) {\n");
+       ATTEMPT_TO_WRITE_TO_FILE(f, "(void** __inputs, void** __outputs, 
malloc_function_ptr malloc) {\n");
 
        const char* struct_prefix = "struct cudf_data_struct_";
        // now we convert the input arguments from void** to the proper 
input/output of the function
@@ -276,15 +324,15 @@ CUDFeval(Client cntxt, MalBlkPtr mb, Mal
                        const char* tpe = GetTypeDefinition(scalar_type);
                        assert(tpe);
                        if (tpe) {
-                               snprintf(buf, sizeof(buf), "%s %s = 
*((%s*)__inputs[%d]);\n", tpe, args[i], tpe, i - (pci->retc + 2));
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to