diff -dcrpN pgsql.orig/src/backend/parser/gram.y pgsql-wherecurrentof/src/backend/parser/gram.y
*** pgsql.orig/src/backend/parser/gram.y	2010-07-26 10:05:46.000000000 +0200
--- pgsql-wherecurrentof/src/backend/parser/gram.y	2010-08-03 10:45:41.000000000 +0200
*************** where_clause:
*** 8201,8207 ****
  /* variant for UPDATE and DELETE */
  where_or_current_clause:
  			WHERE a_expr							{ $$ = $2; }
! 			| WHERE CURRENT_P OF name
  				{
  					CurrentOfExpr *n = makeNode(CurrentOfExpr);
  					/* cvarno is filled in by parse analysis */
--- 8201,8207 ----
  /* variant for UPDATE and DELETE */
  where_or_current_clause:
  			WHERE a_expr							{ $$ = $2; }
! 			| WHERE CURRENT_P OF cursor_name
  				{
  					CurrentOfExpr *n = makeNode(CurrentOfExpr);
  					/* cvarno is filled in by parse analysis */
diff -dcrpN pgsql.orig/src/interfaces/ecpg/ecpglib/execute.c pgsql-wherecurrentof/src/interfaces/ecpg/ecpglib/execute.c
*** pgsql.orig/src/interfaces/ecpg/ecpglib/execute.c	2010-07-11 11:15:00.000000000 +0200
--- pgsql-wherecurrentof/src/interfaces/ecpg/ecpglib/execute.c	2010-08-03 16:50:43.000000000 +0200
*************** ecpg_store_input(const int lineno, const
*** 1082,1099 ****
  	return true;
  }
  
! static void
! free_params(const char **paramValues, int nParams, bool print, int lineno)
  {
  	int			n;
  
! 	for (n = 0; n < nParams; n++)
  	{
  		if (print)
! 			ecpg_log("free_params on line %d: parameter %d = %s\n", lineno, n + 1, paramValues[n] ? paramValues[n] : "null");
! 		ecpg_free((void *) (paramValues[n]));
  	}
! 	ecpg_free(paramValues);
  }
  
  
--- 1082,1109 ----
  	return true;
  }
  
! void
! ecpg_free_params(struct statement *stmt, bool print, int lineno)
  {
  	int			n;
  
! 	for (n = 0; n < stmt->nparams; n++)
  	{
  		if (print)
! 			ecpg_log("free_params on line %d: parameter %d = %s\n", lineno, n + 1, stmt->param_values[n] ? stmt->param_values[n] : "null");
! 		ecpg_free((void *) (stmt->param_values[n]));
  	}
! 	ecpg_free(stmt->param_values);
! 
! 	stmt->nparams = 0;
! 	stmt->param_values = NULL;
! 
! 	for (n = 0; n < stmt->ndollarzero; n++)
! 		ecpg_free((void *) (stmt->dollarzero[n]));
! 	ecpg_free(stmt->dollarzero);
! 
! 	stmt->ndollarzero = 0;
! 	stmt->dollarzero = NULL;
  }
  
  
*************** insert_tobeinserted(int position, int ph
*** 1130,1135 ****
--- 1140,1203 ----
  }
  
  static bool
+ ecpg_replace_inline_params(struct statement * stmt)
+ {
+ 	struct variable *var;
+ 	int			position = 0;
+ 
+ 	/*
+ 	 * We have to check the $0 inline parameters first, they can appear
+ 	 * after $1, e.g. in this example:
+ 	 * EXEC SQL UPDATE table SET f1 = :in1 WHERE CURRENT OF :curname RETURNING id + :in2;
+ 	 * transformed statement is:
+ 	 * "update table set f1 = $1 WHERE CURRENT OF $0 RETURNING id + $2"
+ 	 */
+ 	var = stmt->inlist;
+ 	while (var)
+ 	{
+ 		char	   *tobeinserted;
+ 
+ 		tobeinserted = NULL;
+ 
+ 		if ((position = next_insert(stmt->command, position, stmt->questionmarks) + 1) == 0)
+ 			break;
+ 
+ 		/*
+ 		 * 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
+ 		 */
+ 		if (stmt->command[position] == '0')
+ 		{
+ 			const char **dollarzero;
+ 
+ 			if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, false))
+ 				return false;
+ 
+ 			if (!(dollarzero = (const char **) ecpg_realloc(stmt->dollarzero, sizeof(const char *) * (stmt->ndollarzero + 1), stmt->lineno)))
+ 			{
+ 				ecpg_free_params(stmt, false, stmt->lineno);
+ 				return false;
+ 			}
+ 			stmt->ndollarzero++;
+ 			stmt->dollarzero = dollarzero;
+ 			stmt->dollarzero[stmt->ndollarzero - 1] = strdup(tobeinserted);
+ 
+ 			if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
+ 			{
+ 				ecpg_free_params(stmt, false, stmt->lineno);
+ 				return false;
+ 			}
+ 
+ 			tobeinserted = NULL;
+ 
+ 			var = var->next;
+ 		}
+ 	}
+ 	return true;
+ }
+ 
+ static bool
  ecpg_execute(struct statement * stmt)
  {
  	bool		status = false;
*************** ecpg_execute(struct statement * stmt)
*** 1138,1155 ****
  	PGnotify   *notify;
  	struct variable *var;
  	int			desc_counter = 0;
- 	const char **paramValues = NULL;
- 	int			nParams = 0;
  	int			position = 0;
  	struct sqlca_t *sqlca = ECPGget_sqlca();
  	bool		clear_result = true;
  
  	/*
  	 * If the type is one of the fill in types then we take the argument and
  	 * enter it to our parameter array at the first position. Then if there
  	 * are any more fill in types we add more parameters.
  	 */
- 	var = stmt->inlist;
  	while (var)
  	{
  		char	   *tobeinserted;
--- 1206,1229 ----
  	PGnotify   *notify;
  	struct variable *var;
  	int			desc_counter = 0;
  	int			position = 0;
+ 	int			i;
  	struct sqlca_t *sqlca = ECPGget_sqlca();
  	bool		clear_result = true;
  
+ 	var = stmt->inlist;
+ 
+ 	/*
+ 	 * Skip the inline parameters
+ 	 */
+ 	for (i = 0; i < stmt->ndollarzero; i++)
+ 		var = var->next;
+ 
  	/*
  	 * If the type is one of the fill in types then we take the argument and
  	 * enter it to our parameter array at the first position. Then if there
  	 * are any more fill in types we add more parameters.
  	 */
  	while (var)
  	{
  		char	   *tobeinserted;
*************** ecpg_execute(struct statement * stmt)
*** 1342,1348 ****
  			ecpg_raise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS,
  					   ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS,
  					   NULL);
! 			free_params(paramValues, nParams, false, stmt->lineno);
  			return false;
  		}
  
--- 1416,1422 ----
  			ecpg_raise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS,
  					   ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS,
  					   NULL);
! 			ecpg_free_params(stmt, false, stmt->lineno);
  			return false;
  		}
  
*************** ecpg_execute(struct statement * stmt)
*** 1357,1392 ****
  
  			if (!insert_tobeinserted(position, ph_len, stmt, tobeinserted))
  			{
! 				free_params(paramValues, nParams, false, stmt->lineno);
! 				return false;
! 			}
! 			tobeinserted = NULL;
! 		}
! 
! 		/*
! 		 * 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')
! 		{
! 			if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
! 			{
! 				free_params(paramValues, nParams, false, stmt->lineno);
  				return false;
  			}
  			tobeinserted = NULL;
  		}
  		else
  		{
! 			nParams++;
! 			if (!(paramValues = (const char **) ecpg_realloc(paramValues, sizeof(const char *) * nParams, stmt->lineno)))
  			{
! 				ecpg_free(paramValues);
  				return false;
  			}
  
! 			paramValues[nParams - 1] = tobeinserted;
  
  			/* let's see if this was an old style placeholder */
  			if (stmt->command[position] == '?')
--- 1431,1455 ----
  
  			if (!insert_tobeinserted(position, ph_len, stmt, tobeinserted))
  			{
! 				ecpg_free_params(stmt, false, stmt->lineno);
  				return false;
  			}
  			tobeinserted = NULL;
  		}
  		else
  		{
! 			const char **param_values;
! 
! 			if (!(param_values = (const char **) ecpg_realloc(stmt->param_values, sizeof(const char *) * (stmt->nparams + 1), stmt->lineno)))
  			{
! 				ecpg_free_params(stmt, false, stmt->lineno);
  				return false;
  			}
  
! 			stmt->nparams++;
! 			stmt->param_values = param_values;
! 
! 			stmt->param_values[stmt->nparams - 1] = tobeinserted;
  
  			/* let's see if this was an old style placeholder */
  			if (stmt->command[position] == '?')
*************** ecpg_execute(struct statement * stmt)
*** 1397,1403 ****
  
  				if (!(tobeinserted = (char *) ecpg_alloc(buffersize, stmt->lineno)))
  				{
! 					free_params(paramValues, nParams, false, stmt->lineno);
  					return false;
  				}
  
--- 1460,1466 ----
  
  				if (!(tobeinserted = (char *) ecpg_alloc(buffersize, stmt->lineno)))
  				{
! 					ecpg_free_params(stmt, false, stmt->lineno);
  					return false;
  				}
  
*************** ecpg_execute(struct statement * stmt)
*** 1405,1411 ****
  
  				if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
  				{
! 					free_params(paramValues, nParams, false, stmt->lineno);
  					return false;
  				}
  				tobeinserted = NULL;
--- 1468,1474 ----
  
  				if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
  				{
! 					ecpg_free_params(stmt, false, stmt->lineno);
  					return false;
  				}
  				tobeinserted = NULL;
*************** ecpg_execute(struct statement * stmt)
*** 1421,1427 ****
  	{
  		ecpg_raise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS,
  				 ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
! 		free_params(paramValues, nParams, false, stmt->lineno);
  		return false;
  	}
  
--- 1484,1490 ----
  	{
  		ecpg_raise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS,
  				 ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
! 		ecpg_free_params(stmt, false, stmt->lineno);
  		return false;
  	}
  
*************** ecpg_execute(struct statement * stmt)
*** 1432,1465 ****
  		results = PQexec(stmt->connection->connection, "begin transaction");
  		if (!ecpg_check_PQresult(results, stmt->lineno, stmt->connection->connection, stmt->compat))
  		{
! 			free_params(paramValues, nParams, false, stmt->lineno);
  			return false;
  		}
  		PQclear(results);
  		stmt->connection->committed = false;
  	}
  
! 	ecpg_log("ecpg_execute on line %d: query: %s; with %d parameter(s) on connection %s\n", stmt->lineno, stmt->command, nParams, stmt->connection->name);
  	if (stmt->statement_type == ECPGst_execute)
  	{
! 		results = PQexecPrepared(stmt->connection->connection, stmt->name, nParams, paramValues, NULL, NULL, 0);
  		ecpg_log("ecpg_execute on line %d: using PQexecPrepared for \"%s\"\n", stmt->lineno, stmt->command);
  	}
  	else
  	{
! 		if (nParams == 0)
  		{
  			results = PQexec(stmt->connection->connection, stmt->command);
  			ecpg_log("ecpg_execute on line %d: using PQexec\n", stmt->lineno);
  		}
  		else
  		{
! 			results = PQexecParams(stmt->connection->connection, stmt->command, nParams, NULL, paramValues, NULL, NULL, 0);
  			ecpg_log("ecpg_execute on line %d: using PQexecParams\n", stmt->lineno);
  		}
  	}
  
! 	free_params(paramValues, nParams, true, stmt->lineno);
  
  	if (!ecpg_check_PQresult(results, stmt->lineno, stmt->connection->connection, stmt->compat))
  		return (false);
--- 1495,1528 ----
  		results = PQexec(stmt->connection->connection, "begin transaction");
  		if (!ecpg_check_PQresult(results, stmt->lineno, stmt->connection->connection, stmt->compat))
  		{
! 			ecpg_free_params(stmt, false, stmt->lineno);
  			return false;
  		}
  		PQclear(results);
  		stmt->connection->committed = false;
  	}
  
! 	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)
  	{
! 		results = PQexecPrepared(stmt->connection->connection, stmt->name, stmt->nparams, stmt->param_values, NULL, NULL, 0);
  		ecpg_log("ecpg_execute on line %d: using PQexecPrepared for \"%s\"\n", stmt->lineno, stmt->command);
  	}
  	else
  	{
! 		if (stmt->nparams == 0)
  		{
  			results = PQexec(stmt->connection->connection, stmt->command);
  			ecpg_log("ecpg_execute on line %d: using PQexec\n", stmt->lineno);
  		}
  		else
  		{
! 			results = PQexecParams(stmt->connection->connection, stmt->command, stmt->nparams, NULL, stmt->param_values, NULL, NULL, 0);
  			ecpg_log("ecpg_execute on line %d: using PQexecParams\n", stmt->lineno);
  		}
  	}
  
! 	ecpg_free_params(stmt, true, stmt->lineno);
  
  	if (!ecpg_check_PQresult(results, stmt->lineno, stmt->connection->connection, stmt->compat))
  		return (false);
*************** ECPGdo(const int lineno, const int compa
*** 1767,1816 ****
  		return false;
  	}
  
- 	/*
- 	 * If statement type is ECPGst_prepnormal we are supposed to prepare the
- 	 * statement before executing them
- 	 */
- 	if (statement_type == ECPGst_prepnormal)
- 	{
- 		if (!ecpg_auto_prepare(lineno, connection_name, compat, &prepname, query))
- 			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);
- 
- 	stmt->name = NULL;
- 
- 	if (statement_type == ECPGst_execute)
- 	{
- 		/* if we have an EXECUTE command, only the name is send */
- 		char	   *command = ecpg_prepared(stmt->command, con);
- 
- 		if (command)
- 		{
- 			stmt->name = stmt->command;
- 			stmt->command = ecpg_strdup(command, lineno);
- 		}
- 		else
- 		{
- 			ecpg_raise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, stmt->command);
- 			return (false);
- 		}
- 	}
- 
  	stmt->connection = con;
  	stmt->lineno = lineno;
  	stmt->compat = compat;
  	stmt->force_indicator = force_indicator;
  	stmt->questionmarks = questionmarks;
  	stmt->statement_type = statement_type;
  
  	list = &(stmt->inlist);
  
--- 1830,1846 ----
  		return false;
  	}
  
  	stmt->connection = con;
  	stmt->lineno = lineno;
  	stmt->compat = compat;
  	stmt->force_indicator = force_indicator;
  	stmt->questionmarks = questionmarks;
  	stmt->statement_type = statement_type;
+ 	stmt->command = ecpg_strdup(query, lineno);
+ 	stmt->nparams = 0;
+ 	stmt->param_values = NULL;
+ 	stmt->ndollarzero = 0;
+ 	stmt->dollarzero = NULL;
  
  	list = &(stmt->inlist);
  
*************** ECPGdo(const int lineno, const int compa
*** 1905,1910 ****
--- 1935,1989 ----
  
  	va_end(args);
  
+ 	/* Substitute "$0" inline parameters */
+ 	if (!ecpg_replace_inline_params(stmt))
+ 	{
+ 		setlocale(LC_NUMERIC, oldlocale);
+ 		ecpg_free(oldlocale);
+ 		return false;
+ 	}
+ 
+ 	/*
+ 	 * If statement type is ECPGst_prepnormal we are supposed to prepare the
+ 	 * statement before executing them
+ 	 */
+ 	if (stmt->statement_type == ECPGst_prepnormal)
+ 	{
+ 		if (!ecpg_auto_prepare(lineno, connection_name, compat, &prepname, stmt->command))
+ 		{
+ 			setlocale(LC_NUMERIC, oldlocale);
+ 			ecpg_free(oldlocale);
+ 			return (false);
+ 		}
+ 
+ 		/*
+ 		 * statement is now prepared, so instead of the query we have to
+ 		 * execute the name
+ 		 */
+ 		ecpg_free(stmt->command);
+ 		stmt->command = prepname;
+ 		stmt->statement_type = ECPGst_execute;
+ 	}
+ 
+ 	stmt->name = NULL;
+ 
+ 	if (stmt->statement_type == ECPGst_execute)
+ 	{
+ 		/* if we have an EXECUTE command, only the name is send */
+ 		char	   *command = ecpg_prepared(stmt->command, con);
+ 
+ 		if (command)
+ 		{
+ 			stmt->name = stmt->command;
+ 			stmt->command = ecpg_strdup(command, lineno);
+ 		}
+ 		else
+ 		{
+ 			ecpg_raise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, stmt->command);
+ 			return (false);
+ 		}
+ 	}
+ 
  	/* are we connected? */
  	if (con == NULL || con->connection == NULL)
  	{
diff -dcrpN pgsql.orig/src/interfaces/ecpg/ecpglib/extern.h pgsql-wherecurrentof/src/interfaces/ecpg/ecpglib/extern.h
*** pgsql.orig/src/interfaces/ecpg/ecpglib/extern.h	2010-05-28 08:44:14.000000000 +0200
--- pgsql-wherecurrentof/src/interfaces/ecpg/ecpglib/extern.h	2010-08-03 15:29:18.000000000 +0200
*************** struct statement
*** 60,65 ****
--- 60,69 ----
  	bool		questionmarks;
  	struct variable *inlist;
  	struct variable *outlist;
+ 	const char **dollarzero;
+ 	int		ndollarzero;
+ 	const char **param_values;
+ 	int		nparams;
  };
  
  /* structure to store prepared statements for a connection */
*************** struct prepared_statement *ecpg_find_pre
*** 156,161 ****
--- 160,166 ----
  bool ecpg_store_result(const PGresult *results, int act_field,
  				  const struct statement * stmt, struct variable * var);
  bool		ecpg_store_input(const int, const bool, const struct variable *, char **, bool);
+ void		ecpg_free_params(struct statement *, bool, int);
  
  bool		ecpg_check_PQresult(PGresult *, int, PGconn *, enum COMPAT_MODE);
  void		ecpg_raise(int line, int code, const char *sqlstate, const char *str);
diff -dcrpN pgsql.orig/src/interfaces/ecpg/preproc/ecpg.addons pgsql-wherecurrentof/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql.orig/src/interfaces/ecpg/preproc/ecpg.addons	2010-03-31 10:45:18.000000000 +0200
--- pgsql-wherecurrentof/src/interfaces/ecpg/preproc/ecpg.addons	2010-08-03 14:07:49.000000000 +0200
*************** ECPG: stmtViewStmt rule
*** 192,197 ****
--- 192,213 ----
  
  		output_simple_statement($1);
  	}
+ ECPG: DeleteStmtDELETE_PFROMrelation_expr_opt_aliasusing_clausewhere_or_current_clausereturning_clause addon
+ ECPG: UpdateStmtUPDATErelation_expr_opt_aliasSETset_clause_listfrom_clausewhere_or_current_clausereturning_clause addon
+ 		if (current_cursor_name)
+ 		{
+ 			struct variable *var = find_variable(current_cursor_name + 1);
+ 
+ 			remove_variable_from_list(&argsinsert, var);
+ 			add_variable_to_tail(&argsinsert, var, &no_indicator);
+ 			free(current_cursor_name);
+ 			current_cursor_name = NULL;
+ 		}
+ ECPG: where_or_current_clauseWHERECURRENT_POFcursor_name block
+ 		{
+ 			char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
+ 			$$ = cat_str(2,make_str("where current of"), cursor_marker);
+ 		}
  ECPG: CopyStmtCOPYopt_binaryqualified_nameopt_column_listopt_oidscopy_fromcopy_file_namecopy_delimiteropt_withcopy_options addon
  			if (strcmp($6, "to") == 0 && strcmp($7, "stdin") == 0)
  				mmerror(PARSE_ERROR, ET_ERROR, "COPY TO STDIN is not possible");
*************** ECPG: cursor_namename rule
*** 281,286 ****
--- 297,303 ----
  			sprintf(curname, ":%s", $1);
  			free($1);
  			$1 = curname;
+ 			current_cursor_name = mm_strdup(curname);
  			$$ = $1;
  		}
  ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block
diff -dcrpN pgsql.orig/src/interfaces/ecpg/preproc/ecpg.header pgsql-wherecurrentof/src/interfaces/ecpg/preproc/ecpg.header
*** pgsql.orig/src/interfaces/ecpg/preproc/ecpg.header	2010-05-28 08:44:14.000000000 +0200
--- pgsql-wherecurrentof/src/interfaces/ecpg/preproc/ecpg.header	2010-08-03 12:23:39.000000000 +0200
***************
*** 34,39 ****
--- 34,40 ----
   */
  int struct_level = 0;
  int braces_open; /* brace level counter */
+ char *current_cursor_name = NULL;
  char *current_function;
  int ecpg_internal_var = 0;
  char	*connection = NULL;
diff -dcrpN pgsql.orig/src/interfaces/ecpg/preproc/extern.h pgsql-wherecurrentof/src/interfaces/ecpg/preproc/extern.h
*** pgsql.orig/src/interfaces/ecpg/preproc/extern.h	2010-01-26 10:07:31.000000000 +0100
--- pgsql-wherecurrentof/src/interfaces/ecpg/preproc/extern.h	2010-08-03 12:24:05.000000000 +0200
*************** extern int	braces_open,
*** 29,34 ****
--- 29,35 ----
  			ecpg_internal_var,
  			regression_mode,
  			auto_prepare;
+ extern char *current_cursor_name;
  extern char *current_function;
  extern char *descriptor_index;
  extern char *descriptor_name;
