@@ -757,8 +757,9 @@ decl_const :
757
757
decl_datatype :
758
758
{
759
759
/*
760
- * If there's a lookahead token, read_datatype
761
- * should consume it.
760
+ * If there's a lookahead token, read_datatype() will
761
+ * consume it, and then we must tell bison to forget
762
+ * it.
762
763
*/
763
764
$$ = read_datatype (yychar);
764
765
yyclearin;
@@ -2783,13 +2784,17 @@ read_sql_construct(int until,
2783
2784
return expr;
2784
2785
}
2785
2786
2787
+ /*
2788
+ * Read a datatype declaration, consuming the current lookahead token if any.
2789
+ * Returns a PLpgSQL_type struct.
2790
+ */
2786
2791
static PLpgSQL_type *
2787
2792
read_datatype(int tok)
2788
2793
{
2789
2794
StringInfoData ds;
2790
2795
char *type_name;
2791
2796
int startlocation;
2792
- PLpgSQL_type *result;
2797
+ PLpgSQL_type *result = NULL ;
2793
2798
int parenlevel = 0;
2794
2799
2795
2800
/* Should only be called while parsing DECLARE sections */
@@ -2799,11 +2804,15 @@ read_datatype(int tok)
2799
2804
if (tok == YYEMPTY)
2800
2805
tok = yylex();
2801
2806
2807
+ /* The current token is the start of what we'll pass to parse_datatype */
2802
2808
startlocation = yylloc;
2803
2809
2804
2810
/*
2805
- * If we have a simple or composite identifier, check for %TYPE
2806
- * and %ROWTYPE constructs.
2811
+ * If we have a simple or composite identifier, check for %TYPE and
2812
+ * %ROWTYPE constructs. (Note that if plpgsql_parse_wordtype et al fail
2813
+ * to recognize the identifier, we'll fall through and pass the whole
2814
+ * string to parse_datatype, which will assuredly give an unhelpful
2815
+ * "syntax error". Should we try to give a more specific error?)
2807
2816
*/
2808
2817
if (tok == T_WORD)
2809
2818
{
@@ -2815,18 +2824,10 @@ read_datatype(int tok)
2815
2824
tok = yylex();
2816
2825
if (tok_is_keyword(tok, &yylval,
2817
2826
K_TYPE, "type"))
2818
- {
2819
2827
result = plpgsql_parse_wordtype(dtname);
2820
- if (result)
2821
- return result;
2822
- }
2823
2828
else if (tok_is_keyword(tok, &yylval,
2824
2829
K_ROWTYPE, "rowtype"))
2825
- {
2826
2830
result = plpgsql_parse_wordrowtype(dtname);
2827
- if (result)
2828
- return result;
2829
- }
2830
2831
}
2831
2832
}
2832
2833
else if (plpgsql_token_is_unreserved_keyword(tok))
@@ -2839,18 +2840,10 @@ read_datatype(int tok)
2839
2840
tok = yylex();
2840
2841
if (tok_is_keyword(tok, &yylval,
2841
2842
K_TYPE, "type"))
2842
- {
2843
2843
result = plpgsql_parse_wordtype(dtname);
2844
- if (result)
2845
- return result;
2846
- }
2847
2844
else if (tok_is_keyword(tok, &yylval,
2848
2845
K_ROWTYPE, "rowtype"))
2849
- {
2850
2846
result = plpgsql_parse_wordrowtype(dtname);
2851
- if (result)
2852
- return result;
2853
- }
2854
2847
}
2855
2848
}
2856
2849
else if (tok == T_CWORD)
@@ -2863,21 +2856,56 @@ read_datatype(int tok)
2863
2856
tok = yylex();
2864
2857
if (tok_is_keyword(tok, &yylval,
2865
2858
K_TYPE, "type"))
2866
- {
2867
2859
result = plpgsql_parse_cwordtype(dtnames);
2868
- if (result)
2869
- return result;
2870
- }
2871
2860
else if (tok_is_keyword(tok, &yylval,
2872
2861
K_ROWTYPE, "rowtype"))
2873
- {
2874
2862
result = plpgsql_parse_cwordrowtype(dtnames);
2875
- if (result)
2876
- return result;
2877
- }
2878
2863
}
2879
2864
}
2880
2865
2866
+ /*
2867
+ * If we recognized a %TYPE or %ROWTYPE construct, see if it is followed
2868
+ * by array decoration: [ ARRAY ] [ '[' [ iconst ] ']' [ ... ] ]
2869
+ *
2870
+ * Like the core parser, we ignore the specific numbers and sizes of
2871
+ * dimensions; arrays of different dimensionality are still the same type
2872
+ * in Postgres.
2873
+ */
2874
+ if (result)
2875
+ {
2876
+ bool is_array = false;
2877
+
2878
+ tok = yylex();
2879
+ if (tok_is_keyword(tok, &yylval,
2880
+ K_ARRAY, "array"))
2881
+ {
2882
+ is_array = true;
2883
+ tok = yylex();
2884
+ }
2885
+ while (tok == '[')
2886
+ {
2887
+ is_array = true;
2888
+ tok = yylex();
2889
+ if (tok == ICONST)
2890
+ tok = yylex();
2891
+ if (tok != ']')
2892
+ yyerror("syntax error, expected \"]\"");
2893
+ tok = yylex();
2894
+ }
2895
+ plpgsql_push_back_token(tok);
2896
+
2897
+ if (is_array)
2898
+ result = plpgsql_build_datatype_arrayof(result);
2899
+
2900
+ return result;
2901
+ }
2902
+
2903
+ /*
2904
+ * Not %TYPE or %ROWTYPE, so scan to the end of the datatype declaration,
2905
+ * which could include typmod or array decoration. We are not very picky
2906
+ * here, instead relying on parse_datatype to complain about garbage. But
2907
+ * we must count parens to handle typmods within cursor_arg correctly.
2908
+ */
2881
2909
while (tok != ';')
2882
2910
{
2883
2911
if (tok == 0)
0 commit comments