diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 48cb4f6c2b6338a3c9bfb7fbd0dbae83144b668e..d3529f560e3db0ff4a5dbcd2b22a2084aeb5b995 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.437 2008/05/19 18:08:15 tgl Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.438 2008/07/03 20:58:46 tgl Exp $ --> <chapter id="functions"> <title>Functions and Operators</title> @@ -11484,6 +11484,10 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); <primary>format_type</primary> </indexterm> + <indexterm> + <primary>pg_get_keywords</primary> + </indexterm> + <indexterm> <primary>pg_get_viewdef</primary> </indexterm> @@ -11538,6 +11542,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); <entry><type>text</type></entry> <entry>get SQL name of a data type</entry> </row> + <row> + <entry><literal><function>pg_get_keywords</function>()</literal></entry> + <entry><type>setof record</type></entry> + <entry>get list of SQL keywords and their categories</entry> + </row> <row> <entry><literal><function>pg_get_constraintdef</function>(<parameter>constraint_oid</parameter>)</literal></entry> <entry><type>text</type></entry> @@ -11633,6 +11642,16 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); for the type modifier if no specific modifier is known. </para> + <para> + <function>pg_get_keywords</function> returns a set of records describing + the SQL keywords recognized by the server. The <structfield>word</> column + contains the keyword. The <structfield>catcode</> column contains a + category code: <literal>U</> for unreserved, <literal>C</> for column name, + <literal>T</> for type or function name, or <literal>R</> for reserved. + The <structfield>catdesc</> column contains a possibly-localized string + describing the category. + </para> + <para> <function>pg_get_constraintdef</function>, <function>pg_get_indexdef</function>, <function>pg_get_ruledef</function>, diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index edb765966230a089130e3ed88dffb0a8d62f8ddb..43013e1e7723d0c273bd11e270780811e24e3506 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.197 2008/05/21 19:51:01 meskes Exp $ + * $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.198 2008/07/03 20:58:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -41,7 +41,7 @@ * !!WARNING!!: This list must be sorted by ASCII name, because binary * search is used to locate entries. */ -static const ScanKeyword ScanKeywords[] = { +const ScanKeyword ScanKeywords[] = { /* name, value, category */ {"abort", ABORT_P, UNRESERVED_KEYWORD}, {"absolute", ABSOLUTE_P, UNRESERVED_KEYWORD}, @@ -428,6 +428,9 @@ static const ScanKeyword ScanKeywords[] = { {"zone", ZONE, UNRESERVED_KEYWORD}, }; +/* End of ScanKeywords, for use elsewhere */ +const ScanKeyword *LastScanKeyword = endof(ScanKeywords); + /* * ScanKeywordLookup - see if a given word is a keyword * diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index f99a07a99987767cb5154d375d371f0a79de45f1..b48c004527c0f8adede52979c474818ae8b73977 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.62 2008/04/17 20:56:41 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.63 2008/07/03 20:58:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,10 +20,12 @@ #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,3 +324,72 @@ pg_sleep(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } + +/* Function to return the list of grammar keywords */ +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; + + /* cast-away-const is ugly but alternatives aren't much better */ + 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: /* shouldn't be possible */ + values[1] = NULL; + values[2] = NULL; + break; + } + + tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); + + SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); + } + + SRF_RETURN_DONE(funcctx); +} diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index a49beccd54f1b337f985589df4fe71a688d69cb8..e7ba550c48465211245aeb59295af78e21a8d23c 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.464 2008/06/24 17:58:27 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.465 2008/07/03 20:58:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200806241 +#define CATALOG_VERSION_NO 200807031 #endif diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index dbe791028222bc8197201aa9cdf8317f611d09db..09700e8f43a3fb2d8c31c876b1f5825cd4ed4fa1 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.503 2008/06/17 19:10:56 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.504 2008/07/03 20:58:46 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -2288,6 +2288,9 @@ DESCR("deparse an encoded expression"); DATA(insert OID = 1665 ( pg_get_serial_sequence PGNSP PGUID 12 1 0 f f t f s 2 25 "25 25" _null_ _null_ _null_ pg_get_serial_sequence - _null_ _null_ )); DESCR("name of sequence for a serial column"); +DATA(insert OID = 1686 ( 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("list of SQL keywords"); + /* Generic referential integrity constraint triggers */ DATA(insert OID = 1644 ( RI_FKey_check_ins PGNSP PGUID 12 1 0 f f t f v 0 2279 "" _null_ _null_ _null_ RI_FKey_check_ins - _null_ _null_ )); diff --git a/src/include/parser/keywords.h b/src/include/parser/keywords.h index 717e20e7df4518ab12483902de1372909c79735c..2da7fd3da9e30689e2fb3c0d28df9d5b5fb902b4 100644 --- a/src/include/parser/keywords.h +++ b/src/include/parser/keywords.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/keywords.h,v 1.24 2008/01/01 19:45:58 momjian Exp $ + * $PostgreSQL: pgsql/src/include/parser/keywords.h,v 1.25 2008/07/03 20:58:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,9 @@ typedef struct ScanKeyword int16 category; /* see codes above */ } ScanKeyword; +extern const ScanKeyword ScanKeywords[]; +extern const ScanKeyword *LastScanKeyword; + extern const ScanKeyword *ScanKeywordLookup(const char *text); #endif /* KEYWORDS_H */ diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index c34ee7aa90473a1104c6557cc1a64968ca775f4a..2abbe6678914e32d9360f7f2b2b0481102b4318d 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.317 2008/06/17 19:10:56 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.318 2008/07/03 20:58:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -411,6 +411,7 @@ extern Datum pg_reload_conf(PG_FUNCTION_ARGS); 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);