hi everyone ...

i have attached a patch implementing NO WAIT with the help of a GUC variable.
documentation should be included as well.
it works nicely for me.


test=# begin;
BEGIN
test=# show wait_for_locks;
 wait_for_locks
----------------
 row share
(1 row)

test=# lock table x in exclusive mode;
LOCK TABLE
test=# commit;
COMMIT
test=# begin;
BEGIN
test=# -- somebody else has locked the table ...
test=# lock table x in exclusive mode;
ERROR:  LockAcquire failed



[EMAIL PROTECTED] pgsql]$ difforig > nowait.patch
./doc/src/sgml/runtime.sgml
./src/backend/storage/lmgr/lock.c
./src/backend/utils/misc/guc.c
./src/backend/utils/misc/postgresql.conf.sample
./src/bin/psql/tab-complete.c
./src/include/storage/lock.h
./src/include/utils/guc.h


i hope this patch is ok. if there are any modifications needed just drop me a line.

maybe i will have some spare time to implement "SELECT FOR UPDATE NOWAIT" (SQL version). maybe this extension would make sense as well because many people porting from oracle to pg would like that.

cheers,

Hans

--
Cybertec Geschwinde u Schoenig
Schoengrabern 134, A-2020 Hollabrunn, Austria
Tel: +43/2952/30706 or +43/664/233 90 75
www.cybertec.at, www.postgresql.at, kernel.cybertec.at

*** ./doc/src/sgml/runtime.sgml.orig    2004-02-17 12:06:23.000000000 +0100
--- ./doc/src/sgml/runtime.sgml 2004-02-17 13:10:26.000000000 +0100
***************
*** 2555,2560 ****
--- 2555,2578 ----
        </listitem>
       </varlistentry>
  
+      <varlistentry>
+       <term><varname>wait_for_locks</varname> (<type>string</type>)</term>
+       <listitem>
+        <para>
+         By default an SQL statement has to wait until the desired locks for 
+       processing the command can be acquired. In some cases this is not 
+       the best thing to do. Therefore it is possible to tell PostgreSQL 
+       which locks it is worth waiting for.  The following kinds of locks / 
+       settings are supported: all, access share, row share, row exclusive, 
+       share update exclusive, share, share row exclusive, exclusive, 
+       access exclusive. <quote>all</> is the default setting and means that 
+       PostgreSQL will wait for all locks. If <quote>share</> is specified 
+       PostgreSQL will not wait for locks which are higher or equal to a 
+       share lock.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
       </variablelist>
     </sect2>
  
*** ./src/backend/storage/lmgr/lock.c.orig      2004-02-17 09:45:04.000000000 +0100
--- ./src/backend/storage/lmgr/lock.c   2004-02-17 11:33:13.000000000 +0100
***************
*** 36,41 ****
--- 36,42 ----
  #include "access/xact.h"
  #include "miscadmin.h"
  #include "storage/proc.h"
+ #include "utils/guc.h"
  #include "utils/memutils.h"
  #include "utils/ps_status.h"
  
***************
*** 435,440 ****
--- 436,455 ----
                         locktag->objId.blkno, lock_mode_names[lockmode]);
  #endif
  
+       /* check if NO WAIT has been enabled 
+          the basic strategy is very simple: if the user has selected "all"
+          PostgreSQL will act normally. However, if a certain lock level has
+          been defined PostgreSQL won't wait for locks which are higher than
+          the specified level */
+       if      (Wait_for_locks != 0)
+       {
+               /* now we have to adjust dontWait */
+               if      (lockmode >= Wait_for_locks)
+               {
+                       dontWait = true;
+               }
+       }
+ 
        /* ???????? This must be changed when short term locks will be used */
        locktag->lockmethodid = lockmethodid;
  
*** ./src/backend/utils/misc/guc.c.orig 2004-02-17 09:48:34.000000000 +0100
--- ./src/backend/utils/misc/guc.c      2004-02-17 14:42:10.000000000 +0100
***************
*** 47,52 ****
--- 47,53 ----
  #include "storage/fd.h"
  #include "storage/freespace.h"
  #include "storage/lock.h"
+ #include "storage/lmgr.h"
  #include "storage/proc.h"
  #include "tcop/tcopprot.h"
  #include "utils/array.h"
***************
*** 85,90 ****
--- 86,93 ----
  
  static const char *assign_defaultxactisolevel(const char *newval,
                                                   bool doit, GucSource source);
+ static const char *assign_wait_for_locks(const char *newval,
+                                                  bool doit, GucSource source);
  static const char *assign_log_min_messages(const char *newval,
                                                bool doit, GucSource source);
  static const char *assign_client_min_messages(const char *newval,
***************
*** 132,137 ****
--- 135,141 ----
  int                   client_min_messages = NOTICE;
  
  int                   log_min_duration_statement = -1;
+ int                   Wait_for_locks = 0;
  
  
  /*
***************
*** 149,154 ****
--- 153,159 ----
  static char *client_encoding_string;
  static char *datestyle_string;
  static char *default_iso_level_string;
+ static char *wait_for_locks_string;
  static char *locale_collate;
  static char *locale_ctype;
  static char *regex_flavor_string;
***************
*** 1515,1521 ****
                &default_iso_level_string,
                "read committed", assign_defaultxactisolevel, NULL
        },
! 
        {
                {"dynamic_library_path", PGC_SUSET, CLIENT_CONN_OTHER,
                        gettext_noop("Sets the path for dynamically loadable 
modules."),
--- 1520,1537 ----
                &default_iso_level_string,
                "read committed", assign_defaultxactisolevel, NULL
        },
!       {
!               {"wait_for_locks", PGC_USERSET, CLIENT_CONN_STATEMENT,
!                       gettext_noop("Tells PostgreSQL whether to wait for locks or 
not."),
!                       gettext_noop("Allowed settings: "
!                                "\"all\", \"access share\", \"row share\", "
!                                "\"row exclusive\", \"share update exclusive\", "
!                                "\"share\", \"share row exclusive\", "
!                                "\"exclusive\", \"access exclusive\".")
!               },
!               &wait_for_locks_string,
!               "all", assign_wait_for_locks, NULL
!       },
        {
                {"dynamic_library_path", PGC_SUSET, CLIENT_CONN_OTHER,
                        gettext_noop("Sets the path for dynamically loadable 
modules."),
***************
*** 4457,4462 ****
--- 4473,4533 ----
  #endif
  
  
+ /* in this function we will check if the string in the config-file
+    contains a correct lock level */
+ static const char *
+ assign_wait_for_locks(const char *newval, bool doit, GucSource source)
+ {
+       if (strcasecmp(newval, "all") == 0)
+       {
+               if (doit)
+                       Wait_for_locks = NoLock;
+       }
+       else if (strcasecmp(newval, "access share") == 0)
+       {
+               if (doit)
+                       Wait_for_locks = AccessShareLock;
+       }
+       else if (strcasecmp(newval, "row share") == 0)
+       {
+               if (doit)
+                       Wait_for_locks = RowShareLock;
+       }
+       else if (strcasecmp(newval, "row exclusive") == 0)
+       {
+               if (doit)
+                       Wait_for_locks = RowExclusiveLock;
+       }
+       else if (strcasecmp(newval, "share update exclusive") == 0)
+       {
+               if (doit)
+                       Wait_for_locks = ShareUpdateExclusiveLock;
+       }
+       else if (strcasecmp(newval, "share") == 0)
+       {
+               if (doit)
+                       Wait_for_locks = ShareLock;
+       }
+       else if (strcasecmp(newval, "share row exclusive") == 0)
+       {
+               if (doit)
+                       Wait_for_locks = ShareRowExclusiveLock;
+       }
+       else if (strcasecmp(newval, "exclusive") == 0)
+       {
+               if (doit)
+                       Wait_for_locks = ExclusiveLock;
+       }
+       else if (strcasecmp(newval, "access exclusive") == 0)
+       {
+               if (doit)
+                       Wait_for_locks = AccessExclusiveLock;
+       }
+       else
+               return NULL;
+       return newval;
+ }
+ 
  static const char *
  assign_defaultxactisolevel(const char *newval, bool doit, GucSource source)
  {
*** ./src/backend/utils/misc/postgresql.conf.sample.orig        2004-02-17 
11:02:35.000000000 +0100
--- ./src/backend/utils/misc/postgresql.conf.sample     2004-02-17 13:38:14.000000000 
+0100
***************
*** 248,253 ****
--- 248,257 ----
  # LOCK MANAGEMENT
  #---------------------------------------------------------------------------
  
+ #wait_for_locks = 'all'               # allowed settings: all, access share, 
+                               #  row share, row exclusive, share update 
+                               #  exclusive, share, share row exclusive,
+                               #  exclusive, access exclusive
  #deadlock_timeout = 1000      # in milliseconds
  #max_locks_per_transaction = 64       # min 10, ~260*max_connections bytes each
  
*** ./src/bin/psql/tab-complete.c.orig  2004-02-17 11:51:19.000000000 +0100
--- ./src/bin/psql/tab-complete.c       2004-02-17 11:51:54.000000000 +0100
***************
*** 567,572 ****
--- 567,573 ----
                "unix_socket_directory",
                "unix_socket_group",
                "unix_socket_permissions",
+               "wait_for_locks",
                "wal_buffers",
                "wal_debug",
                "wal_sync_method",
*** ./src/include/storage/lock.h.orig   2004-02-17 10:12:37.000000000 +0100
--- ./src/include/storage/lock.h        2004-02-17 10:16:51.000000000 +0100
***************
*** 32,37 ****
--- 32,45 ----
  
  extern int    max_locks_per_xact;
  
+ 
+ /* PostgreSQL supports NO WAIT via GUC variables 
+    therefore we need information telling us whether we want to wait for locks or
+    not. In addition to that we want to tell the system for which locks we want
+    to wait */
+ extern int  Wait_for_locks;
+ 
+ 
  #ifdef LOCK_DEBUG
  extern int    Trace_lock_oidmin;
  extern bool Trace_locks;
*** ./src/include/utils/guc.h.orig      2004-02-17 10:35:02.000000000 +0100
--- ./src/include/utils/guc.h   2004-02-17 10:35:29.000000000 +0100
***************
*** 126,131 ****
--- 126,132 ----
  extern int    log_min_messages;
  extern int    client_min_messages;
  extern int    log_min_duration_statement;
+ extern int    Wait_for_locks;
  
  
  extern void SetConfigOption(const char *name, const char *value,
---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
    (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])

Reply via email to