Problem
The SQLite to PostgreSQL converter (src/sqlite/converter.rs) loads all rows into memory before inserting to PostgreSQL. This causes out-of-memory errors on large SQLite databases.
Example
A 2.3GB SQLite file with 7.2 million rows in the prices table would require 8-16GB of RAM to process, making the tool unusable for moderately-sized SQLite databases.
Root Cause
convert_table_to_jsonb() calls read_table_data() which returns Vec<HashMap<String, Value>> containing ALL rows, then converts them all to another Vec<(String, JsonValue)> before batch inserting.
// Current implementation - loads everything into memory
let rows = crate::sqlite::reader::read_table_data(conn, table)?;
let mut result = Vec::with_capacity(rows.len());
for row in rows.into_iter() {
// ... convert each row
}
Proposed Solution
Implement streaming/batched processing similar to the xmin-based sync:
- Read rows in batches (e.g., 10,000 rows at a time)
- Convert and insert each batch before reading the next
- Track progress for resumability
This pattern already exists in src/xmin/reader.rs with keyset pagination.
Acceptance Criteria
Problem
The SQLite to PostgreSQL converter (
src/sqlite/converter.rs) loads all rows into memory before inserting to PostgreSQL. This causes out-of-memory errors on large SQLite databases.Example
A 2.3GB SQLite file with 7.2 million rows in the
pricestable would require 8-16GB of RAM to process, making the tool unusable for moderately-sized SQLite databases.Root Cause
convert_table_to_jsonb()callsread_table_data()which returnsVec<HashMap<String, Value>>containing ALL rows, then converts them all to anotherVec<(String, JsonValue)>before batch inserting.Proposed Solution
Implement streaming/batched processing similar to the xmin-based sync:
This pattern already exists in
src/xmin/reader.rswith keyset pagination.Acceptance Criteria