diff --git a/src/interfaces/ecpg/preproc/ecpg.addons b/src/interfaces/ecpg/preproc/ecpg.addons
index 1c610f3dd56f423c86249517ee6750947167b2c5..f7a68f69f138fd673064954203b93db09ec6c14a 100644
--- a/src/interfaces/ecpg/preproc/ecpg.addons
+++ b/src/interfaces/ecpg/preproc/ecpg.addons
@@ -1,5 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.8 2009/11/11 20:31:26 alvherre Exp $ */
-
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.9 2009/11/26 15:06:47 meskes Exp $ */
 ECPG: stmtClosePortalStmt block
 	{
 		if (INFORMIX_MODE)
@@ -213,18 +212,36 @@ ECPG: var_valueNumericOnly addon
 		}
 ECPG: fetch_argscursor_name addon
 		add_additional_variables($1, false);
+		if ($1[0] == ':')
+		{
+			free($1);
+			$1 = make_str("$0");
+		}
 ECPG: fetch_argsfrom_incursor_name addon
 		add_additional_variables($2, false);
+		if ($2[0] == ':')
+		{
+			free($2);
+			$2 = make_str("$0");
+		}
 ECPG: fetch_argsNEXTopt_from_incursor_name addon
 ECPG: fetch_argsPRIORopt_from_incursor_name addon
 ECPG: fetch_argsFIRST_Popt_from_incursor_name addon
 ECPG: fetch_argsLAST_Popt_from_incursor_name addon
 ECPG: fetch_argsALLopt_from_incursor_name addon
-ECPG: fetch_argsFORWARDopt_from_incursor_name addon
-ECPG: fetch_argsBACKWARDopt_from_incursor_name addon
 		add_additional_variables($3, false);
+		if ($3[0] == ':')
+		{
+			free($3);
+			$3 = make_str("$0");
+		}
 ECPG: fetch_argsSignedIconstopt_from_incursor_name addon
 		add_additional_variables($3, false);
+		if ($3[0] == ':')
+		{
+			free($3);
+			$3 = make_str("$0");
+		}
 		if ($1[0] == '$')
 		{
 			free($1);
@@ -233,16 +250,35 @@ ECPG: fetch_argsSignedIconstopt_from_incursor_name addon
 ECPG: fetch_argsFORWARDALLopt_from_incursor_name addon
 ECPG: fetch_argsBACKWARDALLopt_from_incursor_name addon
 		add_additional_variables($4, false);
+		if ($4[0] == ':')
+		{
+			free($4);
+			$4 = make_str("$0");
+		}
 ECPG: fetch_argsABSOLUTE_PSignedIconstopt_from_incursor_name addon
 ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_incursor_name addon
 ECPG: fetch_argsFORWARDSignedIconstopt_from_incursor_name addon
 ECPG: fetch_argsBACKWARDSignedIconstopt_from_incursor_name addon
 		add_additional_variables($4, false);
+		if ($4[0] == ':')
+		{
+			free($4);
+			$4 = make_str("$0");
+		}
 		if ($2[0] == '$')
 		{
 			free($2);
 			$2 = make_str("$0");
 		}
+ECPG: cursor_namename rule
+	| char_civar
+		{
+			char *curname = mm_alloc(strlen($1) + 2);
+			sprintf(curname, ":%s", $1);
+			free($1);
+			$1 = curname;
+			$$ = $1;
+		}
 ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block
 	{
 		$$.name = $2;
@@ -260,6 +296,7 @@ ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block
 ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectStmt block
 	{
 		struct cursor *ptr, *this;
+		char *cursor_marker = $2[0] == ':' ? make_str("$0") : mm_strdup($2);
 		char *comment;
 
 		for (ptr = cur; ptr != NULL; ptr = ptr->next)
@@ -274,7 +311,7 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt
 		this->name = $2;
 		this->connection = connection;
 		this->opened = false;
-		this->command =  cat_str(7, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for"), $7);
+		this->command =  cat_str(7, make_str("declare"), cursor_marker, $3, make_str("cursor"), $5, make_str("for"), $7);
 		this->argsinsert = argsinsert;
 		this->argsresult = argsresult;
 		argsinsert = argsresult = NULL;
@@ -294,6 +331,11 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt
 		else
 			$$ = comment;
 	}
+ECPG: ClosePortalStmtCLOSEcursor_name block
+	{
+		char *cursor_marker = $2[0] == ':' ? make_str("$0") : $2;
+		$$ = cat2_str(make_str("close"), cursor_marker);
+	}
 ECPG: opt_hold block
 	{
 		if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit == true)
@@ -363,6 +405,54 @@ ECPG: FetchStmtMOVEfetch_args rule
 	{
 		$$ = cat2_str(make_str("fetch"), $2);
 	}
+	| FETCH FORWARD cursor_name opt_ecpg_into
+	{
+		char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
+		add_additional_variables($3, false);
+		$$ = cat_str(2, make_str("fetch forward"), cursor_marker);
+	}
+	| FETCH FORWARD from_in cursor_name opt_ecpg_into
+	{
+		char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
+		add_additional_variables($4, false);
+		$$ = cat_str(2, make_str("fetch forward from"), cursor_marker);
+	}
+	| FETCH BACKWARD cursor_name opt_ecpg_into
+	{
+		char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
+		add_additional_variables($3, false);
+		$$ = cat_str(2, make_str("fetch backward"), cursor_marker);
+	}
+	| FETCH BACKWARD from_in cursor_name opt_ecpg_into
+	{
+		char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
+		add_additional_variables($4, false);
+		$$ = cat_str(2, make_str("fetch backward from"), cursor_marker);
+	}
+	| MOVE FORWARD cursor_name
+	{
+		char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
+		add_additional_variables($3, false);
+		$$ = cat_str(2, make_str("move forward"), cursor_marker);
+	}
+	| MOVE FORWARD from_in cursor_name
+	{
+		char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
+		add_additional_variables($4, false);
+		$$ = cat_str(2, make_str("move forward from"), cursor_marker);
+	}
+	| MOVE BACKWARD cursor_name
+	{
+		char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
+		add_additional_variables($3, false);
+		$$ = cat_str(2, make_str("move backward"), cursor_marker);
+	}
+	| MOVE BACKWARD from_in cursor_name
+	{
+		char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
+		add_additional_variables($4, false);
+		$$ = cat_str(2, make_str("move backward from"), cursor_marker);
+	}
 ECPG: select_limitLIMITselect_limit_value','select_offset_value block
         {
                 mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to server");
diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer
index c18844a208f9ff0b3b0ae9bd046802ffbac9c857..e5f50c915e76a0f384dfd8965272bdda7d3afee9 100644
--- a/src/interfaces/ecpg/preproc/ecpg.trailer
+++ b/src/interfaces/ecpg/preproc/ecpg.trailer
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.15 2009/11/21 05:44:05 tgl Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.16 2009/11/26 15:06:47 meskes Exp $ */
 
 statements: /*EMPTY*/
                 | statements statement
@@ -278,6 +278,7 @@ prepared_name: name             {
 ECPGCursorStmt:  DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_name
 		{
 			struct cursor *ptr, *this;
+			char *cursor_marker = $2[0] == ':' ? make_str("$0") : mm_strdup($2);
 			struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
 			const char *con = connection ? connection : "NULL";
 
@@ -294,7 +295,7 @@ ECPGCursorStmt:  DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared
 			this->next = cur;
 			this->name = $2;
 			this->connection = connection;
-			this->command =  cat_str(6, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for $1"));
+			this->command =  cat_str(6, make_str("declare"), cursor_marker, $3, make_str("cursor"), $5, make_str("for $1"));
 			this->argsresult = NULL;
 
 			thisquery->type = &ecpg_query;
@@ -304,6 +305,12 @@ ECPGCursorStmt:  DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared
 			sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7);
 
 			this->argsinsert = NULL;
+			if ($2[0] == ':')
+			{
+				struct variable *var = find_variable($2 + 1);
+				remove_variable_from_list(&argsinsert, var);
+				add_variable_to_head(&(this->argsinsert), var, &no_indicator);
+			}
 			add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
 
 			cur = this;
@@ -947,7 +954,13 @@ ECPGFree:	SQL_FREE name	{ $$ = $2; }
 /*
  * open is an open cursor, at the moment this has to be removed
  */
-ECPGOpen: SQL_OPEN cursor_name opt_ecpg_using { $$ = $2; };
+ECPGOpen: SQL_OPEN cursor_name opt_ecpg_using
+		{
+			if ($2[0] == ':')
+				remove_variable_from_list(&argsinsert, find_variable($2 + 1));
+			$$ = $2;
+		}
+		;
 
 opt_ecpg_using: /*EMPTY*/	{ $$ = EMPTY; }
 		| ecpg_using		{ $$ = $1; }
@@ -1567,6 +1580,17 @@ civarind: cvariable indicator
 		}
 		;
 
+char_civar: char_variable
+		{
+			char *ptr = strstr($1, ".arr");
+
+			if (ptr) /* varchar, we need the struct name here, not the struct element */
+				*ptr = '\0';
+			add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
+			$$ = $1;
+		}
+		;
+
 civar: cvariable
 		{
 			add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
@@ -1782,6 +1806,10 @@ ecpg_into: INTO into_list	{ $$ = EMPTY; }
         | into_descriptor	{ $$ = $1; }
 	;
 
+opt_ecpg_into:	/* EMPTY */	{ $$ = EMPTY; }
+	| ecpg_into		{ $$ = $1; }
+	;
+
 %%
 
 void base_yyerror(const char *error)
diff --git a/src/interfaces/ecpg/preproc/ecpg.type b/src/interfaces/ecpg/preproc/ecpg.type
index 7ca55918270f1e1a90b7daf336d20acf8fb92119..58f410d80dcce4a9fb219ee36bb06d0fc7d35cd4 100644
--- a/src/interfaces/ecpg/preproc/ecpg.type
+++ b/src/interfaces/ecpg/preproc/ecpg.type
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.type,v 1.3 2009/11/21 05:44:05 tgl Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.type,v 1.4 2009/11/26 15:06:47 meskes Exp $ */
 %type <str> ECPGAllocateDescr
 %type <str> ECPGCKeywords
 %type <str> ECPGColId
@@ -42,6 +42,7 @@
 %type <str> c_term
 %type <str> c_thing
 %type <str> char_variable
+%type <str> char_civar
 %type <str> civar
 %type <str> civarind
 %type <str> ColId
@@ -75,6 +76,7 @@
 %type <str> opt_bit_field
 %type <str> opt_connection_name
 %type <str> opt_database_name
+%type <str> opt_ecpg_into
 %type <str> opt_ecpg_using
 %type <str> opt_initializer
 %type <str> opt_options
diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h
index 9643ab240669fdfbf57249119b6913fa937f1f74..8b740f1744a0d7390cdc15c9f2246826859225a9 100644
--- a/src/interfaces/ecpg/preproc/extern.h
+++ b/src/interfaces/ecpg/preproc/extern.h
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.75 2009/09/08 04:25:00 tgl Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.76 2009/11/26 15:06:47 meskes Exp $ */
 
 #ifndef _ECPG_PREPROC_EXTERN_H
 #define _ECPG_PREPROC_EXTERN_H
@@ -90,6 +90,7 @@ extern struct descriptor *lookup_descriptor(char *, char *);
 extern struct variable *descriptor_variable(const char *name, int input);
 extern void add_variable_to_head(struct arguments **, struct variable *, struct variable *);
 extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *);
+extern void remove_variable_from_list(struct arguments ** list, struct variable * var);
 extern void dump_variables(struct arguments *, int);
 extern struct typedefs *get_typedef(char *);
 extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int, bool);
diff --git a/src/interfaces/ecpg/preproc/parse.pl b/src/interfaces/ecpg/preproc/parse.pl
index 8d2bc450b1270ffbb94bc65de70cef6deab95504..e0615d577cfaa5d7192bf962c2ac7f002d06ea6b 100644
--- a/src/interfaces/ecpg/preproc/parse.pl
+++ b/src/interfaces/ecpg/preproc/parse.pl
@@ -1,5 +1,5 @@
 #!/usr/bin/perl
-# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/parse.pl,v 1.5 2009/11/21 05:44:05 tgl Exp $
+# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/parse.pl,v 1.6 2009/11/26 15:06:47 meskes Exp $
 # parser generater for ecpg
 # call with backend parser as stdin
 #
@@ -74,7 +74,8 @@ $replace_line{'reserved_keywordTO'} = 'ignore';
 $replace_line{'reserved_keywordUNION'} = 'ignore';
 
 # some other production rules have to be ignored or replaced
-$replace_line{'fetch_direction'} = 'ignore';
+$replace_line{'fetch_argsFORWARDopt_from_incursor_name'} = 'ignore';
+$replace_line{'fetch_argsBACKWARDopt_from_incursor_name'} = 'ignore';
 $replace_line{"opt_array_boundsopt_array_bounds'['Iconst']'"} = 'ignore';
 $replace_line{'VariableShowStmtSHOWvar_name'} = 'SHOW var_name ecpg_into';
 $replace_line{'VariableShowStmtSHOWTIMEZONE'} = 'SHOW TIME ZONE ecpg_into';
diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.c
index 9d29f340b6360ef26859ce9b02d329144405d7e3..ce3b950621984bb52ed3b4e747ebe4c664714e18 100644
--- a/src/interfaces/ecpg/preproc/variable.c
+++ b/src/interfaces/ecpg/preproc/variable.c
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/variable.c,v 1.50 2009/08/07 10:51:20 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/variable.c,v 1.51 2009/11/26 15:06:47 meskes Exp $ */
 
 #include "postgres_fe.h"
 
@@ -401,6 +401,30 @@ add_variable_to_tail(struct arguments ** list, struct variable * var, struct var
 		*list = new;
 }
 
+void
+remove_variable_from_list(struct arguments ** list, struct variable * var)
+{
+	struct arguments *p, *prev = NULL;
+	bool found = false;
+
+	for (p = *list; p; p = p->next)
+	{
+		if (p->variable == var)
+		{
+			found = true;
+			break;
+		}
+		prev = p;
+	}
+	if (found)
+	{
+		if (prev)
+			prev->next = p->next;
+		else
+			*list = p->next;
+	}
+}
+
 /* Dump out a list of all the variable on this list.
    This is a recursive function that works from the end of the list and
    deletes the list as we go on.
diff --git a/src/interfaces/ecpg/test/ecpg_schedule b/src/interfaces/ecpg/test/ecpg_schedule
index 14fcd41a4640591c9926cb532301e8027803c091..a9245be1fd15d72e3be68b4c8a87e5b9703f54ea 100644
--- a/src/interfaces/ecpg/test/ecpg_schedule
+++ b/src/interfaces/ecpg/test/ecpg_schedule
@@ -16,6 +16,7 @@ test: pgtypeslib/num_test2
 test: preproc/array_of_struct
 test: preproc/autoprep
 test: preproc/comment
+test: preproc/cursor
 test: preproc/define
 test: preproc/init
 test: preproc/strings
diff --git a/src/interfaces/ecpg/test/ecpg_schedule_tcp b/src/interfaces/ecpg/test/ecpg_schedule_tcp
index 814347324439c772371458f87052aaca17955347..917c590c8cbc997d087d0afbb174a6d1581af988 100644
--- a/src/interfaces/ecpg/test/ecpg_schedule_tcp
+++ b/src/interfaces/ecpg/test/ecpg_schedule_tcp
@@ -16,6 +16,7 @@ test: pgtypeslib/num_test2
 test: preproc/array_of_struct
 test: preproc/autoprep
 test: preproc/comment
+test: preproc/cursor
 test: preproc/define
 test: preproc/init
 test: preproc/strings
diff --git a/src/interfaces/ecpg/test/preproc/Makefile b/src/interfaces/ecpg/test/preproc/Makefile
index 94b6779a417c13f02786313993224d308de088f0..ed3243214e84c37325dcfce279fe1abbbb45bdf8 100644
--- a/src/interfaces/ecpg/test/preproc/Makefile
+++ b/src/interfaces/ecpg/test/preproc/Makefile
@@ -7,6 +7,7 @@ include $(top_srcdir)/$(subdir)/../Makefile.regress
 TESTS = array_of_struct array_of_struct.c \
 	autoprep autoprep.c \
 	comment comment.c \
+	cursor cursor.c \
 	define define.c \
 	init init.c \
 	strings strings.c \