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