# rddiv --- divide input relation 1 by input relation 2

   include "rdb_def.r.i"

   define (DB,#)

   relation_des Rrd (RDSIZE), Srd (RDSIZE), Trd (RDSIZE)
   file_des Rfd, Sfd, Tfd
   integer ap, i, j, pos2, bp, rstat, comp
   integer Rkeys (MAXKEYS), Skeys (MAXKEYS)
   integer Rrow (RDATASIZE), Srow (RDATASIZE), Trow (RDATASIZE)
   integer x (RDATASIZE), y (RDATASIZE), z (RDATASIZE)
   integer dest (MAXLINE), garbage (MAXLINE)
   integer load_rd, isatty, add_field_to_rd, create
   integer find_field, get_row, compare_row, rewind
   character orders (MAXKEYS)

  ### Load the descriptors for the original relations

   if (load_rd (Rrd, STDIN) ~= OK)
      call error ("Cannot load input relation 1"p)

   if (load_rd (Srd, STDIN2) ~= OK)
      call error ("Cannot load input relation 2"p)

  ### Create the difference relation descriptor in Trd
  ### Trd = Rrd - Srd
  ### Also, set up the list of keys for sorting R

   init_rd (Trd)
   ap = 0
   for (i = FIRSTRF (Rrd); ISLASTRF (Rrd, i); i = NEXTRF (Rrd, i)) {

      j = find_field (Srd, RFNAME (Rrd,i))
      if (j == 0) { # if the field is in Rrd but not Srd put it in Trd
         pos2 = add_field_to_rd (Trd, RFTYPE (Rrd, i), RFLEN (Rrd, i),
            RFNAME (Rrd, i))
         ap = ap+1
         Rkeys (ap) = i
         orders (ap) = "a"c
      }
   }

  ### set up the list of keys for sorting S

   bp = 0
   for (i = FIRSTRF (Srd) ; ISLASTRF (Srd, i) ; i = NEXTRF(Srd, i)) {

      j = find_field (Rrd, RFNAME (Srd,i) )
      if (j == 0)
         call error ("Relation 2 has domain not defined in relation 1"p)
      else {
         bp = bp+1
         orders (bp) = "a"c
         Skeys (bp) = i
         ap = ap+1
         orders (ap) = "a"c
         Rkeys (ap) = j
      }
   }
   bp = bp+1
   Skeys (bp) = 0
   ap = ap+1
   Rkeys (ap) = 0

   ### sort the two input relations

   Rfd = create ("temp1"s,READWRITE)
   if (Rfd == ERR)  {
      call cant ("temp1"s)
      stop
   }
   Sfd = create ("temp2"s,READWRITE)
   if (Sfd == ERR)  {
      call cant ("temp2"s)
      stop
   }
   call sort (Rrd, Rkeys, orders, STDIN, Rfd)
   call sort (Srd, Skeys, orders, STDIN2, Sfd)

  ### Do the division operation and put out the new relation

   call save_rd (Trd, STDOUT)

   if (isatty (STDOUT) == YES)
      call print_header (Trd, STDOUT)

   if (rewind (Rfd) ~= OK) {
      call print (STDOUT, "Couldn't rewind R*n"s)
      stop
   }
   if (rewind (Sfd) ~= OK) {
      call print (STDOUT, "Couldn't rewind S*n"s)
      stop
   }

   i = get_row (Srd, Sfd, Srow)
   if (i == ERR) {
      call print (STDOUT, "Error on S*n"s)
      stop
   }

   for ( i = 1; i <= MAXLINE; i += 1)
      garbage ( i) = 0

   if (i == EOF) {

      # the divisor is null; output all rows in the dividend

      while ( get_row (Rrd, Rfd, Rrow) ~= EOF) {

         # project Rrow onto Trd
         for ( i = FIRSTRF (Rrd); ISLASTRF (Rrd, i);
                                    i = NEXTRF (Rrd, i)) {
            j = find_field ( Trd, RFNAME (Rrd, i))
            if ( j ~= 0) {
               call get_data (Rrd, i, Rrow, dest)
               call put_data (Trd, j, Trow, dest)
            } # end if
         } # end for

         call put_row (Trd, STDOUT, Trow)
      } # end while
   } # end if

   else {

      # the divisor is not null

      for ( i = FIRSTRF (Trd); ISLASTRF (Trd, i); i = NEXTRF ( Trd, i))
         call put_data (Trd, i, x, garbage)

      rstat = get_row (Rrd, Rfd, Rrow)

      while (rstat ~= EOF) {

         # project Rrow onto Trd
         for ( i = FIRSTRF (Rrd); ISLASTRF (Rrd, i); i = NEXTRF (Rrd, i)) {
            j = find_field ( Trd, RFNAME (Rrd, i))
            if ( j ~= 0) {
               call get_data (Rrd, i, Rrow, dest)
               call put_data (Trd, j, y, dest)
            } # end if
         } # end for


         if ( compare_row (Trd, x, y) ~= 2) {
            # copy y to x
            for ( i = FIRSTRF (Trd); ISLASTRF (Trd, i);
                                       i = NEXTRF (Trd, i)) {
               call get_data (Trd, i, y, dest)
               call put_data (Trd, i, x, dest)
            } # end for
            if (rewind(Sfd) ~= OK) {
               call print (STDOUT, "Couldn't rewind S*n"s)
               stop
            }
            i = get_row (Srd, Sfd, Srow)
            if (i == ERR) {
               call print (STDOUT, "Error on S*n"s)
               stop
            }
         } # end if

         # project Rrow onto Srd
         for ( i = FIRSTRF (Rrd); ISLASTRF (Rrd, i);
                                          i = NEXTRF (Rrd, i)) {
            j = find_field ( Srd, RFNAME (Rrd, i))
            if ( j ~= 0) {
               call get_data (Rrd, i, Rrow, dest)
               call put_data (Srd, j, z, dest)
            } # end if
         } # end for

         comp = compare_row ( Srd, z, Srow)
         select
            when (comp == 1) {
               rstat = get_row (Rrd, Rfd, Rrow)

            } # end when
            when (comp == 2) {
               if (get_row (Srd, Sfd, Srow) == EOF) {
                  call put_row (Trd, STDOUT, x)
                  if (rewind (Sfd) ~= OK) {
                     call print (STDOUT, "Couldn't rewind S*n"s)
                     stop
                  }
                  if (get_row (Srd, Sfd, Srow) == EOF) {
                     call print (STDOUT, "S looks empty*n"s)
                     stop
                  }

                  for ( i = FIRSTRF (Trd); ISLASTRF (Trd, i);
                                          i = NEXTRF (Trd, i)) {
                     call get_data (Trd, i, x, dest)
                     call put_data (Trd, i, y, dest)
                  } # end for
                  while ( compare_row (Trd, x, y) == 2) {
                     rstat = get_row (Rrd, Rfd, Rrow)

                     if (rstat ~= EOF)  {

                        # project Rrow onto Trd
                        for ( i = FIRSTRF (Rrd); ISLASTRF (Rrd, i);
                                                i = NEXTRF (Rrd, i)) {
                           j = find_field ( Trd, RFNAME (Rrd, i))
                           if ( j ~= 0) {
                              call get_data (Rrd, i, Rrow, dest)
                              call put_data (Trd, j, y, dest)
                           } # end if (j ~= 0)
                        } # end for

                     }
                     else  # rstat == EOF
                        for ( i = FIRSTRF (Trd); ISLASTRF (Trd, i);
                                                   i = NEXTRF ( Trd, i))
                           call put_data (Trd, i, y, garbage)
                  } # end while
               } # end if (get_row (Srd, Sfd, Srow) == EOF)
               else
                  rstat = get_row (Rrd, Rfd, Rrow)

            } # end when (comp == 2)
            when (comp == 3) {
               for ( i = FIRSTRF (Trd); ISLASTRF (Trd, i);
                                       i = NEXTRF (Trd, i)) {
                  call get_data (Trd, i, x, dest)
                  call put_data (Trd, i, y, dest)
               } # end for
               while (compare_row (Trd, x, y) == 2) {
                  rstat = get_row (Rrd, Rfd, Rrow)
                  if (rstat ~= EOF) {

                     # project Rrow onto Trd
                     for ( i = FIRSTRF (Rrd); ISLASTRF (Rrd, i);
                                             i = NEXTRF (Rrd, i)) {
                        j = find_field ( Trd, RFNAME (Rrd, i))
                        if ( j ~= 0) {
                           call get_data (Rrd, i, Rrow, dest)
                           call put_data (Trd, j, y, dest)
                        } # end if
                     } # end for
                  } # end if

                  else {
                     for ( i = FIRSTRF (Trd); ISLASTRF (Trd, i); 2
                                 i = NEXTRF ( Trd, i))
                        call put_data (Trd, i, y, garbage)
                  } # end else

               } # end while
            } # end when
            ifany
               ;
            else
               ;
      } # end while (rstat ~= EOF)
   } # end else

   if (isatty (STDOUT) == YES)
      call print_trailer (Trd, STDOUT)

   call close (Rfd)
   call close (Sfd)

   stop

   end

   include "rdb_sort.r.i"
   include "rdb_sub.r.i"
