| Line | Hits | Source | Commit |
|---|---|---|---|
| 509 | - | transformColumnRef(ParseState *pstate, ColumnRef *cref) | - |
| 510 | - | { | - |
| 511 | - | Node *node = NULL; | - |
| 512 | - | char *nspname = NULL; | - |
| 513 | - | char *relname = NULL; | - |
| 514 | - | char *colname = NULL; | - |
| 515 | - | ParseNamespaceItem *nsitem; | - |
| 516 | - | int levels_up; | - |
| 517 | - | enum | - |
| 518 | - | { | - |
| 519 | - | CRERR_NO_COLUMN, | - |
| 520 | - | CRERR_NO_RTE, | - |
| 521 | - | CRERR_WRONG_DB, | - |
| 522 | - | CRERR_TOO_MANY | - |
| 523 | - | } crerr = CRERR_NO_COLUMN; | - |
| 524 | - | const char *err; | - |
| 525 | - | - | |
| 526 | - | /* | - |
| 527 | - | * Check to see if the column reference is in an invalid place within the | - |
| 528 | - | * query. We allow column references in most places, except in default | - |
| 529 | - | * expressions and partition bound expressions. | - |
| 530 | - | */ | - |
| 531 | - | err = NULL; | - |
| 532 | - | switch (pstate->p_expr_kind) | - |
| 533 | - | { | - |
| 534 | - | case EXPR_KIND_NONE: | - |
| 535 | - | Assert(false); /* can't happen */ | - |
| 536 | - | break; | - |
| 537 | - | case EXPR_KIND_OTHER: | - |
| 538 | - | case EXPR_KIND_JOIN_ON: | - |
| 539 | - | case EXPR_KIND_JOIN_USING: | - |
| 540 | - | case EXPR_KIND_FROM_SUBSELECT: | - |
| 541 | - | case EXPR_KIND_FROM_FUNCTION: | - |
| 542 | - | case EXPR_KIND_WHERE: | - |
| 543 | - | case EXPR_KIND_POLICY: | - |
| 544 | - | case EXPR_KIND_HAVING: | - |
| 545 | - | case EXPR_KIND_FILTER: | - |
| 546 | - | case EXPR_KIND_WINDOW_PARTITION: | - |
| 547 | - | case EXPR_KIND_WINDOW_ORDER: | - |
| 548 | - | case EXPR_KIND_WINDOW_FRAME_RANGE: | - |
| 549 | - | case EXPR_KIND_WINDOW_FRAME_ROWS: | - |
| 550 | - | case EXPR_KIND_WINDOW_FRAME_GROUPS: | - |
| 551 | - | case EXPR_KIND_SELECT_TARGET: | - |
| 552 | - | case EXPR_KIND_INSERT_TARGET: | - |
| 553 | - | case EXPR_KIND_UPDATE_SOURCE: | - |
| 554 | - | case EXPR_KIND_UPDATE_TARGET: | - |
| 555 | - | case EXPR_KIND_MERGE_WHEN: | - |
| 556 | - | case EXPR_KIND_GROUP_BY: | - |
| 557 | - | case EXPR_KIND_ORDER_BY: | - |
| 558 | - | case EXPR_KIND_DISTINCT_ON: | - |
| 559 | - | case EXPR_KIND_LIMIT: | - |
| 560 | - | case EXPR_KIND_OFFSET: | - |
| 561 | - | case EXPR_KIND_RETURNING: | - |
| 562 | - | case EXPR_KIND_MERGE_RETURNING: | - |
| 563 | - | case EXPR_KIND_VALUES: | - |
| 564 | - | case EXPR_KIND_VALUES_SINGLE: | - |
| 565 | - | case EXPR_KIND_CHECK_CONSTRAINT: | - |
| 566 | - | case EXPR_KIND_DOMAIN_CHECK: | - |
| 567 | - | case EXPR_KIND_FUNCTION_DEFAULT: | - |
| 568 | - | case EXPR_KIND_INDEX_EXPRESSION: | - |
| 569 | - | case EXPR_KIND_INDEX_PREDICATE: | - |
| 570 | - | case EXPR_KIND_STATS_EXPRESSION: | - |
| 571 | - | case EXPR_KIND_ALTER_COL_TRANSFORM: | - |
| 572 | - | case EXPR_KIND_EXECUTE_PARAMETER: | - |
| 573 | - | case EXPR_KIND_TRIGGER_WHEN: | - |
| 574 | - | case EXPR_KIND_PARTITION_EXPRESSION: | - |
| 575 | - | case EXPR_KIND_CALL_ARGUMENT: | - |
| 576 | - | case EXPR_KIND_COPY_WHERE: | - |
| 577 | - | case EXPR_KIND_GENERATED_COLUMN: | - |
| 578 | - | case EXPR_KIND_CYCLE_MARK: | - |
| 579 | - | case EXPR_KIND_RPR_DEFINE: | b8a35c3Row pattern recognition patch (parse/analysis). |
| 580 | - | /* okay */ | - |
| 581 | - | break; | - |
| 582 | - | - | |
| 583 | - | case EXPR_KIND_COLUMN_DEFAULT: | - |
| 584 | - | err = _("cannot use column reference in DEFAULT expression"); | - |
| 585 | - | break; | - |
| 586 | - | case EXPR_KIND_PARTITION_BOUND: | - |
| 587 | - | err = _("cannot use column reference in partition bound expression"); | - |
| 588 | - | break; | - |
| 589 | - | - | |
| 590 | - | /* | - |
| 591 | - | * There is intentionally no default: case here, so that the | - |
| 592 | - | * compiler will warn if we add a new ParseExprKind without | - |
| 593 | - | * extending this switch. If we do see an unrecognized value at | - |
| 594 | - | * runtime, the behavior will be the same as for EXPR_KIND_OTHER, | - |
| 595 | - | * which is sane anyway. | - |
| 596 | - | */ | - |
| 597 | - | } | - |
| 598 | - | if (err) | - |
| 599 | - | ereport(ERROR, | - |
| 600 | - | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), | - |
| 601 | - | errmsg_internal("%s", err), | - |
| 602 | - | parser_errposition(pstate, cref->location))); | - |
| 603 | - | - | |
| 604 | - | /* | - |
| 605 | - | * Give the PreParseColumnRefHook, if any, first shot. If it returns | - |
| 606 | - | * non-null then that's all, folks. | - |
| 607 | - | */ | - |
| 608 | - | if (pstate->p_pre_columnref_hook != NULL) | - |
| 609 | - | { | - |
| 610 | - | node = pstate->p_pre_columnref_hook(pstate, cref); | - |
| 611 | - | if (node != NULL) | - |
| 612 | - | return node; | - |
| 613 | - | } | - |
| 614 | - | - | |
| 615 | - | /*---------- | - |
| 616 | - | * The allowed syntaxes are: | - |
| 617 | - | * | - |
| 618 | - | * A First try to resolve as unqualified column name; | - |
| 619 | - | * if no luck, try to resolve as unqualified table name (A.*). | - |
| 620 | - | * A.B A is an unqualified table name; B is either a | - |
| 621 | - | * column or function name (trying column name first). | - |
| 622 | - | * A.B.C schema A, table B, col or func name C. | - |
| 623 | - | * A.B.C.D catalog A, schema B, table C, col or func D. | - |
| 624 | - | * A.* A is an unqualified table name; means whole-row value. | - |
| 625 | - | * A.B.* whole-row value of table B in schema A. | - |
| 626 | - | * A.B.C.* whole-row value of table C in schema B in catalog A. | - |
| 627 | - | * | - |
| 628 | - | * We do not need to cope with bare "*"; that will only be accepted by | - |
| 629 | - | * the grammar at the top level of a SELECT list, and transformTargetList | - |
| 630 | - | * will take care of it before it ever gets here. Also, "A.*" etc will | - |
| 631 | - | * be expanded by transformTargetList if they appear at SELECT top level, | - |
| 632 | - | * so here we are only going to see them as function or operator inputs. | - |
| 633 | - | * | - |
| 634 | - | * Currently, if a catalog name is given then it must equal the current | - |
| 635 | - | * database name; we check it here and then discard it. | - |
| 636 | - | *---------- | - |
| 637 | - | */ | - |
| 638 | - | switch (list_length(cref->fields)) | - |
| 639 | - | { | - |
| 640 | - | case 1: | - |
| 641 | - | { | - |
| 642 | - | Node *field1 = (Node *) linitial(cref->fields); | - |
| 643 | - | - | |
| 644 | - | colname = strVal(field1); | - |
| 645 | - | - | |
| 646 | - | /* Try to identify as an unqualified column */ | - |
| 647 | - | node = colNameToVar(pstate, colname, false, cref->location); | - |
| 648 | - | - | |
| 649 | - | if (node == NULL) | - |
| 650 | - | { | - |
| 651 | - | /* | - |
| 652 | - | * Not known as a column of any range-table entry. | - |
| 653 | - | * | - |
| 654 | - | * Try to find the name as a relation. Note that only | - |
| 655 | - | * relations already entered into the rangetable will be | - |
| 656 | - | * recognized. | - |
| 657 | - | * | - |
| 658 | - | * This is a hack for backwards compatibility with | - |
| 659 | - | * PostQUEL-inspired syntax. The preferred form now is | - |
| 660 | - | * "rel.*". | - |
| 661 | - | */ | - |
| 662 | - | nsitem = refnameNamespaceItem(pstate, NULL, colname, | - |
| 663 | - | cref->location, | - |
| 664 | - | &levels_up); | - |
| 665 | - | if (nsitem) | - |
| 666 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | - |
| 667 | - | cref->location); | - |
| 668 | - | } | - |
| 669 | - | break; | - |
| 670 | - | } | - |
| 671 | - | case 2: | - |
| 672 | - | { | - |
| 673 | - | Node *field1 = (Node *) linitial(cref->fields); | - |
| 674 | - | Node *field2 = (Node *) lsecond(cref->fields); | - |
| 675 | - | - | |
| 676 | - | relname = strVal(field1); | - |
| 677 | - | - | |
| 678 | - | /* Locate the referenced nsitem */ | - |
| 679 | - | nsitem = refnameNamespaceItem(pstate, nspname, relname, | - |
| 680 | - | cref->location, | - |
| 681 | - | &levels_up); | - |
| 682 | - | if (nsitem == NULL) | - |
| 683 | - | { | - |
| 684 | - | crerr = CRERR_NO_RTE; | - |
| 685 | - | break; | - |
| 686 | - | } | - |
| 687 | - | - | |
| 688 | - | /* Whole-row reference? */ | - |
| 689 | - | if (IsA(field2, A_Star)) | - |
| 690 | - | { | - |
| 691 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | - |
| 692 | - | cref->location); | - |
| 693 | - | break; | - |
| 694 | - | } | - |
| 695 | - | - | |
| 696 | - | colname = strVal(field2); | - |
| 697 | - | - | |
| 698 | - | /* Try to identify as a column of the nsitem */ | - |
| 699 | - | node = scanNSItemForColumn(pstate, nsitem, levels_up, colname, | - |
| 700 | - | cref->location); | - |
| 701 | - | if (node == NULL) | - |
| 702 | - | { | - |
| 703 | - | /* Try it as a function call on the whole row */ | - |
| 704 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | - |
| 705 | - | cref->location); | - |
| 706 | - | node = ParseFuncOrColumn(pstate, | - |
| 707 | - | list_make1(makeString(colname)), | - |
| 708 | - | list_make1(node), | - |
| 709 | - | pstate->p_last_srf, | - |
| 710 | - | NULL, | - |
| 711 | - | false, | - |
| 712 | - | cref->location); | - |
| 713 | - | } | - |
| 714 | - | break; | - |
| 715 | - | } | - |
| 716 | - | case 3: | - |
| 717 | - | { | - |
| 718 | - | Node *field1 = (Node *) linitial(cref->fields); | - |
| 719 | - | Node *field2 = (Node *) lsecond(cref->fields); | - |
| 720 | - | Node *field3 = (Node *) lthird(cref->fields); | - |
| 721 | - | - | |
| 722 | - | nspname = strVal(field1); | - |
| 723 | - | relname = strVal(field2); | - |
| 724 | - | - | |
| 725 | - | /* Locate the referenced nsitem */ | - |
| 726 | - | nsitem = refnameNamespaceItem(pstate, nspname, relname, | - |
| 727 | - | cref->location, | - |
| 728 | - | &levels_up); | - |
| 729 | - | if (nsitem == NULL) | - |
| 730 | - | { | - |
| 731 | - | crerr = CRERR_NO_RTE; | - |
| 732 | - | break; | - |
| 733 | - | } | - |
| 734 | - | - | |
| 735 | - | /* Whole-row reference? */ | - |
| 736 | - | if (IsA(field3, A_Star)) | - |
| 737 | - | { | - |
| 738 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | - |
| 739 | - | cref->location); | - |
| 740 | - | break; | - |
| 741 | - | } | - |
| 742 | - | - | |
| 743 | - | colname = strVal(field3); | - |
| 744 | - | - | |
| 745 | - | /* Try to identify as a column of the nsitem */ | - |
| 746 | - | node = scanNSItemForColumn(pstate, nsitem, levels_up, colname, | - |
| 747 | - | cref->location); | - |
| 748 | - | if (node == NULL) | - |
| 749 | - | { | - |
| 750 | - | /* Try it as a function call on the whole row */ | - |
| 751 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | - |
| 752 | - | cref->location); | - |
| 753 | - | node = ParseFuncOrColumn(pstate, | - |
| 754 | - | list_make1(makeString(colname)), | - |
| 755 | - | list_make1(node), | - |
| 756 | - | pstate->p_last_srf, | - |
| 757 | - | NULL, | - |
| 758 | - | false, | - |
| 759 | - | cref->location); | - |
| 760 | - | } | - |
| 761 | - | break; | - |
| 762 | - | } | - |
| 763 | - | case 4: | - |
| 764 | - | { | - |
| 765 | - | Node *field1 = (Node *) linitial(cref->fields); | - |
| 766 | - | Node *field2 = (Node *) lsecond(cref->fields); | - |
| 767 | - | Node *field3 = (Node *) lthird(cref->fields); | - |
| 768 | - | Node *field4 = (Node *) lfourth(cref->fields); | - |
| 769 | - | char *catname; | - |
| 770 | - | - | |
| 771 | - | catname = strVal(field1); | - |
| 772 | - | nspname = strVal(field2); | - |
| 773 | - | relname = strVal(field3); | - |
| 774 | - | - | |
| 775 | - | /* | - |
| 776 | - | * We check the catalog name and then ignore it. | - |
| 777 | - | */ | - |
| 778 | - | if (strcmp(catname, get_database_name(MyDatabaseId)) != 0) | - |
| 779 | - | { | - |
| 780 | - | crerr = CRERR_WRONG_DB; | - |
| 781 | - | break; | - |
| 782 | - | } | - |
| 783 | - | - | |
| 784 | - | /* Locate the referenced nsitem */ | - |
| 785 | - | nsitem = refnameNamespaceItem(pstate, nspname, relname, | - |
| 786 | - | cref->location, | - |
| 787 | - | &levels_up); | - |
| 788 | - | if (nsitem == NULL) | - |
| 789 | - | { | - |
| 790 | - | crerr = CRERR_NO_RTE; | - |
| 791 | - | break; | - |
| 792 | - | } | - |
| 793 | - | - | |
| 794 | - | /* Whole-row reference? */ | - |
| 795 | - | if (IsA(field4, A_Star)) | - |
| 796 | - | { | - |
| 797 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | - |
| 798 | - | cref->location); | - |
| 799 | - | break; | - |
| 800 | - | } | - |
| 801 | - | - | |
| 802 | - | colname = strVal(field4); | - |
| 803 | - | - | |
| 804 | - | /* Try to identify as a column of the nsitem */ | - |
| 805 | - | node = scanNSItemForColumn(pstate, nsitem, levels_up, colname, | - |
| 806 | - | cref->location); | - |
| 807 | - | if (node == NULL) | - |
| 808 | - | { | - |
| 809 | - | /* Try it as a function call on the whole row */ | - |
| 810 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | - |
| 811 | - | cref->location); | - |
| 812 | - | node = ParseFuncOrColumn(pstate, | - |
| 813 | - | list_make1(makeString(colname)), | - |
| 814 | - | list_make1(node), | - |
| 815 | - | pstate->p_last_srf, | - |
| 816 | - | NULL, | - |
| 817 | - | false, | - |
| 818 | - | cref->location); | - |
| 819 | - | } | - |
| 820 | - | break; | - |
| 821 | - | } | - |
| 822 | - | default: | - |
| 823 | - | crerr = CRERR_TOO_MANY; /* too many dotted names */ | - |
| 824 | - | break; | - |
| 825 | - | } | - |
| 826 | - | - | |
| 827 | - | /* | - |
| 828 | - | * Now give the PostParseColumnRefHook, if any, a chance. We pass the | - |
| 829 | - | * translation-so-far so that it can throw an error if it wishes in the | - |
| 830 | - | * case that it has a conflicting interpretation of the ColumnRef. (If it | - |
| 831 | - | * just translates anyway, we'll throw an error, because we can't undo | - |
| 832 | - | * whatever effects the preceding steps may have had on the pstate.) If it | - |
| 833 | - | * returns NULL, use the standard translation, or throw a suitable error | - |
| 834 | - | * if there is none. | - |
| 835 | - | */ | - |
| 836 | - | if (pstate->p_post_columnref_hook != NULL) | - |
| 837 | - | { | - |
| 838 | - | Node *hookresult; | - |
| 839 | - | - | |
| 840 | - | hookresult = pstate->p_post_columnref_hook(pstate, cref, node); | - |
| 841 | - | if (node == NULL) | - |
| 842 | - | node = hookresult; | - |
| 843 | - | else if (hookresult != NULL) | - |
| 844 | - | ereport(ERROR, | - |
| 845 | - | (errcode(ERRCODE_AMBIGUOUS_COLUMN), | - |
| 846 | - | errmsg("column reference \"%s\" is ambiguous", | - |
| 847 | - | NameListToString(cref->fields)), | - |
| 848 | - | parser_errposition(pstate, cref->location))); | - |
| 849 | - | } | - |
| 850 | - | - | |
| 851 | - | /* | - |
| 852 | - | * Throw error if no translation found. | - |
| 853 | - | */ | - |
| 854 | - | if (node == NULL) | - |
| 855 | - | { | - |
| 856 | - | switch (crerr) | - |
| 857 | - | { | - |
| 858 | - | case CRERR_NO_COLUMN: | - |
| 859 | - | errorMissingColumn(pstate, relname, colname, cref->location); | - |
| 860 | - | break; | - |
| 861 | - | case CRERR_NO_RTE: | - |
| 862 | - | errorMissingRTE(pstate, makeRangeVar(nspname, relname, | - |
| 863 | - | cref->location)); | - |
| 864 | - | break; | - |
| 865 | - | case CRERR_WRONG_DB: | - |
| 866 | - | ereport(ERROR, | - |
| 867 | - | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), | - |
| 868 | - | errmsg("cross-database references are not implemented: %s", | - |
| 869 | - | NameListToString(cref->fields)), | - |
| 870 | - | parser_errposition(pstate, cref->location))); | - |
| 871 | - | break; | - |
| 872 | - | case CRERR_TOO_MANY: | - |
| 873 | - | ereport(ERROR, | - |
| 874 | - | (errcode(ERRCODE_SYNTAX_ERROR), | - |
| 875 | - | errmsg("improper qualified name (too many dotted names): %s", | - |
| 876 | - | NameListToString(cref->fields)), | - |
| 877 | - | parser_errposition(pstate, cref->location))); | - |
| 878 | - | break; | - |
| 879 | - | } | - |
| 880 | - | } | - |
| 881 | - | - | |
| 882 | - | return node; | - |
| 883 | - | } | - |
| Line | Hits | Source | Commit |
|---|---|---|---|
| 1774 | - | transformSubLink(ParseState *pstate, SubLink *sublink) | - |
| 1775 | - | { | - |
| 1776 | - | Node *result = (Node *) sublink; | - |
| 1777 | - | Query *qtree; | - |
| 1778 | - | const char *err; | - |
| 1779 | - | - | |
| 1780 | - | /* | - |
| 1781 | - | * Check to see if the sublink is in an invalid place within the query. We | - |
| 1782 | - | * allow sublinks everywhere in SELECT/INSERT/UPDATE/DELETE/MERGE, but | - |
| 1783 | - | * generally not in utility statements. | - |
| 1784 | - | */ | - |
| 1785 | - | err = NULL; | - |
| 1786 | - | switch (pstate->p_expr_kind) | - |
| 1787 | - | { | - |
| 1788 | - | case EXPR_KIND_NONE: | - |
| 1789 | - | Assert(false); /* can't happen */ | - |
| 1790 | - | break; | - |
| 1791 | - | case EXPR_KIND_OTHER: | - |
| 1792 | - | /* Accept sublink here; caller must throw error if wanted */ | - |
| 1793 | - | break; | - |
| 1794 | - | case EXPR_KIND_JOIN_ON: | - |
| 1795 | - | case EXPR_KIND_JOIN_USING: | - |
| 1796 | - | case EXPR_KIND_FROM_SUBSELECT: | - |
| 1797 | - | case EXPR_KIND_FROM_FUNCTION: | - |
| 1798 | - | case EXPR_KIND_WHERE: | - |
| 1799 | - | case EXPR_KIND_POLICY: | - |
| 1800 | - | case EXPR_KIND_HAVING: | - |
| 1801 | - | case EXPR_KIND_FILTER: | - |
| 1802 | - | case EXPR_KIND_WINDOW_PARTITION: | - |
| 1803 | - | case EXPR_KIND_WINDOW_ORDER: | - |
| 1804 | - | case EXPR_KIND_WINDOW_FRAME_RANGE: | - |
| 1805 | - | case EXPR_KIND_WINDOW_FRAME_ROWS: | - |
| 1806 | - | case EXPR_KIND_WINDOW_FRAME_GROUPS: | - |
| 1807 | - | case EXPR_KIND_SELECT_TARGET: | - |
| 1808 | - | case EXPR_KIND_INSERT_TARGET: | - |
| 1809 | - | case EXPR_KIND_UPDATE_SOURCE: | - |
| 1810 | - | case EXPR_KIND_UPDATE_TARGET: | - |
| 1811 | - | case EXPR_KIND_MERGE_WHEN: | - |
| 1812 | - | case EXPR_KIND_GROUP_BY: | - |
| 1813 | - | case EXPR_KIND_ORDER_BY: | - |
| 1814 | - | case EXPR_KIND_DISTINCT_ON: | - |
| 1815 | - | case EXPR_KIND_LIMIT: | - |
| 1816 | - | case EXPR_KIND_OFFSET: | - |
| 1817 | - | case EXPR_KIND_RETURNING: | - |
| 1818 | - | case EXPR_KIND_MERGE_RETURNING: | - |
| 1819 | - | case EXPR_KIND_VALUES: | - |
| 1820 | - | case EXPR_KIND_VALUES_SINGLE: | - |
| 1821 | - | case EXPR_KIND_CYCLE_MARK: | - |
| 1822 | - | /* okay */ | - |
| 1823 | - | break; | - |
| 1824 | - | case EXPR_KIND_CHECK_CONSTRAINT: | - |
| 1825 | - | case EXPR_KIND_DOMAIN_CHECK: | - |
| 1826 | - | err = _("cannot use subquery in check constraint"); | - |
| 1827 | - | break; | - |
| 1828 | - | case EXPR_KIND_COLUMN_DEFAULT: | - |
| 1829 | - | case EXPR_KIND_FUNCTION_DEFAULT: | - |
| 1830 | - | err = _("cannot use subquery in DEFAULT expression"); | - |
| 1831 | - | break; | - |
| 1832 | - | case EXPR_KIND_INDEX_EXPRESSION: | - |
| 1833 | - | err = _("cannot use subquery in index expression"); | - |
| 1834 | - | break; | - |
| 1835 | - | case EXPR_KIND_INDEX_PREDICATE: | - |
| 1836 | - | err = _("cannot use subquery in index predicate"); | - |
| 1837 | - | break; | - |
| 1838 | - | case EXPR_KIND_STATS_EXPRESSION: | - |
| 1839 | - | err = _("cannot use subquery in statistics expression"); | - |
| 1840 | - | break; | - |
| 1841 | - | case EXPR_KIND_ALTER_COL_TRANSFORM: | - |
| 1842 | - | err = _("cannot use subquery in transform expression"); | - |
| 1843 | - | break; | - |
| 1844 | - | case EXPR_KIND_EXECUTE_PARAMETER: | - |
| 1845 | - | err = _("cannot use subquery in EXECUTE parameter"); | - |
| 1846 | - | break; | - |
| 1847 | - | case EXPR_KIND_TRIGGER_WHEN: | - |
| 1848 | - | err = _("cannot use subquery in trigger WHEN condition"); | - |
| 1849 | - | break; | - |
| 1850 | - | case EXPR_KIND_PARTITION_BOUND: | - |
| 1851 | - | err = _("cannot use subquery in partition bound"); | - |
| 1852 | - | break; | - |
| 1853 | - | case EXPR_KIND_PARTITION_EXPRESSION: | - |
| 1854 | - | err = _("cannot use subquery in partition key expression"); | - |
| 1855 | - | break; | - |
| 1856 | - | case EXPR_KIND_CALL_ARGUMENT: | - |
| 1857 | - | err = _("cannot use subquery in CALL argument"); | - |
| 1858 | - | break; | - |
| 1859 | - | case EXPR_KIND_COPY_WHERE: | - |
| 1860 | - | err = _("cannot use subquery in COPY FROM WHERE condition"); | - |
| 1861 | - | break; | - |
| 1862 | - | case EXPR_KIND_GENERATED_COLUMN: | - |
| 1863 | - | err = _("cannot use subquery in column generation expression"); | - |
| 1864 | - | break; | - |
| 1865 | 3 | case EXPR_KIND_RPR_DEFINE: | b8a35c3Row pattern recognition patch (parse/analysis). |
| 1866 | 3 | err = _("cannot use subquery in DEFINE expression"); | b8a35c3Row pattern recognition patch (parse/analysis). |
| 1867 | 3 | break; | b8a35c3Row pattern recognition patch (parse/analysis). |
| 1868 | - | - | |
| 1869 | - | /* | - |
| 1870 | - | * There is intentionally no default: case here, so that the | - |
| 1871 | - | * compiler will warn if we add a new ParseExprKind without | - |
| 1872 | - | * extending this switch. If we do see an unrecognized value at | - |
| 1873 | - | * runtime, the behavior will be the same as for EXPR_KIND_OTHER, | - |
| 1874 | - | * which is sane anyway. | - |
| 1875 | - | */ | - |
| 1876 | - | } | - |
| 1877 | - | if (err) | - |
| 1878 | - | ereport(ERROR, | - |
| 1879 | - | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), | - |
| 1880 | - | errmsg_internal("%s", err), | - |
| 1881 | - | parser_errposition(pstate, sublink->location))); | - |
| 1882 | - | - | |
| 1883 | - | pstate->p_hasSubLinks = true; | - |
| 1884 | - | - | |
| 1885 | - | /* | - |
| 1886 | - | * OK, let's transform the sub-SELECT. | - |
| 1887 | - | */ | - |
| 1888 | - | qtree = parse_sub_analyze(sublink->subselect, pstate, NULL, false, true); | - |
| 1889 | - | - | |
| 1890 | - | /* | - |
| 1891 | - | * Check that we got a SELECT. Anything else should be impossible given | - |
| 1892 | - | * restrictions of the grammar, but check anyway. | - |
| 1893 | - | */ | - |
| 1894 | - | if (!IsA(qtree, Query) || | - |
| 1895 | - | qtree->commandType != CMD_SELECT) | - |
| 1896 | - | elog(ERROR, "unexpected non-SELECT command in SubLink"); | - |
| 1897 | - | - | |
| 1898 | - | sublink->subselect = (Node *) qtree; | - |
| 1899 | - | - | |
| 1900 | - | if (sublink->subLinkType == EXISTS_SUBLINK) | - |
| 1901 | - | { | - |
| 1902 | - | /* | - |
| 1903 | - | * EXISTS needs no test expression or combining operator. These fields | - |
| 1904 | - | * should be null already, but make sure. | - |
| 1905 | - | */ | - |
| 1906 | - | sublink->testexpr = NULL; | - |
| 1907 | - | sublink->operName = NIL; | - |
| 1908 | - | } | - |
| 1909 | - | else if (sublink->subLinkType == EXPR_SUBLINK || | - |
| 1910 | - | sublink->subLinkType == ARRAY_SUBLINK) | - |
| 1911 | - | { | - |
| 1912 | - | /* | - |
| 1913 | - | * Make sure the subselect delivers a single column (ignoring resjunk | - |
| 1914 | - | * targets). | - |
| 1915 | - | */ | - |
| 1916 | - | if (count_nonjunk_tlist_entries(qtree->targetList) != 1) | - |
| 1917 | - | ereport(ERROR, | - |
| 1918 | - | (errcode(ERRCODE_SYNTAX_ERROR), | - |
| 1919 | - | errmsg("subquery must return only one column"), | - |
| 1920 | - | parser_errposition(pstate, sublink->location))); | - |
| 1921 | - | - | |
| 1922 | - | /* | - |
| 1923 | - | * EXPR and ARRAY need no test expression or combining operator. These | - |
| 1924 | - | * fields should be null already, but make sure. | - |
| 1925 | - | */ | - |
| 1926 | - | sublink->testexpr = NULL; | - |
| 1927 | - | sublink->operName = NIL; | - |
| 1928 | - | } | - |
| 1929 | - | else if (sublink->subLinkType == MULTIEXPR_SUBLINK) | - |
| 1930 | - | { | - |
| 1931 | - | /* Same as EXPR case, except no restriction on number of columns */ | - |
| 1932 | - | sublink->testexpr = NULL; | - |
| 1933 | - | sublink->operName = NIL; | - |
| 1934 | - | } | - |
| 1935 | - | else | - |
| 1936 | - | { | - |
| 1937 | - | /* ALL, ANY, or ROWCOMPARE: generate row-comparing expression */ | - |
| 1938 | - | Node *lefthand; | - |
| 1939 | - | List *left_list; | - |
| 1940 | - | List *right_list; | - |
| 1941 | - | ListCell *l; | - |
| 1942 | - | - | |
| 1943 | - | /* | - |
| 1944 | - | * If the source was "x IN (select)", convert to "x = ANY (select)". | - |
| 1945 | - | */ | - |
| 1946 | - | if (sublink->operName == NIL) | - |
| 1947 | - | sublink->operName = list_make1(makeString("=")); | - |
| 1948 | - | - | |
| 1949 | - | /* | - |
| 1950 | - | * Transform lefthand expression, and convert to a list | - |
| 1951 | - | */ | - |
| 1952 | - | lefthand = transformExprRecurse(pstate, sublink->testexpr); | - |
| 1953 | - | if (lefthand && IsA(lefthand, RowExpr)) | - |
| 1954 | - | left_list = ((RowExpr *) lefthand)->args; | - |
| 1955 | - | else | - |
| 1956 | - | left_list = list_make1(lefthand); | - |
| 1957 | - | - | |
| 1958 | - | /* | - |
| 1959 | - | * Build a list of PARAM_SUBLINK nodes representing the output columns | - |
| 1960 | - | * of the subquery. | - |
| 1961 | - | */ | - |
| 1962 | - | right_list = NIL; | - |
| 1963 | - | foreach(l, qtree->targetList) | - |
| 1964 | - | { | - |
| 1965 | - | TargetEntry *tent = (TargetEntry *) lfirst(l); | - |
| 1966 | - | Param *param; | - |
| 1967 | - | - | |
| 1968 | - | if (tent->resjunk) | - |
| 1969 | - | continue; | - |
| 1970 | - | - | |
| 1971 | - | param = makeNode(Param); | - |
| 1972 | - | param->paramkind = PARAM_SUBLINK; | - |
| 1973 | - | param->paramid = tent->resno; | - |
| 1974 | - | param->paramtype = exprType((Node *) tent->expr); | - |
| 1975 | - | param->paramtypmod = exprTypmod((Node *) tent->expr); | - |
| 1976 | - | param->paramcollid = exprCollation((Node *) tent->expr); | - |
| 1977 | - | param->location = -1; | - |
| 1978 | - | - | |
| 1979 | - | right_list = lappend(right_list, param); | - |
| 1980 | - | } | - |
| 1981 | - | - | |
| 1982 | - | /* | - |
| 1983 | - | * We could rely on make_row_comparison_op to complain if the list | - |
| 1984 | - | * lengths differ, but we prefer to generate a more specific error | - |
| 1985 | - | * message. | - |
| 1986 | - | */ | - |
| 1987 | - | if (list_length(left_list) < list_length(right_list)) | - |
| 1988 | - | ereport(ERROR, | - |
| 1989 | - | (errcode(ERRCODE_SYNTAX_ERROR), | - |
| 1990 | - | errmsg("subquery has too many columns"), | - |
| 1991 | - | parser_errposition(pstate, sublink->location))); | - |
| 1992 | - | if (list_length(left_list) > list_length(right_list)) | - |
| 1993 | - | ereport(ERROR, | - |
| 1994 | - | (errcode(ERRCODE_SYNTAX_ERROR), | - |
| 1995 | - | errmsg("subquery has too few columns"), | - |
| 1996 | - | parser_errposition(pstate, sublink->location))); | - |
| 1997 | - | - | |
| 1998 | - | /* | - |
| 1999 | - | * Identify the combining operator(s) and generate a suitable | - |
| 2000 | - | * row-comparison expression. | - |
| 2001 | - | */ | - |
| 2002 | - | sublink->testexpr = make_row_comparison_op(pstate, | - |
| 2003 | - | sublink->operName, | - |
| 2004 | - | left_list, | - |
| 2005 | - | right_list, | - |
| 2006 | - | sublink->location); | - |
| 2007 | - | } | - |
| 2008 | - | - | |
| 2009 | - | return result; | - |
| 2010 | - | } | - |
| Line | Hits | Source | Commit |
|---|---|---|---|
| 3138 | - | ParseExprKindName(ParseExprKind exprKind) | - |
| 3139 | - | { | - |
| 3140 | - | switch (exprKind) | - |
| 3141 | - | { | - |
| 3142 | - | case EXPR_KIND_NONE: | - |
| 3143 | - | return "invalid expression context"; | - |
| 3144 | - | case EXPR_KIND_OTHER: | - |
| 3145 | - | return "extension expression"; | - |
| 3146 | - | case EXPR_KIND_JOIN_ON: | - |
| 3147 | - | return "JOIN/ON"; | - |
| 3148 | - | case EXPR_KIND_JOIN_USING: | - |
| 3149 | - | return "JOIN/USING"; | - |
| 3150 | - | case EXPR_KIND_FROM_SUBSELECT: | - |
| 3151 | - | return "sub-SELECT in FROM"; | - |
| 3152 | - | case EXPR_KIND_FROM_FUNCTION: | - |
| 3153 | - | return "function in FROM"; | - |
| 3154 | - | case EXPR_KIND_WHERE: | - |
| 3155 | - | return "WHERE"; | - |
| 3156 | - | case EXPR_KIND_POLICY: | - |
| 3157 | - | return "POLICY"; | - |
| 3158 | - | case EXPR_KIND_HAVING: | - |
| 3159 | - | return "HAVING"; | - |
| 3160 | - | case EXPR_KIND_FILTER: | - |
| 3161 | - | return "FILTER"; | - |
| 3162 | - | case EXPR_KIND_WINDOW_PARTITION: | - |
| 3163 | - | return "window PARTITION BY"; | - |
| 3164 | - | case EXPR_KIND_WINDOW_ORDER: | - |
| 3165 | - | return "window ORDER BY"; | - |
| 3166 | - | case EXPR_KIND_WINDOW_FRAME_RANGE: | - |
| 3167 | - | return "window RANGE"; | - |
| 3168 | - | case EXPR_KIND_WINDOW_FRAME_ROWS: | - |
| 3169 | - | return "window ROWS"; | - |
| 3170 | - | case EXPR_KIND_WINDOW_FRAME_GROUPS: | - |
| 3171 | - | return "window GROUPS"; | - |
| 3172 | - | case EXPR_KIND_SELECT_TARGET: | - |
| 3173 | - | return "SELECT"; | - |
| 3174 | - | case EXPR_KIND_INSERT_TARGET: | - |
| 3175 | - | return "INSERT"; | - |
| 3176 | - | case EXPR_KIND_UPDATE_SOURCE: | - |
| 3177 | - | case EXPR_KIND_UPDATE_TARGET: | - |
| 3178 | - | return "UPDATE"; | - |
| 3179 | - | case EXPR_KIND_MERGE_WHEN: | - |
| 3180 | - | return "MERGE WHEN"; | - |
| 3181 | - | case EXPR_KIND_GROUP_BY: | - |
| 3182 | - | return "GROUP BY"; | - |
| 3183 | - | case EXPR_KIND_ORDER_BY: | - |
| 3184 | - | return "ORDER BY"; | - |
| 3185 | - | case EXPR_KIND_DISTINCT_ON: | - |
| 3186 | - | return "DISTINCT ON"; | - |
| 3187 | - | case EXPR_KIND_LIMIT: | - |
| 3188 | - | return "LIMIT"; | - |
| 3189 | - | case EXPR_KIND_OFFSET: | - |
| 3190 | - | return "OFFSET"; | - |
| 3191 | - | case EXPR_KIND_RETURNING: | - |
| 3192 | - | case EXPR_KIND_MERGE_RETURNING: | - |
| 3193 | - | return "RETURNING"; | - |
| 3194 | - | case EXPR_KIND_VALUES: | - |
| 3195 | - | case EXPR_KIND_VALUES_SINGLE: | - |
| 3196 | - | return "VALUES"; | - |
| 3197 | - | case EXPR_KIND_CHECK_CONSTRAINT: | - |
| 3198 | - | case EXPR_KIND_DOMAIN_CHECK: | - |
| 3199 | - | return "CHECK"; | - |
| 3200 | - | case EXPR_KIND_COLUMN_DEFAULT: | - |
| 3201 | - | case EXPR_KIND_FUNCTION_DEFAULT: | - |
| 3202 | - | return "DEFAULT"; | - |
| 3203 | - | case EXPR_KIND_INDEX_EXPRESSION: | - |
| 3204 | - | return "index expression"; | - |
| 3205 | - | case EXPR_KIND_INDEX_PREDICATE: | - |
| 3206 | - | return "index predicate"; | - |
| 3207 | - | case EXPR_KIND_STATS_EXPRESSION: | - |
| 3208 | - | return "statistics expression"; | - |
| 3209 | - | case EXPR_KIND_ALTER_COL_TRANSFORM: | - |
| 3210 | - | return "USING"; | - |
| 3211 | - | case EXPR_KIND_EXECUTE_PARAMETER: | - |
| 3212 | - | return "EXECUTE"; | - |
| 3213 | - | case EXPR_KIND_TRIGGER_WHEN: | - |
| 3214 | - | return "WHEN"; | - |
| 3215 | - | case EXPR_KIND_PARTITION_BOUND: | - |
| 3216 | - | return "partition bound"; | - |
| 3217 | - | case EXPR_KIND_PARTITION_EXPRESSION: | - |
| 3218 | - | return "PARTITION BY"; | - |
| 3219 | - | case EXPR_KIND_CALL_ARGUMENT: | - |
| 3220 | - | return "CALL"; | - |
| 3221 | - | case EXPR_KIND_COPY_WHERE: | - |
| 3222 | - | return "WHERE"; | - |
| 3223 | - | case EXPR_KIND_GENERATED_COLUMN: | - |
| 3224 | - | return "GENERATED AS"; | - |
| 3225 | - | case EXPR_KIND_CYCLE_MARK: | - |
| 3226 | - | return "CYCLE"; | - |
| 3227 | 3 | case EXPR_KIND_RPR_DEFINE: | b8a35c3Row pattern recognition patch (parse/analysis). |
| 3228 | 3 | return "DEFINE"; | b8a35c3Row pattern recognition patch (parse/analysis). |
| 3229 | - | - | |
| 3230 | - | /* | - |
| 3231 | - | * There is intentionally no default: case here, so that the | - |
| 3232 | - | * compiler will warn if we add a new ParseExprKind without | - |
| 3233 | - | * extending this switch. If we do see an unrecognized value at | - |
| 3234 | - | * runtime, we'll fall through to the "unrecognized" return. | - |
| 3235 | - | */ | - |
| 3236 | - | } | - |
| 3237 | - | return "unrecognized expression kind"; | - |
| 3238 | - | } | - |