Row HistoryTable::get(Dir dir) { void* p; Mmoffset offset; do { offset = dir == NEXT ? next() : prev(); if (offset == 0) return Eof; p = theDB()->mmf->adr(offset - sizeof(int)); } while (*(int*) p != tblnum); Record r1; Commit* commit = (Commit*) *iter; r1.addval(SuDate::parse(ctime(&commit->t))); r1.addval(dir == NEXT ? 0 <= ic && ic < commit->ncreates ? "create" : "delete" : 0 <= id && id < commit->ndeletes ? "delete" : "create"); Record r2(theDB()->mmf, offset); static Record emptyrec; return Row(lisp(emptyrec, r1, emptyrec, r2)); }
// FIXME: Made non-ref in the hope that it would work better. void lp(ASTNode node) { cout << lisp(node) << endl; }
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; } }
Header Project::header() { return strategy == COPY ? source->header().project(flds) : Header(lisp(Fields(), flds), flds); }
Header HistoryTable::header() { return Header(lisp(Fields(), lisp(gcstring("_date"), gcstring("_action")), Fields(), theDB()->get_fields(table)), columns()); }
Indexes HistoryTable::keys() { return lisp(lisp(gcstring("_date"))); }