DBRepair development

HOW THE HELL do you kill it? It won’t stop

When it doubt .. uninstall and reboot

One other quick thing regarding Plex Media Server data: On macOS, it’s spread across a few directories:
~/Library/Application Support/Plex Media Server;
~/Library/Caches/PlexMediaServer; and,
~/Library/Logs/Plex Media Server

So, if you want to fully move your PMS data, you’ll need to account for these as well.

Thanks. I found a way to kill it (uninstall + reboot)
I will make a bunch of symlinks (UGLY HACK)

I never knew Mac was this ugly an implementation.

For what it’s worth, DBRepair.sh uses AppleScript to start and stop the server, run via the osascript utility. For example:
osascript -e 'tell app "Plex Media Server" to quit

Here are the helper functions from the script:

# Mac Helper Functions
startMacPMS() { TMPDIR=/tmp osascript -e 'tell app "Plex Media Server" to launch'; sleep 2; IsRunning && sayStarted; }
stopMacPMS() { osascript -e 'tell app "Plex Media Server" to quit'; sleep 2; IsRunning || sayStopped; }
sayStarted() { [ $HapticOkay -eq 1 ] && osascript -e 'say "started"'; }
sayStopped() { [ $HapticOkay -eq 1 ] && osascript -e 'say "Its stopped"'; }

Yes, Thanks I have all that info. They’re already integrated into the new C code.

Launching out to a shell command is the one bit of shell needed for all the hosts.

If you want to see it. (it looks a lot like the existing)

  // --- Apple Mac ---
  HaveMacPMS = false;
  setString(HomePath, "%s", getenv("HOME"));

  // Is PMS installed (two possibilities)
  if (isDir("/Applications/Plex Media Server.app") ){
    HaveMacPMS = true;
    setString(H.HostType, "Mac");
    H.PkgDir = "/Applications/Plex Media Server.app";
    H.PlexSQLite = "%s/Contents/MacOS/Plex SQLite", H.PkgDir;

  } else if (isDir("~/Applications/Plex Media Server.app")) {
    HaveMacPMS = true;
    setString(H.HostType, "Mac");
    H.PkgDir = "~/Applications/Plex Media Server.app";
    H.PlexSQLite = "%s/Contents/MacOS/Plex SQLite", H.PkgDir;
  }

  if (HaveMacPMS) {
    setString(MacDataPath, "%s/Library/Application Support/Plex Media Server", HomeDir);

    // Where the data lives
    if (HomeDir) {
      setString(H.AppSuppDir, "%s/Library/Application Support", HomeDir);
      // macOS specific: Cache is in ~/Library/Caches, not App Support
      setString(H.CacheDir, "%s/Library/Caches/PlexMediaServer/PhotoTranscoder", HomeDir);
    }

    // Build sub-paths
    setString(H.DbDir, "%s/Plex Media Server/Plug-in Support/Databases", H.AppSuppDir);
    setString(H.LogFile, "%s/DBRepair.log", H.DbDir);

    // Standard temp paths
    setString(H.TmpDir, "/tmp");
    setString(H.SysTmp, "/tmp");

    // MacOS Specifics
    setString(H.Pidof, "pgrep");
    H.RootRequired = false;

    // Service Control
    // Note: Since these are shell functions in your script, we will
    // call the internal startMacPMS / stopMacPMS C functions later.
    H.HaveStartStop = true;
    setString(H.StartCommand, "startMacPMS");
    setString(H.StopCommand, "stopMacPMS");

    return true;
  }

Looks like you’re making steady progress. I look forward to the results!

I have approx 3500 lines of C. (more comments and clearly written)

Pssss.

Don’t tell anyone, Frankie lives. :smiling_face_with_horns:

chuck@tirol bin % ./DBRepair
SYSTEM: macOS,(Mac)
ENGINE: SQLite v3.53.0
STEEL:  ICU Headers LINKED
[Smoke Test Complete]
Binary Architecture: 64-bit


Select

  1 - 'stop'      - Stop PMS.
  2 - 'automatic' - Check, Repair/Optimize, Reindex, and FTS rebuild in one step.
  3 - 'check'     - Perform integrity check of database and FTS indexes.
  4 - 'vacuum'    - Remove empty space from database without optimizing.
  5 - 'repair'    - Repair/Optimize databases.
  6 - 'reindex'   - Rebuild database indexes.
  7 - 'start'     - Start PMS

  8 - 'import'    - Import watch history from another database independent of Plex. (risky).
  9 - 'replace'   - Replace current databases with newest usable backup copy (interactive).
 10 - 'show'      - Show logfile.
 11 - 'status'    - Report status of PMS (run-state and databases).
 12 - 'undo'      - Undo last successful command.

 21 - 'prune'     - Remove old image files from PhotoTranscoder cache & all temp files left by PMS.
 23 - 'deflate'   - Deflate a bloated PMS main database.
 42 - 'ignore'    - Ignore duplicate/constraint errors.

 88 - 'update'    - Check for updates.
 98 - 'quit'      - Quit immediately.  Keep all temporary files.
 99 - 'exit'      - Exit with cleanup options.

Enter command # -or- command name (4 char min) : 10
 
Displaying Session Log: /Users/chuck/Library/Application Support/Plex Media Server/Plug-in Support/Databases/DBRepair.log
------------------------------------------------------------
2026-05-02 03.34.15 - Check   - Check  - FAIL
2026-05-02 03.34.15 - Check   - Check  - FAIL
2026-05-02 03.34.15 - Check   - PASS
2026-05-02 03.34.15 - Check   - FTS Check - No FTS4 tables
2026-05-02 03.34.15 - Check   - FTS Check - PASS
2026-05-02 03.34.42 - Exit    - Delete temp files.
2026-05-02 03.34.42 - Session end. Sat May  2 03:34:42 2026
2026-05-02 03.34.42 - ============================================================
------------------------------------------------------------

and

Enter command # -or- command name (4 char min) : 99
 
Ok to remove temporary databases/workfiles for this session? (y/N): y
Deleting all temporary work files.
chuck@tirol bin % file DBRepair 
DBRepair: Mach-O 64-bit executable arm64
chuck@tirol bin %  ll -h DBRepair 
-rwxr-xr-x  1 chuck  staff    35M May  1 19:29 DBRepair
chuck@tirol bin % 

Static compiled, no external dependencies (other than the databases)

May I have some feedback please on how this this looking and performing ?

Input DB is badly damaged and fragmented , size = 3 GB

This is what I’m proposing for the the new DBRepair to look like.
Some cosmetic work needs to be done.

It will show all work being performed

chuck@tirol Databases % ~/dbrepair/build/pc-darwin-arm64-release/bin/DBRepair stop check repair exit
SYSTEM: macOS,(MacOS)
ENGINE: SQLite v3.53.0
STEEL:  ICU Headers LINKED
[Smoke Test Complete]
Binary Architecture: 64-bit

[2026-05-05 11.28.44]  
[2026-05-05 11.28.44] PMS already stopped.
[2026-05-05 11.28.44]  
[2026-05-05 11.28.44] Checking the PMS databases...
[2026-05-05 11.29.37] Check complete. PMS main database is OK.
[2026-05-05 11.29.37] Check complete. PMS blobs database is OK.
[2026-05-05 11.29.37] 
[2026-05-05 11.29.37] Checking FTS (Full-Text Search) indexes...
[2026-05-05 11.29.37]   FTS index 'spellfix_metadata_titles' (main) - OK
[2026-05-05 11.29.37]   FTS index 'spellfix_tag_titles' (main) - OK
[2026-05-05 11.29.37]   FTS index 'fts4_metadata_titles' (main) - OK
[2026-05-05 11.29.37]   FTS index 'fts4_tag_titles' (main) - OK
[2026-05-05 11.29.37]   FTS index 'fts4_metadata_titles_icu' (main) - OK
[2026-05-05 11.29.37]   FTS index 'fts4_tag_titles_icu' (main) - OK
[2026-05-05 11.29.37]   FTS index 'spellfix_metadata_titles' (blobs) - OK
[2026-05-05 11.29.37]   FTS index 'spellfix_tag_titles' (blobs) - OK
[2026-05-05 11.29.37]   FTS index 'fts4_metadata_titles' (blobs) - OK
[2026-05-05 11.29.37]   FTS index 'fts4_tag_titles' (blobs) - OK
[2026-05-05 11.29.37]   FTS index 'fts4_metadata_titles_icu' (blobs) - OK
[2026-05-05 11.29.37]   FTS index 'fts4_tag_titles_icu' (blobs) - OK
[2026-05-05 11.29.37]  
[2026-05-05 11.29.37] Starting Logical Reconstruction (Resequenced Data Pump)...
[2026-05-05 11.29.37] Backup current databases with '-BACKUP-2026-05-05_11.29.37' timestamp.
[2026-05-05 11.29.37]   Phase 1: Recreating table schemas...
[2026-05-05 11.29.37]   Phase 2: Optimizing and copying data rows...
[2026-05-05 11.29.43]   Phase 3: Building indexes and search data...
[2026-05-05 11.30.34]   Phase 4: Verifying schema...
[2026-05-05 11.31.20] Reconstruction complete. Finalizing file swap...
[2026-05-05 11.31.20] Repair complete. Status: SALVAGED (Schema restored).
[2026-05-05 11.31.20]  
[2026-05-05 11.31.20] Deleting temporary work files.
chuck@tirol Databases % 

Current design thinking:

  1. When you call automatic, it will resequenced the DB (like the shell did) only if the DB is > 2% fragmented

  2. Reindex is redundant after repair. I do that as part of the reconstruction automatically. Does the Reindex command need stay ?

  3. Is it performing fast enough ? (I forget the shell version speed)

Please don’t hesitate if I’ve gone overboard or completely missed the mark in any way.

Does anyone have an old bloated DB I can get a copy of ?

I’m working on the Deflate code.

I think it’s right but the DB I have has other issues and can’t deflate properly

I’d like to compare against another DB

I just realized there exists a bug in DBRepair.sh for MacOS platforms.

  1. Older implementations used /Applications for Plex
  2. New implementations use $HOME/Applications

DBRepair did not understand this.

Attached please find DBRepair-1.16.00.tar to test please.

If it works on everyone’s Mac, I’ll release it. It works on mine.

DBRepair-1.16.00.tar (91 KB)