Реферат: Как сделать двунаправленный запрос
from ...
where ...
$$$ order by ... asc
$$$ order by ... desc
И что при этом программист возьмет на себя интеллектуальную работу по повторению сортировки в обоих концах. Поля, попадающие в сортировку, должны действительно определять строку выборки. Если поля в выборке допускают неуникальные строки, то следует ввести поле, введение которого сделает строку уникальной. Это требуется для корректного сшивания сортировок. Впрочем, это достаточно поверхностное теоретическое суждение и после его проверки оно может оказаться неверным в каких-то версиях.
Все, что нам понадобится, это удерживать в одном запросе два описателя вместо одного. При создании запроса сконструируем два объекта и при выполнении операций будем обращаться к соответствующим нашим внутренним объектам и передавать их данные штатному sql-движку.
Внимание привлекает поведение функций доступа, например, класс %DynamicSQLQuery, функция Fetch:
n %qref,rtn Set %qref=$lg(qHandle,1),rtn=$lg(qHandle,2)
Quit:%qref=""!(rtn="") $$$ERROR($$$GeneralError,"Query not Prepared")
QUIT $$Fetch^@rtn
Как видно по тексту, сама функция принимает и передает qHandle по ссылке, но к сгенерированной рутине обращается, передавая значения через локальные переменные. Код сгенерированной рутины закрыт, но судя по тому, что состояние qHandle должно быть передано наружу, ее модифицировать может только вызываемая рутина $$Fetch^@rtn. Других проблемных моментов я не нашел, поэтому к делу.
Экспортируем классы %DynamicQuery, %DynamicSQLQuery и $ResultSet в cdl. Дописываем к их именам символ 2 и правим коды так, чтобы у %DynamicSQLQuery2 была внутренняя поддержка обратной прокрутки, более развернутого хендла, чтобы у класса %DynamicQuery использовался запрос типа %DynamicSQLQuery2 и чтобы класс %ResultSet2 имел еще одну функцию, обращающуюся к FetchBack.
Получившиеся у меня для Cache' 4.1.9 классы можно загрузить по ссылке в конце страницы.
Проверочный код примерно следующего вида:
run()
n result,i
Set result=##class(%ResultSet2).%New("%DynamicQuery2:SQL")
Do result.Prepare("select ID, Name from NameList
$$$ order by ID ASC $$$ order by ID DESC")
Do result.Execute()
f i=1:1:4 d
. d result.Next()
. Write result.Get("ID"),result.Get("Name"),!
f i=1:1:2 d
. d result.Prior()
. Write result.Get("ID"),result.Get("Name"),!
f i=1:1:4 d
. d result.Next()
. Write result.Get("ID"),result.Get("Name"),!