diff --exclude Makefile.global --exclude pg_config.h --exclude gram.c --exclude scan.c --exclude parse.h -ur postgresql-7.4.5-dist/src/backend/commands/prepare.c postgresql-7.4.5/src/backend/commands/prepare.c --- postgresql-7.4.5-dist/src/backend/commands/prepare.c 2003-08-08 14:41:32.000000000 -0700 +++ postgresql-7.4.5/src/backend/commands/prepare.c 2004-12-01 17:57:57.000000000 -0800 @@ -16,6 +16,7 @@ */ #include "postgres.h" +#include #include "commands/explain.h" #include "commands/prepare.h" #include "executor/executor.h" @@ -25,7 +26,6 @@ #include "tcop/pquery.h" #include "tcop/tcopprot.h" #include "tcop/utility.h" -#include "utils/hsearch.h" #include "utils/memutils.h" @@ -95,7 +95,7 @@ /* Save the results. */ StorePreparedStatement(stmt->name, - NULL, /* text form not available */ + stmt->query_string, commandTag, query_list, plan_list, @@ -195,6 +195,9 @@ if (estate) FreeExecutorState(estate); + /* Completed: update execution statistics */ + entry->exec_count++; + /* No need to pfree other memory, MemoryContext will be reset */ } @@ -285,12 +288,14 @@ List *argtype_list) { PreparedStatement *entry; + struct timeval create_time; MemoryContext oldcxt, entrycxt; char *qstring; char key[NAMEDATALEN]; bool found; + /* Initialize the hash table, if necessary */ if (!prepared_queries) InitQueryHashTable(); @@ -327,6 +332,9 @@ query_list = (List *) copyObject(query_list); plan_list = (List *) copyObject(plan_list); argtype_list = listCopy(argtype_list); + + if (gettimeofday(&create_time, NULL) != 0) + elog(ERROR, "failed to read current system time"); /* Now we can add entry to hash table */ entry = (PreparedStatement *) hash_search(prepared_queries, @@ -346,6 +354,8 @@ entry->plan_list = plan_list; entry->argtype_list = argtype_list; entry->context = entrycxt; + entry->create_time = entry->access_time = create_time; + entry->exec_count = 0; MemoryContextSwitchTo(oldcxt); } @@ -388,6 +398,9 @@ errmsg("prepared statement \"%s\" does not exist", stmt_name))); + if (entry && gettimeofday(&entry->access_time, NULL) != 0) + elog(ERROR, "failed to read current system time"); + return entry; } @@ -434,6 +447,17 @@ } /* + * Return a pointer to the hash table of prepared statements. + * This should be used by callers needing low-level access to + * the list of PreparedStatement structs (e.g. to list them). + */ +HTAB * +FetchPreparedStatementHtab(void) +{ + return prepared_queries; +} + +/* * Implements the 'DEALLOCATE' utility statement: deletes the * specified plan from storage. */ @@ -557,4 +581,7 @@ if (estate) FreeExecutorState(estate); + + /* Completed: update execution statistics */ + entry->exec_count++; } diff --exclude Makefile.global --exclude pg_config.h --exclude gram.c --exclude scan.c --exclude parse.h -ur postgresql-7.4.5-dist/src/backend/parser/gram.y postgresql-7.4.5/src/backend/parser/gram.y --- postgresql-7.4.5-dist/src/backend/parser/gram.y 2003-11-24 08:54:15.000000000 -0800 +++ postgresql-7.4.5/src/backend/parser/gram.y 2004-12-21 09:19:59.000000000 -0800 @@ -66,6 +66,8 @@ extern List *parsetree; /* final parse result is delivered here */ +extern char *base_yytext; + static bool QueryIsRule = FALSE; /* @@ -223,7 +225,7 @@ opt_select_limit opclass_item_list transaction_mode_list transaction_mode_list_or_empty TableFuncElementList - prep_type_clause prep_type_list + prep_as prep_type_clause prep_type_list execute_param_clause %type into_clause OptTempTableName @@ -4096,16 +4098,43 @@ * *****************************************************************************/ -PrepareStmt: PREPARE name prep_type_clause AS PreparableStmt +PrepareStmt: PREPARE name prep_type_clause prep_as PreparableStmt { PrepareStmt *n = makeNode(PrepareStmt); n->name = $2; n->argtypes = $3; + n->query_string = (char *) $4; n->query = (Query *) $5; $$ = (Node *) n; } ; +prep_as: AS + { + /* Save original query string: + We want to save the string representation of the + prepared query - that is, the string following 'AS' in + the PREPARE statement. We reach into the lexographic + analyzer's scan buffer to do this. + + In flex(1), $yytext is a pointer into $scanbuf. As + each token is processed, flex inserts a null terminator + into $scanbuf - this separates $scanbuf into two halves, + the left half consisting of already-processed + characters, and the right half consisting of yet-to-be + processed characters. Taken by itself, $yytext points to + the start of the current token in $scanbuf; the null + terminator of $yytext is the same null terminator that + divides $scanbuf. + + We want the right half of $scanbuf. */ + + char *p = base_yytext + strlen(base_yytext) + 1; + while (isspace(*p)) ++p; + $$ = (void *) pstrdup(p); + } + ; + prep_type_clause: '(' prep_type_list ')' { $$ = $2; } | /* EMPTY */ { $$ = NIL; } ; diff --exclude Makefile.global --exclude pg_config.h --exclude gram.c --exclude scan.c --exclude parse.h -ur postgresql-7.4.5-dist/src/include/commands/prepare.h postgresql-7.4.5/src/include/commands/prepare.h --- postgresql-7.4.5-dist/src/include/commands/prepare.h 2003-08-08 14:42:40.000000000 -0700 +++ postgresql-7.4.5/src/include/commands/prepare.h 2004-12-01 16:26:34.000000000 -0800 @@ -16,6 +16,7 @@ #include "executor/executor.h" #include "nodes/parsenodes.h" #include "tcop/dest.h" +#include "utils/hsearch.h" /* @@ -37,8 +38,11 @@ List *plan_list; /* list of plans */ List *argtype_list; /* list of parameter type OIDs */ MemoryContext context; /* context containing this query */ -} PreparedStatement; + unsigned long exec_count; /* number of successful executions */ + struct timeval create_time; /* wall time at which entry was created */ + struct timeval access_time; /* wall time at which entry was last accessed */ +} PreparedStatement; /* Utility statements PREPARE, EXECUTE, DEALLOCATE, EXPLAIN EXECUTE */ extern void PrepareQuery(PrepareStmt *stmt); @@ -59,4 +63,7 @@ extern List *FetchPreparedStatementParams(const char *stmt_name); extern TupleDesc FetchPreparedStatementResultDesc(PreparedStatement *stmt); +/* Low-level access to the prepared statement hash table */ +extern HTAB *FetchPreparedStatementHtab(void); + #endif /* PREPARE_H */ diff --exclude Makefile.global --exclude pg_config.h --exclude gram.c --exclude scan.c --exclude parse.h -ur postgresql-7.4.5-dist/src/include/nodes/parsenodes.h postgresql-7.4.5/src/include/nodes/parsenodes.h --- postgresql-7.4.5-dist/src/include/nodes/parsenodes.h 2003-09-16 21:25:29.000000000 -0700 +++ postgresql-7.4.5/src/include/nodes/parsenodes.h 2004-12-01 16:20:53.000000000 -0800 @@ -1670,6 +1670,7 @@ List *argtypes; /* Types of parameters (TypeNames) */ List *argtype_oids; /* Types of parameters (OIDs) */ Query *query; /* The query itself */ + char *query_string; /* The query's string representation */ } PrepareStmt;