Разименование объектных ссылок Назад В начало Вперед

Ссылочная целостность в Атлантисе описывается на уровне БД, для удобства прикладных разработчиков существует возможность получать данные из связанных таблиц используя упрощенный синтаксис ->, без описания связей в логической таблице.

Механизм разыменования объектных ссылок основан на описании ссылочной целостности, взятой из словаря. Более того, использовать можно будет только ссылки, имеющие односегментный ключ любого типа. Синтаксически, для разыменования объектных ссылок использовуется символ ^, после имени поля-ссылки. Полученное выражение будет иметь тип 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;

и, соответственно, создать экземпляр объекта необходимого типа.

Оглавление раздела

Подписка обработчика на создание объекта