/** @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 */
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 ) {
}
}
- public function affectedRows() {
+ protected function fetchAffectedRowCount() {
if ( !is_null( $this->mAffectedRows ) ) {
// Forced result for simulated queries
return $this->mAffectedRows;
unset( $options[$forUpdateKey] );
$options['FOR UPDATE'] = [];
- // All tables not in $join_conds are good
- foreach ( $table as $alias => $name ) {
- if ( is_numeric( $alias ) ) {
+ $toCheck = $table;
+ reset( $toCheck );
+ while ( $toCheck ) {
+ $alias = key( $toCheck );
+ $name = $toCheck[$alias];
+ unset( $toCheck[$alias] );
+
+ $hasAlias = !is_numeric( $alias );
+ if ( !$hasAlias && is_string( $name ) ) {
$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;
+ if ( !isset( $join_conds[$alias] ) ||
+ !preg_match( '/^(?:LEFT|RIGHT|FULL)(?: OUTER)? JOIN$/i', $join_conds[$alias][0] )
+ ) {
+ if ( is_array( $name ) ) {
+ // It's a parenthesized group, process all the tables inside the group.
+ $toCheck = array_merge( $toCheck, $name );
+ } else {
+ // Quote alias names so $this->tableName() won't mangle them
+ $options['FOR UPDATE'][] = $hasAlias ? $this->addIdentifierQuotes( $alias ) : $alias;
+ }
}
}
-
- // 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' ) {
}
// If IGNORE is set, we use savepoints to emulate mysql's behavior
+ // @todo If PostgreSQL 9.5+, we could use ON CONFLICT DO NOTHING instead
$savepoint = $olde = null;
$numrowsinserted = 0;
if ( in_array( 'IGNORE', $options ) ) {
}
/*
- * If IGNORE is set, we use savepoints to emulate mysql's behavior
- * Ignore LOW PRIORITY option, since it is MySQL-specific
+ * If IGNORE is set, use the non-native version.
+ * @todo If PostgreSQL 9.5+, we could use ON CONFLICT DO NOTHING
*/
- $savepoint = $olde = null;
- $numrowsinserted = 0;
if ( in_array( 'IGNORE', $insertOptions ) ) {
- $savepoint = new SavepointPostgres( $this, 'mw', $this->queryLogger );
- $olde = error_reporting( 0 );
- $savepoint->savepoint();
+ return $this->nonNativeInsertSelect(
+ $destTable, $srcTable, $varMap, $conds, $fname, $insertOptions, $selectOptions, $selectJoinConds
+ );
}
- $res = parent::nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname,
+ return parent::nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname,
$insertOptions, $selectOptions, $selectJoinConds );
-
- if ( $savepoint ) {
- $bar = pg_result_error( $this->mLastResult );
- if ( $bar != false ) {
- $savepoint->rollback();
- } else {
- $savepoint->release();
- $numrowsinserted++;
- }
- error_reporting( $olde );
- $savepoint->commit();
-
- // Set the affected row count for the whole operation
- $this->mAffectedRows = $numrowsinserted;
-
- // IGNORE always returns true
- return true;
- }
-
- return $res;
}
public function tableName( $name, $format = 'quoted' ) {
}
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;
}
/**
}
/**
- * @var string $table
- * @var string $field
+ * @param string $table
+ * @param string $field
* @return PostgresField|null
*/
public function fieldInfo( $table, $field ) {
public function strencode( $s ) {
// Should not be called by us
- return pg_escape_string( $this->getBindingHandle(), $s );
+ return pg_escape_string( $this->getBindingHandle(), (string)$s );
}
public function addQuotes( $s ) {
$s = pg_escape_bytea( $conn, $s->fetch() );
}
return "'$s'";
+ } elseif ( $s instanceof NextSequenceValue ) {
+ return 'DEFAULT';
}
- return "'" . pg_escape_string( $conn, $s ) . "'";
+ return "'" . pg_escape_string( $conn, (string)$s ) . "'";
}
/**