From 61623a4d40bb7f477bd0db192fe08b727bf4e1b4 Mon Sep 17 00:00:00 2001 From: Khanna Date: Thu, 21 Aug 2025 13:44:43 +0530 Subject: [PATCH v3 2/2] Support WHERE clause and COLUMN list in --table argument This patch support the specification of both a WHERE clause (row filter) and a column list in the table specification via pg_createsubscriber, and modify the utility's name (for example, to a more descriptive or aligned name). For eg:- CREATE PUBLICATION pub FOR TABLE schema.table (col1, col2) WHERE (predicate); --- src/bin/pg_basebackup/pg_createsubscriber.c | 49 +++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/bin/pg_basebackup/pg_createsubscriber.c b/src/bin/pg_basebackup/pg_createsubscriber.c index 0017a740b72..ecfb032593d 100644 --- a/src/bin/pg_basebackup/pg_createsubscriber.c +++ b/src/bin/pg_basebackup/pg_createsubscriber.c @@ -35,6 +35,8 @@ typedef struct TableSpec { char *spec; char *dbname; + char *att_names; + char *row_filter; char *pattern_regex; char *pattern_part1_regex; char *pattern_part2_regex; @@ -143,6 +145,7 @@ static void drop_existing_subscriptions(PGconn *conn, const char *subname, const char *dbname); static void get_publisher_databases(struct CreateSubscriberOptions *opt, bool dbnamespecified); +static char *pg_strcasestr(const char *haystack, const char *needle); #define USEC_PER_SEC 1000000 #define WAIT_INTERVAL 1 /* 1 second */ @@ -177,6 +180,24 @@ enum WaitPMResult POSTMASTER_STILL_STARTING }; +char * +pg_strcasestr(const char *haystack, const char *needle) +{ + if (!*needle) + return (char *) haystack; + for (; *haystack; haystack++) + { + const char *h = haystack; + const char *n = needle; + + while (*h && *n && pg_tolower((unsigned char) *h) == pg_tolower((unsigned char) *n)) + ++h, ++n; + if (!*n) + return (char *) haystack; + } + return NULL; +} + /* * Cleanup objects that were created by pg_createsubscriber if there is an * error. @@ -1746,6 +1767,11 @@ create_publication(PGconn *conn, struct LogicalRepInfo *dbinfo) first_table ? "" : ", ", escaped_schema, escaped_table); + if (tbl->att_names && strlen(tbl->att_names) > 0) + appendPQExpBuffer(str, " ( %s )", tbl->att_names); + + if (tbl->row_filter && strlen(tbl->row_filter) > 0) + appendPQExpBuffer(str, " WHERE %s", tbl->row_filter); first_table = false; PQfreemem(escaped_schema); @@ -2334,6 +2360,8 @@ main(int argc, char **argv) char *second_dot; char *dbname_arg = NULL; char *schema_table_part; + char *paren_start = NULL; + char *where_start = NULL; TableSpec *ts; PQExpBuffer dbbuf; PQExpBuffer schemabuf; @@ -2346,6 +2374,27 @@ main(int argc, char **argv) copy_arg = pg_strdup(optarg); + where_start = pg_strcasestr(copy_arg, " where "); + if (where_start != NULL) + { + *where_start = '\0'; + where_start += 7; + } + + paren_start = strchr(copy_arg, '('); + if (paren_start != NULL) + { + char *paren_end = strrchr(paren_start, ')'); + + if (!paren_end) + pg_fatal("unmatched '(' in --table argument \"%s\"", optarg); + + *paren_start = '\0'; + *paren_end = '\0'; + + paren_start++; + } + first_dot = strchr(copy_arg, '.'); if (first_dot != NULL) second_dot = strchr(first_dot + 1, '.'); -- 2.41.0.windows.3