Re: [PATCHES] TODO item: list prepared queries

2006-01-07 Thread Neil Conway
On Tue, 2006-01-03 at 18:00 -0500, Neil Conway wrote:
> Anyway, if there was a reasonably cheap way to present the query strings 
> of protocol-level and SQL prepared statements in the same manner, I 
> think we should definitely do so. Since there doesn't appear to be one, 
> I'm content to just use the query string as sent by the user. I'll post 
> a revised patch that does that soon.

Attached is the patch I applied to HEAD that uses the query string
supplied by the client, without any rewriting.

-Neil


*** doc/src/sgml/catalogs.sgml	29fbade056e00ee4a48ba6a3f686627f62a103cf
--- doc/src/sgml/catalogs.sgml	f265188b9a381a6c2e67f94290b56f9dc993f5d1
***
*** 4373,4378 
--- 4373,4383 
   
  
   
+   pg_prepared_statements
+   current prepared statements
+  
+ 
+  
pg_prepared_xacts
currently prepared transactions
   
***
*** 4778,4783 
--- 4783,4883 
  
   
  
+  
+   pg_prepared_statements
+ 
+   
+pg_prepared_statements
+   
+ 
+   
+The pg_prepared_statements view displays
+all the prepared statements that are available in the current
+session. See  for more information about prepared
+statements.
+   
+ 
+   
+pg_prepared_statements contains one row
+for each prepared statement. Rows are added to the view when a new
+prepared statement is created, and removed when a prepared
+statement is released (for example, via the 
+command).
+   
+ 
+   
+pg_prepared_statements Columns
+ 
+
+ 
+  
+   Name
+   Type
+   References
+   Description
+  
+ 
+ 
+  
+   name
+   text
+   
+   
+The identifier of the prepared statement.
+   
+  
+  
+   statement
+   text
+   
+   
+The query string submitted by the client to create this
+prepared statement. For prepared statements created via SQL,
+this is the PREPARE statement submitted by
+the client. For prepared statements created via the
+frontend/backend protocol, this is the text of the prepared
+statement itself.
+   
+  
+  
+   prepare_time
+   timestamptz
+   
+   
+The time at which the prepared statement was created.
+   
+  
+  
+   parameter_types
+   oid[]
+   
+   
+The expected parameter types for the prepared statement in the form of
+an array of type OIDs.
+   
+  
+  
+   from_sql
+   boolean
+   
+   
+true if the prepared statement was created
+via the PREPARE SQL statement;
+false if the statement was prepared via the
+frontend/backend protocol.
+   
+  
+ 
+
+   
+ 
+   
+The pg_prepared_statements view is read only.
+   
+  
+ 
   
pg_prepared_xacts
  

*** doc/src/sgml/ref/prepare.sgml	17fce269c43549b6ffa7bf3d5770da9fbdf18896
--- doc/src/sgml/ref/prepare.sgml	98824b3ad9ac4ffa50677f3b8ac821f8a1c84e16
***
*** 145,150 
--- 145,155 
 the 
 documentation.

+ 
+   
+You can see all available prepared statements of a session by querying the
+pg_prepared_statements system view.
+   
   
  
   

*** src/backend/catalog/system_views.sql	307260ff7bc30a48c0c60a40d4130f70310ebff2
--- src/backend/catalog/system_views.sql	7b92550bbcaf9d0ee99c12527f7785385cfeefe7
***
*** 156,161 
--- 156,167 
   LEFT JOIN pg_authid U ON P.ownerid = U.oid
   LEFT JOIN pg_database D ON P.dbid = D.oid;
  
+ CREATE VIEW pg_prepared_statements AS
+ SELECT P.name, P.statement, P.prepare_time, P.parameter_types, P.from_sql
+ FROM pg_prepared_statement() AS P
+ (name text, statement text, prepare_time timestamptz,
+  parameter_types oid[], from_sql boolean);
+ 
  CREATE VIEW pg_settings AS 
  SELECT * 
  FROM pg_show_all_settings() AS A 

*** src/backend/commands/prepare.c	3c1a8b677a84566407472a0b7b85b4cb86587956
--- src/backend/commands/prepare.c	dc237de8d42ca2cd72d75e3b9bf64b8786702e5a
***
*** 16,30 
   */
  #include "postgres.h"
  
  #include "commands/explain.h"
  #include "commands/prepare.h"
  #include "executor/executor.h"
! #include "utils/guc.h"
  #include "optimizer/planner.h"
  #include "rewrite/rewriteHandler.h"
  #include "tcop/pquery.h"
  #include "tcop/tcopprot.h"
  #include "tcop/utility.h"
  #include "utils/hsearch.h"
  #include "utils/memutils.h"
  
--- 16,35 
   */
  #include "postgres.h"
  
+ #include "access/heapam.h"
+ #include "catalog/pg_type.h"
  #include "commands/explain.h"
  #include "commands/prepare.h"
  #include "executor/executor.h"
! #include "funcapi.h"
! #include "parser

Re: [PATCHES] psql tab completion enhancements

2006-01-07 Thread Neil Conway
A few minor stylistic gripes...

On Fri, 2006-01-06 at 20:27 +0100, Joachim Wieland wrote:
> *** 150,155 
> --- 151,171 
>   do {completion_charp = Query_for_list_of_attributes;
> completion_info_charp = table; matches = completion_matches(text,
> complete_from_query); } while(0)
>   
>   /*
> +  * Keep the "malloced" keyword in all the names such that we
> remember that
> +  * memory got allocated here. COMPLETE_WITH_MALLOCED_LIST frees this
> memory.
> +  */
> + #define COMPLETE_WITH_MALLOCED_LIST(list) \
> +   do { COMPLETE_WITH_LIST((const char**) list); free(list); list
> = (char**) 0; } while(0)

NULL is better style than 0 in a pointer context. Also, why are the
casts necessary?

>   /* Forward declaration of functions */
> + static char **get_empty_list();

Should be "static char **get_empty_list(void);", as C89 doesn't check
the parameters passed to a function declared with an empty parameter
list.

> *** 754,760 
> else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
>  (pg_strcasecmp(prev_wd, "ALTER") == 0 ||
>   pg_strcasecmp(prev_wd, "RENAME") == 0))
> !   COMPLETE_WITH_ATTR(prev2_wd);
>   
> /* ALTER TABLE xxx RENAME yyy */
> else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 &&
> --- 780,796 
> else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
>  (pg_strcasecmp(prev_wd, "ALTER") == 0 ||
>   pg_strcasecmp(prev_wd, "RENAME") == 0))
> !   {
> !   char** list = GET_MALLOCED_LIST_WITH_ATTR(prev2_wd);

Should be "char **list = ..." -- similarly in several other places.

> *** 1454,1461 
> else if (pg_strcasecmp(prev_wd, "LOCK") == 0 ||
>  (pg_strcasecmp(prev_wd, "TABLE") == 0 &&
>   pg_strcasecmp(prev2_wd, "LOCK") == 0))
> !   COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
> NULL);
> ! 
> /* For the following, handle the case of a single table only
> for now */
>   
> /* Complete LOCK [TABLE]  with "IN" */
> --- 1497,1510 
> else if (pg_strcasecmp(prev_wd, "LOCK") == 0 ||
>  (pg_strcasecmp(prev_wd, "TABLE") == 0 &&
>   pg_strcasecmp(prev2_wd, "LOCK") == 0))
> !   {
> !   char** list =
> GET_MALLOCED_LIST_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
> !   /* if we have only seen LOCK but not LOCK TABLE so
> far, offer
> !* the TABLE keyword as well */

Is this actually useful? The "TABLE" keyword is just noise.

> *** 2315,2320 
> --- 2368,2437 
>   
>   }
>   
> + /* LIST HELPER FUNCTIONS */
> + 
> + static char**
> + get_empty_list() {
> +   char** list = malloc(sizeof(char*));
> +   list[0] = NULL;
> +   return list;
> + }

Brace style ("{" on newline), "char **", and "(void"), as above.

> + static char**
> + get_query_list(const char *text,
> +  const char *query,
> +  const char* completion_info)
> + {
> +   return _get_query_list(0, text, query, completion_info);
> + }

The difference between get_query_list() and _get_query_list() is not
reflected in the names of the methods. An "_internal" suffix would be
better, for example.

> + static char**
> + _get_query_list(int is_schema_query,
> +   const char *text,
> +   const char *query,
> +   const char* completion_info)

"bool" for boolean variables rather than "int", and consistent parameter
declarations ("char *" not "char*").

> + static char**
> + list_add_item(char **list, char *item)
> + {
> +   int size = 0;
> +   while (list[size])
> +   size++;
> +   list = realloc(list, sizeof(char*) * (size + 1 + 1));
> +   list[size] = item;
> +   list[size+1] = NULL;
> +   return list;
> + }

That's a terribly inefficient implementation.

-Neil



---(end of broadcast)---
TIP 4: Have you searched our list archives?

   http://archives.postgresql.org


Re: [PATCHES] Summary table trigger example race condition

2006-01-07 Thread Mark Kirkwood

Mark Kirkwood wrote:

Jim C. Nasby wrote:


On Fri, Jan 06, 2006 at 02:00:34PM +1300, Mark Kirkwood wrote:

However, I think the actual change is not quite right - after running 




DOH! It would be good if doc/src had a better mechanism for handling
code; one that would allow for writing the code natively (so you don't
have to worry about translating < into < and > into >) and for
unit testing the different pieces of code.



Yes it would - I usually build the SGML -> HTML, then cut the code out 
of a browser session to test - the pain is waiting for the docs to build.



Anyway, updated patch attached.



This one is good!



After re-examining the original code, it looks like it was not actually 
vulnerable to a race condition! (it does the UPDATE, then if not found 
will do an INSERT, and handle unique violation with a repeat of the same 
UPDATE - i.e three DML statements, which are enough to handle the race 
in this case).


However Jim's change handles the race needing only two DML statements in 
a loop, which seems much more elegant! In addition it provides a nice 
example of the 'merge' style code shown in e.g 36-1.


Cheers

Mark


---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [PATCHES] [HACKERS] Inconsistent syntax in GRANT

2006-01-07 Thread Marko Kreen
On 1/7/06, Bruce Momjian  wrote:
> Marko Kreen wrote:
> > The above table seem bit messy, but I see it as much easier to explain
> > to somebody.
>
> I am confused about your list above, so I can't see how that would be
> easy to explain.

Easy as in "use GRANT USAGE, forget about rest".  You are confused
because you know the old way and look them together.

I would have liked to say "the rest are for fine-grained access control",
but with Tom's final proposal, the explanation would continue "SELECT,
UPDATE are for backwards compatibility".

Attached is a patch that fixes tablename->seqname and puts USAGE
as first in list to show it's the preferred way.  I think it should
be mentioned somewhere explicitly, but I cant find proper place for
it.  In the Compatibility section for GRANT?

--
marko
Index: pgsql/doc/src/sgml/ref/grant.sgml
===
*** pgsql.orig/doc/src/sgml/ref/grant.sgml
--- pgsql/doc/src/sgml/ref/grant.sgml
*** GRANT { { SELECT | INSERT | UPDATE | DEL
*** 25,33 
  ON [ TABLE ] tablename [, ...]
  TO { username | GROUP groupname | PUBLIC } [, ...] [ WITH GRANT OPTION ]
  
! GRANT { { SELECT | USAGE | UPDATE }
  [,...] | ALL [ PRIVILEGES ] }
! ON SEQUENCE tablename [, ...]
  TO { username | GROUP groupname | PUBLIC } [, ...] [ WITH GRANT OPTION ]
  
  GRANT { { CREATE | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] }
--- 25,33 
  ON [ TABLE ] tablename [, ...]
  TO { username | GROUP groupname | PUBLIC } [, ...] [ WITH GRANT OPTION ]
  
! GRANT { { USAGE | SELECT | UPDATE }
  [,...] | ALL [ PRIVILEGES ] }
! ON SEQUENCE sequencename [, ...]
  TO { username | GROUP groupname | PUBLIC } [, ...] [ WITH GRANT OPTION ]
  
  GRANT { { CREATE | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] }
Index: pgsql/doc/src/sgml/ref/revoke.sgml
===
*** pgsql.orig/doc/src/sgml/ref/revoke.sgml
--- pgsql/doc/src/sgml/ref/revoke.sgml
*** REVOKE [ GRANT OPTION FOR ]
*** 28,36 
  [ CASCADE | RESTRICT ]
  
  REVOKE [ GRANT OPTION FOR ]
! { { SELECT | UPDATE }
  [,...] | ALL [ PRIVILEGES ] }
! ON SEQUENCE tablename [, ...]
  FROM { username | GROUP groupname | PUBLIC } [, ...]
  [ CASCADE | RESTRICT ]
  
--- 28,36 
  [ CASCADE | RESTRICT ]
  
  REVOKE [ GRANT OPTION FOR ]
! { { USAGE | SELECT | UPDATE }
  [,...] | ALL [ PRIVILEGES ] }
! ON SEQUENCE sequencename [, ...]
  FROM { username | GROUP groupname | PUBLIC } [, ...]
  [ CASCADE | RESTRICT ]
  


---(end of broadcast)---
TIP 5: don't forget to increase your free space map settings