Managing CRUD Combined Objects

IntroductionTable descriptionMain principlesYCOMBD class definition
YCOMB class definitionYCOMB representationYCOMB_CSTD scriptYCOMB_RSTD script

Introduction

A combined object is made of a unique table containing a key with two components. This table has multiple records that are associated with a given value of the first key component.

In this mode:

While the generation of the CRUD code for this type of object is not automated, objects can be created using the supervisor.

Table description

Table "YCOMB [YCO]" has the following structure (technical columns are not listed):

ColumnTypeDescriptionPlace
YGRPCharacter 10GroupHeader
YNAMCharacter 80Group descriptionHeader
YSGRPCharacter 5Group memberLine
YTEXTCharacter 40Member textLine
YDATEDateMember DateLine
YNUMDecimal 9.2Member valueLine

"YCO0" is the unique key of the table. It has no duplicates and it is made of two components: YGRP+YSGRP.

Main principles

"YCOMBD" class definition

This class has the following characteristics:

As there are no particular controls on this class, there is no script associated with it. However, you can add one if necessary.

"YCOMB" class definition

This class has the following characteristics:

"YCOMB" representation

This representation has the following characteristics:

"YCOMB_CSTD" script

HeaderRead methodInsertion methodUpdate method
Delete methodSubprogramsEvents on collectionEvents 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. They are located in the script, right after the $METHOD label in case "CURPTH" is empty.

Additionally, events AREAD_AFTER and ADDLINE_AFTER have to be handled on every "YCOMBD" record. When this happens, "CURPTH" is equal to "YCOMBD".

Header

The beginning of the script is as follows:

sh################ 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

Read method

The AREAD method performs a reading loop on the "YCOMBD" table. For every existing record, the ADDLINE method is invoked on the "YCOMBD" collection to add a line at the end of the table. The standard AREAD method is then used on the line instance to fill the record. The loop process stops if any error is found. This corresponds to the following code:

sh$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

Insertion method

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".

In this case, there is no need to make sure this.YCOMBD(ILINE) is not null because the instance collection was created by only adding lines at the end of the table, and because the deletion is exclusively logical.

The code is as follows:

sh$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

Update method

The same initial control is performed on the update method.

Three loops handle the different modifications that are made on the lines:

The code is as follows:

sh$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

Delete method

A loop is initiated on every line that invokes the DELETE method. The loop stops when an error occurs.

The code is as follows:

sh$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

"CTL_CONSISTENCY" subprogram

This subprogram performs a loop on the "YCOMBD" collection. If at least one line is found, "LINE_FOUND" is set to 1. A second loop, concatenated with the first one, checks whether the same "YGRP" value has been used on another line. If this is the case, an error is invoked and the loop is stopped.

The code is as follows:

sh# 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

Events on the "YCOMB" collection

Two events are necessary to properly manage the collection:

This provides the following code:

sh$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

Events called on the properties

The following additional controls must be performed on the properties (after the $PROPERTIES label in the script below):

This provides the following code:

sh$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

Script associated with the "YCOMB" representation

This script manages the list of codes by using a table in memory. The code is as follows:

sh########################## 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