← Back to Overview

src/backend/parser/parse_collate.c

Coverage: 0/0 lines (0.0%)
Total Lines
0
modified
Covered
0
0.0%
Uncovered
0
100.0%
키보드 네비게이션
assign_collations_walker() lines 255-775
Modified Lines Coverage: 0/0 lines (0.0%)
LineHitsSourceCommit
255 - assign_collations_walker(Node *node, assign_collations_context *context) -
256 - { -
257 - assign_collations_context loccontext; -
258 - Oid collation; -
259 - CollateStrength strength; -
260 - int location; -
261 - -
262 - /* Need do nothing for empty subexpressions */ -
263 - if (node == NULL) -
264 - return false; -
265 - -
266 - /* -
267 - * Prepare for recursion. For most node types, though not all, the first -
268 - * thing we do is recurse to process all nodes below this one. Each level -
269 - * of the tree has its own local context. -
270 - */ -
271 - loccontext.pstate = context->pstate; -
272 - loccontext.collation = InvalidOid; -
273 - loccontext.strength = COLLATE_NONE; -
274 - loccontext.location = -1; -
275 - /* Set these fields just to suppress uninitialized-value warnings: */ -
276 - loccontext.collation2 = InvalidOid; -
277 - loccontext.location2 = -1; -
278 - -
279 - /* -
280 - * Recurse if appropriate, then determine the collation for this node. -
281 - * -
282 - * Note: the general cases are at the bottom of the switch, after various -
283 - * special cases. -
284 - */ -
285 - switch (nodeTag(node)) -
286 - { -
287 - case T_CollateExpr: -
288 - { -
289 - /* -
290 - * COLLATE sets an explicitly derived collation, regardless of -
291 - * what the child state is. But we must recurse to set up -
292 - * collation info below here. -
293 - */ -
294 - CollateExpr *expr = (CollateExpr *) node; -
295 - -
296 - (void) expression_tree_walker(node, -
297 - assign_collations_walker, -
298 - &loccontext); -
299 - -
300 - collation = expr->collOid; -
301 - Assert(OidIsValid(collation)); -
302 - strength = COLLATE_EXPLICIT; -
303 - location = expr->location; -
304 - } -
305 - break; -
306 - case T_FieldSelect: -
307 - { -
308 - /* -
309 - * For FieldSelect, the result has the field's declared -
310 - * collation, independently of what happened in the arguments. -
311 - * (The immediate argument must be composite and thus not -
312 - * collatable, anyhow.) The field's collation was already -
313 - * looked up and saved in the node. -
314 - */ -
315 - FieldSelect *expr = (FieldSelect *) node; -
316 - -
317 - /* ... but first, recurse */ -
318 - (void) expression_tree_walker(node, -
319 - assign_collations_walker, -
320 - &loccontext); -
321 - -
322 - if (OidIsValid(expr->resultcollid)) -
323 - { -
324 - /* Node's result type is collatable. */ -
325 - /* Pass up field's collation as an implicit choice. */ -
326 - collation = expr->resultcollid; -
327 - strength = COLLATE_IMPLICIT; -
328 - location = exprLocation(node); -
329 - } -
330 - else -
331 - { -
332 - /* Node's result type isn't collatable. */ -
333 - collation = InvalidOid; -
334 - strength = COLLATE_NONE; -
335 - location = -1; /* won't be used */ -
336 - } -
337 - } -
338 - break; -
339 - case T_RowExpr: -
340 - { -
341 - /* -
342 - * RowExpr is a special case because the subexpressions are -
343 - * independent: we don't want to complain if some of them have -
344 - * incompatible explicit collations. -
345 - */ -
346 - RowExpr *expr = (RowExpr *) node; -
347 - -
348 - assign_list_collations(context->pstate, expr->args); -
349 - -
350 - /* -
351 - * Since the result is always composite and therefore never -
352 - * has a collation, we can just stop here: this node has no -
353 - * impact on the collation of its parent. -
354 - */ -
355 - return false; /* done */ -
356 - } -
357 - case T_RowCompareExpr: -
358 - { -
359 - /* -
360 - * For RowCompare, we have to find the common collation of -
361 - * each pair of input columns and build a list. If we can't -
362 - * find a common collation, we just put InvalidOid into the -
363 - * list, which may or may not cause an error at runtime. -
364 - */ -
365 - RowCompareExpr *expr = (RowCompareExpr *) node; -
366 - List *colls = NIL; -
367 - ListCell *l; -
368 - ListCell *r; -
369 - -
370 - forboth(l, expr->largs, r, expr->rargs) -
371 - { -
372 - Node *le = (Node *) lfirst(l); -
373 - Node *re = (Node *) lfirst(r); -
374 - Oid coll; -
375 - -
376 - coll = select_common_collation(context->pstate, -
377 - list_make2(le, re), -
378 - true); -
379 - colls = lappend_oid(colls, coll); -
380 - } -
381 - expr->inputcollids = colls; -
382 - -
383 - /* -
384 - * Since the result is always boolean and therefore never has -
385 - * a collation, we can just stop here: this node has no impact -
386 - * on the collation of its parent. -
387 - */ -
388 - return false; /* done */ -
389 - } -
390 - case T_CoerceToDomain: -
391 - { -
392 - /* -
393 - * If the domain declaration included a non-default COLLATE -
394 - * spec, then use that collation as the output collation of -
395 - * the coercion. Otherwise allow the input collation to -
396 - * bubble up. (The input should be of the domain's base type, -
397 - * therefore we don't need to worry about it not being -
398 - * collatable when the domain is.) -
399 - */ -
400 - CoerceToDomain *expr = (CoerceToDomain *) node; -
401 - Oid typcollation = get_typcollation(expr->resulttype); -
402 - -
403 - /* ... but first, recurse */ -
404 - (void) expression_tree_walker(node, -
405 - assign_collations_walker, -
406 - &loccontext); -
407 - -
408 - if (OidIsValid(typcollation)) -
409 - { -
410 - /* Node's result type is collatable. */ -
411 - if (typcollation == DEFAULT_COLLATION_OID) -
412 - { -
413 - /* Collation state bubbles up from child. */ -
414 - collation = loccontext.collation; -
415 - strength = loccontext.strength; -
416 - location = loccontext.location; -
417 - } -
418 - else -
419 - { -
420 - /* Use domain's collation as an implicit choice. */ -
421 - collation = typcollation; -
422 - strength = COLLATE_IMPLICIT; -
423 - location = exprLocation(node); -
424 - } -
425 - } -
426 - else -
427 - { -
428 - /* Node's result type isn't collatable. */ -
429 - collation = InvalidOid; -
430 - strength = COLLATE_NONE; -
431 - location = -1; /* won't be used */ -
432 - } -
433 - -
434 - /* -
435 - * Save the state into the expression node. We know it -
436 - * doesn't care about input collation. -
437 - */ -
438 - if (strength == COLLATE_CONFLICT) -
439 - exprSetCollation(node, InvalidOid); -
440 - else -
441 - exprSetCollation(node, collation); -
442 - } -
443 - break; -
444 - case T_TargetEntry: -
445 - (void) expression_tree_walker(node, -
446 - assign_collations_walker, -
447 - &loccontext); -
448 - -
449 - /* -
450 - * TargetEntry can have only one child, and should bubble that -
451 - * state up to its parent. We can't use the general-case code -
452 - * below because exprType and friends don't work on TargetEntry. -
453 - */ -
454 - collation = loccontext.collation; -
455 - strength = loccontext.strength; -
456 - location = loccontext.location; -
457 - -
458 - /* -
459 - * Throw error if the collation is indeterminate for a TargetEntry -
460 - * that is a sort/group target. We prefer to do this now, instead -
461 - * of leaving the comparison functions to fail at runtime, because -
462 - * we can give a syntax error pointer to help locate the problem. -
463 - * There are some cases where there might not be a failure, for -
464 - * example if the planner chooses to use hash aggregation instead -
465 - * of sorting for grouping; but it seems better to predictably -
466 - * throw an error. (Compare transformSetOperationTree, which will -
467 - * throw error for indeterminate collation of set-op columns, even -
468 - * though the planner might be able to implement the set-op -
469 - * without sorting.) -
470 - */ -
471 - if (strength == COLLATE_CONFLICT && -
472 - ((TargetEntry *) node)->ressortgroupref != 0) -
473 - ereport(ERROR, -
474 - (errcode(ERRCODE_COLLATION_MISMATCH), -
475 - errmsg("collation mismatch between implicit collations \"%s\" and \"%s\"", -
476 - get_collation_name(loccontext.collation), -
477 - get_collation_name(loccontext.collation2)), -
478 - errhint("You can choose the collation by applying the COLLATE clause to one or both expressions."), -
479 - parser_errposition(context->pstate, -
480 - loccontext.location2))); -
481 - break; -
482 - case T_InferenceElem: -
483 - case T_RangeTblRef: -
484 - case T_JoinExpr: -
485 - case T_FromExpr: -
486 - case T_OnConflictExpr: -
487 - case T_SortGroupClause: -
488 - case T_MergeAction: -
489 - (void) expression_tree_walker(node, -
490 - assign_collations_walker, -
491 - &loccontext); -
492 - -
493 - /* -
494 - * When we're invoked on a query's jointree, we don't need to do -
495 - * anything with join nodes except recurse through them to process -
496 - * WHERE/ON expressions. So just stop here. Likewise, we don't -
497 - * need to do anything when invoked on sort/group lists. -
498 - */ -
499 - return false; -
500 - case T_Query: -
501 - { -
502 - /* -
503 - * We get here when we're invoked on the Query belonging to a -
504 - * SubLink. Act as though the Query returns its first output -
505 - * column, which indeed is what it does for EXPR_SUBLINK and -
506 - * ARRAY_SUBLINK cases. In the cases where the SubLink -
507 - * returns boolean, this info will be ignored. Special case: -
508 - * in EXISTS, the Query might return no columns, in which case -
509 - * we need do nothing. -
510 - * -
511 - * We needn't recurse, since the Query is already processed. -
512 - */ -
513 - Query *qtree = (Query *) node; -
514 - TargetEntry *tent; -
515 - -
516 - if (qtree->targetList == NIL) -
517 - return false; -
518 - tent = linitial_node(TargetEntry, qtree->targetList); -
519 - if (tent->resjunk) -
520 - return false; -
521 - -
522 - collation = exprCollation((Node *) tent->expr); -
523 - /* collation doesn't change if it's converted to array */ -
524 - strength = COLLATE_IMPLICIT; -
525 - location = exprLocation((Node *) tent->expr); -
526 - } -
527 - break; -
528 - case T_List: -
529 - (void) expression_tree_walker(node, -
530 - assign_collations_walker, -
531 - &loccontext); -
532 - -
533 - /* -
534 - * When processing a list, collation state just bubbles up from -
535 - * the list elements. -
536 - */ -
537 - collation = loccontext.collation; -
538 - strength = loccontext.strength; -
539 - location = loccontext.location; -
540 - break; -
541 - -
542 - case T_Var: -
543 - case T_Const: -
544 - case T_Param: -
545 - case T_CoerceToDomainValue: -
546 - case T_CaseTestExpr: -
547 - case T_SetToDefault: -
548 - case T_CurrentOfExpr: -
549 - case T_GraphPropertyRef: 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
550 - -
551 - /* -
552 - * General case for childless expression nodes. These should -
553 - * already have a collation assigned; it is not this function's -
554 - * responsibility to look into the catalogs for base-case -
555 - * information. -
556 - */ -
557 - collation = exprCollation(node); -
558 - -
559 - /* -
560 - * Note: in most cases, there will be an assigned collation -
561 - * whenever type_is_collatable(exprType(node)); but an exception -
562 - * occurs for a Var referencing a subquery output column for which -
563 - * a unique collation was not determinable. That may lead to a -
564 - * runtime failure if a collation-sensitive function is applied to -
565 - * the Var. -
566 - */ -
567 - -
568 - if (OidIsValid(collation)) -
569 - strength = COLLATE_IMPLICIT; -
570 - else -
571 - strength = COLLATE_NONE; -
572 - location = exprLocation(node); -
573 - break; -
574 - -
575 - default: -
576 - { -
577 - /* -
578 - * General case for most expression nodes with children. First -
579 - * recurse, then figure out what to assign to this node. -
580 - */ -
581 - Oid typcollation; -
582 - -
583 - /* -
584 - * For most node types, we want to treat all the child -
585 - * expressions alike; but there are a few exceptions, hence -
586 - * this inner switch. -
587 - */ -
588 - switch (nodeTag(node)) -
589 - { -
590 - case T_Aggref: -
591 - { -
592 - /* -
593 - * Aggref is messy enough that we give it its own -
594 - * function, in fact three of them. The FILTER -
595 - * clause is independent of the rest of the -
596 - * aggregate, however, so it can be processed -
597 - * separately. -
598 - */ -
599 - Aggref *aggref = (Aggref *) node; -
600 - -
601 - switch (aggref->aggkind) -
602 - { -
603 - case AGGKIND_NORMAL: -
604 - assign_aggregate_collations(aggref, -
605 - &loccontext); -
606 - break; -
607 - case AGGKIND_ORDERED_SET: -
608 - assign_ordered_set_collations(aggref, -
609 - &loccontext); -
610 - break; -
611 - case AGGKIND_HYPOTHETICAL: -
612 - assign_hypothetical_collations(aggref, -
613 - &loccontext); -
614 - break; -
615 - default: -
616 - elog(ERROR, "unrecognized aggkind: %d", -
617 - (int) aggref->aggkind); -
618 - } -
619 - -
620 - assign_expr_collations(context->pstate, -
621 - (Node *) aggref->aggfilter); -
622 - } -
623 - break; -
624 - case T_WindowFunc: -
625 - { -
626 - /* -
627 - * WindowFunc requires special processing only for -
628 - * its aggfilter clause, as for aggregates. -
629 - */ -
630 - WindowFunc *wfunc = (WindowFunc *) node; -
631 - -
632 - (void) assign_collations_walker((Node *) wfunc->args, -
633 - &loccontext); -
634 - -
635 - assign_expr_collations(context->pstate, -
636 - (Node *) wfunc->aggfilter); -
637 - } -
638 - break; -
639 - case T_CaseExpr: -
640 - { -
641 - /* -
642 - * CaseExpr is a special case because we do not -
643 - * want to recurse into the test expression (if -
644 - * any). It was already marked with collations -
645 - * during transformCaseExpr, and furthermore its -
646 - * collation is not relevant to the result of the -
647 - * CASE --- only the output expressions are. -
648 - */ -
649 - CaseExpr *expr = (CaseExpr *) node; -
650 - ListCell *lc; -
651 - -
652 - foreach(lc, expr->args) -
653 - { -
654 - CaseWhen *when = lfirst_node(CaseWhen, lc); -
655 - -
656 - /* -
657 - * The condition expressions mustn't affect -
658 - * the CASE's result collation either; but -
659 - * since they are known to yield boolean, it's -
660 - * safe to recurse directly on them --- they -
661 - * won't change loccontext. -
662 - */ -
663 - (void) assign_collations_walker((Node *) when->expr, -
664 - &loccontext); -
665 - (void) assign_collations_walker((Node *) when->result, -
666 - &loccontext); -
667 - } -
668 - (void) assign_collations_walker((Node *) expr->defresult, -
669 - &loccontext); -
670 - } -
671 - break; -
672 - case T_SubscriptingRef: -
673 - { -
674 - /* -
675 - * The subscripts are treated as independent -
676 - * expressions not contributing to the node's -
677 - * collation. Only the container, and the source -
678 - * expression if any, contribute. (This models -
679 - * the old behavior, in which the subscripts could -
680 - * be counted on to be integers and thus not -
681 - * contribute anything.) -
682 - */ -
683 - SubscriptingRef *sbsref = (SubscriptingRef *) node; -
684 - -
685 - assign_expr_collations(context->pstate, -
686 - (Node *) sbsref->refupperindexpr); -
687 - assign_expr_collations(context->pstate, -
688 - (Node *) sbsref->reflowerindexpr); -
689 - (void) assign_collations_walker((Node *) sbsref->refexpr, -
690 - &loccontext); -
691 - (void) assign_collations_walker((Node *) sbsref->refassgnexpr, -
692 - &loccontext); -
693 - } -
694 - break; -
695 - default: -
696 - -
697 - /* -
698 - * Normal case: all child expressions contribute -
699 - * equally to loccontext. -
700 - */ -
701 - (void) expression_tree_walker(node, -
702 - assign_collations_walker, -
703 - &loccontext); -
704 - break; -
705 - } -
706 - -
707 - /* -
708 - * Now figure out what collation to assign to this node. -
709 - */ -
710 - typcollation = get_typcollation(exprType(node)); -
711 - if (OidIsValid(typcollation)) -
712 - { -
713 - /* Node's result is collatable; what about its input? */ -
714 - if (loccontext.strength > COLLATE_NONE) -
715 - { -
716 - /* Collation state bubbles up from children. */ -
717 - collation = loccontext.collation; -
718 - strength = loccontext.strength; -
719 - location = loccontext.location; -
720 - } -
721 - else -
722 - { -
723 - /* -
724 - * Collatable output produced without any collatable -
725 - * input. Use the type's collation (which is usually -
726 - * DEFAULT_COLLATION_OID, but might be different for a -
727 - * domain). -
728 - */ -
729 - collation = typcollation; -
730 - strength = COLLATE_IMPLICIT; -
731 - location = exprLocation(node); -
732 - } -
733 - } -
734 - else -
735 - { -
736 - /* Node's result type isn't collatable. */ -
737 - collation = InvalidOid; -
738 - strength = COLLATE_NONE; -
739 - location = -1; /* won't be used */ -
740 - } -
741 - -
742 - /* -
743 - * Save the result collation into the expression node. If the -
744 - * state is COLLATE_CONFLICT, we'll set the collation to -
745 - * InvalidOid, which might result in an error at runtime. -
746 - */ -
747 - if (strength == COLLATE_CONFLICT) -
748 - exprSetCollation(node, InvalidOid); -
749 - else -
750 - exprSetCollation(node, collation); -
751 - -
752 - /* -
753 - * Likewise save the input collation, which is the one that -
754 - * any function called by this node should use. -
755 - */ -
756 - if (loccontext.strength == COLLATE_CONFLICT) -
757 - exprSetInputCollation(node, InvalidOid); -
758 - else -
759 - exprSetInputCollation(node, loccontext.collation); -
760 - } -
761 - break; -
762 - } -
763 - -
764 - /* -
765 - * Now, merge my information into my parent's state. -
766 - */ -
767 - merge_collation_state(collation, -
768 - strength, -
769 - location, -
770 - loccontext.collation2, -
771 - loccontext.location2, -
772 - context); -
773 - -
774 - return false; -
775 - } -