18 #if defined(_WIN32) || defined(_WIN64)
25 #include <libxml/parser.h>
26 #include <libxml/tree.h>
27 #include <libxml/xpath.h>
29 #include <libxslt/xslt.h>
30 #include <libxslt/transform.h>
31 #include <libxslt/xsltutils.h>
37 #include <sqlite3ext.h>
38 static SQLITE_EXTENSION_INIT1
136 sqlite3_vtab **vtabp,
char **errp)
138 int rc = SQLITE_ERROR;
141 xt = sqlite3_malloc(
sizeof (
XTAB));
144 *errp = sqlite3_mprintf(
"out of memory");
147 memset(xt, 0,
sizeof (
XTAB));
153 xt->
idocs = sqlite3_malloc(xt->
sdoc * sizeof (
int));
158 rc = sqlite3_declare_vtab(db,
160 " DOCID INTEGER PRIMARY KEY,"
163 " OPTIONS HIDDEN INTEGER,"
164 " ENCODING HIDDEN TEXT,"
165 " BASEURL HIDDEN TEXT,"
166 " XMLDUMP HIDDEN TEXT"
168 if (rc != SQLITE_OK) {
169 sqlite3_free(xt->
idocs);
171 *errp = sqlite3_mprintf(
"table definition failed (error %d)", rc);
192 const char *
const *argv,
193 sqlite3_vtab **vtabp,
char **errp)
212 sqlite3_mutex_enter(xm->
mutex);
213 for (i = 0; xm->
docs && (i < xt->
ndoc); i++) {
215 if ((n >= 0) && (n < xm->
sdoc)) {
216 xmlDocPtr doc = xm->
docs[n].
doc;
228 sqlite3_mutex_leave(xm->
mutex);
230 sqlite3_free(xt->
idocs);
268 xpath_open(sqlite3_vtab *vtab, sqlite3_vtab_cursor **cursorp)
270 XCSR *xc = sqlite3_malloc(
sizeof (
XCSR));
299 xmlXPathFreeObject(xp->
pobj);
302 xmlXPathFreeContext(xp->
pctx);
332 xmlNodePtr node, parent = 0;
337 if (xp == xc->
first) {
339 }
else if (parent != xp->parent) {
350 if (xp->pobj && (xp->pobj->type == XPATH_NODESET) &&
351 xp->pobj->nodesetval) {
352 newpos = xp->
pos + 1;
353 if (newpos < xp->pobj->nodesetval->nodeNr) {
354 node = xp->pobj->nodesetval->nodeTab[newpos];
355 if (node->parent != xp->parent) {
364 if ((pchg != 0) && (pchg != xc->
nexpr)) {
367 if (xp->pobj && (xp->pobj->type == XPATH_NODESET) &&
368 xp->pobj->nodesetval) {
369 newpos = xp->
pos + 1;
370 if (newpos < xp->pobj->nodesetval->nodeNr) {
371 node = xp->pobj->nodesetval->nodeTab[newpos];
372 if (node->parent == xp->parent) {
377 xp->pos = xp->pobj->nodesetval->nodeNr;
388 if (xp->pobj && (xp->pobj->type == XPATH_NODESET) &&
389 xp->pobj->nodesetval) {
390 newpos = xp->
pos + 1;
391 if (newpos < xp->pobj->nodesetval->nodeNr) {
395 xp->pos = xp->pobj->nodesetval->nodeNr;
427 const char *idxStr,
int argc, sqlite3_value **argv)
468 sqlite3_result_error(ctx,
"column out of bounds", -1);
473 if (xm->docs[n].doc) {
474 sqlite3_result_int(ctx, n + 1);
479 if (xm->docs[n].doc) {
483 xmlDocDumpFormatMemoryEnc(xm->docs[n].doc, &dump,
484 &dump_len,
"utf-8", 1);
486 sqlite3_result_text(ctx, (
char *) dump, dump_len,
493 sqlite3_result_null(ctx);
512 if (xm->docs[n].doc) {
513 *rowidp = (sqlite3_int64) (n + 1);
551 sqlite3_int64 *rowidp)
553 int n = -1, rc = SQLITE_ERROR;
556 xmlDocPtr doc = 0, docToFree = 0;
562 n = sqlite3_value_int(argv[0]);
563 for (i = 0; i < xt->
ndoc; i++) {
564 if ((n - 1) == xt->
idocs[i]) {
567 (xt->
ndoc - (i + 1)) * sizeof (
int));
572 if ((k >= 0) && xm->
mutex) {
577 }
else if ((argc > 1) && (sqlite3_value_type(argv[0]) == SQLITE_NULL)) {
580 int opts = (XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET);
583 if (sqlite3_value_type(argv[1]) != SQLITE_NULL) {
585 sqlite3_free(vtab->zErrMsg);
587 vtab->zErrMsg = sqlite3_mprintf(
"ROWID must be NULL");
588 rc = SQLITE_CONSTRAINT;
591 if (sqlite3_value_type(argv[2]) != SQLITE_NULL) {
592 docid = sqlite3_value_int(argv[2]);
593 if ((sqlite3_value_type(argv[3]) != SQLITE_NULL) ||
594 (sqlite3_value_type(argv[4]) != SQLITE_NULL)) {
596 sqlite3_free(vtab->zErrMsg);
598 vtab->zErrMsg = sqlite3_mprintf(
"XML and PATH must be NULL");
599 rc = SQLITE_CONSTRAINT;
602 sqlite3_mutex_enter(xm->
mutex);
603 for (i = 0; xm->
docs && (i < xt->
ndoc); i++) {
604 if ((docid - 1) == xt->
idocs[i]) {
605 sqlite3_mutex_leave(xm->
mutex);
607 sqlite3_free(vtab->zErrMsg);
609 vtab->zErrMsg = sqlite3_mprintf(
"constraint violation");
610 rc = SQLITE_CONSTRAINT;
614 if ((docid > 0) && (docid <= xm->sdoc)) {
620 sqlite3_mutex_leave(xm->
mutex);
623 sqlite3_free(vtab->zErrMsg);
625 vtab->zErrMsg = sqlite3_mprintf(
"invalid DOCID");
630 if (((sqlite3_value_type(argv[3]) == SQLITE_NULL) &&
631 (sqlite3_value_type(argv[4]) == SQLITE_NULL)) ||
632 ((sqlite3_value_type(argv[3]) != SQLITE_NULL) &&
633 (sqlite3_value_type(argv[4]) != SQLITE_NULL))) {
635 sqlite3_free(vtab->zErrMsg);
637 vtab->zErrMsg = sqlite3_mprintf(
"specify one of XML or PATH");
638 rc = SQLITE_CONSTRAINT;
641 if (sqlite3_value_type(argv[5]) != SQLITE_NULL) {
642 opts = sqlite3_value_int(argv[5]);
644 if (sqlite3_value_type(argv[6]) != SQLITE_NULL) {
645 enc = (
char *) sqlite3_value_text(argv[6]);
647 if (sqlite3_value_type(argv[4]) != SQLITE_NULL) {
648 doc = xmlReadFile((
char *) sqlite3_value_text(argv[4]), enc, opts);
652 if (sqlite3_value_type(argv[7]) != SQLITE_NULL) {
653 url = (
char *) sqlite3_value_text(argv[7]);
655 doc = xmlReadMemory(sqlite3_value_blob(argv[3]),
656 sqlite3_value_bytes(argv[3]),
657 url ? url :
"", enc, opts);
661 sqlite3_free(vtab->zErrMsg);
663 vtab->zErrMsg = sqlite3_mprintf(
"read error");
669 int *idocs = sqlite3_realloc(xt->
idocs, xt->
sdoc +
681 sqlite3_mutex_enter(xm->
mutex);
684 128 * sizeof (
XDOC));
687 sqlite3_mutex_leave(xm->
mutex);
692 memset(docs, 0, 128 *
sizeof (
XDOC));
695 for (i = 0; i < xm->
sdoc; i++) {
701 *rowidp = (sqlite3_int64) (i + 1);
707 sqlite3_mutex_leave(xm->
mutex);
711 sqlite3_free(vtab->zErrMsg);
713 vtab->zErrMsg = sqlite3_mprintf(
"UPDATE not supported");
717 xmlFreeDoc(docToFree);
718 }
else if (doc && (n >= 0)) {
719 sqlite3_mutex_enter(xm->
mutex);
727 sqlite3_mutex_leave(xm->
mutex);
732 sqlite3_free(vtab->zErrMsg);
734 vtab->zErrMsg = sqlite3_mprintf(
"out of memory");
758 sqlite3_value **argv)
760 XTAB *xt = (
XTAB *) sqlite3_user_data(ctx);
764 xmlXPathContextPtr pctx = 0;
765 xmlXPathObjectPtr pobj = 0;
769 if ((argc < 2) || !sqlite3_value_text(argv[1])) {
770 sqlite3_result_error(ctx,
"wrong arguments", -1);
774 sqlite3_result_error(ctx,
"not in virtual table context", -1);
778 sqlite3_result_error(ctx,
"cursor out of bounds", -1);
783 sqlite3_result_error(ctx,
"no docid", -1);
786 p = (
char *) sqlite3_value_text(argv[1]);
788 sqlite3_result_error(ctx,
"no or empty XPath expression", -1);
793 if (!strcmp(p, xp->
expr)) {
799 xp = sqlite3_malloc(
sizeof (
XEXP) + strlen(p));
801 sqlite3_result_error(ctx,
"out of memory", -1);
806 pctx = xmlXPathNewContext(xm->
docs[n].
doc);
809 sqlite3_result_error(ctx,
"out of memory", -1);
812 pobj = xmlXPathEvalExpression((xmlChar *) xp->
expr, pctx);
815 sqlite3_result_error(ctx,
"bad XPath expression", -1);
836 xmlXPathFreeObject(xp->
pobj);
840 xmlXPathFreeContext(xp->
pctx);
847 pctx = xmlXPathNewContext(xm->
docs[n].
doc);
849 sqlite3_result_error(ctx,
"out of memory", -1);
852 pobj = xmlXPathEvalExpression((xmlChar *) xp->
expr, pctx);
854 sqlite3_result_error(ctx,
"bad XPath expression", -1);
868 sqlite3_result_null(ctx);
871 if ((xp->
pobj->type == XPATH_NODESET) && xp->
pobj->nodesetval) {
872 if ((xp->
pos < 0) || (xp->
pos >= xp->
pobj->nodesetval->nodeNr)) {
874 sqlite3_result_null(ctx);
876 xmlNodePtr node = xp->
pobj->nodesetval->nodeTab[xp->
pos];
877 xmlBufferPtr buf = 0;
879 xp->
parent = node->parent;
883 p = (
char *) xmlXPathCastNodeToString(node);
884 n = xmlXPathCastStringToBoolean((xmlChar *) p);
885 sqlite3_result_int(ctx, n);
891 sqlite3_result_double(ctx,
892 xmlXPathCastNodeToNumber(node));
895 buf = xmlBufferCreate();
897 sqlite3_result_error(ctx,
"out of memory", -1);
900 xmlNodeDump(buf, xp->
doc, node, 0, 0);
901 sqlite3_result_text(ctx, (
char *) xmlBufferContent(buf),
902 xmlBufferLength(buf),
907 p = (
char *) xmlXPathCastNodeToString(node);
908 sqlite3_result_text(ctx, p, -1, SQLITE_TRANSIENT);
915 sqlite3_result_null(ctx);
922 sqlite3_result_int(ctx, xmlXPathCastToBoolean(xp->
pobj));
925 sqlite3_result_double(ctx, xmlXPathCastToNumber(xp->
pobj));
928 p = (
char *) xmlXPathCastToString(xp->
pobj);
929 sqlite3_result_text(ctx, p, -1, SQLITE_TRANSIENT);
938 xmlXPathFreeObject(pobj);
941 xmlXPathFreeContext(pctx);
1009 void (**pfunc)(sqlite3_context *,
int, sqlite3_value **),
1015 if (!strcmp(name,
"xpath_string")) {
1020 if (!strcmp(name,
"xpath_boolean")) {
1025 if (!strcmp(name,
"xpath_number")) {
1030 if (!strcmp(name,
"xpath_xml")) {
1038 #if (SQLITE_VERSION_NUMBER > 3004000)
1047 xpath_rename(sqlite3_vtab *vtab,
const char *newname)
1078 #if (SQLITE_VERSION_NUMBER > 3004000)
1107 int argc, sqlite3_value **argv)
1109 xmlDocPtr doc = 0, docToFree = 0;
1110 xmlXPathContextPtr pctx = 0;
1111 xmlXPathObjectPtr pobj = 0;
1112 XMOD *xm = (
XMOD *) sqlite3_user_data(ctx);
1117 sqlite3_result_null(ctx);
1120 if (sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
1121 index = sqlite3_value_int(argv[0]);
1123 sqlite3_result_error(ctx,
"init error", -1);
1126 sqlite3_mutex_enter(xm->
mutex);
1127 if ((index <= 0) || (index > xm->
sdoc) || !xm->
docs[index - 1].
doc) {
1128 sqlite3_mutex_leave(xm->
mutex);
1129 sqlite3_result_error(ctx,
"invalid DOCID", -1);
1132 doc = xm->
docs[index - 1].
doc;
1134 sqlite3_mutex_leave(xm->
mutex);
1136 int opts = (XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET);
1137 char *enc = 0, *url = 0;
1139 p = (
char *) sqlite3_value_blob(argv[0]);
1141 sqlite3_result_null(ctx);
1144 if ((argc > 2) && (sqlite3_value_type(argv[2]) != SQLITE_NULL)) {
1145 opts = sqlite3_value_int(argv[2]);
1147 if ((argc > 3) && (sqlite3_value_type(argv[3]) != SQLITE_NULL)) {
1148 enc = (
char *) sqlite3_value_text(argv[3]);
1150 if ((argc > 4) && (sqlite3_value_type(argv[4]) != SQLITE_NULL)) {
1151 url = (
char *) sqlite3_value_text(argv[4]);
1153 doc = xmlReadMemory(p, sqlite3_value_bytes(argv[0]),
1154 url ? url :
"", enc, opts);
1157 sqlite3_result_error(ctx,
"read error", -1);
1161 p = (
char *) sqlite3_value_text(argv[1]);
1163 sqlite3_result_null(ctx);
1166 pctx = xmlXPathNewContext(doc);
1168 sqlite3_result_error(ctx,
"out of memory", -1);
1171 pobj = xmlXPathEvalExpression((xmlChar *) p, pctx);
1173 sqlite3_result_error(ctx,
"bad XPath expression", -1);
1178 sqlite3_result_int(ctx, xmlXPathCastToBoolean(pobj));
1181 sqlite3_result_double(ctx, xmlXPathCastToNumber(pobj));
1184 if ((pobj->type == XPATH_NODESET) && pobj->nodesetval &&
1185 (pobj->nodesetval->nodeNr)) {
1186 xmlNodePtr node = pobj->nodesetval->nodeTab[0];
1187 xmlBufferPtr buf = 0;
1189 buf = xmlBufferCreate();
1191 sqlite3_result_error(ctx,
"out of memory", -1);
1194 xmlNodeDump(buf, doc, node, 0, 0);
1195 sqlite3_result_text(ctx, (
char *) xmlBufferContent(buf),
1196 xmlBufferLength(buf), SQLITE_TRANSIENT);
1199 sqlite3_result_null(ctx);
1203 p = (
char *) xmlXPathCastToString(pobj);
1204 sqlite3_result_text(ctx, p, -1, SQLITE_TRANSIENT);
1212 xmlXPathFreeObject(pobj);
1215 xmlXPathFreeContext(pctx);
1218 xmlFreeDoc(docToFree);
1221 sqlite3_mutex_enter(xm->
mutex);
1222 if (xm->
docs && index) {
1230 sqlite3_mutex_leave(xm->
mutex);
1232 xmlFreeDoc(docToFree);
1310 XMOD *xm = (
XMOD *) sqlite3_user_data(ctx);
1311 int index = 0, dump_len = 0, fmt = 1;
1313 char *enc =
"utf-8";
1316 sqlite3_result_null(ctx);
1319 index = sqlite3_value_int(argv[0]);
1321 enc = (
char *) sqlite3_value_text(argv[1]);
1327 fmt = sqlite3_value_int(argv[2]);
1330 sqlite3_result_error(ctx,
"init error", -1);
1333 sqlite3_mutex_enter(xm->
mutex);
1334 if ((index <= 0) || (index > xm->
sdoc) || !xm->
docs[index - 1].
doc) {
1335 sqlite3_mutex_leave(xm->
mutex);
1336 sqlite3_result_error(ctx,
"invalid DOCID", -1);
1339 xmlDocDumpFormatMemoryEnc(xm->
docs[index - 1].
doc, &dump, &dump_len,
1342 sqlite3_result_text(ctx, (
char *) dump, dump_len, SQLITE_TRANSIENT);
1345 sqlite3_mutex_leave(xm->
mutex);
1373 xpath_func_transform(sqlite3_context *ctx,
int argc, sqlite3_value **argv)
1375 xmlDocPtr doc = 0, docToFree = 0, res = 0;
1376 xsltStylesheetPtr cur = 0;
1377 XMOD *xm = (
XMOD *) sqlite3_user_data(ctx);
1378 int index = 0, nparams = 0, param0, i;
1380 const char **params = 0;
1383 sqlite3_result_null(ctx);
1386 if (sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
1387 index = sqlite3_value_int(argv[0]);
1389 sqlite3_result_error(ctx,
"init error", -1);
1392 sqlite3_mutex_enter(xm->
mutex);
1393 if ((index <= 0) || (index > xm->
sdoc) || !xm->
docs[index - 1].
doc) {
1394 sqlite3_mutex_leave(xm->
mutex);
1395 sqlite3_result_error(ctx,
"invalid DOCID", -1);
1398 doc = xm->
docs[index - 1].
doc;
1400 sqlite3_mutex_leave(xm->
mutex);
1404 int opts = (XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET);
1405 char *enc = 0, *url = 0;
1407 p = (
char *) sqlite3_value_blob(argv[0]);
1409 sqlite3_result_null(ctx);
1412 if ((argc > 2) && (sqlite3_value_type(argv[2]) != SQLITE_NULL)) {
1413 opts = sqlite3_value_int(argv[2]);
1415 if ((argc > 3) && (sqlite3_value_type(argv[3]) != SQLITE_NULL)) {
1416 enc = (
char *) sqlite3_value_text(argv[3]);
1418 if ((argc > 4) && (sqlite3_value_type(argv[4]) != SQLITE_NULL)) {
1419 url = (
char *) sqlite3_value_text(argv[4]);
1421 doc = xmlReadMemory(p, sqlite3_value_bytes(argv[0]),
1422 url ? url :
"", enc, opts);
1425 sqlite3_result_error(ctx,
"read error", -1);
1431 p = (
char *) sqlite3_value_text(argv[1]);
1433 sqlite3_result_null(ctx);
1436 cur = xsltParseStylesheetFile((xmlChar *) p);
1438 sqlite3_result_error(ctx,
"read error on stylesheet", -1);
1446 params = sqlite3_malloc(nparams *
sizeof (
char *));
1448 sqlite3_result_error(ctx,
"out of memory", -1);
1451 for (i = 0; i < (argc - param0); i++) {
1452 params[i] = (
const char *) sqlite3_value_text(argv[i + param0]);
1458 res = xsltApplyStylesheet(cur, doc, params);
1460 sqlite3_result_error(ctx,
"transformation failed", -1);
1466 xmlFreeDoc(docToFree);
1469 xsltSaveResultToString(&str, &i, res, cur);
1471 sqlite3_result_text(ctx, (
char *) str, i, SQLITE_TRANSIENT);
1474 sqlite3_result_null(ctx);
1479 sqlite3_free(params);
1482 xsltFreeStylesheet(cur);
1485 xmlFreeDoc(docToFree);
1488 sqlite3_mutex_enter(xm->
mutex);
1489 if (xm->
docs && index) {
1492 xmlFreeDoc(docToFree);
1495 xm->
docs[index - 1].
doc = res;
1502 sqlite3_mutex_leave(xm->
mutex);
1504 xmlFreeDoc(docToFree);
1522 int i, n, cleanup = 0;
1523 sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
1528 sqlite3_mutex_enter(mutex);
1539 sqlite3_mutex_leave(mutex);
1541 sqlite3_mutex_enter(xm->
mutex);
1548 sqlite3_mutex_leave(mutex);
1549 sqlite3_mutex_free(mutex);
1550 for (i = 0; i < n; i++) {
1552 xmlFreeDoc(docs->
doc);
1575 sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
1578 return SQLITE_NOMEM;
1580 sqlite3_mutex_enter(mutex);
1582 xm = sqlite3_malloc(
sizeof (
XMOD));
1584 sqlite3_mutex_leave(mutex);
1585 return SQLITE_NOMEM;
1588 xm->
mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
1590 sqlite3_mutex_leave(mutex);
1592 return SQLITE_NOMEM;
1598 sqlite3_mutex_leave(mutex);
1599 sqlite3_mutex_free(xm->
mutex);
1601 return SQLITE_NOMEM;
1610 sqlite3_mutex_leave(mutex);
1611 sqlite3_create_function(db,
"xpath_string", -1, SQLITE_UTF8,
1613 sqlite3_create_function(db,
"xpath_boolean", -1, SQLITE_UTF8,
1615 sqlite3_create_function(db,
"xpath_number", -1, SQLITE_UTF8,
1617 sqlite3_create_function(db,
"xpath_xml", -1, SQLITE_UTF8,
1619 sqlite3_create_function(db,
"xml_dump", -1, SQLITE_UTF8,
1622 sqlite3_create_function(db,
"xslt_transform", -1, SQLITE_UTF8,
1623 (
void *) xm, xpath_func_transform, 0, 0);
1625 rc = sqlite3_create_module_v2(db,
"xpath", &
xpath_mod,
1627 if (rc != SQLITE_OK) {
1628 sqlite3_create_function(db,
"xpath_string", -1, SQLITE_UTF8,
1629 (
void *) xm, 0, 0, 0);
1630 sqlite3_create_function(db,
"xpath_boolean", -1, SQLITE_UTF8,
1631 (
void *) xm, 0, 0, 0);
1632 sqlite3_create_function(db,
"xpath_number", -1, SQLITE_UTF8,
1633 (
void *) xm, 0, 0, 0);
1634 sqlite3_create_function(db,
"xpath_xml", -1, SQLITE_UTF8,
1635 (
void *) xm, 0, 0, 0);
1636 sqlite3_create_function(db,
"xml_dump", -1, SQLITE_UTF8,
1637 (
void *) xm, 0, 0, 0);
1639 sqlite3_create_function(db,
"xslt_transform", -1, SQLITE_UTF8,
1640 (
void *) xm, 0, 0, 0);
1659 const sqlite3_api_routines *api)
1661 SQLITE_EXTENSION_INIT2(api);