Changeset: 0e500eac6fcc for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=0e500eac6fcc Modified Files: monetdb5/extras/pyapi/connection.c monetdb5/extras/pyapi/pyapi.c monetdb5/extras/pyapi/pyapi.h Branch: pythonudf Log Message:
Use function pointers to execute SQL statements because Windows does not like unresolved references. Previously we just relied on the SQL module being loaded at runtime, and left the references unresolved at link time. This is not allowed on Windows. diffs (187 lines): diff --git a/monetdb5/extras/pyapi/connection.c b/monetdb5/extras/pyapi/connection.c --- a/monetdb5/extras/pyapi/connection.c +++ b/monetdb5/extras/pyapi/connection.c @@ -9,6 +9,9 @@ #define PyString_FromString PyUnicode_FromString #endif +CREATE_SQL_FUNCTION_PTR(void,res_table_destroy,(res_table*)); +CREATE_SQL_FUNCTION_PTR(str,SQLstatementIntern_ext,(Client, str *, str, int, bit, res_table **, bit)); + static PyObject * _connection_execute(Py_ConnectionObject *self, PyObject *args) { @@ -230,13 +233,13 @@ PyTypeObject Py_ConnectionType = { void _connection_cleanup_result(void* output) { - res_table_destroy((res_table*) output); + (*res_table_destroy_ptr)((res_table*) output); } char* _connection_query(Client cntxt, char* query, res_table** result) { str res = MAL_SUCCEED; Client c = cntxt; - res = SQLstatementIntern_ext(c, &query, "name", 1, 0, result, 1); + res = (*SQLstatementIntern_ext_ptr)(c, &query, "name", 1, 0, result, 1); return res; } @@ -262,6 +265,9 @@ void _connection_init(void) { import_array(); + LOAD_SQL_FUNCTION_PTR(res_table_destroy); + LOAD_SQL_FUNCTION_PTR(SQLstatementIntern_ext); + if (PyType_Ready(&Py_ConnectionType) < 0) return; } diff --git a/monetdb5/extras/pyapi/pyapi.c b/monetdb5/extras/pyapi/pyapi.c old mode 100755 new mode 100644 --- a/monetdb5/extras/pyapi/pyapi.c +++ b/monetdb5/extras/pyapi/pyapi.c @@ -94,6 +94,18 @@ static char* FunctionBasePath(void) { return basepath; } +CREATE_SQL_FUNCTION_PTR(str,batbte_dec2_dbl,(bat*, int*, bat*)); +CREATE_SQL_FUNCTION_PTR(str,batsht_dec2_dbl,(bat*, int*, bat*)); +CREATE_SQL_FUNCTION_PTR(str,batint_dec2_dbl,(bat*, int*, bat*)); +CREATE_SQL_FUNCTION_PTR(str,batwrd_dec2_dbl,(bat*, int*, bat*)); +CREATE_SQL_FUNCTION_PTR(str,batlng_dec2_dbl,(bat*, int*, bat*)); +CREATE_SQL_FUNCTION_PTR(str,bathge_dec2_dbl,(bat*, int*, bat*)); +CREATE_SQL_FUNCTION_PTR(str,batstr_2time_timestamp,(bat*, bat*, int*)); +CREATE_SQL_FUNCTION_PTR(str,batstr_2time_daytime,(bat*, bat*, int*)); +CREATE_SQL_FUNCTION_PTR(str,batstr_2_date,(bat*, bat*)); +CREATE_SQL_FUNCTION_PTR(str,batdbl_num2dec_lng,(bat*, bat*, int*,int*)); +CREATE_SQL_FUNCTION_PTR(str,SQLbatstr_cast,(Client, MalBlkPtr, MalStkPtr, InstrPtr)); + static MT_Lock pyapiLock; static MT_Lock queryLock; static int pyapiInitialized = FALSE; @@ -1588,6 +1600,18 @@ str return createException(MAL, "pyapi.eval", "Failed to load function \"loads\" from Marshal module."); } PyEval_SaveThread(); + LOAD_SQL_FUNCTION_PTR(batbte_dec2_dbl); + LOAD_SQL_FUNCTION_PTR(batsht_dec2_dbl); + LOAD_SQL_FUNCTION_PTR(batint_dec2_dbl); + LOAD_SQL_FUNCTION_PTR(batwrd_dec2_dbl); + LOAD_SQL_FUNCTION_PTR(batlng_dec2_dbl); + LOAD_SQL_FUNCTION_PTR(bathge_dec2_dbl); + LOAD_SQL_FUNCTION_PTR(bathge_dec2_dbl); + LOAD_SQL_FUNCTION_PTR(batstr_2time_timestamp); + LOAD_SQL_FUNCTION_PTR(batstr_2time_daytime); + LOAD_SQL_FUNCTION_PTR(batstr_2_date); + LOAD_SQL_FUNCTION_PTR(batdbl_num2dec_lng); + LOAD_SQL_FUNCTION_PTR(SQLbatstr_cast); pyapiInitialized++; } MT_lock_unset(&pyapiLock); @@ -2620,7 +2644,7 @@ str ConvertFromSQLType(Client cntxt, BAT stk->stk[6].val.ival = digits; stk->stk[6].vtype = TYPE_int; - res = SQLbatstr_cast(cntxt, &mb, stk, pci); + res = (*SQLbatstr_cast_ptr)(cntxt, &mb, stk, pci); if (res == MAL_SUCCEED) { *ret_bat = BATdescriptor(stk->stk[0].val.bval); @@ -2642,23 +2666,23 @@ str ConvertFromSQLType(Client cntxt, BAT switch(bat_type) { case TYPE_bte: - res = batbte_dec2_dbl(&result, &hpos, &b->batCacheid); + res = (*batbte_dec2_dbl_ptr)(&result, &hpos, &b->batCacheid); break; case TYPE_sht: - res = batsht_dec2_dbl(&result, &hpos, &b->batCacheid); + res = (*batsht_dec2_dbl_ptr)(&result, &hpos, &b->batCacheid); break; case TYPE_int: - res = batint_dec2_dbl(&result, &hpos, &b->batCacheid); + res = (*batint_dec2_dbl_ptr)(&result, &hpos, &b->batCacheid); break; case TYPE_wrd: - res = batwrd_dec2_dbl(&result, &hpos, &b->batCacheid); + res = (*batwrd_dec2_dbl_ptr)(&result, &hpos, &b->batCacheid); break; case TYPE_lng: - res = batlng_dec2_dbl(&result, &hpos, &b->batCacheid); + res = (*batlng_dec2_dbl_ptr)(&result, &hpos, &b->batCacheid); break; #ifdef HAVE_HGE case TYPE_hge: - res = bathge_dec2_dbl(&result, &hpos, &b->batCacheid); + res = (*bathge_dec2_dbl_ptr)(&result, &hpos, &b->batCacheid); break; #endif default: @@ -2687,16 +2711,16 @@ ConvertToSQLType(Client cntxt, BAT *b, e switch(sqltype) { case sql_timestamp: - res = batstr_2time_timestamp(&result_bat, &b->batCacheid, &digits); + res = (*batstr_2time_timestamp_ptr)(&result_bat, &b->batCacheid, &digits); break; case sql_time: - res = batstr_2time_daytime(&result_bat, &b->batCacheid, &digits); + res = (*batstr_2time_daytime_ptr)(&result_bat, &b->batCacheid, &digits); break; case sql_date: - res = batstr_2_date(&result_bat, &b->batCacheid); + res = (*batstr_2_date_ptr)(&result_bat, &b->batCacheid); break; case sql_decimal: - res = batdbl_num2dec_lng(&result_bat, &b->batCacheid, &digits, &scale); + res = (*batdbl_num2dec_lng_ptr)(&result_bat, &b->batCacheid, &digits, &scale); break; default: return createException(MAL, "pyapi.eval", "Convert To SQL Type: Unrecognized SQL type %s (%d).", sql_subtype->type->sqlname, sqltype); @@ -2863,3 +2887,16 @@ bool Python_ReleaseGIL(bool state) PyGILState_Release(gstate); return 0; } + +pyapi_export +void* lookup_function(char *func, char* library) { + void *dl, *fun; + dl = mdlopen(library, RTLD_NOW | RTLD_GLOBAL); + if (dl == NULL) { + return NULL; + } + fun = dlsym(dl, func); + dlclose(dl); + return fun; +} + diff --git a/monetdb5/extras/pyapi/pyapi.h b/monetdb5/extras/pyapi/pyapi.h --- a/monetdb5/extras/pyapi/pyapi.h +++ b/monetdb5/extras/pyapi/pyapi.h @@ -62,6 +62,7 @@ #endif #ifdef _PYAPI_WARNINGS_ +bool option_warning; #define WARNING_MESSAGE(...) { \ if (option_warning) { \ fprintf(stderr, __VA_ARGS__); \ @@ -90,4 +91,16 @@ pyapi_export str PyAPIprelude(void *ret) int PyAPIEnabled(void); +pyapi_export void* lookup_function(char *func, char* library); + +#define CREATE_SQL_FUNCTION_PTR(retval, fcnname, params) \ + typedef retval (*fcnname##_ptr_tpe)params; \ + fcnname##_ptr_tpe fcnname##_ptr = NULL; + +#define LOAD_SQL_FUNCTION_PTR(fcnname) \ + fcnname##_ptr = (fcnname##_ptr_tpe) lookup_function(#fcnname, "sql"); \ + if (fcnname##_ptr == NULL) { \ + WARNING_MESSAGE("Failed to load function %s", #fcnname); \ + } + #endif /* _PYPI_LIB_ */ _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list