diff --git a/pgbelt/cmd/setup.py b/pgbelt/cmd/setup.py index 5a7bfd7c..53dc2966 100644 --- a/pgbelt/cmd/setup.py +++ b/pgbelt/cmd/setup.py @@ -41,7 +41,23 @@ async def _setup_src_node( pglogical_tables = pkey_tables if conf.tables: - pglogical_tables = [t for t in pkey_tables if t in conf.tables] + pglogical_tables = [ + t + for t in pkey_tables + if t + in list( + map(str.lower, conf.tables) + ) # Postgres returns table names in lowercase (in analyze_table_pkeys) + ] + + # Intentionally throw an error if no tables are found, so that the user can correct their config. + # When reported by a certain user, errors showed when running the status command, but it was ignored, + # then the user ran setup and since that DIDN'T throw an error, they assumed everything was fine. + + if not pglogical_tables: + raise ValueError( + f"No tables were targeted to replicate. Please check your config's schema and tables. DB: {conf.db} DC: {conf.dc}, SCHEMA: {conf.schema_name} TABLES: {conf.tables}.\nIf TABLES is [], all tables in the schema should be replicated, but pgbelt still found no tables.\nCheck the schema name or reach out to the pgbelt team for help." + ) await configure_replication_set( src_root_pool, pglogical_tables, conf.schema_name, src_logger @@ -145,7 +161,14 @@ async def setup_back_replication(config_future: Awaitable[DbupgradeConfig]) -> N pglogical_tables = pkeys if conf.tables: - pglogical_tables = [t for t in pkeys if t in conf.tables] + pglogical_tables = [ + t + for t in pkeys + if t + in list( + map(str.lower, conf.tables) + ) # Postgres returns table names in lowercase (in analyze_table_pkeys) + ] await configure_replication_set( dst_root_pool, pglogical_tables, conf.schema_name, dst_logger diff --git a/pgbelt/cmd/status.py b/pgbelt/cmd/status.py index 1ac8c2a2..1c1e4f1a 100644 --- a/pgbelt/cmd/status.py +++ b/pgbelt/cmd/status.py @@ -92,7 +92,14 @@ async def status(conf_future: Awaitable[DbupgradeConfig]) -> dict[str, str]: all_tables = pkey_tables + non_pkey_tables target_tables = all_tables if conf.tables: - target_tables = [t for t in all_tables if t in conf.tables] + target_tables = [ + t + for t in all_tables + if t + in list( + map(str.lower, conf.tables) + ) # Postgres gave us lowercase table names in analyze_table_pkeys + ] if not target_tables: raise ValueError( diff --git a/pgbelt/cmd/sync.py b/pgbelt/cmd/sync.py index 48eedc4b..e73aff92 100644 --- a/pgbelt/cmd/sync.py +++ b/pgbelt/cmd/sync.py @@ -77,7 +77,14 @@ async def dump_tables( _, tables, _ = await analyze_table_pkeys(src_pool, conf.schema_name, logger) if conf.tables: - tables = [t for t in tables if t in conf.tables] + tables = [ + t + for t in tables + if t + in list( + map(str.lower, conf.tables) + ) # Postgres returns table names in lowercase (in analyze_table_pkeys) + ] await dump_source_tables(conf, tables, logger) @@ -185,7 +192,14 @@ async def _dump_and_load_all_tables( ) -> None: _, tables, _ = await analyze_table_pkeys(src_pool, conf.schema_name, src_logger) if conf.tables: - tables = [t for t in tables if t in conf.tables] + tables = [ + t + for t in tables + if t + in list( + map(str.lower, conf.tables) + ) # Postgres returns table names in lowercase (in analyze_table_pkeys) + ] await dump_source_tables(conf, tables, src_logger) await load_dumped_tables(conf, tables, dst_logger) diff --git a/pgbelt/util/postgres.py b/pgbelt/util/postgres.py index 079288cc..24ee2da7 100644 --- a/pgbelt/util/postgres.py +++ b/pgbelt/util/postgres.py @@ -372,9 +372,22 @@ async def precheck_info( AND n.nspname <> 'pglogical' ORDER BY 1,2;""" ) + # We filter the table list if the user has specified a list of tables to target. + # Note, from issue #420, the above query will return the table names in lowercase, + # so we need to map the target_tables to lowercase. if target_tables: - result["tables"] = [t for t in result["tables"] if t["Name"] in target_tables] + + result["tables"] = [ + t + for t in result["tables"] + if t["Name"] in list(map(str.lower, target_tables)) + ] + + # We will not recapitalize the table names in the result["tables"] list, + # to preserve how Postgres sees those tables in its system catalog. Easy + # rabbit hole later if we keep patching the table names to match the user's + # input. result["sequences"] = await pool.fetch( """ @@ -392,12 +405,22 @@ async def precheck_info( ORDER BY 1,2;""" ) - # We filter the sequence list if the user has specified a list of sequences to target. + # We filter the table list if the user has specified a list of tables to target. + # Note, from issue #420, the above query will return the table names in lowercase, + # so we need to map the target_tables to lowercase. if target_sequences: + result["sequences"] = [ - s for s in result["sequences"] if s["Name"] in target_sequences + t + for t in result["sequences"] + if t["Name"] in list(map(str.lower, target_sequences)) ] + # We will not recapitalize the table names in the result["tables"] list, + # to preserve how Postgres sees those tables in its system catalog. Easy + # rabbit hole later if we keep patching the table names to match the user's + # input. + users = await pool.fetch( f""" SELECT r.rolname, r.rolsuper, r.rolinherit,