- сам по себе VIEW не отличается большим интеллектом.
- если не задан явно PROP:ORDER и не указан перед открытием VIEW используемый ключ, то при построении выборки игнорируются все ключи и выборка строится по порядку записей. Естественно — очень медленно, т.к. необходимо перебирать ВСЕ записи. В этом случае, перед открытием VIEW можно и не ставить операторы SET(View) или SET(File), но НЕОБХОДИМО ставить один из них перед первым NEXT()/PREVIOUS()! Иначе, сами понимаете, не будет инициализирован порядок просмотра выборки.
- если не задан явно PROP:ORDER, но перед открытием VIEW задан ключ просмотра, то именно этот ключ и будет использован при построении выборки. Если ключ не подходит для заданного фильтра, то скорость выборки маленькая. Если задан правильный ключ, то первая и последняя записи выборки будут считаны мгновенно. Скорость самой выборки всего диапазона будет зависеть от ее размера. Но, в любом случае, это будет самый оптимальный вариант. Так что, как видим, VIEW не блещет интеллектом и не выбирает сам подходящий ключ — все делает программист.
- если задан явно PROP:ORDER, то теперь все зависит от того, совпадает ли он с ключом, оптимальным для фильтра. Дело в том, что независимо от того, какой ключ будет задан перед открытием VIEW, выбирается ВСЕГДА самый оптимальный для заданной сортировки. Вот здесь и проявляется интеллектуальность VIEW. Если выбранный ключ является оптимальным и для заданного фильтра, то такая выборка будет самой оптимальной. В противном случае я даже затрудняюсь сказать, какой ключ используется или используется выборка по порядку записей. По крайней мере, автоматом НЕ ВЫБИРАЕТСЯ первый ключ — это точно. В результате проведенных тестов есть подозрение, что в некоторых случаях (разные фильтры) выбирается оптимальный ключ, т.к. в этих случаях время построения выборки с сортировкой меньше времени полного прохода всех записей.
Подводя итог под вышесказанным, можно рекомендовать следующие варианты инициализации VIEW:
не используется PROP:ORDER и не используется PROP:FILTER.
Open(View) Set(View) Loop Next(View); if ErrorCode() then Break. . Close(View)
не используется PROP:ORDER, но используется фильтр.
если нет ключа, оптимального для заданного фильтра:
View{PROP:Filter} = '...' Open(View) Set(View) Loop Next(View); if ErrorCode() then Break. . Close(View)
если есть ключ, оптимальный для заданного фильтра:
View{PROP:Filter} = '...' Set(FIL:Key) Open(View) Set(View) ! желательно использовать Loop Next(View); if ErrorCode() then Break. . Close(View)
Заметьте, что нет нужды задавать полную форму оператора SET: SET(FIL:Key,FIL:Key).
В данном случае ОБЯЗАТЕЛЬНО надо инициировать поля ключа, которые не указаны в фильтре. Ключевые поля, указанные в фильтре инициируются автоматом. Но в случае многокомпонентного ключа, во избежании недоразумений и глюков, рекомендую ЯВНО инициировать ВСЕ поля ключа. Т.е. самым правильным и гарантированно работающим кодом будет такой код:
View{PROP:Filter} = '...' Clear(FIL:Record,-1) FIL:KeyField1 = ... FIL:KeyField2 = ... ... Set(FIL:Key) Open(View) Set(View) ! желательно использовать Loop Next(View); if ErrorCode() then Break. . Close(View)
используется PROP:ORDER. В данном случае без разницы — используется фильтр или нет.
View{PROP:Order} = '...' Open(View) Set(View) Loop Next(View); if ErrorCode() then Break. . Close(View)
Так что, правильным кодом для примера, который открыл это обсуждение, будет:
File FILE,PRE(FIL),... Date_Key KEY(+FIL:Date),DUP,NOCASE Record RECORD ... Date DATE ... END END LOC:DateBeg DATE LOC:DateEnd DATE CODE ... Open(File) BIND(FIL:Record) BIND('DateBeg',LOC:DateBeg); LOC:DateBeg = DATE(1,1,2001) BIND('DateEnd',LOC:DateEnd); LOC:DateEnd = DATE(12,31,2001) View{PROP:Filter} = '(FIL:Date => DateBeg) AND (FIL:Date <= DateEnd)' Set(FIL:Date_Key) Open(View) Set(View) ! желательно использовать Loop Next(View); if ErrorCode() then Break. ... . Close(View) Close(File) ...