Skip to content

Commit d3419aa

Browse files
committed
fix(filters): Infer database list from --include-tables and skip rdsadmin
- When --include-tables is specified without --include-databases, the tool now extracts database names from table specs (e.g., "db.table") - Prevents enumerating all databases when only specific tables requested - Also excludes AWS RDS 'rdsadmin' internal database from discovery - Fixes pg_hba.conf rejection errors when replicating from AWS RDS Fixes connection failures when replicating specific tables from AWS RDS.
1 parent 08b3aa0 commit d3419aa

6 files changed

Lines changed: 64 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [5.3.11] - 2025-12-02
6+
7+
### Fixed
8+
9+
- **Skip AWS RDS internal database during discovery**: The `rdsadmin` database (AWS RDS's internal administration database) is now automatically excluded from database discovery, preventing "pg_hba.conf rejects connection" errors when replicating from AWS RDS sources.
10+
11+
- **Infer database list from `--include-tables`**: When using `--include-tables` without `--include-databases`, the tool now automatically extracts database names from the table specifications (e.g., `--include-tables "mydb.table1,mydb.table2"` will only replicate the `mydb` database). Previously, all databases were enumerated even when only specific tables were requested.
12+
513
## [5.3.10] - 2025-12-02
614

715
### Improved

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "database-replicator"
3-
version = "5.3.10"
3+
version = "5.3.11"
44
edition = "2021"
55
license = "Apache-2.0"
66
description = "Universal database-to-PostgreSQL replication CLI. Supports PostgreSQL, SQLite, MongoDB, and MySQL."

src/commands/init.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ pub async fn init(
104104
// Run pre-flight checks before any destructive operations
105105
tracing::info!("Running pre-flight checks...");
106106

107-
let databases = filter.include_databases().map(|v| v.to_vec());
107+
// Get explicit database list from filters (include_databases or extracted from include_tables)
108+
let databases = filter.databases_to_check();
108109
let preflight_result = crate::preflight::run_preflight_checks(
109110
source_url,
110111
target_url,

src/filters.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,58 @@ impl ReplicationFilter {
144144
self.exclude_tables.as_ref()
145145
}
146146

147+
/// Gets the explicit list of databases to check/replicate
148+
///
149+
/// Returns databases from:
150+
/// 1. include_databases if specified, OR
151+
/// 2. database names extracted from include_tables if specified
152+
///
153+
/// Returns None if no explicit database list can be determined
154+
/// (meaning all databases should be enumerated).
155+
pub fn databases_to_check(&self) -> Option<Vec<String>> {
156+
if let Some(ref include) = self.include_databases {
157+
return Some(include.clone());
158+
}
159+
160+
if let Some(ref include_tables) = self.include_tables {
161+
// Extract unique database names from "database.table" format
162+
let mut databases: Vec<String> = include_tables
163+
.iter()
164+
.filter_map(|table| table.split('.').next().map(String::from))
165+
.collect();
166+
databases.sort();
167+
databases.dedup();
168+
if !databases.is_empty() {
169+
return Some(databases);
170+
}
171+
}
172+
173+
None
174+
}
175+
147176
/// Determines if a database should be replicated
177+
///
178+
/// A database is replicated if:
179+
/// 1. It's in the include_databases list (if specified), OR
180+
/// 2. It's referenced in include_tables (if specified and no include_databases), OR
181+
/// 3. No include filters are specified (replicate all)
182+
///
183+
/// AND it's not in the exclude_databases list.
148184
pub fn should_replicate_database(&self, db_name: &str) -> bool {
149-
// If include list exists, database must be in it
185+
// If include_databases list exists, database must be in it
150186
if let Some(ref include) = self.include_databases {
151187
if !include.contains(&db_name.to_string()) {
152188
return false;
153189
}
190+
} else if let Some(ref include_tables) = self.include_tables {
191+
// If include_tables is specified but include_databases is not,
192+
// only replicate databases referenced in include_tables
193+
let db_referenced = include_tables
194+
.iter()
195+
.any(|table| table.split('.').next() == Some(db_name));
196+
if !db_referenced {
197+
return false;
198+
}
154199
}
155200

156201
// If exclude list exists, database must not be in it

src/migration/schema.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,18 @@ pub struct ColumnInfo {
2525
}
2626

2727
/// List all non-system databases in the cluster
28+
///
29+
/// Excludes:
30+
/// - PostgreSQL template databases (template0, template1)
31+
/// - PostgreSQL default database (postgres)
32+
/// - AWS RDS internal database (rdsadmin)
2833
pub async fn list_databases(client: &Client) -> Result<Vec<DatabaseInfo>> {
2934
let rows = client
3035
.query(
3136
"SELECT datname, pg_catalog.pg_get_userbyid(datdba) as owner
3237
FROM pg_catalog.pg_database
3338
WHERE datistemplate = false
34-
AND datname NOT IN ('postgres', 'template0', 'template1')
39+
AND datname NOT IN ('postgres', 'template0', 'template1', 'rdsadmin')
3540
ORDER BY datname",
3641
&[],
3742
)

0 commit comments

Comments
 (0)