bool Compatible::isdup(const Row& row) { if (disjoint != "") return false; // test if row is in source2 if (nil(hdr1)) { hdr1 = source->header(); hdr2 = source2->header(); } Record key = row_to_key(hdr1, row, ki); source2->select(ki, key); Row row2 = source2->get(NEXT); if (row2 == Eof) return false; return equal(row, row2); }
Row Project::get(Dir dir) { static Record emptyrec; if (first) { first = false; src_hdr = source->header(); proj_hdr = src_hdr.project(flds); if (strategy == LOOKUP) { if (idx) idx->free(); idx = new VVtree(td = new TempDest); indexed = false; } } if (strategy == COPY) { return source->get(dir); } else if (strategy == SEQUENTIAL) { if (dir == NEXT) { // output the first of each group // i.e. skip over rows the same as previous output Row row; do if (Eof == (row = source->get(NEXT))) return Eof; while (! rewound && equal(proj_hdr, row, currow)); rewound = false; prevrow = currow; currow = row; // output the first row of a new group return Row(lisp(emptyrec, row_to_key(src_hdr, row, flds))); } else // dir == PREV { // output the last of each group // i.e. output when *next* record is different // (to get the same records as NEXT) if (rewound) prevrow = source->get(PREV); rewound = false; Row row; do { if (Eof == (row = prevrow)) return Eof; prevrow = source->get(PREV); } while (equal(proj_hdr, row, prevrow)); // output the last row of a group currow = row; return Row(lisp(emptyrec, row_to_key(src_hdr, row, flds))); } } else { verify(strategy == LOOKUP); if (rewound) { rewound = false; if (dir == PREV && ! indexed) { // pre-build the index Row row; while (Eof != (row = source->get(NEXT))) { Record key = row_to_key(src_hdr, row, flds); Vdata data(row.data); for (Lisp<Record> rs = row.data; ! nil(rs); ++rs) td->addref(rs->ptr()); // insert will only succeed on first of dups idx->insert(VVslot(key, &data)); } source->rewind(); indexed = true; } } Row row; while (Eof != (row = source->get(dir))) { Record key = row_to_key(src_hdr, row, flds); VVtree::iterator iter = idx->find(key); if (iter == idx->end()) { for (Lisp<Record> rs = row.data; ! nil(rs); ++rs) td->addref(rs->ptr()); Vdata data(row.data); verify(idx->insert(VVslot(key, &data))); return Row(lisp(emptyrec, key)); } else { Vdata* d = iter->data; Records rs; for (int i = d->n - 1; i >= 0; --i) rs.push(Record::from_int(d->r[i], theDB()->mmf)); Row irow(rs); if (row == irow) return Row(lisp(emptyrec, key)); } } if (dir == NEXT) indexed = true; return Eof; } }