Fix #17679: Fix Oracle exception "ORA-01461: can bind a LONG value only for insert into a LONG column" when inserting 4k+ string

This commit is contained in:
vinpel
2020-03-02 21:26:53 +01:00
committed by GitHub
parent e22c9c6d68
commit f165b6b31f
5 changed files with 71 additions and 9 deletions

View File

@ -4,6 +4,7 @@ Yii Framework 2 Change Log
2.0.33 under development 2.0.33 under development
------------------------ ------------------------
- Bug #17679: Fix Oracle exception "ORA-01461: can bind a LONG value only for insert into a LONG column" when inserting 4k+ string (vinpel, 243083df)
- Bug #17859: Fix loading fixtures under Windows (samdark) - Bug #17859: Fix loading fixtures under Windows (samdark)
- Bug #11945: Fix Schema Builder MySQL column definition order (simialbi) - Bug #11945: Fix Schema Builder MySQL column definition order (simialbi)
- Bug #17886: yii\rest\Serializer serialize arrays (patacca) - Bug #17886: yii\rest\Serializer serialize arrays (patacca)

View File

@ -90,8 +90,9 @@ class Command extends Component
/** /**
* @var array pending parameters to be bound to the current PDO statement. * @var array pending parameters to be bound to the current PDO statement.
* @since 2.0.33
*/ */
private $_pendingParams = []; protected $pendingParams = [];
/** /**
* @var string the SQL statement that this command represents * @var string the SQL statement that this command represents
*/ */
@ -312,10 +313,10 @@ class Command extends Component
*/ */
protected function bindPendingParams() protected function bindPendingParams()
{ {
foreach ($this->_pendingParams as $name => $value) { foreach ($this->pendingParams as $name => $value) {
$this->pdoStatement->bindValue($name, $value[0], $value[1]); $this->pdoStatement->bindValue($name, $value[0], $value[1]);
} }
$this->_pendingParams = []; $this->pendingParams = [];
} }
/** /**
@ -334,7 +335,7 @@ class Command extends Component
if ($dataType === null) { if ($dataType === null) {
$dataType = $this->db->getSchema()->getPdoType($value); $dataType = $this->db->getSchema()->getPdoType($value);
} }
$this->_pendingParams[$name] = [$value, $dataType]; $this->pendingParams[$name] = [$value, $dataType];
$this->params[$name] = $value; $this->params[$name] = $value;
return $this; return $this;
@ -360,14 +361,14 @@ class Command extends Component
$schema = $this->db->getSchema(); $schema = $this->db->getSchema();
foreach ($values as $name => $value) { foreach ($values as $name => $value) {
if (is_array($value)) { // TODO: Drop in Yii 2.1 if (is_array($value)) { // TODO: Drop in Yii 2.1
$this->_pendingParams[$name] = $value; $this->pendingParams[$name] = $value;
$this->params[$name] = $value[0]; $this->params[$name] = $value[0];
} elseif ($value instanceof PdoValue) { } elseif ($value instanceof PdoValue) {
$this->_pendingParams[$name] = [$value->getValue(), $value->getType()]; $this->pendingParams[$name] = [$value->getValue(), $value->getType()];
$this->params[$name] = $value->getValue(); $this->params[$name] = $value->getValue();
} else { } else {
$type = $schema->getPdoType($value); $type = $schema->getPdoType($value);
$this->_pendingParams[$name] = [$value, $type]; $this->pendingParams[$name] = [$value, $type];
$this->params[$name] = $value; $this->params[$name] = $value;
} }
} }
@ -1308,7 +1309,7 @@ class Command extends Component
protected function reset() protected function reset()
{ {
$this->_sql = null; $this->_sql = null;
$this->_pendingParams = []; $this->pendingParams = [];
$this->params = []; $this->params = [];
$this->_refreshTableName = null; $this->_refreshTableName = null;
$this->_isolationLevel = false; $this->_isolationLevel = false;

View File

@ -317,7 +317,7 @@ class Connection extends Component
'sqlite' => 'yii\db\sqlite\Command', // sqlite 3 'sqlite' => 'yii\db\sqlite\Command', // sqlite 3
'sqlite2' => 'yii\db\sqlite\Command', // sqlite 2 'sqlite2' => 'yii\db\sqlite\Command', // sqlite 2
'sqlsrv' => 'yii\db\Command', // newer MSSQL driver on MS Windows hosts 'sqlsrv' => 'yii\db\Command', // newer MSSQL driver on MS Windows hosts
'oci' => 'yii\db\Command', // Oracle driver 'oci' => 'yii\db\oci\Command', // Oracle driver
'mssql' => 'yii\db\Command', // older MSSQL driver on MS Windows hosts 'mssql' => 'yii\db\Command', // older MSSQL driver on MS Windows hosts
'dblib' => 'yii\db\Command', // dblib drivers on GNU/Linux (and maybe other OSes) hosts 'dblib' => 'yii\db\Command', // dblib drivers on GNU/Linux (and maybe other OSes) hosts
'cubrid' => 'yii\db\Command', // CUBRID 'cubrid' => 'yii\db\Command', // CUBRID

View File

@ -0,0 +1,34 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\db\oci;
/**
* Command represents an Oracle SQL statement to be executed against a database.
*
* {@inheritdoc}
*
* @since 2.0.33
*/
class Command extends \yii\db\Command
{
/**
* {@inheritdoc}
*/
protected function bindPendingParams()
{
foreach ($this->pendingParams as $name => $value) {
if (\PDO::PARAM_STR === $value[1]) {
$passedByRef = $value[0];
$this->pdoStatement->bindParam($name, $passedByRef, $value[1], strlen($value[0]));
} else {
$this->pdoStatement->bindValue($name, $value[0], $value[1]);
}
}
$this->pendingParams = [];
}
}

View File

@ -7,6 +7,7 @@
namespace yiiunit\framework\db\oci; namespace yiiunit\framework\db\oci;
use yii\db\Schema;
/** /**
* @group db * @group db
* @group oci * @group oci
@ -42,4 +43,29 @@ class CommandTest extends \yiiunit\framework\db\CommandTest
return $data; return $data;
} }
/**
* Testing the "ORA-01461: can bind a LONG value only for insert into a LONG column"
*
* @return void
*/
public function testCLOBStringInsertion()
{
$db = $this->getConnection();
if ($db->getSchema()->getTableSchema('longstring') !== null) {
$db->createCommand()->dropTable('longstring')->execute();
}
$db->createCommand()->createTable('longstring', ['message' => Schema::TYPE_TEXT])->execute();
$longData = str_pad('-', 4001, '-=', STR_PAD_LEFT);
$db->createCommand()->insert('longstring', [
'message' => $longData,
])->execute();
$this->assertEquals(1, $db->createCommand('SELECT count(*) FROM {{longstring}}')->queryScalar());
$db->createCommand()->dropTable('longstring')->execute();
}
} }