]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/c-apps/oils_cstore.c
adding "quite" mode to create
[Evergreen.git] / Open-ILS / src / c-apps / oils_cstore.c
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"
9 #include "oils_idl.h"
10 #include <dbi/dbi.h>
11
12 #include <time.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #define OILS_AUTH_CACHE_PRFX "oils_cstore_"
17 #define MODULENAME "open-ils.cstore"
18 #define PERSIST_NS "http://open-ils.org/spec/opensrf/IDL/persistance/v1"
19 #define OBJECT_NS "http://open-ils.org/spec/opensrf/IDL/objects/v1"
20 #define BASE_NS "http://opensrf.org/spec/IDL/base/v1"
21
22 int osrfAppChildInit();
23 int osrfAppInitialize();
24
25 int verifyObjectClass ( osrfMethodContext*, jsonObject* );
26
27 int beginTransaction ( osrfMethodContext* );
28 int commitTransaction ( osrfMethodContext* );
29 int rollbackTransaction ( osrfMethodContext* );
30
31 int setSavepoint ( osrfMethodContext* );
32 int releaseSavepoint ( osrfMethodContext* );
33 int rollbackSavepoint ( osrfMethodContext* );
34
35 int dispatchCRUDMethod ( osrfMethodContext* );
36 jsonObject* doCreate ( osrfMethodContext*, int* );
37 jsonObject* doRetrieve ( osrfMethodContext*, int* );
38 jsonObject* doUpdate ( osrfMethodContext*, int* );
39 jsonObject* doDelete ( osrfMethodContext*, int* );
40 jsonObject* doSearch ( osrfMethodContext*, osrfHash*, jsonObject*, int* );
41 jsonObject* oilsMakeJSONFromResult( dbi_result, osrfHash* );
42
43 char* searchWriteSimplePredicate ( osrfHash*, const char*, const char*, const char* );
44 char* searchSimplePredicate ( const char*, osrfHash*, jsonObject* );
45 char* searchFunctionPredicate ( osrfHash*, jsonObjectNode* );
46 char* searchFieldTransformPredicate ( osrfHash*, jsonObjectNode* );
47 char* searchBETWEENPredicate ( osrfHash*, jsonObject* );
48 char* searchINPredicate ( osrfHash*, jsonObject* );
49 char* searchPredicate ( osrfHash*, jsonObject* );
50
51 void userDataFree( void* );
52 void sessionDataFree( char*, void* );
53
54 dbi_conn writehandle; /* our MASTER db connection */
55 dbi_conn dbhandle; /* our CURRENT db connection */
56 osrfHash readHandles;
57 jsonObject* jsonNULL = NULL; // 
58
59
60 /* parse and store the IDL here */
61 osrfHash* idl;
62
63 int osrfAppInitialize() {
64
65         // first we register all the transaction and savepoint methods
66         osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.transaction.begin", "beginTransaction", "", 0, 0 );
67         osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.transaction.commit", "commitTransaction", "", 0, 0 );
68         osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.transaction.rollback", "rollbackTransaction", "", 0, 0 );
69
70         osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.savepoint.set", "setSavepoint", "", 1, 0 );
71         osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.savepoint.release", "releaseSavepoint", "", 1, 0 );
72         osrfAppRegisterMethod( MODULENAME, "open-ils.cstore.savepoint.rollback", "rollbackSavepoint", "", 1, 0 );
73
74
75         osrfLogInfo(OSRF_LOG_MARK, "Initializing the CStore Server...");
76         osrfLogInfo(OSRF_LOG_MARK, "Finding XML file...");
77
78         char * idl_filename = osrf_settings_host_value("/apps/%s/app_settings/IDL", MODULENAME);
79         osrfLogInfo(OSRF_LOG_MARK, "Found file:");
80         osrfLogInfo(OSRF_LOG_MARK, idl_filename);
81
82         idl = oilsIDLInit( idl_filename );
83
84         if (!idl) {
85                 osrfLogError(OSRF_LOG_MARK, "Problem loading the IDL.  Seacrest out!");
86                 exit(1);
87         }
88
89         osrfStringArray* global_methods = osrfNewStringArray(6);
90
91         osrfStringArrayAdd( global_methods, "create" );
92         osrfStringArrayAdd( global_methods, "retrieve" );
93         osrfStringArrayAdd( global_methods, "update" );
94         osrfStringArrayAdd( global_methods, "delete" );
95         osrfStringArrayAdd( global_methods, "search" );
96         osrfStringArrayAdd( global_methods, "id_list" );
97
98         int c_index = 0; 
99         char* classname;
100         osrfStringArray* classes = osrfHashKeys( idl );
101         osrfLogDebug(OSRF_LOG_MARK, "%d classes loaded", classes->size );
102         osrfLogDebug(OSRF_LOG_MARK, "At least %d methods will be generated", classes->size * global_methods->size);
103         
104         while ( (classname = osrfStringArrayGetString(classes, c_index++)) ) {
105                 osrfLogInfo(OSRF_LOG_MARK, "Generating class methods for %s", classname);
106                 
107                 osrfHash* idlClass = osrfHashGet(idl, classname);
108
109                 char* virt = osrfHashGet(idlClass, "virtual");
110                 if (virt && !strcmp( virt, "true")) {
111                         osrfLogDebug(OSRF_LOG_MARK, "Class %s is virtual, skipping", classname );
112                         continue;
113                 }
114
115                 osrfLogDebug(OSRF_LOG_MARK, "HERE");
116                 
117                 int i = 0; 
118                 char* method_type;
119                 char* st_tmp;
120                 char* _fm;
121                 char* part;
122                 osrfHash* method_meta;
123                 while ( (method_type = osrfStringArrayGetString(global_methods, i++)) ) {
124                         osrfLogDebug(OSRF_LOG_MARK, "Using files to build %s class methods for %s", method_type, classname);
125
126                         if (!osrfHashGet(idlClass, "fieldmapper")) continue;
127
128                         method_meta = osrfNewHash();
129                         osrfHashSet(method_meta, idlClass, "class");
130
131                         _fm = strdup( (char*)osrfHashGet(idlClass, "fieldmapper") );
132                         part = strtok_r(_fm, ":", &st_tmp);
133
134                         growing_buffer* method_name =  buffer_init(64);
135                         buffer_fadd(method_name, "%s.direct.%s", MODULENAME, part);
136
137                         while ((part = strtok_r(NULL, ":", &st_tmp))) {
138                                 buffer_fadd(method_name, ".%s", part);
139                         }
140                         buffer_fadd(method_name, ".%s", method_type);
141
142
143                         char* method = buffer_data(method_name);
144                         buffer_free(method_name);
145                         free(_fm);
146
147                         osrfHashSet( method_meta, method, "methodname" );
148                         osrfHashSet( method_meta, method_type, "methodtype" );
149
150                         int flags = 0;
151                         if (!(strcmp( method_type, "search" )) || !(strcmp( method_type, "id_list" ))) {
152                                 flags = flags | OSRF_METHOD_STREAMING;
153                         }
154
155                         osrfAppRegisterExtendedMethod(
156                                 MODULENAME,
157                                 method,
158                                 "dispatchCRUDMethod",
159                                 "",
160                                 1,
161                                 flags,
162                                 (void*)method_meta
163                         );
164                 }
165         }
166
167         return 0;
168 }
169
170 /**
171  * Connects to the database 
172  */
173 int osrfAppChildInit() {
174
175         osrfLogDebug(OSRF_LOG_MARK, "Attempting to initialize libdbi...");
176         dbi_initialize(NULL);
177         osrfLogDebug(OSRF_LOG_MARK, "... libdbi initialized.");
178
179         char* driver    = osrf_settings_host_value("/apps/%s/app_settings/driver", MODULENAME);
180         char* user      = osrf_settings_host_value("/apps/%s/app_settings/database/user", MODULENAME);
181         char* host      = osrf_settings_host_value("/apps/%s/app_settings/database/host", MODULENAME);
182         char* port      = osrf_settings_host_value("/apps/%s/app_settings/database/port", MODULENAME);
183         char* db        = osrf_settings_host_value("/apps/%s/app_settings/database/db", MODULENAME);
184         char* pw        = osrf_settings_host_value("/apps/%s/app_settings/database/pw", MODULENAME);
185
186         osrfLogDebug(OSRF_LOG_MARK, "Attempting to load the database driver [%s]...", driver);
187         writehandle = dbi_conn_new(driver);
188
189         if(!writehandle) {
190                 osrfLogError(OSRF_LOG_MARK, "Error loading database driver [%s]", driver);
191                 return -1;
192         }
193         osrfLogDebug(OSRF_LOG_MARK, "Database driver [%s] seems OK", driver);
194
195         osrfLogInfo(OSRF_LOG_MARK, "%s connecting to database.  host=%s, "
196                 "port=%s, user=%s, pw=%s, db=%s", MODULENAME, host, port, user, pw, db );
197
198         if(host) dbi_conn_set_option(writehandle, "host", host );
199         if(port) dbi_conn_set_option_numeric( writehandle, "port", atoi(port) );
200         if(user) dbi_conn_set_option(writehandle, "username", user);
201         if(pw) dbi_conn_set_option(writehandle, "password", pw );
202         if(db) dbi_conn_set_option(writehandle, "dbname", db );
203
204         free(user);
205         free(host);
206         free(port);
207         free(db);
208         free(pw);
209
210         const char* err;
211         if (dbi_conn_connect(writehandle) < 0) {
212                 dbi_conn_error(writehandle, &err);
213                 osrfLogError( OSRF_LOG_MARK, "Error connecting to database: %s", err);
214                 return -1;
215         }
216
217         osrfLogInfo(OSRF_LOG_MARK, "%s successfully connected to the database", MODULENAME);
218
219         int attr;
220         unsigned short type;
221         int i = 0; 
222         char* classname;
223         osrfStringArray* classes = osrfHashKeys( idl );
224         
225         while ( (classname = osrfStringArrayGetString(classes, i++)) ) {
226                 osrfHash* class = osrfHashGet( idl, classname );
227                 osrfHash* fields = osrfHashGet( class, "fields" );
228
229                 char* virt = osrfHashGet(class, "virtual");
230                 if (virt && !strcmp( virt, "true")) {
231                         osrfLogDebug(OSRF_LOG_MARK, "Class %s is virtual, skipping", classname );
232                         continue;
233                 }
234
235         
236                 growing_buffer* sql_buf = buffer_init(32);
237                 buffer_fadd( sql_buf, "SELECT * FROM %s WHERE 1=0;", osrfHashGet(class, "tablename") );
238
239                 char* sql = buffer_data(sql_buf);
240                 buffer_free(sql_buf);
241                 osrfLogDebug(OSRF_LOG_MARK, "%s Investigatory SQL = %s", MODULENAME, sql);
242
243                 dbi_result result = dbi_conn_query(writehandle, sql);
244                 free(sql);
245
246                 if (result) {
247
248                         int columnIndex = 1;
249                         const char* columnName;
250                         osrfHash* _f;
251                         while( (columnName = dbi_result_get_field_name(result, columnIndex++)) ) {
252
253                                 osrfLogDebug(OSRF_LOG_MARK, "Looking for column named [%s]...", (char*)columnName);
254
255                                 /* fetch the fieldmapper index */
256                                 if( (_f = osrfHashGet(fields, (char*)columnName)) ) {
257
258                                         osrfLogDebug(OSRF_LOG_MARK, "Found [%s] in IDL hash...", (char*)columnName);
259
260                                         /* determine the field type and storage attributes */
261                                         type = dbi_result_get_field_type(result, columnName);
262                                         attr = dbi_result_get_field_attribs(result, columnName);
263
264                                         switch( type ) {
265
266                                                 case DBI_TYPE_INTEGER :
267
268                                                         if ( !osrfHashGet(_f, "primitive") )
269                                                                 osrfHashSet(_f,"number", "primitive");
270
271                                                         if( attr & DBI_INTEGER_SIZE8 ) 
272                                                                 osrfHashSet(_f,"INT8", "datatype");
273                                                         else 
274                                                                 osrfHashSet(_f,"INT", "datatype");
275                                                         break;
276
277                                                 case DBI_TYPE_DECIMAL :
278                                                         if ( !osrfHashGet(_f, "primitive") )
279                                                                 osrfHashSet(_f,"number", "primitive");
280
281                                                         osrfHashSet(_f,"NUMERIC", "datatype");
282                                                         break;
283
284                                                 case DBI_TYPE_STRING :
285                                                         if ( !osrfHashGet(_f, "primitive") )
286                                                                 osrfHashSet(_f,"string", "primitive");
287                                                         osrfHashSet(_f,"TEXT", "datatype");
288                                                         break;
289
290                                                 case DBI_TYPE_DATETIME :
291                                                         if ( !osrfHashGet(_f, "primitive") )
292                                                                 osrfHashSet(_f,"string", "primitive");
293
294                                                         osrfHashSet(_f,"TIMESTAMP", "datatype");
295                                                         break;
296
297                                                 case DBI_TYPE_BINARY :
298                                                         if ( !osrfHashGet(_f, "primitive") )
299                                                                 osrfHashSet(_f,"string", "primitive");
300
301                                                         osrfHashSet(_f,"BYTEA", "datatype");
302                                         }
303
304                                         osrfLogDebug(
305                                                 OSRF_LOG_MARK,
306                                                 "Setting [%s] to primitive [%s] and datatype [%s]...",
307                                                 (char*)columnName,
308                                                 osrfHashGet(_f, "primitive"),
309                                                 osrfHashGet(_f, "datatype")
310                                         );
311                                 }
312                         }
313                         dbi_result_free(result);
314                 } else {
315                         osrfLogDebug(OSRF_LOG_MARK, "No data found for class [%s]...", (char*)classname);
316                 }
317         }
318
319         osrfStringArrayFree(classes);
320
321         return 0;
322 }
323
324 void userDataFree( void* blob ) {
325         osrfHashFree( (osrfHash*)blob );
326         return;
327 }
328
329 void sessionDataFree( char* key, void* item ) {
330         if (!(strcmp(key,"xact_id")))
331                 free(item);
332
333         return;
334 }
335
336 int beginTransaction ( osrfMethodContext* ctx ) {
337         OSRF_METHOD_VERIFY_CONTEXT(ctx);
338
339         dbi_result result = dbi_conn_query(writehandle, "START TRANSACTION;");
340         if (!result) {
341                 osrfLogError(OSRF_LOG_MARK, "%s: Error starting transaction", MODULENAME );
342                 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error starting transaction" );
343                 return -1;
344         } else {
345                 jsonObject* ret = jsonNewObject(ctx->session->session_id);
346                 osrfAppRespondComplete( ctx, ret );
347                 jsonObjectFree(ret);
348                 
349                 if (!ctx->session->userData) {
350                         ctx->session->userData = osrfNewHash();
351                         ((osrfHash*)ctx->session->userData)->freeItem = &sessionDataFree;
352                 }
353
354                 osrfHashSet( (osrfHash*)ctx->session->userData, strdup( ctx->session->session_id ), "xact_id" );
355                 ctx->session->userDataFree = &userDataFree;
356                 
357         }
358         return 0;
359 }
360
361 int setSavepoint ( osrfMethodContext* ctx ) {
362         OSRF_METHOD_VERIFY_CONTEXT(ctx);
363
364         char* spName = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
365
366         if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
367                 osrfAppSessionStatus(
368                         ctx->session,
369                         OSRF_STATUS_INTERNALSERVERERROR,
370                         "osrfMethodException",
371                         ctx->request,
372                         "No active transaction -- required for savepoints"
373                 );
374                 return -1;
375         }
376
377         dbi_result result = dbi_conn_queryf(writehandle, "SAVEPOINT \"%s\";", spName);
378         if (!result) {
379                 osrfLogError(
380                         OSRF_LOG_MARK,
381                         "%s: Error creating savepoint %s in transaction %s",
382                         MODULENAME,
383                         spName,
384                         osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )
385                 );
386                 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error creating savepoint" );
387                 return -1;
388         } else {
389                 jsonObject* ret = jsonNewObject(spName);
390                 osrfAppRespondComplete( ctx, ret );
391                 jsonObjectFree(ret);
392         }
393         return 0;
394 }
395
396 int releaseSavepoint ( osrfMethodContext* ctx ) {
397         OSRF_METHOD_VERIFY_CONTEXT(ctx);
398
399         char* spName = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
400
401         if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
402                 osrfAppSessionStatus(
403                         ctx->session,
404                         OSRF_STATUS_INTERNALSERVERERROR,
405                         "osrfMethodException",
406                         ctx->request,
407                         "No active transaction -- required for savepoints"
408                 );
409                 return -1;
410         }
411
412         dbi_result result = dbi_conn_queryf(writehandle, "RELEASE SAVEPOINT \"%s\";", spName);
413         if (!result) {
414                 osrfLogError(
415                         OSRF_LOG_MARK,
416                         "%s: Error releasing savepoint %s in transaction %s",
417                         MODULENAME,
418                         spName,
419                         osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )
420                 );
421                 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error releasing savepoint" );
422                 return -1;
423         } else {
424                 jsonObject* ret = jsonNewObject(spName);
425                 osrfAppRespondComplete( ctx, ret );
426                 jsonObjectFree(ret);
427         }
428         return 0;
429 }
430
431 int rollbackSavepoint ( osrfMethodContext* ctx ) {
432         OSRF_METHOD_VERIFY_CONTEXT(ctx);
433
434         char* spName = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
435
436         if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
437                 osrfAppSessionStatus(
438                         ctx->session,
439                         OSRF_STATUS_INTERNALSERVERERROR,
440                         "osrfMethodException",
441                         ctx->request,
442                         "No active transaction -- required for savepoints"
443                 );
444                 return -1;
445         }
446
447         dbi_result result = dbi_conn_queryf(writehandle, "ROLLBACK TO SAVEPOINT \"%s\";", spName);
448         if (!result) {
449                 osrfLogError(
450                         OSRF_LOG_MARK,
451                         "%s: Error rolling back savepoint %s in transaction %s",
452                         MODULENAME,
453                         spName,
454                         osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )
455                 );
456                 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error rolling back savepoint" );
457                 return -1;
458         } else {
459                 jsonObject* ret = jsonNewObject(spName);
460                 osrfAppRespondComplete( ctx, ret );
461                 jsonObjectFree(ret);
462         }
463         return 0;
464 }
465
466 int commitTransaction ( osrfMethodContext* ctx ) {
467         OSRF_METHOD_VERIFY_CONTEXT(ctx);
468
469         if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
470                 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "No active transaction to commit" );
471                 return -1;
472         }
473
474         dbi_result result = dbi_conn_query(writehandle, "COMMIT;");
475         if (!result) {
476                 osrfLogError(OSRF_LOG_MARK, "%s: Error committing transaction", MODULENAME );
477                 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error committing transaction" );
478                 return -1;
479         } else {
480                 osrfHashRemove(ctx->session->userData, "xact_id");
481                 jsonObject* ret = jsonNewObject(ctx->session->session_id);
482                 osrfAppRespondComplete( ctx, ret );
483                 jsonObjectFree(ret);
484         }
485         return 0;
486 }
487
488 int rollbackTransaction ( osrfMethodContext* ctx ) {
489         OSRF_METHOD_VERIFY_CONTEXT(ctx);
490
491         if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
492                 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "No active transaction to roll back" );
493                 return -1;
494         }
495
496         dbi_result result = dbi_conn_query(writehandle, "ROLLBACK;");
497         if (!result) {
498                 osrfLogError(OSRF_LOG_MARK, "%s: Error rolling back transaction", MODULENAME );
499                 osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, "osrfMethodException", ctx->request, "Error rolling back transaction" );
500                 return -1;
501         } else {
502                 osrfHashRemove(ctx->session->userData, "xact_id");
503                 jsonObject* ret = jsonNewObject(ctx->session->session_id);
504                 osrfAppRespondComplete( ctx, ret );
505                 jsonObjectFree(ret);
506         }
507         return 0;
508 }
509
510 int dispatchCRUDMethod ( osrfMethodContext* ctx ) {
511         OSRF_METHOD_VERIFY_CONTEXT(ctx);
512
513         osrfHash* meta = (osrfHash*) ctx->method->userData;
514         osrfHash* class_obj = osrfHashGet( meta, "class" );
515         
516         int err = 0;
517
518         jsonObject * obj = NULL;
519         if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "create"))
520                 obj = doCreate(ctx, &err);
521
522         if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "retrieve"))
523                 obj = doRetrieve(ctx, &err);
524
525         if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "update"))
526                 obj = doUpdate(ctx, &err);
527
528         if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "delete"))
529                 obj = doDelete(ctx, &err);
530
531         if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "search")) {
532
533                 obj = doSearch(ctx, class_obj, ctx->params, &err);
534                 if(err) return err;
535
536                 jsonObjectNode* cur;
537                 jsonObjectIterator* itr = jsonNewObjectIterator( obj );
538                 while ((cur = jsonObjectIteratorNext( itr ))) {
539                         osrfAppRespond( ctx, jsonObjectClone(cur->item) );
540                 }
541                 jsonObjectIteratorFree(itr);
542                 osrfAppRespondComplete( ctx, NULL );
543
544         } else if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "id_list")) {
545
546                 jsonObject* _p = jsonObjectClone( ctx->params );
547                 if (jsonObjectGetIndex( _p, 1 )) {
548                         jsonObjectRemoveKey( jsonObjectGetIndex( _p, 1 ), "flesh" );
549                         jsonObjectRemoveKey( jsonObjectGetIndex( _p, 1 ), "flesh_columns" );
550                 } else {
551                         jsonObjectSetIndex( _p, 1, jsonParseString("{}") );
552                 }
553
554                 growing_buffer* sel_list = buffer_init(16);
555                 buffer_fadd(sel_list, "{ \"%s\":[\"%s\"] }", osrfHashGet( class_obj, "classname" ), osrfHashGet( class_obj, "primarykey" ));
556                 char* _s = buffer_data(sel_list);
557                 buffer_free(sel_list);
558
559                 jsonObjectSetKey( jsonObjectGetIndex( _p, 1 ), "select", jsonParseString(_s) );
560                 osrfLogDebug(OSRF_LOG_MARK, "%s: Select qualifer set to [%s]", MODULENAME, _s);
561                 free(_s);
562
563                 obj = doSearch(ctx, class_obj, _p, &err);
564                 if(err) return err;
565
566                 jsonObjectNode* cur;
567                 jsonObjectIterator* itr = jsonNewObjectIterator( obj );
568                 while ((cur = jsonObjectIteratorNext( itr ))) {
569                         osrfAppRespond(
570                                 ctx,
571                                 jsonObjectClone(
572                                         jsonObjectGetIndex(
573                                                 cur->item,
574                                                 atoi(
575                                                         osrfHashGet(
576                                                                 osrfHashGet(
577                                                                         osrfHashGet( class_obj, "fields" ),
578                                                                         osrfHashGet( class_obj, "primarykey")
579                                                                 ),
580                                                                 "array_position"
581                                                         )
582                                                 )
583                                         )
584                                 )
585                         );
586                 }
587                 jsonObjectIteratorFree(itr);
588                 osrfAppRespondComplete( ctx, NULL );
589                 
590         } else {
591                 osrfAppRespondComplete( ctx, obj );
592         }
593
594         jsonObjectFree(obj);
595
596         return err;
597 }
598
599 int verifyObjectClass ( osrfMethodContext* ctx, jsonObject* param ) {
600         
601         osrfHash* meta = (osrfHash*) ctx->method->userData;
602         osrfHash* class = osrfHashGet( meta, "class" );
603         
604         if ((strcmp( osrfHashGet(class, "classname"), param->classname ))) {
605
606                 growing_buffer* msg = buffer_init(128);
607                 buffer_fadd(
608                         msg,
609                         "%s: %s method for type %s was passed a %s",
610                         MODULENAME,
611                         osrfHashGet(meta, "methodtype"),
612                         osrfHashGet(class, "classname"),
613                         param->classname
614                 );
615
616                 char* m = buffer_data(msg);
617                 osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException", ctx->request, m );
618
619                 buffer_free(msg);
620                 free(m);
621
622                 return 0;
623         }
624         return 1;
625 }
626
627 jsonObject* doCreate(osrfMethodContext* ctx, int* err ) {
628
629         osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
630         jsonObject* target = jsonObjectGetIndex( ctx->params, 0 );
631         jsonObject* options = jsonObjectGetIndex( ctx->params, 1 );
632
633         if (!verifyObjectClass(ctx, target)) {
634                 *err = -1;
635                 return jsonNULL;
636         }
637
638         if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
639                 osrfAppSessionStatus(
640                         ctx->session,
641                         OSRF_STATUS_BADREQUEST,
642                         "osrfMethodException",
643                         ctx->request,
644                         "No active transaction -- required for CREATE"
645                 );
646                 *err = -1;
647                 return jsonNULL;
648         }
649
650         dbhandle = writehandle;
651
652         osrfHash* fields = osrfHashGet(meta, "fields");
653         char* pkey = osrfHashGet(meta, "primarykey");
654         char* seq = osrfHashGet(meta, "sequence");
655
656         growing_buffer* table_buf = buffer_init(128);
657         growing_buffer* col_buf = buffer_init(128);
658         growing_buffer* val_buf = buffer_init(128);
659
660         buffer_fadd(table_buf,"INSERT INTO %s", osrfHashGet(meta, "tablename"));
661         buffer_add(col_buf,"(");
662         buffer_add(val_buf,"VALUES (");
663
664         int i = 0;
665         int first = 1;
666         char* field_name;
667         osrfStringArray* field_list = osrfHashKeys( fields );
668         while ( (field_name = osrfStringArrayGetString(field_list, i++)) ) {
669
670                 osrfHash* field = osrfHashGet( fields, field_name );
671
672                 if(!( strcmp( osrfHashGet(osrfHashGet(fields,field_name), "virtual"), "true" ) )) continue;
673
674                 int pos = atoi(osrfHashGet(field, "array_position"));
675                 char* value = jsonObjectToSimpleString( jsonObjectGetIndex( target, pos ) );
676
677                 if (first) {
678                         first = 0;
679                 } else {
680                         buffer_add(col_buf, ",");
681                         buffer_add(val_buf, ",");
682                 }
683
684                 buffer_add(col_buf, field_name);
685
686                 if (jsonObjectGetIndex(target, pos)->type == JSON_NULL) {
687                         buffer_add( val_buf, "DEFAULT" );
688                         
689                 } else if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
690                         if ( !strcmp(osrfHashGet(field, "datatype"), "INT8") ) {
691                                 buffer_fadd( val_buf, "%lld", atol(value) );
692                                 
693                         } else if ( !strcmp(osrfHashGet(field, "datatype"), "INT") ) {
694                                 buffer_fadd( val_buf, "%ld", atoll(value) );
695                                 
696                         } else if ( !strcmp(osrfHashGet(field, "datatype"), "NUMERIC") ) {
697                                 buffer_fadd( val_buf, "%f", atof(value) );
698                         }
699                 } else {
700                         if ( dbi_conn_quote_string(writehandle, &value) ) {
701                                 buffer_fadd( val_buf, "%s", value );
702
703                         } else {
704                                 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting string [%s]", MODULENAME, value);
705                                 osrfAppSessionStatus(
706                                         ctx->session,
707                                         OSRF_STATUS_INTERNALSERVERERROR,
708                                         "osrfMethodException",
709                                         ctx->request,
710                                         "Error quoting string -- please see the error log for more details"
711                                 );
712                                 free(value);
713                                 buffer_free(table_buf);
714                                 buffer_free(col_buf);
715                                 buffer_free(val_buf);
716                                 *err = -1;
717                                 return jsonNULL;
718                         }
719                 }
720
721                 free(value);
722                 
723         }
724
725         buffer_add(col_buf,")");
726         buffer_add(val_buf,")");
727
728         growing_buffer* sql = buffer_init(128);
729         buffer_fadd(
730                 sql,
731                 "%s %s %s;",
732                 buffer_data(table_buf),
733                 buffer_data(col_buf),
734                 buffer_data(val_buf)
735         );
736         buffer_free(table_buf);
737         buffer_free(col_buf);
738         buffer_free(val_buf);
739
740         char* query = buffer_data(sql);
741         buffer_free(sql);
742
743         osrfLogDebug(OSRF_LOG_MARK, "%s: Insert SQL [%s]", MODULENAME, query);
744
745         
746         dbi_result result = dbi_conn_query(writehandle, query);
747
748         jsonObject* obj = NULL;
749
750         if (!result) {
751                 obj = jsonNewObject(NULL);
752                 osrfLogError(
753                         OSRF_LOG_MARK,
754                         "%s ERROR inserting %s object using query [%s]",
755                         MODULENAME,
756                         osrfHashGet(meta, "fieldmapper"),
757                         query
758                 );
759                 osrfAppSessionStatus(
760                         ctx->session,
761                         OSRF_STATUS_INTERNALSERVERERROR,
762                         "osrfMethodException",
763                         ctx->request,
764                         "INSERT error -- please see the error log for more details"
765                 );
766                 *err = -1;
767         } else {
768
769                 int pos = atoi(osrfHashGet( osrfHashGet(fields, pkey), "array_position" ));
770                 char* id = jsonObjectToSimpleString(jsonObjectGetIndex(target, pos));
771                 if (!id) {
772                         unsigned long long new_id = dbi_conn_sequence_last(writehandle, seq);
773                         growing_buffer* _id = buffer_init(10);
774                         buffer_fadd(_id, "%lld", new_id);
775                         id = buffer_data(_id);
776                         buffer_free(_id);
777                 }
778
779                 if (    !options
780                         || !jsonObjectGetKey( options, "quiet")
781                         || strcmp( jsonObjectToSimpleString(jsonObjectGetKey( options, "quiet")), "true" )
782                 ) {
783
784                         jsonObject* fake_params = jsonParseString("[]");
785                         jsonObjectPush(fake_params, jsonParseString("{}"));
786
787                         jsonObjectSetKey(
788                                 jsonObjectGetIndex(fake_params, 0),
789                                 osrfHashGet(meta, "primarykey"),
790                                 jsonNewObject(id)
791                         );
792
793                         jsonObject* list = doSearch( ctx,meta, fake_params, err);
794
795                         if(*err) {
796                                 jsonObjectFree( fake_params );
797                                 obj = jsonNULL;
798                         } else {
799                                 obj = jsonObjectClone( jsonObjectGetIndex(list, 0) );
800                         }
801
802                         jsonObjectFree( list );
803                         jsonObjectFree( fake_params );
804
805                 } else {
806                         obj = jsonNewObject(id);
807                 }
808
809         }
810
811         free(query);
812
813         return obj;
814
815 }
816
817
818 jsonObject* doRetrieve(osrfMethodContext* ctx, int* err ) {
819
820         osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
821
822         jsonObject* obj;
823
824         char* id = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
825         jsonObject* order_hash = jsonObjectGetIndex(ctx->params, 1);
826
827         osrfLogDebug(
828                 OSRF_LOG_MARK,
829                 "%s retrieving %s object with id %s",
830                 MODULENAME,
831                 osrfHashGet(meta, "fieldmapper"),
832                 id
833         );
834
835         jsonObject* fake_params = jsonParseString("[]");
836         jsonObjectPush(fake_params, jsonParseString("{}"));
837
838         jsonObjectSetKey(
839                 jsonObjectGetIndex(fake_params, 0),
840                 osrfHashGet(meta, "primarykey"),
841                 jsonParseString(id)
842         );
843
844         if (order_hash) jsonObjectPush(fake_params, jsonObjectClone(order_hash) );
845
846         jsonObject* list = doSearch( ctx,meta, fake_params, err);
847
848         if(*err) {
849                 jsonObjectFree( fake_params );
850                 return jsonNULL;
851         }
852
853         obj = jsonObjectClone( jsonObjectGetIndex(list, 0) );
854
855         jsonObjectFree( list );
856         jsonObjectFree( fake_params );
857
858         return obj;
859 }
860
861 char* jsonNumberToDBString ( osrfHash* field, jsonObject* value ) {
862         growing_buffer* val_buf = buffer_init(32);
863
864         if ( !strncmp(osrfHashGet(field, "datatype"), "INT", 3) ) {
865                 if (value->type == JSON_NUMBER) buffer_fadd( val_buf, "%ld", (long)jsonObjectGetNumber(value) );
866                 else buffer_fadd( val_buf, "%ld", atol(jsonObjectToSimpleString(value)) );
867
868         } else if ( !strcmp(osrfHashGet(field, "datatype"), "NUMERIC") ) {
869                 if (value->type == JSON_NUMBER) buffer_fadd( val_buf, "%f",  jsonObjectGetNumber(value) );
870                 else buffer_fadd( val_buf, "%f", atof(jsonObjectToSimpleString(value)) );
871         }
872
873         char* pred = buffer_data(val_buf);
874         buffer_free(val_buf);
875
876         return pred;
877 }
878
879 char* searchINPredicate (osrfHash* field, jsonObject* node) {
880         growing_buffer* sql_buf = buffer_init(32);
881         
882         buffer_fadd(
883                 sql_buf,
884                 "%s IN (",
885                 osrfHashGet(field, "name")
886         );
887
888         int in_item_index = 0;
889         int in_item_first = 1;
890         jsonObject* in_item;
891         while ( (in_item = jsonObjectGetIndex(node, in_item_index++)) ) {
892
893                 if (in_item_first)
894                         in_item_first = 0;
895                 else
896                         buffer_add(sql_buf, ", ");
897
898                 if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
899                         char* val = jsonNumberToDBString( field, in_item );
900                         buffer_fadd( sql_buf, "%s", val );
901                         free(val);
902
903                 } else {
904                         char* key_string = jsonObjectToSimpleString(in_item);
905                         if ( dbi_conn_quote_string(dbhandle, &key_string) ) {
906                                 buffer_fadd( sql_buf, "%s", key_string );
907                                 free(key_string);
908                         } else {
909                                 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key string [%s]", MODULENAME, key_string);
910                                 free(key_string);
911                                 buffer_free(sql_buf);
912                                 return NULL;
913                         }
914                 }
915         }
916
917         buffer_add(
918                 sql_buf,
919                 ")"
920         );
921
922         char* pred = buffer_data(sql_buf);
923         buffer_free(sql_buf);
924
925         return pred;
926 }
927
928 char* searchValueTransform( jsonObject* array ) {
929         growing_buffer* sql_buf = buffer_init(32);
930
931         char* val = NULL;
932         int func_item_index = 0;
933         int func_item_first = 2;
934         jsonObject* func_item;
935         while ( (func_item = jsonObjectGetIndex(array, func_item_index++)) ) {
936
937                 val = jsonObjectToSimpleString(func_item);
938
939                 if (func_item_first == 2) {
940                         buffer_fadd(sql_buf, "%s( ", val);
941                         free(val);
942                         func_item_first--;
943                         continue;
944                 }
945
946                 if (func_item_first)
947                         func_item_first--;
948                 else
949                         buffer_add(sql_buf, ", ");
950
951                 if ( dbi_conn_quote_string(dbhandle, &val) ) {
952                         buffer_fadd( sql_buf, "%s", val );
953                         free(val);
954                 } else {
955                         osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key string [%s]", MODULENAME, val);
956                         free(val);
957                         buffer_free(sql_buf);
958                         return NULL;
959                 }
960         }
961
962         buffer_add(
963                 sql_buf,
964                 " )"
965         );
966
967         char* pred = buffer_data(sql_buf);
968         buffer_free(sql_buf);
969
970         return pred;
971 }
972
973 char* searchFunctionPredicate (osrfHash* field, jsonObjectNode* node) {
974         growing_buffer* sql_buf = buffer_init(32);
975
976         char* val = searchValueTransform(node->item);
977         
978         buffer_fadd(
979                 sql_buf,
980                 "%s %s %s",
981                 osrfHashGet(field, "name"),
982                 node->key,
983                 val
984         );
985
986         char* pred = buffer_data(sql_buf);
987         buffer_free(sql_buf);
988         free(val);
989
990         return pred;
991 }
992
993 char* searchFieldTransformPredicate (osrfHash* field, jsonObjectNode* node) {
994         growing_buffer* sql_buf = buffer_init(32);
995         
996         char* field_transform = jsonObjectToSimpleString( jsonObjectGetKey( node->item, "transform" ) );
997         char* value = NULL;
998
999         if (jsonObjectGetKey( node->item, "value" )->type == JSON_ARRAY) {
1000                 value = searchValueTransform(jsonObjectGetKey( node->item, "value" ));
1001         } else if (jsonObjectGetKey( node->item, "value" )->type != JSON_NULL) {
1002                 if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1003                         value = jsonNumberToDBString( field, jsonObjectGetKey( node->item, "value" ) );
1004                 } else {
1005                         value = jsonObjectToSimpleString(jsonObjectGetKey( node->item, "value" ));
1006                         if ( !dbi_conn_quote_string(dbhandle, &value) ) {
1007                                 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key string [%s]", MODULENAME, value);
1008                                 free(value);
1009                                 return NULL;
1010                         }
1011                 }
1012         }
1013
1014         buffer_fadd(
1015                 sql_buf,
1016                 "%s(%s) %s %s",
1017                 field_transform,
1018                 osrfHashGet(field, "name"),
1019                 node->key,
1020                 value
1021         );
1022
1023         char* pred = buffer_data(sql_buf);
1024         buffer_free(sql_buf);
1025
1026         return pred;
1027 }
1028
1029 char* searchSimplePredicate (const char* orig_op, osrfHash* field, jsonObject* node) {
1030
1031         char* val = NULL;
1032
1033         if (node->type != JSON_NULL) {
1034                 if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1035                         val = jsonNumberToDBString( field, node );
1036                 } else {
1037                         val = jsonObjectToSimpleString(node);
1038                 }
1039         }
1040
1041         char* pred = searchWriteSimplePredicate( field, osrfHashGet(field, "name"), orig_op, val );
1042
1043         if (val) free(val);
1044
1045         return pred;
1046 }
1047
1048 char* searchWriteSimplePredicate ( osrfHash* field, const char* left, const char* orig_op, const char* right ) {
1049
1050         char* val = NULL;
1051         char* op = NULL;
1052         if (right == NULL) {
1053                 val = strdup("NULL");
1054
1055                 if (strcmp( orig_op, "=" ))
1056                         op = strdup("IS NOT");
1057                 else
1058                         op = strdup("IS");
1059
1060         } else if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1061                 val = strdup(right);
1062                 op = strdup(orig_op);
1063
1064         } else {
1065                 val = strdup(right);
1066                 if ( !dbi_conn_quote_string(dbhandle, &val) ) {
1067                         osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key string [%s]", MODULENAME, val);
1068                         free(val);
1069                         return NULL;
1070                 }
1071                 op = strdup(orig_op);
1072         }
1073
1074         growing_buffer* sql_buf = buffer_init(16);
1075         buffer_fadd( sql_buf, "%s %s %s", left, op, val );
1076         free(val);
1077         free(op);
1078
1079         char* pred = buffer_data(sql_buf);
1080         buffer_free(sql_buf);
1081
1082         return pred;
1083
1084 }
1085
1086 char* searchBETWEENPredicate (osrfHash* field, jsonObject* node) {
1087
1088         char* x_string;
1089         char* y_string;
1090
1091         if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1092                 x_string = jsonNumberToDBString(field, jsonObjectGetIndex(node,0));
1093                 y_string = jsonNumberToDBString(field, jsonObjectGetIndex(node,1));
1094
1095         } else {
1096                 x_string = jsonObjectToSimpleString(jsonObjectGetIndex(node,0));
1097                 y_string = jsonObjectToSimpleString(jsonObjectGetIndex(node,1));
1098                 if ( !(dbi_conn_quote_string(dbhandle, &x_string) && dbi_conn_quote_string(dbhandle, &y_string)) ) {
1099                         osrfLogError(OSRF_LOG_MARK, "%s: Error quoting key strings [%s] and [%s]", MODULENAME, x_string, y_string);
1100                         free(x_string);
1101                         free(y_string);
1102                         return NULL;
1103                 }
1104         }
1105
1106         growing_buffer* sql_buf = buffer_init(32);
1107         buffer_fadd( sql_buf, "%s BETWEEN %s AND %s", osrfHashGet(field, "name"), x_string, y_string );
1108         free(x_string);
1109         free(y_string);
1110
1111         char* pred = buffer_data(sql_buf);
1112         buffer_free(sql_buf);
1113
1114         return pred;
1115 }
1116
1117 char* searchPredicate ( osrfHash* field, jsonObject* node ) {
1118
1119         char* pred = NULL;
1120         if (node->type == JSON_ARRAY) { // equality IN search
1121                 pred = searchINPredicate( field, node );
1122         } else if (node->type == JSON_HASH) { // non-equality search
1123                 jsonObjectNode* pred_node;
1124                 jsonObjectIterator* pred_itr = jsonNewObjectIterator( node );
1125                 while ( (pred_node = jsonObjectIteratorNext( pred_itr )) ) {
1126                         if ( !(strcasecmp( pred_node->key,"between" )) )
1127                                 pred = searchBETWEENPredicate( field, pred_node->item );
1128                         else if ( !(strcasecmp( pred_node->key,"in" )) )
1129                                 pred = searchINPredicate( field, pred_node->item );
1130                         else if ( pred_node->item->type == JSON_ARRAY )
1131                                 pred = searchFunctionPredicate( field, pred_node );
1132                         else if ( pred_node->item->type == JSON_HASH )
1133                                 pred = searchFieldTransformPredicate( field, pred_node );
1134                         else 
1135                                 pred = searchSimplePredicate( pred_node->key, field, pred_node->item );
1136
1137                         break;
1138                 }
1139         } else if (node->type == JSON_NULL) { // IS NULL search
1140                 growing_buffer* _p = buffer_init(16);
1141                 buffer_fadd(
1142                         _p,
1143                         "%s IS NULL",
1144                         osrfHashGet(field, "name")
1145                 );
1146                 pred = buffer_data(_p);
1147                 buffer_free(_p);
1148         } else { // equality search
1149                 pred = searchSimplePredicate( "=", field, node );
1150         }
1151
1152         return pred;
1153
1154 }
1155
1156 jsonObject* doSearch(osrfMethodContext* ctx, osrfHash* meta, jsonObject* params, int* err ) {
1157
1158         // XXX for now...
1159         dbhandle = writehandle;
1160
1161         osrfHash* links = osrfHashGet(meta, "links");
1162         osrfHash* fields = osrfHashGet(meta, "fields");
1163         char* core_class = osrfHashGet(meta, "classname");
1164
1165         jsonObjectNode* node = NULL;
1166         jsonObjectNode* snode = NULL;
1167         jsonObject* _tmp;
1168         jsonObject* obj;
1169         jsonObject* search_hash = jsonObjectGetIndex(params, 0);
1170         jsonObject* order_hash = jsonObjectGetIndex(params, 1);
1171
1172         growing_buffer* sql_buf = buffer_init(128);
1173         buffer_add(sql_buf, "SELECT");
1174
1175         int first = 1;
1176         if ( (_tmp = jsonObjectGetKey( order_hash, "select" )) ) {
1177
1178                 jsonObjectIterator* class_itr = jsonNewObjectIterator( _tmp );
1179                 while ( (snode = jsonObjectIteratorNext( class_itr )) ) {
1180
1181                         osrfHash* idlClass = osrfHashGet( idl, snode->key );
1182                         if (!idlClass) continue;
1183                         char* cname = osrfHashGet(idlClass, "classname");
1184
1185                         jsonObjectIterator* select_itr = jsonNewObjectIterator( snode->item );
1186                         while ( (node = jsonObjectIteratorNext( select_itr )) ) {
1187                                 osrfHash* field = osrfHashGet( osrfHashGet( idlClass, "fields" ), jsonObjectToSimpleString(node->item) );
1188                                 char* fname = osrfHashGet(field, "name");
1189
1190                                 if (!field) continue;
1191
1192                                 if (first) {
1193                                         first = 0;
1194                                 } else {
1195                                         buffer_add(sql_buf, ",");
1196                                 }
1197
1198                                 buffer_fadd(sql_buf, " \"%s\".%s", cname, fname, cname, fname);
1199                         }
1200                 }
1201         } else {
1202                 buffer_add(sql_buf, " *");
1203         }
1204
1205         buffer_fadd(sql_buf, " FROM %s AS \"%s\" WHERE ", osrfHashGet(meta, "tablename"), core_class );
1206
1207
1208         char* pred;
1209         first = 1;
1210         jsonObjectIterator* search_itr = jsonNewObjectIterator( search_hash );
1211         while ( (node = jsonObjectIteratorNext( search_itr )) ) {
1212                 osrfHash* field = osrfHashGet( fields, node->key );
1213
1214                 if (!field) continue;
1215
1216                 if (first) {
1217                         first = 0;
1218                 } else {
1219                         buffer_add(sql_buf, " AND ");
1220                 }
1221
1222                 pred = searchPredicate( field, node->item);
1223                 buffer_fadd( sql_buf, "%s", pred );
1224                 free(pred);
1225         }
1226
1227         jsonObjectIteratorFree(search_itr);
1228
1229         if (order_hash) {
1230                 char* string;
1231                 if ( (_tmp = jsonObjectGetKey( jsonObjectGetKey( order_hash, "order_by" ), core_class ) ) ){
1232                         string = jsonObjectToSimpleString(_tmp);
1233                         buffer_fadd(
1234                                 sql_buf,
1235                                 " ORDER BY %s",
1236                                 string
1237                         );
1238                         free(string);
1239                 }
1240
1241                 if ( (_tmp = jsonObjectGetKey( order_hash, "limit" )) ){
1242                         string = jsonObjectToSimpleString(_tmp);
1243                         buffer_fadd(
1244                                 sql_buf,
1245                                 " LIMIT %d",
1246                                 atoi(string)
1247                         );
1248                         free(string);
1249                 }
1250
1251                 _tmp = jsonObjectGetKey( order_hash, "offset" );
1252                 if (_tmp) {
1253                         string = jsonObjectToSimpleString(_tmp);
1254                         buffer_fadd(
1255                                 sql_buf,
1256                                 " OFFSET %d",
1257                                 atoi(string)
1258                         );
1259                         free(string);
1260                 }
1261         }
1262
1263         buffer_add(sql_buf, ";");
1264
1265         char* sql = buffer_data(sql_buf);
1266         buffer_free(sql_buf);
1267         
1268         osrfLogDebug(OSRF_LOG_MARK, "%s SQL =  %s", MODULENAME, sql);
1269         dbi_result result = dbi_conn_query(dbhandle, sql);
1270
1271         jsonObject* res_list = jsonParseString("[]");
1272         if(result) {
1273                 osrfLogDebug(OSRF_LOG_MARK, "Query returned with no errors");
1274
1275                 if (dbi_result_first_row(result)) {
1276                         /* JSONify the result */
1277                         osrfLogDebug(OSRF_LOG_MARK, "Query returned at least one row");
1278                         do {
1279                                 obj = oilsMakeJSONFromResult( result, meta );
1280                                 jsonObjectPush(res_list, obj);
1281                         } while (dbi_result_next_row(result));
1282                 } else {
1283                         osrfLogDebug(OSRF_LOG_MARK, "%s returned no results for query %s", MODULENAME, sql);
1284                 }
1285
1286                 /* clean up the query */
1287                 dbi_result_free(result); 
1288
1289         } else {
1290                 osrfLogError(OSRF_LOG_MARK, "%s: Error retrieving %s with query [%s]", MODULENAME, osrfHashGet(meta, "fieldmapper"), sql);
1291                 osrfAppSessionStatus(
1292                         ctx->session,
1293                         OSRF_STATUS_INTERNALSERVERERROR,
1294                         "osrfMethodException",
1295                         ctx->request,
1296                         "Severe query error -- see error log for more details"
1297                 );
1298                 *err = -1;
1299                 free(sql);
1300                 jsonObjectFree(res_list);
1301                 return jsonNULL;
1302
1303         }
1304
1305         free(sql);
1306
1307         if (res_list->size && order_hash) {
1308                 _tmp = jsonObjectGetKey( order_hash, "flesh" );
1309                 if (_tmp) {
1310                         int x = (int)jsonObjectGetNumber(_tmp);
1311
1312                         jsonObject* flesh_blob = NULL;
1313                         if ((flesh_blob = jsonObjectGetKey( order_hash, "flesh_fields" )) && x > 0) {
1314
1315                                 flesh_blob = jsonObjectClone( flesh_blob );
1316                                 jsonObject* flesh_fields = jsonObjectGetKey( flesh_blob, core_class );
1317
1318                                 osrfStringArray* link_fields = NULL;
1319
1320                                 if (flesh_fields) {
1321                                         if (flesh_fields->size == 1) {
1322                                                 char* _t = jsonObjectToSimpleString( jsonObjectGetIndex( flesh_fields, 0 ) );
1323                                                 if (!strcmp(_t,"*")) link_fields = osrfHashKeys( links );
1324                                                 free(_t);
1325                                         }
1326
1327                                         if (!link_fields) {
1328                                                 jsonObjectNode* _f;
1329                                                 link_fields = osrfNewStringArray(1);
1330                                                 jsonObjectIterator* _i = jsonNewObjectIterator( flesh_fields );
1331                                                 while ((_f = jsonObjectIteratorNext( _i ))) {
1332                                                         osrfStringArrayAdd( link_fields, jsonObjectToSimpleString( _f->item ) );
1333                                                 }
1334                                         }
1335                                 }
1336
1337                                 jsonObjectNode* cur;
1338                                 jsonObjectIterator* itr = jsonNewObjectIterator( res_list );
1339                                 while ((cur = jsonObjectIteratorNext( itr ))) {
1340
1341                                         int i = 0;
1342                                         char* link_field;
1343                                         
1344                                         while ( (link_field = osrfStringArrayGetString(link_fields, i++)) ) {
1345
1346                                                 osrfLogDebug(OSRF_LOG_MARK, "Starting to flesh %s", link_field);
1347
1348                                                 osrfHash* kid_link = osrfHashGet(links, link_field);
1349                                                 if (!kid_link) continue;
1350
1351                                                 osrfHash* field = osrfHashGet(fields, link_field);
1352                                                 if (!field) continue;
1353
1354                                                 osrfHash* value_field = field;
1355
1356                                                 osrfHash* kid_idl = osrfHashGet(idl, osrfHashGet(kid_link, "class"));
1357                                                 if (!kid_idl) continue;
1358
1359                                                 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "has_many" ))) { // has_many
1360                                                         value_field = osrfHashGet( fields, osrfHashGet(meta, "primarykey") );
1361                                                 }
1362                                                         
1363                                                 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "might_have" ))) { // might_have
1364                                                         value_field = osrfHashGet( fields, osrfHashGet(meta, "primarykey") );
1365                                                 }
1366
1367                                                 osrfStringArray* link_map = osrfHashGet( kid_link, "map" );
1368
1369                                                 if (link_map->size > 0) {
1370                                                         jsonObject* _kid_key = jsonParseString("[]");
1371                                                         jsonObjectPush(
1372                                                                 _kid_key,
1373                                                                 jsonNewObject( osrfStringArrayGetString( link_map, 0 ) )
1374                                                         );
1375
1376                                                         jsonObjectSetKey(
1377                                                                 flesh_blob,
1378                                                                 osrfHashGet(kid_link, "class"),
1379                                                                 _kid_key
1380                                                         );
1381                                                 };
1382
1383                                                 osrfLogDebug(
1384                                                         OSRF_LOG_MARK,
1385                                                         "Link field: %s, remote class: %s, fkey: %s, reltype: %s",
1386                                                         osrfHashGet(kid_link, "field"),
1387                                                         osrfHashGet(kid_link, "class"),
1388                                                         osrfHashGet(kid_link, "key"),
1389                                                         osrfHashGet(kid_link, "reltype")
1390                                                 );
1391
1392                                                 jsonObject* fake_params = jsonParseString("[]");
1393                                                 jsonObjectPush(fake_params, jsonParseString("{}")); // search hash
1394                                                 jsonObjectPush(fake_params, jsonParseString("{}")); // order/flesh hash
1395
1396                                                 osrfLogDebug(OSRF_LOG_MARK, "Creating dummy params object...");
1397
1398                                                 char* search_key =
1399                                                 jsonObjectToSimpleString(
1400                                                         jsonObjectGetIndex(
1401                                                                 cur->item,
1402                                                                 atoi( osrfHashGet(value_field, "array_position") )
1403                                                         )
1404                                                 );
1405
1406                                                 if (!search_key) {
1407                                                         osrfLogDebug(OSRF_LOG_MARK, "Nothing to search for!");
1408                                                         continue;
1409                                                 }
1410                                                         
1411                                                 jsonObjectSetKey(
1412                                                         jsonObjectGetIndex(fake_params, 0),
1413                                                         osrfHashGet(kid_link, "key"),
1414                                                         jsonNewObject( search_key )
1415                                                 );
1416
1417                                                 free(search_key);
1418
1419
1420                                                 jsonObjectSetKey(
1421                                                         jsonObjectGetIndex(fake_params, 1),
1422                                                         "flesh",
1423                                                         jsonNewNumberObject( (double)(x - 1 + link_map->size) )
1424                                                 );
1425
1426                                                 if (flesh_blob)
1427                                                         jsonObjectSetKey( jsonObjectGetIndex(fake_params, 1), "flesh_fields", jsonObjectClone(flesh_blob) );
1428
1429                                                 if (jsonObjectGetKey(order_hash, "order_by")) {
1430                                                         jsonObjectSetKey(
1431                                                                 jsonObjectGetIndex(fake_params, 1),
1432                                                                 "order_by",
1433                                                                 jsonObjectClone(jsonObjectGetKey(order_hash, "order_by"))
1434                                                         );
1435                                                 }
1436
1437                                                 jsonObject* kids = doSearch(ctx, kid_idl, fake_params, err);
1438
1439                                                 if(*err) {
1440                                                         jsonObjectFree( fake_params );
1441                                                         osrfStringArrayFree(link_fields);
1442                                                         jsonObjectIteratorFree(itr);
1443                                                         jsonObjectFree(res_list);
1444                                                         return jsonNULL;
1445                                                 }
1446
1447                                                 osrfLogDebug(OSRF_LOG_MARK, "Search for %s return %d linked objects", osrfHashGet(kid_link, "class"), kids->size);
1448
1449                                                 jsonObject* X = NULL;
1450                                                 if ( link_map->size > 0 && kids->size > 0 ) {
1451                                                         X = kids;
1452                                                         kids = jsonParseString("[]");
1453
1454                                                         jsonObjectNode* _k_node;
1455                                                         jsonObjectIterator* _k = jsonNewObjectIterator( X );
1456                                                         while ((_k_node = jsonObjectIteratorNext( _k ))) {
1457                                                                 jsonObjectPush(
1458                                                                         kids,
1459                                                                         jsonObjectClone(
1460                                                                                 jsonObjectGetIndex(
1461                                                                                         _k_node->item,
1462                                                                                         (unsigned long)atoi(
1463                                                                                                 osrfHashGet(
1464                                                                                                         osrfHashGet(
1465                                                                                                                 osrfHashGet(
1466                                                                                                                         osrfHashGet(
1467                                                                                                                                 idl,
1468                                                                                                                                 osrfHashGet(kid_link, "class")
1469                                                                                                                         ),
1470                                                                                                                         "fields"
1471                                                                                                                 ),
1472                                                                                                                 osrfStringArrayGetString( link_map, 0 )
1473                                                                                                         ),
1474                                                                                                         "array_position"
1475                                                                                                 )
1476                                                                                         )
1477                                                                                 )
1478                                                                         )
1479                                                                 );
1480                                                         }
1481                                                 }
1482
1483                                                 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "has_a" ))) {
1484                                                         osrfLogDebug(OSRF_LOG_MARK, "Storing fleshed objects in %s", osrfHashGet(kid_link, "field"));
1485                                                         jsonObjectSetIndex(
1486                                                                 cur->item,
1487                                                                 (unsigned long)atoi( osrfHashGet( field, "array_position" ) ),
1488                                                                 jsonObjectClone( jsonObjectGetIndex(kids, 0) )
1489                                                         );
1490                                                 }
1491
1492                                                 if (!(strcmp( osrfHashGet(kid_link, "reltype"), "has_many" ))) { // has_many
1493                                                         osrfLogDebug(OSRF_LOG_MARK, "Storing fleshed objects in %s", osrfHashGet(kid_link, "field"));
1494                                                         jsonObjectSetIndex(
1495                                                                 cur->item,
1496                                                                 (unsigned long)atoi( osrfHashGet( field, "array_position" ) ),
1497                                                                 jsonObjectClone( kids )
1498                                                         );
1499                                                 }
1500
1501                                                 if (X) {
1502                                                         jsonObjectFree(kids);
1503                                                         kids = X;
1504                                                 }
1505
1506                                                 jsonObjectFree( kids );
1507                                                 jsonObjectFree( fake_params );
1508
1509                                                 osrfLogDebug(OSRF_LOG_MARK, "Fleshing of %s complete", osrfHashGet(kid_link, "field"));
1510                                                 osrfLogDebug(OSRF_LOG_MARK, "%s", jsonObjectToJSON(cur->item));
1511
1512                                         }
1513                                 }
1514                                 jsonObjectFree( flesh_blob );
1515                                 osrfStringArrayFree(link_fields);
1516                                 jsonObjectIteratorFree(itr);
1517                         }
1518                 }
1519         }
1520
1521         return res_list;
1522 }
1523
1524
1525 jsonObject* doUpdate(osrfMethodContext* ctx, int* err ) {
1526
1527         osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
1528         jsonObject* target = jsonObjectGetIndex(ctx->params, 0);
1529
1530         if (!verifyObjectClass(ctx, target)) {
1531                 *err = -1;
1532                 return jsonNULL;
1533         }
1534
1535         if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
1536                 osrfAppSessionStatus(
1537                         ctx->session,
1538                         OSRF_STATUS_BADREQUEST,
1539                         "osrfMethodException",
1540                         ctx->request,
1541                         "No active transaction -- required for UPDATE"
1542                 );
1543                 *err = -1;
1544                 return jsonNULL;
1545         }
1546
1547         dbhandle = writehandle;
1548
1549         char* pkey = osrfHashGet(meta, "primarykey");
1550         osrfHash* fields = osrfHashGet(meta, "fields");
1551
1552         char* id =
1553                 jsonObjectToSimpleString(
1554                         jsonObjectGetIndex(
1555                                 target,
1556                                 atoi( osrfHashGet( osrfHashGet( fields, pkey ), "array_position" ) )
1557                         )
1558                 );
1559
1560         osrfLogDebug(
1561                 OSRF_LOG_MARK,
1562                 "%s updating %s object with %s = %s",
1563                 MODULENAME,
1564                 osrfHashGet(meta, "fieldmapper"),
1565                 pkey,
1566                 id
1567         );
1568
1569         growing_buffer* sql = buffer_init(128);
1570         buffer_fadd(sql,"UPDATE %s SET", osrfHashGet(meta, "tablename"));
1571
1572         int i = 0;
1573         int first = 1;
1574         char* field_name;
1575         osrfStringArray* field_list = osrfHashKeys( fields );
1576         while ( (field_name = osrfStringArrayGetString(field_list, i++)) ) {
1577
1578                 osrfHash* field = osrfHashGet( fields, field_name );
1579
1580                 if(!( strcmp( field_name, pkey ) )) continue;
1581                 if(!( strcmp( osrfHashGet(osrfHashGet(fields,field_name), "virtual"), "true" ) )) continue;
1582
1583                 int pos = atoi(osrfHashGet(field, "array_position"));
1584                 char* value = jsonObjectToSimpleString( jsonObjectGetIndex( target, pos ) );
1585
1586                 osrfLogDebug( OSRF_LOG_MARK, "Updating %s object with %s = %s", osrfHashGet(meta, "fieldmapper"), field_name, value);
1587
1588                 if (jsonObjectGetIndex(target, pos)->type == JSON_NULL) {
1589                         if ( !(!( strcmp( osrfHashGet(meta, "classname"), "au" ) ) && !( strcmp( field_name, "passwd" ) )) ) { // arg at the special case!
1590                                 if (first) first = 0;
1591                                 else buffer_add(sql, ",");
1592                                 buffer_fadd( sql, " %s = NULL", field_name );
1593                         }
1594                         
1595                 } else if ( !strcmp(osrfHashGet(field, "primitive"), "number") ) {
1596                         if (first) first = 0;
1597                         else buffer_add(sql, ",");
1598
1599                         if ( !strncmp(osrfHashGet(field, "datatype"), "INT", (size_t)3) ) {
1600                                 buffer_fadd( sql, " %s = %ld", field_name, atol(value) );
1601                         } else if ( !strcmp(osrfHashGet(field, "datatype"), "NUMERIC") ) {
1602                                 buffer_fadd( sql, " %s = %f", field_name, atof(value) );
1603                         }
1604
1605                         osrfLogDebug( OSRF_LOG_MARK, "%s is of type %s", field_name, osrfHashGet(field, "datatype"));
1606
1607                 } else {
1608                         if ( dbi_conn_quote_string(dbhandle, &value) ) {
1609                                 if (first) first = 0;
1610                                 else buffer_add(sql, ",");
1611                                 buffer_fadd( sql, " %s = %s", field_name, value );
1612
1613                         } else {
1614                                 osrfLogError(OSRF_LOG_MARK, "%s: Error quoting string [%s]", MODULENAME, value);
1615                                 osrfAppSessionStatus(
1616                                         ctx->session,
1617                                         OSRF_STATUS_INTERNALSERVERERROR,
1618                                         "osrfMethodException",
1619                                         ctx->request,
1620                                         "Error quoting string -- please see the error log for more details"
1621                                 );
1622                                 free(value);
1623                                 free(id);
1624                                 buffer_free(sql);
1625                                 *err = -1;
1626                                 return jsonNULL;
1627                         }
1628                 }
1629
1630                 free(value);
1631                 
1632         }
1633
1634         jsonObject* obj = jsonParseString(id);
1635
1636         if ( strcmp( osrfHashGet( osrfHashGet( osrfHashGet(meta, "fields"), pkey ), "primitive" ), "number" ) )
1637                 dbi_conn_quote_string(dbhandle, &id);
1638
1639         buffer_fadd( sql, " WHERE %s = %s;", pkey, id );
1640
1641         char* query = buffer_data(sql);
1642         buffer_free(sql);
1643
1644         osrfLogDebug(OSRF_LOG_MARK, "%s: Update SQL [%s]", MODULENAME, query);
1645
1646         dbi_result result = dbi_conn_query(dbhandle, query);
1647         free(query);
1648
1649         if (!result) {
1650                 jsonObjectFree(obj);
1651                 obj = jsonNewObject(NULL);
1652                 osrfLogError(
1653                         OSRF_LOG_MARK,
1654                         "%s ERROR updating %s object with %s = %s",
1655                         MODULENAME,
1656                         osrfHashGet(meta, "fieldmapper"),
1657                         pkey,
1658                         id
1659                 );
1660         }
1661
1662         free(id);
1663
1664         return obj;
1665 }
1666
1667 jsonObject* doDelete(osrfMethodContext* ctx, int* err ) {
1668
1669         osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
1670
1671         if (!osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" )) {
1672                 osrfAppSessionStatus(
1673                         ctx->session,
1674                         OSRF_STATUS_BADREQUEST,
1675                         "osrfMethodException",
1676                         ctx->request,
1677                         "No active transaction -- required for DELETE"
1678                 );
1679                 *err = -1;
1680                 return jsonNULL;
1681         }
1682
1683         dbhandle = writehandle;
1684
1685         jsonObject* obj;
1686
1687         char* pkey = osrfHashGet(meta, "primarykey");
1688
1689         char* id;
1690         if (jsonObjectGetIndex(ctx->params, 0)->classname) {
1691                 if (!verifyObjectClass(ctx, jsonObjectGetIndex( ctx->params, 0 ))) {
1692                         *err = -1;
1693                         return jsonNULL;
1694                 }
1695
1696                 id = jsonObjectToSimpleString(
1697                         jsonObjectGetIndex(
1698                                 jsonObjectGetIndex(ctx->params, 0),
1699                                 atoi( osrfHashGet( osrfHashGet( osrfHashGet(meta, "fields"), pkey ), "array_position") )
1700                         )
1701                 );
1702         } else {
1703                 id = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
1704         }
1705
1706         osrfLogDebug(
1707                 OSRF_LOG_MARK,
1708                 "%s deleting %s object with %s = %s",
1709                 MODULENAME,
1710                 osrfHashGet(meta, "fieldmapper"),
1711                 pkey,
1712                 id
1713         );
1714
1715         obj = jsonParseString(id);
1716
1717         if ( strcmp( osrfHashGet( osrfHashGet( osrfHashGet(meta, "fields"), pkey ), "primitive" ), "number" ) )
1718                 dbi_conn_quote_string(writehandle, &id);
1719
1720         dbi_result result = dbi_conn_queryf(writehandle, "DELETE FROM %s WHERE %s = %s;", osrfHashGet(meta, "tablename"), pkey, id);
1721
1722         if (!result) {
1723                 jsonObjectFree(obj);
1724                 obj = jsonNewObject(NULL);
1725                 osrfLogError(
1726                         OSRF_LOG_MARK,
1727                         "%s ERROR deleting %s object with %s = %s",
1728                         MODULENAME,
1729                         osrfHashGet(meta, "fieldmapper"),
1730                         pkey,
1731                         id
1732                 );
1733         }
1734
1735         free(id);
1736
1737         return obj;
1738
1739 }
1740
1741
1742 jsonObject* oilsMakeJSONFromResult( dbi_result result, osrfHash* meta) {
1743         if(!(result && meta)) return jsonNULL;
1744
1745         jsonObject* object = jsonParseString("[]");
1746         jsonObjectSetClass(object, osrfHashGet(meta, "classname"));
1747
1748         osrfHash* fields = osrfHashGet(meta, "fields");
1749
1750         osrfLogDebug(OSRF_LOG_MARK, "Setting object class to %s ", object->classname);
1751
1752         osrfHash* _f;
1753         time_t _tmp_dt;
1754         char dt_string[256];
1755         struct tm gmdt;
1756
1757         int fmIndex;
1758         int columnIndex = 1;
1759         int attr;
1760         unsigned short type;
1761         const char* columnName;
1762
1763         /* cycle through the column list */
1764         while( (columnName = dbi_result_get_field_name(result, columnIndex++)) ) {
1765
1766                 osrfLogDebug(OSRF_LOG_MARK, "Looking for column named [%s]...", (char*)columnName);
1767
1768                 fmIndex = -1; // reset the position
1769                 
1770                 /* determine the field type and storage attributes */
1771                 type = dbi_result_get_field_type(result, columnName);
1772                 attr = dbi_result_get_field_attribs(result, columnName);
1773
1774                 /* fetch the fieldmapper index */
1775                 if( (_f = osrfHashGet(fields, (char*)columnName)) ) {
1776                         char* virt = (char*)osrfHashGet(_f, "virtual");
1777                         char* pos = (char*)osrfHashGet(_f, "array_position");
1778
1779                         if ( !virt || !pos || !(strcmp( virt, "true" )) ) continue;
1780
1781                         fmIndex = atoi( pos );
1782                         osrfLogDebug(OSRF_LOG_MARK, "... Found column at position [%s]...", pos);
1783                 } else {
1784                         continue;
1785                 }
1786
1787                 if (dbi_result_field_is_null(result, columnName)) {
1788                         jsonObjectSetIndex( object, fmIndex, jsonNewObject(NULL) );
1789                 } else {
1790
1791                         switch( type ) {
1792
1793                                 case DBI_TYPE_INTEGER :
1794
1795                                         if( attr & DBI_INTEGER_SIZE8 ) 
1796                                                 jsonObjectSetIndex( object, fmIndex, 
1797                                                         jsonNewNumberObject(dbi_result_get_longlong(result, columnName)));
1798                                         else 
1799                                                 jsonObjectSetIndex( object, fmIndex, 
1800                                                         jsonNewNumberObject(dbi_result_get_long(result, columnName)));
1801
1802                                         break;
1803
1804                                 case DBI_TYPE_DECIMAL :
1805                                         jsonObjectSetIndex( object, fmIndex, 
1806                                                         jsonNewNumberObject(dbi_result_get_double(result, columnName)));
1807                                         break;
1808
1809                                 case DBI_TYPE_STRING :
1810
1811
1812                                         jsonObjectSetIndex(
1813                                                 object,
1814                                                 fmIndex,
1815                                                 jsonNewObject( dbi_result_get_string(result, columnName) )
1816                                         );
1817
1818                                         break;
1819
1820                                 case DBI_TYPE_DATETIME :
1821
1822                                         memset(dt_string, '\0', 256);
1823                                         memset(&gmdt, '\0', sizeof(gmdt));
1824                                         memset(&_tmp_dt, '\0', sizeof(_tmp_dt));
1825
1826                                         _tmp_dt = dbi_result_get_datetime(result, columnName);
1827
1828                                         localtime_r( &_tmp_dt, &gmdt );
1829
1830                                         if (!(attr & DBI_DATETIME_DATE)) {
1831                                                 strftime(dt_string, 255, "%T", &gmdt);
1832                                         } else if (!(attr & DBI_DATETIME_TIME)) {
1833                                                 strftime(dt_string, 255, "%F", &gmdt);
1834                                         } else {
1835                                                 strftime(dt_string, 255, "%FT%T%z", &gmdt);
1836                                         }
1837
1838                                         jsonObjectSetIndex( object, fmIndex, jsonNewObject(dt_string) );
1839
1840                                         break;
1841
1842                                 case DBI_TYPE_BINARY :
1843                                         osrfLogError( OSRF_LOG_MARK, 
1844                                                 "Can't do binary at column %s : index %d", columnName, columnIndex - 1);
1845                         }
1846                 }
1847         }
1848
1849         return object;
1850 }
1851