diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/descriptor.c pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/descriptor.c
*** pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/descriptor.c	2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/descriptor.c	2009-07-14 21:21:46.526800064 +0200
***************
*** 13,18 ****
--- 13,19 ----
  #include "ecpgerrno.h"
  #include "extern.h"
  #include "sqlca.h"
+ #include "sqlda.h"
  #include "sql3types.h"
  
  static void descriptor_free(struct descriptor * desc);
*************** get_char_item(int lineno, void *var, enu
*** 225,230 ****
--- 226,237 ----
  	return (true);
  }
  
+ #define RETURN_IF_NO_DATA	if (ntuples < 1) \
+ 				{ \
+ 					ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL); \
+ 					return (false); \
+ 				}
+ 
  bool
  ECPGget_desc(int lineno, const char *desc_name, int index,...)
  {
*************** ECPGget_desc(int lineno, const char *des
*** 243,253 ****
  		return (false);
  
  	ntuples = PQntuples(ECPGresult);
- 	if (ntuples < 1)
- 	{
- 		ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
- 		return (false);
- 	}
  
  	if (index < 1 || index > PQnfields(ECPGresult))
  	{
--- 250,255 ----
*************** ECPGget_desc(int lineno, const char *des
*** 282,287 ****
--- 284,290 ----
  		switch (type)
  		{
  			case (ECPGd_indicator):
+ 				RETURN_IF_NO_DATA;
  				data_var.ind_type = vartype;
  				data_var.ind_pointer = var;
  				data_var.ind_varcharsize = varcharsize;
*************** ECPGget_desc(int lineno, const char *des
*** 294,299 ****
--- 297,303 ----
  				break;
  
  			case ECPGd_data:
+ 				RETURN_IF_NO_DATA;
  				data_var.type = vartype;
  				data_var.pointer = var;
  				data_var.varcharsize = varcharsize;
*************** ECPGget_desc(int lineno, const char *des
*** 376,381 ****
--- 380,386 ----
  			case ECPGd_ret_length:
  			case ECPGd_ret_octet:
  
+ 				RETURN_IF_NO_DATA;
  				/*
  				 * this is like ECPGstore_result
  				 */
*************** ECPGget_desc(int lineno, const char *des
*** 479,484 ****
--- 484,490 ----
  	sqlca->sqlerrd[2] = ntuples;
  	return (true);
  }
+ #undef RETURN_IF_NO_DATA
  
  bool
  ECPGset_desc_header(int lineno, const char *desc_name, int count)
*************** ecpg_find_desc(int line, const char *nam
*** 721,729 ****
--- 727,846 ----
  	return NULL;				/* not found */
  }
  
+ static pg_sqlda_t*
+ build_sqlda(int lineno, bool input, const char *connection_name, const char *stmt_name)
+ {
+ 	struct connection *con;
+ 	PGresult	*res;
+ 	pg_sqlda_t	*sqlda = NULL;
+ 
+ 	con = ecpg_get_connection(connection_name);
+ 	res = PQdescribePrepared(con->connection, stmt_name);
+ 	if (!ecpg_check_PQresult(res, lineno, con->connection, ECPG_COMPAT_INFORMIX))
+ 		return NULL;
+ 
+ 	sqlda = ecpg_build_sqlda_for_PGresult(lineno, res);
+ 
+ 	PQclear(res);
+ 	return sqlda;
+ }
+ 
+ /* Old, unsupported interface */
  bool
  ECPGdescribe(int line, bool input, const char *statement,...)
  {
  	ecpg_log("ECPGdescribe called on line %d for %s: %s\n", line, input ? "input" : "output", statement);
  	return false;
  }
+ 
+ /* New interface for DESCRIBE [INPUT|OUTPUT], both for named descriptor and Informix-like SQLDA */
+ bool
+ ECPGdescribe2(int line, bool input, const char *connection_name, const char *stmt_name, ...)
+ {
+ 	bool		ret = false;
+ 	va_list		args;
+ 
+ 	/* DESCRIBE INPUT is not yet supported */
+ 	if (input)
+ 		return false;
+ 
+ 	va_start(args, stmt_name);
+ 
+ 	for (;;)
+ 	{
+ 		enum ECPGttype	type, dummy_type;
+ 		void		*ptr, *dummy_ptr;
+ 		long		dummy;
+ 
+ 		/* variable type */
+ 		type = va_arg(args, enum ECPGttype);
+ 
+ 		if (type == ECPGt_EORT)
+ 			break;
+ 
+ 		/* rest of variable parameters*/
+ 		ptr = va_arg(args, void *);
+ 		dummy = va_arg(args, long);
+ 		dummy = va_arg(args, long);
+ 		dummy = va_arg(args, long);
+ 
+ 		/* variable indicator */
+ 		dummy_type = va_arg(args, enum ECPGttype);
+ 		dummy_ptr = va_arg(args, void *);
+ 		dummy = va_arg(args, long);
+ 		dummy = va_arg(args, long);
+ 		dummy = va_arg(args, long);
+ 
+ 		switch (type)
+ 		{
+ 			case ECPGt_descriptor:
+ 			{
+ 				char	*name = ptr;
+ 				struct connection *con = ecpg_get_connection(connection_name);
+ 				struct descriptor *desc = ecpg_find_desc(line, name);
+ 				PGresult	*res;
+ 				ExecStatusType  ret;
+ 
+ 				if (con == NULL)
+ 					break;
+ 				if (desc == NULL)
+ 					break;
+ 
+ 				res = PQdescribePrepared(con->connection, stmt_name);
+ 				ret = PQresultStatus(res);
+ 				if (ecpg_check_PQresult(res, line, con->connection, ECPG_COMPAT_PGSQL))
+ 				{
+ 					if (desc->result != NULL)
+ 						PQclear(desc->result);
+ 					desc->result = res;
+ 					ret = true;
+ 				}
+ 				break;
+ 			}
+ 			case ECPGt_sqlda:
+ 			{
+ 				pg_sqlda_t **sqlda_ptr = ptr;
+ 				pg_sqlda_t *sqlda_new;
+ 
+ 				sqlda_new = build_sqlda(line, input, connection_name, stmt_name);
+ 				if (sqlda_new)
+ 				{
+ 					/* slight leak */
+ #if 0
+ 					pg_sqlda_t *sqlda_old = *sqlda_ptr;
+ 					if (sqlda_old)
+ 						free(sqlda_old); */
+ #endif
+ 					*sqlda_ptr = sqlda_new;
+ 					ret = true;
+ 				}
+ 				break;
+ 			}
+ 			default:
+ 				/* nothing else may come */
+ 				;
+ 		}
+ 	}
+ 
+ 	return ret;
+ }
diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/execute.c pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/execute.c
*** pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/execute.c	2009-07-14 20:10:28.107831473 +0200
--- pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/execute.c	2009-07-14 21:25:02.120803120 +0200
*************** ecpg_store_input(const int lineno, const
*** 1032,1037 ****
--- 1032,1039 ----
  				break;
  
  			case ECPGt_descriptor:
+ 				break;
+ 
  			case ECPGt_sqlda:
  				break;
  
*************** ecpg_execute(struct statement * stmt)
*** 1176,1182 ****
  		{
  			pg_sqlda_t	  **_sqlda = (pg_sqlda_t **)var->pointer;
  			pg_sqlda_t	   *sqlda = *_sqlda;
! 			struct variable desc_inlist;
  			int		i;
  
  			if (sqlda == NULL)
--- 1178,1184 ----
  		{
  			pg_sqlda_t	  **_sqlda = (pg_sqlda_t **)var->pointer;
  			pg_sqlda_t	   *sqlda = *_sqlda;
! 			struct variable	desc_inlist;
  			int		i;
  
  			if (sqlda == NULL)
*************** ecpg_execute(struct statement * stmt)
*** 1201,1207 ****
  							break;
  					}
  					desc_inlist.arrsize = 1;
! 					desc_inlist.offset = 0; 
  					if (sqlda->sqlvar[i].sqlind)
  					{
  						desc_inlist.ind_type = ECPGt_short;
--- 1203,1209 ----
  							break;
  					}
  					desc_inlist.arrsize = 1;
! 					desc_inlist.offset = 0;
  					if (sqlda->sqlvar[i].sqlind)
  					{
  						desc_inlist.ind_type = ECPGt_short;
diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/exports.txt pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/exports.txt
*** pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/exports.txt	2008-03-25 13:58:49.000000000 +0100
--- pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/exports.txt	2009-07-14 21:21:46.532799432 +0200
*************** ECPGstatus                       23
*** 26,28 ****
--- 26,29 ----
  ECPGtrans                        24
  sqlprint                         25
  ECPGget_PGconn			 26
+ ECPGdescribe2			 27
diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/typename.c pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/typename.c
*** pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/typename.c	2009-07-14 20:25:37.012801219 +0200
--- pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/typename.c	2009-07-14 21:25:45.229800483 +0200
*************** ecpg_sqlda_type(int type)
*** 149,155 ****
  			return (-type);
  	}
  }
!  
  int
  ecpg_to_sqlda_type(Oid type)
  {
--- 149,155 ----
  			return (-type);
  	}
  }
! 
  int
  ecpg_to_sqlda_type(Oid type)
  {
diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/include/ecpglib.h pgsql85dev.3describe/src/interfaces/ecpg/include/ecpglib.h
*** pgsql85dev.2sqlda/src/interfaces/ecpg/include/ecpglib.h	2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.3describe/src/interfaces/ecpg/include/ecpglib.h	2009-07-14 21:21:46.533800118 +0200
*************** bool		ECPGset_desc(int, const char *, in
*** 84,89 ****
--- 84,90 ----
  void		ECPGset_noind_null(enum ECPGttype, void *);
  bool		ECPGis_noind_null(enum ECPGttype, void *);
  bool		ECPGdescribe(int, bool, const char *,...);
+ bool		ECPGdescribe2(int, bool, const char *, const char *, ...);
  
  /* dynamic result allocation */
  void		ECPGfree_auto_mem(void);
diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.addons pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.addons	2009-07-14 20:58:07.915799679 +0200
--- pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.addons	2009-07-14 21:26:31.594800717 +0200
*************** ECPG: stmtViewStmt rule
*** 84,90 ****
  	}
  	| ECPGDescribe
  	{
! 		fprintf(yyout, "{ ECPGdescribe(__LINE__, %s,", $1);
  		dump_variables(argsresult, 1);
  		fputs("ECPGt_EORT);", yyout);
  		fprintf(yyout, "}");
--- 84,90 ----
  	}
  	| ECPGDescribe
  	{
! 		fprintf(yyout, "{ ECPGdescribe2(__LINE__, %s,", $1);
  		dump_variables(argsresult, 1);
  		fputs("ECPGt_EORT);", yyout);
  		fprintf(yyout, "}");
*************** ECPG: VariableShowStmtSHOWALL block
*** 341,347 ****
  		mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented");
  		$$ = EMPTY;
  	}
! ECPG: FetchStmtFETCHBACKWARDfrom_incursor_name block 
  	{
  		char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
  		add_additional_variables($4, false);
--- 341,347 ----
  		mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented");
  		$$ = EMPTY;
  	}
! ECPG: FetchStmtFETCHBACKWARDfrom_incursor_name block
  	{
  		char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
  		add_additional_variables($4, false);
diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.trailer pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.trailer	2009-07-14 21:14:32.475802236 +0200
--- pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.trailer	2009-07-14 21:27:26.131801570 +0200
*************** ECPGCursorStmt:  DECLARE cursor_name cur
*** 321,327 ****
  				add_variable_to_head(&(this->argsinsert), var, &no_indicator);
  			}
  			add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
- 
  			cur = this;
  
  			$$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
--- 321,326 ----
*************** into_descriptor: INTO opt_sql SQL_DESCRI
*** 1012,1017 ****
--- 1011,1023 ----
  		}
  		;
  
+ into_sqlda: INTO name
+ 		{
+ 			add_variable_to_head(&argsresult, sqlda_variable($2), &no_indicator);
+ 			$$ = EMPTY;
+ 		}
+ 		;
+ 
  opt_sql: /*EMPTY*/		{ $$ = EMPTY; }
  		| SQL_SQL	{ $$ = make_str("sql"); }
  		;
*************** ECPGDescribe: SQL_DESCRIBE INPUT_P name 
*** 1047,1068 ****
  	{
  		const char *con = connection ? connection : "NULL";
  		mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement");
! 		$$ = (char *) mm_alloc(sizeof("1, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
! 		sprintf($$, "1, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
  	}
  	| SQL_DESCRIBE opt_output name using_descriptor
  	{
  		const char *con = connection ? connection : "NULL";
! 		mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement");
! 		$$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
! 		sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
  	}
  	| SQL_DESCRIBE opt_output name into_descriptor
  	{
  		const char *con = connection ? connection : "NULL";
  		mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement");
! 		$$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
! 		sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
  	}
  	;
  
--- 1053,1085 ----
  	{
  		const char *con = connection ? connection : "NULL";
  		mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement");
! 		$$ = (char *) mm_alloc(sizeof("1, , \"\"") + strlen(con) + strlen($3));
! 		sprintf($$, "1, %s, \"%s\"", con, $3);
  	}
  	| SQL_DESCRIBE opt_output name using_descriptor
  	{
  		const char *con = connection ? connection : "NULL";
! 		$$ = (char *) mm_alloc(sizeof("0, , \"\"") + strlen(con) + strlen($3));
! 		sprintf($$, "0, %s, \"%s\"", con, $3);
  	}
  	| SQL_DESCRIBE opt_output name into_descriptor
  	{
  		const char *con = connection ? connection : "NULL";
+ 		$$ = (char *) mm_alloc(sizeof("0, , \"\"") + strlen(con) + strlen($3));
+ 		sprintf($$, "0, %s, \"%s\"", con, $3);
+ 	}
+ 	| SQL_DESCRIBE INPUT_P name into_sqlda
+ 	{
+ 		const char *con = connection ? connection : "NULL";
  		mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement");
! 		$$ = (char *) mm_alloc(sizeof("1, , \"\"") + strlen(con) + strlen($3));
! 		sprintf($$, "1, %s, \"%s\"", con, $3);
! 	}
! 	| SQL_DESCRIBE opt_output name into_sqlda
! 	{
! 		const char *con = connection ? connection : "NULL";
! 		$$ = (char *) mm_alloc(sizeof("0, , \"\"") + strlen(con) + strlen($3));
! 		sprintf($$, "0, %s, \"%s\"", con, $3);
  	}
  	;
  
diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.type pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.type
*** pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.type	2009-07-14 21:12:50.123800876 +0200
--- pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.type	2009-07-14 21:28:11.510799354 +0200
***************
*** 72,77 ****
--- 72,78 ----
  %type <str> execute_rest
  %type <str> indicator
  %type <str> into_descriptor
+ %type <str> into_sqlda
  %type <str> Iresult
  %type <str> on_off
  %type <str> opt_bit_field
***************
*** 86,92 ****
  %type <str> opt_reference
  %type <str> opt_scale
  %type <str> opt_server
! %type <str> opt_sql   
  %type <str> opt_user
  %type <str> opt_opt_value
  %type <str> ora_user
--- 87,93 ----
  %type <str> opt_reference
  %type <str> opt_scale
  %type <str> opt_server
! %type <str> opt_sql
  %type <str> opt_user
  %type <str> opt_opt_value
  %type <str> ora_user
