@@ -20,7 +20,7 @@ export class MariaDBConnection extends DatabaseConnection {
2020 private pool ?: mariaDB . Pool ;
2121 private isConnecting : boolean ;
2222
23- constructor ( hostname : string , port : number , username : string , password : string , database : string ) {
23+ constructor ( { hostname, port , username , password , database } : { hostname : string , port : number , username : string , password : string , database : string } ) {
2424 super ( ) ;
2525
2626 this . hostname = hostname ;
@@ -181,15 +181,16 @@ export class MariaDBConnection extends DatabaseConnection {
181181 * @private
182182 */
183183 private convertTypes ( field : IDatabaseField ) : IMariaDBField {
184- if ( ! field . maxSize && field . type !== EDatabaseTypes . BOOLEAN ) throw new DatabaseException ( 'Any field (other than boolean) must have a maxSize!' ) ;
184+ if ( ! ( field . type === EDatabaseTypes . BOOLEAN || field . type === EDatabaseTypes . TIMESTAMP ) && ! field . maxSize )
185+ throw new DatabaseException ( 'Any field (other than boolean and timestamp) must have a maxSize!' ) ;
185186 const finalObject : IMariaDBField = {
186187 type : EMariaDBFieldTypes . string ,
187188 attributes : '' ,
188- typeSize : field . maxSize ?? 1 ,
189+ typeSize : ( field . type === EDatabaseTypes . BOOLEAN ? 1 : field . maxSize ) ?? 1 ,
189190 nullable : field . nullable ,
190191 primaryKey : ( field . primaryKey && ( field . type === EDatabaseTypes . UINT || field . type === EDatabaseTypes . SINT ) ) ?? false ,
191192 autoIncrement : field . autoIncrement ?? false ,
192- unique : field . unique ?? false ,
193+ unique : ( field . type === EDatabaseTypes . BOOLEAN ? false : field . unique ) ?? false ,
193194 default : field . default ,
194195 } ;
195196 switch ( field . type ) {
@@ -251,14 +252,14 @@ export class MariaDBConnection extends DatabaseConnection {
251252 const uniqueKeys : string [ ] = [ ] ;
252253 fieldsKeys . forEach ( ( fieldKey ) => {
253254 if ( fields [ fieldKey ] . primaryKey ) primaryKeys . push ( conn . escapeId ( fieldKey ) ) ;
254- if ( fields [ fieldKey ] . unique ) uniqueKeys . push ( conn . escapeId ( fieldKey ) ) ;
255+ if ( fields [ fieldKey ] . type !== EDatabaseTypes . BOOLEAN && fields [ fieldKey ] . unique ) uniqueKeys . push ( conn . escapeId ( fieldKey ) ) ;
255256 } ) ;
256257
257258 // Add the constraints
258259 if ( primaryKeys . length > 0 ) tableFields . push ( `PRIMARY KEY (${ primaryKeys . join ( ', ' ) } )` ) ;
259260 uniqueKeys . filter ( ( key ) => ! primaryKeys . includes ( key ) ) . forEach ( ( key ) => tableFields . push ( `UNIQUE INDEX ${ key } (${ key } )` ) ) ;
260261 fieldsKeys . filter ( key => fields [ key ] . foreignKey ) . forEach ( ( key ) => {
261- let query = `FOREIGN KEY (${ conn . escapeId ( key ) } ) REFERENCES ${ conn . escapeId ( fields [ key ] . foreignKey ! . table . getName ( ) ) } (${ conn . escapeId ( fields [ key ] . foreignKey ! . field ) } )` ;
262+ let query = `CONSTRAINT FOREIGN KEY ${ key + '_fk' } (${ conn . escapeId ( key ) } ) REFERENCES ${ conn . escapeId ( fields [ key ] . foreignKey ! . table . getName ( ) ) } (${ conn . escapeId ( fields [ key ] . foreignKey ! . field ) } )` ;
262263 if ( fields [ key ] . foreignKey ! . onDelete ) query += ` ON DELETE ${ fields [ key ] . foreignKey ! . onDelete ! } ` ;
263264 if ( fields [ key ] . foreignKey ! . onUpdate ) query += ` ON UPDATE ${ fields [ key ] . foreignKey ! . onUpdate ! } ` ;
264265 tableFields . push ( query ) ;
@@ -277,23 +278,22 @@ export class MariaDBConnection extends DatabaseConnection {
277278 const currentFields : IMariaDBDescribeField [ ] = await conn . query ( `DESCRIBE ${ tableName } ` ) ;
278279 const fieldsKeys = Object . keys ( fields ) ;
279280
281+ const tableData : { Table : string , 'Create Table' : string } = ( await conn . query ( `SHOW CREATE TABLE ${ tableName } ` ) ) [ 0 ] ;
282+
280283 const fieldsToAdd = fieldsKeys . filter ( ( key ) => ! currentFields . find ( ( field ) => field . Field === key ) ) ;
281284 const fieldsToRemove = currentFields . filter ( ( field ) => ! fields [ field . Field ] ) ;
282285 const fieldsToUpdate : string [ ] = [ ] ;
283- const existingPrimaryKeys = currentFields . filter ( ( field ) => field . Key === 'PRI' ) ;
286+
284287 const newPrimaryKeys = fieldsKeys . filter ( ( key ) => fields [ key ] . primaryKey ) ;
285- const didPrimaryKeysChange = existingPrimaryKeys . length !== newPrimaryKeys . length ||
286- existingPrimaryKeys . some ( ( key ) => ! newPrimaryKeys . includes ( key . Field ) ) ||
287- newPrimaryKeys . some ( ( key ) => ! existingPrimaryKeys . find ( ( field ) => field . Field === key ) ) ;
288- const existingUniqueKeys = currentFields . filter ( ( field ) => field . Key === 'UNI' ) ;
289- const newUniqueKeys = fieldsKeys . filter ( ( key ) => fields [ key ] . unique && ! fields [ key ] . primaryKey ) ;
290- const uniqueKeysToRemove = existingUniqueKeys . filter ( ( key ) => ! newUniqueKeys . includes ( key . Field ) ) ;
291- const uniqueKeysToAdd = newUniqueKeys . filter ( ( key ) => ! existingUniqueKeys . find ( ( field ) => field . Field === key ) ) ;
292- const existingForeignKeys = currentFields . filter ( ( field ) => field . Key === 'MUL' ) ;
293- const newForeignKeys = fieldsKeys . filter ( ( key ) => fields [ key ] . foreignKey ) ;
294- const foreignKeysToRemove = existingForeignKeys . filter ( ( key ) => ! newForeignKeys . includes ( key . Field ) ) . map ( ( item ) => item . Field ) ;
295- const foreignKeysToAdd = newForeignKeys . filter ( ( key ) => ! existingForeignKeys . find ( ( field ) => field . Field === key ) ) ;
296- const foreignKeysToUpdate = newForeignKeys . filter ( ( key ) => existingForeignKeys . find ( ( field ) => field . Field === key ) ) ;
288+ const newUniqueKeys = fieldsKeys . filter ( ( key ) => fields [ key ] . type !== EDatabaseTypes . BOOLEAN && fields [ key ] . unique && ! fields [ key ] . primaryKey ) ;
289+ const newForeignKeys = fieldsKeys . filter ( ( key ) => fields [ key ] . foreignKey ) . map ( ( key ) => key + '_fk' ) ;
290+
291+ const currentPrimaryKey = ( tableData [ 'Create Table' ] . match ( / P R I M A R Y K E Y \( ( .* ?) \) / ) ?. [ 1 ] ?? '' ) . split ( ',' ) . map ( key => key . replace ( / ` / g, '' ) . trim ( ) ) . filter ( key => key . length > 0 ) ;
292+ const currentUniqueKeys = Array . from ( tableData [ 'Create Table' ] . matchAll ( / U N I Q U E K E Y ` ( .* ?) ` / g) ) . map ( match => match [ 1 ] ) . filter ( key => ! currentPrimaryKey . includes ( key ) ) ;
293+ const currentForeignKeys = Array . from (
294+ tableData [ 'Create Table' ]
295+ . matchAll ( / C O N S T R A I N T ` ( .* ?) ` F O R E I G N K E Y \( ` ( .* ?) ` \) R E F E R E N C E S ` ( .* ?) ` \( ` ( .* ?) ` \) ( O N D E L E T E ( R E S T R I C T | C A S C A D E | S E T N U L L | N O A C T I O N ) ) ? ( O N U P D A T E ( R E S T R I C T | C A S C A D E | S E T N U L L | N O A C T I O N ) ) ? / g) ,
296+ ) . map ( match => match [ 1 ] ) ;
297297
298298 // Find all fields that should be updated
299299 for ( const field of currentFields ) {
@@ -309,20 +309,35 @@ export class MariaDBConnection extends DatabaseConnection {
309309 }
310310
311311 const operations : string [ ] = [ ] ;
312- if ( didPrimaryKeysChange ) {
312+ if ( currentPrimaryKey . join ( ',' ) !== newPrimaryKeys . join ( ',' ) ) {
313313 operations . push ( 'DROP PRIMARY KEY' ) ;
314314 operations . push ( `ADD PRIMARY KEY (${ fieldsKeys . filter ( ( fieldKey ) => fields [ fieldKey ] . primaryKey ) . map ( ( key ) => conn . escapeId ( key ) ) . join ( ', ' ) } )` ) ;
315315 }
316+
316317 fieldsToRemove . forEach ( ( field ) => operations . push ( `DROP ${ field . Field } ` ) ) ;
317318 fieldsToAdd . forEach ( ( field ) => operations . push ( `ADD ${ this . createSQLField ( conn , field , fields [ field ] ) } ` ) ) ;
318319 fieldsToUpdate . forEach ( ( field ) => operations . push ( `CHANGE ${ conn . escapeId ( field ) } ${ this . createSQLField ( conn , field , fields [ field ] ) } ` ) ) ;
319- uniqueKeysToRemove . forEach ( ( field ) => operations . push ( `DROP INDEX ${ field . Field } ` ) ) ;
320+
321+ const uniqueKeysToRemove = currentUniqueKeys . filter ( ( key ) => ! newUniqueKeys . includes ( key ) ) ;
322+ const uniqueKeysToAdd = newUniqueKeys . filter ( ( key ) => ! currentUniqueKeys . includes ( key ) ) ;
323+
324+ uniqueKeysToRemove . forEach ( ( field ) => operations . push ( `DROP INDEX ${ field } ` ) ) ;
320325 uniqueKeysToAdd . forEach ( ( field ) => operations . push ( `ADD UNIQUE INDEX ${ field } (${ field } )` ) ) ;
326+
327+ const foreignKeysToRemove = currentForeignKeys . filter ( ( key ) => ! newForeignKeys . includes ( key ) ) ;
328+ const foreignKeysToAdd = newForeignKeys . filter ( ( key ) => ! currentForeignKeys . includes ( key ) ) ;
329+ const foreignKeysToUpdate = newForeignKeys . filter ( ( key ) => currentForeignKeys . includes ( key ) && ( key !== ( key . replace ( / _ f k $ / , '' ) ) + '_fk' ) ) ;
330+
321331 [ ...foreignKeysToRemove , ...foreignKeysToUpdate ] . forEach ( ( key ) => operations . push ( `DROP FOREIGN KEY ${ conn . escapeId ( key ) } ` ) ) ;
322332 [ ...foreignKeysToAdd , ...foreignKeysToUpdate ] . forEach ( ( key ) => {
323- let query = `ADD FOREIGN KEY (${ conn . escapeId ( key ) } ) REFERENCES ${ conn . escapeId ( fields [ key ] . foreignKey ! . table . getName ( ) ) } (${ conn . escapeId ( fields [ key ] . foreignKey ! . field ) } )` ;
324- if ( fields [ key ] . foreignKey ! . onDelete ) query += ` ON DELETE ${ fields [ key ] . foreignKey ! . onDelete ! } ` ;
325- if ( fields [ key ] . foreignKey ! . onUpdate ) query += ` ON UPDATE ${ fields [ key ] . foreignKey ! . onUpdate ! } ` ;
333+ const fieldKey = key . substring ( 0 , key . length - 3 ) ;
334+
335+ let query = `ADD FOREIGN KEY ${ key } (${ conn . escapeId ( fieldKey ) } ) REFERENCES ${
336+ conn . escapeId ( fields [ fieldKey ] . foreignKey ! . table . getName ( ) )
337+ } (${ conn . escapeId ( fields [ fieldKey ] . foreignKey ! . field ) } )`;
338+
339+ if ( fields [ fieldKey ] . foreignKey ! . onDelete ) query += ` ON DELETE ${ fields [ fieldKey ] . foreignKey ! . onDelete ! } ` ;
340+ if ( fields [ fieldKey ] . foreignKey ! . onUpdate ) query += ` ON UPDATE ${ fields [ fieldKey ] . foreignKey ! . onUpdate ! } ` ;
326341 operations . push ( query ) ;
327342 } ) ;
328343 if ( operations . length > 0 ) await conn . query ( `ALTER TABLE ${ conn . escapeId ( tableName ) } ${ operations . join ( ', ' ) } ` ) ;
0 commit comments