bdb_val.c

00001 /* $Id$
00002  *
00003  * Copyright (C) 2006-2007 Sippy Software, Inc. <sales@sippysoft.com>
00004  *
00005  * This file is part of ser, a free SIP server.
00006  *
00007  * ser is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version
00011  *
00012  * For a license to use the ser software under conditions
00013  * other than those described here, or to purchase support for this
00014  * software, please contact iptel.org by e-mail at the following addresses:
00015  *    info@iptel.org
00016  *
00017  * ser is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  * GNU General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License
00023  * along with this program; if not, write to the Free Software
00024  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025  *
00026  */
00027 
00028 
00029 #include "bdb.h"
00030 
00031 
00032 int bdb_set_row(db_con_t* _h, bdb_urow_p u_r, bdb_val_p _v, bdb_row_p _r)
00033 {
00034         bdb_val_p       v, nv;
00035         bdb_uval_p      uv;
00036         int             c_idx;
00037         int             found;
00038 
00039         /* filling data into row */
00040         for (v = _v, c_idx = 0; v != NULL; v = v->next, c_idx++) {
00041                 nv = pkg_malloc(sizeof(*nv));
00042                 memset(nv, 0, sizeof(*nv));
00043                 bdb_push_field(_r, nv);
00044 
00045                 found = 0;
00046                 for (uv = u_r->fields; uv != NULL; uv = uv->next) {
00047                         if (uv->c_idx == c_idx) {
00048                                 found = 1;
00049                                 break;
00050                         }
00051                 }
00052 
00053                 if (found) {
00054 #ifdef BDB_EXTRA_DEBUG
00055                                 LOG(L_NOTICE, "BDB:bdb_set_row: need to update column #%0d\n", c_idx);
00056 #endif
00057                         if (bdb_field_db2bdb(nv, &(uv->v)) < 0) {
00058                                 return -1;
00059                         }
00060                 } else {
00061 #ifdef BDB_EXTRA_DEBUG
00062                         LOG(L_NOTICE, "BDB:bdb_set_row: no need to update column #%0d\n", c_idx);
00063 #endif
00064                         if (bdb_field_db2bdb(nv, &(v->v)) < 0) {
00065                                 return -1;
00066                         }
00067                 }
00068 
00069                 bdb_push_data(_r, nv);
00070         };
00071 
00072         bdb_merge_tail(_r);
00073 
00074         return 0;
00075 };
00076 
00077 
00078 int bdb_row_db2bdb(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n, bdb_row_p *_r)
00079 {
00080         bdb_row_p       r;
00081         bdb_table_p     t;
00082         bdb_column_p    c;
00083 
00084         int             found;
00085         int             use_key, found_key, key_idx;
00086         int             i;
00087         bdb_val_p       v;
00088 
00089         *_r = NULL;
00090 
00091         if ((t = bdb_find_table(CON_TABLE(_h))) == NULL) {
00092 #ifdef BDB_EXTRA_DEBUG
00093                 LOG(L_ERR, "BDB:bdb_row_db2bdb: table: no table in use\n");
00094 #endif
00095                 return -1;
00096         };
00097 
00098         key_idx = -1;
00099         use_key = -1;
00100 
00101         /* check if all columns exist */
00102         for (i = 0; i < _n; i++) {
00103                 found = 0;
00104                 /* key column is always first one */
00105                 for (c = t->cols, found_key = 1; c != NULL; c = c->next, found_key = 0) {
00106                         if (!strcmp(_k[i], c->name.s)) {
00107                                 found = 1;
00108                                 break;
00109                         }
00110                 }
00111                 if (found_key == 1) {
00112                         key_idx = i;
00113                         use_key++;              /* set to 0 if used in clause only once */
00114                 }
00115                 if (!found) {
00116                         LOG(L_ERR, "BDB:bdb_row_db2bdb: column '%s' does not exist\n", _k[i]);
00117                         return -1;
00118                 }
00119         }
00120 
00121         if (use_key < 0) {
00122 #ifdef BDB_EXTRA_DEBUG
00123                 LOG(L_ERR, "BDB:bdb_row_db2bdb: primary key value must be supplied\n");
00124 #endif
00125                 return -1;
00126         }
00127 
00128         if (use_key > 0) {
00129 #ifdef BDB_EXTRA_DEBUG
00130                 LOG(L_ERR, "BDB:bdb_row_db2bdb: primary key value must be supplied only once\n");
00131 #endif
00132                 return -1;
00133         }
00134 
00135         r = pkg_malloc(sizeof(*r));
00136         memset(r, 0, sizeof(*r));
00137 
00138         /* filling data into row */
00139         for (c = t->cols; c != NULL; c = c->next) {
00140                 v = pkg_malloc(sizeof(*v));
00141                 memset(v, 0, sizeof(*v));
00142                 VAL_NULL(&(v->v)) = 1;                  /* default value is NULL */
00143 
00144                 bdb_push_field(r, v);
00145 
00146                 for (i = 0; i < _n; i++) {
00147                         if (!strcmp(_k[i], c->name.s)) {
00148 #ifdef BDB_EXTRA_DEBUG
00149                                 LOG(L_NOTICE, "BDB:bdb_row_db2bdb: filling column '%.*s'\n", c->name.len, c->name.s);
00150 #endif
00151                                 if (bdb_field_db2bdb(v, &_v[i]) < 0) {
00152                                         bdb_free_row(r);
00153                                         return -1;
00154                                 };
00155 
00156                                 if (i == key_idx) {
00157                                         if (bdb_set_key(r, v) < 0) {
00158                                                 bdb_free_row(r);
00159                                                 return -1;
00160                                         };
00161                                 }
00162 
00163                                 break;
00164                         }
00165                 }
00166 
00167                 bdb_push_data(r, v);
00168         };
00169 
00170         bdb_merge_tail(r);
00171 
00172         *_r = r;
00173 
00174         return 0;
00175 };
00176 
00177 
00178 void bdb_merge_tail(bdb_row_p _r)
00179 {
00180         if (_r->tail.len > 0) {
00181                 _r->data.data = pkg_realloc(_r->data.data, _r->data.size + _r->tail.len);
00182                 memcpy(_r->data.data + _r->data.size, _r->tail.s, _r->tail.len);
00183                 _r->data.size += _r->tail.len;
00184         }
00185 };
00186 
00187 
00188 void bdb_push_data(bdb_row_p _r, bdb_val_p _v)
00189 {
00190         if (_r->data.size == 0) {
00191                 _r->data.data = pkg_malloc(sizeof(*_v));
00192         } else {
00193                 _r->data.data = pkg_realloc(_r->data.data, _r->data.size + sizeof(*_v));
00194         }
00195 
00196         memcpy(_r->data.data + _r->data.size, _v, sizeof(*_v));
00197 
00198         _r->data.size += sizeof(*_v);
00199 
00200         if (!VAL_NULL(&(_v->v))) {
00201                 switch (VAL_TYPE(&(_v->v))) {
00202                 case DB_STRING:
00203                 case DB_STR:
00204                 case DB_BLOB:
00205                         if (_r->tail.len == 0) {
00206                                 _r->tail.s = pkg_malloc(VAL_STR(&(_v->v)).len);
00207                         } else {
00208                                 _r->tail.s = pkg_realloc(_r->tail.s, _r->tail.len + VAL_STR(&(_v->v)).len);
00209                         }
00210                         memcpy(_r->tail.s + _r->tail.len, VAL_STR(&(_v->v)).s, VAL_STR(&(_v->v)).len);
00211                         _r->tail.len += VAL_STR(&(_v->v)).len;
00212                         break;
00213                 default:
00214                         break;
00215                 }
00216         }
00217 };
00218 
00219 
00220 void bdb_push_field(bdb_row_p _r, bdb_val_p _v)
00221 {
00222         bdb_val_p       f;
00223 
00224         if (_r->fields == NULL) {
00225                 _r->fields = _v;
00226                 return;
00227         }
00228         f = _r->fields;
00229         while (f->next != NULL) {
00230                 f = f->next;
00231         }
00232         f->next = _v;
00233 };
00234 
00235 
00236 void bdb_free_field(bdb_val_p _v)
00237 {
00238         if (!VAL_NULL(&(_v->v))) {
00239                 if (VAL_TYPE(&(_v->v)) == DB_STR || VAL_TYPE(&(_v->v)) == DB_STRING ||
00240                     VAL_TYPE(&(_v->v)) == DB_BLOB) {
00241                         pkg_free(VAL_STR(&(_v->v)).s);
00242                 }
00243         }
00244         pkg_free(_v);
00245 };
00246 
00247 
00248 void bdb_free_field_list(bdb_val_p _v)
00249 {
00250         bdb_val_p     curr, next;
00251 
00252         for (curr = _v; curr != NULL;) {
00253                 next = curr->next;
00254                 bdb_free_field(curr);
00255                 curr = next;
00256         }
00257 };
00258 
00259 
00260 void bdb_free_row(bdb_row_p _r)
00261 {
00262         if (_r->fields != NULL) {
00263                 bdb_free_field_list(_r->fields);
00264         }
00265 
00266         if (_r->data.size > 0) {
00267                 pkg_free(_r->data.data);
00268         }
00269 
00270         if (_r->tail.len > 0) {
00271                 pkg_free(_r->tail.s);
00272         }
00273 
00274         pkg_free(_r);
00275 };
00276 
00277 
00278 void bdb_free_row_list(bdb_row_p _r)
00279 {
00280         bdb_row_p     curr, next;
00281 
00282         for (curr = _r; curr != NULL;) {
00283                 next = curr->next;
00284                 bdb_free_row(curr);
00285                 curr = next;
00286         }
00287 };
00288 
00289 
00290 int bdb_field_db2bdb(bdb_val_p v, db_val_t* _v)
00291 {
00292         char    *s;
00293 
00294         VAL_NULL(&(v->v)) = VAL_NULL(_v);
00295         VAL_TYPE(&(v->v)) = VAL_TYPE(_v);
00296 
00297         if (!VAL_NULL(&(v->v))) {
00298                 switch (VAL_TYPE(_v)) {
00299                 case DB_INT:
00300                         VAL_INT(&(v->v)) = VAL_INT(_v);
00301                         break;
00302                 case DB_FLOAT:
00303                         VAL_FLOAT(&(v->v)) = VAL_FLOAT(_v);
00304                         break;
00305                 case DB_DATETIME:
00306                         VAL_TIME(&(v->v)) = VAL_TIME(_v);
00307                         break;
00308                 case DB_BLOB:
00309                         s = pkg_malloc(VAL_BLOB(_v).len);
00310                         memcpy(s, VAL_BLOB(_v).s, VAL_BLOB(_v).len);
00311                         VAL_BLOB(&(v->v)).s = s;
00312                         VAL_BLOB(&(v->v)).len = VAL_BLOB(_v).len;
00313                         break;
00314                 case DB_DOUBLE:
00315                         VAL_DOUBLE(&(v->v)) = VAL_DOUBLE(_v);
00316                         break;
00317                 case DB_STRING:
00318                         VAL_STR(&(v->v)).len = strlen(VAL_STRING(_v)) + 1;
00319                         s = pkg_malloc(VAL_STR(&(v->v)).len);
00320                         strcpy(s, VAL_STRING(_v));
00321                         VAL_STRING(&(v->v)) = s;
00322                         break;
00323                 case DB_STR:
00324                         s = pkg_malloc(VAL_STR(_v).len);
00325                         memcpy(s, VAL_STR(_v).s, VAL_STR(_v).len);
00326                         VAL_STR(&(v->v)).s = s;
00327                         VAL_STR(&(v->v)).len = VAL_STR(_v).len;
00328                         break;
00329                 case DB_BITMAP:
00330                         VAL_BITMAP(&(v->v)) = VAL_BITMAP(_v);
00331                         break;
00332                 default:
00333                         LOG(L_ERR, "BDB:bdb_field_db2bdb: unknown column type: %0X\n", VAL_TYPE(_v));
00334                         return -1;
00335                         break;
00336                 }
00337         }
00338         return 0;
00339 };
00340 
00341 
00342 int bdb_get_db_row(db_con_t* _h, DBT* _data, bdb_val_p* _v)
00343 {
00344         bdb_val_p v, prev;
00345         void *p, *tail;
00346         int l;
00347 
00348         if (!_data || !_data->size) {
00349                 LOG(L_ERR, "BDB:bdb_get_db_row: invalid data\n");
00350                 *_v = NULL;
00351                 return -1;
00352         }
00353 
00354         *_v = (bdb_val_p)_data->data;
00355         prev = NULL;
00356         p = _data->data;
00357         l = 0;
00358         tail = p + sizeof(*v) * BDB_CON_COL_NUM(_h);
00359 
00360         while (l < sizeof(*v) * BDB_CON_COL_NUM(_h)) {
00361                 v = (bdb_val_p)p;
00362                 p += sizeof(*v);
00363                 l += sizeof(*v);
00364                 v->next = NULL;
00365                 if (prev) {
00366                         prev->next = v;
00367                         prev = v;
00368                 } else {
00369                         prev = v;
00370                 }
00371                 if (!VAL_NULL(&(v->v))) {
00372                         switch (VAL_TYPE(&(v->v))) {
00373                         case DB_BLOB:
00374                         case DB_STRING:
00375                         case DB_STR:
00376                                 VAL_STR(&(v->v)).s = tail;
00377                                 tail += VAL_STR(&(v->v)).len;
00378                                 break;
00379                         default:
00380                                 break;
00381                         }
00382                 }
00383         }
00384 
00385         return 0;
00386 };
00387 
00388 int bdb_set_key(bdb_row_p _r, bdb_val_p _v)
00389 {
00390         /* NULL is not allowed for primary key */
00391         if (VAL_NULL(&(_v->v))) {
00392                 LOG(L_ERR, "BDB:bdb_set_key: NULL is not allowed for primary key\n");
00393                 return -1;
00394         }
00395 
00396         switch (VAL_TYPE(&(_v->v))) {
00397         case DB_INT:
00398                 _r->key.data = &VAL_INT(&(_v->v));
00399                 _r->key.size = sizeof(VAL_INT(&(_v->v)));
00400                 break;
00401         case DB_FLOAT:
00402                 _r->key.data = &VAL_FLOAT(&(_v->v));
00403                 _r->key.size = sizeof(VAL_FLOAT(&(_v->v)));
00404                 break;
00405         case DB_DATETIME:
00406                 _r->key.data = &VAL_TIME(&(_v->v));
00407                 _r->key.size = sizeof(VAL_TIME(&(_v->v)));
00408                 break;
00409         case DB_BLOB:
00410                 _r->key.data = VAL_BLOB(&(_v->v)).s;
00411                 _r->key.size = VAL_BLOB(&(_v->v)).len;
00412                 break;
00413         case DB_DOUBLE:
00414                 _r->key.data = &VAL_DOUBLE(&(_v->v));
00415                 _r->key.size = sizeof(VAL_DOUBLE(&(_v->v)));
00416                 break;
00417         case DB_STRING:
00418                 _r->key.data = (void *)VAL_STRING(&(_v->v));
00419                 _r->key.size = strlen(VAL_STRING(&(_v->v))) + 1;
00420                 break;
00421         case DB_STR:
00422                 _r->key.data = VAL_STR(&(_v->v)).s;
00423                 _r->key.size = VAL_STR(&(_v->v)).len;
00424                 break;
00425         case DB_BITMAP:
00426                 _r->key.data = &VAL_BITMAP(&(_v->v));
00427                 _r->key.size = sizeof(VAL_BITMAP(&(_v->v)));
00428                 break;
00429         default:
00430                 LOG(L_ERR, "BDB:bdb_set_skey: unknown column type: %0X\n", VAL_TYPE(&(_v->v)));
00431                 return -1;
00432                 break;
00433         }
00434 
00435         return 0;
00436 };