Skip to content

Commit 8cab7ce

Browse files
committed
feat!: Change the interface for how keys are defined in the table schema
BREAKING CHANGE: The old interface for defining keys in the table schema has been removed.
1 parent 277c16b commit 8cab7ce

25 files changed

+1158
-1175
lines changed

README.md

Lines changed: 168 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ This module extends the popular [`mysql`](https://www.npmjs.com/package/mysql) m
2525
+ [Migration Strategies](#migration-strategies)
2626
+ [Defining Table Schemas](#defining-table-schemas)
2727
+ [Column Types](#column-types)
28+
+ [Key Types](#key-types)
2829

2930
## Installation
3031

@@ -146,6 +147,7 @@ This module.
146147

147148
* [mysql-plus](#module_mysql-plus) ⇐ <code>mysql</code>
148149
* [~ColTypes](#module_mysql-plus..ColTypes)
150+
* [~KeyTypes](#module_mysql-plus..KeyTypes)
149151
* [~createPool(config)](#module_mysql-plus..createPool) ⇒ <code>[PoolPlus](#PoolPlus)</code>
150152
* [~queryCallback](#module_mysql-plus..queryCallback) : <code>function</code>
151153

@@ -172,6 +174,33 @@ const userTable = pool.defineTable('user', {
172174
```
173175

174176

177+
---
178+
179+
<a name="module_mysql-plus..KeyTypes"></a>
180+
181+
### mysql-plus~KeyTypes
182+
A namespace that provides the key type methods used to define keys.
183+
184+
**See**: [Key Types](#key-types)
185+
186+
**Example**:
187+
```js
188+
const mysql = require('mysql-plus');
189+
const pool = mysql.createPool(config);
190+
const userTable = pool.defineTable('user', {
191+
columns: {
192+
id: mysql.ColTypes.bigint().unsigned().notNull().primaryKey(),
193+
uid: mysql.ColTypes.varchar(32).notNull(),
194+
created: mysql.ColTypes.datetime(),
195+
},
196+
keys: [
197+
mysql.KeyTypes.uniqueIndex('uid'),
198+
mysql.KeyTypes.index('created'),
199+
],
200+
});
201+
```
202+
203+
175204
---
176205

177206
<a name="module_mysql-plus..createPool"></a>
@@ -237,6 +266,7 @@ and perform queries and transactions using promises.
237266
* [PoolPlus](#PoolPlus) ⇐ <code>Pool</code>
238267
* _instance_
239268
* [.ColTypes](#PoolPlus+ColTypes)
269+
* [.KeyTypes](#PoolPlus+KeyTypes)
240270
* [.raw(sql)](#PoolPlus+raw) ⇒ <code>Object</code>
241271
* [.basicTable(name)](#PoolPlus+basicTable) ⇒ <code>[MySQLTable](#MySQLTable)</code>
242272
* [.defineTable(name, schema, [migrationStrategy])](#PoolPlus+defineTable) ⇒ <code>[MySQLTable](#MySQLTable)</code>
@@ -271,6 +301,35 @@ const userTable = pool.defineTable('user', {
271301
```
272302

273303

304+
---
305+
306+
<a name="PoolPlus+KeyTypes"></a>
307+
308+
### poolPlus.KeyTypes
309+
A namespace that provides the column type methods used to define keys.
310+
The exact same thing as [`mysqlPlus.KeyTypes`](#module_mysql-plus..KeyTypes).
311+
Just here for convenience.
312+
313+
**See**: [Key Types](#key-types)
314+
315+
**Example**:
316+
```js
317+
const pool = mysql.createPool(config);
318+
const {ColTypes, KeyTypes} = pool;
319+
const userTable = pool.defineTable('user', {
320+
columns: {
321+
id: ColTypes.bigint().unsigned().notNull().primaryKey(),
322+
uid: ColTypes.varchar(32).notNull(),
323+
created: ColTypes.datetime(),
324+
},
325+
keys: [
326+
KeyTypes.uniqueIndex('uid'),
327+
KeyTypes.index('created'),
328+
],
329+
});
330+
```
331+
332+
274333
---
275334

276335
<a name="PoolPlus+raw"></a>
@@ -1043,8 +1102,8 @@ All defined tables will be dropped and recreated.
10431102
A schema is defined by a JavaScript object with certain properties. For `mysql-plus`, the schema properties can be broken down into four main types:
10441103

10451104
+ [Columns](#columns)
1105+
+ [Primary Key](#primary-key)
10461106
+ [Keys](#keys)
1047-
+ [Foreign Keys](#foreign-keys)
10481107
+ [Table Options](#table-options)
10491108

10501109
### Columns
@@ -1064,146 +1123,56 @@ Columns are defined using the `column` property which is an object where the key
10641123

10651124
See the [Column Types](#column-types) section for all possible column types and attributes that can be defined.
10661125

1067-
### Keys
1068-
1069-
The following properties can be used to define different types of keys:
1070-
1071-
+ [`primaryKey`](#primarykey--stringstring)
1072-
+ [`uniqueKeys`](#uniquekeys--arraystringstring)
1073-
+ [`indexes`](#indexes--arraystringstring)
1074-
+ [`spatialIndexes`](#spatialindexes--string)
1075-
1076-
Note that [column definitions](#columndefinition) allow these keys to be defined directly on the column. If that method of defining a key for a column is used, the key should not be defined again using one of these properties (otherwise it will be duplicated).
1077-
1078-
#### `primaryKey` : `string|string[]`
1079-
1080-
Used to define the table's primary key. Its value is the name of one or more columns that make up the primary key.
1081-
1082-
**Example:**
1083-
```js
1084-
// Single column primary key
1085-
{
1086-
primaryKey: 'id',
1087-
}
1088-
1089-
// Multi-column primary key
1090-
{
1091-
primaryKey: ['userID', 'videoID'],
1092-
}
1093-
```
1126+
### Primary Key
10941127

1095-
#### `uniqueKeys` : `Array.<string|string[]>`
1128+
`string|string[]`
10961129

1097-
Used to define the table's unique keys. Its value is an array where the elements are the names of one or more columns that make up a unique key.
1130+
The table’s primary key can be defined with the `primaryKey` property:
10981131

1099-
**Example:**
11001132
```js
11011133
{
1102-
uniqueKeys: [
1103-
'email', // Single column unique key
1104-
['a', 'b'], // Multi-column unique key
1105-
],
1134+
columns: {
1135+
id: pool.ColTypes.int().unsigned().notNull(),
1136+
name: pool.ColTypes.varchar(255).notNull(),
1137+
},
1138+
primaryKey: 'id'
11061139
}
11071140
```
11081141

1109-
#### `indexes` : `Array.<string|string[]>`
1110-
1111-
Used to define the table's indexes. Its value is an array where the elements are the names of one or more columns that make up an index.
1142+
An array can be used to define a multi-column primary key.
11121143

1113-
**Example:**
11141144
```js
11151145
{
1116-
indexes: [
1117-
'points', // Single column index
1118-
['a', 'b'], // Multi-column index
1119-
],
1120-
}
1121-
```
1122-
1123-
#### `spatialIndexes` : `string[]`
1124-
1125-
Used to define the table's spatial indexes. Its value is an array where the elements are the column name for each index.
1126-
1127-
Note that spatial indexes may each only have 1 column and they may only be defined for [geometry-type](https://dev.mysql.com/doc/refman/5.7/en/spatial-type-overview.html) columns.
1128-
1129-
**Example:**
1130-
```js
1131-
{
1132-
spatialIndexes: [
1133-
'coordinates',
1134-
'line',
1135-
],
1146+
columns: {
1147+
id: pool.ColTypes.int().unsigned().notNull(),
1148+
name: pool.ColTypes.varchar(255).notNull(),
1149+
},
1150+
primaryKey: ['id', 'name']
11361151
}
11371152
```
11381153

1139-
### Foreign Keys
1140-
1141-
Foreign keys are defined using the `foreignKeys` property, which is an object that maps column names to a reference table column. The reference table column can be specified with either an object or a shorthand string.
1142-
1143-
If an object, it should have the following properties:
1144-
1145-
+ `table` - The name of the reference table.
1146-
+ `column` - The name of the reference column in the reference table.
1147-
+ `onDelete` (optional) - One of: `RESTRICT`, `CASCADE`, `SET NULL`, `NO ACTION`, `SET DEFAULT`.
1148-
+ `onUpdate` (optional) - Same as `onDelete`.
1149-
1150-
Alternatively, a shorthand string that has the following form may be used:
1151-
1152-
```js
1153-
'<table>.<column> [reference_option]' // `[reference_option]` is optional
1154-
```
1154+
### Keys
11551155

1156-
**Example:**
1156+
Keys can be defined with the `keys` property, which is an array of [`KeyTypes`](#key-types):
11571157

11581158
```js
11591159
{
11601160
columns: {
1161-
id: /* ... */,
1162-
uid: /* ... */,
1163-
userID: /* ... */,
1164-
thingOne: /* ... */,
1165-
thingTwo: /* ... */,
1166-
},
1167-
1168-
foreignKeys: {
1169-
// String shorthand
1170-
id: 'other_table.id', // shorthand for {table: 'other_table', column: 'id'}
1171-
1172-
uid: 'other_table.uid CASCADE',
1173-
// shorthand for {table: 'other_table', column: 'uid', onDelete: 'CASCADE', onUpdate: 'CASCADE'}
1174-
1175-
// Object reference with ON DELETE and ON UPDATE options
1176-
userID: {
1177-
table: 'user',
1178-
column: 'id',
1179-
onDelete: 'CASCADE',
1180-
onUpdate: 'NO ACTION',
1181-
},
1182-
1183-
// Multi-column foreign key (uses comma-separated column names)
1184-
'thingOne, thingTwo': {
1185-
table: 'thing_table',
1186-
column: ['one', 'two'],
1187-
},
1161+
id: pool.ColTypes.int().unsigned().notNull(),
1162+
accountID: pool.ColTypes.int().unsigned().notNull(),
1163+
email: pool.ColTypes.varchar(255).notNull(),
1164+
location: pool.ColTypes.point().notNull(),
11881165
},
1166+
keys: [
1167+
pool.KeyTypes.index('accountID'),
1168+
pool.KeyTypes.uniqueIndex('email'),
1169+
pool.KeyTypes.spatialIndex('location'),
1170+
pool.KeyTypes.foreignKey('accountID').references('account', 'id'),
1171+
]
11891172
}
11901173
```
11911174

1192-
**Note:** Foreign key definitions don't define keys, but [_constraints_](https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_foreign_key_constraint). When defining foreign key constraints, the columns that make up the constraints should also be keys.
1193-
1194-
Keys required for the example above:
1195-
```js
1196-
{
1197-
primaryKey: 'id',
1198-
uniqueKeys: [
1199-
'uid',
1200-
'userID',
1201-
],
1202-
indexes: [
1203-
['thingOne', 'thingTwo'],
1204-
],
1205-
}
1206-
```
1175+
See the [Key Types](#key-types) section for information on the different types of keys that can be defined.
12071176

12081177
### Table Options
12091178

@@ -1418,3 +1387,84 @@ Compatible types:
14181387
+ `multilinestring`
14191388
+ `multipolygon`
14201389
+ `geometrycollection`
1390+
1391+
## Key Types
1392+
1393+
[`mysql.KeyTypes`](#module_mysql-plus..KeyTypes) and [`pool.KeyTypes`](#PoolPlus+KeyTypes) both expose the following methods for defining table keys:
1394+
1395+
+ `index(columnName [, ...otherColumns])` - Creates a regular [index](https://dev.mysql.com/doc/en/create-index.html)
1396+
+ `uniqueIndex(columnName [, ...otherColumns])` - Creates a [unique index](https://dev.mysql.com/doc/en/create-index.html#create-index-unique)
1397+
+ `spatialIndex(columnName)` - Creates a [spatial index](https://dev.mysql.com/doc/en/create-index.html#create-index-spatial)
1398+
+ `foreignKey(columnName [, ...otherColumns])` - Creates a [foreign key constraint](https://dev.mysql.com/doc/en/create-table-foreign-keys.html)
1399+
1400+
**Example:**
1401+
```js
1402+
{
1403+
keys: [
1404+
pool.KeyTypes.index('accountID'),
1405+
pool.KeyTypes.uniqueIndex('email'),
1406+
pool.KeyTypes.spatialIndex('location'),
1407+
pool.KeyTypes.foreignKey('accountID').references('account', 'id'),
1408+
1409+
// Multi-column keys
1410+
pool.KeyTypes.uniqueIndex('accountID', 'email'),
1411+
pool.KeyTypes.foreignKey('userID', 'accountID').references('user', ['id', 'accountID']),
1412+
]
1413+
}
1414+
```
1415+
1416+
All key types have a `name` method that can be used to customize the key’s name (helpful if you need to use an [index hint](https://dev.mysql.com/doc/en/index-hints.html) in a query):
1417+
1418+
```js
1419+
{
1420+
keys: [
1421+
pool.KeyTypes.index('accountID').name('account_key'),
1422+
pool.KeyTypes.uniqueIndex('email').name('email_key'),
1423+
pool.KeyTypes.spatialIndex('location').name('location_key'),
1424+
pool.KeyTypes.foreignKey('accountID').references('account', 'id').name('account_foreign_key'),
1425+
]
1426+
}
1427+
```
1428+
1429+
### Foreign Keys
1430+
1431+
Foreign keys have the following additional methods:
1432+
1433+
+ `references(tableName, columns)` - Sets the name of the reference table (`string`) and the referenced columns (`string|Array<string>`)
1434+
+ `onDelete(action)` - Sets the foreign key’s `ON DELETE` action, where `action` is one of: `RESTRICT`, `CASCADE`, `SET NULL`, `NO ACTION`
1435+
+ `onUpdate(action)` - Sets the foreign key’s `ON UPDATE` action (with the same options as `onDelete`)
1436+
+ `cascade()` - Short for: `.onDelete('CASCADE').onUpdate('CASCADE')`
1437+
1438+
**Example:**
1439+
```js
1440+
{
1441+
columns: {
1442+
id: /* ... */,
1443+
uid: /* ... */,
1444+
userID: /* ... */,
1445+
thingOne: /* ... */,
1446+
thingTwo: /* ... */,
1447+
},
1448+
keys: [
1449+
KeyTypes.foreignKey('id').references('other_table', 'id'),
1450+
KeyTypes.foreignKey('uid').references('other_table', 'uid').cascade(),
1451+
KeyTypes.foreignKey('userID').references('user', 'id').onDelete('CASCADE').onUpdate('SET NULL'),
1452+
KeyTypes.foreignKey('thingOne', 'thingTwo').references('thing_table', ['one', 'two']),
1453+
]
1454+
}
1455+
```
1456+
1457+
**Note:** Foreign keys don't define indexes, but [_constraints_](https://dev.mysql.com/doc/en/glossary.html#glos_foreign_key_constraint). When defining foreign keys, the columns used in the key should also have an index.
1458+
1459+
Indexes required for the example above:
1460+
1461+
```js
1462+
{
1463+
primaryKey: 'id',
1464+
keys: [
1465+
KeyTypes.uniqueIndex('uid'),
1466+
KeyTypes.uniqueIndex('userID'),
1467+
KeyTypes.index('thingOne', 'thingTwo'),
1468+
]
1469+
}
1470+
```

0 commit comments

Comments
 (0)