mirror of
https://github.com/postgres/postgres.git
synced 2025-06-07 11:02:12 +03:00
Make a code-cleanup pass over the collations patch.
This patch is almost entirely cosmetic --- mostly cleaning up a lot of neglected comments, and fixing code layout problems in places where the patch made lines too long and then pgindent did weird things with that. I did find a bug-of-omission in equalTupleDescs().
This commit is contained in:
parent
0cfdc1c657
commit
9e9b9ac7d1
@ -2159,8 +2159,8 @@
|
|||||||
(<structfield>collname</>, <structfield>collnamespace</>).
|
(<structfield>collname</>, <structfield>collnamespace</>).
|
||||||
<productname>PostgreSQL</productname> generally ignores all
|
<productname>PostgreSQL</productname> generally ignores all
|
||||||
collations that do not have <structfield>collencoding</> equal to
|
collations that do not have <structfield>collencoding</> equal to
|
||||||
either the current database's encoding or -1, and creation of new
|
either the current database's encoding or -1, and creation of new entries
|
||||||
entries matching an entry with <structfield>collencoding</> = -1
|
with the same name as an entry with <structfield>collencoding</> = -1
|
||||||
is forbidden. Therefore it is sufficient to use a qualified SQL name
|
is forbidden. Therefore it is sufficient to use a qualified SQL name
|
||||||
(<replaceable>schema</>.<replaceable>name</>) to identify a collation,
|
(<replaceable>schema</>.<replaceable>name</>) to identify a collation,
|
||||||
even though this is not unique according to the catalog definition.
|
even though this is not unique according to the catalog definition.
|
||||||
@ -6138,8 +6138,8 @@
|
|||||||
of the type. If the type does not support collations, this will
|
of the type. If the type does not support collations, this will
|
||||||
be zero. A base type that supports collations will have
|
be zero. A base type that supports collations will have
|
||||||
<symbol>DEFAULT_COLLATION_OID</symbol> here. A domain over a
|
<symbol>DEFAULT_COLLATION_OID</symbol> here. A domain over a
|
||||||
collatable type can have some other collation OID, if one was defined
|
collatable type can have some other collation OID, if one was
|
||||||
for the domain.
|
specified for the domain.
|
||||||
</para></entry>
|
</para></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
@ -1004,12 +1004,11 @@ SELECT am.amname AS index_method,
|
|||||||
|
|
||||||
|
|
||||||
<sect1 id="indexes-collations">
|
<sect1 id="indexes-collations">
|
||||||
<title>Collations and Indexes</title>
|
<title>Indexes and Collations</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
An index can only support one collation for one column or
|
An index can support only one collation per index column.
|
||||||
expression. If multiple collations are of interest, multiple
|
If multiple collations are of interest, multiple indexes may be needed.
|
||||||
indexes may be created.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -1022,23 +1021,21 @@ CREATE TABLE test1c (
|
|||||||
|
|
||||||
CREATE INDEX test1c_content_index ON test1c (content);
|
CREATE INDEX test1c_content_index ON test1c (content);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
The created index automatically follows the collation of the
|
The index automatically uses the collation of the
|
||||||
underlying column, and so a query of the form
|
underlying column. So a query of the form
|
||||||
<programlisting>
|
<programlisting>
|
||||||
SELECT * FROM test1c WHERE content = <replaceable>constant</replaceable>;
|
SELECT * FROM test1c WHERE content > <replaceable>constant</replaceable>;
|
||||||
</programlisting>
|
</programlisting>
|
||||||
could use the index.
|
could use the index, because the comparison will by default use the
|
||||||
</para>
|
collation of the column. However, this index cannot accelerate queries
|
||||||
|
that involve some other collation. So if queries of the form, say,
|
||||||
<para>
|
|
||||||
If in addition, a query of the form, say,
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
SELECT * FROM test1c WHERE content > <replaceable>constant</replaceable> COLLATE "y";
|
SELECT * FROM test1c WHERE content > <replaceable>constant</replaceable> COLLATE "y";
|
||||||
</programlisting>
|
</programlisting>
|
||||||
is of interest, an additional index could be created that supports
|
are also of interest, an additional index could be created that supports
|
||||||
the <literal>"y"</literal> collation, like so:
|
the <literal>"y"</literal> collation, like this:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
CREATE INDEX test1c_content_index ON test1c (content COLLATE "y");
|
CREATE INDEX test1c_content_y_index ON test1c (content COLLATE "y");
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
@ -108,8 +108,8 @@ CREATE COLLATION <replaceable>name</replaceable> FROM <replaceable>existing_coll
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The name of an existing collation to copy. The new collation
|
The name of an existing collation to copy. The new collation
|
||||||
will have the same properties as the existing one, but they
|
will have the same properties as the existing one, but it
|
||||||
will become independent objects.
|
will be an independent object.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -134,7 +134,8 @@ CREATE COLLATION <replaceable>name</replaceable> FROM <replaceable>existing_coll
|
|||||||
<title>Examples</title>
|
<title>Examples</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To create a collation from the locale <literal>fr_FR.utf8</literal>
|
To create a collation from the operating system locale
|
||||||
|
<literal>fr_FR.utf8</literal>
|
||||||
(assuming the current database encoding is <literal>UTF8</literal>):
|
(assuming the current database encoding is <literal>UTF8</literal>):
|
||||||
<programlisting>
|
<programlisting>
|
||||||
CREATE COLLATION french (LOCALE = 'fr_FR.utf8');
|
CREATE COLLATION french (LOCALE = 'fr_FR.utf8');
|
||||||
|
@ -90,7 +90,7 @@ CREATE DOMAIN <replaceable class="parameter">name</replaceable> [ AS ] <replacea
|
|||||||
<para>
|
<para>
|
||||||
An optional collation for the domain. If no collation is
|
An optional collation for the domain. If no collation is
|
||||||
specified, the underlying data type's default collation is used.
|
specified, the underlying data type's default collation is used.
|
||||||
The underlying type must be collatable when <literal>COLLATE</>
|
The underlying type must be collatable if <literal>COLLATE</>
|
||||||
is specified.
|
is specified.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
@ -188,9 +188,8 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ <replaceable class="parameter">name</
|
|||||||
The name of the collation to use for the index. By default,
|
The name of the collation to use for the index. By default,
|
||||||
the index uses the collation declared for the column to be
|
the index uses the collation declared for the column to be
|
||||||
indexed or the result collation of the expression to be
|
indexed or the result collation of the expression to be
|
||||||
indexed. Indexes with nondefault collations are
|
indexed. Indexes with non-default collations can be useful for
|
||||||
available for use by queries that involve expressions using
|
queries that involve expressions using non-default collations.
|
||||||
nondefault collations.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -537,6 +536,13 @@ CREATE INDEX ON films ((lower(title)));
|
|||||||
will choose a name, typically <literal>films_lower_idx</>.)
|
will choose a name, typically <literal>films_lower_idx</>.)
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
To create an index with non-default collation:
|
||||||
|
<programlisting>
|
||||||
|
CREATE INDEX title_idx_german ON films (title COLLATE "de_DE");
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To create an index with non-default sort ordering of nulls:
|
To create an index with non-default sort ordering of nulls:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
|
@ -355,10 +355,10 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If the optional
|
If the optional boolean
|
||||||
parameter <replaceable class="parameter">collatable</replaceable>
|
parameter <replaceable class="parameter">collatable</replaceable>
|
||||||
is true, column definitions and expressions of the type may carry
|
is true, column definitions and expressions of the type may carry
|
||||||
collation information and allow the use of
|
collation information through use of
|
||||||
the <literal>COLLATE</literal> clause. It is up to the
|
the <literal>COLLATE</literal> clause. It is up to the
|
||||||
implementations of the functions operating on the type to actually
|
implementations of the functions operating on the type to actually
|
||||||
make use of the collation information; this does not happen
|
make use of the collation information; this does not happen
|
||||||
|
@ -238,7 +238,7 @@ gmake check LANG=C ENCODING=EUC_JP
|
|||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2>
|
<sect2>
|
||||||
<title>Extra tests</title>
|
<title>Extra Tests</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The regression test suite contains a few test files that are not
|
The regression test suite contains a few test files that are not
|
||||||
@ -253,8 +253,8 @@ gmake check EXTRA_TESTS=numeric_big
|
|||||||
<screen>
|
<screen>
|
||||||
gmake check EXTRA_TESTS=collate.linux.utf8 LANG=en_US.utf8
|
gmake check EXTRA_TESTS=collate.linux.utf8 LANG=en_US.utf8
|
||||||
</screen>
|
</screen>
|
||||||
This test works only on Linux/glibc platforms and when run in a
|
The <literal>collate.linux.utf8</> test works only on Linux/glibc
|
||||||
UTF-8 locale.
|
platforms, and only when run in a locale that uses UTF-8 encoding.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
@ -360,6 +360,8 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
|
|||||||
return false;
|
return false;
|
||||||
if (attr1->attinhcount != attr2->attinhcount)
|
if (attr1->attinhcount != attr2->attinhcount)
|
||||||
return false;
|
return false;
|
||||||
|
if (attr1->attcollation != attr2->attcollation)
|
||||||
|
return false;
|
||||||
/* attacl and attoptions are not even present... */
|
/* attacl and attoptions are not even present... */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,7 +613,9 @@ BuildDescForRelation(List *schema)
|
|||||||
* BuildDescFromLists
|
* BuildDescFromLists
|
||||||
*
|
*
|
||||||
* Build a TupleDesc given lists of column names (as String nodes),
|
* Build a TupleDesc given lists of column names (as String nodes),
|
||||||
* column type OIDs, and column typmods. No constraints are generated.
|
* column type OIDs, typmods, and collation OIDs.
|
||||||
|
*
|
||||||
|
* No constraints are generated.
|
||||||
*
|
*
|
||||||
* This is essentially a cut-down version of BuildDescForRelation for use
|
* This is essentially a cut-down version of BuildDescForRelation for use
|
||||||
* with functions returning RECORD.
|
* with functions returning RECORD.
|
||||||
|
@ -2227,14 +2227,16 @@ getObjectDescription(const ObjectAddress *object)
|
|||||||
case OCLASS_COLLATION:
|
case OCLASS_COLLATION:
|
||||||
{
|
{
|
||||||
HeapTuple collTup;
|
HeapTuple collTup;
|
||||||
|
Form_pg_collation coll;
|
||||||
|
|
||||||
collTup = SearchSysCache1(COLLOID,
|
collTup = SearchSysCache1(COLLOID,
|
||||||
ObjectIdGetDatum(object->objectId));
|
ObjectIdGetDatum(object->objectId));
|
||||||
if (!HeapTupleIsValid(collTup))
|
if (!HeapTupleIsValid(collTup))
|
||||||
elog(ERROR, "cache lookup failed for collation %u",
|
elog(ERROR, "cache lookup failed for collation %u",
|
||||||
object->objectId);
|
object->objectId);
|
||||||
|
coll = (Form_pg_collation) GETSTRUCT(collTup);
|
||||||
appendStringInfo(&buffer, _("collation %s"),
|
appendStringInfo(&buffer, _("collation %s"),
|
||||||
NameStr(((Form_pg_collation) GETSTRUCT(collTup))->collname));
|
NameStr(coll->collname));
|
||||||
ReleaseSysCache(collTup);
|
ReleaseSysCache(collTup);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -644,7 +644,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* First we add the user attributes. This is also a convenient place to
|
* First we add the user attributes. This is also a convenient place to
|
||||||
* add dependencies on their datatypes.
|
* add dependencies on their datatypes and collations.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < natts; i++)
|
for (i = 0; i < natts; i++)
|
||||||
{
|
{
|
||||||
@ -666,7 +666,9 @@ AddNewAttributeTuples(Oid new_rel_oid,
|
|||||||
referenced.objectSubId = 0;
|
referenced.objectSubId = 0;
|
||||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||||
|
|
||||||
if (OidIsValid(attr->attcollation))
|
/* The default collation is pinned, so don't bother recording it */
|
||||||
|
if (OidIsValid(attr->attcollation) &&
|
||||||
|
attr->attcollation != DEFAULT_COLLATION_OID)
|
||||||
{
|
{
|
||||||
referenced.classId = CollationRelationId;
|
referenced.classId = CollationRelationId;
|
||||||
referenced.objectId = attr->attcollation;
|
referenced.objectId = attr->attcollation;
|
||||||
@ -921,7 +923,7 @@ AddNewRelationType(const char *typeName,
|
|||||||
-1, /* typmod */
|
-1, /* typmod */
|
||||||
0, /* array dimensions for typBaseType */
|
0, /* array dimensions for typBaseType */
|
||||||
false, /* Type NOT NULL */
|
false, /* Type NOT NULL */
|
||||||
InvalidOid); /* typcollation */
|
InvalidOid); /* rowtypes never have a collation */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------
|
/* --------------------------------
|
||||||
@ -1183,7 +1185,7 @@ heap_create_with_catalog(const char *relname,
|
|||||||
-1, /* typmod */
|
-1, /* typmod */
|
||||||
0, /* array dimensions for typBaseType */
|
0, /* array dimensions for typBaseType */
|
||||||
false, /* Type NOT NULL */
|
false, /* Type NOT NULL */
|
||||||
InvalidOid); /* typcollation */
|
InvalidOid); /* rowtypes never have a collation */
|
||||||
|
|
||||||
pfree(relarrayname);
|
pfree(relarrayname);
|
||||||
}
|
}
|
||||||
|
@ -351,7 +351,6 @@ ConstructTupleDescriptor(Relation heapRelation,
|
|||||||
to->atthasdef = false;
|
to->atthasdef = false;
|
||||||
to->attislocal = true;
|
to->attislocal = true;
|
||||||
to->attinhcount = 0;
|
to->attinhcount = 0;
|
||||||
|
|
||||||
to->attcollation = collationObjectId[i];
|
to->attcollation = collationObjectId[i];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -388,7 +387,6 @@ ConstructTupleDescriptor(Relation heapRelation,
|
|||||||
to->attcacheoff = -1;
|
to->attcacheoff = -1;
|
||||||
to->atttypmod = -1;
|
to->atttypmod = -1;
|
||||||
to->attislocal = true;
|
to->attislocal = true;
|
||||||
|
|
||||||
to->attcollation = collationObjectId[i];
|
to->attcollation = collationObjectId[i];
|
||||||
|
|
||||||
ReleaseSysCache(tuple);
|
ReleaseSysCache(tuple);
|
||||||
@ -653,6 +651,7 @@ UpdateIndexRelation(Oid indexoid,
|
|||||||
* indexColNames: column names to use for index (List of char *)
|
* indexColNames: column names to use for index (List of char *)
|
||||||
* accessMethodObjectId: OID of index AM to use
|
* accessMethodObjectId: OID of index AM to use
|
||||||
* tableSpaceId: OID of tablespace to use
|
* tableSpaceId: OID of tablespace to use
|
||||||
|
* collationObjectId: array of collation OIDs, one per index column
|
||||||
* classObjectId: array of index opclass OIDs, one per index column
|
* classObjectId: array of index opclass OIDs, one per index column
|
||||||
* coloptions: array of per-index-column indoption settings
|
* coloptions: array of per-index-column indoption settings
|
||||||
* reloptions: AM-specific options
|
* reloptions: AM-specific options
|
||||||
@ -871,7 +870,8 @@ index_create(Relation heapRelation,
|
|||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
UpdateIndexRelation(indexRelationId, heapRelationId, indexInfo,
|
UpdateIndexRelation(indexRelationId, heapRelationId, indexInfo,
|
||||||
collationObjectId, classObjectId, coloptions, isprimary, is_exclusion,
|
collationObjectId, classObjectId, coloptions,
|
||||||
|
isprimary, is_exclusion,
|
||||||
!deferrable,
|
!deferrable,
|
||||||
!concurrent);
|
!concurrent);
|
||||||
|
|
||||||
@ -965,9 +965,11 @@ index_create(Relation heapRelation,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Store dependency on collations */
|
/* Store dependency on collations */
|
||||||
|
/* The default collation is pinned, so don't bother recording it */
|
||||||
for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
|
for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
|
||||||
{
|
{
|
||||||
if (OidIsValid(collationObjectId[i]))
|
if (OidIsValid(collationObjectId[i]) &&
|
||||||
|
collationObjectId[i] != DEFAULT_COLLATION_OID)
|
||||||
{
|
{
|
||||||
referenced.classId = CollationRelationId;
|
referenced.classId = CollationRelationId;
|
||||||
referenced.objectId = collationObjectId[i];
|
referenced.objectId = collationObjectId[i];
|
||||||
@ -2445,8 +2447,8 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
|
|||||||
ivinfo.num_heap_tuples = heapRelation->rd_rel->reltuples;
|
ivinfo.num_heap_tuples = heapRelation->rd_rel->reltuples;
|
||||||
ivinfo.strategy = NULL;
|
ivinfo.strategy = NULL;
|
||||||
|
|
||||||
state.tuplesort = tuplesort_begin_datum(TIDOID,
|
state.tuplesort = tuplesort_begin_datum(TIDOID, TIDLessOperator,
|
||||||
TIDLessOperator, InvalidOid, false,
|
InvalidOid, false,
|
||||||
maintenance_work_mem,
|
maintenance_work_mem,
|
||||||
false);
|
false);
|
||||||
state.htups = state.itups = state.tups_inserted = 0;
|
state.htups = state.itups = state.tups_inserted = 0;
|
||||||
|
@ -643,8 +643,9 @@ GenerateTypeDependencies(Oid typeNamespace,
|
|||||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Normal dependency from a domain to its base type's collation. */
|
/* Normal dependency from a domain to its collation. */
|
||||||
if (OidIsValid(typeCollation))
|
/* We know the default collation is pinned, so don't bother recording it */
|
||||||
|
if (OidIsValid(typeCollation) && typeCollation != DEFAULT_COLLATION_OID)
|
||||||
{
|
{
|
||||||
referenced.classId = CollationRelationId;
|
referenced.classId = CollationRelationId;
|
||||||
referenced.objectId = typeCollation;
|
referenced.objectId = typeCollation;
|
||||||
|
@ -350,7 +350,8 @@ DefineIndex(RangeVar *heapRelation,
|
|||||||
collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
|
collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
|
||||||
classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
|
classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
|
||||||
coloptions = (int16 *) palloc(numberOfAttributes * sizeof(int16));
|
coloptions = (int16 *) palloc(numberOfAttributes * sizeof(int16));
|
||||||
ComputeIndexAttrs(indexInfo, collationObjectId, classObjectId, coloptions, attributeList,
|
ComputeIndexAttrs(indexInfo, collationObjectId, classObjectId,
|
||||||
|
coloptions, attributeList,
|
||||||
exclusionOpNames, relationId,
|
exclusionOpNames, relationId,
|
||||||
accessMethodName, accessMethodId,
|
accessMethodName, accessMethodId,
|
||||||
amcanorder, isconstraint);
|
amcanorder, isconstraint);
|
||||||
@ -395,7 +396,8 @@ DefineIndex(RangeVar *heapRelation,
|
|||||||
indexRelationId =
|
indexRelationId =
|
||||||
index_create(rel, indexRelationName, indexRelationId,
|
index_create(rel, indexRelationName, indexRelationId,
|
||||||
indexInfo, indexColNames,
|
indexInfo, indexColNames,
|
||||||
accessMethodId, tablespaceId, collationObjectId, classObjectId,
|
accessMethodId, tablespaceId,
|
||||||
|
collationObjectId, classObjectId,
|
||||||
coloptions, reloptions, primary,
|
coloptions, reloptions, primary,
|
||||||
isconstraint, deferrable, initdeferred,
|
isconstraint, deferrable, initdeferred,
|
||||||
allowSystemTableMods,
|
allowSystemTableMods,
|
||||||
|
@ -295,7 +295,8 @@ static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recu
|
|||||||
static void ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
static void ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
||||||
ColumnDef *colDef, bool isOid,
|
ColumnDef *colDef, bool isOid,
|
||||||
bool recurse, bool recursing, LOCKMODE lockmode);
|
bool recurse, bool recursing, LOCKMODE lockmode);
|
||||||
static void add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid, Oid collid);
|
static void add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid);
|
||||||
|
static void add_column_collation_dependency(Oid relid, int32 attnum, Oid collid);
|
||||||
static void ATPrepAddOids(List **wqueue, Relation rel, bool recurse,
|
static void ATPrepAddOids(List **wqueue, Relation rel, bool recurse,
|
||||||
AlterTableCmd *cmd, LOCKMODE lockmode);
|
AlterTableCmd *cmd, LOCKMODE lockmode);
|
||||||
static void ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode);
|
static void ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode);
|
||||||
@ -4423,7 +4424,8 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
|||||||
/*
|
/*
|
||||||
* Add needed dependency entries for the new column.
|
* Add needed dependency entries for the new column.
|
||||||
*/
|
*/
|
||||||
add_column_datatype_dependency(myrelid, newattnum, attribute.atttypid, attribute.attcollation);
|
add_column_datatype_dependency(myrelid, newattnum, attribute.atttypid);
|
||||||
|
add_column_collation_dependency(myrelid, newattnum, attribute.attcollation);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Propagate to children as appropriate. Unlike most other ALTER
|
* Propagate to children as appropriate. Unlike most other ALTER
|
||||||
@ -4474,7 +4476,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
|||||||
* Install a column's dependency on its datatype.
|
* Install a column's dependency on its datatype.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid, Oid collid)
|
add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid)
|
||||||
{
|
{
|
||||||
ObjectAddress myself,
|
ObjectAddress myself,
|
||||||
referenced;
|
referenced;
|
||||||
@ -4486,9 +4488,23 @@ add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid, Oid collid)
|
|||||||
referenced.objectId = typid;
|
referenced.objectId = typid;
|
||||||
referenced.objectSubId = 0;
|
referenced.objectSubId = 0;
|
||||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
if (collid)
|
/*
|
||||||
|
* Install a column's dependency on its collation.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
add_column_collation_dependency(Oid relid, int32 attnum, Oid collid)
|
||||||
{
|
{
|
||||||
|
ObjectAddress myself,
|
||||||
|
referenced;
|
||||||
|
|
||||||
|
/* We know the default collation is pinned, so don't bother recording it */
|
||||||
|
if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID)
|
||||||
|
{
|
||||||
|
myself.classId = RelationRelationId;
|
||||||
|
myself.objectId = relid;
|
||||||
|
myself.objectSubId = attnum;
|
||||||
referenced.classId = CollationRelationId;
|
referenced.classId = CollationRelationId;
|
||||||
referenced.objectId = collid;
|
referenced.objectId = collid;
|
||||||
referenced.objectSubId = 0;
|
referenced.objectSubId = 0;
|
||||||
@ -6671,7 +6687,8 @@ ATPrepAlterColumnType(List **wqueue,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
transform = (Node *) makeVar(1, attnum,
|
transform = (Node *) makeVar(1, attnum,
|
||||||
attTup->atttypid, attTup->atttypmod, attTup->attcollation,
|
attTup->atttypid, attTup->atttypmod,
|
||||||
|
attTup->attcollation,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7052,7 +7069,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
|
|||||||
/*
|
/*
|
||||||
* Now scan for dependencies of this column on other things. The only
|
* Now scan for dependencies of this column on other things. The only
|
||||||
* thing we should find is the dependency on the column datatype, which we
|
* thing we should find is the dependency on the column datatype, which we
|
||||||
* want to remove, and possibly an associated collation.
|
* want to remove, and possibly a collation dependency.
|
||||||
*/
|
*/
|
||||||
ScanKeyInit(&key[0],
|
ScanKeyInit(&key[0],
|
||||||
Anum_pg_depend_classid,
|
Anum_pg_depend_classid,
|
||||||
@ -7091,8 +7108,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
|
|||||||
heap_close(depRel, RowExclusiveLock);
|
heap_close(depRel, RowExclusiveLock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Here we go --- change the recorded column type. (Note heapTup is a
|
* Here we go --- change the recorded column type and collation. (Note
|
||||||
* copy of the syscache entry, so okay to scribble on.)
|
* heapTup is a copy of the syscache entry, so okay to scribble on.)
|
||||||
*/
|
*/
|
||||||
attTup->atttypid = targettype;
|
attTup->atttypid = targettype;
|
||||||
attTup->atttypmod = targettypmod;
|
attTup->atttypmod = targettypmod;
|
||||||
@ -7112,8 +7129,9 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
|
|||||||
|
|
||||||
heap_close(attrelation, RowExclusiveLock);
|
heap_close(attrelation, RowExclusiveLock);
|
||||||
|
|
||||||
/* Install dependency on new datatype */
|
/* Install dependencies on new datatype and collation */
|
||||||
add_column_datatype_dependency(RelationGetRelid(rel), attnum, targettype, targetcollid);
|
add_column_datatype_dependency(RelationGetRelid(rel), attnum, targettype);
|
||||||
|
add_column_collation_dependency(RelationGetRelid(rel), attnum, targetcollid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Drop any pg_statistic entry for the column, since it's now wrong type
|
* Drop any pg_statistic entry for the column, since it's now wrong type
|
||||||
|
@ -571,7 +571,7 @@ DefineType(List *names, List *parameters)
|
|||||||
-1, /* typMod (Domains only) */
|
-1, /* typMod (Domains only) */
|
||||||
0, /* Array Dimensions of typbasetype */
|
0, /* Array Dimensions of typbasetype */
|
||||||
false, /* Type NOT NULL */
|
false, /* Type NOT NULL */
|
||||||
collation);
|
collation); /* type's collation */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the array type that goes with it.
|
* Create the array type that goes with it.
|
||||||
@ -611,7 +611,7 @@ DefineType(List *names, List *parameters)
|
|||||||
-1, /* typMod (Domains only) */
|
-1, /* typMod (Domains only) */
|
||||||
0, /* Array dimensions of typbasetype */
|
0, /* Array dimensions of typbasetype */
|
||||||
false, /* Type NOT NULL */
|
false, /* Type NOT NULL */
|
||||||
collation);
|
collation); /* type's collation */
|
||||||
|
|
||||||
pfree(array_type);
|
pfree(array_type);
|
||||||
}
|
}
|
||||||
@ -1069,7 +1069,7 @@ DefineDomain(CreateDomainStmt *stmt)
|
|||||||
basetypeMod, /* typeMod value */
|
basetypeMod, /* typeMod value */
|
||||||
typNDims, /* Array dimensions for base type */
|
typNDims, /* Array dimensions for base type */
|
||||||
typNotNull, /* Type NOT NULL */
|
typNotNull, /* Type NOT NULL */
|
||||||
domaincoll);
|
domaincoll); /* type's collation */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process constraints which refer to the domain ID returned by TypeCreate
|
* Process constraints which refer to the domain ID returned by TypeCreate
|
||||||
@ -1179,7 +1179,7 @@ DefineEnum(CreateEnumStmt *stmt)
|
|||||||
-1, /* typMod (Domains only) */
|
-1, /* typMod (Domains only) */
|
||||||
0, /* Array dimensions of typbasetype */
|
0, /* Array dimensions of typbasetype */
|
||||||
false, /* Type NOT NULL */
|
false, /* Type NOT NULL */
|
||||||
InvalidOid); /* typcollation */
|
InvalidOid); /* type's collation */
|
||||||
|
|
||||||
/* Enter the enum's values into pg_enum */
|
/* Enter the enum's values into pg_enum */
|
||||||
EnumValuesCreate(enumTypeOid, stmt->vals);
|
EnumValuesCreate(enumTypeOid, stmt->vals);
|
||||||
@ -1219,7 +1219,7 @@ DefineEnum(CreateEnumStmt *stmt)
|
|||||||
-1, /* typMod (Domains only) */
|
-1, /* typMod (Domains only) */
|
||||||
0, /* Array dimensions of typbasetype */
|
0, /* Array dimensions of typbasetype */
|
||||||
false, /* Type NOT NULL */
|
false, /* Type NOT NULL */
|
||||||
InvalidOid); /* typcollation */
|
InvalidOid); /* type's collation */
|
||||||
|
|
||||||
pfree(enumArrayName);
|
pfree(enumArrayName);
|
||||||
}
|
}
|
||||||
|
@ -170,13 +170,13 @@ typedef enum
|
|||||||
* the two expressions from the original clause.
|
* the two expressions from the original clause.
|
||||||
*
|
*
|
||||||
* In addition to the expressions themselves, the planner passes the btree
|
* In addition to the expressions themselves, the planner passes the btree
|
||||||
* opfamily OID, btree strategy number (BTLessStrategyNumber or
|
* opfamily OID, collation OID, btree strategy number (BTLessStrategyNumber or
|
||||||
* BTGreaterStrategyNumber), and nulls-first flag that identify the intended
|
* BTGreaterStrategyNumber), and nulls-first flag that identify the intended
|
||||||
* sort ordering for each merge key. The mergejoinable operator is an
|
* sort ordering for each merge key. The mergejoinable operator is an
|
||||||
* equality operator in this opfamily, and the two inputs are guaranteed to be
|
* equality operator in the opfamily, and the two inputs are guaranteed to be
|
||||||
* ordered in either increasing or decreasing (respectively) order according
|
* ordered in either increasing or decreasing (respectively) order according
|
||||||
* to this opfamily, with nulls at the indicated end of the range. This
|
* to the opfamily and collation, with nulls at the indicated end of the range.
|
||||||
* allows us to obtain the needed comparison function from the opfamily.
|
* This allows us to obtain the needed comparison function from the opfamily.
|
||||||
*/
|
*/
|
||||||
static MergeJoinClause
|
static MergeJoinClause
|
||||||
MJExamineQuals(List *mergeclauses,
|
MJExamineQuals(List *mergeclauses,
|
||||||
|
@ -108,7 +108,8 @@ static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
|
|||||||
List *tidquals);
|
List *tidquals);
|
||||||
static FunctionScan *make_functionscan(List *qptlist, List *qpqual,
|
static FunctionScan *make_functionscan(List *qptlist, List *qpqual,
|
||||||
Index scanrelid, Node *funcexpr, List *funccolnames,
|
Index scanrelid, Node *funcexpr, List *funccolnames,
|
||||||
List *funccoltypes, List *funccoltypmods, List *funccolcollations);
|
List *funccoltypes, List *funccoltypmods,
|
||||||
|
List *funccolcollations);
|
||||||
static ValuesScan *make_valuesscan(List *qptlist, List *qpqual,
|
static ValuesScan *make_valuesscan(List *qptlist, List *qpqual,
|
||||||
Index scanrelid, List *values_lists);
|
Index scanrelid, List *values_lists);
|
||||||
static CteScan *make_ctescan(List *qptlist, List *qpqual,
|
static CteScan *make_ctescan(List *qptlist, List *qpqual,
|
||||||
@ -143,9 +144,9 @@ static MergeJoin *make_mergejoin(List *tlist,
|
|||||||
bool *mergenullsfirst,
|
bool *mergenullsfirst,
|
||||||
Plan *lefttree, Plan *righttree,
|
Plan *lefttree, Plan *righttree,
|
||||||
JoinType jointype);
|
JoinType jointype);
|
||||||
static Sort *
|
static Sort *make_sort(PlannerInfo *root, Plan *lefttree, int numCols,
|
||||||
make_sort(PlannerInfo *root, Plan *lefttree, int numCols,
|
AttrNumber *sortColIdx, Oid *sortOperators,
|
||||||
AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst,
|
Oid *collations, bool *nullsFirst,
|
||||||
double limit_tuples);
|
double limit_tuples);
|
||||||
static Plan *prepare_sort_from_pathkeys(PlannerInfo *root,
|
static Plan *prepare_sort_from_pathkeys(PlannerInfo *root,
|
||||||
Plan *lefttree, List *pathkeys,
|
Plan *lefttree, List *pathkeys,
|
||||||
@ -738,7 +739,8 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path)
|
|||||||
/* Now, insert a Sort node if subplan isn't sufficiently ordered */
|
/* Now, insert a Sort node if subplan isn't sufficiently ordered */
|
||||||
if (!pathkeys_contained_in(pathkeys, subpath->pathkeys))
|
if (!pathkeys_contained_in(pathkeys, subpath->pathkeys))
|
||||||
subplan = (Plan *) make_sort(root, subplan, numsortkeys,
|
subplan = (Plan *) make_sort(root, subplan, numsortkeys,
|
||||||
sortColIdx, sortOperators, collations, nullsFirst,
|
sortColIdx, sortOperators,
|
||||||
|
collations, nullsFirst,
|
||||||
best_path->limit_tuples);
|
best_path->limit_tuples);
|
||||||
|
|
||||||
subplans = lappend(subplans, subplan);
|
subplans = lappend(subplans, subplan);
|
||||||
@ -2013,10 +2015,10 @@ create_mergejoin_plan(PlannerInfo *root,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute the opfamily/strategy/nullsfirst arrays needed by the executor.
|
* Compute the opfamily/collation/strategy/nullsfirst arrays needed by the
|
||||||
* The information is in the pathkeys for the two inputs, but we need to
|
* executor. The information is in the pathkeys for the two inputs, but
|
||||||
* be careful about the possibility of mergeclauses sharing a pathkey
|
* we need to be careful about the possibility of mergeclauses sharing a
|
||||||
* (compare find_mergeclauses_for_pathkeys()).
|
* pathkey (compare find_mergeclauses_for_pathkeys()).
|
||||||
*/
|
*/
|
||||||
nClauses = list_length(mergeclauses);
|
nClauses = list_length(mergeclauses);
|
||||||
Assert(nClauses == list_length(best_path->path_mergeclauses));
|
Assert(nClauses == list_length(best_path->path_mergeclauses));
|
||||||
@ -3316,13 +3318,14 @@ make_mergejoin(List *tlist,
|
|||||||
/*
|
/*
|
||||||
* make_sort --- basic routine to build a Sort plan node
|
* make_sort --- basic routine to build a Sort plan node
|
||||||
*
|
*
|
||||||
* Caller must have built the sortColIdx, sortOperators, and nullsFirst
|
* Caller must have built the sortColIdx, sortOperators, collations, and
|
||||||
* arrays already. limit_tuples is as for cost_sort (in particular, pass
|
* nullsFirst arrays already.
|
||||||
* -1 if no limit)
|
* limit_tuples is as for cost_sort (in particular, pass -1 if no limit)
|
||||||
*/
|
*/
|
||||||
static Sort *
|
static Sort *
|
||||||
make_sort(PlannerInfo *root, Plan *lefttree, int numCols,
|
make_sort(PlannerInfo *root, Plan *lefttree, int numCols,
|
||||||
AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst,
|
AttrNumber *sortColIdx, Oid *sortOperators,
|
||||||
|
Oid *collations, bool *nullsFirst,
|
||||||
double limit_tuples)
|
double limit_tuples)
|
||||||
{
|
{
|
||||||
Sort *node = makeNode(Sort);
|
Sort *node = makeNode(Sort);
|
||||||
@ -3378,6 +3381,11 @@ add_sort_column(AttrNumber colIdx, Oid sortOp, Oid coll, bool nulls_first,
|
|||||||
* values that < considers equal. We need not check nulls_first
|
* values that < considers equal. We need not check nulls_first
|
||||||
* however because a lower-order column with the same sortop but
|
* however because a lower-order column with the same sortop but
|
||||||
* opposite nulls direction is redundant.
|
* opposite nulls direction is redundant.
|
||||||
|
*
|
||||||
|
* We could probably consider sort keys with the same sortop and
|
||||||
|
* different collations to be redundant too, but for the moment
|
||||||
|
* treat them as not redundant. This will be needed if we ever
|
||||||
|
* support collations with different notions of equality.
|
||||||
*/
|
*/
|
||||||
if (sortColIdx[i] == colIdx &&
|
if (sortColIdx[i] == colIdx &&
|
||||||
sortOperators[numCols] == sortOp &&
|
sortOperators[numCols] == sortOp &&
|
||||||
@ -3410,8 +3418,9 @@ add_sort_column(AttrNumber colIdx, Oid sortOp, Oid coll, bool nulls_first,
|
|||||||
* 'adjust_tlist_in_place' is TRUE if lefttree must be modified in-place
|
* 'adjust_tlist_in_place' is TRUE if lefttree must be modified in-place
|
||||||
*
|
*
|
||||||
* We must convert the pathkey information into arrays of sort key column
|
* We must convert the pathkey information into arrays of sort key column
|
||||||
* numbers and sort operator OIDs, which is the representation the executor
|
* numbers, sort operator OIDs, collation OIDs, and nulls-first flags,
|
||||||
* wants. These are returned into the output parameters *p_numsortkeys etc.
|
* which is the representation the executor wants. These are returned into
|
||||||
|
* the output parameters *p_numsortkeys etc.
|
||||||
*
|
*
|
||||||
* If the pathkeys include expressions that aren't simple Vars, we will
|
* If the pathkeys include expressions that aren't simple Vars, we will
|
||||||
* usually need to add resjunk items to the input plan's targetlist to
|
* usually need to add resjunk items to the input plan's targetlist to
|
||||||
@ -3610,7 +3619,8 @@ prepare_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys,
|
|||||||
pathkey->pk_eclass->ec_collation,
|
pathkey->pk_eclass->ec_collation,
|
||||||
pathkey->pk_nulls_first,
|
pathkey->pk_nulls_first,
|
||||||
numsortkeys,
|
numsortkeys,
|
||||||
sortColIdx, sortOperators, collations, nullsFirst);
|
sortColIdx, sortOperators,
|
||||||
|
collations, nullsFirst);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(numsortkeys > 0);
|
Assert(numsortkeys > 0);
|
||||||
@ -3655,7 +3665,8 @@ make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys,
|
|||||||
|
|
||||||
/* Now build the Sort node */
|
/* Now build the Sort node */
|
||||||
return make_sort(root, lefttree, numsortkeys,
|
return make_sort(root, lefttree, numsortkeys,
|
||||||
sortColIdx, sortOperators, collations, nullsFirst, limit_tuples);
|
sortColIdx, sortOperators, collations,
|
||||||
|
nullsFirst, limit_tuples);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3701,13 +3712,15 @@ make_sort_from_sortclauses(PlannerInfo *root, List *sortcls, Plan *lefttree)
|
|||||||
exprCollation((Node *) tle->expr),
|
exprCollation((Node *) tle->expr),
|
||||||
sortcl->nulls_first,
|
sortcl->nulls_first,
|
||||||
numsortkeys,
|
numsortkeys,
|
||||||
sortColIdx, sortOperators, collations, nullsFirst);
|
sortColIdx, sortOperators,
|
||||||
|
collations, nullsFirst);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(numsortkeys > 0);
|
Assert(numsortkeys > 0);
|
||||||
|
|
||||||
return make_sort(root, lefttree, numsortkeys,
|
return make_sort(root, lefttree, numsortkeys,
|
||||||
sortColIdx, sortOperators, collations, nullsFirst, -1.0);
|
sortColIdx, sortOperators, collations,
|
||||||
|
nullsFirst, -1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3763,14 +3776,16 @@ make_sort_from_groupcols(PlannerInfo *root,
|
|||||||
exprCollation((Node *) tle->expr),
|
exprCollation((Node *) tle->expr),
|
||||||
grpcl->nulls_first,
|
grpcl->nulls_first,
|
||||||
numsortkeys,
|
numsortkeys,
|
||||||
sortColIdx, sortOperators, collations, nullsFirst);
|
sortColIdx, sortOperators,
|
||||||
|
collations, nullsFirst);
|
||||||
grpno++;
|
grpno++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(numsortkeys > 0);
|
Assert(numsortkeys > 0);
|
||||||
|
|
||||||
return make_sort(root, lefttree, numsortkeys,
|
return make_sort(root, lefttree, numsortkeys,
|
||||||
sortColIdx, sortOperators, collations, nullsFirst, -1.0);
|
sortColIdx, sortOperators, collations,
|
||||||
|
nullsFirst, -1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Material *
|
static Material *
|
||||||
|
@ -281,7 +281,7 @@ SS_assign_special_param(PlannerInfo *root)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the datatype of the first column of the plan's output.
|
* Get the datatype/typmod/collation of the first column of the plan's output.
|
||||||
*
|
*
|
||||||
* This information is stored for ARRAY_SUBLINK execution and for
|
* This information is stored for ARRAY_SUBLINK execution and for
|
||||||
* exprType()/exprTypmod()/exprCollation(), which have no way to get at the
|
* exprType()/exprTypmod()/exprCollation(), which have no way to get at the
|
||||||
@ -290,7 +290,8 @@ SS_assign_special_param(PlannerInfo *root)
|
|||||||
* always.
|
* always.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
get_first_col_type(Plan *plan, Oid *coltype, int32 *coltypmod, Oid *colcollation)
|
get_first_col_type(Plan *plan, Oid *coltype, int32 *coltypmod,
|
||||||
|
Oid *colcollation)
|
||||||
{
|
{
|
||||||
/* In cases such as EXISTS, tlist might be empty; arbitrarily use VOID */
|
/* In cases such as EXISTS, tlist might be empty; arbitrarily use VOID */
|
||||||
if (plan->targetlist)
|
if (plan->targetlist)
|
||||||
@ -478,7 +479,8 @@ build_subplan(PlannerInfo *root, Plan *plan, List *rtable, List *rowmarks,
|
|||||||
splan->subLinkType = subLinkType;
|
splan->subLinkType = subLinkType;
|
||||||
splan->testexpr = NULL;
|
splan->testexpr = NULL;
|
||||||
splan->paramIds = NIL;
|
splan->paramIds = NIL;
|
||||||
get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod, &splan->firstColCollation);
|
get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod,
|
||||||
|
&splan->firstColCollation);
|
||||||
splan->useHashTable = false;
|
splan->useHashTable = false;
|
||||||
splan->unknownEqFalse = unknownEqFalse;
|
splan->unknownEqFalse = unknownEqFalse;
|
||||||
splan->setParam = NIL;
|
splan->setParam = NIL;
|
||||||
@ -976,7 +978,8 @@ SS_process_ctes(PlannerInfo *root)
|
|||||||
splan->subLinkType = CTE_SUBLINK;
|
splan->subLinkType = CTE_SUBLINK;
|
||||||
splan->testexpr = NULL;
|
splan->testexpr = NULL;
|
||||||
splan->paramIds = NIL;
|
splan->paramIds = NIL;
|
||||||
get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod, &splan->firstColCollation);
|
get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod,
|
||||||
|
&splan->firstColCollation);
|
||||||
splan->useHashTable = false;
|
splan->useHashTable = false;
|
||||||
splan->unknownEqFalse = false;
|
splan->unknownEqFalse = false;
|
||||||
splan->setParam = NIL;
|
splan->setParam = NIL;
|
||||||
|
@ -1357,9 +1357,9 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate dummy targetlist for outer query using column names of
|
* Generate dummy targetlist for outer query using column names of
|
||||||
* leftmost select and common datatypes of topmost set operation. Also
|
* leftmost select and common datatypes/collations of topmost set
|
||||||
* make lists of the dummy vars and their names for use in parsing ORDER
|
* operation. Also make lists of the dummy vars and their names for use
|
||||||
* BY.
|
* in parsing ORDER BY.
|
||||||
*
|
*
|
||||||
* Note: we use leftmostRTI as the varno of the dummy variables. It
|
* Note: we use leftmostRTI as the varno of the dummy variables. It
|
||||||
* shouldn't matter too much which RT index they have, as long as they
|
* shouldn't matter too much which RT index they have, as long as they
|
||||||
@ -1371,7 +1371,9 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
|||||||
targetnames = NIL;
|
targetnames = NIL;
|
||||||
left_tlist = list_head(leftmostQuery->targetList);
|
left_tlist = list_head(leftmostQuery->targetList);
|
||||||
|
|
||||||
forthree(lct, sostmt->colTypes, lcm, sostmt->colTypmods, lcc, sostmt->colCollations)
|
forthree(lct, sostmt->colTypes,
|
||||||
|
lcm, sostmt->colTypmods,
|
||||||
|
lcc, sostmt->colCollations)
|
||||||
{
|
{
|
||||||
Oid colType = lfirst_oid(lct);
|
Oid colType = lfirst_oid(lct);
|
||||||
int32 colTypmod = lfirst_int(lcm);
|
int32 colTypmod = lfirst_int(lcm);
|
||||||
|
@ -286,10 +286,10 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Verify that the previously determined output column types match
|
* Verify that the previously determined output column types and
|
||||||
* what the query really produced. We have to check this because the
|
* collations match what the query really produced. We have to check
|
||||||
* recursive term could have overridden the non-recursive term, and we
|
* this because the recursive term could have overridden the
|
||||||
* don't have any easy way to fix that.
|
* non-recursive term, and we don't have any easy way to fix that.
|
||||||
*/
|
*/
|
||||||
ListCell *lctlist,
|
ListCell *lctlist,
|
||||||
*lctyp,
|
*lctyp,
|
||||||
@ -366,11 +366,11 @@ analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist)
|
|||||||
Assert(cte->ctecolnames == NIL);
|
Assert(cte->ctecolnames == NIL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to determine column names and types. The alias column names
|
* We need to determine column names, types, and collations. The alias
|
||||||
* override anything coming from the query itself. (Note: the SQL spec
|
* column names override anything coming from the query itself. (Note:
|
||||||
* says that the alias list must be empty or exactly as long as the output
|
* the SQL spec says that the alias list must be empty or exactly as long
|
||||||
* column set; but we allow it to be shorter for consistency with Alias
|
* as the output column set; but we allow it to be shorter for consistency
|
||||||
* handling.)
|
* with Alias handling.)
|
||||||
*/
|
*/
|
||||||
cte->ctecolnames = copyObject(cte->aliascolnames);
|
cte->ctecolnames = copyObject(cte->aliascolnames);
|
||||||
cte->ctecoltypes = cte->ctecoltypmods = cte->ctecolcollations = NIL;
|
cte->ctecoltypes = cte->ctecoltypmods = cte->ctecolcollations = NIL;
|
||||||
|
@ -1174,7 +1174,8 @@ addRangeTableEntryForFunction(ParseState *pstate,
|
|||||||
eref->colnames = lappend(eref->colnames, makeString(attrname));
|
eref->colnames = lappend(eref->colnames, makeString(attrname));
|
||||||
rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype);
|
rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype);
|
||||||
rte->funccoltypmods = lappend_int(rte->funccoltypmods, attrtypmod);
|
rte->funccoltypmods = lappend_int(rte->funccoltypmods, attrtypmod);
|
||||||
rte->funccolcollations = lappend_oid(rte->funccolcollations, attrcollation);
|
rte->funccolcollations = lappend_oid(rte->funccolcollations,
|
||||||
|
attrcollation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1902,7 +1903,8 @@ expandTupleDesc(TupleDesc tupdesc, Alias *eref,
|
|||||||
Var *varnode;
|
Var *varnode;
|
||||||
|
|
||||||
varnode = makeVar(rtindex, attr->attnum,
|
varnode = makeVar(rtindex, attr->attnum,
|
||||||
attr->atttypid, attr->atttypmod, attr->attcollation,
|
attr->atttypid, attr->atttypmod,
|
||||||
|
attr->attcollation,
|
||||||
sublevels_up);
|
sublevels_up);
|
||||||
varnode->location = location;
|
varnode->location = location;
|
||||||
|
|
||||||
@ -2009,7 +2011,7 @@ get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* get_rte_attribute_type
|
* get_rte_attribute_type
|
||||||
* Get attribute type information from a RangeTblEntry
|
* Get attribute type/typmod/collation information from a RangeTblEntry
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||||
|
@ -372,7 +372,7 @@ transformAssignedExpr(ParseState *pstate,
|
|||||||
Oid type_id; /* type of value provided */
|
Oid type_id; /* type of value provided */
|
||||||
Oid attrtype; /* type of target column */
|
Oid attrtype; /* type of target column */
|
||||||
int32 attrtypmod;
|
int32 attrtypmod;
|
||||||
Oid attrcollation;
|
Oid attrcollation; /* collation of target column */
|
||||||
Relation rd = pstate->p_target_relation;
|
Relation rd = pstate->p_target_relation;
|
||||||
|
|
||||||
Assert(rd != NULL);
|
Assert(rd != NULL);
|
||||||
@ -388,11 +388,12 @@ transformAssignedExpr(ParseState *pstate,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* If the expression is a DEFAULT placeholder, insert the attribute's
|
* If the expression is a DEFAULT placeholder, insert the attribute's
|
||||||
* type/typmod into it so that exprType will report the right things. (We
|
* type/typmod/collation into it so that exprType etc will report the
|
||||||
* expect that the eventually substituted default expression will in fact
|
* right things. (We expect that the eventually substituted default
|
||||||
* have this type and typmod.) Also, reject trying to update a subfield
|
* expression will in fact have this type and typmod. The collation
|
||||||
* or array element with DEFAULT, since there can't be any default for
|
* likely doesn't matter, but let's set it correctly anyway.) Also,
|
||||||
* portions of a column.
|
* reject trying to update a subfield or array element with DEFAULT, since
|
||||||
|
* there can't be any default for portions of a column.
|
||||||
*/
|
*/
|
||||||
if (expr && IsA(expr, SetToDefault))
|
if (expr && IsA(expr, SetToDefault))
|
||||||
{
|
{
|
||||||
|
@ -235,7 +235,8 @@ static void get_from_clause_item(Node *jtnode, Query *query,
|
|||||||
deparse_context *context);
|
deparse_context *context);
|
||||||
static void get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
|
static void get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
|
||||||
deparse_context *context);
|
deparse_context *context);
|
||||||
static void get_from_clause_coldeflist(List *names, List *types, List *typmods, List *collations,
|
static void get_from_clause_coldeflist(List *names,
|
||||||
|
List *types, List *typmods, List *collations,
|
||||||
deparse_context *context);
|
deparse_context *context);
|
||||||
static void get_opclass_name(Oid opclass, Oid actual_datatype,
|
static void get_opclass_name(Oid opclass, Oid actual_datatype,
|
||||||
StringInfo buf);
|
StringInfo buf);
|
||||||
@ -6617,7 +6618,8 @@ get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
|
|||||||
* responsible for ensuring that an alias or AS is present before it.
|
* responsible for ensuring that an alias or AS is present before it.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
get_from_clause_coldeflist(List *names, List *types, List *typmods, List *collations,
|
get_from_clause_coldeflist(List *names,
|
||||||
|
List *types, List *typmods, List *collations,
|
||||||
deparse_context *context)
|
deparse_context *context)
|
||||||
{
|
{
|
||||||
StringInfo buf = context->buf;
|
StringInfo buf = context->buf;
|
||||||
@ -6651,7 +6653,8 @@ get_from_clause_coldeflist(List *names, List *types, List *typmods, List *collat
|
|||||||
appendStringInfo(buf, "%s %s",
|
appendStringInfo(buf, "%s %s",
|
||||||
quote_identifier(attname),
|
quote_identifier(attname),
|
||||||
format_type_with_typemod(atttypid, atttypmod));
|
format_type_with_typemod(atttypid, atttypmod));
|
||||||
if (attcollation && attcollation != DEFAULT_COLLATION_OID)
|
if (OidIsValid(attcollation) &&
|
||||||
|
attcollation != get_typcollation(atttypid))
|
||||||
appendStringInfo(buf, " COLLATE %s",
|
appendStringInfo(buf, " COLLATE %s",
|
||||||
generate_collation_name(attcollation));
|
generate_collation_name(attcollation));
|
||||||
i++;
|
i++;
|
||||||
|
4
src/backend/utils/cache/syscache.c
vendored
4
src/backend/utils/cache/syscache.c
vendored
@ -277,7 +277,7 @@ static const struct cachedesc cacheinfo[] = {
|
|||||||
Anum_pg_collation_collnamespace,
|
Anum_pg_collation_collnamespace,
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
256
|
64
|
||||||
},
|
},
|
||||||
{CollationRelationId, /* COLLOID */
|
{CollationRelationId, /* COLLOID */
|
||||||
CollationOidIndexId,
|
CollationOidIndexId,
|
||||||
@ -288,7 +288,7 @@ static const struct cachedesc cacheinfo[] = {
|
|||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
256
|
64
|
||||||
},
|
},
|
||||||
{ConversionRelationId, /* CONDEFAULT */
|
{ConversionRelationId, /* CONDEFAULT */
|
||||||
ConversionDefaultIndexId,
|
ConversionDefaultIndexId,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user