rpmdb/sqlite.c

Go to the documentation of this file.
00001 /*@-bounds@*/
00002 /*@-mustmod@*/
00003 /*@-paramuse@*/
00004 /*@-globuse@*/
00005 /*@-moduncon@*/
00006 /*@-noeffectuncon@*/
00007 /*@-compdef@*/
00008 /*@-compmempass@*/
00009 /*@-branchstate@*/
00010 /*@-modfilesystem@*/
00011 /*@-evalorderuncon@*/
00012 
00013 /*
00014  * sqlite.c
00015  * sqlite interface for rpmdb
00016  *
00017  * Author: Mark Hatle <mhatle@mvista.com> or <fray@kernel.crashing.org>
00018  * Copyright (c) 2004 MontaVista Software, Inc.
00019  *
00020  * This program is free software; you can redistribute it and/or
00021  * modify it under the terms of the GNU General Public License
00022  * or GNU Library General Public License, at your option,
00023  * as published by the Free Software Foundation; either version 2
00024  * of the License, or (at your option) any later version.
00025  *
00026  * This program is distributed in the hope that it will be useful,
00027  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00028  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00029  * GNU General Public License for more details.
00030  *
00031  * You should have received a copy of the GNU General Public License
00032  * and GNU Library Public License along with this program;
00033  * if not, write to the Free Software Foundation, Inc., 
00034  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00035  *
00036  */
00037 
00038 #include "system.h"
00039 
00040 #include <rpmlib.h>
00041 #include <rpmmacro.h>
00042 #include <rpmurl.h>     /* XXX urlPath proto */
00043 
00044 #include <rpmdb.h>
00045 
00046 #include "sqlite3.h"
00047 
00048 #include "debug.h"
00049 
00050 /*@access rpmdb @*/
00051 /*@access dbiIndex @*/
00052 
00053 /*@unchecked@*/
00054 static int _debug = 0;
00055 
00056 /* Define the things normally in a header... */
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;               /* Database pointer */
00062     int transaction;            /* Do we have a transaction open? */
00063 };
00064 
00065 struct _sql_dbcursor_s {
00066     DB *dbp;
00067 
00068 /*@only@*/ /*@relnull@*/
00069     char * cmd;                 /* SQL command string */
00070 /*@only@*/ /*@relnull@*/
00071     sqlite3_stmt *pStmt;        /* SQL byte code */
00072     const char * pzErrmsg;      /* SQL error msg */
00073 
00074   /* Table -- result of query */
00075 /*@only@*/ /*@null@*/
00076     char ** av;                 /* item ptrs */
00077 /*@only@*/ /*@null@*/
00078     int * avlen;                /* item sizes */
00079     int nalloc;
00080     int ac;                     /* no. of items */
00081     int rx;                     /* Which row are we on? 1, 2, 3 ... */
00082     int nr;                     /* no. of rows */
00083     int nc;                     /* no. of columns */
00084 
00085     int all;                    /* sequential iteration cursor */
00086     DBT ** keys;                /* array of package keys */
00087     int nkeys;
00088 
00089     int count;
00090 
00091     void * lkey;                /* Last key returned */
00092     void * ldata;               /* Last data returned */
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 /*@unchecked@*/
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        /* Nothing to do, was not already in chroot */
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        /* Nothing to do, not in chroot */
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, /*@null@*/ 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     /* XXX FIXME: ptr alignment is fubar here. */
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 /*@only@*/ 
00195 static SCP_t scpResetKeys(/*@only@*/ SCP_t scp)
00196         /*@modifies scp @*/
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 /*@only@*/ 
00215 static SCP_t scpResetAv(/*@only@*/ SCP_t scp)
00216         /*@modifies scp @*/
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             /* Clean up SCP_t used by sqlite3_get_table(). */
00227             sqlite3_free_table(scp->av);
00228             scp->av = NULL;
00229             scp->nalloc = 0;
00230         } else {
00231             /* Clean up SCP_t used by sql_step(). */
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 /*@only@*/ 
00252 static SCP_t scpReset(/*@only@*/ SCP_t scp)
00253         /*@modifies scp @*/
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 /*@null@*/
00280 static SCP_t scpFree(/*@only@*/ SCP_t scp)
00281         /*@modifies scp @*/
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         /*@modifies scp @*/
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     /* XXX scp->nc = need = scp->nalloc = 0 case forces + 1 here */
00329     if (!scp->ac && !need && !scp->nalloc)
00330         need++;
00331    
00332     if (scp->ac + need >= scp->nalloc) {
00333         /* XXX +4 is bogus, was +1 */
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 /*@-infloopsuncon@*/
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             /*@switchbreak@*/ break;
00358         case SQLITE_ROW:
00359             if (scp->av != NULL)
00360             for (i = 0; i < scp->nc; i++) {
00361                 /* Expand the row array for new elements */
00362                 if (scp->ac + need >= scp->nalloc) {
00363                     /* XXX +4 is bogus, was +1 */
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); /* Byte swap?! */
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); /* Byte swap?! */
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             /*@switchbreak@*/ break;
00442         case SQLITE_BUSY:
00443             fprintf(stderr, "sqlite3_step: BUSY %d\n", rc);
00444             /*@switchbreak@*/ 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             /*@switchbreak@*/ break;
00452         case SQLITE_MISUSE:
00453             fprintf(stderr, "sqlite3_step: MISUSE %d\n", rc);
00454             loop = 0;
00455             /*@switchbreak@*/ break;
00456         default:
00457             fprintf(stderr, "sqlite3_step: rc %d\n", rc);
00458             loop = 0;
00459             /*@switchbreak@*/ break;
00460         }
00461     }
00462 /*@=infloopsuncon@*/
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         /*@modifies scp @*/
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         }   /*@innerbreak@*/ 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                 /*@innerbreak@*/ 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); /* Byte swap?! */
00503                 memcpy(&i, key->data, sizeof(i));
00504                 rc = sqlite3_bind_int(scp->pStmt, pos, i);
00505             }   /*@innerbreak@*/ break;
00506             case RPM_INT16_TYPE:
00507             {   unsigned short i;
00508 assert(key->size == sizeof(int_16));
00509 assert(dbiByteSwapped(dbi) == 0); /* Byte swap?! */
00510                 memcpy(&i, key->data, sizeof(i));
00511                 rc = sqlite3_bind_int(scp->pStmt, pos, i);
00512             }   /*@innerbreak@*/ break;
00513             case RPM_INT32_TYPE:
00514 /*          case RPM_INT64_TYPE: */   
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             }   /*@innerbreak@*/ 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                 /*@innerbreak@*/ 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         /*@modifies scp @*/
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  * Transaction support
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     /* XXX:  Transaction Support */
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     /* XXX:  Transaction Support */
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     /* XXX:  Transactions */
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       /* Start a new transaction if we were in the middle of one */
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 /*@-castexpose@*/
00628     dbiIndex dbi = (dbiIndex) dbi_void;
00629 /*@=castexpose@*/
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     /* Check if the table exists... */
00655     sprintf(cmd,
00656         "SELECT name FROM 'sqlite_master' WHERE type='table' and name='%s';",
00657                 dbi->dbi_subfile);
00658 /*@-nullstate@*/
00659     rc = sqlite3_get_table(sqldb->db, cmd,
00660         &scp->av, &scp->nr, &scp->nc, (char **)&scp->pzErrmsg);
00661 /*@=nullstate@*/
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                 /*@innerbreak@*/ break;
00681             case RPM_CHAR_TYPE:
00682             case RPM_INT8_TYPE:
00683             case RPM_INT16_TYPE:
00684             case RPM_INT32_TYPE:
00685 /*          case RPM_INT64_TYPE: */
00686                 keytype = "int UNIQUE";
00687                 /*@innerbreak@*/ break;
00688             case RPM_STRING_TYPE:
00689             case RPM_STRING_ARRAY_TYPE:
00690             case RPM_I18NSTRING_TYPE:
00691                 keytype = "text UNIQUE";
00692                 /*@innerbreak@*/ 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, /*@only@*/ DBC * dbcursor,
00738                 unsigned int flags)
00739         /*@globals fileSystem @*/
00740         /*@modifies dbi, *dbcursor, fileSystem @*/
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 /*@-kepttrans@*/
00762     scp = scpFree(scp);
00763 /*@=kepttrans@*/
00764 
00765 leaveChroot(dbi);
00766 
00767     return rc;
00768 }
00769 
00776 static int sql_close(/*@only@*/ dbiIndex dbi, unsigned int flags)
00777         /*@globals fileSystem @*/
00778         /*@modifies dbi, fileSystem @*/
00779 {
00780     SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
00781     int rc = 0;
00782 
00783     if (sqldb) {
00784 enterChroot(dbi);
00785 
00786         /* Commit, don't open a new one */
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, /*@out@*/ dbiIndex * dbip)
00813         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00814         /*@modifies *dbip, rpmGlobalMacroContext, fileSystem, internalState @*/
00815 {
00816 /*@-nestedextern -shadow @*/
00817     extern struct _dbiVec sqlitevec;
00818 /*@=nestedextern -shadow @*/
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      * Parse db configuration parameters.
00838      */
00839     /*@-mods@*/
00840     if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
00841         /*@-nullstate@*/
00842         return 1;
00843         /*@=nullstate@*/
00844     /*@=mods@*/
00845 
00846    /*
00847      * Get the prefix/root component and directory path
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      * Make a copy of the tagName result..
00861      * use this for the filename and table name
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 /*@-kepttrans@*/ /* WRONG */
00870       dbi->dbi_subfile = t;
00871 /*@=kepttrans@*/
00872     }
00873 
00874     dbi->dbi_mode=O_RDWR;
00875        
00876     /*
00877      * Either the root or directory components may be a URL. Concatenate,
00878      * convert the URL to a path, and add the name of the file.
00879      */
00880     /*@-mods@*/
00881     urlfn = rpmGenPath(NULL, home, NULL);
00882     /*@=mods@*/
00883     (void) urlPath(urlfn, &dbhome);
00884 
00885     /* 
00886      * Create the /var/lib/rpm directory if it doesn't exist (root only).
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     /* Open the Database */
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;     /* Initialize no current transactions */
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     /* initialize table */
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         /*@globals fileSystem @*/
00942         /*@modifies fileSystem @*/
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, /*@null@*/ DB_TXN * txnid,
00962                 /*@out@*/ DBC ** dbcp, unsigned int flags)
00963         /*@globals fileSystem @*/
00964         /*@modifies dbi, *txnid, *dbcp, fileSystem @*/
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     /* If we're going to write, start a transaction (lock the DB) */
00976     if (flags == DB_WRITECURSOR)
00977         rc = sql_startTransaction(dbi);
00978 
00979     if (dbcp)
00980         /*@-onlytrans@*/ *dbcp = dbcursor; /*@=onlytrans@*/
00981     else
00982         /*@-kepttrans -nullstate @*/ (void) sql_cclose(dbi, dbcursor, 0); /*@=kepttrans =nullstate @*/
00983 
00984 leaveChroot(dbi);
00985      
00986     return rc;
00987 }
00988 
00998 static int sql_cdel (dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key,
00999                 DBT * data, unsigned int flags)
01000         /*@globals fileSystem @*/
01001         /*@modifies *dbcursor, fileSystem @*/
01002 {
01003 /*@i@*/    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, /*@null@*/ DBC * dbcursor, DBT * key,
01040                 DBT * data, unsigned int flags)
01041         /*@globals fileSystem @*/
01042         /*@modifies dbi, dbcursor, *key, *data, fileSystem @*/
01043 {
01044 /*@i@*/    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      * First determine if this is a new scan or existing scan
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; /* Signal this scp as now in use... */
01062         scp = scpReset(scp);    /* Free av and avlen, reset counters.*/
01063 
01064 /* XXX: Should we also reset the key table here?  Can you re-use a cursor? */
01065 
01066         /*
01067          * If we're scanning everything, load the iterator key table
01068          */
01069         if ( key->size == 0) {
01070             scp->all = 1;
01071 
01072 /* 
01073  * The only condition not dealt with is if there are multiple identical keys.  This can lead
01074  * to later iteration confusion.  (It may return the same value for the multiple keys.)
01075  */
01076 
01077 /* Only RPMDBI_PACKAGES is supposed to be iterating, and this is guarenteed to be unique */
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                 /*@innerbreak@*/ break;
01085             default:
01086                 scp->cmd = sqlite3_mprintf("SELECT key FROM '%q';",
01087                     dbi->dbi_subfile);
01088                 /*@innerbreak@*/ 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              * We're only scanning ONE element
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);    /* reset */
01119 
01120         /* Prepare SQL statement to retrieve the value for the current key */
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);      /* Free av and avlen, reset counters.*/
01128 
01129     /* Now continue with a normal retrive based on key */
01130     if ((scp->rx + 1) > scp->nkeys )
01131         rc = DB_NOTFOUND; /* At the end of the list */
01132 
01133     if (rc != 0)
01134         goto exit;
01135 
01136     /* Bind key to prepared statement */
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 /* 1 key should return 0 or 1 row/value */
01147 assert(scp->nr < 2);
01148 
01149     if (scp->nr == 0 && scp->all == 0)
01150         rc = DB_NOTFOUND; /* No data for that key found! */
01151 
01152     if (rc != 0)
01153         goto exit;
01154 
01155     /* If we're looking at the whole db, return the key */
01156     if (scp->all) {
01157 
01158 /* To get this far there has to be _1_ key returned! (protect against dup keys) */
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     /* Construct and return the data element (element 0 is "value", 1 is _THE_ value)*/
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     /* XXX FIXME: ptr alignment is fubar here. */
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, /*@null@*/ DBC * dbcursor, DBT * key,
01219                         DBT * data, unsigned int flags)
01220         /*@globals fileSystem @*/
01221         /*@modifies *dbcursor, fileSystem @*/
01222 {
01223 /*@i@*/    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         /*@globals fileSystem @*/
01262         /*@modifies fileSystem @*/
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 /*@-nullstate@*/
01272     sql_rc = sqlite3_get_table(sqldb->db, "SELECT endian FROM 'db_info';",
01273         &scp->av, &scp->nr, &scp->nc, (char **)&scp->pzErrmsg);
01274 /*@=nullstate@*/
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; /* Native endian */
01282         else
01283             rc = 1; /* swapped */
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  *  All of the following are not implemented!
01303  *  they are not used by the rest of the system
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, /*@out@*/ DBC ** dbcp,
01334                 unsigned int flags)
01335         /*@globals fileSystem @*/
01336         /*@modifies dbi, *dbcp, fileSystem @*/
01337 {
01338 if (_debug)
01339 fprintf(stderr, "*** %s:\n", __FUNCTION__);
01340     return EINVAL;
01341 }
01342 
01351 static int sql_cdup (dbiIndex dbi, DBC * dbcursor, /*@out@*/ DBC ** dbcp,
01352                 unsigned int flags)
01353         /*@globals fileSystem @*/
01354         /*@modifies dbi, *dbcp, fileSystem @*/
01355 {
01356 if (_debug)
01357 fprintf(stderr, "*** %s:\n", __FUNCTION__);
01358     return EINVAL;
01359 }
01360 
01371 static int sql_cpget (dbiIndex dbi, /*@null@*/ DBC * dbcursor,
01372                 DBT * key, DBT * pkey, DBT * data, unsigned int flags)
01373         /*@globals fileSystem @*/
01374         /*@modifies *dbcursor, *key, *pkey, *data, fileSystem @*/
01375 {
01376 if (_debug)
01377 fprintf(stderr, "*** %s:\n", __FUNCTION__);
01378     return EINVAL;
01379 }
01380 
01389 static int sql_ccount (dbiIndex dbi, /*@unused@*/ DBC * dbcursor,   
01390                 /*@unused@*/ /*@out@*/ unsigned int * countp,
01391                 /*@unused@*/ unsigned int flags)
01392         /*@globals fileSystem @*/
01393         /*@modifies *dbcursor, fileSystem @*/
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         /*@globals fileSystem @*/
01408         /*@modifies dbi, fileSystem @*/
01409 {
01410 /*@i@*/    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 /*@-sizeoftype@*/
01420     dbi->dbi_stats = xcalloc(1, sizeof(DB_HASH_STAT));
01421 /*@=sizeoftype@*/
01422 
01423     scp->cmd = sqlite3_mprintf("SELECT COUNT('key') FROM '%q';", dbi->dbi_subfile);
01424 /*@-nullstate@*/
01425     rc = sqlite3_get_table(sqldb->db, scp->cmd,
01426                 &scp->av, &scp->nr, &scp->nc, (char **)&scp->pzErrmsg);
01427 /*@=nullstate@*/
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;  /* Good high value */
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 /* Major, minor, patch version of DB.. we're not using db.. so set to 0 */
01455 /* open, close, sync, associate, join */
01456 /* cursor_open, cursor_close, cursor_dup, cursor_delete, cursor_get, */
01457 /* cursor_pget?, cursor_put, cursor_count */
01458 /* db_bytewapped, stat */
01459 /*@observer@*/ /*@unchecked@*/
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 /*@=evalorderuncon@*/
01480 /*@=modfilesystem@*/
01481 /*@=branchstate@*/
01482 /*@=compmempass@*/
01483 /*@=compdef@*/
01484 /*@=moduncon@*/
01485 /*@=noeffectuncon@*/
01486 /*@=globuse@*/
01487 /*@=paramuse@*/
01488 /*@=mustmod@*/
01489 /*@=bounds@*/

Generated on Tue Feb 19 22:26:35 2008 for rpm by  doxygen 1.5.1