diff --git a/app/availableplugins/HistoricPetitionViewer/config/plugin.json b/app/availableplugins/HistoricPetitionViewer/config/plugin.json index 1f0806f1c..fa5ea089b 100644 --- a/app/availableplugins/HistoricPetitionViewer/config/plugin.json +++ b/app/availableplugins/HistoricPetitionViewer/config/plugin.json @@ -21,7 +21,8 @@ }, "indexes": { "petition_hist_attrs_i1": { "columns": [ "petition_id" ] }, - "petition_hist_attrs_i2": { "columns": [ "attribute" ] } + "petition_hist_attrs_i2": { "columns": [ "attribute" ] }, + "petition_hist_attrs_i3": { "needed": false, "columns": [ "historic_petition_viewer_id" ] } } }, "petition_meta_hist_recs": { @@ -64,7 +65,11 @@ "petition_meta_hist_recs_i1": { "columns": [ "petition_id" ] }, "petition_meta_hist_recs_i2": { "columns": [ "enrollee_person_role_id" ] }, "petition_meta_hist_recs_i3": { "columns": [ "sponsor_person_id" ] }, - "petition_meta_hist_recs_i4": { "columns": [ "approver_person_id" ] } + "petition_meta_hist_recs_i4": { "columns": [ "approver_person_id" ] }, + "petition_meta_hist_recs_i5": { "needed": false, "columns": [ "enrollment_flow_id" ] }, + "petition_meta_hist_recs_i6": { "needed": false, "columns": [ "historic_petition_viewer_id" ] }, + "petition_meta_hist_recs_i7": { "needed": false, "columns": [ "enrollee_external_identity_id" ] }, + "petition_meta_hist_recs_i8": { "needed": false, "columns": [ "archived_external_identity_id" ] } } }, "historic_petition_viewers": { diff --git a/app/availableplugins/SqlConnector/config/plugin.json b/app/availableplugins/SqlConnector/config/plugin.json index 514e76f1b..48692a23d 100644 --- a/app/availableplugins/SqlConnector/config/plugin.json +++ b/app/availableplugins/SqlConnector/config/plugin.json @@ -17,7 +17,8 @@ "table_prefix": { "type": "string", "size": 32 } }, "indexes": { - "sql_provisioners_i1": { "columns": [ "provisioning_target_id" ]} + "sql_provisioners_i1": { "columns": [ "provisioning_target_id" ]}, + "sql_provisioners_i2": { "needed": false, "columns": [ "server_id" ]} } }, "sql_sources": { diff --git a/app/config/schema/schema.json b/app/config/schema/schema.json index acdb5d5e8..5c848a763 100644 --- a/app/config/schema/schema.json +++ b/app/config/schema/schema.json @@ -695,7 +695,8 @@ "notifications_i4": { "columns": [ "recipient_group_id" ] }, "notifications_i5": { "columns": [ "source" ] }, "notifications_i6": { "needed": false, "columns": [ "actor_person_id" ] }, - "notifications_i7": { "needed": false, "columns": [ "resolver_person_id" ] } + "notifications_i7": { "needed": false, "columns": [ "resolver_person_id" ] }, + "notifications_i8": { "needed": false, "columns": [ "message_template_id" ] } } }, @@ -943,7 +944,8 @@ "indexes": { "identifier_assignments_i1": { "columns": [ "co_id" ] }, "identifier_assignments_i2": { "needed": false, "columns": [ "email_address_type_id" ] }, - "identifier_assignments_i3": { "needed": false, "columns": [ "identifier_type_id" ] } + "identifier_assignments_i3": { "needed": false, "columns": [ "identifier_type_id" ] }, + "identifier_assignments_i4": { "needed": false, "columns": [ "group_id" ] } }, "clonable": true }, diff --git a/app/plugins/CoreEnroller/config/plugin.json b/app/plugins/CoreEnroller/config/plugin.json index 7c1633d83..ea161f949 100644 --- a/app/plugins/CoreEnroller/config/plugin.json +++ b/app/plugins/CoreEnroller/config/plugin.json @@ -91,7 +91,8 @@ "hidden": { "type": "boolean" } }, "indexes": { - "enrollment_attributes_i1": { "columns": [ "attribute_collector_id" ] } + "enrollment_attributes_i1": { "columns": [ "attribute_collector_id" ] }, + "enrollment_attributes_i2": { "needed": false, "columns": [ "attribute_type" ] } } }, "identifier_collectors": { diff --git a/app/plugins/EnvSource/config/plugin.json b/app/plugins/EnvSource/config/plugin.json index 698fec2a2..de51f1f8f 100644 --- a/app/plugins/EnvSource/config/plugin.json +++ b/app/plugins/EnvSource/config/plugin.json @@ -64,7 +64,12 @@ "lookaside_file": { "type": "path" } }, "indexes": { - "env_sources_i1": { "columns": [ "external_identity_source_id" ] } + "env_sources_i1": { "columns": [ "external_identity_source_id" ] }, + "env_sources_i2": { "needed": false, "columns": [ "default_affiliation_type_id" ] }, + "env_sources_i3": { "needed": false, "columns": [ "address_type_id" ] }, + "env_sources_i4": { "needed": false, "columns": [ "email_address_type_id" ] }, + "env_sources_i5": { "needed": false, "columns": [ "name_type_id" ] }, + "env_sources_i6": { "needed": false, "columns": [ "telephone_number_type_id" ] } } }, "env_source_identities": { diff --git a/app/plugins/OrcidSource/config/plugin.json b/app/plugins/OrcidSource/config/plugin.json index e3113e8b1..a0f0e1b86 100644 --- a/app/plugins/OrcidSource/config/plugin.json +++ b/app/plugins/OrcidSource/config/plugin.json @@ -35,7 +35,13 @@ "telephone_number_type_id": { "type": "integer", "foreignkey": { "table": "types", "column": "id" } } }, "indexes": { - "orcid_sources_i1": { "columns": [ "external_identity_source_id" ] } + "orcid_sources_i1": { "columns": [ "external_identity_source_id" ] }, + "orcid_sources_i2": { "needed": false, "columns": [ "server_id" ] }, + "orcid_sources_i3": { "needed": false, "columns": [ "default_affiliation_type_id" ] }, + "orcid_sources_i4": { "needed": false, "columns": [ "address_type_id" ] }, + "orcid_sources_i5": { "needed": false, "columns": [ "email_address_type_id" ] }, + "orcid_sources_i6": { "needed": false, "columns": [ "name_type_id" ] }, + "orcid_sources_i7": { "needed": false, "columns": [ "telephone_number_type_id" ] } } }, "orcid_tokens": { diff --git a/app/plugins/TermsAgreer/config/plugin.json b/app/plugins/TermsAgreer/config/plugin.json index 90cac19ad..b5e367e5a 100644 --- a/app/plugins/TermsAgreer/config/plugin.json +++ b/app/plugins/TermsAgreer/config/plugin.json @@ -27,7 +27,8 @@ }, "indexes": { "petition_agreements_i1": { "columns": [ "petition_id" ] }, - "petition_agreements_i2": { "needed": false, "columns": [ "terms_and_conditions_id" ] } + "petition_agreements_i2": { "needed": false, "columns": [ "terms_and_conditions_id" ] }, + "petition_agreements_i3": { "needed": false, "columns": [ "agreement_collector_id" ] } } } } diff --git a/app/src/Lib/Util/SchemaManager.php b/app/src/Lib/Util/SchemaManager.php index 890a3d388..cb5f198a6 100644 --- a/app/src/Lib/Util/SchemaManager.php +++ b/app/src/Lib/Util/SchemaManager.php @@ -34,6 +34,7 @@ use Doctrine\DBAL\Schema\Comparator; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\SchemaDiff; +use Doctrine\DBAL\Schema\Table; // Database schema management. We use Doctrine DBAL rather than Cake's migrations // (phinx) because migrations make development annoying (want to add a field @@ -355,7 +356,7 @@ protected function processSchema( $table->addIndex([$sColumn], $tablePrefix.$tName . "_im" . $i++); } - // If this table uses TreeBehavior, emit the appropriate columnsand indexes. + // If this table uses TreeBehavior, emit the appropriate columns and indexes. if(isset($tCfg->tree) && $tCfg->tree) { // Cake's TreeBehavior uses three columns: parent_id (which fks back to the // same table, similar to source_foo), lft, and rght. The recommendation is @@ -375,6 +376,9 @@ protected function processSchema( $table->addColumn("rght", "integer", ['notnull' => false]); } + + // Check for any auto-generated indexes created implicitly by DBAL + $this->checkAutoGeneratedIndexes($table, $tName); } // This is the SQL that represents the desired state of the database @@ -410,7 +414,7 @@ protected function processSchema( // Remove the DROP SEQUENCE statements in $fromSql because they're Postgres automagic // being misinterpreted. (Note toSaveSql might mask this now.) // XXX Maybe debug and file a PR to not emit DROP SEQUENCE on PG for autoincrementesque fields? - if($this->io) $io->out("Skipping sequence drop"); + if($this->io) $this->io->out("Skipping sequence drop"); } else { if(!$diffOnly) { $stmt = $this->conn->executeQuery($sql); @@ -430,4 +434,27 @@ protected function processSchema( // bin/cake schema_cache build --connection default // but so far we don't have an example indicating it's needed. } + + /** + * Check for any auto-generated indexes created implicitly by DBAL. + * + * @since COmanage Registry v5.0.0 + * @param \Doctrine\DBAL\Schema\Table $table Table object + * @param string $tName Table name + * @throws \LogicException If an auto-generated index is detected + */ + protected function checkAutoGeneratedIndexes(Table $table, string $tName): void { + foreach($table->getIndexes() as $index) { + if(str_starts_with(strtolower($index->getName()), 'idx_')) { + throw new \LogicException( + sprintf( + "Table '%s' has an auto-generated index '%s' on columns [%s]. Please define an explicit index in schema.json / plugin.json.", + $tName, + $index->getName(), + implode(', ', $index->getColumns()) + ) + ); + } + } + } } \ No newline at end of file