Внутренняя реализация Клариона #2

СЧ> Если выбирать, то второй, как более гибкий.
СЧ> Но лучше и тот и другой.
СЧ> И еще не забудь про JOIN — он более сложен чем описан у тебя.
СЧ> Лично меня сейчас в JOIN особенно интересует возможность
СЧ> включать/отключать INNER на ходу.

Ну JOIN не такой уж и сложный! По крайней мере — внутренне.
А если ты имеешь ввиду большую глубину вложенности или много JOIN на одинаковых уровнях, так это все реализуется как-бы автоматом. Главное — правильно научиться формировать главный и первый уровни View. А это я уже умею!
Что касается INNER — кто мешает управлять им через PROP:Inner?
Или я не правильно понял? И что значит «на ходу»?
Если ты имеешь ввиду — во время выборки, то ничего не получиться!
Все установки для View дают эффект ТОЛЬКО перед Open(View)!
После этого по этим установкам формируется результирующая выборка, которую и читают по Next/Previous.
Для реализации новых установок надо закрыть View и опять его открыть.

Кстати!
При описании сложного и навороченного View надо быть внимательным! Дело в том, что можно допустить ошибку, которую компилятор пропустит и не ругнется, а View не будет работать так, как хотелось-бы.

Пример:

File1     File,Driver(),Pre(F1)
MainKey     Key(F1:Name),NoCase,Opt
Record      Record
Name          String(60)
Code          Short
Index         Long
          . .

File2     File,Driver(),Pre(F2)
OwnerKey    Key(F2:Owner,F2:Name),NoCase,Opt
Record      Record
Owner         Long
Name          String(60)
Code          Short
Index         Long
          . .

Обратите внимание, что в обоих файлах есть поля с одинаковыми именами. В частности, особое внимание на поле Index.

Сразу оговорюсь, на всякий случай! Я не использую Project потому, что для НЕ-ODBC/SQL-драйверов он все равно не работает. Но это не значит, что он не будет поддерживаться классом виртуальной View!

RptView   View(File1),Filter('F1:Code = LOC:Code')
            Join(F2:OwnerKey,F2:Index)
          . .

Если внимательно посмотреть, то я допустил ошибку в описании структуры View, но компилятор на эту ошибку  не среагирует! В описании Join, как вы знаете, можно использовать для инициализации полей Join-ключа только поля файла, обьявленного на один уровень выше. В данном случае, для инициализации полей ключа F2:OwnerKey можно использовать поля ТОЛЬКО файла File1. Но, по ошибке, я написал F2:Index. И, как я уже упоминал, компилятор пропустит это! Дело в том, что метка Index есть в структурах обоих файлов. В данном случае, все будет работать нормально, т.к. во внутренней структуре View будет указано просто, что для инициализации ключа надо использовать поле N3 из структуры файла File1. Т.е. как нам и нужно. Но может возникнуть такая ситуация, когда подобная ошибка приведет к совершенно иным результатам!

Особенно на это надо обращать внимание при множестве сложных View, когда в ход идет обычное копирование структур с последующей заменой имен файлов/ключей/полей. В подобных случаях не стоит особенно полагаться на компилятор!

И, кстати, если вы попытаетесь воспользоваться подобным упущением компилятора и задать поля из других файлов, то не надейтесь на успех! Как я уже писал, View будет производить доступ к полю не по его метке или имени. И даже не по его адресу. Он просто попросит дать ему поле под нужным номером. И попросит он об этом ТОЛЬКО у файла предыдущего уровня! И только у него!

В моем классе это упущение компилятора будет пофиксено! Что-бы не расслаблялись:)

А что касается вопроса, заданного в предыдущем письме, то, подумав, я решил делать оба варианта, через перезагрузку процедур. И сразу-же — новый вопрос!

Для организации этого дела мне необходима будет таблица связи символьных имен файлов и их указателей. Через средства языка такого получить невозможно просто потому, что нет какой-либо внутренней структуры, в которой были-бы перечислены все, описанные в приложении, файлы!

Поэтому необходимо будет организовать заполнение подобной структуры ручками. Что-то типа:

MyView.AddFile(File1,'File1')

Сами понимаете, что в данном случае можно будет задавать любое символьное имя файла, например:

MyView.AddFile(File1,'Каталог_клиентов')

а при описании View:

MyView.ViewHeader('Каталог_клиентов,Filter(...),Order(...)')
...
MyView.End

Так вот, сам вопрос — делать подобный список файлов глобальным, действующим для всех динамических View, или задавать такой список для каждого View свой?

В первом случае, достаточно будет в начале программы вызвать процедурку из библиотеки и с ее помощью заполнить такой список. Во втором случае, уже после инициализации отдельного экземпляра класса надо будет вызвать метод AddFile для каждого файла, который будет использоваться при описании структуры этого View.

В принципе, у каждого из вариантов есть и свои плюсы и свои минусы. Вопрос в том — как будет удобнее?