dolthub / dolthub/doltlite

dolt_reset('--hard') destroys an uncommitted view or trigger unless an unrelated untracked table exists

Closed
#2,904 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C
Stars
268
Forks
18
Avg merge
2h 26m
Merged PRs (30d)
454

Description

Found in a full-repo review at `0ba280f06f`.

`dolt_reset('--hard')` destroys an uncommitted view or trigger — but only when no unrelated untracked table happens to exist. Dolt preserves it in both cases.

```
DoltLite:
unstaged view + untracked table -> views after reset --hard: vv
unstaged view only -> views after reset --hard: (none) <- destroyed
staged view + untracked table -> views after reset --hard: (none)
staged view only -> views after reset --hard: (none)

Dolt 2.3.1:
unstaged view + untracked table -> views after reset --hard: vv
unstaged view only -> views after reset --hard: vv
```

Triggers behave identically to views. The surviving object persists across reopen.

Repro:

```sql
CREATE TABLE t(id INTEGER PRIMARY KEY, a INT);
INSERT INTO t VALUES(1,1);
SELECT dolt_commit('-A','-m','base');
-- with or without: CREATE TABLE untracked(x);
CREATE VIEW vv AS SELECT a FROM t;
SELECT dolt_reset('--hard');
SELECT coalesce(group_concat(name),'(none)') FROM sqlite_master WHERE type='view';
```

## Cause

`doltlitePreserveUntrackedTablesOnHardReset` runs its catalog rebuild only when there is an untracked table to preserve — `src/doltlite_reset.c:405`:

```c
if( rc==SQLITE_OK && nUntracked>0 ){
```

That rebuild is also what carries working views and triggers across the reset: `appendFallbackSchemaCatalogRows` (`src/prolly_btree_catalog.c:1078-1083`) appends every fallback row whose type is neither `table` nor `index`, i.e. all working views and triggers, and the fallback schema is loaded from the **working** catalog (`src/doltlite_reset.c:421-423`, handed on at `:487-489`).

With no untracked table the whole path is skipped and the hard reset switches wholesale to HEAD's catalog, dropping every working view and trigger. So view survival is decided by "does an untracked table exist", which is unrelated to the question.

## Fix

Decide view/trigger survival on its own terms — an uncommitted view or trigger is untracked work and should survive `--hard` the way an untracked table does — and make that decision independent of whether `nUntracked>0`. The matrix in this report (staged/unstaged × with/without an untracked table, for views and triggers) is the fail-before/pass-after test.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in src/doltlite_reset.c around lines 405, 421-423, and 487-489, then trace appendFallbackSchemaCatalogRows in src/prolly_btree_catalog.c around lines 1078-1083. Reproduce the view and trigger cases with the SQL example, covering staged and unstaged objects with and without an untracked table. Done means the full matrix preserves each uncommitted view or trigger across --hard reset.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, sqlite
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.