Skip to content

Commit c68b244

Browse files
committed
[CONJS-341] Support charset + collation combination in connection options #337
1 parent 956d461 commit c68b244

File tree

3 files changed

+123
-3
lines changed

3 files changed

+123
-3
lines changed

lib/config/connection-options.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ class ConnectionOptions {
6666
this.debug = !!this.logger.network;
6767

6868
if (opts.charset && typeof opts.charset === 'string') {
69+
if (opts.collation && typeof opts.collation === 'string') {
70+
// charset AND collation
71+
this.collation = Collations.fromCharsetAndName(opts.charset.toLowerCase(), opts.collation.toUpperCase());
72+
if (this.collation === undefined) throw new RangeError("Unknown collation '" + opts.collation + "' with charset '" + opts.charset + "'");
73+
}
6974
this.collation = Collations.fromCharset(opts.charset.toLowerCase());
7075
if (this.collation === undefined) {
7176
this.collation = Collations.fromName(opts.charset.toUpperCase());

lib/const/collations.js

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,60 @@ class Collation {
2525
return charsets[index];
2626
}
2727

28-
static fromName(name) {
28+
static fromCharsetAndName(charset, name) {
2929
for (let i = 0; i < charsets.length; i++) {
3030
let collation = charsets[i];
3131
if (collation && collation.name === name) {
32-
return collation;
32+
if (collation.name.startsWith('UTF8MB3_') || charset === 'utf8mb3') {
33+
if (collation.charset === 'utf8' && collation.maxLength === 3)
34+
return collation;
35+
} else if (collation.name.startsWith('UTF8MB4_') || charset === 'utf8mb4' || charset === 'utf8') {
36+
if (collation.charset === 'utf8' && collation.maxLength === 4)
37+
return collation;
38+
} else if (collation.charset === charset) return collation;
3339
}
3440
}
41+
3542
// for compatibility and not found, replace UTF8_ by UTF8MB4_
3643
const nameWithMb4 = name.replace('UTF8_', 'UTF8MB4_');
3744
for (let i = 0; i < charsets.length; i++) {
3845
let collation = charsets[i];
3946
if (collation && collation.name === nameWithMb4) {
40-
return collation;
47+
if (collation.name.startsWith('UTF8MB3_') || charset === 'utf8mb3') {
48+
if (collation.charset === 'utf8' && collation.maxLength === 3)
49+
return collation;
50+
} else if (collation.name.startsWith('UTF8MB4_') || charset === 'utf8mb4' || charset === 'utf8') {
51+
if (collation.charset === 'utf8' && collation.maxLength === 4)
52+
return collation;
53+
} else if (collation.charset === charset) return collation;
4154
}
4255
}
4356

4457
return undefined;
4558
}
59+
60+
static fromName(name) {
61+
let fallback;
62+
for (let i = 0; i < charsets.length; i++) {
63+
let collation = charsets[i];
64+
if (collation && collation.name === name) {
65+
if (collation.charset === 'utf8' && collation.maxLength === 4) return collation;
66+
if (!fallback) fallback = collation;
67+
}
68+
}
69+
if (fallback) return fallback;
70+
// for compatibility and not found, replace UTF8_ by UTF8MB4_
71+
const nameWithMb4 = name.replace('UTF8_', 'UTF8MB4_');
72+
for (let i = 0; i < charsets.length; i++) {
73+
let collation = charsets[i];
74+
if (collation && collation.name === nameWithMb4) {
75+
if (collation.charset === 'utf8' && collation.maxLength === 4) return collation;
76+
if (!fallback) fallback = collation;
77+
}
78+
}
79+
80+
return fallback;
81+
}
4682
}
4783

4884
// generated with query :

test/unit/const/collations.test.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,83 @@ describe.concurrent('collations', () => {
3030
test('fromIndex good index', () => {
3131
assert.equal(Collations.fromIndex(33).name, 'UTF8MB3_GENERAL_CI');
3232
});
33+
34+
test('fromName utf8mb4 default value', () => {
35+
const collation = Collations.fromName('UCA1400_AI_CI');
36+
assert.isDefined(collation);
37+
assert.equal(collation.name, 'UCA1400_AI_CI');
38+
assert.equal(collation.maxLength, 4);
39+
});
40+
41+
42+
test('fromCharsetAndName utf8mb4 with UCA1400_AI_CI', () => {
43+
const collation = Collations.fromCharsetAndName('utf8mb4', 'UCA1400_AI_CI');
44+
assert.isDefined(collation);
45+
assert.equal(collation.name, 'UCA1400_AI_CI');
46+
assert.equal(collation.maxLength, 4);
47+
});
48+
49+
test('fromCharsetAndName utf8mb3 with UCA1400_AI_CI', () => {
50+
const collation = Collations.fromCharsetAndName('utf8mb3', 'UCA1400_AI_CI');
51+
assert.isDefined(collation);
52+
assert.equal(collation.name, 'UCA1400_AI_CI');
53+
assert.equal(collation.maxLength, 3);
54+
});
55+
56+
test('fromCharsetAndName utf8 defaults to utf8mb4', () => {
57+
const collation = Collations.fromCharsetAndName('utf8', 'UCA1400_AI_CI');
58+
assert.isDefined(collation);
59+
assert.equal(collation.name, 'UCA1400_AI_CI');
60+
assert.equal(collation.maxLength, 4);
61+
});
62+
63+
test('fromCharsetAndName non-utf8 charset', () => {
64+
const collation = Collations.fromCharsetAndName('latin1', 'LATIN1_SWEDISH_CI');
65+
assert.isDefined(collation);
66+
assert.equal(collation.name, 'LATIN1_SWEDISH_CI');
67+
assert.equal(collation.charset, 'latin1');
68+
});
69+
70+
test('fromCharsetAndName unknown collation', () => {
71+
assert.isUndefined(Collations.fromCharsetAndName('utf8mb4', 'UNKNOWN_COLLATION'));
72+
});
73+
74+
test('fromCharsetAndName both charset and collation unknown', () => {
75+
assert.isUndefined(Collations.fromCharsetAndName('unknown', 'UNKNOWN_COLLATION'));
76+
});
77+
78+
test('fromCharsetAndName UTF8_ compatibility fallback to UTF8MB4_', () => {
79+
const collation = Collations.fromCharsetAndName('utf8mb4', 'UTF8_GENERAL_CI');
80+
assert.isDefined(collation);
81+
assert.equal(collation.name, 'UTF8MB4_GENERAL_CI');
82+
assert.equal(collation.maxLength, 4);
83+
});
84+
85+
test('fromCharsetAndName ucs2 with UCA1400_AI_CI', () => {
86+
const collation = Collations.fromCharsetAndName('ucs2', 'UCA1400_AI_CI');
87+
assert.isDefined(collation);
88+
assert.equal(collation.name, 'UCA1400_AI_CI');
89+
assert.equal(collation.charset, 'ucs2');
90+
});
91+
92+
test('fromCharsetAndName utf16 with UCA1400_AI_CI', () => {
93+
const collation = Collations.fromCharsetAndName('utf16', 'UCA1400_AI_CI');
94+
assert.isDefined(collation);
95+
assert.equal(collation.name, 'UCA1400_AI_CI');
96+
assert.equal(collation.charset, 'utf16');
97+
});
98+
99+
test('fromCharsetAndName utf8mb4 with UTF8MB4_UNICODE_CI', () => {
100+
const collation = Collations.fromCharsetAndName('utf8mb4', 'UTF8MB4_UNICODE_CI');
101+
assert.isDefined(collation);
102+
assert.equal(collation.name, 'UTF8MB4_UNICODE_CI');
103+
assert.equal(collation.maxLength, 4);
104+
});
105+
106+
test('fromCharsetAndName utf8mb3 with UTF8MB3_GENERAL_CI', () => {
107+
const collation = Collations.fromCharsetAndName('utf8mb3', 'UTF8MB3_GENERAL_CI');
108+
assert.isDefined(collation);
109+
assert.equal(collation.name, 'UTF8MB3_GENERAL_CI');
110+
assert.equal(collation.maxLength, 3);
111+
});
33112
});

0 commit comments

Comments
 (0)