diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c
index 424b5ae..81f94cc 100644
--- a/src/interfaces/ecpg/ecpglib/data.c
+++ b/src/interfaces/ecpg/ecpglib/data.c
@@ -122,6 +122,86 @@ check_special_value(char *ptr, double *retval, char **endptr)
 	return false;
 }
 
+/* imported from src/backend/utils/adt/encode.c */
+
+unsigned
+ecpg_hex_enc_len(unsigned srclen)
+{
+	return srclen << 1;
+}
+
+unsigned
+ecpg_hex_dec_len(unsigned srclen)
+{
+	return srclen >> 1;
+}
+
+static inline char
+get_hex(char c)
+{
+	static const int8 hexlookup[128] = {
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
+		-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	};
+	int			res = -1;
+
+	if (c > 0 && c < 127)
+		res = hexlookup[(unsigned char) c];
+
+	return (char) res;
+}
+
+static unsigned
+hex_decode(const char *src, unsigned len, char *dst)
+{
+	const char *s,
+			   *srcend;
+	char		v1,
+				v2,
+			   *p;
+
+	srcend = src + len;
+	s = src;
+	p = dst;
+	while (s < srcend)
+	{
+		if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
+		{
+			s++;
+			continue;
+		}
+		v1 = get_hex(*s++) << 4;
+		if (s >= srcend)
+			return -1;
+
+		v2 = get_hex(*s++);
+		*p++ = v1 | v2;
+	}
+
+	return p - dst;
+}
+
+unsigned
+ecpg_hex_encode(const char *src, unsigned len, char *dst)
+{
+	static const char hextbl[] = "0123456789abcdef";
+	const char *end = src + len;
+
+	while (src < end)
+	{
+		*dst++ = hextbl[(*src >> 4) & 0xF];
+		*dst++ = hextbl[*src & 0xF];
+		src++;
+	}
+	return len * 2;
+}
+
 bool
 ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 			  enum ECPGttype type, enum ECPGttype ind_type,
@@ -447,6 +527,55 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 					return false;
 					break;
 
+				case ECPGt_bytea:
+					{
+						struct ECPGgeneric_varchar *variable =
+						(struct ECPGgeneric_varchar *) (var + offset * act_tuple);
+						long		dst_size,
+									src_size,
+									dec_size;
+
+						dst_size = ecpg_hex_enc_len(varcharsize);
+						src_size = size - 2;	/* exclude backslash + 'x' */
+						dec_size = src_size < dst_size ? src_size : dst_size;
+						variable->len = hex_decode(pval + 2, dec_size, variable->arr);
+
+						if (dst_size < src_size)
+						{
+							long		rcv_size = ecpg_hex_dec_len(size - 2);
+
+							/* truncation */
+							switch (ind_type)
+							{
+								case ECPGt_short:
+								case ECPGt_unsigned_short:
+									*((short *) (ind + ind_offset * act_tuple)) = rcv_size;
+									break;
+								case ECPGt_int:
+								case ECPGt_unsigned_int:
+									*((int *) (ind + ind_offset * act_tuple)) = rcv_size;
+									break;
+								case ECPGt_long:
+								case ECPGt_unsigned_long:
+									*((long *) (ind + ind_offset * act_tuple)) = rcv_size;
+									break;
+#ifdef HAVE_LONG_LONG_INT
+								case ECPGt_long_long:
+								case ECPGt_unsigned_long_long:
+									*((long long int *) (ind + ind_offset * act_tuple)) = rcv_size;
+									break;
+#endif							/* HAVE_LONG_LONG_INT */
+								default:
+									break;
+							}
+							sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
+						}
+
+						pval += size;
+
+					}
+					break;
+
 				case ECPGt_char:
 				case ECPGt_unsigned_char:
 				case ECPGt_string:
diff --git a/src/interfaces/ecpg/ecpglib/descriptor.c b/src/interfaces/ecpg/ecpglib/descriptor.c
index 186f92c..ae1a7db 100644
--- a/src/interfaces/ecpg/ecpglib/descriptor.c
+++ b/src/interfaces/ecpg/ecpglib/descriptor.c
@@ -636,11 +636,29 @@ ECPGset_desc(int lineno, const char *desc_name, int index,...)
 		{
 			case ECPGd_data:
 				{
-					if (!ecpg_store_input(lineno, true, var, &tobeinserted, false))
+					if (var->type != ECPGt_bytea)
 					{
-						ecpg_free(var);
-						va_end(args);
-						return false;
+						if (!ecpg_store_input(lineno, true, var, &tobeinserted, false))
+						{
+							ecpg_free(var);
+							va_end(args);
+							return false;
+						}
+						desc_item->is_binary = false;
+					}
+					else
+					{
+						struct ECPGgeneric_varchar *variable =
+						(struct ECPGgeneric_varchar *) (var->value);
+
+						if (!(tobeinserted = ecpg_alloc(sizeof(int) + variable->len, lineno)))
+						{
+							ecpg_free(var);
+							va_end(args);
+							return false;
+						}
+						memcpy(tobeinserted, var->value, sizeof(int) + variable->len);
+						desc_item->is_binary = true;
 					}
 
 					ecpg_free(desc_item->data); /* free() takes care of a
diff --git a/src/interfaces/ecpg/ecpglib/ecpglib_extern.h b/src/interfaces/ecpg/ecpglib/ecpglib_extern.h
index 1c9bce1..a4e593c 100644
--- a/src/interfaces/ecpg/ecpglib/ecpglib_extern.h
+++ b/src/interfaces/ecpg/ecpglib/ecpglib_extern.h
@@ -37,6 +37,13 @@ struct ECPGgeneric_varchar
 	char		arr[FLEXIBLE_ARRAY_MEMBER];
 };
 
+/* A generic bytea type. */
+struct ECPGgeneric_bytea
+{
+	int			len;
+	char		arr[FLEXIBLE_ARRAY_MEMBER];
+};
+
 /*
  * type information cache
  */
@@ -64,6 +71,8 @@ struct statement
 	char	   *oldlocale;
 	int			nparams;
 	char	  **paramvalues;
+	int		   *paramlengths;
+	int		   *paramformats;
 	PGresult   *results;
 };
 
@@ -106,6 +115,8 @@ struct descriptor_item
 	int			precision;
 	int			scale;
 	int			type;
+	bool		is_binary;
+	int			data_len;
 	struct descriptor_item *next;
 };
 
@@ -194,6 +205,9 @@ struct sqlda_compat *ecpg_build_compat_sqlda(int, PGresult *, int, enum COMPAT_M
 void		ecpg_set_compat_sqlda(int, struct sqlda_compat **, const PGresult *, int, enum COMPAT_MODE);
 struct sqlda_struct *ecpg_build_native_sqlda(int, PGresult *, int, enum COMPAT_MODE);
 void		ecpg_set_native_sqlda(int, struct sqlda_struct **, const PGresult *, int, enum COMPAT_MODE);
+unsigned	ecpg_hex_dec_len(unsigned srclen);
+unsigned	ecpg_hex_enc_len(unsigned srclen);
+unsigned	ecpg_hex_encode(const char *src, unsigned len, char *dst);
 
 /* SQLSTATE values generated or processed by ecpglib (intentionally
  * not exported -- users should refer to the codes directly) */
diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index 3f5034e..96d3107 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -799,6 +799,20 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
 					*tobeinserted_p = mallocedval;
 				}
 				break;
+
+			case ECPGt_bytea:
+				{
+					struct ECPGgeneric_varchar *variable =
+					(struct ECPGgeneric_varchar *) (var->value);
+
+					if (!(mallocedval = (char *) ecpg_alloc(variable->len, lineno)))
+						return false;
+
+					memcpy(mallocedval, variable->arr, variable->len);
+					*tobeinserted_p = mallocedval;
+				}
+				break;
+
 			case ECPGt_varchar:
 				{
 					struct ECPGgeneric_varchar *variable =
@@ -1041,6 +1055,30 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
 	return true;
 }
 
+static void
+print_param_value(char *value, int len, int is_binary, int lineno, int nth)
+{
+	char *value_s;
+	bool malloced = false;
+
+	if (value == NULL)
+		value_s = "null";
+	else if (! is_binary)
+		value_s = value;
+	else
+	{
+		value_s = ecpg_alloc(ecpg_hex_enc_len(len), lineno);
+		ecpg_hex_encode(value, len, value_s);
+		malloced = true;
+	}
+
+	ecpg_log("ecpg_free_params on line %d: parameter %d = %s\n",
+				lineno, nth, value_s);
+
+	if (malloced)
+		ecpg_free(value_s);
+}
+
 void
 ecpg_free_params(struct statement *stmt, bool print)
 {
@@ -1049,11 +1087,16 @@ ecpg_free_params(struct statement *stmt, bool print)
 	for (n = 0; n < stmt->nparams; n++)
 	{
 		if (print)
-			ecpg_log("ecpg_free_params on line %d: parameter %d = %s\n", stmt->lineno, n + 1, stmt->paramvalues[n] ? stmt->paramvalues[n] : "null");
+			print_param_value(stmt->paramvalues[n], stmt->paramlengths[n],
+								stmt->paramformats[n], stmt->lineno, n + 1);
 		ecpg_free(stmt->paramvalues[n]);
 	}
 	ecpg_free(stmt->paramvalues);
+	ecpg_free(stmt->paramlengths);
+	ecpg_free(stmt->paramformats);
 	stmt->paramvalues = NULL;
+	stmt->paramlengths = NULL;
+	stmt->paramformats = NULL;
 	stmt->nparams = 0;
 }
 
@@ -1120,8 +1163,13 @@ ecpg_build_params(struct statement *stmt)
 	{
 		char	   *tobeinserted;
 		int			counter = 1;
+		bool		binary_format;
+		int			binary_length;
+
 
 		tobeinserted = NULL;
+		binary_length = 0;
+		binary_format = false;
 
 		/*
 		 * A descriptor is a special case since it contains many variables but
@@ -1146,12 +1194,27 @@ ecpg_build_params(struct statement *stmt)
 			{
 				if (desc_item->num == desc_counter)
 				{
-					desc_inlist.type = ECPGt_char;
+					if (!desc_item->is_binary)
+					{
+						desc_inlist.type = ECPGt_char;
+						desc_inlist.varcharsize = strlen(desc_item->data);
+					}
+					else
+					{
+						struct ECPGgeneric_varchar *variable =
+						(struct ECPGgeneric_varchar *) (desc_item->data);
+
+						binary_length = variable->len;
+						binary_format = true;
+
+						desc_inlist.type = ECPGt_bytea;
+						desc_inlist.varcharsize = binary_length;
+					}
 					desc_inlist.value = desc_item->data;
 					desc_inlist.pointer = &(desc_item->data);
-					desc_inlist.varcharsize = strlen(desc_item->data);
 					desc_inlist.arrsize = 1;
 					desc_inlist.offset = 0;
+
 					if (!desc_item->indicator)
 					{
 						desc_inlist.ind_type = ECPGt_NO_INDICATOR;
@@ -1293,6 +1356,15 @@ ecpg_build_params(struct statement *stmt)
 		{
 			if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, false))
 				return false;
+
+			if (var->type == ECPGt_bytea)
+			{
+				struct ECPGgeneric_varchar *variable =
+				(struct ECPGgeneric_varchar *) (var->value);
+
+				binary_length = variable->len;
+				binary_format = true;
+			}
 		}
 
 		/*
@@ -1346,16 +1418,32 @@ ecpg_build_params(struct statement *stmt)
 		else
 		{
 			char	  **paramvalues;
+			int		   *paramlengths;
+			int		   *paramformats;
 
 			if (!(paramvalues = (char **) ecpg_realloc(stmt->paramvalues, sizeof(char *) * (stmt->nparams + 1), stmt->lineno)))
 			{
 				ecpg_free_params(stmt, false);
 				return false;
 			}
+			if (!(paramlengths = (int *) ecpg_realloc(stmt->paramlengths, sizeof(int) * (stmt->nparams + 1), stmt->lineno)))
+			{
+				ecpg_free_params(stmt, false);
+				return false;
+			}
+			if (!(paramformats = (int *) ecpg_realloc(stmt->paramformats, sizeof(int) * (stmt->nparams + 1), stmt->lineno)))
+			{
+				ecpg_free_params(stmt, false);
+				return false;
+			}
 
 			stmt->nparams++;
 			stmt->paramvalues = paramvalues;
+			stmt->paramlengths = paramlengths;
+			stmt->paramformats = paramformats;
 			stmt->paramvalues[stmt->nparams - 1] = tobeinserted;
+			stmt->paramlengths[stmt->nparams - 1] = binary_length;
+			stmt->paramformats[stmt->nparams - 1] = (binary_format ? 1 : 0);
 
 			/* let's see if this was an old style placeholder */
 			if (stmt->command[position] == '?')
@@ -1428,7 +1516,13 @@ ecpg_execute(struct statement *stmt)
 	ecpg_log("ecpg_execute on line %d: query: %s; with %d parameter(s) on connection %s\n", stmt->lineno, stmt->command, stmt->nparams, stmt->connection->name);
 	if (stmt->statement_type == ECPGst_execute)
 	{
-		stmt->results = PQexecPrepared(stmt->connection->connection, stmt->name, stmt->nparams, (const char *const *) stmt->paramvalues, NULL, NULL, 0);
+		stmt->results = PQexecPrepared(stmt->connection->connection,
+									   stmt->name,
+									   stmt->nparams,
+									   (const char *const *) stmt->paramvalues,
+									   (const int *) stmt->paramlengths,
+									   (const int *) stmt->paramformats,
+									   0);
 		ecpg_log("ecpg_execute on line %d: using PQexecPrepared for \"%s\"\n", stmt->lineno, stmt->command);
 	}
 	else
@@ -1440,7 +1534,12 @@ ecpg_execute(struct statement *stmt)
 		}
 		else
 		{
-			stmt->results = PQexecParams(stmt->connection->connection, stmt->command, stmt->nparams, NULL, (const char *const *) stmt->paramvalues, NULL, NULL, 0);
+			stmt->results = PQexecParams(stmt->connection->connection,
+										 stmt->command, stmt->nparams, NULL,
+										 (const char *const *) stmt->paramvalues,
+										 (const int *) stmt->paramlengths,
+										 (const int *) stmt->paramformats,
+										 0);
 			ecpg_log("ecpg_execute on line %d: using PQexecParams\n", stmt->lineno);
 		}
 	}
diff --git a/src/interfaces/ecpg/ecpglib/misc.c b/src/interfaces/ecpg/ecpglib/misc.c
index a26dfdb..349dec3 100644
--- a/src/interfaces/ecpg/ecpglib/misc.c
+++ b/src/interfaces/ecpg/ecpglib/misc.c
@@ -355,6 +355,9 @@ ECPGset_noind_null(enum ECPGttype type, void *ptr)
 			*(((struct ECPGgeneric_varchar *) ptr)->arr) = 0x00;
 			((struct ECPGgeneric_varchar *) ptr)->len = 0;
 			break;
+		case ECPGt_bytea:
+			((struct ECPGgeneric_bytea *) ptr)->len = 0;
+			break;
 		case ECPGt_decimal:
 			memset((char *) ptr, 0, sizeof(decimal));
 			((decimal *) ptr)->sign = NUMERIC_NULL;
@@ -428,6 +431,10 @@ ECPGis_noind_null(enum ECPGttype type, const void *ptr)
 			if (*(((const struct ECPGgeneric_varchar *) ptr)->arr) == 0x00)
 				return true;
 			break;
+		case ECPGt_bytea:
+			if (((struct ECPGgeneric_bytea *) ptr)->len == 0)
+				return true;
+			break;
 		case ECPGt_decimal:
 			if (((const decimal *) ptr)->sign == NUMERIC_NULL)
 				return true;
diff --git a/src/interfaces/ecpg/ecpglib/typename.c b/src/interfaces/ecpg/ecpglib/typename.c
index a3f2817..9251450 100644
--- a/src/interfaces/ecpg/ecpglib/typename.c
+++ b/src/interfaces/ecpg/ecpglib/typename.c
@@ -48,6 +48,8 @@ ecpg_type_name(enum ECPGttype typ)
 			return "bool";
 		case ECPGt_varchar:
 			return "varchar";
+		case ECPGt_bytea:
+			return "bytea";
 		case ECPGt_char_variable:
 			return "char";
 		case ECPGt_decimal:
diff --git a/src/interfaces/ecpg/include/ecpgtype.h b/src/interfaces/ecpg/include/ecpgtype.h
index 38fb3b6..b9fc4ea 100644
--- a/src/interfaces/ecpg/include/ecpgtype.h
+++ b/src/interfaces/ecpg/include/ecpgtype.h
@@ -63,7 +63,8 @@ enum ECPGttype
 	ECPGt_EORT,					/* End of result types. */
 	ECPGt_NO_INDICATOR,			/* no indicator */
 	ECPGt_string,				/* trimmed (char *) type */
-	ECPGt_sqlda					/* C struct descriptor */
+	ECPGt_sqlda,				/* C struct descriptor */
+	ECPGt_bytea
 };
 
  /* descriptor items */
@@ -88,7 +89,7 @@ enum ECPGdtype
 	ECPGd_cardinality
 };
 
-#define IS_SIMPLE_TYPE(type) (((type) >= ECPGt_char && (type) <= ECPGt_interval) || ((type) == ECPGt_string))
+#define IS_SIMPLE_TYPE(type) (((type) >= ECPGt_char && (type) <= ECPGt_interval) || ((type) == ECPGt_string) || ((type) == ECPGt_bytea))
 
 /* we also have to handle different statement types */
 enum ECPG_statement_type
diff --git a/src/interfaces/ecpg/preproc/ecpg.header b/src/interfaces/ecpg/preproc/ecpg.header
index 00143a7..0bd38bd 100644
--- a/src/interfaces/ecpg/preproc/ecpg.header
+++ b/src/interfaces/ecpg/preproc/ecpg.header
@@ -46,6 +46,7 @@ static char	pacounter_buffer[sizeof(int) * CHAR_BIT * 10 / 3]; /* a rough guess
 static struct this_type actual_type[STRUCT_DEPTH];
 static char *actual_startline[STRUCT_DEPTH];
 static int	varchar_counter = 1;
+static int	bytea_counter = 1;
 
 /* temporarily store struct members while creating the data structure */
 struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL };
@@ -562,6 +563,7 @@ add_typedef(char *name, char *dimension, char *length, enum ECPGttype type_enum,
 		ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL;
 
 		if (type_enum != ECPGt_varchar &&
+			type_enum != ECPGt_bytea &&
 			type_enum != ECPGt_char &&
 			type_enum != ECPGt_unsigned_char &&
 			type_enum != ECPGt_string &&
diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer
index 19dc781..c44fcf9 100644
--- a/src/interfaces/ecpg/preproc/ecpg.trailer
+++ b/src/interfaces/ecpg/preproc/ecpg.trailer
@@ -550,6 +550,14 @@ var_type:	simple_type
 				$$.type_index = mm_strdup("-1");
 				$$.type_sizeof = NULL;
 			}
+			else if (strcmp($1, "bytea") == 0)
+			{
+				$$.type_enum = ECPGt_bytea;
+				$$.type_str = EMPTY;
+				$$.type_dimension = mm_strdup("-1");
+				$$.type_index = mm_strdup("-1");
+				$$.type_sizeof = NULL;
+			}
 			else if (strcmp($1, "float") == 0)
 			{
 				$$.type_enum = ECPGt_float;
@@ -627,7 +635,7 @@ var_type:	simple_type
 				/* this is for typedef'ed types */
 				struct typedefs *this = get_typedef($1);
 
-				$$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
+				$$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? EMPTY : mm_strdup(this->name);
 				$$.type_enum = this->type->type_enum;
 				$$.type_dimension = this->type->type_dimension;
 				$$.type_index = this->type->type_index;
@@ -838,7 +846,7 @@ variable_list: variable
 			{ $$ = $1; }
 		| variable_list ',' variable
 		{
-			if (actual_type[struct_level].type_enum == ECPGt_varchar)
+			if (actual_type[struct_level].type_enum == ECPGt_varchar || actual_type[struct_level].type_enum == ECPGt_bytea)
 				$$ = cat_str(3, $1, mm_strdup(";"), $3);
 			else
 				$$ = cat_str(3, $1, mm_strdup(","), $3);
@@ -852,9 +860,10 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize
 			char *length = $3.index2;		/* length of string */
 			char *dim_str;
 			char *vcn;
+			int *varlen_type_counter;
+			char *struct_name;
 
 			adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1), false);
-
 			switch (actual_type[struct_level].type_enum)
 			{
 				case ECPGt_struct:
@@ -868,10 +877,21 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize
 					break;
 
 				case ECPGt_varchar:
+				case ECPGt_bytea:
+					if (actual_type[struct_level].type_enum == ECPGt_varchar)
+					{
+						varlen_type_counter = &varchar_counter;
+						struct_name = " struct varchar_";
+					}
+					else
+					{
+						varlen_type_counter = &bytea_counter;
+						struct_name = " struct bytea_";
+					}
 					if (atoi(dimension) < 0)
-						type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, varchar_counter);
+						type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, *varlen_type_counter);
 					else
-						type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, varchar_counter), dimension);
+						type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, *varlen_type_counter), dimension);
 
 					if (strcmp(dimension, "0") == 0 || abs(atoi(dimension)) == 1)
 							dim_str=mm_strdup("");
@@ -883,12 +903,12 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize
 
 					/* make sure varchar struct name is unique by adding a unique counter to its definition */
 					vcn = (char *) mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
-					sprintf(vcn, "%d", varchar_counter);
+					sprintf(vcn, "%d", *varlen_type_counter);
 					if (strcmp(dimension, "0") == 0)
-						$$ = cat_str(7, make2_str(mm_strdup(" struct varchar_"), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } *"), mm_strdup($2), $4, $5);
+						$$ = cat_str(7, make2_str(mm_strdup(struct_name), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } *"), mm_strdup($2), $4, $5);
 					else
-						$$ = cat_str(8, make2_str(mm_strdup(" struct varchar_"), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } "), mm_strdup($2), dim_str, $4, $5);
-					varchar_counter++;
+						$$ = cat_str(8, make2_str(mm_strdup(struct_name), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } "), mm_strdup($2), dim_str, $4, $5);
+					(*varlen_type_counter)++;
 					break;
 
 				case ECPGt_char:
@@ -1354,6 +1374,7 @@ ECPGVar: SQL_VAR
 						break;
 
 					case ECPGt_varchar:
+					case ECPGt_bytea:
 						if (atoi(dimension) == -1)
 							type = ECPGmake_simple_type($5.type_enum, length, 0);
 						else
diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c
index 40ce3fb..5488db3 100644
--- a/src/interfaces/ecpg/preproc/type.c
+++ b/src/interfaces/ecpg/preproc/type.c
@@ -102,7 +102,7 @@ ECPGmake_simple_type(enum ECPGttype type, char *size, int counter)
 	ne->size = size;
 	ne->u.element = NULL;
 	ne->struct_sizeof = NULL;
-	ne->counter = counter;		/* only needed for varchar */
+	ne->counter = counter;		/* only needed for varchar and bytea */
 
 	return ne;
 }
@@ -175,6 +175,8 @@ get_type(enum ECPGttype type)
 			break;
 		case ECPGt_varchar:
 			return "ECPGt_varchar";
+		case ECPGt_bytea:
+			return "ECPGt_bytea";
 		case ECPGt_NO_INDICATOR:	/* no indicator */
 			return "ECPGt_NO_INDICATOR";
 			break;
@@ -424,6 +426,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
 	{
 		char	   *variable = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4);
 		char	   *offset = (char *) mm_alloc(strlen(name) + strlen("sizeof(struct varchar_)") + 1 + strlen(varcharsize) + sizeof(int) * CHAR_BIT * 10 / 3);
+		char	   *struct_name;
 
 		switch (type)
 		{
@@ -433,6 +436,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
 				 */
 
 			case ECPGt_varchar:
+			case ECPGt_bytea:
 
 				/*
 				 * we have to use the pointer except for arrays with given
@@ -449,10 +453,15 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
 				 * If we created a varchar structure automatically, counter is
 				 * greater than 0.
 				 */
+				if (type == ECPGt_varchar)
+					struct_name = "struct varchar";
+				else
+					struct_name = "struct bytea";
+
 				if (counter)
-					sprintf(offset, "sizeof(struct varchar_%d)", counter);
+					sprintf(offset, "sizeof(%s_%d)", struct_name, counter);
 				else
-					sprintf(offset, "sizeof(struct varchar)");
+					sprintf(offset, "sizeof(%s)", struct_name);
 				break;
 			case ECPGt_char:
 			case ECPGt_unsigned_char:
diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.c
index a953498..887d479 100644
--- a/src/interfaces/ecpg/preproc/variable.c
+++ b/src/interfaces/ecpg/preproc/variable.c
@@ -560,6 +560,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty
 
 			break;
 		case ECPGt_varchar:
+		case ECPGt_bytea:
 			/* pointer has to get dimension 0 */
 			if (pointer_len)
 				*dimension = mm_strdup("0");
