[sql] Как добавить произвольную строку в выборку?
Всем привет!
Пните в нужную сторону, пожалуйста. Простая вроде задачка, а решения что-то не видно.
Вот есть запрос, который выбирает, скажем, ресурсы и который собирается через newQuery. Есть несколько условий для выборки в WHERE, которые генерируются в зависимости от других условий.
Вопрос — как с учётом имеющихся в запросе условий добавить в выборку строку с произвольным id?
Проще объясню на примере:
после генерации условий имеем примерно такой запрос:
Вот к этой выборке нужно присоединить строку с каким-то определённым id (к примеру 5) даже если эта строка с этим id не попадает под условия
Конечно, первым делом напрашивается вот такая запись:
Но фишка в том, что условий на published и deleted может и не быть.
И newQuery составит запрос таким образом, что в выборку попадёт только одна запись:
Так же можно проверять на пустоту вот этот массив:
Вторым делом напрашивается UNION, но как его запихнуть в newQuery при условии, что запрос формируется в getlist-процессоре? Просто так выполнить
В общем, нужно просто добавить произвольную строку в выборку, чтобы объект xPDOQuery остался объектом xPDOQuery. И вот здесь у меня, как вы поняли, затуп. Встрял на этом месте и продвинуться не могу.
Пните в нужную сторону, пожалуйста. Простая вроде задачка, а решения что-то не видно.
Вот есть запрос, который выбирает, скажем, ресурсы и который собирается через newQuery. Есть несколько условий для выборки в WHERE, которые генерируются в зависимости от других условий.
Вопрос — как с учётом имеющихся в запросе условий добавить в выборку строку с произвольным id?
Проще объясню на примере:
после генерации условий имеем примерно такой запрос:
SELECT id, pagetitle FROM modx_site_content WHERE published = 1 AND deleted = 0
Вот к этой выборке нужно присоединить строку с каким-то определённым id (к примеру 5) даже если эта строка с этим id не попадает под условия
published = 1 AND deleted = 0
Конечно, первым делом напрашивается вот такая запись:
SELECT id, pagetitle FROM modx_site_content WHERE (published = 1 AND deleted = 0) OR (id = 5)
/** @var xPDOQuery $query */
// генерируем условия
$query->where(array(array(
'published' => 1,
'deleted' => 0
)));
/*... 7 кругов издевательств над запросом ...*/
$query->where(array(
'OR:id' => 5
));
/*... ещё 7 кругов издевательств над запросом ...*/
Но фишка в том, что условий на published и deleted может и не быть.
И newQuery составит запрос таким образом, что в выборку попадёт только одна запись:
SELECT id, pagetitle FROM modx_site_content WHERE (id = 5)
А нужны-то все, плюс та, у которой id=5.Так же можно проверять на пустоту вот этот массив:
/** @var xPDOQuery $query */
$query->query['where']
, чтобы добавлять условие с id только если других условий нет. Но есть ещё фишка — условия могут добавиться дальше по ходу выполнения. И этот момент, увы, не отловить.Вторым делом напрашивается UNION, но как его запихнуть в newQuery при условии, что запрос формируется в getlist-процессоре? Просто так выполнить
$query->prepare() && $sql = $query->toSQL() // а потом делай с запросом что хочешь
не получится, ведь нужно, чтобы процессор подсчитал количество, прошёл все стадии prepareQueryBefore/AfterCount и остался объектом xPDOQuery до самого конца.В общем, нужно просто добавить произвольную строку в выборку, чтобы объект xPDOQuery остался объектом xPDOQuery. И вот здесь у меня, как вы поняли, затуп. Встрял на этом месте и продвинуться не могу.
Комментарии: 4
Решение в лоб: объявить в процессоре property, типа
То есть, сделать просто временный флаг true-false и отлавливать твоё событие вручную.
protected $been_added = false;
и при добавлении какого-то твоего условия переставлять её в true, а потом проверятьif ($this->been_added) {
$query->where(array(
'OR:id' => 5
));
}
То есть, сделать просто временный флаг true-false и отлавливать твоё событие вручную.
Привет!
Так-то оно, конечно, да. Спасибо за подсказку)
Но возникло 2 «но», о которых расписывать смысла нет. Поэтому пришлось немного перелопатить код, чтобы это условие добавлялось самым последним из всех возможных. Ну и предварительно проверяя массив where на пустоту вот таким вот методом:
Такой изврат нужен потому, что в where могут находится много разных пустых и не пустых массивов любой вложенности. Поэтому !empty($array) тут не поможет.
p.s. вызывать вот так (вдруг кому пригодится):
А по теме — странно, конечно. Вроде такая простая задача, а стандартными средствами не сделать. Абыдна)
Так-то оно, конечно, да. Спасибо за подсказку)
Но возникло 2 «но», о которых расписывать смысла нет. Поэтому пришлось немного перелопатить код, чтобы это условие добавлялось самым последним из всех возможных. Ну и предварительно проверяя массив where на пустоту вот таким вот методом:
public function isDeepEmptyArray (array $where = array()) {
// array('field' => 'value', 'sql string', array('field2' => 'value'));
foreach ($where as $k => $v) {
if (is_string($k) && $k) {
return false;
}
if (is_string($v) && $v) {
return false;
}
if (is_numeric($k) && is_array($v)) {
return $this->isDeepEmptyArray($v);
}
}
return true;
}
Такой изврат нужен потому, что в where могут находится много разных пустых и не пустых массивов любой вложенности. Поэтому !empty($array) тут не поможет.
p.s. вызывать вот так (вдруг кому пригодится):
/** @var xPDOQuery $c */
if (!$this->isDeepEmptyArray($c->query['where'])) { /* ... */ }
А по теме — странно, конечно. Вроде такая простая задача, а стандартными средствами не сделать. Абыдна)
Почему не сделать? Ты же сделал =)
Ну и представь заодно, каково было бы вручную писать этот SQL, без xPDO::Query =)
Ну и представь заодно, каково было бы вручную писать этот SQL, без xPDO::Query =)
Ты же сделал =)Ну так-то да)
Ну и представь заодно, каково было бы вручную писать этот SQL, без xPDO::Query =)Я ручной набор sql'я уже забыл как страшный сон. Вот зачем ты напомнил?) Теперь снова кошмары будут сниться xD
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.