def update(self, transaction_id, release, rollback, key, *columns): data = list(columns) mask = Bits("") mask.build_from_list(data) base_rid = self.table.index.select_index(self.table.key, key)[0] #Commit/Abort if release: #Abort if rollback: #find previous version in log and update it send_query = [transaction_id, ["Update"], (base_rid, data)] datafromLOG = self.logger.find_aborted(send_query) #append the very first, oldest value to the update. next_rid = self.table.db.get_next_rid() data = datafromLOG #self.table.rollback(key) #release all the locks self.table.db.lock_manager.release_write(base_rid, transaction_id) return else: # Try to acquire write_lock LOCK_ACQUIRED = self.table.db.lock_manager.acquire_write( base_rid, transaction_id) if not LOCK_ACQUIRED: #abort this transaction print("Acquire lock fail") return False, False next_rid = self.table.db.get_next_rid() old_value = self.table.get(base_rid, mask) all_old_values = self.table.get(base_rid, Bits('1' * self.table.num_columns)) print("Update", base_rid, key, all_old_values, data) #traceback.print_stack() if transaction_id is not None: send_query = [ transaction_id, ["update", key, data], (all_old_values, data) ] self.logger.first_add(send_query) self.table.put(next_rid, base_rid, key, mask, data) mask = Bits("") mask.build_from_list(columns) _columns = [i for i in columns if not i is None] #print(old_value, _columns, mask.bits, base_rid) count = 0 for i in mask: if i == 1: self.table.index.update_index(i, base_rid, old_value[count], _columns[count]) count += 1 # TODO: Release lock? or release after transcation done if transaction_id is not None: self.logger.finished_add(send_query) return True, True
def create_index(self, table, column_number): zeros = [None] * table.num_columns mask = Bits("") mask.build_from_list(zeros[:column_number] + [1] + zeros[column_number:]) self.tree = OOBTreePy() ks = {} for rid in table.page_directory: r = table.get(rid, mask) ks[rid] = r.columns[0] self.tree.update(ks)
def create_index(self, column_number): if column_number in self.col_btree: return print("Create index", column_number) zeros = [None] * self.table.num_columns mask = Bits("") mask.build_from_list(zeros[:column_number] + [1] + zeros[column_number:]) tree = OOBTreePy() ks = {} for rid in self.table.page_directory: _m = self.table.page_directory[rid] if _m.indirection == 0 or _m.indirection > rid: #print("ADDING INDEX:",rid) r = self.table.get(rid, mask) #ks[rid] = r.columns[0] ks[r[0]] = [rid] tree.update(ks) self.col_btree[column_number] = tree return True
def put(self, rid, base_rid, key, write_mask, cols): new_record = Record(rid, key, Bits('0' * len(cols))) old_locs = None dest = TO_TAIL_PAGE if base_rid is None: dest = TO_BASE_PAGE else: base_record = self.page_directory[base_rid] pre_rid = base_record.get_indirection() new_record.set_indirection(pre_rid) base_record.set_indirection(rid) # Inplace update base record indirection column base_ind_loc = base_record.locations[INDIRECTION_COLUMN] self.columns[INDIRECTION_COLUMN].inplace_update( base_ind_loc[0], base_ind_loc[1], base_record.get_indirection()) base_schema_loc = base_record.locations[SCHEMA_ENCODING_COLUMN] base_record.mask.merge(write_mask) self.columns[SCHEMA_ENCODING_COLUMN].inplace_update( base_schema_loc[0], base_schema_loc[1], base_record.mask) # Merge location data loc_rec = None if not base_rid is None: loc_rec = base_record else: loc_rec = self.page_directory[pre_rid] old_locs = loc_rec.locations # Combine meta cols and data cols meta_and_data = new_record.meta() + cols # b'1111' write_mask.set_meta(15) #print("Writing mask",write_mask.bits) locs = self._write_cols(write_mask, meta_and_data, dest) # Merge old and new locations if dest == TO_TAIL_PAGE: for i in range(len(locs)): if locs[i] is None: locs[i] = old_locs[i] new_record.locations = locs self.page_directory[rid] = new_record
def select(self, key, query_columns): mask = "" for i in query_columns: if i == 1: mask+="1" else: mask+="0" bits_mask = Bits(mask) rid = self.table.key_to_baseRid(key) #print(key, rid) r = self.table.get(rid, bits_mask) return r
def put(self, rid, base_rid, key, write_mask, cols): l = self.num_columns new_record = Record(rid, key, Bits('0' * l)) dest = TO_TAIL_PAGE if base_rid is None: dest = TO_BASE_PAGE else: base_record = self.page_directory[base_rid] pre_rid = base_record.indirection if pre_rid == 0: pre_rid = base_rid new_record.indirection = pre_rid base_record.indirection = rid base_ind_pid = base_record.pids[INDIRECTION_COLUMN] base_offset = base_record.offset self.columns[INDIRECTION_COLUMN].inplace_update( base_ind_pid, base_offset, rid) base_schema_loc = base_record.pids[SCHEMA_ENCODING_COLUMN] base_record.mask.merge(write_mask) self.columns[SCHEMA_ENCODING_COLUMN].inplace_update( base_schema_loc, base_offset, base_record.mask) base_pids = None if not base_rid is None: base_pids = self.page_directory[base_rid].pids if dest == TO_TAIL_PAGE: for i in range(l): if cols[i] is None: _pre_pid = self.page_directory[pre_rid].pids[i + 4] _pre_offset = self.page_directory[pre_rid].offset cols[i] = self.columns[i + 4].read(_pre_pid, _pre_offset) meta_and_data = new_record.meta() + cols write_mask.set_meta(15) locs, offset = self._write_cols(write_mask, meta_and_data, dest, base_pids) new_record.pids = locs new_record.offset = offset self.page_directory[rid] = new_record self.reverse_indirection[rid] = base_rid
def insert(self, transaction_id, release, rollback, *columns): #print("Insert") data = list(columns) next_rid = self.table.db.get_next_rid() #print("Rid",next_rid) if transaction_id is not None: send_query = [transaction_id, ["insert"], (next_rid, data)] self.logger.first_add(send_query) self.table.put(next_rid, None, data[self.table.key], Bits('1' * len(data)), data) for col in range(self.table.num_columns): self.table.index.add_to_index(col, next_rid, data[col]) if transaction_id is not None: self.logger.finished_add(send_query) return True
def sum(self, start_range, end_range, aggregate_column_index): _m = [0]*self.table.num_columns _m[aggregate_column_index] = 1 mask = "" for i in _m: if i == 1: mask += "1" else: mask += "0" bits_mask = Bits(mask) res = 0 for i in range(start_range,end_range+1): rid = self.table.key_to_baseRid(i) if rid is None: continue r = self.table.get(rid, bits_mask) res += r.columns[0] return res
def delete(self, transaction_id, release, rollback, key): #need to get values of the record before we delete it base_rid = self.table.index.select_index(self.table.key, key)[0] old_value = self.table.get(base_rid, Bits('1' * self.table.num_columns)) if transaction_id is not None: send_query = [transaction_id, ["delete", key], (old_value)] self.logger.first_add(send_query) rids = self.table.index.select_index(self.table.key, key) # Try to acquire LOCK # Try to acquire write_lock for i in rids: self.table.index.remove_from_index(self.table.key, i, key) self.table.delete(i) if transaction_id is not None: self.logger.finished_add(send_query) return True
def sum(self, start_range, end_range, aggregate_column_index): _m = [0] * self.table.num_columns _m[aggregate_column_index] = 1 mask = "" for i in _m: if i == 1: mask += "1" else: mask += "0" bits_mask = Bits(mask) rids = self.table.index.col_btree[self.table.key].values( start_range, end_range) if len(rids) <= 0: return False res = 0 for i in rids: r = self.table.get(i[0], bits_mask) res += r[0] return res
def select(self, transaction_id, release, rollback, key, column, query_columns): # if transaction_id is not None: # send_query = [transaction_id, ["select", key, column, query_columns], None] # self.logger.first_add(send_query) found_records = Wrapper() mask = "" for i in query_columns: if i == 1: mask += "1" else: mask += "0" bits_mask = Bits(mask) rids = self.table.index.select_index(column, key) #try to acquire read_lock for r in rids: LOCK_ACQUIRED = self.table.db.lock_manager.acquire_read( r, transaction_id) #we need tid here if not LOCK_ACQUIRED: return False, False if len(rids) <= 0: return False, False print("Select", rids) for r in rids: found_records.additem(QueryResult(self.table.get(r, bits_mask))) # if transaction_id is not None: # self.logger.finished_add(send_query) # return found_records, False return found_records, False
def delete(self, rid): m = Bits("1" * self.num_columns) self.put(0, rid, 0, m, [0] * self.num_columns)
from src.table import Table from src.bits import Bits table = Table("test", 5, 0) table.put(1, None, 0, Bits('11111'), [1, 2, 3, 4, 5]) table.put(2, 1, 0, Bits('11011'), [14, 15, None, 12, 13]) table.put(3, 1, 0, Bits('10000'), [99, None, 199, None, None]) r = table.get(1, Bits('11111')) print(r)
from src.query import Query from src.table import Table from src.bits import Bits table = Table("test", 5, 0) query = Query(table) # record1 = [1, 90, 0, 0, 0] # record2 = [2, 91, 0, 0, 0] # record3 = [3, 92, 0, 0, 0] query.insert(1, 90, 0, 0, 0) query.insert(2, 91, 0, 0, 0) query.insert(3, 92, 0, 0, 0) r1 = table.get(1, Bits('11111')) r2 = table.get(2, Bits('11111')) r3 = table.get(3, Bits('11111')) print(r1) print(r2) print(r3) query.delete(1) query.delete(2) print("record3's LID: ", table.key_lid[3])
def update(self, key, *columns): data = list(columns) mask = Bits("") mask.build_from_list(columns) base_rid = self.table.key_to_baseRid(key) self.table.put(self.table.get_next_rid(), base_rid, key, mask, data)
def insert(self, *columns): data = list(columns) self.table.put(self.table.get_next_rid(), None, data[self.table.key], Bits('11111'), data)