2020use Override ;
2121
2222class Version2020Date20260513185340 extends SimpleMigrationStep {
23- private const TARGET_TABLE = 'tables_columns ' ;
23+ private const TARGET_TABLE_COLUMNS = 'tables_columns ' ;
24+ private const TARGET_TABLE_VIEWS = 'tables_views ' ;
2425 private const COL_ID = 'id ' ;
2526 private const COL_UUID = 'uuid ' ;
2627 private const COL_SELECTION_OPTIONS = 'selection_options ' ;
27- private const INDEX_NAME = 'tables_col_uuid_uniq ' ;
28+ private const INDEX_NAME_COLUMNS = 'tables_col_uuid_uniq ' ;
29+ private const INDEX_NAME_VIEWS = 'tables_views_uuid_uniq ' ;
2830
2931 public function __construct (
3032 private readonly IDBConnection $ db ,
@@ -36,24 +38,28 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
3638 /** @var ISchemaWrapper $schema */
3739 $ schema = $ schemaClosure ();
3840
39- if (!$ schema ->hasTable (self ::TARGET_TABLE )) {
40- return null ;
41- }
41+ $ this ->addUuidColumnToTable ($ schema , self ::TARGET_TABLE_COLUMNS , self ::INDEX_NAME_COLUMNS );
42+ $ this ->addUuidColumnToTable ($ schema , self ::TARGET_TABLE_VIEWS , self ::INDEX_NAME_VIEWS );
43+
44+ return $ schema ;
45+ }
4246
43- $ columnsTable = $ schema ->getTable (self ::TARGET_TABLE );
44- if (!$ columnsTable ->hasColumn (self ::COL_UUID )) {
45- $ columnsTable ->addColumn (self ::COL_UUID , Types::STRING , [
47+ private function addUuidColumnToTable (ISchemaWrapper $ schema , string $ tableName , string $ indexName ): void {
48+ if (!$ schema ->hasTable ($ tableName )) {
49+ return ;
50+ }
51+ $ targetTable = $ schema ->getTable ($ tableName );
52+ if (!$ targetTable ->hasColumn (self ::COL_UUID )) {
53+ $ targetTable ->addColumn (self ::COL_UUID , Types::STRING , [
4654 'notnull ' => false ,
4755 'default ' => null ,
4856 'length ' => 36 ,
4957 'comment ' => 'UUIDv7 identifier to support structural updates across instances ' ,
5058 ]);
5159 }
52- if (!$ columnsTable ->hasUniqueConstraint (self :: INDEX_NAME )) {
53- $ columnsTable ->addUniqueIndex (['table_id ' , self ::COL_UUID ], self :: INDEX_NAME );
60+ if (!$ targetTable ->hasUniqueConstraint ($ indexName )) {
61+ $ targetTable ->addUniqueIndex (['table_id ' , self ::COL_UUID ], $ indexName );
5462 }
55-
56- return $ schema ;
5763 }
5864
5965 private function applyColumnOptionsUpdateIfNecessary (IQueryBuilder $ query , int $ columnId , ?string $ rawSelectionOptions ): void {
@@ -90,19 +96,24 @@ private function applyColumnOptionsUpdateIfNecessary(IQueryBuilder $query, int $
9096
9197 #[Override]
9298 public function postSchemaChange (IOutput $ output , Closure $ schemaClosure , array $ options ): void {
99+ $ this ->fillColumnUuids ();
100+ $ this ->fillViewUuids ();
101+ }
102+
103+ private function fillColumnUuids (): void {
93104 $ qbColUuidUpdate = $ this ->db ->getQueryBuilder ();
94- $ qbColUuidUpdate ->update (self ::TARGET_TABLE )
105+ $ qbColUuidUpdate ->update (self ::TARGET_TABLE_COLUMNS )
95106 ->set (self ::COL_UUID , $ qbColUuidUpdate ->createParameter ('columnUuid ' ))
96107 ->where ($ qbColUuidUpdate ->expr ()->eq (self ::COL_ID , $ qbColUuidUpdate ->createParameter ('columnLocalId ' )));
97108
98109 $ qbColOptionsUuidUpdate = $ this ->db ->getQueryBuilder ();
99- $ qbColOptionsUuidUpdate ->update (self ::TARGET_TABLE )
110+ $ qbColOptionsUuidUpdate ->update (self ::TARGET_TABLE_COLUMNS )
100111 ->set (self ::COL_SELECTION_OPTIONS , $ qbColOptionsUuidUpdate ->createParameter ('columnSelectionOptions ' ))
101112 ->where ($ qbColOptionsUuidUpdate ->expr ()->eq (self ::COL_ID , $ qbColOptionsUuidUpdate ->createParameter ('columnLocalId ' )));
102113
103114 $ qbSelect = $ this ->db ->getQueryBuilder ();
104115 $ qbSelect ->select (self ::COL_ID , self ::COL_SELECTION_OPTIONS )
105- ->from (self ::TARGET_TABLE );
116+ ->from (self ::TARGET_TABLE_COLUMNS );
106117 $ select = $ qbSelect ->executeQuery ();
107118
108119 $ writeBatches = 250 ;
@@ -140,4 +151,49 @@ public function postSchemaChange(IOutput $output, Closure $schemaClosure, array
140151
141152 $ select ->closeCursor ();
142153 }
154+
155+ private function fillViewUuids (): void {
156+ $ qbColUuidUpdate = $ this ->db ->getQueryBuilder ();
157+ $ qbColUuidUpdate ->update (self ::TARGET_TABLE_VIEWS )
158+ ->set (self ::COL_UUID , $ qbColUuidUpdate ->createParameter ('columnUuid ' ))
159+ ->where ($ qbColUuidUpdate ->expr ()->eq (self ::COL_ID , $ qbColUuidUpdate ->createParameter ('columnLocalId ' )));
160+
161+ $ qbSelect = $ this ->db ->getQueryBuilder ();
162+ $ qbSelect ->select (self ::COL_ID )
163+ ->from (self ::TARGET_TABLE_VIEWS );
164+ $ select = $ qbSelect ->executeQuery ();
165+
166+ $ writeBatches = 250 ;
167+ $ updates = 0 ;
168+
169+ try {
170+ $ this ->db ->beginTransaction ();
171+ while (($ columnData = $ select ->fetchAssociative ()) !== false ) {
172+ $ columnId = $ columnData [self ::COL_ID ];
173+ $ qbColUuidUpdate ->setParameters (
174+ [
175+ 'columnLocalId ' => (int )$ columnId ,
176+ 'columnUuid ' => Uuid::v7 ()->toRfc4122 (),
177+ ],
178+ [
179+ Types::INTEGER ,
180+ Types::STRING ,
181+ ]
182+ );
183+ $ qbColUuidUpdate ->executeStatement ();
184+
185+ $ updates ++;
186+ if ($ updates % $ writeBatches === 0 ) {
187+ $ this ->db ->commit ();
188+ $ this ->db ->beginTransaction ();
189+ }
190+ }
191+ $ this ->db ->commit ();
192+ } catch (\Exception $ e ) {
193+ $ this ->db ->rollBack ();
194+ throw $ e ;
195+ }
196+
197+ $ select ->closeCursor ();
198+ }
143199}
0 commit comments