mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-11-04 14:46:19 +08:00 
			
		
		
		
	Fixes #14289: Added yii\db\Command::executeResetSequence() to work with Oracle
				
					
				
			This commit is contained in:
		
				
					committed by
					
						
						Alexander Makarov
					
				
			
			
				
	
			
			
			
						parent
						
							68e5a9b315
						
					
				
				
					commit
					3555633223
				
			@ -4,6 +4,7 @@ Yii Framework 2 Change Log
 | 
				
			|||||||
2.0.16 under development
 | 
					2.0.16 under development
 | 
				
			||||||
------------------------
 | 
					------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Enh #14289: Added `yii\db\Command::executeResetSequence()` to work with Oracle (CedricYii)
 | 
				
			||||||
- Enh #9133: Added `yii\behaviors\OptimisticLockBehavior` (tunecino)
 | 
					- Enh #9133: Added `yii\behaviors\OptimisticLockBehavior` (tunecino)
 | 
				
			||||||
- Bug #16104: Fixed `yii\db\pgsql\QueryBuilder::dropIndex()` to prepend index name with schema name (wapmorgan)
 | 
					- Bug #16104: Fixed `yii\db\pgsql\QueryBuilder::dropIndex()` to prepend index name with schema name (wapmorgan)
 | 
				
			||||||
- Bug #16193: Fixed `yii\filters\Cors` to not reflect origin header value when configured to wildcard origins (Jianjun Chen)
 | 
					- Bug #16193: Fixed `yii\filters\Cors` to not reflect origin header value when configured to wildcard origins (Jianjun Chen)
 | 
				
			||||||
 | 
				
			|||||||
@ -931,10 +931,10 @@ class Command extends Component
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Creates a SQL command for resetting the sequence value of a table's primary key.
 | 
					     * Creates a SQL command for resetting the sequence value of a table's primary key.
 | 
				
			||||||
     * The sequence will be reset such that the primary key of the next new row inserted
 | 
					     * The sequence will be reset such that the primary key of the next new row inserted
 | 
				
			||||||
     * will have the specified value or 1.
 | 
					     * will have the specified value or the maximum existing value +1.
 | 
				
			||||||
     * @param string $table the name of the table whose primary key sequence will be reset
 | 
					     * @param string $table the name of the table whose primary key sequence will be reset
 | 
				
			||||||
     * @param mixed $value the value for the primary key of the next new row inserted. If this is not set,
 | 
					     * @param mixed $value the value for the primary key of the next new row inserted. If this is not set,
 | 
				
			||||||
     * the next new row's primary key will have a value 1.
 | 
					     * the next new row's primary key will have the maximum existing value +1.
 | 
				
			||||||
     * @return $this the command object itself
 | 
					     * @return $this the command object itself
 | 
				
			||||||
     * @throws NotSupportedException if this is not supported by the underlying DBMS
 | 
					     * @throws NotSupportedException if this is not supported by the underlying DBMS
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -945,6 +945,22 @@ class Command extends Component
 | 
				
			|||||||
        return $this->setSql($sql);
 | 
					        return $this->setSql($sql);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Executes a db command resetting the sequence value of a table's primary key.
 | 
				
			||||||
 | 
					     * Reason for execute is that some databases (Oracle) need several queries to do so.
 | 
				
			||||||
 | 
					     * The sequence is reset such that the primary key of the next new row inserted
 | 
				
			||||||
 | 
					     * will have the specified value or the maximum existing value +1.
 | 
				
			||||||
 | 
					     * @param string $table the name of the table whose primary key sequence is reset
 | 
				
			||||||
 | 
					     * @param mixed $value the value for the primary key of the next new row inserted. If this is not set,
 | 
				
			||||||
 | 
					     * the next new row's primary key will have the maximum existing value +1.
 | 
				
			||||||
 | 
					     * @throws NotSupportedException if this is not supported by the underlying DBMS
 | 
				
			||||||
 | 
					     * @since 2.0.16
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function executeResetSequence($table, $value = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->db->getQueryBuilder()->executeResetSequence($table, $value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Builds a SQL command for enabling or disabling integrity check.
 | 
					     * Builds a SQL command for enabling or disabling integrity check.
 | 
				
			||||||
     * @param bool $check whether to turn on or off the integrity check.
 | 
					     * @param bool $check whether to turn on or off the integrity check.
 | 
				
			||||||
 | 
				
			|||||||
@ -1028,10 +1028,10 @@ class QueryBuilder extends \yii\base\BaseObject
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Creates a SQL statement for resetting the sequence value of a table's primary key.
 | 
					     * Creates a SQL statement for resetting the sequence value of a table's primary key.
 | 
				
			||||||
     * The sequence will be reset such that the primary key of the next new row inserted
 | 
					     * The sequence will be reset such that the primary key of the next new row inserted
 | 
				
			||||||
     * will have the specified value or 1.
 | 
					     * will have the specified value or the maximum existing value +1.
 | 
				
			||||||
     * @param string $table the name of the table whose primary key sequence will be reset
 | 
					     * @param string $table the name of the table whose primary key sequence will be reset
 | 
				
			||||||
     * @param array|string $value the value for the primary key of the next new row inserted. If this is not set,
 | 
					     * @param array|string $value the value for the primary key of the next new row inserted. If this is not set,
 | 
				
			||||||
     * the next new row's primary key will have a value 1.
 | 
					     * the next new row's primary key will have the maximum existing value +1.
 | 
				
			||||||
     * @return string the SQL statement for resetting sequence
 | 
					     * @return string the SQL statement for resetting sequence
 | 
				
			||||||
     * @throws NotSupportedException if this is not supported by the underlying DBMS
 | 
					     * @throws NotSupportedException if this is not supported by the underlying DBMS
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -1040,6 +1040,22 @@ class QueryBuilder extends \yii\base\BaseObject
 | 
				
			|||||||
        throw new NotSupportedException($this->db->getDriverName() . ' does not support resetting sequence.');
 | 
					        throw new NotSupportedException($this->db->getDriverName() . ' does not support resetting sequence.');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Execute a SQL statement for resetting the sequence value of a table's primary key.
 | 
				
			||||||
 | 
					     * Reason for execute is that some databases (Oracle) need several queries to do so.
 | 
				
			||||||
 | 
					     * The sequence is reset such that the primary key of the next new row inserted
 | 
				
			||||||
 | 
					     * will have the specified value or the maximum existing value +1.
 | 
				
			||||||
 | 
					     * @param string $table the name of the table whose primary key sequence is reset
 | 
				
			||||||
 | 
					     * @param array|string $value the value for the primary key of the next new row inserted. If this is not set,
 | 
				
			||||||
 | 
					     * the next new row's primary key will have the maximum existing value +1.
 | 
				
			||||||
 | 
					     * @throws NotSupportedException if this is not supported by the underlying DBMS
 | 
				
			||||||
 | 
					     * @since 2.0.16
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function executeResetSequence($table, $value = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->db->createCommand()->resetSequence($table, $value)->execute();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Builds a SQL statement for enabling or disabling integrity check.
 | 
					     * Builds a SQL statement for enabling or disabling integrity check.
 | 
				
			||||||
     * @param bool $check whether to turn on or off the integrity check.
 | 
					     * @param bool $check whether to turn on or off the integrity check.
 | 
				
			||||||
 | 
				
			|||||||
@ -138,27 +138,34 @@ EOD;
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * {@inheritdoc}
 | 
					     * {@inheritdoc}
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function resetSequence($table, $value = null)
 | 
					    public function executeResetSequence($table, $value = null)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $tableSchema = $this->db->getTableSchema($table);
 | 
					        $tableSchema = $this->db->getTableSchema($table);
 | 
				
			||||||
        if ($tableSchema === null) {
 | 
					        if ($tableSchema === null) {
 | 
				
			||||||
            throw new InvalidArgumentException("Unknown table: $table");
 | 
					            throw new InvalidArgumentException("Unknown table: $table");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if ($tableSchema->sequenceName === null) {
 | 
					        if ($tableSchema->sequenceName === null) {
 | 
				
			||||||
            return '';
 | 
					            throw new InvalidArgumentException("There is no sequence associated with table: $table");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($value !== null) {
 | 
					        if ($value !== null) {
 | 
				
			||||||
            $value = (int) $value;
 | 
					            $value = (int) $value;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
 | 
					            if (count($tableSchema->primaryKey)>1) {
 | 
				
			||||||
 | 
					                throw new InvalidArgumentException("Can't reset sequence for composite primary key in table: $table");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            // use master connection to get the biggest PK value
 | 
					            // use master connection to get the biggest PK value
 | 
				
			||||||
            $value = $this->db->useMaster(function (Connection $db) use ($tableSchema) {
 | 
					            $value = $this->db->useMaster(function (Connection $db) use ($tableSchema) {
 | 
				
			||||||
                return $db->createCommand("SELECT MAX(\"{$tableSchema->primaryKey}\") FROM \"{$tableSchema->name}\"")->queryScalar();
 | 
					                return $db->createCommand(
 | 
				
			||||||
 | 
					                    'SELECT MAX("' . $tableSchema->primaryKey[0] . '") FROM "'. $tableSchema->name . '"'
 | 
				
			||||||
 | 
					                )->queryScalar();
 | 
				
			||||||
            }) + 1;
 | 
					            }) + 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return "DROP SEQUENCE \"{$tableSchema->name}_SEQ\";"
 | 
					        //Oracle needs at least two queries to reset sequence (see adding transactions and/or use alter method to avoid grants' issue?)
 | 
				
			||||||
            . "CREATE SEQUENCE \"{$tableSchema->name}_SEQ\" START WITH {$value} INCREMENT BY 1 NOMAXVALUE NOCACHE";
 | 
					        $this->db->createCommand('DROP SEQUENCE "' . $tableSchema->sequenceName . '"')->execute();
 | 
				
			||||||
 | 
					        $this->db->createCommand('CREATE SEQUENCE "' . $tableSchema->sequenceName . '" START WITH ' . $value
 | 
				
			||||||
 | 
					            . ' INCREMENT BY 1 NOMAXVALUE NOCACHE')->execute();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -125,7 +125,7 @@ class ActiveFixture extends BaseActiveFixture
 | 
				
			|||||||
        $table = $this->getTableSchema();
 | 
					        $table = $this->getTableSchema();
 | 
				
			||||||
        $this->db->createCommand()->delete($table->fullName)->execute();
 | 
					        $this->db->createCommand()->delete($table->fullName)->execute();
 | 
				
			||||||
        if ($table->sequenceName !== null) {
 | 
					        if ($table->sequenceName !== null) {
 | 
				
			||||||
            $this->db->createCommand()->resetSequence($table->fullName, 1)->execute();
 | 
					            $this->db->createCommand()->executeResetSequence($table->fullName, 1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -106,19 +106,19 @@ class QueryBuilderTest extends \yiiunit\framework\db\QueryBuilderTest
 | 
				
			|||||||
        $this->assertEquals($this->replaceQuotes($expected), $sql);
 | 
					        $this->assertEquals($this->replaceQuotes($expected), $sql);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function testResetSequence()
 | 
					    public function testExecuteResetSequence()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        $db = $this->getConnection();
 | 
				
			||||||
        $qb = $this->getQueryBuilder();
 | 
					        $qb = $this->getQueryBuilder();
 | 
				
			||||||
 | 
					        $sqlResult = "SELECT last_number FROM user_sequences WHERE sequence_name = 'item_SEQ'";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $expected = 'DROP SEQUENCE "item_SEQ";'
 | 
					        $qb->executeResetSequence('item');
 | 
				
			||||||
            . 'CREATE SEQUENCE "item_SEQ" START WITH 6 INCREMENT BY 1 NOMAXVALUE NOCACHE';
 | 
					        $result = $db->createCommand($sqlResult)->queryScalar();
 | 
				
			||||||
        $sql = $qb->resetSequence('item');
 | 
					        $this->assertEquals(6, $result);
 | 
				
			||||||
        $this->assertEquals($expected, $sql);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $expected = 'DROP SEQUENCE "item_SEQ";'
 | 
					        $qb->executeResetSequence('item', 4);
 | 
				
			||||||
            . 'CREATE SEQUENCE "item_SEQ" START WITH 4 INCREMENT BY 1 NOMAXVALUE NOCACHE';
 | 
					        $result = $db->createCommand($sqlResult)->queryScalar();
 | 
				
			||||||
        $sql = $qb->resetSequence('item', 4);
 | 
					        $this->assertEquals(4, $result);
 | 
				
			||||||
        $this->assertEquals($expected, $sql);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function likeConditionProvider()
 | 
					    public function likeConditionProvider()
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user