Files
turso/Makefile
Glauber Costa 7e76970035 fix: Handle fresh INSERTs in materialized view incremental maintenance
The op_insert function was incorrectly trying to capture an "old record"
for fresh INSERT operations when a table had dependent materialized views.
This caused a "Cannot delete: no current row" error because the cursor
wasn't positioned on any row for new inserts.

The issue was introduced in commit f38333b3 which refactored the state
machine for incremental view handling but didn't properly distinguish
between:
- Fresh INSERT operations (no old record exists)
- UPDATE operations without rowid change (old record should be captured)
- UPDATE operations with rowid change (already handled by DELETE)

This fix checks if cursor.rowid() returns a value before attempting to
capture the old record. If no row exists (fresh INSERT), we correctly
set old_record to None instead of erroring out.

I am also including tests to make sure this doesn't break. The reason I
didn't include tests earlier is that I didn't know it was possible to
run the tests under a flag. But in here, I am just adding the flag to
the execution script.
2025-08-13 06:41:14 -05:00

200 lines
6.1 KiB
Makefile

MINIMUM_RUST_VERSION := 1.73.0
CURRENT_RUST_VERSION := $(shell rustc -V | sed -E 's/rustc ([0-9]+\.[0-9]+\.[0-9]+).*/\1/')
CURRENT_RUST_TARGET := $(shell rustc -vV | grep host | cut -d ' ' -f 2)
RUSTUP := $(shell command -v rustup 2> /dev/null)
UNAME_S := $(shell uname -s)
MINIMUM_TCL_VERSION := 8.6
# Executable used to execute the compatibility tests.
SQLITE_EXEC ?= scripts/limbo-sqlite3
RUST_LOG := off
all: check-rust-version limbo
.PHONY: all
check-rust-version:
@echo "Checking Rust version..."
@if [ "$(shell printf '%s\n' "$(MINIMUM_RUST_VERSION)" "$(CURRENT_RUST_VERSION)" | sort -V | head -n1)" = "$(CURRENT_RUST_VERSION)" ]; then \
echo "Rust version greater than $(MINIMUM_RUST_VERSION) is required. Current version is $(CURRENT_RUST_VERSION)."; \
if [ -n "$(RUSTUP)" ]; then \
echo "Updating Rust..."; \
rustup update stable; \
else \
echo "Please update Rust manually to a version greater than $(MINIMUM_RUST_VERSION)."; \
exit 1; \
fi; \
else \
echo "Rust version $(CURRENT_RUST_VERSION) is acceptable."; \
fi
.PHONY: check-rust-version
check-tcl-version:
@printf '%s\n' \
'set need "$(MINIMUM_TCL_VERSION)"' \
'set have [info patchlevel]' \
'if {[package vcompare $$have $$need] < 0} {' \
' puts stderr "tclsh $$have found — need $$need+"' \
' exit 1' \
'}' \
| tclsh
.PHONY: check-tcl-version
limbo:
cargo build
.PHONY: limbo
limbo-c:
cargo cbuild
.PHONY: limbo-c
uv-sync:
uv sync --all-packages
.PHONE: uv-sync
uv-sync-test:
uv sync --all-extras --dev --package turso_test
.PHONE: uv-sync
test: limbo uv-sync-test test-compat test-vector test-sqlite3 test-shell test-memory test-write test-update test-constraint test-collate test-extensions test-mvcc test-matviews
.PHONY: test
test-extensions: limbo uv-sync-test
RUST_LOG=$(RUST_LOG) uv run --project limbo_test test-extensions
.PHONY: test-extensions
test-shell: limbo uv-sync-test
RUST_LOG=$(RUST_LOG) SQLITE_EXEC=$(SQLITE_EXEC) uv run --project limbo_test test-shell
.PHONY: test-shell
test-compat: check-tcl-version
RUST_LOG=$(RUST_LOG) SQLITE_EXEC=$(SQLITE_EXEC) ./testing/all.test
.PHONY: test-compat
test-vector:
RUST_LOG=$(RUST_LOG) SQLITE_EXEC=$(SQLITE_EXEC) ./testing/vector.test
.PHONY: test-vector
test-time:
RUST_LOG=$(RUST_LOG) SQLITE_EXEC=$(SQLITE_EXEC) ./testing/time.test
.PHONY: test-time
test-matviews:
RUST_LOG=$(RUST_LOG) SQLITE_EXEC=$(SQLITE_EXEC) ./testing/materialized_views.test
.PHONY: test-matviews
reset-db:
./scripts/clone_test_db.sh
.PHONY: reset-db
test-sqlite3: reset-db
cargo test -p turso_sqlite3 --test compat
./scripts/clone_test_db.sh
cargo test -p turso_sqlite3 --test compat --features sqlite3
.PHONY: test-sqlite3
test-json:
RUST_LOG=$(RUST_LOG) SQLITE_EXEC=$(SQLITE_EXEC) ./testing/json.test
.PHONY: test-json
test-memory: limbo uv-sync-test
RUST_LOG=$(RUST_LOG) SQLITE_EXEC=$(SQLITE_EXEC) uv run --project limbo_test test-memory
.PHONY: test-memory
test-write: limbo uv-sync-test
@if [ "$(SQLITE_EXEC)" != "scripts/limbo-sqlite3" ]; then \
RUST_LOG=$(RUST_LOG) SQLITE_EXEC=$(SQLITE_EXEC) uv run --project limbo_test test-write; \
else \
echo "Skipping test-write: SQLITE_EXEC does not have indexes scripts/limbo-sqlite3"; \
fi
.PHONY: test-write
test-update: limbo uv-sync-test
@if [ "$(SQLITE_EXEC)" != "scripts/limbo-sqlite3" ]; then \
RUST_LOG=$(RUST_LOG) SQLITE_EXEC=$(SQLITE_EXEC) uv run --project limbo_test test-update; \
else \
echo "Skipping test-update: SQLITE_EXEC does not have indexes scripts/limbo-sqlite3"; \
fi
.PHONY: test-update
test-collate: limbo uv-sync-test
@if [ "$(SQLITE_EXEC)" != "scripts/limbo-sqlite3" ]; then \
RUST_LOG=$(RUST_LOG) SQLITE_EXEC=$(SQLITE_EXEC) uv run --project limbo_test test-collate; \
else \
echo "Skipping test-collate: SQLITE_EXEC does not have indexes scripts/limbo-sqlite3"; \
fi
.PHONY: test-collate
test-constraint: limbo uv-sync-test
@if [ "$(SQLITE_EXEC)" != "scripts/limbo-sqlite3" ]; then \
RUST_LOG=$(RUST_LOG) SQLITE_EXEC=$(SQLITE_EXEC) uv run --project limbo_test test-constraint; \
else \
echo "Skipping test-constraint: SQLITE_EXEC does not have indexes scripts/limbo-sqlite3"; \
fi
.PHONY: test-constraint
test-mvcc: limbo uv-sync-test
RUST_LOG=$(RUST_LOG) SQLITE_EXEC=$(SQLITE_EXEC) uv run --project limbo_test test-mvcc;
.PHONY: test-mvcc
bench-vfs: uv-sync-test
cargo build --release
RUST_LOG=$(RUST_LOG) uv run --project limbo_test bench-vfs "$(SQL)" "$(N)"
clickbench:
./perf/clickbench/benchmark.sh
.PHONY: clickbench
bench-exclude-tpc-h:
@benchmarks=$$(cargo bench --bench 2>&1 | grep -A 1000 '^Available bench targets:' | grep -v '^Available bench targets:' | grep -v '^ *$$' | grep -v 'tpc_h_benchmark' | xargs -I {} printf -- "--bench %s " {}); \
if [ -z "$$benchmarks" ]; then \
echo "No benchmarks found (excluding tpc_h_benchmark)."; \
exit 1; \
else \
cargo bench $$benchmarks; \
fi
.PHONY: bench-exclude-tpc-h
docker-cli-build:
docker build -f Dockerfile.cli -t turso-cli .
docker-cli-run:
docker run -it -v ./:/app turso-cli
merge-pr:
ifndef PR
$(error PR is required. Usage: make merge-pr PR=123)
endif
@echo "Setting up environment for PR merge..."
@if [ -z "$(GITHUB_REPOSITORY)" ]; then \
REPO=$$(git remote get-url origin | sed -E 's|.*github\.com[:/]([^/]+/[^/]+?)(\.git)?$$|\1|'); \
if [ -z "$$REPO" ]; then \
echo "Error: Could not detect repository from git remote"; \
exit 1; \
fi; \
export GITHUB_REPOSITORY="$$REPO"; \
else \
export GITHUB_REPOSITORY="$(GITHUB_REPOSITORY)"; \
fi; \
echo "Repository: $$REPO"; \
AUTH=$$(gh auth status); \
if [ -z "$$AUTH" ]; then \
echo "auth: $$AUTH"; \
echo "GitHub CLI not authenticated. Starting login process..."; \
gh auth login --scopes repo,workflow; \
else \
if ! echo "$$AUTH" | grep -q "workflow"; then \
echo "Warning: 'workflow' scope not detected. You may need to re-authenticate if merging PRs with workflow changes."; \
echo "Run: gh auth refresh -s repo,workflow"; \
fi; \
fi; \
if [ "$(LOCAL)" = "1" ]; then \
echo "merging PR #$(PR) locally"; \
uv run scripts/merge-pr.py $(PR) --local; \
else \
echo "merging PR #$(PR) on GitHub"; \
uv run scripts/merge-pr.py $(PR); \
fi
.PHONY: merge-pr