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 beginTransaction ( osrfMethodContext* );
31 int commitTransaction ( osrfMethodContext* );
32 int rollbackTransaction ( osrfMethodContext* );
34 int dispatchCRUDMethod ( osrfMethodContext* );
35 jsonObject* doCreate ( osrfHash*, jsonObject* );
36 jsonObject* doRetrieve ( osrfHash*, jsonObject* );
37 jsonObject* doUpdate ( osrfHash*, jsonObject* );
38 jsonObject* doDelete ( osrfHash*, jsonObject* );
39 jsonObject* doSearch ( osrfHash*, jsonObject* );
40 jsonObject* oilsMakeJSONFromResult( dbi_result, osrfHash* );
43 void userDataFree( void* );
45 dbi_conn dbhandle; /* our db connection */
46 xmlDocPtr idlDoc = NULL; // parse and store the IDL here
49 /* parse and store the IDL here */
52 int osrfAppInitialize() {
54 idlHash = osrfNewHash();
55 osrfHash* usrData = NULL;
57 osrfLogInfo(OSRF_LOG_MARK, "Initializing the CStore Server...");
58 osrfLogInfo(OSRF_LOG_MARK, "Finding XML file...");
60 char * idl_filename = osrf_settings_host_value("/apps/%s/app_settings/IDL", MODULENAME);
61 osrfLogInfo(OSRF_LOG_MARK, "Found file:");
62 osrfLogInfo(OSRF_LOG_MARK, idl_filename);
64 osrfLogInfo(OSRF_LOG_MARK, "Parsing the IDL XML...");
65 idlDoc = xmlReadFile( idl_filename, NULL, XML_PARSE_XINCLUDE );
68 osrfLogError(OSRF_LOG_MARK, "Could not load or parse the IDL XML file!");
72 osrfLogInfo(OSRF_LOG_MARK, "...IDL XML parsed");
74 osrfStringArray* global_methods = osrfNewStringArray(1);
76 //osrfStringArrayAdd( global_methods, "create" );
77 osrfStringArrayAdd( global_methods, "retrieve" );
78 //osrfStringArrayAdd( global_methods, "update" );
79 //osrfStringArrayAdd( global_methods, "delete" );
80 osrfStringArrayAdd( global_methods, "search" );
82 xmlNodePtr docRoot = xmlDocGetRootElement(idlDoc);
83 xmlNodePtr kid = docRoot->children;
85 if (!strcmp( (char*)kid->name, "class" )) {
87 usrData = osrfNewHash();
88 osrfHashSet( usrData, xmlGetProp(kid, "id"), "classname");
89 osrfHashSet( usrData, xmlGetNsProp(kid, "tablename", PERSIST_NS), "tablename");
90 osrfHashSet( usrData, xmlGetNsProp(kid, "fieldmapper", OBJECT_NS), "fieldmapper");
92 osrfHashSet( idlHash, usrData, (char*)osrfHashGet(usrData, "classname") );
94 osrfLogInfo(OSRF_LOG_MARK, "Generating class methods for %s", osrfHashGet(usrData, "fieldmapper") );
97 osrfHash* links = osrfNewHash();
98 osrfHash* fields = osrfNewHash();
100 osrfHashSet( usrData, fields, "fields" );
101 osrfHashSet( usrData, links, "links" );
103 xmlNodePtr _cur = kid->children;
106 char* string_tmp = NULL;
108 if (!strcmp( (char*)_cur->name, "fields" )) {
110 if( (string_tmp = (char*)xmlGetNsProp(_cur, "primary", PERSIST_NS)) ) {
113 strdup( string_tmp ),
119 xmlNodePtr _f = _cur->children;
122 if (strcmp( (char*)_f->name, "field" )) {
127 _tmp = osrfNewHash();
129 if( (string_tmp = (char*)xmlGetNsProp(_f, "array_position", OBJECT_NS)) ) {
132 strdup( string_tmp ),
138 if( (string_tmp = (char*)xmlGetNsProp(_f, "virtual", PERSIST_NS)) ) {
141 strdup( string_tmp ),
147 if( (string_tmp = (char*)xmlGetProp(_f, "name")) ) {
150 strdup( string_tmp ),
155 osrfLogInfo(OSRF_LOG_MARK, "Found field %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
166 if (!strcmp( (char*)_cur->name, "links" )) {
167 xmlNodePtr _l = _cur->children;
170 if (strcmp( (char*)_l->name, "link" )) {
175 _tmp = osrfNewHash();
177 if( (string_tmp = (char*)xmlGetProp(_l, "reltype")) ) {
180 strdup( string_tmp ),
184 osrfLogInfo(OSRF_LOG_MARK, "Adding link with reltype %s", string_tmp );
187 if( (string_tmp = (char*)xmlGetProp(_l, "key")) ) {
190 strdup( string_tmp ),
194 osrfLogInfo(OSRF_LOG_MARK, "Link fkey is %s", string_tmp );
197 if( (string_tmp = (char*)xmlGetProp(_l, "class")) ) {
200 strdup( string_tmp ),
204 osrfLogInfo(OSRF_LOG_MARK, "Link fclass is %s", string_tmp );
207 osrfStringArray* map = osrfNewStringArray(0);
209 if( (string_tmp = (char*)xmlGetProp(_l, "map") )) {
210 char* map_list = strdup( string_tmp );
211 osrfLogInfo(OSRF_LOG_MARK, "Link mapping list is %s", string_tmp );
213 if (strlen( map_list ) > 0) {
215 char* _map_class = strtok_r(map_list, " ", &st_tmp);
216 osrfStringArrayAdd(map, strdup(_map_class));
218 while ((_map_class = strtok_r(NULL, " ", &st_tmp))) {
219 osrfStringArrayAdd(map, strdup(_map_class));
223 osrfHashSet( _tmp, map, "map");
225 if( (string_tmp = (char*)xmlGetProp(_l, "field")) ) {
228 strdup( string_tmp ),
239 osrfLogInfo(OSRF_LOG_MARK, "Found link %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
253 osrfHash* method_meta;
254 while ( (method_type = osrfStringArrayGetString(global_methods, i++)) ) {
256 if (!osrfHashGet(usrData, "fieldmapper")) continue;
258 method_meta = osrfNewHash();
259 osrfHashSet(method_meta, usrData, "class");
261 _fm = strdup( (char*)osrfHashGet(usrData, "fieldmapper") );
262 part = strtok_r(_fm, ":", &st_tmp);
264 growing_buffer* method_name = buffer_init(64);
265 buffer_fadd(method_name, "%s.direct.%s", MODULENAME, part);
267 while ((part = strtok_r(NULL, ":", &st_tmp))) {
268 buffer_fadd(method_name, ".%s", part);
270 buffer_fadd(method_name, ".%s", method_type);
273 char* method = buffer_data(method_name);
274 buffer_free(method_name);
277 osrfHashSet( method_meta, method, "methodname" );
278 osrfHashSet( method_meta, method_type, "methodtype" );
281 if (!(strcmp( method_type, "search" ))) {
282 flags = flags | OSRF_METHOD_STREAMING;
285 osrfAppRegisterExtendedMethod(
288 "dispatchCRUDMethod",
303 * Connects to the database
305 int osrfAppChildInit() {
307 osrfLogDebug(OSRF_LOG_MARK, "Attempting to initialize libdbi...");
308 dbi_initialize(NULL);
309 osrfLogDebug(OSRF_LOG_MARK, "... libdbi initialized.");
311 char* driver = osrf_settings_host_value("/apps/%s/app_settings/driver", MODULENAME);
312 char* user = osrf_settings_host_value("/apps/%s/app_settings/database/user", MODULENAME);
313 char* host = osrf_settings_host_value("/apps/%s/app_settings/database/host", MODULENAME);
314 char* port = osrf_settings_host_value("/apps/%s/app_settings/database/port", MODULENAME);
315 char* db = osrf_settings_host_value("/apps/%s/app_settings/database/db", MODULENAME);
316 char* pw = osrf_settings_host_value("/apps/%s/app_settings/database/pw", MODULENAME);
318 osrfLogDebug(OSRF_LOG_MARK, "Attempting to load the database driver [%s]...", driver);
319 dbhandle = dbi_conn_new(driver);
322 osrfLogError(OSRF_LOG_MARK, "Error loading database driver [%s]", driver);
325 osrfLogDebug(OSRF_LOG_MARK, "Database driver [%s] seems OK", driver);
327 osrfLogInfo(OSRF_LOG_MARK, "%s connecting to database. host=%s, "
328 "port=%s, user=%s, pw=%s, db=%s", MODULENAME, host, port, user, pw, db );
330 if(host) dbi_conn_set_option(dbhandle, "host", host );
331 if(port) dbi_conn_set_option_numeric( dbhandle, "port", atoi(port) );
332 if(user) dbi_conn_set_option(dbhandle, "username", user);
333 if(pw) dbi_conn_set_option(dbhandle, "password", pw );
334 if(db) dbi_conn_set_option(dbhandle, "dbname", db );
343 if (dbi_conn_connect(dbhandle) < 0) {
344 dbi_conn_error(dbhandle, &err);
345 osrfLogError( OSRF_LOG_MARK, "Error connecting to database: %s", err);
349 osrfLogInfo(OSRF_LOG_MARK, "%s successfully connected to the database", MODULENAME);
355 osrfStringArray* classes = osrfHashKeys( idlHash );
357 while ( (classname = osrfStringArrayGetString(classes, i++)) ) {
358 osrfHash* class = osrfHashGet( idlHash, classname );
359 osrfHash* fields = osrfHashGet( class, "fields" );
361 growing_buffer* sql_buf = buffer_init(32);
362 buffer_fadd( sql_buf, "SELECT * FROM %s WHERE 1=0;", osrfHashGet(class, "tablename") );
364 char* sql = buffer_data(sql_buf);
365 buffer_free(sql_buf);
366 osrfLogDebug(OSRF_LOG_MARK, "%s Investigatory SQL = %s", MODULENAME, sql);
368 dbi_result result = dbi_conn_query(dbhandle, sql);
374 const char* columnName;
376 while( (columnName = dbi_result_get_field_name(result, columnIndex++)) ) {
378 osrfLogDebug(OSRF_LOG_MARK, "Looking for column named [%s]...", (char*)columnName);
380 /* fetch the fieldmapper index */
381 if( (_f = osrfHashGet(fields, (char*)columnName)) ) {
383 osrfLogDebug(OSRF_LOG_MARK, "Found [%s] in IDL hash...", (char*)columnName);
385 /* determine the field type and storage attributes */
386 type = dbi_result_get_field_type(result, columnName);
387 attr = dbi_result_get_field_attribs(result, columnName);
391 case DBI_TYPE_INTEGER :
393 osrfHashSet(_f,"number", "primitive");
395 if( attr & DBI_INTEGER_SIZE8 )
396 osrfHashSet(_f,"INT8", "datatype");
398 osrfHashSet(_f,"INT", "datatype");
401 case DBI_TYPE_DECIMAL :
402 osrfHashSet(_f,"number", "primitive");
403 osrfHashSet(_f,"NUMERIC", "datatype");
406 case DBI_TYPE_STRING :
407 osrfHashSet(_f,"string", "primitive");
408 osrfHashSet(_f,"TEXT", "datatype");
411 case DBI_TYPE_DATETIME :
412 osrfHashSet(_f,"string", "primitive");
413 osrfHashSet(_f,"TIMESTAMP", "datatype");
416 case DBI_TYPE_BINARY :
417 osrfHashSet(_f,"string", "primitive");
418 osrfHashSet(_f,"BYTEA", "datatype");
423 "Setting [%s] to primitive [%s] and datatype [%s]...",
425 osrfHashGet(_f, "primitive"),
426 osrfHashGet(_f, "datatype")
430 dbi_result_free(result);
432 osrfLogDebug(OSRF_LOG_MARK, "No data found for class [%s]...", (char*)classname);
436 osrfStringArrayFree(classes);
441 void userDataFree( void* blob ) {
442 osrfHashFree( (osrfHash*)blob );
446 int beginTransaction ( osrfMethodContext* ctx ) {
447 OSRF_METHOD_VERIFY_CONTEXT(ctx);
449 dbi_result result = dbi_conn_query(dbhandle, "START TRANSACTION;");
451 osrfLogDebug(OSRF_LOG_MARK, "%s: Error starting transaction", MODULENAME );
452 osrfAppRequestRespondException( ctx->session, ctx->request, "%s: Error starting transaction", MODULENAME );
455 jsonObject* ret = jsonNewObject(ctx->session->session_id);
456 osrfAppRespondComplete( ctx, ret );
459 if (!ctx->session->userData) ctx->session->userData = osrfNewHash();
461 osrfHashSet( ctx->session->userData, strdup( ctx->session->session_id ), "xact_id" );
462 ctx->session->userDataFree = &userDataFree;
468 int commitTransaction ( osrfMethodContext* ctx ) {
469 OSRF_METHOD_VERIFY_CONTEXT(ctx);
471 dbi_result result = dbi_conn_query(dbhandle, "COMMIT;");
473 osrfLogDebug(OSRF_LOG_MARK, "%s: Error committing transaction", MODULENAME );
474 osrfAppRequestRespondException( ctx->session, ctx->request, "%s: Error committing transaction", MODULENAME );
477 jsonObject* ret = jsonNewObject(ctx->session->session_id);
478 osrfAppRespondComplete( ctx, ret );
484 int rollbackTransaction ( osrfMethodContext* ctx ) {
485 OSRF_METHOD_VERIFY_CONTEXT(ctx);
487 dbi_result result = dbi_conn_query(dbhandle, "ROLLBACK;");
489 osrfLogDebug(OSRF_LOG_MARK, "%s: Error rolling back transaction", MODULENAME );
490 osrfAppRequestRespondException( ctx->session, ctx->request, "%s: Error rolling back transaction", MODULENAME );
493 jsonObject* ret = jsonNewObject(ctx->session->session_id);
494 osrfAppRespondComplete( ctx, ret );
500 int dispatchCRUDMethod ( osrfMethodContext* ctx ) {
501 OSRF_METHOD_VERIFY_CONTEXT(ctx);
503 osrfHash* meta = (osrfHash*) ctx->method->userData;
504 osrfHash* class_obj = osrfHashGet( meta, "class" );
506 jsonObject * obj = NULL;
507 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "create"))
508 obj = doCreate(class_obj, ctx->params);
510 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "retrieve"))
511 obj = doRetrieve(class_obj, ctx->params);
513 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "update"))
514 obj = doUpdate(class_obj, ctx->params);
516 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "delete"))
517 obj = doDelete(class_obj, ctx->params);
519 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "search")) {
521 obj = doSearch(class_obj, ctx->params);
522 jsonObjectIterator* itr = jsonNewObjectIterator( obj );
523 while ((cur = jsonObjectIteratorNext( itr ))) {
524 osrfAppRespond( ctx, jsonObjectClone(cur->item) );
526 jsonObjectIteratorFree(itr);
527 osrfAppRespondComplete( ctx, NULL );
530 osrfAppRespondComplete( ctx, obj );
538 jsonObject* doCreate( osrfHash* meta, jsonObject* params ) { return NULL; }
540 jsonObject* doRetrieve( osrfHash* meta, jsonObject* params ) {
544 char* id = jsonObjectToSimpleString(jsonObjectGetIndex(params, 0));
545 jsonObject* order_hash = jsonObjectGetIndex(params, 1);
549 "%s retrieving %s object with id %s",
551 osrfHashGet(meta, "fieldmapper"),
555 jsonObject* fake_params = jsonParseString("[]");
556 jsonObjectPush(fake_params, jsonParseString("{}"));
559 jsonObjectGetIndex(fake_params, 0),
560 osrfHashGet(meta, "primarykey"),
564 if (order_hash) jsonObjectPush(fake_params, jsonObjectClone(order_hash) );
566 jsonObject* list = doSearch(meta, fake_params);
567 obj = jsonObjectClone( jsonObjectGetIndex(list, 0) );
569 jsonObjectFree( list );
570 jsonObjectFree( fake_params );
575 jsonObject* doSearch( osrfHash* meta, jsonObject* params ) {
579 jsonObject* search_hash = jsonObjectGetIndex(params, 0);
580 jsonObject* order_hash = jsonObjectGetIndex(params, 1);
582 growing_buffer* sql_buf = buffer_init(128);
583 buffer_fadd(sql_buf, "SELECT * FROM %s WHERE ", osrfHashGet(meta, "tablename") );
585 jsonObjectNode* node = NULL;
586 jsonObjectIterator* search_itr = jsonNewObjectIterator( search_hash );
589 while ( (node = jsonObjectIteratorNext( search_itr )) ) {
590 osrfHash* field = osrfHashGet( osrfHashGet(meta, "fields"), node->key );
592 if (!field) continue;
597 buffer_add(sql_buf, " AND ");
600 if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
604 osrfHashGet(field, "name"),
605 atoi( jsonObjectToSimpleString(node->item) )
608 char* key_string = jsonObjectToSimpleString(node->item);
609 if ( dbi_conn_quote_string(dbhandle, &key_string) ) {
613 osrfHashGet(field, "name"),
618 osrfLogDebug(OSRF_LOG_MARK, "%s: Error quoting key string [%s]", MODULENAME, key_string);
624 jsonObjectIteratorFree(search_itr);
628 _tmp = jsonObjectGetKey( order_hash, "order_by" );
630 string = jsonObjectToSimpleString(_tmp);
639 _tmp = jsonObjectGetKey( order_hash, "limit" );
641 string = jsonObjectToSimpleString(_tmp);
650 _tmp = jsonObjectGetKey( order_hash, "offset" );
652 string = jsonObjectToSimpleString(_tmp);
662 buffer_add(sql_buf, ";");
664 char* sql = buffer_data(sql_buf);
665 buffer_free(sql_buf);
667 osrfLogDebug(OSRF_LOG_MARK, "%s SQL = %s", MODULENAME, sql);
668 dbi_result result = dbi_conn_query(dbhandle, sql);
670 jsonObject* res_list = jsonParseString("[]");
672 osrfLogDebug(OSRF_LOG_MARK, "Query returned with no errors");
674 /* there should be one row at the most */
675 if (dbi_result_first_row(result)) {
676 /* JSONify the result */
677 osrfLogDebug(OSRF_LOG_MARK, "Query returned at least one row");
679 obj = oilsMakeJSONFromResult( result, meta );
680 jsonObjectPush(res_list, obj);
681 } while (dbi_result_next_row(result));
683 osrfLogDebug(OSRF_LOG_MARK, "%s returned no results for query %s", MODULENAME, sql);
686 /* clean up the query */
687 dbi_result_free(result);
690 osrfLogDebug(OSRF_LOG_MARK, "%s: Error retrieving %s with query [%s]", MODULENAME, osrfHashGet(meta, "fieldmapper"), sql);
696 _tmp = jsonObjectGetKey( order_hash, "flesh" );
698 double x = jsonObjectGetNumber(_tmp);
703 jsonObjectIterator* itr = jsonNewObjectIterator( res_list );
704 while ((cur = jsonObjectIteratorNext( itr ))) {
706 osrfHash* links = osrfHashGet(meta, "links");
707 osrfHash* fields = osrfHashGet(meta, "fields");
711 osrfStringArray* link_fields;
713 jsonObject* flesh_fields = jsonObjectGetKey( order_hash, "flesh_fields" );
716 jsonObjectIterator* _i = jsonNewObjectIterator( flesh_fields );
717 link_fields = osrfNewStringArray(1);
718 while ((_f = jsonObjectIteratorNext( _i ))) {
719 osrfStringArrayAdd( link_fields, jsonObjectToSimpleString( _f->item ) );
722 link_fields = osrfHashKeys( links );
725 while ( (link_field = osrfStringArrayGetString(link_fields, i++)) ) {
727 osrfLogDebug(OSRF_LOG_MARK, "Starting to flesh %s", link_field);
729 osrfHash* kid_link = osrfHashGet(links, link_field);
730 if (!kid_link) continue;
732 osrfHash* field = osrfHashGet(fields, link_field);
733 if (!field) continue;
735 osrfHash* value_field = field;
737 osrfHash* kid_idl = osrfHashGet(idlHash, osrfHashGet(kid_link, "class"));
738 if (!kid_idl) continue;
740 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "has_many" ))) { // has_many
741 value_field = osrfHashGet( fields, osrfHashGet(meta, "primarykey") );
744 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "might_have" ))) { // might_have
745 value_field = osrfHashGet( fields, osrfHashGet(meta, "primarykey") );
750 "Link field: %s, remote class: %s, fkey: %s, reltype: %s",
751 osrfHashGet(kid_link, "field"),
752 osrfHashGet(kid_link, "class"),
753 osrfHashGet(kid_link, "key"),
754 osrfHashGet(kid_link, "reltype")
757 jsonObject* fake_params = jsonParseString("[]");
758 jsonObjectPush(fake_params, jsonParseString("{}")); // search hash
759 jsonObjectPush(fake_params, jsonParseString("{}")); // order/flesh hash
761 osrfLogDebug(OSRF_LOG_MARK, "Creating dummy params object...");
764 jsonObjectToSimpleString(
767 atoi( osrfHashGet(value_field, "array_position") )
772 osrfLogDebug(OSRF_LOG_MARK, "Nothing to search for!");
777 jsonObjectGetIndex(fake_params, 0),
778 osrfHashGet(kid_link, "key"),
779 jsonNewObject( search_key )
786 jsonObjectGetIndex(fake_params, 1),
788 jsonNewNumberObject( (double)((int)x - 1) )
793 jsonObjectGetIndex(fake_params, 1),
795 jsonObjectClone( flesh_fields )
799 if (jsonObjectGetKey(order_hash, "order_by")) {
801 jsonObjectGetIndex(fake_params, 1),
803 jsonObjectClone(jsonObjectGetKey(order_hash, "order_by"))
807 jsonObject* kids = doSearch(kid_idl, fake_params);
809 osrfLogDebug(OSRF_LOG_MARK, "Search for %s return %d linked objects", osrfHashGet(kid_link, "class"), kids->size);
811 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "has_a" ))) {
812 osrfLogDebug(OSRF_LOG_MARK, "Storing fleshed objects in %s", osrfHashGet(kid_link, "field"));
815 (unsigned long)atoi( osrfHashGet( field, "array_position" ) ),
816 jsonObjectClone( jsonObjectGetIndex(kids, 0) )
818 jsonObjectFree( kids );
821 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "has_many" ))) { // has_many
822 osrfLogDebug(OSRF_LOG_MARK, "Storing fleshed objects in %s", osrfHashGet(kid_link, "field"));
825 (unsigned long)atoi( osrfHashGet( field, "array_position" ) ),
830 osrfLogDebug(OSRF_LOG_MARK, "Fleshing of %s complete", osrfHashGet(kid_link, "field"));
832 jsonObjectFree( fake_params );
834 if (flesh_fields) osrfStringArrayFree(link_fields);
836 jsonObjectIteratorFree(itr);
845 jsonObject* doUpdate( osrfHash* meta, jsonObject* params ) { return NULL; }
847 jsonObject* doDelete( osrfHash* meta, jsonObject* params ) { return NULL; }
850 jsonObject* oilsMakeJSONFromResult( dbi_result result, osrfHash* meta) {
851 if(!(result && meta)) return NULL;
853 jsonObject* object = jsonParseString("[]");
854 jsonObjectSetClass(object, osrfHashGet(meta, "classname"));
856 osrfHash* fields = osrfHashGet(meta, "fields");
858 osrfLogDebug(OSRF_LOG_MARK, "Setting object class to %s ", object->classname);
869 const char* columnName;
871 /* cycle through the column list */
872 while( (columnName = dbi_result_get_field_name(result, columnIndex++)) ) {
874 osrfLogDebug(OSRF_LOG_MARK, "Looking for column named [%s]...", (char*)columnName);
876 fmIndex = -1; // reset the position
878 /* determine the field type and storage attributes */
879 type = dbi_result_get_field_type(result, columnName);
880 attr = dbi_result_get_field_attribs(result, columnName);
882 /* fetch the fieldmapper index */
883 if( (_f = osrfHashGet(fields, (char*)columnName)) ) {
884 char* virt = (char*)osrfHashGet(_f, "virtual");
885 char* pos = (char*)osrfHashGet(_f, "array_position");
887 if ( !virt || !pos || !(strcmp( virt, "true" )) ) continue;
889 fmIndex = atoi( pos );
890 osrfLogDebug(OSRF_LOG_MARK, "... Found column at position [%s]...", pos);
893 if (dbi_result_field_is_null(result, columnName)) {
894 jsonObjectSetIndex( object, fmIndex, jsonNewObject(NULL) );
899 case DBI_TYPE_INTEGER :
901 if( attr & DBI_INTEGER_SIZE8 )
902 jsonObjectSetIndex( object, fmIndex,
903 jsonNewNumberObject(dbi_result_get_longlong(result, columnName)));
905 jsonObjectSetIndex( object, fmIndex,
906 jsonNewNumberObject(dbi_result_get_long(result, columnName)));
910 case DBI_TYPE_DECIMAL :
911 jsonObjectSetIndex( object, fmIndex,
912 jsonNewNumberObject(dbi_result_get_double(result, columnName)));
915 case DBI_TYPE_STRING :
921 jsonNewObject( dbi_result_get_string(result, columnName) )
926 case DBI_TYPE_DATETIME :
928 memset(dt_string, '\0', 256);
929 memset(&gmdt, '\0', sizeof(gmdt));
930 memset(&_tmp_dt, '\0', sizeof(_tmp_dt));
932 _tmp_dt = dbi_result_get_datetime(result, columnName);
934 localtime_r( &_tmp_dt, &gmdt );
936 if (!(attr & DBI_DATETIME_DATE)) {
937 strftime(dt_string, 255, "%T", &gmdt);
938 } else if (!(attr & DBI_DATETIME_TIME)) {
939 strftime(dt_string, 255, "%F", &gmdt);
941 /* XXX ARG! My eyes! The goggles, they do nothing! */
943 strftime(dt_string, 255, "%FT%T%z", &gmdt);
946 jsonObjectSetIndex( object, fmIndex, jsonNewObject(dt_string) );
950 case DBI_TYPE_BINARY :
951 osrfLogError( OSRF_LOG_MARK,
952 "Can't do binary at column %s : index %d", columnName, columnIndex - 1);