1 #include "opensrf/osrf_application.h"
2 #include "opensrf/osrf_settings.h"
3 #include "opensrf/utils.h"
4 #include "objson/object.h"
5 #include "opensrf/log.h"
6 #include "oils_utils.h"
7 #include "oils_constants.h"
8 #include "oils_event.h"
14 #include <libxml/globals.h>
15 #include <libxml/xmlerror.h>
16 #include <libxml/parser.h>
17 #include <libxml/tree.h>
18 #include <libxml/debugXML.h>
19 #include <libxml/xmlmemory.h>
21 #define OILS_AUTH_CACHE_PRFX "oils_cstore_"
22 #define MODULENAME "open-ils.cstore"
23 #define PERSIST_NS "http://open-ils.org/spec/opensrf/IDL/persistance/v1"
24 #define OBJECT_NS "http://open-ils.org/spec/opensrf/IDL/objects/v1"
25 #define BASE_NS "http://opensrf.org/spec/IDL/base/v1"
27 int osrfAppChildInit();
28 int osrfAppInitialize();
30 int verifyObjectClass ( osrfMethodContext*, jsonObject* );
32 int beginTransaction ( osrfMethodContext* );
33 int commitTransaction ( osrfMethodContext* );
34 int rollbackTransaction ( osrfMethodContext* );
36 int setSavepoint ( osrfMethodContext* );
37 int releaseSavepoint ( osrfMethodContext* );
38 int rollbackSavepoint ( osrfMethodContext* );
40 int dispatchCRUDMethod ( osrfMethodContext* );
41 jsonObject* doCreate ( osrfMethodContext*, int* );
42 jsonObject* doRetrieve ( osrfMethodContext*, int* );
43 jsonObject* doUpdate ( osrfMethodContext*, int* );
44 jsonObject* doDelete ( osrfMethodContext*, int* );
45 jsonObject* doSearch ( osrfMethodContext*, osrfHash*, jsonObject*, int* );
46 jsonObject* oilsMakeJSONFromResult( dbi_result, osrfHash* );
48 char* searchWriteSimplePredicate ( osrfHash*, const char*, const char*, const char* );
49 char* searchSimplePredicate ( const char*, osrfHash*, jsonObject* );
50 char* searchFunctionPredicate ( osrfHash*, jsonObjectNode* );
51 char* searchFieldTransformPredicate ( osrfHash*, jsonObjectNode* );
52 char* searchBETWEENPredicate ( osrfHash*, jsonObject* );
53 char* searchINPredicate ( osrfHash*, jsonObject* );
54 char* searchPredicate ( osrfHash*, jsonObject* );
56 void userDataFree( void* );
57 void sessionDataFree( char*, void* );
59 dbi_conn writehandle; /* our MASTER db connection */
60 dbi_conn dbhandle; /* our CURRENT db connection */
62 xmlDocPtr idlDoc = NULL; // parse and store the IDL here
63 jsonObject* jsonNULL = NULL; //
66 /* parse and store the IDL here */
69 int osrfAppInitialize() {
71 // first we register all the transaction and savepoint methods
72 osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.transaction.begin", "beginTransaction", "", 0, 0 );
73 osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.transaction.commit", "commitTransaction", "", 0, 0 );
74 osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.transaction.rollback", "rollbackTransaction", "", 0, 0 );
76 osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.savepoint.set", "setSavepoint", "", 1, 0 );
77 osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.savepoint.release", "releaseSavepoint", "", 1, 0 );
78 osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.savepoint.rollback", "rollbackSavepoint", "", 1, 0 );
81 idlHash = osrfNewHash();
82 osrfHash* usrData = NULL;
84 osrfLogInfo(OSRF_LOG_MARK, "Initializing the CStore Server...");
85 osrfLogInfo(OSRF_LOG_MARK, "Finding XML file...");
87 char * idl_filename = osrf_settings_host_value("/apps/%s/app_settings/IDL", MODULENAME);
88 osrfLogInfo(OSRF_LOG_MARK, "Found file:");
89 osrfLogInfo(OSRF_LOG_MARK, idl_filename);
91 osrfLogInfo(OSRF_LOG_MARK, "Parsing the IDL XML...");
92 idlDoc = xmlReadFile( idl_filename, NULL, XML_PARSE_XINCLUDE );
95 osrfLogError(OSRF_LOG_MARK, "Could not load or parse the IDL XML file!");
99 osrfLogInfo(OSRF_LOG_MARK, "...IDL XML parsed");
101 osrfStringArray* global_methods = osrfNewStringArray(1);
103 osrfStringArrayAdd( global_methods, "create" );
104 osrfStringArrayAdd( global_methods, "retrieve" );
105 osrfStringArrayAdd( global_methods, "update" );
106 osrfStringArrayAdd( global_methods, "delete" );
107 osrfStringArrayAdd( global_methods, "search" );
108 osrfStringArrayAdd( global_methods, "id_list" );
110 xmlNodePtr docRoot = xmlDocGetRootElement(idlDoc);
111 xmlNodePtr kid = docRoot->children;
113 if (!strcmp( (char*)kid->name, "class" )) {
115 if (!strcmp(xmlGetNsProp(kid, "virtual", PERSIST_NS), "true"))
118 usrData = osrfNewHash();
119 osrfHashSet( usrData, xmlGetProp(kid, "id"), "classname");
120 osrfHashSet( usrData, xmlGetNsProp(kid, "tablename", PERSIST_NS), "tablename");
121 osrfHashSet( usrData, xmlGetNsProp(kid, "fieldmapper", OBJECT_NS), "fieldmapper");
123 osrfHashSet( idlHash, usrData, (char*)osrfHashGet(usrData, "classname") );
125 osrfLogInfo(OSRF_LOG_MARK, "Generating class methods for %s", osrfHashGet(usrData, "fieldmapper") );
128 osrfHash* links = osrfNewHash();
129 osrfHash* fields = osrfNewHash();
131 osrfHashSet( usrData, fields, "fields" );
132 osrfHashSet( usrData, links, "links" );
134 xmlNodePtr _cur = kid->children;
137 char* string_tmp = NULL;
139 if (!strcmp( (char*)_cur->name, "fields" )) {
141 if( (string_tmp = (char*)xmlGetNsProp(_cur, "primary", PERSIST_NS)) ) {
144 strdup( string_tmp ),
150 if( (string_tmp = (char*)xmlGetNsProp(_cur, "sequence", PERSIST_NS)) ) {
153 strdup( string_tmp ),
159 xmlNodePtr _f = _cur->children;
162 if (strcmp( (char*)_f->name, "field" )) {
167 _tmp = osrfNewHash();
169 if( (string_tmp = (char*)xmlGetNsProp(_f, "array_position", OBJECT_NS)) ) {
172 strdup( string_tmp ),
178 if( (string_tmp = (char*)xmlGetNsProp(_f, "virtual", PERSIST_NS)) ) {
181 strdup( string_tmp ),
187 if( (string_tmp = (char*)xmlGetNsProp(_f, "primitive", PERSIST_NS)) ) {
190 strdup( string_tmp ),
196 if( (string_tmp = (char*)xmlGetProp(_f, "name")) ) {
199 strdup( string_tmp ),
204 osrfLogInfo(OSRF_LOG_MARK, "Found field %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
215 if (!strcmp( (char*)_cur->name, "links" )) {
216 xmlNodePtr _l = _cur->children;
219 if (strcmp( (char*)_l->name, "link" )) {
224 _tmp = osrfNewHash();
226 if( (string_tmp = (char*)xmlGetProp(_l, "reltype")) ) {
229 strdup( string_tmp ),
233 osrfLogInfo(OSRF_LOG_MARK, "Adding link with reltype %s", string_tmp );
236 if( (string_tmp = (char*)xmlGetProp(_l, "key")) ) {
239 strdup( string_tmp ),
243 osrfLogInfo(OSRF_LOG_MARK, "Link fkey is %s", string_tmp );
246 if( (string_tmp = (char*)xmlGetProp(_l, "class")) ) {
249 strdup( string_tmp ),
253 osrfLogInfo(OSRF_LOG_MARK, "Link fclass is %s", string_tmp );
256 osrfStringArray* map = osrfNewStringArray(0);
258 if( (string_tmp = (char*)xmlGetProp(_l, "map") )) {
259 char* map_list = strdup( string_tmp );
260 osrfLogInfo(OSRF_LOG_MARK, "Link mapping list is %s", string_tmp );
262 if (strlen( map_list ) > 0) {
264 char* _map_class = strtok_r(map_list, " ", &st_tmp);
265 osrfStringArrayAdd(map, strdup(_map_class));
267 while ((_map_class = strtok_r(NULL, " ", &st_tmp))) {
268 osrfStringArrayAdd(map, strdup(_map_class));
272 osrfHashSet( _tmp, map, "map");
274 if( (string_tmp = (char*)xmlGetProp(_l, "field")) ) {
277 strdup( string_tmp ),
288 osrfLogInfo(OSRF_LOG_MARK, "Found link %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
302 osrfHash* method_meta;
303 while ( (method_type = osrfStringArrayGetString(global_methods, i++)) ) {
305 if (!osrfHashGet(usrData, "fieldmapper")) continue;
307 method_meta = osrfNewHash();
308 osrfHashSet(method_meta, usrData, "class");
310 _fm = strdup( (char*)osrfHashGet(usrData, "fieldmapper") );
311 part = strtok_r(_fm, ":", &st_tmp);
313 growing_buffer* method_name = buffer_init(64);
314 buffer_fadd(method_name, "%s.direct.%s", MODULENAME, part);
316 while ((part = strtok_r(NULL, ":", &st_tmp))) {
317 buffer_fadd(method_name, ".%s", part);
319 buffer_fadd(method_name, ".%s", method_type);
322 char* method = buffer_data(method_name);
323 buffer_free(method_name);
326 osrfHashSet( method_meta, method, "methodname" );
327 osrfHashSet( method_meta, method_type, "methodtype" );
330 if (!(strcmp( method_type, "search" )) || !(strcmp( method_type, "id_list" ))) {
331 flags = flags | OSRF_METHOD_STREAMING;
334 osrfAppRegisterExtendedMethod(
337 "dispatchCRUDMethod",
352 * Connects to the database
354 int osrfAppChildInit() {
356 osrfLogDebug(OSRF_LOG_MARK, "Attempting to initialize libdbi...");
357 dbi_initialize(NULL);
358 osrfLogDebug(OSRF_LOG_MARK, "... libdbi initialized.");
360 char* driver = osrf_settings_host_value("/apps/%s/app_settings/driver", MODULENAME);
361 char* user = osrf_settings_host_value("/apps/%s/app_settings/database/user", MODULENAME);
362 char* host = osrf_settings_host_value("/apps/%s/app_settings/database/host", MODULENAME);
363 char* port = osrf_settings_host_value("/apps/%s/app_settings/database/port", MODULENAME);
364 char* db = osrf_settings_host_value("/apps/%s/app_settings/database/db", MODULENAME);
365 char* pw = osrf_settings_host_value("/apps/%s/app_settings/database/pw", MODULENAME);
367 osrfLogDebug(OSRF_LOG_MARK, "Attempting to load the database driver [%s]...", driver);
368 writehandle = dbi_conn_new(driver);
371 osrfLogError(OSRF_LOG_MARK, "Error loading database driver [%s]", driver);
374 osrfLogDebug(OSRF_LOG_MARK, "Database driver [%s] seems OK", driver);
376 osrfLogInfo(OSRF_LOG_MARK, "%s connecting to database. host=%s, "
377 "port=%s, user=%s, pw=%s, db=%s", MODULENAME, host, port, user, pw, db );
379 if(host) dbi_conn_set_option(writehandle, "host", host );
380 if(port) dbi_conn_set_option_numeric( writehandle, "port", atoi(port) );
381 if(user) dbi_conn_set_option(writehandle, "username", user);
382 if(pw) dbi_conn_set_option(writehandle, "password", pw );
383 if(db) dbi_conn_set_option(writehandle, "dbname", db );
392 if (dbi_conn_connect(writehandle) < 0) {
393 dbi_conn_error(writehandle, &err);
394 osrfLogError( OSRF_LOG_MARK, "Error connecting to database: %s", err);
398 osrfLogInfo(OSRF_LOG_MARK, "%s successfully connected to the database", MODULENAME);
404 osrfStringArray* classes = osrfHashKeys( idlHash );
406 while ( (classname = osrfStringArrayGetString(classes, i++)) ) {
407 osrfHash* class = osrfHashGet( idlHash, classname );
408 osrfHash* fields = osrfHashGet( class, "fields" );
410 growing_buffer* sql_buf = buffer_init(32);
411 buffer_fadd( sql_buf, "SELECT * FROM %s WHERE 1=0;", osrfHashGet(class, "tablename") );
413 char* sql = buffer_data(sql_buf);
414 buffer_free(sql_buf);
415 osrfLogDebug(OSRF_LOG_MARK, "%s Investigatory SQL = %s", MODULENAME, sql);
417 dbi_result result = dbi_conn_query(writehandle, sql);
423 const char* columnName;
425 while( (columnName = dbi_result_get_field_name(result, columnIndex++)) ) {
427 osrfLogDebug(OSRF_LOG_MARK, "Looking for column named [%s]...", (char*)columnName);
429 /* fetch the fieldmapper index */
430 if( (_f = osrfHashGet(fields, (char*)columnName)) ) {
432 osrfLogDebug(OSRF_LOG_MARK, "Found [%s] in IDL hash...", (char*)columnName);
434 /* determine the field type and storage attributes */
435 type = dbi_result_get_field_type(result, columnName);
436 attr = dbi_result_get_field_attribs(result, columnName);
440 case DBI_TYPE_INTEGER :
442 if ( !osrfHashGet(_f, "primitive") )
443 osrfHashSet(_f,"number", "primitive");
445 if( attr & DBI_INTEGER_SIZE8 )
446 osrfHashSet(_f,"INT8", "datatype");
448 osrfHashSet(_f,"INT", "datatype");
451 case DBI_TYPE_DECIMAL :
452 if ( !osrfHashGet(_f, "primitive") )
453 osrfHashSet(_f,"number", "primitive");
455 osrfHashSet(_f,"NUMERIC", "datatype");
458 case DBI_TYPE_STRING :
459 if ( !osrfHashGet(_f, "primitive") )
460 osrfHashSet(_f,"string", "primitive");
461 osrfHashSet(_f,"TEXT", "datatype");
464 case DBI_TYPE_DATETIME :
465 if ( !osrfHashGet(_f, "primitive") )
466 osrfHashSet(_f,"string", "primitive");
468 osrfHashSet(_f,"TIMESTAMP", "datatype");
471 case DBI_TYPE_BINARY :
472 if ( !osrfHashGet(_f, "primitive") )
473 osrfHashSet(_f,"string", "primitive");
475 osrfHashSet(_f,"BYTEA", "datatype");
480 "Setting [%s] to primitive [%s] and datatype [%s]...",
482 osrfHashGet(_f, "primitive"),
483 osrfHashGet(_f, "datatype")
487 dbi_result_free(result);
489 osrfLogDebug(OSRF_LOG_MARK, "No data found for class [%s]...", (char*)classname);
493 osrfStringArrayFree(classes);
498 void userDataFree( void* blob ) {
499 osrfHashFree( (osrfHash*)blob );
503 void sessionDataFree( char* key, void* item ) {
504 if (!(strcmp(key,"xact_id")))
510 int beginTransaction ( osrfMethodContext* ctx ) {
511 OSRF_METHOD_VERIFY_CONTEXT(ctx);
513 dbi_result result = dbi_conn_query(writehandle, "START TRANSACTION;");
515 osrfLogError(OSRF_LOG_MARK, "%s: Error starting transaction", MODULENAME );
516 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error starting transaction" );
519 jsonObject* ret = jsonNewObject(ctx->session->session_id);
520 osrfAppRespondComplete( ctx, ret );
523 if (!ctx->session->userData) {
524 ctx->session->userData = osrfNewHash();
525 ((osrfHash*)ctx->session->userData)->freeItem = &sessionDataFree;
528 osrfHashSet( (osrfHash*)ctx->session->userData, strdup( ctx->session->session_id ), "xact_id" );
529 ctx->session->userDataFree = &userDataFree;
535 int setSavepoint ( osrfMethodContext* ctx ) {
536 OSRF_METHOD_VERIFY_CONTEXT(ctx);
538 char* spName = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
540 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
541 osrfAppSessionStatus(
543 OSRF_STATUS_INTERNALSERVERERROR,
544 "osrfMethodException",
546 "No active transaction -- required for savepoints"
551 dbi_result result = dbi_conn_queryf(writehandle, "SAVEPOINT \"%s\";", spName);
555 "%s: Error creating savepoint %s in transaction %s",
558 osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )
560 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error creating savepoint" );
563 jsonObject* ret = jsonNewObject(spName);
564 osrfAppRespondComplete( ctx, ret );
570 int releaseSavepoint ( osrfMethodContext* ctx ) {
571 OSRF_METHOD_VERIFY_CONTEXT(ctx);
573 char* spName = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
575 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
576 osrfAppSessionStatus(
578 OSRF_STATUS_INTERNALSERVERERROR,
579 "osrfMethodException",
581 "No active transaction -- required for savepoints"
586 dbi_result result = dbi_conn_queryf(writehandle, "RELEASE SAVEPOINT \"%s\";", spName);
590 "%s: Error releasing savepoint %s in transaction %s",
593 osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )
595 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error releasing savepoint" );
598 jsonObject* ret = jsonNewObject(spName);
599 osrfAppRespondComplete( ctx, ret );
605 int rollbackSavepoint ( osrfMethodContext* ctx ) {
606 OSRF_METHOD_VERIFY_CONTEXT(ctx);
608 char* spName = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
610 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
611 osrfAppSessionStatus(
613 OSRF_STATUS_INTERNALSERVERERROR,
614 "osrfMethodException",
616 "No active transaction -- required for savepoints"
621 dbi_result result = dbi_conn_queryf(writehandle, "ROLLBACK TO SAVEPOINT \"%s\";", spName);
625 "%s: Error rolling back savepoint %s in transaction %s",
628 osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )
630 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error rolling back savepoint" );
633 jsonObject* ret = jsonNewObject(spName);
634 osrfAppRespondComplete( ctx, ret );
640 int commitTransaction ( osrfMethodContext* ctx ) {
641 OSRF_METHOD_VERIFY_CONTEXT(ctx);
643 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
644 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "No active transaction to commit" );
648 dbi_result result = dbi_conn_query(writehandle, "COMMIT;");
650 osrfLogError(OSRF_LOG_MARK, "%s: Error committing transaction", MODULENAME );
651 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error committing transaction" );
654 osrfHashRemove(ctx->session->userData, "xact_id");
655 jsonObject* ret = jsonNewObject(ctx->session->session_id);
656 osrfAppRespondComplete( ctx, ret );
662 int rollbackTransaction ( osrfMethodContext* ctx ) {
663 OSRF_METHOD_VERIFY_CONTEXT(ctx);
665 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
666 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "No active transaction to roll back" );
670 dbi_result result = dbi_conn_query(writehandle, "ROLLBACK;");
672 osrfLogError(OSRF_LOG_MARK, "%s: Error rolling back transaction", MODULENAME );
673 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error rolling back transaction" );
676 osrfHashRemove(ctx->session->userData, "xact_id");
677 jsonObject* ret = jsonNewObject(ctx->session->session_id);
678 osrfAppRespondComplete( ctx, ret );
684 int dispatchCRUDMethod ( osrfMethodContext* ctx ) {
685 OSRF_METHOD_VERIFY_CONTEXT(ctx);
687 osrfHash* meta = (osrfHash*) ctx->method->userData;
688 osrfHash* class_obj = osrfHashGet( meta, "class" );
692 jsonObject * obj = NULL;
693 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "create"))
694 obj = doCreate(ctx, &err);
696 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "retrieve"))
697 obj = doRetrieve(ctx, &err);
699 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "update"))
700 obj = doUpdate(ctx, &err);
702 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "delete"))
703 obj = doDelete(ctx, &err);
705 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "search")) {
707 obj = doSearch(ctx, class_obj, ctx->params, &err);
711 jsonObjectIterator* itr = jsonNewObjectIterator( obj );
712 while ((cur = jsonObjectIteratorNext( itr ))) {
713 osrfAppRespond( ctx, jsonObjectClone(cur->item) );
715 jsonObjectIteratorFree(itr);
716 osrfAppRespondComplete( ctx, NULL );
718 } else if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "id_list")) {
720 jsonObject* _p = jsonObjectClone( ctx->params );
721 if (jsonObjectGetIndex( _p, 1 )) {
722 jsonObjectRemoveKey( jsonObjectGetIndex( _p, 1 ), "flesh" );
723 jsonObjectRemoveKey( jsonObjectGetIndex( _p, 1 ), "flesh_columns" );
725 jsonObjectSetIndex( _p, 1, jsonParseString("{}") );
728 growing_buffer* sel_list = buffer_init(16);
729 buffer_fadd(sel_list, "{ \"%s\":[\"%s\"] }", osrfHashGet( class_obj, "classname" ), osrfHashGet( class_obj, "primarykey" ));
730 char* _s = buffer_data(sel_list);
731 buffer_free(sel_list);
733 jsonObjectSetKey( jsonObjectGetIndex( _p, 1 ), "select", jsonParseString(_s) );
734 osrfLogDebug(OSRF_LOG_MARK, "%s: Select qualifer set to [%s]", MODULENAME, _s);
737 obj = doSearch(ctx, class_obj, _p, &err);
741 jsonObjectIterator* itr = jsonNewObjectIterator( obj );
742 while ((cur = jsonObjectIteratorNext( itr ))) {
751 osrfHashGet( class_obj, "fields" ),
752 osrfHashGet( class_obj, "primarykey")
761 jsonObjectIteratorFree(itr);
762 osrfAppRespondComplete( ctx, NULL );
765 osrfAppRespondComplete( ctx, obj );
773 int verifyObjectClass ( osrfMethodContext* ctx, jsonObject* param ) {
775 osrfHash* meta = (osrfHash*) ctx->method->userData;
776 osrfHash* class = osrfHashGet( meta, "class" );
778 if ((strcmp( osrfHashGet(class, "classname"), param->classname ))) {
780 growing_buffer* msg = buffer_init(128);
783 "%s: %s method for type %s was passed a %s",
785 osrfHashGet(meta, "methodtype"),
786 osrfHashGet(class, "classname"),
790 char* m = buffer_data(msg);
791 osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException", ctx->request, m );
801 jsonObject* doCreate(osrfMethodContext* ctx, int* err ) {
803 osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
804 jsonObject* target = jsonObjectGetIndex( ctx->params, 0 );
806 if (!verifyObjectClass(ctx, target)) {
811 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
812 osrfAppSessionStatus(
814 OSRF_STATUS_BADREQUEST,
815 "osrfMethodException",
817 "No active transaction -- required for CREATE"
823 dbhandle = writehandle;
825 osrfHash* fields = osrfHashGet(meta, "fields");
826 char* pkey = osrfHashGet(meta, "primarykey");
827 char* seq = osrfHashGet(meta, "sequence");
829 growing_buffer* table_buf = buffer_init(128);
830 growing_buffer* col_buf = buffer_init(128);
831 growing_buffer* val_buf = buffer_init(128);
833 buffer_fadd(table_buf,"INSERT INTO %s", osrfHashGet(meta, "tablename"));
834 buffer_add(col_buf,"(");
835 buffer_add(val_buf,"VALUES (");
840 osrfStringArray* field_list = osrfHashKeys( fields );
841 while ( (field_name = osrfStringArrayGetString(field_list, i++)) ) {
843 osrfHash* field = osrfHashGet( fields, field_name );
845 if(!( strcmp( osrfHashGet(osrfHashGet(fields,field_name), "virtual"), "true" ) )) continue;
847 int pos = atoi(osrfHashGet(field, "array_position"));
848 char* value = jsonObjectToSimpleString( jsonObjectGetIndex( target, pos ) );
853 buffer_add(col_buf, ",");
854 buffer_add(val_buf, ",");
857 buffer_add(col_buf, field_name);
859 if (jsonObjectGetIndex(target, pos)->type == JSON_NULL) {
860 buffer_add( val_buf, "DEFAULT" );
862 } else if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
863 if ( !strcmp(osrfHashGet(field, "datatype"), "INT8") ) {
864 buffer_fadd( val_buf, "%lld", atol(value) );
866 } else if ( !strcmp(osrfHashGet(field, "datatype"), "INT") ) {
867 buffer_fadd( val_buf, "%ld", atoll(value) );
869 } else if ( !strcmp(osrfHashGet(field, "datatype"), "NUMERIC") ) {
870 buffer_fadd( val_buf, "%f", atof(value) );
873 if ( dbi_conn_quote_string(writehandle, &value) ) {
874 buffer_fadd( val_buf, "%s", value );
877 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting string [%s]", MODULENAME, value);
878 osrfAppSessionStatus(
880 OSRF_STATUS_INTERNALSERVERERROR,
881 "osrfMethodException",
883 "Error quoting string -- please see the error log for more details"
886 buffer_free(table_buf);
887 buffer_free(col_buf);
888 buffer_free(val_buf);
898 buffer_add(col_buf,")");
899 buffer_add(val_buf,")");
901 growing_buffer* sql = buffer_init(128);
905 buffer_data(table_buf),
906 buffer_data(col_buf),
909 buffer_free(table_buf);
910 buffer_free(col_buf);
911 buffer_free(val_buf);
913 char* query = buffer_data(sql);
916 osrfLogDebug(OSRF_LOG_MARK, "%s: Insert SQL [%s]", MODULENAME, query);
919 dbi_result result = dbi_conn_query(writehandle, query);
921 jsonObject* obj = NULL;
924 obj = jsonNewObject(NULL);
927 "%s ERROR inserting %s object using query [%s]",
929 osrfHashGet(meta, "fieldmapper"),
932 osrfAppSessionStatus(
934 OSRF_STATUS_INTERNALSERVERERROR,
935 "osrfMethodException",
937 "INSERT error -- please see the error log for more details"
942 int pos = atoi(osrfHashGet( osrfHashGet(fields, pkey), "array_position" ));
943 char* id = jsonObjectToSimpleString(jsonObjectGetIndex(target, pos));
945 unsigned long long new_id = dbi_conn_sequence_last(writehandle, seq);
946 growing_buffer* _id = buffer_init(10);
947 buffer_fadd(_id, "%lld", new_id);
948 id = buffer_data(_id);
952 jsonObject* fake_params = jsonParseString("[]");
953 jsonObjectPush(fake_params, jsonParseString("{}"));
956 jsonObjectGetIndex(fake_params, 0),
957 osrfHashGet(meta, "primarykey"),
961 jsonObject* list = doSearch( ctx,meta, fake_params, err);
964 jsonObjectFree( fake_params );
967 obj = jsonObjectClone( jsonObjectGetIndex(list, 0) );
970 jsonObjectFree( list );
971 jsonObjectFree( fake_params );
982 jsonObject* doRetrieve(osrfMethodContext* ctx, int* err ) {
984 osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
988 char* id = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
989 jsonObject* order_hash = jsonObjectGetIndex(ctx->params, 1);
993 "%s retrieving %s object with id %s",
995 osrfHashGet(meta, "fieldmapper"),
999 jsonObject* fake_params = jsonParseString("[]");
1000 jsonObjectPush(fake_params, jsonParseString("{}"));
1003 jsonObjectGetIndex(fake_params, 0),
1004 osrfHashGet(meta, "primarykey"),
1008 if (order_hash) jsonObjectPush(fake_params, jsonObjectClone(order_hash) );
1010 jsonObject* list = doSearch( ctx,meta, fake_params, err);
1013 jsonObjectFree( fake_params );
1017 obj = jsonObjectClone( jsonObjectGetIndex(list, 0) );
1019 jsonObjectFree( list );
1020 jsonObjectFree( fake_params );
1025 char* jsonNumberToDBString ( osrfHash* field, jsonObject* value ) {
1026 growing_buffer* val_buf = buffer_init(32);
1028 if ( !strncmp(osrfHashGet(field, "datatype"), "INT", 3) ) {
1029 if (value->type == JSON_NUMBER) buffer_fadd( val_buf, "%ld", (long)jsonObjectGetNumber(value) );
1030 else buffer_fadd( val_buf, "%ld", atol(jsonObjectToSimpleString(value)) );
1032 } else if ( !strcmp(osrfHashGet(field, "datatype"), "NUMERIC") ) {
1033 if (value->type == JSON_NUMBER) buffer_fadd( val_buf, "%f", jsonObjectGetNumber(value) );
1034 else buffer_fadd( val_buf, "%f", atof(jsonObjectToSimpleString(value)) );
1037 char* pred = buffer_data(val_buf);
1038 buffer_free(val_buf);
1043 char* searchINPredicate (osrfHash* field, jsonObject* node) {
1044 growing_buffer* sql_buf = buffer_init(32);
1049 osrfHashGet(field, "name")
1052 int in_item_index = 0;
1053 int in_item_first = 1;
1054 jsonObject* in_item;
1055 while ( (in_item = jsonObjectGetIndex(node, in_item_index++)) ) {
1060 buffer_add(sql_buf, ", ");
1062 if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1063 char* val = jsonNumberToDBString( field, in_item );
1064 buffer_fadd( sql_buf, "%s", val );
1068 char* key_string = jsonObjectToSimpleString(in_item);
1069 if ( dbi_conn_quote_string(dbhandle, &key_string) ) {
1070 buffer_fadd( sql_buf, "%s", key_string );
1073 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key string [%s]", MODULENAME, key_string);
1075 buffer_free(sql_buf);
1086 char* pred = buffer_data(sql_buf);
1087 buffer_free(sql_buf);
1092 char* searchValueTransform( jsonObject* array ) {
1093 growing_buffer* sql_buf = buffer_init(32);
1096 int func_item_index = 0;
1097 int func_item_first = 2;
1098 jsonObject* func_item;
1099 while ( (func_item = jsonObjectGetIndex(array, func_item_index++)) ) {
1101 val = jsonObjectToSimpleString(func_item);
1103 if (func_item_first == 2) {
1104 buffer_fadd(sql_buf, "%s( ", val);
1110 if (func_item_first)
1113 buffer_add(sql_buf, ", ");
1115 if ( dbi_conn_quote_string(dbhandle, &val) ) {
1116 buffer_fadd( sql_buf, "%s", val );
1119 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key string [%s]", MODULENAME, val);
1121 buffer_free(sql_buf);
1131 char* pred = buffer_data(sql_buf);
1132 buffer_free(sql_buf);
1137 char* searchFunctionPredicate (osrfHash* field, jsonObjectNode* node) {
1138 growing_buffer* sql_buf = buffer_init(32);
1140 char* val = searchValueTransform(node->item);
1145 osrfHashGet(field, "name"),
1150 char* pred = buffer_data(sql_buf);
1151 buffer_free(sql_buf);
1157 char* searchFieldTransformPredicate (osrfHash* field, jsonObjectNode* node) {
1158 growing_buffer* sql_buf = buffer_init(32);
1160 char* field_transform = jsonObjectToSimpleString( jsonObjectGetKey( node->item, "transform" ) );
1163 if (jsonObjectGetKey( node->item, "value" )->type == JSON_ARRAY) {
1164 value = searchValueTransform(jsonObjectGetKey( node->item, "value" ));
1165 } else if (jsonObjectGetKey( node->item, "value" )->type != JSON_NULL) {
1166 if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1167 value = jsonNumberToDBString( field, jsonObjectGetKey( node->item, "value" ) );
1169 value = jsonObjectToSimpleString(jsonObjectGetKey( node->item, "value" ));
1170 if ( !dbi_conn_quote_string(dbhandle, &value) ) {
1171 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key string [%s]", MODULENAME, value);
1182 osrfHashGet(field, "name"),
1187 char* pred = buffer_data(sql_buf);
1188 buffer_free(sql_buf);
1193 char* searchSimplePredicate (const char* orig_op, osrfHash* field, jsonObject* node) {
1197 if (node->type != JSON_NULL) {
1198 if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1199 val = jsonNumberToDBString( field, node );
1201 val = jsonObjectToSimpleString(node);
1205 char* pred = searchWriteSimplePredicate( field, osrfHashGet(field, "name"), orig_op, val );
1212 char* searchWriteSimplePredicate ( osrfHash* field, const char* left, const char* orig_op, const char* right ) {
1216 if (right == NULL) {
1217 val = strdup("NULL");
1219 if (strcmp( orig_op, "=" ))
1220 op = strdup("IS NOT");
1224 } else if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1225 val = strdup(right);
1226 op = strdup(orig_op);
1229 val = strdup(right);
1230 if ( !dbi_conn_quote_string(dbhandle, &val) ) {
1231 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key string [%s]", MODULENAME, val);
1235 op = strdup(orig_op);
1238 growing_buffer* sql_buf = buffer_init(16);
1239 buffer_fadd( sql_buf, "%s %s %s", left, op, val );
1243 char* pred = buffer_data(sql_buf);
1244 buffer_free(sql_buf);
1250 char* searchBETWEENPredicate (osrfHash* field, jsonObject* node) {
1255 if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1256 x_string = jsonNumberToDBString(field, jsonObjectGetIndex(node,0));
1257 y_string = jsonNumberToDBString(field, jsonObjectGetIndex(node,1));
1260 x_string = jsonObjectToSimpleString(jsonObjectGetIndex(node,0));
1261 y_string = jsonObjectToSimpleString(jsonObjectGetIndex(node,1));
1262 if ( !(dbi_conn_quote_string(dbhandle, &x_string) && dbi_conn_quote_string(dbhandle, &y_string)) ) {
1263 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key strings [%s] and [%s]", MODULENAME, x_string, y_string);
1270 growing_buffer* sql_buf = buffer_init(32);
1271 buffer_fadd( sql_buf, "%s BETWEEN %s AND %s", osrfHashGet(field, "name"), x_string, y_string );
1275 char* pred = buffer_data(sql_buf);
1276 buffer_free(sql_buf);
1281 char* searchPredicate ( osrfHash* field, jsonObject* node ) {
1284 if (node->type == JSON_ARRAY) { // equality IN search
1285 pred = searchINPredicate( field, node );
1286 } else if (node->type == JSON_HASH) { // non-equality search
1287 jsonObjectNode* pred_node;
1288 jsonObjectIterator* pred_itr = jsonNewObjectIterator( node );
1289 while ( (pred_node = jsonObjectIteratorNext( pred_itr )) ) {
1290 if ( !(strcasecmp( pred_node->key,"between" )) )
1291 pred = searchBETWEENPredicate( field, pred_node->item );
1292 else if ( !(strcasecmp( pred_node->key,"in" )) )
1293 pred = searchINPredicate( field, pred_node->item );
1294 else if ( pred_node->item->type == JSON_ARRAY )
1295 pred = searchFunctionPredicate( field, pred_node );
1296 else if ( pred_node->item->type == JSON_HASH )
1297 pred = searchFieldTransformPredicate( field, pred_node );
1299 pred = searchSimplePredicate( pred_node->key, field, pred_node->item );
1303 } else if (node->type == JSON_NULL) { // IS NULL search
1304 growing_buffer* _p = buffer_init(16);
1308 osrfHashGet(field, "name")
1310 pred = buffer_data(_p);
1312 } else { // equality search
1313 pred = searchSimplePredicate( "=", field, node );
1320 jsonObject* doSearch(osrfMethodContext* ctx, osrfHash* meta, jsonObject* params, int* err ) {
1323 dbhandle = writehandle;
1325 osrfHash* links = osrfHashGet(meta, "links");
1326 osrfHash* fields = osrfHashGet(meta, "fields");
1327 char* core_class = osrfHashGet(meta, "classname");
1329 jsonObjectNode* node = NULL;
1330 jsonObjectNode* snode = NULL;
1333 jsonObject* search_hash = jsonObjectGetIndex(params, 0);
1334 jsonObject* order_hash = jsonObjectGetIndex(params, 1);
1336 growing_buffer* sql_buf = buffer_init(128);
1337 buffer_add(sql_buf, "SELECT");
1340 if ( (_tmp = jsonObjectGetKey( order_hash, "select" )) ) {
1342 jsonObjectIterator* class_itr = jsonNewObjectIterator( _tmp );
1343 while ( (snode = jsonObjectIteratorNext( class_itr )) ) {
1345 osrfHash* idlClass = osrfHashGet( idlHash, snode->key );
1346 if (!idlClass) continue;
1347 char* cname = osrfHashGet(idlClass, "classname");
1349 jsonObjectIterator* select_itr = jsonNewObjectIterator( snode->item );
1350 while ( (node = jsonObjectIteratorNext( select_itr )) ) {
1351 osrfHash* field = osrfHashGet( osrfHashGet( idlClass, "fields" ), jsonObjectToSimpleString(node->item) );
1352 char* fname = osrfHashGet(field, "name");
1354 if (!field) continue;
1359 buffer_add(sql_buf, ",");
1362 buffer_fadd(sql_buf, " \"%s\".%s", cname, fname, cname, fname);
1366 buffer_add(sql_buf, " *");
1369 buffer_fadd(sql_buf, " FROM %s AS \"%s\" WHERE ", osrfHashGet(meta, "tablename"), core_class );
1374 jsonObjectIterator* search_itr = jsonNewObjectIterator( search_hash );
1375 while ( (node = jsonObjectIteratorNext( search_itr )) ) {
1376 osrfHash* field = osrfHashGet( fields, node->key );
1378 if (!field) continue;
1383 buffer_add(sql_buf, " AND ");
1386 pred = searchPredicate( field, node->item);
1387 buffer_fadd( sql_buf, "%s", pred );
1391 jsonObjectIteratorFree(search_itr);
1395 if ( (_tmp = jsonObjectGetKey( jsonObjectGetKey( order_hash, "order_by" ), core_class ) ) ){
1396 string = jsonObjectToSimpleString(_tmp);
1405 if ( (_tmp = jsonObjectGetKey( order_hash, "limit" )) ){
1406 string = jsonObjectToSimpleString(_tmp);
1415 _tmp = jsonObjectGetKey( order_hash, "offset" );
1417 string = jsonObjectToSimpleString(_tmp);
1427 buffer_add(sql_buf, ";");
1429 char* sql = buffer_data(sql_buf);
1430 buffer_free(sql_buf);
1432 osrfLogDebug(OSRF_LOG_MARK, "%s SQL = %s", MODULENAME, sql);
1433 dbi_result result = dbi_conn_query(dbhandle, sql);
1435 jsonObject* res_list = jsonParseString("[]");
1437 osrfLogDebug(OSRF_LOG_MARK, "Query returned with no errors");
1439 if (dbi_result_first_row(result)) {
1440 /* JSONify the result */
1441 osrfLogDebug(OSRF_LOG_MARK, "Query returned at least one row");
1443 obj = oilsMakeJSONFromResult( result, meta );
1444 jsonObjectPush(res_list, obj);
1445 } while (dbi_result_next_row(result));
1447 osrfLogDebug(OSRF_LOG_MARK, "%s returned no results for query %s", MODULENAME, sql);
1450 /* clean up the query */
1451 dbi_result_free(result);
1454 osrfLogError(OSRF_LOG_MARK, "%s: Error retrieving %s with query [%s]", MODULENAME, osrfHashGet(meta, "fieldmapper"), sql);
1455 osrfAppSessionStatus(
1457 OSRF_STATUS_INTERNALSERVERERROR,
1458 "osrfMethodException",
1460 "Severe query error -- see error log for more details"
1464 jsonObjectFree(res_list);
1471 if (res_list->size && order_hash) {
1472 _tmp = jsonObjectGetKey( order_hash, "flesh" );
1474 int x = (int)jsonObjectGetNumber(_tmp);
1476 jsonObject* flesh_blob = NULL;
1477 if ((flesh_blob = jsonObjectGetKey( order_hash, "flesh_fields" )) && x > 0) {
1479 flesh_blob = jsonObjectClone( flesh_blob );
1480 jsonObject* flesh_fields = jsonObjectGetKey( flesh_blob, core_class );
1482 osrfStringArray* link_fields = NULL;
1485 if (flesh_fields->size == 1) {
1486 char* _t = jsonObjectToSimpleString( jsonObjectGetIndex( flesh_fields, 0 ) );
1487 if (!strcmp(_t,"*")) link_fields = osrfHashKeys( links );
1493 link_fields = osrfNewStringArray(1);
1494 jsonObjectIterator* _i = jsonNewObjectIterator( flesh_fields );
1495 while ((_f = jsonObjectIteratorNext( _i ))) {
1496 osrfStringArrayAdd( link_fields, jsonObjectToSimpleString( _f->item ) );
1501 jsonObjectNode* cur;
1502 jsonObjectIterator* itr = jsonNewObjectIterator( res_list );
1503 while ((cur = jsonObjectIteratorNext( itr ))) {
1508 while ( (link_field = osrfStringArrayGetString(link_fields, i++)) ) {
1510 osrfLogDebug(OSRF_LOG_MARK, "Starting to flesh %s", link_field);
1512 osrfHash* kid_link = osrfHashGet(links, link_field);
1513 if (!kid_link) continue;
1515 osrfHash* field = osrfHashGet(fields, link_field);
1516 if (!field) continue;
1518 osrfHash* value_field = field;
1520 osrfHash* kid_idl = osrfHashGet(idlHash, osrfHashGet(kid_link, "class"));
1521 if (!kid_idl) continue;
1523 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "has_many" ))) { // has_many
1524 value_field = osrfHashGet( fields, osrfHashGet(meta, "primarykey") );
1527 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "might_have" ))) { // might_have
1528 value_field = osrfHashGet( fields, osrfHashGet(meta, "primarykey") );
1531 osrfStringArray* link_map = osrfHashGet( kid_link, "map" );
1533 if (link_map->size > 0) {
1534 jsonObject* _kid_key = jsonParseString("[]");
1537 jsonNewObject( osrfStringArrayGetString( link_map, 0 ) )
1542 osrfHashGet(kid_link, "class"),
1549 "Link field: %s, remote class: %s, fkey: %s, reltype: %s",
1550 osrfHashGet(kid_link, "field"),
1551 osrfHashGet(kid_link, "class"),
1552 osrfHashGet(kid_link, "key"),
1553 osrfHashGet(kid_link, "reltype")
1556 jsonObject* fake_params = jsonParseString("[]");
1557 jsonObjectPush(fake_params, jsonParseString("{}")); // search hash
1558 jsonObjectPush(fake_params, jsonParseString("{}")); // order/flesh hash
1560 osrfLogDebug(OSRF_LOG_MARK, "Creating dummy params object...");
1563 jsonObjectToSimpleString(
1566 atoi( osrfHashGet(value_field, "array_position") )
1571 osrfLogDebug(OSRF_LOG_MARK, "Nothing to search for!");
1576 jsonObjectGetIndex(fake_params, 0),
1577 osrfHashGet(kid_link, "key"),
1578 jsonNewObject( search_key )
1585 jsonObjectGetIndex(fake_params, 1),
1587 jsonNewNumberObject( (double)(x - 1 + link_map->size) )
1591 jsonObjectSetKey( jsonObjectGetIndex(fake_params, 1), "flesh_fields", jsonObjectClone(flesh_blob) );
1593 if (jsonObjectGetKey(order_hash, "order_by")) {
1595 jsonObjectGetIndex(fake_params, 1),
1597 jsonObjectClone(jsonObjectGetKey(order_hash, "order_by"))
1601 jsonObject* kids = doSearch(ctx, kid_idl, fake_params, err);
1604 jsonObjectFree( fake_params );
1605 osrfStringArrayFree(link_fields);
1606 jsonObjectIteratorFree(itr);
1607 jsonObjectFree(res_list);
1611 osrfLogDebug(OSRF_LOG_MARK, "Search for %s return %d linked objects", osrfHashGet(kid_link, "class"), kids->size);
1613 jsonObject* X = NULL;
1614 if ( link_map->size > 0 && kids->size > 0 ) {
1616 kids = jsonParseString("[]");
1618 jsonObjectNode* _k_node;
1619 jsonObjectIterator* _k = jsonNewObjectIterator( X );
1620 while ((_k_node = jsonObjectIteratorNext( _k ))) {
1626 (unsigned long)atoi(
1632 osrfHashGet(kid_link, "class")
1636 osrfStringArrayGetString( link_map, 0 )
1647 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "has_a" ))) {
1648 osrfLogDebug(OSRF_LOG_MARK, "Storing fleshed objects in %s", osrfHashGet(kid_link, "field"));
1651 (unsigned long)atoi( osrfHashGet( field, "array_position" ) ),
1652 jsonObjectClone( jsonObjectGetIndex(kids, 0) )
1656 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "has_many" ))) { // has_many
1657 osrfLogDebug(OSRF_LOG_MARK, "Storing fleshed objects in %s", osrfHashGet(kid_link, "field"));
1660 (unsigned long)atoi( osrfHashGet( field, "array_position" ) ),
1661 jsonObjectClone( kids )
1666 jsonObjectFree(kids);
1670 jsonObjectFree( kids );
1671 jsonObjectFree( fake_params );
1673 osrfLogDebug(OSRF_LOG_MARK, "Fleshing of %s complete", osrfHashGet(kid_link, "field"));
1674 osrfLogDebug(OSRF_LOG_MARK, "%s", jsonObjectToJSON(cur->item));
1678 jsonObjectFree( flesh_blob );
1679 osrfStringArrayFree(link_fields);
1680 jsonObjectIteratorFree(itr);
1689 jsonObject* doUpdate(osrfMethodContext* ctx, int* err ) {
1691 osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
1692 jsonObject* target = jsonObjectGetIndex(ctx->params, 0);
1694 if (!verifyObjectClass(ctx, target)) {
1699 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
1700 osrfAppSessionStatus(
1702 OSRF_STATUS_BADREQUEST,
1703 "osrfMethodException",
1705 "No active transaction -- required for UPDATE"
1711 dbhandle = writehandle;
1713 char* pkey = osrfHashGet(meta, "primarykey");
1714 osrfHash* fields = osrfHashGet(meta, "fields");
1717 jsonObjectToSimpleString(
1720 atoi( osrfHashGet( osrfHashGet( fields, pkey ), "array_position" ) )
1726 "%s updating %s object with %s = %s",
1728 osrfHashGet(meta, "fieldmapper"),
1733 growing_buffer* sql = buffer_init(128);
1734 buffer_fadd(sql,"UPDATE %s SET", osrfHashGet(meta, "tablename"));
1739 osrfStringArray* field_list = osrfHashKeys( fields );
1740 while ( (field_name = osrfStringArrayGetString(field_list, i++)) ) {
1742 osrfHash* field = osrfHashGet( fields, field_name );
1744 if(!( strcmp( field_name, pkey ) )) continue;
1745 if(!( strcmp( osrfHashGet(osrfHashGet(fields,field_name), "virtual"), "true" ) )) continue;
1747 int pos = atoi(osrfHashGet(field, "array_position"));
1748 char* value = jsonObjectToSimpleString( jsonObjectGetIndex( target, pos ) );
1750 osrfLogDebug( OSRF_LOG_MARK, "Updating %s object with %s = %s", osrfHashGet(meta, "fieldmapper"), field_name, value);
1752 if (jsonObjectGetIndex(target, pos)->type == JSON_NULL) {
1753 if ( !(!( strcmp( osrfHashGet(meta, "classname"), "au" ) ) && !( strcmp( field_name, "passwd" ) )) ) { // arg at the special case!
1754 if (first) first = 0;
1755 else buffer_add(sql, ",");
1756 buffer_fadd( sql, " %s = NULL", field_name );
1759 } else if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1760 if (first) first = 0;
1761 else buffer_add(sql, ",");
1763 if ( !strncmp(osrfHashGet(field, "datatype"), "INT", (size_t)3) ) {
1764 buffer_fadd( sql, " %s = %ld", field_name, atol(value) );
1765 } else if ( !strcmp(osrfHashGet(field, "datatype"), "NUMERIC") ) {
1766 buffer_fadd( sql, " %s = %f", field_name, atof(value) );
1769 osrfLogDebug( OSRF_LOG_MARK, "%s is of type %s", field_name, osrfHashGet(field, "datatype"));
1772 if ( dbi_conn_quote_string(dbhandle, &value) ) {
1773 if (first) first = 0;
1774 else buffer_add(sql, ",");
1775 buffer_fadd( sql, " %s = %s", field_name, value );
1778 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting string [%s]", MODULENAME, value);
1779 osrfAppSessionStatus(
1781 OSRF_STATUS_INTERNALSERVERERROR,
1782 "osrfMethodException",
1784 "Error quoting string -- please see the error log for more details"
1798 jsonObject* obj = jsonParseString(id);
1800 if ( strcmp( osrfHashGet( osrfHashGet( osrfHashGet(meta, "fields"), pkey ), "primitive" ), "number" ) )
1801 dbi_conn_quote_string(dbhandle, &id);
1803 buffer_fadd( sql, " WHERE %s = %s;", pkey, id );
1805 char* query = buffer_data(sql);
1808 osrfLogDebug(OSRF_LOG_MARK, "%s: Update SQL [%s]", MODULENAME, query);
1810 dbi_result result = dbi_conn_query(dbhandle, query);
1814 jsonObjectFree(obj);
1815 obj = jsonNewObject(NULL);
1818 "%s ERROR updating %s object with %s = %s",
1820 osrfHashGet(meta, "fieldmapper"),
1831 jsonObject* doDelete(osrfMethodContext* ctx, int* err ) {
1833 osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
1835 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
1836 osrfAppSessionStatus(
1838 OSRF_STATUS_BADREQUEST,
1839 "osrfMethodException",
1841 "No active transaction -- required for DELETE"
1847 dbhandle = writehandle;
1851 char* pkey = osrfHashGet(meta, "primarykey");
1854 if (jsonObjectGetIndex(ctx->params, 0)->classname) {
1855 if (!verifyObjectClass(ctx, jsonObjectGetIndex( ctx->params, 0 ))) {
1860 id = jsonObjectToSimpleString(
1862 jsonObjectGetIndex(ctx->params, 0),
1863 atoi( osrfHashGet( osrfHashGet( osrfHashGet(meta, "fields"), pkey ), "array_position") )
1867 id = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
1872 "%s deleting %s object with %s = %s",
1874 osrfHashGet(meta, "fieldmapper"),
1879 obj = jsonParseString(id);
1881 if ( strcmp( osrfHashGet( osrfHashGet( osrfHashGet(meta, "fields"), pkey ), "primitive" ), "number" ) )
1882 dbi_conn_quote_string(writehandle, &id);
1884 dbi_result result = dbi_conn_queryf(writehandle, "DELETE FROM %s WHERE %s = %s;", osrfHashGet(meta, "tablename"), pkey, id);
1887 jsonObjectFree(obj);
1888 obj = jsonNewObject(NULL);
1891 "%s ERROR deleting %s object with %s = %s",
1893 osrfHashGet(meta, "fieldmapper"),
1906 jsonObject* oilsMakeJSONFromResult( dbi_result result, osrfHash* meta) {
1907 if(!(result && meta)) return jsonNULL;
1909 jsonObject* object = jsonParseString("[]");
1910 jsonObjectSetClass(object, osrfHashGet(meta, "classname"));
1912 osrfHash* fields = osrfHashGet(meta, "fields");
1914 osrfLogDebug(OSRF_LOG_MARK, "Setting object class to %s ", object->classname);
1918 char dt_string[256];
1922 int columnIndex = 1;
1924 unsigned short type;
1925 const char* columnName;
1927 /* cycle through the column list */
1928 while( (columnName = dbi_result_get_field_name(result, columnIndex++)) ) {
1930 osrfLogDebug(OSRF_LOG_MARK, "Looking for column named [%s]...", (char*)columnName);
1932 fmIndex = -1; // reset the position
1934 /* determine the field type and storage attributes */
1935 type = dbi_result_get_field_type(result, columnName);
1936 attr = dbi_result_get_field_attribs(result, columnName);
1938 /* fetch the fieldmapper index */
1939 if( (_f = osrfHashGet(fields, (char*)columnName)) ) {
1940 char* virt = (char*)osrfHashGet(_f, "virtual");
1941 char* pos = (char*)osrfHashGet(_f, "array_position");
1943 if ( !virt || !pos || !(strcmp( virt, "true" )) ) continue;
1945 fmIndex = atoi( pos );
1946 osrfLogDebug(OSRF_LOG_MARK, "... Found column at position [%s]...", pos);
1951 if (dbi_result_field_is_null(result, columnName)) {
1952 jsonObjectSetIndex( object, fmIndex, jsonNewObject(NULL) );
1957 case DBI_TYPE_INTEGER :
1959 if( attr & DBI_INTEGER_SIZE8 )
1960 jsonObjectSetIndex( object, fmIndex,
1961 jsonNewNumberObject(dbi_result_get_longlong(result, columnName)));
1963 jsonObjectSetIndex( object, fmIndex,
1964 jsonNewNumberObject(dbi_result_get_long(result, columnName)));
1968 case DBI_TYPE_DECIMAL :
1969 jsonObjectSetIndex( object, fmIndex,
1970 jsonNewNumberObject(dbi_result_get_double(result, columnName)));
1973 case DBI_TYPE_STRING :
1979 jsonNewObject( dbi_result_get_string(result, columnName) )
1984 case DBI_TYPE_DATETIME :
1986 memset(dt_string, '\0', 256);
1987 memset(&gmdt, '\0', sizeof(gmdt));
1988 memset(&_tmp_dt, '\0', sizeof(_tmp_dt));
1990 _tmp_dt = dbi_result_get_datetime(result, columnName);
1992 localtime_r( &_tmp_dt, &gmdt );
1994 if (!(attr & DBI_DATETIME_DATE)) {
1995 strftime(dt_string, 255, "%T", &gmdt);
1996 } else if (!(attr & DBI_DATETIME_TIME)) {
1997 strftime(dt_string, 255, "%F", &gmdt);
1999 strftime(dt_string, 255, "%FT%T%z", &gmdt);
2002 jsonObjectSetIndex( object, fmIndex, jsonNewObject(dt_string) );
2006 case DBI_TYPE_BINARY :
2007 osrfLogError( OSRF_LOG_MARK,
2008 "Can't do binary at column %s : index %d", columnName, columnIndex - 1);