Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .github/pgslie-example.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 16 additions & 4 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Get latest tag for version tagging
id: get_tag
run: |
# If triggered from a tag, use that tag
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
TAG="${{ github.ref_name }}"
else
# Otherwise, fetch and use the latest tag
git fetch --tags
TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
fi
echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "Using tag: $TAG"

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

Expand All @@ -41,10 +55,8 @@ jobs:
with:
images: edraobdu/pgslice
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
type=semver,pattern={{version}},value=${{ steps.get_tag.outputs.tag }}
type=raw,value=latest

- name: Log in to DockerHub
uses: docker/login-action@v3
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/release-finalize.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ jobs:
echo "Triggering publish workflow for tag v${{ steps.get_version.outputs.version }}"
gh workflow run publish.yml --ref "v${{ steps.get_version.outputs.version }}"

- name: Trigger Docker publish workflow
if: steps.check_release.outputs.is_release == 'true' && steps.check_tag.outputs.tag_exists == 'false'
env:
GH_TOKEN: ${{ github.token }}
run: |
echo "Triggering docker-publish workflow for tag v${{ steps.get_version.outputs.version }}"
gh workflow run docker-publish.yml --ref "v${{ steps.get_version.outputs.version }}"

- name: Delete release branch
if: steps.check_release.outputs.is_release == 'true'
continue-on-error: true
Expand Down
97 changes: 12 additions & 85 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

Python CLI tool for extracting PostgreSQL records with all related data via foreign key relationships.

![PgSlice Example](.github/pgslie-example.gif)

## Overview

`pgslice` extracts a specific database record and **ALL** its related records by following foreign key relationships bidirectionally. Perfect for:
Expand Down Expand Up @@ -57,6 +59,11 @@ pip install pgslice

# Or with uv
uv tool install pgslice

# check instalation
pgslice --version
# or
uv run pgslice --version
```

### From Docker Hub
Expand All @@ -65,12 +72,12 @@ uv tool install pgslice
# Pull the image
docker pull edraobdu/pgslice:latest

# Run pgslice
# Check instalation
docker run --rm -it \
-v $(pwd)/dumps:/home/pgslice/.pgslice/dumps \
-e PGPASSWORD=your_password \
edraobdu/pgslice:latest \
pgslice --host your.db.host --port 5432 --user your_user --database your_db
pgslice --version

# Pin to specific version
docker pull edraobdu/pgslice:0.1.1
Expand Down Expand Up @@ -128,16 +135,6 @@ docker run --rm -it \
pgslice --host your.db.host --database your_db --dump users --pks 42
```

**For remote servers:**
```bash
# Run dump on remote server
ssh user@remote-server "docker run --rm -v /tmp/dumps:/home/pgslice/.pgslice/dumps \
edraobdu/pgslice:latest pgslice --dump users --pks 42"

# Copy file locally
scp user@remote-server:/tmp/dumps/users_42_*.sql ./
```

### From Source (Development)

See [DEVELOPMENT.md](DEVELOPMENT.md) for detailed development setup instructions.
Expand Down Expand Up @@ -192,87 +189,17 @@ pgslice --host localhost --database mydb --tables
pgslice --host localhost --database mydb --describe users
```

### SSH Remote Execution

Run pgslice on a remote server and capture output locally:

```bash
# Execute on remote server, save output locally
ssh remote.server.com "PGPASSWORD=xxx pgslice --host db.internal --database mydb \
--dump users --pks 1 --create-schema" > local_dump.sql

# With SSH tunnel for database access
ssh -f -N -L 5433:db.internal:5432 bastion.example.com
PGPASSWORD=xxx pgslice --host localhost --port 5433 --database mydb \
--dump users --pks 42 > user.sql
```

### Interactive REPL

```bash
# Start interactive REPL
pgslice --host localhost --database mydb
PGPASSWORD=mypassword pgslice --host localhost --database mydb --user myuser --port 5432

pgslice> dump "film" 1 --output film_1.sql
pgslice> dump film 1 --output film_1.sql
pgslice> tables
pgslice> describe "film"
```

## CLI vs REPL: Output Behavior

Understanding the difference between CLI and REPL modes:

### CLI Mode (files with progress)
The CLI writes to files and shows progress bars (helpful for large datasets):

```bash
# Writes to ~/.pgslice/dumps/public_users_42_TIMESTAMP.sql
pgslice --dump users --pks 42

# Specify output file
pgslice --dump users --pks 42 --output user_42.sql
pgslice> describe film
```

### REPL Mode (same behavior)
The REPL also writes to **`~/.pgslice/dumps/`** by default:

```bash
# Writes to ~/.pgslice/dumps/public_users_42_TIMESTAMP.sql
pgslice> dump "users" 42

# Specify custom output path
pgslice> dump "users" 42 --output /path/to/user.sql
```

Both modes now behave identically - always writing to files with visible progress.

### Same Operations, Different Modes

| Operation | CLI | REPL |
|-----------|-----|------|
| **List tables** | `pgslice --tables` | `pgslice> tables` |
| **Describe table** | `pgslice --describe users` | `pgslice> describe "users"` |
| **Dump (auto-named)** | `pgslice --dump users --pks 42` | `pgslice> dump "users" 42` |
| **Dump to file** | `pgslice --dump users --pks 42 --output user.sql` | `pgslice> dump "users" 42 --output user.sql` |
| **Dump (default path)** | `~/.pgslice/dumps/public_users_42_TIMESTAMP.sql` | `~/.pgslice/dumps/public_users_42_TIMESTAMP.sql` |
| **Multiple PKs** | `pgslice --dump users --pks 1,2,3` | `pgslice> dump "users" 1,2,3` |
| **Truncate filter** | `pgslice --dump users --pks 42 --truncate "orders:2024-01-01:2024-12-31"` | `pgslice> dump "users" 42 --truncate "orders:2024-01-01:2024-12-31"` |
| **Wide mode** | `pgslice --dump users --pks 42 --wide` | `pgslice> dump "users" 42 --wide` |

### When to Use Each Mode

**Use CLI mode when:**
- Piping output to other commands
- Scripting and automation
- Remote execution via SSH
- One-off dumps

**Use REPL mode when:**
- Exploring database schema interactively
- Running multiple dumps in a session
- You prefer persistent file output
- Testing different dump configurations

## Configuration

Key environment variables (see `.env.example` for full reference):
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ classifiers = [
dependencies = [
"psycopg[binary]>=3.2.2",
"prompt-toolkit>=3.0.0",
"printy==3.0.0",
"printy==3.0.1",
"tabulate>=0.9.0",
"python-dotenv>=1.0.0",
"tqdm>=4.66.0",
Expand Down
10 changes: 5 additions & 5 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.