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];
102 
109 typedef struct XCSR {
110  sqlite3_vtab_cursor cursor;
111  int pos;
112  int nexpr;
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  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  }
715 done:
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;
730 nomem:
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 
756 static void
757 xpath_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  }
936 done:
937  if (pobj) {
938  xmlXPathFreeObject(pobj);
939  }
940  if (pctx) {
941  xmlXPathFreeContext(pctx);
942  }
943 }
944 
952 static void
953 xpath_vfunc_string(sqlite3_context *ctx, int argc, sqlite3_value **argv)
954 {
955  return xpath_vfunc_common(ctx, 0, argc, argv);
956 }
957 
965 static void
966 xpath_vfunc_boolean(sqlite3_context *ctx, int argc, sqlite3_value **argv)
967 {
968  return xpath_vfunc_common(ctx, 1, argc, argv);
969 }
970 
978 static void
979 xpath_vfunc_number(sqlite3_context *ctx, int argc, sqlite3_value **argv)
980 {
981  return xpath_vfunc_common(ctx, 2, argc, argv);
982 }
983 
991 static void
992 xpath_vfunc_xml(sqlite3_context *ctx, int argc, sqlite3_value **argv)
993 {
994  return xpath_vfunc_common(ctx, 3, argc, argv);
995 }
996 
1007 static int
1008 xpath_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 
1046 static int
1047 xpath_rename(sqlite3_vtab *vtab, const char *newname)
1048 {
1049  return SQLITE_OK;
1050 }
1051 
1052 #endif
1053 
1058 static 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 
1105 static void
1106 xpath_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  }
1210 done:
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 
1245 static void
1246 xpath_func_string(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1247 {
1248  xpath_func_common(ctx, 0, argc, argv);
1249 }
1250 
1258 static void
1259 xpath_func_boolean(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1260 {
1261  xpath_func_common(ctx, 1, argc, argv);
1262 }
1263 
1271 static void
1272 xpath_func_number(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1273 {
1274  xpath_func_common(ctx, 2, argc, argv);
1275 }
1276 
1284 static void
1285 xpath_func_xml(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1286 {
1287  xpath_func_common(ctx, 3, argc, argv);
1288 }
1289 
1307 static void
1308 xpath_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
1372 static void
1373 xpath_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  }
1477 done:
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 
1517 static void
1518 xpath_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
1568 static
1569 #endif
1570 int
1571 xpath_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 
1657 int
1658 sqlite3_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.
Definition: sqlite3odbc.c:1812
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
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
struct XTAB XTAB
static void xpath_func_xml(sqlite3_context *ctx, int argc, sqlite3_value **argv)
XPath select function returning XML.
Definition: xpath.c:1285
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
struct XMOD XMOD
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_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
static int initialized
Definition: xpath.c:66
struct XEXP XEXP
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 XCSR XCSR
struct XDOC XDOC

Generated on Mon Aug 17 2020 by doxygen.
Contact: chw@ch-werner.de