User’s Guide

Read and Update Example

The following program inserts a record into the Employees demo file, reads and backs it out:

adapya/adabas/scripts/n1_acbx.py
"""Store and Read record then backout and close session"""
from __future__ import print_function          # PY3

from adapya.base.defs import log, LOGBEFORE, LOGCMD, LOGCB, LOGRB, LOGRSP, LOGFB
from adapya.adabas.api import Adabasx, DatabaseError, UPD
from adapya.base.dump import dump

FNR=11;DBID=8               # Employees file 11 in database 8
FB=b'AA,8,A.'               # String for format buffer with field AA (personnel-id)

c1=Adabasx(fbl=64,rbl=64)   # allocate set of buffers ACBX,
                            # abd+format and record buffer

log(LOGCMD|LOGCB|LOGRB|LOGFB) # switch on printing of Adabas commands

try:
    # print Adabas buffers after Adabas call
    c1.cb.dbid=DBID         # for ACBX; c1.dbid=DBID for ACB
    c1.cb.fnr=FNR           # set control block fields

    c1.open(mode=UPD)       # issue OP

    c1.cb.cid=b'abcd'       # command id
    c1.cb.isn=0             # no record number yet
    c1.fb.value=FB          # put data into format buffer
    c1.rb.value=b'ABCDEFGH' # ..            record buffer
    c1.rabd.send=8          # set send size for record buffer

    c1.store()              # issue N1

    c1.rb.value=b' '*8      # reset record buffer

    c1.get()                # issue L1

    print( repr(c1.rb.value), 'returned size', c1.rabd.recv)

except DatabaseError as e:
    print('DatabaseError exception:\n%s\n' % e.value)
    dump(e.apa.acbx, header='Control Block Extended')
    raise
finally:
    log(LOGCMD|LOGRSP)
    c1.bt()                 # issue backout
    c1.close()

Some explanations in the following sections. You may also look into source adapya/adabas/api.py

Adabasx Objects

Adabas database requests use a control block and a number of data buffers. In Python such a request can be set up with an Adabasx object

c1=Adabasx(fbl=64,rbl=64)

c1 is an instance of the Adabasx class with an Adabas control block (ACBX) and a format buffer of and record buffer of 64 bytes length each.

The Adabasx and Acbx classes are defined in adapya/adabas/api.py.

When creating the Adabasx object Python calls the __init__() method defined in the Adabas class. Behind the scenes, this method does the following

  1. create a buffer with Abuf() of length ACBXLEN and assign it to the attribute acbx of the Adabasx. Create format and record buffers:

    import from adapya.base.defs Abuf
    self.acbx=Abuf(ACBXLEN)
    self.fb=Abuf(fbl)
    self.rb=Abuf(rbl)
    
  2. define a mapping of Acbx fields to the buffer:

    self.cb=Acbx(buffer=self.acbx)
    

Abuf()

adapya.base.defs defines the buffer class Abuf(size) which is backed by the ctypes character buffer.

Abuf() defines slice and file I/O operations and is used as read/write buffer in the foreign function call to the Adabas database.

Datamap()

Internally, Python has no concept to store data of different variables physically together as in a C struct or assembler DSECT. Yet with pack() and unpack() functions from the Python struct module variables can be mapped to a buffer (or string).

With the datamap.py module from the adapya.base package such a mapping can be defined similar to C structs.

Opening a session with the database

The following statement sets the database id in the Adabas control block in c1 to select the database:

c1.cb.dbid=8
c1.open(mode=UPD) # issue OP

Then the open() method of the Adabasx class issues an Adabas OP command.

Storing a Record

Preparation to store a new record:

c1.cb.cid=b'abcd'
c1.fb.value=FB          # put data into format buffer
c1.rb.value=b'ABCDEFGH' # .. record buffer
c1.rabd.send=8          # set send size for record buffer

c1.store()              # issue N1

In detail: set Command id is set with a 4 byte string:

c1.cb.cid=b'abcd'

Assign data to the record buffer:

c1.rb.value=b'ABCDEFGH'

c1.rb is the record buffer. Make sure that you assign a value with c1.rb.value or with the slice operator:

c1.rb[0:8]=b'ABCDEFGE'

With ACBX the size of the buffers to send must be set. c1.rabd is the record buffer ABD:

c1.rabd.send=8 # set send size for record buffer

The store() function is used to insert a new record. It issues the N1 command and is equivalent to:

c1.call(cmd='N1', isn=0, op1=' ', op2=' ')

Reading a Record

c1.rb.value=b' '*8      # reset record buffer

c1.get() # issue L1

print( repr(c1.rb.value), 'returned size', c1.rabd.recv)

Backing-out the Transaction

At the end of the program we back out the transaction which removes the new record from the database.

c1.bt() # issue backout

Closing the User session

c1.close() # issue close

Response Code Checking vs. Exception Handling

try:
    ....
except DatabaseError as e:
    print('DatabaseError exception:\n%s\n' % e.value)
    dump(apa.acbx, header='Control Block')
    raise

The block within try: and except: contains some Adabas calls.

Any Adabas response code will interupt the program sequence and raise a DatabaseError exception. This is caught in with the except: statement and handled by printing diagnostic information.