Commit 0886fc6a authored by Robert Haas's avatar Robert Haas

Add new to_reg* functions for error-free OID lookups.

These functions won't throw an error if the object doesn't exist,
or if (for functions and operators) there's more than one matching
object.

Yugo Nagata and Nozomi Anzai, reviewed by Amit Khandekar, Marti
Raudsepp, Amit Kapila, and me.
parent 7ca32e25
...@@ -15279,6 +15279,22 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); ...@@ -15279,6 +15279,22 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<primary>collation for</primary> <primary>collation for</primary>
</indexterm> </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> <para>
<xref linkend="functions-info-catalog-table"> lists functions that <xref linkend="functions-info-catalog-table"> lists functions that
extract information from the system catalogs. extract information from the system catalogs.
...@@ -15449,6 +15465,26 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); ...@@ -15449,6 +15465,26 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<entry><type>text</type></entry> <entry><type>text</type></entry>
<entry>get the collation of the argument</entry> <entry>get the collation of the argument</entry>
</row> </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> </tbody>
</tgroup> </tgroup>
</table> </table>
...@@ -15614,6 +15650,18 @@ SELECT collation for ('foo' COLLATE "de_DE"); ...@@ -15614,6 +15650,18 @@ SELECT collation for ('foo' COLLATE "de_DE");
is not of a collatable data type, then an error is raised. is not of a collatable data type, then an error is raised.
</para> </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> <indexterm>
<primary>col_description</primary> <primary>col_description</primary>
</indexterm> </indexterm>
......
...@@ -1556,7 +1556,7 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright) ...@@ -1556,7 +1556,7 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
* will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too. * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
*/ */
FuncCandidateList FuncCandidateList
OpernameGetCandidates(List *names, char oprkind) OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
{ {
FuncCandidateList resultList = NULL; FuncCandidateList resultList = NULL;
char *resultSpace = NULL; char *resultSpace = NULL;
...@@ -1573,7 +1573,9 @@ OpernameGetCandidates(List *names, char oprkind) ...@@ -1573,7 +1573,9 @@ OpernameGetCandidates(List *names, char oprkind)
if (schemaname) if (schemaname)
{ {
/* use exact schema given */ /* use exact schema given */
namespaceId = LookupExplicitNamespace(schemaname, false); namespaceId = LookupExplicitNamespace(schemaname, missing_schema_ok);
if (missing_schema_ok && !OidIsValid(namespaceId))
return NULL;
} }
else else
{ {
......
...@@ -407,7 +407,7 @@ oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, ...@@ -407,7 +407,7 @@ oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId,
FuncCandidateList clist; FuncCandidateList clist;
/* Get binary operators of given name */ /* Get binary operators of given name */
clist = OpernameGetCandidates(opname, 'b'); clist = OpernameGetCandidates(opname, 'b', false);
/* No operators found? Then fail... */ /* No operators found? Then fail... */
if (clist != NULL) if (clist != NULL)
...@@ -553,7 +553,7 @@ right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location) ...@@ -553,7 +553,7 @@ right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
FuncCandidateList clist; FuncCandidateList clist;
/* Get postfix operators of given name */ /* Get postfix operators of given name */
clist = OpernameGetCandidates(op, 'r'); clist = OpernameGetCandidates(op, 'r', false);
/* No operators found? Then fail... */ /* No operators found? Then fail... */
if (clist != NULL) if (clist != NULL)
...@@ -631,7 +631,7 @@ left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location) ...@@ -631,7 +631,7 @@ left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
FuncCandidateList clist; FuncCandidateList clist;
/* Get prefix operators of given name */ /* Get prefix operators of given name */
clist = OpernameGetCandidates(op, 'l'); clist = OpernameGetCandidates(op, 'l', false);
/* No operators found? Then fail... */ /* No operators found? Then fail... */
if (clist != NULL) if (clist != NULL)
......
...@@ -706,9 +706,12 @@ pts_error_callback(void *arg) ...@@ -706,9 +706,12 @@ pts_error_callback(void *arg)
* Given a string that is supposed to be a SQL-compatible type declaration, * Given a string that is supposed to be a SQL-compatible type declaration,
* such as "int4" or "integer" or "character varying(32)", parse * such as "int4" or "integer" or "character varying(32)", parse
* the string and convert it to a type OID and type modifier. * 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 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; StringInfoData buf;
List *raw_parsetree_list; List *raw_parsetree_list;
...@@ -717,6 +720,7 @@ parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p) ...@@ -717,6 +720,7 @@ parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p)
TypeCast *typecast; TypeCast *typecast;
TypeName *typeName; TypeName *typeName;
ErrorContextCallback ptserrcontext; ErrorContextCallback ptserrcontext;
Type tup;
/* make sure we give useful error for empty input */ /* make sure we give useful error for empty input */
if (strspn(str, " \t\n\r\f") == strlen(str)) if (strspn(str, " \t\n\r\f") == strlen(str))
...@@ -782,7 +786,28 @@ parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p) ...@@ -782,7 +786,28 @@ parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p)
if (typeName->setof) if (typeName->setof)
goto fail; 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); pfree(buf.data);
......
...@@ -152,6 +152,31 @@ regprocin(PG_FUNCTION_ARGS) ...@@ -152,6 +152,31 @@ regprocin(PG_FUNCTION_ARGS)
PG_RETURN_OID(result); 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" * regprocout - converts proc OID to "pro_name"
*/ */
...@@ -502,7 +527,7 @@ regoperin(PG_FUNCTION_ARGS) ...@@ -502,7 +527,7 @@ regoperin(PG_FUNCTION_ARGS)
* pg_operator entries in the current search path. * pg_operator entries in the current search path.
*/ */
names = stringToQualifiedNameList(opr_name_or_oid); names = stringToQualifiedNameList(opr_name_or_oid);
clist = OpernameGetCandidates(names, '\0'); clist = OpernameGetCandidates(names, '\0', false);
if (clist == NULL) if (clist == NULL)
ereport(ERROR, ereport(ERROR,
...@@ -519,6 +544,31 @@ regoperin(PG_FUNCTION_ARGS) ...@@ -519,6 +544,31 @@ regoperin(PG_FUNCTION_ARGS)
PG_RETURN_OID(result); 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" * regoperout - converts operator OID to "opr_name"
*/ */
...@@ -558,7 +608,7 @@ regoperout(PG_FUNCTION_ARGS) ...@@ -558,7 +608,7 @@ regoperout(PG_FUNCTION_ARGS)
* qualify it. * qualify it.
*/ */
clist = OpernameGetCandidates(list_make1(makeString(oprname)), clist = OpernameGetCandidates(list_make1(makeString(oprname)),
'\0'); '\0', false);
if (clist != NULL && clist->next == NULL && if (clist != NULL && clist->next == NULL &&
clist->oid == oprid) clist->oid == oprid)
result = pstrdup(oprname); result = pstrdup(oprname);
...@@ -872,6 +922,33 @@ regclassin(PG_FUNCTION_ARGS) ...@@ -872,6 +922,33 @@ regclassin(PG_FUNCTION_ARGS)
PG_RETURN_OID(result); 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" * regclassout - converts class OID to "class_name"
*/ */
...@@ -1028,11 +1105,34 @@ regtypein(PG_FUNCTION_ARGS) ...@@ -1028,11 +1105,34 @@ regtypein(PG_FUNCTION_ARGS)
* Normal case: invoke the full parser to deal with special cases such as * Normal case: invoke the full parser to deal with special cases such as
* array syntax. * array syntax.
*/ */
parseTypeString(typ_name_or_oid, &result, &typmod); parseTypeString(typ_name_or_oid, &result, &typmod, false);
PG_RETURN_OID(result); 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" * regtypeout - converts type OID to "typ_name"
*/ */
...@@ -1523,7 +1623,7 @@ parseNameAndArgTypes(const char *string, bool allowNone, List **names, ...@@ -1523,7 +1623,7 @@ parseNameAndArgTypes(const char *string, bool allowNone, List **names,
else else
{ {
/* Use full parser to resolve the type name */ /* Use full parser to resolve the type name */
parseTypeString(typename, &typeid, &typmod); parseTypeString(typename, &typeid, &typmod, false);
} }
if (*nargs >= FUNC_MAX_ARGS) if (*nargs >= FUNC_MAX_ARGS)
ereport(ERROR, ereport(ERROR,
......
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201404031 #define CATALOG_VERSION_NO 201404081
#endif #endif
...@@ -76,7 +76,8 @@ extern FuncCandidateList FuncnameGetCandidates(List *names, ...@@ -76,7 +76,8 @@ extern FuncCandidateList FuncnameGetCandidates(List *names,
extern bool FunctionIsVisible(Oid funcid); extern bool FunctionIsVisible(Oid funcid);
extern Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright); 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 bool OperatorIsVisible(Oid oprid);
extern Oid OpclassnameGetOpcid(Oid amid, const char *opcname); extern Oid OpclassnameGetOpcid(Oid amid, const char *opcname);
......
...@@ -173,6 +173,8 @@ DATA(insert OID = 44 ( regprocin PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 ...@@ -173,6 +173,8 @@ DATA(insert OID = 44 ( regprocin PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0
DESCR("I/O"); 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_ )); 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"); 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_ )); 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"); 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_ )); 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_ ));
...@@ -3304,6 +3306,8 @@ DATA(insert OID = 2214 ( regoperin PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2 ...@@ -3304,6 +3306,8 @@ DATA(insert OID = 2214 ( regoperin PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2
DESCR("I/O"); 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_ )); 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"); 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_ )); 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"); 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_ )); 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_ ));
...@@ -3312,10 +3316,14 @@ DATA(insert OID = 2218 ( regclassin PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2 ...@@ -3312,10 +3316,14 @@ DATA(insert OID = 2218 ( regclassin PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2
DESCR("I/O"); 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_ )); 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"); 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_ )); 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"); 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_ )); 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"); 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_ )); 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"); DESCR("convert text to regclass");
......
...@@ -47,7 +47,7 @@ extern Datum stringTypeDatum(Type tp, char *string, int32 atttypmod); ...@@ -47,7 +47,7 @@ extern Datum stringTypeDatum(Type tp, char *string, int32 atttypmod);
extern Oid typeidTypeRelid(Oid type_id); 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) #define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid)
......
...@@ -597,6 +597,7 @@ extern char *regexp_fixed_prefix(text *text_re, bool case_insensitive, ...@@ -597,6 +597,7 @@ extern char *regexp_fixed_prefix(text *text_re, bool case_insensitive,
/* regproc.c */ /* regproc.c */
extern Datum regprocin(PG_FUNCTION_ARGS); extern Datum regprocin(PG_FUNCTION_ARGS);
extern Datum regprocout(PG_FUNCTION_ARGS); extern Datum regprocout(PG_FUNCTION_ARGS);
extern Datum to_regproc(PG_FUNCTION_ARGS);
extern Datum regprocrecv(PG_FUNCTION_ARGS); extern Datum regprocrecv(PG_FUNCTION_ARGS);
extern Datum regprocsend(PG_FUNCTION_ARGS); extern Datum regprocsend(PG_FUNCTION_ARGS);
extern Datum regprocedurein(PG_FUNCTION_ARGS); extern Datum regprocedurein(PG_FUNCTION_ARGS);
...@@ -607,6 +608,7 @@ extern Datum regoperin(PG_FUNCTION_ARGS); ...@@ -607,6 +608,7 @@ extern Datum regoperin(PG_FUNCTION_ARGS);
extern Datum regoperout(PG_FUNCTION_ARGS); extern Datum regoperout(PG_FUNCTION_ARGS);
extern Datum regoperrecv(PG_FUNCTION_ARGS); extern Datum regoperrecv(PG_FUNCTION_ARGS);
extern Datum regopersend(PG_FUNCTION_ARGS); extern Datum regopersend(PG_FUNCTION_ARGS);
extern Datum to_regoper(PG_FUNCTION_ARGS);
extern Datum regoperatorin(PG_FUNCTION_ARGS); extern Datum regoperatorin(PG_FUNCTION_ARGS);
extern Datum regoperatorout(PG_FUNCTION_ARGS); extern Datum regoperatorout(PG_FUNCTION_ARGS);
extern Datum regoperatorrecv(PG_FUNCTION_ARGS); extern Datum regoperatorrecv(PG_FUNCTION_ARGS);
...@@ -615,10 +617,12 @@ extern Datum regclassin(PG_FUNCTION_ARGS); ...@@ -615,10 +617,12 @@ extern Datum regclassin(PG_FUNCTION_ARGS);
extern Datum regclassout(PG_FUNCTION_ARGS); extern Datum regclassout(PG_FUNCTION_ARGS);
extern Datum regclassrecv(PG_FUNCTION_ARGS); extern Datum regclassrecv(PG_FUNCTION_ARGS);
extern Datum regclasssend(PG_FUNCTION_ARGS); extern Datum regclasssend(PG_FUNCTION_ARGS);
extern Datum to_regclass(PG_FUNCTION_ARGS);
extern Datum regtypein(PG_FUNCTION_ARGS); extern Datum regtypein(PG_FUNCTION_ARGS);
extern Datum regtypeout(PG_FUNCTION_ARGS); extern Datum regtypeout(PG_FUNCTION_ARGS);
extern Datum regtyperecv(PG_FUNCTION_ARGS); extern Datum regtyperecv(PG_FUNCTION_ARGS);
extern Datum regtypesend(PG_FUNCTION_ARGS); extern Datum regtypesend(PG_FUNCTION_ARGS);
extern Datum to_regtype(PG_FUNCTION_ARGS);
extern Datum regconfigin(PG_FUNCTION_ARGS); extern Datum regconfigin(PG_FUNCTION_ARGS);
extern Datum regconfigout(PG_FUNCTION_ARGS); extern Datum regconfigout(PG_FUNCTION_ARGS);
extern Datum regconfigrecv(PG_FUNCTION_ARGS); extern Datum regconfigrecv(PG_FUNCTION_ARGS);
......
...@@ -3420,7 +3420,7 @@ plperl_spi_prepare(char *query, int argc, SV **argv) ...@@ -3420,7 +3420,7 @@ plperl_spi_prepare(char *query, int argc, SV **argv)
char *typstr; char *typstr;
typstr = sv2cstr(argv[i]); typstr = sv2cstr(argv[i]);
parseTypeString(typstr, &typId, &typmod); parseTypeString(typstr, &typId, &typmod, false);
pfree(typstr); pfree(typstr);
getTypeInputInfo(typId, &typInput, &typIOParam); getTypeInputInfo(typId, &typInput, &typIOParam);
......
...@@ -3492,7 +3492,7 @@ parse_datatype(const char *string, int location) ...@@ -3492,7 +3492,7 @@ parse_datatype(const char *string, int location)
error_context_stack = &syntax_errcontext; error_context_stack = &syntax_errcontext;
/* Let the main parser try to parse it under standard SQL rules */ /* 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 */ /* Restore former ereport callback */
error_context_stack = syntax_errcontext.previous; error_context_stack = syntax_errcontext.previous;
......
...@@ -113,7 +113,7 @@ PLy_spi_prepare(PyObject *self, PyObject *args) ...@@ -113,7 +113,7 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
*information for input conversion. *information for input conversion.
********************************************************/ ********************************************************/
parseTypeString(sptr, &typeId, &typmod); parseTypeString(sptr, &typeId, &typmod, false);
typeTup = SearchSysCache1(TYPEOID, typeTup = SearchSysCache1(TYPEOID,
ObjectIdGetDatum(typeId)); ObjectIdGetDatum(typeId));
......
...@@ -2165,7 +2165,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp, ...@@ -2165,7 +2165,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
typIOParam; typIOParam;
int32 typmod; int32 typmod;
parseTypeString(args[i], &typId, &typmod); parseTypeString(args[i], &typId, &typmod, false);
getTypeInputInfo(typId, &typInput, &typIOParam); getTypeInputInfo(typId, &typInput, &typIOParam);
......
--
-- 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)
...@@ -13,7 +13,7 @@ test: tablespace ...@@ -13,7 +13,7 @@ test: tablespace
# ---------- # ----------
# The first group of parallel tests # 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 # Depends on things setup during char, varchar and text
test: strings test: strings
......
...@@ -20,6 +20,7 @@ test: enum ...@@ -20,6 +20,7 @@ test: enum
test: money test: money
test: rangetypes test: rangetypes
test: pg_lsn test: pg_lsn
test: regproc
test: strings test: strings
test: numerology test: numerology
test: point test: point
......
--
-- 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');
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment