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:
@@ -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) . '"';
|
||||||
|
@@ -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'.");
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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) {
|
do {
|
||||||
// special case: one-column result set
|
if ($limit === 0) break;
|
||||||
$key = key($row);
|
$limit--;
|
||||||
do {
|
$data[] = $row;
|
||||||
if ($limit === 0) break;
|
} while ($row = $this->fetch());
|
||||||
$limit--;
|
|
||||||
$data[] = $row[$key];
|
|
||||||
} while ($row = $this->fetch());
|
|
||||||
|
|
||||||
} else {
|
|
||||||
do {
|
|
||||||
if ($limit === 0) break;
|
|
||||||
$limit--;
|
|
||||||
$data[] = $row;
|
|
||||||
} 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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)
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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, "
|
||||||
|
");
|
||||||
|
@@ -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>
|
||||||
|
Reference in New Issue
Block a user