partial RelationId implementation
This commit is contained in:
		
							parent
							
								
									102ff614f6
								
							
						
					
					
						commit
						0936f81e3c
					
				| @ -46,7 +46,11 @@ export async function createModelFromDatabase( | ||||
|     connectionOptions: IConnectionOptions, | ||||
|     generationOptions: IGenerationOptions | ||||
| ) { | ||||
|     let dbModel = await dataCollectionPhase(driver, connectionOptions); | ||||
|     let dbModel = await dataCollectionPhase( | ||||
|         driver, | ||||
|         connectionOptions, | ||||
|         generationOptions | ||||
|     ); | ||||
|     if (dbModel.length === 0) { | ||||
|         TomgUtils.LogError( | ||||
|             "Tables not found in selected database. Skipping creation of typeorm model.", | ||||
| @ -123,9 +127,10 @@ export async function createModelFromDatabase( | ||||
| } | ||||
| export async function dataCollectionPhase( | ||||
|     driver: AbstractDriver, | ||||
|     connectionOptions: IConnectionOptions | ||||
|     connectionOptions: IConnectionOptions, | ||||
|     generationOptions: IGenerationOptions | ||||
| ) { | ||||
|     return driver.GetDataFromServer(connectionOptions); | ||||
|     return driver.GetDataFromServer(connectionOptions, generationOptions); | ||||
| } | ||||
| 
 | ||||
| export function modelCustomizationPhase( | ||||
|  | ||||
| @ -37,6 +37,9 @@ export function findNameForNewField( | ||||
|         ) && | ||||
|             entity.relations.every( | ||||
|                 v => v.fieldName.toLowerCase() !== fieldName.toLowerCase() | ||||
|             ) && | ||||
|             entity.relationIds.every( | ||||
|                 v => v.fieldName.toLowerCase() !== fieldName.toLowerCase() | ||||
|             )) || | ||||
|         (columnOldName && | ||||
|             columnOldName.toLowerCase() === fieldName.toLowerCase()); | ||||
|  | ||||
| @ -13,6 +13,8 @@ import IConnectionOptions from "../IConnectionOptions"; | ||||
| import { Entity } from "../models/Entity"; | ||||
| import { RelationInternal } from "../models/RelationInternal"; | ||||
| import { Relation } from "../models/Relation"; | ||||
| import IGenerationOptions from "../IGenerationOptions"; | ||||
| import { Column } from "../models/Column"; | ||||
| 
 | ||||
| export default abstract class AbstractDriver { | ||||
|     public abstract standardPort: number; | ||||
| @ -175,7 +177,8 @@ export default abstract class AbstractDriver { | ||||
|     } | ||||
| 
 | ||||
|     public async GetDataFromServer( | ||||
|         connectionOptions: IConnectionOptions | ||||
|         connectionOptions: IConnectionOptions, | ||||
|         generationOptions: IGenerationOptions | ||||
|     ): Promise<Entity[]> { | ||||
|         let dbModel = [] as Entity[]; | ||||
|         await this.ConnectToServer(connectionOptions); | ||||
| @ -200,7 +203,8 @@ export default abstract class AbstractDriver { | ||||
|         dbModel = await this.GetRelations( | ||||
|             dbModel, | ||||
|             sqlEscapedSchema, | ||||
|             connectionOptions.databaseName | ||||
|             connectionOptions.databaseName, | ||||
|             generationOptions | ||||
|         ); | ||||
|         await this.DisconnectFromServer(); | ||||
|         dbModel = AbstractDriver.FindManyToManyRelations(dbModel); | ||||
| @ -234,6 +238,7 @@ export default abstract class AbstractDriver { | ||||
|                 columns: [], | ||||
|                 indices: [], | ||||
|                 relations: [], | ||||
|                 relationIds: [], | ||||
|                 sqlName: val.TABLE_NAME, | ||||
|                 tscName: val.TABLE_NAME, | ||||
|                 database: dbNames.includes(",") ? val.DB_NAME : "", | ||||
| @ -246,7 +251,8 @@ export default abstract class AbstractDriver { | ||||
| 
 | ||||
|     public static GetRelationsFromRelationTempInfo( | ||||
|         relationsTemp: RelationInternal[], | ||||
|         entities: Entity[] | ||||
|         entities: Entity[], | ||||
|         generationOptions: IGenerationOptions | ||||
|     ) { | ||||
|         relationsTemp.forEach(relationTmp => { | ||||
|             if (relationTmp.ownerColumns.length > 1) { | ||||
| @ -298,8 +304,8 @@ export default abstract class AbstractDriver { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             let ownerRelation: Relation | undefined; | ||||
|             let relatedRelation: Relation | undefined; | ||||
|             const ownerColumns: Column[] = []; | ||||
|             const relatedColumns: Column[] = []; | ||||
|             for ( | ||||
|                 let relationColumnIndex = 0; | ||||
|                 relationColumnIndex < relationTmp.ownerColumns.length; | ||||
| @ -327,77 +333,91 @@ export default abstract class AbstractDriver { | ||||
|                     ); | ||||
|                     return; | ||||
|                 } | ||||
|                 let isOneToMany: boolean; | ||||
|                 isOneToMany = false; | ||||
|                 const index = ownerEntity.indices.find( | ||||
|                     ind => | ||||
|                         ind.options.unique && | ||||
|                         ind.columns.length === 1 && | ||||
|                         ind.columns[0] === ownerColumn!.tscName | ||||
|                 ); | ||||
|                 isOneToMany = !index; | ||||
| 
 | ||||
|                 if (true) { | ||||
|                     // TODO: RelationId
 | ||||
|                     ownerEntity.columns = ownerEntity.columns.filter( | ||||
|                         v => | ||||
|                             !relationTmp.ownerColumns.some( | ||||
|                                 u => u === v.tscName | ||||
|                             ) || v.primary | ||||
|                     ); | ||||
|                     relationTmp.relatedTable.columns = relationTmp.relatedTable.columns.filter( | ||||
|                         v => | ||||
|                             !relationTmp.relatedColumns.some( | ||||
|                                 u => u === v.tscName | ||||
|                             ) || v.primary | ||||
|                     ); | ||||
|                 } | ||||
|                 let fieldName = ""; | ||||
|                 if (relationTmp.ownerColumns.length === 1) { | ||||
|                     fieldName = TomgUtils.findNameForNewField( | ||||
|                         ownerColumn.tscName, | ||||
|                         ownerEntity | ||||
|                     ); | ||||
|                 } else { | ||||
|                     fieldName = TomgUtils.findNameForNewField( | ||||
|                         relationTmp.relatedTable.tscName, | ||||
|                         ownerEntity | ||||
|                     ); | ||||
|                 } | ||||
|                 ownerRelation = { | ||||
|                     fieldName, | ||||
|                     relatedField: TomgUtils.findNameForNewField( | ||||
|                         relationTmp.ownerTable.tscName, | ||||
|                         relationTmp.relatedTable | ||||
|                     ), | ||||
|                     relationOptions: { | ||||
|                         onDelete: relationTmp.onDelete, | ||||
|                         onUpdate: relationTmp.onUpdate | ||||
|                     }, | ||||
|                     joinColumnOptions: relationTmp.ownerColumns.map( | ||||
|                         (v, idx) => { | ||||
|                             const retVal: JoinColumnOptions = { | ||||
|                                 name: v, | ||||
|                                 referencedColumnName: | ||||
|                                     relationTmp.relatedColumns[idx] | ||||
|                             }; | ||||
|                             return retVal; | ||||
|                         } | ||||
|                     ), | ||||
|                     relatedTable: relationTmp.relatedTable.tscName, | ||||
|                     relationType: isOneToMany ? "ManyToOne" : "OneToOne" | ||||
|                 }; | ||||
|                 relatedRelation = { | ||||
|                     fieldName: ownerRelation.relatedField, | ||||
|                     relatedField: ownerRelation.fieldName, | ||||
|                     relatedTable: relationTmp.ownerTable.tscName, | ||||
|                     // relationOptions: ownerRelation.relationOptions,
 | ||||
|                     relationType: isOneToMany ? "OneToMany" : "OneToOne" | ||||
|                 }; | ||||
|                 ownerColumns.push(ownerColumn); | ||||
|                 relatedColumns.push(relatedColumn); | ||||
|             } | ||||
|             let isOneToMany: boolean; | ||||
|             isOneToMany = false; | ||||
|             const index = ownerEntity.indices.find( | ||||
|                 ind => | ||||
|                     ind.options.unique && | ||||
|                     ind.columns.length === ownerColumns.length && | ||||
|                     ownerColumns.every(ownerColumn => | ||||
|                         ind.columns.some(col => col === ownerColumn.tscName) | ||||
|                     ) | ||||
|             ); | ||||
|             isOneToMany = !index; | ||||
| 
 | ||||
|             // TODO: RelationId
 | ||||
|             ownerEntity.columns = ownerEntity.columns.filter( | ||||
|                 v => | ||||
|                     !relationTmp.ownerColumns.some(u => u === v.tscName) || | ||||
|                     v.primary | ||||
|             ); | ||||
|             relationTmp.relatedTable.columns = relationTmp.relatedTable.columns.filter( | ||||
|                 v => | ||||
|                     !relationTmp.relatedColumns.some(u => u === v.tscName) || | ||||
|                     v.primary | ||||
|             ); | ||||
|             let fieldName = ""; | ||||
|             if (ownerColumns.length === 1) { | ||||
|                 fieldName = TomgUtils.findNameForNewField( | ||||
|                     ownerColumns[0].tscName, | ||||
|                     ownerEntity | ||||
|                 ); | ||||
|             } else { | ||||
|                 fieldName = TomgUtils.findNameForNewField( | ||||
|                     relationTmp.relatedTable.tscName, | ||||
|                     ownerEntity | ||||
|                 ); | ||||
|             } | ||||
| 
 | ||||
|             const ownerRelation: Relation = { | ||||
|                 fieldName, | ||||
|                 relatedField: TomgUtils.findNameForNewField( | ||||
|                     relationTmp.ownerTable.tscName, | ||||
|                     relationTmp.relatedTable | ||||
|                 ), | ||||
|                 relationOptions: { | ||||
|                     onDelete: relationTmp.onDelete, | ||||
|                     onUpdate: relationTmp.onUpdate | ||||
|                 }, | ||||
|                 joinColumnOptions: relationTmp.ownerColumns.map((v, idx) => { | ||||
|                     const retVal: JoinColumnOptions = { | ||||
|                         name: v, | ||||
|                         referencedColumnName: relationTmp.relatedColumns[idx] | ||||
|                     }; | ||||
|                     return retVal; | ||||
|                 }), | ||||
|                 relatedTable: relationTmp.relatedTable.tscName, | ||||
|                 relationType: isOneToMany ? "ManyToOne" : "OneToOne" | ||||
|             }; | ||||
|             const relatedRelation: Relation = { | ||||
|                 fieldName: ownerRelation.relatedField, | ||||
|                 relatedField: ownerRelation.fieldName, | ||||
|                 relatedTable: relationTmp.ownerTable.tscName, | ||||
|                 // relationOptions: ownerRelation.relationOptions,
 | ||||
|                 relationType: isOneToMany ? "OneToMany" : "OneToOne" | ||||
|             }; | ||||
| 
 | ||||
|             ownerEntity.relations.push(ownerRelation); | ||||
|             relationTmp.relatedTable.relations.push(relatedRelation); | ||||
| 
 | ||||
|             if (generationOptions.relationIds && ownerColumns.length === 1) { | ||||
|                 let relationIdFieldName = ""; | ||||
|                 relationIdFieldName = TomgUtils.findNameForNewField( | ||||
|                     ownerColumns[0].tscName, | ||||
|                     ownerEntity | ||||
|                 ); | ||||
|                 ownerEntity.relationIds.push({ | ||||
|                     fieldName: relationIdFieldName, // TODO: generate name without number(naming strategy)
 | ||||
|                     fieldType: isOneToMany | ||||
|                         ? `${ownerColumns[0].tscType}[]` | ||||
|                         : ownerColumns[0].tscType, | ||||
|                     relationField: ownerRelation.fieldName // TODO: naming strategy
 | ||||
|                 }); | ||||
|                 // TODO: RelationId on ManyToMany
 | ||||
|             } | ||||
|             if (ownerRelation) ownerEntity.relations.push(ownerRelation); | ||||
|             if (relatedRelation) | ||||
|                 relationTmp.relatedTable.relations.push(relatedRelation); | ||||
|         }); | ||||
|         return entities; | ||||
|     } | ||||
| @ -417,7 +437,8 @@ export default abstract class AbstractDriver { | ||||
|     public abstract async GetRelations( | ||||
|         entities: Entity[], | ||||
|         schema: string, | ||||
|         dbNames: string | ||||
|         dbNames: string, | ||||
|         generationOptions: IGenerationOptions | ||||
|     ): Promise<Entity[]>; | ||||
| 
 | ||||
|     public static FindPrimaryColumnsFromIndexes(dbModel: Entity[]) { | ||||
|  | ||||
| @ -14,6 +14,7 @@ import { Entity } from "../models/Entity"; | ||||
| import { Column } from "../models/Column"; | ||||
| import { Index } from "../models/Index"; | ||||
| import { RelationInternal } from "../models/RelationInternal"; | ||||
| import IGenerationOptions from "../IGenerationOptions"; | ||||
| 
 | ||||
| export default class MysqlDriver extends AbstractDriver { | ||||
|     public defaultValues: DataTypeDefaults = new TypeormDriver.MysqlDriver({ | ||||
| @ -316,7 +317,8 @@ export default class MysqlDriver extends AbstractDriver { | ||||
|     public async GetRelations( | ||||
|         entities: Entity[], | ||||
|         schema: string, | ||||
|         dbNames: string | ||||
|         dbNames: string, | ||||
|         generationOptions: IGenerationOptions | ||||
|     ): Promise<Entity[]> { | ||||
|         const response = await this.ExecQuery<{ | ||||
|             TableWithForeignKey: string; | ||||
| @ -385,7 +387,8 @@ export default class MysqlDriver extends AbstractDriver { | ||||
| 
 | ||||
|         const retVal = MysqlDriver.GetRelationsFromRelationTempInfo( | ||||
|             relationsTemp, | ||||
|             entities | ||||
|             entities, | ||||
|             generationOptions | ||||
|         ); | ||||
|         return retVal; | ||||
|     } | ||||
|  | ||||
| @ -44,6 +44,7 @@ export default class SqliteDriver extends AbstractDriver { | ||||
|                 columns: [], | ||||
|                 indices: [], | ||||
|                 relations: [], | ||||
|                 relationIds: [], | ||||
|                 sqlName: val.tbl_name, | ||||
|                 tscName: val.tbl_name, | ||||
|                 fileImports: [] | ||||
|  | ||||
| @ -15,6 +15,11 @@ import { {{toEntityName .}} } from './{{toFileName .}}' | ||||
| {{#if joinTableOptions}}@JoinTable({ {{json joinTableOptions}} }){{/if}} | ||||
| {{toPropertyName fieldName}}:{{toRelation (toEntityName relatedTable) relationType}}; | ||||
| 
 | ||||
| {{/inline}} | ||||
| {{#*inline "RelationId"}} | ||||
| @RelationId(({{toPropertyName entityName}}:{{toEntityName entityName}})=>{{toPropertyName entityName}}.{{toPropertyName relationField}}) | ||||
| {{toPropertyName fieldName}}:{{fieldType}}; | ||||
| 
 | ||||
| {{/inline}} | ||||
| {{#*inline "Entity"}} | ||||
| {{#indices}}{{> Index}}{{/indices~}} | ||||
| @ -23,6 +28,7 @@ export class {{toEntityName tscName}} { | ||||
| 
 | ||||
| {{#columns}}{{> Column}}{{/columns~}} | ||||
| {{#relations}}{{> Relation}}{{/relations~}} | ||||
| {{#relationIds}}{{> RelationId entityName=../tscName}}{{/relationIds~}} | ||||
| } | ||||
| {{/inline}} | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| import { Column } from "./Column"; | ||||
| import { Relation } from "./Relation"; | ||||
| import { Index } from "./Index"; | ||||
| import { RelationId } from "./RelationId"; | ||||
| 
 | ||||
| export type Entity = { | ||||
|     sqlName: string; | ||||
| @ -10,6 +11,7 @@ export type Entity = { | ||||
|     schema?: string; | ||||
| 
 | ||||
|     columns: Column[]; | ||||
|     relationIds: RelationId[]; | ||||
|     relations: Relation[]; | ||||
|     indices: Index[]; | ||||
|     fileImports: string[]; | ||||
|  | ||||
							
								
								
									
										5
									
								
								src/models/RelationId.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/models/RelationId.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| export type RelationId = { | ||||
|     fieldName: string; | ||||
|     fieldType: string; | ||||
|     relationField: string; | ||||
| }; | ||||
| @ -94,14 +94,16 @@ function runTestForMultipleDrivers( | ||||
|                         driver, | ||||
|                         Object.assign(connectionOptions, { | ||||
|                             databaseName: "db1,db2" | ||||
|                         }) | ||||
|                         }), | ||||
|                         generationOptions | ||||
|                     ); | ||||
|                     break; | ||||
| 
 | ||||
|                 default: | ||||
|                     dbModel = await dataCollectionPhase( | ||||
|                         driver, | ||||
|                         connectionOptions | ||||
|                         connectionOptions, | ||||
|                         generationOptions | ||||
|                     ); | ||||
|                     break; | ||||
|             } | ||||
| @ -160,7 +162,11 @@ async function runTest( | ||||
|                 resultsPath, | ||||
|                 filesOrgPathTS | ||||
|             } = await prepareTestRuns(testPartialPath, dbDriver, dbDriver); | ||||
|             let dbModel = await dataCollectionPhase(driver, connectionOptions); | ||||
|             let dbModel = await dataCollectionPhase( | ||||
|                 driver, | ||||
|                 connectionOptions, | ||||
|                 generationOptions | ||||
|             ); | ||||
|             dbModel = modelCustomizationPhase( | ||||
|                 dbModel, | ||||
|                 generationOptions, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user