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
00035
00036 #include "system.h"
00037
00038 #include <rpmio.h>
00039 #include <rpmlog.h>
00040 #include <rpmmacro.h>
00041 #include <rpmurl.h>
00042
00043 #include <rpmtag.h>
00044 #define _RPMDB_INTERNAL
00045 #include <rpmdb.h>
00046
00047 #include <sqlite3.h>
00048
00049 #include "debug.h"
00050
00051
00052
00053
00054
00055 static int _debug = 0;
00056
00057
00058 struct _sql_db_s; typedef struct _sql_db_s SQL_DB;
00059 struct _sql_dbcursor_s; typedef struct _sql_dbcursor_s *SCP_t;
00060
00061 struct _sql_db_s {
00062 sqlite3 * db;
00063 int transaction;
00064 };
00065
00066 struct _sql_dbcursor_s {
00067
00068 DB *dbp;
00069
00070
00071 char * cmd;
00072
00073 sqlite3_stmt *pStmt;
00074 const char * pzErrmsg;
00075
00076
00077
00078 char ** av;
00079
00080 size_t * avlen;
00081 int nalloc;
00082 int ac;
00083 int rx;
00084 int nr;
00085 int nc;
00086
00087 int all;
00088
00089 DBT ** keys;
00090 int nkeys;
00091
00092 int count;
00093
00094 void * lkey;
00095 void * ldata;
00096
00097 int used;
00098 };
00099
00100
00101 union _dbswap {
00102 uint32_t ui;
00103 unsigned char uc[4];
00104 };
00105
00106
00107 #define _DBSWAP(_a) \
00108 { unsigned char _b, *_c = (_a).uc; \
00109 _b = _c[3]; _c[3] = _c[0]; _c[0] = _b; \
00110 _b = _c[2]; _c[2] = _c[1]; _c[1] = _b; \
00111 }
00112
00113
00114 static unsigned int endian = 0x11223344;
00115
00116
00117 static const char * sqlCwd = NULL;
00118
00119 static int sqlInRoot = 0;
00120
00121 static void enterChroot(dbiIndex dbi)
00122
00123
00124 {
00125 char * currDir = NULL;
00126 int xx;
00127
00128 if ((dbi->dbi_root[0] == '/' && dbi->dbi_root[1] == '\0') || dbi->dbi_rpmdb->db_chrootDone || sqlInRoot)
00129
00130 return;
00131
00132 if (_debug)
00133 fprintf(stderr, "sql:chroot(%s)\n", dbi->dbi_root);
00134
00135 {
00136 int currDirLen = 0;
00137
00138 do {
00139 currDirLen += 128;
00140 currDir = xrealloc(currDir, currDirLen);
00141 memset(currDir, 0, currDirLen);
00142 } while (getcwd(currDir, currDirLen) == NULL && errno == ERANGE);
00143 }
00144
00145 sqlCwd = currDir;
00146
00147 xx = Chdir("/");
00148
00149
00150 xx = Chroot(dbi->dbi_root);
00151
00152 assert(xx == 0);
00153 sqlInRoot=1;
00154 }
00155
00156 static void leaveChroot(dbiIndex dbi)
00157
00158
00159 {
00160 int xx;
00161
00162 if ((dbi->dbi_root[0] == '/' && dbi->dbi_root[1] == '\0') || dbi->dbi_rpmdb->db_chrootDone || !sqlInRoot)
00163
00164 return;
00165
00166 if (_debug)
00167 fprintf(stderr, "sql:chroot(.)\n");
00168
00169
00170 xx = Chroot(".");
00171
00172 assert(xx == 0);
00173 if (sqlCwd != NULL) {
00174
00175 xx = Chdir(sqlCwd);
00176
00177 sqlCwd = _free(sqlCwd);
00178 }
00179
00180 sqlInRoot = 0;
00181 }
00182
00183 static void dbg_scp(void *ptr)
00184
00185
00186 {
00187 SCP_t scp = ptr;
00188
00189 if (_debug)
00190 fprintf(stderr, "\tscp %p [%d:%d] av %p avlen %p nr [%d:%d] nc %d all %d\n", scp, scp->ac, scp->nalloc, scp->av, scp->avlen, scp->rx, scp->nr, scp->nc, scp->all);
00191
00192 }
00193
00194 static void dbg_keyval(const char * msg, dbiIndex dbi, DBC * dbcursor,
00195 DBT * key, DBT * data, unsigned int flags)
00196
00197
00198 {
00199
00200 if (!_debug) return;
00201
00202 fprintf(stderr, "%s on %s (%p,%p,%p,0x%x)", msg, dbi->dbi_subfile, dbcursor, key, data, flags);
00203
00204
00205 if (key != NULL && key->data != NULL) {
00206 fprintf(stderr, " key 0x%x[%d]", *(unsigned int *)key->data, key->size);
00207 if (dbi->dbi_rpmtag == RPMTAG_NAME)
00208 fprintf(stderr, " \"%s\"", (const char *)key->data);
00209 }
00210 if (data != NULL && data->data != NULL)
00211 fprintf(stderr, " data 0x%x[%d]", *(unsigned int *)data->data, data->size);
00212
00213 fprintf(stderr, "\n");
00214 if (dbcursor != NULL)
00215 dbg_scp(dbcursor);
00216 }
00217
00218
00219 static SCP_t scpResetKeys( SCP_t scp)
00220
00221 {
00222 int ix;
00223
00224 if (_debug)
00225 fprintf(stderr, "*** scpResetKeys(%p)\n", scp);
00226 dbg_scp(scp);
00227
00228 for ( ix =0 ; ix < scp->nkeys ; ix++ ) {
00229 scp->keys[ix]->data = _free(scp->keys[ix]->data);
00230
00231 scp->keys[ix] = _free(scp->keys[ix]);
00232
00233 }
00234 scp->keys = _free(scp->keys);
00235 scp->nkeys = 0;
00236
00237 return scp;
00238 }
00239
00240
00241 static SCP_t scpResetAv( SCP_t scp)
00242
00243 {
00244 int xx;
00245
00246 if (_debug)
00247 fprintf(stderr, "*** scpResetAv(%p)\n", scp);
00248 dbg_scp(scp);
00249
00250 if (scp->av != NULL) {
00251 if (scp->nalloc <= 0) {
00252
00253 sqlite3_free_table(scp->av);
00254 scp->av = NULL;
00255 scp->nalloc = 0;
00256 } else {
00257
00258
00259 for (xx = 0; xx < scp->ac; xx++)
00260 scp->av[xx] = _free(scp->av[xx]);
00261
00262 if (scp->av != NULL)
00263 memset(scp->av, 0, scp->nalloc * sizeof(*scp->av));
00264 if (scp->avlen != NULL)
00265 memset(scp->avlen, 0, scp->nalloc * sizeof(*scp->avlen));
00266 scp->av = _free(scp->av);
00267 scp->avlen = _free(scp->avlen);
00268 scp->nalloc = 0;
00269 }
00270 } else
00271 scp->nalloc = 0;
00272 scp->ac = 0;
00273 scp->nr = 0;
00274 scp->nc = 0;
00275
00276 return scp;
00277 }
00278
00279
00280 static SCP_t scpReset( SCP_t scp)
00281
00282 {
00283 int xx;
00284
00285 if (_debug)
00286 fprintf(stderr, "*** scpReset(%p)\n", scp);
00287 dbg_scp(scp);
00288
00289 if (scp->cmd) {
00290 sqlite3_free(scp->cmd);
00291 scp->cmd = NULL;
00292 }
00293 if (scp->pStmt) {
00294 xx = sqlite3_reset(scp->pStmt);
00295 if (xx) rpmlog(RPMLOG_WARNING, "reset %d\n", xx);
00296 xx = sqlite3_finalize(scp->pStmt);
00297 if (xx) rpmlog(RPMLOG_WARNING, "finalize %d\n", xx);
00298 scp->pStmt = NULL;
00299 }
00300
00301 scp = scpResetAv(scp);
00302
00303 scp->rx = 0;
00304 return scp;
00305 }
00306
00307
00308 static SCP_t scpFree( SCP_t scp)
00309
00310 {
00311 scp = scpReset(scp);
00312 scp = scpResetKeys(scp);
00313 scp->av = _free(scp->av);
00314 scp->avlen = _free(scp->avlen);
00315
00316 if (_debug)
00317 fprintf(stderr, "*** scpFree(%p)\n", scp);
00318 scp = _free(scp);
00319 return NULL;
00320 }
00321
00322 static SCP_t scpNew(DB * dbp)
00323
00324 {
00325 SCP_t scp = xcalloc(1, sizeof(*scp));
00326
00327 scp->dbp = dbp;
00328
00329
00330 scp->used = 0;
00331
00332 scp->lkey = NULL;
00333 scp->ldata = NULL;
00334
00335 if (_debug)
00336 fprintf(stderr, "*** scpNew(%p)\n", scp);
00337 return scp;
00338 }
00339
00340 static int sql_step(dbiIndex dbi, SCP_t scp)
00341
00342 {
00343 int swapped = dbiByteSwapped(dbi);
00344 const char * cname;
00345 const char * vtype;
00346 size_t nb;
00347 int loop;
00348 int need;
00349 int rc;
00350 int i;
00351
00352 scp->nc = sqlite3_column_count(scp->pStmt);
00353
00354 if (scp->nr == 0 && scp->av != NULL)
00355 need = 2 * scp->nc;
00356 else
00357 need = scp->nc;
00358
00359
00360 if (!scp->ac && !need && !scp->nalloc)
00361 need++;
00362
00363 if (scp->ac + need >= scp->nalloc) {
00364
00365 scp->nalloc = 2 * scp->nalloc + need + 4;
00366 scp->av = xrealloc(scp->av, scp->nalloc * sizeof(*scp->av));
00367 scp->avlen = xrealloc(scp->avlen, scp->nalloc * sizeof(*scp->avlen));
00368 }
00369
00370 if (scp->av != NULL && scp->nr == 0) {
00371 for (i = 0; i < scp->nc; i++) {
00372 scp->av[scp->ac] = xstrdup(sqlite3_column_name(scp->pStmt, i));
00373 if (scp->avlen) scp->avlen[scp->ac] = strlen(scp->av[scp->ac]) + 1;
00374 scp->ac++;
00375 assert(scp->ac <= scp->nalloc);
00376 }
00377 }
00378
00379
00380 loop = 1;
00381 while (loop) {
00382 rc = sqlite3_step(scp->pStmt);
00383 switch (rc) {
00384 case SQLITE_DONE:
00385 if (_debug)
00386 fprintf(stderr, "sqlite3_step: DONE scp %p [%d:%d] av %p avlen %p\n", scp, scp->ac, scp->nalloc, scp->av, scp->avlen);
00387 loop = 0;
00388 break;
00389 case SQLITE_ROW:
00390 if (scp->av != NULL)
00391 for (i = 0; i < scp->nc; i++) {
00392
00393 if (scp->ac + need >= scp->nalloc) {
00394
00395 scp->nalloc = 2 * scp->nalloc + need + 4;
00396 scp->av = xrealloc(scp->av, scp->nalloc * sizeof(*scp->av));
00397 scp->avlen = xrealloc(scp->avlen, scp->nalloc * sizeof(*scp->avlen));
00398 }
00399 assert(scp->av != NULL);
00400 assert(scp->avlen != NULL);
00401
00402 cname = sqlite3_column_name(scp->pStmt, i);
00403 vtype = sqlite3_column_decltype(scp->pStmt, i);
00404 nb = 0;
00405
00406 if (!strcmp(vtype, "blob")) {
00407 const void * v = sqlite3_column_blob(scp->pStmt, i);
00408 nb = sqlite3_column_bytes(scp->pStmt, i);
00409 if (_debug)
00410 fprintf(stderr, "\t%d %s %s %p[%d]\n", i, cname, vtype, v, (int)nb);
00411 if (nb > 0) {
00412 void * t = xmalloc(nb);
00413 scp->av[scp->ac] = memcpy(t, v, nb);
00414 scp->avlen[scp->ac] = nb;
00415 scp->ac++;
00416 }
00417 } else
00418 if (!strcmp(vtype, "double")) {
00419 double v = sqlite3_column_double(scp->pStmt, i);
00420 nb = sizeof(v);
00421 if (_debug)
00422 fprintf(stderr, "\t%d %s %s %g\n", i, cname, vtype, v);
00423 if (nb > 0) {
00424 scp->av[scp->ac] = memcpy(xmalloc(nb), &v, nb);
00425 scp->avlen[scp->ac] = nb;
00426 assert(swapped == 0);
00427 scp->ac++;
00428 }
00429 } else
00430 if (!strcmp(vtype, "int")) {
00431 int32_t v = sqlite3_column_int(scp->pStmt, i);
00432 nb = sizeof(v);
00433 if (_debug)
00434 fprintf(stderr, "\t%d %s %s %d\n", i, cname, vtype, (int) v);
00435 if (nb > 0) {
00436 scp->av[scp->ac] = memcpy(xmalloc(nb), &v, nb);
00437 scp->avlen[scp->ac] = nb;
00438 if (swapped == 1) {
00439 union _dbswap dbswap;
00440 memcpy(&dbswap.ui, scp->av[scp->ac], sizeof(dbswap.ui));
00441 _DBSWAP(dbswap);
00442 memcpy(scp->av[scp->ac], &dbswap.ui, sizeof(dbswap.ui));
00443 }
00444 scp->ac++;
00445 }
00446 } else
00447 if (!strcmp(vtype, "int64")) {
00448 int64_t v = sqlite3_column_int64(scp->pStmt, i);
00449 nb = sizeof(v);
00450 if (_debug)
00451 fprintf(stderr, "\t%d %s %s %ld\n", i, cname, vtype, (long)v);
00452 if (nb > 0) {
00453 scp->av[scp->ac] = memcpy(xmalloc(nb), &v, nb);
00454 scp->avlen[scp->ac] = nb;
00455 assert(swapped == 0);
00456 scp->ac++;
00457 }
00458 } else
00459 if (!strcmp(vtype, "text")) {
00460 const char * v = (const char *)sqlite3_column_text(scp->pStmt, i);
00461 nb = strlen(v) + 1;
00462 if (_debug)
00463 fprintf(stderr, "\t%d %s %s \"%s\"\n", i, cname, vtype, v);
00464 if (nb > 0) {
00465 scp->av[scp->ac] = memcpy(xmalloc(nb), v, nb);
00466 scp->avlen[scp->ac] = nb;
00467 scp->ac++;
00468 }
00469 }
00470 assert(scp->ac <= scp->nalloc);
00471 }
00472 scp->nr++;
00473 break;
00474 case SQLITE_BUSY:
00475 fprintf(stderr, "sqlite3_step: BUSY %d\n", rc);
00476 break;
00477 case SQLITE_ERROR:
00478 fprintf(stderr, "sqlite3_step: ERROR %d -- %s\n", rc, scp->cmd);
00479 fprintf(stderr, " %s (%d)\n",
00480 sqlite3_errmsg(((SQL_DB*)dbi->dbi_db)->db), sqlite3_errcode(((SQL_DB*)dbi->dbi_db)->db));
00481
00482 fprintf(stderr, " cwd '%s'\n", getcwd(NULL,0));
00483
00484 loop = 0;
00485 break;
00486 case SQLITE_MISUSE:
00487 fprintf(stderr, "sqlite3_step: MISUSE %d\n", rc);
00488 loop = 0;
00489 break;
00490 default:
00491 fprintf(stderr, "sqlite3_step: rc %d\n", rc);
00492 loop = 0;
00493 break;
00494 }
00495 }
00496
00497
00498 if (rc == SQLITE_DONE)
00499 rc = SQLITE_OK;
00500
00501 return rc;
00502 }
00503
00504 static int sql_bind_key(dbiIndex dbi, SCP_t scp, int pos, DBT * key)
00505
00506 {
00507 int swapped = dbiByteSwapped(dbi);
00508 int rc = 0;
00509 union _dbswap dbswap;
00510
00511 assert(key->data != NULL);
00512 switch (dbi->dbi_rpmtag) {
00513 case RPMDBI_PACKAGES:
00514 { unsigned int hnum;
00515 assert(key->size == sizeof(uint32_t));
00516 memcpy(&hnum, key->data, sizeof(hnum));
00517
00518 if (swapped == 1) {
00519 memcpy(&dbswap.ui, &hnum, sizeof(dbswap.ui));
00520 _DBSWAP(dbswap);
00521 memcpy(&hnum, &dbswap.ui, sizeof(dbswap.ui));
00522 }
00523 rc = sqlite3_bind_int(scp->pStmt, pos, hnum);
00524 } break;
00525 default:
00526 switch (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE) {
00527 case RPM_BIN_TYPE:
00528
00529 rc = sqlite3_bind_blob(scp->pStmt, pos, key->data, key->size, SQLITE_STATIC);
00530
00531 break;
00532 case RPM_UINT8_TYPE:
00533 { unsigned char i;
00534 assert(key->size == sizeof(unsigned char));
00535 assert(swapped == 0);
00536 memcpy(&i, key->data, sizeof(i));
00537 rc = sqlite3_bind_int(scp->pStmt, pos, (int) i);
00538 } break;
00539 case RPM_UINT16_TYPE:
00540 { unsigned short i;
00541 assert(key->size == sizeof(uint16_t));
00542 assert(swapped == 0);
00543 memcpy(&i, key->data, sizeof(i));
00544 rc = sqlite3_bind_int(scp->pStmt, pos, (int) i);
00545 } break;
00546 case RPM_UINT64_TYPE:
00547 assert(0);
00548 break;
00549 case RPM_UINT32_TYPE:
00550 default:
00551 { unsigned int i;
00552 assert(key->size == sizeof(uint32_t));
00553 memcpy(&i, key->data, sizeof(i));
00554
00555 if (swapped == 1)
00556 {
00557 memcpy(&dbswap.ui, &i, sizeof(dbswap.ui));
00558 _DBSWAP(dbswap);
00559 memcpy(&i, &dbswap.ui, sizeof(dbswap.ui));
00560 }
00561 rc = sqlite3_bind_int(scp->pStmt, pos, i);
00562 } break;
00563 case RPM_STRING_TYPE:
00564 case RPM_STRING_ARRAY_TYPE:
00565 case RPM_I18NSTRING_TYPE:
00566
00567 rc = sqlite3_bind_text(scp->pStmt, pos, key->data, key->size, SQLITE_STATIC);
00568
00569 break;
00570 }
00571 }
00572
00573 return rc;
00574 }
00575
00576 static int sql_bind_data(dbiIndex dbi, SCP_t scp, int pos, DBT * data)
00577
00578 {
00579 int rc;
00580
00581 assert(data->data != NULL);
00582
00583 rc = sqlite3_bind_blob(scp->pStmt, pos, data->data, data->size, SQLITE_STATIC);
00584
00585
00586 return rc;
00587 }
00588
00589
00590
00591
00592
00593
00594 static int sql_startTransaction(dbiIndex dbi)
00595
00596 {
00597 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
00598 int rc = 0;
00599
00600
00601 if (!sqldb->transaction) {
00602 char * pzErrmsg;
00603 rc = sqlite3_exec(sqldb->db, "BEGIN TRANSACTION;", NULL, NULL, &pzErrmsg);
00604
00605 if (_debug)
00606 fprintf(stderr, "Begin %s SQL transaction %s (%d)\n",
00607 dbi->dbi_subfile, pzErrmsg, rc);
00608
00609 if (rc == 0)
00610 sqldb->transaction = 1;
00611 }
00612
00613 return rc;
00614 }
00615
00616 static int sql_endTransaction(dbiIndex dbi)
00617
00618 {
00619 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
00620 int rc=0;
00621
00622
00623 if (sqldb->transaction) {
00624 char * pzErrmsg;
00625 rc = sqlite3_exec(sqldb->db, "END TRANSACTION;", NULL, NULL, &pzErrmsg);
00626
00627 if (_debug)
00628 fprintf(stderr, "End %s SQL transaction %s (%d)\n",
00629 dbi->dbi_subfile, pzErrmsg, rc);
00630
00631 if (rc == 0)
00632 sqldb->transaction = 0;
00633 }
00634
00635 return rc;
00636 }
00637
00638 static int sql_commitTransaction(dbiIndex dbi, int flag)
00639
00640 {
00641 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
00642 int rc = 0;
00643
00644
00645 if ( sqldb->transaction ) {
00646 char * pzErrmsg;
00647 rc = sqlite3_exec(sqldb->db, "COMMIT;", NULL, NULL, &pzErrmsg);
00648
00649 if (_debug)
00650 fprintf(stderr, "Commit %s SQL transaction(s) %s (%d)\n",
00651 dbi->dbi_subfile, pzErrmsg, rc);
00652
00653 sqldb->transaction=0;
00654
00655
00656 if ( flag == 0 )
00657 rc = sql_startTransaction(dbi);
00658 }
00659
00660 return rc;
00661 }
00662
00663 static int sql_busy_handler(void * dbi_void, int time)
00664
00665 {
00666
00667 dbiIndex dbi = (dbiIndex) dbi_void;
00668
00669
00670 rpmlog(RPMLOG_WARNING, _("Unable to get lock on db %s, retrying... (%d)\n"),
00671 dbi->dbi_file, time);
00672
00673 (void) sleep(1);
00674
00675 return 1;
00676 }
00677
00678
00679
00685 static int sql_initDB(dbiIndex dbi)
00686
00687 {
00688 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
00689 SCP_t scp = scpNew(dbi->dbi_db);
00690 char cmd[BUFSIZ];
00691 int rc = 0;
00692
00693 if (dbi->dbi_tmpdir) {
00694 const char *root;
00695 const char *tmpdir;
00696 int xx;
00697 root = (dbi->dbi_root ? dbi->dbi_root : dbi->dbi_rpmdb->db_root);
00698 if ((root[0] == '/' && root[1] == '\0') || dbi->dbi_rpmdb->db_chrootDone)
00699 root = NULL;
00700
00701 tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
00702
00703 sprintf(cmd, "PRAGMA temp_store_directory = '%s';", tmpdir);
00704 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
00705 tmpdir = _free(tmpdir);
00706 }
00707 if (dbi->dbi_eflags & DB_EXCL) {
00708 int xx;
00709 sprintf(cmd, "PRAGMA locking_mode = EXCLUSIVE;");
00710 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
00711 }
00712 if (dbi->dbi_pagesize > 0) {
00713 int xx;
00714 sprintf(cmd, "PRAGMA cache_size = %d;", dbi->dbi_cachesize);
00715 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
00716 }
00717 if (dbi->dbi_cachesize > 0) {
00718 int xx;
00719 sprintf(cmd, "PRAGMA page_size = %d;", dbi->dbi_pagesize);
00720 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
00721 }
00722
00723
00724 sprintf(cmd,
00725 "SELECT name FROM 'sqlite_master' WHERE type='table' and name='%s';",
00726 dbi->dbi_subfile);
00727
00728 rc = sqlite3_get_table(sqldb->db, cmd,
00729 &scp->av, &scp->nr, &scp->nc, (char **)&scp->pzErrmsg);
00730
00731 if (rc)
00732 goto exit;
00733
00734 if (scp->nr < 1) {
00735 const char * valtype = "blob";
00736 const char * keytype;
00737
00738 switch (dbi->dbi_rpmtag) {
00739 case RPMDBI_PACKAGES:
00740 keytype = "int UNIQUE PRIMARY KEY";
00741 valtype = "blob";
00742 break;
00743 default:
00744 switch (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE) {
00745 case RPM_BIN_TYPE:
00746 default:
00747 keytype = "blob UNIQUE";
00748 break;
00749 case RPM_UINT8_TYPE:
00750 case RPM_UINT16_TYPE:
00751 case RPM_UINT32_TYPE:
00752 case RPM_UINT64_TYPE:
00753 keytype = "int UNIQUE";
00754 break;
00755 case RPM_STRING_TYPE:
00756 case RPM_STRING_ARRAY_TYPE:
00757 case RPM_I18NSTRING_TYPE:
00758 keytype = "text UNIQUE";
00759 break;
00760 }
00761 }
00762 if (_debug)
00763 fprintf(stderr, "\t%s(%d) type(%d) keytype %s\n", tagName(dbi->dbi_rpmtag), dbi->dbi_rpmtag, (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE), keytype);
00764 sprintf(cmd, "CREATE %sTABLE '%s' (key %s, value %s)",
00765 dbi->dbi_temporary ? "TEMPORARY " : "",
00766 dbi->dbi_subfile, keytype, valtype);
00767 rc = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
00768 if (rc)
00769 goto exit;
00770
00771 sprintf(cmd, "CREATE %sTABLE 'db_info' (endian TEXT)",
00772 dbi->dbi_temporary ? "TEMPORARY " : "");
00773 rc = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
00774 if (rc)
00775 goto exit;
00776
00777 sprintf(cmd, "INSERT INTO 'db_info' values('%u')", (unsigned)((union _dbswap *)&endian)->uc[0]);
00778 rc = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
00779 if (rc)
00780 goto exit;
00781 }
00782
00783 if (dbi->dbi_no_fsync) {
00784 int xx;
00785 sprintf(cmd, "PRAGMA synchronous = OFF;");
00786 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
00787 }
00788
00789 exit:
00790 if (rc)
00791 rpmlog(RPMLOG_WARNING, "Unable to initDB %s (%d)\n",
00792 scp->pzErrmsg, rc);
00793
00794 scp = scpFree(scp);
00795
00796 return rc;
00797 }
00798
00806 static int sql_cclose (dbiIndex dbi, DBC * dbcursor,
00807 unsigned int flags)
00808
00809
00810 {
00811 SCP_t scp = (SCP_t)dbcursor;
00812 int rc;
00813
00814 if (_debug)
00815 fprintf(stderr, "==> sql_cclose(%p)\n", scp);
00816
00817 if (scp->lkey)
00818 scp->lkey = _free(scp->lkey);
00819
00820 if (scp->ldata)
00821 scp->ldata = _free(scp->ldata);
00822
00823 enterChroot(dbi);
00824
00825 if (flags == DB_WRITECURSOR)
00826 rc = sql_commitTransaction(dbi, 1);
00827 else
00828 rc = sql_endTransaction(dbi);
00829
00830
00831 scp = scpFree(scp);
00832
00833
00834 leaveChroot(dbi);
00835
00836 return rc;
00837 }
00838
00845 static int sql_close( dbiIndex dbi, unsigned int flags)
00846
00847
00848 {
00849 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
00850 int rc = 0;
00851
00852 if (sqldb) {
00853 enterChroot(dbi);
00854
00855
00856 rc = sql_commitTransaction(dbi, 1);
00857
00858 (void) sqlite3_close(sqldb->db);
00859
00860 rpmlog(RPMLOG_DEBUG, D_("closed sql db %s\n"),
00861 dbi->dbi_subfile);
00862
00863 #if defined(MAYBE)
00864 if (dbi->dbi_temporary && !(dbi->dbi_eflags & DB_PRIVATE)) {
00865 const char * dbhome = NULL;
00866 urltype ut = urlPath(dbi->dbi_home, &dbhome);
00867 const char * dbfname = rpmGenPath(dbhome, dbi->dbi_file, NULL);
00868 int xx = (dbfname ? Unlink(dbfname) : 0);
00869 ut = ut; xx = xx;
00870 dbfname = _free(dbfname);
00871 }
00872 #endif
00873
00874 dbi->dbi_stats = _free(dbi->dbi_stats);
00875 dbi->dbi_file = _free(dbi->dbi_file);
00876 dbi->dbi_db = _free(dbi->dbi_db);
00877
00878 leaveChroot(dbi);
00879 }
00880
00881 dbi = _free(dbi);
00882
00883 return rc;
00884 }
00885
00892 static int sql_open(rpmdb rpmdb, rpmTag rpmtag, dbiIndex * dbip)
00893
00894
00895 {
00896
00897 extern struct _dbiVec sqlitevec;
00898
00899
00900 const char * urlfn = NULL;
00901 const char * root;
00902 const char * home;
00903 const char * dbhome;
00904 const char * dbfile;
00905 const char * dbfname;
00906 const char * sql_errcode;
00907 mode_t umask_safed = 0002;
00908 dbiIndex dbi;
00909 SQL_DB * sqldb;
00910 size_t len;
00911 int rc = 0;
00912 int xx;
00913
00914 if (dbip)
00915 *dbip = NULL;
00916
00917
00918
00919
00920
00921 if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
00922
00923 return 1;
00924
00925
00926
00927
00928
00929
00930 root = rpmdb->db_root;
00931 home = rpmdb->db_home;
00932
00933 dbi->dbi_root = root;
00934 dbi->dbi_home = home;
00935
00936 dbfile = tagName(dbi->dbi_rpmtag);
00937
00938 enterChroot(dbi);
00939
00940
00941
00942
00943
00944 {
00945 char * t;
00946 len = strlen(dbfile);
00947 t = xcalloc(len + 1, sizeof(*t));
00948 (void) stpcpy( t, dbfile );
00949 dbi->dbi_file = t;
00950
00951 dbi->dbi_subfile = t;
00952
00953 }
00954
00955 dbi->dbi_mode = O_RDWR;
00956
00957
00958
00959
00960
00961
00962 urlfn = rpmGenPath(NULL, home, NULL);
00963
00964 (void) urlPath(urlfn, &dbhome);
00965
00966
00967
00968
00969 (void) rpmioMkpath(dbhome, 0755, getuid(), getgid());
00970
00971 if (dbi->dbi_eflags & DB_PRIVATE)
00972 dbfname = xstrdup(":memory:");
00973 else
00974 dbfname = rpmGenPath(dbhome, dbi->dbi_file, NULL);
00975
00976 rpmlog(RPMLOG_DEBUG, D_("opening sql db %s (%s) mode=0x%x\n"),
00977 dbfname, dbi->dbi_subfile, dbi->dbi_mode);
00978
00979
00980 sqldb = xcalloc(1, sizeof(*sqldb));
00981
00982 sql_errcode = NULL;
00983 if (dbi->dbi_perms)
00984
00985 umask_safed = umask(~((mode_t)(dbi->dbi_perms)));
00986 xx = sqlite3_open(dbfname, &sqldb->db);
00987 if (dbi->dbi_perms) {
00988 if ((0644 & dbi->dbi_perms) != dbi->dbi_perms) {
00989
00990 (void) Chmod(dbfname, dbi->dbi_perms);
00991 }
00992 (void) umask(umask_safed);
00993 }
00994 if (xx != SQLITE_OK)
00995 sql_errcode = sqlite3_errmsg(sqldb->db);
00996
00997 if (sqldb->db)
00998 (void) sqlite3_busy_handler(sqldb->db, &sql_busy_handler, dbi);
00999
01000 sqldb->transaction = 0;
01001
01002 dbi->dbi_db = (DB *)sqldb;
01003
01004 if (sql_errcode != NULL) {
01005 rpmlog(RPMLOG_DEBUG, D_("Unable to open database: %s\n"), sql_errcode);
01006 rc = EINVAL;
01007 }
01008
01009
01010 if (rc == 0)
01011 rc = sql_initDB(dbi);
01012
01013 if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) {
01014 dbi->dbi_vec = &sqlitevec;
01015 *dbip = dbi;
01016 } else {
01017 (void) sql_close(dbi, 0);
01018 }
01019
01020 urlfn = _free(urlfn);
01021 dbfname = _free(dbfname);
01022
01023
01024 leaveChroot(dbi);
01025
01026
01027 return rc;
01028 }
01029
01036 static int sql_sync (dbiIndex dbi, unsigned int flags)
01037
01038
01039 {
01040 int rc = 0;
01041
01042 enterChroot(dbi);
01043 rc = sql_commitTransaction(dbi, 0);
01044 leaveChroot(dbi);
01045
01046 return rc;
01047 }
01048
01057 static int sql_copen (dbiIndex dbi, DB_TXN * txnid,
01058 DBC ** dbcp, unsigned int flags)
01059
01060
01061 {
01062 SCP_t scp = scpNew(dbi->dbi_db);
01063 DBC * dbcursor = (DBC *)scp;
01064 int rc = 0;
01065
01066 if (_debug)
01067 fprintf(stderr, "==> sql_copen(%s) tag %d type %d scp %p\n", tagName(dbi->dbi_rpmtag), dbi->dbi_rpmtag, (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE), scp);
01068
01069 enterChroot(dbi);
01070
01071
01072 if (flags == DB_WRITECURSOR)
01073 rc = sql_startTransaction(dbi);
01074
01075 if (dbcp)
01076 *dbcp = dbcursor;
01077 else
01078 (void) sql_cclose(dbi, dbcursor, 0);
01079
01080 leaveChroot(dbi);
01081
01082 return rc;
01083 }
01084
01094 static int sql_cdel (dbiIndex dbi, DBC * dbcursor, DBT * key,
01095 DBT * data, unsigned int flags)
01096
01097
01098 {
01099 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
01100 SCP_t scp = scpNew(dbi->dbi_db);
01101 int rc = 0;
01102
01103 dbg_keyval("sql_cdel", dbi, dbcursor, key, data, flags);
01104 enterChroot(dbi);
01105
01106 scp->cmd = sqlite3_mprintf("DELETE FROM '%q' WHERE key=? AND value=?;",
01107 dbi->dbi_subfile);
01108
01109 rc = sqlite3_prepare(sqldb->db, scp->cmd, (int)strlen(scp->cmd), &scp->pStmt, &scp->pzErrmsg);
01110 if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) prepare %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
01111 rc = sql_bind_key(dbi, scp, 1, key);
01112 if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) bind key %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
01113 rc = sql_bind_data(dbi, scp, 2, data);
01114 if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) bind data %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
01115
01116 rc = sql_step(dbi, scp);
01117 if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) sql_step rc %d\n", dbi->dbi_subfile, rc);
01118
01119 scp = scpFree(scp);
01120
01121 leaveChroot(dbi);
01122
01123 return rc;
01124 }
01125
01135 static int sql_cget (dbiIndex dbi, DBC * dbcursor, DBT * key,
01136 DBT * data, unsigned int flags)
01137
01138
01139 {
01140 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
01141 SCP_t scp = (SCP_t)dbcursor;
01142 int rc = 0;
01143 int ix;
01144
01145 assert(dbcursor != NULL);
01146 dbg_keyval("sql_cget", dbi, dbcursor, key, data, flags);
01147
01148 enterChroot(dbi);
01149
01150
01151
01152
01153
01154 if (_debug)
01155 fprintf(stderr, "\tcget(%s) scp %p rc %d flags %d av %p\n",
01156 dbi->dbi_subfile, scp, rc, flags, scp->av);
01157 if ( flags == DB_SET || scp->used == 0 ) {
01158 scp->used = 1;
01159 scp = scpReset(scp);
01160
01161
01162
01163
01164
01165
01166 if ( key->size == 0) {
01167 scp->all = 1;
01168
01169
01170
01171
01172
01173
01174
01175 assert(dbi->dbi_rpmtag == RPMDBI_PACKAGES);
01176
01177 switch (dbi->dbi_rpmtag) {
01178 case RPMDBI_PACKAGES:
01179 scp->cmd = sqlite3_mprintf("SELECT key FROM '%q' ORDER BY key;",
01180 dbi->dbi_subfile);
01181 break;
01182 default:
01183 scp->cmd = sqlite3_mprintf("SELECT key FROM '%q';",
01184 dbi->dbi_subfile);
01185 break;
01186 }
01187 rc = sqlite3_prepare(sqldb->db, scp->cmd, (int)strlen(scp->cmd), &scp->pStmt, &scp->pzErrmsg);
01188 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) sequential prepare %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
01189
01190 rc = sql_step(dbi, scp);
01191 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) sequential sql_step rc %d\n", dbi->dbi_subfile, rc);
01192
01193 scp = scpResetKeys(scp);
01194 scp->nkeys = scp->nr;
01195 scp->keys = xcalloc(scp->nkeys, sizeof(*scp->keys));
01196 for (ix = 0; ix < scp->nkeys; ix++) {
01197 scp->keys[ix] = xmalloc(sizeof(*scp->keys[0]));
01198 scp->keys[ix]->size = (u_int32_t) scp->avlen[ix+1];
01199 scp->keys[ix]->data = xmalloc(scp->keys[ix]->size);
01200 memcpy(scp->keys[ix]->data, scp->av[ix+1], scp->avlen[ix+1]);
01201 }
01202 } else {
01203
01204
01205
01206 scp = scpResetKeys(scp);
01207 scp->nkeys = 1;
01208 scp->keys = xcalloc(scp->nkeys, sizeof(*scp->keys));
01209 scp->keys[0] = xmalloc(sizeof(*scp->keys[0]));
01210 scp->keys[0]->size = key->size;
01211 scp->keys[0]->data = xmalloc(scp->keys[0]->size);
01212 memcpy(scp->keys[0]->data, key->data, key->size);
01213 }
01214
01215 scp = scpReset(scp);
01216
01217
01218 scp->cmd = sqlite3_mprintf("SELECT value FROM '%q' WHERE key=?;", dbi->dbi_subfile);
01219 rc = sqlite3_prepare(sqldb->db, scp->cmd, (int)strlen(scp->cmd), &scp->pStmt, &scp->pzErrmsg);
01220
01221 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) prepare %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
01222 }
01223
01224 scp = scpResetAv(scp);
01225
01226
01227 if ((scp->rx + 1) > scp->nkeys )
01228 rc = DB_NOTFOUND;
01229
01230 if (rc != 0)
01231 goto exit;
01232
01233
01234 rc = sql_bind_key(dbi, scp, 1, scp->keys[scp->rx]);
01235 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) key bind %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
01236
01237 rc = sql_step(dbi, scp);
01238 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) sql_step rc %d\n", dbi->dbi_subfile, rc);
01239
01240 rc = sqlite3_reset(scp->pStmt);
01241 if (rc) rpmlog(RPMLOG_WARNING, "reset %d\n", rc);
01242
01243
01244 assert(scp->nr < 2);
01245
01246 if (scp->nr == 0 && scp->all == 0)
01247 rc = DB_NOTFOUND;
01248
01249 if (rc != 0)
01250 goto exit;
01251
01252
01253 if (scp->all) {
01254
01255
01256 assert(scp->nr == 1);
01257
01258 if ( scp->lkey ) {
01259 scp->lkey = _free(scp->lkey);
01260 }
01261
01262 key->size = scp->keys[scp->rx]->size;
01263 key->data = xmalloc(key->size);
01264 if (! (key->flags & DB_DBT_MALLOC))
01265 scp->lkey = key->data;
01266
01267 (void) memcpy(key->data, scp->keys[scp->rx]->data, key->size);
01268 }
01269
01270
01271 switch (dbi->dbi_rpmtag) {
01272 default:
01273 if ( scp->ldata ) {
01274 scp->ldata = _free(scp->ldata);
01275 }
01276
01277 data->size = (u_int32_t) scp->avlen[1];
01278 data->data = xmalloc(data->size);
01279 if (! (data->flags & DB_DBT_MALLOC) )
01280 scp->ldata = data->data;
01281
01282 (void) memcpy(data->data, scp->av[1], data->size);
01283 }
01284
01285 scp->rx++;
01286
01287
01288 if (_debug)
01289 fprintf(stderr, "\tcget(%s) found key 0x%x (%d)\n", dbi->dbi_subfile,
01290 key->data == NULL ? 0 : *(unsigned int *)key->data, key->size);
01291 if (_debug)
01292 fprintf(stderr, "\tcget(%s) found data 0x%x (%d)\n", dbi->dbi_subfile,
01293 key->data == NULL ? 0 : *(unsigned int *)data->data, data->size);
01294
01295 exit:
01296 if (rc == DB_NOTFOUND) {
01297 if (_debug)
01298 fprintf(stderr, "\tcget(%s) not found\n", dbi->dbi_subfile);
01299 }
01300
01301 leaveChroot(dbi);
01302
01303 return rc;
01304 }
01305
01315 static int sql_cput (dbiIndex dbi, DBC * dbcursor, DBT * key,
01316 DBT * data, unsigned int flags)
01317
01318
01319 {
01320 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
01321 SCP_t scp = scpNew(dbi->dbi_db);
01322 int rc = 0;
01323
01324 dbg_keyval("sql_cput", dbi, dbcursor, key, data, flags);
01325
01326 enterChroot(dbi);
01327
01328 switch (dbi->dbi_rpmtag) {
01329 default:
01330 scp->cmd = sqlite3_mprintf("INSERT OR REPLACE INTO '%q' VALUES(?, ?);",
01331 dbi->dbi_subfile);
01332 rc = sqlite3_prepare(sqldb->db, scp->cmd, (int)strlen(scp->cmd), &scp->pStmt, &scp->pzErrmsg);
01333 if (rc) rpmlog(RPMLOG_WARNING, "cput(%s) prepare %s (%d)\n",dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
01334 rc = sql_bind_key(dbi, scp, 1, key);
01335 if (rc) rpmlog(RPMLOG_WARNING, "cput(%s) key bind %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
01336 rc = sql_bind_data(dbi, scp, 2, data);
01337 if (rc) rpmlog(RPMLOG_WARNING, "cput(%s) data bind %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
01338
01339 rc = sql_step(dbi, scp);
01340 if (rc) rpmlog(RPMLOG_WARNING, "cput(%s) sql_step rc %d\n", dbi->dbi_subfile, rc);
01341
01342 break;
01343 }
01344
01345 scp = scpFree(scp);
01346
01347 leaveChroot(dbi);
01348
01349 return rc;
01350 }
01351
01357 static int sql_byteswapped (dbiIndex dbi)
01358
01359
01360 {
01361 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
01362 SCP_t scp = scpNew(dbi->dbi_db);
01363 int sql_rc, rc = 0;
01364 union _dbswap db_endian;
01365
01366 enterChroot(dbi);
01367
01368
01369 sql_rc = sqlite3_get_table(sqldb->db, "SELECT endian FROM 'db_info';",
01370 &scp->av, &scp->nr, &scp->nc, (char **)&scp->pzErrmsg);
01371
01372
01373 if (sql_rc == 0 && scp->nr > 0) {
01374 assert(scp->av != NULL);
01375 db_endian.uc[0] = (unsigned char) strtol(scp->av[1], NULL, 10);
01376
01377 if ( db_endian.uc[0] == ((union _dbswap *)&endian)->uc[0] )
01378 rc = 0;
01379 else
01380 rc = 1;
01381
01382 } else {
01383 if ( sql_rc ) {
01384 rpmlog(RPMLOG_DEBUG, D_("db_info failed %s (%d)\n"),
01385 scp->pzErrmsg, sql_rc);
01386 }
01387 rpmlog(RPMLOG_WARNING, "Unable to determine DB endian.\n");
01388 }
01389
01390 scp = scpFree(scp);
01391
01392 leaveChroot(dbi);
01393
01394 return rc;
01395 }
01396
01397
01398
01399
01400
01401
01402
01403
01412 static int sql_associate (dbiIndex dbi, dbiIndex dbisecondary,
01413 int (*callback) (DB *, const DBT *, const DBT *, DBT *),
01414 unsigned int flags)
01415
01416 {
01417 if (_debug)
01418 fprintf(stderr, "*** sql_associate:\n");
01419 return EINVAL;
01420 }
01421
01430 static int sql_join (dbiIndex dbi, DBC ** curslist, DBC ** dbcp,
01431 unsigned int flags)
01432
01433
01434 {
01435 if (_debug)
01436 fprintf(stderr, "*** sql_join:\n");
01437 return EINVAL;
01438 }
01439
01448 static int sql_cdup (dbiIndex dbi, DBC * dbcursor, DBC ** dbcp,
01449 unsigned int flags)
01450
01451
01452 {
01453 if (_debug)
01454 fprintf(stderr, "*** sql_cdup:\n");
01455 return EINVAL;
01456 }
01457
01468 static int sql_cpget (dbiIndex dbi, DBC * dbcursor,
01469 DBT * key, DBT * pkey, DBT * data, unsigned int flags)
01470
01471
01472 {
01473 if (_debug)
01474 fprintf(stderr, "*** sql_cpget:\n");
01475 return EINVAL;
01476 }
01477
01486 static int sql_ccount (dbiIndex dbi, DBC * dbcursor,
01487 unsigned int * countp,
01488 unsigned int flags)
01489
01490
01491 {
01492 if (_debug)
01493 fprintf(stderr, "*** sql_ccount:\n");
01494 return EINVAL;
01495 }
01496
01503 static int sql_stat (dbiIndex dbi, unsigned int flags)
01504
01505
01506 {
01507 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
01508 SCP_t scp = scpNew(dbi->dbi_db);
01509 int rc = 0;
01510 long nkeys = -1;
01511
01512 enterChroot(dbi);
01513
01514 dbi->dbi_stats = _free(dbi->dbi_stats);
01515
01516
01517 dbi->dbi_stats = xcalloc(1, sizeof(DB_HASH_STAT));
01518
01519
01520 scp->cmd = sqlite3_mprintf("SELECT COUNT('key') FROM '%q';", dbi->dbi_subfile);
01521
01522 rc = sqlite3_get_table(sqldb->db, scp->cmd,
01523 &scp->av, &scp->nr, &scp->nc, (char **)&scp->pzErrmsg);
01524
01525
01526 if ( rc == 0 && scp->nr > 0) {
01527 assert(scp->av != NULL);
01528 nkeys = strtol(scp->av[1], NULL, 10);
01529
01530 rpmlog(RPMLOG_DEBUG, D_(" stat on %s nkeys %ld\n"),
01531 dbi->dbi_subfile, nkeys);
01532 } else {
01533 if ( rc ) {
01534 rpmlog(RPMLOG_DEBUG, D_("stat failed %s (%d)\n"),
01535 scp->pzErrmsg, rc);
01536 }
01537 }
01538
01539 if (nkeys < 0)
01540 nkeys = 4096;
01541
01542 ((DB_HASH_STAT *)(dbi->dbi_stats))->hash_nkeys = nkeys;
01543
01544 scp = scpFree(scp);
01545
01546 leaveChroot(dbi);
01547
01548 return rc;
01549 }
01550
01551
01552
01553
01554
01555
01556
01557 struct _dbiVec sqlitevec = {
01558 0, 0, 0,
01559 sql_open,
01560 sql_close,
01561 sql_sync,
01562 sql_associate,
01563 sql_join,
01564 sql_copen,
01565 sql_cclose,
01566 sql_cdup,
01567 sql_cdel,
01568 sql_cget,
01569 sql_cpget,
01570 sql_cput,
01571 sql_ccount,
01572 sql_byteswapped,
01573 sql_stat
01574 };
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584