Sindbad~EG File Manager
# Database Export Temp File Fix
## Problem Identified
The database export was creating **multiple separate temp files** instead of accumulating all table data into one file during chunked processing.
### Root Cause
Each database export chunk was creating a new temp file due to overly aggressive collision detection:
1. **Chunk 1**: Creates `db_export_temp_xyz.sql` with tables 1-5
2. **Chunk 2**: Detects "conflict" → creates `db_export_temp_xyz_123_456.sql` with tables 6-10
3. **Chunk 3**: Detects "conflict" → creates `db_export_temp_xyz_789_101.sql` with tables 11-15
**Result**: Only the LAST temp file (with final few tables) got compressed into the final `.sql.gz`. All previous temp files with other tables were abandoned.
### Evidence from Logs
```
[09:01:45] Using temp file: db_export_temp_db_4f55154f120fa9ab_17518787734515_2858043_20250707-085933.sql
[09:01:52] Temp file conflict detected, using unique name: db_export_temp_db_4f55154f120fa9ab_17518787734515_2858043_20250707-085933_2865947_17518789120705.sql
[09:01:59] Temp file conflict detected, using unique name: db_export_temp_db_4f55154f120fa9ab_17518787734515_2858043_20250707-085933_2867953_17518789190314.sql
```
System found 59 tables but final SQL only contained 4 tables (from the last temp file).
## Solution Applied
### 1. Fixed Temp File Path Consistency
**File**: `custom-migrator/includes/class-database-exporter.php`
**Change**: Modified `setup_output_file()` method to reuse existing temp file path during resume operations:
```php
// CRITICAL FIX: For resume operations, reuse the existing temp file path
// This prevents creating multiple temp files and losing data
if ($is_resume && !empty($this->state['temp_file_path'])) {
$this->temp_file_path = $this->state['temp_file_path'];
$this->filesystem->log("Resuming with existing temp file: " . basename($this->temp_file_path));
} else {
// For fresh start, get new temp file path (deterministic naming)
$this->temp_file_path = $this->get_temp_file_path($sql_file);
$this->state['temp_file_path'] = $this->temp_file_path;
}
```
### 2. Enhanced Collision Detection Logic
**File**: `custom-migrator/includes/class-database-exporter.php`
**Change**: Made collision detection smarter to allow reusing temp files from the same export session:
```php
// ENHANCED SAFETY CHECK: Only add uniqueness if file exists and is from a different session
if (file_exists($temp_path)) {
$file_age = time() - filemtime($temp_path);
// If temp file exists and is very recent (less than 2 minutes), check if it's our session
if ($file_age < 120) {
// Check if this might be from the current export session by examining file size
$file_size = filesize($temp_path);
// If file is very small (less than 1KB), it's likely abandoned - safe to reuse
// If file is substantial but old enough (over 5 minutes), also safe to reuse
if ($file_size < 1024 || $file_age > 300) {
$this->filesystem->log("Reusing temp file (size: " . $this->format_bytes($file_size) . ", age: " . round($file_age) . "s): " . basename($temp_path));
} else {
// Recent substantial file - might be from concurrent process, make unique
// ... create unique temp file
}
} else {
// Old temp file, safe to reuse after cleanup
$this->filesystem->log("Reusing temp file after cleanup: " . basename($temp_path));
}
}
```
### 3. State Persistence Between Chunks
**File**: `custom-migrator/includes/class-fallback-exporter.php`
**Change**: Added `temp_file_path` to the resume state passed between chunks:
```php
if (isset($params['tables_processed']) && $params['tables_processed'] > 0) {
$resume_state = array(
'tables_processed' => (int)$params['tables_processed'],
'table_offset' => isset($params['table_offset']) ? (int)$params['table_offset'] : 0,
'total_tables' => isset($params['total_tables']) ? (int)$params['total_tables'] : 0,
'rows_exported' => isset($params['rows_exported']) ? (int)$params['rows_exported'] : 0,
'bytes_written' => isset($params['bytes_written']) ? (int)$params['bytes_written'] : 0,
'temp_file_path' => isset($params['temp_file_path']) ? $params['temp_file_path'] : null, // ADDED
);
}
```
And ensured it gets passed back in the response:
```php
'params' => array_merge($params, array(
'tables_processed' => $result['tables_processed'],
'table_offset' => isset($result['state']['table_offset']) ? $result['state']['table_offset'] : 0,
'total_tables' => $result['total_tables'],
'rows_exported' => $result['rows_exported'],
'bytes_written' => $result['bytes_written'],
'temp_file_path' => isset($result['state']['temp_file_path']) ? $result['state']['temp_file_path'] : null // ADDED
))
```
## Benefits
1. **All Tables Included**: All 59 tables now get included in the final SQL export
2. **Production Safe**: Maintains safety against concurrent processes
3. **Backward Compatible**: Doesn't break existing functionality
4. **Memory Efficient**: Single temp file approach reduces disk usage
5. **Clear Logging**: Better visibility into temp file operations
## Testing
The fix ensures that when you see logs like:
```
Found 59 database tables to export
Database export completed: 59 tables, 30648 rows
```
Your final `.sql.gz` file will actually contain **all 59 tables** instead of just the last few tables from the final chunk.
## Production Impact
This fix resolves the critical data loss issue where only a subset of database tables were being included in exports, ensuring complete and reliable WordPress site migrations.
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists