mirror of
https://github.com/postgres/postgres.git
synced 2025-06-16 06:01:02 +03:00
Further code review for range types patch.
Fix some bugs in coercion logic and pg_dump; more comment cleanup; minor cosmetic improvements.
This commit is contained in:
@ -4506,6 +4506,12 @@ SELECT * FROM pg_attribute
|
|||||||
<entry>Indicates that a function accepts any input data type.</entry>
|
<entry>Indicates that a function accepts any input data type.</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><type>anyelement</></entry>
|
||||||
|
<entry>Indicates that a function accepts any data type
|
||||||
|
(see <xref linkend="extend-types-polymorphic">).</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry><type>anyarray</></entry>
|
<entry><type>anyarray</></entry>
|
||||||
<entry>Indicates that a function accepts any array data type
|
<entry>Indicates that a function accepts any array data type
|
||||||
@ -4513,8 +4519,8 @@ SELECT * FROM pg_attribute
|
|||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry><type>anyelement</></entry>
|
<entry><type>anynonarray</></entry>
|
||||||
<entry>Indicates that a function accepts any data type
|
<entry>Indicates that a function accepts any non-array data type
|
||||||
(see <xref linkend="extend-types-polymorphic">).</entry>
|
(see <xref linkend="extend-types-polymorphic">).</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
@ -4532,12 +4538,6 @@ SELECT * FROM pg_attribute
|
|||||||
<xref linkend="rangetypes">).</entry>
|
<xref linkend="rangetypes">).</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry><type>anynonarray</></entry>
|
|
||||||
<entry>Indicates that a function accepts any non-array data type
|
|
||||||
(see <xref linkend="extend-types-polymorphic">).</entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry><type>cstring</></entry>
|
<entry><type>cstring</></entry>
|
||||||
<entry>Indicates that a function accepts or returns a null-terminated C string.</entry>
|
<entry>Indicates that a function accepts or returns a null-terminated C string.</entry>
|
||||||
@ -4595,9 +4595,9 @@ SELECT * FROM pg_attribute
|
|||||||
languages all forbid use of a pseudo-type as argument type, and allow
|
languages all forbid use of a pseudo-type as argument type, and allow
|
||||||
only <type>void</> and <type>record</> as a result type (plus
|
only <type>void</> and <type>record</> as a result type (plus
|
||||||
<type>trigger</> when the function is used as a trigger). Some also
|
<type>trigger</> when the function is used as a trigger). Some also
|
||||||
support polymorphic functions using the types <type>anyarray</>,
|
support polymorphic functions using the types <type>anyelement</>,
|
||||||
<type>anyelement</>, <type>anyenum</>, <type>anyrange</>, and
|
<type>anyarray</>, <type>anynonarray</>, <type>anyenum</>, and
|
||||||
<type>anynonarray</>.
|
<type>anyrange</>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
@ -91,7 +91,7 @@ ProcedureCreate(const char *procedureName,
|
|||||||
int parameterCount;
|
int parameterCount;
|
||||||
int allParamCount;
|
int allParamCount;
|
||||||
Oid *allParams;
|
Oid *allParams;
|
||||||
char *modes = NULL;
|
char *paramModes = NULL;
|
||||||
bool genericInParam = false;
|
bool genericInParam = false;
|
||||||
bool genericOutParam = false;
|
bool genericOutParam = false;
|
||||||
bool anyrangeInParam = false;
|
bool anyrangeInParam = false;
|
||||||
@ -130,6 +130,7 @@ ProcedureCreate(const char *procedureName,
|
|||||||
FUNC_MAX_ARGS)));
|
FUNC_MAX_ARGS)));
|
||||||
/* note: the above is correct, we do NOT count output arguments */
|
/* note: the above is correct, we do NOT count output arguments */
|
||||||
|
|
||||||
|
/* Deconstruct array inputs */
|
||||||
if (allParameterTypes != PointerGetDatum(NULL))
|
if (allParameterTypes != PointerGetDatum(NULL))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -169,28 +170,27 @@ ProcedureCreate(const char *procedureName,
|
|||||||
ARR_HASNULL(modesArray) ||
|
ARR_HASNULL(modesArray) ||
|
||||||
ARR_ELEMTYPE(modesArray) != CHAROID)
|
ARR_ELEMTYPE(modesArray) != CHAROID)
|
||||||
elog(ERROR, "parameterModes is not a 1-D char array");
|
elog(ERROR, "parameterModes is not a 1-D char array");
|
||||||
modes = (char *) ARR_DATA_PTR(modesArray);
|
paramModes = (char *) ARR_DATA_PTR(modesArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do not allow polymorphic return type unless at least one input argument
|
* Detect whether we have polymorphic or INTERNAL arguments. The first
|
||||||
* is polymorphic. Also, do not allow return type INTERNAL unless at
|
* loop checks input arguments, the second output arguments.
|
||||||
* least one input argument is INTERNAL.
|
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < parameterCount; i++)
|
for (i = 0; i < parameterCount; i++)
|
||||||
{
|
{
|
||||||
switch (parameterTypes->values[i])
|
switch (parameterTypes->values[i])
|
||||||
{
|
{
|
||||||
case ANYRANGEOID:
|
|
||||||
anyrangeInParam = true;
|
|
||||||
/* FALL THROUGH */
|
|
||||||
case ANYARRAYOID:
|
case ANYARRAYOID:
|
||||||
case ANYELEMENTOID:
|
case ANYELEMENTOID:
|
||||||
case ANYNONARRAYOID:
|
case ANYNONARRAYOID:
|
||||||
case ANYENUMOID:
|
case ANYENUMOID:
|
||||||
genericInParam = true;
|
genericInParam = true;
|
||||||
break;
|
break;
|
||||||
|
case ANYRANGEOID:
|
||||||
|
genericInParam = true;
|
||||||
|
anyrangeInParam = true;
|
||||||
|
break;
|
||||||
case INTERNALOID:
|
case INTERNALOID:
|
||||||
internalInParam = true;
|
internalInParam = true;
|
||||||
break;
|
break;
|
||||||
@ -201,23 +201,23 @@ ProcedureCreate(const char *procedureName,
|
|||||||
{
|
{
|
||||||
for (i = 0; i < allParamCount; i++)
|
for (i = 0; i < allParamCount; i++)
|
||||||
{
|
{
|
||||||
if (modes == NULL ||
|
if (paramModes == NULL ||
|
||||||
(modes[i] != PROARGMODE_OUT &&
|
paramModes[i] == PROARGMODE_IN ||
|
||||||
modes[i] != PROARGMODE_INOUT &&
|
paramModes[i] == PROARGMODE_VARIADIC)
|
||||||
modes[i] != PROARGMODE_TABLE))
|
continue; /* ignore input-only params */
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (allParams[i])
|
switch (allParams[i])
|
||||||
{
|
{
|
||||||
case ANYRANGEOID:
|
|
||||||
anyrangeOutParam = true;
|
|
||||||
/* FALL THROUGH */
|
|
||||||
case ANYARRAYOID:
|
case ANYARRAYOID:
|
||||||
case ANYELEMENTOID:
|
case ANYELEMENTOID:
|
||||||
case ANYNONARRAYOID:
|
case ANYNONARRAYOID:
|
||||||
case ANYENUMOID:
|
case ANYENUMOID:
|
||||||
genericOutParam = true;
|
genericOutParam = true;
|
||||||
break;
|
break;
|
||||||
|
case ANYRANGEOID:
|
||||||
|
genericOutParam = true;
|
||||||
|
anyrangeOutParam = true;
|
||||||
|
break;
|
||||||
case INTERNALOID:
|
case INTERNALOID:
|
||||||
internalOutParam = true;
|
internalOutParam = true;
|
||||||
break;
|
break;
|
||||||
@ -225,6 +225,13 @@ ProcedureCreate(const char *procedureName,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not allow polymorphic return type unless at least one input argument
|
||||||
|
* is polymorphic. ANYRANGE return type is even stricter: must have an
|
||||||
|
* ANYRANGE input (since we can't deduce the specific range type from
|
||||||
|
* ANYELEMENT). Also, do not allow return type INTERNAL unless at least
|
||||||
|
* one input argument is INTERNAL.
|
||||||
|
*/
|
||||||
if ((IsPolymorphicType(returnType) || genericOutParam)
|
if ((IsPolymorphicType(returnType) || genericOutParam)
|
||||||
&& !genericInParam)
|
&& !genericInParam)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -259,7 +266,7 @@ ProcedureCreate(const char *procedureName,
|
|||||||
procedureName,
|
procedureName,
|
||||||
format_type_be(parameterTypes->values[0]))));
|
format_type_be(parameterTypes->values[0]))));
|
||||||
|
|
||||||
if (modes != NULL)
|
if (paramModes != NULL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Only the last input parameter can be variadic; if it is, save its
|
* Only the last input parameter can be variadic; if it is, save its
|
||||||
@ -268,7 +275,7 @@ ProcedureCreate(const char *procedureName,
|
|||||||
*/
|
*/
|
||||||
for (i = 0; i < allParamCount; i++)
|
for (i = 0; i < allParamCount; i++)
|
||||||
{
|
{
|
||||||
switch (modes[i])
|
switch (paramModes[i])
|
||||||
{
|
{
|
||||||
case PROARGMODE_IN:
|
case PROARGMODE_IN:
|
||||||
case PROARGMODE_INOUT:
|
case PROARGMODE_INOUT:
|
||||||
@ -298,7 +305,7 @@ ProcedureCreate(const char *procedureName,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
elog(ERROR, "invalid parameter mode '%c'", modes[i]);
|
elog(ERROR, "invalid parameter mode '%c'", paramModes[i]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -654,9 +654,9 @@ RemoveTypeById(Oid typeOid)
|
|||||||
EnumValuesDelete(typeOid);
|
EnumValuesDelete(typeOid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If it is a range type, delete the pg_range entries too; we don't bother
|
* If it is a range type, delete the pg_range entry too; we don't bother
|
||||||
* with making dependency entries for those, so it has to be done "by
|
* with making a dependency entry for that, so it has to be done "by hand"
|
||||||
* hand" here.
|
* here.
|
||||||
*/
|
*/
|
||||||
if (((Form_pg_type) GETSTRUCT(tup))->typtype == TYPTYPE_RANGE)
|
if (((Form_pg_type) GETSTRUCT(tup))->typtype == TYPTYPE_RANGE)
|
||||||
RangeDelete(typeOid);
|
RangeDelete(typeOid);
|
||||||
@ -1475,8 +1475,9 @@ makeRangeConstructor(char *name, Oid namespace, Oid rangeOid, Oid subtype)
|
|||||||
0.0); /* prorows */
|
0.0); /* prorows */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make the constructor internally-dependent on the range type so that
|
* Make the constructors internally-dependent on the range type so
|
||||||
* the user doesn't have to treat them as separate objects.
|
* that they go away silently when the type is dropped. Note that
|
||||||
|
* pg_dump depends on this choice to avoid dumping the constructors.
|
||||||
*/
|
*/
|
||||||
myself.classId = ProcedureRelationId;
|
myself.classId = ProcedureRelationId;
|
||||||
myself.objectId = procOid;
|
myself.objectId = procOid;
|
||||||
|
@ -165,11 +165,12 @@ coerce_type(ParseState *pstate, Node *node,
|
|||||||
* Assume can_coerce_type verified that implicit coercion is okay.
|
* Assume can_coerce_type verified that implicit coercion is okay.
|
||||||
*
|
*
|
||||||
* These cases are unlike the ones above because the exposed type of
|
* These cases are unlike the ones above because the exposed type of
|
||||||
* the argument must be an actual array or enum type. In particular
|
* the argument must be an actual array, enum, or range type. In
|
||||||
* the argument must *not* be an UNKNOWN constant. If it is, we just
|
* particular the argument must *not* be an UNKNOWN constant. If it
|
||||||
* fall through; below, we'll call anyarray_in or anyenum_in, which
|
* is, we just fall through; below, we'll call anyarray_in,
|
||||||
* will produce an error. Also, if what we have is a domain over
|
* anyenum_in, or anyrange_in, which will produce an error. Also, if
|
||||||
* array or enum, we have to relabel it to its base type.
|
* what we have is a domain over array, enum, or range, we have to
|
||||||
|
* relabel it to its base type.
|
||||||
*
|
*
|
||||||
* Note: currently, we can't actually see a domain-over-enum here,
|
* Note: currently, we can't actually see a domain-over-enum here,
|
||||||
* since the other functions in this file will not match such a
|
* since the other functions in this file will not match such a
|
||||||
@ -1273,18 +1274,21 @@ coerce_to_common_type(ParseState *pstate, Node *node,
|
|||||||
*
|
*
|
||||||
* The argument consistency rules are:
|
* The argument consistency rules are:
|
||||||
*
|
*
|
||||||
* 1) All arguments declared ANYARRAY must have matching datatypes,
|
* 1) All arguments declared ANYELEMENT must have the same datatype.
|
||||||
* and must in fact be varlena arrays.
|
* 2) All arguments declared ANYARRAY must have the same datatype,
|
||||||
* 2) All arguments declared ANYELEMENT must have matching datatypes.
|
* which must be a varlena array type.
|
||||||
* 3) If there are arguments of both ANYELEMENT and ANYARRAY, make sure the
|
* 3) All arguments declared ANYRANGE must have the same datatype,
|
||||||
|
* which must be a range type.
|
||||||
|
* 4) If there are arguments of both ANYELEMENT and ANYARRAY, make sure the
|
||||||
* actual ANYELEMENT datatype is in fact the element type for the actual
|
* actual ANYELEMENT datatype is in fact the element type for the actual
|
||||||
* ANYARRAY datatype. Similarly, if there are arguments of both ANYELEMENT
|
* ANYARRAY datatype.
|
||||||
* and ANYRANGE, make sure the actual ANYELEMENT datatype is in fact the
|
* 5) Similarly, if there are arguments of both ANYELEMENT and ANYRANGE,
|
||||||
* subtype for the actual ANYRANGE type.
|
* make sure the actual ANYELEMENT datatype is in fact the subtype for
|
||||||
* 4) ANYENUM is treated the same as ANYELEMENT except that if it is used
|
* the actual ANYRANGE type.
|
||||||
|
* 6) ANYENUM is treated the same as ANYELEMENT except that if it is used
|
||||||
* (alone or in combination with plain ANYELEMENT), we add the extra
|
* (alone or in combination with plain ANYELEMENT), we add the extra
|
||||||
* condition that the ANYELEMENT type must be an enum.
|
* condition that the ANYELEMENT type must be an enum.
|
||||||
* 5) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
|
* 7) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
|
||||||
* we add the extra condition that the ANYELEMENT type must not be an array.
|
* we add the extra condition that the ANYELEMENT type must not be an array.
|
||||||
* (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
|
* (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
|
||||||
* is an extra restriction if not.)
|
* is an extra restriction if not.)
|
||||||
@ -1294,6 +1298,12 @@ coerce_to_common_type(ParseState *pstate, Node *node,
|
|||||||
* argument is a domain over int4[] while another one is just int4[].) Also
|
* argument is a domain over int4[] while another one is just int4[].) Also
|
||||||
* notice that such a domain does *not* match ANYNONARRAY.
|
* notice that such a domain does *not* match ANYNONARRAY.
|
||||||
*
|
*
|
||||||
|
* Similarly, domains over ranges match ANYRANGE, and are immediately
|
||||||
|
* flattened to their base type.
|
||||||
|
*
|
||||||
|
* Note that domains aren't currently considered to match ANYENUM,
|
||||||
|
* even if their base type would match.
|
||||||
|
*
|
||||||
* If we have UNKNOWN input (ie, an untyped literal) for any polymorphic
|
* If we have UNKNOWN input (ie, an untyped literal) for any polymorphic
|
||||||
* argument, assume it is okay.
|
* argument, assume it is okay.
|
||||||
*
|
*
|
||||||
@ -1357,7 +1367,7 @@ check_generic_type_consistency(Oid *actual_arg_types,
|
|||||||
{
|
{
|
||||||
if (actual_type == UNKNOWNOID)
|
if (actual_type == UNKNOWNOID)
|
||||||
continue;
|
continue;
|
||||||
actual_type = getBaseType(actual_type);
|
actual_type = getBaseType(actual_type); /* flatten domains */
|
||||||
if (OidIsValid(range_typeid) && actual_type != range_typeid)
|
if (OidIsValid(range_typeid) && actual_type != range_typeid)
|
||||||
return false;
|
return false;
|
||||||
range_typeid = actual_type;
|
range_typeid = actual_type;
|
||||||
@ -1393,20 +1403,6 @@ check_generic_type_consistency(Oid *actual_arg_types,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (have_anynonarray)
|
|
||||||
{
|
|
||||||
/* require the element type to not be an array or domain over array */
|
|
||||||
if (type_is_array_domain(elem_typeid))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (have_anyenum)
|
|
||||||
{
|
|
||||||
/* require the element type to be an enum */
|
|
||||||
if (!type_is_enum(elem_typeid))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the element type based on the range type, if we have one */
|
/* Get the element type based on the range type, if we have one */
|
||||||
if (OidIsValid(range_typeid))
|
if (OidIsValid(range_typeid))
|
||||||
{
|
{
|
||||||
@ -1428,6 +1424,20 @@ check_generic_type_consistency(Oid *actual_arg_types,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (have_anynonarray)
|
||||||
|
{
|
||||||
|
/* require the element type to not be an array or domain over array */
|
||||||
|
if (type_is_array_domain(elem_typeid))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_anyenum)
|
||||||
|
{
|
||||||
|
/* require the element type to be an enum */
|
||||||
|
if (!type_is_enum(elem_typeid))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Looks valid */
|
/* Looks valid */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1451,47 +1461,47 @@ check_generic_type_consistency(Oid *actual_arg_types,
|
|||||||
* if it is declared as a polymorphic type:
|
* if it is declared as a polymorphic type:
|
||||||
*
|
*
|
||||||
* 1) If return type is ANYARRAY, and any argument is ANYARRAY, use the
|
* 1) If return type is ANYARRAY, and any argument is ANYARRAY, use the
|
||||||
* argument's actual type as the function's return type. Similarly, if
|
* argument's actual type as the function's return type.
|
||||||
* return type is ANYRANGE, and any argument is ANYRANGE, use the argument's
|
* 2) Similarly, if return type is ANYRANGE, and any argument is ANYRANGE,
|
||||||
* actual type as the function's return type.
|
* use the argument's actual type as the function's return type.
|
||||||
* 2) If return type is ANYARRAY, no argument is ANYARRAY, but any argument is
|
* 3) If return type is ANYARRAY, no argument is ANYARRAY, but any argument is
|
||||||
* ANYELEMENT, use the actual type of the argument to determine the
|
* ANYELEMENT, use the actual type of the argument to determine the
|
||||||
* function's return type, i.e. the element type's corresponding array
|
* function's return type, i.e. the element type's corresponding array
|
||||||
* type. Note: similar behavior does not exist for ANYRANGE, because it's
|
* type. (Note: similar behavior does not exist for ANYRANGE, because it's
|
||||||
* impossble to determine the range type from the subtype alone.\
|
* impossible to determine the range type from the subtype alone.)
|
||||||
* 3) If return type is ANYARRAY, no argument is ANYARRAY or ANYELEMENT,
|
* 4) If return type is ANYARRAY, but no argument is ANYARRAY or ANYELEMENT,
|
||||||
* generate an ERROR. Similarly, if the return type is ANYRANGE, and no
|
* generate an error. Similarly, if return type is ANYRANGE, but no
|
||||||
* argument is ANYRANGE or ANYELEMENT, generate an error. These conditions
|
* argument is ANYRANGE, generate an error. (These conditions are
|
||||||
* are prevented by CREATE FUNCTION and is therefore not expected here.
|
* prevented by CREATE FUNCTION and therefore are not expected here.)
|
||||||
* 4) If return type is ANYELEMENT, and any argument is ANYELEMENT, use the
|
* 5) If return type is ANYELEMENT, and any argument is ANYELEMENT, use the
|
||||||
* argument's actual type as the function's return type.
|
* argument's actual type as the function's return type.
|
||||||
* 5) If return type is ANYELEMENT, no argument is ANYELEMENT, but any argument
|
* 6) If return type is ANYELEMENT, no argument is ANYELEMENT, but any argument
|
||||||
* is ANYARRAY or ANYRANGE, use the actual type of the argument to determine
|
* is ANYARRAY or ANYRANGE, use the actual type of the argument to determine
|
||||||
* the function's return type; i.e. the array type's corresponding element
|
* the function's return type, i.e. the array type's corresponding element
|
||||||
* type or the range type's corresponding subtype (or both, in which case
|
* type or the range type's corresponding subtype (or both, in which case
|
||||||
* they must match).
|
* they must match).
|
||||||
* 6) If return type is ANYELEMENT, no argument is ANYARRAY, ANYRANGE, or
|
* 7) If return type is ANYELEMENT, no argument is ANYELEMENT, ANYARRAY, or
|
||||||
* ANYELEMENT, generate an ERROR. This condition is prevented by CREATE
|
* ANYRANGE, generate an error. (This condition is prevented by CREATE
|
||||||
* FUNCTION and is therefore not expected here.
|
* FUNCTION and therefore is not expected here.)
|
||||||
* 7) ANYENUM is treated the same as ANYELEMENT except that if it is used
|
* 8) ANYENUM is treated the same as ANYELEMENT except that if it is used
|
||||||
* (alone or in combination with plain ANYELEMENT), we add the extra
|
* (alone or in combination with plain ANYELEMENT), we add the extra
|
||||||
* condition that the ANYELEMENT type must be an enum.
|
* condition that the ANYELEMENT type must be an enum.
|
||||||
* 8) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
|
* 9) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
|
||||||
* we add the extra condition that the ANYELEMENT type must not be an array.
|
* we add the extra condition that the ANYELEMENT type must not be an array.
|
||||||
* (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
|
* (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
|
||||||
* is an extra restriction if not.)
|
* is an extra restriction if not.)
|
||||||
*
|
*
|
||||||
* Domains over arrays or ranges match ANYARRAY or ANYRANGE arguments,
|
* Domains over arrays or ranges match ANYARRAY or ANYRANGE arguments,
|
||||||
* respectively, and are immediately flattened to their base type. (In
|
* respectively, and are immediately flattened to their base type. (In
|
||||||
* particular, if the return type is also ANYARRAY or ANYRANGE, we'll set it to
|
* particular, if the return type is also ANYARRAY or ANYRANGE, we'll set it
|
||||||
* the base type not the domain type.)
|
* to the base type not the domain type.)
|
||||||
*
|
*
|
||||||
* When allow_poly is false, we are not expecting any of the actual_arg_types
|
* When allow_poly is false, we are not expecting any of the actual_arg_types
|
||||||
* to be polymorphic, and we should not return a polymorphic result type
|
* to be polymorphic, and we should not return a polymorphic result type
|
||||||
* either. When allow_poly is true, it is okay to have polymorphic "actual"
|
* either. When allow_poly is true, it is okay to have polymorphic "actual"
|
||||||
* arg types, and we can return ANYARRAY or ANYELEMENT as the result. (This
|
* arg types, and we can return ANYARRAY, ANYRANGE, or ANYELEMENT as the
|
||||||
* case is currently used only to check compatibility of an aggregate's
|
* result. (This case is currently used only to check compatibility of an
|
||||||
* declaration with the underlying transfn.)
|
* aggregate's declaration with the underlying transfn.)
|
||||||
*
|
*
|
||||||
* A special case is that we could see ANYARRAY as an actual_arg_type even
|
* A special case is that we could see ANYARRAY as an actual_arg_type even
|
||||||
* when allow_poly is false (this is possible only because pg_statistic has
|
* when allow_poly is false (this is possible only because pg_statistic has
|
||||||
@ -1612,7 +1622,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
|||||||
if (array_typeid == ANYARRAYOID && !have_anyelement)
|
if (array_typeid == ANYARRAYOID && !have_anyelement)
|
||||||
{
|
{
|
||||||
/* Special case for ANYARRAY input: okay iff no ANYELEMENT */
|
/* Special case for ANYARRAY input: okay iff no ANYELEMENT */
|
||||||
array_typelem = InvalidOid;
|
array_typelem = ANYELEMENTOID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1642,8 +1652,16 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
|||||||
format_type_be(elem_typeid))));
|
format_type_be(elem_typeid))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the element type based on the range type, if we have one */
|
/* Get the element type based on the range type, if we have one */
|
||||||
else if (OidIsValid(range_typeid))
|
if (OidIsValid(range_typeid))
|
||||||
|
{
|
||||||
|
if (range_typeid == ANYRANGEOID && !have_anyelement)
|
||||||
|
{
|
||||||
|
/* Special case for ANYRANGE input: okay iff no ANYELEMENT */
|
||||||
|
range_typelem = ANYELEMENTOID;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
range_typelem = get_range_subtype(range_typeid);
|
range_typelem = get_range_subtype(range_typeid);
|
||||||
if (!OidIsValid(range_typelem))
|
if (!OidIsValid(range_typelem))
|
||||||
@ -1651,6 +1669,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
|||||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||||
errmsg("argument declared \"anyrange\" is not a range but type %s",
|
errmsg("argument declared \"anyrange\" is not a range but type %s",
|
||||||
format_type_be(range_typeid))));
|
format_type_be(range_typeid))));
|
||||||
|
}
|
||||||
|
|
||||||
if (!OidIsValid(elem_typeid))
|
if (!OidIsValid(elem_typeid))
|
||||||
{
|
{
|
||||||
@ -1670,12 +1689,14 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
|||||||
format_type_be(elem_typeid))));
|
format_type_be(elem_typeid))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!OidIsValid(elem_typeid))
|
|
||||||
|
if (!OidIsValid(elem_typeid))
|
||||||
{
|
{
|
||||||
if (allow_poly)
|
if (allow_poly)
|
||||||
{
|
{
|
||||||
array_typeid = ANYARRAYOID;
|
|
||||||
elem_typeid = ANYELEMENTOID;
|
elem_typeid = ANYELEMENTOID;
|
||||||
|
array_typeid = ANYARRAYOID;
|
||||||
|
range_typeid = ANYRANGEOID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1861,13 +1882,14 @@ resolve_generic_type(Oid declared_type,
|
|||||||
else if (context_declared_type == ANYRANGEOID)
|
else if (context_declared_type == ANYRANGEOID)
|
||||||
{
|
{
|
||||||
/* Use the element type corresponding to actual type */
|
/* Use the element type corresponding to actual type */
|
||||||
Oid range_typelem = get_range_subtype(context_actual_type);
|
Oid context_base_type = getBaseType(context_actual_type);
|
||||||
|
Oid range_typelem = get_range_subtype(context_base_type);
|
||||||
|
|
||||||
if (!OidIsValid(range_typelem))
|
if (!OidIsValid(range_typelem))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||||
errmsg("argument declared \"anyrange\" is not a range but type %s",
|
errmsg("argument declared \"anyrange\" is not a range but type %s",
|
||||||
format_type_be(context_actual_type))));
|
format_type_be(context_base_type))));
|
||||||
return range_typelem;
|
return range_typelem;
|
||||||
}
|
}
|
||||||
else if (context_declared_type == ANYELEMENTOID ||
|
else if (context_declared_type == ANYELEMENTOID ||
|
||||||
@ -1970,12 +1992,12 @@ IsBinaryCoercible(Oid srctype, Oid targettype)
|
|||||||
|
|
||||||
/* Also accept any array type as coercible to ANYARRAY */
|
/* Also accept any array type as coercible to ANYARRAY */
|
||||||
if (targettype == ANYARRAYOID)
|
if (targettype == ANYARRAYOID)
|
||||||
if (type_is_array_domain(srctype))
|
if (type_is_array(srctype))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* Also accept any non-array type as coercible to ANYNONARRAY */
|
/* Also accept any non-array type as coercible to ANYNONARRAY */
|
||||||
if (targettype == ANYNONARRAYOID)
|
if (targettype == ANYNONARRAYOID)
|
||||||
if (!type_is_array_domain(srctype))
|
if (!type_is_array(srctype))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* Also accept any enum type as coercible to ANYENUM */
|
/* Also accept any enum type as coercible to ANYENUM */
|
||||||
|
@ -851,11 +851,11 @@ standard_ProcessUtility(Node *parsetree,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_CreateEnumStmt: /* CREATE TYPE (enum) */
|
case T_CreateEnumStmt: /* CREATE TYPE AS ENUM */
|
||||||
DefineEnum((CreateEnumStmt *) parsetree);
|
DefineEnum((CreateEnumStmt *) parsetree);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_CreateRangeStmt:
|
case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
|
||||||
DefineRange((CreateRangeStmt *) parsetree);
|
DefineRange((CreateRangeStmt *) parsetree);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
10
src/backend/utils/cache/lsyscache.c
vendored
10
src/backend/utils/cache/lsyscache.c
vendored
@ -2253,7 +2253,7 @@ type_is_enum(Oid typid)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* type_is_range
|
* type_is_range
|
||||||
* Returns true if the given type is an range type.
|
* Returns true if the given type is a range type.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
type_is_range(Oid typid)
|
type_is_range(Oid typid)
|
||||||
@ -2867,6 +2867,14 @@ get_namespace_name(Oid nspid)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------- PG_RANGE CACHE ---------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_range_subtype
|
||||||
|
* Returns the subtype of a given range type
|
||||||
|
*
|
||||||
|
* Returns InvalidOid if the type is not a range type.
|
||||||
|
*/
|
||||||
Oid
|
Oid
|
||||||
get_range_subtype(Oid rangeOid)
|
get_range_subtype(Oid rangeOid)
|
||||||
{
|
{
|
||||||
|
2
src/backend/utils/cache/syscache.c
vendored
2
src/backend/utils/cache/syscache.c
vendored
@ -564,7 +564,7 @@ static const struct cachedesc cacheinfo[] = {
|
|||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
1024
|
64
|
||||||
},
|
},
|
||||||
{RelationRelationId, /* RELNAMENSP */
|
{RelationRelationId, /* RELNAMENSP */
|
||||||
ClassNameNspIndexId,
|
ClassNameNspIndexId,
|
||||||
|
@ -481,14 +481,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
|
|||||||
!OidIsValid(anyrange_type))
|
!OidIsValid(anyrange_type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/*
|
/* If needed, deduce one polymorphic type from others */
|
||||||
* We can't deduce a range type from the subtype, because there may be
|
|
||||||
* multiple range types for a single subtype.
|
|
||||||
*/
|
|
||||||
if (have_anyrange_result && !OidIsValid(anyrange_type))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* If needed, deduce one polymorphic type from the other */
|
|
||||||
if (have_anyelement_result && !OidIsValid(anyelement_type))
|
if (have_anyelement_result && !OidIsValid(anyelement_type))
|
||||||
{
|
{
|
||||||
if (OidIsValid(anyarray_type))
|
if (OidIsValid(anyarray_type))
|
||||||
@ -500,10 +493,10 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
|
|||||||
Oid subtype = resolve_generic_type(ANYELEMENTOID,
|
Oid subtype = resolve_generic_type(ANYELEMENTOID,
|
||||||
anyrange_type,
|
anyrange_type,
|
||||||
ANYRANGEOID);
|
ANYRANGEOID);
|
||||||
if (OidIsValid(anyelement_type) &&
|
|
||||||
anyelement_type != subtype)
|
/* check for inconsistent array and range results */
|
||||||
|
if (OidIsValid(anyelement_type) && anyelement_type != subtype)
|
||||||
return false;
|
return false;
|
||||||
else
|
|
||||||
anyelement_type = subtype;
|
anyelement_type = subtype;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -513,6 +506,13 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
|
|||||||
anyelement_type,
|
anyelement_type,
|
||||||
ANYELEMENTOID);
|
ANYELEMENTOID);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can't deduce a range type from other polymorphic inputs, because
|
||||||
|
* there may be multiple range types for the same subtype.
|
||||||
|
*/
|
||||||
|
if (have_anyrange_result && !OidIsValid(anyrange_type))
|
||||||
|
return false;
|
||||||
|
|
||||||
/* Enforce ANYNONARRAY if needed */
|
/* Enforce ANYNONARRAY if needed */
|
||||||
if (have_anynonarray && type_is_array(anyelement_type))
|
if (have_anynonarray && type_is_array(anyelement_type))
|
||||||
return false;
|
return false;
|
||||||
@ -523,9 +523,10 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Identify the collation to use for polymorphic OUT parameters. (It'll
|
* Identify the collation to use for polymorphic OUT parameters. (It'll
|
||||||
* necessarily be the same for both anyelement and anyarray.)
|
* necessarily be the same for both anyelement and anyarray.) Note that
|
||||||
|
* range types are not collatable, so any possible internal collation of
|
||||||
|
* a range type is not considered here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (OidIsValid(anyelement_type))
|
if (OidIsValid(anyelement_type))
|
||||||
anycollation = get_typcollation(anyelement_type);
|
anycollation = get_typcollation(anyelement_type);
|
||||||
else if (OidIsValid(anyarray_type))
|
else if (OidIsValid(anyarray_type))
|
||||||
@ -573,7 +574,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
|
|||||||
anyrange_type,
|
anyrange_type,
|
||||||
-1,
|
-1,
|
||||||
0);
|
0);
|
||||||
TupleDescInitEntryCollation(tupdesc, i + 1, anycollation);
|
/* no collation should be attached to a range type */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -672,19 +673,12 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
|
|||||||
!have_anyrange_result)
|
!have_anyrange_result)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/*
|
|
||||||
* We can't deduce a range type from the subtype, because there may be
|
|
||||||
* multiple range types for a single subtype.
|
|
||||||
*/
|
|
||||||
if (have_anyrange_result && !OidIsValid(anyrange_type))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* If no input polymorphics, parser messed up */
|
/* If no input polymorphics, parser messed up */
|
||||||
if (!OidIsValid(anyelement_type) && !OidIsValid(anyarray_type) &&
|
if (!OidIsValid(anyelement_type) && !OidIsValid(anyarray_type) &&
|
||||||
!OidIsValid(anyrange_type))
|
!OidIsValid(anyrange_type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* If needed, deduce one polymorphic type from the other */
|
/* If needed, deduce one polymorphic type from others */
|
||||||
if (have_anyelement_result && !OidIsValid(anyelement_type))
|
if (have_anyelement_result && !OidIsValid(anyelement_type))
|
||||||
{
|
{
|
||||||
if (OidIsValid(anyarray_type))
|
if (OidIsValid(anyarray_type))
|
||||||
@ -696,10 +690,10 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
|
|||||||
Oid subtype = resolve_generic_type(ANYELEMENTOID,
|
Oid subtype = resolve_generic_type(ANYELEMENTOID,
|
||||||
anyrange_type,
|
anyrange_type,
|
||||||
ANYRANGEOID);
|
ANYRANGEOID);
|
||||||
if (OidIsValid(anyelement_type) &&
|
|
||||||
anyelement_type != subtype)
|
/* check for inconsistent array and range results */
|
||||||
|
if (OidIsValid(anyelement_type) && anyelement_type != subtype)
|
||||||
return false;
|
return false;
|
||||||
else
|
|
||||||
anyelement_type = subtype;
|
anyelement_type = subtype;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -709,6 +703,13 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
|
|||||||
anyelement_type,
|
anyelement_type,
|
||||||
ANYELEMENTOID);
|
ANYELEMENTOID);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can't deduce a range type from other polymorphic inputs, because
|
||||||
|
* there may be multiple range types for the same subtype.
|
||||||
|
*/
|
||||||
|
if (have_anyrange_result && !OidIsValid(anyrange_type))
|
||||||
|
return false;
|
||||||
|
|
||||||
/* XXX do we need to enforce ANYNONARRAY or ANYENUM here? I think not */
|
/* XXX do we need to enforce ANYNONARRAY or ANYENUM here? I think not */
|
||||||
|
|
||||||
/* And finally replace the output column types as needed */
|
/* And finally replace the output column types as needed */
|
||||||
|
@ -52,7 +52,6 @@
|
|||||||
#include "catalog/pg_largeobject.h"
|
#include "catalog/pg_largeobject.h"
|
||||||
#include "catalog/pg_largeobject_metadata.h"
|
#include "catalog/pg_largeobject_metadata.h"
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
#include "catalog/pg_range.h"
|
|
||||||
#include "catalog/pg_trigger.h"
|
#include "catalog/pg_trigger.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "libpq/libpq-fs.h"
|
#include "libpq/libpq-fs.h"
|
||||||
@ -3703,34 +3702,16 @@ getFuncs(int *numFuncs)
|
|||||||
* pg_catalog. In normal dumps we can still ignore those --- but in
|
* pg_catalog. In normal dumps we can still ignore those --- but in
|
||||||
* binary-upgrade mode, we must dump the member objects of the extension,
|
* binary-upgrade mode, we must dump the member objects of the extension,
|
||||||
* so be sure to fetch any such functions.
|
* so be sure to fetch any such functions.
|
||||||
|
*
|
||||||
|
* Also, in 9.2 and up, exclude functions that are internally dependent on
|
||||||
|
* something else, since presumably those will be created as a result of
|
||||||
|
* creating the something else. This currently only acts to suppress
|
||||||
|
* constructor functions for range types. Note that this is OK only
|
||||||
|
* because the constructors don't have any dependencies the range type
|
||||||
|
* doesn't have; otherwise we might not get creation ordering correct.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (g_fout->remoteVersion >= 90200)
|
if (g_fout->remoteVersion >= 70300)
|
||||||
{
|
|
||||||
appendPQExpBuffer(query,
|
|
||||||
"SELECT tableoid, oid, proname, prolang, "
|
|
||||||
"pronargs, proargtypes, prorettype, proacl, "
|
|
||||||
"pronamespace, "
|
|
||||||
"(%s proowner) AS rolname "
|
|
||||||
"FROM pg_proc p "
|
|
||||||
"WHERE NOT proisagg AND "
|
|
||||||
" NOT EXISTS (SELECT 1 FROM pg_depend "
|
|
||||||
" WHERE classid = 'pg_proc'::regclass AND "
|
|
||||||
" objid = p.oid AND deptype = 'i') AND "
|
|
||||||
"(pronamespace != "
|
|
||||||
"(SELECT oid FROM pg_namespace "
|
|
||||||
"WHERE nspname = 'pg_catalog')",
|
|
||||||
username_subquery);
|
|
||||||
if (binary_upgrade && g_fout->remoteVersion >= 90100)
|
|
||||||
appendPQExpBuffer(query,
|
|
||||||
" OR EXISTS(SELECT 1 FROM pg_depend WHERE "
|
|
||||||
"classid = 'pg_proc'::regclass AND "
|
|
||||||
"objid = p.oid AND "
|
|
||||||
"refclassid = 'pg_extension'::regclass AND "
|
|
||||||
"deptype = 'e')");
|
|
||||||
appendPQExpBuffer(query, ")");
|
|
||||||
}
|
|
||||||
else if (g_fout->remoteVersion >= 70300)
|
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(query,
|
appendPQExpBuffer(query,
|
||||||
"SELECT tableoid, oid, proname, prolang, "
|
"SELECT tableoid, oid, proname, prolang, "
|
||||||
@ -3743,9 +3724,14 @@ getFuncs(int *numFuncs)
|
|||||||
"(SELECT oid FROM pg_namespace "
|
"(SELECT oid FROM pg_namespace "
|
||||||
"WHERE nspname = 'pg_catalog')",
|
"WHERE nspname = 'pg_catalog')",
|
||||||
username_subquery);
|
username_subquery);
|
||||||
|
if (g_fout->remoteVersion >= 90200)
|
||||||
|
appendPQExpBuffer(query,
|
||||||
|
"\n AND NOT EXISTS (SELECT 1 FROM pg_depend "
|
||||||
|
"WHERE classid = 'pg_proc'::regclass AND "
|
||||||
|
"objid = p.oid AND deptype = 'i')");
|
||||||
if (binary_upgrade && g_fout->remoteVersion >= 90100)
|
if (binary_upgrade && g_fout->remoteVersion >= 90100)
|
||||||
appendPQExpBuffer(query,
|
appendPQExpBuffer(query,
|
||||||
" OR EXISTS(SELECT 1 FROM pg_depend WHERE "
|
"\n OR EXISTS(SELECT 1 FROM pg_depend WHERE "
|
||||||
"classid = 'pg_proc'::regclass AND "
|
"classid = 'pg_proc'::regclass AND "
|
||||||
"objid = p.oid AND "
|
"objid = p.oid AND "
|
||||||
"refclassid = 'pg_extension'::regclass AND "
|
"refclassid = 'pg_extension'::regclass AND "
|
||||||
@ -7479,31 +7465,25 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
|
|||||||
PQExpBuffer labelq = createPQExpBuffer();
|
PQExpBuffer labelq = createPQExpBuffer();
|
||||||
PQExpBuffer query = createPQExpBuffer();
|
PQExpBuffer query = createPQExpBuffer();
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
|
|
||||||
Oid collationOid;
|
Oid collationOid;
|
||||||
Oid opclassOid;
|
char *procname;
|
||||||
Oid analyzeOid;
|
|
||||||
Oid canonicalOid;
|
|
||||||
Oid subdiffOid;
|
|
||||||
|
|
||||||
/* Set proper schema search path */
|
/*
|
||||||
selectSourceSchema("pg_catalog");
|
* select appropriate schema to ensure names in CREATE are properly
|
||||||
|
* qualified
|
||||||
|
*/
|
||||||
|
selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
|
||||||
|
|
||||||
appendPQExpBuffer(query,
|
appendPQExpBuffer(query,
|
||||||
"SELECT rngtypid, "
|
"SELECT pg_catalog.format_type(rngsubtype, NULL) AS rngsubtype, "
|
||||||
"format_type(rngsubtype, NULL) as rngsubtype, "
|
|
||||||
"rngsubtype::oid as rngsubtypeoid, "
|
|
||||||
"opc.opcname AS opcname, "
|
"opc.opcname AS opcname, "
|
||||||
|
"(SELECT nspname FROM pg_catalog.pg_namespace nsp "
|
||||||
|
" WHERE nsp.oid = opc.opcnamespace) AS opcnsp, "
|
||||||
|
"opc.opcdefault, "
|
||||||
"CASE WHEN rngcollation = st.typcollation THEN 0 "
|
"CASE WHEN rngcollation = st.typcollation THEN 0 "
|
||||||
" ELSE rngcollation END AS collation, "
|
" ELSE rngcollation END AS collation, "
|
||||||
"CASE WHEN opcdefault THEN 0 ELSE rngsubopc END "
|
"rngcanonical, rngsubdiff, t.typanalyze "
|
||||||
" AS rngsubopc, "
|
"FROM pg_catalog.pg_type t, pg_catalog.pg_type st, "
|
||||||
"(SELECT nspname FROM pg_namespace nsp "
|
|
||||||
" WHERE nsp.oid = opc.opcnamespace) AS opcnsp, "
|
|
||||||
"t.typanalyze, t.typanalyze::oid as typanalyzeoid, "
|
|
||||||
"rngcanonical, rngcanonical::oid as rngcanonicaloid, "
|
|
||||||
"rngsubdiff, rngsubdiff::oid as rngsubdiffoid "
|
|
||||||
"FROM pg_catalog.pg_type t, pg_type st, "
|
|
||||||
" pg_catalog.pg_opclass opc, pg_catalog.pg_range r "
|
" pg_catalog.pg_opclass opc, pg_catalog.pg_range r "
|
||||||
"WHERE t.oid = rngtypid AND st.oid = rngsubtype AND "
|
"WHERE t.oid = rngtypid AND st.oid = rngsubtype AND "
|
||||||
" opc.oid = rngsubopc AND rngtypid = '%u'",
|
" opc.oid = rngsubopc AND rngtypid = '%u'",
|
||||||
@ -7511,6 +7491,12 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
|
|||||||
|
|
||||||
res = PQexec(g_conn, query->data);
|
res = PQexec(g_conn, query->data);
|
||||||
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
|
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
|
||||||
|
if (PQntuples(res) != 1)
|
||||||
|
{
|
||||||
|
write_msg(NULL, "query returned %d pg_range entries for range type \"%s\"\n",
|
||||||
|
PQntuples(res), tyinfo->dobj.name);
|
||||||
|
exit_nicely();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DROP must be fully qualified in case same name appears in pg_catalog.
|
* DROP must be fully qualified in case same name appears in pg_catalog.
|
||||||
@ -7522,68 +7508,53 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
|
|||||||
appendPQExpBuffer(delq, "%s;\n",
|
appendPQExpBuffer(delq, "%s;\n",
|
||||||
fmtId(tyinfo->dobj.name));
|
fmtId(tyinfo->dobj.name));
|
||||||
|
|
||||||
/* We might already have a shell type, but setting pg_type_oid is harmless */
|
|
||||||
if (binary_upgrade)
|
if (binary_upgrade)
|
||||||
binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
|
binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
|
||||||
|
|
||||||
appendPQExpBuffer(q, "CREATE TYPE %s AS RANGE (",
|
appendPQExpBuffer(q, "CREATE TYPE %s AS RANGE (",
|
||||||
fmtId(tyinfo->dobj.name));
|
fmtId(tyinfo->dobj.name));
|
||||||
|
|
||||||
/* SUBTYPE */
|
appendPQExpBuffer(q, "\n subtype = %s",
|
||||||
appendPQExpBuffer(q, "\n SUBTYPE = %s",
|
|
||||||
PQgetvalue(res, 0, PQfnumber(res, "rngsubtype")));
|
PQgetvalue(res, 0, PQfnumber(res, "rngsubtype")));
|
||||||
|
|
||||||
/* COLLATION */
|
/* print subtype_opclass only if not default for subtype */
|
||||||
collationOid = atooid(PQgetvalue(res, 0,
|
if (PQgetvalue(res, 0, PQfnumber(res, "opcdefault"))[0] != 't')
|
||||||
PQfnumber(res, "collation")));
|
{
|
||||||
|
char *opcname = PQgetvalue(res, 0, PQfnumber(res, "opcname"));
|
||||||
|
char *nspname = PQgetvalue(res, 0, PQfnumber(res, "opcnsp"));
|
||||||
|
|
||||||
|
/* always schema-qualify, don't try to be smart */
|
||||||
|
appendPQExpBuffer(q, ",\n subtype_opclass = %s.",
|
||||||
|
fmtId(nspname));
|
||||||
|
appendPQExpBuffer(q, "%s", fmtId(opcname));
|
||||||
|
}
|
||||||
|
|
||||||
|
collationOid = atooid(PQgetvalue(res, 0, PQfnumber(res, "collation")));
|
||||||
if (OidIsValid(collationOid))
|
if (OidIsValid(collationOid))
|
||||||
{
|
{
|
||||||
CollInfo *coll;
|
CollInfo *coll = findCollationByOid(collationOid);
|
||||||
|
|
||||||
coll = findCollationByOid(collationOid);
|
|
||||||
if (coll)
|
if (coll)
|
||||||
{
|
{
|
||||||
/* always schema-qualify, don't try to be smart */
|
/* always schema-qualify, don't try to be smart */
|
||||||
appendPQExpBuffer(q, ",\n COLLATION = %s.",
|
appendPQExpBuffer(q, ",\n collation = %s.",
|
||||||
fmtId(coll->dobj.namespace->dobj.name));
|
fmtId(coll->dobj.namespace->dobj.name));
|
||||||
appendPQExpBuffer(q, "%s",
|
appendPQExpBuffer(q, "%s",
|
||||||
fmtId(coll->dobj.name));
|
fmtId(coll->dobj.name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SUBTYPE_OPCLASS */
|
procname = PQgetvalue(res, 0, PQfnumber(res, "rngcanonical"));
|
||||||
opclassOid = atooid(PQgetvalue(res, 0,
|
if (strcmp(procname, "-") != 0)
|
||||||
PQfnumber(res, "rngsubopc")));
|
appendPQExpBuffer(q, ",\n canonical = %s", procname);
|
||||||
if (OidIsValid(opclassOid))
|
|
||||||
{
|
|
||||||
char *opcname = PQgetvalue(res, 0, PQfnumber(res, "opcname"));
|
|
||||||
char *nspname = PQgetvalue(res, 0, PQfnumber(res, "opcnsp"));
|
|
||||||
|
|
||||||
/* always schema-qualify, don't try to be smart */
|
procname = PQgetvalue(res, 0, PQfnumber(res, "rngsubdiff"));
|
||||||
appendPQExpBuffer(q, ",\n SUBTYPE_OPCLASS = %s.",
|
if (strcmp(procname, "-") != 0)
|
||||||
fmtId(nspname));
|
appendPQExpBuffer(q, ",\n subtype_diff = %s", procname);
|
||||||
appendPQExpBuffer(q, "%s", fmtId(opcname));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ANALYZE */
|
procname = PQgetvalue(res, 0, PQfnumber(res, "typanalyze"));
|
||||||
analyzeOid = atooid(PQgetvalue(res, 0,
|
if (strcmp(procname, "-") != 0)
|
||||||
PQfnumber(res, "typanalyzeoid")));
|
appendPQExpBuffer(q, ",\n analyze = %s", procname);
|
||||||
if (OidIsValid(analyzeOid))
|
|
||||||
appendPQExpBuffer(q, ",\n ANALYZE = %s",
|
|
||||||
PQgetvalue(res, 0, PQfnumber(res, "typanalyze")));
|
|
||||||
|
|
||||||
/* CANONICAL */
|
|
||||||
canonicalOid = atooid(PQgetvalue(res, 0,
|
|
||||||
PQfnumber(res, "rngcanonicaloid")));
|
|
||||||
if (OidIsValid(canonicalOid))
|
|
||||||
appendPQExpBuffer(q, ",\n CANONICAL = %s",
|
|
||||||
PQgetvalue(res, 0, PQfnumber(res, "rngcanonical")));
|
|
||||||
|
|
||||||
/* SUBTYPE_DIFF */
|
|
||||||
subdiffOid = atooid(PQgetvalue(res, 0, PQfnumber(res, "rngsubdiffoid")));
|
|
||||||
if (OidIsValid(subdiffOid))
|
|
||||||
appendPQExpBuffer(q, ",\n SUBTYPE_DIFF = %s",
|
|
||||||
PQgetvalue(res, 0, PQfnumber(res, "rngsubdiff")));
|
|
||||||
|
|
||||||
appendPQExpBuffer(q, "\n);\n");
|
appendPQExpBuffer(q, "\n);\n");
|
||||||
|
|
||||||
|
@ -2240,6 +2240,17 @@ typedef struct CreateEnumStmt
|
|||||||
List *vals; /* enum values (list of Value strings) */
|
List *vals; /* enum values (list of Value strings) */
|
||||||
} CreateEnumStmt;
|
} CreateEnumStmt;
|
||||||
|
|
||||||
|
/* ----------------------
|
||||||
|
* Create Type Statement, range types
|
||||||
|
* ----------------------
|
||||||
|
*/
|
||||||
|
typedef struct CreateRangeStmt
|
||||||
|
{
|
||||||
|
NodeTag type;
|
||||||
|
List *typeName; /* qualified name (list of Value strings) */
|
||||||
|
List *params; /* range parameters (list of DefElem) */
|
||||||
|
} CreateRangeStmt;
|
||||||
|
|
||||||
/* ----------------------
|
/* ----------------------
|
||||||
* Alter Type Statement, enum types
|
* Alter Type Statement, enum types
|
||||||
* ----------------------
|
* ----------------------
|
||||||
@ -2253,17 +2264,6 @@ typedef struct AlterEnumStmt
|
|||||||
bool newValIsAfter; /* place new enum value after neighbor? */
|
bool newValIsAfter; /* place new enum value after neighbor? */
|
||||||
} AlterEnumStmt;
|
} AlterEnumStmt;
|
||||||
|
|
||||||
/* ----------------------
|
|
||||||
* Create Type Statement, range types
|
|
||||||
* ----------------------
|
|
||||||
*/
|
|
||||||
typedef struct CreateRangeStmt
|
|
||||||
{
|
|
||||||
NodeTag type;
|
|
||||||
List *typeName; /* qualified name (list of Value strings) */
|
|
||||||
List *params; /* range parameters (list of DefElem) */
|
|
||||||
} CreateRangeStmt;
|
|
||||||
|
|
||||||
/* ----------------------
|
/* ----------------------
|
||||||
* Create View Statement
|
* Create View Statement
|
||||||
* ----------------------
|
* ----------------------
|
||||||
|
@ -502,6 +502,8 @@ extern Datum anynonarray_in(PG_FUNCTION_ARGS);
|
|||||||
extern Datum anynonarray_out(PG_FUNCTION_ARGS);
|
extern Datum anynonarray_out(PG_FUNCTION_ARGS);
|
||||||
extern Datum anyenum_in(PG_FUNCTION_ARGS);
|
extern Datum anyenum_in(PG_FUNCTION_ARGS);
|
||||||
extern Datum anyenum_out(PG_FUNCTION_ARGS);
|
extern Datum anyenum_out(PG_FUNCTION_ARGS);
|
||||||
|
extern Datum anyrange_in(PG_FUNCTION_ARGS);
|
||||||
|
extern Datum anyrange_out(PG_FUNCTION_ARGS);
|
||||||
extern Datum void_in(PG_FUNCTION_ARGS);
|
extern Datum void_in(PG_FUNCTION_ARGS);
|
||||||
extern Datum void_out(PG_FUNCTION_ARGS);
|
extern Datum void_out(PG_FUNCTION_ARGS);
|
||||||
extern Datum void_recv(PG_FUNCTION_ARGS);
|
extern Datum void_recv(PG_FUNCTION_ARGS);
|
||||||
|
@ -73,9 +73,7 @@ typedef struct
|
|||||||
* prototypes for functions defined in rangetypes.c
|
* prototypes for functions defined in rangetypes.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* IO */
|
/* I/O */
|
||||||
extern Datum anyrange_in(PG_FUNCTION_ARGS);
|
|
||||||
extern Datum anyrange_out(PG_FUNCTION_ARGS);
|
|
||||||
extern Datum range_in(PG_FUNCTION_ARGS);
|
extern Datum range_in(PG_FUNCTION_ARGS);
|
||||||
extern Datum range_out(PG_FUNCTION_ARGS);
|
extern Datum range_out(PG_FUNCTION_ARGS);
|
||||||
extern Datum range_recv(PG_FUNCTION_ARGS);
|
extern Datum range_recv(PG_FUNCTION_ARGS);
|
||||||
|
@ -2378,7 +2378,7 @@ compute_function_hashkey(FunctionCallInfo fcinfo,
|
|||||||
/*
|
/*
|
||||||
* This is the same as the standard resolve_polymorphic_argtypes() function,
|
* This is the same as the standard resolve_polymorphic_argtypes() function,
|
||||||
* but with a special case for validation: assume that polymorphic arguments
|
* but with a special case for validation: assume that polymorphic arguments
|
||||||
* are integer, integer-range or integer-array. Also, we go ahead and report
|
* are integer, integer-array or integer-range. Also, we go ahead and report
|
||||||
* the error if we can't resolve the types.
|
* the error if we can't resolve the types.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
@ -2412,12 +2412,12 @@ plpgsql_resolve_polymorphic_argtypes(int numargs,
|
|||||||
case ANYENUMOID: /* XXX dubious */
|
case ANYENUMOID: /* XXX dubious */
|
||||||
argtypes[i] = INT4OID;
|
argtypes[i] = INT4OID;
|
||||||
break;
|
break;
|
||||||
case ANYRANGEOID:
|
|
||||||
argtypes[i] = INT4RANGEOID;
|
|
||||||
break;
|
|
||||||
case ANYARRAYOID:
|
case ANYARRAYOID:
|
||||||
argtypes[i] = INT4ARRAYOID;
|
argtypes[i] = INT4ARRAYOID;
|
||||||
break;
|
break;
|
||||||
|
case ANYRANGEOID:
|
||||||
|
argtypes[i] = INT4RANGEOID;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user