Problem/Motivation
ContentEntityStorage base has a hasData() method that checks if any entities exist at all. This method is called during the uninstall process of a module to warn the user that data will be lost if the module is uninstalled.
When a module has deployment issues and the entity storage table has not been created, the hasData() method will throw an exception, completely blocking the uninstall process. So basically you end up with a broken module, that you cannot uninstall.
Proposed resolution
hasData() should return FALSE when the database table does not exist.
Remaining tasks
Address #18:
Determine how to know when hasData is failing specifically due to a missing database table and not for some other reason.
Suggested solution is to override the query since we can't assume a database backend.
Is it possible to examine the exception instead and return false for the specific missing table exception and throw the error otherwise
User interface changes
None
API changes
None
Data model changes
None
Original report
1. Create a content entity, and mess it up so much that the module that defines the entity installs but the entity table is not created.
(or just delete the entity table for a custom defined entity)
2. Try to uninstall the module... the uninstall page is all broken with a message such as this one:
Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[42S02]: [Microsoft][ODBC Driver 11 for SQL Server][SQL Server]Invalid object name 'powerlog'.: SELECT TOP(1) base_table.[id] AS [id], base_table.[id] AS [base_table_id] FROM powerlog base_table; Array ( ) : SELECT TOP(1) base_table.[id] AS [id], base_table.[id] AS [base_table_id] FROM powerlog base_table; Array ( ) in Drupal\Core\Entity\ContentEntityStorageBase->hasData() (line 74 of core\lib\Drupal\Core\Entity\ContentEntityStorageBase.php).
Drupal\Driver\Database\sqlsrv\Statement->execute(Array, Array)
Drupal\Driver\Database\sqlsrv\Connection->query('SELECT TOP(1) base_table.[id] AS [id], base_table.[id] AS [base_table_id]
FROM
{powerlog} base_table', Array, Array)
Drupal\Core\Database\Query\Select->execute()
Drupal\Core\Entity\Query\Sql\Query->result()
Drupal\Core\Entity\Query\Sql\Query->execute()
Drupal\Core\Entity\ContentEntityStorageBase->hasData()
Drupal\Core\Entity\ContentUninstallValidator->validate('powerlog')
Drupal\Core\Extension\ModuleInstaller->validateUninstall(Array)
Drupal\Core\ProxyClass\Extension\ModuleInstaller->validateUninstall(Array)
Drupal\system\Form\ModulesUninstallForm->buildForm(Array, Object)
Make the uninstall process more fault tolerant for entity management so that if these are crippled, it won't crash.