/* *ThestatementcachecontainsstmtCacheNBucketshashbuckets,each *havingstmtCacheEntPerBucketentries,whichwerecycleasneeded, *givinguptheleast-executedentryinthebucket. *stmtCacheEntries[0]isneverused,sothatzerocanbea"notfound" *indicator.
*/ #define stmtCacheNBuckets 2039/* should be a prime number */ #define stmtCacheEntPerBucket 8
typedefstruct
{ int lineno; char stmtID[STMTID_SIZE]; char *ecpgQuery; long execs; /* # of executions */ constchar *connection; /* connection for the statement */
} stmtCacheEntry;
/* check if we already have prepared this statement */ this = ecpg_find_prepared_statement(stmt->name, con, &prev); if (this && !deallocate_one(lineno, ECPG_COMPAT_PGSQL, con, prev, this)) returnfalse;
/* allocate new statement */ this = (struct prepared_statement *) ecpg_alloc(sizeof(struct prepared_statement), lineno); if (!this) returnfalse;
/* handle the EXEC SQL PREPARE statement */ /* questionmarks is not needed but remains in there for the time being to not change the API */ bool
ECPGprepare(int lineno, constchar *connection_name, constbool questionmarks, constchar *name, constchar *variable)
{ struct connection *con; struct prepared_statement *this,
*prev;
(void) questionmarks; /* quiet the compiler */
con = ecpg_get_connection(connection_name); if (!ecpg_init(con, connection_name, lineno)) returnfalse;
/* check if we already have prepared this statement */ this = ecpg_find_prepared_statement(name, con, &prev); if (this && !deallocate_one(lineno, ECPG_COMPAT_PGSQL, con, prev, this)) returnfalse;
con = ecpg_get_connection(connection_name); if (!ecpg_init(con, connection_name, lineno)) returnfalse;
this = ecpg_find_prepared_statement(name, con, &prev); if (this) return deallocate_one(lineno, c, con, prev, this);
/* prepared statement is not found */ if (INFORMIX_MODE(c)) returntrue;
ecpg_raise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, name); returnfalse;
}
bool
ecpg_deallocate_all_conn(int lineno, enum COMPAT_MODE c, struct connection *con)
{ /* deallocate all prepared statements */ while (con->prep_stmts)
{ if (!deallocate_one(lineno, c, con, NULL, con->prep_stmts)) returnfalse;
}
stmtLeng = strlen(ecpgQuery);
hashLeng = 50; /* use 1st 50 characters of statement */ if (hashLeng > stmtLeng) /* if the statement isn't that long */
hashLeng = stmtLeng; /* use its actual length */
/* quick failure if cache not set up */ if (stmtCacheEntries == NULL) return0;
/* hash the statement */
entNo = HashStmt(ecpgQuery);
/* search the cache */ for (entIx = 0; entIx < stmtCacheEntPerBucket; ++entIx)
{ if (stmtCacheEntries[entNo].stmtID[0]) /* check if entry is in use */
{ if (strcmp(ecpgQuery, stmtCacheEntries[entNo].ecpgQuery) == 0) break; /* found it */
}
++entNo; /* incr entry # */
}
/* if entry wasn't found - set entry # to zero */ if (entIx >= stmtCacheEntPerBucket)
entNo = 0;
return entNo;
}
/* *freeanentryinthestatementcache *Returnsentry#incacheused *ORnegativeerrorcode
*/ staticint
ecpg_freeStmtCacheEntry(int lineno, int compat, int entNo) /* entry # to free */
{
stmtCacheEntry *entry; struct connection *con; struct prepared_statement *this,
*prev;
/* fail if cache isn't set up */ if (stmtCacheEntries == NULL) return -1;
entry = &stmtCacheEntries[entNo]; if (!entry->stmtID[0]) /* return if the entry isn't in use */ return0;
con = ecpg_get_connection(entry->connection);
/* *Iftheconnectionisgone,theprepared_statementlistitownedis *alreadyunreachable,sojustskipthatcleanup.Wemuststillclear *thecacheslotbelowsoitcanbereused.
*/ if (con)
{ /* free the 'prepared_statement' list entry */ this = ecpg_find_prepared_statement(entry->stmtID, con, &prev); if (this && !deallocate_one(lineno, compat, con, prev, this)) return -1;
}
entry->stmtID[0] = '\0';
/* free the memory used by the cache entry */ if (entry->ecpgQuery)
{
ecpg_free(entry->ecpgQuery);
entry->ecpgQuery = 0;
}
return entNo;
}
/* *addanentrytothestatementcache *returnsentry#incacheusedORnegativeerrorcode
*/ staticint
AddStmtToCache(int lineno, /* line # of statement */ constchar *stmtID, /* statement ID */ constchar *connection, /* connection */ int compat, /* compatibility level */ constchar *ecpgQuery) /* query */
{ int ix,
initEntNo,
luEntNo,
entNo;
stmtCacheEntry *entry;
/* allocate and zero cache array if we haven't already */ if (stmtCacheEntries == NULL)
{
stmtCacheEntries = (stmtCacheEntry *)
ecpg_alloc(sizeof(stmtCacheEntry) * stmtCacheArraySize, lineno); if (stmtCacheEntries == NULL) return -1;
}
/* hash the statement */
initEntNo = HashStmt(ecpgQuery);
/* search for an unused entry */
entNo = initEntNo; /* start with the initial entry # for the
* bucket */
luEntNo = initEntNo; /* use it as the initial 'least used' entry */ for (ix = 0; ix < stmtCacheEntPerBucket; ++ix)
{
entry = &stmtCacheEntries[entNo]; if (!entry->stmtID[0]) /* unused entry - use it */ break; if (entry->execs < stmtCacheEntries[luEntNo].execs)
luEntNo = entNo; /* save new 'least used' entry */
++entNo; /* increment entry # */
}
/* 'entNo' is the entry to use - make sure its free */ if (ecpg_freeStmtCacheEntry(lineno, compat, entNo) < 0) return -1;
/* add the query to the entry */
entry = &stmtCacheEntries[entNo];
entry->lineno = lineno;
entry->ecpgQuery = ecpg_strdup(ecpgQuery, lineno);
entry->connection = connection;
entry->execs = 0;
memcpy(entry->stmtID, stmtID, sizeof(entry->stmtID));
return entNo;
}
/* handle cache and preparation of statements in auto-prepare mode */ bool
ecpg_auto_prepare(int lineno, constchar *connection_name, constint compat, char **name, constchar *query)
{ int entNo;
/* search the statement cache for this statement */
entNo = SearchStmtCache(query);
/* if not found - add the statement to the cache */ if (entNo)
{ char *stmtID; struct connection *con; struct prepared_statement *prep;
ecpg_log("ecpg_auto_prepare on line %d: statement found in cache; entry %d\n", lineno, entNo);
stmtID = stmtCacheEntries[entNo].stmtID;
con = ecpg_get_connection(connection_name);
prep = ecpg_find_prepared_statement(stmtID, con, NULL); /* This prepared name doesn't exist on this connection. */ if (!prep && !prepare_common(lineno, con, stmtID, query)) returnfalse;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.