Skip to content

Commit 673fad7

Browse files
committed
feat: Add support for FULLTEXT indexes
1 parent 8cab7ce commit 673fad7

File tree

9 files changed

+176
-3
lines changed

9 files changed

+176
-3
lines changed

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1162,11 +1162,13 @@ Keys can be defined with the `keys` property, which is an array of [`KeyTypes`](
11621162
accountID: pool.ColTypes.int().unsigned().notNull(),
11631163
email: pool.ColTypes.varchar(255).notNull(),
11641164
location: pool.ColTypes.point().notNull(),
1165+
description: pool.ColTypes.text(),
11651166
},
11661167
keys: [
11671168
pool.KeyTypes.index('accountID'),
11681169
pool.KeyTypes.uniqueIndex('email'),
11691170
pool.KeyTypes.spatialIndex('location'),
1171+
pool.KeyTypes.fulltextIndex('description'),
11701172
pool.KeyTypes.foreignKey('accountID').references('account', 'id'),
11711173
]
11721174
}
@@ -1305,6 +1307,7 @@ Methods:
13051307

13061308
+ `charset(value)` - Sets the column's character set
13071309
+ `collate(value)` - Sets the column's collation
1310+
+ `fulltextIndex()` - Creates a [fulltext index](https://dev.mysql.com/doc/en/innodb-fulltext-index.html) for the column (excluding `enum` and `set` columns)
13081311

13091312
Compatible types:
13101313

@@ -1375,7 +1378,7 @@ Normally if the `DEFAULT` is unspecified, MySQL uses `CURRENT_TIMESTAMP` as the
13751378

13761379
Methods:
13771380

1378-
+ `spatialIndex()` - Creates a spatial index for the column
1381+
+ `spatialIndex()` - Creates a [spatial index](https://dev.mysql.com/doc/en/create-index.html#create-index-spatial) for the column
13791382

13801383
Compatible types:
13811384

@@ -1395,6 +1398,7 @@ Compatible types:
13951398
+ `index(columnName [, ...otherColumns])` - Creates a regular [index](https://dev.mysql.com/doc/en/create-index.html)
13961399
+ `uniqueIndex(columnName [, ...otherColumns])` - Creates a [unique index](https://dev.mysql.com/doc/en/create-index.html#create-index-unique)
13971400
+ `spatialIndex(columnName)` - Creates a [spatial index](https://dev.mysql.com/doc/en/create-index.html#create-index-spatial)
1401+
+ `fulltextIndex(columnName)` - Creates a [fulltext index](https://dev.mysql.com/doc/en/innodb-fulltext-index.html)
13981402
+ `foreignKey(columnName [, ...otherColumns])` - Creates a [foreign key constraint](https://dev.mysql.com/doc/en/create-table-foreign-keys.html)
13991403

14001404
**Example:**
@@ -1404,6 +1408,7 @@ Compatible types:
14041408
pool.KeyTypes.index('accountID'),
14051409
pool.KeyTypes.uniqueIndex('email'),
14061410
pool.KeyTypes.spatialIndex('location'),
1411+
pool.KeyTypes.fulltextIndex('description'),
14071412
pool.KeyTypes.foreignKey('accountID').references('account', 'id'),
14081413

14091414
// Multi-column keys
@@ -1421,6 +1426,7 @@ All key types have a `name` method that can be used to customize the key’s nam
14211426
pool.KeyTypes.index('accountID').name('account_key'),
14221427
pool.KeyTypes.uniqueIndex('email').name('email_key'),
14231428
pool.KeyTypes.spatialIndex('location').name('location_key'),
1429+
pool.KeyTypes.fulltextIndex('description').name('description_key'),
14241430
pool.KeyTypes.foreignKey('accountID').references('account', 'id').name('account_foreign_key'),
14251431
]
14261432
}

jsdoc2md/README.hbs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,13 @@ Keys can be defined with the `keys` property, which is an array of [`KeyTypes`](
203203
accountID: pool.ColTypes.int().unsigned().notNull(),
204204
email: pool.ColTypes.varchar(255).notNull(),
205205
location: pool.ColTypes.point().notNull(),
206+
description: pool.ColTypes.text(),
206207
},
207208
keys: [
208209
pool.KeyTypes.index('accountID'),
209210
pool.KeyTypes.uniqueIndex('email'),
210211
pool.KeyTypes.spatialIndex('location'),
212+
pool.KeyTypes.fulltextIndex('description'),
211213
pool.KeyTypes.foreignKey('accountID').references('account', 'id'),
212214
]
213215
}
@@ -346,6 +348,7 @@ Methods:
346348

347349
+ `charset(value)` - Sets the column's character set
348350
+ `collate(value)` - Sets the column's collation
351+
+ `fulltextIndex()` - Creates a [fulltext index](https://dev.mysql.com/doc/en/innodb-fulltext-index.html) for the column (excluding `enum` and `set` columns)
349352

350353
Compatible types:
351354

@@ -416,7 +419,7 @@ Normally if the `DEFAULT` is unspecified, MySQL uses `CURRENT_TIMESTAMP` as the
416419

417420
Methods:
418421

419-
+ `spatialIndex()` - Creates a spatial index for the column
422+
+ `spatialIndex()` - Creates a [spatial index](https://dev.mysql.com/doc/en/create-index.html#create-index-spatial) for the column
420423

421424
Compatible types:
422425

@@ -436,6 +439,7 @@ Compatible types:
436439
+ `index(columnName [, ...otherColumns])` - Creates a regular [index](https://dev.mysql.com/doc/en/create-index.html)
437440
+ `uniqueIndex(columnName [, ...otherColumns])` - Creates a [unique index](https://dev.mysql.com/doc/en/create-index.html#create-index-unique)
438441
+ `spatialIndex(columnName)` - Creates a [spatial index](https://dev.mysql.com/doc/en/create-index.html#create-index-spatial)
442+
+ `fulltextIndex(columnName)` - Creates a [fulltext index](https://dev.mysql.com/doc/en/innodb-fulltext-index.html)
439443
+ `foreignKey(columnName [, ...otherColumns])` - Creates a [foreign key constraint](https://dev.mysql.com/doc/en/create-table-foreign-keys.html)
440444

441445
**Example:**
@@ -445,6 +449,7 @@ Compatible types:
445449
pool.KeyTypes.index('accountID'),
446450
pool.KeyTypes.uniqueIndex('email'),
447451
pool.KeyTypes.spatialIndex('location'),
452+
pool.KeyTypes.fulltextIndex('description'),
448453
pool.KeyTypes.foreignKey('accountID').references('account', 'id'),
449454

450455
// Multi-column keys
@@ -462,6 +467,7 @@ All key types have a `name` method that can be used to customize the key’s nam
462467
pool.KeyTypes.index('accountID').name('account_key'),
463468
pool.KeyTypes.uniqueIndex('email').name('email_key'),
464469
pool.KeyTypes.spatialIndex('location').name('location_key'),
470+
pool.KeyTypes.fulltextIndex('description').name('description_key'),
465471
pool.KeyTypes.foreignKey('accountID').references('account', 'id').name('account_foreign_key'),
466472
]
467473
}

lib/ColumnDefinitions/TextColumnDefinition.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const ColumnDefinition = require('./ColumnDefinition');
55
class TextColumnDefinition extends ColumnDefinition {
66
constructor(type, m) {
77
super(type, m);
8+
this.$fulltextIndex = false;
89
this._charset = null;
910
this._collate = null;
1011
}
@@ -19,6 +20,11 @@ class TextColumnDefinition extends ColumnDefinition {
1920
return this;
2021
}
2122

23+
fulltextIndex() {
24+
this.$fulltextIndex = true;
25+
return this;
26+
}
27+
2228
$equals(columnDefinition, columnTableSchema) {
2329
if (!super.$equals(columnDefinition)) {
2430
return false;

lib/KeyDefinitions/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ const KeyDefinitions = {
2525
throwIfNoColumns(columns);
2626
return new IndexKeyDefinition('SPATIAL INDEX', 'sptl', columns);
2727
},
28+
fulltextIndex(...columns) {
29+
throwIfNoColumns(columns);
30+
return new IndexKeyDefinition('FULLTEXT INDEX', 'fltxt', columns);
31+
},
2832
foreignKey(...columns) {
2933
throwIfNoColumns(columns);
3034
return new ForeignKeyDefinition(columns);

lib/TableDefinition.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,10 @@ function createInternalSchema(schema, tableName) {
411411
const key = KeyDefinitions.spatialIndex(columnName);
412412
indexKeys[key.$name] = key;
413413
}
414+
if (column.$fulltextIndex) {
415+
const key = KeyDefinitions.fulltextIndex(columnName);
416+
indexKeys[key.$name] = key;
417+
}
414418
}
415419

416420
if (schema.primaryKey) {

lib/sqlToSchema.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ function generatePrimaryKeySchema(keySQL) {
163163
const rgxUniqueKey = /^\s*UNIQUE KEY `(\w+)` \((.*?)\)/;
164164
const rgxIndexKey = /^\s*KEY `(\w+)` \((.*?)\)/;
165165
const rgxSpatialKey = /^\s*SPATIAL KEY `(\w+)` \((.*?)\)/;
166+
const rgxFulltextKey = /^\s*FULLTEXT KEY `(\w+)` \((.*?)\)/;
166167
const rgxForeignKey =
167168
/\s*CONSTRAINT `(\w+)` FOREIGN KEY \(`(.*?)`\) REFERENCES `(\w+)` \(`(.*?)`\)(?: ON DELETE (RESTRICT|CASCADE|SET NULL|NO ACTION))?(?: ON UPDATE (RESTRICT|CASCADE|SET NULL|NO ACTION))?/;
168169

@@ -181,6 +182,10 @@ function generateKeySchema(keySQL) {
181182
return KeyDefinitions.spatialIndex(...columnsSQLToSchema(keyMatch[2])).name(keyMatch[1]);
182183
}
183184

185+
if ((keyMatch = rgxFulltextKey.exec(keySQL)) !== null) {
186+
return KeyDefinitions.fulltextIndex(...columnsSQLToSchema(keyMatch[2])).name(keyMatch[1]);
187+
}
188+
184189
if ((keyMatch = rgxForeignKey.exec(keySQL)) !== null) {
185190
const foreignKey = KeyDefinitions
186191
.foreignKey(...columnsSQLToSchema(keyMatch[2]))

test/integration/MySQLPlus.test.js

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ describe('MySQLPlus', function() {
2929
jdoc: ColTypes.json(),
3030
location: ColTypes.point().notNull().spatialIndex(),
3131
line: ColTypes.linestring(),
32+
description: ColTypes.text().fulltextIndex(),
3233
},
3334
keys: [
3435
KeyTypes.uniqueIndex('name', 'letter'),
@@ -52,12 +53,14 @@ describe('MySQLPlus', function() {
5253
' `jdoc` json DEFAULT NULL,\n' +
5354
' `location` point NOT NULL,\n' +
5455
' `line` linestring DEFAULT NULL,\n' +
56+
' `description` text,\n' +
5557
' PRIMARY KEY (`id`),\n' +
5658
' UNIQUE KEY `uniq_email` (`email`),\n' +
5759
' UNIQUE KEY `uniq_name_letter` (`name`,`letter`),\n' +
5860
' UNIQUE KEY `uniq_created` (`created`),\n' +
5961
' KEY `idx_letter` (`letter`),\n' +
60-
' SPATIAL KEY `sptl_location` (`location`)\n' +
62+
' SPATIAL KEY `sptl_location` (`location`),\n' +
63+
' FULLTEXT KEY `fltxt_description` (`description`)\n' +
6164
') ENGINE=InnoDB DEFAULT CHARSET=utf8';
6265

6366
const autoIncTableName = 'auto_inc_table';
@@ -345,6 +348,47 @@ describe('MySQLPlus', function() {
345348
' SPATIAL KEY `sptl_c` (`c`)\n' +
346349
') ENGINE=InnoDB DEFAULT CHARSET=utf8';
347350

351+
const fulltextIndexesTableName = 'fulltext_table';
352+
const fulltextIndexesTableSchema = {
353+
columns: {
354+
a: ColTypes.char(32).notNull(),
355+
b: ColTypes.varchar(255).notNull(),
356+
c: ColTypes.text().notNull(),
357+
},
358+
keys: [
359+
KeyTypes.fulltextIndex('a'),
360+
KeyTypes.fulltextIndex('b'),
361+
],
362+
};
363+
const fulltextIndexesTableExpectedSQL =
364+
'CREATE TABLE `fulltext_table` (\n' +
365+
' `a` char(32) NOT NULL,\n' +
366+
' `b` varchar(255) NOT NULL,\n' +
367+
' `c` text NOT NULL,\n' +
368+
' FULLTEXT KEY `fltxt_a` (`a`),\n' +
369+
' FULLTEXT KEY `fltxt_b` (`b`)\n' +
370+
') ENGINE=InnoDB DEFAULT CHARSET=utf8';
371+
372+
const fulltextIndexesTableMigragedSchema = {
373+
columns: {
374+
a: ColTypes.char(32).notNull(),
375+
b: ColTypes.varchar(255).notNull(),
376+
c: ColTypes.text().notNull(),
377+
},
378+
keys: [
379+
KeyTypes.fulltextIndex('a'),
380+
KeyTypes.fulltextIndex('c'),
381+
],
382+
};
383+
const fulltextIndexesTableMigratedExpectedSQL =
384+
'CREATE TABLE `fulltext_table` (\n' +
385+
' `a` char(32) NOT NULL,\n' +
386+
' `b` varchar(255) NOT NULL,\n' +
387+
' `c` text NOT NULL,\n' +
388+
' FULLTEXT KEY `fltxt_a` (`a`),\n' +
389+
' FULLTEXT KEY `fltxt_c` (`c`)\n' +
390+
') ENGINE=InnoDB DEFAULT CHARSET=utf8';
391+
348392
const foreignKeysTableName = 'fk_table';
349393
const foreignKeysTableSchema = {
350394
columns: {
@@ -567,6 +611,7 @@ describe('MySQLPlus', function() {
567611
pool.defineTable(uniqueKeysTableName, uniqueKeysTableSchema);
568612
pool.defineTable(indexesTableName, indexesTableSchema);
569613
pool.defineTable(spatialIndexesTableName, spatialIndexesTableSchema);
614+
pool.defineTable(fulltextIndexesTableName, fulltextIndexesTableSchema);
570615
pool.defineTable(foreignKeysTableName, foreignKeysTableSchema);
571616
pool.defineTable(optionsTableName, optionsTableSchema);
572617
pool.defineTable(textTableName, textTableSchema);
@@ -638,6 +683,13 @@ describe('MySQLPlus', function() {
638683
cbSpatial();
639684
});
640685

686+
const cbFulltext = cbManager.registerCallback();
687+
pool.query(`SHOW CREATE TABLE \`${fulltextIndexesTableName}\``, (err, result) => {
688+
if (err) throw err;
689+
result[0]['Create Table'].should.equal(fulltextIndexesTableExpectedSQL);
690+
cbFulltext();
691+
});
692+
641693
const cb8 = cbManager.registerCallback();
642694
pool.query(`SHOW CREATE TABLE \`${foreignKeysTableName}\``, (err, result) => {
643695
if (err) throw err;
@@ -691,6 +743,7 @@ describe('MySQLPlus', function() {
691743
pool.defineTable(uniqueKeysTableName, uniqueKeysTableSchema);
692744
pool.defineTable(indexesTableName, indexesTableSchema);
693745
pool.defineTable(spatialIndexesTableName, spatialIndexesTableSchema);
746+
pool.defineTable(fulltextIndexesTableName, fulltextIndexesTableSchema);
694747
pool.defineTable(foreignKeysTableName, foreignKeysTableSchema);
695748
pool.defineTable(optionsTableName, optionsTableSchema);
696749
pool.defineTable(textTableName, textTableSchema);
@@ -767,6 +820,13 @@ describe('MySQLPlus', function() {
767820
cbSpatial();
768821
});
769822

823+
const cbFulltext = cbManager.registerCallback();
824+
pool.query(`SHOW CREATE TABLE \`${fulltextIndexesTableName}\``, (err, result) => {
825+
if (err) throw err;
826+
result[0]['Create Table'].should.equal(fulltextIndexesTableExpectedSQL);
827+
cbFulltext();
828+
});
829+
770830
const cb8 = cbManager.registerCallback();
771831
pool.query(`SHOW CREATE TABLE \`${foreignKeysTableName}\``, (err, result) => {
772832
if (err) throw err;
@@ -820,6 +880,7 @@ describe('MySQLPlus', function() {
820880
pool.defineTable(uniqueKeysTableName, uniqueKeysTableSchema);
821881
pool.defineTable(indexesTableName, indexesTableSchema);
822882
pool.defineTable(spatialIndexesTableName, spatialIndexesTableSchema);
883+
pool.defineTable(fulltextIndexesTableName, fulltextIndexesTableSchema);
823884
pool.defineTable(foreignKeysTableName, foreignKeysTableSchema);
824885
pool.defineTable(optionsTableName, optionsTableSchema);
825886
pool.defineTable(textTableName, textTableSchema);
@@ -891,6 +952,13 @@ describe('MySQLPlus', function() {
891952
cbSpatial();
892953
});
893954

955+
const cbFulltext = cbManager.registerCallback();
956+
pool.query(`SHOW CREATE TABLE \`${fulltextIndexesTableName}\``, (err, result) => {
957+
if (err) throw err;
958+
result[0]['Create Table'].should.equal(fulltextIndexesTableExpectedSQL);
959+
cbFulltext();
960+
});
961+
894962
const cb8 = cbManager.registerCallback();
895963
pool.query(`SHOW CREATE TABLE \`${foreignKeysTableName}\``, (err, result) => {
896964
if (err) throw err;
@@ -943,6 +1011,7 @@ describe('MySQLPlus', function() {
9431011
pool.defineTable(uniqueKeysTableName, uniqueKeysTableMigragedSchema);
9441012
pool.defineTable(indexesTableName, indexesTableMigragedSchema);
9451013
pool.defineTable(spatialIndexesTableName, spatialIndexesTableMigragedSchema);
1014+
pool.defineTable(fulltextIndexesTableName, fulltextIndexesTableMigragedSchema);
9461015
pool.defineTable(foreignKeysTableName, foreignKeysTableMigratedSchema);
9471016
pool.defineTable(optionsTableName, optionsTableMigratedSchema);
9481017

@@ -1020,6 +1089,13 @@ describe('MySQLPlus', function() {
10201089
cbSpatial();
10211090
});
10221091

1092+
const cbFulltext = cbManager.registerCallback();
1093+
pool.query(`SHOW CREATE TABLE \`${fulltextIndexesTableName}\``, (err, result) => {
1094+
if (err) throw err;
1095+
result[0]['Create Table'].should.equal(fulltextIndexesTableMigratedExpectedSQL);
1096+
cbFulltext();
1097+
});
1098+
10231099
const cb8 = cbManager.registerCallback();
10241100
pool.query(`SHOW CREATE TABLE \`${foreignKeysTableName}\``, (err, result) => {
10251101
if (err) throw err;

test/unit/ColumnDefinitions.test.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,12 @@ describe('ColumnDefinitions', () => {
429429

430430
ColumnDefinitions.point().notNull().index().spatialIndex()
431431
.$toSQL().should.equal('point NOT NULL');
432+
433+
ColumnDefinitions.text().fulltextIndex()
434+
.$toSQL().should.equal('text');
435+
436+
ColumnDefinitions.longtext().notNull().index().fulltextIndex()
437+
.$toSQL().should.equal('longtext NOT NULL');
432438
});
433439

434440
it('should allow the columns to be defined as primary keys, but not change the SQL, except for forcing the column to be NOT NULL', () => {
@@ -500,6 +506,26 @@ describe('ColumnDefinitions', () => {
500506
.$toSQL().should.equal('char CHARACTER SET utf8 COLLATE utf8_general_ci');
501507
});
502508

509+
it('should be able to create fulltext indexes', () => {
510+
ColumnDefinitions.char(32).fulltextIndex()
511+
.$toSQL().should.equal('char(32)');
512+
513+
ColumnDefinitions.varchar(255).fulltextIndex()
514+
.$toSQL().should.equal('varchar(255)');
515+
516+
ColumnDefinitions.text().fulltextIndex()
517+
.$toSQL().should.equal('text');
518+
519+
ColumnDefinitions.tinytext().fulltextIndex()
520+
.$toSQL().should.equal('tinytext');
521+
522+
ColumnDefinitions.mediumtext().fulltextIndex()
523+
.$toSQL().should.equal('mediumtext');
524+
525+
ColumnDefinitions.longtext().fulltextIndex()
526+
.$toSQL().should.equal('longtext');
527+
});
528+
503529
});
504530

505531

0 commit comments

Comments
 (0)