Skip to content

Commit bf69b53

Browse files
author
Michael Meskes
committed
Applied patch by Boszormenyi Zoltan <zb@cybertec.at> to add DESCRIBE [OUTPUT] statement to ecpg.
1 parent 40f908b commit bf69b53

22 files changed

+2443
-45
lines changed

src/interfaces/ecpg/ecpglib/descriptor.c

Lines changed: 147 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* dynamic SQL support routines
22
*
3-
* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.33 2009/08/07 10:51:20 meskes Exp $
3+
* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.34 2010/01/15 10:44:34 meskes Exp $
44
*/
55

66
#define POSTGRES_ECPG_INTERNAL
@@ -13,6 +13,7 @@
1313
#include "ecpgerrno.h"
1414
#include "extern.h"
1515
#include "sqlca.h"
16+
#include "sqlda.h"
1617
#include "sql3types.h"
1718

1819
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
226227
return (true);
227228
}
228229

230+
#define RETURN_IF_NO_DATA if (ntuples < 1) \
231+
{ \
232+
ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL); \
233+
return (false); \
234+
}
235+
229236
bool
230237
ECPGget_desc(int lineno, const char *desc_name, int index,...)
231238
{
@@ -244,11 +251,6 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
244251
return (false);
245252

246253
ntuples = PQntuples(ECPGresult);
247-
if (ntuples < 1)
248-
{
249-
ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
250-
return (false);
251-
}
252254

253255
if (index < 1 || index > PQnfields(ECPGresult))
254256
{
@@ -283,6 +285,7 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
283285
switch (type)
284286
{
285287
case (ECPGd_indicator):
288+
RETURN_IF_NO_DATA;
286289
data_var.ind_type = vartype;
287290
data_var.ind_pointer = var;
288291
data_var.ind_varcharsize = varcharsize;
@@ -295,6 +298,7 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
295298
break;
296299

297300
case ECPGd_data:
301+
RETURN_IF_NO_DATA;
298302
data_var.type = vartype;
299303
data_var.pointer = var;
300304
data_var.varcharsize = varcharsize;
@@ -377,6 +381,7 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
377381
case ECPGd_ret_length:
378382
case ECPGd_ret_octet:
379383

384+
RETURN_IF_NO_DATA;
380385
/*
381386
* this is like ECPGstore_result
382387
*/
@@ -480,6 +485,7 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
480485
sqlca->sqlerrd[2] = ntuples;
481486
return (true);
482487
}
488+
#undef RETURN_IF_NO_DATA
483489

484490
bool
485491
ECPGset_desc_header(int lineno, const char *desc_name, int count)
@@ -723,8 +729,140 @@ ecpg_find_desc(int line, const char *name)
723729
}
724730

725731
bool
726-
ECPGdescribe(int line, bool input, const char *statement,...)
732+
ECPGdescribe(int line, int compat, bool input, const char *connection_name, const char *stmt_name, ...)
727733
{
728-
ecpg_log("ECPGdescribe called on line %d for %s: %s\n", line, input ? "input" : "output", statement);
729-
return false;
734+
bool ret = false;
735+
struct connection *con;
736+
struct prepared_statement *prep;
737+
PGresult *res;
738+
va_list args;
739+
740+
/* DESCRIBE INPUT is not yet supported */
741+
if (input)
742+
return ret;
743+
744+
con = ecpg_get_connection(connection_name);
745+
if (!con)
746+
return false;
747+
prep = ecpg_find_prepared_statement(stmt_name, con, NULL);
748+
if (!prep)
749+
return ret;
750+
751+
va_start(args, stmt_name);
752+
753+
for (;;)
754+
{
755+
enum ECPGttype type, dummy_type;
756+
void *ptr, *dummy_ptr;
757+
long dummy;
758+
759+
/* variable type */
760+
type = va_arg(args, enum ECPGttype);
761+
762+
if (type == ECPGt_EORT)
763+
break;
764+
765+
/* rest of variable parameters*/
766+
ptr = va_arg(args, void *);
767+
dummy = va_arg(args, long);
768+
dummy = va_arg(args, long);
769+
dummy = va_arg(args, long);
770+
771+
/* variable indicator */
772+
dummy_type = va_arg(args, enum ECPGttype);
773+
dummy_ptr = va_arg(args, void *);
774+
dummy = va_arg(args, long);
775+
dummy = va_arg(args, long);
776+
dummy = va_arg(args, long);
777+
778+
switch (type)
779+
{
780+
case ECPGt_descriptor:
781+
{
782+
char *name = ptr;
783+
struct descriptor *desc = ecpg_find_desc(line, name);
784+
785+
if (desc == NULL)
786+
break;
787+
788+
res = PQdescribePrepared(con->connection, stmt_name);
789+
if (!ecpg_check_PQresult(res, line, con->connection, compat))
790+
break;
791+
792+
if (desc->result != NULL)
793+
PQclear(desc->result);
794+
795+
desc->result = res;
796+
ret = true;
797+
break;
798+
}
799+
case ECPGt_sqlda:
800+
{
801+
if (INFORMIX_MODE(compat))
802+
{
803+
struct sqlda_compat **_sqlda = ptr;
804+
struct sqlda_compat *sqlda;
805+
806+
res = PQdescribePrepared(con->connection, stmt_name);
807+
if (!ecpg_check_PQresult(res, line, con->connection, compat))
808+
break;
809+
810+
sqlda = ecpg_build_compat_sqlda(line, res, -1, compat);
811+
if (sqlda)
812+
{
813+
struct sqlda_compat *sqlda_old = *_sqlda;
814+
struct sqlda_compat *sqlda_old1;
815+
816+
while (sqlda_old)
817+
{
818+
sqlda_old1 = sqlda_old->desc_next;
819+
free(sqlda_old);
820+
sqlda_old = sqlda_old1;
821+
}
822+
823+
*_sqlda = sqlda;
824+
ret = true;
825+
}
826+
827+
PQclear(res);
828+
}
829+
else
830+
{
831+
struct sqlda_struct **_sqlda = ptr;
832+
struct sqlda_struct *sqlda;
833+
834+
res = PQdescribePrepared(con->connection, stmt_name);
835+
if (!ecpg_check_PQresult(res, line, con->connection, compat))
836+
break;
837+
838+
sqlda = ecpg_build_native_sqlda(line, res, -1, compat);
839+
if (sqlda)
840+
{
841+
struct sqlda_struct *sqlda_old = *_sqlda;
842+
struct sqlda_struct *sqlda_old1;
843+
844+
while (sqlda_old)
845+
{
846+
sqlda_old1 = sqlda_old->desc_next;
847+
free(sqlda_old);
848+
sqlda_old = sqlda_old1;
849+
}
850+
851+
*_sqlda = sqlda;
852+
ret = true;
853+
}
854+
855+
PQclear(res);
856+
}
857+
break;
858+
}
859+
default:
860+
/* nothing else may come */
861+
;
862+
}
863+
}
864+
865+
va_end(args);
866+
867+
return ret;
730868
}

src/interfaces/ecpg/ecpglib/extern.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.36 2010/01/05 16:38:23 meskes Exp $ */
1+
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.37 2010/01/15 10:44:34 meskes Exp $ */
22

33
#ifndef _ECPG_LIB_EXTERN_H
44
#define _ECPG_LIB_EXTERN_H
@@ -60,6 +60,15 @@ struct statement
6060
struct variable *outlist;
6161
};
6262

63+
/* structure to store prepared statements for a connection */
64+
struct prepared_statement
65+
{
66+
char *name;
67+
bool prepared;
68+
struct statement *stmt;
69+
struct prepared_statement *next;
70+
};
71+
6372
/* structure to store connections */
6473
struct connection
6574
{
@@ -139,6 +148,9 @@ struct descriptor *ecpggetdescp(int, char *);
139148

140149
struct descriptor *ecpg_find_desc(int line, const char *name);
141150

151+
struct prepared_statement *ecpg_find_prepared_statement(const char *,
152+
struct connection *, struct prepared_statement **);
153+
142154
bool ecpg_store_result(const PGresult *results, int act_field,
143155
const struct statement * stmt, struct variable * var);
144156
bool ecpg_store_input(const int, const bool, const struct variable *, char **, bool);

src/interfaces/ecpg/ecpglib/prepare.c

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.33 2009/10/15 10:20:15 meskes Exp $ */
1+
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.34 2010/01/15 10:44:34 meskes Exp $ */
22

33
#define POSTGRES_ECPG_INTERNAL
44
#include "postgres_fe.h"
@@ -11,14 +11,6 @@
1111
#include "extern.h"
1212
#include "sqlca.h"
1313

14-
struct prepared_statement
15-
{
16-
char *name;
17-
bool prepared;
18-
struct statement *stmt;
19-
struct prepared_statement *next;
20-
};
21-
2214
#define STMTID_SIZE 32
2315

2416
typedef struct
@@ -35,8 +27,6 @@ static const int stmtCacheNBuckets = 2039; /* # buckets - a prime # */
3527
static const int stmtCacheEntPerBucket = 8; /* # entries/bucket */
3628
static stmtCacheEntry stmtCacheEntries[16384] = {{0, {0}, 0, 0, 0}};
3729

38-
static struct prepared_statement *find_prepared_statement(const char *name,
39-
struct connection * con, struct prepared_statement ** prev);
4030
static bool deallocate_one(int lineno, enum COMPAT_MODE c, struct connection * con,
4131
struct prepared_statement * prev, struct prepared_statement * this);
4232

@@ -126,7 +116,7 @@ ECPGprepare(int lineno, const char *connection_name, const bool questionmarks, c
126116
return false;
127117

128118
/* check if we already have prepared this statement */
129-
this = find_prepared_statement(name, con, &prev);
119+
this = ecpg_find_prepared_statement(name, con, &prev);
130120
if (this && !deallocate_one(lineno, ECPG_COMPAT_PGSQL, con, prev, this))
131121
return false;
132122

@@ -179,8 +169,8 @@ ECPGprepare(int lineno, const char *connection_name, const bool questionmarks, c
179169
return true;
180170
}
181171

182-
static struct prepared_statement *
183-
find_prepared_statement(const char *name,
172+
struct prepared_statement *
173+
ecpg_find_prepared_statement(const char *name,
184174
struct connection * con, struct prepared_statement ** prev_)
185175
{
186176
struct prepared_statement *this,
@@ -262,7 +252,7 @@ ECPGdeallocate(int lineno, int c, const char *connection_name, const char *name)
262252
if (!ecpg_init(con, connection_name, lineno))
263253
return false;
264254

265-
this = find_prepared_statement(name, con, &prev);
255+
this = ecpg_find_prepared_statement(name, con, &prev);
266256
if (this)
267257
return deallocate_one(lineno, c, con, prev, this);
268258

@@ -297,7 +287,7 @@ ecpg_prepared(const char *name, struct connection * con)
297287
{
298288
struct prepared_statement *this;
299289

300-
this = find_prepared_statement(name, con, NULL);
290+
this = ecpg_find_prepared_statement(name, con, NULL);
301291
return this ? this->stmt->command : NULL;
302292
}
303293

@@ -394,7 +384,7 @@ ecpg_freeStmtCacheEntry(int lineno, int compat, int entNo) /* entry # to free *
394384
con = ecpg_get_connection(entry->connection);
395385

396386
/* free the 'prepared_statement' list entry */
397-
this = find_prepared_statement(entry->stmtID, con, &prev);
387+
this = ecpg_find_prepared_statement(entry->stmtID, con, &prev);
398388
if (this && !deallocate_one(lineno, compat, con, prev, this))
399389
return (-1);
400390

src/interfaces/ecpg/include/ecpglib.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* this is a small part of c.h since we don't want to leak all postgres
33
* definitions into ecpg programs
4-
* $PostgreSQL: pgsql/src/interfaces/ecpg/include/ecpglib.h,v 1.80 2009/09/18 13:13:32 meskes Exp $
4+
* $PostgreSQL: pgsql/src/interfaces/ecpg/include/ecpglib.h,v 1.81 2010/01/15 10:44:36 meskes Exp $
55
*/
66

77
#ifndef _ECPGLIB_H
@@ -83,7 +83,7 @@ bool ECPGset_desc(int, const char *, int,...);
8383

8484
void ECPGset_noind_null(enum ECPGttype, void *);
8585
bool ECPGis_noind_null(enum ECPGttype, void *);
86-
bool ECPGdescribe(int, bool, const char *,...);
86+
bool ECPGdescribe(int, int, bool, const char *, const char *, ...);
8787

8888
/* dynamic result allocation */
8989
void ECPGfree_auto_mem(void);

src/interfaces/ecpg/preproc/ecpg.addons

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.13 2010/01/05 16:38:23 meskes Exp $ */
1+
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.14 2010/01/15 10:44:37 meskes Exp $ */
22
ECPG: stmtClosePortalStmt block
33
{
44
if (INFORMIX_MODE)
@@ -84,7 +84,7 @@ ECPG: stmtViewStmt rule
8484
}
8585
| ECPGDescribe
8686
{
87-
fprintf(yyout, "{ ECPGdescribe(__LINE__, %s,", $1);
87+
fprintf(yyout, "{ ECPGdescribe(__LINE__, %d, %s,", compat, $1);
8888
dump_variables(argsresult, 1);
8989
fputs("ECPGt_EORT);", yyout);
9090
fprintf(yyout, "}");

0 commit comments

Comments
 (0)