Разименование объектных ссылок |
Ссылочная целостность в Атлантисе описывается на уровне БД, для удобства прикладных разработчиков существует возможность получать данные из связанных таблиц используя упрощенный синтаксис ->, без описания связей в логической таблице.
Механизм разыменования объектных ссылок основан на описании ссылочной целостности, взятой из словаря. Более того, использовать можно будет только ссылки, имеющие односегментный ключ любого типа. Синтаксически, для разыменования объектных ссылок использовуется символ ^, после имени поля-ссылки. Полученное выражение будет иметь тип ObjRef, никакого синонима, как в случае с обычными ссылками создаваться не будет.
Пример 1. Разыменование объектных ссылок
///////////////////////////////////////////////// // Таблицы create table D_GAL.BaseDoc "Документы-основания" with table_CODE = 1102 with replace ( ... vidDoc : word "вид док-та: договор, счет, счет-фактура", ... ); create table D_ADVSEL.Iski "Исковые заявления и решения суда" with table_CODE = 1739 with replace ( ... cBaseDoc : ref(BaseDoc) "ссылка на ДО на пеню", ... ); ///////////////////////////////////////////////// // Описание прототипов vipInterface vDocument; public: constructor InitKey( iNrec : comp ); function MyType : string; end; vipInterface vInvoice( vDocument ); public: constructor InitKey( iNrec : comp ); function MyType : string; end; vipInterface vGlobalDocumenter; public: function GetVidDoc( iNrec : comp ) : word; end; // Глобальная переменная var pGlobalDocumenter : vGlobalDocumenter; ///////////////////////////////////////////////// // Описание обработчика handler with replace DocumentCreator on createInstance BaseDoc action { var key : comp; if( GetKeyValue(key) = tsOk ) { case pGlobalDocumenter.GetVidDoc( key ) of 201 : result := new(vInvoice, InitKey( key )); else result := new(vDocument, InitKey( key )); end; } else result := nullRef; } ///////////////////////////////////////////////// // Реализации interface vGlobalDocumenter; create view as select BaseDoc.VidDoc from BaseDoc; function GetVidDoc (iNrec : comp) : word; { if getFirst BaseDoc where ((iNrec == BaseDoc.Nrec)) = tsOk result := BaseDoc.VidDoc; else result := 0; } end. interface vDocument; create view as select * from BaseDoc; constructor InitKey (iNrec : comp); { result := getFirst BaseDoc where ((iNrec == BaseDoc.Nrec)) = tsOk; } function o$vDocument.MyType : string; { result := 'Абстрактный документ ' + BaseDoc.VidDoc; } end. interface vInvoice; constructor InitKey (iNrec : comp); { result := inherited::InitKey (iNrec); if result { // можно сделать что-то свое } } function o$vInvoice.MyType : string; { result := 'Счет ' + BaseDoc.VidDoc; } end.
а где то в коде:
... strDocType := vDocument(Iski.cBaseDoc^).MyType; ...
Стоит обратить внимание на тот момент, что при таком использовании ссылка на загруженный объект vDocument (или vInvoice) сразу после вызова MyType освобождается. Для того, чтобы этого не произошло нужно копировать ссылки:
var pDoc : vDoculent; ... pDoc := vDocument(Iski.cBaseDoc^); strDocType := pDoc.MyType; ...
Так же вводится зарегистрированная сервисная функция:
function NewObjRef (key : anyType; tableName : string) : ObjRef;
Пример 2.
При тех же описателях и обработчиках возможно такое использование:
var pDoc : vDoculent; ... pDoc := vDocument(newObjRef(Iski.cBaseDoc, 'BaseDoc')); strDocType := pDoc.MyType; ...
Обработчик необходимо описывать на ту таблицу, из которой реально будет порождаться объект. Значение ключа, по которому создается объект, можно получить через функцию:
function GetKeyValue (key : anyType) : word;
и, соответственно, создать экземпляр объекта необходимого типа.