mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
feat: SAP Hana support (#5246)
* basic impl * finished basic table metadata queries; * implemented data types; * working on data types; * added test for column length; * working on indices * working on query runner * working on schema builder * removed SAP HANA client from dependencies * fixed SAP uuid * working on falling tests; * working on falling tests; * added docker configuration for sap hana * simplifying sample entity * implemented pool; * trying to add SAP Hana to Circle CI * trying to add SAP Hana to Circle CI * trying to add SAP Hana to Circle CI * testing CircleCI config * testing CircleCI config * added sap tests for ci * changed sap port * ci experiments * ci experiments * removing ci, adding docs * removing ci * minor fixes; * fixed falling test; Co-authored-by: AlexMesser <dmzt08@gmail.com>
This commit is contained in:
parent
d19162c8bc
commit
ec9034125d
@ -23,6 +23,30 @@ jobs:
|
||||
POSTGRES_PASSWORD: "test"
|
||||
POSTGRES_DB: "test"
|
||||
- image: circleci/mongo:3.4.18
|
||||
# - image: "store/saplabs/hanaexpress:2.00.040.00.20190729.1"
|
||||
# auth:
|
||||
# username: $DOCKER_USER
|
||||
# password: $DOCKER_PASSWORD
|
||||
## name: hanaexpress
|
||||
## container_name: "typeorm-hanaexpress"
|
||||
## hostname: hxe
|
||||
# command: ['--passwords-url', 'https://raw.githubusercontent.com/typeorm/typeorm/b119f7c3b8748aea9c77c7bc42b8e1be209b43ec/docker/hana/hxe-config.json', '--agree-to-sap-license']
|
||||
## ulimits:
|
||||
## nofile: 1048576
|
||||
## sysctls:
|
||||
## - kernel.shmmax=1073741824
|
||||
## - net.ipv4.ip_local_port_range=40000 60999
|
||||
## - kernel.shmmni=524288
|
||||
## - kernel.shmall=8388608
|
||||
## volumes:
|
||||
## - volume-hana-xe:/hana/mounts
|
||||
## - ./docker/hana/hxe-config.json:/hana/hxe-config.json
|
||||
## ports:
|
||||
## - 39013:39013
|
||||
## - 39017:39017
|
||||
## - 39041-39045:39041-39045
|
||||
## - 1128-1129:1128-1129
|
||||
## - 59013-59014:59013-59014
|
||||
# - image: mcr.microsoft.com/mssql/server:2017-GA-ubuntu
|
||||
# environment:
|
||||
# SA_PASSWORD: "Admin12345"
|
||||
|
||||
@ -57,7 +57,7 @@ TypeORM 的一些特性:
|
||||
- 支持闭包表模式
|
||||
- 在模型或者分离的配置文件中声明模式
|
||||
- json / xml / yml / env 格式的连接配置
|
||||
- 支持 MySQL / MariaDB / Postgres / SQLite / Microsoft SQL Server / Oracle / sql.js
|
||||
- 支持 MySQL / MariaDB / Postgres / SQLite / Microsoft SQL Server / Oracle / SAP Hana / sql.js
|
||||
- 支持 MongoDB NoSQL 数据库
|
||||
- 可在 NodeJS / 浏览器 / Ionic / Cordova / React Native / Expo / Electron 平台上使用
|
||||
- 支持 TypeScript 和 JavaScript
|
||||
@ -198,9 +198,16 @@ await timber.remove();
|
||||
|
||||
查看 [支持的平台](/supported-platforms.md)
|
||||
|
||||
- **SAP Hana**
|
||||
|
||||
```
|
||||
npm config set @sap:registry https://npm.sap.com
|
||||
npm i @sap/hdbext
|
||||
```
|
||||
|
||||
##### TypeScript 配置
|
||||
|
||||
此外,请确保你使用的 TypeScript 编译器版本是**2.3**或更高版本,并且已经在 `tsconfig.json` 中启用了以下设置:
|
||||
此外,请确保你使用的 TypeScript 编译器版本是**3.3**或更高版本,并且已经在 `tsconfig.json` 中启用了以下设置:
|
||||
|
||||
```json
|
||||
"emitDecoratorMetadata": true,
|
||||
|
||||
14
README.md
14
README.md
@ -70,7 +70,7 @@ Some TypeORM features:
|
||||
* supports closure table pattern
|
||||
* schema declaration in models or separate configuration files
|
||||
* connection configuration in json / xml / yml / env formats
|
||||
* supports MySQL / MariaDB / Postgres / CockroachDB / SQLite / Microsoft SQL Server / Oracle / sql.js
|
||||
* supports MySQL / MariaDB / Postgres / CockroachDB / SQLite / Microsoft SQL Server / Oracle / SAP Hana / sql.js
|
||||
* supports MongoDB NoSQL database
|
||||
* works in NodeJS / Browser / Ionic / Cordova / React Native / NativeScript / Expo / Electron platforms
|
||||
* TypeScript and JavaScript support
|
||||
@ -203,11 +203,16 @@ await timber.remove();
|
||||
|
||||
`npm install oracledb --save`
|
||||
|
||||
Install only *one* of them, depending on which database you use.
|
||||
|
||||
To make the Oracle driver work, you need to follow the installation instructions from
|
||||
[their](https://github.com/oracle/node-oracledb) site.
|
||||
|
||||
* for **SAP Hana**
|
||||
|
||||
```
|
||||
npm config set @sap:registry https://npm.sap.com
|
||||
npm i @sap/hdbext
|
||||
```
|
||||
|
||||
* for **MongoDB** (experimental)
|
||||
|
||||
`npm install mongodb --save`
|
||||
@ -216,11 +221,12 @@ await timber.remove();
|
||||
|
||||
Check [documentation of supported platforms](./docs/supported-platforms.md)
|
||||
|
||||
Install only *one* of them, depending on which database you use.
|
||||
|
||||
|
||||
##### TypeScript configuration
|
||||
|
||||
Also, make sure you are using TypeScript compiler version **3.3** or greater,
|
||||
Also, make sure you are using TypeScript version **3.3** or higher,
|
||||
and you have enabled the following settings in `tsconfig.json`:
|
||||
|
||||
```json
|
||||
|
||||
@ -69,6 +69,29 @@ services:
|
||||
ports:
|
||||
- "26257:26257"
|
||||
|
||||
# sap hana (works only on linux)
|
||||
# hanaexpress:
|
||||
# image: "store/saplabs/hanaexpress:2.00.040.00.20190729.1"
|
||||
# container_name: "typeorm-hanaexpress"
|
||||
# hostname: hxe
|
||||
# command: ['--passwords-url', 'file:////hana/hxe-config.json', '--agree-to-sap-license']
|
||||
# ulimits:
|
||||
# nofile: 1048576
|
||||
# sysctls:
|
||||
# - kernel.shmmax=1073741824
|
||||
# - net.ipv4.ip_local_port_range=40000 60999
|
||||
# - kernel.shmmni=524288
|
||||
# - kernel.shmall=8388608
|
||||
# volumes:
|
||||
# - volume-hana-xe:/hana/mounts
|
||||
# - ./docker/hana/hxe-config.json:/hana/hxe-config.json
|
||||
# ports:
|
||||
# - 39013:39013
|
||||
# - 39017:39017
|
||||
# - 39041-39045:39041-39045
|
||||
# - 1128-1129:1128-1129
|
||||
# - 59013-59014:59013-59014
|
||||
|
||||
# mongodb
|
||||
mongodb:
|
||||
image: "mongo:3.4.18"
|
||||
@ -82,3 +105,6 @@ services:
|
||||
# container_name: "typeorm-redis"
|
||||
# ports:
|
||||
# - "6379:6379"
|
||||
|
||||
#volumes:
|
||||
# volume-hana-xe:
|
||||
|
||||
3
docker/hana/hxe-config.json
Normal file
3
docker/hana/hxe-config.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"master_password" : "HXEHana1"
|
||||
}
|
||||
@ -69,6 +69,17 @@
|
||||
"password": "",
|
||||
"database": "defaultdb"
|
||||
},
|
||||
{
|
||||
"skip": true,
|
||||
"name": "sap",
|
||||
"type": "sap",
|
||||
"host": "localhost",
|
||||
"port": 39015,
|
||||
"username": "SYSTEM",
|
||||
"password": "HXEHana1",
|
||||
"database": "HXE",
|
||||
"logging": false
|
||||
},
|
||||
{
|
||||
"skip": false,
|
||||
"disabledIfNotEnabledImplicitly": true,
|
||||
|
||||
@ -70,6 +70,17 @@
|
||||
"password": "",
|
||||
"database": "defaultdb"
|
||||
},
|
||||
{
|
||||
"skip": false,
|
||||
"name": "sap",
|
||||
"type": "sap",
|
||||
"host": "192.168.56.102",
|
||||
"port": 39015,
|
||||
"username": "SYSTEM",
|
||||
"password": "MySuperHanaPwd123!",
|
||||
"database": "HXE",
|
||||
"logging": false
|
||||
},
|
||||
{
|
||||
"skip": false,
|
||||
"disabledIfNotEnabledImplicitly": true,
|
||||
|
||||
570
package-lock.json
generated
570
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "typeorm",
|
||||
"version": "0.2.21",
|
||||
"version": "0.2.22-rc.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -120,6 +120,328 @@
|
||||
"any-observable": "^0.3.0"
|
||||
}
|
||||
},
|
||||
"@sap/hana-client": {
|
||||
"version": "2.4.171",
|
||||
"resolved": "https://npm.sap.com/@sap/hana-client/-/hana-client-2.4.171.tgz",
|
||||
"integrity": "sha512-djtXNfPZl+QMSOYSZxbyEGvUaWxyC0or3U+8odm+5Oc1ScVDaXp54U1E5i4Iw/USFi+1FBIrY+kh5CQ+r62Wog==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@sap/hdbext": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://npm.sap.com/@sap/hdbext/-/hdbext-6.1.1.tgz",
|
||||
"integrity": "sha512-M+VmMghNPVuGOvZnIJUfb8usYqj3HoEIjdcBaDzSHpSLXxUXGaWgWZ0pGgdDV4BTjWPHkbb7ZiBrp4k4heOoSg==",
|
||||
"requires": {
|
||||
"@sap/e2e-trace": "^2.0.0",
|
||||
"@sap/hana-client": "2.4.167",
|
||||
"accept-language": "2.0.16",
|
||||
"async": "2.4.1",
|
||||
"debug": "3.1.0",
|
||||
"lodash": "4.17.13",
|
||||
"verror": "1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sap/e2e-trace": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://npm.sap.com/@sap/e2e-trace/-/e2e-trace-2.0.0.tgz",
|
||||
"integrity": "sha512-iAAd+U8W+c5Yk4f3PSCL68oAjpCG6NUtmh67MD+hifCjM+LIG8R9oDtVgefQ68jImAtsiInBwEFisRkYHBjztw==",
|
||||
"requires": {
|
||||
"request-stats": "3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"http-headers": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/http-headers/-/http-headers-3.0.2.tgz",
|
||||
"integrity": "sha512-87E1I+2Wg4dxxz4rcxElo3dxO/w1ZtgL1yA0Sb6vH3qU16vRKq1NjWQv9SCY3ly2OQROcoxHZOUpmelS+k6wOw==",
|
||||
"requires": {
|
||||
"next-line": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"next-line": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/next-line/-/next-line-1.1.0.tgz",
|
||||
"integrity": "sha1-/K5XhTBStqm66CCOQN19PC0wRgM="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"request-stats": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/request-stats/-/request-stats-3.0.0.tgz",
|
||||
"integrity": "sha1-dpFV3Il0141KHLh7vxTqq5ha/iU=",
|
||||
"requires": {
|
||||
"http-headers": "^3.0.1",
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@sap/hana-client": {
|
||||
"version": "2.4.167",
|
||||
"resolved": "https://npm.sap.com/@sap/hana-client/-/hana-client-2.4.167.tgz",
|
||||
"integrity": "sha512-nUIOcuNa6xhUPr49RR497Pg+UYB/Lb/X2SM2woQGaCeY23mkaQy5w/+TVAgqmW0i0WQhRC1BJ8tXOR2TmLYzmg==",
|
||||
"requires": {
|
||||
"debug": "3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
}
|
||||
}
|
||||
},
|
||||
"accept-language": {
|
||||
"version": "2.0.16",
|
||||
"resolved": "https://registry.npmjs.org/accept-language/-/accept-language-2.0.16.tgz",
|
||||
"integrity": "sha1-uefScQd0rWCfJHbzz+GkkrVgYb4=",
|
||||
"requires": {
|
||||
"bcp47": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
},
|
||||
"async": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz",
|
||||
"integrity": "sha1-YqVrJ5yYoR0JhwlqAcw+6463u9c=",
|
||||
"requires": {
|
||||
"lodash": "^4.14.0"
|
||||
}
|
||||
},
|
||||
"bcp47": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bcp47/-/bcp47-1.1.2.tgz",
|
||||
"integrity": "sha1-NUvjMH/9CEM6ePXh4glYRfifx/4="
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz",
|
||||
"integrity": "sha1-4mifjzVvrWLMplo6kcXfX5VRaS8="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.13",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.13.tgz",
|
||||
"integrity": "sha512-vm3/XWXfWtRua0FkUyEHBZy8kCPjErNBT9fJx8Zvs+U6zjqPbTUOpkaoum3O5uiA8sm+yNMHXfYkTUHFoMxFNA=="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@sap/hdbext": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://npm.sap.com/@sap/hdbext/-/hdbext-6.1.1.tgz",
|
||||
"integrity": "sha512-M+VmMghNPVuGOvZnIJUfb8usYqj3HoEIjdcBaDzSHpSLXxUXGaWgWZ0pGgdDV4BTjWPHkbb7ZiBrp4k4heOoSg==",
|
||||
"requires": {
|
||||
"@sap/e2e-trace": "^2.0.0",
|
||||
"@sap/hana-client": "2.4.167",
|
||||
"accept-language": "2.0.16",
|
||||
"async": "2.4.1",
|
||||
"debug": "3.1.0",
|
||||
"lodash": "4.17.13",
|
||||
"verror": "1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sap/e2e-trace": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://npm.sap.com/@sap/e2e-trace/-/e2e-trace-2.0.0.tgz",
|
||||
"integrity": "sha512-iAAd+U8W+c5Yk4f3PSCL68oAjpCG6NUtmh67MD+hifCjM+LIG8R9oDtVgefQ68jImAtsiInBwEFisRkYHBjztw==",
|
||||
"requires": {
|
||||
"request-stats": "3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"http-headers": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/http-headers/-/http-headers-3.0.2.tgz",
|
||||
"integrity": "sha512-87E1I+2Wg4dxxz4rcxElo3dxO/w1ZtgL1yA0Sb6vH3qU16vRKq1NjWQv9SCY3ly2OQROcoxHZOUpmelS+k6wOw==",
|
||||
"requires": {
|
||||
"next-line": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"next-line": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/next-line/-/next-line-1.1.0.tgz",
|
||||
"integrity": "sha1-/K5XhTBStqm66CCOQN19PC0wRgM="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"request-stats": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/request-stats/-/request-stats-3.0.0.tgz",
|
||||
"integrity": "sha1-dpFV3Il0141KHLh7vxTqq5ha/iU=",
|
||||
"requires": {
|
||||
"http-headers": "^3.0.1",
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@sap/hana-client": {
|
||||
"version": "2.4.167",
|
||||
"resolved": "https://npm.sap.com/@sap/hana-client/-/hana-client-2.4.167.tgz",
|
||||
"integrity": "sha512-nUIOcuNa6xhUPr49RR497Pg+UYB/Lb/X2SM2woQGaCeY23mkaQy5w/+TVAgqmW0i0WQhRC1BJ8tXOR2TmLYzmg==",
|
||||
"requires": {
|
||||
"debug": "3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
}
|
||||
}
|
||||
},
|
||||
"accept-language": {
|
||||
"version": "2.0.16",
|
||||
"resolved": "https://registry.npmjs.org/accept-language/-/accept-language-2.0.16.tgz",
|
||||
"integrity": "sha1-uefScQd0rWCfJHbzz+GkkrVgYb4=",
|
||||
"requires": {
|
||||
"bcp47": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
},
|
||||
"async": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz",
|
||||
"integrity": "sha1-YqVrJ5yYoR0JhwlqAcw+6463u9c=",
|
||||
"requires": {
|
||||
"lodash": "^4.14.0"
|
||||
}
|
||||
},
|
||||
"bcp47": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bcp47/-/bcp47-1.1.2.tgz",
|
||||
"integrity": "sha1-NUvjMH/9CEM6ePXh4glYRfifx/4="
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz",
|
||||
"integrity": "sha1-4mifjzVvrWLMplo6kcXfX5VRaS8="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.13",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.13.tgz",
|
||||
"integrity": "sha512-vm3/XWXfWtRua0FkUyEHBZy8kCPjErNBT9fJx8Zvs+U6zjqPbTUOpkaoum3O5uiA8sm+yNMHXfYkTUHFoMxFNA=="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@sinonjs/commons": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.3.1.tgz",
|
||||
@ -1200,16 +1522,29 @@
|
||||
"yargs": "^11.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"invert-kv": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
|
||||
"integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA=="
|
||||
},
|
||||
"lcid": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
|
||||
"integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
|
||||
"requires": {
|
||||
"invert-kv": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"yargs": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz",
|
||||
"integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==",
|
||||
"version": "11.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.1.tgz",
|
||||
"integrity": "sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==",
|
||||
"requires": {
|
||||
"cliui": "^4.0.0",
|
||||
"decamelize": "^1.1.1",
|
||||
"find-up": "^2.1.0",
|
||||
"get-caller-file": "^1.0.1",
|
||||
"os-locale": "^2.0.0",
|
||||
"os-locale": "^3.1.0",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^1.0.1",
|
||||
"set-blocking": "^2.0.0",
|
||||
@ -1217,6 +1552,26 @@
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^3.2.1",
|
||||
"yargs-parser": "^9.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"os-locale": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
|
||||
"integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
|
||||
"requires": {
|
||||
"execa": "^1.0.0",
|
||||
"lcid": "^2.0.0",
|
||||
"mem": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "9.0.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz",
|
||||
"integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=",
|
||||
"requires": {
|
||||
"camelcase": "^4.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1754,11 +2109,13 @@
|
||||
}
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
|
||||
"integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
|
||||
"version": "6.0.5",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
|
||||
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
|
||||
"requires": {
|
||||
"lru-cache": "^4.0.1",
|
||||
"nice-try": "^1.0.4",
|
||||
"path-key": "^2.0.1",
|
||||
"semver": "^5.5.0",
|
||||
"shebang-command": "^1.2.0",
|
||||
"which": "^1.2.9"
|
||||
}
|
||||
@ -2277,17 +2634,36 @@
|
||||
}
|
||||
},
|
||||
"execa": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
|
||||
"integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
|
||||
"integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
|
||||
"requires": {
|
||||
"cross-spawn": "^5.0.1",
|
||||
"get-stream": "^3.0.0",
|
||||
"cross-spawn": "^6.0.0",
|
||||
"get-stream": "^4.0.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"npm-run-path": "^2.0.0",
|
||||
"p-finally": "^1.0.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"strip-eof": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"get-stream": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
||||
"integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
|
||||
"requires": {
|
||||
"pump": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"requires": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"expand-brackets": {
|
||||
@ -2691,8 +3067,7 @@
|
||||
"version": "2.1.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
@ -2716,15 +3091,13 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@ -2734,22 +3107,19 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
@ -2870,8 +3240,7 @@
|
||||
"version": "2.0.3",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
@ -2885,7 +3254,6 @@
|
||||
"resolved": false,
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
@ -2902,7 +3270,6 @@
|
||||
"resolved": false,
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
@ -2911,15 +3278,13 @@
|
||||
"version": "0.0.8",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
@ -3008,8 +3373,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
@ -3023,7 +3387,6 @@
|
||||
"resolved": false,
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
@ -3119,8 +3482,7 @@
|
||||
"version": "5.1.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
@ -3162,7 +3524,6 @@
|
||||
"resolved": false,
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
@ -3184,7 +3545,6 @@
|
||||
"resolved": false,
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
@ -3242,8 +3602,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
@ -3315,7 +3674,7 @@
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -3466,7 +3825,8 @@
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
|
||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
|
||||
"dev": true
|
||||
},
|
||||
"get-value": {
|
||||
"version": "2.0.6",
|
||||
@ -3748,7 +4108,7 @@
|
||||
},
|
||||
"os-locale": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
|
||||
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -4130,9 +4490,9 @@
|
||||
}
|
||||
},
|
||||
"handlebars": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
|
||||
"integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
|
||||
"integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"neo-async": "^2.6.0",
|
||||
@ -4474,7 +4834,8 @@
|
||||
"invert-kv": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
|
||||
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
|
||||
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
|
||||
"dev": true
|
||||
},
|
||||
"is-absolute": {
|
||||
"version": "1.0.0",
|
||||
@ -4488,7 +4849,7 @@
|
||||
},
|
||||
"is-accessor-descriptor": {
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
|
||||
"resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
|
||||
"integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -4553,7 +4914,7 @@
|
||||
},
|
||||
"is-data-descriptor": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
|
||||
"resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
|
||||
"integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -5027,6 +5388,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
|
||||
"integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"invert-kv": "^1.0.0"
|
||||
}
|
||||
@ -5280,7 +5642,7 @@
|
||||
},
|
||||
"load-json-file": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
||||
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -5293,7 +5655,7 @@
|
||||
"dependencies": {
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
||||
"dev": true
|
||||
}
|
||||
@ -5415,6 +5777,7 @@
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
|
||||
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pseudomap": "^1.0.2",
|
||||
"yallist": "^2.1.2"
|
||||
@ -5501,11 +5864,20 @@
|
||||
}
|
||||
},
|
||||
"mem": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
|
||||
"integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
|
||||
"integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
|
||||
"requires": {
|
||||
"mimic-fn": "^1.0.0"
|
||||
"map-age-cleaner": "^0.1.1",
|
||||
"mimic-fn": "^2.0.0",
|
||||
"p-is-promise": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"memoizee": {
|
||||
@ -6178,9 +6550,9 @@
|
||||
}
|
||||
},
|
||||
"neo-async": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz",
|
||||
"integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==",
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
|
||||
"integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
|
||||
"dev": true
|
||||
},
|
||||
"next-tick": {
|
||||
@ -6547,16 +6919,6 @@
|
||||
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
|
||||
"dev": true
|
||||
},
|
||||
"os-locale": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
|
||||
"integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
|
||||
"requires": {
|
||||
"execa": "^0.7.0",
|
||||
"lcid": "^1.0.0",
|
||||
"mem": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
@ -6753,7 +7115,7 @@
|
||||
"dependencies": {
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
||||
"dev": true
|
||||
}
|
||||
@ -7030,7 +7392,8 @@
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
|
||||
"dev": true
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.1.32",
|
||||
@ -7097,7 +7460,7 @@
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||
"dev": true
|
||||
}
|
||||
@ -7565,9 +7928,9 @@
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
|
||||
},
|
||||
"set-value": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
|
||||
"integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
|
||||
"integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1",
|
||||
@ -8423,16 +8786,23 @@
|
||||
"dev": true
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.4.9",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
|
||||
"integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==",
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.7.2.tgz",
|
||||
"integrity": "sha512-uhRwZcANNWVLrxLfNFEdltoPNhECUR3lc+UdJoG9CBpMcSnKyWA94tc3eAujB1GcMY5Uwq8ZMp4qWpxWYDQmaA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"commander": "~2.17.1",
|
||||
"commander": "~2.20.3",
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
@ -8472,38 +8842,15 @@
|
||||
"dev": true
|
||||
},
|
||||
"union-value": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
|
||||
"integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
|
||||
"integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"arr-union": "^3.1.0",
|
||||
"get-value": "^2.0.6",
|
||||
"is-extendable": "^0.1.1",
|
||||
"set-value": "^0.4.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"extend-shallow": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-extendable": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"set-value": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
|
||||
"integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1",
|
||||
"is-extendable": "^0.1.1",
|
||||
"is-plain-object": "^2.0.1",
|
||||
"to-object-path": "^0.3.0"
|
||||
}
|
||||
}
|
||||
"set-value": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"unique-stream": {
|
||||
@ -8797,7 +9144,8 @@
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
|
||||
"dev": true
|
||||
},
|
||||
"yargonaut": {
|
||||
"version": "1.1.4",
|
||||
@ -9032,14 +9380,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "9.0.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz",
|
||||
"integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=",
|
||||
"requires": {
|
||||
"camelcase": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"yargs-unparser": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz",
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
"browser": {
|
||||
"./browser/driver/postgres/PostgresDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js",
|
||||
"./browser/driver/oracle/OracleDriver.ts": "./browser/platform/BrowserDisabledDriversDummy.js",
|
||||
"./browser/driver/sap/SapDriver.ts": "./browser/platform/BrowserDisabledDriversDummy.js",
|
||||
"./browser/driver/mysql/MysqlDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js",
|
||||
"./browser/driver/sqlserver/SqlServerDriver.ts": "./browser/platform/BrowserDisabledDriversDummy.js",
|
||||
"./browser/driver/mongodb/MongoDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js",
|
||||
@ -46,6 +47,7 @@
|
||||
"oracle-orm"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@sap/hdbext": "^6.1.1",
|
||||
"@types/chai": "^4.1.2",
|
||||
"@types/chai-as-promised": "7.1.0",
|
||||
"@types/debug": "4.1.2",
|
||||
|
||||
@ -3,63 +3,20 @@ import {ConnectionOptions, createConnection} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
|
||||
const options: ConnectionOptions = {
|
||||
// type: "oracle",
|
||||
// host: "localhost",
|
||||
// username: "system",
|
||||
// password: "oracle",
|
||||
// port: 1521,
|
||||
// sid: "xe.oracle.docker",
|
||||
"name": "mysql",
|
||||
"type": "mysql",
|
||||
"host": "localhost",
|
||||
"port": 3306,
|
||||
"username": "test",
|
||||
"password": "test",
|
||||
"database": "test",
|
||||
// type: "postgres",
|
||||
// host: "localhost",
|
||||
// port: 5432,
|
||||
// username: "test",
|
||||
// password: "test",
|
||||
// database: "test",
|
||||
// "type": "mssql",
|
||||
// "host": "192.168.1.6",
|
||||
// "username": "sa",
|
||||
// "password": "admin12345",
|
||||
// "database": "test",
|
||||
// port: 1521,
|
||||
// type: "sqlite",
|
||||
// database: "temp/sqlitedb.db",
|
||||
// logger: "file",
|
||||
// logging: ["query", "error"],
|
||||
// logging: ["error", "schema", "query"],
|
||||
// maxQueryExecutionTime: 90,
|
||||
"name": "sap",
|
||||
"type": "sap",
|
||||
"host": "192.168.56.102",
|
||||
"port": 39015,
|
||||
"username": "SYSTEM",
|
||||
"password": "MySuperHanaPwd123!",
|
||||
"database": "HXE",
|
||||
"logging": true,
|
||||
synchronize: true,
|
||||
entities: [Post]
|
||||
};
|
||||
|
||||
createConnection(options).then(async connection => {
|
||||
|
||||
// const posts: Post[] = [];
|
||||
// for (let i = 0; i < 100; i++) {
|
||||
// let post = new Post();
|
||||
// post.text = "Hello how are you?";
|
||||
// post.title = "hello";
|
||||
// post.likesCount = 100;
|
||||
// posts.push(post);
|
||||
// }
|
||||
//
|
||||
// await connection.manager.save(posts);
|
||||
|
||||
// try {
|
||||
// await connection.query("CREATE DATABASE 'aaaa' AND DIE");
|
||||
//
|
||||
// } catch (err) {
|
||||
// console.log("-------------------------------");
|
||||
// console.log("ERRROR: ", err instanceof QueryFailedError);
|
||||
// console.log(err);
|
||||
// }
|
||||
|
||||
let post = new Post();
|
||||
post.text = "Hello how are you?";
|
||||
post.title = "hello";
|
||||
|
||||
16
src/cache/DbQueryResultCache.ts
vendored
16
src/cache/DbQueryResultCache.ts
vendored
@ -1,14 +1,14 @@
|
||||
import {QueryResultCache} from "./QueryResultCache";
|
||||
import {QueryResultCacheOptions} from "./QueryResultCacheOptions";
|
||||
import {Table} from "../schema-builder/table/Table";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver";
|
||||
import {MssqlParameter} from "../driver/sqlserver/MssqlParameter";
|
||||
import {ObjectLiteral} from "../common/ObjectLiteral";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {OracleDriver} from "../driver/oracle/OracleDriver";
|
||||
import {PostgresConnectionOptions} from "../driver/postgres/PostgresConnectionOptions";
|
||||
import {MssqlParameter} from "../driver/sqlserver/MssqlParameter";
|
||||
import {SqlServerConnectionOptions} from "../driver/sqlserver/SqlServerConnectionOptions";
|
||||
import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
import {Table} from "../schema-builder/table/Table";
|
||||
import {QueryResultCache} from "./QueryResultCache";
|
||||
import {QueryResultCacheOptions} from "./QueryResultCacheOptions";
|
||||
|
||||
/**
|
||||
* Caches query result into current database, into separate table called "query-result-cache".
|
||||
@ -28,7 +28,7 @@ export class DbQueryResultCache implements QueryResultCache {
|
||||
constructor(protected connection: Connection) {
|
||||
|
||||
const options = <SqlServerConnectionOptions|PostgresConnectionOptions>this.connection.driver.options;
|
||||
const cacheOptions = typeof this.connection.options.cache === "object" ? this.connection.options.cache : {};
|
||||
const cacheOptions = typeof this.connection.options.cache === "object" ? this.connection.options.cache : {};
|
||||
const cacheTableName = cacheOptions.tableName || "query-result-cache";
|
||||
|
||||
this.queryResultCacheTable = this.connection.driver.buildTableName(cacheTableName, options.schema, options.database);
|
||||
|
||||
@ -257,7 +257,7 @@ export class Connection {
|
||||
*/
|
||||
// TODO rename
|
||||
async dropDatabase(): Promise<void> {
|
||||
const queryRunner = await this.createQueryRunner("master");
|
||||
const queryRunner = this.createQueryRunner("master");
|
||||
try {
|
||||
if (this.driver instanceof SqlServerDriver || this.driver instanceof MysqlDriver || this.driver instanceof AuroraDataApiDriver) {
|
||||
const databases: string[] = this.driver.database ? [this.driver.database] : [];
|
||||
|
||||
@ -11,6 +11,7 @@ import {ReactNativeConnectionOptions} from "../driver/react-native/ReactNativeCo
|
||||
import {NativescriptConnectionOptions} from "../driver/nativescript/NativescriptConnectionOptions";
|
||||
import {ExpoConnectionOptions} from "../driver/expo/ExpoConnectionOptions";
|
||||
import {AuroraDataApiConnectionOptions} from "../driver/aurora-data-api/AuroraDataApiConnectionOptions";
|
||||
import {SapConnectionOptions} from "../driver/sap/SapConnectionOptions";
|
||||
|
||||
|
||||
/**
|
||||
@ -24,6 +25,7 @@ export type ConnectionOptions =
|
||||
CockroachConnectionOptions|
|
||||
SqliteConnectionOptions|
|
||||
SqlServerConnectionOptions|
|
||||
SapConnectionOptions|
|
||||
OracleConnectionOptions|
|
||||
CordovaConnectionOptions|
|
||||
NativescriptConnectionOptions|
|
||||
|
||||
@ -14,6 +14,7 @@ import {ExpoDriver} from "./expo/ExpoDriver";
|
||||
import {AuroraDataApiDriver} from "./aurora-data-api/AuroraDataApiDriver";
|
||||
import {Driver} from "./Driver";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {SapDriver} from "./sap/SapDriver";
|
||||
|
||||
/**
|
||||
* Helps to create drivers.
|
||||
@ -32,6 +33,8 @@ export class DriverFactory {
|
||||
return new PostgresDriver(connection);
|
||||
case "cockroachdb":
|
||||
return new CockroachDriver(connection);
|
||||
case "sap":
|
||||
return new SapDriver(connection);
|
||||
case "mariadb":
|
||||
return new MysqlDriver(connection);
|
||||
case "sqlite":
|
||||
|
||||
@ -1533,7 +1533,7 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner
|
||||
const foreignKeys = dbForeignKeys.filter(dbFk => dbFk["constraint_name"] === dbForeignKey["constraint_name"]);
|
||||
|
||||
// if referenced table located in currently used schema, we don't need to concat schema name to table name.
|
||||
const schema = dbForeignKey["referenced_table_schema"] === currentSchema ? undefined : dbTable["referenced_table_schema"];
|
||||
const schema = dbForeignKey["referenced_table_schema"] === currentSchema ? undefined : dbForeignKey["referenced_table_schema"];
|
||||
const referencedTableName = this.driver.buildTableName(dbForeignKey["referenced_table_name"], schema);
|
||||
|
||||
return new TableForeignKey({
|
||||
|
||||
@ -1612,7 +1612,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
|
||||
const foreignKeys = dbForeignKeys.filter(dbFk => dbFk["constraint_name"] === dbForeignKey["constraint_name"]);
|
||||
|
||||
// if referenced table located in currently used schema, we don't need to concat schema name to table name.
|
||||
const schema = dbForeignKey["referenced_table_schema"] === currentSchema ? undefined : dbTable["referenced_table_schema"];
|
||||
const schema = dbForeignKey["referenced_table_schema"] === currentSchema ? undefined : dbForeignKey["referenced_table_schema"];
|
||||
const referencedTableName = this.driver.buildTableName(dbForeignKey["referenced_table_name"], schema);
|
||||
|
||||
return new TableForeignKey({
|
||||
|
||||
31
src/driver/sap/SapConnectionCredentialsOptions.ts
Normal file
31
src/driver/sap/SapConnectionCredentialsOptions.ts
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* SAP Hana specific connection credential options.
|
||||
*/
|
||||
export interface SapConnectionCredentialsOptions {
|
||||
|
||||
/**
|
||||
* Database host.
|
||||
*/
|
||||
readonly host?: string;
|
||||
|
||||
/**
|
||||
* Database host port.
|
||||
*/
|
||||
readonly port?: number;
|
||||
|
||||
/**
|
||||
* Database username.
|
||||
*/
|
||||
readonly username?: string;
|
||||
|
||||
/**
|
||||
* Database password.
|
||||
*/
|
||||
readonly password?: string;
|
||||
|
||||
/**
|
||||
* Database name to connect to.
|
||||
*/
|
||||
readonly database?: string;
|
||||
|
||||
}
|
||||
19
src/driver/sap/SapConnectionOptions.ts
Normal file
19
src/driver/sap/SapConnectionOptions.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import {BaseConnectionOptions} from "../../connection/BaseConnectionOptions";
|
||||
import {SapConnectionCredentialsOptions} from "./SapConnectionCredentialsOptions";
|
||||
|
||||
/**
|
||||
* SAP Hana specific connection options.
|
||||
*/
|
||||
export interface SapConnectionOptions extends BaseConnectionOptions, SapConnectionCredentialsOptions {
|
||||
|
||||
/**
|
||||
* Database type.
|
||||
*/
|
||||
readonly type: "sap";
|
||||
|
||||
/**
|
||||
* Database schema.
|
||||
*/
|
||||
readonly schema?: string;
|
||||
|
||||
}
|
||||
645
src/driver/sap/SapDriver.ts
Normal file
645
src/driver/sap/SapDriver.ts
Normal file
@ -0,0 +1,645 @@
|
||||
import {ColumnType, Connection, EntityMetadata, ObjectLiteral, TableColumn} from "../..";
|
||||
import {DriverPackageNotInstalledError} from "../../error/DriverPackageNotInstalledError";
|
||||
import {ColumnMetadata} from "../../metadata/ColumnMetadata";
|
||||
import {PlatformTools} from "../../platform/PlatformTools";
|
||||
import {RdbmsSchemaBuilder} from "../../schema-builder/RdbmsSchemaBuilder";
|
||||
import {ApplyValueTransformers} from "../../util/ApplyValueTransformers";
|
||||
import {DateUtils} from "../../util/DateUtils";
|
||||
import {OrmUtils} from "../../util/OrmUtils";
|
||||
import {Driver} from "../Driver";
|
||||
import {DataTypeDefaults} from "../types/DataTypeDefaults";
|
||||
import {MappedColumnTypes} from "../types/MappedColumnTypes";
|
||||
import {SapConnectionOptions} from "./SapConnectionOptions";
|
||||
import {SapQueryRunner} from "./SapQueryRunner";
|
||||
|
||||
/**
|
||||
* Organizes communication with SAP Hana DBMS.
|
||||
*
|
||||
* todo: looks like there is no built in support for connection pooling, we need to figure out something
|
||||
*/
|
||||
export class SapDriver implements Driver {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Connection used by driver.
|
||||
*/
|
||||
connection: Connection;
|
||||
|
||||
/**
|
||||
* Hana client instance.
|
||||
*/
|
||||
client: any;
|
||||
|
||||
/**
|
||||
* Pool for master database.
|
||||
*/
|
||||
master: any;
|
||||
|
||||
/**
|
||||
* Pool for slave databases.
|
||||
* Used in replication.
|
||||
*/
|
||||
slaves: any[] = [];
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Implemented Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Connection options.
|
||||
*/
|
||||
options: SapConnectionOptions;
|
||||
|
||||
/**
|
||||
* Master database used to perform all write queries.
|
||||
*/
|
||||
database?: string;
|
||||
|
||||
/**
|
||||
* Indicates if replication is enabled.
|
||||
*/
|
||||
isReplicated: boolean = false;
|
||||
|
||||
/**
|
||||
* Indicates if tree tables are supported by this driver.
|
||||
*/
|
||||
treeSupport = true;
|
||||
|
||||
/**
|
||||
* Gets list of supported column data types by a driver.
|
||||
*
|
||||
* @see https://help.sap.com/viewer/4fe29514fd584807ac9f2a04f6754767/2.0.03/en-US/20a1569875191014b507cf392724b7eb.html
|
||||
*/
|
||||
supportedDataTypes: ColumnType[] = [
|
||||
"tinyint",
|
||||
"smallint",
|
||||
"int",
|
||||
"integer",
|
||||
"bigint",
|
||||
"smalldecimal",
|
||||
"decimal",
|
||||
"dec",
|
||||
"real",
|
||||
"double",
|
||||
"float",
|
||||
"date",
|
||||
"time",
|
||||
"seconddate",
|
||||
"timestamp",
|
||||
"boolean",
|
||||
"char",
|
||||
"nchar",
|
||||
"varchar",
|
||||
"nvarchar",
|
||||
"text",
|
||||
"alphanum",
|
||||
"shorttext",
|
||||
"array",
|
||||
"varbinary",
|
||||
"blob",
|
||||
"clob",
|
||||
"nclob",
|
||||
"st_geometry",
|
||||
"st_point",
|
||||
];
|
||||
|
||||
/**
|
||||
* Gets list of spatial column data types.
|
||||
*/
|
||||
spatialTypes: ColumnType[] = [
|
||||
"st_geometry",
|
||||
"st_point",
|
||||
];
|
||||
|
||||
/**
|
||||
* Gets list of column data types that support length by a driver.
|
||||
*/
|
||||
withLengthColumnTypes: ColumnType[] = [
|
||||
"varchar",
|
||||
"nvarchar",
|
||||
"alphanum",
|
||||
"shorttext",
|
||||
"varbinary"
|
||||
];
|
||||
|
||||
/**
|
||||
* Gets list of column data types that support precision by a driver.
|
||||
*/
|
||||
withPrecisionColumnTypes: ColumnType[] = [
|
||||
"decimal",
|
||||
];
|
||||
|
||||
/**
|
||||
* Gets list of column data types that support scale by a driver.
|
||||
*/
|
||||
withScaleColumnTypes: ColumnType[] = [
|
||||
"decimal",
|
||||
];
|
||||
|
||||
/**
|
||||
* Orm has special columns and we need to know what database column types should be for those types.
|
||||
* Column types are driver dependant.
|
||||
*/
|
||||
mappedDataTypes: MappedColumnTypes = {
|
||||
createDate: "timestamp",
|
||||
createDateDefault: "CURRENT_TIMESTAMP",
|
||||
updateDate: "timestamp",
|
||||
updateDateDefault: "CURRENT_TIMESTAMP",
|
||||
version: "integer",
|
||||
treeLevel: "integer",
|
||||
migrationId: "integer",
|
||||
migrationName: "nvarchar",
|
||||
migrationTimestamp: "bigint",
|
||||
cacheId: "integer",
|
||||
cacheIdentifier: "nvarchar",
|
||||
cacheTime: "bigint",
|
||||
cacheDuration: "integer",
|
||||
cacheQuery: "nvarchar(5000)" as any,
|
||||
cacheResult: "text",
|
||||
metadataType: "nvarchar",
|
||||
metadataDatabase: "nvarchar",
|
||||
metadataSchema: "nvarchar",
|
||||
metadataTable: "nvarchar",
|
||||
metadataName: "nvarchar",
|
||||
metadataValue: "nvarchar(5000)" as any,
|
||||
};
|
||||
|
||||
/**
|
||||
* Default values of length, precision and scale depends on column data type.
|
||||
* Used in the cases when length/precision/scale is not specified by user.
|
||||
*/
|
||||
dataTypeDefaults: DataTypeDefaults = {
|
||||
"char": { length: 1 },
|
||||
"nchar": { length: 1 },
|
||||
"varchar": { length: 255 },
|
||||
"nvarchar": { length: 255 },
|
||||
"shorttext": { length: 255 },
|
||||
"varbinary": { length: 255 },
|
||||
"decimal": { precision: 18, scale: 0 },
|
||||
};
|
||||
|
||||
/**
|
||||
* Max length allowed by SAP HANA for aliases (identifiers).
|
||||
* @see https://help.sap.com/viewer/4fe29514fd584807ac9f2a04f6754767/2.0.03/en-US/20a760537519101497e3cfe07b348f3c.html
|
||||
*/
|
||||
maxAliasLength = 128;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(connection: Connection) {
|
||||
this.connection = connection;
|
||||
this.options = connection.options as SapConnectionOptions;
|
||||
this.loadDependencies();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Implemented Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Performs connection to the database.
|
||||
* Based on pooling options, it can either create connection immediately,
|
||||
* either create a pool and create connection when needed.
|
||||
*/
|
||||
async connect(): Promise<void> {
|
||||
// this.master = await this.createConnection(this.options);
|
||||
this.database = this.options.database;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes any action after connection (e.g. create extensions in Postgres driver).
|
||||
*/
|
||||
afterConnect(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes connection with the database.
|
||||
*/
|
||||
async disconnect(): Promise<void> {
|
||||
await this.closeConnection();
|
||||
this.master = undefined;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes connection pool.
|
||||
*/
|
||||
protected async closeConnection(): Promise<void> {
|
||||
return new Promise<void>((ok, fail) => {
|
||||
if (!this.master) return ok();
|
||||
this.master.disconnect((err: any) => err ? fail(err) : ok());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a schema builder used to build and sync a schema.
|
||||
*/
|
||||
createSchemaBuilder() {
|
||||
return new RdbmsSchemaBuilder(this.connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a query runner used to execute database queries.
|
||||
*/
|
||||
createQueryRunner(mode: "master"|"slave" = "master") {
|
||||
return new SapQueryRunner(this, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces parameters in the given sql with special escaping character
|
||||
* and an array of parameter names to be passed to a query.
|
||||
*/
|
||||
escapeQueryWithParameters(sql: string, parameters: ObjectLiteral, nativeParameters: ObjectLiteral): [string, any[]] {
|
||||
const builtParameters: any[] = Object.keys(nativeParameters).map(key => {
|
||||
return nativeParameters[key];
|
||||
});
|
||||
|
||||
if (!parameters || !Object.keys(parameters).length)
|
||||
return [sql, builtParameters];
|
||||
|
||||
const keys = Object.keys(parameters).map(parameter => "(:(\\.\\.\\.)?" + parameter + "\\b)").join("|");
|
||||
sql = sql.replace(new RegExp(keys, "g"), (key: string): string => {
|
||||
let value: any;
|
||||
let isArray = false;
|
||||
if (key.substr(0, 4) === ":...") {
|
||||
isArray = true;
|
||||
value = parameters[key.substr(4)];
|
||||
} else {
|
||||
value = parameters[key.substr(1)];
|
||||
}
|
||||
|
||||
if (isArray) {
|
||||
return value.map((v: any) => {
|
||||
builtParameters.push(v);
|
||||
return "?";
|
||||
// return "$" + builtParameters.length;
|
||||
}).join(", ");
|
||||
|
||||
} else if (value instanceof Function) {
|
||||
return value();
|
||||
|
||||
} else {
|
||||
builtParameters.push(value);
|
||||
return "?";
|
||||
// return "$" + builtParameters.length;
|
||||
}
|
||||
}); // todo: make replace only in value statements, otherwise problems
|
||||
return [sql, builtParameters];
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a column name.
|
||||
*/
|
||||
escape(columnName: string): string {
|
||||
return `"${columnName}"`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build full table name with schema name and table name.
|
||||
* E.g. "mySchema"."myTable"
|
||||
*/
|
||||
buildTableName(tableName: string, schema?: string): string {
|
||||
return schema ? `${schema}.${tableName}` : tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares given value to a value to be persisted, based on its column type and metadata.
|
||||
*/
|
||||
preparePersistentValue(value: any, columnMetadata: ColumnMetadata): any {
|
||||
if (columnMetadata.transformer)
|
||||
value = ApplyValueTransformers.transformTo(columnMetadata.transformer, value);
|
||||
|
||||
if (value === null || value === undefined)
|
||||
return value;
|
||||
|
||||
if (columnMetadata.type === Boolean) {
|
||||
return value === true ? 1 : 0;
|
||||
|
||||
} else if (columnMetadata.type === "date") {
|
||||
return DateUtils.mixedDateToDateString(value);
|
||||
|
||||
} else if (columnMetadata.type === "time") {
|
||||
return DateUtils.mixedDateToTimeString(value);
|
||||
|
||||
} else if (columnMetadata.type === "timestamp"
|
||||
|| columnMetadata.type === Date) {
|
||||
return DateUtils.mixedDateToDatetimeString(value, true);
|
||||
|
||||
} else if (columnMetadata.type === "seconddate") {
|
||||
return DateUtils.mixedDateToDatetimeString(value, false);
|
||||
|
||||
} else if (columnMetadata.type === "simple-array") {
|
||||
return DateUtils.simpleArrayToString(value);
|
||||
|
||||
} else if (columnMetadata.type === "simple-json") {
|
||||
return DateUtils.simpleJsonToString(value);
|
||||
|
||||
} else if (columnMetadata.type === "simple-enum") {
|
||||
return DateUtils.simpleEnumToString(value);
|
||||
|
||||
} else if (columnMetadata.isArray) {
|
||||
return () => `ARRAY(${value.map((it: any) => `'${it}'`)})`;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares given value to a value to be persisted, based on its column type or metadata.
|
||||
*/
|
||||
prepareHydratedValue(value: any, columnMetadata: ColumnMetadata): any {
|
||||
if (value === null || value === undefined)
|
||||
return columnMetadata.transformer ? ApplyValueTransformers.transformFrom(columnMetadata.transformer, value) : value;
|
||||
|
||||
if (columnMetadata.type === Boolean) {
|
||||
value = value ? true : false;
|
||||
|
||||
} else if (columnMetadata.type === "timestamp"
|
||||
|| columnMetadata.type === "seconddate"
|
||||
|| columnMetadata.type === Date) {
|
||||
value = DateUtils.normalizeHydratedDate(value);
|
||||
|
||||
} else if (columnMetadata.type === "date") {
|
||||
value = DateUtils.mixedDateToDateString(value);
|
||||
|
||||
} else if (columnMetadata.type === "time") {
|
||||
value = DateUtils.mixedTimeToString(value);
|
||||
|
||||
} else if (columnMetadata.type === "simple-array") {
|
||||
value = DateUtils.stringToSimpleArray(value);
|
||||
|
||||
} else if (columnMetadata.type === "simple-json") {
|
||||
value = DateUtils.stringToSimpleJson(value);
|
||||
|
||||
} else if (columnMetadata.type === "simple-enum") {
|
||||
value = DateUtils.stringToSimpleEnum(value, columnMetadata);
|
||||
}
|
||||
|
||||
if (columnMetadata.transformer)
|
||||
value = ApplyValueTransformers.transformFrom(columnMetadata.transformer, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a database type from a given column metadata.
|
||||
*/
|
||||
normalizeType(column: { type?: ColumnType, length?: number | string, precision?: number|null, scale?: number }): string {
|
||||
if (column.type === Number || column.type === "integer") {
|
||||
return "integer";
|
||||
|
||||
} else if (column.type === String) {
|
||||
return "nvarchar";
|
||||
|
||||
} else if (column.type === Date) {
|
||||
return "timestamp";
|
||||
|
||||
} else if (column.type === Boolean) {
|
||||
return "boolean";
|
||||
|
||||
} else if ((column.type as any) === Buffer) {
|
||||
return "blob";
|
||||
|
||||
} else if (column.type === "uuid") {
|
||||
return "nvarchar";
|
||||
|
||||
} else if (column.type === "simple-array" || column.type === "simple-json") {
|
||||
return "text";
|
||||
|
||||
} else if (column.type === "simple-enum") {
|
||||
return "nvarchar";
|
||||
|
||||
} else {
|
||||
return column.type as string || "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes "default" value of the column.
|
||||
*/
|
||||
normalizeDefault(columnMetadata: ColumnMetadata): string {
|
||||
const defaultValue = columnMetadata.default;
|
||||
|
||||
if (typeof defaultValue === "number") {
|
||||
return "" + defaultValue;
|
||||
|
||||
} else if (typeof defaultValue === "function") {
|
||||
return defaultValue();
|
||||
|
||||
} else if (typeof defaultValue === "string") {
|
||||
return `'${defaultValue}'`;
|
||||
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes "isUnique" value of the column.
|
||||
*/
|
||||
normalizeIsUnique(column: ColumnMetadata): boolean {
|
||||
return column.entityMetadata.indices.some(idx => idx.isUnique && idx.columns.length === 1 && idx.columns[0] === column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns default column lengths, which is required on column creation.
|
||||
*/
|
||||
getColumnLength(column: ColumnMetadata|TableColumn): string {
|
||||
if (column.length)
|
||||
return column.length.toString();
|
||||
|
||||
if (column.generationStrategy === "uuid")
|
||||
return "36";
|
||||
|
||||
switch (column.type) {
|
||||
case "varchar":
|
||||
case "nvarchar":
|
||||
case "shorttext":
|
||||
case String:
|
||||
return "255";
|
||||
case "alphanum":
|
||||
return "127";
|
||||
case "varbinary":
|
||||
return "255";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates column type definition including length, precision and scale
|
||||
*/
|
||||
createFullType(column: TableColumn): string {
|
||||
let type = column.type;
|
||||
|
||||
// used 'getColumnLength()' method, because SqlServer sets `varchar` and `nvarchar` length to 1 by default.
|
||||
if (this.getColumnLength(column)) {
|
||||
type += `(${this.getColumnLength(column)})`;
|
||||
|
||||
} else if (column.precision !== null && column.precision !== undefined && column.scale !== null && column.scale !== undefined) {
|
||||
type += `(${column.precision},${column.scale})`;
|
||||
|
||||
} else if (column.precision !== null && column.precision !== undefined) {
|
||||
type += `(${column.precision})`;
|
||||
}
|
||||
|
||||
if (column.isArray)
|
||||
type += " array";
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a new database connection to a master server.
|
||||
* Used for replication.
|
||||
* If replication is not setup then returns default connection's database connection.
|
||||
*/
|
||||
obtainMasterConnection(): Promise<any> {
|
||||
return this.createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a new database connection to a slave server.
|
||||
* Used for replication.
|
||||
* If replication is not setup then returns master (default) connection's database connection.
|
||||
*/
|
||||
obtainSlaveConnection(): Promise<any> {
|
||||
// return Promise.resolve(this.master);
|
||||
return this.createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates generated map of values generated or returned by database after INSERT query.
|
||||
*/
|
||||
createGeneratedMap(metadata: EntityMetadata, insertResult: ObjectLiteral) {
|
||||
const generatedMap = metadata.generatedColumns.reduce((map, generatedColumn) => {
|
||||
let value: any;
|
||||
if (generatedColumn.generationStrategy === "increment" && insertResult) {
|
||||
value = insertResult;
|
||||
// } else if (generatedColumn.generationStrategy === "uuid") {
|
||||
// console.log("getting db value:", generatedColumn.databaseName);
|
||||
// value = generatedColumn.getEntityValue(uuidMap);
|
||||
}
|
||||
|
||||
return OrmUtils.mergeDeep(map, generatedColumn.createValueMap(value));
|
||||
}, {} as ObjectLiteral);
|
||||
|
||||
return Object.keys(generatedMap).length > 0 ? generatedMap : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Differentiate columns of this table and columns from the given column metadatas columns
|
||||
* and returns only changed.
|
||||
*/
|
||||
findChangedColumns(tableColumns: TableColumn[], columnMetadatas: ColumnMetadata[]): ColumnMetadata[] {
|
||||
return columnMetadatas.filter(columnMetadata => {
|
||||
const tableColumn = tableColumns.find(c => c.name === columnMetadata.databaseName);
|
||||
if (!tableColumn)
|
||||
return false; // we don't need new columns, we only need exist and changed
|
||||
|
||||
// console.log("table:", columnMetadata.entityMetadata.tableName);
|
||||
// console.log("name:", tableColumn.name, columnMetadata.databaseName);
|
||||
// console.log("type:", tableColumn.type, this.normalizeType(columnMetadata));
|
||||
// console.log("length:", tableColumn.length, columnMetadata.length);
|
||||
// console.log("width:", tableColumn.width, columnMetadata.width);
|
||||
// console.log("precision:", tableColumn.precision, columnMetadata.precision);
|
||||
// console.log("scale:", tableColumn.scale, columnMetadata.scale);
|
||||
// console.log("default:", tableColumn.default, columnMetadata.default);
|
||||
// console.log("isPrimary:", tableColumn.isPrimary, columnMetadata.isPrimary);
|
||||
// console.log("isNullable:", tableColumn.isNullable, columnMetadata.isNullable);
|
||||
// console.log("isUnique:", tableColumn.isUnique, this.normalizeIsUnique(columnMetadata));
|
||||
// console.log("isGenerated:", tableColumn.isGenerated, columnMetadata.isGenerated);
|
||||
// console.log((columnMetadata.generationStrategy !== "uuid" && tableColumn.isGenerated !== columnMetadata.isGenerated));
|
||||
// console.log("==========================================");
|
||||
|
||||
return tableColumn.name !== columnMetadata.databaseName
|
||||
|| tableColumn.type !== this.normalizeType(columnMetadata)
|
||||
|| tableColumn.length !== columnMetadata.length
|
||||
|| tableColumn.precision !== columnMetadata.precision
|
||||
|| tableColumn.scale !== columnMetadata.scale
|
||||
// || tableColumn.comment !== columnMetadata.comment || // todo
|
||||
|| (!tableColumn.isGenerated && this.normalizeDefault(columnMetadata) !== tableColumn.default) // we included check for generated here, because generated columns already can have default values
|
||||
|| tableColumn.isPrimary !== columnMetadata.isPrimary
|
||||
|| tableColumn.isNullable !== columnMetadata.isNullable
|
||||
|| tableColumn.isUnique !== this.normalizeIsUnique(columnMetadata)
|
||||
|| tableColumn.isGenerated !== columnMetadata.isGenerated;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if driver supports RETURNING / OUTPUT statement.
|
||||
*/
|
||||
isReturningSqlSupported(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if driver supports uuid values generation on its own.
|
||||
*/
|
||||
isUUIDGenerationSupported(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an escaped parameter.
|
||||
*/
|
||||
createParameter(parameterName: string, index: number): string {
|
||||
return "?";
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* If driver dependency is not given explicitly, then try to load it via "require".
|
||||
*/
|
||||
protected loadDependencies(): void {
|
||||
try {
|
||||
this.client = PlatformTools.load("@sap/hdbext");
|
||||
|
||||
} catch (e) { // todo: better error for browser env
|
||||
throw new DriverPackageNotInstalledError("SAP Hana", "hdb");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new connection pool for a given database credentials.
|
||||
*/
|
||||
protected createConnection(): Promise<any> {
|
||||
|
||||
// pooling is enabled either when its set explicitly to true,
|
||||
// either when its not defined at all (e.g. enabled by default)
|
||||
return new Promise<any>((ok, fail) => {
|
||||
try {
|
||||
// const master = ();
|
||||
this.client.createConnection({
|
||||
host: this.options.host,
|
||||
port: this.options.port,
|
||||
uid: this.options.username,
|
||||
pwd: this.options.password,
|
||||
databaseName: this.options.database,
|
||||
pooling: true,
|
||||
...this.options.extra
|
||||
}, (err: any, master: any) => {
|
||||
if (err) {
|
||||
fail(err);
|
||||
return;
|
||||
}
|
||||
ok(master);
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
fail(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
1976
src/driver/sap/SapQueryRunner.ts
Normal file
1976
src/driver/sap/SapQueryRunner.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -613,7 +613,7 @@ export class SqlServerDriver implements Driver {
|
||||
});
|
||||
}
|
||||
private lowerDefaultValueIfNessesary(value: string | undefined) {
|
||||
// SqlServer saves function calls in default value as lowercase #2733
|
||||
// SqlServer saves function calls in default value as lowercase https://github.com/typeorm/typeorm/issues/2733
|
||||
if (!value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -1,17 +1,18 @@
|
||||
/**
|
||||
* Column types used for @PrimaryGeneratedColumn() decorator.
|
||||
*/
|
||||
export type PrimaryGeneratedColumnType = "int" // mysql, mssql, oracle, sqlite
|
||||
export type PrimaryGeneratedColumnType = "int" // mysql, mssql, oracle, sqlite, sap
|
||||
|"int2" // postgres, sqlite, cockroachdb
|
||||
|"int4" // postgres, cockroachdb
|
||||
|"int8" // postgres, sqlite, cockroachdb
|
||||
|"integer" // postgres, oracle, sqlite, mysql, cockroachdb
|
||||
|"tinyint" // mysql, mssql, sqlite
|
||||
|"smallint" // mysql, postgres, mssql, oracle, sqlite, cockroachdb
|
||||
|"integer" // postgres, oracle, sqlite, mysql, cockroachdb, sap
|
||||
|"tinyint" // mysql, mssql, sqlite, sap
|
||||
|"smallint" // mysql, postgres, mssql, oracle, sqlite, cockroachdb, sap
|
||||
|"mediumint" // mysql, sqlite
|
||||
|"bigint" // mysql, postgres, mssql, sqlite, cockroachdb
|
||||
|"dec" // oracle, mssql
|
||||
|"decimal" // mysql, postgres, mssql, sqlite
|
||||
|"bigint" // mysql, postgres, mssql, sqlite, cockroachdb, sap
|
||||
|"dec" // oracle, mssql, sap
|
||||
|"decimal" // mysql, postgres, mssql, sqlite, sap
|
||||
|"smalldecimal" // sap
|
||||
|"fixed" // mysql
|
||||
|"numeric" // postgres, mssql, sqlite
|
||||
|"number" // oracle
|
||||
@ -21,7 +22,9 @@ export type PrimaryGeneratedColumnType = "int" // mysql, mssql, oracle, sqlite
|
||||
* Column types where spatial properties are used.
|
||||
*/
|
||||
export type SpatialColumnType = "geometry" // postgres
|
||||
|"geography"; // postgres
|
||||
|"geography" // postgres
|
||||
|"st_geometry" // sap
|
||||
|"st_point"; // sap
|
||||
|
||||
/**
|
||||
* Column types where precision and scale properties are used.
|
||||
@ -30,9 +33,10 @@ export type WithPrecisionColumnType = "float" // mysql, mssql, oracle, sqlite
|
||||
|"double" // mysql, sqlite
|
||||
|"dec" // oracle, mssql, mysql
|
||||
|"decimal" // mysql, postgres, mssql, sqlite
|
||||
|"smalldecimal" // sap
|
||||
|"fixed" // mysql
|
||||
|"numeric" // postgres, mssql, sqlite, mysql
|
||||
|"real" // mysql, postgres, mssql, oracle, sqlite, cockroachdb
|
||||
|"real" // mysql, postgres, mssql, oracle, sqlite, cockroachdb, sap
|
||||
|"double precision" // postgres, oracle, sqlite, mysql, cockroachdb
|
||||
|"number" // oracle
|
||||
|"datetime" // mssql, mysql, sqlite
|
||||
@ -57,14 +61,16 @@ export type WithLengthColumnType = "character varying" // postgres, cockroachdb
|
||||
|"character" // mysql, postgres, sqlite, cockroachdb
|
||||
|"native character" // sqlite
|
||||
|"varchar" // mysql, postgres, mssql, sqlite, cockroachdb
|
||||
|"char" // mysql, postgres, mssql, oracle, cockroachdb
|
||||
|"nchar" // mssql, oracle, sqlite, mysql
|
||||
|"char" // mysql, postgres, mssql, oracle, cockroachdb, sap
|
||||
|"nchar" // mssql, oracle, sqlite, mysql, sap
|
||||
|"national char" // mysql
|
||||
|"varchar2" // oracle
|
||||
|"nvarchar2" // oracle, sqlite
|
||||
|"alphanum" // sap
|
||||
|"shorttext" // sap
|
||||
|"raw" // oracle
|
||||
|"binary" // mssql
|
||||
|"varbinary" // mssql
|
||||
|"varbinary" // mssql, sap
|
||||
|"string"; // cockroachdb
|
||||
|
||||
export type WithWidthColumnType = "tinyint" // mysql
|
||||
@ -86,13 +92,13 @@ export type SimpleColumnType =
|
||||
|"simple-enum" // typeorm-specific, automatically mapped to string
|
||||
|
||||
// numeric types
|
||||
|"bit" // mssql
|
||||
|"int2" // postgres, sqlite, cockroachdb
|
||||
|"integer" // postgres, oracle, sqlite, cockroachdb
|
||||
|"int4" // postgres, cockroachdb
|
||||
|"int8" // postgres, sqlite, cockroachdb
|
||||
|"int64" // cockroachdb
|
||||
|"unsigned big int" // sqlite
|
||||
|"float" // mysql, mssql, oracle, sqlite, sap
|
||||
|"float4" // postgres, cockroachdb
|
||||
|"float8" // postgres, cockroachdb
|
||||
|"smallmoney" // mssql
|
||||
@ -107,21 +113,23 @@ export type SimpleColumnType =
|
||||
|"tinytext" // mysql
|
||||
|"mediumblob" // mysql
|
||||
|"mediumtext" // mysql
|
||||
|"blob" // mysql, oracle, sqlite, cockroachdb
|
||||
|"text" // mysql, postgres, mssql, sqlite, cockroachdb
|
||||
|"blob" // mysql, oracle, sqlite, cockroachdb, sap
|
||||
|"text" // mysql, postgres, mssql, sqlite, cockroachdb, sap
|
||||
|"ntext" // mssql
|
||||
|"citext" // postgres
|
||||
|"hstore" // postgres
|
||||
|"longblob" // mysql
|
||||
|"longtext" // mysql
|
||||
|"alphanum" // sap
|
||||
|"shorttext" // sap
|
||||
|"bytes" // cockroachdb
|
||||
|"bytea" // postgres, cockroachdb
|
||||
|"long" // oracle
|
||||
|"raw" // oracle
|
||||
|"long raw" // oracle
|
||||
|"bfile" // oracle
|
||||
|"clob" // oracle, sqlite
|
||||
|"nclob" // oracle
|
||||
|"clob" // oracle, sqlite, sap
|
||||
|"nclob" // oracle, sap
|
||||
|"image" // mssql
|
||||
|
||||
// date types
|
||||
@ -134,6 +142,7 @@ export type SimpleColumnType =
|
||||
|"interval day to second" // oracle
|
||||
|"interval" // postgres, cockroachdb
|
||||
|"year" // mysql
|
||||
|"seconddate" // sap
|
||||
|
||||
// geometric types
|
||||
|"point" // postgres, mysql
|
||||
@ -150,6 +159,8 @@ export type SimpleColumnType =
|
||||
|"multilinestring" // mysql
|
||||
|"multipolygon" // mysql
|
||||
|"geometrycollection" // mysql
|
||||
|"st_geometry" // sap
|
||||
|"st_point" // sap
|
||||
|
||||
// range types
|
||||
|"int4range" // postgres
|
||||
@ -165,7 +176,7 @@ export type SimpleColumnType =
|
||||
|"cidr" // postgres
|
||||
|"inet" // postgres, cockroachdb
|
||||
|"macaddr"// postgres
|
||||
|"bit" // postgres
|
||||
|"bit" // postgres, mssql
|
||||
|"bit varying" // postgres
|
||||
|"varbit"// postgres
|
||||
|"tsvector" // postgres
|
||||
@ -174,14 +185,14 @@ export type SimpleColumnType =
|
||||
|"xml" // mssql, postgres
|
||||
|"json" // mysql, postgres, cockroachdb
|
||||
|"jsonb" // postgres, cockroachdb
|
||||
|"varbinary" // mssql
|
||||
|"varbinary" // mssql, sap
|
||||
|"hierarchyid" // mssql
|
||||
|"sql_variant" // mssql
|
||||
|"rowid" // oracle
|
||||
|"urowid" // oracle
|
||||
|"uniqueidentifier" // mssql
|
||||
|"rowversion" // mssql
|
||||
|"array" // cockroachdb
|
||||
|"array" // cockroachdb, sap
|
||||
|"cube"; // postgres
|
||||
|
||||
/**
|
||||
|
||||
@ -5,6 +5,7 @@ export type DatabaseType =
|
||||
"mysql"|
|
||||
"postgres"|
|
||||
"cockroachdb"|
|
||||
"sap"|
|
||||
"mariadb"|
|
||||
"sqlite"|
|
||||
"cordova"|
|
||||
|
||||
@ -4,10 +4,10 @@
|
||||
export class OffsetWithoutLimitNotSupportedError extends Error {
|
||||
name = "OffsetWithoutLimitNotSupportedError";
|
||||
|
||||
constructor(driverName: string) {
|
||||
constructor() {
|
||||
super();
|
||||
Object.setPrototypeOf(this, OffsetWithoutLimitNotSupportedError.prototype);
|
||||
this.message = `${driverName} does not support OFFSET without LIMIT in SELECT statements. You must use limit in conjunction with offset function (or take in conjunction with skip function if you are using pagination).`;
|
||||
this.message = `RDBMS does not support OFFSET without LIMIT in SELECT statements. You must use limit in conjunction with offset function (or take in conjunction with skip function if you are using pagination).`;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {CockroachDriver} from "../driver/cockroachdb/CockroachDriver";
|
||||
import {SapDriver} from "../driver/sap/SapDriver";
|
||||
import {EntityMetadata} from "../metadata/EntityMetadata";
|
||||
import {ColumnMetadata} from "../metadata/ColumnMetadata";
|
||||
import {IndexMetadata} from "../metadata/IndexMetadata";
|
||||
@ -129,7 +130,8 @@ export class EntityMetadataBuilder {
|
||||
entityMetadata.foreignKeys.push(foreignKey);
|
||||
}
|
||||
if (uniqueConstraint) {
|
||||
if (this.connection.driver instanceof MysqlDriver || this.connection.driver instanceof AuroraDataApiDriver || this.connection.driver instanceof SqlServerDriver) {
|
||||
if (this.connection.driver instanceof MysqlDriver || this.connection.driver instanceof AuroraDataApiDriver
|
||||
|| this.connection.driver instanceof SqlServerDriver || this.connection.driver instanceof SapDriver) {
|
||||
const index = new IndexMetadata({
|
||||
entityMetadata: uniqueConstraint.entityMetadata,
|
||||
columns: uniqueConstraint.columns,
|
||||
@ -520,8 +522,8 @@ export class EntityMetadataBuilder {
|
||||
});
|
||||
}
|
||||
|
||||
// Mysql stores unique constraints as unique indices.
|
||||
if (this.connection.driver instanceof MysqlDriver || this.connection.driver instanceof AuroraDataApiDriver) {
|
||||
// Mysql and SAP HANA stores unique constraints as unique indices.
|
||||
if (this.connection.driver instanceof MysqlDriver || this.connection.driver instanceof AuroraDataApiDriver || this.connection.driver instanceof SapDriver) {
|
||||
const indices = this.metadataArgsStorage.filterUniques(entityMetadata.inheritanceTree).map(args => {
|
||||
return new IndexMetadata({
|
||||
entityMetadata: entityMetadata,
|
||||
|
||||
@ -3,6 +3,7 @@ import {ObjectLiteral} from "../common/ObjectLiteral";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {PostgresConnectionOptions} from "../driver/postgres/PostgresConnectionOptions";
|
||||
import {PostgresDriver} from "../driver/postgres/PostgresDriver";
|
||||
import {SapDriver} from "../driver/sap/SapDriver";
|
||||
import {SqlServerConnectionOptions} from "../driver/sqlserver/SqlServerConnectionOptions";
|
||||
import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver";
|
||||
import {CannotCreateEntityIdMapError} from "../error/CannotCreateEntityIdMapError";
|
||||
@ -104,7 +105,7 @@ export class EntityMetadata {
|
||||
/**
|
||||
* Enables Sqlite "WITHOUT ROWID" modifier for the "CREATE TABLE" statement
|
||||
*/
|
||||
withoutRowid?: boolean = false;
|
||||
withoutRowid?: boolean = false;
|
||||
|
||||
/**
|
||||
* Original user-given table name (taken from schema or @Entity(tableName) decorator).
|
||||
@ -846,7 +847,7 @@ export class EntityMetadata {
|
||||
*/
|
||||
protected buildTablePath(): string {
|
||||
let tablePath = this.tableName;
|
||||
if (this.schema && ((this.connection.driver instanceof PostgresDriver) || (this.connection.driver instanceof SqlServerDriver))) {
|
||||
if (this.schema && ((this.connection.driver instanceof PostgresDriver) || (this.connection.driver instanceof SqlServerDriver) || (this.connection.driver instanceof SapDriver))) {
|
||||
tablePath = this.schema + "." + tablePath;
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import {SapDriver} from "../driver/sap/SapDriver";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
import {Subject} from "./Subject";
|
||||
import {PromiseUtils} from "../util/PromiseUtils";
|
||||
@ -249,7 +250,8 @@ export class SubjectExecutor {
|
||||
// - when oracle is used, since oracle's bulk insertion is very bad
|
||||
if (subject.changeMaps.length === 0 ||
|
||||
subject.metadata.treeType ||
|
||||
this.queryRunner.connection.driver instanceof OracleDriver) {
|
||||
this.queryRunner.connection.driver instanceof OracleDriver ||
|
||||
this.queryRunner.connection.driver instanceof SapDriver) {
|
||||
singleInsertSubjects.push(subject);
|
||||
|
||||
} else {
|
||||
|
||||
@ -43,6 +43,12 @@ export class PostgresDriver {}
|
||||
*/
|
||||
export class SqlServerDriver {}
|
||||
|
||||
/**
|
||||
* DO NOT IMPORT THIS CLASS -
|
||||
* This is a dummy class for replacement via `package.json` in browser builds
|
||||
*/
|
||||
export class SapDriver {}
|
||||
|
||||
/**
|
||||
* DO NOT IMPORT THIS CLASS -
|
||||
* This is a dummy class for replacement via `package.json` in browser builds
|
||||
|
||||
@ -46,6 +46,12 @@ export class PlatformTools {
|
||||
case "mongodb":
|
||||
return require("mongodb");
|
||||
|
||||
/**
|
||||
* hana
|
||||
*/
|
||||
case "@sap/hdbext":
|
||||
return require("@sap/hdbext");
|
||||
|
||||
/**
|
||||
* mysql
|
||||
*/
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {CockroachDriver} from "../driver/cockroachdb/CockroachDriver";
|
||||
import {SapDriver} from "../driver/sap/SapDriver";
|
||||
import {QueryBuilder} from "./QueryBuilder";
|
||||
import {ObjectLiteral} from "../common/ObjectLiteral";
|
||||
import {ObjectType} from "../common/ObjectType";
|
||||
@ -444,7 +445,7 @@ export class InsertQueryBuilder<Entity> extends QueryBuilder<Entity> {
|
||||
|
||||
// if value for this column was not provided then insert default value
|
||||
} else if (value === undefined) {
|
||||
if (this.connection.driver instanceof AbstractSqliteDriver) { // unfortunately sqlite does not support DEFAULT expression in INSERT queries
|
||||
if (this.connection.driver instanceof AbstractSqliteDriver || this.connection.driver instanceof SapDriver) { // unfortunately sqlite does not support DEFAULT expression in INSERT queries
|
||||
if (column.default !== undefined) { // try to use default defined in the column
|
||||
expression += this.connection.driver.normalizeDefault(column);
|
||||
} else {
|
||||
@ -524,7 +525,7 @@ export class InsertQueryBuilder<Entity> extends QueryBuilder<Entity> {
|
||||
|
||||
// if value for this column was not provided then insert default value
|
||||
} else if (value === undefined) {
|
||||
if (this.connection.driver instanceof AbstractSqliteDriver) {
|
||||
if (this.connection.driver instanceof AbstractSqliteDriver || this.connection.driver instanceof SapDriver) {
|
||||
expression += "NULL";
|
||||
|
||||
} else {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import {SapDriver} from "../driver/sap/SapDriver";
|
||||
import {QueryBuilder} from "./QueryBuilder";
|
||||
import {ObjectLiteral} from "../common/ObjectLiteral";
|
||||
import {QueryExpressionMap} from "./QueryExpressionMap";
|
||||
@ -117,7 +118,7 @@ export class RelationUpdater {
|
||||
|
||||
if (!bulkInserted.length) return;
|
||||
|
||||
if (this.queryBuilder.connection.driver instanceof OracleDriver) {
|
||||
if (this.queryBuilder.connection.driver instanceof OracleDriver || this.queryBuilder.connection.driver instanceof SapDriver) {
|
||||
await Promise.all(bulkInserted.map(value => {
|
||||
return this.queryBuilder
|
||||
.createQueryBuilder()
|
||||
@ -137,4 +138,4 @@ export class RelationUpdater {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import {SapDriver} from "../driver/sap/SapDriver";
|
||||
import {RawSqlResultsToEntityTransformer} from "./transformer/RawSqlResultsToEntityTransformer";
|
||||
import {ObjectLiteral} from "../common/ObjectLiteral";
|
||||
import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver";
|
||||
@ -1592,14 +1593,14 @@ export class SelectQueryBuilder<Entity> extends QueryBuilder<Entity> implements
|
||||
if (offset)
|
||||
return prefix + " OFFSET " + offset + " ROWS";
|
||||
|
||||
} else if (this.connection.driver instanceof MysqlDriver || this.connection.driver instanceof AuroraDataApiDriver) {
|
||||
} else if (this.connection.driver instanceof MysqlDriver || this.connection.driver instanceof AuroraDataApiDriver || this.connection.driver instanceof SapDriver) {
|
||||
|
||||
if (limit && offset)
|
||||
return " LIMIT " + limit + " OFFSET " + offset;
|
||||
if (limit)
|
||||
return " LIMIT " + limit;
|
||||
if (offset)
|
||||
throw new OffsetWithoutLimitNotSupportedError("MySQL");
|
||||
throw new OffsetWithoutLimitNotSupportedError();
|
||||
|
||||
} else if (this.connection.driver instanceof AbstractSqliteDriver) {
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {CockroachDriver} from "../driver/cockroachdb/CockroachDriver";
|
||||
import {SapDriver} from "../driver/sap/SapDriver";
|
||||
import {QueryBuilder} from "./QueryBuilder";
|
||||
import {ObjectLiteral} from "../common/ObjectLiteral";
|
||||
import {Connection} from "../connection/Connection";
|
||||
@ -373,7 +374,8 @@ export class UpdateQueryBuilder<Entity> extends QueryBuilder<Entity> implements
|
||||
let parametersCount = this.connection.driver instanceof MysqlDriver ||
|
||||
this.connection.driver instanceof AuroraDataApiDriver ||
|
||||
this.connection.driver instanceof OracleDriver ||
|
||||
this.connection.driver instanceof AbstractSqliteDriver
|
||||
this.connection.driver instanceof AbstractSqliteDriver ||
|
||||
this.connection.driver instanceof SapDriver
|
||||
? 0 : Object.keys(this.expressionMap.nativeParameters).length;
|
||||
if (metadata) {
|
||||
EntityMetadata.createPropertyPath(metadata, valuesSet).forEach(propertyPath => {
|
||||
@ -401,6 +403,8 @@ export class UpdateQueryBuilder<Entity> extends QueryBuilder<Entity> implements
|
||||
// todo: duplication zone
|
||||
if (value instanceof Function) { // support for SQL expressions in update query
|
||||
updateColumnAndValues.push(this.escape(column.databaseName) + " = " + value());
|
||||
} else if (this.connection.driver instanceof SapDriver && value === null) {
|
||||
updateColumnAndValues.push(this.escape(column.databaseName) + " = NULL");
|
||||
} else {
|
||||
if (this.connection.driver instanceof SqlServerDriver) {
|
||||
value = this.connection.driver.parametrizeValue(column, value);
|
||||
@ -412,7 +416,8 @@ export class UpdateQueryBuilder<Entity> extends QueryBuilder<Entity> implements
|
||||
if (this.connection.driver instanceof MysqlDriver ||
|
||||
this.connection.driver instanceof AuroraDataApiDriver ||
|
||||
this.connection.driver instanceof OracleDriver ||
|
||||
this.connection.driver instanceof AbstractSqliteDriver) {
|
||||
this.connection.driver instanceof AbstractSqliteDriver ||
|
||||
this.connection.driver instanceof SapDriver) {
|
||||
newParameters[paramName] = value;
|
||||
} else {
|
||||
this.expressionMap.nativeParameters[paramName] = value;
|
||||
@ -454,6 +459,8 @@ export class UpdateQueryBuilder<Entity> extends QueryBuilder<Entity> implements
|
||||
// todo: duplication zone
|
||||
if (value instanceof Function) { // support for SQL expressions in update query
|
||||
updateColumnAndValues.push(this.escape(key) + " = " + value());
|
||||
} else if (this.connection.driver instanceof SapDriver && value === null) {
|
||||
updateColumnAndValues.push(this.escape(key) + " = NULL");
|
||||
} else {
|
||||
|
||||
// we need to store array values in a special class to make sure parameter replacement will work correctly
|
||||
@ -463,7 +470,8 @@ export class UpdateQueryBuilder<Entity> extends QueryBuilder<Entity> implements
|
||||
if (this.connection.driver instanceof MysqlDriver ||
|
||||
this.connection.driver instanceof AuroraDataApiDriver ||
|
||||
this.connection.driver instanceof OracleDriver ||
|
||||
this.connection.driver instanceof AbstractSqliteDriver) {
|
||||
this.connection.driver instanceof AbstractSqliteDriver ||
|
||||
this.connection.driver instanceof SapDriver) {
|
||||
newParameters[key] = value;
|
||||
} else {
|
||||
this.expressionMap.nativeParameters[key] = value;
|
||||
@ -484,7 +492,8 @@ export class UpdateQueryBuilder<Entity> extends QueryBuilder<Entity> implements
|
||||
if (this.connection.driver instanceof MysqlDriver ||
|
||||
this.connection.driver instanceof AuroraDataApiDriver ||
|
||||
this.connection.driver instanceof OracleDriver ||
|
||||
this.connection.driver instanceof AbstractSqliteDriver) {
|
||||
this.connection.driver instanceof AbstractSqliteDriver ||
|
||||
this.connection.driver instanceof SapDriver) {
|
||||
this.expressionMap.nativeParameters = Object.assign(newParameters, this.expressionMap.nativeParameters);
|
||||
}
|
||||
|
||||
|
||||
@ -11,5 +11,5 @@ export class DeleteResult {
|
||||
* Number of affected rows/documents
|
||||
* Not all drivers support this
|
||||
*/
|
||||
affected?: number;
|
||||
}
|
||||
affected?: number|null;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {CockroachDriver} from "../driver/cockroachdb/CockroachDriver";
|
||||
import {PostgresConnectionOptions} from "../driver/postgres/PostgresConnectionOptions";
|
||||
import {SapDriver} from "../driver/sap/SapDriver";
|
||||
import {SqlServerConnectionOptions} from "../driver/sqlserver/SqlServerConnectionOptions";
|
||||
import {Table} from "./table/Table";
|
||||
import {TableColumn} from "./table/TableColumn";
|
||||
@ -367,7 +368,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder {
|
||||
// check if table does not exist yet
|
||||
const existTable = this.queryRunner.loadedTables.find(table => {
|
||||
const database = metadata.database && metadata.database !== this.connection.driver.database ? metadata.database : undefined;
|
||||
const schema = metadata.schema || (<SqlServerDriver|PostgresDriver>this.connection.driver).options.schema;
|
||||
const schema = metadata.schema || (<SqlServerDriver|PostgresDriver|SapDriver>this.connection.driver).options.schema;
|
||||
const fullTableName = this.connection.driver.buildTableName(metadata.tableName, schema, database);
|
||||
|
||||
return table.name === fullTableName;
|
||||
|
||||
@ -43,7 +43,7 @@ export class TableForeignKey {
|
||||
onUpdate?: string;
|
||||
|
||||
/**
|
||||
* Set this foreign key constraint as "DEFERRABLE" e.g. check constraints at start
|
||||
* Set this foreign key constraint as "DEFERRABLE" e.g. check constraints at start
|
||||
* or at the end of a transaction
|
||||
*/
|
||||
deferrable?: string;
|
||||
|
||||
@ -100,20 +100,25 @@ export class DateUtils {
|
||||
/**
|
||||
* Converts given value into datetime string in a "YYYY-MM-DD HH-mm-ss" format.
|
||||
*/
|
||||
static mixedDateToDatetimeString(value: Date|any): string|any {
|
||||
static mixedDateToDatetimeString(value: Date|any, useMilliseconds?: boolean): string|any {
|
||||
if (typeof value === "string") {
|
||||
value = new Date(value);
|
||||
}
|
||||
if (value instanceof Date) {
|
||||
return this.formatZerolessValue(value.getFullYear()) + "-" +
|
||||
let finalValue = this.formatZerolessValue(value.getFullYear()) + "-" +
|
||||
this.formatZerolessValue(value.getMonth() + 1) + "-" +
|
||||
this.formatZerolessValue(value.getDate()) + " " +
|
||||
this.formatZerolessValue(value.getHours()) + ":" +
|
||||
this.formatZerolessValue(value.getMinutes()) + ":" +
|
||||
this.formatZerolessValue(value.getSeconds()) + "." +
|
||||
this.formatMilliseconds(value.getMilliseconds());
|
||||
this.formatZerolessValue(value.getSeconds());
|
||||
|
||||
if (useMilliseconds)
|
||||
finalValue += `.${this.formatMilliseconds(value.getMilliseconds())}`;
|
||||
|
||||
value = finalValue;
|
||||
}
|
||||
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -171,7 +176,7 @@ export class DateUtils {
|
||||
|
||||
static stringToSimpleJson(value: any) {
|
||||
try {
|
||||
const simpleJSON = JSON.parse(value);
|
||||
const simpleJSON = JSON.parse(value);
|
||||
return (typeof simpleJSON === "object") ? simpleJSON : {};
|
||||
} catch (err) {
|
||||
return {};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import "reflect-metadata";
|
||||
import {expect} from "chai";
|
||||
import "reflect-metadata";
|
||||
import {Connection} from "../../../../src";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Connection} from "../../../../src/connection/Connection";
|
||||
import {Post} from "./entity/Post";
|
||||
|
||||
describe("columns > readonly functionality", () => {
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
import "reflect-metadata";
|
||||
import {expect} from "chai";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Connection} from "../../../../../src";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
|
||||
describe("database schema > column length > sap", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => {
|
||||
connections = await createTestingConnections({
|
||||
entities: [Post],
|
||||
enabledDrivers: ["sap"],
|
||||
});
|
||||
});
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("all types should create with correct size", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const queryRunner = connection.createQueryRunner();
|
||||
const table = await queryRunner.getTable("post");
|
||||
await queryRunner.release();
|
||||
|
||||
expect(table!.findColumnByName("varchar")!.length).to.be.equal("50");
|
||||
expect(table!.findColumnByName("nvarchar")!.length).to.be.equal("50");
|
||||
expect(table!.findColumnByName("alphanum")!.length).to.be.equal("50");
|
||||
expect(table!.findColumnByName("shorttext")!.length).to.be.equal("50");
|
||||
expect(table!.findColumnByName("varbinary")!.length).to.be.equal("50");
|
||||
|
||||
})));
|
||||
|
||||
it("all types should update their size", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
let metadata = connection.getMetadata(Post);
|
||||
metadata.findColumnWithPropertyName("varchar")!.length = "100";
|
||||
metadata.findColumnWithPropertyName("nvarchar")!.length = "100";
|
||||
metadata.findColumnWithPropertyName("alphanum")!.length = "100";
|
||||
metadata.findColumnWithPropertyName("shorttext")!.length = "100";
|
||||
metadata.findColumnWithPropertyName("varbinary")!.length = "100";
|
||||
|
||||
await connection.synchronize();
|
||||
|
||||
const queryRunner = connection.createQueryRunner();
|
||||
const table = await queryRunner.getTable("post");
|
||||
await queryRunner.release();
|
||||
|
||||
expect(table!.findColumnByName("varchar")!.length).to.be.equal("100");
|
||||
expect(table!.findColumnByName("nvarchar")!.length).to.be.equal("100");
|
||||
expect(table!.findColumnByName("alphanum")!.length).to.be.equal("100");
|
||||
expect(table!.findColumnByName("shorttext")!.length).to.be.equal("100");
|
||||
expect(table!.findColumnByName("varbinary")!.length).to.be.equal("100");
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
@ -0,0 +1,36 @@
|
||||
import {Entity} from "../../../../../../src";
|
||||
import {PrimaryColumn} from "../../../../../../src";
|
||||
import {Column} from "../../../../../../src";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@Column("varchar", {
|
||||
length: 50
|
||||
})
|
||||
varchar: string;
|
||||
|
||||
@Column("nvarchar", {
|
||||
length: 50
|
||||
})
|
||||
nvarchar: string;
|
||||
|
||||
@Column("alphanum", {
|
||||
length: 50
|
||||
})
|
||||
alphanum: string;
|
||||
|
||||
@Column("shorttext", {
|
||||
length: 50
|
||||
})
|
||||
shorttext: string;
|
||||
|
||||
@Column("varbinary", {
|
||||
length: 50
|
||||
})
|
||||
varbinary: Buffer;
|
||||
|
||||
}
|
||||
@ -0,0 +1,209 @@
|
||||
import "reflect-metadata";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Connection} from "../../../../../src";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {PostWithOptions} from "./entity/PostWithOptions";
|
||||
import {PostWithoutTypes} from "./entity/PostWithoutTypes";
|
||||
import {DateUtils} from "../../../../../src/util/DateUtils";
|
||||
|
||||
describe("database schema > column types > sap", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => {
|
||||
connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
enabledDrivers: ["sap"],
|
||||
});
|
||||
});
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("all types should work correctly - persist and hydrate", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const postRepository = connection.getRepository(Post);
|
||||
const queryRunner = connection.createQueryRunner();
|
||||
const table = await queryRunner.getTable("post");
|
||||
await queryRunner.release();
|
||||
|
||||
const post = new Post();
|
||||
post.id = 1;
|
||||
post.name = "Post";
|
||||
post.int = 2147483647;
|
||||
post.integer = 2147483647;
|
||||
post.tinyint = 250;
|
||||
post.smallint = 32767;
|
||||
post.bigint = "8223372036854775807";
|
||||
post.decimal = "8223372036854775807";
|
||||
post.dec = "8223372036854775807";
|
||||
post.smalldecimal = "8223372036854775";
|
||||
post.real = 10.5;
|
||||
post.double = 10.53;
|
||||
post.float = 10.53;
|
||||
post.char = "A";
|
||||
post.nchar = "A";
|
||||
post.varchar = "This is varchar";
|
||||
post.nvarchar = "This is nvarchar";
|
||||
post.alphanum = "This is alphanum";
|
||||
post.text = "This is text";
|
||||
post.shorttext = "This is shorttext";
|
||||
post.dateObj = new Date();
|
||||
post.date = "2017-06-21";
|
||||
post.timeObj = new Date();
|
||||
post.time = "13:27:05";
|
||||
post.timestamp = new Date();
|
||||
post.timestamp.setMilliseconds(0);
|
||||
post.seconddate = new Date();
|
||||
post.seconddate.setMilliseconds(0);
|
||||
post.blob = new Buffer("This is blob");
|
||||
post.clob = "This is clob";
|
||||
post.nclob = "This is nclob";
|
||||
post.boolean = true;
|
||||
// post.array = ["A", "B", "C"]; // TODO
|
||||
post.varbinary = new Buffer("This is varbinary");
|
||||
post.simpleArray = ["A", "B", "C"];
|
||||
await postRepository.save(post);
|
||||
|
||||
const loadedPost = (await postRepository.findOne(1))!;
|
||||
loadedPost.id.should.be.equal(post.id);
|
||||
loadedPost.name.should.be.equal(post.name);
|
||||
loadedPost.int.should.be.equal(post.int);
|
||||
loadedPost.integer.should.be.equal(post.integer);
|
||||
loadedPost.tinyint.should.be.equal(post.tinyint);
|
||||
loadedPost.smallint.should.be.equal(post.smallint);
|
||||
loadedPost.bigint.should.be.equal(post.bigint);
|
||||
loadedPost.decimal.should.be.equal(post.decimal);
|
||||
loadedPost.dec.should.be.equal(post.dec);
|
||||
loadedPost.smalldecimal.should.be.equal(post.smalldecimal);
|
||||
loadedPost.real.should.be.equal(post.real);
|
||||
loadedPost.double.should.be.equal(post.double);
|
||||
loadedPost.float.should.be.equal(post.float);
|
||||
loadedPost.char.should.be.equal(post.char);
|
||||
loadedPost.nchar.should.be.equal(post.nchar);
|
||||
loadedPost.varchar.should.be.equal(post.varchar);
|
||||
loadedPost.nvarchar.should.be.equal(post.nvarchar);
|
||||
loadedPost.alphanum.should.be.equal(post.alphanum);
|
||||
loadedPost.text.should.be.equal(post.text);
|
||||
loadedPost.shorttext.should.be.equal(post.shorttext);
|
||||
loadedPost.dateObj.should.be.equal(DateUtils.mixedDateToDateString(post.dateObj));
|
||||
loadedPost.date.should.be.equal(post.date);
|
||||
loadedPost.timeObj.valueOf().should.be.equal(DateUtils.mixedTimeToString(post.timeObj));
|
||||
loadedPost.time.should.be.equal(post.time);
|
||||
loadedPost.timestamp.valueOf().should.be.equal(post.timestamp.valueOf());
|
||||
loadedPost.seconddate.valueOf().should.be.equal(post.seconddate.valueOf());
|
||||
loadedPost.blob.toString().should.be.equal(post.blob.toString());
|
||||
loadedPost.clob.toString().should.be.equal(post.clob.toString());
|
||||
loadedPost.nclob.toString().should.be.equal(post.nclob.toString());
|
||||
loadedPost.boolean.should.be.equal(post.boolean);
|
||||
loadedPost.varbinary.toString().should.be.equal(post.varbinary.toString());
|
||||
loadedPost.simpleArray[0].should.be.equal(post.simpleArray[0]);
|
||||
loadedPost.simpleArray[1].should.be.equal(post.simpleArray[1]);
|
||||
loadedPost.simpleArray[2].should.be.equal(post.simpleArray[2]);
|
||||
|
||||
table!.findColumnByName("id")!.type.should.be.equal("integer");
|
||||
table!.findColumnByName("name")!.type.should.be.equal("nvarchar");
|
||||
table!.findColumnByName("int")!.type.should.be.equal("integer");
|
||||
table!.findColumnByName("integer")!.type.should.be.equal("integer");
|
||||
table!.findColumnByName("tinyint")!.type.should.be.equal("tinyint");
|
||||
table!.findColumnByName("smallint")!.type.should.be.equal("smallint");
|
||||
table!.findColumnByName("bigint")!.type.should.be.equal("bigint");
|
||||
table!.findColumnByName("decimal")!.type.should.be.equal("decimal");
|
||||
table!.findColumnByName("dec")!.type.should.be.equal("decimal");
|
||||
table!.findColumnByName("real")!.type.should.be.equal("real");
|
||||
table!.findColumnByName("double")!.type.should.be.equal("double");
|
||||
table!.findColumnByName("float")!.type.should.be.equal("double");
|
||||
table!.findColumnByName("char")!.type.should.be.equal("char");
|
||||
table!.findColumnByName("nchar")!.type.should.be.equal("nchar");
|
||||
table!.findColumnByName("varchar")!.type.should.be.equal("varchar");
|
||||
table!.findColumnByName("nvarchar")!.type.should.be.equal("nvarchar");
|
||||
table!.findColumnByName("alphanum")!.type.should.be.equal("alphanum");
|
||||
table!.findColumnByName("text")!.type.should.be.equal("text");
|
||||
table!.findColumnByName("shorttext")!.type.should.be.equal("shorttext");
|
||||
table!.findColumnByName("dateObj")!.type.should.be.equal("date");
|
||||
table!.findColumnByName("date")!.type.should.be.equal("date");
|
||||
table!.findColumnByName("timeObj")!.type.should.be.equal("time");
|
||||
table!.findColumnByName("time")!.type.should.be.equal("time");
|
||||
table!.findColumnByName("timestamp")!.type.should.be.equal("timestamp");
|
||||
table!.findColumnByName("seconddate")!.type.should.be.equal("seconddate");
|
||||
table!.findColumnByName("blob")!.type.should.be.equal("blob");
|
||||
table!.findColumnByName("clob")!.type.should.be.equal("clob");
|
||||
table!.findColumnByName("nclob")!.type.should.be.equal("nclob");
|
||||
table!.findColumnByName("boolean")!.type.should.be.equal("boolean");
|
||||
table!.findColumnByName("varbinary")!.type.should.be.equal("varbinary");
|
||||
table!.findColumnByName("simpleArray")!.type.should.be.equal("text");
|
||||
})));
|
||||
|
||||
it("all types should work correctly - persist and hydrate when options are specified on columns", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const postRepository = connection.getRepository(PostWithOptions);
|
||||
const queryRunner = connection.createQueryRunner();
|
||||
const table = await queryRunner.getTable("post_with_options");
|
||||
await queryRunner.release();
|
||||
|
||||
const post = new PostWithOptions();
|
||||
post.id = 1;
|
||||
post.dec = "60.00";
|
||||
post.decimal = "70.000";
|
||||
post.varchar = "This is varchar";
|
||||
post.nvarchar = "This is nvarchar";
|
||||
post.alphanum = "This is alphanum";
|
||||
post.shorttext = "This is shorttext";
|
||||
await postRepository.save(post);
|
||||
|
||||
const loadedPost = (await postRepository.findOne(1))!;
|
||||
loadedPost.id.should.be.equal(post.id);
|
||||
loadedPost.dec.should.be.equal(post.dec);
|
||||
loadedPost.decimal.should.be.equal(post.decimal);
|
||||
loadedPost.varchar.should.be.equal(post.varchar);
|
||||
loadedPost.nvarchar.should.be.equal(post.nvarchar);
|
||||
loadedPost.alphanum.should.be.equal(post.alphanum);
|
||||
loadedPost.shorttext.should.be.equal(post.shorttext);
|
||||
|
||||
table!.findColumnByName("id")!.type.should.be.equal("integer");
|
||||
table!.findColumnByName("dec")!.type.should.be.equal("decimal");
|
||||
table!.findColumnByName("dec")!.precision!.should.be.equal(10);
|
||||
table!.findColumnByName("dec")!.scale!.should.be.equal(2);
|
||||
table!.findColumnByName("decimal")!.type.should.be.equal("decimal");
|
||||
table!.findColumnByName("decimal")!.precision!.should.be.equal(10);
|
||||
table!.findColumnByName("decimal")!.scale!.should.be.equal(3);
|
||||
table!.findColumnByName("varchar")!.type.should.be.equal("varchar");
|
||||
table!.findColumnByName("varchar")!.length!.should.be.equal("50");
|
||||
table!.findColumnByName("nvarchar")!.type.should.be.equal("nvarchar");
|
||||
table!.findColumnByName("nvarchar")!.length!.should.be.equal("50");
|
||||
table!.findColumnByName("alphanum")!.type.should.be.equal("alphanum");
|
||||
table!.findColumnByName("alphanum")!.length!.should.be.equal("50");
|
||||
table!.findColumnByName("shorttext")!.type.should.be.equal("shorttext");
|
||||
table!.findColumnByName("shorttext")!.length!.should.be.equal("50");
|
||||
|
||||
})));
|
||||
|
||||
it("all types should work correctly - persist and hydrate when types are not specified on columns", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const postRepository = connection.getRepository(PostWithoutTypes);
|
||||
const queryRunner = connection.createQueryRunner();
|
||||
const table = await queryRunner.getTable("post_without_types");
|
||||
await queryRunner.release();
|
||||
|
||||
const post = new PostWithoutTypes();
|
||||
post.id = 1;
|
||||
post.name = "Post";
|
||||
post.boolean = true;
|
||||
post.blob = new Buffer("This is blob");
|
||||
post.timestamp = new Date();
|
||||
await postRepository.save(post);
|
||||
|
||||
const loadedPost = (await postRepository.findOne(1))!;
|
||||
loadedPost.id.should.be.equal(post.id);
|
||||
loadedPost.name.should.be.equal(post.name);
|
||||
loadedPost.boolean.should.be.equal(post.boolean);
|
||||
loadedPost.blob.toString().should.be.equal(post.blob.toString());
|
||||
loadedPost.timestamp.valueOf().should.be.equal(post.timestamp.valueOf());
|
||||
|
||||
table!.findColumnByName("id")!.type.should.be.equal("integer");
|
||||
table!.findColumnByName("name")!.type.should.be.equal("nvarchar");
|
||||
table!.findColumnByName("boolean")!.type.should.be.equal("boolean");
|
||||
table!.findColumnByName("blob")!.type.should.be.equal("blob");
|
||||
table!.findColumnByName("timestamp")!.type.should.be.equal("timestamp");
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
131
test/functional/database-schema/column-types/sap/entity/Post.ts
Normal file
131
test/functional/database-schema/column-types/sap/entity/Post.ts
Normal file
@ -0,0 +1,131 @@
|
||||
import {Entity} from "../../../../../../src";
|
||||
import {PrimaryColumn} from "../../../../../../src";
|
||||
import {Column} from "../../../../../../src";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Numeric Types
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Column("int")
|
||||
int: number;
|
||||
|
||||
@Column("integer")
|
||||
integer: number;
|
||||
|
||||
@Column("tinyint")
|
||||
tinyint: number;
|
||||
|
||||
@Column("smallint")
|
||||
smallint: number;
|
||||
|
||||
@Column("bigint")
|
||||
bigint: string;
|
||||
|
||||
@Column("decimal")
|
||||
decimal: string;
|
||||
|
||||
@Column("dec")
|
||||
dec: string;
|
||||
|
||||
@Column("smalldecimal")
|
||||
smalldecimal: string;
|
||||
|
||||
@Column("real")
|
||||
real: number;
|
||||
|
||||
@Column("double")
|
||||
double: number;
|
||||
|
||||
@Column("float")
|
||||
float: number;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Character Types
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Column("char")
|
||||
char: string;
|
||||
|
||||
@Column("nchar")
|
||||
nchar: string;
|
||||
|
||||
@Column("varchar")
|
||||
varchar: string;
|
||||
|
||||
@Column("nvarchar")
|
||||
nvarchar: string;
|
||||
|
||||
@Column("alphanum")
|
||||
alphanum: string;
|
||||
|
||||
@Column("text")
|
||||
text: string;
|
||||
|
||||
@Column("shorttext")
|
||||
shorttext: string;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Date Types
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Column("date")
|
||||
dateObj: Date;
|
||||
|
||||
@Column("date")
|
||||
date: string;
|
||||
|
||||
@Column("time")
|
||||
timeObj: Date;
|
||||
|
||||
@Column("time")
|
||||
time: string;
|
||||
|
||||
@Column("timestamp")
|
||||
timestamp: Date;
|
||||
|
||||
@Column("seconddate")
|
||||
seconddate: Date;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// LOB Type
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Column("blob")
|
||||
blob: Buffer;
|
||||
|
||||
@Column("clob")
|
||||
clob: string;
|
||||
|
||||
@Column("nclob")
|
||||
nclob: string;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Other Type
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Column("boolean")
|
||||
boolean: boolean;
|
||||
|
||||
// @Column("varchar", { array: true })
|
||||
// array: string[];
|
||||
|
||||
@Column("varbinary")
|
||||
varbinary: Buffer;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// TypeOrm Specific Type
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Column("simple-array")
|
||||
simpleArray: string[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
import {Entity} from "../../../../../../src";
|
||||
import {PrimaryColumn} from "../../../../../../src";
|
||||
import {Column} from "../../../../../../src";
|
||||
|
||||
@Entity()
|
||||
export class PostWithOptions {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Numeric Types
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Column("dec", { precision: 10, scale: 2 })
|
||||
dec: string;
|
||||
|
||||
@Column("decimal", { precision: 10, scale: 3 })
|
||||
decimal: string;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Character Types
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Column("varchar", { length: 50 })
|
||||
varchar: string;
|
||||
|
||||
@Column("nvarchar", { length: 50 })
|
||||
nvarchar: string;
|
||||
|
||||
@Column("alphanum", { length: 50 })
|
||||
alphanum: string;
|
||||
|
||||
@Column("shorttext", { length: 50 })
|
||||
shorttext: string;
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
import {Entity} from "../../../../../../src";
|
||||
import {PrimaryColumn} from "../../../../../../src";
|
||||
import {Column} from "../../../../../../src";
|
||||
|
||||
@Entity()
|
||||
export class PostWithoutTypes {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
boolean: boolean;
|
||||
|
||||
@Column()
|
||||
blob: Buffer;
|
||||
|
||||
@Column()
|
||||
timestamp: Date;
|
||||
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
import "reflect-metadata";
|
||||
import {expect} from "chai";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Connection} from "../../../../src/connection/Connection";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../src/connection/Connection";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
|
||||
describe("database schema > column width", () => {
|
||||
|
||||
@ -31,7 +31,7 @@ describe("database schema > column width", () => {
|
||||
})));
|
||||
|
||||
it("should update data type display width", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
|
||||
let metadata = connection.getMetadata(Post);
|
||||
metadata.findColumnWithPropertyName("int")!.width = 5;
|
||||
metadata.findColumnWithPropertyName("tinyint")!.width = 3;
|
||||
@ -50,7 +50,7 @@ describe("database schema > column width", () => {
|
||||
expect(table!.findColumnByName("smallint")!.width).to.be.equal(4);
|
||||
expect(table!.findColumnByName("mediumint")!.width).to.be.equal(10);
|
||||
expect(table!.findColumnByName("bigint")!.width).to.be.equal(11);
|
||||
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
@ -1,6 +1,6 @@
|
||||
import {Entity} from "../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Column} from "../../../../../src/decorator/columns/Column";
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
@ -23,4 +23,4 @@ export class Post {
|
||||
@Column("bigint", { width: 10 })
|
||||
bigint: number;
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,9 @@
|
||||
import "reflect-metadata";
|
||||
import {CockroachDriver} from "../../../../src/driver/cockroachdb/CockroachDriver";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Connection} from "../../../../src/connection/Connection";
|
||||
import {expect} from "chai";
|
||||
import {EntityMetadata} from "../../../../src/metadata/EntityMetadata";
|
||||
import "reflect-metadata";
|
||||
import {Connection, EntityMetadata} from "../../../../src";
|
||||
import {CockroachDriver} from "../../../../src/driver/cockroachdb/CockroachDriver";
|
||||
import {IndexMetadata} from "../../../../src/metadata/IndexMetadata";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
|
||||
import {Person} from "./entity/Person";
|
||||
|
||||
@ -59,7 +58,7 @@ describe("database schema > indices > reading index from entity and updating dat
|
||||
|
||||
})));
|
||||
|
||||
it("should update the index swaping the 2 columns", () => Promise.all(connections.map(async connection => {
|
||||
it("should update the index swapping the 2 columns", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const entityMetadata = connection.entityMetadatas.find(x => x.name === "Person");
|
||||
entityMetadata!.indices = [new IndexMetadata({
|
||||
|
||||
@ -7,7 +7,7 @@ import {Post} from "./entity/Post";
|
||||
import {Image} from "./entity/Image";
|
||||
|
||||
describe("query builder > relation-count-decorator-many-to-many > many-to-many", () => {
|
||||
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
|
||||
@ -7,7 +7,7 @@ import {Post} from "./entity/Post";
|
||||
import {Image} from "./entity/Image";
|
||||
|
||||
describe("decorators > relation-count-decorator > one-to-many", () => {
|
||||
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import "reflect-metadata";
|
||||
import {SapDriver} from "../../../../src/driver/sap/SapDriver";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Connection} from "../../../../src/connection/Connection";
|
||||
import {expect} from "chai";
|
||||
@ -21,7 +22,7 @@ describe("entity-schema > uniques", () => {
|
||||
const table = await queryRunner.getTable("person");
|
||||
await queryRunner.release();
|
||||
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
expect(table!.indices.length).to.be.equal(1);
|
||||
expect(table!.indices[0].name).to.be.equal("UNIQUE_TEST");
|
||||
expect(table!.indices[0].isUnique).to.be.true;
|
||||
|
||||
@ -22,6 +22,7 @@ describe("persistence > cascades > example 1", () => {
|
||||
profile.photo = photo;
|
||||
|
||||
const user = new User();
|
||||
user.name = "Umed";
|
||||
user.profile = profile;
|
||||
|
||||
await connection.manager.save(user);
|
||||
@ -35,13 +36,16 @@ describe("persistence > cascades > example 1", () => {
|
||||
|
||||
loadedUser!.should.be.eql({
|
||||
id: 1,
|
||||
name: "Umed",
|
||||
profile: {
|
||||
id: 1,
|
||||
photo: {
|
||||
id: 1
|
||||
id: 1,
|
||||
name: "My photo"
|
||||
},
|
||||
user: {
|
||||
id: 1
|
||||
id: 1,
|
||||
name: "Umed"
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
|
||||
@ -7,4 +8,7 @@ export class Photo {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ default: "My photo" })
|
||||
name: string;
|
||||
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Profile} from "./Profile";
|
||||
@ -9,6 +10,9 @@ export class User {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@OneToOne(type => Profile, profile => profile.user, { cascade: ["insert"] })
|
||||
profile: Profile;
|
||||
|
||||
|
||||
@ -44,26 +44,31 @@ describe("persistence > cascades > example 2", () => {
|
||||
|
||||
loadedQuestion!.should.be.eql({
|
||||
id: 1,
|
||||
name: "My question",
|
||||
answers: [{
|
||||
id: 1,
|
||||
photo: {
|
||||
id: 1
|
||||
id: 1,
|
||||
name: "My photo"
|
||||
},
|
||||
user: {
|
||||
id: 1,
|
||||
question: {
|
||||
id: 1
|
||||
id: 1,
|
||||
name: "My question"
|
||||
}
|
||||
}
|
||||
}, {
|
||||
id: 2,
|
||||
photo: {
|
||||
id: 1
|
||||
id: 1,
|
||||
name: "My photo"
|
||||
},
|
||||
user: {
|
||||
id: 1,
|
||||
question: {
|
||||
id: 1
|
||||
id: 1,
|
||||
name: "My question"
|
||||
}
|
||||
}
|
||||
}]
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import {Column} from "../../../../../../src";
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
|
||||
@ -7,4 +8,8 @@ export class Photo {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ default: "My photo" })
|
||||
name: string;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import {Column} from "../../../../../../src";
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Answer} from "./Answer";
|
||||
@ -9,6 +10,9 @@ export class Question {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ default: "My question" })
|
||||
name: string;
|
||||
|
||||
@OneToMany(type => Answer, answer => answer.question, { cascade: ["insert"] })
|
||||
answers: Answer[];
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ import {Connection} from "../../../../src/connection/Connection";
|
||||
import {User} from "./entity/User";
|
||||
|
||||
describe("query builder > cache", () => {
|
||||
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
|
||||
@ -95,7 +95,7 @@ describe("query builder > delete", () => {
|
||||
it("should return correct delete result", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
// don't run test for sqlite and sqljs as they don't return affected rows
|
||||
if (connection.name === "sqlite" || connection.name === "sqljs")
|
||||
if (connection.name === "sqlite" || connection.name === "sqljs" || connection.name === "sap")
|
||||
return;
|
||||
|
||||
// save some users
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import "reflect-metadata";
|
||||
import {expect} from "chai";
|
||||
import {SapDriver} from "../../../../src/driver/sap/SapDriver";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Connection} from "../../../../src/connection/Connection";
|
||||
import {User} from "./entity/User";
|
||||
@ -9,7 +10,7 @@ import {AbstractSqliteDriver} from "../../../../src/driver/sqlite-abstract/Abstr
|
||||
import {OracleDriver} from "../../../../src/driver/oracle/OracleDriver";
|
||||
|
||||
describe("query builder > insert", () => {
|
||||
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
@ -53,8 +54,8 @@ describe("query builder > insert", () => {
|
||||
})));
|
||||
|
||||
it("should perform bulk insertion correctly", () => Promise.all(connections.map(async connection => {
|
||||
// it is skipped for Oracle because it does not support bulk insertion
|
||||
if (connection.driver instanceof OracleDriver)
|
||||
// it is skipped for Oracle and SAP because it does not support bulk insertion
|
||||
if (connection.driver instanceof OracleDriver || connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
await connection.createQueryBuilder()
|
||||
@ -94,8 +95,8 @@ describe("query builder > insert", () => {
|
||||
|
||||
it("should be able to insert entities with different properties set even inside embeds", () => Promise.all(connections.map(async connection => {
|
||||
// this test is skipped for sqlite based drivers because it does not support DEFAULT values in insertions,
|
||||
// also it is skipped for Oracle because it does not support bulk insertion
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof OracleDriver)
|
||||
// also it is skipped for Oracle and SAP because it does not support bulk insertion
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof OracleDriver || connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
await connection
|
||||
@ -140,4 +141,4 @@ describe("query builder > insert", () => {
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import "reflect-metadata";
|
||||
import {CockroachDriver} from "../../../../src/driver/cockroachdb/CockroachDriver";
|
||||
import {SapDriver} from "../../../../src/driver/sap/SapDriver";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Connection} from "../../../../src/connection/Connection";
|
||||
import {PostWithVersion} from "./entity/PostWithVersion";
|
||||
@ -28,7 +29,7 @@ describe("query builder > locking", () => {
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should not attach pessimistic read lock statement on query if locking is not used", () => Promise.all(connections.map(async connection => {
|
||||
if (connection.driver instanceof AbstractSqliteDriver)
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
const sql = connection.createQueryBuilder(PostWithVersion, "post")
|
||||
@ -41,7 +42,7 @@ describe("query builder > locking", () => {
|
||||
})));
|
||||
|
||||
it("should throw error if pessimistic lock used without transaction", () => Promise.all(connections.map(async connection => {
|
||||
if (connection.driver instanceof AbstractSqliteDriver)
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
return Promise.all([
|
||||
@ -58,7 +59,7 @@ describe("query builder > locking", () => {
|
||||
})));
|
||||
|
||||
it("should not throw error if pessimistic lock used with transaction", () => Promise.all(connections.map(async connection => {
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver)
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver || connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
return connection.manager.transaction(entityManager => {
|
||||
@ -77,7 +78,7 @@ describe("query builder > locking", () => {
|
||||
})));
|
||||
|
||||
it("should attach pessimistic read lock statement on query if locking enabled", () => Promise.all(connections.map(async connection => {
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver)
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver || connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
const sql = connection.createQueryBuilder(PostWithVersion, "post")
|
||||
@ -106,12 +107,12 @@ describe("query builder > locking", () => {
|
||||
.setLock("dirty_read")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.getSql();
|
||||
|
||||
|
||||
expect(sql.indexOf("WITH (NOLOCK)") !== -1).to.be.true;
|
||||
})));
|
||||
|
||||
it("should not attach pessimistic write lock statement on query if locking is not used", () => Promise.all(connections.map(async connection => {
|
||||
if (connection.driver instanceof AbstractSqliteDriver)
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
const sql = connection.createQueryBuilder(PostWithVersion, "post")
|
||||
@ -123,7 +124,7 @@ describe("query builder > locking", () => {
|
||||
})));
|
||||
|
||||
it("should attach pessimistic write lock statement on query if locking enabled", () => Promise.all(connections.map(async connection => {
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver)
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver || connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
const sql = connection.createQueryBuilder(PostWithVersion, "post")
|
||||
@ -272,7 +273,7 @@ describe("query builder > locking", () => {
|
||||
})));
|
||||
|
||||
it("should throw error if pessimistic locking not supported by given driver", () => Promise.all(connections.map(async connection => {
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver)
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver || connection.driver instanceof SapDriver)
|
||||
return connection.manager.transaction(entityManager => {
|
||||
return Promise.all([
|
||||
entityManager.createQueryBuilder(PostWithVersion, "post")
|
||||
|
||||
@ -12,7 +12,7 @@ import {Category} from "./entity/Category";
|
||||
import {Image} from "./entity/Image";
|
||||
|
||||
describe("query builder > relation-id > many-to-many > basic-functionality", () => {
|
||||
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import "reflect-metadata";
|
||||
import {expect} from "chai";
|
||||
import "reflect-metadata";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {CockroachDriver} from "../../../src/driver/cockroachdb/CockroachDriver";
|
||||
import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils";
|
||||
import {TableColumn} from "../../../src/schema-builder/table/TableColumn";
|
||||
import {AbstractSqliteDriver} from "../../../src/driver/sqlite-abstract/AbstractSqliteDriver";
|
||||
import {MysqlDriver} from "../../../src/driver/mysql/MysqlDriver";
|
||||
import {AbstractSqliteDriver} from "../../../src/driver/sqlite-abstract/AbstractSqliteDriver";
|
||||
import {TableColumn} from "../../../src/schema-builder/table/TableColumn";
|
||||
import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils";
|
||||
|
||||
describe("query runner > add column", () => {
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import "reflect-metadata";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {Connection} from "../../../src";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
|
||||
describe("query runner > create and drop schema", () => {
|
||||
@ -8,7 +8,7 @@ describe("query runner > create and drop schema", () => {
|
||||
before(async () => {
|
||||
connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
enabledDrivers: ["mssql", "postgres"],
|
||||
enabledDrivers: ["mssql", "postgres", "sap"],
|
||||
dropSchema: true,
|
||||
});
|
||||
});
|
||||
@ -35,4 +35,4 @@ describe("query runner > create and drop schema", () => {
|
||||
await queryRunner.release();
|
||||
})));
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,6 +2,7 @@ import "reflect-metadata";
|
||||
import {expect} from "chai";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {CockroachDriver} from "../../../src/driver/cockroachdb/CockroachDriver";
|
||||
import {SapDriver} from "../../../src/driver/sap/SapDriver";
|
||||
import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils";
|
||||
import {Table} from "../../../src/schema-builder/table/Table";
|
||||
import {TableOptions} from "../../../src/schema-builder/options/TableOptions";
|
||||
@ -58,7 +59,7 @@ describe("query runner > create table", () => {
|
||||
nameColumn!.should.be.exist;
|
||||
nameColumn!.isUnique.should.be.true;
|
||||
table!.should.exist;
|
||||
if (!(connection.driver instanceof MysqlDriver))
|
||||
if (!(connection.driver instanceof MysqlDriver) && !(connection.driver instanceof SapDriver))
|
||||
table!.uniques.length.should.be.equal(1);
|
||||
|
||||
await queryRunner.executeMemoryDownSql();
|
||||
@ -80,7 +81,7 @@ describe("query runner > create table", () => {
|
||||
const versionColumn = table!.findColumnByName("version");
|
||||
const nameColumn = table!.findColumnByName("name");
|
||||
table!.should.exist;
|
||||
if (!(connection.driver instanceof MysqlDriver)) {
|
||||
if (!(connection.driver instanceof MysqlDriver) && !(connection.driver instanceof SapDriver)) {
|
||||
table!.uniques.length.should.be.equal(2);
|
||||
table!.checks.length.should.be.equal(1);
|
||||
}
|
||||
@ -154,7 +155,7 @@ describe("query runner > create table", () => {
|
||||
]
|
||||
};
|
||||
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
questionTableOptions.indices!.push({ columnNames: ["name", "text"] });
|
||||
} else {
|
||||
questionTableOptions.uniques = [{ columnNames: ["name", "text"] }];
|
||||
@ -199,14 +200,14 @@ describe("query runner > create table", () => {
|
||||
]
|
||||
};
|
||||
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
categoryTableOptions.indices = [{ columnNames: ["name", "alternativeName"]}];
|
||||
} else {
|
||||
categoryTableOptions.uniques = [{ columnNames: ["name", "alternativeName"]}];
|
||||
}
|
||||
|
||||
// When we mark column as unique, MySql create index for that column and we don't need to create index separately.
|
||||
if (!(connection.driver instanceof MysqlDriver) && !(connection.driver instanceof OracleDriver))
|
||||
if (!(connection.driver instanceof MysqlDriver) && !(connection.driver instanceof OracleDriver) && !(connection.driver instanceof SapDriver))
|
||||
categoryTableOptions.indices = [{ columnNames: ["questionId"] }];
|
||||
|
||||
await queryRunner.createTable(new Table(categoryTableOptions), true);
|
||||
@ -225,8 +226,8 @@ describe("query runner > create table", () => {
|
||||
questionIdColumn!.generationStrategy!.should.be.equal("increment");
|
||||
questionTable!.should.exist;
|
||||
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
// MySql driver does not have unique and check constraints.
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
// MySql and SAP HANA does not have unique constraints.
|
||||
// all unique constraints is unique indexes.
|
||||
questionTable!.uniques.length.should.be.equal(0);
|
||||
questionTable!.indices.length.should.be.equal(2);
|
||||
@ -259,8 +260,8 @@ describe("query runner > create table", () => {
|
||||
categoryTable!.should.exist;
|
||||
categoryTable!.foreignKeys.length.should.be.equal(1);
|
||||
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
// MySql driver does not have unique constraints. All unique constraints is unique indexes.
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
// MySql and SAP HANA does not have unique constraints. All unique constraints is unique indexes.
|
||||
categoryTable!.indices.length.should.be.equal(3);
|
||||
|
||||
} else if (connection.driver instanceof OracleDriver) {
|
||||
@ -301,7 +302,7 @@ describe("query runner > create table", () => {
|
||||
nameColumn!.isUnique.should.be.true;
|
||||
descriptionColumn!.isUnique.should.be.true;
|
||||
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
table!.uniques.length.should.be.equal(0);
|
||||
table!.indices.length.should.be.equal(4);
|
||||
tagColumn!.isUnique.should.be.true;
|
||||
@ -341,31 +342,31 @@ describe("query runner > create table", () => {
|
||||
const aBook = new Book();
|
||||
aBook.ean = "asdf";
|
||||
await connection.manager.save(aBook);
|
||||
|
||||
|
||||
const desc = await connection.manager.query("SELECT rowid FROM book WHERE ean = 'asdf'");
|
||||
expect(desc[0].rowid).equals(1);
|
||||
|
||||
await queryRunner.dropTable("book");
|
||||
const bookTableIsGone = await queryRunner.getTable("book");
|
||||
expect(bookTableIsGone).to.be.undefined;
|
||||
|
||||
|
||||
// the table 'book2' must NOT contain a 'rowid' column
|
||||
const metadataBook2 = connection.getMetadata(Book2);
|
||||
const newTableBook2 = Table.create(metadataBook2, connection.driver);
|
||||
await queryRunner.createTable(newTableBook2);
|
||||
|
||||
|
||||
try {
|
||||
await connection.manager.query("SELECT rowid FROM book2");
|
||||
} catch (e) {
|
||||
expect(e.message).equal("SQLITE_ERROR: no such column: rowid");
|
||||
}
|
||||
|
||||
await queryRunner.dropTable("book2");
|
||||
await queryRunner.dropTable("book2");
|
||||
const book2TableIsGone = await queryRunner.getTable("book2");
|
||||
expect(book2TableIsGone).to.be.undefined;
|
||||
expect(book2TableIsGone).to.be.undefined;
|
||||
|
||||
await queryRunner.release();
|
||||
}
|
||||
})));
|
||||
})));
|
||||
|
||||
});
|
||||
|
||||
@ -10,7 +10,7 @@ describe("query runner > create unique constraint", () => {
|
||||
before(async () => {
|
||||
connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
enabledDrivers: ["mssql", "postgres", "sqlite", "oracle", "cockroachdb"], // mysql does not supports unique constraints
|
||||
enabledDrivers: ["mssql", "postgres", "sqlite", "oracle", "cockroachdb"], // mysql and sap does not supports unique constraints
|
||||
schemaCreate: true,
|
||||
dropSchema: true,
|
||||
});
|
||||
|
||||
@ -8,7 +8,7 @@ describe("query runner > drop unique constraint", () => {
|
||||
before(async () => {
|
||||
connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
enabledDrivers: ["mssql", "postgres", "sqlite", "oracle", "cockroachdb"], // mysql does not supports unique constraints
|
||||
enabledDrivers: ["mssql", "postgres", "sqlite", "oracle", "cockroachdb"], // mysql and sap does not supports unique constraints
|
||||
schemaCreate: true,
|
||||
dropSchema: true,
|
||||
});
|
||||
|
||||
@ -2,6 +2,7 @@ import "reflect-metadata";
|
||||
import {expect} from "chai";
|
||||
import {Connection} from "../../../src";
|
||||
import {CockroachDriver} from "../../../src/driver/cockroachdb/CockroachDriver";
|
||||
import {SapDriver} from "../../../src/driver/sap/SapDriver";
|
||||
import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils";
|
||||
import {Table} from "../../../src";
|
||||
import {SqlServerDriver} from "../../../src/driver/sqlserver/SqlServerDriver";
|
||||
@ -76,8 +77,8 @@ describe("query runner > rename column", () => {
|
||||
expect(table!.findColumnByName("id")).to.be.undefined;
|
||||
table!.findColumnByName("id2")!.should.be.exist;
|
||||
|
||||
// MySql does not support unique constraints
|
||||
if (!(connection.driver instanceof MysqlDriver)) {
|
||||
// MySql and SAP does not support unique constraints
|
||||
if (!(connection.driver instanceof MysqlDriver) && !(connection.driver instanceof SapDriver)) {
|
||||
const oldUniqueConstraintName = connection.namingStrategy.uniqueConstraintName(table!, ["text", "tag"]);
|
||||
let tableUnique = table!.uniques.find(unique => {
|
||||
return !!unique.columnNames.find(columnName => columnName === "tag");
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import "reflect-metadata";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {CockroachDriver} from "../../../src/driver/cockroachdb/CockroachDriver";
|
||||
import {SapDriver} from "../../../src/driver/sap/SapDriver";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {SqlServerDriver} from "../../../src/driver/sqlserver/SqlServerDriver";
|
||||
import {Table} from "../../../src/schema-builder/table/Table";
|
||||
@ -65,7 +66,7 @@ describe("query runner > rename table", () => {
|
||||
await queryRunner.dropPrimaryKey(table!);
|
||||
|
||||
// MySql does not support unique constraints
|
||||
if (!(connection.driver instanceof MysqlDriver)) {
|
||||
if (!(connection.driver instanceof MysqlDriver) && !(connection.driver instanceof SapDriver)) {
|
||||
const newUniqueConstraintName = connection.namingStrategy.uniqueConstraintName(table!, ["text", "tag"]);
|
||||
let tableUnique = table!.uniques.find(unique => {
|
||||
return !!unique.columnNames.find(columnName => columnName === "tag");
|
||||
@ -104,7 +105,7 @@ describe("query runner > rename table", () => {
|
||||
await queryRunner.createDatabase("testDB", true);
|
||||
await queryRunner.createSchema("testDB.testSchema", true);
|
||||
|
||||
} else if (connection.driver instanceof PostgresDriver) {
|
||||
} else if (connection.driver instanceof PostgresDriver || connection.driver instanceof SapDriver) {
|
||||
questionTableName = "testSchema.question";
|
||||
renamedQuestionTableName = "testSchema.renamedQuestion";
|
||||
categoryTableName = "testSchema.category";
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import "reflect-metadata";
|
||||
import {CockroachDriver} from "../../../../src/driver/cockroachdb/CockroachDriver";
|
||||
import {SapDriver} from "../../../../src/driver/sap/SapDriver";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Connection} from "../../../../src";
|
||||
import {PostWithVersion} from "./entity/PostWithVersion";
|
||||
@ -28,7 +29,7 @@ describe("repository > find options > locking", () => {
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should throw error if pessimistic lock used without transaction", () => Promise.all(connections.map(async connection => {
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver)
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver || connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
return Promise.all([
|
||||
@ -45,7 +46,7 @@ describe("repository > find options > locking", () => {
|
||||
})));
|
||||
|
||||
it("should not throw error if pessimistic lock used with transaction", () => Promise.all(connections.map(async connection => {
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver)
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver || connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
return connection.manager.transaction(entityManager => {
|
||||
@ -64,7 +65,7 @@ describe("repository > find options > locking", () => {
|
||||
})));
|
||||
|
||||
it("should attach pessimistic read lock statement on query if locking enabled", () => Promise.all(connections.map(async connection => {
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver)
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver || connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
const executedSql: string[] = [];
|
||||
@ -97,7 +98,7 @@ describe("repository > find options > locking", () => {
|
||||
})));
|
||||
|
||||
it("should attach pessimistic write lock statement on query if locking enabled", () => Promise.all(connections.map(async connection => {
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver)
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver || connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
const executedSql: string[] = [];
|
||||
@ -249,7 +250,7 @@ describe("repository > find options > locking", () => {
|
||||
})));
|
||||
|
||||
it("should throw error if pessimistic locking not supported by given driver", () => Promise.all(connections.map(async connection => {
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver)
|
||||
if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver || connection.driver instanceof SapDriver)
|
||||
return connection.manager.transaction(entityManager => {
|
||||
return Promise.all([
|
||||
entityManager
|
||||
|
||||
@ -146,7 +146,7 @@ describe("repository > increment method", () => {
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [PostBigInt],
|
||||
enabledDrivers: ["mysql", "mariadb", "postgres"],
|
||||
enabledDrivers: ["mysql", "mariadb", "postgres", "sap"],
|
||||
// logging: true
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import "reflect-metadata";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {Connection} from "../../../src";
|
||||
import {CockroachDriver} from "../../../src/driver/cockroachdb/CockroachDriver";
|
||||
import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils";
|
||||
import {ColumnMetadata} from "../../../src/metadata/ColumnMetadata";
|
||||
import {ColumnMetadataArgs} from "../../../src/metadata-args/ColumnMetadataArgs";
|
||||
import {ColumnMetadata} from "../../../src/metadata/ColumnMetadata";
|
||||
import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils";
|
||||
import {Post} from "./entity/Post";
|
||||
|
||||
describe("schema builder > add column", () => {
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import "reflect-metadata";
|
||||
import {Connection} from "../../../src";
|
||||
import {CockroachDriver} from "../../../src/driver/cockroachdb/CockroachDriver";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {expect} from "chai";
|
||||
import {PromiseUtils} from "../../../src";
|
||||
import {AbstractSqliteDriver} from "../../../src/driver/sqlite-abstract/AbstractSqliteDriver";
|
||||
import {PostgresDriver} from "../../../src/driver/postgres/PostgresDriver";
|
||||
import {SqlServerDriver} from "../../../src/driver/sqlserver/SqlServerDriver";
|
||||
import {Post} from "./entity/Post";
|
||||
import {PostVersion} from "./entity/PostVersion";
|
||||
import "reflect-metadata";
|
||||
import {Connection, PromiseUtils} from "../../../src";
|
||||
import {AuroraDataApiDriver} from "../../../src/driver/aurora-data-api/AuroraDataApiDriver";
|
||||
import {CockroachDriver} from "../../../src/driver/cockroachdb/CockroachDriver";
|
||||
import {MysqlDriver} from "../../../src/driver/mysql/MysqlDriver";
|
||||
import {OracleDriver} from "../../../src/driver/oracle/OracleDriver";
|
||||
import {AuroraDataApiDriver} from "../../../src/driver/aurora-data-api/AuroraDataApiDriver";
|
||||
import {PostgresDriver} from "../../../src/driver/postgres/PostgresDriver";
|
||||
import {SapDriver} from "../../../src/driver/sap/SapDriver";
|
||||
import {AbstractSqliteDriver} from "../../../src/driver/sqlite-abstract/AbstractSqliteDriver";
|
||||
import {SqlServerDriver} from "../../../src/driver/sqlserver/SqlServerDriver";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {Post} from "./entity/Post";
|
||||
import {PostVersion} from "./entity/PostVersion";
|
||||
|
||||
describe("schema builder > change column", () => {
|
||||
|
||||
@ -62,7 +62,7 @@ describe("schema builder > change column", () => {
|
||||
postTable!.findColumnByName("name")!.length.should.be.equal("500");
|
||||
postTable!.findColumnByName("text")!.length.should.be.equal("300");
|
||||
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof AuroraDataApiDriver) {
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof AuroraDataApiDriver || connection.driver instanceof SapDriver) {
|
||||
postTable!.indices.length.should.be.equal(2);
|
||||
} else {
|
||||
postTable!.uniques.length.should.be.equal(2);
|
||||
|
||||
@ -5,7 +5,6 @@ import {PromiseUtils} from "../../../src";
|
||||
import {Teacher} from "./entity/Teacher";
|
||||
import {Post} from "./entity/Post";
|
||||
import {ExclusionMetadata} from "../../../src/metadata/ExclusionMetadata";
|
||||
import {PostgresDriver} from "../../../src/driver/postgres/PostgresDriver";
|
||||
|
||||
describe("schema builder > change exclusion constraint", () => {
|
||||
|
||||
@ -13,6 +12,7 @@ describe("schema builder > change exclusion constraint", () => {
|
||||
before(async () => {
|
||||
connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
enabledDrivers: ["postgres"], // Only PostgreSQL supports exclusion constraints.
|
||||
schemaCreate: true,
|
||||
dropSchema: true,
|
||||
});
|
||||
@ -21,9 +21,6 @@ describe("schema builder > change exclusion constraint", () => {
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should correctly add new exclusion constraint", () => PromiseUtils.runInSequence(connections, async connection => {
|
||||
// Only PostgreSQL supports exclusion constraints.
|
||||
if (!(connection.driver instanceof PostgresDriver))
|
||||
return;
|
||||
|
||||
const teacherMetadata = connection.getMetadata(Teacher);
|
||||
const exclusionMetadata = new ExclusionMetadata({
|
||||
@ -46,9 +43,6 @@ describe("schema builder > change exclusion constraint", () => {
|
||||
}));
|
||||
|
||||
it("should correctly change exclusion", () => PromiseUtils.runInSequence(connections, async connection => {
|
||||
// Only PostgreSQL supports exclusion constraints.
|
||||
if (!(connection.driver instanceof PostgresDriver))
|
||||
return;
|
||||
|
||||
const postMetadata = connection.getMetadata(Post);
|
||||
postMetadata.exclusions[0].expression = `USING gist ("tag" WITH =)`;
|
||||
@ -64,9 +58,6 @@ describe("schema builder > change exclusion constraint", () => {
|
||||
}));
|
||||
|
||||
it("should correctly drop removed exclusion", () => PromiseUtils.runInSequence(connections, async connection => {
|
||||
// Only PostgreSQL supports exclusion constraints.
|
||||
if (!(connection.driver instanceof PostgresDriver))
|
||||
return;
|
||||
|
||||
const postMetadata = connection.getMetadata(Post);
|
||||
postMetadata.exclusions = [];
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import "reflect-metadata";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {PromiseUtils} from "../../../src";
|
||||
import {Teacher} from "./entity/Teacher";
|
||||
import {UniqueMetadata} from "../../../src/metadata/UniqueMetadata";
|
||||
import {Connection} from "../../../src";
|
||||
import {MysqlDriver} from "../../../src/driver/mysql/MysqlDriver";
|
||||
import {Post} from "./entity/Post";
|
||||
import {SapDriver} from "../../../src/driver/sap/SapDriver";
|
||||
import {AbstractSqliteDriver} from "../../../src/driver/sqlite-abstract/AbstractSqliteDriver";
|
||||
import {IndexMetadata} from "../../../src/metadata/IndexMetadata";
|
||||
import {UniqueMetadata} from "../../../src/metadata/UniqueMetadata";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Teacher} from "./entity/Teacher";
|
||||
|
||||
describe("schema builder > change unique constraint", () => {
|
||||
|
||||
@ -28,8 +29,8 @@ describe("schema builder > change unique constraint", () => {
|
||||
let uniqueIndexMetadata: IndexMetadata|undefined = undefined;
|
||||
let uniqueMetadata: UniqueMetadata|undefined = undefined;
|
||||
|
||||
// Mysql stores unique constraints as unique indices.
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
// Mysql and SAP stores unique constraints as unique indices.
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
uniqueIndexMetadata = new IndexMetadata({
|
||||
entityMetadata: teacherMetadata,
|
||||
columns: [nameColumn],
|
||||
@ -60,7 +61,7 @@ describe("schema builder > change unique constraint", () => {
|
||||
const table = await queryRunner.getTable("teacher");
|
||||
await queryRunner.release();
|
||||
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
table!.indices.length.should.be.equal(1);
|
||||
table!.indices[0].isUnique!.should.be.true;
|
||||
|
||||
@ -82,8 +83,8 @@ describe("schema builder > change unique constraint", () => {
|
||||
|
||||
const postMetadata = connection.getMetadata(Post);
|
||||
|
||||
// Mysql stores unique constraints as unique indices.
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
// Mysql and SAP stores unique constraints as unique indices.
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
const uniqueIndexMetadata = postMetadata.indices.find(i => i.columns.length === 2 && i.isUnique === true);
|
||||
uniqueIndexMetadata!.name = "changed_unique";
|
||||
|
||||
@ -98,7 +99,7 @@ describe("schema builder > change unique constraint", () => {
|
||||
const table = await queryRunner.getTable("post");
|
||||
await queryRunner.release();
|
||||
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
const tableIndex = table!.indices.find(index => index.columnNames.length === 2 && index.isUnique === true);
|
||||
tableIndex!.name!.should.be.equal("changed_unique");
|
||||
|
||||
@ -120,8 +121,8 @@ describe("schema builder > change unique constraint", () => {
|
||||
it("should correctly drop removed unique constraint", () => PromiseUtils.runInSequence(connections, async connection => {
|
||||
const postMetadata = connection.getMetadata(Post);
|
||||
|
||||
// Mysql stores unique constraints as unique indices.
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
// Mysql and SAP stores unique constraints as unique indices.
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
const index = postMetadata!.indices.find(i => i.columns.length === 2 && i.isUnique === true);
|
||||
postMetadata!.indices.splice(postMetadata!.indices.indexOf(index!), 1);
|
||||
|
||||
@ -136,7 +137,7 @@ describe("schema builder > change unique constraint", () => {
|
||||
const table = await queryRunner.getTable("post");
|
||||
await queryRunner.release();
|
||||
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
table!.indices.length.should.be.equal(1);
|
||||
|
||||
} else {
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import "reflect-metadata";
|
||||
import {expect} from "chai";
|
||||
import "reflect-metadata";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {CockroachDriver} from "../../../src/driver/cockroachdb/CockroachDriver";
|
||||
import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils";
|
||||
import {MysqlDriver} from "../../../src/driver/mysql/MysqlDriver";
|
||||
import {SapDriver} from "../../../src/driver/sap/SapDriver";
|
||||
import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils";
|
||||
|
||||
describe("schema builder > create table", () => {
|
||||
|
||||
@ -36,7 +37,7 @@ describe("schema builder > create table", () => {
|
||||
const nameColumn = postTable!.findColumnByName("name");
|
||||
postTable!.should.exist;
|
||||
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
postTable!.indices.length.should.be.equal(2);
|
||||
} else {
|
||||
postTable!.uniques.length.should.be.equal(2);
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import "reflect-metadata";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {PostgresDriver} from "../../../src/driver/postgres/PostgresDriver";
|
||||
import {SqlServerDriver} from "../../../src/driver/sqlserver/SqlServerDriver";
|
||||
import {Connection} from "../../../src";
|
||||
import {MysqlDriver} from "../../../src/driver/mysql/MysqlDriver";
|
||||
import {PostgresDriver} from "../../../src/driver/postgres/PostgresDriver";
|
||||
import {SapDriver} from "../../../src/driver/sap/SapDriver";
|
||||
import {SqlServerDriver} from "../../../src/driver/sqlserver/SqlServerDriver";
|
||||
import {ForeignKeyMetadata} from "../../../src/metadata/ForeignKeyMetadata";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
|
||||
describe("schema builder > custom-db-and-schema-sync", () => {
|
||||
|
||||
@ -12,7 +13,7 @@ describe("schema builder > custom-db-and-schema-sync", () => {
|
||||
before(async () => {
|
||||
connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
enabledDrivers: ["mysql", "mssql", "postgres"],
|
||||
enabledDrivers: ["mysql", "mssql", "postgres", "sap"],
|
||||
dropSchema: true,
|
||||
});
|
||||
});
|
||||
@ -43,7 +44,7 @@ describe("schema builder > custom-db-and-schema-sync", () => {
|
||||
await queryRunner.createSchema(photoMetadata.schemaPath, true);
|
||||
await queryRunner.createSchema(albumMetadata.schemaPath, true);
|
||||
|
||||
} else if (connection.driver instanceof PostgresDriver) {
|
||||
} else if (connection.driver instanceof PostgresDriver || connection.driver instanceof SapDriver) {
|
||||
photoMetadata.schema = "photo-schema";
|
||||
photoMetadata.tablePath = "photo-schema.photo";
|
||||
photoMetadata.schemaPath = "photo-schema";
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import "reflect-metadata";
|
||||
import {SapDriver} from "../../../../src/driver/sap/SapDriver";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Connection} from "../../../../src/connection/Connection";
|
||||
import {Post} from "./entity/Post";
|
||||
@ -10,12 +11,15 @@ describe("transaction > transaction with full isolation support", () => {
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
enabledDrivers: ["mysql", "mssql", "postgres"] // todo: for some reasons mariadb tests are not passing here
|
||||
enabledDrivers: ["mysql", "mssql", "postgres", "sap"] // todo: for some reasons mariadb tests are not passing here
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should execute all operations in a single transaction with READ UNCOMMITTED isolation level", () => Promise.all(connections.map(async connection => {
|
||||
// SAP does not support READ UNCOMMITTED isolation level
|
||||
if (connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
let postId: number|undefined = undefined, categoryId: number|undefined = undefined;
|
||||
|
||||
|
||||
16
test/functional/uuid/sap/entity/Post.ts
Normal file
16
test/functional/uuid/sap/entity/Post.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import {PrimaryGeneratedColumn} from "../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Entity} from "../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../src/decorator/columns/Column";
|
||||
import {Generated} from "../../../../../src/decorator/Generated";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
@Generated("uuid")
|
||||
uuid: string;
|
||||
|
||||
}
|
||||
26
test/functional/uuid/sap/entity/Question.ts
Normal file
26
test/functional/uuid/sap/entity/Question.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import {Entity} from "../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../src/decorator/columns/Column";
|
||||
import {Generated} from "../../../../../src/decorator/Generated";
|
||||
|
||||
@Entity()
|
||||
export class Question {
|
||||
|
||||
@PrimaryGeneratedColumn("uuid")
|
||||
id: string;
|
||||
|
||||
@Column()
|
||||
@Generated("uuid")
|
||||
uuid: string;
|
||||
|
||||
@Column()
|
||||
uuid2: string;
|
||||
|
||||
@Column("nvarchar", { nullable: true })
|
||||
uuid3: string|null;
|
||||
|
||||
@Column("nvarchar", { nullable: true })
|
||||
@Generated("uuid")
|
||||
uuid4: string|null;
|
||||
|
||||
}
|
||||
79
test/functional/uuid/sap/uuid-sap.ts
Normal file
79
test/functional/uuid/sap/uuid-sap.ts
Normal file
@ -0,0 +1,79 @@
|
||||
import {expect} from "chai";
|
||||
import "reflect-metadata";
|
||||
import {Connection} from "../../../../src";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Question} from "./entity/Question";
|
||||
|
||||
describe("uuid-mysql", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => {
|
||||
connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
enabledDrivers: ["sap"],
|
||||
});
|
||||
});
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should persist uuid correctly when it is generated non primary column", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const postRepository = connection.getRepository(Post);
|
||||
const questionRepository = connection.getRepository(Question);
|
||||
const queryRunner = connection.createQueryRunner();
|
||||
const postTable = await queryRunner.getTable("post");
|
||||
const questionTable = await queryRunner.getTable("question");
|
||||
await queryRunner.release();
|
||||
|
||||
const post = new Post();
|
||||
await postRepository.save(post);
|
||||
const loadedPost = await postRepository.findOne(1);
|
||||
expect(loadedPost!.uuid).to.be.exist;
|
||||
postTable!.findColumnByName("uuid")!.type.should.be.equal("nvarchar");
|
||||
|
||||
const post2 = new Post();
|
||||
post2.uuid = "fd357b8f-8838-42f6-b7a2-ae027444e895";
|
||||
await postRepository.save(post2);
|
||||
const loadedPost2 = await postRepository.findOne(2);
|
||||
expect(loadedPost2!.uuid).to.equal("fd357b8f-8838-42f6-b7a2-ae027444e895");
|
||||
|
||||
const question = new Question();
|
||||
question.uuid2 = "fd357b8f-8838-42f6-b7a2-ae027444e895";
|
||||
const savedQuestion = await questionRepository.save(question);
|
||||
const loadedQuestion = await questionRepository.findOne(savedQuestion.id);
|
||||
expect(loadedQuestion!.id).to.be.exist;
|
||||
expect(loadedQuestion!.uuid).to.be.exist;
|
||||
expect(loadedQuestion!.uuid2).to.equal("fd357b8f-8838-42f6-b7a2-ae027444e895");
|
||||
expect(loadedQuestion!.uuid3).to.be.null;
|
||||
expect(loadedQuestion!.uuid4).to.be.exist;
|
||||
questionTable!.findColumnByName("id")!.type.should.be.equal("nvarchar");
|
||||
questionTable!.findColumnByName("uuid")!.type.should.be.equal("nvarchar");
|
||||
questionTable!.findColumnByName("uuid2")!.type.should.be.equal("nvarchar");
|
||||
questionTable!.findColumnByName("uuid3")!.type.should.be.equal("nvarchar");
|
||||
|
||||
const question2 = new Question();
|
||||
question2.id = "1ecad7f6-23ee-453e-bb44-16eca26d5189";
|
||||
question2.uuid = "35b44650-b2cd-44ec-aa54-137fbdf1c373";
|
||||
question2.uuid2 = "fd357b8f-8838-42f6-b7a2-ae027444e895";
|
||||
question2.uuid3 = null;
|
||||
question2.uuid4 = null;
|
||||
await questionRepository.save(question2);
|
||||
const loadedQuestion2 = await questionRepository.findOne("1ecad7f6-23ee-453e-bb44-16eca26d5189");
|
||||
expect(loadedQuestion2!.id).to.equal("1ecad7f6-23ee-453e-bb44-16eca26d5189");
|
||||
expect(loadedQuestion2!.uuid).to.equal("35b44650-b2cd-44ec-aa54-137fbdf1c373");
|
||||
expect(loadedQuestion2!.uuid2).to.equal("fd357b8f-8838-42f6-b7a2-ae027444e895");
|
||||
expect(loadedQuestion2!.uuid3).to.be.null;
|
||||
expect(loadedQuestion2!.uuid4).to.be.null;
|
||||
})));
|
||||
|
||||
it("should set generated uuid in the model after save", () => Promise.all(connections.map(async connection => {
|
||||
const question = new Question();
|
||||
question.uuid2 = "fd357b8f-8838-42f6-b7a2-ae027444e895";
|
||||
await connection.manager.save(question);
|
||||
expect(question!.id).to.exist;
|
||||
expect(question!.uuid).to.exist;
|
||||
expect(question!.uuid2).to.exist;
|
||||
})));
|
||||
|
||||
});
|
||||
@ -1,4 +1,6 @@
|
||||
import "reflect-metadata";
|
||||
import {AuroraDataApiDriver} from "../../../src/driver/aurora-data-api/AuroraDataApiDriver";
|
||||
import {SapDriver} from "../../../src/driver/sap/SapDriver";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {Animal} from "./entity/Animal";
|
||||
@ -26,7 +28,7 @@ describe("github issues > #1099 BUG - QueryBuilder MySQL skip sql is wrong", ()
|
||||
.orderBy("a.id")
|
||||
.skip(1);
|
||||
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof AuroraDataApiDriver || connection.driver instanceof SapDriver ) {
|
||||
await qb.getManyAndCount().should.be.rejectedWith(OffsetWithoutLimitNotSupportedError);
|
||||
} else {
|
||||
await qb.getManyAndCount().should.eventually.be.eql([[{ id: 2, name: "dog", categories: [] }, { id: 3, name: "bear", categories: [] }, { id: 4, name: "snake", categories: [] }, ], 4]);
|
||||
|
||||
@ -31,7 +31,7 @@ describe("github issues > #2103 query builder regression", () => {
|
||||
|
||||
const entities = await repository.createQueryBuilder("s")
|
||||
.whereInIds(ids)
|
||||
.andWhere("x = 1")
|
||||
.andWhere("s.x = 1")
|
||||
.getMany();
|
||||
|
||||
entities.map(entity => entity.id).should.be.eql(
|
||||
@ -60,7 +60,7 @@ describe("github issues > #2103 query builder regression", () => {
|
||||
.whereInIds(ids.map(id => {
|
||||
return { id, code: 1 };
|
||||
}))
|
||||
.andWhere("x = 1")
|
||||
.andWhere("s.x = 1")
|
||||
.getMany();
|
||||
|
||||
entities.map(entity => entity.id).should.be.eql(
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { OneToMany, PrimaryGeneratedColumn } from "../../../../src";
|
||||
import {Column, OneToMany, PrimaryGeneratedColumn} from "../../../../src";
|
||||
import { Entity } from "../../../../src/decorator/entity/Entity";
|
||||
import { Bar } from "./Bar";
|
||||
|
||||
@ -6,6 +6,8 @@ import { Bar } from "./Bar";
|
||||
export class Foo {
|
||||
@PrimaryGeneratedColumn() id: number;
|
||||
|
||||
@Column({ default: "foo description" }) description: string;
|
||||
|
||||
@OneToMany(() => Bar, bar => bar.foo, { cascade: true, eager: true })
|
||||
bars?: Bar[];
|
||||
}
|
||||
|
||||
@ -9,5 +9,8 @@ export class Dummy {
|
||||
primary: true,
|
||||
})
|
||||
id: number;
|
||||
|
||||
@Column({ default: "name" })
|
||||
name: string;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import {Entity} from "../../../../src/decorator/entity/Entity";
|
||||
import { PrimaryColumn } from "../../../../src";
|
||||
import {Column, PrimaryColumn} from "../../../../src";
|
||||
|
||||
@Entity()
|
||||
export class Dummy2 {
|
||||
@ -9,5 +9,8 @@ export class Dummy2 {
|
||||
primary: true,
|
||||
})
|
||||
id: number;
|
||||
|
||||
@Column({ default: "name" })
|
||||
name: string;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {JoinTable, Entity, ManyToMany} from "../../../../src";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {PostWithVeryLongName} from "./PostWithVeryLongName";
|
||||
|
||||
@ -7,6 +8,9 @@ export class CategoryWithVeryLongName {
|
||||
@PrimaryGeneratedColumn()
|
||||
categoryId: number;
|
||||
|
||||
@Column({ default: "dummy name" })
|
||||
name: string;
|
||||
|
||||
@ManyToMany(() => PostWithVeryLongName, post => post.categories)
|
||||
@JoinTable()
|
||||
postsWithVeryLongName: PostWithVeryLongName[];
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {AuthorWithVeryLongName} from "./AuthorWithVeryLongName";
|
||||
import {ManyToMany, Entity, ManyToOne} from "../../../../src";
|
||||
import {ManyToMany, Entity, ManyToOne, Column} from "../../../../src";
|
||||
import {CategoryWithVeryLongName} from "./CategoryWithVeryLongName";
|
||||
|
||||
@Entity()
|
||||
@ -8,6 +8,9 @@ export class PostWithVeryLongName {
|
||||
@PrimaryGeneratedColumn()
|
||||
postId: number;
|
||||
|
||||
@Column({ default: "dummy name" })
|
||||
name: string;
|
||||
|
||||
@ManyToOne(() => AuthorWithVeryLongName, author => author.postsWithVeryLongName)
|
||||
authorWithVeryLongName: AuthorWithVeryLongName;
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import "reflect-metadata";
|
||||
import {SapDriver} from "../../../src/driver/sap/SapDriver";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {Post} from "./entity/Post";
|
||||
@ -16,6 +17,9 @@ describe("github issues > #3363 Isolation Level in transaction() from Connection
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should execute operations in READ UNCOMMITED isolation level", () => Promise.all(connections.map(async function(connection) {
|
||||
// SAP does not support READ UNCOMMITTED isolation level
|
||||
if (connection.driver instanceof SapDriver)
|
||||
return;
|
||||
|
||||
let postId: number|undefined = undefined, categoryId: number|undefined = undefined;
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {MysqlDriver} from "../../../src/driver/mysql/MysqlDriver";
|
||||
import {SapDriver} from "../../../src/driver/sap/SapDriver";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {Connection} from "../../../src";
|
||||
import {EntitySchema} from "../../../src";
|
||||
@ -19,7 +20,7 @@ describe("github issues > #3803 column option unique sqlite error", () => {
|
||||
await queryRunner.release();
|
||||
|
||||
// MySQL stores unique constraints as unique indices
|
||||
if (connection.driver instanceof MysqlDriver) {
|
||||
if (connection.driver instanceof MysqlDriver || connection.driver instanceof SapDriver) {
|
||||
expect(table!.indices.length).to.be.equal(1);
|
||||
expect(table!.indices[0].isUnique).to.be.true;
|
||||
expect(table!.indices[0].columnNames[0]).to.be.equal("name");
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {Entity, PrimaryGeneratedColumn, ManyToMany, JoinTable} from "../../../../src";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
import {Category} from "./Category";
|
||||
|
||||
@Entity()
|
||||
@ -7,8 +8,11 @@ export class Question {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@ManyToMany("Category")
|
||||
@JoinTable()
|
||||
categories: Category[];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ describe("github issues > #4190 Relation decorators: allow to pass string instea
|
||||
profile.gender = "male";
|
||||
profile.photo = "me.jpg";
|
||||
await connection.manager.save(profile);
|
||||
|
||||
|
||||
const user = new User();
|
||||
user.name = "Joe Smith";
|
||||
user.profile = profile;
|
||||
@ -44,17 +44,17 @@ describe("github issues > #4190 Relation decorators: allow to pass string instea
|
||||
}]);
|
||||
|
||||
})));
|
||||
|
||||
|
||||
it("should work with many-to-one/one-to-many relations", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const photo1 = new Photo();
|
||||
photo1.url = "me.jpg";
|
||||
await connection.manager.save(photo1);
|
||||
|
||||
|
||||
const photo2 = new Photo();
|
||||
photo2.url = "me-and-bears.jpg";
|
||||
await connection.manager.save(photo2);
|
||||
|
||||
|
||||
const user = new User();
|
||||
user.name = "John";
|
||||
user.photos = [photo1, photo2];
|
||||
@ -102,12 +102,13 @@ describe("github issues > #4190 Relation decorators: allow to pass string instea
|
||||
const category1 = new Category();
|
||||
category1.name = "animals";
|
||||
await connection.manager.save(category1);
|
||||
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "zoo";
|
||||
await connection.manager.save(category2);
|
||||
|
||||
|
||||
const question = new Question();
|
||||
question.name = "About animals";
|
||||
question.categories = [category1, category2];
|
||||
await connection.manager.save(question);
|
||||
|
||||
@ -126,4 +127,4 @@ describe("github issues > #4190 Relation decorators: allow to pass string instea
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import {Generated} from "../../../../src";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
import {PrimaryColumn} from "../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Entity} from "../../../../src/decorator/entity/Entity";
|
||||
import {OneToOne} from "../../../../src/decorator/relations/OneToOne";
|
||||
import {User} from "./User";
|
||||
import {Generated} from "../../../../src/decorator/Generated";
|
||||
|
||||
@Entity()
|
||||
export class AccessToken {
|
||||
@ -11,9 +12,12 @@ export class AccessToken {
|
||||
@Generated()
|
||||
primaryKey: number;
|
||||
|
||||
@Column()
|
||||
expireTime: number;
|
||||
|
||||
@OneToOne(type => User, user => user.access_token, {
|
||||
cascade: true
|
||||
})
|
||||
user: User;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,4 +20,4 @@ export class User {
|
||||
@JoinColumn()
|
||||
access_token: AccessToken;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ describe("github issues > #57 cascade insert not working with OneToOne relations
|
||||
|
||||
// create
|
||||
const token = new AccessToken();
|
||||
token.expireTime = 60000;
|
||||
const user = new User();
|
||||
user.email = "mwelnick@test.com";
|
||||
user.access_token = token; // this is not necessary at all
|
||||
@ -37,6 +38,7 @@ describe("github issues > #57 cascade insert not working with OneToOne relations
|
||||
expect(tokens).not.to.be.undefined;
|
||||
tokens.should.be.eql([{
|
||||
primaryKey: 1,
|
||||
expireTime: 60000,
|
||||
user: {
|
||||
primaryKey: 1,
|
||||
email: "mwelnick@test.com",
|
||||
@ -54,7 +56,8 @@ describe("github issues > #57 cascade insert not working with OneToOne relations
|
||||
primaryKey: 1,
|
||||
email: "mwelnick@test.com",
|
||||
access_token: {
|
||||
primaryKey: 1
|
||||
primaryKey: 1,
|
||||
expireTime: 60000,
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user