diff --git a/AGENTS.md b/AGENTS.md
index f8ca789..401725a 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -201,6 +201,8 @@ rm -rf .greptimedb # clean all data
./testbedctl flush
# flush a table's memtable (admin flush_table)
./testbedctl compact [type] [opts] # trigger compaction (admin compact_table); optional twcs/swcs + parallelism=N
./testbedctl gc [--full] # trigger garbage collection (admin gc_table); --full = full object-storage file listing
+./testbedctl gc-regions ... [--full] # trigger GC for specific regions (admin gc_regions); region ids are u64
+./testbedctl purge [-y] # permanently purge a DROPPED table's data (admin purge_table); destructive, -y skips prompt
./testbedctl clean # remove .greptimedb (full data reset)
```
diff --git a/README.md b/README.md
index dadb28c..eb91881 100644
--- a/README.md
+++ b/README.md
@@ -95,6 +95,8 @@ A utility script for common operations against the running cluster:
./testbedctl flush # Flush a table's memtable (admin flush_table)
./testbedctl compact [type] [opts] # Trigger compaction (admin compact_table); optional twcs/swcs + parallelism=N
./testbedctl gc [--full] # Trigger garbage collection (admin gc_table); --full = full file listing
+./testbedctl gc-regions ... [--full] # Trigger GC for specific regions (admin gc_regions); region ids are u64
+./testbedctl purge [-y] # Permanently purge a DROPPED table's data (admin purge_table); -y skips prompt
./testbedctl clean # Remove .greptimedb
```
diff --git a/testbedctl b/testbedctl
index 2f00752..25d1e15 100755
--- a/testbedctl
+++ b/testbedctl
@@ -28,6 +28,12 @@ Commands:
gc [--full]
Trigger garbage collection (admin gc_table). --full forces a full
object-storage file listing.
+ gc-regions ... [--full]
+ Trigger GC for specific regions (admin gc_regions). Region IDs are
+ u64 numbers (e.g. from greptimedb logs). --full forces a full listing.
+ purge [-y|--yes]
+ Permanently purge a DROPPED table's data (admin purge_table).
+ Irreversible; -y skips the confirmation prompt.
clean Remove .greptimedb directory
help Show this help
EOF
@@ -107,6 +113,68 @@ cmd_gc() {
-c "admin gc_table(${args});"
}
+cmd_gc_regions() {
+ local full=false args="" a id
+ local -a ids=()
+ for a in "$@"; do
+ case "$a" in
+ --full|-f) full=true ;;
+ -*) echo "Unknown option: $a" >&2; exit 1 ;;
+ *)
+ if ! [[ "$a" =~ ^[0-9]+$ ]]; then
+ echo "ERROR: region id must be a number, got '$a'" >&2
+ exit 1
+ fi
+ ids+=("$a") ;;
+ esac
+ done
+ if [ "${#ids[@]}" -eq 0 ]; then
+ echo "Usage: testbedctl gc-regions [region_id...] [--full]" >&2
+ echo " Trigger GC for specific regions (admin gc_regions)." >&2
+ echo " --full: force a full object-storage file listing." >&2
+ echo " Region IDs are u64 values (e.g. from greptimedb logs)." >&2
+ exit 1
+ fi
+ # admin gc_regions(...[, ]) — region ids are u64 numbers (unquoted).
+ for id in "${ids[@]}"; do
+ args="${args:+$args, }${id}"
+ done
+ [ "$full" = true ] && args="${args}, true"
+ # Client PG port 11043: haproxy (distributed) or standalone/standalone-fs.
+ exec psql -h 127.0.0.1 -p 11043 -d public -U root \
+ -c "admin gc_regions(${args});"
+}
+
+cmd_purge() {
+ local table="" yes=false a
+ for a in "$@"; do
+ case "$a" in
+ -y|--yes) yes=true ;;
+ -*) echo "Unknown option: $a" >&2; exit 1 ;;
+ *) [ -z "$table" ] && table="$a" ;;
+ esac
+ done
+ if [ -z "$table" ]; then
+ echo "Usage: testbedctl purge [-y|--yes]" >&2
+ echo " Permanently purge a DROPPED table's data (admin purge_table)." >&2
+ echo " Irreversible. -y skips the confirmation prompt." >&2
+ exit 1
+ fi
+ # purge_table permanently deletes a dropped table's data — confirm first.
+ if [ "$yes" != true ]; then
+ printf "About to PERMANENTLY purge table '%s' (irreversible). Continue? [y/N] " "$table" >&2
+ local reply=""
+ read -r reply || true
+ case "$reply" in
+ y|Y|yes|YES) ;;
+ *) echo "aborted." >&2; exit 1 ;;
+ esac
+ fi
+ # Client PG port 11043: haproxy (distributed) or standalone/standalone-fs.
+ exec psql -h 127.0.0.1 -p 11043 -d public -U root \
+ -c "admin purge_table('${table}');"
+}
+
cmd_mysql() {
# Client MySQL port 11042: haproxy (distributed) or standalone/standalone-fs.
exec mysql -h 127.0.0.1 -P 11042 -u root "$@"
@@ -380,6 +448,8 @@ case "${1:-help}" in
flush) shift; cmd_flush "$@" ;;
compact) shift; cmd_compact "$@" ;;
gc) shift; cmd_gc "$@" ;;
+ gc-regions) shift; cmd_gc_regions "$@" ;;
+ purge) shift; cmd_purge "$@" ;;
clean) cmd_clean ;;
help|--help|-h)
usage