Changeset: 6c8b7012d916 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=6c8b7012d916
Added Files:
sql/backends/monet5/UDF/capi/Tests/capi04.sql
sql/backends/monet5/UDF/capi/Tests/capi04.stable.err
sql/backends/monet5/UDF/capi/Tests/capi04.stable.out
Modified Files:
sql/backends/monet5/UDF/capi/Tests/All
sql/backends/monet5/UDF/capi/capi.c
Branch: jitudf
Log Message:
Support strings in C UDFs.
diffs (truncated from 335 to 300 lines):
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
@@ -3,3 +3,4 @@ capi00
capi01
capi02
capi03
+capi04
diff --git a/sql/backends/monet5/UDF/capi/Tests/capi04.sql
b/sql/backends/monet5/UDF/capi/Tests/capi04.sql
new file mode 100644
--- /dev/null
+++ b/sql/backends/monet5/UDF/capi/Tests/capi04.sql
@@ -0,0 +1,43 @@
+# test strings
+
+START TRANSACTION;
+
+CREATE FUNCTION capi04(inp STRING) RETURNS STRING LANGUAGE C {
+#include <string.h>
+
+ result->initialize(result, inp.count);
+ for(size_t i = 0; i < inp.count; i++) {
+ if (inp.is_null(inp.data[i])) {
+ result->data[i] = result->null_value;
+ } else {
+ // the contract says we must use "malloc" to allocate
for the result strings
+ // "malloc" is a function pointer that actually points
to GDKmalloc
+ result->data[i] = malloc(strlen(inp.data[i]) + 2);
+ strcpy(result->data[i] + 1, inp.data[i]);
+ result->data[i][0] = 'H';
+ printf("%s\n", result->data[i]);
+ }
+ }
+};
+
+CREATE TABLE strings(i STRING);
+INSERT INTO strings VALUES ('ello'), ('ow'), (NULL), ('onestly?'), ('annes');
+
+SELECT capi04(i) FROM strings;
+
+DROP FUNCTION capi04;
+
+# try to modify one of the input strings
+CREATE FUNCTION capi04(inp STRING) RETURNS STRING LANGUAGE C {
+ result->initialize(result, inp.count);
+ for(size_t i = 0; i < inp.count; i++) {
+ result->data[i][0] = 'h';
+ }
+};
+
+SELECT capi04(i) FROM strings;
+
+ROLLBACK;
+
+
+
diff --git a/sql/backends/monet5/UDF/capi/Tests/capi04.stable.err
b/sql/backends/monet5/UDF/capi/Tests/capi04.stable.err
new file mode 100644
--- /dev/null
+++ b/sql/backends/monet5/UDF/capi/Tests/capi04.stable.err
@@ -0,0 +1,37 @@
+stderr of test 'capi04` in directory 'sql/backends/monet5/UDF/capi` itself:
+
+
+# 15:50:30 >
+# 15:50:30 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set"
"mapi_open=true" "--set" "mapi_port=32751" "--set"
"mapi_usock=/var/tmp/mtest-20003/.s.monetdb.32751" "--set" "monet_prompt="
"--forcemito" "--dbpath=NONE/var/MonetDB/mTests_sql_backends_monet5_UDF_capi"
+# 15:50:30 >
+
+# builtin opt gdk_dbpath = /Users/myth/opt/var/monetdb5/dbfarm/demo
+# builtin opt gdk_debug = 0
+# builtin opt gdk_vmtrim = no
+# builtin opt monet_prompt = >
+# builtin opt monet_daemon = no
+# builtin opt mapi_port = 50000
+# builtin opt mapi_open = false
+# builtin opt mapi_autosense = false
+# builtin opt sql_optimizer = default_pipe
+# builtin opt sql_debug = 0
+# cmdline opt gdk_nr_threads = 0
+# cmdline opt mapi_open = true
+# cmdline opt mapi_port = 32751
+# cmdline opt mapi_usock = /var/tmp/mtest-20003/.s.monetdb.32751
+# cmdline opt monet_prompt =
+# cmdline opt gdk_dbpath =
/Users/myth/opt/mTests/sql/backends/monet5/UDF/capi/NONE/var/MonetDB/mTests_sql_backends_monet5_UDF_capi
+# cmdline opt gdk_debug = 536870922
+
+# 15:50:30 >
+# 15:50:30 > "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e"
"--host=/var/tmp/mtest-20003" "--port=32751"
+# 15:50:30 >
+
+MAPI = (monetdb) /var/tmp/mtest-20003/.s.monetdb.32751
+QUERY = SELECT capi04(i) FROM strings;
+ERROR = !Attempting to write to the input or triggered a segfault/bus error
+
+# 15:50:31 >
+# 15:50:31 > "Done."
+# 15:50:31 >
+
diff --git a/sql/backends/monet5/UDF/capi/Tests/capi04.stable.out
b/sql/backends/monet5/UDF/capi/Tests/capi04.stable.out
new file mode 100644
--- /dev/null
+++ b/sql/backends/monet5/UDF/capi/Tests/capi04.stable.out
@@ -0,0 +1,105 @@
+stdout of test 'capi04` in directory 'sql/backends/monet5/UDF/capi` itself:
+
+
+# 15:50:30 >
+# 15:50:30 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set"
"mapi_open=true" "--set" "mapi_port=32751" "--set"
"mapi_usock=/var/tmp/mtest-20003/.s.monetdb.32751" "--set" "monet_prompt="
"--forcemito" "--dbpath=NONE/var/MonetDB/mTests_sql_backends_monet5_UDF_capi"
+# 15:50:30 >
+
+# MonetDB 5 server v11.28.0
+# This is an unreleased version
+# Serving database 'mTests_sql_backends_monet5_UDF_capi', using 4 threads
+# Compiled for x86_64-apple-darwin15.6.0/64bit with 128bit integers
+# Found 8.000 GiB available main-memory.
+# Copyright (c) 1993-July 2008 CWI.
+# Copyright (c) August 2008-2017 MonetDB B.V., all rights reserved
+# Visit https://www.monetdb.org/ for further information
+# Listening for connection requests on mapi:monetdb://Marks-MBP:32751/
+# Listening for UNIX domain connection requests on
mapi:monetdb:///var/tmp/mtest-20003/.s.monetdb.32751
+# MonetDB/SQL module loaded
+
+Ready.
+# SQL catalog created, loading sql scripts once
+# loading sql script: 09_like.sql
+# loading sql script: 10_math.sql
+# loading sql script: 11_times.sql
+# loading sql script: 12_url.sql
+# loading sql script: 13_date.sql
+# loading sql script: 14_inet.sql
+# loading sql script: 15_querylog.sql
+# loading sql script: 16_tracelog.sql
+# loading sql script: 17_temporal.sql
+# loading sql script: 18_index.sql
+# loading sql script: 20_vacuum.sql
+# loading sql script: 21_dependency_functions.sql
+# loading sql script: 22_clients.sql
+# loading sql script: 23_skyserver.sql
+# loading sql script: 25_debug.sql
+# loading sql script: 26_sysmon.sql
+# loading sql script: 27_rejects.sql
+# loading sql script: 39_analytics.sql
+# loading sql script: 39_analytics_hge.sql
+# loading sql script: 40_json.sql
+# loading sql script: 40_json_hge.sql
+# loading sql script: 41_md5sum.sql
+# loading sql script: 45_uuid.sql
+# loading sql script: 46_profiler.sql
+# loading sql script: 51_sys_schema_extension.sql
+# loading sql script: 60_wlcr.sql
+# loading sql script: 72_fits.sql
+# loading sql script: 74_netcdf.sql
+# loading sql script: 75_storagemodel.sql
+# loading sql script: 80_statistics.sql
+# loading sql script: 80_udf.sql
+# loading sql script: 80_udf_hge.sql
+# loading sql script: 90_generator.sql
+# loading sql script: 90_generator_hge.sql
+# loading sql script: 99_system.sql
+Hello
+How
+Honestly?
+Hannes
+
+# 15:50:30 >
+# 15:50:30 > "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e"
"--host=/var/tmp/mtest-20003" "--port=32751"
+# 15:50:30 >
+
+#START TRANSACTION;
+#CREATE FUNCTION capi04(inp STRING) RETURNS STRING LANGUAGE C {
+##include <string.h>
+#
+# result->initialize(result, inp.count);
+# for(size_t i = 0; i < inp.count; i++) {
+# if (inp.is_null(inp.data[i])) {
+# result->data[i] = result->null_value;
+# } else {
+# // the contract says we must use "malloc" to allocate
for the result strings
+# // "malloc" is a function pointer that actually points
to GDKmalloc
+# result->data[i] = malloc(strlen(inp.data[i]) + 2);
+# strcpy(result->data[i] + 1, inp.data[i]);
+# result->data[i][0] = 'H';
+#CREATE TABLE strings(i STRING);
+#INSERT INTO strings VALUES ('ello'), ('ow'), (NULL), ('onestly?'), ('annes');
+[ 5 ]
+#SELECT capi04(i) FROM strings;
+% sys.L2 # table_name
+% L2 # name
+% clob # type
+% 9 # length
+[ "Hello" ]
+[ "How" ]
+[ NULL ]
+[ "Honestly?" ]
+[ "Hannes" ]
+#DROP FUNCTION capi04;
+#CREATE FUNCTION capi04(inp STRING) RETURNS STRING LANGUAGE C {
+# result->initialize(result, inp.count);
+# for(size_t i = 0; i < inp.count; i++) {
+# result->data[i][0] = 'h';
+# }
+#};
+#ROLLBACK;
+
+# 15:50:31 >
+# 15:50:31 > "Done."
+# 15:50:31 >
+
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
@@ -140,19 +140,20 @@ static void tpename##_initialize(struct
self->data = wrapped_GDK_malloc(count * sizeof(self->null_value)); \
}
-#define GENERATE_BASE_FUNCTIONS(tpe) \
-GENERATE_BASE_HEADERS(tpe, tpe); \
-static int tpe##_is_null(tpe value) { \
- return value == tpe##_nil; \
+#define GENERATE_BASE_FUNCTIONS(tpe, tpename) \
+GENERATE_BASE_HEADERS(tpe, tpename); \
+static int tpename##_is_null(tpe value) { \
+ return value == tpename##_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_FUNCTIONS(bte, bte);
+GENERATE_BASE_FUNCTIONS(sht, sht);
+GENERATE_BASE_FUNCTIONS(int, int);
+GENERATE_BASE_FUNCTIONS(lng, lng);
+GENERATE_BASE_FUNCTIONS(flt, flt);
+GENERATE_BASE_FUNCTIONS(dbl, dbl);
+GENERATE_BASE_HEADERS(char*, str);
GENERATE_BASE_HEADERS(cudf_data_date, date);
GENERATE_BASE_HEADERS(cudf_data_time, time);
GENERATE_BASE_HEADERS(cudf_data_timestamp, timestamp);
@@ -195,7 +196,7 @@ GENERATE_BASE_HEADERS(cudf_data_timestam
GENERATE_BAT_OUTPUT_BASE(tpe); \
bat_data->count = 0; \
bat_data->data = NULL; \
- bat_data->null_value = tpe##_nil;\
+ bat_data->null_value = (tpe) tpe##_nil;\
}
#define GENERATE_SCALAR_INPUT(tpe) \
@@ -603,7 +604,31 @@ CUDFeval(Client cntxt, MalBlkPtr mb, Mal
} else if (bat_type == TYPE_dbl) {
GENERATE_BAT_INPUT(input_bats[index], dbl);
} else if (bat_type == TYPE_str) {
- assert(0);
+ BATiter li;
+ BUN p = 0, q = 0;
+ str mprotect_retval;
+ GENERATE_BAT_INPUT_BASE(input_bats[index], str);
+ bat_data->count = BATcount(input_bats[index]);
+ bat_data->data = GDKmalloc(sizeof(char*) *
bat_data->count);
+ if (!bat_data->data) {
+ msg = createException(MAL, "cudf.eval",
MAL_MALLOC_FAIL);
+ goto wrapup;
+ }
+ j = 0;
+
+ li = bat_iterator(input_bats[index]);
+ BATloop(input_bats[index], p, q) {
+ char *t = (char *)BUNtail(li, p);
+ bat_data->data[j] = t;
+ j++;
+ }
+ // for string columns, mprotect the varheap of
the BAT
+ assert(input_bats[index]->tvheap);
+ mprotect_retval =
mprotect_region(input_bats[index]->tvheap->base,
input_bats[index]->tvheap->size, PROT_READ, ®ions);
+ if (mprotect_retval) {
+ msg = createException(MAL, "cudf.eval",
"Failed to mprotect region: %s", mprotect_retval);
+ goto wrapup;
+ }
} else if (bat_type == TYPE_date) {
date* baseptr;
GENERATE_BAT_INPUT_BASE(input_bats[index],
date);
@@ -657,7 +682,6 @@ CUDFeval(Client cntxt, MalBlkPtr mb, Mal
}
}
// output types
- // FIXME: deal with SQL types
for (i = 0; i < output_count; i++) {
size_t index = i;
int bat_type = getBatType(getArgType(mb, pci, i));
@@ -676,7 +700,7 @@ CUDFeval(Client cntxt, MalBlkPtr mb, Mal
} else if (bat_type == TYPE_dbl) {
GENERATE_BAT_OUTPUT(dbl);
} else if (bat_type == TYPE_str) {
- assert(0);
+ GENERATE_BAT_OUTPUT(str);
} else if (bat_type == TYPE_date) {
GENERATE_BAT_OUTPUT_BASE(date);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list