#include "catalog/pg_ts_dict.h"
#include "catalog/pg_type.h"
#include "lib/stringinfo.h"
+#include "mb/pg_wchar.h"
#include "miscadmin.h"
+#include "nodes/miscnodes.h"
#include "parser/parse_type.h"
#include "parser/scansup.h"
#include "utils/acl.h"
static bool parseNumericOid(char *string, Oid *result, Node *escontext);
static bool parseDashOrOid(char *string, Oid *result, Node *escontext);
-static void parseNameAndArgTypes(const char *string, bool allowNone,
- List **names, int *nargs, Oid *argtypes);
+static bool parseNameAndArgTypes(const char *string, bool allowNone,
+ List **names, int *nargs, Oid *argtypes,
+ Node *escontext);
/*****************************************************************************
regprocin(PG_FUNCTION_ARGS)
{
char *pro_name_or_oid = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
RegProcedure result;
List *names;
FuncCandidateList clist;
/* Handle "-" or numeric OID */
- if (parseDashOrOid(pro_name_or_oid, &result, fcinfo->context))
+ if (parseDashOrOid(pro_name_or_oid, &result, escontext))
PG_RETURN_OID(result);
/* Else it's a name, possibly schema-qualified */
* Normal case: parse the name into components and see if it matches any
* pg_proc entries in the current search path.
*/
- names = stringToQualifiedNameList(pro_name_or_oid);
- clist = FuncnameGetCandidates(names, -1, NIL, false, false, false, false);
+ names = stringToQualifiedNameList(pro_name_or_oid, escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
+
+ clist = FuncnameGetCandidates(names, -1, NIL, false, false, false, true);
if (clist == NULL)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function \"%s\" does not exist", pro_name_or_oid)));
else if (clist->next != NULL)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
errmsg("more than one function named \"%s\"",
pro_name_or_oid)));
char *pro_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
List *names;
FuncCandidateList clist;
+ ErrorSaveContext escontext = {T_ErrorSaveContext};
/*
* Parse the name into components and see if it matches any pg_proc
* entries in the current search path.
*/
- names = stringToQualifiedNameList(pro_name);
+ names = stringToQualifiedNameList(pro_name, (Node *) &escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
+
clist = FuncnameGetCandidates(names, -1, NIL, false, false, false, true);
if (clist == NULL || clist->next != NULL)
regprocedurein(PG_FUNCTION_ARGS)
{
char *pro_name_or_oid = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
RegProcedure result;
List *names;
int nargs;
FuncCandidateList clist;
/* Handle "-" or numeric OID */
- if (parseDashOrOid(pro_name_or_oid, &result, fcinfo->context))
+ if (parseDashOrOid(pro_name_or_oid, &result, escontext))
PG_RETURN_OID(result);
/* The rest of this wouldn't work in bootstrap mode */
* which one exactly matches the given argument types. (There will not be
* more than one match.)
*/
- parseNameAndArgTypes(pro_name_or_oid, false, &names, &nargs, argtypes);
+ if (!parseNameAndArgTypes(pro_name_or_oid, false,
+ &names, &nargs, argtypes,
+ escontext))
+ PG_RETURN_NULL();
clist = FuncnameGetCandidates(names, nargs, NIL, false, false,
- false, false);
+ false, true);
for (; clist; clist = clist->next)
{
}
if (clist == NULL)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function \"%s\" does not exist", pro_name_or_oid)));
int nargs;
Oid argtypes[FUNC_MAX_ARGS];
FuncCandidateList clist;
+ ErrorSaveContext escontext = {T_ErrorSaveContext};
/*
* Parse the name and arguments, look up potential matches in the current
* namespace search list, and scan to see which one exactly matches the
* given argument types. (There will not be more than one match.)
*/
- parseNameAndArgTypes(pro_name, false, &names, &nargs, argtypes);
+ if (!parseNameAndArgTypes(pro_name, false,
+ &names, &nargs, argtypes,
+ (Node *) &escontext))
+ PG_RETURN_NULL();
clist = FuncnameGetCandidates(names, nargs, NIL, false, false, false, true);
regoperin(PG_FUNCTION_ARGS)
{
char *opr_name_or_oid = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
Oid result;
List *names;
FuncCandidateList clist;
/* Handle "0" or numeric OID */
- if (parseNumericOid(opr_name_or_oid, &result, fcinfo->context))
+ if (parseNumericOid(opr_name_or_oid, &result, escontext))
PG_RETURN_OID(result);
/* Else it's a name, possibly schema-qualified */
* Normal case: parse the name into components and see if it matches any
* pg_operator entries in the current search path.
*/
- names = stringToQualifiedNameList(opr_name_or_oid);
- clist = OpernameGetCandidates(names, '\0', false);
+ names = stringToQualifiedNameList(opr_name_or_oid, escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
+
+ clist = OpernameGetCandidates(names, '\0', true);
if (clist == NULL)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("operator does not exist: %s", opr_name_or_oid)));
else if (clist->next != NULL)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
errmsg("more than one operator named %s",
opr_name_or_oid)));
char *opr_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
List *names;
FuncCandidateList clist;
+ ErrorSaveContext escontext = {T_ErrorSaveContext};
/*
* Parse the name into components and see if it matches any pg_operator
* entries in the current search path.
*/
- names = stringToQualifiedNameList(opr_name);
+ names = stringToQualifiedNameList(opr_name, (Node *) &escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
+
clist = OpernameGetCandidates(names, '\0', true);
if (clist == NULL || clist->next != NULL)
regoperatorin(PG_FUNCTION_ARGS)
{
char *opr_name_or_oid = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
Oid result;
List *names;
int nargs;
Oid argtypes[FUNC_MAX_ARGS];
/* Handle "0" or numeric OID */
- if (parseNumericOid(opr_name_or_oid, &result, fcinfo->context))
+ if (parseNumericOid(opr_name_or_oid, &result, escontext))
PG_RETURN_OID(result);
/* The rest of this wouldn't work in bootstrap mode */
* which one exactly matches the given argument types. (There will not be
* more than one match.)
*/
- parseNameAndArgTypes(opr_name_or_oid, true, &names, &nargs, argtypes);
+ if (!parseNameAndArgTypes(opr_name_or_oid, true,
+ &names, &nargs, argtypes,
+ escontext))
+ PG_RETURN_NULL();
+
if (nargs == 1)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_UNDEFINED_PARAMETER),
errmsg("missing argument"),
errhint("Use NONE to denote the missing argument of a unary operator.")));
if (nargs != 2)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
errmsg("too many arguments"),
errhint("Provide two argument types for operator.")));
result = OpernameGetOprid(names, argtypes[0], argtypes[1]);
if (!OidIsValid(result))
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("operator does not exist: %s", opr_name_or_oid)));
List *names;
int nargs;
Oid argtypes[FUNC_MAX_ARGS];
+ ErrorSaveContext escontext = {T_ErrorSaveContext};
/*
* Parse the name and arguments, look up potential matches in the current
* namespace search list, and scan to see which one exactly matches the
* given argument types. (There will not be more than one match.)
*/
- parseNameAndArgTypes(opr_name_or_oid, true, &names, &nargs, argtypes);
- if (nargs == 1)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_PARAMETER),
- errmsg("missing argument"),
- errhint("Use NONE to denote the missing argument of a unary operator.")));
+ if (!parseNameAndArgTypes(opr_name_or_oid, true,
+ &names, &nargs, argtypes,
+ (Node *) &escontext))
+ PG_RETURN_NULL();
+
if (nargs != 2)
- ereport(ERROR,
- (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
- errmsg("too many arguments"),
- errhint("Provide two argument types for operator.")));
+ PG_RETURN_NULL();
result = OpernameGetOprid(names, argtypes[0], argtypes[1]);
regclassin(PG_FUNCTION_ARGS)
{
char *class_name_or_oid = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
Oid result;
List *names;
/* Handle "-" or numeric OID */
- if (parseDashOrOid(class_name_or_oid, &result, fcinfo->context))
+ if (parseDashOrOid(class_name_or_oid, &result, escontext))
PG_RETURN_OID(result);
/* Else it's a name, possibly schema-qualified */
* Normal case: parse the name into components and see if it matches any
* pg_class entries in the current search path.
*/
- names = stringToQualifiedNameList(class_name_or_oid);
+ names = stringToQualifiedNameList(class_name_or_oid, escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
/* We might not even have permissions on this relation; don't lock it. */
- result = RangeVarGetRelid(makeRangeVarFromNameList(names), NoLock, false);
+ result = RangeVarGetRelid(makeRangeVarFromNameList(names), NoLock, true);
+
+ if (!OidIsValid(result))
+ ereturn(escontext, (Datum) 0,
+ (errcode(ERRCODE_UNDEFINED_TABLE),
+ errmsg("relation \"%s\" does not exist",
+ NameListToString(names))));
PG_RETURN_OID(result);
}
char *class_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
Oid result;
List *names;
+ ErrorSaveContext escontext = {T_ErrorSaveContext};
/*
* Parse the name into components and see if it matches any pg_class
* entries in the current search path.
*/
- names = stringToQualifiedNameList(class_name);
+ names = stringToQualifiedNameList(class_name, (Node *) &escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
/* We might not even have permissions on this relation; don't lock it. */
result = RangeVarGetRelid(makeRangeVarFromNameList(names), NoLock, true);
regcollationin(PG_FUNCTION_ARGS)
{
char *collation_name_or_oid = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
Oid result;
List *names;
/* Handle "-" or numeric OID */
- if (parseDashOrOid(collation_name_or_oid, &result, fcinfo->context))
+ if (parseDashOrOid(collation_name_or_oid, &result, escontext))
PG_RETURN_OID(result);
/* Else it's a name, possibly schema-qualified */
* Normal case: parse the name into components and see if it matches any
* pg_collation entries in the current search path.
*/
- names = stringToQualifiedNameList(collation_name_or_oid);
+ names = stringToQualifiedNameList(collation_name_or_oid, escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
+
+ result = get_collation_oid(names, true);
- result = get_collation_oid(names, false);
+ if (!OidIsValid(result))
+ ereturn(escontext, (Datum) 0,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("collation \"%s\" for encoding \"%s\" does not exist",
+ NameListToString(names), GetDatabaseEncodingName())));
PG_RETURN_OID(result);
}
char *collation_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
Oid result;
List *names;
+ ErrorSaveContext escontext = {T_ErrorSaveContext};
/*
* Parse the name into components and see if it matches any pg_collation
* entries in the current search path.
*/
- names = stringToQualifiedNameList(collation_name);
+ names = stringToQualifiedNameList(collation_name, (Node *) &escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
result = get_collation_oid(names, true);
regtypein(PG_FUNCTION_ARGS)
{
char *typ_name_or_oid = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
Oid result;
int32 typmod;
/* Handle "-" or numeric OID */
- if (parseDashOrOid(typ_name_or_oid, &result, fcinfo->context))
+ if (parseDashOrOid(typ_name_or_oid, &result, escontext))
PG_RETURN_OID(result);
/* Else it's a type name, possibly schema-qualified or decorated */
/*
* Normal case: invoke the full parser to deal with special cases such as
- * array syntax.
+ * array syntax. We don't need to check for parseTypeString failure,
+ * since we'll just return anyway.
*/
- parseTypeString(typ_name_or_oid, &result, &typmod, false);
+ (void) parseTypeString(typ_name_or_oid, &result, &typmod, escontext);
PG_RETURN_OID(result);
}
char *typ_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
Oid result;
int32 typmod;
+ ErrorSaveContext escontext = {T_ErrorSaveContext};
/*
* Invoke the full parser to deal with special cases such as array syntax.
*/
- parseTypeString(typ_name, &result, &typmod, true);
-
- if (OidIsValid(result))
+ if (parseTypeString(typ_name, &result, &typmod, (Node *) &escontext))
PG_RETURN_OID(result);
else
PG_RETURN_NULL();
regconfigin(PG_FUNCTION_ARGS)
{
char *cfg_name_or_oid = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
Oid result;
List *names;
/* Handle "-" or numeric OID */
- if (parseDashOrOid(cfg_name_or_oid, &result, fcinfo->context))
+ if (parseDashOrOid(cfg_name_or_oid, &result, escontext))
PG_RETURN_OID(result);
/* The rest of this wouldn't work in bootstrap mode */
* Normal case: parse the name into components and see if it matches any
* pg_ts_config entries in the current search path.
*/
- names = stringToQualifiedNameList(cfg_name_or_oid);
+ names = stringToQualifiedNameList(cfg_name_or_oid, escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
- result = get_ts_config_oid(names, false);
+ result = get_ts_config_oid(names, true);
+
+ if (!OidIsValid(result))
+ ereturn(escontext, (Datum) 0,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("text search configuration \"%s\" does not exist",
+ NameListToString(names))));
PG_RETURN_OID(result);
}
regdictionaryin(PG_FUNCTION_ARGS)
{
char *dict_name_or_oid = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
Oid result;
List *names;
/* Handle "-" or numeric OID */
- if (parseDashOrOid(dict_name_or_oid, &result, fcinfo->context))
+ if (parseDashOrOid(dict_name_or_oid, &result, escontext))
PG_RETURN_OID(result);
/* The rest of this wouldn't work in bootstrap mode */
* Normal case: parse the name into components and see if it matches any
* pg_ts_dict entries in the current search path.
*/
- names = stringToQualifiedNameList(dict_name_or_oid);
+ names = stringToQualifiedNameList(dict_name_or_oid, escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
+
+ result = get_ts_dict_oid(names, true);
- result = get_ts_dict_oid(names, false);
+ if (!OidIsValid(result))
+ ereturn(escontext, (Datum) 0,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("text search dictionary \"%s\" does not exist",
+ NameListToString(names))));
PG_RETURN_OID(result);
}
regrolein(PG_FUNCTION_ARGS)
{
char *role_name_or_oid = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
Oid result;
List *names;
/* Handle "-" or numeric OID */
- if (parseDashOrOid(role_name_or_oid, &result, fcinfo->context))
+ if (parseDashOrOid(role_name_or_oid, &result, escontext))
PG_RETURN_OID(result);
/* The rest of this wouldn't work in bootstrap mode */
elog(ERROR, "regrole values must be OIDs in bootstrap mode");
/* Normal case: see if the name matches any pg_authid entry. */
- names = stringToQualifiedNameList(role_name_or_oid);
+ names = stringToQualifiedNameList(role_name_or_oid, escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
if (list_length(names) != 1)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_NAME),
errmsg("invalid name syntax")));
- result = get_role_oid(strVal(linitial(names)), false);
+ result = get_role_oid(strVal(linitial(names)), true);
+
+ if (!OidIsValid(result))
+ ereturn(escontext, (Datum) 0,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("role \"%s\" does not exist",
+ strVal(linitial(names)))));
PG_RETURN_OID(result);
}
char *role_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
Oid result;
List *names;
+ ErrorSaveContext escontext = {T_ErrorSaveContext};
- names = stringToQualifiedNameList(role_name);
+ names = stringToQualifiedNameList(role_name, (Node *) &escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
if (list_length(names) != 1)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_NAME),
- errmsg("invalid name syntax")));
+ PG_RETURN_NULL();
result = get_role_oid(strVal(linitial(names)), true);
regnamespacein(PG_FUNCTION_ARGS)
{
char *nsp_name_or_oid = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
Oid result;
List *names;
/* Handle "-" or numeric OID */
- if (parseDashOrOid(nsp_name_or_oid, &result, fcinfo->context))
+ if (parseDashOrOid(nsp_name_or_oid, &result, escontext))
PG_RETURN_OID(result);
/* The rest of this wouldn't work in bootstrap mode */
elog(ERROR, "regnamespace values must be OIDs in bootstrap mode");
/* Normal case: see if the name matches any pg_namespace entry. */
- names = stringToQualifiedNameList(nsp_name_or_oid);
+ names = stringToQualifiedNameList(nsp_name_or_oid, escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
if (list_length(names) != 1)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_NAME),
errmsg("invalid name syntax")));
- result = get_namespace_oid(strVal(linitial(names)), false);
+ result = get_namespace_oid(strVal(linitial(names)), true);
+
+ if (!OidIsValid(result))
+ ereturn(escontext, (Datum) 0,
+ (errcode(ERRCODE_UNDEFINED_SCHEMA),
+ errmsg("schema \"%s\" does not exist",
+ strVal(linitial(names)))));
PG_RETURN_OID(result);
}
char *nsp_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
Oid result;
List *names;
+ ErrorSaveContext escontext = {T_ErrorSaveContext};
- names = stringToQualifiedNameList(nsp_name);
+ names = stringToQualifiedNameList(nsp_name, (Node *) &escontext);
+ if (names == NIL)
+ PG_RETURN_NULL();
if (list_length(names) != 1)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_NAME),
- errmsg("invalid name syntax")));
+ PG_RETURN_NULL();
result = get_namespace_oid(strVal(linitial(names)), true);
/*
* Given a C string, parse it into a qualified-name list.
+ *
+ * If escontext is an ErrorSaveContext node, invalid input will be
+ * reported there instead of being thrown, and we return NIL.
+ * (NIL is not possible as a success return, since empty-input is an error.)
*/
List *
-stringToQualifiedNameList(const char *string)
+stringToQualifiedNameList(const char *string, Node *escontext)
{
char *rawname;
List *result = NIL;
rawname = pstrdup(string);
if (!SplitIdentifierString(rawname, '.', &namelist))
- ereport(ERROR,
+ ereturn(escontext, NIL,
(errcode(ERRCODE_INVALID_NAME),
errmsg("invalid name syntax")));
if (namelist == NIL)
- ereport(ERROR,
+ ereturn(escontext, NIL,
(errcode(ERRCODE_INVALID_NAME),
errmsg("invalid name syntax")));
*
* If allowNone is true, accept "NONE" and return it as InvalidOid (this is
* for unary operators).
+ *
+ * Returns true on success, false on failure (the latter only possible
+ * if escontext is an ErrorSaveContext node).
*/
-static void
+static bool
parseNameAndArgTypes(const char *string, bool allowNone, List **names,
- int *nargs, Oid *argtypes)
+ int *nargs, Oid *argtypes,
+ Node *escontext)
{
char *rawname;
char *ptr;
break;
}
if (*ptr == '\0')
- ereport(ERROR,
+ ereturn(escontext, false,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("expected a left parenthesis")));
/* Separate the name and parse it into a list */
*ptr++ = '\0';
- *names = stringToQualifiedNameList(rawname);
+ *names = stringToQualifiedNameList(rawname, escontext);
+ if (*names == NIL)
+ return false;
/* Check for the trailing right parenthesis and remove it */
ptr2 = ptr + strlen(ptr);
break;
}
if (*ptr2 != ')')
- ereport(ERROR,
+ ereturn(escontext, false,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("expected a right parenthesis")));
{
/* End of string. Okay unless we had a comma before. */
if (had_comma)
- ereport(ERROR,
+ ereturn(escontext, false,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("expected a type name")));
break;
}
}
if (in_quote || paren_count != 0)
- ereport(ERROR,
+ ereturn(escontext, false,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("improper type name")));
else
{
/* Use full parser to resolve the type name */
- parseTypeString(typename, &typeid, &typmod, false);
+ if (!parseTypeString(typename, &typeid, &typmod, escontext))
+ return false;
}
if (*nargs >= FUNC_MAX_ARGS)
- ereport(ERROR,
+ ereturn(escontext, false,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
errmsg("too many arguments")));
}
pfree(rawname);
+
+ return true;
}
^
-- with schemaname
SELECT regoper('ng_catalog.||/');
-ERROR: schema "ng_catalog" does not exist
+ERROR: operator does not exist: ng_catalog.||/
LINE 1: SELECT regoper('ng_catalog.||/');
^
SELECT regoperator('ng_catalog.+(int4,int4)');
LINE 1: SELECT regoperator('ng_catalog.+(int4,int4)');
^
SELECT regproc('ng_catalog.now');
-ERROR: schema "ng_catalog" does not exist
+ERROR: function "ng_catalog.now" does not exist
LINE 1: SELECT regproc('ng_catalog.now');
^
SELECT regprocedure('ng_catalog.abs(numeric)');
-ERROR: schema "ng_catalog" does not exist
+ERROR: function "ng_catalog.abs(numeric)" does not exist
LINE 1: SELECT regprocedure('ng_catalog.abs(numeric)');
^
SELECT regclass('ng_catalog.pg_class');
-ERROR: schema "ng_catalog" does not exist
+ERROR: relation "ng_catalog.pg_class" does not exist
LINE 1: SELECT regclass('ng_catalog.pg_class');
^
SELECT regtype('ng_catalog.int4');
LINE 1: SELECT regtype('ng_catalog.int4');
^
SELECT regcollation('ng_catalog."POSIX"');
-ERROR: schema "ng_catalog" does not exist
+ERROR: collation "ng_catalog.POSIX" for encoding "SQL_ASCII" does not exist
LINE 1: SELECT regcollation('ng_catalog."POSIX"');
^
-- schemaname not applicable
(1 row)
SELECT to_regrole('foo.bar');
-ERROR: invalid name syntax
+ to_regrole
+------------
+
+(1 row)
+
SELECT to_regrole('Nonexistent');
to_regrole
------------
(1 row)
SELECT to_regrole('foo.bar');
-ERROR: invalid name syntax
+ to_regrole
+------------
+
+(1 row)
+
SELECT to_regnamespace('Nonexistent');
to_regnamespace
-----------------
(1 row)
SELECT to_regnamespace('foo.bar');
-ERROR: invalid name syntax
+ to_regnamespace
+-----------------
+
+(1 row)
+
+-- Test soft-error API
+SELECT pg_input_error_message('ng_catalog.pg_class', 'regclass');
+ pg_input_error_message
+-----------------------------------------------
+ relation "ng_catalog.pg_class" does not exist
+(1 row)
+
+SELECT pg_input_error_message('ng_catalog."POSIX"', 'regcollation');
+ pg_input_error_message
+----------------------------------------------------------------------
+ collation "ng_catalog.POSIX" for encoding "SQL_ASCII" does not exist
+(1 row)
+
+SELECT pg_input_error_message('no_such_config', 'regconfig');
+ pg_input_error_message
+-----------------------------------------------------------
+ text search configuration "no_such_config" does not exist
+(1 row)
+
+SELECT pg_input_error_message('no_such_dictionary', 'regdictionary');
+ pg_input_error_message
+------------------------------------------------------------
+ text search dictionary "no_such_dictionary" does not exist
+(1 row)
+
+SELECT pg_input_error_message('Nonexistent', 'regnamespace');
+ pg_input_error_message
+-------------------------------------
+ schema "nonexistent" does not exist
+(1 row)
+
+SELECT pg_input_error_message('ng_catalog.||/', 'regoper');
+ pg_input_error_message
+-----------------------------------------
+ operator does not exist: ng_catalog.||/
+(1 row)
+
+SELECT pg_input_error_message('-', 'regoper');
+ pg_input_error_message
+--------------------------------
+ more than one operator named -
+(1 row)
+
+SELECT pg_input_error_message('ng_catalog.+(int4,int4)', 'regoperator');
+ pg_input_error_message
+--------------------------------------------------
+ operator does not exist: ng_catalog.+(int4,int4)
+(1 row)
+
+SELECT pg_input_error_message('-', 'regoperator');
+ pg_input_error_message
+-----------------------------
+ expected a left parenthesis
+(1 row)
+
+SELECT pg_input_error_message('ng_catalog.now', 'regproc');
+ pg_input_error_message
+------------------------------------------
+ function "ng_catalog.now" does not exist
+(1 row)
+
+SELECT pg_input_error_message('ng_catalog.abs(numeric)', 'regprocedure');
+ pg_input_error_message
+---------------------------------------------------
+ function "ng_catalog.abs(numeric)" does not exist
+(1 row)
+
+SELECT pg_input_error_message('ng_catalog.abs(numeric', 'regprocedure');
+ pg_input_error_message
+------------------------------
+ expected a right parenthesis
+(1 row)
+
+SELECT pg_input_error_message('regress_regrole_test', 'regrole');
+ pg_input_error_message
+--------------------------------------------
+ role "regress_regrole_test" does not exist
+(1 row)
+
+SELECT pg_input_error_message('no_such_type', 'regtype');
+ pg_input_error_message
+------------------------------------
+ type "no_such_type" does not exist
+(1 row)
+
+-- Some cases that should be soft errors, but are not yet
+SELECT pg_input_error_message('incorrect type name syntax', 'regtype');
+ERROR: syntax error at or near "type"
+LINE 1: SELECT pg_input_error_message('incorrect type name syntax', ...
+ ^
+CONTEXT: invalid type name "incorrect type name syntax"
+SELECT pg_input_error_message('numeric(1,2,3)', 'regtype'); -- bogus typmod
+ERROR: invalid NUMERIC type modifier
+SELECT pg_input_error_message('way.too.many.names', 'regtype');
+ERROR: improper qualified name (too many dotted names): way.too.many.names
+SELECT pg_input_error_message('no_such_catalog.schema.name', 'regtype');
+ERROR: cross-database references are not implemented: no_such_catalog.schema.name