]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/c-apps/oils_cstore.c
timestamp handling is fixed... I need to send a patch to the libdbi folks
[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 <dbi/dbi.h>
10
11 #include <time.h>
12 #include <stdlib.h>
13 #include <string.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>
20 //#include <openils/fieldmapper_lookup.h>
21
22 #define OILS_AUTH_CACHE_PRFX "oils_cstore_"
23 #define MODULENAME "open-ils.cstore"
24 #define PERSIST_NS "http://open-ils.org/spec/opensrf/IDL/persistance/v1"
25 #define OBJECT_NS "http://open-ils.org/spec/opensrf/IDL/objects/v1"
26 #define BASE_NS "http://opensrf.org/spec/IDL/base/v1"
27
28 int osrfAppChildInit();
29 int osrfAppInitialize();
30
31 int dispatchCRUDMethod ( osrfMethodContext* );
32 jsonObject* doCreate ( osrfHash*, jsonObject* );
33 jsonObject* doRetrieve ( osrfHash*, jsonObject* );
34 jsonObject* doUpdate ( osrfHash*, jsonObject* );
35 jsonObject* doDelete ( osrfHash*, jsonObject* );
36 jsonObject* oilsMakeJSONFromResult( dbi_result, osrfHash* );
37
38 dbi_conn dbhandle; /* our db connection */
39 xmlDocPtr idlDoc = NULL; // parse and store the IDL here
40
41
42 /* parse and store the IDL here */
43 osrfHash* idlHash;
44
45 int osrfAppInitialize() {
46
47         idlHash = osrfNewHash();
48
49         osrfLogInfo(OSRF_LOG_MARK, "Initializing the CStore Server...");
50         osrfLogInfo(OSRF_LOG_MARK, "Finding XML file...");
51
52         char * idl_filename = osrf_settings_host_value("/apps/%s/app_settings/IDL", MODULENAME);
53         osrfLogInfo(OSRF_LOG_MARK, "Found file:");
54         osrfLogInfo(OSRF_LOG_MARK, idl_filename);
55
56         osrfLogInfo(OSRF_LOG_MARK, "Parsing the IDL XML...");
57         idlDoc = xmlReadFile( idl_filename, NULL, XML_PARSE_XINCLUDE );
58         
59         if (!idlDoc) {
60                 osrfLogError(OSRF_LOG_MARK, "Could not load or parse the IDL XML file!");
61                 exit(1);
62         }
63
64         osrfLogInfo(OSRF_LOG_MARK, "...IDL XML parsed");
65
66         osrfStringArray* global_methods = osrfNewStringArray(1);
67
68         //osrfStringArrayAdd( global_methods, "create" );
69         osrfStringArrayAdd( global_methods, "retrieve" );
70         //osrfStringArrayAdd( global_methods, "update" );
71         //osrfStringArrayAdd( global_methods, "delete" );
72
73         xmlNodePtr docRoot = xmlDocGetRootElement(idlDoc);
74         xmlNodePtr kid = docRoot->children;
75         while (kid) {
76                 if (!strcmp( (char*)kid->name, "class" )) {
77                         int i = 0; 
78                         char* method_type;
79                         while ( (method_type = osrfStringArrayGetString(global_methods, i++)) ) {
80
81                                 osrfHash * usrData = osrfNewHash();
82                                 osrfHashSet( usrData, xmlGetProp(kid, "id"), "classname");
83                                 osrfHashSet( usrData, xmlGetNsProp(kid, "tablename", PERSIST_NS), "tablename");
84                                 osrfHashSet( usrData, xmlGetNsProp(kid, "fieldmapper", OBJECT_NS), "fieldmapper");
85
86                                 if(!strcmp(method_type, "retrieve"))
87                                         osrfHashSet( idlHash, usrData, (char*)osrfHashGet(usrData, "classname") );
88
89                                 osrfLogInfo(OSRF_LOG_MARK, "Generating class methods for %s", osrfHashGet(usrData, "fieldmapper") );
90
91                                 osrfHash* _tmp;
92                                 osrfHash* links = osrfNewHash();
93                                 osrfHash* fields = osrfNewHash();
94
95                                 osrfHashSet( usrData, fields, "fields" );
96                                 osrfHashSet( usrData, links, "links" );
97
98                                 xmlNodePtr _cur = kid->children;
99
100                                 while (_cur) {
101                                         char* string_tmp = NULL;
102
103                                         if (!strcmp( (char*)_cur->name, "fields" )) {
104
105                                                 if( (string_tmp = (char*)xmlGetNsProp(_cur, "primary", PERSIST_NS)) ) {
106                                                         osrfHashSet(
107                                                                 usrData,
108                                                                 strdup( string_tmp ),
109                                                                 "primarykey"
110                                                         );
111                                                 }
112                                                 string_tmp = NULL;
113
114                                                 xmlNodePtr _f = _cur->children;
115
116                                                 while(_f) {
117                                                         if (strcmp( (char*)_f->name, "field" )) {
118                                                                 _f = _f->next;
119                                                                 continue;
120                                                         }
121
122                                                         _tmp = osrfNewHash();
123
124                                                         if( (string_tmp = (char*)xmlGetNsProp(_f, "array_position", OBJECT_NS)) ) {
125                                                                 osrfHashSet(
126                                                                         _tmp,
127                                                                         strdup( string_tmp ),
128                                                                         "array_position"
129                                                                 );
130                                                         }
131                                                         string_tmp = NULL;
132
133                                                         if( (string_tmp = (char*)xmlGetNsProp(_f, "virtual", PERSIST_NS)) ) {
134                                                                 osrfHashSet(
135                                                                         _tmp,
136                                                                         strdup( string_tmp ),
137                                                                         "virtual"
138                                                                 );
139                                                         }
140                                                         string_tmp = NULL;
141
142                                                         if( (string_tmp = (char*)xmlGetProp(_f, "name")) ) {
143                                                                 osrfHashSet(
144                                                                         _tmp,
145                                                                         strdup( string_tmp ),
146                                                                         "name"
147                                                                 );
148                                                         }
149
150                                                         osrfLogInfo(OSRF_LOG_MARK, "Found field %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
151
152                                                         osrfHashSet(
153                                                                 fields,
154                                                                 _tmp,
155                                                                 strdup( string_tmp )
156                                                         );
157                                                         _f = _f->next;
158                                                 }
159                                         }
160
161                                         if (!strcmp( (char*)_cur->name, "links" )) {
162                                                 xmlNodePtr _l = _cur->children;
163
164                                                 while(_l) {
165                                                         if (strcmp( (char*)_l->name, "link" )) {
166                                                                 _l = _l->next;
167                                                                 continue;
168                                                         }
169
170                                                         _tmp = osrfNewHash();
171
172                                                         if( (string_tmp = (char*)xmlGetProp(_l, "reltype")) ) {
173                                                                 osrfHashSet(
174                                                                         _tmp,
175                                                                         strdup( string_tmp ),
176                                                                         "reltype"
177                                                                 );
178                                                         }
179                                                         osrfLogInfo(OSRF_LOG_MARK, "Adding link with reltype %s", string_tmp );
180                                                         string_tmp = NULL;
181
182                                                         if( (string_tmp = (char*)xmlGetProp(_l, "key")) ) {
183                                                                 osrfHashSet(
184                                                                         _tmp,
185                                                                         strdup( string_tmp ),
186                                                                         "key"
187                                                                 );
188                                                         }
189                                                         osrfLogInfo(OSRF_LOG_MARK, "Link fkey is %s", string_tmp );
190                                                         string_tmp = NULL;
191
192                                                         if( (string_tmp = (char*)xmlGetProp(_l, "class")) ) {
193                                                                 osrfHashSet(
194                                                                         _tmp,
195                                                                         strdup( string_tmp ),
196                                                                         "class"
197                                                                 );
198                                                         }
199                                                         osrfLogInfo(OSRF_LOG_MARK, "Link fclass is %s", string_tmp );
200                                                         string_tmp = NULL;
201
202                                                         osrfStringArray* map = osrfNewStringArray(0);
203
204                                                         if( (string_tmp = (char*)xmlGetProp(_l, "map") )) {
205                                                                 char* map_list = strdup( string_tmp );
206                                                                 osrfLogInfo(OSRF_LOG_MARK, "Link mapping list is %s", string_tmp );
207
208                                                                 if (strlen( map_list ) > 0) {
209                                                                         char* st_tmp;
210                                                                         char* _map_class = strtok_r(map_list, " ", &st_tmp);
211                                                                         osrfStringArrayAdd(map, strdup(_map_class));
212                                                         
213                                                                         while ((_map_class = strtok_r(NULL, " ", &st_tmp))) {
214                                                                                 osrfStringArrayAdd(map, strdup(_map_class));
215                                                                         }
216                                                                 }
217                                                         }
218                                                         osrfHashSet( _tmp, map, "map");
219
220                                                         if( (string_tmp = (char*)xmlGetProp(_l, "field")) ) {
221                                                                 osrfHashSet(
222                                                                         _tmp,
223                                                                         strdup( string_tmp ),
224                                                                         "field"
225                                                                 );
226                                                         }
227
228                                                         osrfHashSet(
229                                                                 links,
230                                                                 _tmp,
231                                                                 strdup( string_tmp )
232                                                         );
233
234                                                         osrfLogInfo(OSRF_LOG_MARK, "Found link %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
235
236                                                         _l = _l->next;
237                                                 }
238                                         }
239
240                                         _cur = _cur->next;
241                                 }
242
243
244                                 char* st_tmp;
245                                 char* _fm;
246                                 if (!osrfHashGet(usrData, "fieldmapper")) continue;
247
248                                 _fm = strdup( (char*)osrfHashGet(usrData, "fieldmapper") );
249                                 char* part = strtok_r(_fm, ":", &st_tmp);
250
251                                 growing_buffer* method_name =  buffer_init(64);
252                                 buffer_fadd(method_name, "%s.direct.%s", MODULENAME, part);
253
254                                 while ((part = strtok_r(NULL, ":", &st_tmp))) {
255                                         buffer_fadd(method_name, ".%s", part);
256                                 }
257                                 buffer_fadd(method_name, ".%s", method_type);
258
259                                 char* method = buffer_data(method_name);
260                                 buffer_free(method_name);
261
262                                 osrfHashSet( usrData, method, "methodname" );
263                                 osrfHashSet( usrData, strdup(method_type), "methodtype" );
264
265                                 osrfAppRegisterExtendedMethod(
266                                         MODULENAME,
267                                         method,
268                                         "dispatchCRUDMethod",
269                                         "",
270                                         1,
271                                         0,
272                                         (void*)usrData
273                                 );
274                         }
275                 }
276                 kid = kid->next;
277         }
278
279         return 0;
280 }
281
282 /**
283  * Connects to the database 
284  */
285 int osrfAppChildInit() {
286
287         osrfLogDebug(OSRF_LOG_MARK, "Attempting to initialize libdbi...");
288         dbi_initialize(NULL);
289         osrfLogDebug(OSRF_LOG_MARK, "... libdbi initialized.");
290
291         char* driver    = osrf_settings_host_value("/apps/%s/app_settings/driver", MODULENAME);
292         char* user      = osrf_settings_host_value("/apps/%s/app_settings/database/user", MODULENAME);
293         char* host      = osrf_settings_host_value("/apps/%s/app_settings/database/host", MODULENAME);
294         char* port      = osrf_settings_host_value("/apps/%s/app_settings/database/port", MODULENAME);
295         char* db        = osrf_settings_host_value("/apps/%s/app_settings/database/db", MODULENAME);
296         char* pw        = osrf_settings_host_value("/apps/%s/app_settings/database/pw", MODULENAME);
297
298         osrfLogDebug(OSRF_LOG_MARK, "Attempting to load the database driver [%s]...", driver);
299         dbhandle = dbi_conn_new(driver);
300
301         if(!dbhandle) {
302                 osrfLogError(OSRF_LOG_MARK, "Error loading database driver [%s]", driver);
303                 return -1;
304         }
305         osrfLogDebug(OSRF_LOG_MARK, "Database driver [%s] seems OK", driver);
306
307         osrfLogInfo(OSRF_LOG_MARK, "%s connecting to database.  host=%s, "
308                 "port=%s, user=%s, pw=%s, db=%s", MODULENAME, host, port, user, pw, db );
309
310         if(host) dbi_conn_set_option(dbhandle, "host", host );
311         if(port) dbi_conn_set_option_numeric( dbhandle, "port", atoi(port) );
312         if(user) dbi_conn_set_option(dbhandle, "username", user);
313         if(pw) dbi_conn_set_option(dbhandle, "password", pw );
314         if(db) dbi_conn_set_option(dbhandle, "dbname", db );
315
316         free(user);
317         free(host);
318         free(port);
319         free(db);
320         free(pw);
321
322         const char* err;
323         if (dbi_conn_connect(dbhandle) < 0) {
324                 dbi_conn_error(dbhandle, &err);
325                 osrfLogError( OSRF_LOG_MARK, "Error connecting to database: %s", err);
326                 return -1;
327         }
328
329         osrfLogInfo(OSRF_LOG_MARK, "%s successfully connected to the database", MODULENAME);
330
331         int attr;
332         unsigned short type;
333         int i = 0; 
334         char* classname;
335         osrfStringArray* classes = osrfHashKeys( idlHash );
336         
337         while ( (classname = osrfStringArrayGetString(classes, i++)) ) {
338                 osrfHash* class = osrfHashGet( idlHash, classname );
339                 osrfHash* fields = osrfHashGet( class, "fields" );
340                 
341                 growing_buffer* sql_buf = buffer_init(32);
342                 buffer_fadd( sql_buf, "SELECT * FROM %s WHERE 1=0;", osrfHashGet(class, "tablename") );
343
344                 char* sql = buffer_data(sql_buf);
345                 buffer_free(sql_buf);
346                 osrfLogDebug(OSRF_LOG_MARK, "%s Investigatory SQL = %s", MODULENAME, sql);
347
348                 dbi_result result = dbi_conn_query(dbhandle, sql);
349                 free(sql);
350
351                 if (result) {
352
353                         int columnIndex = 1;
354                         const char* columnName;
355                         osrfHash* _f;
356                         while( (columnName = dbi_result_get_field_name(result, columnIndex++)) ) {
357
358                                 osrfLogDebug(OSRF_LOG_MARK, "Looking for column named [%s]...", (char*)columnName);
359
360                                 /* fetch the fieldmapper index */
361                                 if( (_f = osrfHashGet(fields, (char*)columnName)) ) {
362
363                                         osrfLogDebug(OSRF_LOG_MARK, "Found [%s] in IDL hash...", (char*)columnName);
364
365                                         /* determine the field type and storage attributes */
366                                         type = dbi_result_get_field_type(result, columnName);
367                                         attr = dbi_result_get_field_attribs(result, columnName);
368
369                                         switch( type ) {
370
371                                                 case DBI_TYPE_INTEGER :
372
373                                                         osrfHashSet(_f,"number", "primitive");
374
375                                                         if( attr & DBI_INTEGER_SIZE8 ) 
376                                                                 osrfHashSet(_f,"INT8", "datatype");
377                                                         else 
378                                                                 osrfHashSet(_f,"INT", "datatype");
379                                                         break;
380
381                                                 case DBI_TYPE_DECIMAL :
382                                                         osrfHashSet(_f,"number", "primitive");
383                                                         osrfHashSet(_f,"NUMERIC", "datatype");
384                                                         break;
385
386                                                 case DBI_TYPE_STRING :
387                                                         osrfHashSet(_f,"string", "primitive");
388                                                         osrfHashSet(_f,"TEXT", "datatype");
389                                                         break;
390
391                                                 case DBI_TYPE_DATETIME :
392                                                         osrfHashSet(_f,"string", "primitive");
393                                                         osrfHashSet(_f,"TIMESTAMP", "datatype");
394                                                         break;
395
396                                                 case DBI_TYPE_BINARY :
397                                                         osrfHashSet(_f,"string", "primitive");
398                                                         osrfHashSet(_f,"BYTEA", "datatype");
399                                         }
400
401                                         osrfLogDebug(
402                                                 OSRF_LOG_MARK,
403                                                 "Setting [%s] to primitive [%s] and datatype [%s]...",
404                                                 (char*)columnName,
405                                                 osrfHashGet(_f, "primitive"),
406                                                 osrfHashGet(_f, "datatype")
407                                         );
408                                 }
409                         }
410                         dbi_result_free(result);
411                 } else {
412                         osrfLogDebug(OSRF_LOG_MARK, "No data found for class [%s]...", (char*)classname);
413                 }
414         }
415
416         osrfStringArrayFree(classes);
417
418         return 0;
419 }
420
421
422 int dispatchCRUDMethod ( osrfMethodContext* ctx ) {
423         OSRF_METHOD_VERIFY_CONTEXT(ctx);
424
425         osrfHash* meta = (osrfHash*) ctx->method->userData;
426
427         jsonObject * obj = NULL;
428         if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "create"))
429                 obj = doCreate(meta, ctx->params);
430
431         if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "retrieve"))
432                 obj = doRetrieve(meta, ctx->params);
433
434         if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "update"))
435                 obj = doUpdate(meta, ctx->params);
436
437         if (!strcmp( (char*)osrfHashGet(meta, "methodtype"), "delete"))
438                 obj = doDelete(meta, ctx->params);
439
440         osrfAppRespondComplete( ctx, obj );
441
442         //jsonObjectFree(obj);
443
444         return 0;
445 }
446
447 jsonObject* doCreate( osrfHash* meta, jsonObject* params ) { return NULL; }
448
449 jsonObject* doRetrieve( osrfHash* meta, jsonObject* params ) {
450
451         jsonObject* obj;
452         char* id = jsonObjectToSimpleString(jsonObjectGetIndex(params, 0));
453
454         osrfLogDebug(
455                 OSRF_LOG_MARK,
456                 "%s retrieving %s object with id %s",
457                 MODULENAME,
458                 osrfHashGet(meta, "fieldmapper"),
459                 id
460         );
461
462
463
464         growing_buffer* sql_buf = buffer_init(128);
465         buffer_fadd(
466                 sql_buf,
467                 "SELECT * FROM %s WHERE %s = %d;",
468                 osrfHashGet(meta, "tablename"),
469                 osrfHashGet(meta, "primarykey"),
470                 atoi(id)
471         );
472
473         char* sql = buffer_data(sql_buf);
474         buffer_free(sql_buf);
475         
476         osrfLogDebug(OSRF_LOG_MARK, "%s SQL =  %s", MODULENAME, sql);
477
478         dbi_result result = dbi_conn_query(dbhandle, sql);
479
480         if(result) {
481                 osrfLogDebug(OSRF_LOG_MARK, "Query returned with no errors");
482
483                 /* there should be one row at the most  */
484                 if (dbi_result_next_row(result)) {
485                         /* JSONify the result */
486                         osrfLogDebug(OSRF_LOG_MARK, "Query returned at least one row");
487                         obj = oilsMakeJSONFromResult( result, meta );
488                 } else {
489                         osrfLogDebug(OSRF_LOG_MARK, "%s: Error retrieving %s with key %s", MODULENAME, osrfHashGet(meta, "fieldmapper"), id);
490                         obj = jsonNewObject(NULL);
491                 }
492
493                 /* clean up the query */
494                 dbi_result_free(result); 
495
496         } else {
497                 obj = jsonNewObject(NULL);
498                 osrfLogDebug(OSRF_LOG_MARK, "%s returned no results for query %s", MODULENAME, sql);
499         }
500
501         free(sql);
502         free(id);
503
504         return obj;
505 }
506
507
508 jsonObject* doUpdate( osrfHash* meta, jsonObject* params ) { return NULL; }
509
510 jsonObject* doDelete( osrfHash* meta, jsonObject* params ) { return NULL; }
511
512
513 jsonObject* oilsMakeJSONFromResult( dbi_result result, osrfHash* meta) {
514         if(!(result && meta)) return NULL;
515
516         jsonObject* object = jsonParseString("[]");
517         jsonObjectSetClass(object, osrfHashGet(meta, "classname"));
518
519         osrfHash* fields = osrfHashGet(meta, "fields");
520
521         osrfLogDebug(OSRF_LOG_MARK, "Setting object class to %s ", object->classname);
522
523         osrfHash* _f;
524         time_t _tmp_dt;
525         char dt_string[256];
526         struct tm gmdt;
527
528         int fmIndex;
529         int columnIndex = 1;
530         int attr;
531         unsigned short type;
532         const char* columnName;
533
534         // this block gets the local timezone. until we can patch libdbi this'll have to do, pig.
535         time_t tmp_t = time(NULL);
536         struct tm ldt;
537         localtime_r( &tmp_t, &ldt );
538
539         char tz_part[8];
540         memset(tz_part,'\0',8);
541
542         strftime(tz_part,7,"%z",&ldt);
543         tz_part[5] = tz_part[4];
544         tz_part[4] = tz_part[3];
545         tz_part[3] = ':';
546
547
548         /* cycle through the column list */
549         while( (columnName = dbi_result_get_field_name(result, columnIndex++)) ) {
550
551                 osrfLogDebug(OSRF_LOG_MARK, "Looking for column named [%s]...", (char*)columnName);
552
553                 fmIndex = -1; // reset the position
554                 
555                 /* determine the field type and storage attributes */
556                 type = dbi_result_get_field_type(result, columnName);
557                 attr = dbi_result_get_field_attribs(result, columnName);
558
559                 /* fetch the fieldmapper index */
560                 if( (_f = osrfHashGet(fields, (char*)columnName)) ) {
561                         char* virt = (char*)osrfHashGet(_f, "virtual");
562                         char* pos = (char*)osrfHashGet(_f, "array_position");
563
564                         if ( !virt || !pos || !(strcmp( virt, "true" )) ) continue;
565
566                         fmIndex = atoi( pos );
567                         osrfLogDebug(OSRF_LOG_MARK, "... Found column at position [%s]...", pos);
568                 }
569
570                 if (dbi_result_field_is_null(result, columnName)) {
571                         jsonObjectSetIndex( object, fmIndex, jsonNewObject(NULL) );
572                 } else {
573
574                         switch( type ) {
575
576                                 case DBI_TYPE_INTEGER :
577
578                                         if( attr & DBI_INTEGER_SIZE8 ) 
579                                                 jsonObjectSetIndex( object, fmIndex, 
580                                                         jsonNewNumberObject(dbi_result_get_longlong(result, columnName)));
581                                         else 
582                                                 jsonObjectSetIndex( object, fmIndex, 
583                                                         jsonNewNumberObject(dbi_result_get_long(result, columnName)));
584
585                                         break;
586
587                                 case DBI_TYPE_DECIMAL :
588                                         jsonObjectSetIndex( object, fmIndex, 
589                                                         jsonNewNumberObject(dbi_result_get_double(result, columnName)));
590                                         break;
591
592                                 case DBI_TYPE_STRING :
593
594
595                                         jsonObjectSetIndex(
596                                                 object,
597                                                 fmIndex,
598                                                 jsonNewObject( dbi_result_get_string(result, columnName) )
599                                         );
600
601                                         break;
602
603                                 case DBI_TYPE_DATETIME :
604
605                                         memset(dt_string, '\0', 256);
606                                         memset(&gmdt, '\0', sizeof(gmdt));
607                                         memset(&_tmp_dt, '\0', sizeof(_tmp_dt));
608
609                                         _tmp_dt = dbi_result_get_datetime(result, columnName);
610
611                                         localtime_r( &_tmp_dt, &gmdt );
612
613                                         if (!(attr & DBI_DATETIME_DATE)) {
614                                                 strftime(dt_string, 255, "%T", &gmdt);
615                                         } else if (!(attr & DBI_DATETIME_TIME)) {
616                                                 strftime(dt_string, 255, "%F", &gmdt);
617                                         } else {
618                                                 /* XXX ARG! My eyes! The goggles, they do nothing! */
619
620                                                 strftime(dt_string, 255, "%FT%T%z", &gmdt);
621                                         }
622
623                                         jsonObjectSetIndex( object, fmIndex, jsonNewObject(dt_string) );
624
625                                         break;
626
627                                 case DBI_TYPE_BINARY :
628                                         osrfLogError( OSRF_LOG_MARK, 
629                                                 "Can't do binary at column %s : index %d", columnName, columnIndex - 1);
630                         }
631                 }
632         }
633
634         return object;
635 }
636