88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.64 2000/07/27 03:50:52 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.65 2000/11/14 23:28:13 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -100,15 +100,12 @@ array_in(PG_FUNCTION_ARGS)
100100Oid element_type = PG_GETARG_OID (1 );/* type of an array element */
101101int32 typmod = PG_GETARG_INT32 (2 );/* typmod for array elements */
102102int typlen ;
103- bool typbyval ,
104- done ;
103+ bool typbyval ;
105104char typdelim ;
106105Oid typinput ;
107106Oid typelem ;
108107char * string_save ,
109- * p ,
110- * q ,
111- * r ;
108+ * p ;
112109FmgrInfo inputproc ;
113110int i ,
114111nitems ;
@@ -120,64 +117,83 @@ array_in(PG_FUNCTION_ARGS)
120117lBound [MAXDIM ];
121118char typalign ;
122119
120+ /* Get info about element type, including its input conversion proc */
123121system_cache_lookup (element_type , true,& typlen ,& typbyval ,& typdelim ,
124122& typelem ,& typinput ,& typalign );
125-
126123fmgr_info (typinput ,& inputproc );
127124
125+ /* Make a modifiable copy of the input */
126+ /* XXX why are we allocating an extra 2 bytes here? */
128127string_save = (char * )palloc (strlen (string )+ 3 );
129128strcpy (string_save ,string );
130129
131- /* --- read array dimensions ---------- */
132- p = q = string_save ;
133- done = false;
134- for (ndim = 0 ; !done ;)
130+ /*
131+ * If the input string starts with dimension info, read and use that.
132+ * Otherwise, we require the input to be in curly-brace style, and we
133+ * prescan the input to determine dimensions.
134+ *
135+ * Dimension info takes the form of one or more [n] or [m:n] items.
136+ * The outer loop iterates once per dimension item.
137+ */
138+ p = string_save ;
139+ ndim = 0 ;
140+ for (;;)
135141{
142+ char * q ;
143+ int ub ;
144+
145+ /*
146+ * Note: we currently allow whitespace between, but not within,
147+ * dimension items.
148+ */
136149while (isspace ((int )* p ))
137150p ++ ;
138- if (* p == '[' )
151+ if (* p != '[' )
152+ break ;/* no more dimension items */
153+ p ++ ;
154+ if (ndim >=MAXDIM )
155+ elog (ERROR ,"array_in: more than %d dimensions" ,MAXDIM );
156+ for (q = p ;isdigit ((int )* q );q ++ );
157+ if (q == p )/* no digits? */
158+ elog (ERROR ,"array_in: missing dimension value" );
159+ if (* q == ':' )
139160{
140- p ++ ;
141- if ((r = (char * )strchr (p ,':' ))== (char * )NULL )
142- lBound [ndim ]= 1 ;
143- else
144- {
145- * r = '\0' ;
146- lBound [ndim ]= atoi (p );
147- p = r + 1 ;
148- }
149- for (q = p ;isdigit ((int )* q );q ++ );
150- if (* q != ']' )
151- elog (ERROR ,"array_in: missing ']' in array declaration" );
161+ /* [m:n] format */
152162* q = '\0' ;
153- dim [ndim ]= atoi (p );
154- if ((dim [ndim ]< 0 )|| (lBound [ndim ]< 0 ))
155- elog (ERROR ,"array_in: array dimensions need to be positive" );
156- dim [ndim ]= dim [ndim ]- lBound [ndim ]+ 1 ;
157- if (dim [ndim ]< 0 )
158- elog (ERROR ,"array_in: upper_bound cannot be < lower_bound" );
163+ lBound [ndim ]= atoi (p );
159164p = q + 1 ;
160- ndim ++ ;
165+ for (q = p ;isdigit ((int )* q );q ++ );
166+ if (q == p )/* no digits? */
167+ elog (ERROR ,"array_in: missing dimension value" );
161168}
162169else
163- done = true;
170+ {
171+ /* [n] format */
172+ lBound [ndim ]= 1 ;
173+ }
174+ if (* q != ']' )
175+ elog (ERROR ,"array_in: missing ']' in array declaration" );
176+ * q = '\0' ;
177+ ub = atoi (p );
178+ p = q + 1 ;
179+ if (ub < lBound [ndim ])
180+ elog (ERROR ,"array_in: upper_bound cannot be < lower_bound" );
181+ dim [ndim ]= ub - lBound [ndim ]+ 1 ;
182+ ndim ++ ;
164183}
165184
166185if (ndim == 0 )
167186{
168- if (* p == '{' )
169- {
170- ndim = ArrayCount (p ,dim ,typdelim );
171- for (i = 0 ;i < ndim ;i ++ )
172- lBound [i ]= 1 ;
173- }
174- else
187+ /* No array dimensions, so intuit dimensions from brace structure */
188+ if (* p != '{' )
175189elog (ERROR ,"array_in: Need to specify dimension" );
190+ ndim = ArrayCount (p ,dim ,typdelim );
191+ for (i = 0 ;i < ndim ;i ++ )
192+ lBound [i ]= 1 ;
176193}
177194else
178195{
179- while (isspace ((int )* p ))
180- p ++ ;
196+ /* If array dimensions are given, expect '=' operator */
181197if (strncmp (p ,ASSGN ,strlen (ASSGN ))!= 0 )
182198elog (ERROR ,"array_in: missing assignment operator" );
183199p += strlen (ASSGN );