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, &regions);
+                               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
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to