blobtoxy.c
Go to the documentation of this file.
1 
186 #ifdef STANDALONE
187 #include <sqlite3.h>
188 #else
189 #include <sqlite3ext.h>
190 static SQLITE_EXTENSION_INIT1
191 #endif
192 
193 #include <stdlib.h>
194 #include <string.h>
195 #include <stdarg.h>
196 #include <stdio.h>
197 
198 #ifdef _WIN32
199 #define strcasecmp _stricmp
200 #define strncasecmp _strnicmp
201 #define vsnprintf _vsnprintf
202 #endif
203 
204 #define TYPE_CODE(num, type) (((num) << 8) | (sizeof (type)))
205 #define TYPE_SIZE(code) ((code) & 0xFF)
206 
207 #define TYPE_CHAR TYPE_CODE( 0, char)
208 #define TYPE_UCHAR TYPE_CODE( 1, char)
209 #define TYPE_SHORT_LE TYPE_CODE( 2, short)
210 #define TYPE_USHORT_LE TYPE_CODE( 3, short)
211 #define TYPE_SHORT_BE TYPE_CODE( 4, short)
212 #define TYPE_USHORT_BE TYPE_CODE( 5, short)
213 #define TYPE_INT_LE TYPE_CODE( 6, int)
214 #define TYPE_UINT_LE TYPE_CODE( 7, int)
215 #define TYPE_INT_BE TYPE_CODE( 8, int)
216 #define TYPE_UINT_BE TYPE_CODE( 9, int)
217 #define TYPE_BIGINT_LE TYPE_CODE(10, sqlite_int64)
218 #define TYPE_BIGINT_BE TYPE_CODE(11, sqlite_int64)
219 #define TYPE_FLOAT TYPE_CODE(12, float)
220 #define TYPE_DOUBLE TYPE_CODE(13, double)
221 
228 typedef struct b2xy_table {
229  sqlite3_vtab base;
230  sqlite3 *db;
231  char *master_table;
233  char *key_column;
234  char *blob_column;
240  int type;
241  int do_x_sl;
243  int argc;
244  char **argv;
245 } b2xy_table;
246 
253 typedef struct b2xy_cursor {
254  sqlite3_vtab_cursor base;
256  sqlite3_stmt *select;
257  sqlite3_value *key;
258  int fix_cols;
259  int num_cols;
260  char *val;
261  int val_len;
264  double x_scale, x_offset;
267  double y_scale, y_offset;
270  int do_x_sl;
272  int type;
273  int index;
275  sqlite_int64 rowid;
276 } b2xy_cursor;
277 
284 static int
285 string_to_type(const char *str)
286 {
287  if (strcasecmp(str, "char") == 0) {
288  return TYPE_CHAR;
289  }
290  if (strcasecmp(str, "uchar") == 0) {
291  return TYPE_UCHAR;
292  }
293  if (strcasecmp(str, "short_le") == 0) {
294  return TYPE_SHORT_LE;
295  }
296  if (strcasecmp(str, "ushort_le") == 0) {
297  return TYPE_USHORT_LE;
298  }
299  if (strcasecmp(str, "short_be") == 0) {
300  return TYPE_SHORT_BE;
301  }
302  if (strcasecmp(str, "ushort_be") == 0) {
303  return TYPE_USHORT_BE;
304  }
305  if (strcasecmp(str, "int_le") == 0) {
306  return TYPE_INT_LE;
307  }
308  if (strcasecmp(str, "uint_le") == 0) {
309  return TYPE_UINT_LE;
310  }
311  if (strcasecmp(str, "int_be") == 0) {
312  return TYPE_INT_BE;
313  }
314  if (strcasecmp(str, "uint_be") == 0) {
315  return TYPE_UINT_BE;
316  }
317  if (strcasecmp(str, "bigint_le") == 0) {
318  return TYPE_BIGINT_LE;
319  }
320  if (strcasecmp(str, "bigint_be") == 0) {
321  return TYPE_BIGINT_BE;
322  }
323  if (strcasecmp(str, "float") == 0) {
324  return TYPE_FLOAT;
325  }
326  if (strcasecmp(str, "double") == 0) {
327  return TYPE_DOUBLE;
328  }
329  return 0;
330 }
331 
338 static int
339 b2xy_destroy(sqlite3_vtab *vtab)
340 {
341  b2xy_table *bt = (b2xy_table *) vtab;
342 
343  sqlite3_free(bt);
344  return SQLITE_OK;
345 }
346 
375 static int
376 b2xy_create(sqlite3 *db, void *userdata, int argc,
377  const char * const *argv, sqlite3_vtab **vtabret, char **errp)
378 {
379  int rc = SQLITE_NOMEM;
380  b2xy_table *bt;
381  int i, size, type = TYPE_CHAR;
382  int x_start = -1, x_length = 0;
383 
384  if (argc < 6) {
385  *errp = sqlite3_mprintf("need at least 3 arguments");
386  return SQLITE_ERROR;
387  }
388  if (argc > 6) {
389  type = string_to_type(argv[6]);
390  if (!type) {
391  *errp = sqlite3_mprintf("unsupported type %Q", argv[6]);
392  return SQLITE_ERROR;
393  }
394  }
395  if (argc > 11) {
396  if ((argv[11][0] != '"') && (argv[11][0] != '\'')) {
397  *errp = sqlite3_mprintf("other columns must be quoted");
398  return SQLITE_ERROR;
399  }
400  }
401  if (argc > 12) {
402  char *endp = 0;
403 
404  x_start = strtol(argv[12], &endp, 10);
405  if ((endp == argv[12]) || (endp && (endp[0] != '\0'))) {
406  *errp = sqlite3_mprintf("X start index must be integer");
407  return SQLITE_ERROR;
408  }
409  if (x_start < 0) {
410  *errp = sqlite3_mprintf("X start index must be >= 0");
411  return SQLITE_ERROR;
412  }
413  }
414  if (argc > 13) {
415  char *endp = 0;
416 
417  x_length = strtol(argv[13], &endp, 10);
418  if ((endp == argv[13]) || (endp && (endp[0] != '\0'))) {
419  *errp = sqlite3_mprintf("X length must be integer");
420  return SQLITE_ERROR;
421  }
422  if (x_length <= 0) {
423  *errp = sqlite3_mprintf("X length must be > 0");
424  return SQLITE_ERROR;
425  }
426  }
427  size = sizeof (char *) * argc;
428  for (i = 0; i < argc; i++) {
429  size += argv[i] ? (strlen(argv[i]) + 1) : 0;
430  }
431  /* additional space for '"' + argv[1] '"."' + argv[3] + '"' */
432  size += argv[1] ? (strlen(argv[1]) + 3) : 3;
433  size += argv[3] ? (strlen(argv[3]) + 3) : 0;
434  bt = sqlite3_malloc(sizeof (b2xy_table) + size);
435  if (bt) {
436  char *p, *key_type = 0, *x_type, *y_type, *other_types = 0;
437 
438  memset(bt, 0, sizeof (b2xy_table) + size);
439  bt->db = db;
440  bt->type = type;
441  bt->x_start = x_start;
442  bt->x_length = x_length;
443  bt->do_x_sl = (x_start >= 0) || (x_length > 0);
444  if (bt->x_start < 0) {
445  bt->x_start = 0;
446  }
447  bt->argc = argc;
448  bt->argv = (char **) (bt + 1);
449  p = (char *) (bt->argv + argc);
450  for (i = 0; i < argc; i++) {
451  if (argv[i]) {
452  bt->argv[i] = p;
453  strcpy(p, argv[i]);
454  p += strlen(p) + 1;
455  }
456  }
457  bt->master_table = bt->argv[3];
458  bt->fq_master_table = p;
459  p[0] = '\0';
460  if (bt->argv[1]) {
461  strcat(p, "\"");
462  strcat(p, bt->argv[1]);
463  strcat(p, "\".");
464  }
465  if (bt->argv[3]) {
466  strcat(p, "\"");
467  strcat(p, bt->argv[3]);
468  strcat(p, "\"");
469  }
470  bt->key_column = bt->argv[4];
471  bt->blob_column = bt->argv[5];
472  if ((bt->argc > 7) && bt->argv[7][0]) {
473  bt->x_scale_column = bt->argv[7];
474  if (strcasecmp(bt->x_scale_column, "null") == 0) {
475  bt->x_scale_column = 0;
476  }
477  }
478  if ((bt->argc > 8) && bt->argv[8][0]) {
479  bt->x_offset_column = bt->argv[8];
480  if (strcasecmp(bt->x_offset_column, "null") == 0) {
481  bt->x_offset_column = 0;
482  }
483  }
484  if ((bt->argc > 9) && bt->argv[9][0]) {
485  bt->y_scale_column = bt->argv[9];
486  if (strcasecmp(bt->y_scale_column, "null") == 0) {
487  bt->y_scale_column = 0;
488  }
489  }
490  if ((bt->argc > 10) && bt->argv[10][0]) {
491  bt->y_offset_column = bt->argv[10];
492  if (strcasecmp(bt->y_offset_column, "null") == 0) {
493  bt->y_offset_column = 0;
494  }
495  }
496  if (bt->argc > 11) {
497  p = bt->argv[11];
498  p[0] = ',';
499  bt->other_columns = p;
500  p += strlen(p) - 1;
501  if ((*p == '"') || (*p == '\'')) {
502  *p = '\0';
503  }
504  } else {
505  bt->other_columns = "";
506  }
507  /* find out types of key and x/y columns */
508  if (bt->x_scale_column || bt->x_offset_column ||
509  (bt->type == TYPE_FLOAT) || (bt->type == TYPE_DOUBLE)) {
510  x_type = " DOUBLE";
511  } else {
512  x_type = " INTEGER";
513  }
514  if (bt->y_scale_column || bt->y_offset_column ||
515  (bt->type == TYPE_FLOAT) || (bt->type == TYPE_DOUBLE)) {
516  y_type = " DOUBLE";
517  } else {
518  y_type = " INTEGER";
519  }
520  p = sqlite3_mprintf("PRAGMA %Q.table_info(%Q)",
521  bt->argv[1] ? bt->argv[1] : "MAIN",
522  bt->master_table);
523  if (p) {
524  int nrows = 0, ncols = 0;
525  char **rows = 0;
526 
527  rc = sqlite3_get_table(db, p, &rows, &nrows, &ncols, 0);
528  sqlite3_free(p);
529  if (rc == SQLITE_OK) {
530  for (i = 1; (ncols >= 3) && (i <= nrows); i++) {
531  p = rows[i * ncols + 1];
532  if (p && (strcasecmp(bt->key_column, p) == 0)) {
533  key_type = sqlite3_mprintf(" %s", rows[i * ncols + 2]);
534  break;
535  }
536  }
537  }
538  if (rows) {
539  sqlite3_free_table(rows);
540  }
541  }
542  /* find out types of other columns */
543  p = 0;
544  if (bt->other_columns[0]) {
545  p = sqlite3_mprintf("SELECT %s FROM %s WHERE 0",
546  bt->other_columns + 1, bt->fq_master_table);
547  }
548  if (p) {
549  sqlite3_stmt *stmt = 0;
550 
551 #if defined(HAVE_SQLITE3PREPAREV2) && HAVE_SQLITE3PREPAREV2
552  rc = sqlite3_prepare_v2(db, p, -1, &stmt, 0);
553 #else
554  rc = sqlite3_prepare(db, p, -1, &stmt, 0);
555 #endif
556  sqlite3_free(p);
557  if ((rc == SQLITE_OK) && stmt) {
558  sqlite3_step(stmt);
559  for (i = 0; i < sqlite3_column_count(stmt); i++) {
560  p = sqlite3_mprintf("%s%s\"%s\" %s",
561  other_types ? other_types : "",
562  other_types ? "," : "",
563  sqlite3_column_name(stmt, i),
564  sqlite3_column_decltype(stmt, i));
565  sqlite3_free(other_types);
566  other_types = 0;
567  if (p) {
568  other_types = p;
569  } else {
570  break;
571  }
572  }
573  sqlite3_finalize(stmt);
574  if (other_types) {
575  p = sqlite3_mprintf(",%s", other_types);
576  sqlite3_free(other_types);
577  other_types = p;
578  }
579  }
580  }
581  p = sqlite3_mprintf("CREATE TABLE \"%s\"(key%s CONSTRAINT fk "
582  "REFERENCES \"%s\"(\"%s\"),x%s,y%s%s)",
583  argv[2], key_type ? key_type : "",
584  bt->master_table, bt->key_column,
585  x_type, y_type,
586  other_types ? other_types : bt->other_columns);
587  if (key_type) {
588  sqlite3_free(key_type);
589  }
590  if (other_types) {
591  sqlite3_free(other_types);
592  }
593  if (p) {
594  rc = sqlite3_declare_vtab(db, p);
595  sqlite3_free(p);
596  }
597  if (rc != SQLITE_OK) {
598  b2xy_destroy((sqlite3_vtab *) bt);
599  bt = 0;
600  }
601  }
602  *vtabret = (sqlite3_vtab *) bt;
603  return rc;
604 }
605 
613 static int
614 b2xy_open(sqlite3_vtab *vtab, sqlite3_vtab_cursor **curret)
615 {
616  int rc = SQLITE_NOMEM;
617  b2xy_table *bt = (b2xy_table *) vtab;
618  b2xy_cursor *bc;
619 
620  bc = sqlite3_malloc(sizeof (b2xy_cursor));
621  if (bc) {
622  memset(bc, 0, sizeof(b2xy_cursor));
623  bc->table = bt;
624  bc->type = bt->type;
625  bc->do_x_sl = bt->do_x_sl;
626  bc->x_start = bt->x_start;
627  bc->x_length = bt->x_length;
628  *curret = (sqlite3_vtab_cursor *) bc;
629  rc = SQLITE_OK;
630  }
631  return rc;
632 }
633 
640 static int
641 b2xy_close(sqlite3_vtab_cursor *cur)
642 {
643  b2xy_cursor *bc = (b2xy_cursor *) cur;
644 
645  sqlite3_finalize(bc->select);
646  sqlite3_free(bc);
647  return SQLITE_OK;
648 }
649 
658 static int
659 b2xy_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i)
660 {
661  b2xy_cursor *bc = (b2xy_cursor *) cur;
662  char *p;
663  double v;
664 
665  switch (i) {
666  case 0:
667  sqlite3_result_value(ctx, bc->key);
668  break;
669  case 1:
670  if (bc->do_x_scale) {
671  v = bc->index * bc->x_scale + bc->x_offset;
672  sqlite3_result_double(ctx, v);
673  } else {
674  sqlite3_result_int(ctx, bc->index);
675  }
676  break;
677  case 2:
678  if (!bc->val ||
679  ((bc->index + 1) * TYPE_SIZE(bc->type) > bc->val_len)) {
680  goto put_null;
681  }
682  p = bc->val + bc->index * TYPE_SIZE(bc->type);
683  switch (bc->type) {
684  case TYPE_CHAR:
685  if (bc->do_y_scale) {
686  v = p[0];
687  goto scale_it;
688  }
689  sqlite3_result_int(ctx, p[0]);
690  break;
691  case TYPE_UCHAR:
692  if (bc->do_y_scale) {
693  v = p[0] & 0xFF;
694  goto scale_it;
695  }
696  sqlite3_result_int(ctx, p[0] & 0xFF);
697  break;
698  case TYPE_SHORT_LE:
699  if (bc->do_y_scale) {
700  v = (p[0] & 0xFF) | (p[1] << 8);
701  goto scale_it;
702  }
703  sqlite3_result_int(ctx, (p[0] & 0xFF) | (p[1] << 8));
704  break;
705  case TYPE_USHORT_LE:
706  if (bc->do_y_scale) {
707  v = (p[0] & 0xFF) | ((p[1] & 0xFF) << 8);
708  goto scale_it;
709  }
710  sqlite3_result_int(ctx, (p[0] & 0xFF) | ((p[1] & 0xFF) << 8));
711  break;
712  case TYPE_SHORT_BE:
713  if (bc->do_y_scale) {
714  v = (p[1] & 0xFF) | (p[0] << 8);
715  goto scale_it;
716  }
717  sqlite3_result_int(ctx, (p[1] & 0xFF) | (p[0] << 8));
718  break;
719  case TYPE_USHORT_BE:
720  if (bc->do_y_scale) {
721  v = (p[1] & 0xFF) | ((p[0] & 0xFF) << 8);
722  goto scale_it;
723  }
724  sqlite3_result_int(ctx, (p[1] & 0xFF) | ((p[0] & 0xFF) << 8));
725  break;
726  case TYPE_INT_LE:
727  if (bc->do_y_scale) {
728  v = (p[0] & 0xFF) | ((p[1] & 0xFF) << 8) |
729  ((p[2] & 0xFF) << 16) | (p[3] << 24);
730  goto scale_it;
731  }
732  sqlite3_result_int64(ctx, (p[0] & 0xFF) |
733  ((p[1] & 0xFF) << 8) |
734  ((p[2] & 0xFF) << 16) |
735  (p[3] << 24));
736  break;
737  case TYPE_UINT_LE:
738  if (bc->do_y_scale) {
739  v = (p[0] & 0xFF) | ((p[1] & 0xFF) << 8) |
740  ((p[2] & 0xFF) << 16) | ((p[3] & 0xFF) << 24);
741  goto scale_it;
742  }
743  sqlite3_result_int64(ctx, (p[0] & 0xFF) |
744  ((p[1] & 0xFF) << 8) |
745  ((p[2] & 0xFF) << 16) |
746  ((p[3] & 0xFF) << 24));
747  break;
748  case TYPE_INT_BE:
749  if (bc->do_y_scale) {
750  v = (p[3] & 0xFF) | ((p[2] & 0xFF) << 8) |
751  ((p[1] & 0xFF) << 16) | (p[0] << 24);
752  goto scale_it;
753  }
754  sqlite3_result_int64(ctx, (p[3] & 0xFF) |
755  ((p[2] & 0xFF) << 8) |
756  ((p[1] & 0xFF) << 16) |
757  (p[0] << 24));
758  break;
759  case TYPE_UINT_BE:
760  if (bc->do_y_scale) {
761  v = (p[3] & 0xFF) | ((p[2] & 0xFF) << 8) |
762  ((p[1] & 0xFF) << 16) | ((p[0] & 0xFF) << 24);
763  goto scale_it;
764  }
765  sqlite3_result_int64(ctx, (p[3] & 0xFF) |
766  ((p[2] & 0xFF) << 8) |
767  ((p[1] & 0xFF) << 16) |
768  ((p[0] & 0xFF) << 24));
769  break;
770  case TYPE_BIGINT_LE:
771  if (bc->do_y_scale) {
772  v = (p[0] & 0xFFLL) | ((p[1] & 0xFFLL) << 8) |
773  ((p[2] & 0xFFLL) << 16) | ((p[3] & 0xFFLL) << 24) |
774  ((p[4] & 0xFFLL) << 32) | ((p[5] & 0xFFLL) << 40) |
775  ((p[6] & 0xFFLL) << 48) | ((p[6] & 0xFFLL) << 56);
776  goto scale_it;
777  }
778  sqlite3_result_int64(ctx, (p[0] & 0xFFLL) |
779  ((p[1] & 0xFFLL) << 8) |
780  ((p[2] & 0xFFLL) << 16) |
781  ((p[3] & 0xFFLL) << 24) |
782  ((p[4] & 0xFFLL) << 32) |
783  ((p[5] & 0xFFLL) << 40) |
784  ((p[6] & 0xFFLL) << 48) |
785  ((p[7] & 0xFFLL) << 56));
786  break;
787  case TYPE_BIGINT_BE:
788  if (bc->do_y_scale) {
789  v = (p[7] & 0xFFLL) | ((p[6] & 0xFFLL) << 8) |
790  ((p[5] & 0xFFLL) << 16) | ((p[4] & 0xFFLL) << 24) |
791  ((p[3] & 0xFFLL) << 32) | ((p[2] & 0xFFLL) << 40) |
792  ((p[1] & 0xFFLL) << 48) | ((p[0] & 0xFFLL) << 56);
793  goto scale_it;
794  }
795  sqlite3_result_int64(ctx, (p[7] & 0xFFLL) |
796  ((p[6] & 0xFFLL) << 8) |
797  ((p[5] & 0xFFLL) << 16) |
798  ((p[4] & 0xFFLL) << 24) |
799  ((p[3] & 0xFFLL) << 32) |
800  ((p[2] & 0xFFLL) << 40) |
801  ((p[1] & 0xFFLL) << 48) |
802  ((p[0] & 0xFFLL) << 56));
803  break;
804  case TYPE_FLOAT:
805  v = ((float *) p)[0];
806  goto scale_it;
807  case TYPE_DOUBLE:
808  v = ((double *) p)[0];
809  if (bc->do_y_scale) {
810  scale_it:
811  v = v * bc->y_scale + bc->y_offset;
812  }
813  sqlite3_result_double(ctx, v);
814  break;
815  default:
816  put_null:
817  sqlite3_result_null(ctx);
818  break;
819  }
820  break;
821  default:
822  i += bc->fix_cols - 3;
823  if ((i < 0) || (i >= bc->num_cols)) {
824  sqlite3_result_null(ctx);
825  } else {
826  sqlite3_result_value(ctx, sqlite3_column_value(bc->select, i));
827  }
828  break;
829  }
830  return SQLITE_OK;
831 }
832 
840 static int
841 b2xy_rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *rowidp)
842 {
843  b2xy_cursor *bc = (b2xy_cursor *) cur;
844 
845  *rowidp = bc->rowid;
846  return SQLITE_OK;
847 }
848 
855 static int
856 b2xy_eof(sqlite3_vtab_cursor *cur)
857 {
858  b2xy_cursor *bc = (b2xy_cursor *) cur;
859 
860  return bc->select ? 0 : 1;
861 }
862 
869 static int
870 b2xy_next(sqlite3_vtab_cursor *cur)
871 {
872  b2xy_cursor *bc = (b2xy_cursor *) cur;
873  b2xy_table *bt = bc->table;
874  int rc, dofetch = 0;
875 
876  if (!bc->select) {
877  return SQLITE_OK;
878  }
879  if (bc->val) {
880  bc->index += 1;
881  }
882  if (!bc->val) {
883  dofetch = 1;
884  } else if (bc->do_x_sl && bc->x_length) {
885  if (bc->index >= bc->x_start + bc->x_length) {
886  dofetch = 1;
887  }
888  } else if ((bc->index + 1) * TYPE_SIZE(bc->type) > bc->val_len) {
889  dofetch = 1;
890  }
891  if (dofetch) {
892 refetch:
893  rc = sqlite3_step(bc->select);
894 
895  if (rc == SQLITE_SCHEMA) {
896  rc = sqlite3_step(bc->select);
897  }
898  if (rc != SQLITE_ROW) {
899  sqlite3_finalize(bc->select);
900  bc->select = 0;
901  return SQLITE_OK;
902  }
903  bc->rowid_from_key = 0;
904  bc->index = bc->x_start;
905  bc->val = (char *) sqlite3_column_blob(bc->select, 1);
906  bc->val_len = sqlite3_column_bytes(bc->select, 1);
907  if (!bc->val) {
908  if (bc->do_x_sl && bc->x_length) {
909  bc->val = (char *) sqlite3_column_text(bc->select, 1);
910  if (!bc->val) {
911  goto refetch;
912  }
913  } else {
914  goto refetch;
915  }
916  }
917  if (!(bc->do_x_sl && bc->x_length) &&
918  (((bc->index + 1) * TYPE_SIZE(bc->type) > bc->val_len))) {
919  goto refetch;
920  }
921  bc->key = sqlite3_column_value(bc->select, 0);
922  if (sqlite3_column_type(bc->select, 0) == SQLITE_INTEGER) {
923  bc->rowid_from_key = 1;
924  bc->rowid = sqlite3_column_int64(bc->select, 0);
925  }
926  bc->do_x_scale = 0;
927  bc->x_scale = 1.0;
928  bc->x_offset = 0.0;
929  if (bt->x_scale_column) {
930  bc->x_scale = sqlite3_column_double(bc->select, bc->x_scale_col);
931  bc->do_x_scale++;
932  }
933  if (bt->x_offset_column) {
934  bc->x_offset = sqlite3_column_double(bc->select, bc->x_offset_col);
935  bc->do_x_scale++;
936  }
937  bc->do_y_scale = 0;
938  bc->y_scale = 1.0;
939  bc->y_offset = 0.0;
940  if (bt->y_scale_column) {
941  bc->y_scale = sqlite3_column_double(bc->select, bc->y_scale_col);
942  bc->do_y_scale++;
943  }
944  if (bt->y_offset_column) {
945  bc->y_offset = sqlite3_column_double(bc->select, bc->y_offset_col);
946  bc->do_y_scale++;
947  }
948  }
949  if (!bc->rowid_from_key) {
950  bc->rowid++;
951  }
952  return SQLITE_OK;
953 }
954 
965 static int
966 b2xy_filter(sqlite3_vtab_cursor *cur, int idxNum, const char *idxStr,
967  int argc, sqlite3_value **argv)
968 {
969  b2xy_cursor *bc = (b2xy_cursor *) cur;
970  b2xy_table *bt = bc->table;
971  char *query, *tmp, *op = 0;
972  int rc;
973 
974  bc->rowid_from_key = 0;
975  bc->rowid = 0;
976  if (bc->select) {
977  sqlite3_finalize(bc->select);
978  bc->select = 0;
979  }
980  bc->fix_cols = 2;
981  query = sqlite3_mprintf("select \"%s\",\"%s\"", bt->key_column,
982  bt->blob_column);
983  if (!query) {
984  return SQLITE_NOMEM;
985  }
986  if (bt->x_scale_column) {
987  tmp = sqlite3_mprintf("%s,\"%s\"", query, bt->x_scale_column);
988  sqlite3_free(query);
989  if (!tmp) {
990  return SQLITE_NOMEM;
991  }
992  query = tmp;
993  bc->x_scale_col = bc->fix_cols;
994  bc->fix_cols++;
995  }
996  if (bt->x_offset_column) {
997  tmp = sqlite3_mprintf("%s,\"%s\"", query, bt->x_offset_column);
998  sqlite3_free(query);
999  if (!tmp) {
1000  return SQLITE_NOMEM;
1001  }
1002  query = tmp;
1003  bc->x_offset_col = bc->fix_cols;
1004  bc->fix_cols++;
1005  }
1006  if (bt->y_scale_column) {
1007  tmp = sqlite3_mprintf("%s,\"%s\"", query, bt->y_scale_column);
1008  sqlite3_free(query);
1009  if (!tmp) {
1010  return SQLITE_NOMEM;
1011  }
1012  query = tmp;
1013  bc->y_scale_col = bc->fix_cols;
1014  bc->fix_cols++;
1015  }
1016  if (bt->y_offset_column) {
1017  tmp = sqlite3_mprintf("%s,\"%s\"", query, bt->y_offset_column);
1018  sqlite3_free(query);
1019  if (!tmp) {
1020  return SQLITE_NOMEM;
1021  }
1022  query = tmp;
1023  bc->y_offset_col = bc->fix_cols;
1024  bc->fix_cols++;
1025  }
1026  tmp = sqlite3_mprintf("%s%s from %s", query, bt->other_columns,
1027  bt->fq_master_table);
1028  sqlite3_free(query);
1029  if (!tmp) {
1030  return SQLITE_NOMEM;
1031  }
1032  query = tmp;
1033  if (idxNum && (argc > 0)) {
1034  switch (idxNum) {
1035  case SQLITE_INDEX_CONSTRAINT_EQ:
1036  op = "=";
1037  break;
1038  case SQLITE_INDEX_CONSTRAINT_GT:
1039  op = ">";
1040  break;
1041  case SQLITE_INDEX_CONSTRAINT_LE:
1042  op = "<=";
1043  break;
1044  case SQLITE_INDEX_CONSTRAINT_LT:
1045  op = "<";
1046  break;
1047  case SQLITE_INDEX_CONSTRAINT_GE:
1048  op = ">=";
1049  break;
1050  case SQLITE_INDEX_CONSTRAINT_MATCH:
1051  op = "like";
1052  break;
1053  }
1054  if (op) {
1055  tmp = sqlite3_mprintf("%s where \"%s\" %s ?",
1056  query, bt->key_column, op);
1057  sqlite3_free(query);
1058  if (!tmp) {
1059  return SQLITE_NOMEM;
1060  }
1061  query = tmp;
1062  }
1063  }
1064  if (idxStr) {
1065  tmp = sqlite3_mprintf("%s %s", query, idxStr);
1066  sqlite3_free(query);
1067  if (!tmp) {
1068  return SQLITE_NOMEM;
1069  }
1070  query = tmp;
1071  }
1072  bc->num_cols = bc->fix_cols;
1073 #if defined(HAVE_SQLITE3PREPAREV2) && HAVE_SQLITE3PREPAREV2
1074  rc = sqlite3_prepare_v2(bt->db, query, -1, &bc->select, 0);
1075 #else
1076  rc = sqlite3_prepare(bt->db, query, -1, &bc->select, 0);
1077  if (rc == SQLITE_SCHEMA) {
1078  rc = sqlite3_prepare(bt->db, query, -1, &bc->select, 0);
1079  }
1080 #endif
1081  sqlite3_free(query);
1082  if (rc == SQLITE_OK) {
1083  bc->num_cols = sqlite3_column_count(bc->select);
1084  if (op) {
1085  sqlite3_bind_value(bc->select, 1, argv[0]);
1086  }
1087  }
1088  return (rc == SQLITE_OK) ? b2xy_next(cur) : rc;
1089 }
1090 
1099 static int
1100 b2xy_bestindex(sqlite3_vtab *tab, sqlite3_index_info *info)
1101 {
1102  b2xy_table *bt = (b2xy_table *) tab;
1103  int i, key_order = 0, consumed = 0;
1104 
1105  /* preset to not using index */
1106  info->idxNum = 0;
1107 
1108  /*
1109  * Only when the key column of the master table
1110  * (0th column in virtual table) is used in a
1111  * constraint, a WHERE condition in the xFilter
1112  * function can be coded. This is indicated by
1113  * setting "idxNum" to the "op" value of that
1114  * constraint.
1115  */
1116  for (i = 0; i < info->nConstraint; ++i) {
1117  if (info->aConstraint[i].usable) {
1118  if ((info->aConstraint[i].iColumn == 0) &&
1119  (info->aConstraint[i].op != 0)) {
1120  info->idxNum = info->aConstraint[i].op;
1121  info->aConstraintUsage[i].argvIndex = 1;
1122  info->aConstraintUsage[i].omit = 1;
1123  info->estimatedCost = 1.0;
1124  break;
1125  }
1126  }
1127  }
1128 
1129  /*
1130  * ORDER BY can be optimized, when our X column
1131  * is not present or to be sorted ascending.
1132  * Additionally when the key column is to be sorted
1133  * an ORDER BY is sent to the xFilter function.
1134  */
1135  for (i = 0; i < info->nOrderBy; i++) {
1136  if (info->aOrderBy[i].iColumn == 0) {
1137  key_order = info->aOrderBy[i].desc ? -1 : 1;
1138  consumed++;
1139  } else if ((info->aOrderBy[i].iColumn == 1) &&
1140  !info->aOrderBy[i].desc) {
1141  consumed++;
1142  }
1143  }
1144  if (consumed) {
1145  /* check for other ORDER BY columns */
1146  for (i = 0; i < info->nOrderBy; i++) {
1147  if ((info->aOrderBy[i].iColumn == 1) &&
1148  info->aOrderBy[i].desc) {
1149  consumed = 0;
1150  } else if (info->aOrderBy[i].iColumn > 1) {
1151  consumed = 0;
1152  }
1153  }
1154  }
1155  if (consumed && key_order) {
1156  info->idxStr = sqlite3_mprintf("ORDER BY \"%s\" %s",
1157  bt->key_column,
1158  (key_order < 0) ? "DESC" : "ASC");
1159  info->needToFreeIdxStr = 1;
1160  }
1161  info->orderByConsumed = consumed;
1162  return SQLITE_OK;
1163 }
1164 
1165 #if (SQLITE_VERSION_NUMBER > 3004000)
1166 
1173 static int
1174 b2xy_rename(sqlite3_vtab *tab, const char *newname)
1175 {
1176  return SQLITE_OK;
1177 }
1178 
1179 #endif
1180 
1181 static const sqlite3_module b2xy_module = {
1182  1, /* iVersion */
1183  b2xy_create, /* xCreate */
1184  b2xy_create, /* xConnect */
1185  b2xy_bestindex, /* xBestIndex */
1186  b2xy_destroy, /* xDisconnect */
1187  b2xy_destroy, /* xDestroy */
1188  b2xy_open, /* xOpen */
1189  b2xy_close, /* xClose */
1190  b2xy_filter, /* xFilter */
1191  b2xy_next, /* xNext */
1192  b2xy_eof, /* xEof */
1193  b2xy_column, /* xColumn */
1194  b2xy_rowid, /* xRowid */
1195  0, /* xUpdate */
1196  0, /* xBegin */
1197  0, /* xSync */
1198  0, /* xCommit */
1199  0, /* xRollback */
1200  0, /* xFindFunction */
1201 #if (SQLITE_VERSION_NUMBER > 3004000)
1202  b2xy_rename, /* xRename */
1203 #endif
1204 };
1205 
1212 typedef struct {
1213  int max;
1214  int idx;
1215  char *str;
1216 } strbuf;
1217 
1224 static int
1226 {
1227  int n = 1024;
1228 
1229  if ((sb->max <= 0) || !sb->str) {
1230  sb->str = sqlite3_malloc(n);
1231  if (!sb->str) {
1232  return SQLITE_NOMEM;
1233  }
1234  sb->max = n;
1235  }
1236  sb->idx = 0;
1237  return SQLITE_OK;
1238 }
1239 
1246 static int
1248 {
1249  int n;
1250  char *str;
1251 
1252  if ((sb->max <= 0) || !sb->str) {
1253  return init_strbuf(sb);
1254  }
1255  n = sb->max * 2;
1256  str = sqlite3_realloc(sb->str, n);
1257  if (!str) {
1258  return SQLITE_NOMEM;
1259  }
1260  sb->max = n;
1261  sb->str = str;
1262  return SQLITE_OK;
1263 }
1264 
1270 static void
1272 {
1273  if (sb->str) {
1274  sqlite3_free(sb->str);
1275  sb->str = 0;
1276  }
1277  sb->max = 0;
1278 }
1279 
1287 static int
1288 print_strbuf(strbuf *sb, const char *fmt, ...)
1289 {
1290  int i, n, rc;
1291  va_list ap;
1292 
1293  va_start(ap, fmt);
1294  for (i = 0; i < 2; i++) {
1295  if (sb->max - (sb->idx + 1) < 256) {
1296  rc = expand_strbuf(sb);
1297  if (rc != SQLITE_OK) {
1298  goto done;
1299  }
1300  }
1301  rc = SQLITE_NOMEM;
1302  n = vsnprintf(sb->str + sb->idx, sb->max - sb->idx, fmt, ap);
1303  if ((n >= 0) && ((sb->idx + n) < (sb->max - 1))) {
1304  sb->idx += n;
1305  rc = SQLITE_OK;
1306  break;
1307  }
1308  }
1309 done:
1310  va_end(ap);
1311  return rc;
1312 }
1313 
1314 #define PATH_MODE_TK ((void *) 0)
1315 #define PATH_MODE_SVG ((void *) 1)
1316 #define PATH_MODE_BLT_X ((void *) 2)
1317 #define PATH_MODE_BLT_Y ((void *) 3)
1318 #define PATH_MODE_BLT ((void *) 4)
1319 #define PATH_MODE_TK3D ((void *) 5)
1320 
1340 static void
1341 common_path_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
1342 {
1343  void *mode = sqlite3_user_data(ctx);
1344  char *data;
1345  int i, linebreak, size, type = TYPE_CHAR;
1346  int do_x_scale = 0, do_y_scale = 0, do_z_scale = 0;
1347  double x_scale, x_offset, y_scale, y_offset, z0, z_scale, z_offset;
1348  strbuf sb;
1349 
1350  if (nargs < 1) {
1351  sqlite3_result_error(ctx, "need at least 1 argument", -1);
1352  return;
1353  }
1354  if (nargs > 1) {
1355  type = string_to_type((const char *) sqlite3_value_text(args[1]));
1356  if (!type) {
1357  sqlite3_result_error(ctx, "bad type name", -1);
1358  return;
1359  }
1360  }
1361  data = (char *) sqlite3_value_blob(args[0]);
1362  size = sqlite3_value_bytes(args[0]) / TYPE_SIZE(type);
1363  if (!data ||
1364  ((mode != PATH_MODE_BLT_X) && (mode != PATH_MODE_BLT_Y) &&
1365  (size < 2)) || (size < 1)) {
1366  goto nullorempty;
1367  }
1368  x_scale = 1;
1369  x_offset = 0;
1370  if (nargs > 2) {
1371  x_scale = sqlite3_value_double(args[2]);
1372  do_x_scale++;
1373  }
1374  if (nargs > 3) {
1375  x_offset = sqlite3_value_double(args[3]);
1376  do_x_scale++;
1377  }
1378  y_scale = 1;
1379  y_offset = 0;
1380  if (nargs > 4) {
1381  y_scale = sqlite3_value_double(args[4]);
1382  do_y_scale++;
1383  }
1384  if (nargs > 5) {
1385  y_offset = sqlite3_value_double(args[5]);
1386  do_y_scale++;
1387  }
1388  z0 = 0;
1389  z_scale = 1;
1390  z_offset = 0;
1391  if ((mode == PATH_MODE_TK3D) && (nargs > 6)) {
1392  z0 = sqlite3_value_double(args[6]);
1393  }
1394  if ((mode == PATH_MODE_TK3D) && (nargs > 7)) {
1395  z_scale = sqlite3_value_double(args[7]);
1396  do_z_scale++;
1397  }
1398  if ((mode == PATH_MODE_TK3D) && (nargs > 8)) {
1399  z_offset = sqlite3_value_double(args[8]);
1400  do_z_scale++;
1401  }
1402  memset(&sb, 0, sizeof (sb));
1403  if (init_strbuf(&sb) != SQLITE_OK) {
1404  goto nullorempty;
1405  }
1406  linebreak = 100;
1407  for (i = 0; i < size; i++, data += TYPE_SIZE(type)) {
1408  double x, y = 0, z = z0;
1409  char *fmt;
1410 
1411  if (do_z_scale) {
1412  z = z0 * z_scale + z_offset;
1413  }
1414  if (do_x_scale) {
1415  x = i * x_scale + x_offset;
1416  } else {
1417  x = i;
1418  }
1419  switch (type) {
1420  case TYPE_CHAR:
1421  y = data[0];
1422  break;
1423  case TYPE_UCHAR:
1424  y = data[0] & 0xFF;
1425  break;
1426  case TYPE_SHORT_LE:
1427  y = (data[0] & 0xFF) | (data[1] << 8);
1428  break;
1429  case TYPE_USHORT_LE:
1430  y = (data[0] & 0xFF) | ((data[1] & 0xFF) << 8);
1431  break;
1432  case TYPE_SHORT_BE:
1433  y = (data[1] & 0xFF) | (data[0] << 8);
1434  break;
1435  case TYPE_USHORT_BE:
1436  y = (data[1] & 0xFF) | ((data[0] & 0xFF) << 8);
1437  break;
1438  case TYPE_INT_LE:
1439  y = (data[0] & 0xFF) | ((data[1] & 0xFF) << 8) |
1440  ((data[2] & 0xFF) << 16) | (data[3] << 24);
1441  break;
1442  case TYPE_UINT_LE:
1443  y = (data[0] & 0xFF) | ((data[1] & 0xFF) << 8) |
1444  ((data[2] & 0xFF) << 16) | ((data[3] & 0xFF) << 24);
1445  break;
1446  case TYPE_INT_BE:
1447  y = (data[3] & 0xFF) | ((data[2] & 0xFF) << 8) |
1448  ((data[1] & 0xFF) << 16) | (data[0] << 24);
1449  break;
1450  case TYPE_UINT_BE:
1451  y = (data[3] & 0xFF) | ((data[2] & 0xFF) << 8) |
1452  ((data[1] & 0xFF) << 16) | ((data[0] & 0xFF) << 24);
1453  break;
1454  case TYPE_FLOAT:
1455  y = ((float *) data)[0];
1456  break;
1457  case TYPE_DOUBLE:
1458  y = ((double *) data)[0];
1459  break;
1460  }
1461  if (do_y_scale) {
1462  y = y * y_scale + y_offset;
1463  }
1464  if ((mode == PATH_MODE_BLT_X) || (mode == PATH_MODE_BLT_Y)) {
1465  double v = (mode == PATH_MODE_BLT_X) ? x : y;
1466 
1467  if (print_strbuf(&sb, (i == 0) ? "%g" : " %g", v) != SQLITE_OK) {
1468  drop_strbuf(&sb);
1469  break;
1470  }
1471  continue;
1472  }
1473  if ((mode == PATH_MODE_SVG) && (i == 0)) {
1474  fmt = "M %g %g";
1475  } else if ((mode == PATH_MODE_SVG) && (i == 1)) {
1476  fmt = " L %g %g";
1477  } else if ((mode == PATH_MODE_SVG) && (sb.idx >= linebreak)) {
1478  fmt = "\nL %g %g";
1479  linebreak = sb.idx + 100;
1480  } else if (i == 0) {
1481  fmt = (mode == PATH_MODE_TK3D) ? "%g %g %g" : "%g %g";
1482  } else {
1483  fmt = (mode == PATH_MODE_TK3D) ? " %g %g %g" : " %g %g";
1484  }
1485  if (print_strbuf(&sb, fmt, x, y, z) != SQLITE_OK) {
1486  drop_strbuf(&sb);
1487  break;
1488  }
1489  }
1490  if (sb.str) {
1491  sqlite3_result_text(ctx, sb.str, sb.idx, sqlite3_free);
1492  sb.str = 0;
1493  return;
1494  }
1495 nullorempty:
1496  if ((mode == PATH_MODE_BLT_X) || (mode == PATH_MODE_BLT_Y)) {
1497  sqlite3_result_text(ctx, "", 0, SQLITE_STATIC);
1498  } else {
1499  sqlite3_result_null(ctx);
1500  }
1501 }
1502 
1509 typedef struct {
1510  int init;
1511  int count;
1513  void *mode;
1515 } path_aggctx;
1516 
1537 static void
1538 common_path_step(sqlite3_context *ctx, int nargs, sqlite3_value **args)
1539 {
1540  path_aggctx *pag;
1541  int type;
1542  char *fmt;
1543  double x, y, z = 0;
1544  double x_scale, y_scale, x_offset, y_offset, z_scale, z_offset;
1545 
1546  if (nargs < 2) {
1547  return;
1548  }
1549  pag = sqlite3_aggregate_context(ctx, sizeof (*pag));
1550  if (!pag->init) {
1551  if (init_strbuf(&pag->sb) != SQLITE_OK) {
1552  return;
1553  }
1554  pag->linebreak = 100;
1555  pag->count = 0;
1556  pag->mode = sqlite3_user_data(ctx);
1557  pag->init = 1;
1558  }
1559  type = sqlite3_value_type(args[0]);
1560  if ((type != SQLITE_INTEGER) && (type != SQLITE_FLOAT)) {
1561  return;
1562  }
1563  type = sqlite3_value_type(args[1]);
1564  if ((type != SQLITE_INTEGER) && (type != SQLITE_FLOAT)) {
1565  return;
1566  }
1567  x = sqlite3_value_double(args[0]);
1568  y = sqlite3_value_double(args[1]);
1569  x_scale = 1;
1570  x_offset = 0;
1571  if (nargs > 2) {
1572  type = sqlite3_value_type(args[2]);
1573  if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1574  x_scale = sqlite3_value_double(args[2]);
1575  }
1576  }
1577  if (nargs > 3) {
1578  type = sqlite3_value_type(args[3]);
1579  if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1580  x_offset = sqlite3_value_double(args[3]);
1581  }
1582  }
1583  y_scale = 1;
1584  y_offset = 0;
1585  if (nargs > 4) {
1586  type = sqlite3_value_type(args[4]);
1587  if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1588  y_scale = sqlite3_value_double(args[4]);
1589  }
1590  }
1591  if (nargs > 5) {
1592  type = sqlite3_value_type(args[5]);
1593  if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1594  y_offset = sqlite3_value_double(args[5]);
1595  }
1596  }
1597  z_scale = 1;
1598  z_offset = 0;
1599  if ((pag->mode == PATH_MODE_TK3D) && (nargs > 6)) {
1600  z = sqlite3_value_double(args[6]);
1601  if (nargs > 7) {
1602  type = sqlite3_value_type(args[7]);
1603  if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1604  z_scale = sqlite3_value_double(args[7]);
1605  }
1606  }
1607  if (nargs > 8) {
1608  type = sqlite3_value_type(args[8]);
1609  if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1610  z_offset = sqlite3_value_double(args[8]);
1611  }
1612  }
1613  z = z * z_scale + z_offset;
1614  }
1615  x = x * x_scale + x_offset;
1616  y = y * y_scale + y_offset;
1617  if ((pag->mode == PATH_MODE_SVG) && (pag->count == 0)) {
1618  fmt = "M %g %g";
1619  } else if ((pag->mode == PATH_MODE_SVG) && (pag->count == 1)) {
1620  fmt = " L %g %g";
1621  } else if ((pag->mode == PATH_MODE_SVG) &&
1622  (pag->sb.idx >= pag->linebreak)) {
1623  fmt = "\nL %g %g";
1624  pag->linebreak = pag->sb.idx + 100;
1625  } else if (pag->count == 0) {
1626  fmt = (pag->mode == PATH_MODE_TK3D) ? "%g %g %g" : "%g %g";
1627  } else {
1628  fmt = (pag->mode == PATH_MODE_TK3D) ? " %g %g %g" : " %g %g";
1629  }
1630  if (print_strbuf(&pag->sb, fmt, x, y, z) != SQLITE_OK) {
1631  drop_strbuf(&pag->sb);
1632  pag->init = 0;
1633  } else {
1634  pag->count++;
1635  }
1636 }
1637 
1643 static void
1644 common_path_finalize(sqlite3_context *ctx)
1645 {
1646  path_aggctx *pag = sqlite3_aggregate_context(ctx, sizeof (*pag));
1647 
1648  if (pag->init) {
1649  if ((pag->count > 1) || (pag->mode == PATH_MODE_BLT)) {
1650  sqlite3_result_text(ctx, pag->sb.str, pag->sb.idx, sqlite3_free);
1651  pag->sb.str = 0;
1652  pag->init = 0;
1653  return;
1654  }
1655  drop_strbuf(&pag->sb);
1656  }
1657  if (pag->mode == PATH_MODE_BLT) {
1658  sqlite3_result_text(ctx, "", 0, SQLITE_STATIC);
1659  } else {
1660  sqlite3_result_null(ctx);
1661  }
1662 }
1663 
1677 static void
1678 blt_vec_step(sqlite3_context *ctx, int nargs, sqlite3_value **args)
1679 {
1680  path_aggctx *pag;
1681  int type;
1682  double v, scale, offset;
1683 
1684  if (nargs < 1) {
1685  return;
1686  }
1687  pag = sqlite3_aggregate_context(ctx, sizeof (*pag));
1688  if (!pag->init) {
1689  if (init_strbuf(&pag->sb) != SQLITE_OK) {
1690  return;
1691  }
1692  pag->count = 0;
1693  pag->mode = PATH_MODE_BLT;
1694  pag->init = 1;
1695  }
1696  type = sqlite3_value_type(args[0]);
1697  if ((type != SQLITE_INTEGER) && (type != SQLITE_FLOAT)) {
1698  return;
1699  }
1700  v = sqlite3_value_double(args[0]);
1701  scale = 1;
1702  offset = 0;
1703  if (nargs > 1) {
1704  type = sqlite3_value_type(args[1]);
1705  if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1706  scale = sqlite3_value_double(args[2]);
1707  }
1708  }
1709  if (nargs > 2) {
1710  type = sqlite3_value_type(args[2]);
1711  if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1712  offset = sqlite3_value_double(args[3]);
1713  }
1714  }
1715  v = v * scale + offset;
1716  if (print_strbuf(&pag->sb, (pag->count == 0) ? "%g" : " %g", v)
1717  != SQLITE_OK) {
1718  drop_strbuf(&pag->sb);
1719  pag->init = 0;
1720  } else {
1721  pag->count++;
1722  }
1723 }
1724 
1732 static void
1733 subblob_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
1734 {
1735  int insize, outsize, start, itemsize = 1, itemskip = 0;
1736  int i, k, n;
1737  char *indata, *outdata;
1738 
1739  if (nargs < 3) {
1740  sqlite3_result_error(ctx, "need at least 1 argument", -1);
1741  return;
1742  }
1743  indata = (char *) sqlite3_value_blob(args[0]);
1744  insize = sqlite3_value_bytes(args[0]);
1745  if (!indata || (insize <= 0)) {
1746 isnull:
1747  sqlite3_result_null(ctx);
1748  return;
1749  }
1750  start = sqlite3_value_int(args[1]);
1751  if (start < 0) {
1752  start = insize - start;
1753  if (start < 0) {
1754  start = 0;
1755  }
1756  } else if (start > 0) {
1757  start--;
1758  }
1759  if (start >= insize) {
1760  goto isnull;
1761  }
1762  outsize = sqlite3_value_int(args[2]);
1763  if (outsize > insize - start) {
1764  outsize = insize - start;
1765  }
1766  if (outsize <= 0) {
1767  goto isnull;
1768  }
1769  if (nargs > 3) {
1770  itemsize = sqlite3_value_int(args[3]);
1771  if ((itemsize <= 0) || (itemsize > outsize)) {
1772  goto isnull;
1773  }
1774  }
1775  if (nargs > 4) {
1776  itemskip = sqlite3_value_int(args[4]);
1777  if (itemskip < 0) {
1778  goto isnull;
1779  }
1780  }
1781  outdata = sqlite3_malloc(outsize);
1782  if (!outdata) {
1783  sqlite3_result_error(ctx, "out of memory", -1);
1784  return;
1785  }
1786  for (i = n = 0; i < outsize; i++) {
1787  for (k = 0; k < itemsize; k++) {
1788  outdata[i + k] = indata[start];
1789  n++;
1790  start++;
1791  if (start >= insize) {
1792  break;
1793  }
1794  }
1795  start += itemskip;
1796  if (start >= insize) {
1797  break;
1798  }
1799  }
1800  if (n > 0) {
1801  sqlite3_result_blob(ctx, outdata, n, sqlite3_free);
1802  return;
1803  }
1804  sqlite3_result_null(ctx);
1805  sqlite3_free(outdata);
1806 }
1807 
1814 typedef struct {
1815  sqlite3_context *ctx;
1816  sqlite3_value *value;
1817  sqlite_int64 count;
1818 } rownumber_ctx;
1819 
1827 static void
1828 rownumber_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
1829 {
1830  rownumber_ctx *rn = sqlite3_get_auxdata(ctx, 0);
1831 
1832  if (!rn || (rn->ctx != ctx) || (rn->value != args[0])) {
1833  rn = sqlite3_malloc(sizeof (*rn));
1834  if (rn) {
1835  rn->ctx = ctx;
1836  rn->value = args[0];
1837  rn->count = 0;
1838  }
1839  sqlite3_set_auxdata(ctx, 0, rn, sqlite3_free);
1840  } else {
1841  rn->count++;
1842  }
1843  sqlite3_result_int64(ctx, rn ? rn->count : 0);
1844 }
1845 
1853 #ifndef STANDALONE
1854 static
1855 #endif
1856 int
1857 b2xy_init(sqlite3 *db)
1858 {
1859  sqlite3_create_function(db, "subblob", -1, SQLITE_ANY, (void *) 0,
1860  subblob_func, 0, 0);
1861  sqlite3_create_function(db, "tk_path_from_blob", -1, SQLITE_UTF8,
1863  sqlite3_create_function(db, "svg_path_from_blob", -1, SQLITE_UTF8,
1865  sqlite3_create_function(db, "blt_vec_x", -1, SQLITE_UTF8,
1867  sqlite3_create_function(db, "blt_vec_y", -1, SQLITE_UTF8,
1869  sqlite3_create_function(db, "tk3d_path_from_blob", -1, SQLITE_UTF8,
1871  sqlite3_create_function(db, "tk_path", -1, SQLITE_ANY, PATH_MODE_TK,
1873  sqlite3_create_function(db, "svg_path", -1, SQLITE_ANY, PATH_MODE_SVG,
1875  sqlite3_create_function(db, "blt_vec", -1, SQLITE_ANY, PATH_MODE_BLT,
1877  sqlite3_create_function(db, "tk3d_path", -1, SQLITE_ANY, PATH_MODE_TK3D,
1879  sqlite3_create_function(db, "rownumber", 1, SQLITE_ANY, 0,
1880  rownumber_func, 0, 0);
1881  return sqlite3_create_module(db, "blobtoxy", &b2xy_module, 0);
1882 }
1883 
1884 #ifndef STANDALONE
1885 
1894 int
1895 sqlite3_extension_init(sqlite3 *db, char **errmsg,
1896  const sqlite3_api_routines *api)
1897 {
1898  SQLITE_EXTENSION_INIT2(api);
1899  return b2xy_init(db);
1900 }
1901 
1902 #endif
1903 
1904 /*
1905  * Local Variables:
1906  * mode: c
1907  * c-basic-offset: 4
1908  * fill-column: 78
1909  * tab-width: 8
1910  * End:
1911  */
sqlite3_context * ctx
SQLite context.
Definition: blobtoxy.c:1815
Internal dynamic string buffer.
Definition: blobtoxy.c:1212
b2xy_table * table
Link to table struct.
Definition: blobtoxy.c:255
static int b2xy_open(sqlite3_vtab *vtab, sqlite3_vtab_cursor **curret)
Open virtual table and return cursor.
Definition: blobtoxy.c:614
static int init_strbuf(strbuf *sb)
Initialize dynamic string buffer with capacity 1024.
Definition: blobtoxy.c:1225
char ** argv
Argument vector from b2xy_create() call.
Definition: blobtoxy.c:244
static int b2xy_next(sqlite3_vtab_cursor *cur)
Retrieve next row from virtual table cursor.
Definition: blobtoxy.c:870
int type
Data type of BLOB.
Definition: blobtoxy.c:272
int val_len
Length of current BLOB.
Definition: blobtoxy.c:261
Structure to describe a virtual table.
Definition: blobtoxy.c:228
#define TYPE_INT_LE
Definition: blobtoxy.c:213
int do_x_scale
If true, use X scale and offset.
Definition: blobtoxy.c:268
double y_offset
Current X scale and offset.
Definition: blobtoxy.c:267
#define PATH_MODE_BLT_Y
Definition: blobtoxy.c:1317
#define TYPE_USHORT_BE
Definition: blobtoxy.c:212
static void drop_strbuf(strbuf *sb)
Free resources of dynamic string buffer.
Definition: blobtoxy.c:1271
sqlite_int64 rowid
Current ROWID.
Definition: blobtoxy.c:275
#define TYPE_CHAR
Definition: blobtoxy.c:207
double y_scale
Definition: blobtoxy.c:267
static int print_strbuf(strbuf *sb, const char *fmt,...)
Format printf-like into dynamic string buffer.
Definition: blobtoxy.c:1288
int x_length
X start/length.
Definition: blobtoxy.c:271
static void common_path_step(sqlite3_context *ctx, int nargs, sqlite3_value **args)
Path/polyline step callback for "tk_path", "svg_path", and "tk3d_path" aggregate functions.
Definition: blobtoxy.c:1538
sqlite3_value * value
SQLite value for this context.
Definition: blobtoxy.c:1816
static void blt_vec_step(sqlite3_context *ctx, int nargs, sqlite3_value **args)
Path/polyline step callback for "blt_vec" aggregate functions.
Definition: blobtoxy.c:1678
#define PATH_MODE_BLT_X
Definition: blobtoxy.c:1316
Driver internal structure representing SQL statement (HSTMT).
Definition: sqlite3odbc.h:230
int type
Data type of BLOB.
Definition: blobtoxy.c:240
static void common_path_finalize(sqlite3_context *ctx)
Path/polyline finalizer.
Definition: blobtoxy.c:1644
char * master_table
Table where to fetch BLOB from.
Definition: blobtoxy.c:231
static int expand_strbuf(strbuf *sb)
Expand or initialize dynamic string buffer.
Definition: blobtoxy.c:1247
#define PATH_MODE_TK
Definition: blobtoxy.c:1314
int do_y_scale
If true, use Y scale and offset.
Definition: blobtoxy.c:269
sqlite3_vtab base
SQLite&#39;s base virtual table struct.
Definition: blobtoxy.c:229
int sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api)
Initializer for SQLite extension load mechanism.
Definition: blobtoxy.c:1895
double x_offset
Current X scale and offset.
Definition: blobtoxy.c:264
#define TYPE_USHORT_LE
Definition: blobtoxy.c:210
int x_length
X start/length.
Definition: blobtoxy.c:242
struct b2xy_table b2xy_table
int num_cols
Total number of columns of result set.
Definition: blobtoxy.c:259
int y_offset_col
Column number of Y offset or 0.
Definition: blobtoxy.c:266
#define PATH_MODE_TK3D
Definition: blobtoxy.c:1319
Internal aggregate context for path/polyline function.
Definition: blobtoxy.c:1509
int rowid_from_key
When true, ROWID used from key column.
Definition: blobtoxy.c:274
#define TYPE_INT_BE
Definition: blobtoxy.c:215
static void common_path_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
Make path/polyline from blob.
Definition: blobtoxy.c:1341
#define TYPE_UINT_BE
Definition: blobtoxy.c:216
sqlite_int64 count
Counter giving row number.
Definition: blobtoxy.c:1817
char * val
Value of current BLOB.
Definition: blobtoxy.c:260
void * mode
mode, see PATH_* defines
Definition: blobtoxy.c:1513
struct b2xy_cursor b2xy_cursor
#define TYPE_UINT_LE
Definition: blobtoxy.c:214
int argc
Number args from b2xy_create() call.
Definition: blobtoxy.c:243
#define TYPE_BIGINT_LE
Definition: blobtoxy.c:217
#define TYPE_SHORT_BE
Definition: blobtoxy.c:211
char * str
string buffer
Definition: blobtoxy.c:1215
SQLite context structure for "rownumber" function.
Definition: blobtoxy.c:1814
static const sqlite3_module b2xy_module
Definition: blobtoxy.c:1181
int index
Current index in BLOB.
Definition: blobtoxy.c:273
static int b2xy_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i)
Return column data of virtual table.
Definition: blobtoxy.c:659
#define PATH_MODE_SVG
Definition: blobtoxy.c:1315
sqlite3_vtab_cursor base
SQLite&#39;s base cursor struct.
Definition: blobtoxy.c:254
static void rownumber_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
"rownumber" function.
Definition: blobtoxy.c:1828
char * other_columns
Other columns or empty string.
Definition: blobtoxy.c:239
#define TYPE_SHORT_LE
Definition: blobtoxy.c:209
static int b2xy_filter(sqlite3_vtab_cursor *cur, int idxNum, const char *idxStr, int argc, sqlite3_value **argv)
Filter function for virtual table.
Definition: blobtoxy.c:966
static int string_to_type(const char *str)
Map type string to type code.
Definition: blobtoxy.c:285
int x_start
Definition: blobtoxy.c:271
sqlite3_stmt * select
Prepared SELECT statement or NULL.
Definition: blobtoxy.c:256
int count
counts formatted elements
Definition: blobtoxy.c:1511
int max
maximum capacity
Definition: blobtoxy.c:1213
char * x_offset_column
Name of column giving X offset or NULL.
Definition: blobtoxy.c:236
static int b2xy_destroy(sqlite3_vtab *vtab)
Destroy virtual table.
Definition: blobtoxy.c:339
char * y_offset_column
Name of column giving Y offset or NULL.
Definition: blobtoxy.c:238
#define TYPE_SIZE(code)
Definition: blobtoxy.c:205
static int b2xy_rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *rowidp)
Return current rowid of virtual table cursor.
Definition: blobtoxy.c:841
int do_x_sl
If true, apply X start/length.
Definition: blobtoxy.c:241
int x_start
Definition: blobtoxy.c:242
int x_scale_col
Column number of X scale or 0.
Definition: blobtoxy.c:262
char * x_scale_column
Name of column giving X scale or NULL.
Definition: blobtoxy.c:235
int idx
current index
Definition: blobtoxy.c:1214
char * blob_column
Name of BLOB column.
Definition: blobtoxy.c:234
#define TYPE_FLOAT
Definition: blobtoxy.c:219
static int b2xy_init(sqlite3 *db)
Module initializer creating SQLite functions and modules.
Definition: blobtoxy.c:1857
Structure to describe a cursor in the virtual table.
Definition: blobtoxy.c:253
char * fq_master_table
Fully qualified master_table.
Definition: blobtoxy.c:232
static int b2xy_eof(sqlite3_vtab_cursor *cur)
Return end of table state of virtual table cursor.
Definition: blobtoxy.c:856
#define TYPE_UCHAR
Definition: blobtoxy.c:208
int linebreak
when to add newline to output
Definition: blobtoxy.c:1512
int fix_cols
Fixed number of columns of result set.
Definition: blobtoxy.c:258
static int b2xy_close(sqlite3_vtab_cursor *cur)
Close virtual table cursor.
Definition: blobtoxy.c:641
int init
init flag, true when initialized
Definition: blobtoxy.c:1510
static void subblob_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
"subblob" function similar to "substr".
Definition: blobtoxy.c:1733
double x_scale
Definition: blobtoxy.c:264
char * key_column
Name of key column.
Definition: blobtoxy.c:233
strbuf sb
string buffer for result
Definition: blobtoxy.c:1514
static int b2xy_bestindex(sqlite3_vtab *tab, sqlite3_index_info *info)
Determines information for filter function according to constraints.
Definition: blobtoxy.c:1100
#define TYPE_DOUBLE
Definition: blobtoxy.c:220
int x_offset_col
Column number of X offset or 0.
Definition: blobtoxy.c:263
char * y_scale_column
Name of column giving Y scale or NULL.
Definition: blobtoxy.c:237
sqlite3_value * key
Value of current key.
Definition: blobtoxy.c:257
#define TYPE_BIGINT_BE
Definition: blobtoxy.c:218
#define PATH_MODE_BLT
Definition: blobtoxy.c:1318
int do_x_sl
If true, apply X start/length.
Definition: blobtoxy.c:270
sqlite3 * db
Open database.
Definition: blobtoxy.c:230
int y_scale_col
Column number of Y scale or 0.
Definition: blobtoxy.c:265
static int b2xy_create(sqlite3 *db, void *userdata, int argc, const char *const *argv, sqlite3_vtab **vtabret, char **errp)
Create virtual table.
Definition: blobtoxy.c:376

Generated on Mon Aug 22 2016 by doxygen.
Contact: chw@ch-werner.de