Pavel Stehule <pavel.steh...@gmail.com> writes:
>
> 2015-03-23 17:11 GMT+01:00 Pavel Stehule <pavel.steh...@gmail.com>:
>
>> Hi
>>
>> 2015-03-15 16:09 GMT+01:00 Tom Lane <t...@sss.pgh.pa.us>:
>>
>>> Pavel Stehule <pavel.steh...@gmail.com> writes:
>>> > 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.
>>>
>>> I think this design is seriously broken.  If I have '-t foo*' the code
>>> should not prevent that from matching multiple tables.  What would the use
>>> case for such a restriction be?
>>>
>>> What would make sense to me is one or both of these ideas:
>>>
>>> * require a match for a wildcard-free -t switch
>>>
>>> * require at least one (not "exactly one") match for a wildcarded -t
>>>   switch.
>>>
>>
>>
>> attached initial implementation
>>
>
> updated version - same mechanism should be used for schema

Hello,

I think this is a bit over-engineered (apart from the fact that
processSQLNamePattern is also used in two dozen of places in
psql/describe.c and all of them must be touched for this patch to
compile).

Also, the new --table-if-exists options seems to be doing what the old
--table did, and I'm not really sure I underestand what --table does
now.

I propose instead to add a separate new option --strict-include, without
argument, that only controls the behavior when an include pattern didn't
find any table (or schema).

Please see attached patch.

--
Alex

diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml
new file mode 100644
index a6e7b08..da33331
*** a/doc/src/sgml/ref/pg_dump.sgml
--- b/doc/src/sgml/ref/pg_dump.sgml
*************** PostgreSQL documentation
*** 365,370 ****
--- 365,377 ----
          <xref linkend="pg-dump-examples" endterm="pg-dump-examples-title">.
         </para>
  
+        <para>
+          When <replaceable class="parameter">schema</replaceable> doesn't
+          specify a pattern, it must match an exact schema name in the database
+          to be dumped.  In case of a pattern, the behavior is controlled
+          by <option>--strict-include</> option.
+        </para>
+ 
         <note>
          <para>
           When <option>-n</> is specified, <application>pg_dump</application>
*************** PostgreSQL documentation
*** 515,520 ****
--- 522,534 ----
         </para>
  
         <para>
+          When <replaceable class="parameter">table</replaceable> doesn't
+          specify a pattern, it must match an exact table name in the database
+          to be dumped.  In case of a pattern, the behavior is controlled
+          by <option>--strict-include</> option.
+        </para>
+ 
+        <para>
          The <option>-n</> and <option>-N</> switches have no effect when
          <option>-t</> is used, because tables selected by <option>-t</> will
          be dumped regardless of those switches, and non-table objects will not
*************** PostgreSQL documentation
*** 902,907 ****
--- 916,938 ----
         </para>
        </listitem>
       </varlistentry>
+ 
+      <varlistentry>
+       <term><option>--strict-include</></term>
+       <listitem>
+        <para>
+          Require that table and/or schema include patterns match at least one
+          entity each.  If any of the include patterns specified doesn't match
+          any entity in the database to be dumped, an error message is printed
+          and dump is aborted.
+        </para>
+        <para>
+          This option has no effect on the exclude table and schema patterns
+          (and also <option>--exclude-table-data</>): not matching any entities
+          isn't considered an error.
+        </para>
+       </listitem>
+      </varlistentry>
  
       <varlistentry>
        <term><option>--use-set-session-authorization</></term>
diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h
new file mode 100644
index 80df8fc..f384c20
*** a/src/bin/pg_dump/pg_backup.h
--- b/src/bin/pg_dump/pg_backup.h
*************** typedef struct _dumpOptions
*** 178,183 ****
--- 178,184 ----
  	int			outputNoTablespaces;
  	int			use_setsessauth;
  	int			enable_row_security;
+ 	int			strict_include;
  
  	/* default, if no "inclusion" switches appear, is to dump everything */
  	bool		include_everything;
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
new file mode 100644
index dccb472..4f62085
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
*************** static void setup_connection(Archive *AH
*** 131,140 ****
  static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
  static void expand_schema_name_patterns(Archive *fout,
  							SimpleStringList *patterns,
! 							SimpleOidList *oids);
  static void expand_table_name_patterns(Archive *fout,
  						   SimpleStringList *patterns,
! 						   SimpleOidList *oids);
  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);
--- 131,142 ----
  static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
  static void expand_schema_name_patterns(Archive *fout,
  							SimpleStringList *patterns,
! 							SimpleOidList *oids,
! 							bool strict);
  static void expand_table_name_patterns(Archive *fout,
  						   SimpleStringList *patterns,
! 						   SimpleOidList *oids,
! 						   bool strict);
  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);
*************** main(int argc, char **argv)
*** 333,338 ****
--- 335,341 ----
  		{"section", required_argument, NULL, 5},
  		{"serializable-deferrable", no_argument, &dopt.serializable_deferrable, 1},
  		{"snapshot", required_argument, NULL, 6},
+ 		{"strict-include", no_argument, &dopt.strict_include, 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},
*************** main(int argc, char **argv)
*** 689,715 ****
  	if (schema_include_patterns.head != NULL)
  	{
  		expand_schema_name_patterns(fout, &schema_include_patterns,
! 									&schema_include_oids);
! 		if (schema_include_oids.head == NULL)
! 			exit_horribly(NULL, "No matching schemas were found\n");
  	}
  	expand_schema_name_patterns(fout, &schema_exclude_patterns,
! 								&schema_exclude_oids);
  	/* non-matching exclusion patterns aren't an error */
  
  	/* Expand table selection patterns into OID lists */
  	if (table_include_patterns.head != NULL)
  	{
  		expand_table_name_patterns(fout, &table_include_patterns,
! 								   &table_include_oids);
! 		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);
  
  	expand_table_name_patterns(fout, &tabledata_exclude_patterns,
! 							   &tabledata_exclude_oids);
  
  	/* non-matching exclusion patterns aren't an error */
  
--- 692,714 ----
  	if (schema_include_patterns.head != NULL)
  	{
  		expand_schema_name_patterns(fout, &schema_include_patterns,
! 									&schema_include_oids, dopt.strict_include);
  	}
  	expand_schema_name_patterns(fout, &schema_exclude_patterns,
! 								&schema_exclude_oids, true);
  	/* non-matching exclusion patterns aren't an error */
  
  	/* Expand table selection patterns into OID lists */
  	if (table_include_patterns.head != NULL)
  	{
  		expand_table_name_patterns(fout, &table_include_patterns,
! 								   &table_include_oids, dopt.strict_include);
  	}
  	expand_table_name_patterns(fout, &table_exclude_patterns,
! 							   &table_exclude_oids, true);
  
  	expand_table_name_patterns(fout, &tabledata_exclude_patterns,
! 							   &tabledata_exclude_oids, true);
  
  	/* non-matching exclusion patterns aren't an error */
  
*************** help(const char *progname)
*** 904,909 ****
--- 903,910 ----
  	printf(_("  --section=SECTION            dump named section (pre-data, data, or post-data)\n"));
  	printf(_("  --serializable-deferrable    wait until the dump can run without anomalies\n"));
  	printf(_("  --snapshot=SNAPSHOT          use given synchronous snapshot for the dump\n"));
+ 	printf(_("  --strict-include             require table and/or schema include patterns to\n"
+ 			 "                               match at least one entity each\n"));
  	printf(_("  --use-set-session-authorization\n"
  			 "                               use SET SESSION AUTHORIZATION commands instead of\n"
  			 "                               ALTER OWNER commands to set ownership\n"));
*************** parseArchiveFormat(const char *format, A
*** 1133,1139 ****
  static void
  expand_schema_name_patterns(Archive *fout,
  							SimpleStringList *patterns,
! 							SimpleOidList *oids)
  {
  	PQExpBuffer query;
  	PGresult   *res;
--- 1134,1141 ----
  static void
  expand_schema_name_patterns(Archive *fout,
  							SimpleStringList *patterns,
! 							SimpleOidList *oids,
! 							bool strict)
  {
  	PQExpBuffer query;
  	PGresult   *res;
*************** expand_schema_name_patterns(Archive *fou
*** 1155,1176 ****
  
  	for (cell = patterns->head; cell; cell = cell->next)
  	{
! 		if (cell != patterns->head)
! 			appendPQExpBufferStr(query, "UNION ALL\n");
  		appendPQExpBuffer(query,
  						  "SELECT oid FROM pg_catalog.pg_namespace n\n");
  		processSQLNamePattern(GetConnection(fout), query, cell->val, false,
  							  false, NULL, "n.nspname", NULL, NULL);
! 	}
  
! 	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)));
! 	}
  
! 	PQclear(res);
  	destroyPQExpBuffer(query);
  }
  
--- 1157,1183 ----
  
  	for (cell = patterns->head; cell; cell = cell->next)
  	{
! 		resetPQExpBuffer(query);
  		appendPQExpBuffer(query,
  						  "SELECT oid FROM pg_catalog.pg_namespace n\n");
+ 
  		processSQLNamePattern(GetConnection(fout), query, cell->val, false,
  							  false, NULL, "n.nspname", NULL, NULL);
! 		res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
  
! 		if (PQntuples(res) < 1 &&
! 			(strict || strcspn(cell->val, "?*") == strlen(cell->val)))
! 		{
! 			exit_horribly(NULL, "Schema(s) not found: %s\n", cell->val);
! 		}
  
! 		for (i = 0; i < PQntuples(res); i++)
! 		{
! 			simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
! 		}
  
! 		PQclear(res);
! 	}
  	destroyPQExpBuffer(query);
  }
  
*************** expand_schema_name_patterns(Archive *fou
*** 1180,1186 ****
   */
  static void
  expand_table_name_patterns(Archive *fout,
! 						   SimpleStringList *patterns, SimpleOidList *oids)
  {
  	PQExpBuffer query;
  	PGresult   *res;
--- 1187,1194 ----
   */
  static void
  expand_table_name_patterns(Archive *fout,
! 						   SimpleStringList *patterns, SimpleOidList *oids,
! 						   bool strict)
  {
  	PQExpBuffer query;
  	PGresult   *res;
*************** expand_table_name_patterns(Archive *fout
*** 1199,1206 ****
  
  	for (cell = patterns->head; cell; cell = cell->next)
  	{
! 		if (cell != patterns->head)
! 			appendPQExpBufferStr(query, "UNION ALL\n");
  		appendPQExpBuffer(query,
  						  "SELECT c.oid"
  						  "\nFROM pg_catalog.pg_class c"
--- 1207,1213 ----
  
  	for (cell = patterns->head; cell; cell = cell->next)
  	{
! 		resetPQExpBuffer(query);
  		appendPQExpBuffer(query,
  						  "SELECT c.oid"
  						  "\nFROM pg_catalog.pg_class c"
*************** expand_table_name_patterns(Archive *fout
*** 1208,1226 ****
  					 "\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)");
! 	}
  
! 	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)));
  	}
  
- 	PQclear(res);
  	destroyPQExpBuffer(query);
  }
  
--- 1215,1240 ----
  					 "\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)");
! 		res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
  
! 		if (PQntuples(res) < 1 &&
! 			(strict || strcspn(cell->val, "?*") == strlen(cell->val)))
! 		{
! 			exit_horribly(NULL, "Table(s) not found: %s\n", cell->val);
! 		}
  
! 		for (i = 0; i < PQntuples(res); i++)
! 		{
! 			simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 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