-
-
Notifications
You must be signed in to change notification settings - Fork 6.2k
/
issue-3118.ts
174 lines (167 loc) · 8.17 KB
/
issue-3118.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import "reflect-metadata"
import "../../utils/test-setup"
import { expect } from "chai"
import { DataSource } from "../../../src/data-source/DataSource"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils"
import { GroupWithVeryLongName } from "./entity/GroupWithVeryLongName"
import { AuthorWithVeryLongName } from "./entity/AuthorWithVeryLongName"
import { PostWithVeryLongName } from "./entity/PostWithVeryLongName"
import { CategoryWithVeryLongName } from "./entity/CategoryWithVeryLongName"
/**
* @see https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
* "The system uses no more than NAMEDATALEN-1 bytes of an identifier; longer names can be
* written in commands, but they will be truncated. By default, NAMEDATALEN is 64 so the
* maximum identifier length is 63 bytes. If this limit is problematic, it can be raised
* by changing the NAMEDATALEN constant in src/include/pg_config_manual.h."
*/
describe("github issues > #3118 shorten alias names (for RDBMS with a limit) when they are longer than 63 characters", () => {
let connections: DataSource[]
before(
async () =>
(connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
enabledDrivers: [
"mysql",
"postgres",
"cockroachdb",
"sap",
"mariadb",
"mssql",
],
})),
)
beforeEach(() => reloadTestingDatabases(connections))
after(() => closeTestingConnections(connections))
it("should be able to load deeply nested entities, even with long aliases", () =>
Promise.all(
connections.map(async (connection) => {
const group = new GroupWithVeryLongName()
group.name = "La Pléiade"
await connection
.getRepository(GroupWithVeryLongName)
.save(group)
const authorFirstNames = [
"Pierre",
"Paul",
"Jacques",
"Jean",
"Rémy",
"Guillaume",
"Lazare",
"Étienne",
]
for (const authorFirstName of authorFirstNames) {
const author = new AuthorWithVeryLongName()
author.firstName = authorFirstName
author.groupWithVeryLongName = group
const post = new PostWithVeryLongName()
post.authorWithVeryLongName = author
const category = new CategoryWithVeryLongName()
category.postsWithVeryLongName = [post]
await connection
.getRepository(AuthorWithVeryLongName)
.save(author)
await connection
.getRepository(PostWithVeryLongName)
.save(post)
await connection
.getRepository(CategoryWithVeryLongName)
.save(category)
}
const [loadedCategory] = await connection.manager.find(
CategoryWithVeryLongName,
{
relations: [
"postsWithVeryLongName",
// before: used to generate a SELECT "AS" alias like `CategoryWithVeryLongName__postsWithVeryLongName__authorWithVeryLongName_firstName`
// now: `CaWiVeLoNa__poWiVeLoNa__auWiVeLoNa_firstName`, which is acceptable by Postgres (limit to 63 characters)
"postsWithVeryLongName.authorWithVeryLongName",
// before:
// used to generate a JOIN "AS" alias like :
// `CategoryWithVeryLongName__postsWithVeryLongName__authorWithVeryLongName_firstName`
// `CategoryWithVeryLongName__postsWithVeryLongName__authorWithVeryLongName__groupWithVeryLongName_name`
// which was truncated automatically by the RDBMS to :
// `CategoryWithVeryLongName__postsWithVeryLongName__authorWithVery`
// `CategoryWithVeryLongName__postsWithVeryLongName__authorWithVery`
// resulting in: `ERROR: table name "CategoryWithVeryLongName__postsWithVeryLongName__authorWithVery" specified more than once`
// now:
// `CaWiVeLoNa__poWiVeLoNa__auWiVeLoNa_firstName`
// `CaWiVeLoNa__poWiVeLoNa__auWiVeLoNa__grWiVeLoNa_name`
"postsWithVeryLongName.authorWithVeryLongName.groupWithVeryLongName",
],
},
)
expect(loadedCategory).not.to.be.null
expect(loadedCategory!.postsWithVeryLongName).not.to.be
.undefined
expect(loadedCategory!.postsWithVeryLongName).not.to.be.empty
expect(
loadedCategory!.postsWithVeryLongName[0]
.authorWithVeryLongName,
).not.to.be.undefined
expect(
loadedCategory!.postsWithVeryLongName[0]
.authorWithVeryLongName.firstName,
).to.be.oneOf(authorFirstNames)
expect(
loadedCategory!.postsWithVeryLongName[0]
.authorWithVeryLongName.groupWithVeryLongName.name,
).to.equal(group.name)
const loadedCategories = await connection.manager.find(
CategoryWithVeryLongName,
{
relations: [
"postsWithVeryLongName",
"postsWithVeryLongName.authorWithVeryLongName",
"postsWithVeryLongName.authorWithVeryLongName.groupWithVeryLongName",
],
},
)
expect(loadedCategories).to.be.an("array").that.is.not.empty
for (const loadedCategory of loadedCategories) {
expect(loadedCategory).not.to.be.null
expect(loadedCategory!.postsWithVeryLongName).not.to.be
.undefined
expect(loadedCategory!.postsWithVeryLongName).not.to.be
.empty
expect(
loadedCategory!.postsWithVeryLongName[0]
.authorWithVeryLongName,
).not.to.be.undefined
expect(
loadedCategory!.postsWithVeryLongName[0]
.authorWithVeryLongName.firstName,
).to.be.oneOf(authorFirstNames)
expect(
loadedCategory!.postsWithVeryLongName[0]
.authorWithVeryLongName.groupWithVeryLongName.name,
).to.equal(group.name)
}
}),
))
it("should shorten table names which exceed the max length", () =>
Promise.all(
connections.map(async (connection) => {
const shortName =
"cat_wit_ver_lon_nam_pos_wit_ver_lon_nam_pos_wit_ver_lon_nam"
const normalName =
"category_with_very_long_name_posts_with_very_long_name_post_with_very_long_name"
const { maxAliasLength } = connection.driver
const expectedTableName =
maxAliasLength &&
maxAliasLength > 0 &&
normalName.length > maxAliasLength
? shortName
: normalName
expect(
connection.entityMetadatas.some(
(em) => em.tableName === expectedTableName,
),
).to.be.true
}),
))
})