diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog
index d733e9e0df0f971869d08be0315295bb12552f30..b9384070be735225099ca1d59ebe6c6599b3e05d 100644
--- a/src/interfaces/ecpg/ChangeLog
+++ b/src/interfaces/ecpg/ChangeLog
@@ -819,5 +819,10 @@ Thu Feb 17 19:37:44 CET 2000
 
 	- Synced preproc.y with gram.y.
 	- Started to clean up preproc.y.
+
+Tue Feb 22 13:48:18 CET 2000
+
+	- Synced preproc.y with gram.y.
+	- Much more clean ups.
 	- Set library version to 3.1.0.
 	- Set ecpg version to 2.7.0.
diff --git a/src/interfaces/ecpg/TODO b/src/interfaces/ecpg/TODO
index d7546c7925e7c9b54c78b4a99a78d4df221cf1f6..84edb5a2b55674b3416c48511f7349ed73e28a96 100644
--- a/src/interfaces/ecpg/TODO
+++ b/src/interfaces/ecpg/TODO
@@ -28,6 +28,8 @@ instead of libpq so we can write backend functions using ecpg.
 
 make ECPGnumeric_lvalue more accurate by using something like ECPGdump_a_*
 
+remove space_or_nl and line_end from pgc.l
+
 Missing statements:
  - exec sql ifdef
  - SQLSTATE
diff --git a/src/interfaces/ecpg/include/ecpgerrno.h b/src/interfaces/ecpg/include/ecpgerrno.h
index 429703a29ca461bc52d44b1cc3526bc99b2b783c..2bc59f4b78521154dd4419f14b3867406577a25d 100644
--- a/src/interfaces/ecpg/include/ecpgerrno.h
+++ b/src/interfaces/ecpg/include/ecpgerrno.h
@@ -32,6 +32,8 @@
 /* dynamic SQL related */
 #define ECPG_UNKNOWN_DESCRIPTOR	-240
 #define ECPG_INVALID_DESCRIPTOR_INDEX	-241
+#define ECPG_UNKNOWN_DESCRIPTOR_ITEM	-242
+#define ECPG_VAR_NOT_NUMERIC	-243
 
 /* finally the backend error messages, they start at 400 */
 #define ECPG_PGSQL		-400
diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h
index 3cb3255c4a8d75989369dbf1c820180f974932d5..0617412a1e90552092c11bc73de6097c41123375 100644
--- a/src/interfaces/ecpg/include/ecpglib.h
+++ b/src/interfaces/ecpg/include/ecpglib.h
@@ -61,6 +61,7 @@ extern		"C"
 	bool		ECPGallocate_desc(int line,const char *name);
 	void		ECPGraise(int line, int code, const char *str);
 	bool		ECPGget_desc_header(int, char *, int *);
+	bool		ECPGget_desc(int, char *, int, ...);
 	
 
 #ifdef __cplusplus
diff --git a/src/interfaces/ecpg/include/ecpgtype.h b/src/interfaces/ecpg/include/ecpgtype.h
index 443d2cb04ec359a081f85cd5cf24175063919be1..f766d374f1b9ab4e9c2c825bc96c173b04a9b583 100644
--- a/src/interfaces/ecpg/include/ecpgtype.h
+++ b/src/interfaces/ecpg/include/ecpgtype.h
@@ -49,6 +49,26 @@ extern		"C"
 		ECPGt_EORT,				/* End of result types. */
 		ECPGt_NO_INDICATOR		/* no indicator */
 	};
+	
+	enum ECPGdtype
+	{
+		ECPGd_count,
+		ECPGd_data,
+		ECPGd_di_code,
+		ECPGd_di_precision,
+		ECPGd_indicator,
+		ECPGd_key_member,
+		ECPGd_length,
+		ECPGd_name,
+		ECPGd_nullable,
+		ECPGd_octet,
+		ECPGd_precision,
+		ECPGd_ret_length,
+		ECPGd_ret_octet,
+		ECPGd_scale,
+		ECPGd_type,
+		ECPGd_EODT,				/* End of descriptor types. */
+	};
 
 #define IS_SIMPLE_TYPE(type) ((type) >= ECPGt_char && (type) <= ECPGt_varchar2)
 
diff --git a/src/interfaces/ecpg/lib/Makefile.in b/src/interfaces/ecpg/lib/Makefile.in
index 947f9fd1a9628c614dcc1b770f1b6788cac655ce..eee0d03ba44d48d163bbbbec28f772d53b3bbb66 100644
--- a/src/interfaces/ecpg/lib/Makefile.in
+++ b/src/interfaces/ecpg/lib/Makefile.in
@@ -6,7 +6,7 @@
 # Copyright (c) 1994, Regents of the University of California
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.58 2000/02/16 16:18:05 meskes Exp $
+#    $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.59 2000/02/22 19:57:05 meskes Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -23,7 +23,7 @@ ifdef KRBVERS
 CFLAGS+= $(KRBFLAGS)
 endif
 
-OBJS= ecpglib.o typename.o
+OBJS= ecpglib.o typename.o descriptor.o
 
 SHLIB_LINK= -L../../libpq -lpq
 
diff --git a/src/interfaces/ecpg/lib/descriptor.c b/src/interfaces/ecpg/lib/descriptor.c
index 09815b2d103cc5e8fe946ed7363cd047f3030969..8169f1d2f2b8376f662d8001db31092b0262d502 100644
--- a/src/interfaces/ecpg/lib/descriptor.c
+++ b/src/interfaces/ecpg/lib/descriptor.c
@@ -10,6 +10,157 @@ ECPGget_desc_header(int lineno, char * desc_name, int *count)
 		return false;
 
 	*count = PQnfields(ECPGresult);
-	ECPGlog("ECPGget-desc_header: found %d sttributes.\n", *count);
+	ECPGlog("ECPGget_desc_header: found %d attributes.\n", *count);
 	return true;
 }	
+
+static bool
+get_int_item(int lineno, void *var, enum ECPGdtype vartype, int value)
+{
+	switch (vartype)
+     	{
+       		case ECPGt_short:
+              		*(short *)var = value;
+               		break;
+		case ECPGt_int:
+	       		*(int *)var = value;
+	  		break;
+  		case ECPGt_long:
+  			*(long *)var = value;
+	  		break;
+  		case ECPGt_unsigned_short:
+  			*(unsigned short *)var = value;
+	  		break;
+		case ECPGt_unsigned_int:
+  			*(unsigned int *)var = value;
+	  		break;
+  		case ECPGt_unsigned_long:
+  			*(unsigned long *)var = value;
+	  		break;
+  		case ECPGt_float:
+  			*(float *)var = value;
+	  		break;
+  		case ECPGt_double:
+  			*(double *)var = value;
+	  		break;
+  		default:
+  			ECPGraise(lineno, ECPG_VAR_NOT_NUMERIC, NULL);
+  			return (false);
+	}
+	
+	return(true);
+}
+
+bool
+ECPGget_desc(int lineno, char *desc_name, int index, ...)
+{
+	va_list         args;
+	PGresult 	*ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
+	enum ECPGdtype	type;
+	bool		DataButNoIndicator = false;
+	
+	va_start(args, index);
+        if (!ECPGresult)
+        	return (false);
+
+       	if (PQntuples(ECPGresult) < 1)
+       	{
+       		ECPGraise(lineno, ECPG_NOT_FOUND, NULL);
+       		return (false);
+       	}
+        
+        if (index < 1 || index >PQnfields(ECPGresult))
+        {
+                ECPGraise(lineno, ECPG_INVALID_DESCRIPTOR_INDEX, NULL);
+                return (false);
+        }
+
+	ECPGlog("ECPGget_desc: reading items for tuple %d\n", index);
+    	--index;
+    	
+    	type =  va_arg(args, enum ECPGdtype);
+    	
+    	while (type != ECPGd_EODT)
+    	{
+    		char type_str[20];
+    		long varcharsize;
+    		long offset;
+    		long arrsize;
+    		enum ECPGttype vartype;
+    		void *var;
+    		
+    		vartype = va_arg(args, enum ECPGttype);
+    		var = va_arg(args, void *);
+    		varcharsize = va_arg(args, long);
+    		arrsize = va_arg(args, long);
+		offset = va_arg(args, long);
+		
+    		switch (type)
+    		{ 
+	        	case (ECPGd_indicator):
+	        		if (!get_int_item(lineno, var, vartype, -PQgetisnull(ECPGresult, 0, index)))
+	        			return (false);
+	                 	break;
+
+	                case ECPGd_name:
+	                 	strncpy((char *)var, PQfname(ECPGresult, index), varcharsize);
+	                 	break;
+	                 	
+	                case ECPGd_nullable:
+	                	if (!get_int_item(lineno, var, vartype, 1))
+	        			return (false);
+	                	break;
+	                	
+	                case ECPGd_key_member:
+	                	if (!get_int_item(lineno, var, vartype, 0))
+	        			return (false);
+	                	break;
+	                 
+	                case ECPGd_scale:
+	                	if (!get_int_item(lineno, var, vartype, (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff))
+	        			return (false);
+		                break;
+		                 
+		        case ECPGd_precision:
+		        	if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) >> 16))
+	        			return (false);
+		                break;
+		                 
+		        case ECPGd_ret_length:
+			case ECPGd_ret_octet:
+				if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, 0, index)))
+	        			return (false);
+			 	break;
+			 	
+			case ECPGd_octet:
+				if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
+	        			return (false);
+	                        break;
+
+			case ECPGd_length:
+				if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) - VARHDRSZ))
+	        			return (false);
+				break;
+				
+                        case ECPGd_type:
+                        	if (!get_int_item(lineno, var, vartype, ECPGDynamicType(PQftype(ECPGresult, index))))
+	        			return (false);
+                        	break;
+                        	
+                        default:
+                        	snprintf(type_str, sizeof(type_str), "%d", type);
+                        	ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, type_str);
+                        	return(false);
+		}
+		
+		type =  va_arg(args, enum ECPGdtype);
+	}
+                        
+        if (DataButNoIndicator && PQgetisnull(ECPGresult, 0, index))
+        {
+               	ECPGraise(lineno, ECPG_MISSING_INDICATOR, NULL);
+               	return (false);
+        }
+
+	return (true);                	
+}
diff --git a/src/interfaces/ecpg/lib/dynamic.c b/src/interfaces/ecpg/lib/dynamic.c
index fb2f28e69c5b508742269e575589df624545d833..12aac32a4584afc80bc318a8352a4834f24ffefa 100644
--- a/src/interfaces/ecpg/lib/dynamic.c
+++ b/src/interfaces/ecpg/lib/dynamic.c
@@ -2,7 +2,7 @@
  *
  * Copyright (c) 2000, Christof Petig <christof.petig@wtal.de>
  *
- * $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/dynamic.c,v 1.4 2000/02/18 16:02:49 meskes Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/dynamic.c,v 1.5 2000/02/22 19:57:05 meskes Exp $
  */
 
 /* I borrowed the include files from ecpglib.c, maybe we don't need all of them */
@@ -198,7 +198,7 @@ bool ECPGdo_descriptor(int line,const char *connection,
 
 			/* free previous result */
 			if (i->result) PQclear(i->result);
-	    	i->result=NULL;
+		    	i->result=NULL;
 	    	
 			status=do_descriptor2(line,connection,&i->result,query);
 			
@@ -206,7 +206,8 @@ bool ECPGdo_descriptor(int line,const char *connection,
 			return (status);
 	    }
 	}
-	ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, NULL);
+	
+	ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, descriptor);
 	return false;
 }
 							
@@ -219,7 +220,7 @@ PGresult *ECPGresultByDescriptor(int line,const char *name)
 		if (!strcmp(name, i->name)) return i->result;
 	}
 	
-	ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, NULL);
+	ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, name);
 	
 	return NULL;
 } 
@@ -238,7 +239,7 @@ bool ECPGdeallocate_desc(int line,const char *name)
 			return true;
 		}
 	}
-	ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, NULL);
+	ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, name);
 	return false;
 } 
 
@@ -259,7 +260,7 @@ ECPGraise(int line, int code, const char *str)
 {
 	struct auto_mem *am;
 	       
-	sqlca.sqlcode=code;
+	sqlca.sqlcode = code;
 	switch (code)
 	{ 
 		case ECPG_NOT_FOUND: 
@@ -294,15 +295,25 @@ ECPGraise(int line, int code, const char *str)
 			
 		case ECPG_UNKNOWN_DESCRIPTOR: 
 			snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
-				"descriptor not found, line %d.", line);
+				"descriptor %s not found, line %d.", str, line);
 			break;
 			
 		case ECPG_INVALID_DESCRIPTOR_INDEX: 
 			snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
 				"descriptor index out of range, line %d.", line);
 			break;
+		
+		case ECPG_UNKNOWN_DESCRIPTOR_ITEM: 
+			snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
+				"unknown descriptor item %s, line %d.", str, line);
+			break;
+		
+		case ECPG_VAR_NOT_NUMERIC: 
+			snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
+				"variable is not a numeric type, line %d.", line);
+			break;
 			
-	    default:
+		default:
 		    	snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
 				"SQL error #%d, line %d.",code, line);
 			break;
diff --git a/src/interfaces/ecpg/lib/ecpglib.c b/src/interfaces/ecpg/lib/ecpglib.c
index 72c38e48a1862e3858b1db00e32d76b7b4867e8b..afdf93bda24eb75a9012ee795122b086a09a9808 100644
--- a/src/interfaces/ecpg/lib/ecpglib.c
+++ b/src/interfaces/ecpg/lib/ecpglib.c
@@ -190,7 +190,7 @@ ecpg_alloc(long size, int lineno)
 	if (!new)
 	{
 		ECPGlog("out of memory\n");
-		ECPGraise(ECPG_OUT_OF_MEMORY, lineno, NULL);
+		ECPGraise(lineno, ECPG_OUT_OF_MEMORY, NULL);
 		return NULL;
 	}
 
@@ -206,7 +206,7 @@ ecpg_strdup(const char *string, int lineno)
 	if (!new)
 	{
 		ECPGlog("out of memory\n");
-		ECPGraise(ECPG_OUT_OF_MEMORY, lineno, NULL);
+		ECPGraise(lineno, ECPG_OUT_OF_MEMORY, NULL);
 		return NULL;
 	}
 
@@ -634,7 +634,7 @@ ECPGexecute(struct statement * stmt)
 
 				default:
 					/* Not implemented yet */
-					ECPGraise(ECPG_UNSUPPORTED, stmt->lineno, ECPGtype_name(var->type));
+					ECPGraise(stmt->lineno, ECPG_UNSUPPORTED, ECPGtype_name(var->type));
 					return false;
 					break;
 			}
@@ -657,7 +657,7 @@ ECPGexecute(struct statement * stmt)
 			 * We have an argument but we dont have the matched up string
 			 * in the string
 			 */
-			ECPGraise(ECPG_TOO_MANY_ARGUMENTS, stmt->lineno, NULL);
+			ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, NULL);
 			return false;
 		}
 		else
@@ -694,7 +694,7 @@ ECPGexecute(struct statement * stmt)
 	/* Check if there are unmatched things left. */
 	if (next_insert(copiedquery) != NULL)
 	{
-		ECPGraise(ECPG_TOO_FEW_ARGUMENTS, stmt->lineno, NULL);
+		ECPGraise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, NULL);
 		return false;
 	}
 
@@ -742,7 +742,7 @@ ECPGexecute(struct statement * stmt)
 				{
 					ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d\n",
 							stmt->lineno, ntuples);
-					ECPGraise(ECPG_NOT_FOUND, stmt->lineno, NULL);
+					ECPGraise(stmt->lineno, ECPG_NOT_FOUND, NULL);
 					status = false;
 					break;
 				}
@@ -756,7 +756,7 @@ ECPGexecute(struct statement * stmt)
 					if (var == NULL)
 					{
 						ECPGlog("ECPGexecute line %d: Too few arguments.\n", stmt->lineno);
-						ECPGraise(ECPG_TOO_FEW_ARGUMENTS, stmt->lineno, NULL);
+						ECPGraise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, NULL);
 						return (false);
 					}
 
@@ -778,7 +778,7 @@ ECPGexecute(struct statement * stmt)
 					{
 						ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d don't fit into array of %d\n",
 								stmt->lineno, ntuples, var->arrsize);
-						ECPGraise(ECPG_TOO_MANY_MATCHES, stmt->lineno, NULL);
+						ECPGraise(stmt->lineno, ECPG_TOO_MANY_MATCHES, NULL);
 						status = false;
 						break;
 					}
@@ -853,7 +853,7 @@ ECPGexecute(struct statement * stmt)
 								}
 								break;
 							default:
-								ECPGraise(ECPG_UNSUPPORTED, stmt->lineno, ECPGtype_name(var->ind_type));
+								ECPGraise(stmt->lineno, ECPG_UNSUPPORTED, ECPGtype_name(var->ind_type));
 								status = false;
 								break;
 						}
@@ -1057,7 +1057,7 @@ ECPGexecute(struct statement * stmt)
 								break;
 
 							default:
-								ECPGraise(ECPG_UNSUPPORTED, stmt->lineno, ECPGtype_name(var->type));
+								ECPGraise(stmt->lineno, ECPG_UNSUPPORTED, ECPGtype_name(var->type));
 								status = false;
 								break;
 						}
@@ -1067,7 +1067,7 @@ ECPGexecute(struct statement * stmt)
 
 				if (status && var != NULL)
 				{
-					ECPGraise(ECPG_TOO_MANY_ARGUMENTS, stmt->lineno, NULL);
+					ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, NULL);
 					status = false;
 				}
 
@@ -1123,7 +1123,7 @@ ECPGexecute(struct statement * stmt)
 }
 
 bool
-ECPGdo(int lineno, const char *connection_name, char *query,...)
+ECPGdo(int lineno, const char *connection_name, char *query, ...)
 {
 	va_list			args;
 	struct statement 	*stmt;
diff --git a/src/interfaces/ecpg/preproc/descriptor.c b/src/interfaces/ecpg/preproc/descriptor.c
index 247e48f234d9874f4fc7959c6c07d08036cfe664..845a70c0aa872bd76383faed8dbae7030220d8c4 100644
--- a/src/interfaces/ecpg/preproc/descriptor.c
+++ b/src/interfaces/ecpg/preproc/descriptor.c
@@ -11,15 +11,14 @@
  
 struct assignment *assignments;
 
-void push_assignment(char *var, char *value)
+void push_assignment(char *var, enum ECPGdtype value)
 {
 	struct assignment *new = (struct assignment *)mm_alloc(sizeof(struct assignment));
 	
 	new->next = assignments;
-	new->variable = mm_alloc(strlen(var)+1);
-	strcpy(new->variable,var);
-	new->value = mm_alloc(strlen(value)+1);
-	strcpy(new->value,value);
+	new->variable = mm_alloc(strlen(var) + 1);
+	strcpy(new->variable, var);
+	new->value = value;
 	assignments = new;
 }
 
@@ -32,7 +31,6 @@ drop_assignments(void)
 
 		assignments = old_head->next;
 		free(old_head->variable);
-		free(old_head->value);
 		free(old_head);
 	}
 }
@@ -61,7 +59,7 @@ static void ECPGnumeric_lvalue(FILE *f,char *name)
 
 static void ECPGstring_buffer(FILE *f, char *name)
 { 
-	const struct variable *v=find_variable(name);
+	const struct variable *v = find_variable(name);
 
 	switch(v->type->typ)
 	{
@@ -177,17 +175,18 @@ static struct descriptor *descriptors;
 
 void add_descriptor(char *name,char *connection)
 {
-	struct descriptor *new=(struct descriptor *)mm_alloc(sizeof(struct descriptor));
+	struct descriptor *new = (struct descriptor *)mm_alloc(sizeof(struct descriptor));
 	
-	new->next=descriptors;
-	new->name=mm_alloc(strlen(name)+1);
+	new->next = descriptors;
+	new->name = mm_alloc(strlen(name) + 1);
 	strcpy(new->name,name);
 	if (connection) 
-	{	new->connection=mm_alloc(strlen(connection)+1);
-		strcpy(new->connection,connection);
+	{
+		new->connection = mm_alloc(strlen(connection) + 1);
+		strcpy(new->connection, connection);
 	}
-	else new->connection=connection;
-	descriptors=new;
+	else new->connection = connection;
+	descriptors = new;
 }
 
 void
@@ -217,13 +216,13 @@ drop_descriptor(char *name,char *connection)
 }
 
 struct descriptor
-*lookup_descriptor(char *name,char *connection)
+*lookup_descriptor(char *name, char *connection)
 {
 	struct descriptor *i;
 	
-	for (i=descriptors;i;i=i->next)
+	for (i = descriptors; i; i = i->next)
 	{
-		if (!strcmp(name,i->name))
+		if (!strcmp(name, i->name))
 		{
 			if ((!connection && !i->connection) 
 				|| (connection && i->connection 
@@ -233,8 +232,8 @@ struct descriptor
 			}
 		}
 	}
-	snprintf(errortext,sizeof errortext,"unknown descriptor %s",name);
-	mmerror(ET_WARN,errortext);
+	snprintf(errortext, sizeof errortext, "unknown descriptor %s", name);
+	mmerror(ET_WARN, errortext);
 	return NULL;
 }
 
@@ -246,10 +245,11 @@ output_get_descr_header(char *desc_name)
 	fprintf(yyout, "{ ECPGget_desc_header(%d, \"%s\", &(", yylineno, desc_name);
 	for (results = assignments; results != NULL; results = results->next)
 	{
-		if (!strcasecmp(results->value, "count"))
+		if (results->value == ECPGd_count)
 			ECPGnumeric_lvalue(yyout,results->variable);
 		else
-		{	snprintf(errortext, sizeof errortext, "unknown descriptor header item '%s'", results->value);
+		{
+			snprintf(errortext, sizeof errortext, "unknown descriptor header item '%d'", results->value);
 			mmerror(ET_WARN, errortext);
 		}
 	}
@@ -260,114 +260,31 @@ output_get_descr_header(char *desc_name)
 }
 
 void
-output_get_descr(char *desc_name)
+output_get_descr(char *desc_name, char *index)
 {
 	struct assignment *results;
-	int flags=0;
-	const int DATA_SEEN=1;
-	const int INDICATOR_SEEN=2;
-	
-	fprintf(yyout,"{\tPGresult *ECPGresult=ECPGresultByDescriptor(%d, \"%s\");\n"
-													,yylineno,desc_name);
-	fputs("\tif (ECPGresult)\n\t{",yyout);
-	fprintf(yyout,"\tif (PQntuples(ECPGresult)<1) ECPGraise(%d,ECPG_NOT_FOUND);\n",yylineno);
-	fprintf(yyout,"\t\telse if (%s<1 || %s>PQnfields(ECPGresult))\n"
-			"\t\t\tECPGraise(%d,ECPG_INVALID_DESCRIPTOR_INDEX);\n"
-				,descriptor_index,descriptor_index,yylineno);
-	fputs("\t\telse\n\t\t{\n",yyout);
-	for (results=assignments;results!=NULL;results=results->next)
+
+	fprintf(yyout, "{ ECPGget_desc(%d,\"%s\",%s,", yylineno, desc_name, index);	
+	for (results = assignments; results != NULL; results = results->next)
 	{
-		if (!strcasecmp(results->value,"type"))
-		{
-			fputs("\t\t\t",yyout);
-			ECPGnumeric_lvalue(yyout,results->variable);
-			fprintf(yyout,"=ECPGDynamicType(PQftype(ECPGresult,(%s)-1));\n",descriptor_index);
-		}
-		else if (!strcasecmp(results->value,"datetime_interval_code"))
-		{
-			fputs("\t\t\t",yyout);
-			ECPGnumeric_lvalue(yyout,results->variable);
-			fprintf(yyout,"=ECPGDynamicType_DDT(PQftype(ECPGresult,(%s)-1));\n",descriptor_index);
-		}
-		else if (!strcasecmp(results->value,"length"))
-		{
-			fputs("\t\t\t",yyout);
-			ECPGnumeric_lvalue(yyout,results->variable);
-			fprintf(yyout,"=PQfmod(ECPGresult,(%s)-1)-VARHDRSZ;\n",descriptor_index);
-		}
-		else if (!strcasecmp(results->value,"octet_length"))
-		{
-			fputs("\t\t\t",yyout);
-			ECPGnumeric_lvalue(yyout,results->variable);
-			fprintf(yyout,"=PQfsize(ECPGresult,(%s)-1);\n",descriptor_index);
-		}
-		else if (!strcasecmp(results->value,"returned_length")
-			|| !strcasecmp(results->value,"returned_octet_length"))
-		{
-			fputs("\t\t\t",yyout);
-			ECPGnumeric_lvalue(yyout,results->variable);
-			fprintf(yyout,"=PQgetlength(ECPGresult,0,(%s)-1);\n",descriptor_index);
-		}
-		else if (!strcasecmp(results->value,"precision"))
-		{
-			fputs("\t\t\t",yyout);
-			ECPGnumeric_lvalue(yyout,results->variable);
-			fprintf(yyout,"=PQfmod(ECPGresult,(%s)-1)>>16;\n",descriptor_index);
-		}
-		else if (!strcasecmp(results->value,"scale"))
-		{
-			fputs("\t\t\t",yyout);
-			ECPGnumeric_lvalue(yyout,results->variable);
-			fprintf(yyout,"=(PQfmod(ECPGresult,(%s)-1)-VARHDRSZ)&0xffff;\n",descriptor_index);
-		}
-		else if (!strcasecmp(results->value,"nullable"))
-		{
-			mmerror(ET_WARN,"nullable is always 1");
-			fputs("\t\t\t",yyout);
-			ECPGnumeric_lvalue(yyout,results->variable);
-			fprintf(yyout,"=1;\n");
-		}
-		else if (!strcasecmp(results->value,"key_member"))
-		{
-			mmerror(ET_WARN,"key_member is always 0");
-			fputs("\t\t\t",yyout);
-			ECPGnumeric_lvalue(yyout,results->variable);
-			fprintf(yyout,"=0;\n");
-		}
-		else if (!strcasecmp(results->value,"name"))
-		{
-			fputs("\t\t\tstrncpy(",yyout);
-			ECPGstring_buffer(yyout,results->variable);
-			fprintf(yyout,",PQfname(ECPGresult,(%s)-1),",descriptor_index);
-			ECPGstring_length(yyout,results->variable);
-			fputs(");\n",yyout);
-		}
-		else if (!strcasecmp(results->value,"indicator"))
-		{
-			flags|=INDICATOR_SEEN;
-			fputs("\t\t\t",yyout);
-			ECPGnumeric_lvalue(yyout,results->variable);
-			fprintf(yyout,"=-PQgetisnull(ECPGresult,0,(%s)-1);\n",descriptor_index);
-		}
-		else if (!strcasecmp(results->value,"data"))
-		{
-			flags|=DATA_SEEN;
-			ECPGdata_assignment(results->variable,descriptor_index);
-		}
-		else
+		const struct variable *v = find_variable(results->variable);
+		
+		switch (results->value)
 		{
-			snprintf(errortext,sizeof errortext,"unknown descriptor header item '%s'",results->value);
-			mmerror(ET_WARN,errortext);
+			case ECPGd_nullable:
+				mmerror(ET_WARN,"nullable is always 1");
+				break;
+			case ECPGd_key_member:
+				mmerror(ET_WARN,"key_member is always 0");
+				break;
+			default:
+				break; 
 		}
-	}
-	if (flags==DATA_SEEN) /* no indicator */
-	{
-		fprintf(yyout,"\t\t\tif (PQgetisnull(ECPGresult,0,(%s)-1))\n"
-					"\t\t\t\tECPGraise(%d,ECPG_MISSING_INDICATOR);\n"
-				,descriptor_index,yylineno);
+		fprintf(yyout, "%s,", get_dtype(results->value));
+		ECPGdump_a_type(yyout, v->name, v->type, NULL, NULL, NULL, NULL);
 	}
 	drop_assignments();
-	fputs("\t\t}\n\t}\n",yyout);
+	fputs("ECPGd_EODT);\n",yyout);
 	
 	whenever_action(2|1);
 }
diff --git a/src/interfaces/ecpg/preproc/ecpg_keywords.c b/src/interfaces/ecpg/preproc/ecpg_keywords.c
index 0cc7699a6dc3a26336b097193956f066cfd9be61..e59dceafca38d13543e041a9744e69ee3c2eef75 100644
--- a/src/interfaces/ecpg/preproc/ecpg_keywords.c
+++ b/src/interfaces/ecpg/preproc/ecpg_keywords.c
@@ -28,6 +28,10 @@ static ScanKeyword ScanKeywords[] = {
 	{"connect", SQL_CONNECT},
 	{"connection", SQL_CONNECTION},
 	{"continue", SQL_CONTINUE},
+	{"count", SQL_COUNT},
+	{"data", SQL_DATA},
+	{"datetime_interval_code", SQL_DATETIME_INTERVAL_CODE},
+	{"datetime_interval_precision", SQL_DATETIME_INTERVAL_PRECISION},
 	{"deallocate", SQL_DEALLOCATE},
 	{"descriptor", SQL_DESCRIPTOR},
 	{"disconnect", SQL_DISCONNECT},
@@ -40,12 +44,20 @@ static ScanKeyword ScanKeywords[] = {
 	{"identified", SQL_IDENTIFIED},
 	{"indicator", SQL_INDICATOR},
 	{"int", SQL_INT},
+	{"key_member", SQL_KEY_MEMBER},
+	{"length", SQL_LENGTH},
 	{"long", SQL_LONG},
+	{"name", SQL_NAME},
+	{"nullable", SQL_NULLABLE},
+	{"octet_length", SQL_OCTET_LENGTH},
 	{"off", SQL_OFF},
 	{"open", SQL_OPEN},
 	{"prepare", SQL_PREPARE},
 	{"reference", SQL_REFERENCE},
 	{"release", SQL_RELEASE},
+	{"returned_length", SQL_RETURNED_LENGTH},
+	{"returned_octet_length", SQL_RETURNED_OCTET_LENGTH},
+	{"scale", SQL_SCALE},
 	{"section", SQL_SECTION},
 	{"short", SQL_SHORT},
 	{"signed", SQL_SIGNED},
diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h
index 3ec8a596b1efde619ee8c8289932a79ef3f3dd1b..7cf42946f419984637e58f6f2bc3f01eecd18fb2 100644
--- a/src/interfaces/ecpg/preproc/extern.h
+++ b/src/interfaces/ecpg/preproc/extern.h
@@ -35,6 +35,7 @@ extern struct descriptor *descriptors;
 
 /* functions */
 
+extern const char *get_dtype(enum ECPGdtype);
 extern void lex_init(void);
 extern char *make_str(const char *);
 extern void output_line_number(void);
@@ -50,8 +51,8 @@ extern void mmerror(enum errortype, char * );
 extern ScanKeyword *ScanECPGKeywordLookup(char *);
 extern ScanKeyword *ScanCKeywordLookup(char *);
 extern void output_get_descr_header(char *);
-extern void output_get_descr(char *);
-extern void push_assignment(char *, char *);
+extern void output_get_descr(char *, char *);
+extern void push_assignment(char *, enum ECPGdtype);
 extern struct variable * find_variable(char *);
 extern void whenever_action(int);
 extern void add_descriptor(char *,char *);
diff --git a/src/interfaces/ecpg/preproc/keywords.c b/src/interfaces/ecpg/preproc/keywords.c
index e8fd0d0bb6427a83b28bd4965294cd3c0f4aba2e..a82975056ffdfff9bd800c823bc5acecaf722168 100644
--- a/src/interfaces/ecpg/preproc/keywords.c
+++ b/src/interfaces/ecpg/preproc/keywords.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.22 2000/02/15 12:15:54 meskes Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.23 2000/02/22 19:57:10 meskes Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -108,6 +108,7 @@ static ScanKeyword ScanKeywords[] = {
 	{"fetch", FETCH},
 	{"float", FLOAT},
 	{"for", FOR},
+	{"force", FORCE},
 	{"foreign", FOREIGN},
 	{"forward", FORWARD},
 	{"from", FROM},
@@ -197,6 +198,7 @@ static ScanKeyword ScanKeywords[] = {
 	{"public", PUBLIC},
 	{"read", READ},
 	{"references", REFERENCES},
+	{"reindex", REINDEX},
 	{"relative", RELATIVE},
 	{"rename", RENAME},
 	{"reset", RESET},
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index f69f21b94d0dc138790545874f1849e3e147fcb4..fcb033787c5cee03b265cd6d6a5aadd49933c298 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -12,7 +12,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.50 2000/01/27 19:00:39 meskes Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.51 2000/02/22 19:57:10 meskes Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -70,29 +70,26 @@ static struct _if_value {
 } stacked_if_value[MAX_NESTED_IF];
 
 %}
+
 %option yylineno
 %s C SQL incl def def_ident
-/* OK, here is a short description of lex/flex rules behavior.
+
+/*
+ * OK, here is a short description of lex/flex rules behavior.
  * The longest pattern which matches an input string is always chosen.
  * For equal-length patterns, the first occurring in the rules list is chosen.
- * INITIAL is the starting condition, to which all non-conditional rules apply.
- * When in an exclusive condition, only those rules defined for that condition apply.
+ * INITIAL is the starting state, to which all non-conditional rules apply.
+ * Exclusive states change parsing rules while the state is active.  When in
+ * an exclusive state, only those rules defined for that state apply.
  *
- * Exclusive states change parsing rules while the state is active.
- * There are exclusive states for quoted strings, extended comments,
- *  and to eliminate parsing troubles for numeric strings.
+ * We use exclusive states for quoted strings, extended comments,
+ * and to eliminate parsing troubles for numeric strings.
  * Exclusive states:
  *  <xb> binary numeric string - thomas 1997-11-16
  *  <xc> extended C-style comments - tgl 1997-07-12
  *  <xd> delimited identifiers (double-quoted identifiers) - tgl 1997-10-27
  *  <xh> hexadecimal numeric string - thomas 1997-11-16
  *  <xq> quoted strings - tgl 1997-07-30
- *
- * The "extended comment" syntax closely resembles allowable operator syntax.
- * So, when in condition <xc>, only strings which would terminate the
- *  "extended comment" trigger any action other than "ignore".
- * Be sure to match _any_ candidate comment, including those with appended
- *	operator-like symbols. - thomas 1997-07-14
  */
 
 %x xb
@@ -109,15 +106,15 @@ static struct _if_value {
  */
 xbstart			[bB]{quote}
 xbstop			{quote}
-xbinside		[^']*
-xbcat			{quote}{space}*\n{space}*{quote}
+xbinside		[^']+
+xbcat			{quote}{whitespace_with_newline}{quote}
 
 /* Hexadecimal number
  */
 xhstart			[xX]{quote}
 xhstop			{quote}
-xhinside		[^']*
-xhcat			{quote}{space}*\n{space}*{quote}
+xhinside		[^']+
+xhcat			{quote}{whitespace_with_newline}{quote}
 
 /* C version of hex number 
  */
@@ -131,9 +128,9 @@ quote			'
 xqstart			{quote}
 xqstop			{quote}
 xqdouble		{quote}{quote}
-xqinside		[^\\']*
+xqinside		[^\\']+
 xqliteral		[\\](.|\n)
-xqcat			{quote}{space}*\n{space}*{quote}
+xqcat			{quote}{whitespace_with_newline}{quote}
 
 /* Delimited quote
  * Allows embedded spaces and other special characters into identifiers.
@@ -141,7 +138,7 @@ xqcat			{quote}{space}*\n{space}*{quote}
 dquote			\"
 xdstart			{dquote}
 xdstop			{dquote}
-xdinside		[^"]*
+xdinside		[^"]+
 
 /* special stuff for C strings */
 xdcqq			\\\\
@@ -149,14 +146,25 @@ xdcqdq			\\\"
 xdcother		[^"]
 xdcinside		({xdcqq}|{xdcqdq}|{xdcother})
 
-/* Comments
+/* C-Style Comments
  * Ignored by the scanner and parser.
+ * The "extended comment" syntax closely resembles allowable operator syntax.
+ * The tricky part here is to get lex to recognize a string starting with
+ * slash-star as a comment, when interpreting it as an operator would produce
+ * a longer match --- remember lex will prefer a longer match!  So, we have
+ * to provide a special rule for xcline (a complete comment that could
+ * otherwise look like an operator), as well as append {op_and_self}* to
+ * xcstart so that it matches at least as much as {operator} would.
+ * Then the tie-breaker (first matching rule of same length) wins.
+ * There is still a problem if someone writes, eg, slash-star-star-slash-plus.
+ * It'll be taken as an xcstart, rather than xcline and an operator as one
+ * could wish.  I don't see any way around that given lex's behavior;
+ * that someone will just have to write a space after the comment.
  */
-xcline			[\/][\*].*[\*][\/]{line_end}+
-xcstart			[\/][\*]{op_and_self}*
-xcstop			{op_and_self}*[\*][\/]{space_or_nl}*
-xcinside		[^*]*
-xcstar			[^/]
+xcline			\/\*{op_and_self}*\*\/
+xcstart                 \/\*{op_and_self}*
+xcstop			\*+\/
+xcinside 		([^*]+)|(\*+[^/])
 
 digit			[0-9]
 letter			[\200-\377_A-Za-z]
@@ -181,12 +189,44 @@ real			((({digit}*\.{digit}+)|({digit}+\.{digit}*)|({digit}+))([Ee][-+]?{digit}+
 
 param			\${integer}
 
-comment			("--"|"//").*
+/*
+ * In order to make the world safe for Windows and Mac clients as well as
+ * Unix ones, we accept either \n or \r as a newline.  A DOS-style \r\n
+ * sequence will be seen as two successive newlines, but that doesn't cause
+ * any problems.  SQL92-style comments, which start with -- and extend to the
+ * next newline, are treated as equivalent to a single whitespace character.
+ *
+ * NOTE a fine point: if there is no newline following --, we will absorb
+ * everything to the end of the input as a comment.  This is correct.  Older
+ * versions of Postgres failed to recognize -- as a comment if the input
+ * did not end with a newline.
+ *
+ * XXX perhaps \f (formfeed) should be treated as a newline as well?
+ */
+
 ccomment		"//".*\n
 
 space			[ \t\r\f]
 space_or_nl		[ \t\r\f\n]
-line_end		{space}*\n
+line_end                {space}*\n
+horiz_space		[ \t\f]
+newline                 [\n\r]
+non_newline		[^\n\r]
+
+comment                 (("--"|"//"){non_newline}*)
+
+whitespace 		({space}|{comment})
+
+/*
+ * SQL92 requires at least one newline in the whitespace separating
+ * string literals that are to be concatenated.  Silly, but who are we
+ * to argue?  Note that {whitespace_with_newline} should not have * after
+ * it, whereas {whitespace} should generally have a * after it...
+ */
+
+horiz_whitespace	({horiz_space}|{comment})
+whitespace_with_newline	({horiz_whitespace}*{newline}{whitespace}*)
+
 other			.
 
 /* some stuff needed for ecpg */
@@ -217,14 +257,16 @@ cppline			{space}*#(.*\\{line_end})*.*
  *  of escaped-quote "\'".
  * Other embedded escaped characters are matched explicitly and the leading
  *  backslash is dropped from the string. - thomas 1997-09-24
+ * Note that xcline must appear before xcstart, which must appear before
+ *  operator, as explained above!  Also whitespace (comment) must appear
+ *  before operator.
  */
 
 %%
-<SQL>{comment}		{ /* ignore */ }
+<SQL>{whitespace}	{ /* ignore */ }
 
 {xcline}		{ ECHO; }
 
-<xc>{xcstar}		{ ECHO; }
 {xcstart}		{
 				before_comment = YYSTATE;
 				ECHO;
@@ -254,7 +296,7 @@ cppline			{space}*#(.*\\{line_end})*.*
 					addlit(yytext, yyleng);
 				}
 <xh>{xhcat}		|
-<xb>{xbcat}		{
+<xb>{xbcat}		{		/* ignore */
 				}
 
 <SQL>{xhstart}		{
@@ -286,7 +328,7 @@ cppline			{space}*#(.*\\{line_end})*.*
 <xq>{xqliteral} {
 					addlit(yytext, yyleng);
 				}
-<xq>{xqcat}		{
+<xq>{xqcat}		{		/* ignore */
 				}
 
 <SQL>{xdstart}		{
@@ -331,43 +373,28 @@ cppline			{space}*#(.*\\{line_end})*.*
 					return Op;
 				}
 <SQL>{param}			{
-					yylval.ival = atoi((char*)&yytext[1]);
+					yylval.ival = atol((char*)&yytext[1]);
 					return PARAM;
 				}
 <C,SQL>{integer}		{
 					char* endptr;
 
 					errno = 0;
-					yylval.ival = strtol((char *)yytext,&endptr,10);
+					yylval.ival = strtol((char *)yytext, &endptr,10);
 					if (*endptr != '\0' || errno == ERANGE)
 					{
 						errno = 0;
 						yylval.str = mm_strdup((char*)yytext);
-						return SCONST;
+						return FCONST;
 					}
 					return ICONST;
 				}
 {decimal}		{
-					char* endptr;
-
-					if (strlen((char *)yytext) <= 17)
-					{
-						errno = 0;
-						yylval.dval = strtod((char *)yytext,&endptr);
-						if (*endptr != '\0' || errno == ERANGE)
-							mmerror(ET_ERROR, "Bad float8 input");
-						return FCONST;
-					}
 					yylval.str = mm_strdup((char*)yytext);
-					return SCONST;
+					return FCONST;
 				}
 <C,SQL>{real}			{
-					char* endptr;
-
-					errno = 0;
-					yylval.dval = strtod((char *)yytext,&endptr);
-					if (*endptr != '\0' || errno == ERANGE)
-						mmerror(ET_ERROR, "Bad float input");
+					yylval.str = mm_strdup((char*)yytext);
 					return FCONST;
 				}
 <SQL>:{identifier}(("->"|\.){identifier})*	{
@@ -433,7 +460,6 @@ cppline			{space}*#(.*\\{line_end})*.*
 						}
 					}
 				}
-<SQL>{space_or_nl}		{ /* ignore */ }
 <SQL>{other}			{ return yytext[0]; }
 <C>{exec_sql}			{ BEGIN SQL; return SQL_START; }
 <C>{ccomment}			{ /* ignore */ } 
diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y
index 2b1f1c304aa5e2b270870fe822056196b6bf1567..a42b68f7debb83e1e173bce6aea599d086b765cd 100644
--- a/src/interfaces/ecpg/preproc/preproc.y
+++ b/src/interfaces/ecpg/preproc/preproc.y
@@ -21,7 +21,6 @@
 int	struct_level = 0;
 int	braces_open; /* brace level counter */
 char	errortext[128];
-char	*descriptor_index= NULL;
 char	*connection = NULL;
 char 	*input_filename = NULL;
 
@@ -154,17 +153,23 @@ make_name(void)
 	int			tagname;
 	struct this_type	type;
 	enum ECPGttype		type_enum;
+	enum ECPGdtype		dtype_enum;
 	struct fetch_desc	descriptor;
 }
 
 /* special embedded SQL token */
 %token		SQL_ALLOCATE SQL_AT SQL_AUTOCOMMIT SQL_BOOL SQL_BREAK 
-%token		SQL_CALL SQL_CONNECT SQL_CONNECTION SQL_CONTINUE
+%token		SQL_CALL SQL_CONNECT SQL_CONNECTION SQL_CONTINUE SQL_COUNT
+%token		SQL_DATA SQL_DATETIME_INTERVAL_CODE SQL_DATETIME_INTERVAL_PRECISION
 %token		SQL_DEALLOCATE SQL_DESCRIPTOR SQL_DISCONNECT SQL_ENUM 
 %token		SQL_FOUND SQL_FREE SQL_GET SQL_GO SQL_GOTO
-%token		SQL_IDENTIFIED SQL_INDICATOR SQL_INT SQL_LONG
-%token		SQL_OFF SQL_OPEN SQL_PREPARE SQL_RELEASE SQL_REFERENCE
-%token		SQL_SECTION SQL_SHORT SQL_SIGNED SQL_SQL 
+%token		SQL_IDENTIFIED SQL_INDICATOR SQL_INT SQL_KEY_MEMBER 
+%token		SQL_LENGTH SQL_LONG
+%token		SQL_NAME SQL_NULLABLE
+%token		SQL_OCTET_LENGTH SQL_OFF SQL_OPEN SQL_PREPARE
+%token		SQL_RELEASE SQL_REFERENCE SQL_RETURNED_LENGTH
+%token		SQL_RETURNED_OCTET_LENGTH
+%token		SQL_SCALE SQL_SECTION SQL_SHORT SQL_SIGNED SQL_SQL 
 %token		SQL_SQLERROR SQL_SQLPRINT
 %token		SQL_SQLWARNING SQL_START SQL_STOP SQL_STRUCT SQL_UNSIGNED
 %token		SQL_VALUE SQL_VAR SQL_WHENEVER
@@ -222,13 +227,13 @@ make_name(void)
 		CACHE, CLUSTER, COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE,
                 DATABASE, DELIMITERS, DO,
 		EACH, ENCODING, EXCLUSIVE, EXPLAIN, EXTEND,
-                FORWARD, FUNCTION, HANDLER,
+                FORCE, FORWARD, FUNCTION, HANDLER,
                 INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
                 LANCOMPILER, LIMIT, LISTEN, UNLISTEN, LOAD, LOCATION, LOCK_P,
 		MAXVALUE, MINVALUE, MODE, MOVE,
                 NEW,  NOCREATEDB, NOCREATEUSER, NONE, NOTHING, NOTIFY, NOTNULL,
 		OFFSET, OIDS, OPERATOR, PASSWORD, PROCEDURAL,
-                RENAME, RESET, RETURNS, ROW, RULE,
+                REINDEX, RENAME, RESET, RETURNS, ROW, RULE,
                 SEQUENCE, SERIAL, SETOF, SHARE, SHOW, START, STATEMENT, STDIN, STDOUT, SYSID
 		TRUNCATE, TRUSTED,
                 UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION
@@ -270,11 +275,11 @@ make_name(void)
 
 %type  <str>	Iconst Fconst Sconst TransactionStmt CreateStmt UserId
 %type  <str>	CreateAsElement OptCreateAs CreateAsList CreateAsStmt
-%type  <str>	OptInherit key_reference key_action comment_text
+%type  <str>	OptInherit key_reference comment_text
 %type  <str>    key_match ColLabel SpecialRuleRelation ColId columnDef
 %type  <str>    ColConstraint ColConstraintElem NumericOnly FloatOnly
 %type  <str>    OptTableElementList OptTableElement TableConstraint
-%type  <str>    ConstraintElem key_actions ColPrimaryKey ColQualList
+%type  <str>    ConstraintElem key_actions ColQualList
 %type  <str>    target_list target_el update_target_list alias_clause
 %type  <str>    update_target_el opt_id relation_name database_name
 %type  <str>    access_method attr_name class index_name name func_name
@@ -304,7 +309,7 @@ make_name(void)
 %type  <str>    func_args_list func_args opt_with ProcedureStmt def_arg
 %type  <str>    def_elem def_list definition def_name def_type DefineStmt
 %type  <str>    opt_instead event event_object RuleActionList opt_using
-%type  <str>	RuleActionStmtOrEmpty RuleActionMulti func_as
+%type  <str>	RuleActionStmtOrEmpty RuleActionMulti func_as reindex_type
 %type  <str>    RuleStmt opt_column opt_name oper_argtypes sysid_clause
 %type  <str>    MathOp RemoveFuncStmt aggr_argtype for_update_clause
 %type  <str>    RemoveAggrStmt remove_type RemoveStmt ExtendStmt
@@ -324,18 +329,18 @@ make_name(void)
 %type  <str>	GrantStmt privileges operation_commalist operation
 %type  <str>	opt_cursor opt_lmode ConstraintsSetStmt comment_tg
 %type  <str>	case_expr when_clause_list case_default case_arg when_clause
-%type  <str>    select_clause opt_select_limit select_limit_value
-%type  <str>    select_offset_value using_expr join_expr
+%type  <str>    select_clause opt_select_limit select_limit_value TimeClause
+%type  <str>    select_offset_value using_expr join_expr ReindexStmt
 %type  <str>	using_list from_expr join_clause join_type
 %type  <str>	join_qual update_list join_clause join_clause_with_union
 %type  <str>	opt_level opt_lock lock_type users_in_new_group_clause
-%type  <str>    OptConstrFromTable comment_op ConstraintAttributeSpec
+%type  <str>    OptConstrFromTable comment_op ConstraintAttribute
 %type  <str>    constraints_set_list constraints_set_namelist comment_fn
 %type  <str>	constraints_set_mode comment_type comment_cl comment_ag
-%type  <str>	ConstraintDeferrabilitySpec ConstraintTimeSpec 
-%type  <str>	CreateGroupStmt AlterGroupStmt DropGroupStmt
-%type  <str>	ColConstraintWithNull ColConstraintElemWithNull
-%type  <str>	join_expr_with_union
+%type  <str>	CreateGroupStmt AlterGroupStmt DropGroupStmt key_delete
+%type  <str>	ColConstraintWithNull ColConstraintElemWithNull NotNull
+%type  <str>	join_expr_with_union DefaultClause DefaultExpr PrimaryKey
+%type  <str>	DeferrabilityClause opt_force key_update
 /***
 #ifdef ENABLE_ORACLE_JOIN_SYNTAX
 %type  <str>   oracle_list oracle_expr oracle_outer
@@ -357,12 +362,14 @@ make_name(void)
 %type  <str>    struct_type s_struct declaration declarations variable_declarations
 %type  <str>    s_struct s_union union_type ECPGSetAutocommit on_off
 %type  <str>	ECPGAllocateDescr ECPGDeallocateDescr
-%type  <str>	ECPGGetDescriptor ECPGGetDescriptorHeader 
+%type  <str>	ECPGGetDescriptorHeader 
 
-%type  <descriptor> ECPGFetchDescStmt
+%type  <descriptor> ECPGFetchDescStmt ECPGGetDescriptor
 
 %type  <type_enum> simple_type signed_type unsigned_type varchar_type
 
+%type  <dtype_enum> descriptor_item desc_header_item
+
 %type  <type>	type
 
 %type  <action> action
@@ -416,6 +423,7 @@ stmt:  AlterTableStmt			{ output_statement($1, 0, NULL); }
 		| UnlistenStmt		{ output_statement($1, 0, NULL); }
 		| LockStmt		{ output_statement($1, 0, NULL); }
 		| ProcedureStmt		{ output_statement($1, 0, NULL); }
+		| ReindexStmt		{ output_statement($1, 0, NULL); }
 		| RemoveAggrStmt	{ output_statement($1, 0, NULL); }
 		| RemoveOperStmt	{ output_statement($1, 0, NULL); }
 		| RemoveFuncStmt	{ output_statement($1, 0, NULL); }
@@ -483,7 +491,11 @@ stmt:  AlterTableStmt			{ output_statement($1, 0, NULL); }
 						free($1);
 					} 
 		| ECPGExecute		{	output_statement($1, 0, NULL); }
-		| ECPGFetchDescStmt	{ 	output_statement($1.str, 1, $1.name); }
+		| ECPGFetchDescStmt	{
+					 	output_statement($1.str, 1, $1.name);
+						free($1.str);
+						free($1.name);
+					}
 		| ECPGFree		{
 						fprintf(yyout, "{ ECPGdeallocate(__LINE__, \"%s\");", $1);
 
@@ -491,12 +503,15 @@ stmt:  AlterTableStmt			{ output_statement($1, 0, NULL); }
 						free($1);
 					}
 		| ECPGGetDescriptor	{	
-						lookup_descriptor($1,connection);
-						output_get_descr($1);
+						lookup_descriptor($1.name, connection);
+						output_get_descr($1.name, $1.str);
+						free($1.name);
+						free($1.str);
 					}
 		| ECPGGetDescriptorHeader	{	
-						lookup_descriptor($1,connection);
+						lookup_descriptor($1, connection);
 						output_get_descr_header($1);
+						free($1);
 					}
 		| ECPGOpen		{	
 						struct cursor *ptr;
@@ -1013,42 +1028,64 @@ OptTableElement:  columnDef		{ $$ = $1; }
 			| TableConstraint	{ $$ = $1; }
 		;
 
-columnDef:  ColId Typename ColQualifier
+columnDef:  ColId Typename ColQualifier opt_collate
 				{
-					$$ = cat_str(3, $1, $2, $3);
+					if (strlen($4) > 0)
+					{
+						sprintf(errortext, "CREATE TABLE/COLLATE %s not yet implemented; clause ignored", $4);
+						mmerror(ET_WARN, errortext);
+					}
+					$$ = cat_str(4, $1, $2, $3, $4);
 				}
-	| ColId SERIAL ColPrimaryKey
+	| ColId SERIAL ColQualifier opt_collate
 		{
-			$$ = cat_str(3, $1, make_str(" serial "), $3);
+			if (strlen($4) > 0)
+			{
+				sprintf(errortext, "CREATE TABLE/COLLATE %s not yet implemented; clause ignored", $4);
+				mmerror(ET_WARN, errortext);
+			}
+			$$ = cat_str(4, $1, make_str(" serial "), $3, $4);
 		}
 		;
 
-ColQualifier:	ColQualList			{ $$ = $1; }
-		| NULL_P ColQualListWithNull    { $$ = cat2_str(make_str("null"), $2); }
-                | NULL_P			{ $$ = make_str("null"); }
-                | /*EMPTY*/           		{ $$ = EMPTY; }
+/*
+ * ColQualifier encapsulates an entire column qualification,
+ * including DEFAULT, constraints, and constraint attributes.
+ * Note that the DefaultClause handles the empty case.
+ */
+ColQualifier:	DefaultClause ColQualList			{ $$ = cat2_str($1, $2); }
+		| NotNull DefaultClause ColQualListWithNull	{ $$ = cat_str(3, $1, $2, $3); }
+		| DefaultExpr NotNull ColQualListWithNull	{ $$ = cat_str(3, $1, $2, $3); }
+                | DefaultExpr NotNull				{ $$ = cat2_str($1, $2); }
+                | NotNull DefaultClause				{ $$ = cat2_str($1, $2); }
+		| NULL_P DefaultClause ColQualListWithNull	{ $$ = cat_str(3, make_str("null"), $2, $3); }
+                | NULL_P DefaultClause				{ $$ = cat2_str(make_str("null"), $2); }
+                | DefaultClause		           		{ $$ = $1; }
+		;
+
+/*
+ * DEFAULT expression must be b_expr not a_expr to prevent shift/reduce
+ * conflict on NOT (since NOT might start a subsequent NOT NULL constraint,
+ * or be part of a_expr NOT LIKE or similar constructs).
+ */
+DefaultClause:  DefaultExpr     { $$ = $1; }
+		| /*EMPTY*/	{ $$ = EMPTY; }
+                ;
+
+DefaultExpr:  DEFAULT NULL_P		{ $$ = make_str("default null"); }
+		| DEFAULT b_expr	{ $$ = cat2_str(make_str("default"), $2); }
 		;
 
 ColQualList:  ColQualList ColConstraint	{ $$ = cat2_str($1,$2); }
 			| ColConstraint	{ $$ = $1; }
 		;
 
-ColQualListWithNull:  ColQualListWithNull ColConstraintWithNull
+ColQualListWithNull:  ColConstraintWithNull ColQualListWithNull
 			{ $$ = cat2_str($1, $2); }
 		|  ColConstraintWithNull
 			{ $$ = $1; }
-ColPrimaryKey:  PRIMARY KEY
-                {
-			$$ = make_str("primary key");
-                }
-              | /*EMPTY*/
-		{
-			$$ = EMPTY;
-		}
-                ;
 
-ColConstraint:
-		CONSTRAINT name ColConstraintElem
+ColConstraint:	CONSTRAINT name ColConstraintElem
 				{
 					$$ = cat_str(3, make_str("constraint"), $2, $3);
 				}
@@ -1056,8 +1093,7 @@ ColConstraint:
 				{ $$ = $1; }
 		;
 
-ColConstraintWithNull:
-		CONSTRAINT name ColConstraintElemWithNull
+ColConstraintWithNull:	CONSTRAINT name ColConstraintElemWithNull
 			{ $$ = cat_str(3, make_str("constraint"), $2, $3); }
 		| ColConstraintElemWithNull
 			{ $$ = $1; }
@@ -1073,26 +1109,18 @@ ColConstraintWithNull:
  * that a column may have that value. WITH NULL leads to
  * shift/reduce conflicts with WITH TIME ZONE anyway.
  * - thomas 1999-01-08
- *
- * DEFAULT expression must be b_expr not a_expr to prevent shift/reduce
- * conflict on NOT (since NOT might start a subsequent NOT NULL constraint,
- * or be part of a_expr NOT LIKE or similar constructs).
  */
 ColConstraintElem:  ColConstraintElemWithNull
                                 {
                                         $$ = $1;
                                 }
-                        | NOT NULL_P
-                                {
-                                        $$ = make_str("not null");
-                                }
                         | UNIQUE
 				{
 					$$ = make_str("unique");
 				}
-			| PRIMARY KEY
+			| PrimaryKey
 				{
-					$$ = make_str("primary key");
+					$$ = $1;
 				}
 			;
 
@@ -1101,20 +1129,22 @@ ColConstraintElemWithNull:  CHECK '(' a_expr ')'
 				{
 					$$ = cat_str(3, make_str("check("), $3, make_str(")"));
 				}
-			| DEFAULT NULL_P
-				{
-					$$ = make_str("default null");
-				}
-			| DEFAULT b_expr
+			| REFERENCES ColId opt_column_list
+				key_match key_actions ConstraintAttribute
 				{
-					$$ = cat2_str(make_str("default"), $2);
+					$$ = cat_str(6, make_str("references"), $2, $3, $4, $5, $6);
 				}
-			| REFERENCES ColId opt_column_list key_match key_actions
+			| REFERENCES ColId opt_column_list
+				key_match key_actions
 				{
 					$$ = cat_str(5, make_str("references"), $2, $3, $4, $5);
 				}
 		;
 
+PrimaryKey:  PRIMARY KEY	{ $$ = make_str("primary key"); }
+
+NotNull:  NOT NULL_P		{ $$ = make_str("not null"); }
+
 /* ConstraintElem specifies constraint syntax which is not embedded into
  *  a column definition. ColConstraintElem specifies the embedded form.
  * - thomas 1997-12-03
@@ -1135,11 +1165,17 @@ ConstraintElem:  CHECK '(' a_expr ')'
 				{
 					$$ = cat_str(3, make_str("unique("), $3, make_str(")"));
 				}
-		| PRIMARY KEY '(' columnList ')'
+		| PrimaryKey '(' columnList ')'
+				{
+					$$ = cat_str(3, make_str("primary key("), $3, make_str(")"));
+				}
+		| FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list
+			key_match key_actions ConstraintAttribute
 				{
-					$$ = cat_str(3, make_str("primary key("), $4, make_str(")"));
+					$$ = cat_str(8, make_str("foreign key("), $4, make_str(") references"), $7, $8, $9, $10, $11);
 				}
-		| FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions
+		| FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list
+			key_match key_actions
 				{
 					$$ = cat_str(7, make_str("foreign key("), $4, make_str(") references"), $7, $8, $9, $10);
 				}
@@ -1151,7 +1187,7 @@ key_match:  MATCH FULL
 		}
 		| MATCH PARTIAL		
 		{
-			mmerror(ET_WARN, "FOREIGN KEY match type PARTIAL not implemented yet");
+			mmerror(ET_WARN, "FOREIGN KEY/MATCH PARTIAL not yet implemented");
 			$$ = make_str("match partial");
 		}
 		| /*EMPTY*/
@@ -1160,14 +1196,16 @@ key_match:  MATCH FULL
 		}
 		;
 
-key_actions:  key_action key_action	{ $$ = cat2_str($1, $2); }
-		| key_action		{ $$ = $1; }
+key_actions:  key_delete		{ $$ = $1; }
+		| key_update		{ $$ = $1; }
+		| key_delete key_update	{ $$ = cat2_str($1, $2); }
+		| key_update key_delete	{ $$ = cat2_str($1, $2); }
 		| /*EMPTY*/		{ $$ = EMPTY; }
 		;
 
-key_action:  ON DELETE key_reference	{ $$ = cat2_str(make_str("on delete"), $3); }
-		| ON UPDATE key_reference		{ $$ = cat2_str(make_str("on update"), $3); }
-		;
+key_delete: ON DELETE key_reference	{ $$ = cat2_str(make_str("on delete"), $3); }
+
+key_update: ON UPDATE key_reference	{ $$ = cat2_str(make_str("on update"), $3); }
 
 key_reference:  NO ACTION	{ $$ = make_str("no action"); }
 		| RESTRICT	{ $$ = make_str("restrict"); }
@@ -1313,7 +1351,7 @@ CreateTrigStmt:  CREATE TRIGGER name TriggerActionTime TriggerEvents ON
 				}
 	|	CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON
                                 relation_name OptConstrFromTable
-				ConstraintAttributeSpec
+				ConstraintAttribute
                                 FOR EACH ROW EXECUTE PROCEDURE
 				name '(' TriggerFuncArgs ')'
 				{
@@ -1388,46 +1426,32 @@ OptConstrFromTable:                     /* Empty */
                                 }
                 ;
 
-ConstraintAttributeSpec: ConstraintDeferrabilitySpec
+ConstraintAttribute: DeferrabilityClause
                 { 	$$ = $1; }
-	| ConstraintDeferrabilitySpec ConstraintTimeSpec
+	| TimeClause
+		{ 	$$ = $1; }
+	| DeferrabilityClause TimeClause
 		{
 			if (strcmp($1, "deferrable") != 0 && strcmp($2, "initially deferrable") == 0 )
 				mmerror(ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
 
                 	$$ = cat2_str($1, $2);
 		}
-	| ConstraintTimeSpec
-		{ 	$$ = $1; }
-	| ConstraintTimeSpec ConstraintDeferrabilitySpec
+	| TimeClause DeferrabilityClause
 		{
 			if (strcmp($2, "deferrable") != 0 && strcmp($1, "initially deferrable") == 0 )
 				mmerror(ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
 
                 	$$ = cat2_str($1, $2);
 		}
-	| /* Empty */
-                       { $$ = 0; }
 	;
 
-ConstraintDeferrabilitySpec: NOT DEFERRABLE
-                                {
-                                        $$ = make_str("not deferrable");
-                                }
-                | DEFERRABLE
-                                {
-                                        $$ = make_str("deferrable");
-                                }
+DeferrabilityClause: NOT DEFERRABLE	{ $$ = make_str("not deferrable"); }
+	                | DEFERRABLE	{ $$ = make_str("deferrable"); }
                 ;
 
-ConstraintTimeSpec: INITIALLY IMMEDIATE
-                                {
-                                        $$ = make_str("initially immediate");
-                                }
-                | INITIALLY DEFERRED
-                                {
-                                        $$ = make_str("initially deferrable");
-                                }
+TimeClause: INITIALLY IMMEDIATE		{ $$ = make_str("initially immediate"); }
+                | INITIALLY DEFERRED	{ $$ = make_str("initially deferrable"); }
                 ;
 
 DropTrigStmt:  DROP TRIGGER name ON relation_name
@@ -1961,6 +1985,25 @@ oper_argtypes:	name
 				{ $$ = cat2_str($1, make_str(", none")); }
 		;
 
+/*****************************************************************************
+ *
+ *              QUERY:
+ *
+ *              REINDEX type <typename> [FORCE] [ALL]
+ *
+ *****************************************************************************/
+ReindexStmt:  REINDEX reindex_type name opt_force
+                                {
+					$$ = cat_str(4, make_str("reindex"), $2, $3, $4);
+				}
+
+reindex_type:   INDEX		{ $$ = make_str("index"); }
+                | TABLE		{ $$ = make_str("table"); }
+                | DATABASE	{ $$ = make_str("database"); }
+                ;
+opt_force:      FORCE		{ $$ = make_str("force"); }
+                | /* EMPTY */	{ $$ = EMPTY; }
+                ;
 
 /*****************************************************************************
  *
@@ -2864,6 +2907,10 @@ generic:  ident					{ $$ = $1; }
 		| SQL_CONNECT			{ $$ = make_str("connect"); }
 		| SQL_CONNECTION		{ $$ = make_str("connection"); }
 		| SQL_CONTINUE			{ $$ = make_str("continue"); }
+		| SQL_COUNT			{ $$ = make_str("count"); }
+		| SQL_DATA			{ $$ = make_str("data"); }
+		| SQL_DATETIME_INTERVAL_CODE	{ $$ = make_str("datetime_interval_code"); }
+		| SQL_DATETIME_INTERVAL_PRECISION	{ $$ = make_str("datetime_interval_precision"); }
 		| SQL_DEALLOCATE		{ $$ = make_str("deallocate"); }
 		| SQL_DISCONNECT		{ $$ = make_str("disconnect"); }
 		| SQL_FOUND			{ $$ = make_str("found"); }
@@ -2872,11 +2919,19 @@ generic:  ident					{ $$ = $1; }
 		| SQL_IDENTIFIED		{ $$ = make_str("identified"); }
 		| SQL_INDICATOR			{ $$ = make_str("indicator"); }
 		| SQL_INT			{ $$ = make_str("int"); }
+		| SQL_KEY_MEMBER		{ $$ = make_str("key_member"); }
+		| SQL_LENGTH			{ $$ = make_str("length"); }
 		| SQL_LONG			{ $$ = make_str("long"); }
+		| SQL_NAME			{ $$ = make_str("name"); }
+		| SQL_NULLABLE			{ $$ = make_str("nullable"); }
+		| SQL_OCTET_LENGTH		{ $$ = make_str("octet_length"); }
 		| SQL_OFF			{ $$ = make_str("off"); }
 		| SQL_OPEN			{ $$ = make_str("open"); }
 		| SQL_PREPARE			{ $$ = make_str("prepare"); }
 		| SQL_RELEASE			{ $$ = make_str("release"); }
+		| SQL_RETURNED_LENGTH		{ $$ = make_str("returned_length"); }
+		| SQL_RETURNED_OCTET_LENGTH	{ $$ = make_str("returned_octet_length"); }
+		| SQL_SCALE			{ $$ = make_str("scale"); }
 		| SQL_SECTION			{ $$ = make_str("section"); }
 		| SQL_SHORT			{ $$ = make_str("short"); }
 		| SQL_SIGNED			{ $$ = make_str("signed"); }
@@ -3019,15 +3074,9 @@ Character:  character '(' Iconst ')'
 				}
 		;
 
-character:  CHARACTER opt_varying opt_charset opt_collate
+character:  CHARACTER opt_varying opt_charset
 				{
-					if (strlen($4) > 0)
-					{
-						sprintf(errortext, "COLLATE %s not yet implemented", $4);
-						mmerror(ET_WARN, errortext);
-					}
-
-					$$ = cat_str(4, make_str("character"), $2, $3, $4);
+					$$ = cat_str(3, make_str("character"), $2, $3);
 				}
 		| CHAR opt_varying	{ $$ = cat2_str(make_str("char"), $2); }
 		| VARCHAR		{ $$ = make_str("varchar"); }
@@ -3401,6 +3450,8 @@ c_expr:  attr
 				{	$$ = cat2_str($1, make_str("()"));  }
 		| func_name '(' expr_list ')'
 				{	$$ = cat_str(4, $1, make_str("("), $3, make_str(")"));  }
+		| func_name '(' ALL expr_list ')'
+				{	$$ = cat_str(4, $1, make_str("( all"), $4, make_str(")"));  }
 		| func_name '(' DISTINCT expr_list ')'
 				{	$$ = cat_str(4, $1, make_str("( distinct"), $4, make_str(")"));  }
 		| func_name '(' '*' ')'
@@ -3870,6 +3921,10 @@ ColId:  ident					{ $$ = $1; }
 		| SQL_CALL			{ $$ = make_str("call"); }
 		| SQL_CONNECT			{ $$ = make_str("connect"); }
 		| SQL_CONTINUE			{ $$ = make_str("continue"); }
+		| SQL_COUNT			{ $$ = make_str("count"); }
+		| SQL_DATA			{ $$ = make_str("data"); }
+		| SQL_DATETIME_INTERVAL_CODE	{ $$ = make_str("datetime_interval_code"); }
+		| SQL_DATETIME_INTERVAL_PRECISION	{ $$ = make_str("datetime_interval_precision"); }
 		| SQL_DEALLOCATE		{ $$ = make_str("deallocate"); }
 		| SQL_DISCONNECT		{ $$ = make_str("disconnect"); }
 		| SQL_FOUND			{ $$ = make_str("found"); }
@@ -3878,11 +3933,19 @@ ColId:  ident					{ $$ = $1; }
 		| SQL_IDENTIFIED		{ $$ = make_str("identified"); }
 		| SQL_INDICATOR			{ $$ = make_str("indicator"); }
 		| SQL_INT			{ $$ = make_str("int"); }
+		| SQL_KEY_MEMBER		{ $$ = make_str("key_member"); }
+		| SQL_LENGTH			{ $$ = make_str("length"); }
 		| SQL_LONG			{ $$ = make_str("long"); }
+		| SQL_NAME			{ $$ = make_str("name"); }
+		| SQL_NULLABLE			{ $$ = make_str("nullable"); }
+		| SQL_OCTET_LENGTH		{ $$ = make_str("octet_length"); }
 		| SQL_OFF			{ $$ = make_str("off"); }
 		| SQL_OPEN			{ $$ = make_str("open"); }
 		| SQL_PREPARE			{ $$ = make_str("prepare"); }
 		| SQL_RELEASE			{ $$ = make_str("release"); }
+		| SQL_RETURNED_LENGTH		{ $$ = make_str("returned_length"); }
+		| SQL_RETURNED_OCTET_LENGTH	{ $$ = make_str("returned_octet_length"); }
+		| SQL_SCALE			{ $$ = make_str("scale"); }
 		| SQL_SECTION			{ $$ = make_str("section"); }
 		| SQL_SHORT			{ $$ = make_str("short"); }
 		| SQL_SIGNED			{ $$ = make_str("signed"); }
@@ -4586,23 +4649,32 @@ ECPGAllocateDescr:	SQL_ALLOCATE SQL_DESCRIPTOR ident
  * read from descriptor
  */
 
-ECPGGetDescHeaderItem: cvariable '=' ident  {
-		push_assignment($1,$3);
+ECPGGetDescHeaderItem: cvariable '=' desc_header_item  {
+		push_assignment($1, $3);
 }
 
-ECPGGetDescItem: cvariable '=' ident  {
-		push_assignment($1,$3);
-}
-	| cvariable '=' TYPE_P {
-		push_assignment($1,"type");
-}
-	| cvariable '=' PRECISION {
-		push_assignment($1,"precision");
-}
-	| cvariable '=' SQL_INDICATOR {
-		push_assignment($1,"indicator");
+desc_header_item:	SQL_COUNT			{ $$ = ECPGd_count; }
+
+ECPGGetDescItem: cvariable '=' descriptor_item  {
+		push_assignment($1, $3);
 }
 
+descriptor_item:	SQL_DATA			{ $$ = ECPGd_data; }
+		|	SQL_DATETIME_INTERVAL_CODE	{ $$ = ECPGd_di_code; }
+		| 	SQL_DATETIME_INTERVAL_PRECISION	{ $$ = ECPGd_di_precision; }
+		|	SQL_INDICATOR			{ $$ = ECPGd_indicator; }
+		|	SQL_KEY_MEMBER			{ $$ = ECPGd_key_member; }
+		|	SQL_LENGTH			{ $$ = ECPGd_length; }
+		|	SQL_NAME			{ $$ = ECPGd_name; }
+		|	SQL_NULLABLE			{ $$ = ECPGd_nullable; }
+		|	SQL_OCTET_LENGTH		{ $$ = ECPGd_octet; }
+		|	PRECISION			{ $$ = ECPGd_precision; }
+		|	SQL_RETURNED_LENGTH		{ $$ = ECPGd_length; }
+		|	SQL_RETURNED_OCTET_LENGTH	{ $$ = ECPGd_ret_octet; }
+		|	SQL_SCALE			{ $$ = ECPGd_scale; }
+		|	TYPE_P				{ $$ = ECPGd_type; }
+		;
+
 ECPGGetDescHeaderItems: ECPGGetDescHeaderItem
 	| ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem;
  
@@ -4613,9 +4685,9 @@ ECPGGetDescriptorHeader:	SQL_GET SQL_DESCRIPTOR ident ECPGGetDescHeaderItems
 		{  $$ = $3; }
 
 ECPGGetDescriptor:	SQL_GET SQL_DESCRIPTOR ident SQL_VALUE cvariable ECPGGetDescItems
-		{  $$ = $3; descriptor_index = $5; }
+		{  $$.str = $5; $$.name = $3; }
 	|	SQL_GET SQL_DESCRIPTOR ident SQL_VALUE Iconst ECPGGetDescItems
-		{  $$ = $3; descriptor_index = $5; }
+		{  $$.str = $5; $$.name = $3; }
 
 /*****************************************************************************
  *
@@ -5049,7 +5121,7 @@ ident: IDENT	{ $$ = $1; }
  * C stuff
  */
 
-symbol: IDENT	{ $$ = $1; }
+symbol: ident	{ $$ = $1; }
 
 cpp_line: CPP_LINE	{ $$ = $1; }
 
diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c
index 039939fe03558333d1cb3911093327100e4527f6..eff50f6a812ac1cbf9519f77276c543b532ae0aa 100644
--- a/src/interfaces/ecpg/preproc/type.c
+++ b/src/interfaces/ecpg/preproc/type.c
@@ -163,7 +163,7 @@ get_type(enum ECPGttype typ)
 			return ("ECPGt_NO_INDICATOR");
 			break;
 		case ECPGt_char_variable:		/* string that should not be
-										 * quoted */
+							 * quoted */
 			return ("ECPGt_char_variable");
 			break;
 		default:
@@ -198,12 +198,13 @@ static void ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, l
 void
 ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *ind_name, struct ECPGtype * ind_typ, const char *prefix, const char *ind_prefix)
 {
+#if 0
 	if (ind_typ == NULL)
 	{
 		ind_typ = &ecpg_no_indicator;
 		ind_name = "no_indicator";
 	}
-
+#endif
 	switch (typ->typ)
 	{
 		case ECPGt_array:
@@ -248,7 +249,8 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in
 			break;
 		default:
 			ECPGdump_a_simple(o, name, typ->typ, typ->size, -1, NULL, prefix);
-			ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix);
+			if (ind_typ != NULL)
+				ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix);
 			break;
 	}
 }
@@ -399,3 +401,60 @@ ECPGfree_type(struct ECPGtype * typ)
 	}
 	free(typ);
 }
+
+const char *
+get_dtype(enum ECPGdtype typ)
+{
+	switch (typ)
+	{
+		case ECPGd_count:
+			return ("ECPGd_countr");
+			break;
+		case ECPGd_data:
+			return ("ECPGd_data");
+			break;
+		case ECPGd_di_code:
+			return ("ECPGd_di_code");
+			break;
+		case ECPGd_di_precision:
+			return ("ECPGd_di_precision");
+			break;
+		case ECPGd_indicator:
+			return ("ECPGd_indicator");
+			break;
+		case ECPGd_key_member:
+			return ("ECPGd_key_member");
+			break;
+		case ECPGd_length:
+			return ("ECPGd_length");
+			break;
+		case ECPGd_name:
+			return ("ECPGd_name");
+			break;
+		case ECPGd_nullable:
+			return ("ECPGd_nullable");
+			break;
+		case ECPGd_octet:
+			return ("ECPGd_octet");
+			break;
+		case ECPGd_precision:
+			return ("ECPGd_precision");
+			break;
+		case ECPGd_ret_length:
+			return ("ECPGd_ret_length");
+		case ECPGd_ret_octet:
+			return ("ECPGd_ret_octet");
+			break;
+		case ECPGd_scale:	
+			return ("ECPGd_scale");
+			break;
+		case ECPGd_type:	
+			return ("ECPGd_type");
+			break;
+		default:
+			sprintf(errortext, "illegal descriptor item %d\n", typ);
+			yyerror(errortext);
+	}
+
+	return NULL;
+}
diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h
index dd393d0d40e0c32cb3bcf1a538a2d4b2a74cfc99..29525c392c3d9cefa0f5de17d962e58cf87c4a85 100644
--- a/src/interfaces/ecpg/preproc/type.h
+++ b/src/interfaces/ecpg/preproc/type.h
@@ -148,9 +148,9 @@ struct descriptor
 
 struct assignment
 {	
-	char 	*variable;
-	char	*value;
-	struct assignment *next;
+	char 			*variable;
+	enum ECPGdtype		value;
+	struct assignment 	*next;
 };
 
 enum errortype {ET_WARN, ET_ERROR, ET_FATAL};
diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.c
index df458dcc070b515312e13aecde6036d5636aa14f..8cbb1d38777148f0875f06ff43155596189256cf 100644
--- a/src/interfaces/ecpg/preproc/variable.c
+++ b/src/interfaces/ecpg/preproc/variable.c
@@ -222,8 +222,9 @@ dump_variables(struct arguments * list, int mode)
 
     /* Then the current element and its indicator */
     ECPGdump_a_type(yyout, list->variable->name, list->variable->type,
-	(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->name : NULL,
-	(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->type : NULL, NULL, NULL);
+/*	(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->name : NULL,
+	(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->type : NULL, NULL, NULL);*/
+	list->indicator->name, list->indicator->type, NULL, NULL);
 
     /* Then release the list element. */
     if (mode != 0)
diff --git a/src/interfaces/ecpg/test/dyntest.pgc b/src/interfaces/ecpg/test/dyntest.pgc
index 6317ba5fe0293d25122605ed17c6a1c625d6187f..3698cf685f5680d77b5f470d8b221c4b3f035f9b 100644
--- a/src/interfaces/ecpg/test/dyntest.pgc
+++ b/src/interfaces/ecpg/test/dyntest.pgc
@@ -2,7 +2,7 @@
  *
  * Copyright (c) 2000, Christof Petig <christof.petig@wtal.de>
  *
- * $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Attic/dyntest.pgc,v 1.2 2000/02/17 19:48:58 meskes Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Attic/dyntest.pgc,v 1.3 2000/02/22 19:57:12 meskes Exp $
  */
 
 #include <stdio.h>
@@ -30,6 +30,10 @@ int main(int argc,char **argv)
   char QUERY[1024];
   exec sql end declare section;
   int done=0;
+  FILE *dbgs;
+
+  if ((dbgs = fopen("log", "w")) != NULL)
+	ECPGdebug(1, dbgs);
   
   snprintf(QUERY,sizeof QUERY,"select * from %s",argc>1?argv[1]:"pg_tables");
 
@@ -123,5 +127,9 @@ int main(int argc,char **argv)
   exec sql close MYCURS;
   
   exec sql deallocate descriptor MYDESC;
+
+  if (dbgs != NULL)
+	fclose(dbgs);
+
   return 0;
 }
diff --git a/src/interfaces/ecpg/test/test2.pgc b/src/interfaces/ecpg/test/test2.pgc
index 2c5d16c4448773216fd5e7a5879a5b77998b1dda..99175d39a9fee4f482ad11be7c7defb364f8ebde 100644
--- a/src/interfaces/ecpg/test/test2.pgc
+++ b/src/interfaces/ecpg/test/test2.pgc
@@ -47,8 +47,8 @@ exec sql end declare section;
 
 	strcpy(msg, "insert");
 	exec sql insert into meskes(name, married, children) values ('Petra', '19900404', 3);
-	exec sql insert into meskes(name, born, age, married, children) values ('Michael', 19660117, 33, '19900404', 3);
-	exec sql insert into meskes(name, born, age) values ('Carsten', 19910103, 8);
+	exec sql insert into meskes(name, born, age, married, children) values ('Michael', 19660117, 34, '19900404', 3);
+	exec sql insert into meskes(name, born, age) values ('Carsten', 19910103,9);
 	exec sql insert into meskes(name, born, age) values ('Marc', 19930907, 6);
 	exec sql insert into meskes(name, born, age) values ('Chris', 19970923, 2);
 
diff --git a/src/interfaces/ecpg/test/test3.pgc b/src/interfaces/ecpg/test/test3.pgc
index 8ba8995e3347968720abb97291357e520e9fd2fa..9e3e4398df53c2a927515a0552db3f972fd995de 100644
--- a/src/interfaces/ecpg/test/test3.pgc
+++ b/src/interfaces/ecpg/test/test3.pgc
@@ -39,8 +39,8 @@ exec sql end declare section;
 
 	strcpy(msg, "insert");
 	exec sql insert into meskes(name, married, children) values (:wifesname, '19900404', 3);
-	exec sql insert into meskes(name, born, age, married, children) values ('Michael', 19660117, 33, '19900404', 3);
-	exec sql insert into meskes(name, born, age) values ('Carsten', 19910103, 8);
+	exec sql insert into meskes(name, born, age, married, children) values ('Michael', 19660117, 34, '19900404', 3);
+	exec sql insert into meskes(name, born, age) values ('Carsten', 19910103, 9);
 	exec sql insert into meskes(name, born, age) values ('Marc', 19930907, 6);
 	exec sql insert into meskes(name, born, age) values ('Chris', 19970923, 2);