Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /repositories/postgreshome/cvs/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.437
diff -c -w -r1.437 func.sgml
*** doc/src/sgml/func.sgml	19 May 2008 18:08:15 -0000	1.437
--- doc/src/sgml/func.sgml	3 Jul 2008 07:01:47 -0000
***************
*** 10903,10908 ****
--- 10903,10914 ----
        </row>
  
        <row>
+        <entry><literal><function>pg_get_keywords</function>()</literal></entry>
+        <entry><type>setof record</type></entry>
+        <entry>list of keywords and their categories</entry>
+       </row>
+ 
+       <row>
         <entry><literal><function>pg_my_temp_schema</function>()</literal></entry>
         <entry><type>oid</type></entry>
         <entry>OID of session's temporary schema, or 0 if none</entry>
***************
*** 11044,11049 ****
--- 11050,11068 ----
     </para>

     <indexterm>
+     <primary>pg_get_keywords</primary>
+    </indexterm>
+
+    <para>
+     <function>pg_get_keywords</function> returns a set of records describing
+     the keywords recognized by the server. The <structfield>word</> column
+     contains the keyword and the <structfield>catcode</> column contains a
+     category code of 'U' for unreserved, 'C' for column name, 'T' for type
+     or function name or 'R' for reserved. The <structfield>catdesc</>
+     column contains a localized string describing the category.
+    </para>
+
+    <indexterm>
      <primary>pg_my_temp_schema</primary>
     </indexterm>

Index: src/backend/parser/keywords.c
===================================================================
RCS file: /repositories/postgreshome/cvs/pgsql/src/backend/parser/keywords.c,v
retrieving revision 1.197
diff -c -w -r1.197 keywords.c
*** src/backend/parser/keywords.c	21 May 2008 19:51:01 -0000	1.197
--- src/backend/parser/keywords.c	3 Jul 2008 07:01:47 -0000
***************
*** 41,47 ****
   * !!WARNING!!: This list must be sorted by ASCII name, because binary
   *		 search is used to locate entries.
   */
! static const ScanKeyword ScanKeywords[] = {
  	/* name, value, category */
  	{"abort", ABORT_P, UNRESERVED_KEYWORD},
  	{"absolute", ABSOLUTE_P, UNRESERVED_KEYWORD},
--- 41,47 ----
   * !!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},
***************
*** 428,433 ****
--- 428,436 ----
  	{"zone", ZONE, UNRESERVED_KEYWORD},
  };

+ /* End of ScanKeywords, for use elsewhere */
+ const ScanKeyword *LastScanKeyword = endof(ScanKeywords);
+
  /*
   * ScanKeywordLookup - see if a given word is a keyword
   *
Index: src/backend/utils/adt/misc.c
===================================================================
RCS file: /repositories/postgreshome/cvs/pgsql/src/backend/utils/adt/misc.c,v
retrieving revision 1.62
diff -c -w -r1.62 misc.c
*** src/backend/utils/adt/misc.c	17 Apr 2008 20:56:41 -0000	1.62
--- src/backend/utils/adt/misc.c	3 Jul 2008 07:01:47 -0000
***************
*** 20,29 ****
--- 20,31 ----
  #include <math.h>

  #include "access/xact.h"
+ #include "catalog/pg_type.h"
  #include "catalog/pg_tablespace.h"
  #include "commands/dbcommands.h"
  #include "funcapi.h"
  #include "miscadmin.h"
+ #include "parser/keywords.h"
  #include "postmaster/syslogger.h"
  #include "storage/fd.h"
  #include "storage/pmsignal.h"
***************
*** 322,324 ****
--- 324,393 ----

  	PG_RETURN_VOID();
  }
+
+ /* Function to return the keywords list */
+ Datum
+ pg_get_keywords(PG_FUNCTION_ARGS)
+ {
+ 	FuncCallContext *funcctx;
+
+ 	if (SRF_IS_FIRSTCALL())
+ 	{
+ 		MemoryContext oldcontext;
+ 		TupleDesc	tupdesc;
+
+ 		funcctx = SRF_FIRSTCALL_INIT();
+ 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+ 		tupdesc = CreateTemplateTupleDesc(3, false);
+ 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "word",
+ 						   TEXTOID, -1, 0);
+   		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catcode",
+ 						   CHAROID, -1, 0);
+ 		TupleDescInitEntry(tupdesc, (AttrNumber) 3, "catdesc",
+ 						   TEXTOID, -1, 0);
+
+ 		funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
+
+ 		MemoryContextSwitchTo(oldcontext);
+ 	}
+
+ 	funcctx = SRF_PERCALL_SETUP();
+
+ 	if (&ScanKeywords[funcctx->call_cntr] < LastScanKeyword)
+ 	{
+ 		char	   *values[3];
+ 		HeapTuple	tuple;
+
+ 		values[0] = (char *)ScanKeywords[funcctx->call_cntr].name;
+
+ 		switch (ScanKeywords[funcctx->call_cntr].category)
+ 		{
+ 			case UNRESERVED_KEYWORD:
+ 			        values[1] = "U";
+ 				values[2] = _("Unreserved");
+ 				break;
+ 			case COL_NAME_KEYWORD:
+ 				values[1] = "C";
+ 				values[2] = _("Column name");
+ 				break;
+ 			case TYPE_FUNC_NAME_KEYWORD:
+                         	values[1] = "T";
+ 				values[2] = _("Type or function name");
+ 				break;
+ 			case RESERVED_KEYWORD:
+ 				values[1] = "R";
+ 				values[2] = _("Reserved");
+ 				break;
+ 			default:
+ 				values[1] = "";
+ 				values[2] = _("Unknown");
+ 		}
+
+ 		tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
+
+ 		SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
+ 	}
+
+ 	SRF_RETURN_DONE(funcctx);
+ }
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /repositories/postgreshome/cvs/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.503
diff -c -w -r1.503 pg_proc.h
*** src/include/catalog/pg_proc.h	17 Jun 2008 19:10:56 -0000	1.503
--- src/include/catalog/pg_proc.h	3 Jul 2008 07:01:47 -0000
***************
*** 3211,3216 ****
--- 3211,3219 ----
  DATA(insert OID = 2626 ( pg_sleep			PGNSP PGUID 12 1 0 f f t f v 1 2278 "701" _null_ _null_ _null_ pg_sleep - _null_ _null_ ));
  DESCR("sleep for the specified time in seconds");

+ DATA(insert OID = 2701 ( pg_get_keywords	PGNSP PGUID 12 10 400 f f t t s 0 2249 "" "{25,18,25}" "{o,o,o}" "{word,catcode,catdesc}" pg_get_keywords - _null_ _null_ ));
+ DESCR("return keyword list");
+
  DATA(insert OID = 2971 (  text				PGNSP PGUID 12 1 0 f f t f i 1 25 "16" _null_ _null_ _null_ booltext - _null_ _null_ ));
  DESCR("convert boolean to text");

Index: src/include/parser/keywords.h
===================================================================
RCS file: /repositories/postgreshome/cvs/pgsql/src/include/parser/keywords.h,v
retrieving revision 1.24
diff -c -w -r1.24 keywords.h
*** src/include/parser/keywords.h	1 Jan 2008 19:45:58 -0000	1.24
--- src/include/parser/keywords.h	3 Jul 2008 07:01:47 -0000
***************
*** 29,33 ****
--- 29,35 ----
  } ScanKeyword;

  extern const ScanKeyword *ScanKeywordLookup(const char *text);
+ extern const ScanKeyword ScanKeywords[];
+ extern const ScanKeyword *LastScanKeyword;

  #endif   /* KEYWORDS_H */
Index: src/include/utils/builtins.h
===================================================================
RCS file: /repositories/postgreshome/cvs/pgsql/src/include/utils/builtins.h,v
retrieving revision 1.317
diff -c -w -r1.317 builtins.h
*** src/include/utils/builtins.h	17 Jun 2008 19:10:56 -0000	1.317
--- src/include/utils/builtins.h	3 Jul 2008 07:01:47 -0000
***************
*** 411,416 ****
--- 411,417 ----
  extern Datum pg_tablespace_databases(PG_FUNCTION_ARGS);
  extern Datum pg_rotate_logfile(PG_FUNCTION_ARGS);
  extern Datum pg_sleep(PG_FUNCTION_ARGS);
+ extern Datum pg_get_keywords(PG_FUNCTION_ARGS);

  /* oid.c */
  extern Datum oidin(PG_FUNCTION_ARGS);
