summaryrefslogtreecommitdiff
path: root/src/interfaces/ecpg/ecpglib/descriptor.c
diff options
context:
space:
mode:
authorMichael Meskes <meskes@postgresql.org>2010-01-15 10:44:39 +0000
committerMichael Meskes <meskes@postgresql.org>2010-01-15 10:44:39 +0000
commitbf69b535c028543194997f520bf7761f93166636 (patch)
treeb6a31958e5f06f6a055c5c17f7e2905e609802a5 /src/interfaces/ecpg/ecpglib/descriptor.c
parent40f908bdcdc726fc11912cd95dfd2f89603d1f37 (diff)
Applied patch by Boszormenyi Zoltan <zb@cybertec.at> to add DESCRIBE [OUTPUT] statement to ecpg.
Diffstat (limited to 'src/interfaces/ecpg/ecpglib/descriptor.c')
-rw-r--r--src/interfaces/ecpg/ecpglib/descriptor.c156
1 files changed, 147 insertions, 9 deletions
diff --git a/src/interfaces/ecpg/ecpglib/descriptor.c b/src/interfaces/ecpg/ecpglib/descriptor.c
index 0712e0ba9b6..367081a684d 100644
--- a/src/interfaces/ecpg/ecpglib/descriptor.c
+++ b/src/interfaces/ecpg/ecpglib/descriptor.c
@@ -1,6 +1,6 @@
/* dynamic SQL support routines
*
- * $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.33 2009/08/07 10:51:20 meskes Exp $
+ * $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.34 2010/01/15 10:44:34 meskes Exp $
*/
#define POSTGRES_ECPG_INTERNAL
@@ -13,6 +13,7 @@
#include "ecpgerrno.h"
#include "extern.h"
#include "sqlca.h"
+#include "sqlda.h"
#include "sql3types.h"
static void descriptor_free(struct descriptor * desc);
@@ -226,6 +227,12 @@ get_char_item(int lineno, void *var, enum ECPGttype vartype, char *value, int va
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,...)
{
@@ -244,11 +251,6 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
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))
{
@@ -283,6 +285,7 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
switch (type)
{
case (ECPGd_indicator):
+ RETURN_IF_NO_DATA;
data_var.ind_type = vartype;
data_var.ind_pointer = var;
data_var.ind_varcharsize = varcharsize;
@@ -295,6 +298,7 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
break;
case ECPGd_data:
+ RETURN_IF_NO_DATA;
data_var.type = vartype;
data_var.pointer = var;
data_var.varcharsize = varcharsize;
@@ -377,6 +381,7 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
case ECPGd_ret_length:
case ECPGd_ret_octet:
+ RETURN_IF_NO_DATA;
/*
* this is like ECPGstore_result
*/
@@ -480,6 +485,7 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
sqlca->sqlerrd[2] = ntuples;
return (true);
}
+#undef RETURN_IF_NO_DATA
bool
ECPGset_desc_header(int lineno, const char *desc_name, int count)
@@ -723,8 +729,140 @@ ecpg_find_desc(int line, const char *name)
}
bool
-ECPGdescribe(int line, bool input, const char *statement,...)
+ECPGdescribe(int line, int compat, bool input, const char *connection_name, const char *stmt_name, ...)
{
- ecpg_log("ECPGdescribe called on line %d for %s: %s\n", line, input ? "input" : "output", statement);
- return false;
+ bool ret = false;
+ struct connection *con;
+ struct prepared_statement *prep;
+ PGresult *res;
+ va_list args;
+
+ /* DESCRIBE INPUT is not yet supported */
+ if (input)
+ return ret;
+
+ con = ecpg_get_connection(connection_name);
+ if (!con)
+ return false;
+ prep = ecpg_find_prepared_statement(stmt_name, con, NULL);
+ if (!prep)
+ return ret;
+
+ 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 descriptor *desc = ecpg_find_desc(line, name);
+
+ if (desc == NULL)
+ break;
+
+ res = PQdescribePrepared(con->connection, stmt_name);
+ if (!ecpg_check_PQresult(res, line, con->connection, compat))
+ break;
+
+ if (desc->result != NULL)
+ PQclear(desc->result);
+
+ desc->result = res;
+ ret = true;
+ break;
+ }
+ case ECPGt_sqlda:
+ {
+ if (INFORMIX_MODE(compat))
+ {
+ struct sqlda_compat **_sqlda = ptr;
+ struct sqlda_compat *sqlda;
+
+ res = PQdescribePrepared(con->connection, stmt_name);
+ if (!ecpg_check_PQresult(res, line, con->connection, compat))
+ break;
+
+ sqlda = ecpg_build_compat_sqlda(line, res, -1, compat);
+ if (sqlda)
+ {
+ struct sqlda_compat *sqlda_old = *_sqlda;
+ struct sqlda_compat *sqlda_old1;
+
+ while (sqlda_old)
+ {
+ sqlda_old1 = sqlda_old->desc_next;
+ free(sqlda_old);
+ sqlda_old = sqlda_old1;
+ }
+
+ *_sqlda = sqlda;
+ ret = true;
+ }
+
+ PQclear(res);
+ }
+ else
+ {
+ struct sqlda_struct **_sqlda = ptr;
+ struct sqlda_struct *sqlda;
+
+ res = PQdescribePrepared(con->connection, stmt_name);
+ if (!ecpg_check_PQresult(res, line, con->connection, compat))
+ break;
+
+ sqlda = ecpg_build_native_sqlda(line, res, -1, compat);
+ if (sqlda)
+ {
+ struct sqlda_struct *sqlda_old = *_sqlda;
+ struct sqlda_struct *sqlda_old1;
+
+ while (sqlda_old)
+ {
+ sqlda_old1 = sqlda_old->desc_next;
+ free(sqlda_old);
+ sqlda_old = sqlda_old1;
+ }
+
+ *_sqlda = sqlda;
+ ret = true;
+ }
+
+ PQclear(res);
+ }
+ break;
+ }
+ default:
+ /* nothing else may come */
+ ;
+ }
+ }
+
+ va_end(args);
+
+ return ret;
}