Skip to content

Commit

Permalink
Updated to work with blob data type;
Browse files Browse the repository at this point in the history
  • Loading branch information
edgardmessias committed Nov 9, 2016
1 parent 45ee3be commit 5886177
Show file tree
Hide file tree
Showing 10 changed files with 44 additions and 185 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Functions not supported by the Firebird database:

* Rename Table
* Check Integrity
* BLOB data type - [See this bug](https://bugs.php.net/bug.php?id=61183)
* BLOB data type for pdo_firebird <= 7.0.13 - [See this bug](https://bugs.php.net/bug.php?id=61183)

Installation
------------
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"yiisoft/yii2": "~2.0.10"
},
"require-dev": {
"yiisoft/yii2-dev": "2.0.x-dev",
"yiisoft/yii2-dev": "~2.0.10",
"yiisoft/yii2-coding-standards": "^2.0.2",
"phpunit/phpunit": "~4.8"
},
Expand Down
18 changes: 8 additions & 10 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

150 changes: 5 additions & 145 deletions src/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,6 @@
class Command extends \yii\db\Command
{

/**
* @var array pending parameters to be bound to the current PDO statement.
*/
private $_pendingParams = [];

/**
* @var string the SQL statement that this command represents
*/
private $_sql;

/**
* @var string name of the table, which schema, should be refreshed after command execution.
*/
private $_refreshTableName;

/**
* Binds a parameter to the SQL statement to be executed.
* @param string|integer $name parameter identifier. For a prepared statement
Expand All @@ -45,35 +30,14 @@ class Command extends \yii\db\Command
*/
public function bindParam($name, &$value, $dataType = null, $length = null, $driverOptions = null)
{
if ($dataType === null) {
$dataType = $this->db->getSchema()->getPdoType($value);
}
if ($dataType == \PDO::PARAM_BOOL) {
$dataType = \PDO::PARAM_INT;
}
return parent::bindParam($name, $value, $dataType, $length, $driverOptions);
}
/**
* Binds pending parameters that were registered via [[bindValue()]] and [[bindValues()]].
* Note that this method requires an active [[pdoStatement]].
*/
protected function bindPendingParams()
{
foreach ($this->_pendingParams as $name => $value) {
if ($value[1] == 'blob') {
$this->pdoStatement->bindParam($name, $value[0]);
} else {
$this->pdoStatement->bindValue($name, $value[0], $value[1]);
}
}
$this->_pendingParams = [];
}

/**
* Returns the SQL statement for this command.
* @return string the SQL statement to be executed
*/
public function getSql()
{
return $this->_sql;
}

/**
* Specifies the SQL statement to be executed.
Expand All @@ -83,63 +47,16 @@ public function getSql()
*/
public function setSql($sql)
{
$refreshTableName = null;

$matches = null;
if (preg_match("/^\s*DROP TABLE IF EXISTS (['\"]?([^\s\;]+)['\"]?);?\s*$/i", $sql, $matches)) {
if ($this->db->getSchema()->getTableSchema($matches[2]) !== null) {
$sql = $this->db->getQueryBuilder()->dropTable($matches[2]);
} else {
$sql = 'select 1 from RDB$DATABASE;'; //Prevent Drop Table
}
$refreshTableName = $matches[2];
}

if ($sql !== $this->_sql) {
$this->cancel();
$this->_sql = $this->db->quoteSql($sql);
$this->_pendingParams = [];
$this->params = [];
$this->_refreshTableName = $refreshTableName;
}

return $this;
}

/**
* Returns the raw SQL by inserting parameter values into the corresponding placeholders in [[sql]].
* Note that the return value of this method should mainly be used for logging purpose.
* It is likely that this method returns an invalid SQL due to improper replacement of parameter placeholders.
* @return string the raw SQL with parameter values inserted into the corresponding placeholders in [[sql]].
*/
public function getRawSql()
{
if (empty($this->params)) {
return $this->_sql;
}
$params = [];
foreach ($this->params as $name => $value) {
if (is_string($name) && strncmp(':', $name, 1)) {
$name = ':' . $name;
}
if (is_string($value)) {
$params[$name] = $this->db->quoteValue($value);
} elseif (is_bool($value)) {
$params[$name] = ($value ? 'TRUE' : 'FALSE');
} elseif ($value === null) {
$params[$name] = 'NULL';
} elseif (!is_object($value) && !is_resource($value)) {
$params[$name] = $value;
}
}
if (!isset($params[1])) {
return strtr($this->_sql, $params);
}
$sql = '';
foreach (explode('?', $this->_sql) as $i => $part) {
$sql .= (isset($params[$i]) ? $params[$i] : '') . $part;
}
return $sql;
return parent::setSql($sql);
}

/**
Expand All @@ -161,64 +78,7 @@ public function bindValue($name, $value, $dataType = null)
if ($dataType == \PDO::PARAM_BOOL) {
$dataType = \PDO::PARAM_INT;
}
$this->_pendingParams[$name] = [$value, $dataType];
$this->params[$name] = $value;

return $this;
}

/**
* Binds a list of values to the corresponding parameters.
* This is similar to [[bindValue()]] except that it binds multiple values at a time.
* Note that the SQL data type of each value is determined by its PHP type.
* @param array $values the values to be bound. This must be given in terms of an associative
* array with array keys being the parameter names, and array values the corresponding parameter values,
* e.g. `[':name' => 'John', ':age' => 25]`. By default, the PDO type of each value is determined
* by its PHP type. You may explicitly specify the PDO type by using an array: `[value, type]`,
* e.g. `[':name' => 'John', ':profile' => [$profile, \PDO::PARAM_LOB]]`.
* @return static the current command being executed
*/
public function bindValues($values)
{
if (empty($values)) {
return $this;
}

$schema = $this->db->getSchema();
foreach ($values as $name => $value) {
if (is_array($value)) {
$this->_pendingParams[$name] = $value;
$this->params[$name] = $value[0];
} else {
$type = $schema->getPdoType($value);
$this->_pendingParams[$name] = [$value, $type];
$this->params[$name] = $value;
}
}

return $this;
}

/**
* Marks a specified table schema to be refreshed after command execution.
* @param string $name name of the table, which schema should be refreshed.
* @return $this this command instance
* @since 2.0.6
*/
protected function requireTableSchemaRefresh($name)
{
$this->_refreshTableName = $name;
return $this;
}

/**
* Refreshes table schema, which was marked by [[requireTableSchemaRefresh()]]
* @since 2.0.6
*/
protected function refreshTableSchema()
{
if ($this->_refreshTableName !== null) {
$this->db->getSchema()->refreshTableSchema($this->_refreshTableName);
}
return parent::bindValue($name, $value, $dataType);
}
}
4 changes: 2 additions & 2 deletions src/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ public function insert($table, $columns, &$params)
if ($value instanceof Expression) {
$columns[$name] = $this->convertExpression($value);
} elseif (isset($columnSchemas[$name]) && in_array($columnSchemas[$name]->type, [Schema::TYPE_TEXT, Schema::TYPE_BINARY])) {
$columns[$name] = [$value, 'blob'];
$columns[$name] = [$value, \PDO::PARAM_LOB];
}
}

Expand All @@ -281,7 +281,7 @@ public function update($table, $columns, $condition, &$params)
if ($value instanceof Expression) {
$columns[$name] = $this->convertExpression($value);
} elseif (isset($columnSchemas[$name]) && in_array($columnSchemas[$name]->type, [Schema::TYPE_TEXT, Schema::TYPE_BINARY])) {
$columns[$name] = [$value, 'blob'];
$columns[$name] = [$value, \PDO::PARAM_LOB];
}
}
return parent::update($table, $columns, $condition, $params);
Expand Down
7 changes: 7 additions & 0 deletions tests/ActiveRecordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,11 @@ public function testPopulateWithoutPk()
{
$this->markTestSkipped();
}

public function testCastValues() {
if (version_compare(phpversion('pdo_firebird'), '7.0.13', '<=')) {
$this->markTestSkipped('BLOB bug for PHP <= 7.0.13, see https://bugs.php.net/bug.php?id=61183');
}
parent::testCastValues();
}
}
8 changes: 4 additions & 4 deletions tests/CommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ public function testColumnCase()

public function testBindParamValue()
{
if (version_compare(phpversion('pdo_firebird'), '7.0.13', '<=')) {
$this->markTestSkipped('BLOB bug for PHP <= 7.0.13, see https://bugs.php.net/bug.php?id=61183');
}

$db = $this->getConnection();

// bindParam
Expand Down Expand Up @@ -96,10 +100,6 @@ public function testBindParamValue()

$command = $db->createCommand('SELECT [[int_col]], [[char_col]], [[float_col]], [[blob_col]], [[numeric_col]], [[bool_col]] FROM {{type}}');

//For Firebird
$command->prepare();
$command->pdoStatement->bindColumn('blob_col', $blobCol, \PDO::PARAM_LOB);

$row = $command->queryOne();
$this->assertEquals($intCol, $row['int_col']);
$this->assertEquals($charCol, $row['char_col']);
Expand Down
12 changes: 9 additions & 3 deletions tests/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -281,14 +281,20 @@ public function testDropIndex()

$this->assertEquals('DROP INDEX idx_int_col', $qb->dropIndex('idx_int_col', 'type'));

$columns = $connection->getTableSchema('type', true)->columnNames;
$columns = $connection->getTableSchema('type', true)->columns;

foreach ($columns as $column) {
$result = $connection->createCommand($qb->createIndex('idx_' .$column, 'type', $column))->execute();
if (strpos($column->dbType, 'blob') !== false) {
continue;
}
$result = $connection->createCommand($qb->createIndex('idx_' . $column->name, 'type', $column->name))->execute();
}

foreach ($columns as $column) {
$result = $connection->createCommand($qb->dropIndex('idx_' .$column, 'type'))->execute();
if (strpos($column->dbType, 'blob') !== false) {
continue;
}
$result = $connection->createCommand($qb->dropIndex('idx_' . $column->name, 'type'))->execute();
}
}

Expand Down
22 changes: 5 additions & 17 deletions tests/SchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,23 +68,11 @@ public function getExpectedColumns()
$columns['smallint_col']['dbType'] = 'smallint';
$columns['smallint_col']['size'] = null;
$columns['smallint_col']['precision'] = null;

/**
* Removed blob support
* @see https://bugs.php.net/bug.php?id=61183
*/
// $columns['char_col3']['dbType'] = 'blob sub_type text';

$columns['char_col3']['dbType'] = 'varchar(255)';
$columns['char_col3']['type'] = 'string';
$columns['char_col3']['size'] = 255;
$columns['char_col3']['precision'] = 255;
$columns['blob_col']['dbType'] = 'varchar(255)';
$columns['blob_col']['phpType'] = 'string';
$columns['blob_col']['type'] = 'string';
$columns['blob_col']['size'] = 255;
$columns['blob_col']['precision'] = 255;

$columns['char_col3']['dbType'] = 'blob sub_type text';
$columns['char_col3']['type'] = 'text';
$columns['blob_col']['dbType'] = 'blob';
$columns['blob_col']['phpType'] = 'resource';
$columns['blob_col']['type'] = 'binary';
$columns['float_col']['dbType'] = 'double precision';
$columns['float_col']['size'] = null;
$columns['float_col']['precision'] = null;
Expand Down
4 changes: 2 additions & 2 deletions tests/data/source.sql
Original file line number Diff line number Diff line change
Expand Up @@ -329,10 +329,10 @@ CREATE TABLE type (
smallint_col SMALLINT DEFAULT '1',
char_col char(100) NOT NULL,
char_col2 varchar(100) DEFAULT 'something',
char_col3 varchar(255),
char_col3 blob sub_type text,
float_col DOUBLE PRECISION NOT NULL,
float_col2 DOUBLE PRECISION DEFAULT '1.23',
blob_col varchar(255),
blob_col blob,
numeric_col decimal(5,2) DEFAULT '33.22',
"time" TIMESTAMP DEFAULT '2002-01-01 00:00:00' NOT NULL,
bool_col SMALLINT NOT NULL,
Expand Down

1 comment on commit 5886177

@edgardmessias
Copy link
Owner Author

@edgardmessias edgardmessias commented on 5886177 Nov 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closes #2, #8

Please sign in to comment.