00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <string.h>
00029 #include <stdlib.h>
00030 #include <stdio.h>
00031 #include <ctype.h>
00032 #include "../../sr_module.h"
00033 #include "../../mem/mem.h"
00034 #include "../../str.h"
00035 #include "../../error.h"
00036 #include "../../config.h"
00037 #include "../../trim.h"
00038 #include "../../lib/srdb2/db.h"
00039 #include "../../select.h"
00040 #include "../../script_cb.h"
00041 #include "../xlog/xl_lib.h"
00042 #include "../../route.h"
00043 #include "../../action.h"
00044 #include "../../ut.h"
00045 #include "../../str_hash.h"
00046
00047
00048 MODULE_VERSION
00049
00050 #define MODULE_NAME "db_ops"
00051 #define MODULE_NAME2 "db"
00052
00053 static char* db_url = DEFAULT_DB_URL;
00054 static int xlbuf_size = 4096;
00055
00056 enum dbops_type {OPEN_QUERY_OPS, INSERT_OPS, UPDATE_OPS, REPLACE_OPS, DELETE_OPS};
00057
00058 #define FLD_DELIM ','
00059 #define PART_DELIM '/'
00060
00061 #define NO_SCRIPT -1
00062
00063 static str* xl_nul = NULL;
00064 static xl_print_log_f* xl_print = NULL;
00065 static xl_parse_format_f* xl_parse = NULL;
00066 static xl_get_nulstr_f* xl_getnul = NULL;
00067
00068 static char *xlbuf = 0;
00069 static char *xlbuf_tail;
00070
00071 struct xlstr {
00072 char *s;
00073 xl_elog_t* xlfmt;
00074 };
00075
00076 struct extra_ops {
00077 char *name;
00078 int type;
00079 char *value;
00080 };
00081
00082 struct dbops_action {
00083 char *query_name;
00084 char *db_url;
00085
00086 db_ctx_t* ctx;
00087 db_cmd_t* cmd;
00088
00089 enum dbops_type operation;
00090 int query_no;
00091 int is_raw_query;
00092 struct xlstr table;
00093
00094 int field_count;
00095 struct xlstr* fields;
00096
00097 int where_count;
00098 struct xlstr* wheres;
00099 int op_count;
00100
00101 struct xlstr* ops;
00102 int value_count;
00103 struct xlstr* values;
00104 int* value_types;
00105
00106 struct xlstr order;
00107 struct xlstr raw;
00108
00109 int extra_ops_count;
00110 struct extra_ops* extra_ops;
00111
00112 db_res_t* result;
00113
00114 struct dbops_action* next;
00115 };
00116
00117 struct dbops_handle {
00118 char *handle_name;
00119 struct dbops_action* action;
00120 db_res_t* result;
00121 int cur_row_no;
00122 struct dbops_handle *next;
00123 };
00124
00125
00126
00127 static struct dbops_action* dbops_actions = 0;
00128
00129
00130 static struct dbops_handle* dbops_handles = 0;
00131
00132 #define eat_spaces(_p) \
00133 while( *(_p)==' ' || *(_p)=='\t' ){\
00134 (_p)++;}
00135
00136 #define eat_alphanum(_p) \
00137 while ( (*(_p) >= 'a' && *(_p) <= 'z') || (*(_p) >= 'A' && *(_p) <= 'Z') || (*(_p) >= '0' && *(_p) <= '9') || (*(_p) == '_') ) {\
00138 (_p)++;\
00139 }
00140
00141 static struct dbops_action* find_action_by_name(char *name, int len) {
00142 struct dbops_action *a;
00143 if (len == -1) len = strlen(name);
00144 for (a=dbops_actions; a; a = a->next) {
00145 if (a->query_name && strlen(a->query_name)==len && strncmp(name, a->query_name, len) == 0)
00146 return a;
00147 }
00148 return NULL;
00149 }
00150
00151 static struct dbops_handle* find_handle_by_name(char *name, int len) {
00152 struct dbops_handle *a;
00153 if (len == -1) len = strlen(name);
00154 for (a=dbops_handles; a; a = a->next) {
00155 if (a->handle_name && strlen(a->handle_name)==len && strncmp(name, a->handle_name, len) == 0)
00156 return a;
00157 }
00158 return NULL;
00159 }
00160
00161 static void trim_apostr(char **s) {
00162 int i;
00163 while ( **s == '\'') {
00164 (*s)++;
00165 }
00166 i = strlen(*s);
00167 while (i && (*s)[i-1] == '\'') {
00168 i--;
00169 (*s)[i] = 0;
00170 }
00171 }
00172
00173 static int get_next_part(char** s, char** part, char delim, int read_only) {
00174 char *c, *c2;
00175 char flag = 0;
00176
00177 c = c2 = *s;
00178 eat_spaces(c);
00179
00180 while (!(((*c2 == delim) && !flag) || *c2==0)) {
00181 if (*c2=='\'')
00182 flag = !flag;
00183 c2++;
00184 }
00185 if ((*c2)==0 && flag) {
00186 ERR(MODULE_NAME": string '%s' is not terminated\n", *s);
00187 return E_CFG;
00188 }
00189 if (*c2) {
00190 if (!read_only) *c2 = 0;
00191 *s = c2+1;
00192 }
00193 else {
00194 *s = c2;
00195 }
00196 eat_spaces(*s);
00197 c2--;
00198
00199 while ( c2 > c && ((*c2 == ' ')||(*c2 == '\t')) ) {
00200 if (!read_only) *c2 = 0;
00201 c2--;
00202 }
00203 *part = c;
00204 return 0;
00205 }
00206
00207 static int split_fields(char *part, int *n, struct xlstr **strs) {
00208 int i, res;
00209 char *c, *fld;
00210
00211 *n = 0;
00212 *strs = 0;
00213 c = part;
00214 while (*c) {
00215 res = get_next_part(&c, &fld, FLD_DELIM, 1);
00216 if (res < 0) return res;
00217 (*n)++;
00218 }
00219 *strs = pkg_malloc( (*n)*sizeof(**strs));
00220 if (!strs) {
00221 ERR(MODULE_NAME": split_fields: not enough pkg memory\n");
00222 return E_OUT_OF_MEM;
00223 }
00224 memset(*strs, 0, (*n)*sizeof(**strs));
00225 i = 0;
00226 c = part;
00227 while (*c) {
00228 res = get_next_part(&c, &(*strs)[i].s, FLD_DELIM, 0);
00229 if (res < 0) return res;
00230 trim_apostr(&(*strs)[i].s);
00231 i++;
00232 }
00233 return 0;
00234 }
00235
00236 static int get_type(char **s, int *type) {
00237 if (*s && (*s)[0] && (*s)[1]==':') {
00238 switch ((*s)[0]) {
00239 case 't':
00240 *type = DB_DATETIME;
00241 break;
00242 case 'i':
00243 *type = DB_INT;
00244 break;
00245 case 'f':
00246 *type = DB_FLOAT;
00247 break;
00248 case 'd':
00249 *type = DB_DOUBLE;
00250 break;
00251 case 's':
00252 *type = DB_CSTR;
00253 break;
00254 default:
00255 ERR(MODULE_NAME": get_type: bad param type in '%s'\n", *s);
00256 return E_CFG;
00257 }
00258 (*s)+=2;
00259 }
00260 return 0;
00261 }
00262
00263 static int parse_ops(char* act_s, struct dbops_action** action, int has_name) {
00264 int res = 0, i;
00265 char *c, *s, *part;
00266 static int query_no = 0;
00267
00268 s = act_s;
00269 *action = pkg_malloc(sizeof(**action));
00270 if (!*action) return E_OUT_OF_MEM;
00271 memset(*action, 0, sizeof(**action));
00272 (*action)->query_no = query_no++;
00273
00274 eat_spaces(s);
00275 c = s;
00276 eat_alphanum(c);
00277 if (has_name) {
00278 char *c2;
00279 c2 = c;
00280 eat_spaces(c2);
00281 if (c != s && *c2 == '=') {
00282 *c = '\0';
00283 if (find_action_by_name(s, -1) != NULL) {
00284 ERR(MODULE_NAME": parse_ops: duplicate query name: %s\n", s);
00285 return E_CFG;
00286 }
00287 (*action)->query_name = s;
00288 s = c2+1;
00289 eat_spaces(s);
00290 c = s;
00291 eat_alphanum(c);
00292 }
00293 else {
00294 ERR(MODULE_NAME": parse_ops: query_no: %d, valid query name not found in '%s'\n%s\n%s\n", (*action)->query_no, s, c, c2);
00295 return E_CFG;
00296 }
00297 }
00298
00299 if (c[0] == ':' && c[1] == '/' && c[2] == '/') {
00300 for (c=s; *c!=':'; c++) {
00301 *c = tolower(*c);
00302 }
00303 (*action)->db_url = s;
00304 s = c+1;
00305 while (*s == '/') s++;
00306 res = get_next_part(&s, &part, PART_DELIM, 1);
00307 if (res < 0) return res;
00308
00309
00310 res = get_next_part(&s, &part, PART_DELIM, 0);
00311 if (res < 0) return res;
00312 }
00313 res = get_next_part(&s, &part, PART_DELIM, 0);
00314 if (res < 0) return res;
00315
00316 for (c = part; *c && *c != PART_DELIM; c++) {
00317 if (*c == ' ') {
00318 (*action)->is_raw_query = 1;
00319 *c = '\0';
00320 break;
00321 }
00322 }
00323 if (strcasecmp(part, "select") == 0)
00324 (*action)->operation = OPEN_QUERY_OPS;
00325 else if (strcasecmp(part, "insert") == 0)
00326 (*action)->operation = INSERT_OPS;
00327 else if (strcasecmp(part, "update") == 0)
00328 (*action)->operation = UPDATE_OPS;
00329 else if (strcasecmp(part, "replace") == 0)
00330 (*action)->operation = REPLACE_OPS;
00331 else if (strcasecmp(part, "delete") == 0)
00332 (*action)->operation = DELETE_OPS;
00333 else {
00334 if ((*action)->is_raw_query) *c = ' ';
00335 ERR(MODULE_NAME": parse_ops: query: %s(%d), unknown type of query '%s'\n", (*action)->query_name, (*action)->query_no, part);
00336 return E_CFG;
00337 }
00338 if ((*action)->is_raw_query) {
00339 *c = ' ';
00340 (*action)->raw.s = part;
00341 (*action)->table.s = part;
00342 }
00343
00344 res = get_next_part(&s, &part, PART_DELIM, 0);
00345 if (res < 0) return res;
00346 if (!(*action)->is_raw_query) {
00347
00348 if (!*part) {
00349 ERR(MODULE_NAME": parse_ops: query: %s(%d), table not specified near '%s' in '%s'\n", (*action)->query_name, (*action)->query_no, s, act_s);
00350 return E_CFG;
00351 }
00352 trim_apostr(&part);
00353 (*action)->table.s = part;
00354
00355 res = get_next_part(&s, &part, PART_DELIM, 0);
00356 if (res < 0) return res;
00357 switch ((*action)->operation) {
00358 case OPEN_QUERY_OPS:
00359 case UPDATE_OPS:
00360 case REPLACE_OPS:
00361 case INSERT_OPS:
00362 res = split_fields(part, &(*action)->field_count, &(*action)->fields);
00363 if (res < 0) return res;
00364 if ((*action)->field_count == 0) {
00365 ERR(MODULE_NAME": parse_ops: query: %s(%d), no field specified near '%s' ?n '%s'\n", (*action)->query_name, (*action)->query_no, part, act_s);
00366 return E_CFG;
00367 }
00368 break;
00369 case DELETE_OPS:
00370 res = split_fields(part, &(*action)->where_count, &(*action)->wheres);
00371 if (res < 0) return res;
00372 res = get_next_part(&s, &part, PART_DELIM, 0);
00373 if (res < 0) return res;
00374 res = split_fields(part, &(*action)->op_count, &(*action)->ops);
00375 if (res < 0) return res;
00376 break;
00377 default:;
00378 }
00379
00380 res = get_next_part(&s, &part, PART_DELIM, 0);
00381 if (res < 0) return res;
00382 switch ((*action)->operation) {
00383 case OPEN_QUERY_OPS:
00384 case UPDATE_OPS:
00385 res = split_fields(part, &(*action)->where_count, &(*action)->wheres);
00386 if (res < 0) return res;
00387 res = get_next_part(&s, &part, PART_DELIM, 0);
00388 if (res < 0) return res;
00389 res = split_fields(part, &(*action)->op_count, &(*action)->ops);
00390 if (res < 0) return res;
00391 res = get_next_part(&s, &part, PART_DELIM, 0);
00392 if (res < 0) return res;
00393 switch ((*action)->operation) {
00394 case OPEN_QUERY_OPS:
00395 if (*part) {
00396 (*action)->order.s = part;
00397 }
00398 res = get_next_part(&s, &part, PART_DELIM, 0);
00399 if (res < 0) return res;
00400 break;
00401 default:;
00402 }
00403 break;
00404 default:
00405 ;
00406 }
00407 }
00408
00409
00410 res = split_fields(part, &(*action)->value_count, &(*action)->values);
00411 if (res < 0) return res;
00412
00413 if ((*action)->value_count) {
00414 (*action)->value_types = (int*)pkg_malloc(sizeof(int) * (*action)->value_count);
00415 if ((*action)->value_types == NULL) {
00416 ERR(MODULE_NAME": No memory left\n");
00417 return -1;
00418 }
00419
00420 for (i=0; i<(*action)->value_count; i++) {
00421 (*action)->value_types[i] = DB_CSTR;
00422 res = get_type(&(*action)->values[i].s, &(*action)->value_types[i]);
00423 if (res < 0) return res;
00424 }
00425 }
00426
00427
00428 res = get_next_part(&s, &part, PART_DELIM, 0);
00429 if (res < 0) return res;
00430
00431 (*action)->extra_ops_count = 0;
00432 c = part;
00433 while (*c) {
00434 char *fld;
00435 res = get_next_part(&c, &fld, FLD_DELIM, 1);
00436 if (res < 0) return res;
00437 (*action)->extra_ops_count++;
00438 }
00439 if ((*action)->extra_ops_count > 0) {
00440 (*action)->extra_ops = pkg_malloc( (*action)->extra_ops_count*sizeof(*(*action)->extra_ops));
00441 if (!(*action)->extra_ops) {
00442 ERR(MODULE_NAME": parse_ops: not enough pkg memory\n");
00443 return E_OUT_OF_MEM;
00444 }
00445 memset((*action)->extra_ops, 0, (*action)->extra_ops_count*sizeof(*(*action)->extra_ops));
00446
00447 i = 0;
00448 c = part;
00449 while (*c) {
00450 char *fld;
00451 res = get_next_part(&c, &fld, FLD_DELIM, 0);
00452 if (res < 0) return res;
00453
00454 (*action)->extra_ops[i].name = fld;
00455 eat_alphanum(fld);
00456 if (*fld != '=') {
00457 ERR(MODULE_NAME": parse_ops: query: %s(%d), bad extra parameter format in '%s'\n", (*action)->query_name, (*action)->query_no, (*action)->extra_ops[i].name);
00458 return E_CFG;
00459 }
00460 *fld = '\0';
00461 fld++;
00462 while (*fld==' ' || *fld=='\t') fld++;
00463 (*action)->extra_ops[i].type = DB_NONE;
00464 res = get_type(&fld, &(*action)->extra_ops[i].type);
00465 if (res < 0) return res;
00466 trim_apostr(&fld);
00467 (*action)->extra_ops[i].value = fld;
00468 DEBUG(MODULE_NAME": extra_ops #%d, name='%s', type=%d, val='%s'\n", i, (*action)->extra_ops[i].name, (*action)->extra_ops[i].type, (*action)->extra_ops[i].value);
00469 i++;
00470 }
00471 }
00472
00473 if (*s) {
00474 ERR(MODULE_NAME": parse_ops: query: %s(%d), too many parameters/parts, remaining '%s' in '%s'\n", (*action)->query_name, (*action)->query_no, s, act_s);
00475 return E_CFG;
00476 }
00477 if ((*action)->is_raw_query) {
00478 DEBUG(MODULE_NAME": query: %s(%d) oper:%d database:'%s' query:'%s' value#:%d extra_ops#:%d\n", (*action)->query_name, (*action)->query_no, (*action)->operation, (*action)->db_url, (*action)->raw.s, (*action)->value_count, (*action)->extra_ops_count);
00479 }
00480 else {
00481
00482 if ((((*action)->operation==OPEN_QUERY_OPS)?0:(*action)->field_count)+(*action)->where_count != (*action)->value_count) {
00483 ERR(MODULE_NAME": parse_ops: query: %s(%d), number of values does not correspond to number of fields (%d+%d!=%d) in '%s'\n", (*action)->query_name, (*action)->query_no, ((*action)->operation==OPEN_QUERY_OPS)?0:(*action)->field_count, (*action)->where_count, (*action)->value_count, act_s);
00484 return E_CFG;
00485 }
00486 DEBUG(MODULE_NAME": query_no:%d oper:%d database:'%s' table:'%s' 'field#:'%d' where#:'%d' order:'%s' value#:%d extra_ops#:%d\n", (*action)->query_no, (*action)->operation, (*action)->db_url, (*action)->table.s, (*action)->field_count, (*action)->where_count, (*action)->order.s, (*action)->value_count, (*action)->extra_ops_count);
00487 }
00488 return 0;
00489 }
00490
00491 static int parse_xlstr(struct xlstr* s) {
00492
00493 if (!s->s) return 0;
00494 if (!strchr(s->s, '%')) return 0;
00495
00496
00497 if (!xl_print) {
00498 xl_print=(xl_print_log_f*)find_export("xprint", NO_SCRIPT, 0);
00499
00500 if (!xl_print) {
00501 ERR(MODULE_NAME": cannot find \"xprint\", is module xlog loaded?\n");
00502 return E_UNSPEC;
00503 }
00504 }
00505
00506 if (!xl_parse) {
00507 xl_parse=(xl_parse_format_f*)find_export("xparse", NO_SCRIPT, 0);
00508
00509 if (!xl_parse) {
00510 ERR(MODULE_NAME": cannot find \"xparse\", is module xlog loaded?\n");
00511 return E_UNSPEC;
00512 }
00513 }
00514
00515 if (!xl_nul) {
00516 xl_getnul=(xl_get_nulstr_f*)find_export("xnulstr", NO_SCRIPT, 0);
00517 if (xl_getnul)
00518 xl_nul=xl_getnul();
00519
00520 if (!xl_nul){
00521 ERR(MODULE_NAME": cannot find \"xnulstr\", is module xlog loaded?\n");
00522 return E_UNSPEC;
00523 }
00524 else
00525 INFO(MODULE_NAME": xlog null is \"%.*s\"\n", xl_nul->len, xl_nul->s);
00526 }
00527
00528 if(xl_parse(s->s, &s->xlfmt) < 0) {
00529 ERR(MODULE_NAME": wrong format '%s'\n", s->s);
00530 return E_UNSPEC;
00531 }
00532
00533 return 0;
00534 }
00535
00536 static int eval_xlstr(struct sip_msg* msg, struct xlstr* s) {
00537 static char* null_str = "";
00538 int len;
00539 if (s->xlfmt) {
00540 len = xlbuf_size - (xlbuf_tail-xlbuf);
00541 if (xl_print(msg, s->xlfmt, xlbuf_tail, &len) < 0) {
00542 ERR(MODULE_NAME": eval_xlstr: Error while formating result\n");
00543 return E_UNSPEC;
00544 }
00545
00546
00547 if ((xl_nul) && (xl_nul->len==len) && strncmp(xl_nul->s, xlbuf_tail, len)==0) {
00548 s->s = null_str;
00549 }
00550 else {
00551 s->s = xlbuf_tail;
00552 s->s[len] = '\0';
00553 xlbuf_tail += len+1;
00554 }
00555 }
00556 else {
00557 if (!s->s)
00558 s->s = null_str;
00559 }
00560 return 0;
00561 }
00562
00563 static int dbops_func(struct sip_msg* m, struct dbops_action* action)
00564 {
00565
00566 int res, i;
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 if (action->is_raw_query) {
00587 DEBUG(MODULE_NAME": dbops_func(%s, %d, raw, %d, '%s', %d)\n", action->query_name, action->query_no, action->operation, action->cmd->table.s, action->value_count);
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 }
00599 else {
00600 DEBUG(MODULE_NAME": dbops_func(%s, %d, %d, '%s', %d, %d, %d)\n", action->query_name, action->query_no, action->operation, action->table.s, action->field_count, action->where_count, action->value_count);
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 }
00644 for (i=0; i<action->value_count; i++) {
00645 char *end;
00646 db_fld_t *cmd_params;
00647 res = eval_xlstr(m, &action->values[i]);
00648 if (res < 0) goto cleanup;
00649
00650
00651 if (action->is_raw_query) {
00652 cmd_params = action->cmd->match+i;
00653 }
00654 else {
00655 switch (action->operation) {
00656 case OPEN_QUERY_OPS:
00657 case DELETE_OPS:
00658 cmd_params = action->cmd->match+i;
00659 break;
00660 case UPDATE_OPS:
00661 if (i < action->field_count)
00662 cmd_params = action->cmd->vals+i;
00663 else
00664 cmd_params = action->cmd->match+i-action->field_count;
00665 break;
00666 case REPLACE_OPS:
00667 case INSERT_OPS:
00668 cmd_params = action->cmd->vals+i;
00669 break;
00670 default:
00671 BUG("Unknown operation type: %d\n", action->operation);
00672 goto err;
00673 }
00674 }
00675
00676 if (!action->values[i].s || !action->values[i].s[0]) cmd_params->flags |= DB_NULL;
00677 switch (cmd_params->type) {
00678 case DB_DATETIME:
00679 if (!(cmd_params->flags & DB_NULL))
00680 cmd_params->v.time = strtol(action->values[i].s, &end, 10);
00681 break;
00682 case DB_INT:
00683 if (!(cmd_params->flags & DB_NULL))
00684 cmd_params->v.int4 = strtol(action->values[i].s, &end, 10);
00685 break;
00686 case DB_FLOAT:
00687 if (!(cmd_params->flags & DB_NULL))
00688 #ifdef __USE_ISOC99
00689 cmd_params->v.flt = strtof(action->values[i].s, &end);
00690 #else
00691 cmd_params->v.flt = strtod(action->values[i].s, &end);
00692 #endif
00693 break;
00694 case DB_DOUBLE:
00695 if (!(cmd_params->flags & DB_NULL))
00696 cmd_params->v.dbl = strtod(action->values[i].s, &end);
00697 break;
00698 case DB_CSTR:
00699 cmd_params->v.cstr = action->values[i].s;
00700 cmd_params->flags &= ~DB_NULL;
00701 break;
00702 default:
00703 BUG("Unknown value type: %d\n", cmd_params->type);
00704 goto err;
00705 }
00706 }
00707 if (db_exec((action->operation==OPEN_QUERY_OPS?&action->result:NULL), action->cmd) < 0) goto err;
00708 res = 1;
00709 cleanup:
00710 return res;
00711 err:
00712 ERR(MODULE_NAME": query: %s(%d), database operation (%d) error, table: '%s'\n", action->query_name, action->query_no, action->operation, action->table.s);
00713 res = -1;
00714 goto cleanup;
00715 }
00716
00717 static int do_seek(db_res_t* result, int *cur_row_no, int row_no) {
00718
00719 if (row_no == *cur_row_no) return 0;
00720 if (row_no < *cur_row_no) *cur_row_no = -1;
00721
00722 DEBUG(MODULE_NAME": do_seek: currowno:%d, rowno=%d\n", *cur_row_no, row_no);
00723 if (*cur_row_no < 0) {
00724 if (!db_first(result)) return -1;
00725 *cur_row_no = 0;
00726 }
00727 while (*cur_row_no < row_no) {
00728 if (!db_next(result)) {
00729 *cur_row_no = -1;
00730 return -1;
00731 }
00732 (*cur_row_no)++;
00733 }
00734 return 0;
00735 }
00736
00737 static int sel_get_field(str* res, int *cur_row_no, int field_no, db_res_t* result) {
00738
00739 int len;
00740 db_rec_t* rec;
00741 len = xlbuf_size-(xlbuf_tail-xlbuf);
00742 res->s = xlbuf_tail;
00743 res->len = 0;
00744 if (field_no == -2) {
00745 res->len = snprintf(res->s, len, "%d", *cur_row_no);
00746 }
00747 else if (field_no < 0) {
00748 int n;
00749 if (*cur_row_no < 0) {
00750 rec = db_first(result);
00751 if (rec) {
00752 *cur_row_no = 0;
00753 }
00754 }
00755 if (field_no == -3) {
00756 if (*cur_row_no >= 0)
00757 n = 0;
00758 else
00759 n = 1;
00760 }
00761 else {
00762 n = 0;
00763 if (*cur_row_no >= 0) {
00764 do {
00765 n++;
00766 rec = db_next(result);
00767 } while (rec);
00768 }
00769 *cur_row_no = -1;
00770 }
00771 res->len = snprintf(res->s, len, "%d", n);
00772 }
00773 else {
00774 if (*cur_row_no < 0) {
00775 ERR(MODULE_NAME": cursor points beyond data\n");
00776 return -1;
00777 }
00778 if (field_no >= result->field_count) {
00779 ERR(MODULE_NAME": field (%d) does not exist, num fields: %d\n", field_no, result->field_count);
00780 return -1;
00781 }
00782 rec = result->cur_rec;
00783 if (!(rec->fld[field_no].flags & DB_NULL)) {
00784 switch (rec->fld[field_no].type) {
00785 case DB_INT:
00786 res->len = snprintf(res->s, len, "%d", rec->fld[field_no].v.int4);
00787 break;
00788 case DB_FLOAT:
00789 res->len = snprintf(res->s, len, "%f", rec->fld[field_no].v.flt);
00790 break;
00791 case DB_DOUBLE:
00792 res->len = snprintf(res->s, len, "%f", rec->fld[field_no].v.dbl);
00793 break;
00794 case DB_STR:
00795 res->len = snprintf(res->s, len, "%.*s",
00796 rec->fld[field_no].v.lstr.len,
00797 rec->fld[field_no].v.lstr.s);
00798 break;
00799 case DB_BLOB:
00800 res->len = snprintf(res->s, len, "%.*s",
00801 rec->fld[field_no].v.blob.len,
00802 rec->fld[field_no].v.blob.s);
00803 break;
00804 case DB_CSTR:
00805 res->len = snprintf(res->s, len, "%s", rec->fld[field_no].v.cstr);
00806 break;
00807 case DB_DATETIME:
00808 res->len = snprintf(res->s, len, "%u", (unsigned int) rec->fld[field_no].v.time);
00809 break;
00810 case DB_BITMAP:
00811 res->len = snprintf(res->s, len, "%u", (unsigned int) rec->fld[field_no].v.bitmap);
00812 break;
00813 default:
00814 break;
00815 }
00816 }
00817 }
00818 xlbuf_tail += res->len;
00819 return 0;
00820 }
00821
00822 static int sel_do_select(str* result, str *query_name, int row_no, int field_no, struct sip_msg* msg) {
00823 struct dbops_action *a;
00824 int cur_row_no, res;
00825
00826 a = find_action_by_name(query_name->s, query_name->len);
00827 if (!a) {
00828 ERR(MODULE_NAME": select: query: %.*s not declared using declare_query param\n", query_name->len, query_name->s);
00829 return -1;
00830 }
00831 if (a->operation != OPEN_QUERY_OPS) {
00832 ERR(MODULE_NAME": select: query: %.*s is not select\n", query_name->len, query_name->s);
00833 return -1;
00834 }
00835
00836 if (row_no < 0) {
00837 ERR(MODULE_NAME": select: Row number must not be negative: %d\n", row_no);
00838 return -1;
00839 }
00840
00841 res = dbops_func(msg, a);
00842 if (res < 0) return res;
00843 cur_row_no = -1;
00844 if (field_no >= 0) {
00845 if (do_seek(a->result, &cur_row_no, row_no) < 0)
00846 return -1;
00847 }
00848
00849 res = sel_get_field(result, &cur_row_no, field_no, a->result);
00850 db_res_free(a->result);
00851 return res;
00852 }
00853
00854 static inline int check_query_opened(struct dbops_handle *handle, char *f) {
00855 if (!handle->result) {
00856 ERR(MODULE_NAME": %s: handle '%s' is not opened. Use db_query() first\n", f, handle->handle_name);
00857 return -1;
00858 }
00859 else
00860 return 1;
00861 }
00862
00863 static int sel_do_fetch(str* result, str *handle_name, int field_no, struct sip_msg* msg) {
00864 struct dbops_handle *a;
00865 a = find_handle_by_name(handle_name->s, handle_name->len);
00866 if (!a) {
00867 ERR(MODULE_NAME": fetch: handle (%.*s) is not declared\n", handle_name->len, handle_name->s);
00868 return -1;
00869 }
00870 if (check_query_opened(a, "fetch") < 0) return -1;
00871 return sel_get_field(result, &a->cur_row_no, field_no, a->result);
00872 }
00873
00874 static int sel_dbops(str* res, select_t* s, struct sip_msg* msg) {
00875 return 0;
00876 }
00877
00878 static int sel_select(str* res, select_t* s, struct sip_msg* msg) {
00879 return sel_do_select(res, &s->params[2].v.s, 0, 0, msg);
00880 }
00881
00882 static int sel_select_is_empty(str* res, select_t* s, struct sip_msg* msg) {
00883 return sel_do_select(res, &s->params[2].v.s, 0, -3, msg);
00884 }
00885
00886 static int sel_select_count(str* res, select_t* s, struct sip_msg* msg) {
00887 return sel_do_select(res, &s->params[2].v.s, 0, -1, msg);
00888 }
00889
00890 static int sel_select_row(str* res, select_t* s, struct sip_msg* msg) {
00891 return sel_do_select(res, &s->params[2].v.s, s->params[4].v.i, 0, msg);
00892 }
00893
00894
00895 static int sel_select_row_field(str* res, select_t* s, struct sip_msg* msg) {
00896 return sel_do_select(res, &s->params[2].v.s, s->params[4].v.i, s->params[6].v.i, msg);
00897 }
00898
00899 static int sel_select_field(str* res, select_t* s, struct sip_msg* msg) {
00900 return sel_do_select(res, &s->params[2].v.s, 0, s->params[4].v.i, msg);
00901 }
00902
00903 static int sel_fetch(str* res, select_t* s, struct sip_msg* msg) {
00904 return sel_do_fetch(res, &s->params[2].v.s, 0, msg);
00905 }
00906
00907 static int sel_fetch_field(str* res, select_t* s, struct sip_msg* msg) {
00908 return sel_do_fetch(res, &s->params[2].v.s, s->params[4].v.i, msg);
00909 }
00910
00911 static int sel_fetch_cur_row_no(str* res, select_t* s, struct sip_msg* msg) {
00912 return sel_do_fetch(res, &s->params[2].v.s, -2, msg);
00913 }
00914
00915 static int sel_fetch_is_empty(str* res, select_t* s, struct sip_msg* msg) {
00916 return sel_do_fetch(res, &s->params[2].v.s, -3, msg);
00917 }
00918
00919 static int sel_fetch_count(str* res, select_t* s, struct sip_msg* msg) {
00920 return sel_do_fetch(res, &s->params[2].v.s, -1, msg);
00921 }
00922
00923
00924 SELECT_F(select_any_nameaddr)
00925 SELECT_F(select_any_uri)
00926
00927 select_row_t sel_declaration[] = {
00928 { NULL, SEL_PARAM_STR, STR_STATIC_INIT(MODULE_NAME2), sel_dbops, SEL_PARAM_EXPECTED},
00929
00930 { sel_dbops, SEL_PARAM_STR, STR_STATIC_INIT("query"), sel_select, CONSUME_NEXT_STR},
00931 { sel_select, SEL_PARAM_STR, STR_STATIC_INIT("is_empty"), sel_select_is_empty},
00932 { sel_select, SEL_PARAM_STR, STR_STATIC_INIT("count"), sel_select_count},
00933 { sel_select, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"), select_any_nameaddr, NESTED | CONSUME_NEXT_STR},
00934 { sel_select, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_any_uri, NESTED | CONSUME_NEXT_STR},
00935 { sel_select, SEL_PARAM_STR, STR_STATIC_INIT("field"), sel_select_field, CONSUME_NEXT_INT},
00936 { sel_select_field, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"), select_any_nameaddr, NESTED | CONSUME_NEXT_STR},
00937 { sel_select_field, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_any_uri, NESTED | CONSUME_NEXT_STR},
00938
00939 { sel_select, SEL_PARAM_STR, STR_STATIC_INIT("row"), sel_select_row, CONSUME_NEXT_INT},
00940 { sel_select_row, SEL_PARAM_STR, STR_STATIC_INIT("field"), sel_select_row_field, CONSUME_NEXT_INT},
00941 { sel_select_row_field, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"), select_any_nameaddr, NESTED | CONSUME_NEXT_STR},
00942 { sel_select_row_field, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_any_uri, NESTED | CONSUME_NEXT_STR},
00943
00944 { sel_dbops, SEL_PARAM_STR, STR_STATIC_INIT("fetch"), sel_fetch, CONSUME_NEXT_STR},
00945 { sel_fetch, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"), select_any_nameaddr, NESTED | CONSUME_NEXT_STR},
00946 { sel_fetch, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_any_uri, NESTED | CONSUME_NEXT_STR},
00947 { sel_fetch, SEL_PARAM_STR, STR_STATIC_INIT("row_no"), sel_fetch_cur_row_no, 0},
00948 { sel_fetch, SEL_PARAM_STR, STR_STATIC_INIT("count"), sel_fetch_count, 0},
00949 { sel_fetch, SEL_PARAM_STR, STR_STATIC_INIT("is_empty"), sel_fetch_is_empty, 0},
00950 { sel_fetch, SEL_PARAM_STR, STR_STATIC_INIT("field"), sel_fetch_field, CONSUME_NEXT_INT},
00951 { sel_fetch_field, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"), select_any_nameaddr, NESTED | CONSUME_NEXT_STR},
00952 { sel_fetch_field, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_any_uri, NESTED | CONSUME_NEXT_STR},
00953
00954 { NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
00955 };
00956
00957 static int dbops_close_query_func(struct sip_msg* m, char* handle, char* dummy) {
00958 struct dbops_handle *a = (void *)handle;
00959 if (a->result) {
00960 db_res_free(a->result);
00961 a->result = 0;
00962 }
00963 return 1;
00964 }
00965
00966 static int dbops_pre_script_cb(struct sip_msg *msg, unsigned int flags, void *param) {
00967 xlbuf_tail = xlbuf;
00968 return 1;
00969 }
00970
00971 static int dbops_post_script_cb(struct sip_msg *msg, unsigned int flags, void *param) {
00972 struct dbops_handle *a;
00973 for (a = dbops_handles; a; a=a->next) {
00974 dbops_close_query_func(msg, (char*) a, 0);
00975 }
00976 return 1;
00977 }
00978
00979 static int init_action(struct dbops_action* action) {
00980 int res, i;
00981
00982 if (!action->db_url)
00983 action->db_url = db_url;
00984
00985 res = parse_xlstr(&action->table);
00986 if (res < 0) return res;
00987 for (i=0; i<action->field_count; i++) {
00988 res = parse_xlstr(&action->fields[i]);
00989 if (res < 0) return res;
00990 }
00991
00992 for (i=0; i<action->where_count; i++) {
00993 res = parse_xlstr(&action->wheres[i]);
00994 if (res < 0) return res;
00995 }
00996 for (i=0; i<action->value_count; i++) {
00997 res = parse_xlstr(&action->values[i]);
00998 if (res < 0) return res;
00999 }
01000 res = parse_xlstr(&action->order);
01001 if (res < 0) return res;
01002 res = parse_xlstr(&action->raw);
01003
01004 return res;
01005 }
01006
01007 static int dbops_fixup_func(void** param, int init_act) {
01008 struct dbops_action **p, *a;
01009 char *c;
01010 int res;
01011
01012
01013 c = *param;
01014 eat_spaces(c);
01015 *param = c;
01016 eat_alphanum(c);
01017 if (*c == 0) {
01018 a = find_action_by_name(*param, -1);
01019 if (!a) {
01020 ERR(MODULE_NAME": fixup_func: query (%s) not declared\n", (char*) *param);
01021 return -1;
01022 }
01023 *param = (void*) a;
01024 return 0;
01025 }
01026
01027 for (p = &dbops_actions; *p; p=&(*p)->next);
01028 res = parse_ops(*param, p, init_act == 0 );
01029 if (res < 0) return res;
01030
01031 *param = (void*) *p;
01032 if (init_act)
01033 return init_action(*p);
01034 else
01035 return 0;
01036 }
01037
01038 static int mod_init(void) {
01039 struct dbops_action* p;
01040
01041 xlbuf = pkg_malloc((xlbuf_size+1)*sizeof(char));
01042 if (!xlbuf) {
01043 ERR(MODULE_NAME": out of memory, cannot create xlbuf\n");
01044 return E_OUT_OF_MEM;
01045 }
01046
01047 for (p=dbops_actions; p; p=p->next) {
01048 int res;
01049 res = init_action(p);
01050 if (res < 0)
01051 return res;
01052 }
01053
01054 register_script_cb(dbops_pre_script_cb, REQUEST_CB | ONREPLY_CB | PRE_SCRIPT_CB, 0);
01055 register_script_cb(dbops_post_script_cb, REQUEST_CB | ONREPLY_CB | POST_SCRIPT_CB, 0);
01056 register_select_table(sel_declaration);
01057
01058 return 0;
01059 }
01060
01061
01062 static int build_match(db_fld_t** match, struct dbops_action* p)
01063 {
01064 int i;
01065 db_fld_t* newp;
01066
01067 if (!p->where_count) {
01068 *match = NULL;
01069 return 0;
01070 }
01071
01072 newp = (db_fld_t*)pkg_malloc(sizeof(db_fld_t) * (p->where_count + 1));
01073 if (newp == NULL) {
01074 ERR(MODULE_NAME": No memory left\n");
01075 return -1;
01076 }
01077 memset(newp, '\0', sizeof(db_fld_t) * p->where_count);
01078
01079 for(i = 0; i < p->where_count; i++) {
01080 newp[i].name = p->wheres[i].s;
01081 newp[i].type = p->value_types[i];
01082
01083 if (i < p->op_count) {
01084 if (!strcmp(p->ops[i].s, "=")) {
01085 newp[i].op = DB_EQ;
01086 } else if (!strcmp(p->ops[i].s, "<=")) {
01087 newp[i].op = DB_LEQ;
01088 } else if (!strcmp(p->ops[i].s, "<")) {
01089 newp[i].op = DB_LT;
01090 } else if (!strcmp(p->ops[i].s, ">")) {
01091 newp[i].op = DB_GT;
01092 } else if (!strcmp(p->ops[i].s, ">=")) {
01093 newp[i].op = DB_GEQ;
01094 } else if (!strcmp(p->ops[i].s, "<>")) {
01095 newp[i].op = DB_NE;
01096 } else if (!strcmp(p->ops[i].s, "!=")) {
01097 newp[i].op = DB_NE;
01098 } else {
01099 ERR(MODULE_NAME": Unsupported operator type: %s\n", p->ops[i].s);
01100 pkg_free(newp);
01101 return -1;
01102 }
01103 }
01104 else {
01105 newp[i].op = DB_EQ;
01106 }
01107 }
01108 newp[i].name = NULL;
01109
01110 *match = newp;
01111 return 0;
01112 }
01113
01114
01115 static int build_result(db_fld_t** result, struct dbops_action* p)
01116 {
01117 int i;
01118 db_fld_t* newp;
01119
01120 if (!p->field_count) {
01121 *result = NULL;
01122 return 0;
01123 }
01124
01125 newp = (db_fld_t*)pkg_malloc(sizeof(db_fld_t) * (p->field_count + 1));
01126 if (newp == NULL) {
01127 ERR(MODULE_NAME": No memory left\n");
01128 return -1;
01129 }
01130 memset(newp, '\0', sizeof(db_fld_t) * p->field_count);
01131
01132 for(i = 0; i < p->field_count; i++) {
01133 newp[i].name = p->fields[i].s;
01134 newp[i].type = DB_NONE;
01135 }
01136 newp[i].name = NULL;
01137 *result = newp;
01138 return 0;
01139 }
01140
01141
01142 static int build_params(db_fld_t** params, struct dbops_action* p)
01143 {
01144 int i;
01145 db_fld_t* newp;
01146
01147 if (!p->value_count) {
01148 *params = NULL;
01149 return 0;
01150 }
01151
01152 newp = (db_fld_t*)pkg_malloc(sizeof(db_fld_t) * (p->value_count - p->where_count + 1));
01153 if (newp == NULL) {
01154 ERR(MODULE_NAME": No memory left\n");
01155 return -1;
01156 }
01157 memset(newp, '\0', sizeof(db_fld_t) * p->value_count);
01158
01159 for(i = 0; i < p->value_count - p->where_count; i++) {
01160 newp[i].name = (i < p->field_count)?p->fields[i].s:"";
01161 newp[i].type = p->value_types[i];
01162 }
01163 newp[i].name = NULL;
01164
01165 *params = newp;
01166 return 0;
01167 }
01168
01169
01170
01171 static int init_db(struct dbops_action* p)
01172 {
01173 db_fld_t* matches = NULL, *result = NULL, *values = NULL;
01174 int type, i;
01175
01176 DEBUG(MODULE_NAME": init_db: query: %s(%d)\n", p->query_name, p->query_no);
01177 if (p->db_url == NULL) {
01178 ERR(MODULE_NAME": No database URL specified\n");
01179 return -1;
01180 }
01181 p->ctx = db_ctx(MODULE_NAME);
01182 if (p->ctx == NULL) {
01183 ERR(MODULE_NAME": Error while initializing database layer\n");
01184 return -1;
01185 }
01186
01187 if (db_add_db(p->ctx, p->db_url) < 0) return -1;
01188 if (db_connect(p->ctx) < 0) return -1;
01189
01190 if (p->is_raw_query) {
01191 type = DB_SQL;
01192 if (build_params(&matches, p) < 0) return -1;
01193 }
01194 else {
01195 switch(p->operation) {
01196 case INSERT_OPS:
01197 case REPLACE_OPS:
01198 type = DB_PUT;
01199 if (build_params(&values, p) < 0) return -1;
01200 break;
01201
01202 case UPDATE_OPS:
01203 type = DB_UPD;
01204 if (build_match(&matches, p) < 0) return -1;
01205 if (build_params(&values, p) < 0) {
01206 if (matches) pkg_free(matches);
01207 return -1;
01208 }
01209 break;
01210
01211 case DELETE_OPS:
01212 type = DB_DEL;
01213
01214 if (build_match(&matches, p) < 0) return -1;
01215 break;
01216
01217 case OPEN_QUERY_OPS:
01218 type = DB_GET;
01219 if (build_match(&matches, p) < 0) return -1;
01220 if (build_result(&result, p) < 0) {
01221 if (matches) pkg_free(matches);
01222 return -1;
01223 }
01224 break;
01225 default:
01226 BUG("Unknown operation %d\n", p->operation);
01227 return -1;
01228 }
01229 }
01230
01231 p->cmd = db_cmd(type, p->ctx, p->table.s, result, matches, values);
01232 if (p->cmd == NULL) {
01233 ERR(MODULE_NAME": init_db: query: %s(%d), error while compiling database query\n", p->query_name, p->query_no);
01234 if (values) pkg_free(values);
01235 if (matches) pkg_free(matches);
01236 if (result) pkg_free(result);
01237 db_disconnect(p->ctx);
01238 db_ctx_free(p->ctx);
01239 return -1;
01240 }
01241 if (values) pkg_free(values);
01242 if (matches) pkg_free(matches);
01243 if (result) pkg_free(result);
01244
01245 for (i=0; i<p->extra_ops_count; i++) {
01246 char *end;
01247 DEBUG(MODULE_NAME": init_db: query_no: %s(%d), setopt('%s', %i, '%s'\n", p->query_name, p->query_no, p->extra_ops[i].name, p->extra_ops[i].type, p->extra_ops[i].value);
01248 switch (p->extra_ops[i].type) {
01249 case DB_NONE:
01250
01251 break;
01252 case DB_DATETIME: {
01253 time_t v;
01254 v = strtol(p->extra_ops[i].value, &end, 10);
01255 if (db_setopt(p->cmd, p->extra_ops[i].name, v) < 0) return -1;
01256 break;
01257 }
01258 case DB_INT: {
01259 int v;
01260 v = strtol(p->extra_ops[i].value, &end, 10);
01261 if (db_setopt(p->cmd, p->extra_ops[i].name, v) < 0) return -1;
01262 break;
01263 }
01264 case DB_FLOAT: {
01265 float v;
01266 #ifdef __USE_ISOC99
01267 v = strtof(p->extra_ops[i].value, &end);
01268 #else
01269 v = strtod(p->extra_ops[i].value, &end);
01270 #endif
01271 if (db_setopt(p->cmd, p->extra_ops[i].name, v) < 0) return -1;
01272 break;
01273 }
01274 case DB_DOUBLE: {
01275 double v;
01276 v = strtod(p->extra_ops[i].value, &end);
01277 if (db_setopt(p->cmd, p->extra_ops[i].name, v) < 0) return -1;
01278 break;
01279 }
01280 case DB_CSTR:
01281 if (db_setopt(p->cmd, p->extra_ops[i].name, p->extra_ops[i].value) < 0) return -1;
01282 break;
01283 default:
01284 BUG("Unknown extra_op type: %d\n", p->extra_ops[i].type);
01285 return -1;
01286 }
01287 }
01288 return 0;
01289 }
01290
01291 static int child_init(int rank) {
01292 struct dbops_action *p, *p2;
01293 if (rank!=PROC_INIT && rank != PROC_MAIN && rank != PROC_TCP_MAIN) {
01294 for (p=dbops_actions; p; p=p->next) {
01295 for (p2=dbops_actions; p!=p2; p2=p2->next) {
01296 if (strcmp(p->db_url, p2->db_url) == 0) {
01297 p->ctx = p2->ctx;
01298 break;
01299 }
01300 }
01301
01302
01303
01304 if (init_db(p) < 0) {
01305 ERR(MODULE_NAME": CHILD INIT #err\n");
01306
01307 return -1;
01308 }
01309 }
01310 }
01311 return 0;
01312 }
01313
01314 static int dbops_close_query_fixup(void** param, int param_no) {
01315 struct dbops_handle *a;
01316 a = find_handle_by_name((char*) *param, -1);
01317 if (!a) {
01318 ERR(MODULE_NAME": handle '%s' is not declared\n", (char*) *param);
01319 return E_CFG;
01320 }
01321 pkg_free (*param);
01322 *param = (void*) a;
01323 return 0;
01324 }
01325
01326 static int dbops_query_fixup(void** param, int param_no) {
01327 int res = 0;
01328 if (param_no == 1) {
01329 res = dbops_fixup_func(param, 1);
01330 if (res < 0) return res;
01331 if (((struct dbops_action*)*param)->operation == OPEN_QUERY_OPS) {
01332 if (fixup_get_param_count(param, param_no) != 2) {
01333 ERR(MODULE_NAME": query_fixup: SELECT query requires 2 parameters\n");
01334 return E_CFG;
01335 }
01336 }
01337 else {
01338 if (fixup_get_param_count(param, param_no) != 1) {
01339 ERR(MODULE_NAME": query_fixup: non SELECT query requires only 1 parameter\n");
01340 return E_CFG;
01341 }
01342 }
01343 }
01344 else if (param_no == 2) {
01345 return dbops_close_query_fixup(param, param_no);
01346 }
01347 return res;
01348 }
01349
01350 static int dbops_query_func(struct sip_msg* m, char* dbops_action, char* handle) {
01351 if ( ((struct dbops_action*) dbops_action)->operation == OPEN_QUERY_OPS ) {
01352 int res;
01353 struct dbops_handle *a = (void*) handle;
01354 dbops_close_query_func(m, handle, 0);
01355 res = dbops_func(m, (void*) dbops_action);
01356 if (res < 0) return res;
01357 a->action = (struct dbops_action*) dbops_action;
01358 a->cur_row_no = -1;
01359 a->result = ((struct dbops_action*) dbops_action)->result;
01360 res = do_seek(((struct dbops_action*) dbops_action)->result, &a->cur_row_no, 0);
01361 if (res < 0) return res;
01362 return 1;
01363 }
01364 else
01365 return dbops_func(m, (void*) dbops_action);
01366 }
01367
01368 static int dbops_seek_fixup(void** param, int param_no) {
01369 if (param_no == 1) {
01370 return dbops_close_query_fixup(param, param_no);
01371 }
01372 else if (param_no == 2) {
01373 return fixup_int_12(param, param_no);
01374 }
01375 return 0;
01376 }
01377
01378 static int dbops_seek_func(struct sip_msg* m, char* handle, char* row_no) {
01379 int res, n;
01380 struct dbops_handle *a = (void *) handle;
01381 res = check_query_opened(a, "seek");
01382 if (res < 0) return res;
01383
01384 if (get_int_fparam(&n, m, (fparam_t*) row_no) < 0) {
01385 return -1;
01386 }
01387 res = do_seek(a->result, &a->cur_row_no, n);
01388 if (res < 0) return res;
01389 return 1;
01390 }
01391
01392 static int dbops_first_func(struct sip_msg* m, char* handle, char* row_no) {
01393 int res;
01394 struct dbops_handle *a = (void *) handle;
01395 res = check_query_opened(a, "first");
01396 if (res < 0) return res;
01397
01398 a->cur_row_no = -1;
01399 res = do_seek(a->result, &a->cur_row_no, 0);
01400 if (res < 0) return res;
01401 return 1;
01402 }
01403
01404 static int dbops_next_func(struct sip_msg* m, char* handle, char* row_no) {
01405 int res;
01406 struct dbops_handle *a = (void *) handle;
01407 res = check_query_opened(a, "next");
01408 if (res < 0) return res;
01409
01410 res = do_seek(a->result, &a->cur_row_no, a->cur_row_no+1);
01411 if (res < 0) return res;
01412 return 1;
01413 }
01414
01415 static int dbops_foreach_fixup(void** param, int param_no) {
01416 if (param_no == 1) {
01417 return dbops_close_query_fixup(param, param_no);
01418 }
01419 else if (param_no == 2) {
01420 int n;
01421 n = route_get(&main_rt, (char*) *param);
01422 if (n == -1) {
01423 ERR(MODULE_NAME": db_foreach: bad route\n");
01424 return E_CFG;
01425 }
01426 pkg_free(*param);
01427 *param=(void*) (unsigned long) n;
01428 }
01429 return 0;
01430 }
01431
01432
01433 static int dbops_foreach_func(struct sip_msg* m, char* handle, char* route_no) {
01434 int res;
01435 db_rec_t* rec;
01436 struct dbops_handle *a = (void *) handle;
01437 struct run_act_ctx ra_ctx;
01438
01439 if ((long)route_no >= main_rt.idx) {
01440 BUG("invalid routing table number #%ld of %d\n", (long) route_no, main_rt.idx);
01441 return -1;
01442 }
01443 if (!main_rt.rlist[(long) route_no]) {
01444 WARN(MODULE_NAME": route not declared (hash:%ld)\n", (long) route_no);
01445 return -1;
01446 }
01447 res = check_query_opened(a, "for_each");
01448 if (res < 0) return res;
01449
01450 res = -1;
01451 a->cur_row_no = 0;
01452 for(rec = db_first(a->result);
01453 rec != NULL;
01454 rec = db_next(a->result),
01455 a->cur_row_no++) {
01456
01457 init_run_actions_ctx(&ra_ctx);
01458 res = run_actions(&ra_ctx, main_rt.rlist[(long) route_no], m);
01459 if (res <= 0) break;
01460 }
01461 if (!rec) a->cur_row_no = -1;
01462 return res;
01463 }
01464
01465 static int declare_query(modparam_t type, char* param) {
01466 void* p = param;
01467 return dbops_fixup_func(&p, 0);
01468 }
01469
01470 static int declare_handle(modparam_t type, char* param) {
01471 struct dbops_handle *a;
01472 if (strlen(param) == 0) {
01473 ERR(MODULE_NAME": declare_handle: handle name is empty\n");
01474 return E_CFG;
01475 }
01476 a = find_handle_by_name(param, -1);
01477 if (a) {
01478 ERR(MODULE_NAME": declare_handle: handle '%s' already exists\n", param);
01479 return E_CFG;
01480 }
01481
01482 a = pkg_malloc(sizeof(*a));
01483 if (!a) {
01484 ERR(MODULE_NAME": Out od memory\n");
01485 return E_OUT_OF_MEM;
01486 }
01487 memset(a, 0, sizeof(*a));
01488 a->handle_name = param;
01489 a->next = dbops_handles;
01490 dbops_handles = a;
01491 return 0;
01492 }
01493
01494 static int dbops_proper_func(struct sip_msg* m, char* dummy1, char* dummy2) {
01495 dbops_pre_script_cb(m, 0, NULL);
01496 dbops_post_script_cb(m, 0, NULL);
01497 return 1;
01498 }
01499
01500
01501
01502
01503 static cmd_export_t cmds[] = {
01504 {MODULE_NAME2"_query", dbops_query_func, 1, dbops_query_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
01505 {MODULE_NAME2"_query", dbops_query_func, 2, dbops_query_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
01506 {MODULE_NAME2"_first", dbops_first_func, 1, dbops_close_query_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
01507 {MODULE_NAME2"_next", dbops_next_func, 1, dbops_close_query_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
01508 {MODULE_NAME2"_seek", dbops_seek_func, 2, dbops_seek_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
01509 {MODULE_NAME2"_close", dbops_close_query_func, 1, dbops_close_query_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
01510 {MODULE_NAME2"_foreach", dbops_foreach_func, 2, dbops_foreach_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
01511 {MODULE_NAME2"_proper", dbops_proper_func, 0, 0, FAILURE_ROUTE},
01512 {0, 0, 0, 0, 0}
01513 };
01514
01515
01516
01517
01518
01519 static param_export_t params[] = {
01520 {"db_url", PARAM_STRING, &db_url},
01521 {"declare_query", PARAM_STRING|PARAM_USE_FUNC, (void*) declare_query},
01522 {"declare_handle", PARAM_STRING|PARAM_USE_FUNC, (void*) declare_handle},
01523 {"xlbuf_size", PARAM_INT, &xlbuf_size},
01524 {0, 0, 0}
01525 };
01526
01527
01528 struct module_exports exports = {
01529 MODULE_NAME,
01530 cmds,
01531 0,
01532 params,
01533 mod_init,
01534 0,
01535 0,
01536 0,
01537 child_init
01538 };