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

Commit4e1f986

Browse files
committed
I found the libpq function PGunescapeBytea a little slow. It was taking a
minute and a half to decode a 500Kb on a fairly fast machine. I think theculprit is sscanf.I attach a patch that replaces the function with one used to perform the sametask in pyPgSQL (a Python interface to PostgreSQL). This code was written byBilly Allie, author of pyPgSQL. I've changed a few variable names to matchthose in the original code and removed a bit of Pythonness.Billy has kindly looked at the code and points out that it is slightlystricter than the original implementation and if it encounters an invalidbytea such as '\12C' it drops the unescape '\' and outputs '12C'.The code is licensed by the author under a BSD license.I've performed limited testing of the function by putting JPEGs intoPostgreSQL, extracting them using them using the new function and diffingagainst the original files.The new function is significantly faster on my machine with the JPEGs beingdecoded in less than a second. I attach a modified libpq example program thatI used for my testing.Ben Lamb.
1 parent0abe743 commit4e1f986

File tree

1 file changed

+43
-76
lines changed

1 file changed

+43
-76
lines changed

‎src/interfaces/libpq/fe-exec.c

Lines changed: 43 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.137 2003/06/0817:43:00 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.138 2003/06/12 01:17:19 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1690,106 +1690,73 @@ PQescapeBytea(const unsigned char *bintext, size_t binlen, size_t *bytealen)
16901690
returnresult;
16911691
}
16921692

1693+
#defineVAL(CH) ((CH) - '0')
1694+
16931695
/*
16941696
*PQunescapeBytea - converts the null terminated string representation
16951697
*of a bytea, strtext, into binary, filling a buffer. It returns a
16961698
*pointer to the buffer which is NULL on error, and the size of the
16971699
*buffer in retbuflen. The pointer may subsequently be used as an
16981700
*argument to the function free(3). It is the reverse of PQescapeBytea.
16991701
*
1700-
*The following transformations are reversed:
1701-
*'\0' == ASCII 0 == \000
1702-
*'\'' == ASCII 39 == \'
1703-
*'\\' == ASCII 92 == \\
1702+
*The following transformations are made:
1703+
*\' == ASCII 39 == '
1704+
*\\ == ASCII 92 == \
1705+
*\ooo == a byte whose value = ooo (ooo is an octal number)
1706+
*\x == x (x is any character not matched by the above transformations)
17041707
*
1705-
*States:
1706-
*0normal0->1->2->3->4
1707-
*1\ 1->5
1708-
*2\0 1->6
1709-
*3\00
1710-
*4\000
1711-
*5\'
1712-
*6\\
17131708
*/
17141709
unsignedchar*
17151710
PQunescapeBytea(constunsignedchar*strtext,size_t*retbuflen)
17161711
{
1717-
size_tbuflen;
1718-
unsignedchar*buffer,
1719-
*bp;
1720-
constunsignedchar*sp;
1721-
unsignedintstate=0;
1712+
size_tstrtextlen,buflen;
1713+
unsignedchar*buffer,*tmpbuf;
1714+
inti,j,byte;
17221715

1723-
if (strtext==NULL)
1716+
if (strtext==NULL) {
17241717
returnNULL;
1725-
buflen=strlen(strtext);/* will shrink, also we discover if
1726-
* strtext */
1727-
buffer= (unsignedchar*)malloc(buflen);/* isn't NULL terminated */
1718+
}
1719+
1720+
strtextlen=strlen(strtext);/* will shrink, also we discover if
1721+
* strtext isn't NULL terminated */
1722+
buffer= (unsignedchar*)malloc(strtextlen);
17281723
if (buffer==NULL)
17291724
returnNULL;
1730-
for (bp=buffer,sp=strtext;*sp!='\0';bp++,sp++)
1725+
1726+
for (i=j=buflen=0;i<strtextlen;)
17311727
{
1732-
switch (state)
1728+
switch (strtext[i])
17331729
{
1734-
case0:
1735-
if (*sp=='\\')
1736-
state=1;
1737-
*bp=*sp;
1738-
break;
1739-
case1:
1740-
if (*sp=='\'')/* state=5 */
1741-
{/* replace \' with 39 */
1742-
bp--;
1743-
*bp='\'';
1744-
buflen--;
1745-
state=0;
1746-
}
1747-
elseif (*sp=='\\')/* state=6 */
1748-
{/* replace \\ with 92 */
1749-
bp--;
1750-
*bp='\\';
1751-
buflen--;
1752-
state=0;
1753-
}
1730+
case'\\':
1731+
i++;
1732+
if (strtext[i]=='\\')
1733+
buffer[j++]=strtext[i++];
17541734
else
17551735
{
1756-
if (isdigit(*sp))
1757-
state=2;
1758-
else
1759-
state=0;
1760-
*bp=*sp;
1736+
if ((isdigit(strtext[i]))&&
1737+
(isdigit(strtext[i+1]))&&
1738+
(isdigit(strtext[i+2])))
1739+
{
1740+
byte=VAL(strtext[i++]);
1741+
byte= (byte <<3)+VAL(strtext[i++]);
1742+
buffer[j++]= (byte <<3)+VAL(strtext[i++]);
1743+
}
17611744
}
17621745
break;
1763-
case2:
1764-
if (isdigit(*sp))
1765-
state=3;
1766-
else
1767-
state=0;
1768-
*bp=*sp;
1769-
break;
1770-
case3:
1771-
if (isdigit(*sp))/* state=4 */
1772-
{
1773-
intv;
17741746

1775-
bp-=3;
1776-
sscanf(sp-2,"%03o",&v);
1777-
*bp=v;
1778-
buflen-=3;
1779-
state=0;
1780-
}
1781-
else
1782-
{
1783-
*bp=*sp;
1784-
state=0;
1785-
}
1786-
break;
1747+
default:
1748+
buffer[j++]=strtext[i++];
17871749
}
17881750
}
1789-
buffer=realloc(buffer,buflen);
1790-
if (buffer==NULL)
1791-
returnNULL;
1751+
buflen=j;/* buflen is the length of the unquoted data */
1752+
tmpbuf=realloc(buffer,buflen);
1753+
1754+
if (!tmpbuf)
1755+
{
1756+
free(buffer);
1757+
return0;
1758+
}
17921759

17931760
*retbuflen=buflen;
1794-
returnbuffer;
1761+
returntmpbuf;
17951762
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp