Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3bba9ce

Browse files
committed
Clean up handling of COLLATE clauses in index column definitions.
Ensure that COLLATE at the top level of an index expression is treated thesame as a grammatically separate COLLATE. Fix bogus reverse-parsing logicin pg_get_indexdef.
1 parent472671e commit3bba9ce

File tree

6 files changed

+94
-70
lines changed

6 files changed

+94
-70
lines changed

‎src/backend/commands/indexcmds.c

Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -837,49 +837,62 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
837837
attcollation=attform->attcollation;
838838
ReleaseSysCache(atttuple);
839839
}
840-
elseif (attribute->expr&&IsA(attribute->expr,Var)&&
841-
((Var*)attribute->expr)->varattno!=InvalidAttrNumber)
842-
{
843-
/* Tricky tricky, he wrote (column) ... treat as simple attr */
844-
Var*var= (Var*)attribute->expr;
845-
846-
indexInfo->ii_KeyAttrNumbers[attn]=var->varattno;
847-
atttype=get_atttype(relId,var->varattno);
848-
attcollation=var->varcollid;
849-
}
850840
else
851841
{
852842
/* Index expression */
853-
Assert(attribute->expr!=NULL);
854-
indexInfo->ii_KeyAttrNumbers[attn]=0;/* marks expression */
855-
indexInfo->ii_Expressions=lappend(indexInfo->ii_Expressions,
856-
attribute->expr);
857-
atttype=exprType(attribute->expr);
858-
attcollation=exprCollation(attribute->expr);
843+
Node*expr=attribute->expr;
859844

860-
/*
861-
* We don't currently support generation of an actual query plan
862-
* for an index expression, only simple scalar expressions; hence
863-
* these restrictions.
864-
*/
865-
if (contain_subplans(attribute->expr))
866-
ereport(ERROR,
867-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
868-
errmsg("cannot use subquery in index expression")));
869-
if (contain_agg_clause(attribute->expr))
870-
ereport(ERROR,
871-
(errcode(ERRCODE_GROUPING_ERROR),
872-
errmsg("cannot use aggregate function in index expression")));
845+
Assert(expr!=NULL);
846+
atttype=exprType(expr);
847+
attcollation=exprCollation(expr);
873848

874849
/*
875-
* A expression using mutable functions is probably wrong, since
876-
* if you aren't going to get the same result for the same data
877-
* every time, it's not clear what the index entries mean at all.
850+
* Strip any top-level COLLATE clause. This ensures that we treat
851+
* "x COLLATE y" and "(x COLLATE y)" alike.
878852
*/
879-
if (CheckMutability((Expr*)attribute->expr))
880-
ereport(ERROR,
881-
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
882-
errmsg("functions in index expression must be marked IMMUTABLE")));
853+
while (IsA(expr,CollateExpr))
854+
expr= (Node*) ((CollateExpr*)expr)->arg;
855+
856+
if (IsA(expr,Var)&&
857+
((Var*)expr)->varattno!=InvalidAttrNumber)
858+
{
859+
/*
860+
* User wrote "(column)" or "(column COLLATE something)".
861+
* Treat it like simple attribute anyway.
862+
*/
863+
indexInfo->ii_KeyAttrNumbers[attn]= ((Var*)expr)->varattno;
864+
}
865+
else
866+
{
867+
indexInfo->ii_KeyAttrNumbers[attn]=0;/* marks expression */
868+
indexInfo->ii_Expressions=lappend(indexInfo->ii_Expressions,
869+
expr);
870+
871+
/*
872+
* We don't currently support generation of an actual query
873+
* plan for an index expression, only simple scalar
874+
* expressions; hence these restrictions.
875+
*/
876+
if (contain_subplans(expr))
877+
ereport(ERROR,
878+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
879+
errmsg("cannot use subquery in index expression")));
880+
if (contain_agg_clause(expr))
881+
ereport(ERROR,
882+
(errcode(ERRCODE_GROUPING_ERROR),
883+
errmsg("cannot use aggregate function in index expression")));
884+
885+
/*
886+
* A expression using mutable functions is probably wrong,
887+
* since if you aren't going to get the same result for the
888+
* same data every time, it's not clear what the index entries
889+
* mean at all.
890+
*/
891+
if (CheckMutability((Expr*)expr))
892+
ereport(ERROR,
893+
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
894+
errmsg("functions in index expression must be marked IMMUTABLE")));
895+
}
883896
}
884897

885898
/*

‎src/backend/utils/adt/ruleutils.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,6 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
794794
List*context;
795795
Oidindrelid;
796796
intkeyno;
797-
Oidkeycoltype;
798797
DatumindcollDatum;
799798
DatumindclassDatum;
800799
DatumindoptionDatum;
@@ -902,6 +901,8 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
902901
{
903902
AttrNumberattnum=idxrec->indkey.values[keyno];
904903
int16opt=indoption->values[keyno];
904+
Oidkeycoltype;
905+
Oidkeycolcollation;
905906

906907
if (!colno)
907908
appendStringInfoString(&buf,sep);
@@ -916,6 +917,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
916917
if (!colno||colno==keyno+1)
917918
appendStringInfoString(&buf,quote_identifier(attname));
918919
keycoltype=get_atttype(indrelid,attnum);
920+
keycolcollation=get_attcollation(indrelid,attnum);
919921
}
920922
else
921923
{
@@ -939,16 +941,18 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
939941
appendStringInfo(&buf,"(%s)",str);
940942
}
941943
keycoltype=exprType(indexkey);
944+
keycolcollation=exprCollation(indexkey);
942945
}
943946

944947
if (!attrsOnly&& (!colno||colno==keyno+1))
945948
{
946-
Oidcoll;
949+
Oidindcoll;
947950

948-
/* Add collation, if not default */
949-
coll=indcollation->values[keyno];
950-
if (coll&&coll!=DEFAULT_COLLATION_OID&&coll!=get_attcollation(indrelid,attnum))
951-
appendStringInfo(&buf," COLLATE %s",generate_collation_name((indcollation->values[keyno])));
951+
/* Add collation, if not default for column */
952+
indcoll=indcollation->values[keyno];
953+
if (OidIsValid(indcoll)&&indcoll!=keycolcollation)
954+
appendStringInfo(&buf," COLLATE %s",
955+
generate_collation_name((indcoll)));
952956

953957
/* Add the operator class name, if not default */
954958
get_opclass_name(indclass->values[keyno],keycoltype,&buf);
@@ -6646,7 +6650,8 @@ get_from_clause_coldeflist(List *names, List *types, List *typmods, List *collat
66466650
quote_identifier(attname),
66476651
format_type_with_typemod(atttypid,atttypmod));
66486652
if (attcollation&&attcollation!=DEFAULT_COLLATION_OID)
6649-
appendStringInfo(buf," COLLATE %s",generate_collation_name(attcollation));
6653+
appendStringInfo(buf," COLLATE %s",
6654+
generate_collation_name(attcollation));
66506655
i++;
66516656
}
66526657

‎src/test/regress/expected/collate.linux.utf8.out

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -747,19 +747,21 @@ SELECT a, (dup(b)).* FROM collate_test3 ORDER BY 2;
747747
CREATE INDEX collate_test1_idx1 ON collate_test1 (b);
748748
CREATE INDEX collate_test1_idx2 ON collate_test1 (b COLLATE "C");
749749
CREATE INDEX collate_test1_idx3 ON collate_test1 ((b COLLATE "C")); -- this is different grammatically
750-
CREATE INDEX collate_test1_idx4 ON collate_test1 (a COLLATE "C"); -- fail
750+
CREATE INDEX collate_test1_idx4 ON collate_test1 (((b||'foo') COLLATE "POSIX"));
751+
CREATE INDEX collate_test1_idx5 ON collate_test1 (a COLLATE "C"); -- fail
751752
ERROR: collations are not supported by type integer
752-
CREATE INDEXcollate_test1_idx5 ON collate_test1 ((a COLLATE "C")); -- fail
753+
CREATE INDEXcollate_test1_idx6 ON collate_test1 ((a COLLATE "C")); -- fail
753754
ERROR: collations are not supported by type integer
754-
LINE 1: ...ATE INDEXcollate_test1_idx5 ON collate_test1 ((a COLLATE "C...
755+
LINE 1: ...ATE INDEXcollate_test1_idx6 ON collate_test1 ((a COLLATE "C...
755756
^
756-
SELECT relname, pg_get_indexdef(oid) FROM pg_class WHERE relname LIKE 'collate_test%_idx%';
757-
relname | pg_get_indexdef
758-
--------------------+----------------------------------------------------------------------------------------------
757+
SELECT relname, pg_get_indexdef(oid) FROM pg_class WHERE relname LIKE 'collate_test%_idx%' ORDER BY 1;
758+
relname |pg_get_indexdef
759+
--------------------+-----------------------------------------------------------------------------------------------------
759760
collate_test1_idx1 | CREATE INDEX collate_test1_idx1 ON collate_test1 USING btree (b)
760761
collate_test1_idx2 | CREATE INDEX collate_test1_idx2 ON collate_test1 USING btree (b COLLATE "C")
761-
collate_test1_idx3 | CREATE INDEX collate_test1_idx3 ON collate_test1 USING btree (((b COLLATE "C")) COLLATE "C")
762-
(3 rows)
762+
collate_test1_idx3 | CREATE INDEX collate_test1_idx3 ON collate_test1 USING btree (b COLLATE "C")
763+
collate_test1_idx4 | CREATE INDEX collate_test1_idx4 ON collate_test1 USING btree (((b || 'foo'::text)) COLLATE "POSIX")
764+
(4 rows)
763765

764766
-- schema manipulation commands
765767
CREATE ROLE regress_test_role;

‎src/test/regress/expected/collate.out

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -524,21 +524,23 @@ SELECT a, (dup(b)).* FROM collate_test2 ORDER BY 2;
524524

525525
-- indexes
526526
CREATE INDEX collate_test1_idx1 ON collate_test1 (b);
527-
CREATE INDEX collate_test1_idx2 ON collate_test1 (b COLLATE "C");
528-
CREATE INDEX collate_test1_idx3 ON collate_test1 ((b COLLATE "C")); -- this is different grammatically
529-
CREATE INDEX collate_test1_idx4 ON collate_test1 (a COLLATE "C"); -- fail
527+
CREATE INDEX collate_test1_idx2 ON collate_test1 (b COLLATE "POSIX");
528+
CREATE INDEX collate_test1_idx3 ON collate_test1 ((b COLLATE "POSIX")); -- this is different grammatically
529+
CREATE INDEX collate_test1_idx4 ON collate_test1 (((b||'foo') COLLATE "POSIX"));
530+
CREATE INDEX collate_test1_idx5 ON collate_test1 (a COLLATE "POSIX"); -- fail
530531
ERROR: collations are not supported by type integer
531-
CREATE INDEXcollate_test1_idx5 ON collate_test1 ((a COLLATE "C")); -- fail
532+
CREATE INDEXcollate_test1_idx6 ON collate_test1 ((a COLLATE "POSIX")); -- fail
532533
ERROR: collations are not supported by type integer
533-
LINE 1: ...ATE INDEXcollate_test1_idx5 ON collate_test1 ((a COLLATE "C...
534+
LINE 1: ...ATE INDEXcollate_test1_idx6 ON collate_test1 ((a COLLATE "P...
534535
^
535-
SELECT relname, pg_get_indexdef(oid) FROM pg_class WHERE relname LIKE 'collate_test%_idx%';
536-
relname | pg_get_indexdef
537-
--------------------+----------------------------------------------------------------------------------------------
536+
SELECT relname, pg_get_indexdef(oid) FROM pg_class WHERE relname LIKE 'collate_test%_idx%' ORDER BY 1;
537+
relname |pg_get_indexdef
538+
--------------------+-----------------------------------------------------------------------------------------------------
538539
collate_test1_idx1 | CREATE INDEX collate_test1_idx1 ON collate_test1 USING btree (b)
539-
collate_test1_idx2 | CREATE INDEX collate_test1_idx2 ON collate_test1 USING btree (b)
540-
collate_test1_idx3 | CREATE INDEX collate_test1_idx3 ON collate_test1 USING btree (((b COLLATE "C")) COLLATE "C")
541-
(3 rows)
540+
collate_test1_idx2 | CREATE INDEX collate_test1_idx2 ON collate_test1 USING btree (b COLLATE "POSIX")
541+
collate_test1_idx3 | CREATE INDEX collate_test1_idx3 ON collate_test1 USING btree (b COLLATE "POSIX")
542+
collate_test1_idx4 | CREATE INDEX collate_test1_idx4 ON collate_test1 USING btree (((b || 'foo'::text)) COLLATE "POSIX")
543+
(4 rows)
542544

543545
--
544546
-- Clean up. Many of these table names will be re-used if the user is

‎src/test/regress/sql/collate.linux.utf8.sql

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,11 +231,12 @@ SELECT a, (dup(b)).* FROM collate_test3 ORDER BY 2;
231231
CREATEINDEXcollate_test1_idx1ON collate_test1 (b);
232232
CREATEINDEXcollate_test1_idx2ON collate_test1 (b COLLATE"C");
233233
CREATEINDEXcollate_test1_idx3ON collate_test1 ((b COLLATE"C"));-- this is different grammatically
234+
CREATEINDEXcollate_test1_idx4ON collate_test1 (((b||'foo') COLLATE"POSIX"));
234235

235-
CREATEINDEXcollate_test1_idx4ON collate_test1 (a COLLATE"C");-- fail
236-
CREATEINDEXcollate_test1_idx5ON collate_test1 ((a COLLATE"C"));-- fail
236+
CREATEINDEXcollate_test1_idx5ON collate_test1 (a COLLATE"C");-- fail
237+
CREATEINDEXcollate_test1_idx6ON collate_test1 ((a COLLATE"C"));-- fail
237238

238-
SELECT relname, pg_get_indexdef(oid)FROM pg_classWHERE relnameLIKE'collate_test%_idx%';
239+
SELECT relname, pg_get_indexdef(oid)FROM pg_classWHERE relnameLIKE'collate_test%_idx%'ORDER BY1;
239240

240241

241242
-- schema manipulation commands

‎src/test/regress/sql/collate.sql

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,14 @@ SELECT a, (dup(b)).* FROM collate_test2 ORDER BY 2;
178178
-- indexes
179179

180180
CREATEINDEXcollate_test1_idx1ON collate_test1 (b);
181-
CREATEINDEXcollate_test1_idx2ON collate_test1 (b COLLATE"C");
182-
CREATEINDEXcollate_test1_idx3ON collate_test1 ((b COLLATE"C"));-- this is different grammatically
181+
CREATEINDEXcollate_test1_idx2ON collate_test1 (b COLLATE"POSIX");
182+
CREATEINDEXcollate_test1_idx3ON collate_test1 ((b COLLATE"POSIX"));-- this is different grammatically
183+
CREATEINDEXcollate_test1_idx4ON collate_test1 (((b||'foo') COLLATE"POSIX"));
183184

184-
CREATEINDEXcollate_test1_idx4ON collate_test1 (a COLLATE"C");-- fail
185-
CREATEINDEXcollate_test1_idx5ON collate_test1 ((a COLLATE"C"));-- fail
185+
CREATEINDEXcollate_test1_idx5ON collate_test1 (a COLLATE"POSIX");-- fail
186+
CREATEINDEXcollate_test1_idx6ON collate_test1 ((a COLLATE"POSIX"));-- fail
186187

187-
SELECT relname, pg_get_indexdef(oid)FROM pg_classWHERE relnameLIKE'collate_test%_idx%';
188+
SELECT relname, pg_get_indexdef(oid)FROM pg_classWHERE relnameLIKE'collate_test%_idx%'ORDER BY1;
188189

189190
--
190191
-- Clean up. Many of these table names will be re-used if the user is

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp