hstore patch, part 1
Started by Andrew Gierthalmost 17 years ago2 messages
This is just the fix for hstore's silent truncation, including
doc patch and regression test. Actual new functionality will
follow later in another patch.
--
Andrew.
Attachments:
hstore_fix.patchtext/x-patchDownload
Index: contrib/hstore/hstore.h
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/hstore/hstore.h,v
retrieving revision 1.6
diff -c -r1.6 hstore.h
*** contrib/hstore/hstore.h 12 May 2008 00:00:42 -0000 1.6
--- contrib/hstore/hstore.h 14 Mar 2009 19:48:24 -0000
***************
*** 16,21 ****
--- 16,23 ----
pos:31;
} HEntry;
+ #define HSTORE_MAX_KEY 65535
+ #define HSTORE_MAX_VALUE 65535
typedef struct
{
***************
*** 45,50 ****
--- 47,55 ----
int comparePairs(const void *a, const void *b);
int uniquePairs(Pairs * a, int4 l, int4 *buflen);
+ uint16 hstoreCheckKeyLen(size_t len);
+ uint16 hstoreCheckValLen(size_t len);
+
#define HStoreContainsStrategyNumber 7
#define HStoreExistsStrategyNumber 9
Index: contrib/hstore/hstore_io.c
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/hstore/hstore_io.c,v
retrieving revision 1.8
diff -c -r1.8 hstore_io.c
*** contrib/hstore/hstore_io.c 12 May 2008 00:00:42 -0000 1.8
--- contrib/hstore/hstore_io.c 14 Mar 2009 19:48:25 -0000
***************
*** 9,14 ****
--- 9,36 ----
PG_MODULE_MAGIC;
+
+ uint16
+ hstoreCheckKeyLen(size_t len)
+ {
+ if (len > HSTORE_MAX_KEY)
+ ereport(ERROR,
+ (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
+ errmsg("string too long for hstore key")));
+ return len;
+ }
+
+ uint16
+ hstoreCheckValLen(size_t len)
+ {
+ if (len > HSTORE_MAX_VALUE)
+ ereport(ERROR,
+ (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
+ errmsg("string too long for hstore value")));
+ return len;
+ }
+
+
typedef struct
{
char *begin;
***************
*** 188,194 ****
state->pairs = (Pairs *) repalloc(state->pairs, sizeof(Pairs) * state->plen);
}
state->pairs[state->pcur].key = state->word;
! state->pairs[state->pcur].keylen = state->cur - state->word;
state->pairs[state->pcur].val = NULL;
state->word = NULL;
st = WEQ;
--- 210,216 ----
state->pairs = (Pairs *) repalloc(state->pairs, sizeof(Pairs) * state->plen);
}
state->pairs[state->pcur].key = state->word;
! state->pairs[state->pcur].keylen = hstoreCheckKeyLen(state->cur - state->word);
state->pairs[state->pcur].val = NULL;
state->word = NULL;
st = WEQ;
***************
*** 228,234 ****
if (!get_val(state, true, &escaped))
elog(ERROR, "Unexpected end of string");
state->pairs[state->pcur].val = state->word;
! state->pairs[state->pcur].vallen = state->cur - state->word;
state->pairs[state->pcur].isnull = false;
state->pairs[state->pcur].needfree = true;
if (state->cur - state->word == 4 && !escaped)
--- 250,256 ----
if (!get_val(state, true, &escaped))
elog(ERROR, "Unexpected end of string");
state->pairs[state->pcur].val = state->word;
! state->pairs[state->pcur].vallen = hstoreCheckValLen(state->cur - state->word);
state->pairs[state->pcur].isnull = false;
state->pairs[state->pcur].needfree = true;
if (state->cur - state->word == 4 && !escaped)
Index: contrib/hstore/hstore_op.c
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/hstore/hstore_op.c,v
retrieving revision 1.11
diff -c -r1.11 hstore_op.c
*** contrib/hstore/hstore_op.c 2 Nov 2008 01:45:26 -0000 1.11
--- contrib/hstore/hstore_op.c 14 Mar 2009 19:48:25 -0000
***************
*** 295,301 ****
SET_VARSIZE(out, len);
out->size = 1;
! ARRPTR(out)->keylen = VARSIZE(key) - VARHDRSZ;
if (PG_ARGISNULL(1))
{
ARRPTR(out)->vallen = 0;
--- 295,301 ----
SET_VARSIZE(out, len);
out->size = 1;
! ARRPTR(out)->keylen = hstoreCheckKeyLen(VARSIZE(key) - VARHDRSZ);
if (PG_ARGISNULL(1))
{
ARRPTR(out)->vallen = 0;
***************
*** 303,309 ****
}
else
{
! ARRPTR(out)->vallen = VARSIZE(val) - VARHDRSZ;
ARRPTR(out)->valisnull = false;
}
ARRPTR(out)->pos = 0;
--- 303,309 ----
}
else
{
! ARRPTR(out)->vallen = hstoreCheckValLen(VARSIZE(val) - VARHDRSZ);
ARRPTR(out)->valisnull = false;
}
ARRPTR(out)->pos = 0;
Index: contrib/hstore/expected/hstore.out
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/hstore/expected/hstore.out,v
retrieving revision 1.4
diff -c -r1.4 hstore.out
*** contrib/hstore/expected/hstore.out 14 Mar 2007 14:21:53 -0000 1.4
--- contrib/hstore/expected/hstore.out 14 Mar 2009 19:48:26 -0000
***************
*** 241,246 ****
--- 241,254 ----
(1 row)
+ select hstore_in(textout('a=>' || repeat('a',65537)));
+ ERROR: string too long for hstore value
+ select hstore_in(textout(repeat('a',65537) || '=>a'));
+ ERROR: string too long for hstore key
+ select repeat('a',65537) => 'a';
+ ERROR: string too long for hstore key
+ select 'a' => repeat('a',65537);
+ ERROR: string too long for hstore value
-- -> operator
select 'aa=>b, c=>d , b=>16'::hstore->'c';
?column?
Index: contrib/hstore/sql/hstore.sql
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/hstore/sql/hstore.sql,v
retrieving revision 1.4
diff -c -r1.4 hstore.sql
*** contrib/hstore/sql/hstore.sql 14 Mar 2007 14:21:53 -0000 1.4
--- contrib/hstore/sql/hstore.sql 14 Mar 2009 19:48:26 -0000
***************
*** 56,61 ****
--- 56,67 ----
select ''::hstore;
select ' '::hstore;
+ select hstore_in(textout('a=>' || repeat('a',65537)));
+ select hstore_in(textout(repeat('a',65537) || '=>a'));
+
+ select repeat('a',65537) => 'a';
+ select 'a' => repeat('a',65537);
+
-- -> operator
select 'aa=>b, c=>d , b=>16'::hstore->'c';
Index: doc/src/sgml/hstore.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/hstore.sgml,v
retrieving revision 1.2
diff -c -r1.2 hstore.sgml
*** doc/src/sgml/hstore.sgml 6 Dec 2007 04:12:10 -0000 1.2
--- doc/src/sgml/hstore.sgml 14 Mar 2009 19:48:27 -0000
***************
*** 14,19 ****
--- 14,25 ----
that are rarely examined, or semi-structured data.
</para>
+ <para>
+ Note that in the current implementation, neither the key nor the value
+ strings can exceed 65535 bytes in length; an error will be thrown if this
+ limit is exceeded. The maximum length may change in future releases.
+ </para>
+
<sect2>
<title><type>hstore</> External Representation</title>