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