Commit Graph

1658 Commits

Author SHA1 Message Date
PThorpe92
8070e51e26 Fix vdbe casting and rounding issues 2025-02-24 11:21:22 -05:00
PThorpe92
8f27a5fc92 Fix (fuzzing tests) casting text to integer to match sqlite behavior 2025-02-24 11:13:25 -05:00
Pekka Enberg
eb6019b453 cargo fmt 2025-02-24 17:39:21 +02:00
Pekka Enberg
16306ee1f4 Merge 'Modify the LIKE function to work with all types' from Mohamed Hossam
This PR fixes
[#1040](https://github.com/tursodatabase/limbo/issues/1040) and modifies
the `LIKE` function in the VDBE to work on expressions of all types like
SQLite.
Looking at how SQLite handles this, it gets the text value of the
expression regardless of its affinity. I used `exec_cast(exp, "TEXT")`
to achieve the same effect. Since most `LIKE` queries will probably be
done on `TEXT` expressions, I avoid casting the expression if it's
already `TEXT`. If either of the expressions was `NULL`, SQLite returns
nothing i.e. `NULL`. I also changed the unreachable arm message from
`Like on non-text registers` to `Like failed`.
The following queries produced the same results in Limbo:
```
SQLite version 3.46.1 2024-08-13 09:16:08 (UTF-16 console I/O)
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> CREATE TABLE tbl (n NULL, i INTEGER, r REAL, t TEXT, b BLOB);
sqlite> INSERT INTO tbl VALUES(NULL,1,2.0,'a',X'0500');
sqlite> SELECT * FROM tbl;
|1|2.0|a|♣
sqlite> SELECT * FROM tbl WHERE n LIKE NULL;
sqlite> SELECT * FROM tbl WHERE n LIKE 'NULL';
sqlite> SELECT * FROM tbl WHERE n LIKE 1;
sqlite> SELECT * FROM tbl WHERE n LIKE 2.0;
sqlite> SELECT * FROM tbl WHERE n LIKE x'0500';
sqlite>
sqlite> SELECT * FROM tbl WHERE i LIKE NULL;
sqlite> SELECT * FROM tbl WHERE i LIKE 1;
|1|2.0|a|♣
sqlite> SELECT * FROM tbl WHERE i LIKE '1';
|1|2.0|a|♣
sqlite> SELECT * FROM tbl WHERE i LIKE 2.0;
sqlite> SELECT * FROM tbl WHERE i LIKE 1.0;
sqlite> SELECT * FROM tbl WHERE i LIKE x'0500';
sqlite>
sqlite> SELECT * FROM tbl WHERE r LIKE NULL;
sqlite> SELECT * FROM tbl WHERE r LIKE 2;
sqlite> SELECT * FROM tbl WHERE r LIKE 2.0;
|1|2.0|a|♣
sqlite> SELECT * FROM tbl WHERE r LIKE '2.0';
|1|2.0|a|♣
sqlite> SELECT * FROM tbl WHERE r LIKE 'a';
sqlite> SELECT * FROM tbl WHERE r LIKE x'0500';
sqlite>
sqlite> SELECT * FROM tbl WHERE t LIKE NULL;
sqlite> SELECT * FROM tbl WHERE t LIKE 1;
sqlite> SELECT * FROM tbl WHERE t LIKE 2.0;
sqlite> SELECT * FROM tbl WHERE t LIKE 'a';
|1|2.0|a|♣
sqlite> SELECT * FROM tbl WHERE t LIKE x'0500';
sqlite>
sqlite> SELECT * FROM tbl WHERE b LIKE NULL;
sqlite> SELECT * FROM tbl WHERE b LIKE 1;
sqlite> SELECT * FROM tbl WHERE b LIKE 2.0;
sqlite> SELECT * FROM tbl WHERE b LIKE 'a';
sqlite> SELECT * FROM tbl WHERE b LIKE x'0500';
|1|2.0|a|♣
sqlite> SELECT * FROM tbl WHERE b LIKE 'x''0500''';
sqlite> SELECT * FROM tbl WHERE b LIKE '♣';
sqlite>
sqlite> SELECT * FROM tbl WHERE 1 LIKE 1;
|1|2.0|a|♣
sqlite> SELECT * FROM tbl WHERE 2.0 LIKE 2.0;
|1|2.0|a|♣
sqlite> SELECT * FROM tbl WHERE 2.0 LIKE '2.0';
|1|2.0|a|♣
sqlite> SELECT * FROM tbl WHERE '2.0' LIKE 2.0;
|1|2.0|a|♣
sqlite> SELECT * FROM tbl WHERE '123.45' LIKE 123.45;
|1|2.0|a|♣
sqlite> SELECT * FROM tbl WHERE NULL LIKE NULL;
sqlite> SELECT * FROM tbl WHERE x'0500' LIKE x'0500';
|1|2.0|a|♣
sqlite> SELECT typeof(n), typeof(i), typeof(r), typeof(t), typeof(b) FROM tbl;
null|integer|real|text|blob
```
Though, these queries are very basic, and more testing could be done.

Closes #1044
2025-02-24 11:27:02 +02:00
Pekka Enberg
4cefb222db Merge 'Fix cast_text_to_number compatibility' from Pedro Muniz
Modified  `cast_text_to_number` to be more compatible with SQLite. When
I was running some fuzz tests, I would eventually get errors due to
incorrect casting of text to `INTEGER` or `REAL`. Previously in code
there were 2 implementations of `cast_text_to_number`: one in
`core/vdbe/insn.rs` and one in `core/vdbe/mod.rs`. I consolidated the
casting to only one function. Previously, the `mod.rs` function was just
calling `checked_cast_text_to_numeric`, which was used in `MustBeInt`
opcode.  Hopefully this fixes some of the CI testing issues we are
having. This was the query that prompted me to do this: `SELECT  ( ( (
878352367 ) <> ( 29 ) ) ) = ( ( ( -4309097 ) / ( -37 || -149680985265412
) ) - 755066415 );`

Closes #1038
2025-02-24 11:20:14 +02:00
Pekka Enberg
600ce590fb Merge 'Handle parsing URI according to SQLite specification' from Preston Thorpe
closes #977
In order to properly get #960 merged and keep some sort of the same API
we have now, we need to support URIs/query parameters for opening new
databases.
This PR doesn't attempt to implement anything useful with this, it only
handles parsing, but it will allow #960 to properly open a new file with
a specific VFS without having to entirely re-design the `open_file`
method/API. The existing option in that PR right now is less than ideal.
e.g. All of the existing methods already accept an `IO` impl
```rust
    pub fn open_file(io: Arc<dyn IO>, path: &str) -> Result<Arc<Database>> {
// or
      pub fn open(
        io: Arc<dyn IO>,
        page_io: Rc<dyn DatabaseStorage>,
        wal: Rc<RefCell<dyn Wal>>,
        shared_wal: Arc<RwLock<WalFileShared>>,
        buffer_pool: Rc<BufferPool>,
    ) -> Result<Arc<Database>> {

```
Right now, most of the parsed query parameters are not options we
support yet, but I figured it's better to handle parsing them now and
using them later on when we support them.
Also, if this looks way overly complicated for what it does... that's
because the cross platform edge-cases are a super pain in the ass.

Closes #1039
2025-02-24 11:17:39 +02:00
m0hossam
2204d92a0b Modify LIKE to handle all affinities including Nulls 2025-02-22 04:43:43 +02:00
pedrocarlo
2e38aa1d6b remove dbg 2025-02-20 16:09:39 -03:00
pedrocarlo
13639899a5 more adjustments to parser to handle edge cases 2025-02-20 16:05:50 -03:00
pedrocarlo
033d0116d6 rewrote parsing from text to integer and real 2025-02-20 02:16:30 -03:00
m0hossam
2425b601f7 Cast the matching value into TEXT before matching 2025-02-20 04:57:01 +02:00
m0hossam
1935426509 Add support for Int columns in LIKE function 2025-02-20 00:42:41 +02:00
PThorpe92
e86f00cb81 Add normalizing windows paths to sqlite spec 2025-02-18 22:41:35 -05:00
pedrocarlo
409297cfdd remove comment 2025-02-19 00:05:56 -03:00
PThorpe92
42a0c18574 Add parsing sqlite URI to prep for vfs 2025-02-18 21:02:48 -05:00
pedrocarlo
0c5696c26a remove comment 2025-02-18 21:43:57 -03:00
alpaylan
39b11812ea bump rusqlite to 0.33.0 from 0.29.0 2025-02-18 15:13:15 -05:00
pedrocarlo
0ca6bbab05 modified cast_text_to_number for more compatability with sqlite 2025-02-18 16:28:44 -03:00
Pekka Enberg
9973c22137 core: Specify mimalloc version
The "*" version is not allowed on crates.io.
2025-02-18 19:40:00 +02:00
Pekka Enberg
98010517d5 Merge 'Add affinity() function to Column' from Jussi Saurio
This is a first step to supporting [sqlite column
affinity](https://www.sqlite.org/datatype3.html) properly in limbo --
just adds an `affinity()` function to `Column` that can then be used
elsewhere

Closes #1030
2025-02-18 17:44:38 +02:00
Jussi Saurio
baf2aec3e9 Fix incorrect CAST text->numeric if valid prefix is 1 char long 2025-02-18 15:07:36 +02:00
Jussi Saurio
89e48a16db Add affinity() function to Column 2025-02-18 10:56:30 +02:00
Pekka Enberg
899ba8367e Merge 'Fix remainder panic on zero right-hand-side' from Jussi Saurio
Closes #1025
2025-02-18 10:08:23 +02:00
Jussi Saurio
8e5499e5ed Fix not evaling constant conditions when no tables in query
We were not evaluating constant conditions (e.g '1 IS NULL')
when there were no tables referenced in the query, because
our WHERE term evaluation was based on "during which loop"
to evaluate them. However, when there are no tables, there are
no loops, so they were never evaluated.
2025-02-17 13:10:27 +02:00
Jussi Saurio
ec3ae2ace6 Fix remainder panic on zero right-hand-side 2025-02-17 13:09:33 +02:00
Jussi Saurio
bece5b601a Add comment about translate_like_base 2025-02-17 10:55:26 +02:00
Jussi Saurio
447f91e5ee optimizer.rs: remove constant folding optimization for NULL since it's incorrect 2025-02-17 07:43:09 +02:00
Jussi Saurio
9bf5b9609f expr.rs: Binary: use translate_expr()'s impl for currently unsupported ops in translate_condition_expr() 2025-02-17 07:43:09 +02:00
Jussi Saurio
28ad12699f expr.rs: Unary: use shared impl in translate_expr() and translate_condition_expr() 2025-02-17 07:43:09 +02:00
Jussi Saurio
dc852fee8c expr.rs: Like: use shared impl in translate_expr() and translate_condition_expr() 2025-02-17 07:43:09 +02:00
Jussi Saurio
c6b8100d64 expr.rs: Case: call translate_expr() from translate_condition_expr() 2025-02-17 07:43:09 +02:00
Jussi Saurio
4f384e3a02 expr.rs: Rowid: call translate_expr() from translate_condition_expr() 2025-02-17 07:43:09 +02:00
Jussi Saurio
d91ba9573b expr.rs: Column: call translate_expr() from translate_condition_expr() 2025-02-17 07:43:08 +02:00
Jussi Saurio
7023ffc215 expr.rs: FunctionCall: call translate_expr() from translate_condition_expr() 2025-02-17 07:43:08 +02:00
Jussi Saurio
b93e01d59f expr.rs: Cast: call translate_expr() from translate_condition_expr() 2025-02-17 07:43:05 +02:00
Nikita Sivukhin
37e27131e3 fix inequality 2025-02-16 12:49:55 +04:00
Nikita Sivukhin
d2a507e458 add unit tests for reading integer serial types 2025-02-16 12:46:45 +04:00
Nikita Sivukhin
279652b271 extend sign for 24/48 bit width serial types 2025-02-16 12:46:18 +04:00
Nikita Sivukhin
db7544fe7a Merge branch 'tursodatabase:main' into fix-and-predicate 2025-02-15 22:57:56 +04:00
Jussi Saurio
aea8b416bc Merge 'mvcc: comments and small cleanup' from Jussi Saurio
Closes #930
2025-02-15 18:18:01 +02:00
Jussi Saurio
01f51a4c20 Merge 'Fix math binary' from Nikita Sivukhin
Fix codegen for binary functions and add fuzz test for math functions
(we need to compile `rusqlite` with `-DSQLITE_ENABLE_MATH_FUNCTIONS` in
order to bundle sqlite with math functions compiled)

Reviewed-by: Jussi Saurio (@jussisaurio)

Closes #1015
2025-02-15 18:17:08 +02:00
Jussi Saurio
cbfd77849d Merge 'Fix substr' from Nikita Sivukhin
Align `substr` implementation with SQLite spec
(https://www.sqlite.org/lang_corefunc.html#substr):
> The substr(X,Y,Z) function returns a substring of input string X that
begins with the Y-th character and which is Z characters long. If Z is
omitted then substr(X,Y) returns all characters through the end of the
string X beginning with the Y-th. The left-most character of X is number
1. If Y is negative then the first character of the substring is found
by counting from the right rather than the left. If Z is negative then
the abs(Z) characters preceding the Y-th character are returned. If X is
a string then characters indices refer to actual UTF-8 characters. If X
is a BLOB then the indices refer to bytes.

Reviewed-by: Jussi Saurio (@jussisaurio)

Closes #1013
2025-02-15 18:16:57 +02:00
Nikita Sivukhin
ee8b03528d fix codegen for and predicate - as jump_if_condition_is_true can be overwritten higher in the stack 2025-02-15 16:27:27 +04:00
Jussi Saurio
e4541edb48 Fix IdxGt,IdxGe,IdxLt,IdxLe instructions
According to SQLite documentation, the way to use these instructions
is to compare the seek key to the index key as you would with the
Compare opcode. The compare opcode states:

"Compare two vectors of registers in reg(P1)..reg(P1+P3-1)
(call this vector "A") and in reg(P2)..reg(P2+P3-1) ("B")."

In other words, we should compare the same number of columns from each,
not compare the entire keys.

This fixes a few Clickbench queries returning incorrect results, and
so closes #1009

---

Future work: support index seek keys that use multiple columns. Our
index seek is many times slower than SQLite because we're not utilizing
all the possible columns -- instead we just use the first index column
to seek.
2025-02-15 12:44:56 +02:00
Nikita Sivukhin
e25660833b fix codegen for binary functions 2025-02-15 14:33:57 +04:00
Nikita Sivukhin
91d723016d fix test 2025-02-15 13:29:14 +04:00
Nikita Sivukhin
b35dab5b6d fix substr implementation 2025-02-15 13:21:43 +04:00
Pekka Enberg
30f700174c Merge 'Added IdxLE and IdxLT opcodes' from Omolola Olamide
I added the two opcodes as an initial step. They are pretty easy to
implement since we already have the counterparts i.e., IdxGE and IdxGT
Is there a design reason behind their omission @penberg @PThorpe92?
I noticed the same for SeekLE and SeekLT.

Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>

Closes #1010
2025-02-15 11:10:17 +02:00
Pekka Enberg
20e37e485a Merge 'Implement the legacy_file_format pragma' from Glauber Costa
easy implementation, sqlite claims it is a noop now
"This pragma no longer functions. It has become a no-op. The
capabilities formerly provided by PRAGMA legacy_file_format are now
available using the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option to the
sqlite3_db_config() C-language interface."

Closes #1007
2025-02-15 11:03:05 +02:00
Pekka Enberg
c53897cb6c Merge 'Support numeric column references in GROUP BY' from Jussi Saurio
We already supported this for ORDER BY but not GROUP BY - again noticed
this when running against some clickbench queries

Closes #1008
2025-02-15 11:02:28 +02:00