From: jenkins-bot Date: Mon, 13 Jan 2014 03:15:46 +0000 (+0000) Subject: Merge "Changed FOR UPDATE handling in Postgresql" X-Git-Tag: 1.31.0-rc.0~17271 X-Git-Url: https://git.cyclocoop.org/%27.WWW_URL.%27admin/?a=commitdiff_plain;h=da39646ddc98bce9cc1243ab217428e449b5d9ae;hp=0998c41943459bec74b95397976f6fed25b99c4a;p=lhc%2Fweb%2Fwiklou.git Merge "Changed FOR UPDATE handling in Postgresql" --- diff --git a/includes/db/DatabasePostgres.php b/includes/db/DatabasePostgres.php index 7f0ea97635..cb671d8ddb 100644 --- a/includes/db/DatabasePostgres.php +++ b/includes/db/DatabasePostgres.php @@ -819,6 +819,29 @@ __INDEXATTR__; return $res->numRows() > 0; } + /** + * Change the FOR UPDATE option as necessary based on the join conditions. Then pass + * to the parent function to get the actual SQL text. + * + * In Postgres when using FOR UPDATE, only the main table and tables that are inner joined + * can be locked. That means tables in an outer join cannot be FOR UPDATE locked. Trying to do + * so causes a DB error. This wrapper checks which tables can be locked and adjusts it accordingly. + */ + function selectSQLText( $table, $vars, $conds = '', $fname = __METHOD__, $options = array(), $join_conds = array() ) { + $forUpdateKey = array_search( 'FOR UPDATE', $options ); + if ( $forUpdateKey !== false && $join_conds ) { + unset( $options[$forUpdateKey] ); + + foreach ( $join_conds as $table => $join_cond ) { + if ( 0 === preg_match( '/^(?:LEFT|RIGHT|FULL)(?: OUTER)? JOIN$/i', $join_cond[0] ) ) { + $options['FOR UPDATE'][] = $table; + } + } + } + + return parent::selectSQLText( $table, $vars, $conds, $fname, $options, $join_conds ); + } + /** * INSERT wrapper, inserts an array into a table * @@ -1537,9 +1560,12 @@ SQL; // : false ); //} - if ( isset( $noKeyOptions['FOR UPDATE'] ) ) { + if ( isset( $options['FOR UPDATE'] ) ) { + $postLimitTail .= ' FOR UPDATE OF ' . implode( ', ', $options['FOR UPDATE'] ); + } else if ( isset( $noKeyOptions['FOR UPDATE'] ) ) { $postLimitTail .= ' FOR UPDATE'; } + if ( isset( $noKeyOptions['DISTINCT'] ) || isset( $noKeyOptions['DISTINCTROW'] ) ) { $startOpts .= 'DISTINCT'; }