The scanning process could try to fetch thousands of roms from the
database, one by one, which is very inefficient, especially when only a
few new roms are added to the library, as the overhead of database calls
is very high compared to metadata API calls.
This change introduces a new method in the roms handler to retrieve roms
by their file names in bulk, which is used during the scan process to
fetch a batch of roms at once, instead of one by one.
It also avoids the `@with_details` decorator when fetching roms during
the scanning process, as those details are not needed, and they were
adding unnecessary joins and data decoding.
As recommended by SQLAlchemy [1], this change makes a single
instantiation of the database engine and session maker, instead of one
entity per handler.
It also uses the provided `URL` constructor to better define the
database URL structure.
[1] https://docs.sqlalchemy.org/en/20/core/connections.html#basic-usage
This change mainly refactors the `scan_platforms` function, moving part
of its logic to `_identify_platform`, `_identify_firmware`, and
`_identify_rom`.
The logic is simpler this way, each smaller function returns `ScanStats`
that can be merged by the caller, and it simplifies future performance
improvements.
The current implementation for some of the database handlers, where the
same method is used to retrieve either a single entity (when an `id` is
passed), a list of entities, or `None`, makes the typing and overall
design more complex.
This change simplifies database handlers, by having two separate methods
where appropiate:
* A method that receives an `id`, and returns either an entity, or `None`.
* A method that optionally receives filters, and returns (depending on
the current handler implementation) a list of entities, or a `Select`
object that allows chaining more SQLAlchemy operations.