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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy