mssql driver without relations

This commit is contained in:
Kononnable 2019-10-02 19:39:43 +02:00
parent ab23f71756
commit 76f3ed2ad2
11 changed files with 346 additions and 336 deletions

View File

@ -44,80 +44,80 @@ export async function createModelFromDatabase(
connectionOptions: IConnectionOptions,
generationOptions: IGenerationOptions
) {
// let dbModel = await dataCollectionPhase(driver, connectionOptions);
// if (dbModel.length === 0) {
// TomgUtils.LogError(
// "Tables not found in selected database. Skipping creation of typeorm model.",
// false
// );
// return;
// }
let dbModel = await dataCollectionPhase(driver, connectionOptions);
if (dbModel.length === 0) {
TomgUtils.LogError(
"Tables not found in selected database. Skipping creation of typeorm model.",
false
);
return;
}
// dbModel = modelCustomizationPhase(
// dbModel,
// generationOptions,
// driver.defaultValues
// );
const dbModel: Entity = {
sqlName: "sqlName",
tscName: "typescriptName",
schema: "schema",
database: "database",
columns: [
{
tscType: "typescriptType",
tscName: "tscName",
options: {
name: "sqlName",
type: "integer",
length: 2,
scale: 2
}
},
{
tscType: "typescriptType",
tscName: "tscName",
options: {
name: "sqlName",
type: "integer",
length: 2,
scale: 2
}
}
],
indices: [
{
columns: ["columns"],
name: "name"
},
{
columns: ["columns"],
name: "name"
}
],
relations: [
{
relationType: "OneToMany",
relatedField: "relatedField",
fieldName: "relation",
relatedTable: "any",
relationOptions: {
onUpdate: "CASCADE",
onDelete: "NO ACTION"
}
},
{
relationType: "OneToOne",
relatedField: "relatedField",
fieldName: "relation",
relatedTable: "any",
relationOptions: {
onUpdate: "CASCADE",
onDelete: "NO ACTION"
}
}
]
};
modelGenerationPhase(connectionOptions, generationOptions, [dbModel]);
// const dbModel: Entity = {
// sqlName: "sqlName",
// tscName: "typescriptName",
// schema: "schema",
// database: "database",
// columns: [
// {
// tscType: "typescriptType",
// tscName: "tscName",
// options: {
// name: "sqlName",
// type: "integer",
// length: 2,
// scale: 2
// }
// },
// {
// tscType: "typescriptType",
// tscName: "tscName",
// options: {
// name: "sqlName",
// type: "integer",
// length: 2,
// scale: 2
// }
// }
// ],
// indices: [
// {
// columns: ["columns"],
// name: "name"
// },
// {
// columns: ["columns"],
// name: "name"
// }
// ],
// relations: [
// {
// relationType: "OneToMany",
// relatedField: "relatedField",
// fieldName: "relation",
// relatedTable: "any",
// relationOptions: {
// onUpdate: "CASCADE",
// onDelete: "NO ACTION"
// }
// },
// {
// relationType: "OneToOne",
// relatedField: "relatedField",
// fieldName: "relation",
// relatedTable: "any",
// relationOptions: {
// onUpdate: "CASCADE",
// onDelete: "NO ACTION"
// }
// }
// ]
// };
modelGenerationPhase(connectionOptions, generationOptions, dbModel);
}
export async function dataCollectionPhase(
driver: AbstractDriver,

View File

@ -175,12 +175,12 @@ export default abstract class AbstractDriver {
sqlEscapedSchema,
connectionOptons.databaseName
);
await this.GetIndexesFromEntity(
dbModel,
sqlEscapedSchema,
connectionOptons.databaseName
);
// TODO: Uncomment
// await this.GetIndexesFromEntity(
// dbModel,
// sqlEscapedSchema,
// connectionOptons.databaseName
// );
// dbModel = await this.GetRelations(
// dbModel,
// sqlEscapedSchema,
@ -203,6 +203,8 @@ export default abstract class AbstractDriver {
response.forEach(val => {
ret.push({
columns: [],
indices: [],
relations: [],
sqlName: val.TABLE_NAME,
tscName: val.TABLE_NAME,
database: dbNames.includes(",") ? val.DB_NAME : "",
@ -381,10 +383,10 @@ export default abstract class AbstractDriver {
): Promise<Entity[]>;
public abstract async GetIndexesFromEntity(
entities: EntityInfo[],
entities: Entity[],
schema: string,
dbNames: string
): Promise<EntityInfo[]>;
): Promise<Entity[]>;
public abstract async GetRelations(
entities: EntityInfo[],

View File

@ -227,77 +227,79 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG
}
public async GetIndexesFromEntity(
entities: EntityInfo[],
entities: Entity[],
schema: string,
dbNames: string
): Promise<EntityInfo[]> {
const request = new MSSQL.Request(this.Connection);
const response: {
TableName: string;
IndexName: string;
ColumnName: string;
is_unique: boolean;
is_primary_key: boolean;
}[] = [];
await Promise.all(
dbNames.split(",").map(async dbName => {
await this.UseDB(dbName);
const resp: {
TableName: string;
IndexName: string;
ColumnName: string;
is_unique: boolean;
is_primary_key: boolean;
}[] = (await request.query(`SELECT
TableName = t.name,
IndexName = ind.name,
ColumnName = col.name,
ind.is_unique,
ind.is_primary_key
FROM
sys.indexes ind
INNER JOIN
sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id
INNER JOIN
sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id
INNER JOIN
sys.tables t ON ind.object_id = t.object_id
INNER JOIN
sys.schemas s on s.schema_id=t.schema_id
WHERE
t.is_ms_shipped = 0 and s.name in (${schema})
ORDER BY
t.name, ind.name, ind.index_id, ic.key_ordinal;`)).recordset;
response.push(...resp);
})
);
entities.forEach(ent => {
response
.filter(filterVal => filterVal.TableName === ent.tsEntityName)
.forEach(resp => {
let indexInfo: IndexInfo = {} as IndexInfo;
const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo;
if (
ent.Indexes.filter(filterVal => {
return filterVal.name === resp.IndexName;
}).length > 0
) {
[indexInfo] = ent.Indexes.filter(filterVal => {
return filterVal.name === resp.IndexName;
});
} else {
indexInfo.columns = [] as IndexColumnInfo[];
indexInfo.name = resp.IndexName;
indexInfo.isUnique = resp.is_unique;
indexInfo.isPrimaryKey = resp.is_primary_key;
ent.Indexes.push(indexInfo);
}
indexColumnInfo.name = resp.ColumnName;
indexInfo.columns.push(indexColumnInfo);
});
});
): Promise<Entity[]> {
throw new Error();
// TODO: Remove
// const request = new MSSQL.Request(this.Connection);
// const response: {
// TableName: string;
// IndexName: string;
// ColumnName: string;
// is_unique: boolean;
// is_primary_key: boolean;
// }[] = [];
// await Promise.all(
// dbNames.split(",").map(async dbName => {
// await this.UseDB(dbName);
// const resp: {
// TableName: string;
// IndexName: string;
// ColumnName: string;
// is_unique: boolean;
// is_primary_key: boolean;
// }[] = (await request.query(`SELECT
// TableName = t.name,
// IndexName = ind.name,
// ColumnName = col.name,
// ind.is_unique,
// ind.is_primary_key
// FROM
// sys.indexes ind
// INNER JOIN
// sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id
// INNER JOIN
// sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id
// INNER JOIN
// sys.tables t ON ind.object_id = t.object_id
// INNER JOIN
// sys.schemas s on s.schema_id=t.schema_id
// WHERE
// t.is_ms_shipped = 0 and s.name in (${schema})
// ORDER BY
// t.name, ind.name, ind.index_id, ic.key_ordinal;`)).recordset;
// response.push(...resp);
// })
// );
// entities.forEach(ent => {
// response
// .filter(filterVal => filterVal.TableName === ent.tsEntityName)
// .forEach(resp => {
// let indexInfo: IndexInfo = {} as IndexInfo;
// const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo;
// if (
// ent.Indexes.filter(filterVal => {
// return filterVal.name === resp.IndexName;
// }).length > 0
// ) {
// [indexInfo] = ent.Indexes.filter(filterVal => {
// return filterVal.name === resp.IndexName;
// });
// } else {
// indexInfo.columns = [] as IndexColumnInfo[];
// indexInfo.name = resp.IndexName;
// indexInfo.isUnique = resp.is_unique;
// indexInfo.isPrimaryKey = resp.is_primary_key;
// ent.Indexes.push(indexInfo);
// }
// indexColumnInfo.name = resp.ColumnName;
// indexInfo.columns.push(indexColumnInfo);
// });
// });
return entities;
// return entities;
}
public async GetRelations(

View File

@ -12,6 +12,7 @@ import RelationTempInfo from "../oldModels/RelationTempInfo";
import IConnectionOptions from "../IConnectionOptions";
import { Entity } from "../models/Entity";
import { Column } from "../models/Column";
import { Index } from "../models/Index";
export default class MysqlDriver extends AbstractDriver {
public defaultValues: DataTypeDefaults = new TypeormDriver.MysqlDriver({
@ -248,10 +249,9 @@ export default class MysqlDriver extends AbstractDriver {
if (options.type) {
ent.columns.push({
generated,
options,
options: { type: "integer", name: "", ...options }, // TODO: Change
tscName,
tscType,
primary
tscType
});
}
});
@ -260,10 +260,10 @@ export default class MysqlDriver extends AbstractDriver {
}
public async GetIndexesFromEntity(
entities: EntityInfo[],
entities: Entity[],
schema: string,
dbNames: string
): Promise<EntityInfo[]> {
): Promise<Entity[]> {
const response = await this.ExecQuery<{
TableName: string;
IndexName: string;
@ -277,29 +277,28 @@ export default class MysqlDriver extends AbstractDriver {
dbNames
)})`);
entities.forEach(ent => {
response
.filter(filterVal => filterVal.TableName === ent.tsEntityName)
.forEach(resp => {
let indexInfo: IndexInfo = {} as IndexInfo;
const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo;
if (
ent.Indexes.filter(
filterVal => filterVal.name === resp.IndexName
).length > 0
) {
indexInfo = ent.Indexes.find(
filterVal => filterVal.name === resp.IndexName
)!;
} else {
indexInfo.columns = [] as IndexColumnInfo[];
indexInfo.name = resp.IndexName;
indexInfo.isUnique = resp.is_unique === 1;
indexInfo.isPrimaryKey = resp.is_primary_key === 1;
ent.Indexes.push(indexInfo);
}
indexColumnInfo.name = resp.ColumnName;
indexInfo.columns.push(indexColumnInfo);
const entityIndices = response.filter(
filterVal => filterVal.TableName === ent.tscName
);
const indexNames = new Set(entityIndices.map(v => v.IndexName));
indexNames.forEach(indexName => {
const records = entityIndices.filter(
v => v.IndexName === indexName
);
const indexInfo: Index = {
name: indexName,
columns: [],
options: {}
};
if (records[0].is_primary_key === 1) indexInfo.primary = true;
if (records[0].is_unique === 1) indexInfo.options.unique = true;
records.forEach(record => {
indexInfo.columns.push(record.ColumnName);
});
ent.indices.push(indexInfo);
});
});
return entities;

View File

@ -207,49 +207,49 @@ export default class OracleDriver extends AbstractDriver {
// return entities;
}
public async GetIndexesFromEntity(
entities: EntityInfo[]
): Promise<EntityInfo[]> {
const response: {
COLUMN_NAME: string;
TABLE_NAME: string;
INDEX_NAME: string;
UNIQUENESS: string;
ISPRIMARYKEY: number;
}[] = (await this.Connection
.execute(`SELECT ind.TABLE_NAME, ind.INDEX_NAME, col.COLUMN_NAME,ind.UNIQUENESS, CASE WHEN uc.CONSTRAINT_NAME IS NULL THEN 0 ELSE 1 END ISPRIMARYKEY
FROM USER_INDEXES ind
JOIN USER_IND_COLUMNS col ON ind.INDEX_NAME=col.INDEX_NAME
LEFT JOIN USER_CONSTRAINTS uc ON uc.INDEX_NAME = ind.INDEX_NAME
ORDER BY col.INDEX_NAME ASC ,col.COLUMN_POSITION ASC`)).rows!;
public async GetIndexesFromEntity(entities: Entity[]): Promise<Entity[]> {
throw new Error();
// TODO: Remove
// const response: {
// COLUMN_NAME: string;
// TABLE_NAME: string;
// INDEX_NAME: string;
// UNIQUENESS: string;
// ISPRIMARYKEY: number;
// }[] = (await this.Connection
// .execute(`SELECT ind.TABLE_NAME, ind.INDEX_NAME, col.COLUMN_NAME,ind.UNIQUENESS, CASE WHEN uc.CONSTRAINT_NAME IS NULL THEN 0 ELSE 1 END ISPRIMARYKEY
// FROM USER_INDEXES ind
// JOIN USER_IND_COLUMNS col ON ind.INDEX_NAME=col.INDEX_NAME
// LEFT JOIN USER_CONSTRAINTS uc ON uc.INDEX_NAME = ind.INDEX_NAME
// ORDER BY col.INDEX_NAME ASC ,col.COLUMN_POSITION ASC`)).rows!;
entities.forEach(ent => {
response
.filter(filterVal => filterVal.TABLE_NAME === ent.tsEntityName)
.forEach(resp => {
let indexInfo: IndexInfo = {} as IndexInfo;
const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo;
if (
ent.Indexes.filter(
filterVal => filterVal.name === resp.INDEX_NAME
).length > 0
) {
indexInfo = ent.Indexes.find(
filterVal => filterVal.name === resp.INDEX_NAME
)!;
} else {
indexInfo.columns = [] as IndexColumnInfo[];
indexInfo.name = resp.INDEX_NAME;
indexInfo.isUnique = resp.UNIQUENESS === "UNIQUE";
indexInfo.isPrimaryKey = resp.ISPRIMARYKEY === 1;
ent.Indexes.push(indexInfo);
}
indexColumnInfo.name = resp.COLUMN_NAME;
indexInfo.columns.push(indexColumnInfo);
});
});
// entities.forEach(ent => {
// response
// .filter(filterVal => filterVal.TABLE_NAME === ent.tsEntityName)
// .forEach(resp => {
// let indexInfo: IndexInfo = {} as IndexInfo;
// const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo;
// if (
// ent.Indexes.filter(
// filterVal => filterVal.name === resp.INDEX_NAME
// ).length > 0
// ) {
// indexInfo = ent.Indexes.find(
// filterVal => filterVal.name === resp.INDEX_NAME
// )!;
// } else {
// indexInfo.columns = [] as IndexColumnInfo[];
// indexInfo.name = resp.INDEX_NAME;
// indexInfo.isUnique = resp.UNIQUENESS === "UNIQUE";
// indexInfo.isPrimaryKey = resp.ISPRIMARYKEY === 1;
// ent.Indexes.push(indexInfo);
// }
// indexColumnInfo.name = resp.COLUMN_NAME;
// indexInfo.columns.push(indexColumnInfo);
// });
// });
return entities;
// return entities;
}
public async GetRelations(entities: EntityInfo[]): Promise<EntityInfo[]> {

View File

@ -401,69 +401,71 @@ export default class PostgresDriver extends AbstractDriver {
}
public async GetIndexesFromEntity(
entities: EntityInfo[],
entities: Entity[],
schema: string
): Promise<EntityInfo[]> {
const response: {
tablename: string;
indexname: string;
columnname: string;
is_unique: number;
is_primary_key: number;
}[] = (await this.Connection.query(`SELECT
c.relname AS tablename,
i.relname as indexname,
f.attname AS columnname,
CASE
WHEN ix.indisunique = true THEN 1
ELSE 0
END AS is_unique,
CASE
WHEN ix.indisprimary='true' THEN 1
ELSE 0
END AS is_primary_key
FROM pg_attribute f
JOIN pg_class c ON c.oid = f.attrelid
JOIN pg_type t ON t.oid = f.atttypid
LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_index AS ix ON f.attnum = ANY(ix.indkey) and c.oid = f.attrelid and c.oid = ix.indrelid
LEFT JOIN pg_class AS i ON ix.indexrelid = i.oid
WHERE c.relkind = 'r'::char
AND n.nspname in (${schema})
AND f.attnum > 0
AND i.oid<>0
ORDER BY c.relname,f.attname;`)).rows;
entities.forEach(ent => {
response
.filter(filterVal => filterVal.tablename === ent.tsEntityName)
.forEach(resp => {
let indexInfo: IndexInfo = {} as IndexInfo;
const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo;
if (
ent.Indexes.filter(
filterVal => filterVal.name === resp.indexname
).length > 0
) {
indexInfo = ent.Indexes.find(
filterVal => filterVal.name === resp.indexname
)!;
} else {
indexInfo.columns = [] as IndexColumnInfo[];
indexInfo.name = resp.indexname;
indexInfo.isUnique = resp.is_unique === 1;
indexInfo.isPrimaryKey = resp.is_primary_key === 1;
ent.Indexes.push(indexInfo);
}
indexColumnInfo.name = resp.columnname;
if (resp.is_primary_key === 0) {
indexInfo.isPrimaryKey = false;
}
indexInfo.columns.push(indexColumnInfo);
});
});
): Promise<Entity[]> {
throw new Error();
// TODO: Remove
// const response: {
// tablename: string;
// indexname: string;
// columnname: string;
// is_unique: number;
// is_primary_key: number;
// }[] = (await this.Connection.query(`SELECT
// c.relname AS tablename,
// i.relname as indexname,
// f.attname AS columnname,
// CASE
// WHEN ix.indisunique = true THEN 1
// ELSE 0
// END AS is_unique,
// CASE
// WHEN ix.indisprimary='true' THEN 1
// ELSE 0
// END AS is_primary_key
// FROM pg_attribute f
// JOIN pg_class c ON c.oid = f.attrelid
// JOIN pg_type t ON t.oid = f.atttypid
// LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum
// LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
// LEFT JOIN pg_index AS ix ON f.attnum = ANY(ix.indkey) and c.oid = f.attrelid and c.oid = ix.indrelid
// LEFT JOIN pg_class AS i ON ix.indexrelid = i.oid
// WHERE c.relkind = 'r'::char
// AND n.nspname in (${schema})
// AND f.attnum > 0
// AND i.oid<>0
// ORDER BY c.relname,f.attname;`)).rows;
// entities.forEach(ent => {
// response
// .filter(filterVal => filterVal.tablename === ent.tsEntityName)
// .forEach(resp => {
// let indexInfo: IndexInfo = {} as IndexInfo;
// const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo;
// if (
// ent.Indexes.filter(
// filterVal => filterVal.name === resp.indexname
// ).length > 0
// ) {
// indexInfo = ent.Indexes.find(
// filterVal => filterVal.name === resp.indexname
// )!;
// } else {
// indexInfo.columns = [] as IndexColumnInfo[];
// indexInfo.name = resp.indexname;
// indexInfo.isUnique = resp.is_unique === 1;
// indexInfo.isPrimaryKey = resp.is_primary_key === 1;
// ent.Indexes.push(indexInfo);
// }
// indexColumnInfo.name = resp.columnname;
// if (resp.is_primary_key === 0) {
// indexInfo.isPrimaryKey = false;
// }
// indexInfo.columns.push(indexColumnInfo);
// });
// });
return entities;
// return entities;
}
public async GetRelations(

View File

@ -42,6 +42,8 @@ export default class SqliteDriver extends AbstractDriver {
}
ret.push({
columns: [],
indices: [],
relations: [],
sqlName: val.tbl_name,
tscName: val.tbl_name
});
@ -217,62 +219,62 @@ export default class SqliteDriver extends AbstractDriver {
// return entities;
}
public async GetIndexesFromEntity(
entities: EntityInfo[]
): Promise<EntityInfo[]> {
await Promise.all(
entities.map(async ent => {
const response = await this.ExecQuery<{
seq: number;
name: string;
unique: number;
origin: string;
partial: number;
}>(`PRAGMA index_list('${ent.tsEntityName}');`);
await Promise.all(
response.map(async resp => {
const indexColumnsResponse = await this.ExecQuery<{
seqno: number;
cid: number;
name: string;
}>(`PRAGMA index_info('${resp.name}');`);
indexColumnsResponse.forEach(element => {
let indexInfo: IndexInfo = {} as IndexInfo;
const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo;
if (
ent.Indexes.filter(filterVal => {
return filterVal.name === resp.name;
}).length > 0
) {
indexInfo = ent.Indexes.find(
filterVal => filterVal.name === resp.name
)!;
} else {
indexInfo.columns = [] as IndexColumnInfo[];
indexInfo.name = resp.name;
indexInfo.isUnique = resp.unique === 1;
ent.Indexes.push(indexInfo);
}
indexColumnInfo.name = element.name;
if (
indexColumnsResponse.length === 1 &&
indexInfo.isUnique
) {
ent.Columns.filter(
v => v.tsName === indexColumnInfo.name
).forEach(v => {
// eslint-disable-next-line no-param-reassign
v.options.unique = true;
});
}
indexInfo.columns.push(indexColumnInfo);
});
})
);
})
);
public async GetIndexesFromEntity(entities: Entity[]): Promise<Entity[]> {
throw new Error();
// TODO: Remove
// await Promise.all(
// entities.map(async ent => {
// const response = await this.ExecQuery<{
// seq: number;
// name: string;
// unique: number;
// origin: string;
// partial: number;
// }>(`PRAGMA index_list('${ent.tsEntityName}');`);
// await Promise.all(
// response.map(async resp => {
// const indexColumnsResponse = await this.ExecQuery<{
// seqno: number;
// cid: number;
// name: string;
// }>(`PRAGMA index_info('${resp.name}');`);
// indexColumnsResponse.forEach(element => {
// let indexInfo: IndexInfo = {} as IndexInfo;
// const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo;
// if (
// ent.Indexes.filter(filterVal => {
// return filterVal.name === resp.name;
// }).length > 0
// ) {
// indexInfo = ent.Indexes.find(
// filterVal => filterVal.name === resp.name
// )!;
// } else {
// indexInfo.columns = [] as IndexColumnInfo[];
// indexInfo.name = resp.name;
// indexInfo.isUnique = resp.unique === 1;
// ent.Indexes.push(indexInfo);
// }
// indexColumnInfo.name = element.name;
// if (
// indexColumnsResponse.length === 1 &&
// indexInfo.isUnique
// ) {
// ent.Columns.filter(
// v => v.tsName === indexColumnInfo.name
// ).forEach(v => {
// // eslint-disable-next-line no-param-reassign
// v.options.unique = true;
// });
// }
// indexInfo.columns.push(indexColumnInfo);
// });
// })
// );
// })
// );
return entities;
// return entities;
}
public async GetRelations(entities: EntityInfo[]): Promise<EntityInfo[]> {

View File

@ -1,5 +1,5 @@
{{#*inline "Index"}}
@Index("{{name}}")
@Index("{{name}}",[{{#columns}}"{{.}}",{{/columns~}}],{ {{json options}} })
{{/inline}}
{{#*inline "Column"}}
{{#generated}}@PrimaryGeneratedColumn({ {{/generated}}{{^generated}}@Column({ {{#primary}}primary:{{primary}},{{/primary}}{{/generated}}{{json options}} })

View File

@ -7,7 +7,7 @@ export type Column = {
primary?: boolean;
generated?: true | "increment" | "uuid";
options: {
type: ColumnType;
type: ColumnType | string; // todo: remove ?
name: string;
length?: number;
width?: number;
@ -17,7 +17,7 @@ export type Column = {
precision?: number;
scale?: number;
unsigned?: boolean;
enum?: string[];
enum?: string; // string[];
array?: boolean; // ?
};
};

View File

@ -10,6 +10,6 @@ export type Entity = {
schema?: string;
columns: Column[];
relations?: Relation[];
indices?: Index[];
relations: Relation[];
indices: Index[];
};

View File

@ -1,5 +1,8 @@
export type Index = {
name?: string;
columns?: ((object?: any) => any[] | { [key: string]: number }) | string[];
unique?: boolean;
name: string;
columns: string[];
options: {
unique?: boolean;
};
primary?: boolean;
};