diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index 0cac9935d2d85a11c6c2b39d51a2fadc90528c73..9d5ce953f1728343f664699c5fab65ef31aa1ed6 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -4321,9 +4321,9 @@ SET xmloption TO { DOCUMENT | CONTENT }; an object identifier. There are also several alias types for oid: regproc, regprocedure, regoper, regoperator, regclass, - regtype, regrole, regconfig, and - regdictionary. shows - an overview. + regtype, regrole, regnamespace, + regconfig, and regdictionary. + shows an overview. @@ -4438,6 +4438,13 @@ SELECT * FROM pg_attribute smithee + + regnamespace + pg_namespace + namespace name + pg_catalog + + regconfig pg_ts_config diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 66028d5877e07fa35f3b0a2bd8803c703f1b4caa..e42187a7d5da76babf397d8030c73c1f8150fad8 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -115,6 +115,8 @@ static const struct typinfo TypInfo[] = { F_REGTYPEIN, F_REGTYPEOUT}, {"regrole", REGROLEOID, 0, 4, true, 'i', 'p', InvalidOid, F_REGROLEIN, F_REGROLEOUT}, + {"regnamespace", REGNAMESPACEOID, 0, 4, true, 'i', 'p', InvalidOid, + F_REGNAMESPACEIN, F_REGNAMESPACEOUT}, {"text", TEXTOID, 0, -1, false, 'i', 'x', DEFAULT_COLLATION_OID, F_TEXTIN, F_TEXTOUT}, {"oid", OIDOID, 0, 4, true, 'i', 'p', InvalidOid, diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index 0ab57322f35e312f5228c9be4c1aacdd4747956b..ec4ba397c71ad4bc39270cffd2f2b23d318b3646 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1603,6 +1603,14 @@ find_expr_references_walker(Node *node, context->addrs); break; + case REGNAMESPACEOID: + objoid = DatumGetObjectId(con->constvalue); + if (SearchSysCacheExists1(NAMESPACEOID, + ObjectIdGetDatum(objoid))) + add_object_address(OCLASS_SCHEMA, objoid, 0, + context->addrs); + break; + /* * Dependencies for regrole should be shared among all * databases, so explicitly inhibit to have dependencies. diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index 8b5672875c244a6befed2b084b2ed1778aba577c..7e5598d53cc917bff029d9cc3903574a7adef5a8 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -1656,7 +1656,103 @@ regrolesend(PG_FUNCTION_ARGS) return oidsend(fcinfo); } +/* + * regnamespacein - converts "nspname" to namespace OID + * + * We also accept a numeric OID, for symmetry with the output routine. + * + * '-' signifies unknown (OID 0). In all other cases, the input must + * match an existing pg_namespace entry. + */ +Datum +regnamespacein(PG_FUNCTION_ARGS) +{ + char *nsp_name_or_oid = PG_GETARG_CSTRING(0); + Oid result = InvalidOid; + + /* '-' ? */ + if (strcmp(nsp_name_or_oid, "-") == 0) + PG_RETURN_OID(InvalidOid); + + /* Numeric OID? */ + if (nsp_name_or_oid[0] >= '0' && + nsp_name_or_oid[0] <= '9' && + strspn(nsp_name_or_oid, "0123456789") == strlen(nsp_name_or_oid)) + { + result = DatumGetObjectId(DirectFunctionCall1(oidin, + CStringGetDatum(nsp_name_or_oid))); + PG_RETURN_OID(result); + } + + /* Normal case: see if the name matches any pg_namespace entry. */ + result = get_namespace_oid(nsp_name_or_oid, false); + + PG_RETURN_OID(result); +} + +/* + * to_regnamespace - converts "nspname" to namespace OID + * + * If the name is not found, we return NULL. + */ +Datum +to_regnamespace(PG_FUNCTION_ARGS) +{ + char *nsp_name = PG_GETARG_CSTRING(0); + Oid result; + + result = get_namespace_oid(nsp_name, true); + + if (OidIsValid(result)) + PG_RETURN_OID(result); + else + PG_RETURN_NULL(); +} + +/* + * regnamespaceout - converts namespace OID to "nsp_name" + */ +Datum +regnamespaceout(PG_FUNCTION_ARGS) +{ + Oid nspid = PG_GETARG_OID(0); + char *result; + + if (nspid == InvalidOid) + { + result = pstrdup("-"); + PG_RETURN_CSTRING(result); + } + result = get_namespace_name(nspid); + if (!result) + { + /* If OID doesn't match any namespace, return it numerically */ + result = (char *) palloc(NAMEDATALEN); + snprintf(result, NAMEDATALEN, "%u", nspid); + } + PG_RETURN_CSTRING(result); +} + +/* + * regnamespacerecv - converts external binary format to regnamespace + */ +Datum +regnamespacerecv(PG_FUNCTION_ARGS) +{ + /* Exactly the same as oidrecv, so share code */ + return oidrecv(fcinfo); +} + +/* + * regnamespacesend - converts regnamespace to binary format + */ +Datum +regnamespacesend(PG_FUNCTION_ARGS) +{ + /* Exactly the same as oidsend, so share code */ + return oidsend(fcinfo); +} /* * text_regclass: convert text to regclass diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index a28868c3130263d709e8631fd33eec602ae0590c..91399f79fc80273c4978f4520abe566fa5dd8ed3 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -3620,6 +3620,7 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue, case REGCONFIGOID: case REGDICTIONARYOID: case REGROLEOID: + case REGNAMESPACEOID: *scaledvalue = convert_numeric_to_scalar(value, valuetypid); *scaledlobound = convert_numeric_to_scalar(lobound, boundstypid); *scaledhibound = convert_numeric_to_scalar(hibound, boundstypid); @@ -3726,6 +3727,7 @@ convert_numeric_to_scalar(Datum value, Oid typid) case REGCONFIGOID: case REGDICTIONARYOID: case REGROLEOID: + case REGNAMESPACEOID: /* we can treat OIDs as integers... */ return (double) DatumGetObjectId(value); } diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 9b7cc5eb76464b241a0475e66df35c8d938e1e7a..5bb03dd0b1ed306437b13330a6c256f5c56e2693 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -151,6 +151,7 @@ GetCCHashEqFuncs(Oid keytype, PGFunction *hashfunc, RegProcedure *eqfunc) case REGCONFIGOID: case REGDICTIONARYOID: case REGROLEOID: + case REGNAMESPACEOID: *hashfunc = hashoid; *eqfunc = F_OIDEQ; diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index c2e6dbf57bfa42f1a8431b22c8f02935d1e1f8b8..662ba27a414095f0231cdac955cd2120d47144af 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201505083 +#define CATALOG_VERSION_NO 201505091 #endif diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h index 4eba2ebbec581215e7e42392d35e7fb920abd3ff..bf6ef10821165fc31061886b84913337487aca68 100644 --- a/src/include/catalog/pg_cast.h +++ b/src/include/catalog/pg_cast.h @@ -217,6 +217,13 @@ DATA(insert ( 21 4096 313 i f )); DATA(insert ( 23 4096 0 i b )); DATA(insert ( 4096 20 1288 a f )); DATA(insert ( 4096 23 0 a b )); +DATA(insert ( 26 4089 0 i b )); +DATA(insert ( 4089 26 0 i b )); +DATA(insert ( 20 4089 1287 i f )); +DATA(insert ( 21 4089 313 i f )); +DATA(insert ( 23 4089 0 i b )); +DATA(insert ( 4089 20 1288 a f )); +DATA(insert ( 4089 23 0 a b )); /* * String category diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 5452d10e8a8986618b212bd212803f17f42a3029..5fa65d63a87ec5267b405ff93713bab120e2f00c 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -3488,6 +3488,13 @@ DESCR("I/O"); DATA(insert OID = 4093 ( to_regrole PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 4096 "2275" _null_ _null_ _null_ _null_ _null_ to_regrole _null_ _null_ _null_ )); DESCR("convert role name to regrole"); +DATA(insert OID = 4084 ( regnamespacein PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 4089 "2275" _null_ _null_ _null_ _null_ _null_ regnamespacein _null_ _null_ _null_ )); +DESCR("I/O"); +DATA(insert OID = 4085 ( regnamespaceout PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2275 "4089" _null_ _null_ _null_ _null_ _null_ regnamespaceout _null_ _null_ _null_ )); +DESCR("I/O"); +DATA(insert OID = 4086 ( to_regnamespace PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 4089 "2275" _null_ _null_ _null_ _null_ _null_ to_regnamespace _null_ _null_ _null_ )); +DESCR("convert namespace name to regnamespace"); + DATA(insert OID = 2246 ( fmgr_internal_validator PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2278 "26" _null_ _null_ _null_ _null_ _null_ fmgr_internal_validator _null_ _null_ _null_ )); DESCR("(internal)"); DATA(insert OID = 2247 ( fmgr_c_validator PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2278 "26" _null_ _null_ _null_ _null_ _null_ fmgr_c_validator _null_ _null_ _null_ )); @@ -3888,6 +3895,10 @@ DATA(insert OID = 4094 ( regrolerecv PGNSP PGUID 12 1 0 0 0 f f f f t f i DESCR("I/O"); DATA(insert OID = 4095 ( regrolesend PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 17 "4096" _null_ _null_ _null_ _null_ _null_ regrolesend _null_ _null_ _null_ )); DESCR("I/O"); +DATA(insert OID = 4087 ( regnamespacerecv PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 4089 "2281" _null_ _null_ _null_ _null_ _null_ regnamespacerecv _null_ _null_ _null_ )); +DESCR("I/O"); +DATA(insert OID = 4088 ( regnamespacesend PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 17 "4089" _null_ _null_ _null_ _null_ _null_ regnamespacesend _null_ _null_ _null_ )); +DESCR("I/O"); DATA(insert OID = 2456 ( bit_recv PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 1560 "2281 26 23" _null_ _null_ _null_ _null_ _null_ bit_recv _null_ _null_ _null_ )); DESCR("I/O"); DATA(insert OID = 2457 ( bit_send PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 17 "1560" _null_ _null_ _null_ _null_ _null_ bit_send _null_ _null_ _null_ )); diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 1430bc15b7447d2caecda5abe45f5b1c1494571f..24933539aabe384f893f115f368d54c273a094a0 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -568,6 +568,10 @@ DATA(insert OID = 4096 ( regrole PGNSP PGUID 4 t b N f t \054 0 0 4097 re DESCR("registered role"); #define REGROLEOID 4096 +DATA(insert OID = 4089 ( regnamespace PGNSP PGUID 4 t b N f t \054 0 0 4090 regnamespacein regnamespaceout regnamespacerecv regnamespacesend - - - i p f 0 -1 0 0 _null_ _null_ _null_ )); +DESCR("registered namespace"); +#define REGNAMESPACEOID 4089 + DATA(insert OID = 2207 ( _regprocedure PGNSP PGUID -1 f b A f t \054 0 2202 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); DATA(insert OID = 2208 ( _regoper PGNSP PGUID -1 f b A f t \054 0 2203 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); DATA(insert OID = 2209 ( _regoperator PGNSP PGUID -1 f b A f t \054 0 2204 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); @@ -575,6 +579,7 @@ DATA(insert OID = 2210 ( _regclass PGNSP PGUID -1 f b A f t \054 0 2205 0 arr DATA(insert OID = 2211 ( _regtype PGNSP PGUID -1 f b A f t \054 0 2206 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); #define REGTYPEARRAYOID 2211 DATA(insert OID = 4097 ( _regrole PGNSP PGUID -1 f b A f t \054 0 4096 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); +DATA(insert OID = 4090 ( _regnamespace PGNSP PGUID -1 f b A f t \054 0 4089 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); /* uuid */ DATA(insert OID = 2950 ( uuid PGNSP PGUID 16 f b U f t \054 0 0 2951 uuid_in uuid_out uuid_recv uuid_send - - - c p f 0 -1 0 0 _null_ _null_ _null_ )); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 654ae1b305e36878d21cff526a6ea5a54ac3f925..a90bfe29e9f5c93fd19419f4ddca3950332c567e 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -635,6 +635,11 @@ extern Datum regroleout(PG_FUNCTION_ARGS); extern Datum regrolerecv(PG_FUNCTION_ARGS); extern Datum regrolesend(PG_FUNCTION_ARGS); extern Datum to_regrole(PG_FUNCTION_ARGS); +extern Datum regnamespacein(PG_FUNCTION_ARGS); +extern Datum regnamespaceout(PG_FUNCTION_ARGS); +extern Datum regnamespacerecv(PG_FUNCTION_ARGS); +extern Datum regnamespacesend(PG_FUNCTION_ARGS); +extern Datum to_regnamespace(PG_FUNCTION_ARGS); extern Datum regconfigin(PG_FUNCTION_ARGS); extern Datum regconfigout(PG_FUNCTION_ARGS); extern Datum regconfigrecv(PG_FUNCTION_ARGS); diff --git a/src/test/regress/expected/regproc.out b/src/test/regress/expected/regproc.out index beda8ecabce7a0dbfbf25f9e944d0631d175b431..8c734f413ce6468c30f50c961892a86c4d7178bf 100644 --- a/src/test/regress/expected/regproc.out +++ b/src/test/regress/expected/regproc.out @@ -46,6 +46,12 @@ SELECT regrole('regtestrole'); regtestrole (1 row) +SELECT regnamespace('pg_catalog'); + regnamespace +-------------- + pg_catalog +(1 row) + SELECT to_regoper('||/'); to_regoper ------------ @@ -88,6 +94,12 @@ SELECT to_regrole('regtestrole'); regtestrole (1 row) +SELECT to_regnamespace('pg_catalog'); + to_regnamespace +----------------- + pg_catalog +(1 row) + -- with schemaname SELECT regoper('pg_catalog.||/'); regoper @@ -186,6 +198,10 @@ SELECT regrole('regtestrole'); ERROR: role "regtestrole" does not exist LINE 1: SELECT regrole('regtestrole'); ^ +SELECT regnamespace('nonexistent'); +ERROR: schema "nonexistent" does not exist +LINE 1: SELECT regnamespace('nonexistent'); + ^ -- with schemaname SELECT regoper('ng_catalog.||/'); ERROR: schema "ng_catalog" does not exist @@ -255,6 +271,12 @@ SELECT to_regrole('regtestrole'); (1 row) +SELECT to_regnamespace('nonexistent'); + to_regnamespace +----------------- + +(1 row) + -- with schemaname SELECT to_regoper('ng_catalog.||/'); to_regoper diff --git a/src/test/regress/sql/regproc.sql b/src/test/regress/sql/regproc.sql index bc77c67cb8f8484667ddc9e8f6502d6aab04d07b..8edaf15f75fcec041be474c93a6a3abafd02b4f6 100644 --- a/src/test/regress/sql/regproc.sql +++ b/src/test/regress/sql/regproc.sql @@ -14,6 +14,7 @@ SELECT regprocedure('abs(numeric)'); SELECT regclass('pg_class'); SELECT regtype('int4'); SELECT regrole('regtestrole'); +SELECT regnamespace('pg_catalog'); SELECT to_regoper('||/'); SELECT to_regoperator('+(int4,int4)'); @@ -22,6 +23,7 @@ SELECT to_regprocedure('abs(numeric)'); SELECT to_regclass('pg_class'); SELECT to_regtype('int4'); SELECT to_regrole('regtestrole'); +SELECT to_regnamespace('pg_catalog'); -- with schemaname @@ -51,6 +53,7 @@ SELECT regprocedure('absinthe(numeric)'); SELECT regclass('pg_classes'); SELECT regtype('int3'); SELECT regrole('regtestrole'); +SELECT regnamespace('nonexistent'); -- with schemaname @@ -72,6 +75,7 @@ SELECT to_regprocedure('absinthe(numeric)'); SELECT to_regclass('pg_classes'); SELECT to_regtype('int3'); SELECT to_regrole('regtestrole'); +SELECT to_regnamespace('nonexistent'); -- with schemaname