Failed COMMIT leaves transaction open and breaks subsequent transactions
Mantenedores costumam responder em até 1 dia
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 4/5
- Tempo estimado
- 3-5 dias
- Facilidade para iniciantes
- 68/100
- Tipo de issue
- Bug
- Clareza
- Claramente especificada
- Status de atividade
- Pouca atividade
- Stack de tecnologia
- react-native, sqlite, typescript
- Domínio
- databases
Direção de pesquisa
Leia packages/react-native-nitro-sqlite/src/operations/transaction.ts, especialmente os caminhos de commit e rollback nas linhas indicadas, e compare o comportamento do commit manual com o comportamento do commit automático. Adicione a cobertura de regressão em um teste Harness usando o reproduzidor de chave estrangeira adiada; considera-se concluído quando o erro de commit original é preservado, a linha inserida está ausente, os erros de rollback continuam visíveis quando aplicável e uma segunda transação é bem-sucedida na mesma conexão.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Summary
When COMMIT fails, transaction() marks the transaction as finished before executing the SQL. The catch block then skips rollback, leaving SQLite inside the failed transaction. A later transaction on the same connection fails with cannot start a transaction within a transaction.
Verified on main at ad8b835 (v9.7.0).
Code evidence
transaction.ts#L44-L52 sets isFinished = true before execute(dbName, 'COMMIT').
If that execute throws, control reaches transaction.ts#L81-L90. The rollback guard is if (!isFinished), so rollback is skipped.
SQLite can legitimately fail COMMIT, including for deferred foreign-key constraints, I/O errors, and busy/locking conditions. A failed commit can leave the transaction active.
Smallest reliable reproducer
const db = open({ name: 'commit-failure.sqlite' })
db.execute('PRAGMA foreign_keys = ON')
db.execute('CREATE TABLE parent (id INTEGER PRIMARY KEY)')
db.execute(`
CREATE TABLE child (
parent_id INTEGER
REFERENCES parent(id)
DEFERRABLE INITIALLY DEFERRED
)
`)
await expect(
db.transaction(async (tx) => {
tx.execute('INSERT INTO child(parent_id) VALUES (?)', [404])
}),
).rejects.toThrow(/FOREIGN KEY constraint failed/)
// Expected: starts cleanly after the failed transaction was rolled back.
// Observed: "cannot start a transaction within a transaction".
await db.transaction(async (tx) => {
tx.execute('SELECT 1')
})
The underlying SQLite sequence is deterministic:
PRAGMA foreign_keys = ON;
CREATE TABLE parent(id INTEGER PRIMARY KEY);
CREATE TABLE child(parent_id INTEGER REFERENCES parent(id) DEFERRABLE INITIALLY DEFERRED);
BEGIN;
INSERT INTO child(parent_id) VALUES (404);
COMMIT; -- FOREIGN KEY constraint failed
BEGIN; -- cannot start a transaction within a transaction
Impact
One commit-time failure poisons the connection for later writes. Callers receive the original commit error, but the library's transaction abstraction no longer restores its documented all-or-nothing/usable-connection invariant.
Acceptance criteria
- Do not transition to a committed/finalized state until
COMMITsucceeds. - On commit failure, attempt rollback while the transaction remains active.
- Preserve the original commit failure; if rollback also fails, expose both errors without replacing the primary cause.
- Model transaction state explicitly enough to distinguish active, committed, rolled back, and failed-finalization states.
- Keep manual
commit()and automatic commit behavior consistent.
Regression-test target
A Harness test using a deferred foreign-key violation that asserts:
- The first transaction rejects with the commit-time constraint error.
- Its inserted row is absent.
- A second transaction on the same connection begins and commits successfully.
- Linguagem predominante
- C
- Estrelas
- 579
- Forks
- 53
- Merge médio
- 2d 3h
- PRs com merge (30d)
- 70
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Sem modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de margelo/react-native-nitro-sqlite
-
area:api area:runtime enhancement
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 35/100
margelo/react-native-nitro-sqlite#402 ·
Mantenedores costumam responder em até 1 dia
-
area:api area:runtime enhancement
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 28/100
margelo/react-native-nitro-sqlite#401 ·
Mantenedores costumam responder em até 1 dia
-
area:api area:runtime enhancement
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 35/100
margelo/react-native-nitro-sqlite#400 ·
Mantenedores costumam responder em até 1 dia
-
area:api area:runtime enhancement
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 28/100
margelo/react-native-nitro-sqlite#399 ·
Mantenedores costumam responder em até 1 dia
-
area:api area:runtime enhancement
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 35/100
margelo/react-native-nitro-sqlite#398 ·
Mantenedores costumam responder em até 1 dia
Todas as issues de margelo/react-native-nitro-sqlite
Issues semelhantes
-
IO.get_env on Node truncates names at embedded NULTalvez já em andamento @Yi-111-a assumiu hoje. Aberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 82/100
HigherOrderCO/Bend#1449 · 1 comentário ·
-
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 88/100
FujiNetWIFI/fujinet-firmware#1872 ·
Mantenedores costumam responder em até 1 dia
-
bug C/C++ code
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 70/100
webarkit/WebARKitLib#84 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 82/100
OpenPrinting/cups#1751 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 72/100
obsproject/obs-studio#14013 ·
Mantenedores costumam responder em até 1 dia