1
0
mirror of https://github.com/dg/dibi.git synced 2025-08-04 13:17:58 +02:00

- BC change: DibiResult::fetchAll() returns always multidimensional arrays (for single columns use fetchPairs() instead)

- added DibiTable::insertOrUpdate()
- new modifier %by
This commit is contained in:
David Grudl
2008-10-01 16:04:16 +00:00
parent 9b84459f09
commit 9eddba204f
9 changed files with 102 additions and 44 deletions

View File

@@ -249,6 +249,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
} }
case dibi::IDENTIFIER: case dibi::IDENTIFIER:
// @see http://www.postgresql.org/docs/8.2/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
$a = strrpos($value, '.'); $a = strrpos($value, '.');
if ($a === FALSE) { if ($a === FALSE) {
return '"' . str_replace('"', '""', $value) . '"'; return '"' . str_replace('"', '""', $value) . '"';

View File

@@ -92,7 +92,7 @@ class DibiConnection extends DibiObject
$driver = preg_replace('#[^a-z0-9_]#', '_', $config['driver']); $driver = preg_replace('#[^a-z0-9_]#', '_', $config['driver']);
$class = "Dibi" . $driver . "Driver"; $class = "Dibi" . $driver . "Driver";
if (!class_exists($class, FALSE)) { if (!class_exists($class, FALSE)) {
include_once __FILE__ . "/../../drivers/$driver.php"; include_once dirname(__FILE__) . "/../drivers/$driver.php";
if (!class_exists($class, FALSE)) { if (!class_exists($class, FALSE)) {
throw new DibiException("Unable to create instance of dibi driver class '$class'."); throw new DibiException("Unable to create instance of dibi driver class '$class'.");

View File

@@ -259,12 +259,11 @@ class DibiFluent extends DibiObject
* Fetches all records from table. * Fetches all records from table.
* @param int offset * @param int offset
* @param int limit * @param int limit
* @param bool simplify one-column result set?
* @return array * @return array
*/ */
public function fetchAll($offset = NULL, $limit = NULL, $simplify = TRUE) public function fetchAll($offset = NULL, $limit = NULL)
{ {
return $this->execute()->fetchAll($offset, $limit, $simplify); return $this->execute()->fetchAll($offset, $limit);
} }

View File

@@ -312,10 +312,9 @@ class DibiResult extends DibiObject implements IDataSource
* *
* @param int offset * @param int offset
* @param int limit * @param int limit
* @param bool simplify one-column result set?
* @return array * @return array
*/ */
final public function fetchAll($offset = NULL, $limit = NULL, $simplify = TRUE) final public function fetchAll($offset = NULL, $limit = NULL)
{ {
$limit = $limit === NULL ? -1 : (int) $limit; $limit = $limit === NULL ? -1 : (int) $limit;
$this->seek((int) $offset); $this->seek((int) $offset);
@@ -323,22 +322,11 @@ class DibiResult extends DibiObject implements IDataSource
if (!$row) return array(); // empty result set if (!$row) return array(); // empty result set
$data = array(); $data = array();
if ($simplify && !$this->objects && count($row) === 1) {
// special case: one-column result set
$key = key($row);
do {
if ($limit === 0) break;
$limit--;
$data[] = $row[$key];
} while ($row = $this->fetch());
} else {
do { do {
if ($limit === 0) break; if ($limit === 0) break;
$limit--; $limit--;
$data[] = $row; $data[] = $row;
} while ($row = $this->fetch()); } while ($row = $this->fetch());
}
return $data; return $data;
} }
@@ -456,13 +444,16 @@ class DibiResult extends DibiObject implements IDataSource
throw new InvalidArgumentException("Either none or both columns must be specified."); throw new InvalidArgumentException("Either none or both columns must be specified.");
} }
if (count($row) < 2) {
throw new UnexpectedValueException("Result must have at least two columns.");
}
// autodetect // autodetect
$tmp = array_keys($row); $tmp = array_keys($row);
$key = $tmp[0]; $key = $tmp[0];
if (count($row) < 2) { // indexed-array
do {
$data[] = $row[$key];
} while ($row = $this->fetch(FALSE));
return $data;
}
$value = $tmp[1]; $value = $tmp[1];
} else { } else {
@@ -633,7 +624,7 @@ class DibiResult extends DibiObject implements IDataSource
*/ */
final public function getIterator($offset = NULL, $limit = NULL) final public function getIterator($offset = NULL, $limit = NULL)
{ {
return new ArrayIterator($this->fetchAll($offset, $limit, FALSE)); return new ArrayIterator($this->fetchAll($offset, $limit));
} }

View File

@@ -162,9 +162,15 @@ abstract class DibiTable extends DibiObject
*/ */
public function update($where, $data) public function update($where, $data)
{ {
$data = $this->prepare($data);
if ($where === NULL && isset($data[$this->primary])) {;
$where = $data[$this->primary];
unset($data[$this->primary]);
}
$this->connection->query( $this->connection->query(
'UPDATE %n', $this->name, 'UPDATE %n', $this->name,
'SET %a', $this->prepare($data), 'SET %a', $data,
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')' 'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
); );
return $this->connection->affectedRows(); return $this->connection->affectedRows();
@@ -172,6 +178,36 @@ abstract class DibiTable extends DibiObject
/**
* Inserts or updates rows in a table.
* @param array|object
* @return int (new) primary key
*/
public function insertOrUpdate($data)
{
$data = $this->prepare($data);
if (!isset($data[$this->primary])) {
throw new InvalidArgumentException("Missing primary key '$this->primary' in dataset.");
}
try {
$this->connection->query(
'INSERT INTO %n', $this->name, '%v', $data
);
} catch (DibiDriverException $e) {
$where = $data[$this->primary];
unset($data[$this->primary]);
$this->connection->query(
'UPDATE %n', $this->name,
'SET %a', $data,
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
);
}
}
/** /**
* Deletes rows from a table by primary key. * Deletes rows from a table by primary key.
* @param mixed primary key value(s) * @param mixed primary key value(s)

View File

@@ -198,11 +198,11 @@ final class DibiTranslator extends DibiObject
if (is_array($value)) { if (is_array($value)) {
$vx = $kx = array(); $vx = $kx = array();
$separator = ', '; $operator = ', ';
switch ($modifier) { switch ($modifier) {
case 'and': case 'and':
case 'or': // key=val AND key IS NULL AND ... case 'or': // key=val AND key IS NULL AND ...
$separator = ' ' . strtoupper($modifier) . ' '; $operator = ' ' . strtoupper($modifier) . ' ';
if (empty($value)) { if (empty($value)) {
return '1'; return '1';
@@ -215,21 +215,12 @@ final class DibiTranslator extends DibiObject
foreach ($value as $k => $v) { foreach ($value as $k => $v) {
$pair = explode('%', $k, 2); // split into identifier & modifier $pair = explode('%', $k, 2); // split into identifier & modifier
$k = $this->delimite($pair[0]); $k = $this->delimite($pair[0]);
if (isset($pair[1])) { $v = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
$pair = explode(' ', $pair[1], 2); // split into modifier & operator $op = isset($pair[1]) && $pair[1] === 'l' ? 'IN' : ($v === 'NULL' ? 'IS' : '=');
$op = isset($pair[1]) ? $pair[1] : '=';
$v = $this->formatValue($v, $pair[0]);
} else {
$op = '=';
$v = $this->formatValue($v, FALSE);
}
if ($v === 'NULL') {
$op = 'IS';
}
$vx[] = $k . ' ' . $op . ' ' . $v; $vx[] = $k . ' ' . $op . ' ' . $v;
} }
} }
return implode($separator, $vx); return implode($operator, $vx);
case 'a': // key=val, key=val, ... case 'a': // key=val, key=val, ...
foreach ($value as $k => $v) { foreach ($value as $k => $v) {
@@ -237,7 +228,7 @@ final class DibiTranslator extends DibiObject
$vx[] = $this->delimite($pair[0]) . '=' $vx[] = $this->delimite($pair[0]) . '='
. $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE); . $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
} }
return implode($separator, $vx); return implode($operator, $vx);
case 'l': // (val, val, ...) case 'l': // (val, val, ...)
@@ -256,6 +247,13 @@ final class DibiTranslator extends DibiObject
} }
return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')'; return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
case 'by': // key ASC, key DESC
foreach ($value as $k => $v) {
$v = (is_string($v) && strcasecmp($v, 'desc')) || $v > 0 ? 'ASC' : 'DESC';
$vx[] = $this->delimite($k) . ' ' . $v;
}
return implode(', ', $vx);
default: // value, value, value - all with the same modifier default: // value, value, value - all with the same modifier
foreach ($value as $v) { foreach ($value as $v) {
$vx[] = $this->formatValue($v, $modifier); $vx[] = $this->formatValue($v, $modifier);

View File

@@ -31,7 +31,7 @@ class Products extends DibiTable
// create table object // create table object
$products = new Products(); $products = new Products;
echo "Table name: $products->name\n"; echo "Table name: $products->name\n";
echo "Primary key: $products->primary\n"; echo "Primary key: $products->primary\n";
@@ -83,6 +83,13 @@ $id = $products->insert($data);
var_dump($id); // generated id var_dump($id); // generated id
// inserts or updates row into a table
$data = array();
$data['title'] = 'New product';
$data[$products->primary] = 5;
$products->insertOrUpdate($data);
// is absolutely SQL injection safe // is absolutely SQL injection safe
$key = '3 OR 1=1'; $key = '3 OR 1=1';
$products->delete($key); $products->delete($key);

View File

@@ -64,3 +64,15 @@ SELECT *
FROM [people] FROM [people]
WHERE [id] IN (", $array, ") WHERE [id] IN (", $array, ")
"); ");
// ORDER BY array
$order = array(
'field1' => 'asc',
'field2' => 'desc',
);
dibi::test("
SELECT *
FROM [people]
ORDER BY %by", $order, "
");

View File

@@ -1,2 +1,16 @@
<style>
h1 {
font-family: Trebuchet MS,"Geneva CE", lucida, sans-serif;
color: #1e5eb6;
}
img {
border: none;
}
</style>
<h1>Icon for your website</h1>
<a href="http://dibiphp.com" title="dibi - tiny 'n' smart database abstraction layer" <a href="http://dibiphp.com" title="dibi - tiny 'n' smart database abstraction layer"
><img src="dibi-powered.gif" width="80" height="15" alt="dibi powered" /></a> ><img src="dibi-powered.gif" width="80" height="15" alt="dibi powered" /></a>