blobtoxy.c
Go to the documentation of this file.
1
186#ifdef STANDALONE
187#include <sqlite3.h>
188#else
189#include <sqlite3ext.h>
190static 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
246
277
284static int
285string_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
338static int
339b2xy_destroy(sqlite3_vtab *vtab)
340{
341 b2xy_table *bt = (b2xy_table *) vtab;
342
343 sqlite3_free(bt);
344 return SQLITE_OK;
345}
346
375static int
376b2xy_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
613static int
614b2xy_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
640static int
641b2xy_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
658static int
659b2xy_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
840static int
841b2xy_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
855static int
856b2xy_eof(sqlite3_vtab_cursor *cur)
857{
858 b2xy_cursor *bc = (b2xy_cursor *) cur;
859
860 return bc->select ? 0 : 1;
861}
862
869static int
870b2xy_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) {
892refetch:
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
965static int
966b2xy_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
1099static int
1100b2xy_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
1173static int
1174b2xy_rename(sqlite3_vtab *tab, const char *newname)
1175{
1176 return SQLITE_OK;
1177}
1178
1179#endif
1180
1181static 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
1212typedef struct {
1213 int max;
1214 int idx;
1215 char *str;
1216} strbuf;
1217
1224static 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
1246static 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
1270static void
1272{
1273 if (sb->str) {
1274 sqlite3_free(sb->str);
1275 sb->str = 0;
1276 }
1277 sb->max = 0;
1278}
1279
1287static int
1288print_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 }
1309done:
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
1340static void
1341common_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 }
1495nullorempty:
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
1509typedef struct {
1510 int init;
1511 int count;
1513 void *mode;
1515} path_aggctx;
1516
1537static void
1538common_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
1643static void
1644common_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
1677static void
1678blt_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
1732static void
1733subblob_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)) {
1746isnull:
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
1814typedef struct {
1815 sqlite3_context *ctx;
1816 sqlite3_value *value;
1817 sqlite_int64 count;
1819
1827static void
1828rownumber_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
1854static
1855#endif
1856int
1857b2xy_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
1894int
1895sqlite3_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 */
static int print_strbuf(strbuf *sb, const char *fmt,...)
Format printf-like into dynamic string buffer.
Definition blobtoxy.c:1288
#define TYPE_UCHAR
Definition blobtoxy.c:208
static int b2xy_close(sqlite3_vtab_cursor *cur)
Close virtual table cursor.
Definition blobtoxy.c:641
#define TYPE_FLOAT
Definition blobtoxy.c:219
#define TYPE_BIGINT_BE
Definition blobtoxy.c:218
static int b2xy_bestindex(sqlite3_vtab *tab, sqlite3_index_info *info)
Determines information for filter function according to constraints.
Definition blobtoxy.c:1100
static int b2xy_next(sqlite3_vtab_cursor *cur)
Retrieve next row from virtual table cursor.
Definition blobtoxy.c:870
static const sqlite3_module b2xy_module
Definition blobtoxy.c:1181
#define TYPE_CHAR
Definition blobtoxy.c:207
#define TYPE_UINT_BE
Definition blobtoxy.c:216
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
struct b2xy_table b2xy_table
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
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
static void subblob_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
"subblob" function similar to "substr".
Definition blobtoxy.c:1733
static int string_to_type(const char *str)
Map type string to type code.
Definition blobtoxy.c:285
#define TYPE_BIGINT_LE
Definition blobtoxy.c:217
#define PATH_MODE_TK3D
Definition blobtoxy.c:1319
static int init_strbuf(strbuf *sb)
Initialize dynamic string buffer with capacity 1024.
Definition blobtoxy.c:1225
static void common_path_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
Make path/polyline from blob.
Definition blobtoxy.c:1341
static int expand_strbuf(strbuf *sb)
Expand or initialize dynamic string buffer.
Definition blobtoxy.c:1247
static void rownumber_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
"rownumber" function.
Definition blobtoxy.c:1828
static void common_path_finalize(sqlite3_context *ctx)
Path/polyline finalizer.
Definition blobtoxy.c:1644
#define PATH_MODE_BLT_X
Definition blobtoxy.c:1316
static int b2xy_destroy(sqlite3_vtab *vtab)
Destroy virtual table.
Definition blobtoxy.c:339
#define TYPE_USHORT_BE
Definition blobtoxy.c:212
struct b2xy_cursor b2xy_cursor
int sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api)
Initializer for SQLite extension load mechanism.
Definition blobtoxy.c:1895
static int b2xy_rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *rowidp)
Return current rowid of virtual table cursor.
Definition blobtoxy.c:841
static int b2xy_init(sqlite3 *db)
Module initializer creating SQLite functions and modules.
Definition blobtoxy.c:1857
#define PATH_MODE_TK
Definition blobtoxy.c:1314
#define TYPE_SIZE(code)
Definition blobtoxy.c:205
#define TYPE_UINT_LE
Definition blobtoxy.c:214
#define TYPE_USHORT_LE
Definition blobtoxy.c:210
static int b2xy_open(sqlite3_vtab *vtab, sqlite3_vtab_cursor **curret)
Open virtual table and return cursor.
Definition blobtoxy.c:614
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
#define TYPE_SHORT_LE
Definition blobtoxy.c:209
static int b2xy_eof(sqlite3_vtab_cursor *cur)
Return end of table state of virtual table cursor.
Definition blobtoxy.c:856
#define PATH_MODE_BLT
Definition blobtoxy.c:1318
static void drop_strbuf(strbuf *sb)
Free resources of dynamic string buffer.
Definition blobtoxy.c:1271
#define TYPE_DOUBLE
Definition blobtoxy.c:220
#define TYPE_INT_BE
Definition blobtoxy.c:215
#define TYPE_INT_LE
Definition blobtoxy.c:213
#define PATH_MODE_BLT_Y
Definition blobtoxy.c:1317
#define TYPE_SHORT_BE
Definition blobtoxy.c:211
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
Structure to describe a cursor in the virtual table.
Definition blobtoxy.c:253
int x_length
X start/length.
Definition blobtoxy.c:271
int do_x_scale
If true, use X scale and offset.
Definition blobtoxy.c:268
int x_scale_col
Column number of X scale or 0.
Definition blobtoxy.c:262
int rowid_from_key
When true, ROWID used from key column.
Definition blobtoxy.c:274
int y_offset_col
Column number of Y offset or 0.
Definition blobtoxy.c:266
sqlite3_vtab_cursor base
SQLite's base cursor struct.
Definition blobtoxy.c:254
int x_offset_col
Column number of X offset or 0.
Definition blobtoxy.c:263
int fix_cols
Fixed number of columns of result set.
Definition blobtoxy.c:258
int val_len
Length of current BLOB.
Definition blobtoxy.c:261
double x_offset
Current X scale and offset.
Definition blobtoxy.c:264
int type
Data type of BLOB.
Definition blobtoxy.c:272
int y_scale_col
Column number of Y scale or 0.
Definition blobtoxy.c:265
int do_y_scale
If true, use Y scale and offset.
Definition blobtoxy.c:269
sqlite_int64 rowid
Current ROWID.
Definition blobtoxy.c:275
int index
Current index in BLOB.
Definition blobtoxy.c:273
sqlite3_value * key
Value of current key.
Definition blobtoxy.c:257
int do_x_sl
If true, apply X start/length.
Definition blobtoxy.c:270
sqlite3_stmt * select
Prepared SELECT statement or NULL.
Definition blobtoxy.c:256
char * val
Value of current BLOB.
Definition blobtoxy.c:260
double y_scale
Definition blobtoxy.c:267
double y_offset
Current X scale and offset.
Definition blobtoxy.c:267
int num_cols
Total number of columns of result set.
Definition blobtoxy.c:259
b2xy_table * table
Link to table struct.
Definition blobtoxy.c:255
double x_scale
Definition blobtoxy.c:264
Structure to describe a virtual table.
Definition blobtoxy.c:228
sqlite3_vtab base
SQLite's base virtual table struct.
Definition blobtoxy.c:229
char * y_offset_column
Name of column giving Y offset or NULL.
Definition blobtoxy.c:238
char * x_scale_column
Name of column giving X scale or NULL.
Definition blobtoxy.c:235
int x_length
X start/length.
Definition blobtoxy.c:242
int x_start
Definition blobtoxy.c:242
sqlite3 * db
Open database.
Definition blobtoxy.c:230
char * blob_column
Name of BLOB column.
Definition blobtoxy.c:234
char * y_scale_column
Name of column giving Y scale or NULL.
Definition blobtoxy.c:237
char * x_offset_column
Name of column giving X offset or NULL.
Definition blobtoxy.c:236
char * key_column
Name of key column.
Definition blobtoxy.c:233
int do_x_sl
If true, apply X start/length.
Definition blobtoxy.c:241
int type
Data type of BLOB.
Definition blobtoxy.c:240
char * fq_master_table
Fully qualified master_table.
Definition blobtoxy.c:232
char ** argv
Argument vector from b2xy_create() call.
Definition blobtoxy.c:244
int argc
Number args from b2xy_create() call.
Definition blobtoxy.c:243
char * other_columns
Other columns or empty string.
Definition blobtoxy.c:239
char * master_table
Table where to fetch BLOB from.
Definition blobtoxy.c:231
Internal aggregate context for path/polyline function.
Definition blobtoxy.c:1509
int init
init flag, true when initialized
Definition blobtoxy.c:1510
int count
counts formatted elements
Definition blobtoxy.c:1511
strbuf sb
string buffer for result
Definition blobtoxy.c:1514
void * mode
mode, see PATH_* defines
Definition blobtoxy.c:1513
int linebreak
when to add newline to output
Definition blobtoxy.c:1512
SQLite context structure for "rownumber" function.
Definition blobtoxy.c:1814
sqlite_int64 count
Counter giving row number.
Definition blobtoxy.c:1817
sqlite3_context * ctx
SQLite context.
Definition blobtoxy.c:1815
sqlite3_value * value
SQLite value for this context.
Definition blobtoxy.c:1816
Driver internal structure representing SQL statement (HSTMT).
Internal dynamic string buffer.
Definition blobtoxy.c:1212
int idx
current index
Definition blobtoxy.c:1214
int max
maximum capacity
Definition blobtoxy.c:1213
char * str
string buffer
Definition blobtoxy.c:1215

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