БУФЕРЫ ЗАПИСЕЙ

Работа с записями таблиц в OpenEdge ABL осуществляется посредством буферов записей, представляющих собой область памяти, в которую помещается запись таблицы для последующей работы с ней.

rec work02

Ввод данных в таблицу:

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

Чтение и редактирование записей таблицы:

С помощью операторов выборки (поиска) записей осуществляется помещение отобранной из таблицы записи в буфер записи. Далее, данные из буфера записи могут быть перемещены в экранный буфер, где они доступны для дальней работы с ними пользователю. По завершению работы пользователя, данные из экранного буфера помещаются в буфер записи, далее из буфера записи обратно в таблицу. Записи так же могут быть обработаны без помещения в экранный буфер, т.е. без непосредственного участия пользователя.

В одном буфере записи может находиться только одна запись таблицы. По умолчанию, для каждой таблицы, с которыми осуществляется работа в процедуре, автоматически создается по одному буферу записи, идентификаторы которых совпадают с соответствующими им именами таблиц. При необходимости, в процедуре возможно объявление дополнительных буферов записей таблиц:

DEFINE {[[NEW] SHARED] | [PRIVATE | PROTECTED] [STATIC]}
  BUFFER buffer-name
  FOR [TEMP-TABLE] table-name
  [PRESELECT] [LABEL label-name]
  [NAMESPACE-URI namespace] [NAMESPACE-PREFIX prefix]
  [XML-NODE-NAME node-name]

buffer-name - идентификатор буфера записи;

table-name - имя таблицы для которой объявляется буфер.

Приведем пример:

DEF BUFFER b-cust-corp FOR cust-corp.
FIND FIRST cust-corp WHERE cust-corp.cust-id EQ 10.
FIND FIRST b-cust-corp WHERE b-cust-corp.cust-id EQ 15.
DISPLAY cust-corp.name-corp b-cust-corp.name-corp.

Таким образом, в процедуре мы имеем два буфера записи для таблицы cust-corp (юридические лица): определенный по умолчанию (cust-corp) и объявленный нами дополнительный буфер (b-cust-corp). Во избежание двусмысленности при работе с двумя буферами записи одной таблицы, при обращении к их данным необходимо полностью указывать идентификатор полей, например: cust-corp.name-corp и b-cust-corp.name-corp.

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

Проиллюстрируем это на простом примере:

Процедура proc1.p    

DEF NEW SHARED BUFFER b-acct FOR acct.
FIND FIRST b-acct WHERE b-acct.acct-bal EQ 40817.
RUN proc2.p.

 Процедура proc2.p

DEF SHARED BUFFER b-acct FOR customer.
DISPLAY b-acct.acct.

Для решения определенных задач, нам может потребоваться как-то определять, находящаяся в буфере запись - это создаваемая новая запись, или же нет. Определить это позволяет функция NEW, возвращающая логическое значение TRUE, для новой записи и FALSE, для уже существовавшей в таблице записи.

NEW buffer-name


КОПИРОВАНИЕ БУФЕРА ЗАПИСИ


Скопировать запись одной таблицы (исходной) в другую (целевую) можно с помощью оператора копирования буфера BUFFER-COPY. Оператор BUFFER-COPY осуществляет копирование значений полей буфера записи исходной таблицы в одноименные поля буфера целевой таблицы.

BUFFER-COPY source [{EXCEPT | USING} field ...]
         TO target
        
[ASSIGN assign-expression]
         [NO-LOBS]
         [NO-ERROR]

source - идентификатор буфера записи исходной таблицы;

EXCEPT field - список полей с разделителем пробел, исключаемых из копирования;

USING field - список полей с разделителем пробел, включаемых в копирование;

TO target - идентификатор буфера записи целевой таблицы;

ASSIGN assign-expression - оператор присваивания, выполняемый в рамках операции копирования буфера записи;

NO-LOBS - отключает копирование полей с типами BLOB и CLOB.

Допустим, нам необходимо создать новую запись в таблице счетов (acct) подобием уже существующей в ней записи, но с другим номером счета (acct.acct). Все другие поля таблицы нам необходимо просто скопировать в новую запись.

DEF VAR vNewAcct AS CHAR NO-UNDO.
DEF BUFFER b-acct FOR acct.

FIND FIRST acct WHERE .....

CREATE b-acct.

BUFFER-COPY acct EXCEPT acct TO b-acct
     ASSIGN
     b-acct.acct = vNewAcct
.

Первым делом, нам необходимо поместить в буфер записи копируемый счет, т.е. найти его в таблице acct, например, с помощью оператора FIND FIRST. После этого, создать с помощью оператора CREATE новую запись счета в таблице и поместить ее в буфер b-acct, в который будет осуществляться копирование данных.

Теперь можно осуществить копирование данных, при этом поле acct мы исключаем из копирования с помощью EXCEPT acct, так как его копировать не нужно, а необходимо присвоить значение из переменной vNewAcct, что мы и сделаем с помощью встроенного оператора ASSIGN.

 

RAW-TRANSFER

Оператор RAW-TRANSFER осуществляет копирование буфера записи в другой буфер записи, а так же копирование данных буфера записи в поле таблицы или переменную типа RAW и обратно.

RAW-TRANSFER
   {  [BUFFER] buffer    TO [FIELD]  raw-field
    | [FIELD]  raw-field TO [BUFFER] buffer
    | [BUFFER] buffer    TO [BUFFER] buffer
   }
   [NO-ERROR]

buffer - буфер записи;

raw-field - переменная или поле таблицы типа RAW.

Структура буфера записи, в который осуществляется копирование данных из переменой или поля таблицы, должна соответствовать структуре хранящейся в них записи.

DEF VAR vRecord AS RAW NO-UNDO.

DEF TEMP-TABLE tt-table NO-UNDO
   FIELD code AS CHAR INIT "Код"
   FIELD val  AS CHAR INIT "Значение"
.

DEF TEMP-TABLE tt-table1 NO-UNDO
   FIELD val  AS CHAR
   FIELD code AS CHAR
/* FIELD disc AS CHAR */
.

CREATE tt-table.
RAW-TRANSFER tt-table TO vRecord.

RAW-TRANSFER vRecord TO tt-table1.
DISPL tt-table1.code tt-table1.val SKIP.

Результат:

code     val
-------- --------
Значение Код

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

 
СРАВНЕНИЕ БУФЕРОВ ЗАПИСЕЙ


Сравнить записи двух таблиц возможно с помощью оператора сравнения буферов BUFFER-COMPARE.

BUFFER-COMPARE source [{EXCEPT | USING} field ...]
            TO target

            [CASE-SENSITIVE | BINARY]
            [SAVE [RESULT IN] result-field]
            [[EXPLICIT] COMPARES]:
               [WHEN field compare-operator expression
                THEN statement-or-block ] ...
            [END [COMPARES]]
            [NO-LOBS]
            [NO-ERROR]

source - идентификатор буфера записи исходной таблицы; 

EXCEPT field - список исключаемых из сравнения полей, разделитель пробел;

USING field - список включаемых в сравнение полей разделитель пробел;

TO target - идентификатор буфера записи целевой таблицы (таблицы, с которой осуществляется сравнение);

CASE-SENSITIVE - чувствительность к регистру при сравнении;

BINARY - осуществляет бинарное сравнение значения без преобразований;

SAVE [RESULT IN] result-field - переменная, или поле таблицы: CHARACTER или LOGICAL типов, в которые осуществляется сохранение результата сравнения. Если в качестве result-field указана переменная, или поле таблицы CHARACTER типа, то результат сравнение будет представлять собой список несовпадающих полей таблиц с разделителем запятая. Если result-field  - переменная, или поле таблицы LOGICAL типа, то результатом сравнения будет TRUE, в случае если все поля таблиц совпадают и FALSE, если хотя бы одно из полей исходной таблицы не совпало с полем целевой таблицы;

NO-LOBS - отключает сравнение полей с типами данных BLOB и CLOB.

Оператор BUFFER-COMPARE осуществляет сравнение значений одноименных полей буферов двух записей. Несовпадающие имена полей исключаются из сравнения.

Типы данных сравниваемых полей должны быть совместимы для возможности сравнения их значений.

Для примера, сравним два платежных документа (таблица op) в текущем и во вчерашнем операционных днях, но с совпадающими номерами документов (op.doc-num).  

DEF VAR vResultCompare AS CHARACTER NO-UNDO.
DEF BUFFER b-op FOR op.

FOR FIRST op WHERE op.op-date = TODAY NO-LOCK:
   FIND FIRST b-op WHERE b-op.op-date = TODAY - 1
AND b-op.doc-num = op.doc-num
NO-LOCK NO-ERROR.

   IF AVAIL b-op THEN
   BUFFER-COMPARE op EXCEPT op op-date TO b-op
     SAVE RESULT IN vResultCompare.
END.
DISPL vResultCompare FORMAT "x(78)".

При сравнении буферов мы исключили два поля op - уникальный ключ документа и op-date - дата документа, так как они заведомо разные. Результат сравнения мы определили сохранить в переменную CHARACTER типа, следовательно ее значение будет либо пусто, если записи совпадают, либо представлять собой список полей значения которых не совпали.


ДИНАМИЧЕСКИЙ БУФЕР ЗАПИСИ


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

CREATE BUFFER buffer-handle FOR TABLE table-expression

buffer-handle - указатель буфера, тип HANDLE;

table-expression - выражение, определяющее имя таблицы, для которой объявляется буфер.

В отличие от статических буферов, обращение к динамическому буферу осуществляется не по его идентификатору, а по его указателю как на объект. Работа с динамическим буфером осуществляется исключительно как с объектом ООП посредством его атрибутов и методов.

По завершению работы, созданный в процедуре динамический буфер, должен быть удален в ней.

DELETE OBJECT buffer-handle


БУФЕР ЗАПИСИ - ОБЪЕКТ ООП


Как мы уже сказали, динамические буферы в OpenEdge ABL являются объектами ООП со своим набором атрибутов и методов.

buffer-handle [:attribute | :method]

При этом, статические буферы, аналогично динамическим, так же являются этими объектами. Если для динамического буфера указатель определяется при его объявлении в операторе CREATE, то для статического буфера указатель можно получить следующим образом:

buffer-handle = BUFFER buffer-name:HANDLE

buffer-handle - указатель буфера, тип HANDLE;

buffer-name - идентификатор статического буфера.

Таким образом, работа с буферами как с объектами ООП может осуществляться независимо от способа их объявления.

Атрибуты:

Атрибут Тип данных Доступ Описание
ADM-DATA CHARACTER чтение/запись
AFTER-BUFFER HANDLE чтение
AFTER-ROWID ROWID чтение
AMBIGUOS LOGICAL чтение Принимает значение TRUE, если поиск записи оператором FIND завершился с ошибкой AMBIGUOS. Изначально имеет значение FALSE
ATTACHED-PAIRLIST CHARACTER чтение
AUTO-DELETE LOGICAL чтение/запись
AUTO-SYNCHRONIZE LOGICAL чтение/запись
AVAILIABLE LOGICAL чтение Значение TRUE указывает на то, что буфер содержит запись таблицы. FALSE - буфер пуст.
BATCH-SIZE INTEGER чтение/запись
BEFORE-BUFFER  HANDLE чтение
BEFOR-ROWID  ROWID  чтение
CAN-CREATE  LOGICAL  чтение
CAN-DELETE  LOGICAL  чтение
CAN-READ  LOGICAL  чтение
CAN-WRITE  LOGICAL  чтение
CRC-VALUE  INTEGER  чтение
CURRENT-CHANGED  LOGICAL  чтение
CURRENT-ITERATION  INTEGER  чтение
DATESET  HANDLE  чтение Указатель ProDataSet, членом которого является запись
DATA-SOURCE  HANDLE  чтение
DATA-SOURCE-COMPLETE-MAP CHARACTER  чтение
DATA-SOURCE-MODIFIED LOGICAL чтение/запись
DATA-SOURCE-ROWID ROWID чтение/запись
DBNAME CHARACTER чтение Имя базы данных (имя файла базы данных, без расширения, или значение определенное стартовым параметром -ld), которой принадлежит запись
DYNAMIC LOGICAL чтение Логическое значение отражающее является ли буфер динамическим (TRUE) или статическим (FALSE).
ERROR  LOGICAL  чтение/запись
ERROR-STRING CHARACTER  чтение/запись
FILL-MODE CHARACTER  чтение/запись
HANDLE HANDALE чтение Указатель буфера записи
HAS-LOBS LOGICAL чтение Значение TRUE указывает на то, что буфер записи содержит поля BLOB или CLOB типов. В противном случае - значение FALSE
INSTANTIATING-PROCEDURE HANDLE
 чтение Указатель процедуры, в которой был создан буфер записи
KEYS CHARACTER чтение
LAST-BATCH LOGICAL чтение/запись
LOCKED LOGICAL чтение Отражает имеет ли запись блокировку выставленную другим пользователем. Значение данного атрибута формируется аналогично функции LOCKED
NAME CHARACTER чтение/запись
NAMESPACE-PREFIX CHARACTER чтение/запись
NAMESPACE-URI CHARACTER чтение/запись
NEW LOGICAL чтение Имеет значение TRUE если запись является новой и FALSE, если находящаяся в буфере запись была прочитана из таблицы
NEXT-SIBLING HANDLE чтение
NUM-CHILD-RELATIONS INTEGER чтение Количество родственных элементов для которых буфер является родителем. Буфер может являться родителем для нескольких элементов, но быть дочерним только для одного.
NUM-FIELDS INTEGER чтение Количество полей в буфере записи
NUM-ITERATIONS INTEGER чтение
NUM-REFERENCES INTEGER чтение Количество ссылок на буфер записи
ORIGIN-ROWID ROWID  чтение
PARENT-RELATION HANDLE чтение
PRIMARY
PRIVATE-DATA  CHRACTER чтение/запись
QUERY HANDLE чтение/запись
RECID RECID чтение RECID записи в таблице базы данных
RECORD-LENGTH  ? чтение Размер записи в байтах
REJECTED
ROWID ROWID чтение ROWID записи в таблице базы данных
ROW-STATE
SERIALIZE-NAME
TABLE CHARACTER чтение Имя таблицы, из которой была извлечена запись
TABLE-HANDLE HANDLE чтение Указатель таблицы, из которой была извлечена запись
TABLE-NUMBER
TYPE CHARACTER чтение Тип объекта, значение "BUFFER"
UNIQUE-ID
XML-NODE-NAME


Методы:

Метод Описание
ACCEPT-CHANGES() Применяет изменения данных в одной или нескольких таблицах ProDataSet
APPLY-CALLBACK()
ATTACH-DATA-SOURCE()
BUFFER-COMPARE()

 

 

Вы здесь: Главная Основы ABL БУФЕРЫ ЗАПИСЕЙ