5 #define _RPMIOB_INTERNAL
12 #if defined(WITH_DBSQL)
14 #elif defined(WITH_SQLITE)
15 #define SQLITE_OS_UNIX 1
16 #define SQLITE_THREADSAFE 1
17 #define SQLITE_THREAD_OVERRIDE_LOCK -1
18 #define SQLITE_TEMP_STORE 1
22 #define _RPMSQL_INTERNAL
23 #define _RPMVT_INTERNAL
24 #define _RPMVC_INTERNAL
28 #include <editline/readline.h>
29 #elif defined(HAVE_READLINE) && HAVE_READLINE==1
30 # include <readline/readline.h>
31 # include <readline/history.h>
34 # define readline(sql, p) local_getline(sql, p)
35 # define add_history(X)
36 # define read_history(X)
37 # define write_history(X)
38 # define stifle_history(X)
57 #if defined(WITH_SQLITE)
59 static struct rpmsql_s _sql;
64 #define VTDBG(_vt, _l) if ((_vt)->debug) fprintf _l
65 #define VTDBGNOISY(_vt, _l) if ((_vt)->debug < 0) fprintf _l
74 struct rpmVT_s * VT = _VT;
78 VTDBGNOISY(vt, (stderr,
"==> %s(%p)\n", __FUNCTION__, vt));
98 if (_rpmvtPool == NULL) {
103 VT = (
struct rpmVT_s *)
rpmioGetPool(pool,
sizeof(*VT));
104 memset(((
char *)VT)+
sizeof(VT->_item), 0,
sizeof(*VT)-
sizeof(VT->_item));
115 if (vd->split && vd->parse && *vd->parse) {
116 char * parse =
rpmExpand(vd->parse, NULL);
118 xx =
argvSplit(&vt->fields, parse, vd->split);
121 parse =
_free(parse);
130 VTDBG(vt, (stderr,
"\tdbpath: %s\n", vd->dbpath));
131 VTDBG(vt, (stderr,
"\tprefix: %s\n", vd->prefix));
132 VTDBG(vt, (stderr,
"\t split: %s\n", vd->split));
133 VTDBG(vt, (stderr,
"\t parse: %s\n", vd->parse));
134 VTDBG(vt, (stderr,
"\t regex: %s\n", vd->regex));
141 #if defined(WITH_SQLITE)
143 typedef struct key_s {
147 static KEY sqlTypes[] = {
148 {
"blob", SQLITE_BLOB },
149 {
"float", SQLITE_FLOAT },
150 {
"int", SQLITE_INTEGER },
151 {
"integer",SQLITE_INTEGER },
152 {
"null", SQLITE_NULL },
153 {
"text", SQLITE_TEXT },
155 static size_t nsqlTypes =
sizeof(sqlTypes) /
sizeof(sqlTypes[0]);
157 static const char * hasSqlType(
const char * s)
160 for (i = 0; i < (int)nsqlTypes; i++) {
161 const char * k = sqlTypes[i].k;
162 const char * se = strcasestr(s, k);
163 if (se == NULL || se <= s || se[-1] !=
' ')
166 if (*se && *se !=
' ')
173 static char * _rpmvtJoin(
const char * a,
const char ** argv,
const char * z)
175 static const char _type[] =
" TEXT";
177 size_t na = (
sizeof(
"\t")-1) + (a ? strlen(a) : 0);
179 size_t nz = (z ? strlen(z) : 0) + strlen(_type) + (sizeof(
",\n")-1);
182 for (av = argv; *av != NULL; av++)
183 nb += na + strlen(*av) + nz;
186 for (av = argv; *av != NULL; av++) {
190 if (hasSqlType(*av) == NULL)
201 static char * _rpmvtAppendCols(
rpmvt vt,
const char ** av)
203 char * h = _rpmvtJoin(
"", av,
"");
209 int fx = (vd->fx == 3 ? 3 : 4);
211 av = (
const char **) (vt->argc > fx ? &vt->argv[fx] : vt->fields);
213 u = _rpmvtJoin(
"", av,
"");
214 u[strlen(u)-2] =
' ';
217 #define dbN vt->argv[1]
218 #define tblN vt->argv[2]
219 hu =
rpmExpand(
"CREATE TABLE ", dbN,
".", tblN,
" (\n", h, u,
");", NULL);
226 VTDBG(vt, (stderr,
"%s\n", hu));
232 sqlite3 * db = (sqlite3 *) vt->db;
235 static const char * hidden[] = {
"path HIDDEN",
"id HIDDEN", NULL };
241 const char * fn = NULL;
246 VTDBG(vt, (stderr,
"--> %s(%p,%p)\n", __FUNCTION__, vt, vtp));
251 hu = _rpmvtAppendCols(vt, hidden);
253 sqlite3_declare_vtab(db, hu));
258 static char _quotes[] =
"'\"";
259 int quoted = (strchr(_quotes, *vt->argv[3]) != NULL);
261 const char * path = NULL;
263 (void)
urlPath(vt->argv[3]+quoted, &path);
264 prefix = (*path !=
'/' && vd->prefix ? vd->prefix :
"");
266 uri[strlen(uri)-quoted] =
'\0';
270 (void)
urlPath(uri, (
const char **) &fn);
272 if (!strcasecmp(vt->argv[0],
"nixdb")) {
273 const char * out =
rpmExpand(
"%{sql ", vd->dbpath,
":",
274 "select path from ValidPaths where glob('", fn,
"', path);",
280 if (!strcasecmp(vt->argv[0],
"Env")) {
283 fprintf(stderr,
" ENV: getenv(%p[%d])\n", &vt->argv[fx],
argvCount(&vt->argv[fx]));
290 fprintf(stderr,
"*** uri %s fn %s\n", uri, fn);
292 const char ** av = NULL;
297 fprintf(stderr,
"GLOB: %d = Glob(%s) av %p[%d]\n", xx, uri, av, ac);
299 rc = SQLITE_NOTFOUND;
304 if (uri[strlen(uri)-1] ==
'/') {
305 DIR * dir = Opendir(uri);
308 fprintf(stderr,
" DIR: %p = Opendir(%s)\n", dir, uri);
310 rc = SQLITE_NOTFOUND;
312 while ((dp = Readdir(dir)) != NULL) {
313 if (!strcmp(dp->d_name,
".") || !strcmp(dp->d_name,
".."))
319 if (dir) xx = Closedir(dir);
321 if (!
Lstat(uri, &sb)) {
325 fprintf(stderr,
"FILE: %d = Slurp(%s)\n", xx, uri);
329 rc = SQLITE_NOTFOUND;
332 rc = SQLITE_NOTFOUND;
336 fprintf(stderr,
"LIST: %d = Append(%p[%d])\n", xx, &vt->argv[3],
argvCount(&vt->argv[3]));
351 (void) rpmvtFree(vt);
359 VTDBG(vt, (stderr,
"<-- %s(%p,%p) rc %d\n", __FUNCTION__, vt, vtp, rc));
366 static struct rpmvd_s _argVD = {
369 int rpmvtCreate(
void * _db,
void * pAux,
370 int argc,
const char *
const * argv,
371 rpmvt * vtp,
char ** pzErr)
373 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_argVD), vtp);
376 int rpmvtConnect(
void * _db,
void * pAux,
377 int argc,
const char *
const * argv,
378 rpmvt * vtp,
char ** pzErr)
380 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_argVD), vtp);
384 static void dumpInfo(
const char * msg,
const struct sqlite3_index_info * s)
386 fprintf(stderr,
"--------------------- %s\n", (msg ? msg :
""));
387 #define _PRT(f,v) fprintf(stderr, "%20s: " #f "\n", #v, s->v)
388 _PRT(%p, aConstraintUsage);
391 _PRT(%d, needToFreeIdxStr);
392 _PRT(%d, orderByConsumed);
393 _PRT(%g, estimatedCost);
398 int rpmvtBestIndex(
rpmvt vt,
void * _pInfo)
400 sqlite3_index_info * pInfo = (sqlite3_index_info *) _pInfo;
406 VTDBG(vt, (stderr,
"--> %s(%p,%p)\n", __FUNCTION__, vt, pInfo));
409 if (pInfo->aConstraint)
410 for (i = 0; i < pInfo->nConstraint; i++) {
411 const struct sqlite3_index_constraint * p = pInfo->aConstraint + i;
412 fprintf(stderr,
"\tcol %s(%d) 0x%02x 0x%02x\n", vt->cols[p->iColumn], p->iColumn,
416 for (i = 0; i < pInfo->nOrderBy; i++) {
417 const struct sqlite3_index_orderby * p = pInfo->aOrderBy + i;
418 fprintf(stderr,
"\tcol %s(%d) %s\n", vt->cols[p->iColumn], p->iColumn,
419 (p->desc ?
"DESC" :
"ASC"));
421 dumpInfo(__FUNCTION__, pInfo);
424 VTDBG(vt, (stderr,
"<-- %s(%p,%p) rc %d\n", __FUNCTION__, vt, pInfo, rc));
429 int rpmvtDisconnect(
rpmvt vt)
431 (void) rpmvtFree(vt);
435 int rpmvtDestroy(
rpmvt vt)
437 (void) rpmvtFree(vt);
441 static const char * dumpArg(
rpmvArg _v)
443 static char buf[BUFSIZ];
445 size_t nb =
sizeof(buf);
446 sqlite3_value * v = (sqlite3_value *) _v;
447 int vtype = sqlite3_value_type(v);
448 unsigned long long ll;
453 snprintf(b, nb,
"%p(%d)", v, vtype);
459 ll = (
unsigned long long) sqlite3_value_int64(v);
463 d = sqlite3_value_double(v);
467 p = sqlite3_value_blob(v);
474 s = (
const char *)sqlite3_value_text(v);
485 static void dumpArgv(
const char * msg,
int argc,
rpmvArg * _argv)
487 if (argc > 0 && _argv) {
489 fprintf(stderr,
"--------------------- %s\n", (msg ? msg :
""));
490 for (i = 0; i < argc; i++)
491 fprintf(stderr,
"\targv[%d] %s\n", i, dumpArg(_argv[i]));
495 int rpmvtUpdate(
rpmvt vt,
int argc,
rpmvArg * _argv, int64_t * pRowid)
497 sqlite3_value ** argv = (sqlite3_value **) _argv;
500 VTDBG(vt, (stderr,
"--> %s(%p,%p[%u],%p)\n", __FUNCTION__, vt, argv, (
unsigned)argc, pRowid));
502 if (argc == 0 || argv == NULL) {
504 dumpArgv(
"ERROR", argc, _argv);
505 rc = SQLITE_NOTFOUND;
508 VTDBG(vt, (stderr,
"\tDELETE ROW 0x%llx\n", *(
unsigned long long *)argv[0]));
510 if (argv[0] == NULL) {
511 VTDBG(vt, (stderr,
"\tADD ROW 0x%llx\n", *(
unsigned long long *)argv[1]));
513 dumpArgv(
"ADD ROW", argc, _argv);
515 if (argv[0] == argv[1]) {
516 VTDBG(vt, (stderr,
"\tUPDATE ROW 0x%llx\n", *(
unsigned long long *)argv[1]));
518 dumpArgv(
"UPDATE argv", argc-2, _argv+2);
520 VTDBG(vt, (stderr,
"\tREPLACE ROW 0x%llx from 0x%llx\n",
521 *(
unsigned long long *)argv[0], *(
unsigned long long *)argv[1]));
523 dumpArgv(
"REPLACE argv", argc-2, _argv+2);
526 VTDBG(vt, (stderr,
"<-- %s(%p,%p[%u],%p) rc %d\n", __FUNCTION__, vt, argv, (
unsigned)argc, pRowid, rc));
530 int rpmvtBegin(
rpmvt vt)
533 VTDBG(vt, (stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, vt, rc));
537 int rpmvtSync(
rpmvt vt)
540 VTDBG(vt, (stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, vt, rc));
544 int rpmvtCommit(
rpmvt vt)
547 VTDBG(vt, (stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, vt, rc));
551 int rpmvtRollback(
rpmvt vt)
554 VTDBG(vt, (stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, vt, rc));
558 int rpmvtFindFunction(
rpmvt vt,
int nArg,
const char * zName,
559 void (**pxFunc)(
void *,
int,
rpmvArg *),
563 VTDBG(vt, (stderr,
"<-- %s(%p,%d,%s,%p,%p) rc %d\n", __FUNCTION__, vt, nArg, zName, pxFunc, ppArg, rc));
567 int rpmvtRename(
rpmvt vt,
const char * zNew)
570 VTDBG(vt, (stderr,
"<-- %s(%p,%s) rc %d\n", __FUNCTION__, vt, zNew, rc));
577 #define VCDBG(_vc, _l) if ((_vc)->debug) fprintf _l
578 #define VCDBGNOISY(_vc, _l) if ((_vc)->debug < 0) fprintf _l
587 struct rpmVC_s * VC = _VC;
590 VCDBGNOISY(vc, (stderr,
"==> %s(%p)\n", __FUNCTION__, vc));
592 (void) rpmvtFree(vc->vt);
605 if (_rpmvcPool == NULL) {
610 VC = (
struct rpmVC_s *)
rpmioGetPool(pool,
sizeof(*VC));
611 memset(((
char *)VC)+
sizeof(VC->_item), 0,
sizeof(*VC)-
sizeof(VC->_item));
619 vc->vt = rpmvtLink(vt);
631 #if defined(WITH_SQLITE)
641 (
void) rpmvcFree(vc);
646 int rpmvcClose(
rpmvc vc)
650 (void) rpmvtFree(vc->vt);
652 (void) rpmvcFree(vc);
656 int rpmvcFilter(
rpmvc vc,
int idxNum,
const char * idxStr,
659 sqlite3_value ** argv = (sqlite3_value **) _argv;
662 VCDBGNOISY(vc, (stderr,
"--> %s(%p,%d,%s,%p[%u]) [%d:%d]\n", __FUNCTION__, vc, idxNum, idxStr, argv, (
unsigned)argc, vc->ix, vc->nrows));
663 dumpArgv(__FUNCTION__, argc, _argv);
668 VCDBGNOISY(vc, (stderr,
"<-- %s(%p,%d,%s,%p[%u]) [%d:%d] rc %d\n", __FUNCTION__, vc, idxNum, idxStr, argv, (
unsigned)argc, vc->ix, vc->nrows, rc));
673 int rpmvcNext(
rpmvc vc)
677 if (vc->ix >= 0 && vc->ix < vc->nrows)
680 if (!(vc->ix >= 0 && vc->ix < vc->nrows))
681 VCDBGNOISY(vc, (stderr,
"<-- %s(%p) rc %d (%d:%d)\n", __FUNCTION__, vc, rc, vc->ix, vc->nrows));
685 int rpmvcEof(
rpmvc vc)
687 int rc = (vc->ix >= 0 && vc->ix < vc->nrows ? 0 : 1);
690 VCDBGNOISY(vc, (stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, vc, rc));
696 int rpmvcColumn(
rpmvc vc,
void * _pContext,
int colx)
698 sqlite3_context * pContext = (sqlite3_context *) _pContext;
701 const char * path = vt->av[vc->ix];
702 const char * col = vt->cols[colx];
708 int * offsets = NULL;
719 nb = noffsets *
sizeof(*offsets);
720 offsets = memset(
alloca(nb), -1, nb);
727 for (i = 0; i < noffsets; i += 2) {
730 assert(offsets[i ] >= 0 && offsets[i ] <= (
int)nb);
731 assert(offsets[i+1] >= 0 && offsets[i+1] <= (
int)nb);
732 offsets[i+1] -= offsets[i];
733 VCDBGNOISY(vc, (stderr,
"\t%d [%d,%d] %.*s\n", i/2, offsets[i], offsets[i+1], offsets[i+1], path+offsets[i]));
738 if (!strcmp(col,
"path"))
739 sqlite3_result_text(pContext, path, -1, SQLITE_STATIC);
744 for (i = 0; i < vt->nfields; i++) {
748 if (path[0] ==
'/' && !strcmp(
"*", vt->fields[i])) {
749 const char * fn =
rpmGetPath(path,
"/", col, NULL);
756 sqlite3_result_null(pContext);
759 if (!strcmp(col, vt->fields[i])) {
760 int ix = 2 * (i + 1);
761 const char * s = path + offsets[ix];
762 size_t ns = offsets[ix+1];
763 sqlite3_result_text(pContext, s, ns, SQLITE_STATIC);
767 if (i == vt->nfields)
768 sqlite3_result_null(pContext);
770 if (vd->split && strlen(vd->split) == 1 && vt->nfields > 0) {
776 for (i = 0; i < vt->nfields; i++) {
777 if (strcmp(col, vt->fields[i]))
779 sqlite3_result_text(pContext, av[i], -1, SQLITE_TRANSIENT);
782 if (i == vt->nfields)
783 sqlite3_result_null(pContext);
786 sqlite3_result_null(pContext);
794 VCDBG(vc, (stderr,
"<-- %s(%p,%p,%d) rc %d\n", __FUNCTION__, vc, pContext, colx, rc));
799 int rpmvcRowid(
rpmvc vc, int64_t * pRowid)
807 VCDBG(vc, (stderr,
"<-- %s(%p,%p) rc %d rowid 0x%llx\n", __FUNCTION__, vc, pRowid, rc, (
unsigned long long)(pRowid ? *pRowid : 0xf00)));
815 const char * _func,
const char * _fn,
unsigned _ln)
817 SQLDBG((stderr,
"==> %s:%u %s(%p) _rpmsqlI %p\n", _fn, _ln, _func, sql,
_rpmsqlI));
819 fprintf(stderr,
"\t flags: 0x%x\n", sql->flags);
820 fprintf(stderr,
"\t av: %p[%u]\n", sql->av, (
unsigned)
argvCount(sql->av));
821 fprintf(stderr,
"\t I: %p\n", sql->I);
822 fprintf(stderr,
"\t S: %p\n", sql->S);
823 fprintf(stderr,
"\t init: %s\n", sql->zInitFile);
824 fprintf(stderr,
"\t database: %s\n", sql->zDbFilename);
825 fprintf(stderr,
"\t table: %s\n", sql->zDestTable);
827 fprintf(stderr,
"\t mode: 0x%x\n", sql->mode);
828 fprintf(stderr,
"\t cnt: 0x%x\n", sql->cnt);
829 fprintf(stderr,
"\t iob: %p\n", sql->iob);
830 fprintf(stderr,
"\t IN ifd: %p\n", sql->ifd);
831 fprintf(stderr,
"\t OUT ofd: %p\n", sql->ofd);
832 fprintf(stderr,
"\t LOG lfd: %p\n", sql->lfd);
833 fprintf(stderr,
"\tTRACE tfd: %p\n", sql->tfd);
835 if (sql->explainPrev.valid) {
836 fprintf(stderr,
"\t explain:\n");
837 fprintf(stderr,
"\t\t mode: 0x%x\n", sql->explainPrev.mode);
838 fprintf(stderr,
"\t\tflags: 0x%x\n", sql->explainPrev.flags);
841 fprintf(stderr,
"\tseparator: %.*s\n", (
int)
sizeof(sql->separator), sql->separator);
842 fprintf(stderr,
"\tnullvalue: %.*s\n", (
int)
sizeof(sql->nullvalue), sql->nullvalue);
843 fprintf(stderr,
"\t outfile: %s\n", sql->outfile);
844 fprintf(stderr,
"\t home: %s\n", sql->zHome);
845 fprintf(stderr,
"\t initrc: %s\n", sql->zInitrc);
846 fprintf(stderr,
"\t history: %s\n", sql->zHistory);
847 fprintf(stderr,
"\t prompt: %s\n", sql->zPrompt);
848 fprintf(stderr,
"\t continue: %s\n", sql->zContinue);
850 fprintf(stderr,
"\t buf: %p[%u]\n", sql->buf, (
unsigned)sql->nbuf);
851 fprintf(stderr,
"\t b: %p[%u]\n", sql->b, (
unsigned)sql->nb);
854 #define rpmsqlDebugDump(_sql) \
855 _rpmsqlDebugDump(_sql, __FUNCTION__, __FILE__, __LINE__)
857 #if defined(WITH_SQLITE)
864 static void rpmsql_error(
int lvl,
const char *fmt, ...)
865 #if defined(__GNUC__) && __GNUC__ >= 2
866 __attribute__((format (printf, 2, 3)))
871 rpmsql_error(
int lvl,
const char *fmt, ...)
877 (void) fprintf(stderr,
"Error: ");
879 (void) vfprintf(stderr, fmt, ap);
881 (void) fprintf(stderr,
"\n");
908 db = (sqlite3 *) (_db ? _db : sql->I);
910 db = (sqlite3 *) _db;
911 rpmsql_error(0,
"sqlite3_%s(%p): rc(%d) %s", msg, db, rc,
921 #if defined(WITH_SQLITE)
926 static void _rpmsqlBeginTimer(
rpmsql sql)
928 if (sql->enableTimer)
929 getrusage(RUSAGE_SELF, &sql->sBegin);
933 static double timeDiff(
struct timeval *pStart,
struct timeval *pEnd)
935 return (pEnd->tv_usec - pStart->tv_usec) * 0.000001 +
936 (double) (pEnd->tv_sec - pStart->tv_sec);
943 static void _rpmsqlEndTimer(
rpmsql sql)
945 if (sql->enableTimer) {
951 getrusage(RUSAGE_SELF, &sEnd);
952 snprintf(b,
sizeof(b),
"CPU Time: user %f sys %f\n",
953 timeDiff(&sql->sBegin.ru_utime, &sEnd.ru_utime),
954 timeDiff(&sql->sBegin.ru_stime, &sEnd.ru_stime));
956 nw =
Fwrite(b, 1, nb, sql->ofd);
961 #define BEGIN_TIMER(_sql) _rpmsqlBeginTimer(_sql)
962 #define END_TIMER(_sql) _rpmsqlEndTimer(_sql)
965 #define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
980 SQLDBG((stderr,
"<== %s() _rpmsqlI %p\n", __FUNCTION__,
_rpmsqlI));
984 #if defined(WITH_SQLITE)
990 static int rpmsqlFprintf(
rpmsql sql,
const char *fmt, ...)
991 #if defined(__GNUC__) && __GNUC__ >= 2
992 __attribute__((format (printf, 2, 3)))
995 static int rpmsqlFprintf(
rpmsql sql,
const char *fmt, ...)
998 size_t nb =
sizeof(b);
1002 if (sql == NULL) sql =
rpmsqlI();
1010 if (!(rc >= 0 && rc < (
int)nb))
1016 size_t nw =
Fwrite(b, 1, rc, sql->ofd);
1017 assert((
int)nw == rc);
1031 #ifdef SQLITE_ENABLE_IOTRACE
1032 static void iotracePrintf(
const char *zFormat, ...)
1041 va_start(ap, zFormat);
1042 z = sqlite3_vmprintf(zFormat, ap);
1045 nw =
Fwrite(z, 1, nz, sql->tfd);
1051 #if defined(SQLITE_CONFIG_LOG)
1056 static void shellLog(
void *_sql,
int iErrCode,
const char *zMsg)
1059 if (sql && sql->lfd) {
1061 int xx =
snprintf(num,
sizeof(num),
"(%d) ", iErrCode);
1062 const char * t =
rpmExpand(num, zMsg,
"\n", NULL);
1063 size_t nt = strlen(t);
1064 size_t nw =
Fwrite(t, 1, nt, sql->lfd);
1078 #define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){}
1079 #define sqliteCharVal(X) sqlite3ReadUtf8(X)
1081 #define sqliteNextChar(X) while( ( *++(X)) ) break
1082 #define sqliteCharVal(X) (int)(*(X))
1101 #define GEN_MATH_WRAP_DOUBLE_1(name, function, domain) \
1102 static void name(sqlite3_context *context, int argc, sqlite3_value **argv) {\
1105 switch (sqlite3_value_type(argv[0])) {\
1107 sqlite3_result_null(context);\
1110 rVal = sqlite3_value_double(argv[0]);\
1112 sqlite3_result_error(context, "domain error", -1);\
1114 sqlite3_result_double(context, function(rVal));\
1124 GEN_MATH_WRAP_DOUBLE_1(sqrtFunc, sqrt, rVal < 0)
1127 GEN_MATH_WRAP_DOUBLE_1(acosFunc, acos, rVal < -1.0 || rVal > 1.0)
1128 GEN_MATH_WRAP_DOUBLE_1(asinFunc, asin, rVal < -1.0 || rVal > 1.0)
1129 GEN_MATH_WRAP_DOUBLE_1(atanFunc, atan, 0)
1137 static double acosh(
double x)
1139 return log(x + sqrt(x * x - 1.0));
1143 GEN_MATH_WRAP_DOUBLE_1(acoshFunc, acosh, rVal < 1)
1145 static double asinh(
double x)
1147 return log(x + sqrt(x * x + 1.0));
1151 GEN_MATH_WRAP_DOUBLE_1(asinhFunc, asinh, 0)
1153 static double atanh(
double x)
1155 return (1.0 / 2.0) * log((1 + x) / (1 - x));
1159 GEN_MATH_WRAP_DOUBLE_1(atanhFunc, atanh, rVal > 1.0 || rVal < -1.0)
1164 static
double cot(
double x)
1166 return 1.0 / tan(x);
1169 GEN_MATH_WRAP_DOUBLE_1(sinFunc, sin, 0)
1170 GEN_MATH_WRAP_DOUBLE_1(cosFunc, cos, 0)
1171 GEN_MATH_WRAP_DOUBLE_1(tanFunc, tan, 0)
1172 GEN_MATH_WRAP_DOUBLE_1(cotFunc, cot, 0)
1174 static
double coth(
double x)
1176 return 1.0 / tanh(x);
1184 static double sinh(
double x)
1186 return (exp(x) - exp(-x)) / 2.0;
1189 GEN_MATH_WRAP_DOUBLE_1(sinhFunc, sinh, 0)
1192 static double cosh(
double x)
1194 return (exp(x) + exp(-x)) / 2.0;
1197 GEN_MATH_WRAP_DOUBLE_1(coshFunc, cosh, 0)
1200 static double tanh(
double x)
1202 return sinh(x) / cosh(x);
1205 GEN_MATH_WRAP_DOUBLE_1(tanhFunc, tanh, 0)
1206 GEN_MATH_WRAP_DOUBLE_1(cothFunc, coth, 0)
1212 static double log10(
double x)
1214 static double l10 = -1.0;
1218 return log(x) / l10;
1221 GEN_MATH_WRAP_DOUBLE_1(logFunc, log, rVal <= 0.0)
1222 GEN_MATH_WRAP_DOUBLE_1(log10Func, log10, rVal <= 0.0)
1223 GEN_MATH_WRAP_DOUBLE_1(expFunc, exp, 0)
1233 #define M_PI 3.14159265358979323846
1239 static double deg2rad(
double x)
1241 return x * M_PI / 180.0;
1247 static double rad2deg(
double x)
1249 return 180.0 * x / M_PI;
1251 GEN_MATH_WRAP_DOUBLE_1(rad2degFunc, rad2deg, 0)
1252 GEN_MATH_WRAP_DOUBLE_1(deg2radFunc, deg2rad, 0)
1257 static
void piFunc(sqlite3_context * context,
1258 int argc, sqlite3_value ** argv)
1260 sqlite3_result_double(context, M_PI);
1268 static void squareFunc(sqlite3_context * context,
1269 int argc, sqlite3_value ** argv)
1275 switch (sqlite3_value_type(argv[0])) {
1276 case SQLITE_INTEGER:
1277 iVal = sqlite3_value_int64(argv[0]);
1278 sqlite3_result_int64(context, iVal * iVal);
1281 sqlite3_result_null(context);
1284 rVal = sqlite3_value_double(argv[0]);
1285 sqlite3_result_double(context, rVal * rVal);
1295 static void powerFunc(sqlite3_context * context,
1296 int argc, sqlite3_value ** argv)
1303 if (sqlite3_value_type(argv[0]) == SQLITE_NULL
1304 || sqlite3_value_type(argv[1]) == SQLITE_NULL) {
1305 sqlite3_result_null(context);
1307 r1 = sqlite3_value_double(argv[0]);
1308 r2 = sqlite3_value_double(argv[1]);
1311 sqlite3_result_error(context,
"domain error", -1);
1313 sqlite3_result_double(context, pow(r1, r2));
1321 static void atn2Func(sqlite3_context * context,
1322 int argc, sqlite3_value ** argv)
1329 if (sqlite3_value_type(argv[0]) == SQLITE_NULL
1330 || sqlite3_value_type(argv[1]) == SQLITE_NULL) {
1331 sqlite3_result_null(context);
1333 r1 = sqlite3_value_double(argv[0]);
1334 r2 = sqlite3_value_double(argv[1]);
1335 sqlite3_result_double(context, atan2(r1, r2));
1345 static void signFunc(sqlite3_context * context,
1346 int argc, sqlite3_value ** argv)
1352 switch (sqlite3_value_type(argv[0])) {
1353 case SQLITE_INTEGER:
1354 iVal = sqlite3_value_int64(argv[0]);
1355 iVal = (iVal > 0) ? 1 : (iVal < 0) ? -1 : 0;
1356 sqlite3_result_int64(context, iVal);
1359 sqlite3_result_null(context);
1364 rVal = sqlite3_value_double(argv[0]);
1365 rVal = (rVal > 0) ? 1 : (rVal < 0) ? -1 : 0;
1366 sqlite3_result_double(context, rVal);
1374 static void ceilFunc(sqlite3_context * context,
1375 int argc, sqlite3_value ** argv)
1381 switch (sqlite3_value_type(argv[0])) {
1382 case SQLITE_INTEGER:
1383 iVal = sqlite3_value_int64(argv[0]);
1384 sqlite3_result_int64(context, iVal);
1387 sqlite3_result_null(context);
1390 rVal = sqlite3_value_double(argv[0]);
1391 sqlite3_result_int64(context, ceil(rVal));
1399 static void floorFunc(sqlite3_context * context,
1400 int argc, sqlite3_value ** argv)
1406 switch (sqlite3_value_type(argv[0])) {
1407 case SQLITE_INTEGER:
1408 iVal = sqlite3_value_int64(argv[0]);
1409 sqlite3_result_int64(context, iVal);
1412 sqlite3_result_null(context);
1415 rVal = sqlite3_value_double(argv[0]);
1416 sqlite3_result_int64(context, floor(rVal));
1425 static void replicateFunc(sqlite3_context * context,
1426 int argc, sqlite3_value ** argv)
1435 if (argc != 2 || SQLITE_NULL == sqlite3_value_type(argv[0]))
1438 iCount = sqlite3_value_int64(argv[1]);
1441 sqlite3_result_error(context,
"domain error", -1);
1443 nLen = sqlite3_value_bytes(argv[0]);
1444 nTLen = nLen * iCount;
1447 strcpy((
char *) zo, (
char *) sqlite3_value_text(argv[0]));
1449 for (i = 0; i < iCount; ++i)
1450 strcpy((
char *) (z + i * nLen), (
char *) zo);
1452 sqlite3_result_text(context, (
char *) z, -1, free);
1457 static void properFunc(sqlite3_context * context,
1458 int argc, sqlite3_value ** argv)
1460 const unsigned char *z;
1467 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1468 sqlite3_result_null(context);
1472 z = sqlite3_value_text(argv[0]);
1473 zo = (
unsigned char *)
xstrdup((
const char *)z);
1476 while ((r = *(z++)) != 0) {
1487 sqlite3_result_text(context, (
char *) zo, -1, free);
1497 static void padlFunc(sqlite3_context * context,
1498 int argc, sqlite3_value ** argv)
1508 if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
1509 sqlite3_result_null(context);
1511 zi = (
const char *) sqlite3_value_text(argv[0]);
1512 ilen = sqlite3_value_int64(argv[1]);
1515 sqlite3_result_error(context,
"domain error", -1);
1518 zl = sqlite3utf8CharLen(zi, -1);
1521 sqlite3_result_text(context,
xstrdup(zi), -1, free);
1523 zo =
xmalloc(strlen(zi) + ilen - zl + 1);
1525 for (i = 1; i + zl <= ilen; ++i)
1529 sqlite3_result_text(context, zo, -1, free);
1540 static void padrFunc(sqlite3_context * context,
1541 int argc, sqlite3_value ** argv)
1552 if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
1553 sqlite3_result_null(context);
1556 zi = (
const char *) sqlite3_value_text(argv[0]);
1557 _ilen = sqlite3_value_int64(argv[1]);
1560 sqlite3_result_error(context,
"domain error", -1);
1564 zl = sqlite3utf8CharLen(zi, -1);
1567 sqlite3_result_text(context,
xstrdup(zi), -1, free);
1570 zo =
xmalloc(zll + ilen - zl + 1);
1571 zt = strcpy(zo, zi) + zll;
1572 for (i = 1; i + zl <= ilen; ++i)
1575 sqlite3_result_text(context, zo, -1, free);
1587 static void padcFunc(sqlite3_context * context,
1588 int argc, sqlite3_value ** argv)
1599 if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
1600 sqlite3_result_null(context);
1603 zi = (
const char *) sqlite3_value_text(argv[0]);
1604 _ilen = sqlite3_value_int64(argv[1]);
1607 sqlite3_result_error(context,
"domain error", -1);
1611 zl = sqlite3utf8CharLen(zi, -1);
1614 sqlite3_result_text(context,
xstrdup(zi), -1, free);
1617 zo =
xmalloc(zll + ilen - zl + 1);
1619 for (i = 1; 2 * i + zl <= ilen; ++i)
1623 for (; i + zl <= ilen; ++i)
1626 sqlite3_result_text(context, zo, -1, free);
1636 static void strfilterFunc(sqlite3_context * context,
1637 int argc, sqlite3_value ** argv)
1651 if (sqlite3_value_type(argv[0]) == SQLITE_NULL
1652 || sqlite3_value_type(argv[1]) == SQLITE_NULL) {
1653 sqlite3_result_null(context);
1655 zi1 = (
const char *) sqlite3_value_text(argv[0]);
1656 zi2 = (
const char *) sqlite3_value_text(argv[1]);
1657 zo =
xmalloc(strlen(zi1) + 1);
1660 while ((c1 = sqliteCharVal(z1)) != 0) {
1662 while ((c2 = sqliteCharVal(z21)) != 0 && c2 != c1)
1663 sqliteNextChar(z21);
1666 sqliteNextChar(z22);
1667 strncpy(zot, z21, z22 - z21);
1674 sqlite3_result_text(context, zo, -1, free);
1685 static int _substr(
const char *z1,
const char *z2,
int s,
const char **p)
1697 while ((sqliteCharVal(z2) != 0) && (c++) < s)
1701 while ((sqliteCharVal(z2)) != 0) {
1706 c1 = sqliteCharVal(zt1);
1707 c2 = sqliteCharVal(zt2);
1708 sqliteNextChar(zt1);
1709 sqliteNextChar(zt2);
1710 }
while (c1 == c2 && c1 != 0 && c2 != 0);
1722 return rVal >= 0 ? rVal + s : rVal;
1732 static void charindexFunc(sqlite3_context * context,
1733 int argc, sqlite3_value ** argv)
1740 assert(argc == 2 || argc == 3);
1741 if (SQLITE_NULL == sqlite3_value_type(argv[0])
1742 || SQLITE_NULL == sqlite3_value_type(argv[1])) {
1743 sqlite3_result_null(context);
1747 z1 = (
const char *) sqlite3_value_text(argv[0]);
1748 z2 = (
const char *) sqlite3_value_text(argv[1]);
1750 s = sqlite3_value_int(argv[2]) - 1;
1757 rVal = _substr(z1, z2, s, NULL);
1758 sqlite3_result_int(context, rVal + 1);
1765 static void leftFunc(sqlite3_context * context,
1766 int argc, sqlite3_value ** argv)
1771 const unsigned char *z;
1772 const unsigned char *zt;
1776 if (SQLITE_NULL == sqlite3_value_type(argv[0])
1777 || SQLITE_NULL == sqlite3_value_type(argv[1])) {
1778 sqlite3_result_null(context);
1782 z = sqlite3_value_text(argv[0]);
1783 l = sqlite3_value_int(argv[1]);
1786 while (sqliteCharVal(zt) && c++ < l)
1792 strncpy((
char *) rz, (
char *) z, zt - z);
1794 sqlite3_result_text(context, (
char *) rz, -1, free);
1801 static void rightFunc(sqlite3_context * context,
1802 int argc, sqlite3_value ** argv)
1813 if (SQLITE_NULL == sqlite3_value_type(argv[0])
1814 || SQLITE_NULL == sqlite3_value_type(argv[1])) {
1815 sqlite3_result_null(context);
1819 z = (
const char *) sqlite3_value_text(argv[0]);
1820 l = sqlite3_value_int(argv[1]);
1823 while (sqliteCharVal(zt) != 0) {
1840 strcpy((
char *) rz, (
char *) (zt));
1841 sqlite3_result_text(context, (
char *) rz, -1, free);
1847 static const char * ltrim(
const char *s)
1858 static const char * rtrim(
char *s)
1860 char *ss = s + strlen(s) - 1;
1861 while (ss >= s && *ss ==
' ')
1870 static void ltrimFunc(sqlite3_context * context,
1871 int argc, sqlite3_value ** argv)
1876 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1877 sqlite3_result_null(context);
1880 z = (
const char *) sqlite3_value_text(argv[0]);
1881 sqlite3_result_text(context,
xstrdup(ltrim(z)), -1, free);
1887 static void rtrimFunc(sqlite3_context * context,
1888 int argc, sqlite3_value ** argv)
1893 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1894 sqlite3_result_null(context);
1897 z = (
const char *) sqlite3_value_text(argv[0]);
1898 sqlite3_result_text(context, rtrim(
xstrdup(z)), -1, free);
1904 static void trimFunc(sqlite3_context * context,
1905 int argc, sqlite3_value ** argv)
1910 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1911 sqlite3_result_null(context);
1914 z = (
const char *) sqlite3_value_text(argv[0]);
1915 sqlite3_result_text(context, rtrim(
xstrdup(ltrim(z))), -1, free);
1924 static void _append(
char **s1,
int l1,
const char *s2,
int l2)
1926 *s1 =
xrealloc(*s1, (l1 + l2 + 1) *
sizeof(
char));
1927 strncpy((*s1) + l1, s2, l2);
1928 *(*(s1) + l1 + l2) =
'\0';
1934 static void replaceFunc(sqlite3_context * context,
1935 int argc, sqlite3_value ** argv)
1950 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1951 sqlite3_result_null(context);
1955 z1 = (
const char *)sqlite3_value_text(argv[0]);
1956 z2 = (
const char *)sqlite3_value_text(argv[1]);
1957 z3 = (
const char *)sqlite3_value_text(argv[2]);
1971 sqlite3_result_text(context,
xstrdup(z1), -1, free);
1980 ret = _substr(z2, zt1, 0, &zt2);
1985 _append(&zo, lzo, zt1, zt2 - zt1);
1987 _append(&zo, lzo, z3, lz3);
1992 _append(&zo, lzo, zt1, lz1 - (zt1 - z1));
1993 sqlite3_result_text(context, zo, -1, free);
1999 static void reverseFunc(sqlite3_context * context,
2000 int argc, sqlite3_value ** argv)
2010 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
2011 sqlite3_result_null(context);
2014 z = (
const char *)sqlite3_value_text(argv[0]);
2021 while (sqliteCharVal(zt) != 0) {
2024 for (i = 1; zt - i >= z; ++i)
2025 *(rzt--) = *(zt - i);
2028 sqlite3_result_text(context, rz, -1, free);
2038 typedef struct StdevCtx StdevCtx;
2053 typedef struct ModeCtx ModeCtx;
2069 static void varianceStep(sqlite3_context * context,
2070 int argc, sqlite3_value ** argv)
2077 p = sqlite3_aggregate_context(context,
sizeof(*p));
2079 if (SQLITE_NULL != sqlite3_value_numeric_type(argv[0])) {
2081 x = sqlite3_value_double(argv[0]);
2082 delta = (x - p->rM);
2083 p->rM += delta / p->cnt;
2084 p->rS += delta * (x - p->rM);
2091 static void modeStep(sqlite3_context * context,
2092 int argc, sqlite3_value ** argv)
2102 type = sqlite3_value_numeric_type(argv[0]);
2104 if (type == SQLITE_NULL)
2107 p = sqlite3_aggregate_context(context,
sizeof(*p));
2110 p->m = calloc(1,
sizeof(map));
2111 if (type == SQLITE_INTEGER) {
2113 *(p->m) = map_make(int_cmp);
2118 *(p->m) = map_make(double_cmp);
2124 if (0 == p->is_double) {
2125 xi = sqlite3_value_int64(argv[0]);
2126 iptr = (int64_t *) calloc(1,
sizeof(int64_t));
2128 map_insert(p->m, iptr);
2130 xd = sqlite3_value_double(argv[0]);
2131 dptr = (
double *) calloc(1,
sizeof(
double));
2133 map_insert(p->m, dptr);
2141 static void modeIterate(
void *e, int64_t c,
void *pp)
2145 ModeCtx *p = (ModeCtx *) pp;
2147 if (0 == p->is_double) {
2152 }
else if (p->mcnt < c) {
2158 ed = *(
double *) (e);
2162 }
else if (p->mcnt < c) {
2175 static void medianIterate(
void *e, int64_t c,
void *pp)
2183 ModeCtx *p = (ModeCtx *) pp;
2189 iR = p->cnt - p->pcnt;
2191 ir = p->cnt - p->mcnt;
2196 if (0 == p->is_double) {
2200 ed = *(
double *) (e);
2213 static void modeFinalize(sqlite3_context * context)
2215 ModeCtx *p = sqlite3_aggregate_context(context, 0);
2217 map_iterate(p->m, modeIterate, p);
2222 if (0 == p->is_double)
2223 sqlite3_result_int64(context, p->riM);
2225 sqlite3_result_double(context, p->rdM);
2233 static void _medianFinalize(sqlite3_context * context)
2235 ModeCtx *p = (ModeCtx *) sqlite3_aggregate_context(context, 0);
2238 map_iterate(p->m, medianIterate, p);
2242 if (0 == p->is_double)
2244 sqlite3_result_int64(context, p->riM);
2246 sqlite3_result_double(context, p->riM * 1.0 / p->mn);
2248 sqlite3_result_double(context, p->rdM / p->mn);
2255 static void medianFinalize(sqlite3_context * context)
2257 ModeCtx *p = (ModeCtx *) sqlite3_aggregate_context(context, 0);
2259 p->pcnt = (p->cnt) / 2.0;
2260 _medianFinalize(context);
2267 static void lower_quartileFinalize(sqlite3_context * context)
2269 ModeCtx *p = (ModeCtx *) sqlite3_aggregate_context(context, 0);
2271 p->pcnt = (p->cnt) / 4.0;
2272 _medianFinalize(context);
2279 static void upper_quartileFinalize(sqlite3_context * context)
2281 ModeCtx *p = (ModeCtx *) sqlite3_aggregate_context(context, 0);
2283 p->pcnt = (p->cnt) * 3 / 4.0;
2284 _medianFinalize(context);
2291 static void stdevFinalize(sqlite3_context * context)
2293 StdevCtx *p = sqlite3_aggregate_context(context, 0);
2294 if (p && p->cnt > 1)
2295 sqlite3_result_double(context, sqrt(p->rS / (p->cnt - 1)));
2297 sqlite3_result_double(context, 0.0);
2303 static void varianceFinalize(sqlite3_context * context)
2305 StdevCtx *p = sqlite3_aggregate_context(context, 0);
2306 if (p && p->cnt > 1)
2307 sqlite3_result_double(context, p->rS / (p->cnt - 1));
2309 sqlite3_result_double(context, 0.0);
2316 static void expandFunc(sqlite3_context * context,
2317 int argc, sqlite3_value ** argv)
2319 sqlite3_result_text(context,
2320 rpmExpand((
const char *)sqlite3_value_text(argv[0]), NULL), -1, free);
2326 static void regexpFunc(sqlite3_context* context,
2327 int argc, sqlite3_value** argv)
2329 const char * value = (
const char *) sqlite3_value_text(argv[0]);
2330 const char * pattern = (
const char *) sqlite3_value_text(argv[1]);
2338 sqlite3_result_int(context, rc);
2341 sqlite3_result_error(context,
"invalid pattern", -1);
2347 static struct rpmsqlCF_s __CF[] = {
2349 {
"acos", 1, 0, SQLITE_UTF8, 0, acosFunc, NULL, NULL },
2350 {
"asin", 1, 0, SQLITE_UTF8, 0, asinFunc, NULL, NULL },
2351 {
"atan", 1, 0, SQLITE_UTF8, 0, atanFunc, NULL, NULL },
2352 {
"atn2", 2, 0, SQLITE_UTF8, 0, atn2Func, NULL, NULL },
2354 {
"atan2", 2, 0, SQLITE_UTF8, 0, atn2Func, NULL, NULL },
2355 {
"acosh", 1, 0, SQLITE_UTF8, 0, acoshFunc, NULL, NULL },
2356 {
"asinh", 1, 0, SQLITE_UTF8, 0, asinhFunc, NULL, NULL },
2357 {
"atanh", 1, 0, SQLITE_UTF8, 0, atanhFunc, NULL, NULL },
2360 {
"difference", 2, 0, SQLITE_UTF8, 0, differenceFunc, NULL, NULL },
2362 {
"degrees", 1, 0, SQLITE_UTF8, 0, rad2degFunc, NULL, NULL },
2363 {
"radians", 1, 0, SQLITE_UTF8, 0, deg2radFunc, NULL, NULL },
2365 {
"cos", 1, 0, SQLITE_UTF8, 0, cosFunc, NULL, NULL },
2366 {
"sin", 1, 0, SQLITE_UTF8, 0, sinFunc, NULL, NULL },
2367 {
"tan", 1, 0, SQLITE_UTF8, 0, tanFunc, NULL, NULL },
2368 {
"cot", 1, 0, SQLITE_UTF8, 0, cotFunc, NULL, NULL },
2369 {
"cosh", 1, 0, SQLITE_UTF8, 0, coshFunc, NULL, NULL },
2370 {
"sinh", 1, 0, SQLITE_UTF8, 0, sinhFunc, NULL, NULL },
2371 {
"tanh", 1, 0, SQLITE_UTF8, 0, tanhFunc, NULL, NULL },
2372 {
"coth", 1, 0, SQLITE_UTF8, 0, cothFunc, NULL, NULL },
2374 {
"exp", 1, 0, SQLITE_UTF8, 0, expFunc, NULL, NULL },
2375 {
"log", 1, 0, SQLITE_UTF8, 0, logFunc, NULL, NULL },
2376 {
"log10", 1, 0, SQLITE_UTF8, 0, log10Func, NULL, NULL },
2377 {
"power", 2, 0, SQLITE_UTF8, 0, powerFunc, NULL, NULL },
2378 {
"sign", 1, 0, SQLITE_UTF8, 0, signFunc, NULL, NULL },
2379 {
"sqrt", 1, 0, SQLITE_UTF8, 0, sqrtFunc, NULL, NULL },
2380 {
"square", 1, 0, SQLITE_UTF8, 0, squareFunc, NULL, NULL },
2382 {
"ceil", 1, 0, SQLITE_UTF8, 0, ceilFunc, NULL, NULL },
2383 {
"floor", 1, 0, SQLITE_UTF8, 0, floorFunc, NULL, NULL },
2385 {
"pi", 0, 0, SQLITE_UTF8, 1, piFunc, NULL, NULL },
2388 {
"replicate", 2, 0, SQLITE_UTF8, 0, replicateFunc, NULL, NULL },
2389 {
"charindex", 2, 0, SQLITE_UTF8, 0, charindexFunc, NULL, NULL },
2390 {
"charindex", 3, 0, SQLITE_UTF8, 0, charindexFunc, NULL, NULL },
2391 {
"leftstr", 2, 0, SQLITE_UTF8, 0, leftFunc, NULL, NULL },
2392 {
"rightstr", 2, 0, SQLITE_UTF8, 0, rightFunc, NULL, NULL },
2393 {
"ltrim", 1, 0, SQLITE_UTF8, 0, ltrimFunc, NULL, NULL },
2394 {
"rtrim", 1, 0, SQLITE_UTF8, 0, rtrimFunc, NULL, NULL },
2395 {
"trim", 1, 0, SQLITE_UTF8, 0, trimFunc, NULL, NULL },
2396 {
"replace", 3, 0, SQLITE_UTF8, 0, replaceFunc, NULL, NULL },
2397 {
"reverse", 1, 0, SQLITE_UTF8, 0, reverseFunc, NULL, NULL },
2398 {
"proper", 1, 0, SQLITE_UTF8, 0, properFunc, NULL, NULL },
2400 {
"padl", 2, 0, SQLITE_UTF8, 0, padlFunc, NULL, NULL },
2401 {
"padr", 2, 0, SQLITE_UTF8, 0, padrFunc, NULL, NULL },
2402 {
"padc", 2, 0, SQLITE_UTF8, 0, padcFunc, NULL, NULL },
2404 {
"strfilter", 2, 0, SQLITE_UTF8, 0, strfilterFunc, NULL, NULL },
2408 {
"stdev", 1, 0, SQLITE_UTF8, 0, NULL, varianceStep, stdevFinalize },
2409 {
"variance", 1, 0, SQLITE_UTF8, 0, NULL, varianceStep, varianceFinalize },
2410 {
"mode", 1, 0, SQLITE_UTF8, 0, NULL, modeStep, modeFinalize },
2411 {
"median", 1, 0, SQLITE_UTF8, 0, NULL, modeStep, medianFinalize },
2412 {
"lower_quartile", 1, 0, SQLITE_UTF8, 0, NULL, modeStep, lower_quartileFinalize },
2413 {
"upper_quartile", 1, 0, SQLITE_UTF8, 0, NULL, modeStep, upper_quartileFinalize },
2417 {
"expand", 1, 0, SQLITE_UTF8, 0, expandFunc, NULL, NULL },
2418 {
"regexp", 2, 0, SQLITE_UTF8, 0, regexpFunc, NULL, NULL },
2419 { NULL, 0, 0, 0, 0, NULL, NULL, NULL }
2422 rpmsqlCF _rpmsqlCFT = __CF;
2424 int _rpmsqlLoadCFT(
rpmsql sql,
void * _CF)
2426 sqlite3 * db = (sqlite3 *)sql->I;
2430 SQLDBG((stderr,
"--> %s(%p,%p)\n", __FUNCTION__, sql, _CF));
2434 for (CF = (rpmsqlCF) _CF; CF->zName != NULL; CF++) {
2435 void * _pApp = NULL;
2438 switch (CF->argType) {
2440 case 0: _pApp = NULL;
break;
2441 case 1: _pApp = (
void *)db;
break;
2442 case 2: _pApp = (
void *)-1;
break;
2445 xx =
rpmsqlCmd(sql,
"create_function", db,
2446 sqlite3_create_function(db, CF->zName, CF->nArg, CF->eTextRep,
2447 _pApp, CF->xFunc, CF->xStep, CF->xFinal));
2448 SQLDBG((stderr,
"\t%s(%s) xx %d\n",
"sqlite3_create_function", CF->zName, xx));
2453 if (CF->needColSeq) {
2454 FuncDef *pFunc = sqlite3FindFunction(db, CF->zName,
2455 strlen(CF_>zName), CF->nArg, CF->eTextRep, 0);
2456 if (pFunc) pFunc->needCollSeq = 1;
2461 SQLDBG((stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, sql, rc));
2467 static struct rpmvd_s _envVD = {
2470 .regex =
"^([^=]+)=(.*)$",
2474 static int envCreateConnect(
void * _db,
void * pAux,
2475 int argc,
const char *
const * argv,
2476 rpmvt * vtp,
char ** pzErr)
2478 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_envVD), vtp);
2481 struct sqlite3_module envModule = {
2482 .xCreate = (
void *) envCreateConnect,
2483 .xConnect = (
void *) envCreateConnect,
2488 static struct rpmvd_s _grdbVD = {
2489 .prefix =
"%{?_etc_group}%{!?_etc_group:/etc/group}",
2492 .parse =
"_group:passwd:gid:groups",
2493 .regex =
"^([^:]*):([^:]*):([^:]*):([^:]*)$",
2497 static int grdbCreateConnect(
void * _db,
void * pAux,
2498 int argc,
const char *
const * argv,
2499 rpmvt * vtp,
char ** pzErr)
2501 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_grdbVD), vtp);
2504 struct sqlite3_module grdbModule = {
2505 .xCreate = (
void *) grdbCreateConnect,
2506 .xConnect = (
void *) grdbCreateConnect,
2511 static struct rpmvd_s _procdbVD = {
2512 .prefix =
"%{?_procdb}%{!?_procdb:/proc/[0-9]}",
2514 .parse =
"dir/pid/*",
2515 .regex =
"^(.+/)([0-9]+)$",
2519 static int procdbCreateConnect(
void * _db,
void * pAux,
2520 int argc,
const char *
const * argv,
2521 rpmvt * vtp,
char ** pzErr)
2523 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_procdbVD), vtp);
2526 struct sqlite3_module procdbModule = {
2527 .xCreate = (
void *) procdbCreateConnect,
2528 .xConnect = (
void *) procdbCreateConnect,
2533 static struct rpmvd_s _pwdbVD = {
2534 .prefix =
"%{?_etc_passwd}%{!?_etc_passwd:/etc/passwd}",
2536 .parse =
"user:passwd:uid:gid:gecos:dir:shell",
2537 .regex =
"^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*)$",
2541 static int pwdbCreateConnect(
void * _db,
void * pAux,
2542 int argc,
const char *
const * argv,
2543 rpmvt * vtp,
char ** pzErr)
2545 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_pwdbVD), vtp);
2548 struct sqlite3_module pwdbModule = {
2549 .xCreate = (
void *) pwdbCreateConnect,
2550 .xConnect = (
void *) pwdbCreateConnect,
2555 static struct rpmvd_s _repodbVD = {
2557 .prefix =
"%{?_repodb}%{!?_repodb:/X/popt/}",
2559 .parse =
"dir/file-NVRA-N-V-R.A",
2560 .regex =
"^(.+/)(((.*)-([^-]+)-([^-]+)\\.([^.]+))\\.rpm)$",
2564 static int repodbCreateConnect(
void * _db,
void * pAux,
2565 int argc,
const char *
const * argv,
2566 rpmvt * vtp,
char ** pzErr)
2568 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_repodbVD), vtp);
2571 struct sqlite3_module repodbModule = {
2572 .xCreate = (
void *) repodbCreateConnect,
2573 .xConnect = (
void *) repodbCreateConnect,
2578 static int _stat_debug = 0;
2580 static struct rpmvd_s _statVD = {
2582 .parse =
"st_dev,st_ino,st_mode,st_nlink,st_uid,st_gid,st_rdev,st_size,st_blksize,st_blocks,st_atime,st_mtime,st_ctime",
2585 static int statCreateConnect(
void * _db,
void * pAux,
2586 int argc,
const char *
const * argv,
2587 rpmvt * vtp,
char ** pzErr)
2589 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_statVD), vtp);
2592 static int statColumn(
rpmvc vc,
void * _pContext,
int colx)
2594 sqlite3_context * pContext = (sqlite3_context *) _pContext;
2596 const char * path = vt->av[vc->ix];
2597 const char * col = vt->cols[colx];
2598 struct stat sb, *st = &sb;
2599 int ret =
Lstat(path, &sb);
2602 if (_stat_debug < 0)
2603 fprintf(stderr,
"--> %s(%p,%p,%d)\n", __FUNCTION__, vc, pContext, colx);
2606 if (!strcmp(col,
"path"))
2607 sqlite3_result_text(pContext, path, -1, SQLITE_STATIC);
2608 else if (!strcmp(col,
"st_dev") && !ret)
2609 sqlite3_result_int64(pContext, st->st_dev);
2610 else if (!strcmp(col,
"st_ino") && !ret)
2611 sqlite3_result_int64(pContext, st->st_ino);
2612 else if (!strcmp(col,
"st_mode") && !ret)
2613 sqlite3_result_int64(pContext, st->st_mode);
2614 else if (!strcmp(col,
"st_nlink") && !ret)
2615 sqlite3_result_int64(pContext, st->st_nlink);
2616 else if (!strcmp(col,
"st_uid") && !ret)
2617 sqlite3_result_int64(pContext, st->st_uid);
2618 else if (!strcmp(col,
"st_gid") && !ret)
2619 sqlite3_result_int64(pContext, st->st_gid);
2620 else if (!strcmp(col,
"st_rdev") && !ret)
2621 sqlite3_result_int64(pContext, st->st_rdev);
2622 else if (!strcmp(col,
"st_size") && !ret)
2623 sqlite3_result_int64(pContext, st->st_size);
2624 else if (!strcmp(col,
"st_blksize") && !ret)
2625 sqlite3_result_int64(pContext, st->st_blksize);
2626 else if (!strcmp(col,
"st_blocks") && !ret)
2627 sqlite3_result_int64(pContext, st->st_blocks);
2628 else if (!strcmp(col,
"st_atime") && !ret)
2629 sqlite3_result_int64(pContext, st->st_atime);
2630 else if (!strcmp(col,
"st_mtime") && !ret)
2631 sqlite3_result_int64(pContext, st->st_mtime);
2632 else if (!strcmp(col,
"st_ctime") && !ret)
2633 sqlite3_result_int64(pContext, st->st_ctime);
2636 sqlite3_result_null(pContext);
2638 if (_stat_debug < 0)
2639 fprintf(stderr,
"<-- %s(%p,%p,%d) rc %d\n", __FUNCTION__, vc, pContext, colx, rc);
2644 struct sqlite3_module statModule = {
2645 .xCreate = (
void *) statCreateConnect,
2646 .xConnect = (
void *) statCreateConnect,
2647 .xColumn = (
void *) statColumn,
2652 static struct rpmvd_s _yumdbVD = {
2653 .prefix =
"%{?_yumdb}%{!?_yumdb:/var/lib/yum/yumdb}/",
2655 .parse =
"dir/hash-NVRA-N-V-R-A/*",
2656 .regex =
"^(.+/)([^-]+)-((.*)-([^-]+)-([^-]+)-([^-]+))$",
2660 static int yumdbCreateConnect(
void * _db,
void * pAux,
2661 int argc,
const char *
const * argv,
2662 rpmvt * vtp,
char ** pzErr)
2664 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_yumdbVD), vtp);
2667 struct sqlite3_module yumdbModule = {
2668 .xCreate = (
void *) yumdbCreateConnect,
2669 .xConnect = (
void *) yumdbCreateConnect,
2674 struct sqlite3_module _rpmvmTemplate = {
2675 .xCreate = (
void *) rpmvtCreate,
2676 .xConnect = (
void *) rpmvtConnect,
2677 .xBestIndex = (
void *) rpmvtBestIndex,
2678 .xDisconnect = (
void *) rpmvtDisconnect,
2679 .xDestroy = (
void *) rpmvtDestroy,
2680 .xOpen = (
void *) rpmvcOpen,
2681 .xClose = (
void *) rpmvcClose,
2682 .xFilter = (
void *) rpmvcFilter,
2683 .xNext = (
void *) rpmvcNext,
2684 .xEof = (
void *) rpmvcEof,
2685 .xColumn = (
void *) rpmvcColumn,
2686 .xRowid = (
void *) rpmvcRowid,
2687 .xUpdate = (
void *) rpmvtUpdate,
2688 .xBegin = (
void *) rpmvtBegin,
2689 .xSync = (
void *) rpmvtSync,
2690 .xCommit = (
void *) rpmvtCommit,
2691 .xRollback = (
void *) rpmvtRollback,
2692 .xFindFunction = (
void *) rpmvtFindFunction,
2693 .xRename = (
void *) rpmvtRename
2696 static struct rpmsqlVMT_s __VMT[] = {
2697 {
"Argv", NULL, NULL },
2698 {
"Env", &envModule, NULL },
2699 {
"Grdb", &grdbModule, NULL },
2700 {
"Procdb", &procdbModule, NULL },
2701 {
"Pwdb", &pwdbModule, NULL },
2702 {
"Repodb", &repodbModule, NULL },
2703 {
"Stat", &statModule, NULL },
2704 {
"Yumdb", &yumdbModule, NULL },
2705 { NULL, NULL, NULL }
2708 static void rpmsqlVMFree(
void * _VM)
2711 SQLDBG((stderr,
"--> %s(%p)\n", __FUNCTION__, _VM));
2717 static void dumpVM(
const char * msg,
const rpmsqlVM s)
2719 fprintf(stderr,
"--------------------- %s\n", (msg ? msg :
""));
2720 #define VMPRT(f) if (s->f) fprintf(stderr, "%20s: %p\n", #f, s->f)
2738 VMPRT(xFindFunction);
2744 static rpmsqlVM rpmsqlVMNew(
const rpmsqlVM s)
2746 rpmsqlVM t =
xcalloc(1,
sizeof(*t));
2748 SQLDBG((stderr,
"--> %s(%p)\n", __FUNCTION__, s));
2749 *t = _rpmvmTemplate;
2752 if (s->iVersion) t->iVersion = s->iVersion;
2753 #define VMCPY(f) if (s->f) t->f = ((s->f != (void *)-1) ? s->f : NULL)
2771 VMCPY(xFindFunction);
2775 SQLDBG((stderr,
"<-- %s(%p) %p\n", __FUNCTION__, s, t));
2779 int _rpmsqlLoadVMT(
void * _db,
const rpmsqlVMT _VMT)
2781 sqlite3 * db = (sqlite3 *) _db;
2785 SQLDBG((stderr,
"--> %s(%p,%p)\n", __FUNCTION__, _db, _VMT));
2786 for (VMT = (rpmsqlVMT)_VMT; VMT->zName != NULL; VMT++) {
2790 sqlite3_create_module_v2(db, VMT->zName,
2791 rpmsqlVMNew(VMT->module), VMT->data, rpmsqlVMFree));
2792 SQLDBG((stderr,
"\t%s(%s) xx %d\n",
"sqlite3_create_module_v2", VMT->zName, xx));
2797 SQLDBG((stderr,
"<-- %s(%p,%p) rc %d\n", __FUNCTION__, _db, _VMT, rc));
2803 #if SQLITE_VERSION_NUMBER <= 3006015
2804 #define sqlite3_enable_load_extension(db, onoff) SQLITE_OK
2805 #define sqlite3_load_extension(db, zFile, zProc, pzErrMsg) SQLITE_OK
2813 static int _rpmsqlOpenDB(
rpmsql sql)
2820 db = (sqlite3 *)sql->I;
2824 sqlite3_open(sql->zDbFilename, &db));
2827 if (db && rc == SQLITE_OK) {
2828 (void) _rpmsqlLoadCFT(sql, _rpmsqlCFT);
2829 (void) _rpmsqlLoadVMT(db, __VMT);
2832 if (db == NULL || sqlite3_errcode(db) != SQLITE_OK) {
2834 rpmsql_error(1,
_(
"unable to open database \"%s\": %s"),
2835 sql->zDbFilename, sqlite3_errmsg(db));
2840 (void)
rpmsqlCmd(sql,
"enable_load_extension", db,
2841 sqlite3_enable_load_extension(db, 1));
2846 SQLDBG((stderr,
"<-- %s(%p) rc %d %s\n", __FUNCTION__, sql, rc, sql->zDbFilename));
2854 #if defined(WITH_SQLITE)
2858 static int isNumber(
const char *z,
int *realnum)
2860 if (*z ==
'-' || *z ==
'+')
2878 if (*z ==
'e' || *z ==
'E') {
2880 if (*z ==
'+' || *z ==
'-')
2896 static int strlen30(
const char *z)
2901 return 0x3fffffff & (int) (z2 - z);
2906 #if defined(WITH_SQLITE)
2911 static void output_hex_blob(
rpmsql sql,
const void *pBlob,
int nBlob)
2913 char *zBlob = (
char *) pBlob;
2916 SQLDBG((stderr,
"--> %s(%p,%p[%u])\n", __FUNCTION__, sql, pBlob, (
unsigned)nBlob));
2917 rpmsqlFprintf(sql,
"X'");
2918 for (i = 0; i < nBlob; i++)
2919 rpmsqlFprintf(sql,
"%02x", zBlob[i]);
2920 rpmsqlFprintf(sql,
"'");
2927 static void output_quoted_string(
rpmsql sql,
const char *z)
2931 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, z));
2932 for (i = 0; z[i]; i++) {
2937 rpmsqlFprintf(sql,
"'%s'", z);
2939 rpmsqlFprintf(sql,
"'");
2941 for (i = 0; z[i] && z[i] !=
'\''; i++)
2944 rpmsqlFprintf(sql,
"''");
2946 }
else if (z[i] ==
'\'') {
2947 rpmsqlFprintf(sql,
"%.*s''", i, z);
2950 rpmsqlFprintf(sql,
"%s", z);
2954 rpmsqlFprintf(sql,
"'");
2962 static void output_c_string(
rpmsql sql,
const char *z)
2965 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, z));
2966 rpmsqlFprintf(sql,
"\"");
2967 while ((c = *(z++)) != 0) {
2969 rpmsqlFprintf(sql,
"\\\\");
2971 rpmsqlFprintf(sql,
"\\t");
2973 rpmsqlFprintf(sql,
"\\n");
2975 rpmsqlFprintf(sql,
"\\r");
2976 else if (!isprint(c))
2977 rpmsqlFprintf(sql,
"\\%03o", c & 0xff);
2979 rpmsqlFprintf(sql,
"%c", c);
2981 rpmsqlFprintf(sql,
"\"");
2989 static void output_html_string(
rpmsql sql,
const char *z)
2992 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, z));
2997 && z[i] !=
'>' && z[i] !=
'\"' && z[i] !=
'\''; i++) {
3000 rpmsqlFprintf(sql,
"%.*s", i, z);
3002 rpmsqlFprintf(sql,
"<");
3003 else if (z[i] ==
'&')
3004 rpmsqlFprintf(sql,
"&");
3005 else if (z[i] ==
'>')
3006 rpmsqlFprintf(sql,
">");
3007 else if (z[i] ==
'\"')
3008 rpmsqlFprintf(sql,
""");
3009 else if (z[i] ==
'\'')
3010 rpmsqlFprintf(sql,
"'");
3022 static const char needCsvQuote[] = {
3023 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3024 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3025 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3026 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3027 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3028 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3029 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3030 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
3031 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3032 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3033 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3034 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3035 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3036 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3037 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3038 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3048 static void output_csv(
rpmsql sql,
const char *z,
int bSep)
3050 SQLDBG((stderr,
"--> %s(%p,%s,0x%x)\n", __FUNCTION__, sql, z, bSep));
3052 rpmsqlFprintf(sql,
"%s", sql->nullvalue);
3055 int nSep = strlen30(sql->separator);
3056 for (i = 0; z[i]; i++) {
3057 if (needCsvQuote[((
unsigned char *) z)[i]]
3058 || (z[i] == sql->separator[0] &&
3059 (nSep == 1 || memcmp(z, sql->separator, nSep) == 0))) {
3065 rpmsqlFprintf(sql,
"\"");
3066 for (i = 0; z[i]; i++) {
3068 rpmsqlFprintf(sql,
"\"");
3069 rpmsqlFprintf(sql,
"%c", z[i]);
3071 rpmsqlFprintf(sql,
"\"");
3073 rpmsqlFprintf(sql,
"%s", z);
3077 rpmsqlFprintf(sql,
"%s", sql->separator);
3085 static int _rpmsqlShellCallback(
void * _sql,
int nArg,
char **azArg,
char **azCol,
3092 SQLDBG((stderr,
"--> %s(%p,%d,%p,%p,%p)\n", __FUNCTION__, _sql, nArg, azArg, azCol, aiType));
3093 switch (sql->mode) {
3094 case RPMSQL_MODE_LINE:
3098 for (i = 0; i < nArg; i++) {
3099 int len = strlen30(azCol[i] ? azCol[i] :
"");
3104 rpmsqlFprintf(sql,
"\n");
3105 for (i = 0; i < nArg; i++)
3106 rpmsqlFprintf(sql,
"%*s = %s\n", w, azCol[i],
3107 azArg[i] ? azArg[i] : sql->nullvalue);
3109 case RPMSQL_MODE_EXPLAIN:
3110 case RPMSQL_MODE_COLUMN:
3111 if (sql->cnt++ == 0) {
3112 for (i = 0; i < nArg; i++) {
3114 w = (i < ArraySize(sql->colWidth) ? sql->colWidth[i] : 0);
3117 w = strlen30(azCol[i] ? azCol[i] :
"");
3120 n = strlen30(azArg && azArg[i]
3121 ? azArg[i] : sql-> nullvalue);
3125 if (i < ArraySize(sql->actualWidth))
3126 sql->actualWidth[i] = w;
3128 rpmsqlFprintf(sql,
"%-*.*s%s", w, w, azCol[i],
3129 i == nArg - 1 ?
"\n" :
" ");
3133 for (i = 0; i < nArg; i++) {
3134 w = (i < ArraySize(sql->actualWidth)
3135 ? sql->actualWidth[i] : 10);
3137 rpmsqlFprintf(sql,
"%-*.*s%s", w, w,
3138 "-----------------------------------"
3139 "----------------------------------------------------------",
3140 i == nArg - 1 ?
"\n" :
" ");
3146 for (i = 0; i < nArg; i++) {
3147 w = (i < ArraySize(sql->actualWidth) ? sql->actualWidth[i] : 10);
3148 if (sql->mode == RPMSQL_MODE_EXPLAIN && azArg[i] &&
3149 strlen30(azArg[i]) > w) {
3150 w = strlen30(azArg[i]);
3152 rpmsqlFprintf(sql,
"%-*.*s%s", w, w,
3153 azArg[i] ? azArg[i] : sql->nullvalue,
3154 i == nArg - 1 ?
"\n" :
" ");
3157 case RPMSQL_MODE_SEMI:
3158 case RPMSQL_MODE_LIST:
3159 if (sql->cnt++ == 0 &&
F_ISSET(sql, SHOWHDR)) {
3160 for (i = 0; i < nArg; i++)
3161 rpmsqlFprintf(sql,
"%s%s", azCol[i],
3162 i == nArg - 1 ?
"\n" : sql->separator);
3167 for (i = 0; i < nArg; i++) {
3171 rpmsqlFprintf(sql,
"%s", z);
3173 rpmsqlFprintf(sql,
"%s", sql->separator);
3174 else if (sql->mode == RPMSQL_MODE_SEMI)
3175 rpmsqlFprintf(sql,
";\n");
3177 rpmsqlFprintf(sql,
"\n");
3180 case RPMSQL_MODE_HTML:
3181 if (sql->cnt++ == 0 &&
F_ISSET(sql, SHOWHDR)) {
3182 rpmsqlFprintf(sql,
"<TR>");
3183 for (i = 0; i < nArg; i++) {
3184 rpmsqlFprintf(sql,
"<TH>");
3185 output_html_string(sql, azCol[i]);
3186 rpmsqlFprintf(sql,
"</TH>\n");
3188 rpmsqlFprintf(sql,
"</TR>\n");
3192 rpmsqlFprintf(sql,
"<TR>");
3193 for (i = 0; i < nArg; i++) {
3194 rpmsqlFprintf(sql,
"<TD>");
3195 output_html_string(sql, azArg[i] ? azArg[i] : sql->nullvalue);
3196 rpmsqlFprintf(sql,
"</TD>\n");
3198 rpmsqlFprintf(sql,
"</TR>\n");
3200 case RPMSQL_MODE_TCL:
3201 if (sql->cnt++ == 0 &&
F_ISSET(sql, SHOWHDR)) {
3202 for (i = 0; i < nArg; i++) {
3203 output_c_string(sql, azCol[i] ? azCol[i] :
"");
3204 rpmsqlFprintf(sql,
"%s", sql->separator);
3206 rpmsqlFprintf(sql,
"\n");
3210 for (i = 0; i < nArg; i++) {
3211 output_c_string(sql, azArg[i] ? azArg[i] : sql->nullvalue);
3212 rpmsqlFprintf(sql,
"%s", sql->separator);
3214 rpmsqlFprintf(sql,
"\n");
3216 case RPMSQL_MODE_CSV:
3217 if (sql->cnt++ == 0 &&
F_ISSET(sql, SHOWHDR)) {
3218 for (i = 0; i < nArg; i++)
3219 output_csv(sql, azCol[i] ? azCol[i] :
"", i < nArg - 1);
3220 rpmsqlFprintf(sql,
"\n");
3224 for (i = 0; i < nArg; i++)
3225 output_csv(sql, azArg[i], i < nArg - 1);
3226 rpmsqlFprintf(sql,
"\n");
3228 case RPMSQL_MODE_INSERT:
3232 rpmsqlFprintf(sql,
"INSERT INTO %s VALUES(", sql->zDestTable);
3233 for (i = 0; i < nArg; i++) {
3234 char *zSep = i > 0 ?
"," :
"";
3235 if ((azArg[i] == 0) || (aiType && aiType[i] == SQLITE_NULL)) {
3236 rpmsqlFprintf(sql,
"%sNULL", zSep);
3237 }
else if (aiType && aiType[i] == SQLITE_TEXT) {
3239 rpmsqlFprintf(sql,
"%s", zSep);
3240 output_quoted_string(sql, azArg[i]);
3242 && (aiType[i] == SQLITE_INTEGER
3243 || aiType[i] == SQLITE_FLOAT)) {
3244 rpmsqlFprintf(sql,
"%s%s", zSep, azArg[i]);
3245 }
else if (aiType && aiType[i] == SQLITE_BLOB && sql->S) {
3246 sqlite3_stmt * pStmt = (sqlite3_stmt *)sql->S;
3247 const void *pBlob = sqlite3_column_blob(pStmt, i);
3248 int nBlob = sqlite3_column_bytes(pStmt, i);
3250 rpmsqlFprintf(sql,
"%s", zSep);
3251 output_hex_blob(sql, pBlob, nBlob);
3252 }
else if (isNumber(azArg[i], 0)) {
3253 rpmsqlFprintf(sql,
"%s%s", zSep, azArg[i]);
3256 rpmsqlFprintf(sql,
"%s", zSep);
3257 output_quoted_string(sql, azArg[i]);
3260 rpmsqlFprintf(sql,
");\n");
3271 static int callback(
void *_sql,
int nArg,
char **azArg,
char **azCol)
3274 return _rpmsqlShellCallback(_sql, nArg, azArg, azCol, NULL);
3283 static void set_table_name(
rpmsql sql,
const char *zName)
3289 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, zName));
3290 sql->zDestTable =
_free(sql->zDestTable);
3293 needQuote = !
xisalpha((
unsigned char) *zName) && *zName !=
'_';
3294 for (i = n = 0; zName[i]; i++, n++) {
3295 if (!
xisalnum((
unsigned char) zName[i]) && zName[i] !=
'_') {
3297 if (zName[i] ==
'\'')
3303 sql->zDestTable = z =
xmalloc(n + 1);
3307 for (i = 0; zName[i]; i++) {
3309 if (zName[i] ==
'\'')
3326 static char *appendText(
char *zIn,
char const *zAppend,
char quote)
3330 int nAppend = strlen30(zAppend);
3331 int nIn = (zIn ? strlen30(zIn) : 0);
3333 SQLDBG((stderr,
"--> %s(%s,%s,0x%02x)\n", __FUNCTION__, zIn, zAppend, quote));
3334 len = nAppend + nIn + 1;
3337 for (i = 0; i < nAppend; i++) {
3338 if (zAppend[i] == quote)
3346 char *zCsr = &zIn[nIn];
3348 for (i = 0; i < nAppend; i++) {
3349 *zCsr++ = zAppend[i];
3350 if (zAppend[i] == quote)
3355 assert((zCsr - zIn) == len);
3357 memcpy(&zIn[nIn], zAppend, nAppend);
3358 zIn[len - 1] =
'\0';
3373 static int run_table_dump_query(
rpmsql sql, sqlite3 * db,
3374 const char *zSelect,
const char *zFirstRow)
3376 sqlite3_stmt * pSelect;
3378 SQLDBG((stderr,
"--> %s(%p,%p,%s,%s)\n", __FUNCTION__, sql, db, zSelect, zFirstRow));
3380 sqlite3_prepare(db, zSelect, -1, &pSelect, 0));
3381 if (rc || pSelect == NULL)
3385 sqlite3_step(pSelect))) == SQLITE_ROW)
3388 rpmsqlFprintf(sql,
"%s", zFirstRow);
3391 rpmsqlFprintf(sql,
"%s;\n", sqlite3_column_text(pSelect, 0));
3395 sqlite3_finalize(pSelect));
3401 #if defined(WITH_SQLITE)
3402 #define iseol(_c) ((char)(_c) == '\n' || (char)(_c) == '\r')
3413 rpmsqlFgets(
char * buf,
size_t nbuf,
rpmsql sql)
3417 FD_t ifd = sql->ifd;
3427 SQLDBG((stderr,
"--> %s(%p[%u],%p) ifd %p fp %p fileno %d fdno %d\n", __FUNCTION__, buf, (
unsigned)nbuf, sql, ifd, ifp, (ifp ? fileno(ifp) : -3),
Fileno(ifd)));
3429 assert(ifp != NULL);
3434 if (fgets(q, (
int)nbuf, ifp) == NULL)
3438 for (q += nb - 1; nb > 0 &&
iseol(*q); q--)
3440 for (; p <= q; p++) {
3447 default: p++;
break;
3452 case '{': p++, bc++;
break;
3453 case '(': p++, pc++;
break;
3454 case '%': p++;
break;
3457 case '{':
if (bc > 0) bc++;
break;
3458 case '}':
if (bc > 0) bc--;
break;
3459 case '(':
if (pc > 0) pc++;
break;
3460 case ')':
if (pc > 0) pc--;
break;
3463 if (nb == 0 || (*q !=
'\\' && !bc && !pc) || *(q+1) ==
'\0') {
3473 SQLDBG((stderr,
"<-- %s(%p[%u],%p) nr %u\n", __FUNCTION__, buf, (
unsigned)nbuf, sql, (
unsigned)nr));
3475 return (nr > 0 ? buf : NULL);
3488 static char *local_getline(
rpmsql sql,
const char *zPrompt)
3492 SQLDBG((stderr,
"--> %s(%s) ofd %p\n", __FUNCTION__, zPrompt, sql->ofd));
3494 if (sql->ofd && zPrompt && *zPrompt) {
3495 size_t nb = strlen(zPrompt);
3496 size_t nw =
Fwrite(zPrompt, 1, nb, sql->ofd);
3501 assert(sql->ifd != NULL);
3502 t = rpmsqlFgets(sql->buf, sql->nbuf, sql);
3504 SQLDBG((stderr,
"<-- %s(%s) ofd %p\n", __FUNCTION__, zPrompt, sql->ofd));
3516 static char *rpmsqlInputOneLine(
rpmsql sql,
const char *zPrior)
3518 const char *zPrompt;
3521 SQLDBG((stderr,
"--> %s(%s)\n", __FUNCTION__, zPrior));
3523 assert(sql->buf != NULL);
3524 assert(sql->ifd != NULL);
3527 zResult = local_getline(sql, NULL);
3529 zPrompt = (zPrior && zPrior[0]) ? sql->zContinue : sql->zPrompt;
3532 #if defined(HAVE_READLINE) && HAVE_READLINE==1
3536 if (zResult != sql->buf) {
3537 strncpy(sql->buf, zResult, sql->nbuf);
3538 zResult =
_free(zResult);
3545 SQLDBG((stderr,
"<-- %s(%s)\n", __FUNCTION__, zPrior));
3554 #if defined(WITH_SQLITE)
3558 static char *save_err_msg(sqlite3 * db)
3560 const char * s = sqlite3_errmsg(db);
3561 int nb = strlen30(s) + 1;
3562 return memcpy(
xmalloc(nb), s, nb);
3575 static int _rpmsqlShellExec(
rpmsql sql,
const char *zSql,
3576 int (*xCallback) (
void *,
int,
char **,
char **,
int *),
3580 sqlite3 * db = (sqlite3 *) sql->I;
3581 sqlite3_stmt * pStmt = NULL;
3583 const char *zLeftover;
3585 SQLDBG((stderr,
"--> %s(%p,%s,%p,%p)\n", __FUNCTION__, sql, zSql, xCallback, pzErrMsg));
3589 while (zSql[0] && rc == SQLITE_OK) {
3591 sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover));
3600 if (sql->ofd &&
F_ISSET(sql, ECHO)) {
3601 const char *zStmtSql = sqlite3_sql(pStmt);
3602 rpmsqlFprintf(sql,
"%s\n", zStmtSql ? zStmtSql : zSql);
3610 sqlite3_step(pStmt));
3612 if (rc == SQLITE_ROW) {
3616 int nCol = sqlite3_column_count(pStmt);
3617 size_t nb = 3 * nCol *
sizeof(
const char *) + 1;
3619 char ** azVals = &azCols[nCol];
3620 int * aiTypes = (
int *) &azVals[nCol];
3624 for (i = 0; i < nCol; i++)
3625 azCols[i] = (
char *) sqlite3_column_name(pStmt, i);
3628 sql->S = (
void *) pStmt;
3632 for (i = 0; i < nCol; i++) {
3633 azVals[i] = (
char *) sqlite3_column_text(pStmt, i);
3634 aiTypes[i] = sqlite3_column_type(pStmt, i);
3635 if (!azVals[i] && (aiTypes[i] != SQLITE_NULL)) {
3642 if (rc != SQLITE_ROW)
3646 if (xCallback (sql, nCol, azVals, azCols, aiTypes)) {
3651 sqlite3_step(pStmt));
3652 }
while (rc == SQLITE_ROW);
3653 azCols =
_free(azCols);
3658 sqlite3_step(pStmt));
3659 }
while (rc == SQLITE_ROW);
3667 sqlite3_finalize(pStmt));
3673 *pzErrMsg = save_err_msg(db);
3689 #if defined(WITH_SQLITE)
3698 static int dump_callback(
void *_sql,
int nArg,
char **azArg,
char **azCol)
3701 sqlite3 * db = (sqlite3 *) sql->I;
3706 const char *zPrepStmt = 0;
3709 SQLDBG((stderr,
"--> %s(%p,%d,%p,%p)\n", __FUNCTION__, _sql, nArg, azArg, azCol));
3717 if (!strcmp(zTable,
"sqlite_sequence")) {
3718 zPrepStmt =
"DELETE FROM sqlite_sequence;\n";
3719 }
else if (!strcmp(zTable,
"sqlite_stat1")) {
3720 rpmsqlFprintf(sql,
"ANALYZE sqlite_master;\n");
3721 }
else if (!strncmp(zTable,
"sqlite_", 7)) {
3724 }
else if (!strncmp(zSql,
"CREATE VIRTUAL TABLE", 20)) {
3726 if (!
F_ISSET(sql, WRITABLE)) {
3727 rpmsqlFprintf(sql,
"PRAGMA writable_schema=ON;\n");
3728 sql->flags |= RPMSQL_FLAGS_WRITABLE;
3732 (
"INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
3733 "VALUES('table','%q','%q',0,'%q');", zTable, zTable, zSql);
3734 rpmsqlFprintf(sql,
"%s\n", zIns);
3739 rpmsqlFprintf(sql,
"%s;\n", zSql);
3741 if (!strcmp(zType,
"table")) {
3742 sqlite3_stmt * pTableInfo = NULL;
3744 char *zTableInfo = 0;
3748 zTableInfo = appendText(zTableInfo,
"PRAGMA table_info(", 0);
3749 zTableInfo = appendText(zTableInfo, zTable,
'"');
3750 zTableInfo = appendText(zTableInfo,
");", 0);
3753 sqlite3_prepare(db, zTableInfo, -1, &pTableInfo, 0));
3754 zTableInfo =
_free(zTableInfo);
3755 if (rc != SQLITE_OK || !pTableInfo)
3758 zSelect = appendText(zSelect,
"SELECT 'INSERT INTO ' || ", 0);
3759 zTmp = appendText(zTmp, zTable,
'"');
3761 zSelect = appendText(zSelect, zTmp,
'\'');
3762 zSelect = appendText(zSelect,
" || ' VALUES(' || ", 0);
3764 sqlite3_step(pTableInfo));
3765 while (rc == SQLITE_ROW) {
3767 (
const char *) sqlite3_column_text(pTableInfo, 1);
3768 zSelect = appendText(zSelect,
"quote(", 0);
3769 zSelect = appendText(zSelect, zText,
'"');
3771 sqlite3_step(pTableInfo));
3772 if (rc == SQLITE_ROW)
3773 zSelect = appendText(zSelect,
") || ',' || ", 0);
3775 zSelect = appendText(zSelect,
") ", 0);
3779 sqlite3_finalize(pTableInfo));
3780 if (rc != SQLITE_OK || nRow == 0) {
3781 zSelect =
_free(zSelect);
3785 zSelect = appendText(zSelect,
"|| ')' FROM ", 0);
3786 zSelect = appendText(zSelect, zTable,
'"');
3788 rc = run_table_dump_query(sql, db, zSelect, zPrepStmt);
3789 if (rc == SQLITE_CORRUPT) {
3790 zSelect = appendText(zSelect,
" ORDER BY rowid DESC", 0);
3791 rc = run_table_dump_query(sql, db, zSelect, NULL);
3793 zSelect =
_free(zSelect);
3808 static int run_schema_dump_query(
rpmsql sql,
3809 const char *zQuery,
char **pzErrMsg)
3811 sqlite3 * db = (sqlite3 *) sql->I;
3814 SQLDBG((stderr,
"--> %s(%p,%s,%p)\n", __FUNCTION__, sql, zQuery, pzErrMsg));
3816 sqlite3_exec(db, zQuery, dump_callback, sql, pzErrMsg));
3817 if (rc == SQLITE_CORRUPT) {
3820 sqlite3_free(*pzErrMsg);
3821 zQ2 =
rpmExpand(zQuery,
" ORDER BY rowid DESC", NULL);
3823 sqlite3_exec(db, zQ2, dump_callback, sql, pzErrMsg));
3833 static char zHelp[] =
3834 ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
3835 ".bail ON|OFF Stop after hitting an error. Default OFF\n"
3836 ".databases List names and files of attached databases\n"
3837 ".dump ?TABLE? ... Dump the database in an SQL text format\n"
3838 " If TABLE specified, only dump tables matching\n"
3839 " LIKE pattern TABLE.\n"
3840 ".echo ON|OFF Turn command echo on or off\n"
3841 ".exit Exit this program\n"
3842 ".explain ?ON|OFF? Turn output mode suitable for EXPLAIN on or off.\n"
3843 " With no args, it turns EXPLAIN on.\n"
3844 ".header(s) ON|OFF Turn display of headers on or off\n"
3845 ".help Show this message\n"
3846 ".import FILE TABLE Import data from FILE into TABLE\n"
3847 ".indices ?TABLE? Show names of all indices\n"
3848 " If TABLE specified, only show indices for tables\n"
3849 " matching LIKE pattern TABLE.\n"
3850 #ifdef SQLITE_ENABLE_IOTRACE
3851 ".iotrace FILE Enable I/O diagnostic logging to FILE\n"
3853 ".load FILE ?ENTRY? Load an extension library\n"
3854 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n"
3855 ".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
3856 " csv Comma-separated values\n"
3857 " column Left-aligned columns. (See .width)\n"
3858 " html HTML <table> code\n"
3859 " insert SQL insert statements for TABLE\n"
3860 " line One value per line\n"
3861 " list Values delimited by .separator string\n"
3862 " tabs Tab-separated values\n"
3863 " tcl TCL list elements\n"
3864 ".nullvalue STRING Print STRING in place of NULL values\n"
3865 ".output FILENAME Send output to FILENAME\n"
3866 ".output stdout Send output to the screen\n"
3867 ".prompt MAIN CONTINUE Replace the standard prompts\n"
3868 ".quit Exit this program\n"
3869 ".read FILENAME Execute SQL in FILENAME\n"
3870 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
3871 ".schema ?TABLE? Show the CREATE statements\n"
3872 " If TABLE specified, only show tables matching\n"
3873 " LIKE pattern TABLE.\n"
3874 ".separator STRING Change separator used by output mode and .import\n"
3875 ".show Show the current values for various settings\n"
3876 ".tables ?TABLE? List names of tables\n"
3877 " If TABLE specified, only list tables matching\n"
3878 " LIKE pattern TABLE.\n"
3879 ".timeout MS Try opening locked tables for MS milliseconds\n"
3880 ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n";
3882 static char zTimerHelp[] =
3883 ".timer ON|OFF Turn the CPU timer measurement on or off\n";
3894 static void resolve_backslashes(
char *z)
3898 for (i = j = 0; (c = z[i]) != 0; i++, j++) {
3903 }
else if (c ==
't') {
3905 }
else if (c ==
'r') {
3907 }
else if (c >=
'0' && c <=
'7') {
3909 if (z[i + 1] >=
'0' && z[i + 1] <=
'7') {
3911 c = (c << 3) + z[i] -
'0';
3912 if (z[i + 1] >=
'0' && z[i + 1] <=
'7') {
3914 c = (c << 3) + z[i] -
'0';
3927 static int booleanValue(
const char * zArg)
3929 int val = atoi(zArg);
3930 if (!strcasecmp(zArg,
"on") || !strcasecmp(zArg,
"yes"))
3932 SQLDBG((stderr,
"<-- %s(%s) val %d\n", __FUNCTION__, zArg, val));
3937 static const char *modeDescr[] = {
3950 static int rpmsqlInput(
rpmsql sql);
3952 static int rpmsqlFOpen(
const char * fn,
FD_t *fdp)
3958 SQLDBG((stderr,
"--> %s(%s,%p) fd %p\n", __FUNCTION__, fn, fdp, fd));
3966 else if (!strcmp(fn,
"stdout") || !strcmp(fn,
"-"))
3967 fd =
fdDup(STDOUT_FILENO);
3968 else if (!strcmp(fn,
"stderr"))
3969 fd =
fdDup(STDERR_FILENO);
3970 else if (!strcmp(fn,
"off"))
3973 fd =
Fopen(fn,
"wb");
3974 if (fd == NULL ||
Ferror(fd)) {
3975 rpmsql_error(1,
_(
"cannot open \"%s\""), fn);
3976 if (fd) (void)
Fclose(fd);
3983 SQLDBG((stderr,
"<-- %s(%s,%p) fd %p rc %d\n", __FUNCTION__, fn, fdp, fd, rc));
3994 static int rpmsqlMetaCommand(
rpmsql sql,
char *zLine)
3996 sqlite3 * db = (sqlite3 *)sql->I;
4003 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, zLine));
4006 while (zLine[i] && nArg < ArraySize(azArg)) {
4007 while (
xisspace((
unsigned char) zLine[i]))
4009 if (zLine[i] ==
'\0')
4011 if (zLine[i] ==
'\'' || zLine[i] ==
'"') {
4012 int delim = zLine[i++];
4013 azArg[nArg++] = &zLine[i];
4014 while (zLine[i] && zLine[i] != delim)
4016 if (zLine[i] == delim)
4019 resolve_backslashes(azArg[nArg - 1]);
4021 azArg[nArg++] = &zLine[i];
4022 while (zLine[i] && !
xisspace((
unsigned char) zLine[i]))
4026 resolve_backslashes(azArg[nArg - 1]);
4033 n = strlen30(azArg[0]);
4035 if (c ==
'b' && n >= 3 && !strncmp(azArg[0],
"backup", n)
4036 && nArg > 1 && nArg < 4) {
4037 const char *zDestFile;
4040 sqlite3_backup *pBackup;
4042 zDestFile = azArg[1];
4045 zDestFile = azArg[2];
4049 sqlite3_open(zDestFile, &pDest));
4052 rpmsql_error(1,
_(
"cannot open \"%s\""), zDestFile);
4055 sqlite3_close(pDest));
4059 db = (sqlite3 *)sql->I;
4060 pBackup = sqlite3_backup_init(pDest,
"main", db, zDb);
4061 if (pBackup == NULL) {
4062 rpmsql_error(1,
"%s", sqlite3_errmsg(pDest));
4064 sqlite3_close(pDest));
4067 while ((rc =
rpmsqlCmd(sql,
"backup_step", db,
4068 sqlite3_backup_step(pBackup, 100))) == SQLITE_OK)
4070 (void)
rpmsqlCmd(sql,
"backup_finish", pBackup,
4071 sqlite3_backup_finish(pBackup));
4072 if (rc == SQLITE_DONE) {
4075 rpmsql_error(1,
"%s", sqlite3_errmsg(pDest));
4079 sqlite3_close(pDest));
4081 if (c ==
'b' && n >= 3 && !strncmp(azArg[0],
"bail", n)
4082 && nArg > 1 && nArg < 3) {
4083 if (booleanValue(azArg[1]))
4084 sql->flags |= RPMSQL_FLAGS_BAIL;
4086 sql->flags &= ~RPMSQL_FLAGS_BAIL;
4088 if (c ==
'd' && n > 1 && !strncmp(azArg[0],
"databases", n) && nArg == 1) {
4090 uint32_t _flags = sql->flags;
4091 uint32_t _mode = sql->mode;
4092 int _cnt = sql->cnt;;
4094 char *zErrMsg = NULL;
4095 memcpy(_colWidth, sql->colWidth,
sizeof(_colWidth));
4097 db = (sqlite3 *)sql->I;
4098 sql->flags |= RPMSQL_FLAGS_SHOWHDR;
4099 sql->mode = RPMSQL_MODE_COLUMN;
4100 sql->colWidth[0] = 3;
4101 sql->colWidth[1] = 15;
4102 sql->colWidth[2] = 58;
4105 sqlite3_exec(db,
"PRAGMA database_list;", callback, sql, &zErrMsg));
4107 rpmsql_error(1,
"%s", zErrMsg);
4108 sqlite3_free(zErrMsg);
4111 memcpy(sql->colWidth, _colWidth,
sizeof(_colWidth));
4114 sql->flags = _flags;
4116 if (c ==
'd' && !strncmp(azArg[0],
"dump", n) && nArg < 3) {
4119 db = (sqlite3 *)sql->I;
4123 rpmsqlFprintf(sql,
"PRAGMA foreign_keys=OFF;\n");
4124 rpmsqlFprintf(sql,
"BEGIN TRANSACTION;\n");
4125 sql->flags &= ~RPMSQL_FLAGS_WRITABLE;
4127 sqlite3_exec(db,
"PRAGMA writable_schema=ON", 0, 0, 0));
4129 t =
rpmExpand(
"SELECT name, type, sql FROM sqlite_master"
4130 " WHERE sql NOT NULL AND type=='table'"
4131 " AND name!='sqlite_sequence'", NULL);
4132 run_schema_dump_query(sql, t, NULL);
4134 t =
rpmExpand(
"SELECT name, type, sql FROM sqlite_master"
4135 " WHERE name=='sqlite_sequence'", NULL);
4136 run_schema_dump_query(sql, t, NULL);
4138 t =
rpmExpand(
"SELECT sql FROM sqlite_master"
4139 " WHERE sql NOT NULL AND type IN ('index','trigger','view')", NULL);
4140 run_table_dump_query(sql, db, t, NULL);
4144 for (i = 1; i < nArg; i++) {
4145 t =
rpmExpand(
"SELECT name, type, sql FROM sqlite_master"
4146 " WHERE tbl_name LIKE '", azArg[i],
"'"
4147 " AND type=='table' AND sql NOT NULL", NULL);
4148 run_schema_dump_query(sql, t, NULL);
4150 t =
rpmExpand(
"SELECT sql FROM sqlite_master"
4151 " WHERE sql NOT NULL"
4152 " AND type IN ('index','trigger','view')"
4153 " AND tbl_name LIKE '", azArg[i],
"'", NULL);
4154 run_table_dump_query(sql, db, t, NULL);
4159 rpmsqlFprintf(sql,
"PRAGMA writable_schema=OFF;\n");
4160 sql->flags &= ~RPMSQL_FLAGS_WRITABLE;
4163 sqlite3_exec(db,
"PRAGMA writable_schema=OFF", 0, 0, 0));
4164 rpmsqlFprintf(sql,
"COMMIT;\n");
4166 if (c ==
'e' && !strncmp(azArg[0],
"echo", n) && nArg > 1 && nArg < 3) {
4167 if (booleanValue(azArg[1]))
4168 sql->flags |= RPMSQL_FLAGS_ECHO;
4170 sql->flags &= ~RPMSQL_FLAGS_ECHO;
4172 if (c ==
'e' && !strncmp(azArg[0],
"exit", n) && nArg == 1) {
4175 if (c ==
'e' && !strncmp(azArg[0],
"explain", n) && nArg < 3) {
4176 int val = nArg >= 2 ? booleanValue(azArg[1]) : 1;
4178 if (!sql->explainPrev.valid) {
4179 sql->explainPrev.valid = 1;
4180 sql->explainPrev.mode = sql->mode;
4181 sql->explainPrev.flags = sql->flags;
4182 memcpy(sql->explainPrev.colWidth, sql->colWidth,
4183 sizeof(sql->colWidth));
4192 sql->mode = RPMSQL_MODE_EXPLAIN;
4193 sql->flags |= RPMSQL_FLAGS_SHOWHDR;
4194 memset(sql->colWidth, 0, ArraySize(sql->colWidth));
4195 sql->colWidth[0] = 4;
4196 sql->colWidth[1] = 13;
4197 sql->colWidth[2] = 4;
4198 sql->colWidth[3] = 4;
4199 sql->colWidth[4] = 4;
4200 sql->colWidth[5] = 13;
4201 sql->colWidth[6] = 2;
4202 sql->colWidth[7] = 13;
4203 }
else if (sql->explainPrev.valid) {
4204 sql->explainPrev.valid = 0;
4205 sql->mode = sql->explainPrev.mode;
4206 sql->flags = sql->explainPrev.flags;
4207 memcpy(sql->colWidth, sql->explainPrev.colWidth,
4208 sizeof(sql->colWidth));
4212 && (!strncmp(azArg[0],
"header", n) || !strncmp(azArg[0],
"headers", n))
4213 && nArg > 1 && nArg < 3)
4215 if (booleanValue(azArg[1]))
4216 sql->flags |= RPMSQL_FLAGS_SHOWHDR;
4218 sql->flags &= ~RPMSQL_FLAGS_SHOWHDR;
4220 if (c ==
'h' && !strncmp(azArg[0],
"help", n)) {
4221 rpmsql_error(0,
"%s", zHelp);
4223 rpmsql_error(0,
"%s", zTimerHelp);
4225 if (c ==
'i' && !strncmp(azArg[0],
"import", n) && nArg == 3) {
4226 char *zTable = azArg[2];
4227 char *zFile = azArg[1];
4228 sqlite3_stmt * pStmt = NULL;
4240 db = (sqlite3 *)sql->I;
4241 nSep = strlen30(sql->separator);
4243 rpmsql_error(1,
_(
"non-null separator required for import"));
4246 zSql = sqlite3_mprintf(
"SELECT * FROM '%q'", zTable);
4247 assert(zSql != NULL);
4248 nByte = strlen30(zSql);
4250 sqlite3_prepare(db, zSql, -1, &pStmt, 0));
4254 sqlite3 * db = (sqlite3 *)sql->I;
4255 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4259 sqlite3_finalize(pStmt));
4262 nCol = sqlite3_column_count(pStmt);
4264 sqlite3_finalize(pStmt));
4268 zSql =
xmalloc(nByte + 20 + nCol * 2);
4269 sqlite3_snprintf(nByte + 20, zSql,
"INSERT INTO '%q' VALUES(?",
4272 for (i = 1; i < nCol; i++) {
4279 sqlite3_prepare(db, zSql, -1, &pStmt, 0));
4283 sqlite3 * db = (sqlite3 *)sql->I;
4284 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4288 sqlite3_finalize(pStmt));
4291 assert(sql->ifd == NULL);
4292 sql->ifd =
Fopen(zFile,
"rb.fpio");
4293 if (sql->ifd == NULL ||
Ferror(sql->ifd)) {
4294 rpmsql_error(1,
_(
"cannot open \"%s\""), zFile);
4296 sqlite3_finalize(pStmt));
4297 if (sql->ifd) (void)
Fclose(sql->ifd);
4301 assert(sql->buf == NULL);
4303 sql->buf =
xmalloc(sql->nbuf);
4304 azCol = malloc(
sizeof(azCol[0]) * (nCol + 1));
4305 if (azCol == NULL) {
4306 if (sql->ifd) (void)
Fclose(sql->ifd);
4309 sqlite3_finalize(pStmt));
4313 sqlite3_exec(db,
"BEGIN", 0, 0, 0));
4315 while ((zLine = local_getline(sql, NULL)) != NULL) {
4320 for (i = 0, z = zLine; *z && *z !=
'\n' && *z !=
'\r'; z++) {
4321 if (*z == sql->separator[0] && !strncmp(z, sql->separator, nSep)) {
4325 azCol[i] = &z[nSep];
4331 if (i + 1 != nCol) {
4333 _(
"%s line %d: expected %d columns of data but found %d"),
4334 zFile, lineno, nCol, i + 1);
4335 zCommit =
"ROLLBACK";
4339 for (i = 0; i < nCol; i++)
4341 sqlite3_bind_text(pStmt, i + 1, azCol[i], -1, SQLITE_STATIC));
4343 sqlite3_step(pStmt));
4345 sqlite3_reset(pStmt));
4348 sqlite3 * db = (sqlite3 *)sql->I;
4349 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4351 zCommit =
"ROLLBACK";
4356 azCol =
_free(azCol);
4357 if (sql->ifd) (void)
Fclose(sql->ifd);
4359 sql->buf =
_free(sql->buf);
4362 sqlite3_finalize(pStmt));
4364 sqlite3_exec(db, zCommit, 0, 0, 0));
4366 if (c ==
'i' && !strncmp(azArg[0],
"indices", n) && nArg < 3) {
4368 uint32_t _flags = sql->flags;
4369 uint32_t _mode = sql->mode;
4371 char *zErrMsg = NULL;
4373 db = (sqlite3 *)sql->I;
4374 sql->flags &= ~RPMSQL_FLAGS_SHOWHDR;
4375 sql->mode = RPMSQL_MODE_LIST;
4377 t =
rpmExpand(
"SELECT name FROM sqlite_master"
4378 " WHERE type='index' AND name NOT LIKE 'sqlite_%'"
4380 "SELECT name FROM sqlite_temp_master"
4381 " WHERE type='index'"
4382 " ORDER BY 1", NULL);
4384 sqlite3_exec(db, t, callback, sql, &zErrMsg));
4387 t =
rpmExpand(
"SELECT name FROM sqlite_master"
4388 " WHERE type='index' AND tbl_name LIKE '", azArg[1],
"'",
4390 "SELECT name FROM sqlite_temp_master"
4391 " WHERE type='index' AND tbl_name LIKE '", azArg[1],
"'",
4392 " ORDER BY 1", NULL);
4394 sqlite3_exec(db, t, callback, sql, &zErrMsg));
4398 rpmsql_error(1,
"%s", zErrMsg);
4399 sqlite3_free(zErrMsg);
4403 rpmsql_error(1,
_(
"querying sqlite_master and sqlite_temp_master"));
4408 sql->flags = _flags;
4411 #ifdef SQLITE_ENABLE_IOTRACE
4412 if (c ==
'i' && !strncmp(azArg[0],
"iotrace", n)) {
4413 extern void (*sqlite3IoTrace) (
const char *, ...);
4414 rc = rpmsqlFOpen((nArg >= 2 ? azArg[1] : NULL), &sql->tfd);
4415 sqlite3IoTrace = (sql->tfd ? iotracePrintf : NULL);
4419 if (c ==
'l' && !strncmp(azArg[0],
"load", n) && nArg >= 2) {
4420 const char *zFile, *zProc;
4423 zProc = nArg >= 3 ? azArg[2] : 0;
4426 db = (sqlite3 *)sql->I;
4427 rc =
rpmsqlCmd(sql,
"load_extension", db,
4428 sqlite3_load_extension(db, zFile, zProc, &zErrMsg));
4430 rpmsql_error(1,
"%s", zErrMsg);
4431 sqlite3_free(zErrMsg);
4437 if (c ==
'l' && !strncmp(azArg[0],
"log", n) && nArg >= 1) {
4439 (void) rpmsqlFOpen((nArg >= 2 ? azArg[1] : NULL), &sql->lfd);
4441 if (c ==
'm' && !strncmp(azArg[0],
"mode", n) && nArg == 2) {
4442 int n2 = strlen30(azArg[1]);
4443 if ((n2 == 4 && !strncmp(azArg[1],
"line", n2))
4444 || (n2 == 5 && !strncmp(azArg[1],
"lines", n2))) {
4445 sql->mode = RPMSQL_MODE_LINE;
4446 }
else if ((n2 == 6 && !strncmp(azArg[1],
"column", n2))
4447 || (n2 == 7 && !strncmp(azArg[1],
"columns", n2))) {
4448 sql->mode = RPMSQL_MODE_COLUMN;
4449 }
else if (n2 == 4 && !strncmp(azArg[1],
"list", n2)) {
4450 sql->mode = RPMSQL_MODE_LIST;
4451 }
else if (n2 == 4 && !strncmp(azArg[1],
"html", n2)) {
4452 sql->mode = RPMSQL_MODE_HTML;
4453 }
else if (n2 == 3 && !strncmp(azArg[1],
"tcl", n2)) {
4454 sql->mode = RPMSQL_MODE_TCL;
4455 }
else if (n2 == 3 && !strncmp(azArg[1],
"csv", n2)) {
4456 sql->mode = RPMSQL_MODE_CSV;
4457 (void)
stpcpy(sql->separator,
",");
4458 }
else if (n2 == 4 && !strncmp(azArg[1],
"tabs", n2)) {
4459 sql->mode = RPMSQL_MODE_LIST;
4460 (void)
stpcpy(sql->separator,
"\t");
4461 }
else if (n2 == 6 && !strncmp(azArg[1],
"insert", n2)) {
4462 sql->mode = RPMSQL_MODE_INSERT;
4463 set_table_name(sql,
"table");
4465 rpmsql_error(1,
_(
"mode should be one of: %s"),
4466 "column csv html insert line list tabs tcl");
4470 if (c ==
'm' && !strncmp(azArg[0],
"mode", n) && nArg == 3) {
4471 int n2 = strlen30(azArg[1]);
4472 if (n2 == 6 && !strncmp(azArg[1],
"insert", n2)) {
4473 sql->mode = RPMSQL_MODE_INSERT;
4474 set_table_name(sql, azArg[2]);
4476 rpmsql_error(1,
_(
"invalid arguments: "
4477 " \"%s\". Enter \".help\" for help"), azArg[2]);
4481 if (c ==
'n' && !strncmp(azArg[0],
"nullvalue", n) && nArg == 2) {
4482 (void)
stpncpy(sql->nullvalue, azArg[1],
sizeof(sql->nullvalue)-1);
4484 if (c ==
'o' && !strncmp(azArg[0],
"output", n) && nArg == 2) {
4485 rc = rpmsqlFOpen((nArg >= 2 ? azArg[1] : NULL), &sql->ofd);
4488 sql->outfile =
_free(sql->outfile);
4490 sql->outfile =
xstrdup(azArg[1]);
4492 sql->ofd =
fdDup(STDOUT_FILENO);
4493 sql->outfile =
xstrdup(
"stdout");
4496 if (c ==
'p' && !strncmp(azArg[0],
"prompt", n)
4497 && (nArg == 2 || nArg == 3)) {
4499 sql->zPrompt =
_free(sql->zPrompt);
4500 sql->zPrompt =
xstrdup(azArg[1]);
4503 sql->zContinue =
_free(sql->zContinue);
4504 sql->zContinue =
xstrdup(azArg[2]);
4507 if (c ==
'q' && !strncmp(azArg[0],
"quit", n) && nArg == 1) {
4510 if (c ==
'r' && n >= 3 && !strncmp(azArg[0],
"read", n)
4512 FD_t _ifd = sql->ifd;
4513 sql->ifd =
Fopen(azArg[1],
"rb.fpio");
4514 if (sql->ifd == NULL ||
Ferror(sql->ifd)) {
4515 rpmsql_error(1,
_(
"cannot open \"%s\""), azArg[1]);
4519 rc = rpmsqlInput(sql);
4521 if (sql->ifd) (void)
Fclose(sql->ifd);
4524 if (c ==
'r' && n >= 3 && !strncmp(azArg[0],
"restore", n)
4525 && nArg > 1 && nArg < 4) {
4526 const char *zSrcFile;
4529 sqlite3_backup *pBackup;
4533 zSrcFile = azArg[1];
4536 zSrcFile = azArg[2];
4540 sqlite3_open(zSrcFile, &pSrc));
4543 rpmsql_error(1,
_(
"cannot open \"%s\""), zSrcFile);
4546 sqlite3_close(pSrc));
4550 db = (sqlite3 *)sql->I;
4551 pBackup = sqlite3_backup_init(db, zDb, pSrc,
"main");
4553 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4555 sqlite3_close(pSrc));
4558 while ((rc = sqlite3_backup_step(pBackup, 100)) == SQLITE_OK
4559 || rc == SQLITE_BUSY)
4561 if (rc == SQLITE_BUSY) {
4562 if (nTimeout++ >= 3)
4567 sqlite3_backup_finish(pBackup);
4574 rpmsql_error(1,
_(
"source database is busy"));
4578 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4583 sqlite3_close(pSrc));
4585 if (c ==
's' && !strncmp(azArg[0],
"schema", n) && nArg < 3) {
4587 uint32_t _flags = sql->flags;
4588 uint32_t _mode = sql->mode;
4591 db = (sqlite3 *)sql->I;
4592 sql->flags &= ~RPMSQL_FLAGS_SHOWHDR;
4593 sql->mode = RPMSQL_MODE_SEMI;
4596 for (i = 0; azArg[1][i]; i++)
4597 azArg[1][i] = (
char) tolower(azArg[1][i]);
4598 if (!strcmp(azArg[1],
"sqlite_master")) {
4599 char *new_argv[2], *new_colv[2];
4600 new_argv[0] =
"CREATE TABLE sqlite_master (\n"
4604 " rootpage integer,\n" " sql text\n" ")";
4606 new_colv[0] =
"sql";
4608 callback(sql, 1, new_argv, new_colv);
4610 }
else if (!strcmp(azArg[1],
"sqlite_temp_master")) {
4611 char *new_argv[2], *new_colv[2];
4612 new_argv[0] =
"CREATE TEMP TABLE sqlite_temp_master (\n"
4616 " rootpage integer,\n" " sql text\n" ")";
4618 new_colv[0] =
"sql";
4620 callback(sql, 1, new_argv, new_colv);
4625 " (SELECT sql sql, type type, tbl_name tbl_name, name name"
4626 " FROM sqlite_master UNION ALL"
4627 " SELECT sql, type, tbl_name, name FROM sqlite_temp_master)"
4628 " WHERE tbl_name LIKE '", azArg[1],
"'"
4629 " AND type!='meta' AND sql NOTNULL "
4630 "ORDER BY substr(type,2,1), name", NULL);
4632 sqlite3_exec(db, t, callback, sql, &zErrMsg));
4636 sql->flags = _flags;
4641 " (SELECT sql sql, type type, tbl_name tbl_name, name name"
4642 " FROM sqlite_master UNION ALL"
4643 " SELECT sql, type, tbl_name, name FROM sqlite_temp_master) "
4644 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'"
4645 "ORDER BY substr(type,2,1), name",
4646 callback, sql, &zErrMsg));
4649 rpmsql_error(1,
"%s", zErrMsg);
4650 sqlite3_free(zErrMsg);
4652 }
else if (rc != SQLITE_OK) {
4653 rpmsql_error(1,
_(
"querying schema information"));
4659 if (c ==
's' && !strncmp(azArg[0],
"separator", n) && nArg == 2) {
4660 (void)
stpncpy(sql->separator, azArg[1],
sizeof(sql->separator)-1);
4662 if (c ==
's' && !strncmp(azArg[0],
"show", n) && nArg == 1) {
4664 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"echo",
F_ISSET(sql, ECHO) ?
"on" :
"off");
4665 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"explain",
4666 sql->explainPrev.valid ?
"on" :
"off");
4667 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"headers",
4668 F_ISSET(sql, SHOWHDR) ?
"on" :
"off");
4669 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"mode", modeDescr[sql->mode]);
4670 rpmsqlFprintf(sql,
"%9.9s: ",
"nullvalue");
4671 output_c_string(sql, sql->nullvalue);
4672 rpmsqlFprintf(sql,
"\n");
4673 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"output",
4674 (sql->outfile ? sql->outfile :
"stdout"));
4675 rpmsqlFprintf(sql,
"%9.9s: ",
"separator");
4676 output_c_string(sql, sql->separator);
4677 rpmsqlFprintf(sql,
"\n");
4678 rpmsqlFprintf(sql,
"%9.9s: ",
"width");
4680 i < (int) ArraySize(sql->colWidth) && sql->colWidth[i] != 0;
4683 rpmsqlFprintf(sql,
"%d ", sql->colWidth[i]);
4685 rpmsqlFprintf(sql,
"\n");
4687 if (c ==
't' && n > 1 && !strncmp(azArg[0],
"tables", n) && nArg < 3) {
4692 db = (sqlite3 *)sql->I;
4695 sqlite3_get_table(db,
4696 "SELECT name FROM sqlite_master "
4697 "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%' "
4699 "SELECT name FROM sqlite_temp_master "
4700 "WHERE type IN ('table','view') "
4702 &azResult, &nRow, 0, &zErrMsg));
4705 t =
rpmExpand(
"SELECT name FROM sqlite_master "
4706 " WHERE type IN ('table','view') AND name LIKE '", azArg[1],
"'"
4708 "SELECT name FROM sqlite_temp_master"
4709 " WHERE type IN ('table','view') AND name LIKE '", azArg[1],
"'"
4710 "ORDER BY 1", NULL);
4712 sqlite3_get_table(db, t, &azResult, &nRow, 0,&zErrMsg));
4716 rpmsql_error(1,
"%s", zErrMsg);
4717 sqlite3_free(zErrMsg);
4720 rpmsql_error(1,
_(
"querying sqlite_master and sqlite_temp_master"));
4723 int len, maxlen = 0;
4725 int nPrintCol, nPrintRow;
4726 for (i = 1; i <= nRow; i++) {
4727 if (azResult[i] == 0)
4729 len = strlen30(azResult[i]);
4733 nPrintCol = 80 / (maxlen + 2);
4736 nPrintRow = (nRow + nPrintCol - 1) / nPrintCol;
4737 for (i = 0; i < nPrintRow; i++) {
4738 for (j = i + 1; j <= nRow; j += nPrintRow) {
4739 char *zSp = j <= nPrintRow ?
"" :
" ";
4740 rpmsqlFprintf(sql,
"%s%-*s", zSp, maxlen,
4741 azResult[j] ? azResult[j] :
"");
4743 rpmsqlFprintf(sql,
"\n");
4746 sqlite3_free_table(azResult);
4748 if (c ==
't' && n > 4 && !strncmp(azArg[0],
"timeout", n) && nArg == 2) {
4750 db = (sqlite3 *)sql->I;
4751 (
void)
rpmsqlCmd(sql,
"busy_timeout", db,
4752 sqlite3_busy_timeout(db, atoi(azArg[1])));
4754 if (HAS_TIMER && c ==
't' && n >= 5
4755 && !strncmp(azArg[0],
"timer", n) && nArg == 2) {
4756 sql->enableTimer = booleanValue(azArg[1]);
4758 if (c ==
'w' && !strncmp(azArg[0],
"width", n) && nArg > 1) {
4760 assert(nArg <= ArraySize(azArg));
4761 for (j = 1; j < nArg && j < ArraySize(sql->colWidth); j++)
4762 sql->colWidth[j - 1] = atoi(azArg[j]);
4765 rpmsql_error(1,
_(
"unknown command or invalid arguments: "
4766 " \"%s\". Enter \".help\" for help"), azArg[0]);
4777 #if defined(WITH_SQLITE)
4783 static int _contains_semicolon(
const char *z,
int N)
4787 for (i = 0; i < N; i++) {
4793 SQLDBG((stderr,
"<-- %s(%s) rc %d\n", __FUNCTION__, z, rc));
4800 static int _all_whitespace(
const char *z)
4805 if (
xisspace(*(
unsigned char *) z))
4807 if (*z ==
'/' && z[1] ==
'*') {
4809 while (*z && (*z !=
'*' || z[1] !=
'/'))
4818 if (*z ==
'-' && z[1] ==
'-') {
4820 while (*z && *z !=
'\n')
4830 SQLDBG((stderr,
"<-- %s(%s) rc %d\n", __FUNCTION__, z, rc));
4839 static int _is_command_terminator(
const char *zLine)
4843 while (
xisspace(*(
unsigned char *) zLine))
4845 if (zLine[0] ==
'/' && _all_whitespace(&zLine[1]))
4848 && _all_whitespace(&zLine[2]))
4852 SQLDBG((stderr,
"<-- %s(%s) rc %d\n", __FUNCTION__, zLine, rc));
4860 static int _is_complete(
char *zSql,
int nSql)
4866 zSql[nSql + 1] =
'\0';
4867 rc = sqlite3_complete(zSql);
4870 SQLDBG((stderr,
"<-- %s(%s) rc %d\n", __FUNCTION__, zSql, rc));
4884 static int rpmsqlInput(
rpmsql sql)
4886 sqlite3 * db = (sqlite3 *) sql->I;
4897 char * _buf = sql->buf;
4898 size_t _nbuf = sql->nbuf;
4900 SQLDBG((stderr,
"--> %s(%p)\n", __FUNCTION__, sql));
4905 sql->buf =
xmalloc(sql->nbuf);
4907 while (errCnt == 0 || !
F_ISSET(sql, BAIL) ||
F_ISSET(sql, PROMPT))
4909 if (sql->ofd)
Fflush(sql->ofd);
4910 zLine = rpmsqlInputOneLine(sql, zSql);
4919 if ((zSql == NULL || zSql[0] ==
'\0') && _all_whitespace(zLine))
4921 if (zLine && zLine[0] ==
'.' && nSql == 0) {
4923 rpmsqlFprintf(sql,
"%s\n", zLine);
4924 rc = rpmsqlMetaCommand(sql, zLine);
4931 if (_is_command_terminator(zLine) && _is_complete(zSql, nSql))
4932 memcpy(zLine,
";", 2);
4936 for (i = 0; zLine[i] &&
xisspace((
unsigned char) zLine[i]); i++)
4938 if (zLine[i] !=
'\0') {
4939 nSql = strlen30(zLine);
4941 memcpy(zSql, zLine, nSql + 1);
4945 int len = strlen30(zLine);
4946 zSql =
xrealloc(zSql, nSql + len + 4);
4947 zSql[nSql++] =
'\n';
4948 memcpy(&zSql[nSql], zLine, len + 1);
4951 if (zSql && _contains_semicolon(&zSql[nSqlPrior], nSql - nSqlPrior)
4952 && sqlite3_complete(zSql)) {
4955 db = (sqlite3 *)sql->I;
4957 rc = _rpmsqlShellExec(sql, zSql, _rpmsqlShellCallback, &zErrMsg);
4959 if (rc || zErrMsg) {
4963 "near line %d: ", startline);
4966 rpmsql_error(1,
"%s%s", zPrefix,
4967 zErrMsg ? zErrMsg : sqlite3_errmsg(db));
4968 zErrMsg =
_free(zErrMsg);
4976 if (!_all_whitespace(zSql))
4977 rpmsql_error(1,
_(
"incomplete SQL: %s"), zSql);
4981 sql->buf =
_free(sql->buf);
4985 SQLDBG((stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, sql, errCnt));
4997 static int rpmsqlInitRC(
rpmsql sql,
const char *sqliterc)
5001 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, sqliterc));
5005 if (sqliterc == NULL)
5006 sqliterc = sql->zInitrc;
5008 FD_t _ifd = sql->ifd;
5009 sql->ifd =
Fopen(sqliterc,
"rb.fpio");
5010 if (!(sql->ifd == NULL ||
Ferror(sql->ifd))) {
5011 if (
F_ISSET(sql, INTERACTIVE))
5012 rpmsql_error(0,
"-- Loading resources from %s", sqliterc);
5013 rc = rpmsqlInput(sql);
5015 if (sql->ifd) (void)
Fclose(sql->ifd);
5019 SQLDBG((stderr,
"<-- %s(%p,%s) rc %d\n", __FUNCTION__, sql, sqliterc, rc));
5028 #if defined(WITH_SQLITE)
5032 static void rpmsqlArgCallback(poptContext con,
5033 enum poptCallbackReason reason,
5034 const struct poptOption *opt,
5042 if (opt->arg == NULL)
5045 assert(arg != NULL);
5046 (void)
stpncpy(sql->separator, arg,
sizeof(sql->separator)-1);
5049 assert(arg != NULL);
5050 (void)
stpncpy(sql->nullvalue, arg,
sizeof(sql->nullvalue)-1);
5053 printf(
"%s\n", sqlite3_libversion());
5058 rpmsql_error(0,
_(
"%s: Unknown callback(0x%x)\n"),
5059 __FUNCTION__, (
unsigned) opt->val);
5060 poptPrintUsage(con, stderr, 0);
5067 static struct poptOption _rpmsqlOptions[] = {
5070 POPT_ARG_CALLBACK | POPT_CBFLAG_INC_DATA | POPT_CBFLAG_CONTINUE,
5071 rpmsqlArgCallback, 0, NULL, NULL},
5074 {
"debug",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH|POPT_ARGFLAG_DOC_HIDDEN, &
_rpmsql_debug, -1,
5075 N_(
"Debug embedded SQL interpreter"), NULL},
5076 {
"create",
'\0', POPT_BIT_SET|POPT_ARGFLAG_ONEDASH|POPT_ARGFLAG_DOC_HIDDEN, &_sql.flags, RPMSQL_FLAGS_CREATE,
5077 N_(
"create database if not exists"), NULL},
5079 {
"init",
'\0', POPT_ARG_STRING|POPT_ARGFLAG_ONEDASH, &_sql.zInitFile, 0,
5080 N_(
"read/process named FILE"),
N_(
"FILE") },
5081 {
"echo",
'\0', POPT_BIT_SET|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_ECHO,
5082 N_(
"print commands before execution"), NULL },
5084 {
"load",
'\0', POPT_BIT_SET|
POPT_ARGFLAG_TOGGLE|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_NOLOAD,
5085 N_(
"disable extension loading (normally enabled)"), NULL },
5086 {
"header",
'\0', POPT_BIT_SET|
POPT_ARGFLAG_TOGGLE|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_SHOWHDR,
5087 N_(
"turn headers on or off"), NULL },
5089 {
"bail",
'\0', POPT_BIT_SET|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_BAIL,
5090 N_(
"stop after hitting an error"), NULL },
5092 {
"interactive",
'\0', POPT_BIT_SET|
POPT_ARGFLAG_TOGGLE|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_INTERACTIVE,
5093 N_(
"force interactive I/O"), NULL },
5094 {
"batch",
'\0', POPT_BIT_CLR|
POPT_ARGFLAG_TOGGLE|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_INTERACTIVE,
5095 N_(
"force batch I/O"), NULL },
5097 {
"column",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_COLUMN,
5098 N_(
"set output mode to 'column'"), NULL },
5099 {
"csv",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_CSV,
5100 N_(
"set output mode to 'csv'"), NULL },
5101 {
"html",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_HTML,
5102 N_(
"set output mode to HTML"), NULL },
5103 {
"line",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_LINE,
5104 N_(
"set output mode to 'line'"), NULL },
5105 {
"list",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_LIST,
5106 N_(
"set output mode to 'list'"), NULL },
5107 {
"separator",
'\0', POPT_ARG_STRING|POPT_ARGFLAG_ONEDASH, 0,
'S',
5108 N_(
"set output field separator (|)"),
N_(
"CHAR") },
5109 {
"nullvalue",
'\0', POPT_ARG_STRING|POPT_ARGFLAG_ONEDASH, 0,
'N',
5110 N_(
"set text string for NULL values"),
N_(
"TEXT") },
5112 {
"version",
'\0', POPT_ARG_NONE|POPT_ARGFLAG_ONEDASH, 0,
'V',
5113 N_(
"show SQLite version"), NULL},
5117 N_(
"Common options for all rpmio executables:"), NULL},
5121 { NULL, (char) -1, POPT_ARG_INCLUDE_TABLE, NULL, 0,
5123 Usage: dbsql [OPTIONS] FILENAME [SQL]\n\
5124 FILENAME is the name of an SQLite database. A new database is created\n\
5125 if the file does not previously exist.\n\
5128 -help show this message\n\
5129 -init filename read/process named file\n\
5130 -echo print commands before execution\n\
5131 -[no]header turn headers on or off\n\
5132 -bail stop after hitting an error\n\
5133 -interactive force interactive I/O\n\
5134 -batch force batch I/O\n\
5135 -column set output mode to 'column'\n\
5136 -csv set output mode to 'csv'\n\
5137 -html set output mode to HTML\n\
5138 -line set output mode to 'line'\n\
5139 -list set output mode to 'list'\n\
5140 -separator 'x' set output field separator (|)\n\
5141 -nullvalue 'text' set text string for NULL values\n\
5142 -version show SQLite version\n\
5161 SQLDBG((stderr,
"==> %s(%p)\n", __FUNCTION__, sql));
5163 sql->zDestTable =
_free(sql->zDestTable);
5178 sql->buf =
_free(sql->buf);
5179 sql->buf = sql->b = NULL;
5180 sql->nbuf = sql->nb = 0;
5183 sql->zHome =
_free(sql->zHome);
5184 sql->zInitrc =
_free(sql->zInitrc);
5185 sql->zHistory =
_free(sql->zHistory);
5186 sql->zPrompt =
_free(sql->zPrompt);
5187 sql->zContinue =
_free(sql->zContinue);
5189 sql->outfile =
_free(sql->outfile);
5191 sql->zDbFilename =
_free(sql->zDbFilename);
5192 sql->zInitFile =
_free(sql->zInitFile);
5194 #if defined(WITH_SQLITE)
5196 sqlite3 * db = (sqlite3 *)sql->I;
5215 if (_rpmsqlPool == NULL) {
5221 memset(((
char *)sql)+
sizeof(sql->_item), 0,
sizeof(*sql)-
sizeof(sql->_item));
5227 const char ** av = sql->av;
5234 #if defined(WITH_SQLITE)
5239 static void rpmsqlInitPopt(
rpmsql sql,
int ac,
char ** av, poptOption tbl)
5245 if (av == NULL || av[0] == NULL || av[1] == NULL)
5248 con = poptGetContext(av[0], ac, (
const char **)av, tbl, 0);
5251 while ((rc = poptGetNextOpt(con)) > 0) {
5252 const char * arg = poptGetOptArg(con);
5257 rpmsql_error(0,
_(
"%s: option table misconfigured (%d)\n"),
5264 SQLDBG((stderr,
"%s: poptGetNextOpt rc(%d): %s\n", __FUNCTION__, rc, poptStrerror(rc)));
5267 sql->flags = _sql.flags;
5268 sql->mode = _sql.mode;
5269 if (_sql.zInitFile) {
5270 sql->zInitFile =
_free(sql->zInitFile);
5271 sql->zInitFile = _sql.zInitFile;
5272 _sql.zInitFile = NULL;
5274 memcpy(sql->separator, _sql.separator,
sizeof(sql->separator));
5275 memcpy(sql->nullvalue, _sql.nullvalue,
sizeof(sql->nullvalue));
5280 con = poptFreeContext(con);
5284 if (sql->separator[0] ==
'\0')
5285 switch (sql->mode) {
5287 case RPMSQL_MODE_LIST: (void)
stpcpy(sql->separator,
"|");
break;
5288 case RPMSQL_MODE_CSV: (void)
stpcpy(sql->separator,
",");
break;
5291 SQLDBG((stderr,
"<== %s(%p, %p[%u], %p)\n", __FUNCTION__, sql, av, (
unsigned)ac, tbl));
5298 (flags & 0x80000000) ?
rpmsqlI() :
5302 SQLDBG((stderr,
"==> %s(%p[%u], 0x%x)\n", __FUNCTION__, av, (
unsigned)ac, flags));
5308 #if defined(WITH_SQLITE)
5311 static int _oneshot;
5312 sqlite3 * db = NULL;
5316 #if defined(SQLITE_CONFIG_LOG)
5317 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, sql);
5319 sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
5324 memset(&_sql, 0,
sizeof(_sql));
5325 sql->flags = _sql.flags = flags;
5326 sql->mode = _sql.mode = RPMSQL_MODE_LIST;
5328 rpmsqlInitPopt(sql, ac, av, (poptOption) _rpmsqlOptions);
5331 if (sql->av && sql->av[0]) {
5332 sql->zDbFilename =
xstrdup(sql->av[0]);
5336 sqlite3_open(sql->zDbFilename, &db));
5337 sql->I = (
void *) db;
5340 sql->zDbFilename =
xstrdup(
":memory:");
5343 if (sql->zInitFile ||
F_ISSET(sql, INTERACTIVE)) {
5344 sql->ofd =
fdDup(STDOUT_FILENO);
5345 xx = rpmsqlInitRC(sql, sql->zInitFile);
5346 if (sql->ofd) (void)
Fclose(sql->ofd);
5348 rpmsqlInitPopt(sql, ac, av, (poptOption) _rpmsqlOptions);
5354 static const char _zInitrc[] =
"/.sqliterc";
5355 static const char _zHistory[] =
"/.sqlite_history";
5357 sql->zHome =
_free(sql->zHome);
5359 sql->zInitrc =
_free(sql->zInitrc);
5360 sql->zInitrc =
rpmGetPath(sql->zHome, _zInitrc, NULL);
5361 sql->zHistory =
_free(sql->zHistory);
5362 sql->zHistory =
rpmGetPath(sql->zHome, _zHistory, NULL);
5368 if (sql->zPrompt == NULL) {
5369 char * t =
xstrdup((av && av[0] ? av[0] :
"sql"));
5370 char * bn = basename(t);
5371 sql->zPrompt =
_free(sql->zPrompt);
5372 sql->zPrompt =
rpmExpand(bn,
"> ", NULL);
5374 sql->zContinue =
_free(sql->zContinue);
5375 sql->zContinue = t =
xstrdup(sql->zPrompt);
5376 while (*t && *t !=
'>')
5386 if (
F_ISSET(sql, INTERACTIVE)) {
5387 if (sql->ofd == NULL)
5388 sql->ofd =
fdDup(STDOUT_FILENO);
5390 if (sql->iob == NULL)
5401 SQLDBG((stderr,
"==> %s(%p,%p[%u]) \"%s\"\n", __FUNCTION__, sql, str, (
unsigned)(str ? strlen(str) : 0), str));
5402 SQLDBG((stderr,
"==========>\n%s\n<==========\n", str));
5404 if (sql == NULL) sql =
rpmsqlI();
5406 #if defined(WITH_SQLITE)
5408 const char * s = str;
5417 uint32_t _flags = sql->flags;
5418 FD_t _ofd = sql->ofd;
5419 FD_t _ifd = sql->ifd;
5421 SQLDBG((stderr,
"*** %s: INTERACTIVE\n", __FUNCTION__));
5422 sql->flags |= RPMSQL_FLAGS_INTERACTIVE;
5423 if (sql->ofd == NULL)
5424 sql->ofd =
fdDup(STDOUT_FILENO);
5427 extern char *db_full_version(
int *,
int *,
int *,
int *,
int *);
5428 fprintf(sql->out,
"%s\n"
5429 "Enter \".help\" for instructions\n"
5430 "Enter SQL statements terminated with a \";\"\n",
5431 db_full_version(NULL, NULL, NULL, NULL, NULL));
5436 "SQLite version ", sqlite3_libversion(),
"\n",
5437 #
if SQLITE_VERSION_NUMBER > 3006015
5438 "\t(", sqlite3_sourceid(),
")\n",
5440 "Enter \".help\" for instructions\n",
5441 "Enter SQL statements terminated with a \";\"\n", NULL);
5443 nw =
Fwrite(t, 1, nb, sql->ofd);
5447 #if defined(HAVE_READLINE) && HAVE_READLINE==1
5454 sql->ifd =
Fdopen(
fdDup(fileno(stdin)),
"rb.fpio");
5457 sql->flags |= RPMSQL_FLAGS_PROMPT;
5458 rc = rpmsqlInput(sql);
5459 sql->flags &= ~RPMSQL_FLAGS_PROMPT;
5461 if (sql->ifd) (void)
Fclose(sql->ifd);
5464 if (sql->zHistory) {
5471 sql->
flags = _flags;
5474 if (!strcmp(s,
"-") || !strcmp(s,
"stdin")) {
5475 FD_t _ofd = sql->ofd;
5476 SQLDBG((stderr,
"*** %s: STDIN\n", __FUNCTION__));
5478 if (sql->ofd == NULL) sql->ofd =
fdDup(STDOUT_FILENO);
5481 assert(sql->ifd == NULL);
5482 sql->ifd =
Fdopen(
fdDup(fileno(stdin)),
"rb.fpio");
5485 rc = rpmsqlInput(sql);
5487 if (sql->ifd) (void)
Fclose(sql->ifd);
5490 if (_ofd == NULL) (void)
Fclose(sql->ofd);
5496 FD_t _ifd = sql->ifd;
5497 SQLDBG((stderr,
"*** %s: FILE\n", __FUNCTION__));
5498 sql->ifd =
Fopen(s,
"rb.fpio");
5499 if (!(sql->ifd == NULL ||
Ferror(sql->ifd))) {
5500 rc = rpmsqlInput(sql);
5502 if (sql->ifd) (void)
Fclose(sql->ifd);
5506 SQLDBG((stderr,
"*** %s: STRING\n", __FUNCTION__));
5509 rc = rpmsqlMetaCommand(sql, t);
5513 char * zErrMsg = NULL;
5515 db = (sqlite3 *)sql->I;
5516 rc = _rpmsqlShellExec(sql, s, _rpmsqlShellCallback, &zErrMsg);
5518 rpmsql_error(1,
"%s", zErrMsg);
5519 zErrMsg =
_free(zErrMsg);
5521 }
else if (rc != 0) {
5522 rpmsql_error(1,
_(
"unable to process SQL \"%s\""), s);
5531 SQLDBG((stderr,
"==========>\n%s\n<==========\n",
rpmiobStr(sql->iob)));
5539 SQLDBG((stderr,
"<== %s(%p,%p[%u]) rc %d\n", __FUNCTION__, sql, str, (
unsigned)(str ? strlen(str) : 0), rc));