mirror of
https://github.com/postgres/postgres.git
synced 2025-06-25 01:02:05 +03:00
Make DROP IF EXISTS more consistently not fail
Some cases were still reporting errors and aborting, instead of a NOTICE that the object was being skipped. This makes it more difficult to cleanly handle pg_dump --clean, so change that to instead skip missing objects properly. Per bug #7873 reported by Dave Rolsky; apparently this affects a large number of users. Authors: Pavel Stehule and Dean Rasheed. Some tweaks by Álvaro Herrera
This commit is contained in:
@ -1259,7 +1259,8 @@ func_get_detail(List *funcname,
|
||||
|
||||
/* Get list of possible candidates from namespace search */
|
||||
raw_candidates = FuncnameGetCandidates(funcname, nargs, fargnames,
|
||||
expand_variadic, expand_defaults);
|
||||
expand_variadic, expand_defaults,
|
||||
false);
|
||||
|
||||
/*
|
||||
* Quickly check if there is an exact match to the input datatypes (there
|
||||
@ -1714,7 +1715,7 @@ FuncNameAsType(List *funcname)
|
||||
Oid result;
|
||||
Type typtup;
|
||||
|
||||
typtup = LookupTypeName(NULL, makeTypeNameFromNameList(funcname), NULL);
|
||||
typtup = LookupTypeName(NULL, makeTypeNameFromNameList(funcname), NULL, false);
|
||||
if (typtup == NULL)
|
||||
return InvalidOid;
|
||||
|
||||
@ -1873,7 +1874,7 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
|
||||
{
|
||||
FuncCandidateList clist;
|
||||
|
||||
clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false);
|
||||
clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false, noError);
|
||||
|
||||
while (clist)
|
||||
{
|
||||
@ -1892,27 +1893,6 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
|
||||
return InvalidOid;
|
||||
}
|
||||
|
||||
/*
|
||||
* LookupTypeNameOid
|
||||
* Convenience routine to look up a type, silently accepting shell types
|
||||
*/
|
||||
static Oid
|
||||
LookupTypeNameOid(const TypeName *typename)
|
||||
{
|
||||
Oid result;
|
||||
Type typtup;
|
||||
|
||||
typtup = LookupTypeName(NULL, typename, NULL);
|
||||
if (typtup == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type \"%s\" does not exist",
|
||||
TypeNameToString(typename))));
|
||||
result = typeTypeId(typtup);
|
||||
ReleaseSysCache(typtup);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* LookupFuncNameTypeNames
|
||||
* Like LookupFuncName, but the argument types are specified by a
|
||||
@ -1940,7 +1920,7 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError)
|
||||
{
|
||||
TypeName *t = (TypeName *) lfirst(args_item);
|
||||
|
||||
argoids[i] = LookupTypeNameOid(t);
|
||||
argoids[i] = LookupTypeNameOid(NULL, t, noError);
|
||||
args_item = lnext(args_item);
|
||||
}
|
||||
|
||||
@ -1980,7 +1960,7 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError)
|
||||
{
|
||||
TypeName *t = (TypeName *) lfirst(lc);
|
||||
|
||||
argoids[i] = LookupTypeNameOid(t);
|
||||
argoids[i] = LookupTypeNameOid(NULL, t, noError);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -148,12 +148,12 @@ LookupOperNameTypeNames(ParseState *pstate, List *opername,
|
||||
if (oprleft == NULL)
|
||||
leftoid = InvalidOid;
|
||||
else
|
||||
leftoid = typenameTypeId(pstate, oprleft);
|
||||
leftoid = LookupTypeNameOid(pstate, oprleft, noError);
|
||||
|
||||
if (oprright == NULL)
|
||||
rightoid = InvalidOid;
|
||||
else
|
||||
rightoid = typenameTypeId(pstate, oprright);
|
||||
rightoid = LookupTypeNameOid(pstate, oprright, noError);
|
||||
|
||||
return LookupOperName(pstate, opername, leftoid, rightoid,
|
||||
noError, location);
|
||||
|
@ -56,7 +56,7 @@ static int32 typenameTypeMod(ParseState *pstate, const TypeName *typeName,
|
||||
*/
|
||||
Type
|
||||
LookupTypeName(ParseState *pstate, const TypeName *typeName,
|
||||
int32 *typmod_p)
|
||||
int32 *typmod_p, bool missing_ok)
|
||||
{
|
||||
Oid typoid;
|
||||
HeapTuple tup;
|
||||
@ -116,24 +116,32 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName,
|
||||
* concurrent DDL. But taking a lock would carry a performance
|
||||
* penalty and would also require a permissions check.
|
||||
*/
|
||||
relid = RangeVarGetRelid(rel, NoLock, false);
|
||||
relid = RangeVarGetRelid(rel, NoLock, missing_ok);
|
||||
attnum = get_attnum(relid, field);
|
||||
if (attnum == InvalidAttrNumber)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("column \"%s\" of relation \"%s\" does not exist",
|
||||
field, rel->relname),
|
||||
parser_errposition(pstate, typeName->location)));
|
||||
typoid = get_atttype(relid, attnum);
|
||||
{
|
||||
if (missing_ok)
|
||||
typoid = InvalidOid;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("column \"%s\" of relation \"%s\" does not exist",
|
||||
field, rel->relname),
|
||||
parser_errposition(pstate, typeName->location)));
|
||||
}
|
||||
else
|
||||
{
|
||||
typoid = get_atttype(relid, attnum);
|
||||
|
||||
/* this construct should never have an array indicator */
|
||||
Assert(typeName->arrayBounds == NIL);
|
||||
/* this construct should never have an array indicator */
|
||||
Assert(typeName->arrayBounds == NIL);
|
||||
|
||||
/* emit nuisance notice (intentionally not errposition'd) */
|
||||
ereport(NOTICE,
|
||||
(errmsg("type reference %s converted to %s",
|
||||
TypeNameToString(typeName),
|
||||
format_type_be(typoid))));
|
||||
/* emit nuisance notice (intentionally not errposition'd) */
|
||||
ereport(NOTICE,
|
||||
(errmsg("type reference %s converted to %s",
|
||||
TypeNameToString(typeName),
|
||||
format_type_be(typoid))));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -149,10 +157,13 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName,
|
||||
/* Look in specific schema only */
|
||||
Oid namespaceId;
|
||||
|
||||
namespaceId = LookupExplicitNamespace(schemaname, false);
|
||||
typoid = GetSysCacheOid2(TYPENAMENSP,
|
||||
PointerGetDatum(typname),
|
||||
ObjectIdGetDatum(namespaceId));
|
||||
namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
|
||||
if (OidIsValid(namespaceId))
|
||||
typoid = GetSysCacheOid2(TYPENAMENSP,
|
||||
PointerGetDatum(typname),
|
||||
ObjectIdGetDatum(namespaceId));
|
||||
else
|
||||
typoid = InvalidOid;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -184,6 +195,43 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName,
|
||||
return (Type) tup;
|
||||
}
|
||||
|
||||
/*
|
||||
* LookupTypeNameOid
|
||||
* Given a TypeName object, lookup the pg_type syscache entry of the type.
|
||||
* Returns InvalidOid if no such type can be found. If the type is found,
|
||||
* return its Oid.
|
||||
*
|
||||
* NB: direct callers of this function need to be aware that the type OID
|
||||
* returned may correspond to a shell type. Most code should go through
|
||||
* typenameTypeId instead.
|
||||
*
|
||||
* pstate is only used for error location info, and may be NULL.
|
||||
*/
|
||||
Oid
|
||||
LookupTypeNameOid(ParseState *pstate, const TypeName *typeName, bool missing_ok)
|
||||
{
|
||||
Oid typoid;
|
||||
Type tup;
|
||||
|
||||
tup = LookupTypeName(pstate, typeName, NULL, missing_ok);
|
||||
if (tup == NULL)
|
||||
{
|
||||
if (!missing_ok)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type \"%s\" does not exist",
|
||||
TypeNameToString(typeName)),
|
||||
parser_errposition(pstate, typeName->location)));
|
||||
|
||||
return InvalidOid;
|
||||
}
|
||||
|
||||
typoid = HeapTupleGetOid(tup);
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
return typoid;
|
||||
}
|
||||
|
||||
/*
|
||||
* typenameType - given a TypeName, return a Type structure and typmod
|
||||
*
|
||||
@ -196,7 +244,7 @@ typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
|
||||
{
|
||||
Type tup;
|
||||
|
||||
tup = LookupTypeName(pstate, typeName, typmod_p);
|
||||
tup = LookupTypeName(pstate, typeName, typmod_p, false);
|
||||
if (tup == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
|
Reference in New Issue
Block a user