28 сент. 2013 г.

Неприятное ограничение рекурсивных CTE

Простейший способ заехать в дурдом -- это отладка рекурсивных запросов в уме. В предыдущем примере у нас закралась ошибка. Объекты, которые ни от кого не зависят, не попадут в итоговую выборку. Но, только в том случае, если глубина уровня их вложенности больше единицы. Всему виной JOIN at_namespace_file_link l ON l.filename = f.filename во второй части CTE. По логике вещей, тут должен быть LEFT JOIN, но рекурсивное CTE внутри себя не может участвовать во внешних объединениях. C'est la vie. И никакой возможности разрулить данную ситуацию внутри самого CTE не просматривается. Остается городить огород с объединением двух выборок.
WITH RECURSIVE
  ns_tree AS (
    SELECT
      f.filename,
      CAST((f.xid || '_' || f.dbid) AS VARCHAR(1024)) AS path,
      l2.uses_xid,
      l2.uses_dbid
    FROM
      at_namespace_file f
      JOIN at_namespace_file_link l
        ON l.uses_xid = f.xid AND l.uses_dbid = f.dbid
      LEFT JOIN at_namespace_file_link l2
        ON l2.filename = f.filename
    WHERE
      l.filename = :filename

    UNION ALL

    SELECT
      f.filename,
      (t.path || '-' || f.xid || '_' || f.dbid)
        AS path,
      l.uses_xid,
      l.uses_dbid
    FROM
      ns_tree t
      JOIN at_namespace_file f
        ON t.uses_xid = f.xid AND t.uses_dbid = f.dbid
      JOIN at_namespace_file_link l
        ON l.filename = f.filename
    WHERE
      POSITION ((f.xid || '_' || f.dbid)
        IN t.path) = 0)

SELECT
  t.filename
FROM
  ns_tree t

UNION

SELECT
  f.filename
FROM
  ns_tree t
  JOIN at_namespace_file f
    ON f.xid = t.uses_xid AND f.dbid = t.uses_dbid
  LEFT JOIN at_namespace_file_link l
    ON l.filename = f.filename
WHERE
  l.filename IS NULL

2 комментария:

Unknown комментирует...

А Можно узнать В какой версии Делфи разрабатываетса Данный продукт.

Andrei комментирует...

Delphi 5.

Все исходники в googlecode и доступны
через SVN. Единственное исключение --
FastReport 4. Его исходники надо купить
отдельно:

http://www.fast-report.com/en/

FastReport подключается через
условную компиляцию. Так что,
если его исходников не будет, то
проект все равно откомпилируется.

Инструкция по компиляции тут:

http://gsbelarus.com/gs/wiki/index.php/Компиляция_платформы_Гедымин

Отправить комментарий