*DECK DB$SR66 
USETEXT MDBCMTX 
USETEXT MD10CTX 
USETEXT UTMPTTX 
      PROC DB$SR66; 
      BEGIN 
 #
* *   DB$SR66 - BUILD CONSTRAINT USE TABLE       PAGE  1
* *   J. G. SERPA                                DATE  08/05/80 
* 
* DC  PURPOSE 
* 
*     BUILD THE CONSTRAINT USE TABLE (CUT) TO BE USED BY DB$SR67 IN 
*     CHECKING THAT CONSTRAINT VIOLATIONS ARE NOT INTRODUCED ACROSS 
*     VERSIONS. 
* 
* DC  ENTRY CONDITIONS
* 
*     PCUT HAS BEEN BUILT, CONTAINING THE WORD ADDRESS OF THE AREA
*     ENTRIES IN THE DDL SCHEMA DIRECTORY AND THEIR ASSOCIATED MASTER 
*     DIRECTORY AREA-IDS. 
*     PCUTNDX CONTAINS THE LENGTH OF THE PCUT.
*     PCUTBP CONTAINS THE ADDRESS OF THE BLOCK FOR THE PRE-CONSTRAINT 
*     USE TABLE.
* 
* DC  EXIT CONDITIONS 
* 
*     IF THERE WERE NO AREAS SPECIFIED FOR THE CURRENT SCHEMA,
*     THE CONSTRAINT USE TABLE IS NOT BUILT AND RETURN IS TO
*     DB$NO.
*     IF THERE ARE CONSTRAINTS SPECIFIED IN THE SCHEMA, THE CONSTRAINT
*     USE TABLE (CUT) HAS BEEN BUILT, OTHERWISE NO ACTION HAS BEEN
*     TAKEN.
*     EACH ENTRY IN THE CUT CONTAINS A PAIR OF AREA IDS WHICH CORRESPOND
*     TO THE PARENT AND CHILD AREA PAIR INVOLVED IN THE CONSTRAINT. 
*     THE CMM BLOCK FOR THE PCUT HAS BEEN RELEASED
*     EXIT IS TO DB$NO. 
* 
* DC  CALLING ROUTINES
* 
*     SCHNTRY - ANALYZE SCHEMA ENTRY (WITHIN DB$SNTX - SYNGEN)
* 
* DC  CALLED ROUTINES 
* 
# 
      XREF PROC DB$ERSC;           # ERROR PROCESSOR FOR SCHEMA FILE   #
      XREF PROC DB$NO;             # SYNTAX TABLE DRIVER -NO- RETURN   #
      XREF PROC DB$UALC;           # ALLOCATE SPACE IN MANAGED MEMORY  #
      XREF PROC DB$UAWS;           # ADJUST WORK SPACE                 #
      XREF PROC DB$UFRE;           # FREE UP SPACE IN MANAGED MEMORY   #
      XREF PROC DB$WGET;           # READ FROM WORD ADDRESSABLE FILE   #
# 
* 
* DC  NON-LOCAL VARIABLES MODIFIED
* 
*     NONE
* 
* DC  DESCRIPTION 
* 
*     FIRST, CHECK THAT AT LEAST ONE AREA WAS SPECIFIED FOR 
*     THE CURRENT SCHEMA. THIS IS DONE BY CHECKING FIELD
*     AREACNT. IF AREACNT IS ZERO, THERE WERE ERRORS IN THE 
*     MD SOURCE INPUT AND THERE IS NO REASON TO TRY BUILDING
*     THE CONSTRAINT USE TABLE. IN THIS CASE, RETURN IS TO
*     DB$NO.
*     IF THERE ARE NO CONSTRAINTS SPECIFIED IN THE SCHEMA (SCCWCSNUM=0) 
*     EXIT TO DB$NO. IF CONSTRAINTS WERE SPECIFIED IN THE SCHEMA, 
*     ALLOCATE A CMM BLOCK BIG ENOUGH TO READ IN THE ENTIRE DDL 
*     CONSTRAINT INTEGRITY TABLE. 
*     A PASS WILL BE MADE THROUGH THE CIT (DDL CONSTRAINT INTEGRITY 
*     TABLE). FOR EACH CONSTRAINT IN THE CIT, THE FOLLOWING PROCESSING
*     WILL BE DONE: 
*     INTRA AREA CONSTRAINTS (I.E., CONSTRAINTS WHERE THE SAME AREA 
*     IS BOTH PARENT AND CHILD) WILL BE SKIPPED OVER. 
*     THE PARENT AREA WORD ADDRESS WILL BE USED TO SEARCH THE PCUT
*     (THIS IS A TABLE BUILT BY DB$SR06 WHICH ASSOCIATES DDL SCHEMA 
*     DIRECTORY AREA WORD ADDRESSES WITH MASTER DIRECTORY AREA-IDS).
*     WHEN A MATCH IS FOUND, THE AREA-ID FOR THIS AREA WILL BE ENTERED
*     INTO THE PARENT AREA SLOT IN THE CUT, THEN THE CHILD AREA WORD
*     ADDRESS WILL BE USED TO SEARCH THE PCUT. WHEN A MATCH IS FOUND, 
*     THE AREA-ID WILL BE ENTERED INTO THE CHILD AREA SLOT IN THE CUT.
*     THEN THE CUT WILL BE SEARCHED FOR AN ENTRY THAT MATCHES THIS ENTRY
*     JUST CREATED. IF A MATCHING ENTRY, OTHER THAN THE ONE JUST
*     CREATED, IS FOUND, THE INDEX INTO THE CUT IS NOT INCREMENTED. 
*     IF A MATCH IS NOT FOUND (MEANING THAT THIS AREA-ID PAIR IS
*     UNIQUE), THE INDEX IS INCREMENTED, THUS MAKING THIS ENTRY 
*     A PERMANENT PART OF THE CUT.
*     WHEN THE TABLE IS COMPLETE, CALL DB$UFRE TO RELEASE THE BLOCK 
*     THAT CONTAINS THE CIT, CALL DB$UAWS TO SHRINK THE CUT TO ITS
*     PRESENT SIZE, AND STORE ITS SIZE INTO THE SCHEMA DIRECTORY. 
* 
 #
  
      BASED ARRAY CIT [0:0] S(1);  # CONSTRAINT INTEGRITY TABLE        #
        BEGIN 
*CALL SCCSHDDCL              SCHEMA CONSTRAINT HEADER 
*CALL SCCSVRDCL              SCHEMA CONSTRAINT VARIABLE 
        END 
  
      BASED ARRAY CUT [0:0] S(DFCUTENT);  # CONSTRAINT USE TABLE       #
        BEGIN 
*CALL MDCUTDCLS              # CONSTRAINT USE TABLE 
        END 
  
      BASED ARRAY MDSCENTRY [0:0] S(1);  # SCHEMA DIRECTORY TABLE      #
        BEGIN 
*CALL MDSCDDCLS              SCHEMA DIRECTORY TABLE 
        END 
  
      BASED ARRAY PCUT [0:0] S(DFPCUTENT);  # PRE-CONSTRAINT USE TABLE #
        BEGIN 
*CALL MDPCTDCLS              # PRE-CONSTRAINT USE TABLE 
        END 
  
      XREF ITEM DE$FTSC;     # FIT FOR SCHEMA LFN                      #
  
      ITEM CITBP;            # CIT BLOCK POINTER                       #
      ITEM CITOFST;          # OFFSET FROM CITBP TO P<CIT>             #
      ITEM CITPTR;           # POINTER INTO THE CIT                    #
      ITEM CUTNDX;           # INDEX INTO THE CUT                      #
      ITEM FOUND B;          # DUMMY BOOLEAN VARIABLE                  #
      ITEM I;                # DUMMY INDEX VARIABLE                    #
      ITEM K;                # DUMMY INDEX VARIABLE                    #
      CONTROL EJECT;
      IF AREACNT EQ 0              # NO AREAS WERE SPECIFIED           #
      THEN
        BEGIN 
        DB$NO;                     # EXIT TO STD                       #
  
        END 
  
      IF SCCWCSNUM[0] EQ 0         # IF THERE ARE NO CONSTRAINTS       #
      THEN
        BEGIN 
        DB$NO;                     # EXIT TO STD                       #
  
        END 
      CUTNDX = 0; 
      CITBP = 0;
      CUTBP = 0;
      DB$UALC(LOC(CITBP),SCCWCITLEN[0],0); # ALLOCATE BLOCK FOR CIT    #
      DB$UALC(LOC(CUTBP),DFCUTENT,DFCUTPD);  # ALLOCATE BLOCK FOR CUT  #
      P<CIT> = CITBP + 1;          # POSITION CIT                      #
      DB$WGET(DE$FTSC,CIT,SCCWCITLEN[0],SCCWCITWA[0],DB$ERSC);  # READ #
      P<CIT> = CITBP + 1;          # POSITION CIT                      #
      P<CUT> = CUTBP + 1;          # POSITION CUT                      #
      P<PCUT> = PCUTBP + 1;        # POSITION THE CUT                  #
      FOR I = 0 STEP 1             # STEP THROUGH THE CIT              #
       UNTIL SCCWCSNUM[0] - 1 
      DO
        BEGIN 
        IF SCCSSUBTYP[0] EQ 2      # IF THIS IS AN INTRA-AREA          #
                                   # CONSTRAINT                        #
        THEN
          BEGIN 
          P<CIT> = LOC(CIT) + SCCSENTLEN[0];  # GET NEXT CONSTRAINT    #
          TEST I; 
  
          END 
        CITPTR = SCCSNAMLENW[0] + SCCSNAMPTR[0];   # POINTER INTO CIT  #
        FOUND = FALSE;
        FOR K = 0 STEP 1           # SEARCH PCUT FOR A MATCH ON        #
                                   # PARENT AREA WORD ADDRESS          #
          WHILE NOT FOUND 
        DO
          BEGIN 
          IF SCCSAREAWA[CITPTR+1] EQ MDPCUTWA[K]  # IF PARENT AREA WORD#
                                                  # ADDRESS MATCHES    #
          THEN
            BEGIN 
            MDCUTAIP[CUTNDX] = MDPCUTAID[K];  # ENTER PARENT AREA ID   #
                                              # INTO THE CUT           #
            FOUND = TRUE; 
            END 
          END 
        FOR K = 0 STEP 1           # SEARCH PCUT FOR A MATCH ON        #
                                   # CHILD AREA WORD ADDRESS           #
          WHILE K LS PCUTNDX
        DO
          BEGIN 
          IF SCCSAREAWA[CITPTR] EQ MDPCUTWA[K]  # IF CHILD AREA WA     #
                                                # MATCHES              #
          THEN
            BEGIN 
            MDCUTAIC[CUTNDX] = MDPCUTAID[K];  # ENTER CHILD AREA ID    #
                                              # INTO THE CUT           #
            K = PCUTNDX;                      # TERMINATE LOOP         #
            END 
          END 
        FOUND = FALSE;
        FOR K = 0 STEP 1           # SEARCH CUT FOR AN ENTRY THAT      #
                                   # MATCHES THE ONE JUST ENTERED      #
        WHILE K LS CUTNDX 
          AND NOT FOUND 
        DO
          BEGIN 
          IF MDCUTWORD[K] EQ MDCUTWORD[CUTNDX]  # IF A MATCH IS FOUND  #
          THEN
            BEGIN 
            FOUND = TRUE;                       # SET FOUND FLAG       #
            END 
          END 
        IF NOT FOUND               # IF A MATCH NOT FOUND              #
        THEN
          BEGIN 
          CUTNDX = CUTNDX + 1;     # INCREMENT INDEX INTO THE CUT      #
          CITOFST = LOC(CIT) - CITBP; # SAVE CIT OFFSET FROM CITPB     #
          DB$UAWS(LOC(CUTBP),DFCUTENT);  # ADD 1 ENTRY TO THE CUT      #
          P<CUT> = CUTBP + 1;      # POSITION CUT                      #
          P<PCUT> = PCUTBP + 1;    # POSITION PCUT                     #
          P<CIT> = CITOFST + CITBP;   # RESTORE CIT ( CMM MIGHT HAVE   #
                                      # CHANGED IT-S POSITION IN CM )  #
          END 
        P<CIT> = LOC(CIT) + SCCSENTLEN[0];  # GET NEXT CONSTRAINT      #
        END 
      DB$UFRE(LOC(CITBP));         # FREE UP THE CIT                   #
      DB$UFRE(LOC(PCUTBP));        # FREE UP THE PCUT                  #
      P<MDSCENTRY> = SCDRBP + 1;   # POSITION SCHEMA DIRECTORY         #
      MDSCCUTSZ[SCHDIRP] = CUTNDX * DFCUTENT;  # STORE SIZE OF CUT     #
      DB$NO;                       # EXIT TO DB$STD                    #
      END 
      TERM
