Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit636a939

Browse files
committed
Fix array_out's failure to backslash backslashes, per bug# 524. Also,
remove brain-dead rule that double quotes are needed if and only if thedatatype is pass-by-reference; neither direction of the implication holdswater. Instead, examine the actual data string to see if it containsany characters that force us to quote it.Add some documentation about quoting of array values, which was previouslyexplained nowhere AFAICT.
1 parenta4e8cd3 commit636a939

File tree

3 files changed

+109
-59
lines changed

3 files changed

+109
-59
lines changed

‎doc/src/sgml/array.sgml

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/array.sgml,v 1.17 2001/11/28 20:49:09 petere Exp $ -->
1+
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/array.sgml,v 1.18 2001/11/29 21:02:41 tgl Exp $ -->
22

33
<chapter id="arrays">
44
<title>Arrays</title>
@@ -248,4 +248,36 @@ SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000;
248248
</para>
249249
</note>
250250

251+
<formalpara>
252+
<title>Quoting array elements.</title>
253+
<para>
254+
As shown above, when writing an array literal value you may write double
255+
quotes around any individual array
256+
element. You <emphasis>must</> do so if the element value would otherwise
257+
confuse the array-value parser. For example, elements containing curly
258+
braces, commas, double quotes, backslashes, or white space must be
259+
double-quoted. To put a double quote or backslash in an array element
260+
value, precede it with a backslash.
261+
</para>
262+
</formalpara>
263+
264+
<tip>
265+
<para>
266+
Remember that what you write in an SQL query will first be interpreted
267+
as a string literal, and then as an array. This doubles the number of
268+
backslashes you need. For example, to insert a <type>text</> array
269+
value containing a backslash and a double quote, you'd need to write
270+
<programlisting>
271+
INSERT ... VALUES ('{"\\\\","\\""}');
272+
</programlisting>
273+
The string-literal processor removes one level of backslashes, so that
274+
what arrives at the array-value parser looks like <literal>{"\\","\""}</>.
275+
In turn, the strings fed to the <type>text</> datatype's input routine
276+
become <literal>\</> and <literal>"</> respectively. (If we were working
277+
with a datatype whose input routine also treated backslashes specially,
278+
<type>bytea</> for example, we might need as many as eight backslashes
279+
in the query to get one backslash into the stored array element.)
280+
</para>
281+
</tip>
282+
251283
</chapter>

‎src/backend/utils/adt/arrayfuncs.c

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.71 2001/10/25 05:49:43 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.72 2001/11/29 21:02:41 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -346,6 +346,7 @@ ArrayCount(char *str, int *dim, int typdelim)
346346
* If element type is pass-by-ref, the Datums point to palloc'd values.
347347
* *nbytes is set to the amount of data space needed for the array,
348348
* including alignment padding but not including array header overhead.
349+
* CAUTION: the contents of "arrayStr" may be modified!
349350
*---------------------------------------------------------------------------
350351
*/
351352
staticDatum*
@@ -564,43 +565,43 @@ array_out(PG_FUNCTION_ARGS)
564565
char*p,
565566
*tmp,
566567
*retval,
567-
**values,
568-
delim[2];
568+
**values;
569+
bool*needquotes;
569570
intnitems,
570571
overall_length,
571572
i,
572573
j,
573574
k,
574-
#ifndefTCL_ARRAYS
575-
l,
576-
#endif
577575
indx[MAXDIM];
578576
intndim,
579577
*dim;
580578

581579
system_cache_lookup(element_type, false,&typlen,&typbyval,
582580
&typdelim,&typelem,&typoutput,&typalign);
583581
fmgr_info(typoutput,&outputproc);
584-
sprintf(delim,"%c",typdelim);
585582
ndim=ARR_NDIM(v);
586583
dim=ARR_DIMS(v);
587584
nitems=ArrayGetNItems(ndim,dim);
588585

589586
if (nitems==0)
590587
{
591-
retval= (char*)palloc(3);
592-
retval[0]='{';
593-
retval[1]='}';
594-
retval[2]='\0';
588+
retval=pstrdup("{}");
595589
PG_RETURN_CSTRING(retval);
596590
}
597591

592+
/*
593+
* Convert all values to string form, count total space needed
594+
* (including any overhead such as escaping backslashes),
595+
* and detect whether each item needs double quotes.
596+
*/
597+
values= (char**)palloc(nitems*sizeof(char*));
598+
needquotes= (bool*)palloc(nitems*sizeof(bool));
598599
p=ARR_DATA_PTR(v);
599600
overall_length=1;/* [TRH] don't forget to count \0 at end. */
600-
values= (char**)palloc(nitems*sizeof(char*));
601601
for (i=0;i<nitems;i++)
602602
{
603603
Datumitemvalue;
604+
boolnq;
604605

605606
itemvalue=fetch_att(p,typbyval,typlen);
606607
values[i]=DatumGetCString(FunctionCall3(&outputproc,
@@ -612,20 +613,32 @@ array_out(PG_FUNCTION_ARGS)
612613
else
613614
p+=INTALIGN(*(int32*)p);
614615

615-
/*
616-
* For the pair of double quotes
617-
*/
618-
if (!typbyval)
619-
overall_length+=2;
620-
616+
/* count data plus backslashes; detect chars needing quotes */
617+
nq= (values[i][0]=='\0');/* force quotes for empty string */
621618
for (tmp=values[i];*tmp;tmp++)
622619
{
620+
charch=*tmp;
621+
623622
overall_length+=1;
623+
if (ch=='"'||ch=='\\')
624+
{
625+
nq= true;
624626
#ifndefTCL_ARRAYS
625-
if (*tmp=='"')
626627
overall_length+=1;
627628
#endif
629+
}
630+
elseif (ch=='{'||ch=='}'||ch==typdelim||
631+
isspace((unsignedchar)ch))
632+
nq= true;
628633
}
634+
635+
needquotes[i]=nq;
636+
637+
/* Count the pair of double quotes, if needed */
638+
if (nq)
639+
overall_length+=2;
640+
641+
/* and the comma */
629642
overall_length+=1;
630643
}
631644

@@ -634,58 +647,63 @@ array_out(PG_FUNCTION_ARGS)
634647
*/
635648
for (i=j=0,k=1;i<ndim;k *=dim[i++],j+=k);
636649

637-
p= (char*)palloc(overall_length+2*j);
638-
retval=p;
650+
retval= (char*)palloc(overall_length+2*j);
651+
p=retval;
652+
653+
#defineAPPENDSTR(str)(strcpy(p, (str)), p += strlen(p))
654+
#defineAPPENDCHAR(ch)(*p++ = (ch), *p = '\0')
639655

640-
strcpy(p,"{");
656+
APPENDCHAR('{');
641657
for (i=0;i<ndim;indx[i++]=0);
642658
j=0;
643659
k=0;
644660
do
645661
{
646662
for (i=j;i<ndim-1;i++)
647-
strcat(p,"{");
663+
APPENDCHAR('{');
648664

649-
/*
650-
* Surround anything that is not passed by value in double quotes.
651-
* See above for more details.
652-
*/
653-
if (!typbyval)
665+
if (needquotes[k])
654666
{
655-
strcat(p,"\"");
667+
APPENDCHAR('"');
656668
#ifndefTCL_ARRAYS
657-
l=strlen(p);
658669
for (tmp=values[k];*tmp;tmp++)
659670
{
660-
if (*tmp=='"')
661-
p[l++]='\\';
662-
p[l++]=*tmp;
671+
charch=*tmp;
672+
673+
if (ch=='"'||ch=='\\')
674+
*p++='\\';
675+
*p++=ch;
663676
}
664-
p[l]='\0';
677+
*p='\0';
665678
#else
666-
strcat(p,values[k]);
679+
APPENDSTR(values[k]);
667680
#endif
668-
strcat(p,"\"");
681+
APPENDCHAR('"');
669682
}
670683
else
671-
strcat(p,values[k]);
684+
APPENDSTR(values[k]);
672685
pfree(values[k++]);
673686

674687
for (i=ndim-1;i >=0;i--)
675688
{
676689
indx[i]= (indx[i]+1) %dim[i];
677690
if (indx[i])
678691
{
679-
strcat(p,delim);
692+
APPENDCHAR(typdelim);
680693
break;
681694
}
682695
else
683-
strcat(p,"}");
696+
APPENDCHAR('}');
684697
}
685698
j=i;
686699
}while (j!=-1);
687700

701+
#undef APPENDSTR
702+
#undef APPENDCHAR
703+
688704
pfree(values);
705+
pfree(needquotes);
706+
689707
PG_RETURN_CSTRING(retval);
690708
}
691709

‎src/test/regress/expected/arrays.out

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ INSERT INTO arrtest (a, b[2][2][1], c, d, e, f, g)
2828
INSERT INTO arrtest (a, b[1][2][2], c, d[2][1])
2929
VALUES ('{}', '{3,4}', '{foo,bar}', '{bar,foo}');
3030
SELECT * FROM arrtest;
31-
a | b |c|d|e|f| g
32-
-------------+-----------------+---------------+-------------------+---------------+-------------------+-----------------
33-
{1,2,3,4,5} | {{{0,0},{1,2}}} | {}| {}|| {} | {}
34-
{11,12,23} | {{3,4},{4,5}} | {"foobar"}| {{"elt1","elt2"}} | {"3.4","6.7"} | {"abc ","abcde"} | {"abc","abcde"}
35-
{} | {3,4} | {"foo","bar"} | {"bar","foo"} | | |
31+
a | b | c | d | e | f |g
32+
-------------+-----------------+-----------+---------------+-----------+-----------------+-------------
33+
{1,2,3,4,5} | {{{0,0},{1,2}}} | {} | {} | | {} | {}
34+
{11,12,23} | {{3,4},{4,5}} | {foobar} | {{elt1,elt2}} | {3.4,6.7} | {"abc ",abcde} | {abc,abcde}
35+
{} | {3,4} | {foo,bar} | {bar,foo} || |
3636
(3 rows)
3737

3838
SELECT arrtest.a[1],
@@ -62,11 +62,11 @@ SELECT a[1:3],
6262
c[1:2],
6363
d[1:1][1:2]
6464
FROM arrtest;
65-
a | b |c| d
66-
------------+-----------------+---------------+-------------------
67-
{1,2,3} | {{{0,0},{1,2}}} ||
68-
{11,12,23} | | {"foobar"}| {{"elt1","elt2"}}
69-
| | {"foo","bar"} |
65+
a | b | c |d
66+
------------+-----------------+-----------+---------------
67+
{1,2,3} | {{{0,0},{1,2}}} | |
68+
{11,12,23} | | {foobar} | {{elt1,elt2}}
69+
| | {foo,bar} |
7070
(3 rows)
7171

7272
SELECT array_dims(a) AS a,array_dims(b) AS b,array_dims(c) AS c
@@ -98,22 +98,22 @@ UPDATE arrtest
9898
SET c[2:2] = '{"new_word"}'
9999
WHERE array_dims(c) is not null;
100100
SELECT a,b,c FROM arrtest;
101-
a | b | c
102-
---------------+-----------------------+-----------------------
101+
a | b |c
102+
---------------+-----------------------+-------------------
103103
{16,25,3,4,5} | {{{113,142},{1,147}}} | {}
104-
{} | {3,4} | {"foo","new_word"}
105-
{16,25,23} | {{3,4},{4,5}} | {"foobar","new_word"}
104+
{} | {3,4} | {foo,new_word}
105+
{16,25,23} | {{3,4},{4,5}} | {foobar,new_word}
106106
(3 rows)
107107

108108
SELECT a[1:3],
109109
b[1:1][1:2][1:2],
110110
c[1:2],
111111
d[1:1][2:2]
112112
FROM arrtest;
113-
a | b |c| d
114-
------------+-----------------------+-----------------------+------------
115-
{16,25,3} | {{{113,142},{1,147}}} ||
116-
| | {"foo","new_word"} |
117-
{16,25,23} | | {"foobar","new_word"} | {{"elt2"}}
113+
a | b | c |d
114+
------------+-----------------------+-------------------+----------
115+
{16,25,3} | {{{113,142},{1,147}}} | |
116+
| | {foo,new_word} |
117+
{16,25,23} | | {foobar,new_word} | {{elt2}}
118118
(3 rows)
119119

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp