Re: pg_dump additional options for performance

Simon Riggs <[email protected]> Thu, 24 Jul 2008 08:37:11 +0100
Newsgroups gmane.comp.db.postgresql.devel.patches
Message-ID <[email protected]>
On Wed, 2008-07-23 at 23:20 -0400, Stephen Frost wrote:

> * Simon Riggs ([email protected]) wrote:
> > ...and with command line help also.
> 
> The documentation and whatnot looks good to me now.  There are a couple
> of other issues I found while looking through and testing the patch
> though-

Thanks for a good review.

> Index: src/bin/pg_dump/pg_dump.c
> ===================================================================
> RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/bin/pg_dump/pg_dump.c,v
> retrieving revision 1.497
> diff -c -r1.497 pg_dump.c
> *** src/bin/pg_dump/pg_dump.c	20 Jul 2008 18:43:30 -0000	1.497
> --- src/bin/pg_dump/pg_dump.c	23 Jul 2008 17:04:24 -0000
> ***************
> *** 225,232 ****
>   	RestoreOptions *ropt;
>   
>   	static int	disable_triggers = 0;
> ! 	static int  outputNoTablespaces = 0;
>   	static int	use_setsessauth = 0;
>   
>   	static struct option long_options[] = {
>   		{"data-only", no_argument, NULL, 'a'},
> --- 229,238 ----
>   	RestoreOptions *ropt;
>   
>   	static int	disable_triggers = 0;
> ! 	static int outputNoTablespaces = 0;
>   	static int	use_setsessauth = 0;
> + 	static int	use_schemaBeforeData;
> + 	static int	use_schemaAfterData;
>   
>   	static struct option long_options[] = {
>   		{"data-only", no_argument, NULL, 'a'},
> ***************
> 
> This hunk appears to have a bit of gratuitous whitespace change, not a
> big deal tho.

OK

> ***************
> *** 464,474 ****
> [...]
> + 	if (dataOnly)
> + 		dumpObjFlags = REQ_DATA;
> + 
> + 	if (use_schemaBeforeData == 1)
> + 		dumpObjFlags = REQ_SCHEMA_BEFORE_DATA;
> + 
> + 	if (use_schemaAfterData == 1)
> + 		dumpObjFlags = REQ_SCHEMA_AFTER_DATA;
> + 
> + 	if (schemaOnly)
> + 		dumpObjFlags = (REQ_SCHEMA_BEFORE_DATA | REQ_SCHEMA_AFTER_DATA);
> ***************
> 
> It wouldn't kill to be consistant between testing for '== 1' and just
> checking for non-zero.  Again, not really a big deal, and I wouldn't
> mention these if there weren't other issues.

OK

> ***************
> *** 646,652 ****
>   	 * Dumping blobs is now default unless we saw an inclusion switch or -s
>   	 * ... but even if we did see one of these, -b turns it back on.
>   	 */
> ! 	if (include_everything && !schemaOnly)
>   		outputBlobs = true;
>   
>   	/*
> --- 689,695 ----
>   	 * Dumping blobs is now default unless we saw an inclusion switch or -s
>   	 * ... but even if we did see one of these, -b turns it back on.
>   	 */
> ! 	if (include_everything && WANT_PRE_SCHEMA(dumpObjFlags))
>   		outputBlobs = true;
>   
>   	/*
> ***************
> 
> Shouldn't this change be to "WANT_DATA(dumpObjFlags)"?  That's what most
> of the '!schemaOnly' get translated to.  Otherwise I think you would be
> getting blobs when you've asked for just schema-before-data, which
> doesn't seem like it'd make much sense.

Yes, fixed

> ***************
> *** 712,718 ****
>   	dumpStdStrings(g_fout);
>   
>   	/* The database item is always next, unless we don't want it at all */
> ! 	if (include_everything && !dataOnly)
>   		dumpDatabase(g_fout);
>   
>   	/* Now the rearrangeable objects. */
> --- 755,761 ----
>   	dumpStdStrings(g_fout);
>   
>   	/* The database item is always next, unless we don't want it at all */
> ! 	if (include_everything && WANT_DATA(dumpObjFlags))
>   		dumpDatabase(g_fout);
>   
>   	/* Now the rearrangeable objects. */
> ***************
> 
> Shouldn't this be 'WANT_PRE_SCHEMA(dumpObjFlags)'?

Yes, fixed

> ***************
> *** 3414,3420 ****
>   			continue;
>   
>   		/* Ignore indexes of tables not to be dumped */
> ! 		if (!tbinfo->dobj.dump)
>   			continue;
>   
>   		if (g_verbose)
> --- 3459,3465 ----
>   			continue;
>   
>   		/* Ignore indexes of tables not to be dumped */
> ! 		if (!tbinfo->dobj.dump || !WANT_POST_SCHEMA(dumpObjFlags))
>   			continue;
>   
>   		if (g_verbose)
> ***************
> 
> I didn't test this, but it strikes me as an unnecessary addition?  If
> anything, wouldn't this check make more sense being done right after
> dropping into getIndexes()?  No sense going through the loop just for
> fun..  Technically, it's a behavioral change for --data-only since it
> used to gather index information anyway, but it's a good optimization if
> done in the right place.

Agreed. I've just removed this. Patch not about optimising logic.

> Also around here, there doesn't appear to be any checking in
> dumpEnumType(), which strikes me as odd.  Wouldn't that deserve a
> 
> if (!WANT_PRE_SCHEMA(dumpObjFlags))
> 	return;
> 
> check?  If not even some kind of equivilant ->dobj.dump check..

Agreed. That appears to be a bug in pg_dump, since this would currently
dump enums if --data-only was specified, which in my understanding would
be wrong.

Have included this:

	/* Skip if not to be dumped */
	if (!tinfo->dobj.dump || !WANT_BEFORE_SCHEMA(dumpObjFlags))
		return;



> ***************
> *** 9803,9809 ****
>   					tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
>   	}
>   
> ! 	if (!schemaOnly)
>   	{
>   		resetPQExpBuffer(query);
>   		appendPQExpBuffer(query, "SELECT pg_catalog.setval(");
> --- 9848,9854 ----
>   					tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
>   	}
>   
> ! 	if (WANT_PRE_SCHEMA(dumpObjFlags))
>   	{
>   		resetPQExpBuffer(query);
>   		appendPQExpBuffer(query, "SELECT pg_catalog.setval(");
> ***************
> 
> This is a mistaken logic invert, which results in setval's not being
> dumped at all when pulling out each piece seperately.  It should be:
> 
> if (WANT_DATA(dumpObjFlags))
> 
> so that setval's are correctly included on the --data-only piece.  As
> --data-only previously existed, this would be a regression too.

OK, fixed.


> Index: src/bin/pg_dump/pg_restore.c
> ===================================================================
> RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/bin/pg_dump/pg_restore.c,v
> retrieving revision 1.88
> diff -c -r1.88 pg_restore.c
> *** src/bin/pg_dump/pg_restore.c	13 Apr 2008 03:49:22 -0000	1.88
> --- src/bin/pg_dump/pg_restore.c	23 Jul 2008 17:06:59 -0000
> + 	if (dataOnly)
> + 		dumpObjFlags = REQ_DATA;
> + 
> + 	if (use_schemaBeforeData == 1)
> + 		dumpObjFlags = REQ_SCHEMA_BEFORE_DATA;
> + 
> + 	if (use_schemaAfterData == 1)
> + 		dumpObjFlags = REQ_SCHEMA_AFTER_DATA;
> + 
> + 	if (schemaOnly)
> + 		dumpObjFlags = (REQ_SCHEMA_BEFORE_DATA | REQ_SCHEMA_AFTER_DATA);
> + 
> ***************
> 
> Ditto previous comment on this, but in pg_restore.c.

OK

> 
> ***************
> *** 405,410 ****
> --- 455,462 ----
>   			 "                           do not restore data of tables that could not be\n"
>   			 "                           created\n"));
>   	printf(_("  --no-tablespaces         do not dump tablespace assignments\n"));
> + 	printf(_("  --schema-before-data	 dump only the part of schema before table data\n"));
> + 	printf(_("  --schema-after-data		 dump only the part of schema after table data\n"));
>   	printf(_("  --use-set-session-authorization\n"
>   			 "                           use SESSION AUTHORIZATION commands instead of\n"
>   			 "                           OWNER TO commands\n"));
> ***************
> 
> Forgot to mention this on pg_dump.c, but in both pg_dump and pg_restore,
> and I hate to be the bearer of bad news, but your command-line
> documentation doesn't line up properly in the output.  You shouldn't be
> using tabs there but instead should use spaces as the other help text
> does, so everything lines up nicely.

OK

-- 
 Simon Riggs           www.2ndQuadrant.com
 PostgreSQL Training, Services and Support


-- 
Sent via pgsql-patches mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches
pg_dump_beforeafter.v6.patch (text/x-patch, 68.8 KB)
Index: doc/src/sgml/ref/pg_dump.sgml
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/doc/src/sgml/ref/pg_dump.sgml,v
retrieving revision 1.103
diff -c -r1.103 pg_dump.sgml
*** doc/src/sgml/ref/pg_dump.sgml	20 Jul 2008 18:43:30 -0000	1.103
--- doc/src/sgml/ref/pg_dump.sgml	24 Jul 2008 07:30:19 -0000
***************
*** 133,139 ****
         <para>
          Include large objects in the dump.  This is the default behavior
          except when <option>--schema</>, <option>--table</>, or
!         <option>--schema-only</> is specified, so the <option>-b</>
          switch is only useful to add large objects to selective dumps.
         </para>
        </listitem>
--- 133,140 ----
         <para>
          Include large objects in the dump.  This is the default behavior
          except when <option>--schema</>, <option>--table</>, or
!         <option>--schema-only</> or <option>--schema-before-data</> or
!         <option>--schema-after-data</> is specified, so the <option>-b</>
          switch is only useful to add large objects to selective dumps.
         </para>
        </listitem>
***************
*** 426,431 ****
--- 427,452 ----
       </varlistentry>
  
       <varlistentry>
+       <term><option>--schema-before-data</option></term>
+       <listitem>
+        <para>
+ 		Dump object definitions (schema) that occur before table data,
+ 		using the order produced by a full dump.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><option>--schema-after-data</option></term>
+       <listitem>
+        <para>
+ 		Dump object definitions (schema) that occur after table data,
+ 		using the order produced by a full dump.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
        <term><option>-S <replaceable class="parameter">username</replaceable></option></term>
        <term><option>--superuser=<replaceable class="parameter">username</replaceable></option></term>
        <listitem>
***************
*** 790,795 ****
--- 811,844 ----
    </para>
  
    <para>
+    The output of <application>pg_dump</application> can be divided into three parts:
+    <itemizedlist>
+     <listitem>
+      <para>
+ 	  Before Data - objects output before data, which includes
+ 	  <command>CREATE TABLE</command> statements and others.
+ 	  This part can be requested using <option>--schema-before-data</>.
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+ 	  Table Data - data can be requested using <option>--data-only</>.
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+ 	  After Data - objects output after data, which includes
+ 	  <command>CREATE INDEX</command> statements and others.
+ 	  This part can be requested using <option>--schema-after-data</>.
+      </para>
+     </listitem>
+    </itemizedlist>
+    This allows us to work more easily with large data dump files when
+    there is some need to edit commands or resequence their execution for
+    performance.
+   </para>
+ 
+   <para>
     Because <application>pg_dump</application> is used to transfer data
     to newer versions of <productname>PostgreSQL</>, the output of
     <application>pg_dump</application> can be loaded into
Index: doc/src/sgml/ref/pg_restore.sgml
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/doc/src/sgml/ref/pg_restore.sgml,v
retrieving revision 1.75
diff -c -r1.75 pg_restore.sgml
*** doc/src/sgml/ref/pg_restore.sgml	13 Apr 2008 03:49:21 -0000	1.75
--- doc/src/sgml/ref/pg_restore.sgml	24 Jul 2008 07:30:19 -0000
***************
*** 321,326 ****
--- 321,346 ----
       </varlistentry>
  
       <varlistentry>
+       <term><option>--schema-before-data</option></term>
+       <listitem>
+        <para>
+ 		Restore object definitions (schema) that occur before table data,
+ 		using the order produced by a full restore.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><option>--schema-after-data</option></term>
+       <listitem>
+        <para>
+ 		Restore object definitions (schema) that occur after table data,
+ 		using the order produced by a full restore.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
        <term><option>-S <replaceable class="parameter">username</replaceable></option></term>
        <term><option>--superuser=<replaceable class="parameter">username</replaceable></option></term>
        <listitem>
***************
*** 572,577 ****
--- 592,626 ----
    </para>
  
    <para>
+    The actions of <application>pg_restore</application> can be 
+    divided into three parts:
+    <itemizedlist>
+     <listitem>
+      <para>
+ 	  Before Data - objects output before data, which includes
+ 	  <command>CREATE TABLE</command> statements and others.
+ 	  This part can be requested using <option>--schema-before-data</>.
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+ 	  Table Data - data can be requested using <option>--data-only</>.
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+ 	  After Data - objects output after data, which includes
+ 	  <command>CREATE INDEX</command> statements and others.
+ 	  This part can be requested using <option>--schema-after-data</>.
+      </para>
+     </listitem>
+    </itemizedlist>
+    This allows us to work more easily with large data dump files when
+    there is some need to edit commands or resequence their execution for
+    performance.
+   </para>
+ 
+   <para>
     The limitations of <application>pg_restore</application> are detailed below.
  
     <itemizedlist>
Index: src/bin/pg_dump/pg_backup.h
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/bin/pg_dump/pg_backup.h,v
retrieving revision 1.47
diff -c -r1.47 pg_backup.h
*** src/bin/pg_dump/pg_backup.h	13 Apr 2008 03:49:21 -0000	1.47
--- src/bin/pg_dump/pg_backup.h	24 Jul 2008 07:30:19 -0000
***************
*** 89,95 ****
  	int			use_setsessauth;/* Use SET SESSION AUTHORIZATION commands
  								 * instead of OWNER TO */
  	char	   *superuser;		/* Username to use as superuser */
! 	int			dataOnly;
  	int			dropSchema;
  	char	   *filename;
  	int			schemaOnly;
--- 89,95 ----
  	int			use_setsessauth;/* Use SET SESSION AUTHORIZATION commands
  								 * instead of OWNER TO */
  	char	   *superuser;		/* Username to use as superuser */
! 	int			dumpObjFlags;	/* which objects types to dump */
  	int			dropSchema;
  	char	   *filename;
  	int			schemaOnly;
Index: src/bin/pg_dump/pg_backup_archiver.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v
retrieving revision 1.157
diff -c -r1.157 pg_backup_archiver.c
*** src/bin/pg_dump/pg_backup_archiver.c	4 May 2008 08:32:21 -0000	1.157
--- src/bin/pg_dump/pg_backup_archiver.c	24 Jul 2008 07:30:19 -0000
***************
*** 56,62 ****
  static void _selectTablespace(ArchiveHandle *AH, const char *tablespace);
  static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te);
  static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te);
! static teReqs _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls);
  static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
  static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
  static TocEntry *getTocEntryByDumpId(ArchiveHandle *AH, DumpId id);
--- 56,62 ----
  static void _selectTablespace(ArchiveHandle *AH, const char *tablespace);
  static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te);
  static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te);
! static int _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls);
  static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
  static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
  static TocEntry *getTocEntryByDumpId(ArchiveHandle *AH, DumpId id);
***************
*** 129,135 ****
  {
  	ArchiveHandle *AH = (ArchiveHandle *) AHX;
  	TocEntry   *te;
! 	teReqs		reqs;
  	OutputContext sav;
  	bool		defnDumped;
  
--- 129,135 ----
  {
  	ArchiveHandle *AH = (ArchiveHandle *) AHX;
  	TocEntry   *te;
! 	int		reqs;
  	OutputContext sav;
  	bool		defnDumped;
  
***************
*** 175,193 ****
  	 * Work out if we have an implied data-only restore. This can happen if
  	 * the dump was data only or if the user has used a toc list to exclude
  	 * all of the schema data. All we do is look for schema entries - if none
! 	 * are found then we set the dataOnly flag.
  	 *
! 	 * We could scan for wanted TABLE entries, but that is not the same as
! 	 * dataOnly. At this stage, it seems unnecessary (6-Mar-2001).
  	 */
! 	if (!ropt->dataOnly)
  	{
  		int			impliedDataOnly = 1;
  
  		for (te = AH->toc->next; te != AH->toc; te = te->next)
  		{
  			reqs = _tocEntryRequired(te, ropt, true);
! 			if ((reqs & REQ_SCHEMA) != 0)
  			{					/* It's schema, and it's wanted */
  				impliedDataOnly = 0;
  				break;
--- 175,193 ----
  	 * Work out if we have an implied data-only restore. This can happen if
  	 * the dump was data only or if the user has used a toc list to exclude
  	 * all of the schema data. All we do is look for schema entries - if none
! 	 * are found then say we only want DATA type objects.
  	 *
! 	 * We could scan for wanted TABLE entries, but that is not the same.
! 	 * At this stage, it seems unnecessary (6-Mar-2001).
  	 */
! 	if (!WANT_DATA(ropt->dumpObjFlags))
  	{
  		int			impliedDataOnly = 1;
  
  		for (te = AH->toc->next; te != AH->toc; te = te->next)
  		{
  			reqs = _tocEntryRequired(te, ropt, true);
! 			if (WANT_SCHEMA_BEFORE_DATA(reqs) || WANT_SCHEMA_AFTER_DATA(reqs))
  			{					/* It's schema, and it's wanted */
  				impliedDataOnly = 0;
  				break;
***************
*** 195,201 ****
  		}
  		if (impliedDataOnly)
  		{
! 			ropt->dataOnly = impliedDataOnly;
  			ahlog(AH, 1, "implied data-only restore\n");
  		}
  	}
--- 195,201 ----
  		}
  		if (impliedDataOnly)
  		{
! 			ropt->dumpObjFlags = REQ_DATA;
  			ahlog(AH, 1, "implied data-only restore\n");
  		}
  	}
***************
*** 236,242 ****
  			AH->currentTE = te;
  
  			reqs = _tocEntryRequired(te, ropt, false /* needn't drop ACLs */ );
! 			if (((reqs & REQ_SCHEMA) != 0) && te->dropStmt)
  			{
  				/* We want the schema */
  				ahlog(AH, 1, "dropping %s %s\n", te->desc, te->tag);
--- 236,242 ----
  			AH->currentTE = te;
  
  			reqs = _tocEntryRequired(te, ropt, false /* needn't drop ACLs */ );
! 			if (((reqs & REQ_SCHEMA_BEFORE_DATA) != 0) && te->dropStmt)
  			{
  				/* We want the schema */
  				ahlog(AH, 1, "dropping %s %s\n", te->desc, te->tag);
***************
*** 278,284 ****
  		/* Dump any relevant dump warnings to stderr */
  		if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0)
  		{
! 			if (!ropt->dataOnly && te->defn != NULL && strlen(te->defn) != 0)
  				write_msg(modulename, "warning from original dump file: %s\n", te->defn);
  			else if (te->copyStmt != NULL && strlen(te->copyStmt) != 0)
  				write_msg(modulename, "warning from original dump file: %s\n", te->copyStmt);
--- 278,284 ----
  		/* Dump any relevant dump warnings to stderr */
  		if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0)
  		{
! 			if (!WANT_DATA(ropt->dumpObjFlags) && te->defn != NULL && strlen(te->defn) != 0)
  				write_msg(modulename, "warning from original dump file: %s\n", te->defn);
  			else if (te->copyStmt != NULL && strlen(te->copyStmt) != 0)
  				write_msg(modulename, "warning from original dump file: %s\n", te->copyStmt);
***************
*** 286,292 ****
  
  		defnDumped = false;
  
! 		if ((reqs & REQ_SCHEMA) != 0)	/* We want the schema */
  		{
  			ahlog(AH, 1, "creating %s %s\n", te->desc, te->tag);
  
--- 286,293 ----
  
  		defnDumped = false;
  
! 		if ((WANT_SCHEMA_BEFORE_DATA(reqs) && WANT_SCHEMA_BEFORE_DATA(ropt->dumpObjFlags)) ||
! 			(WANT_SCHEMA_AFTER_DATA(reqs) && WANT_SCHEMA_AFTER_DATA(ropt->dumpObjFlags)))	/* We want the schema */
  		{
  			ahlog(AH, 1, "creating %s %s\n", te->desc, te->tag);
  
***************
*** 331,337 ****
  		/*
  		 * If we have a data component, then process it
  		 */
! 		if ((reqs & REQ_DATA) != 0)
  		{
  			/*
  			 * hadDumper will be set if there is genuine data component for
--- 332,338 ----
  		/*
  		 * If we have a data component, then process it
  		 */
! 		if (WANT_DATA(reqs))
  		{
  			/*
  			 * hadDumper will be set if there is genuine data component for
***************
*** 343,349 ****
  				/*
  				 * If we can output the data, then restore it.
  				 */
! 				if (AH->PrintTocDataPtr !=NULL && (reqs & REQ_DATA) != 0)
  				{
  #ifndef HAVE_LIBZ
  					if (AH->compression != 0)
--- 344,350 ----
  				/*
  				 * If we can output the data, then restore it.
  				 */
! 				if (AH->PrintTocDataPtr !=NULL && WANT_DATA(reqs))
  				{
  #ifndef HAVE_LIBZ
  					if (AH->compression != 0)
***************
*** 415,421 ****
  		/* Work out what, if anything, we want from this entry */
  		reqs = _tocEntryRequired(te, ropt, true);
  
! 		if ((reqs & REQ_SCHEMA) != 0)	/* We want the schema */
  		{
  			ahlog(AH, 1, "setting owner and privileges for %s %s\n",
  				  te->desc, te->tag);
--- 416,422 ----
  		/* Work out what, if anything, we want from this entry */
  		reqs = _tocEntryRequired(te, ropt, true);
  
! 		if (WANT_SCHEMA_BEFORE_DATA(reqs))	/* We want the schema */
  		{
  			ahlog(AH, 1, "setting owner and privileges for %s %s\n",
  				  te->desc, te->tag);
***************
*** 473,479 ****
  _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
  {
  	/* This hack is only needed in a data-only restore */
! 	if (!ropt->dataOnly || !ropt->disable_triggers)
  		return;
  
  	ahlog(AH, 1, "disabling triggers for %s\n", te->tag);
--- 474,480 ----
  _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
  {
  	/* This hack is only needed in a data-only restore */
! 	if (!WANT_DATA(ropt->dumpObjFlags) || !ropt->disable_triggers)
  		return;
  
  	ahlog(AH, 1, "disabling triggers for %s\n", te->tag);
***************
*** 499,505 ****
  _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
  {
  	/* This hack is only needed in a data-only restore */
! 	if (!ropt->dataOnly || !ropt->disable_triggers)
  		return;
  
  	ahlog(AH, 1, "enabling triggers for %s\n", te->tag);
--- 500,506 ----
  _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
  {
  	/* This hack is only needed in a data-only restore */
! 	if (!WANT_DATA(ropt->dumpObjFlags) || !ropt->disable_triggers)
  		return;
  
  	ahlog(AH, 1, "enabling triggers for %s\n", te->tag);
***************
*** 1321,1327 ****
  	return NULL;
  }
  
! teReqs
  TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt)
  {
  	TocEntry   *te = getTocEntryByDumpId(AH, id);
--- 1322,1328 ----
  	return NULL;
  }
  
! int
  TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt)
  {
  	TocEntry   *te = getTocEntryByDumpId(AH, id);
***************
*** 2026,2035 ****
  					 te->defn);
  }
  
! static teReqs
  _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
  {
! 	teReqs		res = REQ_ALL;
  
  	/* ENCODING and STDSTRINGS items are dumped specially, so always reject */
  	if (strcmp(te->desc, "ENCODING") == 0 ||
--- 2027,2036 ----
  					 te->defn);
  }
  
! static int
  _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
  {
! 	int		res = ropt->dumpObjFlags;
  
  	/* ENCODING and STDSTRINGS items are dumped specially, so always reject */
  	if (strcmp(te->desc, "ENCODING") == 0 ||
***************
*** 2109,2125 ****
  	if ((strcmp(te->desc, "<Init>") == 0) && (strcmp(te->tag, "Max OID") == 0))
  		return 0;
  
- 	/* Mask it if we only want schema */
- 	if (ropt->schemaOnly)
- 		res = res & REQ_SCHEMA;
- 
- 	/* Mask it we only want data */
- 	if (ropt->dataOnly)
- 		res = res & REQ_DATA;
- 
  	/* Mask it if we don't have a schema contribution */
  	if (!te->defn || strlen(te->defn) == 0)
! 		res = res & ~REQ_SCHEMA;
  
  	/* Finally, if there's a per-ID filter, limit based on that as well */
  	if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1])
--- 2110,2118 ----
  	if ((strcmp(te->desc, "<Init>") == 0) && (strcmp(te->tag, "Max OID") == 0))
  		return 0;
  
  	/* Mask it if we don't have a schema contribution */
  	if (!te->defn || strlen(te->defn) == 0)
! 		res = res & ~(REQ_SCHEMA_BEFORE_DATA | REQ_SCHEMA_AFTER_DATA);
  
  	/* Finally, if there's a per-ID filter, limit based on that as well */
  	if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1])
Index: src/bin/pg_dump/pg_backup_archiver.h
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/bin/pg_dump/pg_backup_archiver.h,v
retrieving revision 1.76
diff -c -r1.76 pg_backup_archiver.h
*** src/bin/pg_dump/pg_backup_archiver.h	7 Nov 2007 12:24:24 -0000	1.76
--- src/bin/pg_dump/pg_backup_archiver.h	24 Jul 2008 07:30:19 -0000
***************
*** 158,169 ****
  	STAGE_FINALIZING
  } ArchiverStage;
  
! typedef enum
! {
! 	REQ_SCHEMA = 1,
! 	REQ_DATA = 2,
! 	REQ_ALL = REQ_SCHEMA + REQ_DATA
! } teReqs;
  
  typedef struct _archiveHandle
  {
--- 158,173 ----
  	STAGE_FINALIZING
  } ArchiverStage;
  
! #define REQ_SCHEMA_BEFORE_DATA	(1 << 0)
! #define REQ_DATA				(1 << 1)
! #define REQ_SCHEMA_AFTER_DATA	(1 << 2)
! #define REQ_ALL					(REQ_SCHEMA_BEFORE_DATA + REQ_DATA + REQ_SCHEMA_AFTER_DATA)
! 
! #define WANT_SCHEMA_BEFORE_DATA(req)	((req & REQ_SCHEMA_BEFORE_DATA) == REQ_SCHEMA_BEFORE_DATA)
! #define WANT_DATA(req)					((req & REQ_DATA) == REQ_DATA)
! #define WANT_SCHEMA_AFTER_DATA(req)		((req & REQ_SCHEMA_AFTER_DATA) == REQ_SCHEMA_AFTER_DATA)
! #define WANT_ALL(req)					((req & REQ_ALL) == REQ_ALL)
! 
  
  typedef struct _archiveHandle
  {
***************
*** 317,323 ****
  extern void ReadToc(ArchiveHandle *AH);
  extern void WriteDataChunks(ArchiveHandle *AH);
  
! extern teReqs TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt);
  extern bool checkSeek(FILE *fp);
  
  #define appendStringLiteralAHX(buf,str,AH) \
--- 321,327 ----
  extern void ReadToc(ArchiveHandle *AH);
  extern void WriteDataChunks(ArchiveHandle *AH);
  
! extern int TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt);
  extern bool checkSeek(FILE *fp);
  
  #define appendStringLiteralAHX(buf,str,AH) \
Index: src/bin/pg_dump/pg_dump.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/bin/pg_dump/pg_dump.c,v
retrieving revision 1.497
diff -c -r1.497 pg_dump.c
*** src/bin/pg_dump/pg_dump.c	20 Jul 2008 18:43:30 -0000	1.497
--- src/bin/pg_dump/pg_dump.c	24 Jul 2008 07:35:28 -0000
***************
*** 73,78 ****
--- 73,82 ----
  bool		aclsSkip;
  const char *lockWaitTimeout;
  
+ /* groups of objects: default is we dump all groups */
+ 
+ int			dumpObjFlags;
+ 
  /* subquery used to convert user ID (eg, datdba) to user name */
  static const char *username_subquery;
  
***************
*** 227,232 ****
--- 231,238 ----
  	static int	disable_triggers = 0;
  	static int  outputNoTablespaces = 0;
  	static int	use_setsessauth = 0;
+ 	static int	schemaBeforeData;
+ 	static int	schemaAfterData;
  
  	static struct option long_options[] = {
  		{"data-only", no_argument, NULL, 'a'},
***************
*** 267,272 ****
--- 273,280 ----
  		{"disable-triggers", no_argument, &disable_triggers, 1},
  		{"lock-wait-timeout", required_argument, NULL, 2},
  		{"no-tablespaces", no_argument, &outputNoTablespaces, 1},
+  		{"schema-before-data", no_argument, &schemaBeforeData, 1},
+  		{"schema-after-data", no_argument, &schemaAfterData, 1},
  		{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
  
  		{NULL, 0, NULL, 0}
***************
*** 420,425 ****
--- 428,437 ----
  					disable_triggers = 1;
  				else if (strcmp(optarg, "no-tablespaces") == 0)
  					outputNoTablespaces = 1;
+ 				else if (strcmp(optarg, "schema-before-data") == 0)
+ 					schemaBeforeData = 1;
+ 				else if (strcmp(optarg, "schema-after-data") == 0)
+ 					schemaAfterData = 1;
  				else if (strcmp(optarg, "use-set-session-authorization") == 0)
  					use_setsessauth = 1;
  				else
***************
*** 464,474 ****
  	if (optind < argc)
  		dbname = argv[optind];
  
! 	if (dataOnly && schemaOnly)
  	{
! 		write_msg(NULL, "options -s/--schema-only and -a/--data-only cannot be used together\n");
  		exit(1);
  	}
  
  	if (dataOnly && outputClean)
  	{
--- 476,521 ----
  	if (optind < argc)
  		dbname = argv[optind];
  
! 	/*
! 	 * Look for conflicting options relating to object groupings
! 	 */
! 	if (schemaOnly && dataOnly)
! 	{
! 		write_msg(NULL, "options %s and %s cannot be used together\n",
! 				"-s/--schema-only", "-a/--data-only");
! 		exit(1);
! 	}
! 	else if ((schemaOnly || dataOnly) && 
! 				(schemaBeforeData || schemaAfterData))
  	{
! 		write_msg(NULL, "options %s and %s cannot be used together\n",
! 				schemaOnly ? "-s/--schema-only" : "-a/--data-only",
! 				schemaBeforeData ? "--schema-before-data" : "--schema-after-data");
  		exit(1);
  	}
+ 	else if (schemaBeforeData && schemaAfterData)
+ 	{
+ 		write_msg(NULL, "options %s and %s cannot be used together\n",
+ 				"--schema-before-data", "--schema-after-data");
+ 		exit(1);
+ 	}
+ 
+ 	/*
+ 	 * Decide which of the object groups we will dump
+ 	 */
+ 	dumpObjFlags = REQ_ALL;
+ 
+ 	if (dataOnly)
+ 		dumpObjFlags = REQ_DATA;
+ 
+ 	if (schemaBeforeData)
+ 		dumpObjFlags = REQ_SCHEMA_BEFORE_DATA;
+ 
+ 	if (schemaAfterData)
+ 		dumpObjFlags = REQ_SCHEMA_AFTER_DATA;
+ 
+ 	if (schemaOnly)
+ 		dumpObjFlags = (REQ_SCHEMA_BEFORE_DATA | REQ_SCHEMA_AFTER_DATA);
  
  	if (dataOnly && outputClean)
  	{
***************
*** 646,652 ****
  	 * Dumping blobs is now default unless we saw an inclusion switch or -s
  	 * ... but even if we did see one of these, -b turns it back on.
  	 */
! 	if (include_everything && !schemaOnly)
  		outputBlobs = true;
  
  	/*
--- 693,699 ----
  	 * Dumping blobs is now default unless we saw an inclusion switch or -s
  	 * ... but even if we did see one of these, -b turns it back on.
  	 */
! 	if (include_everything && WANT_DATA(dumpObjFlags))
  		outputBlobs = true;
  
  	/*
***************
*** 658,664 ****
  	if (g_fout->remoteVersion < 80400)
  		guessConstraintInheritance(tblinfo, numTables);
  
! 	if (!schemaOnly)
  		getTableData(tblinfo, numTables, oids);
  
  	if (outputBlobs && hasBlobs(g_fout))
--- 705,711 ----
  	if (g_fout->remoteVersion < 80400)
  		guessConstraintInheritance(tblinfo, numTables);
  
! 	if (WANT_DATA(dumpObjFlags))
  		getTableData(tblinfo, numTables, oids);
  
  	if (outputBlobs && hasBlobs(g_fout))
***************
*** 712,718 ****
  	dumpStdStrings(g_fout);
  
  	/* The database item is always next, unless we don't want it at all */
! 	if (include_everything && !dataOnly)
  		dumpDatabase(g_fout);
  
  	/* Now the rearrangeable objects. */
--- 759,765 ----
  	dumpStdStrings(g_fout);
  
  	/* The database item is always next, unless we don't want it at all */
! 	if (include_everything && WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		dumpDatabase(g_fout);
  
  	/* Now the rearrangeable objects. */
***************
*** 734,740 ****
  		ropt->noTablespace = outputNoTablespaces;
  		ropt->disable_triggers = disable_triggers;
  		ropt->use_setsessauth = use_setsessauth;
! 		ropt->dataOnly = dataOnly;
  
  		if (compressLevel == -1)
  			ropt->compression = 0;
--- 781,787 ----
  		ropt->noTablespace = outputNoTablespaces;
  		ropt->disable_triggers = disable_triggers;
  		ropt->use_setsessauth = use_setsessauth;
! 		ropt->dumpObjFlags = dumpObjFlags;
  
  		if (compressLevel == -1)
  			ropt->compression = 0;
***************
*** 792,797 ****
--- 839,846 ----
  	printf(_("  --disable-dollar-quoting    disable dollar quoting, use SQL standard quoting\n"));
  	printf(_("  --disable-triggers          disable triggers during data-only restore\n"));
  	printf(_("  --no-tablespaces            do not dump tablespace assignments\n"));
+ 	printf(_("  --schema-before-data        dump only the part of schema before table data\n"));
+ 	printf(_("  --schema-after-data         dump only the part of schema after table data\n"));
  	printf(_("  --use-set-session-authorization\n"
  			 "                              use SESSION AUTHORIZATION commands instead of\n"
  	"                              ALTER OWNER commands to set ownership\n"));
***************
*** 5165,5171 ****
  	int			ncomments;
  
  	/* Comments are SCHEMA not data */
! 	if (dataOnly)
  		return;
  
  	/* Search for comments associated with catalogId, using table */
--- 5214,5220 ----
  	int			ncomments;
  
  	/* Comments are SCHEMA not data */
! 	if (!WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	/* Search for comments associated with catalogId, using table */
***************
*** 5216,5222 ****
  	PQExpBuffer target;
  
  	/* Comments are SCHEMA not data */
! 	if (dataOnly)
  		return;
  
  	/* Search for comments associated with relation, using table */
--- 5265,5271 ----
  	PQExpBuffer target;
  
  	/* Comments are SCHEMA not data */
! 	if (!WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	/* Search for comments associated with relation, using table */
***************
*** 5568,5574 ****
  	char	   *qnspname;
  
  	/* Skip if not to be dumped */
! 	if (!nspinfo->dobj.dump || dataOnly)
  		return;
  
  	/* don't dump dummy namespace from pre-7.3 source */
--- 5617,5623 ----
  	char	   *qnspname;
  
  	/* Skip if not to be dumped */
! 	if (!nspinfo->dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	/* don't dump dummy namespace from pre-7.3 source */
***************
*** 5617,5623 ****
  dumpType(Archive *fout, TypeInfo *tinfo)
  {
  	/* Skip if not to be dumped */
! 	if (!tinfo->dobj.dump || dataOnly)
  		return;
  
  	/* Dump out in proper style */
--- 5666,5672 ----
  dumpType(Archive *fout, TypeInfo *tinfo)
  {
  	/* Skip if not to be dumped */
! 	if (!tinfo->dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	/* Dump out in proper style */
***************
*** 5646,5651 ****
--- 5695,5704 ----
  				i;
  	char	   *label;
  
+ 	/* Skip if not to be dumped */
+ 	if (!tinfo->dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
+ 		return;
+ 
  	/* Set proper schema search path so regproc references list correctly */
  	selectSourceSchema(tinfo->dobj.namespace->dobj.name);
  
***************
*** 6262,6268 ****
  	PQExpBuffer q;
  
  	/* Skip if not to be dumped */
! 	if (!stinfo->dobj.dump || dataOnly)
  		return;
  
  	q = createPQExpBuffer();
--- 6315,6321 ----
  	PQExpBuffer q;
  
  	/* Skip if not to be dumped */
! 	if (!stinfo->dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	q = createPQExpBuffer();
***************
*** 6309,6315 ****
  	if (!include_everything)
  		return false;
  	/* And they're schema not data */
! 	if (dataOnly)
  		return false;
  	return true;
  }
--- 6362,6368 ----
  	if (!include_everything)
  		return false;
  	/* And they're schema not data */
! 	if (!WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return false;
  	return true;
  }
***************
*** 6330,6336 ****
  	FuncInfo   *funcInfo;
  	FuncInfo   *validatorInfo = NULL;
  
! 	if (dataOnly)
  		return;
  
  	/*
--- 6383,6389 ----
  	FuncInfo   *funcInfo;
  	FuncInfo   *validatorInfo = NULL;
  
! 	if (!WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	/*
***************
*** 6590,6596 ****
  	int			i;
  
  	/* Skip if not to be dumped */
! 	if (!finfo->dobj.dump || dataOnly)
  		return;
  
  	query = createPQExpBuffer();
--- 6643,6649 ----
  	int			i;
  
  	/* Skip if not to be dumped */
! 	if (!finfo->dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	query = createPQExpBuffer();
***************
*** 6985,6991 ****
  	TypeInfo   *sourceInfo;
  	TypeInfo   *targetInfo;
  
! 	if (dataOnly)
  		return;
  
  	if (OidIsValid(cast->castfunc))
--- 7038,7044 ----
  	TypeInfo   *sourceInfo;
  	TypeInfo   *targetInfo;
  
! 	if (!WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	if (OidIsValid(cast->castfunc))
***************
*** 7135,7141 ****
  	char	   *oprcanhash;
  
  	/* Skip if not to be dumped */
! 	if (!oprinfo->dobj.dump || dataOnly)
  		return;
  
  	/*
--- 7188,7194 ----
  	char	   *oprcanhash;
  
  	/* Skip if not to be dumped */
! 	if (!oprinfo->dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	/*
***************
*** 7519,7525 ****
  	int			i;
  
  	/* Skip if not to be dumped */
! 	if (!opcinfo->dobj.dump || dataOnly)
  		return;
  
  	/*
--- 7572,7578 ----
  	int			i;
  
  	/* Skip if not to be dumped */
! 	if (!opcinfo->dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	/*
***************
*** 7827,7833 ****
  	int			i;
  
  	/* Skip if not to be dumped */
! 	if (!opfinfo->dobj.dump || dataOnly)
  		return;
  
  	/*
--- 7880,7886 ----
  	int			i;
  
  	/* Skip if not to be dumped */
! 	if (!opfinfo->dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	/*
***************
*** 8096,8102 ****
  	bool		condefault;
  
  	/* Skip if not to be dumped */
! 	if (!convinfo->dobj.dump || dataOnly)
  		return;
  
  	query = createPQExpBuffer();
--- 8149,8155 ----
  	bool		condefault;
  
  	/* Skip if not to be dumped */
! 	if (!convinfo->dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	query = createPQExpBuffer();
***************
*** 8250,8256 ****
  	bool		convertok;
  
  	/* Skip if not to be dumped */
! 	if (!agginfo->aggfn.dobj.dump || dataOnly)
  		return;
  
  	query = createPQExpBuffer();
--- 8303,8309 ----
  	bool		convertok;
  
  	/* Skip if not to be dumped */
! 	if (!agginfo->aggfn.dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	query = createPQExpBuffer();
***************
*** 8453,8459 ****
  	PQExpBuffer delq;
  
  	/* Skip if not to be dumped */
! 	if (!prsinfo->dobj.dump || dataOnly)
  		return;
  
  	q = createPQExpBuffer();
--- 8506,8512 ----
  	PQExpBuffer delq;
  
  	/* Skip if not to be dumped */
! 	if (!prsinfo->dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	q = createPQExpBuffer();
***************
*** 8522,8528 ****
  	char	   *tmplname;
  
  	/* Skip if not to be dumped */
! 	if (!dictinfo->dobj.dump || dataOnly)
  		return;
  
  	q = createPQExpBuffer();
--- 8575,8581 ----
  	char	   *tmplname;
  
  	/* Skip if not to be dumped */
! 	if (!dictinfo->dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	q = createPQExpBuffer();
***************
*** 8607,8613 ****
  	PQExpBuffer delq;
  
  	/* Skip if not to be dumped */
! 	if (!tmplinfo->dobj.dump || dataOnly)
  		return;
  
  	q = createPQExpBuffer();
--- 8660,8666 ----
  	PQExpBuffer delq;
  
  	/* Skip if not to be dumped */
! 	if (!tmplinfo->dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	q = createPQExpBuffer();
***************
*** 8673,8679 ****
  	int			i_dictname;
  
  	/* Skip if not to be dumped */
! 	if (!cfginfo->dobj.dump || dataOnly)
  		return;
  
  	q = createPQExpBuffer();
--- 8726,8732 ----
  	int			i_dictname;
  
  	/* Skip if not to be dumped */
! 	if (!cfginfo->dobj.dump || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	q = createPQExpBuffer();
***************
*** 8809,8815 ****
  	PQExpBuffer sql;
  
  	/* Do nothing if ACL dump is not enabled */
! 	if (dataOnly || aclsSkip)
  		return;
  
  	sql = createPQExpBuffer();
--- 8862,8868 ----
  	PQExpBuffer sql;
  
  	/* Do nothing if ACL dump is not enabled */
! 	if (!WANT_SCHEMA_BEFORE_DATA(dumpObjFlags) || aclsSkip)
  		return;
  
  	sql = createPQExpBuffer();
***************
*** 8846,8852 ****
  	{
  		if (tbinfo->relkind == RELKIND_SEQUENCE)
  			dumpSequence(fout, tbinfo);
! 		else if (!dataOnly)
  			dumpTableSchema(fout, tbinfo);
  
  		/* Handle the ACL here */
--- 8899,8905 ----
  	{
  		if (tbinfo->relkind == RELKIND_SEQUENCE)
  			dumpSequence(fout, tbinfo);
! 		else if (WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  			dumpTableSchema(fout, tbinfo);
  
  		/* Handle the ACL here */
***************
*** 9153,9159 ****
  	PQExpBuffer delq;
  
  	/* Only print it if "separate" mode is selected */
! 	if (!tbinfo->dobj.dump || !adinfo->separate || dataOnly)
  		return;
  
  	/* Don't print inherited defaults, either */
--- 9206,9212 ----
  	PQExpBuffer delq;
  
  	/* Only print it if "separate" mode is selected */
! 	if (!tbinfo->dobj.dump || !adinfo->separate || !WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  		return;
  
  	/* Don't print inherited defaults, either */
***************
*** 9238,9244 ****
  	PQExpBuffer q;
  	PQExpBuffer delq;
  
! 	if (dataOnly)
  		return;
  
  	q = createPQExpBuffer();
--- 9291,9297 ----
  	PQExpBuffer q;
  	PQExpBuffer delq;
  
! 	if (!WANT_SCHEMA_AFTER_DATA(dumpObjFlags))
  		return;
  
  	q = createPQExpBuffer();
***************
*** 9307,9313 ****
  	PQExpBuffer delq;
  
  	/* Skip if not to be dumped */
! 	if (!coninfo->dobj.dump || dataOnly)
  		return;
  
  	q = createPQExpBuffer();
--- 9360,9366 ----
  	PQExpBuffer delq;
  
  	/* Skip if not to be dumped */
! 	if (!coninfo->dobj.dump || !WANT_SCHEMA_AFTER_DATA(dumpObjFlags))
  		return;
  
  	q = createPQExpBuffer();
***************
*** 9700,9706 ****
  	 *
  	 * Add a 'SETVAL(seq, last_val, iscalled)' as part of a "data" dump.
  	 */
! 	if (!dataOnly)
  	{
  		resetPQExpBuffer(delqry);
  
--- 9753,9759 ----
  	 *
  	 * Add a 'SETVAL(seq, last_val, iscalled)' as part of a "data" dump.
  	 */
! 	if (WANT_SCHEMA_BEFORE_DATA(dumpObjFlags))
  	{
  		resetPQExpBuffer(delqry);
  
***************
*** 9803,9809 ****
  					tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
  	}
  
! 	if (!schemaOnly)
  	{
  		resetPQExpBuffer(query);
  		appendPQExpBuffer(query, "SELECT pg_catalog.setval(");
--- 9856,9862 ----
  					tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
  	}
  
! 	if (WANT_DATA(dumpObjFlags))
  	{
  		resetPQExpBuffer(query);
  		appendPQExpBuffer(query, "SELECT pg_catalog.setval(");
***************
*** 9836,9842 ****
  	const char *p;
  	int			findx;
  
! 	if (dataOnly)
  		return;
  
  	query = createPQExpBuffer();
--- 9889,9895 ----
  	const char *p;
  	int			findx;
  
! 	if (!WANT_SCHEMA_AFTER_DATA(dumpObjFlags))
  		return;
  
  	query = createPQExpBuffer();
***************
*** 10044,10050 ****
  	PGresult   *res;
  
  	/* Skip if not to be dumped */
! 	if (!rinfo->dobj.dump || dataOnly)
  		return;
  
  	/*
--- 10097,10103 ----
  	PGresult   *res;
  
  	/* Skip if not to be dumped */
! 	if (!rinfo->dobj.dump || !WANT_SCHEMA_AFTER_DATA(dumpObjFlags))
  		return;
  
  	/*
Index: src/bin/pg_dump/pg_restore.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/bin/pg_dump/pg_restore.c,v
retrieving revision 1.88
diff -c -r1.88 pg_restore.c
*** src/bin/pg_dump/pg_restore.c	13 Apr 2008 03:49:22 -0000	1.88
--- src/bin/pg_dump/pg_restore.c	24 Jul 2008 07:30:19 -0000
***************
*** 78,83 ****
--- 78,90 ----
  	static int	no_data_for_failed_tables = 0;
  	static int  outputNoTablespaces = 0;
  	static int	use_setsessauth = 0;
+  	bool		dataOnly = false;
+  	bool		schemaOnly = false;
+  
+  	static int	schemaBeforeData;
+  	static int	schemaAfterData;
+  
+  	int			dumpObjFlags;
  
  	struct option cmdopts[] = {
  		{"clean", 0, NULL, 'c'},
***************
*** 114,119 ****
--- 121,128 ----
  		{"disable-triggers", no_argument, &disable_triggers, 1},
  		{"no-data-for-failed-tables", no_argument, &no_data_for_failed_tables, 1},
  		{"no-tablespaces", no_argument, &outputNoTablespaces, 1},
+  		{"schema-before-data", no_argument, &schemaBeforeData, 1},
+  		{"schema-after-data", no_argument, &schemaAfterData, 1},
  		{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
  
  		{NULL, 0, NULL, 0}
***************
*** 145,151 ****
  		switch (c)
  		{
  			case 'a':			/* Dump data only */
! 				opts->dataOnly = 1;
  				break;
  			case 'c':			/* clean (i.e., drop) schema prior to create */
  				opts->dropSchema = 1;
--- 154,160 ----
  		switch (c)
  		{
  			case 'a':			/* Dump data only */
! 				dataOnly = true;
  				break;
  			case 'c':			/* clean (i.e., drop) schema prior to create */
  				opts->dropSchema = 1;
***************
*** 213,219 ****
  				opts->triggerNames = strdup(optarg);
  				break;
  			case 's':			/* dump schema only */
! 				opts->schemaOnly = 1;
  				break;
  			case 'S':			/* Superuser username */
  				if (strlen(optarg) != 0)
--- 222,228 ----
  				opts->triggerNames = strdup(optarg);
  				break;
  			case 's':			/* dump schema only */
! 				schemaOnly = true;
  				break;
  			case 'S':			/* Superuser username */
  				if (strlen(optarg) != 0)
***************
*** 249,254 ****
--- 258,267 ----
  					no_data_for_failed_tables = 1;
  				else if (strcmp(optarg, "no-tablespaces") == 0)
  					outputNoTablespaces = 1;
+ 				else if (strcmp(optarg, "schema-before-data") == 0)
+ 					schemaBeforeData = 1;
+ 				else if (strcmp(optarg, "schema-after-data") == 0)
+ 					schemaAfterData = 1;
  				else if (strcmp(optarg, "use-set-session-authorization") == 0)
  					use_setsessauth = 1;
  				else
***************
*** 295,300 ****
--- 308,354 ----
  		opts->useDB = 1;
  	}
  
+ 	/*
+ 	 * Look for conflicting options relating to object groupings
+ 	 */
+ 	if (schemaOnly && dataOnly)
+ 	{
+ 		write_msg(NULL, "options %s and %s cannot be used together\n",
+ 				"-s/--schema-only", "-a/--data-only");
+ 		exit(1);
+ 	}
+ 	else if ((schemaOnly || dataOnly) && 
+ 				(schemaBeforeData || schemaAfterData))
+ 	{
+ 		write_msg(NULL, "options %s and %s cannot be used together\n",
+ 				schemaOnly ? "-s/--schema-only" : "-a/--data-only",
+ 				schemaBeforeData ? "--schema-before-data" : "--schema-after-data");
+ 		exit(1);
+ 	}
+ 	else if (schemaBeforeData && schemaAfterData)
+ 	{
+ 		write_msg(NULL, "options %s and %s cannot be used together\n",
+ 				"--schema-before-data", "--schema-after-data");
+ 		exit(1);
+ 	}
+ 
+ 	/*
+ 	 * Decide which of the object groups we will dump
+ 	 */
+ 	dumpObjFlags = REQ_ALL;
+ 
+ 	if (dataOnly)
+ 		dumpObjFlags = REQ_DATA;
+ 
+ 	if (schemaBeforeData)
+ 		dumpObjFlags = REQ_SCHEMA_BEFORE_DATA;
+ 
+ 	if (schemaAfterData)
+ 		dumpObjFlags = REQ_SCHEMA_AFTER_DATA;
+ 
+ 	if (schemaOnly)
+ 		dumpObjFlags = (REQ_SCHEMA_BEFORE_DATA | REQ_SCHEMA_AFTER_DATA);
+ 
  	opts->disable_triggers = disable_triggers;
  	opts->noDataForFailedTables = no_data_for_failed_tables;
  	opts->noTablespace = outputNoTablespaces;
***************
*** 405,410 ****
--- 459,466 ----
  			 "                           do not restore data of tables that could not be\n"
  			 "                           created\n"));
  	printf(_("  --no-tablespaces         do not dump tablespace assignments\n"));
+ 	printf(_("  --schema-before-data     dump only the part of schema before table data\n"));
+ 	printf(_("  --schema-after-data      dump only the part of schema after table data\n"));
  	printf(_("  --use-set-session-authorization\n"
  			 "                           use SESSION AUTHORIZATION commands instead of\n"
  			 "                           OWNER TO commands\n"));
Index: src/interfaces/ecpg/preproc/keywords.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/interfaces/ecpg/preproc/keywords.c,v
retrieving revision 1.85
diff -c -r1.85 keywords.c
*** src/interfaces/ecpg/preproc/keywords.c	1 Jan 2008 19:45:59 -0000	1.85
--- src/interfaces/ecpg/preproc/keywords.c	18 Jul 2008 08:50:27 -0000
***************
*** 1,430 ****
  /*-------------------------------------------------------------------------
   *
   * keywords.c
!  *	  lexical token lookup for reserved words in PostgreSQL
   *
   * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   *
   * IDENTIFICATION
!  *	  $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.84 2007/11/15 21:14:45 momjian Exp $
   *
   *-------------------------------------------------------------------------
   */
- #include "postgres_fe.h"
- 
- #include <ctype.h>
  
! #include "extern.h"
! #include "preproc.h"
  
! /* compile both keyword lists in one file because they are always scanned together */
! #include "ecpg_keywords.c"
  
  /*
!  * List of (keyword-name, keyword-token-value) pairs.
!  *
!  * !!WARNING!!: This list must be sorted, because binary
!  *		 search is used to locate entries.
   */
! static const ScanKeyword ScanPGSQLKeywords[] = {
! 	/* name, value */
! 	{"abort", ABORT_P},
! 	{"absolute", ABSOLUTE_P},
! 	{"access", ACCESS},
! 	{"action", ACTION},
! 	{"add", ADD_P},
! 	{"admin", ADMIN},
! 	{"after", AFTER},
! 	{"aggregate", AGGREGATE},
! 	{"all", ALL},
! 	{"also", ALSO},
! 	{"alter", ALTER},
! 	{"always", ALWAYS},
! 	{"analyse", ANALYSE},		/* British spelling */
! 	{"analyze", ANALYZE},
! 	{"and", AND},
! 	{"any", ANY},
! 	{"array", ARRAY},
! 	{"as", AS},
! 	{"asc", ASC},
! 	{"assertion", ASSERTION},
! 	{"assignment", ASSIGNMENT},
! 	{"asymmetric", ASYMMETRIC},
! 	{"at", AT},
! 	{"authorization", AUTHORIZATION},
! 	{"backward", BACKWARD},
! 	{"before", BEFORE},
! 	{"begin", BEGIN_P},
! 	{"between", BETWEEN},
! 	{"bigint", BIGINT},
! 	{"binary", BINARY},
! 	{"bit", BIT},
! 	{"boolean", BOOLEAN_P},
! 	{"both", BOTH},
! 	{"by", BY},
! 	{"cache", CACHE},
! 	{"called", CALLED},
! 	{"cascade", CASCADE},
! 	{"cascaded", CASCADED},
! 	{"case", CASE},
! 	{"cast", CAST},
! 	{"chain", CHAIN},
! 	{"char", CHAR_P},
! 	{"character", CHARACTER},
! 	{"characteristics", CHARACTERISTICS},
! 	{"check", CHECK},
! 	{"checkpoint", CHECKPOINT},
! 	{"class", CLASS},
! 	{"close", CLOSE},
! 	{"cluster", CLUSTER},
! 	{"coalesce", COALESCE},
! 	{"collate", COLLATE},
! 	{"column", COLUMN},
! 	{"comment", COMMENT},
! 	{"commit", COMMIT},
! 	{"committed", COMMITTED},
! 	{"concurrently", CONCURRENTLY},
! 	{"configuration", CONFIGURATION},
! 	{"connection", CONNECTION},
! 	{"constraint", CONSTRAINT},
! 	{"constraints", CONSTRAINTS},
! 	{"content", CONTENT_P},
! 	{"conversion", CONVERSION_P},
! 	{"copy", COPY},
! 	{"cost", COST},
! 	{"create", CREATE},
! 	{"createdb", CREATEDB},
! 	{"createrole", CREATEROLE},
! 	{"createuser", CREATEUSER},
! 	{"cross", CROSS},
! 	{"csv", CSV},
! 	{"current", CURRENT_P},
! 	{"current_date", CURRENT_DATE},
! 	{"current_role", CURRENT_ROLE},
! 	{"current_time", CURRENT_TIME},
! 	{"current_timestamp", CURRENT_TIMESTAMP},
! 	{"cursor", CURSOR},
! 	{"cycle", CYCLE},
! 	{"database", DATABASE},
! 	{"day", DAY_P},
! 	{"deallocate", DEALLOCATE},
! 	{"dec", DEC},
! 	{"decimal", DECIMAL_P},
! 	{"declare", DECLARE},
! 	{"default", DEFAULT},
! 	{"defaults", DEFAULTS},
! 	{"deferrable", DEFERRABLE},
! 	{"deferred", DEFERRED},
! 	{"definer", DEFINER},
! 	{"delete", DELETE_P},
! 	{"delimiter", DELIMITER},
! 	{"delimiters", DELIMITERS},
! 	{"desc", DESC},
! 	{"dictionary", DICTIONARY},
! 	{"disable", DISABLE_P},
! 	{"discard", DISCARD},
! 	{"distinct", DISTINCT},
! 	{"do", DO},
! 	{"document", DOCUMENT_P},
! 	{"domain", DOMAIN_P},
! 	{"double", DOUBLE_P},
! 	{"drop", DROP},
! 	{"each", EACH},
! 	{"else", ELSE},
! 	{"enable", ENABLE_P},
! 	{"encoding", ENCODING},
! 	{"encrypted", ENCRYPTED},
! 	{"end", END_P},
! 	{"enum", ENUM_P},
! 	{"escape", ESCAPE},
! 	{"except", EXCEPT},
! 	{"excluding", EXCLUDING},
! 	{"exclusive", EXCLUSIVE},
! 	{"execute", EXECUTE},
! 	{"exists", EXISTS},
! 	{"explain", EXPLAIN},
! 	{"external", EXTERNAL},
! 	{"extract", EXTRACT},
! 	{"false", FALSE_P},
! 	{"family", FAMILY},
! 	{"fetch", FETCH},
! 	{"first", FIRST_P},
! 	{"float", FLOAT_P},
! 	{"for", FOR},
! 	{"force", FORCE},
! 	{"foreign", FOREIGN},
! 	{"forward", FORWARD},
! 	{"freeze", FREEZE},
! 	{"from", FROM},
! 	{"full", FULL},
! 	{"function", FUNCTION},
! 	{"get", GET},
! 	{"global", GLOBAL},
! 	{"grant", GRANT},
! 	{"granted", GRANTED},
! 	{"greatest", GREATEST},
! 	{"group", GROUP_P},
! 	{"handler", HANDLER},
! 	{"having", HAVING},
! 	{"header", HEADER_P},
! 	{"hold", HOLD},
! 	{"hour", HOUR_P},
! 	{"if", IF_P},
! 	{"ilike", ILIKE},
! 	{"immediate", IMMEDIATE},
! 	{"immutable", IMMUTABLE},
! 	{"implicit", IMPLICIT_P},
! 	{"in", IN_P},
! 	{"including", INCLUDING},
! 	{"increment", INCREMENT},
! 	{"index", INDEX},
! 	{"indexes", INDEXES},
! 	{"inherit", INHERIT},
! 	{"inherits", INHERITS},
! 	{"initially", INITIALLY},
! 	{"inner", INNER_P},
! 	{"inout", INOUT},
! 	{"input", INPUT_P},
! 	{"insensitive", INSENSITIVE},
! 	{"insert", INSERT},
! 	{"instead", INSTEAD},
! 	{"int", INT_P},
! 	{"integer", INTEGER},
! 	{"intersect", INTERSECT},
! 	{"interval", INTERVAL},
! 	{"into", INTO},
! 	{"invoker", INVOKER},
! 	{"is", IS},
! 	{"isnull", ISNULL},
! 	{"isolation", ISOLATION},
! 	{"join", JOIN},
! 	{"key", KEY},
! 	{"lancompiler", LANCOMPILER},
! 	{"language", LANGUAGE},
! 	{"large", LARGE_P},
! 	{"last", LAST_P},
! 	{"leading", LEADING},
! 	{"least", LEAST},
! 	{"left", LEFT},
! 	{"level", LEVEL},
! 	{"like", LIKE},
! 	{"limit", LIMIT},
! 	{"listen", LISTEN},
! 	{"load", LOAD},
! 	{"local", LOCAL},
! 	{"location", LOCATION},
! 	{"lock", LOCK_P},
! 	{"login", LOGIN_P},
! 	{"mapping", MAPPING},
! 	{"match", MATCH},
! 	{"maxvalue", MAXVALUE},
! 	{"minute", MINUTE_P},
! 	{"minvalue", MINVALUE},
! 	{"mode", MODE},
! 	{"month", MONTH_P},
! 	{"move", MOVE},
! 	{"name", NAME_P},
! 	{"names", NAMES},
! 	{"national", NATIONAL},
! 	{"natural", NATURAL},
! 	{"nchar", NCHAR},
! 	{"new", NEW},
! 	{"next", NEXT},
! 	{"no", NO},
! 	{"nocreatedb", NOCREATEDB},
! 	{"nocreaterole", NOCREATEROLE},
! 	{"nocreateuser", NOCREATEUSER},
! 	{"noinherit", NOINHERIT},
! 	{"nologin", NOLOGIN_P},
! 	{"none", NONE},
! 	{"nosuperuser", NOSUPERUSER},
! 	{"not", NOT},
! 	{"nothing", NOTHING},
! 	{"notify", NOTIFY},
! 	{"notnull", NOTNULL},
! 	{"nowait", NOWAIT},
! 	{"null", NULL_P},
! 	{"nullif", NULLIF},
! 	{"nulls", NULLS_P},
! 	{"numeric", NUMERIC},
! 	{"object", OBJECT_P},
! 	{"of", OF},
! 	{"off", OFF},
! 	{"offset", OFFSET},
! 	{"oids", OIDS},
! 	{"old", OLD},
! 	{"on", ON},
! 	{"only", ONLY},
! 	{"operator", OPERATOR},
! 	{"option", OPTION},
! 	{"or", OR},
! 	{"order", ORDER},
! 	{"out", OUT_P},
! 	{"outer", OUTER_P},
! 	{"overlaps", OVERLAPS},
! 	{"owned", OWNED},
! 	{"owner", OWNER},
! 	{"parser", PARSER},
! 	{"partial", PARTIAL},
! 	{"password", PASSWORD},
! 	{"placing", PLACING},
! 	{"plans", PLANS},
! 	{"position", POSITION},
! 	{"precision", PRECISION},
! 	{"prepare", PREPARE},
! 	{"prepared", PREPARED},
! 	{"preserve", PRESERVE},
! 	{"primary", PRIMARY},
! 	{"prior", PRIOR},
! 	{"privileges", PRIVILEGES},
! 	{"procedural", PROCEDURAL},
! 	{"procedure", PROCEDURE},
! 	{"quote", QUOTE},
! 	{"read", READ},
! 	{"real", REAL},
! 	{"reassign", REASSIGN},
! 	{"recheck", RECHECK},
! 	{"references", REFERENCES},
! 	{"reindex", REINDEX},
! 	{"relative", RELATIVE_P},
! 	{"release", RELEASE},
! 	{"rename", RENAME},
! 	{"repeatable", REPEATABLE},
! 	{"replace", REPLACE},
! 	{"replica", REPLICA},
! 	{"reset", RESET},
! 	{"restart", RESTART},
! 	{"restrict", RESTRICT},
! 	{"returning", RETURNING},
! 	{"returns", RETURNS},
! 	{"revoke", REVOKE},
! 	{"right", RIGHT},
! 	{"role", ROLE},
! 	{"rollback", ROLLBACK},
! 	{"row", ROW},
! 	{"rows", ROWS},
! 	{"rule", RULE},
! 	{"savepoint", SAVEPOINT},
! 	{"schema", SCHEMA},
! 	{"scroll", SCROLL},
! 	{"search", SEARCH},
! 	{"second", SECOND_P},
! 	{"security", SECURITY},
! 	{"select", SELECT},
! 	{"sequence", SEQUENCE},
! 	{"serializable", SERIALIZABLE},
! 	{"session", SESSION},
! 	{"session_user", SESSION_USER},
! 	{"set", SET},
! 	{"setof", SETOF},
! 	{"share", SHARE},
! 	{"show", SHOW},
! 	{"similar", SIMILAR},
! 	{"simple", SIMPLE},
! 	{"smallint", SMALLINT},
! 	{"some", SOME},
! 	{"stable", STABLE},
! 	{"standalone", STANDALONE_P},
! 	{"start", START},
! 	{"statement", STATEMENT},
! 	{"statistics", STATISTICS},
! 	{"stdin", STDIN},
! 	{"stdout", STDOUT},
! 	{"storage", STORAGE},
! 	{"strict", STRICT_P},
! 	{"strip", STRIP_P},
! 	{"substring", SUBSTRING},
! 	{"superuser", SUPERUSER_P},
! 	{"symmetric", SYMMETRIC},
! 	{"sysid", SYSID},
! 	{"system", SYSTEM_P},
! 	{"table", TABLE},
! 	{"tablespace", TABLESPACE},
! 	{"temp", TEMP},
! 	{"template", TEMPLATE},
! 	{"temporary", TEMPORARY},
! 	{"text", TEXT_P},
! 	{"then", THEN},
! 	{"time", TIME},
! 	{"timestamp", TIMESTAMP},
! 	{"to", TO},
! 	{"trailing", TRAILING},
! 	{"transaction", TRANSACTION},
! 	{"treat", TREAT},
! 	{"trigger", TRIGGER},
! 	{"trim", TRIM},
! 	{"true", TRUE_P},
! 	{"truncate", TRUNCATE},
! 	{"trusted", TRUSTED},
! 	{"type", TYPE_P},
! 	{"uncommitted", UNCOMMITTED},
! 	{"unencrypted", UNENCRYPTED},
! 	{"union", UNION},
! 	{"unique", UNIQUE},
! 	{"unknown", UNKNOWN},
! 	{"unlisten", UNLISTEN},
! 	{"until", UNTIL},
! 	{"update", UPDATE},
! 	{"user", USER},
! 	{"using", USING},
! 	{"vacuum", VACUUM},
! 	{"valid", VALID},
! 	{"validator", VALIDATOR},
! 	{"value", VALUE_P},
! 	{"values", VALUES},
! 	{"varchar", VARCHAR},
! 	{"varying", VARYING},
! 	{"verbose", VERBOSE},
! 	{"version", VERSION_P},
! 	{"view", VIEW},
! 	{"volatile", VOLATILE},
! 	{"when", WHEN},
! 	{"where", WHERE},
! 	{"whitespace", WHITESPACE_P},
! 	{"with", WITH},
! 	{"without", WITHOUT},
! 	{"work", WORK},
! 	{"write", WRITE},
! 	{"xml", XML_P},
! 	{"xmlattributes", XMLATTRIBUTES},
! 	{"xmlconcat", XMLCONCAT},
! 	{"xmlelement", XMLELEMENT},
! 	{"xmlforest", XMLFOREST},
! 	{"xmlparse", XMLPARSE},
! 	{"xmlpi", XMLPI},
! 	{"xmlroot", XMLROOT},
! 	{"xmlserialize", XMLSERIALIZE},
! 	{"year", YEAR_P},
! 	{"yes", YES_P},
! 	{"zone", ZONE},
! };
  
  
  /*
!  * Now do a binary search using plain strcmp() comparison.
   */
! const ScanKeyword *
! DoLookup(char *word, const ScanKeyword *low, const ScanKeyword *high)
! {
! 	while (low <= high)
! 	{
! 		const ScanKeyword *middle;
! 		int			difference;
  
! 		middle = low + (high - low) / 2;
! 		difference = strcmp(middle->name, word);
! 		if (difference == 0)
! 			return middle;
! 		else if (difference < 0)
! 			low = middle + 1;
! 		else
! 			high = middle - 1;
! 	}
  
! 	return NULL;
! }
  
  /*
   * ScanKeywordLookup - see if a given word is a keyword
--- 1,436 ----
  /*-------------------------------------------------------------------------
   *
   * keywords.c
!  *	  lexical token lookup for key words in PostgreSQL
!  *
!  * NB: This file is also used by pg_dump.
!  *
   *
   * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   *
   * IDENTIFICATION
!  *	  $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.198 2008/07/03 20:58:46 tgl Exp $
   *
   *-------------------------------------------------------------------------
   */
  
! /* Use c.h so that this file can be built in either frontend or backend */
! #include "c.h"
  
! #include <ctype.h>
  
  /*
!  * This macro definition overrides the YYSTYPE union definition in parse.h.
!  * We don't need that struct in this file, and including the real definition
!  * would require sucking in some backend-only include files.
   */
! #define YYSTYPE int
  
+ #include "parser/keywords.h"
+ #ifndef ECPG_COMPILE
+ #include "parser/parse.h"
+ #else
+ #include "preproc.h"
+ #endif
  
  /*
!  * List of keyword (name, token-value, category) entries.
!  *
!  * !!WARNING!!: This list must be sorted by ASCII name, because binary
!  *		 search is used to locate entries.
   */
! const ScanKeyword ScanKeywords[] = {
! 	/* name, value, category */
! 	{"abort", ABORT_P, UNRESERVED_KEYWORD},
! 	{"absolute", ABSOLUTE_P, UNRESERVED_KEYWORD},
! 	{"access", ACCESS, UNRESERVED_KEYWORD},
! 	{"action", ACTION, UNRESERVED_KEYWORD},
! 	{"add", ADD_P, UNRESERVED_KEYWORD},
! 	{"admin", ADMIN, UNRESERVED_KEYWORD},
! 	{"after", AFTER, UNRESERVED_KEYWORD},
! 	{"aggregate", AGGREGATE, UNRESERVED_KEYWORD},
! 	{"all", ALL, RESERVED_KEYWORD},
! 	{"also", ALSO, UNRESERVED_KEYWORD},
! 	{"alter", ALTER, UNRESERVED_KEYWORD},
! 	{"always", ALWAYS, UNRESERVED_KEYWORD},
! 	{"analyse", ANALYSE, RESERVED_KEYWORD},		/* British spelling */
! 	{"analyze", ANALYZE, RESERVED_KEYWORD},
! 	{"and", AND, RESERVED_KEYWORD},
! 	{"any", ANY, RESERVED_KEYWORD},
! 	{"array", ARRAY, RESERVED_KEYWORD},
! 	{"as", AS, RESERVED_KEYWORD},
! 	{"asc", ASC, RESERVED_KEYWORD},
! 	{"assertion", ASSERTION, UNRESERVED_KEYWORD},
! 	{"assignment", ASSIGNMENT, UNRESERVED_KEYWORD},
! 	{"asymmetric", ASYMMETRIC, RESERVED_KEYWORD},
! 	{"at", AT, UNRESERVED_KEYWORD},
! 	{"authorization", AUTHORIZATION, TYPE_FUNC_NAME_KEYWORD},
! 	{"backward", BACKWARD, UNRESERVED_KEYWORD},
! 	{"before", BEFORE, UNRESERVED_KEYWORD},
! 	{"begin", BEGIN_P, UNRESERVED_KEYWORD},
! 	{"between", BETWEEN, TYPE_FUNC_NAME_KEYWORD},
! 	{"bigint", BIGINT, COL_NAME_KEYWORD},
! 	{"binary", BINARY, TYPE_FUNC_NAME_KEYWORD},
! 	{"bit", BIT, COL_NAME_KEYWORD},
! 	{"boolean", BOOLEAN_P, COL_NAME_KEYWORD},
! 	{"both", BOTH, RESERVED_KEYWORD},
! 	{"by", BY, UNRESERVED_KEYWORD},
! 	{"cache", CACHE, UNRESERVED_KEYWORD},
! 	{"called", CALLED, UNRESERVED_KEYWORD},
! 	{"cascade", CASCADE, UNRESERVED_KEYWORD},
! 	{"cascaded", CASCADED, UNRESERVED_KEYWORD},
! 	{"case", CASE, RESERVED_KEYWORD},
! 	{"cast", CAST, RESERVED_KEYWORD},
! 	{"chain", CHAIN, UNRESERVED_KEYWORD},
! 	{"char", CHAR_P, COL_NAME_KEYWORD},
! 	{"character", CHARACTER, COL_NAME_KEYWORD},
! 	{"characteristics", CHARACTERISTICS, UNRESERVED_KEYWORD},
! 	{"check", CHECK, RESERVED_KEYWORD},
! 	{"checkpoint", CHECKPOINT, UNRESERVED_KEYWORD},
! 	{"class", CLASS, UNRESERVED_KEYWORD},
! 	{"close", CLOSE, UNRESERVED_KEYWORD},
! 	{"cluster", CLUSTER, UNRESERVED_KEYWORD},
! 	{"coalesce", COALESCE, COL_NAME_KEYWORD},
! 	{"collate", COLLATE, RESERVED_KEYWORD},
! 	{"column", COLUMN, RESERVED_KEYWORD},
! 	{"comment", COMMENT, UNRESERVED_KEYWORD},
! 	{"commit", COMMIT, UNRESERVED_KEYWORD},
! 	{"committed", COMMITTED, UNRESERVED_KEYWORD},
! 	{"concurrently", CONCURRENTLY, UNRESERVED_KEYWORD},
! 	{"configuration", CONFIGURATION, UNRESERVED_KEYWORD},
! 	{"connection", CONNECTION, UNRESERVED_KEYWORD},
! 	{"constraint", CONSTRAINT, RESERVED_KEYWORD},
! 	{"constraints", CONSTRAINTS, UNRESERVED_KEYWORD},
! 	{"content", CONTENT_P, UNRESERVED_KEYWORD},
! 	{"continue", CONTINUE_P, UNRESERVED_KEYWORD},
! 	{"conversion", CONVERSION_P, UNRESERVED_KEYWORD},
! 	{"copy", COPY, UNRESERVED_KEYWORD},
! 	{"cost", COST, UNRESERVED_KEYWORD},
! 	{"create", CREATE, RESERVED_KEYWORD},
! 	{"createdb", CREATEDB, UNRESERVED_KEYWORD},
! 	{"createrole", CREATEROLE, UNRESERVED_KEYWORD},
! 	{"createuser", CREATEUSER, UNRESERVED_KEYWORD},
! 	{"cross", CROSS, TYPE_FUNC_NAME_KEYWORD},
! 	{"csv", CSV, UNRESERVED_KEYWORD},
! 	{"current", CURRENT_P, UNRESERVED_KEYWORD},
! 	{"current_date", CURRENT_DATE, RESERVED_KEYWORD},
! 	{"current_role", CURRENT_ROLE, RESERVED_KEYWORD},
! 	{"current_time", CURRENT_TIME, RESERVED_KEYWORD},
! 	{"current_timestamp", CURRENT_TIMESTAMP, RESERVED_KEYWORD},
! 	{"current_user", CURRENT_USER, RESERVED_KEYWORD},
! 	{"cursor", CURSOR, UNRESERVED_KEYWORD},
! 	{"cycle", CYCLE, UNRESERVED_KEYWORD},
! 	{"database", DATABASE, UNRESERVED_KEYWORD},
! 	{"day", DAY_P, UNRESERVED_KEYWORD},
! 	{"deallocate", DEALLOCATE, UNRESERVED_KEYWORD},
! 	{"dec", DEC, COL_NAME_KEYWORD},
! 	{"decimal", DECIMAL_P, COL_NAME_KEYWORD},
! 	{"declare", DECLARE, UNRESERVED_KEYWORD},
! 	{"default", DEFAULT, RESERVED_KEYWORD},
! 	{"defaults", DEFAULTS, UNRESERVED_KEYWORD},
! 	{"deferrable", DEFERRABLE, RESERVED_KEYWORD},
! 	{"deferred", DEFERRED, UNRESERVED_KEYWORD},
! 	{"definer", DEFINER, UNRESERVED_KEYWORD},
! 	{"delete", DELETE_P, UNRESERVED_KEYWORD},
! 	{"delimiter", DELIMITER, UNRESERVED_KEYWORD},
! 	{"delimiters", DELIMITERS, UNRESERVED_KEYWORD},
! 	{"desc", DESC, RESERVED_KEYWORD},
! 	{"dictionary", DICTIONARY, UNRESERVED_KEYWORD},
! 	{"disable", DISABLE_P, UNRESERVED_KEYWORD},
! 	{"discard", DISCARD, UNRESERVED_KEYWORD},
! 	{"distinct", DISTINCT, RESERVED_KEYWORD},
! 	{"do", DO, RESERVED_KEYWORD},
! 	{"document", DOCUMENT_P, UNRESERVED_KEYWORD},
! 	{"domain", DOMAIN_P, UNRESERVED_KEYWORD},
! 	{"double", DOUBLE_P, UNRESERVED_KEYWORD},
! 	{"drop", DROP, UNRESERVED_KEYWORD},
! 	{"each", EACH, UNRESERVED_KEYWORD},
! 	{"else", ELSE, RESERVED_KEYWORD},
! 	{"enable", ENABLE_P, UNRESERVED_KEYWORD},
! 	{"encoding", ENCODING, UNRESERVED_KEYWORD},
! 	{"encrypted", ENCRYPTED, UNRESERVED_KEYWORD},
! 	{"end", END_P, RESERVED_KEYWORD},
! 	{"enum", ENUM_P, UNRESERVED_KEYWORD},
! 	{"escape", ESCAPE, UNRESERVED_KEYWORD},
! 	{"except", EXCEPT, RESERVED_KEYWORD},
! 	{"excluding", EXCLUDING, UNRESERVED_KEYWORD},
! 	{"exclusive", EXCLUSIVE, UNRESERVED_KEYWORD},
! 	{"execute", EXECUTE, UNRESERVED_KEYWORD},
! 	{"exists", EXISTS, COL_NAME_KEYWORD},
! 	{"explain", EXPLAIN, UNRESERVED_KEYWORD},
! 	{"external", EXTERNAL, UNRESERVED_KEYWORD},
! 	{"extract", EXTRACT, COL_NAME_KEYWORD},
! 	{"false", FALSE_P, RESERVED_KEYWORD},
! 	{"family", FAMILY, UNRESERVED_KEYWORD},
! 	{"fetch", FETCH, UNRESERVED_KEYWORD},
! 	{"first", FIRST_P, UNRESERVED_KEYWORD},
! 	{"float", FLOAT_P, COL_NAME_KEYWORD},
! 	{"for", FOR, RESERVED_KEYWORD},
! 	{"force", FORCE, UNRESERVED_KEYWORD},
! 	{"foreign", FOREIGN, RESERVED_KEYWORD},
! 	{"forward", FORWARD, UNRESERVED_KEYWORD},
! 	{"freeze", FREEZE, TYPE_FUNC_NAME_KEYWORD},
! 	{"from", FROM, RESERVED_KEYWORD},
! 	{"full", FULL, TYPE_FUNC_NAME_KEYWORD},
! 	{"function", FUNCTION, UNRESERVED_KEYWORD},
! 	{"global", GLOBAL, UNRESERVED_KEYWORD},
! 	{"grant", GRANT, RESERVED_KEYWORD},
! 	{"granted", GRANTED, UNRESERVED_KEYWORD},
! 	{"greatest", GREATEST, COL_NAME_KEYWORD},
! 	{"group", GROUP_P, RESERVED_KEYWORD},
! 	{"handler", HANDLER, UNRESERVED_KEYWORD},
! 	{"having", HAVING, RESERVED_KEYWORD},
! 	{"header", HEADER_P, UNRESERVED_KEYWORD},
! 	{"hold", HOLD, UNRESERVED_KEYWORD},
! 	{"hour", HOUR_P, UNRESERVED_KEYWORD},
! 	{"identity", IDENTITY_P, UNRESERVED_KEYWORD},
! 	{"if", IF_P, UNRESERVED_KEYWORD},
! 	{"ilike", ILIKE, TYPE_FUNC_NAME_KEYWORD},
! 	{"immediate", IMMEDIATE, UNRESERVED_KEYWORD},
! 	{"immutable", IMMUTABLE, UNRESERVED_KEYWORD},
! 	{"implicit", IMPLICIT_P, UNRESERVED_KEYWORD},
! 	{"in", IN_P, RESERVED_KEYWORD},
! 	{"including", INCLUDING, UNRESERVED_KEYWORD},
! 	{"increment", INCREMENT, UNRESERVED_KEYWORD},
! 	{"index", INDEX, UNRESERVED_KEYWORD},
! 	{"indexes", INDEXES, UNRESERVED_KEYWORD},
! 	{"inherit", INHERIT, UNRESERVED_KEYWORD},
! 	{"inherits", INHERITS, UNRESERVED_KEYWORD},
! 	{"initially", INITIALLY, RESERVED_KEYWORD},
! 	{"inner", INNER_P, TYPE_FUNC_NAME_KEYWORD},
! 	{"inout", INOUT, COL_NAME_KEYWORD},
! 	{"input", INPUT_P, UNRESERVED_KEYWORD},
! 	{"insensitive", INSENSITIVE, UNRESERVED_KEYWORD},
! 	{"insert", INSERT, UNRESERVED_KEYWORD},
! 	{"instead", INSTEAD, UNRESERVED_KEYWORD},
! 	{"int", INT_P, COL_NAME_KEYWORD},
! 	{"integer", INTEGER, COL_NAME_KEYWORD},
! 	{"intersect", INTERSECT, RESERVED_KEYWORD},
! 	{"interval", INTERVAL, COL_NAME_KEYWORD},
! 	{"into", INTO, RESERVED_KEYWORD},
! 	{"invoker", INVOKER, UNRESERVED_KEYWORD},
! 	{"is", IS, TYPE_FUNC_NAME_KEYWORD},
! 	{"isnull", ISNULL, TYPE_FUNC_NAME_KEYWORD},
! 	{"isolation", ISOLATION, UNRESERVED_KEYWORD},
! 	{"join", JOIN, TYPE_FUNC_NAME_KEYWORD},
! 	{"key", KEY, UNRESERVED_KEYWORD},
! 	{"lancompiler", LANCOMPILER, UNRESERVED_KEYWORD},
! 	{"language", LANGUAGE, UNRESERVED_KEYWORD},
! 	{"large", LARGE_P, UNRESERVED_KEYWORD},
! 	{"last", LAST_P, UNRESERVED_KEYWORD},
! 	{"leading", LEADING, RESERVED_KEYWORD},
! 	{"least", LEAST, COL_NAME_KEYWORD},
! 	{"left", LEFT, TYPE_FUNC_NAME_KEYWORD},
! 	{"level", LEVEL, UNRESERVED_KEYWORD},
! 	{"like", LIKE, TYPE_FUNC_NAME_KEYWORD},
! 	{"limit", LIMIT, RESERVED_KEYWORD},
! 	{"listen", LISTEN, UNRESERVED_KEYWORD},
! 	{"load", LOAD, UNRESERVED_KEYWORD},
! 	{"local", LOCAL, UNRESERVED_KEYWORD},
! 	{"localtime", LOCALTIME, RESERVED_KEYWORD},
! 	{"localtimestamp", LOCALTIMESTAMP, RESERVED_KEYWORD},
! 	{"location", LOCATION, UNRESERVED_KEYWORD},
! 	{"lock", LOCK_P, UNRESERVED_KEYWORD},
! 	{"login", LOGIN_P, UNRESERVED_KEYWORD},
! 	{"mapping", MAPPING, UNRESERVED_KEYWORD},
! 	{"match", MATCH, UNRESERVED_KEYWORD},
! 	{"maxvalue", MAXVALUE, UNRESERVED_KEYWORD},
! 	{"minute", MINUTE_P, UNRESERVED_KEYWORD},
! 	{"minvalue", MINVALUE, UNRESERVED_KEYWORD},
! 	{"mode", MODE, UNRESERVED_KEYWORD},
! 	{"month", MONTH_P, UNRESERVED_KEYWORD},
! 	{"move", MOVE, UNRESERVED_KEYWORD},
! 	{"name", NAME_P, UNRESERVED_KEYWORD},
! 	{"names", NAMES, UNRESERVED_KEYWORD},
! 	{"national", NATIONAL, COL_NAME_KEYWORD},
! 	{"natural", NATURAL, TYPE_FUNC_NAME_KEYWORD},
! 	{"nchar", NCHAR, COL_NAME_KEYWORD},
! 	{"new", NEW, RESERVED_KEYWORD},
! 	{"next", NEXT, UNRESERVED_KEYWORD},
! 	{"no", NO, UNRESERVED_KEYWORD},
! 	{"nocreatedb", NOCREATEDB, UNRESERVED_KEYWORD},
! 	{"nocreaterole", NOCREATEROLE, UNRESERVED_KEYWORD},
! 	{"nocreateuser", NOCREATEUSER, UNRESERVED_KEYWORD},
! 	{"noinherit", NOINHERIT, UNRESERVED_KEYWORD},
! 	{"nologin", NOLOGIN_P, UNRESERVED_KEYWORD},
! 	{"none", NONE, COL_NAME_KEYWORD},
! 	{"nosuperuser", NOSUPERUSER, UNRESERVED_KEYWORD},
! 	{"not", NOT, RESERVED_KEYWORD},
! 	{"nothing", NOTHING, UNRESERVED_KEYWORD},
! 	{"notify", NOTIFY, UNRESERVED_KEYWORD},
! 	{"notnull", NOTNULL, TYPE_FUNC_NAME_KEYWORD},
! 	{"nowait", NOWAIT, UNRESERVED_KEYWORD},
! 	{"null", NULL_P, RESERVED_KEYWORD},
! 	{"nullif", NULLIF, COL_NAME_KEYWORD},
! 	{"nulls", NULLS_P, UNRESERVED_KEYWORD},
! 	{"numeric", NUMERIC, COL_NAME_KEYWORD},
! 	{"object", OBJECT_P, UNRESERVED_KEYWORD},
! 	{"of", OF, UNRESERVED_KEYWORD},
! 	{"off", OFF, RESERVED_KEYWORD},
! 	{"offset", OFFSET, RESERVED_KEYWORD},
! 	{"oids", OIDS, UNRESERVED_KEYWORD},
! 	{"old", OLD, RESERVED_KEYWORD},
! 	{"on", ON, RESERVED_KEYWORD},
! 	{"only", ONLY, RESERVED_KEYWORD},
! 	{"operator", OPERATOR, UNRESERVED_KEYWORD},
! 	{"option", OPTION, UNRESERVED_KEYWORD},
! 	{"or", OR, RESERVED_KEYWORD},
! 	{"order", ORDER, RESERVED_KEYWORD},
! 	{"out", OUT_P, COL_NAME_KEYWORD},
! 	{"outer", OUTER_P, TYPE_FUNC_NAME_KEYWORD},
! 	{"overlaps", OVERLAPS, TYPE_FUNC_NAME_KEYWORD},
! 	{"overlay", OVERLAY, COL_NAME_KEYWORD},
! 	{"owned", OWNED, UNRESERVED_KEYWORD},
! 	{"owner", OWNER, UNRESERVED_KEYWORD},
! 	{"parser", PARSER, UNRESERVED_KEYWORD},
! 	{"partial", PARTIAL, UNRESERVED_KEYWORD},
! 	{"password", PASSWORD, UNRESERVED_KEYWORD},
! 	{"placing", PLACING, RESERVED_KEYWORD},
! 	{"plans", PLANS, UNRESERVED_KEYWORD},
! 	{"position", POSITION, COL_NAME_KEYWORD},
! 	{"precision", PRECISION, COL_NAME_KEYWORD},
! 	{"prepare", PREPARE, UNRESERVED_KEYWORD},
! 	{"prepared", PREPARED, UNRESERVED_KEYWORD},
! 	{"preserve", PRESERVE, UNRESERVED_KEYWORD},
! 	{"primary", PRIMARY, RESERVED_KEYWORD},
! 	{"prior", PRIOR, UNRESERVED_KEYWORD},
! 	{"privileges", PRIVILEGES, UNRESERVED_KEYWORD},
! 	{"procedural", PROCEDURAL, UNRESERVED_KEYWORD},
! 	{"procedure", PROCEDURE, UNRESERVED_KEYWORD},
! 	{"quote", QUOTE, UNRESERVED_KEYWORD},
! 	{"read", READ, UNRESERVED_KEYWORD},
! 	{"real", REAL, COL_NAME_KEYWORD},
! 	{"reassign", REASSIGN, UNRESERVED_KEYWORD},
! 	{"recheck", RECHECK, UNRESERVED_KEYWORD},
! 	{"references", REFERENCES, RESERVED_KEYWORD},
! 	{"reindex", REINDEX, UNRESERVED_KEYWORD},
! 	{"relative", RELATIVE_P, UNRESERVED_KEYWORD},
! 	{"release", RELEASE, UNRESERVED_KEYWORD},
! 	{"rename", RENAME, UNRESERVED_KEYWORD},
! 	{"repeatable", REPEATABLE, UNRESERVED_KEYWORD},
! 	{"replace", REPLACE, UNRESERVED_KEYWORD},
! 	{"replica", REPLICA, UNRESERVED_KEYWORD},
! 	{"reset", RESET, UNRESERVED_KEYWORD},
! 	{"restart", RESTART, UNRESERVED_KEYWORD},
! 	{"restrict", RESTRICT, UNRESERVED_KEYWORD},
! 	{"returning", RETURNING, RESERVED_KEYWORD},
! 	{"returns", RETURNS, UNRESERVED_KEYWORD},
! 	{"revoke", REVOKE, UNRESERVED_KEYWORD},
! 	{"right", RIGHT, TYPE_FUNC_NAME_KEYWORD},
! 	{"role", ROLE, UNRESERVED_KEYWORD},
! 	{"rollback", ROLLBACK, UNRESERVED_KEYWORD},
! 	{"row", ROW, COL_NAME_KEYWORD},
! 	{"rows", ROWS, UNRESERVED_KEYWORD},
! 	{"rule", RULE, UNRESERVED_KEYWORD},
! 	{"savepoint", SAVEPOINT, UNRESERVED_KEYWORD},
! 	{"schema", SCHEMA, UNRESERVED_KEYWORD},
! 	{"scroll", SCROLL, UNRESERVED_KEYWORD},
! 	{"search", SEARCH, UNRESERVED_KEYWORD},
! 	{"second", SECOND_P, UNRESERVED_KEYWORD},
! 	{"security", SECURITY, UNRESERVED_KEYWORD},
! 	{"select", SELECT, RESERVED_KEYWORD},
! 	{"sequence", SEQUENCE, UNRESERVED_KEYWORD},
! 	{"serializable", SERIALIZABLE, UNRESERVED_KEYWORD},
! 	{"session", SESSION, UNRESERVED_KEYWORD},
! 	{"session_user", SESSION_USER, RESERVED_KEYWORD},
! 	{"set", SET, UNRESERVED_KEYWORD},
! 	{"setof", SETOF, COL_NAME_KEYWORD},
! 	{"share", SHARE, UNRESERVED_KEYWORD},
! 	{"show", SHOW, UNRESERVED_KEYWORD},
! 	{"similar", SIMILAR, TYPE_FUNC_NAME_KEYWORD},
! 	{"simple", SIMPLE, UNRESERVED_KEYWORD},
! 	{"smallint", SMALLINT, COL_NAME_KEYWORD},
! 	{"some", SOME, RESERVED_KEYWORD},
! 	{"stable", STABLE, UNRESERVED_KEYWORD},
! 	{"standalone", STANDALONE_P, UNRESERVED_KEYWORD},
! 	{"start", START, UNRESERVED_KEYWORD},
! 	{"statement", STATEMENT, UNRESERVED_KEYWORD},
! 	{"statistics", STATISTICS, UNRESERVED_KEYWORD},
! 	{"stdin", STDIN, UNRESERVED_KEYWORD},
! 	{"stdout", STDOUT, UNRESERVED_KEYWORD},
! 	{"storage", STORAGE, UNRESERVED_KEYWORD},
! 	{"strict", STRICT_P, UNRESERVED_KEYWORD},
! 	{"strip", STRIP_P, UNRESERVED_KEYWORD},
! 	{"substring", SUBSTRING, COL_NAME_KEYWORD},
! 	{"superuser", SUPERUSER_P, UNRESERVED_KEYWORD},
! 	{"symmetric", SYMMETRIC, RESERVED_KEYWORD},
! 	{"sysid", SYSID, UNRESERVED_KEYWORD},
! 	{"system", SYSTEM_P, UNRESERVED_KEYWORD},
! 	{"table", TABLE, RESERVED_KEYWORD},
! 	{"tablespace", TABLESPACE, UNRESERVED_KEYWORD},
! 	{"temp", TEMP, UNRESERVED_KEYWORD},
! 	{"template", TEMPLATE, UNRESERVED_KEYWORD},
! 	{"temporary", TEMPORARY, UNRESERVED_KEYWORD},
! 	{"text", TEXT_P, UNRESERVED_KEYWORD},
! 	{"then", THEN, RESERVED_KEYWORD},
! 	{"time", TIME, COL_NAME_KEYWORD},
! 	{"timestamp", TIMESTAMP, COL_NAME_KEYWORD},
! 	{"to", TO, RESERVED_KEYWORD},
! 	{"trailing", TRAILING, RESERVED_KEYWORD},
! 	{"transaction", TRANSACTION, UNRESERVED_KEYWORD},
! 	{"treat", TREAT, COL_NAME_KEYWORD},
! 	{"trigger", TRIGGER, UNRESERVED_KEYWORD},
! 	{"trim", TRIM, COL_NAME_KEYWORD},
! 	{"true", TRUE_P, RESERVED_KEYWORD},
! 	{"truncate", TRUNCATE, UNRESERVED_KEYWORD},
! 	{"trusted", TRUSTED, UNRESERVED_KEYWORD},
! 	{"type", TYPE_P, UNRESERVED_KEYWORD},
! 	{"uncommitted", UNCOMMITTED, UNRESERVED_KEYWORD},
! 	{"unencrypted", UNENCRYPTED, UNRESERVED_KEYWORD},
! 	{"union", UNION, RESERVED_KEYWORD},
! 	{"unique", UNIQUE, RESERVED_KEYWORD},
! 	{"unknown", UNKNOWN, UNRESERVED_KEYWORD},
! 	{"unlisten", UNLISTEN, UNRESERVED_KEYWORD},
! 	{"until", UNTIL, UNRESERVED_KEYWORD},
! 	{"update", UPDATE, UNRESERVED_KEYWORD},
! 	{"user", USER, RESERVED_KEYWORD},
! 	{"using", USING, RESERVED_KEYWORD},
! 	{"vacuum", VACUUM, UNRESERVED_KEYWORD},
! 	{"valid", VALID, UNRESERVED_KEYWORD},
! 	{"validator", VALIDATOR, UNRESERVED_KEYWORD},
! 	{"value", VALUE_P, UNRESERVED_KEYWORD},
! 	{"values", VALUES, COL_NAME_KEYWORD},
! 	{"varchar", VARCHAR, COL_NAME_KEYWORD},
! 	{"variadic", VARIADIC, RESERVED_KEYWORD},
! 	{"varying", VARYING, UNRESERVED_KEYWORD},
! 	{"verbose", VERBOSE, TYPE_FUNC_NAME_KEYWORD},
! 	{"version", VERSION_P, UNRESERVED_KEYWORD},
! 	{"view", VIEW, UNRESERVED_KEYWORD},
! 	{"volatile", VOLATILE, UNRESERVED_KEYWORD},
! 	{"when", WHEN, RESERVED_KEYWORD},
! 	{"where", WHERE, RESERVED_KEYWORD},
! 	{"whitespace", WHITESPACE_P, UNRESERVED_KEYWORD},
  
! 	/*
! 	 * XXX we mark WITH as reserved to force it to be quoted in dumps, even
! 	 * though it is currently unreserved according to gram.y.  This is because
! 	 * we expect we'll have to make it reserved to implement SQL WITH clauses.
! 	 * If that patch manages to do without reserving WITH, adjust this entry
! 	 * at that time; in any case this should be back in sync with gram.y after
! 	 * WITH clauses are implemented.
! 	 */
! 	{"with", WITH, RESERVED_KEYWORD},
! 	{"without", WITHOUT, UNRESERVED_KEYWORD},
! 	{"work", WORK, UNRESERVED_KEYWORD},
! 	{"write", WRITE, UNRESERVED_KEYWORD},
! 	{"xml", XML_P, UNRESERVED_KEYWORD},
! 	{"xmlattributes", XMLATTRIBUTES, COL_NAME_KEYWORD},
! 	{"xmlconcat", XMLCONCAT, COL_NAME_KEYWORD},
! 	{"xmlelement", XMLELEMENT, COL_NAME_KEYWORD},
! 	{"xmlforest", XMLFOREST, COL_NAME_KEYWORD},
! 	{"xmlparse", XMLPARSE, COL_NAME_KEYWORD},
! 	{"xmlpi", XMLPI, COL_NAME_KEYWORD},
! 	{"xmlroot", XMLROOT, COL_NAME_KEYWORD},
! 	{"xmlserialize", XMLSERIALIZE, COL_NAME_KEYWORD},
! 	{"year", YEAR_P, UNRESERVED_KEYWORD},
! 	{"yes", YES_P, UNRESERVED_KEYWORD},
! 	{"zone", ZONE, UNRESERVED_KEYWORD},
! };
  
! /* End of ScanKeywords, for use elsewhere */
! const ScanKeyword *LastScanKeyword = endof(ScanKeywords);
  
  /*
   * ScanKeywordLookup - see if a given word is a keyword
***************
*** 439,450 ****
   * receive a different case-normalization mapping.
   */
  const ScanKeyword *
! ScanKeywordLookup(char *text)
  {
  	int			len,
  				i;
  	char		word[NAMEDATALEN];
! 	const ScanKeyword *res;
  
  	len = strlen(text);
  	/* We assume all keywords are shorter than NAMEDATALEN. */
--- 445,457 ----
   * receive a different case-normalization mapping.
   */
  const ScanKeyword *
! ScanKeywordLookup(const char *text)
  {
  	int			len,
  				i;
  	char		word[NAMEDATALEN];
! 	const ScanKeyword *low;
! 	const ScanKeyword *high;
  
  	len = strlen(text);
  	/* We assume all keywords are shorter than NAMEDATALEN. */
***************
*** 468,476 ****
  	/*
  	 * Now do a binary search using plain strcmp() comparison.
  	 */
! 	res = DoLookup(word, &ScanPGSQLKeywords[0], endof(ScanPGSQLKeywords) - 1);
! 	if (res)
! 		return res;
  
! 	return DoLookup(word, &ScanECPGKeywords[0], endof(ScanECPGKeywords) - 1);
  }
--- 475,496 ----
  	/*
  	 * Now do a binary search using plain strcmp() comparison.
  	 */
! 	low = &ScanKeywords[0];
! 	high = endof(ScanKeywords) - 1;
! 	while (low <= high)
! 	{
! 		const ScanKeyword *middle;
! 		int			difference;
  
! 		middle = low + (high - low) / 2;
! 		difference = strcmp(middle->name, word);
! 		if (difference == 0)
! 			return middle;
! 		else if (difference < 0)
! 			low = middle + 1;
! 		else
! 			high = middle - 1;
! 	}
! 
! 	return NULL;
  }