How to crud combined object
Introduction | Table description | Main principles | The YCOMBD class |
The YCOMB class | The YCOMB representation | The YCOMB_CSTD script | The YCOMB_RSTD script |
In version 6 platform, a "Combined Object" is a type of object where a unique table containing a key with two components has multiple records associated with a given value of the first key component.
In this mode, the screen has a header and a grid.
* The header includes the first component of the key and additional fields with the same value for all records.
* The grid displays a row for each record with the same first key value.
While the generation of the CRUD code for this type of version 6 object is not automated, the new version 7 supervisor enables the creation of these objects as explained in the following example:
The table 'YCOMB [YCO]' to be handled has the following structure (technical columns are not listed):
Column | Type | Description | Place |
---|---|---|---|
YGRP | Character 10 | Group | Header |
YNAM | Character 80 | Group description | Header |
YSGRP | Character 5 | Group member | Line |
YTEXT | Character 40 | Member text | Line |
YDATE | Date | Member Date | Line |
YNUM | Decimal 9.2 | Member value | Line |
'YCO0' is the unique key in the table. This key has no duplicates and is made up of two components: YGRP+YSGRP.
The principles of handling a Combined Object are the following:
This class has the following characteristics:
As there are no particular controls on this class, there is no script associated with the class; however, one can be added if necessary.
This class has the following characteristics:
This representation has the following characteristics:
The properties are:
In the HEADER block
Both are present on all the facets and can be entered.
In the LINES block
All are present on the facets Detail and Edit, and can be entered.
Header | Read method | Insertion method | Update method |
Delete method | Subprograms | Events on collection | Events on properties |
The script implements the CRUD method for the combined object. The 'YCOMB' class is not persistent; therefore, the AREAD, AINSERT, AUPDATE, and ADELETE events are used. This is located in the script just after the '$METHOD' label in case 'CURPTH' is empty.
Additionally, the following two events: 'AREAD_AFTER' and 'ADDLINE_AFTER' have to be handled on every 'YCOMBD' record. When this happens, 'CURPTH' is equal to 'YCOMBD'.
CODECODE CODEsh################ METHODS###############$METHODSCase CURPTHWhen ""Case ACTIONWhen "AREAD" : Gosub AREADWhen "AINSERT": Gosub AINSERTWhen "AUPDATE": Gosub AUPDATEWhen "ADELETE": Gosub ADELETEEndcaseWhen "YCOMBD"Case ACTIONWhen "AREAD_AFTER" : Gosub YCOMBD_AREAD_AFTERWhen "ADDLINE_AFTER" : Gosub YCOMBD_ADDLINE_AFTEREndcaseEndcaseReturn
CODECODE CODEsh$AREADLocal File YCOMB [YCO]Local Integer ILINEFor [YCO] Where YGRP=this.YGRPILINE = fmet this.ADDLINE("YCOMBD",CST_ALASTPOS)[L]ASTATUS = fmet this.YCOMBD(ILINE).AREAD([F:YCO]YGRP,[F:YCO]YSGRP)# The syntax Break condition means that if condition is true (ie 1), a Break 1 is done (Break 0 does nothing)Break [L]ASTATUS>=[V]CST_AERRORNextReturn
Consistency checks must be performed on the insertion method:
The corresponding sub-program is 'CTL_CONSISTENCY'.
A loop is performed to insert all of the lines with 'CST_ANEW' as the line status. While in insertion mode, the only other status that can be encountered is 'CST_ANEWDEL'.
Controlling that 'this.YCOMBD(ILINE)' is not null is useless in this case because the instance collection has been created by only adding lines at the end of the table, and because the deletion done is exclusively logical.The code is as follows:CODECODE CODEsh$AINSERTLocal Integer ILINE# Consistency controlsGosub CTL_CONSISTENCY : If [L]ASTATUS>=[V]CST_AERROR : Return : Endif# Loop on every line that has to be createdFor ILINE=1 To maxtab(this.YCOMBD)If this.YCOMBD(ILINE)<>nullIf this.YCOMBD(ILINE).ASTALIN = CST_ANEW[L]ASTATUS = fmet this.YCOMBD(ILINE).AINSERT()Break ([L]ASTATUS>=[V]CST_AERROR)EndifEndifNextReturn
The same first control is performed on the update method.
Three loops handle the different modifications that are made on the lines:
CODECODE CODEsh$AUPDATELocal Integer ILINEGosub CTL_CONSISTENCY : If [L]ASTATUS>=[V]CST_AERROR : Return : Endif# Delete the linesFor ILINE= 1 To maxtab(this.YCOMBD)If this.YVOMB(ILINE)<>nullIf this.YCOMBD(ILINE).ASTALIN = [V]CST_ADEL[L]ASTATUS = fmet this.YCOMBD(ILINE).ADELETE()If [L]ASTATUS>=[V]CST_AERROR : Return : EndifEndifEndifNext# Update the linesFor ILINE= 1 To maxtab(this.YCOMBD)If this.YCOMBD(ILINE)<>nullIf this.YCOMBD(ILINE).ASTALIN = [V]CST_AUPD[L]ASTATUS = fmet this.YCOMB(ILINE).AUPDATE()If [L]ASTATUS>=[V]CST_AERROR : Return : EndifEndifEndifNext# Insert the linesFor ILINE= 1 To maxtab(this.YCOMBD)If this.YCOMBD(ILINE)<>nullIf this.YCOMBD(ILINE).ASTALIN = [V]CST_ANEW[L]ASTATUS = fmet this.YCOMBD(ILINE).AINSERT()Break [L]ASTATUS>=[V]CST_AERROREndifEndifNextReturn
A loop is initiated on every line that invokes the 'DELETE' method. The loop stops when an error occurs.
The code is as follows:CODECODE CODEsh$ADELETELocal Integer ILINEFor ILINE= 1 To maxtab(this.YCOMBD)If this.YCOMBD(ILINE)<>null[L]ASTATUS = fmet this.YCOMBD(ILINE).ADELETE()Break [L]ASTATUS>=[V]CST_AERROREndifNextReturn
CODECODE CODEsh# Check the consistency$CTL_CONSISTENCYLocal Shortint LINE_FOUNDLocal Integer IL, JLFor IL=1 To maxtab(this.YCOMBD)If this.YCOMB(IL)<>nullIf find(this.YCOMB(IL).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0LINE_FOUND=1For JL= IL+1 To maxtab(this.YCOMBD)If this.YCOMB(JL)<>nullIf find(this.YCOMB(JL).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0If this.YCOMB(IL).YSGRP= this.YCOMB(JL).YSGRP[L]ASTATUS = fmet this.ASETERROR("YGRP", this.YCOMB(IL).YSGRP -":"-mess(94,139,1),[V]CST_AERROR)Break 2EndifEndifEndifNext JLEndifEndifNext ILIf LINE_FOUND=0[L]ASTATUS = fmet this.ASETERROR("",mess(178,123,1),[V]CST_AERROR)EndifReturn
Two events are necessary to properly manage the collection:
CODECODE CODEsh$YCOMB_AREAD_AFTER# Assign ASTALIN to CST_ALL (they have the value 'CST_ANEW' just after AREAD method)this.ASTALIN = [V]CST_ALLReturn$YCOMB_ADDLINE_AFTER# To initialize properties of the headerthis.YGRP = this.APARENT.YGRPthis.YNAM = this.APARENT.YNAMReturn
The following additional controls must be done on the properties (after the '$PROPERTIES' label in the script below):
CODECODE CODEsh$PROPERTIES# If YGRP or YNAM have been modified, perform a loop to update all the linesCase CURPROWhen "YGRP"Case ACTIONWhen 'PROPAGATE'Local Integer ILFor IL= 1 To maxtab(this.YCOMBD)If this.YCOMBD(IL)<>nullthis.YCOMBD(IL).YGRP = this.YGRPEndifNext ILEndcaseWhen "YNAM"Case ACTIONWhen 'PROPAGATE'Local Integer ILFor IL= 1 To maxtab(this.YCOMBD)If this.YCOMBD(IL)<>nullthis.YCOMBD(IL).YGRP = this.YGRPEndifNext ILEndcaseEndcaseReturn
This script manages the list of codes by using a table in memory. The code is as follows:
CODECODE CODEsh########################## Representation YCOMB######################################### METHODS###############$METHODSCase CURPTHWhen ""Case ACTIONWhen "AQUERY_DECODE_CRITERIA_AFTER" : Gosub AQUERY_DECODE_CRITERIA_AFTERWhen "AQUERY_PRIMARYKEYS_AFTER" : Gosub AQUERY_PRIMARYKEYS_AFTERWhen "AQUERY_OPEN_AFTER" : Gosub AQUERY_OPEN_AFTERWhen "AQUERY_TRANS_AFTER" : Gosub AQUERY_TRANS_AFTERWhen "AQUERY_CLOSE_AFTER" : Gosub AQUERY_CLOSE_AFTEREndcaseEndcaseReturn#################### Standard Query Events #########################$AQUERY_DECODE_CRITERIA_AFTERRaz NBPRONBPRO += 1TBPRO(NBPRO) = "YGRP" : TBTYP(NBPRO) = 7 : TBPTH(NBPRO) = "YCOMBH.YGRP" : TBFIL(NBPRO) = "[LNK_]YGRP"NBPRO += 1TBPRO(NBPRO) = "YNAM" : TBTYP(NBPRO) = 7 : TBPTH(NBPRO) = "YCOMBH.YNAM" : TBFIL(NBPRO) = "[LNK_]YNAM"Return$AQUERY_PRIMARYKEYS_AFTERASTDKEY = "[LNK_]YGRP"Return$AQUERY_OPEN_AFTERLocal File YCOMB [QRY_YC]Local Integer I : I=0Local Char TYGRP(12)(1..), TYNAM(40)(1..)For [QRY_YC]YCO0(1)I+=1TYGRP(I) = [F:QRY_YC]YGRPTYNAM(I) = [F:QRY_YC]YNAMNext# A test must be done on I (this will be fixed later)# On empty arrays, for behaves as if 32,768 lines were here!If I<>0Local File (Char YGRP(100),Char YNAM(100)) From Variable TYGRP,TYNAM As [LNK_]ElseLocal File YCOMB [LNK_]EndifReturn$AQUERY_TRANS_AFTERthis.YCOMB.YGRP = [LNK_]YGRPthis.YCOMB.YNAM = [LNK_]YNAMReturn$AQUERY_CLOSE_AFTERClose Local File [LNK_]Return