• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

typeorm / typeorm / 15089093306

17 May 2025 09:03PM UTC coverage: 50.109% (-26.2%) from 76.346%
15089093306

Pull #11437

github

naorpeled
add comment about vector <#>
Pull Request #11437: feat(postgres): support vector data type

5836 of 12767 branches covered (45.71%)

Branch coverage included in aggregate %.

16 of 17 new or added lines in 4 files covered. (94.12%)

6283 existing lines in 64 files now uncovered.

12600 of 24025 relevant lines covered (52.45%)

28708.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.55
/src/schema-builder/table/Table.ts
1
import { TableColumn } from "./TableColumn"
6✔
2
import { TableIndex } from "./TableIndex"
6✔
3
import { TableForeignKey } from "./TableForeignKey"
6✔
4
import { Driver } from "../../driver/Driver"
5
import { TableOptions } from "../options/TableOptions"
6
import { EntityMetadata } from "../../metadata/EntityMetadata"
7
import { TableUtils } from "../util/TableUtils"
6✔
8
import { TableUnique } from "./TableUnique"
6✔
9
import { TableCheck } from "./TableCheck"
6✔
10
import { TableExclusion } from "./TableExclusion"
6✔
11

12
/**
13
 * Table in the database represented in this class.
14
 */
15
export class Table {
6✔
16
    readonly "@instanceof" = Symbol.for("Table")
38,518✔
17

18
    // -------------------------------------------------------------------------
19
    // Public Properties
20
    // -------------------------------------------------------------------------
21

22
    /**
23
     * Database name that this table resides in if it applies.
24
     */
25
    database?: string
26

27
    /**
28
     * Schema name that this table resides in if it applies.
29
     */
30
    schema?: string
31

32
    /**
33
     * May contain database name, schema name and table name, unless they're the current database.
34
     *
35
     * E.g. myDB.mySchema.myTable
36
     */
37
    name: string
38

39
    /**
40
     * Table columns.
41
     */
42
    columns: TableColumn[] = []
38,518✔
43

44
    /**
45
     * Table indices.
46
     */
47
    indices: TableIndex[] = []
38,518✔
48

49
    /**
50
     * Table foreign keys.
51
     */
52
    foreignKeys: TableForeignKey[] = []
38,518✔
53

54
    /**
55
     * Table unique constraints.
56
     */
57
    uniques: TableUnique[] = []
38,518✔
58

59
    /**
60
     * Table check constraints.
61
     */
62
    checks: TableCheck[] = []
38,518✔
63

64
    /**
65
     * Table exclusion constraints.
66
     */
67
    exclusions: TableExclusion[] = []
38,518✔
68

69
    /**
70
     * Indicates if table was just created.
71
     * This is needed, for example to check if we need to skip primary keys creation
72
     * for new tables.
73
     */
74
    justCreated: boolean = false
38,518✔
75

76
    /**
77
     * Enables Sqlite "WITHOUT ROWID" modifier for the "CREATE TABLE" statement
78
     */
79
    withoutRowid?: boolean = false
38,518✔
80

81
    /**
82
     * Table engine.
83
     */
84
    engine?: string
85

86
    /**
87
     * Table comment. Not supported by all database types.
88
     */
89
    comment?: string
90

91
    // -------------------------------------------------------------------------
92
    // Constructor
93
    // -------------------------------------------------------------------------
94

95
    constructor(options?: TableOptions) {
96
        if (options) {
38,518✔
97
            this.database = options.database
37,825✔
98
            this.schema = options.schema
37,825✔
99
            this.name = options.name
37,825✔
100

101
            if (options.columns)
37,825✔
102
                this.columns = options.columns.map(
35,849✔
103
                    (column) => new TableColumn(column),
115,774✔
104
                )
105

106
            if (options.indices)
37,825✔
107
                this.indices = options.indices.map(
35,565✔
108
                    (index) => new TableIndex(index),
17,022✔
109
                )
110

111
            if (options.foreignKeys)
37,825✔
112
                this.foreignKeys = options.foreignKeys.map(
8,701✔
113
                    (foreignKey) =>
114
                        new TableForeignKey({
249✔
115
                            ...foreignKey,
116
                            referencedDatabase:
117
                                foreignKey?.referencedDatabase ||
482✔
118
                                options.database,
119
                            referencedSchema:
120
                                foreignKey?.referencedSchema || options.schema,
448✔
121
                        }),
122
                )
123

124
            if (options.uniques)
37,825✔
125
                this.uniques = options.uniques.map(
35,547✔
126
                    (unique) => new TableUnique(unique),
7,888✔
127
                )
128

129
            if (options.checks)
37,825✔
130
                this.checks = options.checks.map(
35,541✔
131
                    (check) => new TableCheck(check),
649✔
132
                )
133

134
            if (options.exclusions)
37,825✔
135
                this.exclusions = options.exclusions.map(
35,535✔
136
                    (exclusion) => new TableExclusion(exclusion),
122✔
137
                )
138

139
            if (options.justCreated !== undefined)
37,825✔
140
                this.justCreated = options.justCreated
8,677✔
141

142
            if (options.withoutRowid) this.withoutRowid = options.withoutRowid
37,825✔
143

144
            this.engine = options.engine
37,825✔
145

146
            this.comment = options.comment
37,825✔
147
        }
148
    }
149

150
    // -------------------------------------------------------------------------
151
    // Accessors
152
    // -------------------------------------------------------------------------
153

154
    get primaryColumns(): TableColumn[] {
155
        return this.columns.filter((column) => column.isPrimary)
518✔
156
    }
157

158
    // -------------------------------------------------------------------------
159
    // Public Methods
160
    // -------------------------------------------------------------------------
161

162
    /**
163
     * Clones this table to a new table with all properties cloned.
164
     */
165
    clone(): Table {
166
        return new Table({
8,677✔
167
            schema: this.schema,
168
            database: this.database,
169
            name: this.name,
170
            columns: this.columns.map((column) => column.clone()),
30,714✔
171
            indices: this.indices.map((constraint) => constraint.clone()),
7,230✔
172
            foreignKeys: this.foreignKeys.map((constraint) =>
173
                constraint.clone(),
225✔
174
            ),
175
            uniques: this.uniques.map((constraint) => constraint.clone()),
2,822✔
176
            checks: this.checks.map((constraint) => constraint.clone()),
253✔
177
            exclusions: this.exclusions.map((constraint) => constraint.clone()),
47✔
178
            justCreated: this.justCreated,
179
            withoutRowid: this.withoutRowid,
180
            engine: this.engine,
181
            comment: this.comment,
182
        })
183
    }
184

185
    /**
186
     * Add column and creates its constraints.
187
     */
188
    addColumn(column: TableColumn): void {
189
        this.columns.push(column)
83✔
190
    }
191

192
    /**
193
     * Remove column and its constraints.
194
     */
195
    removeColumn(column: TableColumn): void {
196
        const foundColumn = this.columns.find((c) => c.name === column.name)
226✔
197
        if (foundColumn)
98✔
198
            this.columns.splice(this.columns.indexOf(foundColumn), 1)
98✔
199
    }
200

201
    /**
202
     * Adds unique constraint.
203
     */
204
    addUniqueConstraint(uniqueConstraint: TableUnique): void {
205
        this.uniques.push(uniqueConstraint)
18✔
206
        if (uniqueConstraint.columnNames.length === 1) {
18✔
207
            const uniqueColumn = this.columns.find(
4✔
208
                (column) => column.name === uniqueConstraint.columnNames[0],
8✔
209
            )
210
            if (uniqueColumn) uniqueColumn.isUnique = true
4✔
211
        }
212
    }
213

214
    /**
215
     * Removes unique constraint.
216
     */
217
    removeUniqueConstraint(removedUnique: TableUnique): void {
218
        const foundUnique = this.uniques.find(
29✔
219
            (unique) => unique.name === removedUnique.name,
40✔
220
        )
221
        if (foundUnique) {
29✔
222
            this.uniques.splice(this.uniques.indexOf(foundUnique), 1)
29✔
223
            if (foundUnique.columnNames.length === 1) {
29✔
224
                const uniqueColumn = this.columns.find(
10✔
225
                    (column) => column.name === foundUnique.columnNames[0],
20✔
226
                )
227
                if (uniqueColumn) uniqueColumn.isUnique = false
10!
228
            }
229
        }
230
    }
231

232
    /**
233
     * Adds check constraint.
234
     */
235
    addCheckConstraint(checkConstraint: TableCheck): void {
236
        this.checks.push(checkConstraint)
31✔
237
    }
238

239
    /**
240
     * Removes check constraint.
241
     */
242
    removeCheckConstraint(removedCheck: TableCheck): void {
243
        const foundCheck = this.checks.find(
22✔
244
            (check) => check.name === removedCheck.name,
22✔
245
        )
246
        if (foundCheck) {
22✔
247
            this.checks.splice(this.checks.indexOf(foundCheck), 1)
22✔
248
        }
249
    }
250

251
    /**
252
     * Adds exclusion constraint.
253
     */
254
    addExclusionConstraint(exclusionConstraint: TableExclusion): void {
255
        this.exclusions.push(exclusionConstraint)
4✔
256
    }
257

258
    /**
259
     * Removes exclusion constraint.
260
     */
261
    removeExclusionConstraint(removedExclusion: TableExclusion): void {
262
        const foundExclusion = this.exclusions.find(
3✔
263
            (exclusion) => exclusion.name === removedExclusion.name,
3✔
264
        )
265
        if (foundExclusion) {
3✔
266
            this.exclusions.splice(this.exclusions.indexOf(foundExclusion), 1)
3✔
267
        }
268
    }
269

270
    /**
271
     * Adds foreign keys.
272
     */
273
    addForeignKey(foreignKey: TableForeignKey): void {
274
        this.foreignKeys.push(foreignKey)
17,577✔
275
    }
276

277
    /**
278
     * Removes foreign key.
279
     */
280
    removeForeignKey(removedForeignKey: TableForeignKey): void {
281
        const fk = this.foreignKeys.find(
65✔
282
            (foreignKey) => foreignKey.name === removedForeignKey.name,
75✔
283
        )
284
        if (fk) this.foreignKeys.splice(this.foreignKeys.indexOf(fk), 1)
65✔
285
    }
286

287
    /**
288
     * Adds index.
289
     */
290
    addIndex(index: TableIndex, isMysql: boolean = false): void {
62✔
291
        this.indices.push(index)
62✔
292

293
        // in Mysql unique indices and unique constraints are the same thing
294
        // if index is unique and have only one column, we mark this column as unique
295
        if (index.columnNames.length === 1 && index.isUnique && isMysql) {
62!
UNCOV
296
            const column = this.columns.find(
×
UNCOV
297
                (c) => c.name === index.columnNames[0],
×
298
            )
UNCOV
299
            if (column) column.isUnique = true
×
300
        }
301
    }
302

303
    /**
304
     * Removes index.
305
     */
306
    removeIndex(tableIndex: TableIndex, isMysql: boolean = false): void {
71✔
307
        const index = this.indices.find(
71✔
308
            (index) => index.name === tableIndex.name,
73✔
309
        )
310
        if (index) {
71✔
311
            this.indices.splice(this.indices.indexOf(index), 1)
71✔
312

313
            // in Mysql unique indices and unique constraints are the same thing
314
            // if index is unique and have only one column, we move `unique` attribute from its column
315
            if (index.columnNames.length === 1 && index.isUnique && isMysql) {
71!
UNCOV
316
                const column = this.columns.find(
×
UNCOV
317
                    (c) => c.name === index.columnNames[0],
×
318
                )
UNCOV
319
                if (column)
×
UNCOV
320
                    column.isUnique = this.indices.some(
×
321
                        (ind) =>
322
                            ind.columnNames.length === 1 &&
×
323
                            ind.columnNames[0] === column.name &&
324
                            !!index.isUnique,
325
                    )
326
            }
327
        }
328
    }
329

330
    findColumnByName(name: string): TableColumn | undefined {
331
        return this.columns.find((column) => column.name === name)
8,035✔
332
    }
333

334
    /**
335
     * Returns all column indices.
336
     */
337
    findColumnIndices(column: TableColumn): TableIndex[] {
338
        return this.indices.filter((index) => {
185✔
339
            return !!index.columnNames.find(
78✔
340
                (columnName) => columnName === column.name,
78✔
341
            )
342
        })
343
    }
344

345
    /**
346
     * Returns all column foreign keys.
347
     */
348
    findColumnForeignKeys(column: TableColumn): TableForeignKey[] {
349
        return this.foreignKeys.filter((foreignKey) => {
185✔
350
            return !!foreignKey.columnNames.find(
112✔
351
                (columnName) => columnName === column.name,
112✔
352
            )
353
        })
354
    }
355

356
    /**
357
     * Returns all column uniques.
358
     */
359
    findColumnUniques(column: TableColumn): TableUnique[] {
360
        return this.uniques.filter((unique) => {
185✔
361
            return !!unique.columnNames.find(
180✔
362
                (columnName) => columnName === column.name,
228✔
363
            )
364
        })
365
    }
366

367
    /**
368
     * Returns all column checks.
369
     */
370
    findColumnChecks(column: TableColumn): TableCheck[] {
UNCOV
371
        return this.checks.filter((check) => {
×
UNCOV
372
            return !!check.columnNames!.find(
×
UNCOV
373
                (columnName) => columnName === column.name,
×
374
            )
375
        })
376
    }
377

378
    // -------------------------------------------------------------------------
379
    // Static Methods
380
    // -------------------------------------------------------------------------
381

382
    /**
383
     * Creates table from a given entity metadata.
384
     */
385
    static create(entityMetadata: EntityMetadata, driver: Driver): Table {
386
        const database =
387
            entityMetadata.database === driver.database
26,858✔
388
                ? undefined
389
                : entityMetadata.database
390
        const schema =
391
            entityMetadata.schema === (driver.options as any).schema
26,858✔
392
                ? undefined
393
                : entityMetadata.schema
394

395
        const options: TableOptions = {
26,858✔
396
            database: entityMetadata.database,
397
            schema: entityMetadata.schema,
398
            name: driver.buildTableName(
399
                entityMetadata.tableName,
400
                schema,
401
                database,
402
            ),
403
            withoutRowid: entityMetadata.withoutRowid,
404
            engine: entityMetadata.engine,
405
            columns: entityMetadata.columns
406
                .filter((column) => column && !column.isVirtualProperty)
83,733✔
407
                .map((column) =>
408
                    TableUtils.createTableColumnOptions(column, driver),
83,715✔
409
                ),
410
            indices: entityMetadata.indices
411
                .filter((index) => index.synchronize === true)
9,946✔
412
                .map((index) => TableIndex.create(index)),
9,762✔
413
            uniques: entityMetadata.uniques.map((unique) =>
414
                TableUnique.create(unique),
5,054✔
415
            ),
416
            checks: entityMetadata.checks.map((check) =>
417
                TableCheck.create(check),
390✔
418
            ),
419
            exclusions: entityMetadata.exclusions.map((exclusion) =>
420
                TableExclusion.create(exclusion),
75✔
421
            ),
422
            comment: entityMetadata.comment,
423
        }
424

425
        return new Table(options)
26,858✔
426
    }
427
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc