<primary>collation for</primary>
</indexterm>
+ <indexterm>
+ <primary>to_regclass</primary>
+ </indexterm>
+
+ <indexterm>
+ <primary>to_regproc</primary>
+ </indexterm>
+
+ <indexterm>
+ <primary>to_regoper</primary>
+ </indexterm>
+
+ <indexterm>
+ <primary>to_regtype</primary>
+ </indexterm>
+
<para>
<xref linkend="functions-info-catalog-table"> lists functions that
extract information from the system catalogs.
<entry><type>text</type></entry>
<entry>get the collation of the argument</entry>
</row>
+ <row>
+ <entry><literal><function>to_regclass(<parameter>rel_name</parameter>)</function></literal></entry>
+ <entry><type>regclass</type></entry>
+ <entry>get the oid of the named relation</entry>
+ </row>
+ <row>
+ <entry><literal><function>to_regproc(<parameter>func_name</parameter>)</function></literal></entry>
+ <entry><type>regproc</type></entry>
+ <entry>get the oid of the named function</entry>
+ </row>
+ <row>
+ <entry><literal><function>to_regoper(<parameter>operator_name</parameter>)</function></literal></entry>
+ <entry><type>regoper</type></entry>
+ <entry>get the oid of the named operator</entry>
+ </row>
+ <row>
+ <entry><literal><function>to_regtype(<parameter>type_name</parameter>)</function></literal></entry>
+ <entry><type>regtype</type></entry>
+ <entry>get the oid of the named type</entry>
+ </row>
</tbody>
</tgroup>
</table>
is not of a collatable data type, then an error is raised.
</para>
+ <para>
+ The <function>to_regclass</function>, <function>to_regproc</function>,
+ <function>to_regoper</function> and <function>to_regtype</function>
+ translate relation, function, operator, and type names to objects of
+ type <type>regclass</>, <type>regproc</>, <type>regoper</> and
+ <type>regtype</>, respectively. These functions differ from a cast from
+ text in that they don't accept a numeric OID, and that they return null
+ rather than throwing an error if the name is not found (or, for
+ <function>to_regproc</function> and <function>to_regoper</function>, if
+ the given name matches multiple objects).
+ </para>
+
<indexterm>
<primary>col_description</primary>
</indexterm>
* will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
*/
FuncCandidateList
-OpernameGetCandidates(List *names, char oprkind)
+OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
{
FuncCandidateList resultList = NULL;
char *resultSpace = NULL;
if (schemaname)
{
/* use exact schema given */
- namespaceId = LookupExplicitNamespace(schemaname, false);
+ namespaceId = LookupExplicitNamespace(schemaname, missing_schema_ok);
+ if (missing_schema_ok && !OidIsValid(namespaceId))
+ return NULL;
}
else
{
FuncCandidateList clist;
/* Get binary operators of given name */
- clist = OpernameGetCandidates(opname, 'b');
+ clist = OpernameGetCandidates(opname, 'b', false);
/* No operators found? Then fail... */
if (clist != NULL)
FuncCandidateList clist;
/* Get postfix operators of given name */
- clist = OpernameGetCandidates(op, 'r');
+ clist = OpernameGetCandidates(op, 'r', false);
/* No operators found? Then fail... */
if (clist != NULL)
FuncCandidateList clist;
/* Get prefix operators of given name */
- clist = OpernameGetCandidates(op, 'l');
+ clist = OpernameGetCandidates(op, 'l', false);
/* No operators found? Then fail... */
if (clist != NULL)
* Given a string that is supposed to be a SQL-compatible type declaration,
* such as "int4" or "integer" or "character varying(32)", parse
* the string and convert it to a type OID and type modifier.
+ * If missing_ok is true, InvalidOid is returned rather than raising an error
+ * when the type name is not found.
*/
void
-parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p)
+parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p,
+ bool missing_ok)
{
StringInfoData buf;
List *raw_parsetree_list;
TypeCast *typecast;
TypeName *typeName;
ErrorContextCallback ptserrcontext;
+ Type tup;
/* make sure we give useful error for empty input */
if (strspn(str, " \t\n\r\f") == strlen(str))
if (typeName->setof)
goto fail;
- typenameTypeIdAndMod(NULL, typeName, typeid_p, typmod_p);
+ tup = LookupTypeName(NULL, typeName, typmod_p, missing_ok);
+ if (tup == NULL)
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("type \"%s\" does not exist",
+ TypeNameToString(typeName)),
+ parser_errposition(NULL, typeName->location)));
+ *typeid_p = InvalidOid;
+ }
+ else
+ {
+ if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("type \"%s\" is only a shell",
+ TypeNameToString(typeName)),
+ parser_errposition(NULL, typeName->location)));
+ *typeid_p = HeapTupleGetOid(tup);
+ ReleaseSysCache(tup);
+ }
pfree(buf.data);
PG_RETURN_OID(result);
}
+/*
+ * to_regproc - converts "proname" to proc OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regproc(PG_FUNCTION_ARGS)
+{
+ char *pro_name = PG_GETARG_CSTRING(0);
+ List *names;
+ FuncCandidateList clist;
+
+ /*
+ * Parse the name into components and see if it matches any pg_proc entries
+ * in the current search path.
+ */
+ names = stringToQualifiedNameList(pro_name);
+ clist = FuncnameGetCandidates(names, -1, NIL, false, false, true);
+
+ if (clist == NULL || clist->next != NULL)
+ PG_RETURN_NULL();
+
+ PG_RETURN_OID(clist->oid);
+}
+
/*
* regprocout - converts proc OID to "pro_name"
*/
* pg_operator entries in the current search path.
*/
names = stringToQualifiedNameList(opr_name_or_oid);
- clist = OpernameGetCandidates(names, '\0');
+ clist = OpernameGetCandidates(names, '\0', false);
if (clist == NULL)
ereport(ERROR,
PG_RETURN_OID(result);
}
+/*
+ * to_regoper - converts "oprname" to operator OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regoper(PG_FUNCTION_ARGS)
+{
+ char *opr_name = PG_GETARG_CSTRING(0);
+ List *names;
+ FuncCandidateList clist;
+
+ /*
+ * Parse the name into components and see if it matches any pg_operator
+ * entries in the current search path.
+ */
+ names = stringToQualifiedNameList(opr_name);
+ clist = OpernameGetCandidates(names, '\0', true);
+
+ if (clist == NULL || clist->next != NULL)
+ PG_RETURN_NULL();
+
+ PG_RETURN_OID(clist->oid);
+}
+
/*
* regoperout - converts operator OID to "opr_name"
*/
* qualify it.
*/
clist = OpernameGetCandidates(list_make1(makeString(oprname)),
- '\0');
+ '\0', false);
if (clist != NULL && clist->next == NULL &&
clist->oid == oprid)
result = pstrdup(oprname);
PG_RETURN_OID(result);
}
+/*
+ * to_regclass - converts "classname" to class OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regclass(PG_FUNCTION_ARGS)
+{
+ char *class_name = PG_GETARG_CSTRING(0);
+ Oid result;
+ List *names;
+
+ /*
+ * Parse the name into components and see if it matches any pg_class entries
+ * in the current search path.
+ */
+ names = stringToQualifiedNameList(class_name);
+
+ /* We might not even have permissions on this relation; don't lock it. */
+ result = RangeVarGetRelid(makeRangeVarFromNameList(names), NoLock, true);
+
+ if (OidIsValid(result))
+ PG_RETURN_OID(result);
+ else
+ PG_RETURN_NULL();
+}
+
/*
* regclassout - converts class OID to "class_name"
*/
* Normal case: invoke the full parser to deal with special cases such as
* array syntax.
*/
- parseTypeString(typ_name_or_oid, &result, &typmod);
+ parseTypeString(typ_name_or_oid, &result, &typmod, false);
PG_RETURN_OID(result);
}
+/*
+ * to_regtype - converts "typename" to type OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regtype(PG_FUNCTION_ARGS)
+{
+ char *typ_name = PG_GETARG_CSTRING(0);
+ Oid result;
+ int32 typmod;
+
+ /*
+ * Invoke the full parser to deal with special cases such as array syntax.
+ */
+ parseTypeString(typ_name, &result, &typmod, true);
+
+ if (OidIsValid(result))
+ PG_RETURN_OID(result);
+ else
+ PG_RETURN_NULL();
+}
+
/*
* regtypeout - converts type OID to "typ_name"
*/
else
{
/* Use full parser to resolve the type name */
- parseTypeString(typename, &typeid, &typmod);
+ parseTypeString(typename, &typeid, &typmod, false);
}
if (*nargs >= FUNC_MAX_ARGS)
ereport(ERROR,
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201404031
+#define CATALOG_VERSION_NO 201404081
#endif
extern bool FunctionIsVisible(Oid funcid);
extern Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright);
-extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind);
+extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind,
+ bool missing_schema_ok);
extern bool OperatorIsVisible(Oid oprid);
extern Oid OpclassnameGetOpcid(Oid amid, const char *opcname);
DESCR("I/O");
DATA(insert OID = 45 ( regprocout PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2275 "24" _null_ _null_ _null_ _null_ regprocout _null_ _null_ _null_ ));
DESCR("I/O");
+DATA(insert OID = 3494 ( to_regproc PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 24 "2275" _null_ _null_ _null_ _null_ to_regproc _null_ _null_ _null_ ));
+DESCR("convert proname to regproc");
DATA(insert OID = 46 ( textin PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "2275" _null_ _null_ _null_ _null_ textin _null_ _null_ _null_ ));
DESCR("I/O");
DATA(insert OID = 47 ( textout PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "25" _null_ _null_ _null_ _null_ textout _null_ _null_ _null_ ));
DESCR("I/O");
DATA(insert OID = 2215 ( regoperout PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2275 "2203" _null_ _null_ _null_ _null_ regoperout _null_ _null_ _null_ ));
DESCR("I/O");
+DATA(insert OID = 3492 ( to_regoper PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2203 "2275" _null_ _null_ _null_ _null_ to_regoper _null_ _null_ _null_ ));
+DESCR("convert operator name to regoper");
DATA(insert OID = 2216 ( regoperatorin PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2204 "2275" _null_ _null_ _null_ _null_ regoperatorin _null_ _null_ _null_ ));
DESCR("I/O");
DATA(insert OID = 2217 ( regoperatorout PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2275 "2204" _null_ _null_ _null_ _null_ regoperatorout _null_ _null_ _null_ ));
DESCR("I/O");
DATA(insert OID = 2219 ( regclassout PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2275 "2205" _null_ _null_ _null_ _null_ regclassout _null_ _null_ _null_ ));
DESCR("I/O");
+DATA(insert OID = 3495 ( to_regclass PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2205 "2275" _null_ _null_ _null_ _null_ to_regclass _null_ _null_ _null_ ));
+DESCR("convert classname to regclass");
DATA(insert OID = 2220 ( regtypein PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2206 "2275" _null_ _null_ _null_ _null_ regtypein _null_ _null_ _null_ ));
DESCR("I/O");
DATA(insert OID = 2221 ( regtypeout PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2275 "2206" _null_ _null_ _null_ _null_ regtypeout _null_ _null_ _null_ ));
DESCR("I/O");
+DATA(insert OID = 3493 ( to_regtype PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2206 "2275" _null_ _null_ _null_ _null_ to_regtype _null_ _null_ _null_ ));
+DESCR("convert type name to regtype");
DATA(insert OID = 1079 ( regclass PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2205 "25" _null_ _null_ _null_ _null_ text_regclass _null_ _null_ _null_ ));
DESCR("convert text to regclass");
extern Oid typeidTypeRelid(Oid type_id);
-extern void parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p);
+extern void parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok);
#define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid)
/* regproc.c */
extern Datum regprocin(PG_FUNCTION_ARGS);
extern Datum regprocout(PG_FUNCTION_ARGS);
+extern Datum to_regproc(PG_FUNCTION_ARGS);
extern Datum regprocrecv(PG_FUNCTION_ARGS);
extern Datum regprocsend(PG_FUNCTION_ARGS);
extern Datum regprocedurein(PG_FUNCTION_ARGS);
extern Datum regoperout(PG_FUNCTION_ARGS);
extern Datum regoperrecv(PG_FUNCTION_ARGS);
extern Datum regopersend(PG_FUNCTION_ARGS);
+extern Datum to_regoper(PG_FUNCTION_ARGS);
extern Datum regoperatorin(PG_FUNCTION_ARGS);
extern Datum regoperatorout(PG_FUNCTION_ARGS);
extern Datum regoperatorrecv(PG_FUNCTION_ARGS);
extern Datum regclassout(PG_FUNCTION_ARGS);
extern Datum regclassrecv(PG_FUNCTION_ARGS);
extern Datum regclasssend(PG_FUNCTION_ARGS);
+extern Datum to_regclass(PG_FUNCTION_ARGS);
extern Datum regtypein(PG_FUNCTION_ARGS);
extern Datum regtypeout(PG_FUNCTION_ARGS);
extern Datum regtyperecv(PG_FUNCTION_ARGS);
extern Datum regtypesend(PG_FUNCTION_ARGS);
+extern Datum to_regtype(PG_FUNCTION_ARGS);
extern Datum regconfigin(PG_FUNCTION_ARGS);
extern Datum regconfigout(PG_FUNCTION_ARGS);
extern Datum regconfigrecv(PG_FUNCTION_ARGS);
char *typstr;
typstr = sv2cstr(argv[i]);
- parseTypeString(typstr, &typId, &typmod);
+ parseTypeString(typstr, &typId, &typmod, false);
pfree(typstr);
getTypeInputInfo(typId, &typInput, &typIOParam);
error_context_stack = &syntax_errcontext;
/* Let the main parser try to parse it under standard SQL rules */
- parseTypeString(string, &type_id, &typmod);
+ parseTypeString(string, &type_id, &typmod, false);
/* Restore former ereport callback */
error_context_stack = syntax_errcontext.previous;
*information for input conversion.
********************************************************/
- parseTypeString(sptr, &typeId, &typmod);
+ parseTypeString(sptr, &typeId, &typmod, false);
typeTup = SearchSysCache1(TYPEOID,
ObjectIdGetDatum(typeId));
typIOParam;
int32 typmod;
- parseTypeString(args[i], &typId, &typmod);
+ parseTypeString(args[i], &typId, &typmod, false);
getTypeInputInfo(typId, &typInput, &typIOParam);
--- /dev/null
+--
+-- regproc
+--
+/* If objects exist, return oids */
+-- without schemaname
+SELECT regoper('||/');
+ regoper
+---------
+ ||/
+(1 row)
+
+SELECT regproc('now');
+ regproc
+---------
+ now
+(1 row)
+
+SELECT regclass('pg_class');
+ regclass
+----------
+ pg_class
+(1 row)
+
+SELECT regtype('int4');
+ regtype
+---------
+ integer
+(1 row)
+
+SELECT to_regoper('||/');
+ to_regoper
+------------
+ ||/
+(1 row)
+
+SELECT to_regproc('now');
+ to_regproc
+------------
+ now
+(1 row)
+
+SELECT to_regclass('pg_class');
+ to_regclass
+-------------
+ pg_class
+(1 row)
+
+SELECT to_regtype('int4');
+ to_regtype
+------------
+ integer
+(1 row)
+
+-- with schemaname
+SELECT regoper('pg_catalog.||/');
+ regoper
+---------
+ ||/
+(1 row)
+
+SELECT regproc('pg_catalog.now');
+ regproc
+---------
+ now
+(1 row)
+
+SELECT regclass('pg_catalog.pg_class');
+ regclass
+----------
+ pg_class
+(1 row)
+
+SELECT regtype('pg_catalog.int4');
+ regtype
+---------
+ integer
+(1 row)
+
+SELECT to_regoper('pg_catalog.||/');
+ to_regoper
+------------
+ ||/
+(1 row)
+
+SELECT to_regproc('pg_catalog.now');
+ to_regproc
+------------
+ now
+(1 row)
+
+SELECT to_regclass('pg_catalog.pg_class');
+ to_regclass
+-------------
+ pg_class
+(1 row)
+
+SELECT to_regtype('pg_catalog.int4');
+ to_regtype
+------------
+ integer
+(1 row)
+
+/* If objects don't exist, raise errors. */
+-- without schemaname
+SELECT regoper('||//');
+ERROR: operator does not exist: ||//
+LINE 3: SELECT regoper('||//');
+ ^
+SELECT regproc('know');
+ERROR: function "know" does not exist
+LINE 1: SELECT regproc('know');
+ ^
+SELECT regclass('pg_classes');
+ERROR: relation "pg_classes" does not exist
+LINE 1: SELECT regclass('pg_classes');
+ ^
+SELECT regtype('int3');
+ERROR: type "int3" does not exist
+LINE 1: SELECT regtype('int3');
+ ^
+-- with schemaname
+SELECT regoper('ng_catalog.||/');
+ERROR: schema "ng_catalog" does not exist
+LINE 1: SELECT regoper('ng_catalog.||/');
+ ^
+SELECT regproc('ng_catalog.now');
+ERROR: schema "ng_catalog" does not exist
+LINE 1: SELECT regproc('ng_catalog.now');
+ ^
+SELECT regclass('ng_catalog.pg_class');
+ERROR: schema "ng_catalog" does not exist
+LINE 1: SELECT regclass('ng_catalog.pg_class');
+ ^
+SELECT regtype('ng_catalog.int4');
+ERROR: schema "ng_catalog" does not exist
+LINE 1: SELECT regtype('ng_catalog.int4');
+ ^
+/* If objects don't exist, return NULL with no error. */
+-- without schemaname
+SELECT to_regoper('||//');
+ to_regoper
+------------
+
+(1 row)
+
+SELECT to_regproc('know');
+ to_regproc
+------------
+
+(1 row)
+
+SELECT to_regclass('pg_classes');
+ to_regclass
+-------------
+
+(1 row)
+
+SELECT to_regtype('int3');
+ to_regtype
+------------
+
+(1 row)
+
+-- with schemaname
+SELECT to_regoper('ng_catalog.||/');
+ to_regoper
+------------
+
+(1 row)
+
+SELECT to_regproc('ng_catalog.now');
+ to_regproc
+------------
+
+(1 row)
+
+SELECT to_regclass('ng_catalog.pg_class');
+ to_regclass
+-------------
+
+(1 row)
+
+SELECT to_regtype('ng_catalog.int4');
+ to_regtype
+------------
+
+(1 row)
+
# ----------
# The first group of parallel tests
# ----------
-test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric txid uuid enum money rangetypes pg_lsn
+test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric txid uuid enum money rangetypes pg_lsn regproc
# Depends on things setup during char, varchar and text
test: strings
test: money
test: rangetypes
test: pg_lsn
+test: regproc
test: strings
test: numerology
test: point
--- /dev/null
+--
+-- regproc
+--
+
+/* If objects exist, return oids */
+
+-- without schemaname
+
+SELECT regoper('||/');
+SELECT regproc('now');
+SELECT regclass('pg_class');
+SELECT regtype('int4');
+
+SELECT to_regoper('||/');
+SELECT to_regproc('now');
+SELECT to_regclass('pg_class');
+SELECT to_regtype('int4');
+
+-- with schemaname
+
+SELECT regoper('pg_catalog.||/');
+SELECT regproc('pg_catalog.now');
+SELECT regclass('pg_catalog.pg_class');
+SELECT regtype('pg_catalog.int4');
+
+SELECT to_regoper('pg_catalog.||/');
+SELECT to_regproc('pg_catalog.now');
+SELECT to_regclass('pg_catalog.pg_class');
+SELECT to_regtype('pg_catalog.int4');
+
+/* If objects don't exist, raise errors. */
+
+-- without schemaname
+
+SELECT regoper('||//');
+SELECT regproc('know');
+SELECT regclass('pg_classes');
+SELECT regtype('int3');
+
+-- with schemaname
+
+SELECT regoper('ng_catalog.||/');
+SELECT regproc('ng_catalog.now');
+SELECT regclass('ng_catalog.pg_class');
+SELECT regtype('ng_catalog.int4');
+
+/* If objects don't exist, return NULL with no error. */
+
+-- without schemaname
+
+SELECT to_regoper('||//');
+SELECT to_regproc('know');
+SELECT to_regclass('pg_classes');
+SELECT to_regtype('int3');
+
+-- with schemaname
+
+SELECT to_regoper('ng_catalog.||/');
+SELECT to_regproc('ng_catalog.now');
+SELECT to_regclass('ng_catalog.pg_class');
+SELECT to_regtype('ng_catalog.int4');