You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/modules/sqlops/sql_var.c

281 lines
6.5 KiB

/**
* 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(p<in->s+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(p<in->s+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(p<in->s+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(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
p++;
if(p>in->s+in->len || *p=='\0' || *p!=',')
goto error_index;
p++;
while(p<in->s+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(p<in->s+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(p<in->s+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(p<in->s+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;
}