added rowid generation strategy option in column options;

This commit is contained in:
Zotov Dmitry 2019-02-25 21:29:01 +05:00
parent 7c83467ad4
commit f32a82d4a5
11 changed files with 98 additions and 16 deletions

View File

@ -63,7 +63,7 @@ services:
# cockroachdb
cockroachdb:
image: "cockroachdb/cockroach:v2.1.4"
image: "cockroachdb/cockroach:v2.1.5"
container_name: "typeorm-cockroachdb"
command: start --insecure
ports:

View File

@ -3,13 +3,14 @@ import {GeneratedMetadataArgs} from "../metadata-args/GeneratedMetadataArgs";
/**
* Marks a column to generate a value on entity insertion.
* There are two types of generation strategy - increment and uuid.
* There are three types of generation strategy - increment, uuid and rowid (cockroachdb only).
* Increment uses a number which increases by one on each insertion.
* Uuid generates a special UUID token.
* Rowid supports only in CockroachDB and uses `unique_rowid()` function
*
* Note, some databases do not support non-primary generation columns.
*/
export function Generated(strategy: "increment"|"uuid" = "increment"): Function {
export function Generated(strategy: "increment"|"uuid"|"rowid" = "increment"): Function {
return function (object: Object, propertyName: string) {
getMetadataArgsStorage().generations.push({

View File

@ -141,7 +141,7 @@ export function Column(typeOrOptions?: ((type?: any) => Function)|ColumnType|(Co
getMetadataArgsStorage().generations.push({
target: object.constructor,
propertyName: propertyName,
strategy: options.type === "uuid" ? "uuid" : "increment"
strategy: typeof options.generated === "string" ? options.generated : "increment"
} as GeneratedMetadataArgs);
}
}

View File

@ -67,7 +67,7 @@ export function PrimaryColumn(typeOrOptions?: ColumnType|ColumnOptions, options?
getMetadataArgsStorage().generations.push({
target: object.constructor,
propertyName: propertyName,
strategy: options.type === "uuid" ? "uuid" : "increment"
strategy: typeof options.generated === "string" ? options.generated : "increment"
} as GeneratedMetadataArgs);
}
};

View File

@ -23,20 +23,25 @@ export function PrimaryGeneratedColumn(strategy: "increment", options?: PrimaryG
*/
export function PrimaryGeneratedColumn(strategy: "uuid", options?: PrimaryGeneratedColumnUUIDOptions): Function;
/**
* Column decorator is used to mark a specific class property as a table column.
*/
export function PrimaryGeneratedColumn(strategy: "rowid", options?: PrimaryGeneratedColumnUUIDOptions): Function;
/**
* Column decorator is used to mark a specific class property as a table column.
* Only properties decorated with this decorator will be persisted to the database when entity be saved.
* This column creates an integer PRIMARY COLUMN with generated set to true.
*/
export function PrimaryGeneratedColumn(strategyOrOptions?: "increment"|"uuid"|PrimaryGeneratedColumnNumericOptions|PrimaryGeneratedColumnUUIDOptions,
export function PrimaryGeneratedColumn(strategyOrOptions?: "increment"|"uuid"|"rowid"|PrimaryGeneratedColumnNumericOptions|PrimaryGeneratedColumnUUIDOptions,
maybeOptions?: PrimaryGeneratedColumnNumericOptions|PrimaryGeneratedColumnUUIDOptions): Function {
// normalize parameters
const options: ColumnOptions = {};
let strategy: "increment"|"uuid";
let strategy: "increment"|"uuid"|"rowid";
if (strategyOrOptions) {
if (typeof strategyOrOptions === "string")
strategy = strategyOrOptions as "increment"|"uuid";
strategy = strategyOrOptions as "increment"|"uuid"|"rowid";
if (strategyOrOptions instanceof Object) {
strategy = "increment";
@ -51,8 +56,15 @@ export function PrimaryGeneratedColumn(strategyOrOptions?: "increment"|"uuid"|Pr
return function (object: Object, propertyName: string) {
// if column type is not explicitly set then determine it based on generation strategy
if (!options.type)
options.type = strategy === "increment" ? Number : "uuid";
if (!options.type) {
if (strategy === "increment") {
options.type = Number;
} else if (strategy === "uuid") {
options.type = "uuid";
} else if (strategy === "rowid") {
options.type = "int";
}
}
// explicitly set a primary and generated to column options
options.primary = true;

View File

@ -23,10 +23,10 @@ export interface ColumnCommonOptions {
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.
* Specifies if this column will use auto increment (sequence, generated identity, rowid).
* Note that in some databases only one column in entity can be marked as generated, and it must be a primary column.
*/
generated?: boolean;
generated?: boolean|"increment"|"uuid"|"rowid";
/**
* Specifies if column's value must be unique or not.

View File

@ -81,7 +81,7 @@ export interface EntitySchemaColumnOptions {
/**
* Specifies if this column will use AUTO_INCREMENT or not (e.g. generated number).
*/
generated?: true|"increment"|"uuid";
generated?: true|"increment"|"uuid"|"rowid";
/**
* Specifies if column's value must be unique or not.

View File

@ -16,6 +16,6 @@ export interface GeneratedMetadataArgs {
/**
* Generation strategy.
*/
readonly strategy: "uuid"|"increment";
readonly strategy: "uuid"|"increment"|"rowid";
}

View File

@ -261,7 +261,13 @@ export class EntityMetadataBuilder {
if (generated) {
column.isGenerated = true;
column.generationStrategy = generated.strategy;
column.type = generated.strategy === "increment" ? (column.type || Number) : "uuid";
if (generated.strategy === "uuid") {
column.type = "uuid";
} else if (generated.strategy === "rowid") {
column.type = "int";
} else {
column.type = column.type || Number;
}
column.build(this.connection);
this.computeEntityMetadataStep2(entityMetadata);
}

View File

@ -0,0 +1,23 @@
import {Generated} from "../../../../../src";
import {PrimaryColumn} from "../../../../../src";
import {PrimaryGeneratedColumn} from "../../../../../src";
import {Entity} from "../../../../../src";
import {Column} from "../../../../../src";
@Entity()
export class Person {
@PrimaryGeneratedColumn("rowid")
id: string;
@PrimaryColumn()
@Generated("rowid")
id2: string;
@PrimaryColumn({ generated: "rowid" })
id3: string;
@Column({ generated: "rowid" })
id4: string;
}

View File

@ -0,0 +1,40 @@
import "reflect-metadata";
import {closeTestingConnections, createTestingConnections} from "../../../utils/test-utils";
import {Connection} from "../../../../src/connection/Connection";
describe("database-schema > rowid-column", () => {
let connections: Connection[];
before(async () => connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
enabledDrivers: ["cockroachdb"],
dropSchema: true,
schemaCreate: true,
}));
after(() => closeTestingConnections(connections));
it("should create `rowid` generated column", () => Promise.all(connections.map(async connection => {
const queryRunner = connection.createQueryRunner();
const table = await queryRunner.getTable("person");
await queryRunner.release();
table!.findColumnByName("id")!.type.should.be.equal("int");
table!.findColumnByName("id")!.isGenerated.should.be.equal(true);
table!.findColumnByName("id")!.generationStrategy!.should.be.equal("rowid");
table!.findColumnByName("id2")!.type.should.be.equal("int");
table!.findColumnByName("id2")!.isGenerated.should.be.equal(true);
table!.findColumnByName("id2")!.generationStrategy!.should.be.equal("rowid");
table!.findColumnByName("id3")!.type.should.be.equal("int");
table!.findColumnByName("id3")!.isGenerated.should.be.equal(true);
table!.findColumnByName("id3")!.generationStrategy!.should.be.equal("rowid");
table!.findColumnByName("id4")!.type.should.be.equal("int");
table!.findColumnByName("id4")!.isGenerated.should.be.equal(true);
table!.findColumnByName("id4")!.generationStrategy!.should.be.equal("rowid");
})));
});