diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/gram.y | 11 | ||||
-rw-r--r-- | src/backend/parser/parse_node.c | 59 | ||||
-rw-r--r-- | src/backend/parser/parse_target.c | 2 |
3 files changed, 48 insertions, 24 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index c4bed8a5ef7..223ef175dee 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -434,7 +434,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <node> columnDef columnOptions %type <defelt> def_elem reloption_elem old_aggr_elem operator_def_elem %type <node> def_arg columnElem where_clause where_or_current_clause - a_expr b_expr c_expr AexprConst indirection_el + a_expr b_expr c_expr AexprConst indirection_el opt_slice_bound columnref in_expr having_clause func_table array_expr ExclusionWhereClause %type <list> rowsfrom_item rowsfrom_list opt_col_def_list @@ -13191,19 +13191,26 @@ indirection_el: | '[' a_expr ']' { A_Indices *ai = makeNode(A_Indices); + ai->is_slice = false; ai->lidx = NULL; ai->uidx = $2; $$ = (Node *) ai; } - | '[' a_expr ':' a_expr ']' + | '[' opt_slice_bound ':' opt_slice_bound ']' { A_Indices *ai = makeNode(A_Indices); + ai->is_slice = true; ai->lidx = $2; ai->uidx = $4; $$ = (Node *) ai; } ; +opt_slice_bound: + a_expr { $$ = $1; } + | /*EMPTY*/ { $$ = NULL; } + ; + indirection: indirection_el { $$ = list_make1($1); } | indirection indirection_el { $$ = lappend($1, $2); } diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index 4130cbff5ed..591a1f3a681 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -311,18 +311,18 @@ transformArraySubscripts(ParseState *pstate, elementType = transformArrayType(&arrayType, &arrayTypMod); /* - * A list containing only single subscripts refers to a single array - * element. If any of the items are double subscripts (lower:upper), then - * the subscript expression means an array slice operation. In this case, - * we supply a default lower bound of 1 for any items that contain only a - * single subscript. We have to prescan the indirection list to see if - * there are any double subscripts. + * A list containing only simple subscripts refers to a single array + * element. If any of the items are slice specifiers (lower:upper), then + * the subscript expression means an array slice operation. In this case, + * we convert any non-slice items to slices by treating the single + * subscript as the upper bound and supplying an assumed lower bound of 1. + * We have to prescan the list to see if there are any slice items. */ foreach(idx, indirection) { A_Indices *ai = (A_Indices *) lfirst(idx); - if (ai->lidx != NULL) + if (ai->is_slice) { isSlice = true; break; @@ -356,7 +356,7 @@ transformArraySubscripts(ParseState *pstate, errmsg("array subscript must have type integer"), parser_errposition(pstate, exprLocation(ai->lidx)))); } - else + else if (!ai->is_slice) { /* Make a constant 1 */ subexpr = (Node *) makeConst(INT4OID, @@ -367,21 +367,38 @@ transformArraySubscripts(ParseState *pstate, false, true); /* pass by value */ } + else + { + /* Slice with omitted lower bound, put NULL into the list */ + subexpr = NULL; + } lowerIndexpr = lappend(lowerIndexpr, subexpr); } - subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind); - /* If it's not int4 already, try to coerce */ - subexpr = coerce_to_target_type(pstate, - subexpr, exprType(subexpr), - INT4OID, -1, - COERCION_ASSIGNMENT, - COERCE_IMPLICIT_CAST, - -1); - if (subexpr == NULL) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("array subscript must have type integer"), - parser_errposition(pstate, exprLocation(ai->uidx)))); + else + Assert(ai->lidx == NULL && !ai->is_slice); + + if (ai->uidx) + { + subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind); + /* If it's not int4 already, try to coerce */ + subexpr = coerce_to_target_type(pstate, + subexpr, exprType(subexpr), + INT4OID, -1, + COERCION_ASSIGNMENT, + COERCE_IMPLICIT_CAST, + -1); + if (subexpr == NULL) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("array subscript must have type integer"), + parser_errposition(pstate, exprLocation(ai->uidx)))); + } + else + { + /* Slice with omitted upper bound, put NULL into the list */ + Assert(isSlice && ai->is_slice); + subexpr = NULL; + } upperIndexpr = lappend(upperIndexpr, subexpr); } diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 1b3fcd629c1..8c2c38dbe67 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -650,7 +650,7 @@ transformAssignmentIndirection(ParseState *pstate, if (IsA(n, A_Indices)) { subscripts = lappend(subscripts, n); - if (((A_Indices *) n)->lidx != NULL) + if (((A_Indices *) n)->is_slice) isSlice = true; } else if (IsA(n, A_Star)) |