00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <stdio.h>
00035 #include <string.h>
00036 #include <sys/types.h>
00037 #include <stdlib.h>
00038 #include <setjmp.h>
00039
00040 #include "../../mem/mem.h"
00041
00042 #include "dbt_res.h"
00043
00044 #define SIGN(_i) ((_i) > 0 ? 1 : ((_i) < 0 ? -1 : 0))
00045
00046 dbt_result_p dbt_result_new(dbt_table_p _dtp, int *_lres, int _sz)
00047 {
00048 dbt_result_p _dres = NULL;
00049 int i, n;
00050 char *p;
00051
00052 if(!_dtp || _sz < 0)
00053 return NULL;
00054
00055 if(!_lres)
00056 _sz = _dtp->nrcols;
00057
00058 _dres = (dbt_result_p)pkg_malloc(sizeof(dbt_result_t));
00059 if(!_dres)
00060 return NULL;
00061 _dres->colv = (dbt_column_p)pkg_malloc(_sz*sizeof(dbt_column_t));
00062 if(!_dres->colv)
00063 {
00064 LM_DBG("no pkg memory!\n");
00065 pkg_free(_dres);
00066 return NULL;
00067 }
00068 memset(_dres->colv, 0, _sz*sizeof(dbt_column_t));
00069 LM_DBG("new res with %d cols\n", _sz);
00070 for(i = 0; i < _sz; i++)
00071 {
00072 n = (_lres)?_dtp->colv[_lres[i]]->name.len:_dtp->colv[i]->name.len;
00073 p = (_lres)?_dtp->colv[_lres[i]]->name.s:_dtp->colv[i]->name.s;
00074 _dres->colv[i].name.s = (char*)pkg_malloc((n+1)*sizeof(char));
00075 if(!_dres->colv[i].name.s)
00076 {
00077 LM_DBG("no pkg memory\n");
00078 goto clean;
00079 }
00080 _dres->colv[i].name.len = n;
00081 strncpy(_dres->colv[i].name.s, p, n);
00082 _dres->colv[i].name.s[n] = 0;
00083 _dres->colv[i].type =
00084 (_lres)?_dtp->colv[_lres[i]]->type:_dtp->colv[i]->type;
00085 }
00086
00087 _dres->nrcols = _sz;
00088 _dres->nrrows = 0;
00089 _dres->rows = NULL;
00090
00091 return _dres;
00092 clean:
00093 while(i>=0)
00094 {
00095 if(_dres->colv[i].name.s)
00096 pkg_free(_dres->colv[i].name.s);
00097 i--;
00098 }
00099 pkg_free(_dres->colv);
00100 pkg_free(_dres);
00101
00102 return NULL;
00103 }
00104
00105 int dbt_result_free(dbt_result_p _dres)
00106 {
00107 dbt_row_p _rp=NULL, _rp0=NULL;
00108 int i;
00109
00110 if(!_dres)
00111 return -1;
00112 _rp = _dres->rows;
00113 while(_rp)
00114 {
00115 _rp0=_rp;
00116 if(_rp0->fields)
00117 {
00118 for(i=0; i<_dres->nrcols; i++)
00119 {
00120 if((_dres->colv[i].type==DB_STR
00121 || _dres->colv[i].type==DB_STRING)
00122 && _rp0->fields[i].val.str_val.s)
00123 pkg_free(_rp0->fields[i].val.str_val.s);
00124 }
00125 pkg_free(_rp0->fields);
00126 }
00127 pkg_free(_rp0);
00128 _rp=_rp->next;
00129 }
00130 if(_dres->colv)
00131 {
00132 for(i=0; i<_dres->nrcols; i++)
00133 {
00134 if(_dres->colv[i].name.s)
00135 pkg_free(_dres->colv[i].name.s);
00136 }
00137 pkg_free(_dres->colv);
00138 }
00139
00140 pkg_free(_dres);
00141
00142 return 0;
00143 }
00144
00145 int dbt_result_add_row(dbt_result_p _dres, dbt_row_p _drp)
00146 {
00147 if(!_dres || !_drp)
00148 return -1;
00149 _dres->nrrows++;
00150
00151 if(_dres->rows)
00152 (_dres->rows)->prev = _drp;
00153 _drp->next = _dres->rows;
00154 _dres->rows = _drp;
00155
00156 return 0;
00157 }
00158
00159 int* dbt_get_refs(dbt_table_p _dtp, db_key_t* _k, int _n)
00160 {
00161 int i, j, *_lref=NULL;
00162
00163 if(!_dtp || !_k || _n < 0)
00164 return NULL;
00165
00166 _lref = (int*)pkg_malloc(_n*sizeof(int));
00167 if(!_lref)
00168 return NULL;
00169
00170 for(i=0; i < _n; i++)
00171 {
00172 for(j=0; j<_dtp->nrcols; j++)
00173 {
00174 if(_k[i]->len==_dtp->colv[j]->name.len
00175 && !strncasecmp(_k[i]->s, _dtp->colv[j]->name.s,
00176 _dtp->colv[j]->name.len))
00177 {
00178 _lref[i] = j;
00179 break;
00180 }
00181 }
00182 if(j>=_dtp->nrcols)
00183 {
00184 LM_ERR("column <%.*s> not found\n", _k[i]->len, _k[i]->s);
00185 pkg_free(_lref);
00186 return NULL;
00187 }
00188 }
00189 return _lref;
00190 }
00191
00192
00193 int dbt_row_match(dbt_table_p _dtp, dbt_row_p _drp, int* _lkey,
00194 db_op_t* _op, db_val_t* _v, int _n)
00195 {
00196 int i, res;
00197 if(!_dtp || !_drp)
00198 return 0;
00199 if(!_lkey)
00200 return 1;
00201 for(i=0; i<_n; i++)
00202 {
00203 res = dbt_cmp_val(&_drp->fields[_lkey[i]], &_v[i]);
00204 if(!_op || !strcmp(_op[i], OP_EQ))
00205 {
00206 if(res!=0)
00207 return 0;
00208 }else{
00209 if(!strcmp(_op[i], OP_LT))
00210 {
00211 if(res!=-1)
00212 return 0;
00213 }else{
00214 if(!strcmp(_op[i], OP_GT))
00215 {
00216 if(res!=1)
00217 return 0;
00218 }else{
00219 if(!strcmp(_op[i], OP_LEQ))
00220 {
00221 if(res==1)
00222 return 0;
00223 }else{
00224 if(!strcmp(_op[i], OP_GEQ))
00225 {
00226 if(res==-1)
00227 return 0;
00228 }else{
00229 return 0;
00230 }}}}}
00231 }
00232 return 1;
00233 }
00234
00235 int dbt_result_extract_fields(dbt_table_p _dtp, dbt_row_p _drp,
00236 int* _lres, dbt_result_p _dres)
00237 {
00238 dbt_row_p _rp=NULL;
00239 int i, n;
00240
00241 if(!_dtp || !_drp || !_dres || _dres->nrcols<=0)
00242 return -1;
00243
00244 _rp = dbt_result_new_row(_dres);
00245 if(!_rp)
00246 return -1;
00247
00248 for(i=0; i<_dres->nrcols; i++)
00249 {
00250 n = (_lres)?_lres[i]:i;
00251 if(dbt_is_neq_type(_dres->colv[i].type, _dtp->colv[n]->type))
00252 {
00253 LM_DBG("wrong types!\n");
00254 goto clean;
00255 }
00256 _rp->fields[i].nul = _drp->fields[n].nul;
00257 if(_rp->fields[i].nul)
00258 {
00259 memset(&(_rp->fields[i].val), 0, sizeof(_rp->fields[i].val));
00260 continue;
00261 }
00262
00263 switch(_dres->colv[i].type)
00264 {
00265 case DB_INT:
00266 case DB_DATETIME:
00267 case DB_BITMAP:
00268 _rp->fields[i].type = _dres->colv[i].type;
00269 _rp->fields[i].val.int_val = _drp->fields[n].val.int_val;
00270 break;
00271 case DB_DOUBLE:
00272 _rp->fields[i].type = DB_DOUBLE;
00273 _rp->fields[i].val.double_val=_drp->fields[n].val.double_val;
00274 break;
00275 case DB_STRING:
00276 case DB_STR:
00277 case DB_BLOB:
00278 _rp->fields[i].type = _dres->colv[i].type;
00279 _rp->fields[i].val.str_val.len =
00280 _drp->fields[n].val.str_val.len;
00281 _rp->fields[i].val.str_val.s =(char*)pkg_malloc(sizeof(char)*
00282 (_drp->fields[n].val.str_val.len+1));
00283 if(!_rp->fields[i].val.str_val.s)
00284 goto clean;
00285 memcpy(_rp->fields[i].val.str_val.s,
00286 _drp->fields[n].val.str_val.s,
00287 _rp->fields[i].val.str_val.len);
00288 _rp->fields[i].val.str_val.s[_rp->fields[i].val.str_val.len]=0;
00289 break;
00290 default:
00291 goto clean;
00292 }
00293 }
00294
00295 if(_dres->rows)
00296 (_dres->rows)->prev = _rp;
00297 _rp->next = _dres->rows;
00298 _dres->rows = _rp;
00299 _dres->nrrows++;
00300
00301 return 0;
00302
00303 clean:
00304 LM_DBG("make clean!\n");
00305 while(i>=0)
00306 {
00307 if((_rp->fields[i].type == DB_STRING
00308 || _rp->fields[i].type == DB_STR
00309 || _rp->fields[i].type == DB_BLOB)
00310 && !_rp->fields[i].nul
00311 && _rp->fields[i].val.str_val.s)
00312 pkg_free(_rp->fields[i].val.str_val.s);
00313
00314 i--;
00315 }
00316 pkg_free(_rp->fields);
00317 pkg_free(_rp);
00318
00319 return -1;
00320 }
00321
00322 int dbt_result_print(dbt_result_p _dres)
00323 {
00324 #if 0
00325 int i;
00326 FILE *fout = stdout;
00327 dbt_row_p rowp = NULL;
00328 char *p;
00329
00330 if(!_dres || _dres->nrcols<=0)
00331 return -1;
00332
00333 fprintf(fout, "\nContent of result\n");
00334
00335 for(i=0; i<_dres->nrcols; i++)
00336 {
00337 switch(_dres->colv[i].type)
00338 {
00339 case DB_INT:
00340 fprintf(fout, "%.*s(int", _dres->colv[i].name.len,
00341 _dres->colv[i].name.s);
00342 if(_dres->colv[i].flag & DBT_FLAG_NULL)
00343 fprintf(fout, ",null");
00344 fprintf(fout, ") ");
00345 break;
00346 case DB_DOUBLE:
00347 fprintf(fout, "%.*s(double", _dres->colv[i].name.len,
00348 _dres->colv[i].name.s);
00349 if(_dres->colv[i].flag & DBT_FLAG_NULL)
00350 fprintf(fout, ",null");
00351 fprintf(fout, ") ");
00352 break;
00353 case DB_STR:
00354 fprintf(fout, "%.*s(str", _dres->colv[i].name.len,
00355 _dres->colv[i].name.s);
00356 if(_dres->colv[i].flag & DBT_FLAG_NULL)
00357 fprintf(fout, ",null");
00358 fprintf(fout, ") ");
00359 break;
00360 default:
00361 return -1;
00362 }
00363 }
00364 fprintf(fout, "\n");
00365 rowp = _dres->rows;
00366 while(rowp)
00367 {
00368 for(i=0; i<_dres->nrcols; i++)
00369 {
00370 switch(_dres->colv[i].type)
00371 {
00372 case DB_INT:
00373 if(rowp->fields[i].nul)
00374 fprintf(fout, "N ");
00375 else
00376 fprintf(fout, "%d ",
00377 rowp->fields[i].val.int_val);
00378 break;
00379 case DB_DOUBLE:
00380 if(rowp->fields[i].nul)
00381 fprintf(fout, "N ");
00382 else
00383 fprintf(fout, "%.2f ",
00384 rowp->fields[i].val.double_val);
00385 break;
00386 case DB_STR:
00387 fprintf(fout, "\"");
00388 if(!rowp->fields[i].nul)
00389 {
00390 p = rowp->fields[i].val.str_val.s;
00391 while(p < rowp->fields[i].val.str_val.s
00392 + rowp->fields[i].val.str_val.len)
00393 {
00394 switch(*p)
00395 {
00396 case '\n':
00397 fprintf(fout, "\\n");
00398 break;
00399 case '\r':
00400 fprintf(fout, "\\r");
00401 break;
00402 case '\t':
00403 fprintf(fout, "\\t");
00404 break;
00405 case '\\':
00406 fprintf(fout, "\\\\");
00407 break;
00408 case '"':
00409 fprintf(fout, "\\\"");
00410 break;
00411 case '\0':
00412 fprintf(fout, "\\0");
00413 break;
00414 default:
00415 fprintf(fout, "%c", *p);
00416 }
00417 p++;
00418 }
00419 }
00420 fprintf(fout, "\" ");
00421 break;
00422 default:
00423 return -1;
00424 }
00425 }
00426 fprintf(fout, "\n");
00427 rowp = rowp->next;
00428 }
00429 #endif
00430
00431 return 0;
00432 }
00433
00434 int dbt_cmp_val(dbt_val_p _vp, db_val_t* _v)
00435 {
00436 int _l, _n;
00437 if(!_vp && !_v)
00438 return 0;
00439 if(!_v)
00440 return 1;
00441 if(!_vp)
00442 return -1;
00443 if(_vp->nul && _v->nul)
00444 return 0;
00445 if(_v->nul)
00446 return 1;
00447 if(_vp->nul)
00448 return -1;
00449
00450 switch(VAL_TYPE(_v))
00451 {
00452 case DB_INT:
00453 return (_vp->val.int_val<_v->val.int_val)?-1:
00454 (_vp->val.int_val>_v->val.int_val)?1:0;
00455
00456 case DB_BIGINT:
00457 LM_ERR("BIGINT not supported");
00458 return -1;
00459
00460 case DB_DOUBLE:
00461 return (_vp->val.double_val<_v->val.double_val)?-1:
00462 (_vp->val.double_val>_v->val.double_val)?1:0;
00463 case DB_DATETIME:
00464 return (_vp->val.int_val<_v->val.time_val)?-1:
00465 (_vp->val.int_val>_v->val.time_val)?1:0;
00466 case DB_STRING:
00467 _l = strlen(_v->val.string_val);
00468 _l = (_l>_vp->val.str_val.len)?_vp->val.str_val.len:_l;
00469 _n = strncasecmp(_vp->val.str_val.s, _v->val.string_val, _l);
00470 if(_n)
00471 return SIGN(_n);
00472 if(_vp->val.str_val.len == strlen(_v->val.string_val))
00473 return 0;
00474 if(_l==_vp->val.str_val.len)
00475 return -1;
00476 return 1;
00477 case DB_STR:
00478 _l = _v->val.str_val.len;
00479 _l = (_l>_vp->val.str_val.len)?_vp->val.str_val.len:_l;
00480 _n = strncasecmp(_vp->val.str_val.s, _v->val.str_val.s, _l);
00481 if(_n)
00482 return SIGN(_n);
00483 if(_vp->val.str_val.len == _v->val.str_val.len)
00484 return 0;
00485 if(_l==_vp->val.str_val.len)
00486 return -1;
00487 return 1;
00488 case DB_BLOB:
00489 _l = _v->val.blob_val.len;
00490 _l = (_l>_vp->val.str_val.len)?_vp->val.str_val.len:_l;
00491 _n = strncasecmp(_vp->val.str_val.s, _v->val.blob_val.s, _l);
00492 if(_n)
00493 return SIGN(_n);
00494 if(_vp->val.str_val.len == _v->val.blob_val.len)
00495 return 0;
00496 if(_l==_vp->val.str_val.len)
00497 return -1;
00498 return 1;
00499 case DB_BITMAP:
00500 return (_vp->val.int_val<_v->val.bitmap_val)?-1:
00501 (_vp->val.int_val>_v->val.bitmap_val)?1:0;
00502 }
00503 LM_ERR("invalid datatype %d\n", VAL_TYPE(_v));
00504 return -2;
00505 }
00506
00507 dbt_row_p dbt_result_new_row(dbt_result_p _dres)
00508 {
00509 dbt_row_p _drp = NULL;
00510 if(!_dres || _dres->nrcols<=0)
00511 return NULL;
00512
00513 _drp = (dbt_row_p)pkg_malloc(sizeof(dbt_row_t));
00514 if(!_drp)
00515 return NULL;
00516 memset(_drp, 0, sizeof(dbt_row_t));
00517 _drp->fields = (dbt_val_p)pkg_malloc(_dres->nrcols*sizeof(dbt_val_t));
00518 if(!_drp->fields)
00519 {
00520 pkg_free(_drp);
00521 return NULL;
00522 }
00523 memset(_drp->fields, 0, _dres->nrcols*sizeof(dbt_val_t));
00524
00525 _drp->next = _drp->prev = NULL;
00526
00527 return _drp;
00528 }
00529
00530
00531
00532
00533
00534 int dbt_parse_orderbyclause(db_key_t **_o_k, char **_o_op, int *_o_n, db_key_t _o)
00535 {
00536 char *_po, *_ps, *_pe;
00537 char _c = '\0';
00538 char _d[8];
00539 int _n;
00540 int _i;
00541 str *_s;
00542
00543
00544 _n = 1;
00545 for (_i=0; _i < _o->len; _i++)
00546 if (_o->s[_i] == ',')
00547 _n++;
00548
00549
00550 *_o_k = pkg_malloc((sizeof(db_key_t)+sizeof(str)) * _n + _o->len + 1);
00551 if (!*_o_k)
00552 return -1;
00553 _s = (str *)((char *)(*_o_k) + sizeof(db_key_t) * _n);
00554 for (_i=0; _i < _n; _i++)
00555 (*_o_k)[_i] = &_s[_i];
00556 _po = (char *)(*_o_k) + (sizeof(db_key_t) + sizeof(str)) * _n;
00557 memcpy(_po, _o->s, _o->len);
00558 *(_po+_o->len) = '\0';
00559
00560 *_o_op = pkg_malloc(sizeof(db_op_t) * _n);
00561 if (!*_o_op)
00562 {
00563 pkg_free(*_o_k);
00564 return -1;
00565 }
00566
00567 *_o_n = 0;
00568 _ps = _po;
00569 while (*_o_n < _n)
00570 {
00571 while (*_ps == ' ') _ps++;
00572 if (*_ps == '\0')
00573 break;
00574 strcpy(_d, " \f\n\r\t\v,");
00575 if (*_ps == '"' || *_ps == '\'')
00576 {
00577 _d[0] = *_ps;
00578 _d[1] = '\0';
00579 _ps++;
00580 }
00581 _pe = strpbrk(_ps, _d);
00582 if (!_pe && _d[0] == ' ')
00583 _pe = _po + _o->len;
00584 if (! _pe)
00585 goto parse_error;
00586
00587
00588
00589 _c = *_pe;
00590 *_pe = '\0';
00591 (*_o_k)[*_o_n]->s = _ps;
00592 (*_o_k)[*_o_n]->len = _pe - _ps;
00593 (*_o_op)[*_o_n] = '<';
00594 (*_o_n)++;
00595
00596 if (_c == '\0')
00597 break;
00598
00599
00600 _ps = _pe + 1;
00601 if (_c == ',')
00602 continue;
00603 while (*_ps == ' ') _ps++;
00604 if (*_ps == ',')
00605 {
00606 _ps++;
00607 continue;
00608 }
00609 if (*_ps == '\0')
00610 break;
00611
00612
00613 if (strncasecmp(_ps, "DESC", 4) == 0)
00614 {
00615 (*_o_op)[*_o_n-1] = '>';
00616 _ps += 4;
00617 } else if (strncasecmp(_ps, "ASC", 3) == 0)
00618 {
00619 _ps += 3;
00620 } else goto parse_error;
00621
00622
00623 while (*_ps == ' ') _ps++;
00624 if (*_ps == ',')
00625 {
00626 _ps++;
00627 continue;
00628 }
00629 if (*_ps == '\0')
00630 break;
00631 goto parse_error;
00632 }
00633
00634 if (*_ps != '\0' && _c != '\0')
00635 goto parse_error;
00636
00637 if (*_o_n == 0)
00638 {
00639 pkg_free(*_o_k);
00640 pkg_free(*_o_op);
00641 *_o_op = NULL;
00642 *_o_k = NULL;
00643 return 0;
00644 }
00645
00646 return 0;
00647
00648 parse_error:
00649 pkg_free(*_o_k);
00650 pkg_free(*_o_op);
00651 *_o_op = NULL;
00652 *_o_k = NULL;
00653 *_o_n = 0;
00654 return -1;
00655 }
00656
00657
00658
00659
00660
00661
00662 int dbt_mangle_columnselection(int **_lres, int *_nc, int *_o_nc, int *_o_l, int _o_n)
00663 {
00664 int _i, _j;
00665
00666 *_o_nc = 0;
00667
00668 if (! *_lres)
00669 return 0;
00670
00671
00672 for (_i=0; _i < _o_n; _i++)
00673 {
00674 for (_j=0; _j < *_nc && (*_lres)[_j] != _o_l[_i]; _j++);
00675 if (_j == *_nc)
00676 (*_o_nc)++;
00677 }
00678
00679 if (*_o_nc == 0)
00680 return 0;
00681
00682
00683 *_lres = pkg_realloc(*_lres, sizeof(int) * (*_nc + *_o_nc));
00684 if (! *_lres)
00685 return -1;
00686
00687
00688 for (_i=0; _i < _o_n; _i++)
00689 {
00690 for (_j=0; _j < *_nc && (*_lres)[_j] != _o_l[_i]; _j++);
00691 if (_j == *_nc)
00692 {
00693 (*_lres)[*_nc] = _o_l[_i];
00694 (*_nc)++;
00695 }
00696 }
00697
00698
00699 return 0;
00700 }
00701
00702
00703 dbt_result_p dbt_sort_dres;
00704 int *dbt_sort_o_l;
00705 char *dbt_sort_o_op;
00706 int dbt_sort_o_n;
00707 jmp_buf dbt_sort_jmpenv;
00708
00709
00710
00711 int dbt_qsort_compar(const void *_a, const void *_b)
00712 {
00713 int _i, _j, _r;
00714
00715 for (_i=0; _i<dbt_sort_o_n; _i++)
00716 {
00717 _j = dbt_sort_o_l[_i];
00718 _r = dbt_cmp_val(&(*(dbt_row_p *)_a)->fields[_j], &(*(dbt_row_p *)_b)->fields[_j]);
00719 if (_r == 0)
00720 continue;
00721 if (_r == +1 || _r == -1)
00722 return (dbt_sort_o_op[_i] == '<') ? _r : -_r;
00723
00724 longjmp(dbt_sort_jmpenv, _r);
00725 }
00726
00727
00728 return 0;
00729 }
00730
00731
00732 int dbt_sort_result(dbt_result_p _dres, int *_o_l, char *_o_op, int _o_n, int *_lres, int _nc)
00733 {
00734 int _i, _j;
00735 dbt_row_p *_a;
00736 dbt_row_p _el;
00737
00738
00739 if (_lres)
00740 {
00741 for (_i=0; _i < _o_n; _i++)
00742 {
00743
00744 for (_j=0; _lres[_j] != _o_l[_i]; _j++ );
00745 _o_l[_i] = _j;
00746 }
00747 }
00748
00749
00750 _a = pkg_malloc(sizeof(dbt_row_t) * _dres->nrrows);
00751 if (!_a)
00752 return -1;
00753 for (_el=_dres->rows, _i=0; _el != NULL; _el=_el->next, _i++)
00754 _a[_i] = _el;
00755
00756
00757 dbt_sort_dres = _dres;
00758 dbt_sort_o_l = _o_l;
00759 dbt_sort_o_op = _o_op;
00760 dbt_sort_o_n = _o_n;
00761 _i = setjmp(dbt_sort_jmpenv);
00762 if (_i)
00763 {
00764
00765 LM_ERR("qsort aborted\n");
00766 pkg_free(_a);
00767 return _i;
00768 }
00769
00770 qsort(_a, _dres->nrrows, sizeof(dbt_row_p), &dbt_qsort_compar);
00771
00772
00773 for (_i=0; _i < _dres->nrrows; _i++)
00774 {
00775 _a[_i]->prev = (_i > 0) ? _a[_i-1] : NULL;
00776 _a[_i]->next = (_i+1 < _dres->nrrows) ? _a[_i+1] : NULL;
00777 }
00778 _dres->rows = _a[0];
00779
00780 pkg_free(_a);
00781 return 0;
00782 }
00783
00784
00785
00786
00787
00788
00789 void dbt_project_result(dbt_result_p _dres, int _o_nc)
00790 {
00791 int _i;
00792 dbt_row_p _drp;
00793
00794 if (! _o_nc)
00795 return;
00796
00797
00798 for (_i = _dres->nrcols - _o_nc; _i < _dres->nrcols; _i++)
00799 {
00800 if (_dres->colv[_i].type == DB_STRING ||
00801 _dres->colv[_i].type == DB_STR ||
00802 _dres->colv[_i].type == DB_BLOB)
00803 {
00804 for (_drp=_dres->rows; _drp != NULL; _drp = _drp->next)
00805 {
00806 if (! _drp->fields[_i].nul &&
00807 (_drp->fields[_i].type == DB_STRING ||
00808 _drp->fields[_i].type == DB_STR ||
00809 _drp->fields[_i].type == DB_BLOB ))
00810 {
00811 pkg_free(_drp->fields[_i].val.str_val.s);
00812 _drp->fields[_i].val.str_val.s = NULL;
00813 _drp->fields[_i].val.str_val.len = 0;
00814 }
00815 }
00816 }
00817
00818
00819 pkg_free(_dres->colv[_i].name.s);
00820 _dres->colv[_i].name.s = NULL;
00821 _dres->colv[_i].name.len = 0;
00822 }
00823
00824
00825 _dres->nrcols -= _o_nc;
00826 }
00827