189#include <sqlite3ext.h>
190static SQLITE_EXTENSION_INIT1
199#define strcasecmp _stricmp
200#define strncasecmp _strnicmp
201#define vsnprintf _vsnprintf
204#define TYPE_CODE(num, type) (((num) << 8) | (sizeof (type)))
205#define TYPE_SIZE(code) ((code) & 0xFF)
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)
287 if (strcasecmp(str,
"char") == 0) {
290 if (strcasecmp(str,
"uchar") == 0) {
293 if (strcasecmp(str,
"short_le") == 0) {
296 if (strcasecmp(str,
"ushort_le") == 0) {
299 if (strcasecmp(str,
"short_be") == 0) {
302 if (strcasecmp(str,
"ushort_be") == 0) {
305 if (strcasecmp(str,
"int_le") == 0) {
308 if (strcasecmp(str,
"uint_le") == 0) {
311 if (strcasecmp(str,
"int_be") == 0) {
314 if (strcasecmp(str,
"uint_be") == 0) {
317 if (strcasecmp(str,
"bigint_le") == 0) {
320 if (strcasecmp(str,
"bigint_be") == 0) {
323 if (strcasecmp(str,
"float") == 0) {
326 if (strcasecmp(str,
"double") == 0) {
377 const char *
const *argv, sqlite3_vtab **vtabret,
char **errp)
379 int rc = SQLITE_NOMEM;
382 int x_start = -1, x_length = 0;
385 *errp = sqlite3_mprintf(
"need at least 3 arguments");
391 *errp = sqlite3_mprintf(
"unsupported type %Q", argv[6]);
396 if ((argv[11][0] !=
'"') && (argv[11][0] !=
'\'')) {
397 *errp = sqlite3_mprintf(
"other columns must be quoted");
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");
410 *errp = sqlite3_mprintf(
"X start index must be >= 0");
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");
423 *errp = sqlite3_mprintf(
"X length must be > 0");
427 size =
sizeof (
char *) * argc;
428 for (i = 0; i < argc; i++) {
429 size += argv[i] ? (strlen(argv[i]) + 1) : 0;
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);
436 char *p, *key_type = 0, *x_type, *y_type, *other_types = 0;
443 bt->
do_x_sl = (x_start >= 0) || (x_length > 0);
448 bt->
argv = (
char **) (bt + 1);
449 p = (
char *) (bt->
argv + argc);
450 for (i = 0; i < argc; i++) {
462 strcat(p, bt->
argv[1]);
467 strcat(p, bt->
argv[3]);
472 if ((bt->
argc > 7) && bt->
argv[7][0]) {
478 if ((bt->
argc > 8) && bt->
argv[8][0]) {
484 if ((bt->
argc > 9) && bt->
argv[9][0]) {
490 if ((bt->
argc > 10) && bt->
argv[10][0]) {
501 if ((*p ==
'"') || (*p ==
'\'')) {
520 p = sqlite3_mprintf(
"PRAGMA %Q.table_info(%Q)",
524 int nrows = 0, ncols = 0;
527 rc = sqlite3_get_table(db, p, &rows, &nrows, &ncols, 0);
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]);
539 sqlite3_free_table(rows);
545 p = sqlite3_mprintf(
"SELECT %s FROM %s WHERE 0",
549 sqlite3_stmt *
stmt = 0;
551#if defined(HAVE_SQLITE3PREPAREV2) && HAVE_SQLITE3PREPAREV2
552 rc = sqlite3_prepare_v2(db, p, -1, &
stmt, 0);
554 rc = sqlite3_prepare(db, p, -1, &
stmt, 0);
557 if ((rc == SQLITE_OK) &&
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);
573 sqlite3_finalize(
stmt);
575 p = sqlite3_mprintf(
",%s", other_types);
576 sqlite3_free(other_types);
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 :
"",
588 sqlite3_free(key_type);
591 sqlite3_free(other_types);
594 rc = sqlite3_declare_vtab(db, p);
597 if (rc != SQLITE_OK) {
602 *vtabret = (sqlite3_vtab *) bt;
614b2xy_open(sqlite3_vtab *vtab, sqlite3_vtab_cursor **curret)
616 int rc = SQLITE_NOMEM;
628 *curret = (sqlite3_vtab_cursor *) bc;
645 sqlite3_finalize(bc->
select);
667 sqlite3_result_value(ctx, bc->
key);
672 sqlite3_result_double(ctx, v);
674 sqlite3_result_int(ctx, bc->
index);
689 sqlite3_result_int(ctx, p[0]);
696 sqlite3_result_int(ctx, p[0] & 0xFF);
700 v = (p[0] & 0xFF) | (p[1] << 8);
703 sqlite3_result_int(ctx, (p[0] & 0xFF) | (p[1] << 8));
707 v = (p[0] & 0xFF) | ((p[1] & 0xFF) << 8);
710 sqlite3_result_int(ctx, (p[0] & 0xFF) | ((p[1] & 0xFF) << 8));
714 v = (p[1] & 0xFF) | (p[0] << 8);
717 sqlite3_result_int(ctx, (p[1] & 0xFF) | (p[0] << 8));
721 v = (p[1] & 0xFF) | ((p[0] & 0xFF) << 8);
724 sqlite3_result_int(ctx, (p[1] & 0xFF) | ((p[0] & 0xFF) << 8));
728 v = (p[0] & 0xFF) | ((p[1] & 0xFF) << 8) |
729 ((p[2] & 0xFF) << 16) | (p[3] << 24);
732 sqlite3_result_int64(ctx, (p[0] & 0xFF) |
733 ((p[1] & 0xFF) << 8) |
734 ((p[2] & 0xFF) << 16) |
739 v = (p[0] & 0xFF) | ((p[1] & 0xFF) << 8) |
740 ((p[2] & 0xFF) << 16) | ((p[3] & 0xFF) << 24);
743 sqlite3_result_int64(ctx, (p[0] & 0xFF) |
744 ((p[1] & 0xFF) << 8) |
745 ((p[2] & 0xFF) << 16) |
746 ((p[3] & 0xFF) << 24));
750 v = (p[3] & 0xFF) | ((p[2] & 0xFF) << 8) |
751 ((p[1] & 0xFF) << 16) | (p[0] << 24);
754 sqlite3_result_int64(ctx, (p[3] & 0xFF) |
755 ((p[2] & 0xFF) << 8) |
756 ((p[1] & 0xFF) << 16) |
761 v = (p[3] & 0xFF) | ((p[2] & 0xFF) << 8) |
762 ((p[1] & 0xFF) << 16) | ((p[0] & 0xFF) << 24);
765 sqlite3_result_int64(ctx, (p[3] & 0xFF) |
766 ((p[2] & 0xFF) << 8) |
767 ((p[1] & 0xFF) << 16) |
768 ((p[0] & 0xFF) << 24));
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);
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));
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);
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));
805 v = ((
float *) p)[0];
808 v = ((
double *) p)[0];
813 sqlite3_result_double(ctx, v);
817 sqlite3_result_null(ctx);
823 if ((i < 0) || (i >= bc->
num_cols)) {
824 sqlite3_result_null(ctx);
826 sqlite3_result_value(ctx, sqlite3_column_value(bc->
select, i));
860 return bc->
select ? 0 : 1;
893 rc = sqlite3_step(bc->
select);
895 if (rc == SQLITE_SCHEMA) {
896 rc = sqlite3_step(bc->
select);
898 if (rc != SQLITE_ROW) {
899 sqlite3_finalize(bc->
select);
905 bc->
val = (
char *) sqlite3_column_blob(bc->
select, 1);
909 bc->
val = (
char *) sqlite3_column_text(bc->
select, 1);
921 bc->
key = sqlite3_column_value(bc->
select, 0);
922 if (sqlite3_column_type(bc->
select, 0) == SQLITE_INTEGER) {
966b2xy_filter(sqlite3_vtab_cursor *cur,
int idxNum,
const char *idxStr,
967 int argc, sqlite3_value **argv)
971 char *query, *tmp, *op = 0;
977 sqlite3_finalize(bc->
select);
981 query = sqlite3_mprintf(
"select \"%s\",\"%s\"", bt->
key_column,
1000 return SQLITE_NOMEM;
1008 sqlite3_free(query);
1010 return SQLITE_NOMEM;
1018 sqlite3_free(query);
1020 return SQLITE_NOMEM;
1026 tmp = sqlite3_mprintf(
"%s%s from %s", query, bt->
other_columns,
1028 sqlite3_free(query);
1030 return SQLITE_NOMEM;
1033 if (idxNum && (argc > 0)) {
1035 case SQLITE_INDEX_CONSTRAINT_EQ:
1038 case SQLITE_INDEX_CONSTRAINT_GT:
1041 case SQLITE_INDEX_CONSTRAINT_LE:
1044 case SQLITE_INDEX_CONSTRAINT_LT:
1047 case SQLITE_INDEX_CONSTRAINT_GE:
1050 case SQLITE_INDEX_CONSTRAINT_MATCH:
1055 tmp = sqlite3_mprintf(
"%s where \"%s\" %s ?",
1057 sqlite3_free(query);
1059 return SQLITE_NOMEM;
1065 tmp = sqlite3_mprintf(
"%s %s", query, idxStr);
1066 sqlite3_free(query);
1068 return SQLITE_NOMEM;
1073#if defined(HAVE_SQLITE3PREPAREV2) && HAVE_SQLITE3PREPAREV2
1074 rc = sqlite3_prepare_v2(bt->
db, query, -1, &bc->
select, 0);
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);
1081 sqlite3_free(query);
1082 if (rc == SQLITE_OK) {
1085 sqlite3_bind_value(bc->
select, 1, argv[0]);
1088 return (rc == SQLITE_OK) ?
b2xy_next(cur) : rc;
1103 int i, key_order = 0, consumed = 0;
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;
1135 for (i = 0; i < info->nOrderBy; i++) {
1136 if (info->aOrderBy[i].iColumn == 0) {
1137 key_order = info->aOrderBy[i].desc ? -1 : 1;
1139 }
else if ((info->aOrderBy[i].iColumn == 1) &&
1140 !info->aOrderBy[i].desc) {
1146 for (i = 0; i < info->nOrderBy; i++) {
1147 if ((info->aOrderBy[i].iColumn == 1) &&
1148 info->aOrderBy[i].desc) {
1150 }
else if (info->aOrderBy[i].iColumn > 1) {
1155 if (consumed && key_order) {
1156 info->idxStr = sqlite3_mprintf(
"ORDER BY \"%s\" %s",
1158 (key_order < 0) ?
"DESC" :
"ASC");
1159 info->needToFreeIdxStr = 1;
1161 info->orderByConsumed = consumed;
1165#if (SQLITE_VERSION_NUMBER > 3004000)
1174b2xy_rename(sqlite3_vtab *tab,
const char *newname)
1201#if (SQLITE_VERSION_NUMBER > 3004000)
1229 if ((sb->
max <= 0) || !sb->
str) {
1230 sb->
str = sqlite3_malloc(n);
1232 return SQLITE_NOMEM;
1252 if ((sb->
max <= 0) || !sb->
str) {
1256 str = sqlite3_realloc(sb->
str, n);
1258 return SQLITE_NOMEM;
1274 sqlite3_free(sb->
str);
1294 for (i = 0; i < 2; i++) {
1295 if (sb->
max - (sb->
idx + 1) < 256) {
1297 if (rc != SQLITE_OK) {
1302 n = vsnprintf(sb->
str + sb->
idx, sb->
max - sb->
idx, fmt, ap);
1303 if ((n >= 0) && ((sb->
idx + n) < (sb->
max - 1))) {
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)
1343 void *mode = sqlite3_user_data(ctx);
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;
1351 sqlite3_result_error(ctx,
"need at least 1 argument", -1);
1355 type =
string_to_type((
const char *) sqlite3_value_text(args[1]));
1357 sqlite3_result_error(ctx,
"bad type name", -1);
1361 data = (
char *) sqlite3_value_blob(args[0]);
1362 size = sqlite3_value_bytes(args[0]) /
TYPE_SIZE(type);
1365 (size < 2)) || (size < 1)) {
1371 x_scale = sqlite3_value_double(args[2]);
1375 x_offset = sqlite3_value_double(args[3]);
1381 y_scale = sqlite3_value_double(args[4]);
1385 y_offset = sqlite3_value_double(args[5]);
1392 z0 = sqlite3_value_double(args[6]);
1395 z_scale = sqlite3_value_double(args[7]);
1399 z_offset = sqlite3_value_double(args[8]);
1402 memset(&sb, 0,
sizeof (sb));
1407 for (i = 0; i < size; i++, data +=
TYPE_SIZE(type)) {
1408 double x, y = 0, z = z0;
1412 z = z0 * z_scale + z_offset;
1415 x = i * x_scale + x_offset;
1427 y = (data[0] & 0xFF) | (data[1] << 8);
1430 y = (data[0] & 0xFF) | ((data[1] & 0xFF) << 8);
1433 y = (data[1] & 0xFF) | (data[0] << 8);
1436 y = (data[1] & 0xFF) | ((data[0] & 0xFF) << 8);
1439 y = (data[0] & 0xFF) | ((data[1] & 0xFF) << 8) |
1440 ((data[2] & 0xFF) << 16) | (data[3] << 24);
1443 y = (data[0] & 0xFF) | ((data[1] & 0xFF) << 8) |
1444 ((data[2] & 0xFF) << 16) | ((data[3] & 0xFF) << 24);
1447 y = (data[3] & 0xFF) | ((data[2] & 0xFF) << 8) |
1448 ((data[1] & 0xFF) << 16) | (data[0] << 24);
1451 y = (data[3] & 0xFF) | ((data[2] & 0xFF) << 8) |
1452 ((data[1] & 0xFF) << 16) | ((data[0] & 0xFF) << 24);
1455 y = ((
float *) data)[0];
1458 y = ((
double *) data)[0];
1462 y = y * y_scale + y_offset;
1467 if (
print_strbuf(&sb, (i == 0) ?
"%g" :
" %g", v) != SQLITE_OK) {
1479 linebreak = sb.
idx + 100;
1480 }
else if (i == 0) {
1491 sqlite3_result_text(ctx, sb.
str, sb.
idx, sqlite3_free);
1497 sqlite3_result_text(ctx,
"", 0, SQLITE_STATIC);
1499 sqlite3_result_null(ctx);
1544 double x_scale, y_scale, x_offset, y_offset, z_scale, z_offset;
1549 pag = sqlite3_aggregate_context(ctx,
sizeof (*pag));
1556 pag->
mode = sqlite3_user_data(ctx);
1559 type = sqlite3_value_type(args[0]);
1560 if ((type != SQLITE_INTEGER) && (type != SQLITE_FLOAT)) {
1563 type = sqlite3_value_type(args[1]);
1564 if ((type != SQLITE_INTEGER) && (type != SQLITE_FLOAT)) {
1567 x = sqlite3_value_double(args[0]);
1568 y = sqlite3_value_double(args[1]);
1572 type = sqlite3_value_type(args[2]);
1573 if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1574 x_scale = sqlite3_value_double(args[2]);
1578 type = sqlite3_value_type(args[3]);
1579 if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1580 x_offset = sqlite3_value_double(args[3]);
1586 type = sqlite3_value_type(args[4]);
1587 if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1588 y_scale = sqlite3_value_double(args[4]);
1592 type = sqlite3_value_type(args[5]);
1593 if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1594 y_offset = sqlite3_value_double(args[5]);
1600 z = sqlite3_value_double(args[6]);
1602 type = sqlite3_value_type(args[7]);
1603 if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1604 z_scale = sqlite3_value_double(args[7]);
1608 type = sqlite3_value_type(args[8]);
1609 if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1610 z_offset = sqlite3_value_double(args[8]);
1613 z = z * z_scale + z_offset;
1615 x = x * x_scale + x_offset;
1616 y = y * y_scale + y_offset;
1625 }
else if (pag->
count == 0) {
1646 path_aggctx *pag = sqlite3_aggregate_context(ctx,
sizeof (*pag));
1650 sqlite3_result_text(ctx, pag->
sb.
str, pag->
sb.
idx, sqlite3_free);
1658 sqlite3_result_text(ctx,
"", 0, SQLITE_STATIC);
1660 sqlite3_result_null(ctx);
1682 double v, scale, offset;
1687 pag = sqlite3_aggregate_context(ctx,
sizeof (*pag));
1696 type = sqlite3_value_type(args[0]);
1697 if ((type != SQLITE_INTEGER) && (type != SQLITE_FLOAT)) {
1700 v = sqlite3_value_double(args[0]);
1704 type = sqlite3_value_type(args[1]);
1705 if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1706 scale = sqlite3_value_double(args[2]);
1710 type = sqlite3_value_type(args[2]);
1711 if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
1712 offset = sqlite3_value_double(args[3]);
1715 v = v * scale + offset;
1735 int insize, outsize, start, itemsize = 1, itemskip = 0;
1737 char *indata, *outdata;
1740 sqlite3_result_error(ctx,
"need at least 1 argument", -1);
1743 indata = (
char *) sqlite3_value_blob(args[0]);
1744 insize = sqlite3_value_bytes(args[0]);
1745 if (!indata || (insize <= 0)) {
1747 sqlite3_result_null(ctx);
1750 start = sqlite3_value_int(args[1]);
1752 start = insize - start;
1756 }
else if (start > 0) {
1759 if (start >= insize) {
1762 outsize = sqlite3_value_int(args[2]);
1763 if (outsize > insize - start) {
1764 outsize = insize - start;
1770 itemsize = sqlite3_value_int(args[3]);
1771 if ((itemsize <= 0) || (itemsize > outsize)) {
1776 itemskip = sqlite3_value_int(args[4]);
1781 outdata = sqlite3_malloc(outsize);
1783 sqlite3_result_error(ctx,
"out of memory", -1);
1786 for (i = n = 0; i < outsize; i++) {
1787 for (k = 0; k < itemsize; k++) {
1788 outdata[i + k] = indata[start];
1791 if (start >= insize) {
1796 if (start >= insize) {
1801 sqlite3_result_blob(ctx, outdata, n, sqlite3_free);
1804 sqlite3_result_null(ctx);
1805 sqlite3_free(outdata);
1832 if (!rn || (rn->
ctx != ctx) || (rn->
value != args[0])) {
1833 rn = sqlite3_malloc(
sizeof (*rn));
1836 rn->
value = args[0];
1839 sqlite3_set_auxdata(ctx, 0, rn, sqlite3_free);
1843 sqlite3_result_int64(ctx, rn ? rn->
count : 0);
1859 sqlite3_create_function(db,
"subblob", -1, SQLITE_ANY, (
void *) 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,
1881 return sqlite3_create_module(db,
"blobtoxy", &
b2xy_module, 0);
1896 const sqlite3_api_routines *api)
1898 SQLITE_EXTENSION_INIT2(api);
static int print_strbuf(strbuf *sb, const char *fmt,...)
Format printf-like into dynamic string buffer.
static int b2xy_close(sqlite3_vtab_cursor *cur)
Close virtual table cursor.
static int b2xy_bestindex(sqlite3_vtab *tab, sqlite3_index_info *info)
Determines information for filter function according to constraints.
static int b2xy_next(sqlite3_vtab_cursor *cur)
Retrieve next row from virtual table cursor.
static const sqlite3_module b2xy_module
static int b2xy_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i)
Return column data of virtual table.
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.
static void blt_vec_step(sqlite3_context *ctx, int nargs, sqlite3_value **args)
Path/polyline step callback for "blt_vec" aggregate functions.
static void subblob_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
"subblob" function similar to "substr".
static int string_to_type(const char *str)
Map type string to type code.
static int init_strbuf(strbuf *sb)
Initialize dynamic string buffer with capacity 1024.
static void common_path_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
Make path/polyline from blob.
static int expand_strbuf(strbuf *sb)
Expand or initialize dynamic string buffer.
static void rownumber_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
"rownumber" function.
static void common_path_finalize(sqlite3_context *ctx)
Path/polyline finalizer.
static int b2xy_destroy(sqlite3_vtab *vtab)
Destroy virtual table.
struct b2xy_cursor b2xy_cursor
int sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api)
Initializer for SQLite extension load mechanism.
static int b2xy_rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *rowidp)
Return current rowid of virtual table cursor.
static int b2xy_init(sqlite3 *db)
Module initializer creating SQLite functions and modules.
static int b2xy_open(sqlite3_vtab *vtab, sqlite3_vtab_cursor **curret)
Open virtual table and return cursor.
static int b2xy_create(sqlite3 *db, void *userdata, int argc, const char *const *argv, sqlite3_vtab **vtabret, char **errp)
Create virtual table.
static int b2xy_eof(sqlite3_vtab_cursor *cur)
Return end of table state of virtual table cursor.
static void drop_strbuf(strbuf *sb)
Free resources of dynamic string buffer.
static int b2xy_filter(sqlite3_vtab_cursor *cur, int idxNum, const char *idxStr, int argc, sqlite3_value **argv)
Filter function for virtual table.
Structure to describe a cursor in the virtual table.
int x_length
X start/length.
int do_x_scale
If true, use X scale and offset.
int x_scale_col
Column number of X scale or 0.
int rowid_from_key
When true, ROWID used from key column.
int y_offset_col
Column number of Y offset or 0.
sqlite3_vtab_cursor base
SQLite's base cursor struct.
int x_offset_col
Column number of X offset or 0.
int fix_cols
Fixed number of columns of result set.
int val_len
Length of current BLOB.
double x_offset
Current X scale and offset.
int type
Data type of BLOB.
int y_scale_col
Column number of Y scale or 0.
int do_y_scale
If true, use Y scale and offset.
sqlite_int64 rowid
Current ROWID.
int index
Current index in BLOB.
sqlite3_value * key
Value of current key.
int do_x_sl
If true, apply X start/length.
sqlite3_stmt * select
Prepared SELECT statement or NULL.
char * val
Value of current BLOB.
double y_offset
Current X scale and offset.
int num_cols
Total number of columns of result set.
b2xy_table * table
Link to table struct.
Structure to describe a virtual table.
sqlite3_vtab base
SQLite's base virtual table struct.
char * y_offset_column
Name of column giving Y offset or NULL.
char * x_scale_column
Name of column giving X scale or NULL.
int x_length
X start/length.
sqlite3 * db
Open database.
char * blob_column
Name of BLOB column.
char * y_scale_column
Name of column giving Y scale or NULL.
char * x_offset_column
Name of column giving X offset or NULL.
char * key_column
Name of key column.
int do_x_sl
If true, apply X start/length.
int type
Data type of BLOB.
char * fq_master_table
Fully qualified master_table.
char ** argv
Argument vector from b2xy_create() call.
int argc
Number args from b2xy_create() call.
char * other_columns
Other columns or empty string.
char * master_table
Table where to fetch BLOB from.
Internal aggregate context for path/polyline function.
int init
init flag, true when initialized
int count
counts formatted elements
strbuf sb
string buffer for result
void * mode
mode, see PATH_* defines
int linebreak
when to add newline to output
SQLite context structure for "rownumber" function.
sqlite_int64 count
Counter giving row number.
sqlite3_context * ctx
SQLite context.
sqlite3_value * value
SQLite value for this context.
Driver internal structure representing SQL statement (HSTMT).
Internal dynamic string buffer.