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