Merge "Move TransactionProfiler to /libs/rdbms"
[lhc/web/wiklou.git] / includes / db / DatabasePostgres.php
index 867aeb8..22445c0 100644 (file)
@@ -149,7 +149,7 @@ class SavepointPostgres {
                $this->didbegin = false;
                /* If we are not in a transaction, we need to be for savepoint trickery */
                if ( !$dbw->trxLevel() ) {
-                       $dbw->begin( "FOR SAVEPOINT" );
+                       $dbw->begin( "FOR SAVEPOINT", DatabasePostgres::TRANSACTION_INTERNAL );
                        $this->didbegin = true;
                }
        }
@@ -904,7 +904,7 @@ __INDEXATTR__;
         * @param array $selectOptions
         * @return bool
         */
-       function insertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__,
+       function nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__,
                $insertOptions = [], $selectOptions = [] ) {
                $destTable = $this->tableName( $destTable );
 
@@ -927,7 +927,8 @@ __INDEXATTR__;
                if ( !is_array( $selectOptions ) ) {
                        $selectOptions = [ $selectOptions ];
                }
-               list( $startOpts, $useIndex, $tailOpts ) = $this->makeSelectOptions( $selectOptions );
+               list( $startOpts, $useIndex, $tailOpts, $ignoreIndex ) =
+                       $this->makeSelectOptions( $selectOptions );
                if ( is_array( $srcTable ) ) {
                        $srcTable = implode( ',', array_map( [ &$this, 'tableName' ], $srcTable ) );
                } else {
@@ -936,7 +937,7 @@ __INDEXATTR__;
 
                $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' .
                        " SELECT $startOpts " . implode( ',', $varMap ) .
-                       " FROM $srcTable $useIndex";
+                       " FROM $srcTable $useIndex $ignoreIndex ";
 
                if ( $conds != '*' ) {
                        $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
@@ -1207,7 +1208,7 @@ __INDEXATTR__;
         * @param string $desiredSchema
         */
        function determineCoreSchema( $desiredSchema ) {
-               $this->begin( __METHOD__ );
+               $this->begin( __METHOD__, self::TRANSACTION_INTERNAL );
                if ( $this->schemaExists( $desiredSchema ) ) {
                        if ( in_array( $desiredSchema, $this->getSchemas() ) ) {
                                $this->mCoreSchema = $desiredSchema;
@@ -1482,7 +1483,7 @@ SQL;
         */
        function makeSelectOptions( $options ) {
                $preLimitTail = $postLimitTail = '';
-               $startOpts = $useIndex = '';
+               $startOpts = $useIndex = $ignoreIndex = '';
 
                $noKeyOptions = [];
                foreach ( $options as $key => $option ) {
@@ -1512,7 +1513,7 @@ SQL;
                        $startOpts .= 'DISTINCT';
                }
 
-               return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail ];
+               return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail, $ignoreIndex ];
        }
 
        function getDBname() {
@@ -1535,6 +1536,15 @@ SQL;
                return '(' . $this->selectSQLText( $table, $fld, $conds, null, [], $join_conds ) . ')';
        }
 
+       /**
+        * @param string $field Field or column to cast
+        * @return string
+        * @since 1.28
+        */
+       public function buildStringCast( $field ) {
+               return $field . '::text';
+       }
+
        public function getSearchEngine() {
                return 'SearchPostgres';
        }
@@ -1579,21 +1589,21 @@ SQL;
         */
        public function lock( $lockName, $method, $timeout = 5 ) {
                $key = $this->addQuotes( $this->bigintFromLockName( $lockName ) );
-               for ( $attempts = 1; $attempts <= $timeout; ++$attempts ) {
-                       $result = $this->query(
-                               "SELECT pg_try_advisory_lock($key) AS lockstatus", $method );
-                       $row = $this->fetchObject( $result );
-                       if ( $row->lockstatus === 't' ) {
-                               parent::lock( $lockName, $method, $timeout ); // record
-                               return true;
-                       } else {
-                               sleep( 1 );
-                       }
-               }
+               $loop = new WaitConditionLoop(
+                       function () use ( $lockName, $key, $timeout, $method ) {
+                               $res = $this->query( "SELECT pg_try_advisory_lock($key) AS lockstatus", $method );
+                               $row = $this->fetchObject( $res );
+                               if ( $row->lockstatus === 't' ) {
+                                       parent::lock( $lockName, $method, $timeout ); // record
+                                       return true;
+                               }
 
-               wfDebug( __METHOD__ . " failed to acquire lock\n" );
+                               return WaitConditionLoop::CONDITION_CONTINUE;
+                       },
+                       $timeout
+               );
 
-               return false;
+               return ( $loop->invoke() === $loop::CONDITION_REACHED );
        }
 
        /**