perlvdb_conv.c

Go to the documentation of this file.
00001 /* 
00002  * $Id: perlvdb_conv.c 842 2007-02-26 08:46:34Z 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 "perlvdb_conv.h"
00028 #include "perlvdb_oohelpers.h"
00029 
00030 #include "../../dprint.h"
00031 #include "../../mem/mem.h"
00032 
00033 /* Converts a set of pairs to perl SVs.
00034  * For insert, and update (second half)
00035  */
00036 AV *pairs2perlarray(db_key_t* keys, db_val_t* vals, int n) {
00037 
00038    AV *array = newAV();
00039    SV *element;
00040    int i;
00041 
00042    for (i = 0; i < n; i++) {
00043       element = pair2perlpair(*(keys + i), vals + i);
00044       av_push(array, element);
00045    }
00046 
00047    return array;
00048 }
00049 
00050 /* Converts a set of cond's to perl SVs.
00051  * For delete, update (first half), query
00052  */
00053 AV *conds2perlarray(db_key_t* keys, db_op_t* ops, db_val_t* vals, int n) {
00054    AV *array = newAV();
00055    SV *element = NULL;
00056    int i = 0;
00057 
00058    for (i = 0; i < n; i++) {
00059       if (ops) {
00060          if (ops + i)
00061             if (*(ops + i))
00062                element = cond2perlcond(*(keys + i),
00063                      *(ops + i), vals + i);
00064       } else {
00065 /* OP_EQ is defined in OpenSER _and_ perl. Includes collide :( */
00066 #ifdef OP_EQ
00067          element = cond2perlcond(*(keys + i), OP_EQ, vals + i);
00068 #else
00069          element = cond2perlcond(*(keys + i), "=", vals + i);
00070 #endif
00071       }
00072 
00073       av_push(array, element);
00074    }
00075 
00076    return array;
00077 }
00078 
00079 
00080 /* Converts a set of key names to a perl array.
00081  * Needed in query.
00082  */
00083 AV *keys2perlarray(db_key_t* keys, int n) {
00084    AV *array = newAV();
00085    SV *element;
00086    int i;
00087    for (i = 0; i < n; i++) {
00088       element = newSVpv((keys[i])->s, (keys[i])->len); 
00089       av_push(array, element);
00090    }
00091 
00092    return array;
00093 }
00094 
00095 inline SV *valdata(db_val_t* val) {
00096    SV *data = &PL_sv_undef;
00097    const char* stringval;
00098 
00099    switch(VAL_TYPE(val)) {
00100       case DB_INT:
00101          data = newSViv(VAL_INT(val));
00102          break;
00103 
00104       case DB_BIGINT:
00105          LM_ERR("BIGINT not supported");
00106          data = &PL_sv_undef;
00107          break;
00108 
00109       case DB_DOUBLE:
00110          data = newSVnv(VAL_DOUBLE(val));
00111          break;
00112 
00113       case DB_STRING:
00114          stringval = VAL_STRING(val);
00115          if (strlen(stringval) > 0)
00116             data = newSVpv(stringval, strlen(stringval));
00117          else
00118             data = &PL_sv_undef;
00119          break;
00120 
00121       case DB_STR:
00122          if (VAL_STR(val).len > 0)
00123             data = newSVpv(VAL_STR(val).s, VAL_STR(val).len);
00124          else
00125             data = &PL_sv_undef;
00126          break;
00127 
00128       case DB_DATETIME:
00129          data = newSViv((unsigned int)VAL_TIME(val));
00130          break;
00131 
00132       case DB_BLOB:
00133          if (VAL_BLOB(val).len > 0)
00134             data = newSVpv(VAL_BLOB(val).s,
00135                   VAL_BLOB(val).len);
00136          else
00137             data = &PL_sv_undef;
00138          break;
00139 
00140       case DB_BITMAP:
00141          data = newSViv(VAL_BITMAP(val));
00142          break;
00143    }
00144 
00145    return data;
00146 }
00147 
00148 SV *val2perlval(db_val_t* val) {
00149    SV* retval;
00150    SV *class;
00151 
00152    SV *p_data;
00153    SV *p_type;
00154 
00155    class = newSVpv(PERL_CLASS_VALUE, 0);
00156 
00157    p_data = valdata(val);
00158    p_type = newSViv(val->type);
00159    
00160    retval = perlvdb_perlmethod(class, PERL_CONSTRUCTOR_NAME,
00161          p_type, p_data, NULL, NULL);
00162 
00163    return retval;
00164 
00165 }
00166 
00167 SV *pair2perlpair(db_key_t key, db_val_t* val) {
00168    SV* retval;
00169    SV *class;
00170 
00171    SV *p_key;
00172    SV *p_type;
00173    SV *p_data;
00174 
00175    class = newSVpv(PERL_CLASS_PAIR, 0);
00176 
00177    p_key  = newSVpv(key->s, key->len);
00178    p_type = newSViv(val->type);
00179    p_data = valdata(val);
00180    
00181    retval = perlvdb_perlmethod(class, PERL_CONSTRUCTOR_NAME,
00182          p_key, p_type, p_data, NULL);
00183 
00184    SvREFCNT_dec(class);
00185 
00186    return retval;
00187    
00188 }
00189 
00190 SV *cond2perlcond(db_key_t key, db_op_t op, db_val_t* val) {
00191    SV* retval;
00192    SV *class;
00193    
00194    SV *p_key;
00195    SV *p_op;
00196    SV *p_type;
00197    SV *p_data;
00198 
00199    class = newSVpv(PERL_CLASS_REQCOND, 0);
00200 
00201    p_key  = newSVpv(key->s, key->len);
00202    p_op   = newSVpv(op, strlen(op));
00203    p_type = newSViv(val->type);
00204    p_data = valdata(val);
00205    
00206    retval = perlvdb_perlmethod(class, PERL_CONSTRUCTOR_NAME,
00207          p_key, p_op, p_type, p_data);
00208 
00209    return retval;
00210 }
00211 
00212 
00213 
00214 int perlresult2dbres(SV *perlres, db_res_t **r) {
00215 
00216    SV *colarrayref = NULL;
00217    AV *colarray = NULL;
00218    SV *acol = NULL;
00219    int colcount = 0;
00220 
00221 
00222    SV *rowarrayref = NULL;
00223    AV *rowarray = NULL;
00224    int rowcount = 0;
00225 
00226    SV *arowref = NULL;
00227    AV *arow = NULL;
00228    int arowlen = 0;
00229 
00230    SV *aelement = NULL;
00231    SV *atypesv = 0;
00232    int atype = 0;
00233    SV *aval = NULL;
00234 
00235    char *charbuf;
00236    char *currentstring;
00237 
00238    int i, j;
00239    
00240    int retval = 0;
00241    STRLEN len;
00242 
00243    SV *d1; /* helper variables */
00244 
00245    /*db_val_t cur_val;*/ /* Abbreviation in "switch" below. The currently
00246               modified db result value. */
00247 
00248    if (!(SvROK(perlres) &&
00249       (sv_derived_from(perlres, "OpenSER::VDB::Result")))) {
00250       goto error;
00251    }
00252    /* Memory allocation for C side result structure */
00253    *r = (db_res_t *)pkg_malloc(sizeof(db_res_t));
00254    if (!(*r)) {
00255       LM_ERR("no pkg memory left\n");
00256       return -1;
00257    }
00258    memset(*r, 0, sizeof(db_res_t));
00259    
00260    /* Fetch column definitions */
00261    colarrayref = perlvdb_perlmethod(perlres, PERL_VDB_COLDEFSMETHOD,
00262          NULL, NULL, NULL, NULL);
00263    if (!(SvROK(colarrayref))) goto error;
00264    colarray = (AV *)SvRV(colarrayref);
00265    if (!(SvTYPE(colarray) == SVt_PVAV)) goto error;
00266 
00267    colcount = av_len(colarray) + 1;
00268 
00269    /* Allocate col def memory */
00270    (*r)->col.n = colcount;
00271    (*r)->col.types = (db_type_t*)pkg_malloc(colcount*sizeof(db_type_t));
00272    (*r)->col.names = (db_key_t*)pkg_malloc(colcount*sizeof(db_key_t));
00273    
00274     /* reverse direction, as elements are removed by "SvREFCNT_dec" */
00275    for (i = colcount-1; i >= 0; i--) {
00276       acol = *av_fetch(colarray, i, 0);
00277       d1 = perlvdb_perlmethod(acol, PERL_VDB_TYPEMETHOD,
00278             NULL, NULL, NULL, NULL);
00279       if (!SvIOK(d1)) goto error;
00280       (*r)->col.types[i] = SvIV(d1);
00281 
00282       SvREFCNT_dec(d1);
00283       
00284       d1 = perlvdb_perlmethod(acol, PERL_VDB_NAMEMETHOD,
00285             NULL, NULL, NULL, NULL);
00286       if (!SvPOK(d1)) goto error;
00287       currentstring = SvPV(d1, len);
00288       charbuf = pkg_malloc(len+1);
00289       strncpy(charbuf, currentstring, len+1);
00290       (*r)->col.names[i]->s = charbuf;
00291       (*r)->col.names[i]->len = strlen(charbuf);
00292 
00293       SvREFCNT_dec(d1);
00294 
00295    }
00296 
00297    rowarrayref = perlvdb_perlmethod(perlres, PERL_VDB_ROWSMETHOD,
00298          NULL, NULL, NULL, NULL);
00299    if (!(SvROK(rowarrayref))) { /* Empty result set */
00300       (*r)->n = 0;
00301       (*r)->res_rows = 0;
00302       (*r)->last_row = 0;
00303       goto end;
00304    }
00305 
00306    rowarray = (AV *)SvRV(rowarrayref);
00307    if (!(SvTYPE(rowarray) == SVt_PVAV)) goto error;
00308 
00309    rowcount = av_len(rowarray) + 1;
00310 
00311    (*r)->n = rowcount;
00312    (*r)->res_rows = rowcount;
00313    (*r)->last_row = rowcount;
00314    
00315    (*r)->rows = (db_row_t *)pkg_malloc(rowcount*sizeof(db_row_t));
00316 
00317    for (i = 0; i < rowcount; i++) {
00318       arowref = *av_fetch(rowarray, 0, 0);
00319       if (!SvROK(arowref)) goto error;
00320       arow = (AV *)SvRV(arowref);
00321       if (!(SvTYPE(colarray) == SVt_PVAV)) goto error;
00322       arowlen = av_len(arow) + 1;
00323 
00324       (*r)->rows[i].n = arowlen;
00325       (*r)->rows[i].values =
00326          (db_val_t *)pkg_malloc(arowlen*sizeof(db_val_t));
00327 
00328 
00329       for (j = 0; j < arowlen; j++) {
00330          aelement = *av_fetch(arow, j, 0);
00331 #define cur_val (((*r)->rows)[i].values)[j]
00332          /*cur_val = (((*r)->rows)[i].values)[j];*/
00333            /* cur_val is just an "abbreviation" */
00334          if (!(sv_isobject(aelement) && 
00335             sv_derived_from(aelement, PERL_CLASS_VALUE))) {
00336             cur_val.nul = 1;
00337             continue;
00338          }
00339          atype = SvIV(atypesv = perlvdb_perlmethod(aelement,
00340                   PERL_VDB_TYPEMETHOD,
00341                   NULL, NULL, NULL, NULL));
00342          aval = perlvdb_perlmethod(aelement, PERL_VDB_DATAMETHOD,
00343                NULL, NULL, NULL, NULL);
00344 
00345          (*r)->rows[i].values[j].type = atype;
00346          if (!SvOK(aval)) {
00347             cur_val.nul = 1;
00348          } else {
00349             switch (atype) {
00350                case DB_INT:
00351                   cur_val.val.int_val = 
00352                      SvIV(aval);
00353                   cur_val.nul = 0;
00354                   break;
00355                case DB_DOUBLE:
00356                   cur_val.val.double_val = 
00357                      SvNV(aval);
00358                   cur_val.nul = 0;
00359                   break;
00360                case DB_STRING:
00361                case DB_STR:
00362             /* We dont support DB_STR for now.
00363              * Set DB_STRING instead */
00364                   cur_val.type = DB_STRING;
00365                   currentstring = SvPV(aval, len);
00366                   charbuf = pkg_malloc(len+1);
00367                   strncpy(charbuf, currentstring,
00368                         len+1);
00369                   cur_val.val.string_val =
00370                      charbuf;
00371                   cur_val.nul = 0;
00372                   break;
00373                case DB_DATETIME:
00374                   cur_val.val.time_val =
00375                      (time_t)SvIV(aval);
00376                   cur_val.nul = 0;
00377                   break;
00378                case DB_BLOB:
00379                   currentstring = SvPV(aval, len);
00380                   charbuf = pkg_malloc(len+1);
00381                   strncpy(charbuf, currentstring,
00382                         len+1);
00383                   cur_val.val.blob_val.s =
00384                      charbuf;
00385                   cur_val.val.blob_val.len = len;
00386                   cur_val.nul = 0;
00387                   break;
00388                case DB_BITMAP:
00389                   cur_val.val.bitmap_val =
00390                      SvIV(aval);
00391                   cur_val.nul = 0;
00392                   break;
00393                default:
00394                   LM_CRIT("cannot handle this data type.\n");
00395                   return -1;
00396                   break;
00397             }
00398          }
00399          SvREFCNT_dec(atypesv);
00400          SvREFCNT_dec(aval);
00401       }
00402    }
00403 
00404 end:
00405    av_undef(colarray);
00406    av_undef(rowarray);
00407    return retval;
00408 error:
00409    LM_CRIT("broken result set. Exiting, leaving OpenSER in unknown state.\n");
00410    return -1;
00411 }
00412 
00413 
00414 

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