|
8 | 8 | * |
9 | 9 | * |
10 | 10 | * IDENTIFICATION |
11 | | - * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.75 2002/03/02 00:34:24 tgl Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.76 2002/03/16 22:47:13 tgl Exp $ |
12 | 12 | * |
13 | 13 | *------------------------------------------------------------------------- |
14 | 14 | */ |
|
51 | 51 | #defineRETURN_NULL(type) do { *isNull = true; return (type) 0; } while (0) |
52 | 52 |
|
53 | 53 |
|
54 | | -staticintArrayCount(char*str,int*dim,inttypdelim); |
| 54 | +staticintArrayCount(char*str,int*dim,chartypdelim); |
55 | 55 | staticDatum*ReadArrayStr(char*arrayStr,intnitems,intndim,int*dim, |
56 | 56 | FmgrInfo*inputproc,Oidtypelem,int32typmod, |
57 | 57 | chartypdelim,inttyplen,booltypbyval, |
@@ -245,81 +245,84 @@ array_in(PG_FUNCTION_ARGS) |
245 | 245 | *----------------------------------------------------------------------------- |
246 | 246 | */ |
247 | 247 | staticint |
248 | | -ArrayCount(char*str,int*dim,inttypdelim) |
| 248 | +ArrayCount(char*str,int*dim,chartypdelim) |
249 | 249 | { |
250 | 250 | intnest_level=0, |
251 | 251 | i; |
252 | 252 | intndim=0, |
253 | 253 | temp[MAXDIM]; |
254 | 254 | boolscanning_string= false; |
255 | 255 | booleoArray= false; |
256 | | -char*q; |
| 256 | +char*ptr; |
257 | 257 |
|
258 | 258 | for (i=0;i<MAXDIM;++i) |
259 | 259 | temp[i]=dim[i]=0; |
260 | 260 |
|
261 | 261 | if (strncmp(str,"{}",2)==0) |
262 | 262 | return0; |
263 | 263 |
|
264 | | -q=str; |
265 | | -while (eoArray!= true) |
| 264 | +ptr=str; |
| 265 | +while (!eoArray) |
266 | 266 | { |
267 | | -booldone= false; |
| 267 | +boolitemdone= false; |
268 | 268 |
|
269 | | -while (!done) |
| 269 | +while (!itemdone) |
270 | 270 | { |
271 | | -switch (*q) |
| 271 | +switch (*ptr) |
272 | 272 | { |
273 | | -case'\\': |
274 | | -/* skip escaped characters (\ and ") inside strings */ |
275 | | -if (scanning_string&&*(q+1)) |
276 | | -q++; |
277 | | -break; |
278 | 273 | case'\0': |
279 | | - |
280 | | -/* |
281 | | - * Signal a premature end of the string. DZ - |
282 | | - * 2-9-1996 |
283 | | - */ |
| 274 | +/* Signal a premature end of the string */ |
284 | 275 | elog(ERROR,"malformed array constant: %s",str); |
285 | 276 | break; |
| 277 | +case'\\': |
| 278 | +/* skip the escaped character */ |
| 279 | +if (*(ptr+1)) |
| 280 | +ptr++; |
| 281 | +else |
| 282 | +elog(ERROR,"malformed array constant: %s",str); |
| 283 | +break; |
286 | 284 | case'\"': |
287 | 285 | scanning_string= !scanning_string; |
288 | 286 | break; |
289 | 287 | case'{': |
290 | 288 | if (!scanning_string) |
291 | 289 | { |
| 290 | +if (nest_level >=MAXDIM) |
| 291 | +elog(ERROR,"array_in: illformed array constant"); |
292 | 292 | temp[nest_level]=0; |
293 | 293 | nest_level++; |
| 294 | +if (ndim<nest_level) |
| 295 | +ndim=nest_level; |
294 | 296 | } |
295 | 297 | break; |
296 | 298 | case'}': |
297 | 299 | if (!scanning_string) |
298 | 300 | { |
299 | | -if (!ndim) |
300 | | -ndim=nest_level; |
| 301 | +if (nest_level==0) |
| 302 | +elog(ERROR,"array_in: illformed array constant"); |
301 | 303 | nest_level--; |
302 | | -if (nest_level) |
303 | | -temp[nest_level-1]++; |
304 | 304 | if (nest_level==0) |
305 | | -eoArray=done= true; |
| 305 | +eoArray=itemdone= true; |
| 306 | +else |
| 307 | +{ |
| 308 | +/* |
| 309 | + * We don't set itemdone here; see comments in |
| 310 | + * ReadArrayStr |
| 311 | + */ |
| 312 | +temp[nest_level-1]++; |
| 313 | +} |
306 | 314 | } |
307 | 315 | break; |
308 | 316 | default: |
309 | | -if (!ndim) |
310 | | -ndim=nest_level; |
311 | | -if (*q==typdelim&& !scanning_string) |
312 | | -done= true; |
| 317 | +if (*ptr==typdelim&& !scanning_string) |
| 318 | +itemdone= true; |
313 | 319 | break; |
314 | 320 | } |
315 | | -if (!done) |
316 | | -q++; |
| 321 | +if (!itemdone) |
| 322 | +ptr++; |
317 | 323 | } |
318 | 324 | temp[ndim-1]++; |
319 | | -q++; |
320 | | -if (!eoArray) |
321 | | -while (isspace((unsignedchar)*q)) |
322 | | -q++; |
| 325 | +ptr++; |
323 | 326 | } |
324 | 327 | for (i=0;i<ndim;++i) |
325 | 328 | dim[i]=temp[i]; |
@@ -359,103 +362,119 @@ ReadArrayStr(char *arrayStr, |
359 | 362 | inti, |
360 | 363 | nest_level=0; |
361 | 364 | Datum*values; |
362 | | -char*p, |
363 | | -*q, |
364 | | -*r; |
| 365 | +char*ptr; |
365 | 366 | boolscanning_string= false; |
| 367 | +booleoArray= false; |
366 | 368 | intindx[MAXDIM], |
367 | 369 | prod[MAXDIM]; |
368 | | -booleoArray= false; |
369 | 370 |
|
370 | 371 | mda_get_prod(ndim,dim,prod); |
371 | 372 | values= (Datum*)palloc(nitems*sizeof(Datum)); |
372 | 373 | MemSet(values,0,nitems*sizeof(Datum)); |
373 | 374 | MemSet(indx,0,sizeof(indx)); |
374 | | -q=p=arrayStr; |
375 | 375 |
|
376 | 376 | /* read array enclosed within {} */ |
| 377 | +ptr=arrayStr; |
377 | 378 | while (!eoArray) |
378 | 379 | { |
379 | | -booldone= false; |
| 380 | +boolitemdone= false; |
380 | 381 | inti=-1; |
| 382 | +char*itemstart; |
| 383 | + |
| 384 | +/* skip leading whitespace */ |
| 385 | +while (isspace((unsignedchar)*ptr)) |
| 386 | +ptr++; |
| 387 | +itemstart=ptr; |
381 | 388 |
|
382 | | -while (!done) |
| 389 | +while (!itemdone) |
383 | 390 | { |
384 | | -switch (*q) |
| 391 | +switch (*ptr) |
385 | 392 | { |
| 393 | +case'\0': |
| 394 | +/* Signal a premature end of the string */ |
| 395 | +elog(ERROR,"malformed array constant: %s",arrayStr); |
| 396 | +break; |
386 | 397 | case'\\': |
| 398 | +{ |
| 399 | +char*cptr; |
| 400 | + |
387 | 401 | /* Crunch the string on top of the backslash. */ |
388 | | -for (r=q;*r!='\0';r++) |
389 | | -*r=*(r+1); |
| 402 | +for (cptr=ptr;*cptr!='\0';cptr++) |
| 403 | +*cptr=*(cptr+1); |
| 404 | +if (*ptr=='\0') |
| 405 | +elog(ERROR,"malformed array constant: %s",arrayStr); |
390 | 406 | break; |
| 407 | +} |
391 | 408 | case'\"': |
392 | | -if (!scanning_string) |
393 | | -{ |
394 | | -while (p!=q) |
395 | | -p++; |
396 | | -p++;/* get p past first doublequote */ |
397 | | -} |
398 | | -else |
399 | | -*q='\0'; |
| 409 | +{ |
| 410 | +char*cptr; |
| 411 | + |
400 | 412 | scanning_string= !scanning_string; |
| 413 | +/* Crunch the string on top of the quote. */ |
| 414 | +for (cptr=ptr;*cptr!='\0';cptr++) |
| 415 | +*cptr=*(cptr+1); |
| 416 | +/* Back up to not miss following character. */ |
| 417 | +ptr--; |
401 | 418 | break; |
| 419 | +} |
402 | 420 | case'{': |
403 | 421 | if (!scanning_string) |
404 | 422 | { |
405 | | -p++; |
406 | | -nest_level++; |
407 | | -if (nest_level>ndim) |
| 423 | +if (nest_level >=ndim) |
408 | 424 | elog(ERROR,"array_in: illformed array constant"); |
| 425 | +nest_level++; |
409 | 426 | indx[nest_level-1]=0; |
410 | | -indx[ndim-1]=0; |
| 427 | +/* skip leading whitespace */ |
| 428 | +while (isspace((unsignedchar)*(ptr+1))) |
| 429 | +ptr++; |
| 430 | +itemstart=ptr+1; |
411 | 431 | } |
412 | 432 | break; |
413 | 433 | case'}': |
414 | 434 | if (!scanning_string) |
415 | 435 | { |
| 436 | +if (nest_level==0) |
| 437 | +elog(ERROR,"array_in: illformed array constant"); |
416 | 438 | if (i==-1) |
417 | 439 | i=ArrayGetOffset0(ndim,indx,prod); |
| 440 | +indx[nest_level-1]=0; |
418 | 441 | nest_level--; |
419 | 442 | if (nest_level==0) |
420 | | -eoArray=done= true; |
| 443 | +eoArray=itemdone= true; |
421 | 444 | else |
422 | 445 | { |
423 | | -*q='\0'; |
| 446 | +/* |
| 447 | + * tricky coding: terminate item value string at |
| 448 | + * first '}', but don't process it till we see |
| 449 | + * a typdelim char or end of array. This handles |
| 450 | + * case where several '}'s appear successively |
| 451 | + * in a multidimensional array. |
| 452 | + */ |
| 453 | +*ptr='\0'; |
424 | 454 | indx[nest_level-1]++; |
425 | 455 | } |
426 | 456 | } |
427 | 457 | break; |
428 | 458 | default: |
429 | | -if (*q==typdelim&& !scanning_string) |
| 459 | +if (*ptr==typdelim&& !scanning_string) |
430 | 460 | { |
431 | 461 | if (i==-1) |
432 | 462 | i=ArrayGetOffset0(ndim,indx,prod); |
433 | | -done= true; |
| 463 | +itemdone= true; |
434 | 464 | indx[ndim-1]++; |
435 | 465 | } |
436 | 466 | break; |
437 | 467 | } |
438 | | -if (!done) |
439 | | -q++; |
| 468 | +if (!itemdone) |
| 469 | +ptr++; |
440 | 470 | } |
441 | | -*q='\0'; |
442 | | -if (i >=nitems) |
| 471 | +*ptr++='\0'; |
| 472 | +if (i<0||i>=nitems) |
443 | 473 | elog(ERROR,"array_in: illformed array constant"); |
444 | 474 | values[i]=FunctionCall3(inputproc, |
445 | | -CStringGetDatum(p), |
| 475 | +CStringGetDatum(itemstart), |
446 | 476 | ObjectIdGetDatum(typelem), |
447 | 477 | Int32GetDatum(typmod)); |
448 | | -p=++q; |
449 | | - |
450 | | -/* |
451 | | - * if not at the end of the array skip white space |
452 | | - */ |
453 | | -if (!eoArray) |
454 | | -while (isspace((unsignedchar)*q)) |
455 | | -{ |
456 | | -p++; |
457 | | -q++; |
458 | | -} |
459 | 478 | } |
460 | 479 |
|
461 | 480 | /* |
|