sqlops: add a limit of maximum 32 result containers
[kamailio] / src / modules / sqlops / sql_api.c
1 /*
2  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
3  *
4  * This file is part of kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21 /*! \file
22  * \ingroup sqlops
23  * \brief Kamailio SQL-operations :: API
24  *
25  * - Module: \ref sqlops
26  */
27
28
29 #include "../../core/mem/mem.h"
30 #include "../../core/dprint.h"
31 #include "../../core/hashes.h"
32 #include "../../core/ut.h"
33 #include "../../lib/srdb1/db_ut.h"
34 #include "../../core/xavp.h"
35
36 #include "sql_api.h"
37
38 #define SQLOPS_RESULT_MAXSIZE 32
39
40 sql_con_t *_sql_con_root = NULL;
41 sql_result_t *_sql_result_root = NULL;
42
43 static char _sql_empty_buf[1];
44
45 sql_con_t* sql_get_connection(str *name)
46 {
47         sql_con_t *sc;
48         unsigned int conid;
49
50         conid = core_case_hash(name, 0, 0);
51
52         sc = _sql_con_root;
53         while(sc)
54         {
55                 if(conid==sc->conid && sc->name.len==name->len
56                                 && strncmp(sc->name.s, name->s, name->len)==0)
57                         return sc;
58                 sc = sc->next;
59         }
60         return NULL;
61 }
62
63 int sql_init_con(str *name, str *url)
64 {
65         sql_con_t *sc;
66         unsigned int conid;
67
68         *_sql_empty_buf = '\0';
69
70         conid = core_case_hash(name, 0, 0);
71
72         sc = _sql_con_root;
73         while(sc)
74         {
75                 if(conid==sc->conid && sc->name.len==name->len
76                                 && strncmp(sc->name.s, name->s, name->len)==0)
77                 {
78                         LM_ERR("duplicate connection name\n");
79                         return -1;
80                 }
81                 sc = sc->next;
82         }
83         sc = (sql_con_t*)pkg_malloc(sizeof(sql_con_t));
84         if(sc==NULL)
85         {
86                 LM_ERR("no pkg memory\n");
87                 return -1;
88         }
89         memset(sc, 0, sizeof(sql_con_t));
90         sc->conid = conid;
91         sc->name = *name;
92         sc->db_url = *url;
93         sc->next = _sql_con_root;
94         _sql_con_root = sc;
95
96         return 0;
97 }
98
99 int pv_parse_con_name(pv_spec_p sp, str *in)
100 {
101         sql_con_t *con;
102
103         if(sp==NULL || in==NULL || in->len<=0)
104                 return -1;
105
106         con = sql_get_connection(in);
107         if (con==NULL) {
108                 LM_ERR("invalid connection [%.*s]\n", in->len, in->s);
109                 return -1;
110         }
111
112         sp->pvp.pvn.type = PV_NAME_INTSTR;
113         sp->pvp.pvn.u.isname.type = AVP_VAL_STR;
114         sp->pvp.pvn.u.isname.name.s = *in;
115         return 0;
116 }
117
118 int pv_get_sqlrows(struct sip_msg *msg,  pv_param_t *param,
119                 pv_value_t *res)
120 {
121         sql_con_t *con;
122         str* sc;
123
124         sc = &param->pvn.u.isname.name.s;
125         con = sql_get_connection(sc);
126         if(con==NULL)
127         {
128                 LM_ERR("invalid connection [%.*s]\n", sc->len, sc->s);
129                 return -1;
130         }
131
132         if (!DB_CAPABILITY(con->dbf, DB_CAP_AFFECTED_ROWS))
133         {
134                 LM_ERR("con: %p database module does not have DB_CAP_AFFECTED_ROWS [%.*s]\n",
135                        con, sc->len, sc->s);
136                 return -1;
137         }
138
139         return pv_get_sintval(msg, param, res, con->dbf.affected_rows(con->dbh));
140 }
141
142 int sql_connect(int mode)
143 {
144         sql_con_t *sc;
145         sc = _sql_con_root;
146         LM_DBG("trying to connect to database with mode %d\n", mode);
147         while(sc)
148         {
149                 if (db_bind_mod(&sc->db_url, &sc->dbf))
150                 {
151                         LM_DBG("database module not found for [%.*s]\n",
152                                         sc->name.len, sc->name.s);
153                         return -1;
154                 }
155                 if (!DB_CAPABILITY(sc->dbf, DB_CAP_RAW_QUERY))
156                 {
157                         LM_ERR("database module does not have DB_CAP_ALL [%.*s]\n",
158                                         sc->name.len, sc->name.s);
159                         return -1;
160                 }
161                 sc->dbh = sc->dbf.init(&sc->db_url);
162                 if (sc->dbh==NULL)
163                 {
164                         if(!mode) {
165                                 LM_ERR("failed to connect to the database [%.*s]\n",
166                                                 sc->name.len, sc->name.s);
167                                 return -1;
168                         } else {
169                                 LM_INFO("failed to connect to the database [%.*s] - trying next\n",
170                                                 sc->name.len, sc->name.s);
171                         }
172                 }
173                 sc = sc->next;
174         }
175         return 0;
176 }
177
178 int sql_reconnect(sql_con_t *sc)
179 {
180         if(sc==NULL) {
181                 LM_ERR("connection structure not initialized\n");
182                 return -1;
183         }
184         if (sc->dbh!=NULL) {
185                 /* already connected */
186                 return 0;
187         }
188         sc->dbh = sc->dbf.init(&sc->db_url);
189         if (sc->dbh==NULL) {
190                 LM_ERR("failed to connect to the database [%.*s]\n",
191                                         sc->name.len, sc->name.s);
192                 return -1;
193         }
194         return 0;
195 }
196
197 void sql_disconnect(void)
198 {
199         sql_con_t *sc;
200         sc = _sql_con_root;
201         while(sc)
202         {
203                 if (sc->dbh!=NULL)
204                         sc->dbf.close(sc->dbh);
205                 sc->dbh= NULL;
206                 sc = sc->next;
207         }
208 }
209
210 sql_result_t* sql_get_result(str *name)
211 {
212         sql_result_t *sr;
213         unsigned int resid;
214         int i;
215
216         resid = core_case_hash(name, 0, 0);
217
218         sr = _sql_result_root;
219         i = 0;
220         while(sr)
221         {
222                 if(sr->resid==resid && sr->name.len==name->len
223                                 && strncmp(sr->name.s, name->s, name->len)==0)
224                         return sr;
225                 i++;
226                 sr = sr->next;
227         }
228         if(i>SQLOPS_RESULT_MAXSIZE)
229         {
230                 LM_ERR("too many result containers defined\n");
231                 return NULL;
232         }
233         sr = (sql_result_t*)pkg_malloc(sizeof(sql_result_t) + name->len);
234         if(sr==NULL)
235         {
236                 LM_ERR("no pkg memory\n");
237                 return NULL;
238         }
239         memset(sr, 0, sizeof(sql_result_t));
240         memcpy(sr+1, name->s, name->len);
241         sr->name.s = (char *)(sr + 1);
242         sr->name.len = name->len;
243         sr->resid = resid;
244         sr->next = _sql_result_root;
245         _sql_result_root = sr;
246         return sr;
247 }
248
249 void sql_reset_result(sql_result_t *res)
250 {
251         int i, j;
252         if(res->cols)
253         {
254                 for(i=0; i<res->ncols; i++)
255                         if(res->cols[i].name.s!=NULL)
256                                 pkg_free(res->cols[i].name.s);
257                 pkg_free(res->cols);
258                 res->cols = NULL;
259         }
260         if(res->vals)
261         {
262                 for(i=0; i<res->nrows; i++)
263                 {
264                         if(res->vals[i])
265                         {
266                                 for(j=0; j<res->ncols; j++)
267                                 {
268                                         if(res->vals[i][j].flags&PV_VAL_STR
269                                                         && res->vals[i][j].value.s.len>0)
270                                                 pkg_free(res->vals[i][j].value.s.s);
271                                 }
272                                 pkg_free(res->vals[i]);
273                         }
274                 }
275                 pkg_free(res->vals);
276                 res->vals = NULL;
277         }
278         res->nrows = 0;
279         res->ncols = 0;
280 }
281
282 int sql_do_query(sql_con_t *con, str *query, sql_result_t *res)
283 {
284         db1_res_t* db_res = NULL;
285         int i, j;
286         str sv;
287
288         if(res) sql_reset_result(res);
289
290         if(query==NULL)
291         {
292                 LM_ERR("bad parameters\n");
293                 return -1;
294         }
295         if(con->dbf.raw_query(con->dbh, query, &db_res)!=0)
296         {
297                 LM_ERR("cannot do the query [%.*s]\n",
298                                 (query->len>64)?64:query->len, query->s);
299                 return -1;
300         }
301
302         if(db_res==NULL || RES_ROW_N(db_res)<=0 || RES_COL_N(db_res)<=0)
303         {
304                 LM_DBG("no result after query\n");
305                 if (db_res) con->dbf.free_result(con->dbh, db_res);
306                 return 2;
307         }
308         if(!res)
309         {
310                 LM_DBG("no sqlresult parameter, ignoring result from query\n");
311                 con->dbf.free_result(con->dbh, db_res);
312                 return 3;
313         }
314
315         res->ncols = RES_COL_N(db_res);
316         res->nrows = RES_ROW_N(db_res);
317         LM_DBG("rows [%d] cols [%d]\n", res->nrows, res->ncols);
318
319         res->cols = (sql_col_t*)pkg_malloc(res->ncols*sizeof(sql_col_t));
320         if(res->cols==NULL)
321         {
322                 res->ncols = 0;
323                 res->nrows = 0;
324                 LM_ERR("no more memory\n");
325                 return -1;
326         }
327         memset(res->cols, 0, res->ncols*sizeof(sql_col_t));
328         for(i=0; i<res->ncols; i++)
329         {
330                 res->cols[i].name.len = (RES_NAMES(db_res)[i])->len;
331                 res->cols[i].name.s = (char*)pkg_malloc((res->cols[i].name.len+1)
332                                 *sizeof(char));
333                 if(res->cols[i].name.s==NULL)
334                 {
335                         LM_ERR("no more memory\n");
336                         goto error;
337                 }
338                 memcpy(res->cols[i].name.s, RES_NAMES(db_res)[i]->s,
339                                 res->cols[i].name.len);
340                 res->cols[i].name.s[res->cols[i].name.len]='\0';
341                 res->cols[i].colid = core_case_hash(&res->cols[i].name, 0, 0);
342         }
343
344         res->vals = (sql_val_t**)pkg_malloc(res->nrows*sizeof(sql_val_t*));
345         if(res->vals==NULL)
346         {
347                 LM_ERR("no more memory\n");
348                 goto error;
349         }
350         memset(res->vals, 0, res->nrows*sizeof(sql_val_t*));
351         for(i=0; i<res->nrows; i++)
352         {
353                 res->vals[i] = (sql_val_t*)pkg_malloc(res->ncols*sizeof(sql_val_t));
354                 if(res->vals[i]==NULL)
355                 {
356                         LM_ERR("no more memory\n");
357                         goto error;
358                 }
359                 memset(res->vals[i], 0, res->ncols*sizeof(sql_val_t));
360                 for(j=0; j<res->ncols; j++)
361                 {
362                         if(RES_ROWS(db_res)[i].values[j].nul)
363                         {
364                                 res->vals[i][j].flags = PV_VAL_NULL;
365                                 continue;
366                         }
367                         sv.s = NULL;
368                         sv.len = 0;
369                         switch(RES_ROWS(db_res)[i].values[j].type)
370                         {
371                                 case DB1_STRING:
372                                         res->vals[i][j].flags = PV_VAL_STR;
373                                         sv.s=
374                                                 (char*)RES_ROWS(db_res)[i].values[j].val.string_val;
375                                         sv.len=strlen(sv.s);
376                                 break;
377                                 case DB1_STR:
378                                         res->vals[i][j].flags = PV_VAL_STR;
379                                         sv.len=
380                                                 RES_ROWS(db_res)[i].values[j].val.str_val.len;
381                                         sv.s=
382                                                 (char*)RES_ROWS(db_res)[i].values[j].val.str_val.s;
383                                 break;
384                                 case DB1_BLOB:
385                                         res->vals[i][j].flags = PV_VAL_STR;
386                                         sv.len=
387                                                 RES_ROWS(db_res)[i].values[j].val.blob_val.len;
388                                         sv.s=
389                                                 (char*)RES_ROWS(db_res)[i].values[j].val.blob_val.s;
390                                 break;
391                                 case DB1_INT:
392                                         res->vals[i][j].flags = PV_VAL_INT;
393                                         res->vals[i][j].value.n
394                                                 = (int)RES_ROWS(db_res)[i].values[j].val.int_val;
395                                 break;
396                                 case DB1_DATETIME:
397                                         res->vals[i][j].flags = PV_VAL_INT;
398                                         res->vals[i][j].value.n
399                                                 = (int)RES_ROWS(db_res)[i].values[j].val.time_val;
400                                 break;
401                                 case DB1_BITMAP:
402                                         res->vals[i][j].flags = PV_VAL_INT;
403                                         res->vals[i][j].value.n
404                                                 = (int)RES_ROWS(db_res)[i].values[j].val.bitmap_val;
405                                 break;
406                                 case DB1_BIGINT:
407                                         res->vals[i][j].flags = PV_VAL_STR;
408                                         res->vals[i][j].value.s.len = 21*sizeof(char);
409                                         res->vals[i][j].value.s.s
410                                                 = (char*)pkg_malloc(res->vals[i][j].value.s.len);
411                                         if(res->vals[i][j].value.s.s==NULL)
412                                         {
413                                                 LM_ERR("no more memory\n");
414                                                 goto error;
415                                         }
416                                         db_longlong2str(RES_ROWS(db_res)[i].values[j].val.ll_val,
417                                                         res->vals[i][j].value.s.s, &res->vals[i][j].value.s.len);
418                                 break;
419                                 default:
420                                         res->vals[i][j].flags = PV_VAL_NULL;
421                         }
422                         if(res->vals[i][j].flags == PV_VAL_STR && sv.s)
423                         {
424                                 if(sv.len<=0)
425                                 {
426                                         res->vals[i][j].value.s.s = _sql_empty_buf;
427                                         res->vals[i][j].value.s.len = 0;
428                                         continue;
429                                 }
430                                 res->vals[i][j].value.s.s
431                                         = (char*)pkg_malloc((sv.len+1)*sizeof(char));
432                                 if(res->vals[i][j].value.s.s==NULL)
433                                 {
434                                         LM_ERR("no more memory\n");
435                                         goto error;
436                                 }
437                                 memcpy(res->vals[i][j].value.s.s, sv.s, sv.len);
438                                 res->vals[i][j].value.s.s[sv.len] = '\0';
439                                 res->vals[i][j].value.s.len = sv.len;
440                         }
441                 }
442         }
443
444         con->dbf.free_result(con->dbh, db_res);
445         return 1;
446
447 error:
448         con->dbf.free_result(con->dbh, db_res);
449         sql_reset_result(res);
450         return -1;
451 }
452
453 int sql_do_query_async(sql_con_t *con, str *query)
454 {
455         if(query==NULL)
456         {
457                 LM_ERR("bad parameters\n");
458                 return -1;
459         }
460         if(con->dbf.raw_query_async==NULL) {
461                 LM_ERR("the db driver module doesn't support async query\n");
462                 return -1;
463         }
464         if(con->dbf.raw_query_async(con->dbh, query)!=0)
465         {
466                 LM_ERR("cannot do the query\n");
467                 return -1;
468         }
469         return 1;
470 }
471
472 int sql_exec_xquery(struct sip_msg *msg, sql_con_t *con, str *query,
473                 str *xavp)
474 {
475         db1_res_t* db_res = NULL;
476         sr_xavp_t *row = NULL;
477         sr_xval_t val;
478         int i, j;
479
480         if(msg==NULL || query==NULL || xavp==NULL)
481         {
482                 LM_ERR("bad parameters\n");
483                 return -1;
484         }
485
486         if(con->dbf.raw_query(con->dbh, query, &db_res)!=0)
487         {
488                 LM_ERR("cannot do the query\n");
489                 return -1;
490         }
491
492         if(db_res==NULL || RES_ROW_N(db_res)<=0 || RES_COL_N(db_res)<=0)
493         {
494                 LM_DBG("no result after query\n");
495                 con->dbf.free_result(con->dbh, db_res);
496                 return 2;
497         }
498
499         for(i=RES_ROW_N(db_res)-1; i>=0; i--)
500         {
501                 row = NULL;
502                 for(j=RES_COL_N(db_res)-1; j>=0; j--)
503                 {
504                         if(RES_ROWS(db_res)[i].values[j].nul)
505                         {
506                                 val.type = SR_XTYPE_NULL;
507                         } else
508                         {
509                                 switch(RES_ROWS(db_res)[i].values[j].type)
510                                 {
511                                         case DB1_STRING:
512                                                 val.type = SR_XTYPE_STR;
513                                                 val.v.s.s=
514                                                         (char*)RES_ROWS(db_res)[i].values[j].val.string_val;
515                                                 val.v.s.len=strlen(val.v.s.s);
516                                         break;
517                                         case DB1_STR:
518                                                 val.type = SR_XTYPE_STR;
519                                                 val.v.s.len=
520                                                         RES_ROWS(db_res)[i].values[j].val.str_val.len;
521                                                 val.v.s.s=
522                                                         (char*)RES_ROWS(db_res)[i].values[j].val.str_val.s;
523                                         break;
524                                         case DB1_BLOB:
525                                                 val.type = SR_XTYPE_STR;
526                                                 val.v.s.len=
527                                                         RES_ROWS(db_res)[i].values[j].val.blob_val.len;
528                                                 val.v.s.s=
529                                                         (char*)RES_ROWS(db_res)[i].values[j].val.blob_val.s;
530                                         break;
531                                         case DB1_INT:
532                                                 val.type = SR_XTYPE_INT;
533                                                 val.v.i
534                                                         = (int)RES_ROWS(db_res)[i].values[j].val.int_val;
535                                         break;
536                                         case DB1_DATETIME:
537                                                 val.type = SR_XTYPE_INT;
538                                                 val.v.i
539                                                         = (int)RES_ROWS(db_res)[i].values[j].val.time_val;
540                                         break;
541                                         case DB1_BITMAP:
542                                                 val.type = SR_XTYPE_INT;
543                                                 val.v.i
544                                                         = (int)RES_ROWS(db_res)[i].values[j].val.bitmap_val;
545                                         break;
546                                         case DB1_BIGINT:
547                                                 val.type = SR_XTYPE_LLONG;
548                                                 val.v.ll
549                                                         = RES_ROWS(db_res)[i].values[j].val.ll_val;
550                                         break;
551                                         default:
552                                                 val.type = SR_XTYPE_NULL;
553                                 }
554                         }
555                         /* Add column to current row, under the column's name */
556                         LM_DBG("Adding column: %.*s\n", RES_NAMES(db_res)[j]->len, RES_NAMES(db_res)[j]->s);
557                         xavp_add_value(RES_NAMES(db_res)[j], &val, &row);
558                 }
559                 /* Add row to result xavp */
560                 val.type = SR_XTYPE_XAVP;
561                 val.v.xavp = row;
562                 LM_DBG("Adding row\n");
563                 xavp_add_value(xavp, &val, NULL);
564         }
565
566         con->dbf.free_result(con->dbh, db_res);
567         return 1;
568 }
569
570
571 int sql_do_xquery(struct sip_msg *msg, sql_con_t *con, pv_elem_t *query,
572                 pv_elem_t *res)
573 {
574         str sv, xavp;
575         if(msg==NULL || query==NULL || res==NULL)
576         {
577                 LM_ERR("bad parameters\n");
578                 return -1;
579         }
580         if(pv_printf_s(msg, query, &sv)!=0)
581         {
582                 LM_ERR("cannot print the sql query\n");
583                 return -1;
584         }
585
586         if(pv_printf_s(msg, res, &xavp)!=0)
587         {
588                 LM_ERR("cannot print the result parameter\n");
589                 return -1;
590         }
591         return sql_exec_xquery(msg, con, &sv, &xavp);
592 }
593
594
595 int sql_do_pvquery(struct sip_msg *msg, sql_con_t *con, pv_elem_t *query,
596                 pvname_list_t *res)
597 {
598         db1_res_t* db_res = NULL;
599         pvname_list_t* pv;
600         str sv;
601         int i, j;
602
603         if(msg==NULL || query==NULL || res==NULL)
604         {
605                 LM_ERR("bad parameters\n");
606                 return -1;
607         }
608         if(pv_printf_s(msg, query, &sv)!=0)
609         {
610                 LM_ERR("cannot print the sql query\n");
611                 return -1;
612         }
613
614         if(con->dbf.raw_query(con->dbh, &sv, &db_res)!=0)
615         {
616                 LM_ERR("cannot do the query\n");
617                 return -1;
618         }
619
620         if(db_res==NULL || RES_ROW_N(db_res)<=0 || RES_COL_N(db_res)<=0)
621         {
622                 LM_DBG("no result after query\n");
623                 con->dbf.free_result(con->dbh, db_res);
624                 return 2;
625         }
626
627         for(i=RES_ROW_N(db_res)-1; i>=0; i--)
628         {
629                 pv = res;
630                 for(j=0; j<RES_COL_N(db_res); j++)
631                 {
632                         if (pv == NULL) {
633                                 LM_ERR("Missing pv spec for column %d\n", j+1);
634                                 goto error;
635                         }
636                         if (db_val2pv_spec(msg, &RES_ROWS(db_res)[i].values[j], &pv->sname) != 0) {
637                                 LM_ERR("Failed to convert value for column %.*s (row %d)\n",
638                                        RES_NAMES(db_res)[j]->len, RES_NAMES(db_res)[j]->s, i);
639                                 goto error;
640                         }
641                         pv = pv->next;
642                 }
643         }
644
645         con->dbf.free_result(con->dbh, db_res);
646         return 1;
647
648 error:
649         con->dbf.free_result(con->dbh, db_res);
650         return -1;
651 }
652
653
654 int sql_parse_param(char *val)
655 {
656         str name;
657         str tok;
658         str in;
659         char *p;
660
661         /* parse: name=>db_url*/
662         in.s = val;
663         in.len = strlen(in.s);
664         p = in.s;
665
666         while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
667                 p++;
668         if(p>in.s+in.len || *p=='\0')
669                 goto error;
670         name.s = p;
671         while(p < in.s + in.len)
672         {
673                 if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
674                         break;
675                 p++;
676         }
677         if(p>in.s+in.len || *p=='\0')
678                 goto error;
679         name.len = p - name.s;
680         if(*p!='=')
681         {
682                 while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
683                         p++;
684                 if(p>in.s+in.len || *p=='\0' || *p!='=')
685                         goto error;
686         }
687         p++;
688         if(*p!='>')
689                 goto error;
690         p++;
691         while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
692                 p++;
693         tok.s = p;
694         tok.len = in.len + (int)(in.s - p);
695
696         LM_DBG("cname: [%.*s] url: [%.*s]\n", name.len, name.s, tok.len, tok.s);
697
698         return sql_init_con(&name, &tok);
699 error:
700         LM_ERR("invalid sqlops parameter [%.*s] at [%d]\n", in.len, in.s,
701                         (int)(p-in.s));
702         return -1;
703 }
704
705 void sql_destroy(void)
706 {
707         sql_result_t *r;
708         sql_result_t *r0;
709         
710         sql_disconnect();
711
712         r=_sql_result_root;
713         while(r)
714         {
715                 r0 = r->next;
716                 sql_reset_result(r);
717                 pkg_free(r);
718                 r = r0;
719         }
720         _sql_result_root = NULL;
721 }
722
723 /**
724  *
725  */
726 int sqlops_do_query(str *scon, str *squery, str *sres)
727 {
728         sql_con_t *con = NULL;
729         sql_result_t *res = NULL;
730
731         if (scon == NULL || scon->s == NULL)
732         {
733                 LM_ERR("invalid connection name\n");
734                 goto error;
735         }
736
737         con = sql_get_connection(scon);
738         if(con==NULL)
739         {
740                 LM_ERR("invalid connection [%.*s]\n", scon->len, scon->s);
741                 goto error;
742         }
743         /* Result parameter is optional */
744         if (sres && sres->s)
745         {
746                 res = sql_get_result(sres);
747                 if(res==NULL)
748                 {
749                         LM_ERR("invalid result container [%.*s]\n", sres->len, sres->s);
750                         goto error;
751                 }
752         }
753         if(sql_do_query(con, squery, res)<0)
754                 goto error;
755
756         return 0;
757 error:
758         return -1;
759 }
760
761 /**
762  *
763  */
764 int sqlops_get_value(str *sres, int i, int j, sql_val_t **val)
765 {
766         sql_result_t *res = NULL;
767
768         if (sres == NULL || sres->s == NULL)
769         {
770                 LM_ERR("invalid result name\n");
771                 goto error;
772         }
773
774         res = sql_get_result(sres);
775         if(res==NULL)
776         {
777                 LM_ERR("invalid result container [%.*s]\n", sres->len, sres->s);
778                 goto error;
779         }
780         if(i>=res->nrows)
781         {
782                 LM_ERR("row index out of bounds [%d/%d]\n", i, res->nrows);
783                 goto error;
784         }
785         if(j>=res->ncols)
786         {
787                 LM_ERR("column index out of bounds [%d/%d]\n", j, res->ncols);
788                 goto error;
789         }
790         *val = &res->vals[i][j];
791
792         return 0;
793 error:
794         return -1;
795 }
796
797 /**
798  *
799  */
800 int sqlops_is_null(str *sres, int i, int j)
801 {
802         sql_result_t *res = NULL;
803
804         if (sres == NULL || sres->s == NULL)
805         {
806                 LM_ERR("invalid result name\n");
807                 goto error;
808         }
809
810         res = sql_get_result(sres);
811         if(res==NULL)
812         {
813                 LM_ERR("invalid result container [%.*s]\n", sres->len, sres->s);
814                 goto error;
815         }
816         if(i>=res->nrows)
817         {
818                 LM_ERR("row index out of bounds [%d/%d]\n", i, res->nrows);
819                 goto error;
820         }
821         if(j>=res->ncols)
822         {
823                 LM_ERR("column index out of bounds [%d/%d]\n", j, res->ncols);
824                 goto error;
825         }
826         if(res->vals[i][j].flags&PV_VAL_NULL)
827                 return 1;
828         return 0;
829 error:
830         return -1;
831 }
832
833 /**
834  *
835  */
836 int sqlops_get_column(str *sres, int i, str *col)
837 {
838         sql_result_t *res = NULL;
839
840         if (sres == NULL || sres->s == NULL)
841         {
842                 LM_ERR("invalid result name\n");
843                 goto error;
844         }
845
846         res = sql_get_result(sres);
847         if(res==NULL)
848         {
849                 LM_ERR("invalid result container [%.*s]\n", sres->len, sres->s);
850                 goto error;
851         }
852         if(i>=res->ncols)
853         {
854                 LM_ERR("column index out of bounds [%d/%d]\n", i, res->ncols);
855                 goto error;
856         }
857         *col = res->cols[i].name;
858         return 0;
859 error:
860         return -1;
861 }
862
863 /**
864  *
865  */
866 int sqlops_num_columns(str *sres)
867 {
868         sql_result_t *res = NULL;
869
870         if (sres == NULL || sres->s == NULL)
871         {
872                 LM_ERR("invalid result name\n");
873                 goto error;
874         }
875
876         res = sql_get_result(sres);
877         if(res==NULL)
878         {
879                 LM_ERR("invalid result container [%.*s]\n", sres->len, sres->s);
880                 goto error;
881         }
882         return res->ncols;
883 error:
884         return -1;
885 }
886
887 /**
888  *
889  */
890 int sqlops_num_rows(str *sres)
891 {
892         sql_result_t *res = NULL;
893
894         if (sres == NULL || sres->s == NULL)
895         {
896                 LM_ERR("invalid result name\n");
897                 goto error;
898         }
899
900         res = sql_get_result(sres);
901         if(res==NULL)
902         {
903                 LM_ERR("invalid result container [%.*s]\n", sres->len, sres->s);
904                 goto error;
905         }
906         return res->nrows;
907 error:
908         return -1;
909 }
910
911 /**
912  *
913  */
914 void sqlops_reset_result(str *sres)
915 {
916         sql_result_t *res = NULL;
917
918         if (sres == NULL || sres->s == NULL)
919         {
920                 LM_ERR("invalid result name\n");
921                 return;
922         }
923
924         res = sql_get_result(sres);
925         if(res==NULL)
926         {
927                 LM_ERR("invalid result container [%.*s]\n", sres->len, sres->s);
928                 return;
929         }
930         sql_reset_result(res);
931
932         return;
933 }
934
935 /**
936  *
937  */
938 int sqlops_do_xquery(sip_msg_t *msg, str *scon, str *squery, str *xavp)
939 {
940         sql_con_t *con = NULL;
941
942         if (scon == NULL || scon->s == NULL)
943         {
944                 LM_ERR("invalid connection name\n");
945                 goto error;
946         }
947
948         con = sql_get_connection(scon);
949         if(con==NULL)
950         {
951                 LM_ERR("invalid connection [%.*s]\n", scon->len, scon->s);
952                 goto error;
953         }
954         if(sql_exec_xquery(msg, con, squery, xavp)<0)
955                 goto error;
956
957         return 0;
958 error:
959         return -1;
960 }
961