Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jnidzwetzki committed Apr 15, 2024
1 parent 82ce5d2 commit 6ac69c0
Show file tree
Hide file tree
Showing 6 changed files with 474 additions and 2 deletions.
45 changes: 45 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Basic Project Tests
on:
pull_request:
push:
branches:
- main

jobs:
tests:
name: Perform tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Install Rust
uses: dtolnay/rust-toolchain@stable

- name: Set up cargo cache
uses: actions/cache@v3
continue-on-error: false
with:
path: |
~/.pgrx/
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-

- name: Install pgrx
run: |
if [[ ! -d ~/.pgrx ]]; then
cargo install --locked cargo-pgrx
cargo pgrx init
fi
- name: Lint
run: |
cargo fmt --all -- --check
cargo clippy -- -D warnings
- name: Execute tests
run: cargo pgrx test pg15
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ Cargo.lock

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

.vscode
37 changes: 37 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[package]
name = "pg_debug_scan"
version = "0.1.0"
edition = "2021"
authors = ["Jan Nidzwetzki"]
repository = "https://github.com/jnidzwetzki/pg_debug_scan"

[lib]
crate-type = ["cdylib"]

[features]
default = ["pg13"]
pg11 = ["pgrx/pg11", "pgrx-tests/pg11" ]
pg12 = ["pgrx/pg12", "pgrx-tests/pg12" ]
pg13 = ["pgrx/pg13", "pgrx-tests/pg13" ]
pg14 = ["pgrx/pg14", "pgrx-tests/pg14" ]
pg15 = ["pgrx/pg15", "pgrx-tests/pg15" ]
pg16 = ["pgrx/pg16", "pgrx-tests/pg16" ]
pg_test = []

[dependencies]
pgrx = "=0.11.3"
serde = { version = "~1.0", features = ["derive"] }
serde_json = "=1.0"

[dev-dependencies]
pgrx-tests = "=0.11.3"


[profile.dev]
panic = "unwind"

[profile.release]
panic = "unwind"
opt-level = 3
lto = "fat"
codegen-units = 1
82 changes: 80 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,80 @@
# pg_debug_scan
PostgreSQL extension to debug table scans
# Motivation
`pg_debug_scan` is a PostgreSQL extension that debugs table scans by proving custom snapshot definitions. This extension is intended to teach the internals of database systems and allow users to see the results of different snapshots and visibility rules. In addition, I needed a small project to explore writing PostgreSQL extensions in Rust with pgrx.

The foundations of snapshots can be found in this [article](https://jnidzwetzki.github.io/2024/04/03/postgres-and-snapshots.html). This extension provides the function `pg_debug_scan`, which takes a table name and the xmin, xmax, and xip values of a snapshot as arguments and performs a full table scan using this snapshot data.

## Build and Install
```shell
cargo pgrx install
```

## Example
```sql
CREATE EXTENSION pg_debug_scan;

CREATE TABLE temperature (
time timestamptz NOT NULL,
value float
);

INSERT INTO temperature VALUES(now(), 1);
INSERT INTO temperature VALUES(now(), 2);
INSERT INTO temperature VALUES(now(), 3);

BEGIN TRANSACTION;
DELETE FROM TEMPERATURE where value = 2;
SELECT * FROM txid_current_if_assigned();

txid_current_if_assigned
--------------------------
774

COMMIT;

SELECT xmin, xmax, * FROM temperature;
xmin | xmax | time | value
------+------+-------------------------------+-------
771 | 0 | 2024-04-12 15:59:23.348272+02 | 1
773 | 0 | 2024-04-12 15:59:23.362715+02 | 3
(2 rows)

-- Based on the output, we know that the first record should be visible
-- in all transactions with a txid >= 771. The second record if visible
-- for all txid => 773.
--
-- One record is deleted but we can assume it was created with a xmin
-- value of 772 and we know from the txid_current_if_assigned output,
-- it was deleted in the transaction with the id 774.

-- If we use the same data as the snapshot of our session...
SELECT * FROM pg_current_snapshot();
pg_current_snapshot
---------------------
775:775:

-- .. the extension returns the same data as the regular SELECT
SELECT * from pg_debug_scan('temperature', '775:775:');

xmin | xmax | data
------+------+------------------------------------------------------
771 | 0 | {"time":"2024-04-12 15:59:23.348272+02","value":"1"}
773 | 0 | {"time":"2024-04-12 15:59:23.362715+02","value":"3"}

-- However, if we exclude txid 775, the deleted tuple becomes visible again
SELECT * from pg_debug_scan('temperature', '774:774:');

xmin | xmax | data
------+------+------------------------------------------------------
771 | 0 | {"time":"2024-04-12 15:59:23.348272+02","value":"1"}
772 | 774 | {"time":"2024-04-12 15:59:23.357605+02","value":"2"}
773 | 0 | {"time":"2024-04-12 15:59:23.362715+02","value":"3"}

-- And if we go one transaction further back in time, the last insert becomes invisible
SELECT * from pg_debug_scan('temperature', '773:773:');

xmin | xmax | data
------+------+------------------------------------------------------
771 | 0 | {"time":"2024-04-12 15:59:23.348272+02","value":"1"}
772 | 774 | {"time":"2024-04-12 15:59:23.357605+02","value":"2"}
```

5 changes: 5 additions & 0 deletions pg_debug_scan.control
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
comment = 'pg_debug_scan'
default_version = '@CARGO_VERSION@'
module_pathname = '$libdir/pg_debug_scan'
relocatable = false
superuser = true
Loading

0 comments on commit 6ac69c0

Please sign in to comment.