Commit graph

542 commits

Author SHA1 Message Date
Jussi Saurio
84244cf5f8 sim: fix stale name in TxOperation::DropColumn
When processing AddColumn and DropColumn operations, the code looks up tables in transaction_tables.current_tables using the table name stored in the operation. However, transaction_tables.current_tables has tables with their final names (after all renames), while operations store the name at the time they were recorded.

  In the failing case:
  1. DropColumn was recorded with table_name = "stellar_katerina_672"
  2. RenameTable changed the name to "captivating_eco_1159"
  3. At commit, when processing DropColumn, we looked for "stellar_katerina_672" but the table was now named "captivating_eco_1159"

  The fix: Build a mapping from old names → final names by scanning all RenameTable operations first, then use the final name when looking up in transaction_tables.current_tables.
2025-12-20 09:52:58 +02:00
Jussi Saurio
87f9cb71c7 sim: fix apply_snapshot for create table and create index
have to leave for train soon, so claude summary:

Changes in runner/env.rs:
  1. Renamed RowOperation to TxOperation
  2. Fixed the CreateTable variant to store the full Table instead of separate fields
  3. Added CreateIndex and DropIndex variants
  4. Added corresponding record_* methods to both TransactionTables and ShadowTablesMut
  5. Updated apply_snapshot() to handle CreateTable, CreateIndex, and DropIndex operations in order
  6. Removed the index sync loop at the end of apply_snapshot() since operations are now tracked properly

  Changes in model/mod.rs:
  1. Updated Shadow for Create to call record_create_table() before applying the change
  2. Updated Shadow for CreateIndex to call record_create_index() before applying the change
  3. Updated Shadow for DropIndex to call record_drop_index() before applying the change

  The core fix is that CreateTable and CreateIndex operations are now recorded as they happen, so when apply_snapshot() replays operations in order, subsequent operations like AlterTable find the table already created in committed_tables.
2025-12-20 07:51:24 +02:00
pedrocarlo
1c737cfac5 refactor simulator to use new helpers 2025-12-19 17:20:46 -03:00
Pekka Enberg
edd45ff7b8 Improve MVCC DX by dropping --experimental-mvcc flag
The DX is right now pretty terrible:

```
penberg@vonneumann turso % cargo run -- hello.db
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.15s
     Running `target/debug/tursodb hello.db`
Turso v0.4.0-pre.18
Enter ".help" for usage hints.
Did you know that Turso supports live materialized views? Type .manual materialized-views to learn more.
This software is in BETA, use caution with production data and ensure you have backups.
turso> PRAGMA journal_mode = 'experimental_mvcc';
  × Invalid argument supplied: MVCC is not enabled. Enable it with `--experimental-mvcc` flag in the CLI or by setting the MVCC option in `DatabaseOpts`

turso>
```

To add insult to the injury, many SDKs don't even have a way to enable
MVCC via database options. Therefore, let's remove the flag altogether.
2025-12-19 12:59:42 +02:00
Jussi Saurio
9115b74751
Merge 'fix/sim: all alter table ops must be recorded and applied in order' from Jussi Saurio
## Background
In the simulator, we do our best to replicate the effects of an
interactive transaction into the simulator's shadow state whenever that
transaction commits.
## Problem
this didn't work:
BEGIN;
ALTER TABLE t ADD COLUMN foo;
DELETE FROM t WHERE bar != 5;
COMMIT;
None of the rows where bar != 5 were deleted because apply_snapshot()
was checking that the rows in the committed table were exactly equal to
the rows that were recorded, but since the recorded deletes contained a
NULL `foo` column, they never matched. This meant that the sim thought
it should still have all the rows that were deleted.
## Fix:
like all the other operations, record add column / drop column too so
that they are applied in sequential order in apply_snapshot()
No explicit test for this - I ran into this in another branch of mine
whose seed doesn't reproduce on main (because I changed the simulator in
that branch).

Reviewed-by: Pedro Muniz (@pedrocarlo)

Closes #4264
2025-12-18 09:28:28 +02:00
PThorpe92
a9842d1116
Add simulator run with io_uring io backend to github action 2025-12-17 17:22:41 -05:00
PThorpe92
378de85657
Add io_uring IoBackend to simulator 2025-12-17 16:41:24 -05:00
Jussi Saurio
d0f92856fb be stricter in apply_snapshot() 2025-12-17 22:32:58 +02:00
PThorpe92
db60db7d9b
impl cache spilling in pager 2025-12-17 11:57:34 -05:00
Jussi Saurio
da0ec21580 fix/sim: all alter table ops must be recorded and applied in order
this didn't work:

BEGIN;
ALTER TABLE t ADD COLUMN foo;
DELETE FROM t WHERE bar != 5;
COMMIT;

None of the rows where bar != 5 were deleted because apply_snapshot()
was checking that the rows in the committed table were exactly equal
to the rows that were recorded, but since the recorded deletes contained
a NULL `foo` column, they never matched. This meant that the sim thought
it should still have all the rows that were deleted.

Fix:

like all the other operations, record add column / drop column too so
that they are applied in sequential order in apply_snapshot()

No explicit test for this - I ran into this in another branch of mine
whose seed doesn't reproduce on main (because I changed the simulator
in that branch).
2025-12-17 16:27:36 +02:00
Jussi Saurio
4a57710640
fix/core: decouple autocheckpoint result from transaction durability
After flushing the WAL, the db may attempt an automatic checkpoint. Previously,
a checkpoint failure for any other reason than `Busy` rolled back the transaction;
this is incorrect because the WAL has already been written and synced, so the transaction
is actually committed and durable.

For this reason, do the following decoupling:

- Mark the transaction as committed after `SyncWal`
- Any errors beyond that point are wrapped as `LimboError::CheckpointFailed` which is
  handled specially:
    * Tx rollback is not attempted in `abort()` - only the WAL locks are cleaned up
      and checkpoint state machines are reset
    * In the simulator, the results of the query are shadowed into the sim environment
      so that the sim correctly assumes that the transaction's effects were in fact
      committed.
2025-12-16 10:42:48 -05:00
Jussi Saurio
26367a9580
derive debug for sim IO ops 2025-12-16 10:41:54 -05:00
Jussi Saurio
e9975378a5
sim: don't print stats table for ephemeral files 2025-12-16 10:41:48 -05:00
Jussi Saurio
712eb82382 fix/sim: modify existing rows in ALTER COLUMN properly
Bug 1:

apply_snapshot(), which handles committing transaction changes to the
simulator state, had this bug:

let's say a transaction does:
1. ALTER TABLE t ADD COLUMN (e.g., adding 9th column)
2. INSERT INTO t ... (populating all 9 columns)

then apply_snapshot() would:
1. First push the INSERT row (with 9 values) to committed_tables
2. Then detect new_col_count (9) > old_col_count (8) and add NULLs to ALL rows

hence, adding a 10th column to the new row too.

Fix 1:

only add nulls to existing rows that weren't inserted in the same tx after
the ADD COLUMN.

Bug 2:

the exact same thing, but for DROP COLUMN.

Fix 2:

only remove the i'th column from rows that existed prior to the DROP COLUMN
was issued.
2025-12-15 15:20:26 +02:00
Jussi Saurio
83d433bf8f sim: fix bug in apply_snapshot
When a new table was created within a transaction, we were incorrectly clearing the rows of the new table when committing.

This resulted in false positives where the sim thought there shouldn't be any
rows in the table.

Fix: don't do that.
2025-12-11 10:04:05 +02:00
Jussi Saurio
70eeae0d88 expect instead of if let 2025-12-10 08:52:55 +02:00
Jussi Saurio
b10c85f4cb Ensure that 1. insert rows 2. table rename 3. insert more rows is tracked correctly 2025-12-10 08:51:59 +02:00
Jussi Saurio
f8d291402a fix/sim: abandon the entire property if precondition fails
e.g. in "ReadYourUpdatesBack", we first do an UPDATE and then a
SELECT to verify that those updates were actually made.

Problem is the SELECT assertion was made even if the UPDATE failed.

Fix: change interaction handling so that if a precondition in a
property fails, the entire property is abandoned.
2025-12-09 16:06:14 +02:00
Jussi Saurio
7c3bfeed7c sim: fix applying transaction effects
the issue was that the sim was executing queries on
commit, instead of applying their effects. for example,
if transaction T1 did a `DELETE FROM t WHERE TRUE` it would
delete all the rows even if another mvcc transaction T2 had
inserted rows concurrently that should not be visible to
T1.
2025-12-09 13:03:53 +02:00
Jussi Saurio
eea3a8b9f8 sim: handle recoverable errors
WriteWriteConflict should rollback in memory tx but not fail sim.
TxError should not rollback tx but not fail sim either.

Neither of the above should cause sim to shadow the query.
2025-12-09 13:03:49 +02:00
Jussi Saurio
7b8acc7c04 sim: rollback all shadow transactions on REOPEN_DATABASE 2025-12-09 11:32:34 +02:00
Jussi Saurio
826ca4d44d chore: remove experimental_indexes feature flags 2025-12-08 13:00:37 +02:00
Jussi Saurio
b45578becc
Merge 'sim: add binary tool that converts plan.sql to rust test file' from Jussi Saurio
Takes something like:
```sql
CREATE TABLE persistent_budiati_0 (proficient_shifu_1 TEXT, magnificent_calladinejones_2 TEXT, relaxed_gonzalez_3 TEXT, amiable_suhuyini_4 REAL, friendly_infoshop_5 INTEGER, sleek_apocalypticism_6 REAL, gleaming_ocalan_7 BLOB, polite_nelson_8 BLOB, gorgeous_secretariat_9 TEXT, fortuitous_stapleton_10 BLOB); -- 0
BEGIN CONCURRENT; -- 1
BEGIN CONCURRENT; -- 0
COMMIT; -- 1
UPDATE persistent_budiati_0 SET relaxed_gonzalez_3 = 'sleek_column', sleek_apocalypticism_6 = 1384203229.4851246, amiable_suhuyini_4 = 9656243128.574707, proficient_shifu_1 = 'sleek_romanska', gorgeous_secretariat_9 = 'sincere_postillon', friendly_infoshop_5 = 5387193238366539038, gleaming_ocalan_7 = X'6B696E645F616C6578697362616B6572', fortuitous_stapleton_10 = X'62726176655F77616C6C616365', magnificent_calladinejones_2 = 'energetic_brankovich' WHERE (TRUE); -- 0
BEGIN CONCURRENT; -- 1
INSERT INTO persistent_budiati_0 VALUES ('favorable_demibold', 'warmhearted_stroud', 'plucky_x', 6964007180.209948, 6676621284135822576, -6298192003.47883, X'66756E6E795F64757267616E', X'676C65616D696E675F68656E647269636B73', 'diligent_gai', X'66756E6E795F636172746F677261706879'), ('devoted_courtney', 'competitive_cast', 'glowing_p', 7100262433.047049, 2475381022967570429, -7589464447.394688, X'70726F66696369656E745F7275636B7573', X'7370656C6C62696E64696E675F6D617274696E64616C65', 'glittering_klien', X'696E646570656E64656E745F6E6573736965'), ('generous_pannekoek', 'diplomatic_summer', 'educated_moai', 8820129780.595894, 3736576277869875810, -7059365485.414469, X'7068696C6F736F70686963616C5F63726577', X'626F756E746966756C5F6D63656C726F79', 'mirthful_ansart', X'726F6D616E7469635F7361746F7572'), ('glowing_stirning', 'vivacious_moore', 'friendly_mumm', 1084189058.2024403, 8659164316642650802, 7455040212.614258, X'636861726D696E675F6C6565736F6E', X'666C657869626C655F6775726E6F77', 'insightful_okeeffe', X'6D6972746866756C5F72616576736B79'), ('brave_lanark', 'hilarious_council', 'zestful_murphy', 843262820.8342457, -5203301182531706236, -414439452.86331177, X'696D6167696E61746976655F61636861727961', X'6B6E6F776C6564676561626C655F636173746F726961646973', 'optimistic_olday', X'696D6167696E61746976655F656765'), ('creative_offenhartz', 'sincere_ickibob', 'diligent_conspiracy', -6137268237.420029, -7609135034138257256, -7895069391.899394, X'656E6368616E74696E675F6C6561677565', X'68617264776F726B696E675F6265616473616761696E73746661736369736D', 'inquisitive_wilderness', X'676F7267656F75735F7765747A656C'); -- 0
DELETE FROM persistent_budiati_0 WHERE (0); -- 0
INSERT INTO persistent_budiati_0 VALUES ('capable_ramus', 'vivid_romanos', 'courageous_swann', -8348839044.12441, -3153793306041765852, 1497972203.2522106, X'676F7267656F75735F73747261756D65', X'676F7267656F75735F646973636F72646961', 'sleek_velli', X'61646570745F6D6172696E'), ('proficient_strasbourg', 'perfect_zileli', 'powerful_bellegarrigue', 3656370453.798256, 488521277608345023, 9272977102.174099, X'6D6F76696E675F646F626273', X'616D6961626C655F7671', 'bountiful_nippon', X'7265736F7572636566756C5F61676E69'); -- 0
COMMIT; -- 1
DELETE FROM persistent_budiati_0 WHERE (persistent_budiati_0.sleek_apocalypticism_6 > 2122130920.1633062); -- 0
BEGIN CONCURRENT; -- 1
COMMIT; -- 1
COMMIT; -- 0
ALTER TABLE persistent_budiati_0 RENAME TO humorous_chien_11; -- 0
BEGIN CONCURRENT; -- 1
BEGIN CONCURRENT; -- 0
COMMIT; -- 0
COMMIT; -- 1
BEGIN CONCURRENT; -- 1
COMMIT; -- 1
ALTER TABLE humorous_chien_11 RENAME COLUMN gleaming_ocalan_7 TO diplomatic_mendelgleeson_12; -- 1
BEGIN CONCURRENT; -- 1
INSERT INTO humorous_chien_11 VALUES ('capable_nevada', 'brave_fc', 'stupendous_leila', 1841016158.456213, 382581885747084851, 241956515.74888992, X'6F75747374616E64696E675F616E68696C61616C', X'70617373696F6E6174655F72616661656C', 'competitive_aversion', X'70726F706974696F75735F7679736F74736B79'), ('glimmering_kerr', 'ambitious_marsden', 'sincere_garine', 4621457902.119736, -7728284413371611806, -5001194349.263405, X'6C696B61626C655F636C61726B65', X'676F7267656F75735F676F776479', 'bountiful_majaras', X'63726561746976655F737068696E78'), ('unique_poets', 'polite_gori', 'imaginative_ocalan', 6720955495.1690235, 5051068995752523160, 2163769134.7309666, X'706F77657266756C5F7374616C696E', X'6C6F76696E675F6162', 'incredible_alakran', X'72656D61726B61626C655F62726F67616E'), ('breathtaking_lucca', 'persistent_rebelaze', 'ambitious_durgan', -1675368104.83671, 8903219744372423748, 6327505289.906071, X'676C697374656E696E675F676172736F6E', X'6B6E6F776C6564676561626C655F63616765', 'glittering_tierra', X'6C696B61626C655F6F6E66726179'), ('friendly_riesel', 'splendid_waas', 'philosophical_hare', 7521721975.525509, -4077583965067530416, 8568449025.795597, X'7A65737466756C5F7075626C697368696E67', X'68696C6172696F75735F64657074', 'wondrous_anarchofeminists', X'636F6E73696465726174655F62616D796568'); -- 1
UPDATE humorous_chien_11 SET relaxed_gonzalez_3 = 'outstanding_lupalupa', fortuitous_stapleton_10 = X'676C6974746572696E675F67656C61626572746F', sleek_apocalypticism_6 = 4749515806.792229, gorgeous_secretariat_9 = 'faithful_marechal', magnificent_calladinejones_2 = 'gleaming_woodwork', amiable_suhuyini_4 = 302359235.4986744, polite_nelson_8 = X'696D6167696E61746976655F736368776172747A' WHERE (humorous_chien_11.amiable_suhuyini_4 < 9508571248.762548 AND NOT 'philosophical_hare' AND + 7521721975.525509); -- 1
BEGIN CONCURRENT; -- 0
INSERT INTO humorous_chien_11 VALUES ('unique_anarchists', 'generous_action', 'passionate_books', 7230399065.725552, -6224798804581125214, -7465265323.767456, X'7068696C6F736F70686963616C5F647261676F6E6F776C', X'746563686E6F6C6F676963616C5F667261736572', 'mirthful_cd', X'7175616C69666965645F636F6E747265706F696E7473'), ('charming_buck', 'knowledgeable_pannekoek', 'gorgeous_follmann', -8155760089.594284, -6882263070642873795, 7925299744.793644, X'616C6C7572696E675F646566656E7365', X'6B696E645F616D6265727261656B656C6C79', 'twinkling_fidel', X'706F6C6974655F62727562616B6572'), ('sleek_sail', 'passionate_shaffer', 'confident_moen', -4950429037.66798, 67877469559160520, -7911354264.616009, X'726573706F6E7369626C655F776F6E67', X'677265676172696F75735F6F636172726F6C6C', 'glimmering_eco', X'7A65737466756C5F686F66666D616E'); -- 0
INSERT INTO humorous_chien_11 VALUES ('diplomatic_olympics', 'upbeat_cast', 'confident_bregman', -694836719.9655838, -7590350502083497714, -4833340319.208008, X'726F7573696E675F636F7272', X'6F75747374616E64696E675F6869617474', 'independent_hatzimichelakis', X'7368696D6D6572696E675F706178746F6E'), ('determined_fiscella', 'perfect_toronto', 'philosophical_nacional', 6766485377.716101, -1864833171741648409, 4673986463.289207, X'7370656C6C62696E64696E675F6869617474', X'73696E636572655F6E656C736F6E', 'mirthful_nosakhere', X'626F756E746966756C5F6265636F6D696E6773'), ('gleaming_city', 'dazzling_oak', 'dazzling_mazer', -7297230853.519529, 4678152103342429971, 5169450552.174406, X'676C697374656E696E675F626C61636B', X'76696272616E745F7368616E6E6F6E', 'agreeable_peasants', X'70617469656E745F6967617269776579'); -- 1
DELETE FROM humorous_chien_11 WHERE (humorous_chien_11.relaxed_gonzalez_3 < 'zestful_murphx'); -- 0
-- begin testing 'TableHasExpectedContent'
    -- ASSUME table humorous_chien_11 exists; -- 0
    SELECT * FROM humorous_chien_11 WHERE TRUE; -- 0
    -- ASSERT table humorous_chien_11 should have the expected content;; -- 0
-- end testing 'TableHasExpectedContent'
```
and produces:
```rust
use std::sync::Arc;

use turso_core::Connection;

use crate::common::TempDatabase;

#[turso_macros::test]
fn test_bugbase_13956202564301292478(tmp_db: TempDatabase) {
    let mut connections: Vec<Arc<Connection>> = Vec::new();
    for _ in 0..2 {
        connections.push(tmp_db.connect_limbo());
    }

    // Connection 0
    let _ = connections[0].execute("CREATE TABLE persistent_budiati_0 (proficient_shifu_1 TEXT, magnificent_calladinejones_2 TEXT, relaxed_gonzalez_3 TEXT, amiable_suhuyini_4 REAL, friendly_infoshop_5 INTEGER, sleek_apocalypticism_6 REAL, gleaming_ocalan_7 BLOB, polite_nelson_8 BLOB, gorgeous_secretariat_9 TEXT, fortuitous_stapleton_10 BLOB);");

    // Connection 1
    let _ = connections[1].execute("BEGIN CONCURRENT;");

    // Connection 0
    let _ = connections[0].execute("BEGIN CONCURRENT;");

    // Connection 1
    let _ = connections[1].execute("COMMIT;");

    // Connection 0
    let _ = connections[0].execute("UPDATE persistent_budiati_0 SET relaxed_gonzalez_3 = 'sleek_column', sleek_apocalypticism_6 = 1384203229.4851246, amiable_suhuyini_4 = 9656243128.574707, proficient_shifu_1 = 'sleek_romanska', gorgeous_secretariat_9 = 'sincere_postillon', friendly_infoshop_5 = 5387193238366539038, gleaming_ocalan_7 = X'6B696E645F616C6578697362616B6572', fortuitous_stapleton_10 = X'62726176655F77616C6C616365', magnificent_calladinejones_2 = 'energetic_brankovich' WHERE (TRUE);");

    // Connection 1
    let _ = connections[1].execute("BEGIN CONCURRENT;");

    // Connection 0
    let _ = connections[0].execute("INSERT INTO persistent_budiati_0 VALUES ('favorable_demibold', 'warmhearted_stroud', 'plucky_x', 6964007180.209948, 6676621284135822576, -6298192003.47883, X'66756E6E795F64757267616E', X'676C65616D696E675F68656E647269636B73', 'diligent_gai', X'66756E6E795F636172746F677261706879'), ('devoted_courtney', 'competitive_cast', 'glowing_p', 7100262433.047049, 2475381022967570429, -7589464447.394688, X'70726F66696369656E745F7275636B7573', X'7370656C6C62696E64696E675F6D617274696E64616C65', 'glittering_klien', X'696E646570656E64656E745F6E6573736965'), ('generous_pannekoek', 'diplomatic_summer', 'educated_moai', 8820129780.595894, 3736576277869875810, -7059365485.414469, X'7068696C6F736F70686963616C5F63726577', X'626F756E746966756C5F6D63656C726F79', 'mirthful_ansart', X'726F6D616E7469635F7361746F7572'), ('glowing_stirning', 'vivacious_moore', 'friendly_mumm', 1084189058.2024403, 8659164316642650802, 7455040212.614258, X'636861726D696E675F6C6565736F6E', X'666C657869626C655F6775726E6F77', 'insightful_okeeffe', X'6D6972746866756C5F72616576736B79'), ('brave_lanark', 'hilarious_council', 'zestful_murphy', 843262820.8342457, -5203301182531706236, -414439452.86331177, X'696D6167696E61746976655F61636861727961', X'6B6E6F776C6564676561626C655F636173746F726961646973', 'optimistic_olday', X'696D6167696E61746976655F656765'), ('creative_offenhartz', 'sincere_ickibob', 'diligent_conspiracy', -6137268237.420029, -7609135034138257256, -7895069391.899394, X'656E6368616E74696E675F6C6561677565', X'68617264776F726B696E675F6265616473616761696E73746661736369736D', 'inquisitive_wilderness', X'676F7267656F75735F7765747A656C');");

    // Connection 0
    let _ = connections[0].execute("DELETE FROM persistent_budiati_0 WHERE (0);");

    // Connection 0
    let _ = connections[0].execute("INSERT INTO persistent_budiati_0 VALUES ('capable_ramus', 'vivid_romanos', 'courageous_swann', -8348839044.12441, -3153793306041765852, 1497972203.2522106, X'676F7267656F75735F73747261756D65', X'676F7267656F75735F646973636F72646961', 'sleek_velli', X'61646570745F6D6172696E'), ('proficient_strasbourg', 'perfect_zileli', 'powerful_bellegarrigue', 3656370453.798256, 488521277608345023, 9272977102.174099, X'6D6F76696E675F646F626273', X'616D6961626C655F7671', 'bountiful_nippon', X'7265736F7572636566756C5F61676E69');");

    // Connection 1
    let _ = connections[1].execute("COMMIT;");

    // Connection 0
    let _ = connections[0].execute("DELETE FROM persistent_budiati_0 WHERE (persistent_budiati_0.sleek_apocalypticism_6 > 2122130920.1633062);");

    // Connection 1
    let _ = connections[1].execute("BEGIN CONCURRENT;");

    // Connection 1
    let _ = connections[1].execute("COMMIT;");

    // Connection 0
    let _ = connections[0].execute("COMMIT;");

    // Connection 0
    let _ = connections[0].execute("ALTER TABLE persistent_budiati_0 RENAME TO humorous_chien_11;");

    // Connection 1
    let _ = connections[1].execute("BEGIN CONCURRENT;");

    // Connection 0
    let _ = connections[0].execute("BEGIN CONCURRENT;");

    // Connection 0
    let _ = connections[0].execute("COMMIT;");

    // Connection 1
    let _ = connections[1].execute("COMMIT;");

    // Connection 1
    let _ = connections[1].execute("BEGIN CONCURRENT;");

    // Connection 1
    let _ = connections[1].execute("COMMIT;");

    // Connection 1
    let _ = connections[1].execute("ALTER TABLE humorous_chien_11 RENAME COLUMN gleaming_ocalan_7 TO diplomatic_mendelgleeson_12;");

    // Connection 1
    let _ = connections[1].execute("BEGIN CONCURRENT;");

    // Connection 1
    let _ = connections[1].execute("INSERT INTO humorous_chien_11 VALUES ('capable_nevada', 'brave_fc', 'stupendous_leila', 1841016158.456213, 382581885747084851, 241956515.74888992, X'6F75747374616E64696E675F616E68696C61616C', X'70617373696F6E6174655F72616661656C', 'competitive_aversion', X'70726F706974696F75735F7679736F74736B79'), ('glimmering_kerr', 'ambitious_marsden', 'sincere_garine', 4621457902.119736, -7728284413371611806, -5001194349.263405, X'6C696B61626C655F636C61726B65', X'676F7267656F75735F676F776479', 'bountiful_majaras', X'63726561746976655F737068696E78'), ('unique_poets', 'polite_gori', 'imaginative_ocalan', 6720955495.1690235, 5051068995752523160, 2163769134.7309666, X'706F77657266756C5F7374616C696E', X'6C6F76696E675F6162', 'incredible_alakran', X'72656D61726B61626C655F62726F67616E'), ('breathtaking_lucca', 'persistent_rebelaze', 'ambitious_durgan', -1675368104.83671, 8903219744372423748, 6327505289.906071, X'676C697374656E696E675F676172736F6E', X'6B6E6F776C6564676561626C655F63616765', 'glittering_tierra', X'6C696B61626C655F6F6E66726179'), ('friendly_riesel', 'splendid_waas', 'philosophical_hare', 7521721975.525509, -4077583965067530416, 8568449025.795597, X'7A65737466756C5F7075626C697368696E67', X'68696C6172696F75735F64657074', 'wondrous_anarchofeminists', X'636F6E73696465726174655F62616D796568');");

    // Connection 1
    let _ = connections[1].execute("UPDATE humorous_chien_11 SET relaxed_gonzalez_3 = 'outstanding_lupalupa', fortuitous_stapleton_10 = X'676C6974746572696E675F67656C61626572746F', sleek_apocalypticism_6 = 4749515806.792229, gorgeous_secretariat_9 = 'faithful_marechal', magnificent_calladinejones_2 = 'gleaming_woodwork', amiable_suhuyini_4 = 302359235.4986744, polite_nelson_8 = X'696D6167696E61746976655F736368776172747A' WHERE (humorous_chien_11.amiable_suhuyini_4 < 9508571248.762548 AND NOT 'philosophical_hare' AND + 7521721975.525509);");

    // Connection 0
    let _ = connections[0].execute("BEGIN CONCURRENT;");

    // Connection 0
    let _ = connections[0].execute("INSERT INTO humorous_chien_11 VALUES ('unique_anarchists', 'generous_action', 'passionate_books', 7230399065.725552, -6224798804581125214, -7465265323.767456, X'7068696C6F736F70686963616C5F647261676F6E6F776C', X'746563686E6F6C6F676963616C5F667261736572', 'mirthful_cd', X'7175616C69666965645F636F6E747265706F696E7473'), ('charming_buck', 'knowledgeable_pannekoek', 'gorgeous_follmann', -8155760089.594284, -6882263070642873795, 7925299744.793644, X'616C6C7572696E675F646566656E7365', X'6B696E645F616D6265727261656B656C6C79', 'twinkling_fidel', X'706F6C6974655F62727562616B6572'), ('sleek_sail', 'passionate_shaffer', 'confident_moen', -4950429037.66798, 67877469559160520, -7911354264.616009, X'726573706F6E7369626C655F776F6E67', X'677265676172696F75735F6F636172726F6C6C', 'glimmering_eco', X'7A65737466756C5F686F66666D616E');");

    // Connection 1
    let _ = connections[1].execute("INSERT INTO humorous_chien_11 VALUES ('diplomatic_olympics', 'upbeat_cast', 'confident_bregman', -694836719.9655838, -7590350502083497714, -4833340319.208008, X'726F7573696E675F636F7272', X'6F75747374616E64696E675F6869617474', 'independent_hatzimichelakis', X'7368696D6D6572696E675F706178746F6E'), ('determined_fiscella', 'perfect_toronto', 'philosophical_nacional', 6766485377.716101, -1864833171741648409, 4673986463.289207, X'7370656C6C62696E64696E675F6869617474', X'73696E636572655F6E656C736F6E', 'mirthful_nosakhere', X'626F756E746966756C5F6265636F6D696E6773'), ('gleaming_city', 'dazzling_oak', 'dazzling_mazer', -7297230853.519529, 4678152103342429971, 5169450552.174406, X'676C697374656E696E675F626C61636B', X'76696272616E745F7368616E6E6F6E', 'agreeable_peasants', X'70617469656E745F6967617269776579');");

    // Connection 0
    let _ = connections[0].execute("DELETE FROM humorous_chien_11 WHERE (humorous_chien_11.relaxed_gonzalez_3 < 'zestful_murphx');");

    // Connection 0
    let _ = connections[0].execute("SELECT * FROM humorous_chien_11 WHERE TRUE;");

}
```
prompt to opus 4.5:
Create a parser that generates a Rust integration test a lá
test_transactions.rs from files like
.bugbase/17016242926153013649/plan.sql
the "-- <integer>" means connection number, so as many connections
should be created as there are distinct suffixes like that at the end of
a line. lines BEGINNING with --
 eg "-- begin testing 'ReadYourUpdatesBack'" can be ignored.
the end result should be that the parser tool prints out a valid rust
file containing the necessary imports and a test function containing the
statements (modeled after test_transactions.rs tests).
this should be a lightweight script or CLI tool in the simulator
directory where you can give it a sql path and it will produce that
test.

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

Closes #4112
2025-12-08 06:20:39 +02:00
Jussi Saurio
299ccdaee4
Merge 'sim: stop ignoring sql execution errors' from Jussi Saurio
Some checks are pending
Build & publish @tursodatabase/database / db-bindings-x86_64-pc-windows-msvc - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / db-bindings-x86_64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-aarch64-apple-darwin - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-aarch64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-wasm32-wasip1-threads - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-x86_64-pc-windows-msvc - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / Test DB bindings on browser@20 (push) Blocked by required conditions
Build & publish @tursodatabase/database / sync-bindings-x86_64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / Test DB bindings on Linux-x64-gnu - node@20 (push) Blocked by required conditions
Build & publish @tursodatabase/database / Publish (push) Blocked by required conditions
Python / configure-strategy (push) Waiting to run
Python / test (push) Blocked by required conditions
Python / lint (push) Waiting to run
Python / linux (x86_64) (push) Waiting to run
Python / macos-arm64 (aarch64) (push) Waiting to run
Python / sdist (push) Waiting to run
Python / Release (push) Blocked by required conditions
Rust / cargo-fmt-check (push) Waiting to run
Rust / test-sqlite (push) Waiting to run
Rust / build-native (blacksmith-4vcpu-ubuntu-2404) (push) Waiting to run
Rust / build-native (macos-latest) (push) Waiting to run
Rust / build-native (windows-latest) (push) Waiting to run
Rust / clippy (push) Waiting to run
Rust Benchmarks+Nyrkiö / clickbench (push) Waiting to run
Rust / simulator (push) Waiting to run
Rust / test-limbo (push) Waiting to run
Rust Benchmarks+Nyrkiö / bench (push) Waiting to run
Rust Benchmarks+Nyrkiö / tpc-h-criterion (push) Waiting to run
Rust Benchmarks+Nyrkiö / tpc-h (push) Waiting to run
Rust Benchmarks+Nyrkiö / vfs-bench-compile (push) Waiting to run
Reviewed-by: Pedro Muniz (@pedrocarlo)

Closes #4106
2025-12-05 23:04:20 +02:00
Jussi Saurio
f58a839293 sim: add binary tool that converts plan.sql to rust test file
prompt to opus 4.5:

Create a parser that generates a Rust integration test a lá test_transactions.rs
from files like .bugbase/17016242926153013649/plan.sql

the "-- <integer>" means connection number, so as many connections should be created
as there are distinct suffixes like that at the end of a line. lines BEGINNING with --
 eg "-- begin testing 'ReadYourUpdatesBack'" can be ignored.

the end result should be that the parser tool prints out a valid rust file containing
the necessary imports and a test function containing the statements (modeled after
test_transactions.rs tests).

this should be a lightweight script or CLI tool in the simulator directory where you
can give it a sql path and it will produce that test.
2025-12-05 22:40:41 +02:00
Preston Thorpe
231282a5be
Merge 'Simulator Roadmap' from Alperen Keleş
This PR is a working doc on a roadmap for the simulator. @pedrocarlo
@LeMikaelF please take a look.

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

Closes #3954
2025-12-05 13:27:57 -05:00
Jussi Saurio
77ad9d87c5 sim: stop ignoring sql execution errors 2025-12-05 13:14:39 +02:00
pedrocarlo
085c108f0d Simulator: after freestanding DML statement, check the table's content 2025-12-03 10:48:46 -03:00
alpaylan
e66405303c add detailed properties, long term simulation and data collection 2025-11-24 12:19:30 -05:00
pedrocarlo
03f38ae72c simulator: only check all tables if we have any tables to check 2025-11-21 01:10:55 -03:00
pedrocarlo
c2be60b007 add pragma to shrinking 2025-11-17 11:45:02 -03:00
pedrocarlo
f09b73c768 remove Span, as interaction ID is enough to determine membership of a property 2025-11-17 11:45:02 -03:00
pedrocarlo
2aab33b714 find_interactions_range only check for interaction id to determine membership 2025-11-17 11:45:02 -03:00
pedrocarlo
4fd0896538 remove extension queries from other types of properties 2025-11-17 11:45:02 -03:00
pedrocarlo
9d439556ca if table changed names, add its previous names to depending tables when shrinking 2025-11-17 11:45:02 -03:00
pedrocarlo
af31e74d9f add depending tables to assertions to delete them if needed in shrinking 2025-11-17 11:45:02 -03:00
pedrocarlo
087d5f59a1 fix execution ticks not ticking enough 2025-11-17 11:45:02 -03:00
pedrocarlo
836d115853 create interaction plan correct in main.rs 2025-11-17 11:45:02 -03:00
pedrocarlo
2c8754985b refactor shrinking to use utilities in the InteractionPlan to iterate over properties, instead of handrolling property iteration 2025-11-17 11:45:02 -03:00
pedrocarlo
a21f7675dd - update interaction stats on demand instead of reading the entire plan
to calculate metrics per generation step 
- simplify generation as we now only store `Interaction`. So now we can 
  funnel most of the logic for interaction generation, metric update,
  and Interaction append in the `PlanGenerator::next`.
2025-11-17 11:45:02 -03:00
pedrocarlo
157a5cf10a - add Interaction Builder to simplify code for building an interaction.
Modify `generation/property.rs` to use the Builder
- add additional metadata to `Interaction` to give more context for
  shrinking and iterating over interactions that originated from the
  same interaction.
- add Iterator like utilities for `InteractionPlan` to facilitate
  iterating over interactions that came from the same property:
2025-11-17 11:45:02 -03:00
pedrocarlo
c088a653e6 move interaction stats to metrics 2025-11-17 11:45:02 -03:00
pedrocarlo
2fe39d40bb add Span and PropertyMetadata structs 2025-11-17 11:45:02 -03:00
pedrocarlo
a4f0f2364d disable Watch Mode until we can properly serialize interaction plan 2025-11-17 11:45:02 -03:00
pedrocarlo
4f143f385a - modify bugbase to not save interaction plan in a plan.json. As we
will track `Interaction` instead of `Interactions` in the Plan, this
  change will impossibilitate the serialization of the InteractionPlan with Serde Json. 
- make --load just load the previous cli args
2025-11-17 11:45:02 -03:00
pedrocarlo
8f50154db2 separate struct defining code from struct generation code. Also move Remaining to a metrics file 2025-11-17 11:44:20 -03:00
alpaylan
f47293c6b0 detail correctness and properties 2025-11-14 18:09:03 -05:00
Mikaël Francoeur
d309e6ddb3
generate self-inserts with nested subqueries 2025-11-14 09:16:17 -05:00
Mikaël Francoeur
23d6080531
make FromClause recursive 2025-11-14 09:16:17 -05:00
Mikaël Francoeur
8ea038c00b
fix join 2025-11-14 09:16:17 -05:00