Merge "Show a warning in edit preview when a template loop is detected"
[lhc/web/wiklou.git] / includes / libs / rdbms / database / DatabasePostgres.php
index bdac06c..672b345 100644 (file)
@@ -39,8 +39,6 @@ class DatabasePostgres extends Database {
        /** @var int The number of rows affected as an integer */
        protected $mAffectedRows = null;
 
-       /** @var int */
-       private $mInsertId = null;
        /** @var float|string */
        private $numericVersion = null;
        /** @var string Connect string to open a PostgreSQL connection */
@@ -352,14 +350,10 @@ class DatabasePostgres extends Database {
                return pg_field_name( $res, $n );
        }
 
-       /**
-        * Return the result of the last call to nextSequenceValue();
-        * This must be called after nextSequenceValue().
-        *
-        * @return int|null
-        */
        public function insertId() {
-               return $this->mInsertId;
+               $res = $this->query( "SELECT lastval()" );
+               $row = $this->fetchRow( $res );
+               return is_null( $row[0] ) ? null : (int)$row[0];
        }
 
        public function dataSeek( $res, $row ) {
@@ -521,6 +515,10 @@ __INDEXATTR__;
        public function selectSQLText(
                $table, $vars, $conds = '', $fname = __METHOD__, $options = [], $join_conds = []
        ) {
+               if ( is_string( $options ) ) {
+                       $options = [ $options ];
+               }
+
                // 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
@@ -532,12 +530,28 @@ __INDEXATTR__;
                        $forUpdateKey = array_search( 'FOR UPDATE', $options, true );
                        if ( $forUpdateKey !== false && $join_conds ) {
                                unset( $options[$forUpdateKey] );
+                               $options['FOR UPDATE'] = [];
+
+                               // All tables not in $join_conds are good
+                               foreach ( $table as $alias => $name ) {
+                                       if ( is_numeric( $alias ) ) {
+                                               $alias = $name;
+                                       }
+                                       if ( !isset( $join_conds[$alias] ) ) {
+                                               $options['FOR UPDATE'][] = $alias;
+                                       }
+                               }
 
                                foreach ( $join_conds as $table_cond => $join_cond ) {
                                        if ( 0 === preg_match( '/^(?:LEFT|RIGHT|FULL)(?: OUTER)? JOIN$/i', $join_cond[0] ) ) {
                                                $options['FOR UPDATE'][] = $table_cond;
                                        }
                                }
+
+                               // Quote alias names so $this->tableName() won't mangle them
+                               $options['FOR UPDATE'] = array_map( function ( $name ) use ( $table ) {
+                                       return isset( $table[$name] ) ? $this->addIdentifierQuotes( $name ) : $name;
+                               }, $options['FOR UPDATE'] );
                        }
 
                        if ( isset( $options['ORDER BY'] ) && $options['ORDER BY'] == 'NULL' ) {
@@ -756,12 +770,7 @@ __INDEXATTR__;
        }
 
        public function nextSequenceValue( $seqName ) {
-               $safeseq = str_replace( "'", "''", $seqName );
-               $res = $this->query( "SELECT nextval('$safeseq')" );
-               $row = $this->fetchRow( $res );
-               $this->mInsertId = is_null( $row[0] ) ? null : (int)$row[0];
-
-               return $this->mInsertId;
+               return new NextSequenceValue;
        }
 
        /**
@@ -1149,8 +1158,8 @@ SQL;
        }
 
        /**
-        * @var string $table
-        * @var string $field
+        * @param string $table
+        * @param string $field
         * @return PostgresField|null
         */
        public function fieldInfo( $table, $field ) {
@@ -1204,6 +1213,8 @@ SQL;
                                $s = pg_escape_bytea( $conn, $s->fetch() );
                        }
                        return "'$s'";
+               } elseif ( $s instanceof NextSequenceValue ) {
+                       return 'DEFAULT';
                }
 
                return "'" . pg_escape_string( $conn, $s ) . "'";