Update Pgsql

master
Vitaliy Filippov 2018-09-16 02:31:52 +03:00
parent ac253419cb
commit 4f857a1cd5
1 changed files with 63 additions and 11 deletions

View File

@ -3,8 +3,8 @@
/**
* PDO/PostgreSQL wrapper with (mostly) DatabaseMySQL interface :)
* Select builder is inspired by MediaWiki's one.
* Version: 2017-12-13
* (c) Vitaliy Filippov, 2015-2017
* Version: 2018-08-12
* (c) Vitaliy Filippov, 2015-2018
*/
if (!defined('MS_HASH'))
@ -155,6 +155,8 @@ class DatabasePdoPgsql implements Database
{
if ($value === NULL)
return "NULL";
elseif ($value instanceof DatabasePdoPgsql_Fragment)
return $value->bind ? $this->quoteInto($value->text, $value->bind) : $value->text;
if (!$this->link)
$this->connect();
return $this->link->quote($value);
@ -314,8 +316,6 @@ class DatabasePdoPgsql implements Database
$wh[] = "$k IN (" . implode(",", $v) . ")";
}
}
elseif (preg_match('/^-?\d+(\.\d+)?$/s', $v)) // int/float
$wh[] = "$k=$v";
elseif ($v !== NULL)
$wh[] = "$k=".$this->quote($v);
else
@ -344,6 +344,9 @@ class DatabasePdoPgsql implements Database
* 'ORDER BY' => array($orderby_field1 => 'ASC', $orderby_field2 => 'DESC')
* 'LIMIT' => array($offset, $limit) or array($limit) or just $limit
* 'OFFSET' => $offset, for the case when 'LIMIT' is just $limit
* 'DISTINCT' => true
* 'DISTINCT ON' => $fields
* 'HAVING' => $having (like WHERE)
*/
function select_builder($tables, $fields, $where, $options = NULL)
{
@ -357,9 +360,14 @@ class DatabasePdoPgsql implements Database
}
if (is_array($fields))
{
foreach ($fields as $k => $v)
foreach ($fields as $k => &$v)
{
if ($v instanceof DatabasePdoPgsql_Fragment)
$v = $v->bind ? $this->quoteInto($v->text, $v->bind) : $v->text;
if (!ctype_digit("$k"))
$fields[$k] = "$v AS ".$this->quoteId($k);
$v = "$v AS ".$this->quoteId($k);
}
unset($v);
$fields = join(",\n ", str_replace("\n", "\n ", $fields));
}
$more = NULL;
@ -370,11 +378,18 @@ class DatabasePdoPgsql implements Database
$this->calcFoundRows = isset($options['CALC_FOUND_ROWS']) || isset($options['SQL_CALC_FOUND_ROWS']);
if ($this->calcFoundRows)
$fields .= ",\n COUNT(*) OVER () \"*\"";
$sql = "SELECT $fields\nFROM $tables";
$sql = "SELECT";
if (isset($options['DISTINCT ON']))
$sql .= " DISTINCT ON (".implode(', ', (array)$options['DISTINCT ON']).")";
elseif (isset($options['DISTINCT']))
$sql .= " DISTINCT";
$sql .= " $fields\nFROM $tables";
if ($where)
$sql .= "\nWHERE $where";
if (!empty($options['GROUP BY']) && $options['GROUP BY'] !== '0')
$sql .= "\nGROUP BY ".$this->order_option($options['GROUP BY']);
if (!empty($options['HAVING']))
$sql .= "\nHAVING ".$this->where_builder($options['HAVING']);
if (!empty($options['ORDER BY']) && $options['ORDER BY'] !== '0')
$sql .= "\nORDER BY ".$this->order_option($options['ORDER BY']);
$sql .= $this->limit_option($options);
@ -417,7 +432,7 @@ class DatabasePdoPgsql implements Database
if (is_array($g) && count($g) != 2)
$g = $g[0];
if (is_array($g))
return " LIMIT ".$g[1]." OFFSET ".$g[0];
return " LIMIT ".$g[1].($g[0] > 0 ? " OFFSET ".$g[0] : '');
$g = " LIMIT $g";
}
if (!empty($options['OFFSET']))
@ -538,7 +553,7 @@ class DatabasePdoPgsql implements Database
$fs = $format & MS_LIST ? PDO::FETCH_NUM : PDO::FETCH_ASSOC;
$rows = $format & MS_ROW ? [ $res->fetch($fs) ] : $res->fetchAll($fs);
$this->foundRows = reset($rows);
$this->foundRows = end($this->foundRows);
$this->foundRows = $this->foundRows ? end($this->foundRows) : 0;
if ($format & MS_COL)
foreach ($rows as &$row)
$row = reset($row);
@ -567,6 +582,15 @@ class DatabasePdoPgsql implements Database
* 'OFFSET' => $offset, for the case when 'LIMIT' is just $limit
*/
function delete($tables, $where, $options = NULL)
{
$sql = $this->delete_builder($tables, $where, $options);
return $this->query($sql);
}
/**
* Same as delete(), but only returns SQL text
*/
function delete_builder($tables, $where, $options = NULL)
{
list($what, $using) = $this->split_using($tables, $where);
$more = NULL;
@ -576,7 +600,7 @@ class DatabasePdoPgsql implements Database
$where = $this->where_builder($where) ?: '1=1';
$sql .= " WHERE $where";
$sql .= $this->limit_option($options);
return $this->query($sql);
return $sql;
}
protected function values($rows, $forInsert)
@ -587,6 +611,11 @@ class DatabasePdoPgsql implements Database
$key = $rows;
$rows = [ $rows ];
}
else
{
foreach ($rows as $r)
$key += $r;
}
$key = array_keys($key);
foreach ($rows as &$r)
{
@ -600,7 +629,9 @@ class DatabasePdoPgsql implements Database
foreach ($key as &$k)
{
if (strpos($k, '"') === false)
{
$k = $this->quoteId($k);
}
}
return array($key, $rows);
}
@ -611,6 +642,11 @@ class DatabasePdoPgsql implements Database
return new DatabasePdoPgsql_Values($keys, $values, $alias);
}
function fragment($text, array $bind = [])
{
return new DatabasePdoPgsql_Fragment($text, $bind);
}
/**
* Builds an INSERT query.
*
@ -625,12 +661,15 @@ class DatabasePdoPgsql implements Database
*/
function insert_builder($table, $rows, $action = NULL, $uniqueColumns = NULL, $updateCols = NULL)
{
$alias = is_array($table) ? array_keys($table)[0] : NULL;
$table = is_array($table) ? $table[$alias] : $table;
if (isset($this->tableNames[$table]))
{
$table = $this->quoteId($this->tableNames[$table]);
}
list($keys, $values) = $this->values($rows, true);
$sql = "INSERT INTO $table (".implode(',', $keys).") VALUES (".implode('),(', $values).")";
$sql = "INSERT INTO $table".($alias ? " AS $alias" : "").
" (".implode(',', $keys).") VALUES (".implode('),(', $values).")";
if ($action)
{
$sql .= " ON CONFLICT";
@ -825,6 +864,8 @@ class DatabasePdoPgsql implements Database
class DatabasePdoPgsql_Values
{
public $keys, $values, $alias;
function __construct($keys, $values, $alias)
{
$this->keys = $keys;
@ -837,3 +878,14 @@ class DatabasePdoPgsql_Values
return "(VALUES (".implode("),(", $this->values).")) AS ".$this->alias." (".implode(',', $this->keys).")";
}
}
class DatabasePdoPgsql_Fragment
{
public $text, $bind;
function __construct($text, $bind)
{
$this->text = $text;
$this->bind = $bind;
}
}