00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "postgres.h"
00042
00043 #include "catalog/pg_collation.h"
00044 #include "nodes/nodeFuncs.h"
00045 #include "parser/parse_collate.h"
00046 #include "utils/lsyscache.h"
00047
00048
00049
00050
00051
00052
00053
00054 typedef enum
00055 {
00056 COLLATE_NONE,
00057 COLLATE_IMPLICIT,
00058 COLLATE_CONFLICT,
00059 COLLATE_EXPLICIT
00060 } CollateStrength;
00061
00062 typedef struct
00063 {
00064 ParseState *pstate;
00065 Oid collation;
00066 CollateStrength strength;
00067 int location;
00068
00069 Oid collation2;
00070 int location2;
00071 } assign_collations_context;
00072
00073 static bool assign_query_collations_walker(Node *node, ParseState *pstate);
00074 static bool assign_collations_walker(Node *node,
00075 assign_collations_context *context);
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 void
00087 assign_query_collations(ParseState *pstate, Query *query)
00088 {
00089
00090
00091
00092
00093
00094
00095 (void) query_tree_walker(query,
00096 assign_query_collations_walker,
00097 (void *) pstate,
00098 QTW_IGNORE_RANGE_TABLE |
00099 QTW_IGNORE_CTE_SUBQUERIES);
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 static bool
00112 assign_query_collations_walker(Node *node, ParseState *pstate)
00113 {
00114
00115 if (node == NULL)
00116 return false;
00117
00118
00119
00120
00121
00122 if (IsA(node, SetOperationStmt))
00123 return false;
00124
00125 if (IsA(node, List))
00126 assign_list_collations(pstate, (List *) node);
00127 else
00128 assign_expr_collations(pstate, node);
00129
00130 return false;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140 void
00141 assign_list_collations(ParseState *pstate, List *exprs)
00142 {
00143 ListCell *lc;
00144
00145 foreach(lc, exprs)
00146 {
00147 Node *node = (Node *) lfirst(lc);
00148
00149 assign_expr_collations(pstate, node);
00150 }
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 void
00163 assign_expr_collations(ParseState *pstate, Node *expr)
00164 {
00165 assign_collations_context context;
00166
00167
00168 context.pstate = pstate;
00169 context.collation = InvalidOid;
00170 context.strength = COLLATE_NONE;
00171 context.location = -1;
00172
00173
00174 (void) assign_collations_walker(expr, &context);
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 Oid
00194 select_common_collation(ParseState *pstate, List *exprs, bool none_ok)
00195 {
00196 assign_collations_context context;
00197
00198
00199 context.pstate = pstate;
00200 context.collation = InvalidOid;
00201 context.strength = COLLATE_NONE;
00202 context.location = -1;
00203
00204
00205 (void) assign_collations_walker((Node *) exprs, &context);
00206
00207
00208 if (context.strength == COLLATE_CONFLICT)
00209 {
00210 if (none_ok)
00211 return InvalidOid;
00212 ereport(ERROR,
00213 (errcode(ERRCODE_COLLATION_MISMATCH),
00214 errmsg("collation mismatch between implicit collations \"%s\" and \"%s\"",
00215 get_collation_name(context.collation),
00216 get_collation_name(context.collation2)),
00217 errhint("You can choose the collation by applying the COLLATE clause to one or both expressions."),
00218 parser_errposition(context.pstate, context.location2)));
00219 }
00220
00221
00222
00223
00224
00225
00226 return context.collation;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 static bool
00241 assign_collations_walker(Node *node, assign_collations_context *context)
00242 {
00243 assign_collations_context loccontext;
00244 Oid collation;
00245 CollateStrength strength;
00246 int location;
00247
00248
00249 if (node == NULL)
00250 return false;
00251
00252
00253
00254
00255
00256
00257 loccontext.pstate = context->pstate;
00258 loccontext.collation = InvalidOid;
00259 loccontext.strength = COLLATE_NONE;
00260 loccontext.location = -1;
00261
00262
00263
00264
00265
00266
00267
00268 switch (nodeTag(node))
00269 {
00270 case T_CollateExpr:
00271 {
00272
00273
00274
00275
00276
00277 CollateExpr *expr = (CollateExpr *) node;
00278
00279 (void) expression_tree_walker(node,
00280 assign_collations_walker,
00281 (void *) &loccontext);
00282
00283 collation = expr->collOid;
00284 Assert(OidIsValid(collation));
00285 strength = COLLATE_EXPLICIT;
00286 location = expr->location;
00287 }
00288 break;
00289 case T_FieldSelect:
00290 {
00291
00292
00293
00294
00295
00296
00297
00298 FieldSelect *expr = (FieldSelect *) node;
00299
00300
00301 (void) expression_tree_walker(node,
00302 assign_collations_walker,
00303 (void *) &loccontext);
00304
00305 if (OidIsValid(expr->resultcollid))
00306 {
00307
00308
00309 collation = expr->resultcollid;
00310 strength = COLLATE_IMPLICIT;
00311 location = exprLocation(node);
00312 }
00313 else
00314 {
00315
00316 collation = InvalidOid;
00317 strength = COLLATE_NONE;
00318 location = -1;
00319 }
00320 }
00321 break;
00322 case T_RowExpr:
00323 {
00324
00325
00326
00327
00328
00329 RowExpr *expr = (RowExpr *) node;
00330
00331 assign_list_collations(context->pstate, expr->args);
00332
00333
00334
00335
00336
00337
00338 return false;
00339 }
00340 case T_RowCompareExpr:
00341 {
00342
00343
00344
00345
00346
00347
00348 RowCompareExpr *expr = (RowCompareExpr *) node;
00349 List *colls = NIL;
00350 ListCell *l;
00351 ListCell *r;
00352
00353 forboth(l, expr->largs, r, expr->rargs)
00354 {
00355 Node *le = (Node *) lfirst(l);
00356 Node *re = (Node *) lfirst(r);
00357 Oid coll;
00358
00359 coll = select_common_collation(context->pstate,
00360 list_make2(le, re),
00361 true);
00362 colls = lappend_oid(colls, coll);
00363 }
00364 expr->inputcollids = colls;
00365
00366
00367
00368
00369
00370
00371 return false;
00372 }
00373 case T_CoerceToDomain:
00374 {
00375
00376
00377
00378
00379
00380
00381
00382
00383 CoerceToDomain *expr = (CoerceToDomain *) node;
00384 Oid typcollation = get_typcollation(expr->resulttype);
00385
00386
00387 (void) expression_tree_walker(node,
00388 assign_collations_walker,
00389 (void *) &loccontext);
00390
00391 if (OidIsValid(typcollation))
00392 {
00393
00394 if (typcollation == DEFAULT_COLLATION_OID)
00395 {
00396
00397 collation = loccontext.collation;
00398 strength = loccontext.strength;
00399 location = loccontext.location;
00400 }
00401 else
00402 {
00403
00404 collation = typcollation;
00405 strength = COLLATE_IMPLICIT;
00406 location = exprLocation(node);
00407 }
00408 }
00409 else
00410 {
00411
00412 collation = InvalidOid;
00413 strength = COLLATE_NONE;
00414 location = -1;
00415 }
00416
00417
00418
00419
00420
00421 if (strength == COLLATE_CONFLICT)
00422 exprSetCollation(node, InvalidOid);
00423 else
00424 exprSetCollation(node, collation);
00425 }
00426 break;
00427 case T_TargetEntry:
00428 (void) expression_tree_walker(node,
00429 assign_collations_walker,
00430 (void *) &loccontext);
00431
00432
00433
00434
00435
00436
00437 collation = loccontext.collation;
00438 strength = loccontext.strength;
00439 location = loccontext.location;
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 if (strength == COLLATE_CONFLICT &&
00455 ((TargetEntry *) node)->ressortgroupref != 0)
00456 ereport(ERROR,
00457 (errcode(ERRCODE_COLLATION_MISMATCH),
00458 errmsg("collation mismatch between implicit collations \"%s\" and \"%s\"",
00459 get_collation_name(loccontext.collation),
00460 get_collation_name(loccontext.collation2)),
00461 errhint("You can choose the collation by applying the COLLATE clause to one or both expressions."),
00462 parser_errposition(context->pstate,
00463 loccontext.location2)));
00464 break;
00465 case T_RangeTblRef:
00466 case T_JoinExpr:
00467 case T_FromExpr:
00468 case T_SortGroupClause:
00469 (void) expression_tree_walker(node,
00470 assign_collations_walker,
00471 (void *) &loccontext);
00472
00473
00474
00475
00476
00477
00478
00479 return false;
00480 case T_Query:
00481 {
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 Query *qtree = (Query *) node;
00492 TargetEntry *tent;
00493
00494 tent = (TargetEntry *) linitial(qtree->targetList);
00495 Assert(IsA(tent, TargetEntry));
00496 Assert(!tent->resjunk);
00497 collation = exprCollation((Node *) tent->expr);
00498
00499 strength = COLLATE_IMPLICIT;
00500 location = exprLocation((Node *) tent->expr);
00501 }
00502 break;
00503 case T_List:
00504 (void) expression_tree_walker(node,
00505 assign_collations_walker,
00506 (void *) &loccontext);
00507
00508
00509
00510
00511
00512 collation = loccontext.collation;
00513 strength = loccontext.strength;
00514 location = loccontext.location;
00515 break;
00516
00517 case T_Var:
00518 case T_Const:
00519 case T_Param:
00520 case T_CoerceToDomainValue:
00521 case T_CaseTestExpr:
00522 case T_SetToDefault:
00523 case T_CurrentOfExpr:
00524
00525
00526
00527
00528
00529
00530
00531 collation = exprCollation(node);
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 if (OidIsValid(collation))
00543 strength = COLLATE_IMPLICIT;
00544 else
00545 strength = COLLATE_NONE;
00546 location = exprLocation(node);
00547 break;
00548
00549 default:
00550 {
00551
00552
00553
00554
00555 Oid typcollation;
00556
00557
00558
00559
00560
00561
00562 switch (nodeTag(node))
00563 {
00564 case T_Aggref:
00565 {
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 Aggref *aggref = (Aggref *) node;
00584 ListCell *lc;
00585
00586 foreach(lc, aggref->args)
00587 {
00588 TargetEntry *tle = (TargetEntry *) lfirst(lc);
00589
00590 Assert(IsA(tle, TargetEntry));
00591 if (tle->resjunk)
00592 assign_expr_collations(context->pstate,
00593 (Node *) tle);
00594 else
00595 (void) assign_collations_walker((Node *) tle,
00596 &loccontext);
00597 }
00598 }
00599 break;
00600 case T_CaseExpr:
00601 {
00602
00603
00604
00605
00606
00607
00608
00609
00610 CaseExpr *expr = (CaseExpr *) node;
00611 ListCell *lc;
00612
00613 foreach(lc, expr->args)
00614 {
00615 CaseWhen *when = (CaseWhen *) lfirst(lc);
00616
00617 Assert(IsA(when, CaseWhen));
00618
00619
00620
00621
00622
00623
00624
00625
00626 (void) assign_collations_walker((Node *) when->expr,
00627 &loccontext);
00628 (void) assign_collations_walker((Node *) when->result,
00629 &loccontext);
00630 }
00631 (void) assign_collations_walker((Node *) expr->defresult,
00632 &loccontext);
00633 }
00634 break;
00635 default:
00636
00637
00638
00639
00640
00641 (void) expression_tree_walker(node,
00642 assign_collations_walker,
00643 (void *) &loccontext);
00644 break;
00645 }
00646
00647
00648
00649
00650 typcollation = get_typcollation(exprType(node));
00651 if (OidIsValid(typcollation))
00652 {
00653
00654 if (loccontext.strength > COLLATE_NONE)
00655 {
00656
00657 collation = loccontext.collation;
00658 strength = loccontext.strength;
00659 location = loccontext.location;
00660 }
00661 else
00662 {
00663
00664
00665
00666
00667
00668
00669 collation = typcollation;
00670 strength = COLLATE_IMPLICIT;
00671 location = exprLocation(node);
00672 }
00673 }
00674 else
00675 {
00676
00677 collation = InvalidOid;
00678 strength = COLLATE_NONE;
00679 location = -1;
00680 }
00681
00682
00683
00684
00685
00686
00687 if (strength == COLLATE_CONFLICT)
00688 exprSetCollation(node, InvalidOid);
00689 else
00690 exprSetCollation(node, collation);
00691
00692
00693
00694
00695
00696 if (loccontext.strength == COLLATE_CONFLICT)
00697 exprSetInputCollation(node, InvalidOid);
00698 else
00699 exprSetInputCollation(node, loccontext.collation);
00700 }
00701 break;
00702 }
00703
00704
00705
00706
00707
00708
00709 if (strength > context->strength)
00710 {
00711
00712 context->collation = collation;
00713 context->strength = strength;
00714 context->location = location;
00715
00716 if (strength == COLLATE_CONFLICT)
00717 {
00718 context->collation2 = loccontext.collation2;
00719 context->location2 = loccontext.location2;
00720 }
00721 }
00722 else if (strength == context->strength)
00723 {
00724
00725 switch (strength)
00726 {
00727 case COLLATE_NONE:
00728
00729 break;
00730 case COLLATE_IMPLICIT:
00731 if (collation != context->collation)
00732 {
00733
00734
00735
00736 if (context->collation == DEFAULT_COLLATION_OID)
00737 {
00738
00739 context->collation = collation;
00740 context->strength = strength;
00741 context->location = location;
00742 }
00743 else if (collation != DEFAULT_COLLATION_OID)
00744 {
00745
00746
00747
00748
00749
00750
00751
00752 context->strength = COLLATE_CONFLICT;
00753 context->collation2 = collation;
00754 context->location2 = location;
00755 }
00756 }
00757 break;
00758 case COLLATE_CONFLICT:
00759
00760 break;
00761 case COLLATE_EXPLICIT:
00762 if (collation != context->collation)
00763 {
00764
00765
00766
00767
00768
00769
00770 ereport(ERROR,
00771 (errcode(ERRCODE_COLLATION_MISMATCH),
00772 errmsg("collation mismatch between explicit collations \"%s\" and \"%s\"",
00773 get_collation_name(context->collation),
00774 get_collation_name(collation)),
00775 parser_errposition(context->pstate, location)));
00776 }
00777 break;
00778 }
00779 }
00780
00781 return false;
00782 }