From 000f5db3602a39ad3b7cd671a1165393b0aa41df Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 26 Sep 2012 17:42:32 +0200 Subject: [PATCH] Allow ORMTable to access a foreign wiki. wfGetDB() allows us to connect to another wiki's database using LoadBalancer's openForeignConnection method. This change adds an option to ORMTable that allows it to use this facility, so it can be used to access tables on other wikis. Change-Id: I261a2a31e7188f6793b8a110ab764be5ecd09920 --- includes/db/IORMTable.php | 66 ++++++++++++++++++++ includes/db/ORMTable.php | 125 +++++++++++++++++++++++++++++++++++--- 2 files changed, 181 insertions(+), 10 deletions(-) diff --git a/includes/db/IORMTable.php b/includes/db/IORMTable.php index 99413f99b9..9693789f02 100644 --- a/includes/db/IORMTable.php +++ b/includes/db/IORMTable.php @@ -298,6 +298,72 @@ interface IORMTable { */ public function setReadDb( $db ); + + /** + * Get the ID of the any foreign wiki to use as a target for database operations + * + * @since 1.20 + * + * @return String|bool The target wiki, in a form that LBFactory understands (or false if the local wiki is used) + */ + public function getTargetWiki(); + + /** + * Set the ID of the any foreign wiki to use as a target for database operations + * + * @param String|bool $wiki The target wiki, in a form that LBFactory understands (or false if the local wiki shall be used) + * + * @since 1.20 + */ + public function setTargetWiki( $wiki ); + + /** + * Get the database type used for read operations. + * This is to be used instead of wfGetDB. + * + * @see LoadBalancer::getConnection + * + * @since 1.20 + * + * @return DatabaseBase The database object + */ + public function getReadDbConnection(); + + /** + * Get the database type used for read operations. + * This is to be used instead of wfGetDB. + * + * @see LoadBalancer::getConnection + * + * @since 1.20 + * + * @return DatabaseBase The database object + */ + public function getWriteDbConnection(); + + /** + * Get the database type used for read operations. + * + * @see wfGetLB + * + * @since 1.20 + * + * @return LoadBalancer The database load balancer object + */ + public function getLoadBalancer(); + + /** + * Releases the lease on the given database connection. This is useful mainly + * for connections to a foreign wiki. It does nothing for connections to the local wiki. + * + * @see LoadBalancer::reuseConnection + * + * @param DatabaseBase $db the database + * + * @since 1.20 + */ + public function releaseConnection( DatabaseBase $db ); + /** * Update the records matching the provided conditions by * setting the fields that are keys in the $values param to diff --git a/includes/db/ORMTable.php b/includes/db/ORMTable.php index a77074ffca..bcbf17f33c 100644 --- a/includes/db/ORMTable.php +++ b/includes/db/ORMTable.php @@ -47,7 +47,7 @@ abstract class ORMTable implements IORMTable { protected static $instanceCache = array(); /** - * The database connection to use for read operations. + * ID of the database connection to use for read operations. * Can be changed via @see setReadDb. * * @since 1.20 @@ -55,6 +55,15 @@ abstract class ORMTable implements IORMTable { */ protected $readDb = DB_SLAVE; + /** + * The ID of any foreign wiki to use as a target for database operations, + * or false to use the local wiki. + * + * @since 1.20 + * @var String|bool + */ + protected $wiki = false; + /** * Returns a list of default field values. * field name => field value @@ -145,13 +154,17 @@ abstract class ORMTable implements IORMTable { $fields = (array)$fields; } - return wfGetDB( $this->getReadDb() )->select( + $dbr = $this->getReadDbConnection(); + $result = $dbr->select( $this->getName(), $this->getPrefixedFields( $fields ), $this->getPrefixedValues( $conditions ), is_null( $functionName ) ? __METHOD__ : $functionName, $options ); + + $this->releaseConnection( $dbr ); + return $result; } /** @@ -241,15 +254,18 @@ abstract class ORMTable implements IORMTable { */ public function rawSelectRow( array $fields, array $conditions = array(), array $options = array(), $functionName = null ) { - $dbr = wfGetDB( $this->getReadDb() ); + $dbr = $this->getReadDbConnection(); - return $dbr->selectRow( + $result = $dbr->selectRow( $this->getName(), $fields, $conditions, is_null( $functionName ) ? __METHOD__ : $functionName, $options ); + + $this->releaseConnection( $dbr ); + return $result; } /** @@ -327,11 +343,16 @@ abstract class ORMTable implements IORMTable { * @return boolean Success indicator */ public function delete( array $conditions, $functionName = null ) { - return wfGetDB( DB_MASTER )->delete( + $dbw = $this->getWriteDbConnection(); + + $result = $dbw->delete( $this->getName(), $conditions === array() ? '*' : $this->getPrefixedValues( $conditions ), $functionName ) !== false; // DatabaseBase::delete does not always return true for success as documented... + + $this->releaseConnection( $dbw ); + return $result; } /** @@ -397,7 +418,7 @@ abstract class ORMTable implements IORMTable { } /** - * Get the database type used for read operations. + * Get the database ID used for read operations. * * @since 1.20 * @@ -408,7 +429,7 @@ abstract class ORMTable implements IORMTable { } /** - * Set the database type to use for read operations. + * Set the database ID to use for read operations, use DB_XXX constants or an index to the load balancer setup. * * @param integer $db * @@ -418,6 +439,86 @@ abstract class ORMTable implements IORMTable { $this->readDb = $db; } + /** + * Get the ID of the any foreign wiki to use as a target for database operations + * + * @since 1.20 + * + * @return String|bool The target wiki, in a form that LBFactory understands (or false if the local wiki is used) + */ + public function getTargetWiki() { + return $this->wiki; + } + + /** + * Set the ID of the any foreign wiki to use as a target for database operations + * + * @param String|bool $wiki The target wiki, in a form that LBFactory understands (or false if the local wiki shall be used) + * + * @since 1.20 + */ + public function setTargetWiki( $wiki ) { + $this->wiki = $wiki; + } + + /** + * Get the database type used for read operations. + * This is to be used instead of wfGetDB. + * + * @see LoadBalancer::getConnection + * + * @since 1.20 + * + * @return DatabaseBase The database object + */ + public function getReadDbConnection() { + return $this->getLoadBalancer()->getConnection( $this->getReadDb(), array(), $this->getTargetWiki() ); + } + + /** + * Get the database type used for read operations. + * This is to be used instead of wfGetDB. + * + * @see LoadBalancer::getConnection + * + * @since 1.20 + * + * @return DatabaseBase The database object + */ + public function getWriteDbConnection() { + return $this->getLoadBalancer()->getConnection( DB_MASTER, array(), $this->getTargetWiki() ); + } + + /** + * Get the database type used for read operations. + * + * @see wfGetLB + * + * @since 1.20 + * + * @return LoadBalancer The database load balancer object + */ + public function getLoadBalancer() { + return wfGetLB( $this->getTargetWiki() ); + } + + /** + * Releases the lease on the given database connection. This is useful mainly + * for connections to a foreign wiki. It does nothing for connections to the local wiki. + * + * @see LoadBalancer::reuseConnection + * + * @param DatabaseBase $db the database + * + * @since 1.20 + */ + public function releaseConnection( DatabaseBase $db ) { + if ( $this->wiki !== false ) { + // recycle connection to foreign wiki + $this->getLoadBalancer()->reuseConnection( $db ); + } + } + /** * Update the records matching the provided conditions by * setting the fields that are keys in the $values param to @@ -431,14 +532,17 @@ abstract class ORMTable implements IORMTable { * @return boolean Success indicator */ public function update( array $values, array $conditions = array() ) { - $dbw = wfGetDB( DB_MASTER ); + $dbw = $this->getWriteDbConnection(); - return $dbw->update( + $result = $dbw->update( $this->getName(), $this->getPrefixedValues( $values ), $this->getPrefixedValues( $conditions ), __METHOD__ ) !== false; // DatabaseBase::update does not always return true for success as documented... + + $this->releaseConnection( $dbw ); + return $result; } /** @@ -450,6 +554,7 @@ abstract class ORMTable implements IORMTable { * @param array $conditions */ public function updateSummaryFields( $summaryFields = null, array $conditions = array() ) { + $slave = $this->getReadDb(); $this->setReadDb( DB_MASTER ); /** @@ -461,7 +566,7 @@ abstract class ORMTable implements IORMTable { $item->save(); } - $this->setReadDb( DB_SLAVE ); + $this->setReadDb( $slave ); } /** -- 2.20.1