Skip to content

Commit

Permalink
Improve BLOB/CLOB handling.
Browse files Browse the repository at this point in the history
Add Horde_Db_Value_Text and updateBlob().
Fix insertBlob() returns.
Fix Horde_Db_Adapter interface.
  • Loading branch information
yunosh committed Nov 6, 2014
1 parent 340a1a1 commit 482ab31
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 21 deletions.
33 changes: 33 additions & 0 deletions framework/Db/lib/Horde/Db/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,25 @@ public function execute($sql, $arg1 = null, $arg2 = null);
public function insert($sql, $arg1 = null, $arg2 = null, $pk = null,
$idValue = null, $sequenceName = null);

/**
* Inserts a row including BLOBs into a table.
*
* @since Horde_Db 2.1.0
*
* @param string $table The table name.
* @param array $fields A hash of column names and values. BLOB columns
* must be provided as Horde_Db_Value_Binary
* objects.
* @param string $pk The primary key column.
* @param integer $idValue The primary key value. This parameter is
* required if the primary key is inserted
* manually.
*
* @return integer Last inserted ID.
* @throws Horde_Db_Exception
*/
public function insertBlob($table, $fields, $pk = null, $idValue = null);

/**
* Executes the update statement and returns the number of rows affected.
*
Expand All @@ -252,6 +271,20 @@ public function insert($sql, $arg1 = null, $arg2 = null, $pk = null,
*/
public function update($sql, $arg1 = null, $arg2 = null);

/**
* Updates rows including BLOBs into a table.
*
* @since Horde_Db 2.2.0
*
* @param string $table The table name.
* @param array $fields A hash of column names and values. BLOB columns
* must be provided as Horde_Db_Value_Binary objects.
* @param string $where A WHERE clause.
*
* @throws Horde_Db_Exception
*/
public function updateBlob($table, $fields, $where = '');

/**
* Executes the delete statement and returns the number of rows affected.
*
Expand Down
36 changes: 34 additions & 2 deletions framework/Db/lib/Horde/Db/Adapter/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -575,11 +575,11 @@ public function insertBlob($table, $fields, $pk = null, $idValue = null)
{
$query = sprintf(
'INSERT INTO %s (%s) VALUES (%s)',
$table,
$this->quoteTableName($table),
implode(', ', array_map(array($this, 'quoteColumnName'), array_keys($fields))),
implode(', ', array_fill(0, count($fields), '?'))
);
return $this->insert($query, $fields, $pk, $idValue);
return $this->insert($query, $fields, null, $pk, $idValue);
}

/**
Expand All @@ -600,6 +600,38 @@ public function update($sql, $arg1 = null, $arg2 = null)
return $this->_rowCount;
}

/**
* Updates rows including BLOBs into a table.
*
* @since Horde_Db 2.2.0
*
* @param string $table The table name.
* @param array $fields A hash of column names and values. BLOB columns
* must be provided as Horde_Db_Value_Binary objects.
* @param string $where A WHERE clause.
*
* @throws Horde_Db_Exception
*/
public function updateBlob($table, $fields, $where = '')
{
$query = sprintf(
'UPDATE %s SET %s%s',
$this->quoteTableName($table),
implode(
', ',
array_map(
function($field)
{
return $this->quoteColumnName($field) . ' = ?';
},
array_keys($fields)
)
),
strlen($where) ? ' WHERE ' . $where : ''
);
return $this->update($query, $fields);
}

/**
* Executes the delete statement and returns the number of rows affected.
*
Expand Down
76 changes: 65 additions & 11 deletions framework/Db/lib/Horde/Db/Adapter/Oci8.php
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ public function execute($sql, $arg1 = null, $arg2 = null, $lobs = array())
$descriptors = array();
foreach ($lobs as $name => $lob) {
$descriptors[$name] = oci_new_descriptor($this->_connection, OCI_DTYPE_LOB);
oci_bind_by_name($stmt, ':' . $name, $descriptors[$name], -1, OCI_B_BLOB);
oci_bind_by_name($stmt, ':' . $name, $descriptors[$name], -1, $lob instanceof Horde_Db_Value_Binary ? OCI_B_BLOB : OCI_B_CLOB);
}

$flags = $lobs
Expand Down Expand Up @@ -365,16 +365,7 @@ public function insert($sql, $arg1 = null, $arg2 = null, $pk = null,
*/
public function insertBlob($table, $fields, $pk = null, $idValue = null)
{
$blobs = $locators = array();
foreach ($fields as $column => &$field) {
if ($field instanceof Horde_Db_Value_Binary) {
$blobs[$this->quoteColumnName($column)] = $field;
$locators[] = ':' . $this->quoteColumnName($column);
$field = 'EMPTY_BLOB()';
} else {
$field = $this->quote($field);
}
}
list($fields, $blobs, $locators) = $this->_prepareBlobs($fields);

$sql = 'INSERT INTO ' . $this->quoteTableName($table) . ' ('
. implode(
Expand All @@ -391,6 +382,69 @@ public function insertBlob($table, $fields, $pk = null, $idValue = null)
: $this->selectValue('SELECT id FROM horde_db_autoincrement');
}

/**
* Updates rows including BLOBs into a table.
*
* @since Horde_Db 2.2.0
*
* @param string $table The table name.
* @param array $fields A hash of column names and values. BLOB columns
* must be provided as Horde_Db_Value_Binary objects.
* @param string $where A WHERE clause.
*
* @throws Horde_Db_Exception
*/
public function updateBlob($table, $fields, $where = '')
{
list($fields, $blobs, $locators) = $this->_prepareBlobs($fields);

$sql = 'UPDATE ' . $this->quoteTableName($table) . ' SET '
. implode(
', ',
array_map(
function($field, $value)
{
return $this->quoteColumnName($field) . ' = ' . $value;
},
array_keys($fields),
$fields
)
)
. (strlen($where) ? ' WHERE ' . $where : '')
. ' RETURNING ' . implode(', ', array_keys($blobs)) . ' INTO '
. implode(', ', $locators);
$this->execute($sql, null, null, $blobs);

return $this->_rowCount;
}

/**
* Prepares a list of field values to be consumed by insertBlob() or
* updateBlob().
*
* @param array $fields A hash of column names and values. BLOB columns
* must be provided as Horde_Db_Value_Binary objects.
*
* @return array A list of fields, blobs, and locators.
*/
protected function _prepareBlobs($fields)
{
$blobs = $locators = array();
foreach ($fields as $column => &$field) {
if ($field instanceof Horde_Db_Value_Binary ||
$field instanceof Horde_Db_Value_Text) {
$blobs[$this->quoteColumnName($column)] = $field;
$locators[] = ':' . $this->quoteColumnName($column);
$field = $field instanceof Horde_Db_Value_Binary
? 'EMPTY_BLOB()'
: 'EMPTY_CLOB()';
} else {
$field = $this->quote($field);
}
}
return array($fields, $blobs, $locators);
}

/**
* Begins the transaction (and turns off auto-committing).
*/
Expand Down
47 changes: 47 additions & 0 deletions framework/Db/lib/Horde/Db/Value/Text.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
/**
* Copyright 2014 Horde LLC (http://www.horde.org/)
*
* @author Jan Schneider <jan@horde.org>
* @license http://www.horde.org/licenses/bsd
* @category Horde
* @package Db
*/

/**
* Encapsulation object for long text values to be used in SQL statements to
* ensure proper quoting, escaping, retrieval, etc.
*
* @author Jan Schneider <jan@horde.org>
* @license http://www.horde.org/licenses/bsd
* @category Horde
* @package Db
*/
class Horde_Db_Value_Text implements Horde_Db_Value
{
/**
* Text value to be quoted
*
* @var string
* @since Horde_Db 2.1.0
*/
public $value;

/**
* Constructor
*
* @param string $textValue
*/
public function __construct($textValue)
{
$this->value = $textValue;
}

/**
* @param Horde_Db_Adapter $db
*/
public function quote(Horde_Db_Adapter $db)
{
return $db->quoteString($this->value);
}
}
24 changes: 16 additions & 8 deletions framework/Db/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,21 @@
<email>jan@horde.org</email>
<active>yes</active>
</lead>
<date>2014-10-23</date>
<date>2014-11-06</date>
<version>
<release>2.1.6</release>
<api>2.1.0</api>
<release>2.2.0</release>
<api>2.2.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://www.horde.org/licenses/bsd">BSD-2-Clause</license>
<notes>
*
* [jan] Fix returning primary key value from insertBlob().
* [jan] Add Horde_Db_Adapter::updateBlob().
* [jan] Add Horde_Db_Value_Text to encapsulate long text values.
* [jan] Add missing insertBlob to adapter interface.
</notes>
<contents>
<dir baseinstalldir="/" name="/">
Expand Down Expand Up @@ -108,6 +111,7 @@
</dir> <!-- /lib/Horde/Db/Migration -->
<dir name="Value">
<file name="Binary.php" role="php" />
<file name="Text.php" role="php" />
</dir> <!-- /lib/Horde/Db/Value -->
<file name="Adapter.php" role="php" />
<file name="Exception.php" role="php" />
Expand Down Expand Up @@ -325,6 +329,7 @@
<install as="Horde/Db/Migration/Exception.php" name="lib/Horde/Db/Migration/Exception.php" />
<install as="Horde/Db/Migration/Migrator.php" name="lib/Horde/Db/Migration/Migrator.php" />
<install as="Horde/Db/Value/Binary.php" name="lib/Horde/Db/Value/Binary.php" />
<install as="Horde/Db/Value/Text.php" name="lib/Horde/Db/Value/Text.php" />
<install as="Horde/Db/AllTests.php" name="test/Horde/Db/AllTests.php" />
<install as="Horde/Db/bootstrap.php" name="test/Horde/Db/bootstrap.php" />
<install as="Horde/Db/phpunit.xml" name="test/Horde/Db/phpunit.xml" />
Expand Down Expand Up @@ -831,15 +836,18 @@
</release>
<release>
<version>
<release>2.1.6</release>
<api>2.1.0</api></version>
<release>2.2.0</release>
<api>2.2.0</api></version>
<stability>
<release>stable</release>
<api>stable</api></stability>
<date>2014-10-23</date>
<date>2014-11-06</date>
<license uri="http://www.horde.org/licenses/bsd">BSD-2-Clause</license>
<notes>
*
* [jan] Fix returning primary key value from insertBlob().
* [jan] Add Horde_Db_Adapter::updateBlob().
* [jan] Add Horde_Db_Value_Text to encapsulate long text values.
* [jan] Add missing insertBlob to adapter interface.
</notes>
</release>
</changelog>
Expand Down
52 changes: 52 additions & 0 deletions framework/Db/test/Horde/Db/Adapter/TestBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,35 @@ public function testInsert()
$this->assertEquals(7, $result);
}

public function testInsertBlob()
{
$this->_createTable();

$result = $this->_conn->insertBlob(
'unit_tests',
array(
'id' => 7,
'integer_value' => 999,
'blob_value' => new Horde_Db_Value_Binary(str_repeat("\0", 5000))
),
null,
7
);
$this->assertEquals(7, $result);

$result = $this->_conn->insertBlob(
'unit_tests',
array(
'id' => 8,
'integer_value' => 1000,
'text_value' => new Horde_Db_Value_Text(str_repeat('X', 5000))
),
null,
8
);
$this->assertEquals(8, $result);
}

public function testUpdate()
{
$this->_createTable();
Expand All @@ -211,6 +240,29 @@ public function testUpdate()
$this->assertEquals(1, $result);
}

public function testUpdateBlob()
{
$this->_createTable();

$result = $this->_conn->updateBlob(
'unit_tests',
array(
'blob_value' => new Horde_Db_Value_Binary(str_repeat("\0", 5000))
),
'id = 1'
);
$this->assertEquals(1, $result);

$result = $this->_conn->updateBlob(
'unit_tests',
array(
'text_value' => new Horde_Db_Value_Text(str_repeat('X', 5000))
),
'id = 1'
);
$this->assertEquals(1, $result);
}

public function testDelete()
{
$this->_createTable();
Expand Down

0 comments on commit 482ab31

Please sign in to comment.