This is the main table parsing function. We go through all of the data pages linked to the table, separate each data page to rows(records) and parse each record. :return defaultdict(list) with the parsed data -- table[column][row_index]
(self)
| 218 | return parsed_table |
| 219 | |
| 220 | def parse(self): |
| 221 | """ |
| 222 | This is the main table parsing function. We go through all of the data pages linked to the table, separate each |
| 223 | data page to rows(records) and parse each record. |
| 224 | :return defaultdict(list) with the parsed data -- table[column][row_index] |
| 225 | """ |
| 226 | if not self.table.linked_pages: |
| 227 | return self.create_empty_table() |
| 228 | for data_chunk in self.table.linked_pages: |
| 229 | original_data = data_chunk |
| 230 | parsed_data = parse_data_page_header(original_data, version=self.version) |
| 231 | |
| 232 | last_offset = None |
| 233 | for rec_offset in parsed_data.record_offsets: |
| 234 | # Deleted row - Just skip it |
| 235 | if rec_offset & 0x8000: |
| 236 | last_offset = rec_offset & 0xfff |
| 237 | continue |
| 238 | # Overflow page |
| 239 | if rec_offset & 0x4000: |
| 240 | # overflow ptr is 4 bits flags, 12 bits ptr |
| 241 | rec_ptr_offset = rec_offset & 0xfff |
| 242 | # update last pointer to pointer without flags |
| 243 | last_offset = rec_ptr_offset |
| 244 | # The ptr is the offset in the current data page. we get a 4 byte record_pointer from that |
| 245 | overflow_rec_ptr = original_data[rec_ptr_offset:rec_ptr_offset + 4] |
| 246 | overflow_rec_ptr = struct.unpack("<I", overflow_rec_ptr)[0] |
| 247 | record = self._get_overflow_record(overflow_rec_ptr) |
| 248 | if record: |
| 249 | self._parse_row(record) |
| 250 | continue |
| 251 | # First record is actually the last one - from offset until the end of the data |
| 252 | if not last_offset: |
| 253 | record = original_data[rec_offset:] |
| 254 | else: |
| 255 | record = original_data[rec_offset:last_offset] |
| 256 | last_offset = rec_offset |
| 257 | if record: |
| 258 | self._parse_row(record) |
| 259 | return self.parsed_table |
| 260 | |
| 261 | def _parse_row(self, record): |
| 262 | """ |
no test coverage detected