src/backend/parser/parse_expr.c - Coverage Report

← Back to Overview

# src/backend/parser/parse_expr.c

Coverage: 20/20 lines (100.0%)
Total Lines
20
modified
Covered
20
100.0%
Uncovered
0
0.0%
Keyboard navigation
transformColumnRef() lines 511-974
Modified Lines Coverage: 15/15 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
511 | - | transformColumnRef(ParseState *pstate, ColumnRef *cref) | -
512 | - | { | -
513 | - | Node *node = NULL; | -
514 | - | char *nspname = NULL; | -
515 | - | char *relname = NULL; | -
516 | - | char *colname = NULL; | -
517 | - | ParseNamespaceItem *nsitem; | -
518 | - | int levels_up; | -
519 | - | enum | -
520 | - | { | -
521 | - | CRERR_NO_COLUMN, | -
522 | - | CRERR_NO_RTE, | -
523 | - | CRERR_WRONG_DB, | -
524 | - | CRERR_TOO_MANY | -
525 | - | } crerr = CRERR_NO_COLUMN; | -
526 | - | const char *err; | -
527 | - |  | -
528 | - | /* | -
529 | - | * Check to see if the column reference is in an invalid place within the | -
530 | - | * query. We allow column references in most places, except in default | -
531 | - | * expressions and partition bound expressions. | -
532 | - | */ | -
533 | - | err = NULL; | -
534 | - | switch (pstate->p_expr_kind) | -
535 | - | { | -
536 | - | case EXPR_KIND_NONE: | -
537 | - | Assert(false); /* can't happen */ | -
538 | - | break; | -
539 | - | case EXPR_KIND_OTHER: | -
540 | - | case EXPR_KIND_JOIN_ON: | -
541 | - | case EXPR_KIND_JOIN_USING: | -
542 | - | case EXPR_KIND_FROM_SUBSELECT: | -
543 | - | case EXPR_KIND_FROM_FUNCTION: | -
544 | - | case EXPR_KIND_WHERE: | -
545 | - | case EXPR_KIND_POLICY: | -
546 | - | case EXPR_KIND_HAVING: | -
547 | - | case EXPR_KIND_FILTER: | -
548 | - | case EXPR_KIND_WINDOW_PARTITION: | -
549 | - | case EXPR_KIND_WINDOW_ORDER: | -
550 | - | case EXPR_KIND_WINDOW_FRAME_RANGE: | -
551 | - | case EXPR_KIND_WINDOW_FRAME_ROWS: | -
552 | - | case EXPR_KIND_WINDOW_FRAME_GROUPS: | -
553 | - | case EXPR_KIND_SELECT_TARGET: | -
554 | - | case EXPR_KIND_INSERT_TARGET: | -
555 | - | case EXPR_KIND_UPDATE_SOURCE: | -
556 | - | case EXPR_KIND_UPDATE_TARGET: | -
557 | - | case EXPR_KIND_MERGE_WHEN: | -
558 | - | case EXPR_KIND_GROUP_BY: | -
559 | - | case EXPR_KIND_ORDER_BY: | -
560 | - | case EXPR_KIND_DISTINCT_ON: | -
561 | - | case EXPR_KIND_LIMIT: | -
562 | - | case EXPR_KIND_OFFSET: | -
563 | - | case EXPR_KIND_RETURNING: | -
564 | - | case EXPR_KIND_MERGE_RETURNING: | -
565 | - | case EXPR_KIND_VALUES: | -
566 | - | case EXPR_KIND_VALUES_SINGLE: | -
567 | - | case EXPR_KIND_CHECK_CONSTRAINT: | -
568 | - | case EXPR_KIND_DOMAIN_CHECK: | -
569 | - | case EXPR_KIND_FUNCTION_DEFAULT: | -
570 | - | case EXPR_KIND_INDEX_EXPRESSION: | -
571 | - | case EXPR_KIND_INDEX_PREDICATE: | -
572 | - | case EXPR_KIND_STATS_EXPRESSION: | -
573 | - | case EXPR_KIND_ALTER_COL_TRANSFORM: | -
574 | - | case EXPR_KIND_EXECUTE_PARAMETER: | -
575 | - | case EXPR_KIND_TRIGGER_WHEN: | -
576 | - | case EXPR_KIND_PARTITION_EXPRESSION: | -
577 | - | case EXPR_KIND_CALL_ARGUMENT: | -
578 | - | case EXPR_KIND_COPY_WHERE: | -
579 | - | case EXPR_KIND_GENERATED_COLUMN: | -
580 | - | case EXPR_KIND_CYCLE_MARK: | -
581 | - | case EXPR_KIND_PROPGRAPH_PROPERTY: | -
582 | - | case EXPR_KIND_RPR_DEFINE: | c54ba27Row pattern recognition patch (parse/analysis).
583 | - | /* okay */ | -
584 | - | break; | -
585 | - |  | -
586 | - | case EXPR_KIND_COLUMN_DEFAULT: | -
587 | - | err = _("cannot use column reference in DEFAULT expression"); | -
588 | - | break; | -
589 | - | case EXPR_KIND_PARTITION_BOUND: | -
590 | - | err = _("cannot use column reference in partition bound expression"); | -
591 | - | break; | -
592 | - | case EXPR_KIND_FOR_PORTION: | -
593 | - | err = _("cannot use column reference in FOR PORTION OF expression"); | -
594 | - | break; | -
595 | - |  | -
596 | - | /* | -
597 | - | * There is intentionally no default: case here, so that the | -
598 | - | * compiler will warn if we add a new ParseExprKind without | -
599 | - | * extending this switch. If we do see an unrecognized value at | -
600 | - | * runtime, the behavior will be the same as for EXPR_KIND_OTHER, | -
601 | - | * which is sane anyway. | -
602 | - | */ | -
603 | - | } | -
604 | - | if (err) | -
605 | - | ereport(ERROR, | -
606 | - | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), | -
607 | - | errmsg_internal("%s", err), | -
608 | - | parser_errposition(pstate, cref->location))); | -
609 | - |  | -
610 | - | /* | -
611 | - | * Give the PreParseColumnRefHook, if any, first shot. If it returns | -
612 | - | * non-null then that's all, folks. | -
613 | - | */ | -
614 | - | if (pstate->p_pre_columnref_hook != NULL) | -
615 | - | { | -
616 | - | node = pstate->p_pre_columnref_hook(pstate, cref); | -
617 | - | if (node != NULL) | -
618 | - | return node; | -
619 | - | } | -
620 | - |  | -
621 | - | /* | -
622 | - | * Element pattern variables in a GRAPH_TABLE clause form the innermost | -
623 | - | * namespace since we do not allow subqueries in GRAPH_TABLE patterns. Try | -
624 | - | * to resolve the column reference as a graph table property reference | -
625 | - | * before trying to resolve it as a regular column reference. | -
626 | - | */ | -
627 | - | node = transformGraphTablePropertyRef(pstate, cref); | -
628 | - | if (node != NULL) | -
629 | - | return node; | -
630 | - |  | -
631 | - | /*---------- | c54ba27Row pattern recognition patch (parse/analysis).
632 | - | * Qualified references in DEFINE need a tri-classification: | c54ba27Row pattern recognition patch (parse/analysis).
633 | - | * | c54ba27Row pattern recognition patch (parse/analysis).
634 | - | * pattern variable qualifier (e.g. UP.price): valid per | c54ba27Row pattern recognition patch (parse/analysis).
635 | - | * ISO/IEC 19075-5 6.15 / 4.16 but not yet implemented -- | c54ba27Row pattern recognition patch (parse/analysis).
636 | - | * raise FEATURE_NOT_SUPPORTED. | c54ba27Row pattern recognition patch (parse/analysis).
637 | - | * | c54ba27Row pattern recognition patch (parse/analysis).
638 | - | * FROM-clause range variable qualifier: prohibited by | c54ba27Row pattern recognition patch (parse/analysis).
639 | - | * ISO/IEC 19075-5 6.5 -- raise SYNTAX_ERROR. | c54ba27Row pattern recognition patch (parse/analysis).
640 | - | * | c54ba27Row pattern recognition patch (parse/analysis).
641 | - | * any other qualifier (typo, undefined name): fall through and let | c54ba27Row pattern recognition patch (parse/analysis).
642 | - | * normal column resolution produce a sensible error. | c54ba27Row pattern recognition patch (parse/analysis).
643 | - | * | c54ba27Row pattern recognition patch (parse/analysis).
644 | - | * The quoted text reflects only the ColumnRef portion; a trailing field | c54ba27Row pattern recognition patch (parse/analysis).
645 | - | * selection on a composite type (e.g. ".amount" in "(A.items).amount") | c54ba27Row pattern recognition patch (parse/analysis).
646 | - | * lives in the surrounding A_Indirection node and is not included here. | c54ba27Row pattern recognition patch (parse/analysis).
647 | - | * That can be revisited when MEASURES support adds indirection-aware | c54ba27Row pattern recognition patch (parse/analysis).
648 | - | * traversal. | c54ba27Row pattern recognition patch (parse/analysis).
649 | - | *---------- | c54ba27Row pattern recognition patch (parse/analysis).
650 | - | */ | c54ba27Row pattern recognition patch (parse/analysis).
651 | 1173895 | if (pstate->p_expr_kind == EXPR_KIND_RPR_DEFINE && | c54ba27Row pattern recognition patch (parse/analysis).
652 | 10169 | list_length(cref->fields) != 1) | c54ba27Row pattern recognition patch (parse/analysis).
653 | - | { | c54ba27Row pattern recognition patch (parse/analysis).
654 | 40 | char *qualifier = strVal(linitial(cref->fields)); | c54ba27Row pattern recognition patch (parse/analysis).
655 | 40 | bool is_pattern_var = false; | c54ba27Row pattern recognition patch (parse/analysis).
656 | - |  | c54ba27Row pattern recognition patch (parse/analysis).
657 | 72 | foreach_node(String, pv, pstate->p_rpr_pattern_vars) | c54ba27Row pattern recognition patch (parse/analysis).
658 | - | { | c54ba27Row pattern recognition patch (parse/analysis).
659 | 44 | if (strcmp(strVal(pv), qualifier) == 0) | c54ba27Row pattern recognition patch (parse/analysis).
660 | - | { | c54ba27Row pattern recognition patch (parse/analysis).
661 | - | is_pattern_var = true; | c54ba27Row pattern recognition patch (parse/analysis).
662 | - | break; | c54ba27Row pattern recognition patch (parse/analysis).
663 | - | } | c54ba27Row pattern recognition patch (parse/analysis).
664 | - | } | c54ba27Row pattern recognition patch (parse/analysis).
665 | - |  | c54ba27Row pattern recognition patch (parse/analysis).
666 | 40 | if (is_pattern_var) | c54ba27Row pattern recognition patch (parse/analysis).
667 | 12 | ereport(ERROR, | c54ba27Row pattern recognition patch (parse/analysis).
668 | - | errcode(ERRCODE_FEATURE_NOT_SUPPORTED), | c54ba27Row pattern recognition patch (parse/analysis).
669 | - | errmsg("pattern variable qualified expression \"%s\" is not supported in DEFINE clause", | c54ba27Row pattern recognition patch (parse/analysis).
670 | - | NameListToString(cref->fields)), | c54ba27Row pattern recognition patch (parse/analysis).
671 | - | parser_errposition(pstate, cref->location)); | c54ba27Row pattern recognition patch (parse/analysis).
672 | 28 | else if (refnameNamespaceItem(pstate, NULL, qualifier, | c54ba27Row pattern recognition patch (parse/analysis).
673 | - | cref->location, NULL) != NULL) | c54ba27Row pattern recognition patch (parse/analysis).
674 | 8 | ereport(ERROR, | c54ba27Row pattern recognition patch (parse/analysis).
675 | - | errcode(ERRCODE_SYNTAX_ERROR), | c54ba27Row pattern recognition patch (parse/analysis).
676 | - | errmsg("range variable qualified expression \"%s\" is not allowed in DEFINE clause", | c54ba27Row pattern recognition patch (parse/analysis).
677 | - | NameListToString(cref->fields)), | c54ba27Row pattern recognition patch (parse/analysis).
678 | - | parser_errposition(pstate, cref->location)); | c54ba27Row pattern recognition patch (parse/analysis).
679 | - | /* else: unknown qualifier -- fall through to normal resolution */ | c54ba27Row pattern recognition patch (parse/analysis).
680 | - | } | c54ba27Row pattern recognition patch (parse/analysis).
681 | - |  | c54ba27Row pattern recognition patch (parse/analysis).
682 | - | /*---------- | -
683 | - | * The allowed syntaxes are: | -
684 | - | * | -
685 | - | * A First try to resolve as unqualified column name; | -
686 | - | * if no luck, try to resolve as unqualified table name (A.*). | -
687 | - | * A.B A is an unqualified table name; B is either a | -
688 | - | * column or function name (trying column name first). | -
689 | - | * A.B.C schema A, table B, col or func name C. | -
690 | - | * A.B.C.D catalog A, schema B, table C, col or func D. | -
691 | - | * A.* A is an unqualified table name; means whole-row value. | -
692 | - | * A.B.* whole-row value of table B in schema A. | -
693 | - | * A.B.C.* whole-row value of table C in schema B in catalog A. | -
694 | - | * | -
695 | - | * We do not need to cope with bare "*"; that will only be accepted by | -
696 | - | * the grammar at the top level of a SELECT list, and transformTargetList | -
697 | - | * will take care of it before it ever gets here. Also, "A.*" etc will | -
698 | - | * be expanded by transformTargetList if they appear at SELECT top level, | -
699 | - | * so here we are only going to see them as function or operator inputs. | -
700 | - | * | -
701 | - | * Currently, if a catalog name is given then it must equal the current | -
702 | - | * database name; we check it here and then discard it. | -
703 | - | *---------- | -
704 | - | */ | -
705 | - | switch (list_length(cref->fields)) | -
706 | - | { | -
707 | - | case 1: | -
708 | - | { | -
709 | - | Node *field1 = (Node *) linitial(cref->fields); | -
710 | - |  | -
711 | - | colname = strVal(field1); | -
712 | - |  | -
713 | - | /* Try to identify as an unqualified column */ | -
714 | - | node = colNameToVar(pstate, colname, false, cref->location); | -
715 | - |  | -
716 | - | if (node == NULL) | -
717 | - | { | -
718 | - | /* | -
719 | - | * Not known as a column of any range-table entry. | -
720 | - | * | -
721 | - | * Try to find the name as a relation. Note that only | -
722 | - | * relations already entered into the rangetable will be | -
723 | - | * recognized. | -
724 | - | * | -
725 | - | * This is a hack for backwards compatibility with | -
726 | - | * PostQUEL-inspired syntax. The preferred form now is | -
727 | - | * "rel.*". | -
728 | - | */ | -
729 | - | nsitem = refnameNamespaceItem(pstate, NULL, colname, | -
730 | - | cref->location, | -
731 | - | &levels_up); | -
732 | - | if (nsitem) | -
733 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | -
734 | - | cref->location); | -
735 | - | } | -
736 | - | break; | -
737 | - | } | -
738 | - | case 2: | -
739 | - | { | -
740 | - | Node *field1 = (Node *) linitial(cref->fields); | -
741 | - | Node *field2 = (Node *) lsecond(cref->fields); | -
742 | - |  | -
743 | - | relname = strVal(field1); | -
744 | - |  | -
745 | - | /* Locate the referenced nsitem */ | -
746 | - | nsitem = refnameNamespaceItem(pstate, nspname, relname, | -
747 | - | cref->location, | -
748 | - | &levels_up); | -
749 | - | if (nsitem == NULL) | -
750 | - | { | -
751 | - | crerr = CRERR_NO_RTE; | -
752 | - | break; | -
753 | - | } | -
754 | - |  | -
755 | - | /* Whole-row reference? */ | -
756 | - | if (IsA(field2, A_Star)) | -
757 | - | { | -
758 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | -
759 | - | cref->location); | -
760 | - | break; | -
761 | - | } | -
762 | - |  | -
763 | - | colname = strVal(field2); | -
764 | - |  | -
765 | - | /* Try to identify as a column of the nsitem */ | -
766 | - | node = scanNSItemForColumn(pstate, nsitem, levels_up, colname, | -
767 | - | cref->location); | -
768 | - | if (node == NULL) | -
769 | - | { | -
770 | - | /* Try it as a function call on the whole row */ | -
771 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | -
772 | - | cref->location); | -
773 | - | node = ParseFuncOrColumn(pstate, | -
774 | - | list_make1(makeString(colname)), | -
775 | - | list_make1(node), | -
776 | - | pstate->p_last_srf, | -
777 | - | NULL, | -
778 | - | false, | -
779 | - | cref->location); | -
780 | - | } | -
781 | - | break; | -
782 | - | } | -
783 | - | case 3: | -
784 | - | { | -
785 | - | Node *field1 = (Node *) linitial(cref->fields); | -
786 | - | Node *field2 = (Node *) lsecond(cref->fields); | -
787 | - | Node *field3 = (Node *) lthird(cref->fields); | -
788 | - |  | -
789 | - | nspname = strVal(field1); | -
790 | - | relname = strVal(field2); | -
791 | - |  | -
792 | - | /* Locate the referenced nsitem */ | -
793 | - | nsitem = refnameNamespaceItem(pstate, nspname, relname, | -
794 | - | cref->location, | -
795 | - | &levels_up); | -
796 | - | if (nsitem == NULL) | -
797 | - | { | -
798 | - | crerr = CRERR_NO_RTE; | -
799 | - | break; | -
800 | - | } | -
801 | - |  | -
802 | - | /* Whole-row reference? */ | -
803 | - | if (IsA(field3, A_Star)) | -
804 | - | { | -
805 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | -
806 | - | cref->location); | -
807 | - | break; | -
808 | - | } | -
809 | - |  | -
810 | - | colname = strVal(field3); | -
811 | - |  | -
812 | - | /* Try to identify as a column of the nsitem */ | -
813 | - | node = scanNSItemForColumn(pstate, nsitem, levels_up, colname, | -
814 | - | cref->location); | -
815 | - | if (node == NULL) | -
816 | - | { | -
817 | - | /* Try it as a function call on the whole row */ | -
818 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | -
819 | - | cref->location); | -
820 | - | node = ParseFuncOrColumn(pstate, | -
821 | - | list_make1(makeString(colname)), | -
822 | - | list_make1(node), | -
823 | - | pstate->p_last_srf, | -
824 | - | NULL, | -
825 | - | false, | -
826 | - | cref->location); | -
827 | - | } | -
828 | - | break; | -
829 | - | } | -
830 | - | case 4: | -
831 | - | { | -
832 | - | Node *field1 = (Node *) linitial(cref->fields); | -
833 | - | Node *field2 = (Node *) lsecond(cref->fields); | -
834 | - | Node *field3 = (Node *) lthird(cref->fields); | -
835 | - | Node *field4 = (Node *) lfourth(cref->fields); | -
836 | - | char *catname; | -
837 | - |  | -
838 | - | catname = strVal(field1); | -
839 | - | nspname = strVal(field2); | -
840 | - | relname = strVal(field3); | -
841 | - |  | -
842 | - | /* | -
843 | - | * We check the catalog name and then ignore it. | -
844 | - | */ | -
845 | - | if (strcmp(catname, get_database_name(MyDatabaseId)) != 0) | -
846 | - | { | -
847 | - | crerr = CRERR_WRONG_DB; | -
848 | - | break; | -
849 | - | } | -
850 | - |  | -
851 | - | /* Locate the referenced nsitem */ | -
852 | - | nsitem = refnameNamespaceItem(pstate, nspname, relname, | -
853 | - | cref->location, | -
854 | - | &levels_up); | -
855 | - | if (nsitem == NULL) | -
856 | - | { | -
857 | - | crerr = CRERR_NO_RTE; | -
858 | - | break; | -
859 | - | } | -
860 | - |  | -
861 | - | /* Whole-row reference? */ | -
862 | - | if (IsA(field4, A_Star)) | -
863 | - | { | -
864 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | -
865 | - | cref->location); | -
866 | - | break; | -
867 | - | } | -
868 | - |  | -
869 | - | colname = strVal(field4); | -
870 | - |  | -
871 | - | /* Try to identify as a column of the nsitem */ | -
872 | - | node = scanNSItemForColumn(pstate, nsitem, levels_up, colname, | -
873 | - | cref->location); | -
874 | - | if (node == NULL) | -
875 | - | { | -
876 | - | /* Try it as a function call on the whole row */ | -
877 | - | node = transformWholeRowRef(pstate, nsitem, levels_up, | -
878 | - | cref->location); | -
879 | - | node = ParseFuncOrColumn(pstate, | -
880 | - | list_make1(makeString(colname)), | -
881 | - | list_make1(node), | -
882 | - | pstate->p_last_srf, | -
883 | - | NULL, | -
884 | - | false, | -
885 | - | cref->location); | -
886 | - | } | -
887 | - | break; | -
888 | - | } | -
889 | - | default: | -
890 | - | crerr = CRERR_TOO_MANY; /* too many dotted names */ | -
891 | - | break; | -
892 | - | } | -
893 | - |  | -
894 | - | /* | -
895 | - | * Now give the PostParseColumnRefHook, if any, a chance. We pass the | -
896 | - | * translation-so-far so that it can throw an error if it wishes in the | -
897 | - | * case that it has a conflicting interpretation of the ColumnRef. (If it | -
898 | - | * just translates anyway, we'll throw an error, because we can't undo | -
899 | - | * whatever effects the preceding steps may have had on the pstate.) If it | -
900 | - | * returns NULL, use the standard translation, or throw a suitable error | -
901 | - | * if there is none. | -
902 | - | */ | -
903 | - | if (pstate->p_post_columnref_hook != NULL) | -
904 | - | { | -
905 | - | Node *hookresult; | -
906 | - |  | -
907 | - | hookresult = pstate->p_post_columnref_hook(pstate, cref, node); | -
908 | - | if (node == NULL) | -
909 | - | node = hookresult; | -
910 | - | else if (hookresult != NULL) | -
911 | - | ereport(ERROR, | -
912 | - | (errcode(ERRCODE_AMBIGUOUS_COLUMN), | -
913 | - | errmsg("column reference \"%s\" is ambiguous", | -
914 | - | NameListToString(cref->fields)), | -
915 | - | parser_errposition(pstate, cref->location))); | -
916 | - | } | -
917 | - |  | -
918 | - | /* | -
919 | - | * Throw error if no translation found. | -
920 | - | */ | -
921 | - | if (node == NULL) | -
922 | - | { | -
923 | - | switch (crerr) | -
924 | - | { | -
925 | - | case CRERR_NO_COLUMN: | -
926 | - | errorMissingColumn(pstate, relname, colname, cref->location); | -
927 | - | break; | -
928 | - | case CRERR_NO_RTE: | -
929 | - | errorMissingRTE(pstate, makeRangeVar(nspname, relname, | -
930 | - | cref->location)); | -
931 | - | break; | -
932 | - | case CRERR_WRONG_DB: | -
933 | - | ereport(ERROR, | -
934 | - | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), | -
935 | - | errmsg("cross-database references are not implemented: %s", | -
936 | - | NameListToString(cref->fields)), | -
937 | - | parser_errposition(pstate, cref->location))); | -
938 | - | break; | -
939 | - | case CRERR_TOO_MANY: | -
940 | - | ereport(ERROR, | -
941 | - | (errcode(ERRCODE_SYNTAX_ERROR), | -
942 | - | errmsg("improper qualified name (too many dotted names): %s", | -
943 | - | NameListToString(cref->fields)), | -
944 | - | parser_errposition(pstate, cref->location))); | -
945 | - | break; | -
946 | - | } | -
947 | - | } | -
948 | - |  | -
949 | - | /* | c54ba27Row pattern recognition patch (parse/analysis).
950 | - | * Restrict column references in a row pattern DEFINE clause. node is now | c54ba27Row pattern recognition patch (parse/analysis).
951 | - | * a successfully resolved reference, so reject the two forms RPR does not | c54ba27Row pattern recognition patch (parse/analysis).
952 | - | * allow: a correlated reference to an outer query's column, and a | c54ba27Row pattern recognition patch (parse/analysis).
953 | - | * schema/catalog-qualified reference (three or more name parts). Simple | c54ba27Row pattern recognition patch (parse/analysis).
954 | - | * two-part qualifiers (pattern or range variable) are handled earlier, | c54ba27Row pattern recognition patch (parse/analysis).
955 | - | * before resolution. | c54ba27Row pattern recognition patch (parse/analysis).
956 | - | */ | c54ba27Row pattern recognition patch (parse/analysis).
957 | 1173462 | if (pstate->p_expr_kind == EXPR_KIND_RPR_DEFINE) | c54ba27Row pattern recognition patch (parse/analysis).
958 | - | { | c54ba27Row pattern recognition patch (parse/analysis).
959 | 10141 | if (IsA(node, Var) && ((Var *) node)->varlevelsup > 0) | c54ba27Row pattern recognition patch (parse/analysis).
960 | 12 | ereport(ERROR, | c54ba27Row pattern recognition patch (parse/analysis).
961 | - | errcode(ERRCODE_FEATURE_NOT_SUPPORTED), | c54ba27Row pattern recognition patch (parse/analysis).
962 | - | errmsg("cannot use outer query column in DEFINE clause"), | c54ba27Row pattern recognition patch (parse/analysis).
963 | - | parser_errposition(pstate, cref->location)); | c54ba27Row pattern recognition patch (parse/analysis).
964 | - |  | c54ba27Row pattern recognition patch (parse/analysis).
965 | 10129 | if (list_length(cref->fields) >= 3) | c54ba27Row pattern recognition patch (parse/analysis).
966 | 8 | ereport(ERROR, | c54ba27Row pattern recognition patch (parse/analysis).
967 | - | errcode(ERRCODE_SYNTAX_ERROR), | c54ba27Row pattern recognition patch (parse/analysis).
968 | - | errmsg("qualified expression \"%s\" is not allowed in DEFINE clause", | c54ba27Row pattern recognition patch (parse/analysis).
969 | - | NameListToString(cref->fields)), | c54ba27Row pattern recognition patch (parse/analysis).
970 | - | parser_errposition(pstate, cref->location)); | c54ba27Row pattern recognition patch (parse/analysis).
971 | - | } | c54ba27Row pattern recognition patch (parse/analysis).
972 | - |  | c54ba27Row pattern recognition patch (parse/analysis).
973 | - | return node; | -
974 | - | } | -

transformSubLink() lines 1874-2138
Modified Lines Coverage: 3/3 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
1874 | - | transformSubLink(ParseState *pstate, SubLink *sublink) | -
1875 | - | { | -
1876 | - | Node *result = (Node *) sublink; | -
1877 | - | Query *qtree; | -
1878 | - | const char *err; | -
1879 | - |  | -
1880 | - | /* | -
1881 | - | * Check to see if the sublink is in an invalid place within the query. We | -
1882 | - | * allow sublinks everywhere in SELECT/INSERT/UPDATE/DELETE/MERGE, but | -
1883 | - | * generally not in utility statements. | -
1884 | - | */ | -
1885 | - | err = NULL; | -
1886 | - | switch (pstate->p_expr_kind) | -
1887 | - | { | -
1888 | - | case EXPR_KIND_NONE: | -
1889 | - | Assert(false); /* can't happen */ | -
1890 | - | break; | -
1891 | - | case EXPR_KIND_OTHER: | -
1892 | - | /* Accept sublink here; caller must throw error if wanted */ | -
1893 | - | break; | -
1894 | - | case EXPR_KIND_JOIN_ON: | -
1895 | - | case EXPR_KIND_JOIN_USING: | -
1896 | - | case EXPR_KIND_FROM_SUBSELECT: | -
1897 | - | case EXPR_KIND_FROM_FUNCTION: | -
1898 | - | case EXPR_KIND_WHERE: | -
1899 | - | case EXPR_KIND_POLICY: | -
1900 | - | case EXPR_KIND_HAVING: | -
1901 | - | case EXPR_KIND_FILTER: | -
1902 | - | case EXPR_KIND_WINDOW_PARTITION: | -
1903 | - | case EXPR_KIND_WINDOW_ORDER: | -
1904 | - | case EXPR_KIND_WINDOW_FRAME_RANGE: | -
1905 | - | case EXPR_KIND_WINDOW_FRAME_ROWS: | -
1906 | - | case EXPR_KIND_WINDOW_FRAME_GROUPS: | -
1907 | - | case EXPR_KIND_SELECT_TARGET: | -
1908 | - | case EXPR_KIND_INSERT_TARGET: | -
1909 | - | case EXPR_KIND_UPDATE_SOURCE: | -
1910 | - | case EXPR_KIND_UPDATE_TARGET: | -
1911 | - | case EXPR_KIND_MERGE_WHEN: | -
1912 | - | case EXPR_KIND_GROUP_BY: | -
1913 | - | case EXPR_KIND_ORDER_BY: | -
1914 | - | case EXPR_KIND_DISTINCT_ON: | -
1915 | - | case EXPR_KIND_LIMIT: | -
1916 | - | case EXPR_KIND_OFFSET: | -
1917 | - | case EXPR_KIND_RETURNING: | -
1918 | - | case EXPR_KIND_MERGE_RETURNING: | -
1919 | - | case EXPR_KIND_VALUES: | -
1920 | - | case EXPR_KIND_VALUES_SINGLE: | -
1921 | - | case EXPR_KIND_CYCLE_MARK: | -
1922 | - | /* okay */ | -
1923 | - | break; | -
1924 | - | case EXPR_KIND_CHECK_CONSTRAINT: | -
1925 | - | case EXPR_KIND_DOMAIN_CHECK: | -
1926 | - | err = _("cannot use subquery in check constraint"); | -
1927 | - | break; | -
1928 | - | case EXPR_KIND_COLUMN_DEFAULT: | -
1929 | - | case EXPR_KIND_FUNCTION_DEFAULT: | -
1930 | - | err = _("cannot use subquery in DEFAULT expression"); | -
1931 | - | break; | -
1932 | - | case EXPR_KIND_INDEX_EXPRESSION: | -
1933 | - | err = _("cannot use subquery in index expression"); | -
1934 | - | break; | -
1935 | - | case EXPR_KIND_INDEX_PREDICATE: | -
1936 | - | err = _("cannot use subquery in index predicate"); | -
1937 | - | break; | -
1938 | - | case EXPR_KIND_STATS_EXPRESSION: | -
1939 | - | err = _("cannot use subquery in statistics expression"); | -
1940 | - | break; | -
1941 | - | case EXPR_KIND_ALTER_COL_TRANSFORM: | -
1942 | - | err = _("cannot use subquery in transform expression"); | -
1943 | - | break; | -
1944 | - | case EXPR_KIND_EXECUTE_PARAMETER: | -
1945 | - | err = _("cannot use subquery in EXECUTE parameter"); | -
1946 | - | break; | -
1947 | - | case EXPR_KIND_TRIGGER_WHEN: | -
1948 | - | err = _("cannot use subquery in trigger WHEN condition"); | -
1949 | - | break; | -
1950 | - | case EXPR_KIND_PARTITION_BOUND: | -
1951 | - | err = _("cannot use subquery in partition bound"); | -
1952 | - | break; | -
1953 | - | case EXPR_KIND_PARTITION_EXPRESSION: | -
1954 | - | err = _("cannot use subquery in partition key expression"); | -
1955 | - | break; | -
1956 | - | case EXPR_KIND_CALL_ARGUMENT: | -
1957 | - | err = _("cannot use subquery in CALL argument"); | -
1958 | - | break; | -
1959 | - | case EXPR_KIND_COPY_WHERE: | -
1960 | - | err = _("cannot use subquery in COPY FROM WHERE condition"); | -
1961 | - | break; | -
1962 | - | case EXPR_KIND_GENERATED_COLUMN: | -
1963 | - | err = _("cannot use subquery in column generation expression"); | -
1964 | - | break; | -
1965 | - | case EXPR_KIND_PROPGRAPH_PROPERTY: | -
1966 | - | err = _("cannot use subquery in property definition expression"); | -
1967 | - | break; | -
1968 | - | case EXPR_KIND_FOR_PORTION: | -
1969 | - | err = _("cannot use subquery in FOR PORTION OF expression"); | -
1970 | - | break; | -
1971 | - |  | -
1972 | - | /*---------- | c54ba27Row pattern recognition patch (parse/analysis).
1973 | - | * XXX SQL/RPR (ISO/IEC 19075-5 6.17.4 / 4.18.4; R020 / R010) | c54ba27Row pattern recognition patch (parse/analysis).
1974 | - | * permits a subquery nested in a DEFINE expression provided | c54ba27Row pattern recognition patch (parse/analysis).
1975 | - | * that: | c54ba27Row pattern recognition patch (parse/analysis).
1976 | - | * (a) the subquery does not itself perform row pattern | c54ba27Row pattern recognition patch (parse/analysis).
1977 | - | * recognition, and | c54ba27Row pattern recognition patch (parse/analysis).
1978 | - | * (b) the subquery does not reference a row pattern variable | c54ba27Row pattern recognition patch (parse/analysis).
1979 | - | * of the outer query. | c54ba27Row pattern recognition patch (parse/analysis).
1980 | - | * | c54ba27Row pattern recognition patch (parse/analysis).
1981 | - | * We reject all subqueries here for now. Implementing the | c54ba27Row pattern recognition patch (parse/analysis).
1982 | - | * case distinction would mean walking the analyzed subquery | c54ba27Row pattern recognition patch (parse/analysis).
1983 | - | * Query tree for nested RPR window clauses to enforce (a), | c54ba27Row pattern recognition patch (parse/analysis).
1984 | - | * and walking it for ColumnRef qualifiers matching any | c54ba27Row pattern recognition patch (parse/analysis).
1985 | - | * ancestor's p_rpr_pattern_vars to enforce (b). Both checks | c54ba27Row pattern recognition patch (parse/analysis).
1986 | - | * are doable with the existing infrastructure -- they are | c54ba27Row pattern recognition patch (parse/analysis).
1987 | - | * left as future work, not blocked on any other feature. | c54ba27Row pattern recognition patch (parse/analysis).
1988 | - | * Until then this blanket rejection is intentional | c54ba27Row pattern recognition patch (parse/analysis).
1989 | - | * over-rejection, not a standard fit; it subsumes both (a) | c54ba27Row pattern recognition patch (parse/analysis).
1990 | - | * and (b) by making the subquery itself unreachable. | c54ba27Row pattern recognition patch (parse/analysis).
1991 | - | *---------- | c54ba27Row pattern recognition patch (parse/analysis).
1992 | - | */ | c54ba27Row pattern recognition patch (parse/analysis).
1993 | 12 | case EXPR_KIND_RPR_DEFINE: | c54ba27Row pattern recognition patch (parse/analysis).
1994 | 12 | err = _("cannot use subquery in DEFINE expression"); | c54ba27Row pattern recognition patch (parse/analysis).
1995 | 12 | break; | c54ba27Row pattern recognition patch (parse/analysis).
1996 | - |  | c54ba27Row pattern recognition patch (parse/analysis).
1997 | - | /* | -
1998 | - | * There is intentionally no default: case here, so that the | -
1999 | - | * compiler will warn if we add a new ParseExprKind without | -
2000 | - | * extending this switch. If we do see an unrecognized value at | -
2001 | - | * runtime, the behavior will be the same as for EXPR_KIND_OTHER, | -
2002 | - | * which is sane anyway. | -
2003 | - | */ | -
2004 | - | } | -
2005 | - | if (err) | -
2006 | - | ereport(ERROR, | -
2007 | - | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), | -
2008 | - | errmsg_internal("%s", err), | -
2009 | - | parser_errposition(pstate, sublink->location))); | -
2010 | - |  | -
2011 | - | pstate->p_hasSubLinks = true; | -
2012 | - |  | -
2013 | - | /* | -
2014 | - | * OK, let's transform the sub-SELECT. | -
2015 | - | */ | -
2016 | - | qtree = parse_sub_analyze(sublink->subselect, pstate, NULL, false, true); | -
2017 | - |  | -
2018 | - | /* | -
2019 | - | * Check that we got a SELECT. Anything else should be impossible given | -
2020 | - | * restrictions of the grammar, but check anyway. | -
2021 | - | */ | -
2022 | - | if (!IsA(qtree, Query) || | -
2023 | - | qtree->commandType != CMD_SELECT) | -
2024 | - | elog(ERROR, "unexpected non-SELECT command in SubLink"); | -
2025 | - |  | -
2026 | - | sublink->subselect = (Node *) qtree; | -
2027 | - |  | -
2028 | - | if (sublink->subLinkType == EXISTS_SUBLINK) | -
2029 | - | { | -
2030 | - | /* | -
2031 | - | * EXISTS needs no test expression or combining operator. These fields | -
2032 | - | * should be null already, but make sure. | -
2033 | - | */ | -
2034 | - | sublink->testexpr = NULL; | -
2035 | - | sublink->operName = NIL; | -
2036 | - | } | -
2037 | - | else if (sublink->subLinkType == EXPR_SUBLINK || | -
2038 | - | sublink->subLinkType == ARRAY_SUBLINK) | -
2039 | - | { | -
2040 | - | /* | -
2041 | - | * Make sure the subselect delivers a single column (ignoring resjunk | -
2042 | - | * targets). | -
2043 | - | */ | -
2044 | - | if (count_nonjunk_tlist_entries(qtree->targetList) != 1) | -
2045 | - | ereport(ERROR, | -
2046 | - | (errcode(ERRCODE_SYNTAX_ERROR), | -
2047 | - | errmsg("subquery must return only one column"), | -
2048 | - | parser_errposition(pstate, sublink->location))); | -
2049 | - |  | -
2050 | - | /* | -
2051 | - | * EXPR and ARRAY need no test expression or combining operator. These | -
2052 | - | * fields should be null already, but make sure. | -
2053 | - | */ | -
2054 | - | sublink->testexpr = NULL; | -
2055 | - | sublink->operName = NIL; | -
2056 | - | } | -
2057 | - | else if (sublink->subLinkType == MULTIEXPR_SUBLINK) | -
2058 | - | { | -
2059 | - | /* Same as EXPR case, except no restriction on number of columns */ | -
2060 | - | sublink->testexpr = NULL; | -
2061 | - | sublink->operName = NIL; | -
2062 | - | } | -
2063 | - | else | -
2064 | - | { | -
2065 | - | /* ALL, ANY, or ROWCOMPARE: generate row-comparing expression */ | -
2066 | - | Node *lefthand; | -
2067 | - | List *left_list; | -
2068 | - | List *right_list; | -
2069 | - | ListCell *l; | -
2070 | - |  | -
2071 | - | /* | -
2072 | - | * If the source was "x IN (select)", convert to "x = ANY (select)". | -
2073 | - | */ | -
2074 | - | if (sublink->operName == NIL) | -
2075 | - | sublink->operName = list_make1(makeString("=")); | -
2076 | - |  | -
2077 | - | /* | -
2078 | - | * Transform lefthand expression, and convert to a list | -
2079 | - | */ | -
2080 | - | lefthand = transformExprRecurse(pstate, sublink->testexpr); | -
2081 | - | if (lefthand && IsA(lefthand, RowExpr)) | -
2082 | - | left_list = ((RowExpr *) lefthand)->args; | -
2083 | - | else | -
2084 | - | left_list = list_make1(lefthand); | -
2085 | - |  | -
2086 | - | /* | -
2087 | - | * Build a list of PARAM_SUBLINK nodes representing the output columns | -
2088 | - | * of the subquery. | -
2089 | - | */ | -
2090 | - | right_list = NIL; | -
2091 | - | foreach(l, qtree->targetList) | -
2092 | - | { | -
2093 | - | TargetEntry *tent = (TargetEntry *) lfirst(l); | -
2094 | - | Param *param; | -
2095 | - |  | -
2096 | - | if (tent->resjunk) | -
2097 | - | continue; | -
2098 | - |  | -
2099 | - | param = makeNode(Param); | -
2100 | - | param->paramkind = PARAM_SUBLINK; | -
2101 | - | param->paramid = tent->resno; | -
2102 | - | param->paramtype = exprType((Node *) tent->expr); | -
2103 | - | param->paramtypmod = exprTypmod((Node *) tent->expr); | -
2104 | - | param->paramcollid = exprCollation((Node *) tent->expr); | -
2105 | - | param->location = -1; | -
2106 | - |  | -
2107 | - | right_list = lappend(right_list, param); | -
2108 | - | } | -
2109 | - |  | -
2110 | - | /* | -
2111 | - | * We could rely on make_row_comparison_op to complain if the list | -
2112 | - | * lengths differ, but we prefer to generate a more specific error | -
2113 | - | * message. | -
2114 | - | */ | -
2115 | - | if (list_length(left_list) < list_length(right_list)) | -
2116 | - | ereport(ERROR, | -
2117 | - | (errcode(ERRCODE_SYNTAX_ERROR), | -
2118 | - | errmsg("subquery has too many columns"), | -
2119 | - | parser_errposition(pstate, sublink->location))); | -
2120 | - | if (list_length(left_list) > list_length(right_list)) | -
2121 | - | ereport(ERROR, | -
2122 | - | (errcode(ERRCODE_SYNTAX_ERROR), | -
2123 | - | errmsg("subquery has too few columns"), | -
2124 | - | parser_errposition(pstate, sublink->location))); | -
2125 | - |  | -
2126 | - | /* | -
2127 | - | * Identify the combining operator(s) and generate a suitable | -
2128 | - | * row-comparison expression. | -
2129 | - | */ | -
2130 | - | sublink->testexpr = make_row_comparison_op(pstate, | -
2131 | - | sublink->operName, | -
2132 | - | left_list, | -
2133 | - | right_list, | -
2134 | - | sublink->location); | -
2135 | - | } | -
2136 | - |  | -
2137 | - | return result; | -
2138 | - | } | -

ParseExprKindName() lines 3266-3370
Modified Lines Coverage: 2/2 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3266 | - | ParseExprKindName(ParseExprKind exprKind) | -
3267 | - | { | -
3268 | - | switch (exprKind) | -
3269 | - | { | -
3270 | - | case EXPR_KIND_NONE: | -
3271 | - | return "invalid expression context"; | -
3272 | - | case EXPR_KIND_OTHER: | -
3273 | - | return "extension expression"; | -
3274 | - | case EXPR_KIND_JOIN_ON: | -
3275 | - | return "JOIN/ON"; | -
3276 | - | case EXPR_KIND_JOIN_USING: | -
3277 | - | return "JOIN/USING"; | -
3278 | - | case EXPR_KIND_FROM_SUBSELECT: | -
3279 | - | return "sub-SELECT in FROM"; | -
3280 | - | case EXPR_KIND_FROM_FUNCTION: | -
3281 | - | return "function in FROM"; | -
3282 | - | case EXPR_KIND_WHERE: | -
3283 | - | return "WHERE"; | -
3284 | - | case EXPR_KIND_POLICY: | -
3285 | - | return "POLICY"; | -
3286 | - | case EXPR_KIND_HAVING: | -
3287 | - | return "HAVING"; | -
3288 | - | case EXPR_KIND_FILTER: | -
3289 | - | return "FILTER"; | -
3290 | - | case EXPR_KIND_WINDOW_PARTITION: | -
3291 | - | return "window PARTITION BY"; | -
3292 | - | case EXPR_KIND_WINDOW_ORDER: | -
3293 | - | return "window ORDER BY"; | -
3294 | - | case EXPR_KIND_WINDOW_FRAME_RANGE: | -
3295 | - | return "window RANGE"; | -
3296 | - | case EXPR_KIND_WINDOW_FRAME_ROWS: | -
3297 | - | return "window ROWS"; | -
3298 | - | case EXPR_KIND_WINDOW_FRAME_GROUPS: | -
3299 | - | return "window GROUPS"; | -
3300 | - | case EXPR_KIND_SELECT_TARGET: | -
3301 | - | return "SELECT"; | -
3302 | - | case EXPR_KIND_INSERT_TARGET: | -
3303 | - | return "INSERT"; | -
3304 | - | case EXPR_KIND_UPDATE_SOURCE: | -
3305 | - | case EXPR_KIND_UPDATE_TARGET: | -
3306 | - | return "UPDATE"; | -
3307 | - | case EXPR_KIND_MERGE_WHEN: | -
3308 | - | return "MERGE WHEN"; | -
3309 | - | case EXPR_KIND_GROUP_BY: | -
3310 | - | return "GROUP BY"; | -
3311 | - | case EXPR_KIND_ORDER_BY: | -
3312 | - | return "ORDER BY"; | -
3313 | - | case EXPR_KIND_DISTINCT_ON: | -
3314 | - | return "DISTINCT ON"; | -
3315 | - | case EXPR_KIND_LIMIT: | -
3316 | - | return "LIMIT"; | -
3317 | - | case EXPR_KIND_OFFSET: | -
3318 | - | return "OFFSET"; | -
3319 | - | case EXPR_KIND_RETURNING: | -
3320 | - | case EXPR_KIND_MERGE_RETURNING: | -
3321 | - | return "RETURNING"; | -
3322 | - | case EXPR_KIND_VALUES: | -
3323 | - | case EXPR_KIND_VALUES_SINGLE: | -
3324 | - | return "VALUES"; | -
3325 | - | case EXPR_KIND_CHECK_CONSTRAINT: | -
3326 | - | case EXPR_KIND_DOMAIN_CHECK: | -
3327 | - | return "CHECK"; | -
3328 | - | case EXPR_KIND_COLUMN_DEFAULT: | -
3329 | - | case EXPR_KIND_FUNCTION_DEFAULT: | -
3330 | - | return "DEFAULT"; | -
3331 | - | case EXPR_KIND_INDEX_EXPRESSION: | -
3332 | - | return "index expression"; | -
3333 | - | case EXPR_KIND_INDEX_PREDICATE: | -
3334 | - | return "index predicate"; | -
3335 | - | case EXPR_KIND_STATS_EXPRESSION: | -
3336 | - | return "statistics expression"; | -
3337 | - | case EXPR_KIND_ALTER_COL_TRANSFORM: | -
3338 | - | return "USING"; | -
3339 | - | case EXPR_KIND_EXECUTE_PARAMETER: | -
3340 | - | return "EXECUTE"; | -
3341 | - | case EXPR_KIND_TRIGGER_WHEN: | -
3342 | - | return "WHEN"; | -
3343 | - | case EXPR_KIND_PARTITION_BOUND: | -
3344 | - | return "partition bound"; | -
3345 | - | case EXPR_KIND_PARTITION_EXPRESSION: | -
3346 | - | return "PARTITION BY"; | -
3347 | - | case EXPR_KIND_CALL_ARGUMENT: | -
3348 | - | return "CALL"; | -
3349 | - | case EXPR_KIND_COPY_WHERE: | -
3350 | - | return "WHERE"; | -
3351 | - | case EXPR_KIND_GENERATED_COLUMN: | -
3352 | - | return "GENERATED AS"; | -
3353 | - | case EXPR_KIND_CYCLE_MARK: | -
3354 | - | return "CYCLE"; | -
3355 | - | case EXPR_KIND_PROPGRAPH_PROPERTY: | -
3356 | - | return "property definition expression"; | -
3357 | - | case EXPR_KIND_FOR_PORTION: | -
3358 | - | return "FOR PORTION OF"; | -
3359 | 20 | case EXPR_KIND_RPR_DEFINE: | c54ba27Row pattern recognition patch (parse/analysis).
3360 | 20 | return "DEFINE"; | c54ba27Row pattern recognition patch (parse/analysis).
3361 | - |  | -
3362 | - | /* | -
3363 | - | * There is intentionally no default: case here, so that the | -
3364 | - | * compiler will warn if we add a new ParseExprKind without | -
3365 | - | * extending this switch. If we do see an unrecognized value at | -
3366 | - | * runtime, we'll fall through to the "unrecognized" return. | -
3367 | - | */ | -
3368 | - | } | -
3369 | - | return "unrecognized expression kind"; | -
3370 | - | } | -