diff --git a/src/interfaces/ecpg/ecpglib/cursor.c b/src/interfaces/ecpg/ecpglib/cursor.c
index 133d623..6cb236b 100644
--- a/src/interfaces/ecpg/ecpglib/cursor.c
+++ b/src/interfaces/ecpg/ecpglib/cursor.c
@@ -65,7 +65,7 @@ ECPGopen(const char *cursor_name,const char *prepared_name,
 
 	va_start(args, query);
 
-	status = ecpg_do(lineno, compat, force_indicator, real_connection_name, questionmarks, st, query, args);
+	status = ecpg_do(lineno, compat, force_indicator, real_connection_name, questionmarks, st, NULL, query, args);
 
 	va_end(args);
 
@@ -107,7 +107,7 @@ ECPGfetch(const char *cursor_name,
 
 	va_start(args, query);
 
-	status = ecpg_do(lineno, compat, force_indicator, real_connection_name, questionmarks, st, query, args);
+	status = ecpg_do(lineno, compat, force_indicator, real_connection_name, questionmarks, st, NULL, query, args);
 
 	va_end(args);
 
@@ -153,7 +153,7 @@ ECPGclose(const char *cursor_name,
 	/* send the query to backend */
 	va_start(args, query);
 
-	status = ecpg_do(lineno, compat, force_indicator, real_connection_name, questionmarks, st, query, args);
+	status = ecpg_do(lineno, compat, force_indicator, real_connection_name, questionmarks, st, NULL, query, args);
 
 	va_end(args);
 
diff --git a/src/interfaces/ecpg/ecpglib/ecpglib_extern.h b/src/interfaces/ecpg/ecpglib/ecpglib_extern.h
index 1ec2bf4..213718b 100644
--- a/src/interfaces/ecpg/ecpglib/ecpglib_extern.h
+++ b/src/interfaces/ecpg/ecpglib/ecpglib_extern.h
@@ -214,7 +214,7 @@ bool ecpg_store_result(const PGresult *results, int act_field,
 bool		ecpg_store_input(const int, const bool, const struct variable *, char **, bool);
 void		ecpg_free_params(struct statement *stmt, bool print);
 bool ecpg_do_prologue(int, const int, const int, const char *, const bool,
-				 enum ECPG_statement_type, const char *, va_list,
+				 enum ECPG_statement_type, const char *, const char *, va_list,
 				 struct statement **);
 bool		ecpg_build_params(struct statement *);
 bool		ecpg_autostart_transaction(struct statement *stmt);
@@ -222,7 +222,7 @@ bool		ecpg_execute(struct statement *stmt);
 bool		ecpg_process_output(struct statement *, bool);
 void		ecpg_do_epilogue(struct statement *);
 bool ecpg_do(const int, const int, const int, const char *, const bool,
-		const int, const char *, va_list);
+		const int, const char *, const char *, va_list);
 
 bool		ecpg_check_PQresult(PGresult *, int, PGconn *, enum COMPAT_MODE);
 void		ecpg_raise(int line, int code, const char *sqlstate, const char *str);
@@ -231,6 +231,7 @@ char	   *ecpg_prepared(const char *, struct connection *);
 bool		ecpg_deallocate_all_conn(int lineno, enum COMPAT_MODE c, struct connection *conn);
 void		ecpg_log(const char *format,...) pg_attribute_printf(1, 2);
 bool		ecpg_auto_prepare(int, const char *, const int, char **, const char *);
+bool		ecpg_register_prepared_stmt(struct statement *);
 void		ecpg_init_sqlca(struct sqlca_t *sqlca);
 
 struct sqlda_compat *ecpg_build_compat_sqlda(int, PGresult *, int, enum COMPAT_MODE);
diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index 8e61339..0723be7 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -1143,6 +1143,23 @@ insert_tobeinserted(int position, int ph_len, struct statement *stmt, char *tobe
 	return true;
 }
 
+static char*
+convert_bytea_to_string(char *from_data, int from_len, int lineno)
+{
+	char *to_data;
+	int to_len = ecpg_hex_enc_len(from_len) + 4 + 1; /* backslash + 'x' + quote + quote */
+
+	to_data = ecpg_alloc(to_len, lineno);
+	if (!to_data)
+		return NULL;
+
+	strcpy(to_data, "'\\x");
+	ecpg_hex_encode(from_data, from_len, to_data + 3);
+	strcpy(to_data + 3 + ecpg_hex_enc_len(from_len), "\'");
+
+	return to_data;
+}
+
 static bool
 store_input_from_desc(struct statement *stmt, struct descriptor_item *desc_item,
 						char **tobeinserted)
@@ -1440,6 +1457,32 @@ ecpg_build_params(struct statement *stmt)
 			}
 			tobeinserted = NULL;
 		}
+		else if (stmt->statement_type == ECPGst_execnormal)
+		{
+			int	param_id_len;
+			char	*p;
+
+			if (binary_format)
+			{
+				p = convert_bytea_to_string(tobeinserted, binary_length, stmt->lineno);
+				if (!p)
+				{
+					ecpg_free_params(stmt, false);
+					return false;
+				}
+				tobeinserted = p;
+			}
+
+			for (param_id_len = 1, p = stmt->command + position; isdigit(*p); ++param_id_len, ++p)
+				;
+
+			if (!insert_tobeinserted(position, param_id_len, stmt, tobeinserted))
+			{
+				ecpg_free_params(stmt, false);
+				return false;
+			}
+			tobeinserted = NULL;
+		}
 		else
 		{
 			if (!(stmt->paramvalues = (char **) ecpg_realloc(stmt->paramvalues, sizeof(char *) * (stmt->nparams + 1), stmt->lineno)))
@@ -1493,13 +1536,19 @@ ecpg_build_params(struct statement *stmt)
 			var = var->next;
 	}
 
-	/* Check if there are unmatched things left. */
-	if (next_insert(stmt->command, position, stmt->questionmarks, std_strings) >= 0)
+	/*
+	 * PREPARE with AS clause has no parameter to be converted.
+	 */
+	if (stmt->statement_type != ECPGst_prepare)
 	{
-		ecpg_raise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS,
-				   ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
-		ecpg_free_params(stmt, false);
-		return false;
+		/* Check if there are unmatched things left. */
+		if (next_insert(stmt->command, position, stmt->questionmarks, std_strings) >= 0)
+		{
+			ecpg_raise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS,
+					   ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
+			ecpg_free_params(stmt, false);
+			return false;
+		}
 	}
 
 	return true;
@@ -1536,6 +1585,9 @@ 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)
 	{
+		/*
+		 * send only 'B' message and parameters
+		 */
 		stmt->results = PQexecPrepared(stmt->connection->connection,
 									   stmt->name,
 									   stmt->nparams,
@@ -1545,6 +1597,28 @@ ecpg_execute(struct statement *stmt)
 									   0);
 		ecpg_log("ecpg_execute on line %d: using PQexecPrepared for \"%s\"\n", stmt->lineno, stmt->command);
 	}
+	else if (stmt->statement_type == ECPGst_execnormal)
+	{
+		/*
+		 * send 'Q' with 'EXECUTE st(param,...)'. Parameters are string-formatted and embedded into the query.
+		 */
+		stmt->results = PQexec(stmt->connection->connection, stmt->command);
+		ecpg_log("ecpg_execute on line %d: using PQexec\n", stmt->lineno);
+	}
+	else if (stmt->statement_type == ECPGst_prepare)
+	{
+		/*
+		 * send 'Q' with 'PREPARE st(type,...) as ...'.
+		 */
+		stmt->results = PQexec(stmt->connection->connection, stmt->command);
+		ecpg_log("ecpg_execute on line %d: using PQexec\n", stmt->lineno);
+
+		if(! ecpg_register_prepared_stmt(stmt))
+		{
+			ecpg_free_params(stmt, true);
+			return false;
+		}
+	}
 	else
 	{
 		if (stmt->nparams == 0)
@@ -1866,7 +1940,7 @@ ecpg_process_output(struct statement *stmt, bool clear_result)
 bool
 ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
 				 const char *connection_name, const bool questionmarks,
-				 enum ECPG_statement_type statement_type, const char *query,
+				 enum ECPG_statement_type statement_type, const char* prepared_name, const char *query,
 				 va_list args, struct statement **stmt_out)
 {
 	struct statement *stmt = NULL;
@@ -1926,6 +2000,14 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
 	ecpg_pthreads_init();
 #endif
 
+
+	if (prepared_name)
+	{
+		char	*con_name = ecpg_get_con_name_by_declared_name(prepared_name);
+		if (con_name)
+			connection_name = con_name;
+	}
+
 	con = ecpg_get_connection(connection_name);
 
 	if (!ecpg_init(con, connection_name, lineno))
@@ -1938,42 +2020,69 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
 	 * If statement type is ECPGst_prepnormal we are supposed to prepare the
 	 * statement before executing them
 	 */
-	if (statement_type == ECPGst_prepnormal)
+	switch (statement_type)
 	{
-		if (!ecpg_auto_prepare(lineno, connection_name, compat, &prepname, query))
-		{
-			ecpg_do_epilogue(stmt);
-			return false;
-		}
-
-		/*
-		 * statement is now prepared, so instead of the query we have to
-		 * execute the name
-		 */
-		stmt->command = prepname;
-		statement_type = ECPGst_execute;
-	}
-	else
-		stmt->command = ecpg_strdup(query, lineno);
+		case ECPGst_prepnormal:
+			/*
+			 * statement is now prepared, so instead of the query we have to
+			 * execute the name
+			 */
+			if (!ecpg_auto_prepare(lineno, connection_name, compat, &prepname, query))
+			{
+				ecpg_do_epilogue(stmt);
+				return false;
+			}
+			stmt->name = prepname;
+			stmt->command = ecpg_strdup(query, lineno);
+			statement_type = ECPGst_execute;
+			break;
 
-	stmt->name = NULL;
+		case ECPGst_prepare:
+			/*
+			 * If statent type is ECPGst_prepare that is PREPARE with AS clause and
+			 * typelist clause, ecpg_execute will call PQexec("PREPARE name(typelist)")
+			 */
+			stmt->name = ecpg_strdup(prepared_name, lineno);
+			stmt->command = ecpg_strdup(query, lineno);
+			break;
 
-	if (statement_type == ECPGst_execute)
-	{
-		/* if we have an EXECUTE command, only the name is send */
-		char	   *command = ecpg_prepared(stmt->command, con);
+		case ECPGst_execnormal:
+			/*
+			 * Send EXECUTE stm_name($1, 'x', ...). Params will be replaced with vars in build_params.
+			 */
+			if (!ecpg_prepared(prepared_name, con))
+			{
+				ecpg_raise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, prepared_name);
+				ecpg_do_epilogue(stmt);
+				return false;
+			}
+			/* st->command is prepared-name in case of prepnormal and EXECUTE without parameter-list-clause. */
+			stmt->name = ecpg_strdup(prepared_name, lineno);
+			stmt->command = ecpg_strdup(query, lineno);
+			break;
 
-		if (command)
+		case ECPGst_execute:
 		{
-			stmt->name = stmt->command;
+			/*
+			 * Send Bind message only. Prepared query is used only for checking number of params.
+			 */
+			char	*command = ecpg_prepared(prepared_name, con);
+			if (!command)
+			{
+				ecpg_raise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, prepared_name);
+				ecpg_do_epilogue(stmt);
+				return false;
+			}
+			/* st->command is prepared-name in case of prepnormal and EXECUTE without parameter-list-clause. */
+			stmt->name = ecpg_strdup(prepared_name, lineno);
 			stmt->command = ecpg_strdup(command, lineno);
+			break;
 		}
-		else
-		{
-			ecpg_raise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, stmt->command);
-			ecpg_do_epilogue(stmt);
-			return false;
-		}
+
+		default:
+			stmt->name = ecpg_strdup(prepared_name, lineno);
+			stmt->command = ecpg_strdup(query, lineno);
+			break;
 	}
 
 	stmt->connection = con;
@@ -2150,13 +2259,13 @@ ecpg_do_epilogue(struct statement *stmt)
  * in a va_list, so other functions can use this interface.
  */
 bool
-ecpg_do(const int lineno, const int compat, const int force_indicator, const char *connection_name, const bool questionmarks, const int st, const char *query, va_list args)
+ecpg_do(const int lineno, const int compat, const int force_indicator, const char *connection_name, const bool questionmarks, const int st, const char *prepared_name, const char *query, va_list args)
 {
 	struct statement *stmt = NULL;
 
 	if (!ecpg_do_prologue(lineno, compat, force_indicator, connection_name,
 						  questionmarks, (enum ECPG_statement_type) st,
-						  query, args, &stmt))
+						  prepared_name, query, args, &stmt))
 		goto fail;
 
 	if (!ecpg_build_params(stmt))
@@ -2184,13 +2293,10 @@ fail:
  * The input/output parameters are passed as variable-length argument list.
  */
 bool
-ECPGdo(const int lineno, const int compat, const int force_indicator, const char *connection_name, const bool questionmarks, const int st, const char *query,...)
+ECPGdo(const int lineno, const int compat, const int force_indicator, const char *connection_name, const bool questionmarks, const int st, const char *prepared_name, const char *query,...)
 {
 	va_list		args;
 	bool		ret;
-	const char  *real_connection_name = NULL;
-
-	real_connection_name = connection_name;
 
 	if (!query)
 	{
@@ -2198,23 +2304,9 @@ ECPGdo(const int lineno, const int compat, const int force_indicator, const char
 		return false;
 	}
 
-	/* Handle the EXEC SQL EXECUTE... statement */
-	if (ECPGst_execute == st)
-	{
-		real_connection_name = ecpg_get_con_name_by_declared_name(query);
-		if (real_connection_name == NULL)
-		{
-			/*
-			 * If can't get the connection name by declared name then using connection name
-			 * coming from the parameter connection_name
-			 */
-			real_connection_name = connection_name;
-		 }
-	}
-
 	va_start(args, query);
-	ret = ecpg_do(lineno, compat, force_indicator, real_connection_name,
-				  questionmarks, st, query, args);
+	ret = ecpg_do(lineno, compat, force_indicator, connection_name,
+				  questionmarks, st, prepared_name, query, args);
 	va_end(args);
 
 	return ret;
@@ -2225,7 +2317,7 @@ bool
 ECPGdo_descriptor(int line, const char *connection,
 				  const char *descriptor, const char *query)
 {
-	return ECPGdo(line, ECPG_COMPAT_PGSQL, true, connection, '\0', 0, query, ECPGt_EOIT,
+	return ECPGdo(line, ECPG_COMPAT_PGSQL, true, connection, '\0', ECPGst_normal, NULL, query, ECPGt_EOIT,
 				  ECPGt_descriptor, descriptor, 0L, 0L, 0L,
 				  ECPGt_NO_INDICATOR, NULL, 0L, 0L, 0L, ECPGt_EORT);
 }
diff --git a/src/interfaces/ecpg/ecpglib/prepare.c b/src/interfaces/ecpg/ecpglib/prepare.c
index e04312c..30def76 100644
--- a/src/interfaces/ecpg/ecpglib/prepare.c
+++ b/src/interfaces/ecpg/ecpglib/prepare.c
@@ -56,6 +56,60 @@ isvarchar(unsigned char c)
 	return false;
 }
 
+bool
+ecpg_register_prepared_stmt(struct statement *stmt)
+{
+	struct statement *prep_stmt;
+	struct prepared_statement *this;
+	struct connection *con = NULL;
+	struct prepared_statement *prev = NULL;
+	char *real_connection_name;
+	int lineno = stmt->lineno;
+
+    real_connection_name = ecpg_get_con_name_by_declared_name(stmt->name);
+    if (real_connection_name == NULL)
+        real_connection_name = stmt->connection->name;
+
+	con = ecpg_get_connection(real_connection_name);
+	if (!ecpg_init(con, real_connection_name, stmt->lineno))
+		return false;
+
+	/* check if we already have prepared this statement */
+	this = ecpg_find_prepared_statement(stmt->name, con, &prev);
+	if (this && !deallocate_one(lineno, ECPG_COMPAT_PGSQL, con, prev, this))
+		return false;
+
+	/* allocate new statement */
+	this = (struct prepared_statement *) ecpg_alloc(sizeof(struct prepared_statement), lineno);
+	if (!this)
+		return false;
+
+	prep_stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno);
+	if (!stmt)
+	{
+		ecpg_free(this);
+		return false;
+	}
+	memset(prep_stmt, 0, sizeof(struct statement));
+
+	/* create statement */
+	prep_stmt->lineno = lineno;
+	prep_stmt->connection = con;
+	prep_stmt->command = ecpg_strdup(stmt->command, lineno);
+	prep_stmt->inlist = prep_stmt->outlist = NULL;
+	this->name = ecpg_strdup(stmt->name, lineno);
+	this->stmt = prep_stmt;
+	this->prepared = true;
+
+	if (con->prep_stmts == NULL)
+		this->next = NULL;
+	else
+		this->next = con->prep_stmts;
+
+	con->prep_stmts = this;
+	return true;
+}
+
 static bool
 replace_variables(char **text, int lineno)
 {
diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h
index 1edf272..77c2980 100644
--- a/src/interfaces/ecpg/include/ecpglib.h
+++ b/src/interfaces/ecpg/include/ecpglib.h
@@ -49,7 +49,7 @@ bool		ECPGstatus(int, const char *);
 bool		ECPGsetcommit(int, const char *, const char *);
 bool		ECPGsetconn(int, const char *);
 bool		ECPGconnect(int, int, const char *, const char *, const char *, const char *, int);
-bool		ECPGdo(const int, const int, const int, const char *, const bool, const int, const char *,...);
+bool		ECPGdo(const int, const int, const int, const char *, const bool, const int, const char *, const char *,...);
 bool		ECPGtrans(int, const char *, const char *);
 bool		ECPGdisconnect(int, const char *);
 bool		ECPGprepare(int, const char *, const bool, const char *, const char *);
diff --git a/src/interfaces/ecpg/include/ecpgtype.h b/src/interfaces/ecpg/include/ecpgtype.h
index 4a7e8e7..56cb996 100644
--- a/src/interfaces/ecpg/include/ecpgtype.h
+++ b/src/interfaces/ecpg/include/ecpgtype.h
@@ -96,8 +96,10 @@ enum ECPG_statement_type
 {
 	ECPGst_normal,
 	ECPGst_execute,
+	ECPGst_execnormal,
 	ECPGst_exec_immediate,
-	ECPGst_prepnormal
+	ECPGst_prepnormal,
+	ECPGst_prepare
 };
 
 enum ECPG_cursor_statement_type
diff --git a/src/interfaces/ecpg/preproc/ecpg.addons b/src/interfaces/ecpg/preproc/ecpg.addons
index e805281..d1b3484 100644
--- a/src/interfaces/ecpg/preproc/ecpg.addons
+++ b/src/interfaces/ecpg/preproc/ecpg.addons
@@ -20,13 +20,18 @@ ECPG: stmtSelectStmt block
 ECPG: stmtUpdateStmt block
 	{ output_statement($1, 1, ECPGst_prepnormal); }
 ECPG: stmtExecuteStmt block
-	{ output_statement($1, 1, ECPGst_execute); }
-ECPG: stmtPrepareStmt block
 	{
 		if ($1.type == NULL || strlen($1.type) == 0)
+			output_statement($1.name, 1, ECPGst_execute);
+		else
+			output_execute_stmt($1.stmt, 1, $1.name);
+	}
+ECPG: stmtPrepareStmt block
+	{
+		if ($1.type == NULL)
 			output_prepare_statement($1.name, $1.stmt);
 		else
-			output_statement(cat_str(5, mm_strdup("prepare"), $1.name, $1.type, mm_strdup("as"), $1.stmt), 0, ECPGst_normal);
+			output_prepare_stmt(cat_str(5, mm_strdup("prepare"), mm_strdup($1.name), $1.type, mm_strdup("as"), $1.stmt), 0, $1.name);
 	}
 ECPG: stmtTransactionStmt block
 	{
@@ -280,7 +285,7 @@ ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block
 	{
 		$$.name = $2;
 		$$.type = $3;
-		$$.stmt = cat_str(3, mm_strdup("\""), $5, mm_strdup("\""));
+		$$.stmt = $5;
 	}
 	| PREPARE prepared_name FROM execstring
 	{
@@ -289,7 +294,27 @@ ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block
 		$$.stmt = $4;
 	}
 ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block
-	{ $$ = $2; }
+	{
+		$$.name = mm_strdup($2);
+		$$.stmt = cat_str(4, mm_strdup("execute"), $2, mm_strdup($3), $4);
+		$$.type = $3;
+	}
+ECPG: ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEnameexecute_param_clauseopt_with_data block
+	{
+		$$.name = cat_str(8,mm_strdup("create"),$2,mm_strdup("table"),$4,mm_strdup("as execute"),$7,$8,$9);
+		$$.stmt = NULL;
+		$$.type = NULL;
+	}
+ECPG: ExecuteStmtCREATEOptTempTABLEIF_PNOTEXISTScreate_as_targetASEXECUTEnameexecute_param_clauseopt_with_data block
+	{
+		$$.name = cat_str(8,mm_strdup("create"),$2,mm_strdup("table if not exists"),$7,mm_strdup("as execute"),$10,$11,$12);
+		$$.stmt = NULL;
+		$$.type = NULL;
+	}
+ECPG: ExplainableStmtExecuteStmt block
+	{
+		$$ = $1.stmt;
+	}
 ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectStmt block
 	{
 		struct cursor *ptr, *this;
diff --git a/src/interfaces/ecpg/preproc/ecpg.header b/src/interfaces/ecpg/preproc/ecpg.header
index 366dc23..18b7bec 100644
--- a/src/interfaces/ecpg/preproc/ecpg.header
+++ b/src/interfaces/ecpg/preproc/ecpg.header
@@ -593,4 +593,5 @@ add_typedef(char *name, char *dimension, char *length, enum ECPGttype type_enum,
 	struct	fetch_desc	descriptor;
 	struct  su_symbol	struct_union;
 	struct	prep		prep;
+	struct	exec		exec;
 }
diff --git a/src/interfaces/ecpg/preproc/output.c b/src/interfaces/ecpg/preproc/output.c
index 6b46ae6..7d364bb 100644
--- a/src/interfaces/ecpg/preproc/output.c
+++ b/src/interfaces/ecpg/preproc/output.c
@@ -127,28 +127,26 @@ hashline_number(void)
 static char *ecpg_statement_type_name[] = {
 	"ECPGst_normal",
 	"ECPGst_execute",
+	"ECPGst_execnormal",
 	"ECPGst_exec_immediate",
-	"ECPGst_prepnormal"
+	"ECPGst_prepnormal",
+	"ECPGst_prepare"
 };
 
-void
-output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st)
+static void
+output_stmt(char *stmt, int whenever_mode, enum ECPG_statement_type st, char *prepared_name)
 {
-	fprintf(base_yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, ", compat, force_indicator, connection ? connection : "NULL", questionmarks);
-	if (st == ECPGst_execute || st == ECPGst_exec_immediate)
-	{
-		fprintf(base_yyout, "%s, %s, ", ecpg_statement_type_name[st], stmt);
-	}
-	else
-	{
-		if (st == ECPGst_prepnormal && auto_prepare)
-			fputs("ECPGst_prepnormal, \"", base_yyout);
-		else
-			fputs("ECPGst_normal, \"", base_yyout);
+	if (st == ECPGst_prepnormal && ! auto_prepare)
+		st = ECPGst_normal;
 
-		output_escaped_str(stmt, false);
-		fputs("\", ", base_yyout);
-	}
+	if (st == ECPGst_execute)
+		prepared_name = stmt;
+
+	fprintf(base_yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, %s, %s, \"",
+		compat,force_indicator, connection ? connection : "NULL", questionmarks,
+		ecpg_statement_type_name[st], prepared_name ? prepared_name : "NULL");
+	output_escaped_str(stmt, false);
+	fputs("\", ", base_yyout);
 
 	/* dump variables to C file */
 	dump_variables(argsinsert, 1);
@@ -165,6 +163,24 @@ output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st)
 }
 
 void
+output_execute_stmt(char *stmt, int whenever_mode, char *prepared_name)
+{
+	output_stmt(stmt, whenever_mode, ECPGst_execnormal, prepared_name);
+}
+
+void
+output_prepare_stmt(char *stmt, int whenever_mode, char *prepared_name)
+{
+	output_stmt(stmt, whenever_mode, ECPGst_prepare, prepared_name);
+}
+
+void
+output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st)
+{
+	output_stmt(stmt, whenever_mode, st, NULL);
+}
+
+void
 output_prepare_statement(char *name, char *stmt)
 {
 	fprintf(base_yyout, "{ ECPGprepare(__LINE__, %s, %d, ", connection ? connection : "NULL", questionmarks);
diff --git a/src/interfaces/ecpg/preproc/parse.pl b/src/interfaces/ecpg/preproc/parse.pl
index 6f67a5e..76c4dfa 100644
--- a/src/interfaces/ecpg/preproc/parse.pl
+++ b/src/interfaces/ecpg/preproc/parse.pl
@@ -58,6 +58,7 @@ my %replace_string = (
 # ECPG-only replace_types are defined in ecpg-replace_types
 my %replace_types = (
 	'PrepareStmt'      => '<prep>',
+	'ExecuteStmt'      => '<exec>',
 	'opt_array_bounds' => '<index>',
 
 	# "ignore" means: do not create type and rules for this non-term-id
diff --git a/src/interfaces/ecpg/preproc/preproc_extern.h b/src/interfaces/ecpg/preproc/preproc_extern.h
index 8ccfdf0..834fa24 100644
--- a/src/interfaces/ecpg/preproc/preproc_extern.h
+++ b/src/interfaces/ecpg/preproc/preproc_extern.h
@@ -67,6 +67,8 @@ extern const uint16 SQLScanKeywordTokens[];
 extern const char *get_dtype(enum ECPGdtype);
 extern void lex_init(void);
 extern void output_line_number(void);
+extern void output_execute_stmt(char *, int, char *);
+extern void output_prepare_stmt(char *, int, char *);
 extern void output_statement(char *, int, enum ECPG_statement_type);
 extern void output_prepare_statement(char *, char *);
 extern void output_deallocate_prepare_statement(char *);
diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h
index 94377ff..e913f05 100644
--- a/src/interfaces/ecpg/preproc/type.h
+++ b/src/interfaces/ecpg/preproc/type.h
@@ -106,6 +106,13 @@ struct prep
 	char	   *type;
 };
 
+struct exec
+{
+	char	   *name;
+	char	   *stmt;
+	char	   *type;
+};
+
 struct this_type
 {
 	enum ECPGttype type_enum;
