Commit Graph

500 Commits

Author SHA1 Message Date
Ihor Andrianov
2cab36bfc3 add json_replace, jsonb_replace 2025-03-23 20:52:03 +02:00
Ihor Andrianov
c4549ad2cd split json traversal and mutation operation logic 2025-03-23 20:37:12 +02:00
Ihor Andrianov
252583cb1e add jsonb_obj jsonb_array 2025-03-20 15:22:52 +02:00
Ihor Andrianov
32ea972151 make tests pass 2025-03-19 11:29:46 +02:00
Ihor Andrianov
b5e86a9e36 remove and replace functions defenitions 2025-03-18 21:43:48 +02:00
Pekka Enberg
f9d7834874 Merge 'Jsonb extract' from Ihor Andrianov
Made a jsonb traversal by json path.
Changed some ordinary json functions to use jsonb under the hood, so now
behavior of our json module more like sqlite.
Found and fixed some bugs on the way.

Closes #1135
2025-03-17 18:25:28 +02:00
Diego Reis
16396c57c7 Removes unnecessary clone 2025-03-17 10:06:14 -03:00
Diego Reis
2314e7f906 Improve explain output for Transaction bytecode.
It isn't SQLite compliant but it helps a lot, specially when the user doesn't know what each register means.
2025-03-17 09:50:22 -03:00
Diego Reis
590f90ad9a Fix AutoCommit handling of an ongoing halt checkpoint 2025-03-16 15:35:49 -03:00
Ihor Andrianov
23d7d82b6c add jsonb_extract function 2025-03-16 15:14:29 +02:00
Ihor Andrianov
0b22fbd566 Add jsonb to json_valid 2025-03-16 03:26:08 +02:00
Pekka Enberg
731fbaf3c7 Merge 'Jsonb implementation' from Ihor Andrianov
This PR implements a complete JSONB parser and serializer as current PR
draft looks stale.
Sorry for huge PR.
I've choose a recursive parsing approach because:
1. It's simpler to understand and maintain
2. It follows SQLite's implementation pattern, ensuring compatibility
3. It naturally maps to JSON's hierarchical structure
The implementation includes comprehensive test coverage for standard
JSON features and JSON5 extensions. All test cases pass successfully,
handling edge cases like nested structures, escape sequences, and
various number formats.
While the code is ready for review, I believe it would benefit from fuzz
testing in the future to identify any edge cases not covered by the
current tests.
Ready for review, proposals and feedback.

Closes #1114
2025-03-13 21:17:52 +02:00
Pere Diaz Bou
cc320a74ca few checkpoint result cleanup in vdbe 2025-03-12 15:48:22 +01:00
Pere Diaz Bou
be3badc1f3 modify a few btree log level and add end_write_txn after checkpoint 2025-03-12 15:48:22 +01:00
Ihor Andrianov
04f69220b7 add jsonb function implementation and json now understands blobs 2025-03-12 15:03:40 +02:00
Pekka Enberg
b0636e4494 Merge 'Adds Drop Table' from Zaid Humayun
This PR adds support for `DROP TABLE` and addresses issue
https://github.com/tursodatabase/limbo/issues/894
It depends on https://github.com/tursodatabase/limbo/pull/785 being
merged in because it requires the implementation of `free_page`.
EDIT: The PR above has been merged.
It adds the following:
* an implementation for the `DropTable` AST instruction via a method
called `translate_drop_table`
* a couple of new instructions - `Destroy` and `DropTable`. The former
is to modify physical b-tree pages and the latter is to modify in-memory
structures like the schema hash table.
* `btree_destroy` on `BTreeCursor` to walk the tree of pages for this
table and place it in free list.
* state machine traversal for both `btree_destroy` and
`clear_overflow_pages` to ensure performant, correct code.
* unit & tcl tests
* modifies the `Null` instruction to follow SQLite semantics and accept
a second register. It will set all registers in this range to null. This
is required for `DROP TABLE`.
The screenshots below have a comparison of the bytecodes generated via
SQLite & Limbo.
Limbo has the same instruction set except for the subroutines which
involve opening an ephemeral table, copying over the triggers from the
`sqlite_schema` table and then re-inserting them back into the
`sqlite_schema` table.
This is because `OpenEphemeral` is still a WIP and is being tracked at
https://github.com/tursodatabase/limbo/pull/768
![Screenshot 2025-02-09 at 7 05 03 PM](https://github.com/user-
attachments/assets/1d597001-a60c-4a76-89fd-8b90881c77c9)
![Screenshot 2025-02-09 at 7 05 35 PM](https://github.com/user-
attachments/assets/ecfd2a7a-2edc-49cd-a8d1-7b4db8657444)

Reviewed-by: Pere Diaz Bou <pere-altea@homail.com>

Closes #897
2025-03-06 18:27:41 +02:00
Pekka Enberg
2c9d30cef4 core/vdbe: Don't commit MVCC on Halt if no autocommit
Spotted by Pere.
2025-03-06 12:52:03 +02:00
Pekka Enberg
d6c514c8d1 core: Integrate MVCC to B-Tree cursor 2025-03-06 10:16:42 +02:00
Pekka Enberg
bf3163c7fe core: Fix parse_schema() to use existing MVCC TX 2025-03-06 10:16:42 +02:00
Pekka Enberg
ef32a82941 core/vdbe: Integrate MVCC transactions 2025-03-06 10:16:42 +02:00
Pere Diaz Bou
aa7391da50 fix halt return 2025-03-05 22:32:59 +01:00
Pere Diaz Bou
b555561aeb make Program::halt reentrant 2025-03-05 22:32:59 +01:00
Pere Diaz Bou
feeb398e73 finish transaction and reset transaction state 2025-03-05 22:32:59 +01:00
Pere Diaz Bou
262c4de548 add line number and thread id to tracing logs 2025-03-05 15:36:47 +01:00
Pere Diaz Bou
e20dd59353 Make schema a RWLock
This makes it work like in SQLite where only one schema writer is permitted and readers will return error while preparing statement if the schema is changing.
2025-03-05 14:07:48 +01:00
Pere Diaz Bou
e4a8ee5402 move load extensions to Connection
Extensions are loaded per connection and not per database as per SQLite
behaviour. This also helps with removing locks.
2025-03-05 14:07:48 +01:00
Pere Diaz Bou
8daf7666d1 Make database Sync + Send 2025-03-05 14:07:48 +01:00
Pekka Enberg
f57d2b32af core: Clean up B-Tree creation code
Move page allocation to pager so that we don't need to instantiate a
cursor to create a B-Tree.
2025-03-04 18:38:06 +02:00
Pekka Enberg
f3ee86d784 core/vdbe: Replace get_btree_{table,index}_cursor() calls with get_cursor() 2025-03-04 15:17:57 +02:00
Pekka Enberg
cdcaebb878 core/vdbe: Unify B-Tree cursors 2025-03-04 14:35:40 +02:00
Pekka Enberg
1c0d9c3b46 core/vdbe: Replace get_pseudo_cursor() calls with get_cursor() 2025-03-04 14:18:52 +02:00
Pekka Enberg
c12f2aeca4 core/vdbe: Replace get_sorter() calls with get_cursor() 2025-03-04 13:51:05 +02:00
Pekka Enberg
45539a4fe5 core/vdbe: Replace get_vtab_cursor() calls with get_cursor() 2025-03-04 13:43:49 +02:00
Pekka Enberg
085f93ce79 core/vdbe: Add ProgramState::get_cursor() helper 2025-03-04 12:23:35 +02:00
Pekka Enberg
3aeb11b673 core/vdbe: Add ProgramStatem::get_btree_{table,index}_cursor() helpers 2025-03-04 11:40:43 +02:00
Pekka Enberg
222808ab6c ore/vdbe: Add ProgramState::get_pseudo_cursor() helper 2025-03-04 11:21:24 +02:00
Pekka Enberg
06446b768b core/vdbe: Add ProgramState::get_sorter() helper 2025-03-04 11:18:09 +02:00
Pekka Enberg
e4ebb6d9e1 core/vdbe: Add ProgramState::get_vtab_cursor() helper 2025-03-04 11:16:29 +02:00
Pekka Enberg
dc525dd7d1 core/vdbe: Kill call_external_function macro
The call_external_function macro has exactly one call-site and,
therefore, only makes the code harder to read.
2025-03-04 11:01:09 +02:00
Pekka Enberg
ddb188132c Merge 'Clean up extension types API, introduce json text subtype' from Preston Thorpe
This PR cleans up some comments in the extension API and prevents
extensions themselves from calling 'free' on Value types that are
exposed to the user facing traits, as well as changes the `from_ffi`
method for OwnedValues to take ownership and automatically free the
values to prevent memory leaks.
This PR also finds the name of the `args: &[Value]` argument for scalar
functions in extensions, and uses that in the proc macro, instead of
relying on documentation to communicate that the parameter must be named
`args`.

Closes #1054
2025-03-04 10:24:19 +02:00
Pekka Enberg
2e4c18dca2 Merge 'Escape character is ignored in LIKE function' from lgualtieri75
Fixes #1051

Reviewed-by: Preston Thorpe (@PThorpe92)

Closes #1074
2025-03-04 10:23:09 +02:00
PThorpe92
588e43c5aa Minor improvements and cleanups in btree 2025-03-01 15:48:42 -05:00
PThorpe92
5b8efd92a4 Update extension ownership cleanups for new vtab module 2025-03-01 14:27:33 -05:00
PThorpe92
e7713e87ec Prevent extensions from accidentally freeing value types, fix comments 2025-03-01 14:27:33 -05:00
l.gualtieri
6449c79e93 Escape character is ignored in LIKE function #1051 2025-03-01 18:32:09 +01:00
Zaid Humayun
23a904f38d Merge branch 'main' of https://github.com/tursodatabase/limbo 2025-03-01 01:18:45 +05:30
Pekka Enberg
b4e8afa3c7 Merge 'Implement SQLite balancing algorithm' from Pere Diaz Bou
Beep boop.
What happened you ask? I removed the dumb balancing algorithm I
implemented in favor of SQLite's implementation based on B*Tree[1] where
a page is 2/3 full instead of 1/2. It also tries to balance a page by
taking a maximum 3 pages and distributing cells evenly between them.
I've made some changes that are somewhat related:
* Moved most operations on pages out of BTreeCursor because those
operations are based on a page, not on a cursor, and it makes it easier
to test.
* Fixed `write_u16` and `read_u16` cases that didn't need a implicit
offset calculation. Added: `write_u16_no_offset` and
`read_u16_no_offset` to counter this.
* Added some tests with fuzz testing too.
* Fixed some important actions like: `compute_free_space`,
`defragment_page` and `drop_cell`.
[1] https://dl.acm.org/doi/10.1145/356770.356776

Closes #968
2025-02-28 19:10:52 +02:00
l.gualtieri
cf407f639e fix #1064 2025-02-27 19:47:51 +01:00
Pekka Enberg
936ae307b7 core: Kill value type
We currently have two value types, `Value` and `OwnedValue`. The
original thinking was that `Value` is external type and `OwnedValue` is
internal type. However, this just results in unnecessary transformation
between the types as data crosses the Limbo library boundary.

Let's just follow SQLite here and consolidate on a single value type
(where `sqlite3_value` is just an alias for the internal `Mem` type).
The way this will eventually work is that we can have bunch of
pre-allocated `OwnedValue` objects in `ProgramState` and basically
return a reference to them all the way to the application itself, which
extracts the actual value.
2025-02-26 10:57:45 +02:00
Pekka Enberg
fe440b7b34 Merge 'Fix casting text to integer to match SQLite' from Preston Thorpe
```console
thread 'fuzz::tests::logical_expression_fuzz_run' panicked at tests\integration\fuzz\mod.rs:818:13:
assertion `left == right` failed: query: SELECT  ( ( 3622873 || -8851250 ) * ( ( ( -124 ) + ( -5792536 ) ) ) ) = ( 179434259456392 < 65481085924370 ), limbo: [[Integer(1)]], sqlite: [[Integer(0)]]
  left: [[Integer(1)]]
 right: [[Integer(0)]]
```
This and a few other failing fuzzing tests were due to incorrectly
parsing numerics from strings. Some of our casting was done properly,
but it wasn't being applied to all cases where the behavior was needed.
It was also attempting to parse a string[0..N] N times until
`string[0..N].parse()` would no longer succeed. This searches for the
index of the first illegal character and parses the resulting slice
once.
Tests were added for some of the edgecases that were previously failing.
This PR also adds a macro in vdbe/insn.rs that allows for a bit of
cleanup and reduces some matching.

Closes #1053
2025-02-25 15:44:37 +02:00