perlvdbfunc.c

Go to the documentation of this file.
00001 /* 
00002  * $Id: perlvdbfunc.c 816 2007-02-13 18:33:22Z bastian $
00003  *
00004  * Perl virtual database module interface
00005  *
00006  * Copyright (C) 2007 Collax GmbH
00007  *                    (Bastian Friedrich <bastian.friedrich@collax.com>)
00008  *
00009  * This file is part of Kamailio, a free SIP server.
00010  *
00011  * Kamailio is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version
00015  *
00016  * Kamailio is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License 
00022  * along with this program; if not, write to the Free Software 
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  *
00025  */
00026 
00027 #include <string.h>
00028 #include <ctype.h>
00029 #include <stdio.h>
00030 
00031 #include "perlvdb.h"
00032 #include "perlvdbfunc.h"
00033 #include "../../str.h"
00034 
00035 /*
00036  * Simple conversion IV -> int
00037  * including decreasing ref cnt
00038  */
00039 
00040 inline long IV2int(SV *in) {
00041    int ret = -1;
00042 
00043    if (SvOK(in)) {
00044       if (SvIOK(in)) {
00045          ret = SvIV(in);
00046       }
00047       SvREFCNT_dec(in);
00048    }
00049 
00050    return ret;
00051 }
00052 
00053 /*
00054  * Returns the class part of the URI
00055  */
00056 char *parseurl(const char* url) {
00057    char *cn;
00058 
00059    cn = strchr(url, ':') + 1;
00060    if (strlen(cn) > 0)
00061       return cn;
00062    else
00063       return NULL;
00064 }
00065 
00066 
00067 SV *newvdbobj(const char* cn) {
00068    SV* obj;
00069    SV *class;
00070 
00071    class = newSVpv(cn, 0);
00072 
00073    obj = perlvdb_perlmethod(class, PERL_CONSTRUCTOR_NAME,
00074          NULL, NULL, NULL, NULL);
00075 
00076    return obj;
00077 }
00078 
00079 SV *getobj(db_con_t *con) {
00080    return ((SV*)CON_TAIL(con));
00081 }
00082 
00083 /*
00084  * Checks whether the passed SV is a valid VDB object:
00085  * - not null
00086  * - not undef
00087  * - an object
00088  * - derived from OpenSER::VDB
00089  */
00090 int checkobj(SV* obj) {
00091    if (obj != NULL) {
00092       if (obj != &PL_sv_undef) {
00093          if (sv_isobject(obj)) {
00094             if (sv_derived_from(obj, PERL_VDB_BASECLASS)) {
00095                return 1;
00096             }
00097          }
00098       }
00099    }
00100 
00101    return 0;
00102 }
00103 
00104 /*
00105  * Initialize database module
00106  * No function should be called before this
00107  */
00108 db_con_t* perlvdb_db_init(const char* url) {
00109    db_con_t* res;
00110 
00111    char *cn;
00112    SV *obj = NULL;
00113    
00114    int consize = sizeof(db_con_t) + sizeof(SV);
00115    
00116    if (!url) {
00117       LM_ERR("invalid parameter value\n");
00118       return NULL;
00119    }
00120 
00121    cn = parseurl(url);
00122    if (!cn) {
00123       LM_ERR("invalid perl vdb url.\n");
00124       return NULL;
00125    }
00126 
00127    obj = newvdbobj(cn);
00128    if (!checkobj(obj)) {
00129       LM_ERR("could not initialize module. Not inheriting from %s?\n",
00130             PERL_VDB_BASECLASS);
00131       return NULL;
00132    }
00133 
00134    res = pkg_malloc(consize);
00135    if (!res) {
00136       LM_ERR("no pkg memory left\n");
00137       return NULL;
00138    }
00139    memset(res, 0, consize);
00140    CON_TAIL(res) = (unsigned int)(unsigned long)obj;
00141 
00142    return res;
00143 }
00144 
00145 
00146 /*
00147  * Store name of table that will be used by
00148  * subsequent database functions
00149  */
00150 int perlvdb_use_table(db_con_t* h, const str* t) {
00151    SV *ret;
00152    
00153    if (!h || !t || !t->s) {
00154       LM_ERR("invalid parameter value\n");
00155       return -1;
00156    }
00157 
00158    ret = perlvdb_perlmethod(getobj(h), PERL_VDB_USETABLEMETHOD,
00159          sv_2mortal(newSVpv(t->s, t->len)), NULL, NULL, NULL);
00160 
00161    return IV2int(ret);
00162 }
00163 
00164 
00165 void perlvdb_db_close(db_con_t* h) {
00166    if (!h) {
00167       LM_ERR("invalid parameter value\n");
00168       return;
00169    }
00170 
00171    pkg_free(h);
00172 }
00173 
00174 
00175 /*
00176  * Insert a row into specified table
00177  * h: structure representing database connection
00178  * k: key names
00179  * v: values of the keys
00180  * n: number of key=value pairs
00181  */
00182 int perlvdb_db_insertreplace(db_con_t* h, db_key_t* k, db_val_t* v,
00183       int n, char *insertreplace) {
00184    AV *arr;
00185    SV *arrref;
00186    SV *ret;
00187 
00188    arr = pairs2perlarray(k, v, n);
00189    arrref = newRV_noinc((SV*)arr);
00190    ret = perlvdb_perlmethod(getobj(h), insertreplace,
00191          arrref, NULL, NULL, NULL);
00192 
00193    av_undef(arr);
00194 
00195    return IV2int(ret);
00196 }
00197 
00198 int perlvdb_db_insert(db_con_t* h, db_key_t* k, db_val_t* v, int n) {
00199    return perlvdb_db_insertreplace(h, k, v, n, PERL_VDB_INSERTMETHOD);
00200 }
00201 
00202 /*
00203  * Just like insert, but replace the row if it exists
00204  */
00205 int perlvdb_db_replace(db_con_t* h, db_key_t* k, db_val_t* v, int n) {
00206    return perlvdb_db_insertreplace(h, k, v, n, PERL_VDB_REPLACEMETHOD);
00207 }
00208 
00209 /*
00210  * Delete a row from the specified table
00211  * h: structure representing database connection
00212  * k: key names
00213  * o: operators
00214  * v: values of the keys that must match
00215  * n: number of key=value pairs
00216  */
00217 int perlvdb_db_delete(db_con_t* h, db_key_t* k, db_op_t* o, db_val_t* v,
00218       int n) {
00219    AV *arr;
00220    SV *arrref;
00221    SV *ret;
00222 
00223    arr = conds2perlarray(k, o, v, n);
00224    arrref = newRV_noinc((SV*)arr);
00225    ret = perlvdb_perlmethod(getobj(h), PERL_VDB_DELETEMETHOD,
00226          arrref, NULL, NULL, NULL);
00227 
00228    av_undef(arr);
00229 
00230    return IV2int(ret);
00231 }
00232 
00233 
00234 /*
00235  * Update some rows in the specified table
00236  * _h: structure representing database connection
00237  * _k: key names
00238  * _o: operators
00239  * _v: values of the keys that must match
00240  * _uk: updated columns
00241  * _uv: updated values of the columns
00242  * _n: number of key=value pairs
00243  * _un: number of columns to update
00244  */
00245 int perlvdb_db_update(db_con_t* h, db_key_t* k, db_op_t* o, db_val_t* v,
00246          db_key_t* uk, db_val_t* uv, int n, int un) {
00247 
00248    AV *condarr;
00249    AV *updatearr;
00250 
00251    SV *condarrref;
00252    SV *updatearrref;
00253 
00254    SV *ret;
00255 
00256    condarr = conds2perlarray(k, o, v, n);
00257    updatearr = pairs2perlarray(uk, uv, un);
00258 
00259    condarrref = newRV_noinc((SV*)condarr);
00260    updatearrref = newRV_noinc((SV*)updatearr);
00261    
00262    ret = perlvdb_perlmethod(getobj(h), PERL_VDB_UPDATEMETHOD,
00263          condarrref, updatearrref, NULL, NULL);
00264 
00265    av_undef(condarr);
00266    av_undef(updatearr);
00267 
00268    return IV2int(ret);
00269 }
00270 
00271 
00272 /*
00273  * Query table for specified rows
00274  * h: structure representing database connection
00275  * k: key names
00276  * op: operators
00277  * v: values of the keys that must match
00278  * c: column names to return
00279  * n: number of key=values pairs to compare
00280  * nc: number of columns to return
00281  * o: order by the specified column
00282  */
00283 int perlvdb_db_query(db_con_t* h, db_key_t* k, db_op_t* op, db_val_t* v,
00284          db_key_t* c, int n, int nc,
00285          db_key_t o, db_res_t** r) {
00286 
00287 
00288    AV *condarr;
00289    AV *retkeysarr;
00290    SV *order;
00291 
00292    SV *condarrref;
00293    SV *retkeysref;
00294 
00295    SV *resultset;
00296 
00297    int retval = 0;
00298 
00299    /* Create parameter set */
00300    condarr = conds2perlarray(k, op, v, n);
00301    retkeysarr = keys2perlarray(c, nc);
00302 
00303    if (o) order = newSVpv(o->s, o->len);
00304    else order = &PL_sv_undef;
00305 
00306 
00307    condarrref = newRV_noinc((SV*)condarr);
00308    retkeysref = newRV_noinc((SV*)retkeysarr);
00309 
00310    /* Call perl method */
00311    resultset = perlvdb_perlmethod(getobj(h), PERL_VDB_QUERYMETHOD,
00312          condarrref, retkeysref, order, NULL);
00313 
00314    av_undef(condarr);
00315    av_undef(retkeysarr);
00316 
00317    /* Transform perl result set to OpenSER result set */
00318    if (!resultset) {
00319       /* No results. */
00320       LM_ERR("no perl result set.\n");
00321       retval = -1;
00322    } else {
00323       if (sv_isa(resultset, "OpenSER::VDB::Result")) {
00324          retval = perlresult2dbres(resultset, r);
00325       /* Nested refs are decreased/deleted inside the routine */
00326          SvREFCNT_dec(resultset);
00327       } else {
00328          LM_ERR("invalid result set retrieved from perl call.\n");
00329          retval = -1;
00330       }
00331    }
00332 
00333    return retval;
00334 }
00335 
00336 
00337 /*
00338  * Release a result set from memory
00339  */
00340 int perlvdb_db_free_result(db_con_t* _h, db_res_t* _r) {
00341    int i;
00342 
00343    if (_r) {
00344       for (i = 0; i < _r->n; i++) {
00345          if (_r->rows[i].values)
00346             pkg_free(_r->rows[i].values);
00347       }
00348 
00349       if (_r->col.types)
00350          pkg_free(_r->col.types);
00351       if (_r->col.names)
00352          pkg_free(_r->col.names);
00353       if (_r->rows)
00354          pkg_free(_r->rows);
00355       pkg_free(_r);
00356    }
00357    return 0;
00358 }

Generated on Thu May 24 02:00:29 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6