]> granicus.if.org Git - postgresql/blobdiff - src/backend/parser/parse_node.c
Update copyright for 2016
[postgresql] / src / backend / parser / parse_node.c
index fc9e53a41d305433d720636a962cb0e7ff0a86ca..62d2f7105fb61ad40ea001da3a7cab0cbd436581 100644 (file)
@@ -3,7 +3,7 @@
  * parse_node.c
  *       various routines that make nodes for querytrees
  *
- * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
@@ -99,8 +99,8 @@ free_parsestate(ParseState *pstate)
  * is a dummy (always 0, in fact).
  *
  * The locations stored in raw parsetrees are byte offsets into the source
- * string.     We have to convert them to 1-based character indexes for reporting
- * to clients. (We do things this way to avoid unnecessary overhead in the
+ * string.  We have to convert them to 1-based character indexes for reporting
+ * to clients.  (We do things this way to avoid unnecessary overhead in the
  * normal non-error case: computing character indexes would be much more
  * expensive than storing token offsets.)
  */
@@ -129,7 +129,7 @@ parser_errposition(ParseState *pstate, int location)
  * Sometimes the parser calls functions that aren't part of the parser
  * subsystem and can't reasonably be passed a ParseState; yet we would
  * like any errors thrown in those functions to be tagged with a parse
- * error location.     Use this function to set up an error context stack
+ * error location.  Use this function to set up an error context stack
  * entry that will accomplish that.  Usage pattern:
  *
  *             declare a local variable "ParseCallbackState pcbstate"
@@ -221,7 +221,7 @@ transformArrayType(Oid *arrayType, int32 *arrayTypmod)
         * If the input is a domain, smash to base type, and extract the actual
         * typmod to be applied to the base type.  Subscripting a domain is an
         * operation that necessarily works on the base array type, not the domain
-        * itself.      (Note that we provide no method whereby the creator of a
+        * itself.  (Note that we provide no method whereby the creator of a
         * domain over an array type could hide its ability to be subscripted.)
         */
        *arrayType = getBaseTypeAndTypmod(*arrayType, arrayTypmod);
@@ -269,7 +269,7 @@ transformArrayType(Oid *arrayType, int32 *arrayTypmod)
  *
  * In an array assignment, we are given a destination array value plus a
  * source value that is to be assigned to a single element or a slice of
- * that array. We produce an expression that represents the new array value
+ * that array.  We produce an expression that represents the new array value
  * with the source data inserted into the right part of the array.
  *
  * For both cases, if the source array is of a domain-over-array type,
@@ -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);
        }