diff -cpr pgsql-orig/src/backend/access/common/heaptuple.c pgsql/src/backend/access/common/heaptuple.c
*** pgsql-orig/src/backend/access/common/heaptuple.c	2005-09-08 11:10:16.253332616 +0900
--- pgsql/src/backend/access/common/heaptuple.c	2005-09-08 11:11:04.884939488 +0900
*************** heap_fill_tuple(TupleDesc tupleDesc,
*** 173,178 ****
--- 173,185 ----
  			data_length = strlen(DatumGetCString(values[i])) + 1;
  			memcpy(data, DatumGetPointer(values[i]), data_length);
  		}
+ 		else if (att[i]->attlen == -3)
+ 		{
+ 			/* varlena2 */
+ 			*infomask |= HEAP_HASVARWIDTH;
+ 			data_length = varlena2size(DatumGetRawVarlena2P(values[i]));
+ 			memcpy(data, DatumGetPointer(values[i]), data_length);
+ 		}
  		else
  		{
  			/* fixed-length pass-by-reference */
*************** DataFill(char *data,
*** 272,277 ****
--- 279,291 ----
  			data_length = strlen(DatumGetCString(values[i])) + 1;
  			memcpy(data, DatumGetPointer(values[i]), data_length);
  		}
+ 		else if (att[i]->attlen == -3)
+ 		{
+ 			/* varlena2 */
+ 			*infomask |= HEAP_HASVARWIDTH;
+ 			data_length = varlena2size(DatumGetRawVarlena2P(values[i]));
+ 			memcpy(data, DatumGetPointer(values[i]), data_length);
+ 		}
  		else
  		{
  			/* fixed-length pass-by-reference */
diff -cpr pgsql-orig/src/backend/catalog/pg_type.c pgsql/src/backend/catalog/pg_type.c
*** pgsql-orig/src/backend/catalog/pg_type.c	2005-09-08 11:10:16.343318936 +0900
--- pgsql/src/backend/catalog/pg_type.c	2005-09-08 11:11:04.885939336 +0900
*************** TypeCreate(const char *typeName,
*** 189,195 ****
  	 */
  	if (!(internalSize > 0 ||
  		  internalSize == -1 ||
! 		  internalSize == -2))
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
  				 errmsg("invalid type internal size %d",
--- 189,196 ----
  	 */
  	if (!(internalSize > 0 ||
  		  internalSize == -1 ||
! 		  internalSize == -2 ||
! 		  internalSize == -3))
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
  				 errmsg("invalid type internal size %d",
diff -cpr pgsql-orig/src/backend/utils/adt/arrayfuncs.c pgsql/src/backend/utils/adt/arrayfuncs.c
*** pgsql-orig/src/backend/utils/adt/arrayfuncs.c	2005-09-08 11:10:16.217338088 +0900
--- pgsql/src/backend/utils/adt/arrayfuncs.c	2005-09-08 11:11:04.888938880 +0900
*************** ReadArrayStr(char *arrayStr,
*** 817,831 ****
  				totbytes += sizeof(int32);
  				totbytes = att_align(totbytes, typalign);
  			}
! 			else
  			{
  				/* dummy cstring value */
- 				Assert(typlen == -2);
  				values[i] = PointerGetDatum(palloc(1));
  				*((char *) DatumGetPointer(values[i])) = '\0';
  				totbytes += 1;
  				totbytes = att_align(totbytes, typalign);
  			}
  		}
  	}
  	*nbytes = totbytes;
--- 817,839 ----
  				totbytes += sizeof(int32);
  				totbytes = att_align(totbytes, typalign);
  			}
! 			else if (typlen == -2)
  			{
  				/* dummy cstring value */
  				values[i] = PointerGetDatum(palloc(1));
  				*((char *) DatumGetPointer(values[i])) = '\0';
  				totbytes += 1;
  				totbytes = att_align(totbytes, typalign);
  			}
+ 			else
+ 			{
+ 				/* dummy varlena2 value */
+ 				Assert(typlen == -3);
+ 				values[i] = PointerGetDatum(palloc(1));
+ 				*((char *) DatumGetPointer(values[i])) = 0;
+ 				totbytes += 1;
+ 				totbytes = att_align(totbytes, typalign);
+ 			}
  		}
  	}
  	*nbytes = totbytes;
diff -cpr pgsql-orig/src/backend/utils/adt/datum.c pgsql/src/backend/utils/adt/datum.c
*** pgsql-orig/src/backend/utils/adt/datum.c	2005-09-08 11:10:16.201340520 +0900
--- pgsql/src/backend/utils/adt/datum.c	2005-09-08 11:11:04.889938728 +0900
*************** datumGetSize(Datum value, bool typByVal,
*** 93,98 ****
--- 93,110 ----
  
  			size = (Size) (strlen(s) + 1);
  		}
+ 		else if (typLen == -3)
+ 		{
+ 			/* It is a varlena2 datatype */
+ 			struct varlena2 *s = (struct varlena2 *) DatumGetPointer(value);
+ 
+ 			if (!PointerIsValid(s))
+ 				ereport(ERROR,
+ 						(errcode(ERRCODE_DATA_EXCEPTION),
+ 						 errmsg("invalid Datum pointer")));
+ 
+ 			size = (Size) varlena2size(s);
+ 		}
  		else
  		{
  			elog(ERROR, "invalid typLen: %d", typLen);
diff -cpr pgsql-orig/src/backend/utils/adt/varlena.c pgsql/src/backend/utils/adt/varlena.c
*** pgsql-orig/src/backend/utils/adt/varlena.c	2005-09-08 11:10:16.210339152 +0900
--- pgsql/src/backend/utils/adt/varlena.c	2005-09-08 11:44:36.785084176 +0900
*************** pg_column_size(PG_FUNCTION_ARGS)
*** 2684,2689 ****
--- 2684,2694 ----
  		/* cstring */
  		result = strlen(DatumGetCString(value)) + 1;
  	}
+ 	else if (typlen == -3)
+ 	{
+ 		/* varlena2 type */
+ 		result = varlena2size(DatumGetRawVarlena2P(value));
+ 	}
  	else
  	{
  		/* ordinary fixed-width type */
*************** pg_column_size(PG_FUNCTION_ARGS)
*** 2692,2694 ****
--- 2697,2951 ----
  
  	PG_RETURN_INT32(result);
  }
+ 
+ /* varlena2 */
+ 
+ /*
+  * The length of varlena2 is encoded as follows:
+  *
+  * | First    | Trailing | Total | Max     |
+  * | byte     | bytes    | bits  | length  |
+  * +----------+----------+-------+---------+
+  * | 0******* |        0 |     7 | 127     |
+  * | 10****** |        1 |    14 | 16K  -1 |
+  * | 110***** |        2 |    21 | 2M   -1 |
+  * | 1110**** |        3 |    28 | 256M -1 |
+  * | 1111---- |        4 |    32 | 4G   -1 |
+  */
+ 
+ static const uint8 VARLENA2HDRMAP[16] =
+ {
+ 	1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5,
+ };
+ 
+ /* Return the header size of a varlena2 */
+ #define VARLENA2HDRSZ(n)	VARLENA2HDRMAP[(uint8)n[0] >> 4]
+ 
+ /* Decode the byte size of a varlena2 */
+ #define VARLENA2LENGTH_1(n)	\
+ 	((uint32)n[0])
+ #define VARLENA2LENGTH_2(n)			\
+ 	(((uint32)(n[0] & 0x3F) << 8)	\
+ 	+ n[1])
+ #define VARLENA2LENGTH_3(n)			\
+ 	(((uint32)(n[0] & 0x1F) << 16)	\
+ 	+ ((uint32)n[1] << 8)			\
+ 	+ n[2])
+ #define VARLENA2LENGTH_4(n)			\
+ 	(((uint32)(n[0] & 0x0F) << 24)	\
+ 	+ ((uint32)n[1] << 16)			\
+ 	+ ((uint32)n[2] << 8)			\
+ 	+ n[3])
+ #define VARLENA2LENGTH_5(n)	\
+ 	( ((uint32)n[1] << 24)	\
+ 	+ ((uint32)n[2] << 16)	\
+ 	+ ((uint32)n[3] << 8)	\
+ 	+ n[4])
+ 
+ 
+ /* Return the total byte size of a varlena2 */
+ int varlena2size(const struct varlena2 *v)
+ {
+ 	const uint8* len = v->vl2_len;
+ 	switch(VARLENA2HDRSZ(len))
+ 	{
+ 		case 1: return 1 + VARLENA2LENGTH_1(len);
+ 		case 2: return 2 + VARLENA2LENGTH_2(len);
+ 		case 3: return 3 + VARLENA2LENGTH_3(len);
+ 		case 4: return 4 + VARLENA2LENGTH_4(len);
+ 		case 5: return 5 + VARLENA2LENGTH_5(len);
+ 		default:
+ 			elog(ERROR, "varlena2size");
+ 			return -1;
+ 	}
+ }
+ 
+ /* Return the data buffer and the data length of a varlena2 */
+ static char *varlena2extract(struct varlena2 *v, int* length)
+ {
+ 	const uint8* len = v->vl2_len;
+ 	switch(VARLENA2HDRSZ(len))
+ 	{
+ 	case 1:
+ 		*length = VARLENA2LENGTH_1(len);
+ 		return (char *) v + 1;
+ 	case 2:
+ 		*length = VARLENA2LENGTH_2(len);
+ 		return (char *) v + 2;
+ 	case 3:
+ 		*length = VARLENA2LENGTH_3(len);
+ 		return (char *) v + 3;
+ 	case 4:
+ 		*length = VARLENA2LENGTH_4(len);
+ 		return (char *) v + 4;
+ 	case 5:
+ 		*length = VARLENA2LENGTH_5(len);
+ 		return (char *) v + 5;
+ 	default:
+ 		elog(ERROR, "varlena2extract");
+ 		return NULL;
+ 	}
+ }
+ 
+ /* Return a new varlena2. */
+ static struct varlena2 *varlena2new(int length, char** data)
+ {
+ 	struct varlena2 *v;
+ 	if(length < (1 << 7))
+ 	{
+ 		v = (struct varlena2*) palloc(length + 1);
+ 		v->vl2_len[0] = (uint8)length;
+ 		*data = (char *) v + 1;
+ 	}
+ 	else if(length < (1 << 14))
+ 	{
+ 		v = (struct varlena2*) palloc(length + 2);
+ 		v->vl2_len[0] = (uint8)((length & 0x3F00) >> 8) | 0x80;
+ 		v->vl2_len[1] = (uint8)((length & 0x00FF));
+ 		*data = (char *) v + 2;
+ 	}
+ 	else if(length < (1 << 21))
+ 	{
+ 		v = (struct varlena2*) palloc(length + 3);
+ 		v->vl2_len[0] = (uint8)((length & 0x1F0000) >> 16) | 0xC0;
+ 		v->vl2_len[1] = (uint8)((length & 0x00FF00) >> 8);
+ 		v->vl2_len[2] = (uint8)((length & 0x0000FF));
+ 		*data = (char *) v + 3;
+ 	}
+ 	else if(length < (1 << 28))
+ 	{
+ 		v = (struct varlena2*) palloc(length + 4);
+ 		v->vl2_len[0] = (uint8)((length & 0x0F000000) >> 24) | 0xE0;
+ 		v->vl2_len[1] = (uint8)((length & 0x00FF0000) >> 16);
+ 		v->vl2_len[2] = (uint8)((length & 0x0000FF00) >> 8);
+ 		v->vl2_len[3] = (uint8)((length & 0x000000FF));
+ 		*data = (char *) v + 4;
+ 	}
+ 	else
+ 	{
+ 		v = (struct varlena2*) palloc(length + 5);
+ 		v->vl2_len[0] = 0xF0;
+ 		v->vl2_len[1] = (uint8)((length & 0xFF000000) >> 24);
+ 		v->vl2_len[2] = (uint8)((length & 0x00FF0000) >> 16);
+ 		v->vl2_len[3] = (uint8)((length & 0x0000FF00) >> 8);
+ 		v->vl2_len[4] = (uint8)((length & 0x000000FF));
+ 		*data = (char *) v + 5;
+ 	}
+ 	return v;
+ }
+ 
+ #define StringNew(length, data)	((String *) varlena2new((length), (data)))
+ #define StringExtract			varlena2extract
+ 
+ #define BinaryNew(length, data)	((Binary *) varlena2new((length), (data)))
+ #define BinaryExtract			varlena2extract
+ 
+ /*
+  *		stringin			- converts "..." to internal representation
+  */
+ Datum
+ stringin(PG_FUNCTION_ARGS)
+ {
+ 	char	   *inputText = PG_GETARG_CSTRING(0);
+ 	String	   *result;
+ 	char	   *data;
+ 	int			len;
+ 
+ 	/* verify encoding */
+ 	len = strlen(inputText);
+ 	pg_verifymbstr(inputText, len, false);
+ 
+ 	result = StringNew(len, &data);
+ 	memcpy(data, inputText, len);
+ 
+ 	PG_RETURN_STRING_P(result);
+ }
+ 
+ /*
+  *		stringout			- converts internal representation to "..."
+  */
+ Datum
+ stringout(PG_FUNCTION_ARGS)
+ {
+ 	String	   *t = PG_GETARG_STRING_P(0);
+ 	int			len;
+ 	char	   *data;
+ 	char	   *result;
+ 
+ 	data = StringExtract(t, &len);
+ 	result = (char *) palloc(len + 1);
+ 	memcpy(result, data, len);
+ 	result[len] = '\0';
+ 
+ 	PG_RETURN_CSTRING(result);
+ }
+ 
+ /*
+  *		stringrecv			- converts external binary format to string
+  */
+ Datum
+ stringrecv(PG_FUNCTION_ARGS)
+ {
+ 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
+ 	String	   *result;
+ 	char	   *data;
+ 	char	   *inputText;
+ 	int			nbytes;
+ 
+ 	inputText = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
+ 
+ 	/* verify encoding */
+ 	pg_verifymbstr(inputText, nbytes, false);
+ 
+ 	result = StringNew(nbytes, &data);
+ 	memcpy(data, inputText, nbytes);
+ 	pfree(inputText);
+ 
+ 	PG_RETURN_STRING_P(result);
+ }
+ 
+ /*
+  *		stringsend			- converts string to binary format
+  */
+ Datum
+ stringsend(PG_FUNCTION_ARGS)
+ {
+ 	String	   *t = PG_GETARG_STRING_P(0);
+ 	StringInfoData buf;
+ 	char	   *data;
+ 	int			len;
+ 
+ 	data = StringExtract(t, &len);
+ 
+ 	pq_begintypsend(&buf);
+ 	pq_sendtext(&buf, data, len);
+ 	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+ }
+ 
+ Datum
+ binaryin(PG_FUNCTION_ARGS)
+ {
+ 	elog(ERROR, "binaryin not implemented");
+ 	PG_RETURN_VOID();
+ }
+ 
+ Datum
+ binaryout(PG_FUNCTION_ARGS)
+ {
+ 	elog(ERROR, "binaryout not implemented");
+ 	PG_RETURN_VOID();
+ }
+ 
+ Datum
+ binaryrecv(PG_FUNCTION_ARGS)
+ {
+ 	elog(ERROR, "binaryrecv not implemented");
+ 	PG_RETURN_VOID();
+ }
+ 
+ Datum
+ binarysend(PG_FUNCTION_ARGS)
+ {
+ 	elog(ERROR, "binarysend not implemented");
+ 	PG_RETURN_VOID();
+ }
diff -cpr pgsql-orig/src/backend/utils/fmgr/fmgr.c pgsql/src/backend/utils/fmgr/fmgr.c
*** pgsql-orig/src/backend/utils/fmgr/fmgr.c	2005-09-08 11:10:16.221337480 +0900
--- pgsql/src/backend/utils/fmgr/fmgr.c	2005-09-08 11:11:04.894937968 +0900
*************** pg_detoast_datum_slice(struct varlena * 
*** 1828,1833 ****
--- 1828,1851 ----
  }
  
  /*-------------------------------------------------------------------------
+  *		Support routines for toastable datatypes (varlena2)
+  *-------------------------------------------------------------------------
+  */
+ 
+ struct varlena2 *
+ pg_detoast_datum2(struct varlena2 * datum)
+ {
+ #if 1
+ 	return datum;
+ #else /* Not Implementd */
+ 	if (VARATT2_IS_EXTENDED(datum))
+ 		return (struct varlena2 *) heap_tuple_untoast_attr2((varattrib *) datum);
+ 	else
+ 		return datum;
+ #endif
+ }
+ 
+ /*-------------------------------------------------------------------------
   *		Support routines for extracting info from fn_expr parse tree
   *
   * These are needed by polymorphic functions, which accept multiple possible
diff -cpr pgsql-orig/src/include/access/tupmacs.h pgsql/src/include/access/tupmacs.h
*** pgsql-orig/src/include/access/tupmacs.h	2005-09-08 11:10:16.397310728 +0900
--- pgsql/src/include/access/tupmacs.h	2005-09-08 11:11:04.895937816 +0900
***************
*** 121,131 ****
  	( \
  		(cur_offset) + VARATT_SIZE(DatumGetPointer(attval)) \
  	) \
! 	: \
  	( \
- 		AssertMacro((attlen) == -2), \
  		(cur_offset) + (strlen(DatumGetCString(attval)) + 1) \
! 	)) \
  )
  
  /*
--- 121,135 ----
  	( \
  		(cur_offset) + VARATT_SIZE(DatumGetPointer(attval)) \
  	) \
! 	: (((attlen) == -2) ? \
  	( \
  		(cur_offset) + (strlen(DatumGetCString(attval)) + 1) \
! 	) \
! 	: \
! 	( \
! 		AssertMacro((attlen) == -3), \
! 		(cur_offset) + varlena2size(DatumGetRawVarlena2P(attval)) \
! 	))) \
  )
  
  /*
diff -cpr pgsql-orig/src/include/c.h pgsql/src/include/c.h
*** pgsql-orig/src/include/c.h	2005-09-08 11:10:16.361316200 +0900
--- pgsql/src/include/c.h	2005-09-08 11:11:04.896937664 +0900
*************** typedef struct varlena text;
*** 431,436 ****
--- 431,451 ----
  typedef struct varlena BpChar;	/* blank-padded char, ie SQL char(n) */
  typedef struct varlena VarChar; /* var-length char, ie SQL varchar(n) */
  
+ /* ----------------
+  *		Variable-length V2 datatypes all share the 'struct varlena2' header.
+  * ----------------
+  */
+ struct varlena2
+ {
+ 	uint8	vl2_len[1];
+ 	/*		vl2_data[] */
+ };
+ 
+ extern int varlena2size(const struct varlena2 *v);
+ 
+ typedef struct varlena2 Binary;
+ typedef struct varlena2 String;
+ 
  /*
   * Specialized array types.  These are physically laid out just the same
   * as regular arrays (so that the regular array subscripting code works
diff -cpr pgsql-orig/src/include/catalog/pg_proc.h pgsql/src/include/catalog/pg_proc.h
*** pgsql-orig/src/include/catalog/pg_proc.h	2005-09-08 11:10:16.446303280 +0900
--- pgsql/src/include/catalog/pg_proc.h	2005-09-08 11:11:04.902936752 +0900
*************** DESCR("GiST support");
*** 3763,3768 ****
--- 3763,3785 ----
  DATA(insert OID = 2592 (  gist_circle_compress	PGNSP PGUID 12 f f t f i 1 2281 "2281" _null_ _null_ _null_	gist_circle_compress - _null_ ));
  DESCR("GiST support");
  
+ DATA(insert OID = 2593 (  stringin				PGNSP PGUID 12 f f t f i 1 25 "2275" _null_ _null_ _null_ stringin - _null_ ));
+ DESCR("I/O");
+ DATA(insert OID = 2594 (  stringout				PGNSP PGUID 12 f f t f i 1 2275 "31" _null_ _null_ _null_ stringout - _null_ ));
+ DESCR("I/O");
+ DATA(insert OID = 2595 (  stringrecv			PGNSP PGUID 12 f f t f s 1 25 "2281" _null_ _null_ _null_	stringrecv - _null_ ));
+ DESCR("I/O");
+ DATA(insert OID = 2596 (  stringsend			PGNSP PGUID 12 f f t f s 1 17 "31" _null_ _null_ _null_  stringsend - _null_ ));
+ DESCR("I/O");
+ DATA(insert OID = 2597 (  binaryin				PGNSP PGUID 12 f f t f i 1 25 "2275" _null_ _null_ _null_ binaryin - _null_ ));
+ DESCR("I/O");
+ DATA(insert OID = 2598 (  binaryout				PGNSP PGUID 12 f f t f i 1 2275 "21" _null_ _null_ _null_ binaryout - _null_ ));
+ DESCR("I/O");
+ DATA(insert OID = 2599 (  binaryrecv			PGNSP PGUID 12 f f t f s 1 25 "2281" _null_ _null_ _null_	binaryrecv - _null_ ));
+ DESCR("I/O");
+ DATA(insert OID = 2600 (  binarysend			PGNSP PGUID 12 f f t f s 1 17 "32" _null_ _null_ _null_  binarysend - _null_ ));
+ DESCR("I/O");
+ 
  
  /*
   * Symbolic values for provolatile column: these indicate whether the result
diff -cpr pgsql-orig/src/include/catalog/pg_type.h pgsql/src/include/catalog/pg_type.h
*** pgsql-orig/src/include/catalog/pg_type.h	2005-09-08 11:10:16.447303128 +0900
--- pgsql/src/include/catalog/pg_type.h	2005-09-08 11:11:04.903936600 +0900
*************** DATA(insert OID = 30 (	oidvector  PGNSP 
*** 306,311 ****
--- 306,319 ----
  DESCR("array of oids, used in system tables");
  #define OIDVECTOROID	30
  
+ DATA(insert OID = 31 (	string	   PGNSP PGUID -3 f b t \054 0	0 stringin stringout stringrecv stringsend - c p f 0 -1 0 _null_ _null_ ));
+ DESCR("variable-length string, no limit specified");
+ #define STRINGOID		31
+ 
+ DATA(insert OID = 32 (	binary	   PGNSP PGUID -3 f b t \054 0	0 binaryin binaryout binaryrecv binarysend - c p f 0 -1 0 _null_ _null_ ));
+ DESCR("variable-length string, binary values escaped");
+ #define BINARYOID		32
+ 
  /* hand-built rowtype entries for bootstrapped catalogs: */
  
  DATA(insert OID = 71 (	pg_type			PGNSP PGUID -1 f c t \054 1247 0 record_in record_out record_recv record_send - d x f 0 -1 0 _null_ _null_ ));
diff -cpr pgsql-orig/src/include/fmgr.h pgsql/src/include/fmgr.h
*** pgsql-orig/src/include/fmgr.h	2005-09-08 11:10:16.418307536 +0900
--- pgsql/src/include/fmgr.h	2005-09-08 11:11:04.904936448 +0900
*************** extern struct varlena *pg_detoast_datum_
*** 171,176 ****
--- 171,186 ----
  		(int32) f, (int32) c)
  
  /*
+  * Support for fetching detoasted copies of toastable varlena2 datatypes.
+  * pg_detoast_datum2() gives you either the input datum (if not toasted)
+  * or a detoasted copy allocated with palloc().
+  */
+ extern struct varlena2 *pg_detoast_datum2(struct varlena2 * datum);
+ 
+ #define PG_DETOAST_DATUM2(datum) \
+ 	pg_detoast_datum2((struct varlena2 *) DatumGetPointer(datum))
+ 
+ /*
   * Support for cleaning up detoasted copies of inputs.	This must only
   * be used for pass-by-ref datatypes, and normally would only be used
   * for toastable types.  If the given pointer is different from the
*************** extern struct varlena *pg_detoast_datum_
*** 204,217 ****
--- 214,234 ----
  #define PG_GETARG_INT64(n)	 DatumGetInt64(PG_GETARG_DATUM(n))
  /* use this if you want the raw, possibly-toasted input datum: */
  #define PG_GETARG_RAW_VARLENA_P(n)	((struct varlena *) PG_GETARG_POINTER(n))
+ #define PG_GETARG_RAW_VARLENA2_P(n)	((struct varlena2 *) PG_GETARG_POINTER(n))
  /* use this if you want the input datum de-toasted: */
  #define PG_GETARG_VARLENA_P(n) PG_DETOAST_DATUM(PG_GETARG_DATUM(n))
+ #define PG_GETARG_VARLENA2_P(n) PG_DETOAST_DATUM2(PG_GETARG_DATUM(n))
  /* DatumGetFoo macros for varlena types will typically look like this: */
  #define DatumGetByteaP(X)			((bytea *) PG_DETOAST_DATUM(X))
  #define DatumGetTextP(X)			((text *) PG_DETOAST_DATUM(X))
  #define DatumGetBpCharP(X)			((BpChar *) PG_DETOAST_DATUM(X))
  #define DatumGetVarCharP(X)			((VarChar *) PG_DETOAST_DATUM(X))
  #define DatumGetHeapTupleHeader(X)	((HeapTupleHeader) PG_DETOAST_DATUM(X))
+ /* DatumGetFoo macros for varlena2 types will typically look like this: */
+ #define DatumGetRawVarlena2P(X)		((struct varlena2 *) DatumGetPointer(X))
+ #define DatumGetVarlena2P(X)		PG_DETOAST_DATUM2(X)
+ #define DatumGetStringP(X)			((String *) DatumGetVarlena2P(X))
+ #define DatumGetBinaryP(X)			((Binary *) DatumGetVarlena2P(X))
  /* And we also offer variants that return an OK-to-write copy */
  #define DatumGetByteaPCopy(X)		((bytea *) PG_DETOAST_DATUM_COPY(X))
  #define DatumGetTextPCopy(X)		((text *) PG_DETOAST_DATUM_COPY(X))
*************** extern struct varlena *pg_detoast_datum_
*** 226,231 ****
--- 243,250 ----
  /* GETARG macros for varlena types will typically look like this: */
  #define PG_GETARG_BYTEA_P(n)		DatumGetByteaP(PG_GETARG_DATUM(n))
  #define PG_GETARG_TEXT_P(n)			DatumGetTextP(PG_GETARG_DATUM(n))
+ #define PG_GETARG_STRING_P(n)		DatumGetStringP(PG_GETARG_DATUM(n))
+ #define PG_GETARG_BINARY_P(n)		DatumGetBinaryP(PG_GETARG_DATUM(n))
  #define PG_GETARG_BPCHAR_P(n)		DatumGetBpCharP(PG_GETARG_DATUM(n))
  #define PG_GETARG_VARCHAR_P(n)		DatumGetVarCharP(PG_GETARG_DATUM(n))
  #define PG_GETARG_HEAPTUPLEHEADER(n)	DatumGetHeapTupleHeader(PG_GETARG_DATUM(n))
*************** extern struct varlena *pg_detoast_datum_
*** 267,272 ****
--- 286,293 ----
  /* RETURN macros for other pass-by-ref types will typically look like this: */
  #define PG_RETURN_BYTEA_P(x)   PG_RETURN_POINTER(x)
  #define PG_RETURN_TEXT_P(x)    PG_RETURN_POINTER(x)
+ #define PG_RETURN_STRING_P(x)  PG_RETURN_POINTER(x)
+ #define PG_RETURN_BINARY_P(x)  PG_RETURN_POINTER(x)
  #define PG_RETURN_BPCHAR_P(x)  PG_RETURN_POINTER(x)
  #define PG_RETURN_VARCHAR_P(x) PG_RETURN_POINTER(x)
  #define PG_RETURN_HEAPTUPLEHEADER(x)  PG_RETURN_POINTER(x)
diff -cpr pgsql-orig/src/include/utils/builtins.h pgsql/src/include/utils/builtins.h
*** pgsql-orig/src/include/utils/builtins.h	2005-09-08 11:10:16.392311488 +0900
--- pgsql/src/include/utils/builtins.h	2005-09-08 11:11:04.906936144 +0900
*************** extern Datum to_hex64(PG_FUNCTION_ARGS);
*** 601,606 ****
--- 601,616 ----
  extern Datum md5_text(PG_FUNCTION_ARGS);
  extern Datum md5_bytea(PG_FUNCTION_ARGS);
  
+ extern Datum stringin(PG_FUNCTION_ARGS);
+ extern Datum stringout(PG_FUNCTION_ARGS);
+ extern Datum stringrecv(PG_FUNCTION_ARGS);
+ extern Datum stringsend(PG_FUNCTION_ARGS);
+ 
+ extern Datum binaryin(PG_FUNCTION_ARGS);
+ extern Datum binaryout(PG_FUNCTION_ARGS);
+ extern Datum binaryrecv(PG_FUNCTION_ARGS);
+ extern Datum binarysend(PG_FUNCTION_ARGS);
+ 
  extern Datum unknownin(PG_FUNCTION_ARGS);
  extern Datum unknownout(PG_FUNCTION_ARGS);
  extern Datum unknownrecv(PG_FUNCTION_ARGS);
