PostgreSQL Source Code git master
prepare.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include "ecpgerrno.h"
#include "ecpglib.h"
#include "ecpglib_extern.h"
#include "ecpgtype.h"
#include "sqlca.h"
Include dependency graph for prepare.c:

Go to the source code of this file.

Data Structures

struct  stmtCacheEntry
 

Macros

#define POSTGRES_ECPG_INTERNAL
 
#define STMTID_SIZE   32
 
#define stmtCacheNBuckets   2039 /* should be a prime number */
 
#define stmtCacheEntPerBucket   8
 
#define stmtCacheArraySize   (stmtCacheNBuckets * stmtCacheEntPerBucket + 1)
 

Functions

static bool deallocate_one (int lineno, enum COMPAT_MODE c, struct connection *con, struct prepared_statement *prev, struct prepared_statement *this)
 
static bool isvarchar (unsigned char c)
 
bool ecpg_register_prepared_stmt (struct statement *stmt)
 
static bool replace_variables (char **text, int lineno)
 
static bool prepare_common (int lineno, struct connection *con, const char *name, const char *variable)
 
bool ECPGprepare (int lineno, const char *connection_name, const bool questionmarks, const char *name, const char *variable)
 
struct prepared_statementecpg_find_prepared_statement (const char *name, struct connection *con, struct prepared_statement **prev_)
 
bool ECPGdeallocate (int lineno, int c, const char *connection_name, const char *name)
 
bool ecpg_deallocate_all_conn (int lineno, enum COMPAT_MODE c, struct connection *con)
 
bool ECPGdeallocate_all (int lineno, int compat, const char *connection_name)
 
char * ecpg_prepared (const char *name, struct connection *con)
 
char * ECPGprepared_statement (const char *connection_name, const char *name, int lineno)
 
static int HashStmt (const char *ecpgQuery)
 
static int SearchStmtCache (const char *ecpgQuery)
 
static int ecpg_freeStmtCacheEntry (int lineno, int compat, int entNo)
 
static int AddStmtToCache (int lineno, const char *stmtID, const char *connection, int compat, const char *ecpgQuery)
 
bool ecpg_auto_prepare (int lineno, const char *connection_name, const int compat, char **name, const char *query)
 

Variables

static int nextStmtID = 1
 
static stmtCacheEntrystmtCacheEntries = NULL
 

Macro Definition Documentation

◆ POSTGRES_ECPG_INTERNAL

#define POSTGRES_ECPG_INTERNAL

Definition at line 3 of file prepare.c.

◆ stmtCacheArraySize

#define stmtCacheArraySize   (stmtCacheNBuckets * stmtCacheEntPerBucket + 1)

Definition at line 26 of file prepare.c.

◆ stmtCacheEntPerBucket

#define stmtCacheEntPerBucket   8

Definition at line 24 of file prepare.c.

◆ stmtCacheNBuckets

#define stmtCacheNBuckets   2039 /* should be a prime number */

Definition at line 23 of file prepare.c.

◆ STMTID_SIZE

#define STMTID_SIZE   32

Definition at line 14 of file prepare.c.

Function Documentation

◆ AddStmtToCache()

static int AddStmtToCache ( int  lineno,
const char *  stmtID,
const char *  connection,
int  compat,
const char *  ecpgQuery 
)
static

Definition at line 523 of file prepare.c.

528{
529 int ix,
530 initEntNo,
531 luEntNo,
532 entNo;
533 stmtCacheEntry *entry;
534
535 /* allocate and zero cache array if we haven't already */
536 if (stmtCacheEntries == NULL)
537 {
540 if (stmtCacheEntries == NULL)
541 return -1;
542 }
543
544 /* hash the statement */
545 initEntNo = HashStmt(ecpgQuery);
546
547 /* search for an unused entry */
548 entNo = initEntNo; /* start with the initial entry # for the
549 * bucket */
550 luEntNo = initEntNo; /* use it as the initial 'least used' entry */
551 for (ix = 0; ix < stmtCacheEntPerBucket; ++ix)
552 {
553 entry = &stmtCacheEntries[entNo];
554 if (!entry->stmtID[0]) /* unused entry - use it */
555 break;
556 if (entry->execs < stmtCacheEntries[luEntNo].execs)
557 luEntNo = entNo; /* save new 'least used' entry */
558 ++entNo; /* increment entry # */
559 }
560
561 /*
562 * if no unused entries were found, re-use the 'least used' entry found in
563 * the bucket
564 */
565 if (ix >= stmtCacheEntPerBucket)
566 entNo = luEntNo;
567
568 /* 'entNo' is the entry to use - make sure its free */
569 if (ecpg_freeStmtCacheEntry(lineno, compat, entNo) < 0)
570 return -1;
571
572 /* add the query to the entry */
573 entry = &stmtCacheEntries[entNo];
574 entry->lineno = lineno;
575 entry->ecpgQuery = ecpg_strdup(ecpgQuery, lineno, NULL);
576 if (!entry->ecpgQuery)
577 return -1;
578 entry->connection = connection;
579 entry->execs = 0;
580 memcpy(entry->stmtID, stmtID, sizeof(entry->stmtID));
581
582 return entNo;
583}
enum COMPAT_MODE compat
Definition: ecpg.c:26
char * ecpg_strdup(const char *string, int lineno, bool *alloc_failed)
Definition: memory.c:54
char * ecpg_alloc(long size, int lineno)
Definition: memory.c:19
static int ecpg_freeStmtCacheEntry(int lineno, int compat, int entNo)
Definition: prepare.c:483
static int HashStmt(const char *ecpgQuery)
Definition: prepare.c:411
#define stmtCacheEntPerBucket
Definition: prepare.c:24
static stmtCacheEntry * stmtCacheEntries
Definition: prepare.c:38
#define stmtCacheArraySize
Definition: prepare.c:26
char * connection
char stmtID[STMTID_SIZE]
Definition: prepare.c:31
const char * connection
Definition: prepare.c:34
long execs
Definition: prepare.c:33
char * ecpgQuery
Definition: prepare.c:32

References compat, stmtCacheEntry::connection, connection, ecpg_alloc(), ecpg_freeStmtCacheEntry(), ecpg_strdup(), stmtCacheEntry::ecpgQuery, stmtCacheEntry::execs, HashStmt(), stmtCacheEntry::lineno, stmtCacheArraySize, stmtCacheEntPerBucket, stmtCacheEntries, and stmtCacheEntry::stmtID.

Referenced by ecpg_auto_prepare().

◆ deallocate_one()

static bool deallocate_one ( int  lineno,
enum COMPAT_MODE  c,
struct connection con,
struct prepared_statement prev,
struct prepared_statement this 
)
static

Definition at line 292 of file prepare.c.

294{
295 bool r = false;
296
297 ecpg_log("deallocate_one on line %d: name %s\n", lineno, this->name);
298
299 /* first deallocate the statement in the backend */
300 if (this->prepared)
301 {
302 char *text;
303 PGresult *query;
304
305 text = ecpg_alloc(strlen("deallocate \"\" ") + strlen(this->name), this->stmt->lineno);
306
307 if (text)
308 {
309 sprintf(text, "deallocate \"%s\"", this->name);
310 query = PQexec(this->stmt->connection->connection, text);
312 if (ecpg_check_PQresult(query, lineno,
313 this->stmt->connection->connection,
314 this->stmt->compat))
315 {
316 PQclear(query);
317 r = true;
318 }
319 }
320 }
321
322 /*
323 * Just ignore all errors since we do not know the list of cursors we are
324 * allowed to free. We have to trust the software.
325 */
326 if (!r && !INFORMIX_MODE(c))
327 {
329 return false;
330 }
331
332 /* okay, free all the resources */
333 ecpg_free(this->stmt->command);
334 ecpg_free(this->stmt);
335 ecpg_free(this->name);
336 if (prev != NULL)
337 prev->next = this->next;
338 else
339 con->prep_stmts = this->next;
340
341 ecpg_free(this);
342 return true;
343}
static int32 next
Definition: blutils.c:224
struct varlena text
Definition: c.h:708
#define ECPG_INVALID_STMT
Definition: ecpgerrno.h:39
bool ecpg_check_PQresult(PGresult *results, int lineno, PGconn *connection, enum COMPAT_MODE compat)
Definition: error.c:281
void ecpg_log(const char *format,...) pg_attribute_printf(1
#define INFORMIX_MODE(X)
void ecpg_raise(int line, int code, const char *sqlstate, const char *str)
Definition: error.c:13
void ecpg_free(void *ptr)
Definition: memory.c:13
#define ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2279
#define stmt
Definition: indent_codes.h:59
#define PQclear
Definition: libpq-be-fe.h:245
#define sprintf
Definition: port.h:262
char * c
struct prepared_statement * prep_stmts
struct statement * stmt
struct prepared_statement * next
enum COMPAT_MODE compat
Definition: c.h:695
const char * name

References ecpg_alloc(), ecpg_check_PQresult(), ecpg_free(), ECPG_INVALID_STMT, ecpg_log(), ecpg_raise(), ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, INFORMIX_MODE, name, next, prepared_statement::next, PQclear, PQexec(), connection::prep_stmts, prepared_statement::prepared, sprintf, and stmt.

Referenced by ecpg_deallocate_all_conn(), ecpg_freeStmtCacheEntry(), ecpg_register_prepared_stmt(), ECPGdeallocate(), and ECPGprepare().

◆ ecpg_auto_prepare()

bool ecpg_auto_prepare ( int  lineno,
const char *  connection_name,
const int  compat,
char **  name,
const char *  query 
)

Definition at line 587 of file prepare.c.

588{
589 int entNo;
590
591 /* search the statement cache for this statement */
592 entNo = SearchStmtCache(query);
593
594 /* if not found - add the statement to the cache */
595 if (entNo)
596 {
597 char *stmtID;
598 struct connection *con;
599 struct prepared_statement *prep;
600
601 ecpg_log("ecpg_auto_prepare on line %d: statement found in cache; entry %d\n", lineno, entNo);
602
603 stmtID = stmtCacheEntries[entNo].stmtID;
604 *name = ecpg_strdup(stmtID, lineno, NULL);
605 if (*name == NULL)
606 return false;
607
608 con = ecpg_get_connection(connection_name);
609 prep = ecpg_find_prepared_statement(stmtID, con, NULL);
610 /* This prepared name doesn't exist on this connection. */
611 if (!prep && !prepare_common(lineno, con, stmtID, query))
612 {
613 ecpg_free(*name);
614 return false;
615 }
616
617 }
618 else
619 {
620 char stmtID[STMTID_SIZE];
621
622 ecpg_log("ecpg_auto_prepare on line %d: statement not in cache; inserting\n", lineno);
623
624 /* generate a statement ID */
625 sprintf(stmtID, "ecpg%d", nextStmtID++);
626 *name = ecpg_strdup(stmtID, lineno, NULL);
627 if (*name == NULL)
628 return false;
629
630 if (!ECPGprepare(lineno, connection_name, 0, stmtID, query))
631 {
632 ecpg_free(*name);
633 return false;
634 }
635
636 entNo = AddStmtToCache(lineno, stmtID, connection_name, compat, query);
637 if (entNo < 0)
638 {
639 ecpg_free(*name);
640 return false;
641 }
642 }
643
644 /* increase usage counter */
645 stmtCacheEntries[entNo].execs++;
646
647 return true;
648}
struct connection * ecpg_get_connection(const char *connection_name)
Definition: connect.c:76
static bool prepare_common(int lineno, struct connection *con, const char *name, const char *variable)
Definition: prepare.c:172
static int nextStmtID
Definition: prepare.c:37
static int AddStmtToCache(int lineno, const char *stmtID, const char *connection, int compat, const char *ecpgQuery)
Definition: prepare.c:523
static int SearchStmtCache(const char *ecpgQuery)
Definition: prepare.c:447
bool ECPGprepare(int lineno, const char *connection_name, const bool questionmarks, const char *name, const char *variable)
Definition: prepare.c:249
#define STMTID_SIZE
Definition: prepare.c:14
struct prepared_statement * ecpg_find_prepared_statement(const char *name, struct connection *con, struct prepared_statement **prev_)
Definition: prepare.c:271
Definition: type.h:109

References AddStmtToCache(), compat, ecpg_find_prepared_statement(), ecpg_free(), ecpg_get_connection(), ecpg_log(), ecpg_strdup(), ECPGprepare(), stmtCacheEntry::execs, name, nextStmtID, prepare_common(), SearchStmtCache(), sprintf, stmtCacheEntries, stmtCacheEntry::stmtID, and STMTID_SIZE.

Referenced by ecpg_do_prologue().

◆ ecpg_deallocate_all_conn()

bool ecpg_deallocate_all_conn ( int  lineno,
enum COMPAT_MODE  c,
struct connection con 
)

Definition at line 369 of file prepare.c.

370{
371 /* deallocate all prepared statements */
372 while (con->prep_stmts)
373 {
374 if (!deallocate_one(lineno, c, con, NULL, con->prep_stmts))
375 return false;
376 }
377
378 return true;
379}
static bool deallocate_one(int lineno, enum COMPAT_MODE c, struct connection *con, struct prepared_statement *prev, struct prepared_statement *this)
Definition: prepare.c:292

References deallocate_one(), and connection::prep_stmts.

Referenced by ecpg_finish(), and ECPGdeallocate_all().

◆ ecpg_find_prepared_statement()

struct prepared_statement * ecpg_find_prepared_statement ( const char *  name,
struct connection con,
struct prepared_statement **  prev_ 
)

Definition at line 271 of file prepare.c.

273{
274 struct prepared_statement *this,
275 *prev;
276
277 for (this = con->prep_stmts, prev = NULL;
278 this != NULL;
279 prev = this, this = this->next)
280 {
281 if (strcmp(this->name, name) == 0)
282 {
283 if (prev_)
284 *prev_ = prev;
285 return this;
286 }
287 }
288 return NULL;
289}

References name, prepared_statement::next, and connection::prep_stmts.

Referenced by ecpg_auto_prepare(), ecpg_freeStmtCacheEntry(), ecpg_prepared(), ecpg_register_prepared_stmt(), ECPGdeallocate(), ECPGdescribe(), and ECPGprepare().

◆ ecpg_freeStmtCacheEntry()

static int ecpg_freeStmtCacheEntry ( int  lineno,
int  compat,
int  entNo 
)
static

Definition at line 483 of file prepare.c.

485{
486 stmtCacheEntry *entry;
487 struct connection *con;
488 struct prepared_statement *this,
489 *prev;
490
491 /* fail if cache isn't set up */
492 if (stmtCacheEntries == NULL)
493 return -1;
494
495 entry = &stmtCacheEntries[entNo];
496 if (!entry->stmtID[0]) /* return if the entry isn't in use */
497 return 0;
498
499 con = ecpg_get_connection(entry->connection);
500
501 /* free the 'prepared_statement' list entry */
502 this = ecpg_find_prepared_statement(entry->stmtID, con, &prev);
503 if (this && !deallocate_one(lineno, compat, con, prev, this))
504 return -1;
505
506 entry->stmtID[0] = '\0';
507
508 /* free the memory used by the cache entry */
509 if (entry->ecpgQuery)
510 {
511 ecpg_free(entry->ecpgQuery);
512 entry->ecpgQuery = NULL;
513 }
514
515 return entNo;
516}

References compat, stmtCacheEntry::connection, deallocate_one(), ecpg_find_prepared_statement(), ecpg_free(), ecpg_get_connection(), stmtCacheEntry::ecpgQuery, stmtCacheEntries, and stmtCacheEntry::stmtID.

Referenced by AddStmtToCache().

◆ ecpg_prepared()

char * ecpg_prepared ( const char *  name,
struct connection con 
)

Definition at line 389 of file prepare.c.

390{
391 struct prepared_statement *this;
392
393 this = ecpg_find_prepared_statement(name, con, NULL);
394 return this ? this->stmt->command : NULL;
395}

References ecpg_find_prepared_statement(), name, and stmt.

Referenced by ecpg_do_prologue(), and ECPGprepared_statement().

◆ ecpg_register_prepared_stmt()

bool ecpg_register_prepared_stmt ( struct statement stmt)

Definition at line 59 of file prepare.c.

60{
61 struct statement *prep_stmt;
62 struct prepared_statement *this;
63 struct connection *con = stmt->connection;
64 struct prepared_statement *prev = NULL;
65 int lineno = stmt->lineno;
66
67 /* check if we already have prepared this statement */
68 this = ecpg_find_prepared_statement(stmt->name, con, &prev);
69 if (this && !deallocate_one(lineno, ECPG_COMPAT_PGSQL, con, prev, this))
70 return false;
71
72 /* allocate new statement */
73 this = (struct prepared_statement *) ecpg_alloc(sizeof(struct prepared_statement), lineno);
74 if (!this)
75 return false;
76
77 prep_stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno);
78 if (!prep_stmt)
79 {
80 ecpg_free(this);
81 return false;
82 }
83 memset(prep_stmt, 0, sizeof(struct statement));
84
85 /* create statement */
86 prep_stmt->lineno = lineno;
87 prep_stmt->connection = con;
88 prep_stmt->command = ecpg_strdup(stmt->command, lineno, NULL);
89 if (!prep_stmt->command)
90 {
91 ecpg_free(prep_stmt);
92 ecpg_free(this);
93 return false;
94 }
95 prep_stmt->inlist = prep_stmt->outlist = NULL;
96 this->name = ecpg_strdup(stmt->name, lineno, NULL);
97 if (!this->name)
98 {
99 ecpg_free(prep_stmt->command);
100 ecpg_free(prep_stmt);
101 ecpg_free(this);
102 return false;
103 }
104 this->stmt = prep_stmt;
105 this->prepared = true;
106
107 if (con->prep_stmts == NULL)
108 this->next = NULL;
109 else
110 this->next = con->prep_stmts;
111
112 con->prep_stmts = this;
113 return true;
114}
@ ECPG_COMPAT_PGSQL
struct variable * inlist
char * command
struct variable * outlist
struct connection * connection
char * name

References statement::command, statement::connection, deallocate_one(), ecpg_alloc(), ECPG_COMPAT_PGSQL, ecpg_find_prepared_statement(), ecpg_free(), ecpg_strdup(), statement::inlist, statement::lineno, name, statement::name, next, statement::outlist, connection::prep_stmts, and stmt.

Referenced by ecpg_execute().

◆ ECPGdeallocate()

bool ECPGdeallocate ( int  lineno,
int  c,
const char *  connection_name,
const char *  name 
)

Definition at line 347 of file prepare.c.

348{
349 struct connection *con;
350 struct prepared_statement *this,
351 *prev;
352
353 con = ecpg_get_connection(connection_name);
354 if (!ecpg_init(con, connection_name, lineno))
355 return false;
356
357 this = ecpg_find_prepared_statement(name, con, &prev);
358 if (this)
359 return deallocate_one(lineno, c, con, prev, this);
360
361 /* prepared statement is not found */
362 if (INFORMIX_MODE(c))
363 return true;
365 return false;
366}
bool ecpg_init(const struct connection *con, const char *connection_name, const int lineno)
Definition: misc.c:73

References deallocate_one(), ecpg_find_prepared_statement(), ecpg_get_connection(), ecpg_init(), ECPG_INVALID_STMT, ecpg_raise(), ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, INFORMIX_MODE, and name.

Referenced by execute_test(), fn(), and main().

◆ ECPGdeallocate_all()

bool ECPGdeallocate_all ( int  lineno,
int  compat,
const char *  connection_name 
)

Definition at line 382 of file prepare.c.

383{
384 return ecpg_deallocate_all_conn(lineno, compat,
385 ecpg_get_connection(connection_name));
386}
bool ecpg_deallocate_all_conn(int lineno, enum COMPAT_MODE c, struct connection *con)
Definition: prepare.c:369

References compat, ecpg_deallocate_all_conn(), and ecpg_get_connection().

Referenced by main().

◆ ECPGprepare()

bool ECPGprepare ( int  lineno,
const char *  connection_name,
const bool  questionmarks,
const char *  name,
const char *  variable 
)

Definition at line 249 of file prepare.c.

251{
252 struct connection *con;
253 struct prepared_statement *this,
254 *prev;
255
256 (void) questionmarks; /* quiet the compiler */
257
258 con = ecpg_get_connection(connection_name);
259 if (!ecpg_init(con, connection_name, lineno))
260 return false;
261
262 /* check if we already have prepared this statement */
263 this = ecpg_find_prepared_statement(name, con, &prev);
264 if (this && !deallocate_one(lineno, ECPG_COMPAT_PGSQL, con, prev, this))
265 return false;
266
267 return prepare_common(lineno, con, name, variable);
268}
bool questionmarks
Definition: ecpg.c:19

References deallocate_one(), ECPG_COMPAT_PGSQL, ecpg_find_prepared_statement(), ecpg_get_connection(), ecpg_init(), name, prepare_common(), and questionmarks.

Referenced by ecpg_auto_prepare(), execute_test(), fn(), main(), and test().

◆ ECPGprepared_statement()

char * ECPGprepared_statement ( const char *  connection_name,
const char *  name,
int  lineno 
)

Definition at line 400 of file prepare.c.

401{
402 (void) lineno; /* keep the compiler quiet */
403
404 return ecpg_prepared(name, ecpg_get_connection(connection_name));
405}
char * ecpg_prepared(const char *name, struct connection *con)
Definition: prepare.c:389

References ecpg_get_connection(), ecpg_prepared(), and name.

Referenced by execute_test(), main(), and test().

◆ HashStmt()

static int HashStmt ( const char *  ecpgQuery)
static

Definition at line 411 of file prepare.c.

412{
413 int stmtIx,
414 bucketNo,
415 hashLeng,
416 stmtLeng;
417 uint64 hashVal,
418 rotVal;
419
420 stmtLeng = strlen(ecpgQuery);
421 hashLeng = 50; /* use 1st 50 characters of statement */
422 if (hashLeng > stmtLeng) /* if the statement isn't that long */
423 hashLeng = stmtLeng; /* use its actual length */
424
425 hashVal = 0;
426 for (stmtIx = 0; stmtIx < hashLeng; ++stmtIx)
427 {
428 hashVal = hashVal + (unsigned char) ecpgQuery[stmtIx];
429 /* rotate 32-bit hash value left 13 bits */
430 hashVal = hashVal << 13;
431 rotVal = (hashVal & UINT64CONST(0x1fff00000000)) >> 32;
432 hashVal = (hashVal & UINT64CONST(0xffffffff)) | rotVal;
433 }
434
435 bucketNo = hashVal % stmtCacheNBuckets;
436
437 /* Add 1 so that array entry 0 is never used */
438 return bucketNo * stmtCacheEntPerBucket + 1;
439}
uint64_t uint64
Definition: c.h:542
#define UINT64CONST(x)
Definition: c.h:556
#define stmtCacheNBuckets
Definition: prepare.c:23

References stmtCacheEntPerBucket, stmtCacheNBuckets, and UINT64CONST.

Referenced by AddStmtToCache(), and SearchStmtCache().

◆ isvarchar()

static bool isvarchar ( unsigned char  c)
static

Definition at line 44 of file prepare.c.

45{
46 if (isalnum(c))
47 return true;
48
49 if (c == '_' || c == '>' || c == '-' || c == '.')
50 return true;
51
52 if (c >= 128)
53 return true;
54
55 return false;
56}

Referenced by replace_variables().

◆ prepare_common()

static bool prepare_common ( int  lineno,
struct connection con,
const char *  name,
const char *  variable 
)
static

Definition at line 172 of file prepare.c.

173{
174 struct statement *stmt;
175 struct prepared_statement *this;
176 PGresult *query;
177
178 /* allocate new statement */
179 this = (struct prepared_statement *) ecpg_alloc(sizeof(struct prepared_statement), lineno);
180 if (!this)
181 return false;
182
183 stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno);
184 if (!stmt)
185 {
186 ecpg_free(this);
187 return false;
188 }
189
190 /* create statement */
191 stmt->lineno = lineno;
192 stmt->connection = con;
193 stmt->command = ecpg_strdup(variable, lineno, NULL);
194 if (!stmt->command)
195 {
197 ecpg_free(this);
198 return false;
199 }
200 stmt->inlist = stmt->outlist = NULL;
201
202 /* if we have C variables in our statement replace them with '?' */
203 if (!replace_variables(&(stmt->command), lineno))
204 {
205 ecpg_free(stmt->command);
207 ecpg_free(this);
208 return false;
209 }
210
211 /* add prepared statement to our list */
212 this->name = ecpg_strdup(name, lineno, NULL);
213 if (!this->name)
214 {
215 ecpg_free(stmt->command);
217 ecpg_free(this);
218 return false;
219 }
220 this->stmt = stmt;
221
222 /* and finally really prepare the statement */
223 query = PQprepare(stmt->connection->connection, name, stmt->command, 0, NULL);
224 if (!ecpg_check_PQresult(query, stmt->lineno, stmt->connection->connection, stmt->compat))
225 {
226 ecpg_free(stmt->command);
227 ecpg_free(this->name);
228 ecpg_free(this);
229 ecpg_free(stmt);
230 return false;
231 }
232
233 ecpg_log("prepare_common on line %d: name %s; query: \"%s\"\n", stmt->lineno, name, stmt->command);
234 PQclear(query);
235 this->prepared = true;
236
237 if (con->prep_stmts == NULL)
238 this->next = NULL;
239 else
240 this->next = con->prep_stmts;
241
242 con->prep_stmts = this;
243 return true;
244}
PGresult * PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes)
Definition: fe-exec.c:2323
static bool replace_variables(char **text, int lineno)
Definition: prepare.c:117

References ecpg_alloc(), ecpg_check_PQresult(), ecpg_free(), ecpg_log(), ecpg_strdup(), statement::lineno, name, next, PQclear, PQprepare(), connection::prep_stmts, replace_variables(), and stmt.

Referenced by ecpg_auto_prepare(), and ECPGprepare().

◆ replace_variables()

static bool replace_variables ( char **  text,
int  lineno 
)
static

Definition at line 117 of file prepare.c.

118{
119 bool string = false;
120 int counter = 1,
121 ptr = 0;
122
123 for (; (*text)[ptr] != '\0'; ptr++)
124 {
125 if ((*text)[ptr] == '\'')
126 string = string ? false : true;
127
128 if (string || (((*text)[ptr] != ':') && ((*text)[ptr] != '?')))
129 continue;
130
131 if (((*text)[ptr] == ':') && ((*text)[ptr + 1] == ':'))
132 ptr += 2; /* skip '::' */
133 else
134 {
135 /* a rough guess of the size we need: */
136 int buffersize = sizeof(int) * CHAR_BIT * 10 / 3;
137 int len;
138 char *buffer,
139 *newcopy;
140
141 if (!(buffer = ecpg_alloc(buffersize, lineno)))
142 return false;
143
144 snprintf(buffer, buffersize, "$%d", counter++);
145
146 for (len = 1; (*text)[ptr + len] && isvarchar((*text)[ptr + len]); len++)
147 /* skip */ ;
148 if (!(newcopy = ecpg_alloc(strlen(*text) - len + strlen(buffer) + 1, lineno)))
149 {
150 ecpg_free(buffer);
151 return false;
152 }
153
154 memcpy(newcopy, *text, ptr);
155 strcpy(newcopy + ptr, buffer);
156 strcat(newcopy, (*text) +ptr + len);
157
158 ecpg_free(*text);
159 ecpg_free(buffer);
160
161 *text = newcopy;
162
163 if ((*text)[ptr] == '\0') /* we reached the end */
164 ptr--; /* since we will (*text)[ptr]++ in the top
165 * level for loop */
166 }
167 }
168 return true;
169}
static bool isvarchar(unsigned char c)
Definition: prepare.c:44
return false
Definition: isn.c:135
const void size_t len
#define snprintf
Definition: port.h:260

References ecpg_alloc(), ecpg_free(), false, isvarchar(), len, statement::lineno, and snprintf.

Referenced by prepare_common().

◆ SearchStmtCache()

static int SearchStmtCache ( const char *  ecpgQuery)
static

Definition at line 447 of file prepare.c.

448{
449 int entNo,
450 entIx;
451
452 /* quick failure if cache not set up */
453 if (stmtCacheEntries == NULL)
454 return 0;
455
456 /* hash the statement */
457 entNo = HashStmt(ecpgQuery);
458
459 /* search the cache */
460 for (entIx = 0; entIx < stmtCacheEntPerBucket; ++entIx)
461 {
462 if (stmtCacheEntries[entNo].stmtID[0]) /* check if entry is in use */
463 {
464 if (strcmp(ecpgQuery, stmtCacheEntries[entNo].ecpgQuery) == 0)
465 break; /* found it */
466 }
467 ++entNo; /* incr entry # */
468 }
469
470 /* if entry wasn't found - set entry # to zero */
471 if (entIx >= stmtCacheEntPerBucket)
472 entNo = 0;
473
474 return entNo;
475}

References HashStmt(), stmtCacheEntPerBucket, and stmtCacheEntries.

Referenced by ecpg_auto_prepare().

Variable Documentation

◆ nextStmtID

int nextStmtID = 1
static

Definition at line 37 of file prepare.c.

Referenced by ecpg_auto_prepare().

◆ stmtCacheEntries

stmtCacheEntry* stmtCacheEntries = NULL
static