Commit Graph

995 Commits

Author SHA1 Message Date
Jussi Saurio
d2f5e67b25 Merge 'Fix COLLATE' from Jussi Saurio
Fixes the following problems with COLLATE:
- Fix: incorrectly used e.g. `x COLLATE NOCASE = 'fOo'` as index
constraint on an index whose column was not case-insensitively collated
- Fix: various ephemeral indexes (in GROUP BY, ORDER BY, DISTINCT) and
subqueries did not retain proper collation information of columns
- Fix: collation of a given expression was not determined properly
according to SQLite's rules
Adds TCL tests and fuzz test
Closes #3476
Closes #1524
Closes #3305

Reviewed-by: Preston Thorpe <preston@turso.tech>

Closes #3538
2025-10-03 09:34:24 +03:00
Jussi Saurio
ce7fe54841 Collate: add more TCL tests 2025-10-02 21:49:33 +03:00
PThorpe92
361bd70a26 Add regression test for rowid affinity 2025-10-02 14:31:22 -04:00
Pekka Enberg
dc1463c70d Merge 'Improve error handling for cyclic views' from Duy Dang
The cycle is detected by marking a seen view, if a seen view is process
again, that's a cycle and we throw an error.
Close #3404

Closes #3467
2025-10-02 19:33:12 +03:00
Jussi Saurio
30e6524c4e Fix: JOIN USING should pick columns from left table, not right
Closes #3468
Closes #3479
2025-10-02 06:56:52 +03:00
Jussi Saurio
c0da38e24a Merge 'Clear WhereTerm 'from_outer_join' state when LEFT JOIN is optimized to INNER JOIN' from Jussi Saurio
Closes #3470
## Background
In a query like `SELECT * FROM t LEFT JOIN s ON t.a=s.a WHERE s.a =
'foo'` we can remove the LEFT JOIN and replace it with an `INNER JOIN`
because NULL values will never be equal to 'foo'. Rewriting as `INNER
JOIN` allows the optimizer to also reorder the table join order to come
up with a more efficient query plan. In fact, we have this optimization
already.
## Problem
However, there is a dumb bug where `WhereTerm`s involving this join
still retain their `from_outer_join` state, resulting in forcing the
evaluation of those terms at the original join index, which results in
completely wrong bytecode if the join optimizer decides to reorder the
join as `s JOIN t` instead. Effectively it will evaluate `t.a=s.a` after
table `s` is open but table `t` is not open yet.
## Fix
This PR fixes that issue by clearing `from_outer_join` properly from the
relevant `WhereTerm`s.

Closes #3475
2025-10-02 06:56:07 +03:00
Jussi Saurio
78cccdd87a Merge 'Substr fix UTF-8' from Pedro Muniz
Fixes:
- `start_value` and `length_value` should be casted to integers
- proper handling of utf-8 characters
- do not need to cast blob to string, as substr in blobs refers to byte
indexes and not char-indexes

Closes #3465
2025-10-02 06:55:38 +03:00
Preston Thorpe
b310411997 Merge 'printf should truncates floats' from Pavan Nambi
closes https://github.com/tursodatabase/turso/issues/3308

Reviewed-by: Preston Thorpe <preston@turso.tech>

Closes #3415
2025-10-01 19:31:39 -04:00
Jussi Saurio
3ff6b44de2 Merge 'Fix index bookkeeping in DROP COLUMN' from Jussi Saurio
Closes #3448. Nasty bug - see issue for details

Closes #3449
2025-10-01 08:57:08 +03:00
Jussi Saurio
27b1c1a1db Merge 'Fix self-insert with nested subquery' from Mikaël Francoeur
There were 2 problems:
1. The SELECT wasn't propagating which register it used for its results,
so sometimes the INSERT read bad data.
2. `TableReferences::contains_table` was only checking the top-level
tables, not the nested tables in FROM queries. This condition is used to
emit "template 4", the bytecode template for self-inserts.
Closes https://github.com/tursodatabase/turso/issues/3312

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

Closes #3436
2025-10-01 08:56:16 +03:00
Jussi Saurio
63f9913dbb Clear WhereTerm 'from_outer_join' state when LEFT JOIN is optimized to INNER JOIN
Closes #2470

In a query like `SELECT * FROM t LEFT JOIN s ON t.a=s.a WHERE s.a = 'foo'` we can
remove the LEFT JOIN because NULL values will be equal to 'foo'. In fact, we have
this optimization already.

However, there was a dumb bug where `WhereTerm`s involving this join still retained
their `from_outer_join` state, resulting in forcing the evaluation of those terms
at the original join index, which results in completely wrong bytecode if the join
optimizer decides to reorder the join as `s JOIN t` instead. Effectively it will
evaluate `t.a=s.a` after table `s` is open but table `t` is not open yet.

This PR fixes that issue by clearing `from_outer_join` properly from the relevant
`WhereTerm`s.
2025-10-01 00:33:22 +03:00
Duy Dang
5ceab1b3f4 Circle detection for views 2025-10-01 02:12:21 +07:00
Nikita Sivukhin
9ef05adc5e fix upsert conflict handling 2025-09-30 22:39:55 +04:00
pedrocarlo
d5e365def4 add test 2025-09-30 15:26:13 -03:00
Nikita Sivukhin
3590f9882d support multiple conflict clauses in upsert 2025-09-30 20:47:39 +04:00
Nikita Sivukhin
e5aa836ad5 add simple test 2025-09-30 17:57:25 +04:00
Jussi Saurio
594bdce999 Merge 'sum should identify if there is num in strings/prefix of strings' from Pavan Nambi
closes #3285
maybe adding seperate func for it is stupid but i kept running into
issues with not closing some random `}` and it got annoying real quick
so i just moved tht into its own func. - and as i am using same logic in
3 places i think it's ok.

Closes #3412
2025-09-30 10:37:17 +03:00
Jussi Saurio
e6a2e2a9cf Merge 'Remove double-quoted identifier assert' from Diego Reis
Closes #3301
Not every identifier should be double-quoted

Closes #3440
2025-09-30 10:34:49 +03:00
Jussi Saurio
568b0eeff3 Merge 'substr scalar should also work with non-text values' from Diego Reis
Closes #3306
Not only blobs, but numbers are also cast to text

Closes #3439
2025-09-30 10:33:40 +03:00
Jussi Saurio
67be0478e4 Add TCL regression test for DROP COLUMN issue #3448 2025-09-30 10:04:31 +03:00
Pekka Enberg
2b59863447 Merge 'core/printf: Compatibility tests and fixes for printf()' from Luiz Gustavo
Addition of compatibilty tests for `printf()`.
While doing this I found some differences in the current implementation,
so this fixes those too.

Closes #3438
2025-09-30 07:44:35 +03:00
luizgfc
f1811794b9 core/testing: Basic sqlite compatibility tests for printf() 2025-09-30 01:02:12 -03:00
Diego Reis
8e60d64518 rename limbo -> turso 2025-09-29 22:33:39 -03:00
Diego Reis
90f4d69774 fix(3301): Remove identifier assert assumption
Not every identifier should be double-quoted
2025-09-29 22:33:21 -03:00
Diego Reis
c9421e034d fix(3306): substr scalar should also work with non-text values 2025-09-29 21:42:21 -03:00
Mikaël Francoeur
dc231abb2e fix self-insert bug 2025-09-29 17:18:19 -04:00
Glauber Costa
2fde976605 Fix materialized views with complex expressions
SQLite supports complex expressions in group by columns - because of
course it does...

So we need to make sure that a column is created for this expression if
it doesn't exist already, and compute it, the same way we compute
pre-projections in the filter operator.

Fixes #3363
Fixes #3366
Fixes #3365
2025-09-29 11:56:21 -05:00
Preston Thorpe
cdab174350 Merge 'Fix column fetch in joins' from Glauber Costa
In comparisons for joins, we were assuming that the left column belonged
to the left join (and vice-versa). That is incorrect, because you can
write the comparison condition in any order.
Fixes #3368

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

Closes #3400
2025-09-29 12:34:45 -04:00
Preston Thorpe
bbbcbf894e Merge 'translate/upsert: fix explicit conflict target of non-rowid primary key in UPSERT' from Preston Thorpe
closes #3384

Closes #3386
2025-09-29 11:09:29 -04:00
Nikita Sivukhin
a142c59de4 use explicit null if it set instead of column default value 2025-09-29 16:28:09 +04:00
Pavan-Nambi
2335578c94 printf truncates floats 2025-09-28 21:16:33 +05:30
Pavan-Nambi
074a363c30 sum should identify if there is num in strings/prefix of strings 2025-09-28 17:23:55 +05:30
PThorpe92
ace2ac632a Remove semicolon from test 2025-09-27 13:59:51 -04:00
PThorpe92
6e3c30623c Fix regression test to not use dot command 2025-09-27 13:17:50 -04:00
PThorpe92
bd17c5d5df Add regression test for alter table with notnull constraint 2025-09-27 13:15:48 -04:00
Glauber Costa
78ee8b8627 Fix column fetch in joins
In comparisons for joins, we were assuming that the left column belonged
to the left join (and vice-versa). That is incorrect, because you can
write the comparison condition in any order.

Fixes #3368
2025-09-27 12:08:47 -03:00
Pekka Enberg
9eb6f4b51e Merge 'Sqlean fuzzy string ' from Danawan Bimantoro
Add implementations of string distance and phonetics functions:
fuzzy_damlev
fuzzy_hamming
fuzzy_jarowin
fuzzy_leven
fuzzy_osadist
fuzzy_editdist
fuzzy_soundex
fuzzy_rsoundex
fuzzy_phonetic
fuzzy_caver
fuzzy_translit
This implementation follows sqlean-fuzzy

Reviewed-by: Preston Thorpe <preston@turso.tech>

Closes #3262
2025-09-27 16:51:49 +03:00
Pekka Enberg
d7a0a3db56 Merge 'core/translate: allow creating column called 'rowid'' from Preston Thorpe
closes #3282
includes minor refactor, removing `column_is_rowid_alias`, which is only
checking the public field of the argument Column.

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

Closes #3385
2025-09-27 16:51:09 +03:00
Pekka Enberg
5ff0044961 Merge 'length shall not count when it sees nullc' from Pavan Nambi
fixes #3317

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

Closes #3356
2025-09-27 16:50:50 +03:00
PThorpe92
2e186ce8fa Add regression test for upsert explict non-rowid alias PK 2025-09-27 07:52:20 -04:00
Glauber Costa
3ee97ddf36 Make sure complex expressions in filters go through Project
We had code for this, but the code had a fatal flaw: it tried to detect
a complex operation (an operation that needs projection), and return
false (no need for projection), for the others.

This is the exact opposite of what we should do: we should identify the
*simple* operations, and then return true (needs projection) for the
rest.

CAST is a special beast, since it is not a function, but rather, a
special opcode. Everything else above is the true just the same. But for
CAST, we have to do the extra work to capture it in the logical plan and
pass it down.

Fixes #3372
Fixes #3370
Fixes #3369
2025-09-27 07:21:03 -03:00
Danawan Bimantoro
a58c6a3c0b Merge branch 'main' into main 2025-09-27 11:05:44 +07:00
PThorpe92
abab04dac9 Add regression test for col named rowid 2025-09-26 17:33:53 -04:00
Pavan-Nambi
fdabbed539 length shall not count when it sees nullc 2025-09-26 15:07:33 +05:30
danawan
468046c654 translit and script 2025-09-26 15:20:27 +07:00
Jussi Saurio
cfa449a0c0 Merge 'Disallow multiple primary keys in table definition' from Jussi Saurio
Closes #3309

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

Closes #3340
2025-09-26 09:16:14 +03:00
Jussi Saurio
064cc04b69 Merge 'Fix CREATE INDEX with quoted identifiers' from Iaroslav Zeigerman
Discovered this one while working on #3322
It was a bit more elusive because the original error was essentially a
red herring:
```
turso> CREATE INDEX idx ON "t t" (`a a`);
  × unexpected token at SourceSpan { offset: SourceOffset(22), length: 1 }
   ╭────
 1 │ CREATE INDEX idx ON "t t" (`a a`);
   ·                       ┬
   ·                       ╰── here
   ╰────
  help: expected [TK_LP] but found TK_ID
```

Reviewed-by: Preston Thorpe <preston@turso.tech>

Closes #3345
2025-09-26 09:13:30 +03:00
Jussi Saurio
c83ee9fc3e Merge 'Fix ungrouped aggregate with offset clause' from Preston Thorpe
closes #3300

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

Closes #3347
2025-09-26 09:13:16 +03:00
Jussi Saurio
9549ca5d51 Merge 'translate/update: allow for updating nonalias'd rowid column explicitly ' from Preston Thorpe
closes #3276

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

Closes #3349
2025-09-26 09:13:03 +03:00
Jussi Saurio
6d6fc91da3 Disallow multiple primary keys in table definition 2025-09-26 08:59:36 +03:00