Fix incorrect parsing of subquery in IN () clause

This commit is contained in:
Kijin Sung 2020-06-30 13:22:21 +09:00
parent ad5169bc7a
commit fa220fb1e1

View file

@ -33,7 +33,13 @@ class VariableBase
$params = array();
// Process the variable or default value.
if ($this->var && Query::isValidVariable($args[$this->var]))
if ($this instanceof Query)
{
$is_expression = true;
$value = '(' . $this->getQueryString($prefix, $args) . ')';
$params = $this->getQueryParams();
}
elseif ($this->var && Query::isValidVariable($args[$this->var]))
{
$this->filterValue($args[$this->var]);
$is_expression = false;
@ -43,12 +49,6 @@ class VariableBase
{
list($is_expression, $value) = $this->getDefaultValue();
}
elseif ($this instanceof Query)
{
$is_expression = true;
$value = '(' . $this->getQueryString($prefix, $args) . ') AS ' . Query::quoteName($this->alias);
$params = $this->getQueryParams();
}
elseif ($this->not_null)
{
throw new \Rhymix\Framework\Exceptions\QueryError('Variable ' . $this->var . ' for column ' . $this->column . ' is not set');
@ -63,11 +63,11 @@ class VariableBase
// Prepare the target value.
$list_ops = array('in' => true, 'notin' => true, 'not_in' => true, 'between' => true);
if (isset($list_ops[$this->operation]) && !is_array($value) && $value !== '')
if (isset($list_ops[$this->operation]) && !$is_expression && !is_array($value) && $value !== '')
{
$value = explode(',', preg_replace('/[\s\']/', '', $value));
}
// Apply the operator.
switch ($this->operation)
{
@ -161,22 +161,36 @@ class VariableBase
$where = sprintf('%s IS NOT NULL', $column);
break;
case 'in':
$count = count($value);
$placeholders = implode(', ', array_fill(0, $count, '?'));
$where = sprintf('%s IN (%s)', $column, $placeholders);
foreach ($value as $item)
if ($is_expression)
{
$params[] = $item;
$where = sprintf('%s IN %s', $column, $value);
}
else
{
$count = count($value);
$placeholders = implode(', ', array_fill(0, $count, '?'));
$where = sprintf('%s IN (%s)', $column, $placeholders);
foreach ($value as $item)
{
$params[] = $item;
}
}
break;
case 'notin':
case 'not_in':
$count = count($value);
$placeholders = implode(', ', array_fill(0, $count, '?'));
$where = sprintf('%s NOT IN (%s)', $column, $placeholders);
foreach ($value as $item)
if ($is_expression)
{
$params[] = $item;
$where = sprintf('%s IN %s', $column, $value);
}
else
{
$count = count($value);
$placeholders = implode(', ', array_fill(0, $count, '?'));
$where = sprintf('%s NOT IN (%s)', $column, $placeholders);
foreach ($value as $item)
{
$params[] = $item;
}
}
break;
case 'between':