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) && (_vt)->debug) fprintf _l
65 #define VTDBGNOISY(_vt, _l) if ((_vt) && (_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) {
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++) {
191 if (hasSqlType(*av) ==
NULL)
203 static char * _rpmvtAppendCols(
rpmvt vt,
const char ** av)
205 char *
h = _rpmvtJoin(
"", av,
"");
211 int fx = (vd->fx == 3 ? 3 : 4);
213 av = (
const char **) (vt->argc > fx ? &vt->argv[fx] : vt->fields);
215 u = _rpmvtJoin(
"", av,
"");
216 u[strlen(u)-2] =
' ';
219 #define dbN vt->argv[1]
220 #define tblN vt->argv[2]
221 hu =
rpmExpand(
"CREATE TABLE ", dbN,
".", tblN,
" (\n", h, u,
");",
NULL);
228 VTDBG(vt, (stderr,
"%s\n", hu));
234 sqlite3 * db = (sqlite3 *) vt->db;
237 static const char * hidden[] = {
"path HIDDEN",
"id HIDDEN",
NULL };
248 VTDBG(vt, (stderr,
"--> %s(%p,%p)\n", __FUNCTION__, vt, vtp));
253 hu = _rpmvtAppendCols(vt, hidden);
255 sqlite3_declare_vtab(db, hu));
260 static char _quotes[] =
"'\"";
261 int quoted = (strchr(_quotes, *vt->argv[3]) !=
NULL);
266 prefix = (*path !=
'/' && vd->prefix ? vd->prefix :
"");
268 uri[strlen(uri)-quoted] =
'\0';
274 if (!strcasecmp(vt->argv[0],
"nixdb")) {
276 "select path from ValidPaths where glob('", fn,
"', path);",
282 if (!strcasecmp(vt->argv[0],
"Env")) {
285 fprintf(stderr,
" ENV: getenv(%p[%d])\n", &vt->argv[fx],
argvCount(&vt->argv[fx]));
292 fprintf(stderr,
"*** uri %s fn %s\n", uri, fn);
294 const char ** av =
NULL;
299 fprintf(stderr,
"GLOB: %d = Glob(%s) av %p[%d]\n", xx, uri, av, ac);
301 rc = SQLITE_NOTFOUND;
306 if (uri[strlen(uri)-1] ==
'/') {
307 DIR * dir = Opendir(uri);
310 fprintf(stderr,
" DIR: %p = Opendir(%s)\n", dir, uri);
312 rc = SQLITE_NOTFOUND;
314 while ((dp = Readdir(dir)) !=
NULL) {
315 if (!
strcmp(dp->d_name,
".") || !
strcmp(dp->d_name,
".."))
321 if (dir) xx = Closedir(dir);
323 if (!
Lstat(uri, &sb)) {
327 fprintf(stderr,
"FILE: %d = Slurp(%s)\n", xx, uri);
331 rc = SQLITE_NOTFOUND;
334 rc = SQLITE_NOTFOUND;
338 fprintf(stderr,
"LIST: %d = Append(%p[%d])\n", xx, &vt->argv[3],
argvCount(&vt->argv[3]));
353 (
void) rpmvtFree(vt);
361 VTDBG(vt, (stderr,
"<-- %s(%p,%p) rc %d\n", __FUNCTION__, vt, vtp, rc));
368 static struct rpmvd_s _argVD = {
371 int rpmvtCreate(
void * _db,
void * pAux,
372 int argc,
const char *
const * argv,
373 rpmvt * vtp,
char ** pzErr)
375 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_argVD), vtp);
378 int rpmvtConnect(
void * _db,
void * pAux,
379 int argc,
const char *
const * argv,
380 rpmvt * vtp,
char ** pzErr)
382 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_argVD), vtp);
386 static void dumpInfo(
const char *
msg,
const struct sqlite3_index_info * s)
388 fprintf(stderr,
"--------------------- %s\n", (msg ? msg :
""));
389 #define _PRT(f,v) fprintf(stderr, "%20s: " #f "\n", #v, s->v)
390 _PRT(%
p, aConstraintUsage);
393 _PRT(%d, needToFreeIdxStr);
394 _PRT(%d, orderByConsumed);
395 _PRT(%
g, estimatedCost);
400 int rpmvtBestIndex(
rpmvt vt,
void * _pInfo)
402 sqlite3_index_info * pInfo = (sqlite3_index_info *) _pInfo;
408 VTDBG(vt, (stderr,
"--> %s(%p,%p)\n", __FUNCTION__, vt, pInfo));
411 if (pInfo->aConstraint)
412 for (i = 0; i < pInfo->nConstraint; i++) {
413 const struct sqlite3_index_constraint *
p = pInfo->aConstraint +
i;
414 fprintf(stderr,
"\tcol %s(%d) 0x%02x 0x%02x\n", vt->cols[p->iColumn], p->iColumn,
418 for (i = 0; i < pInfo->nOrderBy; i++) {
419 const struct sqlite3_index_orderby *
p = pInfo->aOrderBy +
i;
420 fprintf(stderr,
"\tcol %s(%d) %s\n", vt->cols[p->iColumn], p->iColumn,
421 (p->desc ?
"DESC" :
"ASC"));
423 dumpInfo(__FUNCTION__, pInfo);
426 VTDBG(vt, (stderr,
"<-- %s(%p,%p) rc %d\n", __FUNCTION__, vt, pInfo, rc));
431 int rpmvtDisconnect(
rpmvt vt)
433 (
void) rpmvtFree(vt);
437 int rpmvtDestroy(
rpmvt vt)
439 (
void) rpmvtFree(vt);
443 static const char * dumpArg(
rpmvArg _v)
445 static char buf[BUFSIZ];
447 size_t nb =
sizeof(
buf);
448 sqlite3_value * v = (sqlite3_value *) _v;
449 int vtype = sqlite3_value_type(v);
450 unsigned long long ll;
455 snprintf(b, nb,
"%p(%d)", v, vtype);
461 ll = (
unsigned long long) sqlite3_value_int64(v);
465 d = sqlite3_value_double(v);
469 p = sqlite3_value_blob(v);
476 s = (
const char *)sqlite3_value_text(v);
487 static void dumpArgv(
const char * msg,
int argc,
rpmvArg * _argv)
489 if (argc > 0 && _argv) {
491 fprintf(stderr,
"--------------------- %s\n", (msg ? msg :
""));
492 for (i = 0; i < argc; i++)
493 fprintf(stderr,
"\targv[%d] %s\n", i, dumpArg(_argv[i]));
497 int rpmvtUpdate(
rpmvt vt,
int argc,
rpmvArg * _argv, int64_t * pRowid)
499 sqlite3_value ** argv = (sqlite3_value **) _argv;
502 VTDBG(vt, (stderr,
"--> %s(%p,%p[%u],%p)\n", __FUNCTION__, vt, argv, (
unsigned)argc, pRowid));
504 if (argc == 0 || argv ==
NULL) {
506 dumpArgv(
"ERROR", argc, _argv);
507 rc = SQLITE_NOTFOUND;
510 VTDBG(vt, (stderr,
"\tDELETE ROW 0x%llx\n", *(
unsigned long long *)argv[0]));
512 if (argv[0] ==
NULL) {
513 VTDBG(vt, (stderr,
"\tADD ROW 0x%llx\n", *(
unsigned long long *)argv[1]));
515 dumpArgv(
"ADD ROW", argc, _argv);
517 if (argv[0] == argv[1]) {
518 VTDBG(vt, (stderr,
"\tUPDATE ROW 0x%llx\n", *(
unsigned long long *)argv[1]));
520 dumpArgv(
"UPDATE argv", argc-2, _argv+2);
522 VTDBG(vt, (stderr,
"\tREPLACE ROW 0x%llx from 0x%llx\n",
523 *(
unsigned long long *)argv[0], *(
unsigned long long *)argv[1]));
525 dumpArgv(
"REPLACE argv", argc-2, _argv+2);
528 VTDBG(vt, (stderr,
"<-- %s(%p,%p[%u],%p) rc %d\n", __FUNCTION__, vt, argv, (
unsigned)argc, pRowid, rc));
532 int rpmvtBegin(
rpmvt vt)
535 VTDBG(vt, (stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, vt, rc));
539 int rpmvtSync(
rpmvt vt)
542 VTDBG(vt, (stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, vt, rc));
546 int rpmvtCommit(
rpmvt vt)
549 VTDBG(vt, (stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, vt, rc));
553 int rpmvtRollback(
rpmvt vt)
556 VTDBG(vt, (stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, vt, rc));
560 int rpmvtFindFunction(
rpmvt vt,
int nArg,
const char * zName,
561 void (**pxFunc)(
void *,
int,
rpmvArg *),
565 VTDBG(vt, (stderr,
"<-- %s(%p,%d,%s,%p,%p) rc %d\n", __FUNCTION__, vt, nArg, zName, pxFunc, ppArg, rc));
569 int rpmvtRename(
rpmvt vt,
const char * zNew)
572 VTDBG(vt, (stderr,
"<-- %s(%p,%s) rc %d\n", __FUNCTION__, vt, zNew, rc));
579 #define VCDBG(_vc, _l) if ((_vc)->debug) fprintf _l
580 #define VCDBGNOISY(_vc, _l) if ((_vc)->debug < 0) fprintf _l
589 struct rpmVC_s * VC = _VC;
592 VCDBGNOISY(vc, (stderr,
"==> %s(%p)\n", __FUNCTION__, vc));
594 (
void) rpmvtFree(vc->vt);
607 if (_rpmvcPool ==
NULL) {
612 VC = (
struct rpmVC_s *)
rpmioGetPool(pool,
sizeof(*VC));
613 memset(((
char *)VC)+
sizeof(VC->_item), 0,
sizeof(*VC)-
sizeof(VC->_item));
621 vc->vt = rpmvtLink(vt);
633 #if defined(WITH_SQLITE)
643 (
void) rpmvcFree(vc);
648 int rpmvcClose(
rpmvc vc)
652 (
void) rpmvtFree(vc->vt);
654 (
void) rpmvcFree(vc);
658 int rpmvcFilter(
rpmvc vc,
int idxNum,
const char * idxStr,
661 sqlite3_value ** argv = (sqlite3_value **) _argv;
664 VCDBGNOISY(vc, (stderr,
"--> %s(%p,%d,%s,%p[%u]) [%d:%d]\n", __FUNCTION__, vc, idxNum, idxStr, argv, (
unsigned)argc, vc->ix, vc->nrows));
665 dumpArgv(__FUNCTION__, argc, _argv);
670 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));
675 int rpmvcNext(
rpmvc vc)
679 if (vc->ix >= 0 && vc->ix < vc->nrows)
682 if (!(vc->ix >= 0 && vc->ix < vc->nrows))
683 VCDBGNOISY(vc, (stderr,
"<-- %s(%p) rc %d (%d:%d)\n", __FUNCTION__, vc, rc, vc->ix, vc->nrows));
687 int rpmvcEof(
rpmvc vc)
689 int rc = (vc->ix >= 0 && vc->ix < vc->nrows ? 0 : 1);
692 VCDBGNOISY(vc, (stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, vc, rc));
698 int rpmvcColumn(
rpmvc vc,
void * _pContext,
int colx)
700 sqlite3_context * pContext = (sqlite3_context *) _pContext;
703 const char * path = vt->av[vc->ix];
704 const char * col = vt->cols[colx];
710 int * offsets =
NULL;
721 nb = noffsets *
sizeof(*offsets);
729 for (i = 0; i < noffsets; i += 2) {
732 assert(offsets[i ] >= 0 && offsets[i ] <= (
int)nb);
733 assert(offsets[i+1] >= 0 && offsets[i+1] <= (
int)nb);
734 offsets[i+1] -= offsets[
i];
735 VCDBGNOISY(vc, (stderr,
"\t%d [%d,%d] %.*s\n", i/2, offsets[i], offsets[i+1], offsets[i+1], path+offsets[i]));
741 sqlite3_result_text(pContext, path, -1, SQLITE_STATIC);
746 for (i = 0; i < vt->nfields; i++) {
750 if (path[0] ==
'/' && !
strcmp(
"*", vt->fields[i])) {
758 sqlite3_result_null(pContext);
761 if (!
strcmp(col, vt->fields[i])) {
762 int ix = 2 * (i + 1);
763 const char * s = path + offsets[
ix];
764 size_t ns = offsets[ix+1];
765 sqlite3_result_text(pContext, s, ns, SQLITE_STATIC);
769 if (i == vt->nfields)
770 sqlite3_result_null(pContext);
772 if (vd->split && strlen(vd->split) == 1 && vt->nfields > 0) {
778 for (i = 0; i < vt->nfields; i++) {
779 if (
strcmp(col, vt->fields[i]))
781 sqlite3_result_text(pContext, av[i], -1, SQLITE_TRANSIENT);
784 if (i == vt->nfields)
785 sqlite3_result_null(pContext);
788 sqlite3_result_null(pContext);
796 VCDBG(vc, (stderr,
"<-- %s(%p,%p,%d) rc %d\n", __FUNCTION__, vc, pContext, colx, rc));
801 int rpmvcRowid(
rpmvc vc, int64_t * pRowid)
809 VCDBG(vc, (stderr,
"<-- %s(%p,%p) rc %d rowid 0x%llx\n", __FUNCTION__, vc, pRowid, rc, (
unsigned long long)(pRowid ? *pRowid : 0xf00)));
817 const char * _func,
const char * _fn,
unsigned _ln)
819 SQLDBG((stderr,
"==> %s:%u %s(%p) _rpmsqlI %p\n", _fn, _ln, _func, sql,
_rpmsqlI));
821 fprintf(stderr,
"\t flags: 0x%x\n", sql->flags);
823 fprintf(stderr,
"\t I: %p\n", sql->I);
824 fprintf(stderr,
"\t S: %p\n", sql->S);
825 fprintf(stderr,
"\t init: %s\n", sql->zInitFile);
826 fprintf(stderr,
"\t database: %s\n", sql->zDbFilename);
827 fprintf(stderr,
"\t table: %s\n", sql->zDestTable);
829 fprintf(stderr,
"\t mode: 0x%x\n", sql->mode);
830 fprintf(stderr,
"\t cnt: 0x%x\n", sql->cnt);
831 fprintf(stderr,
"\t iob: %p\n", sql->iob);
832 fprintf(stderr,
"\t IN ifd: %p\n", sql->ifd);
833 fprintf(stderr,
"\t OUT ofd: %p\n", sql->ofd);
834 fprintf(stderr,
"\t LOG lfd: %p\n", sql->lfd);
835 fprintf(stderr,
"\tTRACE tfd: %p\n", sql->tfd);
837 if (sql->explainPrev.valid) {
838 fprintf(stderr,
"\t explain:\n");
839 fprintf(stderr,
"\t\t mode: 0x%x\n", sql->explainPrev.mode);
840 fprintf(stderr,
"\t\tflags: 0x%x\n", sql->explainPrev.flags);
843 fprintf(stderr,
"\tseparator: %.*s\n", (
int)
sizeof(sql->separator), sql->separator);
844 fprintf(stderr,
"\tnullvalue: %.*s\n", (
int)
sizeof(sql->nullvalue), sql->nullvalue);
845 fprintf(stderr,
"\t outfile: %s\n", sql->outfile);
846 fprintf(stderr,
"\t home: %s\n", sql->zHome);
847 fprintf(stderr,
"\t initrc: %s\n", sql->zInitrc);
848 fprintf(stderr,
"\t history: %s\n", sql->zHistory);
849 fprintf(stderr,
"\t prompt: %s\n", sql->zPrompt);
850 fprintf(stderr,
"\t continue: %s\n", sql->zContinue);
852 fprintf(stderr,
"\t buf: %p[%u]\n", sql->buf, (
unsigned)sql->nbuf);
853 fprintf(stderr,
"\t b: %p[%u]\n", sql->b, (
unsigned)sql->nb);
856 #define rpmsqlDebugDump(_sql) \
857 _rpmsqlDebugDump(_sql, __FUNCTION__, __FILE__, __LINE__)
859 #if defined(WITH_SQLITE)
866 static void rpmsql_error(
int lvl,
const char *fmt, ...)
867 #if defined(__GNUC__) && __GNUC__ >= 2
868 __attribute__((
format (printf, 2, 3)))
873 rpmsql_error(
int lvl,
const char *fmt, ...)
881 (
void) vfprintf(stderr, fmt, ap);
910 db = (sqlite3 *) (_db ? _db : sql->I);
912 db = (sqlite3 *) _db;
913 rpmsql_error(0,
"sqlite3_%s(%p): rc(%d) %s", msg, db, rc,
923 #if defined(WITH_SQLITE)
928 static void _rpmsqlBeginTimer(
rpmsql sql)
930 if (sql->enableTimer)
931 getrusage(RUSAGE_SELF, &sql->sBegin);
935 static double timeDiff(
struct timeval *pStart,
struct timeval *pEnd)
937 return (pEnd->tv_usec - pStart->tv_usec) * 0.000001 +
938 (double) (pEnd->tv_sec - pStart->tv_sec);
945 static void _rpmsqlEndTimer(
rpmsql sql)
947 if (sql->enableTimer) {
953 getrusage(RUSAGE_SELF, &sEnd);
954 snprintf(b,
sizeof(b),
"CPU Time: user %f sys %f\n",
955 timeDiff(&sql->sBegin.ru_utime, &sEnd.ru_utime),
956 timeDiff(&sql->sBegin.ru_stime, &sEnd.ru_stime));
958 nw =
Fwrite(b, 1, nb, sql->ofd);
963 #define BEGIN_TIMER(_sql) _rpmsqlBeginTimer(_sql)
964 #define END_TIMER(_sql) _rpmsqlEndTimer(_sql)
967 #define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
982 SQLDBG((stderr,
"<== %s() _rpmsqlI %p\n", __FUNCTION__,
_rpmsqlI));
986 #if defined(WITH_SQLITE)
992 static int rpmsqlFprintf(
rpmsql sql,
const char *fmt, ...)
993 #if defined(__GNUC__) && __GNUC__ >= 2
994 __attribute__((
format (printf, 2, 3)))
997 static int rpmsqlFprintf(
rpmsql sql,
const char *fmt, ...)
1000 size_t nb =
sizeof(
b);
1012 if (!(rc >= 0 && rc < (
int)nb))
1018 size_t nw =
Fwrite(b, 1, rc, sql->ofd);
1033 #ifdef SQLITE_ENABLE_IOTRACE
1034 static void iotracePrintf(
const char *zFormat, ...)
1043 va_start(ap, zFormat);
1044 z = sqlite3_vmprintf(zFormat, ap);
1047 nw =
Fwrite(z, 1, nz, sql->tfd);
1053 #if defined(SQLITE_CONFIG_LOG)
1058 static void shellLog(
void *_sql,
int iErrCode,
const char *zMsg)
1061 if (sql && sql->lfd) {
1063 int xx =
snprintf(num,
sizeof(num),
"(%d) ", iErrCode);
1065 size_t nt = strlen(t);
1066 size_t nw =
Fwrite(t, 1, nt, sql->lfd);
1080 #define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){}
1081 #define sqliteCharVal(X) sqlite3ReadUtf8(X)
1083 #define sqliteNextChar(X) while( ( *++(X)) ) break
1084 #define sqliteCharVal(X) (int)(*(X))
1103 #define GEN_MATH_WRAP_DOUBLE_1(name, function, domain) \
1104 static void name(sqlite3_context *context, int argc, sqlite3_value **argv) {\
1107 switch (sqlite3_value_type(argv[0])) {\
1109 sqlite3_result_null(context);\
1112 rVal = sqlite3_value_double(argv[0]);\
1114 sqlite3_result_error(context, "domain error", -1);\
1116 sqlite3_result_double(context, function(rVal));\
1126 GEN_MATH_WRAP_DOUBLE_1(sqrtFunc, sqrt, rVal < 0)
1129 GEN_MATH_WRAP_DOUBLE_1(acosFunc, acos, rVal < -1.0 || rVal > 1.0)
1130 GEN_MATH_WRAP_DOUBLE_1(asinFunc, asin, rVal < -1.0 || rVal > 1.0)
1131 GEN_MATH_WRAP_DOUBLE_1(atanFunc, atan, 0)
1139 static double acosh(
double x)
1141 return log(x + sqrt(x * x - 1.0));
1145 GEN_MATH_WRAP_DOUBLE_1(acoshFunc, acosh, rVal < 1)
1147 static double asinh(
double x)
1149 return log(x + sqrt(x * x + 1.0));
1153 GEN_MATH_WRAP_DOUBLE_1(asinhFunc, asinh, 0)
1155 static double atanh(
double x)
1157 return (1.0 / 2.0) * log((1 + x) / (1 - x));
1161 GEN_MATH_WRAP_DOUBLE_1(atanhFunc, atanh, rVal > 1.0 || rVal < -1.0)
1166 static
double cot(
double x)
1168 return 1.0 / tan(x);
1171 GEN_MATH_WRAP_DOUBLE_1(sinFunc, sin, 0)
1172 GEN_MATH_WRAP_DOUBLE_1(cosFunc, cos, 0)
1173 GEN_MATH_WRAP_DOUBLE_1(tanFunc, tan, 0)
1174 GEN_MATH_WRAP_DOUBLE_1(cotFunc, cot, 0)
1176 static
double coth(
double x)
1178 return 1.0 / tanh(x);
1186 static double sinh(
double x)
1188 return (exp(x) - exp(-x)) / 2.0;
1191 GEN_MATH_WRAP_DOUBLE_1(sinhFunc, sinh, 0)
1194 static double cosh(
double x)
1196 return (exp(x) + exp(-x)) / 2.0;
1199 GEN_MATH_WRAP_DOUBLE_1(coshFunc, cosh, 0)
1202 static double tanh(
double x)
1204 return sinh(x) / cosh(x);
1207 GEN_MATH_WRAP_DOUBLE_1(tanhFunc, tanh, 0)
1208 GEN_MATH_WRAP_DOUBLE_1(cothFunc, coth, 0)
1214 static double log10(
double x)
1216 static double l10 = -1.0;
1220 return log(x) / l10;
1223 GEN_MATH_WRAP_DOUBLE_1(logFunc, log, rVal <= 0.0)
1224 GEN_MATH_WRAP_DOUBLE_1(log10Func, log10, rVal <= 0.0)
1225 GEN_MATH_WRAP_DOUBLE_1(expFunc, exp, 0)
1235 #define M_PI 3.14159265358979323846
1241 static double deg2rad(
double x)
1243 return x * M_PI / 180.0;
1249 static double rad2deg(
double x)
1251 return 180.0 * x / M_PI;
1253 GEN_MATH_WRAP_DOUBLE_1(rad2degFunc, rad2deg, 0)
1254 GEN_MATH_WRAP_DOUBLE_1(deg2radFunc, deg2rad, 0)
1259 static
void piFunc(sqlite3_context * context,
1260 int argc, sqlite3_value ** argv)
1262 sqlite3_result_double(context, M_PI);
1270 static void squareFunc(sqlite3_context * context,
1271 int argc, sqlite3_value ** argv)
1277 switch (sqlite3_value_type(argv[0])) {
1278 case SQLITE_INTEGER:
1279 iVal = sqlite3_value_int64(argv[0]);
1280 sqlite3_result_int64(context, iVal * iVal);
1283 sqlite3_result_null(context);
1286 rVal = sqlite3_value_double(argv[0]);
1287 sqlite3_result_double(context, rVal * rVal);
1297 static void powerFunc(sqlite3_context * context,
1298 int argc, sqlite3_value ** argv)
1305 if (sqlite3_value_type(argv[0]) == SQLITE_NULL
1306 || sqlite3_value_type(argv[1]) == SQLITE_NULL) {
1307 sqlite3_result_null(context);
1309 r1 = sqlite3_value_double(argv[0]);
1310 r2 = sqlite3_value_double(argv[1]);
1313 sqlite3_result_error(context,
"domain error", -1);
1315 sqlite3_result_double(context, pow(r1, r2));
1323 static void atn2Func(sqlite3_context * context,
1324 int argc, sqlite3_value ** argv)
1331 if (sqlite3_value_type(argv[0]) == SQLITE_NULL
1332 || sqlite3_value_type(argv[1]) == SQLITE_NULL) {
1333 sqlite3_result_null(context);
1335 r1 = sqlite3_value_double(argv[0]);
1336 r2 = sqlite3_value_double(argv[1]);
1337 sqlite3_result_double(context, atan2(r1, r2));
1347 static void signFunc(sqlite3_context * context,
1348 int argc, sqlite3_value ** argv)
1354 switch (sqlite3_value_type(argv[0])) {
1355 case SQLITE_INTEGER:
1356 iVal = sqlite3_value_int64(argv[0]);
1357 iVal = (iVal > 0) ? 1 : (iVal < 0) ? -1 : 0;
1358 sqlite3_result_int64(context, iVal);
1361 sqlite3_result_null(context);
1366 rVal = sqlite3_value_double(argv[0]);
1367 rVal = (rVal > 0) ? 1 : (rVal < 0) ? -1 : 0;
1368 sqlite3_result_double(context, rVal);
1376 static void ceilFunc(sqlite3_context * context,
1377 int argc, sqlite3_value ** argv)
1383 switch (sqlite3_value_type(argv[0])) {
1384 case SQLITE_INTEGER:
1385 iVal = sqlite3_value_int64(argv[0]);
1386 sqlite3_result_int64(context, iVal);
1389 sqlite3_result_null(context);
1392 rVal = sqlite3_value_double(argv[0]);
1393 sqlite3_result_int64(context, ceil(rVal));
1401 static void floorFunc(sqlite3_context * context,
1402 int argc, sqlite3_value ** argv)
1408 switch (sqlite3_value_type(argv[0])) {
1409 case SQLITE_INTEGER:
1410 iVal = sqlite3_value_int64(argv[0]);
1411 sqlite3_result_int64(context, iVal);
1414 sqlite3_result_null(context);
1417 rVal = sqlite3_value_double(argv[0]);
1418 sqlite3_result_int64(context, floor(rVal));
1427 static void replicateFunc(sqlite3_context * context,
1428 int argc, sqlite3_value ** argv)
1437 if (argc != 2 || SQLITE_NULL == sqlite3_value_type(argv[0]))
1440 iCount = sqlite3_value_int64(argv[1]);
1443 sqlite3_result_error(context,
"domain error", -1);
1445 nLen = sqlite3_value_bytes(argv[0]);
1446 nTLen = nLen * iCount;
1449 strcpy((
char *) zo, (
char *) sqlite3_value_text(argv[0]));
1451 for (i = 0; i < iCount; ++
i)
1452 strcpy((
char *) (z + i * nLen), (
char *) zo);
1454 sqlite3_result_text(context, (
char *) z, -1, free);
1459 static void properFunc(sqlite3_context * context,
1460 int argc, sqlite3_value ** argv)
1462 const unsigned char *z;
1469 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1470 sqlite3_result_null(context);
1474 z = sqlite3_value_text(argv[0]);
1475 zo = (
unsigned char *)
xstrdup((
const char *)z);
1478 while ((r = *(z++)) != 0) {
1489 sqlite3_result_text(context, (
char *) zo, -1, free);
1499 static void padlFunc(sqlite3_context * context,
1500 int argc, sqlite3_value ** argv)
1510 if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
1511 sqlite3_result_null(context);
1513 zi = (
const char *) sqlite3_value_text(argv[0]);
1514 ilen = sqlite3_value_int64(argv[1]);
1517 sqlite3_result_error(context,
"domain error", -1);
1520 zl = sqlite3utf8CharLen(zi, -1);
1523 sqlite3_result_text(context,
xstrdup(zi), -1, free);
1525 zo =
xmalloc(strlen(zi) + ilen - zl + 1);
1527 for (i = 1; i + zl <= ilen; ++
i)
1531 sqlite3_result_text(context, zo, -1, free);
1542 static void padrFunc(sqlite3_context * context,
1543 int argc, sqlite3_value ** argv)
1554 if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
1555 sqlite3_result_null(context);
1558 zi = (
const char *) sqlite3_value_text(argv[0]);
1559 _ilen = sqlite3_value_int64(argv[1]);
1562 sqlite3_result_error(context,
"domain error", -1);
1566 zl = sqlite3utf8CharLen(zi, -1);
1569 sqlite3_result_text(context,
xstrdup(zi), -1, free);
1572 zo =
xmalloc(zll + ilen - zl + 1);
1573 zt = strcpy(zo, zi) + zll;
1574 for (i = 1; i + zl <= ilen; ++
i)
1577 sqlite3_result_text(context, zo, -1, free);
1589 static void padcFunc(sqlite3_context * context,
1590 int argc, sqlite3_value ** argv)
1601 if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
1602 sqlite3_result_null(context);
1605 zi = (
const char *) sqlite3_value_text(argv[0]);
1606 _ilen = sqlite3_value_int64(argv[1]);
1609 sqlite3_result_error(context,
"domain error", -1);
1613 zl = sqlite3utf8CharLen(zi, -1);
1616 sqlite3_result_text(context,
xstrdup(zi), -1, free);
1619 zo =
xmalloc(zll + ilen - zl + 1);
1621 for (i = 1; 2 * i + zl <= ilen; ++
i)
1625 for (; i + zl <= ilen; ++
i)
1628 sqlite3_result_text(context, zo, -1, free);
1638 static void strfilterFunc(sqlite3_context * context,
1639 int argc, sqlite3_value ** argv)
1653 if (sqlite3_value_type(argv[0]) == SQLITE_NULL
1654 || sqlite3_value_type(argv[1]) == SQLITE_NULL) {
1655 sqlite3_result_null(context);
1657 zi1 = (
const char *) sqlite3_value_text(argv[0]);
1658 zi2 = (
const char *) sqlite3_value_text(argv[1]);
1659 zo =
xmalloc(strlen(zi1) + 1);
1662 while ((c1 = sqliteCharVal(z1)) != 0) {
1664 while ((c2 = sqliteCharVal(z21)) != 0 && c2 != c1)
1665 sqliteNextChar(z21);
1668 sqliteNextChar(z22);
1676 sqlite3_result_text(context, zo, -1, free);
1687 static int _substr(
const char *z1,
const char *z2,
int s,
const char **p)
1699 while ((sqliteCharVal(z2) != 0) && (c++) < s)
1703 while ((sqliteCharVal(z2)) != 0) {
1708 c1 = sqliteCharVal(zt1);
1709 c2 = sqliteCharVal(zt2);
1710 sqliteNextChar(zt1);
1711 sqliteNextChar(zt2);
1712 }
while (c1 == c2 && c1 != 0 && c2 != 0);
1724 return rVal >= 0 ? rVal + s : rVal;
1734 static void charindexFunc(sqlite3_context * context,
1735 int argc, sqlite3_value ** argv)
1742 assert(argc == 2 || argc == 3);
1743 if (SQLITE_NULL == sqlite3_value_type(argv[0])
1744 || SQLITE_NULL == sqlite3_value_type(argv[1])) {
1745 sqlite3_result_null(context);
1749 z1 = (
const char *) sqlite3_value_text(argv[0]);
1750 z2 = (
const char *) sqlite3_value_text(argv[1]);
1752 s = sqlite3_value_int(argv[2]) - 1;
1759 rVal = _substr(z1, z2, s,
NULL);
1760 sqlite3_result_int(context, rVal + 1);
1767 static void leftFunc(sqlite3_context * context,
1768 int argc, sqlite3_value ** argv)
1773 const unsigned char *z;
1774 const unsigned char *zt;
1778 if (SQLITE_NULL == sqlite3_value_type(argv[0])
1779 || SQLITE_NULL == sqlite3_value_type(argv[1])) {
1780 sqlite3_result_null(context);
1784 z = sqlite3_value_text(argv[0]);
1785 l = sqlite3_value_int(argv[1]);
1788 while (sqliteCharVal(zt) && c++ < l)
1794 strncpy((
char *) rz, (
char *) z, zt - z);
1796 sqlite3_result_text(context, (
char *) rz, -1, free);
1803 static void rightFunc(sqlite3_context * context,
1804 int argc, sqlite3_value ** argv)
1815 if (SQLITE_NULL == sqlite3_value_type(argv[0])
1816 || SQLITE_NULL == sqlite3_value_type(argv[1])) {
1817 sqlite3_result_null(context);
1821 z = (
const char *) sqlite3_value_text(argv[0]);
1822 l = sqlite3_value_int(argv[1]);
1825 while (sqliteCharVal(zt) != 0) {
1842 strcpy((
char *) rz, (
char *) (zt));
1843 sqlite3_result_text(context, (
char *) rz, -1, free);
1849 static const char * ltrim(
const char *s)
1860 static const char * rtrim(
char *s)
1862 char *ss = s + strlen(s) - 1;
1863 while (ss >= s && *ss ==
' ')
1872 static void ltrimFunc(sqlite3_context * context,
1873 int argc, sqlite3_value ** argv)
1878 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1879 sqlite3_result_null(context);
1882 z = (
const char *) sqlite3_value_text(argv[0]);
1883 sqlite3_result_text(context,
xstrdup(ltrim(z)), -1, free);
1889 static void rtrimFunc(sqlite3_context * context,
1890 int argc, sqlite3_value ** argv)
1895 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1896 sqlite3_result_null(context);
1899 z = (
const char *) sqlite3_value_text(argv[0]);
1900 sqlite3_result_text(context, rtrim(
xstrdup(z)), -1, free);
1906 static void trimFunc(sqlite3_context * context,
1907 int argc, sqlite3_value ** argv)
1912 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1913 sqlite3_result_null(context);
1916 z = (
const char *) sqlite3_value_text(argv[0]);
1917 sqlite3_result_text(context, rtrim(
xstrdup(ltrim(z))), -1, free);
1926 static void _append(
char **s1,
int l1,
const char *s2,
int l2)
1928 *s1 =
xrealloc(*s1, (l1 + l2 + 1) *
sizeof(
char));
1930 *(*(s1) + l1 + l2) =
'\0';
1936 static void replaceFunc(sqlite3_context * context,
1937 int argc, sqlite3_value ** argv)
1952 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1953 sqlite3_result_null(context);
1957 z1 = (
const char *)sqlite3_value_text(argv[0]);
1958 z2 = (
const char *)sqlite3_value_text(argv[1]);
1959 z3 = (
const char *)sqlite3_value_text(argv[2]);
1973 sqlite3_result_text(context,
xstrdup(z1), -1, free);
1982 ret = _substr(z2, zt1, 0, &zt2);
1987 _append(&zo, lzo, zt1, zt2 - zt1);
1989 _append(&zo, lzo, z3, lz3);
1994 _append(&zo, lzo, zt1, lz1 - (zt1 - z1));
1995 sqlite3_result_text(context, zo, -1, free);
2001 static void reverseFunc(sqlite3_context * context,
2002 int argc, sqlite3_value ** argv)
2012 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
2013 sqlite3_result_null(context);
2016 z = (
const char *)sqlite3_value_text(argv[0]);
2023 while (sqliteCharVal(zt) != 0) {
2026 for (i = 1; zt - i >= z; ++
i)
2027 *(rzt--) = *(zt -
i);
2030 sqlite3_result_text(context, rz, -1, free);
2040 typedef struct StdevCtx StdevCtx;
2055 typedef struct ModeCtx ModeCtx;
2071 static void varianceStep(sqlite3_context * context,
2072 int argc, sqlite3_value ** argv)
2079 p = sqlite3_aggregate_context(context,
sizeof(*p));
2081 if (SQLITE_NULL != sqlite3_value_numeric_type(argv[0])) {
2083 x = sqlite3_value_double(argv[0]);
2084 delta = (x - p->rM);
2085 p->rM += delta / p->cnt;
2086 p->rS += delta * (x - p->rM);
2093 static void modeStep(sqlite3_context * context,
2094 int argc, sqlite3_value ** argv)
2104 type = sqlite3_value_numeric_type(argv[0]);
2106 if (type == SQLITE_NULL)
2109 p = sqlite3_aggregate_context(context,
sizeof(*p));
2112 p->m = calloc(1,
sizeof(map));
2113 if (type == SQLITE_INTEGER) {
2115 *(p->m) = map_make(int_cmp);
2120 *(p->m) = map_make(double_cmp);
2126 if (0 == p->is_double) {
2127 xi = sqlite3_value_int64(argv[0]);
2128 iptr = (int64_t *) calloc(1,
sizeof(int64_t));
2130 map_insert(p->m, iptr);
2132 xd = sqlite3_value_double(argv[0]);
2133 dptr = (
double *) calloc(1,
sizeof(
double));
2135 map_insert(p->m, dptr);
2143 static void modeIterate(
void *e, int64_t c,
void *pp)
2147 ModeCtx *p = (ModeCtx *) pp;
2149 if (0 == p->is_double) {
2154 }
else if (p->mcnt < c) {
2160 ed = *(
double *) (e);
2164 }
else if (p->mcnt < c) {
2177 static void medianIterate(
void *e, int64_t c,
void *pp)
2185 ModeCtx *p = (ModeCtx *) pp;
2191 iR = p->cnt - p->pcnt;
2193 ir = p->cnt - p->mcnt;
2198 if (0 == p->is_double) {
2202 ed = *(
double *) (e);
2215 static void modeFinalize(sqlite3_context * context)
2217 ModeCtx *p = sqlite3_aggregate_context(context, 0);
2219 map_iterate(p->m, modeIterate, p);
2224 if (0 == p->is_double)
2225 sqlite3_result_int64(context, p->riM);
2227 sqlite3_result_double(context, p->rdM);
2235 static void _medianFinalize(sqlite3_context * context)
2237 ModeCtx *p = (ModeCtx *) sqlite3_aggregate_context(context, 0);
2240 map_iterate(p->m, medianIterate, p);
2244 if (0 == p->is_double)
2246 sqlite3_result_int64(context, p->riM);
2248 sqlite3_result_double(context, p->riM * 1.0 / p->mn);
2250 sqlite3_result_double(context, p->rdM / p->mn);
2257 static void medianFinalize(sqlite3_context * context)
2259 ModeCtx *p = (ModeCtx *) sqlite3_aggregate_context(context, 0);
2261 p->pcnt = (p->cnt) / 2.0;
2262 _medianFinalize(context);
2269 static void lower_quartileFinalize(sqlite3_context * context)
2271 ModeCtx *p = (ModeCtx *) sqlite3_aggregate_context(context, 0);
2273 p->pcnt = (p->cnt) / 4.0;
2274 _medianFinalize(context);
2281 static void upper_quartileFinalize(sqlite3_context * context)
2283 ModeCtx *p = (ModeCtx *) sqlite3_aggregate_context(context, 0);
2285 p->pcnt = (p->cnt) * 3 / 4.0;
2286 _medianFinalize(context);
2293 static void stdevFinalize(sqlite3_context * context)
2295 StdevCtx *p = sqlite3_aggregate_context(context, 0);
2296 if (p && p->cnt > 1)
2297 sqlite3_result_double(context, sqrt(p->rS / (p->cnt - 1)));
2299 sqlite3_result_double(context, 0.0);
2305 static void varianceFinalize(sqlite3_context * context)
2307 StdevCtx *p = sqlite3_aggregate_context(context, 0);
2308 if (p && p->cnt > 1)
2309 sqlite3_result_double(context, p->rS / (p->cnt - 1));
2311 sqlite3_result_double(context, 0.0);
2318 static void expandFunc(sqlite3_context * context,
2319 int argc, sqlite3_value ** argv)
2321 sqlite3_result_text(context,
2322 rpmExpand((
const char *)sqlite3_value_text(argv[0]),
NULL), -1, free);
2328 static void regexpFunc(sqlite3_context* context,
2329 int argc, sqlite3_value** argv)
2331 const char *
value = (
const char *) sqlite3_value_text(argv[0]);
2332 const char *
pattern = (
const char *) sqlite3_value_text(argv[1]);
2340 sqlite3_result_int(context, rc);
2343 sqlite3_result_error(context,
"invalid pattern", -1);
2349 static struct rpmsqlCF_s __CF[] = {
2351 {
"acos", 1, 0, SQLITE_UTF8, 0, acosFunc,
NULL, NULL },
2352 {
"asin", 1, 0, SQLITE_UTF8, 0, asinFunc,
NULL, NULL },
2353 {
"atan", 1, 0, SQLITE_UTF8, 0, atanFunc,
NULL, NULL },
2354 {
"atn2", 2, 0, SQLITE_UTF8, 0, atn2Func,
NULL, NULL },
2356 {
"atan2", 2, 0, SQLITE_UTF8, 0, atn2Func,
NULL, NULL },
2357 {
"acosh", 1, 0, SQLITE_UTF8, 0, acoshFunc,
NULL, NULL },
2358 {
"asinh", 1, 0, SQLITE_UTF8, 0, asinhFunc,
NULL, NULL },
2359 {
"atanh", 1, 0, SQLITE_UTF8, 0, atanhFunc,
NULL, NULL },
2362 {
"difference", 2, 0, SQLITE_UTF8, 0, differenceFunc,
NULL, NULL },
2364 {
"degrees", 1, 0, SQLITE_UTF8, 0, rad2degFunc,
NULL, NULL },
2365 {
"radians", 1, 0, SQLITE_UTF8, 0, deg2radFunc,
NULL, NULL },
2367 {
"cos", 1, 0, SQLITE_UTF8, 0, cosFunc,
NULL, NULL },
2368 {
"sin", 1, 0, SQLITE_UTF8, 0, sinFunc,
NULL, NULL },
2369 {
"tan", 1, 0, SQLITE_UTF8, 0, tanFunc,
NULL, NULL },
2370 {
"cot", 1, 0, SQLITE_UTF8, 0, cotFunc,
NULL, NULL },
2371 {
"cosh", 1, 0, SQLITE_UTF8, 0, coshFunc,
NULL, NULL },
2372 {
"sinh", 1, 0, SQLITE_UTF8, 0, sinhFunc,
NULL, NULL },
2373 {
"tanh", 1, 0, SQLITE_UTF8, 0, tanhFunc,
NULL, NULL },
2374 {
"coth", 1, 0, SQLITE_UTF8, 0, cothFunc,
NULL, NULL },
2376 {
"exp", 1, 0, SQLITE_UTF8, 0, expFunc,
NULL, NULL },
2377 {
"log", 1, 0, SQLITE_UTF8, 0, logFunc,
NULL, NULL },
2378 {
"log10", 1, 0, SQLITE_UTF8, 0, log10Func,
NULL, NULL },
2379 {
"power", 2, 0, SQLITE_UTF8, 0, powerFunc,
NULL, NULL },
2380 {
"sign", 1, 0, SQLITE_UTF8, 0, signFunc,
NULL, NULL },
2381 {
"sqrt", 1, 0, SQLITE_UTF8, 0, sqrtFunc,
NULL, NULL },
2382 {
"square", 1, 0, SQLITE_UTF8, 0, squareFunc,
NULL, NULL },
2384 {
"ceil", 1, 0, SQLITE_UTF8, 0, ceilFunc,
NULL, NULL },
2385 {
"floor", 1, 0, SQLITE_UTF8, 0, floorFunc,
NULL, NULL },
2387 {
"pi", 0, 0, SQLITE_UTF8, 1, piFunc,
NULL, NULL },
2390 {
"replicate", 2, 0, SQLITE_UTF8, 0, replicateFunc,
NULL, NULL },
2391 {
"charindex", 2, 0, SQLITE_UTF8, 0, charindexFunc,
NULL, NULL },
2392 {
"charindex", 3, 0, SQLITE_UTF8, 0, charindexFunc,
NULL, NULL },
2393 {
"leftstr", 2, 0, SQLITE_UTF8, 0, leftFunc,
NULL, NULL },
2394 {
"rightstr", 2, 0, SQLITE_UTF8, 0, rightFunc,
NULL, NULL },
2395 {
"ltrim", 1, 0, SQLITE_UTF8, 0, ltrimFunc,
NULL, NULL },
2396 {
"rtrim", 1, 0, SQLITE_UTF8, 0, rtrimFunc,
NULL, NULL },
2397 {
"trim", 1, 0, SQLITE_UTF8, 0, trimFunc,
NULL, NULL },
2398 {
"replace", 3, 0, SQLITE_UTF8, 0, replaceFunc,
NULL, NULL },
2399 {
"reverse", 1, 0, SQLITE_UTF8, 0, reverseFunc,
NULL, NULL },
2400 {
"proper", 1, 0, SQLITE_UTF8, 0, properFunc,
NULL, NULL },
2402 {
"padl", 2, 0, SQLITE_UTF8, 0, padlFunc,
NULL, NULL },
2403 {
"padr", 2, 0, SQLITE_UTF8, 0, padrFunc,
NULL, NULL },
2404 {
"padc", 2, 0, SQLITE_UTF8, 0, padcFunc,
NULL, NULL },
2406 {
"strfilter", 2, 0, SQLITE_UTF8, 0, strfilterFunc,
NULL, NULL },
2410 {
"stdev", 1, 0, SQLITE_UTF8, 0,
NULL, varianceStep, stdevFinalize },
2411 {
"variance", 1, 0, SQLITE_UTF8, 0,
NULL, varianceStep, varianceFinalize },
2412 {
"mode", 1, 0, SQLITE_UTF8, 0,
NULL, modeStep, modeFinalize },
2413 {
"median", 1, 0, SQLITE_UTF8, 0,
NULL, modeStep, medianFinalize },
2414 {
"lower_quartile", 1, 0, SQLITE_UTF8, 0,
NULL, modeStep, lower_quartileFinalize },
2415 {
"upper_quartile", 1, 0, SQLITE_UTF8, 0,
NULL, modeStep, upper_quartileFinalize },
2419 {
"expand", 1, 0, SQLITE_UTF8, 0, expandFunc,
NULL, NULL },
2420 {
"regexp", 2, 0, SQLITE_UTF8, 0, regexpFunc,
NULL, NULL },
2424 rpmsqlCF _rpmsqlCFT = __CF;
2426 int _rpmsqlLoadCFT(
rpmsql sql,
void * _CF)
2428 sqlite3 * db = (sqlite3 *)sql->I;
2432 SQLDBG((stderr,
"--> %s(%p,%p)\n", __FUNCTION__, sql, _CF));
2436 for (CF = (rpmsqlCF) _CF; CF->zName !=
NULL; CF++) {
2437 void * _pApp =
NULL;
2440 switch (CF->argType) {
2442 case 0: _pApp =
NULL;
break;
2443 case 1: _pApp = (
void *)db;
break;
2444 case 2: _pApp = (
void *)-1;
break;
2447 xx =
rpmsqlCmd(sql,
"create_function", db,
2448 sqlite3_create_function(db, CF->zName, CF->nArg, CF->eTextRep,
2449 _pApp, CF->xFunc, CF->xStep, CF->xFinal));
2450 SQLDBG((stderr,
"\t%s(%s) xx %d\n",
"sqlite3_create_function", CF->zName, xx));
2455 if (CF->needColSeq) {
2456 FuncDef *pFunc = sqlite3FindFunction(db, CF->zName,
2457 strlen(CF_>zName), CF->nArg, CF->eTextRep, 0);
2458 if (pFunc) pFunc->needCollSeq = 1;
2463 SQLDBG((stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, sql, rc));
2469 static struct rpmvd_s _envVD = {
2472 .regex =
"^([^=]+)=(.*)$",
2476 static int envCreateConnect(
void * _db,
void * pAux,
2477 int argc,
const char *
const * argv,
2478 rpmvt * vtp,
char ** pzErr)
2480 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_envVD), vtp);
2483 struct sqlite3_module envModule = {
2484 .xCreate = (
void *) envCreateConnect,
2485 .xConnect = (
void *) envCreateConnect,
2490 static struct rpmvd_s _grdbVD = {
2491 .prefix =
"%{?_etc_group}%{!?_etc_group:/etc/group}",
2494 .parse =
"_group:passwd:gid:groups",
2495 .regex =
"^([^:]*):([^:]*):([^:]*):([^:]*)$",
2499 static int grdbCreateConnect(
void * _db,
void * pAux,
2500 int argc,
const char *
const * argv,
2501 rpmvt * vtp,
char ** pzErr)
2503 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_grdbVD), vtp);
2506 struct sqlite3_module grdbModule = {
2507 .xCreate = (
void *) grdbCreateConnect,
2508 .xConnect = (
void *) grdbCreateConnect,
2513 static struct rpmvd_s _procdbVD = {
2514 .prefix =
"%{?_procdb}%{!?_procdb:/proc/[0-9]}",
2516 .parse =
"dir/pid/*",
2517 .regex =
"^(.+/)([0-9]+)$",
2521 static int procdbCreateConnect(
void * _db,
void * pAux,
2522 int argc,
const char *
const * argv,
2523 rpmvt * vtp,
char ** pzErr)
2525 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_procdbVD), vtp);
2528 struct sqlite3_module procdbModule = {
2529 .xCreate = (
void *) procdbCreateConnect,
2530 .xConnect = (
void *) procdbCreateConnect,
2535 static struct rpmvd_s _pwdbVD = {
2536 .prefix =
"%{?_etc_passwd}%{!?_etc_passwd:/etc/passwd}",
2538 .parse =
"user:passwd:uid:gid:gecos:dir:shell",
2539 .regex =
"^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*)$",
2543 static int pwdbCreateConnect(
void * _db,
void * pAux,
2544 int argc,
const char *
const * argv,
2545 rpmvt * vtp,
char ** pzErr)
2547 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_pwdbVD), vtp);
2550 struct sqlite3_module pwdbModule = {
2551 .xCreate = (
void *) pwdbCreateConnect,
2552 .xConnect = (
void *) pwdbCreateConnect,
2557 static struct rpmvd_s _repodbVD = {
2559 .prefix =
"%{?_repodb}%{!?_repodb:/X/popt/}",
2561 .parse =
"dir/file-NVRA-N-V-R.A",
2562 .regex =
"^(.+/)(((.*)-([^-]+)-([^-]+)\\.([^.]+))\\.rpm)$",
2566 static int repodbCreateConnect(
void * _db,
void * pAux,
2567 int argc,
const char *
const * argv,
2568 rpmvt * vtp,
char ** pzErr)
2570 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_repodbVD), vtp);
2573 struct sqlite3_module repodbModule = {
2574 .xCreate = (
void *) repodbCreateConnect,
2575 .xConnect = (
void *) repodbCreateConnect,
2580 static int _stat_debug = 0;
2582 static struct rpmvd_s _statVD = {
2584 .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",
2587 static int statCreateConnect(
void * _db,
void * pAux,
2588 int argc,
const char *
const * argv,
2589 rpmvt * vtp,
char ** pzErr)
2591 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_statVD), vtp);
2594 static int statColumn(
rpmvc vc,
void * _pContext,
int colx)
2596 sqlite3_context * pContext = (sqlite3_context *) _pContext;
2598 const char * path = vt->av[vc->ix];
2599 const char * col = vt->cols[colx];
2600 struct stat sb, *
st = &sb;
2601 int ret =
Lstat(path, &sb);
2604 if (_stat_debug < 0)
2605 fprintf(stderr,
"--> %s(%p,%p,%d)\n", __FUNCTION__, vc, pContext, colx);
2608 if (!
strcmp(col,
"path"))
2609 sqlite3_result_text(pContext, path, -1, SQLITE_STATIC);
2610 else if (!
strcmp(col,
"st_dev") && !ret)
2611 sqlite3_result_int64(pContext, st->st_dev);
2612 else if (!
strcmp(col,
"st_ino") && !ret)
2613 sqlite3_result_int64(pContext, st->st_ino);
2614 else if (!
strcmp(col,
"st_mode") && !ret)
2615 sqlite3_result_int64(pContext, st->st_mode);
2616 else if (!
strcmp(col,
"st_nlink") && !ret)
2617 sqlite3_result_int64(pContext, st->st_nlink);
2618 else if (!
strcmp(col,
"st_uid") && !ret)
2619 sqlite3_result_int64(pContext, st->st_uid);
2620 else if (!
strcmp(col,
"st_gid") && !ret)
2621 sqlite3_result_int64(pContext, st->st_gid);
2622 else if (!
strcmp(col,
"st_rdev") && !ret)
2623 sqlite3_result_int64(pContext, st->st_rdev);
2624 else if (!
strcmp(col,
"st_size") && !ret)
2625 sqlite3_result_int64(pContext, st->st_size);
2626 else if (!
strcmp(col,
"st_blksize") && !ret)
2627 sqlite3_result_int64(pContext, st->st_blksize);
2628 else if (!
strcmp(col,
"st_blocks") && !ret)
2629 sqlite3_result_int64(pContext, st->st_blocks);
2630 else if (!
strcmp(col,
"st_atime") && !ret)
2631 sqlite3_result_int64(pContext, st->st_atime);
2632 else if (!
strcmp(col,
"st_mtime") && !ret)
2633 sqlite3_result_int64(pContext, st->st_mtime);
2634 else if (!
strcmp(col,
"st_ctime") && !ret)
2635 sqlite3_result_int64(pContext, st->st_ctime);
2638 sqlite3_result_null(pContext);
2640 if (_stat_debug < 0)
2641 fprintf(stderr,
"<-- %s(%p,%p,%d) rc %d\n", __FUNCTION__, vc, pContext, colx, rc);
2646 struct sqlite3_module statModule = {
2647 .xCreate = (
void *) statCreateConnect,
2648 .xConnect = (
void *) statCreateConnect,
2649 .xColumn = (
void *) statColumn,
2654 static struct rpmvd_s _yumdbVD = {
2655 .prefix =
"%{?_yumdb}%{!?_yumdb:/var/lib/yum/yumdb}/",
2657 .parse =
"dir/hash-NVRA-N-V-R-A/*",
2658 .regex =
"^(.+/)([^-]+)-((.*)-([^-]+)-([^-]+)-([^-]+))$",
2662 static int yumdbCreateConnect(
void * _db,
void * pAux,
2663 int argc,
const char *
const * argv,
2664 rpmvt * vtp,
char ** pzErr)
2666 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_yumdbVD), vtp);
2669 struct sqlite3_module yumdbModule = {
2670 .xCreate = (
void *) yumdbCreateConnect,
2671 .xConnect = (
void *) yumdbCreateConnect,
2676 struct sqlite3_module _rpmvmTemplate = {
2677 .xCreate = (
void *) rpmvtCreate,
2678 .xConnect = (
void *) rpmvtConnect,
2679 .xBestIndex = (
void *) rpmvtBestIndex,
2680 .xDisconnect = (
void *) rpmvtDisconnect,
2681 .xDestroy = (
void *) rpmvtDestroy,
2682 .xOpen = (
void *) rpmvcOpen,
2683 .xClose = (
void *) rpmvcClose,
2684 .xFilter = (
void *) rpmvcFilter,
2685 .xNext = (
void *) rpmvcNext,
2686 .xEof = (
void *) rpmvcEof,
2687 .xColumn = (
void *) rpmvcColumn,
2688 .xRowid = (
void *) rpmvcRowid,
2689 .xUpdate = (
void *) rpmvtUpdate,
2690 .xBegin = (
void *) rpmvtBegin,
2691 .xSync = (
void *) rpmvtSync,
2692 .xCommit = (
void *) rpmvtCommit,
2693 .xRollback = (
void *) rpmvtRollback,
2694 .xFindFunction = (
void *) rpmvtFindFunction,
2695 .xRename = (
void *) rpmvtRename
2698 static struct rpmsqlVMT_s __VMT[] = {
2700 {
"Env", &envModule,
NULL },
2701 {
"Grdb", &grdbModule,
NULL },
2702 {
"Procdb", &procdbModule,
NULL },
2703 {
"Pwdb", &pwdbModule,
NULL },
2704 {
"Repodb", &repodbModule,
NULL },
2705 {
"Stat", &statModule,
NULL },
2706 {
"Yumdb", &yumdbModule,
NULL },
2710 static void rpmsqlVMFree(
void * _VM)
2713 SQLDBG((stderr,
"--> %s(%p)\n", __FUNCTION__, _VM));
2719 static void dumpVM(
const char * msg,
const rpmsqlVM s)
2721 fprintf(stderr,
"--------------------- %s\n", (msg ? msg :
""));
2722 #define VMPRT(f) if (s->f) fprintf(stderr, "%20s: %p\n", #f, s->f)
2740 VMPRT(xFindFunction);
2746 static rpmsqlVM rpmsqlVMNew(
const rpmsqlVM s)
2748 rpmsqlVM t =
xcalloc(1,
sizeof(*t));
2750 SQLDBG((stderr,
"--> %s(%p)\n", __FUNCTION__, s));
2751 *t = _rpmvmTemplate;
2754 if (s->iVersion) t->iVersion = s->iVersion;
2755 #define VMCPY(f) if (s->f) t->f = ((s->f != (void *)-1) ? s->f : NULL)
2773 VMCPY(xFindFunction);
2777 SQLDBG((stderr,
"<-- %s(%p) %p\n", __FUNCTION__, s, t));
2781 int _rpmsqlLoadVMT(
void * _db,
const rpmsqlVMT _VMT)
2783 sqlite3 * db = (sqlite3 *) _db;
2787 SQLDBG((stderr,
"--> %s(%p,%p)\n", __FUNCTION__, _db, _VMT));
2788 for (VMT = (rpmsqlVMT)_VMT; VMT->zName !=
NULL; VMT++) {
2792 sqlite3_create_module_v2(db, VMT->zName,
2793 rpmsqlVMNew(VMT->module), VMT->data, rpmsqlVMFree));
2794 SQLDBG((stderr,
"\t%s(%s) xx %d\n",
"sqlite3_create_module_v2", VMT->zName, xx));
2799 SQLDBG((stderr,
"<-- %s(%p,%p) rc %d\n", __FUNCTION__, _db, _VMT, rc));
2805 #if SQLITE_VERSION_NUMBER <= 3006015
2806 #define sqlite3_enable_load_extension(db, onoff) SQLITE_OK
2807 #define sqlite3_load_extension(db, zFile, zProc, pzErrMsg) SQLITE_OK
2815 static int _rpmsqlOpenDB(
rpmsql sql)
2822 db = (sqlite3 *)sql->I;
2826 sqlite3_open(sql->zDbFilename, &db));
2829 if (db && rc == SQLITE_OK) {
2830 (
void) _rpmsqlLoadCFT(sql, _rpmsqlCFT);
2831 (
void) _rpmsqlLoadVMT(db, __VMT);
2834 if (db ==
NULL || sqlite3_errcode(db) != SQLITE_OK) {
2836 rpmsql_error(1,
_(
"unable to open database \"%s\": %s"),
2837 sql->zDbFilename, sqlite3_errmsg(db));
2843 sqlite3_enable_load_extension(db, 1));
2848 SQLDBG((stderr,
"<-- %s(%p) rc %d %s\n", __FUNCTION__, sql, rc, sql->zDbFilename));
2856 #if defined(WITH_SQLITE)
2860 static int isNumber(
const char *z,
int *realnum)
2862 if (*z ==
'-' || *z ==
'+')
2880 if (*z ==
'e' || *z ==
'E') {
2882 if (*z ==
'+' || *z ==
'-')
2898 static int strlen30(
const char *z)
2903 return 0x3fffffff & (
int) (z2 - z);
2908 #if defined(WITH_SQLITE)
2913 static void output_hex_blob(
rpmsql sql,
const void *pBlob,
int nBlob)
2915 char *zBlob = (
char *) pBlob;
2918 SQLDBG((stderr,
"--> %s(%p,%p[%u])\n", __FUNCTION__, sql, pBlob, (
unsigned)nBlob));
2919 rpmsqlFprintf(sql,
"X'");
2920 for (i = 0; i < nBlob; i++)
2921 rpmsqlFprintf(sql,
"%02x", zBlob[i]);
2922 rpmsqlFprintf(sql,
"'");
2929 static void output_quoted_string(
rpmsql sql,
const char *z)
2933 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, z));
2934 for (i = 0; z[
i]; i++) {
2939 rpmsqlFprintf(sql,
"'%s'", z);
2941 rpmsqlFprintf(sql,
"'");
2943 for (i = 0; z[
i] && z[
i] !=
'\''; i++)
2946 rpmsqlFprintf(sql,
"''");
2948 }
else if (z[i] ==
'\'') {
2949 rpmsqlFprintf(sql,
"%.*s''", i, z);
2952 rpmsqlFprintf(sql,
"%s", z);
2956 rpmsqlFprintf(sql,
"'");
2964 static void output_c_string(
rpmsql sql,
const char *z)
2967 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, z));
2968 rpmsqlFprintf(sql,
"\"");
2969 while ((c = *(z++)) != 0) {
2971 rpmsqlFprintf(sql,
"\\\\");
2973 rpmsqlFprintf(sql,
"\\t");
2975 rpmsqlFprintf(sql,
"\\n");
2977 rpmsqlFprintf(sql,
"\\r");
2978 else if (!isprint(c))
2979 rpmsqlFprintf(sql,
"\\%03o", c & 0xff);
2981 rpmsqlFprintf(sql,
"%c", c);
2983 rpmsqlFprintf(sql,
"\"");
2991 static void output_html_string(
rpmsql sql,
const char *z)
2994 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, z));
2999 && z[
i] !=
'>' && z[
i] !=
'\"' && z[
i] !=
'\''; i++) {
3002 rpmsqlFprintf(sql,
"%.*s", i, z);
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,
""");
3011 else if (z[i] ==
'\'')
3012 rpmsqlFprintf(sql,
"'");
3024 static const char needCsvQuote[] = {
3025 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3026 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3027 1, 0, 1, 0, 0, 0, 0, 1, 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, 0,
3031 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3032 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,
3039 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3040 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3050 static void output_csv(
rpmsql sql,
const char *z,
int bSep)
3052 SQLDBG((stderr,
"--> %s(%p,%s,0x%x)\n", __FUNCTION__, sql, z, bSep));
3054 rpmsqlFprintf(sql,
"%s", sql->nullvalue);
3057 int nSep = strlen30(sql->separator);
3058 for (i = 0; z[
i]; i++) {
3059 if (needCsvQuote[((
unsigned char *) z)[i]]
3060 || (z[i] == sql->separator[0] &&
3061 (nSep == 1 || memcmp(z, sql->separator, nSep) == 0))) {
3067 rpmsqlFprintf(sql,
"\"");
3068 for (i = 0; z[
i]; i++) {
3070 rpmsqlFprintf(sql,
"\"");
3071 rpmsqlFprintf(sql,
"%c", z[i]);
3073 rpmsqlFprintf(sql,
"\"");
3075 rpmsqlFprintf(sql,
"%s", z);
3079 rpmsqlFprintf(sql,
"%s", sql->separator);
3087 static int _rpmsqlShellCallback(
void * _sql,
int nArg,
char **azArg,
char **azCol,
3094 SQLDBG((stderr,
"--> %s(%p,%d,%p,%p,%p)\n", __FUNCTION__, _sql, nArg, azArg, azCol, aiType));
3095 switch (sql->mode) {
3096 case RPMSQL_MODE_LINE:
3100 for (i = 0; i < nArg; i++) {
3101 int len = strlen30(azCol[i] ? azCol[i] :
"");
3106 rpmsqlFprintf(sql,
"\n");
3107 for (i = 0; i < nArg; i++)
3108 rpmsqlFprintf(sql,
"%*s = %s\n", w, azCol[i],
3109 azArg[i] ? azArg[i] : sql->nullvalue);
3111 case RPMSQL_MODE_EXPLAIN:
3112 case RPMSQL_MODE_COLUMN:
3113 if (sql->cnt++ == 0) {
3114 for (i = 0; i < nArg; i++) {
3116 w = (i < ArraySize(sql->colWidth) ? sql->colWidth[
i] : 0);
3119 w = strlen30(azCol[i] ? azCol[i] :
"");
3122 n = strlen30(azArg && azArg[i]
3123 ? azArg[i] : sql-> nullvalue);
3127 if (i < ArraySize(sql->actualWidth))
3128 sql->actualWidth[
i] = w;
3130 rpmsqlFprintf(sql,
"%-*.*s%s", w, w, azCol[i],
3131 i == nArg - 1 ?
"\n" :
" ");
3135 for (i = 0; i < nArg; i++) {
3136 w = (i < ArraySize(sql->actualWidth)
3137 ? sql->actualWidth[
i] : 10);
3139 rpmsqlFprintf(sql,
"%-*.*s%s", w, w,
3140 "-----------------------------------"
3141 "----------------------------------------------------------",
3142 i == nArg - 1 ?
"\n" :
" ");
3148 for (i = 0; i < nArg; i++) {
3149 w = (i < ArraySize(sql->actualWidth) ? sql->actualWidth[
i] : 10);
3150 if (sql->mode == RPMSQL_MODE_EXPLAIN && azArg[i] &&
3151 strlen30(azArg[i]) > w) {
3152 w = strlen30(azArg[i]);
3154 rpmsqlFprintf(sql,
"%-*.*s%s", w, w,
3155 azArg[i] ? azArg[i] : sql->nullvalue,
3156 i == nArg - 1 ?
"\n" :
" ");
3159 case RPMSQL_MODE_SEMI:
3160 case RPMSQL_MODE_LIST:
3161 if (sql->cnt++ == 0 &&
F_ISSET(sql, SHOWHDR)) {
3162 for (i = 0; i < nArg; i++)
3163 rpmsqlFprintf(sql,
"%s%s", azCol[i],
3164 i == nArg - 1 ?
"\n" : sql->separator);
3169 for (i = 0; i < nArg; i++) {
3173 rpmsqlFprintf(sql,
"%s", z);
3175 rpmsqlFprintf(sql,
"%s", sql->separator);
3176 else if (sql->mode == RPMSQL_MODE_SEMI)
3177 rpmsqlFprintf(sql,
";\n");
3179 rpmsqlFprintf(sql,
"\n");
3182 case RPMSQL_MODE_HTML:
3183 if (sql->cnt++ == 0 &&
F_ISSET(sql, SHOWHDR)) {
3184 rpmsqlFprintf(sql,
"<TR>");
3185 for (i = 0; i < nArg; i++) {
3186 rpmsqlFprintf(sql,
"<TH>");
3187 output_html_string(sql, azCol[i]);
3188 rpmsqlFprintf(sql,
"</TH>\n");
3190 rpmsqlFprintf(sql,
"</TR>\n");
3194 rpmsqlFprintf(sql,
"<TR>");
3195 for (i = 0; i < nArg; i++) {
3196 rpmsqlFprintf(sql,
"<TD>");
3197 output_html_string(sql, azArg[i] ? azArg[i] : sql->nullvalue);
3198 rpmsqlFprintf(sql,
"</TD>\n");
3200 rpmsqlFprintf(sql,
"</TR>\n");
3202 case RPMSQL_MODE_TCL:
3203 if (sql->cnt++ == 0 &&
F_ISSET(sql, SHOWHDR)) {
3204 for (i = 0; i < nArg; i++) {
3205 output_c_string(sql, azCol[i] ? azCol[i] :
"");
3206 rpmsqlFprintf(sql,
"%s", sql->separator);
3208 rpmsqlFprintf(sql,
"\n");
3212 for (i = 0; i < nArg; i++) {
3213 output_c_string(sql, azArg[i] ? azArg[i] : sql->nullvalue);
3214 rpmsqlFprintf(sql,
"%s", sql->separator);
3216 rpmsqlFprintf(sql,
"\n");
3218 case RPMSQL_MODE_CSV:
3219 if (sql->cnt++ == 0 &&
F_ISSET(sql, SHOWHDR)) {
3220 for (i = 0; i < nArg; i++)
3221 output_csv(sql, azCol[i] ? azCol[i] :
"", i < nArg - 1);
3222 rpmsqlFprintf(sql,
"\n");
3226 for (i = 0; i < nArg; i++)
3227 output_csv(sql, azArg[i], i < nArg - 1);
3228 rpmsqlFprintf(sql,
"\n");
3230 case RPMSQL_MODE_INSERT:
3234 rpmsqlFprintf(sql,
"INSERT INTO %s VALUES(", sql->zDestTable);
3235 for (i = 0; i < nArg; i++) {
3236 char *zSep = i > 0 ?
"," :
"";
3237 if ((azArg[i] == 0) || (aiType && aiType[i] == SQLITE_NULL)) {
3238 rpmsqlFprintf(sql,
"%sNULL", zSep);
3239 }
else if (aiType && aiType[i] == SQLITE_TEXT) {
3241 rpmsqlFprintf(sql,
"%s", zSep);
3242 output_quoted_string(sql, azArg[i]);
3244 && (aiType[i] == SQLITE_INTEGER
3245 || aiType[i] == SQLITE_FLOAT)) {
3246 rpmsqlFprintf(sql,
"%s%s", zSep, azArg[i]);
3247 }
else if (aiType && aiType[i] == SQLITE_BLOB && sql->S) {
3248 sqlite3_stmt * pStmt = (sqlite3_stmt *)sql->S;
3249 const void *pBlob = sqlite3_column_blob(pStmt, i);
3250 int nBlob = sqlite3_column_bytes(pStmt, i);
3252 rpmsqlFprintf(sql,
"%s", zSep);
3253 output_hex_blob(sql, pBlob, nBlob);
3254 }
else if (isNumber(azArg[i], 0)) {
3255 rpmsqlFprintf(sql,
"%s%s", zSep, azArg[i]);
3258 rpmsqlFprintf(sql,
"%s", zSep);
3259 output_quoted_string(sql, azArg[i]);
3262 rpmsqlFprintf(sql,
");\n");
3273 static int callback(
void *_sql,
int nArg,
char **azArg,
char **azCol)
3276 return _rpmsqlShellCallback(_sql, nArg, azArg, azCol,
NULL);
3285 static void set_table_name(
rpmsql sql,
const char *zName)
3291 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, zName));
3292 sql->zDestTable =
_free(sql->zDestTable);
3295 needQuote = !
xisalpha((
unsigned char) *zName) && *zName !=
'_';
3296 for (i = n = 0; zName[
i]; i++, n++) {
3297 if (!
xisalnum((
unsigned char) zName[i]) && zName[i] !=
'_') {
3299 if (zName[i] ==
'\'')
3305 sql->zDestTable = z =
xmalloc(n + 1);
3309 for (i = 0; zName[
i]; i++) {
3311 if (zName[i] ==
'\'')
3328 static char *appendText(
char *zIn,
char const *zAppend,
char quote)
3332 int nAppend = strlen30(zAppend);
3333 int nIn = (zIn ? strlen30(zIn) : 0);
3335 SQLDBG((stderr,
"--> %s(%s,%s,0x%02x)\n", __FUNCTION__, zIn, zAppend, quote));
3336 len = nAppend + nIn + 1;
3339 for (i = 0; i < nAppend; i++) {
3340 if (zAppend[i] == quote)
3348 char *zCsr = &zIn[nIn];
3350 for (i = 0; i < nAppend; i++) {
3351 *zCsr++ = zAppend[
i];
3352 if (zAppend[i] == quote)
3357 assert((zCsr - zIn) == len);
3359 memcpy(&zIn[nIn], zAppend, nAppend);
3360 zIn[len - 1] =
'\0';
3375 static int run_table_dump_query(
rpmsql sql, sqlite3 * db,
3376 const char *zSelect,
const char *zFirstRow)
3378 sqlite3_stmt * pSelect;
3380 SQLDBG((stderr,
"--> %s(%p,%p,%s,%s)\n", __FUNCTION__, sql, db, zSelect, zFirstRow));
3382 sqlite3_prepare(db, zSelect, -1, &pSelect, 0));
3383 if (rc || pSelect ==
NULL)
3387 sqlite3_step(pSelect))) == SQLITE_ROW)
3390 rpmsqlFprintf(sql,
"%s", zFirstRow);
3393 rpmsqlFprintf(sql,
"%s;\n", sqlite3_column_text(pSelect, 0));
3397 sqlite3_finalize(pSelect));
3403 #if defined(WITH_SQLITE)
3404 #define iseol(_c) ((char)(_c) == '\n' || (char)(_c) == '\r')
3415 rpmsqlFgets(
char * buf,
size_t nbuf,
rpmsql sql)
3419 FD_t ifd = sql->ifd;
3429 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)));
3436 if (fgets(q, (
int)nbuf, ifp) ==
NULL)
3440 for (q += nb - 1; nb > 0 &&
iseol(*q); q--)
3442 for (; p <=
q; p++) {
3449 default: p++;
break;
3454 case '{': p++,
bc++;
break;
3455 case '(': p++, pc++;
break;
3456 case '%': p++;
break;
3459 case '{':
if (
bc > 0)
bc++;
break;
3460 case '}':
if (
bc > 0)
bc--;
break;
3461 case '(':
if (pc > 0) pc++;
break;
3462 case ')':
if (pc > 0) pc--;
break;
3465 if (nb == 0 || (*q !=
'\\' && !
bc && !pc) || *(q+1) ==
'\0') {
3475 SQLDBG((stderr,
"<-- %s(%p[%u],%p) nr %u\n", __FUNCTION__, buf, (
unsigned)nbuf, sql, (
unsigned)nr));
3477 return (nr > 0 ? buf :
NULL);
3490 static char *local_getline(
rpmsql sql,
const char *zPrompt)
3494 SQLDBG((stderr,
"--> %s(%s) ofd %p\n", __FUNCTION__, zPrompt, sql->ofd));
3496 if (sql->ofd && zPrompt && *zPrompt) {
3497 size_t nb = strlen(zPrompt);
3498 size_t nw =
Fwrite(zPrompt, 1, nb, sql->ofd);
3504 t = rpmsqlFgets(sql->buf, sql->nbuf, sql);
3506 SQLDBG((stderr,
"<-- %s(%s) ofd %p\n", __FUNCTION__, zPrompt, sql->ofd));
3518 static char *rpmsqlInputOneLine(
rpmsql sql,
const char *zPrior)
3520 const char *zPrompt;
3523 SQLDBG((stderr,
"--> %s(%s)\n", __FUNCTION__, zPrior));
3529 zResult = local_getline(sql,
NULL);
3531 zPrompt = (zPrior && zPrior[0]) ? sql->zContinue : sql->zPrompt;
3534 #if defined(HAVE_READLINE) && HAVE_READLINE==1
3538 if (zResult != sql->buf) {
3539 strncpy(sql->buf, zResult, sql->nbuf);
3540 zResult =
_free(zResult);
3547 SQLDBG((stderr,
"<-- %s(%s)\n", __FUNCTION__, zPrior));
3556 #if defined(WITH_SQLITE)
3560 static char *save_err_msg(sqlite3 * db)
3562 const char * s = sqlite3_errmsg(db);
3563 int nb = strlen30(s) + 1;
3564 return memcpy(
xmalloc(nb), s, nb);
3577 static int _rpmsqlShellExec(
rpmsql sql,
const char *zSql,
3578 int (*xCallback) (
void *,
int,
char **,
char **,
int *),
3582 sqlite3 * db = (sqlite3 *) sql->I;
3583 sqlite3_stmt * pStmt =
NULL;
3585 const char *zLeftover;
3587 SQLDBG((stderr,
"--> %s(%p,%s,%p,%p)\n", __FUNCTION__, sql, zSql, xCallback, pzErrMsg));
3591 while (zSql[0] && rc == SQLITE_OK) {
3593 sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover));
3602 if (sql->ofd &&
F_ISSET(sql, ECHO)) {
3603 const char *zStmtSql = sqlite3_sql(pStmt);
3604 rpmsqlFprintf(sql,
"%s\n", zStmtSql ? zStmtSql : zSql);
3612 sqlite3_step(pStmt));
3614 if (rc == SQLITE_ROW) {
3618 int nCol = sqlite3_column_count(pStmt);
3619 size_t nb = 3 * nCol *
sizeof(
const char *) + 1;
3621 char ** azVals = &azCols[nCol];
3622 int * aiTypes = (
int *) &azVals[nCol];
3626 for (i = 0; i < nCol; i++)
3627 azCols[i] = (
char *) sqlite3_column_name(pStmt, i);
3630 sql->S = (
void *) pStmt;
3634 for (i = 0; i < nCol; i++) {
3635 azVals[
i] = (
char *) sqlite3_column_text(pStmt, i);
3636 aiTypes[
i] = sqlite3_column_type(pStmt, i);
3637 if (!azVals[i] && (aiTypes[i] != SQLITE_NULL)) {
3644 if (rc != SQLITE_ROW)
3648 if (xCallback (sql, nCol, azVals, azCols, aiTypes)) {
3653 sqlite3_step(pStmt));
3654 }
while (rc == SQLITE_ROW);
3655 azCols =
_free(azCols);
3660 sqlite3_step(pStmt));
3661 }
while (rc == SQLITE_ROW);
3669 sqlite3_finalize(pStmt));
3675 *pzErrMsg = save_err_msg(db);
3691 #if defined(WITH_SQLITE)
3700 static int dump_callback(
void *_sql,
int nArg,
char **azArg,
char **azCol)
3703 sqlite3 * db = (sqlite3 *) sql->I;
3708 const char *zPrepStmt = 0;
3711 SQLDBG((stderr,
"--> %s(%p,%d,%p,%p)\n", __FUNCTION__, _sql, nArg, azArg, azCol));
3719 if (!
strcmp(zTable,
"sqlite_sequence")) {
3720 zPrepStmt =
"DELETE FROM sqlite_sequence;\n";
3721 }
else if (!
strcmp(zTable,
"sqlite_stat1")) {
3722 rpmsqlFprintf(sql,
"ANALYZE sqlite_master;\n");
3723 }
else if (!strncmp(zTable,
"sqlite_", 7)) {
3726 }
else if (!strncmp(zSql,
"CREATE VIRTUAL TABLE", 20)) {
3728 if (!
F_ISSET(sql, WRITABLE)) {
3729 rpmsqlFprintf(sql,
"PRAGMA writable_schema=ON;\n");
3730 sql->flags |= RPMSQL_FLAGS_WRITABLE;
3734 (
"INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
3735 "VALUES('table','%q','%q',0,'%q');", zTable, zTable, zSql);
3736 rpmsqlFprintf(sql,
"%s\n", zIns);
3741 rpmsqlFprintf(sql,
"%s;\n", zSql);
3743 if (!
strcmp(zType,
"table")) {
3744 sqlite3_stmt * pTableInfo =
NULL;
3746 char *zTableInfo = 0;
3750 zTableInfo = appendText(zTableInfo,
"PRAGMA table_info(", 0);
3751 zTableInfo = appendText(zTableInfo, zTable,
'"');
3752 zTableInfo = appendText(zTableInfo,
");", 0);
3755 sqlite3_prepare(db, zTableInfo, -1, &pTableInfo, 0));
3756 zTableInfo =
_free(zTableInfo);
3757 if (rc != SQLITE_OK || !pTableInfo)
3760 zSelect = appendText(zSelect,
"SELECT 'INSERT INTO ' || ", 0);
3762 zTmp = appendText(zTmp, zTable,
'"');
3764 zSelect = appendText(zSelect, zTmp,
'\'');
3767 zSelect = appendText(zSelect,
" || ' VALUES(' || ", 0);
3769 sqlite3_step(pTableInfo));
3770 while (rc == SQLITE_ROW) {
3772 (
const char *) sqlite3_column_text(pTableInfo, 1);
3773 zSelect = appendText(zSelect,
"quote(", 0);
3774 zSelect = appendText(zSelect, zText,
'"');
3776 sqlite3_step(pTableInfo));
3777 if (rc == SQLITE_ROW)
3778 zSelect = appendText(zSelect,
") || ',' || ", 0);
3780 zSelect = appendText(zSelect,
") ", 0);
3784 sqlite3_finalize(pTableInfo));
3785 if (rc != SQLITE_OK || nRow == 0) {
3786 zSelect =
_free(zSelect);
3790 zSelect = appendText(zSelect,
"|| ')' FROM ", 0);
3791 zSelect = appendText(zSelect, zTable,
'"');
3793 rc = run_table_dump_query(sql, db, zSelect, zPrepStmt);
3794 if (rc == SQLITE_CORRUPT) {
3795 zSelect = appendText(zSelect,
" ORDER BY rowid DESC", 0);
3796 rc = run_table_dump_query(sql, db, zSelect,
NULL);
3798 zSelect =
_free(zSelect);
3813 static int run_schema_dump_query(
rpmsql sql,
3814 const char *zQuery,
char **pzErrMsg)
3816 sqlite3 * db = (sqlite3 *) sql->I;
3819 SQLDBG((stderr,
"--> %s(%p,%s,%p)\n", __FUNCTION__, sql, zQuery, pzErrMsg));
3821 sqlite3_exec(db, zQuery, dump_callback, sql, pzErrMsg));
3822 if (rc == SQLITE_CORRUPT) {
3825 sqlite3_free(*pzErrMsg);
3828 sqlite3_exec(db, zQ2, dump_callback, sql, pzErrMsg));
3838 static char zHelp[] =
3839 ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
3840 ".bail ON|OFF Stop after hitting an error. Default OFF\n"
3841 ".databases List names and files of attached databases\n"
3842 ".dump ?TABLE? ... Dump the database in an SQL text format\n"
3843 " If TABLE specified, only dump tables matching\n"
3844 " LIKE pattern TABLE.\n"
3845 ".echo ON|OFF Turn command echo on or off\n"
3846 ".exit Exit this program\n"
3847 ".explain ?ON|OFF? Turn output mode suitable for EXPLAIN on or off.\n"
3848 " With no args, it turns EXPLAIN on.\n"
3849 ".header(s) ON|OFF Turn display of headers on or off\n"
3850 ".help Show this message\n"
3851 ".import FILE TABLE Import data from FILE into TABLE\n"
3852 ".indices ?TABLE? Show names of all indices\n"
3853 " If TABLE specified, only show indices for tables\n"
3854 " matching LIKE pattern TABLE.\n"
3855 #ifdef SQLITE_ENABLE_IOTRACE
3856 ".iotrace FILE Enable I/O diagnostic logging to FILE\n"
3858 ".load FILE ?ENTRY? Load an extension library\n"
3859 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n"
3860 ".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
3861 " csv Comma-separated values\n"
3862 " column Left-aligned columns. (See .width)\n"
3863 " html HTML <table> code\n"
3864 " insert SQL insert statements for TABLE\n"
3865 " line One value per line\n"
3866 " list Values delimited by .separator string\n"
3867 " tabs Tab-separated values\n"
3868 " tcl TCL list elements\n"
3869 ".nullvalue STRING Print STRING in place of NULL values\n"
3870 ".output FILENAME Send output to FILENAME\n"
3871 ".output stdout Send output to the screen\n"
3872 ".prompt MAIN CONTINUE Replace the standard prompts\n"
3873 ".quit Exit this program\n"
3874 ".read FILENAME Execute SQL in FILENAME\n"
3875 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
3876 ".schema ?TABLE? Show the CREATE statements\n"
3877 " If TABLE specified, only show tables matching\n"
3878 " LIKE pattern TABLE.\n"
3879 ".separator STRING Change separator used by output mode and .import\n"
3880 ".show Show the current values for various settings\n"
3881 ".tables ?TABLE? List names of tables\n"
3882 " If TABLE specified, only list tables matching\n"
3883 " LIKE pattern TABLE.\n"
3884 ".timeout MS Try opening locked tables for MS milliseconds\n"
3885 ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n";
3887 static char zTimerHelp[] =
3888 ".timer ON|OFF Turn the CPU timer measurement on or off\n";
3899 static void resolve_backslashes(
char *z)
3903 for (i = j = 0; (c = z[
i]) != 0; i++, j++) {
3908 }
else if (c ==
't') {
3910 }
else if (c ==
'r') {
3912 }
else if (c >=
'0' && c <=
'7') {
3914 if (z[i + 1] >=
'0' && z[i + 1] <=
'7') {
3916 c = (c << 3) + z[i] -
'0';
3917 if (z[i + 1] >=
'0' && z[i + 1] <=
'7') {
3919 c = (c << 3) + z[i] -
'0';
3932 static int booleanValue(
const char * zArg)
3934 int val = atoi(zArg);
3935 if (!strcasecmp(zArg,
"on") || !strcasecmp(zArg,
"yes"))
3937 SQLDBG((stderr,
"<-- %s(%s) val %d\n", __FUNCTION__, zArg, val));
3942 static const char *modeDescr[] = {
3955 static int rpmsqlInput(
rpmsql sql);
3957 static int rpmsqlFOpen(
const char * fn,
FD_t *fdp)
3963 SQLDBG((stderr,
"--> %s(%s,%p) fd %p\n", __FUNCTION__, fn, fdp, fd));
3972 fd =
fdDup(STDOUT_FILENO);
3973 else if (!
strcmp(fn,
"stderr"))
3974 fd =
fdDup(STDERR_FILENO);
3975 else if (!
strcmp(fn,
"off"))
3978 fd =
Fopen(fn,
"wb");
3980 rpmsql_error(1,
_(
"cannot open \"%s\""), fn);
3988 SQLDBG((stderr,
"<-- %s(%s,%p) fd %p rc %d\n", __FUNCTION__, fn, fdp, fd, rc));
3999 static int rpmsqlMetaCommand(
rpmsql sql,
char *zLine)
4001 sqlite3 * db = (sqlite3 *)sql->I;
4008 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, zLine));
4011 while (zLine[i] && nArg < ArraySize(azArg)) {
4012 while (
xisspace((
unsigned char) zLine[i]))
4014 if (zLine[i] ==
'\0')
4016 if (zLine[i] ==
'\'' || zLine[i] ==
'"') {
4017 int delim = zLine[i++];
4018 azArg[nArg++] = &zLine[
i];
4019 while (zLine[i] && zLine[i] != delim)
4021 if (zLine[i] == delim)
4024 resolve_backslashes(azArg[nArg - 1]);
4026 azArg[nArg++] = &zLine[
i];
4027 while (zLine[i] && !
xisspace((
unsigned char) zLine[i]))
4031 resolve_backslashes(azArg[nArg - 1]);
4038 n = strlen30(azArg[0]);
4040 if (c ==
'b' && n >= 3 && !strncmp(azArg[0],
"backup", n)
4041 && nArg > 1 && nArg < 4) {
4042 const char *zDestFile;
4045 sqlite3_backup *pBackup;
4047 zDestFile = azArg[1];
4050 zDestFile = azArg[2];
4054 sqlite3_open(zDestFile, &pDest));
4057 rpmsql_error(1,
_(
"cannot open \"%s\""), zDestFile);
4060 sqlite3_close(pDest));
4064 db = (sqlite3 *)sql->I;
4065 pBackup = sqlite3_backup_init(pDest,
"main", db, zDb);
4066 if (pBackup ==
NULL) {
4067 rpmsql_error(1,
"%s", sqlite3_errmsg(pDest));
4069 sqlite3_close(pDest));
4072 while ((rc =
rpmsqlCmd(sql,
"backup_step", db,
4073 sqlite3_backup_step(pBackup, 100))) == SQLITE_OK)
4076 sqlite3_backup_finish(pBackup));
4077 if (rc == SQLITE_DONE) {
4080 rpmsql_error(1,
"%s", sqlite3_errmsg(pDest));
4084 sqlite3_close(pDest));
4086 if (c ==
'b' && n >= 3 && !strncmp(azArg[0],
"bail", n)
4087 && nArg > 1 && nArg < 3) {
4088 if (booleanValue(azArg[1]))
4089 sql->flags |= RPMSQL_FLAGS_BAIL;
4091 sql->flags &= ~RPMSQL_FLAGS_BAIL;
4093 if (c ==
'd' && n > 1 && !strncmp(azArg[0],
"databases", n) && nArg == 1) {
4095 uint32_t _flags = sql->flags;
4096 uint32_t _mode = sql->mode;
4097 int _cnt = sql->cnt;;
4099 char *zErrMsg =
NULL;
4100 memcpy(_colWidth, sql->colWidth,
sizeof(_colWidth));
4102 db = (sqlite3 *)sql->I;
4103 sql->flags |= RPMSQL_FLAGS_SHOWHDR;
4104 sql->mode = RPMSQL_MODE_COLUMN;
4105 sql->colWidth[0] = 3;
4106 sql->colWidth[1] = 15;
4107 sql->colWidth[2] = 58;
4110 sqlite3_exec(db,
"PRAGMA database_list;", callback, sql, &zErrMsg));
4112 rpmsql_error(1,
"%s", zErrMsg);
4113 sqlite3_free(zErrMsg);
4116 memcpy(sql->colWidth, _colWidth,
sizeof(_colWidth));
4119 sql->flags = _flags;
4121 if (c ==
'd' && !strncmp(azArg[0],
"dump", n) && nArg < 3) {
4124 db = (sqlite3 *)sql->I;
4128 rpmsqlFprintf(sql,
"PRAGMA foreign_keys=OFF;\n");
4129 rpmsqlFprintf(sql,
"BEGIN TRANSACTION;\n");
4130 sql->flags &= ~RPMSQL_FLAGS_WRITABLE;
4132 sqlite3_exec(db,
"PRAGMA writable_schema=ON", 0, 0, 0));
4134 t =
rpmExpand(
"SELECT name, type, sql FROM sqlite_master"
4135 " WHERE sql NOT NULL AND type=='table'"
4136 " AND name!='sqlite_sequence'",
NULL);
4137 run_schema_dump_query(sql, t,
NULL);
4139 t =
rpmExpand(
"SELECT name, type, sql FROM sqlite_master"
4140 " WHERE name=='sqlite_sequence'",
NULL);
4141 run_schema_dump_query(sql, t,
NULL);
4143 t =
rpmExpand(
"SELECT sql FROM sqlite_master"
4144 " WHERE sql NOT NULL AND type IN ('index','trigger','view')",
NULL);
4145 run_table_dump_query(sql, db, t,
NULL);
4149 for (i = 1; i < nArg; i++) {
4150 t =
rpmExpand(
"SELECT name, type, sql FROM sqlite_master"
4151 " WHERE tbl_name LIKE '", azArg[i],
"'"
4152 " AND type=='table' AND sql NOT NULL",
NULL);
4153 run_schema_dump_query(sql, t,
NULL);
4155 t =
rpmExpand(
"SELECT sql FROM sqlite_master"
4156 " WHERE sql NOT NULL"
4157 " AND type IN ('index','trigger','view')"
4158 " AND tbl_name LIKE '", azArg[i],
"'",
NULL);
4159 run_table_dump_query(sql, db, t,
NULL);
4164 rpmsqlFprintf(sql,
"PRAGMA writable_schema=OFF;\n");
4165 sql->flags &= ~RPMSQL_FLAGS_WRITABLE;
4168 sqlite3_exec(db,
"PRAGMA writable_schema=OFF", 0, 0, 0));
4169 rpmsqlFprintf(sql,
"COMMIT;\n");
4171 if (c ==
'e' && !strncmp(azArg[0],
"echo", n) && nArg > 1 && nArg < 3) {
4172 if (booleanValue(azArg[1]))
4173 sql->flags |= RPMSQL_FLAGS_ECHO;
4175 sql->flags &= ~RPMSQL_FLAGS_ECHO;
4177 if (c ==
'e' && !strncmp(azArg[0],
"exit", n) && nArg == 1) {
4180 if (c ==
'e' && !strncmp(azArg[0],
"explain", n) && nArg < 3) {
4181 int val = nArg >= 2 ? booleanValue(azArg[1]) : 1;
4183 if (!sql->explainPrev.valid) {
4184 sql->explainPrev.valid = 1;
4185 sql->explainPrev.mode = sql->mode;
4186 sql->explainPrev.flags = sql->flags;
4187 memcpy(sql->explainPrev.colWidth, sql->colWidth,
4188 sizeof(sql->colWidth));
4197 sql->mode = RPMSQL_MODE_EXPLAIN;
4198 sql->flags |= RPMSQL_FLAGS_SHOWHDR;
4199 memset(sql->colWidth, 0, ArraySize(sql->colWidth));
4200 sql->colWidth[0] = 4;
4201 sql->colWidth[1] = 13;
4202 sql->colWidth[2] = 4;
4203 sql->colWidth[3] = 4;
4204 sql->colWidth[4] = 4;
4205 sql->colWidth[5] = 13;
4206 sql->colWidth[6] = 2;
4207 sql->colWidth[7] = 13;
4208 }
else if (sql->explainPrev.valid) {
4209 sql->explainPrev.valid = 0;
4210 sql->mode = sql->explainPrev.mode;
4211 sql->flags = sql->explainPrev.flags;
4212 memcpy(sql->colWidth, sql->explainPrev.colWidth,
4213 sizeof(sql->colWidth));
4217 && (!strncmp(azArg[0],
"header", n) || !strncmp(azArg[0],
"headers", n))
4218 && nArg > 1 && nArg < 3)
4220 if (booleanValue(azArg[1]))
4221 sql->flags |= RPMSQL_FLAGS_SHOWHDR;
4223 sql->flags &= ~RPMSQL_FLAGS_SHOWHDR;
4225 if (c ==
'h' && !strncmp(azArg[0],
"help", n)) {
4226 rpmsql_error(0,
"%s", zHelp);
4228 rpmsql_error(0,
"%s", zTimerHelp);
4230 if (c ==
'i' && !strncmp(azArg[0],
"import", n) && nArg == 3) {
4231 char *zTable = azArg[2];
4232 char *zFile = azArg[1];
4233 sqlite3_stmt * pStmt =
NULL;
4245 db = (sqlite3 *)sql->I;
4246 nSep = strlen30(sql->separator);
4248 rpmsql_error(1,
_(
"non-null separator required for import"));
4251 zSql = sqlite3_mprintf(
"SELECT * FROM '%q'", zTable);
4253 nByte = strlen30(zSql);
4255 sqlite3_prepare(db, zSql, -1, &pStmt, 0));
4259 sqlite3 * db = (sqlite3 *)sql->I;
4260 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4264 sqlite3_finalize(pStmt));
4267 nCol = sqlite3_column_count(pStmt);
4269 sqlite3_finalize(pStmt));
4273 zSql =
xmalloc(nByte + 20 + nCol * 2);
4274 sqlite3_snprintf(nByte + 20, zSql,
"INSERT INTO '%q' VALUES(?",
4277 for (i = 1; i < nCol; i++) {
4284 sqlite3_prepare(db, zSql, -1, &pStmt, 0));
4288 sqlite3 * db = (sqlite3 *)sql->I;
4289 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4293 sqlite3_finalize(pStmt));
4297 sql->ifd =
Fopen(zFile,
"rb.fpio");
4299 rpmsql_error(1,
_(
"cannot open \"%s\""), zFile);
4301 sqlite3_finalize(pStmt));
4308 sql->buf =
xmalloc(sql->nbuf);
4309 azCol = malloc(
sizeof(azCol[0]) * (nCol + 1));
4310 if (azCol ==
NULL) {
4314 sqlite3_finalize(pStmt));
4318 sqlite3_exec(db,
"BEGIN", 0, 0, 0));
4320 while ((zLine = local_getline(sql,
NULL)) !=
NULL) {
4325 for (i = 0, z = zLine; *z && *z !=
'\n' && *z !=
'\r'; z++) {
4326 if (*z == sql->separator[0] && !strncmp(z, sql->separator, nSep)) {
4330 azCol[
i] = &z[nSep];
4336 if (i + 1 != nCol) {
4338 _(
"%s line %d: expected %d columns of data but found %d"),
4339 zFile, lineno, nCol, i + 1);
4340 zCommit =
"ROLLBACK";
4344 for (i = 0; i < nCol; i++)
4346 sqlite3_bind_text(pStmt, i + 1, azCol[i], -1, SQLITE_STATIC));
4348 sqlite3_step(pStmt));
4350 sqlite3_reset(pStmt));
4353 sqlite3 * db = (sqlite3 *)sql->I;
4354 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4356 zCommit =
"ROLLBACK";
4361 azCol =
_free(azCol);
4364 sql->buf =
_free(sql->buf);
4367 sqlite3_finalize(pStmt));
4369 sqlite3_exec(db, zCommit, 0, 0, 0));
4371 if (c ==
'i' && !strncmp(azArg[0],
"indices", n) && nArg < 3) {
4373 uint32_t _flags = sql->flags;
4374 uint32_t _mode = sql->mode;
4376 char *zErrMsg =
NULL;
4378 db = (sqlite3 *)sql->I;
4379 sql->flags &= ~RPMSQL_FLAGS_SHOWHDR;
4380 sql->mode = RPMSQL_MODE_LIST;
4382 t =
rpmExpand(
"SELECT name FROM sqlite_master"
4383 " WHERE type='index' AND name NOT LIKE 'sqlite_%'"
4385 "SELECT name FROM sqlite_temp_master"
4386 " WHERE type='index'"
4387 " ORDER BY 1",
NULL);
4389 sqlite3_exec(db, t, callback, sql, &zErrMsg));
4392 t =
rpmExpand(
"SELECT name FROM sqlite_master"
4393 " WHERE type='index' AND tbl_name LIKE '", azArg[1],
"'",
4395 "SELECT name FROM sqlite_temp_master"
4396 " WHERE type='index' AND tbl_name LIKE '", azArg[1],
"'",
4397 " ORDER BY 1",
NULL);
4399 sqlite3_exec(db, t, callback, sql, &zErrMsg));
4403 rpmsql_error(1,
"%s", zErrMsg);
4404 sqlite3_free(zErrMsg);
4408 rpmsql_error(1,
_(
"querying sqlite_master and sqlite_temp_master"));
4413 sql->flags = _flags;
4416 #ifdef SQLITE_ENABLE_IOTRACE
4417 if (c ==
'i' && !strncmp(azArg[0],
"iotrace", n)) {
4418 extern void (*sqlite3IoTrace) (
const char *, ...);
4419 rc = rpmsqlFOpen((nArg >= 2 ? azArg[1] :
NULL), &sql->tfd);
4420 sqlite3IoTrace = (sql->tfd ? iotracePrintf :
NULL);
4424 if (c ==
'l' && !strncmp(azArg[0],
"load", n) && nArg >= 2) {
4425 const char *zFile, *zProc;
4428 zProc = nArg >= 3 ? azArg[2] : 0;
4431 db = (sqlite3 *)sql->I;
4432 rc =
rpmsqlCmd(sql,
"load_extension", db,
4433 sqlite3_load_extension(db, zFile, zProc, &zErrMsg));
4435 rpmsql_error(1,
"%s", zErrMsg);
4436 sqlite3_free(zErrMsg);
4442 if (c ==
'l' && !strncmp(azArg[0],
"log", n) && nArg >= 1) {
4444 (
void) rpmsqlFOpen((nArg >= 2 ? azArg[1] :
NULL), &sql->lfd);
4446 if (c ==
'm' && !strncmp(azArg[0],
"mode", n) && nArg == 2) {
4447 int n2 = strlen30(azArg[1]);
4448 if ((n2 == 4 && !strncmp(azArg[1],
"line", n2))
4449 || (n2 == 5 && !strncmp(azArg[1],
"lines", n2))) {
4450 sql->mode = RPMSQL_MODE_LINE;
4451 }
else if ((n2 == 6 && !strncmp(azArg[1],
"column", n2))
4452 || (n2 == 7 && !strncmp(azArg[1],
"columns", n2))) {
4453 sql->mode = RPMSQL_MODE_COLUMN;
4454 }
else if (n2 == 4 && !strncmp(azArg[1],
"list", n2)) {
4455 sql->mode = RPMSQL_MODE_LIST;
4456 }
else if (n2 == 4 && !strncmp(azArg[1],
"html", n2)) {
4457 sql->mode = RPMSQL_MODE_HTML;
4458 }
else if (n2 == 3 && !strncmp(azArg[1],
"tcl", n2)) {
4459 sql->mode = RPMSQL_MODE_TCL;
4460 }
else if (n2 == 3 && !strncmp(azArg[1],
"csv", n2)) {
4461 sql->mode = RPMSQL_MODE_CSV;
4463 }
else if (n2 == 4 && !strncmp(azArg[1],
"tabs", n2)) {
4464 sql->mode = RPMSQL_MODE_LIST;
4466 }
else if (n2 == 6 && !strncmp(azArg[1],
"insert", n2)) {
4467 sql->mode = RPMSQL_MODE_INSERT;
4468 set_table_name(sql,
"table");
4470 rpmsql_error(1,
_(
"mode should be one of: %s"),
4471 "column csv html insert line list tabs tcl");
4475 if (c ==
'm' && !strncmp(azArg[0],
"mode", n) && nArg == 3) {
4476 int n2 = strlen30(azArg[1]);
4477 if (n2 == 6 && !strncmp(azArg[1],
"insert", n2)) {
4478 sql->mode = RPMSQL_MODE_INSERT;
4479 set_table_name(sql, azArg[2]);
4481 rpmsql_error(1,
_(
"invalid arguments: "
4482 " \"%s\". Enter \".help\" for help"), azArg[2]);
4486 if (c ==
'n' && !strncmp(azArg[0],
"nullvalue", n) && nArg == 2) {
4487 (
void)
stpncpy(sql->nullvalue, azArg[1],
sizeof(sql->nullvalue)-1);
4489 if (c ==
'o' && !strncmp(azArg[0],
"output", n) && nArg == 2) {
4490 rc = rpmsqlFOpen((nArg >= 2 ? azArg[1] :
NULL), &sql->ofd);
4493 sql->outfile =
_free(sql->outfile);
4495 sql->outfile =
xstrdup(azArg[1]);
4497 sql->ofd =
fdDup(STDOUT_FILENO);
4498 sql->outfile =
xstrdup(
"stdout");
4501 if (c ==
'p' && !strncmp(azArg[0],
"prompt", n)
4502 && (nArg == 2 || nArg == 3)) {
4504 sql->zPrompt =
_free(sql->zPrompt);
4505 sql->zPrompt =
xstrdup(azArg[1]);
4508 sql->zContinue =
_free(sql->zContinue);
4509 sql->zContinue =
xstrdup(azArg[2]);
4512 if (c ==
'q' && !strncmp(azArg[0],
"quit", n) && nArg == 1) {
4515 if (c ==
'r' && n >= 3 && !strncmp(azArg[0],
"read", n)
4517 FD_t _ifd = sql->ifd;
4518 sql->ifd =
Fopen(azArg[1],
"rb.fpio");
4520 rpmsql_error(1,
_(
"cannot open \"%s\""), azArg[1]);
4524 rc = rpmsqlInput(sql);
4529 if (c ==
'r' && n >= 3 && !strncmp(azArg[0],
"restore", n)
4530 && nArg > 1 && nArg < 4) {
4531 const char *zSrcFile;
4534 sqlite3_backup *pBackup;
4538 zSrcFile = azArg[1];
4541 zSrcFile = azArg[2];
4545 sqlite3_open(zSrcFile, &pSrc));
4548 rpmsql_error(1,
_(
"cannot open \"%s\""), zSrcFile);
4551 sqlite3_close(pSrc));
4555 db = (sqlite3 *)sql->I;
4556 pBackup = sqlite3_backup_init(db, zDb, pSrc,
"main");
4558 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4560 sqlite3_close(pSrc));
4563 while ((rc = sqlite3_backup_step(pBackup, 100)) == SQLITE_OK
4564 || rc == SQLITE_BUSY)
4566 if (rc == SQLITE_BUSY) {
4567 if (nTimeout++ >= 3)
4572 sqlite3_backup_finish(pBackup);
4579 rpmsql_error(1,
_(
"source database is busy"));
4583 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4588 sqlite3_close(pSrc));
4590 if (c ==
's' && !strncmp(azArg[0],
"schema", n) && nArg < 3) {
4592 uint32_t _flags = sql->flags;
4593 uint32_t _mode = sql->mode;
4596 db = (sqlite3 *)sql->I;
4597 sql->flags &= ~RPMSQL_FLAGS_SHOWHDR;
4598 sql->mode = RPMSQL_MODE_SEMI;
4601 for (i = 0; azArg[1][
i]; i++)
4602 azArg[1][i] = (
char) tolower(azArg[1][i]);
4603 if (!
strcmp(azArg[1],
"sqlite_master")) {
4604 char *new_argv[2], *new_colv[2];
4605 new_argv[0] =
"CREATE TABLE sqlite_master (\n"
4609 " rootpage integer,\n" " sql text\n" ")";
4611 new_colv[0] =
"sql";
4613 callback(sql, 1, new_argv, new_colv);
4615 }
else if (!
strcmp(azArg[1],
"sqlite_temp_master")) {
4616 char *new_argv[2], *new_colv[2];
4617 new_argv[0] =
"CREATE TEMP TABLE sqlite_temp_master (\n"
4621 " rootpage integer,\n" " sql text\n" ")";
4623 new_colv[0] =
"sql";
4625 callback(sql, 1, new_argv, new_colv);
4630 " (SELECT sql sql, type type, tbl_name tbl_name, name name"
4631 " FROM sqlite_master UNION ALL"
4632 " SELECT sql, type, tbl_name, name FROM sqlite_temp_master)"
4633 " WHERE tbl_name LIKE '", azArg[1],
"'"
4634 " AND type!='meta' AND sql NOTNULL "
4635 "ORDER BY substr(type,2,1), name",
NULL);
4637 sqlite3_exec(db, t, callback, sql, &zErrMsg));
4641 sql->flags = _flags;
4646 " (SELECT sql sql, type type, tbl_name tbl_name, name name"
4647 " FROM sqlite_master UNION ALL"
4648 " SELECT sql, type, tbl_name, name FROM sqlite_temp_master) "
4649 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'"
4650 "ORDER BY substr(type,2,1), name",
4651 callback, sql, &zErrMsg));
4654 rpmsql_error(1,
"%s", zErrMsg);
4655 sqlite3_free(zErrMsg);
4657 }
else if (rc != SQLITE_OK) {
4658 rpmsql_error(1,
_(
"querying schema information"));
4664 if (c ==
's' && !strncmp(azArg[0],
"separator", n) && nArg == 2) {
4665 (
void)
stpncpy(sql->separator, azArg[1],
sizeof(sql->separator)-1);
4667 if (c ==
's' && !strncmp(azArg[0],
"show", n) && nArg == 1) {
4669 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"echo",
F_ISSET(sql, ECHO) ?
"on" :
"off");
4670 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"explain",
4671 sql->explainPrev.valid ?
"on" :
"off");
4672 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"headers",
4673 F_ISSET(sql, SHOWHDR) ?
"on" :
"off");
4674 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"mode", modeDescr[sql->mode]);
4675 rpmsqlFprintf(sql,
"%9.9s: ",
"nullvalue");
4676 output_c_string(sql, sql->nullvalue);
4677 rpmsqlFprintf(sql,
"\n");
4678 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"output",
4679 (sql->outfile ? sql->outfile :
"stdout"));
4680 rpmsqlFprintf(sql,
"%9.9s: ",
"separator");
4681 output_c_string(sql, sql->separator);
4682 rpmsqlFprintf(sql,
"\n");
4683 rpmsqlFprintf(sql,
"%9.9s: ",
"width");
4685 i < (
int) ArraySize(sql->colWidth) && sql->colWidth[
i] != 0;
4688 rpmsqlFprintf(sql,
"%d ", sql->colWidth[i]);
4690 rpmsqlFprintf(sql,
"\n");
4692 if (c ==
't' && n > 1 && !strncmp(azArg[0],
"tables", n) && nArg < 3) {
4697 db = (sqlite3 *)sql->I;
4700 sqlite3_get_table(db,
4701 "SELECT name FROM sqlite_master "
4702 "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%' "
4704 "SELECT name FROM sqlite_temp_master "
4705 "WHERE type IN ('table','view') "
4707 &azResult, &nRow, 0, &zErrMsg));
4710 t =
rpmExpand(
"SELECT name FROM sqlite_master "
4711 " WHERE type IN ('table','view') AND name LIKE '", azArg[1],
"'"
4713 "SELECT name FROM sqlite_temp_master"
4714 " WHERE type IN ('table','view') AND name LIKE '", azArg[1],
"'"
4715 "ORDER BY 1",
NULL);
4717 sqlite3_get_table(db, t, &azResult, &nRow, 0,&zErrMsg));
4721 rpmsql_error(1,
"%s", zErrMsg);
4722 sqlite3_free(zErrMsg);
4725 rpmsql_error(1,
_(
"querying sqlite_master and sqlite_temp_master"));
4728 int len, maxlen = 0;
4730 int nPrintCol, nPrintRow;
4731 for (i = 1; i <= nRow; i++) {
4732 if (azResult[i] == 0)
4734 len = strlen30(azResult[i]);
4738 nPrintCol = 80 / (maxlen + 2);
4741 nPrintRow = (nRow + nPrintCol - 1) / nPrintCol;
4742 for (i = 0; i < nPrintRow; i++) {
4743 for (j = i + 1; j <= nRow; j += nPrintRow) {
4744 char *zSp = j <= nPrintRow ?
"" :
" ";
4745 rpmsqlFprintf(sql,
"%s%-*s", zSp, maxlen,
4746 azResult[j] ? azResult[j] :
"");
4748 rpmsqlFprintf(sql,
"\n");
4751 sqlite3_free_table(azResult);
4753 if (c ==
't' && n > 4 && !strncmp(azArg[0],
"timeout", n) && nArg == 2) {
4755 db = (sqlite3 *)sql->I;
4756 (
void)
rpmsqlCmd(sql,
"busy_timeout", db,
4757 sqlite3_busy_timeout(db, atoi(azArg[1])));
4759 if (HAS_TIMER && c ==
't' && n >= 5
4760 && !strncmp(azArg[0],
"timer", n) && nArg == 2) {
4761 sql->enableTimer = booleanValue(azArg[1]);
4763 if (c ==
'w' && !strncmp(azArg[0],
"width", n) && nArg > 1) {
4765 assert(nArg <= ArraySize(azArg));
4766 for (j = 1; j < nArg && j < ArraySize(sql->colWidth); j++)
4767 sql->colWidth[j - 1] = atoi(azArg[j]);
4770 rpmsql_error(1,
_(
"unknown command or invalid arguments: "
4771 " \"%s\". Enter \".help\" for help"), azArg[0]);
4782 #if defined(WITH_SQLITE)
4788 static int _contains_semicolon(
const char *z,
int N)
4792 for (i = 0; i <
N; i++) {
4798 SQLDBG((stderr,
"<-- %s(%s) rc %d\n", __FUNCTION__, z, rc));
4805 static int _all_whitespace(
const char *z)
4810 if (
xisspace(*(
unsigned char *) z))
4812 if (*z ==
'/' && z[1] ==
'*') {
4814 while (*z && (*z !=
'*' || z[1] !=
'/'))
4823 if (*z ==
'-' && z[1] ==
'-') {
4825 while (*z && *z !=
'\n')
4835 SQLDBG((stderr,
"<-- %s(%s) rc %d\n", __FUNCTION__, z, rc));
4844 static int _is_command_terminator(
const char *zLine)
4848 while (
xisspace(*(
unsigned char *) zLine))
4850 if (zLine[0] ==
'/' && _all_whitespace(&zLine[1]))
4853 && _all_whitespace(&zLine[2]))
4857 SQLDBG((stderr,
"<-- %s(%s) rc %d\n", __FUNCTION__, zLine, rc));
4865 static int _is_complete(
char *zSql,
int nSql)
4871 zSql[nSql + 1] =
'\0';
4872 rc = sqlite3_complete(zSql);
4875 SQLDBG((stderr,
"<-- %s(%s) rc %d\n", __FUNCTION__, zSql, rc));
4889 static int rpmsqlInput(
rpmsql sql)
4891 sqlite3 * db = (sqlite3 *) sql->I;
4902 char * _buf = sql->buf;
4903 size_t _nbuf = sql->nbuf;
4905 SQLDBG((stderr,
"--> %s(%p)\n", __FUNCTION__, sql));
4910 sql->buf =
xmalloc(sql->nbuf);
4912 while (errCnt == 0 || !
F_ISSET(sql, BAIL) ||
F_ISSET(sql, PROMPT))
4914 if (sql->ofd)
Fflush(sql->ofd);
4915 zLine = rpmsqlInputOneLine(sql, zSql);
4924 if ((zSql ==
NULL || zSql[0] ==
'\0') && _all_whitespace(zLine))
4926 if (zLine && zLine[0] ==
'.' && nSql == 0) {
4928 rpmsqlFprintf(sql,
"%s\n", zLine);
4929 rc = rpmsqlMetaCommand(sql, zLine);
4936 if (_is_command_terminator(zLine) && _is_complete(zSql, nSql))
4937 memcpy(zLine,
";", 2);
4941 for (i = 0; zLine[
i] &&
xisspace((
unsigned char) zLine[i]); i++)
4943 if (zLine[i] !=
'\0') {
4944 nSql = strlen30(zLine);
4946 memcpy(zSql, zLine, nSql + 1);
4950 int len = strlen30(zLine);
4951 zSql =
xrealloc(zSql, nSql + len + 4);
4952 zSql[nSql++] =
'\n';
4953 memcpy(&zSql[nSql], zLine, len + 1);
4956 if (zSql && _contains_semicolon(&zSql[nSqlPrior], nSql - nSqlPrior)
4957 && sqlite3_complete(zSql)) {
4960 db = (sqlite3 *)sql->I;
4962 rc = _rpmsqlShellExec(sql, zSql, _rpmsqlShellCallback, &zErrMsg);
4964 if (rc || zErrMsg) {
4968 "near line %d: ", startline);
4971 rpmsql_error(1,
"%s%s", zPrefix,
4972 zErrMsg ? zErrMsg : sqlite3_errmsg(db));
4973 zErrMsg =
_free(zErrMsg);
4981 if (!_all_whitespace(zSql))
4982 rpmsql_error(1,
_(
"incomplete SQL: %s"), zSql);
4986 sql->buf =
_free(sql->buf);
4990 SQLDBG((stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, sql, errCnt));
5002 static int rpmsqlInitRC(
rpmsql sql,
const char *sqliterc)
5006 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, sqliterc));
5010 if (sqliterc ==
NULL)
5011 sqliterc = sql->zInitrc;
5013 FD_t _ifd = sql->ifd;
5014 sql->ifd =
Fopen(sqliterc,
"rb.fpio");
5015 if (!(sql->ifd ==
NULL ||
Ferror(sql->ifd))) {
5016 if (
F_ISSET(sql, INTERACTIVE))
5017 rpmsql_error(0,
"-- Loading resources from %s", sqliterc);
5018 rc = rpmsqlInput(sql);
5024 SQLDBG((stderr,
"<-- %s(%p,%s) rc %d\n", __FUNCTION__, sql, sqliterc, rc));
5033 #if defined(WITH_SQLITE)
5038 enum poptCallbackReason reason,
5039 const struct poptOption *opt,
5047 if (opt->arg ==
NULL)
5051 (
void)
stpncpy(sql->separator, arg,
sizeof(sql->separator)-1);
5055 (
void)
stpncpy(sql->nullvalue, arg,
sizeof(sql->nullvalue)-1);
5058 printf(
"%s\n", sqlite3_libversion());
5063 rpmsql_error(0,
_(
"%s: Unknown callback(0x%x)\n"),
5064 __FUNCTION__, (
unsigned) opt->val);
5065 poptPrintUsage(con, stderr, 0);
5072 static struct poptOption _rpmsqlOptions[] = {
5075 POPT_ARG_CALLBACK | POPT_CBFLAG_INC_DATA | POPT_CBFLAG_CONTINUE,
5076 rpmsqlArgCallback, 0,
NULL, NULL},
5079 {
"debug",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH|POPT_ARGFLAG_DOC_HIDDEN, &
_rpmsql_debug, -1,
5080 N_(
"Debug embedded SQL interpreter"),
NULL},
5081 {
"create",
'\0', POPT_BIT_SET|POPT_ARGFLAG_ONEDASH|POPT_ARGFLAG_DOC_HIDDEN, &_sql.flags, RPMSQL_FLAGS_CREATE,
5082 N_(
"create database if not exists"),
NULL},
5084 {
"init",
'\0', POPT_ARG_STRING|POPT_ARGFLAG_ONEDASH, &_sql.zInitFile, 0,
5085 N_(
"read/process named FILE"),
N_(
"FILE") },
5086 {
"echo",
'\0', POPT_BIT_SET|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_ECHO,
5087 N_(
"print commands before execution"),
NULL },
5089 {
"load",
'\0', POPT_BIT_SET|
POPT_ARGFLAG_TOGGLE|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_NOLOAD,
5090 N_(
"disable extension loading (normally enabled)"),
NULL },
5091 {
"header",
'\0', POPT_BIT_SET|
POPT_ARGFLAG_TOGGLE|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_SHOWHDR,
5092 N_(
"turn headers on or off"),
NULL },
5094 {
"bail",
'\0', POPT_BIT_SET|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_BAIL,
5095 N_(
"stop after hitting an error"),
NULL },
5097 {
"interactive",
'\0', POPT_BIT_SET|
POPT_ARGFLAG_TOGGLE|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_INTERACTIVE,
5098 N_(
"force interactive I/O"),
NULL },
5099 {
"batch",
'\0', POPT_BIT_CLR|
POPT_ARGFLAG_TOGGLE|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_INTERACTIVE,
5100 N_(
"force batch I/O"),
NULL },
5102 {
"column",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_COLUMN,
5103 N_(
"set output mode to 'column'"),
NULL },
5104 {
"csv",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_CSV,
5105 N_(
"set output mode to 'csv'"),
NULL },
5106 {
"html",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_HTML,
5107 N_(
"set output mode to HTML"),
NULL },
5108 {
"line",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_LINE,
5109 N_(
"set output mode to 'line'"),
NULL },
5110 {
"list",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_LIST,
5111 N_(
"set output mode to 'list'"),
NULL },
5112 {
"separator",
'\0', POPT_ARG_STRING|POPT_ARGFLAG_ONEDASH, 0,
'S',
5113 N_(
"set output field separator (|)"),
N_(
"CHAR") },
5114 {
"nullvalue",
'\0', POPT_ARG_STRING|POPT_ARGFLAG_ONEDASH, 0,
'N',
5115 N_(
"set text string for NULL values"),
N_(
"TEXT") },
5117 {
"version",
'\0', POPT_ARG_NONE|POPT_ARGFLAG_ONEDASH, 0,
'V',
5118 N_(
"show SQLite version"),
NULL},
5122 N_(
"Common options for all rpmio executables:"),
NULL},
5126 {
NULL, (char) -1, POPT_ARG_INCLUDE_TABLE,
NULL, 0,
5128 Usage: dbsql [OPTIONS] FILENAME [SQL]\n\
5129 FILENAME is the name of an SQLite database. A new database is created\n\
5130 if the file does not previously exist.\n\
5133 -help show this message\n\
5134 -init filename read/process named file\n\
5135 -echo print commands before execution\n\
5136 -[no]header turn headers on or off\n\
5137 -bail stop after hitting an error\n\
5138 -interactive force interactive I/O\n\
5139 -batch force batch I/O\n\
5140 -column set output mode to 'column'\n\
5141 -csv set output mode to 'csv'\n\
5142 -html set output mode to HTML\n\
5143 -line set output mode to 'line'\n\
5144 -list set output mode to 'list'\n\
5145 -separator 'x' set output field separator (|)\n\
5146 -nullvalue 'text' set text string for NULL values\n\
5147 -version show SQLite version\n\
5166 SQLDBG((stderr,
"==> %s(%p)\n", __FUNCTION__, sql));
5168 sql->zDestTable =
_free(sql->zDestTable);
5183 sql->buf =
_free(sql->buf);
5184 sql->buf = sql->b =
NULL;
5185 sql->nbuf = sql->nb = 0;
5188 sql->zHome =
_free(sql->zHome);
5189 sql->zInitrc =
_free(sql->zInitrc);
5190 sql->zHistory =
_free(sql->zHistory);
5191 sql->zPrompt =
_free(sql->zPrompt);
5192 sql->zContinue =
_free(sql->zContinue);
5194 sql->outfile =
_free(sql->outfile);
5196 sql->zDbFilename =
_free(sql->zDbFilename);
5197 sql->zInitFile =
_free(sql->zInitFile);
5199 #if defined(WITH_SQLITE)
5201 sqlite3 * db = (sqlite3 *)sql->I;
5220 if (_rpmsqlPool ==
NULL) {
5226 memset(((
char *)sql)+
sizeof(sql->_item), 0,
sizeof(*sql)-
sizeof(sql->_item));
5232 const char ** av = sql->av;
5239 #if defined(WITH_SQLITE)
5244 static void rpmsqlInitPopt(
rpmsql sql,
int ac,
char ** av, poptOption tbl)
5253 con = poptGetContext(av[0], ac, (
const char **)av, tbl, 0);
5256 while ((rc = poptGetNextOpt(con)) > 0) {
5257 const char * arg = poptGetOptArg(con);
5262 rpmsql_error(0,
_(
"%s: option table misconfigured (%d)\n"),
5269 SQLDBG((stderr,
"%s: poptGetNextOpt rc(%d): %s\n", __FUNCTION__, rc, poptStrerror(rc)));
5272 sql->flags = _sql.flags;
5273 sql->mode = _sql.mode;
5274 if (_sql.zInitFile) {
5275 sql->zInitFile =
_free(sql->zInitFile);
5276 sql->zInitFile = _sql.zInitFile;
5277 _sql.zInitFile =
NULL;
5279 memcpy(sql->separator, _sql.separator,
sizeof(sql->separator));
5280 memcpy(sql->nullvalue, _sql.nullvalue,
sizeof(sql->nullvalue));
5285 con = poptFreeContext(con);
5289 if (sql->separator[0] ==
'\0')
5290 switch (sql->mode) {
5292 case RPMSQL_MODE_LIST: (
void)
stpcpy(sql->separator,
"|");
break;
5293 case RPMSQL_MODE_CSV: (
void)
stpcpy(sql->separator,
",");
break;
5296 SQLDBG((stderr,
"<== %s(%p, %p[%u], %p)\n", __FUNCTION__, sql, av, (
unsigned)ac, tbl));
5303 (flags & 0x80000000) ?
rpmsqlI() :
5307 SQLDBG((stderr,
"==> %s(%p[%u], 0x%x)\n", __FUNCTION__, av, (
unsigned)ac, flags));
5313 #if defined(WITH_SQLITE)
5316 static int _oneshot;
5317 sqlite3 * db =
NULL;
5321 #if defined(SQLITE_CONFIG_LOG)
5322 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, sql);
5324 sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
5329 memset(&_sql, 0,
sizeof(_sql));
5330 sql->flags = _sql.flags =
flags;
5331 sql->mode = _sql.mode = RPMSQL_MODE_LIST;
5333 rpmsqlInitPopt(sql, ac, av, (poptOption) _rpmsqlOptions);
5336 if (sql->av && sql->av[0]) {
5337 sql->zDbFilename =
xstrdup(sql->av[0]);
5341 sqlite3_open(sql->zDbFilename, &db));
5342 sql->I = (
void *) db;
5345 sql->zDbFilename =
xstrdup(
":memory:");
5348 if (sql->zInitFile ||
F_ISSET(sql, INTERACTIVE)) {
5349 sql->ofd =
fdDup(STDOUT_FILENO);
5350 xx = rpmsqlInitRC(sql, sql->zInitFile);
5353 rpmsqlInitPopt(sql, ac, av, (poptOption) _rpmsqlOptions);
5359 static const char _zInitrc[] =
"/.sqliterc";
5360 static const char _zHistory[] =
"/.sqlite_history";
5362 sql->zHome =
_free(sql->zHome);
5363 {
char * t =
getenv(
"HOME");
5364 sql->zHome =
xstrdup((t ? t :
"/"));
5366 sql->zInitrc =
_free(sql->zInitrc);
5368 sql->zHistory =
_free(sql->zHistory);
5375 if (sql->zPrompt ==
NULL) {
5376 char * t =
xstrdup((av && av[0] ? av[0] :
"sql"));
5377 char * bn = basename(t);
5378 sql->zPrompt =
_free(sql->zPrompt);
5381 sql->zContinue =
_free(sql->zContinue);
5382 sql->zContinue = t =
xstrdup(sql->zPrompt);
5383 while (*t && *t !=
'>')
5393 if (
F_ISSET(sql, INTERACTIVE)) {
5394 if (sql->ofd ==
NULL)
5395 sql->ofd =
fdDup(STDOUT_FILENO);
5397 if (sql->iob ==
NULL)
5408 SQLDBG((stderr,
"==> %s(%p,%p[%u]) \"%s\"\n", __FUNCTION__, sql, str, (
unsigned)(str ? strlen(str) : 0), str));
5409 SQLDBG((stderr,
"==========>\n%s\n<==========\n", str));
5413 #if defined(WITH_SQLITE)
5415 const char * s = str;
5424 uint32_t _flags = sql->flags;
5425 FD_t _ofd = sql->ofd;
5426 FD_t _ifd = sql->ifd;
5428 SQLDBG((stderr,
"*** %s: INTERACTIVE\n", __FUNCTION__));
5429 sql->flags |= RPMSQL_FLAGS_INTERACTIVE;
5430 if (sql->ofd ==
NULL)
5431 sql->ofd =
fdDup(STDOUT_FILENO);
5434 extern char *db_full_version(
int *,
int *,
int *,
int *,
int *);
5436 "Enter \".help\" for instructions\n"
5437 "Enter SQL statements terminated with a \";\"\n",
5443 "SQLite version ", sqlite3_libversion(),
"\n",
5444 #
if SQLITE_VERSION_NUMBER > 3006015
5445 "\t(", sqlite3_sourceid(),
")\n",
5447 "Enter \".help\" for instructions\n",
5448 "Enter SQL statements terminated with a \";\"\n",
NULL);
5450 nw =
Fwrite(t, 1, nb, sql->ofd);
5454 #if defined(HAVE_READLINE) && HAVE_READLINE==1
5461 sql->ifd =
Fdopen(
fdDup(fileno(stdin)),
"rb.fpio");
5464 sql->flags |= RPMSQL_FLAGS_PROMPT;
5465 rc = rpmsqlInput(sql);
5466 sql->flags &= ~RPMSQL_FLAGS_PROMPT;
5471 if (sql->zHistory) {
5478 sql->
flags = _flags;
5482 FD_t _ofd = sql->ofd;
5483 SQLDBG((stderr,
"*** %s: STDIN\n", __FUNCTION__));
5485 if (sql->ofd ==
NULL) sql->ofd =
fdDup(STDOUT_FILENO);
5489 sql->ifd =
Fdopen(
fdDup(fileno(stdin)),
"rb.fpio");
5492 rc = rpmsqlInput(sql);
5503 FD_t _ifd = sql->ifd;
5504 SQLDBG((stderr,
"*** %s: FILE\n", __FUNCTION__));
5505 sql->ifd =
Fopen(s,
"rb.fpio");
5506 if (!(sql->ifd ==
NULL ||
Ferror(sql->ifd))) {
5507 rc = rpmsqlInput(sql);
5513 SQLDBG((stderr,
"*** %s: STRING\n", __FUNCTION__));
5516 rc = rpmsqlMetaCommand(sql, t);
5520 char * zErrMsg =
NULL;
5522 db = (sqlite3 *)sql->I;
5523 rc = _rpmsqlShellExec(sql, s, _rpmsqlShellCallback, &zErrMsg);
5525 rpmsql_error(1,
"%s", zErrMsg);
5526 zErrMsg =
_free(zErrMsg);
5528 }
else if (rc != 0) {
5529 rpmsql_error(1,
_(
"unable to process SQL \"%s\""), s);
5538 SQLDBG((stderr,
"==========>\n%s\n<==========\n",
rpmiobStr(sql->iob)));
5546 SQLDBG((stderr,
"<== %s(%p,%p[%u]) rc %d\n", __FUNCTION__, sql, str, (
unsigned)(str ? strlen(str) : 0), rc));
rpmiob rpmiobRTrim(rpmiob iob)
Trim trailing white space.
int mireSetEOptions(miRE mire, int *offsets, int noffsets)
Initialize pattern execute options (PCRE only).
miRE mireNew(rpmMireMode mode, int tag)
Create pattern container.
char * getenv(const char *name)
static PyObject *int type
static int xtoupper(int c)
static int xisalnum(int c)
size_t Fwrite(const void *buf, size_t size, size_t nmemb, FD_t fd)
fwrite(3) clone.
char * xstrdup(const char *str)
size_t rpmiobLen(rpmiob iob)
Return I/O buffer len.
#define rpmsqlDebugDump(_sql)
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
char * rpmGetPath(const char *path,...)
Return (malloc'ed) expanded, canonicalized, file path.
static char *size_t nb
fgets(3) analogue that reads \ continuations.
int Access(const char *path, int amode)
access(2) clone.
int mireRegcomp(miRE mire, const char *pattern)
Compile pattern match.
int mireSetCOptions(miRE mire, rpmMireMode mode, int tag, int options, const unsigned char *table)
Initialize pattern compile options.
int argvAppend(ARGV_t *argvp, ARGV_t av)
Append one argv array to another.
int rpmsqlCmd(rpmsql sql, const char *msg, void *_db, int rc)
Check sqlite3 return code, displaying error messages.
static rpmsql rpmsqlI(void)
Return the global interpreter, creating laziliy if needed.
int Fflush(FD_t fd)
fflush(3) clone.
rpmsql rpmsqlLink(rpmsql sql)
Reference a sql interpreter instance.
rpmiob rpmiobFree(rpmiob iob)
Destroy a I/O buffer instance.
static int xisalpha(int c)
rpmiob rpmiobAppend(rpmiob iob, const char *s, size_t nl)
Append string to I/O buffer.
static rpmsql rpmsqlGetPool(rpmioPool pool)
int rpmiobSlurp(const char *fn, rpmiob *iobp)
rpmsql rpmsqlNew(char **av, uint32_t flags)
Create and load a sql interpreter.
static int xtolower(int c)
enum rpmRC_e rpmRC
RPM return codes.
memset(_r, 0, sizeof(*_r))
int rpmGlob(const char *patterns, int *argcPtr, const char ***argvPtr)
Return URL path(s) from a (URL prefixed) pattern glob.
miRE mireFree(miRE mire)
Free pattern container.
void * xcalloc(size_t nmemb, size_t size)
assert(key->size==sizeof(hdrNum))
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
static void rpmsqlFini(void *_sql)
rpmsql pool destructor.
fprintf(stderr,"--> %s(%p,%p,%p) sig %p sigp %p\n", __FUNCTION__, dig, t, rsactx, sig, sigp)
rpmvt rpmvtNew(void *db, void *pModule, const char *const *argv, rpmvd vd)
volatile int _rpmsqlSeenInterrupt
int argvCount(const ARGV_t argv)
Return no.
char * stpncpy(char *dest, const char *src, size_t n)
int Lstat(const char *path, struct stat *st)
lstat(2) clone.
#define POPT_ARGFLAG_TOGGLE
#define VTDBGNOISY(_vt, _l)
static int xisspace(int c)
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
int Glob_pattern_p(const char *pattern, int quote)
glob_pattern_p(3) clone.
The FD_t File Handle data structure.
int argvAdd(ARGV_t *argvp, ARGstr_t val)
Add a string to an argv array.
int mireRegexec(miRE mire, const char *val, size_t vallen)
Execute pattern match.
#define VCDBGNOISY(_vc, _l)
char * rpmExpand(const char *arg,...)
Return (malloc'ed) concatenated macro expansion(s).
#define stifle_history(X)
static rpmvt rpmvtGetPool(rpmioPool pool)
#define F_ISSET(_psm, _FLAG)
static void _rpmsqlDebugDump(rpmsql sql, const char *_func, const char *_fn, unsigned _ln)
int Fclose(FD_t fd)
fclose(3) clone.
rpmiob rpmiobNew(size_t len)
Create an I/O buffer.
void argvPrint(const char *msg, ARGV_t argv, FILE *fp)
Print argv array elements.
static const char *char c
Return text between pl and matching pr characters.
static void rpmvtFini(void *_VT)
rpmvt pool destructor.
int Ferror(FD_t fd)
ferror(3) clone.
char * rpmiobStr(rpmiob iob)
Return I/O buffer (as string).
return strcmp(ame->name, bme->name)
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
static int snprintf(char *buf, int nb, const char *fmt,...)
static void rpmvcFini(void *_VC)
rpmvc pool destructor.
static const char * prefix[]
Tables for prefixing and suffixing patterns, according to the -w, -x, and -F options.
static int vsnprintf(char *buf, int nb, const char *fmt, va_list ap)
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
char * stpcpy(char *dest, const char *src)
rpmvc rpmvcNew(rpmvt vt, int nrows)
FD_t Fdopen(FD_t ofd, const char *fmode)
rpmRC rpmsqlRun(rpmsql sql, const char *str, const char **resultp)
Execute sql from STRING | FILE | STDIN | INTERACTIVE.
int argvSplit(ARGV_t *argvp, const char *str, const char *seps)
Split a string into an argv array.
static int xisblank(int c)
int Fileno(FD_t fd)
fileno(3) clone.
static void
Print copy of spec file, filling in Group/Description/Summary from specspo.
char * buf
Parse (and execute) macro undefinition.
int
Save source and expand field into target.
struct poptOption rpmioAllPoptTable[]
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
static rpmvc rpmvcGetPool(rpmioPool pool)
const char ** rpmsqlArgv(rpmsql sql, int *argcp)
Return arguments from a sql interpreter.