# rdnat --- perform the natural join of two relations include "rdb_def.r.i" define (DB,#) relation_des rd1 (RDSIZE), rd2 (RDSIZE), rd3 (RDSIZE), rd4 (RDSIZE) integer errs, ap, lastap, i1, i2, i, j, k, l, pos2, put integer match1 (MAXFIELDS), match2 (MAXFIELDS) integer out1 (MAXFIELDS), out2 (MAXFIELDS) integer row1 (RDATASIZE), row2 (RDATASIZE) integer row3 (RDATASIZE), row4 (RDATASIZE), buf (RDATASIZE) integer buf1 (RDATASIZE), buf2 (RDATASIZE) integer rpn (RPNSIZE), cbuf (RDATASIZE) integer getarg, load_rd, get_row, isatty, eval, parse, add_field_to_rd integer get_name, find_field, find_qual_field, compare_field character arg (MAXARG), oldname (MAXARG), newname (RFNAMESIZE) file_mark m file_mark markf ### Load the descriptors for the original relations if (load_rd (rd1, STDIN) ~= OK) call error ("Cannot load input relation 1"p) if (load_rd (rd2, STDIN2) ~= OK) call error ("Cannot load input relation 2"p) ### create the result relation descriptor in rd3 call move$ (rd1, rd3, RDLEN (rd1)) # determine join fields and build output relation descriptor ap = 0 for (i = FIRSTRF (rd2) ; ISLASTRF (rd2, i) ; i = NEXTRF(rd2, i)) { j = find_field (rd3, RFNAME (rd2,i) ) if (j == 0) { pos2 = add_field_to_rd (rd3, RFTYPE (rd2, i), RFLEN (rd2, i), RFNAME (rd2, i)) if (pos2 == 0) call error ("Resulting relation has too many domains"p) } else { ap = ap + 1 match1 (ap) = j match2 (ap) = i } } lastap = ap ### Do the join operation and put out the new relation call save_rd (rd3, STDOUT) if (isatty (STDOUT) == YES) call print_header (rd3, STDOUT) m = markf (STDIN2) while (get_row (rd1, STDIN, row1 ) ~= EOF) { j = FIRSTRF (rd3) for (i = FIRSTRF(rd1); ISLASTRF(rd1, i); i = NEXTRF(rd1,i)) { call get_data (rd1, i, row1, buf1) call put_data (rd3, j, row3, buf1) j = NEXTRF(rd3, j) } call seekf (m, STDIN2) while (get_row (rd2, STDIN2, row2) ~= EOF) { put = 1 for (ap = 1; ap <= lastap; ap += 1) { call get_data (rd1, match1 (ap), row1, buf1) call get_data (rd2, match2 (ap), row2, buf2) if (compare_field (RFTYPE (rd1, match1(ap)), buf1, buf2) ~= 2) { put = 0 } } if (put == 1) { for (i = j; ISLASTRF(rd3, i); i = NEXTRF(rd3, i)) { k = find_field (rd2, RFNAME (rd3, i)) if (k == 0) call print (STDOUT, "field not found*n"s) else { call get_data (rd2, k, row2, buf2) call put_data (rd3, i, row3, buf2) } } call put_row (rd3, STDOUT, row3) } } } if (isatty (STDOUT) == YES) call print_trailer (rd3, STDOUT) stop end # get_name --- parse a field name specification integer function get_name (arg, oldname, newname) character arg (ARB), oldname (MAXARG), newname (RFNAMESIZE) integer i, j newname (1) = EOS oldname (1) = EOS if (~ IS_LETTER (arg (1))) return (ERR) oldname (1) = arg (1) for (i = 2; arg (i) ~= EOS && arg (i) ~= '='c && i < MAXARG; i += 1) { if (~ IS_LETTER (arg (i)) && ~ IS_DIGIT (arg (i)) && arg (i) ~= '_'c && arg (i) ~= '.'c) { oldname (1) = EOS return (ERR) } oldname (i) = arg (i) } oldname (i) = EOS if (arg (i) == EOS) { for (i = 1; arg (i) ~= '.'c && arg (i) ~= EOS && i < RFNAMESIZE; i += 1) newname (i) = arg (i) newname (i) = EOS } else if (arg (i) == '='c) { i += 1 if (~ IS_LETTER (arg (i))) return (ERR) newname (1) = arg (i) for ({j = 2; i += 1}; arg (i) ~= EOS && j < RFNAMESIZE; {j += 1; i += 1}) { if (~ IS_LETTER (arg (i)) && ~ IS_DIGIT (arg (i)) && arg (i) ~= '_'c) { newname (1) = EOS return (ERR) } newname (j) = arg (i) } newname (j) = EOS if (arg (i) ~= EOS) return (ERR) } else return (ERR) DB call print (ERROUT, "in get_name: *s *s *s*n"s, arg, oldname, newname) return (OK) end include "rdb_sub.r.i"