rpm  5.4.15
sqlite.c
Go to the documentation of this file.
1 /*@-mustmod@*/
2 /*@-paramuse@*/
3 /*@-globuse@*/
4 /*@-moduncon@*/
5 /*@-noeffectuncon@*/
6 /*@-compdef@*/
7 /*@-compmempass@*/
8 /*@-modfilesystem@*/
9 /*@-evalorderuncon@*/
10 
11 /*
12  * sqlite.c
13  * sqlite interface for rpmdb
14  *
15  * Author: Mark Hatle <mhatle@mvista.com> or <fray@kernel.crashing.org>
16  * Copyright (c) 2004 MontaVista Software, Inc.
17  *
18  * This program is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU General Public License
20  * or GNU Library General Public License, at your option,
21  * as published by the Free Software Foundation; either version 2
22  * of the License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * and GNU Library Public License along with this program;
31  * if not, write to the Free Software Foundation, Inc.,
32  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33  *
34  */
35 
36 #include "system.h"
37 
38 #include <sqlite3.h>
39 
40 #define _RPMSQL_INTERNAL
41 #include <rpmsql.h>
42 
43 #include <rpmlog.h>
44 #include <rpmmacro.h>
45 #include <rpmurl.h> /* XXX urlPath proto */
46 
47 #include <rpmtag.h>
48 #define _RPMDB_INTERNAL
49 #include <rpmdb.h>
50 
51 #include "debug.h"
52 
53 /* XXX retrofit the *BSD typedef for the deprived. */
54 #if defined(__QNXNTO__)
55 typedef rpmuint32_t u_int32_t;
56 #endif
57 
58 #if defined(__LCLINT__)
59 #define UINT32_T u_int32_t
60 #else
61 #define UINT32_T uint32_t
62 #endif
63 
64 /*@access rpmdb @*/
65 /*@access dbiIndex @*/
66 
67 /*@unchecked@*/
68 int _sqldb_debug = 0;
69 
70 #define SQLDBDEBUG(_dbi, _list) \
71  if (((_dbi) && (_dbi)->dbi_debug) || (_sqldb_debug)) fprintf _list
72 
73 /* =================================================================== */
74 /*@-redef@*/
75 typedef struct key_s {
76  uint32_t v;
77 /*@observer@*/
78  const char *n;
79 } KEY;
80 /*@=redef@*/
81 
82 /*@observer@*/
83 static const char * tblName(uint32_t v, KEY * tbl, size_t ntbl)
84  /*@*/
85 {
86  const char * n = NULL;
87  static char buf[32];
88  size_t i;
89 
90  for (i = 0; i < ntbl; i++) {
91  if (v != tbl[i].v)
92  continue;
93  n = tbl[i].n;
94  break;
95  }
96  if (n == NULL) {
97  (void) snprintf(buf, sizeof(buf), "0x%x", (unsigned)v);
98  n = buf;
99  }
100  return n;
101 }
102 
103 static const char * fmtBits(uint32_t flags, KEY tbl[], size_t ntbl, char *t)
104  /*@modifies t @*/
105 {
106  char pre = '<';
107  char * te = t;
108  int i;
109 
110  sprintf(t, "0x%x", (unsigned)flags);
111  te = t;
112  te += strlen(te);
113  for (i = 0; i < 32; i++) {
114  uint32_t mask = (1 << i);
115  const char * name;
116 
117  if (!(flags & mask))
118  continue;
119 
120  name = tblName(mask, tbl, ntbl);
121  *te++ = pre;
122  pre = ',';
123  te = stpcpy(te, name);
124  }
125  if (pre == ',') *te++ = '>';
126  *te = '\0';
127  return t;
128 }
129 #define _DBT_ENTRY(_v) { DB_DBT_##_v, #_v, }
130 /*@unchecked@*/ /*@observer@*/
131 static KEY DBTflags[] = {
132  _DBT_ENTRY(MALLOC),
133  _DBT_ENTRY(REALLOC),
134  _DBT_ENTRY(USERMEM),
135  _DBT_ENTRY(PARTIAL),
136  _DBT_ENTRY(APPMALLOC),
137  _DBT_ENTRY(MULTIPLE),
138 #if defined(DB_DBT_READONLY) /* XXX db-5.2.28 */
139  _DBT_ENTRY(READONLY),
140 #endif
141 };
142 #undef _DBT_ENTRY
143 /*@unchecked@*/
144 static size_t nDBTflags = sizeof(DBTflags) / sizeof(DBTflags[0]);
145 /*@observer@*/
146 static char * fmtDBT(const DBT * K, char * te)
147  /*@modifies te @*/
148 {
149  static size_t keymax = 35;
150  int unprintable;
151  uint32_t i;
152 
153  sprintf(te, "%p[%u]\t", K->data, (unsigned)K->size);
154  te += strlen(te);
155  (void) fmtBits(K->flags, DBTflags, nDBTflags, te);
156  te += strlen(te);
157  if (K->data && K->size > 0) {
158  uint8_t * _u;
159  size_t _nu;
160 
161  /* Grab the key data/size. */
162  if (K->flags & DB_DBT_MULTIPLE) {
163  DBT * _K = K->data;
164  _u = _K->data;
165  _nu = _K->size;
166  } else {
167  _u = K->data;
168  _nu = K->size;
169  }
170  /* Verify if data is a string. */
171  unprintable = 0;
172  for (i = 0; i < _nu; i++)
173  unprintable |= !xisprint(_u[i]);
174 
175  /* Display the data. */
176  if (!unprintable) {
177  size_t nb = (_nu < keymax ? _nu : keymax);
178  char * ellipsis = (_nu < keymax ? "" : "...");
179  sprintf(te, "\t\"%.*s%s\"", (int)nb, (char *)_u, ellipsis);
180  } else {
181  switch (_nu) {
182  default: break;
183  case 4: sprintf(te, "\t0x%08x", (unsigned)*(uint32_t *)_u); break;
184  }
185  }
186 
187  te += strlen(te);
188  *te = '\0';
189  }
190  return te;
191 }
192 /*@observer@*/
193 static const char * fmtKDR(const DBT * K, const DBT * P, const DBT * D, const DBT * R)
194  /*@*/
195 {
196  static char buf[BUFSIZ];
197  char * te = buf;
198 
199  if (K) {
200  te = stpcpy(te, "\n\t key: ");
201  te = fmtDBT(K, te);
202  }
203  if (P) {
204  te = stpcpy(te, "\n\t pkey: ");
205  te = fmtDBT(P, te);
206  }
207  if (D) {
208  te = stpcpy(te, "\n\t data: ");
209  te = fmtDBT(D, te);
210  }
211  if (R) {
212  te = stpcpy(te, "\n\t res: ");
213  te = fmtDBT(R, te);
214  }
215  *te = '\0';
216 
217  return buf;
218 }
219 #define _KEYDATA(_K, _P, _D, _R) fmtKDR(_K, _P, _D, _R)
220 
221 /* =================================================================== */
222 static int Xcvtdberr(/*@unused@*/ dbiIndex dbi, const char * msg,
223  int error, int printit,
224  const char * func, const char * fn, unsigned ln)
225  /*@globals fileSystem @*/
226  /*@modifies fileSystem @*/
227 {
228  int rc = error;
229 
230  if (printit && rc)
231  switch (rc) {
232  case SQLITE_DONE:
233  break; /* Filter out valid returns. */
234  default:
235  { rpmsql sql = (rpmsql) dbi->dbi_db;
236  sqlite3 * sqlI = (sqlite3 *) sql->I;
237  const char * errmsg = dbi != NULL
238  ? sqlite3_errmsg(sqlI)
239  : "";
240  rpmlog(RPMLOG_ERR, "%s:%s:%u: %s(%d): %s\n",
241  func, fn, ln, msg, rc, errmsg);
242  } break;
243  }
244 
245  return rc;
246 }
247 #define cvtdberr(_dbi, _msg, _error) \
248  Xcvtdberr(_dbi, _msg, _error, _sqldb_debug, __FUNCTION__, __FILE__, __LINE__)
249 
250 /* =================================================================== */
251 struct _sql_dbcursor_s; typedef struct _sql_dbcursor_s *SCP_t;
254  /* XXX FIXME: chain back to the sqlite3 * handle. */
255 
256 /*@only@*/ /*@relnull@*/
257  char * cmd; /* SQL command string */
258 /*@only@*/ /*@relnull@*/
259  sqlite3_stmt *pStmt; /* SQL byte code */
260  char * pzErrmsg; /* SQL error msg */
261 
262  /* Table -- result of query */
263 /*@only@*/ /*@relnull@*/
264  char ** av; /* item ptrs */
265 /*@only@*/ /*@relnull@*/
266  size_t * avlen; /* item sizes */
267  int nalloc;
268  int ac; /* no. of items */
269  int rx; /* Which row are we on? 1, 2, 3 ... */
270  int nr; /* no. of rows */
271  int nc; /* no. of columns */
272 
273  int all; /* sequential iteration cursor */
274 /*@relnull@*/
275  DBT ** keys; /* array of package keys */
276  int nkeys;
277 
278  int count;
279 
280 /*@null@*/
281  void * lkey; /* Last key returned */
282 /*@null@*/
283  void * ldata; /* Last data returned */
284 
285  int used;
286 #if defined(__LCLINT__)
287 /*@refs@*/
288  int nrefs;
289 #endif
290 };
291 
292 /*==============================================================*/
293 int _scp_debug = 0;
294 
295 #define SCPDEBUG(_dbi, _list) if (_scp_debug) fprintf _list
296 
302 /*@unused@*/ /*@null@*/
303 SCP_t scpUnlink (/*@killref@*/ /*@only@*/ /*@null@*/ SCP_t scp)
304  /*@modifies scp @*/;
305 #define scpUnlink(_scp) \
306  ((SCP_t)rpmioUnlinkPoolItem((rpmioItem)(_scp), __FUNCTION__, __FILE__, __LINE__))
307 
313 /*@unused@*/ /*@newref@*/ /*@null@*/
314 SCP_t scpLink (/*@null@*/ SCP_t scp)
315  /*@modifies scp @*/;
316 #define scpLink(_scp) \
317  ((SCP_t)rpmioLinkPoolItem((rpmioItem)(_scp), __FUNCTION__, __FILE__, __LINE__))
318 
324 /*@null@*/
325 SCP_t scpFree(/*@killref@*/ /*@null@*/SCP_t scp)
326  /*@globals fileSystem @*/
327  /*@modifies scp, fileSystem @*/;
328 #define scpFree(_scp) \
329  ((SCP_t)rpmioFreePoolItem((rpmioItem)(_scp), __FUNCTION__, __FILE__, __LINE__))
330 
331 static void dbg_scp(void *ptr)
332  /*@globals stderr, fileSystem @*/
333  /*@modifies stderr, fileSystem @*/
334 {
335  SCP_t scp = ptr;
336 
337 if (_scp_debug)
338 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);
339 
340 }
341 
342 static void dbg_keyval(const char * msg, dbiIndex dbi, /*@null@*/ DBC * dbcursor,
343  DBT * key, DBT * data, unsigned int flags)
344  /*@globals stderr, fileSystem @*/
345  /*@modifies stderr, fileSystem @*/
346 {
347 
348 if (!_scp_debug) return;
349 
350  fprintf(stderr, "%s on %s (%p,%p,%p,0x%x)", msg, dbi->dbi_subfile, dbcursor, key, data, flags);
351 
352  /* XXX FIXME: ptr alignment is fubar here. */
353  if (key != NULL && key->data != NULL) {
354  fprintf(stderr, " key 0x%x[%d]", *(unsigned int *)key->data, key->size);
355  if (dbi->dbi_rpmtag == RPMTAG_NAME)
356  fprintf(stderr, " \"%s\"", (const char *)key->data);
357  }
358  if (data != NULL && data->data != NULL)
359  fprintf(stderr, " data 0x%x[%d]", *(unsigned int *)data->data, data->size);
360 
361  fprintf(stderr, "\n");
362  if (dbcursor != NULL)
363  dbg_scp(dbcursor);
364 }
365 
366 /*@only@*/
367 static SCP_t scpResetKeys(/*@only@*/ SCP_t scp)
368  /*@modifies scp @*/
369 {
370  int ix;
371 
372 #if 0
373 SCPDEBUG(NULL, (stderr, "--> %s(%p)\n", __FUNCTION__, scp));
374 dbg_scp(scp);
375 #endif
376 
377  for ( ix =0 ; ix < scp->nkeys ; ix++ ) {
378  scp->keys[ix]->data = _free(scp->keys[ix]->data);
379 /*@-unqualifiedtrans@*/
380  scp->keys[ix] = _free(scp->keys[ix]);
381 /*@=unqualifiedtrans@*/
382  }
383  scp->keys = _free(scp->keys);
384  scp->nkeys = 0;
385 
386  return scp;
387 }
388 
389 /*@only@*/
390 static SCP_t scpResetAv(/*@only@*/ SCP_t scp)
391  /*@modifies scp @*/
392 {
393  int xx;
394 
395 #if 0
396 SCPDEBUG(NULL, (stderr, "--> %s(%p)\n", __FUNCTION__, scp));
397 dbg_scp(scp);
398 #endif
399 
400  if (scp->av != NULL) {
401  if (scp->nalloc <= 0) {
402  /* Clean up SCP_t used by sqlite3_get_table(). */
403  sqlite3_free_table(scp->av);
404  scp->av = NULL;
405  scp->nalloc = 0;
406  } else {
407  /* Clean up SCP_t used by sql_step(). */
408  for (xx = 0; xx < scp->ac; xx++)
409  scp->av[xx] = _free(scp->av[xx]);
410  if (scp->av != NULL)
411  memset(scp->av, 0, scp->nalloc * sizeof(*scp->av));
412  if (scp->avlen != NULL)
413  memset(scp->avlen, 0, scp->nalloc * sizeof(*scp->avlen));
414  scp->av = _free(scp->av);
415  scp->avlen = _free(scp->avlen);
416  scp->nalloc = 0;
417  }
418  } else
419  scp->nalloc = 0;
420  scp->ac = 0;
421  scp->nr = 0;
422  scp->nc = 0;
423 
424  return scp;
425 }
426 
427 /*@only@*/
428 static SCP_t scpReset(/*@only@*/ SCP_t scp)
429  /*@modifies scp @*/
430 {
431  int xx;
432 
433 #if 0
434 SCPDEBUG(NULL, (stderr, "--> %s(%p)\n", __FUNCTION__, scp));
435 dbg_scp(scp);
436 #endif
437 
438 #ifndef DYING
439  if (scp->cmd) {
440  sqlite3_free(scp->cmd);
441  scp->cmd = NULL;
442  }
443 #else
444  scp->cmd = _free(scp->cmd);
445 #endif
446 
447  if (scp->pStmt) {
448  xx = cvtdberr(NULL, "sqlite3_reset",
449  sqlite3_reset(scp->pStmt));
450  xx = cvtdberr(NULL, "sqlite3_finalize",
451  sqlite3_finalize(scp->pStmt));
452  scp->pStmt = NULL;
453  }
454 
455  scp = scpResetAv(scp);
456 
457  scp->rx = 0;
458  return scp;
459 }
460 
461 static void scpFini(void * _scp)
462  /*@globals fileSystem @*/
463  /*@modifies *_scp, fileSystem @*/
464 {
465  SCP_t scp = (SCP_t) _scp;
466 
467 SCPDEBUG(NULL, (stderr, "==> %s(%p)\n", __FUNCTION__, scp));
468  scp = scpReset(scp);
469  scp = scpResetKeys(scp);
470  scp->av = _free(scp->av);
471  scp->avlen = _free(scp->avlen);
472 }
473 
474 /*@unchecked@*/ /*@only@*/ /*@null@*/
476 
477 static SCP_t scpGetPool(/*@null@*/ rpmioPool pool)
478  /*@globals _rpmscpPool, fileSystem @*/
479  /*@modifies pool, _scpPool, fileSystem @*/
480 {
481  SCP_t scp;
482 
483  if (_scpPool == NULL) {
484  _scpPool = rpmioNewPool("scp", sizeof(*scp), -1, _scp_debug,
485  NULL, NULL, scpFini);
486  pool = _scpPool;
487  }
488  scp = (SCP_t) rpmioGetPool(pool, sizeof(*scp));
489  memset(((char *)scp)+sizeof(scp->_item), 0, sizeof(*scp)-sizeof(scp->_item));
490  return scp;
491 }
492 
493 static SCP_t scpNew(/*@unsed@*/ void * dbp)
494 {
495  SCP_t scp = scpGetPool(_scpPool);
496 
497 #ifdef NOTYET /* XXX FIXME: chain back to the sqlite3 * handle. */
498 /*@-temptrans@*/
499  scp->dbp = dbp;
500 /*@=temptrans@*/
501 #endif
502 
503  scp->used = 0;
504  scp->lkey = NULL;
505  scp->ldata = NULL;
506 
507  return scpLink(scp);
508 }
509 
510 /* ============================================================== */
511 static int sql_step(dbiIndex dbi, SCP_t scp)
512  /*@modifies dbi, scp @*/
513 {
514  int swapped = dbiByteSwapped(dbi);
515  const char * cname;
516  const char * vtype;
517  size_t nb;
518  int loop;
519  int need;
520  int rc;
521  int i;
522 
523  scp->nc = sqlite3_column_count(scp->pStmt); /* XXX cvtdberr? */
524 
525  if (scp->nr == 0 && scp->av != NULL)
526  need = 2 * scp->nc;
527  else
528  need = scp->nc;
529 
530  /* XXX scp->nc = need = scp->nalloc = 0 case forces + 1 here */
531  if (!scp->ac && !need && !scp->nalloc)
532  need++;
533 
534  if (scp->ac + need >= scp->nalloc) {
535  /* XXX +4 is bogus, was +1 */
536  scp->nalloc = 2 * scp->nalloc + need + 4;
537  scp->av = xrealloc(scp->av, scp->nalloc * sizeof(*scp->av));
538  scp->avlen = xrealloc(scp->avlen, scp->nalloc * sizeof(*scp->avlen));
539  }
540 
541  if (scp->av != NULL && scp->nr == 0) {
542  for (i = 0; i < scp->nc; i++) {
543  scp->av[scp->ac] = xstrdup(sqlite3_column_name(scp->pStmt, i));
544  if (scp->avlen) scp->avlen[scp->ac] = strlen(scp->av[scp->ac]) + 1;
545  scp->ac++;
546 assert(scp->ac <= scp->nalloc);
547  }
548  }
549 
550  loop = 1;
551  while (loop) {
552  rc = cvtdberr(dbi, "sqlite3_step",
553  sqlite3_step(scp->pStmt));
554  switch (rc) {
555  case SQLITE_DONE:
556 SQLDBDEBUG(dbi, (stderr, "%s(%p,%p): DONE [%d:%d] av %p avlen %p\n", __FUNCTION__, dbi, scp, scp->ac, scp->nalloc, scp->av, scp->avlen));
557  loop = 0;
558  /*@switchbreak@*/ break;
559  case SQLITE_ROW:
560  if (scp->av != NULL)
561  for (i = 0; i < scp->nc; i++) {
562  /* Expand the row array for new elements */
563  if (scp->ac + need >= scp->nalloc) {
564  /* XXX +4 is bogus, was +1 */
565  scp->nalloc = 2 * scp->nalloc + need + 4;
566  scp->av = xrealloc(scp->av, scp->nalloc * sizeof(*scp->av));
567  scp->avlen = xrealloc(scp->avlen, scp->nalloc * sizeof(*scp->avlen));
568  }
569 assert(scp->av != NULL);
570 assert(scp->avlen != NULL);
571 
572  cname = sqlite3_column_name(scp->pStmt, i);
573  vtype = sqlite3_column_decltype(scp->pStmt, i);
574  nb = 0;
575 
576  if (!strcmp(vtype, "blob")) {
577  const void * v = sqlite3_column_blob(scp->pStmt, i);
578  nb = sqlite3_column_bytes(scp->pStmt, i);
579 SQLDBDEBUG(dbi, (stderr, "\t%d %s %s %p[%d]\n", i, cname, vtype, v, (int)nb));
580  if (nb > 0) {
581  void * t = (void *) xmalloc(nb);
582  scp->av[scp->ac] = (char *) memcpy(t, v, nb);
583  scp->avlen[scp->ac] = nb;
584  scp->ac++;
585  }
586  } else
587  if (!strcmp(vtype, "double")) {
588  double v = sqlite3_column_double(scp->pStmt, i);
589  nb = sizeof(v);
590 SQLDBDEBUG(dbi, (stderr, "\t%d %s %s %g\n", i, cname, vtype, v));
591  if (nb > 0) {
592  scp->av[scp->ac] = (char *) memcpy(xmalloc(nb), &v, nb);
593  scp->avlen[scp->ac] = nb;
594 assert(swapped == 0); /* Byte swap?! */
595  scp->ac++;
596  }
597  } else
598  if (!strcmp(vtype, "int")) {
599  rpmint32_t v = sqlite3_column_int(scp->pStmt, i);
600  nb = sizeof(v);
601 SQLDBDEBUG(dbi, (stderr, "\t%d %s %s %d\n", i, cname, vtype, (int) v));
602  if (nb > 0) {
603  scp->av[scp->ac] = (char *) memcpy(xmalloc(nb), &v, nb);
604  scp->avlen[scp->ac] = nb;
605  scp->ac++;
606  }
607  } else
608  if (!strcmp(vtype, "int64")) {
609  int64_t v = sqlite3_column_int64(scp->pStmt, i);
610  nb = sizeof(v);
611 SQLDBDEBUG(dbi, (stderr, "\t%d %s %s %ld\n", i, cname, vtype, (long)v));
612  if (nb > 0) {
613  scp->av[scp->ac] = (char *) memcpy(xmalloc(nb), &v, nb);
614  scp->avlen[scp->ac] = nb;
615 assert(swapped == 0); /* Byte swap?! */
616  scp->ac++;
617  }
618  } else
619  if (!strcmp(vtype, "text")) {
620  const char * v = (const char *)sqlite3_column_text(scp->pStmt, i);
621  nb = strlen(v) + 1;
622 SQLDBDEBUG(dbi, (stderr, "\t%d %s %s \"%s\"\n", i, cname, vtype, v));
623  if (nb > 0) {
624  scp->av[scp->ac] = (char *) memcpy(xmalloc(nb), v, nb);
625  scp->avlen[scp->ac] = nb;
626  scp->ac++;
627  }
628  }
629 assert(scp->ac <= scp->nalloc);
630  }
631  scp->nr++;
632  /*@switchbreak@*/ break;
633  case SQLITE_BUSY:
634  fprintf(stderr, "sqlite3_step: BUSY %d\n", rc);
635  /*@switchbreak@*/ break;
636  case SQLITE_ERROR:
637  { rpmsql sql = (rpmsql) dbi->dbi_db;
638  sqlite3 * sqlI = (sqlite3 *) sql->I;
639  fprintf(stderr, "sqlite3_step: ERROR %d -- %s\n", rc, scp->cmd);
640  fprintf(stderr, " %s (%d)\n",
641  sqlite3_errmsg(sqlI), sqlite3_errcode(sqlI));
642  fprintf(stderr, " cwd '%s'\n", getcwd(NULL,0));
643  loop = 0;
644  } /*@switchbreak@*/ break;
645  case SQLITE_MISUSE:
646  fprintf(stderr, "sqlite3_step: MISUSE %d\n", rc);
647  loop = 0;
648  /*@switchbreak@*/ break;
649  default:
650  fprintf(stderr, "sqlite3_step: rc %d\n", rc);
651  loop = 0;
652  /*@switchbreak@*/ break;
653  }
654  }
655 
656  if (rc == SQLITE_DONE)
657  rc = SQLITE_OK;
658 
659  return rc;
660 }
661 
662 static int sql_bind_key(dbiIndex dbi, SCP_t scp, int pos, DBT * key)
663  /*@modifies dbi, scp @*/
664 {
665  int rc = 0;
666 
667 assert(key->data != NULL);
668  switch (dbi->dbi_rpmtag) {
669  case RPMDBI_PACKAGES:
670  { unsigned int hnum;
671 assert(key->size == sizeof(rpmuint32_t));
672  memcpy(&hnum, key->data, sizeof(hnum));
673 
674  rc = cvtdberr(dbi, "sqlite3_bind_int",
675  sqlite3_bind_int(scp->pStmt, pos, hnum));
676  } break;
677  default:
678  switch (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE) {
679  default:
680 assert(0); /* borken */
681  case RPM_BIN_TYPE:
682  rc = cvtdberr(dbi, "sqlite3_bind_blob",
683  sqlite3_bind_blob(scp->pStmt, pos,
684  key->data, key->size, SQLITE_STATIC));
685  /*@innerbreak@*/ break;
686  case RPM_UINT8_TYPE:
687  { rpmuint8_t i;
688 assert(key->size == sizeof(rpmuint8_t));
689  memcpy(&i, key->data, sizeof(i));
690  rc = cvtdberr(dbi, "sqlite3_bind_int",
691  sqlite3_bind_int(scp->pStmt, pos, (int) i));
692  } /*@innerbreak@*/ break;
693  case RPM_UINT16_TYPE:
694  { rpmuint16_t i;
695 assert(key->size == sizeof(rpmuint16_t));
696  memcpy(&i, key->data, sizeof(i));
697  rc = cvtdberr(dbi, "sqlite3_bind_int",
698  sqlite3_bind_int(scp->pStmt, pos, (int) i));
699  } /*@innerbreak@*/ break;
700  case RPM_UINT32_TYPE:
701  { rpmuint32_t i;
702 assert(key->size == sizeof(rpmuint32_t));
703  memcpy(&i, key->data, sizeof(i));
704 
705  rc = cvtdberr(dbi, "sqlite3_bind_int",
706  sqlite3_bind_int(scp->pStmt, pos, i));
707  } /*@innerbreak@*/ break;
708  case RPM_UINT64_TYPE:
709  { rpmuint64_t i;
710 assert(key->size == sizeof(rpmuint64_t));
711  memcpy(&i, key->data, sizeof(i));
712 
713  rc = cvtdberr(dbi, "sqlite3_bind_int64",
714  sqlite3_bind_int64(scp->pStmt, pos, i));
715  } /*@innerbreak@*/ break;
716  /*@innerbreak@*/ break;
717  case RPM_STRING_TYPE:
718  case RPM_I18NSTRING_TYPE:
720  rc = cvtdberr(dbi, "sqlite3_bind_text",
721  sqlite3_bind_text(scp->pStmt, pos,
722  key->data, key->size, SQLITE_STATIC));
723  /*@innerbreak@*/ break;
724  }
725  }
726 
727  return rc;
728 }
729 
730 static int sql_bind_data(/*@unused@*/ dbiIndex dbi, SCP_t scp,
731  int pos, DBT * data)
732  /*@modifies scp @*/
733 {
734  int rc;
735 
736 assert(data->data != NULL);
737  rc = cvtdberr(dbi, "sqlite3_bind_blob",
738  sqlite3_bind_blob(scp->pStmt, pos,
739  data->data, data->size, SQLITE_STATIC));
740 
741  return rc;
742 }
743 
744 /* =================================================================== */
745 static int sql_exec(dbiIndex dbi, const char * cmd,
746  int (*callback)(void*,int,char**,char**),
747  void * context)
748 {
749  rpmsql sql = (rpmsql) dbi->dbi_db;
750  sqlite3 * sqlI = (sqlite3 *) sql->I;
751  char * errmsg = NULL;
752  int rc = cvtdberr(dbi, "sqlite3_exec",
753  sqlite3_exec(sqlI, cmd, callback, context, &errmsg));
754 
755 SQLDBDEBUG(dbi, (stderr, "%s\n<-- %s(%p,%p(%p)) rc %d %s\n", cmd, __FUNCTION__, dbi, callback, context, rc, (errmsg ? errmsg : "")));
756  errmsg = _free(errmsg);
757  return rc;
758 }
759 
760 static int sql_busy_handler(void * _dbi, int time)
761  /*@*/
762 {
763  dbiIndex dbi = (dbiIndex) _dbi;
764  int rc = 1; /* assume retry */
765 
766 #ifdef DYING
767  rpmlog(RPMLOG_WARNING, _("Unable to get lock on db %s, retrying... (%d)\n"),
768  dbi->dbi_file, time);
769 #endif
770 
771  /* XXX FIXME: backoff timer with drop dead ceiling. */
772  (void) sleep(1);
773 
774 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%d) rc %d\n", __FUNCTION__, _dbi, time, rc));
775  return rc;
776 }
777 
778 /* =================================================================== */
779 
780 /* XXX FIXME: all the "new.key" fields in trigger need headerGet() getter */
781 static const char _Packages_sql_init[] = "\
782  CREATE TABLE IF NOT EXISTS 'Packages' (\n\
783  key INTEGER UNIQUE PRIMARY KEY NOT NULL,\n\
784  value BLOB NOT NULL\n\
785 \n\
786  );\n\
787  CREATE TRIGGER IF NOT EXISTS insert_Packages AFTER INSERT ON 'Packages'\n\
788  BEGIN\n\
789  INSERT INTO 'Nvra' (key,value) VALUES (\n\
790  new.key, new.rowid );\n\
791  INSERT INTO 'Packagecolor' (key,value) VALUES (\n\
792  new.key, new.rowid );\n\
793  INSERT INTO 'Pubkeys' (key,value) VALUES (\n\
794  new.key, new.rowid );\n\
795  INSERT INTO 'Sha1header' (key,value) VALUES (\n\
796  new.key, new.rowid );\n\
797  INSERT INTO 'Installtid' (key,value) VALUES (\n\
798  new.key, new.rowid );\n\
799  INSERT INTO 'Providename' (key,value) VALUES (\n\
800  new.key, new.rowid );\n\
801  INSERT INTO 'Group' (key,value) VALUES (\n\
802  new.key, new.rowid );\n\
803  INSERT INTO 'Release' (key,value) VALUES (\n\
804  new.key, new.rowid );\n\
805  INSERT INTO 'Version' (key,value) VALUES (\n\
806  new.key, new.rowid );\n\
807  INSERT INTO 'Name' (key,value) VALUES (\n\
808  new.key, new.rowid );\n\
809  END;\n\
810  CREATE TRIGGER IF NOT EXISTS delete_Packages BEFORE DELETE ON 'Packages'\n\
811  BEGIN\n\
812  DELETE FROM 'Nvra' WHERE value = old.rowid;\n\
813  DELETE FROM 'Packagecolor' WHERE value = old.rowid;\n\
814  DELETE FROM 'Pubkeys' WHERE value = old.rowid;\n\
815  DELETE FROM 'Sha1header' WHERE value = old.rowid;\n\
816  DELETE FROM 'Installtid' WHERE value = old.rowid;\n\
817  DELETE FROM 'Providename' WHERE value = old.rowid;\n\
818  DELETE FROM 'Group' WHERE value = old.rowid;\n\
819  DELETE FROM 'Release' WHERE value = old.rowid;\n\
820  DELETE FROM 'Version' WHERE value = old.rowid;\n\
821  DELETE FROM 'Name' WHERE value = old.rowid;\n\
822  END;\n\
823 \n\
824  CREATE TABLE IF NOT EXISTS 'Seqno' (\n\
825  key INTEGER,\n\
826  value INTEGER\n\
827  );\n\
828 \n\
829  CREATE TABLE IF NOT EXISTS 'Nvra' (\n\
830  key TEXT NOT NULL,\n\
831  value INTEGER REFERENCES 'Packages'\n\
832  );\n\
833 \n\
834  CREATE TABLE IF NOT EXISTS 'Packagecolor' (\n\
835  key INTEGER NOT NULL,\n\
836  value INTEGER REFERENCES 'Packages'\n\
837  );\n\
838 \n\
839  CREATE TABLE IF NOT EXISTS 'Pubkeys' (\n\
840  key BLOB NOT NULL,\n\
841  value INTEGER REFERENCES 'Packages'\n\
842  );\n\
843 \n\
844  CREATE TABLE IF NOT EXISTS 'Sha1header' (\n\
845  key TEXT NOT NULL,\n\
846  value INTEGER REFERENCES 'Packages'\n\
847  );\n\
848 \n\
849  CREATE TABLE IF NOT EXISTS 'Installtid' (\n\
850  key INTEGER NOT NULL,\n\
851  value INTEGER REFERENCES 'Packages'\n\
852  );\n\
853 \n\
854  CREATE TABLE IF NOT EXISTS 'Providename' (\n\
855  key TEXT NOT NULL,\n\
856  value INTEGER REFERENCES 'Packages'\n\
857  );\n\
858 \n\
859  CREATE TABLE IF NOT EXISTS 'Group' (\n\
860  key TEXT NOT NULL,\n\
861  value INTEGER REFERENCES 'Packages'\n\
862  );\n\
863 \n\
864  CREATE TABLE IF NOT EXISTS 'Release' (\n\
865  key TEXT NOT NULL,\n\
866  value INTEGER REFERENCES 'Packages'\n\
867  );\n\
868 \n\
869  CREATE TABLE IF NOT EXISTS 'Version' (\n\
870  key TEXT NOT NULL,\n\
871  value INTEGER REFERENCES 'Packages'\n\
872  );\n\
873 \n\
874  CREATE TABLE IF NOT EXISTS 'Name' (\n\
875  key TEXT NOT NULL,\n\
876  value INTEGER REFERENCES 'Packages'\n\
877  );\n\
878 ";
879 
880 static const char * tagTypes[] = {
881  "",
882  "INTEGER NOT NULL", /* RPM_UINT8_TYPE */
883  "INTEGER NOT NULL", /* RPM_UINT8_TYPE */
884  "INTEGER NOT NULL", /* RPM_UINT16_TYPE */
885  "INTEGER NOT NULL", /* RPM_UINT32_TYPE */
886  "INTEGER NOT NULL", /* RPM_UINT64_TYPE */
887  "TEXT NOT NULL", /* RPM_STRING_TYPE */
888  "BLOB NOT NULL", /* RPM_BIN_TYPE */
889  "TEXT NOT NULL", /* RPM_STRING_ARRAY_TYPE */
890  "TEXT NOT NULL", /* RPM_I18NSTRING_TYPE */
891 };
892 static size_t ntagTypes = sizeof(tagTypes) / sizeof(tagTypes[0]);
893 
894 static int sql_initDB_cb(void * _dbi, int argc, char ** argv, char ** cols)
895 {
896  dbiIndex dbi = (dbiIndex) _dbi;
897  int rc = -1;
898  if (dbi && argc == 1) {
899  char * end = NULL;
900  dbi->dbi_table_exists = strtoll(argv[0], &end, 10);
901  if (end && *end == '\0') rc = 0;
902  }
903 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p[%d],%p) rc %d table_exists %llu\n", __FUNCTION__, _dbi, argv, argc, cols, rc, (unsigned long long) (dbi ? dbi->dbi_table_exists : 0)));
904  return rc;
905 }
906 
912 static int sql_initDB(dbiIndex dbi)
913  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
914  /*@modifies internalState @*/
915 {
916  char cmd[BUFSIZ];
917  int rc = 0;
918 
919 #ifdef REFERENCE
920 PRAGMA auto_vacuum = 0 | NONE | 1 | FULL | 2 | INCREMENTAL;
921 PRAGMA automatic_index = boolean;
922 PRAGMA cache_size = pages | -kibibytes;
923 PRAGMA case_sensitive_like = boolean;
924 PRAGMA checkpoint_fullfsync = boolean;
925 PRAGMA collation_list;
926 PRAGMA compile_options;
927 PRAGMA count_changes = boolean;
928 PRAGMA database_list;
929 PRAGMA default_cache_size = Number-of-pages;
930 PRAGMA empty_result_callbacks = boolean;
931 PRAGMA encoding = "UTF-8" | "UTF-16" | "UTF-16le" | "UTF-16be";
932 PRAGMA foreign_key_list(table-name);
933 PRAGMA foreign_keys = boolean;
934 PRAGMA freelist_count;
935 PRAGMA full_column_names = boolean;
936 PRAGMA fullfsync = boolean;
937 PRAGMA ignore_check_constraints = boolean;
938 PRAGMA incremental_vacuum(N);
939 PRAGMA index_info(index-name);
940 PRAGMA index_list(table-name);
941 PRAGMA integrity_check(integer)
942 PRAGMA database.journal_mode = DELETE | TRUNCATE | PERSIST | MEMORY | WAL | OFF;
943 PRAGMA journal_size_limit = N;
944 PRAGMA legacy_file_format = boolean;
945 PRAGMA locking_mode = NORMAL | EXCLUSIVE;
946 PRAGMA max_page_count = N;
947 PRAGMA page_count;
948 PRAGMA page_size = bytes;
949 PRAGMA parser_trace = boolean;
950 PRAGMA quick_check(integer);
951 PRAGMA read_uncommitted = boolean;
952 PRAGMA recursive_triggers = boolean;
953 PRAGMA reverse_unordered_selects = boolean;
954 PRAGMA schema_version = integer;
955 PRAGMA user_version = integer;
956 PRAGMA database.secure_delete = boolean;
957 PRAGMA short_column_names = boolean; (deprecated)
958 PRAGMA shrink_memory;
959 PRAGMA synchronous = 0 | OFF | 1 | NORMAL | 2 | FULL;
960 PRAGMA table_info(table-name);
961 PRAGMA temp_store = 0 | DEFAULT | 1 | FILE | 2 | MEMORY;
962 PRAGMA temp_store_directory = 'directory-name';
963 PRAGMA vdbe_listing = boolean;
964 PRAGMA vdbe_trace = boolean;
965 PRAGMA wal_autocheckpoint=N;
966 PRAGMA database.wal_checkpoint(PASSIVE | FULL | RESTART);
967 PRAGMA writable_schema = boolean;
968 #endif
969 
970  if (dbi->dbi_tmpdir) {
971  const char *root;
972  const char *tmpdir;
973  root = (dbi->dbi_root ? dbi->dbi_root : dbi->dbi_rpmdb->db_root);
974  if ((root[0] == '/' && root[1] == '\0') || dbi->dbi_rpmdb->db_chrootDone)
975  root = NULL;
976  tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
977  if (rpmioMkpath(tmpdir, 0755, getuid(), getgid()) == 0) {
978  sprintf(cmd, " PRAGMA temp_store_directory = '%s';", tmpdir);
979  rc = sql_exec(dbi, cmd, NULL, NULL);
980  }
981  tmpdir = _free(tmpdir);
982  }
983 
984  if (dbi->dbi_eflags & DB_EXCL) {
985  sprintf(cmd, " PRAGMA locking_mode = EXCLUSIVE;");
986  rc = sql_exec(dbi, cmd, NULL, NULL);
987  }
988 
989  if (dbi->dbi_no_fsync) {
990  static const char _cmd[] = " PRAGMA synchronous = OFF;";
991  rc = sql_exec(dbi, _cmd, NULL, NULL);
992  }
993 
994 #ifdef DYING
995  if (dbi->dbi_pagesize > 0) {
996  sprintf(cmd, " PRAGMA cache_size = %d;", dbi->dbi_cachesize);
997  rc = sql_exec(dbi, cmd, NULL, NULL);
998  }
999  if (dbi->dbi_cachesize > 0) {
1000  sprintf(cmd, " PRAGMA page_size = %d;", dbi->dbi_pagesize);
1001  rc = sql_exec(dbi, cmd, NULL, NULL);
1002  }
1003 #endif
1004 
1005  /* Determine if table has already been initialized. */
1006  if (!dbi->dbi_table_exists) {
1007  sprintf(cmd, "\
1008  SELECT count(type) FROM 'sqlite_master' WHERE type='table' and name='%s';\n\
1009 ", dbi->dbi_subfile);
1010  rc = sql_exec(dbi, cmd, sql_initDB_cb, dbi);
1011  if (rc)
1012  goto exit;
1013  }
1014 
1015  /* Create the table schema (if not yet done). */
1016  if (!dbi->dbi_table_exists) {
1017  const char * valtype = "INTEGER REFERENCES Packages";
1018  const char * keytype;
1019  int kt;
1020 
1021  switch (dbi->dbi_rpmtag) {
1022  case RPMDBI_PACKAGES:
1023  rc = sql_exec(dbi, _Packages_sql_init, NULL, NULL);
1024  /*@ fallthrough @*/
1025  case RPMTAG_PUBKEYS:
1026  case RPMDBI_SEQNO:
1027  keytype = NULL;
1028  break;
1029  default:
1030  kt = (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE);
1031  keytype = tagTypes[(kt > 0 && kt < (int)ntagTypes ? kt : 0)];
1032  break;
1033  }
1034 
1035  if (keytype) {
1036  /* XXX no need for IF NOT EXISTS */
1037  /* XXX add per-table triggers? */
1038  sprintf(cmd, "\
1039  CREATE %sTABLE IF NOT EXISTS '%s' (key %s, value %s);\
1040 ",
1041  dbi->dbi_temporary ? "TEMPORARY " : "",
1042  dbi->dbi_subfile, keytype, valtype);
1043  rc = sql_exec(dbi, cmd, NULL, NULL);
1044  if (rc)
1045  goto exit;
1046  }
1047  }
1048 
1049 exit:
1050 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p) rc %d\n", __FUNCTION__, dbi, rc));
1051  return rc;
1052 }
1053 
1061 static int sql_cclose (dbiIndex dbi, /*@only@*/ DBC * dbcursor,
1062  unsigned int flags)
1063  /*@globals fileSystem, internalState @*/
1064  /*@modifies dbi, *dbcursor, fileSystem, internalState @*/
1065 {
1066  SCP_t scp = (SCP_t) dbcursor;
1067  int rc = 0;
1068 
1069 SQLDBDEBUG(dbi, (stderr, "==> sql_cclose(%p)\n", scp));
1070 
1071  if (scp->lkey)
1072  scp->lkey = _free(scp->lkey);
1073 
1074  if (scp->ldata)
1075  scp->ldata = _free(scp->ldata);
1076 
1077  scp = scpFree(scp);
1078 
1079 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p,0x%x) rc %d\n", __FUNCTION__, dbi, dbcursor, flags, rc));
1080  return rc;
1081 }
1082 
1089 static int sql_close(/*@only@*/ dbiIndex dbi, unsigned int flags)
1090  /*@globals fileSystem, internalState @*/
1091  /*@modifies dbi, fileSystem, internalState @*/
1092 {
1093  rpmsql sql = (rpmsql) dbi->dbi_db;
1094  int rc = 0;
1095 
1096  if (sql) {
1097 
1098 #if defined(MAYBE) /* XXX should SQLite and BDB have different semantics? */
1099  if (dbi->dbi_temporary && !(dbi->dbi_eflags & DB_PRIVATE)) {
1100  const char * dbhome = NULL;
1101  urltype ut = urlPath(dbi->dbi_home, &dbhome);
1102  const char * dbfname = rpmGenPath(dbhome, dbi->dbi_file, NULL);
1103  int xx = (dbfname ? Unlink(dbfname) : 0);
1104  (void)ut; (void)xx; /* XXX tell gcc to be quiet. */
1105  dbfname = _free(dbfname);
1106  }
1107 #endif
1108 
1109  /* XXX different than Berkeley DB: dbi->dbi_db is allocated. */
1110  sql = rpmsqlFree(sql);
1111  dbi->dbi_db = sql = NULL;
1112 
1113  rpmlog(RPMLOG_DEBUG, D_("closed table %s\n"),
1114  dbi->dbi_subfile);
1115 
1116  }
1117 
1118  (void) db3Free(dbi);
1119 
1120 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,0x%x) rc %d\n", __FUNCTION__, dbi, flags, rc));
1121  return rc;
1122 }
1123 
1131 static int sql_open(rpmdb rpmdb, rpmTag rpmtag, /*@out@*/ dbiIndex * dbip)
1132  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1133  /*@modifies *dbip, rpmGlobalMacroContext, fileSystem, internalState @*/
1134 {
1135 /*@-nestedextern -shadow @*/
1136  extern struct _dbiVec sqlitevec;
1137 /*@=nestedextern -shadow @*/
1138 
1139  const char * urlfn = NULL;
1140  const char * dbhome = NULL;
1141  const char * dbfname = NULL;
1142  dbiIndex dbi = NULL;
1143  rpmsql sql = NULL;
1144  int rc = -1; /* assume failure */
1145  int xx;
1146 
1147 /* XXX dbi = NULL here */
1148 SQLDBDEBUG(dbi, (stderr, "==> %s(%p,%s(%u),%p)\n", __FUNCTION__, rpmdb, tagName(rpmtag), rpmtag, dbip));
1149 
1150  if (dbip)
1151  *dbip = NULL;
1152 
1153  /* Parse db configuration parameters. */
1154  if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
1155  goto exit;
1156 
1157  /* Get the prefix/root component and directory path */
1158  dbi->dbi_root = xstrdup(rpmdb->db_root);
1159  dbi->dbi_home = xstrdup(rpmdb->db_home);
1160  { const char * s = tagName(dbi->dbi_rpmtag);
1161  dbi->dbi_file = xstrdup(s);
1162  dbi->dbi_subfile = xstrdup(s);
1163  }
1164  dbi->dbi_mode = O_RDWR;
1165 
1166  /*
1167  * Either the root or directory components may be a URL. Concatenate,
1168  * convert the URL to a path, and add the name of the file.
1169  */
1170  urlfn = rpmGenPath(NULL, dbi->dbi_home, NULL);
1171  (void) urlPath(urlfn, &dbhome);
1172 
1173  /* Create the %{sqldb} directory if it doesn't exist. */
1174  (void) rpmioMkpath(dbhome, 0755, getuid(), getgid());
1175 
1176  if (dbi->dbi_eflags & DB_PRIVATE)
1177  dbfname = xstrdup(":memory:");
1178  else {
1179 #ifdef DYING /* XXX all tables in a single database file. */
1180  dbfname = rpmGenPath(dbhome, dbi->dbi_file, NULL);
1181 #else
1182  dbfname = rpmGenPath(dbhome, "sqldb", NULL);
1183 #endif
1184  }
1185 
1186  rpmlog(RPMLOG_DEBUG, D_("opening table %s (%s) mode=0x%x\n"),
1187  dbfname, dbi->dbi_subfile, dbi->dbi_mode);
1188 
1189  /* Open the Database */
1190  /* XXX use single handle for all tables in one database file? */
1191  { const char * _av[] = { __FUNCTION__, NULL, NULL };
1192  int _flags = RPMSQL_FLAGS_CREATE;
1193  _av[1] = dbfname;
1194  sql = rpmsqlNew((char **) _av, _flags);
1195  if (sql == NULL || sql->I == NULL)
1196  goto exit;
1197  rc = 0;
1198  }
1199 
1200  { sqlite3 * sqlI = (sqlite3 *) sql->I;
1201  xx = cvtdberr(dbi, "sqlite3_busy_handler",
1202  sqlite3_busy_handler(sqlI, &sql_busy_handler, dbi));
1203  }
1204 
1205  dbi->dbi_db = (void *) sql;
1206 
1207  /* Initialize table */
1208  xx = sql_initDB(dbi); /* XXX wire up rc == 0 on success */
1209 
1210 exit:
1211  if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) {
1212  dbi->dbi_vec = &sqlitevec;
1213  *dbip = dbi;
1214  /* XXX BDB secondary -> primary db3Associate() */
1215  /* XXX BDB Seqno seqid_init() */
1216  } else {
1217  if (dbi) {
1218  (void) sql_close(dbi, 0);
1219  }
1220  dbi = NULL;
1221  if (dbip) *dbip = dbi;
1222  }
1223 
1224  urlfn = _free(urlfn);
1225  dbfname = _free(dbfname);
1226 
1227 SQLDBDEBUG(dbi, (stderr, "<== %s(%p,%s(%u),%p) rc %d dbi %p\n", __FUNCTION__, rpmdb, tagName(rpmtag), rpmtag, dbip, rc, (dbip ? *dbip : NULL)));
1228  return rc;
1229 }
1230 
1237 static int sql_sync (dbiIndex dbi, /*@unused@*/ unsigned int flags)
1238  /*@globals fileSystem, internalState @*/
1239  /*@modifies fileSystem, internalState @*/
1240 {
1241  int rc = 0;
1242 
1243  /* XXX FIXME: implement. */
1244 
1245 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,0x%x) rc %d\n", __FUNCTION__, dbi, flags, rc));
1246  return rc;
1247 }
1248 
1256 static int sql_exists(dbiIndex dbi, DBT * key, unsigned int flags)
1257  /*@globals fileSystem @*/
1258  /*@modifies fileSystem @*/
1259 {
1260  int rc = EINVAL;
1261 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p,0x%x) rc %d %s\n", __FUNCTION__, dbi, key, flags, rc, _KEYDATA(key, NULL, NULL, NULL)));
1262  return rc;
1263 }
1264 
1265 #ifdef REFERENCE
1266 UPDATE SQLITE_SEQUENCE SET seq = 0 WHERE name = 'MyTable';
1267 #endif
1268 static const char seqno_inc_cmd[] = "\
1269  BEGIN EXCLUSIVE TRANSACTION;\n\
1270  REPLACE INTO Seqno VALUES (0,\n\
1271  COALESCE((SELECT value FROM Seqno WHERE key == 0), 0) + 1);\n\
1272  SELECT value FROM Seqno WHERE key == 0;\n\
1273  COMMIT TRANSACTION;\n\
1274 ";
1275 
1276 static int sql_seqno_cb(void * _dbi, int argc, char ** argv, char ** cols)
1277 {
1278  dbiIndex dbi = (dbiIndex) _dbi;
1279  int rc = -1;
1280  if (dbi && argc == 1) {
1281  char * end = NULL;
1282  dbi->dbi_seqno = strtoll(argv[0], &end, 10);
1283  if (end && *end) rc = 0;
1284  if (end && *end == '\0') rc = 0;
1285  }
1286 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p[%d],%p) rc %d seqno %llu\n", __FUNCTION__, _dbi, argv, argc, cols, rc, (unsigned long long) (dbi ? dbi->dbi_seqno : 0)));
1287  return rc;
1288 }
1289 
1297 static int sql_seqno(dbiIndex dbi, int64_t * seqnop, unsigned int flags)
1298 {
1299  int rc = EINVAL;
1300  if (dbi && seqnop) {
1301  /* XXX DB_SEQNO has min:max increment/decrement and name */
1302  rc = sql_exec(dbi, seqno_inc_cmd, sql_seqno_cb, dbi);
1303  if (!rc) *seqnop = dbi->dbi_seqno;
1304  }
1305 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p,0x%x) rc %d seqno %llu\n", __FUNCTION__, dbi, seqnop, flags, rc, (unsigned long long) (seqnop ? *seqnop : 0xdeadbeef)));
1306  return rc;
1307 }
1308 
1317 static int sql_copen (dbiIndex dbi,
1318  /*@unused@*/ /*@null@*/ DB_TXN * txnid,
1319  /*@out@*/ DBC ** dbcp, unsigned int flags)
1320  /*@globals fileSystem, internalState @*/
1321  /*@modifies dbi, *txnid, *dbcp, fileSystem, internalState @*/
1322 {
1323  rpmsql sql = (rpmsql) dbi->dbi_db;
1324  SCP_t scp = scpNew(sql);
1325  DBC * dbcursor = (DBC *)scp;
1326  int rc = 0;
1327 
1328 SQLDBDEBUG(dbi, (stderr, "==> %s(%s) tag %d type %d scp %p\n", __FUNCTION__, tagName(dbi->dbi_rpmtag), dbi->dbi_rpmtag, (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE), scp));
1329 
1330  if (dbcp)
1331  *dbcp = dbcursor;
1332  else
1333  (void) sql_cclose(dbi, dbcursor, 0);
1334 
1335 SQLDBDEBUG(dbi, (stderr, "<== %s(%p,%p,%p,0x%x) rc %d subfile %s\n", __FUNCTION__, dbi, txnid, dbcp, flags, rc, dbi->dbi_subfile));
1336  return rc;
1337 }
1338 
1348 static int sql_cdel (dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key,
1349  DBT * data, unsigned int flags)
1350  /*@globals fileSystem, internalState @*/
1351  /*@modifies dbi, *dbcursor, fileSystem, internalState @*/
1352 {
1353  rpmsql sql = (rpmsql) dbi->dbi_db;
1354  sqlite3 * sqlI = (sqlite3 *) sql->I;
1355  SCP_t scp = scpLink(dbcursor); /* XXX scpNew() instead? */
1356  int rc = 0;
1357 
1358 dbg_keyval(__FUNCTION__, dbi, dbcursor, key, data, flags);
1359 
1360 assert(scp->cmd == NULL); /* XXX memleak prevention */
1361  scp->cmd = sqlite3_mprintf("DELETE FROM '%q' WHERE key=? AND value=?;",
1362  dbi->dbi_subfile);
1363 
1364  rc = cvtdberr(dbi, "sqlite3_prepare",
1365  sqlite3_prepare(sqlI, scp->cmd, (int)strlen(scp->cmd),
1366  &scp->pStmt, (const char **) &scp->pzErrmsg));
1367  if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) prepare %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqlI), rc);
1368  rc = cvtdberr(dbi, "sql_bind_key",
1369  sql_bind_key(dbi, scp, 1, key));
1370  if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) bind key %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqlI), rc);
1371  rc = cvtdberr(dbi, "sql_bind_data",
1372  sql_bind_data(dbi, scp, 2, data));
1373  if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) bind data %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqlI), rc);
1374 
1375  rc = cvtdberr(dbi, "sql_step",
1376  sql_step(dbi, scp));
1377  if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) sql_step rc %d\n", dbi->dbi_subfile, rc);
1378 
1379  scp = scpFree(scp);
1380 
1381 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,%p,0x%x) rc %d subfile %s %s\n", __FUNCTION__, dbi, dbcursor, key, data, flags, rc, dbi->dbi_subfile, _KEYDATA(key, NULL, data, NULL)));
1382  return rc;
1383 }
1384 
1394 static int sql_cget (dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key,
1395  DBT * data, unsigned int flags)
1396  /*@globals fileSystem, internalState @*/
1397  /*@modifies dbi, dbcursor, *key, *data, fileSystem, internalState @*/
1398 {
1399  rpmsql sql = (rpmsql) dbi->dbi_db;
1400  sqlite3 * sqlI = (sqlite3 *) sql->I;
1401  SCP_t scp = (SCP_t)dbcursor;
1402  int rc = 0;
1403  int ix;
1404 
1405 assert(dbcursor != NULL);
1406 dbg_keyval(__FUNCTION__, dbi, dbcursor, key, data, flags);
1407 
1408  /* First determine if this is a new scan or existing scan */
1409 
1410 SQLDBDEBUG(dbi, (stderr, "\tcget(%s) scp %p rc %d flags %d av %p\n",
1411  dbi->dbi_subfile, scp, rc, flags, scp->av));
1412  if (flags == DB_SET || scp->used == 0) {
1413  scp->used = 1; /* Signal this scp as now in use... */
1414  scp = scpReset(scp); /* Free av and avlen, reset counters.*/
1415 
1416 /* XXX: Should we also reset the key table here? Can you re-use a cursor? */
1417 
1418  /* If we're scanning everything, load the iterator key table */
1419  if (key->size == 0) {
1420  scp->all = 1;
1421 
1422 /*
1423  * The only condition not dealt with is if there are multiple identical keys. This can lead
1424  * to later iteration confusion. (It may return the same value for the multiple keys.)
1425  */
1426 
1427 assert(scp->cmd == NULL); /* XXX memleak prevention */
1428  switch (dbi->dbi_rpmtag) {
1429  case RPMDBI_PACKAGES:
1430  scp->cmd = sqlite3_mprintf("SELECT key FROM '%q' ORDER BY key;",
1431  dbi->dbi_subfile);
1432  break;
1433  default:
1434  scp->cmd = sqlite3_mprintf("SELECT key FROM '%q';",
1435  dbi->dbi_subfile);
1436  break;
1437  }
1438  rc = cvtdberr(dbi, "sqlite3_prepare",
1439  sqlite3_prepare(sqlI, scp->cmd,
1440  (int)strlen(scp->cmd), &scp->pStmt,
1441  (const char **) &scp->pzErrmsg));
1442  if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) sequential prepare %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqlI), rc);
1443 
1444  rc = sql_step(dbi, scp);
1445  if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) sequential sql_step rc %d\n", dbi->dbi_subfile, rc);
1446 
1447  scp = scpResetKeys(scp);
1448  scp->nkeys = scp->nr;
1449  scp->keys = (DBT **) xcalloc(scp->nkeys, sizeof(*scp->keys));
1450  for (ix = 0; ix < scp->nkeys; ix++) {
1451  scp->keys[ix] = (DBT *) xmalloc(sizeof(*scp->keys[0]));
1452  scp->keys[ix]->size = (UINT32_T) scp->avlen[ix+1];
1453  scp->keys[ix]->data = (void *) xmalloc(scp->keys[ix]->size);
1454  memcpy(scp->keys[ix]->data, scp->av[ix+1], scp->avlen[ix+1]);
1455  }
1456  } else {
1457  /* We're only scanning ONE element */
1458  scp = scpResetKeys(scp);
1459  scp->nkeys = 1;
1460  scp->keys = (DBT **) xcalloc(scp->nkeys, sizeof(*scp->keys));
1461  scp->keys[0] = (DBT *) xmalloc(sizeof(*scp->keys[0]));
1462  scp->keys[0]->size = key->size;
1463  scp->keys[0]->data = (void *) xmalloc(scp->keys[0]->size);
1464  memcpy(scp->keys[0]->data, key->data, key->size);
1465  }
1466 
1467  scp = scpReset(scp);
1468 
1469  /* Prepare SQL statement to retrieve the value for the current key */
1470 assert(scp->cmd == NULL); /* XXX memleak prevention */
1471  scp->cmd = sqlite3_mprintf("SELECT value FROM '%q' WHERE key=?;", dbi->dbi_subfile);
1472  rc = cvtdberr(dbi, "sqlite3_prepare",
1473  sqlite3_prepare(sqlI, scp->cmd, (int)strlen(scp->cmd),
1474  &scp->pStmt, (const char **) &scp->pzErrmsg));
1475 
1476  if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) prepare %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqlI), rc);
1477  }
1478 
1479  scp = scpResetAv(scp);
1480 
1481  /* Now continue with a normal retrive based on key */
1482  if ((scp->rx + 1) > scp->nkeys )
1483  rc = DB_NOTFOUND; /* At the end of the list */
1484 
1485  if (rc != 0)
1486  goto exit;
1487 
1488  /* Bind key to prepared statement */
1489  rc = cvtdberr(dbi, "sql_bind_key",
1490  sql_bind_key(dbi, scp, 1, scp->keys[scp->rx]));
1491  if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) key bind %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqlI), rc);
1492 
1493  rc = cvtdberr(dbi, "sql_step",
1494  sql_step(dbi, scp));
1495  if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) sql_step rc %d\n", dbi->dbi_subfile, rc);
1496 
1497  rc = cvtdberr(dbi, "sqlite3_reset",
1498  sqlite3_reset(scp->pStmt));
1499  if (rc) rpmlog(RPMLOG_WARNING, "reset %d\n", rc);
1500 
1501 /* 1 key should return 0 or 1 row/value */
1502 assert(scp->nr < 2);
1503 
1504  if (scp->nr == 0 && scp->all == 0)
1505  rc = DB_NOTFOUND; /* No data for that key found! */
1506 
1507  if (rc != 0)
1508  goto exit;
1509 
1510  /* If we're looking at the whole db, return the key */
1511  if (scp->all) {
1512 
1513 assert(scp->nr == 1); /* XXX Ensure no duplicate keys */
1514 
1515  if (scp->lkey)
1516  scp->lkey = _free(scp->lkey);
1517 
1518  key->size = scp->keys[scp->rx]->size;
1519  key->data = (void *) xmalloc(key->size);
1520  if (! (key->flags & DB_DBT_MALLOC))
1521  scp->lkey = key->data;
1522 
1523  (void) memcpy(key->data, scp->keys[scp->rx]->data, key->size);
1524  }
1525 
1526  /* Construct and return the data element (element 0 is "value", 1 is _THE_ value)*/
1527  switch (dbi->dbi_rpmtag) {
1528  default:
1529  if (scp->ldata)
1530  scp->ldata = _free(scp->ldata);
1531 
1532  data->size = (UINT32_T) scp->avlen[1];
1533  data->data = (void *) xmalloc(data->size);
1534  if (! (data->flags & DB_DBT_MALLOC) )
1535  scp->ldata = data->data;
1536 
1537  (void) memcpy(data->data, scp->av[1], data->size);
1538  }
1539 
1540  scp->rx++;
1541 
1542  /* XXX FIXME: ptr alignment is fubar here. */
1543 SQLDBDEBUG(dbi, (stderr, "\tcget(%s) found key 0x%x (%d)\n", dbi->dbi_subfile,
1544  key->data == NULL ? 0 : *(unsigned int *)key->data, key->size));
1545 SQLDBDEBUG(dbi, (stderr, "\tcget(%s) found data 0x%x (%d)\n", dbi->dbi_subfile,
1546  key->data == NULL ? 0 : *(unsigned int *)data->data, data->size));
1547 
1548 exit:
1549  if (rc == DB_NOTFOUND) {
1550 SQLDBDEBUG(dbi, (stderr, "\tcget(%s) not found\n", dbi->dbi_subfile));
1551  }
1552 
1553 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,%p,0x%x) rc %d subfile %s %s\n", __FUNCTION__, dbi, dbcursor, key, data, flags, rc, dbi->dbi_subfile, _KEYDATA(key, NULL, data, NULL)));
1554  return rc;
1555 }
1556 
1566 static int sql_cput (dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key,
1567  DBT * data, unsigned int flags)
1568  /*@globals fileSystem, internalState @*/
1569  /*@modifies dbi, *dbcursor, fileSystem, internalState @*/
1570 {
1571  rpmsql sql = (rpmsql) dbi->dbi_db;
1572  sqlite3 * sqlI = (sqlite3 *) sql->I;
1573  SCP_t scp = scpLink(dbcursor); /* XXX scpNew() instead? */
1574  int rc = 0;
1575 
1576 dbg_keyval("sql_cput", dbi, dbcursor, key, data, flags);
1577 
1578 assert(scp->cmd == NULL); /* XXX memleak prevention */
1579  switch (dbi->dbi_rpmtag) {
1580  default:
1581  /* XXX sqlite3_prepare() persistence */
1582  scp->cmd = sqlite3_mprintf("INSERT OR REPLACE INTO '%q' VALUES(?, ?);",
1583  dbi->dbi_subfile);
1584  rc = cvtdberr(dbi, "sqlite3_prepare",
1585  sqlite3_prepare(sqlI, scp->cmd, (int)strlen(scp->cmd),
1586  &scp->pStmt, (const char **) &scp->pzErrmsg));
1587  rc = cvtdberr(dbi, "sql_bind_key",
1588  sql_bind_key(dbi, scp, 1, key));
1589  rc = cvtdberr(dbi, "sql_bind_data",
1590  sql_bind_data(dbi, scp, 2, data));
1591 
1592  rc = sql_step(dbi, scp);
1593  if (rc) rpmlog(RPMLOG_WARNING, "cput(%s) sql_step rc %d\n", dbi->dbi_subfile, rc);
1594 
1595  break;
1596  }
1597 
1598  scp = scpFree(scp);
1599 
1600 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,%p,0x%x) rc %d subfile %s %s\n", __FUNCTION__, dbi, dbcursor, key, data, flags, rc, dbi->dbi_subfile, _KEYDATA(key, NULL, data, NULL)));
1601  return rc;
1602 }
1603 
1609 static int sql_byteswapped (dbiIndex dbi)
1610  /*@globals fileSystem, internalState @*/
1611  /*@modifies fileSystem, internalState @*/
1612 {
1613  int rc = 0; /* XXX FIXME: assume native always */
1614 #if defined(NOISY)
1615 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p) rc %d subfile %s\n", __FUNCTION__, dbi, rc, dbi->dbi_subfile));
1616 #endif
1617  return rc;
1618 }
1619 
1628 static int sql_associate (/*@unused@*/ dbiIndex dbi,
1629  /*@unused@*/ dbiIndex dbisecondary,
1630  /*@unused@*/int (*callback) (DB *, const DBT *, const DBT *, DBT *),
1631  /*@unused@*/ unsigned int flags)
1632  /*@*/
1633 {
1634  int rc = EINVAL;
1635 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,0x%x) rc %d subfile %s\n", __FUNCTION__, dbi, dbisecondary, callback, flags, rc, dbi->dbi_subfile));
1636  return rc;
1637 }
1638 
1647 static int sql_associate_foreign (/*@unused@*/ dbiIndex dbi,
1648  /*@unused@*/ dbiIndex dbisecondary,
1649  /*@unused@*/int (*callback) (DB *, const DBT *, DBT *, const DBT *, int *),
1650  /*@unused@*/ unsigned int flags)
1651  /*@*/
1652 {
1653  int rc = EINVAL;
1654 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,0x%x) rc %d subfile %s\n", __FUNCTION__, dbi, dbisecondary, callback, flags, rc, dbi->dbi_subfile));
1655  return rc;
1656 }
1657 
1666 static int sql_join (/*@unused@*/ dbiIndex dbi,
1667  /*@unused@*/ DBC ** curslist,
1668  /*@unused@*/ /*@out@*/ DBC ** dbcp,
1669  /*@unused@*/ unsigned int flags)
1670  /*@globals fileSystem @*/
1671  /*@modifies dbi, *dbcp, fileSystem @*/
1672 {
1673  int rc = EINVAL;
1674 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,0x%x) rc %d\n", __FUNCTION__, dbi, curslist, dbcp, flags, rc));
1675  return rc;
1676 }
1677 
1686 static int sql_cdup (/*@unused@*/ dbiIndex dbi,
1687  /*@unused@*/ DBC * dbcursor,
1688  /*@unused@*/ /*@out@*/ DBC ** dbcp,
1689  /*@unused@*/ unsigned int flags)
1690  /*@globals fileSystem @*/
1691  /*@modifies dbi, *dbcp, fileSystem @*/
1692 {
1693  int rc = EINVAL;
1694 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,0x%x) rc %d\n", __FUNCTION__, dbi, dbcursor, dbcp, flags, rc));
1695  return rc;
1696 }
1697 
1708 static int sql_cpget (/*@unused@*/ dbiIndex dbi,
1709  /*@unused@*/ /*@null@*/ DBC * dbcursor,
1710  /*@unused@*/ DBT * key,
1711  /*@unused@*/ DBT * pkey,
1712  /*@unused@*/ DBT * data,
1713  /*@unused@*/ unsigned int flags)
1714  /*@globals fileSystem @*/
1715  /*@modifies *dbcursor, *key, *pkey, *data, fileSystem @*/
1716 {
1717  int rc = EINVAL;
1718 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,%p,%p,0x%x) rc %d %s\n", __FUNCTION__, dbi, dbcursor, key, pkey, data, flags, rc, _KEYDATA(key, pkey, data, NULL)));
1719  return rc;
1720 }
1721 
1730 static int sql_ccount (/*@unused@*/ dbiIndex dbi,
1731  /*@unused@*/ DBC * dbcursor,
1732  /*@unused@*/ /*@out@*/ unsigned int * countp,
1733  /*@unused@*/ unsigned int flags)
1734  /*@globals fileSystem @*/
1735  /*@modifies *dbcursor, fileSystem @*/
1736 {
1737  int rc = EINVAL;
1738 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,0x%x) rc %d\n", __FUNCTION__, dbi, dbcursor, countp, flags, rc));
1739  return rc;
1740 }
1741 
1742 static int sql_stat_cb(void * _dbi, int argc, char ** argv, char ** cols)
1743 {
1744  dbiIndex dbi = (dbiIndex) _dbi;
1745  int rc = -1;
1746  if (dbi && argc == 1) {
1747  char * end = NULL;
1748  dbi->dbi_table_nkeys = strtoll(argv[0], &end, 10);
1749  if (end && *end == '\0') rc = 0;
1750  }
1751 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p[%d],%p) rc %d table_nkeys %llu\n", __FUNCTION__, _dbi, argv, argc, cols, rc, (unsigned long long) (dbi ? dbi->dbi_table_nkeys : 0)));
1752  return rc;
1753 }
1754 
1761 static int sql_stat (dbiIndex dbi, /*@unused@*/ unsigned int flags)
1762  /*@globals fileSystem, internalState @*/
1763  /*@modifies dbi, fileSystem, internalState @*/
1764 {
1765  char * cmd;
1766  int rc = 0;
1767 
1768  dbi->dbi_table_nkeys = -1;
1769 
1770  cmd = sqlite3_mprintf(" SELECT COUNT('key') FROM '%q';", dbi->dbi_subfile);
1771  rc = sql_exec(dbi, cmd, sql_stat_cb, dbi);
1772  cmd = _free(cmd);
1773 
1774  if (dbi->dbi_table_nkeys < 0)
1775  dbi->dbi_table_nkeys = 4096; /* XXX hacky */
1776 
1777  dbi->dbi_stats = _free(dbi->dbi_stats);
1778  { DB_HASH_STAT * _stats = (DB_HASH_STAT *) xcalloc(1, sizeof(*_stats));
1779  _stats->hash_nkeys = dbi->dbi_table_nkeys;
1780  dbi->dbi_stats = (void *) _stats;
1781  }
1782 
1783 SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,0x%x) rc %d subfile %s\n", __FUNCTION__, dbi, flags, rc, dbi->dbi_subfile));
1784  return rc;
1785 }
1786 
1787 /* Major, minor, patch version of DB.. we're not using db.. so set to 0 */
1788 /* open, close, sync, associate, asociate_foreign, join */
1789 /* cursor_open, cursor_close, cursor_dup, cursor_delete, cursor_get, */
1790 /* cursor_pget?, cursor_put, cursor_count */
1791 /* db_bytewapped, stat */
1792 /*@observer@*/ /*@unchecked@*/
1793 struct _dbiVec sqlitevec = {
1794  "Sqlite " SQLITE_VERSION,
1795  ((SQLITE_VERSION_NUMBER / (1000 * 1000)) % 1000),
1796  ((SQLITE_VERSION_NUMBER / ( 1000)) % 1000),
1797  ((SQLITE_VERSION_NUMBER ) % 1000),
1798  sql_open,
1799  sql_close,
1800  sql_sync,
1801  sql_associate,
1803  sql_join,
1804  sql_exists,
1805  sql_seqno,
1806  sql_copen,
1807  sql_cclose,
1808  sql_cdup,
1809  sql_cdel,
1810  sql_cget,
1811  sql_cpget,
1812  sql_cput,
1813  sql_ccount,
1815  sql_stat
1816 };
1817 
1818 /*@=evalorderuncon@*/
1819 /*@=modfilesystem@*/
1820 /*@=compmempass@*/
1821 /*@=compdef@*/
1822 /*@=moduncon@*/
1823 /*@=noeffectuncon@*/
1824 /*@=globuse@*/
1825 /*@=paramuse@*/
1826 /*@=mustmod@*/
rpmioPool _scpPool
Definition: sqlite.c:475
static SCP_t scpGetPool(rpmioPool pool)
Definition: sqlite.c:477
#define scpUnlink(_scp)
Definition: sqlite.c:305
#define scpFree(_scp)
Definition: sqlite.c:328
static int sql_bind_key(dbiIndex dbi, SCP_t scp, int pos, DBT *key)
Definition: sqlite.c:662
static int sql_join(dbiIndex dbi, DBC **curslist, DBC **dbcp, unsigned int flags)
Return join cursor for list of cursors.
Definition: sqlite.c:1666
enum urltype_e urltype
Supported URL types.
const char const char * cmd
Definition: mongo.h:777
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
static int sql_stat(dbiIndex dbi, unsigned int flags)
Save statistics in database handle.
Definition: sqlite.c:1761
struct rpmsql_s * rpmsql
Definition: rpmsql.h:20
Definition: libsql.c:29
static int sql_ccount(dbiIndex dbi, DBC *dbcursor, unsigned int *countp, unsigned int flags)
Retrieve count of (possible) duplicate items using dbcursor->c_count.
Definition: sqlite.c:1730
static void dbg_scp(void *ptr)
Definition: sqlite.c:331
static size_t nDBTflags
Definition: sqlite.c:144
const char int time
Definition: bson.h:1005
void * lkey
Definition: sqlite.c:281
sqlite3_stmt * pStmt
Definition: sqlite.c:259
static int Xcvtdberr(dbiIndex dbi, const char *msg, int error, int printit, const char *func, const char *fn, unsigned ln)
Definition: sqlite.c:222
int rpmioMkpath(const char *path, mode_t mode, uid_t uid, gid_t gid)
Insure that directories in path exist, creating as needed.
Definition: rpmio.c:3017
#define DB_SET
Definition: db_emu.h:88
char * pzErrmsg
Definition: sqlite.c:260
static int sql_bind_data(dbiIndex dbi, SCP_t scp, int pos, DBT *data)
Definition: sqlite.c:730
struct key_s KEY
#define DB_DBT_MULTIPLE
Definition: db_emu.h:36
static int sql_sync(dbiIndex dbi, unsigned int flags)
Flush pending operations to disk.
Definition: sqlite.c:1237
static int sql_seqno(dbiIndex dbi, int64_t *seqnop, unsigned int flags)
Return next sequence number.
Definition: sqlite.c:1297
unsigned short rpmuint16_t
Definition: rpmiotypes.h:27
static void dbg_keyval(const char *msg, dbiIndex dbi, DBC *dbcursor, DBT *key, DBT *data, unsigned int flags)
Definition: sqlite.c:342
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
static int sql_cput(dbiIndex dbi, DBC *dbcursor, DBT *key, DBT *data, unsigned int flags)
Store (key,data) pair using db->put or dbcursor->c_put.
Definition: sqlite.c:1566
#define DB_NOTFOUND
Definition: db_emu.h:94
static int sql_initDB(dbiIndex dbi)
Verify the DB is setup.
Definition: sqlite.c:912
static void scpFini(void *_scp)
Definition: sqlite.c:461
#define UINT32_T
Definition: sqlite.c:61
static int sql_open(rpmdb rpmdb, rpmTag rpmtag, dbiIndex *dbip)
Return handle for an index database.
Definition: sqlite.c:1131
char ** av
Definition: sqlite.c:264
static int sql_seqno_cb(void *_dbi, int argc, char **argv, char **cols)
Definition: sqlite.c:1276
rpmsql rpmsqlNew(char **av, uint32_t flags)
Create and load a sql interpreter.
Definition: rpmsql.c:5450
#define _DBT_ENTRY(_v)
Definition: sqlite.c:129
Yet Another syslog(3) API clone.
static int xisprint(int c)
Definition: rpmiotypes.h:564
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
static int sql_cdel(dbiIndex dbi, DBC *dbcursor, DBT *key, DBT *data, unsigned int flags)
Delete (key,data) pair(s) using db->del or dbcursor->c_del.
Definition: sqlite.c:1348
static size_t ntagTypes
Definition: sqlite.c:892
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
void * data
Definition: db_emu.h:22
#define RPMDBI_SEQNO
Definition: rpmtag.h:488
int _scp_debug
Definition: sqlite.c:293
const char const bson_bool_t v
Definition: bson.h:919
#define scpLink(_scp)
Definition: sqlite.c:316
static SCP_t scpResetKeys(SCP_t scp)
Definition: sqlite.c:367
size_t * avlen
Definition: sqlite.c:266
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:220
#define SQLDBDEBUG(_dbi, _list)
Definition: sqlite.c:70
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:26
static int sql_busy_handler(void *_dbi, int time)
Definition: sqlite.c:760
#define cvtdberr(_dbi, _msg, _error)
Definition: sqlite.c:247
unsigned int tagType(rpmTag tag)
Return tag data type from value.
Definition: tagname.c:441
struct rpmioItem_s _item
Definition: sqlite.c:253
const char const bson * data
Definition: mongo.h:463
unsigned long long rpmuint64_t
Definition: rpmiotypes.h:29
uint32_t v
Definition: libsql.c:31
static int sql_exec(dbiIndex dbi, const char *cmd, int(*callback)(void *, int, char **, char **), void *context)
Definition: sqlite.c:745
const char * tagName(rpmTag tag)
Return tag name from value.
Definition: tagname.c:436
static int sql_cget(dbiIndex dbi, DBC *dbcursor, DBT *key, DBT *data, unsigned int flags)
Retrieve (key,data) pair using db->get or dbcursor->c_get.
Definition: sqlite.c:1394
DBT ** keys
Definition: sqlite.c:275
void * ldata
Definition: sqlite.c:283
static int sql_cdup(dbiIndex dbi, DBC *dbcursor, DBC **dbcp, unsigned int flags)
Duplicate a database cursor.
Definition: sqlite.c:1686
const char * rpmGenPath(const char *urlroot, const char *urlmdir, const char *urlfile)
Merge 3 args into path, any or all of which may be a url.
Definition: macro.c:3477
struct rpmdb_s * rpmdb
Database of headers and tag value indices.
Definition: rpmtypes.h:43
#define _KEYDATA(_K, _P, _D, _R)
Definition: sqlite.c:219
static SCP_t scpNew(void *dbp)
Definition: sqlite.c:493
static SCP_t scpReset(SCP_t scp)
Definition: sqlite.c:428
static char * fmtDBT(const DBT *K, char *te)
Definition: sqlite.c:146
uint32_t size
Definition: db_emu.h:23
uint32_t flags
Definition: db_emu.h:43
const char const bson int mongo_write_concern int flags
Definition: mongo.h:485
uint32_t hash_nkeys
Definition: db_emu.h:56
static int sql_cclose(dbiIndex dbi, DBC *dbcursor, unsigned int flags)
Close database cursor.
Definition: sqlite.c:1061
int rpmint32_t
Definition: rpmiotypes.h:33
rpmsql rpmsqlFree(rpmsql sql)
Destroy a sql interpreter.
static int sql_cpget(dbiIndex dbi, DBC *dbcursor, DBT *key, DBT *pkey, DBT *data, unsigned int flags)
Retrieve (key,data) pair using dbcursor->c_pget.
Definition: sqlite.c:1708
const char const int i
Definition: bson.h:778
static int sql_associate_foreign(dbiIndex dbi, dbiIndex dbisecondary, int(*callback)(DB *, const DBT *, DBT *, const DBT *, int *), unsigned int flags)
Associate secondary database with primary.
Definition: sqlite.c:1647
#define DB_PRIVATE
Definition: db_emu.h:98
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:430
static int snprintf(char *buf, int nb, const char *fmt,...)
Definition: rpmps.c:220
const char const bson * key
Definition: mongo.h:717
static KEY DBTflags[]
Definition: sqlite.c:131
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
Definition: rpmmalloc.c:109
Definition: db_emu.h:72
static const char * tagTypes[]
Definition: sqlite.c:880
#define DB_EXCL
Definition: db_emu.h:97
char * stpcpy(char *dest, const char *src)
static int sql_copen(dbiIndex dbi, DB_TXN *txnid, DBC **dbcp, unsigned int flags)
Open database cursor.
Definition: sqlite.c:1317
static const char * fmtBits(uint32_t flags, KEY tbl[], size_t ntbl, char *t)
Definition: sqlite.c:103
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
static const char seqno_inc_cmd[]
Definition: sqlite.c:1268
static const char * tblName(uint32_t v, KEY *tbl, size_t ntbl)
Definition: sqlite.c:83
int _sqldb_debug
Definition: sqlite.c:68
static int sql_byteswapped(dbiIndex dbi)
Is database byte swapped?
Definition: sqlite.c:1609
static SCP_t scpResetAv(SCP_t scp)
Definition: sqlite.c:390
#define RPM_MASK_TYPE
Definition: rpmtag.h:43
Definition: db_emu.h:17
static const char * name
struct _sql_dbcursor_s * SCP_t
Definition: sqlite.c:251
#define _(Text)
Definition: system.h:29
#define xmalloc
Definition: system.h:32
static const char * fmtKDR(const DBT *K, const DBT *P, const DBT *D, const DBT *R)
Definition: sqlite.c:193
Access RPM indices using Berkeley DB interface(s).
enum rpmTag_e rpmTag
Definition: rpmtag.h:470
#define D_(Text)
Definition: system.h:526
static int sql_close(dbiIndex dbi, unsigned int flags)
Close index database, and destroy database handle.
Definition: sqlite.c:1089
const char * n
Definition: db3.c:184
static const char _Packages_sql_init[]
Definition: sqlite.c:781
struct _dbiVec sqlitevec
Definition: sqlite.c:1793
#define DB_DBT_MALLOC
Definition: db_emu.h:35
#define RPMDBI_PACKAGES
Pseudo-tags used by the rpmdb and rpmgi iterator API's.
Definition: rpmtag.h:479
#define xrealloc
Definition: system.h:35
#define SET(opt)
Definition: fts.c:197
char * cmd
Definition: sqlite.c:257
static int sql_exists(dbiIndex dbi, DBT *key, unsigned int flags)
Return whether key exists in a database.
Definition: sqlite.c:1256
static int sql_associate(dbiIndex dbi, dbiIndex dbisecondary, int(*callback)(DB *, const DBT *, const DBT *, DBT *), unsigned int flags)
Associate secondary database with primary.
Definition: sqlite.c:1628
static int sql_step(dbiIndex dbi, SCP_t scp)
Definition: sqlite.c:511
struct _dbiIndex * dbiIndex
Definition: rpmdb.h:59
static int sql_stat_cb(void *_dbi, int argc, char **argv, char **cols)
Definition: sqlite.c:1742
static int sql_initDB_cb(void *_dbi, int argc, char **argv, char **cols)
Definition: sqlite.c:894
#define SCPDEBUG(_dbi, _list)
Definition: sqlite.c:295
int Unlink(const char *path)
unlink(2) clone.
Definition: rpmrpc.c:397