xpath.c
Go to the documentation of this file.
1
18#if defined(_WIN32) || defined(_WIN64)
19#include <windows.h>
20#endif
21#include <stdio.h>
22#include <string.h>
23#include <ctype.h>
24#include <stdlib.h>
25#include <libxml/parser.h>
26#include <libxml/tree.h>
27#include <libxml/xpath.h>
28#ifdef WITH_XSLT
29#include <libxslt/xslt.h>
30#include <libxslt/transform.h>
31#include <libxslt/xsltutils.h>
32#endif
33
34#ifdef STANDALONE
35#include <sqlite3.h>
36#else
37#include <sqlite3ext.h>
38static SQLITE_EXTENSION_INIT1
39#endif
40
47typedef struct XDOC {
48 xmlDocPtr doc;
49 int refcnt;
51
58typedef struct XMOD {
59 int refcnt;
60 sqlite3_mutex *mutex;
61 int sdoc;
62 int ndoc;
65
66static int initialized = 0;
67static XMOD *xmod = 0;
68
75typedef struct XTAB {
76 sqlite3_vtab vtab;
77 sqlite3 *db;
79 struct XCSR *xc;
80 int sdoc;
81 int ndoc;
82 int *idocs;
84
91typedef struct XEXP {
92 struct XEXP *next;
93 struct XEXP *prev;
94 xmlDocPtr doc;
95 xmlXPathContextPtr pctx;
96 xmlXPathObjectPtr pobj;
97 xmlNodePtr parent;
98 int pos;
99 int conv;
100 char expr[1];
102
109typedef struct XCSR {
110 sqlite3_vtab_cursor cursor;
111 int pos;
112 int nexpr;
116
134static int
135xpath_connect(sqlite3* db, void *aux, int argc, const char * const *argv,
136 sqlite3_vtab **vtabp, char **errp)
137{
138 int rc = SQLITE_ERROR;
139 XTAB *xt;
140
141 xt = sqlite3_malloc(sizeof (XTAB));
142 if (!xt) {
143nomem:
144 *errp = sqlite3_mprintf("out of memory");
145 return rc;
146 }
147 memset(xt, 0, sizeof (XTAB));
148 xt->db = db;
149 xt->xm = (XMOD *) aux;
150 xt->xc = 0;
151 xt->sdoc = 128;
152 xt->ndoc = 0;
153 xt->idocs = sqlite3_malloc(xt->sdoc * sizeof (int));
154 if (!xt->idocs) {
155 sqlite3_free(xt);
156 goto nomem;
157 }
158 rc = sqlite3_declare_vtab(db,
159 "CREATE TABLE x("
160 " DOCID INTEGER PRIMARY KEY,"
161 " XML HIDDEN BLOB,"
162 " PATH HIDDEN TEXT,"
163 " OPTIONS HIDDEN INTEGER,"
164 " ENCODING HIDDEN TEXT,"
165 " BASEURL HIDDEN TEXT,"
166 " XMLDUMP HIDDEN TEXT"
167 ")");
168 if (rc != SQLITE_OK) {
169 sqlite3_free(xt->idocs);
170 sqlite3_free(xt);
171 *errp = sqlite3_mprintf("table definition failed (error %d)", rc);
172 return rc;
173 }
174 *vtabp = &xt->vtab;
175 *errp = 0;
176 return SQLITE_OK;
177}
178
190static int
191xpath_create(sqlite3* db, void *aux, int argc,
192 const char *const *argv,
193 sqlite3_vtab **vtabp, char **errp)
194{
195 return xpath_connect(db, aux, argc, argv, vtabp, errp);
196}
197
204static int
205xpath_disconnect(sqlite3_vtab *vtab)
206{
207 XTAB *xt = (XTAB *) vtab;
208 XMOD *xm = xt->xm;
209 int i, n;
210
211 if (xm->mutex) {
212 sqlite3_mutex_enter(xm->mutex);
213 for (i = 0; xm->docs && (i < xt->ndoc); i++) {
214 n = xt->idocs[i];
215 if ((n >= 0) && (n < xm->sdoc)) {
216 xmlDocPtr doc = xm->docs[n].doc;
217 if (doc) {
218 xm->docs[n].refcnt -= 1;
219 if (xm->docs[n].refcnt <= 0) {
220 xm->docs[n].doc = 0;
221 xm->docs[n].refcnt = 0;
222 xm->ndoc--;
223 xmlFreeDoc(doc);
224 }
225 }
226 }
227 }
228 sqlite3_mutex_leave(xm->mutex);
229 }
230 sqlite3_free(xt->idocs);
231 sqlite3_free(xt);
232 return SQLITE_OK;
233}
234
241static int
242xpath_destroy(sqlite3_vtab *vtab)
243{
244 return xpath_disconnect(vtab);
245}
246
254static int
255xpath_bestindex(sqlite3_vtab *vtab, sqlite3_index_info *info)
256{
257 return SQLITE_OK;
258}
259
267static int
268xpath_open(sqlite3_vtab *vtab, sqlite3_vtab_cursor **cursorp)
269{
270 XCSR *xc = sqlite3_malloc(sizeof (XCSR));
271
272 if (!xc) {
273 return SQLITE_ERROR;
274 }
275 xc->cursor.pVtab = vtab;
276 xc->pos = -1;
277 xc->nexpr = 0;
278 xc->first = xc->last = 0;
279 *cursorp = &xc->cursor;
280 return SQLITE_OK;
281}
282
289static int
290xpath_close(sqlite3_vtab_cursor *cursor)
291{
292 XCSR *xc = (XCSR *) cursor;
293 XEXP *xp = xc->first, *next;
294 XTAB *xt = (XTAB *) xc->cursor.pVtab;
295
296 while (xp) {
297 next = xp->next;
298 if (xp->pobj) {
299 xmlXPathFreeObject(xp->pobj);
300 }
301 if (xp->pctx) {
302 xmlXPathFreeContext(xp->pctx);
303 }
304 sqlite3_free(xp);
305 xp = next;
306 }
307 if (xt->xc == xc) {
308 xt->xc = 0;
309 }
310 sqlite3_free(xc);
311 return SQLITE_OK;
312}
313
320static int
321xpath_next(sqlite3_vtab_cursor *cursor)
322{
323 XCSR *xc = (XCSR *) cursor;
324 XTAB *xt = (XTAB *) xc->cursor.pVtab;
325 XEXP *xp;
326
327 if (xc->pos < xt->ndoc) {
328 int ninc = 0;
329
330 if ((xc->pos >= 0) && xc->nexpr) {
331 int newpos;
332 xmlNodePtr node, parent = 0;
333
334 xp = xc->first;
335 while (xp) {
336 if (xp->pobj) {
337 if (xp == xc->first) {
338 parent = xp->parent;
339 } else if (parent != xp->parent) {
340 break;
341 }
342 }
343 xp = xp->next;
344 }
345 if (parent && !xp) {
346 int pchg = 0;
347
348 xp = xc->first;
349 while (xp) {
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) {
356 pchg++;
357 }
358 } else {
359 pchg++;
360 }
361 }
362 xp = xp->next;
363 }
364 if ((pchg != 0) && (pchg != xc->nexpr)) {
365 xp = xc->first;
366 while (xp) {
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) {
373 xp->pos = newpos;
374 ninc++;
375 }
376 } else {
377 xp->pos = xp->pobj->nodesetval->nodeNr;
378 ninc++;
379 }
380 }
381 xp = xp->next;
382 }
383 }
384 }
385 if (!ninc) {
386 xp = xc->first;
387 while (xp) {
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) {
392 xp->pos = newpos;
393 ninc++;
394 } else {
395 xp->pos = xp->pobj->nodesetval->nodeNr;
396 }
397 }
398 xp = xp->next;
399 }
400 }
401 }
402 if (!ninc) {
403 xc->pos++;
404 xp = xc->first;
405 while (xp) {
406 xp->pos = -1;
407 xp->parent = 0;
408 xp = xp->next;
409 }
410 }
411 }
412 return SQLITE_OK;
413}
414
425static int
426xpath_filter(sqlite3_vtab_cursor *cursor, int idxNum,
427 const char *idxStr, int argc, sqlite3_value **argv)
428{
429 XCSR *xc = (XCSR *) cursor;
430 XTAB *xt = (XTAB *) xc->cursor.pVtab;
431
432 xc->pos = -1;
433 xt->xc = xc;
434 return xpath_next(cursor);
435}
436
443static int
444xpath_eof(sqlite3_vtab_cursor *cursor)
445{
446 XCSR *xc = (XCSR *) cursor;
447 XTAB *xt = (XTAB *) xc->cursor.pVtab;
448
449 return xc->pos >= xt->ndoc;
450}
451
460static int
461xpath_column(sqlite3_vtab_cursor *cursor, sqlite3_context *ctx, int n)
462{
463 XCSR *xc = (XCSR *) cursor;
464 XTAB *xt = (XTAB *) xc->cursor.pVtab;
465 XMOD *xm = (XMOD *) xt->xm;
466
467 if ((xc->pos < 0) || (xc->pos >= xt->ndoc)) {
468 sqlite3_result_error(ctx, "column out of bounds", -1);
469 return SQLITE_ERROR;
470 }
471 if (n == 0) {
472 n = xt->idocs[xc->pos];
473 if (xm->docs[n].doc) {
474 sqlite3_result_int(ctx, n + 1);
475 return SQLITE_OK;
476 }
477 } else if (n == 6) {
478 n = xt->idocs[xc->pos];
479 if (xm->docs[n].doc) {
480 xmlChar *dump = 0;
481 int dump_len = 0;
482
483 xmlDocDumpFormatMemoryEnc(xm->docs[n].doc, &dump,
484 &dump_len, "utf-8", 1);
485 if (dump) {
486 sqlite3_result_text(ctx, (char *) dump, dump_len,
487 SQLITE_TRANSIENT);
488 xmlFree(dump);
489 return SQLITE_OK;
490 }
491 }
492 }
493 sqlite3_result_null(ctx);
494 return SQLITE_OK;
495}
496
504static int
505xpath_rowid(sqlite3_vtab_cursor *cursor, sqlite3_int64 *rowidp)
506{
507 XCSR *xc = (XCSR *) cursor;
508 XTAB *xt = (XTAB *) xc->cursor.pVtab;
509 XMOD *xm = (XMOD *) xt->xm;
510 int n = xt->idocs[xc->pos];
511
512 if (xm->docs[n].doc) {
513 *rowidp = (sqlite3_int64) (n + 1);
514 return SQLITE_OK;
515 }
516 return SQLITE_ERROR;
517}
518
549static int
550xpath_update(sqlite3_vtab *vtab, int argc, sqlite3_value **argv,
551 sqlite3_int64 *rowidp)
552{
553 int n = -1, rc = SQLITE_ERROR;
554 XTAB *xt = (XTAB *) vtab;
555 XMOD *xm = (XMOD *) xt->xm;
556 xmlDocPtr doc = 0, docToFree = 0;
557
558 if (argc == 1) {
559 /* DELETE */
560 int i, k = -1;
561
562 n = sqlite3_value_int(argv[0]);
563 for (i = 0; i < xt->ndoc; i++) {
564 if ((n - 1) == xt->idocs[i]) {
565 k = xt->idocs[i];
566 memmove(xt->idocs + i, xt->idocs + i + 1,
567 (xt->ndoc - (i + 1)) * sizeof (int));
568 xt->ndoc--;
569 break;
570 }
571 }
572 if ((k >= 0) && xm->mutex) {
573 n = k;
574 doc = xm->docs[n].doc;
575 }
576 rc = SQLITE_OK;
577 } else if ((argc > 1) && (sqlite3_value_type(argv[0]) == SQLITE_NULL)) {
578 /* INSERT */
579 int i, docid;
580 int opts = (XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET);
581 char *enc = 0;
582
583 if (sqlite3_value_type(argv[1]) != SQLITE_NULL) {
584 if (vtab->zErrMsg) {
585 sqlite3_free(vtab->zErrMsg);
586 }
587 vtab->zErrMsg = sqlite3_mprintf("ROWID must be NULL");
588 rc = SQLITE_CONSTRAINT;
589 goto done;
590 }
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)) {
595 if (vtab->zErrMsg) {
596 sqlite3_free(vtab->zErrMsg);
597 }
598 vtab->zErrMsg = sqlite3_mprintf("XML and PATH must be NULL");
599 rc = SQLITE_CONSTRAINT;
600 goto done;
601 }
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);
606 if (vtab->zErrMsg) {
607 sqlite3_free(vtab->zErrMsg);
608 }
609 vtab->zErrMsg = sqlite3_mprintf("constraint violation");
610 rc = SQLITE_CONSTRAINT;
611 goto done;
612 }
613 }
614 if ((docid > 0) && (docid <= xm->sdoc)) {
615 doc = xm->docs[docid - 1].doc;
616 if (doc) {
617 xm->docs[docid - 1].refcnt++;
618 }
619 }
620 sqlite3_mutex_leave(xm->mutex);
621 if (!doc) {
622 if (vtab->zErrMsg) {
623 sqlite3_free(vtab->zErrMsg);
624 }
625 vtab->zErrMsg = sqlite3_mprintf("invalid DOCID");
626 goto done;
627 }
628 goto havedoc;
629 }
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))) {
634 if (vtab->zErrMsg) {
635 sqlite3_free(vtab->zErrMsg);
636 }
637 vtab->zErrMsg = sqlite3_mprintf("specify one of XML or PATH");
638 rc = SQLITE_CONSTRAINT;
639 goto done;
640 }
641 if (sqlite3_value_type(argv[5]) != SQLITE_NULL) {
642 opts = sqlite3_value_int(argv[5]);
643 }
644 if (sqlite3_value_type(argv[6]) != SQLITE_NULL) {
645 enc = (char *) sqlite3_value_text(argv[6]);
646 }
647 if (sqlite3_value_type(argv[4]) != SQLITE_NULL) {
648 doc = xmlReadFile((char *) sqlite3_value_text(argv[4]), enc, opts);
649 } else {
650 char *url = 0;
651
652 if (sqlite3_value_type(argv[7]) != SQLITE_NULL) {
653 url = (char *) sqlite3_value_text(argv[7]);
654 }
655 doc = xmlReadMemory(sqlite3_value_blob(argv[3]),
656 sqlite3_value_bytes(argv[3]),
657 url ? url : "", enc, opts);
658 }
659 if (!doc) {
660 if (vtab->zErrMsg) {
661 sqlite3_free(vtab->zErrMsg);
662 }
663 vtab->zErrMsg = sqlite3_mprintf("read error");
664 goto done;
665 }
666 docToFree = doc;
667havedoc:
668 if (xt->ndoc >= xt->sdoc) {
669 int *idocs = sqlite3_realloc(xt->idocs, xt->sdoc +
670 128 * sizeof (int));
671
672 if (!idocs) {
673 goto nomem;
674 }
675 xt->idocs = idocs;
676 xt->sdoc += 128;
677 }
678 if (!xm->mutex) {
679 goto nomem;
680 }
681 sqlite3_mutex_enter(xm->mutex);
682 if (xm->ndoc >= xt->sdoc) {
683 XDOC *docs = sqlite3_realloc(xm->docs, xt->sdoc +
684 128 * sizeof (XDOC));
685
686 if (!docs) {
687 sqlite3_mutex_leave(xm->mutex);
688 goto nomem;
689 }
690 xm->docs = docs;
691 docs += xt->sdoc;
692 memset(docs, 0, 128 * sizeof (XDOC));
693 xt->sdoc += 128;
694 }
695 for (i = 0; i < xm->sdoc; i++) {
696 if (!xm->docs[i].doc) {
697 xm->docs[i].doc = doc;
698 xm->docs[i].refcnt = 1;
699 xm->ndoc++;
700 xt->idocs[xt->ndoc++] = i;
701 *rowidp = (sqlite3_int64) (i + 1);
702 doc = docToFree = 0;
703 rc = SQLITE_OK;
704 break;
705 }
706 }
707 sqlite3_mutex_leave(xm->mutex);
708 } else {
709 /* UPDATE */
710 if (vtab->zErrMsg) {
711 sqlite3_free(vtab->zErrMsg);
712 }
713 vtab->zErrMsg = sqlite3_mprintf("UPDATE not supported");
714 }
715done:
716 if (docToFree) {
717 xmlFreeDoc(docToFree);
718 } else if (doc && (n >= 0)) {
719 sqlite3_mutex_enter(xm->mutex);
720 xm->docs[n].refcnt -= 1;
721 if (xm->docs[n].refcnt <= 0) {
722 xm->docs[n].doc = 0;
723 xm->docs[n].refcnt = 0;
724 xm->ndoc--;
725 xmlFreeDoc(doc);
726 }
727 sqlite3_mutex_leave(xm->mutex);
728 }
729 return rc;
730nomem:
731 if (vtab->zErrMsg) {
732 sqlite3_free(vtab->zErrMsg);
733 }
734 vtab->zErrMsg = sqlite3_mprintf("out of memory");
735 rc = SQLITE_NOMEM;
736 goto done;
737}
738
756static void
757xpath_vfunc_common(sqlite3_context *ctx, int conv, int argc,
758 sqlite3_value **argv)
759{
760 XTAB *xt = (XTAB *) sqlite3_user_data(ctx);
761 XMOD *xm = xt->xm;
762 XCSR *xc = xt->xc;
763 XEXP *xp;
764 xmlXPathContextPtr pctx = 0;
765 xmlXPathObjectPtr pobj = 0;
766 int n;
767 char *p;
768
769 if ((argc < 2) || !sqlite3_value_text(argv[1])) {
770 sqlite3_result_error(ctx, "wrong arguments", -1);
771 goto done;
772 }
773 if (!xc) {
774 sqlite3_result_error(ctx, "not in virtual table context", -1);
775 goto done;
776 }
777 if ((xc->pos < 0) || (xc->pos >= xt->ndoc)) {
778 sqlite3_result_error(ctx, "cursor out of bounds", -1);
779 goto done;
780 }
781 n = xt->idocs[xc->pos];
782 if (!xm->docs[n].doc) {
783 sqlite3_result_error(ctx, "no docid", -1);
784 goto done;
785 }
786 p = (char *) sqlite3_value_text(argv[1]);
787 if (!p || !p[0]) {
788 sqlite3_result_error(ctx, "no or empty XPath expression", -1);
789 goto done;
790 }
791 xp = xc->first;
792 while (xp) {
793 if (!strcmp(p, xp->expr)) {
794 break;
795 }
796 xp = xp->next;
797 }
798 if (!xp) {
799 xp = sqlite3_malloc(sizeof (XEXP) + strlen(p));
800 if (!xp) {
801 sqlite3_result_error(ctx, "out of memory", -1);
802 goto done;
803 }
804 xp->next = xp->prev = 0;
805 strcpy(xp->expr, p);
806 pctx = xmlXPathNewContext(xm->docs[n].doc);
807 if (!pctx) {
808 sqlite3_free(xp);
809 sqlite3_result_error(ctx, "out of memory", -1);
810 goto done;
811 }
812 pobj = xmlXPathEvalExpression((xmlChar *) xp->expr, pctx);
813 if (!pobj) {
814 sqlite3_free(xp);
815 sqlite3_result_error(ctx, "bad XPath expression", -1);
816 goto done;
817 }
818 xp->doc = xm->docs[n].doc;
819 xp->pctx = pctx;
820 xp->pobj = pobj;
821 xp->parent = 0;
822 xp->pos = -1;
823 xp->conv = conv;
824 pctx = 0;
825 pobj = 0;
826 xc->nexpr++;
827 if (xc->first) {
828 xc->last->next = xp;
829 xp->prev = xc->last;
830 xc->last = xp;
831 } else {
832 xc->first = xc->last = xp;
833 }
834 } else if (xm->docs[n].doc != xp->doc) {
835 if (xp->pobj) {
836 xmlXPathFreeObject(xp->pobj);
837 xp->pobj = 0;
838 }
839 if (xp->pctx) {
840 xmlXPathFreeContext(xp->pctx);
841 xp->pctx = 0;
842 }
843 xp->doc = xm->docs[n].doc;
844 xp->parent = 0;
845 xp->pos = -1;
846 if (xp->doc) {
847 pctx = xmlXPathNewContext(xm->docs[n].doc);
848 if (!pctx) {
849 sqlite3_result_error(ctx, "out of memory", -1);
850 goto done;
851 }
852 pobj = xmlXPathEvalExpression((xmlChar *) xp->expr, pctx);
853 if (!pobj) {
854 sqlite3_result_error(ctx, "bad XPath expression", -1);
855 goto done;
856 }
857 xp->pctx = pctx;
858 xp->pobj = pobj;
859 pctx = 0;
860 pobj = 0;
861 }
862 }
863 if (xp->pos < 0) {
864 xp->pos = 0;
865 }
866 if (!xp->pobj) {
867 xp->parent = 0;
868 sqlite3_result_null(ctx);
869 goto done;
870 }
871 if ((xp->pobj->type == XPATH_NODESET) && xp->pobj->nodesetval) {
872 if ((xp->pos < 0) || (xp->pos >= xp->pobj->nodesetval->nodeNr)) {
873 xp->parent = 0;
874 sqlite3_result_null(ctx);
875 } else {
876 xmlNodePtr node = xp->pobj->nodesetval->nodeTab[xp->pos];
877 xmlBufferPtr buf = 0;
878
879 xp->parent = node->parent;
880 if (node) {
881 switch (xp->conv) {
882 case 1:
883 p = (char *) xmlXPathCastNodeToString(node);
884 n = xmlXPathCastStringToBoolean((xmlChar *) p);
885 sqlite3_result_int(ctx, n);
886 if (p) {
887 xmlFree(p);
888 }
889 break;
890 case 2:
891 sqlite3_result_double(ctx,
892 xmlXPathCastNodeToNumber(node));
893 break;
894 case 3:
895 buf = xmlBufferCreate();
896 if (!buf) {
897 sqlite3_result_error(ctx, "out of memory", -1);
898 goto done;
899 }
900 xmlNodeDump(buf, xp->doc, node, 0, 0);
901 sqlite3_result_text(ctx, (char *) xmlBufferContent(buf),
902 xmlBufferLength(buf),
903 SQLITE_TRANSIENT);
904 xmlBufferFree(buf);
905 break;
906 default:
907 p = (char *) xmlXPathCastNodeToString(node);
908 sqlite3_result_text(ctx, p, -1, SQLITE_TRANSIENT);
909 if (p) {
910 xmlFree(p);
911 }
912 break;
913 }
914 } else {
915 sqlite3_result_null(ctx);
916 }
917 }
918 } else {
919 xp->parent = 0;
920 switch (xp->conv) {
921 case 1:
922 sqlite3_result_int(ctx, xmlXPathCastToBoolean(xp->pobj));
923 break;
924 case 2:
925 sqlite3_result_double(ctx, xmlXPathCastToNumber(xp->pobj));
926 break;
927 default:
928 p = (char *) xmlXPathCastToString(xp->pobj);
929 sqlite3_result_text(ctx, p, -1, SQLITE_TRANSIENT);
930 if (p) {
931 xmlFree(p);
932 }
933 break;
934 }
935 }
936done:
937 if (pobj) {
938 xmlXPathFreeObject(pobj);
939 }
940 if (pctx) {
941 xmlXPathFreeContext(pctx);
942 }
943}
944
952static void
953xpath_vfunc_string(sqlite3_context *ctx, int argc, sqlite3_value **argv)
954{
955 return xpath_vfunc_common(ctx, 0, argc, argv);
956}
957
965static void
966xpath_vfunc_boolean(sqlite3_context *ctx, int argc, sqlite3_value **argv)
967{
968 return xpath_vfunc_common(ctx, 1, argc, argv);
969}
970
978static void
979xpath_vfunc_number(sqlite3_context *ctx, int argc, sqlite3_value **argv)
980{
981 return xpath_vfunc_common(ctx, 2, argc, argv);
982}
983
991static void
992xpath_vfunc_xml(sqlite3_context *ctx, int argc, sqlite3_value **argv)
993{
994 return xpath_vfunc_common(ctx, 3, argc, argv);
995}
996
1007static int
1008xpath_findfunc(sqlite3_vtab *vtab, int nargs, const char *name,
1009 void (**pfunc)(sqlite3_context *, int, sqlite3_value **),
1010 void **parg)
1011{
1012 if (nargs != 2) {
1013 return 0;
1014 }
1015 if (!strcmp(name, "xpath_string")) {
1016 *pfunc = xpath_vfunc_string;
1017 *parg = vtab;
1018 return 1;
1019 }
1020 if (!strcmp(name, "xpath_boolean")) {
1021 *pfunc = xpath_vfunc_boolean;
1022 *parg = vtab;
1023 return 1;
1024 }
1025 if (!strcmp(name, "xpath_number")) {
1026 *pfunc = xpath_vfunc_number;
1027 *parg = vtab;
1028 return 1;
1029 }
1030 if (!strcmp(name, "xpath_xml")) {
1031 *pfunc = xpath_vfunc_xml;
1032 *parg = vtab;
1033 return 1;
1034 }
1035 return 0;
1036}
1037
1038#if (SQLITE_VERSION_NUMBER > 3004000)
1039
1046static int
1047xpath_rename(sqlite3_vtab *vtab, const char *newname)
1048{
1049 return SQLITE_OK;
1050}
1051
1052#endif
1053
1058static sqlite3_module xpath_mod = {
1059 1, /* iVersion */
1060 xpath_create, /* xCreate */
1061 xpath_connect, /* xConnect */
1062 xpath_bestindex, /* xBestIndex */
1063 xpath_disconnect, /* xDisconnect */
1064 xpath_destroy, /* xDestroy */
1065 xpath_open, /* xOpen */
1066 xpath_close, /* xClose */
1067 xpath_filter, /* xFilter */
1068 xpath_next, /* xNext */
1069 xpath_eof, /* xEof */
1070 xpath_column, /* xColumn */
1071 xpath_rowid, /* xRowid */
1072 xpath_update, /* xUpdate */
1073 0, /* xBegin */
1074 0, /* xSync */
1075 0, /* xCommit */
1076 0, /* xRollback */
1077 xpath_findfunc, /* xFindFunction */
1078#if (SQLITE_VERSION_NUMBER > 3004000)
1079 xpath_rename, /* xRename */
1080#endif
1081};
1082
1105static void
1106xpath_func_common(sqlite3_context *ctx, int conv,
1107 int argc, sqlite3_value **argv)
1108{
1109 xmlDocPtr doc = 0, docToFree = 0;
1110 xmlXPathContextPtr pctx = 0;
1111 xmlXPathObjectPtr pobj = 0;
1112 XMOD *xm = (XMOD *) sqlite3_user_data(ctx);
1113 int index = 0;
1114 char *p;
1115
1116 if (argc < 2) {
1117 sqlite3_result_null(ctx);
1118 goto done;
1119 }
1120 if (sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
1121 index = sqlite3_value_int(argv[0]);
1122 if (!xm->mutex) {
1123 sqlite3_result_error(ctx, "init error", -1);
1124 goto done;
1125 }
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);
1130 goto done;
1131 }
1132 doc = xm->docs[index - 1].doc;
1133 xm->docs[index - 1].refcnt += 1;
1134 sqlite3_mutex_leave(xm->mutex);
1135 } else {
1136 int opts = (XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET);
1137 char *enc = 0, *url = 0;
1138
1139 p = (char *) sqlite3_value_blob(argv[0]);
1140 if (!p) {
1141 sqlite3_result_null(ctx);
1142 return;
1143 }
1144 if ((argc > 2) && (sqlite3_value_type(argv[2]) != SQLITE_NULL)) {
1145 opts = sqlite3_value_int(argv[2]);
1146 }
1147 if ((argc > 3) && (sqlite3_value_type(argv[3]) != SQLITE_NULL)) {
1148 enc = (char *) sqlite3_value_text(argv[3]);
1149 }
1150 if ((argc > 4) && (sqlite3_value_type(argv[4]) != SQLITE_NULL)) {
1151 url = (char *) sqlite3_value_text(argv[4]);
1152 }
1153 doc = xmlReadMemory(p, sqlite3_value_bytes(argv[0]),
1154 url ? url : "", enc, opts);
1155 docToFree = doc;
1156 if (!doc) {
1157 sqlite3_result_error(ctx, "read error", -1);
1158 goto done;
1159 }
1160 }
1161 p = (char *) sqlite3_value_text(argv[1]);
1162 if (!p) {
1163 sqlite3_result_null(ctx);
1164 goto done;
1165 }
1166 pctx = xmlXPathNewContext(doc);
1167 if (!pctx) {
1168 sqlite3_result_error(ctx, "out of memory", -1);
1169 goto done;
1170 }
1171 pobj = xmlXPathEvalExpression((xmlChar *) p, pctx);
1172 if (!pobj) {
1173 sqlite3_result_error(ctx, "bad XPath expression", -1);
1174 goto done;
1175 }
1176 switch (conv) {
1177 case 1:
1178 sqlite3_result_int(ctx, xmlXPathCastToBoolean(pobj));
1179 break;
1180 case 2:
1181 sqlite3_result_double(ctx, xmlXPathCastToNumber(pobj));
1182 break;
1183 case 3:
1184 if ((pobj->type == XPATH_NODESET) && pobj->nodesetval &&
1185 (pobj->nodesetval->nodeNr)) {
1186 xmlNodePtr node = pobj->nodesetval->nodeTab[0];
1187 xmlBufferPtr buf = 0;
1188
1189 buf = xmlBufferCreate();
1190 if (!buf) {
1191 sqlite3_result_error(ctx, "out of memory", -1);
1192 goto done;
1193 }
1194 xmlNodeDump(buf, doc, node, 0, 0);
1195 sqlite3_result_text(ctx, (char *) xmlBufferContent(buf),
1196 xmlBufferLength(buf), SQLITE_TRANSIENT);
1197 xmlBufferFree(buf);
1198 } else {
1199 sqlite3_result_null(ctx);
1200 }
1201 break;
1202 default:
1203 p = (char *) xmlXPathCastToString(pobj);
1204 sqlite3_result_text(ctx, p, -1, SQLITE_TRANSIENT);
1205 if (p) {
1206 xmlFree(p);
1207 }
1208 break;
1209 }
1210done:
1211 if (pobj) {
1212 xmlXPathFreeObject(pobj);
1213 }
1214 if (pctx) {
1215 xmlXPathFreeContext(pctx);
1216 }
1217 if (docToFree) {
1218 xmlFreeDoc(docToFree);
1219 } else if (doc) {
1220 if (xm->mutex) {
1221 sqlite3_mutex_enter(xm->mutex);
1222 if (xm->docs && index) {
1223 xm->docs[index - 1].refcnt -= 1;
1224 if (xm->docs[index - 1].refcnt <= 0) {
1225 docToFree = doc;
1226 xm->docs[index - 1].refcnt = 0;
1227 xm->docs[index - 1].doc = 0;
1228 }
1229 }
1230 sqlite3_mutex_leave(xm->mutex);
1231 if (docToFree) {
1232 xmlFreeDoc(docToFree);
1233 }
1234 }
1235 }
1236}
1237
1245static void
1246xpath_func_string(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1247{
1248 xpath_func_common(ctx, 0, argc, argv);
1249}
1250
1258static void
1259xpath_func_boolean(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1260{
1261 xpath_func_common(ctx, 1, argc, argv);
1262}
1263
1271static void
1272xpath_func_number(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1273{
1274 xpath_func_common(ctx, 2, argc, argv);
1275}
1276
1284static void
1285xpath_func_xml(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1286{
1287 xpath_func_common(ctx, 3, argc, argv);
1288}
1289
1307static void
1308xpath_func_dump(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1309{
1310 XMOD *xm = (XMOD *) sqlite3_user_data(ctx);
1311 int index = 0, dump_len = 0, fmt = 1;
1312 xmlChar *dump = 0;
1313 char *enc = "utf-8";
1314
1315 if (argc < 1) {
1316 sqlite3_result_null(ctx);
1317 return;
1318 }
1319 index = sqlite3_value_int(argv[0]);
1320 if (argc > 1) {
1321 enc = (char *) sqlite3_value_text(argv[1]);
1322 if (!enc) {
1323 enc = "utf-8";
1324 }
1325 }
1326 if (argc > 2) {
1327 fmt = sqlite3_value_int(argv[2]);
1328 }
1329 if (!xm->mutex) {
1330 sqlite3_result_error(ctx, "init error", -1);
1331 return;
1332 }
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);
1337 return;
1338 }
1339 xmlDocDumpFormatMemoryEnc(xm->docs[index - 1].doc, &dump, &dump_len,
1340 enc, fmt);
1341 if (dump) {
1342 sqlite3_result_text(ctx, (char *) dump, dump_len, SQLITE_TRANSIENT);
1343 xmlFree(dump);
1344 }
1345 sqlite3_mutex_leave(xm->mutex);
1346}
1347
1348#ifdef WITH_XSLT
1372static void
1373xpath_func_transform(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1374{
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;
1379 char *p;
1380 const char **params = 0;
1381
1382 if (argc < 2) {
1383 sqlite3_result_null(ctx);
1384 goto done;
1385 }
1386 if (sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
1387 index = sqlite3_value_int(argv[0]);
1388 if (!xm->mutex) {
1389 sqlite3_result_error(ctx, "init error", -1);
1390 goto done;
1391 }
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);
1396 goto done;
1397 }
1398 doc = xm->docs[index - 1].doc;
1399 xm->docs[index - 1].refcnt += 1;
1400 sqlite3_mutex_leave(xm->mutex);
1401 param0 = 2;
1402 nparams = argc - 2;
1403 } else {
1404 int opts = (XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET);
1405 char *enc = 0, *url = 0;
1406
1407 p = (char *) sqlite3_value_blob(argv[0]);
1408 if (!p) {
1409 sqlite3_result_null(ctx);
1410 return;
1411 }
1412 if ((argc > 2) && (sqlite3_value_type(argv[2]) != SQLITE_NULL)) {
1413 opts = sqlite3_value_int(argv[2]);
1414 }
1415 if ((argc > 3) && (sqlite3_value_type(argv[3]) != SQLITE_NULL)) {
1416 enc = (char *) sqlite3_value_text(argv[3]);
1417 }
1418 if ((argc > 4) && (sqlite3_value_type(argv[4]) != SQLITE_NULL)) {
1419 url = (char *) sqlite3_value_text(argv[4]);
1420 }
1421 doc = xmlReadMemory(p, sqlite3_value_bytes(argv[0]),
1422 url ? url : "", enc, opts);
1423 docToFree = doc;
1424 if (!doc) {
1425 sqlite3_result_error(ctx, "read error", -1);
1426 goto done;
1427 }
1428 param0 = 5;
1429 nparams = argc - 5;
1430 }
1431 p = (char *) sqlite3_value_text(argv[1]);
1432 if (!p) {
1433 sqlite3_result_null(ctx);
1434 goto done;
1435 }
1436 cur = xsltParseStylesheetFile((xmlChar *) p);
1437 if (!cur) {
1438 sqlite3_result_error(ctx, "read error on stylesheet", -1);
1439 goto done;
1440 }
1441 if (nparams <= 0) {
1442 nparams = 1;
1443 } else {
1444 nparams++;
1445 }
1446 params = sqlite3_malloc(nparams * sizeof (char *));
1447 if (!params) {
1448 sqlite3_result_error(ctx, "out of memory", -1);
1449 goto done;
1450 }
1451 for (i = 0; i < (argc - param0); i++) {
1452 params[i] = (const char *) sqlite3_value_text(argv[i + param0]);
1453 if (!params[i]) {
1454 params[i] = "";
1455 }
1456 }
1457 params[i] = 0;
1458 res = xsltApplyStylesheet(cur, doc, params);
1459 if (!res) {
1460 sqlite3_result_error(ctx, "transformation failed", -1);
1461 goto done;
1462 }
1463 if (docToFree) {
1464 xmlChar *str = 0;
1465
1466 xmlFreeDoc(docToFree);
1467 docToFree = res;
1468 i = 0;
1469 xsltSaveResultToString(&str, &i, res, cur);
1470 if (str) {
1471 sqlite3_result_text(ctx, (char *) str, i, SQLITE_TRANSIENT);
1472 xmlFree(str);
1473 } else {
1474 sqlite3_result_null(ctx);
1475 }
1476 }
1477done:
1478 if (params) {
1479 sqlite3_free(params);
1480 }
1481 if (cur) {
1482 xsltFreeStylesheet(cur);
1483 }
1484 if (docToFree) {
1485 xmlFreeDoc(docToFree);
1486 } else if (doc) {
1487 if (xm->mutex) {
1488 sqlite3_mutex_enter(xm->mutex);
1489 if (xm->docs && index) {
1490 docToFree = doc;
1491 xm->docs[index - 1].doc = 0;
1492 xmlFreeDoc(docToFree);
1493 docToFree = 0;
1494 xm->docs[index - 1].refcnt -= 1;
1495 xm->docs[index - 1].doc = res;
1496 if (xm->docs[index - 1].refcnt <= 0) {
1497 docToFree = res;
1498 xm->docs[index - 1].refcnt = 0;
1499 xm->docs[index - 1].doc = 0;
1500 }
1501 }
1502 sqlite3_mutex_leave(xm->mutex);
1503 if (docToFree) {
1504 xmlFreeDoc(docToFree);
1505 }
1506 }
1507 }
1508}
1509#endif
1510
1517static void
1518xpath_fini(void *aux)
1519{
1520 XMOD *xm = (XMOD *) aux;
1521 XDOC *docs;
1522 int i, n, cleanup = 0;
1523 sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
1524
1525 if (!mutex) {
1526 return;
1527 }
1528 sqlite3_mutex_enter(mutex);
1529 if (initialized) {
1530 xm->refcnt--;
1531 if (xm->refcnt <= 0) {
1532 xmod = 0;
1533 initialized = 0;
1534 cleanup = 1;
1535 }
1536 } else {
1537 cleanup = 1;
1538 }
1539 sqlite3_mutex_leave(mutex);
1540 if (cleanup) {
1541 sqlite3_mutex_enter(xm->mutex);
1542 mutex = xm->mutex;
1543 xm->mutex = 0;
1544 docs = xm->docs;
1545 n = xm->ndoc;
1546 xm->docs = 0;
1547 xm->sdoc = xm->ndoc = 0;
1548 sqlite3_mutex_leave(mutex);
1549 sqlite3_mutex_free(mutex);
1550 for (i = 0; i < n; i++) {
1551 if (docs->refcnt <= 0) {
1552 xmlFreeDoc(docs->doc);
1553 docs->doc = 0;
1554 }
1555 }
1556 sqlite3_free(docs);
1557 sqlite3_free(xm);
1558 }
1559}
1560
1567#ifndef STANDALONE
1568static
1569#endif
1570int
1571xpath_init(sqlite3 *db)
1572{
1573 XMOD *xm;
1574 int rc;
1575 sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
1576
1577 if (!mutex) {
1578 return SQLITE_NOMEM;
1579 }
1580 sqlite3_mutex_enter(mutex);
1581 if (!initialized) {
1582 xm = sqlite3_malloc(sizeof (XMOD));
1583 if (!xm) {
1584 sqlite3_mutex_leave(mutex);
1585 return SQLITE_NOMEM;
1586 }
1587 xm->refcnt = 1;
1588 xm->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
1589 if (!xm->mutex) {
1590 sqlite3_mutex_leave(mutex);
1591 sqlite3_free(xm);
1592 return SQLITE_NOMEM;
1593 }
1594 xm->sdoc = 128;
1595 xm->ndoc = 0;
1596 xm->docs = sqlite3_malloc(xm->sdoc * sizeof (XDOC));
1597 if (!xm->docs) {
1598 sqlite3_mutex_leave(mutex);
1599 sqlite3_mutex_free(xm->mutex);
1600 sqlite3_free(xm);
1601 return SQLITE_NOMEM;
1602 }
1603 memset(xm->docs, 0, xm->sdoc * sizeof (XDOC));
1604 xmod = xm;
1605 initialized = 1;
1606 } else {
1607 xm = xmod;
1608 xm->refcnt++;
1609 }
1610 sqlite3_mutex_leave(mutex);
1611 sqlite3_create_function(db, "xpath_string", -1, SQLITE_UTF8,
1612 (void *) xm, xpath_func_string, 0, 0);
1613 sqlite3_create_function(db, "xpath_boolean", -1, SQLITE_UTF8,
1614 (void *) xm, xpath_func_boolean, 0, 0);
1615 sqlite3_create_function(db, "xpath_number", -1, SQLITE_UTF8,
1616 (void *) xm, xpath_func_number, 0, 0);
1617 sqlite3_create_function(db, "xpath_xml", -1, SQLITE_UTF8,
1618 (void *) xm, xpath_func_xml, 0, 0);
1619 sqlite3_create_function(db, "xml_dump", -1, SQLITE_UTF8,
1620 (void *) xm, xpath_func_dump, 0, 0);
1621#ifdef WITH_XSLT
1622 sqlite3_create_function(db, "xslt_transform", -1, SQLITE_UTF8,
1623 (void *) xm, xpath_func_transform, 0, 0);
1624#endif
1625 rc = sqlite3_create_module_v2(db, "xpath", &xpath_mod,
1626 (void *) xm, xpath_fini);
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);
1638#ifdef WITH_XSLT
1639 sqlite3_create_function(db, "xslt_transform", -1, SQLITE_UTF8,
1640 (void *) xm, 0, 0, 0);
1641#endif
1642 xpath_fini(xm);
1643 }
1644 return rc;
1645}
1646
1647#ifndef STANDALONE
1648
1657int
1658sqlite3_extension_init(sqlite3 *db, char **errmsg,
1659 const sqlite3_api_routines *api)
1660{
1661 SQLITE_EXTENSION_INIT2(api);
1662 return xpath_init(db);
1663}
1664
1665#endif
static SQLRETURN nomem(STMT *s)
Report S1000 (out of memory) SQL error given STMT.
Structure to describe virtual table cursor.
Definition xpath.c:109
XEXP * last
Last XPath expr.
Definition xpath.c:114
int nexpr
Number of XPath expr.
Definition xpath.c:112
int pos
Current index.
Definition xpath.c:111
XEXP * first
First XPath expr.
Definition xpath.c:113
sqlite3_vtab_cursor cursor
SQLite virtual table cursor.
Definition xpath.c:110
Structure to cache XML document.
Definition xpath.c:47
xmlDocPtr doc
XML document.
Definition xpath.c:48
int refcnt
Reference counter.
Definition xpath.c:49
Structure to describe XPath expression.
Definition xpath.c:91
xmlXPathContextPtr pctx
Current XPath context.
Definition xpath.c:95
int conv
Conversion: string/boolean/number.
Definition xpath.c:99
xmlXPathObjectPtr pobj
Current XPath objects.
Definition xpath.c:96
struct XEXP * next
Next item.
Definition xpath.c:92
xmlDocPtr doc
Current XML document.
Definition xpath.c:94
struct XEXP * prev
Previous item.
Definition xpath.c:93
char expr[1]
XPath expression text.
Definition xpath.c:100
int pos
Position within XPath expr.
Definition xpath.c:98
xmlNodePtr parent
Current parent node or NULL.
Definition xpath.c:97
Structure holding per module/database data.
Definition xpath.c:58
sqlite3_mutex * mutex
DOC table mutex.
Definition xpath.c:60
XDOC * docs
Array of modules's DOCs.
Definition xpath.c:63
int ndoc
Number of used entries in docs array.
Definition xpath.c:62
int sdoc
Size of docs array.
Definition xpath.c:61
int refcnt
Reference counter.
Definition xpath.c:59
Structure to describe virtual table.
Definition xpath.c:75
int ndoc
Number of used entries in idocs array.
Definition xpath.c:81
sqlite3_vtab vtab
SQLite virtual table.
Definition xpath.c:76
XMOD * xm
Module data.
Definition xpath.c:78
int sdoc
Size of idocs array.
Definition xpath.c:80
int * idocs
Indexes in module-wide DOC table.
Definition xpath.c:82
sqlite3 * db
Open database.
Definition xpath.c:77
struct XCSR * xc
Current cursor.
Definition xpath.c:79
static void xpath_func_common(sqlite3_context *ctx, int conv, int argc, sqlite3_value **argv)
Common XPath select function.
Definition xpath.c:1106
static int xpath_rowid(sqlite3_vtab_cursor *cursor, sqlite3_int64 *rowidp)
Return current rowid of virtual table cursor.
Definition xpath.c:505
static int xpath_next(sqlite3_vtab_cursor *cursor)
Retrieve next row from virtual table cursor.
Definition xpath.c:321
static XMOD * xmod
Definition xpath.c:67
static void xpath_vfunc_string(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning string value from virtual table.
Definition xpath.c:953
static void xpath_vfunc_number(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning number from virtual table.
Definition xpath.c:979
static int xpath_filter(sqlite3_vtab_cursor *cursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv)
Filter function for virtual table.
Definition xpath.c:426
static void xpath_vfunc_xml(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning XML from virtual table.
Definition xpath.c:992
struct XEXP XEXP
static int xpath_destroy(sqlite3_vtab *vtab)
Destroy virtual table.
Definition xpath.c:242
static void xpath_vfunc_boolean(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning boolean value from virtual table.
Definition xpath.c:966
static void xpath_func_number(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning number.
Definition xpath.c:1272
static sqlite3_module xpath_mod
SQLite module descriptor.
Definition xpath.c:1058
static void xpath_func_string(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning string value.
Definition xpath.c:1246
static void xpath_func_xml(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning XML.
Definition xpath.c:1285
struct XMOD XMOD
static int xpath_close(sqlite3_vtab_cursor *cursor)
Close virtual table cursor.
Definition xpath.c:290
int sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api)
Initializer for SQLite extension load mechanism.
Definition xpath.c:1658
static int xpath_bestindex(sqlite3_vtab *vtab, sqlite3_index_info *info)
Determines information for filter function according to constraints.
Definition xpath.c:255
static int xpath_disconnect(sqlite3_vtab *vtab)
Disconnect virtual table.
Definition xpath.c:205
static int xpath_column(sqlite3_vtab_cursor *cursor, sqlite3_context *ctx, int n)
Return column data of virtual table.
Definition xpath.c:461
static int xpath_create(sqlite3 *db, void *aux, int argc, const char *const *argv, sqlite3_vtab **vtabp, char **errp)
Create virtual table.
Definition xpath.c:191
static int xpath_eof(sqlite3_vtab_cursor *cursor)
Return end of table state of virtual table cursor.
Definition xpath.c:444
static void xpath_fini(void *aux)
Module finalizer.
Definition xpath.c:1518
static int xpath_connect(sqlite3 *db, void *aux, int argc, const char *const *argv, sqlite3_vtab **vtabp, char **errp)
Connect to virtual table.
Definition xpath.c:135
struct XTAB XTAB
static int xpath_init(sqlite3 *db)
Module initializer creating SQLite module and functions.
Definition xpath.c:1571
static void xpath_func_dump(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Function to dump XML document.
Definition xpath.c:1308
static void xpath_func_boolean(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning boolean value.
Definition xpath.c:1259
static int xpath_update(sqlite3_vtab *vtab, int argc, sqlite3_value **argv, sqlite3_int64 *rowidp)
Insert/delete row into/from virtual table.
Definition xpath.c:550
static int xpath_open(sqlite3_vtab *vtab, sqlite3_vtab_cursor **cursorp)
Open virtual table and return cursor.
Definition xpath.c:268
static void xpath_vfunc_common(sqlite3_context *ctx, int conv, int argc, sqlite3_value **argv)
Common XPath select function for virtual table.
Definition xpath.c:757
struct XCSR XCSR
static int initialized
Definition xpath.c:66
static int xpath_findfunc(sqlite3_vtab *vtab, int nargs, const char *name, void(**pfunc)(sqlite3_context *, int, sqlite3_value **), void **parg)
Find overloaded function on virtual table.
Definition xpath.c:1008
struct XDOC XDOC

Generated on Sun Nov 26 2023 by doxygen.
Contact: chw@ch-werner.de