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
###############
$METHODS
Case CURPTH
When ""
Case ACTION
When "AREAD" : Gosub AREAD
When "AINSERT" : Gosub AINSERT
When "AUPDATE" : Gosub AUPDATE
When "ADELETE" : Gosub ADELETE
Endcase
When "YCOMBD"
Case ACTION
When "AREAD_AFTER" : Gosub YCOMBD_AREAD_AFTER
When "ADDLINE_AFTER" : Gosub YCOMBD_ADDLINE_AFTER
Endcase
Endcase
Return
CODECODE CODEsh
$AREAD
Local File YCOMB [YCO]
Local Integer ILINE
For [YCO] Where YGRP=this.YGRP
ILINE = 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_AERROR
Next
Return
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
$AINSERT
Local Integer ILINE
# Consistency controls
Gosub CTL_CONSISTENCY : If [L]ASTATUS>=[V]CST_AERROR : Return : Endif
# Loop on every line that has to be created
For ILINE=1 To maxtab(this.YCOMBD)
If this.YCOMBD(ILINE)<>null
If this.YCOMBD(ILINE).ASTALIN = CST_ANEW
[L]ASTATUS = fmet this.YCOMBD(ILINE).AINSERT()
Break ([L]ASTATUS>=[V]CST_AERROR)
Endif
Endif
Next
Return
The same first control is performed on the update method.
Three loops handle the different modifications that are made on the lines:
CODECODE CODEsh
$AUPDATE
Local Integer ILINE
Gosub CTL_CONSISTENCY : If [L]ASTATUS>=[V]CST_AERROR : Return : Endif
# Delete the lines
For ILINE= 1 To maxtab(this.YCOMBD)
If this.YVOMB(ILINE)<>null
If this.YCOMBD(ILINE).ASTALIN = [V]CST_ADEL
[L]ASTATUS = fmet this.YCOMBD(ILINE).ADELETE()
If [L]ASTATUS>=[V]CST_AERROR : Return : Endif
Endif
Endif
Next
# Update the lines
For ILINE= 1 To maxtab(this.YCOMBD)
If this.YCOMBD(ILINE)<>null
If this.YCOMBD(ILINE).ASTALIN = [V]CST_AUPD
[L]ASTATUS = fmet this.YCOMB(ILINE).AUPDATE()
If [L]ASTATUS>=[V]CST_AERROR : Return : Endif
Endif
Endif
Next
# Insert the lines
For ILINE= 1 To maxtab(this.YCOMBD)
If this.YCOMBD(ILINE)<>null
If this.YCOMBD(ILINE).ASTALIN = [V]CST_ANEW
[L]ASTATUS = fmet this.YCOMBD(ILINE).AINSERT()
Break [L]ASTATUS>=[V]CST_AERROR
Endif
Endif
Next
Return
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
$ADELETE
Local Integer ILINE
For ILINE= 1 To maxtab(this.YCOMBD)
If this.YCOMBD(ILINE)<>null
[L]ASTATUS = fmet this.YCOMBD(ILINE).ADELETE()
Break [L]ASTATUS>=[V]CST_AERROR
Endif
Next
Return
CODECODE CODEsh
# Check the consistency
$CTL_CONSISTENCY
Local Shortint LINE_FOUND
Local Integer IL, JL
For IL=1 To maxtab(this.YCOMBD)
If this.YCOMB(IL)<>null
If find(this.YCOMB(IL).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0
LINE_FOUND=1
For JL= IL+1 To maxtab(this.YCOMBD)
If this.YCOMB(JL)<>null
If find(this.YCOMB(JL).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0
If 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 2
Endif
Endif
Endif
Next JL
Endif
Endif
Next IL
If LINE_FOUND=0
[L]ASTATUS = fmet this.ASETERROR("",mess(178,123,1),[V]CST_AERROR)
Endif
Return
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_ALL
Return
$YCOMB_ADDLINE_AFTER
# To initialize properties of the header
this.YGRP = this.APARENT.YGRP
this.YNAM = this.APARENT.YNAM
Return
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 lines
Case CURPRO
When "YGRP"
Case ACTION
When 'PROPAGATE'
Local Integer IL
For IL= 1 To maxtab(this.YCOMBD)
If this.YCOMBD(IL)<>null
this.YCOMBD(IL).YGRP = this.YGRP
Endif
Next IL
Endcase
When "YNAM"
Case ACTION
When 'PROPAGATE'
Local Integer IL
For IL= 1 To maxtab(this.YCOMBD)
If this.YCOMBD(IL)<>null
this.YCOMBD(IL).YGRP = this.YGRP
Endif
Next IL
Endcase
Endcase
Return
This script manages the list of codes by using a table in memory. The code is as follows:
CODECODE CODEsh
#########################
# Representation YCOMB
#########################
###############
# METHODS
###############
$METHODS
Case CURPTH
When ""
Case ACTION
When "AQUERY_DECODE_CRITERIA_AFTER" : Gosub AQUERY_DECODE_CRITERIA_AFTER
When "AQUERY_PRIMARYKEYS_AFTER" : Gosub AQUERY_PRIMARYKEYS_AFTER
When "AQUERY_OPEN_AFTER" : Gosub AQUERY_OPEN_AFTER
When "AQUERY_TRANS_AFTER" : Gosub AQUERY_TRANS_AFTER
When "AQUERY_CLOSE_AFTER" : Gosub AQUERY_CLOSE_AFTER
Endcase
Endcase
Return
#################### Standard Query Events #########################
$AQUERY_DECODE_CRITERIA_AFTER
Raz NBPRO
NBPRO += 1
TBPRO(NBPRO) = "YGRP" : TBTYP(NBPRO) = 7 : TBPTH(NBPRO) = "YCOMBH.YGRP" : TBFIL(NBPRO) = "[LNK_]YGRP"
NBPRO += 1
TBPRO(NBPRO) = "YNAM" : TBTYP(NBPRO) = 7 : TBPTH(NBPRO) = "YCOMBH.YNAM" : TBFIL(NBPRO) = "[LNK_]YNAM"
Return
$AQUERY_PRIMARYKEYS_AFTER
ASTDKEY = "[LNK_]YGRP"
Return
$AQUERY_OPEN_AFTER
Local File YCOMB [QRY_YC]
Local Integer I : I=0
Local Char TYGRP(12)(1..), TYNAM(40)(1..)
For [QRY_YC]YCO0(1)
I+=1
TYGRP(I) = [F:QRY_YC]YGRP
TYNAM(I) = [F:QRY_YC]YNAM
Next
# 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<>0
Local File (Char YGRP(100),Char YNAM(100)) From Variable TYGRP,TYNAM As [LNK_]
Else
Local File YCOMB [LNK_]
Endif
Return
$AQUERY_TRANS_AFTER
this.YCOMB.YGRP = [LNK_]YGRP
this.YCOMB.YNAM = [LNK_]YNAM
Return
$AQUERY_CLOSE_AFTER
Close Local File [LNK_]
Return