Adapya: how to read, store and update data in severals files in one transaction

Adapya – how to read, store and update data in severals files in one transaction.

I’m starting with python and adapya.
I’d be greatful for an example/some tips how in one transaction read data from two different files, store data into two another files and update one of reading file.
I tried to adjust the serarch.py example with searching using datamaps.

I have two maps:
emptel.py (from example from documentation),
emp2.py (new map),
search_2.py (adjusted search.py from script from documentaton)

emptel.py: -----------------------------------------------------------
from adapya.base.datamap import Datamap, String
from adapya.adabas.metadata import metamap, Metadata
empTelFormat = ‘AA,AC,AD,AE,AH,8,U,AL,AN,AM,AO,AP.’
emp = Datamap(‘EmplTel’,
String(‘personnel_id’, 8),
String(‘firstname’, 20),
String(‘m_initial’, 20),
String(‘lastname’, 20),
String(‘birth’, 8),
String(‘country’, 3),
String(‘areacode’, 6),
String(‘phone’, 15),
String(‘department’, 6),
String(‘jobtitle’, 25)
)
metadata = Metadata(dbid=10,fnr=11,fb=empTelFormat,dmap=emp)

emp2.py: -----------------------------------------------------------
from adapya.base.datamap import Datamap, String
from adapya.adabas.metadata import metamap, Metadata
emp2Format = ‘AA,AC,AE,AO,AP.’
emp2 = Datamap(‘EmplTel’,
String(‘personnel_id’, 8),
String(‘firstname’, 20),
String(‘lastname’, 20),
String(‘department’, 6),
String(‘jobtitle’, 25)
)
metadata = Metadata(dbid=10,fnr=11,fb=emp2Format,dmap=emp2)

search_2.py:
from future import print_function
from adapya.adabas.API import Adabas, Adabasx, archit2str
from adapya.adabas.API import DataEnd, DatabaseError, InterfaceError, adaSetTimeout
from adapya.adabas.API import setsaf
from adapya.adabas.fields import readfdt
from adapya.base.defs import log,LOGBEFORE,LOGCMD,LOGCB,LOGRB,LOGRSP,LOGFB,
LOGSB,LOGIB,LOGMB,LOGVB,LOGSP,evals
from adapya.base.conv import str2ebc
from adapya.base.datamap import funpack, Datamap, String, T_VAR0
from adapya.base import datamap
import datetime
import getopt
import sys
import os

PY3 = True
getinput = input

debug=0
arc=None
acode=0
acbx=0
dbid=0
dmap = None # datamap from metadata
dprint = None # detail print function from metadata
descending=0
fnr=0
format=‘’
histo=‘’
islstr=‘’
isnlist=0
isnlower=0
toisn = 0 # test
multifetch=1
metadata = None
password=‘’
noclose=0
quantum = 8
readop=‘’
replytimeout=0
safuid=safpw=safnew=‘’
search=‘’
sortfields=‘’
superc=‘’
value=‘’
verbose=0
wcode=0
timezone=‘’

readop=‘AO.’
value=evals(‘SALE04’)
quantity = 1

metafile = ‘empltel’
import importlib
memo = importlib.import_module(metafile)
metadata = memo.metadata

read another field by another superdesc. -------------------------- SECOND DATAMAP

readop=‘AO.’
value=evals(‘SALESMAN’)
quantity = 1

metafile2 = ‘emp2’
memo2 = importlib.import_module(metafile2)
metadata2 = memo2.metadata

---------------------------------------------------------------------END VAR. FOR SECOND DATAMAP

readmod=3

dbid = metadata.dbid
fnr = metadata.fnr
dmap = metadata.dmap

rbl1 = dmap.getsize() # if dmap else 4096
rblm = min(rbl1multifetch, 215-1 if not acbx else 220-1) # limit rbl
mbl = 4+16
multifetch

fbl = len(metadata.fb) # if metadata else len(format)

c1=Adabas(fbl=fbl,rbl=rblm,sbl=32,vbl=128,ibl=max(isnlist*4,mbl),
multifetch=multifetch,password=password)
c1.dbid=dbid

c1.cb.fnr=fnr
c1.cb.cid=‘SSPY’
c1.fb.write(metadata.fb) # if metadata else format) # tu jest metadata

LOGL3=LOGS1=LOGRD=LOG0=LOGRSP

try:

log(LOG0)

c1.open(arc=arc,acode=acode,wcode=wcode,tz=timezone)
# c1.printopsys()

desc=readop[0:2]      # extract descriptor
c1.sb.write(readop)    # set selection criterion
c1.vb.write(value)
log(LOGL3)


c1.cb.cid='SSP2'

seq = readop[0:2]

dm = Datamap( 'record',String('vrec' , 0, opt=T_VAR0, sizefunc=lambda: dm.dmlen ))
nr = 0

c1.cb.rsv1=b'\xd5' # rsv1=N no option check

row = memo.emp
row.buffer = c1.rb
row.offset = 0

for isn,_ in c1.read(seq=seq,dmap=dm,descending=descending,startisn=isnlower,toisn=toisn):
    nr += 1
    dm.prepare() # adjust variable field
   
    print(' ' + dm.vrec)
    
    c1.cb.cmdt=0 # no further time for additional records in multifetch
    

    if seq not in ('I') and nr == c1.cb.isq:
        break
    if nr>5: # not more than 5 rows
        break

datamap.debug=0

----------------------------------------------------------------------

# HERE I'D LIKE TO READ DATA FROM ANOTHER FILE 
# OR THE SAME FILE BUT ANOTHER LIST OF FIELDS AND BY ANOTHER DESC. - FOR EXAMPLE FOR DMAP EMP2
# ....
# AND LATER STORE DATA TO ANOTHER TWO FILES AND UPDATE DATA IN THE FIRST FILE
# ...
# AT THE END : ET()

# -----------------------------------------------------------------------

except DatabaseError as e:
print( ‘DatabaseError Exception on database %d\n\t%s’ % (dbid,e.value))
print( ‘Terminating due to database error’)
sys.exit(8)
except InterfaceError as e:
print( ‘Database %d –\n\t%s’ % (dbid,e.value))
sys.exit(16)
except Exception as e:
print( e)
from traceback import print_exc
print_exc()
sys.exit(12)
finally:
if not noclose:
log(LOG0)
c1.close()
# print(‘Adabas session closed. I/Os=%d, calls=%d, cpu=%4.3f ms’ % (
# c1.cb.isn, c1.cb.isl, c1.cb.isq/4096000. if acbx else c1.cb.isq * 1048.576))
else:
print( ‘noclose: Skipping close to database %d’ % dbid)

Working with other database files is can be facilitated when using another set of Adabas call parameters, i.e. c2=Adabas(…). For instance, taking your code as a basis to read all employees of SALE04 department and getting the employee’s cars from the Vehicles file.
There is a second read loop within the first: from the current Employees record personnel_id is taken to read in the Vehicles file.
A separate set of Adabas call parameters is needed for example for a read loop.
For update commands another set of Adabas call parameters would be used.
Examples for updates and inserts can be found in the adapya/adabas/scripts folder: ticker.py and n1_acbx.py

Does this answer your questions?

Reading_in_2_files.zip (2.4 KB)

dbid2, fnr2, dm2 = meta2.dbid, meta2.fnr, meta2.dmap    
rbl2, fbl2 = dm2.getsize(), len(meta2.fb)

c2 = Adabas(fbl=fbl2,rbl=rbl2,sbl=32,vbl=128,ibl=4)

c2.cb.dbid = meta2.dbid
c2.cb.fnr = meta2.fnr
c2.fb.write(meta2.fb)

try:
    c1.open()   # Adabas open call

    seq = fld1              # descriptor
    c1.searchfield(fld1,vlen1+1,value1+'*',first=1,last=1)  # if value ends with *: from-to selection

    print('\nSelecting records in %s with field %s = %s\n' % (dm1.dmname, fld1, value1+'*'))

    for isn, rec1 in c1.read(seq=seq,dmap=dm1):
        rec1.lprint()    # print record line

        value2 = rec1.personnel_id
        vlen2 = len(value2)
        seq2 = fld2              # descriptor
        c2.searchfield(fld2,vlen2+1,value2+'*',first=1,last=1)
 
        for isn2,rec2 in c2.read(seq=seq2,dmap=dm2):
            rec2.dprint()    # print record detail 
1 Like

Thank you!
Reading data from two files works.

MU fields and fields within PE need to be defined in the format buffer with the right syntax that can be looked up in the Adabas Command reference manual.

And MUs/PEs need to be specified in the Datamap. Examples of use can be found in folder adapya.base.test file datamap_test.py

I have set up an example with a new metafile ‘emplrec’ and some improvements in datamap.py and search.py - see attachment

Essentially, MU fields need an ‘occurs’ parameter and for PEs there is a ‘Periodic’ element with ‘occurs’ parameter that contains another Datamap structure. For example:

emplrec = Datamap('Employee',
        String('personnel_id',8,fn='AA'),
        String('address_line',20,fn='AI',occurs=2),
        Periodic(Datamap('Income',
            String('currency',3,fn='AR'),
            Unpacked('salary',9,fn='AS'),
            Unpacked('bonus',9,fn='AT',occurs=3),
            ),occurs=2)
       )    

Using the emplrec with the search script:

>search -M emplrec --read AO. --value SALE20

    1   556 Record
Employee
personnel_id = '20006500'
first_name   = 'STEPHEN'
name         = 'SAMUELSON'
birth        = 714178
address_line = ['C/O GMD CORP.', ' 8601 DUNWOODY PLACE']
city         = 'IRVINE'
country      = 'USA'
dept         = 'SALE20'
jobtitle     = 'SALES PERSON'

    Income
    currency    salary     bonus
    USD          32000 6000, 0, 0

    USD          29400 4500, 0, 0

I hope this answers your questions.
Handling_MU_and_PE.zip (26.2 KB)

1 Like

Thank you.
Now it’s clear.