2015-03-14 19:33 GMT+01:00 Pavel Stehule <pavel.steh...@gmail.com>:

>
>
> 2015-03-13 23:43 GMT+01:00 Josh Berkus <j...@agliodbs.com>:
>
>> On 03/13/2015 10:01 AM, Pavel Stehule wrote:
>> >
>> >
>> > 2015-03-13 17:39 GMT+01:00 Robert Haas <robertmh...@gmail.com
>> > <mailto:robertmh...@gmail.com>>:
>> >
>> >     On Fri, Mar 13, 2015 at 11:26 AM, Pavel Stehule
>> >     <pavel.steh...@gmail.com <mailto:pavel.steh...@gmail.com>> wrote:
>> >     > we found possible bug in pg_dump. It raise a error only when all
>> >     specified
>> >     > tables doesn't exists. When it find any table, then ignore missing
>> >     other.
>> >     >
>> >     > /usr/local/pgsql/bin/pg_dump -t Foo -t omega -s postgres >
>> >     /dev/null; echo
>> >     > $?
>> >     >
>> >     > foo doesn't exists - it creates broken backup due missing "Foo"
>> table
>> >     >
>> >     >  [pavel@localhost include]$ /usr/local/pgsql/bin/pg_dump -t Foo
>> -t
>> >     omegaa -s
>> >     > postgres > /dev/null; echo $?
>> >     > pg_dump: No matching tables were found
>> >     > 1
>> >     >
>> >     > Is it ok? I am thinking, so it is potentially dangerous. Any
>> >     explicitly
>> >     > specified table should to exists.
>> >
>> >     Keep in mind that the argument to -t is a pattern, not just a table
>> >     name.  I'm not sure how much that affects the calculus here, but
>> it's
>> >     something to think about.
>> >
>> >
>> > yes, it has a sense, although now, I am don't think so it was a good
>> > idea. There should be some difference between table name and table
>> pattern.
>>
>> There was a long discussion about this when the feature was introduced
>> in 7.3(?) IIRC.  Changing it now would break backwards-compatibility, so
>> you'd really need to introduce a new option.
>>
>> And, if you introduce a new option which is a specific table name, would
>> you require a schema name or not?
>>
>
> We can use a same rules like we use for STRICT clause somewhere. There
> should be only one table specified by the option. If it is not necessary,
> then only name is enough, else qualified name is necessary.
>
> what is a name for this option? Maybe only with long name - some like
> 'required-table' ?
>

other variant, I hope better than previous. We can introduce new long
option "--strict". With this active option, every pattern specified by -t
option have to have identifies exactly only one table. It can be used for
any other "should to exists" patterns - schemas. Initial implementation in
attachment.

Regards

Pavel


>
> Regards
>
> Pavel
>
>
>>
>> --
>> Josh Berkus
>> PostgreSQL Experts Inc.
>> http://pgexperts.com
>>
>
>
commit 3d3c6f6583c44a06633aea7978ad0631fed1679b
Author: Pavel Stehule <pavel.steh...@gooddata.com>
Date:   Sun Mar 15 00:53:49 2015 +0100

    initial

diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index fdfb431..2a0d50f 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -134,7 +134,8 @@ static void expand_schema_name_patterns(Archive *fout,
 							SimpleOidList *oids);
 static void expand_table_name_patterns(Archive *fout,
 						   SimpleStringList *patterns,
-						   SimpleOidList *oids);
+						   SimpleOidList *oids,
+						   bool strict_table_names);
 static NamespaceInfo *findNamespace(Archive *fout, Oid nsoid, Oid objoid);
 static void dumpTableData(Archive *fout, DumpOptions *dopt, TableDataInfo *tdinfo);
 static void refreshMatViewData(Archive *fout, TableDataInfo *tdinfo);
@@ -253,6 +254,8 @@ static char *get_synchronized_snapshot(Archive *fout);
 static PGresult *ExecuteSqlQueryForSingleRow(Archive *fout, char *query);
 static void setupDumpWorker(Archive *AHX, DumpOptions *dopt, RestoreOptions *ropt);
 
+static int			strict_table_names = false;
+
 
 int
 main(int argc, char **argv)
@@ -332,6 +335,7 @@ main(int argc, char **argv)
 		{"section", required_argument, NULL, 5},
 		{"serializable-deferrable", no_argument, &dopt.serializable_deferrable, 1},
 		{"snapshot", required_argument, NULL, 6},
+		{"strict", no_argument, &strict_table_names, 1},
 		{"use-set-session-authorization", no_argument, &dopt.use_setsessauth, 1},
 		{"no-security-labels", no_argument, &dopt.no_security_labels, 1},
 		{"no-synchronized-snapshots", no_argument, &dopt.no_synchronized_snapshots, 1},
@@ -700,15 +704,18 @@ main(int argc, char **argv)
 	if (table_include_patterns.head != NULL)
 	{
 		expand_table_name_patterns(fout, &table_include_patterns,
-								   &table_include_oids);
+								   &table_include_oids,
+								   strict_table_names);
 		if (table_include_oids.head == NULL)
 			exit_horribly(NULL, "No matching tables were found\n");
 	}
 	expand_table_name_patterns(fout, &table_exclude_patterns,
-							   &table_exclude_oids);
+							   &table_exclude_oids,
+							   false);
 
 	expand_table_name_patterns(fout, &tabledata_exclude_patterns,
-							   &tabledata_exclude_oids);
+							   &tabledata_exclude_oids,
+							   false);
 
 	/* non-matching exclusion patterns aren't an error */
 
@@ -1173,13 +1180,30 @@ expand_schema_name_patterns(Archive *fout,
 	destroyPQExpBuffer(query);
 }
 
+static void
+append_table_name_query(Archive *fout, PQExpBuffer query, char *tablename)
+{
+	appendPQExpBuffer(query,
+					  "SELECT c.oid"
+					  "\nFROM pg_catalog.pg_class c"
+		"\n     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
+				 "\nWHERE c.relkind in ('%c', '%c', '%c', '%c', '%c')\n",
+					  RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW,
+					  RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
+
+	processSQLNamePattern(GetConnection(fout), query, tablename, true,
+						  false, "n.nspname", "c.relname", NULL,
+						  "pg_catalog.pg_table_is_visible(c.oid)");
+}
+
 /*
  * Find the OIDs of all tables matching the given list of patterns,
  * and append them to the given OID list.
  */
 static void
 expand_table_name_patterns(Archive *fout,
-						   SimpleStringList *patterns, SimpleOidList *oids)
+						   SimpleStringList *patterns, SimpleOidList *oids,
+									    bool strict_table_names)
 {
 	PQExpBuffer query;
 	PGresult   *res;
@@ -1196,31 +1220,43 @@ expand_table_name_patterns(Archive *fout,
 	 * duplicate entries in the OID list, but we don't care.
 	 */
 
-	for (cell = patterns->head; cell; cell = cell->next)
+	if (!strict_table_names)
 	{
-		if (cell != patterns->head)
-			appendPQExpBufferStr(query, "UNION ALL\n");
-		appendPQExpBuffer(query,
-						  "SELECT c.oid"
-						  "\nFROM pg_catalog.pg_class c"
-		"\n     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
-					 "\nWHERE c.relkind in ('%c', '%c', '%c', '%c', '%c')\n",
-						  RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW,
-						  RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
-		processSQLNamePattern(GetConnection(fout), query, cell->val, true,
-							  false, "n.nspname", "c.relname", NULL,
-							  "pg_catalog.pg_table_is_visible(c.oid)");
-	}
+		for (cell = patterns->head; cell; cell = cell->next)
+		{
+			if (cell != patterns->head)
+				appendPQExpBufferStr(query, "UNION ALL\n");
+			append_table_name_query(fout, query, cell->val);
+		}
 
-	res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+		res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+		for (i = 0; i < PQntuples(res); i++)
+		{
+			simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
+		}
 
-	for (i = 0; i < PQntuples(res); i++)
-	{
-		simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
+		PQclear(res);
+		destroyPQExpBuffer(query);
 	}
+	else
+	{
+		for (cell = patterns->head; cell; cell = cell->next)
+		{
+			query = createPQExpBuffer();
+			append_table_name_query(fout, query, cell->val);
 
-	PQclear(res);
-	destroyPQExpBuffer(query);
+			res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+			if (PQntuples(res) < 1)
+				exit_horribly(NULL, "No matching table were found for '%s'\n", cell->val);
+			else if (PQntuples(res) > 1)
+				exit_horribly(NULL, "More than one table found for '%s'\n", cell->val);
+			else
+				simple_oid_list_append(oids, atooid(PQgetvalue(res, 0, 0)));
+
+			PQclear(res);
+			destroyPQExpBuffer(query);
+		}
+	}
 }
 
 /*
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to