Revert per-index collation version tracking feature.
authorThomas Munro <tmunro@postgresql.org>
Fri, 7 May 2021 08:17:42 +0000 (20:17 +1200)
committerThomas Munro <tmunro@postgresql.org>
Fri, 7 May 2021 09:10:11 +0000 (21:10 +1200)
Design problems were discovered in the handling of composite types and
record types that would cause some relevant versions not to be recorded.
Misgivings were also expressed about the use of the pg_depend catalog
for this purpose.  We're out of time for this release so we'll revert
and try again.

Commits reverted:

1bf946bd: Doc: Document known problem with Windows collation versions.
cf002008: Remove no-longer-relevant test case.
ef387bed: Fix bogus collation-version-recording logic.
0fb0a050: Hide internal error for pg_collation_actual_version(<bad OID>).
ff942057: Suppress "warning: variable 'collcollate' set but not used".
d50e3b1f: Fix assertion in collation version lookup.
f24b1569: Rethink extraction of collation dependencies.
257836a7: Track collation versions for indexes.
cd6f479e: Add pg_depend.refobjversion.
7d1297df: Remove pg_collation.collversion.

Discussion: https://postgr.es/m/CA%2BhUKGLhj5t1fcjqAu8iD9B3ixJtsTNqyCCD4V0aTO9kAKAjjA%40mail.gmail.com

55 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/charset.sgml
doc/src/sgml/func.sgml
doc/src/sgml/ref/alter_collation.sgml
doc/src/sgml/ref/alter_index.sgml
doc/src/sgml/ref/create_collation.sgml
doc/src/sgml/ref/pgupgrade.sgml
doc/src/sgml/ref/reindex.sgml
src/backend/catalog/dependency.c
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/catalog/pg_collation.c
src/backend/catalog/pg_constraint.c
src/backend/catalog/pg_depend.c
src/backend/catalog/pg_type.c
src/backend/commands/collationcmds.c
src/backend/commands/statscmds.c
src/backend/commands/tablecmds.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/optimizer/util/plancat.c
src/backend/parser/gram.y
src/backend/tcop/utility.c
src/backend/utils/adt/pg_locale.c
src/backend/utils/adt/pg_upgrade_support.c
src/backend/utils/cache/relcache.c
src/bin/pg_dump/pg_backup.h
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h
src/bin/pg_upgrade/dump.c
src/bin/pg_upgrade/option.c
src/bin/pg_upgrade/pg_upgrade.h
src/bin/psql/tab-complete.c
src/include/catalog/catversion.h
src/include/catalog/dependency.h
src/include/catalog/index.h
src/include/catalog/pg_collation.h
src/include/catalog/pg_depend.h
src/include/catalog/pg_type.h
src/include/commands/collationcmds.h
src/include/nodes/parsenodes.h
src/include/utils/pg_locale.h
src/include/utils/rel.h
src/test/Makefile
src/test/locale/.gitignore
src/test/locale/Makefile
src/test/locale/t/001_index.pl [deleted file]
src/test/regress/expected/collate.icu.utf8.out
src/test/regress/expected/collate.linux.utf8.out
src/test/regress/expected/create_index.out
src/test/regress/expected/misc_sanity.out
src/test/regress/sql/collate.icu.utf8.sql
src/test/regress/sql/collate.linux.utf8.sql
src/test/regress/sql/create_index.sql
src/tools/pgindent/typedefs.list

index 492ed348b3a7242fbf6b6a6c5c2f433ded2f2deb..29ee9605b61dc0cf50a51ce587de4de8d0fe60d2 100644 (file)
@@ -2374,6 +2374,17 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
        <symbol>LC_CTYPE</symbol> for this collation object
       </para></entry>
      </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>collversion</structfield> <type>text</type>
+      </para>
+      <para>
+       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.
+      </para></entry>
+     </row>
     </tbody>
    </tgroup>
   </table>
@@ -3317,18 +3328,6 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
        A code defining the specific semantics of this dependency relationship; see text
       </para></entry>
      </row>
-
-     <row>
-      <entry role="catalog_table_entry"><para role="column_definition">
-       <structfield>refobjversion</structfield> <type>text</type>
-       </para>
-       <para>
-        An optional version for the referenced object.  Currently used for
-        indexes' collations (see <xref linkend="collation-versions"/>).
-       </para>
-      </entry>
-     </row>
-
     </tbody>
    </tgroup>
   </table>
index 1c673cc1103a490997a943e8f91e348a09fc78ac..98df74d0e1017bb17b7ccb77978ae5575b0cc43e 100644 (file)
@@ -948,54 +948,6 @@ CREATE COLLATION ignore_accents (provider = icu, locale = 'und-u-ks-level1-kc-tr
     </tip>
    </sect3>
   </sect2>
-
-  <sect2 id="collation-versions">
-   <title>Collation Versions</title>
-
-   <para>
-    The sort order defined by a collation is not necessarily fixed over time.
-    <productname>PostgreSQL</productname> 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.
-    <productname>PostgreSQL</productname> defends against this by recording the
-    current version of each referenced collation for any index that depends on
-    it in the
-    <link linkend="catalog-pg-depend"><structname>pg_depend</structname></link>
-    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
-    <xref linkend="sql-reindex"/> command or the
-    <xref linkend="sql-alterindex"/> command is used to update the version.
-   </para>
-   <para>
-    Version information is available from the
-    <literal>icu</literal> provider on all operating systems.  For the
-    <literal>libc</literal> provider, versions are currently only available
-    on systems using the GNU C library (most Linux systems), FreeBSD and
-    Windows.
-   </para>
-
-   <note>
-    <para>
-     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.
-    </para>
-    <para>
-     When using Windows collations, version information is only available for
-     collations defined with BCP 47 language tags such as
-     <literal>en-US</literal>.  Currently, <command>initdb</command> selects
-     a default locale using a traditional Windows language and country
-     string such as <literal>English_United States.1252</literal>.  The
-     <literal>--lc-collate</literal> option can be used to provide an explicit
-     locale name in BCP 47 format.
-    </para>
-   </note>
-  </sect2>
  </sect1>
 
  <sect1 id="multibyte">
index 0b5571460de7856117243d7c3c970b49cc08b00e..4d1f1794ca336eb1d2fe0f489ab111f41ecc0858 100644 (file)
@@ -26547,9 +26547,11 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup());
        </para>
        <para>
         Returns the actual version of the collation object as it is currently
-        installed in the operating system.  <literal>null</literal> is returned
-        on operating systems where <productname>PostgreSQL</productname>
-        doesn't have support for versions.
+        installed in the operating system.  If this is different from the
+        value in
+        <structname>pg_collation</structname>.<structfield>collversion</structfield>,
+        then objects depending on the collation might need to be rebuilt.  See
+        also <xref linkend="sql-altercollation"/>.
        </para></entry>
       </row>
 
index 65429aabe28b3e8037612281719741a636062a21..af9ff2867b72234f94e2bf52b0def1086acb6c48 100644 (file)
@@ -21,6 +21,8 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
+ALTER COLLATION <replaceable>name</replaceable> REFRESH VERSION
+
 ALTER COLLATION <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 ALTER COLLATION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER COLLATION <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
@@ -86,9 +88,70 @@ ALTER COLLATION <replaceable>name</replaceable> SET SCHEMA <replaceable>new_sche
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>REFRESH VERSION</literal></term>
+    <listitem>
+     <para>
+      Update the collation's version.
+      See <xref linkend="sql-altercollation-notes"/> below.
+     </para>
+    </listitem>
+   </varlistentry>
   </variablelist>
  </refsect1>
 
+ <refsect1 id="sql-altercollation-notes" xreflabel="Notes">
+  <title>Notes</title>
+
+  <para>
+   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:
+<screen>
+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.
+</screen>
+   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 <command>pg_upgrade</command> 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 <command>REINDEX</command>.  When that is done, the collation version
+   can be refreshed using the command <literal>ALTER COLLATION ... REFRESH
+   VERSION</literal>.  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.
+  </para>
+  <para>
+   When using collations provided by <literal>libc</literal> and
+   <productname>PostgreSQL</productname> 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.
+  </para>
+  <para>
+   Currently, there is no version tracking for the database default collation.
+  </para>
+
+  <para>
+   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:
+<programlisting><![CDATA[
+SELECT pg_describe_object(refclassid, refobjid, refobjsubid) AS "Collation",
+       pg_describe_object(classid, objid, objsubid) AS "Object"
+  FROM pg_depend d JOIN pg_collation c
+       ON refclassid = 'pg_collation'::regclass AND refobjid = c.oid
+  WHERE c.collversion <> pg_collation_actual_version(c.oid)
+  ORDER BY 1, 2;
+]]></programlisting></para>
+ </refsect1>
+
  <refsect1>
   <title>Examples</title>
 
index 4b446384c262b2b2e2db5cb5a20d28af45cd6934..e26efec064bee3fe5502c2060cd3bf2b33de2841 100644 (file)
@@ -25,7 +25,6 @@ ALTER INDEX [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RENA
 ALTER INDEX [ IF EXISTS ] <replaceable class="parameter">name</replaceable> SET TABLESPACE <replaceable class="parameter">tablespace_name</replaceable>
 ALTER INDEX <replaceable class="parameter">name</replaceable> ATTACH PARTITION <replaceable class="parameter">index_name</replaceable>
 ALTER INDEX <replaceable class="parameter">name</replaceable> [ NO ] DEPENDS ON EXTENSION <replaceable class="parameter">extension_name</replaceable>
-ALTER INDEX <replaceable class="parameter">name</replaceable> ALTER COLLATION <replaceable class="parameter">collation_name</replaceable> REFRESH VERSION
 ALTER INDEX [ IF EXISTS ] <replaceable class="parameter">name</replaceable> SET ( <replaceable class="parameter">storage_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )
 ALTER INDEX [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RESET ( <replaceable class="parameter">storage_parameter</replaceable> [, ... ] )
 ALTER INDEX [ IF EXISTS ] <replaceable class="parameter">name</replaceable> ALTER [ COLUMN ] <replaceable class="parameter">column_number</replaceable>
@@ -113,20 +112,6 @@ ALTER INDEX ALL IN TABLESPACE <replaceable class="parameter">name</replaceable>
     </listitem>
    </varlistentry>
 
-   <varlistentry>
-    <term><literal>ALTER COLLATION <replaceable class="parameter">collation_name</replaceable> REFRESH VERSION</literal></term>
-    <listitem>
-     <para>
-      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, <xref linkend="sql-reindex"/> is a safe alternative.
-      See <xref linkend="collation-versions"/> for more information.
-     </para>
-    </listitem>
-   </varlistentry>
-
    <varlistentry>
     <term><literal>SET ( <replaceable class="parameter">storage_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term>
     <listitem>
index b97842071f92fe50cd2c0e4e06170ad4b92ede45..58f5f0cd63a270df12ead21bc79cb5283b67415a 100644 (file)
@@ -27,6 +27,7 @@ CREATE COLLATION [ IF NOT EXISTS ] <replaceable>name</replaceable> (
     [ LC_CTYPE = <replaceable>lc_ctype</replaceable>, ]
     [ PROVIDER = <replaceable>provider</replaceable>, ]
     [ DETERMINISTIC = <replaceable>boolean</replaceable>, ]
+    [ VERSION = <replaceable>version</replaceable> ]
 )
 CREATE COLLATION [ IF NOT EXISTS ] <replaceable>name</replaceable> FROM <replaceable>existing_collation</replaceable>
 </synopsis>
@@ -148,6 +149,26 @@ CREATE COLLATION [ IF NOT EXISTS ] <replaceable>name</replaceable> FROM <replace
      </listitem>
     </varlistentry>
 
+    <varlistentry>
+     <term><replaceable>version</replaceable></term>
+
+     <listitem>
+      <para>
+       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 <command>pg_upgrade</command> for copying the version from an
+       existing installation.
+      </para>
+
+      <para>
+       See also <xref linkend="sql-altercollation"/> for how to handle
+       collation version mismatches.
+      </para>
+     </listitem>
+    </varlistentry>
+
     <varlistentry>
      <term><replaceable>existing_collation</replaceable></term>
 
index 4737d97d20203d42a68641642ee5747f89301dd3..a83c63cd98f4b6f716b3246bcf5cde0b644b3083 100644 (file)
@@ -215,21 +215,6 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
-     <varlistentry>
-      <term><option>--index-collation-versions-unknown</option></term>
-      <listitem>
-       <para>
-        When upgrading indexes from releases before 14 that didn't track
-        collation versions, <application>pg_upgrade</application>
-        assumes by default that the upgraded indexes are compatible with the
-        currently installed versions of relevant collations (see
-        <xref linkend="collation-versions"/>).  Specify
-        <option>--index-collation-versions-unknown</option> to mark
-        them as needing to be rebuilt instead.
-       </para>
-      </listitem>
-     </varlistentry>
-
      <varlistentry>
       <term><option>-?</option></term>
       <term><option>--help</option></term>
index 53c362dcd3ea412d5af994e9ea8db13f218f7bb3..e6b25ee670f7376560b701eabe10e96352f439a1 100644 (file)
@@ -40,15 +40,6 @@ REINDEX [ ( <replaceable class="parameter">option</replaceable> [, ...] ) ] { IN
    several scenarios in which to use <command>REINDEX</command>:
 
    <itemizedlist>
-    <listitem>
-     <para>
-      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 <xref linkend="collation-versions"/> for
-      more information.
-     </para>
-    </listitem>
-
     <listitem>
      <para>
       An index has become corrupted, and no longer contains valid
index 41093ea6aee0d0b1a6b849ca763e570ea181911f..259cde33976a4cfa7e50275d17ce9f84010ea8f1 100644 (file)
@@ -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);
 }
 
 /*
index 42ff175bc80a244b643fe8a666459bc206e3a5ad..431e62e3897269e5fe7af84ab0a9a96f86f722df 100644 (file)
@@ -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
index a628b3281ce8e73dd82ccb8b713d24b344e4e482..8ded2b53d4c74062a726763196bca6ab856a834d 100644 (file)
@@ -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. */
-       for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
-       {
-           Oid         colloid = collationObjectId[i];
+       /* placeholder for normal dependencies */
+       addrs = new_object_addresses();
 
-           if (OidIsValid(colloid))
-           {
-               Oid         opclass = classObjectId[i];
+       /* Store dependency on collations */
 
-               /*
-                * 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
+       /* The default collation is pinned, so don't bother recording it */
+       for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
+       {
+           if (OidIsValid(collationObjectId[i]) &&
+               collationObjectId[i] != DEFAULT_COLLATION_OID)
            {
-               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);
 }
 
 /*
index 40d98a334a6e9b40357d4640c91731b05fa68f38..19068b652a0b255ab12a0c8d682d1745cae2ff69 100644 (file)
@@ -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);
 
index 0081558c48ad3d55571dfebd2286656f47ca2ef9..a4e890020ff4bbeee083e73638292c5ab54750a3 100644 (file)
@@ -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 */
index 1217c01b8ae9864b74e221352fb90578248ab8e6..54688094f58482c88e4dba231e91a234d9e8cc0b 100644 (file)
 #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++;
index dc9d28a32c5723c04262783368d7c6402fbf54b5..da65584476b18b851fccf4c67686654b3e608bcf 100644 (file)
@@ -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
  *
index b8ec6f575641750d1c7a761ce1c8b4faf1e24b1b..ebb0994db32af41ee03d80b2173ffae49e6f4204 100644 (file)
@@ -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))
            {
index df4768952d5b8bd12c02fc25b7f1c018b110daa9..acae19176c01d5314604ee8459dcd50966e01d91 100644 (file)
@@ -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
index 0da61784d7a19fc27fbc27b04a10e0373d7063a5..3b5d41168391837cbee53e58e6087ac54f5d6a70 100644 (file)
@@ -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.
  */
index 632cc31a045e2b241e89087c45b7695e6c4f3b41..f5a7760740f56b9dbc2b6665030af36015f11819 100644 (file)
@@ -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;
index a410a29a178d5270a3373cd7f1c6288a5d770f81..ce76d093dda3f95241580311796d3bd72d386cb8 100644 (file)
@@ -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;
index 295ce114506cec4b0600fc903652d206ca2c65f4..c5194fdbbf23b5fc97e6b32a9335d77ff91e42c0 100644 (file)
@@ -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
index b4ab4014c873720e4354201ec5b1d2fe6a7ac953..aaf1a51f685ae8a8b9977a07bd267b202cbe76e3 100644 (file)
@@ -263,7 +263,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 }
 
 %type <node>   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 <name> 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
index 16c6f17e2355ae6bd38bee3e18386090e90a96ae..1a8fc16773322375a962f843b57ef115a7f1ae14 100644 (file)
@@ -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:
            {
index aa4874163f88e6c2add6a9655a5ca13f9cba7fd4..eab089f252f7dd1bc6684edcea250526f51d5949 100644 (file)
@@ -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
 /*
index a575c950790ad096c6790735df2fbe64ecfa6dde..b5b46d723127a51e376a5d450dab04825f6c317b 100644 (file)
@@ -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"
index 31c8e07f2a75f05615273968083aa58cfa25ed66..bd88f6105ba10603a2584ee66fb995a1b973500b 100644 (file)
@@ -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;
index 3bc86635f798d7a74ce5afe775f04ab2c1e60d5d..fc054af5ba18ce53c6bbf63e47be6c2d77a2f524 100644 (file)
@@ -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;
 
 /*
index 3cb3598f2b5e65323029b557f507f44428f9f89b..e384690d94ae2f9ae0deef03d93a14d22a792320 100644 (file)
@@ -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,64 +7254,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
         * is not.
         */
        resetPQExpBuffer(query);
-       if (fout->remoteVersion >= 140000)
-       {
-           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, "
-                             "(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)
+       if (fout->remoteVersion >= 110000)
        {
            appendPQExpBuffer(query,
                              "SELECT t.tableoid, t.oid, "
@@ -7347,9 +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, "
-                             "'{}' 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.
  *
index 53408430819bfc69c52dffed94c9f2abc26ba534..49e1b0a09c4eab05940a2ec08ac5a81f063765e7 100644 (file)
@@ -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 */
index 33d9591f3743fda252dc1c57135293a137a9c930..90060d0f8ebf7a358e558d5d002e6b1b65320056 100644 (file)
@@ -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);
index 4b74f9eea7e7b2931eb57711cf98169bae5d5172..64bbda565084e0f2c25b002cd052fd78841e893e 100644 (file)
@@ -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"
index d7666da3f270704b82ff47b5747f46840363315b..a5f71c5294ff33fd73d22b9d7d793010adec7e93 100644 (file)
@@ -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
index 7c4933333b3b8462dcecbd1fdd4a2105c5e05809..d917987fd588c5580ff5602070c68d3255f7efa5 100644 (file)
@@ -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 <name> ALTER */
    else if (Matches("ALTER", "INDEX", MatchAny, "ALTER"))
-       COMPLETE_WITH("COLLATION", "COLUMN");
+       COMPLETE_WITH("COLUMN");
    /* ALTER INDEX <name> 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 <name> 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 <name> ALTER COLLATION <name> */
-   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 <name> */
    else if (Matches("ALTER", "LANGUAGE", MatchAny))
index 22dcd0a270c6ffc1e21edbd9c684545f0b75cf21..a54be88d7f174136d7d37a620b737b8d366b50e6 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202104271
+#define CATALOG_VERSION_NO 202105051
 
 #endif
index f272e2c99f8747dc34a220c42f23f72124094373..fd44081e741eca151cc74f4de3a69f9021c6f41a 100644 (file)
@@ -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);
 
index e22d506436b1246e9c2490c6817f53736ec5c135..008f723e1043e9dbd4ee047ffa792c7d3fb30bbd 100644 (file)
@@ -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,
index c6394ca22216550568149c4063fd798e08363048..52bfd2cb7bf4b9f829397905ff4a0d6ad5985cc0 100644 (file)
@@ -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);
 
index 606a2a8e192ece3ab1a3e92c96b24aa63b645629..e0bc1141457e3df8b4b5405a678ebb35c824e2f7 100644 (file)
@@ -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));
index 8ee5fa0507a3784aba54d470d4809e368ed7c86d..33557760e1902724321119f46a839f93f1ca3826 100644 (file)
@@ -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);
 
index 4e690458805de294050dd5be4a9a249af7f457ea..e49a5db0fbdea767fe0db7eb40ff4f783bacf34b 100644 (file)
@@ -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 */
index 615dfa26aa2f326b947271024706ef1a62f15fcb..fea31232519425184f1539a4527b496c30de6b67 100644 (file)
@@ -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
  *
index 5a37caefbe47a6a56939a05ce00e9d00550c43a7..2946f46c76f9753d1ef087ad44ba77ccd9aab2ff 100644 (file)
@@ -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);
index 5bd44be9a79e0fda4b1b32b81f898a70559171b8..774ac5b2b193f7ad3f40824a26b7de30fc7496c9 100644 (file)
@@ -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
index f7859c2fd5e79ef9c81539183015992f404fb9bf..46275915ff327750ff6372b887a95bb8f8cac006 100644 (file)
@@ -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
index 64e1bf2a8037cbe5e1cab39b5f53529282c08cec..620d3df425421a0f5e423e2c947f5a55aee51a96 100644 (file)
@@ -1,2 +1 @@
 /test-ctype
-/tmp_check/
index 673e14dcd08a12d62570dd49717712748a0fcb9d..7ba096b542710aaea454c85f5216f97c0296c158 100644 (file)
@@ -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 (file)
index a67f78c..0000000
+++ /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;
index faf99f76b540b0a71a936643eee20053e905425c..70133df8042cca63f51f3e300dffbf439f8f9412 100644 (file)
@@ -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)
-
index 580b00eea79bcf75829d932aaed8f45831752dd2..f06ae543e497713787cccd057080c1ee5837cf30 100644 (file)
@@ -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);
index 7f8f91b92c6bc6f7c0aacffb24377465f496259d..49f2a158c1fb2aa7c470e492dfb2cb253ed180a0 100644 (file)
@@ -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)
index 9ebe28a78da30c8e0f54f7f7151bc07ccc472e9a..a67f40198a45dd463358e6f5fa547cbcebc538ed 100644 (file)
@@ -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 ****************
index 4c71f4d249e5f54ce08f175a346d64875bc8ade7..9cee3d0042b1ca88bb79aa3318c414b3196fe340 100644 (file)
@@ -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;
index c697c994880555f216f5ace3ef8b82be71fb3c03..cbbd2203e413b0141242224e444dd353a92a56fe 100644 (file)
@@ -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";
index 51c9a121514ac53b58a84b955ea9e2d50424d862..8bc76f7c6f1872fa8e8a80a1938a64f8d6c001b9 100644 (file)
@@ -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));
index 878b67a276d43bf5830e3cffc4b9a7550890de47..0f197a9c8db9fd4fa0f000f2bdc5e4dfc80beafd 100644 (file)
@@ -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