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>
38 static SQLITE_EXTENSION_INIT1
39 #endif
40 
47 typedef struct XDOC {
48  xmlDocPtr doc;
49  int refcnt;
50 } XDOC;
51 
58 typedef struct XMOD {
59  int refcnt;
60  sqlite3_mutex *mutex;
61  int sdoc;
62  int ndoc;
64 } XMOD;
65 
66 static int initialized = 0;
67 static XMOD *xmod = 0;
68 
75 typedef struct XTAB {
76  sqlite3_vtab vtab;
77  sqlite3 *db;
78  XMOD *xm;
79  struct XCSR *xc;
80  int sdoc;
81  int ndoc;
82  int *idocs;
83 } XTAB;
84 
91 typedef 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];
101 } XEXP;
102 
109 typedef struct XCSR {
110  sqlite3_vtab_cursor cursor;
111  int pos;
112  int nexpr;
115 } XCSR;
116 
134 static int
135 xpath_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) {
143 nomem:
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 
190 static int
191 xpath_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 
204 static int
205 xpath_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 
241 static int
242 xpath_destroy(sqlite3_vtab *vtab)
243 {
244  return xpath_disconnect(vtab);
245 }
246 
254 static int
255 xpath_bestindex(sqlite3_vtab *vtab, sqlite3_index_info *info)
256 {
257  return SQLITE_OK;
258 }
259 
267 static int
268 xpath_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 
289 static int
290 xpath_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 
320 static int
321 xpath_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 
425 static int
426 xpath_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 
443 static int
444 xpath_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 
460 static int
461 xpath_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 
504 static int
505 xpath_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 
549 static int
550 xpath_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;
667 havedoc:
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  } else {
708  /* UPDATE */
709  if (vtab->zErrMsg) {
710  sqlite3_free(vtab->zErrMsg);
711  }
712  vtab->zErrMsg = sqlite3_mprintf("UPDATE not supported");
713  }
714 done:
715  if (docToFree) {
716  xmlFreeDoc(docToFree);
717  } else if (doc && (n >= 0)) {
718  sqlite3_mutex_enter(xm->mutex);
719  xm->docs[n].refcnt -= 1;
720  if (xm->docs[n].refcnt <= 0) {
721  xm->docs[n].doc = 0;
722  xm->docs[n].refcnt = 0;
723  xm->ndoc--;
724  xmlFreeDoc(doc);
725  }
726  sqlite3_mutex_leave(xm->mutex);
727  }
728  return rc;
729 nomem:
730  if (vtab->zErrMsg) {
731  sqlite3_free(vtab->zErrMsg);
732  }
733  vtab->zErrMsg = sqlite3_mprintf("out of memory");
734  rc = SQLITE_NOMEM;
735  goto done;
736 }
737 
755 static void
756 xpath_vfunc_common(sqlite3_context *ctx, int conv, int argc,
757  sqlite3_value **argv)
758 {
759  XTAB *xt = (XTAB *) sqlite3_user_data(ctx);
760  XMOD *xm = xt->xm;
761  XCSR *xc = xt->xc;
762  XEXP *xp;
763  xmlXPathContextPtr pctx = 0;
764  xmlXPathObjectPtr pobj = 0;
765  int n;
766  char *p;
767 
768  if ((argc < 2) || !sqlite3_value_text(argv[1])) {
769  sqlite3_result_error(ctx, "wrong arguments", -1);
770  goto done;
771  }
772  if (!xc) {
773  sqlite3_result_error(ctx, "not in virtual table context", -1);
774  goto done;
775  }
776  if ((xc->pos < 0) || (xc->pos >= xt->ndoc)) {
777  sqlite3_result_error(ctx, "cursor out of bounds", -1);
778  goto done;
779  }
780  n = xt->idocs[xc->pos];
781  if (!xm->docs[n].doc) {
782  sqlite3_result_error(ctx, "no docid", -1);
783  goto done;
784  }
785  p = (char *) sqlite3_value_text(argv[1]);
786  if (!p || !p[0]) {
787  sqlite3_result_error(ctx, "no or empty XPath expression", -1);
788  goto done;
789  }
790  xp = xc->first;
791  while (xp) {
792  if (!strcmp(p, xp->expr)) {
793  break;
794  }
795  xp = xp->next;
796  }
797  if (!xp) {
798  xp = sqlite3_malloc(sizeof (XEXP) + strlen(p));
799  if (!xp) {
800  sqlite3_result_error(ctx, "out of memory", -1);
801  goto done;
802  }
803  xp->next = xp->prev = 0;
804  strcpy(xp->expr, p);
805  pctx = xmlXPathNewContext(xm->docs[n].doc);
806  if (!pctx) {
807  sqlite3_free(xp);
808  sqlite3_result_error(ctx, "out of memory", -1);
809  goto done;
810  }
811  pobj = xmlXPathEvalExpression((xmlChar *) xp->expr, pctx);
812  if (!pobj) {
813  sqlite3_free(xp);
814  sqlite3_result_error(ctx, "bad XPath expression", -1);
815  goto done;
816  }
817  xp->doc = xm->docs[n].doc;
818  xp->pctx = pctx;
819  xp->pobj = pobj;
820  xp->parent = 0;
821  xp->pos = -1;
822  xp->conv = conv;
823  pctx = 0;
824  pobj = 0;
825  xc->nexpr++;
826  if (xc->first) {
827  xc->last->next = xp;
828  xp->prev = xc->last;
829  xc->last = xp;
830  } else {
831  xc->first = xc->last = xp;
832  }
833  } else if (xm->docs[n].doc != xp->doc) {
834  if (xp->pobj) {
835  xmlXPathFreeObject(xp->pobj);
836  xp->pobj = 0;
837  }
838  if (xp->pctx) {
839  xmlXPathFreeContext(xp->pctx);
840  xp->pctx = 0;
841  }
842  xp->doc = xm->docs[n].doc;
843  xp->parent = 0;
844  xp->pos = -1;
845  if (xp->doc) {
846  pctx = xmlXPathNewContext(xm->docs[n].doc);
847  if (!pctx) {
848  sqlite3_result_error(ctx, "out of memory", -1);
849  goto done;
850  }
851  pobj = xmlXPathEvalExpression((xmlChar *) xp->expr, pctx);
852  if (!pobj) {
853  sqlite3_result_error(ctx, "bad XPath expression", -1);
854  goto done;
855  }
856  xp->pctx = pctx;
857  xp->pobj = pobj;
858  pctx = 0;
859  pobj = 0;
860  }
861  }
862  if (xp->pos < 0) {
863  xp->pos = 0;
864  }
865  if (!xp->pobj) {
866  xp->parent = 0;
867  sqlite3_result_null(ctx);
868  goto done;
869  }
870  if ((xp->pobj->type == XPATH_NODESET) && xp->pobj->nodesetval) {
871  if ((xp->pos < 0) || (xp->pos >= xp->pobj->nodesetval->nodeNr)) {
872  xp->parent = 0;
873  sqlite3_result_null(ctx);
874  } else {
875  xmlNodePtr node = xp->pobj->nodesetval->nodeTab[xp->pos];
876  xmlBufferPtr buf = 0;
877 
878  xp->parent = node->parent;
879  if (node) {
880  switch (xp->conv) {
881  case 1:
882  p = (char *) xmlXPathCastNodeToString(node);
883  n = xmlXPathCastStringToBoolean((xmlChar *) p);
884  sqlite3_result_int(ctx, n);
885  if (p) {
886  xmlFree(p);
887  }
888  break;
889  case 2:
890  sqlite3_result_double(ctx,
891  xmlXPathCastNodeToNumber(node));
892  break;
893  case 3:
894  buf = xmlBufferCreate();
895  if (!buf) {
896  sqlite3_result_error(ctx, "out of memory", -1);
897  goto done;
898  }
899  xmlNodeDump(buf, xp->doc, node, 0, 0);
900  sqlite3_result_text(ctx, (char *) xmlBufferContent(buf),
901  xmlBufferLength(buf),
902  SQLITE_TRANSIENT);
903  xmlBufferFree(buf);
904  break;
905  default:
906  p = (char *) xmlXPathCastNodeToString(node);
907  sqlite3_result_text(ctx, p, -1, SQLITE_TRANSIENT);
908  if (p) {
909  xmlFree(p);
910  }
911  break;
912  }
913  } else {
914  sqlite3_result_null(ctx);
915  }
916  }
917  } else {
918  xp->parent = 0;
919  switch (xp->conv) {
920  case 1:
921  sqlite3_result_int(ctx, xmlXPathCastToBoolean(xp->pobj));
922  break;
923  case 2:
924  sqlite3_result_double(ctx, xmlXPathCastToNumber(xp->pobj));
925  break;
926  default:
927  p = (char *) xmlXPathCastToString(xp->pobj);
928  sqlite3_result_text(ctx, p, -1, SQLITE_TRANSIENT);
929  if (p) {
930  xmlFree(p);
931  }
932  break;
933  }
934  }
935 done:
936  if (pobj) {
937  xmlXPathFreeObject(pobj);
938  }
939  if (pctx) {
940  xmlXPathFreeContext(pctx);
941  }
942 }
943 
951 static void
952 xpath_vfunc_string(sqlite3_context *ctx, int argc, sqlite3_value **argv)
953 {
954  return xpath_vfunc_common(ctx, 0, argc, argv);
955 }
956 
964 static void
965 xpath_vfunc_boolean(sqlite3_context *ctx, int argc, sqlite3_value **argv)
966 {
967  return xpath_vfunc_common(ctx, 1, argc, argv);
968 }
969 
977 static void
978 xpath_vfunc_number(sqlite3_context *ctx, int argc, sqlite3_value **argv)
979 {
980  return xpath_vfunc_common(ctx, 2, argc, argv);
981 }
982 
990 static void
991 xpath_vfunc_xml(sqlite3_context *ctx, int argc, sqlite3_value **argv)
992 {
993  return xpath_vfunc_common(ctx, 3, argc, argv);
994 }
995 
1006 static int
1007 xpath_findfunc(sqlite3_vtab *vtab, int nargs, const char *name,
1008  void (**pfunc)(sqlite3_context *, int, sqlite3_value **),
1009  void **parg)
1010 {
1011  if (nargs != 2) {
1012  return 0;
1013  }
1014  if (!strcmp(name, "xpath_string")) {
1015  *pfunc = xpath_vfunc_string;
1016  *parg = vtab;
1017  return 1;
1018  }
1019  if (!strcmp(name, "xpath_boolean")) {
1020  *pfunc = xpath_vfunc_boolean;
1021  *parg = vtab;
1022  return 1;
1023  }
1024  if (!strcmp(name, "xpath_number")) {
1025  *pfunc = xpath_vfunc_number;
1026  *parg = vtab;
1027  return 1;
1028  }
1029  if (!strcmp(name, "xpath_xml")) {
1030  *pfunc = xpath_vfunc_xml;
1031  *parg = vtab;
1032  return 1;
1033  }
1034  return 0;
1035 }
1036 
1037 #if (SQLITE_VERSION_NUMBER > 3004000)
1038 
1045 static int
1046 xpath_rename(sqlite3_vtab *vtab, const char *newname)
1047 {
1048  return SQLITE_OK;
1049 }
1050 
1051 #endif
1052 
1057 static sqlite3_module xpath_mod = {
1058  1, /* iVersion */
1059  xpath_create, /* xCreate */
1060  xpath_connect, /* xConnect */
1061  xpath_bestindex, /* xBestIndex */
1062  xpath_disconnect, /* xDisconnect */
1063  xpath_destroy, /* xDestroy */
1064  xpath_open, /* xOpen */
1065  xpath_close, /* xClose */
1066  xpath_filter, /* xFilter */
1067  xpath_next, /* xNext */
1068  xpath_eof, /* xEof */
1069  xpath_column, /* xColumn */
1070  xpath_rowid, /* xRowid */
1071  xpath_update, /* xUpdate */
1072  0, /* xBegin */
1073  0, /* xSync */
1074  0, /* xCommit */
1075  0, /* xRollback */
1076  xpath_findfunc, /* xFindFunction */
1077 #if (SQLITE_VERSION_NUMBER > 3004000)
1078  xpath_rename, /* xRename */
1079 #endif
1080 };
1081 
1104 static void
1105 xpath_func_common(sqlite3_context *ctx, int conv,
1106  int argc, sqlite3_value **argv)
1107 {
1108  xmlDocPtr doc = 0, docToFree = 0;
1109  xmlXPathContextPtr pctx = 0;
1110  xmlXPathObjectPtr pobj = 0;
1111  XMOD *xm = (XMOD *) sqlite3_user_data(ctx);
1112  int index = 0;
1113  char *p;
1114 
1115  if (argc < 2) {
1116  sqlite3_result_null(ctx);
1117  goto done;
1118  }
1119  if (sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
1120  index = sqlite3_value_int(argv[0]);
1121  if (!xm->mutex) {
1122  sqlite3_result_error(ctx, "init error", -1);
1123  goto done;
1124  }
1125  sqlite3_mutex_enter(xm->mutex);
1126  if ((index <= 0) || (index > xm->sdoc) || !xm->docs[index - 1].doc) {
1127  sqlite3_mutex_leave(xm->mutex);
1128  sqlite3_result_error(ctx, "invalid DOCID", -1);
1129  goto done;
1130  }
1131  doc = xm->docs[index - 1].doc;
1132  xm->docs[index - 1].refcnt += 1;
1133  sqlite3_mutex_leave(xm->mutex);
1134  } else {
1135  int opts = (XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET);
1136  char *enc = 0, *url = 0;
1137 
1138  p = (char *) sqlite3_value_blob(argv[0]);
1139  if (!p) {
1140  sqlite3_result_null(ctx);
1141  return;
1142  }
1143  if ((argc > 2) && (sqlite3_value_type(argv[2]) != SQLITE_NULL)) {
1144  opts = sqlite3_value_int(argv[2]);
1145  }
1146  if ((argc > 3) && (sqlite3_value_type(argv[3]) != SQLITE_NULL)) {
1147  enc = (char *) sqlite3_value_text(argv[3]);
1148  }
1149  if ((argc > 4) && (sqlite3_value_type(argv[4]) != SQLITE_NULL)) {
1150  url = (char *) sqlite3_value_text(argv[4]);
1151  }
1152  doc = xmlReadMemory(p, sqlite3_value_bytes(argv[0]),
1153  url ? url : "", enc, opts);
1154  docToFree = doc;
1155  if (!doc) {
1156  sqlite3_result_error(ctx, "read error", -1);
1157  goto done;
1158  }
1159  }
1160  p = (char *) sqlite3_value_text(argv[1]);
1161  if (!p) {
1162  sqlite3_result_null(ctx);
1163  goto done;
1164  }
1165  pctx = xmlXPathNewContext(doc);
1166  if (!pctx) {
1167  sqlite3_result_error(ctx, "out of memory", -1);
1168  goto done;
1169  }
1170  pobj = xmlXPathEvalExpression((xmlChar *) p, pctx);
1171  if (!pobj) {
1172  sqlite3_result_error(ctx, "bad XPath expression", -1);
1173  goto done;
1174  }
1175  switch (conv) {
1176  case 1:
1177  sqlite3_result_int(ctx, xmlXPathCastToBoolean(pobj));
1178  break;
1179  case 2:
1180  sqlite3_result_double(ctx, xmlXPathCastToNumber(pobj));
1181  break;
1182  case 3:
1183  if ((pobj->type == XPATH_NODESET) && pobj->nodesetval &&
1184  (pobj->nodesetval->nodeNr)) {
1185  xmlNodePtr node = pobj->nodesetval->nodeTab[0];
1186  xmlBufferPtr buf = 0;
1187 
1188  buf = xmlBufferCreate();
1189  if (!buf) {
1190  sqlite3_result_error(ctx, "out of memory", -1);
1191  goto done;
1192  }
1193  xmlNodeDump(buf, doc, node, 0, 0);
1194  sqlite3_result_text(ctx, (char *) xmlBufferContent(buf),
1195  xmlBufferLength(buf), SQLITE_TRANSIENT);
1196  xmlBufferFree(buf);
1197  } else {
1198  sqlite3_result_null(ctx);
1199  }
1200  break;
1201  default:
1202  p = (char *) xmlXPathCastToString(pobj);
1203  sqlite3_result_text(ctx, p, -1, SQLITE_TRANSIENT);
1204  if (p) {
1205  xmlFree(p);
1206  }
1207  break;
1208  }
1209 done:
1210  if (pobj) {
1211  xmlXPathFreeObject(pobj);
1212  }
1213  if (pctx) {
1214  xmlXPathFreeContext(pctx);
1215  }
1216  if (docToFree) {
1217  xmlFreeDoc(docToFree);
1218  } else if (doc) {
1219  if (xm->mutex) {
1220  sqlite3_mutex_enter(xm->mutex);
1221  if (xm->docs && index) {
1222  xm->docs[index - 1].refcnt -= 1;
1223  if (xm->docs[index - 1].refcnt <= 0) {
1224  docToFree = doc;
1225  xm->docs[index - 1].refcnt = 0;
1226  xm->docs[index - 1].doc = 0;
1227  }
1228  }
1229  sqlite3_mutex_leave(xm->mutex);
1230  if (docToFree) {
1231  xmlFreeDoc(docToFree);
1232  }
1233  }
1234  }
1235 }
1236 
1244 static void
1245 xpath_func_string(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1246 {
1247  xpath_func_common(ctx, 0, argc, argv);
1248 }
1249 
1257 static void
1258 xpath_func_boolean(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1259 {
1260  xpath_func_common(ctx, 1, argc, argv);
1261 }
1262 
1270 static void
1271 xpath_func_number(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1272 {
1273  xpath_func_common(ctx, 2, argc, argv);
1274 }
1275 
1283 static void
1284 xpath_func_xml(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1285 {
1286  xpath_func_common(ctx, 3, argc, argv);
1287 }
1288 
1306 static void
1307 xpath_func_dump(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1308 {
1309  XMOD *xm = (XMOD *) sqlite3_user_data(ctx);
1310  int index = 0, dump_len = 0, fmt = 1;
1311  xmlChar *dump = 0;
1312  char *enc = "utf-8";
1313 
1314  if (argc < 1) {
1315  sqlite3_result_null(ctx);
1316  return;
1317  }
1318  index = sqlite3_value_int(argv[0]);
1319  if (argc > 1) {
1320  enc = (char *) sqlite3_value_text(argv[1]);
1321  if (!enc) {
1322  enc = "utf-8";
1323  }
1324  }
1325  if (argc > 2) {
1326  fmt = sqlite3_value_int(argv[2]);
1327  }
1328  if (!xm->mutex) {
1329  sqlite3_result_error(ctx, "init error", -1);
1330  return;
1331  }
1332  sqlite3_mutex_enter(xm->mutex);
1333  if ((index <= 0) || (index > xm->sdoc) || !xm->docs[index - 1].doc) {
1334  sqlite3_mutex_leave(xm->mutex);
1335  sqlite3_result_error(ctx, "invalid DOCID", -1);
1336  return;
1337  }
1338  xmlDocDumpFormatMemoryEnc(xm->docs[index - 1].doc, &dump, &dump_len,
1339  enc, fmt);
1340  if (dump) {
1341  sqlite3_result_text(ctx, (char *) dump, dump_len, SQLITE_TRANSIENT);
1342  xmlFree(dump);
1343  }
1344  sqlite3_mutex_leave(xm->mutex);
1345 }
1346 
1347 #ifdef WITH_XSLT
1348 
1371 static void
1372 xpath_func_transform(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1373 {
1374  xmlDocPtr doc = 0, docToFree = 0, res = 0;
1375  xsltStylesheetPtr cur = 0;
1376  XMOD *xm = (XMOD *) sqlite3_user_data(ctx);
1377  int index = 0, nparams = 0, param0, i;
1378  char *p;
1379  const char **params = 0;
1380 
1381  if (argc < 2) {
1382  sqlite3_result_null(ctx);
1383  goto done;
1384  }
1385  if (sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
1386  index = sqlite3_value_int(argv[0]);
1387  if (!xm->mutex) {
1388  sqlite3_result_error(ctx, "init error", -1);
1389  goto done;
1390  }
1391  sqlite3_mutex_enter(xm->mutex);
1392  if ((index <= 0) || (index > xm->sdoc) || !xm->docs[index - 1].doc) {
1393  sqlite3_mutex_leave(xm->mutex);
1394  sqlite3_result_error(ctx, "invalid DOCID", -1);
1395  goto done;
1396  }
1397  doc = xm->docs[index - 1].doc;
1398  xm->docs[index - 1].refcnt += 1;
1399  sqlite3_mutex_leave(xm->mutex);
1400  param0 = 2;
1401  nparams = argc - 2;
1402  } else {
1403  int opts = (XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET);
1404  char *enc = 0, *url = 0;
1405 
1406  p = (char *) sqlite3_value_blob(argv[0]);
1407  if (!p) {
1408  sqlite3_result_null(ctx);
1409  return;
1410  }
1411  if ((argc > 2) && (sqlite3_value_type(argv[2]) != SQLITE_NULL)) {
1412  opts = sqlite3_value_int(argv[2]);
1413  }
1414  if ((argc > 3) && (sqlite3_value_type(argv[3]) != SQLITE_NULL)) {
1415  enc = (char *) sqlite3_value_text(argv[3]);
1416  }
1417  if ((argc > 4) && (sqlite3_value_type(argv[4]) != SQLITE_NULL)) {
1418  url = (char *) sqlite3_value_text(argv[4]);
1419  }
1420  doc = xmlReadMemory(p, sqlite3_value_bytes(argv[0]),
1421  url ? url : "", enc, opts);
1422  docToFree = doc;
1423  if (!doc) {
1424  sqlite3_result_error(ctx, "read error", -1);
1425  goto done;
1426  }
1427  param0 = 5;
1428  nparams = argc - 5;
1429  }
1430  p = (char *) sqlite3_value_text(argv[1]);
1431  if (!p) {
1432  sqlite3_result_null(ctx);
1433  goto done;
1434  }
1435  cur = xsltParseStylesheetFile((xmlChar *) p);
1436  if (!cur) {
1437  sqlite3_result_error(ctx, "read error on stylesheet", -1);
1438  goto done;
1439  }
1440  if (nparams <= 0) {
1441  nparams = 1;
1442  } else {
1443  nparams++;
1444  }
1445  params = sqlite3_malloc(nparams * sizeof (char *));
1446  if (!params) {
1447  sqlite3_result_error(ctx, "out of memory", -1);
1448  goto done;
1449  }
1450  for (i = 0; i < (argc - param0); i++) {
1451  params[i] = (const char *) sqlite3_value_text(argv[i + param0]);
1452  if (!params[i]) {
1453  params[i] = "";
1454  }
1455  }
1456  params[i] = 0;
1457  res = xsltApplyStylesheet(cur, doc, params);
1458  if (!res) {
1459  sqlite3_result_error(ctx, "transformation failed", -1);
1460  goto done;
1461  }
1462  if (docToFree) {
1463  xmlChar *str = 0;
1464 
1465  xmlFreeDoc(docToFree);
1466  docToFree = res;
1467  i = 0;
1468  xsltSaveResultToString(&str, &i, res, cur);
1469  if (str) {
1470  sqlite3_result_text(ctx, (char *) str, i, SQLITE_TRANSIENT);
1471  xmlFree(str);
1472  } else {
1473  sqlite3_result_null(ctx);
1474  }
1475  }
1476 done:
1477  if (params) {
1478  sqlite3_free(params);
1479  }
1480  if (cur) {
1481  xsltFreeStylesheet(cur);
1482  }
1483  if (docToFree) {
1484  xmlFreeDoc(docToFree);
1485  } else if (doc) {
1486  if (xm->mutex) {
1487  sqlite3_mutex_enter(xm->mutex);
1488  if (xm->docs && index) {
1489  docToFree = doc;
1490  xm->docs[index - 1].doc = 0;
1491  xmlFreeDoc(docToFree);
1492  docToFree = 0;
1493  xm->docs[index - 1].refcnt -= 1;
1494  xm->docs[index - 1].doc = res;
1495  if (xm->docs[index - 1].refcnt <= 0) {
1496  docToFree = res;
1497  xm->docs[index - 1].refcnt = 0;
1498  xm->docs[index - 1].doc = 0;
1499  }
1500  }
1501  sqlite3_mutex_leave(xm->mutex);
1502  if (docToFree) {
1503  xmlFreeDoc(docToFree);
1504  }
1505  }
1506  }
1507 }
1508 #endif
1509 
1516 static void
1517 xpath_fini(void *aux)
1518 {
1519  XMOD *xm = (XMOD *) aux;
1520  XDOC *docs;
1521  int i, n, cleanup = 0;
1522  sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
1523 
1524  if (!mutex) {
1525  return;
1526  }
1527  sqlite3_mutex_enter(mutex);
1528  if (initialized) {
1529  xm->refcnt--;
1530  if (xm->refcnt <= 0) {
1531  xmod = 0;
1532  initialized = 0;
1533  cleanup = 1;
1534  }
1535  } else {
1536  cleanup = 1;
1537  }
1538  sqlite3_mutex_leave(mutex);
1539  if (cleanup) {
1540  sqlite3_mutex_enter(xm->mutex);
1541  mutex = xm->mutex;
1542  xm->mutex = 0;
1543  docs = xm->docs;
1544  n = xm->ndoc;
1545  xm->docs = 0;
1546  xm->sdoc = xm->ndoc = 0;
1547  sqlite3_mutex_leave(mutex);
1548  sqlite3_mutex_free(mutex);
1549  for (i = 0; i < n; i++) {
1550  if (docs->refcnt <= 0) {
1551  xmlFreeDoc(docs->doc);
1552  docs->doc = 0;
1553  }
1554  }
1555  sqlite3_free(docs);
1556  sqlite3_free(xm);
1557  }
1558 }
1559 
1566 #ifndef STANDALONE
1567 static
1568 #endif
1569 int
1570 xpath_init(sqlite3 *db)
1571 {
1572  XMOD *xm;
1573  int rc;
1574  sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
1575 
1576  if (!mutex) {
1577  return SQLITE_NOMEM;
1578  }
1579  sqlite3_mutex_enter(mutex);
1580  if (!initialized) {
1581  xm = sqlite3_malloc(sizeof (XMOD));
1582  if (!xm) {
1583  sqlite3_mutex_leave(mutex);
1584  return SQLITE_NOMEM;
1585  }
1586  xm->refcnt = 1;
1587  xm->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
1588  if (!xm->mutex) {
1589  sqlite3_mutex_leave(mutex);
1590  sqlite3_free(xm);
1591  return SQLITE_NOMEM;
1592  }
1593  xm->sdoc = 128;
1594  xm->ndoc = 0;
1595  xm->docs = sqlite3_malloc(xm->sdoc * sizeof (XDOC));
1596  if (!xm->docs) {
1597  sqlite3_mutex_leave(mutex);
1598  sqlite3_mutex_free(xm->mutex);
1599  sqlite3_free(xm);
1600  return SQLITE_NOMEM;
1601  }
1602  memset(xm->docs, 0, xm->sdoc * sizeof (XDOC));
1603  xmod = xm;
1604  initialized = 1;
1605  } else {
1606  xm = xmod;
1607  xm->refcnt++;
1608  }
1609  sqlite3_mutex_leave(mutex);
1610  sqlite3_create_function(db, "xpath_string", -1, SQLITE_UTF8,
1611  (void *) xm, xpath_func_string, 0, 0);
1612  sqlite3_create_function(db, "xpath_boolean", -1, SQLITE_UTF8,
1613  (void *) xm, xpath_func_boolean, 0, 0);
1614  sqlite3_create_function(db, "xpath_number", -1, SQLITE_UTF8,
1615  (void *) xm, xpath_func_number, 0, 0);
1616  sqlite3_create_function(db, "xpath_xml", -1, SQLITE_UTF8,
1617  (void *) xm, xpath_func_xml, 0, 0);
1618  sqlite3_create_function(db, "xml_dump", -1, SQLITE_UTF8,
1619  (void *) xm, xpath_func_dump, 0, 0);
1620 #ifdef WITH_XSLT
1621  sqlite3_create_function(db, "xslt_transform", -1, SQLITE_UTF8,
1622  (void *) xm, xpath_func_transform, 0, 0);
1623 #endif
1624  rc = sqlite3_create_module_v2(db, "xpath", &xpath_mod,
1625  (void *) xm, xpath_fini);
1626  if (rc != SQLITE_OK) {
1627  sqlite3_create_function(db, "xpath_string", -1, SQLITE_UTF8,
1628  (void *) xm, 0, 0, 0);
1629  sqlite3_create_function(db, "xpath_boolean", -1, SQLITE_UTF8,
1630  (void *) xm, 0, 0, 0);
1631  sqlite3_create_function(db, "xpath_number", -1, SQLITE_UTF8,
1632  (void *) xm, 0, 0, 0);
1633  sqlite3_create_function(db, "xpath_xml", -1, SQLITE_UTF8,
1634  (void *) xm, 0, 0, 0);
1635  sqlite3_create_function(db, "xml_dump", -1, SQLITE_UTF8,
1636  (void *) xm, 0, 0, 0);
1637 #ifdef WITH_XSLT
1638  sqlite3_create_function(db, "xslt_transform", -1, SQLITE_UTF8,
1639  (void *) xm, 0, 0, 0);
1640 #endif
1641  xpath_fini(xm);
1642  }
1643  return rc;
1644 }
1645 
1646 #ifndef STANDALONE
1647 
1656 int
1657 sqlite3_extension_init(sqlite3 *db, char **errmsg,
1658  const sqlite3_api_routines *api)
1659 {
1660  SQLITE_EXTENSION_INIT2(api);
1661  return xpath_init(db);
1662 }
1663 
1664 #endif
xmlXPathContextPtr pctx
Current XPath context.
Definition: xpath.c:95
static SQLRETURN nomem(STMT *s)
Report S1000 (out of memory) SQL error given STMT.
Definition: sqlite3odbc.c:1830
struct XEXP * prev
Previous item.
Definition: xpath.c:93
int refcnt
Reference counter.
Definition: xpath.c:49
static sqlite3_module xpath_mod
SQLite module descriptor.
Definition: xpath.c:1057
struct XTAB XTAB
xmlNodePtr parent
Current parent node or NULL.
Definition: xpath.c:97
int conv
Conversion: string/boolean/number.
Definition: xpath.c:99
int sdoc
Size of idocs array.
Definition: xpath.c:80
static int xpath_init(sqlite3 *db)
Module initializer creating SQLite module and functions.
Definition: xpath.c:1570
static void xpath_func_dump(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Function to dump XML document.
Definition: xpath.c:1307
static void xpath_func_boolean(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning boolean value.
Definition: xpath.c:1258
static void xpath_fini(void *aux)
Module finalizer.
Definition: xpath.c:1517
static void xpath_vfunc_number(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning number from virtual table.
Definition: xpath.c:978
int ndoc
Number of used entries in docs array.
Definition: xpath.c:62
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
xmlXPathObjectPtr pobj
Current XPath objects.
Definition: xpath.c:96
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:756
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:1007
struct XCSR * xc
Current cursor.
Definition: xpath.c:79
xmlDocPtr doc
Current XML document.
Definition: xpath.c:94
int ndoc
Number of used entries in idocs array.
Definition: xpath.c:81
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_column(sqlite3_vtab_cursor *cursor, sqlite3_context *ctx, int n)
Return column data of virtual table.
Definition: xpath.c:461
static int initialized
Definition: xpath.c:66
char expr[1]
XPath expression text.
Definition: xpath.c:100
int nexpr
Number of XPath expr.
Definition: xpath.c:112
sqlite3_mutex * mutex
DOC table mutex.
Definition: xpath.c:60
int refcnt
Reference counter.
Definition: xpath.c:59
XMOD * xm
Module data.
Definition: xpath.c:78
struct XCSR XCSR
static int xpath_rowid(sqlite3_vtab_cursor *cursor, sqlite3_int64 *rowidp)
Return current rowid of virtual table cursor.
Definition: xpath.c:505
static void xpath_func_string(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning string value.
Definition: xpath.c:1245
struct XEXP XEXP
XEXP * first
First XPath expr.
Definition: xpath.c:113
static XMOD * xmod
Definition: xpath.c:67
sqlite3_vtab_cursor cursor
SQLite virtual table cursor.
Definition: xpath.c:110
Structure to cache XML document.
Definition: xpath.c:47
static void xpath_func_common(sqlite3_context *ctx, int conv, int argc, sqlite3_value **argv)
Common XPath select function.
Definition: xpath.c:1105
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
XEXP * last
Last XPath expr.
Definition: xpath.c:114
static void xpath_func_xml(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning XML.
Definition: xpath.c:1284
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
static int xpath_next(sqlite3_vtab_cursor *cursor)
Retrieve next row from virtual table cursor.
Definition: xpath.c:321
int sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api)
Initializer for SQLite extension load mechanism.
Definition: xpath.c:1657
static int xpath_destroy(sqlite3_vtab *vtab)
Destroy virtual table.
Definition: xpath.c:242
struct XMOD XMOD
static void xpath_func_number(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning number.
Definition: xpath.c:1271
Structure to describe virtual table cursor.
Definition: xpath.c:109
int pos
Current index.
Definition: xpath.c:111
XDOC * docs
Array of modules's DOCs.
Definition: xpath.c:63
Structure to describe virtual table.
Definition: xpath.c:75
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:952
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_xml(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning XML from virtual table.
Definition: xpath.c:991
int * idocs
Indexes in module-wide DOC table.
Definition: xpath.c:82
sqlite3 * db
Open database.
Definition: xpath.c:77
Structure holding per module/database data.
Definition: xpath.c:58
static int xpath_bestindex(sqlite3_vtab *vtab, sqlite3_index_info *info)
Determines information for filter function according to constraints.
Definition: xpath.c:255
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:965
int sdoc
Size of docs array.
Definition: xpath.c:61
xmlDocPtr doc
XML document.
Definition: xpath.c:48
static int xpath_disconnect(sqlite3_vtab *vtab)
Disconnect virtual table.
Definition: xpath.c:205
static int xpath_eof(sqlite3_vtab_cursor *cursor)
Return end of table state of virtual table cursor.
Definition: xpath.c:444
Structure to describe XPath expression.
Definition: xpath.c:91
int pos
Position within XPath expr.
Definition: xpath.c:98
sqlite3_vtab vtab
SQLite virtual table.
Definition: xpath.c:76
static int xpath_close(sqlite3_vtab_cursor *cursor)
Close virtual table cursor.
Definition: xpath.c:290
struct XEXP * next
Next item.
Definition: xpath.c:92
struct XDOC XDOC

Generated on Sun Oct 25 2015 by doxygen.
Contact: chw@ch-werner.de