[sql] Как добавить произвольную строку в выборку?

Всем привет!

Пните в нужную сторону, пожалуйста. Простая вроде задачка, а решения что-то не видно.

Вот есть запрос, который выбирает, скажем, ресурсы и который собирается через 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. И вот здесь у меня, как вы поняли, затуп. Встрял на этом месте и продвинуться не могу.
Алексей Карташов
12 апреля 2015, 03:33
modx.pro
1
4 469
0

Комментарии: 4

Василий Наумкин
12 апреля 2015, 06:46
0
Решение в лоб: объявить в процессоре property, типа
protected $been_added = false;
и при добавлении какого-то твоего условия переставлять её в true, а потом проверять
if ($this->been_added) {
	$query->where(array(
		'OR:id' => 5
	));
}

То есть, сделать просто временный флаг true-false и отлавливать твоё событие вручную.
    Алексей Карташов
    12 апреля 2015, 07:38
    0
    Привет!
    Так-то оно, конечно, да. Спасибо за подсказку)

    Но возникло 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'])) { /* ... */ }

    А по теме — странно, конечно. Вроде такая простая задача, а стандартными средствами не сделать. Абыдна)
      Василий Наумкин
      12 апреля 2015, 07:53
      0
      Почему не сделать? Ты же сделал =)

      Ну и представь заодно, каково было бы вручную писать этот SQL, без xPDO::Query =)
        Алексей Карташов
        12 апреля 2015, 09:07
        0
        Ты же сделал =)
        Ну так-то да)

        Ну и представь заодно, каково было бы вручную писать этот SQL, без xPDO::Query =)
        Я ручной набор sql'я уже забыл как страшный сон. Вот зачем ты напомнил?) Теперь снова кошмары будут сниться xD
    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
    4