Index: openacs-4/packages/xotcl-core/tcl/05-db-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/05-db-procs.tcl,v diff -u -r1.148.2.29 -r1.148.2.30 --- openacs-4/packages/xotcl-core/tcl/05-db-procs.tcl 5 Jan 2021 09:38:55 -0000 1.148.2.29 +++ openacs-4/packages/xotcl-core/tcl/05-db-procs.tcl 24 Jan 2021 19:54:13 -0000 1.148.2.30 @@ -295,6 +295,7 @@ ::xo::db::Driver abstract instproc list {{-dbn ""} {-bind ""} -prepare qn sql} ::xo::db::Driver abstract instproc dml {{-dbn ""} {-bind ""} -prepare qn sql} ::xo::db::Driver abstract instproc foreach {{-dbn ""} {-bind ""} -prepare qn sql {script}} + ::xo::db::Driver abstract instproc row_lock {{-dbn ""} {-bind ""} {-for "UPDATE"} -prepare qn sql} ::xo::db::Driver abstract instproc transaction {{-dbn ""} script args} ::xo::db::Driver abstract instproc ds {onOff} ::xo::db::Driver abstract instproc prepare {-handle {-argtypes ""} sql} @@ -553,6 +554,16 @@ uplevel [list ::db_list [uplevel [list [self] qn $qn]] $sql {*}$bindOpt] } + ::xo::db::DB instproc row_lock {{-dbn ""} {-bind ""} {-for "UPDATE"} -prepare qn sql} { + # + # PostgreSQL has several variants of row-level lock modes (the + # "for" part), but other database systems just support only "FOR + # UPDATE", which should work always. Therefore, ignore for other + # DB-systems the specified value and use just "FOR UPDATE". + # + :uplevel [list ::xo::dc list -dbn $dbn -bind $bind $qn "$sql FOR UPDATE"] + } + proc ::xo::db::pg_0or1row {sql} { ns_log notice "::xo::db::pg_0or1row deprecated" ::db_with_handle h { @@ -643,6 +654,11 @@ return [db_resultrows] } + ::xo::db::DB-postgresql instproc row_lock {{-dbn ""} {-bind ""} {-for "UPDATE"} -prepare qn sql} { + set prepareOpt [expr {[info exists prepare] ? [list -prepare $prepare] : ""}] + :uplevel [list ::xo::dc list -dbn $dbn -bind $bind {*}$prepareOpt $qn "$sql FOR $for"] + } + ::xo::db::DB-postgresql instproc prepare {-handle:required {-argtypes ""} sql} { # # Define a md5 key for the prepared statement in nsv based on the Index: openacs-4/packages/xotcl-core/tcl/cr-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/cr-procs.tcl,v diff -u -r1.76.2.36 -r1.76.2.37 --- openacs-4/packages/xotcl-core/tcl/cr-procs.tcl 6 Dec 2020 08:21:09 -0000 1.76.2.36 +++ openacs-4/packages/xotcl-core/tcl/cr-procs.tcl 24 Jan 2021 19:54:13 -0000 1.76.2.37 @@ -1001,6 +1001,10 @@ } ::xo::dc transaction { + ::xo::dc row_lock -for "no key update" -prepare integer item_lock { + select item_id from cr_items where item_id = :item_id + } + [:info class] instvar storage_type set revision_id [xo::dc nextval acs_object_id_seq] if {$storage_type eq "file"} { @@ -1036,18 +1040,27 @@ # If we do not make the revision live, use the old # revision_id, and let CrCache save it ...... # - # TODO: is this still needed? comment out for testing - # - #set revision_id $old_revision_id } + + # + # Update instance variables "modifying_user" and "last_modified" + # from potentially changed DB values. + # set :modifying_user $creation_user ::xo::dc 1row -prepare integer get_metadata { select context_id, last_modified from acs_objects where object_id = :revision_id } set :last_modified $last_modified - if {[info exists :context_id] && - $context_id != ${:context_id}} { + + # + # In case the context_id has in the DB is different as in the + # instance variable, push the value from the instance variable + # to the DB as well. + # + if {[info exists :context_id] + && $context_id != ${:context_id} + } { set context_id ${:context_id} ::xo::dc dml update_context { update acs_objects