feat(mysql): add support for MySQL 9 / MariaDB 12 (#11575)

This commit is contained in:
Lucian Mocanu 2025-09-17 09:08:31 +02:00 committed by GitHub
parent 3fac86b60e
commit 8b76e1af74
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
49 changed files with 751 additions and 586 deletions

View File

@ -0,0 +1,28 @@
[
{
"skip": false,
"name": "mysql",
"type": "mysql",
"connectorPackage": "mysql2",
"host": "localhost",
"port": 3306,
"username": "root",
"password": "admin",
"database": "test",
"legacySpatialSupport": false,
"logging": false
},
{
"skip": false,
"name": "mariadb",
"type": "mariadb",
"connectorPackage": "mysql2",
"host": "localhost",
"port": 3307,
"username": "root",
"password": "admin",
"database": "test",
"legacySpatialSupport": false,
"logging": false
}
]

View File

@ -103,7 +103,7 @@ jobs:
services:
mysql:
image: mysql:5.7.37
image: mysql:5.7.44
ports:
- "3306:3306"
env:
@ -112,7 +112,7 @@ jobs:
MYSQL_PASSWORD: "test"
MYSQL_DATABASE: "test"
mariadb:
image: mariadb:10.11.13
image: mariadb:10.6.22-jammy
ports:
- "3307:3306"
env:
@ -137,7 +137,49 @@ jobs:
- name: Coveralls Parallel
uses: coverallsapp/github-action@v2
with:
flag-name: mysql+mariadb-node:${{ inputs.node-version }}
flag-name: mysql_mariadb-node:${{ inputs.node-version }}
parallel: true
mysql_mariadb_latest:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:9.4.0
ports:
- "3306:3306"
env:
MYSQL_ROOT_PASSWORD: "admin"
MYSQL_USER: "test"
MYSQL_PASSWORD: "test"
MYSQL_DATABASE: "test"
mariadb:
image: mariadb:12.0.1-rc
ports:
- "3307:3306"
env:
MYSQL_ROOT_PASSWORD: "admin"
MYSQL_USER: "test"
MYSQL_PASSWORD: "test"
MYSQL_DATABASE: "test"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: "npm"
- uses: actions/download-artifact@v4
with:
name: build
path: build/
- run: npm ci
- run: cp .github/workflows/test/mysql-mariadb-latest.ormconfig.json ormconfig.json
- run: npx nyc npm run test:ci
- name: Coveralls Parallel
uses: coverallsapp/github-action@v2
with:
flag-name: mysql_mariadb_latest-node:${{ inputs.node-version }}
parallel: true
better-sqlite3:

View File

@ -531,11 +531,11 @@ createConnection({
+-------------+--------------+----------------------------+
| photo |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(100) | |
| description | text | |
| filename | varchar(255) | |
| views | int(11) | |
| views | int | |
| isPublished | boolean | |
+-------------+--------------+----------------------------+
```
@ -770,13 +770,13 @@ export class PhotoMetadata {
+-------------+--------------+----------------------------+
| photo_metadata |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| height | int(11) | |
| width | int(11) | |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| height | int | |
| width | int | |
| comment | varchar(255) | |
| compressed | boolean | |
| orientation | varchar(255) | |
| photoId | int(11) | FOREIGN KEY |
| photoId | int | FOREIGN KEY |
+-------------+--------------+----------------------------+
```
@ -1009,7 +1009,7 @@ export class Photo {
+-------------+--------------+----------------------------+
| author |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(255) | |
+-------------+--------------+----------------------------+
```
@ -1020,12 +1020,12 @@ export class Photo {
+-------------+--------------+----------------------------+
| photo |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(255) | |
| description | varchar(255) | |
| filename | varchar(255) | |
| isPublished | boolean | |
| authorId | int(11) | FOREIGN KEY |
| authorId | int | FOREIGN KEY |
+-------------+--------------+----------------------------+
```
@ -1075,8 +1075,8 @@ export class Photo {
+-------------+--------------+----------------------------+
| album_photos_photo_albums |
+-------------+--------------+----------------------------+
| album_id | int(11) | PRIMARY KEY FOREIGN KEY |
| photo_id | int(11) | PRIMARY KEY FOREIGN KEY |
| album_id | int | PRIMARY KEY FOREIGN KEY |
| photo_id | int | PRIMARY KEY FOREIGN KEY |
+-------------+--------------+----------------------------+
```

View File

@ -522,11 +522,11 @@ createConnection({
+-------------+--------------+----------------------------+
| photo |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(100) | |
| description | text | |
| filename | varchar(255) | |
| views | int(11) | |
| views | int | |
| isPublished | boolean | |
+-------------+--------------+----------------------------+
```
@ -757,13 +757,13 @@ export class PhotoMetadata {
+-------------+--------------+----------------------------+
| photo_metadata |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| height | int(11) | |
| width | int(11) | |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| height | int | |
| width | int | |
| comment | varchar(255) | |
| compressed | boolean | |
| orientation | varchar(255) | |
| photoId | int(11) | FOREIGN KEY |
| photoId | int | FOREIGN KEY |
+-------------+--------------+----------------------------+
```
@ -998,7 +998,7 @@ N:1/1:N 관계에서 소유자측은 항상 다대일(ManyToOne)이다. 즉 `@Ma
+-------------+--------------+----------------------------+
| author |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(255) | |
+-------------+--------------+----------------------------+
```
@ -1009,12 +1009,12 @@ N:1/1:N 관계에서 소유자측은 항상 다대일(ManyToOne)이다. 즉 `@Ma
+-------------+--------------+----------------------------+
| photo |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(255) | |
| description | varchar(255) | |
| filename | varchar(255) | |
| isPublished | boolean | |
| authorId | int(11) | FOREIGN KEY |
| authorId | int | FOREIGN KEY |
+-------------+--------------+----------------------------+
```
@ -1064,8 +1064,8 @@ export class Photo {
+-------------+--------------+----------------------------+
| album_photos_photo_albums |
+-------------+--------------+----------------------------+
| album_id | int(11) | PRIMARY KEY FOREIGN KEY |
| photo_id | int(11) | PRIMARY KEY FOREIGN KEY |
| album_id | int | PRIMARY KEY FOREIGN KEY |
| photo_id | int | PRIMARY KEY FOREIGN KEY |
+-------------+--------------+----------------------------+
```

View File

@ -1,8 +1,19 @@
services:
# mysql
mysql:
image: "mysql:5.7.37"
container_name: "typeorm-mysql"
mysql-5:
image: "mysql:5.7.44"
container_name: "typeorm-mysql-5"
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: "admin"
MYSQL_USER: "test"
MYSQL_PASSWORD: "test"
MYSQL_DATABASE: "test"
mysql-9:
image: "mysql:9.4.0"
container_name: "typeorm-mysql-9"
ports:
- "3306:3306"
environment:
@ -12,9 +23,20 @@ services:
MYSQL_DATABASE: "test"
# mariadb
mariadb:
image: "mariadb:10.11.13"
container_name: "typeorm-mariadb"
mariadb-10:
image: "mariadb:10.6.22-jammy"
container_name: "typeorm-mariadb-10"
ports:
- "3307:3306"
environment:
MYSQL_ROOT_PASSWORD: "admin"
MYSQL_USER: "test"
MYSQL_PASSWORD: "test"
MYSQL_DATABASE: "test"
mariadb-12:
image: "mariadb:12.0.1-rc"
container_name: "typeorm-mariadb-12"
ports:
- "3307:3306"
environment:
@ -24,11 +46,11 @@ services:
MYSQL_DATABASE: "test"
# postgres
postgres14:
postgres-14:
# postgis is postgres + PostGIS (only). If you need additional extensions,
# it's probably time to create a purpose-built image.
image: "postgis/postgis:14-3.5"
container_name: "typeorm-postgres14"
container_name: "typeorm-postgres-14"
ports:
- "5432:5432"
environment:
@ -37,11 +59,11 @@ services:
POSTGRES_DB: "test"
# postgres
postgres:
postgres-17:
# postgis is postgres + PostGIS (only). If you need additional extensions,
# it's probably time to create a purpose-built image.
image: "postgis/postgis:17-3.5"
container_name: "typeorm-postgres"
container_name: "typeorm-postgres-17"
ports:
- "5432:5432"
environment:

View File

@ -21,6 +21,7 @@ npm install mysql2
See [Data Source Options](../data-source/2-data-source-options.md) for the common data source options. You can use the data source types `mysql`, `mariadb` and `aurora-mysql` to connect to the respective databases.
- `connectorPackage` - The database client, either `mysql` or `mysql2`. If the specified client cannot be loaded, it will fall back to the alternative. (Current default: `mysql`)
- `url` - Connection url where the connection is performed. Please note that other data source options will override parameters set from url.
- `host` - Database host.
@ -33,8 +34,7 @@ See [Data Source Options](../data-source/2-data-source-options.md) for the commo
- `database` - Database name.
- `charset` - The charset for the connection. This is called "collation" in the SQL-level of MySQL
(like utf8_general_ci). If an SQL-level charset is specified (like utf8mb4), then the default collation for that charset is used. (Default: `UTF8_GENERAL_CI`).
- `charset` and `collation` - The charset/collation for the connection. If an SQL-level charset is specified (like utf8mb4) then the default collation for that charset is used.
- `timezone` - the timezone configured on the MySQL server. This is used to typecast server date/time
values to JavaScript Date object and vice versa. This can be `local`, `Z`, or an offset in the form

View File

@ -26,11 +26,11 @@ export class User {
This will create following database table:
```shell
```text
+-------------+--------------+----------------------------+
| user |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| firstName | varchar(255) | |
| lastName | varchar(255) | |
| isActive | boolean | |
@ -205,12 +205,6 @@ For example:
@Column("varchar", { length: 200 })
```
or
```typescript
@Column({ type: "int", width: 200 })
```
> Note about `bigint` type: `bigint` column type, used in SQL databases, doesn't fit into the regular `number` type and maps property to a `string` instead.
### `enum` column type
@ -393,7 +387,6 @@ List of available options in `ColumnOptions`:
You can change it by specifying your own name.
- `length: number` - Column type's length. For example if you want to create `varchar(150)` type you specify column type and length options.
- `width: number` - column type's display width. Used only for [MySQL integer types](https://dev.mysql.com/doc/refman/5.7/en/integer-types.html)
- `onUpdate: string` - `ON UPDATE` trigger. Used only in [MySQL](https://dev.mysql.com/doc/refman/5.7/en/timestamp-initialization.html).
- `nullable: boolean` - Makes column `NULL` or `NOT NULL` in the database. By default column is `nullable: false`.
- `update: boolean` - Indicates if column value is updated by "save" operation. If false, you'll be able to write this value only when you first time insert the object. Default value is `true`.
@ -406,7 +399,6 @@ List of available options in `ColumnOptions`:
- `precision: number` - The precision for a decimal (exact numeric) column (applies only for decimal column), which is the maximum
number of digits that are stored for the values. Used in some column types.
- `scale: number` - The scale for a decimal (exact numeric) column (applies only for decimal column), which represents the number of digits to the right of the decimal point and must not be greater than precision. Used in some column types.
- `zerofill: boolean` - Puts `ZEROFILL` attribute on to a numeric column. Used only in MySQL. If `true`, MySQL automatically adds the `UNSIGNED` attribute to this column.
- `unsigned: boolean` - Puts `UNSIGNED` attribute on to a numeric column. Used only in MySQL.
- `charset: string` - Defines a column character set. Not supported by all database types.
- `collation: string` - Defines a column collation.

View File

@ -133,11 +133,11 @@ export class Student {
All columns defined in the `Name` entity will be merged into `user`, `employee` and `student`:
```shell
```text
+-------------+--------------+----------------------------+
| user |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| nameFirst | varchar(255) | |
| nameLast | varchar(255) | |
| isActive | boolean | |
@ -146,16 +146,16 @@ All columns defined in the `Name` entity will be merged into `user`, `employee`
+-------------+--------------+----------------------------+
| employee |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| nameFirst | varchar(255) | |
| nameLast | varchar(255) | |
| salary | int(11) | |
| salary | int | |
+-------------+--------------+----------------------------+
+-------------+--------------+----------------------------+
| student |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| nameFirst | varchar(255) | |
| nameLast | varchar(255) | |
| faculty | varchar(255) | |

View File

@ -504,11 +504,11 @@ Now if you run your `index.ts`, a connection with the database will be initializ
+-------------+--------------+----------------------------+
| photo |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(100) | |
| description | text | |
| filename | varchar(255) | |
| views | int(11) | |
| views | int | |
| isPublished | boolean | |
+-------------+--------------+----------------------------+
```
@ -703,13 +703,13 @@ If you run the app, you'll see a newly generated table, and it will contain a co
+-------------+--------------+----------------------------+
| photo_metadata |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| height | int(11) | |
| width | int(11) | |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| height | int | |
| width | int | |
| comment | varchar(255) | |
| compressed | boolean | |
| orientation | varchar(255) | |
| photoId | int(11) | FOREIGN KEY |
| photoId | int | FOREIGN KEY |
+-------------+--------------+----------------------------+
```
@ -999,7 +999,7 @@ After you run the application, the ORM will create the `author` table:
+-------------+--------------+----------------------------+
| author |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(255) | |
+-------------+--------------+----------------------------+
```
@ -1010,12 +1010,12 @@ It will also modify the `photo` table, adding a new `author` column and creating
+-------------+--------------+----------------------------+
| photo |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(255) | |
| description | varchar(255) | |
| filename | varchar(255) | |
| isPublished | boolean | |
| authorId | int(11) | FOREIGN KEY |
| authorId | int | FOREIGN KEY |
+-------------+--------------+----------------------------+
```
@ -1067,8 +1067,8 @@ After you run the application, the ORM will create an **album_photos_photo_album
+-------------+--------------+----------------------------+
| album_photos_photo_albums |
+-------------+--------------+----------------------------+
| album_id | int(11) | PRIMARY KEY FOREIGN KEY |
| photo_id | int(11) | PRIMARY KEY FOREIGN KEY |
| album_id | int | PRIMARY KEY FOREIGN KEY |
| photo_id | int | PRIMARY KEY FOREIGN KEY |
+-------------+--------------+----------------------------+
```

View File

@ -134,7 +134,7 @@ export class User {
You can change it by specifying your own name.
- `length: string|number` - Column type's length. For example, if you want to create `varchar(150)` type
you specify column type and length options.
- `width: number` - column type's display width. Used only for [MySQL integer types](https://dev.mysql.com/doc/refman/5.7/en/integer-types.html)
- `width: number` - column type's display width. Used only for [MySQL integer types](https://dev.mysql.com/doc/refman/5.7/en/integer-types.html). _Deprecated_ in newer MySQL versions, will be removed from TypeORM in an upcoming version.
- `onUpdate: string` - `ON UPDATE` trigger. Used only in [MySQL](https://dev.mysql.com/doc/refman/5.7/en/timestamp-initialization.html).
- `nullable: boolean` - determines whether the column can become `NULL` or always has to be `NOT NULL`. By default column is `nullable: false`.
- `update: boolean` - Indicates if column value is updated by "save" operation. If false, you'll be able to write this value only when you first time insert the object.
@ -150,8 +150,7 @@ export class User {
- `scale: number` - The scale for a decimal (exact numeric) column (applies only for decimal column),
which represents the number of digits to the right of the decimal point and must not be greater than precision.
Used in some column types.
- `zerofill: boolean` - Puts `ZEROFILL` attribute on to a numeric column. Used only in MySQL.
If `true`, MySQL automatically adds the `UNSIGNED` attribute to this column.
- `zerofill: boolean` - Puts `ZEROFILL` attribute on to a numeric column. Used only in MySQL. If `true`, MySQL automatically adds the `UNSIGNED` attribute to this column. _Deprecated_ in newer MySQL versions, will be removed from TypeORM in an upcoming version. Use a character column and the `LPAD` function as suggested by MySQL.
- `unsigned: boolean` - Puts `UNSIGNED` attribute on to a numeric column. Used only in MySQL.
- `charset: string` - Defines a column character set. Not supported by all database types.
- `collation: string` - Defines a column collation.

View File

@ -50,11 +50,11 @@ The side you set `@JoinColumn` on, that side's table will contain a "relation id
This example will produce the following tables:
```shell
```text
+-------------+--------------+----------------------------+
| profile |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| gender | varchar(255) | |
| photo | varchar(255) | |
+-------------+--------------+----------------------------+
@ -62,9 +62,9 @@ This example will produce the following tables:
+-------------+--------------+----------------------------+
| user |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(255) | |
| profileId | int(11) | FOREIGN KEY |
| profileId | int | FOREIGN KEY |
+-------------+--------------+----------------------------+
```

View File

@ -46,19 +46,19 @@ Where you set `@ManyToOne` - its related entity will have "relation id" and fore
This example will produce following tables:
```shell
```text
+-------------+--------------+----------------------------+
| photo |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| url | varchar(255) | |
| userId | int(11) | FOREIGN KEY |
| userId | int | FOREIGN KEY |
+-------------+--------------+----------------------------+
+-------------+--------------+----------------------------+
| user |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(255) | |
+-------------+--------------+----------------------------+
```

View File

@ -51,18 +51,18 @@ You must put `@JoinTable` on one (owning) side of relation.
This example will produce following tables:
```shell
```text
+-------------+--------------+----------------------------+
| category |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(255) | |
+-------------+--------------+----------------------------+
+-------------+--------------+----------------------------+
| question |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| id | int | PRIMARY KEY AUTO_INCREMENT |
| title | varchar(255) | |
| text | varchar(255) | |
+-------------+--------------+----------------------------+
@ -70,8 +70,8 @@ This example will produce following tables:
+-------------+--------------+----------------------------+
| question_categories_category |
+-------------+--------------+----------------------------+
| questionId | int(11) | PRIMARY KEY FOREIGN KEY |
| categoryId | int(11) | PRIMARY KEY FOREIGN KEY |
| questionId | int | PRIMARY KEY FOREIGN KEY |
| categoryId | int | PRIMARY KEY FOREIGN KEY |
+-------------+--------------+----------------------------+
```

View File

@ -3,22 +3,26 @@
"skip": false,
"name": "mysql",
"type": "mysql",
"connectorPackage": "mysql2",
"host": "localhost",
"port": 3306,
"username": "root",
"password": "admin",
"database": "test",
"legacySpatialSupport": false,
"logging": false
},
{
"skip": false,
"name": "mariadb",
"type": "mariadb",
"connectorPackage": "mysql2",
"host": "localhost",
"port": 3307,
"username": "root",
"password": "admin",
"database": "test",
"legacySpatialSupport": false,
"logging": false
},
{

8
package-lock.json generated
View File

@ -64,7 +64,7 @@
"mongodb": "^6.15.0",
"mssql": "^11.0.1",
"mysql": "^2.18.1",
"mysql2": "^3.14.0",
"mysql2": "^3.14.2",
"nyc": "^17.1.0",
"oracledb": "^6.8.0",
"pg": "^8.14.1",
@ -11339,9 +11339,9 @@
}
},
"node_modules/mysql2": {
"version": "3.14.0",
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.0.tgz",
"integrity": "sha512-8eMhmG6gt/hRkU1G+8KlGOdQi2w+CgtNoD1ksXZq9gQfkfDsX4LHaBwTe1SY0Imx//t2iZA03DFnyYKPinxSRw==",
"version": "3.14.2",
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.2.tgz",
"integrity": "sha512-YD6mZMeoypmheHT6b2BrVmQFvouEpRICuvPIREulx2OvP1xAxxeqkMQqZSTBefv0PiOBKGYFa2zQtY+gf/4eQw==",
"dev": true,
"license": "MIT",
"dependencies": {

View File

@ -145,7 +145,7 @@
"mongodb": "^6.15.0",
"mssql": "^11.0.1",
"mysql": "^2.18.1",
"mysql2": "^3.14.0",
"mysql2": "^3.14.2",
"nyc": "^17.1.0",
"oracledb": "^6.8.0",
"pg": "^8.14.1",

View File

@ -1,25 +1,25 @@
import { getMetadataArgsStorage } from "../../globals"
import {
ColumnType,
SimpleColumnType,
SpatialColumnType,
UnsignedColumnType,
WithLengthColumnType,
WithPrecisionColumnType,
WithWidthColumnType,
} from "../../driver/types/ColumnTypes"
import { ColumnMetadataArgs } from "../../metadata-args/ColumnMetadataArgs"
import { ColumnCommonOptions } from "../options/ColumnCommonOptions"
import { SpatialColumnOptions } from "../options/SpatialColumnOptions"
import { ColumnWithLengthOptions } from "../options/ColumnWithLengthOptions"
import { ColumnNumericOptions } from "../options/ColumnNumericOptions"
import { ColumnEnumOptions } from "../options/ColumnEnumOptions"
import { ColumnEmbeddedOptions } from "../options/ColumnEmbeddedOptions"
import { EmbeddedMetadataArgs } from "../../metadata-args/EmbeddedMetadataArgs"
import { ColumnTypeUndefinedError } from "../../error/ColumnTypeUndefinedError"
import { ColumnHstoreOptions } from "../options/ColumnHstoreOptions"
import { ColumnWithWidthOptions } from "../options/ColumnWithWidthOptions"
import { getMetadataArgsStorage } from "../../globals"
import { ColumnMetadataArgs } from "../../metadata-args/ColumnMetadataArgs"
import { EmbeddedMetadataArgs } from "../../metadata-args/EmbeddedMetadataArgs"
import { GeneratedMetadataArgs } from "../../metadata-args/GeneratedMetadataArgs"
import { ColumnCommonOptions } from "../options/ColumnCommonOptions"
import { ColumnEmbeddedOptions } from "../options/ColumnEmbeddedOptions"
import { ColumnEnumOptions } from "../options/ColumnEnumOptions"
import { ColumnHstoreOptions } from "../options/ColumnHstoreOptions"
import { ColumnNumericOptions } from "../options/ColumnNumericOptions"
import { ColumnOptions } from "../options/ColumnOptions"
import { ColumnUnsignedOptions } from "../options/ColumnUnsignedOptions"
import { ColumnWithLengthOptions } from "../options/ColumnWithLengthOptions"
import { SpatialColumnOptions } from "../options/SpatialColumnOptions"
/**
* Column decorator is used to mark a specific class property as a table column. Only properties decorated with this
@ -65,8 +65,8 @@ export function Column(
* Only properties decorated with this decorator will be persisted to the database when entity be saved.
*/
export function Column(
type: WithWidthColumnType,
options?: ColumnCommonOptions & ColumnWithWidthOptions,
type: UnsignedColumnType,
options?: ColumnCommonOptions & ColumnUnsignedOptions,
): PropertyDecorator
/**

View File

@ -16,12 +16,19 @@ export interface ColumnNumericOptions {
/**
* Puts ZEROFILL attribute on to numeric column. Works only for MySQL.
* If you specify ZEROFILL for a numeric column, MySQL automatically adds the UNSIGNED attribute to the column
* If you specify ZEROFILL for a numeric column, MySQL automatically adds
* the UNSIGNED attribute to the column
* @deprecated MySQL deprecated and removed the ZEROFILL attribute. This
* will also be removed from TypeORM in an upcoming version. Use a character
* column and the `LPAD` function as suggested by MySQL or handle the
* formatting in the application layer.
*/
zerofill?: boolean
/**
* Puts UNSIGNED attribute on to numeric column. Works only for MySQL.
* @deprecated MySQL deprecated the UNSIGNED attribute for non-integer
* numeric types. This will also be removed from TypeORM in an upcoming version.
*/
unsigned?: boolean
}

View File

@ -25,6 +25,9 @@ export interface ColumnOptions extends ColumnCommonOptions {
/**
* Column type's display width. Used only on some column types in MySQL.
* For example, INT(4) specifies an INT with a display width of four digits.
* @deprecated No longer supported in newer MySQL versions, will be removed
* from TypeORM in an upcoming version. Use a character column and the
* `LPAD` function as suggested by MySQL
*/
width?: number
@ -105,6 +108,9 @@ export interface ColumnOptions extends ColumnCommonOptions {
/**
* Puts ZEROFILL attribute on to numeric column. Works only for MySQL.
* If you specify ZEROFILL for a numeric column, MySQL automatically adds the UNSIGNED attribute to this column
* @deprecated No longer supported in newer MySQL versions, will be removed
* from TypeORM in an upcoming version. Use a character column and the
* `LPAD` function as suggested by MySQL
*/
zerofill?: boolean

View File

@ -0,0 +1,30 @@
/**
* Options for columns that can define a length of the column type.
*/
export interface ColumnUnsignedOptions {
/**
* Column type's display width. Used only on some column types in MySQL.
* For example, INT(4) specifies an INT with a display width of four digits.
* @deprecated MySQL deprecated and removed display width for integer types,
* TypeORM will also remove it in an upcoming version. Use a character
* column and the `LPAD` function as suggested by MySQL or handle the
* formatting in the application layer.
*/
width?: number
/**
* Puts ZEROFILL attribute on to numeric column. Works only for MySQL.
* If you specify ZEROFILL for a numeric column, MySQL automatically adds
* the UNSIGNED attribute to this column
* @deprecated MySQL deprecated and removed the zerofill attribute. This
* will also be removed from TypeORM in an upcoming version. Use a character
* column and the `LPAD` function as suggested by MySQL or handle the
* formatting in the application layer.
*/
zerofill?: boolean
/**
* Puts UNSIGNED attribute on to numeric column. Works only for MySQL.
*/
unsigned?: boolean
}

View File

@ -1,21 +0,0 @@
/**
* Options for columns that can define a length of the column type.
*/
export interface ColumnWithWidthOptions {
/**
* Column type's display width. Used only on some column types in MySQL.
* For example, INT(4) specifies an INT with a display width of four digits.
*/
width?: number
/**
* Puts ZEROFILL attribute on to numeric column. Works only for MySQL.
* If you specify ZEROFILL for a numeric column, MySQL automatically adds the UNSIGNED attribute to this column
*/
zerofill?: boolean
/**
* Puts UNSIGNED attribute on to numeric column. Works only for MySQL.
*/
unsigned?: boolean
}

View File

@ -22,6 +22,9 @@ export interface PrimaryGeneratedColumnNumericOptions {
/**
* Puts ZEROFILL attribute on to numeric column. Works only for MySQL.
* If you specify ZEROFILL for a numeric column, MySQL automatically adds the UNSIGNED attribute to the column
* @deprecated No longer supported in newer MySQL versions, will be removed
* from TypeORM in an upcoming version. Use a character column and the
* `LPAD` function as suggested by MySQL
*/
zerofill?: boolean

View File

@ -1,29 +1,29 @@
import { ObjectLiteral } from "../../common/ObjectLiteral"
import { DataSource } from "../../data-source"
import { TypeORMError } from "../../error"
import { ColumnMetadata } from "../../metadata/ColumnMetadata"
import { EntityMetadata } from "../../metadata/EntityMetadata"
import { PlatformTools } from "../../platform/PlatformTools"
import { RdbmsSchemaBuilder } from "../../schema-builder/RdbmsSchemaBuilder"
import { Table } from "../../schema-builder/table/Table"
import { TableColumn } from "../../schema-builder/table/TableColumn"
import { TableForeignKey } from "../../schema-builder/table/TableForeignKey"
import { View } from "../../schema-builder/view/View"
import { ApplyValueTransformers } from "../../util/ApplyValueTransformers"
import { DateUtils } from "../../util/DateUtils"
import { InstanceChecker } from "../../util/InstanceChecker"
import { OrmUtils } from "../../util/OrmUtils"
import { Driver } from "../Driver"
import { DriverUtils } from "../DriverUtils"
import { ColumnType, UnsignedColumnType } from "../types/ColumnTypes"
import { CteCapabilities } from "../types/CteCapabilities"
import { AuroraMysqlQueryRunner } from "./AuroraMysqlQueryRunner"
import { ObjectLiteral } from "../../common/ObjectLiteral"
import { ColumnMetadata } from "../../metadata/ColumnMetadata"
import { DateUtils } from "../../util/DateUtils"
import { PlatformTools } from "../../platform/PlatformTools"
import { DataSource } from "../../data-source"
import { RdbmsSchemaBuilder } from "../../schema-builder/RdbmsSchemaBuilder"
import { AuroraMysqlConnectionOptions } from "./AuroraMysqlConnectionOptions"
import { MappedColumnTypes } from "../types/MappedColumnTypes"
import { ColumnType } from "../types/ColumnTypes"
import { DataTypeDefaults } from "../types/DataTypeDefaults"
import { TableColumn } from "../../schema-builder/table/TableColumn"
import { AuroraMysqlConnectionCredentialsOptions } from "./AuroraMysqlConnectionCredentialsOptions"
import { EntityMetadata } from "../../metadata/EntityMetadata"
import { OrmUtils } from "../../util/OrmUtils"
import { ApplyValueTransformers } from "../../util/ApplyValueTransformers"
import { MappedColumnTypes } from "../types/MappedColumnTypes"
import { ReplicationMode } from "../types/ReplicationMode"
import { TypeORMError } from "../../error"
import { Table } from "../../schema-builder/table/Table"
import { View } from "../../schema-builder/view/View"
import { TableForeignKey } from "../../schema-builder/table/TableForeignKey"
import { InstanceChecker } from "../../util/InstanceChecker"
import { UpsertType } from "../types/UpsertType"
import { AuroraMysqlConnectionCredentialsOptions } from "./AuroraMysqlConnectionCredentialsOptions"
import { AuroraMysqlConnectionOptions } from "./AuroraMysqlConnectionOptions"
import { AuroraMysqlQueryRunner } from "./AuroraMysqlQueryRunner"
/**
* Organizes communication with MySQL DBMS.
@ -181,10 +181,9 @@ export class AuroraMysqlDriver implements Driver {
]
/**
* Gets list of column data types that support length by a driver.
* Gets list of column data types that support unsigned by a driver.
*/
withWidthColumnTypes: ColumnType[] = [
"bit",
unsignedColumnTypes: UnsignedColumnType[] = [
"tinyint",
"smallint",
"mediumint",
@ -224,26 +223,6 @@ export class AuroraMysqlDriver implements Driver {
"real",
]
/**
* Gets list of column data types that supports UNSIGNED and ZEROFILL attributes.
*/
unsignedAndZerofillTypes: ColumnType[] = [
"int",
"integer",
"smallint",
"tinyint",
"mediumint",
"bigint",
"decimal",
"dec",
"numeric",
"fixed",
"float",
"double",
"double precision",
"real",
]
/**
* ORM has special columns and we need to know what database column types should be for those columns.
* Column types are driver dependant.

View File

@ -1,28 +1,28 @@
import { ObjectLiteral } from "../../common/ObjectLiteral"
import { TypeORMError } from "../../error"
import { QueryRunnerAlreadyReleasedError } from "../../error/QueryRunnerAlreadyReleasedError"
import { TransactionNotStartedError } from "../../error/TransactionNotStartedError"
import { ReadStream } from "../../platform/PlatformTools"
import { BaseQueryRunner } from "../../query-runner/BaseQueryRunner"
import { QueryResult } from "../../query-runner/QueryResult"
import { QueryRunner } from "../../query-runner/QueryRunner"
import { ObjectLiteral } from "../../common/ObjectLiteral"
import { TransactionNotStartedError } from "../../error/TransactionNotStartedError"
import { TableColumn } from "../../schema-builder/table/TableColumn"
import { TableIndexOptions } from "../../schema-builder/options/TableIndexOptions"
import { Table } from "../../schema-builder/table/Table"
import { TableCheck } from "../../schema-builder/table/TableCheck"
import { TableColumn } from "../../schema-builder/table/TableColumn"
import { TableExclusion } from "../../schema-builder/table/TableExclusion"
import { TableForeignKey } from "../../schema-builder/table/TableForeignKey"
import { TableIndex } from "../../schema-builder/table/TableIndex"
import { QueryRunnerAlreadyReleasedError } from "../../error/QueryRunnerAlreadyReleasedError"
import { View } from "../../schema-builder/view/View"
import { Query } from "../Query"
import { AuroraMysqlDriver } from "./AuroraMysqlDriver"
import { ReadStream } from "../../platform/PlatformTools"
import { OrmUtils } from "../../util/OrmUtils"
import { TableIndexOptions } from "../../schema-builder/options/TableIndexOptions"
import { TableUnique } from "../../schema-builder/table/TableUnique"
import { BaseQueryRunner } from "../../query-runner/BaseQueryRunner"
import { View } from "../../schema-builder/view/View"
import { Broadcaster } from "../../subscriber/Broadcaster"
import { ColumnType } from "../types/ColumnTypes"
import { TableCheck } from "../../schema-builder/table/TableCheck"
import { IsolationLevel } from "../types/IsolationLevel"
import { TableExclusion } from "../../schema-builder/table/TableExclusion"
import { TypeORMError } from "../../error"
import { MetadataTableType } from "../types/MetadataTableType"
import { InstanceChecker } from "../../util/InstanceChecker"
import { OrmUtils } from "../../util/OrmUtils"
import { Query } from "../Query"
import { ColumnType, UnsignedColumnType } from "../types/ColumnTypes"
import { IsolationLevel } from "../types/IsolationLevel"
import { MetadataTableType } from "../types/MetadataTableType"
import { AuroraMysqlDriver } from "./AuroraMysqlDriver"
/**
* Runs queries on a single mysql database connection.
@ -2137,14 +2137,16 @@ export class AuroraMysqlQueryRunner
// Unsigned columns are handled differently when it comes to width.
// Hence, we need to set the unsigned attribute before we check the width.
tableColumn.unsigned = tableColumn.zerofill
? true
: dbColumn["COLUMN_TYPE"].indexOf("unsigned") !== -1
tableColumn.zerofill =
dbColumn["COLUMN_TYPE"].includes("zerofill")
tableColumn.unsigned =
tableColumn.zerofill ||
dbColumn["COLUMN_TYPE"].includes("unsigned")
if (
this.driver.withWidthColumnTypes.indexOf(
tableColumn.type as ColumnType,
) !== -1
this.driver.unsignedColumnTypes.includes(
tableColumn.type as UnsignedColumnType,
)
) {
const width = dbColumn["COLUMN_TYPE"].substring(
dbColumn["COLUMN_TYPE"].indexOf("(") + 1,

View File

@ -1,32 +1,32 @@
import { Driver, ReturningType } from "../Driver"
import { ObjectLiteral } from "../../common/ObjectLiteral"
import { DataSource } from "../../data-source/DataSource"
import { TypeORMError } from "../../error"
import { ConnectionIsNotSetError } from "../../error/ConnectionIsNotSetError"
import { DriverPackageNotInstalledError } from "../../error/DriverPackageNotInstalledError"
import { DriverUtils } from "../DriverUtils"
import { CteCapabilities } from "../types/CteCapabilities"
import { MysqlQueryRunner } from "./MysqlQueryRunner"
import { ObjectLiteral } from "../../common/ObjectLiteral"
import { ColumnMetadata } from "../../metadata/ColumnMetadata"
import { DateUtils } from "../../util/DateUtils"
import { PlatformTools } from "../../platform/PlatformTools"
import { DataSource } from "../../data-source/DataSource"
import { RdbmsSchemaBuilder } from "../../schema-builder/RdbmsSchemaBuilder"
import { MysqlConnectionOptions } from "./MysqlConnectionOptions"
import { MappedColumnTypes } from "../types/MappedColumnTypes"
import { ColumnType } from "../types/ColumnTypes"
import { DataTypeDefaults } from "../types/DataTypeDefaults"
import { TableColumn } from "../../schema-builder/table/TableColumn"
import { MysqlConnectionCredentialsOptions } from "./MysqlConnectionCredentialsOptions"
import { EntityMetadata } from "../../metadata/EntityMetadata"
import { OrmUtils } from "../../util/OrmUtils"
import { ApplyValueTransformers } from "../../util/ApplyValueTransformers"
import { ReplicationMode } from "../types/ReplicationMode"
import { TypeORMError } from "../../error"
import { PlatformTools } from "../../platform/PlatformTools"
import { RdbmsSchemaBuilder } from "../../schema-builder/RdbmsSchemaBuilder"
import { Table } from "../../schema-builder/table/Table"
import { View } from "../../schema-builder/view/View"
import { TableColumn } from "../../schema-builder/table/TableColumn"
import { TableForeignKey } from "../../schema-builder/table/TableForeignKey"
import { VersionUtils } from "../../util/VersionUtils"
import { View } from "../../schema-builder/view/View"
import { ApplyValueTransformers } from "../../util/ApplyValueTransformers"
import { DateUtils } from "../../util/DateUtils"
import { InstanceChecker } from "../../util/InstanceChecker"
import { OrmUtils } from "../../util/OrmUtils"
import { VersionUtils } from "../../util/VersionUtils"
import { Driver, ReturningType } from "../Driver"
import { DriverUtils } from "../DriverUtils"
import { ColumnType, UnsignedColumnType } from "../types/ColumnTypes"
import { CteCapabilities } from "../types/CteCapabilities"
import { DataTypeDefaults } from "../types/DataTypeDefaults"
import { MappedColumnTypes } from "../types/MappedColumnTypes"
import { ReplicationMode } from "../types/ReplicationMode"
import { UpsertType } from "../types/UpsertType"
import { MysqlConnectionCredentialsOptions } from "./MysqlConnectionCredentialsOptions"
import { MysqlConnectionOptions } from "./MysqlConnectionOptions"
import { MysqlQueryRunner } from "./MysqlQueryRunner"
/**
* Organizes communication with MySQL DBMS.
@ -189,10 +189,9 @@ export class MysqlDriver implements Driver {
]
/**
* Gets list of column data types that support length by a driver.
* Gets list of column data types that support the unsigned attribute by a driver.
*/
withWidthColumnTypes: ColumnType[] = [
"bit",
unsignedColumnTypes: UnsignedColumnType[] = [
"tinyint",
"smallint",
"mediumint",
@ -232,26 +231,6 @@ export class MysqlDriver implements Driver {
"real",
]
/**
* Gets list of column data types that supports UNSIGNED and ZEROFILL attributes.
*/
unsignedAndZerofillTypes: ColumnType[] = [
"int",
"integer",
"smallint",
"tinyint",
"mediumint",
"bigint",
"decimal",
"dec",
"numeric",
"fixed",
"float",
"double",
"double precision",
"real",
]
/**
* ORM has special columns and we need to know what database column types should be for those columns.
* Column types are driver dependant.

View File

@ -21,8 +21,9 @@ import { BroadcasterResult } from "../../subscriber/BroadcasterResult"
import { InstanceChecker } from "../../util/InstanceChecker"
import { OrmUtils } from "../../util/OrmUtils"
import { VersionUtils } from "../../util/VersionUtils"
import { DriverUtils } from "../DriverUtils"
import { Query } from "../Query"
import { ColumnType } from "../types/ColumnTypes"
import { ColumnType, UnsignedColumnType } from "../types/ColumnTypes"
import { IsolationLevel } from "../types/IsolationLevel"
import { MetadataTableType } from "../types/MetadataTableType"
import { ReplicationMode } from "../types/ReplicationMode"
@ -2654,17 +2655,14 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner {
}
tableColumn.zerofill =
dbColumn["COLUMN_TYPE"].indexOf("zerofill") !==
-1
tableColumn.unsigned = tableColumn.zerofill
? true
: dbColumn["COLUMN_TYPE"].indexOf(
"unsigned",
) !== -1
dbColumn["COLUMN_TYPE"].includes("zerofill")
tableColumn.unsigned =
tableColumn.zerofill ||
dbColumn["COLUMN_TYPE"].includes("unsigned")
if (
this.driver.withWidthColumnTypes.indexOf(
tableColumn.type as ColumnType,
) !== -1
this.driver.unsignedColumnTypes.includes(
tableColumn.type as UnsignedColumnType,
)
) {
const width = dbColumn["COLUMN_TYPE"].substring(
dbColumn["COLUMN_TYPE"].indexOf("(") + 1,
@ -3389,12 +3387,21 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner {
/**
* Checks if column display width is by default.
* @deprecated MySQL no longer supports column width in newer versions.
*/
protected isDefaultColumnWidth(
table: Table,
column: TableColumn,
width: number,
): boolean {
// Skip the whole check on servers that no longer expose width metadata.
if (
this.driver.options.type === "mysql" &&
DriverUtils.isReleaseVersionOrGreater(this.driver, "8.0.0")
) {
return true
}
// if table have metadata, we check if length is specified in column metadata
if (this.connection.hasMetadata(table.name)) {
const metadata = this.connection.getMetadata(table.name)

View File

@ -94,12 +94,6 @@ export interface SpannerConnectionOptions
*/
readonly multipleStatements?: boolean
/**
* Use spatial functions like GeomFromText and AsText which are removed in MySQL 8.
* (Default: true)
*/
readonly legacySpatialSupport?: boolean
/**
* List of connection flags to use other than the default ones. It is also possible to blacklist default ones.
* For more information, check https://github.com/mysqljs/mysql#connection-flags.

View File

@ -112,11 +112,6 @@ export class SpannerDriver implements Driver {
*/
withLengthColumnTypes: ColumnType[] = ["string", "bytes"]
/**
* Gets list of column data types that support length by a driver.
*/
withWidthColumnTypes: ColumnType[] = []
/**
* Gets list of column data types that support precision by a driver.
*/

View File

@ -78,11 +78,12 @@ export type WithLengthColumnType =
| "half_vector" // sap
| "real_vector" // sap
export type WithWidthColumnType =
export type UnsignedColumnType =
| "tinyint" // mysql
| "smallint" // mysql
| "mediumint" // mysql
| "int" // mysql
| "integer" // mysql
| "bigint" // mysql
/**
@ -217,7 +218,7 @@ export type SimpleColumnType =
export type ColumnType =
| WithPrecisionColumnType
| WithLengthColumnType
| WithWidthColumnType
| UnsignedColumnType
| SpatialColumnType
| SimpleColumnType
| BooleanConstructor

View File

@ -1,11 +1,12 @@
import "reflect-metadata"
import { Post } from "./entity/Post"
import { DataSource } from "../../../../../src/data-source/DataSource"
import { expect } from "chai"
import { DataSource } from "../../../../../src"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../../../utils/test-utils"
import { Post } from "./entity/Post"
import { DriverUtils } from "../../../../../src/driver/DriverUtils"
describe("database schema > column collation > mysql", () => {
let connections: DataSource[]
@ -33,24 +34,34 @@ describe("database schema > column collation > mysql", () => {
post.description = "This is post"
await postRepository.save(post)
table!
.findColumnByName("name")!
.charset!.should.be.equal("ascii")
table!
.findColumnByName("name")!
.collation!.should.be.equal("ascii_general_ci")
table!
.findColumnByName("title")!
.charset!.should.be.equal("utf8")
table!
.findColumnByName("title")!
.collation!.should.be.equal("utf8_general_ci")
table!
.findColumnByName("description")!
.charset!.should.be.equal("cp852")
table!
.findColumnByName("description")!
.collation!.should.be.equal("cp852_general_ci")
expect(table!.findColumnByName("name")).to.include({
charset: "ascii",
collation: "ascii_general_ci",
})
if (
connection.driver.options.type === "mysql" &&
DriverUtils.isReleaseVersionOrGreater(
connection.driver,
"8.0",
)
) {
// Charset: utf8mb4 and collation: utf8mb4_0900_ai_ci are default on MySQL 8.0+
expect(table!.findColumnByName("title")).to.include({
charset: undefined,
collation: undefined,
})
} else {
expect(table!.findColumnByName("title")).to.include({
charset: "utf8mb4",
collation: "utf8mb4_general_ci",
})
}
expect(table!.findColumnByName("description")).to.include({
charset: "cp852",
collation: "cp852_general_ci",
})
}),
))
})

View File

@ -10,7 +10,7 @@ export class Post {
@Column({ collation: "ascii_general_ci" })
name: string
@Column({ charset: "utf8" })
@Column({ charset: "utf8mb4" })
title: string
@Column({ charset: "cp852", collation: "cp852_general_ci" })

View File

@ -1,4 +1,4 @@
import { Entity, PrimaryGeneratedColumn } from "../../../../src"
import { Entity, PrimaryGeneratedColumn } from "../../../../../../src"
@Entity()
export class UuidEntity {

View File

@ -0,0 +1,54 @@
import { expect } from "chai"
import { DataSource } from "../../../../../src"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../../../utils/test-utils"
import { UuidEntity } from "./entity/UuidEntity"
import { DriverUtils } from "../../../../../src/driver/DriverUtils"
describe("database schema > column types > mysql > uuid", () => {
let connections: DataSource[]
before(
async () =>
(connections = await createTestingConnections({
entities: [UuidEntity],
schemaCreate: true,
dropSchema: true,
enabledDrivers: ["mysql", "mariadb"],
})),
)
beforeEach(() => reloadTestingDatabases(connections))
after(() => closeTestingConnections(connections))
it("should create table with appropriate UUID column type based on database version", () =>
Promise.all(
connections.map(async (connection) => {
const uuidRepository = connection.getRepository(UuidEntity)
// seems there is an issue with the persisting id that crosses over from mysql to mariadb
const uuidEntity: UuidEntity = {
id: "ceb2897c-a1cf-11ed-8dbd-040300000000",
}
await uuidRepository.save(uuidEntity)
const queryRunner = connection.createQueryRunner()
const uuidTable = await queryRunner.getTable("uuid_entity")
await queryRunner.release()
const hasNativeUuidSupport =
connection.driver.options.type === "mariadb" &&
DriverUtils.isReleaseVersionOrGreater(
connection.driver,
"10.7",
)
const expectedType = hasNativeUuidSupport ? "uuid" : "varchar"
const expectedLength = hasNativeUuidSupport ? "" : "36"
const idColumn = uuidTable!.findColumnByName("id")
expect(idColumn?.type).to.equal(expectedType)
expect(idColumn?.length).to.equal(expectedLength)
}),
))
})

View File

@ -7,14 +7,34 @@ import {
createTestingConnections,
reloadTestingDatabases,
} from "../../../../utils/test-utils"
import { DriverUtils } from "../../../../../src/driver/DriverUtils"
describe("database schema > column width", () => {
let connections: DataSource[]
before(async () => {
connections = await createTestingConnections({
entities: [Post],
enabledDrivers: ["mysql"],
enabledDrivers: ["mariadb", "mysql"],
})
await Promise.all(
connections.map(async (connection) => {
// column width no longer supported on Mysql 8.0+
if (
connection.driver.options.type === "mysql" &&
DriverUtils.isReleaseVersionOrGreater(
connection.driver,
"8.0",
)
) {
await connection.destroy()
}
}),
)
connections = connections.filter(
(connection) => connection.isInitialized,
)
})
beforeEach(() => reloadTestingDatabases(connections))
after(() => closeTestingConnections(connections))

View File

@ -14,7 +14,7 @@ describe("driver > mysql > connection options > enableQueryTimeout", () => {
entities: [__dirname + "/entity/*{.js,.ts}"],
schemaCreate: true,
dropSchema: true,
enabledDrivers: ["mysql"],
enabledDrivers: ["mariadb", "mysql"],
}
const timeoutMs = 150
const longQueryTimeSec = 0.2
@ -41,14 +41,9 @@ describe("driver > mysql > connection options > enableQueryTimeout", () => {
dataSource.manager
.sql`SELECT SLEEP(${longQueryTimeSec})`,
).to.eventually.be.rejected.then((err) => {
expect(err).to.have.nested.property(
"driverError.code",
expect(err.driverError?.code).to.equal(
"PROTOCOL_SEQUENCE_TIMEOUT",
)
expect(err).to.have.nested.property(
"driverError.timeout",
timeoutMs,
)
})
}),
))

View File

@ -6,13 +6,14 @@ import {
} from "../../../../utils/test-utils"
import { DataSource } from "../../../../../src/data-source/DataSource"
import { PersonSchema } from "./entity/Person"
import { DriverUtils } from "../../../../../src/driver/DriverUtils"
describe("entity-schema > columns > mysql", () => {
let connections: DataSource[]
before(
async () =>
(connections = await createTestingConnections({
entities: [<any>PersonSchema],
entities: [PersonSchema],
enabledDrivers: ["mysql"],
})),
)
@ -26,10 +27,22 @@ describe("entity-schema > columns > mysql", () => {
const table = await queryRunner.getTable("person")
await queryRunner.release()
table!.findColumnByName("Id")!.unsigned!.should.be.true
table!.findColumnByName("PostCode")!.zerofill!.should.be.true
table!.findColumnByName("PostCode")!.unsigned!.should.be.true
table!.findColumnByName("PostCode")!.width!.should.be.equal(9)
table!.findColumnByName("Id")!.unsigned.should.equal(true)
table!.findColumnByName("PostCode")!.zerofill.should.equal(true)
table!.findColumnByName("PostCode")!.unsigned.should.equal(true)
if (
connection.driver.options.type !== "mysql" ||
!DriverUtils.isReleaseVersionOrGreater(
connection.driver,
"8.0",
)
) {
table!
.findColumnByName("PostCode")!
.width!.should.be.equal(9)
}
table!
.findColumnByName("VirtualFullName")!
.asExpression!.should.be.equal(

View File

@ -1,23 +1,24 @@
import "reflect-metadata"
import { expect } from "chai"
import {
DataSource,
LockNotSupportedOnGivenDriverError,
NoVersionOrUpdateDateColumnError,
OptimisticLockCanNotBeUsedError,
OptimisticLockVersionMismatchError,
PessimisticLockTransactionRequiredError,
} from "../../../../src/"
import { DriverUtils } from "../../../../src/driver/DriverUtils"
import { VersionUtils } from "../../../../src/util/VersionUtils"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../../utils/test-utils"
import { DataSource } from "../../../../src/data-source/DataSource"
import { PostWithVersion } from "./entity/PostWithVersion"
import { Post } from "./entity/Post"
import { expect } from "chai"
import { PostWithoutVersionAndUpdateDate } from "./entity/PostWithoutVersionAndUpdateDate"
import { PostWithUpdateDate } from "./entity/PostWithUpdateDate"
import { PostWithVersion } from "./entity/PostWithVersion"
import { PostWithVersionAndUpdatedDate } from "./entity/PostWithVersionAndUpdatedDate"
import { OptimisticLockVersionMismatchError } from "../../../../src/error/OptimisticLockVersionMismatchError"
import { OptimisticLockCanNotBeUsedError } from "../../../../src/error/OptimisticLockCanNotBeUsedError"
import { NoVersionOrUpdateDateColumnError } from "../../../../src/error/NoVersionOrUpdateDateColumnError"
import { PessimisticLockTransactionRequiredError } from "../../../../src/error/PessimisticLockTransactionRequiredError"
import { LockNotSupportedOnGivenDriverError } from "../../../../src/error/LockNotSupportedOnGivenDriverError"
import { VersionUtils } from "../../../../src/util/VersionUtils"
import { DriverUtils } from "../../../../src/driver/DriverUtils"
describe("query builder > locking", () => {
let connections: DataSource[]
@ -379,7 +380,17 @@ describe("query builder > locking", () => {
.getSql()
if (DriverUtils.isMySQLFamily(connection.driver)) {
expect(sql).to.contain("LOCK IN SHARE MODE")
if (
connection.driver.options.type === "mysql" &&
DriverUtils.isReleaseVersionOrGreater(
connection.driver,
"8.0",
)
) {
expect(sql).to.contain("FOR SHARE")
} else {
expect(sql).to.contain("LOCK IN SHARE MODE")
}
} else if (connection.driver.options.type === "postgres") {
expect(sql).to.contain("FOR SHARE")
} else if (connection.driver.options.type === "oracle") {

View File

@ -1,9 +1,4 @@
import "../../../utils/test-setup"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../../utils/test-utils"
import { expect } from "chai"
import {
DataSource,
LockNotSupportedOnGivenDriverError,
@ -13,13 +8,18 @@ import {
PessimisticLockTransactionRequiredError,
QueryRunner,
} from "../../../../src"
import { PostWithVersion } from "./entity/PostWithVersion"
import { expect } from "chai"
import { DriverUtils } from "../../../../src/driver/DriverUtils"
import "../../../utils/test-setup"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../../utils/test-utils"
import { Post } from "./entity/Post"
import { PostWithoutVersionAndUpdateDate } from "./entity/PostWithoutVersionAndUpdateDate"
import { PostWithUpdateDate } from "./entity/PostWithUpdateDate"
import { PostWithVersion } from "./entity/PostWithVersion"
import { PostWithVersionAndUpdatedDate } from "./entity/PostWithVersionAndUpdatedDate"
import { Post } from "./entity/Post"
import { DriverUtils } from "../../../../src/driver/DriverUtils"
describe("repository > find options > locking", () => {
let connections: DataSource[]
@ -147,7 +147,17 @@ describe("repository > find options > locking", () => {
})
if (DriverUtils.isMySQLFamily(connection.driver)) {
expect(executedSql[0]).to.contain("LOCK IN SHARE MODE")
if (
connection.driver.options.type === "mysql" &&
DriverUtils.isReleaseVersionOrGreater(
connection.driver,
"8.0",
)
) {
expect(executedSql[0]).to.contain("FOR SHARE")
} else {
expect(executedSql[0]).to.contain("LOCK IN SHARE MODE")
}
} else if (connection.driver.options.type === "postgres") {
expect(executedSql[0]).to.contain("FOR SHARE")
} else if (connection.driver.options.type === "oracle") {

View File

@ -4,9 +4,9 @@ import { Post } from "./Post"
@Entity()
export class Category {
@PrimaryColumn({ collation: "ascii_general_ci", charset: "ascii" })
@PrimaryColumn({ charset: "ascii", collation: "ascii_general_ci" })
id: string
@ManyToMany((type) => Post, (post) => post.categories)
@ManyToMany(() => Post, (post) => post.categories)
posts: Post[]
}

View File

@ -4,10 +4,10 @@ import { Category } from "./Category"
@Entity()
export class Post {
@PrimaryColumn({ collation: "utf8_unicode_ci", charset: "utf8" })
@PrimaryColumn({ charset: "latin2", collation: "latin2_general_ci" })
id: string
@ManyToMany((type) => Category, (category) => category.posts)
@ManyToMany(() => Category, (category) => category.posts)
@JoinTable()
categories: Category[]
}

View File

@ -1,4 +1,4 @@
import "reflect-metadata"
import { expect } from "chai"
import { DataSource } from "../../../src/data-source/DataSource"
import {
closeTestingConnections,
@ -10,7 +10,7 @@ describe("github issues > #1839 Charset and collation not being carried to JoinT
before(async () => {
connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
enabledDrivers: ["mysql"],
enabledDrivers: ["mariadb", "mysql"],
schemaCreate: true,
dropSchema: true,
})
@ -24,19 +24,16 @@ describe("github issues > #1839 Charset and collation not being carried to JoinT
const table = await queryRunner.getTable(
"post_categories_category",
)
table!
.findColumnByName("postId")!
.charset!.should.be.equal("utf8")
table!
.findColumnByName("postId")!
.collation!.should.be.equal("utf8_unicode_ci")
table!
.findColumnByName("categoryId")!
.charset!.should.be.equal("ascii")
table!
.findColumnByName("categoryId")!
.collation!.should.be.equal("ascii_general_ci")
await queryRunner.release()
expect(table!.findColumnByName("postId")).to.include({
charset: "latin2",
collation: "latin2_general_ci",
})
expect(table!.findColumnByName("categoryId")).to.include({
charset: "ascii",
collation: "ascii_general_ci",
})
}),
))
})

View File

@ -1,8 +1,7 @@
import "reflect-metadata"
import { expect } from "chai"
import { DataSource } from "../../../src"
import { getTypeOrmConfig } from "../../utils/test-utils"
import { MysqlConnectionOptions } from "../../../src/driver/mysql/MysqlConnectionOptions"
import { getTypeOrmConfig } from "../../utils/test-utils"
describe("github issues > #2096 [mysql] Database name isn't read from url", () => {
it("should be possible to define a database by connection url for mysql", async () => {
@ -10,25 +9,29 @@ describe("github issues > #2096 [mysql] Database name isn't read from url", () =
// it is important to synchronize here, to trigger EntityMetadataValidator.validate
// that previously threw the error where the database on the driver object was undefined
const mysqlConfig: MysqlConnectionOptions = config.find(
const mysqlConfig = config.find(
(c) => c.name === "mysql" && !c.skip,
) as MysqlConnectionOptions
if (mysqlConfig) {
const { username, password, host, port, database } = mysqlConfig
const url = `mysql://${username}:${password}@${host}:${port}/${database}`
const dataSource = new DataSource({
name: "#2096",
url,
entities: [__dirname + "/entity/*{.js,.ts}"],
synchronize: true,
type: "mysql",
})
await dataSource.initialize()
expect(dataSource.isInitialized).to.eq(true)
await dataSource.destroy()
if (!mysqlConfig) {
return
}
const { username, password, host, port, database, ...restConfig } =
mysqlConfig
const url = `mysql://${username}:${password}@${host}:${port}/${database}`
const dataSource = new DataSource({
...restConfig,
name: "#2096",
url,
entities: [__dirname + "/entity/*{.js,.ts}"],
synchronize: true,
type: "mysql",
})
await dataSource.initialize()
expect(dataSource.isInitialized).to.equal(true)
await dataSource.destroy()
})
})

View File

@ -1,10 +1,10 @@
import "reflect-metadata"
import {
createTestingConnections,
closeTestingConnections,
} from "../../utils/test-utils"
import { DataSource } from "../../../src/data-source/DataSource"
import { expect } from "chai"
import { DataSource } from "../../../src/data-source/DataSource"
import { DriverUtils } from "../../../src/driver/DriverUtils"
import {
closeTestingConnections,
createTestingConnections,
} from "../../utils/test-utils"
import { LetterBox } from "./entity/LetterBox"
// Another related path: test/functional/spatial
@ -12,24 +12,31 @@ describe("github issues > #3702 MySQL Spatial Type Support : GeomFromText functi
describe("when legacySpatialSupport: true", () => {
let connections: DataSource[]
before(
async () =>
(connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
enabledDrivers: ["mysql"],
dropSchema: true,
schemaCreate: true,
driverSpecific: {
// it's default
// legacySpatialSupport: true,
},
})),
)
before(async () => {
connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
enabledDrivers: ["mysql"],
dropSchema: true,
schemaCreate: true,
driverSpecific: {
legacySpatialSupport: true,
},
})
})
after(() => closeTestingConnections(connections))
it("should use GeomFromText", () =>
Promise.all(
connections.map(async (connection) => {
if (
DriverUtils.isReleaseVersionOrGreater(
connection.driver,
"8.0",
)
) {
return
}
const queryBuilder = connection
.createQueryBuilder()
.insert()
@ -48,6 +55,15 @@ describe("github issues > #3702 MySQL Spatial Type Support : GeomFromText functi
it("should provide SRID", () =>
Promise.all(
connections.map(async (connection) => {
if (
DriverUtils.isReleaseVersionOrGreater(
connection.driver,
"8.0",
)
) {
return
}
const queryBuilder = connection
.createQueryBuilder()
.insert()
@ -65,6 +81,15 @@ describe("github issues > #3702 MySQL Spatial Type Support : GeomFromText functi
it("should use AsText", () =>
Promise.all(
connections.map(async (connection) => {
if (
DriverUtils.isReleaseVersionOrGreater(
connection.driver,
"8.0",
)
) {
return
}
const repository = connection.getRepository(LetterBox)
const queryBuilder = repository
.createQueryBuilder("letterBox")

View File

@ -1,3 +1,4 @@
import { expect } from "chai"
import { DataSource } from "../../../src/data-source/DataSource"
import { MysqlConnectionOptions } from "../../../src/driver/mysql/MysqlConnectionOptions"
import {
@ -25,29 +26,20 @@ describe("github issues > #4753 MySQL Replication Config broken", () => {
// Skip if MySQL tests aren't enabled at all
return
}
const { host, username, password, database, ...restConfig } =
connectionOptions
const dataSource = new DataSource({
type: "mysql",
...restConfig,
replication: {
master: {
host: connectionOptions.host,
username: connectionOptions.username,
password: connectionOptions.password,
database: connectionOptions.database,
},
slaves: [
{
host: connectionOptions.host,
username: connectionOptions.username,
password: connectionOptions.password,
database: connectionOptions.database,
},
],
master: { host, username, password, database },
slaves: [{ host, username, password, database }],
},
entities: [User],
})
dataSources.push(dataSource)
await dataSource.connect()
dataSource.isInitialized.should.be.true
await dataSource.initialize()
expect(dataSource.isInitialized).to.equal(true)
})
})

View File

@ -9,17 +9,35 @@ import { DataSource } from "../../../src"
import { fail } from "assert"
import { Query } from "../../../src/driver/Query"
import { MysqlConnectionOptions } from "../../../src/driver/mysql/MysqlConnectionOptions"
import { DriverUtils } from "../../../src/driver/DriverUtils"
describe("github issues > #6442 JoinTable does not respect inverseJoinColumns referenced column width", () => {
let connections: DataSource[]
before(async () => {
return (connections = await createTestingConnections({
connections = await createTestingConnections({
entities: [__dirname + "/entity/v1/*{.js,.ts}"],
schemaCreate: true,
dropSchema: true,
enabledDrivers: ["mysql"],
}))
enabledDrivers: ["mariadb", "mysql"],
})
await Promise.all(
connections.map(async (connection) => {
// column width no longer supported on Mysql 8.0+
if (
connection.driver.options.type === "mysql" &&
DriverUtils.isReleaseVersionOrGreater(
connection.driver,
"8.0",
)
) {
await connection.destroy()
}
}),
)
connections = connections.filter(
(connection) => connection.isInitialized,
)
})
beforeEach(async () => await reloadTestingDatabases(connections))
after(async () => await closeTestingConnections(connections))

View File

@ -9,12 +9,12 @@ import { Car } from "./Car"
@Entity()
export class Record extends BaseEntity {
@Column({ type: "timestamp", precision: 3, primary: true })
timestamp: Date
@Column({ type: "uuid", primary: true })
carUuid: string
@Column({ type: "timestamp", precision: 3, primary: true })
timestamp: Date
@ManyToOne(() => Car, (car) => car.records, { onDelete: "CASCADE" })
@JoinColumn({ name: "carUuid" })
car: Car

View File

@ -1,13 +1,13 @@
import { expect } from "chai"
import { DataSource } from "../../../src"
import "../../utils/test-setup"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils"
import { expect } from "chai"
import { Car } from "./entity/Car"
import { Record } from "./entity/Record"
import { DataSource } from "../../../src"
describe("github issues > #8747 QueryBuilder update handles Date objects wrong on a ManyToOne relationship.", () => {
let dataSources: DataSource[]
@ -15,7 +15,7 @@ describe("github issues > #8747 QueryBuilder update handles Date objects wrong o
async () =>
(dataSources = await createTestingConnections({
enabledDrivers: ["mysql", "postgres", "mariadb"],
entities: [__dirname + "/entity/*{.js,.ts}"],
entities: [__dirname + "/entity/*.{js,ts}"],
schemaCreate: true,
dropSchema: true,
})),

View File

@ -1,203 +1,150 @@
import { expect } from "chai"
import { DataSource } from "../../../src"
import { ConnectionMetadataBuilder } from "../../../src/connection/ConnectionMetadataBuilder"
import { DriverUtils } from "../../../src/driver/DriverUtils"
import { EntityMetadataValidator } from "../../../src/metadata-builder/EntityMetadataValidator"
import "../../utils/test-setup"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils"
import { BadInet4 } from "./badEntity/BadInet4"
import { BadInet6 } from "./badEntity/BadInet6"
import { BadUuid } from "./badEntity/BadUuid"
import { Address } from "./entity/Address"
import { User } from "./entity/User"
import { UuidEntity } from "./entity/UuidEntity"
describe("github issues > #8832 Add uuid, inet4, and inet6 types for mariadb", () => {
describe("basic use of new mariadb types", () => {
let connections: DataSource[]
before(
async () =>
(connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
schemaCreate: true,
dropSchema: true,
enabledDrivers: ["mariadb"],
})),
)
beforeEach(() => reloadTestingDatabases(connections))
after(() => closeTestingConnections(connections))
describe("github issues > #8832 Add uuid, inet4 and inet6 types for mariadb", () => {
let connections: DataSource[]
before(async () => {
connections = await createTestingConnections({
entities: [Address, User],
enabledDrivers: ["mariadb"],
driverSpecific: {
synchronize: false,
},
})
it("should create table with uuid, inet4, and inet6 type set to column for relevant mariadb versions", () =>
Promise.all(
connections.map(async (connection) => {
const userRepository = connection.getRepository(User)
const newUser = await userRepository.save({
uuid: "ceb2897c-a1cf-11ed-8dbd-040300000000",
inet4: "192.0.2.146",
inet6: "2001:0db8:0000:0000:0000:ff00:0042:8329",
})
const savedUser = await userRepository.findOneOrFail({
where: { uuid: newUser.uuid },
})
const foundUser = await userRepository.findOne({
where: { id: savedUser.id },
})
expect(foundUser).to.not.be.null
expect(foundUser!.uuid).to.deep.equal(newUser.uuid)
expect(foundUser!.inet4).to.deep.equal(newUser.inet4)
expect(foundUser!.inet6).to.deep.equal(
"2001:db8::ff00:42:8329",
// uuid is available since 10.7
// inet4 is available since 10.10
// inet6 is available since 10.5
await Promise.all(
connections.map(async (connection) => {
if (
!DriverUtils.isReleaseVersionOrGreater(
connection.driver,
"10.10",
)
expect(foundUser!.another_uuid_field).to.not.be.undefined
) {
await connection.destroy()
const columnTypes: {
COLUMN_NAME: string
DATA_TYPE: string
}[] = await connection.sql`
SELECT
COLUMN_NAME,
DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = ${connection.driver.database}
AND TABLE_NAME = 'user'
AND COLUMN_NAME IN ('id', 'uuid', 'inet4', 'inet6', 'anotherUuid')`
return
}
const expectedColumnTypes: Record<string, string> = {
id: "uuid",
uuid: "uuid",
inet4: "inet4",
inet6: "inet6",
another_uuid_field: "uuid",
}
columnTypes.forEach(({ COLUMN_NAME, DATA_TYPE }) => {
expect(DATA_TYPE).to.equal(
expectedColumnTypes[COLUMN_NAME],
)
})
// save a relation
const addressRepository = connection.getRepository(Address)
const newAddress: Address = {
city: "Codersville",
state: "Coderado",
user: foundUser!,
}
await addressRepository.save(newAddress)
const foundAddress = await addressRepository.findOne({
where: { user: { id: foundUser!.id } },
})
expect(foundAddress).to.not.be.null
}),
))
})
describe("regression test mysql uuid generation", () => {
let connections: DataSource[]
before(
async () =>
(connections = await createTestingConnections({
entities: [UuidEntity],
schemaCreate: true,
dropSchema: true,
enabledDrivers: ["mysql", "mariadb"],
})),
await connection.synchronize()
}),
)
beforeEach(() => reloadTestingDatabases(connections))
after(() => closeTestingConnections(connections))
it("should create table with with varchar with length 36 when version is mysql", () =>
Promise.all(
connections.map(async (connection) => {
const uuidRepository = connection.getRepository(UuidEntity)
// seems there is an issue with the persisting id that crosses over from mysql to mariadb
const uuidEntity: UuidEntity = {
id: "ceb2897c-a1cf-11ed-8dbd-040300000000",
}
await uuidRepository.save(uuidEntity)
const columnTypes: {
DATA_TYPE: string
CHARACTER_MAXIMUM_LENGTH: string
}[] = await connection.sql`
SELECT
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = ${connection.driver.database}
AND TABLE_NAME = 'UuidEntity'
AND COLUMN_NAME = 'id'`
const isMysql = connection.driver.options.type === "mysql"
const expectedType = isMysql ? "varchar" : "uuid"
const expectedLength = isMysql ? "36" : null
columnTypes.forEach(
({ DATA_TYPE, CHARACTER_MAXIMUM_LENGTH }) => {
expect(DATA_TYPE).to.equal(expectedType)
expect(CHARACTER_MAXIMUM_LENGTH).to.equal(
expectedLength,
)
},
)
}),
))
})
describe("entity-metadata-validator", () => {
let connections: DataSource[]
before(
async () =>
(connections = await createTestingConnections({
entities: [],
schemaCreate: true,
dropSchema: true,
enabledDrivers: ["mariadb"],
})),
connections = connections.filter(
(connection) => connection.isInitialized,
)
beforeEach(() => reloadTestingDatabases(connections))
after(() => closeTestingConnections(connections))
it("should throw error if mariadb uuid is supported and length is provided to property", async () =>
Promise.all(
connections.map(async (connection) => {
// version supports all the new types
connection.driver.version = "10.10.0"
const connectionMetadataBuilder =
new ConnectionMetadataBuilder(connection)
const entityMetadatas =
await connectionMetadataBuilder.buildEntityMetadatas([
BadInet4,
BadInet6,
BadUuid,
])
const entityMetadataValidator =
new EntityMetadataValidator()
entityMetadatas.forEach((entityMetadata) => {
expect(() =>
entityMetadataValidator.validate(
entityMetadata,
entityMetadatas,
connection.driver,
),
).to.throw(Error)
})
}),
))
})
after(() => closeTestingConnections(connections))
it("should create table with uuid, inet4, and inet6 type set to column for relevant mariadb versions", () =>
Promise.all(
connections.map(async (connection) => {
const userRepository = connection.getRepository(User)
const newUser = await userRepository.save({
uuid: "ceb2897c-a1cf-11ed-8dbd-040300000000",
inet4: "192.0.2.146",
inet6: "2001:0db8:0000:0000:0000:ff00:0042:8329",
})
const savedUser = await userRepository.findOneOrFail({
where: { uuid: newUser.uuid },
})
const foundUser = await userRepository.findOne({
where: { id: savedUser.id },
})
expect(foundUser).to.not.be.null
expect(foundUser!.uuid).to.deep.equal(newUser.uuid)
expect(foundUser!.inet4).to.deep.equal(newUser.inet4)
expect(foundUser!.inet6).to.deep.equal("2001:db8::ff00:42:8329")
expect(foundUser!.another_uuid_field).to.not.be.undefined
const columnTypes: {
COLUMN_NAME: string
DATA_TYPE: string
}[] = await connection.sql`
SELECT
COLUMN_NAME,
DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = ${connection.driver.database}
AND TABLE_NAME = 'user'
AND COLUMN_NAME IN ('id', 'uuid', 'inet4', 'inet6', 'anotherUuid')`
const expectedColumnTypes: Record<string, string> = {
id: "uuid",
uuid: "uuid",
inet4: "inet4",
inet6: "inet6",
another_uuid_field: "uuid",
}
columnTypes.forEach(({ COLUMN_NAME, DATA_TYPE }) => {
expect(DATA_TYPE).to.equal(expectedColumnTypes[COLUMN_NAME])
})
// save a relation
const addressRepository = connection.getRepository(Address)
const newAddress: Address = {
city: "Codersville",
state: "Coderado",
user: foundUser!,
}
await addressRepository.save(newAddress)
const foundAddress = await addressRepository.findOne({
where: { user: { id: foundUser!.id } },
})
expect(foundAddress).to.not.be.null
}),
))
it("should throw error if mariadb uuid is supported and length is provided to property", async () =>
Promise.all(
connections.map(async (connection) => {
// version supports all the new types
connection.driver.version = "10.10.0"
const connectionMetadataBuilder = new ConnectionMetadataBuilder(
connection,
)
const entityMetadatas =
await connectionMetadataBuilder.buildEntityMetadatas([
BadInet4,
BadInet6,
BadUuid,
])
const entityMetadataValidator = new EntityMetadataValidator()
entityMetadatas.forEach((entityMetadata) => {
expect(() =>
entityMetadataValidator.validate(
entityMetadata,
entityMetadatas,
connection.driver,
),
).to.throw(Error)
})
}),
))
})

View File

@ -23,7 +23,7 @@ describe("ImportUtils.importOrRequireFile", () => {
`
try {
await fs.rmdir(testDir, { recursive: true })
await fs.rm(testDir, { recursive: true, force: true })
} catch {
// no-op
}
@ -44,7 +44,7 @@ describe("ImportUtils.importOrRequireFile", () => {
expect(exports.default).to.be.a("function")
expect(exports.number).to.be.eq(6)
await fs.rmdir(testDir, { recursive: true })
await fs.rm(testDir, { recursive: true, force: true })
})
it("should import .js file as CommonJS", async () => {
@ -64,7 +64,7 @@ describe("ImportUtils.importOrRequireFile", () => {
`
try {
await fs.rmdir(testDir, { recursive: true })
await fs.rm(testDir, { recursive: true, force: true })
} catch {
// no-op
}
@ -85,7 +85,7 @@ describe("ImportUtils.importOrRequireFile", () => {
expect(exports.test).to.be.a("function")
expect(exports.number).to.be.eq(6)
await fs.rmdir(testDir, { recursive: true })
await fs.rm(testDir, { recursive: true, force: true })
})
it("should import .mjs file as ESM", async () => {
@ -100,7 +100,7 @@ describe("ImportUtils.importOrRequireFile", () => {
`
try {
await fs.rmdir(testDir, { recursive: true })
await fs.rm(testDir, { recursive: true, force: true })
} catch {
// no-op
}
@ -116,7 +116,7 @@ describe("ImportUtils.importOrRequireFile", () => {
expect(exports.default).to.be.a("function")
expect(exports.number).to.be.eq(6)
await fs.rmdir(testDir, { recursive: true })
await fs.rm(testDir, { recursive: true, force: true })
})
it("should import .cjs file as CommonJS", async () => {
@ -133,7 +133,7 @@ describe("ImportUtils.importOrRequireFile", () => {
`
try {
await fs.rmdir(testDir, { recursive: true })
await fs.rm(testDir, { recursive: true, force: true })
} catch {
// no-op
}
@ -149,7 +149,7 @@ describe("ImportUtils.importOrRequireFile", () => {
expect(exports.test).to.be.a("function")
expect(exports.number).to.be.eq(6)
await fs.rmdir(testDir, { recursive: true })
await fs.rm(testDir, { recursive: true, force: true })
})
it("should import .json file as CommonJS", async () => {
@ -159,7 +159,7 @@ describe("ImportUtils.importOrRequireFile", () => {
const jsonFileContent = { test: 6 }
try {
await fs.rmdir(testDir, { recursive: true })
await fs.rm(testDir, { recursive: true, force: true })
} catch {
// no-op
}
@ -178,7 +178,7 @@ describe("ImportUtils.importOrRequireFile", () => {
expect(moduleType).to.be.eq("commonjs")
expect(exports.test).to.be.eq(6)
await fs.rmdir(testDir, { recursive: true })
await fs.rm(testDir, { recursive: true, force: true })
})
it("Should use cache to find package.json", async () => {