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* searchSimplePredicate ( const char*, osrfHash*, jsonObject* );
49 char* searchFunctionPredicate ( osrfHash*, jsonObjectNode* );
50 char* searchBETWEENPredicate ( osrfHash*, jsonObject* );
51 char* searchINPredicate ( osrfHash*, jsonObject* );
52 char* searchPredicate ( osrfHash*, jsonObject* );
54 void userDataFree( void* );
55 void sessionDataFree( char*, void* );
57 dbi_conn dbhandle; /* our db connection */
58 xmlDocPtr idlDoc = NULL; // parse and store the IDL here
59 jsonObject* jsonNULL = NULL; //
62 /* parse and store the IDL here */
65 int osrfAppInitialize() {
67 // first we register all the transaction and savepoint methods
68 osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.transaction.begin", "beginTransaction", "", 0, 0 );
69 osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.transaction.commit", "commitTransaction", "", 0, 0 );
70 osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.transaction.rollback", "rollbackTransaction", "", 0, 0 );
72 osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.savepoint.set", "setSavepoint", "", 1, 0 );
73 osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.savepoint.release", "releaseSavepoint", "", 1, 0 );
74 osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.savepoint.rollback", "rollbackSavepoint", "", 1, 0 );
77 idlHash = osrfNewHash();
78 osrfHash* usrData = NULL;
80 osrfLogInfo(OSRF_LOG_MARK, "Initializing the CStore Server...");
81 osrfLogInfo(OSRF_LOG_MARK, "Finding XML file...");
83 char * idl_filename = osrf_settings_host_value("/apps/%s/app_settings/IDL", MODULENAME);
84 osrfLogInfo(OSRF_LOG_MARK, "Found file:");
85 osrfLogInfo(OSRF_LOG_MARK, idl_filename);
87 osrfLogInfo(OSRF_LOG_MARK, "Parsing the IDL XML...");
88 idlDoc = xmlReadFile( idl_filename, NULL, XML_PARSE_XINCLUDE );
91 osrfLogError(OSRF_LOG_MARK, "Could not load or parse the IDL XML file!");
95 osrfLogInfo(OSRF_LOG_MARK, "...IDL XML parsed");
97 osrfStringArray* global_methods = osrfNewStringArray(1);
99 osrfStringArrayAdd( global_methods, "create" );
100 osrfStringArrayAdd( global_methods, "retrieve" );
101 osrfStringArrayAdd( global_methods, "update" );
102 osrfStringArrayAdd( global_methods, "delete" );
103 osrfStringArrayAdd( global_methods, "search" );
105 xmlNodePtr docRoot = xmlDocGetRootElement(idlDoc);
106 xmlNodePtr kid = docRoot->children;
108 if (!strcmp( (char*)kid->name, "class" )) {
110 usrData = osrfNewHash();
111 osrfHashSet( usrData, xmlGetProp(kid, "id"), "classname");
112 osrfHashSet( usrData, xmlGetNsProp(kid, "tablename", PERSIST_NS), "tablename");
113 osrfHashSet( usrData, xmlGetNsProp(kid, "fieldmapper", OBJECT_NS), "fieldmapper");
115 osrfHashSet( idlHash, usrData, (char*)osrfHashGet(usrData, "classname") );
117 osrfLogInfo(OSRF_LOG_MARK, "Generating class methods for %s", osrfHashGet(usrData, "fieldmapper") );
120 osrfHash* links = osrfNewHash();
121 osrfHash* fields = osrfNewHash();
123 osrfHashSet( usrData, fields, "fields" );
124 osrfHashSet( usrData, links, "links" );
126 xmlNodePtr _cur = kid->children;
129 char* string_tmp = NULL;
131 if (!strcmp( (char*)_cur->name, "fields" )) {
133 if( (string_tmp = (char*)xmlGetNsProp(_cur, "primary", PERSIST_NS)) ) {
136 strdup( string_tmp ),
142 if( (string_tmp = (char*)xmlGetNsProp(_cur, "sequence", PERSIST_NS)) ) {
145 strdup( string_tmp ),
151 xmlNodePtr _f = _cur->children;
154 if (strcmp( (char*)_f->name, "field" )) {
159 _tmp = osrfNewHash();
161 if( (string_tmp = (char*)xmlGetNsProp(_f, "array_position", OBJECT_NS)) ) {
164 strdup( string_tmp ),
170 if( (string_tmp = (char*)xmlGetNsProp(_f, "virtual", PERSIST_NS)) ) {
173 strdup( string_tmp ),
179 if( (string_tmp = (char*)xmlGetProp(_f, "name")) ) {
182 strdup( string_tmp ),
187 osrfLogInfo(OSRF_LOG_MARK, "Found field %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
198 if (!strcmp( (char*)_cur->name, "links" )) {
199 xmlNodePtr _l = _cur->children;
202 if (strcmp( (char*)_l->name, "link" )) {
207 _tmp = osrfNewHash();
209 if( (string_tmp = (char*)xmlGetProp(_l, "reltype")) ) {
212 strdup( string_tmp ),
216 osrfLogInfo(OSRF_LOG_MARK, "Adding link with reltype %s", string_tmp );
219 if( (string_tmp = (char*)xmlGetProp(_l, "key")) ) {
222 strdup( string_tmp ),
226 osrfLogInfo(OSRF_LOG_MARK, "Link fkey is %s", string_tmp );
229 if( (string_tmp = (char*)xmlGetProp(_l, "class")) ) {
232 strdup( string_tmp ),
236 osrfLogInfo(OSRF_LOG_MARK, "Link fclass is %s", string_tmp );
239 osrfStringArray* map = osrfNewStringArray(0);
241 if( (string_tmp = (char*)xmlGetProp(_l, "map") )) {
242 char* map_list = strdup( string_tmp );
243 osrfLogInfo(OSRF_LOG_MARK, "Link mapping list is %s", string_tmp );
245 if (strlen( map_list ) > 0) {
247 char* _map_class = strtok_r(map_list, " ", &st_tmp);
248 osrfStringArrayAdd(map, strdup(_map_class));
250 while ((_map_class = strtok_r(NULL, " ", &st_tmp))) {
251 osrfStringArrayAdd(map, strdup(_map_class));
255 osrfHashSet( _tmp, map, "map");
257 if( (string_tmp = (char*)xmlGetProp(_l, "field")) ) {
260 strdup( string_tmp ),
271 osrfLogInfo(OSRF_LOG_MARK, "Found link %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
285 osrfHash* method_meta;
286 while ( (method_type = osrfStringArrayGetString(global_methods, i++)) ) {
288 if (!osrfHashGet(usrData, "fieldmapper")) continue;
290 method_meta = osrfNewHash();
291 osrfHashSet(method_meta, usrData, "class");
293 _fm = strdup( (char*)osrfHashGet(usrData, "fieldmapper") );
294 part = strtok_r(_fm, ":", &st_tmp);
296 growing_buffer* method_name = buffer_init(64);
297 buffer_fadd(method_name, "%s.direct.%s", MODULENAME, part);
299 while ((part = strtok_r(NULL, ":", &st_tmp))) {
300 buffer_fadd(method_name, ".%s", part);
302 buffer_fadd(method_name, ".%s", method_type);
305 char* method = buffer_data(method_name);
306 buffer_free(method_name);
309 osrfHashSet( method_meta, method, "methodname" );
310 osrfHashSet( method_meta, method_type, "methodtype" );
313 if (!(strcmp( method_type, "search" ))) {
314 flags = flags | OSRF_METHOD_STREAMING;
317 osrfAppRegisterExtendedMethod(
320 "dispatchCRUDMethod",
335 * Connects to the database
337 int osrfAppChildInit() {
339 osrfLogDebug(OSRF_LOG_MARK, "Attempting to initialize libdbi...");
340 dbi_initialize(NULL);
341 osrfLogDebug(OSRF_LOG_MARK, "... libdbi initialized.");
343 char* driver = osrf_settings_host_value("/apps/%s/app_settings/driver", MODULENAME);
344 char* user = osrf_settings_host_value("/apps/%s/app_settings/database/user", MODULENAME);
345 char* host = osrf_settings_host_value("/apps/%s/app_settings/database/host", MODULENAME);
346 char* port = osrf_settings_host_value("/apps/%s/app_settings/database/port", MODULENAME);
347 char* db = osrf_settings_host_value("/apps/%s/app_settings/database/db", MODULENAME);
348 char* pw = osrf_settings_host_value("/apps/%s/app_settings/database/pw", MODULENAME);
350 osrfLogDebug(OSRF_LOG_MARK, "Attempting to load the database driver [%s]...", driver);
351 dbhandle = dbi_conn_new(driver);
354 osrfLogError(OSRF_LOG_MARK, "Error loading database driver [%s]", driver);
357 osrfLogDebug(OSRF_LOG_MARK, "Database driver [%s] seems OK", driver);
359 osrfLogInfo(OSRF_LOG_MARK, "%s connecting to database. host=%s, "
360 "port=%s, user=%s, pw=%s, db=%s", MODULENAME, host, port, user, pw, db );
362 if(host) dbi_conn_set_option(dbhandle, "host", host );
363 if(port) dbi_conn_set_option_numeric( dbhandle, "port", atoi(port) );
364 if(user) dbi_conn_set_option(dbhandle, "username", user);
365 if(pw) dbi_conn_set_option(dbhandle, "password", pw );
366 if(db) dbi_conn_set_option(dbhandle, "dbname", db );
375 if (dbi_conn_connect(dbhandle) < 0) {
376 dbi_conn_error(dbhandle, &err);
377 osrfLogError( OSRF_LOG_MARK, "Error connecting to database: %s", err);
381 osrfLogInfo(OSRF_LOG_MARK, "%s successfully connected to the database", MODULENAME);
387 osrfStringArray* classes = osrfHashKeys( idlHash );
389 while ( (classname = osrfStringArrayGetString(classes, i++)) ) {
390 osrfHash* class = osrfHashGet( idlHash, classname );
391 osrfHash* fields = osrfHashGet( class, "fields" );
393 growing_buffer* sql_buf = buffer_init(32);
394 buffer_fadd( sql_buf, "SELECT * FROM %s WHERE 1=0;", osrfHashGet(class, "tablename") );
396 char* sql = buffer_data(sql_buf);
397 buffer_free(sql_buf);
398 osrfLogDebug(OSRF_LOG_MARK, "%s Investigatory SQL = %s", MODULENAME, sql);
400 dbi_result result = dbi_conn_query(dbhandle, sql);
406 const char* columnName;
408 while( (columnName = dbi_result_get_field_name(result, columnIndex++)) ) {
410 osrfLogDebug(OSRF_LOG_MARK, "Looking for column named [%s]...", (char*)columnName);
412 /* fetch the fieldmapper index */
413 if( (_f = osrfHashGet(fields, (char*)columnName)) ) {
415 osrfLogDebug(OSRF_LOG_MARK, "Found [%s] in IDL hash...", (char*)columnName);
417 /* determine the field type and storage attributes */
418 type = dbi_result_get_field_type(result, columnName);
419 attr = dbi_result_get_field_attribs(result, columnName);
423 case DBI_TYPE_INTEGER :
425 osrfHashSet(_f,"number", "primitive");
427 if( attr & DBI_INTEGER_SIZE8 )
428 osrfHashSet(_f,"INT8", "datatype");
430 osrfHashSet(_f,"INT", "datatype");
433 case DBI_TYPE_DECIMAL :
434 osrfHashSet(_f,"number", "primitive");
435 osrfHashSet(_f,"NUMERIC", "datatype");
438 case DBI_TYPE_STRING :
439 osrfHashSet(_f,"string", "primitive");
440 osrfHashSet(_f,"TEXT", "datatype");
443 case DBI_TYPE_DATETIME :
444 osrfHashSet(_f,"string", "primitive");
445 osrfHashSet(_f,"TIMESTAMP", "datatype");
448 case DBI_TYPE_BINARY :
449 osrfHashSet(_f,"string", "primitive");
450 osrfHashSet(_f,"BYTEA", "datatype");
455 "Setting [%s] to primitive [%s] and datatype [%s]...",
457 osrfHashGet(_f, "primitive"),
458 osrfHashGet(_f, "datatype")
462 dbi_result_free(result);
464 osrfLogDebug(OSRF_LOG_MARK, "No data found for class [%s]...", (char*)classname);
468 osrfStringArrayFree(classes);
473 void userDataFree( void* blob ) {
474 osrfHashFree( (osrfHash*)blob );
478 void sessionDataFree( char* key, void* item ) {
479 if (!(strcmp(key,"xact_id")))
485 int beginTransaction ( osrfMethodContext* ctx ) {
486 OSRF_METHOD_VERIFY_CONTEXT(ctx);
488 dbi_result result = dbi_conn_query(dbhandle, "START TRANSACTION;");
490 osrfLogError(OSRF_LOG_MARK, "%s: Error starting transaction", MODULENAME );
491 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error starting transaction" );
494 jsonObject* ret = jsonNewObject(ctx->session->session_id);
495 osrfAppRespondComplete( ctx, ret );
498 if (!ctx->session->userData) {
499 ctx->session->userData = osrfNewHash();
500 ((osrfHash*)ctx->session->userData)->freeItem = &sessionDataFree;
503 osrfHashSet( (osrfHash*)ctx->session->userData, strdup( ctx->session->session_id ), "xact_id" );
504 ctx->session->userDataFree = &userDataFree;
510 int setSavepoint ( osrfMethodContext* ctx ) {
511 OSRF_METHOD_VERIFY_CONTEXT(ctx);
513 char* spName = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
515 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
516 osrfAppSessionStatus(
518 OSRF_STATUS_INTERNALSERVERERROR,
519 "osrfMethodException",
521 "No active transaction -- required for savepoints"
526 dbi_result result = dbi_conn_queryf(dbhandle, "SAVEPOINT \"%s\";", spName);
530 "%s: Error creating savepoint %s in transaction %s",
533 osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )
535 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error creating savepoint" );
538 jsonObject* ret = jsonNewObject(spName);
539 osrfAppRespondComplete( ctx, ret );
545 int releaseSavepoint ( osrfMethodContext* ctx ) {
546 OSRF_METHOD_VERIFY_CONTEXT(ctx);
548 char* spName = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
550 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
551 osrfAppSessionStatus(
553 OSRF_STATUS_INTERNALSERVERERROR,
554 "osrfMethodException",
556 "No active transaction -- required for savepoints"
561 dbi_result result = dbi_conn_queryf(dbhandle, "RELEASE SAVEPOINT \"%s\";", spName);
565 "%s: Error releasing savepoint %s in transaction %s",
568 osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )
570 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error releasing savepoint" );
573 jsonObject* ret = jsonNewObject(spName);
574 osrfAppRespondComplete( ctx, ret );
580 int rollbackSavepoint ( osrfMethodContext* ctx ) {
581 OSRF_METHOD_VERIFY_CONTEXT(ctx);
583 char* spName = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
585 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
586 osrfAppSessionStatus(
588 OSRF_STATUS_INTERNALSERVERERROR,
589 "osrfMethodException",
591 "No active transaction -- required for savepoints"
596 dbi_result result = dbi_conn_queryf(dbhandle, "ROLLBACK TO SAVEPOINT \"%s\";", spName);
600 "%s: Error rolling back savepoint %s in transaction %s",
603 osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )
605 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error rolling back savepoint" );
608 jsonObject* ret = jsonNewObject(spName);
609 osrfAppRespondComplete( ctx, ret );
615 int commitTransaction ( osrfMethodContext* ctx ) {
616 OSRF_METHOD_VERIFY_CONTEXT(ctx);
618 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
619 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "No active transaction to commit" );
623 dbi_result result = dbi_conn_query(dbhandle, "COMMIT;");
625 osrfLogError(OSRF_LOG_MARK, "%s: Error committing transaction", MODULENAME );
626 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error committing transaction" );
629 osrfHashRemove(ctx->session->userData, "xact_id");
630 jsonObject* ret = jsonNewObject(ctx->session->session_id);
631 osrfAppRespondComplete( ctx, ret );
637 int rollbackTransaction ( osrfMethodContext* ctx ) {
638 OSRF_METHOD_VERIFY_CONTEXT(ctx);
640 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
641 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "No active transaction to roll back" );
645 dbi_result result = dbi_conn_query(dbhandle, "ROLLBACK;");
647 osrfLogError(OSRF_LOG_MARK, "%s: Error rolling back transaction", MODULENAME );
648 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error rolling back transaction" );
651 osrfHashRemove(ctx->session->userData, "xact_id");
652 jsonObject* ret = jsonNewObject(ctx->session->session_id);
653 osrfAppRespondComplete( ctx, ret );
659 int dispatchCRUDMethod ( osrfMethodContext* ctx ) {
660 OSRF_METHOD_VERIFY_CONTEXT(ctx);
662 osrfHash* meta = (osrfHash*) ctx->method->userData;
663 osrfHash* class_obj = osrfHashGet( meta, "class" );
667 jsonObject * obj = NULL;
668 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "create"))
669 obj = doCreate(ctx, &err);
671 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "retrieve"))
672 obj = doRetrieve(ctx, &err);
674 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "update"))
675 obj = doUpdate(ctx, &err);
677 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "delete"))
678 obj = doDelete(ctx, &err);
680 if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "search")) {
682 obj = doSearch(ctx, class_obj, ctx->params, &err);
686 jsonObjectIterator* itr = jsonNewObjectIterator( obj );
687 while ((cur = jsonObjectIteratorNext( itr ))) {
688 osrfAppRespond( ctx, jsonObjectClone(cur->item) );
690 jsonObjectIteratorFree(itr);
691 osrfAppRespondComplete( ctx, NULL );
694 osrfAppRespondComplete( ctx, obj );
702 int verifyObjectClass ( osrfMethodContext* ctx, jsonObject* param ) {
704 osrfHash* meta = (osrfHash*) ctx->method->userData;
705 osrfHash* class = osrfHashGet( meta, "class" );
707 if ((strcmp( osrfHashGet(class, "classname"), param->classname ))) {
709 growing_buffer* msg = buffer_init(128);
712 "%s: %s method for type %s was passed a %s",
714 osrfHashGet(meta, "methodtype"),
715 osrfHashGet(class, "classname"),
719 char* m = buffer_data(msg);
720 osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException", ctx->request, m );
730 jsonObject* doCreate(osrfMethodContext* ctx, int* err ) {
732 osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
733 jsonObject* target = jsonObjectGetIndex( ctx->params, 0 );
735 if (!verifyObjectClass(ctx, target)) {
740 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
741 osrfAppSessionStatus(
743 OSRF_STATUS_BADREQUEST,
744 "osrfMethodException",
746 "No active transaction -- required for CREATE"
752 osrfHash* fields = osrfHashGet(meta, "fields");
753 char* pkey = osrfHashGet(meta, "primarykey");
754 char* seq = osrfHashGet(meta, "sequence");
756 growing_buffer* table_buf = buffer_init(128);
757 growing_buffer* col_buf = buffer_init(128);
758 growing_buffer* val_buf = buffer_init(128);
760 buffer_fadd(table_buf,"INSERT INTO %s", osrfHashGet(meta, "tablename"));
761 buffer_add(col_buf,"(");
762 buffer_add(val_buf,"VALUES (");
767 osrfStringArray* field_list = osrfHashKeys( fields );
768 while ( (field_name = osrfStringArrayGetString(field_list, i++)) ) {
770 osrfHash* field = osrfHashGet( fields, field_name );
772 if(!( strcmp( osrfHashGet(osrfHashGet(fields,field_name), "virtual"), "true" ) )) continue;
774 int pos = atoi(osrfHashGet(field, "array_position"));
775 char* value = jsonObjectToSimpleString( jsonObjectGetIndex( target, pos ) );
780 buffer_add(col_buf, ",");
781 buffer_add(val_buf, ",");
784 buffer_add(col_buf, field_name);
786 if (jsonObjectGetIndex(target, pos)->type == JSON_NULL) {
787 buffer_add( val_buf, "DEFAULT" );
789 } else if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
790 if ( !strcmp(osrfHashGet(field, "datatype"), "INT8") ) {
791 buffer_fadd( val_buf, "%lld", atol(value) );
793 } else if ( !strcmp(osrfHashGet(field, "datatype"), "INT") ) {
794 buffer_fadd( val_buf, "%ld", atoll(value) );
796 } else if ( !strcmp(osrfHashGet(field, "datatype"), "NUMERIC") ) {
797 buffer_fadd( val_buf, "%f", atof(value) );
800 if ( dbi_conn_quote_string(dbhandle, &value) ) {
801 buffer_fadd( val_buf, "%s", value );
804 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting string [%s]", MODULENAME, value);
805 osrfAppSessionStatus(
807 OSRF_STATUS_INTERNALSERVERERROR,
808 "osrfMethodException",
810 "Error quoting string -- please see the error log for more details"
813 buffer_free(table_buf);
814 buffer_free(col_buf);
815 buffer_free(val_buf);
825 buffer_add(col_buf,")");
826 buffer_add(val_buf,")");
828 growing_buffer* sql = buffer_init(128);
832 buffer_data(table_buf),
833 buffer_data(col_buf),
836 buffer_free(table_buf);
837 buffer_free(col_buf);
838 buffer_free(val_buf);
840 char* query = buffer_data(sql);
843 osrfLogDebug(OSRF_LOG_MARK, "%s: Insert SQL [%s]", MODULENAME, query);
846 dbi_result result = dbi_conn_query(dbhandle, query);
848 jsonObject* obj = NULL;
851 obj = jsonNewObject(NULL);
854 "%s ERROR inserting %s object using query [%s]",
856 osrfHashGet(meta, "fieldmapper"),
859 osrfAppSessionStatus(
861 OSRF_STATUS_INTERNALSERVERERROR,
862 "osrfMethodException",
864 "INSERT error -- please see the error log for more details"
869 int pos = atoi(osrfHashGet( osrfHashGet(fields, pkey), "array_position" ));
870 char* id = jsonObjectToSimpleString(jsonObjectGetIndex(target, pos));
872 unsigned long long new_id = dbi_conn_sequence_last(dbhandle, seq);
873 growing_buffer* _id = buffer_init(10);
874 buffer_fadd(_id, "%lld", new_id);
875 id = buffer_data(_id);
879 jsonObject* fake_params = jsonParseString("[]");
880 jsonObjectPush(fake_params, jsonParseString("{}"));
883 jsonObjectGetIndex(fake_params, 0),
884 osrfHashGet(meta, "primarykey"),
888 jsonObject* list = doSearch( ctx,meta, fake_params, err);
891 jsonObjectFree( fake_params );
894 obj = jsonObjectClone( jsonObjectGetIndex(list, 0) );
897 jsonObjectFree( list );
898 jsonObjectFree( fake_params );
909 jsonObject* doRetrieve(osrfMethodContext* ctx, int* err ) {
911 osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
915 char* id = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
916 jsonObject* order_hash = jsonObjectGetIndex(ctx->params, 1);
920 "%s retrieving %s object with id %s",
922 osrfHashGet(meta, "fieldmapper"),
926 jsonObject* fake_params = jsonParseString("[]");
927 jsonObjectPush(fake_params, jsonParseString("{}"));
930 jsonObjectGetIndex(fake_params, 0),
931 osrfHashGet(meta, "primarykey"),
935 if (order_hash) jsonObjectPush(fake_params, jsonObjectClone(order_hash) );
937 jsonObject* list = doSearch( ctx,meta, fake_params, err);
940 jsonObjectFree( fake_params );
944 obj = jsonObjectClone( jsonObjectGetIndex(list, 0) );
946 jsonObjectFree( list );
947 jsonObjectFree( fake_params );
952 char* jsonNumberToDBString ( osrfHash* field, jsonObject* value ) {
953 growing_buffer* val_buf = buffer_init(32);
955 if ( !strncmp(osrfHashGet(field, "datatype"), "INT", 3) ) {
956 if (value->type == JSON_NUMBER) buffer_fadd( val_buf, "%ld", (long)jsonObjectGetNumber(value) );
957 else buffer_fadd( val_buf, "%ld", atol(jsonObjectToSimpleString(value)) );
959 } else if ( !strcmp(osrfHashGet(field, "datatype"), "NUMERIC") ) {
960 if (value->type == JSON_NUMBER) buffer_fadd( val_buf, "%f", jsonObjectGetNumber(value) );
961 else buffer_fadd( val_buf, "%f", atof(jsonObjectToSimpleString(value)) );
964 char* pred = buffer_data(val_buf);
965 buffer_free(val_buf);
970 char* searchINPredicate (osrfHash* field, jsonObject* node) {
971 growing_buffer* sql_buf = buffer_init(32);
976 osrfHashGet(field, "name")
979 int in_item_index = 0;
980 int in_item_first = 1;
982 while ( (in_item = jsonObjectGetIndex(node, in_item_index++)) ) {
987 buffer_add(sql_buf, ", ");
989 if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
990 char* val = jsonNumberToDBString( field, in_item );
991 buffer_fadd( sql_buf, "%s", val );
995 char* key_string = jsonObjectToSimpleString(in_item);
996 if ( dbi_conn_quote_string(dbhandle, &key_string) ) {
997 buffer_fadd( sql_buf, "%s", key_string );
1000 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key string [%s]", MODULENAME, key_string);
1002 buffer_free(sql_buf);
1013 char* pred = buffer_data(sql_buf);
1014 buffer_free(sql_buf);
1019 char* searchFunctionPredicate (osrfHash* field, jsonObjectNode* node) {
1020 growing_buffer* sql_buf = buffer_init(32);
1025 osrfHashGet(field, "name"),
1030 int func_item_index = 0;
1031 int func_item_first = 2;
1032 jsonObject* func_item;
1033 while ( (func_item = jsonObjectGetIndex(node->item, func_item_index++)) ) {
1035 val = jsonObjectToSimpleString(func_item);
1037 if (func_item_first == 2) {
1038 buffer_fadd(sql_buf, "%s( ", val);
1044 if (func_item_first)
1047 buffer_add(sql_buf, ", ");
1049 if ( dbi_conn_quote_string(dbhandle, &val) ) {
1050 buffer_fadd( sql_buf, "%s", val );
1053 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key string [%s]", MODULENAME, val);
1055 buffer_free(sql_buf);
1065 char* pred = buffer_data(sql_buf);
1066 buffer_free(sql_buf);
1071 char* searchSimplePredicate (const char* orig_op, osrfHash* field, jsonObject* node) {
1075 if (node->type == JSON_NULL) {
1076 val = strdup("NULL");
1078 if (strcmp( orig_op, "=" ))
1079 op = strdup("IS NOT");
1083 } else if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1084 val = jsonNumberToDBString( field, node );
1085 op = strdup (orig_op);
1088 val = jsonObjectToSimpleString(node);
1089 op = strdup (orig_op);
1090 if ( !dbi_conn_quote_string(dbhandle, &val) ) {
1091 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key string [%s]", MODULENAME, val);
1097 growing_buffer* sql_buf = buffer_init(16);
1098 buffer_fadd( sql_buf, "%s %s %s", osrfHashGet(field, "name"), op, val );
1102 char* pred = buffer_data(sql_buf);
1103 buffer_free(sql_buf);
1108 char* searchBETWEENPredicate (osrfHash* field, jsonObject* node) {
1113 if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1114 x_string = jsonNumberToDBString(field, jsonObjectGetIndex(node,0));
1115 y_string = jsonNumberToDBString(field, jsonObjectGetIndex(node,1));
1118 x_string = jsonObjectToSimpleString(jsonObjectGetIndex(node,0));
1119 y_string = jsonObjectToSimpleString(jsonObjectGetIndex(node,1));
1120 if ( !(dbi_conn_quote_string(dbhandle, &x_string) && dbi_conn_quote_string(dbhandle, &y_string)) ) {
1121 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key strings [%s] and [%s]", MODULENAME, x_string, y_string);
1128 growing_buffer* sql_buf = buffer_init(32);
1129 buffer_fadd( sql_buf, "%s BETWEEN %s AND %s", osrfHashGet(field, "name"), x_string, y_string );
1133 char* pred = buffer_data(sql_buf);
1134 buffer_free(sql_buf);
1139 char* searchPredicate ( osrfHash* field, jsonObject* node ) {
1142 if (node->type == JSON_ARRAY) { // equality IN search
1143 pred = searchINPredicate( field, node );
1144 } else if (node->type == JSON_HASH) { // non-equality search
1145 jsonObjectNode* pred_node;
1146 jsonObjectIterator* pred_itr = jsonNewObjectIterator( node );
1147 while ( (pred_node = jsonObjectIteratorNext( pred_itr )) ) {
1148 if ( !(strcasecmp( pred_node->key,"between" )) )
1149 pred = searchBETWEENPredicate( field, pred_node->item );
1150 else if ( !(strcasecmp( pred_node->key,"in" )) )
1151 pred = searchINPredicate( field, pred_node->item );
1152 else if ( pred_node->item->type == JSON_ARRAY )
1153 pred = searchFunctionPredicate( field, pred_node );
1155 pred = searchSimplePredicate( pred_node->key, field, pred_node->item );
1159 } else if (node->type == JSON_NULL) { // IS NULL search
1160 growing_buffer* _p = buffer_init(16);
1164 osrfHashGet(field, "name")
1166 pred = buffer_data(_p);
1168 } else { // equality search
1169 pred = searchSimplePredicate( "=", field, node );
1176 jsonObject* doSearch(osrfMethodContext* ctx, osrfHash* meta, jsonObject* params, int* err ) {
1178 osrfHash* links = osrfHashGet(meta, "links");
1179 osrfHash* fields = osrfHashGet(meta, "fields");
1183 jsonObject* search_hash = jsonObjectGetIndex(params, 0);
1184 jsonObject* order_hash = jsonObjectGetIndex(params, 1);
1186 growing_buffer* sql_buf = buffer_init(128);
1187 buffer_fadd(sql_buf, "SELECT * FROM %s WHERE ", osrfHashGet(meta, "tablename") );
1189 jsonObjectNode* node = NULL;
1190 jsonObjectIterator* search_itr = jsonNewObjectIterator( search_hash );
1194 while ( (node = jsonObjectIteratorNext( search_itr )) ) {
1195 osrfHash* field = osrfHashGet( fields, node->key );
1197 if (!field) continue;
1201 field = osrfNewHash();
1202 osrfHashSet(field, node->key, "name");
1209 buffer_add(sql_buf, " AND ");
1212 pred = searchPredicate( field, node->item);
1213 buffer_fadd( sql_buf, "%s", pred );
1217 jsonObjectIteratorFree(search_itr);
1221 _tmp = jsonObjectGetKey( order_hash, "order_by" );
1223 string = jsonObjectToSimpleString(_tmp);
1232 _tmp = jsonObjectGetKey( order_hash, "limit" );
1234 string = jsonObjectToSimpleString(_tmp);
1243 _tmp = jsonObjectGetKey( order_hash, "offset" );
1245 string = jsonObjectToSimpleString(_tmp);
1255 buffer_add(sql_buf, ";");
1257 char* sql = buffer_data(sql_buf);
1258 buffer_free(sql_buf);
1260 osrfLogDebug(OSRF_LOG_MARK, "%s SQL = %s", MODULENAME, sql);
1261 dbi_result result = dbi_conn_query(dbhandle, sql);
1263 jsonObject* res_list = jsonParseString("[]");
1265 osrfLogDebug(OSRF_LOG_MARK, "Query returned with no errors");
1267 if (dbi_result_first_row(result)) {
1268 /* JSONify the result */
1269 osrfLogDebug(OSRF_LOG_MARK, "Query returned at least one row");
1271 obj = oilsMakeJSONFromResult( result, meta );
1272 jsonObjectPush(res_list, obj);
1273 } while (dbi_result_next_row(result));
1275 osrfLogDebug(OSRF_LOG_MARK, "%s returned no results for query %s", MODULENAME, sql);
1278 /* clean up the query */
1279 dbi_result_free(result);
1282 osrfLogError(OSRF_LOG_MARK, "%s: Error retrieving %s with query [%s]", MODULENAME, osrfHashGet(meta, "fieldmapper"), sql);
1283 osrfAppSessionStatus(
1285 OSRF_STATUS_INTERNALSERVERERROR,
1286 "osrfMethodException",
1288 "Severe query error -- see error log for more details"
1292 jsonObjectFree(res_list);
1300 _tmp = jsonObjectGetKey( order_hash, "flesh" );
1302 int x = (int)jsonObjectGetNumber(_tmp);
1306 jsonObjectNode* cur;
1307 jsonObjectIterator* itr = jsonNewObjectIterator( res_list );
1308 while ((cur = jsonObjectIteratorNext( itr ))) {
1312 osrfStringArray* link_fields;
1314 jsonObject* flesh_fields = jsonObjectGetKey( order_hash, "flesh_fields" );
1317 jsonObjectIterator* _i = jsonNewObjectIterator( flesh_fields );
1318 link_fields = osrfNewStringArray(1);
1319 while ((_f = jsonObjectIteratorNext( _i ))) {
1320 osrfStringArrayAdd( link_fields, jsonObjectToSimpleString( _f->item ) );
1323 link_fields = osrfHashKeys( links );
1326 while ( (link_field = osrfStringArrayGetString(link_fields, i++)) ) {
1328 osrfLogDebug(OSRF_LOG_MARK, "Starting to flesh %s", link_field);
1330 osrfHash* kid_link = osrfHashGet(links, link_field);
1331 if (!kid_link) continue;
1333 osrfHash* field = osrfHashGet(fields, link_field);
1334 if (!field) continue;
1336 osrfHash* value_field = field;
1338 osrfHash* kid_idl = osrfHashGet(idlHash, osrfHashGet(kid_link, "class"));
1339 if (!kid_idl) continue;
1341 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "has_many" ))) { // has_many
1342 value_field = osrfHashGet( fields, osrfHashGet(meta, "primarykey") );
1345 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "might_have" ))) { // might_have
1346 value_field = osrfHashGet( fields, osrfHashGet(meta, "primarykey") );
1351 "Link field: %s, remote class: %s, fkey: %s, reltype: %s",
1352 osrfHashGet(kid_link, "field"),
1353 osrfHashGet(kid_link, "class"),
1354 osrfHashGet(kid_link, "key"),
1355 osrfHashGet(kid_link, "reltype")
1358 jsonObject* fake_params = jsonParseString("[]");
1359 jsonObjectPush(fake_params, jsonParseString("{}")); // search hash
1360 jsonObjectPush(fake_params, jsonParseString("{}")); // order/flesh hash
1362 osrfLogDebug(OSRF_LOG_MARK, "Creating dummy params object...");
1365 jsonObjectToSimpleString(
1368 atoi( osrfHashGet(value_field, "array_position") )
1373 osrfLogDebug(OSRF_LOG_MARK, "Nothing to search for!");
1378 jsonObjectGetIndex(fake_params, 0),
1379 osrfHashGet(kid_link, "key"),
1380 jsonNewObject( search_key )
1387 jsonObjectGetIndex(fake_params, 1),
1389 jsonNewNumberObject( (double)(x - 1) )
1394 jsonObjectGetIndex(fake_params, 1),
1396 jsonObjectClone( flesh_fields )
1400 if (jsonObjectGetKey(order_hash, "order_by")) {
1402 jsonObjectGetIndex(fake_params, 1),
1404 jsonObjectClone(jsonObjectGetKey(order_hash, "order_by"))
1408 jsonObject* kids = doSearch(ctx, kid_idl, fake_params, err);
1411 jsonObjectFree( fake_params );
1412 if (flesh_fields) osrfStringArrayFree(link_fields);
1413 jsonObjectIteratorFree(itr);
1414 jsonObjectFree(res_list);
1420 osrfLogDebug(OSRF_LOG_MARK, "Search for %s return %d linked objects", osrfHashGet(kid_link, "class"), kids->size);
1422 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "has_a" ))) {
1423 osrfLogDebug(OSRF_LOG_MARK, "Storing fleshed objects in %s", osrfHashGet(kid_link, "field"));
1426 (unsigned long)atoi( osrfHashGet( field, "array_position" ) ),
1427 jsonObjectClone( jsonObjectGetIndex(kids, 0) )
1429 jsonObjectFree( kids );
1432 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "has_many" ))) { // has_many
1433 osrfLogDebug(OSRF_LOG_MARK, "Storing fleshed objects in %s", osrfHashGet(kid_link, "field"));
1436 (unsigned long)atoi( osrfHashGet( field, "array_position" ) ),
1441 osrfLogDebug(OSRF_LOG_MARK, "Fleshing of %s complete", osrfHashGet(kid_link, "field"));
1443 jsonObjectFree( fake_params );
1445 if (flesh_fields) osrfStringArrayFree(link_fields);
1447 jsonObjectIteratorFree(itr);
1456 jsonObject* doUpdate(osrfMethodContext* ctx, int* err ) {
1458 osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
1459 jsonObject* target = jsonObjectGetIndex(ctx->params, 0);
1461 if (!verifyObjectClass(ctx, target)) {
1466 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
1467 osrfAppSessionStatus(
1469 OSRF_STATUS_BADREQUEST,
1470 "osrfMethodException",
1472 "No active transaction -- required for UPDATE"
1478 char* pkey = osrfHashGet(meta, "primarykey");
1479 osrfHash* fields = osrfHashGet(meta, "fields");
1482 jsonObjectToSimpleString(
1485 atoi( osrfHashGet( osrfHashGet( fields, pkey ), "array_position" ) )
1491 "%s updating %s object with %s = %s",
1493 osrfHashGet(meta, "fieldmapper"),
1498 growing_buffer* sql = buffer_init(128);
1499 buffer_fadd(sql,"UPDATE %s SET", osrfHashGet(meta, "tablename"));
1504 osrfStringArray* field_list = osrfHashKeys( fields );
1505 while ( (field_name = osrfStringArrayGetString(field_list, i++)) ) {
1507 osrfHash* field = osrfHashGet( fields, field_name );
1509 if(!( strcmp( field_name, pkey ) )) continue;
1510 if(!( strcmp( osrfHashGet(osrfHashGet(fields,field_name), "virtual"), "true" ) )) continue;
1512 int pos = atoi(osrfHashGet(field, "array_position"));
1513 char* value = jsonObjectToSimpleString( jsonObjectGetIndex( target, pos ) );
1515 osrfLogDebug( OSRF_LOG_MARK, "Updating %s object with %s = %s", osrfHashGet(meta, "fieldmapper"), field_name, value);
1517 if (jsonObjectGetIndex(target, pos)->type == JSON_NULL) {
1518 if ( !(!( strcmp( osrfHashGet(meta, "classname"), "au" ) ) && !( strcmp( field_name, "passwd" ) )) ) { // arg at the special case!
1519 if (first) first = 0;
1520 else buffer_add(sql, ",");
1521 buffer_fadd( sql, " %s = NULL", field_name );
1524 } else if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1525 if (first) first = 0;
1526 else buffer_add(sql, ",");
1528 if ( !strncmp(osrfHashGet(field, "datatype"), "INT", (size_t)3) ) {
1529 buffer_fadd( sql, " %s = %ld", field_name, atol(value) );
1530 } else if ( !strcmp(osrfHashGet(field, "datatype"), "NUMERIC") ) {
1531 buffer_fadd( sql, " %s = %f", field_name, atof(value) );
1534 osrfLogDebug( OSRF_LOG_MARK, "%s is of type %s", field_name, osrfHashGet(field, "datatype"));
1537 if ( dbi_conn_quote_string(dbhandle, &value) ) {
1538 if (first) first = 0;
1539 else buffer_add(sql, ",");
1540 buffer_fadd( sql, " %s = %s", field_name, value );
1543 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting string [%s]", MODULENAME, value);
1544 osrfAppSessionStatus(
1546 OSRF_STATUS_INTERNALSERVERERROR,
1547 "osrfMethodException",
1549 "Error quoting string -- please see the error log for more details"
1563 jsonObject* obj = jsonParseString(id);
1565 if ( strcmp( osrfHashGet( osrfHashGet( osrfHashGet(meta, "fields"), pkey ), "primitive" ), "number" ) )
1566 dbi_conn_quote_string(dbhandle, &id);
1568 buffer_fadd( sql, " WHERE %s = %s;", pkey, id );
1570 char* query = buffer_data(sql);
1573 osrfLogDebug(OSRF_LOG_MARK, "%s: Update SQL [%s]", MODULENAME, query);
1575 dbi_result result = dbi_conn_query(dbhandle, query);
1579 jsonObjectFree(obj);
1580 obj = jsonNewObject(NULL);
1583 "%s ERROR updating %s object with %s = %s",
1585 osrfHashGet(meta, "fieldmapper"),
1596 jsonObject* doDelete(osrfMethodContext* ctx, int* err ) {
1598 osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
1600 if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
1601 osrfAppSessionStatus(
1603 OSRF_STATUS_BADREQUEST,
1604 "osrfMethodException",
1606 "No active transaction -- required for DELETE"
1614 char* pkey = osrfHashGet(meta, "primarykey");
1617 if (jsonObjectGetIndex(ctx->params, 0)->classname) {
1618 if (!verifyObjectClass(ctx, jsonObjectGetIndex( ctx->params, 0 ))) {
1623 id = jsonObjectToSimpleString(
1625 jsonObjectGetIndex(ctx->params, 0),
1626 atoi( osrfHashGet( osrfHashGet( osrfHashGet(meta, "fields"), pkey ), "array_position") )
1630 id = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
1635 "%s deleting %s object with %s = %s",
1637 osrfHashGet(meta, "fieldmapper"),
1642 obj = jsonParseString(id);
1644 if ( strcmp( osrfHashGet( osrfHashGet( osrfHashGet(meta, "fields"), pkey ), "primitive" ), "number" ) )
1645 dbi_conn_quote_string(dbhandle, &id);
1647 dbi_result result = dbi_conn_queryf(dbhandle, "DELETE FROM %s WHERE %s = %s;", osrfHashGet(meta, "tablename"), pkey, id);
1650 jsonObjectFree(obj);
1651 obj = jsonNewObject(NULL);
1654 "%s ERROR deleting %s object with %s = %s",
1656 osrfHashGet(meta, "fieldmapper"),
1669 jsonObject* oilsMakeJSONFromResult( dbi_result result, osrfHash* meta) {
1670 if(!(result && meta)) return jsonNULL;
1672 jsonObject* object = jsonParseString("[]");
1673 jsonObjectSetClass(object, osrfHashGet(meta, "classname"));
1675 osrfHash* fields = osrfHashGet(meta, "fields");
1677 osrfLogDebug(OSRF_LOG_MARK, "Setting object class to %s ", object->classname);
1681 char dt_string[256];
1685 int columnIndex = 1;
1687 unsigned short type;
1688 const char* columnName;
1690 /* cycle through the column list */
1691 while( (columnName = dbi_result_get_field_name(result, columnIndex++)) ) {
1693 osrfLogDebug(OSRF_LOG_MARK, "Looking for column named [%s]...", (char*)columnName);
1695 fmIndex = -1; // reset the position
1697 /* determine the field type and storage attributes */
1698 type = dbi_result_get_field_type(result, columnName);
1699 attr = dbi_result_get_field_attribs(result, columnName);
1701 /* fetch the fieldmapper index */
1702 if( (_f = osrfHashGet(fields, (char*)columnName)) ) {
1703 char* virt = (char*)osrfHashGet(_f, "virtual");
1704 char* pos = (char*)osrfHashGet(_f, "array_position");
1706 if ( !virt || !pos || !(strcmp( virt, "true" )) ) continue;
1708 fmIndex = atoi( pos );
1709 osrfLogDebug(OSRF_LOG_MARK, "... Found column at position [%s]...", pos);
1712 if (dbi_result_field_is_null(result, columnName)) {
1713 jsonObjectSetIndex( object, fmIndex, jsonNewObject(NULL) );
1718 case DBI_TYPE_INTEGER :
1720 if( attr & DBI_INTEGER_SIZE8 )
1721 jsonObjectSetIndex( object, fmIndex,
1722 jsonNewNumberObject(dbi_result_get_longlong(result, columnName)));
1724 jsonObjectSetIndex( object, fmIndex,
1725 jsonNewNumberObject(dbi_result_get_long(result, columnName)));
1729 case DBI_TYPE_DECIMAL :
1730 jsonObjectSetIndex( object, fmIndex,
1731 jsonNewNumberObject(dbi_result_get_double(result, columnName)));
1734 case DBI_TYPE_STRING :
1740 jsonNewObject( dbi_result_get_string(result, columnName) )
1745 case DBI_TYPE_DATETIME :
1747 memset(dt_string, '\0', 256);
1748 memset(&gmdt, '\0', sizeof(gmdt));
1749 memset(&_tmp_dt, '\0', sizeof(_tmp_dt));
1751 _tmp_dt = dbi_result_get_datetime(result, columnName);
1753 localtime_r( &_tmp_dt, &gmdt );
1755 if (!(attr & DBI_DATETIME_DATE)) {
1756 strftime(dt_string, 255, "%T", &gmdt);
1757 } else if (!(attr & DBI_DATETIME_TIME)) {
1758 strftime(dt_string, 255, "%F", &gmdt);
1760 /* XXX ARG! My eyes! The goggles, they do nothing! */
1762 strftime(dt_string, 255, "%FT%T%z", &gmdt);
1765 jsonObjectSetIndex( object, fmIndex, jsonNewObject(dt_string) );
1769 case DBI_TYPE_BINARY :
1770 osrfLogError( OSRF_LOG_MARK,
1771 "Can't do binary at column %s : index %d", columnName, columnIndex - 1);