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.

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>
  
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to