Repository navigation
What's new in 3.0.0
Deleted-record recovery rebuilt around what examiners need to trust it, a query builder that
needs no SQL, the values inside BLOBs as columns, formulas of your own, folder scans picked by
your own conditions, scrolling that keeps up with millions of rows, and plain words for what a
database does by itself.
Highlights
- Recovered records you can trust. Every record says what it is - deleted, older version,
inserted again, unreferenced page, index entry - where it was found, how sure the match to
a table is and why. Copies of live rows are left out, even when the bytes fit several
tables; rows on pages nothing references are listed apart (they may be live rows a damaged
or manipulated tree hides). - Query without SQL. Add tables and they join on their links; tick columns; filter with
month bars, value lists, number ranges or any SQLite condition; summarise, label values,
calculate new columns; across the databases of a case, and over recovered rows too. - Fields inside values. Open a BLOB or JSON column (plists, NSKeyedArchiver, protobuf,
JSON) and use its fields - a payment's sender, receiver and amount - as columns in Query
and its exports (also to join other tables), and as columns of their own in Browse
(ƒ sender.name,ƒ amount: sorted, filtered, copied and exported like any column). - Formulas of your own, as new columns. Right-click a column header › Calculate
from…: a formula in Excel-like terms (round(x / 100, 2),x * qty + fee,
upper(left(name, 3)),x if x > 0 else 0,date(x, "ms"),json(x, "to.name"),
any column of the row by name; sizessize(x), durations, date parts and zones,
conversions between date kinds, hashes, base64 / hex / UTF-8, regular expressions,
fields inside JSON, plist, NSKeyedArchiver and protobuf values) or steps (divide,
round, thousands, text edits…),
checked as you type with a live preview on real rows; the result is a new ƒ= column,
sortable and exportable, remembered per table; the stored values never change. - Show as number. Right-click a column header › Show as number: thousands
separators, ÷100 (amounts kept in the smallest unit), ÷1,000, ÷1,000,000, exact for
integers, a badge on the header, the stored value kept in copies and beside the shown
text in exports; remembered per table and column; works on ƒ columns. - Pick the databases of a folder by your own conditions. Open Folder goes in three
steps - the folder, which files (optional conditions on the file name, path in the
folder, folder name, extension or size: is, is not, contains, starts / ends with, matches
*?, at least / at most; all or any of them), then Scan for databases, with a line
saying beforehand what the scan will do. Files that do not match are never opened, so a
scan of a whole users folder for the files named one way reads only those (890,000 files
seen, 1,900 opened, in about a minute). The list fills as databases are found; a stopped
scan keeps them and offers Scan again; Tick shown only, and sort by any column. - Drag the scrollbar anywhere in millions of rows. The rows follow the thumb as it
moves (a 2.5-million-row table: every step of a drag shows the rows at the thumb), the
scrollbar spans the whole table at once (the row count is no longer held back behind
other work on the table), a jump draws about three times faster, and the status line
says 'reading rows' only when a read really keeps the view waiting. - Triggers in plain words. What each trigger does - deletes rows of another table,
deletes its own table's old rows, writes a change log, refuses a change, calls an app
function - above its SQL; per table, which triggers change it; a recovered record says
when its table's rows are deleted or logged by the database itself. - The database as of any commit. Open a WAL database as it was after any of its commits,
beside the live state; the banner says when a checkpoint already copied later commits
into the main file. - A recovery says where it is. The running step - looking for dropped tables,
comparing with the live rows of a table, reading the pages - with how far it is, the
time left in the step and the time elapsed. - The window keeps up while the engine works. A recovery or a row-history scan in
the background no longer makes scrolling or a tab switch stutter: while you click,
type or scroll, the interpreter hands over to the window within a fraction of a
millisecond, and back to full speed for the workers when you only watch. - Search results scroll smoothly. The results list draws only the lines that come
into view (a wheel step on a full window of results took 100-400 ms before); the
data grids paint the plain rows' stripes and grid lines as one image (about a sixth
less work per scroll step). - An illustrated guide. Help › Open the illustrated guide: one page, light and dark,
with diagrams of how a deleted row comes back, where a database keeps traces, what the
states and confidences mean, the tabs, reports and the limits.
Recovery
- A dedicated Recovered Records view: tables overview, records in their table's own columns,
a record panel with dates read as dates, Copy / Open / Row history; recovery runs by itself
after opening a small database. - Recovered: records whose first bytes a freeblock header overwrote (their rowid inferred,
and said, when the page leaves one possibility or one live row agrees in every column but
one; at most medium confidence); records cut by a newer, shorter one (partial,
low confidence); rows written before ALTER TABLE ADD COLUMN; deleted index entries; older
cells between the live cells of a page; overflow chains past a freelist trunk; UTF-16
databases; hot rollback journals. - New states: inserted again (deleted, and the same values are live under another rowid -
the record names it), older version also for a row replaced through its UNIQUE key
(INSERT OR REPLACE). - Fewer false "deleted": a copy of a live row with parts zeroed is a live copy, not an older
version; a record whose rowid was overwritten is matched to its live row through the
table's UNIQUE index, also in tables too large to compare in memory. - Fewer misreadings: a freeblock of a live page is read only as its own table's record;
sqlite_sequence holds only a name and a number; a guessed end with a blob or broken text in
a text or number column is not a record. - Missing row numbers: gaps in a table's rowids, after the last row up to sqlite_sequence,
cross-checked with the recovered records. - Files that look encrypted are said to be so - also those whose header carries another
product's name instead of 'SQLite format 3' (an encrypted database format): an error banner,
the warning count, and 'encrypted' in the Overview instead of 0 tables and 0 rows. - Search with 'Recovered records' recovers for at most search_recover_seconds (5 minutes by
default) per database, shows the pages it is on, keeps its clock running, and says when it
stopped at the limit (the Forensics tab recovers without it). - Recovery is faster on large phone databases (a 15 MB, 176-table one: 139 s to 55 s), with
identical results.
Browse, Search, Timeline, SQL
- Date columns open as dates when their name and values say so (the stored value kept, the
choice remembered); exports add a '(date, UTC)' column beside the stored value. - BLOB pictures as thumbnails in the grid; the BLOB inspector opens a decoded value level by
level. - Search covers recovered records (freeblocks, unallocated space, freed and unreferenced
pages, the rollback journal) when asked, and says what it left out; previews start near the
match. Every result line says what it is - a live row, a WAL version, a recovered record
(with its page and offset, tinted) - and the Kind filter uses the same words. - Fields inside a BLOB / JSON column become new columns of the Browse grid (named ƒ field, remembered per table name,
in their own colour, said in the status line): sort, filter, copy and export them like any
column; the stored value stays untouched. - A recovered record's detail window shows its state, where its bytes are (file, page,
offset in the page, byte offset in the file, length, WAL frame), why it was read so, every
value (copy with a right-click or Ctrl+C, view whole, pretty JSON), and the bytes
themselves in a hex view with the record highlighted; Copy ▾ and Save ▾ give the record as
JSON, CSV, text or its bytes. Recovered records in Forensics and Browse carry a Byte offset
column; reports carry the file path and byte offset of every record. - The Query tab: a column's tooltip shows sample values, a card's menu opens the first rows
of its table, the column list keeps the actions used most (the rest under More ▾). - The navigator marks tables whose rows have older versions (⟲ n) once Forensics counted
them - by itself soon after a database with a WAL or journal opens - and a 'Has history'
chip lists the databases that have them. - Every list's header text sits over its values (left-aligned, right-aligned over numbers).
- Identifying facts whole, everywhere: databases with the same file name are named by the
folders that tell them apart ('History (anu)', 'History (bob)' - never '#2' unless the paths
are identical); the Overview shows each database's full path and whole SHA-256, hover
repeats them, right-click copies the hash or the line, and Export ▾ copies or saves every
database's facts (path, size in bytes, tables, rows, WAL, SHA-256, dates, links, triggers,
warnings) as CSV, JSON or text; the search scope dialog shows each database's path. - Links between databases: the same column of a same-named table in another database (ten
Chrome profiles' meta.key) is a copy of that table, counted as 'the same table in N
databases' and never drawn as a link. - The HTML forensic report reads for analysis: the records table leads with the state,
table, rowid, confidence and a preview; the whole record and its provenance open in the
drawer; the recovery's numbers are words; audit findings' details are lists. - Timeline and column filters draw the busy part of the dates, with the far ones counted at
the ends; 0 and -1 are 'not set', never 1970. - SQL completion for tables, columns, keywords and functions; result columns that hold dates
are shown as dates.
Cases, Overview, Relationships
- A new case lands on the Overview with its largest database active; the date range shown is
the span most date columns share; links between databases show their progress; a Triggers
column per database. - The relationship diagram opens readable; a table's panel lists its triggers.
- A row window opened while the links are still being worked out gets its Related (N)
buttons once they are known; it opens faster (one window fewer for each line). - The Limits window groups every limit by area; Help starts with Getting started.
Fixes
- A date column holding one date in the future (an end time, an expiry) is no longer read
in another format decades away: the reading with most dates in the past and nearest to
now wins (a Core Data end time: 2025-2030, not 1994-1999). - A row window's date says which reading it shows and why ('found for the whole column',
as the Timeline reads it); 'Read as: 1 other ▾' lists what the same number would mean in
another format. - The WAL tab is always there: a database without a -wal file gets a plain statement of
that, why, which databases of the case have one, and how a WAL is read when there is
one (the tab no longer comes and goes, and switching the active database no longer
jumps to the SQL tab). - Forensics: the record panel's buttons are never cut off in a narrow panel; the facts
at the top of the Bytes window and the recovered record window (page, byte offset,
path, state) are selectable and copyable. - The window no longer freezes for seconds while a recovery builds the live index of a
very large table (the issue counter waited on the scan's lock); grids reset on a tab
switch without a layout pass. - Forensics: with recovered records shown the panes no longer resize in a loop (the
records grid redrew without end and the tab felt stuck). - Relationships diagram: Auto-arrange of a large case keeps the cards readable (fitted
whole, every card was drawn empty); Fit still shows everything. - Closing the window with a database open asks first, and says the evidence is checked
once more on closing. - The window comes to the front when the tool starts (it could appear behind the window
it was started from, until clicked). - Row detail: a wide text lost its last letter and a long one its end (a field sized by
character count); values are measured now and a long one wraps whole. - Relationships diagram: Auto-arrange packs the blocks of tables beside a tall one
instead of in rows under it (a third less height on a six-database case). - Clearer counts and names: the navigator has column headings and a database's total
waits for the exact count; empty tables say 0, not ~0; values show SQLite type names
everywhere; Search filters are named like the list's headings; a table card counts
links and tables; the Scope dialog says what each number counts; the Overview and
Timeline say what their figures are; Row History explains where a version was seen. - Many layout fixes at small sizes and high scaling, dark theme contrast (tagged rows, WAL
windows), and wording that says when a list or result was cut off. - Searchable dropdown lists close when another program takes the focus (they no longer float
over it).
Windows builds
- The portable build is the zip of the program folder; there is no self-extracting single
file any more (such files, which unpack a Python runtime into a temporary folder on each
start, are what some virus scanners flag by heuristics). The installer wraps the same
folder. PyInstaller's start-up code is compiled for each release instead of the shared
prebuilt one, and no TLS code is bundled (the program never opens a connection). - The installer and the portable folder carry LICENSE and THIRD-PARTY-NOTICES (the
bundled software and its licenses).
Downloads (Windows 10 / 11, 64-bit)
| File | What it is |
|---|---|
SQLiteGUIAnalyzer-3.0.0-setup.exe |
Installer. Installs for you only (no administrator rights needed) or for all users, adds a Start menu entry and an uninstaller. |
SQLiteGUIAnalyzer-3.0.0-portable.zip |
Portable folder: unzip anywhere (for example a USB drive) and run SQLiteGUIAnalyzer.exe inside it. Nothing is installed. |
SHA256SUMS.txt |
SHA-256 checksums of the files above. |
The builds include Python, Tcl/Tk and Pillow (JPEG and WEBP previews). The program is a plain folder (no self-extracting single file) built with a PyInstaller bootloader compiled for this release. Until the builds are code-signed, Windows SmartScreen may ask for confirmation on the first start (More info, then Run anyway).
To run from source instead you only need Python 3.8 or newer with Tkinter; see the README.
SHA-256
8b4915e122b2fbee27a3d237170bf486441b88e3f243bf4eaa395ae9ea894c68 SQLiteGUIAnalyzer-3.0.0-setup.exe
94655c0269c2a1d1e820c6630930d008cc31428d32577fe404fca4eef511c896 SQLiteGUIAnalyzer-3.0.0-portable.zip
Check a download in PowerShell: Get-FileHash <file> -Algorithm SHA256.