00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00035 #include <string.h>
00036
00037 #include "../../mem/mem.h"
00038 #include "../../dprint.h"
00039 #include "../../ut.h"
00040
00041 #include "bdb_cmd.h"
00042 #include "bdb_fld.h"
00043 #include "bdb_con.h"
00044 #include "bdb_uri.h"
00045 #include "bdb_res.h"
00046 #include "bdb_lib.h"
00047 #include "bdb_crs_compat.h"
00048
00049 #define BDB_BUF_SIZE 1024
00050
00056 static void bdb_cmd_free(db_cmd_t* cmd, bdb_cmd_t* payload)
00057 {
00058 db_drv_free(&payload->gen);
00059 if (payload->dbcp)
00060 payload->dbcp->CLOSE_CURSOR(payload->dbcp);
00061 if(payload->skey.s)
00062 pkg_free(payload->skey.s);
00063 pkg_free(payload);
00064 }
00065
00066 int bdb_prepare_query(db_cmd_t* cmd, bdb_cmd_t *bcmd)
00067 {
00068 bdb_tcache_t *tbc = NULL;
00069 bdb_table_t *tp = NULL;
00070 bdb_fld_t *f;
00071 db_fld_t *fld;
00072 int mode;
00073 int i;
00074
00075 if(bcmd->bcon==NULL || bcmd->bcon->dbp==NULL)
00076 return -1;
00077
00078 tbc = bdblib_get_table(bcmd->bcon->dbp, &cmd->table);
00079 if(tbc==NULL)
00080 {
00081 ERR("bdb: table does not exist!\n");
00082 return -1;
00083 }
00084
00085 tp = tbc->dtp;
00086 if(tp==NULL || tp->db==NULL)
00087 {
00088 ERR("bdb: table not loaded!\n");
00089 return -1;
00090 }
00091
00092 mode = 0;
00093 if (!DB_FLD_EMPTY(cmd->result))
00094 {
00095 if (cmd->result_count > tp->ncols)
00096 {
00097 ERR("bdb: too many columns in query\n");
00098 goto error;
00099 }
00100 } else {
00101 mode = 1;
00102 cmd->result = db_fld(tp->ncols + 1);
00103 cmd->result_count = tp->ncols;
00104 for(i = 0; i < cmd->result_count; i++) {
00105 if (bdb_fld(cmd->result + i, cmd->table.s) < 0)
00106 goto error;
00107 }
00108 }
00109
00110 for (i = 0; i < cmd->result_count; i++) {
00111 fld = cmd->result + i;
00112 f = DB_GET_PAYLOAD(fld);
00113 if(mode==1)
00114 {
00115 DBG("bdb: column name [%.*s]\n", tp->colp[i]->name.len,
00116 tp->colp[i]->name.s);
00117
00118 f->name = pkg_malloc(tp->colp[i]->name.len+1);
00119 if (f->name == NULL) {
00120 ERR("bdb: Out of private memory\n");
00121 goto error;
00122 }
00123 strncpy(f->name, tp->colp[i]->name.s, tp->colp[i]->name.len);
00124 f->name[tp->colp[i]->name.len] = '\0';
00125 fld->name = f->name;
00126 fld->type = tp->colp[i]->type;
00127 f->col_pos = i;
00128 } else {
00129 f->col_pos = bdb_get_colpos(tp, fld->name);
00130 if(f->col_pos == -1)
00131 {
00132 ERR("bdb: Column not found\n");
00133 goto error;
00134 }
00135 }
00136 switch(fld->type) {
00137 case DB_INT:
00138 case DB_BITMAP:
00139 case DB_FLOAT:
00140 case DB_DOUBLE:
00141 case DB_DATETIME:
00142 case DB_STR:
00143 if (!f->buf.s) f->buf.s = pkg_malloc(BDB_BUF_SIZE);
00144 if (f->buf.s == NULL) {
00145 ERR("bdb: No memory left\n");
00146 goto error;
00147 }
00148 fld[i].v.lstr.s = f->buf.s;
00149 break;
00150
00151 case DB_CSTR:
00152 if (!f->buf.s) f->buf.s = pkg_malloc(BDB_BUF_SIZE);
00153 if (f->buf.s == NULL) {
00154 ERR("bdb: No memory left\n");
00155 goto error;
00156 }
00157 fld[i].v.cstr = f->buf.s;
00158 break;
00159
00160 case DB_BLOB:
00161 if (!f->buf.s) f->buf.s = pkg_malloc(BDB_BUF_SIZE);
00162 if (f->buf.s == NULL) {
00163 ERR("mysql: No memory left\n");
00164 goto error;
00165 }
00166 fld[i].v.blob.s = f->buf.s;
00167 break;
00168
00169 case DB_NONE:
00170
00171 break;
00172 }
00173 }
00174
00175 if (!DB_FLD_EMPTY(cmd->match))
00176 {
00177 if (cmd->match_count > tp->ncols)
00178 {
00179 ERR("bdb: too many columns in match struct of query\n");
00180 goto error;
00181 }
00182 for (i = 0; i < cmd->match_count; i++) {
00183 fld = cmd->result + i;
00184 f = DB_GET_PAYLOAD(fld);
00185 f->col_pos = bdb_get_colpos(tp, fld->name);
00186 if(f->col_pos == -1)
00187 {
00188 ERR("bdb: Match column not found\n");
00189 goto error;
00190 }
00191 }
00192 }
00193
00194 return 0;
00195
00196 error:
00197 return -1;
00198 }
00199
00200 int bdb_query(db_cmd_t* cmd, bdb_cmd_t *bcmd)
00201 {
00202 DBT key;
00203 DB *db;
00204 static char kbuf[MAX_ROW_SIZE];
00205 int klen;
00206
00207 bdb_tcache_t *tbc = NULL;
00208 bdb_table_t *tp = NULL;
00209
00210 if(bcmd->bcon==NULL || bcmd->bcon->dbp==NULL)
00211 return -1;
00212
00213 tbc = bdblib_get_table(bcmd->bcon->dbp, &cmd->table);
00214 if(tbc==NULL)
00215 {
00216 ERR("bdb: table does not exist!\n");
00217 return -1;
00218 }
00219
00220 tp = tbc->dtp;
00221 if(tp==NULL)
00222 {
00223 ERR("bdb: table not loaded!\n");
00224 return -1;
00225 }
00226 db = tp->db;
00227 if(db==NULL)
00228 {
00229 ERR("bdb: db structure not intialized!\n");
00230 return -1;
00231 }
00232
00233 if (DB_FLD_EMPTY(cmd->match))
00234 {
00235 if (db->cursor(db, NULL, &bcmd->dbcp, 0) != 0)
00236 {
00237 ERR("bdb: error creating cursor\n");
00238 goto error;
00239 }
00240 bcmd->skey.len = 0;
00241 return 0;
00242 }
00243
00244 memset(&key, 0, sizeof(DBT));
00245 memset(kbuf, 0, MAX_ROW_SIZE);
00246
00247 klen=MAX_ROW_SIZE;
00248 if(bdblib_valtochar(tp, cmd->match, cmd->match_count,
00249 kbuf, &klen, BDB_KEY)!=0)
00250 {
00251 ERR("bdb: error creating key\n");
00252 goto error;
00253 }
00254
00255 if(klen > bcmd->skey_size || bcmd->skey.s==NULL)
00256 {
00257 if(bcmd->skey.s!=NULL)
00258 pkg_free(bcmd->skey.s);
00259 bcmd->skey.s = (char*)pkg_malloc(klen*sizeof(char));
00260 if(bcmd->skey.s == NULL)
00261 {
00262 ERR("bdb: no pkg memory\n");
00263 goto error;
00264 }
00265 bcmd->skey_size = klen;
00266 }
00267 memcpy(bcmd->skey.s, kbuf, klen);
00268 bcmd->skey.len = klen;
00269
00270 return 0;
00271 error:
00272 return -1;
00273 }
00274
00275 int bdb_cmd(db_cmd_t* cmd)
00276 {
00277 bdb_cmd_t *bcmd;
00278 db_con_t *con;
00279 bdb_con_t *bcon;
00280
00281 bcmd = (bdb_cmd_t*)pkg_malloc(sizeof(bdb_cmd_t));
00282 if (bcmd == NULL) {
00283 ERR("bdb: No memory left\n");
00284 goto error;
00285 }
00286 memset(bcmd, '\0', sizeof(bdb_cmd_t));
00287 if (db_drv_init(&bcmd->gen, bdb_cmd_free) < 0) goto error;
00288
00289 con = cmd->ctx->con[db_payload_idx];
00290 bcon = DB_GET_PAYLOAD(con);
00291 bcmd->bcon = bcon;
00292
00293 switch(cmd->type) {
00294 case DB_PUT:
00295 case DB_DEL:
00296 case DB_UPD:
00297 ERR("bdb: The driver does not support DB modifications yet.\n");
00298 goto error;
00299 break;
00300
00301 case DB_GET:
00302 if(bdb_prepare_query(cmd, bcmd)!=0)
00303 {
00304 ERR("bdb: error preparing query.\n");
00305 goto error;
00306 }
00307 break;
00308
00309 case DB_SQL:
00310 ERR("bdb: The driver does not support raw queries yet.\n");
00311 goto error;
00312 }
00313
00314 DB_SET_PAYLOAD(cmd, bcmd);
00315 return 0;
00316
00317 error:
00318 if (bcmd) {
00319 DB_SET_PAYLOAD(cmd, NULL);
00320 db_drv_free(&bcmd->gen);
00321 pkg_free(bcmd);
00322 }
00323 return -1;
00324 }
00325
00326
00327 int bdb_cmd_exec(db_res_t* res, db_cmd_t* cmd)
00328 {
00329 db_con_t* con;
00330 bdb_cmd_t *bcmd;
00331 bdb_con_t *bcon;
00332
00333
00334
00335
00336 con = cmd->ctx->con[db_payload_idx];
00337 bcmd = DB_GET_PAYLOAD(cmd);
00338 bcon = DB_GET_PAYLOAD(con);
00339
00340 if ((bcon->flags & BDB_CONNECTED)==0) {
00341 ERR("bdb: not connected\n");
00342 return -1;
00343 }
00344 bcmd->next_flag = -1;
00345 switch(cmd->type) {
00346 case DB_DEL:
00347 case DB_PUT:
00348 case DB_UPD:
00349
00350 DBG("bdb: query with no result.\n");
00351 break;
00352 case DB_GET:
00353 return bdb_query(cmd, bcmd);
00354 break;
00355 default:
00356
00357 DBG("bdb: query with result.\n");
00358 }
00359
00360 return 0;
00361 }
00362
00363 int bdb_update_result(db_cmd_t *cmd, DBT *data)
00364 {
00365 bdb_fld_t *f;
00366 db_fld_t *fld;
00367 int i;
00368 int col;
00369 char *s;
00370 static str col_map[MAX_NUM_COLS];
00371
00372 memset(col_map, 0, MAX_NUM_COLS*sizeof(str));
00373
00374 col = 0;
00375 s = (char*)data->data;
00376 col_map[col].s = s;
00377 while(*s!='\0')
00378 {
00379 if(*s == *DELIM)
00380 {
00381 col_map[col].len = s - col_map[col].s;
00382 col++;
00383 col_map[col].s = s+1;
00384 }
00385 s++;
00386 }
00387 col_map[col].len = s - col_map[col].s;
00388
00389 for (i = 0; i < cmd->result_count; i++) {
00390 fld = cmd->result + i;
00391 f = DB_GET_PAYLOAD(fld);
00392 if(col_map[f->col_pos].len == 0)
00393 {
00394 fld->flags |= DB_NULL;
00395 continue;
00396 }
00397 fld->flags &= ~DB_NULL;
00398
00399 switch(fld->type) {
00400 case DB_STR:
00401 fld->v.lstr.s = f->buf.s;
00402 if(col_map[f->col_pos].len < BDB_BUF_SIZE)
00403 {
00404 fld->v.lstr.len = col_map[f->col_pos].len;
00405 } else {
00406
00407 fld->v.lstr.len = BDB_BUF_SIZE - 1;
00408 }
00409 memcpy(fld->v.lstr.s, col_map[f->col_pos].s, fld->v.lstr.len);
00410 break;
00411
00412 case DB_BLOB:
00413 fld->v.blob.s = f->buf.s;
00414 if(col_map[f->col_pos].len < BDB_BUF_SIZE)
00415 {
00416 fld->v.blob.len = col_map[f->col_pos].len;
00417 } else {
00418
00419 fld->v.blob.len = BDB_BUF_SIZE - 1;
00420 }
00421 memcpy(fld->v.blob.s, col_map[f->col_pos].s, fld->v.blob.len);
00422
00423 break;
00424
00425 case DB_CSTR:
00426 fld->v.cstr = f->buf.s;
00427 if(col_map[f->col_pos].len < BDB_BUF_SIZE)
00428 {
00429 memcpy(fld->v.cstr, col_map[f->col_pos].s,
00430 col_map[f->col_pos].len);
00431 fld->v.cstr[col_map[f->col_pos].len] = '\0';
00432 } else {
00433
00434 memcpy(fld->v.cstr, col_map[f->col_pos].s,
00435 BDB_BUF_SIZE - 1);
00436 fld->v.cstr[BDB_BUF_SIZE - 1] = '\0';;
00437 }
00438
00439 break;
00440
00441 case DB_DATETIME:
00442
00443 col_map[f->col_pos].s[col_map[f->col_pos].len]='\0';
00444 if (bdb_str2time(col_map[f->col_pos].s, &fld->v.time) < 0)
00445 {
00446 ERR("Error while converting INT value from string\n");
00447 return -1;
00448 }
00449 break;
00450
00451 case DB_INT:
00452
00453 col_map[f->col_pos].s[col_map[f->col_pos].len]='\0';
00454 if (bdb_str2int(col_map[f->col_pos].s, &fld->v.int4) < 0)
00455 {
00456 ERR("Error while converting INT value from string\n");
00457 return -1;
00458 }
00459 break;
00460
00461 case DB_FLOAT:
00462 case DB_DOUBLE:
00463
00464 col_map[f->col_pos].s[col_map[f->col_pos].len]='\0';
00465 if (bdb_str2double(col_map[f->col_pos].s, &fld->v.dbl) < 0)
00466 {
00467 ERR("Error while converting DOUBLE value from string\n");
00468 return -1;
00469 }
00470 break;
00471
00472 case DB_BITMAP:
00473
00474 col_map[f->col_pos].s[col_map[f->col_pos].len]='\0';
00475 if (bdb_str2int(col_map[f->col_pos].s, &fld->v.int4) < 0)
00476 {
00477 ERR("Error while converting BITMAP value from string\n");
00478 return -1;
00479 }
00480 break;
00481
00482 case DB_NONE:
00483 break;
00484 }
00485 }
00486 return 0;
00487
00488 }
00489
00490 int bdb_cmd_first(db_res_t* res)
00491 {
00492 bdb_cmd_t *bcmd;
00493
00494 bcmd = DB_GET_PAYLOAD(res->cmd);
00495 switch (bcmd->next_flag) {
00496 case -2:
00497 return 1;
00498 case 0:
00499 return 0;
00500 case 1:
00501 case 2:
00502 ERR("bdb: no next row.\n");
00503 return -1;
00504 default:
00505 return bdb_cmd_next(res);
00506 }
00507 }
00508
00509
00510 int bdb_cmd_next(db_res_t* res)
00511 {
00512 db_con_t *con;
00513 bdb_res_t *bres;
00514 bdb_con_t *bcon;
00515 bdb_cmd_t *bcmd;
00516 DBT key, data;
00517 int ret;
00518 static char dbuf[MAX_ROW_SIZE];
00519
00520 con = res->cmd->ctx->con[db_payload_idx];
00521 bres = DB_GET_PAYLOAD(res);
00522 bcon = DB_GET_PAYLOAD(con);
00523 bcmd = DB_GET_PAYLOAD(res->cmd);
00524
00525 if (bcmd->next_flag == 2 || bcmd->next_flag == -2) return 1;
00526
00527 memset(&key, 0, sizeof(DBT));
00528 memset(&data, 0, sizeof(DBT));
00529 memset(dbuf, 0, MAX_ROW_SIZE);
00530
00531 data.data = dbuf;
00532 data.ulen = MAX_ROW_SIZE;
00533 data.flags = DB_DBT_USERMEM;
00534
00535 ret = 0;
00536 if(bcmd->skey.len==0)
00537 {
00538 while((ret = bcmd->dbcp->c_get(bcmd->dbcp, &key, &data, DB_NEXT))==0)
00539 {
00540 if(!strncasecmp((char*)key.data,"METADATA",8))
00541 continue;
00542 break;
00543 }
00544 if(ret!=0)
00545 {
00546 bcmd->next_flag = bcmd->next_flag<0?-2:2;
00547 return 1;
00548 }
00549 } else {
00550 key.data = bcmd->skey.s;
00551 key.ulen = bcmd->skey_size;
00552 key.flags = DB_DBT_USERMEM;
00553 key.size = bcmd->skey.len;
00554 ret = bcmd->dbcp->c_get(bcmd->dbcp, &key, &data, DB_NEXT);
00555 if(ret!=0)
00556 {
00557 bcmd->next_flag = bcmd->next_flag<0?-2:2;
00558 return 1;
00559 }
00560 }
00561
00562 if (bcmd->next_flag <= 0) {
00563 bcmd->next_flag++;
00564 }
00565
00566 if (bdb_update_result(res->cmd, &data) < 0) {
00567 return -1;
00568 }
00569
00570 res->cur_rec->fld = res->cmd->result;
00571 return 0;
00572 }
00573
00574