mirror of
https://github.com/ChuckPa/PlexDBRepair.git
synced 2026-02-04 06:22:59 -05:00
feat: Add FTS4 index integrity check and rebuild functionality
Add detection and automatic repair for FTS4 (Full-Text Search) index corruption, which can occur even when PRAGMA integrity_check passes. New functions: - CheckFTS(): Validates FTS4 index integrity using SQLite's integrity-check command - DoFTSRebuild(): Rebuilds corrupted FTS4 indexes using SQLite's rebuild command Enhanced existing commands: - 'check' (option 3): Now includes FTS integrity checking - 'reindex' (option 6): Now checks FTS indexes and rebuilds if corruption detected - 'automatic' (option 2): Checks FTS after repair/reindex and automatically rebuilds if damaged Refactored FTS table query into reusable FTS_TABLE_QUERY constant for maintainability. Fixes: https://github.com/ChuckPa/DBRepair/issues/269
This commit is contained in:
290
DBRepair.sh
290
DBRepair.sh
@@ -62,6 +62,17 @@ STATPERMS="%a"
|
||||
# On all hosts except QNAP
|
||||
DFFLAGS="-m"
|
||||
|
||||
# FTS4 virtual table query - excludes shadow tables (_content, _segments, etc.)
|
||||
FTS_TABLE_QUERY="SELECT name FROM sqlite_master"
|
||||
FTS_TABLE_QUERY="$FTS_TABLE_QUERY WHERE type='table'"
|
||||
FTS_TABLE_QUERY="$FTS_TABLE_QUERY AND sql LIKE '%fts4%'"
|
||||
FTS_TABLE_QUERY="$FTS_TABLE_QUERY AND name NOT LIKE '%_content'"
|
||||
FTS_TABLE_QUERY="$FTS_TABLE_QUERY AND name NOT LIKE '%_segments'"
|
||||
FTS_TABLE_QUERY="$FTS_TABLE_QUERY AND name NOT LIKE '%_segdir'"
|
||||
FTS_TABLE_QUERY="$FTS_TABLE_QUERY AND name NOT LIKE '%_stat'"
|
||||
FTS_TABLE_QUERY="$FTS_TABLE_QUERY AND name NOT LIKE '%_docsize'"
|
||||
FTS_TABLE_QUERY="$FTS_TABLE_QUERY ORDER BY name;"
|
||||
|
||||
# If LC_ALL is null, default to C
|
||||
[ "$LC_ALL" = "" ] && export LC_ALL=C
|
||||
|
||||
@@ -158,6 +169,83 @@ CheckDatabases() {
|
||||
return $Damaged
|
||||
}
|
||||
|
||||
# Global flags for FTS status (separate from main DB)
|
||||
FTSDamaged=0
|
||||
CheckedFTS=0
|
||||
|
||||
# Check FTS (Full-Text Search) index integrity
|
||||
CheckFTS() {
|
||||
|
||||
# Arg1 = calling function name for logging
|
||||
|
||||
FTSDamaged=0
|
||||
local Caller="${1:-Check}"
|
||||
local FTSFail=0
|
||||
|
||||
Output "Checking FTS (Full-Text Search) indexes"
|
||||
|
||||
# Get list of FTS4 virtual tables (exclude shadow tables)
|
||||
FTSTables="$("$PLEX_SQLITE" $CPPL.db "$FTS_TABLE_QUERY" 2>&1)"
|
||||
|
||||
if [ -z "$FTSTables" ]; then
|
||||
Output "No FTS4 tables found in main database."
|
||||
WriteLog "$Caller - FTS Check - No FTS4 tables"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check each FTS table
|
||||
for Table in $FTSTables
|
||||
do
|
||||
Result="$("$PLEX_SQLITE" $CPPL.db "INSERT INTO $Table($Table) VALUES('integrity-check');" 2>&1)"
|
||||
ExitCode=$?
|
||||
|
||||
if [ $ExitCode -eq 0 ] && [ -z "$Result" ]; then
|
||||
Output " FTS index '$Table' - OK"
|
||||
WriteLog "$Caller - FTS Check: $Table - PASS"
|
||||
else
|
||||
Output " FTS index '$Table' - DAMAGED"
|
||||
Output " Error: $Result"
|
||||
WriteLog "$Caller - FTS Check: $Table - FAIL ($Result)"
|
||||
FTSFail=1
|
||||
fi
|
||||
done
|
||||
|
||||
# Check blobs database FTS tables
|
||||
FTSTablesBlobs="$("$PLEX_SQLITE" $CPPL.blobs.db "$FTS_TABLE_QUERY" 2>&1)"
|
||||
|
||||
if [ -n "$FTSTablesBlobs" ]; then
|
||||
for Table in $FTSTablesBlobs
|
||||
do
|
||||
Result="$("$PLEX_SQLITE" $CPPL.blobs.db "INSERT INTO $Table($Table) VALUES('integrity-check');" 2>&1)"
|
||||
ExitCode=$?
|
||||
|
||||
if [ $ExitCode -eq 0 ] && [ -z "$Result" ]; then
|
||||
Output " FTS index '$Table' (blobs) - OK"
|
||||
WriteLog "$Caller - FTS Check (blobs): $Table - PASS"
|
||||
else
|
||||
Output " FTS index '$Table' (blobs) - DAMAGED"
|
||||
Output " Error: $Result"
|
||||
WriteLog "$Caller - FTS Check (blobs): $Table - FAIL ($Result)"
|
||||
FTSFail=1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
CheckedFTS=1
|
||||
if [ $FTSFail -eq 0 ]; then
|
||||
Output "FTS integrity check complete. All FTS indexes OK."
|
||||
WriteLog "$Caller - FTS Check - PASS"
|
||||
FTSDamaged=0
|
||||
else
|
||||
Output "FTS integrity check complete. One or more FTS indexes are DAMAGED."
|
||||
Output "Use 'reindex' command (option 6) or 'automatic' (option 2) to rebuild."
|
||||
WriteLog "$Caller - FTS Check - FAIL"
|
||||
FTSDamaged=1
|
||||
fi
|
||||
|
||||
return $FTSFail
|
||||
}
|
||||
|
||||
# Return list of database backup dates for consideration in replace action
|
||||
GetDates(){
|
||||
|
||||
@@ -932,6 +1020,151 @@ DoIndex() {
|
||||
|
||||
}
|
||||
|
||||
##### FTS REBUILD
|
||||
DoFTSRebuild() {
|
||||
|
||||
# Clear flags
|
||||
Damaged=0
|
||||
Fail=0
|
||||
|
||||
# Check databases before rebuilding FTS if not previously checked
|
||||
if ! CheckDatabases "FTSRbld" ; then
|
||||
Damaged=1
|
||||
CheckedDB=1
|
||||
Fail=1
|
||||
[ $IgnoreErrors -eq 1 ] && Fail=0
|
||||
fi
|
||||
|
||||
# If damaged, warn but allow continue (FTS corruption often passes integrity_check)
|
||||
if [ $Damaged -eq 1 ] && [ $IgnoreErrors -eq 0 ]; then
|
||||
Output "WARNING: Database integrity check failed."
|
||||
Output "FTS rebuild may still help if the corruption is isolated to FTS indexes."
|
||||
if ! ConfirmYesNo "Continue with FTS rebuild anyway? "; then
|
||||
Output "FTS rebuild cancelled."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Make backup
|
||||
Output "Backing up databases"
|
||||
MakeBackups "FTSRbld"
|
||||
Result=$?
|
||||
[ $IgnoreErrors -eq 1 ] && Result=0
|
||||
|
||||
if [ $Result -eq 0 ]; then
|
||||
WriteLog "FTSRbld - MakeBackup - PASS"
|
||||
else
|
||||
Output "Error making backups. Cannot continue."
|
||||
WriteLog "FTSRbld - MakeBackup - FAIL ($Result)"
|
||||
Fail=1
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get list of FTS4 tables (exclude shadow tables)
|
||||
Output "Scanning for FTS4 tables in main database..."
|
||||
|
||||
FTSTables="$("$PLEX_SQLITE" $CPPL.db "$FTS_TABLE_QUERY" 2>&1)"
|
||||
Result=$?
|
||||
|
||||
if ! SQLiteOK $Result; then
|
||||
Output "Error scanning for FTS tables. Error code $Result"
|
||||
WriteLog "FTSRbld - Scan FTS tables - FAIL ($Result)"
|
||||
Fail=1
|
||||
RestoreSaved "$TimeStamp"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# If no FTS tables found, nothing to do
|
||||
if [ -z "$FTSTables" ]; then
|
||||
Output "No FTS4 tables found in database."
|
||||
WriteLog "FTSRbld - No FTS4 tables found"
|
||||
return 0
|
||||
fi
|
||||
|
||||
Output "Found FTS4 tables:"
|
||||
for Table in $FTSTables
|
||||
do
|
||||
Output " - $Table"
|
||||
done
|
||||
Output ""
|
||||
|
||||
# Rebuild each FTS table
|
||||
Output "Rebuilding FTS4 indexes in main database..."
|
||||
for Table in $FTSTables
|
||||
do
|
||||
Output " Rebuilding $Table..."
|
||||
|
||||
"$PLEX_SQLITE" $CPPL.db "INSERT INTO $Table($Table) VALUES('rebuild');" 2>&1
|
||||
Result=$?
|
||||
[ $IgnoreErrors -eq 1 ] && Result=0
|
||||
|
||||
if SQLiteOK $Result; then
|
||||
Output " $Table rebuilt successfully."
|
||||
WriteLog "FTSRbld - Rebuild: $Table - PASS"
|
||||
else
|
||||
Output " $Table rebuild failed. Error code $Result"
|
||||
WriteLog "FTSRbld - Rebuild: $Table - FAIL ($Result)"
|
||||
Fail=1
|
||||
fi
|
||||
done
|
||||
|
||||
# Check blobs database for FTS tables
|
||||
Output ""
|
||||
Output "Scanning for FTS4 tables in blobs database..."
|
||||
|
||||
FTSTablesBlobs="$("$PLEX_SQLITE" $CPPL.blobs.db "$FTS_TABLE_QUERY" 2>&1)"
|
||||
Result=$?
|
||||
|
||||
if ! SQLiteOK $Result; then
|
||||
Output "Error scanning blobs database for FTS tables. Error code $Result"
|
||||
WriteLog "FTSRbld - Scan FTS tables (blobs) - FAIL ($Result)"
|
||||
# Don't fail entirely if blobs scan fails - main DB may be OK
|
||||
elif [ -z "$FTSTablesBlobs" ]; then
|
||||
Output "No FTS4 tables found in blobs database."
|
||||
WriteLog "FTSRbld - No FTS4 tables in blobs database"
|
||||
else
|
||||
Output "Found FTS4 tables in blobs database:"
|
||||
for Table in $FTSTablesBlobs
|
||||
do
|
||||
Output " - $Table"
|
||||
done
|
||||
Output ""
|
||||
|
||||
Output "Rebuilding FTS4 indexes in blobs database..."
|
||||
for Table in $FTSTablesBlobs
|
||||
do
|
||||
Output " Rebuilding $Table..."
|
||||
|
||||
"$PLEX_SQLITE" $CPPL.blobs.db "INSERT INTO $Table($Table) VALUES('rebuild');" 2>&1
|
||||
Result=$?
|
||||
[ $IgnoreErrors -eq 1 ] && Result=0
|
||||
|
||||
if SQLiteOK $Result; then
|
||||
Output " $Table rebuilt successfully."
|
||||
WriteLog "FTSRbld - Rebuild (blobs): $Table - PASS"
|
||||
else
|
||||
Output " $Table rebuild failed. Error code $Result"
|
||||
WriteLog "FTSRbld - Rebuild (blobs): $Table - FAIL ($Result)"
|
||||
Fail=1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
Output ""
|
||||
Output "FTS rebuild complete."
|
||||
|
||||
if [ $Fail -eq 0 ]; then
|
||||
SetLast "FTSRbld" "$TimeStamp"
|
||||
WriteLog "FTSRbld - PASS"
|
||||
else
|
||||
Output "Some FTS tables failed to rebuild. Restoring backup."
|
||||
RestoreSaved "$TimeStamp"
|
||||
WriteLog "FTSRbld - FAIL"
|
||||
fi
|
||||
|
||||
return $Fail
|
||||
}
|
||||
|
||||
##### UNDO
|
||||
DoUndo(){
|
||||
# Confirm there is something to undo
|
||||
@@ -2188,8 +2421,8 @@ do
|
||||
echo ""
|
||||
[ $HaveStartStop -gt 0 ] && echo " 1 - 'stop' - Stop PMS."
|
||||
[ $HaveStartStop -eq 0 ] && echo " 1 - 'stop' - (Not available. Stop manually.)"
|
||||
echo " 2 - 'automatic' - Check, Repair/Optimize, and Reindex Database in one step."
|
||||
echo " 3 - 'check' - Perform integrity check of database."
|
||||
echo " 2 - 'automatic' - Check, Repair/Optimize, Reindex, and FTS rebuild in one step."
|
||||
echo " 3 - 'check' - Perform integrity check of database and FTS indexes."
|
||||
echo " 4 - 'vacuum' - Remove empty space from database without optimizing."
|
||||
echo " 5 - 'repair' - Repair/Optimize databases."
|
||||
echo " 6 - 'reindex' - Rebuild database indexes."
|
||||
@@ -2326,9 +2559,29 @@ do
|
||||
WriteLog "Reindex - PASS"
|
||||
fi
|
||||
|
||||
# Now check FTS indexes and repair if damaged
|
||||
DoUpdateTimestamp
|
||||
Output ""
|
||||
if ! CheckFTS "Auto "; then
|
||||
Output ""
|
||||
Output "FTS indexes are damaged. Attempting automatic FTS rebuild..."
|
||||
WriteLog "Auto - FTS damaged, attempting rebuild"
|
||||
|
||||
if DoFTSRebuild; then
|
||||
WriteLog "Auto - FTS Rebuild - PASS"
|
||||
Output "FTS rebuild successful."
|
||||
else
|
||||
WriteLog "Auto - FTS Rebuild - FAIL"
|
||||
Output "FTS rebuild failed. You may need to run 'reindex' command manually."
|
||||
# Don't fail auto entirely - main DB repair succeeded
|
||||
fi
|
||||
else
|
||||
WriteLog "Auto - FTS Check - PASS"
|
||||
fi
|
||||
|
||||
# All good to here
|
||||
WriteLog "Auto - COMPLETED"
|
||||
Output "Automatic Check, Repair/optimize, & Index successful."
|
||||
Output "Automatic Check, Repair/optimize, Index, & FTS check successful."
|
||||
;;
|
||||
|
||||
|
||||
@@ -2350,6 +2603,14 @@ do
|
||||
WriteLog "Check - FAIL"
|
||||
CheckedDB=0
|
||||
fi
|
||||
|
||||
# Also check FTS indexes (these can be damaged even when integrity_check passes)
|
||||
Output ""
|
||||
if ! CheckFTS "Check "; then
|
||||
Output ""
|
||||
Output "NOTE: FTS indexes are damaged but main database structure is OK."
|
||||
Output " Use 'reindex' (option 6) or 'automatic' (option 2) to rebuild."
|
||||
fi
|
||||
;;
|
||||
|
||||
# Vacuum
|
||||
@@ -2413,6 +2674,24 @@ do
|
||||
# Now index
|
||||
if DoIndex ; then
|
||||
WriteLog "Reindex - PASS"
|
||||
|
||||
# Check FTS indexes and repair if damaged
|
||||
Output ""
|
||||
if ! CheckFTS "Reindex"; then
|
||||
Output ""
|
||||
Output "FTS indexes are damaged. Rebuilding..."
|
||||
WriteLog "Reindex - FTS damaged, attempting rebuild"
|
||||
|
||||
if DoFTSRebuild; then
|
||||
WriteLog "Reindex - FTS Rebuild - PASS"
|
||||
Output "FTS rebuild successful."
|
||||
else
|
||||
WriteLog "Reindex - FTS Rebuild - FAIL"
|
||||
Output "FTS rebuild failed."
|
||||
fi
|
||||
else
|
||||
WriteLog "Reindex - FTS Check - PASS"
|
||||
fi
|
||||
else
|
||||
WriteLog "Reindex - FAIL"
|
||||
fi
|
||||
@@ -2494,6 +2773,9 @@ do
|
||||
[ $CheckedDB -eq 0 ] && Output " Databases are not checked, Status unknown."
|
||||
[ $CheckedDB -eq 1 ] && [ $Damaged -eq 0 ] && Output " Databases are OK."
|
||||
[ $CheckedDB -eq 1 ] && [ $Damaged -eq 1 ] && Output " Databases were checked and are damaged."
|
||||
[ $CheckedFTS -eq 0 ] && Output " FTS indexes are not checked, Status unknown."
|
||||
[ $CheckedFTS -eq 1 ] && [ $FTSDamaged -eq 0 ] && Output " FTS indexes are OK."
|
||||
[ $CheckedFTS -eq 1 ] && [ $FTSDamaged -eq 1 ] && Output " FTS indexes are damaged."
|
||||
Output ""
|
||||
;;
|
||||
|
||||
@@ -2713,4 +2995,4 @@ do
|
||||
esac
|
||||
done
|
||||
done
|
||||
exit 0
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user