Skip to content

Add schema-object staging scenarios to the dolt_add oracle#1657

Merged
timsehn merged 1 commit into
masterfrom
test/add-oracle-schema-objects
Jul 16, 2026
Merged

Add schema-object staging scenarios to the dolt_add oracle#1657
timsehn merged 1 commit into
masterfrom
test/add-oracle-schema-objects

Conversation

@timsehn

@timsehn timsehn commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

The dolt_add oracle (516 lines) had zero schema-object coverage: every scenario exercised plain table rows. These seven scenarios verify staging semantics against real Dolt for the two schema-object surfaces:

Views and triggers (behavior established by #1652, visible in status per #1653):

  • view_unstaged_after_named_add — a new view stays unstaged when only a named table is added
  • view_staged_by_all — views and triggers stage via dolt_add('-A')
  • view_dropped_then_all — a staged view drop matches Dolt

Index changes (attributed to their parent table per #1654):

  • index_change_unstaged_after_named_add_other — an index on table A stays unstaged when only table B is added by name
  • index_staged_with_named_table — a named add of the indexed table carries its index change
  • index_staged_by_all — index changes stage via -A
  • index_staged_then_more_data — staged index followed by new working-tree rows splits staged/unstaged correctly

The scenarios were split-validated before those PRs merged — the 3 view/trigger scenarios against master post-#1653, the 4 index scenarios against #1654's branch — and now pass unified on current master: 34 passed, 0 failed (27 pre-existing + 7 new).

🤖 Generated with Claude Code

The add oracle had no coverage of schema objects. Seven scenarios now
lock the staging semantics against real Dolt: views and triggers stay
unstaged through named adds and stage via -A (including a staged view
drop), and index changes surface through their parent table across
named adds of the indexed table, named adds of unrelated tables,
add -A, and staged-then-modified states.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Version-Control Performance Ceilings

Runs: median of 3 executions per benchmark, excluding fixture setup. The
working-set fixtures use 800 committed tables with 125 rows each
(100000 rows total); data-dirty cases update 1 row in 40
tables, and schema-dirty cases update 1 row plus add a column in 20 tables.
Branch tests use 300 branches, checkout uses a clean 400-table
branch switch over 100000 rows, and merge
tests use 100000-row tables with 2000 changed or conflicting
rows per side.

Benchmark Median ms Ceiling ms Result
status_clean_many_tables 82 200 PASS
status_dirty_many_tables 86 200 PASS
diff_regular_working_one_table 77 150 PASS
diff_regular_working_many_tables 91 200 PASS
diff_stat_working_many_tables 91 200 PASS
diff_schema_working_many_tables 92 200 PASS
branch_list_many_branches 23 100 PASS
branch_create_delete 25 100 PASS
checkout_branch_clean 57 200 PASS
merge_data_no_conflicts 29 150 PASS
merge_schema_no_conflicts 22 100 PASS
merge_data_conflicts 127 250 PASS
merge_data_conflicts_with_resolve 127 250 PASS

@github-actions

Copy link
Copy Markdown

Sysbench-Style Benchmark (BLOB PK): Doltlite vs SQLite

Companion to the classic Sysbench-Style Benchmark. Every workload here
runs against tables with a 16-byte big-endian BLOB PRIMARY KEY.

Individual ratios gated at 2.5×; section averages gated at 2×. Autocommit writes use 6× / 5×.

In-Memory

Reads

Test SQLite (us) Doltlite (us) Multiplier
oltp_point_select 30,627 37,676 1.23
oltp_range_select 13,137 14,420 1.10
oltp_sum_range 12,041 14,219 1.18
oltp_order_range 2,867 3,116 1.09
oltp_distinct_range 3,909 4,179 1.07
oltp_index_scan 4,631 6,379 1.38
select_random_points 18,172 20,818 1.15
select_random_ranges 4,101 5,298 1.29
covering_index_scan 4,359 4,646 1.07
groupby_scan 31,492 33,522 1.06
index_join 6,716 9,450 1.41
index_join_scan 4,436 5,512 1.24
types_table_scan 1,070,077 1,284,472 1.20
table_scan 1,258,180 1,415,499 1.13
oltp_read_only 121,275 137,050 1.13
Average 1.18

Writes

Test SQLite (us) Doltlite (us) Multiplier
oltp_bulk_insert 242,982 350,194 1.44
oltp_insert 20,182 39,056 1.94
oltp_update_index 68,589 130,116 1.90
oltp_update_non_index 49,317 84,046 1.70
oltp_delete_insert 48,923 102,135 2.09
oltp_write_only 27,739 61,009 2.20
types_delete_insert 32,389 53,559 1.65
oltp_read_write 87,337 138,971 1.59
Average 1.81

File-Backed

Reads

Test SQLite (us) Doltlite (us) Multiplier
oltp_point_select 99,988 61,860 0.62
oltp_range_select 20,836 16,824 0.81
oltp_sum_range 19,478 16,832 0.86
oltp_order_range 3,734 3,497 0.94
oltp_distinct_range 4,878 4,531 0.93
oltp_index_scan 12,100 9,007 0.74
select_random_points 26,720 24,083 0.90
select_random_ranges 11,138 7,749 0.70
covering_index_scan 12,442 7,282 0.59
groupby_scan 32,744 33,887 1.03
index_join 11,229 11,150 0.99
index_join_scan 5,340 5,920 1.11
types_table_scan 1,058,989 1,299,964 1.23
table_scan 1,271,390 1,417,145 1.11
oltp_read_only 223,979 172,082 0.77
Average 0.89

Writes

Test SQLite (us) Doltlite (us) Multiplier
oltp_bulk_insert 257,402 378,410 1.47
oltp_insert 37,589 51,363 1.37
oltp_update_index 104,787 161,047 1.54
oltp_update_non_index 85,572 107,722 1.26
oltp_delete_insert 85,677 128,577 1.50
oltp_write_only 61,202 83,374 1.36
types_delete_insert 53,167 71,049 1.34
oltp_read_write 123,362 161,072 1.31
Average 1.39

File-Backed (autocommit)

Each statement runs as its own transaction — exposes per-commit
fixed costs that the wrapped-in-BEGIN/COMMIT tests amortize away.
SQLite uses WAL mode with synchronous=FULL in this section so
the comparison uses SQLite's durable WAL autocommit path.

Reads

Reads have no commit cost; these are the same SQL files as the
File-Backed Reads section, included here for symmetry and to
catch any per-statement overhead doltlite pays on the read path.

Test SQLite (us) Doltlite (us) Multiplier
oltp_point_select 55,373 61,308 1.11
oltp_range_select 16,035 16,853 1.05
oltp_sum_range 14,681 16,893 1.15
oltp_order_range 3,299 3,571 1.08
oltp_distinct_range 4,346 4,547 1.05
oltp_index_scan 7,351 8,896 1.21
select_random_points 21,288 23,872 1.12
select_random_ranges 6,634 7,736 1.17
covering_index_scan 7,769 7,236 0.93
groupby_scan 32,383 33,884 1.05
index_join 8,856 11,389 1.29
index_join_scan 4,872 5,961 1.22
types_table_scan 1,061,418 1,290,895 1.22
table_scan 1,355,999 1,420,638 1.05
oltp_read_only 153,025 173,706 1.14
Average 1.12

Writes

Test SQLite (us) Doltlite (us) Multiplier
oltp_bulk_insert_ac 38,165 128,327 3.36
oltp_insert_ac 46,298 160,053 3.46
oltp_update_index_ac 44,570 170,473 3.82
oltp_update_non_index_ac 44,212 162,847 3.68
oltp_delete_insert_ac 51,635 167,600 3.25
oltp_write_only_ac 48,298 181,334 3.75
types_delete_insert_ac 50,798 153,074 3.01
oltp_read_write_ac 47,864 157,937 3.30
Average 3.46

100000 rows, median of 5 invocations per test; autocommit writes use 9, workload-only timing via host monotonic clock when available.

Performance Ceiling Check (2.5x individual, 2x average; autocommit writes: 6x / 5x)

All tests within ceilings.

@github-actions

Copy link
Copy Markdown

Sysbench-Style Benchmark (TEXT PK): Doltlite vs SQLite

Companion to the classic Sysbench-Style Benchmark. Every workload here
runs against tables with a 32-char hex TEXT PRIMARY KEY (UUID-shaped).

Individual ratios gated at 2.5×; section averages gated at 2×. Autocommit writes use 6× / 5×.

In-Memory

Reads

Test SQLite (us) Doltlite (us) Multiplier
oltp_point_select 33,163 37,548 1.13
oltp_range_select 16,506 14,216 0.86
oltp_sum_range 13,593 13,953 1.03
oltp_order_range 3,387 3,261 0.96
oltp_distinct_range 4,306 4,316 1.00
oltp_index_scan 5,048 6,321 1.25
select_random_points 19,747 22,064 1.12
select_random_ranges 4,413 5,334 1.21
covering_index_scan 5,347 4,890 0.91
groupby_scan 34,959 35,903 1.03
index_join 7,793 9,792 1.26
index_join_scan 4,999 6,284 1.26
types_table_scan 1,404,391 1,323,513 0.94
table_scan 1,718,650 1,457,707 0.85
oltp_read_only 135,971 138,843 1.02
Average 1.06

Writes

Test SQLite (us) Doltlite (us) Multiplier
oltp_bulk_insert 229,300 344,624 1.50
oltp_insert 23,778 40,589 1.71
oltp_update_index 79,112 147,347 1.86
oltp_update_non_index 53,336 92,833 1.74
oltp_delete_insert 57,815 111,602 1.93
oltp_write_only 32,650 67,907 2.08
types_delete_insert 35,211 57,508 1.63
oltp_read_write 97,214 143,256 1.47
Average 1.74

File-Backed

Reads

Test SQLite (us) Doltlite (us) Multiplier
oltp_point_select 114,646 65,930 0.58
oltp_range_select 24,465 16,936 0.69
oltp_sum_range 22,131 16,664 0.75
oltp_order_range 4,229 3,571 0.84
oltp_distinct_range 5,259 4,595 0.87
oltp_index_scan 13,570 9,279 0.68
select_random_points 27,540 24,390 0.89
select_random_ranges 12,738 8,235 0.65
covering_index_scan 15,167 7,851 0.52
groupby_scan 36,101 35,809 0.99
index_join 12,468 11,927 0.96
index_join_scan 6,018 6,336 1.05
types_table_scan 1,376,746 1,324,812 0.96
table_scan 1,713,530 1,455,205 0.85
oltp_read_only 249,161 181,415 0.73
Average 0.80

Writes

Test SQLite (us) Doltlite (us) Multiplier
oltp_bulk_insert 249,436 371,162 1.49
oltp_insert 68,441 52,462 0.77
oltp_update_index 118,346 178,772 1.51
oltp_update_non_index 94,855 118,223 1.25
oltp_delete_insert 96,727 140,294 1.45
oltp_write_only 90,650 91,342 1.01
types_delete_insert 56,236 77,287 1.37
oltp_read_write 145,741 163,056 1.12
Average 1.25

File-Backed (autocommit)

Each statement runs as its own transaction — exposes per-commit
fixed costs that the wrapped-in-BEGIN/COMMIT tests amortize away.
SQLite uses WAL mode with synchronous=FULL in this section so
the comparison uses SQLite's durable WAL autocommit path.

Reads

Reads have no commit cost; these are the same SQL files as the
File-Backed Reads section, included here for symmetry and to
catch any per-statement overhead doltlite pays on the read path.

Test SQLite (us) Doltlite (us) Multiplier
oltp_point_select 58,584 65,051 1.11
oltp_range_select 18,590 16,956 0.91
oltp_sum_range 16,233 16,457 1.01
oltp_order_range 3,756 3,588 0.96
oltp_distinct_range 4,690 4,623 0.99
oltp_index_scan 8,081 9,208 1.14
select_random_points 22,556 24,403 1.08
select_random_ranges 7,228 8,250 1.14
covering_index_scan 9,372 7,831 0.84
groupby_scan 35,220 36,142 1.03
index_join 9,741 11,775 1.21
index_join_scan 5,408 6,457 1.19
types_table_scan 1,406,469 1,317,336 0.94
table_scan 1,762,874 1,454,258 0.82
oltp_read_only 174,633 178,735 1.02
Average 1.03

Writes

Test SQLite (us) Doltlite (us) Multiplier
oltp_bulk_insert_ac 16,837 63,567 3.78
oltp_insert_ac 19,010 78,555 4.13
oltp_update_index_ac 20,390 97,563 4.78
oltp_update_non_index_ac 15,954 73,523 4.61
oltp_delete_insert_ac 18,725 87,558 4.68
oltp_write_only_ac 18,678 83,830 4.49
types_delete_insert_ac 15,378 74,977 4.88
oltp_read_write_ac 24,632 93,038 3.78
Average 4.39

100000 rows, median of 5 invocations per test; autocommit writes use 9, workload-only timing via host monotonic clock when available.

Performance Ceiling Check (2.5x individual, 2x average; autocommit writes: 6x / 5x)

All tests within ceilings.

@github-actions

Copy link
Copy Markdown

Sysbench-Style Benchmark: Doltlite vs SQLite

In-Memory

Reads

Test SQLite (us) Doltlite (us) Multiplier
oltp_point_select 26,466 30,668 1.16
oltp_range_select 10,204 13,007 1.27
oltp_sum_range 10,002 12,139 1.21
oltp_order_range 2,578 2,911 1.13
oltp_distinct_range 3,583 3,978 1.11
oltp_index_scan 4,079 5,437 1.33
select_random_points 11,420 11,268 0.99
select_random_ranges 3,029 4,067 1.34
covering_index_scan 4,156 4,173 1.00
groupby_scan 29,272 32,439 1.11
index_join 6,005 8,150 1.36
index_join_scan 3,591 4,628 1.29
types_table_scan 1,112,666 1,315,750 1.18
table_scan 1,289,938 1,457,761 1.13
oltp_read_only 109,838 124,693 1.14
Average 1.18

Writes

Test SQLite (us) Doltlite (us) Multiplier
oltp_bulk_insert 183,855 256,191 1.39
oltp_insert 15,853 28,474 1.80
oltp_update_index 53,816 100,018 1.86
oltp_update_non_index 36,908 60,713 1.64
oltp_delete_insert 49,427 74,632 1.51
oltp_write_only 24,071 46,140 1.92
types_delete_insert 25,576 40,931 1.60
oltp_read_write 74,551 113,145 1.52
Average 1.65

File-Backed

Reads

Test SQLite (us) Doltlite (us) Multiplier
oltp_point_select 94,476 54,323 0.57
oltp_range_select 17,782 15,417 0.87
oltp_sum_range 17,300 14,803 0.86
oltp_order_range 3,424 3,252 0.95
oltp_distinct_range 4,481 4,217 0.94
oltp_index_scan 11,061 8,254 0.75
select_random_points 18,007 14,063 0.78
select_random_ranges 10,133 6,560 0.65
covering_index_scan 11,728 7,228 0.62
groupby_scan 30,944 33,800 1.09
index_join 10,637 10,477 0.98
index_join_scan 4,521 4,969 1.10
types_table_scan 1,121,242 1,321,706 1.18
table_scan 1,284,527 1,459,580 1.14
oltp_read_only 213,918 160,557 0.75
Average 0.88

Writes

Test SQLite (us) Doltlite (us) Multiplier
oltp_bulk_insert 195,203 275,273 1.41
oltp_insert 22,600 35,970 1.59
oltp_update_index 87,220 119,452 1.37
oltp_update_non_index 59,512 85,454 1.44
oltp_delete_insert 73,801 97,457 1.32
oltp_write_only 48,202 65,091 1.35
types_delete_insert 41,975 54,625 1.30
oltp_read_write 102,045 131,196 1.29
Average 1.38

File-Backed (autocommit)

Each statement runs as its own transaction — exposes per-commit
fixed costs that the wrapped-in-BEGIN/COMMIT tests amortize away.
SQLite uses WAL mode with synchronous=FULL in this section so
the comparison uses SQLite's durable WAL autocommit path.

Reads

Reads have no commit cost; these are the same SQL files as the
File-Backed Reads section, included here for symmetry and to
catch any per-statement overhead doltlite pays on the read path.

Test SQLite (us) Doltlite (us) Multiplier
oltp_point_select 49,146 54,842 1.12
oltp_range_select 14,057 15,477 1.10
oltp_sum_range 12,593 14,846 1.18
oltp_order_range 2,928 3,262 1.11
oltp_distinct_range 3,997 4,246 1.06
oltp_index_scan 6,867 8,215 1.20
select_random_points 14,025 14,689 1.05
select_random_ranges 5,553 6,530 1.18
covering_index_scan 6,920 7,155 1.03
groupby_scan 29,798 32,950 1.11
index_join 8,233 10,364 1.26
index_join_scan 4,128 4,924 1.19
types_table_scan 1,114,980 1,326,091 1.19
table_scan 1,280,441 1,449,124 1.13
oltp_read_only 140,709 161,535 1.15
Average 1.14

Writes

Test SQLite (us) Doltlite (us) Multiplier
oltp_bulk_insert_ac 22,106 83,951 3.80
oltp_insert_ac 24,630 98,277 3.99
oltp_update_index_ac 25,633 113,353 4.42
oltp_update_non_index_ac 23,326 91,976 3.94
oltp_delete_insert_ac 24,830 101,566 4.09
oltp_write_only_ac 26,792 104,185 3.89
types_delete_insert_ac 23,944 91,063 3.80
oltp_read_write_ac 29,894 111,704 3.74
Average 3.96

100000 rows, median of 5 invocations per test; autocommit writes use 9, workload-only timing via host monotonic clock when available.

Performance Ceiling Check (2.5x individual, 2x average; autocommit writes: 6x / 5x)

All tests within ceilings.

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

Sysbench-Style Benchmark (composite PK): Doltlite vs SQLite

Companion to the classic Sysbench-Style Benchmark. Every workload here
runs against tables with a 2-column INTEGER PRIMARY KEY(a, b) WITHOUT ROWID.

Individual ratios gated at 2.5×; section averages gated at 2×. Autocommit writes use 6× / 5×.

In-Memory

Reads

Test SQLite (us) Doltlite (us) Multiplier
oltp_point_select 33,313 38,691 1.16
oltp_range_select 19,302 21,155 1.10
oltp_sum_range 17,279 20,308 1.18
oltp_order_range 3,725 3,931 1.06
oltp_distinct_range 4,747 5,041 1.06
oltp_index_scan 4,682 6,432 1.37
select_random_points 29,074 32,054 1.10
select_random_ranges 7,441 8,341 1.12
covering_index_scan 4,474 4,728 1.06
groupby_scan 38,456 41,557 1.08
index_join 8,044 11,012 1.37
index_join_scan 4,185 5,899 1.41
types_table_scan 1,268,433 1,306,275 1.03
table_scan 1,538,614 1,403,903 0.91
oltp_read_only 151,493 168,212 1.11
Average 1.14

Writes

Test SQLite (us) Doltlite (us) Multiplier
oltp_bulk_insert 243,415 343,089 1.41
oltp_insert 19,215 36,668 1.91
oltp_update_index 67,915 124,877 1.84
oltp_update_non_index 52,260 83,993 1.61
oltp_delete_insert 49,492 96,994 1.96
oltp_write_only 27,402 60,025 2.19
types_delete_insert 31,976 53,351 1.67
oltp_read_write 99,363 148,925 1.50
Average 1.76

File-Backed

Reads

Test SQLite (us) Doltlite (us) Multiplier
oltp_point_select 115,898 66,203 0.57
oltp_range_select 27,150 24,240 0.89
oltp_sum_range 25,548 22,872 0.90
oltp_order_range 4,558 4,263 0.94
oltp_distinct_range 5,577 5,364 0.96
oltp_index_scan 13,239 8,883 0.67
select_random_points 36,009 33,479 0.93
select_random_ranges 15,827 11,159 0.71
covering_index_scan 12,964 7,267 0.56
groupby_scan 38,693 41,382 1.07
index_join 12,457 12,095 0.97
index_join_scan 4,993 6,037 1.21
types_table_scan 1,127,312 1,246,961 1.11
table_scan 1,355,210 1,362,920 1.01
oltp_read_only 266,255 204,317 0.77
Average 0.88

Writes

Test SQLite (us) Doltlite (us) Multiplier
oltp_bulk_insert 260,027 364,488 1.40
oltp_insert 25,832 47,208 1.83
oltp_update_index 97,204 143,955 1.48
oltp_update_non_index 74,754 105,055 1.41
oltp_delete_insert 74,736 120,207 1.61
oltp_write_only 51,075 78,173 1.53
types_delete_insert 48,740 66,787 1.37
oltp_read_write 117,431 168,463 1.43
Average 1.51

File-Backed (autocommit)

Each statement runs as its own transaction — exposes per-commit
fixed costs that the wrapped-in-BEGIN/COMMIT tests amortize away.
SQLite uses WAL mode with synchronous=FULL in this section so
the comparison uses SQLite's durable WAL autocommit path.

Reads

Reads have no commit cost; these are the same SQL files as the
File-Backed Reads section, included here for symmetry and to
catch any per-statement overhead doltlite pays on the read path.

Test SQLite (us) Doltlite (us) Multiplier
oltp_point_select 60,829 66,533 1.09
oltp_range_select 22,054 24,266 1.10
oltp_sum_range 20,469 23,018 1.12
oltp_order_range 4,104 4,253 1.04
oltp_distinct_range 5,078 5,309 1.05
oltp_index_scan 7,742 9,116 1.18
select_random_points 32,083 35,258 1.10
select_random_ranges 10,555 11,415 1.08
covering_index_scan 7,694 7,478 0.97
groupby_scan 38,691 42,001 1.09
index_join 9,741 12,332 1.27
index_join_scan 4,621 6,137 1.33
types_table_scan 1,182,593 1,272,105 1.08
table_scan 1,466,743 1,407,797 0.96
oltp_read_only 195,602 207,466 1.06
Average 1.10

Writes

Test SQLite (us) Doltlite (us) Multiplier
oltp_bulk_insert_ac 16,742 65,558 3.92
oltp_insert_ac 18,543 83,718 4.51
oltp_update_index_ac 19,866 96,794 4.87
oltp_update_non_index_ac 16,484 73,475 4.46
oltp_delete_insert_ac 17,654 85,255 4.83
oltp_write_only_ac 18,150 84,671 4.67
types_delete_insert_ac 15,943 76,341 4.79
oltp_read_write_ac 28,365 102,554 3.62
Average 4.46

100000 rows, median of 5 invocations per test; autocommit writes use 9, workload-only timing via host monotonic clock when available.

Performance Ceiling Check (2.5x individual, 2x average; autocommit writes: 6x / 5x)

All tests within ceilings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant