diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 492ed348b3..29ee9605b6 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -2374,6 +2374,17 @@ SCRAM-SHA-256$<iteration count>:&l
LC_CTYPE for this collation object
+
+
+
+ collversiontext
+
+
+ Provider-specific version of the collation. This is recorded when the
+ collation is created and then checked when it is used, to detect
+ changes in the collation definition that could lead to data corruption.
+
+
@@ -3317,18 +3328,6 @@ SCRAM-SHA-256$<iteration count>:&l
A code defining the specific semantics of this dependency relationship; see text
-
-
-
- refobjversiontext
-
-
- An optional version for the referenced object. Currently used for
- indexes' collations (see ).
-
-
-
-
diff --git a/doc/src/sgml/charset.sgml b/doc/src/sgml/charset.sgml
index 1c673cc110..98df74d0e1 100644
--- a/doc/src/sgml/charset.sgml
+++ b/doc/src/sgml/charset.sgml
@@ -948,54 +948,6 @@ CREATE COLLATION ignore_accents (provider = icu, locale = 'und-u-ks-level1-kc-tr
-
-
- Collation Versions
-
-
- The sort order defined by a collation is not necessarily fixed over time.
- PostgreSQL relies on external libraries that
- are subject to operating system upgrades, and can also differ between
- servers involved in binary replication and file-system-level migration.
- Persistent data structures such as B-trees that depend on sort order might
- be corrupted by any resulting change.
- PostgreSQL defends against this by recording the
- current version of each referenced collation for any index that depends on
- it in the
- pg_depend
- catalog, if the collation provider makes that information available. If the
- provider later begins to report a different version, a warning will be
- issued when the index is accessed, until either the
- command or the
- command is used to update the version.
-
-
- Version information is available from the
- icu provider on all operating systems. For the
- libc provider, versions are currently only available
- on systems using the GNU C library (most Linux systems), FreeBSD and
- Windows.
-
-
-
-
- When using the GNU C library for collations, the C library's version
- is used as a proxy for the collation version. Many Linux distributions
- change collation definitions only when upgrading the C library, but this
- approach is imperfect as maintainers are free to back-port newer
- collation definitions to older C library releases.
-
-
- When using Windows collations, version information is only available for
- collations defined with BCP 47 language tags such as
- en-US. Currently, initdb selects
- a default locale using a traditional Windows language and country
- string such as English_United States.1252. The
- --lc-collate option can be used to provide an explicit
- locale name in BCP 47 format.
-
-
-
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 0b5571460d..4d1f1794ca 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -26547,9 +26547,11 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup());
Returns the actual version of the collation object as it is currently
- installed in the operating system. null is returned
- on operating systems where PostgreSQL
- doesn't have support for versions.
+ installed in the operating system. If this is different from the
+ value in
+ pg_collation.collversion,
+ then objects depending on the collation might need to be rebuilt. See
+ also .
diff --git a/doc/src/sgml/ref/alter_collation.sgml b/doc/src/sgml/ref/alter_collation.sgml
index 65429aabe2..af9ff2867b 100644
--- a/doc/src/sgml/ref/alter_collation.sgml
+++ b/doc/src/sgml/ref/alter_collation.sgml
@@ -21,6 +21,8 @@ PostgreSQL documentation
+ALTER COLLATION name REFRESH VERSION
+
ALTER COLLATION name RENAME TO new_name
ALTER COLLATION name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER COLLATION name SET SCHEMA new_schema
@@ -86,9 +88,70 @@ ALTER COLLATION name SET SCHEMA new_sche
+
+ REFRESH VERSION
+
+
+ Update the collation's version.
+ See below.
+
+
+
+
+ Notes
+
+
+ When using collations provided by the ICU library, the ICU-specific version
+ of the collator is recorded in the system catalog when the collation object
+ is created. When the collation is used, the current version is
+ checked against the recorded version, and a warning is issued when there is
+ a mismatch, for example:
+
+WARNING: collation "xx-x-icu" has version mismatch
+DETAIL: The collation in the database was created using version 1.2.3.4, but the operating system provides version 2.3.4.5.
+HINT: Rebuild all objects affected by this collation and run ALTER COLLATION pg_catalog."xx-x-icu" REFRESH VERSION, or build PostgreSQL with the right library version.
+
+ A change in collation definitions can lead to corrupt indexes and other
+ problems because the database system relies on stored objects having a
+ certain sort order. Generally, this should be avoided, but it can happen
+ in legitimate circumstances, such as when
+ using pg_upgrade to upgrade to server binaries linked
+ with a newer version of ICU. When this happens, all objects depending on
+ the collation should be rebuilt, for example,
+ using REINDEX. When that is done, the collation version
+ can be refreshed using the command ALTER COLLATION ... REFRESH
+ VERSION. This will update the system catalog to record the
+ current collator version and will make the warning go away. Note that this
+ does not actually check whether all affected objects have been rebuilt
+ correctly.
+
+
+ When using collations provided by libc and
+ PostgreSQL was built with the GNU C library, the
+ C library's version is used as a collation version. Since collation
+ definitions typically change only with GNU C library releases, this provides
+ some defense against corruption, but it is not completely reliable.
+
+
+ Currently, there is no version tracking for the database default collation.
+
+
+
+ The following query can be used to identify all collations in the current
+ database that need to be refreshed and the objects that depend on them:
+ pg_collation_actual_version(c.oid)
+ ORDER BY 1, 2;
+]]>
+
+
Examples
diff --git a/doc/src/sgml/ref/alter_index.sgml b/doc/src/sgml/ref/alter_index.sgml
index 4b446384c2..e26efec064 100644
--- a/doc/src/sgml/ref/alter_index.sgml
+++ b/doc/src/sgml/ref/alter_index.sgml
@@ -25,7 +25,6 @@ ALTER INDEX [ IF EXISTS ] name RENA
ALTER INDEX [ IF EXISTS ] name SET TABLESPACE tablespace_name
ALTER INDEX name ATTACH PARTITION index_name
ALTER INDEX name [ NO ] DEPENDS ON EXTENSION extension_name
-ALTER INDEX name ALTER COLLATION collation_name REFRESH VERSION
ALTER INDEX [ IF EXISTS ] name SET ( storage_parameter [= value] [, ... ] )
ALTER INDEX [ IF EXISTS ] name RESET ( storage_parameter [, ... ] )
ALTER INDEX [ IF EXISTS ] name ALTER [ COLUMN ] column_number
@@ -113,20 +112,6 @@ ALTER INDEX ALL IN TABLESPACE name
-
- ALTER COLLATION collation_name REFRESH VERSION
-
-
- Silences warnings about mismatched collation versions, by declaring
- that the index is compatible with the current collation definition.
- Be aware that incorrect use of this command can hide index corruption.
- If you don't know whether a collation's definition has changed
- incompatibly, is a safe alternative.
- See for more information.
-
-
-
-
SET ( storage_parameter [= value] [, ... ] )
diff --git a/doc/src/sgml/ref/create_collation.sgml b/doc/src/sgml/ref/create_collation.sgml
index b97842071f..58f5f0cd63 100644
--- a/doc/src/sgml/ref/create_collation.sgml
+++ b/doc/src/sgml/ref/create_collation.sgml
@@ -27,6 +27,7 @@ CREATE COLLATION [ IF NOT EXISTS ] name (
[ LC_CTYPE = lc_ctype, ]
[ PROVIDER = provider, ]
[ DETERMINISTIC = boolean, ]
+ [ VERSION = version ]
)
CREATE COLLATION [ IF NOT EXISTS ] name FROM existing_collation
@@ -148,6 +149,26 @@ CREATE COLLATION [ IF NOT EXISTS ] name FROM
+
+ version
+
+
+
+ Specifies the version string to store with the collation. Normally,
+ this should be omitted, which will cause the version to be computed
+ from the actual version of the collation as provided by the operating
+ system. This option is intended to be used
+ by pg_upgrade for copying the version from an
+ existing installation.
+
+
+
+ See also for how to handle
+ collation version mismatches.
+
+
+
+
existing_collation
diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml
index 4737d97d20..a83c63cd98 100644
--- a/doc/src/sgml/ref/pgupgrade.sgml
+++ b/doc/src/sgml/ref/pgupgrade.sgml
@@ -215,21 +215,6 @@ PostgreSQL documentation
-
-
-
-
- When upgrading indexes from releases before 14 that didn't track
- collation versions, pg_upgrade
- assumes by default that the upgraded indexes are compatible with the
- currently installed versions of relevant collations (see
- ). Specify
- to mark
- them as needing to be rebuilt instead.
-
-
-
-
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 53c362dcd3..e6b25ee670 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -40,15 +40,6 @@ REINDEX [ ( option [, ...] ) ] { IN
several scenarios in which to use REINDEX:
-
-
- The index depends on the sort order of a collation, and the definition
- of the collation has changed. This can cause index scans to fail to
- find keys that are present. See for
- more information.
-
-
-
An index has become corrupted, and no longer contains valid
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 41093ea6ae..259cde3397 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -76,7 +76,6 @@
#include "rewrite/rewriteRemove.h"
#include "storage/lmgr.h"
#include "utils/acl.h"
-#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
@@ -435,84 +434,6 @@ performMultipleDeletions(const ObjectAddresses *objects,
table_close(depRel, RowExclusiveLock);
}
-/*
- * Call a function for all objects that 'object' depend on. If the function
- * returns true, refobjversion will be updated in the catalog.
- */
-void
-visitDependenciesOf(const ObjectAddress *object,
- VisitDependenciesOfCB callback,
- void *userdata)
-{
- Relation depRel;
- ScanKeyData key[3];
- SysScanDesc scan;
- HeapTuple tup;
- ObjectAddress otherObject;
-
- ScanKeyInit(&key[0],
- Anum_pg_depend_classid,
- BTEqualStrategyNumber, F_OIDEQ,
- ObjectIdGetDatum(object->classId));
- ScanKeyInit(&key[1],
- Anum_pg_depend_objid,
- BTEqualStrategyNumber, F_OIDEQ,
- ObjectIdGetDatum(object->objectId));
- ScanKeyInit(&key[2],
- Anum_pg_depend_objsubid,
- BTEqualStrategyNumber, F_INT4EQ,
- Int32GetDatum(object->objectSubId));
-
- depRel = table_open(DependRelationId, RowExclusiveLock);
- scan = systable_beginscan(depRel, DependDependerIndexId, true,
- NULL, 3, key);
-
- while (HeapTupleIsValid(tup = systable_getnext(scan)))
- {
- Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
- char *new_version;
- Datum depversion;
- bool isnull;
-
- otherObject.classId = foundDep->refclassid;
- otherObject.objectId = foundDep->refobjid;
- otherObject.objectSubId = foundDep->refobjsubid;
-
- depversion = heap_getattr(tup, Anum_pg_depend_refobjversion,
- RelationGetDescr(depRel), &isnull);
-
- /* Does the callback want to update the version? */
- if (callback(&otherObject,
- isnull ? NULL : TextDatumGetCString(depversion),
- &new_version,
- userdata))
- {
- Datum values[Natts_pg_depend];
- bool nulls[Natts_pg_depend];
- bool replaces[Natts_pg_depend];
-
- memset(values, 0, sizeof(values));
- memset(nulls, false, sizeof(nulls));
- memset(replaces, false, sizeof(replaces));
-
- if (new_version)
- values[Anum_pg_depend_refobjversion - 1] =
- CStringGetTextDatum(new_version);
- else
- nulls[Anum_pg_depend_refobjversion - 1] = true;
- replaces[Anum_pg_depend_refobjversion - 1] = true;
-
- tup = heap_modify_tuple(tup, RelationGetDescr(depRel), values,
- nulls, replaces);
- CatalogTupleUpdate(depRel, &tup->t_self, tup);
-
- heap_freetuple(tup);
- }
- }
- systable_endscan(scan);
- table_close(depRel, RowExclusiveLock);
-}
-
/*
* findDependentObjects - find all objects that depend on 'object'
*
@@ -1639,38 +1560,6 @@ ReleaseDeletionLock(const ObjectAddress *object)
AccessExclusiveLock);
}
-/*
- * Record dependencies on a list of collations, optionally with their current
- * version.
- */
-void
-recordDependencyOnCollations(ObjectAddress *myself,
- List *collations,
- bool record_version)
-{
- ObjectAddresses *addrs;
- ListCell *lc;
-
- if (list_length(collations) == 0)
- return;
-
- addrs = new_object_addresses();
- foreach(lc, collations)
- {
- ObjectAddress referenced;
-
- ObjectAddressSet(referenced, CollationRelationId, lfirst_oid(lc));
-
- add_exact_object_address(&referenced, addrs);
- }
-
- eliminate_duplicate_dependencies(addrs);
- recordMultipleDependencies(myself, addrs->refs, addrs->numrefs,
- DEPENDENCY_NORMAL, record_version);
-
- free_object_addresses(addrs);
-}
-
/*
* recordDependencyOnExpr - find expression dependencies
*
@@ -1705,10 +1594,8 @@ recordDependencyOnExpr(const ObjectAddress *depender,
/* And record 'em */
recordMultipleDependencies(depender,
- context.addrs->refs,
- context.addrs->numrefs,
- behavior,
- false);
+ context.addrs->refs, context.addrs->numrefs,
+ behavior);
free_object_addresses(context.addrs);
}
@@ -1735,8 +1622,7 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
Node *expr, Oid relId,
DependencyType behavior,
DependencyType self_behavior,
- bool reverse_self,
- bool record_version)
+ bool reverse_self)
{
find_expr_references_context context;
RangeTblEntry rte;
@@ -1795,10 +1681,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
/* Record the self-dependencies with the appropriate direction */
if (!reverse_self)
recordMultipleDependencies(depender,
- self_addrs->refs,
- self_addrs->numrefs,
- self_behavior,
- record_version);
+ self_addrs->refs, self_addrs->numrefs,
+ self_behavior);
else
{
/* Can't use recordMultipleDependencies, so do it the hard way */
@@ -1817,10 +1701,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
/* Record the external dependencies */
recordMultipleDependencies(depender,
- context.addrs->refs,
- context.addrs->numrefs,
- behavior,
- record_version);
+ context.addrs->refs, context.addrs->numrefs,
+ behavior);
free_object_addresses(context.addrs);
}
@@ -1835,17 +1717,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
* the datatype. However we do need a type dependency if there is no such
* indirect dependency, as for example in Const and CoerceToDomain nodes.
*
- * Collations are handled primarily by recording the inputcollid's of node
- * types that have them, as those are the ones that are semantically
- * significant during expression evaluation. We also record the collation of
- * CollateExpr nodes, since those will be needed to print such nodes even if
- * they don't really affect semantics. Collations of leaf nodes such as Vars
- * can be ignored on the grounds that if they're not default, they came from
- * the referenced object (e.g., a table column), so the dependency on that
- * object is enough. (Note: in a post-const-folding expression tree, a
- * CollateExpr's collation could have been absorbed into a Const or
- * RelabelType node. While ruleutils.c prints such collations for clarity,
- * we may ignore them here as they have no semantic effect.)
+ * Similarly, we don't need to create dependencies on collations except where
+ * the collation is being freshly introduced to the expression.
*/
static bool
find_expr_references_walker(Node *node,
@@ -1906,6 +1779,17 @@ find_expr_references_walker(Node *node,
add_object_address(OCLASS_TYPE, con->consttype, 0,
context->addrs);
+ /*
+ * We must also depend on the constant's collation: it could be
+ * different from the datatype's, if a CollateExpr was const-folded to
+ * a simple constant. However we can save work in the most common
+ * case where the collation is "default", since we know that's pinned.
+ */
+ if (OidIsValid(con->constcollid) &&
+ con->constcollid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, con->constcollid, 0,
+ context->addrs);
+
/*
* If it's a regclass or similar literal referring to an existing
* object, add a reference to that object. (Currently, only the
@@ -1990,6 +1874,11 @@ find_expr_references_walker(Node *node,
/* A parameter must depend on the parameter's datatype */
add_object_address(OCLASS_TYPE, param->paramtype, 0,
context->addrs);
+ /* and its collation, just as for Consts */
+ if (OidIsValid(param->paramcollid) &&
+ param->paramcollid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, param->paramcollid, 0,
+ context->addrs);
}
else if (IsA(node, FuncExpr))
{
@@ -1997,9 +1886,6 @@ find_expr_references_walker(Node *node,
add_object_address(OCLASS_PROC, funcexpr->funcid, 0,
context->addrs);
- if (OidIsValid(funcexpr->inputcollid))
- add_object_address(OCLASS_COLLATION, funcexpr->inputcollid, 0,
- context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, OpExpr))
@@ -2008,9 +1894,6 @@ find_expr_references_walker(Node *node,
add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
context->addrs);
- if (OidIsValid(opexpr->inputcollid))
- add_object_address(OCLASS_COLLATION, opexpr->inputcollid, 0,
- context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, DistinctExpr))
@@ -2019,9 +1902,6 @@ find_expr_references_walker(Node *node,
add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0,
context->addrs);
- if (OidIsValid(distinctexpr->inputcollid))
- add_object_address(OCLASS_COLLATION, distinctexpr->inputcollid, 0,
- context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, NullIfExpr))
@@ -2030,9 +1910,6 @@ find_expr_references_walker(Node *node,
add_object_address(OCLASS_OPERATOR, nullifexpr->opno, 0,
context->addrs);
- if (OidIsValid(nullifexpr->inputcollid))
- add_object_address(OCLASS_COLLATION, nullifexpr->inputcollid, 0,
- context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, ScalarArrayOpExpr))
@@ -2041,9 +1918,6 @@ find_expr_references_walker(Node *node,
add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
context->addrs);
- if (OidIsValid(opexpr->inputcollid))
- add_object_address(OCLASS_COLLATION, opexpr->inputcollid, 0,
- context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, Aggref))
@@ -2052,9 +1926,6 @@ find_expr_references_walker(Node *node,
add_object_address(OCLASS_PROC, aggref->aggfnoid, 0,
context->addrs);
- if (OidIsValid(aggref->inputcollid))
- add_object_address(OCLASS_COLLATION, aggref->inputcollid, 0,
- context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, WindowFunc))
@@ -2063,9 +1934,6 @@ find_expr_references_walker(Node *node,
add_object_address(OCLASS_PROC, wfunc->winfnoid, 0,
context->addrs);
- if (OidIsValid(wfunc->inputcollid))
- add_object_address(OCLASS_COLLATION, wfunc->inputcollid, 0,
- context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, SubscriptingRef))
@@ -2110,6 +1978,11 @@ find_expr_references_walker(Node *node,
else
add_object_address(OCLASS_TYPE, fselect->resulttype, 0,
context->addrs);
+ /* the collation might not be referenced anywhere else, either */
+ if (OidIsValid(fselect->resultcollid) &&
+ fselect->resultcollid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, fselect->resultcollid, 0,
+ context->addrs);
}
else if (IsA(node, FieldStore))
{
@@ -2136,6 +2009,11 @@ find_expr_references_walker(Node *node,
/* since there is no function dependency, need to depend on type */
add_object_address(OCLASS_TYPE, relab->resulttype, 0,
context->addrs);
+ /* the collation might not be referenced anywhere else, either */
+ if (OidIsValid(relab->resultcollid) &&
+ relab->resultcollid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, relab->resultcollid, 0,
+ context->addrs);
}
else if (IsA(node, CoerceViaIO))
{
@@ -2144,6 +2022,11 @@ find_expr_references_walker(Node *node,
/* since there is no exposed function, need to depend on type */
add_object_address(OCLASS_TYPE, iocoerce->resulttype, 0,
context->addrs);
+ /* the collation might not be referenced anywhere else, either */
+ if (OidIsValid(iocoerce->resultcollid) &&
+ iocoerce->resultcollid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, iocoerce->resultcollid, 0,
+ context->addrs);
}
else if (IsA(node, ArrayCoerceExpr))
{
@@ -2152,6 +2035,11 @@ find_expr_references_walker(Node *node,
/* as above, depend on type */
add_object_address(OCLASS_TYPE, acoerce->resulttype, 0,
context->addrs);
+ /* the collation might not be referenced anywhere else, either */
+ if (OidIsValid(acoerce->resultcollid) &&
+ acoerce->resultcollid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, acoerce->resultcollid, 0,
+ context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, ConvertRowtypeExpr))
@@ -2191,24 +2079,6 @@ find_expr_references_walker(Node *node,
add_object_address(OCLASS_OPFAMILY, lfirst_oid(l), 0,
context->addrs);
}
- foreach(l, rcexpr->inputcollids)
- {
- Oid inputcollid = lfirst_oid(l);
-
- if (OidIsValid(inputcollid))
- add_object_address(OCLASS_COLLATION, inputcollid, 0,
- context->addrs);
- }
- /* fall through to examine arguments */
- }
- else if (IsA(node, MinMaxExpr))
- {
- MinMaxExpr *mmexpr = (MinMaxExpr *) node;
-
- /* minmaxtype will match one of the inputs, so no need to record it */
- if (OidIsValid(mmexpr->inputcollid))
- add_object_address(OCLASS_COLLATION, mmexpr->inputcollid, 0,
- context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, CoerceToDomain))
@@ -2255,7 +2125,8 @@ find_expr_references_walker(Node *node,
if (OidIsValid(wc->endInRangeFunc))
add_object_address(OCLASS_PROC, wc->endInRangeFunc, 0,
context->addrs);
- if (OidIsValid(wc->inRangeColl))
+ if (OidIsValid(wc->inRangeColl) &&
+ wc->inRangeColl != DEFAULT_COLLATION_OID)
add_object_address(OCLASS_COLLATION, wc->inRangeColl, 0,
context->addrs);
/* fall through to examine substructure */
@@ -2415,7 +2286,7 @@ find_expr_references_walker(Node *node,
{
Oid collid = lfirst_oid(ct);
- if (OidIsValid(collid))
+ if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID)
add_object_address(OCLASS_COLLATION, collid, 0,
context->addrs);
}
@@ -2437,7 +2308,7 @@ find_expr_references_walker(Node *node,
{
Oid collid = lfirst_oid(ct);
- if (OidIsValid(collid))
+ if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID)
add_object_address(OCLASS_COLLATION, collid, 0,
context->addrs);
}
@@ -2834,8 +2705,7 @@ record_object_address_dependencies(const ObjectAddress *depender,
eliminate_duplicate_dependencies(referenced);
recordMultipleDependencies(depender,
referenced->refs, referenced->numrefs,
- behavior,
- false);
+ behavior);
}
/*
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 42ff175bc8..431e62e389 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -2357,7 +2357,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
*/
recordDependencyOnSingleRelExpr(&colobject, expr, RelationGetRelid(rel),
DEPENDENCY_AUTO,
- DEPENDENCY_AUTO, false, false);
+ DEPENDENCY_AUTO, false);
}
else
{
@@ -2367,7 +2367,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
*/
recordDependencyOnSingleRelExpr(&defobject, expr, RelationGetRelid(rel),
DEPENDENCY_NORMAL,
- DEPENDENCY_NORMAL, false, false);
+ DEPENDENCY_NORMAL, false);
}
/*
@@ -3729,8 +3729,7 @@ StorePartitionKey(Relation rel,
RelationGetRelid(rel),
DEPENDENCY_NORMAL,
DEPENDENCY_INTERNAL,
- true /* reverse the self-deps */ ,
- false /* don't track versions */ );
+ true /* reverse the self-deps */ );
/*
* We must invalidate the relcache so that the next
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index a628b3281c..8ded2b53d4 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -54,7 +54,6 @@
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
#include "catalog/storage.h"
-#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/progress.h"
#include "commands/tablecmds.h"
@@ -78,7 +77,6 @@
#include "utils/guc.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
-#include "utils/pg_locale.h"
#include "utils/memutils.h"
#include "utils/pg_rusage.h"
#include "utils/rel.h"
@@ -1034,8 +1032,6 @@ index_create(Relation heapRelation,
ObjectAddress myself,
referenced;
ObjectAddresses *addrs;
- List *colls = NIL,
- *colls_no_version = NIL;
ObjectAddressSet(myself, RelationRelationId, indexRelationId);
@@ -1119,65 +1115,30 @@ index_create(Relation heapRelation,
recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_SEC);
}
- /* Get dependencies on collations for all index keys. */
+ /* placeholder for normal dependencies */
+ addrs = new_object_addresses();
+
+ /* Store dependency on collations */
+
+ /* The default collation is pinned, so don't bother recording it */
for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
{
- Oid colloid = collationObjectId[i];
-
- if (OidIsValid(colloid))
+ if (OidIsValid(collationObjectId[i]) &&
+ collationObjectId[i] != DEFAULT_COLLATION_OID)
{
- Oid opclass = classObjectId[i];
-
- /*
- * The *_pattern_ops opclasses are special: they explicitly do
- * not depend on collation order so we can save some effort.
- *
- * XXX With more analysis, we could also skip version tracking
- * for some cases like hash indexes with deterministic
- * collations, because they will never need to order strings.
- */
- if (opclass == TEXT_BTREE_PATTERN_OPS_OID ||
- opclass == VARCHAR_BTREE_PATTERN_OPS_OID ||
- opclass == BPCHAR_BTREE_PATTERN_OPS_OID)
- colls_no_version = lappend_oid(colls_no_version, colloid);
- else
- colls = lappend_oid(colls, colloid);
- }
- else
- {
- Form_pg_attribute att = TupleDescAttr(indexTupDesc, i);
-
- Assert(i < indexTupDesc->natts);
-
- /*
- * Even though there is no top-level collation, there may be
- * collations affecting ordering inside types, so look there
- * too.
- */
- colls = list_concat(colls, GetTypeCollations(att->atttypid));
+ ObjectAddressSet(referenced, CollationRelationId,
+ collationObjectId[i]);
+ add_exact_object_address(&referenced, addrs);
}
}
- /*
- * If we have anything in both lists, keep just the versioned one to
- * avoid some duplication.
- */
- if (colls_no_version != NIL && colls != NIL)
- colls_no_version = list_difference_oid(colls_no_version, colls);
-
- /* Store the versioned and unversioned collation dependencies. */
- if (colls_no_version != NIL)
- recordDependencyOnCollations(&myself, colls_no_version, false);
- if (colls != NIL)
- recordDependencyOnCollations(&myself, colls, true);
-
/* Store dependency on operator classes */
- addrs = new_object_addresses();
for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
{
ObjectAddressSet(referenced, OperatorClassRelationId, classObjectId[i]);
add_exact_object_address(&referenced, addrs);
}
+
record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
free_object_addresses(addrs);
@@ -1188,7 +1149,7 @@ index_create(Relation heapRelation,
(Node *) indexInfo->ii_Expressions,
heapRelationId,
DEPENDENCY_NORMAL,
- DEPENDENCY_AUTO, false, true);
+ DEPENDENCY_AUTO, false);
}
/* Store dependencies on anything mentioned in predicate */
@@ -1198,7 +1159,7 @@ index_create(Relation heapRelation,
(Node *) indexInfo->ii_Predicate,
heapRelationId,
DEPENDENCY_NORMAL,
- DEPENDENCY_AUTO, false, true);
+ DEPENDENCY_AUTO, false);
}
}
else
@@ -1277,130 +1238,6 @@ index_create(Relation heapRelation,
return indexRelationId;
}
-typedef struct do_collation_version_check_context
-{
- Oid relid;
- List *warned_colls;
-} do_collation_version_check_context;
-
-/*
- * Raise a warning if the recorded and current collation version don't match.
- * This is a callback for visitDependenciesOf().
- */
-static bool
-do_collation_version_check(const ObjectAddress *otherObject,
- const char *version,
- char **new_version,
- void *data)
-{
- do_collation_version_check_context *context = data;
- char *current_version;
-
- /* We only care about dependencies on collations with a version. */
- if (!version || otherObject->classId != CollationRelationId)
- return false;
-
- /* Ask the provider for the current version. Give up if unsupported. */
- current_version = get_collation_version_for_oid(otherObject->objectId,
- false);
- if (!current_version)
- return false;
-
- /*
- * We don't expect too many duplicates, but it's possible, and we don't
- * want to generate duplicate warnings.
- */
- if (list_member_oid(context->warned_colls, otherObject->objectId))
- return false;
-
- /* Do they match? */
- if (strcmp(current_version, version) != 0)
- {
- /*
- * The version has changed, probably due to an OS/library upgrade or
- * streaming replication between different OS/library versions.
- */
- ereport(WARNING,
- (errmsg("index \"%s\" depends on collation \"%s\" version \"%s\", but the current version is \"%s\"",
- get_rel_name(context->relid),
- get_collation_name(otherObject->objectId),
- version,
- current_version),
- errdetail("The index may be corrupted due to changes in sort order."),
- errhint("REINDEX to avoid the risk of corruption.")));
-
- /* Remember not to complain about this collation again. */
- context->warned_colls = lappend_oid(context->warned_colls,
- otherObject->objectId);
- }
-
- return false;
-}
-
-/* index_check_collation_versions
- * Check the collation version for all dependencies on the given index.
- */
-void
-index_check_collation_versions(Oid relid)
-{
- do_collation_version_check_context context;
- ObjectAddress object;
-
- /*
- * The callback needs the relid for error messages, and some scratch space
- * to avoid duplicate warnings.
- */
- context.relid = relid;
- context.warned_colls = NIL;
-
- object.classId = RelationRelationId;
- object.objectId = relid;
- object.objectSubId = 0;
-
- visitDependenciesOf(&object, &do_collation_version_check, &context);
-
- list_free(context.warned_colls);
-}
-
-/*
- * Update the version for collations. A callback for visitDependenciesOf().
- */
-static bool
-do_collation_version_update(const ObjectAddress *otherObject,
- const char *version,
- char **new_version,
- void *data)
-{
- Oid *coll = data;
-
- /* We only care about dependencies on collations with versions. */
- if (!version || otherObject->classId != CollationRelationId)
- return false;
-
- /* If we're only trying to update one collation, skip others. */
- if (OidIsValid(*coll) && otherObject->objectId != *coll)
- return false;
-
- *new_version = get_collation_version_for_oid(otherObject->objectId, false);
-
- return true;
-}
-
-/*
- * Record the current versions of one or all collations that an index depends
- * on. InvalidOid means all.
- */
-void
-index_update_collation_versions(Oid relid, Oid coll)
-{
- ObjectAddress object;
-
- object.classId = RelationRelationId;
- object.objectId = relid;
- object.objectSubId = 0;
- visitDependenciesOf(&object, &do_collation_version_update, &coll);
-}
-
/*
* index_concurrently_create_copy
*
@@ -1864,10 +1701,6 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
changeDependenciesOf(RelationRelationId, oldIndexId, newIndexId);
changeDependenciesOn(RelationRelationId, oldIndexId, newIndexId);
- /* Now we have the old index's collation versions, so fix that. */
- CommandCounterIncrement();
- index_update_collation_versions(newIndexId, InvalidOid);
-
/*
* Copy over statistics from old to new index
*/
@@ -3921,9 +3754,6 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
/* Close rels, but keep locks */
index_close(iRel, NoLock);
table_close(heapRelation, NoLock);
-
- /* Record the current versions of all depended-on collations. */
- index_update_collation_versions(indexId, InvalidOid);
}
/*
diff --git a/src/backend/catalog/pg_collation.c b/src/backend/catalog/pg_collation.c
index 40d98a334a..19068b652a 100644
--- a/src/backend/catalog/pg_collation.c
+++ b/src/backend/catalog/pg_collation.c
@@ -49,6 +49,7 @@ CollationCreate(const char *collname, Oid collnamespace,
bool collisdeterministic,
int32 collencoding,
const char *collcollate, const char *collctype,
+ const char *collversion,
bool if_not_exists,
bool quiet)
{
@@ -166,6 +167,10 @@ CollationCreate(const char *collname, Oid collnamespace,
values[Anum_pg_collation_collcollate - 1] = NameGetDatum(&name_collate);
namestrcpy(&name_ctype, collctype);
values[Anum_pg_collation_collctype - 1] = NameGetDatum(&name_ctype);
+ if (collversion)
+ values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(collversion);
+ else
+ nulls[Anum_pg_collation_collversion - 1] = true;
tup = heap_form_tuple(tupDesc, values, nulls);
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 0081558c48..a4e890020f 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -362,7 +362,7 @@ CreateConstraintEntry(const char *constraintName,
*/
recordDependencyOnSingleRelExpr(&conobject, conExpr, relId,
DEPENDENCY_NORMAL,
- DEPENDENCY_NORMAL, false, true);
+ DEPENDENCY_NORMAL, false);
}
/* Post creation hook for new constraint */
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index 1217c01b8a..54688094f5 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -19,16 +19,13 @@
#include "access/table.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
-#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_extension.h"
#include "commands/extension.h"
#include "miscadmin.h"
-#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
-#include "utils/pg_locale.h"
#include "utils/rel.h"
@@ -47,24 +44,18 @@ recordDependencyOn(const ObjectAddress *depender,
const ObjectAddress *referenced,
DependencyType behavior)
{
- recordMultipleDependencies(depender, referenced, 1, behavior, false);
+ recordMultipleDependencies(depender, referenced, 1, behavior);
}
/*
* Record multiple dependencies (of the same kind) for a single dependent
* object. This has a little less overhead than recording each separately.
- *
- * If record_version is true, then a record is added even if the referenced
- * object is pinned, and the dependency version will be retrieved according to
- * the referenced object kind. For now, only collation version is
- * supported.
*/
void
recordMultipleDependencies(const ObjectAddress *depender,
const ObjectAddress *referenced,
int nreferenced,
- DependencyType behavior,
- bool record_version)
+ DependencyType behavior)
{
Relation dependDesc;
CatalogIndexState indstate;
@@ -103,30 +94,12 @@ recordMultipleDependencies(const ObjectAddress *depender,
slot_init_count = 0;
for (i = 0; i < nreferenced; i++, referenced++)
{
- char *version = NULL;
-
- if (record_version)
- {
- /* For now we only know how to deal with collations. */
- if (referenced->classId == CollationRelationId)
- {
- /* These are unversioned, so don't waste cycles on them. */
- if (referenced->objectId == C_COLLATION_OID ||
- referenced->objectId == POSIX_COLLATION_OID)
- continue;
-
- version = get_collation_version_for_oid(referenced->objectId,
- false);
- }
- }
-
/*
* If the referenced object is pinned by the system, there's no real
- * need to record dependencies on it, unless we need to record a
- * version. This saves lots of space in pg_depend, so it's worth the
- * time taken to check.
+ * need to record dependencies on it. This saves lots of space in
+ * pg_depend, so it's worth the time taken to check.
*/
- if (version == NULL && isObjectPinned(referenced, dependDesc))
+ if (isObjectPinned(referenced, dependDesc))
continue;
if (slot_init_count < max_slots)
@@ -142,9 +115,6 @@ recordMultipleDependencies(const ObjectAddress *depender,
* Record the dependency. Note we don't bother to check for duplicate
* dependencies; there's no harm in them.
*/
- memset(slot[slot_stored_count]->tts_isnull, false,
- slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool));
-
slot[slot_stored_count]->tts_values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
slot[slot_stored_count]->tts_values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
slot[slot_stored_count]->tts_values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
@@ -152,10 +122,9 @@ recordMultipleDependencies(const ObjectAddress *depender,
slot[slot_stored_count]->tts_values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
slot[slot_stored_count]->tts_values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
slot[slot_stored_count]->tts_values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);
- if (version)
- slot[slot_stored_count]->tts_values[Anum_pg_depend_refobjversion - 1] = CStringGetTextDatum(version);
- else
- slot[slot_stored_count]->tts_isnull[Anum_pg_depend_refobjversion - 1] = true;
+
+ memset(slot[slot_stored_count]->tts_isnull, false,
+ slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool));
ExecStoreVirtualTuple(slot[slot_stored_count]);
slot_stored_count++;
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index dc9d28a32c..da65584476 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -15,7 +15,6 @@
#include "postgres.h"
#include "access/htup_details.h"
-#include "access/relation.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/binary_upgrade.h"
@@ -520,74 +519,6 @@ TypeCreate(Oid newTypeOid,
return address;
}
-/*
- * Get a list of all distinct collations that the given type depends on.
- */
-List *
-GetTypeCollations(Oid typeoid)
-{
- List *result = NIL;
- HeapTuple tuple;
- Form_pg_type typeTup;
-
- tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeoid));
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "cache lookup failed for type %u", typeoid);
- typeTup = (Form_pg_type) GETSTRUCT(tuple);
-
- /*
- * If the type has a typcollation attribute, report that and we're done.
- * Otherwise, it could be a container type that we should recurse into.
- */
- if (OidIsValid(typeTup->typcollation))
- result = list_make1_oid(typeTup->typcollation);
- else if (typeTup->typtype == TYPTYPE_COMPOSITE)
- {
- Relation rel = relation_open(typeTup->typrelid, AccessShareLock);
- TupleDesc desc = RelationGetDescr(rel);
-
- for (int i = 0; i < RelationGetNumberOfAttributes(rel); i++)
- {
- Form_pg_attribute att = TupleDescAttr(desc, i);
-
- if (att->attisdropped)
- continue;
- if (OidIsValid(att->attcollation))
- result = list_append_unique_oid(result, att->attcollation);
- else
- result = list_concat_unique_oid(result,
- GetTypeCollations(att->atttypid));
- }
-
- relation_close(rel, NoLock);
- }
- else if (typeTup->typtype == TYPTYPE_DOMAIN)
- {
- Assert(OidIsValid(typeTup->typbasetype));
- result = GetTypeCollations(typeTup->typbasetype);
- }
- else if (typeTup->typtype == TYPTYPE_RANGE)
- {
- Oid rangecoll = get_range_collation(typeTup->oid);
-
- if (OidIsValid(rangecoll))
- result = list_make1_oid(rangecoll);
- else
- {
- Oid rangeid = get_range_subtype(typeTup->oid);
-
- Assert(OidIsValid(rangeid));
- result = GetTypeCollations(rangeid);
- }
- }
- else if (IsTrueArrayType(typeTup))
- result = GetTypeCollations(typeTup->typelem);
-
- ReleaseSysCache(tuple);
-
- return result;
-}
-
/*
* GenerateTypeDependencies: build the dependencies needed for a type
*
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index b8ec6f5756..ebb0994db3 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -62,12 +62,14 @@ DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_e
DefElem *lcctypeEl = NULL;
DefElem *providerEl = NULL;
DefElem *deterministicEl = NULL;
+ DefElem *versionEl = NULL;
char *collcollate = NULL;
char *collctype = NULL;
char *collproviderstr = NULL;
bool collisdeterministic = true;
int collencoding = 0;
char collprovider = 0;
+ char *collversion = NULL;
Oid newoid;
ObjectAddress address;
@@ -95,6 +97,8 @@ DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_e
defelp = &providerEl;
else if (strcmp(defel->defname, "deterministic") == 0)
defelp = &deterministicEl;
+ else if (strcmp(defel->defname, "version") == 0)
+ defelp = &versionEl;
else
{
ereport(ERROR,
@@ -163,6 +167,9 @@ DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_e
if (deterministicEl)
collisdeterministic = defGetBoolean(deterministicEl);
+ if (versionEl)
+ collversion = defGetString(versionEl);
+
if (collproviderstr)
{
if (pg_strcasecmp(collproviderstr, "icu") == 0)
@@ -209,6 +216,9 @@ DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_e
}
}
+ if (!collversion)
+ collversion = get_collation_actual_version(collprovider, collcollate);
+
newoid = CollationCreate(collName,
collNamespace,
GetUserId(),
@@ -217,6 +227,7 @@ DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_e
collencoding,
collcollate,
collctype,
+ collversion,
if_not_exists,
false); /* not quiet */
@@ -267,13 +278,101 @@ IsThereCollationInNamespace(const char *collname, Oid nspOid)
collname, get_namespace_name(nspOid))));
}
+/*
+ * ALTER COLLATION
+ */
+ObjectAddress
+AlterCollation(AlterCollationStmt *stmt)
+{
+ Relation rel;
+ Oid collOid;
+ HeapTuple tup;
+ Form_pg_collation collForm;
+ Datum collversion;
+ bool isnull;
+ char *oldversion;
+ char *newversion;
+ ObjectAddress address;
+
+ rel = table_open(CollationRelationId, RowExclusiveLock);
+ collOid = get_collation_oid(stmt->collname, false);
+
+ if (!pg_collation_ownercheck(collOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_COLLATION,
+ NameListToString(stmt->collname));
+
+ tup = SearchSysCacheCopy1(COLLOID, ObjectIdGetDatum(collOid));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for collation %u", collOid);
+
+ collForm = (Form_pg_collation) GETSTRUCT(tup);
+ collversion = SysCacheGetAttr(COLLOID, tup, Anum_pg_collation_collversion,
+ &isnull);
+ oldversion = isnull ? NULL : TextDatumGetCString(collversion);
+
+ newversion = get_collation_actual_version(collForm->collprovider, NameStr(collForm->collcollate));
+
+ /* cannot change from NULL to non-NULL or vice versa */
+ if ((!oldversion && newversion) || (oldversion && !newversion))
+ elog(ERROR, "invalid collation version change");
+ else if (oldversion && newversion && strcmp(newversion, oldversion) != 0)
+ {
+ bool nulls[Natts_pg_collation];
+ bool replaces[Natts_pg_collation];
+ Datum values[Natts_pg_collation];
+
+ ereport(NOTICE,
+ (errmsg("changing version from %s to %s",
+ oldversion, newversion)));
+
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(newversion);
+ replaces[Anum_pg_collation_collversion - 1] = true;
+
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel),
+ values, nulls, replaces);
+ }
+ else
+ ereport(NOTICE,
+ (errmsg("version has not changed")));
+
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ InvokeObjectPostAlterHook(CollationRelationId, collOid, 0);
+
+ ObjectAddressSet(address, CollationRelationId, collOid);
+
+ heap_freetuple(tup);
+ table_close(rel, NoLock);
+
+ return address;
+}
+
+
Datum
pg_collation_actual_version(PG_FUNCTION_ARGS)
{
Oid collid = PG_GETARG_OID(0);
+ HeapTuple tp;
+ char *collcollate;
+ char collprovider;
char *version;
- version = get_collation_version_for_oid(collid, true);
+ tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
+ if (!HeapTupleIsValid(tp))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("collation with OID %u does not exist", collid)));
+
+ collcollate = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collcollate));
+ collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
+
+ ReleaseSysCache(tp);
+
+ version = get_collation_actual_version(collprovider, collcollate);
if (version)
PG_RETURN_TEXT_P(cstring_to_text(version));
@@ -495,6 +594,7 @@ pg_import_system_collations(PG_FUNCTION_ARGS)
collid = CollationCreate(localebuf, nspid, GetUserId(),
COLLPROVIDER_LIBC, true, enc,
localebuf, localebuf,
+ get_collation_actual_version(COLLPROVIDER_LIBC, localebuf),
true, true);
if (OidIsValid(collid))
{
@@ -555,6 +655,7 @@ pg_import_system_collations(PG_FUNCTION_ARGS)
collid = CollationCreate(alias, nspid, GetUserId(),
COLLPROVIDER_LIBC, true, enc,
locale, locale,
+ get_collation_actual_version(COLLPROVIDER_LIBC, locale),
true, true);
if (OidIsValid(collid))
{
@@ -616,6 +717,7 @@ pg_import_system_collations(PG_FUNCTION_ARGS)
nspid, GetUserId(),
COLLPROVIDER_ICU, true, -1,
collcollate, collcollate,
+ get_collation_actual_version(COLLPROVIDER_ICU, collcollate),
true, true);
if (OidIsValid(collid))
{
diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c
index df4768952d..acae19176c 100644
--- a/src/backend/commands/statscmds.c
+++ b/src/backend/commands/statscmds.c
@@ -555,7 +555,7 @@ CreateStatistics(CreateStatsStmt *stmt)
(Node *) stxexprs,
relid,
DEPENDENCY_NORMAL,
- DEPENDENCY_AUTO, false, true);
+ DEPENDENCY_AUTO, false);
/*
* Also add dependencies on namespace and owner. These are required
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 0da61784d7..3b5d411683 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -94,7 +94,6 @@
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/partcache.h"
-#include "utils/pg_locale.h"
#include "utils/relcache.h"
#include "utils/ruleutils.h"
#include "utils/snapmgr.h"
@@ -602,7 +601,6 @@ static void refuseDupeIndexAttach(Relation parentIdx, Relation partIdx,
Relation partitionTbl);
static List *GetParentedForeignKeyRefs(Relation partition);
static void ATDetachCheckNoForeignKeyRefs(Relation partition);
-static void ATExecAlterCollationRefreshVersion(Relation rel, List *coll);
static char GetAttributeCompression(Form_pg_attribute att, char *compression);
@@ -4333,10 +4331,6 @@ AlterTableGetLockLevel(List *cmds)
cmd_lockmode = AccessShareLock;
break;
- case AT_AlterCollationRefreshVersion:
- cmd_lockmode = AccessExclusiveLock;
- break;
-
default: /* oops */
elog(ERROR, "unrecognized alter table type: %d",
(int) cmd->subtype);
@@ -4524,12 +4518,6 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
/* This command never recurses */
pass = AT_PASS_MISC;
break;
- case AT_AlterCollationRefreshVersion: /* ALTER COLLATION ... REFRESH
- * VERSION */
- ATSimplePermissions(rel, ATT_INDEX);
- /* This command never recurses */
- pass = AT_PASS_MISC;
- break;
case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE);
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
@@ -5139,11 +5127,6 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
case AT_DetachPartitionFinalize:
ATExecDetachPartitionFinalize(rel, ((PartitionCmd *) cmd->def)->name);
break;
- case AT_AlterCollationRefreshVersion:
- /* ATPrepCmd ensured it must be an index */
- Assert(rel->rd_rel->relkind == RELKIND_INDEX);
- ATExecAlterCollationRefreshVersion(rel, cmd->object);
- break;
default: /* oops */
elog(ERROR, "unrecognized alter table type: %d",
(int) cmd->subtype);
@@ -18626,20 +18609,6 @@ ATDetachCheckNoForeignKeyRefs(Relation partition)
}
}
-/*
- * ALTER INDEX ... ALTER COLLATION ... REFRESH VERSION
- *
- * Update refobjversion to the current collation version by force. This clears
- * warnings about version mismatches without the need to run REINDEX,
- * potentially hiding corruption due to ordering changes.
- */
-static void
-ATExecAlterCollationRefreshVersion(Relation rel, List *coll)
-{
- index_update_collation_versions(rel->rd_id, get_collation_oid(coll, false));
- CacheInvalidateRelcache(rel);
-}
-
/*
* resolve column compression specification to compression method.
*/
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 632cc31a04..f5a7760740 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3347,7 +3347,6 @@ _copyAlterTableCmd(const AlterTableCmd *from)
COPY_SCALAR_FIELD(subtype);
COPY_STRING_FIELD(name);
- COPY_NODE_FIELD(object);
COPY_SCALAR_FIELD(num);
COPY_NODE_FIELD(newowner);
COPY_NODE_FIELD(def);
@@ -3357,6 +3356,16 @@ _copyAlterTableCmd(const AlterTableCmd *from)
return newnode;
}
+static AlterCollationStmt *
+_copyAlterCollationStmt(const AlterCollationStmt *from)
+{
+ AlterCollationStmt *newnode = makeNode(AlterCollationStmt);
+
+ COPY_NODE_FIELD(collname);
+
+ return newnode;
+}
+
static AlterDomainStmt *
_copyAlterDomainStmt(const AlterDomainStmt *from)
{
@@ -5369,6 +5378,9 @@ copyObjectImpl(const void *from)
case T_AlterTableCmd:
retval = _copyAlterTableCmd(from);
break;
+ case T_AlterCollationStmt:
+ retval = _copyAlterCollationStmt(from);
+ break;
case T_AlterDomainStmt:
retval = _copyAlterDomainStmt(from);
break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index a410a29a17..ce76d093dd 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1140,6 +1140,14 @@ _equalAlterTableCmd(const AlterTableCmd *a, const AlterTableCmd *b)
return true;
}
+static bool
+_equalAlterCollationStmt(const AlterCollationStmt *a, const AlterCollationStmt *b)
+{
+ COMPARE_NODE_FIELD(collname);
+
+ return true;
+}
+
static bool
_equalAlterDomainStmt(const AlterDomainStmt *a, const AlterDomainStmt *b)
{
@@ -3362,6 +3370,9 @@ equal(const void *a, const void *b)
case T_AlterTableCmd:
retval = _equalAlterTableCmd(a, b);
break;
+ case T_AlterCollationStmt:
+ retval = _equalAlterCollationStmt(a, b);
+ break;
case T_AlterDomainStmt:
retval = _equalAlterDomainStmt(a, b);
break;
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 295ce11450..c5194fdbbf 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -27,7 +27,6 @@
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "catalog/heap.h"
-#include "catalog/index.h"
#include "catalog/pg_am.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_statistic_ext.h"
@@ -199,14 +198,6 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
indexRelation = index_open(indexoid, lmode);
index = indexRelation->rd_index;
- /* Warn if any dependent collations' versions have moved. */
- if (!IsSystemRelation(relation) &&
- !indexRelation->rd_version_checked)
- {
- index_check_collation_versions(indexoid);
- indexRelation->rd_version_checked = true;
- }
-
/*
* Ignore invalid indexes, since they can't safely be used for
* queries. Note that this is OK because the data structure we
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index b4ab4014c8..aaf1a51f68 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -263,7 +263,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
}
%type stmt toplevel_stmt schema_stmt routine_body_stmt
- AlterEventTrigStmt
+ AlterEventTrigStmt AlterCollationStmt
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
AlterObjectDependsStmt AlterObjectSchemaStmt AlterOwnerStmt
@@ -902,6 +902,7 @@ toplevel_stmt:
stmt:
AlterEventTrigStmt
+ | AlterCollationStmt
| AlterDatabaseStmt
| AlterDatabaseSetStmt
| AlterDefaultPrivilegesStmt
@@ -2682,14 +2683,6 @@ alter_table_cmd:
n->subtype = AT_NoForceRowSecurity;
$$ = (Node *)n;
}
- /* ALTER INDEX ALTER COLLATION ... REFRESH VERSION */
- | ALTER COLLATION any_name REFRESH VERSION_P
- {
- AlterTableCmd *n = makeNode(AlterTableCmd);
- n->subtype = AT_AlterCollationRefreshVersion;
- n->object = $3;
- $$ = (Node *)n;
- }
| alter_generic_options
{
AlterTableCmd *n = makeNode(AlterTableCmd);
@@ -10377,6 +10370,21 @@ drop_option:
}
;
+/*****************************************************************************
+ *
+ * ALTER COLLATION
+ *
+ *****************************************************************************/
+
+AlterCollationStmt: ALTER COLLATION any_name REFRESH VERSION_P
+ {
+ AlterCollationStmt *n = makeNode(AlterCollationStmt);
+ n->collname = $3;
+ $$ = (Node *)n;
+ }
+ ;
+
+
/*****************************************************************************
*
* ALTER SYSTEM
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 16c6f17e23..1a8fc16773 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1850,6 +1850,10 @@ ProcessUtilitySlow(ParseState *pstate,
address = AlterStatistics((AlterStatsStmt *) parsetree);
break;
+ case T_AlterCollationStmt:
+ address = AlterCollation((AlterCollationStmt *) parsetree);
+ break;
+
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(parsetree));
@@ -3001,6 +3005,10 @@ CreateCommandTag(Node *parsetree)
tag = CMDTAG_DROP_SUBSCRIPTION;
break;
+ case T_AlterCollationStmt:
+ tag = CMDTAG_ALTER_COLLATION;
+ break;
+
case T_PrepareStmt:
tag = CMDTAG_PREPARE;
break;
@@ -3617,6 +3625,10 @@ GetCommandLogLevel(Node *parsetree)
lev = LOGSTMT_DDL;
break;
+ case T_AlterCollationStmt:
+ lev = LOGSTMT_DDL;
+ break;
+
/* already-planned queries */
case T_PlannedStmt:
{
diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c
index aa4874163f..eab089f252 100644
--- a/src/backend/utils/adt/pg_locale.c
+++ b/src/backend/utils/adt/pg_locale.c
@@ -57,9 +57,7 @@
#include "access/htup_details.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_control.h"
-#include "catalog/pg_database.h"
#include "mb/pg_wchar.h"
-#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/formatting.h"
#include "utils/hsearch.h"
@@ -127,9 +125,6 @@ static char *IsoLocaleName(const char *); /* MSVC specific */
static void icu_set_collation_attributes(UCollator *collator, const char *loc);
#endif
-static char *get_collation_actual_version(char collprovider,
- const char *collcollate);
-
/*
* pg_perm_setlocale
*
@@ -1488,10 +1483,12 @@ pg_newlocale_from_collation(Oid collid)
/* We haven't computed this yet in this session, so do it */
HeapTuple tp;
Form_pg_collation collform;
- const char *collcollate pg_attribute_unused();
+ const char *collcollate;
const char *collctype pg_attribute_unused();
struct pg_locale_struct result;
pg_locale_t resultp;
+ Datum collversion;
+ bool isnull;
tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
if (!HeapTupleIsValid(tp))
@@ -1593,6 +1590,41 @@ pg_newlocale_from_collation(Oid collid)
#endif /* not USE_ICU */
}
+ collversion = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
+ &isnull);
+ if (!isnull)
+ {
+ char *actual_versionstr;
+ char *collversionstr;
+
+ actual_versionstr = get_collation_actual_version(collform->collprovider, collcollate);
+ if (!actual_versionstr)
+ {
+ /*
+ * This could happen when specifying a version in CREATE
+ * COLLATION for a libc locale, or manually creating a mess in
+ * the catalogs.
+ */
+ ereport(ERROR,
+ (errmsg("collation \"%s\" has no actual version, but a version was specified",
+ NameStr(collform->collname))));
+ }
+ collversionstr = TextDatumGetCString(collversion);
+
+ if (strcmp(actual_versionstr, collversionstr) != 0)
+ ereport(WARNING,
+ (errmsg("collation \"%s\" has version mismatch",
+ NameStr(collform->collname)),
+ errdetail("The collation in the database was created using version %s, "
+ "but the operating system provides version %s.",
+ collversionstr, actual_versionstr),
+ errhint("Rebuild all objects affected by this collation and run "
+ "ALTER COLLATION %s REFRESH VERSION, "
+ "or build PostgreSQL with the right library version.",
+ quote_qualified_identifier(get_namespace_name(collform->collnamespace),
+ NameStr(collform->collname)))));
+ }
+
ReleaseSysCache(tp);
/* We'll keep the pg_locale_t structures in TopMemoryContext */
@@ -1609,7 +1641,7 @@ pg_newlocale_from_collation(Oid collid)
* Get provider-specific collation version string for the given collation from
* the operating system/library.
*/
-static char *
+char *
get_collation_actual_version(char collprovider, const char *collcollate)
{
char *collversion = NULL;
@@ -1697,49 +1729,6 @@ get_collation_actual_version(char collprovider, const char *collcollate)
return collversion;
}
-/*
- * Get provider-specific collation version string for a given collation OID.
- * Return NULL if the provider doesn't support versions, or the collation is
- * unversioned (for example "C"). Unknown OIDs result in NULL if missing_ok is
- * true.
- */
-char *
-get_collation_version_for_oid(Oid oid, bool missing_ok)
-{
- HeapTuple tp;
- char *version;
-
- if (oid == DEFAULT_COLLATION_OID)
- {
- Form_pg_database dbform;
-
- tp = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
- if (!HeapTupleIsValid(tp))
- elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
- dbform = (Form_pg_database) GETSTRUCT(tp);
- version = get_collation_actual_version(COLLPROVIDER_LIBC,
- NameStr(dbform->datcollate));
- }
- else
- {
- Form_pg_collation collform;
-
- tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(oid));
- if (!HeapTupleIsValid(tp))
- {
- if (missing_ok)
- return NULL;
- elog(ERROR, "cache lookup failed for collation %u", oid);
- }
- collform = (Form_pg_collation) GETSTRUCT(tp);
- version = get_collation_actual_version(collform->collprovider,
- NameStr(collform->collcollate));
- }
-
- ReleaseSysCache(tp);
-
- return version;
-}
#ifdef USE_ICU
/*
diff --git a/src/backend/utils/adt/pg_upgrade_support.c b/src/backend/utils/adt/pg_upgrade_support.c
index a575c95079..b5b46d7231 100644
--- a/src/backend/utils/adt/pg_upgrade_support.c
+++ b/src/backend/utils/adt/pg_upgrade_support.c
@@ -13,7 +13,6 @@
#include "catalog/binary_upgrade.h"
#include "catalog/heap.h"
-#include "catalog/index.h"
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
#include "commands/extension.h"
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 31c8e07f2a..bd88f6105b 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -42,7 +42,6 @@
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/catalog.h"
-#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/partition.h"
@@ -6069,7 +6068,6 @@ load_relcache_init_file(bool shared)
rel->rd_idattr = NULL;
rel->rd_pubactions = NULL;
rel->rd_statvalid = false;
- rel->rd_version_checked = false;
rel->rd_statlist = NIL;
rel->rd_fkeyvalid = false;
rel->rd_fkeylist = NIL;
diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h
index 3bc86635f7..fc054af5ba 100644
--- a/src/bin/pg_dump/pg_backup.h
+++ b/src/bin/pg_dump/pg_backup.h
@@ -180,7 +180,6 @@ typedef struct _dumpOptions
int sequence_data; /* dump sequence data even in schema-only mode */
int do_nothing;
- int coll_unknown;
} DumpOptions;
/*
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 3cb3598f2b..e384690d94 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -46,7 +46,6 @@
#include "catalog/pg_attribute_d.h"
#include "catalog/pg_cast_d.h"
#include "catalog/pg_class_d.h"
-#include "catalog/pg_collation_d.h"
#include "catalog/pg_default_acl_d.h"
#include "catalog/pg_largeobject_d.h"
#include "catalog/pg_largeobject_metadata_d.h"
@@ -296,9 +295,6 @@ static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
static const char *getAttrName(int attrnum, const TableInfo *tblInfo);
static const char *fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer);
static bool nonemptyReloptions(const char *reloptions);
-static void appendIndexCollationVersion(PQExpBuffer buffer, const IndxInfo *indxinfo,
- bool coll_unknown,
- Archive *fout);
static void appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
const char *prefix, Archive *fout);
static char *get_synchronized_snapshot(Archive *fout);
@@ -401,7 +397,6 @@ main(int argc, char **argv)
{"on-conflict-do-nothing", no_argument, &dopt.do_nothing, 1},
{"rows-per-insert", required_argument, NULL, 10},
{"include-foreign-data", required_argument, NULL, 11},
- {"index-collation-versions-unknown", no_argument, &dopt.coll_unknown, 1},
{NULL, 0, NULL, 0}
};
@@ -734,10 +729,6 @@ main(int argc, char **argv)
if (archiveFormat != archDirectory && numWorkers > 1)
fatal("parallel backup only supported by the directory format");
- /* Unknown collation versions only relevant in binary upgrade mode */
- if (dopt.coll_unknown && !dopt.binary_upgrade)
- fatal("option --index-collation-versions-unknown only works in binary upgrade mode");
-
/* Open the output file */
fout = CreateArchive(filename, archiveFormat, compressLevel, dosync,
archiveMode, setupDumpWorker);
@@ -7227,9 +7218,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
i_tablespace,
i_indreloptions,
i_indstatcols,
- i_indstatvals,
- i_inddependcollnames,
- i_inddependcollversions;
+ i_indstatvals;
int ntups;
for (i = 0; i < numTables; i++)
@@ -7265,7 +7254,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
* is not.
*/
resetPQExpBuffer(query);
- if (fout->remoteVersion >= 140000)
+ if (fout->remoteVersion >= 110000)
{
appendPQExpBuffer(query,
"SELECT t.tableoid, t.oid, "
@@ -7290,66 +7279,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
"(SELECT pg_catalog.array_agg(attstattarget ORDER BY attnum) "
" FROM pg_catalog.pg_attribute "
" WHERE attrelid = i.indexrelid AND "
- " attstattarget >= 0) AS indstatvals, "
- "(SELECT pg_catalog.array_agg(quote_ident(ns.nspname) || '.' || quote_ident(c.collname) ORDER BY refobjid) "
- " FROM pg_catalog.pg_depend d "
- " JOIN pg_catalog.pg_collation c ON (c.oid = d.refobjid) "
- " JOIN pg_catalog.pg_namespace ns ON (c.collnamespace = ns.oid) "
- " WHERE d.classid = 'pg_catalog.pg_class'::regclass AND "
- " d.objid = i.indexrelid AND "
- " d.objsubid = 0 AND "
- " d.refclassid = 'pg_catalog.pg_collation'::regclass AND "
- " d.refobjversion IS NOT NULL) AS inddependcollnames, "
- "(SELECT pg_catalog.array_agg(quote_literal(refobjversion) ORDER BY refobjid) "
- " FROM pg_catalog.pg_depend "
- " WHERE classid = 'pg_catalog.pg_class'::regclass AND "
- " objid = i.indexrelid AND "
- " objsubid = 0 AND "
- " refclassid = 'pg_catalog.pg_collation'::regclass AND "
- " refobjversion IS NOT NULL) AS inddependcollversions "
- "FROM pg_catalog.pg_index i "
- "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
- "JOIN pg_catalog.pg_class t2 ON (t2.oid = i.indrelid) "
- "LEFT JOIN pg_catalog.pg_constraint c "
- "ON (i.indrelid = c.conrelid AND "
- "i.indexrelid = c.conindid AND "
- "c.contype IN ('p','u','x')) "
- "LEFT JOIN pg_catalog.pg_inherits inh "
- "ON (inh.inhrelid = indexrelid) "
- "WHERE i.indrelid = '%u'::pg_catalog.oid "
- "AND (i.indisvalid OR t2.relkind = 'p') "
- "AND i.indisready "
- "ORDER BY indexname",
- tbinfo->dobj.catId.oid);
- }
- else if (fout->remoteVersion >= 110000)
- {
- appendPQExpBuffer(query,
- "SELECT t.tableoid, t.oid, "
- "t.relname AS indexname, "
- "inh.inhparent AS parentidx, "
- "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
- "i.indnkeyatts AS indnkeyatts, "
- "i.indnatts AS indnatts, "
- "i.indkey, i.indisclustered, "
- "i.indisreplident, "
- "c.contype, c.conname, "
- "c.condeferrable, c.condeferred, "
- "c.tableoid AS contableoid, "
- "c.oid AS conoid, "
- "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
- "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
- "t.reloptions AS indreloptions, "
- "(SELECT pg_catalog.array_agg(attnum ORDER BY attnum) "
- " FROM pg_catalog.pg_attribute "
- " WHERE attrelid = i.indexrelid AND "
- " attstattarget >= 0) AS indstatcols,"
- "(SELECT pg_catalog.array_agg(attstattarget ORDER BY attnum) "
- " FROM pg_catalog.pg_attribute "
- " WHERE attrelid = i.indexrelid AND "
- " attstattarget >= 0) AS indstatvals, "
- "'{}' AS inddependcollnames, "
- "'{}' AS inddependcollversions "
+ " attstattarget >= 0) AS indstatvals "
"FROM pg_catalog.pg_index i "
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
"JOIN pg_catalog.pg_class t2 ON (t2.oid = i.indrelid) "
@@ -7388,9 +7318,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
"t.reloptions AS indreloptions, "
"'' AS indstatcols, "
- "'' AS indstatvals, "
- "'{}' AS inddependcollnames, "
- "'{}' AS inddependcollversions "
+ "'' AS indstatvals "
"FROM pg_catalog.pg_index i "
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
"LEFT JOIN pg_catalog.pg_constraint c "
@@ -7425,9 +7353,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
"t.reloptions AS indreloptions, "
"'' AS indstatcols, "
- "'' AS indstatvals, "
- "'{}' AS inddependcollnames, "
- "'{}' AS inddependcollversions "
+ "'' AS indstatvals "
"FROM pg_catalog.pg_index i "
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
"LEFT JOIN pg_catalog.pg_constraint c "
@@ -7458,9 +7384,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
"t.reloptions AS indreloptions, "
"'' AS indstatcols, "
- "'' AS indstatvals, "
- "'{}' AS inddependcollnames, "
- "'{}' AS inddependcollversions "
+ "'' AS indstatvals "
"FROM pg_catalog.pg_index i "
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
"LEFT JOIN pg_catalog.pg_depend d "
@@ -7494,9 +7418,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
"null AS indreloptions, "
"'' AS indstatcols, "
- "'' AS indstatvals, "
- "'{}' AS inddependcollnames, "
- "'{}' AS inddependcollversions "
+ "'' AS indstatvals "
"FROM pg_catalog.pg_index i "
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
"LEFT JOIN pg_catalog.pg_depend d "
@@ -7536,8 +7458,6 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
i_indreloptions = PQfnumber(res, "indreloptions");
i_indstatcols = PQfnumber(res, "indstatcols");
i_indstatvals = PQfnumber(res, "indstatvals");
- i_inddependcollnames = PQfnumber(res, "inddependcollnames");
- i_inddependcollversions = PQfnumber(res, "inddependcollversions");
tbinfo->indexes = indxinfo =
(IndxInfo *) pg_malloc(ntups * sizeof(IndxInfo));
@@ -7563,8 +7483,6 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
indxinfo[j].indreloptions = pg_strdup(PQgetvalue(res, j, i_indreloptions));
indxinfo[j].indstatcols = pg_strdup(PQgetvalue(res, j, i_indstatcols));
indxinfo[j].indstatvals = pg_strdup(PQgetvalue(res, j, i_indstatvals));
- indxinfo[j].inddependcollnames = pg_strdup(PQgetvalue(res, j, i_inddependcollnames));
- indxinfo[j].inddependcollversions = pg_strdup(PQgetvalue(res, j, i_inddependcollversions));
indxinfo[j].indkeys = (Oid *) pg_malloc(indxinfo[j].indnattrs * sizeof(Oid));
parseOidArray(PQgetvalue(res, j, i_indkey),
indxinfo[j].indkeys, indxinfo[j].indnattrs);
@@ -13933,10 +13851,12 @@ dumpCollation(Archive *fout, const CollInfo *collinfo)
if (fout->remoteVersion >= 100000)
appendPQExpBufferStr(query,
- "collprovider, ");
+ "collprovider, "
+ "collversion, ");
else
appendPQExpBufferStr(query,
- "'c' AS collprovider, ");
+ "'c' AS collprovider, "
+ "NULL AS collversion, ");
if (fout->remoteVersion >= 120000)
appendPQExpBufferStr(query,
@@ -13997,6 +13917,24 @@ dumpCollation(Archive *fout, const CollInfo *collinfo)
appendStringLiteralAH(q, collctype, fout);
}
+ /*
+ * For binary upgrade, carry over the collation version. For normal
+ * dump/restore, omit the version, so that it is computed upon restore.
+ */
+ if (dopt->binary_upgrade)
+ {
+ int i_collversion;
+
+ i_collversion = PQfnumber(res, "collversion");
+ if (!PQgetisnull(res, 0, i_collversion))
+ {
+ appendPQExpBufferStr(q, ", version = ");
+ appendStringLiteralAH(q,
+ PQgetvalue(res, 0, i_collversion),
+ fout);
+ }
+ }
+
appendPQExpBufferStr(q, ");\n");
if (dopt->binary_upgrade)
@@ -16770,8 +16708,7 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo)
/*
* If there's an associated constraint, don't dump the index per se, but
- * do dump any comment, or in binary upgrade mode dependency on a
- * collation version for it. (This is safe because dependency ordering
+ * do dump any comment for it. (This is safe because dependency ordering
* will have ensured the constraint is emitted first.) Note that the
* emitted comment has to be shown as depending on the constraint, not the
* index, in such cases.
@@ -16843,9 +16780,6 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo)
"pg_catalog.pg_class",
"INDEX", qqindxname);
- if (dopt->binary_upgrade)
- appendIndexCollationVersion(q, indxinfo, dopt->coll_unknown, fout);
-
/* If the index defines identity, we need to record that. */
if (indxinfo->indisreplident)
{
@@ -16874,20 +16808,6 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo)
if (indstatvalsarray)
free(indstatvalsarray);
}
- else if (dopt->binary_upgrade)
- {
- appendIndexCollationVersion(q, indxinfo, dopt->coll_unknown, fout);
-
- if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
- ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
- ARCHIVE_OPTS(.tag = indxinfo->dobj.name,
- .namespace = tbinfo->dobj.namespace->dobj.name,
- .tablespace = indxinfo->tablespace,
- .owner = tbinfo->rolname,
- .description = "INDEX",
- .section = SECTION_POST_DATA,
- .createStmt = q->data));
- }
/* Dump Index Comments */
if (indxinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -18896,82 +18816,6 @@ nonemptyReloptions(const char *reloptions)
return (reloptions != NULL && strlen(reloptions) > 2);
}
-/*
- * Generate UPDATE statements to import the collation versions into the new
- * cluster, during a binary upgrade.
- */
-static void
-appendIndexCollationVersion(PQExpBuffer buffer, const IndxInfo *indxinfo,
- bool coll_unknown, Archive *fout)
-{
- char *inddependcollnames = indxinfo->inddependcollnames;
- char *inddependcollversions = indxinfo->inddependcollversions;
- char **inddependcollnamesarray;
- char **inddependcollversionsarray;
- int ninddependcollnames;
- int ninddependcollversions;
-
- /*
- * By default, the new cluster's index will have pg_depends rows with
- * current collation versions, meaning that we assume the index isn't
- * corrupted if importing from a release that didn't record versions.
- * However, if --index-collation-versions-unknown was passed in, then we
- * assume such indexes might be corrupted, and clobber versions with
- * 'unknown' to trigger version warnings.
- */
- if (coll_unknown)
- {
- appendPQExpBuffer(buffer,
- "\n-- For binary upgrade, clobber new index's collation versions\n");
- appendPQExpBuffer(buffer,
- "UPDATE pg_catalog.pg_depend SET refobjversion = 'unknown' WHERE objid = '%u'::pg_catalog.oid AND refclassid = 'pg_catalog.pg_collation'::regclass AND refobjversion IS NOT NULL;\n",
- indxinfo->dobj.catId.oid);
- }
-
- /* Restore the versions that were recorded by the old cluster (if any). */
- if (strlen(inddependcollnames) == 0 && strlen(inddependcollversions) == 0)
- {
- ninddependcollnames = ninddependcollversions = 0;
- inddependcollnamesarray = inddependcollversionsarray = NULL;
- }
- else
- {
- if (!parsePGArray(inddependcollnames,
- &inddependcollnamesarray,
- &ninddependcollnames))
- fatal("could not parse index collation name array");
- if (!parsePGArray(inddependcollversions,
- &inddependcollversionsarray,
- &ninddependcollversions))
- fatal("could not parse index collation version array");
- }
-
- if (ninddependcollnames != ninddependcollversions)
- fatal("mismatched number of collation names and versions for index");
-
- if (ninddependcollnames > 0)
- appendPQExpBufferStr(buffer,
- "\n-- For binary upgrade, restore old index's collation versions\n");
- for (int i = 0; i < ninddependcollnames; i++)
- {
- /*
- * Import refobjversion from the old cluster, being careful to resolve
- * the collation OID by name in the new cluster.
- */
- appendPQExpBuffer(buffer,
- "UPDATE pg_catalog.pg_depend SET refobjversion = %s WHERE objid = '%u'::pg_catalog.oid AND refclassid = 'pg_catalog.pg_collation'::regclass AND refobjversion IS NOT NULL AND refobjid = ",
- inddependcollversionsarray[i],
- indxinfo->dobj.catId.oid);
- appendStringLiteralAH(buffer, inddependcollnamesarray[i], fout);
- appendPQExpBuffer(buffer, "::regcollation;\n");
- }
-
- if (inddependcollnamesarray)
- free(inddependcollnamesarray);
- if (inddependcollversionsarray)
- free(inddependcollversionsarray);
-}
-
/*
* Format a reloptions array and append it to the given buffer.
*
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 5340843081..49e1b0a09c 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -376,8 +376,6 @@ typedef struct _indxInfo
int indnattrs; /* total number of index attributes */
Oid *indkeys; /* In spite of the name 'indkeys' this field
* contains both key and nonkey attributes */
- char *inddependcollnames; /* FQ names of depended-on collations */
- char *inddependcollversions; /* versions of the above */
bool indisclustered;
bool indisreplident;
Oid parentidx; /* if a partition, parent index OID */
diff --git a/src/bin/pg_upgrade/dump.c b/src/bin/pg_upgrade/dump.c
index 33d9591f37..90060d0f8e 100644
--- a/src/bin/pg_upgrade/dump.c
+++ b/src/bin/pg_upgrade/dump.c
@@ -52,11 +52,9 @@ generate_old_dump(void)
parallel_exec_prog(log_file_name, NULL,
"\"%s/pg_dump\" %s --schema-only --quote-all-identifiers "
- "--binary-upgrade --format=custom %s %s --file=\"%s\" %s",
+ "--binary-upgrade --format=custom %s --file=\"%s\" %s",
new_cluster.bindir, cluster_conn_opts(&old_cluster),
log_opts.verbose ? "--verbose" : "",
- user_opts.ind_coll_unknown ?
- "--index-collation-versions-unknown" : "",
sql_file_name, escaped_connstr.data);
termPQExpBuffer(&escaped_connstr);
diff --git a/src/bin/pg_upgrade/option.c b/src/bin/pg_upgrade/option.c
index 4b74f9eea7..64bbda5650 100644
--- a/src/bin/pg_upgrade/option.c
+++ b/src/bin/pg_upgrade/option.c
@@ -56,7 +56,6 @@ parseCommandLine(int argc, char *argv[])
{"socketdir", required_argument, NULL, 's'},
{"verbose", no_argument, NULL, 'v'},
{"clone", no_argument, NULL, 1},
- {"index-collation-versions-unknown", no_argument, NULL, 2},
{NULL, 0, NULL, 0}
};
@@ -204,10 +203,6 @@ parseCommandLine(int argc, char *argv[])
user_opts.transfer_mode = TRANSFER_MODE_CLONE;
break;
- case 2:
- user_opts.ind_coll_unknown = true;
- break;
-
default:
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
os_info.progname);
@@ -312,8 +307,6 @@ usage(void)
printf(_(" -v, --verbose enable verbose internal logging\n"));
printf(_(" -V, --version display version information, then exit\n"));
printf(_(" --clone clone instead of copying files to new cluster\n"));
- printf(_(" --index-collation-versions-unknown\n"
- " mark text indexes as needing to be rebuilt\n"));
printf(_(" -?, --help show this help, then exit\n"));
printf(_("\n"
"Before running pg_upgrade you must:\n"
diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h
index d7666da3f2..a5f71c5294 100644
--- a/src/bin/pg_upgrade/pg_upgrade.h
+++ b/src/bin/pg_upgrade/pg_upgrade.h
@@ -292,7 +292,6 @@ typedef struct
transferMode transfer_mode; /* copy files or link them? */
int jobs; /* number of processes/threads to use */
char *socketdir; /* directory to use for Unix sockets */
- bool ind_coll_unknown; /* mark unknown index collation versions */
} UserOpts;
typedef struct
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 7c4933333b..d917987fd5 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -45,7 +45,6 @@
#include "catalog/pg_am_d.h"
#include "catalog/pg_class_d.h"
-#include "catalog/pg_collation_d.h"
#include "common.h"
#include "libpq-fe.h"
#include "pqexpbuffer.h"
@@ -842,20 +841,6 @@ static const SchemaQuery Query_for_list_of_collations = {
" (SELECT tgrelid FROM pg_catalog.pg_trigger "\
" WHERE pg_catalog.quote_ident(tgname)='%s')"
-/* the silly-looking length condition is just to eat up the current word */
-#define Query_for_list_of_colls_for_one_index \
-" SELECT DISTINCT pg_catalog.quote_ident(coll.collname) " \
-" FROM pg_catalog.pg_depend d, pg_catalog.pg_collation coll, " \
-" pg_catalog.pg_class c" \
-" WHERE (%d = pg_catalog.length('%s'))" \
-" AND d.refclassid = " CppAsString2(CollationRelationId) \
-" AND d.refobjid = coll.oid " \
-" AND d.classid = " CppAsString2(RelationRelationId) \
-" AND d.objid = c.oid " \
-" AND c.relkind = " CppAsString2(RELKIND_INDEX) \
-" AND pg_catalog.pg_table_is_visible(c.oid) " \
-" AND c.relname = '%s'"
-
#define Query_for_list_of_ts_configurations \
"SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\
" WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'"
@@ -1769,15 +1754,14 @@ psql_completion(const char *text, int start, int end)
else if (Matches("ALTER", "INDEX", MatchAny))
COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET",
"RESET", "ATTACH PARTITION",
- "DEPENDS ON EXTENSION", "NO DEPENDS ON EXTENSION",
- "ALTER COLLATION");
+ "DEPENDS ON EXTENSION", "NO DEPENDS ON EXTENSION");
else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH"))
COMPLETE_WITH("PARTITION");
else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH", "PARTITION"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
/* ALTER INDEX ALTER */
else if (Matches("ALTER", "INDEX", MatchAny, "ALTER"))
- COMPLETE_WITH("COLLATION", "COLUMN");
+ COMPLETE_WITH("COLUMN");
/* ALTER INDEX ALTER COLUMN */
else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN"))
{
@@ -1816,15 +1800,10 @@ psql_completion(const char *text, int start, int end)
"buffering =", /* GiST */
"pages_per_range =", "autosummarize =" /* BRIN */
);
- /* ALTER INDEX ALTER COLLATION */
- else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLLATION"))
- {
- completion_info_charp = prev3_wd;
- COMPLETE_WITH_QUERY(Query_for_list_of_colls_for_one_index);
- }
- /* ALTER INDEX ALTER COLLATION */
- else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLLATION", MatchAny))
- COMPLETE_WITH("REFRESH VERSION");
+ else if (Matches("ALTER", "INDEX", MatchAny, "NO", "DEPENDS"))
+ COMPLETE_WITH("ON EXTENSION");
+ else if (Matches("ALTER", "INDEX", MatchAny, "DEPENDS"))
+ COMPLETE_WITH("ON EXTENSION");
/* ALTER LANGUAGE */
else if (Matches("ALTER", "LANGUAGE", MatchAny))
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 22dcd0a270..a54be88d7f 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202104271
+#define CATALOG_VERSION_NO 202105051
#endif
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index f272e2c99f..fd44081e74 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -167,8 +167,7 @@ extern void recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
Node *expr, Oid relId,
DependencyType behavior,
DependencyType self_behavior,
- bool reverse_self,
- bool record_version);
+ bool reverse_self);
extern ObjectClass getObjectClass(const ObjectAddress *object);
@@ -188,30 +187,16 @@ extern void sort_object_addresses(ObjectAddresses *addrs);
extern void free_object_addresses(ObjectAddresses *addrs);
-typedef bool(*VisitDependenciesOfCB) (const ObjectAddress *otherObject,
- const char *version,
- char **new_version,
- void *data);
-
-extern void visitDependenciesOf(const ObjectAddress *object,
- VisitDependenciesOfCB callback,
- void *data);
-
/* in pg_depend.c */
extern void recordDependencyOn(const ObjectAddress *depender,
const ObjectAddress *referenced,
DependencyType behavior);
-extern void recordDependencyOnCollations(ObjectAddress *myself,
- List *collations,
- bool record_version);
-
extern void recordMultipleDependencies(const ObjectAddress *depender,
const ObjectAddress *referenced,
int nreferenced,
- DependencyType behavior,
- bool record_version);
+ DependencyType behavior);
extern void recordDependencyOnCurrentExtension(const ObjectAddress *object,
bool isReplace);
@@ -232,6 +217,7 @@ extern long changeDependencyFor(Oid classId, Oid objectId,
extern long changeDependenciesOf(Oid classId, Oid oldObjectId,
Oid newObjectId);
+
extern long changeDependenciesOn(Oid refClassId, Oid oldRefObjectId,
Oid newRefObjectId);
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index e22d506436..008f723e10 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -136,9 +136,6 @@ extern void FormIndexDatum(IndexInfo *indexInfo,
Datum *values,
bool *isnull);
-extern void index_check_collation_versions(Oid relid);
-extern void index_update_collation_versions(Oid relid, Oid coll);
-
extern void index_build(Relation heapRelation,
Relation indexRelation,
IndexInfo *indexInfo,
diff --git a/src/include/catalog/pg_collation.h b/src/include/catalog/pg_collation.h
index c6394ca222..52bfd2cb7b 100644
--- a/src/include/catalog/pg_collation.h
+++ b/src/include/catalog/pg_collation.h
@@ -41,6 +41,11 @@ CATALOG(pg_collation,3456,CollationRelationId)
int32 collencoding; /* encoding for this collation; -1 = "all" */
NameData collcollate; /* LC_COLLATE setting */
NameData collctype; /* LC_CTYPE setting */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ text collversion BKI_DEFAULT(_null_); /* provider-dependent */
+ /* version of */
+ /* collation data */
+#endif
} FormData_pg_collation;
/* ----------------
@@ -50,6 +55,8 @@ CATALOG(pg_collation,3456,CollationRelationId)
*/
typedef FormData_pg_collation *Form_pg_collation;
+DECLARE_TOAST(pg_collation, 8888, 8889);
+
DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, on pg_collation using btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops));
#define CollationNameEncNspIndexId 3164
DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, on pg_collation using btree(oid oid_ops));
@@ -70,6 +77,7 @@ extern Oid CollationCreate(const char *collname, Oid collnamespace,
bool collisdeterministic,
int32 collencoding,
const char *collcollate, const char *collctype,
+ const char *collversion,
bool if_not_exists,
bool quiet);
diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h
index 606a2a8e19..e0bc114145 100644
--- a/src/include/catalog/pg_depend.h
+++ b/src/include/catalog/pg_depend.h
@@ -63,9 +63,6 @@ CATALOG(pg_depend,2608,DependRelationId)
* field. See DependencyType in catalog/dependency.h.
*/
char deptype; /* see codes in dependency.h */
-#ifdef CATALOG_VARLEN
- text refobjversion; /* version of referenced object */
-#endif
} FormData_pg_depend;
/* ----------------
@@ -75,8 +72,6 @@ CATALOG(pg_depend,2608,DependRelationId)
*/
typedef FormData_pg_depend *Form_pg_depend;
-DECLARE_TOAST(pg_depend, 8888, 8889);
-
DECLARE_INDEX(pg_depend_depender_index, 2673, on pg_depend using btree(classid oid_ops, objid oid_ops, objsubid int4_ops));
#define DependDependerIndexId 2673
DECLARE_INDEX(pg_depend_reference_index, 2674, on pg_depend using btree(refclassid oid_ops, refobjid oid_ops, refobjsubid int4_ops));
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 8ee5fa0507..33557760e1 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -390,8 +390,6 @@ extern void GenerateTypeDependencies(HeapTuple typeTuple,
bool isDependentType,
bool rebuild);
-extern List *GetTypeCollations(Oid typeObjectid);
-
extern void RenameTypeInternal(Oid typeOid, const char *newTypeName,
Oid typeNamespace);
diff --git a/src/include/commands/collationcmds.h b/src/include/commands/collationcmds.h
index 4e69045880..e49a5db0fb 100644
--- a/src/include/commands/collationcmds.h
+++ b/src/include/commands/collationcmds.h
@@ -20,5 +20,6 @@
extern ObjectAddress DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists);
extern void IsThereCollationInNamespace(const char *collname, Oid nspOid);
+extern ObjectAddress AlterCollation(AlterCollationStmt *stmt);
#endif /* COLLATIONCMDS_H */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 615dfa26aa..fea3123251 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1933,7 +1933,6 @@ typedef enum AlterTableType
AT_AddIdentity, /* ADD IDENTITY */
AT_SetIdentity, /* SET identity column options */
AT_DropIdentity, /* DROP IDENTITY */
- AT_AlterCollationRefreshVersion, /* ALTER COLLATION ... REFRESH VERSION */
AT_ReAddStatistics /* internal to commands/tablecmds.c */
} AlterTableType;
@@ -1950,7 +1949,6 @@ typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */
AlterTableType subtype; /* Type of table alteration to apply */
char *name; /* column, constraint, or trigger to act on,
* or tablespace */
- List *object; /* collation to act on if it's a collation */
int16 num; /* attribute number for columns referenced by
* number */
RoleSpec *newowner;
@@ -1961,6 +1959,17 @@ typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */
} AlterTableCmd;
+/* ----------------------
+ * Alter Collation
+ * ----------------------
+ */
+typedef struct AlterCollationStmt
+{
+ NodeTag type;
+ List *collname;
+} AlterCollationStmt;
+
+
/* ----------------------
* Alter Domain
*
diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h
index 5a37caefbe..2946f46c76 100644
--- a/src/include/utils/pg_locale.h
+++ b/src/include/utils/pg_locale.h
@@ -103,7 +103,7 @@ typedef struct pg_locale_struct *pg_locale_t;
extern pg_locale_t pg_newlocale_from_collation(Oid collid);
-extern char *get_collation_version_for_oid(Oid collid, bool missing_ok);
+extern char *get_collation_actual_version(char collprovider, const char *collcollate);
#ifdef USE_ICU
extern int32_t icu_to_uchar(UChar **buff_uchar, const char *buff, size_t nbytes);
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 5bd44be9a7..774ac5b2b1 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -63,7 +63,6 @@ typedef struct RelationData
bool rd_indexvalid; /* is rd_indexlist valid? (also rd_pkindex and
* rd_replidindex) */
bool rd_statvalid; /* is rd_statlist valid? */
- bool rd_version_checked; /* has version check been done yet? */
/*----------
* rd_createSubid is the ID of the highest subtransaction the rel has
diff --git a/src/test/Makefile b/src/test/Makefile
index f7859c2fd5..46275915ff 100644
--- a/src/test/Makefile
+++ b/src/test/Makefile
@@ -12,8 +12,7 @@ subdir = src/test
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
-SUBDIRS = perl regress isolation modules authentication recovery subscription \
- locale
+SUBDIRS = perl regress isolation modules authentication recovery subscription
# Test suites that are not safe by default but can be run if selected
# by the user via the whitespace-separated list in variable
diff --git a/src/test/locale/.gitignore b/src/test/locale/.gitignore
index 64e1bf2a80..620d3df425 100644
--- a/src/test/locale/.gitignore
+++ b/src/test/locale/.gitignore
@@ -1,2 +1 @@
/test-ctype
-/tmp_check/
diff --git a/src/test/locale/Makefile b/src/test/locale/Makefile
index 673e14dcd0..7ba096b542 100644
--- a/src/test/locale/Makefile
+++ b/src/test/locale/Makefile
@@ -4,7 +4,6 @@ subdir = src/test/locale
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
-export with_icu
PROGS = test-ctype
DIRS = de_DE.ISO8859-1 gr_GR.ISO8859-7 koi8-r koi8-to-win1251
@@ -21,9 +20,3 @@ clean distclean maintainer-clean:
# These behave like installcheck targets.
check-%: all
@$(MAKE) -C `echo $@ | sed 's/^check-//'` test
-
-check:
- $(prove_check)
-
-installcheck:
- $(prove_installcheck)
diff --git a/src/test/locale/t/001_index.pl b/src/test/locale/t/001_index.pl
deleted file mode 100644
index a67f78cb71..0000000000
--- a/src/test/locale/t/001_index.pl
+++ /dev/null
@@ -1,67 +0,0 @@
-use strict;
-use warnings;
-
-use Config;
-use PostgresNode;
-use TestLib;
-use Test::More;
-
-if ($ENV{with_icu} eq 'yes')
-{
- plan tests => 10;
-}
-else
-{
- plan skip_all => 'ICU not supported by this build';
-}
-
-#### Set up the server
-
-note "setting up data directory";
-my $node = get_new_node('main');
-$node->init(extra => [ '--encoding=UTF8' ]);
-
-$ENV{PGHOST} = $node->host;
-$ENV{PGPORT} = $node->port;
-$node->start;
-
-sub test_index
-{
- my ($err_like, $err_comm) = @_;
- my ($ret, $out, $err) = $node->psql('postgres', "SELECT * FROM icu1");
- is($ret, 0, 'SELECT should succeed.');
- like($err, $err_like, $err_comm);
-}
-
-$node->safe_psql('postgres', 'CREATE TABLE icu1(val text);');
-$node->safe_psql('postgres', 'CREATE INDEX icu1_fr ON icu1 (val COLLATE "fr-x-icu");');
-
-test_index(qr/^$/, 'No warning should be raised');
-
-# Simulate different collation version
-$node->safe_psql('postgres',
- "UPDATE pg_depend SET refobjversion = 'not_a_version'"
- . " WHERE refobjversion IS NOT NULL"
- . " AND objid::regclass::text = 'icu1_fr';");
-
-test_index(qr/index "icu1_fr" depends on collation "fr-x-icu" version "not_a_version", but the current version is/,
- 'Different collation version warning should be raised.');
-
-$node->safe_psql('postgres', 'ALTER INDEX icu1_fr ALTER COLLATION "fr-x-icu" REFRESH VERSION;');
-
-test_index(qr/^$/, 'No warning should be raised');
-
-# Simulate different collation version
-$node->safe_psql('postgres',
- "UPDATE pg_depend SET refobjversion = 'not_a_version'"
- . " WHERE refobjversion IS NOT NULL"
- . " AND objid::regclass::text = 'icu1_fr';");
-
-test_index(qr/index "icu1_fr" depends on collation "fr-x-icu" version "not_a_version", but the current version is/,
- 'Different collation version warning should be raised.');
-
-$node->safe_psql('postgres', 'REINDEX TABLE icu1;');
-
-test_index(qr/^$/, 'No warning should be raised');
-
-$node->stop;
diff --git a/src/test/regress/expected/collate.icu.utf8.out b/src/test/regress/expected/collate.icu.utf8.out
index faf99f76b5..70133df804 100644
--- a/src/test/regress/expected/collate.icu.utf8.out
+++ b/src/test/regress/expected/collate.icu.utf8.out
@@ -1082,6 +1082,9 @@ SELECT collname FROM pg_collation WHERE collname LIKE 'test%';
DROP SCHEMA test_schema;
DROP ROLE regress_test_role;
+-- ALTER
+ALTER COLLATION "en-x-icu" REFRESH VERSION;
+NOTICE: version has not changed
-- dependencies
CREATE COLLATION test0 FROM "C";
CREATE TABLE collate_dep_test1 (a int, b text COLLATE test0);
@@ -1947,184 +1950,6 @@ SELECT (SELECT count(*) FROM test33_0) <> (SELECT count(*) FROM test33_1);
t
(1 row)
--- collation versioning support
-CREATE TYPE t_en_fr AS (fr text COLLATE "fr-x-icu", en text COLLATE "en-x-icu");
-CREATE DOMAIN d_en_fr AS t_en_fr;
-CREATE DOMAIN d_es AS text COLLATE "es-x-icu";
-CREATE TYPE t_en_fr_ga AS (en_fr t_en_fr, ga text COLLATE "ga-x-icu");
-CREATE DOMAIN d_en_fr_ga AS t_en_fr_ga;
-CREATE TYPE t_custom AS (meh text, meh2 text);
-CREATE DOMAIN d_custom AS t_custom;
-CREATE COLLATION custom (
- LOCALE = 'fr-x-icu', PROVIDER = 'icu'
-);
-CREATE TYPE myrange AS range (subtype = text, collation = "POSIX");
-CREATE TYPE myrange_en_fr_ga AS range(subtype = t_en_fr_ga);
-CREATE TABLE collate_test (
- id integer,
- val text COLLATE "fr-x-icu",
- t_en_fr t_en_fr,
- d_en_fr d_en_fr,
- d_es d_es,
- t_en_fr_ga t_en_fr_ga,
- d_en_fr_ga d_en_fr_ga,
- d_en_fr_ga_arr d_en_fr_ga[],
- myrange myrange,
- myrange_en_fr_ga myrange_en_fr_ga
-);
-CREATE INDEX icuidx00_val ON collate_test(val);
--- shouldn't get duplicated dependencies
-CREATE INDEX icuidx00_val_val ON collate_test(val, val);
--- shouldn't track version
-CREATE INDEX icuidx00_val_pattern ON collate_test(val text_pattern_ops);
--- should have single dependency, no version
-CREATE INDEX icuidx00_val_pattern_val_pattern ON collate_test(val text_pattern_ops, val text_pattern_ops);
--- should have single dependency, with version
-CREATE INDEX icuidx00_val_pattern_val ON collate_test(val text_pattern_ops, val);
--- should have single dependency, with version
-CREATE INDEX icuidx00_val_val_pattern ON collate_test(val, val text_pattern_ops);
--- two rows expected, only one a version, because we don't try to merge these yet
-CREATE INDEX icuidx00_val_pattern_where ON collate_test(val text_pattern_ops) WHERE val >= val;
--- two rows expected with version, because we don't try to merge these yet
-CREATE INDEX icuidx00_val_where ON collate_test(val) WHERE val >= val;
--- two rows expected with version (expression walker + attribute)
-CREATE INDEX icuidx00_val_pattern_expr ON collate_test(val varchar_pattern_ops, (val || val));
--- two rows expected, one with a version (expression walker + attribute)
-CREATE INDEX icuidx00_val_pattern_expr_pattern ON collate_test(val varchar_pattern_ops, (val || val) text_pattern_ops);
--- should have single dependency, with version tracked
-CREATE INDEX icuidx01_t_en_fr__d_es ON collate_test (t_en_fr, d_es);
-CREATE INDEX icuidx02_d_en_fr ON collate_test (d_en_fr);
-CREATE INDEX icuidx03_t_en_fr_ga ON collate_test (t_en_fr_ga);
-CREATE INDEX icuidx04_d_en_fr_ga ON collate_test (d_en_fr_ga);
-CREATE INDEX icuidx05_d_en_fr_ga_arr ON collate_test (d_en_fr_ga_arr);
-CREATE INDEX icuidx06_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga).en_fr.fr = 'foo';
-CREATE INDEX icuidx07_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga).ga = 'foo';
-CREATE INDEX icuidx08_d_en_fr_ga ON collate_test(id) WHERE (t_en_fr_ga) = ('foo', 'bar', 'baz');
-CREATE INDEX icuidx09_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga) = ('foo', 'bar', 'baz');
-CREATE INDEX icuidx10_d_en_fr_ga_es ON collate_test(id) WHERE (d_en_fr_ga) = ('foo', 'bar', 'baz' COLLATE "es-x-icu");
-CREATE INDEX icuidx11_d_es ON collate_test(id) WHERE (d_es) = ('foo');
-CREATE INDEX icuidx12_custom ON collate_test(id) WHERE ('foo', 'bar')::d_custom = ('foo', 'bar' COLLATE custom)::d_custom;
-CREATE INDEX icuidx13_custom ON collate_test(id) WHERE ('foo' COLLATE custom, 'bar')::d_custom = ('foo', 'bar')::d_custom;
-CREATE INDEX icuidx14_myrange ON collate_test(myrange);
-CREATE INDEX icuidx15_myrange_en_fr_ga ON collate_test USING gist (myrange_en_fr_ga);
-CREATE TABLE collate_part(id integer, val text COLLATE "en-x-icu") PARTITION BY range(id);
-CREATE TABLE collate_part_0 PARTITION OF collate_part FOR VALUES FROM (0) TO (1);
-CREATE TABLE collate_part_1 PARTITION OF collate_part FOR VALUES FROM (1) TO (1000000);
-CREATE INDEX icuidx17_part ON collate_part_1 (val);
-SELECT objid::regclass::text collate "C", refobjid::regcollation::text collate "C",
-CASE
-WHEN refobjid = 'default'::regcollation THEN 'XXX' -- depends on libc version support
-WHEN refobjversion IS NULL THEN 'version not tracked'
-WHEN refobjversion = pg_collation_actual_version(refobjid) THEN 'up to date'
-ELSE 'out of date'
-END AS version
-FROM pg_depend d
-LEFT JOIN pg_class c ON c.oid = d.objid
-WHERE refclassid = 'pg_collation'::regclass
-AND coalesce(relkind, 'i') = 'i'
-AND relname LIKE 'icuidx%'
-ORDER BY 1, 2, 3;
- objid | refobjid | version
------------------------------------+------------+---------------------
- icuidx00_val | "fr-x-icu" | up to date
- icuidx00_val_pattern | "fr-x-icu" | version not tracked
- icuidx00_val_pattern_expr | "fr-x-icu" | up to date
- icuidx00_val_pattern_expr | "fr-x-icu" | up to date
- icuidx00_val_pattern_expr_pattern | "fr-x-icu" | up to date
- icuidx00_val_pattern_expr_pattern | "fr-x-icu" | version not tracked
- icuidx00_val_pattern_val | "fr-x-icu" | up to date
- icuidx00_val_pattern_val_pattern | "fr-x-icu" | version not tracked
- icuidx00_val_pattern_where | "fr-x-icu" | up to date
- icuidx00_val_pattern_where | "fr-x-icu" | version not tracked
- icuidx00_val_val | "fr-x-icu" | up to date
- icuidx00_val_val_pattern | "fr-x-icu" | up to date
- icuidx00_val_where | "fr-x-icu" | up to date
- icuidx00_val_where | "fr-x-icu" | up to date
- icuidx01_t_en_fr__d_es | "en-x-icu" | up to date
- icuidx01_t_en_fr__d_es | "es-x-icu" | up to date
- icuidx01_t_en_fr__d_es | "fr-x-icu" | up to date
- icuidx02_d_en_fr | "en-x-icu" | up to date
- icuidx02_d_en_fr | "fr-x-icu" | up to date
- icuidx03_t_en_fr_ga | "en-x-icu" | up to date
- icuidx03_t_en_fr_ga | "fr-x-icu" | up to date
- icuidx03_t_en_fr_ga | "ga-x-icu" | up to date
- icuidx04_d_en_fr_ga | "en-x-icu" | up to date
- icuidx04_d_en_fr_ga | "fr-x-icu" | up to date
- icuidx04_d_en_fr_ga | "ga-x-icu" | up to date
- icuidx05_d_en_fr_ga_arr | "en-x-icu" | up to date
- icuidx05_d_en_fr_ga_arr | "fr-x-icu" | up to date
- icuidx05_d_en_fr_ga_arr | "ga-x-icu" | up to date
- icuidx06_d_en_fr_ga | "fr-x-icu" | up to date
- icuidx07_d_en_fr_ga | "ga-x-icu" | up to date
- icuidx10_d_en_fr_ga_es | "es-x-icu" | up to date
- icuidx11_d_es | "es-x-icu" | up to date
- icuidx12_custom | custom | up to date
- icuidx13_custom | custom | up to date
- icuidx15_myrange_en_fr_ga | "en-x-icu" | up to date
- icuidx15_myrange_en_fr_ga | "fr-x-icu" | up to date
- icuidx15_myrange_en_fr_ga | "ga-x-icu" | up to date
- icuidx17_part | "en-x-icu" | up to date
-(38 rows)
-
--- Validate that REINDEX will update the stored version.
-UPDATE pg_depend SET refobjversion = 'not a version'
-WHERE refclassid = 'pg_collation'::regclass
-AND objid::regclass::text LIKE 'icuidx%'
-AND refobjversion IS NOT NULL;
-REINDEX TABLE collate_test;
-REINDEX TABLE collate_part_0;
-REINDEX TABLE collate_part_1;
-SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version';
- objid
--------
-(0 rows)
-
--- Validate that REINDEX CONCURRENTLY will update the stored version.
-UPDATE pg_depend SET refobjversion = 'not a version'
-WHERE refclassid = 'pg_collation'::regclass
-AND objid::regclass::text LIKE 'icuidx%'
-AND refobjversion IS NOT NULL;
-REINDEX TABLE CONCURRENTLY collate_test;
-REINDEX TABLE CONCURRENTLY collate_part_0;
-REINDEX INDEX CONCURRENTLY icuidx17_part;
-SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version';
- objid
--------
-(0 rows)
-
--- Validate that VACUUM FULL will update the stored version.
-UPDATE pg_depend SET refobjversion = 'not a version'
-WHERE refclassid = 'pg_collation'::regclass
-AND objid::regclass::text LIKE 'icuidx%'
-AND refobjversion IS NOT NULL;
-VACUUM FULL collate_test;
-VACUUM FULL collate_part_0;
-VACUUM FULL collate_part_1;
-SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version';
- objid
--------
-(0 rows)
-
--- Test ALTER INDEX name ALTER COLLATION name REFRESH VERSION
-UPDATE pg_depend SET refobjversion = 'not a version'
-WHERE refclassid = 'pg_collation'::regclass
-AND objid::regclass::text = 'icuidx17_part'
-AND refobjversion IS NOT NULL;
-SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version';
- objid
----------------
- icuidx17_part
-(1 row)
-
-ALTER INDEX icuidx17_part ALTER COLLATION "en-x-icu" REFRESH VERSION;
-SELECT objid::regclass, refobjversion = 'not a version' AS ver FROM pg_depend
-WHERE refclassid = 'pg_collation'::regclass
-AND objid::regclass::text = 'icuidx17_part';
- objid | ver
----------------+-----
- icuidx17_part | f
-(1 row)
-
-- cleanup
RESET search_path;
SET client_min_messages TO warning;
@@ -2132,17 +1957,3 @@ DROP SCHEMA collate_tests CASCADE;
RESET client_min_messages;
-- leave a collation for pg_upgrade test
CREATE COLLATION coll_icu_upgrade FROM "und-x-icu";
--- Test user-visible function for inspecting versions
-SELECT pg_collation_actual_version('"en-x-icu"'::regcollation) is not null;
- ?column?
-----------
- t
-(1 row)
-
--- Invalid OIDs are silently ignored
-SELECT pg_collation_actual_version(0) is null;
- ?column?
-----------
- t
-(1 row)
-
diff --git a/src/test/regress/expected/collate.linux.utf8.out b/src/test/regress/expected/collate.linux.utf8.out
index 580b00eea7..f06ae543e4 100644
--- a/src/test/regress/expected/collate.linux.utf8.out
+++ b/src/test/regress/expected/collate.linux.utf8.out
@@ -1093,6 +1093,9 @@ SELECT collname FROM pg_collation WHERE collname LIKE 'test%';
DROP SCHEMA test_schema;
DROP ROLE regress_test_role;
+-- ALTER
+ALTER COLLATION "en_US" REFRESH VERSION;
+NOTICE: version has not changed
-- dependencies
CREATE COLLATION test0 FROM "C";
CREATE TABLE collate_dep_test1 (a int, b text COLLATE test0);
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 7f8f91b92c..49f2a158c1 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2026,10 +2026,10 @@ REINDEX TABLE concur_reindex_tab; -- notice
NOTICE: table "concur_reindex_tab" has no indexes to reindex
REINDEX (CONCURRENTLY) TABLE concur_reindex_tab; -- notice
NOTICE: table "concur_reindex_tab" has no indexes that can be reindexed concurrently
-ALTER TABLE concur_reindex_tab ADD COLUMN c2 text COLLATE "C"; -- add toast index
+ALTER TABLE concur_reindex_tab ADD COLUMN c2 text; -- add toast index
-- Normal index with integer column
CREATE UNIQUE INDEX concur_reindex_ind1 ON concur_reindex_tab(c1);
--- Normal index with text column (with unversioned collation)
+-- Normal index with text column
CREATE INDEX concur_reindex_ind2 ON concur_reindex_tab(c2);
-- UNIQUE index with expression
CREATE UNIQUE INDEX concur_reindex_ind3 ON concur_reindex_tab(abs(c1));
@@ -2483,7 +2483,7 @@ WARNING: cannot reindex system catalogs concurrently, skipping all
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
c1 | integer | | not null |
- c2 | text | C | |
+ c2 | text | | |
Indexes:
"concur_reindex_ind1" PRIMARY KEY, btree (c1)
"concur_reindex_ind2" btree (c2)
diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out
index 9ebe28a78d..a67f40198a 100644
--- a/src/test/regress/expected/misc_sanity.out
+++ b/src/test/regress/expected/misc_sanity.out
@@ -18,8 +18,8 @@ WHERE refclassid = 0 OR refobjid = 0 OR
deptype NOT IN ('a', 'e', 'i', 'n', 'p') OR
(deptype != 'p' AND (classid = 0 OR objid = 0)) OR
(deptype = 'p' AND (classid != 0 OR objid != 0 OR objsubid != 0));
- classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype | refobjversion
----------+-------+----------+------------+----------+-------------+---------+---------------
+ classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype
+---------+-------+----------+------------+----------+-------------+---------
(0 rows)
-- **************** pg_shdepend ****************
diff --git a/src/test/regress/sql/collate.icu.utf8.sql b/src/test/regress/sql/collate.icu.utf8.sql
index 4c71f4d249..9cee3d0042 100644
--- a/src/test/regress/sql/collate.icu.utf8.sql
+++ b/src/test/regress/sql/collate.icu.utf8.sql
@@ -405,6 +405,11 @@ DROP SCHEMA test_schema;
DROP ROLE regress_test_role;
+-- ALTER
+
+ALTER COLLATION "en-x-icu" REFRESH VERSION;
+
+
-- dependencies
CREATE COLLATION test0 FROM "C";
@@ -742,134 +747,6 @@ INSERT INTO test33 VALUES (2, 'DEF');
-- they end up in the same partition (but it's platform-dependent which one)
SELECT (SELECT count(*) FROM test33_0) <> (SELECT count(*) FROM test33_1);
--- collation versioning support
-CREATE TYPE t_en_fr AS (fr text COLLATE "fr-x-icu", en text COLLATE "en-x-icu");
-CREATE DOMAIN d_en_fr AS t_en_fr;
-CREATE DOMAIN d_es AS text COLLATE "es-x-icu";
-CREATE TYPE t_en_fr_ga AS (en_fr t_en_fr, ga text COLLATE "ga-x-icu");
-CREATE DOMAIN d_en_fr_ga AS t_en_fr_ga;
-CREATE TYPE t_custom AS (meh text, meh2 text);
-CREATE DOMAIN d_custom AS t_custom;
-
-CREATE COLLATION custom (
- LOCALE = 'fr-x-icu', PROVIDER = 'icu'
-);
-
-CREATE TYPE myrange AS range (subtype = text, collation = "POSIX");
-CREATE TYPE myrange_en_fr_ga AS range(subtype = t_en_fr_ga);
-
-CREATE TABLE collate_test (
- id integer,
- val text COLLATE "fr-x-icu",
- t_en_fr t_en_fr,
- d_en_fr d_en_fr,
- d_es d_es,
- t_en_fr_ga t_en_fr_ga,
- d_en_fr_ga d_en_fr_ga,
- d_en_fr_ga_arr d_en_fr_ga[],
- myrange myrange,
- myrange_en_fr_ga myrange_en_fr_ga
-);
-
-CREATE INDEX icuidx00_val ON collate_test(val);
--- shouldn't get duplicated dependencies
-CREATE INDEX icuidx00_val_val ON collate_test(val, val);
--- shouldn't track version
-CREATE INDEX icuidx00_val_pattern ON collate_test(val text_pattern_ops);
--- should have single dependency, no version
-CREATE INDEX icuidx00_val_pattern_val_pattern ON collate_test(val text_pattern_ops, val text_pattern_ops);
--- should have single dependency, with version
-CREATE INDEX icuidx00_val_pattern_val ON collate_test(val text_pattern_ops, val);
--- should have single dependency, with version
-CREATE INDEX icuidx00_val_val_pattern ON collate_test(val, val text_pattern_ops);
--- two rows expected, only one a version, because we don't try to merge these yet
-CREATE INDEX icuidx00_val_pattern_where ON collate_test(val text_pattern_ops) WHERE val >= val;
--- two rows expected with version, because we don't try to merge these yet
-CREATE INDEX icuidx00_val_where ON collate_test(val) WHERE val >= val;
--- two rows expected with version (expression walker + attribute)
-CREATE INDEX icuidx00_val_pattern_expr ON collate_test(val varchar_pattern_ops, (val || val));
--- two rows expected, one with a version (expression walker + attribute)
-CREATE INDEX icuidx00_val_pattern_expr_pattern ON collate_test(val varchar_pattern_ops, (val || val) text_pattern_ops);
--- should have single dependency, with version tracked
-CREATE INDEX icuidx01_t_en_fr__d_es ON collate_test (t_en_fr, d_es);
-CREATE INDEX icuidx02_d_en_fr ON collate_test (d_en_fr);
-CREATE INDEX icuidx03_t_en_fr_ga ON collate_test (t_en_fr_ga);
-CREATE INDEX icuidx04_d_en_fr_ga ON collate_test (d_en_fr_ga);
-CREATE INDEX icuidx05_d_en_fr_ga_arr ON collate_test (d_en_fr_ga_arr);
-CREATE INDEX icuidx06_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga).en_fr.fr = 'foo';
-CREATE INDEX icuidx07_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga).ga = 'foo';
-CREATE INDEX icuidx08_d_en_fr_ga ON collate_test(id) WHERE (t_en_fr_ga) = ('foo', 'bar', 'baz');
-CREATE INDEX icuidx09_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga) = ('foo', 'bar', 'baz');
-CREATE INDEX icuidx10_d_en_fr_ga_es ON collate_test(id) WHERE (d_en_fr_ga) = ('foo', 'bar', 'baz' COLLATE "es-x-icu");
-CREATE INDEX icuidx11_d_es ON collate_test(id) WHERE (d_es) = ('foo');
-CREATE INDEX icuidx12_custom ON collate_test(id) WHERE ('foo', 'bar')::d_custom = ('foo', 'bar' COLLATE custom)::d_custom;
-CREATE INDEX icuidx13_custom ON collate_test(id) WHERE ('foo' COLLATE custom, 'bar')::d_custom = ('foo', 'bar')::d_custom;
-CREATE INDEX icuidx14_myrange ON collate_test(myrange);
-CREATE INDEX icuidx15_myrange_en_fr_ga ON collate_test USING gist (myrange_en_fr_ga);
-
-CREATE TABLE collate_part(id integer, val text COLLATE "en-x-icu") PARTITION BY range(id);
-CREATE TABLE collate_part_0 PARTITION OF collate_part FOR VALUES FROM (0) TO (1);
-CREATE TABLE collate_part_1 PARTITION OF collate_part FOR VALUES FROM (1) TO (1000000);
-CREATE INDEX icuidx17_part ON collate_part_1 (val);
-
-SELECT objid::regclass::text collate "C", refobjid::regcollation::text collate "C",
-CASE
-WHEN refobjid = 'default'::regcollation THEN 'XXX' -- depends on libc version support
-WHEN refobjversion IS NULL THEN 'version not tracked'
-WHEN refobjversion = pg_collation_actual_version(refobjid) THEN 'up to date'
-ELSE 'out of date'
-END AS version
-FROM pg_depend d
-LEFT JOIN pg_class c ON c.oid = d.objid
-WHERE refclassid = 'pg_collation'::regclass
-AND coalesce(relkind, 'i') = 'i'
-AND relname LIKE 'icuidx%'
-ORDER BY 1, 2, 3;
-
--- Validate that REINDEX will update the stored version.
-UPDATE pg_depend SET refobjversion = 'not a version'
-WHERE refclassid = 'pg_collation'::regclass
-AND objid::regclass::text LIKE 'icuidx%'
-AND refobjversion IS NOT NULL;
-
-REINDEX TABLE collate_test;
-REINDEX TABLE collate_part_0;
-REINDEX TABLE collate_part_1;
-
-SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version';
-
--- Validate that REINDEX CONCURRENTLY will update the stored version.
-UPDATE pg_depend SET refobjversion = 'not a version'
-WHERE refclassid = 'pg_collation'::regclass
-AND objid::regclass::text LIKE 'icuidx%'
-AND refobjversion IS NOT NULL;
-REINDEX TABLE CONCURRENTLY collate_test;
-REINDEX TABLE CONCURRENTLY collate_part_0;
-REINDEX INDEX CONCURRENTLY icuidx17_part;
-
-SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version';
-
--- Validate that VACUUM FULL will update the stored version.
-UPDATE pg_depend SET refobjversion = 'not a version'
-WHERE refclassid = 'pg_collation'::regclass
-AND objid::regclass::text LIKE 'icuidx%'
-AND refobjversion IS NOT NULL;
-VACUUM FULL collate_test;
-VACUUM FULL collate_part_0;
-VACUUM FULL collate_part_1;
-
-SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version';
-
--- Test ALTER INDEX name ALTER COLLATION name REFRESH VERSION
-UPDATE pg_depend SET refobjversion = 'not a version'
-WHERE refclassid = 'pg_collation'::regclass
-AND objid::regclass::text = 'icuidx17_part'
-AND refobjversion IS NOT NULL;
-SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version';
-ALTER INDEX icuidx17_part ALTER COLLATION "en-x-icu" REFRESH VERSION;
-SELECT objid::regclass, refobjversion = 'not a version' AS ver FROM pg_depend
-WHERE refclassid = 'pg_collation'::regclass
-AND objid::regclass::text = 'icuidx17_part';
-- cleanup
RESET search_path;
@@ -879,8 +756,3 @@ RESET client_min_messages;
-- leave a collation for pg_upgrade test
CREATE COLLATION coll_icu_upgrade FROM "und-x-icu";
-
--- Test user-visible function for inspecting versions
-SELECT pg_collation_actual_version('"en-x-icu"'::regcollation) is not null;
--- Invalid OIDs are silently ignored
-SELECT pg_collation_actual_version(0) is null;
diff --git a/src/test/regress/sql/collate.linux.utf8.sql b/src/test/regress/sql/collate.linux.utf8.sql
index c697c99488..cbbd2203e4 100644
--- a/src/test/regress/sql/collate.linux.utf8.sql
+++ b/src/test/regress/sql/collate.linux.utf8.sql
@@ -406,6 +406,11 @@ DROP SCHEMA test_schema;
DROP ROLE regress_test_role;
+-- ALTER
+
+ALTER COLLATION "en_US" REFRESH VERSION;
+
+
-- dependencies
CREATE COLLATION test0 FROM "C";
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index 51c9a12151..8bc76f7c6f 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -797,10 +797,10 @@ CREATE TABLE concur_reindex_tab (c1 int);
-- REINDEX
REINDEX TABLE concur_reindex_tab; -- notice
REINDEX (CONCURRENTLY) TABLE concur_reindex_tab; -- notice
-ALTER TABLE concur_reindex_tab ADD COLUMN c2 text COLLATE "C"; -- add toast index
+ALTER TABLE concur_reindex_tab ADD COLUMN c2 text; -- add toast index
-- Normal index with integer column
CREATE UNIQUE INDEX concur_reindex_ind1 ON concur_reindex_tab(c1);
--- Normal index with text column (with unversioned collation)
+-- Normal index with text column
CREATE INDEX concur_reindex_ind2 ON concur_reindex_tab(c2);
-- UNIQUE index with expression
CREATE UNIQUE INDEX concur_reindex_ind3 ON concur_reindex_tab(abs(c1));
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 878b67a276..0f197a9c8d 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2948,8 +2948,6 @@ dlist_head
dlist_iter
dlist_mutable_iter
dlist_node
-do_collation_version_check_context
-do_collation_version_update_context
ds_state
dsa_area
dsa_area_control