/** * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com) * * This file is part of kamailio, a free SIP server. * * Kamailio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * Kamailio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /*! \file * \ingroup sqlops * \brief Kamailio SQL-operations :: Variables * * - Module: \ref sqlops */ #include "../../mem/mem.h" #include "../../dprint.h" #include "../../mod_fix.h" #include "sql_api.h" #include "sql_var.h" typedef struct _sql_pv { str resname; sql_result_t *res; int type; gparam_t row; gparam_t col; } sql_pv_t; int pv_get_dbr(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { sql_pv_t *spv; int row; int col; spv = (sql_pv_t*)param->pvn.u.dname; if(spv->res==NULL) { spv->res = sql_get_result(&spv->resname); if(spv->res==NULL) return pv_get_null(msg, param, res); } switch(spv->type) { case 1: return pv_get_sintval(msg, param, res, spv->res->nrows); break; case 2: return pv_get_sintval(msg, param, res, spv->res->ncols); break; case 3: if(fixup_get_ivalue(msg, &spv->row, &row)!=0) return pv_get_null(msg, param, res); if(fixup_get_ivalue(msg, &spv->col, &col)!=0) return pv_get_null(msg, param, res); if(row>=spv->res->nrows) return pv_get_null(msg, param, res); if(col>=spv->res->ncols) return pv_get_null(msg, param, res); if(spv->res->vals[row][col].flags&PV_VAL_NULL) return pv_get_null(msg, param, res); if(spv->res->vals[row][col].flags&PV_VAL_INT) return pv_get_sintval(msg, param, res, spv->res->vals[row][col].value.n); return pv_get_strval(msg, param, res, &spv->res->vals[row][col].value.s); break; case 4: if(fixup_get_ivalue(msg, &spv->col, &col)!=0) return pv_get_null(msg, param, res); if(col>=spv->res->ncols) return pv_get_null(msg, param, res); return pv_get_strval(msg, param, res, &spv->res->cols[col].name); break; } return 0; } int sql_parse_index(str *in, gparam_t *gp) { if(in->s[0]==PV_MARKER) { gp->type = GPARAM_TYPE_PVS; gp->v.pvs = (pv_spec_t*)pkg_malloc(sizeof(pv_spec_t)); if (gp->v.pvs == NULL) { LM_ERR("no pkg memory left for pv_spec_t\n"); return -1; } if(pv_parse_spec(in, gp->v.pvs)==NULL) { LM_ERR("invalid PV identifier\n"); pkg_free(gp->v.pvs); return -1; } } else { gp->type = GPARAM_TYPE_INT; if(str2sint(in, &gp->v.i) != 0) { LM_ERR("bad number <%.*s>\n", in->len, in->s); return -1; } } return 0; } int pv_parse_dbr_name(pv_spec_p sp, str *in) { sql_pv_t *spv=NULL; char *p; str pvs; str tok; spv = (sql_pv_t*)pkg_malloc(sizeof(sql_pv_t)); if(spv==NULL) return -1; memset(spv, 0, sizeof(sql_pv_t)); p = in->s; while(ps+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')) p++; if(p>in->s+in->len || *p=='\0') goto error; spv->resname.s = p; while(p < in->s + in->len) { if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r') break; p++; } if(p>in->s+in->len || *p=='\0') goto error; spv->resname.len = p - spv->resname.s; spv->res = sql_get_result(&spv->resname); if(*p!='=') { while(ps+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')) p++; if(p>in->s+in->len || *p=='\0' || *p!='=') goto error; } p++; if(*p!='>') goto error; p++; pvs.len = in->len - (int)(p - in->s); pvs.s = p; p = pvs.s+pvs.len-1; while(p>pvs.s && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')) p--; if(p==pvs.s) { LM_ERR("invalid key in [%.*s]\n", in->len, in->s); goto error; } pvs.len = p - pvs.s + 1; LM_DBG("res [%.*s] - key [%.*s]\n", spv->resname.len, spv->resname.s, pvs.len, pvs.s); if(pvs.len==4 && strncmp(pvs.s, "rows", 4)==0) { spv->type = 1; } else if(pvs.len==4 && strncmp(pvs.s, "cols", 4)==0) { spv->type = 2; } else if(pvs.s[0]=='[') { spv->type = 3; p = pvs.s+1; while(ps+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')) p++; if(p>in->s+in->len || *p=='\0') goto error_index; tok.s = p; while(p < in->s + in->len) { if(*p==',' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r') break; p++; } if(p>in->s+in->len || *p=='\0') goto error_index; tok.len = p - tok.s; if(sql_parse_index(&tok, &spv->row)!=0) goto error_index; while(ps+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')) p++; if(p>in->s+in->len || *p=='\0' || *p!=',') goto error_index; p++; while(ps+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')) p++; if(p>in->s+in->len || *p=='\0') goto error_index; tok.s = p; while(p < in->s + in->len) { if(*p==']' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r') break; p++; } if(p>in->s+in->len || *p=='\0') goto error_index; tok.len = p - tok.s; if(sql_parse_index(&tok, &spv->col)!=0) goto error_index; while(ps+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')) p++; if(p>in->s+in->len || *p=='\0' || *p!=']') goto error_index; } else if(pvs.len>9 && strncmp(pvs.s, "colname", 7)==0) { spv->type = 4; p = pvs.s+7; while(ps+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')) p++; if(p>in->s+in->len || *p=='\0' || *p!='[') goto error_index; p++; tok.s = p; while(p < in->s + in->len) { if(*p==']' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r') break; p++; } if(p>in->s+in->len || *p=='\0') goto error_index; tok.len = p - tok.s; if(sql_parse_index(&tok, &spv->col)!=0) goto error_index; while(ps+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')) p++; if(p>in->s+in->len || *p=='\0' || *p!=']') goto error_index; } else { LM_ERR("unknown key [%.*s]\n", pvs.len, pvs.s); if(spv!=NULL) pkg_free(spv); return -1; } sp->pvp.pvn.u.dname = (void*)spv; sp->pvp.pvn.type = PV_NAME_PVAR; return 0; error: LM_ERR("invalid pv name [%.*s]\n", in->len, in->s); if(spv!=NULL) pkg_free(spv); return -1; error_index: LM_ERR("invalid index in [%.*s]\n", pvs.len, pvs.s); if(spv!=NULL) pkg_free(spv); return -1; }