Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go back to pseudo-sequential where() and having() placeholders? #142

Open
wants to merge 3 commits into
base: 3.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 79 additions & 50 deletions src/AbstractQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ abstract class AbstractQuery
*/
protected $builder;

protected $seq_bind_prefix = '';

protected $seq_bind_number = 0;

/**
*
* Constructor.
Expand All @@ -84,10 +88,14 @@ abstract class AbstractQuery
* @param AbstractBuilder $builder A builder for the query.
*
*/
public function __construct(QuoterInterface $quoter, $builder)
{
public function __construct(
QuoterInterface $quoter,
$builder,
$seq_bind_prefix = ''
) {
$this->quoter = $quoter;
$this->builder = $builder;
$this->seq_bind_prefix = $seq_bind_prefix;
}

/**
Expand Down Expand Up @@ -257,32 +265,31 @@ public function resetFlags()

/**
*
* Adds conditions and binds values to a clause.
* Adds conditions to a clause, and binds values.
*
* @param string $clause The clause to work with, typically 'where' or
* 'having'.
*
* @param string $andor Add the condition using this operator, typically
* 'AND' or 'OR'.
*
* @param string $cond The WHERE condition.
*
* @param array $bind arguments to bind to placeholders
* @param array $cond The intermixed WHERE snippets and bind values.
*
* @return null
*
*/
protected function addClauseCondWithBind($clause, $andor, $cond, $bind)
protected function addClauseConditions($clause, $andor, array $cond)
{
if ($cond instanceof Closure) {
$this->addClauseCondClosure($clause, $andor, $cond);
$this->bindValues($bind);
if (empty($cond)) {
return;
}

$cond = $this->quoter->quoteNamesIn($cond);
$cond = $this->rebuildCondAndBindValues($cond, $bind);
if ($cond[0] instanceof Closure) {
$this->addClauseClosure($clause, $andor, $cond[0]);
return;
}

$cond = $this->fixConditions($cond);
$clause =& $this->$clause;
if ($clause) {
$clause[] = "$andor $cond";
Expand All @@ -291,6 +298,58 @@ protected function addClauseCondWithBind($clause, $andor, $cond, $bind)
}
}

/**
*
* Rebuilds intermixed condition snippets and bind values into a single
* string, binding along the way.
*
* @param array $cond The intermixed condition snippets and bind values.
*
* @return string The rebuilt condition string.
*
*/
protected function fixConditions(array $cond)
{
$fixed = '';
while (! empty($cond)) {
$fixed .= $this->fixCondition($cond);
}
return $fixed;
}

/**
*
* Rebuilds the next condition snippets and its bind value.
*
* @param array $cond The intermixed condition snippets and bind values.
*
* @return string The rebuilt condition string.
*
*/
protected function fixCondition(&$cond)
{
$fixed = $this->quoter->quoteNamesIn(array_shift($cond));
if (! $cond) {
return $fixed;
}

$value = array_shift($cond);

if ($value instanceof SelectInterface) {
$fixed .= $value->getStatement();
$this->bind_values = array_merge(
$this->bind_values,
$value->getBindValues()
);
return $fixed;
}

$place = $this->getSeqPlaceholder();
$fixed .= ":{$place}";
$this->bindValue($place, $value);
return $fixed;
}

/**
*
* Adds to a clause through a closure, enclosing within parentheses.
Expand All @@ -306,7 +365,7 @@ protected function addClauseCondWithBind($clause, $andor, $cond, $bind)
* @return null
*
*/
protected function addClauseCondClosure($clause, $andor, $closure)
protected function addClauseClosure($clause, $andor, $closure)
{
// retain the prior set of conditions, and temporarily reset the clause
// for the closure to work with (otherwise there will be an extraneous
Expand Down Expand Up @@ -342,43 +401,6 @@ protected function addClauseCondClosure($clause, $andor, $closure)
$this->$clause = $set;
}

/**
*
* Rebuilds a condition string, replacing sequential placeholders with
* named placeholders, and binding the sequential values to the named
* placeholders.
*
* @param string $cond The condition with sequential placeholders.
*
* @param array $bind_values The values to bind to the sequential
* placeholders under their named versions.
*
* @return string The rebuilt condition string.
*
*/
protected function rebuildCondAndBindValues($cond, array $bind_values)
{
$selects = [];

foreach ($bind_values as $key => $val) {
if ($val instanceof SelectInterface) {
$selects[":{$key}"] = $val;
} else {
$this->bindValue($key, $val);
}
}

foreach ($selects as $key => $select) {
$selects[$key] = $select->getStatement();
$this->bind_values = array_merge(
$this->bind_values,
$select->getBindValues()
);
}

$cond = strtr($cond, $selects);
return $cond;
}

/**
*
Expand All @@ -396,4 +418,11 @@ protected function addOrderBy(array $spec)
}
return $this;
}

protected function getSeqPlaceholder()
{
$this->seq_bind_number ++;
return $this->seq_bind_prefix . "_{$this->seq_bind_number}_";
}

}
35 changes: 15 additions & 20 deletions src/Common/Select.php
Original file line number Diff line number Diff line change
Expand Up @@ -483,13 +483,13 @@ protected function subSelect($spec, $indent)
* @throws Exception
*
*/
public function join($join, $spec, $cond = null, array $bind = array())
public function join($join, $spec, ...$cond)
{
$join = strtoupper(ltrim("$join JOIN"));
$this->addTableRef($join, $spec);

$spec = $this->quoter->quoteName($spec);
$cond = $this->fixJoinCondition($cond, $bind);
$cond = $this->fixJoinConditions($cond);
return $this->addJoin(rtrim("$join $spec $cond"));
}

Expand All @@ -505,14 +505,13 @@ public function join($join, $spec, $cond = null, array $bind = array())
* @return string
*
*/
protected function fixJoinCondition($cond, array $bind)
protected function fixJoinConditions(array $cond)
{
if (! $cond) {
if (empty($cond)) {
return '';
}

$cond = $this->quoter->quoteNamesIn($cond);
$cond = $this->rebuildCondAndBindValues($cond, $bind);
$cond = $this->fixConditions($cond);

if (strtoupper(substr(ltrim($cond), 0, 3)) == 'ON ') {
return $cond;
Expand Down Expand Up @@ -540,9 +539,9 @@ protected function fixJoinCondition($cond, array $bind)
* @throws Exception
*
*/
public function innerJoin($spec, $cond = null, array $bind = array())
public function innerJoin($spec, ...$conditions)
{
return $this->join('INNER', $spec, $cond, $bind);
return $this->join('INNER', $spec, ...$conditions);
}

/**
Expand All @@ -560,9 +559,9 @@ public function innerJoin($spec, $cond = null, array $bind = array())
* @throws Exception
*
*/
public function leftJoin($spec, $cond = null, array $bind = array())
public function leftJoin($spec, ...$conditions)
{
return $this->join('LEFT', $spec, $cond, $bind);
return $this->join('LEFT', $spec, ...$conditions);
}

/**
Expand All @@ -586,14 +585,14 @@ public function leftJoin($spec, $cond = null, array $bind = array())
* @throws Exception
*
*/
public function joinSubSelect($join, $spec, $name, $cond = null, array $bind = array())
public function joinSubSelect($join, $spec, $name, ...$conditions)
{
$join = strtoupper(ltrim("$join JOIN"));
$this->addTableRef("$join (SELECT ...) AS", $name);

$spec = $this->subSelect($spec, ' ');
$name = $this->quoter->quoteName($name);
$cond = $this->fixJoinCondition($cond, $bind);
$cond = $this->fixJoinConditions($conditions);

$text = rtrim("$join ($spec ) AS $name $cond");
return $this->addJoin(' ' . $text);
Expand Down Expand Up @@ -637,16 +636,12 @@ public function groupBy(array $spec)
*
* Adds a HAVING condition to the query by AND.
*
* @param string $cond The HAVING condition.
*
* @param array $bind arguments to bind to placeholders
*
* @return $this
*
*/
public function having($cond, array $bind = [])
public function having(...$conditions)
{
$this->addClauseCondWithBind('having', 'AND', $cond, $bind);
$this->addClauseConditions('having', 'AND', $conditions);
return $this;
}

Expand All @@ -663,9 +658,9 @@ public function having($cond, array $bind = [])
* @see having()
*
*/
public function orHaving($cond, array $bind = [])
public function orHaving(...$conditions)
{
$this->addClauseCondWithBind('having', 'OR', $cond, $bind);
$this->addClauseConditions('having', 'OR', $conditions);
return $this;
}

Expand Down
20 changes: 6 additions & 14 deletions src/Common/SelectInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ public function fromSubSelect($spec, $name);
* @return $this
*
*/
public function join($join, $spec, $cond = null);
public function join($join, $spec, ...$conditions);

/**
*
Expand All @@ -193,7 +193,7 @@ public function join($join, $spec, $cond = null);
* @throws \Exception
*
*/
public function innerJoin($spec, $cond = null, array $bind = array());
public function innerJoin($spec, ...$conditions);

/**
*
Expand All @@ -210,7 +210,7 @@ public function innerJoin($spec, $cond = null, array $bind = array());
* @throws \Exception
*
*/
public function leftJoin($spec, $cond = null, array $bind = array());
public function leftJoin($spec, ...$conditions);

/**
*
Expand All @@ -229,7 +229,7 @@ public function leftJoin($spec, $cond = null, array $bind = array());
* @return $this
*
*/
public function joinSubSelect($join, $spec, $name, $cond = null);
public function joinSubSelect($join, $spec, $name, ...$conditions);

/**
*
Expand All @@ -246,29 +246,21 @@ public function groupBy(array $spec);
*
* Adds a HAVING condition to the query by AND.
*
* @param string $cond The HAVING condition.
*
* @param array $bind Values to be bound to placeholders.
*
* @return $this
*
*/
public function having($cond, array $bind = []);
public function having(...$conditions);

/**
*
* Adds a HAVING condition to the query by OR.
*
* @param string $cond The HAVING condition.
*
* @param array $bind Values to be bound to placeholders.
*
* @return $this
*
* @see having()
*
*/
public function orHaving($cond, array $bind = []);
public function orHaving(...$conditions);

/**
*
Expand Down
4 changes: 2 additions & 2 deletions src/Common/WhereInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ interface WhereInterface
* @return $this
*
*/
public function where($cond, array $bind = []);
public function where(...$conditions);

/**
*
Expand All @@ -47,5 +47,5 @@ public function where($cond, array $bind = []);
* @see where()
*
*/
public function orWhere($cond, array $bind = []);
public function orWhere(...$conditions);
}
Loading