diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index 4394b42..1f53deb 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -33,6 +33,8 @@
 #include "pgtypes_timestamp.h"
 #include "pgtypes_interval.h"
 
+#define MAXLEN_INT_IN_TEXTFORMAT (sizeof(int) * CHAR_BIT * 3 / 10)
+
 /*
  *	This function returns a newly malloced string that has ' and \
  *	escaped.
@@ -112,7 +114,7 @@ free_statement(struct statement *stmt)
 }
 
 static int
-next_insert(char *text, int pos, bool questionmarks, bool std_strings)
+next_insert(char *text, int pos, bool questionmarks, bool std_strings, int *replace_len_p)
 {
 	bool		string = false;
 	int			p = pos;
@@ -134,12 +136,18 @@ next_insert(char *text, int pos, bool questionmarks, bool std_strings)
 					 /* empty loop body */ ;
 				if (!isalpha((unsigned char) text[i]) &&
 					isascii((unsigned char) text[i]) &&text[i] != '_')
+				{
 					/* not dollar delimited quote */
+					if (replace_len_p)
+						*replace_len_p = i - p;
 					return p;
+				}
 			}
 			else if (questionmarks && text[p] == '?')
 			{
 				/* also allow old style placeholders */
+				if (replace_len_p)
+					*replace_len_p = 1;
 				return p;
 			}
 		}
@@ -1130,34 +1138,59 @@ ecpg_free_params(struct statement *stmt, bool print)
 }
 
 static bool
-insert_tobeinserted(int position, int ph_len, struct statement *stmt, char *tobeinserted)
+expand_exprlist(struct statement *stmt, int pos, int num)
+{
+	char	   *newcopy;
+	int			newsize;
+	int			c;
+	static const int param_len = 1 /* $ */ + MAXLEN_INT_IN_TEXTFORMAT;
+
+	newsize = strlen(stmt->command) + param_len + 1 /* null terminate */;
+
+	if (num == 1)
+		/* 1st calling. Create expression list */
+		newsize += 2;	/* for two parentheses */
+	else
+		newsize += 1;	/* for comma */
+
+	if (!(newcopy = (char *) ecpg_alloc(newsize, stmt->lineno)))
+		return false;
+
+	strncpy(newcopy, stmt->command, newsize);
+
+	if (num == 1)
+		c = snprintf(newcopy + pos, newsize, "($%d)", num);
+	else
+		c = snprintf(newcopy + pos, newsize, ",$%d", num);
+
+	strncat(newcopy + pos + c, stmt->command + pos, newsize);
+	stmt->command = newcopy;
+
+	return true;
+}
+
+static bool
+replace_parameter(int position, int tobereplaced, struct statement *stmt, char *replacer)
 {
 	char	   *newcopy;
 
 	if (!(newcopy = (char *) ecpg_alloc(strlen(stmt->command)
-										+ strlen(tobeinserted)
+										+ strlen(replacer)
 										+ 1, stmt->lineno)))
-	{
-		ecpg_free(tobeinserted);
 		return false;
-	}
 
 	strcpy(newcopy, stmt->command);
-	strcpy(newcopy + position - 1, tobeinserted);
+	strcpy(newcopy + position, replacer);
 
 	/*
 	 * The strange thing in the second argument is the rest of the string from
 	 * the old string
 	 */
-	strcat(newcopy,
-		   stmt->command
-		   + position
-		   + ph_len - 1);
+	strcat(newcopy, stmt->command + position + tobereplaced);
 
 	ecpg_free(stmt->command);
 	stmt->command = newcopy;
 
-	ecpg_free(tobeinserted);
 	return true;
 }
 
@@ -1220,9 +1253,11 @@ ecpg_build_params(struct statement *stmt)
 {
 	struct variable *var;
 	int			desc_counter = 0;
-	int			position = 0;
+	int			next_search_pos = 0;
+	int			param_num = 1;
 	const char *value;
 	bool		std_strings = false;
+	int			replacee_pos;
 
 	/* Get standard_conforming_strings setting. */
 	value = PQparameterStatus(stmt->connection->connection, "standard_conforming_strings");
@@ -1241,6 +1276,10 @@ ecpg_build_params(struct statement *stmt)
 		int			counter = 1;
 		bool		binary_format;
 		int			binary_length;
+		char	   *replacer;
+		int			replacer_len;
+		int		    bytes_tobereplaced;
+		bool		set_to_param = true;
 
 
 		tobeinserted = NULL;
@@ -1410,15 +1449,52 @@ ecpg_build_params(struct statement *stmt)
 		}
 
 		/*
-		 * now tobeinserted points to an area that contains the next
-		 * parameter; now find the position in the string where it belongs
+		 * When ECPGst_exec_embedded_in_other_stmt, we create parameter list in query and
+		 * replace them with value of the var incrementally.
+		 * In this case, $0 as prepared statement name has always appeared at first.
+		 * Therefore, if next_search_pos is not initial value, it's pointing to
+		 * the next byte of prepared statement name that is position for creating
+		 * parameter list, or pointing to position for expanding.
 		 */
-		if ((position = next_insert(stmt->command, position, stmt->questionmarks, std_strings) + 1) == 0)
+		if (next_search_pos != 0 && stmt->statement_type == ECPGst_exec_embedded_in_other_stmt)
+		{
+			if (!expand_exprlist(stmt, next_search_pos, param_num))
+			{
+				ecpg_free_params(stmt, false);
+				ecpg_free(tobeinserted);
+				return false;
+			}
+			++param_num;
+		}
+
+		/*
+		 * Find parameter in query and do the followings:
+		 *
+		 * 1. Check whether we must replace the parameter.
+		 * - $0: It is a special parameter cursor name or statement name because
+		 *       backend cannot accept parameterized cursor name.
+		 * - $1: It is a special parameter query for cursor because backend cannot
+		 *       accept parameterized query for cursor.
+		 *       It can be distinguished by var->type == ECPGt_char_variable.
+		 * - ? : It is a simple parameter in old style. We should replace it new style
+		 *       '$[0-9]*' and fall through.
+		 * - $[0-9]*:
+		 *       It is a simple parameter in new style, but we should replace it
+		 *       because we cannot send the value of parameter with PQexecParams
+		 *       in case of ECPGst_exec_with_exprlist and ECPGst_exec_embedded_in_other_stmt.
+		 *
+		 * 2. Otherwise
+		 * - $[0-9]*:
+		 *       Set value of the var to params.
+		 */
+		replacee_pos = next_insert(stmt->command, next_search_pos, stmt->questionmarks,
+								   std_strings, &bytes_tobereplaced);
+
+		/*
+		 * There is no paremeter for replacing.
+		 */ 
+		if (replacee_pos == -1)
 		{
-			/*
-			 * We have an argument but we don't have the matched up
-			 * placeholder in the string
-			 */
 			ecpg_raise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS,
 					   ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS,
 					   NULL);
@@ -1427,80 +1503,86 @@ ecpg_build_params(struct statement *stmt)
 			return false;
 		}
 
-		/*
-		 * if var->type=ECPGt_char_variable we have a dynamic cursor we have
-		 * to simulate a dynamic cursor because there is no backend
-		 * functionality for it
-		 */
-		if (var->type == ECPGt_char_variable)
+		set_to_param = true;
+		replacer = NULL;
+		if (strcmp(stmt->command + replacee_pos, "$0") == 0)
 		{
-			int			ph_len = (stmt->command[position] == '?') ? strlen("?") : strlen("$1");
-
-			if (!insert_tobeinserted(position, ph_len, stmt, tobeinserted))
-			{
-				ecpg_free_params(stmt, false);
-				return false;
-			}
-			tobeinserted = NULL;
+			set_to_param = false;
+			replacer_len = strlen(tobeinserted);
+			replacer = tobeinserted;
 		}
-
-		/*
-		 * if the placeholder is '$0' we have to replace it on the client side
-		 * this is for places we want to support variables at that are not
-		 * supported in the backend
-		 */
-		else if (stmt->command[position] == '0')
+		else if (strcmp(stmt->command + replacee_pos, "$1") == 0 &&
+				 var->type == ECPGt_char_variable)
 		{
-			if (stmt->statement_type == ECPGst_prepare ||
-				stmt->statement_type == ECPGst_exec_with_exprlist)
-			{
-				/* Need to double-quote the inserted statement name. */
-				char	   *str = ecpg_alloc(strlen(tobeinserted) + 2 + 1,
-											 stmt->lineno);
-
-				if (!str)
-				{
-					ecpg_free(tobeinserted);
-					ecpg_free_params(stmt, false);
-					return false;
-				}
-				sprintf(str, "\"%s\"", tobeinserted);
-				ecpg_free(tobeinserted);
-				tobeinserted = str;
-			}
-
-			if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
+			set_to_param = false;
+			replacer_len = strlen(tobeinserted);
+			replacer = tobeinserted;
+		}
+		else if (stmt->command[replacee_pos] == '?')
+		{
+			set_to_param = false;
+			replacer_len = 1 + MAXLEN_INT_IN_TEXTFORMAT;	/* $[0-9]* */
+			if (!(replacer = (char *) ecpg_alloc(replacer_len + 1, stmt->lineno)))
 			{
 				ecpg_free_params(stmt, false);
+				ecpg_free(tobeinserted);
 				return false;
 			}
-			tobeinserted = NULL;
+			snprintf(replacer, replacer_len, "$%d", counter++);
 		}
-		else if (stmt->statement_type == ECPGst_exec_with_exprlist)
+
+		if (stmt->statement_type == ECPGst_exec_with_exprlist ||
+		    stmt->statement_type == ECPGst_exec_embedded_in_other_stmt)
 		{
+			set_to_param = false;
+
+			/*
+			 * tobeinerted is in binary format, but it must be in text format
+			 * for embedding to query
+			 */
 			if (binary_format)
 			{
-				char	   *p = convert_bytea_to_string(tobeinserted,
-														binary_length,
-														stmt->lineno);
+				if (replacer && replacer != tobeinserted)
+					ecpg_free(replacer);
 
-				ecpg_free(tobeinserted);
-				if (!p)
+				replacer = convert_bytea_to_string(tobeinserted,
+													binary_length,
+													stmt->lineno);
+				if (!replacer)
 				{
 					ecpg_free_params(stmt, false);
+					ecpg_free(tobeinserted);
 					return false;
 				}
-				tobeinserted = p;
 			}
+			else
+				replacer = tobeinserted;
+
+			replacer_len = strlen(replacer);
+		}
 
-			if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
+		if (replacer)
+		{
+			if (!replace_parameter(replacee_pos, bytes_tobereplaced, stmt, replacer))
 			{
+				if (replacer != tobeinserted)
+					ecpg_free(replacer);
 				ecpg_free_params(stmt, false);
+				ecpg_free(tobeinserted);
 				return false;
 			}
-			tobeinserted = NULL;
+			if (replacer != tobeinserted)
+				ecpg_free(replacer);
+
+			next_search_pos = replacee_pos + replacer_len;
 		}
 		else
+			next_search_pos = replacee_pos + bytes_tobereplaced;
+
+		/*
+		 * Set value of the var to params
+		 */
+		if (set_to_param)
 		{
 			if (!(stmt->paramvalues = (char **) ecpg_realloc(stmt->paramvalues, sizeof(char *) * (stmt->nparams + 1), stmt->lineno)))
 			{
@@ -1513,6 +1595,7 @@ ecpg_build_params(struct statement *stmt)
 			if (!(stmt->paramlengths = (int *) ecpg_realloc(stmt->paramlengths, sizeof(int) * (stmt->nparams + 1), stmt->lineno)))
 			{
 				ecpg_free_params(stmt, false);
+				ecpg_free(tobeinserted);
 				return false;
 			}
 			stmt->paramlengths[stmt->nparams] = binary_length;
@@ -1520,52 +1603,31 @@ ecpg_build_params(struct statement *stmt)
 			if (!(stmt->paramformats = (int *) ecpg_realloc(stmt->paramformats, sizeof(int) * (stmt->nparams + 1), stmt->lineno)))
 			{
 				ecpg_free_params(stmt, false);
+				ecpg_free(tobeinserted);
 				return false;
 			}
 			stmt->paramformats[stmt->nparams] = (binary_format ? 1 : 0);
 			stmt->nparams++;
-
-			/* let's see if this was an old style placeholder */
-			if (stmt->command[position] == '?')
-			{
-				/* yes, replace with new style */
-				int			buffersize = sizeof(int) * CHAR_BIT * 10 / 3;	/* a rough guess of the
-																			 * size we need */
-
-				if (!(tobeinserted = (char *) ecpg_alloc(buffersize, stmt->lineno)))
-				{
-					ecpg_free_params(stmt, false);
-					return false;
-				}
-
-				snprintf(tobeinserted, buffersize, "$%d", counter++);
-
-				if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
-				{
-					ecpg_free_params(stmt, false);
-					return false;
-				}
-				tobeinserted = NULL;
-			}
 		}
 
+		tobeinserted = NULL;
+
 		if (desc_counter == 0)
 			var = var->next;
 	}
 
 	/*
-	 * Check if there are unmatched things left. PREPARE AS has no parameter.
-	 * Check other statement.
+	 * Check number of parameters and vars.
+	 * ECPGst_prepare must be excluded because it includes unreplacable parameters.
 	 */
-	if (stmt->statement_type != ECPGst_prepare &&
-		next_insert(stmt->command, position, stmt->questionmarks, std_strings) >= 0)
+	replacee_pos = next_insert(stmt->command, next_search_pos, stmt->questionmarks, std_strings, NULL);
+	if (replacee_pos != -1 && 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;
 	}
-
 	return true;
 }
 
diff --git a/src/interfaces/ecpg/include/ecpgtype.h b/src/interfaces/ecpg/include/ecpgtype.h
index cdeb43d..f40e0de 100644
--- a/src/interfaces/ecpg/include/ecpgtype.h
+++ b/src/interfaces/ecpg/include/ecpgtype.h
@@ -99,7 +99,8 @@ enum ECPG_statement_type
 	ECPGst_exec_immediate,
 	ECPGst_prepnormal,
 	ECPGst_prepare,
-	ECPGst_exec_with_exprlist
+	ECPGst_exec_with_exprlist,
+	ECPGst_exec_embedded_in_other_stmt
 };
 
 enum ECPG_cursor_statement_type
diff --git a/src/interfaces/ecpg/preproc/ecpg.addons b/src/interfaces/ecpg/preproc/ecpg.addons
index cbffd50..6087135 100644
--- a/src/interfaces/ecpg/preproc/ecpg.addons
+++ b/src/interfaces/ecpg/preproc/ecpg.addons
@@ -21,8 +21,8 @@ ECPG: stmtUpdateStmt block
 	{ output_statement($1, 1, ECPGst_prepnormal); }
 ECPG: stmtExecuteStmt block
 	{
-		if ($1.type == NULL || strlen($1.type) == 0)
-			output_statement($1.name, 1, ECPGst_execute);
+		if ($1.stmt_type == ECPGst_execute)
+			output_statement($1.name, 1, $1.stmt_type);
 		else
 		{
 			if ($1.name[0] != '"')
@@ -39,7 +39,7 @@ ECPG: stmtExecuteStmt block
 				sprintf(length, "%zu", strlen(str));
 				add_variable_to_tail(&argsinsert, new_variable(str, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator);
 			}
-			output_statement(cat_str(3, mm_strdup("execute"), mm_strdup("$0"), $1.type), 0, ECPGst_exec_with_exprlist);
+			output_statement(mm_strdup($1.stmt), 0, $1.stmt_type);
 		}
 	}
 ECPG: stmtPrepareStmt block
@@ -337,14 +337,30 @@ ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block
 	{
 		$$.name = $2;
 		$$.type = $3;
+		if (strlen($$.type) == 0)
+		{
+			$$.stmt = $$.name;
+			$$.stmt_type = ECPGst_execute;
+		}
+		else
+		{
+			$$.stmt = cat_str(3,mm_strdup("execute"),mm_strdup("$0"),mm_strdup($3));
+			$$.stmt_type = ECPGst_exec_with_exprlist;
+		}
 	}
 ECPG: ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEprepared_nameexecute_param_clauseopt_with_dataexecute_rest block
 	{
-		$$.name = cat_str(8,mm_strdup("create"),$2,mm_strdup("table"),$4,mm_strdup("as execute"),$7,$8,$9);
+		$$.name = $7;
+		$$.type = $8;
+		$$.stmt = cat_str(8,mm_strdup("create"),$2,mm_strdup("table"),$4,mm_strdup("as execute"),mm_strdup("$0"),mm_strdup($8),$9);
+		$$.stmt_type = ECPGst_exec_embedded_in_other_stmt;
 	}
 ECPG: ExecuteStmtCREATEOptTempTABLEIF_PNOTEXISTScreate_as_targetASEXECUTEprepared_nameexecute_param_clauseopt_with_dataexecute_rest block
 	{
-		$$.name = cat_str(8,mm_strdup("create"),$2,mm_strdup("table if not exists"),$7,mm_strdup("as execute"),$10,$11,$12);
+		$$.name = $10;
+		$$.type = $11;
+		$$.stmt = cat_str(8,mm_strdup("create"),$2,mm_strdup("table if not exists"),$7,mm_strdup("as execute"),mm_strdup("$0"),mm_strdup($11),$12);
+		$$.stmt_type = ECPGst_exec_embedded_in_other_stmt;
 	}
 ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectStmt block
 	{
diff --git a/src/interfaces/ecpg/preproc/output.c b/src/interfaces/ecpg/preproc/output.c
index 9419a39..bd31bb3 100644
--- a/src/interfaces/ecpg/preproc/output.c
+++ b/src/interfaces/ecpg/preproc/output.c
@@ -130,7 +130,8 @@ static char *ecpg_statement_type_name[] = {
 	"ECPGst_exec_immediate",
 	"ECPGst_prepnormal",
 	"ECPGst_prepare",
-	"ECPGst_exec_with_exprlist"
+	"ECPGst_exec_with_exprlist",
+	"ECPGst_exec_embedded_in_other_stmt"
 };
 
 void
@@ -143,8 +144,9 @@ output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st)
 
 	/*
 	 * In following cases, stmt is CSTRING or char_variable. They must be
-	 * output directly. - prepared_name of EXECUTE without exprlist -
-	 * execstring of EXECUTE IMMEDIATE
+	 * output directly.
+	 * - prepared_name of EXECUTE without exprlist
+	 * - execstring of EXECUTE IMMEDIATE
 	 */
 	fprintf(base_yyout, "%s, ", ecpg_statement_type_name[st]);
 	if (st == ECPGst_execute || st == ECPGst_exec_immediate)
diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h
index 9c1df73..90643d7 100644
--- a/src/interfaces/ecpg/preproc/type.h
+++ b/src/interfaces/ecpg/preproc/type.h
@@ -110,6 +110,8 @@ struct exec
 {
 	char	   *name;
 	char	   *type;
+	char	   *stmt;
+	enum ECPG_statement_type	stmt_type;
 };
 
 struct this_type
