1 /*
2 * Copyright (C) 2007 - 2011 Vivien Malerba <malerba@gnome-db.org>
3 * Copyright (C) 2008 Murray Cumming <murrayc@murrayc.com>
4 * Copyright (C) 2010 David King <davidk@openismus.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #include <libxml/xpathInternals.h>
23 #include <libxslt/variables.h>
24
25 #include <libgda/libgda.h>
26
27 #include "libgda-xslt.h"
28 #include "sql_backend.h"
29 #include <libxml/xpathInternals.h>
30 #include <libgda/gda-debug-macros.h>
31
32 #include <libgda/handlers/gda-handler-boolean.h>
33 #include <libgda/handlers/gda-handler-numerical.h>
34 #include <libgda/handlers/gda-handler-string.h>
35 #include <libgda/handlers/gda-handler-time.h>
36 #include <libgda/handlers/gda-handler-type.h>
37
38 #include <sql-parser/gda-sql-parser.h>
39
40 static GHashTable *data_handlers = NULL; /* key = GType, value = GdaDataHandler obj */
41 static xmlChar *value_to_xmlchar (const GValue * value);
42
43
44
45 static void look_predefined_query_by_name (GdaXsltExCont * exec,
46 const char *query_name,
47 GdaStatement ** query);
48
49 static void set_resultset_value (GdaXsltIntCont * pdata,
50 const char *resultset_name,
51 GObject * result, GError ** error);
52 static int get_resultset_col_value (GdaXsltIntCont * pdata,
53 const char *resultset_name,
54 const char *colname, char **outvalue,
55 GError ** error);
56 static int get_resultset_nodeset (GdaXsltIntCont * pdata,
57 const char *resultset_name,
58 xmlXPathObjectPtr * nodeset,
59 GError ** error);
60 static int _utility_data_model_to_nodeset (GdaDataModel * model,
61 xmlXPathObjectPtr * nodeset,
62 GError ** error);
63 static int gda_xslt_bk_internal_query (GdaXsltExCont * exec,
64 GdaXsltIntCont * pdata,
65 xsltTransformContextPtr ctxt,
66 xmlNodePtr query_node);
67
68 int
_gda_xslt_holder_set_value(GdaHolder * param,xsltTransformContextPtr ctxt)69 _gda_xslt_holder_set_value (GdaHolder *param, xsltTransformContextPtr ctxt)
70 {
71 GType gdatype;
72 gchar *name;
73 GValue *value;
74 xmlChar *xvalue;
75 xmlXPathObjectPtr xsltvar;
76
77 /* information from libgda */
78 gdatype = gda_holder_get_g_type (param);
79 name = gda_text_to_alphanum (gda_holder_get_id (param));
80
81 /* information from libxslt and libxml */
82 xsltvar = xsltVariableLookup (ctxt, (const xmlChar *) name, NULL);
83 xvalue = xmlXPathCastToString (xsltvar);
84
85 value = g_new0 (GValue, 1);
86 if (!gda_value_set_from_string (value, (gchar *) xvalue, gdatype)) {
87 /* error */
88 g_free (value);
89 g_free (xvalue);
90 return -1;
91 }
92 else {
93 gint retval = 0;
94 if (! gda_holder_set_value (param, value, NULL))
95 retval = -1;
96 g_free (xvalue);
97 gda_value_free (value);
98 return retval;
99 }
100 }
101
102 int
_gda_xslt_bk_section(GdaXsltExCont * exec,GdaXsltIntCont * pdata,xsltTransformContextPtr ctxt,xmlNodePtr node,xmlNodePtr inst,G_GNUC_UNUSED xsltStylePreCompPtr comp)103 _gda_xslt_bk_section (GdaXsltExCont * exec, GdaXsltIntCont * pdata,
104 xsltTransformContextPtr ctxt, xmlNodePtr node,
105 xmlNodePtr inst, G_GNUC_UNUSED xsltStylePreCompPtr comp)
106 {
107 xmlNode *cur_node = NULL;
108 xmlNode *query_node = NULL;
109 xmlNode *template_node = NULL;
110 int res;
111
112 for (cur_node = inst->children; cur_node; cur_node = cur_node->next) {
113 if (cur_node->type == XML_ELEMENT_NODE &&
114 xmlStrEqual (cur_node->ns->href,
115 BAD_CAST GDA_XSLT_EXTENSION_URI)) {
116 printf ("found element in sql namespace: name[%s]\n",
117 cur_node->name);
118 if (xmlStrEqual
119 (cur_node->name,
120 BAD_CAST GDA_XSLT_ELEM_INTERNAL_QUERY)) {
121 query_node = cur_node;
122 }
123 else if (xmlStrEqual
124 (cur_node->name,
125 BAD_CAST GDA_XSLT_ELEM_INTERNAL_TEMPLATE)) {
126 template_node = cur_node;
127 }
128 }
129 }
130 if (query_node == NULL) {
131 g_set_error (&(exec->error), 0, 0,
132 "%s", "no query node in section node");
133 return -1;
134 }
135 /* set the query context */
136 res = gda_xslt_bk_internal_query (exec, pdata, ctxt, query_node);
137 if (res < 0) {
138 printf ("sql_bk_internal_query res [%d]\n", res);
139 return -1;
140 }
141 /* run the template */
142 if (template_node) {
143 /* template node must have only
144 xml comments and ONE xsl:call-template nodes */
145 for (cur_node = template_node->children; cur_node;
146 cur_node = cur_node->next) {
147 if (IS_XSLT_ELEM (cur_node)) {
148 if (IS_XSLT_NAME (cur_node, "call-template")) {
149 xsltStylePreCompPtr info =
150 (xsltStylePreCompPtr)
151 cur_node->psvi;
152 if (info != NULL) {
153 xsltCallTemplate
154 (ctxt, node,
155 cur_node, info);
156 }
157 else {
158 printf ("the xsltStylePreCompPtr is empthy\n");
159 return -1;
160 }
161 }
162 else {
163 #ifdef GDA_DEBUG_NO
164 printf ("only one call-template node is allowed on sql:template node\n");
165 #endif
166 return -1;
167 }
168 }
169 else if (cur_node->type != XML_COMMENT_NODE) {
170 #ifdef GDA_DEBUG_NO
171 printf ("only one xsl:call-template or comment node is allowed on sql:template node\n");
172 #endif
173 return -1;
174 }
175 }
176 }
177 /* unset the query context */
178 // TODO, delete the query result information and the query if it was created inline
179 return 0;
180
181 }
182
183 xmlXPathObjectPtr
_gda_xslt_bk_fun_getnodeset(xmlChar * set,GdaXsltExCont * exec,GdaXsltIntCont * pdata)184 _gda_xslt_bk_fun_getnodeset (xmlChar * set, GdaXsltExCont * exec,
185 GdaXsltIntCont * pdata)
186 {
187 xmlXPathObjectPtr nodeset;
188 int res;
189 #ifdef GDA_DEBUG_NO
190 printf ("running function:_gda_xslt_bk_fun_getnodeset\n");
191 #endif
192 res = get_resultset_nodeset (pdata, (gchar*) set, &nodeset, &(exec->error));
193 if (res < 0 || nodeset == NULL) {
194 xsltGenericError (xsltGenericErrorContext,
195 "_gda_xslt_bk_fun_getnodeset error\n");
196 return NULL;
197 }
198 return nodeset;
199 }
200
201 xmlXPathObjectPtr
_gda_xslt_bk_fun_getvalue(xmlChar * set,xmlChar * name,GdaXsltExCont * exec,GdaXsltIntCont * pdata,int getXml)202 _gda_xslt_bk_fun_getvalue (xmlChar * set, xmlChar * name, GdaXsltExCont * exec,
203 GdaXsltIntCont * pdata,int getXml)
204 {
205 xmlXPathObjectPtr value;
206 int res;
207 xmlDocPtr sqlxmldoc;
208 xmlNodePtr rootnode;
209 xmlNodePtr copyrootnode;
210 #ifdef GDA_DEBUG_NO
211 g_print ("running function:_gda_xslt_bk_fun_getvalue (getxml [%d])", getXml);
212 #endif
213 char *strvalue;
214 res = get_resultset_col_value (pdata, (const char *) set,
215 (const char *) name, &strvalue,
216 &(exec->error));
217 if (res < 0) {
218 xsltGenericError (xsltGenericErrorContext,
219 "_gda_xslt_bk_fun_getvalue: internal error on get_resultset_col_value\n");
220 return NULL;
221 }
222
223 if( getXml) {
224 sqlxmldoc = xmlParseDoc((const xmlChar *)strvalue);
225 if (sqlxmldoc == NULL) {
226 xsltGenericError (xsltGenericErrorContext,
227 "_gda_xslt_bk_fun_getvalue: xmlParseDoc fauld\n");
228 return NULL;
229 }
230 rootnode = xmlDocGetRootElement(sqlxmldoc);
231 copyrootnode = xmlCopyNode(rootnode,1);
232 if (copyrootnode == NULL) {
233 xsltGenericError (xsltGenericErrorContext,
234 "_gda_xslt_bk_fun_getvalue: get or copy of root node fauld\n");
235 return NULL;
236 }
237 value = (xmlXPathObjectPtr) xmlXPathNewNodeSet (copyrootnode);
238 xmlFreeDoc(sqlxmldoc );
239 } else {
240 value = (xmlXPathObjectPtr) xmlXPathNewCString ((const char *)
241 strvalue);
242 }
243
244 if (value == NULL) {
245 xsltGenericError (xsltGenericErrorContext,
246 "_gda_xslt_bk_fun_getvalue: internal error\n");
247 return NULL;
248 }
249 return value;
250 }
251
252 xmlXPathObjectPtr
_gda_xslt_bk_fun_checkif(G_GNUC_UNUSED xmlChar * setname,G_GNUC_UNUSED xmlChar * sql_condition,G_GNUC_UNUSED GdaXsltExCont * exec,G_GNUC_UNUSED GdaXsltIntCont * pdata)253 _gda_xslt_bk_fun_checkif (G_GNUC_UNUSED xmlChar * setname, G_GNUC_UNUSED xmlChar * sql_condition,
254 G_GNUC_UNUSED GdaXsltExCont * exec, G_GNUC_UNUSED GdaXsltIntCont * pdata)
255 {
256 return xmlXPathNewBoolean (1);
257 }
258
259
260
261 /* utility functions */
262 static void
set_resultset_value(GdaXsltIntCont * pdata,const char * resultset_name,GObject * result,G_GNUC_UNUSED GError ** error)263 set_resultset_value (GdaXsltIntCont * pdata, const char *resultset_name,
264 GObject * result, G_GNUC_UNUSED GError ** error)
265 {
266 #ifdef GDA_DEBUG_NO
267 g_print ("new resultset: name[%s]", resultset_name);
268 #endif
269 g_hash_table_insert (pdata->result_sets, g_strdup (resultset_name),
270 (gpointer) result);
271 }
272
273 static int
get_resultset_col_value(GdaXsltIntCont * pdata,const char * resultset_name,const char * colname,char ** outvalue,GError ** error)274 get_resultset_col_value (GdaXsltIntCont * pdata, const char *resultset_name,
275 const char *colname, char **outvalue,
276 GError ** error)
277 {
278 gpointer orig_key = NULL;
279 gpointer value = NULL;
280 GObject *result;
281 #ifdef GDA_DEBUG_NO
282 g_print ("searching resultset[%s]", resultset_name);
283 #endif
284
285 if (g_hash_table_lookup_extended
286 (pdata->result_sets, resultset_name, &orig_key, &value)) {
287 #ifdef GDA_DEBUG_NO
288 g_print ("resultset found [%p]", value);
289 #endif
290 result = (GObject *) value;
291 }
292 else {
293 #ifdef GDA_DEBUG_NO
294 g_print ("no resultset found");
295 #endif
296 *outvalue = NULL;
297 return -1;
298 }
299
300 if (!GDA_IS_DATA_MODEL (result)) {
301 #ifdef GDA_DEBUG_NO
302 g_print ("this is not a data model, returning NULL");
303 #endif
304 *outvalue = NULL;
305 return -1;
306 }
307 gint col_index;
308 col_index = gda_data_model_get_column_index (GDA_DATA_MODEL (result), colname);
309 if (col_index < 0) {
310 #ifdef GDA_DEBUG_NO
311 g_print ("no column found by name [%s]", colname);
312 #endif
313 *outvalue = NULL;
314 return -1;
315 }
316 const GValue *db_value;
317 db_value = gda_data_model_get_value_at (GDA_DATA_MODEL (result), col_index, 0, error);
318 if (db_value == NULL) {
319 #ifdef GDA_DEBUG_NO
320 g_print ("no value found on col_index [%d]", col_index);
321 #endif
322 *outvalue = NULL;
323 return -1;
324 }
325 gchar *gvalue_string;
326 gvalue_string = (gchar*) value_to_xmlchar (db_value);
327 if (gvalue_string == NULL) {
328 #ifdef GDA_DEBUG_NO
329 g_print ("faild to stringify gvalue");
330 #endif
331 *outvalue = NULL;
332 return -1;
333 }
334 *outvalue = g_strdup (gvalue_string);
335 g_free (gvalue_string);
336 return 0;
337 }
338
339 static int
get_resultset_nodeset(GdaXsltIntCont * pdata,const char * resultset_name,xmlXPathObjectPtr * nodeset,GError ** error)340 get_resultset_nodeset (GdaXsltIntCont * pdata, const char *resultset_name,
341 xmlXPathObjectPtr * nodeset, GError ** error)
342 {
343 gpointer orig_key = NULL;
344 gpointer value = NULL;
345 GObject *result;
346 int res;
347 #ifdef GDA_DEBUG_NO
348 g_print ("searching resultset[%s]", resultset_name);
349 #endif
350
351 if (g_hash_table_lookup_extended
352 (pdata->result_sets, resultset_name, &orig_key, &value)) {
353 #ifdef GDA_DEBUG_NO
354 g_print ("resultset found [%p]\n", value);
355 #endif
356 result = (GObject *) value;
357 }
358 else {
359 #ifdef GDA_DEBUG_NO
360 g_print ("no resultset found\n");
361 #endif
362 g_set_error (error, 0, 0,
363 "no resultset found for name [%s]\n",
364 resultset_name);
365 *nodeset = NULL;
366 return -1;
367 }
368 // Dont check if this is a Data Model, because saving the result we alreally check
369 res = _utility_data_model_to_nodeset (GDA_DATA_MODEL (result),
370 nodeset, error);
371 if (res < 0) {
372 #ifdef GDA_DEBUG_NO
373 g_print ("_utility_data_model_to_nodeset fault");
374 #endif
375 *nodeset = NULL;
376 return -1;
377 }
378 return 0;
379 }
380
381 /* -------------------------------------------------- */
382 static int
_utility_data_model_to_nodeset(GdaDataModel * model,xmlXPathObjectPtr * nodeset,GError ** error)383 _utility_data_model_to_nodeset (GdaDataModel * model,
384 xmlXPathObjectPtr * nodeset, GError ** error)
385 {
386 gint nrows, i;
387 gint *rcols, rnb_cols;
388 gchar **col_ids = NULL;
389 gint c;
390
391 xmlNodePtr mainnode;
392 mainnode = xmlNewNode (NULL, (xmlChar *) "resultset");
393 if (mainnode == NULL) {
394 #ifdef GDA_DEBUG_NO
395 g_print ("xmlNewNode return NULL\n");
396 #endif
397 g_set_error (error, 0, 0, "%s", "xmlNewNode return NULL\n");
398 return -1;
399 }
400 /* compute columns */
401 rnb_cols = gda_data_model_get_n_columns (model);
402 rcols = g_new (gint, rnb_cols);
403 for (i = 0; i < rnb_cols; i++)
404 rcols[i] = i;
405
406 col_ids = g_new0 (gchar *, rnb_cols);
407 for (c = 0; c < rnb_cols; c++) {
408 GdaColumn *column;
409 const gchar *name;
410 column = gda_data_model_describe_column (model, rcols[c]);
411 name = gda_column_get_name (column);
412 if (name)
413 col_ids[c] = g_strdup (name);
414 else
415 col_ids[c] = g_strdup_printf ("_%d", c);
416 }
417
418 /* add the model data to the XML output */
419 nrows = gda_data_model_get_n_rows (model);
420 if (nrows > 0) {
421 xmlNodePtr row, field;
422 gint r, c;
423 for (r = 0; r < nrows; r++) {
424 row = xmlNewChild (mainnode, NULL, (xmlChar *) "row", NULL);
425 for (c = 0; c < rnb_cols; c++) {
426 GValue *value;
427 xmlChar *str = NULL;
428 gboolean isnull = FALSE;
429
430 value = (GValue *) gda_data_model_get_value_at (model, rcols[c], r, error);
431 if (!value) {
432 for (c = 0; c < rnb_cols; c++)
433 g_free (col_ids[c]);
434 g_free (col_ids);
435 g_free (rcols);
436 return -1;
437 }
438 if (gda_value_is_null ((GValue *) value))
439 isnull = TRUE;
440 else
441 str = value_to_xmlchar (value);
442 field = xmlNewTextChild (row, NULL, (xmlChar *) "column", (xmlChar *) str);
443 xmlSetProp (field, (xmlChar *) "name", (xmlChar *) col_ids[c]);
444 if (isnull)
445 xmlSetProp (field, (xmlChar *) "isnull", (xmlChar *) "true");
446 g_free (str);
447 }
448 }
449 }
450 for (c = 0; c < rnb_cols; c++)
451 g_free (col_ids[c]);
452 g_free (col_ids);
453 g_free (rcols);
454
455 *nodeset = (xmlXPathObjectPtr) xmlXPathNewNodeSet (mainnode);
456
457 return 0;
458 }
459
460 static void
look_predefined_query_by_name(GdaXsltExCont * exec,const char * query_name,GdaStatement ** query)461 look_predefined_query_by_name (GdaXsltExCont * exec, const char *query_name,
462 GdaStatement ** query)
463 {
464 gpointer orig_key = NULL;
465 gpointer value = NULL;
466 #ifdef GDA_DEBUG_NO
467 g_print ("searching predefined query name[%s]", query_name);
468 #endif
469
470 if (g_hash_table_lookup_extended
471 (exec->query_hash, query_name, &orig_key, &value)) {
472 #ifdef GDA_DEBUG_NO
473 g_print ("query found [%p]", value);
474 #endif
475 *query = (GdaStatement *) value;
476 }
477 else {
478 #ifdef GDA_DEBUG_NO
479 g_print ("no predefined query found");
480 #endif
481 *query = NULL;
482 }
483 }
484
485 static int
gda_xslt_bk_internal_query(GdaXsltExCont * exec,GdaXsltIntCont * pdata,xsltTransformContextPtr ctxt,xmlNodePtr query_node)486 gda_xslt_bk_internal_query (GdaXsltExCont * exec, GdaXsltIntCont * pdata,
487 xsltTransformContextPtr ctxt,
488 xmlNodePtr query_node)
489 {
490 GdaStatement *query = NULL;
491 GdaSet *params;
492 int ret = 0;
493 GdaDataModel *resQuery;
494 GSList *plist;
495 int predefined = 0;
496
497 xmlNodePtr sqltxt_node = NULL;
498 xmlChar *query_name;
499
500 #ifdef GDA_DEBUG_NO
501 g_print ("running function:gda_xslt_bk_internal_query \n");
502 #endif
503
504 query_name = xmlGetProp (query_node, (const xmlChar *) "name");
505 if (query_name == NULL) {
506 g_set_error (&(exec->error), 0, 0,
507 "%s", "the query element is not correct, no 'name' attribute\n");
508 return -1;
509 }
510
511 look_predefined_query_by_name (exec, (gchar*) query_name, &(query));
512 if (!query) {
513 /* the query is not predefined */
514 /* get the xml text node with the sql */
515 sqltxt_node = query_node->children;
516 if (sqltxt_node == NULL || sqltxt_node->type != XML_TEXT_NODE) {
517 g_set_error (&(exec->error), 0, 0,
518 "%s", "the query element is not correct, it have not a first text children\n");
519 return -1;
520 }
521 #ifdef GDA_DEBUG_NO
522 printf ("query_content[%s]\n", XML_GET_CONTENT (sqltxt_node));
523 #endif
524 /* create the query */
525 GdaSqlParser *parser;
526 parser = gda_connection_create_parser (exec->cnc);
527 query = gda_sql_parser_parse_string (parser, (gchar*) XML_GET_CONTENT (sqltxt_node), NULL, &(exec->error));
528 g_object_unref (parser);
529 if (!query) {
530 #ifdef GDA_DEBUG_NO
531 g_print ("gda_query_new_from_sql:error [%s]\n",
532 exec->error && exec->error->message ? exec->error->
533 message : "No detail");
534 #endif
535 return -1;
536 }
537 }
538 else {
539 /* the query is predefined */
540 predefined = 1;
541 }
542
543 /* find the parameters on xsltcontext */
544 if (! gda_statement_get_parameters (query, ¶ms, &(exec->error)))
545 return -1;
546
547 if (params != NULL) {
548 plist = params->holders;
549 while (plist && ret == 0) {
550 ret = _gda_xslt_holder_set_value (GDA_HOLDER (plist->data), ctxt);
551 plist = g_slist_next (plist);
552 }
553 }
554
555 /* run the query */
556 resQuery = gda_connection_statement_execute_select (exec->cnc, query, params, &(exec->error));
557 if (!resQuery) {
558 #ifdef GDA_DEBUG_NO
559 g_print ("gda_query_execute:error [%s]\n",
560 exec->error
561 && exec->error->message ? exec->error->
562 message : "No detail");
563 #endif
564 return -1;
565 }
566
567 /* save the result to the internal context */
568 set_resultset_value (pdata, (const char *) query_name, (GObject*) resQuery, &(exec->error));
569
570 /* free the parameters */
571 if (params)
572 g_object_unref (params);
573 /* free the query if not predefined */
574 if (!predefined && query)
575 g_object_unref (query);
576 xmlFree (query_name);
577 return 0;
578 }
579
580
581 /* from libgda */
582 static gboolean
gtype_equal(gconstpointer a,gconstpointer b)583 gtype_equal (gconstpointer a, gconstpointer b)
584 {
585 return (GType) a == (GType) b ? TRUE : FALSE;
586 }
587
588 static xmlChar *
value_to_xmlchar(const GValue * value)589 value_to_xmlchar (const GValue * value)
590 {
591 GdaDataHandler *dh;
592 gchar *str;
593
594 if (!value || gda_value_is_null (value))
595 return (BAD_CAST "");
596 else if ((G_VALUE_TYPE (value) == GDA_TYPE_BINARY) ||
597 (G_VALUE_TYPE (value) == GDA_TYPE_BLOB)) {
598 TO_IMPLEMENT;
599 return (BAD_CAST "Binary data");
600 }
601 if (!data_handlers) {
602 /* initialize the internal data handlers */
603 data_handlers =
604 g_hash_table_new_full (g_direct_hash, gtype_equal,
605 NULL, (GDestroyNotify)
606 g_object_unref);
607
608 g_hash_table_insert (data_handlers, (gpointer) G_TYPE_INT64,
609 gda_handler_numerical_new ());
610 g_hash_table_insert (data_handlers,
611 (gpointer) G_TYPE_UINT64,
612 gda_handler_numerical_new ());
613 g_hash_table_insert (data_handlers,
614 (gpointer) G_TYPE_BOOLEAN,
615 gda_handler_boolean_new ());
616 g_hash_table_insert (data_handlers, (gpointer) G_TYPE_DATE,
617 gda_handler_time_new ());
618 g_hash_table_insert (data_handlers,
619 (gpointer) G_TYPE_DOUBLE,
620 gda_handler_numerical_new ());
621 g_hash_table_insert (data_handlers, (gpointer) G_TYPE_INT,
622 gda_handler_numerical_new ());
623 g_hash_table_insert (data_handlers,
624 (gpointer) GDA_TYPE_NUMERIC,
625 gda_handler_numerical_new ());
626 g_hash_table_insert (data_handlers, (gpointer) G_TYPE_FLOAT,
627 gda_handler_numerical_new ());
628 g_hash_table_insert (data_handlers,
629 (gpointer) GDA_TYPE_SHORT,
630 gda_handler_numerical_new ());
631 g_hash_table_insert (data_handlers,
632 (gpointer) GDA_TYPE_USHORT,
633 gda_handler_numerical_new ());
634 g_hash_table_insert (data_handlers,
635 (gpointer) G_TYPE_STRING,
636 gda_handler_string_new ());
637 g_hash_table_insert (data_handlers,
638 (gpointer) GDA_TYPE_TIME,
639 gda_handler_time_new ());
640 g_hash_table_insert (data_handlers,
641 (gpointer) GDA_TYPE_TIMESTAMP,
642 gda_handler_time_new ());
643 g_hash_table_insert (data_handlers, (gpointer) G_TYPE_CHAR,
644 gda_handler_numerical_new ());
645 g_hash_table_insert (data_handlers, (gpointer) G_TYPE_UCHAR,
646 gda_handler_numerical_new ());
647 g_hash_table_insert (data_handlers, (gpointer) G_TYPE_ULONG,
648 gda_handler_numerical_new ());
649 g_hash_table_insert (data_handlers, (gpointer) G_TYPE_LONG,
650 gda_handler_numerical_new ());
651 g_hash_table_insert (data_handlers, (gpointer) G_TYPE_GTYPE,
652 gda_handler_type_new ());
653 g_hash_table_insert (data_handlers, (gpointer) G_TYPE_UINT,
654 gda_handler_numerical_new ());
655 }
656
657 dh = g_hash_table_lookup (data_handlers,
658 (gpointer) G_VALUE_TYPE (value));
659 if (dh)
660 str = gda_data_handler_get_str_from_value (dh, value);
661 else
662 str = gda_value_stringify (value);
663 return (BAD_CAST (str ? str : ""));
664 }
665