11#if DETWS_ENABLE_SQLITE
17uint16_t be16(
const uint8_t *p)
19 return (uint16_t)(((uint16_t)p[0] << 8) | p[1]);
21uint32_t
be32(
const uint8_t *p)
23 return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
26const char SQLITE_MAGIC[16] = {
'S',
'Q',
'L',
'i',
't',
'e',
' ',
'f',
'o',
'r',
'm',
'a',
't',
' ',
'3',
'\0'};
28bool is_pow2(uint32_t v)
30 return v && (v & (v - 1)) == 0;
34size_t sqlite_varint_decode(
const uint8_t *buf,
size_t len, uint64_t *out)
37 for (
size_t i = 0; i < 8; i++)
41 v = (v << 7) | (uint8_t)(buf[i] & 0x7f);
42 if ((buf[i] & 0x80) == 0)
50 v = (v << 8) | buf[8];
55uint64_t sqlite_serial_type_size(uint64_t t)
84 return t >= 12 ? (t - 12) / 2 : 0;
88bool sqlite_parse_db_header(
const uint8_t *buf,
size_t len, SqliteDbHeader *out)
90 if (len < 100 || memcmp(buf, SQLITE_MAGIC, 16) != 0)
93 uint16_t raw_ps = be16(buf + 16);
94 uint32_t page_size = (raw_ps == 1) ? 65536u : raw_ps;
96 if (page_size < 512 || page_size > 65536 || !is_pow2(page_size))
99 out->page_size = page_size;
100 out->write_version = buf[18];
101 out->read_version = buf[19];
102 out->reserved_per_page = buf[20];
103 out->file_change_counter =
be32(buf + 24);
104 out->page_count =
be32(buf + 28);
105 out->freelist_first =
be32(buf + 32);
106 out->freelist_count =
be32(buf + 36);
107 out->schema_cookie =
be32(buf + 40);
108 out->schema_format =
be32(buf + 44);
109 out->text_encoding =
be32(buf + 56);
110 out->user_version =
be32(buf + 60);
111 out->application_id =
be32(buf + 68);
112 out->sqlite_version =
be32(buf + 96);
116bool sqlite_parse_btree_header(
const uint8_t *page,
size_t page_len,
size_t offset, SqliteBtreeHeader *out)
118 if (offset + 8 > page_len)
120 const uint8_t *p = page + offset;
123 (type == SqliteBtree::SQLITE_BTREE_INTERIOR_INDEX || type == SqliteBtree::SQLITE_BTREE_INTERIOR_TABLE);
124 bool leaf = (type == SqliteBtree::SQLITE_BTREE_LEAF_INDEX || type == SqliteBtree::SQLITE_BTREE_LEAF_TABLE);
125 if (!interior && !leaf)
127 uint8_t hdr = interior ? 12 : 8;
128 if (offset + hdr > page_len)
132 out->first_freeblock = be16(p + 1);
133 out->cell_count = be16(p + 3);
134 uint16_t ccs = be16(p + 5);
135 out->cell_content_start = (ccs == 0) ? 65536u : ccs;
136 out->frag_free_bytes = p[7];
137 out->right_most_page = interior ?
be32(p + 8) : 0;
138 out->header_size = hdr;
142uint32_t sqlite_cell_pointer(
const uint8_t *page,
size_t page_len,
const SqliteBtreeHeader *bh,
size_t page_offset,
145 if (i >= bh->cell_count)
147 size_t at = page_offset + bh->header_size + (size_t)i * 2;
148 if (at + 2 > page_len)
150 return be16(page + at);
153bool sqlite_parse_table_leaf_cell(
const uint8_t *page,
size_t page_len, uint32_t page_size, uint8_t reserved,
154 uint32_t cell_off, SqliteTableLeafCell *out)
156 if (cell_off >= page_len)
158 uint64_t payload_len = 0;
160 size_t n1 = sqlite_varint_decode(page + cell_off, page_len - cell_off, &payload_len);
163 size_t n2 = sqlite_varint_decode(page + cell_off + n1, page_len - cell_off - n1, &rowid);
168 uint32_t usable = page_size - reserved;
169 uint32_t max_local = usable - 35;
170 uint32_t min_local = ((usable - 12) * 32) / 255 - 23;
172 if (payload_len <= max_local)
174 local = (uint32_t)payload_len;
178 uint32_t k = min_local + (uint32_t)((payload_len - min_local) % (usable - 4));
179 local = (k <= max_local) ? k : min_local;
183 out->payload_len = (uint32_t)payload_len;
184 out->local_off = cell_off + (uint32_t)(n1 + n2);
185 out->local_len = local;
186 out->has_overflow = local < payload_len;
187 if (out->local_off + local > page_len)
192bool sqlite_read_payload(SqlitePageReader read,
void *ctx, uint32_t page_size, uint8_t reserved,
193 const uint8_t *leaf_page,
const SqliteTableLeafCell *cell, uint8_t *out, uint32_t out_cap,
196 if (cell->payload_len > out_cap)
198 if ((
size_t)cell->local_off + cell->local_len > page_size)
201 memcpy(out, leaf_page + cell->local_off, cell->local_len);
202 uint32_t got = cell->local_len;
203 if (!cell->has_overflow)
204 return got == cell->payload_len;
207 size_t ptr_off = (size_t)cell->local_off + cell->local_len;
208 if (ptr_off + 4 > page_size)
210 uint32_t next =
be32(leaf_page + ptr_off);
212 uint32_t usable = page_size - reserved;
213 uint32_t content = usable - 4;
218 uint32_t max_pages = cell->payload_len / content + 2;
220 for (uint32_t pages = 0; next != 0 && got < cell->payload_len; pages++)
224 if (pages >= max_pages)
226 if (!read(ctx, next, work_page, page_size))
228 uint32_t nnext =
be32(work_page);
229 uint32_t chunk = cell->payload_len - got;
234 if (got + chunk > out_cap)
236 memcpy(out + got, work_page + 4, chunk);
240 return got == cell->payload_len;
243bool sqlite_record_begin(SqliteRecordCursor *c,
const uint8_t *rec, uint32_t rec_len)
245 uint64_t hdr_len = 0;
246 size_t n = sqlite_varint_decode(rec, rec_len, &hdr_len);
247 if (n == 0 || hdr_len > rec_len || hdr_len < n)
250 c->rec_len = rec_len;
251 c->hdr_pos = (uint32_t)n;
252 c->hdr_end = (uint32_t)hdr_len;
253 c->val_pos = (uint32_t)hdr_len;
257bool sqlite_record_next(SqliteRecordCursor *c, uint64_t *serial_type,
const uint8_t **val, uint32_t *val_len)
259 if (c->hdr_pos >= c->hdr_end)
262 size_t n = sqlite_varint_decode(c->rec + c->hdr_pos, c->hdr_end - c->hdr_pos, &st);
265 uint32_t sz = (uint32_t)sqlite_serial_type_size(st);
266 if (c->val_pos + sz > c->rec_len)
269 *val = c->rec + c->val_pos;
271 c->hdr_pos += (uint32_t)n;
276int64_t sqlite_column_int(uint64_t serial_type,
const uint8_t *val, uint32_t val_len)
278 if (serial_type == 8)
280 if (serial_type == 9)
282 if (serial_type < 1 || serial_type > 6)
284 size_t nbytes = (size_t)sqlite_serial_type_size(serial_type);
285 if (val_len < nbytes)
288 for (
size_t i = 0; i < nbytes; i++)
289 u = (u << 8) | val[i];
290 size_t bits = nbytes * 8;
291 if (bits < 64 && (u & (1ULL << (bits - 1))))
292 u |= ~((1ULL << bits) - 1);
296double sqlite_column_float(
const uint8_t *val, uint32_t val_len)
301 for (
int i = 0; i < 8; i++)
302 u = (u << 8) | val[i];
311size_t page_hdr_off(uint32_t pgno)
313 return pgno == 1 ? 100 : 0;
318uint32_t interior_child(
const uint8_t *page,
size_t page_len,
const SqliteBtreeHeader *h,
size_t off, uint16_t i)
320 if (i >= h->cell_count)
321 return h->right_most_page;
322 uint32_t cp = sqlite_cell_pointer(page, page_len, h, off, i);
323 if (cp == 0 || (
size_t)cp + 4 > page_len)
325 return be32(page + cp);
329bool cursor_descend(SqliteTableCursor *c, uint32_t pgno)
333 if (!c->read(c->ctx, pgno, c->work, c->page_size))
335 size_t off = page_hdr_off(pgno);
337 if (!sqlite_parse_btree_header(c->work, c->page_size, off, &h))
339 if (h.type == SqliteBtree::SQLITE_BTREE_LEAF_TABLE)
341 memcpy(c->leaf, c->work, c->page_size);
343 c->leaf_off = (uint32_t)off;
345 c->leaf_count = h.cell_count;
349 if (h.type != SqliteBtree::SQLITE_BTREE_INTERIOR_TABLE)
351 if (c->depth >= SQLITE_BTREE_MAX_DEPTH)
353 uint32_t child = interior_child(c->work, c->page_size, &h, off, 0);
356 c->stack_pg[c->depth] = pgno;
357 c->stack_idx[c->depth] = 1;
364bool sqlite_table_cursor_begin(SqliteTableCursor *c, SqlitePageReader read,
void *ctx, uint32_t page_size,
365 uint8_t reserved, uint32_t rootpage, uint8_t *leaf_buf, uint8_t *work_buf)
369 c->page_size = page_size;
370 c->reserved = reserved;
373 c->ovf_buf =
nullptr;
378 return cursor_descend(c, rootpage);
381void sqlite_table_cursor_set_overflow_buf(SqliteTableCursor *c, uint8_t *buf, uint32_t cap)
389static bool sqlite_cursor_begin_row(SqliteTableCursor *c,
const SqliteTableLeafCell *cell, SqliteRecordCursor *row)
391 if (!cell->has_overflow || !c->ovf_buf)
392 return sqlite_record_begin(row, c->leaf + cell->local_off, cell->local_len);
394 if (!sqlite_read_payload(c->read, c->ctx, c->page_size, c->reserved, c->leaf, cell, c->ovf_buf, c->ovf_cap,
397 return sqlite_record_begin(row, c->ovf_buf, cell->payload_len);
400bool sqlite_table_cursor_next(SqliteTableCursor *c, uint64_t *rowid, SqliteRecordCursor *row)
404 if (c->leaf_cell < c->leaf_count)
406 uint32_t cp = sqlite_cell_pointer(c->leaf, c->page_size, &c->leaf_hdr, c->leaf_off, c->leaf_cell);
410 SqliteTableLeafCell cell;
411 if (!sqlite_parse_table_leaf_cell(c->leaf, c->page_size, c->page_size, c->reserved, cp, &cell))
413 if (!sqlite_cursor_begin_row(c, &cell, row))
421 int top = c->depth - 1;
422 if (!c->read(c->ctx, c->stack_pg[top], c->work, c->page_size))
424 size_t off = page_hdr_off(c->stack_pg[top]);
426 if (!sqlite_parse_btree_header(c->work, c->page_size, off, &h))
428 if (c->stack_idx[top] <= h.cell_count)
430 uint32_t child = interior_child(c->work, c->page_size, &h, off, c->stack_idx[top]);
432 if (child == 0 || !cursor_descend(c, child))
448void wr_be16(uint8_t *p, uint16_t v)
450 p[0] = (uint8_t)(v >> 8);
453void wr_be32(uint8_t *p, uint32_t v)
455 p[0] = (uint8_t)(v >> 24);
456 p[1] = (uint8_t)(v >> 16);
457 p[2] = (uint8_t)(v >> 8);
462size_t varint_len(uint64_t v)
468 if (v <= 0x1fffffULL)
470 if (v <= 0xfffffffULL)
472 if (v <= 0x7ffffffffULL)
474 if (v <= 0x3ffffffffffULL)
476 if (v <= 0x1ffffffffffffULL)
478 if (v <= 0xffffffffffffffULL)
484void value_serial(
const SqliteValue *v, uint64_t *st, uint32_t *vlen)
488 case SqliteColType::SQLITE_COL_NULL:
492 case SqliteColType::SQLITE_COL_FLOAT:
496 case SqliteColType::SQLITE_COL_TEXT:
497 *st = 13 + (uint64_t)2 * v->len;
500 case SqliteColType::SQLITE_COL_BLOB:
501 *st = 12 + (uint64_t)2 * v->len;
504 case SqliteColType::SQLITE_COL_INT:
519 else if (x >= -128 && x <= 127)
524 else if (x >= -32768 && x <= 32767)
529 else if (x >= -8388608 && x <= 8388607)
534 else if (x >= -2147483648LL && x <= 2147483647LL)
539 else if (x >= -140737488355328LL && x <= 140737488355327LL)
552uint32_t write_value(
const SqliteValue *v, uint64_t st, uint32_t vlen, uint8_t *out)
554 if (v->type == SqliteColType::SQLITE_COL_TEXT || v->type == SqliteColType::SQLITE_COL_BLOB)
557 memcpy(out, v->data, vlen);
560 if (v->type == SqliteColType::SQLITE_COL_FLOAT)
563 memcpy(&u, &v->f, 8);
564 for (
int i = 7; i >= 0; i--)
565 *out++ = (uint8_t)(u >> (i * 8));
568 if (st >= 1 && st <= 6)
570 uint64_t u = (uint64_t)v->i;
571 for (
int i = (
int)vlen - 1; i >= 0; i--)
572 out[(
int)vlen - 1 - i] = (uint8_t)(u >> (i * 8));
579uint32_t record_len(
const SqliteValue *cols, uint32_t n)
582 uint32_t val_len = 0;
583 for (uint32_t c = 0; c < n; c++)
587 value_serial(&cols[c], &st, &vl);
588 st_len += (uint32_t)varint_len(st);
592 size_t hs_varlen = 1;
595 uint64_t hs = hs_varlen + st_len;
596 if (varint_len(hs) == hs_varlen)
598 hs_varlen = varint_len(hs);
600 return (uint32_t)hs_varlen + st_len + val_len;
605bool write_leaf_page(uint8_t *page, uint32_t page_size, uint32_t hdr_off,
const SqliteRow *rows, uint32_t nrows)
607 const uint32_t usable = page_size;
608 const uint32_t max_local = usable - 35;
612 for (uint32_t r = 0; r < nrows; r++)
614 uint32_t rl = record_len(rows[r].cols, rows[r].ncols);
615 if (rl == 0 && rows[r].ncols != 0)
619 total += (uint32_t)varint_len(rl) + (uint32_t)varint_len(rows[r].rowid) + rl;
621 uint32_t header_end = hdr_off + 8 + 2 * nrows;
622 if ((uint64_t)header_end + total > page_size)
625 uint32_t content_start = page_size - total;
628 uint8_t *h = page + hdr_off;
629 h[0] = (uint8_t)SqliteBtree::SQLITE_BTREE_LEAF_TABLE;
631 wr_be16(h + 3, (uint16_t)nrows);
632 wr_be16(h + 5, (uint16_t)(content_start == 65536 ? 0 : content_start));
636 uint32_t off = page_size;
637 for (uint32_t r = 0; r < nrows; r++)
639 uint32_t rl = record_len(rows[r].cols, rows[r].ncols);
640 uint32_t cell_len = (uint32_t)varint_len(rl) + (uint32_t)varint_len(rows[r].rowid) + rl;
642 uint8_t *cp = page + off;
643 size_t k = sqlite_varint_encode(rl, cp, cell_len);
644 k += sqlite_varint_encode(rows[r].rowid, cp + k, cell_len - k);
645 uint32_t w = sqlite_encode_record(rows[r].cols, rows[r].ncols, cp + k, cell_len - (uint32_t)k);
648 wr_be16(page + hdr_off + 8 + 2 * r, (uint16_t)off);
654size_t sqlite_varint_encode(uint64_t v, uint8_t *out,
size_t cap)
656 size_t n = varint_len(v);
662 for (
int i = 0; i < 8; i++)
663 out[i] = (uint8_t)(0x80 | (uint8_t)((v >> (57 - 7 * i)) & 0x7f));
668 for (
size_t i = 0; i < n; i++)
670 uint8_t bits = (uint8_t)((v >> (7 * (n - 1 - i))) & 0x7f);
671 out[i] = (i + 1 < n) ? (uint8_t)(bits | 0x80) : bits;
676uint32_t sqlite_encode_record(
const SqliteValue *cols, uint32_t n, uint8_t *out, uint32_t out_cap)
678 uint32_t total = record_len(cols, n);
679 if (total == 0 && n != 0)
686 for (uint32_t c = 0; c < n; c++)
690 value_serial(&cols[c], &st, &vl);
691 st_len += (uint32_t)varint_len(st);
693 size_t hs_varlen = 1;
696 uint64_t hs = hs_varlen + st_len;
697 if (varint_len(hs) == hs_varlen)
699 hs_varlen = varint_len(hs);
701 uint32_t header_size = (uint32_t)hs_varlen + st_len;
703 uint32_t pos = (uint32_t)sqlite_varint_encode(header_size, out, out_cap);
705 for (uint32_t c = 0; c < n; c++)
709 value_serial(&cols[c], &st, &vl);
710 pos += (uint32_t)sqlite_varint_encode(st, out + pos, out_cap - pos);
713 for (uint32_t c = 0; c < n; c++)
717 value_serial(&cols[c], &st, &vl);
718 pos += write_value(&cols[c], st, vl, out + pos);
723uint32_t sqlite_build_table_db(uint32_t page_size,
const char *table_name,
const char *create_sql,
724 const SqliteRow *rows, uint32_t nrows, uint8_t *out, uint32_t out_cap)
726 if (page_size < 512 || page_size > 65536 || !is_pow2(page_size))
728 if ((uint64_t)page_size * 2 > out_cap || !table_name || !create_sql)
731 memset(out, 0, (
size_t)page_size * 2);
734 memcpy(out, SQLITE_MAGIC, 16);
735 wr_be16(out + 16, (uint16_t)(page_size == 65536 ? 1 : page_size));
742 wr_be32(out + 24, 1);
743 wr_be32(out + 28, 2);
744 wr_be32(out + 40, 1);
745 wr_be32(out + 44, 4);
746 wr_be32(out + 56, 1);
747 wr_be32(out + 92, 1);
748 wr_be32(out + 96, 3046001);
751 uint32_t name_len = (uint32_t)strnlen(table_name, out_cap);
752 uint32_t sql_len = (uint32_t)strnlen(create_sql, out_cap);
753 SqliteValue master[5];
754 master[0] = {SqliteColType::SQLITE_COL_TEXT, 0, 0, (
const uint8_t *)
"table", 5};
755 master[1] = {SqliteColType::SQLITE_COL_TEXT, 0, 0, (
const uint8_t *)table_name, name_len};
756 master[2] = {SqliteColType::SQLITE_COL_TEXT, 0, 0, (
const uint8_t *)table_name, name_len};
757 master[3] = {SqliteColType::SQLITE_COL_INT, 2, 0,
nullptr, 0};
758 master[4] = {SqliteColType::SQLITE_COL_TEXT, 0, 0, (
const uint8_t *)create_sql, sql_len};
759 SqliteRow master_row = {1, master, 5};
760 if (!write_leaf_page(out, page_size, 100, &master_row, 1))
764 if (!write_leaf_page(out + page_size, page_size, 0, rows, nrows))
767 return page_size * 2;
uint32_t be32(const uint8_t *p)