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