This commit is contained in:
Umed Khudoiberdiev 2017-05-26 13:15:36 +05:00
parent eb51cb3ef3
commit 95eff0746c
13 changed files with 109 additions and 36 deletions

View File

@ -19,7 +19,6 @@ export function PrimaryGeneratedColumn(options?: ColumnOptions): Function {
if (!options) options = {} as ColumnOptions;
// check if there is no type in column options then set the int type - by default for auto generated column
if (!options.type)
options = Object.assign({type: "int"} as ColumnOptions, options);
// check if column is not nullable, because we cannot allow a primary key to be nullable

View File

@ -8,36 +8,36 @@ export interface ColumnOptions {
/**
* Column type. Must be one of the value from the ColumnTypes class.
*/
readonly type?: ColumnType;
type?: ColumnType;
/**
* Column name in the database.
*/
readonly name?: string;
name?: string;
/**
* Column type's length. Used only on some column types.
* For example type = "string" and length = "100" means that ORM will create a column with type varchar(100).
*/
readonly length?: string|number;
length?: string|number;
/**
* Indicates if this column is PRIMARY.
* Same can be achieved if @PrimaryColumn decorator will be used.
*/
readonly primary?: boolean;
primary?: boolean;
/**
* Specifies if this column will use auto increment (sequence, generated identity).
* Note that only one column in entity can be marked as generated, and it must be a primary column.
* (todo: create validation logic for this condition)
*/
readonly generated?: boolean;
generated?: boolean; // |"uuid"|"sequence";
/**
* Specifies if column's value must be unique or not.
*/
readonly unique?: boolean;
unique?: boolean;
/**
* Indicates if column's value can be set to NULL.
@ -47,43 +47,43 @@ export interface ColumnOptions {
/**
* Column comment.
*/
readonly comment?: string;
comment?: string;
/**
* Default database value.
*/
readonly default?: any;
default?: any;
/**
* The precision for a decimal (exact numeric) column (applies only for decimal column), which is the maximum
* number of digits that are stored for the values.
*/
readonly precision?: number;
precision?: number;
/**
* The scale for a decimal (exact numeric) column (applies only for decimal column), which represents the number
* of digits to the right of the decimal point and must not be greater than precision.
*/
readonly scale?: number;
scale?: number;
/**
* Indicates if this date column will contain a timezone.
* Used only for date-typed column types.
* Note that timezone option is not supported by all databases (only postgres for now).
*/
readonly timezone?: boolean;
timezone?: boolean;
/**
* Indicates if date object must be stored in given date's timezone.
* By default date is saved in UTC timezone.
* Works only with "datetime" columns.
*/
readonly localTimezone?: boolean;
localTimezone?: boolean;
/**
* Indicates if column's type will be set as a fixed-length data type.
* Works only with "string" columns.
*/
readonly fixedLength?: boolean;
fixedLength?: boolean;
}

View File

@ -8,7 +8,7 @@ export interface EntityOptions {
/**
* Specifies a default order by used for queries from this table when no explicit order by is specified.
*/
readonly orderBy?: OrderByCondition|((object: any) => OrderByCondition|any);
orderBy?: OrderByCondition|((object: any) => OrderByCondition|any);
/**
* Table's database engine type (like "InnoDB", "MyISAM", etc).
@ -16,11 +16,11 @@ export interface EntityOptions {
* If you update this value and table is already created, it will not change table's engine type.
* Note that not all databases support this option.
*/
readonly engine?: string;
engine?: string;
/**
* Specifies if this table will be skipped during schema synchronization.
*/
readonly skipSchemaSync?: boolean;
skipSchemaSync?: boolean;
}

View File

@ -6,13 +6,13 @@ export interface IndexOptions {
/**
* Indicates if this composite index must be unique or not.
*/
readonly unique?: boolean;
unique?: boolean;
/**
* If true, the index only references documents with the specified field.
* These indexes use less space but behave differently in some situations (particularly sorts).
* This option is only supported for mongodb database.
*/
readonly sparse?: boolean;
sparse?: boolean;
}

View File

@ -6,11 +6,11 @@ export interface JoinColumnOptions {
/**
* Name of the column.
*/
readonly name?: string;
name?: string;
/**
* Name of the column in the entity to which this column is referenced.
*/
readonly referencedColumnName?: string; // TODO rename to referencedColumn
referencedColumnName?: string; // TODO rename to referencedColumn
}

View File

@ -9,16 +9,16 @@ export interface JoinTableMultipleColumnsOptions {
* Name of the table that will be created to store values of the both tables (join table).
* By default is auto generated.
*/
readonly name?: string;
name?: string;
/**
* First column of the join table.
*/
readonly joinColumns?: JoinColumnOptions[];
joinColumns?: JoinColumnOptions[];
/**
* Second (inverse) column of the join table.
*/
readonly inverseJoinColumns?: JoinColumnOptions[];
inverseJoinColumns?: JoinColumnOptions[];
}

View File

@ -9,16 +9,16 @@ export interface JoinTableOptions {
* Name of the table that will be created to store values of the both tables (join table).
* By default is auto generated.
*/
readonly name?: string;
name?: string;
/**
* First column of the join table.
*/
readonly joinColumn?: JoinColumnOptions;
joinColumn?: JoinColumnOptions;
/**
* Second (inverse) column of the join table.
*/
readonly inverseJoinColumn?: JoinColumnOptions;
inverseJoinColumn?: JoinColumnOptions;
}

View File

@ -11,43 +11,43 @@ export interface RelationOptions {
* If set to true then it means that related object can be allowed to be inserted / updated / removed to the db.
* This is option a shortcut if you would like to set cascadeInsert, cascadeUpdate and cascadeRemove to true.
*/
readonly cascadeAll?: boolean;
cascadeAll?: boolean;
/**
* If set to true then it means that related object can be allowed to be inserted to the db.
*/
readonly cascadeInsert?: boolean;
cascadeInsert?: boolean;
/**
* If set to true then it means that related object can be allowed to be updated in the db.
*/
readonly cascadeUpdate?: boolean;
cascadeUpdate?: boolean;
/**
* If set to true then it means that related object can be allowed to be remove from the db.
*/
readonly cascadeRemove?: boolean;
cascadeRemove?: boolean;
/**
* Indicates if relation column value can be nullable or not.
*/
readonly nullable?: boolean;
nullable?: boolean;
/**
* Database cascade action on delete.
*/
readonly onDelete?: OnDeleteType;
onDelete?: OnDeleteType;
/**
* Indicates if this relation will be a primary key.
* Can be used only for many-to-one and owner one-to-one relations.
*/
readonly primary?: boolean;
primary?: boolean;
/**
* Set this relation to be lazy. Note: lazy relations are promises. When you call them they return promise
* which resolve relation result then. If your property's type is Promise then this relation is set to lazy automatically.
*/
readonly lazy?: boolean;
lazy?: boolean;
}

View File

@ -415,7 +415,7 @@ export class ColumnMetadata {
if (this.embeddedMetadata && this.embeddedMetadata.parentPropertyNames.length)
path = this.embeddedMetadata.parentPropertyNames.join(".") + ".";
if (this.referencedColumn)
if (this.referencedColumn && this.referencedColumn.propertyName !== this.propertyName)
path += this.referencedColumn.propertyName + ".";
return path + this.propertyName;

View File

@ -112,7 +112,10 @@ export class IndexMetadata {
}
}
// console.log("columnPropertyNames:", columnPropertyNames);
// console.log("this.entityMetadata.columns:", this.entityMetadata.columns);
const columns = this.entityMetadata.columns.filter(column => columnPropertyNames.indexOf(column.propertyPath) !== -1);
// console.log("columns:", columns);
this.entityMetadata.relations
.filter(relation => relation.isWithJoinColumn && columnPropertyNames.indexOf(relation.propertyName) !== -1)
.forEach(relation => columns.push(...relation.joinColumns));

View File

@ -0,0 +1,26 @@
import {Entity} from "../../../../src/decorator/entity/Entity";
import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn";
import {Column} from "../../../../src/decorator/columns/Column";
import {Index} from "../../../../src/decorator/Index";
import {OneToOne} from "../../../../src/decorator/relations/OneToOne";
import {JoinColumn} from "../../../../src/decorator/relations/JoinColumn";
import {User} from "./User";
@Entity()
@Index("table_index_userId_mid", (post: Item) => [post.userId, post.mid])
export class Item {
@PrimaryGeneratedColumn()
postId: number;
@OneToOne(type => User, users => users.userId)
@JoinColumn({ name: "userId" })
userData: User;
@Column({ type: "int"})
userId: number;
@Column({ type: "int" })
mid: number;
}

View File

@ -0,0 +1,14 @@
import {Entity} from "../../../../src/decorator/entity/Entity";
import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn";
import {Column} from "../../../../src/decorator/columns/Column";
@Entity()
export class User {
@PrimaryGeneratedColumn()
userId: number;
@Column()
name: string;
}

View File

@ -0,0 +1,31 @@
import "reflect-metadata";
import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
import {Connection} from "../../../src/connection/Connection";
import {Item} from "./entity/Item";
import {User} from "./entity/User";
describe("github issues > #495 Unable to set multi-column indices", () => {
let connections: Connection[];
before(async () => connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
schemaCreate: true,
dropSchemaOnConnection: true,
}));
beforeEach(() => reloadTestingDatabases(connections));
after(() => closeTestingConnections(connections));
it("should successfully create indices and save an object", () => Promise.all(connections.map(async connection => {
const user = new User();
user.name = "stonecold";
const item = new Item();
item.userData = user;
item.mid = 1;
await connection.manager.save(user);
await connection.manager.save(item);
})));
});