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) {
116 char * parse =
rpmExpand(vd->parse, NULL);
118 xx =
argvSplit(&vt->fields, parse, vd->split);
121 parse =
_free(parse);
130 VTDBG(vt, (stderr,
"\tdbpath: %s\n", vd->dbpath));
131 VTDBG(vt, (stderr,
"\tprefix: %s\n", vd->prefix));
132 VTDBG(vt, (stderr,
"\t split: %s\n", vd->split));
133 VTDBG(vt, (stderr,
"\t parse: %s\n", vd->parse));
134 VTDBG(vt, (stderr,
"\t regex: %s\n", vd->regex));
141 #if defined(WITH_SQLITE)
143 typedef struct key_s {
148 {
"blob", SQLITE_BLOB },
149 {
"float", SQLITE_FLOAT },
150 {
"int", SQLITE_INTEGER },
151 {
"integer",SQLITE_INTEGER },
152 {
"null", SQLITE_NULL },
153 {
"text", SQLITE_TEXT },
157 static const char *
hasSqlType(
const char * s)
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++) {
211 int fx = (vd->fx == 3 ? 3 : 4);
213 av = (
const char **) (vt->argc > fx ? &vt->argv[fx] : vt->fields);
216 u[strlen(u)-2] =
' ';
219 #define dbN vt->argv[1]
220 #define tblN vt->argv[2]
228 VTDBG(vt, (stderr,
"%s\n", hu));
234 sqlite3 *
db = (sqlite3 *) vt->db;
237 static const char * hidden[] = {
"path HIDDEN",
"id HIDDEN", NULL };
243 const char * fn = NULL;
248 VTDBG(vt, (stderr,
"--> %s(%p,%p)\n", __FUNCTION__, vt, vtp));
255 sqlite3_declare_vtab(
db, hu));
260 static char _quotes[] =
"'\"";
261 int quoted = (strchr(_quotes, *vt->argv[3]) != NULL);
263 const char * path = NULL;
265 (void)
urlPath(vt->argv[3]+quoted, &path);
266 prefix = (*path !=
'/' && vd->prefix ? vd->prefix :
"");
268 uri[strlen(uri)-quoted] =
'\0';
272 (void)
urlPath(uri, (
const char **) &fn);
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] ==
'/') {
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,
".."))
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);
722 offsets = memset(
alloca(nb), -1, nb);
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]));
740 if (!strcmp(col,
"path"))
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])) {
751 const char * fn =
rpmGetPath(path,
"/", col, NULL);
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);
822 fprintf(stderr,
"\t av: %p[%u]\n", sql->av, (
unsigned)
argvCount(sql->av));
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
873 rpmsql_error(
int lvl,
const char *fmt, ...)
879 (void) fprintf(stderr,
"Error: ");
881 (void) vfprintf(stderr, fmt, ap);
883 (void) fprintf(stderr,
"\n");
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)
993 static int rpmsqlFprintf(
rpmsql sql,
const char *fmt, ...)
994 #if defined(__GNUC__) && __GNUC__ >= 2
998 static int rpmsqlFprintf(
rpmsql sql,
const char *fmt, ...)
1001 size_t nb =
sizeof(
b);
1005 if (sql == NULL) sql =
rpmsqlI();
1013 if (!(rc >= 0 && rc < (
int)nb))
1019 size_t nw =
Fwrite(b, 1, rc, sql->ofd);
1020 assert((
int)nw == rc);
1034 #ifdef SQLITE_ENABLE_IOTRACE
1035 static void iotracePrintf(
const char *zFormat, ...)
1044 va_start(ap, zFormat);
1045 z = sqlite3_vmprintf(zFormat, ap);
1048 nw =
Fwrite(z, 1, nz, sql->tfd);
1054 #if defined(SQLITE_CONFIG_LOG)
1059 static void shellLog(
void *_sql,
int iErrCode,
const char *zMsg)
1062 if (sql && sql->lfd) {
1064 int xx =
snprintf(num,
sizeof(num),
"(%d) ", iErrCode);
1065 const char * t =
rpmExpand(num, zMsg,
"\n", NULL);
1066 size_t nt = strlen(t);
1067 size_t nw =
Fwrite(t, 1, nt, sql->lfd);
1081 #define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){}
1082 #define sqliteCharVal(X) sqlite3ReadUtf8(X)
1084 #define sqliteNextChar(X) while( ( *++(X)) ) break
1085 #define sqliteCharVal(X) (int)(*(X))
1104 #define GEN_MATH_WRAP_DOUBLE_1(name, function, domain) \
1105 static void name(sqlite3_context *context, int argc, sqlite3_value **argv) {\
1108 switch (sqlite3_value_type(argv[0])) {\
1110 sqlite3_result_null(context);\
1113 rVal = sqlite3_value_double(argv[0]);\
1115 sqlite3_result_error(context, "domain error", -1);\
1117 sqlite3_result_double(context, function(rVal));\
1127 GEN_MATH_WRAP_DOUBLE_1(sqrtFunc, sqrt, rVal < 0)
1130 GEN_MATH_WRAP_DOUBLE_1(acosFunc, acos, rVal < -1.0 || rVal > 1.0)
1131 GEN_MATH_WRAP_DOUBLE_1(asinFunc, asin, rVal < -1.0 || rVal > 1.0)
1132 GEN_MATH_WRAP_DOUBLE_1(atanFunc, atan, 0)
1140 static double acosh(
double x)
1142 return log(x + sqrt(x * x - 1.0));
1146 GEN_MATH_WRAP_DOUBLE_1(acoshFunc, acosh, rVal < 1)
1148 static double asinh(
double x)
1150 return log(x + sqrt(x * x + 1.0));
1154 GEN_MATH_WRAP_DOUBLE_1(asinhFunc, asinh, 0)
1156 static double atanh(
double x)
1158 return (1.0 / 2.0) * log((1 + x) / (1 - x));
1162 GEN_MATH_WRAP_DOUBLE_1(atanhFunc, atanh, rVal > 1.0 || rVal < -1.0)
1167 static
double cot(
double x)
1169 return 1.0 / tan(x);
1172 GEN_MATH_WRAP_DOUBLE_1(sinFunc, sin, 0)
1173 GEN_MATH_WRAP_DOUBLE_1(cosFunc, cos, 0)
1174 GEN_MATH_WRAP_DOUBLE_1(tanFunc, tan, 0)
1175 GEN_MATH_WRAP_DOUBLE_1(cotFunc, cot, 0)
1177 static
double coth(
double x)
1179 return 1.0 / tanh(x);
1187 static double sinh(
double x)
1189 return (exp(x) - exp(-x)) / 2.0;
1192 GEN_MATH_WRAP_DOUBLE_1(sinhFunc, sinh, 0)
1195 static double cosh(
double x)
1197 return (exp(x) + exp(-x)) / 2.0;
1200 GEN_MATH_WRAP_DOUBLE_1(coshFunc, cosh, 0)
1203 static double tanh(
double x)
1205 return sinh(x) / cosh(x);
1208 GEN_MATH_WRAP_DOUBLE_1(tanhFunc, tanh, 0)
1209 GEN_MATH_WRAP_DOUBLE_1(cothFunc, coth, 0)
1215 static double log10(
double x)
1217 static double l10 = -1.0;
1221 return log(x) / l10;
1224 GEN_MATH_WRAP_DOUBLE_1(logFunc, log, rVal <= 0.0)
1225 GEN_MATH_WRAP_DOUBLE_1(log10Func, log10, rVal <= 0.0)
1226 GEN_MATH_WRAP_DOUBLE_1(expFunc, exp, 0)
1236 #define M_PI 3.14159265358979323846
1244 static double deg2rad(
double x)
1246 return x * M_PI / 180.0;
1254 static double rad2deg(
double x)
1256 return 180.0 * x / M_PI;
1258 GEN_MATH_WRAP_DOUBLE_1(rad2degFunc, rad2deg, 0)
1259 GEN_MATH_WRAP_DOUBLE_1(deg2radFunc, deg2rad, 0)
1267 static
void piFunc(sqlite3_context * context,
1268 int argc, sqlite3_value ** argv)
1270 sqlite3_result_double(context, M_PI);
1281 static void squareFunc(sqlite3_context * context,
1282 int argc, sqlite3_value ** argv)
1288 switch (sqlite3_value_type(argv[0])) {
1289 case SQLITE_INTEGER:
1290 iVal = sqlite3_value_int64(argv[0]);
1291 sqlite3_result_int64(context, iVal * iVal);
1294 sqlite3_result_null(context);
1297 rVal = sqlite3_value_double(argv[0]);
1298 sqlite3_result_double(context, rVal * rVal);
1311 static void powerFunc(sqlite3_context * context,
1312 int argc, sqlite3_value ** argv)
1319 if (sqlite3_value_type(argv[0]) == SQLITE_NULL
1320 || sqlite3_value_type(argv[1]) == SQLITE_NULL) {
1321 sqlite3_result_null(context);
1323 r1 = sqlite3_value_double(argv[0]);
1324 r2 = sqlite3_value_double(argv[1]);
1327 sqlite3_result_error(context,
"domain error", -1);
1329 sqlite3_result_double(context, pow(r1, r2));
1340 static void atn2Func(sqlite3_context * context,
1341 int argc, sqlite3_value ** argv)
1348 if (sqlite3_value_type(argv[0]) == SQLITE_NULL
1349 || sqlite3_value_type(argv[1]) == SQLITE_NULL) {
1350 sqlite3_result_null(context);
1352 r1 = sqlite3_value_double(argv[0]);
1353 r2 = sqlite3_value_double(argv[1]);
1354 sqlite3_result_double(context, atan2(r1, r2));
1367 static void signFunc(sqlite3_context * context,
1368 int argc, sqlite3_value ** argv)
1374 switch (sqlite3_value_type(argv[0])) {
1375 case SQLITE_INTEGER:
1376 iVal = sqlite3_value_int64(argv[0]);
1377 iVal = (iVal > 0) ? 1 : (iVal < 0) ? -1 : 0;
1378 sqlite3_result_int64(context, iVal);
1381 sqlite3_result_null(context);
1386 rVal = sqlite3_value_double(argv[0]);
1387 rVal = (rVal > 0) ? 1 : (rVal < 0) ? -1 : 0;
1388 sqlite3_result_double(context, rVal);
1399 static void ceilFunc(sqlite3_context * context,
1400 int argc, sqlite3_value ** argv)
1406 switch (sqlite3_value_type(argv[0])) {
1407 case SQLITE_INTEGER:
1408 iVal = sqlite3_value_int64(argv[0]);
1409 sqlite3_result_int64(context, iVal);
1412 sqlite3_result_null(context);
1415 rVal = sqlite3_value_double(argv[0]);
1416 sqlite3_result_int64(context, ceil(rVal));
1427 static void floorFunc(sqlite3_context * context,
1428 int argc, sqlite3_value ** argv)
1434 switch (sqlite3_value_type(argv[0])) {
1435 case SQLITE_INTEGER:
1436 iVal = sqlite3_value_int64(argv[0]);
1437 sqlite3_result_int64(context, iVal);
1440 sqlite3_result_null(context);
1443 rVal = sqlite3_value_double(argv[0]);
1444 sqlite3_result_int64(context, floor(rVal));
1456 static void replicateFunc(sqlite3_context * context,
1457 int argc, sqlite3_value ** argv)
1466 if (argc != 2 || SQLITE_NULL == sqlite3_value_type(argv[0]))
1469 iCount = sqlite3_value_int64(argv[1]);
1472 sqlite3_result_error(context,
"domain error", -1);
1474 nLen = sqlite3_value_bytes(argv[0]);
1475 nTLen = nLen * iCount;
1478 strcpy((
char *) zo, (
char *) sqlite3_value_text(argv[0]));
1480 for (i = 0; i < iCount; ++
i)
1481 strcpy((
char *) (z + i * nLen), (
char *) zo);
1483 sqlite3_result_text(context, (
char *) z, -1, free);
1488 static void properFunc(sqlite3_context * context,
1489 int argc, sqlite3_value ** argv)
1491 const unsigned char *z;
1498 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1499 sqlite3_result_null(context);
1503 z = sqlite3_value_text(argv[0]);
1504 zo = (
unsigned char *)
xstrdup((
const char *)z);
1507 while ((r = *(z++)) != 0) {
1518 sqlite3_result_text(context, (
char *) zo, -1, free);
1531 static void padlFunc(sqlite3_context * context,
1532 int argc, sqlite3_value ** argv)
1542 if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
1543 sqlite3_result_null(context);
1545 zi = (
const char *) sqlite3_value_text(argv[0]);
1546 ilen = sqlite3_value_int64(argv[1]);
1549 sqlite3_result_error(context,
"domain error", -1);
1552 zl = sqlite3utf8CharLen(zi, -1);
1555 sqlite3_result_text(context,
xstrdup(zi), -1, free);
1557 zo =
xmalloc(strlen(zi) + ilen - zl + 1);
1559 for (i = 1; i + zl <= ilen; ++
i)
1563 sqlite3_result_text(context, zo, -1, free);
1577 static void padrFunc(sqlite3_context * context,
1578 int argc, sqlite3_value ** argv)
1589 if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
1590 sqlite3_result_null(context);
1593 zi = (
const char *) sqlite3_value_text(argv[0]);
1594 _ilen = sqlite3_value_int64(argv[1]);
1597 sqlite3_result_error(context,
"domain error", -1);
1601 zl = sqlite3utf8CharLen(zi, -1);
1604 sqlite3_result_text(context,
xstrdup(zi), -1, free);
1607 zo =
xmalloc(zll + ilen - zl + 1);
1608 zt = strcpy(zo, zi) + zll;
1609 for (i = 1; i + zl <= ilen; ++
i)
1612 sqlite3_result_text(context, zo, -1, free);
1627 static void padcFunc(sqlite3_context * context,
1628 int argc, sqlite3_value ** argv)
1639 if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
1640 sqlite3_result_null(context);
1643 zi = (
const char *) sqlite3_value_text(argv[0]);
1644 _ilen = sqlite3_value_int64(argv[1]);
1647 sqlite3_result_error(context,
"domain error", -1);
1651 zl = sqlite3utf8CharLen(zi, -1);
1654 sqlite3_result_text(context,
xstrdup(zi), -1, free);
1657 zo =
xmalloc(zll + ilen - zl + 1);
1659 for (i = 1; 2 * i + zl <= ilen; ++
i)
1663 for (; i + zl <= ilen; ++
i)
1666 sqlite3_result_text(context, zo, -1, free);
1679 static void strfilterFunc(sqlite3_context * context,
1680 int argc, sqlite3_value ** argv)
1694 if (sqlite3_value_type(argv[0]) == SQLITE_NULL
1695 || sqlite3_value_type(argv[1]) == SQLITE_NULL) {
1696 sqlite3_result_null(context);
1698 zi1 = (
const char *) sqlite3_value_text(argv[0]);
1699 zi2 = (
const char *) sqlite3_value_text(argv[1]);
1700 zo =
xmalloc(strlen(zi1) + 1);
1703 while ((c1 = sqliteCharVal(z1)) != 0) {
1705 while ((c2 = sqliteCharVal(z21)) != 0 && c2 != c1)
1706 sqliteNextChar(z21);
1709 sqliteNextChar(z22);
1710 strncpy(zot, z21, z22 - z21);
1717 sqlite3_result_text(context, zo, -1, free);
1733 static int _substr(
const char *z1,
const char *z2,
int s,
const char **p)
1745 while ((sqliteCharVal(z2) != 0) && (c++) < s)
1749 while ((sqliteCharVal(z2)) != 0) {
1754 c1 = sqliteCharVal(zt1);
1755 c2 = sqliteCharVal(zt2);
1756 sqliteNextChar(zt1);
1757 sqliteNextChar(zt2);
1758 }
while (c1 == c2 && c1 != 0 && c2 != 0);
1770 return rVal >= 0 ? rVal + s : rVal;
1783 static void charindexFunc(sqlite3_context * context,
1784 int argc, sqlite3_value ** argv)
1791 assert(argc == 2 || argc == 3);
1792 if (SQLITE_NULL == sqlite3_value_type(argv[0])
1793 || SQLITE_NULL == sqlite3_value_type(argv[1])) {
1794 sqlite3_result_null(context);
1798 z1 = (
const char *) sqlite3_value_text(argv[0]);
1799 z2 = (
const char *) sqlite3_value_text(argv[1]);
1801 s = sqlite3_value_int(argv[2]) - 1;
1808 rVal = _substr(z1, z2, s, NULL);
1809 sqlite3_result_int(context, rVal + 1);
1819 static void leftFunc(sqlite3_context * context,
1820 int argc, sqlite3_value ** argv)
1825 const unsigned char *z;
1826 const unsigned char *zt;
1830 if (SQLITE_NULL == sqlite3_value_type(argv[0])
1831 || SQLITE_NULL == sqlite3_value_type(argv[1])) {
1832 sqlite3_result_null(context);
1836 z = sqlite3_value_text(argv[0]);
1837 l = sqlite3_value_int(argv[1]);
1840 while (sqliteCharVal(zt) && c++ < l)
1846 strncpy((
char *) rz, (
char *) z, zt - z);
1848 sqlite3_result_text(context, (
char *) rz, -1, free);
1858 static void rightFunc(sqlite3_context * context,
1859 int argc, sqlite3_value ** argv)
1870 if (SQLITE_NULL == sqlite3_value_type(argv[0])
1871 || SQLITE_NULL == sqlite3_value_type(argv[1])) {
1872 sqlite3_result_null(context);
1876 z = (
const char *) sqlite3_value_text(argv[0]);
1877 l = sqlite3_value_int(argv[1]);
1880 while (sqliteCharVal(zt) != 0) {
1897 strcpy((
char *) rz, (
char *) (zt));
1898 sqlite3_result_text(context, (
char *) rz, -1, free);
1906 static const char * ltrim(
const char *s)
1919 static const char * rtrim(
char *s)
1921 char *ss = s + strlen(s) - 1;
1922 while (ss >= s && *ss ==
' ')
1934 static void ltrimFunc(sqlite3_context * context,
1935 int argc, sqlite3_value ** argv)
1940 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1941 sqlite3_result_null(context);
1944 z = (
const char *) sqlite3_value_text(argv[0]);
1945 sqlite3_result_text(context,
xstrdup(ltrim(z)), -1, free);
1954 static void rtrimFunc(sqlite3_context * context,
1955 int argc, sqlite3_value ** argv)
1960 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1961 sqlite3_result_null(context);
1964 z = (
const char *) sqlite3_value_text(argv[0]);
1965 sqlite3_result_text(context, rtrim(
xstrdup(z)), -1, free);
1974 static void trimFunc(sqlite3_context * context,
1975 int argc, sqlite3_value ** argv)
1980 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
1981 sqlite3_result_null(context);
1984 z = (
const char *) sqlite3_value_text(argv[0]);
1985 sqlite3_result_text(context, rtrim(
xstrdup(ltrim(z))), -1, free);
1998 static void _append(
char **s1,
int l1,
const char *s2,
int l2)
2000 *s1 =
xrealloc(*s1, (l1 + l2 + 1) *
sizeof(
char));
2001 strncpy((*s1) + l1, s2, l2);
2002 *(*(s1) + l1 + l2) =
'\0';
2011 static void replaceFunc(sqlite3_context * context,
2012 int argc, sqlite3_value ** argv)
2027 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
2028 sqlite3_result_null(context);
2032 z1 = (
const char *)sqlite3_value_text(argv[0]);
2033 z2 = (
const char *)sqlite3_value_text(argv[1]);
2034 z3 = (
const char *)sqlite3_value_text(argv[2]);
2048 sqlite3_result_text(context,
xstrdup(z1), -1, free);
2057 ret = _substr(z2, zt1, 0, &zt2);
2062 _append(&zo, lzo, zt1, zt2 - zt1);
2064 _append(&zo, lzo, z3, lz3);
2069 _append(&zo, lzo, zt1, lz1 - (zt1 - z1));
2070 sqlite3_result_text(context, zo, -1, free);
2079 static void reverseFunc(sqlite3_context * context,
2080 int argc, sqlite3_value ** argv)
2090 if (SQLITE_NULL == sqlite3_value_type(argv[0])) {
2091 sqlite3_result_null(context);
2094 z = (
const char *)sqlite3_value_text(argv[0]);
2101 while (sqliteCharVal(zt) != 0) {
2104 for (i = 1; zt - i >= z; ++
i)
2105 *(rzt--) = *(zt -
i);
2108 sqlite3_result_text(context, rz, -1, free);
2118 typedef struct StdevCtx StdevCtx;
2133 typedef struct ModeCtx ModeCtx;
2152 static void varianceStep(sqlite3_context * context,
2153 int argc, sqlite3_value ** argv)
2160 p = sqlite3_aggregate_context(context,
sizeof(*p));
2162 if (SQLITE_NULL != sqlite3_value_numeric_type(argv[0])) {
2164 x = sqlite3_value_double(argv[0]);
2165 delta = (x - p->rM);
2166 p->rM += delta / p->cnt;
2167 p->rS += delta * (x - p->rM);
2177 static void modeStep(sqlite3_context * context,
2178 int argc, sqlite3_value ** argv)
2188 type = sqlite3_value_numeric_type(argv[0]);
2190 if (type == SQLITE_NULL)
2193 p = sqlite3_aggregate_context(context,
sizeof(*p));
2196 p->m = calloc(1,
sizeof(map));
2197 if (type == SQLITE_INTEGER) {
2199 *(p->m) = map_make(int_cmp);
2204 *(p->m) = map_make(double_cmp);
2210 if (0 == p->is_double) {
2211 xi = sqlite3_value_int64(argv[0]);
2212 iptr = (int64_t *) calloc(1,
sizeof(int64_t));
2214 map_insert(p->m, iptr);
2216 xd = sqlite3_value_double(argv[0]);
2217 dptr = (
double *) calloc(1,
sizeof(
double));
2219 map_insert(p->m, dptr);
2230 static void modeIterate(
void *e, int64_t c,
void *pp)
2234 ModeCtx *p = (ModeCtx *) pp;
2236 if (0 == p->is_double) {
2241 }
else if (p->mcnt < c) {
2247 ed = *(
double *) (e);
2251 }
else if (p->mcnt < c) {
2267 static void medianIterate(
void *e, int64_t c,
void *pp)
2275 ModeCtx *p = (ModeCtx *) pp;
2281 iR = p->cnt - p->pcnt;
2283 ir = p->cnt - p->mcnt;
2288 if (0 == p->is_double) {
2292 ed = *(
double *) (e);
2306 static void modeFinalize(sqlite3_context * context)
2308 ModeCtx *p = sqlite3_aggregate_context(context, 0);
2310 map_iterate(p->m, modeIterate, p);
2315 if (0 == p->is_double)
2316 sqlite3_result_int64(context, p->riM);
2318 sqlite3_result_double(context, p->rdM);
2327 static void _medianFinalize(sqlite3_context * context)
2329 ModeCtx *p = (ModeCtx *) sqlite3_aggregate_context(context, 0);
2332 map_iterate(p->m, medianIterate, p);
2336 if (0 == p->is_double)
2338 sqlite3_result_int64(context, p->riM);
2340 sqlite3_result_double(context, p->riM * 1.0 / p->mn);
2342 sqlite3_result_double(context, p->rdM / p->mn);
2350 static void medianFinalize(sqlite3_context * context)
2352 ModeCtx *p = (ModeCtx *) sqlite3_aggregate_context(context, 0);
2354 p->pcnt = (p->cnt) / 2.0;
2355 _medianFinalize(context);
2363 static void lower_quartileFinalize(sqlite3_context * context)
2365 ModeCtx *p = (ModeCtx *) sqlite3_aggregate_context(context, 0);
2367 p->pcnt = (p->cnt) / 4.0;
2368 _medianFinalize(context);
2376 static void upper_quartileFinalize(sqlite3_context * context)
2378 ModeCtx *p = (ModeCtx *) sqlite3_aggregate_context(context, 0);
2380 p->pcnt = (p->cnt) * 3 / 4.0;
2381 _medianFinalize(context);
2389 static void stdevFinalize(sqlite3_context * context)
2391 StdevCtx *p = sqlite3_aggregate_context(context, 0);
2392 if (p && p->cnt > 1)
2393 sqlite3_result_double(context, sqrt(p->rS / (p->cnt - 1)));
2395 sqlite3_result_double(context, 0.0);
2402 static void varianceFinalize(sqlite3_context * context)
2404 StdevCtx *p = sqlite3_aggregate_context(context, 0);
2405 if (p && p->cnt > 1)
2406 sqlite3_result_double(context, p->rS / (p->cnt - 1));
2408 sqlite3_result_double(context, 0.0);
2418 static void expandFunc(sqlite3_context * context,
2419 int argc, sqlite3_value ** argv)
2421 sqlite3_result_text(context,
2422 rpmExpand((
const char *)sqlite3_value_text(argv[0]), NULL), -1, free);
2431 static void regexpFunc(sqlite3_context* context,
2432 int argc, sqlite3_value** argv)
2434 const char * value = (
const char *) sqlite3_value_text(argv[0]);
2435 const char *
pattern = (
const char *) sqlite3_value_text(argv[1]);
2443 sqlite3_result_int(context, rc);
2446 sqlite3_result_error(context,
"invalid pattern", -1);
2452 static struct rpmsqlCF_s __CF[] = {
2454 {
"acos", 1, 0, SQLITE_UTF8, 0, acosFunc, NULL, NULL },
2455 {
"asin", 1, 0, SQLITE_UTF8, 0, asinFunc, NULL, NULL },
2456 {
"atan", 1, 0, SQLITE_UTF8, 0, atanFunc, NULL, NULL },
2457 {
"atn2", 2, 0, SQLITE_UTF8, 0, atn2Func, NULL, NULL },
2459 {
"atan2", 2, 0, SQLITE_UTF8, 0, atn2Func, NULL, NULL },
2460 {
"acosh", 1, 0, SQLITE_UTF8, 0, acoshFunc, NULL, NULL },
2461 {
"asinh", 1, 0, SQLITE_UTF8, 0, asinhFunc, NULL, NULL },
2462 {
"atanh", 1, 0, SQLITE_UTF8, 0, atanhFunc, NULL, NULL },
2465 {
"difference", 2, 0, SQLITE_UTF8, 0, differenceFunc, NULL, NULL },
2467 {
"degrees", 1, 0, SQLITE_UTF8, 0, rad2degFunc, NULL, NULL },
2468 {
"radians", 1, 0, SQLITE_UTF8, 0, deg2radFunc, NULL, NULL },
2470 {
"cos", 1, 0, SQLITE_UTF8, 0, cosFunc, NULL, NULL },
2471 {
"sin", 1, 0, SQLITE_UTF8, 0, sinFunc, NULL, NULL },
2472 {
"tan", 1, 0, SQLITE_UTF8, 0, tanFunc, NULL, NULL },
2473 {
"cot", 1, 0, SQLITE_UTF8, 0, cotFunc, NULL, NULL },
2474 {
"cosh", 1, 0, SQLITE_UTF8, 0, coshFunc, NULL, NULL },
2475 {
"sinh", 1, 0, SQLITE_UTF8, 0, sinhFunc, NULL, NULL },
2476 {
"tanh", 1, 0, SQLITE_UTF8, 0, tanhFunc, NULL, NULL },
2477 {
"coth", 1, 0, SQLITE_UTF8, 0, cothFunc, NULL, NULL },
2479 {
"exp", 1, 0, SQLITE_UTF8, 0, expFunc, NULL, NULL },
2480 {
"log", 1, 0, SQLITE_UTF8, 0, logFunc, NULL, NULL },
2481 {
"log10", 1, 0, SQLITE_UTF8, 0, log10Func, NULL, NULL },
2482 {
"power", 2, 0, SQLITE_UTF8, 0, powerFunc, NULL, NULL },
2483 {
"sign", 1, 0, SQLITE_UTF8, 0, signFunc, NULL, NULL },
2484 {
"sqrt", 1, 0, SQLITE_UTF8, 0, sqrtFunc, NULL, NULL },
2485 {
"square", 1, 0, SQLITE_UTF8, 0, squareFunc, NULL, NULL },
2487 {
"ceil", 1, 0, SQLITE_UTF8, 0, ceilFunc, NULL, NULL },
2488 {
"floor", 1, 0, SQLITE_UTF8, 0, floorFunc, NULL, NULL },
2490 {
"pi", 0, 0, SQLITE_UTF8, 1, piFunc, NULL, NULL },
2493 {
"replicate", 2, 0, SQLITE_UTF8, 0, replicateFunc, NULL, NULL },
2494 {
"charindex", 2, 0, SQLITE_UTF8, 0, charindexFunc, NULL, NULL },
2495 {
"charindex", 3, 0, SQLITE_UTF8, 0, charindexFunc, NULL, NULL },
2496 {
"leftstr", 2, 0, SQLITE_UTF8, 0, leftFunc, NULL, NULL },
2497 {
"rightstr", 2, 0, SQLITE_UTF8, 0, rightFunc, NULL, NULL },
2498 {
"ltrim", 1, 0, SQLITE_UTF8, 0, ltrimFunc, NULL, NULL },
2499 {
"rtrim", 1, 0, SQLITE_UTF8, 0, rtrimFunc, NULL, NULL },
2500 {
"trim", 1, 0, SQLITE_UTF8, 0, trimFunc, NULL, NULL },
2501 {
"replace", 3, 0, SQLITE_UTF8, 0, replaceFunc, NULL, NULL },
2502 {
"reverse", 1, 0, SQLITE_UTF8, 0, reverseFunc, NULL, NULL },
2503 {
"proper", 1, 0, SQLITE_UTF8, 0, properFunc, NULL, NULL },
2505 {
"padl", 2, 0, SQLITE_UTF8, 0, padlFunc, NULL, NULL },
2506 {
"padr", 2, 0, SQLITE_UTF8, 0, padrFunc, NULL, NULL },
2507 {
"padc", 2, 0, SQLITE_UTF8, 0, padcFunc, NULL, NULL },
2509 {
"strfilter", 2, 0, SQLITE_UTF8, 0, strfilterFunc, NULL, NULL },
2513 {
"stdev", 1, 0, SQLITE_UTF8, 0, NULL, varianceStep, stdevFinalize },
2514 {
"variance", 1, 0, SQLITE_UTF8, 0, NULL, varianceStep, varianceFinalize },
2515 {
"mode", 1, 0, SQLITE_UTF8, 0, NULL, modeStep, modeFinalize },
2516 {
"median", 1, 0, SQLITE_UTF8, 0, NULL, modeStep, medianFinalize },
2517 {
"lower_quartile", 1, 0, SQLITE_UTF8, 0, NULL, modeStep, lower_quartileFinalize },
2518 {
"upper_quartile", 1, 0, SQLITE_UTF8, 0, NULL, modeStep, upper_quartileFinalize },
2522 {
"expand", 1, 0, SQLITE_UTF8, 0, expandFunc, NULL, NULL },
2523 {
"regexp", 2, 0, SQLITE_UTF8, 0, regexpFunc, NULL, NULL },
2524 { NULL, 0, 0, 0, 0, NULL, NULL, NULL }
2527 rpmsqlCF _rpmsqlCFT = __CF;
2529 int _rpmsqlLoadCFT(
rpmsql sql,
void * _CF)
2531 sqlite3 * db = (sqlite3 *)sql->I;
2535 SQLDBG((stderr,
"--> %s(%p,%p)\n", __FUNCTION__, sql, _CF));
2539 for (CF = (rpmsqlCF) _CF; CF->zName != NULL; CF++) {
2540 void * _pApp = NULL;
2543 switch (CF->argType) {
2545 case 0: _pApp = NULL;
break;
2546 case 1: _pApp = (
void *)db;
break;
2547 case 2: _pApp = (
void *)-1;
break;
2550 xx =
rpmsqlCmd(sql,
"create_function", db,
2551 sqlite3_create_function(db, CF->zName, CF->nArg, CF->eTextRep,
2552 _pApp, CF->xFunc, CF->xStep, CF->xFinal));
2553 SQLDBG((stderr,
"\t%s(%s) xx %d\n",
"sqlite3_create_function", CF->zName, xx));
2558 if (CF->needColSeq) {
2559 FuncDef *pFunc = sqlite3FindFunction(db, CF->zName,
2560 strlen(CF_>zName), CF->nArg, CF->eTextRep, 0);
2561 if (pFunc) pFunc->needCollSeq = 1;
2566 SQLDBG((stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, sql, rc));
2572 static struct rpmvd_s _envVD = {
2575 .regex =
"^([^=]+)=(.*)$",
2579 static int envCreateConnect(
void * _db,
void * pAux,
2580 int argc,
const char *
const * argv,
2581 rpmvt * vtp,
char ** pzErr)
2583 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_envVD), vtp);
2586 struct sqlite3_module envModule = {
2587 .xCreate = (
void *) envCreateConnect,
2588 .xConnect = (
void *) envCreateConnect,
2593 static struct rpmvd_s _grdbVD = {
2594 .prefix =
"%{?_etc_group}%{!?_etc_group:/etc/group}",
2597 .parse =
"_group:passwd:gid:groups",
2598 .regex =
"^([^:]*):([^:]*):([^:]*):([^:]*)$",
2602 static int grdbCreateConnect(
void * _db,
void * pAux,
2603 int argc,
const char *
const * argv,
2604 rpmvt * vtp,
char ** pzErr)
2606 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_grdbVD), vtp);
2609 struct sqlite3_module grdbModule = {
2610 .xCreate = (
void *) grdbCreateConnect,
2611 .xConnect = (
void *) grdbCreateConnect,
2616 static struct rpmvd_s _procdbVD = {
2617 .prefix =
"%{?_procdb}%{!?_procdb:/proc/[0-9]}",
2619 .parse =
"dir/pid/*",
2620 .regex =
"^(.+/)([0-9]+)$",
2624 static int procdbCreateConnect(
void * _db,
void * pAux,
2625 int argc,
const char *
const * argv,
2626 rpmvt * vtp,
char ** pzErr)
2628 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_procdbVD), vtp);
2631 struct sqlite3_module procdbModule = {
2632 .xCreate = (
void *) procdbCreateConnect,
2633 .xConnect = (
void *) procdbCreateConnect,
2638 static struct rpmvd_s _pwdbVD = {
2639 .prefix =
"%{?_etc_passwd}%{!?_etc_passwd:/etc/passwd}",
2641 .parse =
"user:passwd:uid:gid:gecos:dir:shell",
2642 .regex =
"^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*)$",
2646 static int pwdbCreateConnect(
void * _db,
void * pAux,
2647 int argc,
const char *
const * argv,
2648 rpmvt * vtp,
char ** pzErr)
2650 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_pwdbVD), vtp);
2653 struct sqlite3_module pwdbModule = {
2654 .xCreate = (
void *) pwdbCreateConnect,
2655 .xConnect = (
void *) pwdbCreateConnect,
2660 static struct rpmvd_s _repodbVD = {
2662 .prefix =
"%{?_repodb}%{!?_repodb:/X/popt/}",
2664 .parse =
"dir/file-NVRA-N-V-R.A",
2665 .regex =
"^(.+/)(((.*)-([^-]+)-([^-]+)\\.([^.]+))\\.rpm)$",
2669 static int repodbCreateConnect(
void * _db,
void * pAux,
2670 int argc,
const char *
const * argv,
2671 rpmvt * vtp,
char ** pzErr)
2673 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_repodbVD), vtp);
2676 struct sqlite3_module repodbModule = {
2677 .xCreate = (
void *) repodbCreateConnect,
2678 .xConnect = (
void *) repodbCreateConnect,
2683 static int _stat_debug = 0;
2685 static struct rpmvd_s _statVD = {
2687 .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",
2690 static int statCreateConnect(
void * _db,
void * pAux,
2691 int argc,
const char *
const * argv,
2692 rpmvt * vtp,
char ** pzErr)
2694 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_statVD), vtp);
2697 static int statColumn(
rpmvc vc,
void * _pContext,
int colx)
2699 sqlite3_context * pContext = (sqlite3_context *) _pContext;
2701 const char * path = vt->av[vc->ix];
2702 const char * col = vt->cols[colx];
2703 struct stat sb, *st = &sb;
2704 int ret =
Lstat(path, &sb);
2707 if (_stat_debug < 0)
2708 fprintf(stderr,
"--> %s(%p,%p,%d)\n", __FUNCTION__, vc, pContext, colx);
2711 if (!strcmp(col,
"path"))
2712 sqlite3_result_text(pContext, path, -1, SQLITE_STATIC);
2713 else if (!strcmp(col,
"st_dev") && !ret)
2714 sqlite3_result_int64(pContext, st->st_dev);
2715 else if (!strcmp(col,
"st_ino") && !ret)
2716 sqlite3_result_int64(pContext, st->st_ino);
2717 else if (!strcmp(col,
"st_mode") && !ret)
2718 sqlite3_result_int64(pContext, st->st_mode);
2719 else if (!strcmp(col,
"st_nlink") && !ret)
2720 sqlite3_result_int64(pContext, st->st_nlink);
2721 else if (!strcmp(col,
"st_uid") && !ret)
2722 sqlite3_result_int64(pContext, st->st_uid);
2723 else if (!strcmp(col,
"st_gid") && !ret)
2724 sqlite3_result_int64(pContext, st->st_gid);
2725 else if (!strcmp(col,
"st_rdev") && !ret)
2726 sqlite3_result_int64(pContext, st->st_rdev);
2727 else if (!strcmp(col,
"st_size") && !ret)
2728 sqlite3_result_int64(pContext, st->st_size);
2729 else if (!strcmp(col,
"st_blksize") && !ret)
2730 sqlite3_result_int64(pContext, st->st_blksize);
2731 else if (!strcmp(col,
"st_blocks") && !ret)
2732 sqlite3_result_int64(pContext, st->st_blocks);
2733 else if (!strcmp(col,
"st_atime") && !ret)
2734 sqlite3_result_int64(pContext, st->st_atime);
2735 else if (!strcmp(col,
"st_mtime") && !ret)
2736 sqlite3_result_int64(pContext, st->st_mtime);
2737 else if (!strcmp(col,
"st_ctime") && !ret)
2738 sqlite3_result_int64(pContext, st->st_ctime);
2741 sqlite3_result_null(pContext);
2743 if (_stat_debug < 0)
2744 fprintf(stderr,
"<-- %s(%p,%p,%d) rc %d\n", __FUNCTION__, vc, pContext, colx, rc);
2749 struct sqlite3_module statModule = {
2750 .xCreate = (
void *) statCreateConnect,
2751 .xConnect = (
void *) statCreateConnect,
2752 .xColumn = (
void *) statColumn,
2757 static struct rpmvd_s _yumdbVD = {
2758 .prefix =
"%{?_yumdb}%{!?_yumdb:/var/lib/yum/yumdb}/",
2760 .parse =
"dir/hash-NVRA-N-V-R-A/*",
2761 .regex =
"^(.+/)([^-]+)-((.*)-([^-]+)-([^-]+)-([^-]+))$",
2765 static int yumdbCreateConnect(
void * _db,
void * pAux,
2766 int argc,
const char *
const * argv,
2767 rpmvt * vtp,
char ** pzErr)
2769 return rpmvtLoadArgv(
rpmvtNew(_db, pAux, argv, &_yumdbVD), vtp);
2772 struct sqlite3_module yumdbModule = {
2773 .xCreate = (
void *) yumdbCreateConnect,
2774 .xConnect = (
void *) yumdbCreateConnect,
2779 struct sqlite3_module _rpmvmTemplate = {
2780 .xCreate = (
void *) rpmvtCreate,
2781 .xConnect = (
void *) rpmvtConnect,
2782 .xBestIndex = (
void *) rpmvtBestIndex,
2783 .xDisconnect = (
void *) rpmvtDisconnect,
2784 .xDestroy = (
void *) rpmvtDestroy,
2785 .xOpen = (
void *) rpmvcOpen,
2786 .xClose = (
void *) rpmvcClose,
2787 .xFilter = (
void *) rpmvcFilter,
2788 .xNext = (
void *) rpmvcNext,
2789 .xEof = (
void *) rpmvcEof,
2790 .xColumn = (
void *) rpmvcColumn,
2791 .xRowid = (
void *) rpmvcRowid,
2792 .xUpdate = (
void *) rpmvtUpdate,
2793 .xBegin = (
void *) rpmvtBegin,
2794 .xSync = (
void *) rpmvtSync,
2795 .xCommit = (
void *) rpmvtCommit,
2796 .xRollback = (
void *) rpmvtRollback,
2797 .xFindFunction = (
void *) rpmvtFindFunction,
2798 .xRename = (
void *) rpmvtRename
2801 static struct rpmsqlVMT_s
__VMT[] = {
2802 {
"Argv", NULL, NULL },
2803 {
"Env", &envModule, NULL },
2804 {
"Grdb", &grdbModule, NULL },
2805 {
"Procdb", &procdbModule, NULL },
2806 {
"Pwdb", &pwdbModule, NULL },
2807 {
"Repodb", &repodbModule, NULL },
2808 {
"Stat", &statModule, NULL },
2809 {
"Yumdb", &yumdbModule, NULL },
2810 { NULL, NULL, NULL }
2813 static void rpmsqlVMFree(
void * _VM)
2816 SQLDBG((stderr,
"--> %s(%p)\n", __FUNCTION__, _VM));
2822 static void dumpVM(
const char * msg,
const rpmsqlVM s)
2824 fprintf(stderr,
"--------------------- %s\n", (msg ? msg :
""));
2825 #define VMPRT(f) if (s->f) fprintf(stderr, "%20s: %p\n", #f, s->f)
2843 VMPRT(xFindFunction);
2849 static rpmsqlVM rpmsqlVMNew(
const rpmsqlVM s)
2851 rpmsqlVM t =
xcalloc(1,
sizeof(*t));
2853 SQLDBG((stderr,
"--> %s(%p)\n", __FUNCTION__, s));
2854 *t = _rpmvmTemplate;
2857 if (s->iVersion) t->iVersion = s->iVersion;
2858 #define VMCPY(f) if (s->f) t->f = ((s->f != (void *)-1) ? s->f : NULL)
2876 VMCPY(xFindFunction);
2880 SQLDBG((stderr,
"<-- %s(%p) %p\n", __FUNCTION__, s, t));
2884 int _rpmsqlLoadVMT(
void * _db,
const rpmsqlVMT _VMT)
2886 sqlite3 * db = (sqlite3 *) _db;
2890 SQLDBG((stderr,
"--> %s(%p,%p)\n", __FUNCTION__, _db, _VMT));
2891 for (VMT = (rpmsqlVMT)_VMT; VMT->zName != NULL; VMT++) {
2895 sqlite3_create_module_v2(db, VMT->zName,
2896 rpmsqlVMNew(VMT->module), VMT->data, rpmsqlVMFree));
2897 SQLDBG((stderr,
"\t%s(%s) xx %d\n",
"sqlite3_create_module_v2", VMT->zName, xx));
2902 SQLDBG((stderr,
"<-- %s(%p,%p) rc %d\n", __FUNCTION__, _db, _VMT, rc));
2908 #if SQLITE_VERSION_NUMBER <= 3006015
2909 #define sqlite3_enable_load_extension(db, onoff) SQLITE_OK
2910 #define sqlite3_load_extension(db, zFile, zProc, pzErrMsg) SQLITE_OK
2918 static int _rpmsqlOpenDB(
rpmsql sql)
2925 db = (sqlite3 *)sql->I;
2929 sqlite3_open(sql->zDbFilename, &db));
2932 if (db && rc == SQLITE_OK) {
2933 (void) _rpmsqlLoadCFT(sql, _rpmsqlCFT);
2934 (void) _rpmsqlLoadVMT(db, __VMT);
2937 if (db == NULL || sqlite3_errcode(db) != SQLITE_OK) {
2939 rpmsql_error(1,
_(
"unable to open database \"%s\": %s"),
2940 sql->zDbFilename, sqlite3_errmsg(db));
2945 (void)
rpmsqlCmd(sql,
"enable_load_extension", db,
2946 sqlite3_enable_load_extension(db, 1));
2951 SQLDBG((stderr,
"<-- %s(%p) rc %d %s\n", __FUNCTION__, sql, rc, sql->zDbFilename));
2959 #if defined(WITH_SQLITE)
2965 static int isNumber(
const char *z,
int *realnum)
2967 if (*z ==
'-' || *z ==
'+')
2985 if (*z ==
'e' || *z ==
'E') {
2987 if (*z ==
'+' || *z ==
'-')
3004 static int strlen30(
const char *z)
3009 return 0x3fffffff & (int) (z2 - z);
3014 #if defined(WITH_SQLITE)
3021 static void output_hex_blob(
rpmsql sql,
const void *pBlob,
int nBlob)
3023 char *zBlob = (
char *) pBlob;
3026 SQLDBG((stderr,
"--> %s(%p,%p[%u])\n", __FUNCTION__, sql, pBlob, (
unsigned)nBlob));
3027 rpmsqlFprintf(sql,
"X'");
3028 for (i = 0; i < nBlob; i++)
3029 rpmsqlFprintf(sql,
"%02x", zBlob[i]);
3030 rpmsqlFprintf(sql,
"'");
3038 static void output_quoted_string(
rpmsql sql,
const char *z)
3042 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, z));
3043 for (i = 0; z[
i]; i++) {
3048 rpmsqlFprintf(sql,
"'%s'", z);
3050 rpmsqlFprintf(sql,
"'");
3052 for (i = 0; z[
i] && z[
i] !=
'\''; i++)
3055 rpmsqlFprintf(sql,
"''");
3057 }
else if (z[i] ==
'\'') {
3058 rpmsqlFprintf(sql,
"%.*s''", i, z);
3061 rpmsqlFprintf(sql,
"%s", z);
3065 rpmsqlFprintf(sql,
"'");
3074 static void output_c_string(
rpmsql sql,
const char *z)
3077 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, z));
3078 rpmsqlFprintf(sql,
"\"");
3079 while ((c = *(z++)) != 0) {
3081 rpmsqlFprintf(sql,
"\\\\");
3083 rpmsqlFprintf(sql,
"\\t");
3085 rpmsqlFprintf(sql,
"\\n");
3087 rpmsqlFprintf(sql,
"\\r");
3088 else if (!isprint(c))
3089 rpmsqlFprintf(sql,
"\\%03o", c & 0xff);
3091 rpmsqlFprintf(sql,
"%c", c);
3093 rpmsqlFprintf(sql,
"\"");
3102 static void output_html_string(
rpmsql sql,
const char *z)
3105 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, z));
3110 && z[
i] !=
'>' && z[
i] !=
'\"' && z[
i] !=
'\''; i++) {
3113 rpmsqlFprintf(sql,
"%.*s", i, z);
3115 rpmsqlFprintf(sql,
"<");
3116 else if (z[i] ==
'&')
3117 rpmsqlFprintf(sql,
"&");
3118 else if (z[i] ==
'>')
3119 rpmsqlFprintf(sql,
">");
3120 else if (z[i] ==
'\"')
3121 rpmsqlFprintf(sql,
""");
3122 else if (z[i] ==
'\'')
3123 rpmsqlFprintf(sql,
"'");
3135 static const char needCsvQuote[] = {
3136 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3137 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3138 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3140 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3141 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3142 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
3144 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3145 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3146 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3147 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3148 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3149 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3150 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3151 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3163 static void output_csv(
rpmsql sql,
const char *z,
int bSep)
3165 SQLDBG((stderr,
"--> %s(%p,%s,0x%x)\n", __FUNCTION__, sql, z, bSep));
3167 rpmsqlFprintf(sql,
"%s", sql->nullvalue);
3170 int nSep = strlen30(sql->separator);
3171 for (i = 0; z[
i]; i++) {
3172 if (needCsvQuote[((
unsigned char *) z)[i]]
3173 || (z[i] == sql->separator[0] &&
3174 (nSep == 1 || memcmp(z, sql->separator, nSep) == 0))) {
3180 rpmsqlFprintf(sql,
"\"");
3181 for (i = 0; z[
i]; i++) {
3183 rpmsqlFprintf(sql,
"\"");
3184 rpmsqlFprintf(sql,
"%c", z[i]);
3186 rpmsqlFprintf(sql,
"\"");
3188 rpmsqlFprintf(sql,
"%s", z);
3192 rpmsqlFprintf(sql,
"%s", sql->separator);
3204 static int _rpmsqlShellCallback(
void * _sql,
int nArg,
char **azArg,
char **azCol,
3211 SQLDBG((stderr,
"--> %s(%p,%d,%p,%p,%p)\n", __FUNCTION__, _sql, nArg, azArg, azCol, aiType));
3212 switch (sql->mode) {
3213 case RPMSQL_MODE_LINE:
3217 for (i = 0; i < nArg; i++) {
3218 int len = strlen30(azCol[i] ? azCol[i] :
"");
3223 rpmsqlFprintf(sql,
"\n");
3224 for (i = 0; i < nArg; i++)
3225 rpmsqlFprintf(sql,
"%*s = %s\n", w, azCol[i],
3226 azArg[i] ? azArg[i] : sql->nullvalue);
3228 case RPMSQL_MODE_EXPLAIN:
3229 case RPMSQL_MODE_COLUMN:
3230 if (sql->cnt++ == 0) {
3231 for (i = 0; i < nArg; i++) {
3233 w = (i < ArraySize(sql->colWidth) ? sql->colWidth[
i] : 0);
3236 w = strlen30(azCol[i] ? azCol[i] :
"");
3239 n = strlen30(azArg && azArg[i]
3240 ? azArg[i] : sql-> nullvalue);
3244 if (i < ArraySize(sql->actualWidth))
3245 sql->actualWidth[
i] =
w;
3247 rpmsqlFprintf(sql,
"%-*.*s%s", w, w, azCol[i],
3248 i == nArg - 1 ?
"\n" :
" ");
3252 for (i = 0; i < nArg; i++) {
3253 w = (i < ArraySize(sql->actualWidth)
3254 ? sql->actualWidth[
i] : 10);
3256 rpmsqlFprintf(sql,
"%-*.*s%s", w, w,
3257 "-----------------------------------"
3258 "----------------------------------------------------------",
3259 i == nArg - 1 ?
"\n" :
" ");
3265 for (i = 0; i < nArg; i++) {
3266 w = (i < ArraySize(sql->actualWidth) ? sql->actualWidth[
i] : 10);
3267 if (sql->mode == RPMSQL_MODE_EXPLAIN && azArg[i] &&
3268 strlen30(azArg[i]) >
w) {
3269 w = strlen30(azArg[i]);
3271 rpmsqlFprintf(sql,
"%-*.*s%s", w, w,
3272 azArg[i] ? azArg[i] : sql->nullvalue,
3273 i == nArg - 1 ?
"\n" :
" ");
3276 case RPMSQL_MODE_SEMI:
3277 case RPMSQL_MODE_LIST:
3278 if (sql->cnt++ == 0 &&
F_ISSET(sql, SHOWHDR)) {
3279 for (i = 0; i < nArg; i++)
3280 rpmsqlFprintf(sql,
"%s%s", azCol[i],
3281 i == nArg - 1 ?
"\n" : sql->separator);
3286 for (i = 0; i < nArg; i++) {
3290 rpmsqlFprintf(sql,
"%s", z);
3292 rpmsqlFprintf(sql,
"%s", sql->separator);
3293 else if (sql->mode == RPMSQL_MODE_SEMI)
3294 rpmsqlFprintf(sql,
";\n");
3296 rpmsqlFprintf(sql,
"\n");
3299 case RPMSQL_MODE_HTML:
3300 if (sql->cnt++ == 0 &&
F_ISSET(sql, SHOWHDR)) {
3301 rpmsqlFprintf(sql,
"<TR>");
3302 for (i = 0; i < nArg; i++) {
3303 rpmsqlFprintf(sql,
"<TH>");
3304 output_html_string(sql, azCol[i]);
3305 rpmsqlFprintf(sql,
"</TH>\n");
3307 rpmsqlFprintf(sql,
"</TR>\n");
3311 rpmsqlFprintf(sql,
"<TR>");
3312 for (i = 0; i < nArg; i++) {
3313 rpmsqlFprintf(sql,
"<TD>");
3314 output_html_string(sql, azArg[i] ? azArg[i] : sql->nullvalue);
3315 rpmsqlFprintf(sql,
"</TD>\n");
3317 rpmsqlFprintf(sql,
"</TR>\n");
3319 case RPMSQL_MODE_TCL:
3320 if (sql->cnt++ == 0 &&
F_ISSET(sql, SHOWHDR)) {
3321 for (i = 0; i < nArg; i++) {
3322 output_c_string(sql, azCol[i] ? azCol[i] :
"");
3323 rpmsqlFprintf(sql,
"%s", sql->separator);
3325 rpmsqlFprintf(sql,
"\n");
3329 for (i = 0; i < nArg; i++) {
3330 output_c_string(sql, azArg[i] ? azArg[i] : sql->nullvalue);
3331 rpmsqlFprintf(sql,
"%s", sql->separator);
3333 rpmsqlFprintf(sql,
"\n");
3335 case RPMSQL_MODE_CSV:
3336 if (sql->cnt++ == 0 &&
F_ISSET(sql, SHOWHDR)) {
3337 for (i = 0; i < nArg; i++)
3338 output_csv(sql, azCol[i] ? azCol[i] :
"", i < nArg - 1);
3339 rpmsqlFprintf(sql,
"\n");
3343 for (i = 0; i < nArg; i++)
3344 output_csv(sql, azArg[i], i < nArg - 1);
3345 rpmsqlFprintf(sql,
"\n");
3347 case RPMSQL_MODE_INSERT:
3351 rpmsqlFprintf(sql,
"INSERT INTO %s VALUES(", sql->zDestTable);
3352 for (i = 0; i < nArg; i++) {
3353 char *zSep = i > 0 ?
"," :
"";
3354 if ((azArg[i] == 0) || (aiType && aiType[i] == SQLITE_NULL)) {
3355 rpmsqlFprintf(sql,
"%sNULL", zSep);
3356 }
else if (aiType && aiType[i] == SQLITE_TEXT) {
3358 rpmsqlFprintf(sql,
"%s", zSep);
3359 output_quoted_string(sql, azArg[i]);
3361 && (aiType[i] == SQLITE_INTEGER
3362 || aiType[i] == SQLITE_FLOAT)) {
3363 rpmsqlFprintf(sql,
"%s%s", zSep, azArg[i]);
3364 }
else if (aiType && aiType[i] == SQLITE_BLOB && sql->S) {
3365 sqlite3_stmt * pStmt = (sqlite3_stmt *)sql->S;
3366 const void *pBlob = sqlite3_column_blob(pStmt, i);
3367 int nBlob = sqlite3_column_bytes(pStmt, i);
3369 rpmsqlFprintf(sql,
"%s", zSep);
3370 output_hex_blob(sql, pBlob, nBlob);
3371 }
else if (isNumber(azArg[i], 0)) {
3372 rpmsqlFprintf(sql,
"%s%s", zSep, azArg[i]);
3375 rpmsqlFprintf(sql,
"%s", zSep);
3376 output_quoted_string(sql, azArg[i]);
3379 rpmsqlFprintf(sql,
");\n");
3393 static int callback(
void *_sql,
int nArg,
char **azArg,
char **azCol)
3396 return _rpmsqlShellCallback(_sql, nArg, azArg, azCol, NULL);
3406 static void set_table_name(
rpmsql sql,
const char *zName)
3412 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, zName));
3413 sql->zDestTable =
_free(sql->zDestTable);
3416 needQuote = !
xisalpha((
unsigned char) *zName) && *zName !=
'_';
3417 for (i = n = 0; zName[
i]; i++, n++) {
3418 if (!
xisalnum((
unsigned char) zName[i]) && zName[i] !=
'_') {
3420 if (zName[i] ==
'\'')
3426 sql->zDestTable = z =
xmalloc(n + 1);
3430 for (i = 0; zName[
i]; i++) {
3432 if (zName[i] ==
'\'')
3453 static char *appendText(
char *zIn,
char const *zAppend,
char quote)
3457 int nAppend = strlen30(zAppend);
3458 int nIn = (zIn ? strlen30(zIn) : 0);
3460 SQLDBG((stderr,
"--> %s(%s,%s,0x%02x)\n", __FUNCTION__, zIn, zAppend, quote));
3461 len = nAppend + nIn + 1;
3464 for (i = 0; i < nAppend; i++) {
3465 if (zAppend[i] == quote)
3473 char *zCsr = &zIn[nIn];
3475 for (i = 0; i < nAppend; i++) {
3476 *zCsr++ = zAppend[
i];
3477 if (zAppend[i] == quote)
3482 assert((zCsr - zIn) == len);
3484 memcpy(&zIn[nIn], zAppend, nAppend);
3485 zIn[len - 1] =
'\0';
3503 static int run_table_dump_query(
rpmsql sql, sqlite3 * db,
3504 const char *zSelect,
const char *zFirstRow)
3506 sqlite3_stmt * pSelect;
3508 SQLDBG((stderr,
"--> %s(%p,%p,%s,%s)\n", __FUNCTION__, sql, db, zSelect, zFirstRow));
3510 sqlite3_prepare(db, zSelect, -1, &pSelect, 0));
3511 if (rc || pSelect == NULL)
3515 sqlite3_step(pSelect))) == SQLITE_ROW)
3518 rpmsqlFprintf(sql,
"%s", zFirstRow);
3521 rpmsqlFprintf(sql,
"%s;\n", sqlite3_column_text(pSelect, 0));
3525 sqlite3_finalize(pSelect));
3531 #if defined(WITH_SQLITE)
3532 #define iseol(_c) ((char)(_c) == '\n' || (char)(_c) == '\r')
3543 rpmsqlFgets(
char * buf,
size_t nbuf,
rpmsql sql)
3547 FD_t ifd = sql->ifd;
3557 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)));
3559 assert(ifp != NULL);
3564 if (fgets(q, (
int)nbuf, ifp) == NULL)
3568 for (q += nb - 1; nb > 0 &&
iseol(*q); q--)
3570 for (; p <= q; p++) {
3577 default: p++;
break;
3582 case '{': p++, bc++;
break;
3583 case '(': p++, pc++;
break;
3584 case '%': p++;
break;
3587 case '{':
if (bc > 0) bc++;
break;
3588 case '}':
if (bc > 0) bc--;
break;
3589 case '(':
if (pc > 0) pc++;
break;
3590 case ')':
if (pc > 0) pc--;
break;
3593 if (nb == 0 || (*q !=
'\\' && !bc && !pc) || *(q+1) ==
'\0') {
3603 SQLDBG((stderr,
"<-- %s(%p[%u],%p) nr %u\n", __FUNCTION__, buf, (
unsigned)nbuf, sql, (
unsigned)nr));
3605 return (nr > 0 ? buf : NULL);
3619 static char *local_getline(
rpmsql sql,
const char *zPrompt)
3623 SQLDBG((stderr,
"--> %s(%s) ofd %p\n", __FUNCTION__, zPrompt, sql->ofd));
3625 if (sql->ofd && zPrompt && *zPrompt) {
3626 size_t nb = strlen(zPrompt);
3627 size_t nw =
Fwrite(zPrompt, 1, nb, sql->ofd);
3632 assert(sql->ifd != NULL);
3633 t = rpmsqlFgets(sql->buf, sql->nbuf, sql);
3635 SQLDBG((stderr,
"<-- %s(%s) ofd %p\n", __FUNCTION__, zPrompt, sql->ofd));
3648 static char *rpmsqlInputOneLine(
rpmsql sql,
const char *zPrior)
3650 const char *zPrompt;
3653 SQLDBG((stderr,
"--> %s(%s)\n", __FUNCTION__, zPrior));
3655 assert(sql->buf != NULL);
3656 assert(sql->ifd != NULL);
3659 zResult = local_getline(sql, NULL);
3661 zPrompt = (zPrior && zPrior[0]) ? sql->zContinue : sql->zPrompt;
3664 #if defined(HAVE_READLINE) && HAVE_READLINE==1
3668 if (zResult != sql->buf) {
3669 strncpy(sql->buf, zResult, sql->nbuf);
3670 zResult =
_free(zResult);
3677 SQLDBG((stderr,
"<-- %s(%s)\n", __FUNCTION__, zPrior));
3686 #if defined(WITH_SQLITE)
3691 static char *save_err_msg(sqlite3 * db)
3693 const char * s = sqlite3_errmsg(db);
3694 int nb = strlen30(s) + 1;
3695 return memcpy(
xmalloc(nb), s, nb);
3711 static int _rpmsqlShellExec(
rpmsql sql,
const char *zSql,
3712 int (*xCallback) (
void *,
int,
char **,
char **,
int *),
3716 sqlite3 * db = (sqlite3 *) sql->I;
3717 sqlite3_stmt * pStmt = NULL;
3719 const char *zLeftover;
3721 SQLDBG((stderr,
"--> %s(%p,%s,%p,%p)\n", __FUNCTION__, sql, zSql, xCallback, pzErrMsg));
3725 while (zSql[0] && rc == SQLITE_OK) {
3727 sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover));
3736 if (sql->ofd &&
F_ISSET(sql, ECHO)) {
3737 const char *zStmtSql = sqlite3_sql(pStmt);
3738 rpmsqlFprintf(sql,
"%s\n", zStmtSql ? zStmtSql : zSql);
3746 sqlite3_step(pStmt));
3748 if (rc == SQLITE_ROW) {
3752 int nCol = sqlite3_column_count(pStmt);
3753 size_t nb = 3 * nCol *
sizeof(
const char *) + 1;
3755 char ** azVals = &azCols[nCol];
3756 int * aiTypes = (
int *) &azVals[nCol];
3760 for (i = 0; i < nCol; i++)
3761 azCols[i] = (
char *) sqlite3_column_name(pStmt, i);
3764 sql->S = (
void *) pStmt;
3768 for (i = 0; i < nCol; i++) {
3769 azVals[
i] = (
char *) sqlite3_column_text(pStmt, i);
3770 aiTypes[
i] = sqlite3_column_type(pStmt, i);
3771 if (!azVals[i] && (aiTypes[i] != SQLITE_NULL)) {
3778 if (rc != SQLITE_ROW)
3782 if (xCallback (sql, nCol, azVals, azCols, aiTypes)) {
3787 sqlite3_step(pStmt));
3788 }
while (rc == SQLITE_ROW);
3789 azCols =
_free(azCols);
3794 sqlite3_step(pStmt));
3795 }
while (rc == SQLITE_ROW);
3803 sqlite3_finalize(pStmt));
3809 *pzErrMsg = save_err_msg(db);
3825 #if defined(WITH_SQLITE)
3837 static int dump_callback(
void *_sql,
int nArg,
char **azArg,
char **azCol)
3840 sqlite3 * db = (sqlite3 *) sql->I;
3845 const char *zPrepStmt = 0;
3848 SQLDBG((stderr,
"--> %s(%p,%d,%p,%p)\n", __FUNCTION__, _sql, nArg, azArg, azCol));
3856 if (!strcmp(zTable,
"sqlite_sequence")) {
3857 zPrepStmt =
"DELETE FROM sqlite_sequence;\n";
3858 }
else if (!strcmp(zTable,
"sqlite_stat1")) {
3859 rpmsqlFprintf(sql,
"ANALYZE sqlite_master;\n");
3860 }
else if (!strncmp(zTable,
"sqlite_", 7)) {
3863 }
else if (!strncmp(zSql,
"CREATE VIRTUAL TABLE", 20)) {
3865 if (!
F_ISSET(sql, WRITABLE)) {
3866 rpmsqlFprintf(sql,
"PRAGMA writable_schema=ON;\n");
3867 sql->flags |= RPMSQL_FLAGS_WRITABLE;
3871 (
"INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
3872 "VALUES('table','%q','%q',0,'%q');", zTable, zTable, zSql);
3873 rpmsqlFprintf(sql,
"%s\n", zIns);
3878 rpmsqlFprintf(sql,
"%s;\n", zSql);
3880 if (!strcmp(zType,
"table")) {
3881 sqlite3_stmt * pTableInfo = NULL;
3883 char *zTableInfo = 0;
3887 zTableInfo = appendText(zTableInfo,
"PRAGMA table_info(", 0);
3888 zTableInfo = appendText(zTableInfo, zTable,
'"');
3889 zTableInfo = appendText(zTableInfo,
");", 0);
3892 sqlite3_prepare(db, zTableInfo, -1, &pTableInfo, 0));
3893 zTableInfo =
_free(zTableInfo);
3894 if (rc != SQLITE_OK || !pTableInfo)
3897 zSelect = appendText(zSelect,
"SELECT 'INSERT INTO ' || ", 0);
3899 zTmp = appendText(zTmp, zTable,
'"');
3901 zSelect = appendText(zSelect, zTmp,
'\'');
3904 zSelect = appendText(zSelect,
" || ' VALUES(' || ", 0);
3906 sqlite3_step(pTableInfo));
3907 while (rc == SQLITE_ROW) {
3909 (
const char *) sqlite3_column_text(pTableInfo, 1);
3910 zSelect = appendText(zSelect,
"quote(", 0);
3911 zSelect = appendText(zSelect, zText,
'"');
3913 sqlite3_step(pTableInfo));
3914 if (rc == SQLITE_ROW)
3915 zSelect = appendText(zSelect,
") || ',' || ", 0);
3917 zSelect = appendText(zSelect,
") ", 0);
3921 sqlite3_finalize(pTableInfo));
3922 if (rc != SQLITE_OK || nRow == 0) {
3923 zSelect =
_free(zSelect);
3927 zSelect = appendText(zSelect,
"|| ')' FROM ", 0);
3928 zSelect = appendText(zSelect, zTable,
'"');
3930 rc = run_table_dump_query(sql, db, zSelect, zPrepStmt);
3931 if (rc == SQLITE_CORRUPT) {
3932 zSelect = appendText(zSelect,
" ORDER BY rowid DESC", 0);
3933 rc = run_table_dump_query(sql, db, zSelect, NULL);
3935 zSelect =
_free(zSelect);
3952 static int run_schema_dump_query(
rpmsql sql,
3953 const char *zQuery,
char **pzErrMsg)
3955 sqlite3 * db = (sqlite3 *) sql->I;
3958 SQLDBG((stderr,
"--> %s(%p,%s,%p)\n", __FUNCTION__, sql, zQuery, pzErrMsg));
3960 sqlite3_exec(db, zQuery, dump_callback, sql, pzErrMsg));
3961 if (rc == SQLITE_CORRUPT) {
3964 sqlite3_free(*pzErrMsg);
3965 zQ2 =
rpmExpand(zQuery,
" ORDER BY rowid DESC", NULL);
3967 sqlite3_exec(db, zQ2, dump_callback, sql, pzErrMsg));
3977 static char zHelp[] =
3978 ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
3979 ".bail ON|OFF Stop after hitting an error. Default OFF\n"
3980 ".databases List names and files of attached databases\n"
3981 ".dump ?TABLE? ... Dump the database in an SQL text format\n"
3982 " If TABLE specified, only dump tables matching\n"
3983 " LIKE pattern TABLE.\n"
3984 ".echo ON|OFF Turn command echo on or off\n"
3985 ".exit Exit this program\n"
3986 ".explain ?ON|OFF? Turn output mode suitable for EXPLAIN on or off.\n"
3987 " With no args, it turns EXPLAIN on.\n"
3988 ".header(s) ON|OFF Turn display of headers on or off\n"
3989 ".help Show this message\n"
3990 ".import FILE TABLE Import data from FILE into TABLE\n"
3991 ".indices ?TABLE? Show names of all indices\n"
3992 " If TABLE specified, only show indices for tables\n"
3993 " matching LIKE pattern TABLE.\n"
3994 #ifdef SQLITE_ENABLE_IOTRACE
3995 ".iotrace FILE Enable I/O diagnostic logging to FILE\n"
3997 ".load FILE ?ENTRY? Load an extension library\n"
3998 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n"
3999 ".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
4000 " csv Comma-separated values\n"
4001 " column Left-aligned columns. (See .width)\n"
4002 " html HTML <table> code\n"
4003 " insert SQL insert statements for TABLE\n"
4004 " line One value per line\n"
4005 " list Values delimited by .separator string\n"
4006 " tabs Tab-separated values\n"
4007 " tcl TCL list elements\n"
4008 ".nullvalue STRING Print STRING in place of NULL values\n"
4009 ".output FILENAME Send output to FILENAME\n"
4010 ".output stdout Send output to the screen\n"
4011 ".prompt MAIN CONTINUE Replace the standard prompts\n"
4012 ".quit Exit this program\n"
4013 ".read FILENAME Execute SQL in FILENAME\n"
4014 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
4015 ".schema ?TABLE? Show the CREATE statements\n"
4016 " If TABLE specified, only show tables matching\n"
4017 " LIKE pattern TABLE.\n"
4018 ".separator STRING Change separator used by output mode and .import\n"
4019 ".show Show the current values for various settings\n"
4020 ".tables ?TABLE? List names of tables\n"
4021 " If TABLE specified, only list tables matching\n"
4022 " LIKE pattern TABLE.\n"
4023 ".timeout MS Try opening locked tables for MS milliseconds\n"
4024 ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n";
4026 static char zTimerHelp[] =
4027 ".timer ON|OFF Turn the CPU timer measurement on or off\n";
4038 static void resolve_backslashes(
char *z)
4042 for (i = j = 0; (c = z[
i]) != 0; i++, j++) {
4047 }
else if (c ==
't') {
4049 }
else if (c ==
'r') {
4051 }
else if (c >=
'0' && c <=
'7') {
4053 if (z[i + 1] >=
'0' && z[i + 1] <=
'7') {
4055 c = (c << 3) + z[i] -
'0';
4056 if (z[i + 1] >=
'0' && z[i + 1] <=
'7') {
4058 c = (c << 3) + z[i] -
'0';
4072 static int booleanValue(
const char * zArg)
4074 int val = atoi(zArg);
4075 if (!strcasecmp(zArg,
"on") || !strcasecmp(zArg,
"yes"))
4077 SQLDBG((stderr,
"<-- %s(%s) val %d\n", __FUNCTION__, zArg, val));
4082 static const char *modeDescr[] = {
4095 static int rpmsqlInput(
rpmsql sql);
4097 static int rpmsqlFOpen(
const char * fn,
FD_t *fdp)
4103 SQLDBG((stderr,
"--> %s(%s,%p) fd %p\n", __FUNCTION__, fn, fdp, fd));
4111 else if (!strcmp(fn,
"stdout") || !strcmp(fn,
"-"))
4112 fd =
fdDup(STDOUT_FILENO);
4113 else if (!strcmp(fn,
"stderr"))
4114 fd =
fdDup(STDERR_FILENO);
4115 else if (!strcmp(fn,
"off"))
4118 fd =
Fopen(fn,
"wb");
4119 if (fd == NULL ||
Ferror(fd)) {
4120 rpmsql_error(1,
_(
"cannot open \"%s\""), fn);
4121 if (fd) (void)
Fclose(fd);
4128 SQLDBG((stderr,
"<-- %s(%s,%p) fd %p rc %d\n", __FUNCTION__, fn, fdp, fd, rc));
4140 static int rpmsqlMetaCommand(
rpmsql sql,
char *zLine)
4142 sqlite3 * db = (sqlite3 *)sql->I;
4149 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, zLine));
4152 while (zLine[i] && nArg < ArraySize(azArg)) {
4153 while (
xisspace((
unsigned char) zLine[i]))
4155 if (zLine[i] ==
'\0')
4157 if (zLine[i] ==
'\'' || zLine[i] ==
'"') {
4158 int delim = zLine[i++];
4159 azArg[nArg++] = &zLine[
i];
4160 while (zLine[i] && zLine[i] != delim)
4162 if (zLine[i] == delim)
4165 resolve_backslashes(azArg[nArg - 1]);
4167 azArg[nArg++] = &zLine[
i];
4168 while (zLine[i] && !
xisspace((
unsigned char) zLine[i]))
4172 resolve_backslashes(azArg[nArg - 1]);
4179 n = strlen30(azArg[0]);
4181 if (c ==
'b' && n >= 3 && !strncmp(azArg[0],
"backup", n)
4182 && nArg > 1 && nArg < 4) {
4183 const char *zDestFile;
4186 sqlite3_backup *pBackup;
4188 zDestFile = azArg[1];
4191 zDestFile = azArg[2];
4195 sqlite3_open(zDestFile, &pDest));
4198 rpmsql_error(1,
_(
"cannot open \"%s\""), zDestFile);
4201 sqlite3_close(pDest));
4205 db = (sqlite3 *)sql->I;
4206 pBackup = sqlite3_backup_init(pDest,
"main", db, zDb);
4207 if (pBackup == NULL) {
4208 rpmsql_error(1,
"%s", sqlite3_errmsg(pDest));
4210 sqlite3_close(pDest));
4213 while ((rc =
rpmsqlCmd(sql,
"backup_step", db,
4214 sqlite3_backup_step(pBackup, 100))) == SQLITE_OK)
4216 (void)
rpmsqlCmd(sql,
"backup_finish", pBackup,
4217 sqlite3_backup_finish(pBackup));
4218 if (rc == SQLITE_DONE) {
4221 rpmsql_error(1,
"%s", sqlite3_errmsg(pDest));
4225 sqlite3_close(pDest));
4227 if (c ==
'b' && n >= 3 && !strncmp(azArg[0],
"bail", n)
4228 && nArg > 1 && nArg < 3) {
4229 if (booleanValue(azArg[1]))
4230 sql->flags |= RPMSQL_FLAGS_BAIL;
4232 sql->flags &= ~RPMSQL_FLAGS_BAIL;
4234 if (c ==
'd' && n > 1 && !strncmp(azArg[0],
"databases", n) && nArg == 1) {
4236 uint32_t _flags = sql->flags;
4237 uint32_t _mode = sql->mode;
4238 int _cnt = sql->cnt;;
4240 char *zErrMsg = NULL;
4241 memcpy(_colWidth, sql->colWidth,
sizeof(_colWidth));
4243 db = (sqlite3 *)sql->I;
4244 sql->flags |= RPMSQL_FLAGS_SHOWHDR;
4245 sql->mode = RPMSQL_MODE_COLUMN;
4246 sql->colWidth[0] = 3;
4247 sql->colWidth[1] = 15;
4248 sql->colWidth[2] = 58;
4251 sqlite3_exec(db,
"PRAGMA database_list;", callback, sql, &zErrMsg));
4253 rpmsql_error(1,
"%s", zErrMsg);
4254 sqlite3_free(zErrMsg);
4257 memcpy(sql->colWidth, _colWidth,
sizeof(_colWidth));
4260 sql->flags = _flags;
4262 if (c ==
'd' && !strncmp(azArg[0],
"dump", n) && nArg < 3) {
4265 db = (sqlite3 *)sql->I;
4269 rpmsqlFprintf(sql,
"PRAGMA foreign_keys=OFF;\n");
4270 rpmsqlFprintf(sql,
"BEGIN TRANSACTION;\n");
4271 sql->flags &= ~RPMSQL_FLAGS_WRITABLE;
4273 sqlite3_exec(db,
"PRAGMA writable_schema=ON", 0, 0, 0));
4275 t =
rpmExpand(
"SELECT name, type, sql FROM sqlite_master"
4276 " WHERE sql NOT NULL AND type=='table'"
4277 " AND name!='sqlite_sequence'", NULL);
4278 run_schema_dump_query(sql, t, NULL);
4280 t =
rpmExpand(
"SELECT name, type, sql FROM sqlite_master"
4281 " WHERE name=='sqlite_sequence'", NULL);
4282 run_schema_dump_query(sql, t, NULL);
4284 t =
rpmExpand(
"SELECT sql FROM sqlite_master"
4285 " WHERE sql NOT NULL AND type IN ('index','trigger','view')", NULL);
4286 run_table_dump_query(sql, db, t, NULL);
4290 for (i = 1; i < nArg; i++) {
4291 t =
rpmExpand(
"SELECT name, type, sql FROM sqlite_master"
4292 " WHERE tbl_name LIKE '", azArg[i],
"'"
4293 " AND type=='table' AND sql NOT NULL", NULL);
4294 run_schema_dump_query(sql, t, NULL);
4296 t =
rpmExpand(
"SELECT sql FROM sqlite_master"
4297 " WHERE sql NOT NULL"
4298 " AND type IN ('index','trigger','view')"
4299 " AND tbl_name LIKE '", azArg[i],
"'", NULL);
4300 run_table_dump_query(sql, db, t, NULL);
4305 rpmsqlFprintf(sql,
"PRAGMA writable_schema=OFF;\n");
4306 sql->flags &= ~RPMSQL_FLAGS_WRITABLE;
4309 sqlite3_exec(db,
"PRAGMA writable_schema=OFF", 0, 0, 0));
4310 rpmsqlFprintf(sql,
"COMMIT;\n");
4312 if (c ==
'e' && !strncmp(azArg[0],
"echo", n) && nArg > 1 && nArg < 3) {
4313 if (booleanValue(azArg[1]))
4314 sql->flags |= RPMSQL_FLAGS_ECHO;
4316 sql->flags &= ~RPMSQL_FLAGS_ECHO;
4318 if (c ==
'e' && !strncmp(azArg[0],
"exit", n) && nArg == 1) {
4321 if (c ==
'e' && !strncmp(azArg[0],
"explain", n) && nArg < 3) {
4322 int val = nArg >= 2 ? booleanValue(azArg[1]) : 1;
4324 if (!sql->explainPrev.valid) {
4325 sql->explainPrev.valid = 1;
4326 sql->explainPrev.mode = sql->mode;
4327 sql->explainPrev.flags = sql->flags;
4328 memcpy(sql->explainPrev.colWidth, sql->colWidth,
4329 sizeof(sql->colWidth));
4338 sql->mode = RPMSQL_MODE_EXPLAIN;
4339 sql->flags |= RPMSQL_FLAGS_SHOWHDR;
4340 memset(sql->colWidth, 0, ArraySize(sql->colWidth));
4341 sql->colWidth[0] = 4;
4342 sql->colWidth[1] = 13;
4343 sql->colWidth[2] = 4;
4344 sql->colWidth[3] = 4;
4345 sql->colWidth[4] = 4;
4346 sql->colWidth[5] = 13;
4347 sql->colWidth[6] = 2;
4348 sql->colWidth[7] = 13;
4349 }
else if (sql->explainPrev.valid) {
4350 sql->explainPrev.valid = 0;
4351 sql->mode = sql->explainPrev.mode;
4352 sql->flags = sql->explainPrev.flags;
4353 memcpy(sql->colWidth, sql->explainPrev.colWidth,
4354 sizeof(sql->colWidth));
4358 && (!strncmp(azArg[0],
"header", n) || !strncmp(azArg[0],
"headers", n))
4359 && nArg > 1 && nArg < 3)
4361 if (booleanValue(azArg[1]))
4362 sql->flags |= RPMSQL_FLAGS_SHOWHDR;
4364 sql->flags &= ~RPMSQL_FLAGS_SHOWHDR;
4366 if (c ==
'h' && !strncmp(azArg[0],
"help", n)) {
4367 rpmsql_error(0,
"%s", zHelp);
4369 rpmsql_error(0,
"%s", zTimerHelp);
4371 if (c ==
'i' && !strncmp(azArg[0],
"import", n) && nArg == 3) {
4372 char *zTable = azArg[2];
4373 char *zFile = azArg[1];
4374 sqlite3_stmt * pStmt = NULL;
4386 db = (sqlite3 *)sql->I;
4387 nSep = strlen30(sql->separator);
4389 rpmsql_error(1,
_(
"non-null separator required for import"));
4392 zSql = sqlite3_mprintf(
"SELECT * FROM '%q'", zTable);
4393 assert(zSql != NULL);
4394 nByte = strlen30(zSql);
4396 sqlite3_prepare(db, zSql, -1, &pStmt, 0));
4400 sqlite3 * db = (sqlite3 *)sql->I;
4401 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4405 sqlite3_finalize(pStmt));
4408 nCol = sqlite3_column_count(pStmt);
4410 sqlite3_finalize(pStmt));
4414 zSql =
xmalloc(nByte + 20 + nCol * 2);
4415 sqlite3_snprintf(nByte + 20, zSql,
"INSERT INTO '%q' VALUES(?",
4418 for (i = 1; i < nCol; i++) {
4425 sqlite3_prepare(db, zSql, -1, &pStmt, 0));
4429 sqlite3 * db = (sqlite3 *)sql->I;
4430 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4434 sqlite3_finalize(pStmt));
4437 assert(sql->ifd == NULL);
4438 sql->ifd =
Fopen(zFile,
"rb.fpio");
4439 if (sql->ifd == NULL ||
Ferror(sql->ifd)) {
4440 rpmsql_error(1,
_(
"cannot open \"%s\""), zFile);
4442 sqlite3_finalize(pStmt));
4443 if (sql->ifd) (void)
Fclose(sql->ifd);
4447 assert(sql->buf == NULL);
4449 sql->buf =
xmalloc(sql->nbuf);
4450 azCol = malloc(
sizeof(azCol[0]) * (nCol + 1));
4451 if (azCol == NULL) {
4452 if (sql->ifd) (void)
Fclose(sql->ifd);
4455 sqlite3_finalize(pStmt));
4459 sqlite3_exec(db,
"BEGIN", 0, 0, 0));
4461 while ((zLine = local_getline(sql, NULL)) != NULL) {
4466 for (i = 0, z = zLine; *z && *z !=
'\n' && *z !=
'\r'; z++) {
4467 if (*z == sql->separator[0] && !strncmp(z, sql->separator, nSep)) {
4471 azCol[
i] = &z[nSep];
4477 if (i + 1 != nCol) {
4479 _(
"%s line %d: expected %d columns of data but found %d"),
4480 zFile, lineno, nCol, i + 1);
4481 zCommit =
"ROLLBACK";
4485 for (i = 0; i < nCol; i++)
4487 sqlite3_bind_text(pStmt, i + 1, azCol[i], -1, SQLITE_STATIC));
4489 sqlite3_step(pStmt));
4491 sqlite3_reset(pStmt));
4494 sqlite3 * db = (sqlite3 *)sql->I;
4495 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4497 zCommit =
"ROLLBACK";
4502 azCol =
_free(azCol);
4503 if (sql->ifd) (void)
Fclose(sql->ifd);
4505 sql->buf =
_free(sql->buf);
4508 sqlite3_finalize(pStmt));
4510 sqlite3_exec(db, zCommit, 0, 0, 0));
4512 if (c ==
'i' && !strncmp(azArg[0],
"indices", n) && nArg < 3) {
4514 uint32_t _flags = sql->flags;
4515 uint32_t _mode = sql->mode;
4517 char *zErrMsg = NULL;
4519 db = (sqlite3 *)sql->I;
4520 sql->flags &= ~RPMSQL_FLAGS_SHOWHDR;
4521 sql->mode = RPMSQL_MODE_LIST;
4523 t =
rpmExpand(
"SELECT name FROM sqlite_master"
4524 " WHERE type='index' AND name NOT LIKE 'sqlite_%'"
4526 "SELECT name FROM sqlite_temp_master"
4527 " WHERE type='index'"
4528 " ORDER BY 1", NULL);
4530 sqlite3_exec(db, t, callback, sql, &zErrMsg));
4533 t =
rpmExpand(
"SELECT name FROM sqlite_master"
4534 " WHERE type='index' AND tbl_name LIKE '", azArg[1],
"'",
4536 "SELECT name FROM sqlite_temp_master"
4537 " WHERE type='index' AND tbl_name LIKE '", azArg[1],
"'",
4538 " ORDER BY 1", NULL);
4540 sqlite3_exec(db, t, callback, sql, &zErrMsg));
4544 rpmsql_error(1,
"%s", zErrMsg);
4545 sqlite3_free(zErrMsg);
4549 rpmsql_error(1,
_(
"querying sqlite_master and sqlite_temp_master"));
4554 sql->flags = _flags;
4557 #ifdef SQLITE_ENABLE_IOTRACE
4558 if (c ==
'i' && !strncmp(azArg[0],
"iotrace", n)) {
4559 extern void (*sqlite3IoTrace) (
const char *, ...);
4560 rc = rpmsqlFOpen((nArg >= 2 ? azArg[1] : NULL), &sql->tfd);
4561 sqlite3IoTrace = (sql->tfd ? iotracePrintf : NULL);
4565 if (c ==
'l' && !strncmp(azArg[0],
"load", n) && nArg >= 2) {
4566 const char *zFile, *zProc;
4569 zProc = nArg >= 3 ? azArg[2] : 0;
4572 db = (sqlite3 *)sql->I;
4573 rc =
rpmsqlCmd(sql,
"load_extension", db,
4574 sqlite3_load_extension(db, zFile, zProc, &zErrMsg));
4576 rpmsql_error(1,
"%s", zErrMsg);
4577 sqlite3_free(zErrMsg);
4583 if (c ==
'l' && !strncmp(azArg[0],
"log", n) && nArg >= 1) {
4585 (void) rpmsqlFOpen((nArg >= 2 ? azArg[1] : NULL), &sql->lfd);
4587 if (c ==
'm' && !strncmp(azArg[0],
"mode", n) && nArg == 2) {
4588 int n2 = strlen30(azArg[1]);
4589 if ((n2 == 4 && !strncmp(azArg[1],
"line", n2))
4590 || (n2 == 5 && !strncmp(azArg[1],
"lines", n2))) {
4591 sql->mode = RPMSQL_MODE_LINE;
4592 }
else if ((n2 == 6 && !strncmp(azArg[1],
"column", n2))
4593 || (n2 == 7 && !strncmp(azArg[1],
"columns", n2))) {
4594 sql->mode = RPMSQL_MODE_COLUMN;
4595 }
else if (n2 == 4 && !strncmp(azArg[1],
"list", n2)) {
4596 sql->mode = RPMSQL_MODE_LIST;
4597 }
else if (n2 == 4 && !strncmp(azArg[1],
"html", n2)) {
4598 sql->mode = RPMSQL_MODE_HTML;
4599 }
else if (n2 == 3 && !strncmp(azArg[1],
"tcl", n2)) {
4600 sql->mode = RPMSQL_MODE_TCL;
4601 }
else if (n2 == 3 && !strncmp(azArg[1],
"csv", n2)) {
4602 sql->mode = RPMSQL_MODE_CSV;
4603 (void)
stpcpy(sql->separator,
",");
4604 }
else if (n2 == 4 && !strncmp(azArg[1],
"tabs", n2)) {
4605 sql->mode = RPMSQL_MODE_LIST;
4606 (void)
stpcpy(sql->separator,
"\t");
4607 }
else if (n2 == 6 && !strncmp(azArg[1],
"insert", n2)) {
4608 sql->mode = RPMSQL_MODE_INSERT;
4609 set_table_name(sql,
"table");
4611 rpmsql_error(1,
_(
"mode should be one of: %s"),
4612 "column csv html insert line list tabs tcl");
4616 if (c ==
'm' && !strncmp(azArg[0],
"mode", n) && nArg == 3) {
4617 int n2 = strlen30(azArg[1]);
4618 if (n2 == 6 && !strncmp(azArg[1],
"insert", n2)) {
4619 sql->mode = RPMSQL_MODE_INSERT;
4620 set_table_name(sql, azArg[2]);
4622 rpmsql_error(1,
_(
"invalid arguments: "
4623 " \"%s\". Enter \".help\" for help"), azArg[2]);
4627 if (c ==
'n' && !strncmp(azArg[0],
"nullvalue", n) && nArg == 2) {
4628 (void)
stpncpy(sql->nullvalue, azArg[1],
sizeof(sql->nullvalue)-1);
4630 if (c ==
'o' && !strncmp(azArg[0],
"output", n) && nArg == 2) {
4631 rc = rpmsqlFOpen((nArg >= 2 ? azArg[1] : NULL), &sql->ofd);
4634 sql->outfile =
_free(sql->outfile);
4636 sql->outfile =
xstrdup(azArg[1]);
4638 sql->ofd =
fdDup(STDOUT_FILENO);
4639 sql->outfile =
xstrdup(
"stdout");
4642 if (c ==
'p' && !strncmp(azArg[0],
"prompt", n)
4643 && (nArg == 2 || nArg == 3)) {
4645 sql->zPrompt =
_free(sql->zPrompt);
4646 sql->zPrompt =
xstrdup(azArg[1]);
4649 sql->zContinue =
_free(sql->zContinue);
4650 sql->zContinue =
xstrdup(azArg[2]);
4653 if (c ==
'q' && !strncmp(azArg[0],
"quit", n) && nArg == 1) {
4656 if (c ==
'r' && n >= 3 && !strncmp(azArg[0],
"read", n)
4658 FD_t _ifd = sql->ifd;
4659 sql->ifd =
Fopen(azArg[1],
"rb.fpio");
4660 if (sql->ifd == NULL ||
Ferror(sql->ifd)) {
4661 rpmsql_error(1,
_(
"cannot open \"%s\""), azArg[1]);
4665 rc = rpmsqlInput(sql);
4667 if (sql->ifd) (void)
Fclose(sql->ifd);
4670 if (c ==
'r' && n >= 3 && !strncmp(azArg[0],
"restore", n)
4671 && nArg > 1 && nArg < 4) {
4672 const char *zSrcFile;
4675 sqlite3_backup *pBackup;
4679 zSrcFile = azArg[1];
4682 zSrcFile = azArg[2];
4686 sqlite3_open(zSrcFile, &pSrc));
4689 rpmsql_error(1,
_(
"cannot open \"%s\""), zSrcFile);
4692 sqlite3_close(pSrc));
4696 db = (sqlite3 *)sql->I;
4697 pBackup = sqlite3_backup_init(db, zDb, pSrc,
"main");
4699 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4701 sqlite3_close(pSrc));
4704 while ((rc = sqlite3_backup_step(pBackup, 100)) == SQLITE_OK
4705 || rc == SQLITE_BUSY)
4707 if (rc == SQLITE_BUSY) {
4708 if (nTimeout++ >= 3)
4713 sqlite3_backup_finish(pBackup);
4720 rpmsql_error(1,
_(
"source database is busy"));
4724 rpmsql_error(1,
"%s", sqlite3_errmsg(db));
4729 sqlite3_close(pSrc));
4731 if (c ==
's' && !strncmp(azArg[0],
"schema", n) && nArg < 3) {
4733 uint32_t _flags = sql->flags;
4734 uint32_t _mode = sql->mode;
4737 db = (sqlite3 *)sql->I;
4738 sql->flags &= ~RPMSQL_FLAGS_SHOWHDR;
4739 sql->mode = RPMSQL_MODE_SEMI;
4742 for (i = 0; azArg[1][
i]; i++)
4743 azArg[1][i] = (
char) tolower(azArg[1][i]);
4744 if (!strcmp(azArg[1],
"sqlite_master")) {
4745 char *new_argv[2], *new_colv[2];
4746 new_argv[0] =
"CREATE TABLE sqlite_master (\n"
4750 " rootpage integer,\n" " sql text\n" ")";
4752 new_colv[0] =
"sql";
4754 callback(sql, 1, new_argv, new_colv);
4756 }
else if (!strcmp(azArg[1],
"sqlite_temp_master")) {
4757 char *new_argv[2], *new_colv[2];
4758 new_argv[0] =
"CREATE TEMP TABLE sqlite_temp_master (\n"
4762 " rootpage integer,\n" " sql text\n" ")";
4764 new_colv[0] =
"sql";
4766 callback(sql, 1, new_argv, new_colv);
4771 " (SELECT sql sql, type type, tbl_name tbl_name, name name"
4772 " FROM sqlite_master UNION ALL"
4773 " SELECT sql, type, tbl_name, name FROM sqlite_temp_master)"
4774 " WHERE tbl_name LIKE '", azArg[1],
"'"
4775 " AND type!='meta' AND sql NOTNULL "
4776 "ORDER BY substr(type,2,1), name", NULL);
4778 sqlite3_exec(db, t, callback, sql, &zErrMsg));
4782 sql->flags = _flags;
4787 " (SELECT sql sql, type type, tbl_name tbl_name, name name"
4788 " FROM sqlite_master UNION ALL"
4789 " SELECT sql, type, tbl_name, name FROM sqlite_temp_master) "
4790 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'"
4791 "ORDER BY substr(type,2,1), name",
4792 callback, sql, &zErrMsg));
4795 rpmsql_error(1,
"%s", zErrMsg);
4796 sqlite3_free(zErrMsg);
4798 }
else if (rc != SQLITE_OK) {
4799 rpmsql_error(1,
_(
"querying schema information"));
4805 if (c ==
's' && !strncmp(azArg[0],
"separator", n) && nArg == 2) {
4806 (void)
stpncpy(sql->separator, azArg[1],
sizeof(sql->separator)-1);
4808 if (c ==
's' && !strncmp(azArg[0],
"show", n) && nArg == 1) {
4810 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"echo",
F_ISSET(sql, ECHO) ?
"on" :
"off");
4811 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"explain",
4812 sql->explainPrev.valid ?
"on" :
"off");
4813 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"headers",
4814 F_ISSET(sql, SHOWHDR) ?
"on" :
"off");
4815 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"mode", modeDescr[sql->mode]);
4816 rpmsqlFprintf(sql,
"%9.9s: ",
"nullvalue");
4817 output_c_string(sql, sql->nullvalue);
4818 rpmsqlFprintf(sql,
"\n");
4819 rpmsqlFprintf(sql,
"%9.9s: %s\n",
"output",
4820 (sql->outfile ? sql->outfile :
"stdout"));
4821 rpmsqlFprintf(sql,
"%9.9s: ",
"separator");
4822 output_c_string(sql, sql->separator);
4823 rpmsqlFprintf(sql,
"\n");
4824 rpmsqlFprintf(sql,
"%9.9s: ",
"width");
4826 i < (int) ArraySize(sql->colWidth) && sql->colWidth[
i] != 0;
4829 rpmsqlFprintf(sql,
"%d ", sql->colWidth[i]);
4831 rpmsqlFprintf(sql,
"\n");
4833 if (c ==
't' && n > 1 && !strncmp(azArg[0],
"tables", n) && nArg < 3) {
4838 db = (sqlite3 *)sql->I;
4841 sqlite3_get_table(db,
4842 "SELECT name FROM sqlite_master "
4843 "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%' "
4845 "SELECT name FROM sqlite_temp_master "
4846 "WHERE type IN ('table','view') "
4848 &azResult, &nRow, 0, &zErrMsg));
4851 t =
rpmExpand(
"SELECT name FROM sqlite_master "
4852 " WHERE type IN ('table','view') AND name LIKE '", azArg[1],
"'"
4854 "SELECT name FROM sqlite_temp_master"
4855 " WHERE type IN ('table','view') AND name LIKE '", azArg[1],
"'"
4856 "ORDER BY 1", NULL);
4858 sqlite3_get_table(db, t, &azResult, &nRow, 0,&zErrMsg));
4862 rpmsql_error(1,
"%s", zErrMsg);
4863 sqlite3_free(zErrMsg);
4866 rpmsql_error(1,
_(
"querying sqlite_master and sqlite_temp_master"));
4869 int len, maxlen = 0;
4871 int nPrintCol, nPrintRow;
4872 for (i = 1; i <= nRow; i++) {
4873 if (azResult[i] == 0)
4875 len = strlen30(azResult[i]);
4879 nPrintCol = 80 / (maxlen + 2);
4882 nPrintRow = (nRow + nPrintCol - 1) / nPrintCol;
4883 for (i = 0; i < nPrintRow; i++) {
4884 for (j = i + 1; j <= nRow; j += nPrintRow) {
4885 char *zSp = j <= nPrintRow ?
"" :
" ";
4886 rpmsqlFprintf(sql,
"%s%-*s", zSp, maxlen,
4887 azResult[j] ? azResult[j] :
"");
4889 rpmsqlFprintf(sql,
"\n");
4892 sqlite3_free_table(azResult);
4894 if (c ==
't' && n > 4 && !strncmp(azArg[0],
"timeout", n) && nArg == 2) {
4896 db = (sqlite3 *)sql->I;
4897 (
void)
rpmsqlCmd(sql,
"busy_timeout", db,
4898 sqlite3_busy_timeout(db, atoi(azArg[1])));
4900 if (HAS_TIMER && c ==
't' && n >= 5
4901 && !strncmp(azArg[0],
"timer", n) && nArg == 2) {
4902 sql->enableTimer = booleanValue(azArg[1]);
4904 if (c ==
'w' && !strncmp(azArg[0],
"width", n) && nArg > 1) {
4906 assert(nArg <= ArraySize(azArg));
4907 for (j = 1; j < nArg && j < ArraySize(sql->colWidth); j++)
4908 sql->colWidth[j - 1] = atoi(azArg[j]);
4911 rpmsql_error(1,
_(
"unknown command or invalid arguments: "
4912 " \"%s\". Enter \".help\" for help"), azArg[0]);
4923 #if defined(WITH_SQLITE)
4932 static int _contains_semicolon(
const char *z,
int N)
4936 for (i = 0; i < N; i++) {
4942 SQLDBG((stderr,
"<-- %s(%s) rc %d\n", __FUNCTION__, z, rc));
4950 static int _all_whitespace(
const char *z)
4955 if (
xisspace(*(
unsigned char *) z))
4957 if (*z ==
'/' && z[1] ==
'*') {
4959 while (*z && (*z !=
'*' || z[1] !=
'/'))
4968 if (*z ==
'-' && z[1] ==
'-') {
4970 while (*z && *z !=
'\n')
4980 SQLDBG((stderr,
"<-- %s(%s) rc %d\n", __FUNCTION__, z, rc));
4990 static int _is_command_terminator(
const char *zLine)
4994 while (
xisspace(*(
unsigned char *) zLine))
4996 if (zLine[0] ==
'/' && _all_whitespace(&zLine[1]))
4999 && _all_whitespace(&zLine[2]))
5003 SQLDBG((stderr,
"<-- %s(%s) rc %d\n", __FUNCTION__, zLine, rc));
5014 static int _is_complete(
char *zSql,
int nSql)
5020 zSql[nSql + 1] =
'\0';
5021 rc = sqlite3_complete(zSql);
5024 SQLDBG((stderr,
"<-- %s(%s) rc %d\n", __FUNCTION__, zSql, rc));
5038 static int rpmsqlInput(
rpmsql sql)
5040 sqlite3 * db = (sqlite3 *) sql->I;
5051 char * _buf = sql->buf;
5052 size_t _nbuf = sql->nbuf;
5054 SQLDBG((stderr,
"--> %s(%p)\n", __FUNCTION__, sql));
5059 sql->buf =
xmalloc(sql->nbuf);
5061 while (errCnt == 0 || !
F_ISSET(sql, BAIL) ||
F_ISSET(sql, PROMPT))
5063 if (sql->ofd)
Fflush(sql->ofd);
5064 zLine = rpmsqlInputOneLine(sql, zSql);
5073 if ((zSql == NULL || zSql[0] ==
'\0') && _all_whitespace(zLine))
5075 if (zLine && zLine[0] ==
'.' && nSql == 0) {
5077 rpmsqlFprintf(sql,
"%s\n", zLine);
5078 rc = rpmsqlMetaCommand(sql, zLine);
5085 if (_is_command_terminator(zLine) && _is_complete(zSql, nSql))
5086 memcpy(zLine,
";", 2);
5090 for (i = 0; zLine[
i] &&
xisspace((
unsigned char) zLine[i]); i++)
5092 if (zLine[i] !=
'\0') {
5093 nSql = strlen30(zLine);
5095 memcpy(zSql, zLine, nSql + 1);
5099 int len = strlen30(zLine);
5100 zSql =
xrealloc(zSql, nSql + len + 4);
5101 zSql[nSql++] =
'\n';
5102 memcpy(&zSql[nSql], zLine, len + 1);
5105 if (zSql && _contains_semicolon(&zSql[nSqlPrior], nSql - nSqlPrior)
5106 && sqlite3_complete(zSql)) {
5109 db = (sqlite3 *)sql->I;
5111 rc = _rpmsqlShellExec(sql, zSql, _rpmsqlShellCallback, &zErrMsg);
5113 if (rc || zErrMsg) {
5117 "near line %d: ", startline);
5120 rpmsql_error(1,
"%s%s", zPrefix,
5121 zErrMsg ? zErrMsg : sqlite3_errmsg(db));
5122 zErrMsg =
_free(zErrMsg);
5130 if (!_all_whitespace(zSql))
5131 rpmsql_error(1,
_(
"incomplete SQL: %s"), zSql);
5135 sql->buf =
_free(sql->buf);
5139 SQLDBG((stderr,
"<-- %s(%p) rc %d\n", __FUNCTION__, sql, errCnt));
5152 static int rpmsqlInitRC(
rpmsql sql,
const char *sqliterc)
5156 SQLDBG((stderr,
"--> %s(%p,%s)\n", __FUNCTION__, sql, sqliterc));
5160 if (sqliterc == NULL)
5161 sqliterc = sql->zInitrc;
5163 FD_t _ifd = sql->ifd;
5164 sql->ifd =
Fopen(sqliterc,
"rb.fpio");
5165 if (!(sql->ifd == NULL ||
Ferror(sql->ifd))) {
5166 if (
F_ISSET(sql, INTERACTIVE))
5167 rpmsql_error(0,
"-- Loading resources from %s", sqliterc);
5168 rc = rpmsqlInput(sql);
5170 if (sql->ifd) (void)
Fclose(sql->ifd);
5174 SQLDBG((stderr,
"<-- %s(%p,%s) rc %d\n", __FUNCTION__, sql, sqliterc, rc));
5183 #if defined(WITH_SQLITE)
5187 static void rpmsqlArgCallback(poptContext con,
5188 enum poptCallbackReason reason,
5189 const struct poptOption *opt,
5197 if (opt->arg == NULL)
5200 assert(arg != NULL);
5201 (void)
stpncpy(sql->separator, arg,
sizeof(sql->separator)-1);
5204 assert(arg != NULL);
5205 (void)
stpncpy(sql->nullvalue, arg,
sizeof(sql->nullvalue)-1);
5208 printf(
"%s\n", sqlite3_libversion());
5213 rpmsql_error(0,
_(
"%s: Unknown callback(0x%x)\n"),
5214 __FUNCTION__, (
unsigned) opt->val);
5215 poptPrintUsage(con, stderr, 0);
5222 static struct poptOption _rpmsqlOptions[] = {
5225 POPT_ARG_CALLBACK | POPT_CBFLAG_INC_DATA | POPT_CBFLAG_CONTINUE,
5226 rpmsqlArgCallback, 0, NULL, NULL},
5229 {
"debug",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH|POPT_ARGFLAG_DOC_HIDDEN, &
_rpmsql_debug, -1,
5230 N_(
"Debug embedded SQL interpreter"), NULL},
5231 {
"create",
'\0', POPT_BIT_SET|POPT_ARGFLAG_ONEDASH|POPT_ARGFLAG_DOC_HIDDEN, &_sql.flags, RPMSQL_FLAGS_CREATE,
5232 N_(
"create database if not exists"), NULL},
5234 {
"init",
'\0', POPT_ARG_STRING|POPT_ARGFLAG_ONEDASH, &_sql.zInitFile, 0,
5235 N_(
"read/process named FILE"),
N_(
"FILE") },
5236 {
"echo",
'\0', POPT_BIT_SET|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_ECHO,
5237 N_(
"print commands before execution"), NULL },
5239 {
"load",
'\0', POPT_BIT_SET|
POPT_ARGFLAG_TOGGLE|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_NOLOAD,
5240 N_(
"disable extension loading (normally enabled)"), NULL },
5241 {
"header",
'\0', POPT_BIT_SET|
POPT_ARGFLAG_TOGGLE|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_SHOWHDR,
5242 N_(
"turn headers on or off"), NULL },
5244 {
"bail",
'\0', POPT_BIT_SET|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_BAIL,
5245 N_(
"stop after hitting an error"), NULL },
5247 {
"interactive",
'\0', POPT_BIT_SET|
POPT_ARGFLAG_TOGGLE|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_INTERACTIVE,
5248 N_(
"force interactive I/O"), NULL },
5249 {
"batch",
'\0', POPT_BIT_CLR|
POPT_ARGFLAG_TOGGLE|POPT_ARGFLAG_ONEDASH, &_sql.flags, RPMSQL_FLAGS_INTERACTIVE,
5250 N_(
"force batch I/O"), NULL },
5252 {
"column",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_COLUMN,
5253 N_(
"set output mode to 'column'"), NULL },
5254 {
"csv",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_CSV,
5255 N_(
"set output mode to 'csv'"), NULL },
5256 {
"html",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_HTML,
5257 N_(
"set output mode to HTML"), NULL },
5258 {
"line",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_LINE,
5259 N_(
"set output mode to 'line'"), NULL },
5260 {
"list",
'\0', POPT_ARG_VAL|POPT_ARGFLAG_ONEDASH, &_sql.mode, RPMSQL_MODE_LIST,
5261 N_(
"set output mode to 'list'"), NULL },
5262 {
"separator",
'\0', POPT_ARG_STRING|POPT_ARGFLAG_ONEDASH, 0,
'S',
5263 N_(
"set output field separator (|)"),
N_(
"CHAR") },
5264 {
"nullvalue",
'\0', POPT_ARG_STRING|POPT_ARGFLAG_ONEDASH, 0,
'N',
5265 N_(
"set text string for NULL values"),
N_(
"TEXT") },
5267 {
"version",
'\0', POPT_ARG_NONE|POPT_ARGFLAG_ONEDASH, 0,
'V',
5268 N_(
"show SQLite version"), NULL},
5272 N_(
"Common options for all rpmio executables:"), NULL},
5276 { NULL, (char) -1, POPT_ARG_INCLUDE_TABLE, NULL, 0,
5278 Usage: dbsql [OPTIONS] FILENAME [SQL]\n\
5279 FILENAME is the name of an SQLite database. A new database is created\n\
5280 if the file does not previously exist.\n\
5283 -help show this message\n\
5284 -init filename read/process named file\n\
5285 -echo print commands before execution\n\
5286 -[no]header turn headers on or off\n\
5287 -bail stop after hitting an error\n\
5288 -interactive force interactive I/O\n\
5289 -batch force batch I/O\n\
5290 -column set output mode to 'column'\n\
5291 -csv set output mode to 'csv'\n\
5292 -html set output mode to HTML\n\
5293 -line set output mode to 'line'\n\
5294 -list set output mode to 'list'\n\
5295 -separator 'x' set output field separator (|)\n\
5296 -nullvalue 'text' set text string for NULL values\n\
5297 -version show SQLite version\n\
5316 SQLDBG((stderr,
"==> %s(%p)\n", __FUNCTION__, sql));
5318 sql->zDestTable =
_free(sql->zDestTable);
5333 sql->buf =
_free(sql->buf);
5334 sql->buf = sql->b = NULL;
5335 sql->nbuf = sql->nb = 0;
5338 sql->zHome =
_free(sql->zHome);
5339 sql->zInitrc =
_free(sql->zInitrc);
5340 sql->zHistory =
_free(sql->zHistory);
5341 sql->zPrompt =
_free(sql->zPrompt);
5342 sql->zContinue =
_free(sql->zContinue);
5344 sql->outfile =
_free(sql->outfile);
5346 sql->zDbFilename =
_free(sql->zDbFilename);
5347 sql->zInitFile =
_free(sql->zInitFile);
5349 #if defined(WITH_SQLITE)
5351 sqlite3 * db = (sqlite3 *)sql->I;
5370 if (_rpmsqlPool == NULL) {
5376 memset(((
char *)sql)+
sizeof(sql->_item), 0,
sizeof(*sql)-
sizeof(sql->_item));
5382 const char ** av = sql->av;
5389 #if defined(WITH_SQLITE)
5394 static void rpmsqlInitPopt(
rpmsql sql,
int ac,
char ** av, poptOption tbl)
5400 if (av == NULL || av[0] == NULL || av[1] == NULL)
5403 con = poptGetContext(av[0], ac, (
const char **)av, tbl, 0);
5406 while ((rc = poptGetNextOpt(con)) > 0) {
5407 const char * arg = poptGetOptArg(con);
5412 rpmsql_error(0,
_(
"%s: option table misconfigured (%d)\n"),
5419 SQLDBG((stderr,
"%s: poptGetNextOpt rc(%d): %s\n", __FUNCTION__, rc, poptStrerror(rc)));
5422 sql->flags = _sql.flags;
5423 sql->mode = _sql.mode;
5424 if (_sql.zInitFile) {
5425 sql->zInitFile =
_free(sql->zInitFile);
5426 sql->zInitFile = _sql.zInitFile;
5427 _sql.zInitFile = NULL;
5429 memcpy(sql->separator, _sql.separator,
sizeof(sql->separator));
5430 memcpy(sql->nullvalue, _sql.nullvalue,
sizeof(sql->nullvalue));
5435 con = poptFreeContext(con);
5439 if (sql->separator[0] ==
'\0')
5440 switch (sql->mode) {
5442 case RPMSQL_MODE_LIST: (void)
stpcpy(sql->separator,
"|");
break;
5443 case RPMSQL_MODE_CSV: (void)
stpcpy(sql->separator,
",");
break;
5446 SQLDBG((stderr,
"<== %s(%p, %p[%u], %p)\n", __FUNCTION__, sql, av, (
unsigned)ac, tbl));
5453 (flags & 0x80000000) ?
rpmsqlI() :
5457 SQLDBG((stderr,
"==> %s(%p[%u], 0x%x)\n", __FUNCTION__, av, (
unsigned)ac, flags));
5463 #if defined(WITH_SQLITE)
5466 static int _oneshot;
5467 sqlite3 * db = NULL;
5471 #if defined(SQLITE_CONFIG_LOG)
5472 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, sql);
5474 sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
5479 memset(&_sql, 0,
sizeof(_sql));
5480 sql->flags = _sql.flags =
flags;
5481 sql->mode = _sql.mode = RPMSQL_MODE_LIST;
5483 rpmsqlInitPopt(sql, ac, av, (poptOption) _rpmsqlOptions);
5486 if (sql->av && sql->av[0]) {
5487 sql->zDbFilename =
xstrdup(sql->av[0]);
5491 sqlite3_open(sql->zDbFilename, &db));
5492 sql->I = (
void *) db;
5495 sql->zDbFilename =
xstrdup(
":memory:");
5498 if (sql->zInitFile ||
F_ISSET(sql, INTERACTIVE)) {
5499 sql->ofd =
fdDup(STDOUT_FILENO);
5500 xx = rpmsqlInitRC(sql, sql->zInitFile);
5501 if (sql->ofd) (void)
Fclose(sql->ofd);
5503 rpmsqlInitPopt(sql, ac, av, (poptOption) _rpmsqlOptions);
5509 static const char _zInitrc[] =
"/.sqliterc";
5510 static const char _zHistory[] =
"/.sqlite_history";
5512 sql->zHome =
_free(sql->zHome);
5513 {
char * t =
getenv(
"HOME");
5514 sql->zHome =
xstrdup((t ? t :
"/"));
5516 sql->zInitrc =
_free(sql->zInitrc);
5517 sql->zInitrc =
rpmGetPath(sql->zHome, _zInitrc, NULL);
5518 sql->zHistory =
_free(sql->zHistory);
5519 sql->zHistory =
rpmGetPath(sql->zHome, _zHistory, NULL);
5525 if (sql->zPrompt == NULL) {
5526 char * t =
xstrdup((av && av[0] ? av[0] :
"sql"));
5527 char * bn = basename(t);
5528 sql->zPrompt =
_free(sql->zPrompt);
5529 sql->zPrompt =
rpmExpand(bn,
"> ", NULL);
5531 sql->zContinue =
_free(sql->zContinue);
5532 sql->zContinue = t =
xstrdup(sql->zPrompt);
5533 while (*t && *t !=
'>')
5543 if (
F_ISSET(sql, INTERACTIVE)) {
5544 if (sql->ofd == NULL)
5545 sql->ofd =
fdDup(STDOUT_FILENO);
5547 if (sql->iob == NULL)
5558 SQLDBG((stderr,
"==> %s(%p,%p[%u]) \"%s\"\n", __FUNCTION__, sql, str, (
unsigned)(str ? strlen(str) : 0), str));
5559 SQLDBG((stderr,
"==========>\n%s\n<==========\n", str));
5561 if (sql == NULL) sql =
rpmsqlI();
5563 #if defined(WITH_SQLITE)
5565 const char * s =
str;
5574 uint32_t _flags = sql->flags;
5575 FD_t _ofd = sql->ofd;
5576 FD_t _ifd = sql->ifd;
5578 SQLDBG((stderr,
"*** %s: INTERACTIVE\n", __FUNCTION__));
5579 sql->flags |= RPMSQL_FLAGS_INTERACTIVE;
5580 if (sql->ofd == NULL)
5581 sql->ofd =
fdDup(STDOUT_FILENO);
5584 extern char *db_full_version(
int *,
int *,
int *,
int *,
int *);
5585 fprintf(sql->out,
"%s\n"
5586 "Enter \".help\" for instructions\n"
5587 "Enter SQL statements terminated with a \";\"\n",
5588 db_full_version(NULL, NULL, NULL, NULL, NULL));
5593 "SQLite version ", sqlite3_libversion(),
"\n",
5594 #
if SQLITE_VERSION_NUMBER > 3006015
5595 "\t(", sqlite3_sourceid(),
")\n",
5597 "Enter \".help\" for instructions\n",
5598 "Enter SQL statements terminated with a \";\"\n", NULL);
5600 nw =
Fwrite(t, 1, nb, sql->ofd);
5604 #if defined(HAVE_READLINE) && HAVE_READLINE==1
5611 sql->ifd =
Fdopen(
fdDup(fileno(stdin)),
"rb.fpio");
5614 sql->flags |= RPMSQL_FLAGS_PROMPT;
5615 rc = rpmsqlInput(sql);
5616 sql->flags &= ~RPMSQL_FLAGS_PROMPT;
5618 if (sql->ifd) (void)
Fclose(sql->ifd);
5621 if (sql->zHistory) {
5628 sql->
flags = _flags;
5631 if (!strcmp(s,
"-") || !strcmp(s,
"stdin")) {
5632 FD_t _ofd = sql->ofd;
5633 SQLDBG((stderr,
"*** %s: STDIN\n", __FUNCTION__));
5635 if (sql->ofd == NULL) sql->ofd =
fdDup(STDOUT_FILENO);
5638 assert(sql->ifd == NULL);
5639 sql->ifd =
Fdopen(
fdDup(fileno(stdin)),
"rb.fpio");
5642 rc = rpmsqlInput(sql);
5644 if (sql->ifd) (void)
Fclose(sql->ifd);
5647 if (_ofd == NULL) (void)
Fclose(sql->ofd);
5653 FD_t _ifd = sql->ifd;
5654 SQLDBG((stderr,
"*** %s: FILE\n", __FUNCTION__));
5655 sql->ifd =
Fopen(s,
"rb.fpio");
5656 if (!(sql->ifd == NULL ||
Ferror(sql->ifd))) {
5657 rc = rpmsqlInput(sql);
5659 if (sql->ifd) (void)
Fclose(sql->ifd);
5663 SQLDBG((stderr,
"*** %s: STRING\n", __FUNCTION__));
5666 rc = rpmsqlMetaCommand(sql, t);
5670 char * zErrMsg = NULL;
5672 db = (sqlite3 *)sql->I;
5673 rc = _rpmsqlShellExec(sql, s, _rpmsqlShellCallback, &zErrMsg);
5675 rpmsql_error(1,
"%s", zErrMsg);
5676 zErrMsg =
_free(zErrMsg);
5678 }
else if (rc != 0) {
5679 rpmsql_error(1,
_(
"unable to process SQL \"%s\""), s);
5688 SQLDBG((stderr,
"==========>\n%s\n<==========\n",
rpmiobStr(sql->iob)));
5696 SQLDBG((stderr,
"<== %s(%p,%p[%u]) rc %d\n", __FUNCTION__, sql, str, (
unsigned)(str ? strlen(str) : 0), rc));
const char const double d
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.
const char const char size_t len
char * getenv(const char *name)
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.
static char * _rpmvtAppendCols(rpmvt vt, const char **av)
char * rpmGetPath(const char *path,...)
Return (malloc'ed) expanded, canonicalized, file path.
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.
static struct rpmsqlVMT_s __VMT[]
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)
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)
const char const bson_bool_t v
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.
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)
const char const char int arg
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.
const char const bson int mongo_write_concern int flags
void argvPrint(const char *msg, ARGV_t argv, FILE *fp)
Print argv array elements.
static void rpmvtFini(void *_VT)
rpmvt pool destructor.
enum rpmRC_e rpmRC
RPM return codes.
int Ferror(FD_t fd)
ferror(3) clone.
char * rpmiobStr(rpmiob iob)
Return I/O buffer (as string).
static const char * hasSqlType(const char *s)
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.
const char const bson const bson bson * out
static int vsnprintf(char *buf, int nb, const char *fmt, va_list ap)
struct dirent * Readdir(DIR *dir)
readdir(3) clone.
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.
static char * _rpmvtJoin(const char *a, const char **argv, const char *z)
char * stpcpy(char *dest, const char *src)
rpmvc rpmvcNew(rpmvt vt, int nrows)
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
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.
int Closedir(DIR *dir)
closedir(3) clone.
const char const char * pattern
DIR * Opendir(const char *path)
opendir(3) clone.
struct poptOption rpmioAllPoptTable[]
Popt option table for options shared by all modes and executables.
static rpmvc rpmvcGetPool(rpmioPool pool)
const char ** rpmsqlArgv(rpmsql sql, int *argcp)
Return arguments from a sql interpreter.
const char const bson int num
__attribute__((visibility("hidden"))) int mayAddToFilesAwaitingFiletriggers(const char *rootDir