</para></entry>
</row>
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>rngconstruct2</structfield> <type>regproc</type>
+ (references <link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.<structfield>oid</structfield>)
+ </para>
+ <para>
+ OID of the 2-argument range constructor function (lower and upper)
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>rngconstruct3</structfield> <type>regproc</type>
+ (references <link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.<structfield>oid</structfield>)
+ </para>
+ <para>
+ OID of the 3-argument range constructor function (lower, upper, and
+ flags)
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>rngmltconstruct0</structfield> <type>regproc</type>
+ (references <link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.<structfield>oid</structfield>)
+ </para>
+ <para>
+ OID of the 0-argument multirange constructor function (constructs empty
+ range)
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>rngmltconstruct1</structfield> <type>regproc</type>
+ (references <link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.<structfield>oid</structfield>)
+ </para>
+ <para>
+ OID of the 1-argument multirange constructor function (constructs
+ multirange from single range, also used as cast function)
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>rngmltconstruct2</structfield> <type>regproc</type>
+ (references <link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.<structfield>oid</structfield>)
+ </para>
+ <para>
+ OID of the 2-argument multirange constructor function (constructs
+ multirange from array of ranges)
+ </para></entry>
+ </row>
+
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>rngcanonical</structfield> <type>regproc</type>
void
RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation,
Oid rangeSubOpclass, RegProcedure rangeCanonical,
- RegProcedure rangeSubDiff, Oid multirangeTypeOid)
+ RegProcedure rangeSubDiff, Oid multirangeTypeOid,
+ RegProcedure rangeConstruct2, RegProcedure rangeConstruct3,
+ RegProcedure mltrngConstruct0, RegProcedure mltrngConstruct1, RegProcedure mltrngConstruct2)
{
Relation pg_range;
Datum values[Natts_pg_range];
values[Anum_pg_range_rngcanonical - 1] = ObjectIdGetDatum(rangeCanonical);
values[Anum_pg_range_rngsubdiff - 1] = ObjectIdGetDatum(rangeSubDiff);
values[Anum_pg_range_rngmultitypid - 1] = ObjectIdGetDatum(multirangeTypeOid);
+ values[Anum_pg_range_rngconstruct2 - 1] = ObjectIdGetDatum(rangeConstruct2);
+ values[Anum_pg_range_rngconstruct3 - 1] = ObjectIdGetDatum(rangeConstruct3);
+ values[Anum_pg_range_rngmltconstruct0 - 1] = ObjectIdGetDatum(mltrngConstruct0);
+ values[Anum_pg_range_rngmltconstruct1 - 1] = ObjectIdGetDatum(mltrngConstruct1);
+ values[Anum_pg_range_rngmltconstruct2 - 1] = ObjectIdGetDatum(mltrngConstruct2);
tup = heap_form_tuple(RelationGetDescr(pg_range), values, nulls);
Oid binary_upgrade_next_mrng_array_pg_type_oid = InvalidOid;
static void makeRangeConstructors(const char *name, Oid namespace,
- Oid rangeOid, Oid subtype);
+ Oid rangeOid, Oid subtype,
+ Oid *rangeConstruct2_p, Oid *rangeConstruct3_p);
static void makeMultirangeConstructors(const char *name, Oid namespace,
Oid multirangeOid, Oid rangeOid,
- Oid rangeArrayOid, Oid *castFuncOid);
+ Oid rangeArrayOid,
+ Oid *mltrngConstruct0_p, Oid *mltrngConstruct1_p, Oid *mltrngConstruct2_p);
static Oid findTypeInputFunction(List *procname, Oid typeOid);
static Oid findTypeOutputFunction(List *procname, Oid typeOid);
static Oid findTypeReceiveFunction(List *procname, Oid typeOid);
ListCell *lc;
ObjectAddress address;
ObjectAddress mltrngaddress PG_USED_FOR_ASSERTS_ONLY;
+ Oid rangeConstruct2Oid = InvalidOid;
+ Oid rangeConstruct3Oid = InvalidOid;
+ Oid mltrngConstruct0Oid = InvalidOid;
+ Oid mltrngConstruct1Oid = InvalidOid;
+ Oid mltrngConstruct2Oid = InvalidOid;
Oid castFuncOid;
/* Convert list of names to a name and namespace */
InvalidOid); /* type's collation (ranges never have one) */
Assert(multirangeOid == mltrngaddress.objectId);
- /* Create the entry in pg_range */
- RangeCreate(typoid, rangeSubtype, rangeCollation, rangeSubOpclass,
- rangeCanonical, rangeSubtypeDiff, multirangeOid);
-
/*
* Create the array type that goes with it.
*/
CommandCounterIncrement();
/* And create the constructor functions for this range type */
- makeRangeConstructors(typeName, typeNamespace, typoid, rangeSubtype);
+ makeRangeConstructors(typeName, typeNamespace, typoid, rangeSubtype,
+ &rangeConstruct2Oid, &rangeConstruct3Oid);
makeMultirangeConstructors(multirangeTypeName, typeNamespace,
multirangeOid, typoid, rangeArrayOid,
- &castFuncOid);
+ &mltrngConstruct0Oid, &mltrngConstruct1Oid, &mltrngConstruct2Oid);
+ castFuncOid = mltrngConstruct1Oid;
+
+ /* Create the entry in pg_range */
+ RangeCreate(typoid, rangeSubtype, rangeCollation, rangeSubOpclass,
+ rangeCanonical, rangeSubtypeDiff, multirangeOid,
+ rangeConstruct2Oid, rangeConstruct3Oid,
+ mltrngConstruct0Oid, mltrngConstruct1Oid, mltrngConstruct2Oid);
/* Create cast from the range type to its multirange type */
CastCreate(typoid, multirangeOid, castFuncOid, InvalidOid, InvalidOid,
*
* We actually define 2 functions, with 2 through 3 arguments. This is just
* to offer more convenience for the user.
+ *
+ * The OIDs of the created functions are returned through the pointer
+ * arguments.
*/
static void
makeRangeConstructors(const char *name, Oid namespace,
- Oid rangeOid, Oid subtype)
+ Oid rangeOid, Oid subtype,
+ Oid *rangeConstruct2_p, Oid *rangeConstruct3_p)
{
static const char *const prosrc[2] = {"range_constructor2",
"range_constructor3"};
* pg_dump depends on this choice to avoid dumping the constructors.
*/
recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
+
+ if (pronargs[i] == 2)
+ *rangeConstruct2_p = myself.objectId;
+ else if (pronargs[i] == 3)
+ *rangeConstruct3_p = myself.objectId;
}
}
* If we had an anyrangearray polymorphic type we could use it here,
* but since each type has its own constructor name there's no need.
*
- * Sets castFuncOid to the oid of the new constructor that can be used
- * to cast from a range to a multirange.
+ * The OIDs of the created functions are returned through the pointer
+ * arguments.
*/
static void
makeMultirangeConstructors(const char *name, Oid namespace,
Oid multirangeOid, Oid rangeOid, Oid rangeArrayOid,
- Oid *castFuncOid)
+ Oid *mltrngConstruct0_p, Oid *mltrngConstruct1_p, Oid *mltrngConstruct2_p)
{
ObjectAddress myself,
referenced;
* depends on this choice to avoid dumping the constructors.
*/
recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
+ *mltrngConstruct0_p = myself.objectId;
pfree(argtypes);
/*
0.0); /* prorows */
/* ditto */
recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
+ *mltrngConstruct1_p = myself.objectId;
pfree(argtypes);
- *castFuncOid = myself.objectId;
/* n-arg constructor - vararg */
argtypes = buildoidvector(&rangeArrayOid, 1);
0.0); /* prorows */
/* ditto */
recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
+ *mltrngConstruct2_p = myself.objectId;
pfree(argtypes);
pfree(allParameterTypes);
pfree(parameterModes);
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202601161
+#define CATALOG_VERSION_NO 202601221
#endif
{ rngtypid => 'int4range', rngsubtype => 'int4',
rngmultitypid => 'int4multirange', rngsubopc => 'btree/int4_ops',
+ rngconstruct2 => 'int4range(int4,int4)', rngconstruct3 => 'int4range(int4,int4,text)',
+ rngmltconstruct0 => 'int4multirange()', rngmltconstruct1 => 'int4multirange(int4range)', rngmltconstruct2 => 'int4multirange(_int4range)',
rngcanonical => 'int4range_canonical', rngsubdiff => 'int4range_subdiff' },
{ rngtypid => 'numrange', rngsubtype => 'numeric',
rngmultitypid => 'nummultirange', rngsubopc => 'btree/numeric_ops',
+ rngconstruct2 => 'numrange(numeric,numeric)', rngconstruct3 => 'numrange(numeric,numeric,text)',
+ rngmltconstruct0 => 'nummultirange()', rngmltconstruct1 => 'nummultirange(numrange)', rngmltconstruct2 => 'nummultirange(_numrange)',
rngcanonical => '-', rngsubdiff => 'numrange_subdiff' },
{ rngtypid => 'tsrange', rngsubtype => 'timestamp',
rngmultitypid => 'tsmultirange', rngsubopc => 'btree/timestamp_ops',
+ rngconstruct2 => 'tsrange(timestamp,timestamp)', rngconstruct3 => 'tsrange(timestamp,timestamp,text)',
+ rngmltconstruct0 => 'tsmultirange()', rngmltconstruct1 => 'tsmultirange(tsrange)', rngmltconstruct2 => 'tsmultirange(_tsrange)',
rngcanonical => '-', rngsubdiff => 'tsrange_subdiff' },
{ rngtypid => 'tstzrange', rngsubtype => 'timestamptz',
rngmultitypid => 'tstzmultirange', rngsubopc => 'btree/timestamptz_ops',
+ rngconstruct2 => 'tstzrange(timestamptz,timestamptz)', rngconstruct3 => 'tstzrange(timestamptz,timestamptz,text)',
+ rngmltconstruct0 => 'tstzmultirange()', rngmltconstruct1 => 'tstzmultirange(tstzrange)', rngmltconstruct2 => 'tstzmultirange(_tstzrange)',
rngcanonical => '-', rngsubdiff => 'tstzrange_subdiff' },
{ rngtypid => 'daterange', rngsubtype => 'date',
rngmultitypid => 'datemultirange', rngsubopc => 'btree/date_ops',
+ rngconstruct2 => 'daterange(date,date)', rngconstruct3 => 'daterange(date,date,text)',
+ rngmltconstruct0 => 'datemultirange()', rngmltconstruct1 => 'datemultirange(daterange)', rngmltconstruct2 => 'datemultirange(_daterange)',
rngcanonical => 'daterange_canonical', rngsubdiff => 'daterange_subdiff' },
{ rngtypid => 'int8range', rngsubtype => 'int8',
rngmultitypid => 'int8multirange', rngsubopc => 'btree/int8_ops',
+ rngconstruct2 => 'int8range(int8,int8)', rngconstruct3 => 'int8range(int8,int8,text)',
+ rngmltconstruct0 => 'int8multirange()', rngmltconstruct1 => 'int8multirange(int8range)', rngmltconstruct2 => 'int8multirange(_int8range)',
rngcanonical => 'int8range_canonical', rngsubdiff => 'int8range_subdiff' },
]
/* subtype's btree opclass */
Oid rngsubopc BKI_LOOKUP(pg_opclass);
+ /* range constructor functions */
+ regproc rngconstruct2 BKI_LOOKUP(pg_proc);
+ regproc rngconstruct3 BKI_LOOKUP(pg_proc);
+
+ /* multirange constructor functions */
+ regproc rngmltconstruct0 BKI_LOOKUP(pg_proc);
+ regproc rngmltconstruct1 BKI_LOOKUP(pg_proc);
+ regproc rngmltconstruct2 BKI_LOOKUP(pg_proc);
+
/* canonicalize range, or 0 */
regproc rngcanonical BKI_LOOKUP_OPT(pg_proc);
extern void RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation,
Oid rangeSubOpclass, RegProcedure rangeCanonical,
- RegProcedure rangeSubDiff, Oid multirangeTypeOid);
+ RegProcedure rangeSubDiff, Oid multirangeTypeOid,
+ RegProcedure rangeConstruct2, RegProcedure rangeConstruct3,
+ RegProcedure mltrngConstruct0, RegProcedure mltrngConstruct1, RegProcedure mltrngConstruct2);
extern void RangeDelete(Oid rangeTypeOid);
#endif /* PG_RANGE_H */
NOTICE: checking pg_range {rngmultitypid} => pg_type {oid}
NOTICE: checking pg_range {rngcollation} => pg_collation {oid}
NOTICE: checking pg_range {rngsubopc} => pg_opclass {oid}
+NOTICE: checking pg_range {rngconstruct2} => pg_proc {oid}
+NOTICE: checking pg_range {rngconstruct3} => pg_proc {oid}
+NOTICE: checking pg_range {rngmltconstruct0} => pg_proc {oid}
+NOTICE: checking pg_range {rngmltconstruct1} => pg_proc {oid}
+NOTICE: checking pg_range {rngmltconstruct2} => pg_proc {oid}
NOTICE: checking pg_range {rngcanonical} => pg_proc {oid}
NOTICE: checking pg_range {rngsubdiff} => pg_proc {oid}
NOTICE: checking pg_transform {trftype} => pg_type {oid}
-- Look for illegal values in pg_range fields.
SELECT r.rngtypid, r.rngsubtype
FROM pg_range as r
-WHERE r.rngtypid = 0 OR r.rngsubtype = 0 OR r.rngsubopc = 0;
+WHERE r.rngtypid = 0 OR r.rngsubtype = 0 OR r.rngsubopc = 0
+ OR r.rngconstruct2 = 0 OR r.rngconstruct3 = 0
+ OR r.rngmltconstruct0 = 0 OR r.rngmltconstruct1 = 0 OR r.rngmltconstruct2 = 0;
rngtypid | rngsubtype
----------+------------
(0 rows)
----------+------------+---------------
(0 rows)
+-- check constructor function arguments and return types
+--
+-- proname and prosrc are not required to have these particular
+-- values, but this matches what DefineRange() produces and serves to
+-- sanity-check the catalog entries for built-in types.
+SELECT r.rngtypid, r.rngsubtype, p.proname
+FROM pg_range r JOIN pg_proc p ON p.oid = r.rngconstruct2 JOIN pg_type t ON r.rngtypid = t.oid
+WHERE p.pronargs != 2
+ OR p.proargtypes[0] != r.rngsubtype OR p.proargtypes[1] != r.rngsubtype
+ OR p.prorettype != r.rngtypid
+ OR p.proname != t.typname OR p.prosrc != 'range_constructor2';
+ rngtypid | rngsubtype | proname
+----------+------------+---------
+(0 rows)
+
+SELECT r.rngtypid, r.rngsubtype, p.proname
+FROM pg_range r JOIN pg_proc p ON p.oid = r.rngconstruct3 JOIN pg_type t ON r.rngtypid = t.oid
+WHERE p.pronargs != 3
+ OR p.proargtypes[0] != r.rngsubtype OR p.proargtypes[1] != r.rngsubtype OR p.proargtypes[2] != 'pg_catalog.text'::regtype
+ OR p.prorettype != r.rngtypid
+ OR p.proname != t.typname OR p.prosrc != 'range_constructor3';
+ rngtypid | rngsubtype | proname
+----------+------------+---------
+(0 rows)
+
+SELECT r.rngtypid, r.rngsubtype, p.proname
+FROM pg_range r JOIN pg_proc p ON p.oid = r.rngmltconstruct0 JOIN pg_type t ON r.rngmultitypid = t.oid
+WHERE p.pronargs != 0
+ OR p.prorettype != r.rngmultitypid
+ OR p.proname != t.typname OR p.prosrc != 'multirange_constructor0';
+ rngtypid | rngsubtype | proname
+----------+------------+---------
+(0 rows)
+
+SELECT r.rngtypid, r.rngsubtype, p.proname
+FROM pg_range r JOIN pg_proc p ON p.oid = r.rngmltconstruct1 JOIN pg_type t ON r.rngmultitypid = t.oid
+WHERE p.pronargs != 1
+ OR p.proargtypes[0] != r.rngtypid
+ OR p.prorettype != r.rngmultitypid
+ OR p.proname != t.typname OR p.prosrc != 'multirange_constructor1';
+ rngtypid | rngsubtype | proname
+----------+------------+---------
+(0 rows)
+
+SELECT r.rngtypid, r.rngsubtype, p.proname
+FROM pg_range r JOIN pg_proc p ON p.oid = r.rngmltconstruct2 JOIN pg_type t ON r.rngmultitypid = t.oid JOIN pg_type t2 ON r.rngtypid = t2.oid
+WHERE p.pronargs != 1
+ OR p.proargtypes[0] != t2.typarray
+ OR p.prorettype != r.rngmultitypid
+ OR p.proname != t.typname OR p.prosrc != 'multirange_constructor2';
+ rngtypid | rngsubtype | proname
+----------+------------+---------
+(0 rows)
+
+-- ******************************************
-- Create a table that holds all the known in-core data types and leave it
-- around so as pg_upgrade is able to test their binary compatibility.
CREATE TABLE tab_core_types AS SELECT
SELECT r.rngtypid, r.rngsubtype
FROM pg_range as r
-WHERE r.rngtypid = 0 OR r.rngsubtype = 0 OR r.rngsubopc = 0;
+WHERE r.rngtypid = 0 OR r.rngsubtype = 0 OR r.rngsubopc = 0
+ OR r.rngconstruct2 = 0 OR r.rngconstruct3 = 0
+ OR r.rngmltconstruct0 = 0 OR r.rngmltconstruct1 = 0 OR r.rngmltconstruct2 = 0;
-- rngcollation should be specified iff subtype is collatable
FROM pg_range r
WHERE r.rngmultitypid IS NULL OR r.rngmultitypid = 0;
+-- check constructor function arguments and return types
+--
+-- proname and prosrc are not required to have these particular
+-- values, but this matches what DefineRange() produces and serves to
+-- sanity-check the catalog entries for built-in types.
+
+SELECT r.rngtypid, r.rngsubtype, p.proname
+FROM pg_range r JOIN pg_proc p ON p.oid = r.rngconstruct2 JOIN pg_type t ON r.rngtypid = t.oid
+WHERE p.pronargs != 2
+ OR p.proargtypes[0] != r.rngsubtype OR p.proargtypes[1] != r.rngsubtype
+ OR p.prorettype != r.rngtypid
+ OR p.proname != t.typname OR p.prosrc != 'range_constructor2';
+
+SELECT r.rngtypid, r.rngsubtype, p.proname
+FROM pg_range r JOIN pg_proc p ON p.oid = r.rngconstruct3 JOIN pg_type t ON r.rngtypid = t.oid
+WHERE p.pronargs != 3
+ OR p.proargtypes[0] != r.rngsubtype OR p.proargtypes[1] != r.rngsubtype OR p.proargtypes[2] != 'pg_catalog.text'::regtype
+ OR p.prorettype != r.rngtypid
+ OR p.proname != t.typname OR p.prosrc != 'range_constructor3';
+
+SELECT r.rngtypid, r.rngsubtype, p.proname
+FROM pg_range r JOIN pg_proc p ON p.oid = r.rngmltconstruct0 JOIN pg_type t ON r.rngmultitypid = t.oid
+WHERE p.pronargs != 0
+ OR p.prorettype != r.rngmultitypid
+ OR p.proname != t.typname OR p.prosrc != 'multirange_constructor0';
+
+SELECT r.rngtypid, r.rngsubtype, p.proname
+FROM pg_range r JOIN pg_proc p ON p.oid = r.rngmltconstruct1 JOIN pg_type t ON r.rngmultitypid = t.oid
+WHERE p.pronargs != 1
+ OR p.proargtypes[0] != r.rngtypid
+ OR p.prorettype != r.rngmultitypid
+ OR p.proname != t.typname OR p.prosrc != 'multirange_constructor1';
+
+SELECT r.rngtypid, r.rngsubtype, p.proname
+FROM pg_range r JOIN pg_proc p ON p.oid = r.rngmltconstruct2 JOIN pg_type t ON r.rngmultitypid = t.oid JOIN pg_type t2 ON r.rngtypid = t2.oid
+WHERE p.pronargs != 1
+ OR p.proargtypes[0] != t2.typarray
+ OR p.prorettype != r.rngmultitypid
+ OR p.proname != t.typname OR p.prosrc != 'multirange_constructor2';
+
+
+-- ******************************************
+
-- Create a table that holds all the known in-core data types and leave it
-- around so as pg_upgrade is able to test their binary compatibility.
CREATE TABLE tab_core_types AS SELECT