From 946bbd6568ae8dee9ba71a78950cdd38cbf90d77 Mon Sep 17 00:00:00 2001 From: Hasan Jamil <78340806+hjamil-24@users.noreply.github.com> Date: Mon, 24 Jun 2024 14:24:19 +0530 Subject: [PATCH 1/2] feat(oracle): Oracle V7 support * feat(oracle): add support to v7 --------- Co-authored-by: Hasan Jamil --- .github/workflows/ci.yml | 4 +- CHANGELOG.md | 12 - dev/oracle/latest/docker-compose.yml | 18 + dev/oracle/latest/reset.sh | 7 + dev/oracle/latest/start.sh | 22 + dev/oracle/latest/stop.sh | 10 + dev/oracle/oldest/docker-compose.yml | 17 + dev/oracle/oldest/reset.sh | 7 + dev/oracle/oldest/start.sh | 22 + dev/oracle/oldest/stop.sh | 10 + dev/oracle/privileges.sql | 6 + dev/oracle/wait-until-healthy.sh | 21 + package.json | 8 +- packages/core/CHANGELOG.md | 11 - packages/core/package.json | 10 +- packages/core/src/abstract-dialect/dialect.ts | 8 + .../query-generator-typescript.ts | 11 +- .../src/abstract-dialect/query-generator.js | 86 +- packages/core/src/model.js | 2 +- packages/core/src/sequelize-typescript.ts | 1 + packages/core/src/sequelize.internals.ts | 5 +- packages/core/src/sequelize.js | 2 +- packages/core/test/config/config.ts | 19 + .../associations/belongs-to-many.test.js | 64 +- .../associations/belongs-to.test.js | 2 +- .../integration/associations/has-many.test.js | 2 +- .../integration/associations/has-one.test.js | 2 +- packages/core/test/integration/cls.test.ts | 6 +- .../test/integration/configuration.test.ts | 9 + .../integration/data-types/data-types.test.ts | 251 ++-- .../integration/data-types/methods.test.ts | 335 ++--- .../oracle/data-types/methods.test.ts | 213 +++ packages/core/test/integration/error.test.ts | 40 +- .../core/test/integration/include.test.js | 14 + .../test/integration/include/findAll.test.js | 8 +- .../test/integration/include/schema.test.js | 10 +- .../test/integration/instance/values.test.js | 4 +- packages/core/test/integration/json.test.ts | 21 +- .../model-repository/bulk-destroy.test.ts | 18 + .../model-repository/destroy.test.ts | 16 + packages/core/test/integration/model.test.js | 49 +- .../model/attributes/field.test.js | 10 + .../model/attributes/types.test.js | 2 + .../integration/model/bulk-create.test.js | 1 + .../core/test/integration/model/count.test.js | 7 +- .../test/integration/model/create.test.js | 6 +- .../test/integration/model/findAll.test.js | 5 +- .../integration/model/findAll/order.test.js | 4 +- .../test/integration/model/paranoid.test.js | 58 +- .../test/integration/model/update.test.ts | 1 + packages/core/test/integration/pool.test.ts | 8 + .../add-show-remove-constraint.test.ts | 82 +- .../query-interface/changeColumn.test.js | 6 +- .../query-interface/describeTable.test.js | 10 + .../query-interface/list-tables.test.ts | 24 +- .../query-interface/remove-column.test.ts | 8 +- .../query-interface/schemas.test.ts | 9 +- .../core/test/integration/sequelize.test.js | 17 +- .../test/integration/sequelize/query.test.js | 144 +- .../integration/sequelize/transaction.test.ts | 9 +- .../core/test/integration/transaction.test.js | 36 +- packages/core/test/integration/utils.test.ts | 4 +- packages/core/test/unit/configuration.test.ts | 2 +- .../test/unit/data-types/binary-types.test.ts | 4 + .../unit/data-types/decimal-numbers.test.ts | 24 +- .../test/unit/data-types/integers.test.ts | 25 +- .../unit/data-types/misc-data-types.test.ts | 4 + .../test/unit/data-types/string-types.test.ts | 12 + .../unit/data-types/temporal-types.test.ts | 6 + .../core/test/unit/data-types/uuid.test.ts | 1 + packages/core/test/unit/pool.test.ts | 9 + .../query-generator/add-column-query.test.ts | 1 + .../add-constraint-query.test.ts | 2 +- .../query-generator/bulk-delete-query.test.ts | 4 + .../query-generator/bulk-insert-query.test.ts | 7 +- .../commit-transaction-query.test.ts | 1 + .../create-schema-query.test.ts | 18 +- .../create-table-query.test.ts | 35 + .../describe-table-query.test.ts | 25 + .../query-generator/drop-schema-query.test.ts | 4 + .../query-generator/drop-table-query.test.ts | 7 + .../get-constraint-snippet.test.ts | 2 +- .../unit/query-generator/insert-query.test.ts | 20 +- .../json-path-extraction-query.test.ts | 4 + .../list-schemas-query.test.ts | 2 + .../query-generator/list-tables-query.test.ts | 3 + .../remove-constraint-query.test.ts | 4 + .../remove-index-query.test.ts | 19 +- .../rename-table-query.test.ts | 6 +- .../rollback-transaction-query.test.ts | 1 + .../unit/query-generator/select-query.test.ts | 88 ++ .../set-isolation-level-query.test.ts | 2 + .../show-constraints-query.test.ts | 9 + .../show-indexes-query.test.ts | 28 + .../start-transaction-query.test.ts | 4 +- .../table-exists-query.test.ts | 6 + .../truncate-table-query.test.ts | 6 + .../unit/query-generator/update-query.test.ts | 13 + .../query-generator/version-query.test.ts | 1 + .../unit/query-interface/bulk-insert.test.ts | 4 + .../unit/query-interface/bulk-update.test.ts | 3 + .../unit/query-interface/create-table.test.ts | 4 + .../unit/query-interface/drop-table.test.ts | 1 + .../test/unit/query-interface/insert.test.ts | 190 +-- .../unit/query-interface/raw-select.test.ts | 1 + .../test/unit/query-interface/select.test.ts | 1 + .../test/unit/query-interface/update.test.ts | 3 + .../test/unit/query-interface/upsert.test.ts | 229 +-- .../core/test/unit/sql/add-column.test.js | 1 + .../core/test/unit/sql/change-column.test.js | 7 + .../core/test/unit/sql/create-table.test.js | 3 + .../core/test/unit/sql/generateJoin.test.js | 19 +- packages/core/test/unit/sql/group.test.js | 2 + packages/core/test/unit/sql/index.test.js | 3 + packages/core/test/unit/sql/insert.test.js | 12 +- packages/core/test/unit/sql/literal.test.ts | 8 + packages/core/test/unit/sql/order.test.js | 2 + packages/core/test/unit/sql/select.test.js | 134 +- packages/core/test/unit/sql/update.test.js | 3 + packages/core/test/unit/sql/where.test.ts | 40 + packages/core/test/unit/transaction.test.ts | 2 + packages/core/test/unit/utils/sql.test.ts | 38 + packages/oracle/.eslintrc.js | 5 + packages/oracle/package.json | 53 + .../src/_internal/data-types-overrides.ts | 427 ++++++ packages/oracle/src/connection-manager.ts | 181 +++ packages/oracle/src/dialect.ts | 192 +++ packages/oracle/src/index.mjs | 7 + packages/oracle/src/index.ts | 7 + .../query-generator-typescript.internal.ts | 336 +++++ packages/oracle/src/query-generator.d.ts | 5 + .../oracle/src/query-generator.internal.ts | 50 + packages/oracle/src/query-generator.js | 1295 +++++++++++++++++ .../query-interface-typescript.internal.ts | 45 + packages/oracle/src/query-interface.d.ts | 8 + packages/oracle/src/query-interface.js | 93 ++ packages/oracle/src/query.d.ts | 5 + packages/oracle/src/query.js | 755 ++++++++++ packages/oracle/tsconfig.json | 8 + packages/oracle/typedoc.json | 5 + packages/snowflake/package.json | 2 +- packages/utils/CHANGELOG.md | 8 - packages/validator-js/CHANGELOG.md | 8 - test/esm-named-exports.test.js | 1 + yarn.lock | 788 +++++----- 145 files changed, 6096 insertions(+), 1141 deletions(-) delete mode 100644 CHANGELOG.md create mode 100644 dev/oracle/latest/docker-compose.yml create mode 100644 dev/oracle/latest/reset.sh create mode 100644 dev/oracle/latest/start.sh create mode 100644 dev/oracle/latest/stop.sh create mode 100644 dev/oracle/oldest/docker-compose.yml create mode 100644 dev/oracle/oldest/reset.sh create mode 100644 dev/oracle/oldest/start.sh create mode 100644 dev/oracle/oldest/stop.sh create mode 100644 dev/oracle/privileges.sql create mode 100755 dev/oracle/wait-until-healthy.sh delete mode 100644 packages/core/CHANGELOG.md create mode 100644 packages/core/test/integration/dialects/oracle/data-types/methods.test.ts create mode 100644 packages/oracle/.eslintrc.js create mode 100644 packages/oracle/package.json create mode 100644 packages/oracle/src/_internal/data-types-overrides.ts create mode 100644 packages/oracle/src/connection-manager.ts create mode 100644 packages/oracle/src/dialect.ts create mode 100644 packages/oracle/src/index.mjs create mode 100644 packages/oracle/src/index.ts create mode 100644 packages/oracle/src/query-generator-typescript.internal.ts create mode 100644 packages/oracle/src/query-generator.d.ts create mode 100644 packages/oracle/src/query-generator.internal.ts create mode 100644 packages/oracle/src/query-generator.js create mode 100644 packages/oracle/src/query-interface-typescript.internal.ts create mode 100644 packages/oracle/src/query-interface.d.ts create mode 100644 packages/oracle/src/query-interface.js create mode 100644 packages/oracle/src/query.d.ts create mode 100644 packages/oracle/src/query.js create mode 100644 packages/oracle/tsconfig.json create mode 100644 packages/oracle/typedoc.json delete mode 100644 packages/utils/CHANGELOG.md delete mode 100644 packages/validator-js/CHANGELOG.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52451795f2e2..06e4925fcf8e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -108,6 +108,8 @@ jobs: run: yarn lerna run test-unit-ibmi --scope=@sequelize/core - name: Unit tests (core - snowflake) run: yarn lerna run test-unit-snowflake --scope=@sequelize/core + - name: Unit tests (core - oracle) + run: yarn lerna run test-unit-oracle --scope=@sequelize/core - name: SQLite SSCCE run: yarn sscce-sqlite3 test-win: @@ -233,7 +235,7 @@ jobs: matrix: node-version: [18, 20] database-version: [oldest, latest] - dialect: [mysql, mariadb, mssql, db2] + dialect: [mysql, mariadb, mssql, db2, oracle] name: ${{ matrix.dialect }} ${{ matrix.database-version }} (Node ${{ matrix.node-version }}) runs-on: ubuntu-latest needs: [unit-test, test-typings] diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 98985ff78922..000000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,12 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# [7.0.0-alpha.41](https://github.com/sequelize/sequelize/compare/v7.0.0-alpha.40...v7.0.0-alpha.41) (2024-05-17) - -### Bug Fixes - -- make `BaseSqlExpression` a unique class ([#17158](https://github.com/sequelize/sequelize/issues/17158)) ([6a5ea6c](https://github.com/sequelize/sequelize/commit/6a5ea6c774b1812a40dd26e873b56291f868bf3f)) -- set sequelize dialect type in query generator and interface ([#17285](https://github.com/sequelize/sequelize/issues/17285)) ([0227288](https://github.com/sequelize/sequelize/commit/0227288d1c6fcbf2d4f09e2efa50e4aeb9d435f2)) -- **snowflake:** add proxy connection options ([#17309](https://github.com/sequelize/sequelize/issues/17309)) ([51b781e](https://github.com/sequelize/sequelize/commit/51b781e4028f4eda5c4221d94cf4c9141055a762)) diff --git a/dev/oracle/latest/docker-compose.yml b/dev/oracle/latest/docker-compose.yml new file mode 100644 index 000000000000..e605de6d215f --- /dev/null +++ b/dev/oracle/latest/docker-compose.yml @@ -0,0 +1,18 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +services: + oraclexedb: + container_name: oraclexedb + image: gvenzl/oracle-free:23.4-slim + environment: + ORACLE_PASSWORD: password + ORACLE_DATABASE: XEPDB1 + ports: + - 1521:1521 + healthcheck: + test: ['CMD-SHELL', 'sqlplus', 'system/password@localhost:1521/XEPDB1'] + retries: 10 + +networks: + default: + name: sequelize-oraclexedb-network diff --git a/dev/oracle/latest/reset.sh b/dev/oracle/latest/reset.sh new file mode 100644 index 000000000000..65e5dd244865 --- /dev/null +++ b/dev/oracle/latest/reset.sh @@ -0,0 +1,7 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +#!/usr/bin/env bash +set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 + +docker compose -p oraclexedb down --remove-orphans --volumes diff --git a/dev/oracle/latest/start.sh b/dev/oracle/latest/start.sh new file mode 100644 index 000000000000..17db4f2ab52b --- /dev/null +++ b/dev/oracle/latest/start.sh @@ -0,0 +1,22 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +#!/usr/bin/env bash +set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 + +# Remove an existing Oracle DB docker image +docker-compose -p oraclexedb down --remove-orphans + +# Bring up new Oracle DB docker image +docker-compose -p oraclexedb up -d + +# Wait until Oracle DB is set up and docker state is healthy +./../wait-until-healthy.sh oraclexedb + +# Moving privileges.sql to docker container +docker cp ../privileges.sql oraclexedb:/opt/oracle/. + +# Granting all the needed privileges to sequelizetest user +docker exec -t oraclexedb sqlplus system/password@localhost:1521/XEPDB1 @privileges.sql + +echo "Local Oracle DB is ready for use!" \ No newline at end of file diff --git a/dev/oracle/latest/stop.sh b/dev/oracle/latest/stop.sh new file mode 100644 index 000000000000..10a1b9f82962 --- /dev/null +++ b/dev/oracle/latest/stop.sh @@ -0,0 +1,10 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +#!/usr/bin/env bash +set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 + + +docker-compose -p oraclexedb down --remove-orphans + +echo "Local Oracle DB instance stopped (if it was running). \ No newline at end of file diff --git a/dev/oracle/oldest/docker-compose.yml b/dev/oracle/oldest/docker-compose.yml new file mode 100644 index 000000000000..a67c6d82ddb8 --- /dev/null +++ b/dev/oracle/oldest/docker-compose.yml @@ -0,0 +1,17 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +services: + oraclexedb: + container_name: oraclexedb + image: gvenzl/oracle-xe:18-slim + environment: + ORACLE_PASSWORD: password + ports: + - 1521:1521 + healthcheck: + test: ['CMD-SHELL', 'sqlplus', 'system/password@XEPDB1'] + retries: 10 + +networks: + default: + name: sequelize-oraclexedb-network diff --git a/dev/oracle/oldest/reset.sh b/dev/oracle/oldest/reset.sh new file mode 100644 index 000000000000..65e5dd244865 --- /dev/null +++ b/dev/oracle/oldest/reset.sh @@ -0,0 +1,7 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +#!/usr/bin/env bash +set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 + +docker compose -p oraclexedb down --remove-orphans --volumes diff --git a/dev/oracle/oldest/start.sh b/dev/oracle/oldest/start.sh new file mode 100644 index 000000000000..7e65c69a0660 --- /dev/null +++ b/dev/oracle/oldest/start.sh @@ -0,0 +1,22 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +#!/usr/bin/env bash +set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 + +# Remove an existing Oracle DB docker image +docker-compose -p oraclexedb down --remove-orphans + +# Bring up new Oracle DB docker image +docker-compose -p oraclexedb up -d + +# Wait until Oracle DB is set up and docker state is healthy +./../wait-until-healthy.sh oraclexedb + +# Moving privileges.sql to docker container +docker cp ../privileges.sql oraclexedb:/opt/oracle/. + +# Granting all the needed privileges to sequelizetest user +docker exec -t oraclexedb sqlplus system/password@XEPDB1 @privileges.sql + +echo "Local Oracle DB is ready for use!" \ No newline at end of file diff --git a/dev/oracle/oldest/stop.sh b/dev/oracle/oldest/stop.sh new file mode 100644 index 000000000000..9a2cd75af41d --- /dev/null +++ b/dev/oracle/oldest/stop.sh @@ -0,0 +1,10 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +#!/usr/bin/env bash +set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 + + +docker-compose -p oraclexedb down --remove-orphans + +echo "Local Oracle DB instance stopped (if it was running)." \ No newline at end of file diff --git a/dev/oracle/privileges.sql b/dev/oracle/privileges.sql new file mode 100644 index 000000000000..2f58584b9064 --- /dev/null +++ b/dev/oracle/privileges.sql @@ -0,0 +1,6 @@ +-- Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +create user sequelizetest identified by sequelizepassword; +grant all privileges to sequelizetest; +alter user sequelizetest quota unlimited on users; +exit; \ No newline at end of file diff --git a/dev/oracle/wait-until-healthy.sh b/dev/oracle/wait-until-healthy.sh new file mode 100755 index 000000000000..096242f82a05 --- /dev/null +++ b/dev/oracle/wait-until-healthy.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +if [ "$#" -ne 1 ]; then + >&2 echo "Please provide the container name or hash" + exit 1 +fi + +for _ in {1..50} +do + state=$(docker inspect -f '{{ .State.Health.Status }}' $1 2>&1) + return_code=$? + if [ ${return_code} -eq 0 ] && [ "$state" == "healthy" ]; then + echo "$1 is healthy!" + sleep 60 + exit 0 + fi + sleep 6 +done + +>&2 echo "Timeout of 5m exceeded when waiting for container to be healthy: $1" +exit 1 diff --git a/package.json b/package.json index dba122361310..8abe7f810484 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "test-integration-db2": "yarn lerna run test-integration-db2", "test-integration-ibmi": "yarn lerna run test-integration-ibmi", "test-integration-snowflake": "yarn lerna run test-integration-snowflake", + "test-integration-oracle": "yarn lerna run test-integration-oracle", "sync-exports": "lerna run sync-exports", "build": "lerna run build", "docs": "typedoc", @@ -34,6 +35,7 @@ "reset-postgres": "bash dev/postgres/oldest/reset.sh; bash dev/postgres/latest/reset.sh", "reset-mssql": "bash dev/mssql/oldest/reset.sh; bash dev/mssql/latest/reset.sh", "reset-db2": "bash dev/db2/oldest/reset.sh; bash dev/db2/latest/reset.sh", + "reset-oracle": "bash dev/oracle/oldest/reset.sh; bash dev/oracle/latest/reset.sh", "reset-all": "concurrently \"npm:reset-*(!all)\"", "start-mariadb-oldest": "bash dev/mariadb/oldest/start.sh", "start-mariadb-latest": "bash dev/mariadb/latest/start.sh", @@ -45,6 +47,8 @@ "start-mssql-latest": "bash dev/mssql/latest/start.sh", "start-db2-oldest": "bash dev/db2/oldest/start.sh", "start-db2-latest": "bash dev/db2/latest/start.sh", + "start-oracle-oldest": "bash dev/oracle/oldest/start.sh", + "start-oracle-latest": "bash dev/oracle/latest/start.sh", "start-oldest": "concurrently \"npm:start-*-oldest\"", "start-latest": "concurrently \"npm:start-*-latest\"", "stop-mariadb": "bash dev/mariadb/oldest/stop.sh; bash dev/mariadb/latest/stop.sh", @@ -52,6 +56,7 @@ "stop-postgres": "bash dev/postgres/oldest/stop.sh; bash dev/postgres/latest/stop.sh", "stop-mssql": "bash dev/mssql/oldest/stop.sh; bash dev/mssql/latest/stop.sh", "stop-db2": "bash dev/db2/oldest/stop.sh; bash dev/db2/latest/stop.sh", + "stop-oracle": "bash dev/oracle/oldest/stop.sh; bash dev/oracle/latest/stop.sh", "stop-all": "concurrently \"npm:stop-*(!all)\"", "----------------------------------------- SSCCEs ------------------------------------------": "", "sscce": "ts-node sscce.ts", @@ -61,7 +66,8 @@ "sscce-postgres-native": "cross-env DIALECT=postgres-native yarn sscce", "sscce-sqlite3": "cross-env DIALECT=sqlite3 yarn sscce", "sscce-mssql": "cross-env DIALECT=mssql yarn sscce", - "sscce-db2": "cross-env DIALECT=db2 yarn sscce" + "sscce-db2": "cross-env DIALECT=db2 yarn sscce", + "sscce-oracle": "cross-env DIALECT=oracle yarn sscce" }, "workspaces": [ "packages/*" diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md deleted file mode 100644 index d0aacc643d2e..000000000000 --- a/packages/core/CHANGELOG.md +++ /dev/null @@ -1,11 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# [7.0.0-alpha.41](https://github.com/sequelize/sequelize/compare/v7.0.0-alpha.40...v7.0.0-alpha.41) (2024-05-17) - -### Bug Fixes - -- make `BaseSqlExpression` a unique class ([#17158](https://github.com/sequelize/sequelize/issues/17158)) ([6a5ea6c](https://github.com/sequelize/sequelize/commit/6a5ea6c774b1812a40dd26e873b56291f868bf3f)) -- set sequelize dialect type in query generator and interface ([#17285](https://github.com/sequelize/sequelize/issues/17285)) ([0227288](https://github.com/sequelize/sequelize/commit/0227288d1c6fcbf2d4f09e2efa50e4aeb9d435f2)) diff --git a/packages/core/package.json b/packages/core/package.json index dfe8768e3f31..00df9db06ee5 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@sequelize/core", - "description": "Sequelize is a promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Amazon Redshift, Snowflake’s Data Cloud, Db2, and IBM i. It features solid transaction support, relations, eager and lazy loading, read replication and more.", + "description": "Sequelize is a promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Amazon Redshift, Snowflake’s Data Cloud, Db2, Oracle and IBM i. It features solid transaction support, relations, eager and lazy loading, read replication and more.", "version": "7.0.0-alpha.41", "funding": [ { @@ -109,6 +109,7 @@ "sql", "sqlserver", "snowflake", + "oracledb", "orm", "nodejs", "object relational mapper", @@ -143,7 +144,8 @@ "test-unit-db2": "cross-env DIALECT=db2 yarn _test-unit", "test-unit-ibmi": "cross-env DIALECT=ibmi yarn _test-unit", "test-unit-snowflake": "cross-env DIALECT=snowflake yarn _test-unit", - "test-unit-all": "yarn test-unit-mariadb && yarn test-unit-mysql && yarn test-unit-postgres && yarn test-unit-mssql && yarn test-unit-sqlite3 && yarn test-unit-snowflake && yarn test-unit-db2 && yarn test-unit-ibmi", + "test-unit-oracle": "cross-env DIALECT=oracle yarn _test-unit", + "test-unit-all": "yarn test-unit-mariadb && yarn test-unit-mysql && yarn test-unit-postgres && yarn test-unit-mssql && yarn test-unit-sqlite && yarn test-unit-snowflake && yarn test-unit-db2 && yarn test-unit-oracle && yarn test-unit-ibmi", "test-unit": "yarn test-unit-all", "----------------------------------------- integration tests ---------------------------------------------": "", "test-integration-mariadb": "cross-env DIALECT=mariadb yarn test-integration", @@ -155,7 +157,8 @@ "test-integration-db2": "cross-env DIALECT=db2 yarn test-integration", "test-integration-ibmi": "cross-env DIALECT=ibmi yarn test-integration", "test-integration-snowflake": "cross-env DIALECT=snowflake yarn test-integration", - "test-integration-all": "yarn test-integration-mariadb && yarn test-integration-mysql && yarn test-integration-postgres && yarn test-integration-postgres-native && yarn test-integration-sqlite3 && yarn test-integration-mssql && yarn test-integration-db2 && yarn test-integration-ibmi && yarn test-integration-snowflake", + "test-integration-oracle": "cross-env DIALECT=oracle yarn test-integration", + "test-integration-all": "yarn test-integration-mariadb && yarn test-integration-mysql && yarn test-integration-postgres && yarn test-integration-postgres-native && yarn test-integration-sqlite && yarn test-integration-mssql && yarn test-integration-db2 && yarn test-integration-ibmi && yarn test-integration-snowflake && yarn test-integration-oracle", "----------------------------------------- all tests ---------------------------------------------": "", "test-mariadb": "cross-env DIALECT=mariadb yarn test", "test-mysql": "cross-env DIALECT=mysql yarn test", @@ -165,6 +168,7 @@ "test-mssql": "cross-env DIALECT=mssql yarn test", "test-db2": "cross-env DIALECT=db2 yarn test", "test-ibmi": "cross-env DIALECT=ibmi yarn test", + "test-oracle": "cross-env DIALECT=oracle yarn test", "----------------------------------------- development ---------------------------------------------": "", "build": "node ../../build-packages.mjs core" }, diff --git a/packages/core/src/abstract-dialect/dialect.ts b/packages/core/src/abstract-dialect/dialect.ts index b733b3d3428f..728837ca305a 100644 --- a/packages/core/src/abstract-dialect/dialect.ts +++ b/packages/core/src/abstract-dialect/dialect.ts @@ -68,6 +68,12 @@ export type DialectSupports = { /* does the dialect support returning values for inserted/updated fields */ returnValues: false | 'output' | 'returning'; + /* does the dialect support returning values for inserted/updated fields in outBinds */ + returnIntoValues: boolean; + + /* does the dialect support topLevelOrderBy (ORDER BY clasue) to get desired results */ + topLevelOrderByRequired: boolean; + /* features specific to autoIncrement values */ autoIncrement: { /* does the dialect require modification of insert queries when inserting auto increment fields */ @@ -324,6 +330,8 @@ export abstract class AbstractDialect< skipLocked: false, finalTable: false, returnValues: false, + returnIntoValues: false, + topLevelOrderByRequired: false, autoIncrement: { identityInsert: false, defaultValue: true, diff --git a/packages/core/src/abstract-dialect/query-generator-typescript.ts b/packages/core/src/abstract-dialect/query-generator-typescript.ts index b2312525f3db..87549432f857 100644 --- a/packages/core/src/abstract-dialect/query-generator-typescript.ts +++ b/packages/core/src/abstract-dialect/query-generator-typescript.ts @@ -607,6 +607,15 @@ export class AbstractQueryGeneratorTypeScript 0 ? valueQuery : emptyQuery}`.trim()};`; + if (this.dialect.supports.returnIntoValues && options.returning) { + // Populating the returnAttributes array and performing operations needed for output binds of insertQuery + this.populateInsertQueryReturnIntoBinds( + returningModelAttributes, + returnTypes, + Object.keys(bind).length, + returnAttributes, + options, + ); + } + + query = `${`${replacements.attributes.length > 0 ? valueQuery : emptyQuery}${returnAttributes.join(',')}`.trim()};`; if (this.dialect.supports.finalTable) { query = `SELECT * FROM FINAL TABLE (${replacements.attributes.length > 0 ? valueQuery : emptyQuery});`; } @@ -398,6 +420,17 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { ]); } + /** + * Helper method for populating the returning into bind information + * that is needed by some dialects (currently Oracle) + * This is called when `dialect.supports.returnIntoClause` is `True` + * + * @private + */ + populateInsertQueryReturnIntoBinds() { + // noop by default + } + /** * Returns an update query * @@ -429,14 +462,22 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { const bindParam = options.bindParam === undefined ? this.bindParam(bind) : options.bindParam; - if ( - this.dialect.supports['LIMIT ON UPDATE'] && - options.limit && - this.dialect.name !== 'mssql' && - this.dialect.name !== 'db2' - ) { - // TODO: use bind parameter - suffix = ` LIMIT ${this.escape(options.limit, options)} `; + if (this.dialect.supports['LIMIT ON UPDATE'] && options.limit) { + if (!['mssql', 'db2', 'oracle'].includes(this.dialect.name)) { + // TODO: use bind parameter + suffix = ` LIMIT ${this.escape(options.limit, options)} `; + } else if (this.dialect.name === 'oracle') { + // This cannot be set in where clause because rownum will be quoted + if (where && ((where.length && where.length > 0) || Object.keys(where).length > 0)) { + // If we have a where clause, we add AND + suffix += ' AND '; + } else { + // No where clause, we add where + suffix += ' WHERE '; + } + + suffix += `rownum <= ${this.escape(options.limit)} `; + } } if (this.dialect.supports.returnValues && options.returning) { @@ -1183,7 +1224,13 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { } else { // Ordering is handled by the subqueries, so ordering the UNION'ed result is not needed groupedLimitOrder = options.order; - delete options.order; + // For dialects which don't allow for ordering in the subqueries, the result of a select + // is a set, not a sequence, and so is the result of UNION. + // So the top level ORDER BY is required + if (!this.dialect.supports.topLevelOrderByRequired) { + delete options.order; + } + where = and(new Literal(placeholder), where); } @@ -1204,7 +1251,7 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { model, }, model, - ).replace(/;$/, '')}) AS sub`; // Every derived table must have its own alias + ).replace(/;$/, '')}) ${this.getAliasToken()} sub`; // Every derived table must have its own alias const splicePos = baseQuery.indexOf(placeholder); mainQueryItems.push( @@ -1391,7 +1438,7 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { modelName: model && model.name, as: mainTable.quotedAs, }); - query = `SELECT ${attributes.main.join(', ')} FROM (${subQueryItems.join('')}) AS ${mainTable.quotedAs}${mainJoinQueries.join('')}${mainQueryItems.join('')}`; + query = `SELECT ${attributes.main.join(', ')} FROM (${subQueryItems.join('')}) ${this.getAliasToken()} ${mainTable.quotedAs}${mainJoinQueries.join('')}${mainQueryItems.join('')}`; } else { query = mainQueryItems.join(''); } @@ -1553,6 +1600,11 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { /json_extract\(/i, `json_extract(${this.quoteIdentifier(includeAs.internalAs)}.`, ); + } else if (/json_value\(/.test(attr)) { + prefix = attr.replace( + /json_value\(/i, + `json_value(${this.quoteIdentifier(includeAs.internalAs)}.`, + ); } else { prefix = `${this.quoteIdentifier(includeAs.internalAs)}.${this.quoteIdentifier(attr)}`; } @@ -1885,6 +1937,8 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { if (returnValuesType === 'returning') { returningFragment = ` RETURNING ${returnFields.join(', ')}`; + } else if (this.dialect.supports.returnIntoValues) { + returningFragment = ` RETURNING ${returnFields.join(', ')} INTO `; } else if (returnValuesType === 'output') { outputFragment = ` OUTPUT ${returnFields.map(field => `INSERTED.${field}`).join(', ')}`; @@ -1900,7 +1954,7 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { } } - return { outputFragment, returnFields, returningFragment, tmpTable }; + return { outputFragment, returnFields, returnTypes, returningFragment, tmpTable }; } generateThroughJoin(include, includeAs, parentTableName, topLevelInfo, options) { @@ -2280,7 +2334,7 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { fragment += ` ${attributes.join(', ')} FROM ${tables}`; if (options.groupedLimit) { - fragment += ` AS ${mainTableAs}`; + fragment += ` ${this.getAliasToken()} ${mainTableAs}`; } return fragment; diff --git a/packages/core/src/model.js b/packages/core/src/model.js index d333d20916b5..aa8c05d94842 100644 --- a/packages/core/src/model.js +++ b/packages/core/src/model.js @@ -2328,7 +2328,7 @@ ${associationOwner._getAssociationDebugList()}`); } } - if (options.ignoreDuplicates && ['mssql', 'db2', 'ibmi'].includes(dialect)) { + if (options.ignoreDuplicates && ['mssql', 'db2', 'ibmi', 'oracle'].includes(dialect)) { throw new Error(`${dialect} does not support the ignoreDuplicates option.`); } diff --git a/packages/core/src/sequelize-typescript.ts b/packages/core/src/sequelize-typescript.ts index 2b1d7f9dd67a..79bf9a5e2034 100644 --- a/packages/core/src/sequelize-typescript.ts +++ b/packages/core/src/sequelize-typescript.ts @@ -207,6 +207,7 @@ export const SUPPORTED_DIALECTS = Object.freeze([ 'db2', 'snowflake', 'ibmi', + 'oracle', ] as const); // DO NOT MAKE THIS CLASS PUBLIC! diff --git a/packages/core/src/sequelize.internals.ts b/packages/core/src/sequelize.internals.ts index 4221d2ca9096..0701817d215f 100644 --- a/packages/core/src/sequelize.internals.ts +++ b/packages/core/src/sequelize.internals.ts @@ -44,9 +44,12 @@ export function importDialect(dialect: string): typeof AbstractDialect { case 'snowflake': // eslint-disable-next-line import/no-extraneous-dependencies -- legacy function, will be removed. User needs to install the dependency themselves return require('@sequelize/snowflake').SnowflakeDialect; + case 'oracle': + // eslint-disable-next-line import/no-extraneous-dependencies -- legacy function, will be removed. User needs to install the dependency themselves + return require('@sequelize/oracle').OracleDialect; default: throw new Error( - `The dialect ${dialect} is not natively supported. Native dialects: mariadb, mssql, mysql, postgres, sqlite3, ibmi, db2 and snowflake.`, + `The dialect ${dialect} is not natively supported. Native dialects: mariadb, mssql, mysql, postgres, sqlite3, ibmi, db2, oracle and snowflake.`, ); } } diff --git a/packages/core/src/sequelize.js b/packages/core/src/sequelize.js index ef2ea2756319..95b24d27cea4 100644 --- a/packages/core/src/sequelize.js +++ b/packages/core/src/sequelize.js @@ -594,7 +594,7 @@ Use Sequelize#query if you wish to use replacements.`); }; await this.query( - `SELECT 1+1 AS result${this.dialect.name === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `SELECT 1+1 AS result${this.dialect.name === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : this.dialect.name === 'oracle' ? ' FROM DUAL' : ''}`, options, ); } diff --git a/packages/core/test/config/config.ts b/packages/core/test/config/config.ts index 423c606b576b..56627ba81ead 100644 --- a/packages/core/test/config/config.ts +++ b/packages/core/test/config/config.ts @@ -4,6 +4,7 @@ import { IBMiDialect } from '@sequelize/db2-ibmi'; import { MariaDbDialect } from '@sequelize/mariadb'; import { MsSqlDialect } from '@sequelize/mssql'; import { MySqlDialect } from '@sequelize/mysql'; +import { OracleDialect } from '@sequelize/oracle'; import { PostgresDialect } from '@sequelize/postgres'; import { SnowflakeDialect } from '@sequelize/snowflake'; import { SqliteDialect } from '@sequelize/sqlite3'; @@ -27,6 +28,7 @@ export interface DialectConfigs { postgres: Options; db2: Options; ibmi: Options; + oracle: Options; } export interface DialectConnectionConfigs { @@ -38,6 +40,7 @@ export interface DialectConnectionConfigs { postgres: ConnectionOptions; db2: ConnectionOptions; ibmi: ConnectionOptions; + oracle: ConnectionOptions; } const seqPort = env.SEQ_PORT ? parseSafeInteger.orThrow(env.SEQ_PORT) : undefined; @@ -143,6 +146,22 @@ export const CONFIG: DialectConfigs = { }, }, + oracle: { + dialect: OracleDialect, + database: env.SEQ_ORACLE_DB || env.SEQ_DB || 'XEPDB1', + username: env.SEQ_ORACLE_USER || env.SEQ_USER || 'sequelizetest', + password: env.SEQ_ORACLE_PW || env.SEQ_PW || 'sequelizepassword', + host: env.SEQ_ORACLE_HOST || env.SEQ_HOST || '127.0.0.1', + port: env.SEQ_ORACLE_PORT || env.SEQ_PORT || 1521, + pool: { + max: Number(env.SEQ_ORACLE_POOL_MAX || env.SEQ_POOL_MAX || 5), + idle: Number(env.SEQ_ORACLE_POOL_IDLE || env.SEQ_POOL_IDLE || 3000), + }, + oracleOptions: { + stmtCacheSize: Number(env.SEQ_ORACLE_STMT_CACHE || 0), + }, + }, + ibmi: { dialect: IBMiDialect, dataSourceName: env.SEQ_IBMI_DB || env.SEQ_DB, diff --git a/packages/core/test/integration/associations/belongs-to-many.test.js b/packages/core/test/integration/associations/belongs-to-many.test.js index 3485630f72f1..982010719227 100644 --- a/packages/core/test/integration/associations/belongs-to-many.test.js +++ b/packages/core/test/integration/associations/belongs-to-many.test.js @@ -1797,7 +1797,9 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), () => { beforeEach(function () { const keyDataType = ['mysql', 'mariadb', 'db2', 'ibmi'].includes(dialect) ? 'BINARY(255)' - : DataTypes.BLOB('tiny'); + : dialect === 'oracle' + ? DataTypes.STRING(255, true) + : DataTypes.BLOB('tiny'); this.Article = this.sequelize.define('Article', { id: { type: keyDataType, @@ -2321,42 +2323,44 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), () => { await t.rollback(); }); - it('supports transactions when updating a through model', async function () { - const sequelize = await Support.createSingleTransactionalTestSequelizeInstance( - this.sequelize, - ); - const User = sequelize.define('User', { username: DataTypes.STRING }); - const Task = sequelize.define('Task', { title: DataTypes.STRING }); + if (!['oracle'].includes(dialect)) { + it('supports transactions when updating a through model', async function () { + const sequelize = await Support.createSingleTransactionalTestSequelizeInstance( + this.sequelize, + ); + const User = sequelize.define('User', { username: DataTypes.STRING }); + const Task = sequelize.define('Task', { title: DataTypes.STRING }); - const UserTask = sequelize.define('UserTask', { - status: DataTypes.STRING, - }); + const UserTask = sequelize.define('UserTask', { + status: DataTypes.STRING, + }); - User.belongsToMany(Task, { through: UserTask, as: 'Tasks', inverse: 'Users' }); - await sequelize.sync({ force: true }); + User.belongsToMany(Task, { through: UserTask, as: 'Tasks', inverse: 'Users' }); + await sequelize.sync({ force: true }); - const [user, task, t] = await Promise.all([ - User.create({ username: 'foo' }), - Task.create({ title: 'task' }), - sequelize.startUnmanagedTransaction({ isolationLevel: IsolationLevel.SERIALIZABLE }), - ]); + const [user, task, t] = await Promise.all([ + User.create({ username: 'foo' }), + Task.create({ title: 'task' }), + sequelize.startUnmanagedTransaction({ isolationLevel: IsolationLevel.SERIALIZABLE }), + ]); - await task.addUser(user, { through: { status: 'pending' } }); // Create without transaction, so the old value is - // accesible from outside the transaction - await task.addUser(user, { transaction: t, through: { status: 'completed' } }); // Add an already exisiting user in - // a transaction, updating a value - // in the join table + await task.addUser(user, { through: { status: 'pending' } }); // Create without transaction, so the old value is + // accesible from outside the transaction + await task.addUser(user, { transaction: t, through: { status: 'completed' } }); // Add an already exisiting user in + // a transaction, updating a value + // in the join table - const [tasks, transactionTasks] = await Promise.all([ - user.getTasks(), - user.getTasks({ transaction: t }), - ]); + const [tasks, transactionTasks] = await Promise.all([ + user.getTasks(), + user.getTasks({ transaction: t }), + ]); - expect(tasks[0].UserTask.status).to.equal('pending'); - expect(transactionTasks[0].UserTask.status).to.equal('completed'); + expect(tasks[0].UserTask.status).to.equal('pending'); + expect(transactionTasks[0].UserTask.status).to.equal('completed'); - await t.rollback(); - }); + await t.rollback(); + }); + } } it('supports passing the primary key instead of an object', async function () { diff --git a/packages/core/test/integration/associations/belongs-to.test.js b/packages/core/test/integration/associations/belongs-to.test.js index 7bd735627724..716600a89eb9 100644 --- a/packages/core/test/integration/associations/belongs-to.test.js +++ b/packages/core/test/integration/associations/belongs-to.test.js @@ -675,7 +675,7 @@ describe(Support.getTestDialectTeaser('BelongsTo'), () => { } // NOTE: mssql does not support changing an autoincrement primary key - if (!['mssql', 'db2', 'ibmi'].includes(dialect)) { + if (!['mssql', 'db2', 'ibmi', 'oracle'].includes(dialect)) { it('can cascade updates', async function () { const Task = this.sequelize.define('Task', { title: DataTypes.STRING }); const User = this.sequelize.define('User', { username: DataTypes.STRING }); diff --git a/packages/core/test/integration/associations/has-many.test.js b/packages/core/test/integration/associations/has-many.test.js index 3f99d23826d1..04851a609c6e 100644 --- a/packages/core/test/integration/associations/has-many.test.js +++ b/packages/core/test/integration/associations/has-many.test.js @@ -1114,7 +1114,7 @@ describe('HasMany', () => { }); // NOTE: mssql does not support changing an autoincrement primary key - if (!['mssql', 'db2', 'ibmi'].includes(dialectName)) { + if (!['mssql', 'db2', 'ibmi', 'oracle'].includes(dialectName)) { it('can cascade updates', async function () { const Task = this.sequelize.define('Task', { title: DataTypes.STRING }); const User = this.sequelize.define('User', { username: DataTypes.STRING }); diff --git a/packages/core/test/integration/associations/has-one.test.js b/packages/core/test/integration/associations/has-one.test.js index 58ebaf66da21..46d28f206a30 100644 --- a/packages/core/test/integration/associations/has-one.test.js +++ b/packages/core/test/integration/associations/has-one.test.js @@ -362,7 +362,7 @@ describe(Support.getTestDialectTeaser('HasOne'), () => { }); // NOTE: mssql does not support changing an autoincrement primary key - if (!['mssql', 'db2', 'ibmi'].includes(dialect)) { + if (!['mssql', 'db2', 'ibmi', 'oracle'].includes(dialect)) { it('can cascade updates', async function () { const Task = this.sequelize.define('Task', { title: DataTypes.STRING }); const User = this.sequelize.define('User', { username: DataTypes.STRING }); diff --git a/packages/core/test/integration/cls.test.ts b/packages/core/test/integration/cls.test.ts index 7b06946f3974..48f35f39c7e4 100644 --- a/packages/core/test/integration/cls.test.ts +++ b/packages/core/test/integration/cls.test.ts @@ -7,6 +7,7 @@ import sinon from 'sinon'; import { beforeAll2, createMultiTransactionalTestSequelizeInstance, + getTestDialect, sequelize, setResetMode, } from './support'; @@ -173,7 +174,10 @@ describe('AsyncLocalStorage (ContinuationLocalStorage) Transactions (CLS)', () = it('promises returned by sequelize.query are correctly patched', async () => { await vars.clsSequelize.transaction(async t => { - await vars.clsSequelize.query('select 1', { type: QueryTypes.SELECT }); + await vars.clsSequelize.query( + `select 1 ${getTestDialect() === 'oracle' ? 'FROM DUAL' : ''}`, + { type: QueryTypes.SELECT }, + ); return expect(vars.clsSequelize.getCurrentClsTransaction()).to.equal(t); }); diff --git a/packages/core/test/integration/configuration.test.ts b/packages/core/test/integration/configuration.test.ts index e1bfcf075381..76c5f1f385fc 100644 --- a/packages/core/test/integration/configuration.test.ts +++ b/packages/core/test/integration/configuration.test.ts @@ -62,6 +62,10 @@ describe('Configuration', () => { storage: '/path/to/no/where/land', mode: OPEN_READONLY, }, + oracle: { + ...CONFIG.oracle, + port: 19_999, + }, }; const errorByDialect: Record> = { @@ -73,6 +77,7 @@ describe('Configuration', () => { snowflake: HostNotReachableError, db2: ConnectionRefusedError, sqlite3: InvalidConnectionError, + oracle: ConnectionRefusedError, }; const seq = new Sequelize(badHostConfigs[dialectName]); @@ -123,6 +128,10 @@ describe('Configuration', () => { ...CONFIG.ibmi, password: 'wrongpassword', }, + oracle: { + ...CONFIG.oracle, + password: 'wrongpassword', + }, }; const seq = new Sequelize(config[dialectName]); diff --git a/packages/core/test/integration/data-types/data-types.test.ts b/packages/core/test/integration/data-types/data-types.test.ts index 3d29a8c64276..8c949ebb4f40 100644 --- a/packages/core/test/integration/data-types/data-types.test.ts +++ b/packages/core/test/integration/data-types/data-types.test.ts @@ -128,13 +128,16 @@ describe('DataTypes', () => { return { User }; }); - it('accepts strings', async () => { + (dialect.name !== 'oracle' ? it : it.skip)('accepts strings', async () => { await testSimpleInOut(vars.User, 'binaryStringAttr', 'abc', 'abc'); }); - it('is deserialized as a string when DataType is not specified', async () => { - await testSimpleInOutRaw(vars.User, 'binaryStringAttr', 'abc', 'abc'); - }); + (dialect.name !== 'oracle' ? it : it.skip)( + 'is deserialized as a string when DataType is not specified', + async () => { + await testSimpleInOutRaw(vars.User, 'binaryStringAttr', 'abc', 'abc'); + }, + ); }); describe('STRING(100).BINARY', () => { @@ -164,7 +167,7 @@ describe('DataTypes', () => { }); // TODO: add length check constraint in sqlite - if (dialect.name !== 'sqlite3') { + if (dialect.name !== 'sqlite3' && dialect.name !== 'oracle') { it('throws if the string is too long', async () => { await expect( vars.User.create({ @@ -200,9 +203,13 @@ describe('DataTypes', () => { await testSimpleInOut(vars.User, 'textAttr', '123456', '123456'); }); - it('is deserialized as a string when DataType is not specified', async () => { - await testSimpleInOutRaw(vars.User, 'textAttr', 'abc', 'abc'); - }); + // For raw queries, Oracle expects hex string during insertion + (dialect.name === 'oracle' ? it.skip : it)( + 'is deserialized as a string when DataType is not specified', + async () => { + await testSimpleInOutRaw(vars.User, 'textAttr', 'abc', 'abc'); + }, + ); }); describe(`TEXT()`, () => { @@ -310,70 +317,72 @@ describe('DataTypes', () => { }); }); - describe('CHAR().BINARY', () => { - if (!dialect.supports.dataTypes.CHAR) { - it('throws, because this dialect does not support CHAR', async () => { - expect(() => { - sequelize.define('CrashedModel', { - attr: DataTypes.CHAR(5), - }); - }).to.throwWithCause(`${dialect.name} does not support the CHAR data type.`); - }); - - return; - } + if (dialect.name !== 'oracle') { + describe('CHAR().BINARY', () => { + if (!dialect.supports.dataTypes.CHAR) { + it('throws, because this dialect does not support CHAR', async () => { + expect(() => { + sequelize.define('CrashedModel', { + attr: DataTypes.CHAR(5), + }); + }).to.throwWithCause(`${dialect.name} does not support the CHAR data type.`); + }); - if (!dialect.supports.dataTypes.COLLATE_BINARY) { - it('throws if CHAR.BINARY is used', () => { - expect(() => { - sequelize.define('CrashedModel', { - attr: DataTypes.CHAR(5).BINARY, - }); - }).to.throwWithCause(`${dialect.name} does not support the CHAR.BINARY data type.`); - }); + return; + } - return; - } + if (!dialect.supports.dataTypes.COLLATE_BINARY) { + it('throws if CHAR.BINARY is used', () => { + expect(() => { + sequelize.define('CrashedModel', { + attr: DataTypes.CHAR(5).BINARY, + }); + }).to.throwWithCause(`${dialect.name} does not support the CHAR.BINARY data type.`); + }); - const vars = beforeAll2(async () => { - class User extends Model> { - declare binaryCharAttr: string | ArrayBuffer | Uint8Array | Blob; + return; } - User.init( - { - binaryCharAttr: { - type: DataTypes.CHAR(5).BINARY, - allowNull: false, + const vars = beforeAll2(async () => { + class User extends Model> { + declare binaryCharAttr: string | ArrayBuffer | Uint8Array | Blob; + } + + User.init( + { + binaryCharAttr: { + type: DataTypes.CHAR(5).BINARY, + allowNull: false, + }, }, - }, - { sequelize }, - ); + { sequelize }, + ); - await User.sync({ force: true }); + await User.sync({ force: true }); - return { User }; - }); + return { User }; + }); - it('is serialized/deserialized as strings', async () => { - // mysql does not pad columns, unless PAD_CHAR_TO_FULL_LENGTH is true - if (dialect.name === 'db2') { - await testSimpleInOut(vars.User, 'binaryCharAttr', '1234', '1234 '); - } else { - await testSimpleInOut(vars.User, 'binaryCharAttr', '1234', '1234'); - } - }); + it('is serialized/deserialized as strings', async () => { + // mysql does not pad columns, unless PAD_CHAR_TO_FULL_LENGTH is true + if (dialect.name === 'db2') { + await testSimpleInOut(vars.User, 'binaryCharAttr', '1234', '1234 '); + } else { + await testSimpleInOut(vars.User, 'binaryCharAttr', '1234', '1234'); + } + }); - it('is deserialized as a string when DataType is not specified', async () => { - // mysql does not pad columns, unless PAD_CHAR_TO_FULL_LENGTH is true - // https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_pad_char_to_full_length - if (dialect.name === 'db2') { - await testSimpleInOutRaw(vars.User, 'binaryCharAttr', Buffer.from(' 234'), ' 234 '); - } else { - await testSimpleInOutRaw(vars.User, 'binaryCharAttr', Buffer.from(' 234'), ' 234'); - } + it('is deserialized as a string when DataType is not specified', async () => { + // mysql does not pad columns, unless PAD_CHAR_TO_FULL_LENGTH is true + // https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_pad_char_to_full_length + if (dialect.name === 'db2') { + await testSimpleInOutRaw(vars.User, 'binaryCharAttr', Buffer.from(' 234'), ' 234 '); + } else { + await testSimpleInOutRaw(vars.User, 'binaryCharAttr', Buffer.from(' 234'), ' 234'); + } + }); }); - }); + } describe('CITEXT', () => { if (!dialect.supports.dataTypes.CITEXT) { @@ -546,6 +555,12 @@ describe('DataTypes', () => { await testSimpleInOutRaw(vars.User, 'booleanAttr', true, 1); await testSimpleInOutRaw(vars.User, 'booleanAttr', false, 0); }); + } else if (dialect.name === 'oracle') { + // Oracle uses CHAR(1). + it('is deserialized as a char string when DataType is not specified', async () => { + await testSimpleInOutRaw(vars.User, 'booleanAttr', true, '1'); + await testSimpleInOutRaw(vars.User, 'booleanAttr', false, '0'); + }); } else { it('is deserialized as a boolean when DataType is not specified', async () => { await testSimpleInOutRaw(vars.User, 'booleanAttr', true, true); @@ -599,7 +614,10 @@ describe('DataTypes', () => { it('accepts numbers, bigints, strings', async () => { await testSimpleInOut(vars.User, 'intAttr', 123, 123); - await testSimpleInOut(vars.User, 'intAttr', 123n, 123); + if (dialect.name !== 'oracle') { + await testSimpleInOut(vars.User, 'intAttr', 123n, 123); + } + await testSimpleInOut(vars.User, 'intAttr', '123', 123); await testSimpleInOut( @@ -665,7 +683,10 @@ describe('DataTypes', () => { it('accepts numbers, bigints, strings', async () => { await testSimpleInOut(vars.User, 'intAttr', 123, 123); - await testSimpleInOut(vars.User, 'intAttr', 123n, 123); + if (dialect.name !== 'oracle') { + await testSimpleInOut(vars.User, 'intAttr', 123n, 123); + } + await testSimpleInOut(vars.User, 'intAttr', '123', 123); await testSimpleInOut( @@ -729,8 +750,10 @@ describe('DataTypes', () => { }); it('rejects unsafe integers', async () => { - await expect(vars.User.create({ bigintAttr: 9_007_199_254_740_992 })).to.be.rejected; - await expect(vars.User.create({ bigintAttr: -9_007_199_254_740_992 })).to.be.rejected; + if (dialect.name !== 'oracle') { + await expect(vars.User.create({ bigintAttr: 9_007_199_254_740_992 })).to.be.rejected; + await expect(vars.User.create({ bigintAttr: -9_007_199_254_740_992 })).to.be.rejected; + } await expect(vars.User.create({ bigintAttr: 123.4 })).to.be.rejected; await expect(vars.User.create({ bigintAttr: Number.NaN })).to.be.rejected; @@ -745,7 +768,11 @@ describe('DataTypes', () => { }); it('is deserialized as a string when DataType is not specified', async () => { - await testSimpleInOutRaw(vars.User, 'bigintAttr', 123n, '123'); + if (dialect.name !== 'oracle') { + await testSimpleInOutRaw(vars.User, 'bigintAttr', 123n, '123'); + } else { + await testSimpleInOutRaw(vars.User, 'bigintAttr', 123n, 123); + } }); if (dialect.supports.dataTypes.INTS.unsigned) { @@ -806,7 +833,10 @@ describe('DataTypes', () => { it(`accepts numbers, bigints, strings, +-Infinity`, async () => { await testSimpleInOut(vars.User, 'attr', 100.5, 100.5); - await testSimpleInOut(vars.User, 'attr', 123n, 123); + if (dialect.name !== 'oracle') { + await testSimpleInOut(vars.User, 'attr', 123n, 123); + } + await testSimpleInOut(vars.User, 'attr', '100.5', 100.5); }); @@ -855,7 +885,9 @@ describe('DataTypes', () => { it(`is deserialized as a JS number when DataType is not specified`, async () => { await testSimpleInOutRaw(vars.User, 'attr', 100.5, 100.5); - await testSimpleInOutRaw(vars.User, 'attr', 123n, 123); + if (dialect.name !== 'oracle') { + await testSimpleInOutRaw(vars.User, 'attr', 123n, 123); + } if (dialect.supports.dataTypes[attrType].NaN) { await testSimpleInOutRaw(vars.User, 'attr', Number.NaN, Number.NaN); @@ -954,7 +986,10 @@ describe('DataTypes', () => { it('accepts numbers, bigints, strings', async () => { await testSimpleInOut(vars.User, 'decimalAttr', 123.4, '123.4'); - await testSimpleInOut(vars.User, 'decimalAttr', 123n, '123'); + if (dialect.name !== 'oracle') { + await testSimpleInOut(vars.User, 'decimalAttr', 123n, '123'); + } + await testSimpleInOut(vars.User, 'decimalAttr', '123.4', '123.4'); }); @@ -980,7 +1015,7 @@ describe('DataTypes', () => { await expect(vars.User.create({ decimalAttr: 'abc' })).to.be.rejected; }); - if (dialect.name === 'sqlite3') { + if (dialect.name === 'sqlite3' || dialect.name === 'oracle') { // sqlite3 doesn't give us a way to do sql type-based parsing, *and* returns bigints as js numbers. // this behavior is undesired but is still tested against to ensure we update this test when this is finally fixed. it('is deserialized as a number when DataType is not specified (undesired sqlite limitation)', async () => { @@ -1033,6 +1068,7 @@ describe('DataTypes', () => { 123n, dialect.name === 'mssql' ? '123' : '123.00', ); + await testSimpleInOut( vars.User, 'decimalAttr', @@ -1195,7 +1231,9 @@ describe('DataTypes', () => { ? '2022-01-01 00:00:00.000 +00:00' : dialect.name === 'db2' ? '2022-01-01 00:00:00.000000+00' - : '2022-01-01 00:00:00+00', + : dialect.name === 'oracle' + ? new Date('2022-01-01T00:00:00Z') + : '2022-01-01 00:00:00+00', ); }); }); @@ -1233,7 +1271,7 @@ describe('DataTypes', () => { it('clamps to specified precision', async () => { // sqlite does not support restricting the precision - if (dialect.name !== 'sqlite3') { + if (dialect.name !== 'sqlite3' && dialect.name !== 'oracle') { await testSimpleInOut( vars.User, 'dateMinPrecisionAttr', @@ -1333,9 +1371,20 @@ describe('DataTypes', () => { } }); - it(`is deserialized as a string when DataType is not specified`, async () => { - await testSimpleInOutRaw(vars.User, 'dateAttr', '2022-01-01', '2022-01-01'); - }); + if (dialect.name === 'oracle') { + it(`is deserialized as a date when DataType is not specified`, async () => { + await testSimpleInOutRaw( + vars.User, + 'dateAttr', + '2022-01-01', + new Date('2022-01-01T00:00:00.000Z'), + ); + }); + } else { + it(`is deserialized as a string when DataType is not specified`, async () => { + await testSimpleInOutRaw(vars.User, 'dateAttr', '2022-01-01', '2022-01-01'); + }); + } }); describe('TIME(precision)', () => { @@ -1701,40 +1750,48 @@ describe('DataTypes', () => { // TODO: expected for mariadb 10.4 : https://jira.mariadb.org/browse/MDEV-15558 expect(table.jsonStr.type).to.equal('LONGTEXT'); break; + case 'oracle': + expect(table.jsonStr.type).to.equal('BLOB'); + break; default: expect(table.jsonStr.type).to.equal(jsonTypeName); } }); - it('properly serializes default values', async () => { - const createdUser = await vars.User.create(); - await createdUser.reload(); - expect(createdUser.get()).to.deep.eq({ - jsonStr: 'abc', - jsonBoolean: true, - jsonNumber: 1, - jsonNull: null, - jsonArray: ['a', 'b'], - jsonObject: { key: 'abc' }, - id: 1, + // Oracle Database < 21 doesn't consider scalars as JSON column + // thus, fails the CHECK constraint test. + if (dialect.name !== 'oracle') { + it('properly serializes default values', async () => { + const createdUser = await vars.User.create(); + await createdUser.reload(); + expect(createdUser.get()).to.deep.eq({ + jsonStr: 'abc', + jsonBoolean: true, + jsonNumber: 1, + jsonNull: null, + jsonArray: ['a', 'b'], + jsonObject: { key: 'abc' }, + id: 1, + }); }); - }); - it('properly serializes values', async () => { - await testSimpleInOut(vars.User, 'jsonStr', 'abc', 'abc'); - await testSimpleInOut(vars.User, 'jsonBoolean', true, true); - await testSimpleInOut(vars.User, 'jsonBoolean', false, false); - await testSimpleInOut(vars.User, 'jsonNumber', 123.4, 123.4); - await testSimpleInOut(vars.User, 'jsonArray', [1, 2], [1, 2]); - await testSimpleInOut(vars.User, 'jsonObject', { a: 1 }, { a: 1 }); - await testSimpleInOut(vars.User, 'jsonNull', null, null); - }); + it('properly serializes values', async () => { + await testSimpleInOut(vars.User, 'jsonStr', 'abc', 'abc'); + await testSimpleInOut(vars.User, 'jsonBoolean', true, true); + await testSimpleInOut(vars.User, 'jsonBoolean', false, false); + await testSimpleInOut(vars.User, 'jsonNumber', 123.4, 123.4); + await testSimpleInOut(vars.User, 'jsonArray', [1, 2], [1, 2]); + await testSimpleInOut(vars.User, 'jsonObject', { a: 1 }, { a: 1 }); + await testSimpleInOut(vars.User, 'jsonNull', null, null); + }); + } // MariaDB: supports a JSON type, but: // - MariaDB 10.5 says it's a JSON col, on which we enabled automatic JSON parsing. // - MariaDB 10.4 says it's a string, so we can't parse it based on the type. + // Oracle JSON is BLOB column with check `IS JSON`. // TODO [2024-06-18]: Re-enable this test when we drop support for MariaDB < 10.5 - if (dialect.name !== 'mariadb') { + if (dialect.name !== 'mariadb' && dialect.name !== 'oracle') { if (dialect.name === 'mssql' || dialect.name === 'sqlite3') { // MSSQL: does not have a JSON type, so we can't parse it if our DataType is not specified. // SQLite: sqlite3 does not tell us the type of a column, we cannot parse based on it. diff --git a/packages/core/test/integration/data-types/methods.test.ts b/packages/core/test/integration/data-types/methods.test.ts index e0c1683f6c7a..7c645fd98cd5 100644 --- a/packages/core/test/integration/data-types/methods.test.ts +++ b/packages/core/test/integration/data-types/methods.test.ts @@ -15,197 +15,204 @@ import { beforeAll2, beforeEach2, sequelize, setResetMode } from '../support'; const dialect = sequelize.dialect; -describe('DataType Methods', () => { - setResetMode('none'); - - const customValueSymbol = Symbol('dummy'); - - class CustomDataType extends DataTypes.STRING { - parseDatabaseValue(_value: unknown): any { - return customValueSymbol; +// For a custom data-type definition for Oracle, _getBindDef() is required to +// provide information about BINDOUT variables. Similar tests have been added +// in dialects/oracle/data-types/methods.test.ts +if (dialect.name !== 'oracle') { + describe('DataType Methods', () => { + setResetMode('none'); + + const customValueSymbol = Symbol('dummy'); + + class CustomDataType extends DataTypes.STRING { + parseDatabaseValue(_value: unknown): any { + return customValueSymbol; + } } - } - const models = beforeAll2(async () => { - class User extends Model, InferCreationAttributes> { - declare id: CreationOptional; - declare name: string | null; - declare projects?: NonAttribute; - } + const models = beforeAll2(async () => { + class User extends Model, InferCreationAttributes> { + declare id: CreationOptional; + declare name: string | null; + declare projects?: NonAttribute; + } - User.init( - { - id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, - name: { type: CustomDataType, allowNull: true, field: 'first_name' }, - }, - { sequelize }, - ); + User.init( + { + id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, + name: { type: CustomDataType, allowNull: true, field: 'first_name' }, + }, + { sequelize }, + ); - class Project extends Model, InferCreationAttributes> { - declare name: string; - declare userId: ForeignKey; - declare stakeholders?: NonAttribute>; + class Project extends Model, InferCreationAttributes> { + declare name: string; + declare userId: ForeignKey; + declare stakeholders?: NonAttribute< + Array + >; - declare addStakeholder: BelongsToManyAddAssociationMixin; - } + declare addStakeholder: BelongsToManyAddAssociationMixin; + } - Project.init( - { - name: { type: CustomDataType, allowNull: false }, - }, - { sequelize }, - ); - - class ProjectStakeholder extends Model< - InferAttributes, - InferCreationAttributes - > { - declare key: string; - } + Project.init( + { + name: { type: CustomDataType, allowNull: false }, + }, + { sequelize }, + ); - ProjectStakeholder.init( - { - key: { type: CustomDataType, allowNull: false }, - }, - { sequelize, noPrimaryKey: true, timestamps: false }, - ); - - Project.belongsTo(User, { - as: 'user', - inverse: { as: 'projects', type: 'hasMany' }, - foreignKey: 'userId', - }); + class ProjectStakeholder extends Model< + InferAttributes, + InferCreationAttributes + > { + declare key: string; + } - Project.belongsToMany(User, { - as: 'stakeholders', - inverse: 'stakeholdings', - through: ProjectStakeholder, + ProjectStakeholder.init( + { + key: { type: CustomDataType, allowNull: false }, + }, + { sequelize, noPrimaryKey: true, timestamps: false }, + ); + + Project.belongsTo(User, { + as: 'user', + inverse: { as: 'projects', type: 'hasMany' }, + foreignKey: 'userId', + }); + + Project.belongsToMany(User, { + as: 'stakeholders', + inverse: 'stakeholdings', + through: ProjectStakeholder, + }); + + await User.sync({ force: true }); + await Project.sync({ force: true }); + await ProjectStakeholder.sync({ force: true }); + + const user1 = await User.create({ name: 'John' }); + const user2 = await User.create({ name: 'Stakeholder User' }); + const project = await Project.create({ name: 'Project 1', userId: user1.id }); + await project.addStakeholder(user2, { through: { key: 'dummy-value' } }); + + return { User, Project, ProjectStakeholder }; }); - await User.sync({ force: true }); - await Project.sync({ force: true }); - await ProjectStakeholder.sync({ force: true }); - - const user1 = await User.create({ name: 'John' }); - const user2 = await User.create({ name: 'Stakeholder User' }); - const project = await Project.create({ name: 'Project 1', userId: user1.id }); - await project.addStakeholder(user2, { through: { key: 'dummy-value' } }); - - return { User, Project, ProjectStakeholder }; - }); - - const spies = beforeEach2(() => { - // add mocha spy to sanitize - return { - sanitize: sinon.spy(DataTypes.STRING.prototype, 'sanitize'), - validate: sinon.spy(DataTypes.STRING.prototype, 'validate'), - parseDatabaseValue: sinon.spy(CustomDataType.prototype, 'parseDatabaseValue'), - }; - }); - - afterEach(() => { - for (const spy of Object.values(spies)) { - spy.restore(); - } - }); + const spies = beforeEach2(() => { + // add mocha spy to sanitize + return { + sanitize: sinon.spy(DataTypes.STRING.prototype, 'sanitize'), + validate: sinon.spy(DataTypes.STRING.prototype, 'validate'), + parseDatabaseValue: sinon.spy(CustomDataType.prototype, 'parseDatabaseValue'), + }; + }); - it(`setting a value on a model only calls 'sanitize'`, () => { - models.User.build({ name: 'foo' }); + afterEach(() => { + for (const spy of Object.values(spies)) { + spy.restore(); + } + }); - expect(spies.sanitize.calledOnce).to.eq(true, 'sanitized not called exactly once'); - expect(spies.validate.called).to.eq(false, 'validate should not have been called'); - expect(spies.parseDatabaseValue.called).to.eq( - false, - 'parseDatabaseValue should not have been called', - ); - }); + it(`setting a value on a model only calls 'sanitize'`, () => { + models.User.build({ name: 'foo' }); - it(`retrieving a model only calls 'parseDatabaseValue' (no join)`, async () => { - const out = await models.User.findOne({ rejectOnEmpty: true }); + expect(spies.sanitize.calledOnce).to.eq(true, 'sanitized not called exactly once'); + expect(spies.validate.called).to.eq(false, 'validate should not have been called'); + expect(spies.parseDatabaseValue.called).to.eq( + false, + 'parseDatabaseValue should not have been called', + ); + }); - expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue not called on top level model'); + it(`retrieving a model only calls 'parseDatabaseValue' (no join)`, async () => { + const out = await models.User.findOne({ rejectOnEmpty: true }); - expect(spies.sanitize.called).to.eq(false, 'sanitize should not have been called'); - expect(spies.validate.called).to.eq(false, 'validate should not have been called'); - }); + expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue not called on top level model'); - it(`retrieving a model only calls 'parseDatabaseValue' (with join)`, async () => { - // this test is separate from the no-join version because they use different code paths. - // We test both double nested associations & that through tables are handled correctly. - const out = await models.User.findOne({ - include: [ - { - association: 'projects', - include: ['stakeholders'], - }, - ], - rejectOnEmpty: true, + expect(spies.sanitize.called).to.eq(false, 'sanitize should not have been called'); + expect(spies.validate.called).to.eq(false, 'validate should not have been called'); }); - expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue not called on top level model'); - expect(out.projects![0].name).to.eq( - customValueSymbol, - 'parseDatabaseValue not called on first include level', - ); - expect(out.projects![0].stakeholders![0].name).to.eq( - customValueSymbol, - 'parseDatabaseValue not called on second include level', - ); - expect(out.projects![0].stakeholders![0].ProjectStakeholder.key).to.eq( - customValueSymbol, - 'parseDatabaseValue not called on Many-To-Many through table', - ); - - expect(spies.sanitize.called).to.eq(false, 'sanitize should not have been called'); - expect(spies.validate.called).to.eq(false, 'validate should not have been called'); - }); + it(`retrieving a model only calls 'parseDatabaseValue' (with join)`, async () => { + // this test is separate from the no-join version because they use different code paths. + // We test both double nested associations & that through tables are handled correctly. + const out = await models.User.findOne({ + include: [ + { + association: 'projects', + include: ['stakeholders'], + }, + ], + rejectOnEmpty: true, + }); + + expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue not called on top level model'); + expect(out.projects![0].name).to.eq( + customValueSymbol, + 'parseDatabaseValue not called on first include level', + ); + expect(out.projects![0].stakeholders![0].name).to.eq( + customValueSymbol, + 'parseDatabaseValue not called on second include level', + ); + expect(out.projects![0].stakeholders![0].ProjectStakeholder.key).to.eq( + customValueSymbol, + 'parseDatabaseValue not called on Many-To-Many through table', + ); + + expect(spies.sanitize.called).to.eq(false, 'sanitize should not have been called'); + expect(spies.validate.called).to.eq(false, 'validate should not have been called'); + }); - if (dialect.supports.returnValues) { - it(`inserting a model calls 'parseDatabaseValue' on returned values`, async () => { - // 'name' attr has a different name in the database - const out = await models.User.create({ name: 'foo' }, { returning: true }); + if (dialect.supports.returnValues) { + it(`inserting a model calls 'parseDatabaseValue' on returned values`, async () => { + // 'name' attr has a different name in the database + const out = await models.User.create({ name: 'foo' }, { returning: true }); - expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); + expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); - // sanitize is called when the user input is added to the model - expect(spies.sanitize.called).to.eq(true, 'sanitize should have been called'); - // validate is called before persisting the model - expect(spies.validate.called).to.eq(true, 'validate should have been called'); - }); + // sanitize is called when the user input is added to the model + expect(spies.sanitize.called).to.eq(true, 'sanitize should have been called'); + // validate is called before persisting the model + expect(spies.validate.called).to.eq(true, 'validate should have been called'); + }); - it(`upserting a model calls 'parseDatabaseValue' on returned values`, async () => { - // 'name' attr has a different name in the database - const [out] = await models.User.upsert({ name: 'foo', id: 1234 }, { returning: true }); + it(`upserting a model calls 'parseDatabaseValue' on returned values`, async () => { + // 'name' attr has a different name in the database + const [out] = await models.User.upsert({ name: 'foo', id: 1234 }, { returning: true }); - expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); + expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); - // sanitize is called when the user input is added to the model - expect(spies.sanitize.called).to.eq(true, 'sanitize should have been called'); - // validate is called before persisting the model - expect(spies.validate.called).to.eq(true, 'validate should have been called'); - }); - } + // sanitize is called when the user input is added to the model + expect(spies.sanitize.called).to.eq(true, 'sanitize should have been called'); + // validate is called before persisting the model + expect(spies.validate.called).to.eq(true, 'validate should have been called'); + }); + } - if (dialect.supports.returnValues === 'returning') { - it(`updating a model calls 'parseDatabaseValue' on returned values`, async () => { - const user = await models.User.create({ name: 'foo' }); - user.name = 'bob'; - await user.save({ returning: true }); + if (dialect.supports.returnValues === 'returning') { + it(`updating a model calls 'parseDatabaseValue' on returned values`, async () => { + const user = await models.User.create({ name: 'foo' }); + user.name = 'bob'; + await user.save({ returning: true }); - expect(user.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); - }); + expect(user.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); + }); - // TODO: add test for 'returning' on DELETE queries once https://github.com/sequelize/sequelize/pull/14879 has been merged - } + // TODO: add test for 'returning' on DELETE queries once https://github.com/sequelize/sequelize/pull/14879 has been merged + } - it(`does not call 'parseDatabaseValue' on null values`, async () => { - const user = await models.User.create({ name: null }); - await user.reload(); + it(`does not call 'parseDatabaseValue' on null values`, async () => { + const user = await models.User.create({ name: null }); + await user.reload(); - expect(user.name).to.eq(null, 'parseDatabaseValue called on null value'); - expect(spies.parseDatabaseValue.called).to.eq( - false, - 'parseDatabaseValue should not have been called', - ); + expect(user.name).to.eq(null, 'parseDatabaseValue called on null value'); + expect(spies.parseDatabaseValue.called).to.eq( + false, + 'parseDatabaseValue should not have been called', + ); + }); }); -}); +} diff --git a/packages/core/test/integration/dialects/oracle/data-types/methods.test.ts b/packages/core/test/integration/dialects/oracle/data-types/methods.test.ts new file mode 100644 index 000000000000..29409f98fea8 --- /dev/null +++ b/packages/core/test/integration/dialects/oracle/data-types/methods.test.ts @@ -0,0 +1,213 @@ +import type { + BelongsToManyAddAssociationMixin, + CreationOptional, + ForeignKey, + InferAttributes, + InferCreationAttributes, + NonAttribute, +} from '@sequelize/core'; +import { DataTypes, Model } from '@sequelize/core'; +import { expect } from 'chai'; +import sinon from 'sinon'; +import { beforeAll2, beforeEach2, sequelize, setResetMode } from '../../../support'; + +// This test suite ensures DataType methods are called at the appropriate time + +const dialect = sequelize.dialect; + +describe('DataType Methods', () => { + setResetMode('none'); + + const customValueSymbol = Symbol('dummy'); + + class CustomDataType extends DataTypes.STRING { + parseDatabaseValue(_value: unknown): any { + return customValueSymbol; + } + + _getBindDef(oracledb: any) { + return { type: oracledb.DB_TYPE_VARCHAR, maxSize: 255 }; + } + } + + const models = beforeAll2(async () => { + class User extends Model, InferCreationAttributes> { + declare id: CreationOptional; + declare name: string | null; + declare projects?: NonAttribute; + } + + User.init( + { + id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, + name: { type: CustomDataType, allowNull: true, field: 'first_name' }, + }, + { sequelize }, + ); + + class Project extends Model, InferCreationAttributes> { + declare name: string; + declare userId: ForeignKey; + declare stakeholders?: NonAttribute>; + + declare addStakeholder: BelongsToManyAddAssociationMixin; + } + + Project.init( + { + name: { type: CustomDataType, allowNull: false }, + }, + { sequelize }, + ); + + class ProjectStakeholder extends Model< + InferAttributes, + InferCreationAttributes + > { + declare key: string; + } + + ProjectStakeholder.init( + { + key: { type: CustomDataType, allowNull: false }, + }, + { sequelize, noPrimaryKey: true, timestamps: false }, + ); + + Project.belongsTo(User, { + as: 'user', + inverse: { as: 'projects', type: 'hasMany' }, + foreignKey: 'userId', + }); + + Project.belongsToMany(User, { + as: 'stakeholders', + inverse: 'stakeholdings', + through: ProjectStakeholder, + }); + + await User.sync({ force: true }); + await Project.sync({ force: true }); + await ProjectStakeholder.sync({ force: true }); + + const user1 = await User.create({ name: 'John' }); + const user2 = await User.create({ name: 'Stakeholder User' }); + const project = await Project.create({ name: 'Project 1', userId: user1.id }); + await project.addStakeholder(user2, { through: { key: 'dummy-value' } }); + + return { User, Project, ProjectStakeholder }; + }); + + const spies = beforeEach2(() => { + // add mocha spy to sanitize + return { + sanitize: sinon.spy(DataTypes.STRING.prototype, 'sanitize'), + validate: sinon.spy(DataTypes.STRING.prototype, 'validate'), + parseDatabaseValue: sinon.spy(CustomDataType.prototype, 'parseDatabaseValue'), + }; + }); + + afterEach(() => { + for (const spy of Object.values(spies)) { + spy.restore(); + } + }); + + it(`setting a value on a model only calls 'sanitize'`, () => { + models.User.build({ name: 'foo' }); + + expect(spies.sanitize.calledOnce).to.eq(true, 'sanitized not called exactly once'); + expect(spies.validate.called).to.eq(false, 'validate should not have been called'); + expect(spies.parseDatabaseValue.called).to.eq( + false, + 'parseDatabaseValue should not have been called', + ); + }); + + it(`retrieving a model only calls 'parseDatabaseValue' (no join)`, async () => { + const out = await models.User.findOne({ rejectOnEmpty: true }); + + expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue not called on top level model'); + + expect(spies.sanitize.called).to.eq(false, 'sanitize should not have been called'); + expect(spies.validate.called).to.eq(false, 'validate should not have been called'); + }); + + it(`retrieving a model only calls 'parseDatabaseValue' (with join)`, async () => { + // this test is separate from the no-join version because they use different code paths. + // We test both double nested associations & that through tables are handled correctly. + const out = await models.User.findOne({ + include: [ + { + association: 'projects', + include: ['stakeholders'], + }, + ], + rejectOnEmpty: true, + }); + + expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue not called on top level model'); + expect(out.projects![0].name).to.eq( + customValueSymbol, + 'parseDatabaseValue not called on first include level', + ); + expect(out.projects![0].stakeholders![0].name).to.eq( + customValueSymbol, + 'parseDatabaseValue not called on second include level', + ); + expect(out.projects![0].stakeholders![0].ProjectStakeholder.key).to.eq( + customValueSymbol, + 'parseDatabaseValue not called on Many-To-Many through table', + ); + + expect(spies.sanitize.called).to.eq(false, 'sanitize should not have been called'); + expect(spies.validate.called).to.eq(false, 'validate should not have been called'); + }); + + if (dialect.supports.returnValues) { + it(`inserting a model calls 'parseDatabaseValue' on returned values`, async () => { + // 'name' attr has a different name in the database + const out = await models.User.create({ name: 'foo' }, { returning: true }); + + expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); + + // sanitize is called when the user input is added to the model + expect(spies.sanitize.called).to.eq(true, 'sanitize should have been called'); + // validate is called before persisting the model + expect(spies.validate.called).to.eq(true, 'validate should have been called'); + }); + + it(`upserting a model calls 'parseDatabaseValue' on returned values`, async () => { + // 'name' attr has a different name in the database + const [out] = await models.User.upsert({ name: 'foo', id: 1234 }, { returning: true }); + + expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); + + // sanitize is called when the user input is added to the model + expect(spies.sanitize.called).to.eq(true, 'sanitize should have been called'); + // validate is called before persisting the model + expect(spies.validate.called).to.eq(true, 'validate should have been called'); + }); + } + + if (dialect.supports.returnValues === 'returning') { + it(`updating a model calls 'parseDatabaseValue' on returned values`, async () => { + const user = await models.User.create({ name: 'foo' }); + user.name = 'bob'; + await user.save({ returning: true }); + + expect(user.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); + }); + } + + it(`does not call 'parseDatabaseValue' on null values`, async () => { + const user = await models.User.create({ name: null }); + await user.reload(); + + expect(user.name).to.eq(null, 'parseDatabaseValue called on null value'); + expect(spies.parseDatabaseValue.called).to.eq( + false, + 'parseDatabaseValue should not have been called', + ); + }); +}); diff --git a/packages/core/test/integration/error.test.ts b/packages/core/test/integration/error.test.ts index e7784ddb56ae..c38e2d0ca264 100644 --- a/packages/core/test/integration/error.test.ts +++ b/packages/core/test/integration/error.test.ts @@ -492,7 +492,7 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { await expect(User.create({ name: 'jan' })).to.be.rejectedWith(UniqueConstraintError); // And when the model is not passed at all - if (['db2', 'ibmi'].includes(dialect)) { + if (['db2', 'ibmi', 'oracle'].includes(dialect)) { await expect( sequelize.query('INSERT INTO "users" ("name") VALUES (\'jan\')'), ).to.be.rejectedWith(UniqueConstraintError); @@ -550,7 +550,7 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { } catch (error) { expect(error).to.be.instanceOf(ValidationError); assert(error instanceof ValidationError); - if (dialect === 'db2') { + if (dialect === 'db2' || dialect === 'oracle') { expect(error.errors).to.have.length(0); } else { expect(error.errors).to.have.length(1); @@ -603,6 +603,10 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { expect(error.errors[0].message).to.equal('username must be unique'); break; + case 'oracle': + expect(error.cause.message).to.match(/ORA-00001: unique constraint \(.*\) violated/); + break; + default: expect(error.cause.message).to.contain("Duplicate entry 'foo' for key 'username'"); expect(error.errors[0].path).to.equal('username'); @@ -626,7 +630,7 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { } catch (error) { expect(error).to.be.instanceOf(ValidationError); assert(error instanceof ValidationError); - if (dialect === 'db2') { + if (dialect === 'db2' || dialect === 'oracle') { expect(error.errors).to.have.length(0); } else { expect(error.errors).to.have.length(1); @@ -675,6 +679,12 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { ); break; + case 'oracle': + expect(error.cause.message).to.match( + /ORA-00001: unique constraint \(.*.users_username_unique\) violated/, + ); + break; + default: expect(error.cause.message).to.contain( "Duplicate entry 'foo' for key 'users_username_unique'", @@ -711,7 +721,7 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { } catch (error) { expect(error).to.be.instanceOf(ForeignKeyConstraintError); assert(error instanceof ForeignKeyConstraintError); - if (dialect === 'sqlite3') { + if (dialect === 'sqlite3' || dialect === 'oracle') { expect(error.index).to.be.undefined; } else { expect(error.index).to.equal('Tasks_userId_Users_fk'); @@ -750,6 +760,14 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { ); break; + case 'oracle': + expect(error.table).to.be.undefined; + expect(error.fields).to.be.null; + expect(error.cause.message).to.match( + /ORA-02292: integrity constraint \(.*.Tasks_userId_Users_fk\) violated - child record found/, + ); + break; + default: expect(error.table).to.equal('Users'); expect(error.fields).to.deep.equal(['userId']); @@ -786,7 +804,7 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { } catch (error) { expect(error).to.be.instanceOf(ForeignKeyConstraintError); assert(error instanceof ForeignKeyConstraintError); - if (dialect === 'sqlite3') { + if (dialect === 'sqlite3' || dialect === 'oracle') { expect(error.index).to.be.undefined; } else { expect(error.index).to.equal('Tasks_userId_Users_fk'); @@ -825,6 +843,14 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { ); break; + case 'oracle': + expect(error.table).to.be.undefined; + expect(error.fields).to.be.null; + expect(error.cause.message).to.match( + /ORA-02291: integrity constraint \(.*.Tasks_userId_Users_fk\) violated - parent key not found/, + ); + break; + default: expect(error.table).to.equal('Users'); expect(error.fields).to.deep.equal(['userId']); @@ -867,6 +893,10 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { assert(error.errors[2] instanceof UnknownConstraintError); expect(error.errors[2].constraint).to.equal('unique_constraint'); expect(error.errors[2].table).to.equal('Users'); + } else if (dialect === 'oracle') { + expect(error).to.be.instanceOf(DatabaseError); + assert(error instanceof DatabaseError); + expect(error.message).to.match(/^ORA-02264: name already used by an existing constraint/); } else { expect(error).to.be.instanceOf(DatabaseError); assert(error instanceof DatabaseError); diff --git a/packages/core/test/integration/include.test.js b/packages/core/test/integration/include.test.js index 842b211aac45..59c7b499f14e 100644 --- a/packages/core/test/integration/include.test.js +++ b/packages/core/test/integration/include.test.js @@ -753,6 +753,20 @@ Instead of specifying a Model, either: break; } + case 'oracle': { + findAttributes = [ + Sequelize.literal( + '(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END) AS "postComments.someProperty"', + ), + [ + Sequelize.literal('(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END)'), + 'someProperty2', + ], + ]; + + break; + } + default: { findAttributes = [ Sequelize.literal('EXISTS(SELECT 1) AS "postComments.someProperty"'), diff --git a/packages/core/test/integration/include/findAll.test.js b/packages/core/test/integration/include/findAll.test.js index d27bfee27d45..5d39f0fbe4a8 100644 --- a/packages/core/test/integration/include/findAll.test.js +++ b/packages/core/test/integration/include/findAll.test.js @@ -121,7 +121,7 @@ describe(Support.getTestDialectTeaser('Include'), () => { { title: 'Pen' }, { title: 'Monitor' }, ]); - const products = await Product.findAll(); + const products = await Product.findAll({ order: [['id', 'ASC']] }); const groupMembers = [ { groupId: groups[0].id, rankId: ranks[0].id }, { groupId: groups[1].id, rankId: ranks[2].id }, @@ -343,7 +343,9 @@ describe(Support.getTestDialectTeaser('Include'), () => { for (const i of [0, 1, 2, 3, 4]) { const [user, products] = await Promise.all([ User.create(), - Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => Product.findAll()), + Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => + Product.findAll({ order: [['id', 'ASC']] }), + ), ]); await Promise.all([ GroupMember.bulkCreate([ @@ -1174,7 +1176,7 @@ describe(Support.getTestDialectTeaser('Include'), () => { await Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]); - const products = await Product.findAll(); + const products = await Product.findAll({ order: [['id', 'ASC']] }); await Promise.all([ GroupMember.bulkCreate([ { userId: user.id, groupId: groups[0].id, rankId: ranks[0].id }, diff --git a/packages/core/test/integration/include/schema.test.js b/packages/core/test/integration/include/schema.test.js index c19b4335af3d..a014d20e0596 100644 --- a/packages/core/test/integration/include/schema.test.js +++ b/packages/core/test/integration/include/schema.test.js @@ -154,7 +154,7 @@ describe(Support.getTestDialectTeaser('Includes with schemas'), () => { { title: 'Bed' }, { title: 'Pen' }, { title: 'Monitor' }, - ]).then(() => Product.findAll()), + ]).then(() => Product.findAll({ order: [['id', 'ASC']] })), ]); const groupMembers = [ { accUserId: user.id, GroupId: groups[0].id, rankId: ranks[0].id }, @@ -273,7 +273,9 @@ describe(Support.getTestDialectTeaser('Includes with schemas'), () => { for (const i of [0, 1, 2, 3, 4]) { const [user, products] = await Promise.all([ AccUser.create(), - Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => Product.findAll()), + Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => + Product.findAll({ order: [['id', 'ASC']] }), + ), ]); await Promise.all([ GroupMember.bulkCreate([ @@ -954,7 +956,9 @@ describe(Support.getTestDialectTeaser('Includes with schemas'), () => { for (const i of [0, 1, 2, 3, 4]) { const [user, products] = await Promise.all([ User.create({ name: 'FooBarzz' }), - Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => Product.findAll()), + Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => + Product.findAll({ order: [['id', 'ASC']] }), + ), ]); await Promise.all([ GroupMember.bulkCreate([ diff --git a/packages/core/test/integration/instance/values.test.js b/packages/core/test/integration/instance/values.test.js index e79930e0d244..1f089eb96217 100644 --- a/packages/core/test/integration/instance/values.test.js +++ b/packages/core/test/integration/instance/values.test.js @@ -111,7 +111,9 @@ describe(Support.getTestDialectTeaser('DAO'), () => { ? this.sequelize.fn('', this.sequelize.fn('datetime', 'now')) : dialect === 'mssql' ? this.sequelize.fn('', this.sequelize.fn('getdate')) - : this.sequelize.fn('NOW'); + : dialect === 'oracle' + ? this.sequelize.fn('', this.sequelize.literal('SYSDATE')) + : this.sequelize.fn('NOW'); user.set({ d: now, diff --git a/packages/core/test/integration/json.test.ts b/packages/core/test/integration/json.test.ts index f59f3034726d..8317c5ac3f3a 100644 --- a/packages/core/test/integration/json.test.ts +++ b/packages/core/test/integration/json.test.ts @@ -57,20 +57,25 @@ describe('JSON Manipulation', () => { expect(user.jsonAttr).to.deep.equal({ name: 'larry' }); }); - it('should be able to store strings that require escaping', async () => { - const text = 'Multi-line \n \'$string\' needing "escaping" for $$ and $1 type values'; - - await vars.User.create({ jsonAttr: text }); - const user = await vars.User.findOne({ rejectOnEmpty: true }); - expect(user.jsonAttr).to.equal(text); - }); + (dialectName === 'oracle' ? it.skip : it)( + 'should be able to store strings that require escaping', + async () => { + const text = 'Multi-line \n \'$string\' needing "escaping" for $$ and $1 type values'; + + await vars.User.create({ jsonAttr: text }); + const user = await vars.User.findOne({ rejectOnEmpty: true }); + expect(user.jsonAttr).to.equal(text); + }, + ); }); const JSON_OBJECT = { name: 'swen', phones: [1337, 42] }; const JSON_STRING = 'kate'; +// Oracle database < 21 doesn't supports scalars to be treated as JSON +// thus fails with CHECk constraint violation errors describe('JSON Querying', () => { - if (!dialect.supports.dataTypes.JSON) { + if (!dialect.supports.dataTypes.JSON || dialect.name === 'oracle') { return; } diff --git a/packages/core/test/integration/model-repository/bulk-destroy.test.ts b/packages/core/test/integration/model-repository/bulk-destroy.test.ts index fd97cb31e01f..ba878c0f1953 100644 --- a/packages/core/test/integration/model-repository/bulk-destroy.test.ts +++ b/packages/core/test/integration/model-repository/bulk-destroy.test.ts @@ -116,6 +116,16 @@ describe('ModelRepository#_UNSTABLE_bulkDestroy', () => { ], { genericQuotes: true }, ), + oracle: toMatchSql([ + 'BEGIN TRANSACTION', + 'SELECT "id", "createdAt", "updatedAt" FROM "Users" "User" WHERE "User"."id" = 1;', + 'SELECT "id", "ownerId", "createdAt", "updatedAt" FROM "Projects" "Project" WHERE "Project"."ownerId" IN (1);', + 'SELECT "id", "projectId", "createdAt", "updatedAt" FROM "Tasks" "Task" WHERE "Task"."projectId" IN (1);', + 'DELETE FROM "Tasks" WHERE "id" = 1', + 'DELETE FROM "Projects" WHERE "id" = 1', + 'DELETE FROM "Users" WHERE "id" = 1', + 'COMMIT TRANSACTION', + ]), }); }); @@ -155,6 +165,14 @@ describe('ModelRepository#_UNSTABLE_bulkDestroy', () => { 'DELETE FROM [Projects] WHERE [id] = 1; SELECT @@ROWCOUNT AS AFFECTEDROWS;', 'DELETE FROM [Users] WHERE [id] = 1; SELECT @@ROWCOUNT AS AFFECTEDROWS;', ]), + oracle: toMatchSql([ + 'SELECT "id", "createdAt", "updatedAt" FROM "Users" "User" WHERE "User"."id" = 1;', + 'SELECT "id", "ownerId", "createdAt", "updatedAt" FROM "Projects" "Project" WHERE "Project"."ownerId" IN (1);', + 'SELECT "id", "projectId", "createdAt", "updatedAt" FROM "Tasks" "Task" WHERE "Task"."projectId" IN (1);', + 'DELETE FROM "Tasks" WHERE "id" = 1', + 'DELETE FROM "Projects" WHERE "id" = 1', + 'DELETE FROM "Users" WHERE "id" = 1', + ]), }); }); }); diff --git a/packages/core/test/integration/model-repository/destroy.test.ts b/packages/core/test/integration/model-repository/destroy.test.ts index c800557bb72d..885c0cf46144 100644 --- a/packages/core/test/integration/model-repository/destroy.test.ts +++ b/packages/core/test/integration/model-repository/destroy.test.ts @@ -109,6 +109,15 @@ describe('ModelRepository#_UNSTABLE_destroy', () => { ], { genericQuotes: true }, ), + oracle: toMatchSql([ + 'BEGIN TRANSACTION', + 'SELECT "id", "ownerId", "createdAt", "updatedAt" FROM "Projects" "Project" WHERE "Project"."ownerId" IN (1);', + 'SELECT "id", "projectId", "createdAt", "updatedAt" FROM "Tasks" "Task" WHERE "Task"."projectId" IN (1);', + 'DELETE FROM "Tasks" WHERE "id" = 1', + 'DELETE FROM "Projects" WHERE "id" = 1', + 'DELETE FROM "Users" WHERE "id" = 1', + 'COMMIT TRANSACTION', + ]), }); }); @@ -144,6 +153,13 @@ describe('ModelRepository#_UNSTABLE_destroy', () => { 'DELETE FROM [Projects] WHERE [id] = 1; SELECT @@ROWCOUNT AS AFFECTEDROWS;', 'DELETE FROM [Users] WHERE [id] = 1; SELECT @@ROWCOUNT AS AFFECTEDROWS;', ]), + oracle: toMatchSql([ + 'SELECT "id", "ownerId", "createdAt", "updatedAt" FROM "Projects" "Project" WHERE "Project"."ownerId" IN (1);', + 'SELECT "id", "projectId", "createdAt", "updatedAt" FROM "Tasks" "Task" WHERE "Task"."projectId" IN (1);', + 'DELETE FROM "Tasks" WHERE "id" = 1', + 'DELETE FROM "Projects" WHERE "id" = 1', + 'DELETE FROM "Users" WHERE "id" = 1', + ]), }); }); }); diff --git a/packages/core/test/integration/model.test.js b/packages/core/test/integration/model.test.js index 6fee10188e18..2f7d58de63a6 100644 --- a/packages/core/test/integration/model.test.js +++ b/packages/core/test/integration/model.test.js @@ -286,6 +286,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { } case 'db2': + case 'oracle': case 'mssql': { expect(index.fields).to.deep.equal([ { attribute: 'user_name', collate: undefined, length: undefined, order: 'ASC' }, @@ -551,6 +552,28 @@ describe(Support.getTestDialectTeaser('Model'), () => { break; } + case 'oracle': { + primary = args[0]; + idx1 = args[1]; + idx2 = args[2]; + idx3 = args[3]; + + expect(idx1.fields).to.deep.equal([ + { attribute: 'fieldB', length: undefined, order: 'ASC', collate: undefined }, + { attribute: 'fieldA', length: undefined, order: 'ASC', collate: undefined }, + ]); + + expect(idx2.fields).to.deep.equal([ + { attribute: 'fieldC', length: undefined, order: 'ASC', collate: undefined }, + ]); + + expect(idx3.fields).to.deep.equal([ + { attribute: 'fieldD', length: undefined, order: 'ASC', collate: undefined }, + ]); + + break; + } + case 'db2': { idx1 = args[1]; @@ -1012,7 +1035,9 @@ describe(Support.getTestDialectTeaser('Model'), () => { if (dialectName === 'sqlite3' && sql.includes('TABLE_INFO')) { test++; expect(sql).to.not.contain('special'); - } else if (['mysql', 'mssql', 'mariadb', 'db2', 'ibmi'].includes(dialectName)) { + } else if ( + ['mysql', 'mssql', 'mariadb', 'db2', 'ibmi', 'oracle'].includes(dialectName) + ) { test++; expect(sql).to.not.contain('special'); } @@ -1031,7 +1056,9 @@ describe(Support.getTestDialectTeaser('Model'), () => { if (dialectName === 'sqlite3' && sql.includes('TABLE_INFO')) { test++; expect(sql).to.contain('special'); - } else if (['mysql', 'mssql', 'mariadb', 'db2', 'ibmi'].includes(dialectName)) { + } else if ( + ['mysql', 'mssql', 'mariadb', 'db2', 'ibmi', 'oracle'].includes(dialectName) + ) { test++; expect(sql).to.contain('special'); } @@ -1080,7 +1107,8 @@ describe(Support.getTestDialectTeaser('Model'), () => { switch (dialectName) { case 'postgres': case 'db2': - case 'ibmi': { + case 'ibmi': + case 'oracle': { expect(sql).to.match(/REFERENCES\s+"prefix"\."UserPubs" \("id"\)/); break; @@ -1127,7 +1155,8 @@ describe(Support.getTestDialectTeaser('Model'), () => { switch (dialectName) { case 'postgres': case 'db2': - case 'ibmi': { + case 'ibmi': + case 'oracle': { expect(UserPublic).to.include('INSERT INTO "UserPublics"'); break; @@ -1159,7 +1188,8 @@ describe(Support.getTestDialectTeaser('Model'), () => { switch (dialectName) { case 'postgres': case 'db2': - case 'ibmi': { + case 'ibmi': + case 'oracle': { expect(UserSpecial).to.include('INSERT INTO "special"."UserSpecials"'); break; @@ -1197,7 +1227,8 @@ describe(Support.getTestDialectTeaser('Model'), () => { switch (dialectName) { case 'postgres': case 'db2': - case 'ibmi': { + case 'ibmi': + case 'oracle': { expect(user).to.include('UPDATE "special"."UserSpecials"'); break; @@ -1395,6 +1426,12 @@ describe(Support.getTestDialectTeaser('Model'), () => { break; } + case 'oracle': { + expect(error.message).to.match(/^ORA-00942:/); + + break; + } + case 'ibmi': { expect(error.message).to.match( /[a-zA-Z0-9[\] /-]+?"4uth0r5" in SEQUELIZE type \*FILE not found\./, diff --git a/packages/core/test/integration/model/attributes/field.test.js b/packages/core/test/integration/model/attributes/field.test.js index 821f61d4b453..39d680855e81 100644 --- a/packages/core/test/integration/model/attributes/field.test.js +++ b/packages/core/test/integration/model/attributes/field.test.js @@ -487,6 +487,16 @@ describe(Support.getTestDialectTeaser('Model'), () => { Sequelize.literal('1 AS "someProperty"'), [Sequelize.literal('1'), 'someProperty2'], ]; + } else if (dialect === 'oracle') { + findAttributes = [ + Sequelize.literal( + '(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END) AS "someProperty"', + ), + [ + Sequelize.literal('(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END)'), + 'someProperty2', + ], + ]; } else { findAttributes = [ Sequelize.literal('EXISTS(SELECT 1) AS "someProperty"'), diff --git a/packages/core/test/integration/model/attributes/types.test.js b/packages/core/test/integration/model/attributes/types.test.js index 91c445c95e58..1b041a32a6f5 100644 --- a/packages/core/test/integration/model/attributes/types.test.js +++ b/packages/core/test/integration/model/attributes/types.test.js @@ -112,6 +112,8 @@ describe(Support.getTestDialectTeaser('Model'), () => { 'CAST(CASE WHEN EXISTS(SELECT 1) THEN 1 ELSE 0 END AS BIT) AS "someBoolean"'; } else if (['db2', 'ibmi'].includes(dialect)) { boolQuery = '1 AS "someBoolean"'; + } else if (dialect === 'oracle') { + boolQuery = '(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END) AS "someBoolean"'; } const post = await Post.findOne({ diff --git a/packages/core/test/integration/model/bulk-create.test.js b/packages/core/test/integration/model/bulk-create.test.js index d585e6fcc536..b2708e970050 100644 --- a/packages/core/test/integration/model/bulk-create.test.js +++ b/packages/core/test/integration/model/bulk-create.test.js @@ -170,6 +170,7 @@ describe('Model', () => { logging(sql) { switch (dialectName) { case 'postgres': + case 'oracle': case 'ibmi': { expect(sql).to.include( 'INSERT INTO "Beers" ("id","style","createdAt","updatedAt") VALUES (DEFAULT', diff --git a/packages/core/test/integration/model/count.test.js b/packages/core/test/integration/model/count.test.js index 397312215800..b58073af119d 100644 --- a/packages/core/test/integration/model/count.test.js +++ b/packages/core/test/integration/model/count.test.js @@ -55,7 +55,12 @@ describe('Model.count', () => { }); }); - if (dialectName !== 'mssql' && dialectName !== 'db2' && dialectName !== 'ibmi') { + if ( + dialectName !== 'mssql' && + dialectName !== 'db2' && + dialectName !== 'ibmi' && + dialectName !== 'oracle' + ) { describe('aggregate', () => { it('allows grouping by aliased attribute', async function () { await this.User.aggregate('id', 'count', { diff --git a/packages/core/test/integration/model/create.test.js b/packages/core/test/integration/model/create.test.js index fcf096815ca1..b013c8e1ca16 100644 --- a/packages/core/test/integration/model/create.test.js +++ b/packages/core/test/integration/model/create.test.js @@ -495,7 +495,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { } it('should not fail silently with concurrency higher than pool, a unique constraint and a create hook resulting in mismatched values', async function () { - if (['sqlite3', 'mssql', 'db2', 'ibmi'].includes(dialectName)) { + if (['sqlite', 'mssql', 'db2', 'ibmi', 'oracle'].includes(dialectName)) { return; } @@ -911,7 +911,9 @@ describe(Support.getTestDialectTeaser('Model'), () => { ? '$sequelize_1' : dialectName === 'mssql' ? '@sequelize_1' - : '?'; + : dialectName === 'oracle' + ? ':1' + : '?'; let match = false; const user = await this.User.create( diff --git a/packages/core/test/integration/model/findAll.test.js b/packages/core/test/integration/model/findAll.test.js index e3a0d4f1e914..0ee161355a1b 100644 --- a/packages/core/test/integration/model/findAll.test.js +++ b/packages/core/test/integration/model/findAll.test.js @@ -26,7 +26,9 @@ describe(Support.getTestDialectTeaser('Model'), () => { intVal: DataTypes.INTEGER, theDate: DataTypes.DATE, aBool: DataTypes.BOOLEAN, - binary: DataTypes.BLOB, + ...(dialectName === 'oracle' + ? { binary: DataTypes.STRING(16, true) } + : { binary: DataTypes.BLOB }), }); await this.User.sync({ force: true }); @@ -117,6 +119,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { }); }); + // Oracle WHERE IN clause for BLOB isn't supported. Use `RAW` datatype. it('should not break when using smart syntax on binary fields', async function () { const users = await this.User.findAll({ where: { diff --git a/packages/core/test/integration/model/findAll/order.test.js b/packages/core/test/integration/model/findAll/order.test.js index ca52996eca7e..c70a23bdb913 100644 --- a/packages/core/test/integration/model/findAll/order.test.js +++ b/packages/core/test/integration/model/findAll/order.test.js @@ -24,7 +24,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { }); }); - if (current.dialect.name !== 'mssql' && current.dialect.name !== 'ibmi') { + if (!['oracle', 'ibmi', 'mssql'].includes(current.dialect.name)) { const email = current.dialect.name === 'db2' ? '"email"' : 'email'; it('should work with order: literal()', async function () { const users = await this.User.findAll({ @@ -96,7 +96,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { } it('should not throw on a literal', async function () { - if (['db2', 'ibmi'].includes(current.dialect.name)) { + if (['db2', 'ibmi', 'oracle'].includes(current.dialect.name)) { await this.User.findAll({ order: [['id', this.sequelize.literal('ASC, "name" DESC')]], }); diff --git a/packages/core/test/integration/model/paranoid.test.js b/packages/core/test/integration/model/paranoid.test.js index b8070ba29f77..2e734f4bf89f 100644 --- a/packages/core/test/integration/model/paranoid.test.js +++ b/packages/core/test/integration/model/paranoid.test.js @@ -124,40 +124,44 @@ describe('Paranoid Model', () => { await this.Model.sync({ force: true }); }); - it('should soft delete with JSON condition', async function () { - await this.Model.bulkCreate([ - { - name: 'One', - data: { - field: { - deep: true, + // Oracle stores JSON as BLOB. where condition with equality isn't supported for this. + (dialectName === 'oracle' ? it.skip : it)( + 'should soft delete with JSON condition', + async function () { + await this.Model.bulkCreate([ + { + name: 'One', + data: { + field: { + deep: true, + }, }, }, - }, - { - name: 'Two', - data: { - field: { - deep: false, + { + name: 'Two', + data: { + field: { + deep: false, + }, }, }, - }, - ]); - - await this.Model.destroy({ - where: { - data: { - field: { - deep: true, + ]); + + await this.Model.destroy({ + where: { + data: { + field: { + deep: true, + }, }, }, - }, - }); + }); - const records = await this.Model.findAll(); - expect(records.length).to.equal(1); - expect(records[0].get('name')).to.equal('Two'); - }); + const records = await this.Model.findAll(); + expect(records.length).to.equal(1); + expect(records[0].get('name')).to.equal('Two'); + }, + ); }); } diff --git a/packages/core/test/integration/model/update.test.ts b/packages/core/test/integration/model/update.test.ts index af6a523923b8..a500e47893c2 100644 --- a/packages/core/test/integration/model/update.test.ts +++ b/packages/core/test/integration/model/update.test.ts @@ -457,6 +457,7 @@ describe('Model.update', () => { mssql: `UPDATE [users1] SET [secretValue]=@sequelize_1,[updatedAt]=@sequelize_2 OUTPUT INSERTED.* WHERE [id] = @sequelize_3`, db2: `SELECT * FROM FINAL TABLE (UPDATE "users1" SET "secretValue"=?,"updatedAt"=? WHERE "id" = ?);`, ibmi: `UPDATE "users1" SET "secretValue"=?,"updatedAt"=? WHERE "id" = ?;`, + oracle: `UPDATE "users1" SET "secretValue"=:1,"updatedAt"=:2 WHERE "id" = :3`, }); }, returning: [sql.col('*')], diff --git a/packages/core/test/integration/pool.test.ts b/packages/core/test/integration/pool.test.ts index 58894933e8d1..57abb9e2ae79 100644 --- a/packages/core/test/integration/pool.test.ts +++ b/packages/core/test/integration/pool.test.ts @@ -41,6 +41,10 @@ function assertSameConnection( expect(newConnection.dummyId).to.equal(oldConnection.dummyId).and.to.be.ok; break; + case 'oracle': + expect(oldConnection).to.be.equal(newConnection); + break; + default: throw new Error('Unsupported dialect'); } @@ -75,6 +79,10 @@ function assertNewConnection(newConnection: AbstractConnection, oldConnection: A expect(oldConnection.dummyId).to.be.ok; break; + case 'oracle': + expect(oldConnection).to.not.be.equal(newConnection); + break; + default: throw new Error('Unsupported dialect'); } diff --git a/packages/core/test/integration/query-interface/add-show-remove-constraint.test.ts b/packages/core/test/integration/query-interface/add-show-remove-constraint.test.ts index 462936ebc806..0cc6d0f0cee2 100644 --- a/packages/core/test/integration/query-interface/add-show-remove-constraint.test.ts +++ b/packages/core/test/integration/query-interface/add-show-remove-constraint.test.ts @@ -78,6 +78,8 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { 'Expected error to be an instance of AggregateError', ); err = error.errors.at(-1); + } else if (dialect === 'oracle') { + expect(error).to.be.instanceOf(UnknownConstraintError); } else { assert( err instanceof UnknownConstraintError, @@ -112,14 +114,13 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: 'custom_constraint_name', constraintType: 'UNIQUE', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - tableSchema: defaultSchema, + ...(dialect !== 'oracle' && { tableSchema: defaultSchema }), tableName: 'actors', - columnNames: ['name', 'age'], + columnNames: dialect === 'oracle' ? ['age', 'name'] : ['name', 'age'], ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), }); - await queryInterface.removeConstraint('actors', 'custom_constraint_name'); const constraintsAfterRemove = await queryInterface.showConstraints('actors', { constraintName: 'custom_constraint_name', @@ -156,14 +157,17 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: 'custom_constraint_name', constraintType: 'FOREIGN KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - tableSchema: defaultSchema, + ...(dialect !== 'oracle' && { tableSchema: defaultSchema }), tableName: 'actors', columnNames: ['level_id'], referencedTableName: 'levels', referencedTableSchema: defaultSchema, referencedColumnNames: ['id'], deleteAction: 'CASCADE', - updateAction: dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', + ...(dialect !== 'oracle' && { + updateAction: + dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', + }), ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), @@ -186,7 +190,7 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: ['mariadb', 'mysql'].includes(dialect) ? 'PRIMARY' : 'pk_levels', constraintType: 'PRIMARY KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - tableSchema: defaultSchema, + ...(dialect !== 'oracle' && { tableSchema: defaultSchema }), tableName: 'levels', columnNames: ['id'], ...(sequelize.dialect.supports.constraints.deferrable && { @@ -232,14 +236,17 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: 'custom_constraint_name', constraintType: 'FOREIGN KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - tableSchema: defaultSchema, + ...(dialect !== 'oracle' && { tableSchema: defaultSchema }), tableName: 'actors', columnNames: ['level_id', 'manager_id'], referencedTableSchema: defaultSchema, referencedTableName: 'levels', referencedColumnNames: ['id', 'manager_id'], deleteAction: 'CASCADE', - updateAction: dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', + ...(dialect !== 'oracle' && { + updateAction: + dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', + }), ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), @@ -261,9 +268,9 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: ['mariadb', 'mysql'].includes(dialect) ? 'PRIMARY' : 'pk_levels', constraintType: 'PRIMARY KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - tableSchema: defaultSchema, + ...(dialect !== 'oracle' && { tableSchema: defaultSchema }), tableName: 'levels', - columnNames: ['id', 'manager_id'], + columnNames: dialect === 'oracle' ? ['manager_id', 'id'] : ['id', 'manager_id'], ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), @@ -296,7 +303,7 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { field: 'id', }, onDelete: 'CASCADE', - onUpdate: 'CASCADE', + onUpdate: dialect !== 'oracle' ? 'CASCADE' : undefined, }); const constraintType = await queryInterface.showConstraints('actors', { @@ -344,7 +351,7 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { const constraintType = await queryInterface.showConstraints('actors', { constraintType: 'CHECK', }); - if (dialect === 'postgres') { + if (dialect === 'postgres' || dialect === 'oracle') { // Postgres adds a CHECK constraint for each column with not null expect(constraintType).to.have.length(6); expect(constraintType[5].constraintType).to.equal('CHECK'); @@ -360,21 +367,24 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { expect(constraints[0]).to.deep.equal({ ...(['mssql', 'postgres'].includes(dialect) && { constraintCatalog: 'sequelize_test' }), constraintSchema: defaultSchema, + ...(['oracle'].includes(dialect) && { columnNames: ['age'] }), constraintName: 'custom_constraint_name', constraintType: 'CHECK', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - tableSchema: defaultSchema, + ...(dialect !== 'oracle' && { tableSchema: defaultSchema }), tableName: 'actors', - definition: - dialect === 'mssql' - ? '([age]>(10))' - : dialect === 'db2' - ? '"age" > 10' - : dialect === 'postgres' - ? '((age > 10))' - : ['mysql', 'sqlite3'].includes(dialect) - ? '(`age` > 10)' - : '`age` > 10', + ...(dialect !== 'oracle' && { + definition: + dialect === 'mssql' + ? '([age]>(10))' + : dialect === 'db2' + ? '"age" > 10' + : dialect === 'postgres' + ? '((age > 10))' + : ['mysql', 'sqlite3'].includes(dialect) + ? '(`age` > 10)' + : '`age` > 10', + }), ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), @@ -526,15 +536,17 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: 'custom_constraint_name', constraintType: 'FOREIGN KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - tableSchema: schema, + ...(dialect !== 'oracle' && { tableSchema: schema }), tableName: 'actors', columnNames: ['level_id'], referencedTableSchema: schema, referencedTableName: 'levels', referencedColumnNames: ['id'], deleteAction: 'CASCADE', - updateAction: - dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', + ...(dialect !== 'oracle' && { + updateAction: + dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', + }), ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), @@ -561,7 +573,7 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: ['mariadb', 'mysql'].includes(dialect) ? 'PRIMARY' : 'pk_levels', constraintType: 'PRIMARY KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - tableSchema: schema, + ...(dialect !== 'oracle' && { tableSchema: schema }), tableName: 'levels', columnNames: ['id'], ...(sequelize.dialect.supports.constraints.deferrable && { @@ -647,15 +659,17 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: 'custom_constraint_name', constraintType: 'FOREIGN KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - tableSchema: schema, + ...(dialect !== 'oracle' && { tableSchema: schema }), tableName: 'actors', columnNames: ['level_id'], referencedTableSchema: schema, referencedTableName: 'levels', referencedColumnNames: ['id'], deleteAction: 'CASCADE', - updateAction: - dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', + ...(dialect !== 'oracle' && { + updateAction: + dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', + }), ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), @@ -675,15 +689,17 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: 'custom_constraint_name', constraintType: 'FOREIGN KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - tableSchema: sequelize.dialect.getDefaultSchema(), + ...(dialect !== 'oracle' && { tableSchema: sequelize.dialect.getDefaultSchema() }), tableName: 'actors', columnNames: ['level_id'], referencedTableSchema: sequelize.dialect.getDefaultSchema(), referencedTableName: 'levels', referencedColumnNames: ['id'], deleteAction: 'CASCADE', - updateAction: - dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', + ...(dialect !== 'oracle' && { + updateAction: + dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', + }), ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), diff --git a/packages/core/test/integration/query-interface/changeColumn.test.js b/packages/core/test/integration/query-interface/changeColumn.test.js index eab6d6279758..ccdf90198296 100644 --- a/packages/core/test/integration/query-interface/changeColumn.test.js +++ b/packages/core/test/integration/query-interface/changeColumn.test.js @@ -51,6 +51,8 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { if (['postgres', 'postgres-native', 'mssql', 'db2'].includes(dialect)) { expect(table.currency.type).to.equal('REAL'); + } else if (dialect === 'oracle') { + expect(table.currency.type).to.equal('BINARY_FLOAT'); } else { expect(table.currency.type).to.equal('FLOAT'); } @@ -89,6 +91,8 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { if (['postgres', 'postgres-native', 'mssql', 'sqlite3', 'db2'].includes(dialect)) { expect(table.currency.type).to.equal('REAL'); + } else if (dialect === 'oracle') { + expect(table.currency.type).to.equal('BINARY_FLOAT'); } else { expect(table.currency.type).to.equal('FLOAT'); } @@ -251,7 +255,7 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { expect(describedTable.level_id.allowNull).to.equal(true); }); - if (!['db2', 'ibmi', 'sqlite3'].includes(dialect)) { + if (!['db2', 'ibmi', 'sqlite3', 'oracle'].includes(dialect)) { it('should change the comment of column', async function () { const describedTable = await this.queryInterface.describeTable({ tableName: 'users', diff --git a/packages/core/test/integration/query-interface/describeTable.test.js b/packages/core/test/integration/query-interface/describeTable.test.js index ac8e4036f5ec..0722056ce413 100644 --- a/packages/core/test/integration/query-interface/describeTable.test.js +++ b/packages/core/test/integration/query-interface/describeTable.test.js @@ -117,6 +117,9 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { case 'db2': assertVal = 'VARCHAR'; break; + case 'oracle': + assertVal = 'NVARCHAR2'; + break; } expect(username.type).to.equal(assertVal); @@ -124,6 +127,7 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { switch (dialect) { case 'sqlite3': + case 'oracle': expect(username.defaultValue).to.be.undefined; break; default: @@ -151,12 +155,16 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { case 'ibmi': assertVal = 'SMALLINT'; break; + case 'oracle': + assertVal = 'CHAR'; + break; } expect(isAdmin.type).to.equal(assertVal); expect(isAdmin.allowNull).to.be.true; switch (dialect) { case 'sqlite3': + case 'oracle': expect(isAdmin.defaultValue).to.be.undefined; break; default: @@ -168,6 +176,8 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { expect(enumVals.special).to.have.length(2); } else if (dialect === 'mysql') { expect(enumVals.type).to.eql("ENUM('hello','world')"); + } else if (dialect === 'oracle') { + expect(enumVals.type).to.eql('VARCHAR2'); } if (['postgres', 'mysql', 'mssql'].includes(dialect)) { diff --git a/packages/core/test/integration/query-interface/list-tables.test.ts b/packages/core/test/integration/query-interface/list-tables.test.ts index aa1ecf9e8f43..162b5557f922 100644 --- a/packages/core/test/integration/query-interface/list-tables.test.ts +++ b/packages/core/test/integration/query-interface/list-tables.test.ts @@ -33,14 +33,36 @@ describe('QueryInterface#listTables', () => { throw error; } } + } else if (dialectName === 'oracle') { + const plsql = [ + 'BEGIN', + 'EXECUTE IMMEDIATE', + "'DROP VIEW V_Fail';", + 'EXCEPTION WHEN OTHERS THEN', + ' IF SQLCODE != -942 THEN', + ' RAISE;', + ' END IF;', + 'END;', + ].join(' '); + await sequelize.query(plsql); } else { await sequelize.queryRaw('DROP VIEW IF EXISTS V_Fail;'); } } + const fromQuery = () => { + if (['db2', 'ibmi'].includes(dialectName)) { + return 'FROM SYSIBM.SYSDUMMY1'; + } else if (dialectName === 'oracle') { + return 'FROM DUAL'; + } + + return ''; + }; + await queryInterface.createTable('my_test_table', { name: DataTypes.STRING }); await cleanup(); - const sql = `CREATE VIEW V_Fail AS SELECT 1 Id${['db2', 'ibmi'].includes(dialectName) ? ' FROM SYSIBM.SYSDUMMY1' : ''};`; + const sql = `CREATE VIEW V_Fail AS SELECT 1 Id ${fromQuery()};`; await sequelize.queryRaw(sql); const allTables = await queryInterface.listTables(); const tableNames = allTables.map(v => v.tableName); diff --git a/packages/core/test/integration/query-interface/remove-column.test.ts b/packages/core/test/integration/query-interface/remove-column.test.ts index e578ad502c80..fe74622c583a 100644 --- a/packages/core/test/integration/query-interface/remove-column.test.ts +++ b/packages/core/test/integration/query-interface/remove-column.test.ts @@ -214,15 +214,17 @@ describe(getTestDialectTeaser('QueryInterface#removeColumn'), () => { constraintName: dialectName === 'sqlite3' ? 'FOREIGN' : 'actors_level_id_fkey', constraintType: 'FOREIGN KEY', ...(['mssql', 'postgres'].includes(dialectName) && { tableCatalog: 'sequelize_test' }), - tableSchema: defaultSchema, + ...(dialectName !== 'oracle' && { tableSchema: defaultSchema }), tableName: 'actors', columnNames: ['level_id'], referencedTableName: 'level', referencedTableSchema: defaultSchema, referencedColumnNames: ['id'], deleteAction: 'CASCADE', - updateAction: - dialectName === 'mariadb' ? 'RESTRICT' : dialectName === 'sqlite3' ? '' : 'NO ACTION', + ...(dialectName !== 'oracle' && { + updateAction: + dialectName === 'mariadb' ? 'RESTRICT' : dialectName === 'sqlite3' ? '' : 'NO ACTION', + }), ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), diff --git a/packages/core/test/integration/query-interface/schemas.test.ts b/packages/core/test/integration/query-interface/schemas.test.ts index a172ed1fd931..5567d27dc154 100644 --- a/packages/core/test/integration/query-interface/schemas.test.ts +++ b/packages/core/test/integration/query-interface/schemas.test.ts @@ -179,13 +179,16 @@ describe('QueryInterface#{create,drop,list}Schema', () => { expect(postDeletionSchemas).to.not.include(testSchema, 'dropSchema did not drop testSchema'); }); + // For Oracle Database, users are considered as schema. listSchemas() doesn't allow to fetch the + // defaultSchema. it('shows all schemas', async () => { await queryInterface.createSchema(testSchema); const allSchemas = await queryInterface.listSchemas(); - const expected = !dialect.supports.multiDatabases - ? [sequelize.dialect.getDefaultSchema(), testSchema] - : [testSchema]; + const expected = + !dialect.supports.multiDatabases && dialect.name !== 'oracle' + ? [sequelize.dialect.getDefaultSchema(), testSchema] + : [testSchema]; expect(allSchemas.sort()).to.deep.eq(expected.sort(basicComparator())); }); diff --git a/packages/core/test/integration/sequelize.test.js b/packages/core/test/integration/sequelize.test.js index 3cf3982e7c1f..699dabfa2968 100644 --- a/packages/core/test/integration/sequelize.test.js +++ b/packages/core/test/integration/sequelize.test.js @@ -21,7 +21,7 @@ const { CONFIG } = require('../config/config'); const dialect = getTestDialect(); const qq = str => { - if (['postgres', 'mssql', 'db2', 'ibmi'].includes(dialect)) { + if (['postgres', 'mssql', 'db2', 'ibmi', 'oracle'].includes(dialect)) { return `"${str}"`; } @@ -61,6 +61,9 @@ const badUsernameConfig = { snowflake: { account: 'bad_account', }, + oracle: { + username: 'bad_user', + }, }; const noPasswordConfig = { @@ -92,6 +95,9 @@ const noPasswordConfig = { snowflake: { password: null, }, + oracle: { + password: null, + }, }; const badAddressConfig = { @@ -117,6 +123,9 @@ const badAddressConfig = { ibmi: { system: 'bad-address', }, + oracle: { + port: 9999, + }, }; describe(getTestDialectTeaser('Sequelize'), () => { @@ -384,6 +393,12 @@ describe(getTestDialectTeaser('Sequelize'), () => { break; } + case 'oracle': { + expect(error.message).to.include('NJS-007'); + + break; + } + case 'ibmi': { expect(error.message).to.equal('[odbc] Error connecting to the database'); expect(error.cause.odbcErrors[0].message).to.include( diff --git a/packages/core/test/integration/sequelize/query.test.js b/packages/core/test/integration/sequelize/query.test.js index 00357119657a..a5db0bcd23d3 100644 --- a/packages/core/test/integration/sequelize/query.test.js +++ b/packages/core/test/integration/sequelize/query.test.js @@ -26,7 +26,7 @@ const dialectName = getTestDialect(); const queryGenerator = sequelize.queryGenerator; const qq = str => { - if (['postgres', 'mssql', 'db2', 'ibmi'].includes(dialectName)) { + if (['postgres', 'mssql', 'db2', 'ibmi', 'oracle'].includes(dialectName)) { return `"${str}"`; } @@ -37,6 +37,25 @@ const qq = str => { return str; }; +const fromQuery = () => { + let query = ''; + if (dialectName === 'oracle') { + query += ' FROM DUAL'; + } else if (dialectName === 'ibmi') { + query += ' FROM SYSIBM.SYSDUMMY1'; + } + + return query; +}; + +const dateLiteral = str => { + if (dialectName === 'oracle') { + return `to_date('${str}','YYYY-MM-DD HH24:MI:SS')`; + } + + return `'${str}'`; +}; + describe(getTestDialectTeaser('Sequelize'), () => { allowDeprecationsInSuite(['SEQUELIZE0023']); @@ -57,11 +76,11 @@ describe(getTestDialectTeaser('Sequelize'), () => { }, }); - this.insertQuery = `INSERT INTO ${qq(this.User.tableName)} (username, email_address, ${qq( + this.insertQuery = `INSERT INTO ${qq(this.User.tableName)} (${qq('username')}, ${qq('email_address')}, ${qq( 'createdAt', )}, ${qq( 'updatedAt', - )}) VALUES ('john', 'john@gmail.com', '2012-01-01 10:10:10', '2012-01-01 10:10:10')`; + )}) VALUES ('john', 'john@gmail.com', ${dateLiteral('2012-01-01 10:10:10')}, ${dateLiteral('2012-01-01 10:10:10')})`; if (['db2', 'ibmi'].includes(dialectName)) { this.insertQuery = `INSERT INTO ${qq(this.User.tableName)} ("username", "email_address", ${qq('createdAt')}, ${qq('updatedAt')}) VALUES ('john', 'john@gmail.com', '2012-01-01 10:10:10', '2012-01-01 10:10:10')`; @@ -100,8 +119,10 @@ describe(getTestDialectTeaser('Sequelize'), () => { it('properly bind parameters on extra retries', async function () { const payload = { username: 'test', - createdAt: '2010-10-10 00:00:00', - updatedAt: '2010-10-10 00:00:00', + createdAt: + dialectName === 'oracle' ? new Date('2010-10-10 00:00:00') : '2010-10-10 00:00:00', + updatedAt: + dialectName === 'oracle' ? new Date('2010-10-10 00:00:00') : '2010-10-10 00:00:00', }; const spy = sinon.spy(); @@ -135,7 +156,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { benchmark: true, }); - await sequelize.query(`select 1${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''};`); + await sequelize.query(`select 1${fromQuery()};`); expect(logger.calledOnce).to.be.true; expect(logger.args[0][0]).to.be.match(/Executed \((\d*|default)\): select 1/); expect(typeof logger.args[0][1] === 'number').to.be.true; @@ -144,13 +165,10 @@ describe(getTestDialectTeaser('Sequelize'), () => { it('executes a query with benchmarking option and custom logger', async function () { const logger = sinon.spy(); - await this.sequelize.query( - `select 1${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''};`, - { - logging: logger, - benchmark: true, - }, - ); + await this.sequelize.query(`select 1${fromQuery()};`, { + logging: logger, + benchmark: true, + }); expect(logger.calledOnce).to.be.true; expect(logger.args[0][0]).to.be.match(/Executed \(\d*|default\): select 1;/); @@ -163,12 +181,9 @@ describe(getTestDialectTeaser('Sequelize'), () => { logging: logger, }); - await sequelize.query( - `select 1${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''};`, - { - queryLabel: 'tricky select', - }, - ); + await sequelize.query(`select 1${fromQuery()};`, { + queryLabel: 'tricky select', + }); expect(logger.calledOnce).to.be.true; expect(logger.args[0][0]).to.be.match( /^tricky select[\n]Executing \((\d*|default)\): select 1/, @@ -181,12 +196,9 @@ describe(getTestDialectTeaser('Sequelize'), () => { logging: logger, }); - await sequelize.query( - `select 1${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''};`, - { - queryLabel: '', - }, - ); + await sequelize.query(`select 1${fromQuery()};`, { + queryLabel: '', + }); expect(logger.calledOnce).to.be.true; expect(logger.args[0][0]).to.be.match(/^Executing \((\d*|default)\): select 1/); }); @@ -198,12 +210,9 @@ describe(getTestDialectTeaser('Sequelize'), () => { benchmark: true, }); - await sequelize.query( - `select 1${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''};`, - { - queryLabel: 'tricky select', - }, - ); + await sequelize.query(`select 1${fromQuery()};`, { + queryLabel: 'tricky select', + }); expect(logger.calledOnce).to.be.true; expect(logger.args[0][0]).to.be.match( /^tricky select[\n]Executed \((\d*|default)\): select 1/, @@ -306,7 +315,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { } await vars.sequelize.query( - `select $1${typeCast} as foo, $2${typeCast} as bar${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `select $1${typeCast} as foo, $2${typeCast} as bar${fromQuery()}`, { bind: ['foo', 'bar'], logging: s => { @@ -518,7 +527,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { it('emits full stacktraces for unique constraint error', async function () { let query; - if (['db2', 'ibmi'].includes(dialectName)) { + if (['db2', 'ibmi', 'oracle'].includes(dialectName)) { query = `INSERT INTO ${qq(this.User.tableName)} ("username", "email_address", ${qq( 'createdAt', )}, ${qq( @@ -542,15 +551,19 @@ describe(getTestDialectTeaser('Sequelize'), () => { error = error_; } - expect(error).to.be.instanceOf(UniqueConstraintError); - expect(error.stack).to.contain('query.test'); + if (dialectName === 'oracle') { + expect(error).to.be.instanceOf(DatabaseError); + } else { + expect(error).to.be.instanceOf(UniqueConstraintError); + expect(error.stack).to.contain('query.test'); + } }); it('emits full stacktraces for constraint validation error', async function () { let error = null; try { let query; - if (['db2', 'ibmi'].includes(dialectName)) { + if (['db2', 'ibmi', 'oracle'].includes(dialectName)) { query = `INSERT INTO ${qq(this.UserVisit.tableName)} ("user_id", "visited_at", ${qq( 'createdAt', )}, ${qq( @@ -569,8 +582,12 @@ describe(getTestDialectTeaser('Sequelize'), () => { error = error_; } - expect(error).to.be.instanceOf(ForeignKeyConstraintError); - expect(error.stack).to.contain('query.test'); + if (dialectName === 'oracle') { + expect(error).to.be.instanceOf(DatabaseError); + } else { + expect(error).to.be.instanceOf(ForeignKeyConstraintError); + expect(error.stack).to.contain('query.test'); + } }); }); } @@ -747,14 +764,14 @@ describe(getTestDialectTeaser('Sequelize'), () => { // dialects in which the following values will be returned as bigints instead of ints const isBigInt = dialectName === 'mysql'; it('dot separated attributes when doing a raw query without nest', async function () { - const sql = `select 1 as ${queryGenerator.quoteIdentifier('foo.bar.baz')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`; + const sql = `select 1 as ${queryGenerator.quoteIdentifier('foo.bar.baz')}${fromQuery()}`; const results = await this.sequelize.query(sql, { raw: true, nest: false }); expect(results[0]).to.deep.equal([{ 'foo.bar.baz': isBigInt ? '1' : 1 }]); }); it('destructs dot separated attributes when doing a raw query using nest', async function () { - const sql = `select 1 as ${queryGenerator.quoteIdentifier('foo.bar.baz')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`; + const sql = `select 1 as ${queryGenerator.quoteIdentifier('foo.bar.baz')}${fromQuery()}`; const result = await this.sequelize.query(sql, { raw: true, nest: true }); expect(result).to.deep.equal([{ foo: { bar: { baz: isBigInt ? '1' : 1 } } }]); @@ -763,7 +780,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { it('replaces token with the passed array', async function () { const expected = [{ foo: isBigInt ? '1' : 1, bar: isBigInt ? '2' : 2 }]; const result = await this.sequelize.query( - `select ? as ${queryGenerator.quoteIdentifier('foo')}, ? as ${queryGenerator.quoteIdentifier('bar')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `select ? as ${queryGenerator.quoteIdentifier('foo')}, ? as ${queryGenerator.quoteIdentifier('bar')}${fromQuery()}`, { type: this.sequelize.QueryTypes.SELECT, replacements: [1, 2] }, ); expect(result).to.deep.equal(expected); @@ -774,7 +791,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { await expect( this.sequelize .query( - `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}${fromQuery()}`, { raw: true, replacements: { one: 1, two: 2 } }, ) .then(obj => obj[0]), @@ -786,7 +803,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { await expect( this.sequelize .query( - `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}, '00:00' as ${queryGenerator.quoteIdentifier('baz')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}, '00:00' as ${queryGenerator.quoteIdentifier('baz')}${fromQuery()}`, { raw: true, replacements: { one: 1, two: 2 } }, ) .then(obj => obj[0]), @@ -800,7 +817,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { await expect( this.sequelize .query( - `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}, :one as ${queryGenerator.quoteIdentifier('baz')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}, :one as ${queryGenerator.quoteIdentifier('baz')}${fromQuery()}`, { raw: true, replacements: { one: 1, two: 2 } }, ) .then(obj => obj[0]), @@ -812,7 +829,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { await expect( this.sequelize .query( - `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}${fromQuery()}`, { raw: true, replacements: { one: 1, two: null } }, ) .then(obj => obj[0]), @@ -828,7 +845,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { const typeCast = ['postgres', 'db2'].includes(dialectName) ? '::int' : ''; let logSql; const result = await this.sequelize.query( - `select $1${typeCast} as ${queryGenerator.quoteIdentifier('foo')}, $2${typeCast} as ${queryGenerator.quoteIdentifier('bar')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `select $1${typeCast} as ${queryGenerator.quoteIdentifier('foo')}, $2${typeCast} as ${queryGenerator.quoteIdentifier('bar')}${fromQuery()}`, { type: this.sequelize.QueryTypes.SELECT, bind: [1, 2], @@ -849,7 +866,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { const typeCast = ['postgres', 'db2'].includes(dialectName) ? '::int' : ''; let logSql; const result = await this.sequelize.query( - `select $one${typeCast} as ${queryGenerator.quoteIdentifier('foo')}, $two${typeCast} as ${queryGenerator.quoteIdentifier('bar')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `select $one${typeCast} as ${queryGenerator.quoteIdentifier('foo')}, $two${typeCast} as ${queryGenerator.quoteIdentifier('bar')}${fromQuery()}`, { raw: true, bind: { one: 1, two: 2 }, @@ -868,12 +885,12 @@ describe(getTestDialectTeaser('Sequelize'), () => { } }); - if (dialectName !== 'db2') { + if (!['db2', 'oracle'].includes(dialectName)) { it('binds named parameters with the passed object using the same key twice', async function () { const typeCast = dialectName === 'postgres' ? '::int' : ''; let logSql; const result = await this.sequelize.query( - `select $one${typeCast} as foo, $two${typeCast} as bar, $one${typeCast} as baz${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `select $one${typeCast} as foo, $two${typeCast} as bar, $one${typeCast} as baz${fromQuery()}`, { raw: true, bind: { one: 1, two: 2 }, @@ -899,10 +916,10 @@ describe(getTestDialectTeaser('Sequelize'), () => { it('binds named parameters with the passed object having a null property', async function () { const typeCast = ['postgres', 'db2'].includes(dialectName) ? '::int' : ''; const result = await this.sequelize.query( - `select $one${typeCast} as foo, $two${typeCast} as bar${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `select $one${typeCast} as foo, $two${typeCast} as bar${fromQuery()}`, { raw: true, bind: { one: 1, two: null } }, ); - const expected = ['db2', 'ibmi'].includes(dialectName) + const expected = ['db2', 'ibmi', 'oracle'].includes(dialectName) ? [{ FOO: 1, BAR: null }] : [{ foo: 1, bar: null }]; expect(result[0]).to.deep.equal(expected); @@ -913,7 +930,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { const typeCast = ['postgres', 'db2'].includes(dialectName) ? '::int' : ''; let logSql; const result = await this.sequelize.query( - `select $1${typeCast} as foo, '$$ / $$1' as bar${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `select $1${typeCast} as foo, '$$ / $$1' as bar${fromQuery()}`, { raw: true, bind: [1], @@ -922,7 +939,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { }, }, ); - const expected = ['db2', 'ibmi'].includes(dialectName) + const expected = ['db2', 'ibmi', 'oracle'].includes(dialectName) ? [{ FOO: 1, BAR: '$$ / $$1' }] : [{ foo: 1, bar: '$$ / $$1' }]; expect(result[0]).to.deep.equal(expected); @@ -935,10 +952,10 @@ describe(getTestDialectTeaser('Sequelize'), () => { it('does not transform $$ in strings (named)', async function () { const typeCast = ['postgres', 'db2'].includes(dialectName) ? '::int' : ''; const result = await this.sequelize.query( - `select $one${typeCast} as foo, '$$ / $$one' as bar${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `select $one${typeCast} as foo, '$$ / $$one' as bar${fromQuery()}`, { raw: true, bind: { one: 1 } }, ); - const expected = ['db2', 'ibmi'].includes(dialectName) + const expected = ['db2', 'ibmi', 'oracle'].includes(dialectName) ? [{ FOO: 1, BAR: '$$ / $$one' }] : [{ foo: 1, bar: '$$ / $$one' }]; expect(result[0]).to.deep.equal(expected); @@ -947,23 +964,24 @@ describe(getTestDialectTeaser('Sequelize'), () => { it(`does not treat a $ as a bind param if it's in the middle of an identifier`, async function () { const typeCast = ['postgres', 'db2'].includes(dialectName) ? '::int' : ''; const result = await this.sequelize.query( - `select $one${typeCast} as foo$bar${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + `select $one${typeCast} as foo$bar${fromQuery()}`, { raw: true, bind: { one: 1 } }, ); - const expected = ['db2', 'ibmi'].includes(dialectName) + const expected = ['db2', 'ibmi', 'oracle'].includes(dialectName) ? [{ FOO$BAR: 1 }] : [{ foo$bar: 1 }]; expect(result[0]).to.deep.equal(expected); }); } - if (['postgres', 'sqlite3', 'mssql'].includes(dialectName)) { + if (['postgres', 'sqlite3', 'mssql', 'oracle'].includes(dialectName)) { it('does not improperly escape arrays of strings bound to named parameters', async function () { - const result = await this.sequelize.query('select :stringArray as foo', { + const result = await this.sequelize.query(`select :stringArray as foo${fromQuery()}`, { raw: true, replacements: { stringArray: sql.list(['"string"']) }, }); - expect(result[0]).to.deep.equal([{ foo: '"string"' }]); + const expectedData = dialectName !== 'oracle' ? { foo: '"string"' } : { FOO: '"string"' }; + expect(result[0]).to.deep.equal([expectedData]); }); } @@ -971,11 +989,11 @@ describe(getTestDialectTeaser('Sequelize'), () => { let datetime = dialectName === 'sqlite3' ? "date('now')" : 'NOW()'; if (dialectName === 'mssql') { datetime = 'GETDATE()'; + } else if (dialectName === 'oracle') { + datetime = 'SYSDATE'; } - const [result] = await this.sequelize.query( - `SELECT ${datetime} AS t${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, - ); + const [result] = await this.sequelize.query(`SELECT ${datetime} AS t${fromQuery()}`); expect(dayjs(result[0].t).isValid()).to.be.true; }); diff --git a/packages/core/test/integration/sequelize/transaction.test.ts b/packages/core/test/integration/sequelize/transaction.test.ts index e1e52400851c..74e10c66c60a 100644 --- a/packages/core/test/integration/sequelize/transaction.test.ts +++ b/packages/core/test/integration/sequelize/transaction.test.ts @@ -340,7 +340,7 @@ describe(getTestDialectTeaser('Sequelize#transaction'), () => { } // These dialects do not allow dirty reads with isolation level "READ UNCOMMITTED". - if (!['postgres', 'sqlite3'].includes(dialectName)) { + if (!['postgres', 'sqlite3', 'oracle'].includes(dialectName)) { it('should allow dirty read with isolation level "READ UNCOMMITTED"', async () => { const { User, transactionSequelize } = vars; const t1 = await transactionSequelize.startUnmanagedTransaction({ @@ -427,7 +427,7 @@ describe(getTestDialectTeaser('Sequelize#transaction'), () => { } // These dialects do not allow phantom reads with isolation level "REPEATABLE READ" as they use snapshot rather than locking. - if (['mariadb', 'mysql', 'postgres'].includes(dialectName)) { + if (['mariadb', 'mysql', 'postgres', 'oracle'].includes(dialectName)) { it('should not read newly committed rows when using the REPEATABLE READ isolation level', async () => { const { User, transactionSequelize } = vars; @@ -479,7 +479,7 @@ describe(getTestDialectTeaser('Sequelize#transaction'), () => { } // PostgreSQL is excluded because it detects Serialization Failure on commit instead of acquiring locks on the read rows - if (!['postgres'].includes(dialectName)) { + if (!['postgres', 'oracle'].includes(dialectName)) { it('should block updates after reading a row using SERIALIZABLE', async () => { const { User, transactionSequelize } = vars; const transactionSpy = sinon.spy(); @@ -591,6 +591,9 @@ describe(getTestDialectTeaser('Sequelize#transaction'), () => { case 'mssql': query = "WAITFOR DELAY '00:00:02';"; break; + case 'oracle': + query = 'BEGIN DBMS_SESSION.sleep(2); END;'; + break; default: query = 'select sleep(2);'; break; diff --git a/packages/core/test/integration/transaction.test.js b/packages/core/test/integration/transaction.test.js index 625ab8ca541b..8c027e4ba3ae 100644 --- a/packages/core/test/integration/transaction.test.js +++ b/packages/core/test/integration/transaction.test.js @@ -20,6 +20,14 @@ const current = Support.sequelize; const delay = require('delay'); const pSettle = require('p-settle'); +const fromQuery = () => { + if (dialect === 'oracle') { + return ' FROM DUAL'; + } + + return ''; +}; + describe(Support.getTestDialectTeaser('Transaction'), () => { if (!current.dialect.supports.transactions) { return; @@ -108,7 +116,10 @@ describe(Support.getTestDialectTeaser('Transaction'), () => { transaction.afterRollback(afterRollback); transaction.afterTransaction(afterTransaction); - return this.sequelize.query('SELECT 1+1', { transaction, type: QueryTypes.SELECT }); + return this.sequelize.query(`SELECT 1+1${fromQuery()}`, { + transaction, + type: QueryTypes.SELECT, + }); }); expect(afterCommit).to.have.been.calledOnce; @@ -260,31 +271,31 @@ describe(Support.getTestDialectTeaser('Transaction'), () => { it('does not allow queries after commit', async function () { const t = await this.sequelize.startUnmanagedTransaction(); - await this.sequelize.query('SELECT 1+1', { transaction: t, raw: true }); + await this.sequelize.query(`SELECT 1+1${fromQuery()}`, { transaction: t, raw: true }); await t.commit(); - await expect(this.sequelize.query('SELECT 1+1', { transaction: t, raw: true })) + await expect(this.sequelize.query(`SELECT 1+1${fromQuery()}`, { transaction: t, raw: true })) .to.be.eventually.rejectedWith( Error, /commit has been called on this transaction\([^)]+\), you can no longer use it\. \(The rejected query is attached as the 'sql' property of this error\)/, ) .and.have.deep.property('sql') - .that.equal('SELECT 1+1'); + .that.equal(`SELECT 1+1${fromQuery()}`); }); it('does not allow queries immediately after commit call', async function () { await expect( (async () => { const t = await this.sequelize.startUnmanagedTransaction(); - await this.sequelize.query('SELECT 1+1', { transaction: t, raw: true }); + await this.sequelize.query(`SELECT 1+1${fromQuery()}`, { transaction: t, raw: true }); await Promise.all([ expect(t.commit()).to.eventually.be.fulfilled, - expect(this.sequelize.query('SELECT 1+1', { transaction: t, raw: true })) + expect(this.sequelize.query(`SELECT 1+1${fromQuery()}`, { transaction: t, raw: true })) .to.be.eventually.rejectedWith( Error, /commit has been called on this transaction\([^)]+\), you can no longer use it\. \(The rejected query is attached as the 'sql' property of this error\)/, ) .and.have.deep.property('sql') - .that.equal('SELECT 1+1'), + .that.equal(`SELECT 1+1${fromQuery()}`), ]); })(), ).to.be.eventually.fulfilled; @@ -294,10 +305,13 @@ describe(Support.getTestDialectTeaser('Transaction'), () => { await expect( (async () => { const t = await this.sequelize.startUnmanagedTransaction(); - await this.sequelize.query('SELECT 1+1', { transaction: t, raw: true }); + await this.sequelize.query(`SELECT 1+1${fromQuery()}`, { transaction: t, raw: true }); await t.rollback(); - return await this.sequelize.query('SELECT 1+1', { transaction: t, raw: true }); + return await this.sequelize.query(`SELECT 1+1${fromQuery()}`, { + transaction: t, + raw: true, + }); })(), ).to.eventually.be.rejected; }); @@ -319,13 +333,13 @@ describe(Support.getTestDialectTeaser('Transaction'), () => { this.sequelize.startUnmanagedTransaction().then(async t => { await Promise.all([ expect(t.rollback()).to.eventually.be.fulfilled, - expect(this.sequelize.query('SELECT 1+1', { transaction: t, raw: true })) + expect(this.sequelize.query(`SELECT 1+1${fromQuery()}`, { transaction: t, raw: true })) .to.be.eventually.rejectedWith( Error, /rollback has been called on this transaction\([^)]+\), you can no longer use it\. \(The rejected query is attached as the 'sql' property of this error\)/, ) .and.have.deep.property('sql') - .that.equal('SELECT 1+1'), + .that.equal(`SELECT 1+1${fromQuery()}`), ]); }), ).to.eventually.be.fulfilled; diff --git a/packages/core/test/integration/utils.test.ts b/packages/core/test/integration/utils.test.ts index 095d5505614b..02637e78371c 100644 --- a/packages/core/test/integration/utils.test.ts +++ b/packages/core/test/integration/utils.test.ts @@ -35,7 +35,7 @@ describe(getTestDialectTeaser('fn()'), () => { // some dialects return the result of arithmetic functions (SUM, COUNT) as integer & floats, others as bigints & decimals. const arithmeticAsNumber = dialectName === 'sqlite3' || dialectName === 'db2'; - if (dialectName !== 'mssql' && dialectName !== 'ibmi') { + if (!['mssql', 'ibmi', 'oracle'].includes(dialectName)) { it('accepts condition object (with cast)', async () => { const type = dialectName === 'mysql' ? 'unsigned' : 'int'; @@ -82,7 +82,7 @@ describe(getTestDialectTeaser('fn()'), () => { }); } - if (dialectName !== 'mssql' && dialectName !== 'postgres' && dialectName !== 'ibmi') { + if (!['mssql', 'postgres', 'ibmi', 'oracle'].includes(dialectName)) { it('accepts condition object (auto casting)', async () => { const [airplane] = await vars.Airplane.findAll({ attributes: [ diff --git a/packages/core/test/unit/configuration.test.ts b/packages/core/test/unit/configuration.test.ts index 5aae50908c46..521961190714 100644 --- a/packages/core/test/unit/configuration.test.ts +++ b/packages/core/test/unit/configuration.test.ts @@ -28,7 +28,7 @@ describe('Sequelize constructor', () => { new Sequelize({ dialect: 'some-fancy-dialect' }); }).to.throw( Error, - 'The dialect some-fancy-dialect is not natively supported. Native dialects: mariadb, mssql, mysql, postgres, sqlite3, ibmi, db2 and snowflake.', + 'The dialect some-fancy-dialect is not natively supported. Native dialects: mariadb, mssql, mysql, postgres, sqlite3, ibmi, db2, oracle and snowflake.', ); }); diff --git a/packages/core/test/unit/data-types/binary-types.test.ts b/packages/core/test/unit/data-types/binary-types.test.ts index 1479c0bba120..c91f1611d9bb 100644 --- a/packages/core/test/unit/data-types/binary-types.test.ts +++ b/packages/core/test/unit/data-types/binary-types.test.ts @@ -17,6 +17,7 @@ describe('DataTypes.BLOB', () => { db2: 'BLOB(255)', postgres: 'BYTEA', sqlite3: 'BLOB', + oracle: 'BLOB', }); testDataTypeSql('BLOB("medium")', DataTypes.BLOB('medium'), { @@ -26,6 +27,7 @@ describe('DataTypes.BLOB', () => { db2: 'BLOB(16M)', postgres: 'BYTEA', sqlite3: 'BLOB', + oracle: 'BLOB', }); testDataTypeSql('BLOB({ length: "medium" })', DataTypes.BLOB({ length: 'medium' }), { @@ -35,6 +37,7 @@ describe('DataTypes.BLOB', () => { db2: 'BLOB(16M)', postgres: 'BYTEA', sqlite3: 'BLOB', + oracle: 'BLOB', }); testDataTypeSql('BLOB("long")', DataTypes.BLOB('long'), { @@ -44,6 +47,7 @@ describe('DataTypes.BLOB', () => { db2: 'BLOB(2G)', postgres: 'BYTEA', sqlite3: 'BLOB', + oracle: 'BLOB', }); describe('validate', () => { diff --git a/packages/core/test/unit/data-types/decimal-numbers.test.ts b/packages/core/test/unit/data-types/decimal-numbers.test.ts index 5396b37d5267..99e371dac74f 100644 --- a/packages/core/test/unit/data-types/decimal-numbers.test.ts +++ b/packages/core/test/unit/data-types/decimal-numbers.test.ts @@ -16,21 +16,25 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat testDataTypeSql('REAL', DataTypes.REAL, { default: 'REAL', + oracle: 'BINARY_DOUBLE', }); testDataTypeSql('REAL.UNSIGNED', DataTypes.REAL.UNSIGNED, { default: 'REAL UNSIGNED', 'sqlite3 snowflake ibmi db2 mssql postgres': 'REAL', + oracle: 'BINARY_DOUBLE', }); testDataTypeSql('REAL(11, 12)', DataTypes.REAL(11, 12), { default: 'REAL(11, 12)', 'sqlite3 snowflake ibmi db2 mssql postgres': 'REAL', + oracle: 'BINARY_DOUBLE', }); testDataTypeSql('REAL(11, 12).UNSIGNED', DataTypes.REAL(11, 12).UNSIGNED, { default: 'REAL(11, 12) UNSIGNED', 'sqlite3 snowflake ibmi db2 mssql postgres': 'REAL', + oracle: 'BINARY_DOUBLE', }); testDataTypeSql( @@ -39,6 +43,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat { default: 'REAL(11, 12) UNSIGNED', 'sqlite3 snowflake ibmi db2 mssql postgres': 'REAL', + oracle: 'BINARY_DOUBLE', }, ); @@ -68,6 +73,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'DOUBLE', sqlite3: 'REAL', snowflake: 'FLOAT', + oracle: 'BINARY_DOUBLE', }); testDataTypeSql('DOUBLE.UNSIGNED', DataTypes.DOUBLE.UNSIGNED, { @@ -76,6 +82,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'DOUBLE', 'postgres mssql': 'DOUBLE PRECISION', snowflake: 'FLOAT', + oracle: 'BINARY_DOUBLE', }); testDataTypeSql('DOUBLE(11, 12)', DataTypes.DOUBLE(11, 12), { @@ -84,6 +91,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'DOUBLE', 'postgres mssql': 'DOUBLE PRECISION', snowflake: 'FLOAT', + oracle: 'BINARY_DOUBLE', }); testDataTypeSql('DOUBLE(11, 12).UNSIGNED', DataTypes.DOUBLE(11, 12).UNSIGNED, { @@ -92,6 +100,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'DOUBLE', 'postgres mssql': 'DOUBLE PRECISION', snowflake: 'FLOAT', + oracle: 'BINARY_DOUBLE', }); testDataTypeSql('DOUBLE(11, 12).UNSIGNED.ZEROFILL', DataTypes.DOUBLE(11, 12).UNSIGNED.ZEROFILL, { @@ -134,24 +143,28 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mysql mariadb snowflake': 'FLOAT', // REAL in sqlite is double-precision (no single-precision support), but single-precision in all others 'postgres mssql sqlite3 db2 ibmi': 'REAL', + oracle: 'BINARY_FLOAT', }); testDataTypeSql('FLOAT.UNSIGNED', DataTypes.FLOAT.UNSIGNED, { 'mysql mariadb': 'FLOAT UNSIGNED', snowflake: 'FLOAT', 'postgres mssql sqlite3 db2 ibmi': 'REAL', + oracle: 'BINARY_FLOAT', }); testDataTypeSql('FLOAT(11, 12)', DataTypes.FLOAT(11, 12), { 'mysql mariadb': 'FLOAT(11, 12)', snowflake: 'FLOAT', 'postgres mssql sqlite3 db2 ibmi': 'REAL', + oracle: 'BINARY_FLOAT', }); testDataTypeSql('FLOAT(11, 12).UNSIGNED', DataTypes.FLOAT(11, 12).UNSIGNED, { 'mysql mariadb': 'FLOAT(11, 12) UNSIGNED', snowflake: 'FLOAT', 'postgres mssql sqlite3 db2 ibmi': 'REAL', + oracle: 'BINARY_FLOAT', }); testDataTypeSql( @@ -161,6 +174,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mysql mariadb': 'FLOAT(11, 12) UNSIGNED', snowflake: 'FLOAT', 'postgres mssql sqlite3 db2 ibmi': 'REAL', + oracle: 'BINARY_FLOAT', }, ); @@ -225,11 +239,13 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat ), sqlite3: unsupportedError, postgres: 'DECIMAL', + oracle: 'NUMBER', }); testDataTypeSql('DECIMAL(10, 2)', DataTypes.DECIMAL(10, 2), { default: 'DECIMAL(10, 2)', sqlite3: unsupportedError, + oracle: 'NUMBER(10, 2)', }); testDataTypeSql( @@ -238,6 +254,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat { default: 'DECIMAL(10, 2)', sqlite3: unsupportedError, + oracle: 'NUMBER(10, 2)', }, ); @@ -245,6 +262,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: 'DECIMAL(10, 2)', 'mysql mariadb': 'DECIMAL(10, 2) UNSIGNED', sqlite3: unsupportedError, + oracle: 'NUMBER(10, 2)', }); testDataTypeSql('DECIMAL(10, 2).UNSIGNED.ZEROFILL', DataTypes.DECIMAL(10, 2).UNSIGNED.ZEROFILL, { @@ -260,6 +278,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: 'DECIMAL(10, 2)', 'mysql mariadb': 'DECIMAL(10, 2) UNSIGNED', sqlite3: unsupportedError, + oracle: 'NUMBER(10, 2)', }, ); @@ -283,7 +302,10 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat it('should throw an error if `value` is invalid', () => { const type: DataTypeInstance = DataTypes.DECIMAL(10, 2).toDialectDataType(dialect); - const typeName = supportsDecimal.constrained ? 'decimal(10, 2)' : 'decimal'; + let typeName = supportsDecimal.constrained ? 'decimal(10, 2)' : 'decimal'; + if (dialect.name === 'oracle') { + typeName = 'number(10, 2)'; + } expect(() => { type.validate('foobar'); diff --git a/packages/core/test/unit/data-types/integers.test.ts b/packages/core/test/unit/data-types/integers.test.ts index a7663e4dd386..7e9ad1857e75 100644 --- a/packages/core/test/unit/data-types/integers.test.ts +++ b/packages/core/test/unit/data-types/integers.test.ts @@ -21,6 +21,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mssql postgres db2 ibmi': 'SMALLINT', 'mysql mariadb': 'TINYINT', 'sqlite3 snowflake': 'INTEGER', + oracle: 'NUMBER(3)', }, }, { @@ -31,6 +32,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mssql postgres db2 ibmi': 'SMALLINT', 'mysql mariadb': 'TINYINT(2)', 'sqlite3 snowflake': 'INTEGER', + oracle: 'NUMBER(3)', }, }, { @@ -40,6 +42,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mssql postgres db2 ibmi': 'SMALLINT', 'mysql mariadb': 'TINYINT(2)', 'sqlite3 snowflake': 'INTEGER', + oracle: 'NUMBER(3)', }, }, { @@ -53,6 +56,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'sqlite3 snowflake': 'INTEGER', // TINYINT is unsigned in mssql mssql: 'TINYINT', + oracle: 'NUMBER(3)', }, }, { @@ -63,6 +67,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mysql mariadb': 'TINYINT(2) UNSIGNED', 'sqlite3 snowflake': 'INTEGER', mssql: 'TINYINT', + oracle: 'NUMBER(3)', }, }, { @@ -155,6 +160,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat expect: { default: 'SMALLINT', 'sqlite3 snowflake': 'INTEGER', + oracle: 'SMALLINT', }, }, { @@ -164,6 +170,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: 'SMALLINT', 'sqlite3 snowflake': 'INTEGER', 'mysql mariadb': 'SMALLINT(4)', + oracle: 'NUMBER(4,0)', }, }, { @@ -173,6 +180,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: 'SMALLINT', 'sqlite3 snowflake': 'INTEGER', 'mysql mariadb': 'SMALLINT(4)', + oracle: 'NUMBER(4,0)', }, }, { @@ -184,6 +192,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'sqlite3 snowflake': 'INTEGER', 'postgres db2 ibmi': 'INTEGER', mssql: 'INT', + oracle: 'SMALLINT', }, }, { @@ -194,6 +203,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'sqlite3 snowflake': 'INTEGER', 'postgres db2 ibmi': 'INTEGER', mssql: 'INT', + oracle: 'NUMBER(4,0)', }, }, { @@ -287,6 +297,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mariadb mysql': 'MEDIUMINT', // falls back to larger type + CHECK constraint 'db2 ibmi mssql postgres snowflake sqlite3': 'INTEGER', + oracle: 'NUMBER(8)', }, }, { @@ -295,6 +306,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat expect: { 'mariadb mysql': 'MEDIUMINT(2)', 'db2 ibmi mssql postgres snowflake sqlite3': 'INTEGER', + oracle: 'NUMBER(8)', }, }, { @@ -303,6 +315,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat expect: { 'mariadb mysql': 'MEDIUMINT(2)', 'db2 ibmi mssql postgres snowflake sqlite3': 'INTEGER', + oracle: 'NUMBER(8)', }, }, { @@ -311,6 +324,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat expect: { 'mariadb mysql': 'MEDIUMINT UNSIGNED', 'db2 ibmi mssql postgres snowflake sqlite3': 'INTEGER', + oracle: 'NUMBER(8)', }, }, { @@ -319,6 +333,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat expect: { 'mariadb mysql': 'MEDIUMINT(2) UNSIGNED', 'db2 ibmi mssql postgres snowflake sqlite3': 'INTEGER', + oracle: 'NUMBER(8)', }, }, { @@ -410,7 +425,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat testDataTypeSql('INTEGER.UNSIGNED', DataTypes.INTEGER.UNSIGNED, { // sqlite & snowflake are both 64 bits integers (actually snowflake accepts up to 99999999999999999999999999999999999999) - 'sqlite3 snowflake': 'INTEGER', + 'sqlite3 oracle snowflake': 'INTEGER', 'mysql mariadb': 'INTEGER UNSIGNED', 'ibmi postgres db2 mssql': 'BIGINT', }); @@ -423,17 +438,20 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat testDataTypeSql('INTEGER(11)', DataTypes.INTEGER(11), { default: 'INTEGER', 'mysql mariadb': 'INTEGER(11)', + oracle: 'NUMBER(11,0)', }); testDataTypeSql('INTEGER({ length: 11 })', DataTypes.INTEGER({ length: 11 }), { default: 'INTEGER', 'mysql mariadb': 'INTEGER(11)', + oracle: 'NUMBER(11,0)', }); testDataTypeSql('INTEGER(11).UNSIGNED', DataTypes.INTEGER(11).UNSIGNED, { 'mysql mariadb': 'INTEGER(11) UNSIGNED', 'sqlite3 snowflake': 'INTEGER', 'ibmi postgres db2 mssql': 'BIGINT', + oracle: 'NUMBER(11,0)', }); testDataTypeSql('INTEGER(11).UNSIGNED.ZEROFILL', DataTypes.INTEGER(11).UNSIGNED.ZEROFILL, { @@ -492,6 +510,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat testDataTypeSql('BIGINT', DataTypes.BIGINT, { default: 'BIGINT', 'sqlite3 snowflake': 'INTEGER', + oracle: 'NUMBER(19, 0)', }); testDataTypeSql('BIGINT.UNSIGNED', DataTypes.BIGINT.UNSIGNED, { @@ -499,6 +518,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mysql mariadb': 'BIGINT UNSIGNED', // INTEGER in snowflake goes up to 99999999999999999999999999999999999999, which is enough to store an unsigned 64-bit integer. snowflake: 'INTEGER', + oracle: 'NUMBER(19, 0)', }); testDataTypeSql('BIGINT.UNSIGNED.ZEROFILL', DataTypes.BIGINT.UNSIGNED.ZEROFILL, { @@ -510,12 +530,14 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: 'BIGINT', 'sqlite3 snowflake': 'INTEGER', 'mysql mariadb': 'BIGINT(11)', + oracle: 'NUMBER(19, 0)', }); testDataTypeSql('BIGINT({ length: 11 })', DataTypes.BIGINT({ length: 11 }), { default: 'BIGINT', 'sqlite3 snowflake': 'INTEGER', 'mysql mariadb': 'BIGINT(11)', + oracle: 'NUMBER(19, 0)', }); testDataTypeSql('BIGINT(11).UNSIGNED', DataTypes.BIGINT(11).UNSIGNED, { @@ -523,6 +545,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: unsignedUnsupportedError, 'mysql mariadb': 'BIGINT(11) UNSIGNED', snowflake: 'INTEGER', + oracle: 'NUMBER(19, 0)', }); testDataTypeSql('BIGINT(11).UNSIGNED.ZEROFILL', DataTypes.BIGINT(11).UNSIGNED.ZEROFILL, { diff --git a/packages/core/test/unit/data-types/misc-data-types.test.ts b/packages/core/test/unit/data-types/misc-data-types.test.ts index 3ea3c343895b..5c1335225889 100644 --- a/packages/core/test/unit/data-types/misc-data-types.test.ts +++ b/packages/core/test/unit/data-types/misc-data-types.test.ts @@ -17,6 +17,7 @@ describe('DataTypes.BOOLEAN', () => { mariadb: 'TINYINT(1)', mysql: 'TINYINT(1)', sqlite3: 'INTEGER', + oracle: 'CHAR(1)', }); describe('validate', () => { @@ -57,6 +58,7 @@ describe('DataTypes.ENUM', () => { mssql: `NVARCHAR(255)`, sqlite3: 'TEXT', 'db2 ibmi snowflake': 'VARCHAR(255)', + oracle: 'VARCHAR2(512)', }); }); @@ -188,6 +190,7 @@ describe('DataTypes.JSON', () => { // SQL server supports JSON functions, but it is stored as a string with a ISJSON constraint. mssql: 'NVARCHAR(MAX)', sqlite3: 'TEXT', + oracle: 'BLOB', }); describe('escape', () => { @@ -200,6 +203,7 @@ describe('DataTypes.JSON', () => { default: `'"string"'`, mysql: `CAST('"string"' AS JSON)`, mssql: `N'"string"'`, + oracle: `'string'`, }); }); diff --git a/packages/core/test/unit/data-types/string-types.test.ts b/packages/core/test/unit/data-types/string-types.test.ts index e4df01fa7f28..5279749b8fe1 100644 --- a/packages/core/test/unit/data-types/string-types.test.ts +++ b/packages/core/test/unit/data-types/string-types.test.ts @@ -17,18 +17,21 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: 'VARCHAR(255)', mssql: 'NVARCHAR(255)', sqlite3: 'TEXT', + oracle: 'NVARCHAR2(255)', }); testDataTypeSql('STRING(1234)', DataTypes.STRING(1234), { default: 'VARCHAR(1234)', mssql: 'NVARCHAR(1234)', sqlite3: 'TEXT', + oracle: 'NVARCHAR2(1234)', }); testDataTypeSql('STRING({ length: 1234 })', DataTypes.STRING({ length: 1234 }), { default: 'VARCHAR(1234)', mssql: 'NVARCHAR(1234)', sqlite3: 'TEXT', + oracle: 'NVARCHAR2(1234)', }); testDataTypeSql('STRING(1234).BINARY', DataTypes.STRING(1234).BINARY, { @@ -36,6 +39,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'VARCHAR(1234) FOR BIT DATA', sqlite3: 'TEXT COLLATE BINARY', 'mssql postgres': binaryCollationUnsupportedError, + oracle: 'RAW(1234)', }); testDataTypeSql('STRING.BINARY', DataTypes.STRING.BINARY, { @@ -43,6 +47,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'VARCHAR(255) FOR BIT DATA', sqlite3: 'TEXT COLLATE BINARY', 'mssql postgres': binaryCollationUnsupportedError, + oracle: 'RAW(255)', }); }); @@ -62,6 +67,7 @@ describe('DataTypes.TEXT', () => { default: 'TEXT', 'ibmi db2': 'CLOB(2147483647)', mssql: 'NVARCHAR(MAX)', // in mssql text is actually representing a non unicode text field + oracle: 'CLOB', }); testDataTypeSql('TEXT("tiny")', DataTypes.TEXT('tiny'), { @@ -69,6 +75,7 @@ describe('DataTypes.TEXT', () => { 'ibmi db2': 'VARCHAR(256)', mssql: 'NVARCHAR(256)', 'mariadb mysql': 'TINYTEXT', + oracle: 'CLOB', }); testDataTypeSql('TEXT({ length: "tiny" })', DataTypes.TEXT({ length: 'tiny' }), { @@ -76,6 +83,7 @@ describe('DataTypes.TEXT', () => { 'ibmi db2': 'VARCHAR(256)', mssql: 'NVARCHAR(256)', 'mariadb mysql': 'TINYTEXT', + oracle: 'CLOB', }); testDataTypeSql('TEXT("medium")', DataTypes.TEXT('medium'), { @@ -83,6 +91,7 @@ describe('DataTypes.TEXT', () => { 'ibmi db2': 'CLOB(16777216)', mssql: 'NVARCHAR(MAX)', 'mariadb mysql': 'MEDIUMTEXT', + oracle: 'CLOB', }); testDataTypeSql('TEXT("long")', DataTypes.TEXT('long'), { @@ -90,6 +99,7 @@ describe('DataTypes.TEXT', () => { 'ibmi db2': 'CLOB(2147483647)', mssql: 'NVARCHAR(MAX)', 'mariadb mysql': 'LONGTEXT', + oracle: 'CLOB', }); }); @@ -166,6 +176,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'CHAR(12) FOR BIT DATA', sqlite3: charNotSupportedError, 'postgres mssql': binaryNotSupportedError, + oracle: 'RAW(12)', }); testDataTypeSql('CHAR.BINARY', DataTypes.CHAR.BINARY, { @@ -173,6 +184,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'CHAR(255) FOR BIT DATA', sqlite3: charNotSupportedError, 'postgres mssql': binaryNotSupportedError, + oracle: 'RAW(255)', }); }); }); diff --git a/packages/core/test/unit/data-types/temporal-types.test.ts b/packages/core/test/unit/data-types/temporal-types.test.ts index e00cd34f144f..f543f49021cd 100644 --- a/packages/core/test/unit/data-types/temporal-types.test.ts +++ b/packages/core/test/unit/data-types/temporal-types.test.ts @@ -17,6 +17,7 @@ describe('DataTypes.DATE', () => { mssql: 'DATETIMEOFFSET', 'mariadb mysql': 'DATETIME', sqlite3: 'TEXT', + oracle: 'TIMESTAMP WITH LOCAL TIME ZONE', }); testDataTypeSql('DATE(0)', DataTypes.DATE(0), { @@ -25,6 +26,7 @@ describe('DataTypes.DATE', () => { 'mariadb mysql': 'DATETIME(0)', 'db2 ibmi snowflake': 'TIMESTAMP(0)', sqlite3: 'TEXT', + oracle: 'TIMESTAMP WITH LOCAL TIME ZONE', }); testDataTypeSql('DATE(6)', DataTypes.DATE(6), { @@ -34,6 +36,7 @@ describe('DataTypes.DATE', () => { mariadb: 'DATETIME(6)', mysql: 'DATETIME(6)', sqlite3: 'TEXT', + oracle: 'TIMESTAMP WITH LOCAL TIME ZONE', }); }); @@ -137,6 +140,8 @@ describe('DataTypes.TIME', () => { db2: new Error(`db2 does not support the TIME(precision) data type. See https://sequelize.org/docs/v7/models/data-types/ for a list of supported data types.`), sqlite3: 'TEXT', + oracle: new Error(`oracle does not support the TIME(precision) data type. +See https://sequelize.org/docs/v7/models/data-types/ for a list of supported data types`), }); }); }); @@ -147,6 +152,7 @@ describe('DataTypes.NOW', () => { default: 'NOW', db2: 'CURRENT TIME', mssql: 'GETDATE()', + oracle: 'SYSDATE', }); }); }); diff --git a/packages/core/test/unit/data-types/uuid.test.ts b/packages/core/test/unit/data-types/uuid.test.ts index fdf416abe350..f306f010b7f6 100644 --- a/packages/core/test/unit/data-types/uuid.test.ts +++ b/packages/core/test/unit/data-types/uuid.test.ts @@ -15,6 +15,7 @@ describe('DataTypes.UUID', () => { 'mariadb mysql': 'CHAR(36) BINARY', snowflake: 'VARCHAR(36)', sqlite3: 'TEXT', + oracle: 'VARCHAR2(36)', }); }); diff --git a/packages/core/test/unit/pool.test.ts b/packages/core/test/unit/pool.test.ts index 99b2584c9796..ea83771180f6 100644 --- a/packages/core/test/unit/pool.test.ts +++ b/packages/core/test/unit/pool.test.ts @@ -132,6 +132,9 @@ describe('sequelize.pool', () => { snowflake: { account: 'replica1', }, + oracle: { + host: 'replica1', + }, }; const replica2Overrides: DialectConnectionConfigs = { @@ -159,6 +162,9 @@ describe('sequelize.pool', () => { snowflake: { account: 'replica2', }, + oracle: { + host: 'replica1', + }, }; const connectionOptions = sequelize.options.replication.write; @@ -230,6 +236,9 @@ describe('sequelize.pool', () => { snowflake: { account: 'write', }, + oracle: { + host: 'write', + }, }; const connectionOptions = sequelize.options.replication.write; diff --git a/packages/core/test/unit/query-generator/add-column-query.test.ts b/packages/core/test/unit/query-generator/add-column-query.test.ts index ece57cdcfe1c..ea980a43a357 100644 --- a/packages/core/test/unit/query-generator/add-column-query.test.ts +++ b/packages/core/test/unit/query-generator/add-column-query.test.ts @@ -31,6 +31,7 @@ describe('QueryGenerator#addColumnQuery', () => { default: `ALTER TABLE [Users] ADD [age] INTEGER;`, mssql: `ALTER TABLE [Users] ADD [age] INTEGER NULL;`, postgres: `ALTER TABLE "Users" ADD COLUMN "age" INTEGER;`, + oracle: `ALTER TABLE "Users" ADD "age" INTEGER NULL;`, }, ); }); diff --git a/packages/core/test/unit/query-generator/add-constraint-query.test.ts b/packages/core/test/unit/query-generator/add-constraint-query.test.ts index 492431e7a0f0..244a088fa168 100644 --- a/packages/core/test/unit/query-generator/add-constraint-query.test.ts +++ b/packages/core/test/unit/query-generator/add-constraint-query.test.ts @@ -561,7 +561,7 @@ describe('QueryGenerator#addConstraintQuery', () => { { default: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_otherId_otherTable_fk] FOREIGN KEY ([otherId]) REFERENCES [otherTable] ([id]) ON UPDATE CASCADE`, sqlite3: notSupportedError, - 'db2 ibmi': onUpdateNotSupportedError, + 'db2 ibmi oracle': onUpdateNotSupportedError, }, ); }); diff --git a/packages/core/test/unit/query-generator/bulk-delete-query.test.ts b/packages/core/test/unit/query-generator/bulk-delete-query.test.ts index ca2003457840..5af4db934f15 100644 --- a/packages/core/test/unit/query-generator/bulk-delete-query.test.ts +++ b/packages/core/test/unit/query-generator/bulk-delete-query.test.ts @@ -25,6 +25,7 @@ describe('QueryGenerator#bulkDeleteQuery', () => { "DELETE FROM `myTable` WHERE rowid IN (SELECT rowid FROM `myTable` WHERE `name` = 'barry' LIMIT 10)", 'db2 ibmi': `DELETE FROM "myTable" WHERE "name" = 'barry' FETCH NEXT 10 ROWS ONLY`, 'mssql postgres snowflake': limitNotSupportedError, + oracle: limitNotSupportedError, }, ); }); @@ -39,6 +40,7 @@ describe('QueryGenerator#bulkDeleteQuery', () => { "DELETE FROM `MyModels` WHERE rowid IN (SELECT rowid FROM `MyModels` WHERE `name` = 'barry' LIMIT 10)", 'db2 ibmi': `DELETE FROM "MyModels" WHERE "name" = 'barry' FETCH NEXT 10 ROWS ONLY`, 'postgres snowflake': `DELETE FROM "MyModels" WHERE "id" IN (SELECT "id" FROM "MyModels" WHERE "name" = 'barry' ORDER BY "id" LIMIT 10)`, + oracle: `DELETE FROM "MyModels" WHERE rowid IN (SELECT rowid FROM "MyModels" WHERE rownum <= 10 AND "name" = 'barry')`, }); }); @@ -55,6 +57,7 @@ describe('QueryGenerator#bulkDeleteQuery', () => { "DELETE FROM `MyModels` WHERE rowid IN (SELECT rowid FROM `MyModels` WHERE `name` = 'barry' LIMIT 10)", 'db2 ibmi': `DELETE FROM "MyModels" WHERE "name" = 'barry' FETCH NEXT 10 ROWS ONLY`, 'postgres snowflake': `DELETE FROM "MyModels" WHERE "id" IN (SELECT "id" FROM "MyModels" WHERE "name" = 'barry' ORDER BY "id" LIMIT 10)`, + oracle: `DELETE FROM "MyModels" WHERE rowid IN (SELECT rowid FROM "MyModels" WHERE rownum <= 10 AND "name" = 'barry')`, }, ); }); @@ -78,6 +81,7 @@ describe('QueryGenerator#bulkDeleteQuery', () => { sqlite3: `DELETE FROM \`MyModels\` WHERE rowid IN (SELECT rowid FROM \`MyModels\` WHERE name = 'Zoe' LIMIT 1)`, 'db2 ibmi': `DELETE FROM "MyModels" WHERE name = 'Zoe' FETCH NEXT 1 ROWS ONLY`, 'postgres snowflake': `DELETE FROM "MyModels" WHERE "id" IN (SELECT "id" FROM "MyModels" WHERE name = 'Zoe' ORDER BY "id" LIMIT 1)`, + oracle: `DELETE FROM "MyModels" WHERE rowid IN (SELECT rowid FROM "MyModels" WHERE rownum <= :limit AND name = 'Zoe')`, }); }); diff --git a/packages/core/test/unit/query-generator/bulk-insert-query.test.ts b/packages/core/test/unit/query-generator/bulk-insert-query.test.ts index 507e1a52ea11..47034b1da617 100644 --- a/packages/core/test/unit/query-generator/bulk-insert-query.test.ts +++ b/packages/core/test/unit/query-generator/bulk-insert-query.test.ts @@ -1,5 +1,7 @@ import { DataTypes, literal } from '@sequelize/core'; -import { beforeAll2, expectsql, sequelize } from '../../support'; +import { beforeAll2, expectsql, getTestDialect, sequelize } from '../../support'; + +const dialect = getTestDialect(); describe('QueryGenerator#bulkInsertQuery', () => { const queryGenerator = sequelize.queryGenerator; @@ -16,7 +18,8 @@ describe('QueryGenerator#bulkInsertQuery', () => { return { User }; }); - it('parses named replacements in literals', async () => { + // The Oracle dialect doesn't support replacements for bulkInsert + (dialect !== 'oracle' ? it : it.skip)('parses named replacements in literals', async () => { const { User } = vars; const sql = queryGenerator.bulkInsertQuery( diff --git a/packages/core/test/unit/query-generator/commit-transaction-query.test.ts b/packages/core/test/unit/query-generator/commit-transaction-query.test.ts index b707b6c9f9c5..dc12c2ea438d 100644 --- a/packages/core/test/unit/query-generator/commit-transaction-query.test.ts +++ b/packages/core/test/unit/query-generator/commit-transaction-query.test.ts @@ -12,6 +12,7 @@ describe('QueryGenerator#commitTransactionQuery', () => { expectsql(() => queryGenerator.commitTransactionQuery(), { default: 'COMMIT', 'db2 ibmi mssql': notSupportedError, + oracle: 'COMMIT TRANSACTION', }); }); }); diff --git a/packages/core/test/unit/query-generator/create-schema-query.test.ts b/packages/core/test/unit/query-generator/create-schema-query.test.ts index ac624615e5b2..4880e9f3cf01 100644 --- a/packages/core/test/unit/query-generator/create-schema-query.test.ts +++ b/packages/core/test/unit/query-generator/create-schema-query.test.ts @@ -13,6 +13,7 @@ describe('QueryGenerator#createSchemaQuery', () => { expectsql(() => queryGenerator.createSchemaQuery('mySchema'), { default: 'CREATE SCHEMA [mySchema]', sqlite3: notSupportedError, + oracle: `DECLARE USER_FOUND BOOLEAN := FALSE; BEGIN BEGIN EXECUTE IMMEDIATE 'CREATE USER "mySchema" IDENTIFIED BY 12345 DEFAULT TABLESPACE USERS' ; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1920 THEN RAISE; ELSE USER_FOUND := TRUE; END IF; END; IF NOT USER_FOUND THEN EXECUTE IMMEDIATE 'GRANT "CONNECT" TO "mySchema"' ; EXECUTE IMMEDIATE 'GRANT CREATE TABLE TO "mySchema"' ; EXECUTE IMMEDIATE 'GRANT CREATE VIEW TO "mySchema"' ; EXECUTE IMMEDIATE 'GRANT CREATE ANY TRIGGER TO "mySchema"' ; EXECUTE IMMEDIATE 'GRANT CREATE ANY PROCEDURE TO "mySchema"' ; EXECUTE IMMEDIATE 'GRANT CREATE SEQUENCE TO "mySchema"' ; EXECUTE IMMEDIATE 'GRANT CREATE SYNONYM TO "mySchema"' ; EXECUTE IMMEDIATE 'ALTER USER "mySchema" QUOTA UNLIMITED ON USERS' ; END IF; END;`, }); }); @@ -20,9 +21,11 @@ describe('QueryGenerator#createSchemaQuery', () => { expectsql(() => queryGenerator.createSchemaQuery('mySchema', { authorization: 'myUser' }), { default: 'CREATE SCHEMA [mySchema] AUTHORIZATION [myUser]', sqlite3: notSupportedError, - 'mariadb mysql snowflake': buildInvalidOptionReceivedError('createSchemaQuery', dialectName, [ - 'authorization', - ]), + 'mariadb mysql snowflake oracle': buildInvalidOptionReceivedError( + 'createSchemaQuery', + dialectName, + ['authorization'], + ), }); }); @@ -32,7 +35,7 @@ describe('QueryGenerator#createSchemaQuery', () => { { default: 'CREATE SCHEMA [mySchema] AUTHORIZATION CURRENT USER', sqlite3: notSupportedError, - 'mariadb mysql snowflake': buildInvalidOptionReceivedError( + 'mariadb mysql snowflake oracle': buildInvalidOptionReceivedError( 'createSchemaQuery', dialectName, ['authorization'], @@ -68,7 +71,7 @@ describe('QueryGenerator#createSchemaQuery', () => { it('supports the ifNotExists option', () => { expectsql(() => queryGenerator.createSchemaQuery('mySchema', { ifNotExists: true }), { default: 'CREATE SCHEMA IF NOT EXISTS [mySchema]', - 'db2 ibmi mssql': buildInvalidOptionReceivedError('createSchemaQuery', dialectName, [ + 'db2 ibmi mssql oracle': buildInvalidOptionReceivedError('createSchemaQuery', dialectName, [ 'ifNotExists', ]), sqlite3: notSupportedError, @@ -122,6 +125,11 @@ describe('QueryGenerator#createSchemaQuery', () => { 'charset', 'collate', ]), + oracle: buildInvalidOptionReceivedError('createSchemaQuery', dialectName, [ + 'authorization', + 'charset', + 'collate', + ]), sqlite3: notSupportedError, }, ); diff --git a/packages/core/test/unit/query-generator/create-table-query.test.ts b/packages/core/test/unit/query-generator/create-table-query.test.ts index d720a53db4b4..7c1aaa0f885a 100644 --- a/packages/core/test/unit/query-generator/create-table-query.test.ts +++ b/packages/core/test/unit/query-generator/create-table-query.test.ts @@ -17,6 +17,7 @@ describe('QueryGenerator#createTableQuery', () => { 'mariadb mysql': 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] DATE);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -28,6 +29,7 @@ describe('QueryGenerator#createTableQuery', () => { 'mariadb mysql': 'CREATE TABLE IF NOT EXISTS `MyModels` (`myColumn` DATE) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[MyModels]', 'U') IS NULL CREATE TABLE [MyModels] ([myColumn] DATE);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "MyModels" ("myColumn" DATE); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "MyModels" ("myColumn" DATE)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -40,6 +42,7 @@ describe('QueryGenerator#createTableQuery', () => { 'mariadb mysql': 'CREATE TABLE IF NOT EXISTS `MyModels` (`myColumn` DATE) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[MyModels]', 'U') IS NULL CREATE TABLE [MyModels] ([myColumn] DATE);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "MyModels" ("myColumn" DATE); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "MyModels" ("myColumn" DATE)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -56,6 +59,7 @@ describe('QueryGenerator#createTableQuery', () => { mssql: `IF OBJECT_ID(N'[mySchema].[myTable]', 'U') IS NULL CREATE TABLE [mySchema].[myTable] ([myColumn] DATE);`, sqlite3: 'CREATE TABLE IF NOT EXISTS `mySchema.myTable` (`myColumn` DATE);', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "mySchema"."myTable" ("myColumn" DATE); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "mySchema"."myTable" ("myColumn" DATE)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -71,6 +75,7 @@ describe('QueryGenerator#createTableQuery', () => { 'mariadb mysql': 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] DATE);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -86,6 +91,7 @@ describe('QueryGenerator#createTableQuery', () => { mssql: `IF OBJECT_ID(N'[mySchema].[myTable]', 'U') IS NULL CREATE TABLE [mySchema].[myTable] ([myColumn] DATE);`, sqlite3: 'CREATE TABLE IF NOT EXISTS `mySchema.myTable` (`myColumn` DATE);', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "mySchema"."myTable" ("myColumn" DATE); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "mySchema"."myTable" ("myColumn" DATE)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -115,6 +121,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE, `secondColumn` TEXT) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] DATE, [secondColumn] TEXT);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -127,6 +134,7 @@ describe('QueryGenerator#createTableQuery', () => { mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] DATE, PRIMARY KEY ([myColumn]));`, sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE PRIMARY KEY);', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, PRIMARY KEY ("myColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE,PRIMARY KEY ("myColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -145,6 +153,7 @@ describe('QueryGenerator#createTableQuery', () => { sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE NOT NULL, `secondColumn` TEXT NOT NULL, PRIMARY KEY (`myColumn`, `secondColumn`));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT, PRIMARY KEY ("myColumn", "secondColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT,PRIMARY KEY ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -161,6 +170,7 @@ describe('QueryGenerator#createTableQuery', () => { 'snowflake db2': 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE REFERENCES "Bar" ("id")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE,FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -181,6 +191,7 @@ describe('QueryGenerator#createTableQuery', () => { 'snowflake db2': 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, PRIMARY KEY ("myColumn"), FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE REFERENCES "Bar" ("id"), PRIMARY KEY ("myColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE,PRIMARY KEY ("myColumn"),FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -205,6 +216,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id") COMMENT Foo);', db2: `CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id")); -- 'Foo', TableName = "myTable", ColumnName = "myColumn";`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE REFERENCES "Bar" ("id") COMMENT Foo); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE,FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id") COMMENT Foo)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -216,6 +228,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE NOT NULL) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] DATE NOT NULL);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE NOT NULL); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE NOT NULL)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -236,6 +249,7 @@ describe('QueryGenerator#createTableQuery', () => { sqlite3: 'CREATE TABLE IF NOT EXISTS `mySchema.myTable` (`myColumn` DATE COMMENT Foo);', db2: `CREATE TABLE IF NOT EXISTS "mySchema"."myTable" ("myColumn" DATE); -- 'Foo', TableName = "mySchema"."myTable", ColumnName = "myColumn";`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "mySchema"."myTable" ("myColumn" DATE COMMENT Foo); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "mySchema"."myTable" ("myColumn" DATE COMMENT Foo)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -259,6 +273,7 @@ describe('QueryGenerator#createTableQuery', () => { @level1type = N'Table', @level1name = [myTable], @level2type = N'Column', @level2name = [secondColumn];`, db2: `CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" DATE); -- 'Foo', TableName = "myTable", ColumnName = "myColumn"; -- 'Foo Bar', TableName = "myTable", ColumnName = "secondColumn";`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE COMMENT Foo, "secondColumn" DATE COMMENT Foo Bar); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE COMMENT Foo, "secondColumn" DATE COMMENT Foo Bar)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -277,6 +292,7 @@ describe('QueryGenerator#createTableQuery', () => { @level1type = N'Table', @level1name = [myTable], @level2type = N'Column', @level2name = [myColumn];`, db2: `CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE COMMENT Foo); -- 'Bar', TableName = "myTable", ColumnName = "myColumn";`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE COMMENT Foo COMMENT Bar); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE COMMENT Foo COMMENT Bar)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -296,6 +312,7 @@ describe('QueryGenerator#createTableQuery', () => { sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE COMMENT Foo PRIMARY KEY);', db2: `CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE); -- 'Foo PRIMARY KEY', TableName = "myTable", ColumnName = "myColumn";`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE COMMENT Foo, PRIMARY KEY ("myColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE COMMENT Foo,PRIMARY KEY ("myColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -328,6 +345,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" "public"."enum_myTable_myColumn");', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] ENUM("foo", "bar"));`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" ENUM("foo", "bar")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" ENUM("foo", "bar"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -345,6 +363,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER, `secondColumn` BIGINT, `thirdColumn` SMALLINT) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER, [secondColumn] BIGINT, [thirdColumn] SMALLINT);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER, "secondColumn" BIGINT, "thirdColumn" SMALLINT); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER, "secondColumn" BIGINT, "thirdColumn" SMALLINT)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -365,6 +384,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" SERIAL, "secondColumn" BIGSERIAL, "thirdColumn" SMALLSERIAL);', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER SERIAL, [secondColumn] BIGINT SERIAL, [thirdColumn] SMALLINT SERIAL);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER SERIAL, "secondColumn" BIGINT SERIAL, "thirdColumn" SMALLINT SERIAL); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER SERIAL, "secondColumn" BIGINT SERIAL, "thirdColumn" SMALLINT SERIAL)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -377,6 +397,7 @@ describe('QueryGenerator#createTableQuery', () => { postgres: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" SERIAL);', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER SERIAL NOT NULL);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER SERIAL NOT NULL); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER SERIAL NOT NULL)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -387,6 +408,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER AUTOINCREMENT) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER AUTOINCREMENT);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER AUTOINCREMENT); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER AUTOINCREMENT)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -399,6 +421,7 @@ describe('QueryGenerator#createTableQuery', () => { mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER, PRIMARY KEY ([myColumn]));`, sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER PRIMARY KEY);', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER, PRIMARY KEY ("myColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER,PRIMARY KEY ("myColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -417,6 +440,7 @@ describe('QueryGenerator#createTableQuery', () => { sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER NOT NULL, `secondColumn` TEXT NOT NULL, PRIMARY KEY (`myColumn`, `secondColumn`));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER, "secondColumn" TEXT, PRIMARY KEY ("myColumn", "secondColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER, "secondColumn" TEXT,PRIMARY KEY ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -437,6 +461,7 @@ describe('QueryGenerator#createTableQuery', () => { sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER NOT NULL, `secondColumn` INTEGER NOT NULL, `thirdColumn` TEXT NOT NULL, PRIMARY KEY (`secondColumn`, `thirdColumn`));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER NOT NULL, "secondColumn" INTEGER NOT NULL, "thirdColumn" TEXT, PRIMARY KEY ("secondColumn", "thirdColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER NOT NULL, "secondColumn" INTEGER NOT NULL, "thirdColumn" TEXT,PRIMARY KEY ("secondColumn", "thirdColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -453,6 +478,7 @@ describe('QueryGenerator#createTableQuery', () => { sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER PRIMARY KEY AUTOINCREMENT);', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER AUTOINCREMENT, PRIMARY KEY ("myColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER AUTOINCREMENT,PRIMARY KEY ("myColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -468,6 +494,7 @@ describe('QueryGenerator#createTableQuery', () => { mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER(5) UNSIGNED, PRIMARY KEY ([myColumn]));`, sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER PRIMARY KEY);', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER(5) UNSIGNED, PRIMARY KEY ("myColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER(5) UNSIGNED,PRIMARY KEY ("myColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -479,6 +506,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER(5) UNSIGNED) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER(5) UNSIGNED);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER(5) UNSIGNED); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER(5) UNSIGNED)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -494,6 +522,7 @@ describe('QueryGenerator#createTableQuery', () => { 'snowflake db2': 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" INTEGER, FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER REFERENCES "Bar" ("id")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER,FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -604,6 +633,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" TEXT, UNIQUE "uniq_myTable_myColumn_secondColumn" ("myColumn", "secondColumn"));', db2: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE NOT NULL, "secondColumn" TEXT NOT NULL, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -627,6 +657,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" TEXT, UNIQUE "myIndex" ("myColumn", "secondColumn"));', db2: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE NOT NULL, "secondColumn" TEXT NOT NULL, CONSTRAINT "myIndex" UNIQUE ("myColumn", "secondColumn"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT, CONSTRAINT "myIndex" UNIQUE ("myColumn", "secondColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT, CONSTRAINT "myIndex" UNIQUE ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -650,6 +681,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, UNIQUE "uniq_myTable_myColumn" ("myColumn"));', db2: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE NOT NULL, CONSTRAINT "uniq_myTable_myColumn" UNIQUE ("myColumn"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, CONSTRAINT "uniq_myTable_myColumn" UNIQUE ("myColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE, CONSTRAINT "uniq_myTable_myColumn" UNIQUE ("myColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -673,6 +705,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" TEXT, UNIQUE "uniq_myTable_myColumn_secondColumn" ("myColumn", "secondColumn"), PRIMARY KEY ("myColumn", "secondColumn"));', db2: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" TEXT, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"), PRIMARY KEY ("myColumn", "secondColumn"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT, PRIMARY KEY ("myColumn", "secondColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT,PRIMARY KEY ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -696,6 +729,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE NOT NULL, "secondColumn" TEXT, UNIQUE "uniq_myTable_myColumn_secondColumn" ("myColumn", "secondColumn"));', db2: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE NOT NULL, "secondColumn" TEXT NOT NULL, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE NOT NULL, "secondColumn" TEXT, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE NOT NULL, "secondColumn" TEXT, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -719,6 +753,7 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" TEXT, UNIQUE "uniq_myTable_myColumn_secondColumn" ("myColumn", "secondColumn"), PRIMARY KEY ("myColumn"), FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"));', db2: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" TEXT NOT NULL, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"), PRIMARY KEY ("myColumn"), FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE REFERENCES "Bar" ("id"), "secondColumn" TEXT, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"), PRIMARY KEY ("myColumn")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE , "secondColumn" TEXT,PRIMARY KEY ("myColumn"),FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"), CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); diff --git a/packages/core/test/unit/query-generator/describe-table-query.test.ts b/packages/core/test/unit/query-generator/describe-table-query.test.ts index 84ab12a60bc2..6b068f7594bd 100644 --- a/packages/core/test/unit/query-generator/describe-table-query.test.ts +++ b/packages/core/test/unit/query-generator/describe-table-query.test.ts @@ -75,6 +75,10 @@ describe('QueryGenerator#describeTableQuery', () => { ON QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME WHERE QSYS2.SYSCOLUMNS.TABLE_SCHEMA = CURRENT SCHEMA AND QSYS2.SYSCOLUMNS.TABLE_NAME = 'myTable'`, + oracle: `SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type FROM all_tab_columns atc + LEFT OUTER JOIN (SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc + INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) + WHERE (atc.OWNER = '${dialect.getDefaultSchema()}') AND (atc.TABLE_NAME = 'myTable')ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC`, }); }); @@ -150,6 +154,10 @@ describe('QueryGenerator#describeTableQuery', () => { ON QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME WHERE QSYS2.SYSCOLUMNS.TABLE_SCHEMA = CURRENT SCHEMA AND QSYS2.SYSCOLUMNS.TABLE_NAME = 'MyModels'`, + oracle: `SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type FROM all_tab_columns atc + LEFT OUTER JOIN (SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc + INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) + WHERE (atc.OWNER = '${dialect.getDefaultSchema()}') AND (atc.TABLE_NAME = 'MyModels')ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC`, }); }); @@ -226,6 +234,11 @@ describe('QueryGenerator#describeTableQuery', () => { ON QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME WHERE QSYS2.SYSCOLUMNS.TABLE_SCHEMA = CURRENT SCHEMA AND QSYS2.SYSCOLUMNS.TABLE_NAME = 'MyModels'`, + oracle: `SELECT + atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type + FROM all_tab_columns atc + LEFT OUTER JOIN (SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc + ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) WHERE (atc.OWNER = '${dialect.getDefaultSchema()}') AND (atc.TABLE_NAME = 'MyModels')ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC`, }); }); @@ -299,6 +312,10 @@ describe('QueryGenerator#describeTableQuery', () => { ON QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME WHERE QSYS2.SYSCOLUMNS.TABLE_SCHEMA = 'mySchema' AND QSYS2.SYSCOLUMNS.TABLE_NAME = 'myTable'`, + oracle: `SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type FROM all_tab_columns atc + LEFT OUTER JOIN (SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc + INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) + WHERE (atc.OWNER = 'mySchema') AND (atc.TABLE_NAME = 'myTable')ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC`, }, ); }); @@ -378,6 +395,10 @@ describe('QueryGenerator#describeTableQuery', () => { ON QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME WHERE QSYS2.SYSCOLUMNS.TABLE_SCHEMA = CURRENT SCHEMA AND QSYS2.SYSCOLUMNS.TABLE_NAME = 'myTable'`, + oracle: `SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type FROM all_tab_columns atc + LEFT OUTER JOIN (SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc + INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) + WHERE (atc.OWNER = '${dialect.getDefaultSchema()}') AND (atc.TABLE_NAME = 'myTable')ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC`, }, ); }); @@ -455,6 +476,10 @@ describe('QueryGenerator#describeTableQuery', () => { ON QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME WHERE QSYS2.SYSCOLUMNS.TABLE_SCHEMA = 'mySchema' AND QSYS2.SYSCOLUMNS.TABLE_NAME = 'myTable'`, + oracle: `SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type FROM all_tab_columns atc + LEFT OUTER JOIN (SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc + INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) + WHERE (atc.OWNER = 'mySchema') AND (atc.TABLE_NAME = 'myTable')ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC`, }); }); diff --git a/packages/core/test/unit/query-generator/drop-schema-query.test.ts b/packages/core/test/unit/query-generator/drop-schema-query.test.ts index 12c5623df622..ec2bb90467b9 100644 --- a/packages/core/test/unit/query-generator/drop-schema-query.test.ts +++ b/packages/core/test/unit/query-generator/drop-schema-query.test.ts @@ -13,6 +13,7 @@ describe('QueryGenerator#dropSchemaQuery', () => { default: 'DROP SCHEMA [mySchema]', db2: 'DROP SCHEMA "mySchema" RESTRICT', sqlite3: notSupportedError, + oracle: `BEGIN EXECUTE IMMEDIATE 'DROP USER "mySchema" CASCADE' ; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1918 THEN RAISE; END IF; END;`, }); }); @@ -21,6 +22,7 @@ describe('QueryGenerator#dropSchemaQuery', () => { default: 'DROP SCHEMA IF EXISTS [mySchema]', 'db2 mssql': buildInvalidOptionReceivedError('dropSchemaQuery', dialectName, ['ifExists']), sqlite3: notSupportedError, + oracle: `BEGIN EXECUTE IMMEDIATE 'DROP USER "mySchema" CASCADE' ; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1918 THEN RAISE; END IF; END;`, }); }); @@ -31,6 +33,7 @@ describe('QueryGenerator#dropSchemaQuery', () => { 'cascade', ]), sqlite3: notSupportedError, + oracle: `BEGIN EXECUTE IMMEDIATE 'DROP USER "mySchema" CASCADE' ; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1918 THEN RAISE; END IF; END;`, }); }); @@ -43,6 +46,7 @@ describe('QueryGenerator#dropSchemaQuery', () => { ]), 'mariadb mysql': buildInvalidOptionReceivedError('dropSchemaQuery', dialectName, ['cascade']), sqlite3: notSupportedError, + oracle: `BEGIN EXECUTE IMMEDIATE 'DROP USER "mySchema" CASCADE' ; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1918 THEN RAISE; END IF; END;`, }); }); }); diff --git a/packages/core/test/unit/query-generator/drop-table-query.test.ts b/packages/core/test/unit/query-generator/drop-table-query.test.ts index de34dd6df782..b32fbb1df4b3 100644 --- a/packages/core/test/unit/query-generator/drop-table-query.test.ts +++ b/packages/core/test/unit/query-generator/drop-table-query.test.ts @@ -10,6 +10,7 @@ describe('QueryGenerator#dropTableQuery', () => { it('produces a query that drops a table', () => { expectsql(() => queryGenerator.dropTableQuery('myTable'), { default: `DROP TABLE IF EXISTS [myTable]`, + oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "myTable" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); }); @@ -17,6 +18,7 @@ describe('QueryGenerator#dropTableQuery', () => { expectsql(() => queryGenerator.dropTableQuery('myTable', { cascade: true }), { default: buildInvalidOptionReceivedError('dropTableQuery', dialectName, ['cascade']), 'postgres snowflake': `DROP TABLE IF EXISTS "myTable" CASCADE`, + oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "myTable" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); }); @@ -25,6 +27,7 @@ describe('QueryGenerator#dropTableQuery', () => { expectsql(() => queryGenerator.dropTableQuery(MyModel), { default: `DROP TABLE IF EXISTS [MyModels]`, + oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "MyModels" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); }); @@ -34,6 +37,7 @@ describe('QueryGenerator#dropTableQuery', () => { expectsql(() => queryGenerator.dropTableQuery(myDefinition), { default: `DROP TABLE IF EXISTS [MyModels]`, + oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "MyModels" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); }); @@ -41,6 +45,7 @@ describe('QueryGenerator#dropTableQuery', () => { expectsql(() => queryGenerator.dropTableQuery({ tableName: 'myTable', schema: 'mySchema' }), { default: `DROP TABLE IF EXISTS [mySchema].[myTable]`, sqlite3: 'DROP TABLE IF EXISTS `mySchema.myTable`', + oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "mySchema"."myTable" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); }); @@ -50,6 +55,7 @@ describe('QueryGenerator#dropTableQuery', () => { queryGenerator.dropTableQuery({ tableName: 'myTable', schema: dialect.getDefaultSchema() }), { default: `DROP TABLE IF EXISTS [myTable]`, + oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "myTable" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }, ); }); @@ -61,6 +67,7 @@ describe('QueryGenerator#dropTableQuery', () => { expectsql(() => queryGeneratorSchema.dropTableQuery('myTable'), { default: `DROP TABLE IF EXISTS [mySchema].[myTable]`, sqlite3: 'DROP TABLE IF EXISTS `mySchema.myTable`', + oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "mySchema"."myTable" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); }); diff --git a/packages/core/test/unit/query-generator/get-constraint-snippet.test.ts b/packages/core/test/unit/query-generator/get-constraint-snippet.test.ts index 64af232085bb..1c780e17bb87 100644 --- a/packages/core/test/unit/query-generator/get-constraint-snippet.test.ts +++ b/packages/core/test/unit/query-generator/get-constraint-snippet.test.ts @@ -533,7 +533,7 @@ describe('QueryGeneratorInternal#getConstraintSnippet', () => { }), { default: `CONSTRAINT [myTable_otherId_otherTable_fk] FOREIGN KEY ([otherId]) REFERENCES [otherTable] ([id]) ON UPDATE CASCADE`, - 'db2 ibmi': onUpdateNotSupportedError, + 'db2 ibmi oracle': onUpdateNotSupportedError, }, ); }); diff --git a/packages/core/test/unit/query-generator/insert-query.test.ts b/packages/core/test/unit/query-generator/insert-query.test.ts index 465e9276d9ed..308801ef9b0e 100644 --- a/packages/core/test/unit/query-generator/insert-query.test.ts +++ b/packages/core/test/unit/query-generator/insert-query.test.ts @@ -4,6 +4,7 @@ import { beforeAll2, expectsql, sequelize } from '../../support'; describe('QueryGenerator#insertQuery', () => { const queryGenerator = sequelize.queryGenerator; + const dialect = sequelize.dialect; const vars = beforeAll2(() => { const User = sequelize.define( @@ -56,6 +57,7 @@ describe('QueryGenerator#insertQuery', () => { default: `INSERT INTO [Users] ([firstName],[lastName],[username]) VALUES ($sequelize_1,$lastName,$sequelize_2);`, db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName","username") VALUES ($sequelize_1,$lastName,$sequelize_2));`, ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName","username") VALUES ($sequelize_1,$lastName,$sequelize_2))`, + oracle: `INSERT INTO "Users" ("firstName","lastName","username") VALUES (:1,$lastName,:2);`, }); expect(bind).to.deep.eq({ @@ -78,6 +80,7 @@ describe('QueryGenerator#insertQuery', () => { default: `INSERT INTO [Users] ([firstName],[lastName],[username]) VALUES ($sequelize_1,$1,$sequelize_2);`, db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName","username") VALUES ($sequelize_1,$1,$sequelize_2));`, ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName","username") VALUES ($sequelize_1,$1,$sequelize_2))`, + oracle: `INSERT INTO "Users" ("firstName","lastName","username") VALUES (:1,$1,:2);`, }); expect(bind).to.deep.eq({ sequelize_1: 'John', @@ -157,10 +160,12 @@ describe('QueryGenerator#insertQuery', () => { 'INSERT INTO [Users] ([firstName]) OUTPUT INSERTED.[id], INSERTED.[firstName] VALUES ($sequelize_1);', db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES ($sequelize_1));', ibmi: 'SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES ($sequelize_1))', + oracle: `INSERT INTO "Users" ("firstName") VALUES (:1) RETURNING "id", "firstName" INTO :2,:3;`, }); }); - it('supports array of strings (column names)', () => { + // node-oracledb requires OUTBIND definition, RETURNING '*' isn't valid for oracle. + (dialect.name === 'oracle' ? it.skip : it)('supports array of strings (column names)', () => { const { User } = vars; const { query } = queryGenerator.insertQuery( @@ -188,7 +193,8 @@ describe('QueryGenerator#insertQuery', () => { }); }); - it('supports array of literals', () => { + // node-oracledb requires OUTBIND definition, '*' isn't valid for oracle. + (dialect.name === 'oracle' ? it.skip : it)('supports array of literals', () => { const { User } = vars; expectsql( @@ -229,6 +235,7 @@ describe('QueryGenerator#insertQuery', () => { default: 'INSERT INTO [myTable] ([birthday]) VALUES ($sequelize_1);', 'db2 ibmi': 'SELECT * FROM FINAL TABLE (INSERT INTO "myTable" ("birthday") VALUES ($sequelize_1));', + oracle: `INSERT INTO "myTable" ("birthday") VALUES (:1);`, }, bind: { mysql: { @@ -255,6 +262,9 @@ describe('QueryGenerator#insertQuery', () => { mssql: { sequelize_1: '2011-03-27 10:01:55.000 +00:00', }, + oracle: { + sequelize_1: new Date('2011-03-27T10:01:55Z'), + }, }, }); }); @@ -267,6 +277,7 @@ describe('QueryGenerator#insertQuery', () => { 'INSERT INTO [myTable] ([positive],[negative]) VALUES ($sequelize_1,$sequelize_2);', 'db2 ibmi': 'SELECT * FROM FINAL TABLE (INSERT INTO "myTable" ("positive","negative") VALUES ($sequelize_1,$sequelize_2));', + oracle: `INSERT INTO "myTable" ("positive","negative") VALUES (:1,:2);`, }, bind: { sqlite3: { @@ -301,6 +312,10 @@ describe('QueryGenerator#insertQuery', () => { sequelize_1: true, sequelize_2: false, }, + oracle: { + sequelize_1: '1', + sequelize_2: '0', + }, }, }); }); @@ -315,6 +330,7 @@ describe('QueryGenerator#insertQuery', () => { default: 'INSERT INTO [myTable] ([value],[name]) VALUES ($sequelize_1,$sequelize_2);', 'db2 ibmi': 'SELECT * FROM FINAL TABLE (INSERT INTO "myTable" ("value","name") VALUES ($sequelize_1,$sequelize_2));', + oracle: `INSERT INTO "myTable" ("value","name") VALUES (:1,:2);`, }); expect(bind).to.deep.eq({ diff --git a/packages/core/test/unit/query-generator/json-path-extraction-query.test.ts b/packages/core/test/unit/query-generator/json-path-extraction-query.test.ts index 7edfea4feed6..632df98eea13 100644 --- a/packages/core/test/unit/query-generator/json-path-extraction-query.test.ts +++ b/packages/core/test/unit/query-generator/json-path-extraction-query.test.ts @@ -24,6 +24,7 @@ describe('QueryGenerator#jsonPathExtractionQuery', () => { mariadb: `json_compact(json_extract(\`profile\`,'$.id'))`, 'mysql sqlite3': `json_extract(\`profile\`,'$.id')`, postgres: `"profile"->'id'`, + oracle: `json_value("profile",'$."id"')`, }, ); }); @@ -41,6 +42,7 @@ describe('QueryGenerator#jsonPathExtractionQuery', () => { mariadb: `json_compact(json_extract(\`profile\`,'$[0]'))`, 'mysql sqlite3': `json_extract(\`profile\`,'$[0]')`, postgres: `"profile"->0`, + oracle: `json_value("profile",'$[0]')`, }, ); }); @@ -58,6 +60,7 @@ describe('QueryGenerator#jsonPathExtractionQuery', () => { mariadb: `json_compact(json_extract(\`profile\`,'$.id.username[0]."0".name'))`, 'mysql sqlite3': `json_extract(\`profile\`,'$.id.username[0]."0".name')`, postgres: `"profile"#>ARRAY['id','username','0','0','name']::VARCHAR(255)[]`, + oracle: `json_value("profile",'$."id"."username"[0][0]."name"')`, }, ); }); @@ -76,6 +79,7 @@ describe('QueryGenerator#jsonPathExtractionQuery', () => { mariadb: `json_compact(json_extract(\`profile\`,'$."\\\\""."\\'"."$"'))`, sqlite3: `json_extract(\`profile\`,'$."\\""."''"."$"')`, postgres: `"profile"#>ARRAY['"','''','$']::VARCHAR(255)[]`, + oracle: `json_value("profile",'$.""."''"."$"')`, }, ); }); diff --git a/packages/core/test/unit/query-generator/list-schemas-query.test.ts b/packages/core/test/unit/query-generator/list-schemas-query.test.ts index c63ae40a7753..218006362fd4 100644 --- a/packages/core/test/unit/query-generator/list-schemas-query.test.ts +++ b/packages/core/test/unit/query-generator/list-schemas-query.test.ts @@ -17,6 +17,7 @@ describe('QueryGenerator#listSchemasQuery', () => { sqlite3: notSupportedError, postgres: `SELECT schema_name AS "schema" FROM information_schema.schemata WHERE schema_name !~ E'^pg_' AND schema_name NOT IN ('public', 'information_schema', 'tiger', 'tiger_data', 'topology')`, snowflake: `SELECT SCHEMA_NAME AS "schema" FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('INFORMATION_SCHEMA', 'PERFORMANCE_SCHEMA', 'SYS', 'information_schema', 'performance_schema', 'sys')`, + oracle: `SELECT USERNAME AS "schema" FROM ALL_USERS WHERE COMMON = ('NO') AND USERNAME != user`, }); }); @@ -30,6 +31,7 @@ describe('QueryGenerator#listSchemasQuery', () => { sqlite3: notSupportedError, postgres: `SELECT schema_name AS "schema" FROM information_schema.schemata WHERE schema_name !~ E'^pg_' AND schema_name NOT IN ('public', 'information_schema', 'tiger', 'tiger_data', 'topology', 'test', 'Te''st2')`, snowflake: `SELECT SCHEMA_NAME AS "schema" FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('INFORMATION_SCHEMA', 'PERFORMANCE_SCHEMA', 'SYS', 'information_schema', 'performance_schema', 'sys', 'test', 'Te''st2')`, + oracle: `SELECT USERNAME AS "schema" FROM ALL_USERS WHERE COMMON = ('NO') AND USERNAME != user`, }); }); }); diff --git a/packages/core/test/unit/query-generator/list-tables-query.test.ts b/packages/core/test/unit/query-generator/list-tables-query.test.ts index 536e5a7fba0a..ae1397e915a1 100644 --- a/packages/core/test/unit/query-generator/list-tables-query.test.ts +++ b/packages/core/test/unit/query-generator/list-tables-query.test.ts @@ -14,6 +14,7 @@ describe('QueryGenerator#listTablesQuery', () => { mariadb: `SELECT TABLE_NAME AS \`tableName\`, TABLE_SCHEMA AS \`schema\` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA NOT IN ('MYSQL', 'INFORMATION_SCHEMA', 'PERFORMANCE_SCHEMA', 'SYS', 'mysql', 'information_schema', 'performance_schema', 'sys') ORDER BY TABLE_SCHEMA, TABLE_NAME`, postgres: `SELECT table_name AS "tableName", table_schema AS "schema" FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_name != 'spatial_ref_sys' AND table_schema !~ E'^pg_' AND table_schema NOT IN ('information_schema', 'tiger', 'tiger_data', 'topology') ORDER BY table_schema, table_name`, snowflake: `SELECT TABLE_NAME AS "tableName", TABLE_SCHEMA AS "schema" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA NOT IN ('INFORMATION_SCHEMA', 'PERFORMANCE_SCHEMA', 'SYS', 'information_schema', 'performance_schema', 'sys') ORDER BY TABLE_SCHEMA, TABLE_NAME`, + oracle: `SELECT owner as "schema", table_name as "tableName" FROM all_tables where OWNER IN(SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE ORACLE_MAINTAINED = 'N')`, }); }); @@ -27,6 +28,7 @@ describe('QueryGenerator#listTablesQuery', () => { mariadb: `SELECT TABLE_NAME AS \`tableName\`, TABLE_SCHEMA AS \`schema\` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = 'mySchema' ORDER BY TABLE_SCHEMA, TABLE_NAME`, postgres: `SELECT table_name AS "tableName", table_schema AS "schema" FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_name != 'spatial_ref_sys' AND table_schema = 'mySchema' ORDER BY table_schema, table_name`, snowflake: `SELECT TABLE_NAME AS "tableName", TABLE_SCHEMA AS "schema" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = 'mySchema' ORDER BY TABLE_SCHEMA, TABLE_NAME`, + oracle: `SELECT owner as "schema", table_name as "tableName" FROM all_tables where OWNER IN(SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE ORACLE_MAINTAINED = 'N' AND USERNAME='mySchema')`, }); }); @@ -42,6 +44,7 @@ describe('QueryGenerator#listTablesQuery', () => { mariadb: `SELECT TABLE_NAME AS \`tableName\`, TABLE_SCHEMA AS \`schema\` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = 'sequelize_test' ORDER BY TABLE_SCHEMA, TABLE_NAME`, postgres: `SELECT table_name AS "tableName", table_schema AS "schema" FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_name != 'spatial_ref_sys' AND table_schema = 'public' ORDER BY table_schema, table_name`, snowflake: `SELECT TABLE_NAME AS "tableName", TABLE_SCHEMA AS "schema" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = 'PUBLIC' ORDER BY TABLE_SCHEMA, TABLE_NAME`, + oracle: `SELECT owner as "schema", table_name as "tableName" FROM all_tables where OWNER IN(SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE ORACLE_MAINTAINED = 'N' AND USERNAME='${sequelize.dialect.getDefaultSchema()}')`, }, ); }); diff --git a/packages/core/test/unit/query-generator/remove-constraint-query.test.ts b/packages/core/test/unit/query-generator/remove-constraint-query.test.ts index fc556e7563f4..6040b5fac409 100644 --- a/packages/core/test/unit/query-generator/remove-constraint-query.test.ts +++ b/packages/core/test/unit/query-generator/remove-constraint-query.test.ts @@ -27,6 +27,9 @@ describe('QueryGenerator#removeConstraintQuery', () => { dialect.name, ['ifExists'], ), + oracle: buildInvalidOptionReceivedError('removeConstraintQuery', dialect.name, [ + 'ifExists', + ]), }, ); }); @@ -59,6 +62,7 @@ describe('QueryGenerator#removeConstraintQuery', () => { snowflake: buildInvalidOptionReceivedError('removeConstraintQuery', dialect.name, [ 'ifExists', ]), + oracle: buildInvalidOptionReceivedError('removeConstraintQuery', dialect.name, ['cascade']), sqlite3: notSupportedError, }, ); diff --git a/packages/core/test/unit/query-generator/remove-index-query.test.ts b/packages/core/test/unit/query-generator/remove-index-query.test.ts index 8e28f0374c72..da50f1e2f5b9 100644 --- a/packages/core/test/unit/query-generator/remove-index-query.test.ts +++ b/packages/core/test/unit/query-generator/remove-index-query.test.ts @@ -15,7 +15,7 @@ describe('QueryGenerator#removeIndexQuery', () => { default: `DROP INDEX [user_foo_bar] ON [myTable]`, sqlite3: 'DROP INDEX `user_foo_bar`', ibmi: `BEGIN DROP INDEX "user_foo_bar"; COMMIT; END`, - db2: `DROP INDEX "user_foo_bar"`, + 'db2 oracle': `DROP INDEX "user_foo_bar"`, postgres: `DROP INDEX "public"."user_foo_bar"`, snowflake: notImplementedError, }); @@ -26,7 +26,7 @@ describe('QueryGenerator#removeIndexQuery', () => { default: `DROP INDEX [my_table_foo_bar] ON [myTable]`, sqlite3: 'DROP INDEX `my_table_foo_bar`', ibmi: `BEGIN DROP INDEX "my_table_foo_bar"; COMMIT; END`, - db2: `DROP INDEX "my_table_foo_bar"`, + 'db2 oracle': `DROP INDEX "my_table_foo_bar"`, postgres: `DROP INDEX "public"."my_table_foo_bar"`, snowflake: notImplementedError, }); @@ -54,7 +54,7 @@ describe('QueryGenerator#removeIndexQuery', () => { postgres: `DROP INDEX IF EXISTS "public"."user_foo_bar"`, ibmi: `BEGIN IF EXISTS (SELECT * FROM QSYS2.SYSINDEXES WHERE INDEX_NAME = "user_foo_bar") THEN DROP INDEX "user_foo_bar"; COMMIT; END IF; END`, snowflake: notImplementedError, - 'db2 mysql': buildInvalidOptionReceivedError('removeIndexQuery', dialect.name, [ + 'db2 mysql oracle': buildInvalidOptionReceivedError('removeIndexQuery', dialect.name, [ 'ifExists', ]), }, @@ -80,7 +80,7 @@ describe('QueryGenerator#removeIndexQuery', () => { default: `DROP INDEX IF EXISTS [user_foo_bar] ON [myTable] CASCADE`, postgres: `DROP INDEX IF EXISTS "public"."user_foo_bar" CASCADE`, snowflake: notImplementedError, - 'db2 mysql': buildInvalidOptionReceivedError('removeIndexQuery', dialect.name, [ + 'db2 mysql oracle': buildInvalidOptionReceivedError('removeIndexQuery', dialect.name, [ 'cascade', 'ifExists', ]), @@ -104,7 +104,7 @@ describe('QueryGenerator#removeIndexQuery', () => { default: `DROP INDEX CONCURRENTLY IF EXISTS [user_foo_bar] ON [myTable]`, postgres: `DROP INDEX CONCURRENTLY IF EXISTS "public"."user_foo_bar"`, snowflake: notImplementedError, - 'db2 mysql': buildInvalidOptionReceivedError('removeIndexQuery', dialect.name, [ + 'db2 mysql oracle': buildInvalidOptionReceivedError('removeIndexQuery', dialect.name, [ 'concurrently', 'ifExists', ]), @@ -144,7 +144,7 @@ describe('QueryGenerator#removeIndexQuery', () => { default: `DROP INDEX [user_foo_bar] ON [MyModels]`, sqlite3: 'DROP INDEX `user_foo_bar`', ibmi: `BEGIN DROP INDEX "user_foo_bar"; COMMIT; END`, - db2: `DROP INDEX "user_foo_bar"`, + 'db2 oracle': `DROP INDEX "user_foo_bar"`, postgres: `DROP INDEX "public"."user_foo_bar"`, snowflake: notImplementedError, }); @@ -161,6 +161,7 @@ describe('QueryGenerator#removeIndexQuery', () => { db2: `DROP INDEX "user_foo_bar"`, postgres: `DROP INDEX "public"."user_foo_bar"`, snowflake: notImplementedError, + oracle: `DROP INDEX "user_foo_bar"`, }); }); @@ -176,7 +177,7 @@ describe('QueryGenerator#removeIndexQuery', () => { sqlite3: 'DROP INDEX `user_foo_bar`', postgres: `DROP INDEX "mySchema"."user_foo_bar"`, ibmi: `BEGIN DROP INDEX "user_foo_bar"; COMMIT; END`, - db2: `DROP INDEX "user_foo_bar"`, + 'db2 oracle': `DROP INDEX "user_foo_bar"`, snowflake: notImplementedError, }, ); @@ -193,7 +194,7 @@ describe('QueryGenerator#removeIndexQuery', () => { default: `DROP INDEX [user_foo_bar] ON [myTable]`, sqlite3: 'DROP INDEX `user_foo_bar`', ibmi: `BEGIN DROP INDEX "user_foo_bar"; COMMIT; END`, - db2: `DROP INDEX "user_foo_bar"`, + 'db2 oracle': `DROP INDEX "user_foo_bar"`, postgres: `DROP INDEX "public"."user_foo_bar"`, snowflake: notImplementedError, }, @@ -209,7 +210,7 @@ describe('QueryGenerator#removeIndexQuery', () => { sqlite3: 'DROP INDEX `user_foo_bar`', postgres: `DROP INDEX "mySchema"."user_foo_bar"`, ibmi: `BEGIN DROP INDEX "user_foo_bar"; COMMIT; END`, - db2: 'DROP INDEX "user_foo_bar"', + 'db2 oracle': 'DROP INDEX "user_foo_bar"', snowflake: notImplementedError, }); }); diff --git a/packages/core/test/unit/query-generator/rename-table-query.test.ts b/packages/core/test/unit/query-generator/rename-table-query.test.ts index 312652f14d16..32e0ce9cd669 100644 --- a/packages/core/test/unit/query-generator/rename-table-query.test.ts +++ b/packages/core/test/unit/query-generator/rename-table-query.test.ts @@ -56,7 +56,7 @@ describe('QueryGenerator#renameTableQuery', () => { ), { default: changeSchemaNotSetError, - 'db2 ibmi': moveSchemaNotSupportedError, + 'db2 ibmi oracle': moveSchemaNotSupportedError, }, ); }); @@ -74,7 +74,7 @@ describe('QueryGenerator#renameTableQuery', () => { mssql: `ALTER SCHEMA [newSchema] TRANSFER [oldSchema].[oldTable]`, sqlite3: 'ALTER TABLE `oldSchema.oldTable` RENAME TO `newSchema.oldTable`', postgres: `ALTER TABLE "oldSchema"."oldTable" SET SCHEMA "newSchema"`, - 'db2 ibmi': buildInvalidOptionReceivedError('renameTableQuery', dialect.name, [ + 'db2 ibmi oracle': buildInvalidOptionReceivedError('renameTableQuery', dialect.name, [ 'changeSchema', ]), }, @@ -92,7 +92,7 @@ describe('QueryGenerator#renameTableQuery', () => { { default: 'ALTER TABLE [oldSchema].[oldTable] RENAME TO [newSchema].[newTable]', sqlite3: 'ALTER TABLE `oldSchema.oldTable` RENAME TO `newSchema.newTable`', - 'db2 ibmi': buildInvalidOptionReceivedError('renameTableQuery', dialect.name, [ + 'db2 ibmi oracle': buildInvalidOptionReceivedError('renameTableQuery', dialect.name, [ 'changeSchema', ]), 'mssql postgres': moveSchemaWithRenameNotSupportedError, diff --git a/packages/core/test/unit/query-generator/rollback-transaction-query.test.ts b/packages/core/test/unit/query-generator/rollback-transaction-query.test.ts index a69f3132d9a2..b0e9b894d819 100644 --- a/packages/core/test/unit/query-generator/rollback-transaction-query.test.ts +++ b/packages/core/test/unit/query-generator/rollback-transaction-query.test.ts @@ -12,6 +12,7 @@ describe('QueryGenerator#rollbackTransactionQuery', () => { expectsql(() => queryGenerator.rollbackTransactionQuery(), { default: 'ROLLBACK', 'db2 ibmi mssql': notSupportedError, + oracle: 'ROLLBACK TRANSACTION', }); }); }); diff --git a/packages/core/test/unit/query-generator/select-query.test.ts b/packages/core/test/unit/query-generator/select-query.test.ts index 2f7dd5a25c21..f94dd289f579 100644 --- a/packages/core/test/unit/query-generator/select-query.test.ts +++ b/packages/core/test/unit/query-generator/select-query.test.ts @@ -90,6 +90,7 @@ describe('QueryGenerator#selectQuery', () => { 'mariadb mysql': 'SELECT `id` FROM `Users` AS `User` ORDER BY `User`.`id` LIMIT 18446744073709551615 OFFSET 1;', 'db2 ibmi mssql': `SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] OFFSET 1 ROWS;`, + oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id" OFFSET 1 ROWS;`, }); }); @@ -110,6 +111,7 @@ describe('QueryGenerator#selectQuery', () => { default: 'SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] LIMIT 10;', mssql: `SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;`, 'db2 ibmi': `SELECT "id" FROM "Users" AS "User" ORDER BY "User"."id" FETCH NEXT 10 ROWS ONLY;`, + oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id" OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;`, }); }); @@ -130,6 +132,7 @@ describe('QueryGenerator#selectQuery', () => { expectsql(sql, { default: 'SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] LIMIT 10 OFFSET 1;', 'db2 ibmi mssql': `SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] OFFSET 1 ROWS FETCH NEXT 10 ROWS ONLY;`, + oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id" OFFSET 1 ROWS FETCH NEXT 10 ROWS ONLY;`, }); }); @@ -151,6 +154,7 @@ describe('QueryGenerator#selectQuery', () => { default: `SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] LIMIT 10;`, mssql: `SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;`, 'db2 ibmi': `SELECT "id" FROM "Users" AS "User" ORDER BY "User"."id" FETCH NEXT 10 ROWS ONLY;`, + oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id" OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;`, }); }); @@ -169,6 +173,7 @@ describe('QueryGenerator#selectQuery', () => { expectsql(sql, { default: `SELECT [id] FROM [Users] AS [User];`, + oracle: `SELECT "id" FROM "Users" "User";`, }); }); @@ -190,6 +195,7 @@ describe('QueryGenerator#selectQuery', () => { default: `SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] LIMIT 0;`, mssql: new Error(`LIMIT 0 is not supported by ${dialectName} dialect.`), 'db2 ibmi': `SELECT "id" FROM "Users" AS "User" ORDER BY "User"."id" FETCH NEXT 0 ROWS ONLY;`, + oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id";`, }, ); }); @@ -214,6 +220,7 @@ describe('QueryGenerator#selectQuery', () => { 'db2 ibmi': `SELECT "id" FROM "Users" AS "User" ORDER BY "User"."id" FETCH NEXT ''';DELETE FROM user' ROWS ONLY;`, 'mariadb mysql': "SELECT `id` FROM `Users` AS `User` ORDER BY `User`.`id` LIMIT '\\';DELETE FROM user';", + oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id" OFFSET 0 ROWS FETCH NEXT ''';DELETE FROM user' ROWS ONLY;`, }); }); @@ -238,6 +245,7 @@ describe('QueryGenerator#selectQuery', () => { 'db2 ibmi': `SELECT "id" FROM "Users" AS "User" ORDER BY "User"."id" OFFSET ''';DELETE FROM user' ROWS FETCH NEXT 10 ROWS ONLY;`, 'mariadb mysql': "SELECT `id` FROM `Users` AS `User` ORDER BY `User`.`id` LIMIT 10 OFFSET '\\';DELETE FROM user';", + oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id" OFFSET ''';DELETE FROM user' ROWS FETCH NEXT 10 ROWS ONLY;`, }); }); }); @@ -259,6 +267,7 @@ describe('QueryGenerator#selectQuery', () => { expectsql(sql, { default: `SELECT [id] FROM [Projects] AS [Project] WHERE [Project].[duration] = 9007199254740993;`, + oracle: `SELECT "id" FROM "Projects" "Project" WHERE "Project"."duration" = 9007199254740993;`, }); }); @@ -276,6 +285,7 @@ describe('QueryGenerator#selectQuery', () => { expectsql(sql, { default: `SELECT [id], CAST([createdAt] AS VARCHAR) AS [createdAt] FROM [Users] AS [User];`, + oracle: `SELECT "id", CAST("createdAt" AS VARCHAR) AS "createdAt" FROM "Users" "User";`, }); }); @@ -294,6 +304,7 @@ describe('QueryGenerator#selectQuery', () => { expectsql(sql, { default: `SELECT [id] FROM [Users] AS [User];`, + oracle: `SELECT "id" FROM "Users" "User";`, }); }); @@ -314,6 +325,7 @@ describe('QueryGenerator#selectQuery', () => { default: `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = 'foo'';DROP TABLE mySchema.myTable;';`, 'mysql mariadb': `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = 'foo\\';DROP TABLE mySchema.myTable;';`, mssql: `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = N'foo'';DROP TABLE mySchema.myTable;';`, + oracle: `SELECT "id" FROM "Users" "User" WHERE "User"."username" = 'foo'';DROP TABLE mySchema.myTable;';`, }); }); @@ -337,6 +349,7 @@ describe('QueryGenerator#selectQuery', () => { postgres: `SELECT "data"->'email' AS "email" FROM "Users" AS "User";`, mariadb: `SELECT json_compact(json_extract(\`data\`,'$.email')) AS \`email\` FROM \`Users\` AS \`User\`;`, 'sqlite3 mysql': `SELECT json_extract([data],'$.email') AS [email] FROM [Users] AS [User];`, + oracle: `SELECT json_value("data",'$."email"') AS "email" FROM "Users" "User";`, }); }); } @@ -411,6 +424,16 @@ describe('QueryGenerator#selectQuery', () => { OFFSET 'repl4' ROWS FETCH NEXT 'repl3' ROWS ONLY; `, + oracle: ` + SELECT uppercase('id') AS "id", 'id2' + FROM "Users" "User" + WHERE "User"."username" = 'repl1' OR "User"."username" = (uppercase(CAST('repl1' AS STRING)) = 'repl1') + GROUP BY 'the group' + HAVING "User"."username" = 'repl1' + ORDER BY 'repl2' + OFFSET 'repl4' ROWS + FETCH NEXT 'repl3' ROWS ONLY; + `, }); }); @@ -435,6 +458,7 @@ describe('QueryGenerator#selectQuery', () => { expectsql(sql, { default: `SELECT id FROM [Users] AS [User] WHERE id = ':id';`, + oracle: `SELECT id FROM "Users" "User" WHERE id = ':id';`, }); }); @@ -516,6 +540,19 @@ describe('QueryGenerator#selectQuery', () => { LEFT OUTER JOIN "Users" AS "projects->owner" ON "projects"."ownerId" = "projects->owner"."id" `, + oracle: ` + SELECT + "User"."id", + "projects"."id" AS "projects.id", + 'repl1', 'repl1' AS "projects.id2", + "projects->owner"."id" AS "projects.owner.id", + 'repl2' + FROM "Users" "User" + INNER JOIN "Projects" "projects" + ON 'on' AND 'where' + LEFT OUTER JOIN "Users" "projects->owner" + ON "projects"."ownerId" = "projects->owner"."id"; + `, }); }); @@ -577,6 +614,21 @@ describe('QueryGenerator#selectQuery', () => { ) ON [Project].[id] = [contributors->ProjectContributor].[projectId]; `, + oracle: ` + SELECT + "Project"."id", + "contributors"."id" AS "contributors.id", + "contributors->ProjectContributor"."userId" AS "contributors.ProjectContributor.userId", + "contributors->ProjectContributor"."projectId" AS "contributors.ProjectContributor.projectId" + FROM "Projects" "Project" + LEFT OUTER JOIN ( + "ProjectContributors" "contributors->ProjectContributor" + INNER JOIN "Users" "contributors" + ON "contributors"."id" = "contributors->ProjectContributor"."userId" + AND 'where' + ) + ON "Project"."id" = "contributors->ProjectContributor"."projectId"; + `, }); }); @@ -705,6 +757,26 @@ describe('QueryGenerator#selectQuery', () => { ON "projects"."ownerId" = "projects->owner"."id" ORDER BY 'order' `, + oracle: ` + SELECT + "User".*, + "projects"."id" AS "projects.id", + 'repl1', + 'repl1' AS "projects.id2", + "projects->owner"."id" AS "projects.owner.id", + 'repl2' FROM ( + SELECT "User"."id" + FROM "Users" "User" + ORDER BY 'order' + OFFSET 'offset' ROWS + FETCH NEXT 'limit' ROWS ONLY + ) "User" + INNER JOIN "Projects" "projects" + ON 'on' AND 'where' + LEFT OUTER JOIN "Users" "projects->owner" + ON "projects"."ownerId" = "projects->owner"."id" + ORDER BY 'order'; + `, }); }); @@ -783,6 +855,20 @@ Only named replacements (:name) are allowed in literal() because we cannot guara [a].* AS [col_a_all], * AS [col_all] FROM [Users] AS [User];`, + oracle: ` + SELECT + "count(*)" AS "count", + ".*", + "*", + count(*) AS "literal_count", + count('*') AS "fn_count_str", + count(*) AS "fn_count_col", + count(*) AS "fn_count_lit", + "a"."b" AS "col_a_b", + "a".* AS "col_a_all", + * AS "col_all" + FROM "Users" "User"; + `, }); }); @@ -802,6 +888,7 @@ Only named replacements (:name) are allowed in literal() because we cannot guara expectsql(sql, { default: `SELECT *, YEAR([createdAt]) AS [creationYear] FROM [Users] AS [User] GROUP BY [creationYear], [title] HAVING [User].[creationYear] > 2002;`, + oracle: `SELECT *, YEAR("createdAt") AS "creationYear" FROM "Users" "User" GROUP BY "creationYear", "title" HAVING "User"."creationYear" > 2002;`, }); }); }); @@ -937,6 +1024,7 @@ Only named replacements (:name) are allowed in literal() because we cannot guara expectsql(sql, { default: `SELECT 1 AS [_0] FROM [Users] AS [User] GROUP BY [_0] ORDER BY [_0];`, + oracle: `SELECT 1 AS "_0" FROM "Users" "User" GROUP BY "_0" ORDER BY "_0";`, }); }); }); diff --git a/packages/core/test/unit/query-generator/set-isolation-level-query.test.ts b/packages/core/test/unit/query-generator/set-isolation-level-query.test.ts index e411b822003f..5e9bf6703c6a 100644 --- a/packages/core/test/unit/query-generator/set-isolation-level-query.test.ts +++ b/packages/core/test/unit/query-generator/set-isolation-level-query.test.ts @@ -27,6 +27,7 @@ describe('QueryGenerator#setIsolationLevelQuery', () => { sqlite3: 'PRAGMA read_uncommitted = 1', snowflake: notSupportedError, 'db2 ibmi mssql': queryNotSupportedError, + oracle: 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED', }); }); @@ -38,6 +39,7 @@ describe('QueryGenerator#setIsolationLevelQuery', () => { ), snowflake: notSupportedError, 'db2 ibmi mssql': queryNotSupportedError, + oracle: 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', }); }); diff --git a/packages/core/test/unit/query-generator/show-constraints-query.test.ts b/packages/core/test/unit/query-generator/show-constraints-query.test.ts index e1cc0c8a618a..4aebfbbae856 100644 --- a/packages/core/test/unit/query-generator/show-constraints-query.test.ts +++ b/packages/core/test/unit/query-generator/show-constraints-query.test.ts @@ -16,6 +16,7 @@ describe('QueryGenerator#showConstraintsQuery', () => { snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'PUBLIC' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'myTable'`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'sequelize_test' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, + oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='myTable' AND C.OWNER ='${dialect.getDefaultSchema()}' ORDER BY C.CONSTRAINT_NAME`, }); }); @@ -27,6 +28,7 @@ describe('QueryGenerator#showConstraintsQuery', () => { postgres: `SELECT c.constraint_catalog AS "constraintCatalog", c.constraint_schema AS "constraintSchema", c.constraint_name AS "constraintName", c.constraint_type AS "constraintType", c.table_catalog AS "tableCatalog", c.table_schema AS "tableSchema", c.table_name AS "tableName", kcu.column_name AS "columnNames", ccu.table_schema AS "referencedTableSchema", ccu.table_name AS "referencedTableName", ccu.column_name AS "referencedColumnNames", r.delete_rule AS "deleteAction", r.update_rule AS "updateAction", ch.check_clause AS "definition", c.is_deferrable AS "isDeferrable", c.initially_deferred AS "initiallyDeferred" FROM INFORMATION_SCHEMA.table_constraints c LEFT JOIN INFORMATION_SCHEMA.referential_constraints r ON c.constraint_catalog = r.constraint_catalog AND c.constraint_schema = r.constraint_schema AND c.constraint_name = r.constraint_name LEFT JOIN INFORMATION_SCHEMA.key_column_usage kcu ON c.constraint_catalog = kcu.constraint_catalog AND c.constraint_schema = kcu.constraint_schema AND c.constraint_name = kcu.constraint_name LEFT JOIN information_schema.constraint_column_usage AS ccu ON r.constraint_catalog = ccu.constraint_catalog AND r.constraint_schema = ccu.constraint_schema AND r.constraint_name = ccu.constraint_name LEFT JOIN INFORMATION_SCHEMA.check_constraints ch ON c.constraint_catalog = ch.constraint_catalog AND c.constraint_schema = ch.constraint_schema AND c.constraint_name = ch.constraint_name WHERE c.table_name = 'myTable' AND c.table_schema = 'public' AND c.constraint_name = 'foo_bar' ORDER BY c.constraint_name, kcu.ordinal_position`, snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'PUBLIC' AND c.CONSTRAINT_NAME = 'foo_bar' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'myTable'`, + oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='myTable' AND C.OWNER ='${dialect.getDefaultSchema()}' AND C.CONSTRAINT_NAME ='foo_bar' ORDER BY C.CONSTRAINT_NAME`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'sequelize_test' AND c.CONSTRAINT_NAME = 'foo_bar' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }); }); @@ -41,6 +43,7 @@ describe('QueryGenerator#showConstraintsQuery', () => { postgres: `SELECT c.constraint_catalog AS "constraintCatalog", c.constraint_schema AS "constraintSchema", c.constraint_name AS "constraintName", c.constraint_type AS "constraintType", c.table_catalog AS "tableCatalog", c.table_schema AS "tableSchema", c.table_name AS "tableName", kcu.column_name AS "columnNames", ccu.table_schema AS "referencedTableSchema", ccu.table_name AS "referencedTableName", ccu.column_name AS "referencedColumnNames", r.delete_rule AS "deleteAction", r.update_rule AS "updateAction", ch.check_clause AS "definition", c.is_deferrable AS "isDeferrable", c.initially_deferred AS "initiallyDeferred" FROM INFORMATION_SCHEMA.table_constraints c LEFT JOIN INFORMATION_SCHEMA.referential_constraints r ON c.constraint_catalog = r.constraint_catalog AND c.constraint_schema = r.constraint_schema AND c.constraint_name = r.constraint_name LEFT JOIN INFORMATION_SCHEMA.key_column_usage kcu ON c.constraint_catalog = kcu.constraint_catalog AND c.constraint_schema = kcu.constraint_schema AND c.constraint_name = kcu.constraint_name LEFT JOIN information_schema.constraint_column_usage AS ccu ON r.constraint_catalog = ccu.constraint_catalog AND r.constraint_schema = ccu.constraint_schema AND r.constraint_name = ccu.constraint_name LEFT JOIN INFORMATION_SCHEMA.check_constraints ch ON c.constraint_catalog = ch.constraint_catalog AND c.constraint_schema = ch.constraint_schema AND c.constraint_name = ch.constraint_name WHERE c.table_name = 'myTable' AND c.table_schema = 'public' AND c.constraint_type = 'FOREIGN KEY' ORDER BY c.constraint_name, kcu.ordinal_position`, snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'PUBLIC' AND c.CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'myTable'`, + oracle: `SELECT DISTINCT a.table_name "tableName", a.constraint_name "constraintName", a.owner "constraintSchema", a.column_name "columnNames",CASE c.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", c.r_owner "referencedTableSchema", c.DELETE_RULE "deleteAction", b.table_name "referencedTableName", b.column_name "referencedColumnNames" FROM all_cons_columns a JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name JOIN all_cons_columns b ON c.owner = b.owner AND c.r_constraint_name = b.constraint_name WHERE c.constraint_type = 'R' AND a.table_name = 'myTable' AND a.owner = '${dialect.getDefaultSchema()}' ORDER BY a.table_name, a.column_name, b.column_name`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'sequelize_test' AND c.CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }, ); @@ -56,6 +59,7 @@ describe('QueryGenerator#showConstraintsQuery', () => { 'columnName', ]), sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'myTable'`, + oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='myTable' AND C.OWNER ='${dialect.getDefaultSchema()}' ORDER BY C.CONSTRAINT_NAME`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'sequelize_test' AND kcu.COLUMN_NAME = 'some_column' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }); }); @@ -70,6 +74,7 @@ describe('QueryGenerator#showConstraintsQuery', () => { postgres: `SELECT c.constraint_catalog AS "constraintCatalog", c.constraint_schema AS "constraintSchema", c.constraint_name AS "constraintName", c.constraint_type AS "constraintType", c.table_catalog AS "tableCatalog", c.table_schema AS "tableSchema", c.table_name AS "tableName", kcu.column_name AS "columnNames", ccu.table_schema AS "referencedTableSchema", ccu.table_name AS "referencedTableName", ccu.column_name AS "referencedColumnNames", r.delete_rule AS "deleteAction", r.update_rule AS "updateAction", ch.check_clause AS "definition", c.is_deferrable AS "isDeferrable", c.initially_deferred AS "initiallyDeferred" FROM INFORMATION_SCHEMA.table_constraints c LEFT JOIN INFORMATION_SCHEMA.referential_constraints r ON c.constraint_catalog = r.constraint_catalog AND c.constraint_schema = r.constraint_schema AND c.constraint_name = r.constraint_name LEFT JOIN INFORMATION_SCHEMA.key_column_usage kcu ON c.constraint_catalog = kcu.constraint_catalog AND c.constraint_schema = kcu.constraint_schema AND c.constraint_name = kcu.constraint_name LEFT JOIN information_schema.constraint_column_usage AS ccu ON r.constraint_catalog = ccu.constraint_catalog AND r.constraint_schema = ccu.constraint_schema AND r.constraint_name = ccu.constraint_name LEFT JOIN INFORMATION_SCHEMA.check_constraints ch ON c.constraint_catalog = ch.constraint_catalog AND c.constraint_schema = ch.constraint_schema AND c.constraint_name = ch.constraint_name WHERE c.table_name = 'MyModels' AND c.table_schema = 'public' ORDER BY c.constraint_name, kcu.ordinal_position`, snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'MyModels' AND c.TABLE_SCHEMA = 'PUBLIC' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'MyModels'`, + oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='MyModels' AND C.OWNER ='${dialect.getDefaultSchema()}' ORDER BY C.CONSTRAINT_NAME`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'MyModels' AND c.TABLE_SCHEMA = 'sequelize_test' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }); }); @@ -86,6 +91,7 @@ describe('QueryGenerator#showConstraintsQuery', () => { snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'MyModels' AND c.TABLE_SCHEMA = 'PUBLIC' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'MyModels'`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'MyModels' AND c.TABLE_SCHEMA = 'sequelize_test' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, + oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='MyModels' AND C.OWNER ='${dialect.getDefaultSchema()}' ORDER BY C.CONSTRAINT_NAME`, }); }); @@ -99,6 +105,7 @@ describe('QueryGenerator#showConstraintsQuery', () => { postgres: `SELECT c.constraint_catalog AS "constraintCatalog", c.constraint_schema AS "constraintSchema", c.constraint_name AS "constraintName", c.constraint_type AS "constraintType", c.table_catalog AS "tableCatalog", c.table_schema AS "tableSchema", c.table_name AS "tableName", kcu.column_name AS "columnNames", ccu.table_schema AS "referencedTableSchema", ccu.table_name AS "referencedTableName", ccu.column_name AS "referencedColumnNames", r.delete_rule AS "deleteAction", r.update_rule AS "updateAction", ch.check_clause AS "definition", c.is_deferrable AS "isDeferrable", c.initially_deferred AS "initiallyDeferred" FROM INFORMATION_SCHEMA.table_constraints c LEFT JOIN INFORMATION_SCHEMA.referential_constraints r ON c.constraint_catalog = r.constraint_catalog AND c.constraint_schema = r.constraint_schema AND c.constraint_name = r.constraint_name LEFT JOIN INFORMATION_SCHEMA.key_column_usage kcu ON c.constraint_catalog = kcu.constraint_catalog AND c.constraint_schema = kcu.constraint_schema AND c.constraint_name = kcu.constraint_name LEFT JOIN information_schema.constraint_column_usage AS ccu ON r.constraint_catalog = ccu.constraint_catalog AND r.constraint_schema = ccu.constraint_schema AND r.constraint_name = ccu.constraint_name LEFT JOIN INFORMATION_SCHEMA.check_constraints ch ON c.constraint_catalog = ch.constraint_catalog AND c.constraint_schema = ch.constraint_schema AND c.constraint_name = ch.constraint_name WHERE c.table_name = 'myTable' AND c.table_schema = 'mySchema' ORDER BY c.constraint_name, kcu.ordinal_position`, snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'mySchema' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'mySchema.myTable'`, + oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='myTable' AND C.OWNER ='mySchema' ORDER BY C.CONSTRAINT_NAME`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'mySchema' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }, ); @@ -118,6 +125,7 @@ describe('QueryGenerator#showConstraintsQuery', () => { postgres: `SELECT c.constraint_catalog AS "constraintCatalog", c.constraint_schema AS "constraintSchema", c.constraint_name AS "constraintName", c.constraint_type AS "constraintType", c.table_catalog AS "tableCatalog", c.table_schema AS "tableSchema", c.table_name AS "tableName", kcu.column_name AS "columnNames", ccu.table_schema AS "referencedTableSchema", ccu.table_name AS "referencedTableName", ccu.column_name AS "referencedColumnNames", r.delete_rule AS "deleteAction", r.update_rule AS "updateAction", ch.check_clause AS "definition", c.is_deferrable AS "isDeferrable", c.initially_deferred AS "initiallyDeferred" FROM INFORMATION_SCHEMA.table_constraints c LEFT JOIN INFORMATION_SCHEMA.referential_constraints r ON c.constraint_catalog = r.constraint_catalog AND c.constraint_schema = r.constraint_schema AND c.constraint_name = r.constraint_name LEFT JOIN INFORMATION_SCHEMA.key_column_usage kcu ON c.constraint_catalog = kcu.constraint_catalog AND c.constraint_schema = kcu.constraint_schema AND c.constraint_name = kcu.constraint_name LEFT JOIN information_schema.constraint_column_usage AS ccu ON r.constraint_catalog = ccu.constraint_catalog AND r.constraint_schema = ccu.constraint_schema AND r.constraint_name = ccu.constraint_name LEFT JOIN INFORMATION_SCHEMA.check_constraints ch ON c.constraint_catalog = ch.constraint_catalog AND c.constraint_schema = ch.constraint_schema AND c.constraint_name = ch.constraint_name WHERE c.table_name = 'myTable' AND c.table_schema = 'public' ORDER BY c.constraint_name, kcu.ordinal_position`, snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'PUBLIC' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'myTable'`, + oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='myTable' AND C.OWNER ='${dialect.getDefaultSchema()}' ORDER BY C.CONSTRAINT_NAME`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'sequelize_test' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }, ); @@ -134,6 +142,7 @@ describe('QueryGenerator#showConstraintsQuery', () => { postgres: `SELECT c.constraint_catalog AS "constraintCatalog", c.constraint_schema AS "constraintSchema", c.constraint_name AS "constraintName", c.constraint_type AS "constraintType", c.table_catalog AS "tableCatalog", c.table_schema AS "tableSchema", c.table_name AS "tableName", kcu.column_name AS "columnNames", ccu.table_schema AS "referencedTableSchema", ccu.table_name AS "referencedTableName", ccu.column_name AS "referencedColumnNames", r.delete_rule AS "deleteAction", r.update_rule AS "updateAction", ch.check_clause AS "definition", c.is_deferrable AS "isDeferrable", c.initially_deferred AS "initiallyDeferred" FROM INFORMATION_SCHEMA.table_constraints c LEFT JOIN INFORMATION_SCHEMA.referential_constraints r ON c.constraint_catalog = r.constraint_catalog AND c.constraint_schema = r.constraint_schema AND c.constraint_name = r.constraint_name LEFT JOIN INFORMATION_SCHEMA.key_column_usage kcu ON c.constraint_catalog = kcu.constraint_catalog AND c.constraint_schema = kcu.constraint_schema AND c.constraint_name = kcu.constraint_name LEFT JOIN information_schema.constraint_column_usage AS ccu ON r.constraint_catalog = ccu.constraint_catalog AND r.constraint_schema = ccu.constraint_schema AND r.constraint_name = ccu.constraint_name LEFT JOIN INFORMATION_SCHEMA.check_constraints ch ON c.constraint_catalog = ch.constraint_catalog AND c.constraint_schema = ch.constraint_schema AND c.constraint_name = ch.constraint_name WHERE c.table_name = 'myTable' AND c.table_schema = 'mySchema' ORDER BY c.constraint_name, kcu.ordinal_position`, snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'mySchema' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'mySchema.myTable'`, + oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='myTable' AND C.OWNER ='mySchema' ORDER BY C.CONSTRAINT_NAME`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'mySchema' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }); }); diff --git a/packages/core/test/unit/query-generator/show-indexes-query.test.ts b/packages/core/test/unit/query-generator/show-indexes-query.test.ts index abdca5b92894..d85318b1f61d 100644 --- a/packages/core/test/unit/query-generator/show-indexes-query.test.ts +++ b/packages/core/test/unit/query-generator/show-indexes-query.test.ts @@ -29,6 +29,11 @@ describe('QueryGenerator#showIndexesQuery', () => { QSYS2.SYSKEYS.COLUMN_NAME, CAST('INDEX' AS VARCHAR(11)), QSYS2.SYSINDEXES.TABLE_SCHEMA, QSYS2.SYSINDEXES.TABLE_NAME from QSYS2.SYSKEYS left outer join QSYS2.SYSINDEXES on QSYS2.SYSKEYS.INDEX_NAME = QSYS2.SYSINDEXES.INDEX_NAME where QSYS2.SYSINDEXES.TABLE_SCHEMA = CURRENT SCHEMA and QSYS2.SYSINDEXES.TABLE_NAME = 'myTable'`, + oracle: `SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type + FROM all_ind_columns i + INNER JOIN all_indexes u ON (u.table_name = i.table_name AND u.index_name = i.index_name) + LEFT OUTER JOIN all_constraints c ON (c.table_name = i.table_name AND c.index_name = i.index_name) + WHERE i.table_name = 'myTable' AND u.table_owner = '${dialect.getDefaultSchema()}' ORDER BY index_name, column_position`, }); }); @@ -58,6 +63,11 @@ describe('QueryGenerator#showIndexesQuery', () => { QSYS2.SYSKEYS.COLUMN_NAME, CAST('INDEX' AS VARCHAR(11)), QSYS2.SYSINDEXES.TABLE_SCHEMA, QSYS2.SYSINDEXES.TABLE_NAME from QSYS2.SYSKEYS left outer join QSYS2.SYSINDEXES on QSYS2.SYSKEYS.INDEX_NAME = QSYS2.SYSINDEXES.INDEX_NAME where QSYS2.SYSINDEXES.TABLE_SCHEMA = CURRENT SCHEMA and QSYS2.SYSINDEXES.TABLE_NAME = 'MyModels'`, + oracle: `SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type + FROM all_ind_columns i + INNER JOIN all_indexes u ON (u.table_name = i.table_name AND u.index_name = i.index_name) + LEFT OUTER JOIN all_constraints c ON (c.table_name = i.table_name AND c.index_name = i.index_name) + WHERE i.table_name = 'MyModels' AND u.table_owner = '${dialect.getDefaultSchema()}' ORDER BY index_name, column_position`, }); }); @@ -88,6 +98,9 @@ describe('QueryGenerator#showIndexesQuery', () => { QSYS2.SYSKEYS.COLUMN_NAME, CAST('INDEX' AS VARCHAR(11)), QSYS2.SYSINDEXES.TABLE_SCHEMA, QSYS2.SYSINDEXES.TABLE_NAME from QSYS2.SYSKEYS left outer join QSYS2.SYSINDEXES on QSYS2.SYSKEYS.INDEX_NAME = QSYS2.SYSINDEXES.INDEX_NAME where QSYS2.SYSINDEXES.TABLE_SCHEMA = CURRENT SCHEMA and QSYS2.SYSINDEXES.TABLE_NAME = 'MyModels'`, + oracle: `SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type FROM all_ind_columns i + INNER JOIN all_indexes u ON (u.table_name = i.table_name AND u.index_name = i.index_name) + LEFT OUTER JOIN all_constraints c ON (c.table_name = i.table_name AND c.index_name = i.index_name) WHERE i.table_name = 'MyModels' AND u.table_owner = '${dialect.getDefaultSchema()}' ORDER BY index_name, column_position`, }); }); @@ -115,6 +128,11 @@ describe('QueryGenerator#showIndexesQuery', () => { QSYS2.SYSKEYS.COLUMN_NAME, CAST('INDEX' AS VARCHAR(11)), QSYS2.SYSINDEXES.TABLE_SCHEMA, QSYS2.SYSINDEXES.TABLE_NAME from QSYS2.SYSKEYS left outer join QSYS2.SYSINDEXES on QSYS2.SYSKEYS.INDEX_NAME = QSYS2.SYSINDEXES.INDEX_NAME where QSYS2.SYSINDEXES.TABLE_SCHEMA = 'mySchema' and QSYS2.SYSINDEXES.TABLE_NAME = 'myTable'`, + oracle: `SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type + FROM all_ind_columns i + INNER JOIN all_indexes u ON (u.table_name = i.table_name AND u.index_name = i.index_name) + LEFT OUTER JOIN all_constraints c ON (c.table_name = i.table_name AND c.index_name = i.index_name) + WHERE i.table_name = 'myTable' AND u.table_owner = 'mySchema' ORDER BY index_name, column_position`, }); }); @@ -148,6 +166,11 @@ describe('QueryGenerator#showIndexesQuery', () => { QSYS2.SYSKEYS.COLUMN_NAME, CAST('INDEX' AS VARCHAR(11)), QSYS2.SYSINDEXES.TABLE_SCHEMA, QSYS2.SYSINDEXES.TABLE_NAME from QSYS2.SYSKEYS left outer join QSYS2.SYSINDEXES on QSYS2.SYSKEYS.INDEX_NAME = QSYS2.SYSINDEXES.INDEX_NAME where QSYS2.SYSINDEXES.TABLE_SCHEMA = CURRENT SCHEMA and QSYS2.SYSINDEXES.TABLE_NAME = 'myTable'`, + oracle: `SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type + FROM all_ind_columns i + INNER JOIN all_indexes u ON (u.table_name = i.table_name AND u.index_name = i.index_name) + LEFT OUTER JOIN all_constraints c ON (c.table_name = i.table_name AND c.index_name = i.index_name) + WHERE i.table_name = 'myTable' AND u.table_owner = '${dialect.getDefaultSchema()}' ORDER BY index_name, column_position`, }, ); }); @@ -179,6 +202,11 @@ describe('QueryGenerator#showIndexesQuery', () => { QSYS2.SYSKEYS.COLUMN_NAME, CAST('INDEX' AS VARCHAR(11)), QSYS2.SYSINDEXES.TABLE_SCHEMA, QSYS2.SYSINDEXES.TABLE_NAME from QSYS2.SYSKEYS left outer join QSYS2.SYSINDEXES on QSYS2.SYSKEYS.INDEX_NAME = QSYS2.SYSINDEXES.INDEX_NAME where QSYS2.SYSINDEXES.TABLE_SCHEMA = 'mySchema' and QSYS2.SYSINDEXES.TABLE_NAME = 'myTable'`, + oracle: `SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type + FROM all_ind_columns i + INNER JOIN all_indexes u ON (u.table_name = i.table_name AND u.index_name = i.index_name) + LEFT OUTER JOIN all_constraints c ON (c.table_name = i.table_name AND c.index_name = i.index_name) + WHERE i.table_name = 'myTable' AND u.table_owner = 'mySchema' ORDER BY index_name, column_position`, }); }); diff --git a/packages/core/test/unit/query-generator/start-transaction-query.test.ts b/packages/core/test/unit/query-generator/start-transaction-query.test.ts index 0c23e7ac91b4..3cd417e34c4e 100644 --- a/packages/core/test/unit/query-generator/start-transaction-query.test.ts +++ b/packages/core/test/unit/query-generator/start-transaction-query.test.ts @@ -15,6 +15,7 @@ describe('QueryGenerator#startTransactionQuery', () => { default: 'START TRANSACTION', sqlite3: 'BEGIN DEFERRED TRANSACTION', 'db2 ibmi mssql': notSupportedError, + oracle: 'BEGIN TRANSACTION', }); }); @@ -24,6 +25,7 @@ describe('QueryGenerator#startTransactionQuery', () => { snowflake: 'START TRANSACTION NAME "myTransaction"', sqlite3: 'BEGIN DEFERRED TRANSACTION', 'db2 ibmi mssql': notSupportedError, + oracle: 'BEGIN TRANSACTION', }); }); @@ -86,7 +88,7 @@ describe('QueryGenerator#startTransactionQuery', () => { default: buildInvalidOptionReceivedError('startTransactionQuery', dialect.name, [ 'transactionType', ]), - 'snowflake sqlite3': buildInvalidOptionReceivedError( + 'snowflake sqlite3 oracle': buildInvalidOptionReceivedError( 'startTransactionQuery', dialect.name, ['readOnly'], diff --git a/packages/core/test/unit/query-generator/table-exists-query.test.ts b/packages/core/test/unit/query-generator/table-exists-query.test.ts index a99a4dfba560..c55e3285824a 100644 --- a/packages/core/test/unit/query-generator/table-exists-query.test.ts +++ b/packages/core/test/unit/query-generator/table-exists-query.test.ts @@ -13,6 +13,7 @@ describe('QueryGenerator#tableExistsQuery', () => { ibmi: `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TABLE_NAME = 'myTable' AND TABLE_SCHEMA = CURRENT SCHEMA`, mssql: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = N'myTable' AND TABLE_SCHEMA = N'${defaultSchema}'`, sqlite3: `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'myTable'`, + oracle: `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'myTable' AND OWNER = USER`, }); }); @@ -25,6 +26,7 @@ describe('QueryGenerator#tableExistsQuery', () => { ibmi: `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TABLE_NAME = 'MyModels' AND TABLE_SCHEMA = CURRENT SCHEMA`, mssql: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = N'MyModels' AND TABLE_SCHEMA = N'${defaultSchema}'`, sqlite3: `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'MyModels'`, + oracle: `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'MyModels' AND OWNER = '${defaultSchema}'`, }); }); @@ -38,6 +40,7 @@ describe('QueryGenerator#tableExistsQuery', () => { ibmi: `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TABLE_NAME = 'MyModels' AND TABLE_SCHEMA = CURRENT SCHEMA`, mssql: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = N'MyModels' AND TABLE_SCHEMA = N'${defaultSchema}'`, sqlite3: `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'MyModels'`, + oracle: `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'MyModels' AND OWNER = USER`, }); }); @@ -48,6 +51,7 @@ describe('QueryGenerator#tableExistsQuery', () => { ibmi: `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TABLE_NAME = 'myTable' AND TABLE_SCHEMA = 'mySchema'`, mssql: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = N'myTable' AND TABLE_SCHEMA = N'mySchema'`, sqlite3: `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'mySchema.myTable'`, + oracle: `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'myTable' AND OWNER = 'mySchema'`, }); }); @@ -64,6 +68,7 @@ describe('QueryGenerator#tableExistsQuery', () => { ibmi: `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TABLE_NAME = 'myTable' AND TABLE_SCHEMA = CURRENT SCHEMA`, mssql: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = N'myTable' AND TABLE_SCHEMA = N'${defaultSchema}'`, sqlite3: `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'myTable'`, + oracle: `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'myTable' AND OWNER = '${defaultSchema}'`, }, ); }); @@ -78,6 +83,7 @@ describe('QueryGenerator#tableExistsQuery', () => { ibmi: `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TABLE_NAME = 'myTable' AND TABLE_SCHEMA = 'mySchema'`, mssql: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = N'myTable' AND TABLE_SCHEMA = N'mySchema'`, sqlite3: `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'mySchema.myTable'`, + oracle: `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'myTable' AND OWNER = USER`, }); }); diff --git a/packages/core/test/unit/query-generator/truncate-table-query.test.ts b/packages/core/test/unit/query-generator/truncate-table-query.test.ts index 9dfa1528c1dd..31b1ea03d412 100644 --- a/packages/core/test/unit/query-generator/truncate-table-query.test.ts +++ b/packages/core/test/unit/query-generator/truncate-table-query.test.ts @@ -13,6 +13,7 @@ describe('QueryGenerator#truncateTableQuery', () => { 'db2 ibmi': 'TRUNCATE TABLE "myTable" IMMEDIATE', 'mariadb mysql': 'TRUNCATE `myTable`', 'postgres snowflake': 'TRUNCATE "myTable"', + oracle: `TRUNCATE TABLE "myTable"`, }); }); @@ -62,6 +63,7 @@ describe('QueryGenerator#truncateTableQuery', () => { 'db2 ibmi': 'TRUNCATE TABLE "MyModels" IMMEDIATE', 'mariadb mysql': 'TRUNCATE `MyModels`', 'postgres snowflake': 'TRUNCATE "MyModels"', + oracle: `TRUNCATE TABLE "MyModels"`, }); }); @@ -75,6 +77,7 @@ describe('QueryGenerator#truncateTableQuery', () => { 'db2 ibmi': 'TRUNCATE TABLE "MyModels" IMMEDIATE', 'mariadb mysql': 'TRUNCATE `MyModels`', 'postgres snowflake': 'TRUNCATE "MyModels"', + oracle: `TRUNCATE TABLE "MyModels"`, }); }); @@ -87,6 +90,7 @@ describe('QueryGenerator#truncateTableQuery', () => { 'db2 ibmi': 'TRUNCATE TABLE "mySchema"."myTable" IMMEDIATE', 'mariadb mysql': 'TRUNCATE `mySchema`.`myTable`', 'postgres snowflake': 'TRUNCATE "mySchema"."myTable"', + oracle: 'TRUNCATE TABLE "mySchema"."myTable"', }, ); }); @@ -104,6 +108,7 @@ describe('QueryGenerator#truncateTableQuery', () => { 'db2 ibmi': 'TRUNCATE TABLE "myTable" IMMEDIATE', 'mariadb mysql': 'TRUNCATE `myTable`', 'postgres snowflake': 'TRUNCATE "myTable"', + oracle: `TRUNCATE TABLE "myTable"`, }, ); }); @@ -118,6 +123,7 @@ describe('QueryGenerator#truncateTableQuery', () => { 'db2 ibmi': 'TRUNCATE TABLE "mySchema"."myTable" IMMEDIATE', 'mariadb mysql': 'TRUNCATE `mySchema`.`myTable`', 'postgres snowflake': 'TRUNCATE "mySchema"."myTable"', + oracle: 'TRUNCATE TABLE "mySchema"."myTable"', }); }); diff --git a/packages/core/test/unit/query-generator/update-query.test.ts b/packages/core/test/unit/query-generator/update-query.test.ts index 6984a84fc9ce..47afefd3d2b6 100644 --- a/packages/core/test/unit/query-generator/update-query.test.ts +++ b/packages/core/test/unit/query-generator/update-query.test.ts @@ -59,6 +59,7 @@ describe('QueryGenerator#updateQuery', () => { expectsql(query, { default: 'UPDATE [Users] SET [firstName]=$sequelize_1,[lastName]=$1,[username]=$sequelize_2', db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1,"lastName"=$1,"username"=$sequelize_2);`, + oracle: `UPDATE "Users" SET "firstName"=:1,"lastName"=$1,"username"=:2`, }); expect(bind).to.deep.eq({ sequelize_1: 'John', @@ -105,6 +106,7 @@ describe('QueryGenerator#updateQuery', () => { query: { default: 'UPDATE [myTable] SET [date]=$sequelize_1 WHERE [id] = $sequelize_2', db2: 'SELECT * FROM FINAL TABLE (UPDATE "myTable" SET "date"=$sequelize_1 WHERE "id" = $sequelize_2);', + oracle: `UPDATE "myTable" SET "date"=:1 WHERE "id" = :2`, }, bind: { mysql: { @@ -139,6 +141,10 @@ describe('QueryGenerator#updateQuery', () => { sequelize_1: '2011-03-27 10:01:55.000 +00:00', sequelize_2: 2, }, + oracle: { + sequelize_1: new Date('2011-03-27T10:01:55Z'), + sequelize_2: 2, + }, }, }); }); @@ -158,6 +164,7 @@ describe('QueryGenerator#updateQuery', () => { default: 'UPDATE [myTable] SET [positive]=$sequelize_1,[negative]=$sequelize_2 WHERE [id] = $sequelize_3', db2: 'SELECT * FROM FINAL TABLE (UPDATE "myTable" SET "positive"=$sequelize_1,"negative"=$sequelize_2 WHERE "id" = $sequelize_3);', + oracle: `UPDATE "myTable" SET "positive"=:1,"negative"=:2 WHERE "id" = :3`, }, bind: { sqlite3: { @@ -200,6 +207,11 @@ describe('QueryGenerator#updateQuery', () => { sequelize_2: false, sequelize_3: 2, }, + oracle: { + sequelize_1: '1', + sequelize_2: '0', + sequelize_3: 2, + }, }, }); }); @@ -219,6 +231,7 @@ describe('QueryGenerator#updateQuery', () => { default: 'UPDATE [myTable] SET [value]=$sequelize_1,[name]=$sequelize_2 WHERE [id] = $sequelize_3', db2: 'SELECT * FROM FINAL TABLE (UPDATE "myTable" SET "value"=$sequelize_1,"name"=$sequelize_2 WHERE "id" = $sequelize_3);', + oracle: `UPDATE "myTable" SET "value"=:1,"name"=:2 WHERE "id" = :3`, }); expect(bind).to.deep.eq({ diff --git a/packages/core/test/unit/query-generator/version-query.test.ts b/packages/core/test/unit/query-generator/version-query.test.ts index 709e962b6934..d93881142f23 100644 --- a/packages/core/test/unit/query-generator/version-query.test.ts +++ b/packages/core/test/unit/query-generator/version-query.test.ts @@ -12,6 +12,7 @@ describe('QueryGenerator#versionQuery', () => { snowflake: 'SELECT CURRENT_VERSION() AS "version"', db2: 'select service_level as "version" from TABLE (sysproc.env_get_inst_info()) as A', ibmi: `SELECT CONCAT(OS_VERSION, CONCAT('.', OS_RELEASE)) AS "version" FROM SYSIBMADM.ENV_SYS_INFO`, + oracle: `SELECT VERSION_FULL FROM PRODUCT_COMPONENT_VERSION WHERE PRODUCT LIKE 'Oracle%'`, }); }); }); diff --git a/packages/core/test/unit/query-interface/bulk-insert.test.ts b/packages/core/test/unit/query-interface/bulk-insert.test.ts index b504d1e0fbf6..e90bece7a6e8 100644 --- a/packages/core/test/unit/query-interface/bulk-insert.test.ts +++ b/packages/core/test/unit/query-interface/bulk-insert.test.ts @@ -41,6 +41,8 @@ describe('QueryInterface#bulkInsert', () => { mssql: toMatchRegex( /^INSERT INTO \[Users\] \(\[firstName\]\) VALUES (?:\(N'\w+'\),){999}\(N'\w+'\);$/, ), + // oracle uses `executeMany()` provided by node-oracledb driver and passes the value with binds + oracle: toMatchRegex(/^INSERT INTO "Users" \("firstName"\) VALUES \(:\d\)$/), }); }); @@ -65,6 +67,7 @@ describe('QueryInterface#bulkInsert', () => { mssql: toMatchRegex( /^(?:INSERT INTO \[Users\] \(\[firstName\]\) VALUES (?:\(N'\w+'\),){999}\(N'\w+'\);){2}$/, ), + oracle: toMatchRegex(/^INSERT INTO "Users" \("firstName"\) VALUES \(:\d\)$/), }); }); @@ -100,6 +103,7 @@ describe('QueryInterface#bulkInsert', () => { ibmi: toMatchSql( `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES (':injection'))`, ), + oracle: toMatchSql(`INSERT INTO "Users" ("firstName") VALUES (:1)`), }); }); }); diff --git a/packages/core/test/unit/query-interface/bulk-update.test.ts b/packages/core/test/unit/query-interface/bulk-update.test.ts index 7fe18bac8103..bf498781c778 100644 --- a/packages/core/test/unit/query-interface/bulk-update.test.ts +++ b/packages/core/test/unit/query-interface/bulk-update.test.ts @@ -48,6 +48,7 @@ describe('QueryInterface#bulkUpdate', () => { expectsql(firstCall.args[0], { default: `UPDATE [Users] SET [firstName]=$sequelize_1 WHERE [firstName] = $sequelize_2`, db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1 WHERE "firstName" = $sequelize_2);`, + oracle: `UPDATE "Users" SET "firstName"=:1 WHERE "firstName" = :2`, }); expect(firstCall.args[1]?.bind).to.deep.eq({ @@ -101,6 +102,7 @@ describe('QueryInterface#bulkUpdate', () => { expectsql(firstCall.args[0], { default: 'UPDATE [Users] SET [firstName]=$sequelize_1 WHERE [firstName] = $one', db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1 WHERE "firstName" = $one);`, + oracle: `UPDATE "Users" SET "firstName"=:1 WHERE "firstName" = $one`, }); expect(firstCall.args[1]?.bind).to.deep.eq({ @@ -132,6 +134,7 @@ describe('QueryInterface#bulkUpdate', () => { expectsql(firstCall.args[0], { default: 'UPDATE [Users] SET [firstName]=$sequelize_1 WHERE [firstName] = $1', db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1 WHERE "firstName" = $1);`, + oracle: `UPDATE "Users" SET "firstName"=:1 WHERE "firstName" = $1`, }); expect(firstCall.args[1]?.bind).to.deep.eq({ diff --git a/packages/core/test/unit/query-interface/create-table.test.ts b/packages/core/test/unit/query-interface/create-table.test.ts index f81d2c7633eb..07ca716eef33 100644 --- a/packages/core/test/unit/query-interface/create-table.test.ts +++ b/packages/core/test/unit/query-interface/create-table.test.ts @@ -40,6 +40,7 @@ describe('QueryInterface#createTable', () => { snowflake: 'CREATE TABLE IF NOT EXISTS "table" ("id" VARCHAR(36), PRIMARY KEY ("id"));', db2: 'CREATE TABLE IF NOT EXISTS "table" ("id" CHAR(36) FOR BIT DATA NOT NULL, PRIMARY KEY ("id"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "table" ("id" CHAR(36), PRIMARY KEY ("id")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "table" ("id" VARCHAR2(36),PRIMARY KEY ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -93,9 +94,11 @@ describe('QueryInterface#createTable', () => { snowflake: 'CREATE TABLE IF NOT EXISTS "table" ("id" VARCHAR(36), PRIMARY KEY ("id"));', db2: 'CREATE TABLE IF NOT EXISTS "table" ("id" CHAR(36) FOR BIT DATA NOT NULL, PRIMARY KEY ("id"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "table" ("id" CHAR(36), PRIMARY KEY ("id")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "table" ("id" VARCHAR2(36),PRIMARY KEY ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); + // oracle uses BLOB with CHECK constraint and JSON_NULL isn't allowed. it('supports JSON_NULL default values', async () => { if (!dialect.supports.dataTypes.JSON) { return; @@ -117,6 +120,7 @@ describe('QueryInterface#createTable', () => { 'mariadb mysql': 'CREATE TABLE IF NOT EXISTS `table` (`json` JSON) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[table]', 'U') IS NULL CREATE TABLE [table] ([json] NVARCHAR(MAX) DEFAULT N'null');`, sqlite3: "CREATE TABLE IF NOT EXISTS `table` (`json` TEXT DEFAULT 'null');", + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "table" ("json" BLOB CHECK ("json" IS JSON))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); }); diff --git a/packages/core/test/unit/query-interface/drop-table.test.ts b/packages/core/test/unit/query-interface/drop-table.test.ts index b1b9261dfd24..1878a1e62a45 100644 --- a/packages/core/test/unit/query-interface/drop-table.test.ts +++ b/packages/core/test/unit/query-interface/drop-table.test.ts @@ -19,6 +19,7 @@ describe('QueryInterface#dropTable', () => { const firstCall = stub.getCall(0); expectsql(firstCall.args[0], { default: 'DROP TABLE IF EXISTS [myTable] CASCADE', + oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "myTable" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); } else { await expect( diff --git a/packages/core/test/unit/query-interface/insert.test.ts b/packages/core/test/unit/query-interface/insert.test.ts index 8727ff0795d8..46531b06f25c 100644 --- a/packages/core/test/unit/query-interface/insert.test.ts +++ b/packages/core/test/unit/query-interface/insert.test.ts @@ -4,6 +4,7 @@ import sinon from 'sinon'; import { beforeAll2, expectsql, sequelize } from '../../support'; describe('QueryInterface#insert', () => { + const dialect = sequelize.dialect; const vars = beforeAll2(() => { const User = sequelize.define( 'User', @@ -21,37 +22,41 @@ describe('QueryInterface#insert', () => { }); // you'll find more replacement tests in query-generator tests - it('does not parse replacements outside of raw sql', async () => { - const { User } = vars; - const stub = sinon.stub(sequelize, 'queryRaw'); - - await sequelize.queryInterface.insert( - null, - User.table, - { - firstName: 'Zoe', - }, - { - returning: [':data'], - replacements: { - data: 'abc', + // Oracle nedds bindDefinitions to be defined for outBinds which can't be obtained with bind and replacement present together. + (dialect.name === 'oracle' ? it.skip : it)( + 'does not parse replacements outside of raw sql', + async () => { + const { User } = vars; + const stub = sinon.stub(sequelize, 'queryRaw'); + + await sequelize.queryInterface.insert( + null, + User.table, + { + firstName: 'Zoe', }, - }, - ); - - expect(stub.callCount).to.eq(1); - const firstCall = stub.getCall(0); - expectsql(firstCall.args[0], { - postgres: `INSERT INTO "Users" ("firstName") VALUES ($sequelize_1) RETURNING ":data";`, - default: 'INSERT INTO [Users] ([firstName]) VALUES ($sequelize_1);', - mssql: `INSERT INTO [Users] ([firstName]) OUTPUT INSERTED.[:data] VALUES ($sequelize_1);`, - db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES ($sequelize_1));`, - ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES ($sequelize_1))`, - }); - expect(firstCall.args[1]?.bind).to.deep.eq({ - sequelize_1: 'Zoe', - }); - }); + { + returning: [':data'], + replacements: { + data: 'abc', + }, + }, + ); + + expect(stub.callCount).to.eq(1); + const firstCall = stub.getCall(0); + expectsql(firstCall.args[0], { + postgres: `INSERT INTO "Users" ("firstName") VALUES ($sequelize_1) RETURNING ":data";`, + default: 'INSERT INTO [Users] ([firstName]) VALUES ($sequelize_1);', + mssql: `INSERT INTO [Users] ([firstName]) OUTPUT INSERTED.[:data] VALUES ($sequelize_1);`, + db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES ($sequelize_1));`, + ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES ($sequelize_1))`, + }); + expect(firstCall.args[1]?.bind).to.deep.eq({ + sequelize_1: 'Zoe', + }); + }, + ); it('throws if a bind parameter name starts with the reserved "sequelize_" prefix', async () => { const { User } = vars; @@ -75,65 +80,72 @@ describe('QueryInterface#insert', () => { ); }); - it('merges user-provided bind parameters with sequelize-generated bind parameters (object bind)', async () => { - const { User } = vars; - const stub = sinon.stub(sequelize, 'queryRaw'); + // Oracle doesn't recommend user defined bind. This can mess up the SQL statements leading to errors. + (dialect.name === 'oracle' ? it.skip : it)( + 'merges user-provided bind parameters with sequelize-generated bind parameters (object bind)', + async () => { + const { User } = vars; + const stub = sinon.stub(sequelize, 'queryRaw'); - await sequelize.queryInterface.insert( - null, - User.table, - { - firstName: literal('$firstName'), - lastName: 'Doe', - }, - { - bind: { - firstName: 'John', + await sequelize.queryInterface.insert( + null, + User.table, + { + firstName: literal('$firstName'), + lastName: 'Doe', }, - }, - ); - - expect(stub.callCount).to.eq(1); - const firstCall = stub.getCall(0); - expectsql(firstCall.args[0], { - default: 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($firstName,$sequelize_1);', - db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($firstName,$sequelize_1));`, - ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($firstName,$sequelize_1))`, - }); - - expect(firstCall.args[1]?.bind).to.deep.eq({ - firstName: 'John', - sequelize_1: 'Doe', - }); - }); - - it('merges user-provided bind parameters with sequelize-generated bind parameters (array bind)', async () => { - const { User } = vars; - const stub = sinon.stub(sequelize, 'queryRaw'); - - await sequelize.queryInterface.insert( - null, - User.table, - { - firstName: literal('$1'), - lastName: 'Doe', - }, - { - bind: ['John'], - }, - ); - - expect(stub.callCount).to.eq(1); - const firstCall = stub.getCall(0); - expectsql(firstCall.args[0], { - default: 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($1,$sequelize_1);', - db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($1,$sequelize_1));`, - ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($1,$sequelize_1))`, - }); - - expect(firstCall.args[1]?.bind).to.deep.eq({ - 1: 'John', - sequelize_1: 'Doe', - }); - }); + { + bind: { + firstName: 'John', + }, + }, + ); + + expect(stub.callCount).to.eq(1); + const firstCall = stub.getCall(0); + expectsql(firstCall.args[0], { + default: 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($firstName,$sequelize_1);', + db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($firstName,$sequelize_1));`, + ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($firstName,$sequelize_1))`, + }); + + expect(firstCall.args[1]?.bind).to.deep.eq({ + firstName: 'John', + sequelize_1: 'Doe', + }); + }, + ); + + (dialect.name === 'oracle' ? it.skip : it)( + 'merges user-provided bind parameters with sequelize-generated bind parameters (array bind)', + async () => { + const { User } = vars; + const stub = sinon.stub(sequelize, 'queryRaw'); + + await sequelize.queryInterface.insert( + null, + User.table, + { + firstName: literal('$1'), + lastName: 'Doe', + }, + { + bind: ['John'], + }, + ); + + expect(stub.callCount).to.eq(1); + const firstCall = stub.getCall(0); + expectsql(firstCall.args[0], { + default: 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($1,$sequelize_1);', + db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($1,$sequelize_1));`, + ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($1,$sequelize_1))`, + }); + + expect(firstCall.args[1]?.bind).to.deep.eq({ + 1: 'John', + sequelize_1: 'Doe', + }); + }, + ); }); diff --git a/packages/core/test/unit/query-interface/raw-select.test.ts b/packages/core/test/unit/query-interface/raw-select.test.ts index 49a3dc1d426d..17c095b4eeb2 100644 --- a/packages/core/test/unit/query-interface/raw-select.test.ts +++ b/packages/core/test/unit/query-interface/raw-select.test.ts @@ -46,6 +46,7 @@ describe('QueryInterface#rawSelect', () => { expectsql(firstCall.args[0], { default: `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = 'some :data';`, mssql: `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = N'some :data';`, + oracle: `SELECT "id" FROM "Users" "User" WHERE "User"."username" = 'some :data';`, }); }); }); diff --git a/packages/core/test/unit/query-interface/select.test.ts b/packages/core/test/unit/query-interface/select.test.ts index 32c424bc9583..a804bbafaa10 100644 --- a/packages/core/test/unit/query-interface/select.test.ts +++ b/packages/core/test/unit/query-interface/select.test.ts @@ -41,6 +41,7 @@ describe('QueryInterface#select', () => { expectsql(firstCall.args[0], { default: `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = 'some :data';`, mssql: `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = N'some :data';`, + oracle: `SELECT "id" FROM "Users" "User" WHERE "User"."username" = 'some :data';`, }); }); }); diff --git a/packages/core/test/unit/query-interface/update.test.ts b/packages/core/test/unit/query-interface/update.test.ts index be29f5f88225..d3c052a34f96 100644 --- a/packages/core/test/unit/query-interface/update.test.ts +++ b/packages/core/test/unit/query-interface/update.test.ts @@ -50,6 +50,7 @@ describe('QueryInterface#update', () => { mssql: 'UPDATE [Users] SET [firstName]=$sequelize_1 OUTPUT INSERTED.[:data] WHERE [firstName] = $sequelize_2', db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1 WHERE "firstName" = $sequelize_2);`, + oracle: `UPDATE "Users" SET "firstName"=:1 WHERE "firstName" = :2`, }); expect(firstCall.args[1]?.bind).to.deep.eq({ sequelize_1: ':name', @@ -103,6 +104,7 @@ describe('QueryInterface#update', () => { expectsql(firstCall.args[0], { default: 'UPDATE [Users] SET [firstName]=$sequelize_1 WHERE [id] = $id', db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1 WHERE "id" = $id);`, + oracle: `UPDATE "Users" SET "firstName"=:1 WHERE "id" = $id`, }); expect(firstCall.args[1]?.bind).to.deep.eq({ @@ -132,6 +134,7 @@ describe('QueryInterface#update', () => { expectsql(firstCall.args[0], { default: 'UPDATE [Users] SET [firstName]=$sequelize_1 WHERE [id] = $1', db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1 WHERE "id" = $1);`, + oracle: `UPDATE "Users" SET "firstName"=:1 WHERE "id" = $1`, }); expect(firstCall.args[1]?.bind).to.deep.eq({ diff --git a/packages/core/test/unit/query-interface/upsert.test.ts b/packages/core/test/unit/query-interface/upsert.test.ts index 76861783dfd4..30e14b6c5102 100644 --- a/packages/core/test/unit/query-interface/upsert.test.ts +++ b/packages/core/test/unit/query-interface/upsert.test.ts @@ -27,32 +27,35 @@ describe('QueryInterface#upsert', () => { }); // you'll find more replacement tests in query-generator tests - it('does not parse replacements outside of raw sql', async () => { - const { User } = vars; - const stub = sinon.stub(sequelize, 'queryRaw'); + // For oracle the datatype validation for id fails. Oracle uses Where clause which does the type validation. + (dialectName === 'oracle' ? it.skip : it)( + 'does not parse replacements outside of raw sql', + async () => { + const { User } = vars; + const stub = sinon.stub(sequelize, 'queryRaw'); - await sequelize.queryInterface.upsert( - User.tableName, - { firstName: ':name' }, - { firstName: ':name' }, - { id: ':id' }, - { - model: User, - replacements: { - name: 'Zoe', - data: 'abc', + await sequelize.queryInterface.upsert( + User.tableName, + { firstName: ':name' }, + { firstName: ':name' }, + { id: ':id' }, + { + model: User, + replacements: { + name: 'Zoe', + data: 'abc', + }, }, - }, - ); + ); - expect(stub.callCount).to.eq(1); - const firstCall = stub.getCall(0); - expectsql(firstCall.args[0], { - default: - 'INSERT INTO [Users] ([firstName]) VALUES ($sequelize_1) ON CONFLICT ([id]) DO UPDATE SET [firstName]=EXCLUDED.[firstName];', - 'mariadb mysql': - 'INSERT INTO `Users` (`firstName`) VALUES ($sequelize_1) ON DUPLICATE KEY UPDATE `firstName`=$sequelize_1;', - mssql: ` + expect(stub.callCount).to.eq(1); + const firstCall = stub.getCall(0); + expectsql(firstCall.args[0], { + default: + 'INSERT INTO [Users] ([firstName]) VALUES ($sequelize_1) ON CONFLICT ([id]) DO UPDATE SET [firstName]=EXCLUDED.[firstName];', + 'mariadb mysql': + 'INSERT INTO `Users` (`firstName`) VALUES ($sequelize_1) ON DUPLICATE KEY UPDATE `firstName`=$sequelize_1;', + mssql: ` MERGE INTO [Users] WITH(HOLDLOCK) AS [Users_target] USING (VALUES(N':name')) AS [Users_source]([firstName]) @@ -62,7 +65,7 @@ describe('QueryInterface#upsert', () => { WHEN NOT MATCHED THEN INSERT ([firstName]) VALUES(N':name') OUTPUT $action, INSERTED.*; `, - db2: ` + db2: ` MERGE INTO "Users" AS "Users_target" USING (VALUES(':name')) AS "Users_source"("firstName") @@ -72,16 +75,17 @@ describe('QueryInterface#upsert', () => { WHEN NOT MATCHED THEN INSERT ("firstName") VALUES(':name'); `, - }); - - if (dialectName === 'mssql' || dialectName === 'db2') { - expect(firstCall.args[1]?.bind).to.be.undefined; - } else { - expect(firstCall.args[1]?.bind).to.deep.eq({ - sequelize_1: ':name', }); - } - }); + + if (dialectName === 'mssql' || dialectName === 'db2') { + expect(firstCall.args[1]?.bind).to.be.undefined; + } else { + expect(firstCall.args[1]?.bind).to.deep.eq({ + sequelize_1: ':name', + }); + } + }, + ); it('throws if a bind parameter name starts with the reserved "sequelize_" prefix', async () => { const { User } = vars; @@ -105,35 +109,37 @@ describe('QueryInterface#upsert', () => { ); }); - it('merges user-provided bind parameters with sequelize-generated bind parameters (object bind)', async () => { - const { User } = vars; - const stub = sinon.stub(sequelize, 'queryRaw'); + (dialectName === 'oracle' ? it.skip : it)( + 'merges user-provided bind parameters with sequelize-generated bind parameters (object bind)', + async () => { + const { User } = vars; + const stub = sinon.stub(sequelize, 'queryRaw'); - await sequelize.queryInterface.upsert( - User.tableName, - { - firstName: literal('$firstName'), - lastName: 'Doe', - }, - {}, - // TODO: weird mssql/db2 specific behavior that should be unified - dialectName === 'mssql' || dialectName === 'db2' ? { id: 1 } : {}, - { - model: User, - bind: { - firstName: 'John', + await sequelize.queryInterface.upsert( + User.tableName, + { + firstName: literal('$firstName'), + lastName: 'Doe', }, - }, - ); + {}, + // TODO: weird mssql/db2 specific behavior that should be unified + dialectName === 'mssql' || dialectName === 'db2' ? { id: 1 } : {}, + { + model: User, + bind: { + firstName: 'John', + }, + }, + ); - expect(stub.callCount).to.eq(1); - const firstCall = stub.getCall(0); - expectsql(firstCall.args[0], { - default: - 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($firstName,$sequelize_1) ON CONFLICT ([id]) DO NOTHING;', - 'mariadb mysql': - 'INSERT INTO `Users` (`firstName`,`lastName`) VALUES ($firstName,$sequelize_1) ON DUPLICATE KEY UPDATE `id`=`id`;', - mssql: ` + expect(stub.callCount).to.eq(1); + const firstCall = stub.getCall(0); + expectsql(firstCall.args[0], { + default: + 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($firstName,$sequelize_1) ON CONFLICT ([id]) DO NOTHING;', + 'mariadb mysql': + 'INSERT INTO `Users` (`firstName`,`lastName`) VALUES ($firstName,$sequelize_1) ON DUPLICATE KEY UPDATE `id`=`id`;', + mssql: ` MERGE INTO [Users] WITH(HOLDLOCK) AS [Users_target] USING (VALUES($firstName, N'Doe')) AS [Users_source]([firstName], [lastName]) ON [Users_target].[id] = [Users_source].[id] @@ -141,54 +147,57 @@ describe('QueryInterface#upsert', () => { INSERT ([firstName], [lastName]) VALUES($firstName, N'Doe') OUTPUT $action, INSERTED.*; `, - db2: ` + db2: ` MERGE INTO "Users" AS "Users_target" USING (VALUES($firstName, 'Doe')) AS "Users_source"("firstName", "lastName") ON "Users_target"."id" = "Users_source"."id" WHEN NOT MATCHED THEN INSERT ("firstName", "lastName") VALUES($firstName, 'Doe'); `, - }); - - if (dialectName === 'mssql' || dialectName === 'db2') { - expect(firstCall.args[1]?.bind).to.deep.eq({ - firstName: 'John', - }); - } else { - expect(firstCall.args[1]?.bind).to.deep.eq({ - firstName: 'John', - sequelize_1: 'Doe', }); - } - }); - it('merges user-provided bind parameters with sequelize-generated bind parameters (array bind)', async () => { - const { User } = vars; - const stub = sinon.stub(sequelize, 'queryRaw'); + if (dialectName === 'mssql' || dialectName === 'db2') { + expect(firstCall.args[1]?.bind).to.deep.eq({ + firstName: 'John', + }); + } else { + expect(firstCall.args[1]?.bind).to.deep.eq({ + firstName: 'John', + sequelize_1: 'Doe', + }); + } + }, + ); - await sequelize.queryInterface.upsert( - User.tableName, - { - firstName: literal('$1'), - lastName: 'Doe', - }, - {}, - // TODO: weird mssql/db2 specific behavior that should be unified - dialectName === 'mssql' || dialectName === 'db2' ? { id: 1 } : {}, - { - model: User, - bind: ['John'], - }, - ); + (dialectName === 'oracle' ? it.skip : it)( + 'merges user-provided bind parameters with sequelize-generated bind parameters (array bind)', + async () => { + const { User } = vars; + const stub = sinon.stub(sequelize, 'queryRaw'); - expect(stub.callCount).to.eq(1); - const firstCall = stub.getCall(0); - expectsql(firstCall.args[0], { - default: - 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($1,$sequelize_1) ON CONFLICT ([id]) DO NOTHING;', - 'mariadb mysql': - 'INSERT INTO `Users` (`firstName`,`lastName`) VALUES ($1,$sequelize_1) ON DUPLICATE KEY UPDATE `id`=`id`;', - mssql: ` + await sequelize.queryInterface.upsert( + User.tableName, + { + firstName: literal('$1'), + lastName: 'Doe', + }, + {}, + // TODO: weird mssql/db2 specific behavior that should be unified + dialectName === 'mssql' || dialectName === 'db2' ? { id: 1 } : {}, + { + model: User, + bind: ['John'], + }, + ); + + expect(stub.callCount).to.eq(1); + const firstCall = stub.getCall(0); + expectsql(firstCall.args[0], { + default: + 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($1,$sequelize_1) ON CONFLICT ([id]) DO NOTHING;', + 'mariadb mysql': + 'INSERT INTO `Users` (`firstName`,`lastName`) VALUES ($1,$sequelize_1) ON DUPLICATE KEY UPDATE `id`=`id`;', + mssql: ` MERGE INTO [Users] WITH(HOLDLOCK) AS [Users_target] USING (VALUES($1, N'Doe')) AS [Users_source]([firstName], [lastName]) ON [Users_target].[id] = [Users_source].[id] @@ -196,25 +205,26 @@ describe('QueryInterface#upsert', () => { INSERT ([firstName], [lastName]) VALUES($1, N'Doe') OUTPUT $action, INSERTED.*; `, - db2: ` + db2: ` MERGE INTO "Users" AS "Users_target" USING (VALUES($1, 'Doe')) AS "Users_source"("firstName", "lastName") ON "Users_target"."id" = "Users_source"."id" WHEN NOT MATCHED THEN INSERT ("firstName", "lastName") VALUES($1, 'Doe'); `, - }); - - // mssql does not generate any bind parameter - if (dialectName === 'mssql' || dialectName === 'db2') { - expect(firstCall.args[1]?.bind).to.deep.eq(['John']); - } else { - expect(firstCall.args[1]?.bind).to.deep.eq({ - 1: 'John', - sequelize_1: 'Doe', }); - } - }); + + // mssql does not generate any bind parameter + if (dialectName === 'mssql' || dialectName === 'db2') { + expect(firstCall.args[1]?.bind).to.deep.eq(['John']); + } else { + expect(firstCall.args[1]?.bind).to.deep.eq({ + 1: 'John', + sequelize_1: 'Doe', + }); + } + }, + ); it('binds parameters if they are literals', async () => { const { User } = vars; @@ -257,6 +267,7 @@ describe('QueryInterface#upsert', () => { ON "Users_target"."id" = "Users_source"."id" WHEN MATCHED THEN UPDATE SET "Users_target"."counter" = \`counter\` + 1 WHEN NOT MATCHED THEN INSERT ("firstName", "counter") VALUES('Jonh', \`counter\` + 1); `, + oracle: `DECLARE BEGIN UPDATE "Users" SET "counter"=\`counter\` + 1; IF (SQL%ROWCOUNT = 0) THEN INSERT INTO "Users" ("firstName","counter") VALUES (:1,\`counter\` + 1); :isUpdate := 0; ELSE :isUpdate := 1; END IF; END;`, }); }); }); diff --git a/packages/core/test/unit/sql/add-column.test.js b/packages/core/test/unit/sql/add-column.test.js index 80fc01bdd300..6d9e6209a6b5 100644 --- a/packages/core/test/unit/sql/add-column.test.js +++ b/packages/core/test/unit/sql/add-column.test.js @@ -115,6 +115,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'ALTER TABLE "custom"."Users" ADD "level_id" REAL NOT NULL;', snowflake: 'ALTER TABLE "custom"."Users" ADD "level_id" FLOAT NOT NULL;', ibmi: 'ALTER TABLE "custom"."Users" ADD "level_id" REAL NOT NULL', + oracle: 'ALTER TABLE "custom"."Users" ADD "level_id" BINARY_FLOAT NOT NULL;', }, ); }); diff --git a/packages/core/test/unit/sql/change-column.test.js b/packages/core/test/unit/sql/change-column.test.js index d96a70a90e37..35a614d4ec05 100644 --- a/packages/core/test/unit/sql/change-column.test.js +++ b/packages/core/test/unit/sql/change-column.test.js @@ -56,6 +56,7 @@ describe('QueryInterface#changeColumn', () => { 'ALTER TABLE "users" ALTER COLUMN "level_id" SET NOT NULL;ALTER TABLE "users" ALTER COLUMN "level_id" DROP DEFAULT;ALTER TABLE "users" ALTER COLUMN "level_id" TYPE REAL;', snowflake: 'ALTER TABLE "users" ALTER COLUMN "level_id" SET NOT NULL;ALTER TABLE "users" ALTER COLUMN "level_id" DROP DEFAULT;ALTER TABLE "users" ALTER COLUMN "level_id" TYPE FLOAT;', + oracle: `DECLARE CONS_NAME VARCHAR2(200); BEGIN BEGIN EXECUTE IMMEDIATE 'ALTER TABLE "users" MODIFY "level_id" BINARY_FLOAT NOT NULL'; EXCEPTION WHEN OTHERS THEN IF SQLCODE = -1442 OR SQLCODE = -1451 THEN EXECUTE IMMEDIATE 'ALTER TABLE "users" MODIFY "level_id" BINARY_FLOAT '; ELSE RAISE; END IF; END; END;`, }); }); @@ -85,6 +86,12 @@ describe('QueryInterface#changeColumn', () => { 'ALTER TABLE "users" ADD FOREIGN KEY ("level_id") REFERENCES "level" ("id") ON DELETE CASCADE ON UPDATE CASCADE;', snowflake: 'ALTER TABLE "users" ADD FOREIGN KEY ("level_id") REFERENCES "level" ("id") ON DELETE CASCADE ON UPDATE CASCADE;', + oracle: `DECLARE CONS_NAME VARCHAR2(200); BEGIN BEGIN SELECT constraint_name INTO cons_name + FROM + (SELECT DISTINCT cc.owner, cc.table_name, cc.constraint_name, cc.column_name AS cons_columns FROM all_cons_columns cc, all_constraints c WHERE cc.owner = c.owner AND cc.table_name = c.table_name AND cc.constraint_name = c.constraint_name AND c.constraint_type = 'R' GROUP BY cc.owner, cc.table_name, cc.constraint_name, cc.column_name) + WHERE owner = '${sequelize.dialect.getDefaultSchema()}' AND table_name = 'users' AND cons_columns = 'level_id' ; + EXCEPTION WHEN NO_DATA_FOUND THEN CONS_NAME := NULL; END; IF CONS_NAME IS NOT NULL THEN EXECUTE IMMEDIATE 'ALTER TABLE "users" DROP CONSTRAINT "'||CONS_NAME||'"'; END IF; + EXECUTE IMMEDIATE 'ALTER TABLE "users" ADD FOREIGN KEY ("level_id") REFERENCES "level" ("id") ON DELETE CASCADE'; END;`, }); }); }); diff --git a/packages/core/test/unit/sql/create-table.test.js b/packages/core/test/unit/sql/create-table.test.js index 26b09ddd3b03..7df494826e5b 100644 --- a/packages/core/test/unit/sql/create-table.test.js +++ b/packages/core/test/unit/sql/create-table.test.js @@ -42,6 +42,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { BEGIN END; CREATE TABLE "foo"."users" ("id" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) , "mood" VARCHAR(255) CHECK ("mood" IN('happy', 'sad')), PRIMARY KEY ("id")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "foo"."users" ("id" NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY, "mood" VARCHAR2(512) CHECK ("mood" IN(''happy'', ''sad'')),PRIMARY KEY ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -90,6 +91,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { BEGIN END; CREATE TABLE "bar"."projects" ("id" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) , "user_id" INTEGER REFERENCES "bar"."users" ("id") ON DELETE NO ACTION, PRIMARY KEY ("id")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "bar"."projects" ("id" NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY, "user_id" INTEGER NULL,PRIMARY KEY ("id"),FOREIGN KEY ("user_id") REFERENCES "bar"."users" ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -134,6 +136,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { BEGIN END; CREATE TABLE "images" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) REFERENCES "files" ("id"), PRIMARY KEY ("id")); END`, + oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "images" ("id" NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY,PRIMARY KEY ("id"),FOREIGN KEY ("id") REFERENCES "files" ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); diff --git a/packages/core/test/unit/sql/generateJoin.test.js b/packages/core/test/unit/sql/generateJoin.test.js index a0b2fb6c58ba..4d5165f01790 100644 --- a/packages/core/test/unit/sql/generateJoin.test.js +++ b/packages/core/test/unit/sql/generateJoin.test.js @@ -122,6 +122,7 @@ describe('QueryGenerator#generateJoin', () => { }, { default: 'LEFT OUTER JOIN [company] AS [Company] ON [User].[company_id] = [Company].[id]', + oracle: `LEFT OUTER JOIN "company" "Company" ON "User"."company_id" = "Company"."id"`, }, ); }); @@ -149,6 +150,7 @@ describe('QueryGenerator#generateJoin', () => { 'INNER JOIN `company` AS `Company` ON `User`.`company_id` = `Company`.`id` OR `Company`.`public` = 1', mssql: 'INNER JOIN [company] AS [Company] ON [User].[company_id] = [Company].[id] OR [Company].[public] = 1', + oracle: `INNER JOIN "company" "Company" ON "User"."company_id" = "Company"."id" OR "Company"."public" = 1`, }, ); }); @@ -171,6 +173,7 @@ describe('QueryGenerator#generateJoin', () => { { default: 'LEFT OUTER JOIN [company] AS [Professionals->Company] ON [Professionals].[company_id] = [Professionals->Company].[id]', + oracle: `LEFT OUTER JOIN "company" "Professionals->Company" ON "Professionals"."company_id" = "Professionals->Company"."id"`, }, ); }); @@ -187,6 +190,7 @@ describe('QueryGenerator#generateJoin', () => { }, { default: 'LEFT OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id]', + oracle: `LEFT OUTER JOIN "company" "Company" ON "User"."companyId" = "Company"."id"`, }, ); }); @@ -212,6 +216,7 @@ describe('QueryGenerator#generateJoin', () => { "LEFT OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id] AND [Company].[name] = 'ABC'", mssql: "LEFT OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id] AND [Company].[name] = N'ABC'", + oracle: `LEFT OUTER JOIN "company" "Company" ON "User"."companyId" = "Company"."id" AND "Company"."name" = 'ABC'`, }, ); }); @@ -233,6 +238,7 @@ describe('QueryGenerator#generateJoin', () => { }, { default: `${sequelize.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id]`, + oracle: `RIGHT OUTER JOIN "company" "Company" ON "User"."companyId" = "Company"."id"`, }, ); }); @@ -255,6 +261,7 @@ describe('QueryGenerator#generateJoin', () => { { default: 'LEFT OUTER JOIN [user] AS [Company->Owner] ON [Company].[owner_id] = [Company->Owner].[id_user]', + oracle: `LEFT OUTER JOIN "user" "Company->Owner" ON "Company"."owner_id" = "Company->Owner"."id_user"`, }, ); }); @@ -282,6 +289,7 @@ describe('QueryGenerator#generateJoin', () => { { default: 'LEFT OUTER JOIN [profession] AS [Company->Owner->Profession] ON [Company->Owner].[professionId] = [Company->Owner->Profession].[id]', + oracle: `LEFT OUTER JOIN "profession" "Company->Owner->Profession" ON "Company->Owner"."professionId" = "Company->Owner->Profession"."id"`, }, ); }); @@ -305,6 +313,7 @@ describe('QueryGenerator#generateJoin', () => { { default: 'LEFT OUTER JOIN [user] AS [Company->Owner] ON [Company].[owner_id] = [Company->Owner].[id_user]', + oracle: `LEFT OUTER JOIN "user" "Company->Owner" ON "Company"."owner_id" = "Company->Owner"."id_user"`, }, ); }); @@ -321,6 +330,7 @@ describe('QueryGenerator#generateJoin', () => { }, { default: 'INNER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id]', + oracle: `INNER JOIN "company" "Company" ON "User"."companyId" = "Company"."id"`, }, ); }); @@ -338,7 +348,10 @@ describe('QueryGenerator#generateJoin', () => { model: User, include: [User.Tasks], }, - { default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [User].[id_user] = [Tasks].[user_id]' }, + { + default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [User].[id_user] = [Tasks].[user_id]', + oracle: `LEFT OUTER JOIN "task" "Tasks" ON "User"."id_user" = "Tasks"."user_id"`, + }, ); }); @@ -355,6 +368,7 @@ describe('QueryGenerator#generateJoin', () => { { // The primary key of the main model will be aliased because it's coming from a subquery that the :M join is not a part of default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [User].[id] = [Tasks].[user_id]', + oracle: `LEFT OUTER JOIN "task" "Tasks" ON "User"."id" = "Tasks"."user_id"`, }, ); }); @@ -381,6 +395,7 @@ describe('QueryGenerator#generateJoin', () => { { default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [User].[id_user] = [Tasks].[user_id] OR [Tasks].[user_id] = 2', + oracle: `LEFT OUTER JOIN "task" "Tasks" ON "User"."id_user" = "Tasks"."user_id" OR "Tasks"."user_id" = 2`, }, ); }); @@ -401,6 +416,7 @@ describe('QueryGenerator#generateJoin', () => { }, { default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [Tasks].[user_id] = [User].[alternative_id]', + oracle: `LEFT OUTER JOIN "task" "Tasks" ON "Tasks"."user_id" = "User"."alternative_id"`, }, ); }); @@ -433,6 +449,7 @@ describe('QueryGenerator#generateJoin', () => { { default: 'LEFT OUTER JOIN [user] AS [Company->Owner] ON [Company].[owner_id] = [Company->Owner].[id_user] OR [Company->Owner].[id_user] = 2', + oracle: `LEFT OUTER JOIN "user" "Company->Owner" ON "Company"."owner_id" = "Company->Owner"."id_user" OR "Company->Owner"."id_user" = 2`, }, ); }); diff --git a/packages/core/test/unit/sql/group.test.js b/packages/core/test/unit/sql/group.test.js index f327048c072f..ab575a5c94a5 100644 --- a/packages/core/test/unit/sql/group.test.js +++ b/packages/core/test/unit/sql/group.test.js @@ -42,6 +42,7 @@ describe('QueryGenerator#selectQuery with "group"', () => { ibmi: 'SELECT * FROM "Users" AS "User" GROUP BY "name"', mssql: 'SELECT * FROM [Users] AS [User] GROUP BY [name];', snowflake: 'SELECT * FROM "Users" AS "User" GROUP BY "name";', + oracle: `SELECT * FROM "Users" "User" GROUP BY "name";`, }, ); }); @@ -61,6 +62,7 @@ describe('QueryGenerator#selectQuery with "group"', () => { ibmi: 'SELECT * FROM "Users" AS "User"', mssql: 'SELECT * FROM [Users] AS [User];', snowflake: 'SELECT * FROM "Users" AS "User";', + oracle: `SELECT * FROM "Users" "User";`, }, ); }); diff --git a/packages/core/test/unit/sql/index.test.js b/packages/core/test/unit/sql/index.test.js index c646239e6a2b..d5b8cb1b5366 100644 --- a/packages/core/test/unit/sql/index.test.js +++ b/packages/core/test/unit/sql/index.test.js @@ -89,6 +89,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: 'CREATE INDEX CONCURRENTLY "user_field_c" ON "User" ("fieldC")', mariadb: 'ALTER TABLE `User` ADD FULLTEXT INDEX `user_field_c` (`fieldC`)', mysql: 'ALTER TABLE `User` ADD FULLTEXT INDEX `user_field_c` (`fieldC`)', + oracle: `CREATE INDEX "user_field_c" ON "User" ("fieldC")`, }, ); @@ -119,6 +120,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'ALTER TABLE `User` ADD UNIQUE INDEX `a_b_uniq` USING BTREE (`fieldB`, `fieldA`(5) DESC) WITH PARSER foo', mysql: 'ALTER TABLE `User` ADD UNIQUE INDEX `a_b_uniq` USING BTREE (`fieldB`, `fieldA`(5) DESC) WITH PARSER foo', + oracle: `CREATE UNIQUE INDEX "a_b_uniq" ON "User" ("fieldB", "fieldA" DESC)`, }, ); }); @@ -138,6 +140,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ibmi: 'CREATE INDEX "table_column" ON "table" ("column" DESC)', mariadb: 'ALTER TABLE `table` ADD INDEX `table_column` (`column`(5) DESC)', mysql: 'ALTER TABLE `table` ADD INDEX `table_column` (`column`(5) DESC)', + oracle: `CREATE INDEX "table_column" ON "table" ("column" DESC)`, }, ); }); diff --git a/packages/core/test/unit/sql/insert.test.js b/packages/core/test/unit/sql/insert.test.js index 2974bd666a71..e58641ad99be 100644 --- a/packages/core/test/unit/sql/insert.test.js +++ b/packages/core/test/unit/sql/insert.test.js @@ -43,6 +43,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'INSERT INTO "users" ("user_name") VALUES ($sequelize_1) RETURNING "id", "user_name";', db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("user_name") VALUES ($sequelize_1));', snowflake: 'INSERT INTO "users" ("user_name") VALUES ($sequelize_1);', + oracle: `INSERT INTO "users" ("user_name") VALUES (:1) RETURNING "id", "user_name" INTO :2,:3;`, default: 'INSERT INTO `users` (`user_name`) VALUES ($sequelize_1);', }, bind: { sequelize_1: 'triggertest' }, @@ -67,6 +68,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ibmi: 'SELECT * FROM FINAL TABLE (INSERT INTO "ms" ("id") VALUES ($sequelize_1))', postgres: 'INSERT INTO "ms" ("id") VALUES ($sequelize_1);', snowflake: 'INSERT INTO "ms" ("id") VALUES ($sequelize_1);', + oracle: `INSERT INTO "ms" ("id") VALUES (:1);`, default: 'INSERT INTO `ms` (`id`) VALUES ($sequelize_1);', }, bind: { sequelize_1: 0 }, @@ -168,6 +170,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { { query: { default: 'INSERT INTO [users] ([date]) VALUES ($sequelize_1);', + oracle: `INSERT INTO "users" ("date") VALUES (:1);`, }, bind: { // these dialects change the DB-side timezone, and the input doesn't specify the timezone offset, so we have to offset the value ourselves @@ -177,6 +180,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: { sequelize_1: '2015-01-20 01:00:00.000' }, // These dialects do specify the offset, so they can use whichever offset they want. postgres: { sequelize_1: '2015-01-20 01:00:00.000 +01:00' }, + oracle: { sequelize_1: new Date(Date.UTC(2015, 0, 20)) }, }, }, ); @@ -210,6 +214,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("date") VALUES ($sequelize_1));', snowflake: 'INSERT INTO "users" ("date") VALUES ($sequelize_1);', mssql: 'INSERT INTO [users] ([date]) VALUES ($sequelize_1);', + oracle: `INSERT INTO "users" ("date") VALUES (:1);`, default: 'INSERT INTO `users` (`date`) VALUES ($sequelize_1);', }, bind: { @@ -221,6 +226,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite3: { sequelize_1: '2015-01-20 00:00:00.000 +00:00' }, mssql: { sequelize_1: '2015-01-20 00:00:00.000 +00:00' }, postgres: { sequelize_1: '2015-01-20 00:00:00.000 +00:00' }, + oracle: { sequelize_1: new Date(Date.UTC(2015, 0, 20)) }, }, }, ); @@ -253,6 +259,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("date") VALUES ($sequelize_1));', snowflake: 'INSERT INTO "users" ("date") VALUES ($sequelize_1);', mssql: 'INSERT INTO [users] ([date]) VALUES ($sequelize_1);', + oracle: `INSERT INTO "users" ("date") VALUES (:1);`, default: 'INSERT INTO `users` (`date`) VALUES ($sequelize_1);', }, bind: { @@ -264,6 +271,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite3: { sequelize_1: '2015-01-20 01:02:03.089 +00:00' }, postgres: { sequelize_1: '2015-01-20 01:02:03.089 +00:00' }, mssql: { sequelize_1: '2015-01-20 01:02:03.089 +00:00' }, + oracle: { sequelize_1: new Date(Date.UTC(2015, 0, 20, 1, 2, 3, 89)) }, }, }, ); @@ -292,6 +300,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("user_name") VALUES ($sequelize_1));', snowflake: 'INSERT INTO "users" ("user_name") VALUES ($sequelize_1);', mssql: 'INSERT INTO [users] ([user_name]) VALUES ($sequelize_1);', + oracle: `INSERT INTO "users" ("user_name") VALUES (:1);`, default: 'INSERT INTO `users` (`user_name`) VALUES ($sequelize_1);', }, bind: { @@ -355,11 +364,12 @@ describe(Support.getTestDialectTeaser('SQL'), () => { "INSERT INTO `users` (`user_name`,`pass_word`) VALUES ('testuser','12345') ON DUPLICATE KEY UPDATE `user_name`=VALUES(`user_name`),`pass_word`=VALUES(`pass_word`),`updated_at`=VALUES(`updated_at`);", sqlite3: "INSERT INTO `users` (`user_name`,`pass_word`) VALUES ('testuser','12345') ON CONFLICT (`user_name`) DO UPDATE SET `user_name`=EXCLUDED.`user_name`,`pass_word`=EXCLUDED.`pass_word`,`updated_at`=EXCLUDED.`updated_at`;", + oracle: `INSERT INTO "users" ("user_name","pass_word") VALUES (:1,:2)`, }, ); }); - it('allow bulk insert primary key with 0', () => { + (dialect.name !== 'oracle' ? it : it.skip)('allow bulk insert primary key with 0', () => { const M = Support.sequelize.define('m', { id: { type: DataTypes.INTEGER, diff --git a/packages/core/test/unit/sql/literal.test.ts b/packages/core/test/unit/sql/literal.test.ts index 252dea97f22d..b98c9be3e8ea 100644 --- a/packages/core/test/unit/sql/literal.test.ts +++ b/packages/core/test/unit/sql/literal.test.ts @@ -23,6 +23,7 @@ describe('json', () => { sqlite3: `(json_extract(\`metadata\`,'$.language') = '"icelandic"' AND json_extract(\`metadata\`,'$.pg_rating.dk') = '"G"') AND json_extract(\`another_json_field\`,'$.x') = '1'`, mariadb: `(json_compact(json_extract(\`metadata\`,'$.language')) = '"icelandic"' AND json_compact(json_extract(\`metadata\`,'$.pg_rating.dk')) = '"G"') AND json_compact(json_extract(\`another_json_field\`,'$.x')) = '1'`, mysql: `(json_extract(\`metadata\`,'$.language') = CAST('"icelandic"' AS JSON) AND json_extract(\`metadata\`,'$.pg_rating.dk') = CAST('"G"' AS JSON)) AND json_extract(\`another_json_field\`,'$.x') = CAST('1' AS JSON)`, + oracle: `(json_value("metadata",'$."language"') = 'icelandic' AND json_value("metadata",'$."pg_rating"."dk"') = 'G') AND json_value("another_json_field",'$."x"') = '1'`, }); }); @@ -33,6 +34,7 @@ describe('json', () => { postgres: `"metadata"#>ARRAY['pg_rating','dk']::VARCHAR(255)[]`, mariadb: `json_compact(json_extract(\`metadata\`,'$.pg_rating.dk'))`, 'sqlite3 mysql': `json_extract(\`metadata\`,'$.pg_rating.dk')`, + oracle: `json_value("metadata",'$."pg_rating"."dk"')`, }); }); @@ -41,6 +43,7 @@ describe('json', () => { postgres: `"profile"#>ARRAY['id','0','1']::VARCHAR(255)[]`, mariadb: `json_compact(json_extract(\`profile\`,'$.id."0"."1"'))`, 'sqlite3 mysql': `json_extract(\`profile\`,'$.id."0"."1"')`, + oracle: `json_value("profile",'$."id"[0][1]')`, }); }); @@ -53,6 +56,7 @@ describe('json', () => { sqlite3: `json_extract(\`metadata\`,'$.pg_rating.is') = '"U"'`, mariadb: `json_compact(json_extract(\`metadata\`,'$.pg_rating.is')) = '"U"'`, mysql: `json_extract(\`metadata\`,'$.pg_rating.is') = CAST('"U"' AS JSON)`, + oracle: `json_value("metadata",'$."pg_rating"."is"') = 'U'`, }); }); @@ -75,6 +79,7 @@ describe('json', () => { sqlite3: `json_extract(\`profile\`,'$.id') = '1'`, mariadb: `json_compact(json_extract(\`profile\`,'$.id')) = '1'`, mysql: `json_extract(\`profile\`,'$.id') = CAST('1' AS JSON)`, + oracle: `json_value("profile",'$."id"') = '1'`, }); }); @@ -86,6 +91,7 @@ describe('json', () => { sqlite3: `json_extract(\`property\`,'$.value') = '1' AND json_extract(\`another\`,'$.value') = '"string"'`, mariadb: `json_compact(json_extract(\`property\`,'$.value')) = '1' AND json_compact(json_extract(\`another\`,'$.value')) = '"string"'`, mysql: `json_extract(\`property\`,'$.value') = CAST('1' AS JSON) AND json_extract(\`another\`,'$.value') = CAST('"string"' AS JSON)`, + oracle: `json_value("property",'$."value"') = '1' AND json_value("another",'$."value"') = 'string'`, }, ); }); @@ -96,6 +102,7 @@ describe('json', () => { sqlite3: `json_extract(\`profile\`,'$.id') = '"1"'`, mariadb: `json_compact(json_extract(\`profile\`,'$.id')) = '"1"'`, mysql: `json_extract(\`profile\`,'$.id') = CAST('"1"' AS JSON)`, + oracle: `json_value("profile",'$."id"') = '1'`, }); }); }); @@ -154,6 +161,7 @@ describe('fn', () => { mssql: `concat(N'user', 1, 1, N'2011-03-27 10:01:55.000 +00:00', lower(N'user'))`, sqlite3: `concat('user', 1, 1, '2011-03-27 10:01:55.000 +00:00', lower('user'))`, ibmi: `concat('user', 1, 1, '2011-03-27 10:01:55.000', lower('user'))`, + oracle: `concat('user', 1, 1, TO_TIMESTAMP_TZ('2011-03-27 10:01:55.000 +00:00', 'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM'), lower('user'))`, default: `concat('user', 1, true, '2011-03-27 10:01:55.000', lower('user'))`, }); }); diff --git a/packages/core/test/unit/sql/order.test.js b/packages/core/test/unit/sql/order.test.js index aa6f7285eacf..cd20cc643e4c 100644 --- a/packages/core/test/unit/sql/order.test.js +++ b/packages/core/test/unit/sql/order.test.js @@ -336,6 +336,7 @@ describe('QueryGenerator#selectQuery with "order"', () => { 'SELECT [Subtask].[id], [Subtask].[name], [Subtask].[createdAt], [Task].[id] AS [Task.id], [Task].[name] AS [Task.name], [Task].[created_at] AS [Task.createdAt], [Task->Project].[id] AS [Task.Project.id], [Task->Project].[name] AS [Task.Project.name], [Task->Project].[created_at] AS [Task.Project.createdAt] FROM [subtask] AS [Subtask] INNER JOIN [task] AS [Task] ON [Subtask].[task_id] = [Task].[id] INNER JOIN [project] AS [Task->Project] ON [Task].[project_id] = [Task->Project].[id] ORDER BY [Task->Project].[created_at] ASC, [Task->Project].[created_at], [Task].[created_at] ASC, [Task].[created_at], [Task->Project].[created_at] ASC, [Task->Project].[created_at], [Task].[created_at] ASC, [Task].[created_at], [Task->Project].[created_at] ASC, [Task->Project].[created_at], [Task].[created_at] ASC, [Task].[created_at], [Task->Project].[created_at] ASC, [Task->Project].[created_at], [Task].[created_at] ASC, [Task].[created_at], [Subtask].[created_at] ASC, [Subtask].[created_at], [Subtask].[created_at];', postgres: 'SELECT "Subtask"."id", "Subtask"."name", "Subtask"."createdAt", "Task"."id" AS "Task.id", "Task"."name" AS "Task.name", "Task"."created_at" AS "Task.createdAt", "Task->Project"."id" AS "Task.Project.id", "Task->Project"."name" AS "Task.Project.name", "Task->Project"."created_at" AS "Task.Project.createdAt" FROM "subtask" AS "Subtask" INNER JOIN "task" AS "Task" ON "Subtask"."task_id" = "Task"."id" INNER JOIN "project" AS "Task->Project" ON "Task"."project_id" = "Task->Project"."id" ORDER BY "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Subtask"."created_at" ASC, "Subtask"."created_at", "Subtask"."created_at";', + oracle: `SELECT "Subtask"."id", "Subtask"."name", "Subtask"."createdAt", "Task"."id" AS "Task.id", "Task"."name" AS "Task.name", "Task"."created_at" AS "Task.createdAt", "Task->Project"."id" AS "Task.Project.id", "Task->Project"."name" AS "Task.Project.name", "Task->Project"."created_at" AS "Task.Project.createdAt" FROM "subtask" "Subtask" INNER JOIN "task" "Task" ON "Subtask"."task_id" = "Task"."id" INNER JOIN "project" "Task->Project" ON "Task"."project_id" = "Task->Project"."id" ORDER BY "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Subtask"."created_at" ASC, "Subtask"."created_at", "Subtask"."created_at";`, }, ); }); @@ -358,6 +359,7 @@ describe('QueryGenerator#selectQuery with "order"', () => { postgres: 'SELECT "id", "name" FROM "subtask" AS "Subtask" ORDER BY RANDOM();', snowflake: 'SELECT "id", "name" FROM "subtask" AS "Subtask" ORDER BY RANDOM();', sqlite3: 'SELECT `id`, `name` FROM `subtask` AS `Subtask` ORDER BY RANDOM();', + oracle: `SELECT "id", "name" FROM "subtask" "Subtask" ORDER BY RAND();`, }, ); }); diff --git a/packages/core/test/unit/sql/select.test.js b/packages/core/test/unit/sql/select.test.js index a269ff2f66bf..417c49e5a773 100644 --- a/packages/core/test/unit/sql/select.test.js +++ b/packages/core/test/unit/sql/select.test.js @@ -53,6 +53,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mssql: "SELECT [email], [first_name] AS [firstName] FROM [User] WHERE [User].[email] = N'jon.snow@gmail.com' ORDER BY [email] DESC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;", ibmi: 'SELECT "email", "first_name" AS "firstName" FROM "User" WHERE "User"."email" = \'jon.snow@gmail.com\' ORDER BY "email" DESC FETCH NEXT 10 ROWS ONLY', + oracle: `SELECT "email", "first_name" AS "firstName" FROM "User" WHERE "User"."email" = 'jon.snow@gmail.com' ORDER BY "email" DESC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;`, }, ); @@ -80,6 +81,12 @@ describe(Support.getTestDialectTeaser('SQL'), () => { `SELECT * FROM (SELECT [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [User] WHERE [User].[companyId] = 1 ORDER BY [last_name] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) AS sub`, `SELECT * FROM (SELECT [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [User] WHERE [User].[companyId] = 5 ORDER BY [last_name] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) AS sub`, ].join(current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ')}) AS [User];`, + oracle: `SELECT "User".* FROM (${[ + `SELECT * FROM (SELECT "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "User" WHERE "User"."companyId" = 1 ORDER BY "last_name" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub`, + `SELECT * FROM (SELECT "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "User" WHERE "User"."companyId" = 5 ORDER BY "last_name" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub`, + ].join( + current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', + )}) "User" ORDER BY "last_name" ASC;`, }, ); @@ -195,6 +202,26 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ].join( current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', )}) AS [user] ORDER BY [subquery_order_0] ASC;`, + oracle: `SELECT "user".* FROM (${[ + `SELECT * FROM ( + SELECT "user"."id_user" AS "id", "user"."last_name" AS "subquery_order_0", "project_user"."user_id" AS "project_user.userId", "project_user"."project_id" AS "project_user.projectId" + FROM "users" "user" + INNER JOIN "project_users" "project_user" + ON "user"."id_user" = "project_user"."user_id" + AND "project_user"."project_id" = 1 + ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY + ) sub`, + `SELECT * FROM ( + SELECT "user"."id_user" AS "id", "user"."last_name" AS "subquery_order_0", "project_user"."user_id" AS "project_user.userId", "project_user"."project_id" AS "project_user.projectId" + FROM "users" "user" + INNER JOIN "project_users" "project_user" + ON "user"."id_user" = "project_user"."user_id" + AND "project_user"."project_id" = 5 + ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY + ) sub`, + ].join( + current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', + )}) "user" ORDER BY "subquery_order_0" ASC;`, }, ); }); @@ -286,6 +313,26 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ].join( current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', )}) AS [user] ORDER BY [subquery_order_0] ASC;`, + oracle: `SELECT "user".* FROM (${[ + `SELECT * FROM ( + SELECT "user"."id_user" AS "id", "user"."last_name" AS "subquery_order_0", "project_user"."user_id" AS "project_user.userId", "project_user"."project_id" AS "project_user.projectId" + FROM "users" "user" + INNER JOIN "project_users" "project_user" + ON "user"."id_user" = "project_user"."user_id" + AND ("project_user"."project_id" = 1 AND "project_user"."status" = 1) + ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY + ) sub`, + `SELECT * FROM ( + SELECT "user"."id_user" AS "id", "user"."last_name" AS "subquery_order_0", "project_user"."user_id" AS "project_user.userId", "project_user"."project_id" AS "project_user.projectId" + FROM "users" "user" + INNER JOIN "project_users" "project_user" + ON "user"."id_user" = "project_user"."user_id" + AND ("project_user"."project_id" = 5 AND "project_user"."status" = 1) + ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY + ) sub`, + ].join( + current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', + )}) "user" ORDER BY "subquery_order_0" ASC;`, }, ); }); @@ -377,6 +424,27 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ].join( current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', )}) AS [user] ORDER BY [subquery_order_0] ASC;`, + oracle: `SELECT "user".* FROM (${[ + `SELECT * FROM ( + SELECT "user"."id_user" AS "id", "user"."id_user" AS "subquery_order_0", "project_user"."user_id" AS "project_user.userId", "project_user"."project_id" AS "project_user.projectId" + FROM "users" "user" + INNER JOIN "project_users" "project_user" + ON "user"."id_user" = "project_user"."user_id" + AND "project_user"."project_id" = 1 WHERE "user"."age" >= 21 + ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY + ) sub`, + `SELECT * FROM ( + SELECT "user"."id_user" AS "id", "user"."id_user" AS "subquery_order_0", "project_user"."user_id" AS "project_user.userId", "project_user"."project_id" AS "project_user.projectId" + FROM "users" "user" + INNER JOIN "project_users" "project_user" + ON "user"."id_user" = "project_user"."user_id" + AND "project_user"."project_id" = 5 + WHERE "user"."age" >= 21 + ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY + ) sub`, + ].join( + current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', + )}) "user" ORDER BY "subquery_order_0" ASC;`, }, ); }); @@ -492,6 +560,12 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ].join( current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', )}) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id] = [POSTS].[user_id];`, + oracle: `SELECT "user".*, "POSTS"."id" AS "POSTS.id", "POSTS"."title" AS "POSTS.title" FROM (${[ + `SELECT * FROM (SELECT "id_user" AS "id", "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "users" "user" WHERE "user"."companyId" = 1 ORDER BY "lastName" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub`, + `SELECT * FROM (SELECT "id_user" AS "id", "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "users" "user" WHERE "user"."companyId" = 5 ORDER BY "lastName" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub`, + ].join( + current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', + )}) "user" LEFT OUTER JOIN "post" "POSTS" ON "user"."id" = "POSTS"."user_id" ORDER BY "lastName" ASC;`, }, ); }); @@ -528,6 +602,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { { default: `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title] FROM (SELECT [user].[id_user] AS [id], [user].[email], [user].[first_name] AS [firstName], [user].[last_name] AS [lastName] FROM [users] AS [user] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC LIMIT 30 OFFSET 10) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id_user] = [POSTS].[user_id] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC;`, 'db2 ibmi mssql': `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title] FROM (SELECT [user].[id_user] AS [id], [user].[email], [user].[first_name] AS [firstName], [user].[last_name] AS [lastName] FROM [users] AS [user] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC OFFSET 10 ROWS FETCH NEXT 30 ROWS ONLY) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id_user] = [POSTS].[user_id] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC;`, + oracle: `SELECT "user".*, "POSTS"."id" AS "POSTS.id", "POSTS"."title" AS "POSTS.title" FROM (SELECT "user"."id_user" AS "id", "user"."email", "user"."first_name" AS "firstName", "user"."last_name" AS "lastName" FROM "users" "user" ORDER BY "user".${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC OFFSET 10 ROWS FETCH NEXT 30 ROWS ONLY) "user" LEFT OUTER JOIN "post" "POSTS" ON "user"."id_user" = "POSTS"."user_id" ORDER BY "user".${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC;`, }, ); }); @@ -572,6 +647,11 @@ describe(Support.getTestDialectTeaser('SQL'), () => { FROM [users] AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id_user] = [POSTS].[user_id] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC OFFSET 10 ROWS FETCH NEXT 30 ROWS ONLY;`, + oracle: + Support.minifySql(`SELECT "user"."id_user" AS "id", "user"."email", "user"."first_name" AS "firstName", "user"."last_name" AS "lastName", "POSTS"."id" AS "POSTS.id", "POSTS"."title" AS "POSTS.title" + FROM "users" "user" LEFT OUTER JOIN "post" "POSTS" + ON "user"."id_user" = "POSTS"."user_id" + ORDER BY "user".${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC OFFSET 10 ROWS FETCH NEXT 30 ROWS ONLY;`), }, ); }); @@ -631,6 +711,12 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ].join( current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', )}) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id] = [POSTS].[user_id] LEFT OUTER JOIN [comment] AS [POSTS->COMMENTS] ON [POSTS].[id] = [POSTS->COMMENTS].[post_id];`, + oracle: `SELECT "user".*, "POSTS"."id" AS "POSTS.id", "POSTS"."title" AS "POSTS.title", "POSTS->COMMENTS"."id" AS "POSTS.COMMENTS.id", "POSTS->COMMENTS"."title" AS "POSTS.COMMENTS.title" FROM (${[ + `SELECT * FROM (SELECT "id_user" AS "id", "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "users" "user" WHERE "user"."companyId" = 1 ORDER BY "lastName" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub`, + `SELECT * FROM (SELECT "id_user" AS "id", "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "users" "user" WHERE "user"."companyId" = 5 ORDER BY "lastName" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub`, + ].join( + current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', + )}) "user" LEFT OUTER JOIN "post" "POSTS" ON "user"."id" = "POSTS"."user_id" LEFT OUTER JOIN "comment" "POSTS->COMMENTS" ON "POSTS"."id" = "POSTS->COMMENTS"."post_id" ORDER BY "lastName" ASC;`, }, ); }); @@ -679,6 +765,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ), { ibmi: 'SELECT "User"."name", "User"."age", "posts"."id" AS "posts.id", "posts"."title" AS "posts.title" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "posts" ON "User"."id" = "posts"."user_id"', + oracle: `SELECT "User"."name", "User"."age", "posts"."id" AS "posts.id", "posts"."title" AS "posts.title" FROM "User" "User" LEFT OUTER JOIN "Post" "posts" ON "User"."id" = "posts"."user_id";`, default: 'SELECT [User].[name], [User].[age], [posts].[id] AS [posts.id], [posts].[title] AS [posts.title] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [posts] ON [User].[id] = [posts].[user_id];', }, @@ -729,6 +816,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ), { default: `SELECT [User].[name], [User].[age], [posts].[id] AS [posts.id], [posts].[title] AS [posts.title] FROM [User] AS [User] ${current.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN [Post] AS [posts] ON [User].[id] = [posts].[user_id];`, + oracle: `SELECT "User"."name", "User"."age", "posts"."id" AS "posts.id", "posts"."title" AS "posts.title" FROM "User" "User" ${current.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN "Post" "posts" ON "User"."id" = "posts"."user_id";`, }, ); }); @@ -803,6 +891,23 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ) ON [user].[id_user] = [projects->project_user].[user_id] ORDER BY [projects->project_user].[user_id] ASC;`, + oracle: ` + SELECT "user"."id_user", + "user"."id", + "projects"."id" AS "projects.id", + "projects"."title" AS "projects.title", + "projects"."createdAt" AS "projects.createdAt", + "projects"."updatedAt" AS "projects.updatedAt", + "projects->project_user"."user_id" AS "projects.project_user.userId", + "projects->project_user"."project_id" AS "projects.project_user.projectId" + FROM "User" "user" + ${current.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN ( + "project_users" "projects->project_user" + INNER JOIN "projects" "projects" + ON "projects"."id" = "projects->project_user"."project_id" + ) + ON "user"."id_user" = "projects->project_user"."user_id" + ORDER BY "projects->project_user"."user_id" ASC;`, }, ); }); @@ -877,6 +982,11 @@ describe(Support.getTestDialectTeaser('SQL'), () => { '(SELECT [User].[name], [User].[age], [User].[id], [postaliasname].[id] AS [postaliasname.id], [postaliasname].[title] AS [postaliasname.title] FROM [User] AS [User] ' + 'INNER JOIN [Post] AS [postaliasname] ON [User].[id] = [postaliasname].[user_id] ' + `WHERE ( SELECT [user_id] FROM [Post] AS [postaliasname] WHERE [postaliasname].[user_id] = [User].[id] ORDER BY [postaliasname].[id] OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY) IS NOT NULL) AS [User];`, + oracle: + `SELECT "User".* FROM ` + + `(SELECT "User"."name", "User"."age", "User"."id", "postaliasname"."id" AS "postaliasname.id", "postaliasname"."title" AS "postaliasname.title" FROM "User" "User" ` + + `INNER JOIN "Post" "postaliasname" ON "User"."id" = "postaliasname"."user_id" ` + + `WHERE (SELECT "user_id" FROM "Post" "postaliasname" WHERE "postaliasname"."user_id" = "User"."id" ORDER BY "postaliasname"."id" OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY) IS NOT NULL) "User";`, }, ); }); @@ -925,6 +1035,11 @@ describe(Support.getTestDialectTeaser('SQL'), () => { '(SELECT [User].[name], [User].[age], [User].[id], [postaliasname].[id] AS [postaliasname.id], [postaliasname].[title] AS [postaliasname.title] FROM [User] AS [User] ' + 'INNER JOIN [Post] AS [postaliasname] ON [User].[id] = [postaliasname].[user_id] ' + `WHERE [postaliasname].[title] = ${sql.escape('test')} AND ( SELECT [user_id] FROM [Post] AS [postaliasname] WHERE [postaliasname].[user_id] = [User].[id] ORDER BY [postaliasname].[id] OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY) IS NOT NULL) AS [User];`, + oracle: + `SELECT "User".* FROM ` + + `(SELECT "User"."name", "User"."age", "User"."id", "postaliasname"."id" AS "postaliasname.id", "postaliasname"."title" AS "postaliasname.title" FROM "User" "User" ` + + `INNER JOIN "Post" "postaliasname" ON "User"."id" = "postaliasname"."user_id" ` + + `WHERE "postaliasname"."title" = 'test' AND (SELECT "user_id" FROM "Post" "postaliasname" WHERE "postaliasname"."user_id" = "User"."id" ORDER BY "postaliasname"."id" OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY) IS NOT NULL) "User";`, }, ); }); @@ -1014,6 +1129,16 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'INNER JOIN [Professions] AS [profession] ON [Users].[professionId] = [profession].[id] ' + `WHERE [Users].[companyId] = [Company].[id] ORDER BY [Users].[id] OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY` + `) IS NOT NULL ORDER BY [Company].[id] OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY) AS [Company];`, + oracle: + `SELECT "Company".* FROM (` + + `SELECT "Company"."name", "Company"."public", "Company"."id" FROM "Company" "Company" ` + + `INNER JOIN "Users" "Users" ON "Company"."id" = "Users"."companyId" ` + + `INNER JOIN "Professions" "Users->profession" ON "Users"."professionId" = "Users->profession"."id" ` + + `WHERE ("Company"."scopeId" IN (42) AND "Users->profession"."name" = 'test') AND (` + + `SELECT "Users"."companyId" FROM "Users" "Users" ` + + `INNER JOIN "Professions" "profession" ON "Users"."professionId" = "profession"."id" ` + + `WHERE "Users"."companyId" = "Company"."id" ORDER BY "Users"."id" OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY` + + `) IS NOT NULL ORDER BY "Company"."id" OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY) "Company";`, }, ); }); @@ -1051,6 +1176,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { "SELECT `name`, `age`, `data` FROM `User` AS `User` WHERE `User`.`data` IN (X'313233');", mssql: 'SELECT [name], [age], [data] FROM [User] AS [User] WHERE [User].[data] IN (0x313233);', + oracle: `SELECT "name", "age", "data" FROM "User" "User" WHERE "User"."data" IN ('313233');`, }, ); }); @@ -1205,6 +1331,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { // expectsql fails with consecutive TICKS so we add the dialect-specific one ourself default: `SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} AS ${TICK_LEFT}Posts.* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} FROM ${TICK_LEFT}User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];`, ibmi: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM ""User""; DELETE FROM ""User"";SELECT ""id""" AS "Posts.* FROM ""User""; DELETE FROM ""User"";SELECT ""id""" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "Posts" ON "User"."id" = "Posts"."user_id"', + oracle: `SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} AS ${TICK_LEFT}Posts.* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} FROM ${TICK_LEFT}User" "User" LEFT OUTER JOIN "Post" "Posts" ON "User"."id" = "Posts"."user_id";`, }, ); @@ -1239,6 +1366,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { // expectsql fails with consecutive TICKS so we add the dialect-specific one ourself default: `SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} AS ${TICK_LEFT}Posts.data] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];`, ibmi: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM ""User""; DELETE FROM ""User"";SELECT ""id""" AS "Posts.data" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "Posts" ON "User"."id" = "Posts"."user_id"', + oracle: `SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} AS ${TICK_LEFT}Posts.data" FROM "User" "User" LEFT OUTER JOIN "Post" "Posts" ON "User"."id" = "Posts"."user_id";`, }, ); @@ -1262,6 +1390,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ), { ibmi: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM User; DELETE FROM User;SELECT id" AS "Posts.data" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "Posts" ON "User"."id" = "Posts"."user_id"', + oracle: `SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM User; DELETE FROM User;SELECT id" AS "Posts.data" FROM "User" "User" LEFT OUTER JOIN "Post" "Posts" ON "User"."id" = "Posts"."user_id";`, default: 'SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[* FROM User; DELETE FROM User;SELECT id] AS [Posts.data] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];', }, @@ -1296,7 +1425,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { { default: 'SELECT [name], [age] FROM [User];', ibmi: 'SELECT "name", "age" FROM "User"', - postgres: 'SELECT name, age FROM "User";', + 'postgres oracle': 'SELECT name, age FROM "User";', snowflake: 'SELECT name, age FROM User;', }, ); @@ -1352,6 +1481,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title" FROM "User" AS "User" LEFT OUTER JOIN Post AS Posts ON "User".id = Posts.user_id;', snowflake: 'SELECT User.name, User.age, Posts.id AS "Posts.id", Posts.title AS "Posts.title" FROM User AS User LEFT OUTER JOIN Post AS Posts ON User.id = Posts.user_id;', + oracle: `SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title" FROM "User" "User" LEFT OUTER JOIN Post Posts ON "User".id = Posts.user_id;`, }, ); }); @@ -1421,6 +1551,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title", "Posts->Comments".id AS "Posts.Comments.id", "Posts->Comments".title AS "Posts.Comments.title", "Posts->Comments".createdAt AS "Posts.Comments.createdAt", "Posts->Comments".updatedAt AS "Posts.Comments.updatedAt", "Posts->Comments".post_id AS "Posts.Comments.post_id" FROM "User" AS "User" LEFT OUTER JOIN Post AS Posts ON "User".id = Posts.user_id LEFT OUTER JOIN Comment AS "Posts->Comments" ON Posts.id = "Posts->Comments".post_id;', snowflake: 'SELECT User.name, User.age, Posts.id AS "Posts.id", Posts.title AS "Posts.title", "Posts->Comments".id AS "Posts.Comments.id", "Posts->Comments".title AS "Posts.Comments.title", "Posts->Comments".createdAt AS "Posts.Comments.createdAt", "Posts->Comments".updatedAt AS "Posts.Comments.updatedAt", "Posts->Comments".post_id AS "Posts.Comments.post_id" FROM User AS User LEFT OUTER JOIN Post AS Posts ON User.id = Posts.user_id LEFT OUTER JOIN Comment AS "Posts->Comments" ON Posts.id = "Posts->Comments".post_id;', + oracle: `SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title", "Posts->Comments".id AS "Posts.Comments.id", "Posts->Comments".title AS "Posts.Comments.title", "Posts->Comments".createdAt AS "Posts.Comments.createdAt", "Posts->Comments".updatedAt AS "Posts.Comments.updatedAt", "Posts->Comments".post_id AS "Posts.Comments.post_id" FROM "User" "User" LEFT OUTER JOIN Post Posts ON "User".id = Posts.user_id LEFT OUTER JOIN "Comment" "Posts->Comments" ON Posts.id = "Posts->Comments".post_id;`, }, ); }); @@ -1483,6 +1614,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'SELECT "User".name, "User".age, "User"."status.label" AS statuslabel, Posts.id AS "Posts.id", Posts.title AS "Posts.title", Posts."status.label" AS "Posts.statuslabel" FROM "User" AS "User" LEFT OUTER JOIN Post AS Posts ON "User".id = Posts.user_id;', snowflake: 'SELECT User.name, User.age, User."status.label" AS statuslabel, Posts.id AS "Posts.id", Posts.title AS "Posts.title", Posts."status.label" AS "Posts.statuslabel" FROM User AS User LEFT OUTER JOIN Post AS Posts ON User.id = Posts.user_id;', + oracle: `SELECT "User".name, "User".age, "User"."status.label" AS statuslabel, Posts.id AS "Posts.id", Posts.title AS "Posts.title", Posts."status.label" AS "Posts.statuslabel" FROM "User" "User" LEFT OUTER JOIN Post Posts ON "User".id = Posts.user_id;`, }, ); }); diff --git a/packages/core/test/unit/sql/update.test.js b/packages/core/test/unit/sql/update.test.js index ed9d907be782..ec07c3b7ecef 100644 --- a/packages/core/test/unit/sql/update.test.js +++ b/packages/core/test/unit/sql/update.test.js @@ -40,6 +40,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { query: { db2: 'SELECT * FROM FINAL TABLE (UPDATE "users" SET "user_name"=$sequelize_1 WHERE "id" = $sequelize_2);', ibmi: 'UPDATE "users" SET "user_name"=$sequelize_1 WHERE "id" = $sequelize_2', + oracle: `UPDATE "users" SET "user_name"=:1 WHERE "id" = :2`, default: 'UPDATE [users] SET [user_name]=$sequelize_1 WHERE [id] = $sequelize_2', }, bind: { @@ -85,6 +86,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'UPDATE "users" SET "user_name"=$sequelize_1 WHERE "id" = $sequelize_2 RETURNING "id", "user_name"', db2: 'SELECT * FROM FINAL TABLE (UPDATE "users" SET "user_name"=$sequelize_1 WHERE "id" = $sequelize_2);', snowflake: 'UPDATE "users" SET "user_name"=$sequelize_1 WHERE "id" = $sequelize_2', + oracle: `UPDATE "users" SET "user_name"=:1 WHERE "id" = :2`, default: 'UPDATE `users` SET `user_name`=$sequelize_1 WHERE `id` = $sequelize_2', }, bind: { @@ -131,6 +133,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'SELECT * FROM FINAL TABLE (UPDATE (SELECT * FROM "Users" WHERE "username" = $sequelize_2 FETCH NEXT 1 ROWS ONLY) SET "username"=$sequelize_1);', snowflake: 'UPDATE "Users" SET "username"=$sequelize_1 WHERE "username" = $sequelize_2 LIMIT 1', + oracle: `UPDATE "Users" SET "username"=:1 WHERE "username" = :2 AND rownum <= 1`, default: 'UPDATE [Users] SET [username]=$sequelize_1 WHERE [username] = $sequelize_2', }, bind: { diff --git a/packages/core/test/unit/sql/where.test.ts b/packages/core/test/unit/sql/where.test.ts index 30e086e2ec23..5d1d7af20f39 100644 --- a/packages/core/test/unit/sql/where.test.ts +++ b/packages/core/test/unit/sql/where.test.ts @@ -412,6 +412,7 @@ Caused by: "undefined" cannot be escaped`), db2: '"stringAttr" = \'here is a null char: \0\'', ibmi: '"stringAttr" = \'here is a null char: \0\'', sqlite3: "`stringAttr` = 'here is a null char: \0'", + oracle: `"stringAttr" = 'here is a null char: \0'`, }, ); @@ -424,6 +425,7 @@ Caused by: "undefined" cannot be escaped`), 'mariadb mysql': `\`dateAttr\` = '2013-01-01 00:00:00.000'`, mssql: `[dateAttr] = N'2013-01-01 00:00:00.000 +00:00'`, 'db2 snowflake ibmi': `"dateAttr" = '2013-01-01 00:00:00.000'`, + oracle: `"dateAttr" = TO_TIMESTAMP_TZ('2013-01-01 00:00:00.000 +00:00', 'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM')`, }, ); @@ -437,6 +439,7 @@ Caused by: "undefined" cannot be escaped`), db2: `"binaryAttr" = BLOB('Sequelize')`, snowflake: `"binaryAttr" = X'53657175656c697a65'`, mssql: '[binaryAttr] = 0x53657175656c697a65', + oracle: `"binaryAttr" = '53657175656c697a65'`, }, ); @@ -451,6 +454,7 @@ Caused by: "undefined" cannot be escaped`), db2: `"binaryAttr" IN (BLOB('Seque''lize1'), BLOB('Sequelize2'))`, snowflake: `"binaryAttr" IN (X'5365717565276c697a6531', X'53657175656c697a6532')`, mssql: '[binaryAttr] IN (0x5365717565276c697a6531, 0x53657175656c697a6532)', + oracle: `"binaryAttr" IN ('5365717565276c697a6531', '53657175656c697a6532')`, }, ); }); @@ -534,6 +538,7 @@ Caused by: "undefined" cannot be escaped`), mssql: '[booleanAttr] = 1', sqlite3: '`booleanAttr` = 1', ibmi: '"booleanAttr" = 1', + oracle: `"booleanAttr" = 1`, }, ); @@ -571,6 +576,7 @@ Caused by: "undefined" cannot be escaped`), mssql: `[dateAttr] = N'2021-01-01 00:00:00.000 +00:00'`, 'mariadb mysql': `\`dateAttr\` = '2021-01-01 00:00:00.000'`, 'db2 ibmi snowflake': `"dateAttr" = '2021-01-01 00:00:00.000'`, + oracle: `"dateAttr" = TO_TIMESTAMP_TZ('2021-01-01 00:00:00.000 +00:00', 'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM')`, }, ); @@ -790,6 +796,7 @@ Caused by: "undefined" cannot be escaped`), { default: '[booleanAttr] = true', 'mssql sqlite3 ibmi': '[booleanAttr] = 1', + oracle: `"booleanAttr" = 1`, }, ); @@ -826,6 +833,7 @@ Caused by: "undefined" cannot be escaped`), { default: '[booleanAttr] != true', 'mssql ibmi sqlite3': '[booleanAttr] != 1', + oracle: `"booleanAttr" != 1`, }, ); @@ -863,6 +871,7 @@ Caused by: "undefined" cannot be escaped`), { default: '[booleanAttr] IS false', 'mssql ibmi sqlite3': '[booleanAttr] IS 0', + oracle: `"booleanAttr" IS 0`, }, ); @@ -871,6 +880,7 @@ Caused by: "undefined" cannot be escaped`), { default: '[booleanAttr] IS true', 'mssql ibmi sqlite3': '[booleanAttr] IS 1', + oracle: `"booleanAttr" IS 1`, }, ); @@ -967,6 +977,7 @@ Caused by: "undefined" cannot be escaped`), { default: '[booleanAttr] IS NOT false', 'mssql ibmi sqlite3': '[booleanAttr] IS NOT 0', + oracle: `"booleanAttr" IS NOT 0`, }, ); @@ -975,6 +986,7 @@ Caused by: "undefined" cannot be escaped`), { default: '[booleanAttr] IS NOT true', 'mssql ibmi sqlite3': '[booleanAttr] IS NOT 1', + oracle: `"booleanAttr" IS NOT 1`, }, ); }); @@ -1026,6 +1038,7 @@ Caused by: "undefined" cannot be escaped`), mssql: 'NOT ([booleanAttr] = 0)', ibmi: 'NOT ("booleanAttr" = 0)', sqlite3: 'NOT (`booleanAttr` = 0)', + oracle: `NOT ("booleanAttr" = 0)`, }, ); @@ -1036,6 +1049,7 @@ Caused by: "undefined" cannot be escaped`), mssql: 'NOT ([booleanAttr] = 1)', ibmi: 'NOT ("booleanAttr" = 1)', sqlite3: 'NOT (`booleanAttr` = 1)', + oracle: 'NOT ("booleanAttr" = 1)', }, ); @@ -1088,6 +1102,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `NOT (json_extract(\`data\`,'$.key') = '10')`, mariadb: `NOT (json_compact(json_extract(\`data\`,'$.key')) = '10')`, mysql: `NOT (json_extract(\`data\`,'$.key') = CAST('10' AS JSON))`, + oracle: `NOT (json_value("data",'$."key"') = '10')`, }, ); } @@ -2889,6 +2904,7 @@ Caused by: "undefined" cannot be escaped`), default: `[jsonAttr] = '"value"'`, mysql: `\`jsonAttr\` = CAST('"value"' AS JSON)`, mssql: `[jsonAttr] = N'"value"'`, + oracle: `"jsonAttr" = 'value'`, }, ); @@ -2939,6 +2955,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') = '"value"'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) = '"value"'`, mysql: `json_extract(\`jsonAttr\`,'$.nested') = CAST('"value"' AS JSON)`, + oracle: `json_value("jsonAttr",'$."nested"') = 'value'`, }, ); @@ -2956,6 +2973,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') = 'null'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) = 'null'`, mysql: `json_extract(\`jsonAttr\`,'$.nested') = CAST('null' AS JSON)`, + oracle: `json_value("jsonAttr",'$."nested"') = 'null'`, }, ); @@ -2966,6 +2984,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') IS NULL`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) IS NULL`, mysql: `json_extract(\`jsonAttr\`,'$.nested') IS NULL`, + oracle: `json_value("jsonAttr",'$."nested"') IS NULL`, }, ); @@ -2976,6 +2995,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') = 'null'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) = 'null'`, mysql: `json_extract(\`jsonAttr\`,'$.nested') = CAST('null' AS JSON)`, + oracle: `json_value("jsonAttr",'$."nested"') = 'null'`, }, ); @@ -2986,6 +3006,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') IS NULL`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) IS NULL`, mysql: `json_extract(\`jsonAttr\`,'$.nested') IS NULL`, + oracle: `json_value("jsonAttr",'$."nested"') IS NULL`, }, ); @@ -2994,6 +3015,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `'"value"' = json_extract(\`jsonAttr\`,'$.nested')`, mariadb: `'"value"' = json_compact(json_extract(\`jsonAttr\`,'$.nested'))`, mysql: `CAST('"value"' AS JSON) = json_extract(\`jsonAttr\`,'$.nested')`, + oracle: `'value' = json_value("jsonAttr",'$."nested"')`, }); testSql( @@ -3003,6 +3025,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested.twice') = '"value"'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested.twice')) = '"value"'`, mysql: `json_extract(\`jsonAttr\`,'$.nested.twice') = CAST('"value"' AS JSON)`, + oracle: `json_value("jsonAttr",'$."nested"."twice"') = 'value'`, }, ); @@ -3015,6 +3038,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') = '"value"'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) = '"value"'`, mysql: `json_extract(\`jsonAttr\`,'$.nested') = CAST('"value"' AS JSON)`, + oracle: `json_value("jsonAttr",'$."nested"') = 'value'`, }, ); @@ -3027,6 +3051,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested.twice') = '"value"'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested.twice')) = '"value"'`, mysql: `json_extract(\`jsonAttr\`,'$.nested.twice') = CAST('"value"' AS JSON)`, + oracle: `json_value("jsonAttr",'$."nested"."twice"') = 'value'`, }, ); @@ -3049,6 +3074,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') != '"value"'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) != '"value"'`, mysql: `json_extract(\`jsonAttr\`,'$.nested') != CAST('"value"' AS JSON)`, + oracle: `json_value("jsonAttr",'$."nested"') != 'value'`, }, ); @@ -3061,6 +3087,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') = '"value"'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) = '"value"'`, mysql: `json_extract(\`jsonAttr\`,'$.nested') = CAST('"value"' AS JSON)`, + oracle: `json_value("jsonAttr",'$."nested"') = 'value'`, }, ); @@ -3073,6 +3100,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`association\`.\`jsonAttr\`,'$.nested') = '"value"'`, mariadb: `json_compact(json_extract(\`association\`.\`jsonAttr\`,'$.nested')) = '"value"'`, mysql: `json_extract(\`association\`.\`jsonAttr\`,'$.nested') = CAST('"value"' AS JSON)`, + oracle: `json_value("association"."jsonAttr",'$."nested"') = 'value'`, }, ); @@ -3085,6 +3113,7 @@ Caused by: "undefined" cannot be escaped`), postgres: `CAST("jsonAttr"->'nested' AS STRING) = 'value'`, mariadb: `CAST(json_compact(json_extract(\`jsonAttr\`,'$.nested')) AS STRING) = 'value'`, 'sqlite3 mysql': `CAST(json_extract(\`jsonAttr\`,'$.nested') AS STRING) = 'value'`, + oracle: `CAST(json_value("jsonAttr",'$."nested"') AS STRING) = 'value'`, }, ); @@ -3107,6 +3136,7 @@ Caused by: "undefined" cannot be escaped`), postgres: `CAST("association"."jsonAttr"#>ARRAY['nested','deep']::VARCHAR(255)[] AS STRING) = 'value'`, mariadb: `CAST(json_compact(json_extract(\`association\`.\`jsonAttr\`,'$.nested.deep')) AS STRING) = 'value'`, 'sqlite3 mysql': `CAST(json_extract(\`association\`.\`jsonAttr\`,'$.nested.deep') AS STRING) = 'value'`, + oracle: `CAST(json_value("association"."jsonAttr",'$."nested"."deep"') AS STRING) = 'value'`, }, ); @@ -3118,6 +3148,7 @@ Caused by: "undefined" cannot be escaped`), postgres: `CAST("jsonAttr"->'nested' AS STRING) = 'value'`, mariadb: `CAST(json_compact(json_extract(\`jsonAttr\`,'$.nested')) AS STRING) = 'value'`, 'sqlite3 mysql': `CAST(json_extract(\`jsonAttr\`,'$.nested') AS STRING) = 'value'`, + oracle: `CAST(json_value("jsonAttr",'$."nested"') AS STRING) = 'value'`, }, ); @@ -3128,6 +3159,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested.attribute') = '4'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested.attribute')) = '4'`, mysql: `json_extract(\`jsonAttr\`,'$.nested.attribute') = CAST('4' AS JSON)`, + oracle: `json_value("jsonAttr",'$."nested"."attribute"') = '4'`, }, ); @@ -3139,6 +3171,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$."0"') = '4'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$."0"')) = '4'`, mysql: `json_extract(\`jsonAttr\`,'$."0"') = CAST('4' AS JSON)`, + oracle: `json_value("jsonAttr",'$[0]') = '4'`, }, ); @@ -3152,6 +3185,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$[0]') = '4'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$[0]')) = '4'`, mysql: `json_extract(\`jsonAttr\`,'$[0]') = CAST('4' AS JSON)`, + oracle: `json_value("jsonAttr",'$[0]') = '4'`, }, ); @@ -3162,6 +3196,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$."0".attribute') = '4'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$."0".attribute')) = '4'`, mysql: `json_extract(\`jsonAttr\`,'$."0".attribute') = CAST('4' AS JSON)`, + oracle: `json_value("jsonAttr",'$[0]."attribute"') = '4'`, }, ); @@ -3173,6 +3208,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$."hyphenated-key"') = '4'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$."hyphenated-key"')) = '4'`, mysql: `json_extract(\`jsonAttr\`,'$."hyphenated-key"') = CAST('4' AS JSON)`, + oracle: `json_value("jsonAttr",'$."hyphenated-key"') = '4'`, }, ); @@ -3184,6 +3220,7 @@ Caused by: "undefined" cannot be escaped`), mysql: `json_extract(\`jsonAttr\`,'$."a\\')) AS DECIMAL) = 1 DELETE YOLO INJECTIONS; -- "') = CAST('1' AS JSON)`, sqlite3: `json_extract(\`jsonAttr\`,'$."a'')) AS DECIMAL) = 1 DELETE YOLO INJECTIONS; -- "') = '1'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$."a\\')) AS DECIMAL) = 1 DELETE YOLO INJECTIONS; -- "')) = '1'`, + oracle: `json_value("jsonAttr",'$."a'')) AS DECIMAL) = 1 DELETE YOLO INJECTIONS; -- "') = '1'`, }, ); @@ -3196,6 +3233,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$[0].nested.attribute') = '4'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$[0].nested.attribute')) = '4'`, mysql: `json_extract(\`jsonAttr\`,'$[0].nested.attribute') = CAST('4' AS JSON)`, + oracle: `json_value("jsonAttr",'$[0]."nested"."attribute"') = '4'`, }, ); @@ -3207,6 +3245,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`aliased_json\`,'$.nested.attribute') = '4'`, mariadb: `json_compact(json_extract(\`aliased_json\`,'$.nested.attribute')) = '4'`, mysql: `json_extract(\`aliased_json\`,'$.nested.attribute') = CAST('4' AS JSON)`, + oracle: `json_value("aliased_json",'$."nested"."attribute"') = '4'`, }, ); } @@ -4002,6 +4041,7 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`col\`,'$.jsonPath') = '"value"'`, mariadb: `json_compact(json_extract(\`col\`,'$.jsonPath')) = '"value"'`, mysql: `json_extract(\`col\`,'$.jsonPath') = CAST('"value"' AS JSON)`, + oracle: `json_value("col",'$."jsonPath"') = 'value'`, }); } }); diff --git a/packages/core/test/unit/transaction.test.ts b/packages/core/test/unit/transaction.test.ts index f181001af030..f42c6b8e19d9 100644 --- a/packages/core/test/unit/transaction.test.ts +++ b/packages/core/test/unit/transaction.test.ts @@ -51,6 +51,7 @@ describe('Transaction', () => { all: ['START TRANSACTION'], snowflake: ['START TRANSACTION NAME "123"'], sqlite3: ['BEGIN DEFERRED TRANSACTION'], + oracle: ['BEGIN TRANSACTION'], }; await sequelize.transaction(async () => { @@ -65,6 +66,7 @@ describe('Transaction', () => { all: ['SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED', 'START TRANSACTION'], postgres: ['START TRANSACTION', 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED'], sqlite3: ['BEGIN DEFERRED TRANSACTION', 'PRAGMA read_uncommitted = 1'], + oracle: ['BEGIN TRANSACTION', 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED'], }; try { diff --git a/packages/core/test/unit/utils/sql.test.ts b/packages/core/test/unit/utils/sql.test.ts index bfb1bd45915a..1fc076a7a4f1 100644 --- a/packages/core/test/unit/utils/sql.test.ts +++ b/packages/core/test/unit/utils/sql.test.ts @@ -32,10 +32,13 @@ describe('mapBindParameters', () => { postgres: `SELECT "$id" FROM users WHERE id = '$id' OR id = $1 OR id = '''$id'''`, sqlite3: `SELECT \`$id\` FROM users WHERE id = '$id' OR id = $id OR id = '''$id'''`, mssql: `SELECT [$id] FROM users WHERE id = '$id' OR id = @id OR id = '''$id'''`, + oracle: `SELECT "$id" FROM users WHERE id = '$id' OR id = :id OR id = '''$id'''`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; + } else if (dialect.name === 'oracle') { + expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['id']); } @@ -52,10 +55,13 @@ describe('mapBindParameters', () => { postgres: `SELECT * FROM users WHERE id = $1`, sqlite3: `SELECT * FROM users WHERE id = $1`, mssql: `SELECT * FROM users WHERE id = @1`, + oracle: `SELECT * FROM users WHERE id = :1`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; + } else if (dialect.name === 'oracle') { + expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['1']); } @@ -71,6 +77,7 @@ describe('mapBindParameters', () => { postgres: `SELECT * FROM users WHERE id = $1::string`, sqlite3: `SELECT * FROM users WHERE id = $param::string`, mssql: `SELECT * FROM users WHERE id = @param::string`, + oracle: `SELECT * FROM users WHERE id = :param::string`, }); }); @@ -82,6 +89,7 @@ describe('mapBindParameters', () => { postgres: `SELECT * FROM users WHERE json_col->>$1`, sqlite3: `SELECT * FROM users WHERE json_col->>$key`, mssql: `SELECT * FROM users WHERE json_col->>@key`, + oracle: `SELECT * FROM users WHERE json_col->>:key`, }); }); @@ -94,6 +102,7 @@ describe('mapBindParameters', () => { sqlite3: `SELECT * FROM users WHERE id = $id;`, mssql: `SELECT * FROM users WHERE id = @id;`, ibmi: `SELECT * FROM users WHERE id = ?;`, // 'default' removes the ; for ibmi + oracle: `SELECT * FROM users WHERE id = :id;`, }); }); @@ -121,10 +130,13 @@ describe('mapBindParameters', () => { postgres: `SELECT * FROM users WHERE id = $1`, sqlite3: `SELECT * FROM users WHERE id = $a`, mssql: `SELECT * FROM users WHERE id = @a`, + oracle: `SELECT * FROM users WHERE id = :a`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; + } else if (dialect.name === 'oracle') { + expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['a']); } @@ -143,12 +155,15 @@ describe('mapBindParameters', () => { postgres: `SELECT * FROM users WHERE id = fn($1) OR id = fn('a',$1) OR id=$1 OR id$id = 1 OR id = $1`, sqlite3: `SELECT * FROM users WHERE id = fn($id) OR id = fn('a',$id) OR id=$id OR id$id = 1 OR id = $id`, mssql: `SELECT * FROM users WHERE id = fn(@id) OR id = fn('a',@id) OR id=@id OR id$id = 1 OR id = @id`, + oracle: `SELECT * FROM users WHERE id = fn(:id) OR id = fn('a',:id) OR id=:id OR id$id = 1 OR id = :id`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; } else if (dialect.name === 'postgres') { expect(bindOrder).to.deep.eq(['id']); + } else if (dialect.name === 'oracle') { + expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['id', 'id', 'id', 'id']); } @@ -166,6 +181,8 @@ describe('mapBindParameters', () => { if (supportsNamedParameters) { expect(bindOrder).to.be.null; + } else if (dialect.name === 'oracle') { + expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq([]); } @@ -183,6 +200,8 @@ describe('mapBindParameters', () => { if (supportsNamedParameters) { expect(bindOrder).to.be.null; + } else if (dialect.name === 'oracle') { + expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq([]); } @@ -196,10 +215,13 @@ describe('mapBindParameters', () => { postgres: `SELECT z$$ $1 x$$ * FROM users`, sqlite3: `SELECT z$$ $id x$$ * FROM users`, mssql: `SELECT z$$ @id x$$ * FROM users`, + oracle: `SELECT z$$ :id x$$ * FROM users`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; + } else if (dialect.name === 'oracle') { + expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['id']); } @@ -216,10 +238,13 @@ describe('mapBindParameters', () => { postgres: `SELECT $$ abc $$ AS string FROM users WHERE id = $1`, sqlite3: `SELECT $$ abc $$ AS string FROM users WHERE id = $id`, mssql: `SELECT $$ abc $$ AS string FROM users WHERE id = @id`, + oracle: `SELECT $$ abc $$ AS string FROM users WHERE id = :id`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; + } else if (dialect.name === 'oracle') { + expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['id']); } @@ -316,10 +341,13 @@ SELECT * FROM users WHERE id = e'\\' $id' OR id = $id`), postgres: `SELECT * FROM users WHERE id = '\\\\' OR id = $1`, sqlite3: `SELECT * FROM users WHERE id = '\\\\' OR id = $id`, mssql: `SELECT * FROM users WHERE id = '\\\\' OR id = @id`, + oracle: `SELECT * FROM users WHERE id = '\\\\' OR id = :id`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; + } else if (dialect.name === 'oracle') { + expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['id']); } @@ -366,6 +394,10 @@ SELECT * FROM users WHERE id = '\\\\\\' $id' OR id = $id`), SELECT * FROM users -- WHERE id = $id WHERE id = @id `, + oracle: ` + SELECT * FROM users -- WHERE id = $id + WHERE id = :id + `, }); }); @@ -422,6 +454,12 @@ SELECT * FROM users WHERE id = '\\\\\\' $id' OR id = $id`), */ WHERE id = @id `, + oracle: ` + SELECT * FROM users /* + WHERE id = $id + */ + WHERE id = :id + `, }); }); }); diff --git a/packages/oracle/.eslintrc.js b/packages/oracle/.eslintrc.js new file mode 100644 index 000000000000..e13dec291282 --- /dev/null +++ b/packages/oracle/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + parserOptions: { + project: [`${__dirname}/tsconfig.json`], + }, +}; diff --git a/packages/oracle/package.json b/packages/oracle/package.json new file mode 100644 index 000000000000..f25bf32094eb --- /dev/null +++ b/packages/oracle/package.json @@ -0,0 +1,53 @@ +{ + "bugs": "https://github.com/sequelize/sequelize/issues", + "description": "Oracle Database Connector for Sequelize", + "exports": { + ".": { + "import": { + "types": "./lib/index.d.mts", + "default": "./lib/index.mjs" + }, + "require": { + "types": "./lib/index.d.ts", + "default": "./lib/index.js" + } + } + }, + "main": "./lib/index.js", + "types": "./lib/index.d.ts", + "sideEffects": false, + "homepage": "https://sequelize.org", + "license": "MIT", + "name": "@sequelize/oracle", + "repository": "https://github.com/sequelize/sequelize", + "scripts": { + "build": "../../build-packages.mjs oracle", + "test": "concurrently \"npm:test-*\"", + "test-typings": "tsc --noEmit --project tsconfig.json", + "test-unit": "mocha src/**/*.test.ts", + "test-exports": "../../dev/sync-exports.mjs ./src --check-outdated", + "sync-exports": "../../dev/sync-exports.mjs ./src" + }, + "type": "commonjs", + "version": "7.0.0-alpha.40", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@sequelize/core": "workspace:*", + "@sequelize/utils": "workspace:*", + "@types/oracledb": "^6.3", + "dayjs": "^1.11.10", + "lodash": "4.17.21", + "oracledb": "6.5", + "semver": "7.6.0" + }, + "devDependencies": { + "@types/chai": "4.3.14", + "@types/mocha": "10.0.6", + "@types/sinon": "17.0.3", + "chai": "4.4.1", + "mocha": "10.4.0", + "sinon": "18.0.0" + } +} diff --git a/packages/oracle/src/_internal/data-types-overrides.ts b/packages/oracle/src/_internal/data-types-overrides.ts new file mode 100644 index 000000000000..e65112a2490e --- /dev/null +++ b/packages/oracle/src/_internal/data-types-overrides.ts @@ -0,0 +1,427 @@ +// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +import type { AbstractDialect, BindParamOptions } from '@sequelize/core'; +import type { AcceptedDate } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/data-types.js'; +import * as BaseTypes from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/data-types.js'; +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; + +// eslint-disable-next-line @typescript-eslint/consistent-type-imports +type Lib = typeof import('oracledb'); + +dayjs.extend(utc); + +// legacy support +let Moment: any; +try { + // eslint-disable-next-line import/no-extraneous-dependencies + Moment = require('moment'); +} catch { + /* ignore */ +} + +function isMoment(value: any): boolean { + return Moment?.isMoment(value) ?? false; +} + +export class STRING extends BaseTypes.STRING { + protected _checkOptionSupport(dialect: AbstractDialect) { + super._checkOptionSupport(dialect); + // @ts-expect-error -- Object is possibly 'null'. + if (this.options.length > 4000 || (this.options.binary && this.options.length > 2000)) { + dialect.warnDataTypeIssue( + `Oracle supports length up to 32764 bytes or characters; Be sure that your administrator has extended the MAX_STRING_SIZE parameter. Check https://docs.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-7B72E154-677A-4342-A1EA-C74C1EA928E6`, + ); + } + } + + toSql() { + if (!this.options.binary) { + return `NVARCHAR2(${this.options.length ?? 255})`; + } + + return `RAW(${this.options.length ?? 255})`; + } + + _getBindDef(oracledb: Lib) { + if (this.options.binary) { + return { type: oracledb.DB_TYPE_RAW, maxSize: this.options.length || 255 }; + } + + return { type: oracledb.DB_TYPE_VARCHAR, maxSize: this.options.length || 255 }; + } +} + +export class BOOLEAN extends BaseTypes.BOOLEAN { + toSql() { + return 'CHAR(1)'; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_CHAR, maxSize: 1 }; + } + + escape(value: boolean): string { + return value ? '1' : '0'; + } + + toBindableValue(value: boolean): unknown { + return value === true ? '1' : value === false ? '0' : value; + } + + parseDatabaseValue(value: unknown): boolean { + if (value === '1' || value === 'true') { + return true; + } + + return false; + } +} + +export class UUID extends BaseTypes.UUID { + toSql() { + return 'VARCHAR2(36)'; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_VARCHAR, maxSize: 36 }; + } +} + +export class NOW extends BaseTypes.NOW { + toSql(): string { + return 'SYSDATE'; + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + toBindableValue(value: never): unknown { + return 'SYSDATE'; + } +} + +export class ENUM extends BaseTypes.ENUM { + toSql() { + return 'VARCHAR2(512)'; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_VARCHAR, maxSize: 512 }; + } +} + +export class TEXT extends BaseTypes.TEXT { + toSql() { + return 'CLOB'; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_CLOB }; + } +} + +export class CHAR extends BaseTypes.CHAR { + protected _checkOptionSupport(dialect: AbstractDialect) { + super._checkOptionSupport(dialect); + if (this.options.binary) { + dialect.warnDataTypeIssue('Oracle CHAR.BINARY datatype is not of Fixed Length.'); + } + } + + toSql() { + if (this.options.binary) { + return `RAW(${this.options.length ?? 255})`; + } + + return super.toSql(); + } + + _getBindDef(oracledb: Lib) { + if (this.options.binary) { + return { type: oracledb.DB_TYPE_RAW, maxSize: this.options.length }; + } + + return { type: oracledb.DB_TYPE_CHAR, maxSize: this.options.length }; + } +} + +export class DATE extends BaseTypes.DATE { + toSql() { + return 'TIMESTAMP WITH LOCAL TIME ZONE'; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_TIMESTAMP_LTZ }; + } + + toBindableValue(date: AcceptedDate) { + const format = 'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM'; + date = this._applyTimezone(date); + + const formatedDate = date.format('YYYY-MM-DD HH:mm:ss.SSS Z'); + + return `TO_TIMESTAMP_TZ('${formatedDate}', '${format}')`; + } + + /** + * avoids appending TO_TIMESTAMP_TZ in toBindableValue() + * + * @override + */ + getBindParamSql(value: AcceptedDate, options: BindParamOptions): string { + if (dayjs.isDayjs(value) || isMoment(value)) { + return options.bindParam(this._sanitize(value)); + } + + return options.bindParam(value); + } + + _sanitize(value: any) { + return new Date(value); + } +} + +type AcceptedNumber = number | bigint | boolean | string | null; + +export class DECIMAL extends BaseTypes.DECIMAL { + toSql() { + let result: string = 'NUMBER'; + if (!this.options.precision) { + return result; + } + + result += `(${this.options.precision}`; + + if (this.options.scale) { + result += `, ${this.options.scale}`; + } + + result += ')'; + + return result; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_NUMBER }; + } + + // Oracle treats DECIMAL as NUMBER(precision, scale). + sanitize(value: AcceptedNumber): AcceptedNumber { + if (typeof value === 'bigint') { + return value.toString(); + } + + return value; + } +} + +export class TINYINT extends BaseTypes.TINYINT { + toSql() { + return 'NUMBER(3)'; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_NUMBER }; + } +} + +export class SMALLINT extends BaseTypes.SMALLINT { + toSql() { + if (this.options.length) { + return `NUMBER(${this.options.length},0)`; + } + + return 'SMALLINT'; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_NUMBER }; + } +} + +export class MEDIUMINT extends BaseTypes.MEDIUMINT { + toSql() { + return 'NUMBER(8)'; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_NUMBER }; + } +} + +export class INTEGER extends BaseTypes.INTEGER { + toSql(): string { + if (this.options.length) { + return `NUMBER(${this.options.length},0)`; + } + + return 'INTEGER'; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_NUMBER }; + } +} + +/** + * @deprecated use FLOAT. + */ +export class REAL extends BaseTypes.REAL { + toSql() { + return 'BINARY_DOUBLE'; + } + + // https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-0BA2E065-8006-426C-A3CB-1F6B0C8F283C + toBindableValue(value: any) { + if (value === Number.POSITIVE_INFINITY) { + return 'inf'; + } + + if (value === Number.NEGATIVE_INFINITY) { + return '-inf'; + } + + return value; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_BINARY_DOUBLE }; + } +} + +export class BIGINT extends BaseTypes.BIGINT { + protected _checkOptionSupport(dialect: AbstractDialect) { + super._checkOptionSupport(dialect); + if (this.options.length || this.options.zerofill) { + dialect.warnDataTypeIssue(`${dialect.name} does not support BIGINT with options.`); + delete this.options.length; + this.options.zerofill = undefined; + } + } + + toSql(): string { + return 'NUMBER(19, 0)'; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_NUMBER }; + } + + sanitize(value: any) { + if (typeof value === 'bigint' || typeof value === 'number') { + return value.toString(); + } + + return value; + } +} + +export class FLOAT extends BaseTypes.FLOAT { + toSql() { + return 'BINARY_FLOAT'; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_BINARY_FLOAT }; + } +} + +export class BLOB extends BaseTypes.BLOB { + toSql(): string { + return 'BLOB'; + } + // check for hexify + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_BLOB }; + } +} + +export class JSON extends BaseTypes.JSON { + toSql(): string { + return 'BLOB'; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_BLOB }; + } + + toBindableValue(value: any): string { + if (value === null) { + const sequelize = this._getDialect().sequelize; + + const isExplicit = sequelize.options.nullJsonStringification === 'explicit'; + if (isExplicit) { + throw new Error( + `Attempted to insert the JavaScript null into a JSON column, but the "nullJsonStringification" option is set to "explicit", so Sequelize cannot decide whether to use the SQL NULL or the JSON 'null'. Use the SQL_NULL or JSON_NULL variable instead, or set the option to a different value. See https://sequelize.org/docs/v7/querying/json/ for details.`, + ); + } + } + + return typeof value === 'string' ? value : globalThis.JSON.stringify(value); + } + + getBindParamSql(value: any, options: BindParamOptions): any { + return options.bindParam(Buffer.from(globalThis.JSON.stringify(value))); + } +} + +export class DOUBLE extends BaseTypes.DOUBLE { + protected getNumberSqlTypeName(): string { + return 'DOUBLE PRECISION'; + } + + protected _checkOptionSupport(dialect: AbstractDialect): void { + super._checkOptionSupport(dialect); + + if (this.options.zerofill) { + dialect.warnDataTypeIssue( + `${dialect.name}: ${this.getDataTypeId} doesn't support zerofill option.`, + ); + } + } + + toSql(): string { + return 'BINARY_DOUBLE'; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_BINARY_DOUBLE }; + } +} + +export class DATEONLY extends BaseTypes.DATEONLY { + toBindableValue(date: AcceptedDate) { + if (date) { + const format = 'YYYY/MM/DD'; + + return this.escape(`TO_DATE('${date}','${format}')`); + } + + return this.escape(date); + } + + parseDatabaseValue(value: any) { + if (value) { + return dayjs.utc(value).format('YYYY-MM-DD'); + } + + return value; + } + + _getBindDef(oracledb: Lib) { + return { type: oracledb.DB_TYPE_DATE }; + } + + /** + * avoids appending TO_DATE in toBindableValue() + * + * @override + */ + getBindParamSql(value: AcceptedDate, options: BindParamOptions): string { + if (typeof value === 'string') { + return options.bindParam(new Date(value)); + } + + return options.bindParam(value); + } +} diff --git a/packages/oracle/src/connection-manager.ts b/packages/oracle/src/connection-manager.ts new file mode 100644 index 000000000000..7a074ff25df3 --- /dev/null +++ b/packages/oracle/src/connection-manager.ts @@ -0,0 +1,181 @@ +// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +import type { AbstractConnection, ConnectionOptions } from '@sequelize/core'; +import { + AbstractConnectionManager, + AccessDeniedError, + ConnectionError, + ConnectionRefusedError, + ConnectionTimedOutError, + HostNotReachableError, + InvalidConnectionError, +} from '@sequelize/core'; +import { logger } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/logger.js'; +import type { Connection as oracledbConnection } from 'oracledb'; +import oracledb from 'oracledb'; +import type { OracleDialect } from './dialect.js'; + +export type oracledbModule = typeof oracledb; + +const debug = logger.debugContext('connection:oracle'); + +export interface OracleConnection extends oracledbConnection, AbstractConnection { + on(event: 'error', listener: (err: any) => void): this; +} + +export interface OracleConnectionOptions extends oracledb.ConnectionAttributes { + database?: string; + + host?: string; + + oracleOptions?: object; + + port?: number | string; +} + +export class OracleConnectionManager extends AbstractConnectionManager< + OracleDialect, + OracleConnection +> { + lib: typeof oracledb; + constructor(dialect: OracleDialect) { + super(dialect); + this.lib = oracledb; + } + + buildConnectString(config: ConnectionOptions) { + if (!config.host || config.host.length === 0) { + return config.database; + } + + let connectString = config.host; + if (config.port) { + connectString += `:${config.port}`; + } else { + connectString += ':1521'; + } + + if (config.database && config.database.length > 0) { + connectString += `/${config.database}`; + } + + return connectString; + } + + /** + * Method for initializing the lib + * + * @param config + */ + extendLib(config: ConnectionOptions) { + if (config.oracleOptions) { + if ('maxRows' in config.oracleOptions) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error add maxRow + oracledb.maxRows = config.oracleOptions.maxRows; + } + + if ('fetchAsString' in config.oracleOptions) { + // @ts-expect-error -- add fetchAsString + oracledb.fetchAsString = config.oracleOptions.fetchAsString; + } + } + + oracledb.fetchAsString = [oracledb.CLOB]; + + // Retrieve BLOB always as Buffer. + oracledb.fetchAsBuffer = [oracledb.BLOB]; + } + + async connect(config: ConnectionOptions): Promise { + this.extendLib(config); + this.lib = oracledb; + const connectionConfig: OracleConnectionOptions = { + username: config.username, + password: config.password, + connectString: this.buildConnectString(config), + ...config.oracleOptions, + }; + + try { + const connection: OracleConnection = (await this.lib.getConnection( + connectionConfig, + )) as OracleConnection; + + debug('connection acquired'); + connection.on('error', error => { + switch (error.code) { + case 'ESOCKET': + case 'ECONNRESET': + case 'EPIPE': + case 'PROTOCOL_CONNECTION_LOST': + void this.sequelize.pool.destroy(connection); + break; + default: + } + }); + + return connection; + } catch (error: any) { + let errorCode = error.message.split(':'); + errorCode = errorCode[0]; + + switch (errorCode) { + case 'ORA-12560': // ORA-12560: TNS: Protocol Adapter Error + case 'ORA-12154': // ORA-12154: TNS: Could not resolve the connect identifier specified + case 'ORA-12505': // ORA-12505: TNS: Listener does not currently know of SID given in connect descriptor + case 'ORA-12514': // ORA-12514: TNS: Listener does not currently know of service requested in connect descriptor + case 'NJS-511': // NJS-511: connection refused + case 'NJS-516': // NJS-516: No Config Dir + case 'NJS-517': // NJS-517: TNS Entry not found + case 'NJS-520': // NJS-520: TNS Names File missing + throw new ConnectionRefusedError(error); + case 'ORA-28000': // ORA-28000: Account locked + case 'ORA-28040': // ORA-28040: No matching authentication protocol + case 'ORA-01017': // ORA-01017: invalid username/password; logon denied + case 'NJS-506': // NJS-506: TLS Auth Failure + throw new AccessDeniedError(error); + case 'ORA-12541': // ORA-12541: TNS: No listener + case 'NJS-503': // NJS-503: Connection Incomplete + case 'NJS-508': // NJS-508: TLS HOST MATCH Failure + case 'NJS-507': // NJS-507: TLS DN MATCH Failure + throw new HostNotReachableError(error); + case 'NJS-512': // NJS-512: Invalid Connect String Parameters + case 'NJS-515': // NJS-515: Invalid EZCONNECT Syntax + case 'NJS-518': // NJS-518: Invald ServiceName + case 'NJS-519': // NJS-519: Invald SID + throw new InvalidConnectionError(error); + case 'ORA-12170': // ORA-12170: TNS: Connect Timeout occurred + case 'NJS-510': // NJS-510: Connect Timeout occurred + throw new ConnectionTimedOutError(error); + default: + throw new ConnectionError(error); + } + } + } + + async disconnect(connection: OracleConnection) { + if (!connection.isHealthy()) { + debug('connection tried to disconnect but was already at CLOSED state'); + + return; + } + + await new Promise((resolve, reject) => { + connection.close(error => { + if (error) { + // eslint-disable-next-line prefer-promise-reject-errors + return void reject(); + } + + resolve(); + + return undefined; + }); + }); + } + + validate(connection: OracleConnection): boolean { + return connection && connection.isHealthy(); + } +} diff --git a/packages/oracle/src/dialect.ts b/packages/oracle/src/dialect.ts new file mode 100644 index 000000000000..52e88a20f1c3 --- /dev/null +++ b/packages/oracle/src/dialect.ts @@ -0,0 +1,192 @@ +// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +import type { Sequelize } from '@sequelize/core'; +import { AbstractDialect } from '@sequelize/core'; +import type { SupportableNumericOptions } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/dialect.js'; +import { createNamedParamBindCollector } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/sql.js'; +import { getSynchronizedTypeKeys } from '@sequelize/utils'; +import * as DataTypes from './_internal/data-types-overrides'; +import { OracleConnectionManager } from './connection-manager'; +import type { OracleConnectionOptions, oracledbModule } from './connection-manager.js'; +import { OracleQueryGenerator } from './query-generator.js'; +import { OracleQueryInterface } from './query-interface.js'; +import { OracleQuery } from './query.js'; + +export interface OracleDialectOptions { + /** + * The oracledb module to user. + */ + oracledbModule?: oracledbModule; +} + +const CONNECTION_OPTION_NAMES = getSynchronizedTypeKeys({ + database: undefined, + host: undefined, + oracleOptions: undefined, + port: undefined, + accessToken: undefined, + accessTokenConfig: undefined, + connectString: undefined, + connectionString: undefined, + walletPassword: undefined, + walletLocation: undefined, + edition: undefined, + events: undefined, + externalAuth: undefined, + matchAny: undefined, + newPassword: undefined, + password: undefined, + sslAllowWeakDNMatch: undefined, + httpsProxy: undefined, + httpsProxyPort: undefined, + debugJdwp: undefined, + retryCount: undefined, + retryDelay: undefined, + connectTimeout: undefined, + transportConnectTimeout: undefined, + expireTime: undefined, + sdu: undefined, + connectionIdPrefix: undefined, + configDir: undefined, + sourceRoute: undefined, + sslServerCertDN: undefined, + sslServerDNMatch: undefined, + poolAlias: undefined, + privilege: undefined, + shardingKey: undefined, + stmtCacheSize: undefined, + superShardingKey: undefined, + tag: undefined, + user: undefined, + username: undefined, +}); + +const numericOptions: SupportableNumericOptions = { + zerofill: false, + unsigned: true, +}; + +export class OracleDialect extends AbstractDialect { + static readonly supports = AbstractDialect.extendSupport({ + 'VALUES ()': true, + 'LIMIT ON UPDATE': true, + lock: false, + forShare: 'LOCK IN SHARE MODE', + index: { + collate: false, + length: false, + parser: false, + type: false, + using: false, + }, + constraints: { + restrict: false, + onUpdate: false, + }, + returnValues: false, + returnIntoValues: true, + 'ORDER NULLS': true, + schemas: true, + inserts: { + updateOnDuplicate: false, + }, + indexViaAlter: false, + dataTypes: { + COLLATE_BINARY: true, + GEOMETRY: false, + JSON: true, + INTS: numericOptions, + DOUBLE: numericOptions, + DECIMAL: { unconstrained: true }, + TIME: { + precision: false, + }, + }, + jsonOperations: true, + jsonExtraction: { + quoted: true, + }, + dropTable: { + cascade: true, + }, + renameTable: { + changeSchema: false, + }, + delete: { + limit: true, + }, + startTransaction: { + useBegin: true, + }, + upserts: true, + bulkDefault: true, + topLevelOrderByRequired: true, + }); + + readonly connectionManager: OracleConnectionManager; + readonly queryGenerator: OracleQueryGenerator; + readonly queryInterface: OracleQueryInterface; + readonly Query = OracleQuery; + readonly dataTypesDocumentationUrl = + 'https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/Data-Types.html'; + + constructor(sequelize: Sequelize, options: OracleDialectOptions) { + super({ + dataTypesDocumentationUrl: + 'https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/Data-Types.html', + minimumDatabaseVersion: '18.0.0', + identifierDelimiter: '"', + name: 'oracle', + options, + sequelize, + dataTypeOverrides: DataTypes, + }); + + this.connectionManager = new OracleConnectionManager(this); + // this.connectionManager.initPools(); + this.queryGenerator = new OracleQueryGenerator(this); + this.queryInterface = new OracleQueryInterface(this); + } + + parseConnectionUrl(): OracleConnectionOptions { + throw new Error( + 'The "url" option is not supported by the Db2 dialect. Instead, please use the "odbcOptions" option.', + ); + } + + getDefaultSchema(): string { + return this.sequelize.options.replication.write.username?.toUpperCase() ?? ''; + } + + createBindCollector() { + return createNamedParamBindCollector(':'); + } + + static getDefaultPort(): number { + return 1521; + } + + escapeString(val: string): string { + if (val.startsWith('TO_TIMESTAMP') || val.startsWith('TO_DATE')) { + return val; + } + + val = val.replaceAll("'", "''"); + + return `'${val}'`; + } + + escapeBuffer(buffer: Buffer): string { + const hex = buffer.toString('hex'); + + return `'${hex}'`; + } + + static getSupportedOptions() { + return []; + } + + static getSupportedConnectionOptions() { + return CONNECTION_OPTION_NAMES; + } +} diff --git a/packages/oracle/src/index.mjs b/packages/oracle/src/index.mjs new file mode 100644 index 000000000000..93a13199ae04 --- /dev/null +++ b/packages/oracle/src/index.mjs @@ -0,0 +1,7 @@ +import Pkg from './index.js'; + +export const OracleConnectionManager = Pkg.OracleConnectionManager; +export const OracleDialect = Pkg.OracleDialect; +export const OracleQueryGenerator = Pkg.OracleQueryGenerator; +export const OracleQueryInterface = Pkg.OracleQueryInterface; +export const OracleQuery = Pkg.OracleQuery; diff --git a/packages/oracle/src/index.ts b/packages/oracle/src/index.ts new file mode 100644 index 000000000000..77a8f97c40cc --- /dev/null +++ b/packages/oracle/src/index.ts @@ -0,0 +1,7 @@ +/** Generated File, do not modify directly. Run "yarn sync-exports" in the folder of the package instead */ + +export * from './connection-manager.js'; +export * from './dialect.js'; +export * from './query-generator.js'; +export * from './query-interface.js'; +export * from './query.js'; diff --git a/packages/oracle/src/query-generator-typescript.internal.ts b/packages/oracle/src/query-generator-typescript.internal.ts new file mode 100644 index 000000000000..2295ceff1c29 --- /dev/null +++ b/packages/oracle/src/query-generator-typescript.internal.ts @@ -0,0 +1,336 @@ +// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +import type { + BulkDeleteQueryOptions, + CreateSchemaQueryOptions, + RemoveColumnQueryOptions, + RemoveConstraintQueryOptions, + RemoveIndexQueryOptions, + RenameTableQueryOptions, + TableOrModel, + TruncateTableQueryOptions, +} from '@sequelize/core'; +import { AbstractQueryGenerator, IsolationLevel } from '@sequelize/core'; +import { + CREATE_SCHEMA_QUERY_SUPPORTABLE_OPTIONS, + REMOVE_COLUMN_QUERY_SUPPORTABLE_OPTIONS, + REMOVE_INDEX_QUERY_SUPPORTABLE_OPTIONS, + RENAME_TABLE_QUERY_SUPPORTABLE_OPTIONS, + TRUNCATE_TABLE_QUERY_SUPPORTABLE_OPTIONS, +} from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-generator-typescript.js'; +import type { TableNameWithSchema } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-interface.js'; +import { rejectInvalidOptions } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/check.js'; +import { joinSQLFragments } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/join-sql-fragments.js'; +import { + extractModelDefinition, + isModelStatic, +} from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/model-utils.js'; +import { EMPTY_SET } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/object.js'; +import { generateIndexName } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/string.js'; +import type { OracleDialect } from './dialect.js'; +import { OracleQueryGeneratorInternal } from './query-generator.internal.js'; + +export class OracleQueryGeneratorTypeScript extends AbstractQueryGenerator { + readonly #internals: OracleQueryGeneratorInternal; + + constructor( + dialect: OracleDialect, + internals: OracleQueryGeneratorInternal = new OracleQueryGeneratorInternal(dialect), + ) { + super(dialect, internals); + + this.#internals = internals; + } + + describeTableQuery(tableName: TableOrModel) { + const table = this.extractTableDetails(tableName); + const currTableName = this.getCatalogName(table.tableName); + const schema = this.getCatalogName(table.schema); + + // name, type, datalength (except number / nvarchar), datalength varchar, datalength number, nullable, default value, primary ? + return [ + 'SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type ', + 'FROM all_tab_columns atc ', + 'LEFT OUTER JOIN ', + '(SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ', + 'ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) ', + schema ? `WHERE (atc.OWNER = ${this.escape(schema)}) ` : 'WHERE atc.OWNER = USER ', + `AND (atc.TABLE_NAME = ${this.escape(currTableName)})`, + 'ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC', + ].join(''); + } + + removeIndexQuery( + tableName: TableOrModel, + indexNameOrAttributes: string | string[], + options: RemoveIndexQueryOptions, + ) { + if (options) { + rejectInvalidOptions( + 'removeIndexQuery', + this.dialect, + REMOVE_INDEX_QUERY_SUPPORTABLE_OPTIONS, + EMPTY_SET, + options, + ); + } + + let indexName: string; + if (Array.isArray(indexNameOrAttributes)) { + const table = this.extractTableDetails(tableName); + indexName = generateIndexName(table, { fields: indexNameOrAttributes }); + } else { + indexName = indexNameOrAttributes; + } + + return `DROP INDEX ${this.quoteIdentifier(indexName)}`; + } + + /** + * Returns the value as it is stored in the Oracle DB + * + * @param value + */ + getCatalogName(value: string | undefined) { + if (value && this.options.quoteIdentifiers === false) { + const quotedValue = this.quoteIdentifier(value); + if (quotedValue === value) { + value = value.toUpperCase(); + } + } + + return value; + } + + showIndexesQuery(table: TableNameWithSchema) { + const [tableName, owner] = this.getSchemaNameAndTableName(table); + const sql = [ + 'SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type ', + 'FROM all_ind_columns i ', + 'INNER JOIN all_indexes u ', + 'ON (u.table_name = i.table_name AND u.index_name = i.index_name) ', + 'LEFT OUTER JOIN all_constraints c ', + 'ON (c.table_name = i.table_name AND c.index_name = i.index_name) ', + `WHERE i.table_name = ${this.escape(tableName)}`, + ' AND u.table_owner = ', + owner ? this.escape(owner) : 'USER', + ' ORDER BY index_name, column_position', + ]; + + return sql.join(''); + } + + /** + * Returns the tableName and schemaName as it is stored the Oracle DB + * + * @param table + */ + getSchemaNameAndTableName(table: any) { + table = this.extractTableDetails(table); + const tableName = this.getCatalogName(table.tableName || table); + const schemaName = this.getCatalogName(table.schema); + + return [tableName, schemaName]; + } + + removeConstraintQuery( + tableName: TableOrModel, + constraintName: string, + options?: RemoveConstraintQueryOptions, + ) { + if (constraintName.startsWith('sys')) { + return joinSQLFragments([ + 'ALTER TABLE', + this.quoteTable(tableName), + 'DROP CONSTRAINT', + options?.ifExists ? 'IF EXISTS' : '', + constraintName, + options?.cascade ? 'CASCADE' : '', + ]); + } + + return super.removeConstraintQuery(tableName, constraintName, options); + } + + renameTableQuery( + beforeTableName: TableOrModel, + afterTableName: TableOrModel, + options?: RenameTableQueryOptions, + ): string { + if (options) { + rejectInvalidOptions( + 'renameTableQuery', + this.dialect, + RENAME_TABLE_QUERY_SUPPORTABLE_OPTIONS, + EMPTY_SET, + options, + ); + } + + const beforeTable = this.extractTableDetails(beforeTableName); + const afterTable = this.extractTableDetails(afterTableName); + const renamedTable = afterTable.tableName; + + if (beforeTable.schema !== afterTable.schema) { + throw new Error( + `Moving tables between schemas is not supported by ${this.dialect.name} dialect.`, + ); + } + + return `ALTER TABLE ${this.quoteTable(beforeTableName)} RENAME TO ${this.quoteTable(renamedTable)}`; + } + + getAliasToken(): string { + return ''; + } + + removeColumnQuery( + tableName: TableOrModel, + attributeName: string, + options: RemoveColumnQueryOptions, + ): string { + rejectInvalidOptions( + 'removeColumnQuery', + this.dialect, + REMOVE_COLUMN_QUERY_SUPPORTABLE_OPTIONS, + EMPTY_SET, + options, + ); + + return joinSQLFragments([ + 'ALTER TABLE', + this.quoteTable(tableName), + 'DROP COLUMN', + this.quoteIdentifier(attributeName), + ]); + } + + createSchemaQuery(schema: string, options: CreateSchemaQueryOptions): string { + if (options) { + rejectInvalidOptions( + 'createSchemaQuery', + this.dialect, + CREATE_SCHEMA_QUERY_SUPPORTABLE_OPTIONS, + EMPTY_SET, + options, + ); + } + + const quotedSchema = this.quoteIdentifier(schema); + + return [ + 'DECLARE', + 'USER_FOUND BOOLEAN := FALSE;', + 'BEGIN', + ' BEGIN', + ' EXECUTE IMMEDIATE ', + this.escape(`CREATE USER ${quotedSchema} IDENTIFIED BY 12345 DEFAULT TABLESPACE USERS`), + ';', + ' EXCEPTION WHEN OTHERS THEN', + ' IF SQLCODE != -1920 THEN', + ' RAISE;', + ' ELSE', + ' USER_FOUND := TRUE;', + ' END IF;', + ' END;', + ' IF NOT USER_FOUND THEN', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT "CONNECT" TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT CREATE TABLE TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT CREATE VIEW TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT CREATE ANY TRIGGER TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT CREATE ANY PROCEDURE TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT CREATE SEQUENCE TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT CREATE SYNONYM TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`ALTER USER ${quotedSchema} QUOTA UNLIMITED ON USERS`), + ';', + ' END IF;', + 'END;', + ].join(' '); + } + + truncateTableQuery(tableName: TableOrModel, options: TruncateTableQueryOptions): string { + if (options) { + rejectInvalidOptions( + 'truncateTableQuery', + this.dialect, + TRUNCATE_TABLE_QUERY_SUPPORTABLE_OPTIONS, + EMPTY_SET, + options, + ); + } + + return `TRUNCATE TABLE ${this.quoteTable(tableName)}`; + } + + bulkDeleteQuery(tableName: TableOrModel, options: BulkDeleteQueryOptions): string { + const table = this.quoteTable(tableName); + const modelDefinition = extractModelDefinition(tableName); + const whereOptions = isModelStatic(tableName) ? { ...options, model: tableName } : options; + let queryTmpl; + + let whereClause = this.whereQuery(options.where, whereOptions); + whereClause = whereClause.replace('WHERE', ''); + + if (options.limit && this.dialect.supports.delete.limit) { + if (!modelDefinition) { + throw new Error( + 'Using LIMIT in bulkDeleteQuery requires specifying a model or model definition.', + ); + } + + const whereTmpl = whereClause ? ` AND ${whereClause}` : ''; + queryTmpl = `DELETE FROM ${table} WHERE rowid IN (SELECT rowid FROM ${table} WHERE rownum <= ${this.escape(options.limit)}${whereTmpl})`; + } else { + const whereTmpl = whereClause ? ` WHERE${whereClause}` : ''; + queryTmpl = `DELETE FROM ${table}${whereTmpl}`; + } + + return queryTmpl; + } + + setIsolationLevelQuery(isolationLevel: IsolationLevel): string { + switch (isolationLevel) { + case IsolationLevel.READ_UNCOMMITTED: + case IsolationLevel.READ_COMMITTED: + return 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED'; + case IsolationLevel.REPEATABLE_READ: + case IsolationLevel.SERIALIZABLE: + // Serializable mode is equal to Snapshot Isolation (SI) + // defined in ANSI std. + return 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE'; + default: + throw new Error( + `The ${isolationLevel} isolation level is not supported by ${this.dialect.name}.`, + ); + } + } + + commitTransactionQuery() { + return 'COMMIT TRANSACTION'; + } + + rollbackTransactionQuery(): string { + if (this.dialect.supports.connectionTransactionMethods) { + throw new Error( + `rollbackTransactionQuery is not supported by the ${this.dialect.name} dialect.`, + ); + } + + return 'ROLLBACK TRANSACTION'; + } +} diff --git a/packages/oracle/src/query-generator.d.ts b/packages/oracle/src/query-generator.d.ts new file mode 100644 index 000000000000..3272395c6757 --- /dev/null +++ b/packages/oracle/src/query-generator.d.ts @@ -0,0 +1,5 @@ +// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +import { OracleQueryGeneratorTypeScript } from './query-generator-typescript.internal.ts'; + +export class OracleQueryGenerator extends OracleQueryGeneratorTypeScript {} diff --git a/packages/oracle/src/query-generator.internal.ts b/packages/oracle/src/query-generator.internal.ts new file mode 100644 index 000000000000..01202f88359d --- /dev/null +++ b/packages/oracle/src/query-generator.internal.ts @@ -0,0 +1,50 @@ +// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +import { attributeTypeToSql } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/data-types-utils.js'; +import { AbstractQueryGeneratorInternal } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-generator-internal.js'; +import type { EscapeOptions } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-generator-typescript.js'; +import type { AddLimitOffsetOptions } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-generator.internal-types.js'; +import { wrapAmbiguousWhere } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/where-sql-builder.js'; +import type { Cast } from '@sequelize/core/_non-semver-use-at-your-own-risk_/expression-builders/cast.js'; +import type { OracleDialect } from './dialect.js'; + +export class OracleQueryGeneratorInternal< + Dialect extends OracleDialect = OracleDialect, +> extends AbstractQueryGeneratorInternal { + addLimitAndOffset(options: AddLimitOffsetOptions) { + let fragment = ''; + const offset = options.offset || 0; + + if (options.offset || options.limit) { + fragment += ` OFFSET ${this.queryGenerator.escape(offset, options)} ROWS`; + } + + if (options.limit) { + fragment += ` FETCH NEXT ${this.queryGenerator.escape(options.limit, options)} ROWS ONLY`; + } + + return fragment; + } + + formatCast(cast: Cast, options?: EscapeOptions | undefined): string { + const type = this.sequelize.normalizeDataType(cast.type); + + let castSql = wrapAmbiguousWhere( + cast.expression, + this.queryGenerator.escape(cast.expression, { ...options, type }), + ); + const targetSql = attributeTypeToSql(type).toUpperCase(); + + if (type === 'boolean') { + castSql = `(CASE WHEN ${castSql}='true' THEN 1 ELSE 0 END)`; + + return `CAST(${castSql} AS NUMBER)`; + } else if (type === 'TIMESTAMPTZ') { + castSql = castSql.slice(0, -1); + + return `${castSql} RETURNING TIMESTAMP WITH TIME ZONE)`; + } + + return `CAST(${castSql} AS ${targetSql})`; + } +} diff --git a/packages/oracle/src/query-generator.js b/packages/oracle/src/query-generator.js new file mode 100644 index 000000000000..051a70dcffe7 --- /dev/null +++ b/packages/oracle/src/query-generator.js @@ -0,0 +1,1295 @@ +// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +'use strict'; + +import each from 'lodash/each'; +import forOwn from 'lodash/forOwn'; +import includes from 'lodash/includes'; +import isPlainObject from 'lodash/isPlainObject'; +import toPath from 'lodash/toPath'; + +import { DataTypes } from '@sequelize/core'; +import { normalizeDataType } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/data-types-utils.js'; +import { + ADD_COLUMN_QUERY_SUPPORTABLE_OPTIONS, + CREATE_TABLE_QUERY_SUPPORTABLE_OPTIONS, +} from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-generator.js'; +import { rejectInvalidOptions } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/check.js'; +import { quoteIdentifier } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/dialect.js'; +import { joinSQLFragments } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/join-sql-fragments.js'; +import { + EMPTY_OBJECT, + EMPTY_SET, + getObjectFromMap, +} from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/object.js'; +import { defaultValueSchemable } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/query-builder-utils.js'; +import { OracleQueryGeneratorTypeScript } from './query-generator-typescript.internal'; + +const CREATE_TABLE_QUERY_SUPPORTED_OPTIONS = new Set(['uniqueKeys']); + +/** + * list of reserved words in Oracle DB 21c + * source: https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-7B72E154-677A-4342-A1EA-C74C1EA928E6 + * + * @private + */ +const ORACLE_RESERVED_WORDS = [ + 'ACCESS', + 'ADD', + 'ALL', + 'ALTER', + 'AND', + 'ANY', + 'ARRAYLEN', + 'AS', + 'ASC', + 'AUDIT', + 'BETWEEN', + 'BY', + 'CHAR', + 'CHECK', + 'CLUSTER', + 'COLUMN', + 'COMMENT', + 'COMPRESS', + 'CONNECT', + 'CREATE', + 'CURRENT', + 'DATE', + 'DECIMAL', + 'DEFAULT', + 'DELETE', + 'DESC', + 'DISTINCT', + 'DROP', + 'ELSE', + 'EXCLUSIVE', + 'EXISTS', + 'FILE', + 'FLOAT', + 'FOR', + 'FROM', + 'GRANT', + 'GROUP', + 'HAVING', + 'IDENTIFIED', + 'IMMEDIATE', + 'IN', + 'INCREMENT', + 'INDEX', + 'INITIAL', + 'INSERT', + 'INTEGER', + 'INTERSECT', + 'INTO', + 'IS', + 'LEVEL', + 'LIKE', + 'LOCK', + 'LONG', + 'MAXEXTENTS', + 'MINUS', + 'MODE', + 'MODIFY', + 'NOAUDIT', + 'NOCOMPRESS', + 'NOT', + 'NOTFOUND', + 'NOWAIT', + 'NULL', + 'NUMBER', + 'OF', + 'OFFLINE', + 'ON', + 'ONLINE', + 'OPTION', + 'OR', + 'ORDER', + 'PCTFREE', + 'PRIOR', + 'PRIVILEGES', + 'PUBLIC', + 'RAW', + 'RENAME', + 'RESOURCE', + 'REVOKE', + 'ROW', + 'ROWID', + 'ROWLABEL', + 'ROWNUM', + 'ROWS', + 'SELECT', + 'SESSION', + 'SET', + 'SHARE', + 'SIZE', + 'SMALLINT', + 'SQLBUF', + 'START', + 'SUCCESSFUL', + 'SYNONYM', + 'SYSDATE', + 'TABLE', + 'THEN', + 'TO', + 'TRIGGER', + 'UID', + 'UNION', + 'UNIQUE', + 'UPDATE', + 'USER', + 'VALIDATE', + 'VALUES', + 'VARCHAR', + 'VARCHAR2', + 'VIEW', + 'WHENEVER', + 'WHERE', + 'WITH', +]; +const JSON_FUNCTION_REGEX = /^\s*((?:[a-z]+_){0,2}jsonb?(?:_[a-z]+){0,2})\([^)]*\)/i; +const JSON_OPERATOR_REGEX = /^\s*(->>?|@>|<@|\?[|&]?|\|{2}|#-)/i; +const TOKEN_CAPTURE_REGEX = /^\s*((?:([`"'])(?:(?!\2).|\2{2})*\2)|[\w\d\s]+|[().,;+-])/i; + +export class OracleQueryGenerator extends OracleQueryGeneratorTypeScript { + listSchemasQuery() { + return 'SELECT USERNAME AS "schema" FROM ALL_USERS WHERE COMMON = (\'NO\') AND USERNAME != user'; + } + + dropSchemaQuery(schema) { + return [ + 'BEGIN', + 'EXECUTE IMMEDIATE ', + this.escape(`DROP USER ${this.quoteTable(schema)} CASCADE`), + ';', + 'EXCEPTION WHEN OTHERS THEN', + ' IF SQLCODE != -1918 THEN', + ' RAISE;', + ' END IF;', + 'END;', + ].join(' '); + } + + versionQuery() { + return `SELECT VERSION_FULL FROM PRODUCT_COMPONENT_VERSION WHERE PRODUCT LIKE 'Oracle%'`; + } + + createTableQuery(tableName, attributes, options) { + if (options) { + rejectInvalidOptions( + 'createTableQuery', + this.dialect, + CREATE_TABLE_QUERY_SUPPORTABLE_OPTIONS, + CREATE_TABLE_QUERY_SUPPORTED_OPTIONS, + options, + ); + } + + const primaryKeys = []; + const foreignKeys = Object.create(null); + const attrStr = []; + const checkStr = []; + + const values = { + table: this.quoteTable(tableName), + }; + + // Starting by dealing with all attributes + for (let attr in attributes) { + if (!Object.hasOwn(attributes, attr)) { + continue; + } + + const dataType = attributes[attr]; + attr = this.quoteIdentifier(attr); + + // ORACLE doesn't support inline REFERENCES declarations: move to the end + if (dataType.includes('PRIMARY KEY')) { + // Primary key + primaryKeys.push(attr); + if (dataType.includes('REFERENCES')) { + const match = dataType.match(/^(.+) (REFERENCES.*)$/); + attrStr.push(`${attr} ${match[1].replace(/PRIMARY KEY/, '')}`); + + // match[2] already has foreignKeys in correct format so we don't need to replace + foreignKeys[attr] = match[2]; + } else { + attrStr.push(`${attr} ${dataType.replace(/PRIMARY KEY/, '').trim()}`); + } + } else if (dataType.includes('REFERENCES')) { + // Foreign key + const match = dataType.match(/^(.+) (REFERENCES.*)$/); + attrStr.push(`${attr} ${match[1]}`); + + // match[2] already has foreignKeys in correct format so we don't need to replace + foreignKeys[attr] = match[2]; + } else { + attrStr.push(`${attr} ${dataType}`); + } + } + + values.attributes = attrStr.join(', '); + + const pkString = primaryKeys.join(', '); + + if (pkString.length > 0) { + values.attributes += `,PRIMARY KEY (${pkString})`; + } + + // Dealing with FKs + for (const fkey in foreignKeys) { + if (!Object.hasOwn(foreignKeys, fkey)) { + continue; + } + + // Oracle default response for FK, doesn't support if defined + if (foreignKeys[fkey].includes('ON DELETE NO ACTION')) { + foreignKeys[fkey] = foreignKeys[fkey].replace('ON DELETE NO ACTION', ''); + } + + values.attributes += `,FOREIGN KEY (${fkey}) ${foreignKeys[fkey]}`; + } + + if (checkStr.length > 0) { + values.attributes += `, ${checkStr.join(', ')}`; + } + + // Specific case for unique indexes with Oracle, we have to set the constraint on the column, if not, no FK will be possible (ORA-02270: no matching unique or primary key for this column-list) + if (options && options.indexes && options.indexes.length > 0) { + const idxToDelete = []; + options.indexes.forEach((index, idx) => { + if ( + 'unique' in index && + (index.unique === true || (index.unique.length > 0 && index.unique !== false)) + ) { + // If unique index, transform to unique constraint on column + const fields = index.fields.map(field => { + if (typeof field === 'string') { + return field; + } + + return field.attribute; + }); + + // Now we have to be sure that the constraint isn't already declared in uniqueKeys + let canContinue = true; + if (options.uniqueKeys) { + const keys = Object.keys(options.uniqueKeys); + + // eslint-disable-next-line unicorn/no-for-loop + for (let fieldIdx = 0; fieldIdx < keys.length; fieldIdx++) { + const currUnique = options.uniqueKeys[keys[fieldIdx]]; + + if (currUnique.fields.length === fields.length) { + let i; + // lengths are the same, possible same constraint + for (i = 0; i < currUnique.fields.length; i++) { + const field = currUnique.fields[i]; + + if (includes(fields, field)) { + canContinue = false; + } else { + // We have at least one different column, even if we found the same columns previously, we let the constraint be created + canContinue = true; + break; + } + } + + if (i === currUnique.fields.length) { + break; + } + } + } + + if (canContinue) { + const indexName = 'name' in index ? index.name : ''; + const constraintToAdd = { + name: indexName, + fields, + }; + if (!('uniqueKeys' in options)) { + options.uniqueKeys = {}; + } + + options.uniqueKeys[indexName] = constraintToAdd; + idxToDelete.push(idx); + } else { + // The constraint already exists, we remove it from the list + idxToDelete.push(idx); + } + } + } + }); + idxToDelete.forEach(idx => { + options.indexes.splice(idx, 1); + }); + } + + if (options?.uniqueKeys) { + // only need to sort primary keys once, don't do it in place + let sortedPrimaryKeys = [...primaryKeys]; + sortedPrimaryKeys = sortedPrimaryKeys.map(elem => { + return elem.replaceAll('"', ''); + }); + sortedPrimaryKeys.sort(); + each(options.uniqueKeys, (columns, indexName) => { + const sortedColumnFields = [...columns.fields]; + sortedColumnFields.sort(); + // if primary keys === unique keys, then skip adding new constraint + const uniqueIsPrimary = + sortedColumnFields.length === primaryKeys.length && + sortedColumnFields.every((value, index) => { + return value === sortedPrimaryKeys[index]; + }); + if (uniqueIsPrimary) { + return true; + } + + // generate Constraint name, if no indexName is given + if (typeof indexName !== 'string') { + indexName = `uniq_${tableName}_${columns.fields.join('_')}`; + } + + values.attributes += `, CONSTRAINT ${this.quoteIdentifier(indexName)} UNIQUE (${columns.fields.map(field => this.quoteIdentifier(field)).join(', ')})`; + }); + } + + // we replace single quotes by two quotes in order for the execute statement to work + const query = joinSQLFragments(['CREATE TABLE', values.table, `(${values.attributes})`]); + + return joinSQLFragments([ + 'BEGIN', + 'EXECUTE IMMEDIATE', + `${this.escape(query)};`, + 'EXCEPTION WHEN OTHERS THEN', + 'IF SQLCODE != -955 THEN', + 'RAISE;', + 'END IF;', + 'END;', + ]); + } + + tableExistsQuery(table) { + const [tableName, schemaName] = this.getSchemaNameAndTableName(table); + + return `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = ${this.escape(tableName)} AND OWNER = ${table.schema ? this.escape(schemaName) : 'USER'}`; + } + + showConstraintsQuery(tableName, options) { + if (options && options.constraintType === 'FOREIGN KEY') { + return this.getForeignKeysQuery(tableName); + } + + let table = this.extractTableDetails(tableName); + const schema = this.getCatalogName(table.schema); + table = this.getCatalogName(table.tableName); + + return joinSQLFragments([ + 'SELECT C.CONSTRAINT_NAME "constraintName",', + `CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType",`, + 'C.TABLE_NAME "tableName",', + 'C.OWNER "constraintSchema",', + 'C.COLUMN_NAME "columnNames"', + 'FROM ALL_CONS_COLUMNS C', + 'INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME', + `WHERE C.TABLE_NAME =${this.escape(table)}`, + `AND C.OWNER =${this.escape(schema)}`, + options?.constraintName + ? `AND C.CONSTRAINT_NAME =${this.escape(options.constraintName)}` + : '', + options?.constraintType + ? `AND A.CONSTRAINT_TYPE =${this.escape(this._getConstraintType(options.constraintType))}` + : '', + 'ORDER BY C.CONSTRAINT_NAME', + ]); + } + + _getConstraintType(type) { + switch (type) { + case 'CHECK': + return 'C'; + case 'FOREIGN KEY': + return 'R'; + case 'PRIMARY KEY': + return 'P'; + case 'UNIQUE': + return 'U'; + default: + throw new Error(`Constraint type ${type} is not supported`); + } + } + + listTablesQuery(options) { + let query = `SELECT owner as "schema", table_name as "tableName" FROM all_tables where OWNER IN`; + if (options && options.schema) { + query += `(SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE ORACLE_MAINTAINED = 'N' AND USERNAME=${this.escape(options.schema)})`; + } else { + query += `(SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE ORACLE_MAINTAINED = 'N')`; + } + + return query; + } + + dropTableQuery(tableName) { + return joinSQLFragments([ + 'BEGIN ', + "EXECUTE IMMEDIATE 'DROP TABLE", + this.quoteTable(tableName), + "CASCADE CONSTRAINTS PURGE';", + 'EXCEPTION WHEN OTHERS THEN', + ' IF SQLCODE != -942 THEN', + ' RAISE;', + ' END IF;', + 'END;', + ]); + } + + /* + Modifying the indexname so that it is prefixed with the schema name + otherwise Oracle tries to add the index to the USER schema + @overide + */ + addIndexQuery(tableName, attributes, options, rawTablename) { + if (typeof tableName !== 'string' && attributes.name) { + attributes.name = `${tableName.schema}.${attributes.name}`; + } + + return super.addIndexQuery(tableName, attributes, options, rawTablename); + } + + // addConstraintQuery(tableName, options) { + // options = options || {}; + + // const constraintSnippet = this.getConstraintSnippet(tableName, options); + + // tableName = this.quoteTable(tableName); + // return `ALTER TABLE ${tableName} ADD ${constraintSnippet};`; + // } + + addColumnQuery(table, key, dataType, options) { + if (options) { + rejectInvalidOptions( + 'addColumnQuery', + this.dialect, + ADD_COLUMN_QUERY_SUPPORTABLE_OPTIONS, + EMPTY_SET, + options, + ); + } + + dataType = { + ...dataType, + field: key, + type: normalizeDataType(dataType.type, this.dialect), + }; + dataType.field = key; + + const attribute = joinSQLFragments([ + this.quoteIdentifier(key), + this.attributeToSQL(dataType, { + attributeName: key, + context: 'addColumn', + }), + ]); + + return joinSQLFragments(['ALTER TABLE', this.quoteTable(table), 'ADD', attribute, ';']); + } + + /** + * Function to add new foreign key to the attribute + * Block for add and drop foreign key constraint query + * taking the assumption that there is a single column foreign key reference always + * i.e. we always do - FOREIGN KEY (a) reference B(a) during createTable queryGenerator + * so there would be one and only one match for a constraint name for each column + * and every foreign keyed column would have a different constraint name + * Since sequelize doesn't support multiple column foreign key, added complexity to + * add the feature isn't needed + * + * @param {string} definition The operation that needs to be performed on the attribute + * @param {string|object} table The table that needs to be altered + * @param {string} attributeName The name of the attribute which would get altered + */ + _alterForeignKeyConstraint(definition, table, attributeName) { + const [tableName, schemaName] = this.getSchemaNameAndTableName(table); + const attributeNameConstant = this.escape(this.getCatalogName(attributeName)); + const schemaNameConstant = table.schema ? this.escape(this.getCatalogName(schemaName)) : 'USER'; + const tableNameConstant = this.escape(this.getCatalogName(tableName)); + const getConsNameQuery = [ + 'SELECT constraint_name INTO cons_name', + 'FROM (', + ' SELECT DISTINCT cc.owner, cc.table_name, cc.constraint_name, cc.column_name AS cons_columns', + ' FROM all_cons_columns cc, all_constraints c', + ' WHERE cc.owner = c.owner', + ' AND cc.table_name = c.table_name', + ' AND cc.constraint_name = c.constraint_name', + " AND c.constraint_type = 'R'", + ' GROUP BY cc.owner, cc.table_name, cc.constraint_name, cc.column_name', + ')', + 'WHERE owner =', + schemaNameConstant, + 'AND table_name =', + tableNameConstant, + 'AND cons_columns =', + attributeNameConstant, + ';', + ].join(' '); + const secondQuery = joinSQLFragments([ + `ALTER TABLE ${this.quoteTable(table)}`, + 'ADD FOREIGN KEY', + `(${this.quoteIdentifier(attributeName)})`, + definition.replace(/.+?(?=REFERENCES)/, ''), + ]); + + return [ + 'BEGIN', + getConsNameQuery, + 'EXCEPTION', + 'WHEN NO_DATA_FOUND THEN', + ' CONS_NAME := NULL;', + 'END;', + 'IF CONS_NAME IS NOT NULL THEN', + ` EXECUTE IMMEDIATE 'ALTER TABLE ${this.quoteTable(table)} DROP CONSTRAINT "'||CONS_NAME||'"';`, + 'END IF;', + `EXECUTE IMMEDIATE ${this.escape(secondQuery)};`, + ].join(' '); + } + + /** + * Function to alter table modify + * + * @param {string} definition The operation that needs to be performed on the attribute + * @param {object|string} table The table that needs to be altered + * @param {string} attributeName The name of the attribute which would get altered + */ + _modifyQuery(definition, table, attributeName) { + const query = joinSQLFragments([ + 'ALTER TABLE', + this.quoteTable(table), + 'MODIFY', + this.quoteIdentifier(attributeName), + definition, + ]); + const secondQuery = query.replace('NOT NULL', '').replace('NULL', ''); + + return [ + 'BEGIN', + `EXECUTE IMMEDIATE ${this.escape(query)};`, + 'EXCEPTION', + 'WHEN OTHERS THEN', + ' IF SQLCODE = -1442 OR SQLCODE = -1451 THEN', + // We execute the statement without the NULL / NOT NULL clause if the first statement failed due to this + ` EXECUTE IMMEDIATE ${this.escape(secondQuery)};`, + ' ELSE', + ' RAISE;', + ' END IF;', + 'END;', + ].join(' '); + } + + changeColumnQuery(table, attributes) { + const sql = ['DECLARE', 'CONS_NAME VARCHAR2(200);', 'BEGIN']; + for (const attributeName in attributes) { + if (!Object.hasOwn(attributes, attributeName)) { + continue; + } + + const definition = attributes[attributeName]; + // eslint-disable-next-line unicorn/prefer-regexp-test + if (definition.match(/REFERENCES/)) { + sql.push(this._alterForeignKeyConstraint(definition, table, attributeName)); + } else { + // Building the modify query + sql.push(this._modifyQuery(definition, table, attributeName)); + } + } + + sql.push('END;'); + + return sql.join(' '); + } + + renameColumnQuery(tableName, attrBefore, attributes) { + const newName = Object.keys(attributes)[0]; + + return `ALTER TABLE ${this.quoteTable(tableName)} RENAME COLUMN ${this.quoteIdentifier(attrBefore)} TO ${this.quoteIdentifier(newName)}`; + } + + /** + * Populates the returnAttributes array with outbind bindByPosition values + * and also the options.outBindAttributes map with bindDef for outbind of InsertQuery + * + * @param {Array} returningModelAttributes + * @param {Array} returnTypes + * @param {number} inbindLength + * @param {object} returnAttributes + * @param {object} options + * + * @private + */ + populateInsertQueryReturnIntoBinds( + returningModelAttributes, + returnTypes, + inbindLength, + returnAttributes, + options, + ) { + const oracledb = this.sequelize.dialect.connectionManager.lib; + const outBindAttributes = Object.create(null); + const outbind = {}; + const outbindParam = this.bindParam(outbind, inbindLength); + returningModelAttributes.forEach((element, index) => { + // generateReturnValues function quotes identifier based on the quoteIdentifier option + // If the identifier starts with a quote we remove it else we use it as is + if (element.startsWith('"')) { + element = element.slice(1, -1); + } + + outBindAttributes[element] = Object.assign(returnTypes[index]._getBindDef(oracledb), { + dir: oracledb.BIND_OUT, + }); + const returnAttribute = `${outbindParam(undefined)}`; + returnAttributes.push(returnAttribute); + }); + options.outBindAttributes = outBindAttributes; + } + + /** + * Override of upsertQuery, Oracle specific + * Using PL/SQL for finding the row + * + * @param {object|string} tableName + * @param {Array} insertValues + * @param {Array} updateValues + * @param {Array} where + * @param {object} model + * @param {object} options + */ + upsertQuery(tableName, insertValues, updateValues, where, model, options) { + const modelDefinition = model.modelDefinition; + const rawAttributes = getObjectFromMap(modelDefinition.attributes); + const updateQuery = this.updateQuery(tableName, updateValues, where, options, rawAttributes); + // This bind is passed so that the insert query starts appending to this same bind array + options.bind = updateQuery.bind; + const insertQuery = this.insertQuery(tableName, insertValues, rawAttributes, options); + + const sql = [ + 'DECLARE ', + 'BEGIN ', + updateQuery.query + ? [ + updateQuery.query, + '; ', + ' IF ( SQL%ROWCOUNT = 0 ) THEN ', + insertQuery.query, + ' :isUpdate := 0; ', + 'ELSE ', + ' :isUpdate := 1; ', + ' END IF; ', + ].join('') + : [ + insertQuery.query, + ' :isUpdate := 0; ', + // If there is a conflict on insert we ignore + 'EXCEPTION WHEN OTHERS THEN', + ' IF SQLCODE != -1 THEN', + ' RAISE;', + ' END IF;', + ].join(''), + 'END;', + ]; + + const query = sql.join(''); + + if (options.bindParam !== false) { + options.bind = updateQuery.bind || insertQuery.bind; + } + + return query; + } + + /** + * Returns an insert into command for multiple values. + * + * @param {string} tableName + * @param {object} fieldValueHashes + * @param {object} options + * @param {object} fieldMappedAttributes + * + * @private + */ + bulkInsertQuery(tableName, fieldValueHashes, options, fieldMappedAttributes) { + options = options || {}; + options.executeMany = true; + fieldMappedAttributes = fieldMappedAttributes || {}; + + const tuples = []; + const allColumns = {}; + const inBindBindDefMap = {}; + const outBindBindDefMap = {}; + const oracledb = this.sequelize.dialect.connectionManager.lib; + + // Generating the allColumns map + // The data is provided as an array of objects. + // Each object may contain differing numbers of attributes. + // A set of the attribute names that are used in all objects must be determined. + // The allColumns map contains the column names and indicates whether the value is generated or not + // We set allColumns[key] to true if the field is an + // auto-increment field and the value given is null and fieldMappedAttributes[key] + // is valid for the specific column else it is set to false + for (const fieldValueHash of fieldValueHashes) { + forOwn(fieldValueHash, (value, key) => { + allColumns[key] = + fieldMappedAttributes[key] && + fieldMappedAttributes[key].autoIncrement === true && + value === null; + }); + } + + // Building the inbind parameter + // A list that would have inbind positions like [:1, :2, :3...] to be used in generating sql string + let inBindPosition; + // Iterating over each row of the fieldValueHashes + for (const fieldValueHash of fieldValueHashes) { + // Has each column for a row after coverting it to appropriate format using this.format function + // like ['Mick', 'Broadstone', 2022-02-16T05:24:18.949Z, 2022-02-16T05:24:18.949Z], + let tuple = []; + const bindMap = {}; + // A function expression for this.bindParam/options.bindparam function + // This function is passed to this.format function which inserts column values to the tuple list + // using _bindParam/_stringify function in data-type.js file + const inbindParam = + options.bindParam === undefined ? this.bindParam(bindMap) : options.bindParam; + // We are iterating over each col + // and pushing the given values to tuple list using this.format function + // and also simultaneously generating the bindPosition + // tempBindPostions has the inbind positions + const tempBindPositions = Object.keys(allColumns).map(key => { + if (allColumns[key] === true) { + // We had set allAttributes[key] to true since at least one row for an auto increment column was null + // If we get any other row that has this specific column as non-null we must raise an error + // Since for an auto-increment column, either all row has to be null or all row has to be a non-null + if (fieldValueHash[key] !== null) { + throw new Error( + 'For an auto-increment column either all row must be null or non-null, a mix of null and non-null is not allowed!', + ); + } + + // Return DEFAULT for auto-increment column and if all values for the column is null in each row + return 'DEFAULT'; + } + + // Sanitizes the values given by the user and pushes it to the tuple list using inBindParam function and + // also generates the inbind position for the sql string for example (:1, :2, :3.....) which is a by product of the push + return this.escape(fieldValueHash[key] ?? null, { + model: options.model, + type: fieldMappedAttributes[key] ? fieldMappedAttributes[key].type : null, + bindParam: inbindParam, + }); + }); + + // Even though the bind variable positions are calculated for each row we only retain the values for the first row + // since the values will be identical + if (!inBindPosition) { + inBindPosition = tempBindPositions; + } + + tuple = Object.values(bindMap); + // Adding the row to the array of rows that will be supplied to executeMany() + tuples.push(tuple); + } + + // The columns that we are expecting to be returned from the DB like ["id1", "id2"...] + const returnColumn = []; + // The outbind positions for the returning columns like [:3, :4, :5....] + const returnColumnBindPositions = []; + // Has the columns name in which data would be inserted like ["id", "name".....] + const insertColumns = []; + // Iterating over the allColumns keys to get the bindDef for inbind and outbinds + // and also to get the list of insert and return column after applying this.quoteIdentifier + for (const key of Object.keys(allColumns)) { + // If fieldMappenAttributes[attr] is defined we generate the bindDef + // and return clause else we can skip it + if (fieldMappedAttributes[key]) { + // BindDef for the specific column + const bindDef = fieldMappedAttributes[key].type._getBindDef(oracledb); + if (allColumns[key]) { + // Binddef for outbinds + bindDef.dir = oracledb.BIND_OUT; + outBindBindDefMap[key] = bindDef; + + // Building the outbind parameter list + // ReturnColumn has the column name for example "id", "usedId", quoting depends on quoteIdentifier option + returnColumn.push(this.quoteIdentifier(key)); + // Pushing the outbind index to the returnColumnPositions to generate (:3, :4, :5) + // The start offset depend on the tuple length (bind array size of a particular row) + // the outbind position starts after the position where inbind position ends + returnColumnBindPositions.push(`:${tuples[0].length + returnColumn.length}`); + } else { + // Binddef for inbinds + bindDef.dir = oracledb.BIND_IN; + inBindBindDefMap[key] = bindDef; + } + } + + // Quoting and pushing each insert column based on quoteIdentifier option + insertColumns.push(this.quoteIdentifier(key)); + } + + // Generating the sql query + let query = joinSQLFragments([ + 'INSERT', + 'INTO', + // Table name for the table in which data needs to inserted + this.quoteTable(tableName), + // Columns names for the columns of the table (example "a", "b", "c" - quoting depends on the quoteidentifier option) + `(${insertColumns.join(',')})`, + 'VALUES', + // InBind position for the insert query (for example :1, :2, :3....) + `(${inBindPosition})`, + ]); + + // If returnColumn.length is > 0 + // then the returning into clause is needed + if (returnColumn.length > 0) { + options.outBindAttributes = outBindBindDefMap; + query = joinSQLFragments([ + query, + 'RETURNING', + // List of return column (for example "id", "userId"....) + `${returnColumn.join(',')}`, + 'INTO', + // List of outbindPosition (for example :4, :5, :6....) + // Start offset depends on where inbindPosition end + `${returnColumnBindPositions}`, + ]); + } + + // Binding the bind variable to result + const result = query; + // Binding the bindParam to result + // Tuple has each row for the insert query + options.bind = tuples; + // Setting options.inbindAttribute + options.inbindAttributes = inBindBindDefMap; + + return result; + } + + deleteQuery(tableName, where, options = EMPTY_OBJECT, model) { + const table = tableName; + + let whereClause = this.whereQuery(where, { ...options, model }); + whereClause = whereClause.replace('WHERE', ''); + let queryTmpl; + // delete with limit and optional condition on Oracle: DELETE FROM WHERE rowid in (SELECT rowid FROM WHERE AND rownum <= ) + // Note that the condition has to be in the subquery; otherwise, the subquery would select arbitrary rows. + if (options.limit) { + const whereTmpl = whereClause ? ` AND ${whereClause}` : ''; + queryTmpl = `DELETE FROM ${this.quoteTable(table)} WHERE rowid IN (SELECT rowid FROM ${this.quoteTable(table)} WHERE rownum <= ${this.escape(options.limit)}${whereTmpl})`; + } else { + const whereTmpl = whereClause ? ` WHERE${whereClause}` : ''; + queryTmpl = `DELETE FROM ${this.quoteTable(table)}${whereTmpl}`; + } + + return queryTmpl; + } + + attributeToSQL(attribute, options) { + if (!isPlainObject(attribute)) { + attribute = { + type: attribute, + }; + } + + // handle self referential constraints + if ( + attribute.references && + attribute.Model && + attribute.Model.tableName === attribute.references.tableName + ) { + this.sequelize.log( + 'Oracle does not support self referencial constraints, ' + + 'we will remove it but we recommend restructuring your query', + ); + attribute.onDelete = ''; + } + + let template; + + if (attribute.type instanceof DataTypes.ENUM) { + // enums are a special case + template = attribute.type.toSql({ dialect: this.dialect }); + template += ` CHECK (${this.quoteIdentifier(options.attributeName)} IN(${attribute.type.options.values + .map(value => { + return this.escape(value, undefined, {}); + }) + .join(', ')}))`; + + return template; + } + + if (attribute.type instanceof DataTypes.JSON) { + template = attribute.type.toSql(); + template += ` CHECK (${this.quoteIdentifier(options.attributeName)} IS JSON)`; + + return template; + } + + if (attribute.type instanceof DataTypes.BOOLEAN) { + template = attribute.type.toSql(); + template += ` CHECK (${this.quoteIdentifier(options.attributeName)} IN('1', '0'))`; + + return template; + } + + if (attribute.autoIncrement) { + template = ' NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY'; + } else if (attribute.type && attribute.type === 'DOUBLE') { + template = attribute.type.toSql(); + } else if (attribute.type) { + // setting it to false because oracle doesn't support unsigned int so put a check to make it behave like unsigned int + let unsignedTemplate = ''; + if (attribute.type?.options?.unsigned) { + attribute.type.options.unsigned = false; + unsignedTemplate += ` CHECK(${this.quoteIdentifier(options.attributeName)} >= 0)`; + } + + template = attribute.type.toString(); + + // Blobs/texts cannot have a defaultValue + if ( + attribute.type && + attribute.type !== 'TEXT' && + attribute.type._binary !== true && + defaultValueSchemable(attribute.defaultValue, this.dialect) + ) { + template += ` DEFAULT ${this.escape(attribute.defaultValue)}`; + } + + if (!attribute.autoIncrement) { + // If autoincrement, not null is set automatically + if (attribute.allowNull === false) { + template += ' NOT NULL'; + } else if ( + !attribute.primaryKey && + !defaultValueSchemable(attribute.defaultValue, this.dialect) + ) { + template += ' NULL'; + } + } + + template += unsignedTemplate; + } else { + template = ''; + } + + if (attribute.primaryKey) { + template += ' PRIMARY KEY'; + } + + if ((!options || !options.withoutForeignKeyConstraints) && attribute.references) { + template += ` REFERENCES ${this.quoteTable(attribute.references.table)}`; + + if (attribute.references.key) { + template += ` (${this.quoteIdentifier(attribute.references.key)})`; + } else { + template += ` (${this.quoteIdentifier('id')})`; + } + + if (attribute.onDelete && attribute.onDelete.toUpperCase() !== 'NO ACTION') { + template += ` ON DELETE ${attribute.onDelete.toUpperCase()}`; + } + } + + return template; + } + + attributesToSQL(attributes, options) { + const result = {}; + + for (const key in attributes) { + const attribute = attributes[key]; + const attributeName = attribute.field || key; + result[attributeName] = this.attributeToSQL(attribute, { attributeName, ...options }); + } + + return result; + } + + createTrigger() { + throwMethodUndefined('createTrigger'); + } + + dropTrigger() { + throwMethodUndefined('dropTrigger'); + } + + renameTrigger() { + throwMethodUndefined('renameTrigger'); + } + + createFunction() { + throwMethodUndefined('createFunction'); + } + + dropFunction() { + throwMethodUndefined('dropFunction'); + } + + renameFunction() { + throwMethodUndefined('renameFunction'); + } + + getConstraintsOnColumn(table, column) { + const [tableName, schemaName] = this.getSchemaNameAndTableName(table); + column = this.getCatalogName(column); + const sql = [ + 'SELECT CONSTRAINT_NAME FROM user_cons_columns WHERE TABLE_NAME = ', + this.escape(tableName), + ' and OWNER = ', + table.schema ? this.escape(schemaName) : 'USER', + ' and COLUMN_NAME = ', + this.escape(column), + ' AND POSITION IS NOT NULL ORDER BY POSITION', + ].join(''); + + return sql; + } + + getForeignKeysQuery(table) { + // We don't call quoteTable as we don't want the schema in the table name, Oracle seperates it on another field + const tableDetails = this.extractTableDetails(table); + const tableName = this.getCatalogName(tableDetails.tableName); + const schemaName = this.getCatalogName(tableDetails.schema); + const sql = [ + 'SELECT DISTINCT a.table_name "tableName", a.constraint_name "constraintName", a.owner "constraintSchema", a.column_name "columnNames",', + `CASE c.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType",`, + ' c.r_owner "referencedTableSchema",', + ' c.DELETE_RULE "deleteAction",', + ' b.table_name "referencedTableName", b.column_name "referencedColumnNames"', + ' FROM all_cons_columns a', + ' JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name', + ' JOIN all_cons_columns b ON c.owner = b.owner AND c.r_constraint_name = b.constraint_name', + " WHERE c.constraint_type = 'R'", + ' AND a.table_name = ', + this.escape(tableName), + ' AND a.owner = ', + tableDetails.schema && schemaName !== '' ? this.escape(schemaName) : 'USER', + ' ORDER BY a.table_name, a.column_name, b.column_name', + ].join(''); + + return sql; + } + + dropForeignKeyQuery(tableName, foreignKey) { + return this.dropConstraintQuery(tableName, foreignKey); + } + + getPrimaryKeyConstraintQuery(table) { + const [tableName, schemaName] = this.getSchemaNameAndTableName(table); + const sql = [ + 'SELECT cols.column_name, atc.identity_column ', + 'FROM all_constraints cons, all_cons_columns cols ', + 'INNER JOIN all_tab_columns atc ON(atc.table_name = cols.table_name AND atc.COLUMN_NAME = cols.COLUMN_NAME )', + 'WHERE cols.table_name = ', + this.escape(tableName), + 'AND cols.owner = ', + table.schema ? this.escape(schemaName) : 'USER ', + "AND cons.constraint_type = 'P' ", + 'AND cons.constraint_name = cols.constraint_name ', + 'AND cons.owner = cols.owner ', + 'ORDER BY cols.table_name, cols.position', + ].join(''); + + return sql; + } + + dropConstraintQuery(tableName, constraintName) { + return `ALTER TABLE ${this.quoteTable(tableName)} DROP CONSTRAINT ${constraintName}`; + } + + // handleSequelizeMethod(smth, tableName, factory, options, prepend) { + // let str; + // if (smth instanceof Utils.Json) { + // // Parse nested object + // if (smth.conditions) { + // const conditions = this.parseConditionObject(smth.conditions).map(condition => + // `${this.jsonPathExtractionQuery(condition.path[0], _.tail(condition.path))} = '${condition.value}'` + // ); + + // return conditions.join(' AND '); + // } + // if (smth.path) { + + // // Allow specifying conditions using the sqlite json functions + // if (this._checkValidJsonStatement(smth.path)) { + // str = smth.path; + // } else { + // // Also support json property accessors + // const paths = _.toPath(smth.path); + // const column = paths.shift(); + // str = this.jsonPathExtractionQuery(column, paths); + // } + // if (smth.value) { + // str += util.format(' = %s', this.escape(smth.value)); + // } + + // return str; + // } + // } + // if (smth instanceof Utils.Cast) { + // if (smth.val instanceof Utils.SequelizeMethod) { + // str = this.handleSequelizeMethod(smth.val, tableName, factory, options, prepend); + // if (smth.type === 'boolean') { + // str = `(CASE WHEN ${str}='true' THEN 1 ELSE 0 END)`; + // return `CAST(${str} AS NUMBER)`; + // } if (smth.type === 'timestamptz' && /json_value\(/.test(str)) { + // str = str.slice(0, -1); + // return `${str} RETURNING TIMESTAMP WITH TIME ZONE)`; + // } + // } + // } + // return super.handleSequelizeMethod(smth, tableName, factory, options, prepend); + // } + + _checkValidJsonStatement(stmt) { + if (typeof stmt !== 'string') { + return false; + } + + let currentIndex = 0; + let openingBrackets = 0; + let closingBrackets = 0; + let hasJsonFunction = false; + let hasInvalidToken = false; + + while (currentIndex < stmt.length) { + const string = stmt.slice(currentIndex); + const functionMatches = JSON_FUNCTION_REGEX.exec(string); + if (functionMatches) { + currentIndex += functionMatches[0].indexOf('('); + hasJsonFunction = true; + continue; + } + + const operatorMatches = JSON_OPERATOR_REGEX.exec(string); + if (operatorMatches) { + currentIndex += operatorMatches[0].length; + hasJsonFunction = true; + continue; + } + + const tokenMatches = TOKEN_CAPTURE_REGEX.exec(string); + if (tokenMatches) { + const capturedToken = tokenMatches[1]; + if (capturedToken === '(') { + openingBrackets++; + } else if (capturedToken === ')') { + closingBrackets++; + } else if (capturedToken === ';') { + hasInvalidToken = true; + break; + } + + currentIndex += tokenMatches[0].length; + continue; + } + + break; + } + + // Check invalid json statement + if (hasJsonFunction && (hasInvalidToken || openingBrackets !== closingBrackets)) { + throw new Error(`Invalid json statement: ${stmt}`); + } + + // return true if the statement has valid json function + return hasJsonFunction; + } + + isIdentifierQuoted(identifier) { + return /^\s*(?:([`"'])(?:(?!\1).|\1{2})*\1\.?)+\s*$/i.test(identifier); + } + + addTicks(identifier, tickChar) { + identifier = identifier.replaceAll(new RegExp(tickChar, 'g'), ''); + + return tickChar + identifier + tickChar; + } + + jsonPathExtractionQuery(column, path) { + let paths = toPath(path); + const quotedColumn = this.isIdentifierQuoted(column) ? column : this.quoteIdentifier(column); + + paths = paths.map(subPath => { + return /\D/.test(subPath) ? this.addTicks(subPath, '"') : subPath; + }); + + const pathStr = this.escape( + ['$'] + .concat(paths) + .join('.') + .replaceAll(/\.(\d+)(?:(?=\.)|$)/g, (__, digit) => `[${digit}]`), + ); + const extractQuery = `json_value(${quotedColumn},${pathStr})`; + + return extractQuery; + } + + booleanValue(value) { + return value ? 1 : 0; + } + + quoteIdentifier(identifier, force = false) { + const optForceQuote = force; + const optQuoteIdentifiers = this.options.quoteIdentifiers !== false; + const regExp = /^(([\w][\w\d_]*))$/g; + + if ( + optForceQuote !== true && + optQuoteIdentifiers === false && + regExp.test(identifier) && + !ORACLE_RESERVED_WORDS.includes(identifier.toUpperCase()) + ) { + // In Oracle, if tables, attributes or alias are created double-quoted, + // they are always case sensitive. If they contain any lowercase + // characters, they must always be double-quoted otherwise it + // would get uppercased by the DB. + // Here, we strip quotes if we don't want case sensitivity. + return identifier; + } + + return quoteIdentifier(identifier, this.dialect.TICK_CHAR_LEFT, this.dialect.TICK_CHAR_RIGHT); + } + + /** + * It causes bindbyPosition like :1, :2, :3 + * We pass the val parameter so that the outBind indexes + * starts after the inBind indexes end + * + * @param {Array} bind + * @param {number} posOffset + */ + bindParam(bind, posOffset = 0) { + let i = Object.keys(bind).length; + + return value => { + const bindName = `sequelize_${++i}`; + bind[bindName] = value; + + return `:${Object.keys(bind).length + posOffset}`; + }; + } + + /** + * Returns the authenticate test query string + */ + authTestQuery() { + return 'SELECT 1+1 AS result FROM DUAL'; + } +} + +/* istanbul ignore next */ +function throwMethodUndefined(methodName) { + throw new Error(`The method "${methodName}" is not defined! Please add it to your sql dialect.`); +} diff --git a/packages/oracle/src/query-interface-typescript.internal.ts b/packages/oracle/src/query-interface-typescript.internal.ts new file mode 100644 index 000000000000..912f4df55061 --- /dev/null +++ b/packages/oracle/src/query-interface-typescript.internal.ts @@ -0,0 +1,45 @@ +// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +import type { FetchDatabaseVersionOptions, QiDropAllTablesOptions } from '@sequelize/core'; +import { AbstractQueryInterface } from '@sequelize/core'; +import { AbstractQueryInterfaceInternal } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-interface-internal.js'; +import type { OracleDialect } from './dialect.js'; + +export class OracleQueryInterfaceTypescript< + Dialect extends OracleDialect = OracleDialect, +> extends AbstractQueryInterface { + readonly #internalQueryInterface: AbstractQueryInterfaceInternal; + + constructor(dialect: Dialect, internalQueryInterface?: AbstractQueryInterfaceInternal) { + internalQueryInterface ??= new AbstractQueryInterfaceInternal(dialect); + + super(dialect, internalQueryInterface); + this.#internalQueryInterface = internalQueryInterface; + } + + async fetchDatabaseVersion(options?: FetchDatabaseVersionOptions): Promise { + const payload = await this.#internalQueryInterface.fetchDatabaseVersionRaw<{ + VERSION_FULL: string; + }>(options); + + return payload.VERSION_FULL; + } + + async dropAllTables(options?: QiDropAllTablesOptions | undefined): Promise { + const skip = options?.skip || []; + const allTables = await this.listTables(options); + const tableNames = allTables.filter(tableName => !skip.includes(tableName.tableName)); + + const dropOptions = { ...options }; + // enable "cascade" by default if supported by this dialect + if (this.sequelize.dialect.supports.dropTable.cascade && dropOptions.cascade === undefined) { + dropOptions.cascade = true; + } + + // Drop all the tables loop to avoid deadlocks and timeouts + for (const tableName of tableNames) { + // eslint-disable-next-line no-await-in-loop + await this.dropTable(tableName, dropOptions); + } + } +} diff --git a/packages/oracle/src/query-interface.d.ts b/packages/oracle/src/query-interface.d.ts new file mode 100644 index 000000000000..ce2c71a80cb3 --- /dev/null +++ b/packages/oracle/src/query-interface.d.ts @@ -0,0 +1,8 @@ +// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +import type { OracleDialect } from './dialect.js'; +import { OracleQueryInterfaceTypescript } from './query-interface-typescript.internal.ts'; + +export class OracleQueryInterface< + Dialect extends OracleDialect = OracleDialect, +> extends OracleQueryInterfaceTypescript {} diff --git a/packages/oracle/src/query-interface.js b/packages/oracle/src/query-interface.js new file mode 100644 index 000000000000..50e106879b48 --- /dev/null +++ b/packages/oracle/src/query-interface.js @@ -0,0 +1,93 @@ +// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +import { QueryTypes } from '@sequelize/core'; +import { assertNoReservedBind } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/sql.js'; + +const intersection = require('lodash/intersection'); +const uniq = require('lodash/uniq'); +const { OracleQueryInterfaceTypescript } = require('./query-interface-typescript.internal'); + +export class OracleQueryInterface extends OracleQueryInterfaceTypescript { + async upsert(tableName, insertValues, updateValues, where, options) { + if (options.bind) { + assertNoReservedBind(options.bind); + } + + options = { ...options }; + + const model = options.model; + const primaryKeys = Object.values(model.primaryKeys).map(item => item.field); + const uniqueKeys = Object.values(model.uniqueKeys) + .filter(c => c.fields.length > 0) + .map(c => c.fields); + const indexKeys = Object.values(model.getIndexes()) + .filter(c => c.unique && c.fields.length > 0) + .map(c => c.fields); + + options.type = QueryTypes.UPSERT; + options.updateOnDuplicate = Object.keys(updateValues); + options.upsertKeys = []; + + // For fields in updateValues, try to find a constraint or unique index + // that includes given field. Only first matching upsert key is used. + for (const field of options.updateOnDuplicate) { + const uniqueKey = uniqueKeys.find(fields => fields.includes(field)); + if (uniqueKey) { + options.upsertKeys = uniqueKey; + break; + } + + const indexKey = indexKeys.find(fields => fields.includes(field)); + if (indexKey) { + options.upsertKeys = indexKey; + break; + } + } + + // Always use PK, if no constraint available OR update data contains PK + if ( + options.upsertKeys.length === 0 || + intersection(options.updateOnDuplicate, primaryKeys).length + ) { + options.upsertKeys = primaryKeys; + } + + options.upsertKeys = uniq(options.upsertKeys); + + let whereHasNull = false; + + primaryKeys.forEach(element => { + if (where[element] === null) { + whereHasNull = true; + } + }); + + if (whereHasNull === true) { + where = options.upsertKeys.reduce((result, attribute) => { + result[attribute] = insertValues[attribute]; + + return result; + }, {}); + } + + if (typeof tableName === 'object') { + tableName = tableName.tableName; + } + + const sql = this.queryGenerator.upsertQuery( + tableName, + insertValues, + updateValues, + where, + model, + options, + ); + // we need set this to undefined otherwise sequelize would raise an error + // Error: Both `sql.bind` and `options.bind` cannot be set at the same time + if (sql.bind) { + options.bind = undefined; + } + + return await this.sequelize.query(sql, options); + } +} diff --git a/packages/oracle/src/query.d.ts b/packages/oracle/src/query.d.ts new file mode 100644 index 000000000000..97668d29ed21 --- /dev/null +++ b/packages/oracle/src/query.d.ts @@ -0,0 +1,5 @@ +// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +import { AbstractQuery } from '@sequelize/core'; + +export class OracleQuery extends AbstractQuery {} diff --git a/packages/oracle/src/query.js b/packages/oracle/src/query.js new file mode 100644 index 000000000000..75d366b867a2 --- /dev/null +++ b/packages/oracle/src/query.js @@ -0,0 +1,755 @@ +// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved + +import { + AbstractQuery, + DatabaseError, + ForeignKeyConstraintError, + UniqueConstraintError, + UnknownConstraintError, + ValidationErrorItem, +} from '@sequelize/core'; +import { logger } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/logger.js'; +import { nameIndex } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/string.js'; +import extend from 'lodash/extend'; +import isPlainObject from 'lodash/isPlainObject'; +import mapKeys from 'lodash/mapKeys'; +import mapValues from 'lodash/mapValues'; +import reduce from 'lodash/reduce'; +import toPairs from 'lodash/toPairs'; + +const debug = logger.debugContext('sql:oracle'); + +export class OracleQuery extends AbstractQuery { + constructor(connection, sequelize, options) { + super(connection, sequelize, options); + this.options = extend( + { + // eslint-disable-next-line no-console + logging: console.log, + plain: false, + raw: false, + }, + options || {}, + ); + + this.checkLoggingOption(); + this.outFormat = options.outFormat || this.sequelize.dialect.connectionManager.lib.OBJECT; + } + + getInsertIdField() { + return 'id'; + } + + getExecOptions() { + const execOpts = { outFormat: this.outFormat, autoCommit: this.autoCommit }; + + // We set the oracledb + const oracledb = this.sequelize.dialect.connectionManager.lib; + + if (this.model && this.isSelectQuery()) { + const fInfo = {}; + const keys = Object.keys(this.model.tableAttributes); + for (const key of keys) { + const keyValue = this.model.tableAttributes[key]; + if (keyValue.type.getDataTypeId() === 'DECIMAL') { + fInfo[key] = { type: oracledb.STRING }; + } + + // Fetching BIGINT as string since, node-oracledb doesn't support JS BIGINT yet + if (keyValue.type.getDataTypeId() === 'BIGINT') { + fInfo[key] = { type: oracledb.STRING }; + } + } + + if (fInfo) { + execOpts.fetchInfo = fInfo; + } + } + + return execOpts; + } + + /** + * convert binding values for unsupported + * types in connector library + * + * @param {string} bindingDictionary a string representing the key to scan + * @param {object} oracledb native oracle library + * @private + */ + _convertBindAttributes(bindingDictionary, oracledb) { + if (this.model && this.options[bindingDictionary]) { + // check against model if we have some BIGINT + const keys = Object.keys(this.model.tableAttributes); + for (const key of keys) { + const keyValue = this.model.tableAttributes[key]; + if (keyValue.type.getDataTypeId() === 'BIGINT') { + const oldBinding = this.options[bindingDictionary][key]; + if (oldBinding) { + this.options[bindingDictionary][key] = { + ...oldBinding, + type: oracledb.STRING, + maxSize: 10_000_000, // TOTALLY ARBITRARY Number to prevent query failure + }; + } + } + } + } + } + + async run(sql, parameters) { + // We set the oracledb + const oracledb = this.sequelize.dialect.connectionManager.lib; + const complete = this._logQuery(sql, debug, parameters); + const outParameters = []; + const bindParameters = []; + const bindDef = []; + + // eslint-disable-next-line unicorn/prefer-regexp-test + if (!sql.match(/END;$/)) { + this.sql = sql.replace(/; *$/, ''); + } else { + this.sql = sql; + } + + // When this.options.bindAttributes exists then it is an insertQuery/upsertQuery + // So we insert the return bind direction and type + if ( + this.options.outBindAttributes && + (Array.isArray(parameters) || isPlainObject(parameters)) + ) { + this._convertBindAttributes('outBindAttributes', oracledb); + outParameters.push(...Object.values(this.options.outBindAttributes)); + // For upsertQuery we need to push the bindDef for isUpdate + if (this.isUpsertQuery()) { + outParameters.push({ dir: oracledb.BIND_OUT }); + } + } + + this.bindParameters = outParameters; + // construct input binds from parameters for single row insert execute call + // ex: [3, 4,...] + if (Array.isArray(parameters) || isPlainObject(parameters)) { + if (this.options.executeMany) { + // Constructing BindDefs for ExecuteMany call + // Building the bindDef for in and out binds + this._convertBindAttributes('inbindAttributes', oracledb); + bindDef.push(...Object.values(this.options.inbindAttributes)); + // eslint-disable-next-line unicorn/no-array-push-push + bindDef.push(...outParameters); + this.bindParameters = parameters; + } else { + Object.values(parameters).forEach(value => { + bindParameters.push(value); + }); + bindParameters.push(...outParameters); + Object.assign(this.bindParameters, bindParameters); + } + } + + // TRANSACTION SUPPORT + if (this.sql.startsWith('BEGIN TRANSACTION')) { + this.autocommit = false; + + // eslint-disable-next-line unicorn/no-useless-promise-resolve-reject + return Promise.resolve(); + } + + if (this.sql.startsWith('SET AUTOCOMMIT ON')) { + this.autocommit = true; + + // eslint-disable-next-line unicorn/no-useless-promise-resolve-reject + return Promise.resolve(); + } + + if (this.sql.startsWith('SET AUTOCOMMIT OFF')) { + this.autocommit = false; + + // eslint-disable-next-line unicorn/no-useless-promise-resolve-reject + return Promise.resolve(); + } + + if (this.sql.startsWith('DECLARE x NUMBER')) { + // Calling a stored procedure for bulkInsert with NO attributes, returns nothing + if (this.autoCommit === undefined) { + if (this.connection.uuid) { + this.autoCommit = false; + } else { + this.autoCommit = true; + } + } + + try { + await this.connection.execute(this.sql, this.bindParameters, { + autoCommit: this.autoCommit, + }); + + return Object.create(null); + } catch (error) { + throw this.formatError(error); + } finally { + complete(); + } + } + + if (this.sql.startsWith('BEGIN')) { + // Call to stored procedures - BEGIN TRANSACTION has been treated before + if (this.autoCommit === undefined) { + if (this.connection.uuid) { + this.autoCommit = false; + } else { + this.autoCommit = true; + } + } + + try { + const result = await this.connection.execute(this.sql, this.bindParameters, { + outFormat: this.outFormat, + autoCommit: this.autoCommit, + }); + if (!Array.isArray(result.outBinds)) { + return [result.outBinds]; + } + + return result.outBinds; + } catch (error) { + throw this.formatError(error); + } finally { + complete(); + } + } + + if (this.sql.startsWith('COMMIT TRANSACTION')) { + try { + await this.connection.commit(); + + return Object.create(null); + } catch (error) { + throw this.formatError(error); + } finally { + complete(); + } + } + + if (this.sql.startsWith('ROLLBACK TRANSACTION')) { + try { + await this.connection.rollback(); + + return Object.create(null); + } catch (error) { + throw this.formatError(error); + } finally { + complete(); + } + } + + if (this.sql.startsWith('SET TRANSACTION')) { + try { + await this.connection.execute(this.sql, [], { autoCommit: false }); + + return Object.create(null); + } catch (error) { + throw this.formatError(error); + } finally { + complete(); + } + } + + // QUERY SUPPORT + // As Oracle does everything in transaction, if autoCommit is not defined, we set it to true + if (this.autoCommit === undefined) { + if (this.connection.uuid) { + this.autoCommit = false; + } else { + this.autoCommit = true; + } + } + + // inbind parameters added byname. merge them + if ('inputParameters' in this.options && this.options.inputParameters !== null) { + Object.assign(this.bindParameters, this.options.inputParameters); + } + + const execOpts = this.getExecOptions(); + if (this.options.executeMany && bindDef.length > 0) { + execOpts.bindDefs = bindDef; + } + + const executePromise = this.options.executeMany + ? this.connection.executeMany(this.sql, this.bindParameters, execOpts) + : this.connection.execute(this.sql, this.bindParameters, execOpts); + try { + const result = await executePromise; + + return this.formatResults(result); + } catch (error) { + throw this.formatError(error); + } finally { + complete(); + } + } + + /** + * The parameters to query.run function are built here + * + * @param {string} sql + * @param {Array} values + * @param {string} dialect + */ + static formatBindParameters(sql, values, dialect) { + const replacementFunc = (match, key, values) => { + if (values[key] !== undefined) { + return `:${key}`; + } + + return undefined; + }; + + sql = AbstractQuery.formatBindParameters(sql, values, dialect, replacementFunc)[0]; + + return [sql, values]; + } + + /** + * Building the attribute map by matching the column names received + * from DB and the one in rawAttributes + * to sequelize format + * + * @param {object} attrsMap + * @param {object} rawAttributes + * @private + */ + _getAttributeMap(attrsMap, rawAttributes) { + attrsMap = Object.assign( + attrsMap, + reduce( + rawAttributes, + (mp, _, key) => { + const catalogKey = this.sequelize.queryInterface.queryGenerator.getCatalogName(key); + mp[catalogKey] = key; + + return mp; + }, + {}, + ), + ); + } + + /** + * Process rows received from the DB. + * Use parse function to parse the returned value + * to sequelize format + * + * @param {Array} rows + * @private + */ + _processRows(rows) { + let result = rows; + let attrsMap = {}; + + // When quoteIdentifiers is false we need to map the DB column names + // To the one in attribute list + if (this.sequelize.options.quoteIdentifiers === false) { + // Building the attribute map from this.options.attributes + // Needed in case of an aggregate function + attrsMap = reduce( + this.options.attributes, + (mp, v) => { + // Aggregate function is of form + // Fn {fn: 'min', min}, so we have the name in index one of the object + if (typeof v === 'object') { + v = v[1]; + } + + const catalogv = this.sequelize.queryInterface.queryGenerator.getCatalogName(v); + mp[catalogv] = v; + + return mp; + }, + {}, + ); + + // Building the attribute map by matching the column names received + // from DB and the one in model.rawAttributes + if (this.model) { + const modelDefinition = this.model.modelDefinition; + this._getAttributeMap(attrsMap, modelDefinition.rawAttributes); + } + + // If aliasesmapping exists we update the attribute map + if (this.options.aliasesMapping) { + const obj = Object.fromEntries(this.options.aliasesMapping); + rows = rows.map(row => + toPairs(row).reduce((acc, [key, value]) => { + const mapping = Object.values(obj).find(element => { + const catalogElement = + this.sequelize.queryInterface.queryGenerator.getCatalogName(element); + + return catalogElement === key; + }); + if (mapping) { + acc[mapping || key] = value; + } + + return acc; + }, {}), + ); + } + + // Modify the keys into the format that sequelize expects + result = rows.map(row => { + return mapKeys(row, (value, key) => { + const targetAttr = attrsMap[key]; + if (typeof targetAttr === 'string' && targetAttr !== key) { + return targetAttr; + } + + return key; + }); + }); + } + + // We parse the value received from the DB based on its datatype + if (this.model) { + const modelDefinition = this.model.modelDefinition; + result = result.map(row => { + return mapValues(row, (value, key) => { + if (modelDefinition.rawAttributes[key] && modelDefinition.rawAttributes[key].type) { + let typeid = modelDefinition.rawAttributes[key].type.toLocaleString(); + if (modelDefinition.rawAttributes[key].type.getDataTypeId() === 'JSON') { + value = JSON.parse(value); + } + + // For some types, the "name" of the type is returned with the length, we remove it + // For Boolean we skip this because BOOLEAN is mapped to CHAR(1) and we dont' want to + // remove the (1) for BOOLEAN + if ( + typeid.includes('(') && + modelDefinition.rawAttributes[key].type.getDataTypeId() !== 'BOOLEAN' + ) { + typeid = typeid.slice(0, typeid.indexOf('(')); + } + + const parser = this.sequelize.dialect.getParserForDatabaseDataType(typeid); + if ((value !== null) & parser) { + value = parser(value); + } + } + + return value; + }); + }); + } + + return result; + } + + /** + * High level function that handles the results of a query execution. + * Example: + * Oracle format : + * { rows: //All rows + [ [ 'Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production' ], + [ 'PL/SQL Release 11.2.0.1.0 - Production' ], + [ 'CORE\t11.2.0.1.0\tProduction' ], + [ 'TNS for 64-bit Windows: Version 11.2.0.1.0 - Production' ], + [ 'NLSRTL Version 11.2.0.1.0 - Production' ] ], + resultSet: undefined, + outBinds: undefined, //Used for dbms_put.line + rowsAffected: undefined, //Number of rows affected + metaData: [ { name: 'BANNER' } ] } + * + * @param {Array} data - The result of the query execution. + */ + formatResults(data) { + let result = this.instance; + if (this.isInsertQuery(data)) { + let insertData; + if (data.outBinds) { + const keys = Object.keys(this.options.outBindAttributes); + insertData = data.outBinds; + // For one row insert out bind array is 1D array + // we convert it to 2D array for uniformity + if (this.instance) { + insertData = [insertData]; + } + + // Mapping the bind parameter to their values + const res = insertData.map(row => { + const obj = {}; + row.forEach((element, index) => { + obj[keys[index]] = element[0]; + }); + + return obj; + }); + insertData = res; + // For bulk insert this.insert is undefined + // we map result to res, for one row insert + // result needs to be this.instance + if (!this.instance) { + result = res; + } + } + + this.handleInsertQuery(insertData); + + return [result, data.rowsAffected]; + } + + if (this.isDescribeQuery()) { + result = {}; + // Getting the table name on which we are doing describe query + const table = Object.keys(this.sequelize.models); + const modelAttributes = {}; + // Get the model raw attributes + if (this.sequelize.models && table.length > 0) { + this._getAttributeMap( + modelAttributes, + this.sequelize.models[table[0]].modelDefinition.rawAttributes, + ); + } + + data.rows.forEach(_result => { + if (_result.Default) { + _result.Default = _result.Default.replace(`('`, '') + .replace(`')`, '') + // eslint-disable-next-line unicorn/prefer-string-replace-all + .replace(/'/g, ''); /* jshint ignore: line */ + } + + // no need to add additional entries for column already in. + if (!(modelAttributes[_result.COLUMN_NAME] in result) && !(_result.COLUMN_NAME in result)) { + let key = modelAttributes[_result.COLUMN_NAME]; + if (!key) { + key = _result.COLUMN_NAME; + } + + result[key] = { + type: _result.DATA_TYPE.toUpperCase(), + // eslint-disable-next-line no-unneeded-ternary + allowNull: _result.NULLABLE === 'N' ? false : true, + defaultValue: undefined, + primaryKey: _result.CONSTRAINT_TYPE === 'P', + }; + } + }); + } else if (this.isShowIndexesQuery()) { + result = this.handleShowIndexesQuery(data.rows); + } else if (this.isSelectQuery()) { + const rows = data.rows; + const result = this._processRows(rows); + + return this.handleSelectQuery(result); + } else if (this.isCallQuery()) { + result = data.rows[0]; + } else if (this.isUpdateQuery()) { + result = [result, data.rowsAffected]; + } else if (this.isBulkUpdateQuery()) { + result = data.rowsAffected; + } else if (this.isDeleteQuery()) { + result = data.rowsAffected; + } else if (this.isUpsertQuery()) { + // Upsert Query, will return nothing + data = data.outBinds; + const keys = Object.keys(this.options.outBindAttributes); + const obj = {}; + for (const k in keys) { + obj[keys[k]] = data[k]; + } + + // eslint-disable-next-line unicorn/prefer-at + obj.isUpdate = data[data.length - 1]; + data = obj; + // eslint-disable-next-line eqeqeq + result = [{ isNewRecord: data.isUpdate, value: data }, data.isUpdate == 0]; + } else if (this.isShowConstraintsQuery()) { + result = this.handleShowConstraintsQuery(data); + } else if (this.isRawQuery()) { + // If data.rows exists then it is a select query + // Hence we would have two components + // metaData and rows and we return them + // as [data.rows, data.metaData] + // Else it is result of update/upsert/insert query + // and it has no rows so we return [data, data] + if (data && data.rows) { + return [data.rows, data.metaData]; + } + + return [data, data]; + } + + return result; + } + + handleShowConstraintsQuery(data) { + // Convert snake_case keys to camelCase as its generated by stored procedure + return data.rows.map(result => { + const constraint = {}; + for (const key in result) { + constraint[key] = result[key]; + } + + return constraint; + }); + } + + formatError(err) { + let match; + // ORA-00001: unique constraint (USER.XXXXXXX) violated + match = err.message.match(/unique constraint ([\s\S]*) violated/); + if (match && match.length > 1) { + match[1] = match[1].replace('(', '').replace(')', '').split('.')[1]; // As we get (SEQUELIZE.UNIQNAME), we replace to have UNIQNAME + const errors = []; + let fields = []; + let message = 'Validation error'; + let uniqueKey = null; + + if (this.model) { + const uniqueKeys = this.model.getIndexes(); + + uniqueKey = uniqueKeys.find(key => { + // We check directly AND with quotes -> "a"" === a || "a" === "a" + return ( + key.name.toUpperCase() === match[1].toUpperCase() || + key.name.toUpperCase() === `"${match[1].toUpperCase()}"` + ); + }); + + if (uniqueKey) { + fields = uniqueKey.fields; + } + + // eslint-disable-next-line no-implicit-coercion + if (uniqueKey && !!uniqueKey.msg) { + message = uniqueKey.msg; + } + + fields.forEach(field => { + errors.push( + new ValidationErrorItem( + this.getUniqueConstraintErrorMessage(field), + 'unique violation', + field, + null, + ), + ); + }); + } + + return new UniqueConstraintError({ + message, + errors, + cause: err, + fields, + }); + } + + // ORA-02291: integrity constraint (string.string) violated - parent key not found / ORA-02292: integrity constraint (string.string) violated - child record found + match = err.message.match(/ORA-02291/) || err.message.match(/ORA-02292/); + if (match && match.length > 0) { + return new ForeignKeyConstraintError({ + fields: null, + index: match[1], + cause: err, + }); + } + + // ORA-02443: Cannot drop constraint - nonexistent constraint + match = err.message.match(/ORA-02443/); + if (match && match.length > 0) { + return new UnknownConstraintError(match[1]); + } + + return new DatabaseError(err); + } + + isShowIndexesQuery() { + // eslint-disable-next-line unicorn/prefer-includes + return this.sql.indexOf('SELECT i.index_name,i.table_name, i.column_name, u.uniqueness') > -1; + } + + isSelectCountQuery() { + return this.sql.toUpperCase().includes('SELECT COUNT('); + } + + handleShowIndexesQuery(data) { + const acc = []; + + // We first treat the datas + data.forEach(indexRecord => { + // We create the object + if (!acc[indexRecord.INDEX_NAME]) { + acc[indexRecord.INDEX_NAME] = { + unique: indexRecord.UNIQUENESS === 'UNIQUE', + primary: indexRecord.CONSTRAINT_TYPE === 'P', + name: indexRecord.INDEX_NAME, + tableName: indexRecord.TABLE_NAME.toLowerCase(), + type: undefined, + }; + acc[indexRecord.INDEX_NAME].fields = []; + } + + // We create the fields + acc[indexRecord.INDEX_NAME].fields.push({ + name: indexRecord.COLUMN_NAME, + length: undefined, + order: indexRecord.DESCEND, + collate: undefined, + }); + }); + + const returnIndexes = []; + const accKeys = Object.keys(acc); + for (const accKey of accKeys) { + const columns = {}; + columns.fields = acc[accKey].fields; + columns.unique = acc[accKey].unique; + // We are generating index field name in the format sequelize expects + // to avoid creating a unique index on auto-generated index name + // eslint-disable-next-line unicorn/prefer-regexp-test + if (acc[accKey].name.match(/SYS_C[0-9]*/)) { + acc[accKey].name = nameIndex(columns, acc[accKey].tableName).name; + } + + // eslint-disable-next-line array-callback-return + acc[accKey].fields.map(field => { + field.attribute = field.name; + delete field.name; + }); + returnIndexes.push(acc[accKey]); + } + + return returnIndexes; + } + + handleInsertQuery(results, metaData) { + if (this.instance && results && results.length > 0) { + if ('pkReturnVal' in results[0]) { + // The PK of the table is a reserved word (ex : uuid), we have to change the name in the result for the model to find the value correctly + results[0][this.model.primaryKeyAttribute] = results[0].pkReturnVal; + delete results[0].pkReturnVal; + } + + // add the inserted row id to the instance + const modelDefinition = this.model.modelDefinition; + const autoIncrementField = modelDefinition.autoIncrementAttributeName; + let id = null; + let autoIncrementAlias = null; + + if ( + Object.hasOwn(modelDefinition.rawAttributes, autoIncrementField) && + modelDefinition.rawAttributes[autoIncrementField].field !== undefined + ) { + autoIncrementAlias = modelDefinition.rawAttributes[autoIncrementField].field; + } + + id = id || (results && results[0][this.getInsertIdField()]); + id = id || (metaData && metaData[this.getInsertIdField()]); + id = id || (results && results[0][autoIncrementField]); + id = id || (autoIncrementAlias && results && results[0][autoIncrementAlias]); + + this.instance[autoIncrementField] = id; + } + } +} diff --git a/packages/oracle/tsconfig.json b/packages/oracle/tsconfig.json new file mode 100644 index 000000000000..cfbb24587f8d --- /dev/null +++ b/packages/oracle/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig-preset.json", + "compilerOptions": { + "outDir": "./lib", + "rootDir": "./src" + }, + "include": ["./src/**/*.ts"] +} diff --git a/packages/oracle/typedoc.json b/packages/oracle/typedoc.json new file mode 100644 index 000000000000..a6500efb0151 --- /dev/null +++ b/packages/oracle/typedoc.json @@ -0,0 +1,5 @@ +{ + "extends": ["../../typedoc.base.json"], + "entryPoints": ["src/index.ts"], + "excludeExternals": true +} diff --git a/packages/snowflake/package.json b/packages/snowflake/package.json index a6e3cd11fa91..dfa61834ae86 100644 --- a/packages/snowflake/package.json +++ b/packages/snowflake/package.json @@ -38,7 +38,7 @@ "dependencies": { "@sequelize/core": "workspace:*", "@sequelize/utils": "workspace:*", - "@types/snowflake-sdk": "^1.6.23", + "@types/snowflake-sdk": "1.6.23", "lodash": "^4.17.21", "snowflake-sdk": "^1.10.0" } diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md deleted file mode 100644 index ad4758077967..000000000000 --- a/packages/utils/CHANGELOG.md +++ /dev/null @@ -1,8 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# [7.0.0-alpha.41](https://github.com/sequelize/sequelize/compare/v7.0.0-alpha.40...v7.0.0-alpha.41) (2024-05-17) - -**Note:** Version bump only for package @sequelize/utils diff --git a/packages/validator-js/CHANGELOG.md b/packages/validator-js/CHANGELOG.md deleted file mode 100644 index cb2f514a2f3a..000000000000 --- a/packages/validator-js/CHANGELOG.md +++ /dev/null @@ -1,8 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# [7.0.0-alpha.41](https://github.com/sequelize/sequelize/compare/v7.0.0-alpha.40...v7.0.0-alpha.41) (2024-05-17) - -**Note:** Version bump only for package @sequelize/validator.js diff --git a/test/esm-named-exports.test.js b/test/esm-named-exports.test.js index f9aa4f3533e2..cd2ac968f305 100644 --- a/test/esm-named-exports.test.js +++ b/test/esm-named-exports.test.js @@ -64,6 +64,7 @@ const ignoredCjsKeysMap = { '@sequelize/mariadb': ['__esModule'], '@sequelize/mssql': ['__esModule'], '@sequelize/mysql': ['__esModule'], + '@sequelize/oracle': ['__esModule'], '@sequelize/postgres': ['__esModule'], '@sequelize/snowflake': ['__esModule'], '@sequelize/sqlite3': ['__esModule'], diff --git a/yarn.lock b/yarn.lock index d1643979d6d7..86cfbddebb63 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,13 +5,6 @@ __metadata: version: 8 cacheKey: 10c0 -"@aashutoshrathi/word-wrap@npm:^1.2.3": - version: 1.2.6 - resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" - checksum: 10c0/53c2b231a61a46792b39a0d43bc4f4f776bb4542aa57ee04930676802e5501282c2fc8aac14e4cd1f1120ff8b52616b6ff5ab539ad30aa2277d726444b71619f - languageName: node - linkType: hard - "@ampproject/remapping@npm:^2.2.0": version: 2.3.0 resolution: "@ampproject/remapping@npm:2.3.0" @@ -1137,28 +1130,28 @@ __metadata: linkType: hard "@azure/abort-controller@npm:^2.0.0": - version: 2.1.1 - resolution: "@azure/abort-controller@npm:2.1.1" + version: 2.1.2 + resolution: "@azure/abort-controller@npm:2.1.2" dependencies: tslib: "npm:^2.6.2" - checksum: 10c0/9dd6a0b240646d76abe9a92641755cd1e7ed87ef8caf4a16d737fe588a2f26e9a42dd9e1f77da7d10e8c8489ebe17a50a75837226a69c1ae8be83bf20e624aa3 + checksum: 10c0/3771b6820e33ebb56e79c7c68e2288296b8c2529556fbd29cf4cf2fbff7776e7ce1120072972d8df9f1bf50e2c3224d71a7565362b589595563f710b8c3d7b79 languageName: node linkType: hard "@azure/core-auth@npm:^1.3.0, @azure/core-auth@npm:^1.4.0, @azure/core-auth@npm:^1.5.0": - version: 1.7.1 - resolution: "@azure/core-auth@npm:1.7.1" + version: 1.7.2 + resolution: "@azure/core-auth@npm:1.7.2" dependencies: "@azure/abort-controller": "npm:^2.0.0" "@azure/core-util": "npm:^1.1.0" tslib: "npm:^2.6.2" - checksum: 10c0/34ea323097174495cd4cfc291cc39de7af53523a7fbc31b6fd3468c8dd47aa214734b4ddb540c70da8d693fc57629ed52337b5d770a940a97e9edb18f3d285a7 + checksum: 10c0/2b4c489855308cea46363dc8f216eeb63cb85aea08f1ab7cff0a6e47604eed2b0fc46415d7f6d71da0aa7922b81c631920d05698eb14454b65be07825c5c599a languageName: node linkType: hard "@azure/core-client@npm:^1.3.0, @azure/core-client@npm:^1.4.0, @azure/core-client@npm:^1.5.0": - version: 1.9.1 - resolution: "@azure/core-client@npm:1.9.1" + version: 1.9.2 + resolution: "@azure/core-client@npm:1.9.2" dependencies: "@azure/abort-controller": "npm:^2.0.0" "@azure/core-auth": "npm:^1.4.0" @@ -1167,18 +1160,18 @@ __metadata: "@azure/core-util": "npm:^1.6.1" "@azure/logger": "npm:^1.0.0" tslib: "npm:^2.6.2" - checksum: 10c0/da0c7b54e9447b73674e178527a126068ad56f8de95cffa95be297674edd10233bed865b725eae7aef34d8f7ed3ef82bc4806f931207bdc3c6982413aae53f2f + checksum: 10c0/4dab1f3b070f7c2c5a8390f81c7afdf31c030ad0599e75e16b9684959fb666cb57d34b63977639a60a7535f63f30a8a708210e8e48ff68a30732b7518044ebce languageName: node linkType: hard "@azure/core-http-compat@npm:^2.0.1": - version: 2.1.1 - resolution: "@azure/core-http-compat@npm:2.1.1" + version: 2.1.2 + resolution: "@azure/core-http-compat@npm:2.1.2" dependencies: "@azure/abort-controller": "npm:^2.0.0" "@azure/core-client": "npm:^1.3.0" "@azure/core-rest-pipeline": "npm:^1.3.0" - checksum: 10c0/4a8f1845b223be9f44d94b52d08223ca9e0d4036a91492a27d0d3cbd1cb9f696df794dba1d58a7530c5926d5dbe51123e063e3c2e559d01313ee498ee3b07661 + checksum: 10c0/e7b5374819d740c96c075956c756a753b7e9f6d7774bbadcc5000c3c4f808554e4d7146ccde7b94bcb21c39ed4a7e5b043b2a3b7d208b959310ea7e1440decca languageName: node linkType: hard @@ -1205,39 +1198,39 @@ __metadata: linkType: hard "@azure/core-lro@npm:^2.2.0": - version: 2.7.1 - resolution: "@azure/core-lro@npm:2.7.1" + version: 2.7.2 + resolution: "@azure/core-lro@npm:2.7.2" dependencies: "@azure/abort-controller": "npm:^2.0.0" "@azure/core-util": "npm:^1.2.0" "@azure/logger": "npm:^1.0.0" tslib: "npm:^2.6.2" - checksum: 10c0/55ce51fa74fbbb8f702e5fda1ab3983d9575fc6188be34473f339c2096be203fbc4bc38cc1aacc75576a654bbc319ae198e316a12745f56bac12d0c20baa98ca + checksum: 10c0/bee809e47661b40021bbbedf88de54019715fdfcc95ac552b1d901719c29d78e293eeab51257b8f5155aac768eb4ea420715004d00d6e32109f5f97db5960d39 languageName: node linkType: hard "@azure/core-paging@npm:^1.1.1": - version: 1.6.1 - resolution: "@azure/core-paging@npm:1.6.1" + version: 1.6.2 + resolution: "@azure/core-paging@npm:1.6.2" dependencies: tslib: "npm:^2.6.2" - checksum: 10c0/a68e6cf2ec324022dc60065b8916576b2f85b0a2b038a9a501a97b38a1977b6c8fcf1adef4db615910c442dcf75123dee1fb2c7cbfa42a9730fd26d89a3b9f67 + checksum: 10c0/c727782f8dc66eff50c03421af2ca55f497f33e14ec845f5918d76661c57bc8e3a7ca9fa3d39181287bfbfa45f28cb3d18b67c31fd36bbe34146387dbd07b440 languageName: node linkType: hard "@azure/core-rest-pipeline@npm:^1.1.0, @azure/core-rest-pipeline@npm:^1.3.0, @azure/core-rest-pipeline@npm:^1.8.1, @azure/core-rest-pipeline@npm:^1.9.1": - version: 1.15.1 - resolution: "@azure/core-rest-pipeline@npm:1.15.1" + version: 1.16.0 + resolution: "@azure/core-rest-pipeline@npm:1.16.0" dependencies: "@azure/abort-controller": "npm:^2.0.0" "@azure/core-auth": "npm:^1.4.0" "@azure/core-tracing": "npm:^1.0.1" - "@azure/core-util": "npm:^1.3.0" + "@azure/core-util": "npm:^1.9.0" "@azure/logger": "npm:^1.0.0" http-proxy-agent: "npm:^7.0.0" https-proxy-agent: "npm:^7.0.0" tslib: "npm:^2.6.2" - checksum: 10c0/11994f2c5b041bfe72892a3086a8ba23ddf700cb293ce0e36d1cd41676e492b0dae8f3a19aadaa315008d49811bfbacf567b2f363916cabf26d473d2d7c07bf0 + checksum: 10c0/9a798563eb1514e1eabaa9c072c3dc0d25ca837e94bf1e778431a749b3634d661866fe00ac0f49dd2938917001a241ea2de84ac6ea5179b5410b3a0807054a0b languageName: node linkType: hard @@ -1252,21 +1245,21 @@ __metadata: linkType: hard "@azure/core-tracing@npm:^1.0.0, @azure/core-tracing@npm:^1.0.1": - version: 1.1.1 - resolution: "@azure/core-tracing@npm:1.1.1" + version: 1.1.2 + resolution: "@azure/core-tracing@npm:1.1.2" dependencies: tslib: "npm:^2.6.2" - checksum: 10c0/e8c77e6acfe74965cd25389132c2b8009f48cb146e6ef1fe472923e6719dcb3575175af68f56dd38b78493dfc4264f5ea79a37e12cb7ebac3e93f090d4cb8ba2 + checksum: 10c0/0e844d581117ae81318a503ddfc143146b847ed9152d0c84f20fdc4cb0b2187a4e9da29aed13d5b7a201f39fe601a59c4db6455005ed8e0d3b5aab0ee77a56e1 languageName: node linkType: hard -"@azure/core-util@npm:^1.0.0, @azure/core-util@npm:^1.1.0, @azure/core-util@npm:^1.1.1, @azure/core-util@npm:^1.2.0, @azure/core-util@npm:^1.3.0, @azure/core-util@npm:^1.6.1": - version: 1.8.1 - resolution: "@azure/core-util@npm:1.8.1" +"@azure/core-util@npm:^1.0.0, @azure/core-util@npm:^1.1.0, @azure/core-util@npm:^1.1.1, @azure/core-util@npm:^1.2.0, @azure/core-util@npm:^1.6.1, @azure/core-util@npm:^1.9.0": + version: 1.9.0 + resolution: "@azure/core-util@npm:1.9.0" dependencies: "@azure/abort-controller": "npm:^2.0.0" tslib: "npm:^2.6.2" - checksum: 10c0/a321e2dc06788a62cce7ec1fc2967a60818145c737694ea27c8cd60df52b076fbc338baa8a76b70706c6f3658f7f4e92cbf821f91efadefcc9286b14f1f45f98 + checksum: 10c0/6eb6efc8b8401fd6e3b56631e8e9a1dbc23a0048ae3bf498d10163624f805032a7730905465b2ebe95c840e5e939e66bf320448de8df50f66346e89b1295f9e7 languageName: node linkType: hard @@ -1312,44 +1305,44 @@ __metadata: linkType: hard "@azure/logger@npm:^1.0.0": - version: 1.1.1 - resolution: "@azure/logger@npm:1.1.1" + version: 1.1.2 + resolution: "@azure/logger@npm:1.1.2" dependencies: tslib: "npm:^2.6.2" - checksum: 10c0/79014d78774b7a24c236a9c83550e9769c39cb6d4469c23ab35998dd1a67fed8fd43c947eb7382cdeab826747fa7fabc686a37e4aee67535cc6ce5e0302c9323 + checksum: 10c0/829c1da363b8fe732ca26326400575dc824e1032974dc499db539e9599e0e4f1b1f4bf936b68329171fece7e2d4bba3ffaaebb35ac60b73db4715c6dc026147a languageName: node linkType: hard "@azure/msal-browser@npm:^3.5.0": - version: 3.11.1 - resolution: "@azure/msal-browser@npm:3.11.1" + version: 3.14.0 + resolution: "@azure/msal-browser@npm:3.14.0" dependencies: - "@azure/msal-common": "npm:14.8.1" - checksum: 10c0/3588a45e28be299a799c96bfabe6fad9aebdf92c37b523e9ea32d1e7abca57b19fa2a657f80764724899491d31469003cd7b486f040dbd26ef9ad8bdd633e41d + "@azure/msal-common": "npm:14.10.0" + checksum: 10c0/435c06bdd09b8c8d393b74d901cecda702f6ec962c79e3a5baa5706bd1144679008469cef2c35f6c8e17db0c125134f61dc106b519c67b5b6ae3158548abb165 languageName: node linkType: hard -"@azure/msal-common@npm:14.8.1": - version: 14.8.1 - resolution: "@azure/msal-common@npm:14.8.1" - checksum: 10c0/979b3715c77fd050416b5b804d5c421e6bdbe1d94e750b32bc7855c7fec80e76f4f0bf51626624211487412fdd30e41748f390f58514e8ae6bd98ffe0fa2023e +"@azure/msal-common@npm:14.10.0": + version: 14.10.0 + resolution: "@azure/msal-common@npm:14.10.0" + checksum: 10c0/532aa92665f7ec91e57e96606bf2342ac751bc1f3054a094b26e376669732e8f7c957a5c65d62e381daa3cb097e2990d7cf077080e2d50159884f5ad573157d4 languageName: node linkType: hard "@azure/msal-node@npm:^2.5.1": - version: 2.6.6 - resolution: "@azure/msal-node@npm:2.6.6" + version: 2.8.1 + resolution: "@azure/msal-node@npm:2.8.1" dependencies: - "@azure/msal-common": "npm:14.8.1" + "@azure/msal-common": "npm:14.10.0" jsonwebtoken: "npm:^9.0.0" uuid: "npm:^8.3.0" - checksum: 10c0/b9178b3716c1977da4c1c64c3d565b413d602c297368142bc0d9bb38ade7eda9951e3777741f55c9eafa3530977efc115c632251fe94809c63d2b289c6791ae9 + checksum: 10c0/69332453c0d08f69c885542384244784197c252a22b715aa77a6d26913b892fb3fbdd1dbd493450e49605aca1d8990f1f4a84a21ab72f7e89972902ab8a99ade languageName: node linkType: hard "@azure/storage-blob@npm:^12.11.0": - version: 12.17.0 - resolution: "@azure/storage-blob@npm:12.17.0" + version: 12.18.0 + resolution: "@azure/storage-blob@npm:12.18.0" dependencies: "@azure/abort-controller": "npm:^1.0.0" "@azure/core-http": "npm:^3.0.0" @@ -1359,7 +1352,7 @@ __metadata: "@azure/logger": "npm:^1.0.0" events: "npm:^3.0.0" tslib: "npm:^2.2.0" - checksum: 10c0/462e04cdfcbc891a32522ba2c6cf922c2621996255b5d436411bc4c55f7bcd86ca2693881cad32df718187f574a2799cb118672ebf92f3842be02813735737ac + checksum: 10c0/0bd50e1516ac8a137c3737fbf32b73b188936ed80400526eca07c737d9c9ad790465a4462157e8cbb2dc2e459bcb328c4dd31f6a39631505ed85304d452ecf72 languageName: node linkType: hard @@ -1404,16 +1397,16 @@ __metadata: linkType: hard "@babel/eslint-parser@npm:^7.21.3": - version: 7.24.1 - resolution: "@babel/eslint-parser@npm:7.24.1" + version: 7.24.5 + resolution: "@babel/eslint-parser@npm:7.24.5" dependencies: "@nicolo-ribaudo/eslint-scope-5-internals": "npm:5.1.1-v1" eslint-visitor-keys: "npm:^2.1.0" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 - checksum: 10c0/76b066be5245fa24ea5726bea24ceca75811599dce43db5e120e91283f3a27be150a2b0559a8472bec2824f6abc66fb29e90b3f1889c596ec855a811fc83dc90 + eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 + checksum: 10c0/bf8e89a00bd0895962c8c592b3f81a21186a9002bbbc57b0d6d9a72a8aeb087858222842f094479dd96f1783a5a1744ba9f1e907fdba60aa92f4775275550097 languageName: node linkType: hard @@ -1567,11 +1560,11 @@ __metadata: linkType: hard "@babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2": - version: 7.24.4 - resolution: "@babel/runtime@npm:7.24.4" + version: 7.24.5 + resolution: "@babel/runtime@npm:7.24.5" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: 10c0/785aff96a3aa8ff97f90958e1e8a7b1d47f793b204b47c6455eaadc3f694f48c97cd5c0a921fe3596d818e71f18106610a164fb0f1c71fd68c622a58269d537c + checksum: 10c0/05730e43e8ba6550eae9fd4fb5e7d9d3cb91140379425abcb2a1ff9cebad518a280d82c4c4b0f57ada26a863106ac54a748d90c775790c0e2cd0ddd85ccdf346 languageName: node linkType: hard @@ -1855,7 +1848,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": +"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.6.1": version: 4.10.0 resolution: "@eslint-community/regexpp@npm:4.10.0" checksum: 10c0/c5f60ef1f1ea7649fa7af0e80a5a79f64b55a8a8fa5086de4727eb4c86c652aedee407a9c143b8995d2c0b2d75c1222bec9ba5d73dbfc1f314550554f0979ef4 @@ -1918,27 +1911,25 @@ __metadata: linkType: hard "@google-cloud/storage@npm:^7.7.0": - version: 7.9.0 - resolution: "@google-cloud/storage@npm:7.9.0" + version: 7.11.0 + resolution: "@google-cloud/storage@npm:7.11.0" dependencies: "@google-cloud/paginator": "npm:^5.0.0" "@google-cloud/projectify": "npm:^4.0.0" "@google-cloud/promisify": "npm:^4.0.0" abort-controller: "npm:^3.0.0" async-retry: "npm:^1.3.3" - compressible: "npm:^2.0.12" duplexify: "npm:^4.1.3" - ent: "npm:^2.2.0" fast-xml-parser: "npm:^4.3.0" gaxios: "npm:^6.0.2" google-auth-library: "npm:^9.6.3" + html-entities: "npm:^2.5.2" mime: "npm:^3.0.0" - mime-types: "npm:^2.0.8" p-limit: "npm:^3.0.1" retry-request: "npm:^7.0.0" teeny-request: "npm:^9.0.0" uuid: "npm:^8.0.0" - checksum: 10c0/20d4acfb2104ca2e1b167e4cc43f1303fb006fd546b7e76962789d1636e06a659f46be6db64333c4bc073f27962970de72593321f3578dcf5d5e567a0bc0c0d8 + checksum: 10c0/4f9dfd18033256eff8ba69c6f9bdd77b251ecf40627d745cfc92d221460b2f657982cbb0892e869e5654ba040d4727b8c9556b5bf5003b5a281bccb3aa2e060a languageName: node linkType: hard @@ -2304,39 +2295,39 @@ __metadata: linkType: hard "@npmcli/fs@npm:^3.1.0": - version: 3.1.0 - resolution: "@npmcli/fs@npm:3.1.0" + version: 3.1.1 + resolution: "@npmcli/fs@npm:3.1.1" dependencies: semver: "npm:^7.3.5" - checksum: 10c0/162b4a0b8705cd6f5c2470b851d1dc6cd228c86d2170e1769d738c1fbb69a87160901411c3c035331e9e99db72f1f1099a8b734bf1637cc32b9a5be1660e4e1e + checksum: 10c0/c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99 languageName: node linkType: hard "@npmcli/git@npm:^5.0.0": - version: 5.0.4 - resolution: "@npmcli/git@npm:5.0.4" + version: 5.0.7 + resolution: "@npmcli/git@npm:5.0.7" dependencies: "@npmcli/promise-spawn": "npm:^7.0.0" lru-cache: "npm:^10.0.1" npm-pick-manifest: "npm:^9.0.0" - proc-log: "npm:^3.0.0" + proc-log: "npm:^4.0.0" promise-inflight: "npm:^1.0.1" promise-retry: "npm:^2.0.1" semver: "npm:^7.3.5" which: "npm:^4.0.0" - checksum: 10c0/e70aa4d980c356cc97cb3c5b24d3fe88e3b26672ace60ad2ff1a7d2a9f139143ebb32975380bd5ad798a3ba13c91faf76de9a85dd1e8f731797a5c963b61b35a + checksum: 10c0/d9895fce3e554e927411ead941d434233585a3edaf8d2ebe3e8d48fdd14e2ce238d227248df30e3300b1c050e982459f4d0b18375bd3c17c4edeb0621da33ade languageName: node linkType: hard "@npmcli/installed-package-contents@npm:^2.0.1": - version: 2.0.2 - resolution: "@npmcli/installed-package-contents@npm:2.0.2" + version: 2.1.0 + resolution: "@npmcli/installed-package-contents@npm:2.1.0" dependencies: npm-bundled: "npm:^3.0.0" npm-normalize-package-bin: "npm:^3.0.0" bin: - installed-package-contents: lib/index.js - checksum: 10c0/03efadb365997e3b54d1d1ea30ef3555729a68939ab2b7b7800a4a2750afb53da222f52be36bd7c44950434c3e26cbe7be28dac093efdf7b1bbe9e025ab62a07 + installed-package-contents: bin/index.js + checksum: 10c0/f5ecba0d45fc762f3e0d5def29fbfabd5d55e8147b01ae0a101769245c2e0038bc82a167836513a98aaed0a15c3d81fcdb232056bb8a962972a432533e518fce languageName: node linkType: hard @@ -2358,26 +2349,26 @@ __metadata: linkType: hard "@npmcli/package-json@npm:^5.0.0": - version: 5.0.0 - resolution: "@npmcli/package-json@npm:5.0.0" + version: 5.1.0 + resolution: "@npmcli/package-json@npm:5.1.0" dependencies: "@npmcli/git": "npm:^5.0.0" glob: "npm:^10.2.2" hosted-git-info: "npm:^7.0.0" json-parse-even-better-errors: "npm:^3.0.0" normalize-package-data: "npm:^6.0.0" - proc-log: "npm:^3.0.0" + proc-log: "npm:^4.0.0" semver: "npm:^7.5.3" - checksum: 10c0/489b0e42d05c1c3c43ba94b6435c062ae28bee3e8ebf3b8e0977fe4ab8eb37fe6ab019203b38f39b54a592d85df2a602c0d700fc23adc630f4e7bfb0207a8a9e + checksum: 10c0/81bcac33276da86aae5ae62bfc70bfa6da1c1e1a7b0b9ecf3586279186f7c5d2e056ea7323b658f08999fe474e1ae0334df00cbdf48521e2489115f74e28f6af languageName: node linkType: hard "@npmcli/promise-spawn@npm:^7.0.0": - version: 7.0.1 - resolution: "@npmcli/promise-spawn@npm:7.0.1" + version: 7.0.2 + resolution: "@npmcli/promise-spawn@npm:7.0.2" dependencies: which: "npm:^4.0.0" - checksum: 10c0/441024049170fc9dd0c793fef7366fd1b2a36c06f1036c52ac4a5d0f2d46deced89f2a94fef20f51aa9934edb4d611ff76b060be2b82086d29d2094ee1b46122 + checksum: 10c0/8f2af5bc2c1b1ccfb9bcd91da8873ab4723616d8bd5af877c0daa40b1e2cbfa4afb79e052611284179cae918c945a1b99ae1c565d78a355bec1a461011e89f71 languageName: node linkType: hard @@ -2997,6 +2988,26 @@ __metadata: languageName: unknown linkType: soft +"@sequelize/oracle@workspace:packages/oracle": + version: 0.0.0-use.local + resolution: "@sequelize/oracle@workspace:packages/oracle" + dependencies: + "@sequelize/core": "workspace:*" + "@sequelize/utils": "workspace:*" + "@types/chai": "npm:4.3.14" + "@types/mocha": "npm:10.0.6" + "@types/oracledb": "npm:^6.3" + "@types/sinon": "npm:17.0.3" + chai: "npm:4.4.1" + dayjs: "npm:^1.11.10" + lodash: "npm:4.17.21" + mocha: "npm:10.4.0" + oracledb: "npm:6.5" + semver: "npm:7.6.0" + sinon: "npm:18.0.0" + languageName: unknown + linkType: soft + "@sequelize/postgres@workspace:packages/postgres": version: 0.0.0-use.local resolution: "@sequelize/postgres@workspace:packages/postgres" @@ -3024,7 +3035,7 @@ __metadata: dependencies: "@sequelize/core": "workspace:*" "@sequelize/utils": "workspace:*" - "@types/snowflake-sdk": "npm:^1.6.23" + "@types/snowflake-sdk": "npm:1.6.23" lodash: "npm:^4.17.21" snowflake-sdk: "npm:^1.10.0" languageName: unknown @@ -3080,12 +3091,12 @@ __metadata: languageName: node linkType: hard -"@sigstore/bundle@npm:^2.3.0, @sigstore/bundle@npm:^2.3.1": - version: 2.3.1 - resolution: "@sigstore/bundle@npm:2.3.1" +"@sigstore/bundle@npm:^2.3.2": + version: 2.3.2 + resolution: "@sigstore/bundle@npm:2.3.2" dependencies: - "@sigstore/protobuf-specs": "npm:^0.3.1" - checksum: 10c0/f5cc08e6420055ca20c1fa458725cf3d090974c3650aacfb6ba0b09d9c59149e5f4d8c5bfe9f2253daf2c29548262e9e4ea83b4b2fc4abbaf93cf49ee2687f05 + "@sigstore/protobuf-specs": "npm:^0.3.2" + checksum: 10c0/872a95928236bd9950a2ecc66af1c60a82f6b482a62a20d0f817392d568a60739a2432cad70449ac01e44e9eaf85822d6d9ebc6ade6cb3e79a7d62226622eb5d languageName: node linkType: hard @@ -3103,10 +3114,10 @@ __metadata: languageName: node linkType: hard -"@sigstore/protobuf-specs@npm:^0.3.0, @sigstore/protobuf-specs@npm:^0.3.1": - version: 0.3.1 - resolution: "@sigstore/protobuf-specs@npm:0.3.1" - checksum: 10c0/bc926aeb472dcd1f99e887d54d9402e259e186ee2a15cdb395cdb565fdd3457f84a044ef355c96359c3c625127a93fb3c45c7e3bd2f16ac0912a58a6bf3fc137 +"@sigstore/protobuf-specs@npm:^0.3.2": + version: 0.3.2 + resolution: "@sigstore/protobuf-specs@npm:0.3.2" + checksum: 10c0/108eed419181ff599763f2d28ff5087e7bce9d045919de548677520179fe77fb2e2b7290216c93c7a01bdb2972b604bf44599273c991bbdf628fbe1b9b70aacb languageName: node linkType: hard @@ -3121,15 +3132,17 @@ __metadata: languageName: node linkType: hard -"@sigstore/sign@npm:^2.3.0": - version: 2.3.0 - resolution: "@sigstore/sign@npm:2.3.0" +"@sigstore/sign@npm:^2.3.2": + version: 2.3.2 + resolution: "@sigstore/sign@npm:2.3.2" dependencies: - "@sigstore/bundle": "npm:^2.3.0" + "@sigstore/bundle": "npm:^2.3.2" "@sigstore/core": "npm:^1.0.0" - "@sigstore/protobuf-specs": "npm:^0.3.1" - make-fetch-happen: "npm:^13.0.0" - checksum: 10c0/e11b9318c283604747e0ff6084e17f9da210dd999e8c5c32a229db6b9a9faf54698994458c2a09dec0a1a43ac99eb0d278ca6d5d86045145a96c941aad969e1d + "@sigstore/protobuf-specs": "npm:^0.3.2" + make-fetch-happen: "npm:^13.0.1" + proc-log: "npm:^4.2.0" + promise-retry: "npm:^2.0.1" + checksum: 10c0/a1e7908f3e4898f04db4d713fa10ddb3ae4f851592c9b554f1269073211e1417528b5088ecee60f27039fde5a5426ae573481d77cfd7e4395d2a0ddfcf5f365f languageName: node linkType: hard @@ -3143,24 +3156,24 @@ __metadata: languageName: node linkType: hard -"@sigstore/tuf@npm:^2.3.1": - version: 2.3.2 - resolution: "@sigstore/tuf@npm:2.3.2" +"@sigstore/tuf@npm:^2.3.4": + version: 2.3.4 + resolution: "@sigstore/tuf@npm:2.3.4" dependencies: - "@sigstore/protobuf-specs": "npm:^0.3.0" - tuf-js: "npm:^2.2.0" - checksum: 10c0/c05008fa46efec1546cc2cdb46e54d6a4773cbd05efa3ad7272339b4f935d58634b9f8494b109197b506116fb894206bf1cdb1fc09351a00297c23ef3c2a1a01 + "@sigstore/protobuf-specs": "npm:^0.3.2" + tuf-js: "npm:^2.2.1" + checksum: 10c0/97839882d787196517933df5505fae4634975807cc7adcd1783c7840c2a9729efb83ada47556ec326d544b9cb0d1851af990dc46eebb5fe7ea17bf7ce1fc0b8c languageName: node linkType: hard -"@sigstore/verify@npm:^1.2.0": - version: 1.2.0 - resolution: "@sigstore/verify@npm:1.2.0" +"@sigstore/verify@npm:^1.2.1": + version: 1.2.1 + resolution: "@sigstore/verify@npm:1.2.1" dependencies: - "@sigstore/bundle": "npm:^2.3.1" + "@sigstore/bundle": "npm:^2.3.2" "@sigstore/core": "npm:^1.1.0" - "@sigstore/protobuf-specs": "npm:^0.3.1" - checksum: 10c0/ed0d9cb8c71bde23bd48e40725e5b4bd3ff1595b6d9e4b1ed4f2dfd06f6bf76a3dc69d86f8b2e4488a9cb4ade0d9a41718bd33119b9afca66f90badd52a373fe + "@sigstore/protobuf-specs": "npm:^0.3.2" + checksum: 10c0/af06580a8d5357c31259da1ac7323137054e0ac41e933278d95a4bc409a4463620125cb4c00b502f6bc32fdd68c2293019391b0d31ed921ee3852a9e84358628 languageName: node linkType: hard @@ -3946,13 +3959,13 @@ __metadata: languageName: node linkType: hard -"@tufjs/models@npm:2.0.0": - version: 2.0.0 - resolution: "@tufjs/models@npm:2.0.0" +"@tufjs/models@npm:2.0.1": + version: 2.0.1 + resolution: "@tufjs/models@npm:2.0.1" dependencies: "@tufjs/canonical-json": "npm:2.0.0" - minimatch: "npm:^9.0.3" - checksum: 10c0/252f525b05526077430920b30b125e197a3d711f4c6d1ceeee9cea5044035e4d94e57db481d96bd8e9d1ce5ee23fcc9fe989e7e0c9c2aec7e1edc27326ee16e6 + minimatch: "npm:^9.0.4" + checksum: 10c0/ad9e82fd921954501fd90ed34ae062254637595577ad13fdc1e076405c0ea5ee7d8aebad09e63032972fd92b07f1786c15b24a195a171fc8ac470ca8e2ffbcc4 languageName: node linkType: hard @@ -3988,6 +4001,13 @@ __metadata: languageName: node linkType: hard +"@types/chai@npm:4.3.14": + version: 4.3.14 + resolution: "@types/chai@npm:4.3.14" + checksum: 10c0/7712594c1e457cb99c7227d0fe1afcbb900bbd1369494ec2d2b0d79a383057a09ab13d23d7b300287394b99995a8c017aa55e6b9a369b77910bc10310ba504af + languageName: node + linkType: hard + "@types/cli-progress@npm:^3.11.5": version: 3.11.5 resolution: "@types/cli-progress@npm:3.11.5" @@ -4054,7 +4074,7 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.9": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db @@ -4138,6 +4158,15 @@ __metadata: languageName: node linkType: hard +"@types/oracledb@npm:^6.3": + version: 6.4.1 + resolution: "@types/oracledb@npm:6.4.1" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/938aca4cb1a65db7fbb18b9aa2ac63f4fee18607d9e60dc38ad458d0cecd35c4dcde61f700060b951d257931b5e4b05f26eea5f1a19064678929a2361fff8a3e + languageName: node + linkType: hard + "@types/pg@npm:^8.11.4": version: 8.11.6 resolution: "@types/pg@npm:8.11.6" @@ -4150,12 +4179,12 @@ __metadata: linkType: hard "@types/readable-stream@npm:^4.0.0": - version: 4.0.11 - resolution: "@types/readable-stream@npm:4.0.11" + version: 4.0.14 + resolution: "@types/readable-stream@npm:4.0.14" dependencies: "@types/node": "npm:*" safe-buffer: "npm:~5.1.1" - checksum: 10c0/62242febee3fbd4ff019a413cdc57d90aa12094b818eebf6f9cdfe32098fcb794af33157660bde17970b7b26fbb466df98e3fb745840bfe7b8f7ad665fa53866 + checksum: 10c0/28dee6f7ce67c5068f9eb6d6f72c4aa49c58d01c96fa343dcf8561b98f59bad559cb4a3d231eeaaed31fdc2b82f42e7ed0a509efc56b25a9c70de514fc341e24 languageName: node linkType: hard @@ -4171,7 +4200,7 @@ __metadata: languageName: node linkType: hard -"@types/semver@npm:7.5.8, @types/semver@npm:^7.3.12, @types/semver@npm:^7.5.0": +"@types/semver@npm:7.5.8, @types/semver@npm:^7.3.12": version: 7.5.8 resolution: "@types/semver@npm:7.5.8" checksum: 10c0/8663ff927234d1c5fcc04b33062cb2b9fcfbe0f5f351ed26c4d1e1581657deebd506b41ff7fdf89e787e3d33ce05854bc01686379b89e9c49b564c4cfa988efa @@ -4204,7 +4233,7 @@ __metadata: languageName: node linkType: hard -"@types/snowflake-sdk@npm:^1.6.23": +"@types/snowflake-sdk@npm:1.6.23": version: 1.6.23 resolution: "@types/snowflake-sdk@npm:1.6.23" dependencies: @@ -4268,45 +4297,43 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^7.2.0": - version: 7.5.0 - resolution: "@typescript-eslint/eslint-plugin@npm:7.5.0" - dependencies: - "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:7.5.0" - "@typescript-eslint/type-utils": "npm:7.5.0" - "@typescript-eslint/utils": "npm:7.5.0" - "@typescript-eslint/visitor-keys": "npm:7.5.0" - debug: "npm:^4.3.4" + version: 7.10.0 + resolution: "@typescript-eslint/eslint-plugin@npm:7.10.0" + dependencies: + "@eslint-community/regexpp": "npm:^4.10.0" + "@typescript-eslint/scope-manager": "npm:7.10.0" + "@typescript-eslint/type-utils": "npm:7.10.0" + "@typescript-eslint/utils": "npm:7.10.0" + "@typescript-eslint/visitor-keys": "npm:7.10.0" graphemer: "npm:^1.4.0" - ignore: "npm:^5.2.4" + ignore: "npm:^5.3.1" natural-compare: "npm:^1.4.0" - semver: "npm:^7.5.4" - ts-api-utils: "npm:^1.0.1" + ts-api-utils: "npm:^1.3.0" peerDependencies: "@typescript-eslint/parser": ^7.0.0 eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/932a7b5a09c0138ef5a0bf00f8e6039fa209d4047092ffc187de048543c21f7ce24dc14f25f4c87b6f3bbb62335fc952e259e271fde88baf793217bde6460cfa + checksum: 10c0/bf3f0118ea5961c3eb01894678246458a329d82dda9ac7c2f5bfe77896410d05a08a4655e533bcb1ed2a3132ba6421981ec8c2ed0a3545779d9603ea231947ae languageName: node linkType: hard "@typescript-eslint/parser@npm:^7.2.0": - version: 7.5.0 - resolution: "@typescript-eslint/parser@npm:7.5.0" + version: 7.10.0 + resolution: "@typescript-eslint/parser@npm:7.10.0" dependencies: - "@typescript-eslint/scope-manager": "npm:7.5.0" - "@typescript-eslint/types": "npm:7.5.0" - "@typescript-eslint/typescript-estree": "npm:7.5.0" - "@typescript-eslint/visitor-keys": "npm:7.5.0" + "@typescript-eslint/scope-manager": "npm:7.10.0" + "@typescript-eslint/types": "npm:7.10.0" + "@typescript-eslint/typescript-estree": "npm:7.10.0" + "@typescript-eslint/visitor-keys": "npm:7.10.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/65521202ff024e79594272fbb7e4731ecf9d2fdd2f58fc81450bfd2bca94ce9c17b0eadd7338c01701f5cf16d38b6c025ed3fc322380b1e4b5424b7484098cda + checksum: 10c0/4c4fbf43b5b05d75b766acb803d3dd078c6e080641a77f9e48ba005713466738ea4a71f0564fa3ce520988d65158d14c8c952ba01ccbc431ab4a05935db5ce6d languageName: node linkType: hard @@ -4320,30 +4347,30 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/scope-manager@npm:7.5.0" +"@typescript-eslint/scope-manager@npm:7.10.0": + version: 7.10.0 + resolution: "@typescript-eslint/scope-manager@npm:7.10.0" dependencies: - "@typescript-eslint/types": "npm:7.5.0" - "@typescript-eslint/visitor-keys": "npm:7.5.0" - checksum: 10c0/a017b151a6b39ef591f8e2e65598e005e1b4b2d5494e4b91bddb5856b3a4d57dd8a58d2bc7a140e627eb574f93a2c8fe55f1307aa264c928ffd31d9e190bc5dd + "@typescript-eslint/types": "npm:7.10.0" + "@typescript-eslint/visitor-keys": "npm:7.10.0" + checksum: 10c0/1d4f7ee137b95bd423b5a1b0d03251202dfc19bd8b6adfa5ff5df25fd5aa30e2d8ca50ab0d8d2e92441670ecbc2a82b3c2dbe39a4f268ec1ee1c1e267f7fd1d1 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/type-utils@npm:7.5.0" +"@typescript-eslint/type-utils@npm:7.10.0": + version: 7.10.0 + resolution: "@typescript-eslint/type-utils@npm:7.10.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:7.5.0" - "@typescript-eslint/utils": "npm:7.5.0" + "@typescript-eslint/typescript-estree": "npm:7.10.0" + "@typescript-eslint/utils": "npm:7.10.0" debug: "npm:^4.3.4" - ts-api-utils: "npm:^1.0.1" + ts-api-utils: "npm:^1.3.0" peerDependencies: eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/12915d4d1872638f5281e222a0d191676c478f250699c84864862e95a59e708222acefbf7ffdafc0872a007261219a3a2b1e667ff45eeafea7c4bcc5b955262c + checksum: 10c0/55e9a6690f9cedb79d30abb1990b161affaa2684dac246b743223353812c9c1e3fd2d923c67b193c6a3624a07e1c82c900ce7bf5b6b9891c846f04cb480ebd9f languageName: node linkType: hard @@ -4354,17 +4381,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/types@npm:7.5.0" - checksum: 10c0/f3394f71f422dbd89f63b230f20e9769c12e47a287ff30ca03a80714e57ea21279b6f12a8ab14bafb00b59926f20a88894b2d1e72679f7ff298bae112679d4b3 - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:^7.2.0": - version: 7.8.0 - resolution: "@typescript-eslint/types@npm:7.8.0" - checksum: 10c0/b2fdbfc21957bfa46f7d8809b607ad8c8b67c51821d899064d09392edc12f28b2318a044f0cd5d523d782e84e8f0558778877944964cf38e139f88790cf9d466 +"@typescript-eslint/types@npm:7.10.0, @typescript-eslint/types@npm:^7.2.0": + version: 7.10.0 + resolution: "@typescript-eslint/types@npm:7.10.0" + checksum: 10c0/f01d9330b93cc362ba7967ab5037396f64742076450e1f93139fa69cbe93a6ece3ed55d68ab780c9b7d07ef4a7c645da410305216a2cfc5dec7eba49ee65ab23 languageName: node linkType: hard @@ -4386,39 +4406,36 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/typescript-estree@npm:7.5.0" +"@typescript-eslint/typescript-estree@npm:7.10.0": + version: 7.10.0 + resolution: "@typescript-eslint/typescript-estree@npm:7.10.0" dependencies: - "@typescript-eslint/types": "npm:7.5.0" - "@typescript-eslint/visitor-keys": "npm:7.5.0" + "@typescript-eslint/types": "npm:7.10.0" + "@typescript-eslint/visitor-keys": "npm:7.10.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" - minimatch: "npm:9.0.3" - semver: "npm:^7.5.4" - ts-api-utils: "npm:^1.0.1" + minimatch: "npm:^9.0.4" + semver: "npm:^7.6.0" + ts-api-utils: "npm:^1.3.0" peerDependenciesMeta: typescript: optional: true - checksum: 10c0/ea3a270c725d6be273188b86110e0393052cd64d1c54a56eb5ea405e6d3fbbe84fb3b1ce1b8496a4078ac1eefd37aedcf12be91876764f6de31d5aa5131c7bcd + checksum: 10c0/6200695834c566e52e2fa7331f1a05019f7815969d8c1e1e237b85a99664d36f41ccc16384eff3f8582a0ecb75f1cc315b56ee9283b818da37f24fa4d42f1d7a languageName: node linkType: hard -"@typescript-eslint/utils@npm:7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/utils@npm:7.5.0" +"@typescript-eslint/utils@npm:7.10.0": + version: 7.10.0 + resolution: "@typescript-eslint/utils@npm:7.10.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" - "@types/json-schema": "npm:^7.0.12" - "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:7.5.0" - "@typescript-eslint/types": "npm:7.5.0" - "@typescript-eslint/typescript-estree": "npm:7.5.0" - semver: "npm:^7.5.4" + "@typescript-eslint/scope-manager": "npm:7.10.0" + "@typescript-eslint/types": "npm:7.10.0" + "@typescript-eslint/typescript-estree": "npm:7.10.0" peerDependencies: eslint: ^8.56.0 - checksum: 10c0/c815ed6909769648953d6963c069038f7cac0c979051b25718feb30e0d3337b9647b75b8de00ac03fe960f0cc8dc4e8a81d4aac4719090a99785e0068712bd24 + checksum: 10c0/6724471f94f2788f59748f7efa2a3a53ea910099993bee2fa5746ab5acacecdc9fcb110c568b18099ddc946ea44919ed394bff2bd055ba81fc69f5e6297b73bf languageName: node linkType: hard @@ -4450,13 +4467,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/visitor-keys@npm:7.5.0" +"@typescript-eslint/visitor-keys@npm:7.10.0": + version: 7.10.0 + resolution: "@typescript-eslint/visitor-keys@npm:7.10.0" dependencies: - "@typescript-eslint/types": "npm:7.5.0" - eslint-visitor-keys: "npm:^3.4.1" - checksum: 10c0/eecf02b8dd54e83738a143aca87b902af4b357028a90fd34ed7a2f40a3ae2f6a188b9ba53903f23c80e868f1fffbb039e9ddb63525438d659707cc7bfb269317 + "@typescript-eslint/types": "npm:7.10.0" + eslint-visitor-keys: "npm:^3.4.3" + checksum: 10c0/049e812bcd28869059d04c7bf3543bb55f5205f468b777439c4f120417fb856fb6024cb1d25291aa12556bd08e84f043a96d754ffb2cde37abb604d6f3c51634 languageName: node linkType: hard @@ -4572,9 +4589,9 @@ __metadata: linkType: hard "adm-zip@npm:^0.5.10": - version: 0.5.10 - resolution: "adm-zip@npm:0.5.10" - checksum: 10c0/1f391a4e02940688b6ca6d4b3ea96cc82a9dbe1596671d7dbc052f9a53ed2efa6ba9ba253f032ea16e70081f22d6ddd1af2d65d6be700853cdee9c2fc925c20e + version: 0.5.12 + resolution: "adm-zip@npm:0.5.12" + checksum: 10c0/fca2893b416bfcbee8b371a403f4d2e980a3c1055ce7b9b0b2ac8540c8efe6bbb27cc63ddf64ff6e6ed40c84fcb1ede7e95d230e7a567025e03f1044efbf6be0 languageName: node linkType: hard @@ -5082,13 +5099,13 @@ __metadata: linkType: hard "axios@npm:^1.6.0, axios@npm:^1.6.2, axios@npm:^1.6.8": - version: 1.6.8 - resolution: "axios@npm:1.6.8" + version: 1.7.1 + resolution: "axios@npm:1.7.1" dependencies: follow-redirects: "npm:^1.15.6" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: 10c0/0f22da6f490335479a89878bc7d5a1419484fbb437b564a80c34888fc36759ae4f56ea28d55a191695e5ed327f0bad56e7ff60fb6770c14d1be6501505d47ab9 + checksum: 10c0/554395472f18f4ddb43b4be2900473bc1a4d589464a8ab16f6954c53d9cace4317d5c9e009d5bb05f098d9565b2fa45f152a5d4cecb87536c8f0c370c25a7770 languageName: node linkType: hard @@ -5349,11 +5366,11 @@ __metadata: linkType: hard "builtins@npm:^5.0.0": - version: 5.0.1 - resolution: "builtins@npm:5.0.1" + version: 5.1.0 + resolution: "builtins@npm:5.1.0" dependencies: semver: "npm:^7.0.0" - checksum: 10c0/9390a51a9abbc0233dac79c66715f927508b9d0c62cb7a42448fe8c52def60c707e6e9eb2cc4c9b7aba11601899935bca4e4064ae5e19c04c7e1bb9309e69134 + checksum: 10c0/3c32fe5bd7ed4ff7dbd6fb14bcb9d7eaa7e967327f1899cd336f8625d3f46fceead0a53528f1e332aeaee757034ebb307cb2f1a37af2b86a3c5ad4845d01c0c8 languageName: node linkType: hard @@ -5411,8 +5428,8 @@ __metadata: linkType: hard "cacache@npm:^18.0.0": - version: 18.0.2 - resolution: "cacache@npm:18.0.2" + version: 18.0.3 + resolution: "cacache@npm:18.0.3" dependencies: "@npmcli/fs": "npm:^3.1.0" fs-minipass: "npm:^3.0.0" @@ -5426,7 +5443,7 @@ __metadata: ssri: "npm:^10.0.0" tar: "npm:^6.1.11" unique-filename: "npm:^3.0.0" - checksum: 10c0/7992665305cc251a984f4fdbab1449d50e88c635bc43bf2785530c61d239c61b349e5734461baa461caaee65f040ab14e2d58e694f479c0810cffd181ba5eabc + checksum: 10c0/dfda92840bb371fb66b88c087c61a74544363b37a265023223a99965b16a16bbb87661fe4948718d79df6e0cc04e85e62784fbcf1832b2a5e54ff4c46fbb45b7 languageName: node linkType: hard @@ -5520,9 +5537,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.30001587": - version: 1.0.30001606 - resolution: "caniuse-lite@npm:1.0.30001606" - checksum: 10c0/fc9816f7d073e4f655c00acf9d6625f923e722430545b0aabefb9dc01347f3093608eb18841cf981acbd464fcac918a708908549738a8cd9517a14ac005bf8fc + version: 1.0.30001620 + resolution: "caniuse-lite@npm:1.0.30001620" + checksum: 10c0/3783117143fbdc98c1b91a579d0f2a7bcee7008f322ba7a2bf56a6c3d105400772c7ed8026840b4ea909ec7bf254bcc36532f2ce1b1a1240b00d0335da39b7ec languageName: node linkType: hard @@ -5585,15 +5602,15 @@ __metadata: linkType: hard "chai@npm:>1.9.0": - version: 5.1.0 - resolution: "chai@npm:5.1.0" + version: 5.1.1 + resolution: "chai@npm:5.1.1" dependencies: assertion-error: "npm:^2.0.1" - check-error: "npm:^2.0.0" + check-error: "npm:^2.1.1" deep-eql: "npm:^5.0.1" loupe: "npm:^3.1.0" pathval: "npm:^2.0.0" - checksum: 10c0/15ff6799051f5e0080440297451f1ef47164b4e825105c8df75100a24d60e0aea24455cff7287afbff091ba7bedc6b42e12d6f0f8bfb5b47cc1bdb446336bba0 + checksum: 10c0/e7f00e5881e3d5224f08fe63966ed6566bd9fdde175863c7c16dd5240416de9b34c4a0dd925f4fd64ad56256ca6507d32cf6131c49e1db65c62578eb31d4566c languageName: node linkType: hard @@ -5671,10 +5688,10 @@ __metadata: languageName: node linkType: hard -"check-error@npm:^2.0.0": - version: 2.0.0 - resolution: "check-error@npm:2.0.0" - checksum: 10c0/31149712894c000a55ca87198930344e2440e258fec6679bf13b0714f850b0c5131ce2b3cdb3119d18a5286fb503dcd7382062f9209e2eca30c34ab616b64e48 +"check-error@npm:^2.1.1": + version: 2.1.1 + resolution: "check-error@npm:2.1.1" + checksum: 10c0/979f13eccab306cf1785fa10941a590b4e7ea9916ea2a4f8c87f0316fc3eab07eabefb6e587424ef0f88cbcd3805791f172ea739863ca3d7ce2afc54641c7f0e languageName: node linkType: hard @@ -6004,15 +6021,6 @@ __metadata: languageName: node linkType: hard -"compressible@npm:^2.0.12": - version: 2.0.18 - resolution: "compressible@npm:2.0.18" - dependencies: - mime-db: "npm:>= 1.43.0 < 2" - checksum: 10c0/8a03712bc9f5b9fe530cc5a79e164e665550d5171a64575d7dcf3e0395d7b4afa2d79ab176c61b5b596e28228b350dd07c1a2a6ead12fd81d1b6cd632af2fef7 - languageName: node - linkType: hard - "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -6484,7 +6492,7 @@ __metadata: languageName: node linkType: hard -"define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": +"define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -6707,9 +6715,9 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.4.668": - version: 1.4.729 - resolution: "electron-to-chromium@npm:1.4.729" - checksum: 10c0/9f093b873a5e02da5fd5db5a1038c3a3f84bd43ff6d0e894280848717e5892953cc814a4ddf1de2acbfa9af4fe356c714f036f39b82d52bc6c8c3aed6e97fbde + version: 1.4.776 + resolution: "electron-to-chromium@npm:1.4.776" + checksum: 10c0/6bec4c2d17058ffead3b769c908c05c735e2f96014c19d90472863cff03f23f16b60e25fbaf53ccec1e12999fba98eeed88fbcfdd5e347d5aff33ed06c27538e languageName: node linkType: hard @@ -6767,12 +6775,12 @@ __metadata: linkType: hard "enhanced-resolve@npm:^5.12.0": - version: 5.16.0 - resolution: "enhanced-resolve@npm:5.16.0" + version: 5.16.1 + resolution: "enhanced-resolve@npm:5.16.1" dependencies: graceful-fs: "npm:^4.2.4" tapable: "npm:^2.2.0" - checksum: 10c0/dd69669cbb638ccacefd03e04d5e195ee6a99b7f5f8012f86d2df7781834de357923e06064ea621137c4ce0b37cc12b872b4e6d1ac6ab15fe98e7f1dfbbb08c4 + checksum: 10c0/57d52625b978f18b32351a03006699de1e3695ce27af936ab4f1f98d3a4c825b219b445910bb4eef398303bbb5f37d7e382f842513d0f3a32614b78f6fd07ab7 languageName: node linkType: hard @@ -6785,13 +6793,6 @@ __metadata: languageName: node linkType: hard -"ent@npm:^2.2.0": - version: 2.2.0 - resolution: "ent@npm:2.2.0" - checksum: 10c0/d12c504d93afb8b22551323f78f60f0a2660289cf2de2210bdd2fdb07ac204956da23510a7711bf48079aa0aa726e21724224de6c6289120ddcf27652b30cb17 - languageName: node - linkType: hard - "entities@npm:^4.4.0": version: 4.5.0 resolution: "entities@npm:4.5.0" @@ -6831,7 +6832,7 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.1, es-abstract@npm:^1.23.2": +"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.1, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3": version: 1.23.3 resolution: "es-abstract@npm:1.23.3" dependencies: @@ -6902,12 +6903,12 @@ __metadata: linkType: hard "es-iterator-helpers@npm:^1.0.15, es-iterator-helpers@npm:^1.0.17": - version: 1.0.18 - resolution: "es-iterator-helpers@npm:1.0.18" + version: 1.0.19 + resolution: "es-iterator-helpers@npm:1.0.19" dependencies: call-bind: "npm:^1.0.7" define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.0" + es-abstract: "npm:^1.23.3" es-errors: "npm:^1.3.0" es-set-tostringtag: "npm:^2.0.3" function-bind: "npm:^1.1.2" @@ -6919,7 +6920,7 @@ __metadata: internal-slot: "npm:^1.0.7" iterator.prototype: "npm:^1.1.2" safe-array-concat: "npm:^1.1.2" - checksum: 10c0/93be402e01fa3d8bf62fcadd2fb3055126ffcfe8846911b10b85918ef46775252696c84e6191ec8125bedb61e92242ad1a54a86118436ba19814720cb9ff4aed + checksum: 10c0/ae8f0241e383b3d197383b9842c48def7fce0255fb6ed049311b686ce295595d9e389b466f6a1b7d4e7bb92d82f5e716d6fae55e20c1040249bf976743b038c5 languageName: node linkType: hard @@ -7047,7 +7048,7 @@ __metadata: languageName: node linkType: hard -"escalade@npm:^3.1.1": +"escalade@npm:^3.1.1, escalade@npm:^3.1.2": version: 3.1.2 resolution: "escalade@npm:3.1.2" checksum: 10c0/6b4adafecd0682f3aa1cd1106b8fff30e492c7015b178bc81b2d2f75106dabea6c6d6e8508fc491bd58e597c74abb0e8e2368f943ecb9393d4162e3c2f3cf287 @@ -7245,11 +7246,11 @@ __metadata: linkType: hard "eslint-plugin-react-hooks@npm:^4.6.0": - version: 4.6.0 - resolution: "eslint-plugin-react-hooks@npm:4.6.0" + version: 4.6.2 + resolution: "eslint-plugin-react-hooks@npm:4.6.2" peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - checksum: 10c0/58c7e10ea5792c33346fcf5cb4024e14837035ce412ff99c2dcb7c4f903dc9b17939078f80bfef826301ce326582c396c00e8e0ac9d10ac2cde2b42d33763c65 + checksum: 10c0/4844e58c929bc05157fb70ba1e462e34f1f4abcbc8dd5bbe5b04513d33e2699effb8bca668297976ceea8e7ebee4e8fc29b9af9d131bcef52886feaa2308b2cc languageName: node linkType: hard @@ -7293,13 +7294,13 @@ __metadata: linkType: hard "eslint-plugin-sort-destructure-keys@npm:^1.5.0": - version: 1.5.0 - resolution: "eslint-plugin-sort-destructure-keys@npm:1.5.0" + version: 1.6.0 + resolution: "eslint-plugin-sort-destructure-keys@npm:1.6.0" dependencies: natural-compare-lite: "npm:^1.4.0" peerDependencies: - eslint: 3 - 8 - checksum: 10c0/1ab8ff259cca162344f09a47b6bdeccf03a6780771e70bd750c9a41a3f0ebb8935a631bd0712492fd49ba3e8a40c8016aec0aa525bd5b896dfef7461c6cdd335 + eslint: 3 - 9 + checksum: 10c0/274702971da1d179c2066f9beaa59d883e08cb7fbc257ea5826e8ffbca79c22b0a23c198d35857ac6364426e654eee91d6bd494f6124898ce0687da28f43a122 languageName: node linkType: hard @@ -7674,8 +7675,8 @@ __metadata: linkType: hard "fancy-test@npm:^3.0.15": - version: 3.0.15 - resolution: "fancy-test@npm:3.0.15" + version: 3.0.16 + resolution: "fancy-test@npm:3.0.16" dependencies: "@types/chai": "npm:*" "@types/lodash": "npm:*" @@ -7686,7 +7687,7 @@ __metadata: nock: "npm:^13.5.4" sinon: "npm:^16.1.3" stdout-stderr: "npm:^0.1.9" - checksum: 10c0/3cee0ec858f5f7ccf1ce1326c55993b1ef455145ce62a5a2bc2cf46f7cfce599b04395cbefbeb955e15c5237da83db2f7d2ce890825c5f50fbf58f0b065b92d0 + checksum: 10c0/7085ea303039ab41b6a28a9461d9d424b259df6082821d10d35f589807eb7ff7aec1d870c9c347a22b8ce9f5cc2bc5e443c820b68e93d3b2244f12bfe75d66a2 languageName: node linkType: hard @@ -7745,13 +7746,13 @@ __metadata: linkType: hard "fast-xml-parser@npm:^4.2.5, fast-xml-parser@npm:^4.3.0": - version: 4.3.6 - resolution: "fast-xml-parser@npm:4.3.6" + version: 4.4.0 + resolution: "fast-xml-parser@npm:4.4.0" dependencies: strnum: "npm:^1.0.5" bin: fxparser: src/cli/cli.js - checksum: 10c0/9ebe2ac142c6978cae423c39c2a9b561edb76be584317d578768ed4a006a61fc0e83abf8c6fe31029139c4ad15ea1f2e7b6720ba9e6eda0e5266d7f2770fb079 + checksum: 10c0/ce32fad713471a40bea67959894168f297a5dd0aba64b89a2abc71a4fec0b1ae1d49c2dd8d8719ca8beeedf477824358c8a486b360b9f3ef12abc2e355d11318 languageName: node linkType: hard @@ -8164,15 +8165,15 @@ __metadata: linkType: hard "gaxios@npm:^6.0.0, gaxios@npm:^6.0.2, gaxios@npm:^6.1.1": - version: 6.4.0 - resolution: "gaxios@npm:6.4.0" + version: 6.6.0 + resolution: "gaxios@npm:6.6.0" dependencies: extend: "npm:^3.0.2" https-proxy-agent: "npm:^7.0.1" is-stream: "npm:^2.0.0" node-fetch: "npm:^2.6.9" uuid: "npm:^9.0.1" - checksum: 10c0/b9bd31daa7e223a177f1ae9ea69db2ebce06d5870cfedb3eee2a19e26c31d0b1b9172569d44f89e0d6394bf6fc5b1d061ae78612c94b90b2b5c7cf92a9e6dab3 + checksum: 10c0/45ddf2e3664eed37d62e9467bb3cf81519057797c3169c7762f1be2917019d7a53ce4ff2091266afd29d05cd56e0f507b6862214b51c3fbe7730b9a6b79cb6a2 languageName: node linkType: hard @@ -8311,11 +8312,11 @@ __metadata: linkType: hard "get-tsconfig@npm:^4.5.0": - version: 4.7.3 - resolution: "get-tsconfig@npm:4.7.3" + version: 4.7.5 + resolution: "get-tsconfig@npm:4.7.5" dependencies: resolve-pkg-maps: "npm:^1.0.0" - checksum: 10c0/b15ca9d5d0887ebfccadc9fe88b6ff3827a5691ec90e7608a5e9c74bef959c14aba62f6bb88ac7f50322395731789a2cf654244f00e10f4f76349911b6846d6f + checksum: 10c0/a917dff2ba9ee187c41945736bf9bbab65de31ce5bc1effd76267be483a7340915cff232199406379f26517d2d0a4edcdbcda8cca599c2480a0f2cf1e1de3efa languageName: node linkType: hard @@ -8501,11 +8502,12 @@ __metadata: linkType: hard "globalthis@npm:^1.0.3": - version: 1.0.3 - resolution: "globalthis@npm:1.0.3" + version: 1.0.4 + resolution: "globalthis@npm:1.0.4" dependencies: - define-properties: "npm:^1.1.3" - checksum: 10c0/0db6e9af102a5254630351557ac15e6909bc7459d3e3f6b001e59fe784c96d31108818f032d9095739355a88467459e6488ff16584ee6250cd8c27dec05af4b0 + define-properties: "npm:^1.2.1" + gopd: "npm:^1.0.1" + checksum: 10c0/9d156f313af79d80b1566b93e19285f481c591ad6d0d319b4be5e03750d004dde40a39a0f26f7e635f9007a3600802f53ecd85a759b86f109e80a5f705e01846 languageName: node linkType: hard @@ -8537,8 +8539,8 @@ __metadata: linkType: hard "google-auth-library@npm:^9.6.3": - version: 9.7.0 - resolution: "google-auth-library@npm:9.7.0" + version: 9.10.0 + resolution: "google-auth-library@npm:9.10.0" dependencies: base64-js: "npm:^1.3.0" ecdsa-sig-formatter: "npm:^1.0.11" @@ -8546,7 +8548,7 @@ __metadata: gcp-metadata: "npm:^6.1.0" gtoken: "npm:^7.0.0" jws: "npm:^4.0.0" - checksum: 10c0/158e00b3a177038db2b28c3f69f835278f9bbe101327742aff284afa51f98721feaa14480eb0fea2da2c365820d0dc05528bd969ad45f37f4da6e3599bf2e16c + checksum: 10c0/21acad6dc712a0a935c3608b92d9aab80b05f1d4e0be5fb7efe5b2069a6453f2cee12867b5fb0a724c01a167ed3f5e4280e30740d2c1bff86f153b187205d4ed languageName: node linkType: hard @@ -8769,11 +8771,18 @@ __metadata: linkType: hard "hosted-git-info@npm:^7.0.0": - version: 7.0.1 - resolution: "hosted-git-info@npm:7.0.1" + version: 7.0.2 + resolution: "hosted-git-info@npm:7.0.2" dependencies: lru-cache: "npm:^10.0.1" - checksum: 10c0/361c4254f717f06d581a5a90aa0156a945e662e05ebbb533c1fa9935f10886d8247db48cbbcf9667f02e519e6479bf16dcdcf3124c3030e76c4c3ca2c88ee9d3 + checksum: 10c0/b19dbd92d3c0b4b0f1513cf79b0fc189f54d6af2129eeb201de2e9baaa711f1936929c848b866d9c8667a0f956f34bf4f07418c12be1ee9ca74fd9246335ca1f + languageName: node + linkType: hard + +"html-entities@npm:^2.5.2": + version: 2.5.2 + resolution: "html-entities@npm:2.5.2" + checksum: 10c0/f20ffb4326606245c439c231de40a7c560607f639bf40ffbfb36b4c70729fd95d7964209045f1a4e62fe17f2364cef3d6e49b02ea09016f207fde51c2211e481 languageName: node linkType: hard @@ -8958,11 +8967,11 @@ __metadata: linkType: hard "ignore-walk@npm:^6.0.4": - version: 6.0.4 - resolution: "ignore-walk@npm:6.0.4" + version: 6.0.5 + resolution: "ignore-walk@npm:6.0.5" dependencies: minimatch: "npm:^9.0.0" - checksum: 10c0/6dd2ea369f3d32d90cb26ca6647bc6e112ed483433270ed89b8055dd708d00777c2cbc85b93b43f53e2100851277fd1539796a758ae4c64b84445d4f1da5fd8f + checksum: 10c0/8bd6d37c82400016c7b6538b03422dde8c9d7d3e99051c8357dd205d499d42828522fb4fbce219c9c21b4b069079445bacdc42bbd3e2e073b52856c2646d8a39 languageName: node linkType: hard @@ -8973,7 +8982,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.0.4, ignore@npm:^5.0.5, ignore@npm:^5.2.0, ignore@npm:^5.2.4, ignore@npm:~5.3.1": +"ignore@npm:^5.0.4, ignore@npm:^5.0.5, ignore@npm:^5.2.0, ignore@npm:^5.2.4, ignore@npm:^5.3.1, ignore@npm:~5.3.1": version: 5.3.1 resolution: "ignore@npm:5.3.1" checksum: 10c0/703f7f45ffb2a27fb2c5a8db0c32e7dee66b33a225d28e8db4e1be6474795f606686a6e3bcc50e1aa12f2042db4c9d4a7d60af3250511de74620fbed052ea4cd @@ -9746,8 +9755,8 @@ __metadata: linkType: hard "jake@npm:^10.8.5": - version: 10.8.7 - resolution: "jake@npm:10.8.7" + version: 10.9.1 + resolution: "jake@npm:10.9.1" dependencies: async: "npm:^3.2.3" chalk: "npm:^4.0.2" @@ -9755,7 +9764,7 @@ __metadata: minimatch: "npm:^3.1.2" bin: jake: bin/cli.js - checksum: 10c0/89326d01a8bc110d02d973729a66394c79a34b34461116f5c530a2a2dbc30265683fe6737928f75df9178e9d369ff1442f5753fb983d525e740eefdadc56a103 + checksum: 10c0/dda972431a926462f08fcf583ea8997884216a43daa5cce81cb42e7e661dc244f836c0a802fde23439c6e1fc59743d1c0be340aa726d3b17d77557611a5cd541 languageName: node linkType: hard @@ -9887,9 +9896,9 @@ __metadata: linkType: hard "json-parse-even-better-errors@npm:^3.0.0": - version: 3.0.1 - resolution: "json-parse-even-better-errors@npm:3.0.1" - checksum: 10c0/bc40600b14231dff1ff911d269c7ed89fbf3dbedf25cad3f47c10ff9cbb998ce03921372a17f27f3c7cfed76e679bc6c02a7b4cb2604b0ba68cd51ed16899492 + version: 3.0.2 + resolution: "json-parse-even-better-errors@npm:3.0.2" + checksum: 10c0/147f12b005768abe9fab78d2521ce2b7e1381a118413d634a40e6d907d7d10f5e9a05e47141e96d6853af7cc36d2c834d0a014251be48791e037ff2f13d2b94b languageName: node linkType: hard @@ -10519,11 +10528,11 @@ __metadata: linkType: hard "loupe@npm:^3.1.0": - version: 3.1.0 - resolution: "loupe@npm:3.1.0" + version: 3.1.1 + resolution: "loupe@npm:3.1.1" dependencies: get-func-name: "npm:^2.0.1" - checksum: 10c0/8c2aebbabb732945092de4c2193a319f79c7a28aa70a20c1e1cd50568116c9a3b1a0a132277a1706d8742cd582be91119a85b5cdb443f1f97f1a375381fa22c7 + checksum: 10c0/99f88badc47e894016df0c403de846fedfea61154aadabbf776c8428dd59e8d8378007135d385d737de32ae47980af07d22ba7bec5ef7beebd721de9baa0a0af languageName: node linkType: hard @@ -10544,9 +10553,9 @@ __metadata: linkType: hard "lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.2.0 - resolution: "lru-cache@npm:10.2.0" - checksum: 10c0/c9847612aa2daaef102d30542a8d6d9b2c2bb36581c1bf0dc3ebf5e5f3352c772a749e604afae2e46873b930a9e9523743faac4e5b937c576ab29196774712ee + version: 10.2.2 + resolution: "lru-cache@npm:10.2.2" + checksum: 10c0/402d31094335851220d0b00985084288136136992979d0e015f0f1697e15d1c86052d7d53ae86b614e5b058425606efffc6969a31a091085d7a2b80a8a1e26d6 languageName: node linkType: hard @@ -10647,9 +10656,9 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^13.0.0": - version: 13.0.0 - resolution: "make-fetch-happen@npm:13.0.0" +"make-fetch-happen@npm:^13.0.0, make-fetch-happen@npm:^13.0.1": + version: 13.0.1 + resolution: "make-fetch-happen@npm:13.0.1" dependencies: "@npmcli/agent": "npm:^2.0.0" cacache: "npm:^18.0.0" @@ -10660,9 +10669,10 @@ __metadata: minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" negotiator: "npm:^0.6.3" + proc-log: "npm:^4.2.0" promise-retry: "npm:^2.0.1" ssri: "npm:^10.0.0" - checksum: 10c0/43b9f6dcbc6fe8b8604cb6396957c3698857a15ba4dbc38284f7f0e61f248300585ef1eb8cc62df54e9c724af977e45b5cdfd88320ef7f53e45070ed3488da55 + checksum: 10c0/df5f4dbb6d98153b751bccf4dc4cc500de85a96a9331db9805596c46aa9f99d9555983954e6c1266d9f981ae37a9e4647f42b9a4bb5466f867f4012e582c9e7e languageName: node linkType: hard @@ -10830,14 +10840,14 @@ __metadata: languageName: node linkType: hard -"mime-db@npm:1.52.0, mime-db@npm:>= 1.43.0 < 2": +"mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa languageName: node linkType: hard -"mime-types@npm:^2.0.8, mime-types@npm:^2.1.12, mime-types@npm:^2.1.29": +"mime-types@npm:^2.1.12, mime-types@npm:^2.1.29": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -11012,8 +11022,8 @@ __metadata: linkType: hard "minipass-fetch@npm:^3.0.0": - version: 3.0.4 - resolution: "minipass-fetch@npm:3.0.4" + version: 3.0.5 + resolution: "minipass-fetch@npm:3.0.5" dependencies: encoding: "npm:^0.1.13" minipass: "npm:^7.0.3" @@ -11022,7 +11032,7 @@ __metadata: dependenciesMeta: encoding: optional: true - checksum: 10c0/1b63c1f3313e88eeac4689f1b71c9f086598db9a189400e3ee960c32ed89e06737fa23976c9305c2d57464fb3fcdc12749d3378805c9d6176f5569b0d0ee8a75 + checksum: 10c0/9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b languageName: node linkType: hard @@ -11370,11 +11380,11 @@ __metadata: linkType: hard "node-abi@npm:^3.3.0": - version: 3.57.0 - resolution: "node-abi@npm:3.57.0" + version: 3.62.0 + resolution: "node-abi@npm:3.62.0" dependencies: semver: "npm:^7.3.5" - checksum: 10c0/8d78542e39a3c49ac476d12c70ef0366f26a40a215af44498656e75fc85e5646309765a3277e1cbb2ec40283a9e86f7aefcdd699e30576c582f6bb931e6c802b + checksum: 10c0/62e11264cbb51387cf4599b04e0418c7eba725afe3a228504ade957d61f579a5cb24df79dad9d338b9beb58d723643d40c9fcae2cfc2fe775c0ef56bb0fd0ec8 languageName: node linkType: hard @@ -11506,13 +11516,13 @@ __metadata: linkType: hard "nopt@npm:^7.0.0": - version: 7.2.0 - resolution: "nopt@npm:7.2.0" + version: 7.2.1 + resolution: "nopt@npm:7.2.1" dependencies: abbrev: "npm:^2.0.0" bin: nopt: bin/nopt.js - checksum: 10c0/9bd7198df6f16eb29ff16892c77bcf7f0cc41f9fb5c26280ac0def2cf8cf319f3b821b3af83eba0e74c85807cc430a16efe0db58fe6ae1f41e69519f585b6aff + checksum: 10c0/a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81 languageName: node linkType: hard @@ -11588,11 +11598,11 @@ __metadata: linkType: hard "npm-bundled@npm:^3.0.0": - version: 3.0.0 - resolution: "npm-bundled@npm:3.0.0" + version: 3.0.1 + resolution: "npm-bundled@npm:3.0.1" dependencies: npm-normalize-package-bin: "npm:^3.0.0" - checksum: 10c0/65fcc621ba6e183be2715e3bbbf29d85e65e986965f06ee5e96a293d62dfad59ee57a9dcdd1c591eab156e03d58b3c35926b4211ce792d683458e15bb9f642c7 + checksum: 10c0/7975590a50b7ce80dd9f3eddc87f7e990c758f2f2c4d9313dd67a9aca38f1a5ac0abe20d514b850902c441e89d2346adfc3c6f1e9cbab3ea28ebb653c4442440 languageName: node linkType: hard @@ -11643,14 +11653,14 @@ __metadata: linkType: hard "npm-package-arg@npm:^11.0.0": - version: 11.0.1 - resolution: "npm-package-arg@npm:11.0.1" + version: 11.0.2 + resolution: "npm-package-arg@npm:11.0.2" dependencies: hosted-git-info: "npm:^7.0.0" - proc-log: "npm:^3.0.0" + proc-log: "npm:^4.0.0" semver: "npm:^7.3.5" validate-npm-package-name: "npm:^5.0.0" - checksum: 10c0/f5bc4056ffe46497847fb31e349c834efe01d36d170926d1032443e183219d5e6ce75a49c1d398caf2236d3a69180597d255bff685c68d6a81f2eac96262b94d + checksum: 10c0/d730572e128980db45c97c184a454cb565283bf849484bf92e3b4e8ec2d08a21bd4b2cba9467466853add3e8c7d81e5de476904ac241f3ae63e6905dfc8196d4 languageName: node linkType: hard @@ -11678,14 +11688,14 @@ __metadata: linkType: hard "npm-pick-manifest@npm:^9.0.0": - version: 9.0.0 - resolution: "npm-pick-manifest@npm:9.0.0" + version: 9.0.1 + resolution: "npm-pick-manifest@npm:9.0.1" dependencies: npm-install-checks: "npm:^6.0.0" npm-normalize-package-bin: "npm:^3.0.0" npm-package-arg: "npm:^11.0.0" semver: "npm:^7.3.5" - checksum: 10c0/930859b70fb7b8cd8aee1c9819c2fbe95db5ae246398fbd6eaa819793675e36be97da2b4d19e1b56a913a016f7a0a33070cd3ed363ad522d5dbced9c0d94d037 + checksum: 10c0/c9b93a533b599bccba4f5d7ba313725d83a0058d981e8318176bfbb3a6c9435acd1a995847eaa3ffb45162161947db9b0674ceee13cfe716b345573ca1073d8e languageName: node linkType: hard @@ -11705,8 +11715,8 @@ __metadata: linkType: hard "npm-registry-fetch@npm:^16.0.0": - version: 16.2.0 - resolution: "npm-registry-fetch@npm:16.2.0" + version: 16.2.1 + resolution: "npm-registry-fetch@npm:16.2.1" dependencies: "@npmcli/redact": "npm:^1.1.0" make-fetch-happen: "npm:^13.0.0" @@ -11715,8 +11725,8 @@ __metadata: minipass-json-stream: "npm:^1.0.1" minizlib: "npm:^2.1.2" npm-package-arg: "npm:^11.0.0" - proc-log: "npm:^3.0.0" - checksum: 10c0/7b149b2b680c40e36b1f644e3a45c91c05014b1c648012f1d8f85a8f160fec3bc9b8379a74c1a3e3d78ce7395b755144de03a2216f9e246e73b9e69e8d0b2e10 + proc-log: "npm:^4.0.0" + checksum: 10c0/bccffc291771d55056a6ebedb7aaf431cecc663286e060dc2936e8e0deee454a4a71654f772afcaa44f0d74a2c02403d8b45486a0aa2dd6d2bd8c09c9134eeb9 languageName: node linkType: hard @@ -12103,16 +12113,16 @@ __metadata: linkType: hard "optionator@npm:^0.9.3": - version: 0.9.3 - resolution: "optionator@npm:0.9.3" + version: 0.9.4 + resolution: "optionator@npm:0.9.4" dependencies: - "@aashutoshrathi/word-wrap": "npm:^1.2.3" deep-is: "npm:^0.1.3" fast-levenshtein: "npm:^2.0.6" levn: "npm:^0.4.1" prelude-ls: "npm:^1.2.1" type-check: "npm:^0.4.0" - checksum: 10c0/66fba794d425b5be51353035cf3167ce6cfa049059cbb93229b819167687e0f48d2bc4603fcb21b091c99acb516aae1083624675b15c4765b2e4693a085e959c + word-wrap: "npm:^1.2.5" + checksum: 10c0/4afb687a059ee65b61df74dfe87d8d6815cd6883cb8b3d5883a910df72d0f5d029821f37025e4bccf4048873dbdb09acc6d303d27b8f76b1a80dd5a7d5334675 languageName: node linkType: hard @@ -12149,6 +12159,13 @@ __metadata: languageName: node linkType: hard +"oracledb@npm:6.5": + version: 6.5.0 + resolution: "oracledb@npm:6.5.0" + checksum: 10c0/a524673026a5df5187de7e6891c4d583ad70b04abbc0c69ac65922670d65f7b2187150b8c1059b669cfbae0c21dc206790c2aab2fec1931ceeee195916ee4c38 + languageName: node + linkType: hard + "os-tmpdir@npm:~1.0.2": version: 1.0.2 resolution: "os-tmpdir@npm:1.0.2" @@ -12351,8 +12368,8 @@ __metadata: linkType: hard "pacote@npm:^17.0.5": - version: 17.0.6 - resolution: "pacote@npm:17.0.6" + version: 17.0.7 + resolution: "pacote@npm:17.0.7" dependencies: "@npmcli/git": "npm:^5.0.0" "@npmcli/installed-package-contents": "npm:^2.0.1" @@ -12365,7 +12382,7 @@ __metadata: npm-packlist: "npm:^8.0.0" npm-pick-manifest: "npm:^9.0.0" npm-registry-fetch: "npm:^16.0.0" - proc-log: "npm:^3.0.0" + proc-log: "npm:^4.0.0" promise-retry: "npm:^2.0.1" read-package-json: "npm:^7.0.0" read-package-json-fast: "npm:^3.0.0" @@ -12374,7 +12391,7 @@ __metadata: tar: "npm:^6.1.11" bin: pacote: lib/bin.js - checksum: 10c0/d8fc116cb91d453d2a42493ea5ced3ff57dbfdb6e5b9b514f1d0465422e80042c69013fb4f77be5f27751185c6b174a40d8a53debdfb57cc4ba82a9650d970db + checksum: 10c0/05730d3233918e4d89a4b9f8b436cddbe5081a4922c26c8af7d8f7db3adc79b211edd0e1ef2fd1c5b280811fd93a4486d76188fe75f3172a09d864f099d61066 languageName: node linkType: hard @@ -12534,9 +12551,9 @@ __metadata: linkType: hard "path-to-regexp@npm:^6.2.1": - version: 6.2.1 - resolution: "path-to-regexp@npm:6.2.1" - checksum: 10c0/7a73811ca703e5c199e5b50b9649ab8f6f7b458a37f7dff9ea338815203f5b1f95fe8cb24d4fdfe2eab5d67ce43562d92534330babca35cdf3231f966adb9360 + version: 6.2.2 + resolution: "path-to-regexp@npm:6.2.2" + checksum: 10c0/4b60852d3501fd05ca9dd08c70033d73844e5eca14e41f499f069afa8364f780f15c5098002f93bd42af8b3514de62ac6e82a53b5662de881d2b08c9ef21ea6b languageName: node linkType: hard @@ -12682,10 +12699,10 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: 10c0/20a5b249e331c14479d94ec6817a182fd7a5680debae82705747b2db7ec50009a5f6648d0621c561b0572703f84dbef0858abcbd5856d3c5511426afcb1961f7 +"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1": + version: 1.0.1 + resolution: "picocolors@npm:1.0.1" + checksum: 10c0/c63cdad2bf812ef0d66c8db29583802355d4ca67b9285d846f390cc15c2f6ccb94e8cb7eb6a6e97fc5990a6d3ad4ae42d86c84d3146e667c739a4234ed50d400 languageName: node linkType: hard @@ -12903,6 +12920,13 @@ __metadata: languageName: node linkType: hard +"proc-log@npm:^4.0.0, proc-log@npm:^4.2.0": + version: 4.2.0 + resolution: "proc-log@npm:4.2.0" + checksum: 10c0/17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9 + languageName: node + linkType: hard + "process-nextick-args@npm:~2.0.0": version: 2.0.1 resolution: "process-nextick-args@npm:2.0.1" @@ -12951,11 +12975,11 @@ __metadata: linkType: hard "promzard@npm:^1.0.0": - version: 1.0.1 - resolution: "promzard@npm:1.0.1" + version: 1.0.2 + resolution: "promzard@npm:1.0.2" dependencies: read: "npm:^3.0.1" - checksum: 10c0/8445442ff1ff71a2ac2d91ca6a0908631cf6573745298afe52283af23ec00c2dc6276ac4e75cd9bb521c126d33d268c5e5682c93eda492a5dcca8a76e0f671b3 + checksum: 10c0/d53c4ecb8b606b7e4bdeab14ac22c5f81a57463d29de1b8fe43bbc661106d9e4a79d07044bd3f69bde82c7ebacba7307db90a9699bc20482ce637bdea5fb8e4b languageName: node linkType: hard @@ -13100,9 +13124,9 @@ __metadata: linkType: hard "react-is@npm:^18.0.0": - version: 18.2.0 - resolution: "react-is@npm:18.2.0" - checksum: 10c0/6eb5e4b28028c23e2bfcf73371e72cd4162e4ac7ab445ddae2afe24e347a37d6dc22fae6e1748632cd43c6d4f9b8f86dcf26bf9275e1874f436d129952528ae0 + version: 18.3.1 + resolution: "react-is@npm:18.3.1" + checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072 languageName: node linkType: hard @@ -13136,14 +13160,14 @@ __metadata: linkType: hard "read-package-json@npm:^7.0.0": - version: 7.0.0 - resolution: "read-package-json@npm:7.0.0" + version: 7.0.1 + resolution: "read-package-json@npm:7.0.1" dependencies: glob: "npm:^10.2.2" json-parse-even-better-errors: "npm:^3.0.0" normalize-package-data: "npm:^6.0.0" npm-normalize-package-bin: "npm:^3.0.0" - checksum: 10c0/a2d373d0f87613fe86ec49c7e4bcdaf2a14967c258c6ccfd9585dec8b21e3d5bfe422c460648fb30e8c93fc13579da0d9c9c65adc5ec4e95ec888d99e4bccc79 + checksum: 10c0/4bb2ad7dc6f460d0db04c5ef6ad7e9644d9566f07fa3563a938aedf0ee4b5ea0f0e2c5a321f79a73b34488ade0bd5937a7671ee3b453c42cd9d5e7e9b07c57f3 languageName: node linkType: hard @@ -13699,6 +13723,17 @@ __metadata: languageName: node linkType: hard +"semver@npm:7.6.0": + version: 7.6.0 + resolution: "semver@npm:7.6.0" + dependencies: + lru-cache: "npm:^6.0.0" + bin: + semver: bin/semver.js + checksum: 10c0/fbfe717094ace0aa8d6332d7ef5ce727259815bd8d8815700853f4faf23aacbd7192522f0dc5af6df52ef4fa85a355ebd2f5d39f554bd028200d6cf481ab9b53 + languageName: node + linkType: hard + "semver@npm:^6.0.0, semver@npm:^6.1.2, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" @@ -13886,16 +13921,16 @@ __metadata: linkType: hard "sigstore@npm:^2.2.0": - version: 2.3.0 - resolution: "sigstore@npm:2.3.0" + version: 2.3.1 + resolution: "sigstore@npm:2.3.1" dependencies: - "@sigstore/bundle": "npm:^2.3.1" + "@sigstore/bundle": "npm:^2.3.2" "@sigstore/core": "npm:^1.0.0" - "@sigstore/protobuf-specs": "npm:^0.3.1" - "@sigstore/sign": "npm:^2.3.0" - "@sigstore/tuf": "npm:^2.3.1" - "@sigstore/verify": "npm:^1.2.0" - checksum: 10c0/13271fc0d0960a61994faf1a9c165429e74b09d090fb3f9dbe63b8c4ce5e275ade8abf5c72b738684888a8b87538ec2c4691d7a06c6023c0f2ff8f1aea104f2d + "@sigstore/protobuf-specs": "npm:^0.3.2" + "@sigstore/sign": "npm:^2.3.2" + "@sigstore/tuf": "npm:^2.3.4" + "@sigstore/verify": "npm:^1.2.1" + checksum: 10c0/8906b1074130d430d707e46f15c66eb6996891dc0d068705f1884fb1251a4a367f437267d44102cdebcee34f1768b3f30131a2ec8fb7aac74ba250903a459aa7 languageName: node linkType: hard @@ -14127,12 +14162,12 @@ __metadata: linkType: hard "socks@npm:^2.6.2, socks@npm:^2.7.1": - version: 2.8.1 - resolution: "socks@npm:2.8.1" + version: 2.8.3 + resolution: "socks@npm:2.8.3" dependencies: ip-address: "npm:^9.0.5" smart-buffer: "npm:^4.2.0" - checksum: 10c0/ac77b515c260473cc7c4452f09b20939e22510ce3ae48385c516d1d5784374d5cc75be3cb18ff66cc985a7f4f2ef8fef84e984c5ec70aad58355ed59241f40a8 + checksum: 10c0/d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7 languageName: node linkType: hard @@ -14320,11 +14355,11 @@ __metadata: linkType: hard "ssri@npm:^10.0.0, ssri@npm:^10.0.1": - version: 10.0.5 - resolution: "ssri@npm:10.0.5" + version: 10.0.6 + resolution: "ssri@npm:10.0.6" dependencies: minipass: "npm:^7.0.3" - checksum: 10c0/b091f2ae92474183c7ac5ed3f9811457e1df23df7a7e70c9476eaa9a0c4a0c8fc190fb45acefbf023ca9ee864dd6754237a697dc52a0fb182afe65d8e77443d8 + checksum: 10c0/e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227 languageName: node linkType: hard @@ -14921,7 +14956,7 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^1.0.1": +"ts-api-utils@npm:^1.3.0": version: 1.3.0 resolution: "ts-api-utils@npm:1.3.0" peerDependencies: @@ -15027,14 +15062,14 @@ __metadata: languageName: node linkType: hard -"tuf-js@npm:^2.2.0": - version: 2.2.0 - resolution: "tuf-js@npm:2.2.0" +"tuf-js@npm:^2.2.1": + version: 2.2.1 + resolution: "tuf-js@npm:2.2.1" dependencies: - "@tufjs/models": "npm:2.0.0" + "@tufjs/models": "npm:2.0.1" debug: "npm:^4.3.4" - make-fetch-happen: "npm:^13.0.0" - checksum: 10c0/9a11793feed2aa798c1a50107a0f031034b4a670016684e0d0b7d97be3fff7f98f53783c30120bce795c16d58f1b951410bb673aae92cc2437d641cc7457e215 + make-fetch-happen: "npm:^13.0.1" + checksum: 10c0/7c17b097571f001730d7be0aeaec6bec46ed2f25bf73990b1133c383d511a1ce65f831e5d6d78770940a85b67664576ff0e4c98e5421bab6d33ff36e4be500c8 languageName: node linkType: hard @@ -15368,16 +15403,16 @@ __metadata: linkType: hard "update-browserslist-db@npm:^1.0.13": - version: 1.0.13 - resolution: "update-browserslist-db@npm:1.0.13" + version: 1.0.16 + resolution: "update-browserslist-db@npm:1.0.16" dependencies: - escalade: "npm:^3.1.1" - picocolors: "npm:^1.0.0" + escalade: "npm:^3.1.2" + picocolors: "npm:^1.0.1" peerDependencies: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 10c0/e52b8b521c78ce1e0c775f356cd16a9c22c70d25f3e01180839c407a5dc787fb05a13f67560cbaf316770d26fa99f78f1acd711b1b54a4f35d4820d4ea7136e6 + checksum: 10c0/5995399fc202adbb51567e4810e146cdf7af630a92cc969365a099150cb00597e425cc14987ca7080b09a4d0cfd2a3de53fbe72eebff171aed7f9bb81f9bf405 languageName: node linkType: hard @@ -15466,7 +15501,7 @@ __metadata: languageName: node linkType: hard -"validate-npm-package-name@npm:5.0.0, validate-npm-package-name@npm:^5.0.0": +"validate-npm-package-name@npm:5.0.0": version: 5.0.0 resolution: "validate-npm-package-name@npm:5.0.0" dependencies: @@ -15484,6 +15519,13 @@ __metadata: languageName: node linkType: hard +"validate-npm-package-name@npm:^5.0.0": + version: 5.0.1 + resolution: "validate-npm-package-name@npm:5.0.1" + checksum: 10c0/903e738f7387404bb72f7ac34e45d7010c877abd2803dc2d614612527927a40a6d024420033132e667b1bade94544b8a1f65c9431a4eb30d0ce0d80093cd1f74 + languageName: node + linkType: hard + "validator@npm:^13.11.0": version: 13.12.0 resolution: "validator@npm:13.12.0" @@ -15727,7 +15769,7 @@ __metadata: languageName: node linkType: hard -"word-wrap@npm:~1.2.3": +"word-wrap@npm:^1.2.5, word-wrap@npm:~1.2.3": version: 1.2.5 resolution: "word-wrap@npm:1.2.5" checksum: 10c0/e0e4a1ca27599c92a6ca4c32260e8a92e8a44f4ef6ef93f803f8ed823f486e0889fc0b93be4db59c8d51b3064951d25e43d434e95dc8c960cc3a63d65d00ba20 From 7abdd070623ea817ba8cd772dafadd8243e94b81 Mon Sep 17 00:00:00 2001 From: Hasan Jamil <78340806+hjamil-24@users.noreply.github.com> Date: Mon, 24 Jun 2024 14:25:46 +0530 Subject: [PATCH 2/2] Revert "feat(oracle): Oracle V7 support" This reverts commit 946bbd6568ae8dee9ba71a78950cdd38cbf90d77. --- .github/workflows/ci.yml | 4 +- CHANGELOG.md | 12 + dev/oracle/latest/docker-compose.yml | 18 - dev/oracle/latest/reset.sh | 7 - dev/oracle/latest/start.sh | 22 - dev/oracle/latest/stop.sh | 10 - dev/oracle/oldest/docker-compose.yml | 17 - dev/oracle/oldest/reset.sh | 7 - dev/oracle/oldest/start.sh | 22 - dev/oracle/oldest/stop.sh | 10 - dev/oracle/privileges.sql | 6 - dev/oracle/wait-until-healthy.sh | 21 - package.json | 8 +- packages/core/CHANGELOG.md | 11 + packages/core/package.json | 10 +- packages/core/src/abstract-dialect/dialect.ts | 8 - .../query-generator-typescript.ts | 11 +- .../src/abstract-dialect/query-generator.js | 86 +- packages/core/src/model.js | 2 +- packages/core/src/sequelize-typescript.ts | 1 - packages/core/src/sequelize.internals.ts | 5 +- packages/core/src/sequelize.js | 2 +- packages/core/test/config/config.ts | 19 - .../associations/belongs-to-many.test.js | 64 +- .../associations/belongs-to.test.js | 2 +- .../integration/associations/has-many.test.js | 2 +- .../integration/associations/has-one.test.js | 2 +- packages/core/test/integration/cls.test.ts | 6 +- .../test/integration/configuration.test.ts | 9 - .../integration/data-types/data-types.test.ts | 251 ++-- .../integration/data-types/methods.test.ts | 335 +++-- .../oracle/data-types/methods.test.ts | 213 --- packages/core/test/integration/error.test.ts | 40 +- .../core/test/integration/include.test.js | 14 - .../test/integration/include/findAll.test.js | 8 +- .../test/integration/include/schema.test.js | 10 +- .../test/integration/instance/values.test.js | 4 +- packages/core/test/integration/json.test.ts | 21 +- .../model-repository/bulk-destroy.test.ts | 18 - .../model-repository/destroy.test.ts | 16 - packages/core/test/integration/model.test.js | 49 +- .../model/attributes/field.test.js | 10 - .../model/attributes/types.test.js | 2 - .../integration/model/bulk-create.test.js | 1 - .../core/test/integration/model/count.test.js | 7 +- .../test/integration/model/create.test.js | 6 +- .../test/integration/model/findAll.test.js | 5 +- .../integration/model/findAll/order.test.js | 4 +- .../test/integration/model/paranoid.test.js | 58 +- .../test/integration/model/update.test.ts | 1 - packages/core/test/integration/pool.test.ts | 8 - .../add-show-remove-constraint.test.ts | 82 +- .../query-interface/changeColumn.test.js | 6 +- .../query-interface/describeTable.test.js | 10 - .../query-interface/list-tables.test.ts | 24 +- .../query-interface/remove-column.test.ts | 8 +- .../query-interface/schemas.test.ts | 9 +- .../core/test/integration/sequelize.test.js | 17 +- .../test/integration/sequelize/query.test.js | 144 +- .../integration/sequelize/transaction.test.ts | 9 +- .../core/test/integration/transaction.test.js | 36 +- packages/core/test/integration/utils.test.ts | 4 +- packages/core/test/unit/configuration.test.ts | 2 +- .../test/unit/data-types/binary-types.test.ts | 4 - .../unit/data-types/decimal-numbers.test.ts | 24 +- .../test/unit/data-types/integers.test.ts | 25 +- .../unit/data-types/misc-data-types.test.ts | 4 - .../test/unit/data-types/string-types.test.ts | 12 - .../unit/data-types/temporal-types.test.ts | 6 - .../core/test/unit/data-types/uuid.test.ts | 1 - packages/core/test/unit/pool.test.ts | 9 - .../query-generator/add-column-query.test.ts | 1 - .../add-constraint-query.test.ts | 2 +- .../query-generator/bulk-delete-query.test.ts | 4 - .../query-generator/bulk-insert-query.test.ts | 7 +- .../commit-transaction-query.test.ts | 1 - .../create-schema-query.test.ts | 18 +- .../create-table-query.test.ts | 35 - .../describe-table-query.test.ts | 25 - .../query-generator/drop-schema-query.test.ts | 4 - .../query-generator/drop-table-query.test.ts | 7 - .../get-constraint-snippet.test.ts | 2 +- .../unit/query-generator/insert-query.test.ts | 20 +- .../json-path-extraction-query.test.ts | 4 - .../list-schemas-query.test.ts | 2 - .../query-generator/list-tables-query.test.ts | 3 - .../remove-constraint-query.test.ts | 4 - .../remove-index-query.test.ts | 19 +- .../rename-table-query.test.ts | 6 +- .../rollback-transaction-query.test.ts | 1 - .../unit/query-generator/select-query.test.ts | 88 -- .../set-isolation-level-query.test.ts | 2 - .../show-constraints-query.test.ts | 9 - .../show-indexes-query.test.ts | 28 - .../start-transaction-query.test.ts | 4 +- .../table-exists-query.test.ts | 6 - .../truncate-table-query.test.ts | 6 - .../unit/query-generator/update-query.test.ts | 13 - .../query-generator/version-query.test.ts | 1 - .../unit/query-interface/bulk-insert.test.ts | 4 - .../unit/query-interface/bulk-update.test.ts | 3 - .../unit/query-interface/create-table.test.ts | 4 - .../unit/query-interface/drop-table.test.ts | 1 - .../test/unit/query-interface/insert.test.ts | 190 ++- .../unit/query-interface/raw-select.test.ts | 1 - .../test/unit/query-interface/select.test.ts | 1 - .../test/unit/query-interface/update.test.ts | 3 - .../test/unit/query-interface/upsert.test.ts | 229 ++- .../core/test/unit/sql/add-column.test.js | 1 - .../core/test/unit/sql/change-column.test.js | 7 - .../core/test/unit/sql/create-table.test.js | 3 - .../core/test/unit/sql/generateJoin.test.js | 19 +- packages/core/test/unit/sql/group.test.js | 2 - packages/core/test/unit/sql/index.test.js | 3 - packages/core/test/unit/sql/insert.test.js | 12 +- packages/core/test/unit/sql/literal.test.ts | 8 - packages/core/test/unit/sql/order.test.js | 2 - packages/core/test/unit/sql/select.test.js | 134 +- packages/core/test/unit/sql/update.test.js | 3 - packages/core/test/unit/sql/where.test.ts | 40 - packages/core/test/unit/transaction.test.ts | 2 - packages/core/test/unit/utils/sql.test.ts | 38 - packages/oracle/.eslintrc.js | 5 - packages/oracle/package.json | 53 - .../src/_internal/data-types-overrides.ts | 427 ------ packages/oracle/src/connection-manager.ts | 181 --- packages/oracle/src/dialect.ts | 192 --- packages/oracle/src/index.mjs | 7 - packages/oracle/src/index.ts | 7 - .../query-generator-typescript.internal.ts | 336 ----- packages/oracle/src/query-generator.d.ts | 5 - .../oracle/src/query-generator.internal.ts | 50 - packages/oracle/src/query-generator.js | 1295 ----------------- .../query-interface-typescript.internal.ts | 45 - packages/oracle/src/query-interface.d.ts | 8 - packages/oracle/src/query-interface.js | 93 -- packages/oracle/src/query.d.ts | 5 - packages/oracle/src/query.js | 755 ---------- packages/oracle/tsconfig.json | 8 - packages/oracle/typedoc.json | 5 - packages/snowflake/package.json | 2 +- packages/utils/CHANGELOG.md | 8 + packages/validator-js/CHANGELOG.md | 8 + test/esm-named-exports.test.js | 1 - yarn.lock | 788 +++++----- 145 files changed, 1141 insertions(+), 6096 deletions(-) create mode 100644 CHANGELOG.md delete mode 100644 dev/oracle/latest/docker-compose.yml delete mode 100644 dev/oracle/latest/reset.sh delete mode 100644 dev/oracle/latest/start.sh delete mode 100644 dev/oracle/latest/stop.sh delete mode 100644 dev/oracle/oldest/docker-compose.yml delete mode 100644 dev/oracle/oldest/reset.sh delete mode 100644 dev/oracle/oldest/start.sh delete mode 100644 dev/oracle/oldest/stop.sh delete mode 100644 dev/oracle/privileges.sql delete mode 100755 dev/oracle/wait-until-healthy.sh create mode 100644 packages/core/CHANGELOG.md delete mode 100644 packages/core/test/integration/dialects/oracle/data-types/methods.test.ts delete mode 100644 packages/oracle/.eslintrc.js delete mode 100644 packages/oracle/package.json delete mode 100644 packages/oracle/src/_internal/data-types-overrides.ts delete mode 100644 packages/oracle/src/connection-manager.ts delete mode 100644 packages/oracle/src/dialect.ts delete mode 100644 packages/oracle/src/index.mjs delete mode 100644 packages/oracle/src/index.ts delete mode 100644 packages/oracle/src/query-generator-typescript.internal.ts delete mode 100644 packages/oracle/src/query-generator.d.ts delete mode 100644 packages/oracle/src/query-generator.internal.ts delete mode 100644 packages/oracle/src/query-generator.js delete mode 100644 packages/oracle/src/query-interface-typescript.internal.ts delete mode 100644 packages/oracle/src/query-interface.d.ts delete mode 100644 packages/oracle/src/query-interface.js delete mode 100644 packages/oracle/src/query.d.ts delete mode 100644 packages/oracle/src/query.js delete mode 100644 packages/oracle/tsconfig.json delete mode 100644 packages/oracle/typedoc.json create mode 100644 packages/utils/CHANGELOG.md create mode 100644 packages/validator-js/CHANGELOG.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 06e4925fcf8e..52451795f2e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -108,8 +108,6 @@ jobs: run: yarn lerna run test-unit-ibmi --scope=@sequelize/core - name: Unit tests (core - snowflake) run: yarn lerna run test-unit-snowflake --scope=@sequelize/core - - name: Unit tests (core - oracle) - run: yarn lerna run test-unit-oracle --scope=@sequelize/core - name: SQLite SSCCE run: yarn sscce-sqlite3 test-win: @@ -235,7 +233,7 @@ jobs: matrix: node-version: [18, 20] database-version: [oldest, latest] - dialect: [mysql, mariadb, mssql, db2, oracle] + dialect: [mysql, mariadb, mssql, db2] name: ${{ matrix.dialect }} ${{ matrix.database-version }} (Node ${{ matrix.node-version }}) runs-on: ubuntu-latest needs: [unit-test, test-typings] diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000000..98985ff78922 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [7.0.0-alpha.41](https://github.com/sequelize/sequelize/compare/v7.0.0-alpha.40...v7.0.0-alpha.41) (2024-05-17) + +### Bug Fixes + +- make `BaseSqlExpression` a unique class ([#17158](https://github.com/sequelize/sequelize/issues/17158)) ([6a5ea6c](https://github.com/sequelize/sequelize/commit/6a5ea6c774b1812a40dd26e873b56291f868bf3f)) +- set sequelize dialect type in query generator and interface ([#17285](https://github.com/sequelize/sequelize/issues/17285)) ([0227288](https://github.com/sequelize/sequelize/commit/0227288d1c6fcbf2d4f09e2efa50e4aeb9d435f2)) +- **snowflake:** add proxy connection options ([#17309](https://github.com/sequelize/sequelize/issues/17309)) ([51b781e](https://github.com/sequelize/sequelize/commit/51b781e4028f4eda5c4221d94cf4c9141055a762)) diff --git a/dev/oracle/latest/docker-compose.yml b/dev/oracle/latest/docker-compose.yml deleted file mode 100644 index e605de6d215f..000000000000 --- a/dev/oracle/latest/docker-compose.yml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -services: - oraclexedb: - container_name: oraclexedb - image: gvenzl/oracle-free:23.4-slim - environment: - ORACLE_PASSWORD: password - ORACLE_DATABASE: XEPDB1 - ports: - - 1521:1521 - healthcheck: - test: ['CMD-SHELL', 'sqlplus', 'system/password@localhost:1521/XEPDB1'] - retries: 10 - -networks: - default: - name: sequelize-oraclexedb-network diff --git a/dev/oracle/latest/reset.sh b/dev/oracle/latest/reset.sh deleted file mode 100644 index 65e5dd244865..000000000000 --- a/dev/oracle/latest/reset.sh +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -#!/usr/bin/env bash -set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ -cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 - -docker compose -p oraclexedb down --remove-orphans --volumes diff --git a/dev/oracle/latest/start.sh b/dev/oracle/latest/start.sh deleted file mode 100644 index 17db4f2ab52b..000000000000 --- a/dev/oracle/latest/start.sh +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -#!/usr/bin/env bash -set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ -cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 - -# Remove an existing Oracle DB docker image -docker-compose -p oraclexedb down --remove-orphans - -# Bring up new Oracle DB docker image -docker-compose -p oraclexedb up -d - -# Wait until Oracle DB is set up and docker state is healthy -./../wait-until-healthy.sh oraclexedb - -# Moving privileges.sql to docker container -docker cp ../privileges.sql oraclexedb:/opt/oracle/. - -# Granting all the needed privileges to sequelizetest user -docker exec -t oraclexedb sqlplus system/password@localhost:1521/XEPDB1 @privileges.sql - -echo "Local Oracle DB is ready for use!" \ No newline at end of file diff --git a/dev/oracle/latest/stop.sh b/dev/oracle/latest/stop.sh deleted file mode 100644 index 10a1b9f82962..000000000000 --- a/dev/oracle/latest/stop.sh +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -#!/usr/bin/env bash -set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ -cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 - - -docker-compose -p oraclexedb down --remove-orphans - -echo "Local Oracle DB instance stopped (if it was running). \ No newline at end of file diff --git a/dev/oracle/oldest/docker-compose.yml b/dev/oracle/oldest/docker-compose.yml deleted file mode 100644 index a67c6d82ddb8..000000000000 --- a/dev/oracle/oldest/docker-compose.yml +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -services: - oraclexedb: - container_name: oraclexedb - image: gvenzl/oracle-xe:18-slim - environment: - ORACLE_PASSWORD: password - ports: - - 1521:1521 - healthcheck: - test: ['CMD-SHELL', 'sqlplus', 'system/password@XEPDB1'] - retries: 10 - -networks: - default: - name: sequelize-oraclexedb-network diff --git a/dev/oracle/oldest/reset.sh b/dev/oracle/oldest/reset.sh deleted file mode 100644 index 65e5dd244865..000000000000 --- a/dev/oracle/oldest/reset.sh +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -#!/usr/bin/env bash -set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ -cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 - -docker compose -p oraclexedb down --remove-orphans --volumes diff --git a/dev/oracle/oldest/start.sh b/dev/oracle/oldest/start.sh deleted file mode 100644 index 7e65c69a0660..000000000000 --- a/dev/oracle/oldest/start.sh +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -#!/usr/bin/env bash -set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ -cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 - -# Remove an existing Oracle DB docker image -docker-compose -p oraclexedb down --remove-orphans - -# Bring up new Oracle DB docker image -docker-compose -p oraclexedb up -d - -# Wait until Oracle DB is set up and docker state is healthy -./../wait-until-healthy.sh oraclexedb - -# Moving privileges.sql to docker container -docker cp ../privileges.sql oraclexedb:/opt/oracle/. - -# Granting all the needed privileges to sequelizetest user -docker exec -t oraclexedb sqlplus system/password@XEPDB1 @privileges.sql - -echo "Local Oracle DB is ready for use!" \ No newline at end of file diff --git a/dev/oracle/oldest/stop.sh b/dev/oracle/oldest/stop.sh deleted file mode 100644 index 9a2cd75af41d..000000000000 --- a/dev/oracle/oldest/stop.sh +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -#!/usr/bin/env bash -set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ -cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 - - -docker-compose -p oraclexedb down --remove-orphans - -echo "Local Oracle DB instance stopped (if it was running)." \ No newline at end of file diff --git a/dev/oracle/privileges.sql b/dev/oracle/privileges.sql deleted file mode 100644 index 2f58584b9064..000000000000 --- a/dev/oracle/privileges.sql +++ /dev/null @@ -1,6 +0,0 @@ --- Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -create user sequelizetest identified by sequelizepassword; -grant all privileges to sequelizetest; -alter user sequelizetest quota unlimited on users; -exit; \ No newline at end of file diff --git a/dev/oracle/wait-until-healthy.sh b/dev/oracle/wait-until-healthy.sh deleted file mode 100755 index 096242f82a05..000000000000 --- a/dev/oracle/wait-until-healthy.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -if [ "$#" -ne 1 ]; then - >&2 echo "Please provide the container name or hash" - exit 1 -fi - -for _ in {1..50} -do - state=$(docker inspect -f '{{ .State.Health.Status }}' $1 2>&1) - return_code=$? - if [ ${return_code} -eq 0 ] && [ "$state" == "healthy" ]; then - echo "$1 is healthy!" - sleep 60 - exit 0 - fi - sleep 6 -done - ->&2 echo "Timeout of 5m exceeded when waiting for container to be healthy: $1" -exit 1 diff --git a/package.json b/package.json index 8abe7f810484..dba122361310 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,6 @@ "test-integration-db2": "yarn lerna run test-integration-db2", "test-integration-ibmi": "yarn lerna run test-integration-ibmi", "test-integration-snowflake": "yarn lerna run test-integration-snowflake", - "test-integration-oracle": "yarn lerna run test-integration-oracle", "sync-exports": "lerna run sync-exports", "build": "lerna run build", "docs": "typedoc", @@ -35,7 +34,6 @@ "reset-postgres": "bash dev/postgres/oldest/reset.sh; bash dev/postgres/latest/reset.sh", "reset-mssql": "bash dev/mssql/oldest/reset.sh; bash dev/mssql/latest/reset.sh", "reset-db2": "bash dev/db2/oldest/reset.sh; bash dev/db2/latest/reset.sh", - "reset-oracle": "bash dev/oracle/oldest/reset.sh; bash dev/oracle/latest/reset.sh", "reset-all": "concurrently \"npm:reset-*(!all)\"", "start-mariadb-oldest": "bash dev/mariadb/oldest/start.sh", "start-mariadb-latest": "bash dev/mariadb/latest/start.sh", @@ -47,8 +45,6 @@ "start-mssql-latest": "bash dev/mssql/latest/start.sh", "start-db2-oldest": "bash dev/db2/oldest/start.sh", "start-db2-latest": "bash dev/db2/latest/start.sh", - "start-oracle-oldest": "bash dev/oracle/oldest/start.sh", - "start-oracle-latest": "bash dev/oracle/latest/start.sh", "start-oldest": "concurrently \"npm:start-*-oldest\"", "start-latest": "concurrently \"npm:start-*-latest\"", "stop-mariadb": "bash dev/mariadb/oldest/stop.sh; bash dev/mariadb/latest/stop.sh", @@ -56,7 +52,6 @@ "stop-postgres": "bash dev/postgres/oldest/stop.sh; bash dev/postgres/latest/stop.sh", "stop-mssql": "bash dev/mssql/oldest/stop.sh; bash dev/mssql/latest/stop.sh", "stop-db2": "bash dev/db2/oldest/stop.sh; bash dev/db2/latest/stop.sh", - "stop-oracle": "bash dev/oracle/oldest/stop.sh; bash dev/oracle/latest/stop.sh", "stop-all": "concurrently \"npm:stop-*(!all)\"", "----------------------------------------- SSCCEs ------------------------------------------": "", "sscce": "ts-node sscce.ts", @@ -66,8 +61,7 @@ "sscce-postgres-native": "cross-env DIALECT=postgres-native yarn sscce", "sscce-sqlite3": "cross-env DIALECT=sqlite3 yarn sscce", "sscce-mssql": "cross-env DIALECT=mssql yarn sscce", - "sscce-db2": "cross-env DIALECT=db2 yarn sscce", - "sscce-oracle": "cross-env DIALECT=oracle yarn sscce" + "sscce-db2": "cross-env DIALECT=db2 yarn sscce" }, "workspaces": [ "packages/*" diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md new file mode 100644 index 000000000000..d0aacc643d2e --- /dev/null +++ b/packages/core/CHANGELOG.md @@ -0,0 +1,11 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [7.0.0-alpha.41](https://github.com/sequelize/sequelize/compare/v7.0.0-alpha.40...v7.0.0-alpha.41) (2024-05-17) + +### Bug Fixes + +- make `BaseSqlExpression` a unique class ([#17158](https://github.com/sequelize/sequelize/issues/17158)) ([6a5ea6c](https://github.com/sequelize/sequelize/commit/6a5ea6c774b1812a40dd26e873b56291f868bf3f)) +- set sequelize dialect type in query generator and interface ([#17285](https://github.com/sequelize/sequelize/issues/17285)) ([0227288](https://github.com/sequelize/sequelize/commit/0227288d1c6fcbf2d4f09e2efa50e4aeb9d435f2)) diff --git a/packages/core/package.json b/packages/core/package.json index 00df9db06ee5..dfe8768e3f31 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@sequelize/core", - "description": "Sequelize is a promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Amazon Redshift, Snowflake’s Data Cloud, Db2, Oracle and IBM i. It features solid transaction support, relations, eager and lazy loading, read replication and more.", + "description": "Sequelize is a promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Amazon Redshift, Snowflake’s Data Cloud, Db2, and IBM i. It features solid transaction support, relations, eager and lazy loading, read replication and more.", "version": "7.0.0-alpha.41", "funding": [ { @@ -109,7 +109,6 @@ "sql", "sqlserver", "snowflake", - "oracledb", "orm", "nodejs", "object relational mapper", @@ -144,8 +143,7 @@ "test-unit-db2": "cross-env DIALECT=db2 yarn _test-unit", "test-unit-ibmi": "cross-env DIALECT=ibmi yarn _test-unit", "test-unit-snowflake": "cross-env DIALECT=snowflake yarn _test-unit", - "test-unit-oracle": "cross-env DIALECT=oracle yarn _test-unit", - "test-unit-all": "yarn test-unit-mariadb && yarn test-unit-mysql && yarn test-unit-postgres && yarn test-unit-mssql && yarn test-unit-sqlite && yarn test-unit-snowflake && yarn test-unit-db2 && yarn test-unit-oracle && yarn test-unit-ibmi", + "test-unit-all": "yarn test-unit-mariadb && yarn test-unit-mysql && yarn test-unit-postgres && yarn test-unit-mssql && yarn test-unit-sqlite3 && yarn test-unit-snowflake && yarn test-unit-db2 && yarn test-unit-ibmi", "test-unit": "yarn test-unit-all", "----------------------------------------- integration tests ---------------------------------------------": "", "test-integration-mariadb": "cross-env DIALECT=mariadb yarn test-integration", @@ -157,8 +155,7 @@ "test-integration-db2": "cross-env DIALECT=db2 yarn test-integration", "test-integration-ibmi": "cross-env DIALECT=ibmi yarn test-integration", "test-integration-snowflake": "cross-env DIALECT=snowflake yarn test-integration", - "test-integration-oracle": "cross-env DIALECT=oracle yarn test-integration", - "test-integration-all": "yarn test-integration-mariadb && yarn test-integration-mysql && yarn test-integration-postgres && yarn test-integration-postgres-native && yarn test-integration-sqlite && yarn test-integration-mssql && yarn test-integration-db2 && yarn test-integration-ibmi && yarn test-integration-snowflake && yarn test-integration-oracle", + "test-integration-all": "yarn test-integration-mariadb && yarn test-integration-mysql && yarn test-integration-postgres && yarn test-integration-postgres-native && yarn test-integration-sqlite3 && yarn test-integration-mssql && yarn test-integration-db2 && yarn test-integration-ibmi && yarn test-integration-snowflake", "----------------------------------------- all tests ---------------------------------------------": "", "test-mariadb": "cross-env DIALECT=mariadb yarn test", "test-mysql": "cross-env DIALECT=mysql yarn test", @@ -168,7 +165,6 @@ "test-mssql": "cross-env DIALECT=mssql yarn test", "test-db2": "cross-env DIALECT=db2 yarn test", "test-ibmi": "cross-env DIALECT=ibmi yarn test", - "test-oracle": "cross-env DIALECT=oracle yarn test", "----------------------------------------- development ---------------------------------------------": "", "build": "node ../../build-packages.mjs core" }, diff --git a/packages/core/src/abstract-dialect/dialect.ts b/packages/core/src/abstract-dialect/dialect.ts index 728837ca305a..b733b3d3428f 100644 --- a/packages/core/src/abstract-dialect/dialect.ts +++ b/packages/core/src/abstract-dialect/dialect.ts @@ -68,12 +68,6 @@ export type DialectSupports = { /* does the dialect support returning values for inserted/updated fields */ returnValues: false | 'output' | 'returning'; - /* does the dialect support returning values for inserted/updated fields in outBinds */ - returnIntoValues: boolean; - - /* does the dialect support topLevelOrderBy (ORDER BY clasue) to get desired results */ - topLevelOrderByRequired: boolean; - /* features specific to autoIncrement values */ autoIncrement: { /* does the dialect require modification of insert queries when inserting auto increment fields */ @@ -330,8 +324,6 @@ export abstract class AbstractDialect< skipLocked: false, finalTable: false, returnValues: false, - returnIntoValues: false, - topLevelOrderByRequired: false, autoIncrement: { identityInsert: false, defaultValue: true, diff --git a/packages/core/src/abstract-dialect/query-generator-typescript.ts b/packages/core/src/abstract-dialect/query-generator-typescript.ts index 87549432f857..b2312525f3db 100644 --- a/packages/core/src/abstract-dialect/query-generator-typescript.ts +++ b/packages/core/src/abstract-dialect/query-generator-typescript.ts @@ -607,15 +607,6 @@ export class AbstractQueryGeneratorTypeScript 0 ? valueQuery : emptyQuery}${returnAttributes.join(',')}`.trim()};`; + query = `${`${replacements.attributes.length > 0 ? valueQuery : emptyQuery}`.trim()};`; if (this.dialect.supports.finalTable) { query = `SELECT * FROM FINAL TABLE (${replacements.attributes.length > 0 ? valueQuery : emptyQuery});`; } @@ -420,17 +398,6 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { ]); } - /** - * Helper method for populating the returning into bind information - * that is needed by some dialects (currently Oracle) - * This is called when `dialect.supports.returnIntoClause` is `True` - * - * @private - */ - populateInsertQueryReturnIntoBinds() { - // noop by default - } - /** * Returns an update query * @@ -462,22 +429,14 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { const bindParam = options.bindParam === undefined ? this.bindParam(bind) : options.bindParam; - if (this.dialect.supports['LIMIT ON UPDATE'] && options.limit) { - if (!['mssql', 'db2', 'oracle'].includes(this.dialect.name)) { - // TODO: use bind parameter - suffix = ` LIMIT ${this.escape(options.limit, options)} `; - } else if (this.dialect.name === 'oracle') { - // This cannot be set in where clause because rownum will be quoted - if (where && ((where.length && where.length > 0) || Object.keys(where).length > 0)) { - // If we have a where clause, we add AND - suffix += ' AND '; - } else { - // No where clause, we add where - suffix += ' WHERE '; - } - - suffix += `rownum <= ${this.escape(options.limit)} `; - } + if ( + this.dialect.supports['LIMIT ON UPDATE'] && + options.limit && + this.dialect.name !== 'mssql' && + this.dialect.name !== 'db2' + ) { + // TODO: use bind parameter + suffix = ` LIMIT ${this.escape(options.limit, options)} `; } if (this.dialect.supports.returnValues && options.returning) { @@ -1224,13 +1183,7 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { } else { // Ordering is handled by the subqueries, so ordering the UNION'ed result is not needed groupedLimitOrder = options.order; - // For dialects which don't allow for ordering in the subqueries, the result of a select - // is a set, not a sequence, and so is the result of UNION. - // So the top level ORDER BY is required - if (!this.dialect.supports.topLevelOrderByRequired) { - delete options.order; - } - + delete options.order; where = and(new Literal(placeholder), where); } @@ -1251,7 +1204,7 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { model, }, model, - ).replace(/;$/, '')}) ${this.getAliasToken()} sub`; // Every derived table must have its own alias + ).replace(/;$/, '')}) AS sub`; // Every derived table must have its own alias const splicePos = baseQuery.indexOf(placeholder); mainQueryItems.push( @@ -1438,7 +1391,7 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { modelName: model && model.name, as: mainTable.quotedAs, }); - query = `SELECT ${attributes.main.join(', ')} FROM (${subQueryItems.join('')}) ${this.getAliasToken()} ${mainTable.quotedAs}${mainJoinQueries.join('')}${mainQueryItems.join('')}`; + query = `SELECT ${attributes.main.join(', ')} FROM (${subQueryItems.join('')}) AS ${mainTable.quotedAs}${mainJoinQueries.join('')}${mainQueryItems.join('')}`; } else { query = mainQueryItems.join(''); } @@ -1600,11 +1553,6 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { /json_extract\(/i, `json_extract(${this.quoteIdentifier(includeAs.internalAs)}.`, ); - } else if (/json_value\(/.test(attr)) { - prefix = attr.replace( - /json_value\(/i, - `json_value(${this.quoteIdentifier(includeAs.internalAs)}.`, - ); } else { prefix = `${this.quoteIdentifier(includeAs.internalAs)}.${this.quoteIdentifier(attr)}`; } @@ -1937,8 +1885,6 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { if (returnValuesType === 'returning') { returningFragment = ` RETURNING ${returnFields.join(', ')}`; - } else if (this.dialect.supports.returnIntoValues) { - returningFragment = ` RETURNING ${returnFields.join(', ')} INTO `; } else if (returnValuesType === 'output') { outputFragment = ` OUTPUT ${returnFields.map(field => `INSERTED.${field}`).join(', ')}`; @@ -1954,7 +1900,7 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { } } - return { outputFragment, returnFields, returnTypes, returningFragment, tmpTable }; + return { outputFragment, returnFields, returningFragment, tmpTable }; } generateThroughJoin(include, includeAs, parentTableName, topLevelInfo, options) { @@ -2334,7 +2280,7 @@ export class AbstractQueryGenerator extends AbstractQueryGeneratorTypeScript { fragment += ` ${attributes.join(', ')} FROM ${tables}`; if (options.groupedLimit) { - fragment += ` ${this.getAliasToken()} ${mainTableAs}`; + fragment += ` AS ${mainTableAs}`; } return fragment; diff --git a/packages/core/src/model.js b/packages/core/src/model.js index aa8c05d94842..d333d20916b5 100644 --- a/packages/core/src/model.js +++ b/packages/core/src/model.js @@ -2328,7 +2328,7 @@ ${associationOwner._getAssociationDebugList()}`); } } - if (options.ignoreDuplicates && ['mssql', 'db2', 'ibmi', 'oracle'].includes(dialect)) { + if (options.ignoreDuplicates && ['mssql', 'db2', 'ibmi'].includes(dialect)) { throw new Error(`${dialect} does not support the ignoreDuplicates option.`); } diff --git a/packages/core/src/sequelize-typescript.ts b/packages/core/src/sequelize-typescript.ts index 79bf9a5e2034..2b1d7f9dd67a 100644 --- a/packages/core/src/sequelize-typescript.ts +++ b/packages/core/src/sequelize-typescript.ts @@ -207,7 +207,6 @@ export const SUPPORTED_DIALECTS = Object.freeze([ 'db2', 'snowflake', 'ibmi', - 'oracle', ] as const); // DO NOT MAKE THIS CLASS PUBLIC! diff --git a/packages/core/src/sequelize.internals.ts b/packages/core/src/sequelize.internals.ts index 0701817d215f..4221d2ca9096 100644 --- a/packages/core/src/sequelize.internals.ts +++ b/packages/core/src/sequelize.internals.ts @@ -44,12 +44,9 @@ export function importDialect(dialect: string): typeof AbstractDialect { case 'snowflake': // eslint-disable-next-line import/no-extraneous-dependencies -- legacy function, will be removed. User needs to install the dependency themselves return require('@sequelize/snowflake').SnowflakeDialect; - case 'oracle': - // eslint-disable-next-line import/no-extraneous-dependencies -- legacy function, will be removed. User needs to install the dependency themselves - return require('@sequelize/oracle').OracleDialect; default: throw new Error( - `The dialect ${dialect} is not natively supported. Native dialects: mariadb, mssql, mysql, postgres, sqlite3, ibmi, db2, oracle and snowflake.`, + `The dialect ${dialect} is not natively supported. Native dialects: mariadb, mssql, mysql, postgres, sqlite3, ibmi, db2 and snowflake.`, ); } } diff --git a/packages/core/src/sequelize.js b/packages/core/src/sequelize.js index 95b24d27cea4..ef2ea2756319 100644 --- a/packages/core/src/sequelize.js +++ b/packages/core/src/sequelize.js @@ -594,7 +594,7 @@ Use Sequelize#query if you wish to use replacements.`); }; await this.query( - `SELECT 1+1 AS result${this.dialect.name === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : this.dialect.name === 'oracle' ? ' FROM DUAL' : ''}`, + `SELECT 1+1 AS result${this.dialect.name === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, options, ); } diff --git a/packages/core/test/config/config.ts b/packages/core/test/config/config.ts index 56627ba81ead..423c606b576b 100644 --- a/packages/core/test/config/config.ts +++ b/packages/core/test/config/config.ts @@ -4,7 +4,6 @@ import { IBMiDialect } from '@sequelize/db2-ibmi'; import { MariaDbDialect } from '@sequelize/mariadb'; import { MsSqlDialect } from '@sequelize/mssql'; import { MySqlDialect } from '@sequelize/mysql'; -import { OracleDialect } from '@sequelize/oracle'; import { PostgresDialect } from '@sequelize/postgres'; import { SnowflakeDialect } from '@sequelize/snowflake'; import { SqliteDialect } from '@sequelize/sqlite3'; @@ -28,7 +27,6 @@ export interface DialectConfigs { postgres: Options; db2: Options; ibmi: Options; - oracle: Options; } export interface DialectConnectionConfigs { @@ -40,7 +38,6 @@ export interface DialectConnectionConfigs { postgres: ConnectionOptions; db2: ConnectionOptions; ibmi: ConnectionOptions; - oracle: ConnectionOptions; } const seqPort = env.SEQ_PORT ? parseSafeInteger.orThrow(env.SEQ_PORT) : undefined; @@ -146,22 +143,6 @@ export const CONFIG: DialectConfigs = { }, }, - oracle: { - dialect: OracleDialect, - database: env.SEQ_ORACLE_DB || env.SEQ_DB || 'XEPDB1', - username: env.SEQ_ORACLE_USER || env.SEQ_USER || 'sequelizetest', - password: env.SEQ_ORACLE_PW || env.SEQ_PW || 'sequelizepassword', - host: env.SEQ_ORACLE_HOST || env.SEQ_HOST || '127.0.0.1', - port: env.SEQ_ORACLE_PORT || env.SEQ_PORT || 1521, - pool: { - max: Number(env.SEQ_ORACLE_POOL_MAX || env.SEQ_POOL_MAX || 5), - idle: Number(env.SEQ_ORACLE_POOL_IDLE || env.SEQ_POOL_IDLE || 3000), - }, - oracleOptions: { - stmtCacheSize: Number(env.SEQ_ORACLE_STMT_CACHE || 0), - }, - }, - ibmi: { dialect: IBMiDialect, dataSourceName: env.SEQ_IBMI_DB || env.SEQ_DB, diff --git a/packages/core/test/integration/associations/belongs-to-many.test.js b/packages/core/test/integration/associations/belongs-to-many.test.js index 982010719227..3485630f72f1 100644 --- a/packages/core/test/integration/associations/belongs-to-many.test.js +++ b/packages/core/test/integration/associations/belongs-to-many.test.js @@ -1797,9 +1797,7 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), () => { beforeEach(function () { const keyDataType = ['mysql', 'mariadb', 'db2', 'ibmi'].includes(dialect) ? 'BINARY(255)' - : dialect === 'oracle' - ? DataTypes.STRING(255, true) - : DataTypes.BLOB('tiny'); + : DataTypes.BLOB('tiny'); this.Article = this.sequelize.define('Article', { id: { type: keyDataType, @@ -2323,44 +2321,42 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), () => { await t.rollback(); }); - if (!['oracle'].includes(dialect)) { - it('supports transactions when updating a through model', async function () { - const sequelize = await Support.createSingleTransactionalTestSequelizeInstance( - this.sequelize, - ); - const User = sequelize.define('User', { username: DataTypes.STRING }); - const Task = sequelize.define('Task', { title: DataTypes.STRING }); + it('supports transactions when updating a through model', async function () { + const sequelize = await Support.createSingleTransactionalTestSequelizeInstance( + this.sequelize, + ); + const User = sequelize.define('User', { username: DataTypes.STRING }); + const Task = sequelize.define('Task', { title: DataTypes.STRING }); - const UserTask = sequelize.define('UserTask', { - status: DataTypes.STRING, - }); + const UserTask = sequelize.define('UserTask', { + status: DataTypes.STRING, + }); - User.belongsToMany(Task, { through: UserTask, as: 'Tasks', inverse: 'Users' }); - await sequelize.sync({ force: true }); + User.belongsToMany(Task, { through: UserTask, as: 'Tasks', inverse: 'Users' }); + await sequelize.sync({ force: true }); - const [user, task, t] = await Promise.all([ - User.create({ username: 'foo' }), - Task.create({ title: 'task' }), - sequelize.startUnmanagedTransaction({ isolationLevel: IsolationLevel.SERIALIZABLE }), - ]); + const [user, task, t] = await Promise.all([ + User.create({ username: 'foo' }), + Task.create({ title: 'task' }), + sequelize.startUnmanagedTransaction({ isolationLevel: IsolationLevel.SERIALIZABLE }), + ]); - await task.addUser(user, { through: { status: 'pending' } }); // Create without transaction, so the old value is - // accesible from outside the transaction - await task.addUser(user, { transaction: t, through: { status: 'completed' } }); // Add an already exisiting user in - // a transaction, updating a value - // in the join table + await task.addUser(user, { through: { status: 'pending' } }); // Create without transaction, so the old value is + // accesible from outside the transaction + await task.addUser(user, { transaction: t, through: { status: 'completed' } }); // Add an already exisiting user in + // a transaction, updating a value + // in the join table - const [tasks, transactionTasks] = await Promise.all([ - user.getTasks(), - user.getTasks({ transaction: t }), - ]); + const [tasks, transactionTasks] = await Promise.all([ + user.getTasks(), + user.getTasks({ transaction: t }), + ]); - expect(tasks[0].UserTask.status).to.equal('pending'); - expect(transactionTasks[0].UserTask.status).to.equal('completed'); + expect(tasks[0].UserTask.status).to.equal('pending'); + expect(transactionTasks[0].UserTask.status).to.equal('completed'); - await t.rollback(); - }); - } + await t.rollback(); + }); } it('supports passing the primary key instead of an object', async function () { diff --git a/packages/core/test/integration/associations/belongs-to.test.js b/packages/core/test/integration/associations/belongs-to.test.js index 716600a89eb9..7bd735627724 100644 --- a/packages/core/test/integration/associations/belongs-to.test.js +++ b/packages/core/test/integration/associations/belongs-to.test.js @@ -675,7 +675,7 @@ describe(Support.getTestDialectTeaser('BelongsTo'), () => { } // NOTE: mssql does not support changing an autoincrement primary key - if (!['mssql', 'db2', 'ibmi', 'oracle'].includes(dialect)) { + if (!['mssql', 'db2', 'ibmi'].includes(dialect)) { it('can cascade updates', async function () { const Task = this.sequelize.define('Task', { title: DataTypes.STRING }); const User = this.sequelize.define('User', { username: DataTypes.STRING }); diff --git a/packages/core/test/integration/associations/has-many.test.js b/packages/core/test/integration/associations/has-many.test.js index 04851a609c6e..3f99d23826d1 100644 --- a/packages/core/test/integration/associations/has-many.test.js +++ b/packages/core/test/integration/associations/has-many.test.js @@ -1114,7 +1114,7 @@ describe('HasMany', () => { }); // NOTE: mssql does not support changing an autoincrement primary key - if (!['mssql', 'db2', 'ibmi', 'oracle'].includes(dialectName)) { + if (!['mssql', 'db2', 'ibmi'].includes(dialectName)) { it('can cascade updates', async function () { const Task = this.sequelize.define('Task', { title: DataTypes.STRING }); const User = this.sequelize.define('User', { username: DataTypes.STRING }); diff --git a/packages/core/test/integration/associations/has-one.test.js b/packages/core/test/integration/associations/has-one.test.js index 46d28f206a30..58ebaf66da21 100644 --- a/packages/core/test/integration/associations/has-one.test.js +++ b/packages/core/test/integration/associations/has-one.test.js @@ -362,7 +362,7 @@ describe(Support.getTestDialectTeaser('HasOne'), () => { }); // NOTE: mssql does not support changing an autoincrement primary key - if (!['mssql', 'db2', 'ibmi', 'oracle'].includes(dialect)) { + if (!['mssql', 'db2', 'ibmi'].includes(dialect)) { it('can cascade updates', async function () { const Task = this.sequelize.define('Task', { title: DataTypes.STRING }); const User = this.sequelize.define('User', { username: DataTypes.STRING }); diff --git a/packages/core/test/integration/cls.test.ts b/packages/core/test/integration/cls.test.ts index 48f35f39c7e4..7b06946f3974 100644 --- a/packages/core/test/integration/cls.test.ts +++ b/packages/core/test/integration/cls.test.ts @@ -7,7 +7,6 @@ import sinon from 'sinon'; import { beforeAll2, createMultiTransactionalTestSequelizeInstance, - getTestDialect, sequelize, setResetMode, } from './support'; @@ -174,10 +173,7 @@ describe('AsyncLocalStorage (ContinuationLocalStorage) Transactions (CLS)', () = it('promises returned by sequelize.query are correctly patched', async () => { await vars.clsSequelize.transaction(async t => { - await vars.clsSequelize.query( - `select 1 ${getTestDialect() === 'oracle' ? 'FROM DUAL' : ''}`, - { type: QueryTypes.SELECT }, - ); + await vars.clsSequelize.query('select 1', { type: QueryTypes.SELECT }); return expect(vars.clsSequelize.getCurrentClsTransaction()).to.equal(t); }); diff --git a/packages/core/test/integration/configuration.test.ts b/packages/core/test/integration/configuration.test.ts index 76c5f1f385fc..e1bfcf075381 100644 --- a/packages/core/test/integration/configuration.test.ts +++ b/packages/core/test/integration/configuration.test.ts @@ -62,10 +62,6 @@ describe('Configuration', () => { storage: '/path/to/no/where/land', mode: OPEN_READONLY, }, - oracle: { - ...CONFIG.oracle, - port: 19_999, - }, }; const errorByDialect: Record> = { @@ -77,7 +73,6 @@ describe('Configuration', () => { snowflake: HostNotReachableError, db2: ConnectionRefusedError, sqlite3: InvalidConnectionError, - oracle: ConnectionRefusedError, }; const seq = new Sequelize(badHostConfigs[dialectName]); @@ -128,10 +123,6 @@ describe('Configuration', () => { ...CONFIG.ibmi, password: 'wrongpassword', }, - oracle: { - ...CONFIG.oracle, - password: 'wrongpassword', - }, }; const seq = new Sequelize(config[dialectName]); diff --git a/packages/core/test/integration/data-types/data-types.test.ts b/packages/core/test/integration/data-types/data-types.test.ts index 8c949ebb4f40..3d29a8c64276 100644 --- a/packages/core/test/integration/data-types/data-types.test.ts +++ b/packages/core/test/integration/data-types/data-types.test.ts @@ -128,16 +128,13 @@ describe('DataTypes', () => { return { User }; }); - (dialect.name !== 'oracle' ? it : it.skip)('accepts strings', async () => { + it('accepts strings', async () => { await testSimpleInOut(vars.User, 'binaryStringAttr', 'abc', 'abc'); }); - (dialect.name !== 'oracle' ? it : it.skip)( - 'is deserialized as a string when DataType is not specified', - async () => { - await testSimpleInOutRaw(vars.User, 'binaryStringAttr', 'abc', 'abc'); - }, - ); + it('is deserialized as a string when DataType is not specified', async () => { + await testSimpleInOutRaw(vars.User, 'binaryStringAttr', 'abc', 'abc'); + }); }); describe('STRING(100).BINARY', () => { @@ -167,7 +164,7 @@ describe('DataTypes', () => { }); // TODO: add length check constraint in sqlite - if (dialect.name !== 'sqlite3' && dialect.name !== 'oracle') { + if (dialect.name !== 'sqlite3') { it('throws if the string is too long', async () => { await expect( vars.User.create({ @@ -203,13 +200,9 @@ describe('DataTypes', () => { await testSimpleInOut(vars.User, 'textAttr', '123456', '123456'); }); - // For raw queries, Oracle expects hex string during insertion - (dialect.name === 'oracle' ? it.skip : it)( - 'is deserialized as a string when DataType is not specified', - async () => { - await testSimpleInOutRaw(vars.User, 'textAttr', 'abc', 'abc'); - }, - ); + it('is deserialized as a string when DataType is not specified', async () => { + await testSimpleInOutRaw(vars.User, 'textAttr', 'abc', 'abc'); + }); }); describe(`TEXT()`, () => { @@ -317,72 +310,70 @@ describe('DataTypes', () => { }); }); - if (dialect.name !== 'oracle') { - describe('CHAR().BINARY', () => { - if (!dialect.supports.dataTypes.CHAR) { - it('throws, because this dialect does not support CHAR', async () => { - expect(() => { - sequelize.define('CrashedModel', { - attr: DataTypes.CHAR(5), - }); - }).to.throwWithCause(`${dialect.name} does not support the CHAR data type.`); - }); + describe('CHAR().BINARY', () => { + if (!dialect.supports.dataTypes.CHAR) { + it('throws, because this dialect does not support CHAR', async () => { + expect(() => { + sequelize.define('CrashedModel', { + attr: DataTypes.CHAR(5), + }); + }).to.throwWithCause(`${dialect.name} does not support the CHAR data type.`); + }); - return; - } + return; + } - if (!dialect.supports.dataTypes.COLLATE_BINARY) { - it('throws if CHAR.BINARY is used', () => { - expect(() => { - sequelize.define('CrashedModel', { - attr: DataTypes.CHAR(5).BINARY, - }); - }).to.throwWithCause(`${dialect.name} does not support the CHAR.BINARY data type.`); - }); + if (!dialect.supports.dataTypes.COLLATE_BINARY) { + it('throws if CHAR.BINARY is used', () => { + expect(() => { + sequelize.define('CrashedModel', { + attr: DataTypes.CHAR(5).BINARY, + }); + }).to.throwWithCause(`${dialect.name} does not support the CHAR.BINARY data type.`); + }); - return; - } + return; + } - const vars = beforeAll2(async () => { - class User extends Model> { - declare binaryCharAttr: string | ArrayBuffer | Uint8Array | Blob; - } + const vars = beforeAll2(async () => { + class User extends Model> { + declare binaryCharAttr: string | ArrayBuffer | Uint8Array | Blob; + } - User.init( - { - binaryCharAttr: { - type: DataTypes.CHAR(5).BINARY, - allowNull: false, - }, + User.init( + { + binaryCharAttr: { + type: DataTypes.CHAR(5).BINARY, + allowNull: false, }, - { sequelize }, - ); + }, + { sequelize }, + ); - await User.sync({ force: true }); + await User.sync({ force: true }); - return { User }; - }); + return { User }; + }); - it('is serialized/deserialized as strings', async () => { - // mysql does not pad columns, unless PAD_CHAR_TO_FULL_LENGTH is true - if (dialect.name === 'db2') { - await testSimpleInOut(vars.User, 'binaryCharAttr', '1234', '1234 '); - } else { - await testSimpleInOut(vars.User, 'binaryCharAttr', '1234', '1234'); - } - }); + it('is serialized/deserialized as strings', async () => { + // mysql does not pad columns, unless PAD_CHAR_TO_FULL_LENGTH is true + if (dialect.name === 'db2') { + await testSimpleInOut(vars.User, 'binaryCharAttr', '1234', '1234 '); + } else { + await testSimpleInOut(vars.User, 'binaryCharAttr', '1234', '1234'); + } + }); - it('is deserialized as a string when DataType is not specified', async () => { - // mysql does not pad columns, unless PAD_CHAR_TO_FULL_LENGTH is true - // https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_pad_char_to_full_length - if (dialect.name === 'db2') { - await testSimpleInOutRaw(vars.User, 'binaryCharAttr', Buffer.from(' 234'), ' 234 '); - } else { - await testSimpleInOutRaw(vars.User, 'binaryCharAttr', Buffer.from(' 234'), ' 234'); - } - }); + it('is deserialized as a string when DataType is not specified', async () => { + // mysql does not pad columns, unless PAD_CHAR_TO_FULL_LENGTH is true + // https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_pad_char_to_full_length + if (dialect.name === 'db2') { + await testSimpleInOutRaw(vars.User, 'binaryCharAttr', Buffer.from(' 234'), ' 234 '); + } else { + await testSimpleInOutRaw(vars.User, 'binaryCharAttr', Buffer.from(' 234'), ' 234'); + } }); - } + }); describe('CITEXT', () => { if (!dialect.supports.dataTypes.CITEXT) { @@ -555,12 +546,6 @@ describe('DataTypes', () => { await testSimpleInOutRaw(vars.User, 'booleanAttr', true, 1); await testSimpleInOutRaw(vars.User, 'booleanAttr', false, 0); }); - } else if (dialect.name === 'oracle') { - // Oracle uses CHAR(1). - it('is deserialized as a char string when DataType is not specified', async () => { - await testSimpleInOutRaw(vars.User, 'booleanAttr', true, '1'); - await testSimpleInOutRaw(vars.User, 'booleanAttr', false, '0'); - }); } else { it('is deserialized as a boolean when DataType is not specified', async () => { await testSimpleInOutRaw(vars.User, 'booleanAttr', true, true); @@ -614,10 +599,7 @@ describe('DataTypes', () => { it('accepts numbers, bigints, strings', async () => { await testSimpleInOut(vars.User, 'intAttr', 123, 123); - if (dialect.name !== 'oracle') { - await testSimpleInOut(vars.User, 'intAttr', 123n, 123); - } - + await testSimpleInOut(vars.User, 'intAttr', 123n, 123); await testSimpleInOut(vars.User, 'intAttr', '123', 123); await testSimpleInOut( @@ -683,10 +665,7 @@ describe('DataTypes', () => { it('accepts numbers, bigints, strings', async () => { await testSimpleInOut(vars.User, 'intAttr', 123, 123); - if (dialect.name !== 'oracle') { - await testSimpleInOut(vars.User, 'intAttr', 123n, 123); - } - + await testSimpleInOut(vars.User, 'intAttr', 123n, 123); await testSimpleInOut(vars.User, 'intAttr', '123', 123); await testSimpleInOut( @@ -750,10 +729,8 @@ describe('DataTypes', () => { }); it('rejects unsafe integers', async () => { - if (dialect.name !== 'oracle') { - await expect(vars.User.create({ bigintAttr: 9_007_199_254_740_992 })).to.be.rejected; - await expect(vars.User.create({ bigintAttr: -9_007_199_254_740_992 })).to.be.rejected; - } + await expect(vars.User.create({ bigintAttr: 9_007_199_254_740_992 })).to.be.rejected; + await expect(vars.User.create({ bigintAttr: -9_007_199_254_740_992 })).to.be.rejected; await expect(vars.User.create({ bigintAttr: 123.4 })).to.be.rejected; await expect(vars.User.create({ bigintAttr: Number.NaN })).to.be.rejected; @@ -768,11 +745,7 @@ describe('DataTypes', () => { }); it('is deserialized as a string when DataType is not specified', async () => { - if (dialect.name !== 'oracle') { - await testSimpleInOutRaw(vars.User, 'bigintAttr', 123n, '123'); - } else { - await testSimpleInOutRaw(vars.User, 'bigintAttr', 123n, 123); - } + await testSimpleInOutRaw(vars.User, 'bigintAttr', 123n, '123'); }); if (dialect.supports.dataTypes.INTS.unsigned) { @@ -833,10 +806,7 @@ describe('DataTypes', () => { it(`accepts numbers, bigints, strings, +-Infinity`, async () => { await testSimpleInOut(vars.User, 'attr', 100.5, 100.5); - if (dialect.name !== 'oracle') { - await testSimpleInOut(vars.User, 'attr', 123n, 123); - } - + await testSimpleInOut(vars.User, 'attr', 123n, 123); await testSimpleInOut(vars.User, 'attr', '100.5', 100.5); }); @@ -885,9 +855,7 @@ describe('DataTypes', () => { it(`is deserialized as a JS number when DataType is not specified`, async () => { await testSimpleInOutRaw(vars.User, 'attr', 100.5, 100.5); - if (dialect.name !== 'oracle') { - await testSimpleInOutRaw(vars.User, 'attr', 123n, 123); - } + await testSimpleInOutRaw(vars.User, 'attr', 123n, 123); if (dialect.supports.dataTypes[attrType].NaN) { await testSimpleInOutRaw(vars.User, 'attr', Number.NaN, Number.NaN); @@ -986,10 +954,7 @@ describe('DataTypes', () => { it('accepts numbers, bigints, strings', async () => { await testSimpleInOut(vars.User, 'decimalAttr', 123.4, '123.4'); - if (dialect.name !== 'oracle') { - await testSimpleInOut(vars.User, 'decimalAttr', 123n, '123'); - } - + await testSimpleInOut(vars.User, 'decimalAttr', 123n, '123'); await testSimpleInOut(vars.User, 'decimalAttr', '123.4', '123.4'); }); @@ -1015,7 +980,7 @@ describe('DataTypes', () => { await expect(vars.User.create({ decimalAttr: 'abc' })).to.be.rejected; }); - if (dialect.name === 'sqlite3' || dialect.name === 'oracle') { + if (dialect.name === 'sqlite3') { // sqlite3 doesn't give us a way to do sql type-based parsing, *and* returns bigints as js numbers. // this behavior is undesired but is still tested against to ensure we update this test when this is finally fixed. it('is deserialized as a number when DataType is not specified (undesired sqlite limitation)', async () => { @@ -1068,7 +1033,6 @@ describe('DataTypes', () => { 123n, dialect.name === 'mssql' ? '123' : '123.00', ); - await testSimpleInOut( vars.User, 'decimalAttr', @@ -1231,9 +1195,7 @@ describe('DataTypes', () => { ? '2022-01-01 00:00:00.000 +00:00' : dialect.name === 'db2' ? '2022-01-01 00:00:00.000000+00' - : dialect.name === 'oracle' - ? new Date('2022-01-01T00:00:00Z') - : '2022-01-01 00:00:00+00', + : '2022-01-01 00:00:00+00', ); }); }); @@ -1271,7 +1233,7 @@ describe('DataTypes', () => { it('clamps to specified precision', async () => { // sqlite does not support restricting the precision - if (dialect.name !== 'sqlite3' && dialect.name !== 'oracle') { + if (dialect.name !== 'sqlite3') { await testSimpleInOut( vars.User, 'dateMinPrecisionAttr', @@ -1371,20 +1333,9 @@ describe('DataTypes', () => { } }); - if (dialect.name === 'oracle') { - it(`is deserialized as a date when DataType is not specified`, async () => { - await testSimpleInOutRaw( - vars.User, - 'dateAttr', - '2022-01-01', - new Date('2022-01-01T00:00:00.000Z'), - ); - }); - } else { - it(`is deserialized as a string when DataType is not specified`, async () => { - await testSimpleInOutRaw(vars.User, 'dateAttr', '2022-01-01', '2022-01-01'); - }); - } + it(`is deserialized as a string when DataType is not specified`, async () => { + await testSimpleInOutRaw(vars.User, 'dateAttr', '2022-01-01', '2022-01-01'); + }); }); describe('TIME(precision)', () => { @@ -1750,48 +1701,40 @@ describe('DataTypes', () => { // TODO: expected for mariadb 10.4 : https://jira.mariadb.org/browse/MDEV-15558 expect(table.jsonStr.type).to.equal('LONGTEXT'); break; - case 'oracle': - expect(table.jsonStr.type).to.equal('BLOB'); - break; default: expect(table.jsonStr.type).to.equal(jsonTypeName); } }); - // Oracle Database < 21 doesn't consider scalars as JSON column - // thus, fails the CHECK constraint test. - if (dialect.name !== 'oracle') { - it('properly serializes default values', async () => { - const createdUser = await vars.User.create(); - await createdUser.reload(); - expect(createdUser.get()).to.deep.eq({ - jsonStr: 'abc', - jsonBoolean: true, - jsonNumber: 1, - jsonNull: null, - jsonArray: ['a', 'b'], - jsonObject: { key: 'abc' }, - id: 1, - }); + it('properly serializes default values', async () => { + const createdUser = await vars.User.create(); + await createdUser.reload(); + expect(createdUser.get()).to.deep.eq({ + jsonStr: 'abc', + jsonBoolean: true, + jsonNumber: 1, + jsonNull: null, + jsonArray: ['a', 'b'], + jsonObject: { key: 'abc' }, + id: 1, }); + }); - it('properly serializes values', async () => { - await testSimpleInOut(vars.User, 'jsonStr', 'abc', 'abc'); - await testSimpleInOut(vars.User, 'jsonBoolean', true, true); - await testSimpleInOut(vars.User, 'jsonBoolean', false, false); - await testSimpleInOut(vars.User, 'jsonNumber', 123.4, 123.4); - await testSimpleInOut(vars.User, 'jsonArray', [1, 2], [1, 2]); - await testSimpleInOut(vars.User, 'jsonObject', { a: 1 }, { a: 1 }); - await testSimpleInOut(vars.User, 'jsonNull', null, null); - }); - } + it('properly serializes values', async () => { + await testSimpleInOut(vars.User, 'jsonStr', 'abc', 'abc'); + await testSimpleInOut(vars.User, 'jsonBoolean', true, true); + await testSimpleInOut(vars.User, 'jsonBoolean', false, false); + await testSimpleInOut(vars.User, 'jsonNumber', 123.4, 123.4); + await testSimpleInOut(vars.User, 'jsonArray', [1, 2], [1, 2]); + await testSimpleInOut(vars.User, 'jsonObject', { a: 1 }, { a: 1 }); + await testSimpleInOut(vars.User, 'jsonNull', null, null); + }); // MariaDB: supports a JSON type, but: // - MariaDB 10.5 says it's a JSON col, on which we enabled automatic JSON parsing. // - MariaDB 10.4 says it's a string, so we can't parse it based on the type. - // Oracle JSON is BLOB column with check `IS JSON`. // TODO [2024-06-18]: Re-enable this test when we drop support for MariaDB < 10.5 - if (dialect.name !== 'mariadb' && dialect.name !== 'oracle') { + if (dialect.name !== 'mariadb') { if (dialect.name === 'mssql' || dialect.name === 'sqlite3') { // MSSQL: does not have a JSON type, so we can't parse it if our DataType is not specified. // SQLite: sqlite3 does not tell us the type of a column, we cannot parse based on it. diff --git a/packages/core/test/integration/data-types/methods.test.ts b/packages/core/test/integration/data-types/methods.test.ts index 7c645fd98cd5..e0c1683f6c7a 100644 --- a/packages/core/test/integration/data-types/methods.test.ts +++ b/packages/core/test/integration/data-types/methods.test.ts @@ -15,204 +15,197 @@ import { beforeAll2, beforeEach2, sequelize, setResetMode } from '../support'; const dialect = sequelize.dialect; -// For a custom data-type definition for Oracle, _getBindDef() is required to -// provide information about BINDOUT variables. Similar tests have been added -// in dialects/oracle/data-types/methods.test.ts -if (dialect.name !== 'oracle') { - describe('DataType Methods', () => { - setResetMode('none'); - - const customValueSymbol = Symbol('dummy'); - - class CustomDataType extends DataTypes.STRING { - parseDatabaseValue(_value: unknown): any { - return customValueSymbol; - } - } +describe('DataType Methods', () => { + setResetMode('none'); - const models = beforeAll2(async () => { - class User extends Model, InferCreationAttributes> { - declare id: CreationOptional; - declare name: string | null; - declare projects?: NonAttribute; - } + const customValueSymbol = Symbol('dummy'); - User.init( - { - id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, - name: { type: CustomDataType, allowNull: true, field: 'first_name' }, - }, - { sequelize }, - ); + class CustomDataType extends DataTypes.STRING { + parseDatabaseValue(_value: unknown): any { + return customValueSymbol; + } + } - class Project extends Model, InferCreationAttributes> { - declare name: string; - declare userId: ForeignKey; - declare stakeholders?: NonAttribute< - Array - >; + const models = beforeAll2(async () => { + class User extends Model, InferCreationAttributes> { + declare id: CreationOptional; + declare name: string | null; + declare projects?: NonAttribute; + } - declare addStakeholder: BelongsToManyAddAssociationMixin; - } + User.init( + { + id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, + name: { type: CustomDataType, allowNull: true, field: 'first_name' }, + }, + { sequelize }, + ); - Project.init( - { - name: { type: CustomDataType, allowNull: false }, - }, - { sequelize }, - ); + class Project extends Model, InferCreationAttributes> { + declare name: string; + declare userId: ForeignKey; + declare stakeholders?: NonAttribute>; - class ProjectStakeholder extends Model< - InferAttributes, - InferCreationAttributes - > { - declare key: string; - } + declare addStakeholder: BelongsToManyAddAssociationMixin; + } - ProjectStakeholder.init( - { - key: { type: CustomDataType, allowNull: false }, - }, - { sequelize, noPrimaryKey: true, timestamps: false }, - ); - - Project.belongsTo(User, { - as: 'user', - inverse: { as: 'projects', type: 'hasMany' }, - foreignKey: 'userId', - }); - - Project.belongsToMany(User, { - as: 'stakeholders', - inverse: 'stakeholdings', - through: ProjectStakeholder, - }); - - await User.sync({ force: true }); - await Project.sync({ force: true }); - await ProjectStakeholder.sync({ force: true }); - - const user1 = await User.create({ name: 'John' }); - const user2 = await User.create({ name: 'Stakeholder User' }); - const project = await Project.create({ name: 'Project 1', userId: user1.id }); - await project.addStakeholder(user2, { through: { key: 'dummy-value' } }); - - return { User, Project, ProjectStakeholder }; - }); + Project.init( + { + name: { type: CustomDataType, allowNull: false }, + }, + { sequelize }, + ); + + class ProjectStakeholder extends Model< + InferAttributes, + InferCreationAttributes + > { + declare key: string; + } - const spies = beforeEach2(() => { - // add mocha spy to sanitize - return { - sanitize: sinon.spy(DataTypes.STRING.prototype, 'sanitize'), - validate: sinon.spy(DataTypes.STRING.prototype, 'validate'), - parseDatabaseValue: sinon.spy(CustomDataType.prototype, 'parseDatabaseValue'), - }; + ProjectStakeholder.init( + { + key: { type: CustomDataType, allowNull: false }, + }, + { sequelize, noPrimaryKey: true, timestamps: false }, + ); + + Project.belongsTo(User, { + as: 'user', + inverse: { as: 'projects', type: 'hasMany' }, + foreignKey: 'userId', }); - afterEach(() => { - for (const spy of Object.values(spies)) { - spy.restore(); - } + Project.belongsToMany(User, { + as: 'stakeholders', + inverse: 'stakeholdings', + through: ProjectStakeholder, }); - it(`setting a value on a model only calls 'sanitize'`, () => { - models.User.build({ name: 'foo' }); + await User.sync({ force: true }); + await Project.sync({ force: true }); + await ProjectStakeholder.sync({ force: true }); - expect(spies.sanitize.calledOnce).to.eq(true, 'sanitized not called exactly once'); - expect(spies.validate.called).to.eq(false, 'validate should not have been called'); - expect(spies.parseDatabaseValue.called).to.eq( - false, - 'parseDatabaseValue should not have been called', - ); - }); + const user1 = await User.create({ name: 'John' }); + const user2 = await User.create({ name: 'Stakeholder User' }); + const project = await Project.create({ name: 'Project 1', userId: user1.id }); + await project.addStakeholder(user2, { through: { key: 'dummy-value' } }); - it(`retrieving a model only calls 'parseDatabaseValue' (no join)`, async () => { - const out = await models.User.findOne({ rejectOnEmpty: true }); + return { User, Project, ProjectStakeholder }; + }); - expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue not called on top level model'); + const spies = beforeEach2(() => { + // add mocha spy to sanitize + return { + sanitize: sinon.spy(DataTypes.STRING.prototype, 'sanitize'), + validate: sinon.spy(DataTypes.STRING.prototype, 'validate'), + parseDatabaseValue: sinon.spy(CustomDataType.prototype, 'parseDatabaseValue'), + }; + }); - expect(spies.sanitize.called).to.eq(false, 'sanitize should not have been called'); - expect(spies.validate.called).to.eq(false, 'validate should not have been called'); - }); + afterEach(() => { + for (const spy of Object.values(spies)) { + spy.restore(); + } + }); - it(`retrieving a model only calls 'parseDatabaseValue' (with join)`, async () => { - // this test is separate from the no-join version because they use different code paths. - // We test both double nested associations & that through tables are handled correctly. - const out = await models.User.findOne({ - include: [ - { - association: 'projects', - include: ['stakeholders'], - }, - ], - rejectOnEmpty: true, - }); - - expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue not called on top level model'); - expect(out.projects![0].name).to.eq( - customValueSymbol, - 'parseDatabaseValue not called on first include level', - ); - expect(out.projects![0].stakeholders![0].name).to.eq( - customValueSymbol, - 'parseDatabaseValue not called on second include level', - ); - expect(out.projects![0].stakeholders![0].ProjectStakeholder.key).to.eq( - customValueSymbol, - 'parseDatabaseValue not called on Many-To-Many through table', - ); - - expect(spies.sanitize.called).to.eq(false, 'sanitize should not have been called'); - expect(spies.validate.called).to.eq(false, 'validate should not have been called'); - }); + it(`setting a value on a model only calls 'sanitize'`, () => { + models.User.build({ name: 'foo' }); - if (dialect.supports.returnValues) { - it(`inserting a model calls 'parseDatabaseValue' on returned values`, async () => { - // 'name' attr has a different name in the database - const out = await models.User.create({ name: 'foo' }, { returning: true }); + expect(spies.sanitize.calledOnce).to.eq(true, 'sanitized not called exactly once'); + expect(spies.validate.called).to.eq(false, 'validate should not have been called'); + expect(spies.parseDatabaseValue.called).to.eq( + false, + 'parseDatabaseValue should not have been called', + ); + }); - expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); + it(`retrieving a model only calls 'parseDatabaseValue' (no join)`, async () => { + const out = await models.User.findOne({ rejectOnEmpty: true }); - // sanitize is called when the user input is added to the model - expect(spies.sanitize.called).to.eq(true, 'sanitize should have been called'); - // validate is called before persisting the model - expect(spies.validate.called).to.eq(true, 'validate should have been called'); - }); + expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue not called on top level model'); - it(`upserting a model calls 'parseDatabaseValue' on returned values`, async () => { - // 'name' attr has a different name in the database - const [out] = await models.User.upsert({ name: 'foo', id: 1234 }, { returning: true }); + expect(spies.sanitize.called).to.eq(false, 'sanitize should not have been called'); + expect(spies.validate.called).to.eq(false, 'validate should not have been called'); + }); - expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); + it(`retrieving a model only calls 'parseDatabaseValue' (with join)`, async () => { + // this test is separate from the no-join version because they use different code paths. + // We test both double nested associations & that through tables are handled correctly. + const out = await models.User.findOne({ + include: [ + { + association: 'projects', + include: ['stakeholders'], + }, + ], + rejectOnEmpty: true, + }); - // sanitize is called when the user input is added to the model - expect(spies.sanitize.called).to.eq(true, 'sanitize should have been called'); - // validate is called before persisting the model - expect(spies.validate.called).to.eq(true, 'validate should have been called'); - }); - } + expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue not called on top level model'); + expect(out.projects![0].name).to.eq( + customValueSymbol, + 'parseDatabaseValue not called on first include level', + ); + expect(out.projects![0].stakeholders![0].name).to.eq( + customValueSymbol, + 'parseDatabaseValue not called on second include level', + ); + expect(out.projects![0].stakeholders![0].ProjectStakeholder.key).to.eq( + customValueSymbol, + 'parseDatabaseValue not called on Many-To-Many through table', + ); + + expect(spies.sanitize.called).to.eq(false, 'sanitize should not have been called'); + expect(spies.validate.called).to.eq(false, 'validate should not have been called'); + }); - if (dialect.supports.returnValues === 'returning') { - it(`updating a model calls 'parseDatabaseValue' on returned values`, async () => { - const user = await models.User.create({ name: 'foo' }); - user.name = 'bob'; - await user.save({ returning: true }); + if (dialect.supports.returnValues) { + it(`inserting a model calls 'parseDatabaseValue' on returned values`, async () => { + // 'name' attr has a different name in the database + const out = await models.User.create({ name: 'foo' }, { returning: true }); - expect(user.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); - }); + expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); - // TODO: add test for 'returning' on DELETE queries once https://github.com/sequelize/sequelize/pull/14879 has been merged - } + // sanitize is called when the user input is added to the model + expect(spies.sanitize.called).to.eq(true, 'sanitize should have been called'); + // validate is called before persisting the model + expect(spies.validate.called).to.eq(true, 'validate should have been called'); + }); + + it(`upserting a model calls 'parseDatabaseValue' on returned values`, async () => { + // 'name' attr has a different name in the database + const [out] = await models.User.upsert({ name: 'foo', id: 1234 }, { returning: true }); + + expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); + + // sanitize is called when the user input is added to the model + expect(spies.sanitize.called).to.eq(true, 'sanitize should have been called'); + // validate is called before persisting the model + expect(spies.validate.called).to.eq(true, 'validate should have been called'); + }); + } - it(`does not call 'parseDatabaseValue' on null values`, async () => { - const user = await models.User.create({ name: null }); - await user.reload(); + if (dialect.supports.returnValues === 'returning') { + it(`updating a model calls 'parseDatabaseValue' on returned values`, async () => { + const user = await models.User.create({ name: 'foo' }); + user.name = 'bob'; + await user.save({ returning: true }); - expect(user.name).to.eq(null, 'parseDatabaseValue called on null value'); - expect(spies.parseDatabaseValue.called).to.eq( - false, - 'parseDatabaseValue should not have been called', - ); + expect(user.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); }); + + // TODO: add test for 'returning' on DELETE queries once https://github.com/sequelize/sequelize/pull/14879 has been merged + } + + it(`does not call 'parseDatabaseValue' on null values`, async () => { + const user = await models.User.create({ name: null }); + await user.reload(); + + expect(user.name).to.eq(null, 'parseDatabaseValue called on null value'); + expect(spies.parseDatabaseValue.called).to.eq( + false, + 'parseDatabaseValue should not have been called', + ); }); -} +}); diff --git a/packages/core/test/integration/dialects/oracle/data-types/methods.test.ts b/packages/core/test/integration/dialects/oracle/data-types/methods.test.ts deleted file mode 100644 index 29409f98fea8..000000000000 --- a/packages/core/test/integration/dialects/oracle/data-types/methods.test.ts +++ /dev/null @@ -1,213 +0,0 @@ -import type { - BelongsToManyAddAssociationMixin, - CreationOptional, - ForeignKey, - InferAttributes, - InferCreationAttributes, - NonAttribute, -} from '@sequelize/core'; -import { DataTypes, Model } from '@sequelize/core'; -import { expect } from 'chai'; -import sinon from 'sinon'; -import { beforeAll2, beforeEach2, sequelize, setResetMode } from '../../../support'; - -// This test suite ensures DataType methods are called at the appropriate time - -const dialect = sequelize.dialect; - -describe('DataType Methods', () => { - setResetMode('none'); - - const customValueSymbol = Symbol('dummy'); - - class CustomDataType extends DataTypes.STRING { - parseDatabaseValue(_value: unknown): any { - return customValueSymbol; - } - - _getBindDef(oracledb: any) { - return { type: oracledb.DB_TYPE_VARCHAR, maxSize: 255 }; - } - } - - const models = beforeAll2(async () => { - class User extends Model, InferCreationAttributes> { - declare id: CreationOptional; - declare name: string | null; - declare projects?: NonAttribute; - } - - User.init( - { - id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, - name: { type: CustomDataType, allowNull: true, field: 'first_name' }, - }, - { sequelize }, - ); - - class Project extends Model, InferCreationAttributes> { - declare name: string; - declare userId: ForeignKey; - declare stakeholders?: NonAttribute>; - - declare addStakeholder: BelongsToManyAddAssociationMixin; - } - - Project.init( - { - name: { type: CustomDataType, allowNull: false }, - }, - { sequelize }, - ); - - class ProjectStakeholder extends Model< - InferAttributes, - InferCreationAttributes - > { - declare key: string; - } - - ProjectStakeholder.init( - { - key: { type: CustomDataType, allowNull: false }, - }, - { sequelize, noPrimaryKey: true, timestamps: false }, - ); - - Project.belongsTo(User, { - as: 'user', - inverse: { as: 'projects', type: 'hasMany' }, - foreignKey: 'userId', - }); - - Project.belongsToMany(User, { - as: 'stakeholders', - inverse: 'stakeholdings', - through: ProjectStakeholder, - }); - - await User.sync({ force: true }); - await Project.sync({ force: true }); - await ProjectStakeholder.sync({ force: true }); - - const user1 = await User.create({ name: 'John' }); - const user2 = await User.create({ name: 'Stakeholder User' }); - const project = await Project.create({ name: 'Project 1', userId: user1.id }); - await project.addStakeholder(user2, { through: { key: 'dummy-value' } }); - - return { User, Project, ProjectStakeholder }; - }); - - const spies = beforeEach2(() => { - // add mocha spy to sanitize - return { - sanitize: sinon.spy(DataTypes.STRING.prototype, 'sanitize'), - validate: sinon.spy(DataTypes.STRING.prototype, 'validate'), - parseDatabaseValue: sinon.spy(CustomDataType.prototype, 'parseDatabaseValue'), - }; - }); - - afterEach(() => { - for (const spy of Object.values(spies)) { - spy.restore(); - } - }); - - it(`setting a value on a model only calls 'sanitize'`, () => { - models.User.build({ name: 'foo' }); - - expect(spies.sanitize.calledOnce).to.eq(true, 'sanitized not called exactly once'); - expect(spies.validate.called).to.eq(false, 'validate should not have been called'); - expect(spies.parseDatabaseValue.called).to.eq( - false, - 'parseDatabaseValue should not have been called', - ); - }); - - it(`retrieving a model only calls 'parseDatabaseValue' (no join)`, async () => { - const out = await models.User.findOne({ rejectOnEmpty: true }); - - expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue not called on top level model'); - - expect(spies.sanitize.called).to.eq(false, 'sanitize should not have been called'); - expect(spies.validate.called).to.eq(false, 'validate should not have been called'); - }); - - it(`retrieving a model only calls 'parseDatabaseValue' (with join)`, async () => { - // this test is separate from the no-join version because they use different code paths. - // We test both double nested associations & that through tables are handled correctly. - const out = await models.User.findOne({ - include: [ - { - association: 'projects', - include: ['stakeholders'], - }, - ], - rejectOnEmpty: true, - }); - - expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue not called on top level model'); - expect(out.projects![0].name).to.eq( - customValueSymbol, - 'parseDatabaseValue not called on first include level', - ); - expect(out.projects![0].stakeholders![0].name).to.eq( - customValueSymbol, - 'parseDatabaseValue not called on second include level', - ); - expect(out.projects![0].stakeholders![0].ProjectStakeholder.key).to.eq( - customValueSymbol, - 'parseDatabaseValue not called on Many-To-Many through table', - ); - - expect(spies.sanitize.called).to.eq(false, 'sanitize should not have been called'); - expect(spies.validate.called).to.eq(false, 'validate should not have been called'); - }); - - if (dialect.supports.returnValues) { - it(`inserting a model calls 'parseDatabaseValue' on returned values`, async () => { - // 'name' attr has a different name in the database - const out = await models.User.create({ name: 'foo' }, { returning: true }); - - expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); - - // sanitize is called when the user input is added to the model - expect(spies.sanitize.called).to.eq(true, 'sanitize should have been called'); - // validate is called before persisting the model - expect(spies.validate.called).to.eq(true, 'validate should have been called'); - }); - - it(`upserting a model calls 'parseDatabaseValue' on returned values`, async () => { - // 'name' attr has a different name in the database - const [out] = await models.User.upsert({ name: 'foo', id: 1234 }, { returning: true }); - - expect(out.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); - - // sanitize is called when the user input is added to the model - expect(spies.sanitize.called).to.eq(true, 'sanitize should have been called'); - // validate is called before persisting the model - expect(spies.validate.called).to.eq(true, 'validate should have been called'); - }); - } - - if (dialect.supports.returnValues === 'returning') { - it(`updating a model calls 'parseDatabaseValue' on returned values`, async () => { - const user = await models.User.create({ name: 'foo' }); - user.name = 'bob'; - await user.save({ returning: true }); - - expect(user.name).to.eq(customValueSymbol, 'parseDatabaseValue has not been called'); - }); - } - - it(`does not call 'parseDatabaseValue' on null values`, async () => { - const user = await models.User.create({ name: null }); - await user.reload(); - - expect(user.name).to.eq(null, 'parseDatabaseValue called on null value'); - expect(spies.parseDatabaseValue.called).to.eq( - false, - 'parseDatabaseValue should not have been called', - ); - }); -}); diff --git a/packages/core/test/integration/error.test.ts b/packages/core/test/integration/error.test.ts index c38e2d0ca264..e7784ddb56ae 100644 --- a/packages/core/test/integration/error.test.ts +++ b/packages/core/test/integration/error.test.ts @@ -492,7 +492,7 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { await expect(User.create({ name: 'jan' })).to.be.rejectedWith(UniqueConstraintError); // And when the model is not passed at all - if (['db2', 'ibmi', 'oracle'].includes(dialect)) { + if (['db2', 'ibmi'].includes(dialect)) { await expect( sequelize.query('INSERT INTO "users" ("name") VALUES (\'jan\')'), ).to.be.rejectedWith(UniqueConstraintError); @@ -550,7 +550,7 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { } catch (error) { expect(error).to.be.instanceOf(ValidationError); assert(error instanceof ValidationError); - if (dialect === 'db2' || dialect === 'oracle') { + if (dialect === 'db2') { expect(error.errors).to.have.length(0); } else { expect(error.errors).to.have.length(1); @@ -603,10 +603,6 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { expect(error.errors[0].message).to.equal('username must be unique'); break; - case 'oracle': - expect(error.cause.message).to.match(/ORA-00001: unique constraint \(.*\) violated/); - break; - default: expect(error.cause.message).to.contain("Duplicate entry 'foo' for key 'username'"); expect(error.errors[0].path).to.equal('username'); @@ -630,7 +626,7 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { } catch (error) { expect(error).to.be.instanceOf(ValidationError); assert(error instanceof ValidationError); - if (dialect === 'db2' || dialect === 'oracle') { + if (dialect === 'db2') { expect(error.errors).to.have.length(0); } else { expect(error.errors).to.have.length(1); @@ -679,12 +675,6 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { ); break; - case 'oracle': - expect(error.cause.message).to.match( - /ORA-00001: unique constraint \(.*.users_username_unique\) violated/, - ); - break; - default: expect(error.cause.message).to.contain( "Duplicate entry 'foo' for key 'users_username_unique'", @@ -721,7 +711,7 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { } catch (error) { expect(error).to.be.instanceOf(ForeignKeyConstraintError); assert(error instanceof ForeignKeyConstraintError); - if (dialect === 'sqlite3' || dialect === 'oracle') { + if (dialect === 'sqlite3') { expect(error.index).to.be.undefined; } else { expect(error.index).to.equal('Tasks_userId_Users_fk'); @@ -760,14 +750,6 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { ); break; - case 'oracle': - expect(error.table).to.be.undefined; - expect(error.fields).to.be.null; - expect(error.cause.message).to.match( - /ORA-02292: integrity constraint \(.*.Tasks_userId_Users_fk\) violated - child record found/, - ); - break; - default: expect(error.table).to.equal('Users'); expect(error.fields).to.deep.equal(['userId']); @@ -804,7 +786,7 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { } catch (error) { expect(error).to.be.instanceOf(ForeignKeyConstraintError); assert(error instanceof ForeignKeyConstraintError); - if (dialect === 'sqlite3' || dialect === 'oracle') { + if (dialect === 'sqlite3') { expect(error.index).to.be.undefined; } else { expect(error.index).to.equal('Tasks_userId_Users_fk'); @@ -843,14 +825,6 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { ); break; - case 'oracle': - expect(error.table).to.be.undefined; - expect(error.fields).to.be.null; - expect(error.cause.message).to.match( - /ORA-02291: integrity constraint \(.*.Tasks_userId_Users_fk\) violated - parent key not found/, - ); - break; - default: expect(error.table).to.equal('Users'); expect(error.fields).to.deep.equal(['userId']); @@ -893,10 +867,6 @@ describe(getTestDialectTeaser('Sequelize Errors'), () => { assert(error.errors[2] instanceof UnknownConstraintError); expect(error.errors[2].constraint).to.equal('unique_constraint'); expect(error.errors[2].table).to.equal('Users'); - } else if (dialect === 'oracle') { - expect(error).to.be.instanceOf(DatabaseError); - assert(error instanceof DatabaseError); - expect(error.message).to.match(/^ORA-02264: name already used by an existing constraint/); } else { expect(error).to.be.instanceOf(DatabaseError); assert(error instanceof DatabaseError); diff --git a/packages/core/test/integration/include.test.js b/packages/core/test/integration/include.test.js index 59c7b499f14e..842b211aac45 100644 --- a/packages/core/test/integration/include.test.js +++ b/packages/core/test/integration/include.test.js @@ -753,20 +753,6 @@ Instead of specifying a Model, either: break; } - case 'oracle': { - findAttributes = [ - Sequelize.literal( - '(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END) AS "postComments.someProperty"', - ), - [ - Sequelize.literal('(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END)'), - 'someProperty2', - ], - ]; - - break; - } - default: { findAttributes = [ Sequelize.literal('EXISTS(SELECT 1) AS "postComments.someProperty"'), diff --git a/packages/core/test/integration/include/findAll.test.js b/packages/core/test/integration/include/findAll.test.js index 5d39f0fbe4a8..d27bfee27d45 100644 --- a/packages/core/test/integration/include/findAll.test.js +++ b/packages/core/test/integration/include/findAll.test.js @@ -121,7 +121,7 @@ describe(Support.getTestDialectTeaser('Include'), () => { { title: 'Pen' }, { title: 'Monitor' }, ]); - const products = await Product.findAll({ order: [['id', 'ASC']] }); + const products = await Product.findAll(); const groupMembers = [ { groupId: groups[0].id, rankId: ranks[0].id }, { groupId: groups[1].id, rankId: ranks[2].id }, @@ -343,9 +343,7 @@ describe(Support.getTestDialectTeaser('Include'), () => { for (const i of [0, 1, 2, 3, 4]) { const [user, products] = await Promise.all([ User.create(), - Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => - Product.findAll({ order: [['id', 'ASC']] }), - ), + Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => Product.findAll()), ]); await Promise.all([ GroupMember.bulkCreate([ @@ -1176,7 +1174,7 @@ describe(Support.getTestDialectTeaser('Include'), () => { await Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]); - const products = await Product.findAll({ order: [['id', 'ASC']] }); + const products = await Product.findAll(); await Promise.all([ GroupMember.bulkCreate([ { userId: user.id, groupId: groups[0].id, rankId: ranks[0].id }, diff --git a/packages/core/test/integration/include/schema.test.js b/packages/core/test/integration/include/schema.test.js index a014d20e0596..c19b4335af3d 100644 --- a/packages/core/test/integration/include/schema.test.js +++ b/packages/core/test/integration/include/schema.test.js @@ -154,7 +154,7 @@ describe(Support.getTestDialectTeaser('Includes with schemas'), () => { { title: 'Bed' }, { title: 'Pen' }, { title: 'Monitor' }, - ]).then(() => Product.findAll({ order: [['id', 'ASC']] })), + ]).then(() => Product.findAll()), ]); const groupMembers = [ { accUserId: user.id, GroupId: groups[0].id, rankId: ranks[0].id }, @@ -273,9 +273,7 @@ describe(Support.getTestDialectTeaser('Includes with schemas'), () => { for (const i of [0, 1, 2, 3, 4]) { const [user, products] = await Promise.all([ AccUser.create(), - Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => - Product.findAll({ order: [['id', 'ASC']] }), - ), + Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => Product.findAll()), ]); await Promise.all([ GroupMember.bulkCreate([ @@ -956,9 +954,7 @@ describe(Support.getTestDialectTeaser('Includes with schemas'), () => { for (const i of [0, 1, 2, 3, 4]) { const [user, products] = await Promise.all([ User.create({ name: 'FooBarzz' }), - Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => - Product.findAll({ order: [['id', 'ASC']] }), - ), + Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => Product.findAll()), ]); await Promise.all([ GroupMember.bulkCreate([ diff --git a/packages/core/test/integration/instance/values.test.js b/packages/core/test/integration/instance/values.test.js index 1f089eb96217..e79930e0d244 100644 --- a/packages/core/test/integration/instance/values.test.js +++ b/packages/core/test/integration/instance/values.test.js @@ -111,9 +111,7 @@ describe(Support.getTestDialectTeaser('DAO'), () => { ? this.sequelize.fn('', this.sequelize.fn('datetime', 'now')) : dialect === 'mssql' ? this.sequelize.fn('', this.sequelize.fn('getdate')) - : dialect === 'oracle' - ? this.sequelize.fn('', this.sequelize.literal('SYSDATE')) - : this.sequelize.fn('NOW'); + : this.sequelize.fn('NOW'); user.set({ d: now, diff --git a/packages/core/test/integration/json.test.ts b/packages/core/test/integration/json.test.ts index 8317c5ac3f3a..f59f3034726d 100644 --- a/packages/core/test/integration/json.test.ts +++ b/packages/core/test/integration/json.test.ts @@ -57,25 +57,20 @@ describe('JSON Manipulation', () => { expect(user.jsonAttr).to.deep.equal({ name: 'larry' }); }); - (dialectName === 'oracle' ? it.skip : it)( - 'should be able to store strings that require escaping', - async () => { - const text = 'Multi-line \n \'$string\' needing "escaping" for $$ and $1 type values'; - - await vars.User.create({ jsonAttr: text }); - const user = await vars.User.findOne({ rejectOnEmpty: true }); - expect(user.jsonAttr).to.equal(text); - }, - ); + it('should be able to store strings that require escaping', async () => { + const text = 'Multi-line \n \'$string\' needing "escaping" for $$ and $1 type values'; + + await vars.User.create({ jsonAttr: text }); + const user = await vars.User.findOne({ rejectOnEmpty: true }); + expect(user.jsonAttr).to.equal(text); + }); }); const JSON_OBJECT = { name: 'swen', phones: [1337, 42] }; const JSON_STRING = 'kate'; -// Oracle database < 21 doesn't supports scalars to be treated as JSON -// thus fails with CHECk constraint violation errors describe('JSON Querying', () => { - if (!dialect.supports.dataTypes.JSON || dialect.name === 'oracle') { + if (!dialect.supports.dataTypes.JSON) { return; } diff --git a/packages/core/test/integration/model-repository/bulk-destroy.test.ts b/packages/core/test/integration/model-repository/bulk-destroy.test.ts index ba878c0f1953..fd97cb31e01f 100644 --- a/packages/core/test/integration/model-repository/bulk-destroy.test.ts +++ b/packages/core/test/integration/model-repository/bulk-destroy.test.ts @@ -116,16 +116,6 @@ describe('ModelRepository#_UNSTABLE_bulkDestroy', () => { ], { genericQuotes: true }, ), - oracle: toMatchSql([ - 'BEGIN TRANSACTION', - 'SELECT "id", "createdAt", "updatedAt" FROM "Users" "User" WHERE "User"."id" = 1;', - 'SELECT "id", "ownerId", "createdAt", "updatedAt" FROM "Projects" "Project" WHERE "Project"."ownerId" IN (1);', - 'SELECT "id", "projectId", "createdAt", "updatedAt" FROM "Tasks" "Task" WHERE "Task"."projectId" IN (1);', - 'DELETE FROM "Tasks" WHERE "id" = 1', - 'DELETE FROM "Projects" WHERE "id" = 1', - 'DELETE FROM "Users" WHERE "id" = 1', - 'COMMIT TRANSACTION', - ]), }); }); @@ -165,14 +155,6 @@ describe('ModelRepository#_UNSTABLE_bulkDestroy', () => { 'DELETE FROM [Projects] WHERE [id] = 1; SELECT @@ROWCOUNT AS AFFECTEDROWS;', 'DELETE FROM [Users] WHERE [id] = 1; SELECT @@ROWCOUNT AS AFFECTEDROWS;', ]), - oracle: toMatchSql([ - 'SELECT "id", "createdAt", "updatedAt" FROM "Users" "User" WHERE "User"."id" = 1;', - 'SELECT "id", "ownerId", "createdAt", "updatedAt" FROM "Projects" "Project" WHERE "Project"."ownerId" IN (1);', - 'SELECT "id", "projectId", "createdAt", "updatedAt" FROM "Tasks" "Task" WHERE "Task"."projectId" IN (1);', - 'DELETE FROM "Tasks" WHERE "id" = 1', - 'DELETE FROM "Projects" WHERE "id" = 1', - 'DELETE FROM "Users" WHERE "id" = 1', - ]), }); }); }); diff --git a/packages/core/test/integration/model-repository/destroy.test.ts b/packages/core/test/integration/model-repository/destroy.test.ts index 885c0cf46144..c800557bb72d 100644 --- a/packages/core/test/integration/model-repository/destroy.test.ts +++ b/packages/core/test/integration/model-repository/destroy.test.ts @@ -109,15 +109,6 @@ describe('ModelRepository#_UNSTABLE_destroy', () => { ], { genericQuotes: true }, ), - oracle: toMatchSql([ - 'BEGIN TRANSACTION', - 'SELECT "id", "ownerId", "createdAt", "updatedAt" FROM "Projects" "Project" WHERE "Project"."ownerId" IN (1);', - 'SELECT "id", "projectId", "createdAt", "updatedAt" FROM "Tasks" "Task" WHERE "Task"."projectId" IN (1);', - 'DELETE FROM "Tasks" WHERE "id" = 1', - 'DELETE FROM "Projects" WHERE "id" = 1', - 'DELETE FROM "Users" WHERE "id" = 1', - 'COMMIT TRANSACTION', - ]), }); }); @@ -153,13 +144,6 @@ describe('ModelRepository#_UNSTABLE_destroy', () => { 'DELETE FROM [Projects] WHERE [id] = 1; SELECT @@ROWCOUNT AS AFFECTEDROWS;', 'DELETE FROM [Users] WHERE [id] = 1; SELECT @@ROWCOUNT AS AFFECTEDROWS;', ]), - oracle: toMatchSql([ - 'SELECT "id", "ownerId", "createdAt", "updatedAt" FROM "Projects" "Project" WHERE "Project"."ownerId" IN (1);', - 'SELECT "id", "projectId", "createdAt", "updatedAt" FROM "Tasks" "Task" WHERE "Task"."projectId" IN (1);', - 'DELETE FROM "Tasks" WHERE "id" = 1', - 'DELETE FROM "Projects" WHERE "id" = 1', - 'DELETE FROM "Users" WHERE "id" = 1', - ]), }); }); }); diff --git a/packages/core/test/integration/model.test.js b/packages/core/test/integration/model.test.js index 2f7d58de63a6..6fee10188e18 100644 --- a/packages/core/test/integration/model.test.js +++ b/packages/core/test/integration/model.test.js @@ -286,7 +286,6 @@ describe(Support.getTestDialectTeaser('Model'), () => { } case 'db2': - case 'oracle': case 'mssql': { expect(index.fields).to.deep.equal([ { attribute: 'user_name', collate: undefined, length: undefined, order: 'ASC' }, @@ -552,28 +551,6 @@ describe(Support.getTestDialectTeaser('Model'), () => { break; } - case 'oracle': { - primary = args[0]; - idx1 = args[1]; - idx2 = args[2]; - idx3 = args[3]; - - expect(idx1.fields).to.deep.equal([ - { attribute: 'fieldB', length: undefined, order: 'ASC', collate: undefined }, - { attribute: 'fieldA', length: undefined, order: 'ASC', collate: undefined }, - ]); - - expect(idx2.fields).to.deep.equal([ - { attribute: 'fieldC', length: undefined, order: 'ASC', collate: undefined }, - ]); - - expect(idx3.fields).to.deep.equal([ - { attribute: 'fieldD', length: undefined, order: 'ASC', collate: undefined }, - ]); - - break; - } - case 'db2': { idx1 = args[1]; @@ -1035,9 +1012,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { if (dialectName === 'sqlite3' && sql.includes('TABLE_INFO')) { test++; expect(sql).to.not.contain('special'); - } else if ( - ['mysql', 'mssql', 'mariadb', 'db2', 'ibmi', 'oracle'].includes(dialectName) - ) { + } else if (['mysql', 'mssql', 'mariadb', 'db2', 'ibmi'].includes(dialectName)) { test++; expect(sql).to.not.contain('special'); } @@ -1056,9 +1031,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { if (dialectName === 'sqlite3' && sql.includes('TABLE_INFO')) { test++; expect(sql).to.contain('special'); - } else if ( - ['mysql', 'mssql', 'mariadb', 'db2', 'ibmi', 'oracle'].includes(dialectName) - ) { + } else if (['mysql', 'mssql', 'mariadb', 'db2', 'ibmi'].includes(dialectName)) { test++; expect(sql).to.contain('special'); } @@ -1107,8 +1080,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { switch (dialectName) { case 'postgres': case 'db2': - case 'ibmi': - case 'oracle': { + case 'ibmi': { expect(sql).to.match(/REFERENCES\s+"prefix"\."UserPubs" \("id"\)/); break; @@ -1155,8 +1127,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { switch (dialectName) { case 'postgres': case 'db2': - case 'ibmi': - case 'oracle': { + case 'ibmi': { expect(UserPublic).to.include('INSERT INTO "UserPublics"'); break; @@ -1188,8 +1159,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { switch (dialectName) { case 'postgres': case 'db2': - case 'ibmi': - case 'oracle': { + case 'ibmi': { expect(UserSpecial).to.include('INSERT INTO "special"."UserSpecials"'); break; @@ -1227,8 +1197,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { switch (dialectName) { case 'postgres': case 'db2': - case 'ibmi': - case 'oracle': { + case 'ibmi': { expect(user).to.include('UPDATE "special"."UserSpecials"'); break; @@ -1426,12 +1395,6 @@ describe(Support.getTestDialectTeaser('Model'), () => { break; } - case 'oracle': { - expect(error.message).to.match(/^ORA-00942:/); - - break; - } - case 'ibmi': { expect(error.message).to.match( /[a-zA-Z0-9[\] /-]+?"4uth0r5" in SEQUELIZE type \*FILE not found\./, diff --git a/packages/core/test/integration/model/attributes/field.test.js b/packages/core/test/integration/model/attributes/field.test.js index 39d680855e81..821f61d4b453 100644 --- a/packages/core/test/integration/model/attributes/field.test.js +++ b/packages/core/test/integration/model/attributes/field.test.js @@ -487,16 +487,6 @@ describe(Support.getTestDialectTeaser('Model'), () => { Sequelize.literal('1 AS "someProperty"'), [Sequelize.literal('1'), 'someProperty2'], ]; - } else if (dialect === 'oracle') { - findAttributes = [ - Sequelize.literal( - '(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END) AS "someProperty"', - ), - [ - Sequelize.literal('(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END)'), - 'someProperty2', - ], - ]; } else { findAttributes = [ Sequelize.literal('EXISTS(SELECT 1) AS "someProperty"'), diff --git a/packages/core/test/integration/model/attributes/types.test.js b/packages/core/test/integration/model/attributes/types.test.js index 1b041a32a6f5..91c445c95e58 100644 --- a/packages/core/test/integration/model/attributes/types.test.js +++ b/packages/core/test/integration/model/attributes/types.test.js @@ -112,8 +112,6 @@ describe(Support.getTestDialectTeaser('Model'), () => { 'CAST(CASE WHEN EXISTS(SELECT 1) THEN 1 ELSE 0 END AS BIT) AS "someBoolean"'; } else if (['db2', 'ibmi'].includes(dialect)) { boolQuery = '1 AS "someBoolean"'; - } else if (dialect === 'oracle') { - boolQuery = '(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END) AS "someBoolean"'; } const post = await Post.findOne({ diff --git a/packages/core/test/integration/model/bulk-create.test.js b/packages/core/test/integration/model/bulk-create.test.js index b2708e970050..d585e6fcc536 100644 --- a/packages/core/test/integration/model/bulk-create.test.js +++ b/packages/core/test/integration/model/bulk-create.test.js @@ -170,7 +170,6 @@ describe('Model', () => { logging(sql) { switch (dialectName) { case 'postgres': - case 'oracle': case 'ibmi': { expect(sql).to.include( 'INSERT INTO "Beers" ("id","style","createdAt","updatedAt") VALUES (DEFAULT', diff --git a/packages/core/test/integration/model/count.test.js b/packages/core/test/integration/model/count.test.js index b58073af119d..397312215800 100644 --- a/packages/core/test/integration/model/count.test.js +++ b/packages/core/test/integration/model/count.test.js @@ -55,12 +55,7 @@ describe('Model.count', () => { }); }); - if ( - dialectName !== 'mssql' && - dialectName !== 'db2' && - dialectName !== 'ibmi' && - dialectName !== 'oracle' - ) { + if (dialectName !== 'mssql' && dialectName !== 'db2' && dialectName !== 'ibmi') { describe('aggregate', () => { it('allows grouping by aliased attribute', async function () { await this.User.aggregate('id', 'count', { diff --git a/packages/core/test/integration/model/create.test.js b/packages/core/test/integration/model/create.test.js index b013c8e1ca16..fcf096815ca1 100644 --- a/packages/core/test/integration/model/create.test.js +++ b/packages/core/test/integration/model/create.test.js @@ -495,7 +495,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { } it('should not fail silently with concurrency higher than pool, a unique constraint and a create hook resulting in mismatched values', async function () { - if (['sqlite', 'mssql', 'db2', 'ibmi', 'oracle'].includes(dialectName)) { + if (['sqlite3', 'mssql', 'db2', 'ibmi'].includes(dialectName)) { return; } @@ -911,9 +911,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { ? '$sequelize_1' : dialectName === 'mssql' ? '@sequelize_1' - : dialectName === 'oracle' - ? ':1' - : '?'; + : '?'; let match = false; const user = await this.User.create( diff --git a/packages/core/test/integration/model/findAll.test.js b/packages/core/test/integration/model/findAll.test.js index 0ee161355a1b..e3a0d4f1e914 100644 --- a/packages/core/test/integration/model/findAll.test.js +++ b/packages/core/test/integration/model/findAll.test.js @@ -26,9 +26,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { intVal: DataTypes.INTEGER, theDate: DataTypes.DATE, aBool: DataTypes.BOOLEAN, - ...(dialectName === 'oracle' - ? { binary: DataTypes.STRING(16, true) } - : { binary: DataTypes.BLOB }), + binary: DataTypes.BLOB, }); await this.User.sync({ force: true }); @@ -119,7 +117,6 @@ describe(Support.getTestDialectTeaser('Model'), () => { }); }); - // Oracle WHERE IN clause for BLOB isn't supported. Use `RAW` datatype. it('should not break when using smart syntax on binary fields', async function () { const users = await this.User.findAll({ where: { diff --git a/packages/core/test/integration/model/findAll/order.test.js b/packages/core/test/integration/model/findAll/order.test.js index c70a23bdb913..ca52996eca7e 100644 --- a/packages/core/test/integration/model/findAll/order.test.js +++ b/packages/core/test/integration/model/findAll/order.test.js @@ -24,7 +24,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { }); }); - if (!['oracle', 'ibmi', 'mssql'].includes(current.dialect.name)) { + if (current.dialect.name !== 'mssql' && current.dialect.name !== 'ibmi') { const email = current.dialect.name === 'db2' ? '"email"' : 'email'; it('should work with order: literal()', async function () { const users = await this.User.findAll({ @@ -96,7 +96,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { } it('should not throw on a literal', async function () { - if (['db2', 'ibmi', 'oracle'].includes(current.dialect.name)) { + if (['db2', 'ibmi'].includes(current.dialect.name)) { await this.User.findAll({ order: [['id', this.sequelize.literal('ASC, "name" DESC')]], }); diff --git a/packages/core/test/integration/model/paranoid.test.js b/packages/core/test/integration/model/paranoid.test.js index 2e734f4bf89f..b8070ba29f77 100644 --- a/packages/core/test/integration/model/paranoid.test.js +++ b/packages/core/test/integration/model/paranoid.test.js @@ -124,44 +124,40 @@ describe('Paranoid Model', () => { await this.Model.sync({ force: true }); }); - // Oracle stores JSON as BLOB. where condition with equality isn't supported for this. - (dialectName === 'oracle' ? it.skip : it)( - 'should soft delete with JSON condition', - async function () { - await this.Model.bulkCreate([ - { - name: 'One', - data: { - field: { - deep: true, - }, + it('should soft delete with JSON condition', async function () { + await this.Model.bulkCreate([ + { + name: 'One', + data: { + field: { + deep: true, }, }, - { - name: 'Two', - data: { - field: { - deep: false, - }, + }, + { + name: 'Two', + data: { + field: { + deep: false, }, }, - ]); - - await this.Model.destroy({ - where: { - data: { - field: { - deep: true, - }, + }, + ]); + + await this.Model.destroy({ + where: { + data: { + field: { + deep: true, }, }, - }); + }, + }); - const records = await this.Model.findAll(); - expect(records.length).to.equal(1); - expect(records[0].get('name')).to.equal('Two'); - }, - ); + const records = await this.Model.findAll(); + expect(records.length).to.equal(1); + expect(records[0].get('name')).to.equal('Two'); + }); }); } diff --git a/packages/core/test/integration/model/update.test.ts b/packages/core/test/integration/model/update.test.ts index a500e47893c2..af6a523923b8 100644 --- a/packages/core/test/integration/model/update.test.ts +++ b/packages/core/test/integration/model/update.test.ts @@ -457,7 +457,6 @@ describe('Model.update', () => { mssql: `UPDATE [users1] SET [secretValue]=@sequelize_1,[updatedAt]=@sequelize_2 OUTPUT INSERTED.* WHERE [id] = @sequelize_3`, db2: `SELECT * FROM FINAL TABLE (UPDATE "users1" SET "secretValue"=?,"updatedAt"=? WHERE "id" = ?);`, ibmi: `UPDATE "users1" SET "secretValue"=?,"updatedAt"=? WHERE "id" = ?;`, - oracle: `UPDATE "users1" SET "secretValue"=:1,"updatedAt"=:2 WHERE "id" = :3`, }); }, returning: [sql.col('*')], diff --git a/packages/core/test/integration/pool.test.ts b/packages/core/test/integration/pool.test.ts index 57abb9e2ae79..58894933e8d1 100644 --- a/packages/core/test/integration/pool.test.ts +++ b/packages/core/test/integration/pool.test.ts @@ -41,10 +41,6 @@ function assertSameConnection( expect(newConnection.dummyId).to.equal(oldConnection.dummyId).and.to.be.ok; break; - case 'oracle': - expect(oldConnection).to.be.equal(newConnection); - break; - default: throw new Error('Unsupported dialect'); } @@ -79,10 +75,6 @@ function assertNewConnection(newConnection: AbstractConnection, oldConnection: A expect(oldConnection.dummyId).to.be.ok; break; - case 'oracle': - expect(oldConnection).to.not.be.equal(newConnection); - break; - default: throw new Error('Unsupported dialect'); } diff --git a/packages/core/test/integration/query-interface/add-show-remove-constraint.test.ts b/packages/core/test/integration/query-interface/add-show-remove-constraint.test.ts index 0cc6d0f0cee2..462936ebc806 100644 --- a/packages/core/test/integration/query-interface/add-show-remove-constraint.test.ts +++ b/packages/core/test/integration/query-interface/add-show-remove-constraint.test.ts @@ -78,8 +78,6 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { 'Expected error to be an instance of AggregateError', ); err = error.errors.at(-1); - } else if (dialect === 'oracle') { - expect(error).to.be.instanceOf(UnknownConstraintError); } else { assert( err instanceof UnknownConstraintError, @@ -114,13 +112,14 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: 'custom_constraint_name', constraintType: 'UNIQUE', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - ...(dialect !== 'oracle' && { tableSchema: defaultSchema }), + tableSchema: defaultSchema, tableName: 'actors', - columnNames: dialect === 'oracle' ? ['age', 'name'] : ['name', 'age'], + columnNames: ['name', 'age'], ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), }); + await queryInterface.removeConstraint('actors', 'custom_constraint_name'); const constraintsAfterRemove = await queryInterface.showConstraints('actors', { constraintName: 'custom_constraint_name', @@ -157,17 +156,14 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: 'custom_constraint_name', constraintType: 'FOREIGN KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - ...(dialect !== 'oracle' && { tableSchema: defaultSchema }), + tableSchema: defaultSchema, tableName: 'actors', columnNames: ['level_id'], referencedTableName: 'levels', referencedTableSchema: defaultSchema, referencedColumnNames: ['id'], deleteAction: 'CASCADE', - ...(dialect !== 'oracle' && { - updateAction: - dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', - }), + updateAction: dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), @@ -190,7 +186,7 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: ['mariadb', 'mysql'].includes(dialect) ? 'PRIMARY' : 'pk_levels', constraintType: 'PRIMARY KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - ...(dialect !== 'oracle' && { tableSchema: defaultSchema }), + tableSchema: defaultSchema, tableName: 'levels', columnNames: ['id'], ...(sequelize.dialect.supports.constraints.deferrable && { @@ -236,17 +232,14 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: 'custom_constraint_name', constraintType: 'FOREIGN KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - ...(dialect !== 'oracle' && { tableSchema: defaultSchema }), + tableSchema: defaultSchema, tableName: 'actors', columnNames: ['level_id', 'manager_id'], referencedTableSchema: defaultSchema, referencedTableName: 'levels', referencedColumnNames: ['id', 'manager_id'], deleteAction: 'CASCADE', - ...(dialect !== 'oracle' && { - updateAction: - dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', - }), + updateAction: dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), @@ -268,9 +261,9 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: ['mariadb', 'mysql'].includes(dialect) ? 'PRIMARY' : 'pk_levels', constraintType: 'PRIMARY KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - ...(dialect !== 'oracle' && { tableSchema: defaultSchema }), + tableSchema: defaultSchema, tableName: 'levels', - columnNames: dialect === 'oracle' ? ['manager_id', 'id'] : ['id', 'manager_id'], + columnNames: ['id', 'manager_id'], ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), @@ -303,7 +296,7 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { field: 'id', }, onDelete: 'CASCADE', - onUpdate: dialect !== 'oracle' ? 'CASCADE' : undefined, + onUpdate: 'CASCADE', }); const constraintType = await queryInterface.showConstraints('actors', { @@ -351,7 +344,7 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { const constraintType = await queryInterface.showConstraints('actors', { constraintType: 'CHECK', }); - if (dialect === 'postgres' || dialect === 'oracle') { + if (dialect === 'postgres') { // Postgres adds a CHECK constraint for each column with not null expect(constraintType).to.have.length(6); expect(constraintType[5].constraintType).to.equal('CHECK'); @@ -367,24 +360,21 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { expect(constraints[0]).to.deep.equal({ ...(['mssql', 'postgres'].includes(dialect) && { constraintCatalog: 'sequelize_test' }), constraintSchema: defaultSchema, - ...(['oracle'].includes(dialect) && { columnNames: ['age'] }), constraintName: 'custom_constraint_name', constraintType: 'CHECK', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - ...(dialect !== 'oracle' && { tableSchema: defaultSchema }), + tableSchema: defaultSchema, tableName: 'actors', - ...(dialect !== 'oracle' && { - definition: - dialect === 'mssql' - ? '([age]>(10))' - : dialect === 'db2' - ? '"age" > 10' - : dialect === 'postgres' - ? '((age > 10))' - : ['mysql', 'sqlite3'].includes(dialect) - ? '(`age` > 10)' - : '`age` > 10', - }), + definition: + dialect === 'mssql' + ? '([age]>(10))' + : dialect === 'db2' + ? '"age" > 10' + : dialect === 'postgres' + ? '((age > 10))' + : ['mysql', 'sqlite3'].includes(dialect) + ? '(`age` > 10)' + : '`age` > 10', ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), @@ -536,17 +526,15 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: 'custom_constraint_name', constraintType: 'FOREIGN KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - ...(dialect !== 'oracle' && { tableSchema: schema }), + tableSchema: schema, tableName: 'actors', columnNames: ['level_id'], referencedTableSchema: schema, referencedTableName: 'levels', referencedColumnNames: ['id'], deleteAction: 'CASCADE', - ...(dialect !== 'oracle' && { - updateAction: - dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', - }), + updateAction: + dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), @@ -573,7 +561,7 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: ['mariadb', 'mysql'].includes(dialect) ? 'PRIMARY' : 'pk_levels', constraintType: 'PRIMARY KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - ...(dialect !== 'oracle' && { tableSchema: schema }), + tableSchema: schema, tableName: 'levels', columnNames: ['id'], ...(sequelize.dialect.supports.constraints.deferrable && { @@ -659,17 +647,15 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: 'custom_constraint_name', constraintType: 'FOREIGN KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - ...(dialect !== 'oracle' && { tableSchema: schema }), + tableSchema: schema, tableName: 'actors', columnNames: ['level_id'], referencedTableSchema: schema, referencedTableName: 'levels', referencedColumnNames: ['id'], deleteAction: 'CASCADE', - ...(dialect !== 'oracle' && { - updateAction: - dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', - }), + updateAction: + dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), @@ -689,17 +675,15 @@ describe('QueryInterface#{add,show,removeConstraint}', () => { constraintName: 'custom_constraint_name', constraintType: 'FOREIGN KEY', ...(['mssql', 'postgres'].includes(dialect) && { tableCatalog: 'sequelize_test' }), - ...(dialect !== 'oracle' && { tableSchema: sequelize.dialect.getDefaultSchema() }), + tableSchema: sequelize.dialect.getDefaultSchema(), tableName: 'actors', columnNames: ['level_id'], referencedTableSchema: sequelize.dialect.getDefaultSchema(), referencedTableName: 'levels', referencedColumnNames: ['id'], deleteAction: 'CASCADE', - ...(dialect !== 'oracle' && { - updateAction: - dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', - }), + updateAction: + dialect === 'mariadb' ? 'RESTRICT' : dialect === 'sqlite3' ? '' : 'NO ACTION', ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), diff --git a/packages/core/test/integration/query-interface/changeColumn.test.js b/packages/core/test/integration/query-interface/changeColumn.test.js index ccdf90198296..eab6d6279758 100644 --- a/packages/core/test/integration/query-interface/changeColumn.test.js +++ b/packages/core/test/integration/query-interface/changeColumn.test.js @@ -51,8 +51,6 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { if (['postgres', 'postgres-native', 'mssql', 'db2'].includes(dialect)) { expect(table.currency.type).to.equal('REAL'); - } else if (dialect === 'oracle') { - expect(table.currency.type).to.equal('BINARY_FLOAT'); } else { expect(table.currency.type).to.equal('FLOAT'); } @@ -91,8 +89,6 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { if (['postgres', 'postgres-native', 'mssql', 'sqlite3', 'db2'].includes(dialect)) { expect(table.currency.type).to.equal('REAL'); - } else if (dialect === 'oracle') { - expect(table.currency.type).to.equal('BINARY_FLOAT'); } else { expect(table.currency.type).to.equal('FLOAT'); } @@ -255,7 +251,7 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { expect(describedTable.level_id.allowNull).to.equal(true); }); - if (!['db2', 'ibmi', 'sqlite3', 'oracle'].includes(dialect)) { + if (!['db2', 'ibmi', 'sqlite3'].includes(dialect)) { it('should change the comment of column', async function () { const describedTable = await this.queryInterface.describeTable({ tableName: 'users', diff --git a/packages/core/test/integration/query-interface/describeTable.test.js b/packages/core/test/integration/query-interface/describeTable.test.js index 0722056ce413..ac8e4036f5ec 100644 --- a/packages/core/test/integration/query-interface/describeTable.test.js +++ b/packages/core/test/integration/query-interface/describeTable.test.js @@ -117,9 +117,6 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { case 'db2': assertVal = 'VARCHAR'; break; - case 'oracle': - assertVal = 'NVARCHAR2'; - break; } expect(username.type).to.equal(assertVal); @@ -127,7 +124,6 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { switch (dialect) { case 'sqlite3': - case 'oracle': expect(username.defaultValue).to.be.undefined; break; default: @@ -155,16 +151,12 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { case 'ibmi': assertVal = 'SMALLINT'; break; - case 'oracle': - assertVal = 'CHAR'; - break; } expect(isAdmin.type).to.equal(assertVal); expect(isAdmin.allowNull).to.be.true; switch (dialect) { case 'sqlite3': - case 'oracle': expect(isAdmin.defaultValue).to.be.undefined; break; default: @@ -176,8 +168,6 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { expect(enumVals.special).to.have.length(2); } else if (dialect === 'mysql') { expect(enumVals.type).to.eql("ENUM('hello','world')"); - } else if (dialect === 'oracle') { - expect(enumVals.type).to.eql('VARCHAR2'); } if (['postgres', 'mysql', 'mssql'].includes(dialect)) { diff --git a/packages/core/test/integration/query-interface/list-tables.test.ts b/packages/core/test/integration/query-interface/list-tables.test.ts index 162b5557f922..aa1ecf9e8f43 100644 --- a/packages/core/test/integration/query-interface/list-tables.test.ts +++ b/packages/core/test/integration/query-interface/list-tables.test.ts @@ -33,36 +33,14 @@ describe('QueryInterface#listTables', () => { throw error; } } - } else if (dialectName === 'oracle') { - const plsql = [ - 'BEGIN', - 'EXECUTE IMMEDIATE', - "'DROP VIEW V_Fail';", - 'EXCEPTION WHEN OTHERS THEN', - ' IF SQLCODE != -942 THEN', - ' RAISE;', - ' END IF;', - 'END;', - ].join(' '); - await sequelize.query(plsql); } else { await sequelize.queryRaw('DROP VIEW IF EXISTS V_Fail;'); } } - const fromQuery = () => { - if (['db2', 'ibmi'].includes(dialectName)) { - return 'FROM SYSIBM.SYSDUMMY1'; - } else if (dialectName === 'oracle') { - return 'FROM DUAL'; - } - - return ''; - }; - await queryInterface.createTable('my_test_table', { name: DataTypes.STRING }); await cleanup(); - const sql = `CREATE VIEW V_Fail AS SELECT 1 Id ${fromQuery()};`; + const sql = `CREATE VIEW V_Fail AS SELECT 1 Id${['db2', 'ibmi'].includes(dialectName) ? ' FROM SYSIBM.SYSDUMMY1' : ''};`; await sequelize.queryRaw(sql); const allTables = await queryInterface.listTables(); const tableNames = allTables.map(v => v.tableName); diff --git a/packages/core/test/integration/query-interface/remove-column.test.ts b/packages/core/test/integration/query-interface/remove-column.test.ts index fe74622c583a..e578ad502c80 100644 --- a/packages/core/test/integration/query-interface/remove-column.test.ts +++ b/packages/core/test/integration/query-interface/remove-column.test.ts @@ -214,17 +214,15 @@ describe(getTestDialectTeaser('QueryInterface#removeColumn'), () => { constraintName: dialectName === 'sqlite3' ? 'FOREIGN' : 'actors_level_id_fkey', constraintType: 'FOREIGN KEY', ...(['mssql', 'postgres'].includes(dialectName) && { tableCatalog: 'sequelize_test' }), - ...(dialectName !== 'oracle' && { tableSchema: defaultSchema }), + tableSchema: defaultSchema, tableName: 'actors', columnNames: ['level_id'], referencedTableName: 'level', referencedTableSchema: defaultSchema, referencedColumnNames: ['id'], deleteAction: 'CASCADE', - ...(dialectName !== 'oracle' && { - updateAction: - dialectName === 'mariadb' ? 'RESTRICT' : dialectName === 'sqlite3' ? '' : 'NO ACTION', - }), + updateAction: + dialectName === 'mariadb' ? 'RESTRICT' : dialectName === 'sqlite3' ? '' : 'NO ACTION', ...(sequelize.dialect.supports.constraints.deferrable && { deferrable: 'INITIALLY_IMMEDIATE', }), diff --git a/packages/core/test/integration/query-interface/schemas.test.ts b/packages/core/test/integration/query-interface/schemas.test.ts index 5567d27dc154..a172ed1fd931 100644 --- a/packages/core/test/integration/query-interface/schemas.test.ts +++ b/packages/core/test/integration/query-interface/schemas.test.ts @@ -179,16 +179,13 @@ describe('QueryInterface#{create,drop,list}Schema', () => { expect(postDeletionSchemas).to.not.include(testSchema, 'dropSchema did not drop testSchema'); }); - // For Oracle Database, users are considered as schema. listSchemas() doesn't allow to fetch the - // defaultSchema. it('shows all schemas', async () => { await queryInterface.createSchema(testSchema); const allSchemas = await queryInterface.listSchemas(); - const expected = - !dialect.supports.multiDatabases && dialect.name !== 'oracle' - ? [sequelize.dialect.getDefaultSchema(), testSchema] - : [testSchema]; + const expected = !dialect.supports.multiDatabases + ? [sequelize.dialect.getDefaultSchema(), testSchema] + : [testSchema]; expect(allSchemas.sort()).to.deep.eq(expected.sort(basicComparator())); }); diff --git a/packages/core/test/integration/sequelize.test.js b/packages/core/test/integration/sequelize.test.js index 699dabfa2968..3cf3982e7c1f 100644 --- a/packages/core/test/integration/sequelize.test.js +++ b/packages/core/test/integration/sequelize.test.js @@ -21,7 +21,7 @@ const { CONFIG } = require('../config/config'); const dialect = getTestDialect(); const qq = str => { - if (['postgres', 'mssql', 'db2', 'ibmi', 'oracle'].includes(dialect)) { + if (['postgres', 'mssql', 'db2', 'ibmi'].includes(dialect)) { return `"${str}"`; } @@ -61,9 +61,6 @@ const badUsernameConfig = { snowflake: { account: 'bad_account', }, - oracle: { - username: 'bad_user', - }, }; const noPasswordConfig = { @@ -95,9 +92,6 @@ const noPasswordConfig = { snowflake: { password: null, }, - oracle: { - password: null, - }, }; const badAddressConfig = { @@ -123,9 +117,6 @@ const badAddressConfig = { ibmi: { system: 'bad-address', }, - oracle: { - port: 9999, - }, }; describe(getTestDialectTeaser('Sequelize'), () => { @@ -393,12 +384,6 @@ describe(getTestDialectTeaser('Sequelize'), () => { break; } - case 'oracle': { - expect(error.message).to.include('NJS-007'); - - break; - } - case 'ibmi': { expect(error.message).to.equal('[odbc] Error connecting to the database'); expect(error.cause.odbcErrors[0].message).to.include( diff --git a/packages/core/test/integration/sequelize/query.test.js b/packages/core/test/integration/sequelize/query.test.js index a5db0bcd23d3..00357119657a 100644 --- a/packages/core/test/integration/sequelize/query.test.js +++ b/packages/core/test/integration/sequelize/query.test.js @@ -26,7 +26,7 @@ const dialectName = getTestDialect(); const queryGenerator = sequelize.queryGenerator; const qq = str => { - if (['postgres', 'mssql', 'db2', 'ibmi', 'oracle'].includes(dialectName)) { + if (['postgres', 'mssql', 'db2', 'ibmi'].includes(dialectName)) { return `"${str}"`; } @@ -37,25 +37,6 @@ const qq = str => { return str; }; -const fromQuery = () => { - let query = ''; - if (dialectName === 'oracle') { - query += ' FROM DUAL'; - } else if (dialectName === 'ibmi') { - query += ' FROM SYSIBM.SYSDUMMY1'; - } - - return query; -}; - -const dateLiteral = str => { - if (dialectName === 'oracle') { - return `to_date('${str}','YYYY-MM-DD HH24:MI:SS')`; - } - - return `'${str}'`; -}; - describe(getTestDialectTeaser('Sequelize'), () => { allowDeprecationsInSuite(['SEQUELIZE0023']); @@ -76,11 +57,11 @@ describe(getTestDialectTeaser('Sequelize'), () => { }, }); - this.insertQuery = `INSERT INTO ${qq(this.User.tableName)} (${qq('username')}, ${qq('email_address')}, ${qq( + this.insertQuery = `INSERT INTO ${qq(this.User.tableName)} (username, email_address, ${qq( 'createdAt', )}, ${qq( 'updatedAt', - )}) VALUES ('john', 'john@gmail.com', ${dateLiteral('2012-01-01 10:10:10')}, ${dateLiteral('2012-01-01 10:10:10')})`; + )}) VALUES ('john', 'john@gmail.com', '2012-01-01 10:10:10', '2012-01-01 10:10:10')`; if (['db2', 'ibmi'].includes(dialectName)) { this.insertQuery = `INSERT INTO ${qq(this.User.tableName)} ("username", "email_address", ${qq('createdAt')}, ${qq('updatedAt')}) VALUES ('john', 'john@gmail.com', '2012-01-01 10:10:10', '2012-01-01 10:10:10')`; @@ -119,10 +100,8 @@ describe(getTestDialectTeaser('Sequelize'), () => { it('properly bind parameters on extra retries', async function () { const payload = { username: 'test', - createdAt: - dialectName === 'oracle' ? new Date('2010-10-10 00:00:00') : '2010-10-10 00:00:00', - updatedAt: - dialectName === 'oracle' ? new Date('2010-10-10 00:00:00') : '2010-10-10 00:00:00', + createdAt: '2010-10-10 00:00:00', + updatedAt: '2010-10-10 00:00:00', }; const spy = sinon.spy(); @@ -156,7 +135,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { benchmark: true, }); - await sequelize.query(`select 1${fromQuery()};`); + await sequelize.query(`select 1${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''};`); expect(logger.calledOnce).to.be.true; expect(logger.args[0][0]).to.be.match(/Executed \((\d*|default)\): select 1/); expect(typeof logger.args[0][1] === 'number').to.be.true; @@ -165,10 +144,13 @@ describe(getTestDialectTeaser('Sequelize'), () => { it('executes a query with benchmarking option and custom logger', async function () { const logger = sinon.spy(); - await this.sequelize.query(`select 1${fromQuery()};`, { - logging: logger, - benchmark: true, - }); + await this.sequelize.query( + `select 1${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''};`, + { + logging: logger, + benchmark: true, + }, + ); expect(logger.calledOnce).to.be.true; expect(logger.args[0][0]).to.be.match(/Executed \(\d*|default\): select 1;/); @@ -181,9 +163,12 @@ describe(getTestDialectTeaser('Sequelize'), () => { logging: logger, }); - await sequelize.query(`select 1${fromQuery()};`, { - queryLabel: 'tricky select', - }); + await sequelize.query( + `select 1${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''};`, + { + queryLabel: 'tricky select', + }, + ); expect(logger.calledOnce).to.be.true; expect(logger.args[0][0]).to.be.match( /^tricky select[\n]Executing \((\d*|default)\): select 1/, @@ -196,9 +181,12 @@ describe(getTestDialectTeaser('Sequelize'), () => { logging: logger, }); - await sequelize.query(`select 1${fromQuery()};`, { - queryLabel: '', - }); + await sequelize.query( + `select 1${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''};`, + { + queryLabel: '', + }, + ); expect(logger.calledOnce).to.be.true; expect(logger.args[0][0]).to.be.match(/^Executing \((\d*|default)\): select 1/); }); @@ -210,9 +198,12 @@ describe(getTestDialectTeaser('Sequelize'), () => { benchmark: true, }); - await sequelize.query(`select 1${fromQuery()};`, { - queryLabel: 'tricky select', - }); + await sequelize.query( + `select 1${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''};`, + { + queryLabel: 'tricky select', + }, + ); expect(logger.calledOnce).to.be.true; expect(logger.args[0][0]).to.be.match( /^tricky select[\n]Executed \((\d*|default)\): select 1/, @@ -315,7 +306,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { } await vars.sequelize.query( - `select $1${typeCast} as foo, $2${typeCast} as bar${fromQuery()}`, + `select $1${typeCast} as foo, $2${typeCast} as bar${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, { bind: ['foo', 'bar'], logging: s => { @@ -527,7 +518,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { it('emits full stacktraces for unique constraint error', async function () { let query; - if (['db2', 'ibmi', 'oracle'].includes(dialectName)) { + if (['db2', 'ibmi'].includes(dialectName)) { query = `INSERT INTO ${qq(this.User.tableName)} ("username", "email_address", ${qq( 'createdAt', )}, ${qq( @@ -551,19 +542,15 @@ describe(getTestDialectTeaser('Sequelize'), () => { error = error_; } - if (dialectName === 'oracle') { - expect(error).to.be.instanceOf(DatabaseError); - } else { - expect(error).to.be.instanceOf(UniqueConstraintError); - expect(error.stack).to.contain('query.test'); - } + expect(error).to.be.instanceOf(UniqueConstraintError); + expect(error.stack).to.contain('query.test'); }); it('emits full stacktraces for constraint validation error', async function () { let error = null; try { let query; - if (['db2', 'ibmi', 'oracle'].includes(dialectName)) { + if (['db2', 'ibmi'].includes(dialectName)) { query = `INSERT INTO ${qq(this.UserVisit.tableName)} ("user_id", "visited_at", ${qq( 'createdAt', )}, ${qq( @@ -582,12 +569,8 @@ describe(getTestDialectTeaser('Sequelize'), () => { error = error_; } - if (dialectName === 'oracle') { - expect(error).to.be.instanceOf(DatabaseError); - } else { - expect(error).to.be.instanceOf(ForeignKeyConstraintError); - expect(error.stack).to.contain('query.test'); - } + expect(error).to.be.instanceOf(ForeignKeyConstraintError); + expect(error.stack).to.contain('query.test'); }); }); } @@ -764,14 +747,14 @@ describe(getTestDialectTeaser('Sequelize'), () => { // dialects in which the following values will be returned as bigints instead of ints const isBigInt = dialectName === 'mysql'; it('dot separated attributes when doing a raw query without nest', async function () { - const sql = `select 1 as ${queryGenerator.quoteIdentifier('foo.bar.baz')}${fromQuery()}`; + const sql = `select 1 as ${queryGenerator.quoteIdentifier('foo.bar.baz')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`; const results = await this.sequelize.query(sql, { raw: true, nest: false }); expect(results[0]).to.deep.equal([{ 'foo.bar.baz': isBigInt ? '1' : 1 }]); }); it('destructs dot separated attributes when doing a raw query using nest', async function () { - const sql = `select 1 as ${queryGenerator.quoteIdentifier('foo.bar.baz')}${fromQuery()}`; + const sql = `select 1 as ${queryGenerator.quoteIdentifier('foo.bar.baz')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`; const result = await this.sequelize.query(sql, { raw: true, nest: true }); expect(result).to.deep.equal([{ foo: { bar: { baz: isBigInt ? '1' : 1 } } }]); @@ -780,7 +763,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { it('replaces token with the passed array', async function () { const expected = [{ foo: isBigInt ? '1' : 1, bar: isBigInt ? '2' : 2 }]; const result = await this.sequelize.query( - `select ? as ${queryGenerator.quoteIdentifier('foo')}, ? as ${queryGenerator.quoteIdentifier('bar')}${fromQuery()}`, + `select ? as ${queryGenerator.quoteIdentifier('foo')}, ? as ${queryGenerator.quoteIdentifier('bar')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, { type: this.sequelize.QueryTypes.SELECT, replacements: [1, 2] }, ); expect(result).to.deep.equal(expected); @@ -791,7 +774,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { await expect( this.sequelize .query( - `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}${fromQuery()}`, + `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, { raw: true, replacements: { one: 1, two: 2 } }, ) .then(obj => obj[0]), @@ -803,7 +786,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { await expect( this.sequelize .query( - `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}, '00:00' as ${queryGenerator.quoteIdentifier('baz')}${fromQuery()}`, + `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}, '00:00' as ${queryGenerator.quoteIdentifier('baz')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, { raw: true, replacements: { one: 1, two: 2 } }, ) .then(obj => obj[0]), @@ -817,7 +800,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { await expect( this.sequelize .query( - `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}, :one as ${queryGenerator.quoteIdentifier('baz')}${fromQuery()}`, + `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}, :one as ${queryGenerator.quoteIdentifier('baz')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, { raw: true, replacements: { one: 1, two: 2 } }, ) .then(obj => obj[0]), @@ -829,7 +812,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { await expect( this.sequelize .query( - `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}${fromQuery()}`, + `select :one as ${queryGenerator.quoteIdentifier('foo')}, :two as ${queryGenerator.quoteIdentifier('bar')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, { raw: true, replacements: { one: 1, two: null } }, ) .then(obj => obj[0]), @@ -845,7 +828,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { const typeCast = ['postgres', 'db2'].includes(dialectName) ? '::int' : ''; let logSql; const result = await this.sequelize.query( - `select $1${typeCast} as ${queryGenerator.quoteIdentifier('foo')}, $2${typeCast} as ${queryGenerator.quoteIdentifier('bar')}${fromQuery()}`, + `select $1${typeCast} as ${queryGenerator.quoteIdentifier('foo')}, $2${typeCast} as ${queryGenerator.quoteIdentifier('bar')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, { type: this.sequelize.QueryTypes.SELECT, bind: [1, 2], @@ -866,7 +849,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { const typeCast = ['postgres', 'db2'].includes(dialectName) ? '::int' : ''; let logSql; const result = await this.sequelize.query( - `select $one${typeCast} as ${queryGenerator.quoteIdentifier('foo')}, $two${typeCast} as ${queryGenerator.quoteIdentifier('bar')}${fromQuery()}`, + `select $one${typeCast} as ${queryGenerator.quoteIdentifier('foo')}, $two${typeCast} as ${queryGenerator.quoteIdentifier('bar')}${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, { raw: true, bind: { one: 1, two: 2 }, @@ -885,12 +868,12 @@ describe(getTestDialectTeaser('Sequelize'), () => { } }); - if (!['db2', 'oracle'].includes(dialectName)) { + if (dialectName !== 'db2') { it('binds named parameters with the passed object using the same key twice', async function () { const typeCast = dialectName === 'postgres' ? '::int' : ''; let logSql; const result = await this.sequelize.query( - `select $one${typeCast} as foo, $two${typeCast} as bar, $one${typeCast} as baz${fromQuery()}`, + `select $one${typeCast} as foo, $two${typeCast} as bar, $one${typeCast} as baz${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, { raw: true, bind: { one: 1, two: 2 }, @@ -916,10 +899,10 @@ describe(getTestDialectTeaser('Sequelize'), () => { it('binds named parameters with the passed object having a null property', async function () { const typeCast = ['postgres', 'db2'].includes(dialectName) ? '::int' : ''; const result = await this.sequelize.query( - `select $one${typeCast} as foo, $two${typeCast} as bar${fromQuery()}`, + `select $one${typeCast} as foo, $two${typeCast} as bar${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, { raw: true, bind: { one: 1, two: null } }, ); - const expected = ['db2', 'ibmi', 'oracle'].includes(dialectName) + const expected = ['db2', 'ibmi'].includes(dialectName) ? [{ FOO: 1, BAR: null }] : [{ foo: 1, bar: null }]; expect(result[0]).to.deep.equal(expected); @@ -930,7 +913,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { const typeCast = ['postgres', 'db2'].includes(dialectName) ? '::int' : ''; let logSql; const result = await this.sequelize.query( - `select $1${typeCast} as foo, '$$ / $$1' as bar${fromQuery()}`, + `select $1${typeCast} as foo, '$$ / $$1' as bar${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, { raw: true, bind: [1], @@ -939,7 +922,7 @@ describe(getTestDialectTeaser('Sequelize'), () => { }, }, ); - const expected = ['db2', 'ibmi', 'oracle'].includes(dialectName) + const expected = ['db2', 'ibmi'].includes(dialectName) ? [{ FOO: 1, BAR: '$$ / $$1' }] : [{ foo: 1, bar: '$$ / $$1' }]; expect(result[0]).to.deep.equal(expected); @@ -952,10 +935,10 @@ describe(getTestDialectTeaser('Sequelize'), () => { it('does not transform $$ in strings (named)', async function () { const typeCast = ['postgres', 'db2'].includes(dialectName) ? '::int' : ''; const result = await this.sequelize.query( - `select $one${typeCast} as foo, '$$ / $$one' as bar${fromQuery()}`, + `select $one${typeCast} as foo, '$$ / $$one' as bar${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, { raw: true, bind: { one: 1 } }, ); - const expected = ['db2', 'ibmi', 'oracle'].includes(dialectName) + const expected = ['db2', 'ibmi'].includes(dialectName) ? [{ FOO: 1, BAR: '$$ / $$one' }] : [{ foo: 1, bar: '$$ / $$one' }]; expect(result[0]).to.deep.equal(expected); @@ -964,24 +947,23 @@ describe(getTestDialectTeaser('Sequelize'), () => { it(`does not treat a $ as a bind param if it's in the middle of an identifier`, async function () { const typeCast = ['postgres', 'db2'].includes(dialectName) ? '::int' : ''; const result = await this.sequelize.query( - `select $one${typeCast} as foo$bar${fromQuery()}`, + `select $one${typeCast} as foo$bar${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, { raw: true, bind: { one: 1 } }, ); - const expected = ['db2', 'ibmi', 'oracle'].includes(dialectName) + const expected = ['db2', 'ibmi'].includes(dialectName) ? [{ FOO$BAR: 1 }] : [{ foo$bar: 1 }]; expect(result[0]).to.deep.equal(expected); }); } - if (['postgres', 'sqlite3', 'mssql', 'oracle'].includes(dialectName)) { + if (['postgres', 'sqlite3', 'mssql'].includes(dialectName)) { it('does not improperly escape arrays of strings bound to named parameters', async function () { - const result = await this.sequelize.query(`select :stringArray as foo${fromQuery()}`, { + const result = await this.sequelize.query('select :stringArray as foo', { raw: true, replacements: { stringArray: sql.list(['"string"']) }, }); - const expectedData = dialectName !== 'oracle' ? { foo: '"string"' } : { FOO: '"string"' }; - expect(result[0]).to.deep.equal([expectedData]); + expect(result[0]).to.deep.equal([{ foo: '"string"' }]); }); } @@ -989,11 +971,11 @@ describe(getTestDialectTeaser('Sequelize'), () => { let datetime = dialectName === 'sqlite3' ? "date('now')" : 'NOW()'; if (dialectName === 'mssql') { datetime = 'GETDATE()'; - } else if (dialectName === 'oracle') { - datetime = 'SYSDATE'; } - const [result] = await this.sequelize.query(`SELECT ${datetime} AS t${fromQuery()}`); + const [result] = await this.sequelize.query( + `SELECT ${datetime} AS t${dialectName === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''}`, + ); expect(dayjs(result[0].t).isValid()).to.be.true; }); diff --git a/packages/core/test/integration/sequelize/transaction.test.ts b/packages/core/test/integration/sequelize/transaction.test.ts index 74e10c66c60a..e1e52400851c 100644 --- a/packages/core/test/integration/sequelize/transaction.test.ts +++ b/packages/core/test/integration/sequelize/transaction.test.ts @@ -340,7 +340,7 @@ describe(getTestDialectTeaser('Sequelize#transaction'), () => { } // These dialects do not allow dirty reads with isolation level "READ UNCOMMITTED". - if (!['postgres', 'sqlite3', 'oracle'].includes(dialectName)) { + if (!['postgres', 'sqlite3'].includes(dialectName)) { it('should allow dirty read with isolation level "READ UNCOMMITTED"', async () => { const { User, transactionSequelize } = vars; const t1 = await transactionSequelize.startUnmanagedTransaction({ @@ -427,7 +427,7 @@ describe(getTestDialectTeaser('Sequelize#transaction'), () => { } // These dialects do not allow phantom reads with isolation level "REPEATABLE READ" as they use snapshot rather than locking. - if (['mariadb', 'mysql', 'postgres', 'oracle'].includes(dialectName)) { + if (['mariadb', 'mysql', 'postgres'].includes(dialectName)) { it('should not read newly committed rows when using the REPEATABLE READ isolation level', async () => { const { User, transactionSequelize } = vars; @@ -479,7 +479,7 @@ describe(getTestDialectTeaser('Sequelize#transaction'), () => { } // PostgreSQL is excluded because it detects Serialization Failure on commit instead of acquiring locks on the read rows - if (!['postgres', 'oracle'].includes(dialectName)) { + if (!['postgres'].includes(dialectName)) { it('should block updates after reading a row using SERIALIZABLE', async () => { const { User, transactionSequelize } = vars; const transactionSpy = sinon.spy(); @@ -591,9 +591,6 @@ describe(getTestDialectTeaser('Sequelize#transaction'), () => { case 'mssql': query = "WAITFOR DELAY '00:00:02';"; break; - case 'oracle': - query = 'BEGIN DBMS_SESSION.sleep(2); END;'; - break; default: query = 'select sleep(2);'; break; diff --git a/packages/core/test/integration/transaction.test.js b/packages/core/test/integration/transaction.test.js index 8c027e4ba3ae..625ab8ca541b 100644 --- a/packages/core/test/integration/transaction.test.js +++ b/packages/core/test/integration/transaction.test.js @@ -20,14 +20,6 @@ const current = Support.sequelize; const delay = require('delay'); const pSettle = require('p-settle'); -const fromQuery = () => { - if (dialect === 'oracle') { - return ' FROM DUAL'; - } - - return ''; -}; - describe(Support.getTestDialectTeaser('Transaction'), () => { if (!current.dialect.supports.transactions) { return; @@ -116,10 +108,7 @@ describe(Support.getTestDialectTeaser('Transaction'), () => { transaction.afterRollback(afterRollback); transaction.afterTransaction(afterTransaction); - return this.sequelize.query(`SELECT 1+1${fromQuery()}`, { - transaction, - type: QueryTypes.SELECT, - }); + return this.sequelize.query('SELECT 1+1', { transaction, type: QueryTypes.SELECT }); }); expect(afterCommit).to.have.been.calledOnce; @@ -271,31 +260,31 @@ describe(Support.getTestDialectTeaser('Transaction'), () => { it('does not allow queries after commit', async function () { const t = await this.sequelize.startUnmanagedTransaction(); - await this.sequelize.query(`SELECT 1+1${fromQuery()}`, { transaction: t, raw: true }); + await this.sequelize.query('SELECT 1+1', { transaction: t, raw: true }); await t.commit(); - await expect(this.sequelize.query(`SELECT 1+1${fromQuery()}`, { transaction: t, raw: true })) + await expect(this.sequelize.query('SELECT 1+1', { transaction: t, raw: true })) .to.be.eventually.rejectedWith( Error, /commit has been called on this transaction\([^)]+\), you can no longer use it\. \(The rejected query is attached as the 'sql' property of this error\)/, ) .and.have.deep.property('sql') - .that.equal(`SELECT 1+1${fromQuery()}`); + .that.equal('SELECT 1+1'); }); it('does not allow queries immediately after commit call', async function () { await expect( (async () => { const t = await this.sequelize.startUnmanagedTransaction(); - await this.sequelize.query(`SELECT 1+1${fromQuery()}`, { transaction: t, raw: true }); + await this.sequelize.query('SELECT 1+1', { transaction: t, raw: true }); await Promise.all([ expect(t.commit()).to.eventually.be.fulfilled, - expect(this.sequelize.query(`SELECT 1+1${fromQuery()}`, { transaction: t, raw: true })) + expect(this.sequelize.query('SELECT 1+1', { transaction: t, raw: true })) .to.be.eventually.rejectedWith( Error, /commit has been called on this transaction\([^)]+\), you can no longer use it\. \(The rejected query is attached as the 'sql' property of this error\)/, ) .and.have.deep.property('sql') - .that.equal(`SELECT 1+1${fromQuery()}`), + .that.equal('SELECT 1+1'), ]); })(), ).to.be.eventually.fulfilled; @@ -305,13 +294,10 @@ describe(Support.getTestDialectTeaser('Transaction'), () => { await expect( (async () => { const t = await this.sequelize.startUnmanagedTransaction(); - await this.sequelize.query(`SELECT 1+1${fromQuery()}`, { transaction: t, raw: true }); + await this.sequelize.query('SELECT 1+1', { transaction: t, raw: true }); await t.rollback(); - return await this.sequelize.query(`SELECT 1+1${fromQuery()}`, { - transaction: t, - raw: true, - }); + return await this.sequelize.query('SELECT 1+1', { transaction: t, raw: true }); })(), ).to.eventually.be.rejected; }); @@ -333,13 +319,13 @@ describe(Support.getTestDialectTeaser('Transaction'), () => { this.sequelize.startUnmanagedTransaction().then(async t => { await Promise.all([ expect(t.rollback()).to.eventually.be.fulfilled, - expect(this.sequelize.query(`SELECT 1+1${fromQuery()}`, { transaction: t, raw: true })) + expect(this.sequelize.query('SELECT 1+1', { transaction: t, raw: true })) .to.be.eventually.rejectedWith( Error, /rollback has been called on this transaction\([^)]+\), you can no longer use it\. \(The rejected query is attached as the 'sql' property of this error\)/, ) .and.have.deep.property('sql') - .that.equal(`SELECT 1+1${fromQuery()}`), + .that.equal('SELECT 1+1'), ]); }), ).to.eventually.be.fulfilled; diff --git a/packages/core/test/integration/utils.test.ts b/packages/core/test/integration/utils.test.ts index 02637e78371c..095d5505614b 100644 --- a/packages/core/test/integration/utils.test.ts +++ b/packages/core/test/integration/utils.test.ts @@ -35,7 +35,7 @@ describe(getTestDialectTeaser('fn()'), () => { // some dialects return the result of arithmetic functions (SUM, COUNT) as integer & floats, others as bigints & decimals. const arithmeticAsNumber = dialectName === 'sqlite3' || dialectName === 'db2'; - if (!['mssql', 'ibmi', 'oracle'].includes(dialectName)) { + if (dialectName !== 'mssql' && dialectName !== 'ibmi') { it('accepts condition object (with cast)', async () => { const type = dialectName === 'mysql' ? 'unsigned' : 'int'; @@ -82,7 +82,7 @@ describe(getTestDialectTeaser('fn()'), () => { }); } - if (!['mssql', 'postgres', 'ibmi', 'oracle'].includes(dialectName)) { + if (dialectName !== 'mssql' && dialectName !== 'postgres' && dialectName !== 'ibmi') { it('accepts condition object (auto casting)', async () => { const [airplane] = await vars.Airplane.findAll({ attributes: [ diff --git a/packages/core/test/unit/configuration.test.ts b/packages/core/test/unit/configuration.test.ts index 521961190714..5aae50908c46 100644 --- a/packages/core/test/unit/configuration.test.ts +++ b/packages/core/test/unit/configuration.test.ts @@ -28,7 +28,7 @@ describe('Sequelize constructor', () => { new Sequelize({ dialect: 'some-fancy-dialect' }); }).to.throw( Error, - 'The dialect some-fancy-dialect is not natively supported. Native dialects: mariadb, mssql, mysql, postgres, sqlite3, ibmi, db2, oracle and snowflake.', + 'The dialect some-fancy-dialect is not natively supported. Native dialects: mariadb, mssql, mysql, postgres, sqlite3, ibmi, db2 and snowflake.', ); }); diff --git a/packages/core/test/unit/data-types/binary-types.test.ts b/packages/core/test/unit/data-types/binary-types.test.ts index c91f1611d9bb..1479c0bba120 100644 --- a/packages/core/test/unit/data-types/binary-types.test.ts +++ b/packages/core/test/unit/data-types/binary-types.test.ts @@ -17,7 +17,6 @@ describe('DataTypes.BLOB', () => { db2: 'BLOB(255)', postgres: 'BYTEA', sqlite3: 'BLOB', - oracle: 'BLOB', }); testDataTypeSql('BLOB("medium")', DataTypes.BLOB('medium'), { @@ -27,7 +26,6 @@ describe('DataTypes.BLOB', () => { db2: 'BLOB(16M)', postgres: 'BYTEA', sqlite3: 'BLOB', - oracle: 'BLOB', }); testDataTypeSql('BLOB({ length: "medium" })', DataTypes.BLOB({ length: 'medium' }), { @@ -37,7 +35,6 @@ describe('DataTypes.BLOB', () => { db2: 'BLOB(16M)', postgres: 'BYTEA', sqlite3: 'BLOB', - oracle: 'BLOB', }); testDataTypeSql('BLOB("long")', DataTypes.BLOB('long'), { @@ -47,7 +44,6 @@ describe('DataTypes.BLOB', () => { db2: 'BLOB(2G)', postgres: 'BYTEA', sqlite3: 'BLOB', - oracle: 'BLOB', }); describe('validate', () => { diff --git a/packages/core/test/unit/data-types/decimal-numbers.test.ts b/packages/core/test/unit/data-types/decimal-numbers.test.ts index 99e371dac74f..5396b37d5267 100644 --- a/packages/core/test/unit/data-types/decimal-numbers.test.ts +++ b/packages/core/test/unit/data-types/decimal-numbers.test.ts @@ -16,25 +16,21 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat testDataTypeSql('REAL', DataTypes.REAL, { default: 'REAL', - oracle: 'BINARY_DOUBLE', }); testDataTypeSql('REAL.UNSIGNED', DataTypes.REAL.UNSIGNED, { default: 'REAL UNSIGNED', 'sqlite3 snowflake ibmi db2 mssql postgres': 'REAL', - oracle: 'BINARY_DOUBLE', }); testDataTypeSql('REAL(11, 12)', DataTypes.REAL(11, 12), { default: 'REAL(11, 12)', 'sqlite3 snowflake ibmi db2 mssql postgres': 'REAL', - oracle: 'BINARY_DOUBLE', }); testDataTypeSql('REAL(11, 12).UNSIGNED', DataTypes.REAL(11, 12).UNSIGNED, { default: 'REAL(11, 12) UNSIGNED', 'sqlite3 snowflake ibmi db2 mssql postgres': 'REAL', - oracle: 'BINARY_DOUBLE', }); testDataTypeSql( @@ -43,7 +39,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat { default: 'REAL(11, 12) UNSIGNED', 'sqlite3 snowflake ibmi db2 mssql postgres': 'REAL', - oracle: 'BINARY_DOUBLE', }, ); @@ -73,7 +68,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'DOUBLE', sqlite3: 'REAL', snowflake: 'FLOAT', - oracle: 'BINARY_DOUBLE', }); testDataTypeSql('DOUBLE.UNSIGNED', DataTypes.DOUBLE.UNSIGNED, { @@ -82,7 +76,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'DOUBLE', 'postgres mssql': 'DOUBLE PRECISION', snowflake: 'FLOAT', - oracle: 'BINARY_DOUBLE', }); testDataTypeSql('DOUBLE(11, 12)', DataTypes.DOUBLE(11, 12), { @@ -91,7 +84,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'DOUBLE', 'postgres mssql': 'DOUBLE PRECISION', snowflake: 'FLOAT', - oracle: 'BINARY_DOUBLE', }); testDataTypeSql('DOUBLE(11, 12).UNSIGNED', DataTypes.DOUBLE(11, 12).UNSIGNED, { @@ -100,7 +92,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'DOUBLE', 'postgres mssql': 'DOUBLE PRECISION', snowflake: 'FLOAT', - oracle: 'BINARY_DOUBLE', }); testDataTypeSql('DOUBLE(11, 12).UNSIGNED.ZEROFILL', DataTypes.DOUBLE(11, 12).UNSIGNED.ZEROFILL, { @@ -143,28 +134,24 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mysql mariadb snowflake': 'FLOAT', // REAL in sqlite is double-precision (no single-precision support), but single-precision in all others 'postgres mssql sqlite3 db2 ibmi': 'REAL', - oracle: 'BINARY_FLOAT', }); testDataTypeSql('FLOAT.UNSIGNED', DataTypes.FLOAT.UNSIGNED, { 'mysql mariadb': 'FLOAT UNSIGNED', snowflake: 'FLOAT', 'postgres mssql sqlite3 db2 ibmi': 'REAL', - oracle: 'BINARY_FLOAT', }); testDataTypeSql('FLOAT(11, 12)', DataTypes.FLOAT(11, 12), { 'mysql mariadb': 'FLOAT(11, 12)', snowflake: 'FLOAT', 'postgres mssql sqlite3 db2 ibmi': 'REAL', - oracle: 'BINARY_FLOAT', }); testDataTypeSql('FLOAT(11, 12).UNSIGNED', DataTypes.FLOAT(11, 12).UNSIGNED, { 'mysql mariadb': 'FLOAT(11, 12) UNSIGNED', snowflake: 'FLOAT', 'postgres mssql sqlite3 db2 ibmi': 'REAL', - oracle: 'BINARY_FLOAT', }); testDataTypeSql( @@ -174,7 +161,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mysql mariadb': 'FLOAT(11, 12) UNSIGNED', snowflake: 'FLOAT', 'postgres mssql sqlite3 db2 ibmi': 'REAL', - oracle: 'BINARY_FLOAT', }, ); @@ -239,13 +225,11 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat ), sqlite3: unsupportedError, postgres: 'DECIMAL', - oracle: 'NUMBER', }); testDataTypeSql('DECIMAL(10, 2)', DataTypes.DECIMAL(10, 2), { default: 'DECIMAL(10, 2)', sqlite3: unsupportedError, - oracle: 'NUMBER(10, 2)', }); testDataTypeSql( @@ -254,7 +238,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat { default: 'DECIMAL(10, 2)', sqlite3: unsupportedError, - oracle: 'NUMBER(10, 2)', }, ); @@ -262,7 +245,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: 'DECIMAL(10, 2)', 'mysql mariadb': 'DECIMAL(10, 2) UNSIGNED', sqlite3: unsupportedError, - oracle: 'NUMBER(10, 2)', }); testDataTypeSql('DECIMAL(10, 2).UNSIGNED.ZEROFILL', DataTypes.DECIMAL(10, 2).UNSIGNED.ZEROFILL, { @@ -278,7 +260,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: 'DECIMAL(10, 2)', 'mysql mariadb': 'DECIMAL(10, 2) UNSIGNED', sqlite3: unsupportedError, - oracle: 'NUMBER(10, 2)', }, ); @@ -302,10 +283,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat it('should throw an error if `value` is invalid', () => { const type: DataTypeInstance = DataTypes.DECIMAL(10, 2).toDialectDataType(dialect); - let typeName = supportsDecimal.constrained ? 'decimal(10, 2)' : 'decimal'; - if (dialect.name === 'oracle') { - typeName = 'number(10, 2)'; - } + const typeName = supportsDecimal.constrained ? 'decimal(10, 2)' : 'decimal'; expect(() => { type.validate('foobar'); diff --git a/packages/core/test/unit/data-types/integers.test.ts b/packages/core/test/unit/data-types/integers.test.ts index 7e9ad1857e75..a7663e4dd386 100644 --- a/packages/core/test/unit/data-types/integers.test.ts +++ b/packages/core/test/unit/data-types/integers.test.ts @@ -21,7 +21,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mssql postgres db2 ibmi': 'SMALLINT', 'mysql mariadb': 'TINYINT', 'sqlite3 snowflake': 'INTEGER', - oracle: 'NUMBER(3)', }, }, { @@ -32,7 +31,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mssql postgres db2 ibmi': 'SMALLINT', 'mysql mariadb': 'TINYINT(2)', 'sqlite3 snowflake': 'INTEGER', - oracle: 'NUMBER(3)', }, }, { @@ -42,7 +40,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mssql postgres db2 ibmi': 'SMALLINT', 'mysql mariadb': 'TINYINT(2)', 'sqlite3 snowflake': 'INTEGER', - oracle: 'NUMBER(3)', }, }, { @@ -56,7 +53,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'sqlite3 snowflake': 'INTEGER', // TINYINT is unsigned in mssql mssql: 'TINYINT', - oracle: 'NUMBER(3)', }, }, { @@ -67,7 +63,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mysql mariadb': 'TINYINT(2) UNSIGNED', 'sqlite3 snowflake': 'INTEGER', mssql: 'TINYINT', - oracle: 'NUMBER(3)', }, }, { @@ -160,7 +155,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat expect: { default: 'SMALLINT', 'sqlite3 snowflake': 'INTEGER', - oracle: 'SMALLINT', }, }, { @@ -170,7 +164,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: 'SMALLINT', 'sqlite3 snowflake': 'INTEGER', 'mysql mariadb': 'SMALLINT(4)', - oracle: 'NUMBER(4,0)', }, }, { @@ -180,7 +173,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: 'SMALLINT', 'sqlite3 snowflake': 'INTEGER', 'mysql mariadb': 'SMALLINT(4)', - oracle: 'NUMBER(4,0)', }, }, { @@ -192,7 +184,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'sqlite3 snowflake': 'INTEGER', 'postgres db2 ibmi': 'INTEGER', mssql: 'INT', - oracle: 'SMALLINT', }, }, { @@ -203,7 +194,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'sqlite3 snowflake': 'INTEGER', 'postgres db2 ibmi': 'INTEGER', mssql: 'INT', - oracle: 'NUMBER(4,0)', }, }, { @@ -297,7 +287,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mariadb mysql': 'MEDIUMINT', // falls back to larger type + CHECK constraint 'db2 ibmi mssql postgres snowflake sqlite3': 'INTEGER', - oracle: 'NUMBER(8)', }, }, { @@ -306,7 +295,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat expect: { 'mariadb mysql': 'MEDIUMINT(2)', 'db2 ibmi mssql postgres snowflake sqlite3': 'INTEGER', - oracle: 'NUMBER(8)', }, }, { @@ -315,7 +303,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat expect: { 'mariadb mysql': 'MEDIUMINT(2)', 'db2 ibmi mssql postgres snowflake sqlite3': 'INTEGER', - oracle: 'NUMBER(8)', }, }, { @@ -324,7 +311,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat expect: { 'mariadb mysql': 'MEDIUMINT UNSIGNED', 'db2 ibmi mssql postgres snowflake sqlite3': 'INTEGER', - oracle: 'NUMBER(8)', }, }, { @@ -333,7 +319,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat expect: { 'mariadb mysql': 'MEDIUMINT(2) UNSIGNED', 'db2 ibmi mssql postgres snowflake sqlite3': 'INTEGER', - oracle: 'NUMBER(8)', }, }, { @@ -425,7 +410,7 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat testDataTypeSql('INTEGER.UNSIGNED', DataTypes.INTEGER.UNSIGNED, { // sqlite & snowflake are both 64 bits integers (actually snowflake accepts up to 99999999999999999999999999999999999999) - 'sqlite3 oracle snowflake': 'INTEGER', + 'sqlite3 snowflake': 'INTEGER', 'mysql mariadb': 'INTEGER UNSIGNED', 'ibmi postgres db2 mssql': 'BIGINT', }); @@ -438,20 +423,17 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat testDataTypeSql('INTEGER(11)', DataTypes.INTEGER(11), { default: 'INTEGER', 'mysql mariadb': 'INTEGER(11)', - oracle: 'NUMBER(11,0)', }); testDataTypeSql('INTEGER({ length: 11 })', DataTypes.INTEGER({ length: 11 }), { default: 'INTEGER', 'mysql mariadb': 'INTEGER(11)', - oracle: 'NUMBER(11,0)', }); testDataTypeSql('INTEGER(11).UNSIGNED', DataTypes.INTEGER(11).UNSIGNED, { 'mysql mariadb': 'INTEGER(11) UNSIGNED', 'sqlite3 snowflake': 'INTEGER', 'ibmi postgres db2 mssql': 'BIGINT', - oracle: 'NUMBER(11,0)', }); testDataTypeSql('INTEGER(11).UNSIGNED.ZEROFILL', DataTypes.INTEGER(11).UNSIGNED.ZEROFILL, { @@ -510,7 +492,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat testDataTypeSql('BIGINT', DataTypes.BIGINT, { default: 'BIGINT', 'sqlite3 snowflake': 'INTEGER', - oracle: 'NUMBER(19, 0)', }); testDataTypeSql('BIGINT.UNSIGNED', DataTypes.BIGINT.UNSIGNED, { @@ -518,7 +499,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'mysql mariadb': 'BIGINT UNSIGNED', // INTEGER in snowflake goes up to 99999999999999999999999999999999999999, which is enough to store an unsigned 64-bit integer. snowflake: 'INTEGER', - oracle: 'NUMBER(19, 0)', }); testDataTypeSql('BIGINT.UNSIGNED.ZEROFILL', DataTypes.BIGINT.UNSIGNED.ZEROFILL, { @@ -530,14 +510,12 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: 'BIGINT', 'sqlite3 snowflake': 'INTEGER', 'mysql mariadb': 'BIGINT(11)', - oracle: 'NUMBER(19, 0)', }); testDataTypeSql('BIGINT({ length: 11 })', DataTypes.BIGINT({ length: 11 }), { default: 'BIGINT', 'sqlite3 snowflake': 'INTEGER', 'mysql mariadb': 'BIGINT(11)', - oracle: 'NUMBER(19, 0)', }); testDataTypeSql('BIGINT(11).UNSIGNED', DataTypes.BIGINT(11).UNSIGNED, { @@ -545,7 +523,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: unsignedUnsupportedError, 'mysql mariadb': 'BIGINT(11) UNSIGNED', snowflake: 'INTEGER', - oracle: 'NUMBER(19, 0)', }); testDataTypeSql('BIGINT(11).UNSIGNED.ZEROFILL', DataTypes.BIGINT(11).UNSIGNED.ZEROFILL, { diff --git a/packages/core/test/unit/data-types/misc-data-types.test.ts b/packages/core/test/unit/data-types/misc-data-types.test.ts index 5c1335225889..3ea3c343895b 100644 --- a/packages/core/test/unit/data-types/misc-data-types.test.ts +++ b/packages/core/test/unit/data-types/misc-data-types.test.ts @@ -17,7 +17,6 @@ describe('DataTypes.BOOLEAN', () => { mariadb: 'TINYINT(1)', mysql: 'TINYINT(1)', sqlite3: 'INTEGER', - oracle: 'CHAR(1)', }); describe('validate', () => { @@ -58,7 +57,6 @@ describe('DataTypes.ENUM', () => { mssql: `NVARCHAR(255)`, sqlite3: 'TEXT', 'db2 ibmi snowflake': 'VARCHAR(255)', - oracle: 'VARCHAR2(512)', }); }); @@ -190,7 +188,6 @@ describe('DataTypes.JSON', () => { // SQL server supports JSON functions, but it is stored as a string with a ISJSON constraint. mssql: 'NVARCHAR(MAX)', sqlite3: 'TEXT', - oracle: 'BLOB', }); describe('escape', () => { @@ -203,7 +200,6 @@ describe('DataTypes.JSON', () => { default: `'"string"'`, mysql: `CAST('"string"' AS JSON)`, mssql: `N'"string"'`, - oracle: `'string'`, }); }); diff --git a/packages/core/test/unit/data-types/string-types.test.ts b/packages/core/test/unit/data-types/string-types.test.ts index 5279749b8fe1..e4df01fa7f28 100644 --- a/packages/core/test/unit/data-types/string-types.test.ts +++ b/packages/core/test/unit/data-types/string-types.test.ts @@ -17,21 +17,18 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat default: 'VARCHAR(255)', mssql: 'NVARCHAR(255)', sqlite3: 'TEXT', - oracle: 'NVARCHAR2(255)', }); testDataTypeSql('STRING(1234)', DataTypes.STRING(1234), { default: 'VARCHAR(1234)', mssql: 'NVARCHAR(1234)', sqlite3: 'TEXT', - oracle: 'NVARCHAR2(1234)', }); testDataTypeSql('STRING({ length: 1234 })', DataTypes.STRING({ length: 1234 }), { default: 'VARCHAR(1234)', mssql: 'NVARCHAR(1234)', sqlite3: 'TEXT', - oracle: 'NVARCHAR2(1234)', }); testDataTypeSql('STRING(1234).BINARY', DataTypes.STRING(1234).BINARY, { @@ -39,7 +36,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'VARCHAR(1234) FOR BIT DATA', sqlite3: 'TEXT COLLATE BINARY', 'mssql postgres': binaryCollationUnsupportedError, - oracle: 'RAW(1234)', }); testDataTypeSql('STRING.BINARY', DataTypes.STRING.BINARY, { @@ -47,7 +43,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'VARCHAR(255) FOR BIT DATA', sqlite3: 'TEXT COLLATE BINARY', 'mssql postgres': binaryCollationUnsupportedError, - oracle: 'RAW(255)', }); }); @@ -67,7 +62,6 @@ describe('DataTypes.TEXT', () => { default: 'TEXT', 'ibmi db2': 'CLOB(2147483647)', mssql: 'NVARCHAR(MAX)', // in mssql text is actually representing a non unicode text field - oracle: 'CLOB', }); testDataTypeSql('TEXT("tiny")', DataTypes.TEXT('tiny'), { @@ -75,7 +69,6 @@ describe('DataTypes.TEXT', () => { 'ibmi db2': 'VARCHAR(256)', mssql: 'NVARCHAR(256)', 'mariadb mysql': 'TINYTEXT', - oracle: 'CLOB', }); testDataTypeSql('TEXT({ length: "tiny" })', DataTypes.TEXT({ length: 'tiny' }), { @@ -83,7 +76,6 @@ describe('DataTypes.TEXT', () => { 'ibmi db2': 'VARCHAR(256)', mssql: 'NVARCHAR(256)', 'mariadb mysql': 'TINYTEXT', - oracle: 'CLOB', }); testDataTypeSql('TEXT("medium")', DataTypes.TEXT('medium'), { @@ -91,7 +83,6 @@ describe('DataTypes.TEXT', () => { 'ibmi db2': 'CLOB(16777216)', mssql: 'NVARCHAR(MAX)', 'mariadb mysql': 'MEDIUMTEXT', - oracle: 'CLOB', }); testDataTypeSql('TEXT("long")', DataTypes.TEXT('long'), { @@ -99,7 +90,6 @@ describe('DataTypes.TEXT', () => { 'ibmi db2': 'CLOB(2147483647)', mssql: 'NVARCHAR(MAX)', 'mariadb mysql': 'LONGTEXT', - oracle: 'CLOB', }); }); @@ -176,7 +166,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'CHAR(12) FOR BIT DATA', sqlite3: charNotSupportedError, 'postgres mssql': binaryNotSupportedError, - oracle: 'RAW(12)', }); testDataTypeSql('CHAR.BINARY', DataTypes.CHAR.BINARY, { @@ -184,7 +173,6 @@ See https://sequelize.org/docs/v7/models/data-types/ for a list of supported dat 'db2 ibmi': 'CHAR(255) FOR BIT DATA', sqlite3: charNotSupportedError, 'postgres mssql': binaryNotSupportedError, - oracle: 'RAW(255)', }); }); }); diff --git a/packages/core/test/unit/data-types/temporal-types.test.ts b/packages/core/test/unit/data-types/temporal-types.test.ts index f543f49021cd..e00cd34f144f 100644 --- a/packages/core/test/unit/data-types/temporal-types.test.ts +++ b/packages/core/test/unit/data-types/temporal-types.test.ts @@ -17,7 +17,6 @@ describe('DataTypes.DATE', () => { mssql: 'DATETIMEOFFSET', 'mariadb mysql': 'DATETIME', sqlite3: 'TEXT', - oracle: 'TIMESTAMP WITH LOCAL TIME ZONE', }); testDataTypeSql('DATE(0)', DataTypes.DATE(0), { @@ -26,7 +25,6 @@ describe('DataTypes.DATE', () => { 'mariadb mysql': 'DATETIME(0)', 'db2 ibmi snowflake': 'TIMESTAMP(0)', sqlite3: 'TEXT', - oracle: 'TIMESTAMP WITH LOCAL TIME ZONE', }); testDataTypeSql('DATE(6)', DataTypes.DATE(6), { @@ -36,7 +34,6 @@ describe('DataTypes.DATE', () => { mariadb: 'DATETIME(6)', mysql: 'DATETIME(6)', sqlite3: 'TEXT', - oracle: 'TIMESTAMP WITH LOCAL TIME ZONE', }); }); @@ -140,8 +137,6 @@ describe('DataTypes.TIME', () => { db2: new Error(`db2 does not support the TIME(precision) data type. See https://sequelize.org/docs/v7/models/data-types/ for a list of supported data types.`), sqlite3: 'TEXT', - oracle: new Error(`oracle does not support the TIME(precision) data type. -See https://sequelize.org/docs/v7/models/data-types/ for a list of supported data types`), }); }); }); @@ -152,7 +147,6 @@ describe('DataTypes.NOW', () => { default: 'NOW', db2: 'CURRENT TIME', mssql: 'GETDATE()', - oracle: 'SYSDATE', }); }); }); diff --git a/packages/core/test/unit/data-types/uuid.test.ts b/packages/core/test/unit/data-types/uuid.test.ts index f306f010b7f6..fdf416abe350 100644 --- a/packages/core/test/unit/data-types/uuid.test.ts +++ b/packages/core/test/unit/data-types/uuid.test.ts @@ -15,7 +15,6 @@ describe('DataTypes.UUID', () => { 'mariadb mysql': 'CHAR(36) BINARY', snowflake: 'VARCHAR(36)', sqlite3: 'TEXT', - oracle: 'VARCHAR2(36)', }); }); diff --git a/packages/core/test/unit/pool.test.ts b/packages/core/test/unit/pool.test.ts index ea83771180f6..99b2584c9796 100644 --- a/packages/core/test/unit/pool.test.ts +++ b/packages/core/test/unit/pool.test.ts @@ -132,9 +132,6 @@ describe('sequelize.pool', () => { snowflake: { account: 'replica1', }, - oracle: { - host: 'replica1', - }, }; const replica2Overrides: DialectConnectionConfigs = { @@ -162,9 +159,6 @@ describe('sequelize.pool', () => { snowflake: { account: 'replica2', }, - oracle: { - host: 'replica1', - }, }; const connectionOptions = sequelize.options.replication.write; @@ -236,9 +230,6 @@ describe('sequelize.pool', () => { snowflake: { account: 'write', }, - oracle: { - host: 'write', - }, }; const connectionOptions = sequelize.options.replication.write; diff --git a/packages/core/test/unit/query-generator/add-column-query.test.ts b/packages/core/test/unit/query-generator/add-column-query.test.ts index ea980a43a357..ece57cdcfe1c 100644 --- a/packages/core/test/unit/query-generator/add-column-query.test.ts +++ b/packages/core/test/unit/query-generator/add-column-query.test.ts @@ -31,7 +31,6 @@ describe('QueryGenerator#addColumnQuery', () => { default: `ALTER TABLE [Users] ADD [age] INTEGER;`, mssql: `ALTER TABLE [Users] ADD [age] INTEGER NULL;`, postgres: `ALTER TABLE "Users" ADD COLUMN "age" INTEGER;`, - oracle: `ALTER TABLE "Users" ADD "age" INTEGER NULL;`, }, ); }); diff --git a/packages/core/test/unit/query-generator/add-constraint-query.test.ts b/packages/core/test/unit/query-generator/add-constraint-query.test.ts index 244a088fa168..492431e7a0f0 100644 --- a/packages/core/test/unit/query-generator/add-constraint-query.test.ts +++ b/packages/core/test/unit/query-generator/add-constraint-query.test.ts @@ -561,7 +561,7 @@ describe('QueryGenerator#addConstraintQuery', () => { { default: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_otherId_otherTable_fk] FOREIGN KEY ([otherId]) REFERENCES [otherTable] ([id]) ON UPDATE CASCADE`, sqlite3: notSupportedError, - 'db2 ibmi oracle': onUpdateNotSupportedError, + 'db2 ibmi': onUpdateNotSupportedError, }, ); }); diff --git a/packages/core/test/unit/query-generator/bulk-delete-query.test.ts b/packages/core/test/unit/query-generator/bulk-delete-query.test.ts index 5af4db934f15..ca2003457840 100644 --- a/packages/core/test/unit/query-generator/bulk-delete-query.test.ts +++ b/packages/core/test/unit/query-generator/bulk-delete-query.test.ts @@ -25,7 +25,6 @@ describe('QueryGenerator#bulkDeleteQuery', () => { "DELETE FROM `myTable` WHERE rowid IN (SELECT rowid FROM `myTable` WHERE `name` = 'barry' LIMIT 10)", 'db2 ibmi': `DELETE FROM "myTable" WHERE "name" = 'barry' FETCH NEXT 10 ROWS ONLY`, 'mssql postgres snowflake': limitNotSupportedError, - oracle: limitNotSupportedError, }, ); }); @@ -40,7 +39,6 @@ describe('QueryGenerator#bulkDeleteQuery', () => { "DELETE FROM `MyModels` WHERE rowid IN (SELECT rowid FROM `MyModels` WHERE `name` = 'barry' LIMIT 10)", 'db2 ibmi': `DELETE FROM "MyModels" WHERE "name" = 'barry' FETCH NEXT 10 ROWS ONLY`, 'postgres snowflake': `DELETE FROM "MyModels" WHERE "id" IN (SELECT "id" FROM "MyModels" WHERE "name" = 'barry' ORDER BY "id" LIMIT 10)`, - oracle: `DELETE FROM "MyModels" WHERE rowid IN (SELECT rowid FROM "MyModels" WHERE rownum <= 10 AND "name" = 'barry')`, }); }); @@ -57,7 +55,6 @@ describe('QueryGenerator#bulkDeleteQuery', () => { "DELETE FROM `MyModels` WHERE rowid IN (SELECT rowid FROM `MyModels` WHERE `name` = 'barry' LIMIT 10)", 'db2 ibmi': `DELETE FROM "MyModels" WHERE "name" = 'barry' FETCH NEXT 10 ROWS ONLY`, 'postgres snowflake': `DELETE FROM "MyModels" WHERE "id" IN (SELECT "id" FROM "MyModels" WHERE "name" = 'barry' ORDER BY "id" LIMIT 10)`, - oracle: `DELETE FROM "MyModels" WHERE rowid IN (SELECT rowid FROM "MyModels" WHERE rownum <= 10 AND "name" = 'barry')`, }, ); }); @@ -81,7 +78,6 @@ describe('QueryGenerator#bulkDeleteQuery', () => { sqlite3: `DELETE FROM \`MyModels\` WHERE rowid IN (SELECT rowid FROM \`MyModels\` WHERE name = 'Zoe' LIMIT 1)`, 'db2 ibmi': `DELETE FROM "MyModels" WHERE name = 'Zoe' FETCH NEXT 1 ROWS ONLY`, 'postgres snowflake': `DELETE FROM "MyModels" WHERE "id" IN (SELECT "id" FROM "MyModels" WHERE name = 'Zoe' ORDER BY "id" LIMIT 1)`, - oracle: `DELETE FROM "MyModels" WHERE rowid IN (SELECT rowid FROM "MyModels" WHERE rownum <= :limit AND name = 'Zoe')`, }); }); diff --git a/packages/core/test/unit/query-generator/bulk-insert-query.test.ts b/packages/core/test/unit/query-generator/bulk-insert-query.test.ts index 47034b1da617..507e1a52ea11 100644 --- a/packages/core/test/unit/query-generator/bulk-insert-query.test.ts +++ b/packages/core/test/unit/query-generator/bulk-insert-query.test.ts @@ -1,7 +1,5 @@ import { DataTypes, literal } from '@sequelize/core'; -import { beforeAll2, expectsql, getTestDialect, sequelize } from '../../support'; - -const dialect = getTestDialect(); +import { beforeAll2, expectsql, sequelize } from '../../support'; describe('QueryGenerator#bulkInsertQuery', () => { const queryGenerator = sequelize.queryGenerator; @@ -18,8 +16,7 @@ describe('QueryGenerator#bulkInsertQuery', () => { return { User }; }); - // The Oracle dialect doesn't support replacements for bulkInsert - (dialect !== 'oracle' ? it : it.skip)('parses named replacements in literals', async () => { + it('parses named replacements in literals', async () => { const { User } = vars; const sql = queryGenerator.bulkInsertQuery( diff --git a/packages/core/test/unit/query-generator/commit-transaction-query.test.ts b/packages/core/test/unit/query-generator/commit-transaction-query.test.ts index dc12c2ea438d..b707b6c9f9c5 100644 --- a/packages/core/test/unit/query-generator/commit-transaction-query.test.ts +++ b/packages/core/test/unit/query-generator/commit-transaction-query.test.ts @@ -12,7 +12,6 @@ describe('QueryGenerator#commitTransactionQuery', () => { expectsql(() => queryGenerator.commitTransactionQuery(), { default: 'COMMIT', 'db2 ibmi mssql': notSupportedError, - oracle: 'COMMIT TRANSACTION', }); }); }); diff --git a/packages/core/test/unit/query-generator/create-schema-query.test.ts b/packages/core/test/unit/query-generator/create-schema-query.test.ts index 4880e9f3cf01..ac624615e5b2 100644 --- a/packages/core/test/unit/query-generator/create-schema-query.test.ts +++ b/packages/core/test/unit/query-generator/create-schema-query.test.ts @@ -13,7 +13,6 @@ describe('QueryGenerator#createSchemaQuery', () => { expectsql(() => queryGenerator.createSchemaQuery('mySchema'), { default: 'CREATE SCHEMA [mySchema]', sqlite3: notSupportedError, - oracle: `DECLARE USER_FOUND BOOLEAN := FALSE; BEGIN BEGIN EXECUTE IMMEDIATE 'CREATE USER "mySchema" IDENTIFIED BY 12345 DEFAULT TABLESPACE USERS' ; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1920 THEN RAISE; ELSE USER_FOUND := TRUE; END IF; END; IF NOT USER_FOUND THEN EXECUTE IMMEDIATE 'GRANT "CONNECT" TO "mySchema"' ; EXECUTE IMMEDIATE 'GRANT CREATE TABLE TO "mySchema"' ; EXECUTE IMMEDIATE 'GRANT CREATE VIEW TO "mySchema"' ; EXECUTE IMMEDIATE 'GRANT CREATE ANY TRIGGER TO "mySchema"' ; EXECUTE IMMEDIATE 'GRANT CREATE ANY PROCEDURE TO "mySchema"' ; EXECUTE IMMEDIATE 'GRANT CREATE SEQUENCE TO "mySchema"' ; EXECUTE IMMEDIATE 'GRANT CREATE SYNONYM TO "mySchema"' ; EXECUTE IMMEDIATE 'ALTER USER "mySchema" QUOTA UNLIMITED ON USERS' ; END IF; END;`, }); }); @@ -21,11 +20,9 @@ describe('QueryGenerator#createSchemaQuery', () => { expectsql(() => queryGenerator.createSchemaQuery('mySchema', { authorization: 'myUser' }), { default: 'CREATE SCHEMA [mySchema] AUTHORIZATION [myUser]', sqlite3: notSupportedError, - 'mariadb mysql snowflake oracle': buildInvalidOptionReceivedError( - 'createSchemaQuery', - dialectName, - ['authorization'], - ), + 'mariadb mysql snowflake': buildInvalidOptionReceivedError('createSchemaQuery', dialectName, [ + 'authorization', + ]), }); }); @@ -35,7 +32,7 @@ describe('QueryGenerator#createSchemaQuery', () => { { default: 'CREATE SCHEMA [mySchema] AUTHORIZATION CURRENT USER', sqlite3: notSupportedError, - 'mariadb mysql snowflake oracle': buildInvalidOptionReceivedError( + 'mariadb mysql snowflake': buildInvalidOptionReceivedError( 'createSchemaQuery', dialectName, ['authorization'], @@ -71,7 +68,7 @@ describe('QueryGenerator#createSchemaQuery', () => { it('supports the ifNotExists option', () => { expectsql(() => queryGenerator.createSchemaQuery('mySchema', { ifNotExists: true }), { default: 'CREATE SCHEMA IF NOT EXISTS [mySchema]', - 'db2 ibmi mssql oracle': buildInvalidOptionReceivedError('createSchemaQuery', dialectName, [ + 'db2 ibmi mssql': buildInvalidOptionReceivedError('createSchemaQuery', dialectName, [ 'ifNotExists', ]), sqlite3: notSupportedError, @@ -125,11 +122,6 @@ describe('QueryGenerator#createSchemaQuery', () => { 'charset', 'collate', ]), - oracle: buildInvalidOptionReceivedError('createSchemaQuery', dialectName, [ - 'authorization', - 'charset', - 'collate', - ]), sqlite3: notSupportedError, }, ); diff --git a/packages/core/test/unit/query-generator/create-table-query.test.ts b/packages/core/test/unit/query-generator/create-table-query.test.ts index 7c1aaa0f885a..d720a53db4b4 100644 --- a/packages/core/test/unit/query-generator/create-table-query.test.ts +++ b/packages/core/test/unit/query-generator/create-table-query.test.ts @@ -17,7 +17,6 @@ describe('QueryGenerator#createTableQuery', () => { 'mariadb mysql': 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] DATE);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -29,7 +28,6 @@ describe('QueryGenerator#createTableQuery', () => { 'mariadb mysql': 'CREATE TABLE IF NOT EXISTS `MyModels` (`myColumn` DATE) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[MyModels]', 'U') IS NULL CREATE TABLE [MyModels] ([myColumn] DATE);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "MyModels" ("myColumn" DATE); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "MyModels" ("myColumn" DATE)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -42,7 +40,6 @@ describe('QueryGenerator#createTableQuery', () => { 'mariadb mysql': 'CREATE TABLE IF NOT EXISTS `MyModels` (`myColumn` DATE) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[MyModels]', 'U') IS NULL CREATE TABLE [MyModels] ([myColumn] DATE);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "MyModels" ("myColumn" DATE); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "MyModels" ("myColumn" DATE)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -59,7 +56,6 @@ describe('QueryGenerator#createTableQuery', () => { mssql: `IF OBJECT_ID(N'[mySchema].[myTable]', 'U') IS NULL CREATE TABLE [mySchema].[myTable] ([myColumn] DATE);`, sqlite3: 'CREATE TABLE IF NOT EXISTS `mySchema.myTable` (`myColumn` DATE);', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "mySchema"."myTable" ("myColumn" DATE); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "mySchema"."myTable" ("myColumn" DATE)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -75,7 +71,6 @@ describe('QueryGenerator#createTableQuery', () => { 'mariadb mysql': 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] DATE);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -91,7 +86,6 @@ describe('QueryGenerator#createTableQuery', () => { mssql: `IF OBJECT_ID(N'[mySchema].[myTable]', 'U') IS NULL CREATE TABLE [mySchema].[myTable] ([myColumn] DATE);`, sqlite3: 'CREATE TABLE IF NOT EXISTS `mySchema.myTable` (`myColumn` DATE);', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "mySchema"."myTable" ("myColumn" DATE); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "mySchema"."myTable" ("myColumn" DATE)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -121,7 +115,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE, `secondColumn` TEXT) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] DATE, [secondColumn] TEXT);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -134,7 +127,6 @@ describe('QueryGenerator#createTableQuery', () => { mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] DATE, PRIMARY KEY ([myColumn]));`, sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE PRIMARY KEY);', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, PRIMARY KEY ("myColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE,PRIMARY KEY ("myColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -153,7 +145,6 @@ describe('QueryGenerator#createTableQuery', () => { sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE NOT NULL, `secondColumn` TEXT NOT NULL, PRIMARY KEY (`myColumn`, `secondColumn`));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT, PRIMARY KEY ("myColumn", "secondColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT,PRIMARY KEY ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -170,7 +161,6 @@ describe('QueryGenerator#createTableQuery', () => { 'snowflake db2': 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE REFERENCES "Bar" ("id")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE,FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -191,7 +181,6 @@ describe('QueryGenerator#createTableQuery', () => { 'snowflake db2': 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, PRIMARY KEY ("myColumn"), FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE REFERENCES "Bar" ("id"), PRIMARY KEY ("myColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE,PRIMARY KEY ("myColumn"),FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -216,7 +205,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id") COMMENT Foo);', db2: `CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id")); -- 'Foo', TableName = "myTable", ColumnName = "myColumn";`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE REFERENCES "Bar" ("id") COMMENT Foo); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE,FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id") COMMENT Foo)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -228,7 +216,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE NOT NULL) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] DATE NOT NULL);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE NOT NULL); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE NOT NULL)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -249,7 +236,6 @@ describe('QueryGenerator#createTableQuery', () => { sqlite3: 'CREATE TABLE IF NOT EXISTS `mySchema.myTable` (`myColumn` DATE COMMENT Foo);', db2: `CREATE TABLE IF NOT EXISTS "mySchema"."myTable" ("myColumn" DATE); -- 'Foo', TableName = "mySchema"."myTable", ColumnName = "myColumn";`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "mySchema"."myTable" ("myColumn" DATE COMMENT Foo); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "mySchema"."myTable" ("myColumn" DATE COMMENT Foo)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -273,7 +259,6 @@ describe('QueryGenerator#createTableQuery', () => { @level1type = N'Table', @level1name = [myTable], @level2type = N'Column', @level2name = [secondColumn];`, db2: `CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" DATE); -- 'Foo', TableName = "myTable", ColumnName = "myColumn"; -- 'Foo Bar', TableName = "myTable", ColumnName = "secondColumn";`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE COMMENT Foo, "secondColumn" DATE COMMENT Foo Bar); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE COMMENT Foo, "secondColumn" DATE COMMENT Foo Bar)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -292,7 +277,6 @@ describe('QueryGenerator#createTableQuery', () => { @level1type = N'Table', @level1name = [myTable], @level2type = N'Column', @level2name = [myColumn];`, db2: `CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE COMMENT Foo); -- 'Bar', TableName = "myTable", ColumnName = "myColumn";`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE COMMENT Foo COMMENT Bar); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE COMMENT Foo COMMENT Bar)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -312,7 +296,6 @@ describe('QueryGenerator#createTableQuery', () => { sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` DATE COMMENT Foo PRIMARY KEY);', db2: `CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE); -- 'Foo PRIMARY KEY', TableName = "myTable", ColumnName = "myColumn";`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE COMMENT Foo, PRIMARY KEY ("myColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE COMMENT Foo,PRIMARY KEY ("myColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -345,7 +328,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" "public"."enum_myTable_myColumn");', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] ENUM("foo", "bar"));`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" ENUM("foo", "bar")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" ENUM("foo", "bar"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -363,7 +345,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER, `secondColumn` BIGINT, `thirdColumn` SMALLINT) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER, [secondColumn] BIGINT, [thirdColumn] SMALLINT);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER, "secondColumn" BIGINT, "thirdColumn" SMALLINT); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER, "secondColumn" BIGINT, "thirdColumn" SMALLINT)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -384,7 +365,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" SERIAL, "secondColumn" BIGSERIAL, "thirdColumn" SMALLSERIAL);', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER SERIAL, [secondColumn] BIGINT SERIAL, [thirdColumn] SMALLINT SERIAL);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER SERIAL, "secondColumn" BIGINT SERIAL, "thirdColumn" SMALLINT SERIAL); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER SERIAL, "secondColumn" BIGINT SERIAL, "thirdColumn" SMALLINT SERIAL)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -397,7 +377,6 @@ describe('QueryGenerator#createTableQuery', () => { postgres: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" SERIAL);', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER SERIAL NOT NULL);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER SERIAL NOT NULL); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER SERIAL NOT NULL)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -408,7 +387,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER AUTOINCREMENT) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER AUTOINCREMENT);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER AUTOINCREMENT); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER AUTOINCREMENT)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -421,7 +399,6 @@ describe('QueryGenerator#createTableQuery', () => { mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER, PRIMARY KEY ([myColumn]));`, sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER PRIMARY KEY);', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER, PRIMARY KEY ("myColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER,PRIMARY KEY ("myColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -440,7 +417,6 @@ describe('QueryGenerator#createTableQuery', () => { sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER NOT NULL, `secondColumn` TEXT NOT NULL, PRIMARY KEY (`myColumn`, `secondColumn`));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER, "secondColumn" TEXT, PRIMARY KEY ("myColumn", "secondColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER, "secondColumn" TEXT,PRIMARY KEY ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -461,7 +437,6 @@ describe('QueryGenerator#createTableQuery', () => { sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER NOT NULL, `secondColumn` INTEGER NOT NULL, `thirdColumn` TEXT NOT NULL, PRIMARY KEY (`secondColumn`, `thirdColumn`));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER NOT NULL, "secondColumn" INTEGER NOT NULL, "thirdColumn" TEXT, PRIMARY KEY ("secondColumn", "thirdColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER NOT NULL, "secondColumn" INTEGER NOT NULL, "thirdColumn" TEXT,PRIMARY KEY ("secondColumn", "thirdColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -478,7 +453,6 @@ describe('QueryGenerator#createTableQuery', () => { sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER PRIMARY KEY AUTOINCREMENT);', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER AUTOINCREMENT, PRIMARY KEY ("myColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER AUTOINCREMENT,PRIMARY KEY ("myColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -494,7 +468,6 @@ describe('QueryGenerator#createTableQuery', () => { mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER(5) UNSIGNED, PRIMARY KEY ([myColumn]));`, sqlite3: 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER PRIMARY KEY);', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER(5) UNSIGNED, PRIMARY KEY ("myColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER(5) UNSIGNED,PRIMARY KEY ("myColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -506,7 +479,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS `myTable` (`myColumn` INTEGER(5) UNSIGNED) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[myTable]', 'U') IS NULL CREATE TABLE [myTable] ([myColumn] INTEGER(5) UNSIGNED);`, ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER(5) UNSIGNED); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER(5) UNSIGNED)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -522,7 +494,6 @@ describe('QueryGenerator#createTableQuery', () => { 'snowflake db2': 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" INTEGER, FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" INTEGER REFERENCES "Bar" ("id")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" INTEGER,FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -633,7 +604,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" TEXT, UNIQUE "uniq_myTable_myColumn_secondColumn" ("myColumn", "secondColumn"));', db2: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE NOT NULL, "secondColumn" TEXT NOT NULL, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -657,7 +627,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" TEXT, UNIQUE "myIndex" ("myColumn", "secondColumn"));', db2: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE NOT NULL, "secondColumn" TEXT NOT NULL, CONSTRAINT "myIndex" UNIQUE ("myColumn", "secondColumn"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT, CONSTRAINT "myIndex" UNIQUE ("myColumn", "secondColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT, CONSTRAINT "myIndex" UNIQUE ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -681,7 +650,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, UNIQUE "uniq_myTable_myColumn" ("myColumn"));', db2: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE NOT NULL, CONSTRAINT "uniq_myTable_myColumn" UNIQUE ("myColumn"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, CONSTRAINT "uniq_myTable_myColumn" UNIQUE ("myColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE, CONSTRAINT "uniq_myTable_myColumn" UNIQUE ("myColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -705,7 +673,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" TEXT, UNIQUE "uniq_myTable_myColumn_secondColumn" ("myColumn", "secondColumn"), PRIMARY KEY ("myColumn", "secondColumn"));', db2: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" TEXT, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"), PRIMARY KEY ("myColumn", "secondColumn"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT, PRIMARY KEY ("myColumn", "secondColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE, "secondColumn" TEXT,PRIMARY KEY ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -729,7 +696,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE NOT NULL, "secondColumn" TEXT, UNIQUE "uniq_myTable_myColumn_secondColumn" ("myColumn", "secondColumn"));', db2: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE NOT NULL, "secondColumn" TEXT NOT NULL, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE NOT NULL, "secondColumn" TEXT, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE NOT NULL, "secondColumn" TEXT, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -753,7 +719,6 @@ describe('QueryGenerator#createTableQuery', () => { 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" TEXT, UNIQUE "uniq_myTable_myColumn_secondColumn" ("myColumn", "secondColumn"), PRIMARY KEY ("myColumn"), FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"));', db2: 'CREATE TABLE IF NOT EXISTS "myTable" ("myColumn" DATE, "secondColumn" TEXT NOT NULL, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"), PRIMARY KEY ("myColumn"), FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "myTable" ("myColumn" DATE REFERENCES "Bar" ("id"), "secondColumn" TEXT, CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"), PRIMARY KEY ("myColumn")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "myTable" ("myColumn" DATE , "secondColumn" TEXT,PRIMARY KEY ("myColumn"),FOREIGN KEY ("myColumn") REFERENCES "Bar" ("id"), CONSTRAINT "uniq_myTable_myColumn_secondColumn" UNIQUE ("myColumn", "secondColumn"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); diff --git a/packages/core/test/unit/query-generator/describe-table-query.test.ts b/packages/core/test/unit/query-generator/describe-table-query.test.ts index 6b068f7594bd..84ab12a60bc2 100644 --- a/packages/core/test/unit/query-generator/describe-table-query.test.ts +++ b/packages/core/test/unit/query-generator/describe-table-query.test.ts @@ -75,10 +75,6 @@ describe('QueryGenerator#describeTableQuery', () => { ON QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME WHERE QSYS2.SYSCOLUMNS.TABLE_SCHEMA = CURRENT SCHEMA AND QSYS2.SYSCOLUMNS.TABLE_NAME = 'myTable'`, - oracle: `SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type FROM all_tab_columns atc - LEFT OUTER JOIN (SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc - INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) - WHERE (atc.OWNER = '${dialect.getDefaultSchema()}') AND (atc.TABLE_NAME = 'myTable')ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC`, }); }); @@ -154,10 +150,6 @@ describe('QueryGenerator#describeTableQuery', () => { ON QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME WHERE QSYS2.SYSCOLUMNS.TABLE_SCHEMA = CURRENT SCHEMA AND QSYS2.SYSCOLUMNS.TABLE_NAME = 'MyModels'`, - oracle: `SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type FROM all_tab_columns atc - LEFT OUTER JOIN (SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc - INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) - WHERE (atc.OWNER = '${dialect.getDefaultSchema()}') AND (atc.TABLE_NAME = 'MyModels')ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC`, }); }); @@ -234,11 +226,6 @@ describe('QueryGenerator#describeTableQuery', () => { ON QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME WHERE QSYS2.SYSCOLUMNS.TABLE_SCHEMA = CURRENT SCHEMA AND QSYS2.SYSCOLUMNS.TABLE_NAME = 'MyModels'`, - oracle: `SELECT - atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type - FROM all_tab_columns atc - LEFT OUTER JOIN (SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc - ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) WHERE (atc.OWNER = '${dialect.getDefaultSchema()}') AND (atc.TABLE_NAME = 'MyModels')ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC`, }); }); @@ -312,10 +299,6 @@ describe('QueryGenerator#describeTableQuery', () => { ON QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME WHERE QSYS2.SYSCOLUMNS.TABLE_SCHEMA = 'mySchema' AND QSYS2.SYSCOLUMNS.TABLE_NAME = 'myTable'`, - oracle: `SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type FROM all_tab_columns atc - LEFT OUTER JOIN (SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc - INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) - WHERE (atc.OWNER = 'mySchema') AND (atc.TABLE_NAME = 'myTable')ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC`, }, ); }); @@ -395,10 +378,6 @@ describe('QueryGenerator#describeTableQuery', () => { ON QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME WHERE QSYS2.SYSCOLUMNS.TABLE_SCHEMA = CURRENT SCHEMA AND QSYS2.SYSCOLUMNS.TABLE_NAME = 'myTable'`, - oracle: `SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type FROM all_tab_columns atc - LEFT OUTER JOIN (SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc - INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) - WHERE (atc.OWNER = '${dialect.getDefaultSchema()}') AND (atc.TABLE_NAME = 'myTable')ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC`, }, ); }); @@ -476,10 +455,6 @@ describe('QueryGenerator#describeTableQuery', () => { ON QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME WHERE QSYS2.SYSCOLUMNS.TABLE_SCHEMA = 'mySchema' AND QSYS2.SYSCOLUMNS.TABLE_NAME = 'myTable'`, - oracle: `SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type FROM all_tab_columns atc - LEFT OUTER JOIN (SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc - INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) - WHERE (atc.OWNER = 'mySchema') AND (atc.TABLE_NAME = 'myTable')ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC`, }); }); diff --git a/packages/core/test/unit/query-generator/drop-schema-query.test.ts b/packages/core/test/unit/query-generator/drop-schema-query.test.ts index ec2bb90467b9..12c5623df622 100644 --- a/packages/core/test/unit/query-generator/drop-schema-query.test.ts +++ b/packages/core/test/unit/query-generator/drop-schema-query.test.ts @@ -13,7 +13,6 @@ describe('QueryGenerator#dropSchemaQuery', () => { default: 'DROP SCHEMA [mySchema]', db2: 'DROP SCHEMA "mySchema" RESTRICT', sqlite3: notSupportedError, - oracle: `BEGIN EXECUTE IMMEDIATE 'DROP USER "mySchema" CASCADE' ; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1918 THEN RAISE; END IF; END;`, }); }); @@ -22,7 +21,6 @@ describe('QueryGenerator#dropSchemaQuery', () => { default: 'DROP SCHEMA IF EXISTS [mySchema]', 'db2 mssql': buildInvalidOptionReceivedError('dropSchemaQuery', dialectName, ['ifExists']), sqlite3: notSupportedError, - oracle: `BEGIN EXECUTE IMMEDIATE 'DROP USER "mySchema" CASCADE' ; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1918 THEN RAISE; END IF; END;`, }); }); @@ -33,7 +31,6 @@ describe('QueryGenerator#dropSchemaQuery', () => { 'cascade', ]), sqlite3: notSupportedError, - oracle: `BEGIN EXECUTE IMMEDIATE 'DROP USER "mySchema" CASCADE' ; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1918 THEN RAISE; END IF; END;`, }); }); @@ -46,7 +43,6 @@ describe('QueryGenerator#dropSchemaQuery', () => { ]), 'mariadb mysql': buildInvalidOptionReceivedError('dropSchemaQuery', dialectName, ['cascade']), sqlite3: notSupportedError, - oracle: `BEGIN EXECUTE IMMEDIATE 'DROP USER "mySchema" CASCADE' ; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1918 THEN RAISE; END IF; END;`, }); }); }); diff --git a/packages/core/test/unit/query-generator/drop-table-query.test.ts b/packages/core/test/unit/query-generator/drop-table-query.test.ts index b32fbb1df4b3..de34dd6df782 100644 --- a/packages/core/test/unit/query-generator/drop-table-query.test.ts +++ b/packages/core/test/unit/query-generator/drop-table-query.test.ts @@ -10,7 +10,6 @@ describe('QueryGenerator#dropTableQuery', () => { it('produces a query that drops a table', () => { expectsql(() => queryGenerator.dropTableQuery('myTable'), { default: `DROP TABLE IF EXISTS [myTable]`, - oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "myTable" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); }); @@ -18,7 +17,6 @@ describe('QueryGenerator#dropTableQuery', () => { expectsql(() => queryGenerator.dropTableQuery('myTable', { cascade: true }), { default: buildInvalidOptionReceivedError('dropTableQuery', dialectName, ['cascade']), 'postgres snowflake': `DROP TABLE IF EXISTS "myTable" CASCADE`, - oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "myTable" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); }); @@ -27,7 +25,6 @@ describe('QueryGenerator#dropTableQuery', () => { expectsql(() => queryGenerator.dropTableQuery(MyModel), { default: `DROP TABLE IF EXISTS [MyModels]`, - oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "MyModels" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); }); @@ -37,7 +34,6 @@ describe('QueryGenerator#dropTableQuery', () => { expectsql(() => queryGenerator.dropTableQuery(myDefinition), { default: `DROP TABLE IF EXISTS [MyModels]`, - oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "MyModels" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); }); @@ -45,7 +41,6 @@ describe('QueryGenerator#dropTableQuery', () => { expectsql(() => queryGenerator.dropTableQuery({ tableName: 'myTable', schema: 'mySchema' }), { default: `DROP TABLE IF EXISTS [mySchema].[myTable]`, sqlite3: 'DROP TABLE IF EXISTS `mySchema.myTable`', - oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "mySchema"."myTable" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); }); @@ -55,7 +50,6 @@ describe('QueryGenerator#dropTableQuery', () => { queryGenerator.dropTableQuery({ tableName: 'myTable', schema: dialect.getDefaultSchema() }), { default: `DROP TABLE IF EXISTS [myTable]`, - oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "myTable" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }, ); }); @@ -67,7 +61,6 @@ describe('QueryGenerator#dropTableQuery', () => { expectsql(() => queryGeneratorSchema.dropTableQuery('myTable'), { default: `DROP TABLE IF EXISTS [mySchema].[myTable]`, sqlite3: 'DROP TABLE IF EXISTS `mySchema.myTable`', - oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "mySchema"."myTable" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); }); diff --git a/packages/core/test/unit/query-generator/get-constraint-snippet.test.ts b/packages/core/test/unit/query-generator/get-constraint-snippet.test.ts index 1c780e17bb87..64af232085bb 100644 --- a/packages/core/test/unit/query-generator/get-constraint-snippet.test.ts +++ b/packages/core/test/unit/query-generator/get-constraint-snippet.test.ts @@ -533,7 +533,7 @@ describe('QueryGeneratorInternal#getConstraintSnippet', () => { }), { default: `CONSTRAINT [myTable_otherId_otherTable_fk] FOREIGN KEY ([otherId]) REFERENCES [otherTable] ([id]) ON UPDATE CASCADE`, - 'db2 ibmi oracle': onUpdateNotSupportedError, + 'db2 ibmi': onUpdateNotSupportedError, }, ); }); diff --git a/packages/core/test/unit/query-generator/insert-query.test.ts b/packages/core/test/unit/query-generator/insert-query.test.ts index 308801ef9b0e..465e9276d9ed 100644 --- a/packages/core/test/unit/query-generator/insert-query.test.ts +++ b/packages/core/test/unit/query-generator/insert-query.test.ts @@ -4,7 +4,6 @@ import { beforeAll2, expectsql, sequelize } from '../../support'; describe('QueryGenerator#insertQuery', () => { const queryGenerator = sequelize.queryGenerator; - const dialect = sequelize.dialect; const vars = beforeAll2(() => { const User = sequelize.define( @@ -57,7 +56,6 @@ describe('QueryGenerator#insertQuery', () => { default: `INSERT INTO [Users] ([firstName],[lastName],[username]) VALUES ($sequelize_1,$lastName,$sequelize_2);`, db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName","username") VALUES ($sequelize_1,$lastName,$sequelize_2));`, ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName","username") VALUES ($sequelize_1,$lastName,$sequelize_2))`, - oracle: `INSERT INTO "Users" ("firstName","lastName","username") VALUES (:1,$lastName,:2);`, }); expect(bind).to.deep.eq({ @@ -80,7 +78,6 @@ describe('QueryGenerator#insertQuery', () => { default: `INSERT INTO [Users] ([firstName],[lastName],[username]) VALUES ($sequelize_1,$1,$sequelize_2);`, db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName","username") VALUES ($sequelize_1,$1,$sequelize_2));`, ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName","username") VALUES ($sequelize_1,$1,$sequelize_2))`, - oracle: `INSERT INTO "Users" ("firstName","lastName","username") VALUES (:1,$1,:2);`, }); expect(bind).to.deep.eq({ sequelize_1: 'John', @@ -160,12 +157,10 @@ describe('QueryGenerator#insertQuery', () => { 'INSERT INTO [Users] ([firstName]) OUTPUT INSERTED.[id], INSERTED.[firstName] VALUES ($sequelize_1);', db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES ($sequelize_1));', ibmi: 'SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES ($sequelize_1))', - oracle: `INSERT INTO "Users" ("firstName") VALUES (:1) RETURNING "id", "firstName" INTO :2,:3;`, }); }); - // node-oracledb requires OUTBIND definition, RETURNING '*' isn't valid for oracle. - (dialect.name === 'oracle' ? it.skip : it)('supports array of strings (column names)', () => { + it('supports array of strings (column names)', () => { const { User } = vars; const { query } = queryGenerator.insertQuery( @@ -193,8 +188,7 @@ describe('QueryGenerator#insertQuery', () => { }); }); - // node-oracledb requires OUTBIND definition, '*' isn't valid for oracle. - (dialect.name === 'oracle' ? it.skip : it)('supports array of literals', () => { + it('supports array of literals', () => { const { User } = vars; expectsql( @@ -235,7 +229,6 @@ describe('QueryGenerator#insertQuery', () => { default: 'INSERT INTO [myTable] ([birthday]) VALUES ($sequelize_1);', 'db2 ibmi': 'SELECT * FROM FINAL TABLE (INSERT INTO "myTable" ("birthday") VALUES ($sequelize_1));', - oracle: `INSERT INTO "myTable" ("birthday") VALUES (:1);`, }, bind: { mysql: { @@ -262,9 +255,6 @@ describe('QueryGenerator#insertQuery', () => { mssql: { sequelize_1: '2011-03-27 10:01:55.000 +00:00', }, - oracle: { - sequelize_1: new Date('2011-03-27T10:01:55Z'), - }, }, }); }); @@ -277,7 +267,6 @@ describe('QueryGenerator#insertQuery', () => { 'INSERT INTO [myTable] ([positive],[negative]) VALUES ($sequelize_1,$sequelize_2);', 'db2 ibmi': 'SELECT * FROM FINAL TABLE (INSERT INTO "myTable" ("positive","negative") VALUES ($sequelize_1,$sequelize_2));', - oracle: `INSERT INTO "myTable" ("positive","negative") VALUES (:1,:2);`, }, bind: { sqlite3: { @@ -312,10 +301,6 @@ describe('QueryGenerator#insertQuery', () => { sequelize_1: true, sequelize_2: false, }, - oracle: { - sequelize_1: '1', - sequelize_2: '0', - }, }, }); }); @@ -330,7 +315,6 @@ describe('QueryGenerator#insertQuery', () => { default: 'INSERT INTO [myTable] ([value],[name]) VALUES ($sequelize_1,$sequelize_2);', 'db2 ibmi': 'SELECT * FROM FINAL TABLE (INSERT INTO "myTable" ("value","name") VALUES ($sequelize_1,$sequelize_2));', - oracle: `INSERT INTO "myTable" ("value","name") VALUES (:1,:2);`, }); expect(bind).to.deep.eq({ diff --git a/packages/core/test/unit/query-generator/json-path-extraction-query.test.ts b/packages/core/test/unit/query-generator/json-path-extraction-query.test.ts index 632df98eea13..7edfea4feed6 100644 --- a/packages/core/test/unit/query-generator/json-path-extraction-query.test.ts +++ b/packages/core/test/unit/query-generator/json-path-extraction-query.test.ts @@ -24,7 +24,6 @@ describe('QueryGenerator#jsonPathExtractionQuery', () => { mariadb: `json_compact(json_extract(\`profile\`,'$.id'))`, 'mysql sqlite3': `json_extract(\`profile\`,'$.id')`, postgres: `"profile"->'id'`, - oracle: `json_value("profile",'$."id"')`, }, ); }); @@ -42,7 +41,6 @@ describe('QueryGenerator#jsonPathExtractionQuery', () => { mariadb: `json_compact(json_extract(\`profile\`,'$[0]'))`, 'mysql sqlite3': `json_extract(\`profile\`,'$[0]')`, postgres: `"profile"->0`, - oracle: `json_value("profile",'$[0]')`, }, ); }); @@ -60,7 +58,6 @@ describe('QueryGenerator#jsonPathExtractionQuery', () => { mariadb: `json_compact(json_extract(\`profile\`,'$.id.username[0]."0".name'))`, 'mysql sqlite3': `json_extract(\`profile\`,'$.id.username[0]."0".name')`, postgres: `"profile"#>ARRAY['id','username','0','0','name']::VARCHAR(255)[]`, - oracle: `json_value("profile",'$."id"."username"[0][0]."name"')`, }, ); }); @@ -79,7 +76,6 @@ describe('QueryGenerator#jsonPathExtractionQuery', () => { mariadb: `json_compact(json_extract(\`profile\`,'$."\\\\""."\\'"."$"'))`, sqlite3: `json_extract(\`profile\`,'$."\\""."''"."$"')`, postgres: `"profile"#>ARRAY['"','''','$']::VARCHAR(255)[]`, - oracle: `json_value("profile",'$.""."''"."$"')`, }, ); }); diff --git a/packages/core/test/unit/query-generator/list-schemas-query.test.ts b/packages/core/test/unit/query-generator/list-schemas-query.test.ts index 218006362fd4..c63ae40a7753 100644 --- a/packages/core/test/unit/query-generator/list-schemas-query.test.ts +++ b/packages/core/test/unit/query-generator/list-schemas-query.test.ts @@ -17,7 +17,6 @@ describe('QueryGenerator#listSchemasQuery', () => { sqlite3: notSupportedError, postgres: `SELECT schema_name AS "schema" FROM information_schema.schemata WHERE schema_name !~ E'^pg_' AND schema_name NOT IN ('public', 'information_schema', 'tiger', 'tiger_data', 'topology')`, snowflake: `SELECT SCHEMA_NAME AS "schema" FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('INFORMATION_SCHEMA', 'PERFORMANCE_SCHEMA', 'SYS', 'information_schema', 'performance_schema', 'sys')`, - oracle: `SELECT USERNAME AS "schema" FROM ALL_USERS WHERE COMMON = ('NO') AND USERNAME != user`, }); }); @@ -31,7 +30,6 @@ describe('QueryGenerator#listSchemasQuery', () => { sqlite3: notSupportedError, postgres: `SELECT schema_name AS "schema" FROM information_schema.schemata WHERE schema_name !~ E'^pg_' AND schema_name NOT IN ('public', 'information_schema', 'tiger', 'tiger_data', 'topology', 'test', 'Te''st2')`, snowflake: `SELECT SCHEMA_NAME AS "schema" FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('INFORMATION_SCHEMA', 'PERFORMANCE_SCHEMA', 'SYS', 'information_schema', 'performance_schema', 'sys', 'test', 'Te''st2')`, - oracle: `SELECT USERNAME AS "schema" FROM ALL_USERS WHERE COMMON = ('NO') AND USERNAME != user`, }); }); }); diff --git a/packages/core/test/unit/query-generator/list-tables-query.test.ts b/packages/core/test/unit/query-generator/list-tables-query.test.ts index ae1397e915a1..536e5a7fba0a 100644 --- a/packages/core/test/unit/query-generator/list-tables-query.test.ts +++ b/packages/core/test/unit/query-generator/list-tables-query.test.ts @@ -14,7 +14,6 @@ describe('QueryGenerator#listTablesQuery', () => { mariadb: `SELECT TABLE_NAME AS \`tableName\`, TABLE_SCHEMA AS \`schema\` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA NOT IN ('MYSQL', 'INFORMATION_SCHEMA', 'PERFORMANCE_SCHEMA', 'SYS', 'mysql', 'information_schema', 'performance_schema', 'sys') ORDER BY TABLE_SCHEMA, TABLE_NAME`, postgres: `SELECT table_name AS "tableName", table_schema AS "schema" FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_name != 'spatial_ref_sys' AND table_schema !~ E'^pg_' AND table_schema NOT IN ('information_schema', 'tiger', 'tiger_data', 'topology') ORDER BY table_schema, table_name`, snowflake: `SELECT TABLE_NAME AS "tableName", TABLE_SCHEMA AS "schema" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA NOT IN ('INFORMATION_SCHEMA', 'PERFORMANCE_SCHEMA', 'SYS', 'information_schema', 'performance_schema', 'sys') ORDER BY TABLE_SCHEMA, TABLE_NAME`, - oracle: `SELECT owner as "schema", table_name as "tableName" FROM all_tables where OWNER IN(SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE ORACLE_MAINTAINED = 'N')`, }); }); @@ -28,7 +27,6 @@ describe('QueryGenerator#listTablesQuery', () => { mariadb: `SELECT TABLE_NAME AS \`tableName\`, TABLE_SCHEMA AS \`schema\` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = 'mySchema' ORDER BY TABLE_SCHEMA, TABLE_NAME`, postgres: `SELECT table_name AS "tableName", table_schema AS "schema" FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_name != 'spatial_ref_sys' AND table_schema = 'mySchema' ORDER BY table_schema, table_name`, snowflake: `SELECT TABLE_NAME AS "tableName", TABLE_SCHEMA AS "schema" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = 'mySchema' ORDER BY TABLE_SCHEMA, TABLE_NAME`, - oracle: `SELECT owner as "schema", table_name as "tableName" FROM all_tables where OWNER IN(SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE ORACLE_MAINTAINED = 'N' AND USERNAME='mySchema')`, }); }); @@ -44,7 +42,6 @@ describe('QueryGenerator#listTablesQuery', () => { mariadb: `SELECT TABLE_NAME AS \`tableName\`, TABLE_SCHEMA AS \`schema\` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = 'sequelize_test' ORDER BY TABLE_SCHEMA, TABLE_NAME`, postgres: `SELECT table_name AS "tableName", table_schema AS "schema" FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_name != 'spatial_ref_sys' AND table_schema = 'public' ORDER BY table_schema, table_name`, snowflake: `SELECT TABLE_NAME AS "tableName", TABLE_SCHEMA AS "schema" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = 'PUBLIC' ORDER BY TABLE_SCHEMA, TABLE_NAME`, - oracle: `SELECT owner as "schema", table_name as "tableName" FROM all_tables where OWNER IN(SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE ORACLE_MAINTAINED = 'N' AND USERNAME='${sequelize.dialect.getDefaultSchema()}')`, }, ); }); diff --git a/packages/core/test/unit/query-generator/remove-constraint-query.test.ts b/packages/core/test/unit/query-generator/remove-constraint-query.test.ts index 6040b5fac409..fc556e7563f4 100644 --- a/packages/core/test/unit/query-generator/remove-constraint-query.test.ts +++ b/packages/core/test/unit/query-generator/remove-constraint-query.test.ts @@ -27,9 +27,6 @@ describe('QueryGenerator#removeConstraintQuery', () => { dialect.name, ['ifExists'], ), - oracle: buildInvalidOptionReceivedError('removeConstraintQuery', dialect.name, [ - 'ifExists', - ]), }, ); }); @@ -62,7 +59,6 @@ describe('QueryGenerator#removeConstraintQuery', () => { snowflake: buildInvalidOptionReceivedError('removeConstraintQuery', dialect.name, [ 'ifExists', ]), - oracle: buildInvalidOptionReceivedError('removeConstraintQuery', dialect.name, ['cascade']), sqlite3: notSupportedError, }, ); diff --git a/packages/core/test/unit/query-generator/remove-index-query.test.ts b/packages/core/test/unit/query-generator/remove-index-query.test.ts index da50f1e2f5b9..8e28f0374c72 100644 --- a/packages/core/test/unit/query-generator/remove-index-query.test.ts +++ b/packages/core/test/unit/query-generator/remove-index-query.test.ts @@ -15,7 +15,7 @@ describe('QueryGenerator#removeIndexQuery', () => { default: `DROP INDEX [user_foo_bar] ON [myTable]`, sqlite3: 'DROP INDEX `user_foo_bar`', ibmi: `BEGIN DROP INDEX "user_foo_bar"; COMMIT; END`, - 'db2 oracle': `DROP INDEX "user_foo_bar"`, + db2: `DROP INDEX "user_foo_bar"`, postgres: `DROP INDEX "public"."user_foo_bar"`, snowflake: notImplementedError, }); @@ -26,7 +26,7 @@ describe('QueryGenerator#removeIndexQuery', () => { default: `DROP INDEX [my_table_foo_bar] ON [myTable]`, sqlite3: 'DROP INDEX `my_table_foo_bar`', ibmi: `BEGIN DROP INDEX "my_table_foo_bar"; COMMIT; END`, - 'db2 oracle': `DROP INDEX "my_table_foo_bar"`, + db2: `DROP INDEX "my_table_foo_bar"`, postgres: `DROP INDEX "public"."my_table_foo_bar"`, snowflake: notImplementedError, }); @@ -54,7 +54,7 @@ describe('QueryGenerator#removeIndexQuery', () => { postgres: `DROP INDEX IF EXISTS "public"."user_foo_bar"`, ibmi: `BEGIN IF EXISTS (SELECT * FROM QSYS2.SYSINDEXES WHERE INDEX_NAME = "user_foo_bar") THEN DROP INDEX "user_foo_bar"; COMMIT; END IF; END`, snowflake: notImplementedError, - 'db2 mysql oracle': buildInvalidOptionReceivedError('removeIndexQuery', dialect.name, [ + 'db2 mysql': buildInvalidOptionReceivedError('removeIndexQuery', dialect.name, [ 'ifExists', ]), }, @@ -80,7 +80,7 @@ describe('QueryGenerator#removeIndexQuery', () => { default: `DROP INDEX IF EXISTS [user_foo_bar] ON [myTable] CASCADE`, postgres: `DROP INDEX IF EXISTS "public"."user_foo_bar" CASCADE`, snowflake: notImplementedError, - 'db2 mysql oracle': buildInvalidOptionReceivedError('removeIndexQuery', dialect.name, [ + 'db2 mysql': buildInvalidOptionReceivedError('removeIndexQuery', dialect.name, [ 'cascade', 'ifExists', ]), @@ -104,7 +104,7 @@ describe('QueryGenerator#removeIndexQuery', () => { default: `DROP INDEX CONCURRENTLY IF EXISTS [user_foo_bar] ON [myTable]`, postgres: `DROP INDEX CONCURRENTLY IF EXISTS "public"."user_foo_bar"`, snowflake: notImplementedError, - 'db2 mysql oracle': buildInvalidOptionReceivedError('removeIndexQuery', dialect.name, [ + 'db2 mysql': buildInvalidOptionReceivedError('removeIndexQuery', dialect.name, [ 'concurrently', 'ifExists', ]), @@ -144,7 +144,7 @@ describe('QueryGenerator#removeIndexQuery', () => { default: `DROP INDEX [user_foo_bar] ON [MyModels]`, sqlite3: 'DROP INDEX `user_foo_bar`', ibmi: `BEGIN DROP INDEX "user_foo_bar"; COMMIT; END`, - 'db2 oracle': `DROP INDEX "user_foo_bar"`, + db2: `DROP INDEX "user_foo_bar"`, postgres: `DROP INDEX "public"."user_foo_bar"`, snowflake: notImplementedError, }); @@ -161,7 +161,6 @@ describe('QueryGenerator#removeIndexQuery', () => { db2: `DROP INDEX "user_foo_bar"`, postgres: `DROP INDEX "public"."user_foo_bar"`, snowflake: notImplementedError, - oracle: `DROP INDEX "user_foo_bar"`, }); }); @@ -177,7 +176,7 @@ describe('QueryGenerator#removeIndexQuery', () => { sqlite3: 'DROP INDEX `user_foo_bar`', postgres: `DROP INDEX "mySchema"."user_foo_bar"`, ibmi: `BEGIN DROP INDEX "user_foo_bar"; COMMIT; END`, - 'db2 oracle': `DROP INDEX "user_foo_bar"`, + db2: `DROP INDEX "user_foo_bar"`, snowflake: notImplementedError, }, ); @@ -194,7 +193,7 @@ describe('QueryGenerator#removeIndexQuery', () => { default: `DROP INDEX [user_foo_bar] ON [myTable]`, sqlite3: 'DROP INDEX `user_foo_bar`', ibmi: `BEGIN DROP INDEX "user_foo_bar"; COMMIT; END`, - 'db2 oracle': `DROP INDEX "user_foo_bar"`, + db2: `DROP INDEX "user_foo_bar"`, postgres: `DROP INDEX "public"."user_foo_bar"`, snowflake: notImplementedError, }, @@ -210,7 +209,7 @@ describe('QueryGenerator#removeIndexQuery', () => { sqlite3: 'DROP INDEX `user_foo_bar`', postgres: `DROP INDEX "mySchema"."user_foo_bar"`, ibmi: `BEGIN DROP INDEX "user_foo_bar"; COMMIT; END`, - 'db2 oracle': 'DROP INDEX "user_foo_bar"', + db2: 'DROP INDEX "user_foo_bar"', snowflake: notImplementedError, }); }); diff --git a/packages/core/test/unit/query-generator/rename-table-query.test.ts b/packages/core/test/unit/query-generator/rename-table-query.test.ts index 32e0ce9cd669..312652f14d16 100644 --- a/packages/core/test/unit/query-generator/rename-table-query.test.ts +++ b/packages/core/test/unit/query-generator/rename-table-query.test.ts @@ -56,7 +56,7 @@ describe('QueryGenerator#renameTableQuery', () => { ), { default: changeSchemaNotSetError, - 'db2 ibmi oracle': moveSchemaNotSupportedError, + 'db2 ibmi': moveSchemaNotSupportedError, }, ); }); @@ -74,7 +74,7 @@ describe('QueryGenerator#renameTableQuery', () => { mssql: `ALTER SCHEMA [newSchema] TRANSFER [oldSchema].[oldTable]`, sqlite3: 'ALTER TABLE `oldSchema.oldTable` RENAME TO `newSchema.oldTable`', postgres: `ALTER TABLE "oldSchema"."oldTable" SET SCHEMA "newSchema"`, - 'db2 ibmi oracle': buildInvalidOptionReceivedError('renameTableQuery', dialect.name, [ + 'db2 ibmi': buildInvalidOptionReceivedError('renameTableQuery', dialect.name, [ 'changeSchema', ]), }, @@ -92,7 +92,7 @@ describe('QueryGenerator#renameTableQuery', () => { { default: 'ALTER TABLE [oldSchema].[oldTable] RENAME TO [newSchema].[newTable]', sqlite3: 'ALTER TABLE `oldSchema.oldTable` RENAME TO `newSchema.newTable`', - 'db2 ibmi oracle': buildInvalidOptionReceivedError('renameTableQuery', dialect.name, [ + 'db2 ibmi': buildInvalidOptionReceivedError('renameTableQuery', dialect.name, [ 'changeSchema', ]), 'mssql postgres': moveSchemaWithRenameNotSupportedError, diff --git a/packages/core/test/unit/query-generator/rollback-transaction-query.test.ts b/packages/core/test/unit/query-generator/rollback-transaction-query.test.ts index b0e9b894d819..a69f3132d9a2 100644 --- a/packages/core/test/unit/query-generator/rollback-transaction-query.test.ts +++ b/packages/core/test/unit/query-generator/rollback-transaction-query.test.ts @@ -12,7 +12,6 @@ describe('QueryGenerator#rollbackTransactionQuery', () => { expectsql(() => queryGenerator.rollbackTransactionQuery(), { default: 'ROLLBACK', 'db2 ibmi mssql': notSupportedError, - oracle: 'ROLLBACK TRANSACTION', }); }); }); diff --git a/packages/core/test/unit/query-generator/select-query.test.ts b/packages/core/test/unit/query-generator/select-query.test.ts index f94dd289f579..2f7dd5a25c21 100644 --- a/packages/core/test/unit/query-generator/select-query.test.ts +++ b/packages/core/test/unit/query-generator/select-query.test.ts @@ -90,7 +90,6 @@ describe('QueryGenerator#selectQuery', () => { 'mariadb mysql': 'SELECT `id` FROM `Users` AS `User` ORDER BY `User`.`id` LIMIT 18446744073709551615 OFFSET 1;', 'db2 ibmi mssql': `SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] OFFSET 1 ROWS;`, - oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id" OFFSET 1 ROWS;`, }); }); @@ -111,7 +110,6 @@ describe('QueryGenerator#selectQuery', () => { default: 'SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] LIMIT 10;', mssql: `SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;`, 'db2 ibmi': `SELECT "id" FROM "Users" AS "User" ORDER BY "User"."id" FETCH NEXT 10 ROWS ONLY;`, - oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id" OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;`, }); }); @@ -132,7 +130,6 @@ describe('QueryGenerator#selectQuery', () => { expectsql(sql, { default: 'SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] LIMIT 10 OFFSET 1;', 'db2 ibmi mssql': `SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] OFFSET 1 ROWS FETCH NEXT 10 ROWS ONLY;`, - oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id" OFFSET 1 ROWS FETCH NEXT 10 ROWS ONLY;`, }); }); @@ -154,7 +151,6 @@ describe('QueryGenerator#selectQuery', () => { default: `SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] LIMIT 10;`, mssql: `SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;`, 'db2 ibmi': `SELECT "id" FROM "Users" AS "User" ORDER BY "User"."id" FETCH NEXT 10 ROWS ONLY;`, - oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id" OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;`, }); }); @@ -173,7 +169,6 @@ describe('QueryGenerator#selectQuery', () => { expectsql(sql, { default: `SELECT [id] FROM [Users] AS [User];`, - oracle: `SELECT "id" FROM "Users" "User";`, }); }); @@ -195,7 +190,6 @@ describe('QueryGenerator#selectQuery', () => { default: `SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] LIMIT 0;`, mssql: new Error(`LIMIT 0 is not supported by ${dialectName} dialect.`), 'db2 ibmi': `SELECT "id" FROM "Users" AS "User" ORDER BY "User"."id" FETCH NEXT 0 ROWS ONLY;`, - oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id";`, }, ); }); @@ -220,7 +214,6 @@ describe('QueryGenerator#selectQuery', () => { 'db2 ibmi': `SELECT "id" FROM "Users" AS "User" ORDER BY "User"."id" FETCH NEXT ''';DELETE FROM user' ROWS ONLY;`, 'mariadb mysql': "SELECT `id` FROM `Users` AS `User` ORDER BY `User`.`id` LIMIT '\\';DELETE FROM user';", - oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id" OFFSET 0 ROWS FETCH NEXT ''';DELETE FROM user' ROWS ONLY;`, }); }); @@ -245,7 +238,6 @@ describe('QueryGenerator#selectQuery', () => { 'db2 ibmi': `SELECT "id" FROM "Users" AS "User" ORDER BY "User"."id" OFFSET ''';DELETE FROM user' ROWS FETCH NEXT 10 ROWS ONLY;`, 'mariadb mysql': "SELECT `id` FROM `Users` AS `User` ORDER BY `User`.`id` LIMIT 10 OFFSET '\\';DELETE FROM user';", - oracle: `SELECT "id" FROM "Users" "User" ORDER BY "User"."id" OFFSET ''';DELETE FROM user' ROWS FETCH NEXT 10 ROWS ONLY;`, }); }); }); @@ -267,7 +259,6 @@ describe('QueryGenerator#selectQuery', () => { expectsql(sql, { default: `SELECT [id] FROM [Projects] AS [Project] WHERE [Project].[duration] = 9007199254740993;`, - oracle: `SELECT "id" FROM "Projects" "Project" WHERE "Project"."duration" = 9007199254740993;`, }); }); @@ -285,7 +276,6 @@ describe('QueryGenerator#selectQuery', () => { expectsql(sql, { default: `SELECT [id], CAST([createdAt] AS VARCHAR) AS [createdAt] FROM [Users] AS [User];`, - oracle: `SELECT "id", CAST("createdAt" AS VARCHAR) AS "createdAt" FROM "Users" "User";`, }); }); @@ -304,7 +294,6 @@ describe('QueryGenerator#selectQuery', () => { expectsql(sql, { default: `SELECT [id] FROM [Users] AS [User];`, - oracle: `SELECT "id" FROM "Users" "User";`, }); }); @@ -325,7 +314,6 @@ describe('QueryGenerator#selectQuery', () => { default: `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = 'foo'';DROP TABLE mySchema.myTable;';`, 'mysql mariadb': `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = 'foo\\';DROP TABLE mySchema.myTable;';`, mssql: `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = N'foo'';DROP TABLE mySchema.myTable;';`, - oracle: `SELECT "id" FROM "Users" "User" WHERE "User"."username" = 'foo'';DROP TABLE mySchema.myTable;';`, }); }); @@ -349,7 +337,6 @@ describe('QueryGenerator#selectQuery', () => { postgres: `SELECT "data"->'email' AS "email" FROM "Users" AS "User";`, mariadb: `SELECT json_compact(json_extract(\`data\`,'$.email')) AS \`email\` FROM \`Users\` AS \`User\`;`, 'sqlite3 mysql': `SELECT json_extract([data],'$.email') AS [email] FROM [Users] AS [User];`, - oracle: `SELECT json_value("data",'$."email"') AS "email" FROM "Users" "User";`, }); }); } @@ -424,16 +411,6 @@ describe('QueryGenerator#selectQuery', () => { OFFSET 'repl4' ROWS FETCH NEXT 'repl3' ROWS ONLY; `, - oracle: ` - SELECT uppercase('id') AS "id", 'id2' - FROM "Users" "User" - WHERE "User"."username" = 'repl1' OR "User"."username" = (uppercase(CAST('repl1' AS STRING)) = 'repl1') - GROUP BY 'the group' - HAVING "User"."username" = 'repl1' - ORDER BY 'repl2' - OFFSET 'repl4' ROWS - FETCH NEXT 'repl3' ROWS ONLY; - `, }); }); @@ -458,7 +435,6 @@ describe('QueryGenerator#selectQuery', () => { expectsql(sql, { default: `SELECT id FROM [Users] AS [User] WHERE id = ':id';`, - oracle: `SELECT id FROM "Users" "User" WHERE id = ':id';`, }); }); @@ -540,19 +516,6 @@ describe('QueryGenerator#selectQuery', () => { LEFT OUTER JOIN "Users" AS "projects->owner" ON "projects"."ownerId" = "projects->owner"."id" `, - oracle: ` - SELECT - "User"."id", - "projects"."id" AS "projects.id", - 'repl1', 'repl1' AS "projects.id2", - "projects->owner"."id" AS "projects.owner.id", - 'repl2' - FROM "Users" "User" - INNER JOIN "Projects" "projects" - ON 'on' AND 'where' - LEFT OUTER JOIN "Users" "projects->owner" - ON "projects"."ownerId" = "projects->owner"."id"; - `, }); }); @@ -614,21 +577,6 @@ describe('QueryGenerator#selectQuery', () => { ) ON [Project].[id] = [contributors->ProjectContributor].[projectId]; `, - oracle: ` - SELECT - "Project"."id", - "contributors"."id" AS "contributors.id", - "contributors->ProjectContributor"."userId" AS "contributors.ProjectContributor.userId", - "contributors->ProjectContributor"."projectId" AS "contributors.ProjectContributor.projectId" - FROM "Projects" "Project" - LEFT OUTER JOIN ( - "ProjectContributors" "contributors->ProjectContributor" - INNER JOIN "Users" "contributors" - ON "contributors"."id" = "contributors->ProjectContributor"."userId" - AND 'where' - ) - ON "Project"."id" = "contributors->ProjectContributor"."projectId"; - `, }); }); @@ -757,26 +705,6 @@ describe('QueryGenerator#selectQuery', () => { ON "projects"."ownerId" = "projects->owner"."id" ORDER BY 'order' `, - oracle: ` - SELECT - "User".*, - "projects"."id" AS "projects.id", - 'repl1', - 'repl1' AS "projects.id2", - "projects->owner"."id" AS "projects.owner.id", - 'repl2' FROM ( - SELECT "User"."id" - FROM "Users" "User" - ORDER BY 'order' - OFFSET 'offset' ROWS - FETCH NEXT 'limit' ROWS ONLY - ) "User" - INNER JOIN "Projects" "projects" - ON 'on' AND 'where' - LEFT OUTER JOIN "Users" "projects->owner" - ON "projects"."ownerId" = "projects->owner"."id" - ORDER BY 'order'; - `, }); }); @@ -855,20 +783,6 @@ Only named replacements (:name) are allowed in literal() because we cannot guara [a].* AS [col_a_all], * AS [col_all] FROM [Users] AS [User];`, - oracle: ` - SELECT - "count(*)" AS "count", - ".*", - "*", - count(*) AS "literal_count", - count('*') AS "fn_count_str", - count(*) AS "fn_count_col", - count(*) AS "fn_count_lit", - "a"."b" AS "col_a_b", - "a".* AS "col_a_all", - * AS "col_all" - FROM "Users" "User"; - `, }); }); @@ -888,7 +802,6 @@ Only named replacements (:name) are allowed in literal() because we cannot guara expectsql(sql, { default: `SELECT *, YEAR([createdAt]) AS [creationYear] FROM [Users] AS [User] GROUP BY [creationYear], [title] HAVING [User].[creationYear] > 2002;`, - oracle: `SELECT *, YEAR("createdAt") AS "creationYear" FROM "Users" "User" GROUP BY "creationYear", "title" HAVING "User"."creationYear" > 2002;`, }); }); }); @@ -1024,7 +937,6 @@ Only named replacements (:name) are allowed in literal() because we cannot guara expectsql(sql, { default: `SELECT 1 AS [_0] FROM [Users] AS [User] GROUP BY [_0] ORDER BY [_0];`, - oracle: `SELECT 1 AS "_0" FROM "Users" "User" GROUP BY "_0" ORDER BY "_0";`, }); }); }); diff --git a/packages/core/test/unit/query-generator/set-isolation-level-query.test.ts b/packages/core/test/unit/query-generator/set-isolation-level-query.test.ts index 5e9bf6703c6a..e411b822003f 100644 --- a/packages/core/test/unit/query-generator/set-isolation-level-query.test.ts +++ b/packages/core/test/unit/query-generator/set-isolation-level-query.test.ts @@ -27,7 +27,6 @@ describe('QueryGenerator#setIsolationLevelQuery', () => { sqlite3: 'PRAGMA read_uncommitted = 1', snowflake: notSupportedError, 'db2 ibmi mssql': queryNotSupportedError, - oracle: 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED', }); }); @@ -39,7 +38,6 @@ describe('QueryGenerator#setIsolationLevelQuery', () => { ), snowflake: notSupportedError, 'db2 ibmi mssql': queryNotSupportedError, - oracle: 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', }); }); diff --git a/packages/core/test/unit/query-generator/show-constraints-query.test.ts b/packages/core/test/unit/query-generator/show-constraints-query.test.ts index 4aebfbbae856..e1cc0c8a618a 100644 --- a/packages/core/test/unit/query-generator/show-constraints-query.test.ts +++ b/packages/core/test/unit/query-generator/show-constraints-query.test.ts @@ -16,7 +16,6 @@ describe('QueryGenerator#showConstraintsQuery', () => { snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'PUBLIC' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'myTable'`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'sequelize_test' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, - oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='myTable' AND C.OWNER ='${dialect.getDefaultSchema()}' ORDER BY C.CONSTRAINT_NAME`, }); }); @@ -28,7 +27,6 @@ describe('QueryGenerator#showConstraintsQuery', () => { postgres: `SELECT c.constraint_catalog AS "constraintCatalog", c.constraint_schema AS "constraintSchema", c.constraint_name AS "constraintName", c.constraint_type AS "constraintType", c.table_catalog AS "tableCatalog", c.table_schema AS "tableSchema", c.table_name AS "tableName", kcu.column_name AS "columnNames", ccu.table_schema AS "referencedTableSchema", ccu.table_name AS "referencedTableName", ccu.column_name AS "referencedColumnNames", r.delete_rule AS "deleteAction", r.update_rule AS "updateAction", ch.check_clause AS "definition", c.is_deferrable AS "isDeferrable", c.initially_deferred AS "initiallyDeferred" FROM INFORMATION_SCHEMA.table_constraints c LEFT JOIN INFORMATION_SCHEMA.referential_constraints r ON c.constraint_catalog = r.constraint_catalog AND c.constraint_schema = r.constraint_schema AND c.constraint_name = r.constraint_name LEFT JOIN INFORMATION_SCHEMA.key_column_usage kcu ON c.constraint_catalog = kcu.constraint_catalog AND c.constraint_schema = kcu.constraint_schema AND c.constraint_name = kcu.constraint_name LEFT JOIN information_schema.constraint_column_usage AS ccu ON r.constraint_catalog = ccu.constraint_catalog AND r.constraint_schema = ccu.constraint_schema AND r.constraint_name = ccu.constraint_name LEFT JOIN INFORMATION_SCHEMA.check_constraints ch ON c.constraint_catalog = ch.constraint_catalog AND c.constraint_schema = ch.constraint_schema AND c.constraint_name = ch.constraint_name WHERE c.table_name = 'myTable' AND c.table_schema = 'public' AND c.constraint_name = 'foo_bar' ORDER BY c.constraint_name, kcu.ordinal_position`, snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'PUBLIC' AND c.CONSTRAINT_NAME = 'foo_bar' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'myTable'`, - oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='myTable' AND C.OWNER ='${dialect.getDefaultSchema()}' AND C.CONSTRAINT_NAME ='foo_bar' ORDER BY C.CONSTRAINT_NAME`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'sequelize_test' AND c.CONSTRAINT_NAME = 'foo_bar' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }); }); @@ -43,7 +41,6 @@ describe('QueryGenerator#showConstraintsQuery', () => { postgres: `SELECT c.constraint_catalog AS "constraintCatalog", c.constraint_schema AS "constraintSchema", c.constraint_name AS "constraintName", c.constraint_type AS "constraintType", c.table_catalog AS "tableCatalog", c.table_schema AS "tableSchema", c.table_name AS "tableName", kcu.column_name AS "columnNames", ccu.table_schema AS "referencedTableSchema", ccu.table_name AS "referencedTableName", ccu.column_name AS "referencedColumnNames", r.delete_rule AS "deleteAction", r.update_rule AS "updateAction", ch.check_clause AS "definition", c.is_deferrable AS "isDeferrable", c.initially_deferred AS "initiallyDeferred" FROM INFORMATION_SCHEMA.table_constraints c LEFT JOIN INFORMATION_SCHEMA.referential_constraints r ON c.constraint_catalog = r.constraint_catalog AND c.constraint_schema = r.constraint_schema AND c.constraint_name = r.constraint_name LEFT JOIN INFORMATION_SCHEMA.key_column_usage kcu ON c.constraint_catalog = kcu.constraint_catalog AND c.constraint_schema = kcu.constraint_schema AND c.constraint_name = kcu.constraint_name LEFT JOIN information_schema.constraint_column_usage AS ccu ON r.constraint_catalog = ccu.constraint_catalog AND r.constraint_schema = ccu.constraint_schema AND r.constraint_name = ccu.constraint_name LEFT JOIN INFORMATION_SCHEMA.check_constraints ch ON c.constraint_catalog = ch.constraint_catalog AND c.constraint_schema = ch.constraint_schema AND c.constraint_name = ch.constraint_name WHERE c.table_name = 'myTable' AND c.table_schema = 'public' AND c.constraint_type = 'FOREIGN KEY' ORDER BY c.constraint_name, kcu.ordinal_position`, snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'PUBLIC' AND c.CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'myTable'`, - oracle: `SELECT DISTINCT a.table_name "tableName", a.constraint_name "constraintName", a.owner "constraintSchema", a.column_name "columnNames",CASE c.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", c.r_owner "referencedTableSchema", c.DELETE_RULE "deleteAction", b.table_name "referencedTableName", b.column_name "referencedColumnNames" FROM all_cons_columns a JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name JOIN all_cons_columns b ON c.owner = b.owner AND c.r_constraint_name = b.constraint_name WHERE c.constraint_type = 'R' AND a.table_name = 'myTable' AND a.owner = '${dialect.getDefaultSchema()}' ORDER BY a.table_name, a.column_name, b.column_name`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'sequelize_test' AND c.CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }, ); @@ -59,7 +56,6 @@ describe('QueryGenerator#showConstraintsQuery', () => { 'columnName', ]), sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'myTable'`, - oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='myTable' AND C.OWNER ='${dialect.getDefaultSchema()}' ORDER BY C.CONSTRAINT_NAME`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'sequelize_test' AND kcu.COLUMN_NAME = 'some_column' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }); }); @@ -74,7 +70,6 @@ describe('QueryGenerator#showConstraintsQuery', () => { postgres: `SELECT c.constraint_catalog AS "constraintCatalog", c.constraint_schema AS "constraintSchema", c.constraint_name AS "constraintName", c.constraint_type AS "constraintType", c.table_catalog AS "tableCatalog", c.table_schema AS "tableSchema", c.table_name AS "tableName", kcu.column_name AS "columnNames", ccu.table_schema AS "referencedTableSchema", ccu.table_name AS "referencedTableName", ccu.column_name AS "referencedColumnNames", r.delete_rule AS "deleteAction", r.update_rule AS "updateAction", ch.check_clause AS "definition", c.is_deferrable AS "isDeferrable", c.initially_deferred AS "initiallyDeferred" FROM INFORMATION_SCHEMA.table_constraints c LEFT JOIN INFORMATION_SCHEMA.referential_constraints r ON c.constraint_catalog = r.constraint_catalog AND c.constraint_schema = r.constraint_schema AND c.constraint_name = r.constraint_name LEFT JOIN INFORMATION_SCHEMA.key_column_usage kcu ON c.constraint_catalog = kcu.constraint_catalog AND c.constraint_schema = kcu.constraint_schema AND c.constraint_name = kcu.constraint_name LEFT JOIN information_schema.constraint_column_usage AS ccu ON r.constraint_catalog = ccu.constraint_catalog AND r.constraint_schema = ccu.constraint_schema AND r.constraint_name = ccu.constraint_name LEFT JOIN INFORMATION_SCHEMA.check_constraints ch ON c.constraint_catalog = ch.constraint_catalog AND c.constraint_schema = ch.constraint_schema AND c.constraint_name = ch.constraint_name WHERE c.table_name = 'MyModels' AND c.table_schema = 'public' ORDER BY c.constraint_name, kcu.ordinal_position`, snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'MyModels' AND c.TABLE_SCHEMA = 'PUBLIC' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'MyModels'`, - oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='MyModels' AND C.OWNER ='${dialect.getDefaultSchema()}' ORDER BY C.CONSTRAINT_NAME`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'MyModels' AND c.TABLE_SCHEMA = 'sequelize_test' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }); }); @@ -91,7 +86,6 @@ describe('QueryGenerator#showConstraintsQuery', () => { snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'MyModels' AND c.TABLE_SCHEMA = 'PUBLIC' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'MyModels'`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'MyModels' AND c.TABLE_SCHEMA = 'sequelize_test' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, - oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='MyModels' AND C.OWNER ='${dialect.getDefaultSchema()}' ORDER BY C.CONSTRAINT_NAME`, }); }); @@ -105,7 +99,6 @@ describe('QueryGenerator#showConstraintsQuery', () => { postgres: `SELECT c.constraint_catalog AS "constraintCatalog", c.constraint_schema AS "constraintSchema", c.constraint_name AS "constraintName", c.constraint_type AS "constraintType", c.table_catalog AS "tableCatalog", c.table_schema AS "tableSchema", c.table_name AS "tableName", kcu.column_name AS "columnNames", ccu.table_schema AS "referencedTableSchema", ccu.table_name AS "referencedTableName", ccu.column_name AS "referencedColumnNames", r.delete_rule AS "deleteAction", r.update_rule AS "updateAction", ch.check_clause AS "definition", c.is_deferrable AS "isDeferrable", c.initially_deferred AS "initiallyDeferred" FROM INFORMATION_SCHEMA.table_constraints c LEFT JOIN INFORMATION_SCHEMA.referential_constraints r ON c.constraint_catalog = r.constraint_catalog AND c.constraint_schema = r.constraint_schema AND c.constraint_name = r.constraint_name LEFT JOIN INFORMATION_SCHEMA.key_column_usage kcu ON c.constraint_catalog = kcu.constraint_catalog AND c.constraint_schema = kcu.constraint_schema AND c.constraint_name = kcu.constraint_name LEFT JOIN information_schema.constraint_column_usage AS ccu ON r.constraint_catalog = ccu.constraint_catalog AND r.constraint_schema = ccu.constraint_schema AND r.constraint_name = ccu.constraint_name LEFT JOIN INFORMATION_SCHEMA.check_constraints ch ON c.constraint_catalog = ch.constraint_catalog AND c.constraint_schema = ch.constraint_schema AND c.constraint_name = ch.constraint_name WHERE c.table_name = 'myTable' AND c.table_schema = 'mySchema' ORDER BY c.constraint_name, kcu.ordinal_position`, snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'mySchema' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'mySchema.myTable'`, - oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='myTable' AND C.OWNER ='mySchema' ORDER BY C.CONSTRAINT_NAME`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'mySchema' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }, ); @@ -125,7 +118,6 @@ describe('QueryGenerator#showConstraintsQuery', () => { postgres: `SELECT c.constraint_catalog AS "constraintCatalog", c.constraint_schema AS "constraintSchema", c.constraint_name AS "constraintName", c.constraint_type AS "constraintType", c.table_catalog AS "tableCatalog", c.table_schema AS "tableSchema", c.table_name AS "tableName", kcu.column_name AS "columnNames", ccu.table_schema AS "referencedTableSchema", ccu.table_name AS "referencedTableName", ccu.column_name AS "referencedColumnNames", r.delete_rule AS "deleteAction", r.update_rule AS "updateAction", ch.check_clause AS "definition", c.is_deferrable AS "isDeferrable", c.initially_deferred AS "initiallyDeferred" FROM INFORMATION_SCHEMA.table_constraints c LEFT JOIN INFORMATION_SCHEMA.referential_constraints r ON c.constraint_catalog = r.constraint_catalog AND c.constraint_schema = r.constraint_schema AND c.constraint_name = r.constraint_name LEFT JOIN INFORMATION_SCHEMA.key_column_usage kcu ON c.constraint_catalog = kcu.constraint_catalog AND c.constraint_schema = kcu.constraint_schema AND c.constraint_name = kcu.constraint_name LEFT JOIN information_schema.constraint_column_usage AS ccu ON r.constraint_catalog = ccu.constraint_catalog AND r.constraint_schema = ccu.constraint_schema AND r.constraint_name = ccu.constraint_name LEFT JOIN INFORMATION_SCHEMA.check_constraints ch ON c.constraint_catalog = ch.constraint_catalog AND c.constraint_schema = ch.constraint_schema AND c.constraint_name = ch.constraint_name WHERE c.table_name = 'myTable' AND c.table_schema = 'public' ORDER BY c.constraint_name, kcu.ordinal_position`, snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'PUBLIC' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'myTable'`, - oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='myTable' AND C.OWNER ='${dialect.getDefaultSchema()}' ORDER BY C.CONSTRAINT_NAME`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'sequelize_test' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }, ); @@ -142,7 +134,6 @@ describe('QueryGenerator#showConstraintsQuery', () => { postgres: `SELECT c.constraint_catalog AS "constraintCatalog", c.constraint_schema AS "constraintSchema", c.constraint_name AS "constraintName", c.constraint_type AS "constraintType", c.table_catalog AS "tableCatalog", c.table_schema AS "tableSchema", c.table_name AS "tableName", kcu.column_name AS "columnNames", ccu.table_schema AS "referencedTableSchema", ccu.table_name AS "referencedTableName", ccu.column_name AS "referencedColumnNames", r.delete_rule AS "deleteAction", r.update_rule AS "updateAction", ch.check_clause AS "definition", c.is_deferrable AS "isDeferrable", c.initially_deferred AS "initiallyDeferred" FROM INFORMATION_SCHEMA.table_constraints c LEFT JOIN INFORMATION_SCHEMA.referential_constraints r ON c.constraint_catalog = r.constraint_catalog AND c.constraint_schema = r.constraint_schema AND c.constraint_name = r.constraint_name LEFT JOIN INFORMATION_SCHEMA.key_column_usage kcu ON c.constraint_catalog = kcu.constraint_catalog AND c.constraint_schema = kcu.constraint_schema AND c.constraint_name = kcu.constraint_name LEFT JOIN information_schema.constraint_column_usage AS ccu ON r.constraint_catalog = ccu.constraint_catalog AND r.constraint_schema = ccu.constraint_schema AND r.constraint_name = ccu.constraint_name LEFT JOIN INFORMATION_SCHEMA.check_constraints ch ON c.constraint_catalog = ch.constraint_catalog AND c.constraint_schema = ch.constraint_schema AND c.constraint_name = ch.constraint_name WHERE c.table_name = 'myTable' AND c.table_schema = 'mySchema' ORDER BY c.constraint_name, kcu.ordinal_position`, snowflake: `SELECT c.CONSTRAINT_CATALOG AS constraintCatalog, c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_CATALOG AS tableCatalog, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, fk.TABLE_SCHEMA AS referencedTableSchema, fk.TABLE_NAME AS referencedTableName, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, c.IS_DEFERRABLE AS isDeferrable, c.INITIALLY_DEFERRED AS initiallyDeferred FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON r.UNIQUE_CONSTRAINT_CATALOG = fk.CONSTRAINT_CATALOG AND r.UNIQUE_CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA AND r.UNIQUE_CONSTRAINT_NAME = fk.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'mySchema' ORDER BY c.CONSTRAINT_NAME`, sqlite3: `SELECT sql FROM sqlite_master WHERE tbl_name = 'mySchema.myTable'`, - oracle: `SELECT C.CONSTRAINT_NAME "constraintName", CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType", C.TABLE_NAME "tableName", C.OWNER "constraintSchema", C.COLUMN_NAME "columnNames" FROM ALL_CONS_COLUMNS C INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME WHERE C.TABLE_NAME ='myTable' AND C.OWNER ='mySchema' ORDER BY C.CONSTRAINT_NAME`, 'mariadb mysql': `SELECT c.CONSTRAINT_SCHEMA AS constraintSchema, c.CONSTRAINT_NAME AS constraintName, c.CONSTRAINT_TYPE AS constraintType, c.TABLE_SCHEMA AS tableSchema, c.TABLE_NAME AS tableName, kcu.COLUMN_NAME AS columnNames, kcu.REFERENCED_TABLE_SCHEMA AS referencedTableSchema, kcu.REFERENCED_TABLE_NAME AS referencedTableName, kcu.REFERENCED_COLUMN_NAME AS referencedColumnNames, r.DELETE_RULE AS deleteAction, r.UPDATE_RULE AS updateAction, ch.CHECK_CLAUSE AS definition FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS r ON c.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.TABLE_NAME = r.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND c.TABLE_NAME = kcu.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS ch ON c.CONSTRAINT_CATALOG = ch.CONSTRAINT_CATALOG AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_NAME = 'myTable' AND c.TABLE_SCHEMA = 'mySchema' ORDER BY c.CONSTRAINT_NAME, kcu.ORDINAL_POSITION`, }); }); diff --git a/packages/core/test/unit/query-generator/show-indexes-query.test.ts b/packages/core/test/unit/query-generator/show-indexes-query.test.ts index d85318b1f61d..abdca5b92894 100644 --- a/packages/core/test/unit/query-generator/show-indexes-query.test.ts +++ b/packages/core/test/unit/query-generator/show-indexes-query.test.ts @@ -29,11 +29,6 @@ describe('QueryGenerator#showIndexesQuery', () => { QSYS2.SYSKEYS.COLUMN_NAME, CAST('INDEX' AS VARCHAR(11)), QSYS2.SYSINDEXES.TABLE_SCHEMA, QSYS2.SYSINDEXES.TABLE_NAME from QSYS2.SYSKEYS left outer join QSYS2.SYSINDEXES on QSYS2.SYSKEYS.INDEX_NAME = QSYS2.SYSINDEXES.INDEX_NAME where QSYS2.SYSINDEXES.TABLE_SCHEMA = CURRENT SCHEMA and QSYS2.SYSINDEXES.TABLE_NAME = 'myTable'`, - oracle: `SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type - FROM all_ind_columns i - INNER JOIN all_indexes u ON (u.table_name = i.table_name AND u.index_name = i.index_name) - LEFT OUTER JOIN all_constraints c ON (c.table_name = i.table_name AND c.index_name = i.index_name) - WHERE i.table_name = 'myTable' AND u.table_owner = '${dialect.getDefaultSchema()}' ORDER BY index_name, column_position`, }); }); @@ -63,11 +58,6 @@ describe('QueryGenerator#showIndexesQuery', () => { QSYS2.SYSKEYS.COLUMN_NAME, CAST('INDEX' AS VARCHAR(11)), QSYS2.SYSINDEXES.TABLE_SCHEMA, QSYS2.SYSINDEXES.TABLE_NAME from QSYS2.SYSKEYS left outer join QSYS2.SYSINDEXES on QSYS2.SYSKEYS.INDEX_NAME = QSYS2.SYSINDEXES.INDEX_NAME where QSYS2.SYSINDEXES.TABLE_SCHEMA = CURRENT SCHEMA and QSYS2.SYSINDEXES.TABLE_NAME = 'MyModels'`, - oracle: `SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type - FROM all_ind_columns i - INNER JOIN all_indexes u ON (u.table_name = i.table_name AND u.index_name = i.index_name) - LEFT OUTER JOIN all_constraints c ON (c.table_name = i.table_name AND c.index_name = i.index_name) - WHERE i.table_name = 'MyModels' AND u.table_owner = '${dialect.getDefaultSchema()}' ORDER BY index_name, column_position`, }); }); @@ -98,9 +88,6 @@ describe('QueryGenerator#showIndexesQuery', () => { QSYS2.SYSKEYS.COLUMN_NAME, CAST('INDEX' AS VARCHAR(11)), QSYS2.SYSINDEXES.TABLE_SCHEMA, QSYS2.SYSINDEXES.TABLE_NAME from QSYS2.SYSKEYS left outer join QSYS2.SYSINDEXES on QSYS2.SYSKEYS.INDEX_NAME = QSYS2.SYSINDEXES.INDEX_NAME where QSYS2.SYSINDEXES.TABLE_SCHEMA = CURRENT SCHEMA and QSYS2.SYSINDEXES.TABLE_NAME = 'MyModels'`, - oracle: `SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type FROM all_ind_columns i - INNER JOIN all_indexes u ON (u.table_name = i.table_name AND u.index_name = i.index_name) - LEFT OUTER JOIN all_constraints c ON (c.table_name = i.table_name AND c.index_name = i.index_name) WHERE i.table_name = 'MyModels' AND u.table_owner = '${dialect.getDefaultSchema()}' ORDER BY index_name, column_position`, }); }); @@ -128,11 +115,6 @@ describe('QueryGenerator#showIndexesQuery', () => { QSYS2.SYSKEYS.COLUMN_NAME, CAST('INDEX' AS VARCHAR(11)), QSYS2.SYSINDEXES.TABLE_SCHEMA, QSYS2.SYSINDEXES.TABLE_NAME from QSYS2.SYSKEYS left outer join QSYS2.SYSINDEXES on QSYS2.SYSKEYS.INDEX_NAME = QSYS2.SYSINDEXES.INDEX_NAME where QSYS2.SYSINDEXES.TABLE_SCHEMA = 'mySchema' and QSYS2.SYSINDEXES.TABLE_NAME = 'myTable'`, - oracle: `SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type - FROM all_ind_columns i - INNER JOIN all_indexes u ON (u.table_name = i.table_name AND u.index_name = i.index_name) - LEFT OUTER JOIN all_constraints c ON (c.table_name = i.table_name AND c.index_name = i.index_name) - WHERE i.table_name = 'myTable' AND u.table_owner = 'mySchema' ORDER BY index_name, column_position`, }); }); @@ -166,11 +148,6 @@ describe('QueryGenerator#showIndexesQuery', () => { QSYS2.SYSKEYS.COLUMN_NAME, CAST('INDEX' AS VARCHAR(11)), QSYS2.SYSINDEXES.TABLE_SCHEMA, QSYS2.SYSINDEXES.TABLE_NAME from QSYS2.SYSKEYS left outer join QSYS2.SYSINDEXES on QSYS2.SYSKEYS.INDEX_NAME = QSYS2.SYSINDEXES.INDEX_NAME where QSYS2.SYSINDEXES.TABLE_SCHEMA = CURRENT SCHEMA and QSYS2.SYSINDEXES.TABLE_NAME = 'myTable'`, - oracle: `SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type - FROM all_ind_columns i - INNER JOIN all_indexes u ON (u.table_name = i.table_name AND u.index_name = i.index_name) - LEFT OUTER JOIN all_constraints c ON (c.table_name = i.table_name AND c.index_name = i.index_name) - WHERE i.table_name = 'myTable' AND u.table_owner = '${dialect.getDefaultSchema()}' ORDER BY index_name, column_position`, }, ); }); @@ -202,11 +179,6 @@ describe('QueryGenerator#showIndexesQuery', () => { QSYS2.SYSKEYS.COLUMN_NAME, CAST('INDEX' AS VARCHAR(11)), QSYS2.SYSINDEXES.TABLE_SCHEMA, QSYS2.SYSINDEXES.TABLE_NAME from QSYS2.SYSKEYS left outer join QSYS2.SYSINDEXES on QSYS2.SYSKEYS.INDEX_NAME = QSYS2.SYSINDEXES.INDEX_NAME where QSYS2.SYSINDEXES.TABLE_SCHEMA = 'mySchema' and QSYS2.SYSINDEXES.TABLE_NAME = 'myTable'`, - oracle: `SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type - FROM all_ind_columns i - INNER JOIN all_indexes u ON (u.table_name = i.table_name AND u.index_name = i.index_name) - LEFT OUTER JOIN all_constraints c ON (c.table_name = i.table_name AND c.index_name = i.index_name) - WHERE i.table_name = 'myTable' AND u.table_owner = 'mySchema' ORDER BY index_name, column_position`, }); }); diff --git a/packages/core/test/unit/query-generator/start-transaction-query.test.ts b/packages/core/test/unit/query-generator/start-transaction-query.test.ts index 3cd417e34c4e..0c23e7ac91b4 100644 --- a/packages/core/test/unit/query-generator/start-transaction-query.test.ts +++ b/packages/core/test/unit/query-generator/start-transaction-query.test.ts @@ -15,7 +15,6 @@ describe('QueryGenerator#startTransactionQuery', () => { default: 'START TRANSACTION', sqlite3: 'BEGIN DEFERRED TRANSACTION', 'db2 ibmi mssql': notSupportedError, - oracle: 'BEGIN TRANSACTION', }); }); @@ -25,7 +24,6 @@ describe('QueryGenerator#startTransactionQuery', () => { snowflake: 'START TRANSACTION NAME "myTransaction"', sqlite3: 'BEGIN DEFERRED TRANSACTION', 'db2 ibmi mssql': notSupportedError, - oracle: 'BEGIN TRANSACTION', }); }); @@ -88,7 +86,7 @@ describe('QueryGenerator#startTransactionQuery', () => { default: buildInvalidOptionReceivedError('startTransactionQuery', dialect.name, [ 'transactionType', ]), - 'snowflake sqlite3 oracle': buildInvalidOptionReceivedError( + 'snowflake sqlite3': buildInvalidOptionReceivedError( 'startTransactionQuery', dialect.name, ['readOnly'], diff --git a/packages/core/test/unit/query-generator/table-exists-query.test.ts b/packages/core/test/unit/query-generator/table-exists-query.test.ts index c55e3285824a..a99a4dfba560 100644 --- a/packages/core/test/unit/query-generator/table-exists-query.test.ts +++ b/packages/core/test/unit/query-generator/table-exists-query.test.ts @@ -13,7 +13,6 @@ describe('QueryGenerator#tableExistsQuery', () => { ibmi: `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TABLE_NAME = 'myTable' AND TABLE_SCHEMA = CURRENT SCHEMA`, mssql: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = N'myTable' AND TABLE_SCHEMA = N'${defaultSchema}'`, sqlite3: `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'myTable'`, - oracle: `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'myTable' AND OWNER = USER`, }); }); @@ -26,7 +25,6 @@ describe('QueryGenerator#tableExistsQuery', () => { ibmi: `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TABLE_NAME = 'MyModels' AND TABLE_SCHEMA = CURRENT SCHEMA`, mssql: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = N'MyModels' AND TABLE_SCHEMA = N'${defaultSchema}'`, sqlite3: `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'MyModels'`, - oracle: `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'MyModels' AND OWNER = '${defaultSchema}'`, }); }); @@ -40,7 +38,6 @@ describe('QueryGenerator#tableExistsQuery', () => { ibmi: `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TABLE_NAME = 'MyModels' AND TABLE_SCHEMA = CURRENT SCHEMA`, mssql: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = N'MyModels' AND TABLE_SCHEMA = N'${defaultSchema}'`, sqlite3: `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'MyModels'`, - oracle: `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'MyModels' AND OWNER = USER`, }); }); @@ -51,7 +48,6 @@ describe('QueryGenerator#tableExistsQuery', () => { ibmi: `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TABLE_NAME = 'myTable' AND TABLE_SCHEMA = 'mySchema'`, mssql: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = N'myTable' AND TABLE_SCHEMA = N'mySchema'`, sqlite3: `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'mySchema.myTable'`, - oracle: `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'myTable' AND OWNER = 'mySchema'`, }); }); @@ -68,7 +64,6 @@ describe('QueryGenerator#tableExistsQuery', () => { ibmi: `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TABLE_NAME = 'myTable' AND TABLE_SCHEMA = CURRENT SCHEMA`, mssql: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = N'myTable' AND TABLE_SCHEMA = N'${defaultSchema}'`, sqlite3: `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'myTable'`, - oracle: `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'myTable' AND OWNER = '${defaultSchema}'`, }, ); }); @@ -83,7 +78,6 @@ describe('QueryGenerator#tableExistsQuery', () => { ibmi: `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TABLE_NAME = 'myTable' AND TABLE_SCHEMA = 'mySchema'`, mssql: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = N'myTable' AND TABLE_SCHEMA = N'mySchema'`, sqlite3: `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'mySchema.myTable'`, - oracle: `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'myTable' AND OWNER = USER`, }); }); diff --git a/packages/core/test/unit/query-generator/truncate-table-query.test.ts b/packages/core/test/unit/query-generator/truncate-table-query.test.ts index 31b1ea03d412..9dfa1528c1dd 100644 --- a/packages/core/test/unit/query-generator/truncate-table-query.test.ts +++ b/packages/core/test/unit/query-generator/truncate-table-query.test.ts @@ -13,7 +13,6 @@ describe('QueryGenerator#truncateTableQuery', () => { 'db2 ibmi': 'TRUNCATE TABLE "myTable" IMMEDIATE', 'mariadb mysql': 'TRUNCATE `myTable`', 'postgres snowflake': 'TRUNCATE "myTable"', - oracle: `TRUNCATE TABLE "myTable"`, }); }); @@ -63,7 +62,6 @@ describe('QueryGenerator#truncateTableQuery', () => { 'db2 ibmi': 'TRUNCATE TABLE "MyModels" IMMEDIATE', 'mariadb mysql': 'TRUNCATE `MyModels`', 'postgres snowflake': 'TRUNCATE "MyModels"', - oracle: `TRUNCATE TABLE "MyModels"`, }); }); @@ -77,7 +75,6 @@ describe('QueryGenerator#truncateTableQuery', () => { 'db2 ibmi': 'TRUNCATE TABLE "MyModels" IMMEDIATE', 'mariadb mysql': 'TRUNCATE `MyModels`', 'postgres snowflake': 'TRUNCATE "MyModels"', - oracle: `TRUNCATE TABLE "MyModels"`, }); }); @@ -90,7 +87,6 @@ describe('QueryGenerator#truncateTableQuery', () => { 'db2 ibmi': 'TRUNCATE TABLE "mySchema"."myTable" IMMEDIATE', 'mariadb mysql': 'TRUNCATE `mySchema`.`myTable`', 'postgres snowflake': 'TRUNCATE "mySchema"."myTable"', - oracle: 'TRUNCATE TABLE "mySchema"."myTable"', }, ); }); @@ -108,7 +104,6 @@ describe('QueryGenerator#truncateTableQuery', () => { 'db2 ibmi': 'TRUNCATE TABLE "myTable" IMMEDIATE', 'mariadb mysql': 'TRUNCATE `myTable`', 'postgres snowflake': 'TRUNCATE "myTable"', - oracle: `TRUNCATE TABLE "myTable"`, }, ); }); @@ -123,7 +118,6 @@ describe('QueryGenerator#truncateTableQuery', () => { 'db2 ibmi': 'TRUNCATE TABLE "mySchema"."myTable" IMMEDIATE', 'mariadb mysql': 'TRUNCATE `mySchema`.`myTable`', 'postgres snowflake': 'TRUNCATE "mySchema"."myTable"', - oracle: 'TRUNCATE TABLE "mySchema"."myTable"', }); }); diff --git a/packages/core/test/unit/query-generator/update-query.test.ts b/packages/core/test/unit/query-generator/update-query.test.ts index 47afefd3d2b6..6984a84fc9ce 100644 --- a/packages/core/test/unit/query-generator/update-query.test.ts +++ b/packages/core/test/unit/query-generator/update-query.test.ts @@ -59,7 +59,6 @@ describe('QueryGenerator#updateQuery', () => { expectsql(query, { default: 'UPDATE [Users] SET [firstName]=$sequelize_1,[lastName]=$1,[username]=$sequelize_2', db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1,"lastName"=$1,"username"=$sequelize_2);`, - oracle: `UPDATE "Users" SET "firstName"=:1,"lastName"=$1,"username"=:2`, }); expect(bind).to.deep.eq({ sequelize_1: 'John', @@ -106,7 +105,6 @@ describe('QueryGenerator#updateQuery', () => { query: { default: 'UPDATE [myTable] SET [date]=$sequelize_1 WHERE [id] = $sequelize_2', db2: 'SELECT * FROM FINAL TABLE (UPDATE "myTable" SET "date"=$sequelize_1 WHERE "id" = $sequelize_2);', - oracle: `UPDATE "myTable" SET "date"=:1 WHERE "id" = :2`, }, bind: { mysql: { @@ -141,10 +139,6 @@ describe('QueryGenerator#updateQuery', () => { sequelize_1: '2011-03-27 10:01:55.000 +00:00', sequelize_2: 2, }, - oracle: { - sequelize_1: new Date('2011-03-27T10:01:55Z'), - sequelize_2: 2, - }, }, }); }); @@ -164,7 +158,6 @@ describe('QueryGenerator#updateQuery', () => { default: 'UPDATE [myTable] SET [positive]=$sequelize_1,[negative]=$sequelize_2 WHERE [id] = $sequelize_3', db2: 'SELECT * FROM FINAL TABLE (UPDATE "myTable" SET "positive"=$sequelize_1,"negative"=$sequelize_2 WHERE "id" = $sequelize_3);', - oracle: `UPDATE "myTable" SET "positive"=:1,"negative"=:2 WHERE "id" = :3`, }, bind: { sqlite3: { @@ -207,11 +200,6 @@ describe('QueryGenerator#updateQuery', () => { sequelize_2: false, sequelize_3: 2, }, - oracle: { - sequelize_1: '1', - sequelize_2: '0', - sequelize_3: 2, - }, }, }); }); @@ -231,7 +219,6 @@ describe('QueryGenerator#updateQuery', () => { default: 'UPDATE [myTable] SET [value]=$sequelize_1,[name]=$sequelize_2 WHERE [id] = $sequelize_3', db2: 'SELECT * FROM FINAL TABLE (UPDATE "myTable" SET "value"=$sequelize_1,"name"=$sequelize_2 WHERE "id" = $sequelize_3);', - oracle: `UPDATE "myTable" SET "value"=:1,"name"=:2 WHERE "id" = :3`, }); expect(bind).to.deep.eq({ diff --git a/packages/core/test/unit/query-generator/version-query.test.ts b/packages/core/test/unit/query-generator/version-query.test.ts index d93881142f23..709e962b6934 100644 --- a/packages/core/test/unit/query-generator/version-query.test.ts +++ b/packages/core/test/unit/query-generator/version-query.test.ts @@ -12,7 +12,6 @@ describe('QueryGenerator#versionQuery', () => { snowflake: 'SELECT CURRENT_VERSION() AS "version"', db2: 'select service_level as "version" from TABLE (sysproc.env_get_inst_info()) as A', ibmi: `SELECT CONCAT(OS_VERSION, CONCAT('.', OS_RELEASE)) AS "version" FROM SYSIBMADM.ENV_SYS_INFO`, - oracle: `SELECT VERSION_FULL FROM PRODUCT_COMPONENT_VERSION WHERE PRODUCT LIKE 'Oracle%'`, }); }); }); diff --git a/packages/core/test/unit/query-interface/bulk-insert.test.ts b/packages/core/test/unit/query-interface/bulk-insert.test.ts index e90bece7a6e8..b504d1e0fbf6 100644 --- a/packages/core/test/unit/query-interface/bulk-insert.test.ts +++ b/packages/core/test/unit/query-interface/bulk-insert.test.ts @@ -41,8 +41,6 @@ describe('QueryInterface#bulkInsert', () => { mssql: toMatchRegex( /^INSERT INTO \[Users\] \(\[firstName\]\) VALUES (?:\(N'\w+'\),){999}\(N'\w+'\);$/, ), - // oracle uses `executeMany()` provided by node-oracledb driver and passes the value with binds - oracle: toMatchRegex(/^INSERT INTO "Users" \("firstName"\) VALUES \(:\d\)$/), }); }); @@ -67,7 +65,6 @@ describe('QueryInterface#bulkInsert', () => { mssql: toMatchRegex( /^(?:INSERT INTO \[Users\] \(\[firstName\]\) VALUES (?:\(N'\w+'\),){999}\(N'\w+'\);){2}$/, ), - oracle: toMatchRegex(/^INSERT INTO "Users" \("firstName"\) VALUES \(:\d\)$/), }); }); @@ -103,7 +100,6 @@ describe('QueryInterface#bulkInsert', () => { ibmi: toMatchSql( `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES (':injection'))`, ), - oracle: toMatchSql(`INSERT INTO "Users" ("firstName") VALUES (:1)`), }); }); }); diff --git a/packages/core/test/unit/query-interface/bulk-update.test.ts b/packages/core/test/unit/query-interface/bulk-update.test.ts index bf498781c778..7fe18bac8103 100644 --- a/packages/core/test/unit/query-interface/bulk-update.test.ts +++ b/packages/core/test/unit/query-interface/bulk-update.test.ts @@ -48,7 +48,6 @@ describe('QueryInterface#bulkUpdate', () => { expectsql(firstCall.args[0], { default: `UPDATE [Users] SET [firstName]=$sequelize_1 WHERE [firstName] = $sequelize_2`, db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1 WHERE "firstName" = $sequelize_2);`, - oracle: `UPDATE "Users" SET "firstName"=:1 WHERE "firstName" = :2`, }); expect(firstCall.args[1]?.bind).to.deep.eq({ @@ -102,7 +101,6 @@ describe('QueryInterface#bulkUpdate', () => { expectsql(firstCall.args[0], { default: 'UPDATE [Users] SET [firstName]=$sequelize_1 WHERE [firstName] = $one', db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1 WHERE "firstName" = $one);`, - oracle: `UPDATE "Users" SET "firstName"=:1 WHERE "firstName" = $one`, }); expect(firstCall.args[1]?.bind).to.deep.eq({ @@ -134,7 +132,6 @@ describe('QueryInterface#bulkUpdate', () => { expectsql(firstCall.args[0], { default: 'UPDATE [Users] SET [firstName]=$sequelize_1 WHERE [firstName] = $1', db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1 WHERE "firstName" = $1);`, - oracle: `UPDATE "Users" SET "firstName"=:1 WHERE "firstName" = $1`, }); expect(firstCall.args[1]?.bind).to.deep.eq({ diff --git a/packages/core/test/unit/query-interface/create-table.test.ts b/packages/core/test/unit/query-interface/create-table.test.ts index 07ca716eef33..f81d2c7633eb 100644 --- a/packages/core/test/unit/query-interface/create-table.test.ts +++ b/packages/core/test/unit/query-interface/create-table.test.ts @@ -40,7 +40,6 @@ describe('QueryInterface#createTable', () => { snowflake: 'CREATE TABLE IF NOT EXISTS "table" ("id" VARCHAR(36), PRIMARY KEY ("id"));', db2: 'CREATE TABLE IF NOT EXISTS "table" ("id" CHAR(36) FOR BIT DATA NOT NULL, PRIMARY KEY ("id"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "table" ("id" CHAR(36), PRIMARY KEY ("id")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "table" ("id" VARCHAR2(36),PRIMARY KEY ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); @@ -94,11 +93,9 @@ describe('QueryInterface#createTable', () => { snowflake: 'CREATE TABLE IF NOT EXISTS "table" ("id" VARCHAR(36), PRIMARY KEY ("id"));', db2: 'CREATE TABLE IF NOT EXISTS "table" ("id" CHAR(36) FOR BIT DATA NOT NULL, PRIMARY KEY ("id"));', ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "table" ("id" CHAR(36), PRIMARY KEY ("id")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "table" ("id" VARCHAR2(36),PRIMARY KEY ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); - // oracle uses BLOB with CHECK constraint and JSON_NULL isn't allowed. it('supports JSON_NULL default values', async () => { if (!dialect.supports.dataTypes.JSON) { return; @@ -120,7 +117,6 @@ describe('QueryInterface#createTable', () => { 'mariadb mysql': 'CREATE TABLE IF NOT EXISTS `table` (`json` JSON) ENGINE=InnoDB;', mssql: `IF OBJECT_ID(N'[table]', 'U') IS NULL CREATE TABLE [table] ([json] NVARCHAR(MAX) DEFAULT N'null');`, sqlite3: "CREATE TABLE IF NOT EXISTS `table` (`json` TEXT DEFAULT 'null');", - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "table" ("json" BLOB CHECK ("json" IS JSON))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }); }); }); diff --git a/packages/core/test/unit/query-interface/drop-table.test.ts b/packages/core/test/unit/query-interface/drop-table.test.ts index 1878a1e62a45..b1b9261dfd24 100644 --- a/packages/core/test/unit/query-interface/drop-table.test.ts +++ b/packages/core/test/unit/query-interface/drop-table.test.ts @@ -19,7 +19,6 @@ describe('QueryInterface#dropTable', () => { const firstCall = stub.getCall(0); expectsql(firstCall.args[0], { default: 'DROP TABLE IF EXISTS [myTable] CASCADE', - oracle: `BEGIN EXECUTE IMMEDIATE 'DROP TABLE "myTable" CASCADE CONSTRAINTS PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;`, }); } else { await expect( diff --git a/packages/core/test/unit/query-interface/insert.test.ts b/packages/core/test/unit/query-interface/insert.test.ts index 46531b06f25c..8727ff0795d8 100644 --- a/packages/core/test/unit/query-interface/insert.test.ts +++ b/packages/core/test/unit/query-interface/insert.test.ts @@ -4,7 +4,6 @@ import sinon from 'sinon'; import { beforeAll2, expectsql, sequelize } from '../../support'; describe('QueryInterface#insert', () => { - const dialect = sequelize.dialect; const vars = beforeAll2(() => { const User = sequelize.define( 'User', @@ -22,41 +21,37 @@ describe('QueryInterface#insert', () => { }); // you'll find more replacement tests in query-generator tests - // Oracle nedds bindDefinitions to be defined for outBinds which can't be obtained with bind and replacement present together. - (dialect.name === 'oracle' ? it.skip : it)( - 'does not parse replacements outside of raw sql', - async () => { - const { User } = vars; - const stub = sinon.stub(sequelize, 'queryRaw'); - - await sequelize.queryInterface.insert( - null, - User.table, - { - firstName: 'Zoe', - }, - { - returning: [':data'], - replacements: { - data: 'abc', - }, + it('does not parse replacements outside of raw sql', async () => { + const { User } = vars; + const stub = sinon.stub(sequelize, 'queryRaw'); + + await sequelize.queryInterface.insert( + null, + User.table, + { + firstName: 'Zoe', + }, + { + returning: [':data'], + replacements: { + data: 'abc', }, - ); - - expect(stub.callCount).to.eq(1); - const firstCall = stub.getCall(0); - expectsql(firstCall.args[0], { - postgres: `INSERT INTO "Users" ("firstName") VALUES ($sequelize_1) RETURNING ":data";`, - default: 'INSERT INTO [Users] ([firstName]) VALUES ($sequelize_1);', - mssql: `INSERT INTO [Users] ([firstName]) OUTPUT INSERTED.[:data] VALUES ($sequelize_1);`, - db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES ($sequelize_1));`, - ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES ($sequelize_1))`, - }); - expect(firstCall.args[1]?.bind).to.deep.eq({ - sequelize_1: 'Zoe', - }); - }, - ); + }, + ); + + expect(stub.callCount).to.eq(1); + const firstCall = stub.getCall(0); + expectsql(firstCall.args[0], { + postgres: `INSERT INTO "Users" ("firstName") VALUES ($sequelize_1) RETURNING ":data";`, + default: 'INSERT INTO [Users] ([firstName]) VALUES ($sequelize_1);', + mssql: `INSERT INTO [Users] ([firstName]) OUTPUT INSERTED.[:data] VALUES ($sequelize_1);`, + db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES ($sequelize_1));`, + ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES ($sequelize_1))`, + }); + expect(firstCall.args[1]?.bind).to.deep.eq({ + sequelize_1: 'Zoe', + }); + }); it('throws if a bind parameter name starts with the reserved "sequelize_" prefix', async () => { const { User } = vars; @@ -80,72 +75,65 @@ describe('QueryInterface#insert', () => { ); }); - // Oracle doesn't recommend user defined bind. This can mess up the SQL statements leading to errors. - (dialect.name === 'oracle' ? it.skip : it)( - 'merges user-provided bind parameters with sequelize-generated bind parameters (object bind)', - async () => { - const { User } = vars; - const stub = sinon.stub(sequelize, 'queryRaw'); + it('merges user-provided bind parameters with sequelize-generated bind parameters (object bind)', async () => { + const { User } = vars; + const stub = sinon.stub(sequelize, 'queryRaw'); - await sequelize.queryInterface.insert( - null, - User.table, - { - firstName: literal('$firstName'), - lastName: 'Doe', - }, - { - bind: { - firstName: 'John', - }, - }, - ); - - expect(stub.callCount).to.eq(1); - const firstCall = stub.getCall(0); - expectsql(firstCall.args[0], { - default: 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($firstName,$sequelize_1);', - db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($firstName,$sequelize_1));`, - ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($firstName,$sequelize_1))`, - }); - - expect(firstCall.args[1]?.bind).to.deep.eq({ - firstName: 'John', - sequelize_1: 'Doe', - }); - }, - ); - - (dialect.name === 'oracle' ? it.skip : it)( - 'merges user-provided bind parameters with sequelize-generated bind parameters (array bind)', - async () => { - const { User } = vars; - const stub = sinon.stub(sequelize, 'queryRaw'); - - await sequelize.queryInterface.insert( - null, - User.table, - { - firstName: literal('$1'), - lastName: 'Doe', - }, - { - bind: ['John'], + await sequelize.queryInterface.insert( + null, + User.table, + { + firstName: literal('$firstName'), + lastName: 'Doe', + }, + { + bind: { + firstName: 'John', }, - ); - - expect(stub.callCount).to.eq(1); - const firstCall = stub.getCall(0); - expectsql(firstCall.args[0], { - default: 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($1,$sequelize_1);', - db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($1,$sequelize_1));`, - ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($1,$sequelize_1))`, - }); - - expect(firstCall.args[1]?.bind).to.deep.eq({ - 1: 'John', - sequelize_1: 'Doe', - }); - }, - ); + }, + ); + + expect(stub.callCount).to.eq(1); + const firstCall = stub.getCall(0); + expectsql(firstCall.args[0], { + default: 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($firstName,$sequelize_1);', + db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($firstName,$sequelize_1));`, + ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($firstName,$sequelize_1))`, + }); + + expect(firstCall.args[1]?.bind).to.deep.eq({ + firstName: 'John', + sequelize_1: 'Doe', + }); + }); + + it('merges user-provided bind parameters with sequelize-generated bind parameters (array bind)', async () => { + const { User } = vars; + const stub = sinon.stub(sequelize, 'queryRaw'); + + await sequelize.queryInterface.insert( + null, + User.table, + { + firstName: literal('$1'), + lastName: 'Doe', + }, + { + bind: ['John'], + }, + ); + + expect(stub.callCount).to.eq(1); + const firstCall = stub.getCall(0); + expectsql(firstCall.args[0], { + default: 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($1,$sequelize_1);', + db2: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($1,$sequelize_1));`, + ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName","lastName") VALUES ($1,$sequelize_1))`, + }); + + expect(firstCall.args[1]?.bind).to.deep.eq({ + 1: 'John', + sequelize_1: 'Doe', + }); + }); }); diff --git a/packages/core/test/unit/query-interface/raw-select.test.ts b/packages/core/test/unit/query-interface/raw-select.test.ts index 17c095b4eeb2..49a3dc1d426d 100644 --- a/packages/core/test/unit/query-interface/raw-select.test.ts +++ b/packages/core/test/unit/query-interface/raw-select.test.ts @@ -46,7 +46,6 @@ describe('QueryInterface#rawSelect', () => { expectsql(firstCall.args[0], { default: `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = 'some :data';`, mssql: `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = N'some :data';`, - oracle: `SELECT "id" FROM "Users" "User" WHERE "User"."username" = 'some :data';`, }); }); }); diff --git a/packages/core/test/unit/query-interface/select.test.ts b/packages/core/test/unit/query-interface/select.test.ts index a804bbafaa10..32c424bc9583 100644 --- a/packages/core/test/unit/query-interface/select.test.ts +++ b/packages/core/test/unit/query-interface/select.test.ts @@ -41,7 +41,6 @@ describe('QueryInterface#select', () => { expectsql(firstCall.args[0], { default: `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = 'some :data';`, mssql: `SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = N'some :data';`, - oracle: `SELECT "id" FROM "Users" "User" WHERE "User"."username" = 'some :data';`, }); }); }); diff --git a/packages/core/test/unit/query-interface/update.test.ts b/packages/core/test/unit/query-interface/update.test.ts index d3c052a34f96..be29f5f88225 100644 --- a/packages/core/test/unit/query-interface/update.test.ts +++ b/packages/core/test/unit/query-interface/update.test.ts @@ -50,7 +50,6 @@ describe('QueryInterface#update', () => { mssql: 'UPDATE [Users] SET [firstName]=$sequelize_1 OUTPUT INSERTED.[:data] WHERE [firstName] = $sequelize_2', db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1 WHERE "firstName" = $sequelize_2);`, - oracle: `UPDATE "Users" SET "firstName"=:1 WHERE "firstName" = :2`, }); expect(firstCall.args[1]?.bind).to.deep.eq({ sequelize_1: ':name', @@ -104,7 +103,6 @@ describe('QueryInterface#update', () => { expectsql(firstCall.args[0], { default: 'UPDATE [Users] SET [firstName]=$sequelize_1 WHERE [id] = $id', db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1 WHERE "id" = $id);`, - oracle: `UPDATE "Users" SET "firstName"=:1 WHERE "id" = $id`, }); expect(firstCall.args[1]?.bind).to.deep.eq({ @@ -134,7 +132,6 @@ describe('QueryInterface#update', () => { expectsql(firstCall.args[0], { default: 'UPDATE [Users] SET [firstName]=$sequelize_1 WHERE [id] = $1', db2: `SELECT * FROM FINAL TABLE (UPDATE "Users" SET "firstName"=$sequelize_1 WHERE "id" = $1);`, - oracle: `UPDATE "Users" SET "firstName"=:1 WHERE "id" = $1`, }); expect(firstCall.args[1]?.bind).to.deep.eq({ diff --git a/packages/core/test/unit/query-interface/upsert.test.ts b/packages/core/test/unit/query-interface/upsert.test.ts index 30e14b6c5102..76861783dfd4 100644 --- a/packages/core/test/unit/query-interface/upsert.test.ts +++ b/packages/core/test/unit/query-interface/upsert.test.ts @@ -27,35 +27,32 @@ describe('QueryInterface#upsert', () => { }); // you'll find more replacement tests in query-generator tests - // For oracle the datatype validation for id fails. Oracle uses Where clause which does the type validation. - (dialectName === 'oracle' ? it.skip : it)( - 'does not parse replacements outside of raw sql', - async () => { - const { User } = vars; - const stub = sinon.stub(sequelize, 'queryRaw'); + it('does not parse replacements outside of raw sql', async () => { + const { User } = vars; + const stub = sinon.stub(sequelize, 'queryRaw'); - await sequelize.queryInterface.upsert( - User.tableName, - { firstName: ':name' }, - { firstName: ':name' }, - { id: ':id' }, - { - model: User, - replacements: { - name: 'Zoe', - data: 'abc', - }, + await sequelize.queryInterface.upsert( + User.tableName, + { firstName: ':name' }, + { firstName: ':name' }, + { id: ':id' }, + { + model: User, + replacements: { + name: 'Zoe', + data: 'abc', }, - ); + }, + ); - expect(stub.callCount).to.eq(1); - const firstCall = stub.getCall(0); - expectsql(firstCall.args[0], { - default: - 'INSERT INTO [Users] ([firstName]) VALUES ($sequelize_1) ON CONFLICT ([id]) DO UPDATE SET [firstName]=EXCLUDED.[firstName];', - 'mariadb mysql': - 'INSERT INTO `Users` (`firstName`) VALUES ($sequelize_1) ON DUPLICATE KEY UPDATE `firstName`=$sequelize_1;', - mssql: ` + expect(stub.callCount).to.eq(1); + const firstCall = stub.getCall(0); + expectsql(firstCall.args[0], { + default: + 'INSERT INTO [Users] ([firstName]) VALUES ($sequelize_1) ON CONFLICT ([id]) DO UPDATE SET [firstName]=EXCLUDED.[firstName];', + 'mariadb mysql': + 'INSERT INTO `Users` (`firstName`) VALUES ($sequelize_1) ON DUPLICATE KEY UPDATE `firstName`=$sequelize_1;', + mssql: ` MERGE INTO [Users] WITH(HOLDLOCK) AS [Users_target] USING (VALUES(N':name')) AS [Users_source]([firstName]) @@ -65,7 +62,7 @@ describe('QueryInterface#upsert', () => { WHEN NOT MATCHED THEN INSERT ([firstName]) VALUES(N':name') OUTPUT $action, INSERTED.*; `, - db2: ` + db2: ` MERGE INTO "Users" AS "Users_target" USING (VALUES(':name')) AS "Users_source"("firstName") @@ -75,17 +72,16 @@ describe('QueryInterface#upsert', () => { WHEN NOT MATCHED THEN INSERT ("firstName") VALUES(':name'); `, - }); + }); - if (dialectName === 'mssql' || dialectName === 'db2') { - expect(firstCall.args[1]?.bind).to.be.undefined; - } else { - expect(firstCall.args[1]?.bind).to.deep.eq({ - sequelize_1: ':name', - }); - } - }, - ); + if (dialectName === 'mssql' || dialectName === 'db2') { + expect(firstCall.args[1]?.bind).to.be.undefined; + } else { + expect(firstCall.args[1]?.bind).to.deep.eq({ + sequelize_1: ':name', + }); + } + }); it('throws if a bind parameter name starts with the reserved "sequelize_" prefix', async () => { const { User } = vars; @@ -109,37 +105,35 @@ describe('QueryInterface#upsert', () => { ); }); - (dialectName === 'oracle' ? it.skip : it)( - 'merges user-provided bind parameters with sequelize-generated bind parameters (object bind)', - async () => { - const { User } = vars; - const stub = sinon.stub(sequelize, 'queryRaw'); + it('merges user-provided bind parameters with sequelize-generated bind parameters (object bind)', async () => { + const { User } = vars; + const stub = sinon.stub(sequelize, 'queryRaw'); - await sequelize.queryInterface.upsert( - User.tableName, - { - firstName: literal('$firstName'), - lastName: 'Doe', - }, - {}, - // TODO: weird mssql/db2 specific behavior that should be unified - dialectName === 'mssql' || dialectName === 'db2' ? { id: 1 } : {}, - { - model: User, - bind: { - firstName: 'John', - }, + await sequelize.queryInterface.upsert( + User.tableName, + { + firstName: literal('$firstName'), + lastName: 'Doe', + }, + {}, + // TODO: weird mssql/db2 specific behavior that should be unified + dialectName === 'mssql' || dialectName === 'db2' ? { id: 1 } : {}, + { + model: User, + bind: { + firstName: 'John', }, - ); + }, + ); - expect(stub.callCount).to.eq(1); - const firstCall = stub.getCall(0); - expectsql(firstCall.args[0], { - default: - 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($firstName,$sequelize_1) ON CONFLICT ([id]) DO NOTHING;', - 'mariadb mysql': - 'INSERT INTO `Users` (`firstName`,`lastName`) VALUES ($firstName,$sequelize_1) ON DUPLICATE KEY UPDATE `id`=`id`;', - mssql: ` + expect(stub.callCount).to.eq(1); + const firstCall = stub.getCall(0); + expectsql(firstCall.args[0], { + default: + 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($firstName,$sequelize_1) ON CONFLICT ([id]) DO NOTHING;', + 'mariadb mysql': + 'INSERT INTO `Users` (`firstName`,`lastName`) VALUES ($firstName,$sequelize_1) ON DUPLICATE KEY UPDATE `id`=`id`;', + mssql: ` MERGE INTO [Users] WITH(HOLDLOCK) AS [Users_target] USING (VALUES($firstName, N'Doe')) AS [Users_source]([firstName], [lastName]) ON [Users_target].[id] = [Users_source].[id] @@ -147,57 +141,54 @@ describe('QueryInterface#upsert', () => { INSERT ([firstName], [lastName]) VALUES($firstName, N'Doe') OUTPUT $action, INSERTED.*; `, - db2: ` + db2: ` MERGE INTO "Users" AS "Users_target" USING (VALUES($firstName, 'Doe')) AS "Users_source"("firstName", "lastName") ON "Users_target"."id" = "Users_source"."id" WHEN NOT MATCHED THEN INSERT ("firstName", "lastName") VALUES($firstName, 'Doe'); `, - }); + }); - if (dialectName === 'mssql' || dialectName === 'db2') { - expect(firstCall.args[1]?.bind).to.deep.eq({ - firstName: 'John', - }); - } else { - expect(firstCall.args[1]?.bind).to.deep.eq({ - firstName: 'John', - sequelize_1: 'Doe', - }); - } - }, - ); + if (dialectName === 'mssql' || dialectName === 'db2') { + expect(firstCall.args[1]?.bind).to.deep.eq({ + firstName: 'John', + }); + } else { + expect(firstCall.args[1]?.bind).to.deep.eq({ + firstName: 'John', + sequelize_1: 'Doe', + }); + } + }); - (dialectName === 'oracle' ? it.skip : it)( - 'merges user-provided bind parameters with sequelize-generated bind parameters (array bind)', - async () => { - const { User } = vars; - const stub = sinon.stub(sequelize, 'queryRaw'); + it('merges user-provided bind parameters with sequelize-generated bind parameters (array bind)', async () => { + const { User } = vars; + const stub = sinon.stub(sequelize, 'queryRaw'); - await sequelize.queryInterface.upsert( - User.tableName, - { - firstName: literal('$1'), - lastName: 'Doe', - }, - {}, - // TODO: weird mssql/db2 specific behavior that should be unified - dialectName === 'mssql' || dialectName === 'db2' ? { id: 1 } : {}, - { - model: User, - bind: ['John'], - }, - ); + await sequelize.queryInterface.upsert( + User.tableName, + { + firstName: literal('$1'), + lastName: 'Doe', + }, + {}, + // TODO: weird mssql/db2 specific behavior that should be unified + dialectName === 'mssql' || dialectName === 'db2' ? { id: 1 } : {}, + { + model: User, + bind: ['John'], + }, + ); - expect(stub.callCount).to.eq(1); - const firstCall = stub.getCall(0); - expectsql(firstCall.args[0], { - default: - 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($1,$sequelize_1) ON CONFLICT ([id]) DO NOTHING;', - 'mariadb mysql': - 'INSERT INTO `Users` (`firstName`,`lastName`) VALUES ($1,$sequelize_1) ON DUPLICATE KEY UPDATE `id`=`id`;', - mssql: ` + expect(stub.callCount).to.eq(1); + const firstCall = stub.getCall(0); + expectsql(firstCall.args[0], { + default: + 'INSERT INTO [Users] ([firstName],[lastName]) VALUES ($1,$sequelize_1) ON CONFLICT ([id]) DO NOTHING;', + 'mariadb mysql': + 'INSERT INTO `Users` (`firstName`,`lastName`) VALUES ($1,$sequelize_1) ON DUPLICATE KEY UPDATE `id`=`id`;', + mssql: ` MERGE INTO [Users] WITH(HOLDLOCK) AS [Users_target] USING (VALUES($1, N'Doe')) AS [Users_source]([firstName], [lastName]) ON [Users_target].[id] = [Users_source].[id] @@ -205,26 +196,25 @@ describe('QueryInterface#upsert', () => { INSERT ([firstName], [lastName]) VALUES($1, N'Doe') OUTPUT $action, INSERTED.*; `, - db2: ` + db2: ` MERGE INTO "Users" AS "Users_target" USING (VALUES($1, 'Doe')) AS "Users_source"("firstName", "lastName") ON "Users_target"."id" = "Users_source"."id" WHEN NOT MATCHED THEN INSERT ("firstName", "lastName") VALUES($1, 'Doe'); `, - }); + }); - // mssql does not generate any bind parameter - if (dialectName === 'mssql' || dialectName === 'db2') { - expect(firstCall.args[1]?.bind).to.deep.eq(['John']); - } else { - expect(firstCall.args[1]?.bind).to.deep.eq({ - 1: 'John', - sequelize_1: 'Doe', - }); - } - }, - ); + // mssql does not generate any bind parameter + if (dialectName === 'mssql' || dialectName === 'db2') { + expect(firstCall.args[1]?.bind).to.deep.eq(['John']); + } else { + expect(firstCall.args[1]?.bind).to.deep.eq({ + 1: 'John', + sequelize_1: 'Doe', + }); + } + }); it('binds parameters if they are literals', async () => { const { User } = vars; @@ -267,7 +257,6 @@ describe('QueryInterface#upsert', () => { ON "Users_target"."id" = "Users_source"."id" WHEN MATCHED THEN UPDATE SET "Users_target"."counter" = \`counter\` + 1 WHEN NOT MATCHED THEN INSERT ("firstName", "counter") VALUES('Jonh', \`counter\` + 1); `, - oracle: `DECLARE BEGIN UPDATE "Users" SET "counter"=\`counter\` + 1; IF (SQL%ROWCOUNT = 0) THEN INSERT INTO "Users" ("firstName","counter") VALUES (:1,\`counter\` + 1); :isUpdate := 0; ELSE :isUpdate := 1; END IF; END;`, }); }); }); diff --git a/packages/core/test/unit/sql/add-column.test.js b/packages/core/test/unit/sql/add-column.test.js index 6d9e6209a6b5..80fc01bdd300 100644 --- a/packages/core/test/unit/sql/add-column.test.js +++ b/packages/core/test/unit/sql/add-column.test.js @@ -115,7 +115,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'ALTER TABLE "custom"."Users" ADD "level_id" REAL NOT NULL;', snowflake: 'ALTER TABLE "custom"."Users" ADD "level_id" FLOAT NOT NULL;', ibmi: 'ALTER TABLE "custom"."Users" ADD "level_id" REAL NOT NULL', - oracle: 'ALTER TABLE "custom"."Users" ADD "level_id" BINARY_FLOAT NOT NULL;', }, ); }); diff --git a/packages/core/test/unit/sql/change-column.test.js b/packages/core/test/unit/sql/change-column.test.js index 35a614d4ec05..d96a70a90e37 100644 --- a/packages/core/test/unit/sql/change-column.test.js +++ b/packages/core/test/unit/sql/change-column.test.js @@ -56,7 +56,6 @@ describe('QueryInterface#changeColumn', () => { 'ALTER TABLE "users" ALTER COLUMN "level_id" SET NOT NULL;ALTER TABLE "users" ALTER COLUMN "level_id" DROP DEFAULT;ALTER TABLE "users" ALTER COLUMN "level_id" TYPE REAL;', snowflake: 'ALTER TABLE "users" ALTER COLUMN "level_id" SET NOT NULL;ALTER TABLE "users" ALTER COLUMN "level_id" DROP DEFAULT;ALTER TABLE "users" ALTER COLUMN "level_id" TYPE FLOAT;', - oracle: `DECLARE CONS_NAME VARCHAR2(200); BEGIN BEGIN EXECUTE IMMEDIATE 'ALTER TABLE "users" MODIFY "level_id" BINARY_FLOAT NOT NULL'; EXCEPTION WHEN OTHERS THEN IF SQLCODE = -1442 OR SQLCODE = -1451 THEN EXECUTE IMMEDIATE 'ALTER TABLE "users" MODIFY "level_id" BINARY_FLOAT '; ELSE RAISE; END IF; END; END;`, }); }); @@ -86,12 +85,6 @@ describe('QueryInterface#changeColumn', () => { 'ALTER TABLE "users" ADD FOREIGN KEY ("level_id") REFERENCES "level" ("id") ON DELETE CASCADE ON UPDATE CASCADE;', snowflake: 'ALTER TABLE "users" ADD FOREIGN KEY ("level_id") REFERENCES "level" ("id") ON DELETE CASCADE ON UPDATE CASCADE;', - oracle: `DECLARE CONS_NAME VARCHAR2(200); BEGIN BEGIN SELECT constraint_name INTO cons_name - FROM - (SELECT DISTINCT cc.owner, cc.table_name, cc.constraint_name, cc.column_name AS cons_columns FROM all_cons_columns cc, all_constraints c WHERE cc.owner = c.owner AND cc.table_name = c.table_name AND cc.constraint_name = c.constraint_name AND c.constraint_type = 'R' GROUP BY cc.owner, cc.table_name, cc.constraint_name, cc.column_name) - WHERE owner = '${sequelize.dialect.getDefaultSchema()}' AND table_name = 'users' AND cons_columns = 'level_id' ; - EXCEPTION WHEN NO_DATA_FOUND THEN CONS_NAME := NULL; END; IF CONS_NAME IS NOT NULL THEN EXECUTE IMMEDIATE 'ALTER TABLE "users" DROP CONSTRAINT "'||CONS_NAME||'"'; END IF; - EXECUTE IMMEDIATE 'ALTER TABLE "users" ADD FOREIGN KEY ("level_id") REFERENCES "level" ("id") ON DELETE CASCADE'; END;`, }); }); }); diff --git a/packages/core/test/unit/sql/create-table.test.js b/packages/core/test/unit/sql/create-table.test.js index 7df494826e5b..26b09ddd3b03 100644 --- a/packages/core/test/unit/sql/create-table.test.js +++ b/packages/core/test/unit/sql/create-table.test.js @@ -42,7 +42,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { BEGIN END; CREATE TABLE "foo"."users" ("id" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) , "mood" VARCHAR(255) CHECK ("mood" IN('happy', 'sad')), PRIMARY KEY ("id")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "foo"."users" ("id" NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY, "mood" VARCHAR2(512) CHECK ("mood" IN(''happy'', ''sad'')),PRIMARY KEY ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -91,7 +90,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { BEGIN END; CREATE TABLE "bar"."projects" ("id" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) , "user_id" INTEGER REFERENCES "bar"."users" ("id") ON DELETE NO ACTION, PRIMARY KEY ("id")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "bar"."projects" ("id" NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY, "user_id" INTEGER NULL,PRIMARY KEY ("id"),FOREIGN KEY ("user_id") REFERENCES "bar"."users" ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); @@ -136,7 +134,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { BEGIN END; CREATE TABLE "images" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) REFERENCES "files" ("id"), PRIMARY KEY ("id")); END`, - oracle: `BEGIN EXECUTE IMMEDIATE 'CREATE TABLE "images" ("id" NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY,PRIMARY KEY ("id"),FOREIGN KEY ("id") REFERENCES "files" ("id"))'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;`, }, ); }); diff --git a/packages/core/test/unit/sql/generateJoin.test.js b/packages/core/test/unit/sql/generateJoin.test.js index 4d5165f01790..a0b2fb6c58ba 100644 --- a/packages/core/test/unit/sql/generateJoin.test.js +++ b/packages/core/test/unit/sql/generateJoin.test.js @@ -122,7 +122,6 @@ describe('QueryGenerator#generateJoin', () => { }, { default: 'LEFT OUTER JOIN [company] AS [Company] ON [User].[company_id] = [Company].[id]', - oracle: `LEFT OUTER JOIN "company" "Company" ON "User"."company_id" = "Company"."id"`, }, ); }); @@ -150,7 +149,6 @@ describe('QueryGenerator#generateJoin', () => { 'INNER JOIN `company` AS `Company` ON `User`.`company_id` = `Company`.`id` OR `Company`.`public` = 1', mssql: 'INNER JOIN [company] AS [Company] ON [User].[company_id] = [Company].[id] OR [Company].[public] = 1', - oracle: `INNER JOIN "company" "Company" ON "User"."company_id" = "Company"."id" OR "Company"."public" = 1`, }, ); }); @@ -173,7 +171,6 @@ describe('QueryGenerator#generateJoin', () => { { default: 'LEFT OUTER JOIN [company] AS [Professionals->Company] ON [Professionals].[company_id] = [Professionals->Company].[id]', - oracle: `LEFT OUTER JOIN "company" "Professionals->Company" ON "Professionals"."company_id" = "Professionals->Company"."id"`, }, ); }); @@ -190,7 +187,6 @@ describe('QueryGenerator#generateJoin', () => { }, { default: 'LEFT OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id]', - oracle: `LEFT OUTER JOIN "company" "Company" ON "User"."companyId" = "Company"."id"`, }, ); }); @@ -216,7 +212,6 @@ describe('QueryGenerator#generateJoin', () => { "LEFT OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id] AND [Company].[name] = 'ABC'", mssql: "LEFT OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id] AND [Company].[name] = N'ABC'", - oracle: `LEFT OUTER JOIN "company" "Company" ON "User"."companyId" = "Company"."id" AND "Company"."name" = 'ABC'`, }, ); }); @@ -238,7 +233,6 @@ describe('QueryGenerator#generateJoin', () => { }, { default: `${sequelize.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id]`, - oracle: `RIGHT OUTER JOIN "company" "Company" ON "User"."companyId" = "Company"."id"`, }, ); }); @@ -261,7 +255,6 @@ describe('QueryGenerator#generateJoin', () => { { default: 'LEFT OUTER JOIN [user] AS [Company->Owner] ON [Company].[owner_id] = [Company->Owner].[id_user]', - oracle: `LEFT OUTER JOIN "user" "Company->Owner" ON "Company"."owner_id" = "Company->Owner"."id_user"`, }, ); }); @@ -289,7 +282,6 @@ describe('QueryGenerator#generateJoin', () => { { default: 'LEFT OUTER JOIN [profession] AS [Company->Owner->Profession] ON [Company->Owner].[professionId] = [Company->Owner->Profession].[id]', - oracle: `LEFT OUTER JOIN "profession" "Company->Owner->Profession" ON "Company->Owner"."professionId" = "Company->Owner->Profession"."id"`, }, ); }); @@ -313,7 +305,6 @@ describe('QueryGenerator#generateJoin', () => { { default: 'LEFT OUTER JOIN [user] AS [Company->Owner] ON [Company].[owner_id] = [Company->Owner].[id_user]', - oracle: `LEFT OUTER JOIN "user" "Company->Owner" ON "Company"."owner_id" = "Company->Owner"."id_user"`, }, ); }); @@ -330,7 +321,6 @@ describe('QueryGenerator#generateJoin', () => { }, { default: 'INNER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id]', - oracle: `INNER JOIN "company" "Company" ON "User"."companyId" = "Company"."id"`, }, ); }); @@ -348,10 +338,7 @@ describe('QueryGenerator#generateJoin', () => { model: User, include: [User.Tasks], }, - { - default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [User].[id_user] = [Tasks].[user_id]', - oracle: `LEFT OUTER JOIN "task" "Tasks" ON "User"."id_user" = "Tasks"."user_id"`, - }, + { default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [User].[id_user] = [Tasks].[user_id]' }, ); }); @@ -368,7 +355,6 @@ describe('QueryGenerator#generateJoin', () => { { // The primary key of the main model will be aliased because it's coming from a subquery that the :M join is not a part of default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [User].[id] = [Tasks].[user_id]', - oracle: `LEFT OUTER JOIN "task" "Tasks" ON "User"."id" = "Tasks"."user_id"`, }, ); }); @@ -395,7 +381,6 @@ describe('QueryGenerator#generateJoin', () => { { default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [User].[id_user] = [Tasks].[user_id] OR [Tasks].[user_id] = 2', - oracle: `LEFT OUTER JOIN "task" "Tasks" ON "User"."id_user" = "Tasks"."user_id" OR "Tasks"."user_id" = 2`, }, ); }); @@ -416,7 +401,6 @@ describe('QueryGenerator#generateJoin', () => { }, { default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [Tasks].[user_id] = [User].[alternative_id]', - oracle: `LEFT OUTER JOIN "task" "Tasks" ON "Tasks"."user_id" = "User"."alternative_id"`, }, ); }); @@ -449,7 +433,6 @@ describe('QueryGenerator#generateJoin', () => { { default: 'LEFT OUTER JOIN [user] AS [Company->Owner] ON [Company].[owner_id] = [Company->Owner].[id_user] OR [Company->Owner].[id_user] = 2', - oracle: `LEFT OUTER JOIN "user" "Company->Owner" ON "Company"."owner_id" = "Company->Owner"."id_user" OR "Company->Owner"."id_user" = 2`, }, ); }); diff --git a/packages/core/test/unit/sql/group.test.js b/packages/core/test/unit/sql/group.test.js index ab575a5c94a5..f327048c072f 100644 --- a/packages/core/test/unit/sql/group.test.js +++ b/packages/core/test/unit/sql/group.test.js @@ -42,7 +42,6 @@ describe('QueryGenerator#selectQuery with "group"', () => { ibmi: 'SELECT * FROM "Users" AS "User" GROUP BY "name"', mssql: 'SELECT * FROM [Users] AS [User] GROUP BY [name];', snowflake: 'SELECT * FROM "Users" AS "User" GROUP BY "name";', - oracle: `SELECT * FROM "Users" "User" GROUP BY "name";`, }, ); }); @@ -62,7 +61,6 @@ describe('QueryGenerator#selectQuery with "group"', () => { ibmi: 'SELECT * FROM "Users" AS "User"', mssql: 'SELECT * FROM [Users] AS [User];', snowflake: 'SELECT * FROM "Users" AS "User";', - oracle: `SELECT * FROM "Users" "User";`, }, ); }); diff --git a/packages/core/test/unit/sql/index.test.js b/packages/core/test/unit/sql/index.test.js index d5b8cb1b5366..c646239e6a2b 100644 --- a/packages/core/test/unit/sql/index.test.js +++ b/packages/core/test/unit/sql/index.test.js @@ -89,7 +89,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: 'CREATE INDEX CONCURRENTLY "user_field_c" ON "User" ("fieldC")', mariadb: 'ALTER TABLE `User` ADD FULLTEXT INDEX `user_field_c` (`fieldC`)', mysql: 'ALTER TABLE `User` ADD FULLTEXT INDEX `user_field_c` (`fieldC`)', - oracle: `CREATE INDEX "user_field_c" ON "User" ("fieldC")`, }, ); @@ -120,7 +119,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'ALTER TABLE `User` ADD UNIQUE INDEX `a_b_uniq` USING BTREE (`fieldB`, `fieldA`(5) DESC) WITH PARSER foo', mysql: 'ALTER TABLE `User` ADD UNIQUE INDEX `a_b_uniq` USING BTREE (`fieldB`, `fieldA`(5) DESC) WITH PARSER foo', - oracle: `CREATE UNIQUE INDEX "a_b_uniq" ON "User" ("fieldB", "fieldA" DESC)`, }, ); }); @@ -140,7 +138,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ibmi: 'CREATE INDEX "table_column" ON "table" ("column" DESC)', mariadb: 'ALTER TABLE `table` ADD INDEX `table_column` (`column`(5) DESC)', mysql: 'ALTER TABLE `table` ADD INDEX `table_column` (`column`(5) DESC)', - oracle: `CREATE INDEX "table_column" ON "table" ("column" DESC)`, }, ); }); diff --git a/packages/core/test/unit/sql/insert.test.js b/packages/core/test/unit/sql/insert.test.js index e58641ad99be..2974bd666a71 100644 --- a/packages/core/test/unit/sql/insert.test.js +++ b/packages/core/test/unit/sql/insert.test.js @@ -43,7 +43,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'INSERT INTO "users" ("user_name") VALUES ($sequelize_1) RETURNING "id", "user_name";', db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("user_name") VALUES ($sequelize_1));', snowflake: 'INSERT INTO "users" ("user_name") VALUES ($sequelize_1);', - oracle: `INSERT INTO "users" ("user_name") VALUES (:1) RETURNING "id", "user_name" INTO :2,:3;`, default: 'INSERT INTO `users` (`user_name`) VALUES ($sequelize_1);', }, bind: { sequelize_1: 'triggertest' }, @@ -68,7 +67,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ibmi: 'SELECT * FROM FINAL TABLE (INSERT INTO "ms" ("id") VALUES ($sequelize_1))', postgres: 'INSERT INTO "ms" ("id") VALUES ($sequelize_1);', snowflake: 'INSERT INTO "ms" ("id") VALUES ($sequelize_1);', - oracle: `INSERT INTO "ms" ("id") VALUES (:1);`, default: 'INSERT INTO `ms` (`id`) VALUES ($sequelize_1);', }, bind: { sequelize_1: 0 }, @@ -170,7 +168,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { { query: { default: 'INSERT INTO [users] ([date]) VALUES ($sequelize_1);', - oracle: `INSERT INTO "users" ("date") VALUES (:1);`, }, bind: { // these dialects change the DB-side timezone, and the input doesn't specify the timezone offset, so we have to offset the value ourselves @@ -180,7 +177,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: { sequelize_1: '2015-01-20 01:00:00.000' }, // These dialects do specify the offset, so they can use whichever offset they want. postgres: { sequelize_1: '2015-01-20 01:00:00.000 +01:00' }, - oracle: { sequelize_1: new Date(Date.UTC(2015, 0, 20)) }, }, }, ); @@ -214,7 +210,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("date") VALUES ($sequelize_1));', snowflake: 'INSERT INTO "users" ("date") VALUES ($sequelize_1);', mssql: 'INSERT INTO [users] ([date]) VALUES ($sequelize_1);', - oracle: `INSERT INTO "users" ("date") VALUES (:1);`, default: 'INSERT INTO `users` (`date`) VALUES ($sequelize_1);', }, bind: { @@ -226,7 +221,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite3: { sequelize_1: '2015-01-20 00:00:00.000 +00:00' }, mssql: { sequelize_1: '2015-01-20 00:00:00.000 +00:00' }, postgres: { sequelize_1: '2015-01-20 00:00:00.000 +00:00' }, - oracle: { sequelize_1: new Date(Date.UTC(2015, 0, 20)) }, }, }, ); @@ -259,7 +253,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("date") VALUES ($sequelize_1));', snowflake: 'INSERT INTO "users" ("date") VALUES ($sequelize_1);', mssql: 'INSERT INTO [users] ([date]) VALUES ($sequelize_1);', - oracle: `INSERT INTO "users" ("date") VALUES (:1);`, default: 'INSERT INTO `users` (`date`) VALUES ($sequelize_1);', }, bind: { @@ -271,7 +264,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite3: { sequelize_1: '2015-01-20 01:02:03.089 +00:00' }, postgres: { sequelize_1: '2015-01-20 01:02:03.089 +00:00' }, mssql: { sequelize_1: '2015-01-20 01:02:03.089 +00:00' }, - oracle: { sequelize_1: new Date(Date.UTC(2015, 0, 20, 1, 2, 3, 89)) }, }, }, ); @@ -300,7 +292,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("user_name") VALUES ($sequelize_1));', snowflake: 'INSERT INTO "users" ("user_name") VALUES ($sequelize_1);', mssql: 'INSERT INTO [users] ([user_name]) VALUES ($sequelize_1);', - oracle: `INSERT INTO "users" ("user_name") VALUES (:1);`, default: 'INSERT INTO `users` (`user_name`) VALUES ($sequelize_1);', }, bind: { @@ -364,12 +355,11 @@ describe(Support.getTestDialectTeaser('SQL'), () => { "INSERT INTO `users` (`user_name`,`pass_word`) VALUES ('testuser','12345') ON DUPLICATE KEY UPDATE `user_name`=VALUES(`user_name`),`pass_word`=VALUES(`pass_word`),`updated_at`=VALUES(`updated_at`);", sqlite3: "INSERT INTO `users` (`user_name`,`pass_word`) VALUES ('testuser','12345') ON CONFLICT (`user_name`) DO UPDATE SET `user_name`=EXCLUDED.`user_name`,`pass_word`=EXCLUDED.`pass_word`,`updated_at`=EXCLUDED.`updated_at`;", - oracle: `INSERT INTO "users" ("user_name","pass_word") VALUES (:1,:2)`, }, ); }); - (dialect.name !== 'oracle' ? it : it.skip)('allow bulk insert primary key with 0', () => { + it('allow bulk insert primary key with 0', () => { const M = Support.sequelize.define('m', { id: { type: DataTypes.INTEGER, diff --git a/packages/core/test/unit/sql/literal.test.ts b/packages/core/test/unit/sql/literal.test.ts index b98c9be3e8ea..252dea97f22d 100644 --- a/packages/core/test/unit/sql/literal.test.ts +++ b/packages/core/test/unit/sql/literal.test.ts @@ -23,7 +23,6 @@ describe('json', () => { sqlite3: `(json_extract(\`metadata\`,'$.language') = '"icelandic"' AND json_extract(\`metadata\`,'$.pg_rating.dk') = '"G"') AND json_extract(\`another_json_field\`,'$.x') = '1'`, mariadb: `(json_compact(json_extract(\`metadata\`,'$.language')) = '"icelandic"' AND json_compact(json_extract(\`metadata\`,'$.pg_rating.dk')) = '"G"') AND json_compact(json_extract(\`another_json_field\`,'$.x')) = '1'`, mysql: `(json_extract(\`metadata\`,'$.language') = CAST('"icelandic"' AS JSON) AND json_extract(\`metadata\`,'$.pg_rating.dk') = CAST('"G"' AS JSON)) AND json_extract(\`another_json_field\`,'$.x') = CAST('1' AS JSON)`, - oracle: `(json_value("metadata",'$."language"') = 'icelandic' AND json_value("metadata",'$."pg_rating"."dk"') = 'G') AND json_value("another_json_field",'$."x"') = '1'`, }); }); @@ -34,7 +33,6 @@ describe('json', () => { postgres: `"metadata"#>ARRAY['pg_rating','dk']::VARCHAR(255)[]`, mariadb: `json_compact(json_extract(\`metadata\`,'$.pg_rating.dk'))`, 'sqlite3 mysql': `json_extract(\`metadata\`,'$.pg_rating.dk')`, - oracle: `json_value("metadata",'$."pg_rating"."dk"')`, }); }); @@ -43,7 +41,6 @@ describe('json', () => { postgres: `"profile"#>ARRAY['id','0','1']::VARCHAR(255)[]`, mariadb: `json_compact(json_extract(\`profile\`,'$.id."0"."1"'))`, 'sqlite3 mysql': `json_extract(\`profile\`,'$.id."0"."1"')`, - oracle: `json_value("profile",'$."id"[0][1]')`, }); }); @@ -56,7 +53,6 @@ describe('json', () => { sqlite3: `json_extract(\`metadata\`,'$.pg_rating.is') = '"U"'`, mariadb: `json_compact(json_extract(\`metadata\`,'$.pg_rating.is')) = '"U"'`, mysql: `json_extract(\`metadata\`,'$.pg_rating.is') = CAST('"U"' AS JSON)`, - oracle: `json_value("metadata",'$."pg_rating"."is"') = 'U'`, }); }); @@ -79,7 +75,6 @@ describe('json', () => { sqlite3: `json_extract(\`profile\`,'$.id') = '1'`, mariadb: `json_compact(json_extract(\`profile\`,'$.id')) = '1'`, mysql: `json_extract(\`profile\`,'$.id') = CAST('1' AS JSON)`, - oracle: `json_value("profile",'$."id"') = '1'`, }); }); @@ -91,7 +86,6 @@ describe('json', () => { sqlite3: `json_extract(\`property\`,'$.value') = '1' AND json_extract(\`another\`,'$.value') = '"string"'`, mariadb: `json_compact(json_extract(\`property\`,'$.value')) = '1' AND json_compact(json_extract(\`another\`,'$.value')) = '"string"'`, mysql: `json_extract(\`property\`,'$.value') = CAST('1' AS JSON) AND json_extract(\`another\`,'$.value') = CAST('"string"' AS JSON)`, - oracle: `json_value("property",'$."value"') = '1' AND json_value("another",'$."value"') = 'string'`, }, ); }); @@ -102,7 +96,6 @@ describe('json', () => { sqlite3: `json_extract(\`profile\`,'$.id') = '"1"'`, mariadb: `json_compact(json_extract(\`profile\`,'$.id')) = '"1"'`, mysql: `json_extract(\`profile\`,'$.id') = CAST('"1"' AS JSON)`, - oracle: `json_value("profile",'$."id"') = '1'`, }); }); }); @@ -161,7 +154,6 @@ describe('fn', () => { mssql: `concat(N'user', 1, 1, N'2011-03-27 10:01:55.000 +00:00', lower(N'user'))`, sqlite3: `concat('user', 1, 1, '2011-03-27 10:01:55.000 +00:00', lower('user'))`, ibmi: `concat('user', 1, 1, '2011-03-27 10:01:55.000', lower('user'))`, - oracle: `concat('user', 1, 1, TO_TIMESTAMP_TZ('2011-03-27 10:01:55.000 +00:00', 'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM'), lower('user'))`, default: `concat('user', 1, true, '2011-03-27 10:01:55.000', lower('user'))`, }); }); diff --git a/packages/core/test/unit/sql/order.test.js b/packages/core/test/unit/sql/order.test.js index cd20cc643e4c..aa6f7285eacf 100644 --- a/packages/core/test/unit/sql/order.test.js +++ b/packages/core/test/unit/sql/order.test.js @@ -336,7 +336,6 @@ describe('QueryGenerator#selectQuery with "order"', () => { 'SELECT [Subtask].[id], [Subtask].[name], [Subtask].[createdAt], [Task].[id] AS [Task.id], [Task].[name] AS [Task.name], [Task].[created_at] AS [Task.createdAt], [Task->Project].[id] AS [Task.Project.id], [Task->Project].[name] AS [Task.Project.name], [Task->Project].[created_at] AS [Task.Project.createdAt] FROM [subtask] AS [Subtask] INNER JOIN [task] AS [Task] ON [Subtask].[task_id] = [Task].[id] INNER JOIN [project] AS [Task->Project] ON [Task].[project_id] = [Task->Project].[id] ORDER BY [Task->Project].[created_at] ASC, [Task->Project].[created_at], [Task].[created_at] ASC, [Task].[created_at], [Task->Project].[created_at] ASC, [Task->Project].[created_at], [Task].[created_at] ASC, [Task].[created_at], [Task->Project].[created_at] ASC, [Task->Project].[created_at], [Task].[created_at] ASC, [Task].[created_at], [Task->Project].[created_at] ASC, [Task->Project].[created_at], [Task].[created_at] ASC, [Task].[created_at], [Subtask].[created_at] ASC, [Subtask].[created_at], [Subtask].[created_at];', postgres: 'SELECT "Subtask"."id", "Subtask"."name", "Subtask"."createdAt", "Task"."id" AS "Task.id", "Task"."name" AS "Task.name", "Task"."created_at" AS "Task.createdAt", "Task->Project"."id" AS "Task.Project.id", "Task->Project"."name" AS "Task.Project.name", "Task->Project"."created_at" AS "Task.Project.createdAt" FROM "subtask" AS "Subtask" INNER JOIN "task" AS "Task" ON "Subtask"."task_id" = "Task"."id" INNER JOIN "project" AS "Task->Project" ON "Task"."project_id" = "Task->Project"."id" ORDER BY "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Subtask"."created_at" ASC, "Subtask"."created_at", "Subtask"."created_at";', - oracle: `SELECT "Subtask"."id", "Subtask"."name", "Subtask"."createdAt", "Task"."id" AS "Task.id", "Task"."name" AS "Task.name", "Task"."created_at" AS "Task.createdAt", "Task->Project"."id" AS "Task.Project.id", "Task->Project"."name" AS "Task.Project.name", "Task->Project"."created_at" AS "Task.Project.createdAt" FROM "subtask" "Subtask" INNER JOIN "task" "Task" ON "Subtask"."task_id" = "Task"."id" INNER JOIN "project" "Task->Project" ON "Task"."project_id" = "Task->Project"."id" ORDER BY "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Subtask"."created_at" ASC, "Subtask"."created_at", "Subtask"."created_at";`, }, ); }); @@ -359,7 +358,6 @@ describe('QueryGenerator#selectQuery with "order"', () => { postgres: 'SELECT "id", "name" FROM "subtask" AS "Subtask" ORDER BY RANDOM();', snowflake: 'SELECT "id", "name" FROM "subtask" AS "Subtask" ORDER BY RANDOM();', sqlite3: 'SELECT `id`, `name` FROM `subtask` AS `Subtask` ORDER BY RANDOM();', - oracle: `SELECT "id", "name" FROM "subtask" "Subtask" ORDER BY RAND();`, }, ); }); diff --git a/packages/core/test/unit/sql/select.test.js b/packages/core/test/unit/sql/select.test.js index 417c49e5a773..a269ff2f66bf 100644 --- a/packages/core/test/unit/sql/select.test.js +++ b/packages/core/test/unit/sql/select.test.js @@ -53,7 +53,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mssql: "SELECT [email], [first_name] AS [firstName] FROM [User] WHERE [User].[email] = N'jon.snow@gmail.com' ORDER BY [email] DESC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;", ibmi: 'SELECT "email", "first_name" AS "firstName" FROM "User" WHERE "User"."email" = \'jon.snow@gmail.com\' ORDER BY "email" DESC FETCH NEXT 10 ROWS ONLY', - oracle: `SELECT "email", "first_name" AS "firstName" FROM "User" WHERE "User"."email" = 'jon.snow@gmail.com' ORDER BY "email" DESC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;`, }, ); @@ -81,12 +80,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { `SELECT * FROM (SELECT [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [User] WHERE [User].[companyId] = 1 ORDER BY [last_name] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) AS sub`, `SELECT * FROM (SELECT [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [User] WHERE [User].[companyId] = 5 ORDER BY [last_name] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) AS sub`, ].join(current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ')}) AS [User];`, - oracle: `SELECT "User".* FROM (${[ - `SELECT * FROM (SELECT "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "User" WHERE "User"."companyId" = 1 ORDER BY "last_name" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub`, - `SELECT * FROM (SELECT "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "User" WHERE "User"."companyId" = 5 ORDER BY "last_name" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub`, - ].join( - current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', - )}) "User" ORDER BY "last_name" ASC;`, }, ); @@ -202,26 +195,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ].join( current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', )}) AS [user] ORDER BY [subquery_order_0] ASC;`, - oracle: `SELECT "user".* FROM (${[ - `SELECT * FROM ( - SELECT "user"."id_user" AS "id", "user"."last_name" AS "subquery_order_0", "project_user"."user_id" AS "project_user.userId", "project_user"."project_id" AS "project_user.projectId" - FROM "users" "user" - INNER JOIN "project_users" "project_user" - ON "user"."id_user" = "project_user"."user_id" - AND "project_user"."project_id" = 1 - ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY - ) sub`, - `SELECT * FROM ( - SELECT "user"."id_user" AS "id", "user"."last_name" AS "subquery_order_0", "project_user"."user_id" AS "project_user.userId", "project_user"."project_id" AS "project_user.projectId" - FROM "users" "user" - INNER JOIN "project_users" "project_user" - ON "user"."id_user" = "project_user"."user_id" - AND "project_user"."project_id" = 5 - ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY - ) sub`, - ].join( - current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', - )}) "user" ORDER BY "subquery_order_0" ASC;`, }, ); }); @@ -313,26 +286,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ].join( current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', )}) AS [user] ORDER BY [subquery_order_0] ASC;`, - oracle: `SELECT "user".* FROM (${[ - `SELECT * FROM ( - SELECT "user"."id_user" AS "id", "user"."last_name" AS "subquery_order_0", "project_user"."user_id" AS "project_user.userId", "project_user"."project_id" AS "project_user.projectId" - FROM "users" "user" - INNER JOIN "project_users" "project_user" - ON "user"."id_user" = "project_user"."user_id" - AND ("project_user"."project_id" = 1 AND "project_user"."status" = 1) - ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY - ) sub`, - `SELECT * FROM ( - SELECT "user"."id_user" AS "id", "user"."last_name" AS "subquery_order_0", "project_user"."user_id" AS "project_user.userId", "project_user"."project_id" AS "project_user.projectId" - FROM "users" "user" - INNER JOIN "project_users" "project_user" - ON "user"."id_user" = "project_user"."user_id" - AND ("project_user"."project_id" = 5 AND "project_user"."status" = 1) - ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY - ) sub`, - ].join( - current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', - )}) "user" ORDER BY "subquery_order_0" ASC;`, }, ); }); @@ -424,27 +377,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ].join( current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', )}) AS [user] ORDER BY [subquery_order_0] ASC;`, - oracle: `SELECT "user".* FROM (${[ - `SELECT * FROM ( - SELECT "user"."id_user" AS "id", "user"."id_user" AS "subquery_order_0", "project_user"."user_id" AS "project_user.userId", "project_user"."project_id" AS "project_user.projectId" - FROM "users" "user" - INNER JOIN "project_users" "project_user" - ON "user"."id_user" = "project_user"."user_id" - AND "project_user"."project_id" = 1 WHERE "user"."age" >= 21 - ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY - ) sub`, - `SELECT * FROM ( - SELECT "user"."id_user" AS "id", "user"."id_user" AS "subquery_order_0", "project_user"."user_id" AS "project_user.userId", "project_user"."project_id" AS "project_user.projectId" - FROM "users" "user" - INNER JOIN "project_users" "project_user" - ON "user"."id_user" = "project_user"."user_id" - AND "project_user"."project_id" = 5 - WHERE "user"."age" >= 21 - ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY - ) sub`, - ].join( - current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', - )}) "user" ORDER BY "subquery_order_0" ASC;`, }, ); }); @@ -560,12 +492,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ].join( current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', )}) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id] = [POSTS].[user_id];`, - oracle: `SELECT "user".*, "POSTS"."id" AS "POSTS.id", "POSTS"."title" AS "POSTS.title" FROM (${[ - `SELECT * FROM (SELECT "id_user" AS "id", "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "users" "user" WHERE "user"."companyId" = 1 ORDER BY "lastName" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub`, - `SELECT * FROM (SELECT "id_user" AS "id", "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "users" "user" WHERE "user"."companyId" = 5 ORDER BY "lastName" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub`, - ].join( - current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', - )}) "user" LEFT OUTER JOIN "post" "POSTS" ON "user"."id" = "POSTS"."user_id" ORDER BY "lastName" ASC;`, }, ); }); @@ -602,7 +528,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { { default: `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title] FROM (SELECT [user].[id_user] AS [id], [user].[email], [user].[first_name] AS [firstName], [user].[last_name] AS [lastName] FROM [users] AS [user] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC LIMIT 30 OFFSET 10) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id_user] = [POSTS].[user_id] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC;`, 'db2 ibmi mssql': `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title] FROM (SELECT [user].[id_user] AS [id], [user].[email], [user].[first_name] AS [firstName], [user].[last_name] AS [lastName] FROM [users] AS [user] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC OFFSET 10 ROWS FETCH NEXT 30 ROWS ONLY) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id_user] = [POSTS].[user_id] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC;`, - oracle: `SELECT "user".*, "POSTS"."id" AS "POSTS.id", "POSTS"."title" AS "POSTS.title" FROM (SELECT "user"."id_user" AS "id", "user"."email", "user"."first_name" AS "firstName", "user"."last_name" AS "lastName" FROM "users" "user" ORDER BY "user".${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC OFFSET 10 ROWS FETCH NEXT 30 ROWS ONLY) "user" LEFT OUTER JOIN "post" "POSTS" ON "user"."id_user" = "POSTS"."user_id" ORDER BY "user".${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC;`, }, ); }); @@ -647,11 +572,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { FROM [users] AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id_user] = [POSTS].[user_id] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC OFFSET 10 ROWS FETCH NEXT 30 ROWS ONLY;`, - oracle: - Support.minifySql(`SELECT "user"."id_user" AS "id", "user"."email", "user"."first_name" AS "firstName", "user"."last_name" AS "lastName", "POSTS"."id" AS "POSTS.id", "POSTS"."title" AS "POSTS.title" - FROM "users" "user" LEFT OUTER JOIN "post" "POSTS" - ON "user"."id_user" = "POSTS"."user_id" - ORDER BY "user".${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC OFFSET 10 ROWS FETCH NEXT 30 ROWS ONLY;`), }, ); }); @@ -711,12 +631,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ].join( current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', )}) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id] = [POSTS].[user_id] LEFT OUTER JOIN [comment] AS [POSTS->COMMENTS] ON [POSTS].[id] = [POSTS->COMMENTS].[post_id];`, - oracle: `SELECT "user".*, "POSTS"."id" AS "POSTS.id", "POSTS"."title" AS "POSTS.title", "POSTS->COMMENTS"."id" AS "POSTS.COMMENTS.id", "POSTS->COMMENTS"."title" AS "POSTS.COMMENTS.title" FROM (${[ - `SELECT * FROM (SELECT "id_user" AS "id", "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "users" "user" WHERE "user"."companyId" = 1 ORDER BY "lastName" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub`, - `SELECT * FROM (SELECT "id_user" AS "id", "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "users" "user" WHERE "user"."companyId" = 5 ORDER BY "lastName" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub`, - ].join( - current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ', - )}) "user" LEFT OUTER JOIN "post" "POSTS" ON "user"."id" = "POSTS"."user_id" LEFT OUTER JOIN "comment" "POSTS->COMMENTS" ON "POSTS"."id" = "POSTS->COMMENTS"."post_id" ORDER BY "lastName" ASC;`, }, ); }); @@ -765,7 +679,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ), { ibmi: 'SELECT "User"."name", "User"."age", "posts"."id" AS "posts.id", "posts"."title" AS "posts.title" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "posts" ON "User"."id" = "posts"."user_id"', - oracle: `SELECT "User"."name", "User"."age", "posts"."id" AS "posts.id", "posts"."title" AS "posts.title" FROM "User" "User" LEFT OUTER JOIN "Post" "posts" ON "User"."id" = "posts"."user_id";`, default: 'SELECT [User].[name], [User].[age], [posts].[id] AS [posts.id], [posts].[title] AS [posts.title] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [posts] ON [User].[id] = [posts].[user_id];', }, @@ -816,7 +729,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ), { default: `SELECT [User].[name], [User].[age], [posts].[id] AS [posts.id], [posts].[title] AS [posts.title] FROM [User] AS [User] ${current.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN [Post] AS [posts] ON [User].[id] = [posts].[user_id];`, - oracle: `SELECT "User"."name", "User"."age", "posts"."id" AS "posts.id", "posts"."title" AS "posts.title" FROM "User" "User" ${current.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN "Post" "posts" ON "User"."id" = "posts"."user_id";`, }, ); }); @@ -891,23 +803,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ) ON [user].[id_user] = [projects->project_user].[user_id] ORDER BY [projects->project_user].[user_id] ASC;`, - oracle: ` - SELECT "user"."id_user", - "user"."id", - "projects"."id" AS "projects.id", - "projects"."title" AS "projects.title", - "projects"."createdAt" AS "projects.createdAt", - "projects"."updatedAt" AS "projects.updatedAt", - "projects->project_user"."user_id" AS "projects.project_user.userId", - "projects->project_user"."project_id" AS "projects.project_user.projectId" - FROM "User" "user" - ${current.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN ( - "project_users" "projects->project_user" - INNER JOIN "projects" "projects" - ON "projects"."id" = "projects->project_user"."project_id" - ) - ON "user"."id_user" = "projects->project_user"."user_id" - ORDER BY "projects->project_user"."user_id" ASC;`, }, ); }); @@ -982,11 +877,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { '(SELECT [User].[name], [User].[age], [User].[id], [postaliasname].[id] AS [postaliasname.id], [postaliasname].[title] AS [postaliasname.title] FROM [User] AS [User] ' + 'INNER JOIN [Post] AS [postaliasname] ON [User].[id] = [postaliasname].[user_id] ' + `WHERE ( SELECT [user_id] FROM [Post] AS [postaliasname] WHERE [postaliasname].[user_id] = [User].[id] ORDER BY [postaliasname].[id] OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY) IS NOT NULL) AS [User];`, - oracle: - `SELECT "User".* FROM ` + - `(SELECT "User"."name", "User"."age", "User"."id", "postaliasname"."id" AS "postaliasname.id", "postaliasname"."title" AS "postaliasname.title" FROM "User" "User" ` + - `INNER JOIN "Post" "postaliasname" ON "User"."id" = "postaliasname"."user_id" ` + - `WHERE (SELECT "user_id" FROM "Post" "postaliasname" WHERE "postaliasname"."user_id" = "User"."id" ORDER BY "postaliasname"."id" OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY) IS NOT NULL) "User";`, }, ); }); @@ -1035,11 +925,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { '(SELECT [User].[name], [User].[age], [User].[id], [postaliasname].[id] AS [postaliasname.id], [postaliasname].[title] AS [postaliasname.title] FROM [User] AS [User] ' + 'INNER JOIN [Post] AS [postaliasname] ON [User].[id] = [postaliasname].[user_id] ' + `WHERE [postaliasname].[title] = ${sql.escape('test')} AND ( SELECT [user_id] FROM [Post] AS [postaliasname] WHERE [postaliasname].[user_id] = [User].[id] ORDER BY [postaliasname].[id] OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY) IS NOT NULL) AS [User];`, - oracle: - `SELECT "User".* FROM ` + - `(SELECT "User"."name", "User"."age", "User"."id", "postaliasname"."id" AS "postaliasname.id", "postaliasname"."title" AS "postaliasname.title" FROM "User" "User" ` + - `INNER JOIN "Post" "postaliasname" ON "User"."id" = "postaliasname"."user_id" ` + - `WHERE "postaliasname"."title" = 'test' AND (SELECT "user_id" FROM "Post" "postaliasname" WHERE "postaliasname"."user_id" = "User"."id" ORDER BY "postaliasname"."id" OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY) IS NOT NULL) "User";`, }, ); }); @@ -1129,16 +1014,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'INNER JOIN [Professions] AS [profession] ON [Users].[professionId] = [profession].[id] ' + `WHERE [Users].[companyId] = [Company].[id] ORDER BY [Users].[id] OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY` + `) IS NOT NULL ORDER BY [Company].[id] OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY) AS [Company];`, - oracle: - `SELECT "Company".* FROM (` + - `SELECT "Company"."name", "Company"."public", "Company"."id" FROM "Company" "Company" ` + - `INNER JOIN "Users" "Users" ON "Company"."id" = "Users"."companyId" ` + - `INNER JOIN "Professions" "Users->profession" ON "Users"."professionId" = "Users->profession"."id" ` + - `WHERE ("Company"."scopeId" IN (42) AND "Users->profession"."name" = 'test') AND (` + - `SELECT "Users"."companyId" FROM "Users" "Users" ` + - `INNER JOIN "Professions" "profession" ON "Users"."professionId" = "profession"."id" ` + - `WHERE "Users"."companyId" = "Company"."id" ORDER BY "Users"."id" OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY` + - `) IS NOT NULL ORDER BY "Company"."id" OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY) "Company";`, }, ); }); @@ -1176,7 +1051,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { "SELECT `name`, `age`, `data` FROM `User` AS `User` WHERE `User`.`data` IN (X'313233');", mssql: 'SELECT [name], [age], [data] FROM [User] AS [User] WHERE [User].[data] IN (0x313233);', - oracle: `SELECT "name", "age", "data" FROM "User" "User" WHERE "User"."data" IN ('313233');`, }, ); }); @@ -1331,7 +1205,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { // expectsql fails with consecutive TICKS so we add the dialect-specific one ourself default: `SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} AS ${TICK_LEFT}Posts.* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} FROM ${TICK_LEFT}User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];`, ibmi: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM ""User""; DELETE FROM ""User"";SELECT ""id""" AS "Posts.* FROM ""User""; DELETE FROM ""User"";SELECT ""id""" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "Posts" ON "User"."id" = "Posts"."user_id"', - oracle: `SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} AS ${TICK_LEFT}Posts.* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} FROM ${TICK_LEFT}User" "User" LEFT OUTER JOIN "Post" "Posts" ON "User"."id" = "Posts"."user_id";`, }, ); @@ -1366,7 +1239,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { // expectsql fails with consecutive TICKS so we add the dialect-specific one ourself default: `SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} AS ${TICK_LEFT}Posts.data] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];`, ibmi: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM ""User""; DELETE FROM ""User"";SELECT ""id""" AS "Posts.data" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "Posts" ON "User"."id" = "Posts"."user_id"', - oracle: `SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} AS ${TICK_LEFT}Posts.data" FROM "User" "User" LEFT OUTER JOIN "Post" "Posts" ON "User"."id" = "Posts"."user_id";`, }, ); @@ -1390,7 +1262,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ), { ibmi: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM User; DELETE FROM User;SELECT id" AS "Posts.data" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "Posts" ON "User"."id" = "Posts"."user_id"', - oracle: `SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM User; DELETE FROM User;SELECT id" AS "Posts.data" FROM "User" "User" LEFT OUTER JOIN "Post" "Posts" ON "User"."id" = "Posts"."user_id";`, default: 'SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[* FROM User; DELETE FROM User;SELECT id] AS [Posts.data] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];', }, @@ -1425,7 +1296,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { { default: 'SELECT [name], [age] FROM [User];', ibmi: 'SELECT "name", "age" FROM "User"', - 'postgres oracle': 'SELECT name, age FROM "User";', + postgres: 'SELECT name, age FROM "User";', snowflake: 'SELECT name, age FROM User;', }, ); @@ -1481,7 +1352,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title" FROM "User" AS "User" LEFT OUTER JOIN Post AS Posts ON "User".id = Posts.user_id;', snowflake: 'SELECT User.name, User.age, Posts.id AS "Posts.id", Posts.title AS "Posts.title" FROM User AS User LEFT OUTER JOIN Post AS Posts ON User.id = Posts.user_id;', - oracle: `SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title" FROM "User" "User" LEFT OUTER JOIN Post Posts ON "User".id = Posts.user_id;`, }, ); }); @@ -1551,7 +1421,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title", "Posts->Comments".id AS "Posts.Comments.id", "Posts->Comments".title AS "Posts.Comments.title", "Posts->Comments".createdAt AS "Posts.Comments.createdAt", "Posts->Comments".updatedAt AS "Posts.Comments.updatedAt", "Posts->Comments".post_id AS "Posts.Comments.post_id" FROM "User" AS "User" LEFT OUTER JOIN Post AS Posts ON "User".id = Posts.user_id LEFT OUTER JOIN Comment AS "Posts->Comments" ON Posts.id = "Posts->Comments".post_id;', snowflake: 'SELECT User.name, User.age, Posts.id AS "Posts.id", Posts.title AS "Posts.title", "Posts->Comments".id AS "Posts.Comments.id", "Posts->Comments".title AS "Posts.Comments.title", "Posts->Comments".createdAt AS "Posts.Comments.createdAt", "Posts->Comments".updatedAt AS "Posts.Comments.updatedAt", "Posts->Comments".post_id AS "Posts.Comments.post_id" FROM User AS User LEFT OUTER JOIN Post AS Posts ON User.id = Posts.user_id LEFT OUTER JOIN Comment AS "Posts->Comments" ON Posts.id = "Posts->Comments".post_id;', - oracle: `SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title", "Posts->Comments".id AS "Posts.Comments.id", "Posts->Comments".title AS "Posts.Comments.title", "Posts->Comments".createdAt AS "Posts.Comments.createdAt", "Posts->Comments".updatedAt AS "Posts.Comments.updatedAt", "Posts->Comments".post_id AS "Posts.Comments.post_id" FROM "User" "User" LEFT OUTER JOIN Post Posts ON "User".id = Posts.user_id LEFT OUTER JOIN "Comment" "Posts->Comments" ON Posts.id = "Posts->Comments".post_id;`, }, ); }); @@ -1614,7 +1483,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'SELECT "User".name, "User".age, "User"."status.label" AS statuslabel, Posts.id AS "Posts.id", Posts.title AS "Posts.title", Posts."status.label" AS "Posts.statuslabel" FROM "User" AS "User" LEFT OUTER JOIN Post AS Posts ON "User".id = Posts.user_id;', snowflake: 'SELECT User.name, User.age, User."status.label" AS statuslabel, Posts.id AS "Posts.id", Posts.title AS "Posts.title", Posts."status.label" AS "Posts.statuslabel" FROM User AS User LEFT OUTER JOIN Post AS Posts ON User.id = Posts.user_id;', - oracle: `SELECT "User".name, "User".age, "User"."status.label" AS statuslabel, Posts.id AS "Posts.id", Posts.title AS "Posts.title", Posts."status.label" AS "Posts.statuslabel" FROM "User" "User" LEFT OUTER JOIN Post Posts ON "User".id = Posts.user_id;`, }, ); }); diff --git a/packages/core/test/unit/sql/update.test.js b/packages/core/test/unit/sql/update.test.js index ec07c3b7ecef..ed9d907be782 100644 --- a/packages/core/test/unit/sql/update.test.js +++ b/packages/core/test/unit/sql/update.test.js @@ -40,7 +40,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { query: { db2: 'SELECT * FROM FINAL TABLE (UPDATE "users" SET "user_name"=$sequelize_1 WHERE "id" = $sequelize_2);', ibmi: 'UPDATE "users" SET "user_name"=$sequelize_1 WHERE "id" = $sequelize_2', - oracle: `UPDATE "users" SET "user_name"=:1 WHERE "id" = :2`, default: 'UPDATE [users] SET [user_name]=$sequelize_1 WHERE [id] = $sequelize_2', }, bind: { @@ -86,7 +85,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { 'UPDATE "users" SET "user_name"=$sequelize_1 WHERE "id" = $sequelize_2 RETURNING "id", "user_name"', db2: 'SELECT * FROM FINAL TABLE (UPDATE "users" SET "user_name"=$sequelize_1 WHERE "id" = $sequelize_2);', snowflake: 'UPDATE "users" SET "user_name"=$sequelize_1 WHERE "id" = $sequelize_2', - oracle: `UPDATE "users" SET "user_name"=:1 WHERE "id" = :2`, default: 'UPDATE `users` SET `user_name`=$sequelize_1 WHERE `id` = $sequelize_2', }, bind: { @@ -133,7 +131,6 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'SELECT * FROM FINAL TABLE (UPDATE (SELECT * FROM "Users" WHERE "username" = $sequelize_2 FETCH NEXT 1 ROWS ONLY) SET "username"=$sequelize_1);', snowflake: 'UPDATE "Users" SET "username"=$sequelize_1 WHERE "username" = $sequelize_2 LIMIT 1', - oracle: `UPDATE "Users" SET "username"=:1 WHERE "username" = :2 AND rownum <= 1`, default: 'UPDATE [Users] SET [username]=$sequelize_1 WHERE [username] = $sequelize_2', }, bind: { diff --git a/packages/core/test/unit/sql/where.test.ts b/packages/core/test/unit/sql/where.test.ts index 5d1d7af20f39..30e086e2ec23 100644 --- a/packages/core/test/unit/sql/where.test.ts +++ b/packages/core/test/unit/sql/where.test.ts @@ -412,7 +412,6 @@ Caused by: "undefined" cannot be escaped`), db2: '"stringAttr" = \'here is a null char: \0\'', ibmi: '"stringAttr" = \'here is a null char: \0\'', sqlite3: "`stringAttr` = 'here is a null char: \0'", - oracle: `"stringAttr" = 'here is a null char: \0'`, }, ); @@ -425,7 +424,6 @@ Caused by: "undefined" cannot be escaped`), 'mariadb mysql': `\`dateAttr\` = '2013-01-01 00:00:00.000'`, mssql: `[dateAttr] = N'2013-01-01 00:00:00.000 +00:00'`, 'db2 snowflake ibmi': `"dateAttr" = '2013-01-01 00:00:00.000'`, - oracle: `"dateAttr" = TO_TIMESTAMP_TZ('2013-01-01 00:00:00.000 +00:00', 'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM')`, }, ); @@ -439,7 +437,6 @@ Caused by: "undefined" cannot be escaped`), db2: `"binaryAttr" = BLOB('Sequelize')`, snowflake: `"binaryAttr" = X'53657175656c697a65'`, mssql: '[binaryAttr] = 0x53657175656c697a65', - oracle: `"binaryAttr" = '53657175656c697a65'`, }, ); @@ -454,7 +451,6 @@ Caused by: "undefined" cannot be escaped`), db2: `"binaryAttr" IN (BLOB('Seque''lize1'), BLOB('Sequelize2'))`, snowflake: `"binaryAttr" IN (X'5365717565276c697a6531', X'53657175656c697a6532')`, mssql: '[binaryAttr] IN (0x5365717565276c697a6531, 0x53657175656c697a6532)', - oracle: `"binaryAttr" IN ('5365717565276c697a6531', '53657175656c697a6532')`, }, ); }); @@ -538,7 +534,6 @@ Caused by: "undefined" cannot be escaped`), mssql: '[booleanAttr] = 1', sqlite3: '`booleanAttr` = 1', ibmi: '"booleanAttr" = 1', - oracle: `"booleanAttr" = 1`, }, ); @@ -576,7 +571,6 @@ Caused by: "undefined" cannot be escaped`), mssql: `[dateAttr] = N'2021-01-01 00:00:00.000 +00:00'`, 'mariadb mysql': `\`dateAttr\` = '2021-01-01 00:00:00.000'`, 'db2 ibmi snowflake': `"dateAttr" = '2021-01-01 00:00:00.000'`, - oracle: `"dateAttr" = TO_TIMESTAMP_TZ('2021-01-01 00:00:00.000 +00:00', 'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM')`, }, ); @@ -796,7 +790,6 @@ Caused by: "undefined" cannot be escaped`), { default: '[booleanAttr] = true', 'mssql sqlite3 ibmi': '[booleanAttr] = 1', - oracle: `"booleanAttr" = 1`, }, ); @@ -833,7 +826,6 @@ Caused by: "undefined" cannot be escaped`), { default: '[booleanAttr] != true', 'mssql ibmi sqlite3': '[booleanAttr] != 1', - oracle: `"booleanAttr" != 1`, }, ); @@ -871,7 +863,6 @@ Caused by: "undefined" cannot be escaped`), { default: '[booleanAttr] IS false', 'mssql ibmi sqlite3': '[booleanAttr] IS 0', - oracle: `"booleanAttr" IS 0`, }, ); @@ -880,7 +871,6 @@ Caused by: "undefined" cannot be escaped`), { default: '[booleanAttr] IS true', 'mssql ibmi sqlite3': '[booleanAttr] IS 1', - oracle: `"booleanAttr" IS 1`, }, ); @@ -977,7 +967,6 @@ Caused by: "undefined" cannot be escaped`), { default: '[booleanAttr] IS NOT false', 'mssql ibmi sqlite3': '[booleanAttr] IS NOT 0', - oracle: `"booleanAttr" IS NOT 0`, }, ); @@ -986,7 +975,6 @@ Caused by: "undefined" cannot be escaped`), { default: '[booleanAttr] IS NOT true', 'mssql ibmi sqlite3': '[booleanAttr] IS NOT 1', - oracle: `"booleanAttr" IS NOT 1`, }, ); }); @@ -1038,7 +1026,6 @@ Caused by: "undefined" cannot be escaped`), mssql: 'NOT ([booleanAttr] = 0)', ibmi: 'NOT ("booleanAttr" = 0)', sqlite3: 'NOT (`booleanAttr` = 0)', - oracle: `NOT ("booleanAttr" = 0)`, }, ); @@ -1049,7 +1036,6 @@ Caused by: "undefined" cannot be escaped`), mssql: 'NOT ([booleanAttr] = 1)', ibmi: 'NOT ("booleanAttr" = 1)', sqlite3: 'NOT (`booleanAttr` = 1)', - oracle: 'NOT ("booleanAttr" = 1)', }, ); @@ -1102,7 +1088,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `NOT (json_extract(\`data\`,'$.key') = '10')`, mariadb: `NOT (json_compact(json_extract(\`data\`,'$.key')) = '10')`, mysql: `NOT (json_extract(\`data\`,'$.key') = CAST('10' AS JSON))`, - oracle: `NOT (json_value("data",'$."key"') = '10')`, }, ); } @@ -2904,7 +2889,6 @@ Caused by: "undefined" cannot be escaped`), default: `[jsonAttr] = '"value"'`, mysql: `\`jsonAttr\` = CAST('"value"' AS JSON)`, mssql: `[jsonAttr] = N'"value"'`, - oracle: `"jsonAttr" = 'value'`, }, ); @@ -2955,7 +2939,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') = '"value"'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) = '"value"'`, mysql: `json_extract(\`jsonAttr\`,'$.nested') = CAST('"value"' AS JSON)`, - oracle: `json_value("jsonAttr",'$."nested"') = 'value'`, }, ); @@ -2973,7 +2956,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') = 'null'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) = 'null'`, mysql: `json_extract(\`jsonAttr\`,'$.nested') = CAST('null' AS JSON)`, - oracle: `json_value("jsonAttr",'$."nested"') = 'null'`, }, ); @@ -2984,7 +2966,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') IS NULL`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) IS NULL`, mysql: `json_extract(\`jsonAttr\`,'$.nested') IS NULL`, - oracle: `json_value("jsonAttr",'$."nested"') IS NULL`, }, ); @@ -2995,7 +2976,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') = 'null'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) = 'null'`, mysql: `json_extract(\`jsonAttr\`,'$.nested') = CAST('null' AS JSON)`, - oracle: `json_value("jsonAttr",'$."nested"') = 'null'`, }, ); @@ -3006,7 +2986,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') IS NULL`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) IS NULL`, mysql: `json_extract(\`jsonAttr\`,'$.nested') IS NULL`, - oracle: `json_value("jsonAttr",'$."nested"') IS NULL`, }, ); @@ -3015,7 +2994,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `'"value"' = json_extract(\`jsonAttr\`,'$.nested')`, mariadb: `'"value"' = json_compact(json_extract(\`jsonAttr\`,'$.nested'))`, mysql: `CAST('"value"' AS JSON) = json_extract(\`jsonAttr\`,'$.nested')`, - oracle: `'value' = json_value("jsonAttr",'$."nested"')`, }); testSql( @@ -3025,7 +3003,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested.twice') = '"value"'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested.twice')) = '"value"'`, mysql: `json_extract(\`jsonAttr\`,'$.nested.twice') = CAST('"value"' AS JSON)`, - oracle: `json_value("jsonAttr",'$."nested"."twice"') = 'value'`, }, ); @@ -3038,7 +3015,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') = '"value"'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) = '"value"'`, mysql: `json_extract(\`jsonAttr\`,'$.nested') = CAST('"value"' AS JSON)`, - oracle: `json_value("jsonAttr",'$."nested"') = 'value'`, }, ); @@ -3051,7 +3027,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested.twice') = '"value"'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested.twice')) = '"value"'`, mysql: `json_extract(\`jsonAttr\`,'$.nested.twice') = CAST('"value"' AS JSON)`, - oracle: `json_value("jsonAttr",'$."nested"."twice"') = 'value'`, }, ); @@ -3074,7 +3049,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') != '"value"'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) != '"value"'`, mysql: `json_extract(\`jsonAttr\`,'$.nested') != CAST('"value"' AS JSON)`, - oracle: `json_value("jsonAttr",'$."nested"') != 'value'`, }, ); @@ -3087,7 +3061,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested') = '"value"'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested')) = '"value"'`, mysql: `json_extract(\`jsonAttr\`,'$.nested') = CAST('"value"' AS JSON)`, - oracle: `json_value("jsonAttr",'$."nested"') = 'value'`, }, ); @@ -3100,7 +3073,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`association\`.\`jsonAttr\`,'$.nested') = '"value"'`, mariadb: `json_compact(json_extract(\`association\`.\`jsonAttr\`,'$.nested')) = '"value"'`, mysql: `json_extract(\`association\`.\`jsonAttr\`,'$.nested') = CAST('"value"' AS JSON)`, - oracle: `json_value("association"."jsonAttr",'$."nested"') = 'value'`, }, ); @@ -3113,7 +3085,6 @@ Caused by: "undefined" cannot be escaped`), postgres: `CAST("jsonAttr"->'nested' AS STRING) = 'value'`, mariadb: `CAST(json_compact(json_extract(\`jsonAttr\`,'$.nested')) AS STRING) = 'value'`, 'sqlite3 mysql': `CAST(json_extract(\`jsonAttr\`,'$.nested') AS STRING) = 'value'`, - oracle: `CAST(json_value("jsonAttr",'$."nested"') AS STRING) = 'value'`, }, ); @@ -3136,7 +3107,6 @@ Caused by: "undefined" cannot be escaped`), postgres: `CAST("association"."jsonAttr"#>ARRAY['nested','deep']::VARCHAR(255)[] AS STRING) = 'value'`, mariadb: `CAST(json_compact(json_extract(\`association\`.\`jsonAttr\`,'$.nested.deep')) AS STRING) = 'value'`, 'sqlite3 mysql': `CAST(json_extract(\`association\`.\`jsonAttr\`,'$.nested.deep') AS STRING) = 'value'`, - oracle: `CAST(json_value("association"."jsonAttr",'$."nested"."deep"') AS STRING) = 'value'`, }, ); @@ -3148,7 +3118,6 @@ Caused by: "undefined" cannot be escaped`), postgres: `CAST("jsonAttr"->'nested' AS STRING) = 'value'`, mariadb: `CAST(json_compact(json_extract(\`jsonAttr\`,'$.nested')) AS STRING) = 'value'`, 'sqlite3 mysql': `CAST(json_extract(\`jsonAttr\`,'$.nested') AS STRING) = 'value'`, - oracle: `CAST(json_value("jsonAttr",'$."nested"') AS STRING) = 'value'`, }, ); @@ -3159,7 +3128,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$.nested.attribute') = '4'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$.nested.attribute')) = '4'`, mysql: `json_extract(\`jsonAttr\`,'$.nested.attribute') = CAST('4' AS JSON)`, - oracle: `json_value("jsonAttr",'$."nested"."attribute"') = '4'`, }, ); @@ -3171,7 +3139,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$."0"') = '4'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$."0"')) = '4'`, mysql: `json_extract(\`jsonAttr\`,'$."0"') = CAST('4' AS JSON)`, - oracle: `json_value("jsonAttr",'$[0]') = '4'`, }, ); @@ -3185,7 +3152,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$[0]') = '4'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$[0]')) = '4'`, mysql: `json_extract(\`jsonAttr\`,'$[0]') = CAST('4' AS JSON)`, - oracle: `json_value("jsonAttr",'$[0]') = '4'`, }, ); @@ -3196,7 +3162,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$."0".attribute') = '4'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$."0".attribute')) = '4'`, mysql: `json_extract(\`jsonAttr\`,'$."0".attribute') = CAST('4' AS JSON)`, - oracle: `json_value("jsonAttr",'$[0]."attribute"') = '4'`, }, ); @@ -3208,7 +3173,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$."hyphenated-key"') = '4'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$."hyphenated-key"')) = '4'`, mysql: `json_extract(\`jsonAttr\`,'$."hyphenated-key"') = CAST('4' AS JSON)`, - oracle: `json_value("jsonAttr",'$."hyphenated-key"') = '4'`, }, ); @@ -3220,7 +3184,6 @@ Caused by: "undefined" cannot be escaped`), mysql: `json_extract(\`jsonAttr\`,'$."a\\')) AS DECIMAL) = 1 DELETE YOLO INJECTIONS; -- "') = CAST('1' AS JSON)`, sqlite3: `json_extract(\`jsonAttr\`,'$."a'')) AS DECIMAL) = 1 DELETE YOLO INJECTIONS; -- "') = '1'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$."a\\')) AS DECIMAL) = 1 DELETE YOLO INJECTIONS; -- "')) = '1'`, - oracle: `json_value("jsonAttr",'$."a'')) AS DECIMAL) = 1 DELETE YOLO INJECTIONS; -- "') = '1'`, }, ); @@ -3233,7 +3196,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`jsonAttr\`,'$[0].nested.attribute') = '4'`, mariadb: `json_compact(json_extract(\`jsonAttr\`,'$[0].nested.attribute')) = '4'`, mysql: `json_extract(\`jsonAttr\`,'$[0].nested.attribute') = CAST('4' AS JSON)`, - oracle: `json_value("jsonAttr",'$[0]."nested"."attribute"') = '4'`, }, ); @@ -3245,7 +3207,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`aliased_json\`,'$.nested.attribute') = '4'`, mariadb: `json_compact(json_extract(\`aliased_json\`,'$.nested.attribute')) = '4'`, mysql: `json_extract(\`aliased_json\`,'$.nested.attribute') = CAST('4' AS JSON)`, - oracle: `json_value("aliased_json",'$."nested"."attribute"') = '4'`, }, ); } @@ -4041,7 +4002,6 @@ Caused by: "undefined" cannot be escaped`), sqlite3: `json_extract(\`col\`,'$.jsonPath') = '"value"'`, mariadb: `json_compact(json_extract(\`col\`,'$.jsonPath')) = '"value"'`, mysql: `json_extract(\`col\`,'$.jsonPath') = CAST('"value"' AS JSON)`, - oracle: `json_value("col",'$."jsonPath"') = 'value'`, }); } }); diff --git a/packages/core/test/unit/transaction.test.ts b/packages/core/test/unit/transaction.test.ts index f42c6b8e19d9..f181001af030 100644 --- a/packages/core/test/unit/transaction.test.ts +++ b/packages/core/test/unit/transaction.test.ts @@ -51,7 +51,6 @@ describe('Transaction', () => { all: ['START TRANSACTION'], snowflake: ['START TRANSACTION NAME "123"'], sqlite3: ['BEGIN DEFERRED TRANSACTION'], - oracle: ['BEGIN TRANSACTION'], }; await sequelize.transaction(async () => { @@ -66,7 +65,6 @@ describe('Transaction', () => { all: ['SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED', 'START TRANSACTION'], postgres: ['START TRANSACTION', 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED'], sqlite3: ['BEGIN DEFERRED TRANSACTION', 'PRAGMA read_uncommitted = 1'], - oracle: ['BEGIN TRANSACTION', 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED'], }; try { diff --git a/packages/core/test/unit/utils/sql.test.ts b/packages/core/test/unit/utils/sql.test.ts index 1fc076a7a4f1..bfb1bd45915a 100644 --- a/packages/core/test/unit/utils/sql.test.ts +++ b/packages/core/test/unit/utils/sql.test.ts @@ -32,13 +32,10 @@ describe('mapBindParameters', () => { postgres: `SELECT "$id" FROM users WHERE id = '$id' OR id = $1 OR id = '''$id'''`, sqlite3: `SELECT \`$id\` FROM users WHERE id = '$id' OR id = $id OR id = '''$id'''`, mssql: `SELECT [$id] FROM users WHERE id = '$id' OR id = @id OR id = '''$id'''`, - oracle: `SELECT "$id" FROM users WHERE id = '$id' OR id = :id OR id = '''$id'''`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; - } else if (dialect.name === 'oracle') { - expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['id']); } @@ -55,13 +52,10 @@ describe('mapBindParameters', () => { postgres: `SELECT * FROM users WHERE id = $1`, sqlite3: `SELECT * FROM users WHERE id = $1`, mssql: `SELECT * FROM users WHERE id = @1`, - oracle: `SELECT * FROM users WHERE id = :1`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; - } else if (dialect.name === 'oracle') { - expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['1']); } @@ -77,7 +71,6 @@ describe('mapBindParameters', () => { postgres: `SELECT * FROM users WHERE id = $1::string`, sqlite3: `SELECT * FROM users WHERE id = $param::string`, mssql: `SELECT * FROM users WHERE id = @param::string`, - oracle: `SELECT * FROM users WHERE id = :param::string`, }); }); @@ -89,7 +82,6 @@ describe('mapBindParameters', () => { postgres: `SELECT * FROM users WHERE json_col->>$1`, sqlite3: `SELECT * FROM users WHERE json_col->>$key`, mssql: `SELECT * FROM users WHERE json_col->>@key`, - oracle: `SELECT * FROM users WHERE json_col->>:key`, }); }); @@ -102,7 +94,6 @@ describe('mapBindParameters', () => { sqlite3: `SELECT * FROM users WHERE id = $id;`, mssql: `SELECT * FROM users WHERE id = @id;`, ibmi: `SELECT * FROM users WHERE id = ?;`, // 'default' removes the ; for ibmi - oracle: `SELECT * FROM users WHERE id = :id;`, }); }); @@ -130,13 +121,10 @@ describe('mapBindParameters', () => { postgres: `SELECT * FROM users WHERE id = $1`, sqlite3: `SELECT * FROM users WHERE id = $a`, mssql: `SELECT * FROM users WHERE id = @a`, - oracle: `SELECT * FROM users WHERE id = :a`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; - } else if (dialect.name === 'oracle') { - expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['a']); } @@ -155,15 +143,12 @@ describe('mapBindParameters', () => { postgres: `SELECT * FROM users WHERE id = fn($1) OR id = fn('a',$1) OR id=$1 OR id$id = 1 OR id = $1`, sqlite3: `SELECT * FROM users WHERE id = fn($id) OR id = fn('a',$id) OR id=$id OR id$id = 1 OR id = $id`, mssql: `SELECT * FROM users WHERE id = fn(@id) OR id = fn('a',@id) OR id=@id OR id$id = 1 OR id = @id`, - oracle: `SELECT * FROM users WHERE id = fn(:id) OR id = fn('a',:id) OR id=:id OR id$id = 1 OR id = :id`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; } else if (dialect.name === 'postgres') { expect(bindOrder).to.deep.eq(['id']); - } else if (dialect.name === 'oracle') { - expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['id', 'id', 'id', 'id']); } @@ -181,8 +166,6 @@ describe('mapBindParameters', () => { if (supportsNamedParameters) { expect(bindOrder).to.be.null; - } else if (dialect.name === 'oracle') { - expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq([]); } @@ -200,8 +183,6 @@ describe('mapBindParameters', () => { if (supportsNamedParameters) { expect(bindOrder).to.be.null; - } else if (dialect.name === 'oracle') { - expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq([]); } @@ -215,13 +196,10 @@ describe('mapBindParameters', () => { postgres: `SELECT z$$ $1 x$$ * FROM users`, sqlite3: `SELECT z$$ $id x$$ * FROM users`, mssql: `SELECT z$$ @id x$$ * FROM users`, - oracle: `SELECT z$$ :id x$$ * FROM users`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; - } else if (dialect.name === 'oracle') { - expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['id']); } @@ -238,13 +216,10 @@ describe('mapBindParameters', () => { postgres: `SELECT $$ abc $$ AS string FROM users WHERE id = $1`, sqlite3: `SELECT $$ abc $$ AS string FROM users WHERE id = $id`, mssql: `SELECT $$ abc $$ AS string FROM users WHERE id = @id`, - oracle: `SELECT $$ abc $$ AS string FROM users WHERE id = :id`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; - } else if (dialect.name === 'oracle') { - expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['id']); } @@ -341,13 +316,10 @@ SELECT * FROM users WHERE id = e'\\' $id' OR id = $id`), postgres: `SELECT * FROM users WHERE id = '\\\\' OR id = $1`, sqlite3: `SELECT * FROM users WHERE id = '\\\\' OR id = $id`, mssql: `SELECT * FROM users WHERE id = '\\\\' OR id = @id`, - oracle: `SELECT * FROM users WHERE id = '\\\\' OR id = :id`, }); if (supportsNamedParameters) { expect(bindOrder).to.be.null; - } else if (dialect.name === 'oracle') { - expect(bindOrder).to.be.null; } else { expect(bindOrder).to.deep.eq(['id']); } @@ -394,10 +366,6 @@ SELECT * FROM users WHERE id = '\\\\\\' $id' OR id = $id`), SELECT * FROM users -- WHERE id = $id WHERE id = @id `, - oracle: ` - SELECT * FROM users -- WHERE id = $id - WHERE id = :id - `, }); }); @@ -454,12 +422,6 @@ SELECT * FROM users WHERE id = '\\\\\\' $id' OR id = $id`), */ WHERE id = @id `, - oracle: ` - SELECT * FROM users /* - WHERE id = $id - */ - WHERE id = :id - `, }); }); }); diff --git a/packages/oracle/.eslintrc.js b/packages/oracle/.eslintrc.js deleted file mode 100644 index e13dec291282..000000000000 --- a/packages/oracle/.eslintrc.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - parserOptions: { - project: [`${__dirname}/tsconfig.json`], - }, -}; diff --git a/packages/oracle/package.json b/packages/oracle/package.json deleted file mode 100644 index f25bf32094eb..000000000000 --- a/packages/oracle/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "bugs": "https://github.com/sequelize/sequelize/issues", - "description": "Oracle Database Connector for Sequelize", - "exports": { - ".": { - "import": { - "types": "./lib/index.d.mts", - "default": "./lib/index.mjs" - }, - "require": { - "types": "./lib/index.d.ts", - "default": "./lib/index.js" - } - } - }, - "main": "./lib/index.js", - "types": "./lib/index.d.ts", - "sideEffects": false, - "homepage": "https://sequelize.org", - "license": "MIT", - "name": "@sequelize/oracle", - "repository": "https://github.com/sequelize/sequelize", - "scripts": { - "build": "../../build-packages.mjs oracle", - "test": "concurrently \"npm:test-*\"", - "test-typings": "tsc --noEmit --project tsconfig.json", - "test-unit": "mocha src/**/*.test.ts", - "test-exports": "../../dev/sync-exports.mjs ./src --check-outdated", - "sync-exports": "../../dev/sync-exports.mjs ./src" - }, - "type": "commonjs", - "version": "7.0.0-alpha.40", - "publishConfig": { - "access": "public" - }, - "dependencies": { - "@sequelize/core": "workspace:*", - "@sequelize/utils": "workspace:*", - "@types/oracledb": "^6.3", - "dayjs": "^1.11.10", - "lodash": "4.17.21", - "oracledb": "6.5", - "semver": "7.6.0" - }, - "devDependencies": { - "@types/chai": "4.3.14", - "@types/mocha": "10.0.6", - "@types/sinon": "17.0.3", - "chai": "4.4.1", - "mocha": "10.4.0", - "sinon": "18.0.0" - } -} diff --git a/packages/oracle/src/_internal/data-types-overrides.ts b/packages/oracle/src/_internal/data-types-overrides.ts deleted file mode 100644 index e65112a2490e..000000000000 --- a/packages/oracle/src/_internal/data-types-overrides.ts +++ /dev/null @@ -1,427 +0,0 @@ -// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -import type { AbstractDialect, BindParamOptions } from '@sequelize/core'; -import type { AcceptedDate } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/data-types.js'; -import * as BaseTypes from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/data-types.js'; -import dayjs from 'dayjs'; -import utc from 'dayjs/plugin/utc'; - -// eslint-disable-next-line @typescript-eslint/consistent-type-imports -type Lib = typeof import('oracledb'); - -dayjs.extend(utc); - -// legacy support -let Moment: any; -try { - // eslint-disable-next-line import/no-extraneous-dependencies - Moment = require('moment'); -} catch { - /* ignore */ -} - -function isMoment(value: any): boolean { - return Moment?.isMoment(value) ?? false; -} - -export class STRING extends BaseTypes.STRING { - protected _checkOptionSupport(dialect: AbstractDialect) { - super._checkOptionSupport(dialect); - // @ts-expect-error -- Object is possibly 'null'. - if (this.options.length > 4000 || (this.options.binary && this.options.length > 2000)) { - dialect.warnDataTypeIssue( - `Oracle supports length up to 32764 bytes or characters; Be sure that your administrator has extended the MAX_STRING_SIZE parameter. Check https://docs.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-7B72E154-677A-4342-A1EA-C74C1EA928E6`, - ); - } - } - - toSql() { - if (!this.options.binary) { - return `NVARCHAR2(${this.options.length ?? 255})`; - } - - return `RAW(${this.options.length ?? 255})`; - } - - _getBindDef(oracledb: Lib) { - if (this.options.binary) { - return { type: oracledb.DB_TYPE_RAW, maxSize: this.options.length || 255 }; - } - - return { type: oracledb.DB_TYPE_VARCHAR, maxSize: this.options.length || 255 }; - } -} - -export class BOOLEAN extends BaseTypes.BOOLEAN { - toSql() { - return 'CHAR(1)'; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_CHAR, maxSize: 1 }; - } - - escape(value: boolean): string { - return value ? '1' : '0'; - } - - toBindableValue(value: boolean): unknown { - return value === true ? '1' : value === false ? '0' : value; - } - - parseDatabaseValue(value: unknown): boolean { - if (value === '1' || value === 'true') { - return true; - } - - return false; - } -} - -export class UUID extends BaseTypes.UUID { - toSql() { - return 'VARCHAR2(36)'; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_VARCHAR, maxSize: 36 }; - } -} - -export class NOW extends BaseTypes.NOW { - toSql(): string { - return 'SYSDATE'; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - toBindableValue(value: never): unknown { - return 'SYSDATE'; - } -} - -export class ENUM extends BaseTypes.ENUM { - toSql() { - return 'VARCHAR2(512)'; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_VARCHAR, maxSize: 512 }; - } -} - -export class TEXT extends BaseTypes.TEXT { - toSql() { - return 'CLOB'; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_CLOB }; - } -} - -export class CHAR extends BaseTypes.CHAR { - protected _checkOptionSupport(dialect: AbstractDialect) { - super._checkOptionSupport(dialect); - if (this.options.binary) { - dialect.warnDataTypeIssue('Oracle CHAR.BINARY datatype is not of Fixed Length.'); - } - } - - toSql() { - if (this.options.binary) { - return `RAW(${this.options.length ?? 255})`; - } - - return super.toSql(); - } - - _getBindDef(oracledb: Lib) { - if (this.options.binary) { - return { type: oracledb.DB_TYPE_RAW, maxSize: this.options.length }; - } - - return { type: oracledb.DB_TYPE_CHAR, maxSize: this.options.length }; - } -} - -export class DATE extends BaseTypes.DATE { - toSql() { - return 'TIMESTAMP WITH LOCAL TIME ZONE'; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_TIMESTAMP_LTZ }; - } - - toBindableValue(date: AcceptedDate) { - const format = 'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM'; - date = this._applyTimezone(date); - - const formatedDate = date.format('YYYY-MM-DD HH:mm:ss.SSS Z'); - - return `TO_TIMESTAMP_TZ('${formatedDate}', '${format}')`; - } - - /** - * avoids appending TO_TIMESTAMP_TZ in toBindableValue() - * - * @override - */ - getBindParamSql(value: AcceptedDate, options: BindParamOptions): string { - if (dayjs.isDayjs(value) || isMoment(value)) { - return options.bindParam(this._sanitize(value)); - } - - return options.bindParam(value); - } - - _sanitize(value: any) { - return new Date(value); - } -} - -type AcceptedNumber = number | bigint | boolean | string | null; - -export class DECIMAL extends BaseTypes.DECIMAL { - toSql() { - let result: string = 'NUMBER'; - if (!this.options.precision) { - return result; - } - - result += `(${this.options.precision}`; - - if (this.options.scale) { - result += `, ${this.options.scale}`; - } - - result += ')'; - - return result; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_NUMBER }; - } - - // Oracle treats DECIMAL as NUMBER(precision, scale). - sanitize(value: AcceptedNumber): AcceptedNumber { - if (typeof value === 'bigint') { - return value.toString(); - } - - return value; - } -} - -export class TINYINT extends BaseTypes.TINYINT { - toSql() { - return 'NUMBER(3)'; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_NUMBER }; - } -} - -export class SMALLINT extends BaseTypes.SMALLINT { - toSql() { - if (this.options.length) { - return `NUMBER(${this.options.length},0)`; - } - - return 'SMALLINT'; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_NUMBER }; - } -} - -export class MEDIUMINT extends BaseTypes.MEDIUMINT { - toSql() { - return 'NUMBER(8)'; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_NUMBER }; - } -} - -export class INTEGER extends BaseTypes.INTEGER { - toSql(): string { - if (this.options.length) { - return `NUMBER(${this.options.length},0)`; - } - - return 'INTEGER'; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_NUMBER }; - } -} - -/** - * @deprecated use FLOAT. - */ -export class REAL extends BaseTypes.REAL { - toSql() { - return 'BINARY_DOUBLE'; - } - - // https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-0BA2E065-8006-426C-A3CB-1F6B0C8F283C - toBindableValue(value: any) { - if (value === Number.POSITIVE_INFINITY) { - return 'inf'; - } - - if (value === Number.NEGATIVE_INFINITY) { - return '-inf'; - } - - return value; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_BINARY_DOUBLE }; - } -} - -export class BIGINT extends BaseTypes.BIGINT { - protected _checkOptionSupport(dialect: AbstractDialect) { - super._checkOptionSupport(dialect); - if (this.options.length || this.options.zerofill) { - dialect.warnDataTypeIssue(`${dialect.name} does not support BIGINT with options.`); - delete this.options.length; - this.options.zerofill = undefined; - } - } - - toSql(): string { - return 'NUMBER(19, 0)'; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_NUMBER }; - } - - sanitize(value: any) { - if (typeof value === 'bigint' || typeof value === 'number') { - return value.toString(); - } - - return value; - } -} - -export class FLOAT extends BaseTypes.FLOAT { - toSql() { - return 'BINARY_FLOAT'; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_BINARY_FLOAT }; - } -} - -export class BLOB extends BaseTypes.BLOB { - toSql(): string { - return 'BLOB'; - } - // check for hexify - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_BLOB }; - } -} - -export class JSON extends BaseTypes.JSON { - toSql(): string { - return 'BLOB'; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_BLOB }; - } - - toBindableValue(value: any): string { - if (value === null) { - const sequelize = this._getDialect().sequelize; - - const isExplicit = sequelize.options.nullJsonStringification === 'explicit'; - if (isExplicit) { - throw new Error( - `Attempted to insert the JavaScript null into a JSON column, but the "nullJsonStringification" option is set to "explicit", so Sequelize cannot decide whether to use the SQL NULL or the JSON 'null'. Use the SQL_NULL or JSON_NULL variable instead, or set the option to a different value. See https://sequelize.org/docs/v7/querying/json/ for details.`, - ); - } - } - - return typeof value === 'string' ? value : globalThis.JSON.stringify(value); - } - - getBindParamSql(value: any, options: BindParamOptions): any { - return options.bindParam(Buffer.from(globalThis.JSON.stringify(value))); - } -} - -export class DOUBLE extends BaseTypes.DOUBLE { - protected getNumberSqlTypeName(): string { - return 'DOUBLE PRECISION'; - } - - protected _checkOptionSupport(dialect: AbstractDialect): void { - super._checkOptionSupport(dialect); - - if (this.options.zerofill) { - dialect.warnDataTypeIssue( - `${dialect.name}: ${this.getDataTypeId} doesn't support zerofill option.`, - ); - } - } - - toSql(): string { - return 'BINARY_DOUBLE'; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_BINARY_DOUBLE }; - } -} - -export class DATEONLY extends BaseTypes.DATEONLY { - toBindableValue(date: AcceptedDate) { - if (date) { - const format = 'YYYY/MM/DD'; - - return this.escape(`TO_DATE('${date}','${format}')`); - } - - return this.escape(date); - } - - parseDatabaseValue(value: any) { - if (value) { - return dayjs.utc(value).format('YYYY-MM-DD'); - } - - return value; - } - - _getBindDef(oracledb: Lib) { - return { type: oracledb.DB_TYPE_DATE }; - } - - /** - * avoids appending TO_DATE in toBindableValue() - * - * @override - */ - getBindParamSql(value: AcceptedDate, options: BindParamOptions): string { - if (typeof value === 'string') { - return options.bindParam(new Date(value)); - } - - return options.bindParam(value); - } -} diff --git a/packages/oracle/src/connection-manager.ts b/packages/oracle/src/connection-manager.ts deleted file mode 100644 index 7a074ff25df3..000000000000 --- a/packages/oracle/src/connection-manager.ts +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -import type { AbstractConnection, ConnectionOptions } from '@sequelize/core'; -import { - AbstractConnectionManager, - AccessDeniedError, - ConnectionError, - ConnectionRefusedError, - ConnectionTimedOutError, - HostNotReachableError, - InvalidConnectionError, -} from '@sequelize/core'; -import { logger } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/logger.js'; -import type { Connection as oracledbConnection } from 'oracledb'; -import oracledb from 'oracledb'; -import type { OracleDialect } from './dialect.js'; - -export type oracledbModule = typeof oracledb; - -const debug = logger.debugContext('connection:oracle'); - -export interface OracleConnection extends oracledbConnection, AbstractConnection { - on(event: 'error', listener: (err: any) => void): this; -} - -export interface OracleConnectionOptions extends oracledb.ConnectionAttributes { - database?: string; - - host?: string; - - oracleOptions?: object; - - port?: number | string; -} - -export class OracleConnectionManager extends AbstractConnectionManager< - OracleDialect, - OracleConnection -> { - lib: typeof oracledb; - constructor(dialect: OracleDialect) { - super(dialect); - this.lib = oracledb; - } - - buildConnectString(config: ConnectionOptions) { - if (!config.host || config.host.length === 0) { - return config.database; - } - - let connectString = config.host; - if (config.port) { - connectString += `:${config.port}`; - } else { - connectString += ':1521'; - } - - if (config.database && config.database.length > 0) { - connectString += `/${config.database}`; - } - - return connectString; - } - - /** - * Method for initializing the lib - * - * @param config - */ - extendLib(config: ConnectionOptions) { - if (config.oracleOptions) { - if ('maxRows' in config.oracleOptions) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error add maxRow - oracledb.maxRows = config.oracleOptions.maxRows; - } - - if ('fetchAsString' in config.oracleOptions) { - // @ts-expect-error -- add fetchAsString - oracledb.fetchAsString = config.oracleOptions.fetchAsString; - } - } - - oracledb.fetchAsString = [oracledb.CLOB]; - - // Retrieve BLOB always as Buffer. - oracledb.fetchAsBuffer = [oracledb.BLOB]; - } - - async connect(config: ConnectionOptions): Promise { - this.extendLib(config); - this.lib = oracledb; - const connectionConfig: OracleConnectionOptions = { - username: config.username, - password: config.password, - connectString: this.buildConnectString(config), - ...config.oracleOptions, - }; - - try { - const connection: OracleConnection = (await this.lib.getConnection( - connectionConfig, - )) as OracleConnection; - - debug('connection acquired'); - connection.on('error', error => { - switch (error.code) { - case 'ESOCKET': - case 'ECONNRESET': - case 'EPIPE': - case 'PROTOCOL_CONNECTION_LOST': - void this.sequelize.pool.destroy(connection); - break; - default: - } - }); - - return connection; - } catch (error: any) { - let errorCode = error.message.split(':'); - errorCode = errorCode[0]; - - switch (errorCode) { - case 'ORA-12560': // ORA-12560: TNS: Protocol Adapter Error - case 'ORA-12154': // ORA-12154: TNS: Could not resolve the connect identifier specified - case 'ORA-12505': // ORA-12505: TNS: Listener does not currently know of SID given in connect descriptor - case 'ORA-12514': // ORA-12514: TNS: Listener does not currently know of service requested in connect descriptor - case 'NJS-511': // NJS-511: connection refused - case 'NJS-516': // NJS-516: No Config Dir - case 'NJS-517': // NJS-517: TNS Entry not found - case 'NJS-520': // NJS-520: TNS Names File missing - throw new ConnectionRefusedError(error); - case 'ORA-28000': // ORA-28000: Account locked - case 'ORA-28040': // ORA-28040: No matching authentication protocol - case 'ORA-01017': // ORA-01017: invalid username/password; logon denied - case 'NJS-506': // NJS-506: TLS Auth Failure - throw new AccessDeniedError(error); - case 'ORA-12541': // ORA-12541: TNS: No listener - case 'NJS-503': // NJS-503: Connection Incomplete - case 'NJS-508': // NJS-508: TLS HOST MATCH Failure - case 'NJS-507': // NJS-507: TLS DN MATCH Failure - throw new HostNotReachableError(error); - case 'NJS-512': // NJS-512: Invalid Connect String Parameters - case 'NJS-515': // NJS-515: Invalid EZCONNECT Syntax - case 'NJS-518': // NJS-518: Invald ServiceName - case 'NJS-519': // NJS-519: Invald SID - throw new InvalidConnectionError(error); - case 'ORA-12170': // ORA-12170: TNS: Connect Timeout occurred - case 'NJS-510': // NJS-510: Connect Timeout occurred - throw new ConnectionTimedOutError(error); - default: - throw new ConnectionError(error); - } - } - } - - async disconnect(connection: OracleConnection) { - if (!connection.isHealthy()) { - debug('connection tried to disconnect but was already at CLOSED state'); - - return; - } - - await new Promise((resolve, reject) => { - connection.close(error => { - if (error) { - // eslint-disable-next-line prefer-promise-reject-errors - return void reject(); - } - - resolve(); - - return undefined; - }); - }); - } - - validate(connection: OracleConnection): boolean { - return connection && connection.isHealthy(); - } -} diff --git a/packages/oracle/src/dialect.ts b/packages/oracle/src/dialect.ts deleted file mode 100644 index 52e88a20f1c3..000000000000 --- a/packages/oracle/src/dialect.ts +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -import type { Sequelize } from '@sequelize/core'; -import { AbstractDialect } from '@sequelize/core'; -import type { SupportableNumericOptions } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/dialect.js'; -import { createNamedParamBindCollector } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/sql.js'; -import { getSynchronizedTypeKeys } from '@sequelize/utils'; -import * as DataTypes from './_internal/data-types-overrides'; -import { OracleConnectionManager } from './connection-manager'; -import type { OracleConnectionOptions, oracledbModule } from './connection-manager.js'; -import { OracleQueryGenerator } from './query-generator.js'; -import { OracleQueryInterface } from './query-interface.js'; -import { OracleQuery } from './query.js'; - -export interface OracleDialectOptions { - /** - * The oracledb module to user. - */ - oracledbModule?: oracledbModule; -} - -const CONNECTION_OPTION_NAMES = getSynchronizedTypeKeys({ - database: undefined, - host: undefined, - oracleOptions: undefined, - port: undefined, - accessToken: undefined, - accessTokenConfig: undefined, - connectString: undefined, - connectionString: undefined, - walletPassword: undefined, - walletLocation: undefined, - edition: undefined, - events: undefined, - externalAuth: undefined, - matchAny: undefined, - newPassword: undefined, - password: undefined, - sslAllowWeakDNMatch: undefined, - httpsProxy: undefined, - httpsProxyPort: undefined, - debugJdwp: undefined, - retryCount: undefined, - retryDelay: undefined, - connectTimeout: undefined, - transportConnectTimeout: undefined, - expireTime: undefined, - sdu: undefined, - connectionIdPrefix: undefined, - configDir: undefined, - sourceRoute: undefined, - sslServerCertDN: undefined, - sslServerDNMatch: undefined, - poolAlias: undefined, - privilege: undefined, - shardingKey: undefined, - stmtCacheSize: undefined, - superShardingKey: undefined, - tag: undefined, - user: undefined, - username: undefined, -}); - -const numericOptions: SupportableNumericOptions = { - zerofill: false, - unsigned: true, -}; - -export class OracleDialect extends AbstractDialect { - static readonly supports = AbstractDialect.extendSupport({ - 'VALUES ()': true, - 'LIMIT ON UPDATE': true, - lock: false, - forShare: 'LOCK IN SHARE MODE', - index: { - collate: false, - length: false, - parser: false, - type: false, - using: false, - }, - constraints: { - restrict: false, - onUpdate: false, - }, - returnValues: false, - returnIntoValues: true, - 'ORDER NULLS': true, - schemas: true, - inserts: { - updateOnDuplicate: false, - }, - indexViaAlter: false, - dataTypes: { - COLLATE_BINARY: true, - GEOMETRY: false, - JSON: true, - INTS: numericOptions, - DOUBLE: numericOptions, - DECIMAL: { unconstrained: true }, - TIME: { - precision: false, - }, - }, - jsonOperations: true, - jsonExtraction: { - quoted: true, - }, - dropTable: { - cascade: true, - }, - renameTable: { - changeSchema: false, - }, - delete: { - limit: true, - }, - startTransaction: { - useBegin: true, - }, - upserts: true, - bulkDefault: true, - topLevelOrderByRequired: true, - }); - - readonly connectionManager: OracleConnectionManager; - readonly queryGenerator: OracleQueryGenerator; - readonly queryInterface: OracleQueryInterface; - readonly Query = OracleQuery; - readonly dataTypesDocumentationUrl = - 'https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/Data-Types.html'; - - constructor(sequelize: Sequelize, options: OracleDialectOptions) { - super({ - dataTypesDocumentationUrl: - 'https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/Data-Types.html', - minimumDatabaseVersion: '18.0.0', - identifierDelimiter: '"', - name: 'oracle', - options, - sequelize, - dataTypeOverrides: DataTypes, - }); - - this.connectionManager = new OracleConnectionManager(this); - // this.connectionManager.initPools(); - this.queryGenerator = new OracleQueryGenerator(this); - this.queryInterface = new OracleQueryInterface(this); - } - - parseConnectionUrl(): OracleConnectionOptions { - throw new Error( - 'The "url" option is not supported by the Db2 dialect. Instead, please use the "odbcOptions" option.', - ); - } - - getDefaultSchema(): string { - return this.sequelize.options.replication.write.username?.toUpperCase() ?? ''; - } - - createBindCollector() { - return createNamedParamBindCollector(':'); - } - - static getDefaultPort(): number { - return 1521; - } - - escapeString(val: string): string { - if (val.startsWith('TO_TIMESTAMP') || val.startsWith('TO_DATE')) { - return val; - } - - val = val.replaceAll("'", "''"); - - return `'${val}'`; - } - - escapeBuffer(buffer: Buffer): string { - const hex = buffer.toString('hex'); - - return `'${hex}'`; - } - - static getSupportedOptions() { - return []; - } - - static getSupportedConnectionOptions() { - return CONNECTION_OPTION_NAMES; - } -} diff --git a/packages/oracle/src/index.mjs b/packages/oracle/src/index.mjs deleted file mode 100644 index 93a13199ae04..000000000000 --- a/packages/oracle/src/index.mjs +++ /dev/null @@ -1,7 +0,0 @@ -import Pkg from './index.js'; - -export const OracleConnectionManager = Pkg.OracleConnectionManager; -export const OracleDialect = Pkg.OracleDialect; -export const OracleQueryGenerator = Pkg.OracleQueryGenerator; -export const OracleQueryInterface = Pkg.OracleQueryInterface; -export const OracleQuery = Pkg.OracleQuery; diff --git a/packages/oracle/src/index.ts b/packages/oracle/src/index.ts deleted file mode 100644 index 77a8f97c40cc..000000000000 --- a/packages/oracle/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** Generated File, do not modify directly. Run "yarn sync-exports" in the folder of the package instead */ - -export * from './connection-manager.js'; -export * from './dialect.js'; -export * from './query-generator.js'; -export * from './query-interface.js'; -export * from './query.js'; diff --git a/packages/oracle/src/query-generator-typescript.internal.ts b/packages/oracle/src/query-generator-typescript.internal.ts deleted file mode 100644 index 2295ceff1c29..000000000000 --- a/packages/oracle/src/query-generator-typescript.internal.ts +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -import type { - BulkDeleteQueryOptions, - CreateSchemaQueryOptions, - RemoveColumnQueryOptions, - RemoveConstraintQueryOptions, - RemoveIndexQueryOptions, - RenameTableQueryOptions, - TableOrModel, - TruncateTableQueryOptions, -} from '@sequelize/core'; -import { AbstractQueryGenerator, IsolationLevel } from '@sequelize/core'; -import { - CREATE_SCHEMA_QUERY_SUPPORTABLE_OPTIONS, - REMOVE_COLUMN_QUERY_SUPPORTABLE_OPTIONS, - REMOVE_INDEX_QUERY_SUPPORTABLE_OPTIONS, - RENAME_TABLE_QUERY_SUPPORTABLE_OPTIONS, - TRUNCATE_TABLE_QUERY_SUPPORTABLE_OPTIONS, -} from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-generator-typescript.js'; -import type { TableNameWithSchema } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-interface.js'; -import { rejectInvalidOptions } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/check.js'; -import { joinSQLFragments } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/join-sql-fragments.js'; -import { - extractModelDefinition, - isModelStatic, -} from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/model-utils.js'; -import { EMPTY_SET } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/object.js'; -import { generateIndexName } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/string.js'; -import type { OracleDialect } from './dialect.js'; -import { OracleQueryGeneratorInternal } from './query-generator.internal.js'; - -export class OracleQueryGeneratorTypeScript extends AbstractQueryGenerator { - readonly #internals: OracleQueryGeneratorInternal; - - constructor( - dialect: OracleDialect, - internals: OracleQueryGeneratorInternal = new OracleQueryGeneratorInternal(dialect), - ) { - super(dialect, internals); - - this.#internals = internals; - } - - describeTableQuery(tableName: TableOrModel) { - const table = this.extractTableDetails(tableName); - const currTableName = this.getCatalogName(table.tableName); - const schema = this.getCatalogName(table.schema); - - // name, type, datalength (except number / nvarchar), datalength varchar, datalength number, nullable, default value, primary ? - return [ - 'SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type ', - 'FROM all_tab_columns atc ', - 'LEFT OUTER JOIN ', - '(SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ', - 'ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) ', - schema ? `WHERE (atc.OWNER = ${this.escape(schema)}) ` : 'WHERE atc.OWNER = USER ', - `AND (atc.TABLE_NAME = ${this.escape(currTableName)})`, - 'ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC', - ].join(''); - } - - removeIndexQuery( - tableName: TableOrModel, - indexNameOrAttributes: string | string[], - options: RemoveIndexQueryOptions, - ) { - if (options) { - rejectInvalidOptions( - 'removeIndexQuery', - this.dialect, - REMOVE_INDEX_QUERY_SUPPORTABLE_OPTIONS, - EMPTY_SET, - options, - ); - } - - let indexName: string; - if (Array.isArray(indexNameOrAttributes)) { - const table = this.extractTableDetails(tableName); - indexName = generateIndexName(table, { fields: indexNameOrAttributes }); - } else { - indexName = indexNameOrAttributes; - } - - return `DROP INDEX ${this.quoteIdentifier(indexName)}`; - } - - /** - * Returns the value as it is stored in the Oracle DB - * - * @param value - */ - getCatalogName(value: string | undefined) { - if (value && this.options.quoteIdentifiers === false) { - const quotedValue = this.quoteIdentifier(value); - if (quotedValue === value) { - value = value.toUpperCase(); - } - } - - return value; - } - - showIndexesQuery(table: TableNameWithSchema) { - const [tableName, owner] = this.getSchemaNameAndTableName(table); - const sql = [ - 'SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type ', - 'FROM all_ind_columns i ', - 'INNER JOIN all_indexes u ', - 'ON (u.table_name = i.table_name AND u.index_name = i.index_name) ', - 'LEFT OUTER JOIN all_constraints c ', - 'ON (c.table_name = i.table_name AND c.index_name = i.index_name) ', - `WHERE i.table_name = ${this.escape(tableName)}`, - ' AND u.table_owner = ', - owner ? this.escape(owner) : 'USER', - ' ORDER BY index_name, column_position', - ]; - - return sql.join(''); - } - - /** - * Returns the tableName and schemaName as it is stored the Oracle DB - * - * @param table - */ - getSchemaNameAndTableName(table: any) { - table = this.extractTableDetails(table); - const tableName = this.getCatalogName(table.tableName || table); - const schemaName = this.getCatalogName(table.schema); - - return [tableName, schemaName]; - } - - removeConstraintQuery( - tableName: TableOrModel, - constraintName: string, - options?: RemoveConstraintQueryOptions, - ) { - if (constraintName.startsWith('sys')) { - return joinSQLFragments([ - 'ALTER TABLE', - this.quoteTable(tableName), - 'DROP CONSTRAINT', - options?.ifExists ? 'IF EXISTS' : '', - constraintName, - options?.cascade ? 'CASCADE' : '', - ]); - } - - return super.removeConstraintQuery(tableName, constraintName, options); - } - - renameTableQuery( - beforeTableName: TableOrModel, - afterTableName: TableOrModel, - options?: RenameTableQueryOptions, - ): string { - if (options) { - rejectInvalidOptions( - 'renameTableQuery', - this.dialect, - RENAME_TABLE_QUERY_SUPPORTABLE_OPTIONS, - EMPTY_SET, - options, - ); - } - - const beforeTable = this.extractTableDetails(beforeTableName); - const afterTable = this.extractTableDetails(afterTableName); - const renamedTable = afterTable.tableName; - - if (beforeTable.schema !== afterTable.schema) { - throw new Error( - `Moving tables between schemas is not supported by ${this.dialect.name} dialect.`, - ); - } - - return `ALTER TABLE ${this.quoteTable(beforeTableName)} RENAME TO ${this.quoteTable(renamedTable)}`; - } - - getAliasToken(): string { - return ''; - } - - removeColumnQuery( - tableName: TableOrModel, - attributeName: string, - options: RemoveColumnQueryOptions, - ): string { - rejectInvalidOptions( - 'removeColumnQuery', - this.dialect, - REMOVE_COLUMN_QUERY_SUPPORTABLE_OPTIONS, - EMPTY_SET, - options, - ); - - return joinSQLFragments([ - 'ALTER TABLE', - this.quoteTable(tableName), - 'DROP COLUMN', - this.quoteIdentifier(attributeName), - ]); - } - - createSchemaQuery(schema: string, options: CreateSchemaQueryOptions): string { - if (options) { - rejectInvalidOptions( - 'createSchemaQuery', - this.dialect, - CREATE_SCHEMA_QUERY_SUPPORTABLE_OPTIONS, - EMPTY_SET, - options, - ); - } - - const quotedSchema = this.quoteIdentifier(schema); - - return [ - 'DECLARE', - 'USER_FOUND BOOLEAN := FALSE;', - 'BEGIN', - ' BEGIN', - ' EXECUTE IMMEDIATE ', - this.escape(`CREATE USER ${quotedSchema} IDENTIFIED BY 12345 DEFAULT TABLESPACE USERS`), - ';', - ' EXCEPTION WHEN OTHERS THEN', - ' IF SQLCODE != -1920 THEN', - ' RAISE;', - ' ELSE', - ' USER_FOUND := TRUE;', - ' END IF;', - ' END;', - ' IF NOT USER_FOUND THEN', - ' EXECUTE IMMEDIATE ', - this.escape(`GRANT "CONNECT" TO ${quotedSchema}`), - ';', - ' EXECUTE IMMEDIATE ', - this.escape(`GRANT CREATE TABLE TO ${quotedSchema}`), - ';', - ' EXECUTE IMMEDIATE ', - this.escape(`GRANT CREATE VIEW TO ${quotedSchema}`), - ';', - ' EXECUTE IMMEDIATE ', - this.escape(`GRANT CREATE ANY TRIGGER TO ${quotedSchema}`), - ';', - ' EXECUTE IMMEDIATE ', - this.escape(`GRANT CREATE ANY PROCEDURE TO ${quotedSchema}`), - ';', - ' EXECUTE IMMEDIATE ', - this.escape(`GRANT CREATE SEQUENCE TO ${quotedSchema}`), - ';', - ' EXECUTE IMMEDIATE ', - this.escape(`GRANT CREATE SYNONYM TO ${quotedSchema}`), - ';', - ' EXECUTE IMMEDIATE ', - this.escape(`ALTER USER ${quotedSchema} QUOTA UNLIMITED ON USERS`), - ';', - ' END IF;', - 'END;', - ].join(' '); - } - - truncateTableQuery(tableName: TableOrModel, options: TruncateTableQueryOptions): string { - if (options) { - rejectInvalidOptions( - 'truncateTableQuery', - this.dialect, - TRUNCATE_TABLE_QUERY_SUPPORTABLE_OPTIONS, - EMPTY_SET, - options, - ); - } - - return `TRUNCATE TABLE ${this.quoteTable(tableName)}`; - } - - bulkDeleteQuery(tableName: TableOrModel, options: BulkDeleteQueryOptions): string { - const table = this.quoteTable(tableName); - const modelDefinition = extractModelDefinition(tableName); - const whereOptions = isModelStatic(tableName) ? { ...options, model: tableName } : options; - let queryTmpl; - - let whereClause = this.whereQuery(options.where, whereOptions); - whereClause = whereClause.replace('WHERE', ''); - - if (options.limit && this.dialect.supports.delete.limit) { - if (!modelDefinition) { - throw new Error( - 'Using LIMIT in bulkDeleteQuery requires specifying a model or model definition.', - ); - } - - const whereTmpl = whereClause ? ` AND ${whereClause}` : ''; - queryTmpl = `DELETE FROM ${table} WHERE rowid IN (SELECT rowid FROM ${table} WHERE rownum <= ${this.escape(options.limit)}${whereTmpl})`; - } else { - const whereTmpl = whereClause ? ` WHERE${whereClause}` : ''; - queryTmpl = `DELETE FROM ${table}${whereTmpl}`; - } - - return queryTmpl; - } - - setIsolationLevelQuery(isolationLevel: IsolationLevel): string { - switch (isolationLevel) { - case IsolationLevel.READ_UNCOMMITTED: - case IsolationLevel.READ_COMMITTED: - return 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED'; - case IsolationLevel.REPEATABLE_READ: - case IsolationLevel.SERIALIZABLE: - // Serializable mode is equal to Snapshot Isolation (SI) - // defined in ANSI std. - return 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE'; - default: - throw new Error( - `The ${isolationLevel} isolation level is not supported by ${this.dialect.name}.`, - ); - } - } - - commitTransactionQuery() { - return 'COMMIT TRANSACTION'; - } - - rollbackTransactionQuery(): string { - if (this.dialect.supports.connectionTransactionMethods) { - throw new Error( - `rollbackTransactionQuery is not supported by the ${this.dialect.name} dialect.`, - ); - } - - return 'ROLLBACK TRANSACTION'; - } -} diff --git a/packages/oracle/src/query-generator.d.ts b/packages/oracle/src/query-generator.d.ts deleted file mode 100644 index 3272395c6757..000000000000 --- a/packages/oracle/src/query-generator.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -import { OracleQueryGeneratorTypeScript } from './query-generator-typescript.internal.ts'; - -export class OracleQueryGenerator extends OracleQueryGeneratorTypeScript {} diff --git a/packages/oracle/src/query-generator.internal.ts b/packages/oracle/src/query-generator.internal.ts deleted file mode 100644 index 01202f88359d..000000000000 --- a/packages/oracle/src/query-generator.internal.ts +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -import { attributeTypeToSql } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/data-types-utils.js'; -import { AbstractQueryGeneratorInternal } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-generator-internal.js'; -import type { EscapeOptions } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-generator-typescript.js'; -import type { AddLimitOffsetOptions } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-generator.internal-types.js'; -import { wrapAmbiguousWhere } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/where-sql-builder.js'; -import type { Cast } from '@sequelize/core/_non-semver-use-at-your-own-risk_/expression-builders/cast.js'; -import type { OracleDialect } from './dialect.js'; - -export class OracleQueryGeneratorInternal< - Dialect extends OracleDialect = OracleDialect, -> extends AbstractQueryGeneratorInternal { - addLimitAndOffset(options: AddLimitOffsetOptions) { - let fragment = ''; - const offset = options.offset || 0; - - if (options.offset || options.limit) { - fragment += ` OFFSET ${this.queryGenerator.escape(offset, options)} ROWS`; - } - - if (options.limit) { - fragment += ` FETCH NEXT ${this.queryGenerator.escape(options.limit, options)} ROWS ONLY`; - } - - return fragment; - } - - formatCast(cast: Cast, options?: EscapeOptions | undefined): string { - const type = this.sequelize.normalizeDataType(cast.type); - - let castSql = wrapAmbiguousWhere( - cast.expression, - this.queryGenerator.escape(cast.expression, { ...options, type }), - ); - const targetSql = attributeTypeToSql(type).toUpperCase(); - - if (type === 'boolean') { - castSql = `(CASE WHEN ${castSql}='true' THEN 1 ELSE 0 END)`; - - return `CAST(${castSql} AS NUMBER)`; - } else if (type === 'TIMESTAMPTZ') { - castSql = castSql.slice(0, -1); - - return `${castSql} RETURNING TIMESTAMP WITH TIME ZONE)`; - } - - return `CAST(${castSql} AS ${targetSql})`; - } -} diff --git a/packages/oracle/src/query-generator.js b/packages/oracle/src/query-generator.js deleted file mode 100644 index 051a70dcffe7..000000000000 --- a/packages/oracle/src/query-generator.js +++ /dev/null @@ -1,1295 +0,0 @@ -// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -'use strict'; - -import each from 'lodash/each'; -import forOwn from 'lodash/forOwn'; -import includes from 'lodash/includes'; -import isPlainObject from 'lodash/isPlainObject'; -import toPath from 'lodash/toPath'; - -import { DataTypes } from '@sequelize/core'; -import { normalizeDataType } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/data-types-utils.js'; -import { - ADD_COLUMN_QUERY_SUPPORTABLE_OPTIONS, - CREATE_TABLE_QUERY_SUPPORTABLE_OPTIONS, -} from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-generator.js'; -import { rejectInvalidOptions } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/check.js'; -import { quoteIdentifier } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/dialect.js'; -import { joinSQLFragments } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/join-sql-fragments.js'; -import { - EMPTY_OBJECT, - EMPTY_SET, - getObjectFromMap, -} from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/object.js'; -import { defaultValueSchemable } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/query-builder-utils.js'; -import { OracleQueryGeneratorTypeScript } from './query-generator-typescript.internal'; - -const CREATE_TABLE_QUERY_SUPPORTED_OPTIONS = new Set(['uniqueKeys']); - -/** - * list of reserved words in Oracle DB 21c - * source: https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-7B72E154-677A-4342-A1EA-C74C1EA928E6 - * - * @private - */ -const ORACLE_RESERVED_WORDS = [ - 'ACCESS', - 'ADD', - 'ALL', - 'ALTER', - 'AND', - 'ANY', - 'ARRAYLEN', - 'AS', - 'ASC', - 'AUDIT', - 'BETWEEN', - 'BY', - 'CHAR', - 'CHECK', - 'CLUSTER', - 'COLUMN', - 'COMMENT', - 'COMPRESS', - 'CONNECT', - 'CREATE', - 'CURRENT', - 'DATE', - 'DECIMAL', - 'DEFAULT', - 'DELETE', - 'DESC', - 'DISTINCT', - 'DROP', - 'ELSE', - 'EXCLUSIVE', - 'EXISTS', - 'FILE', - 'FLOAT', - 'FOR', - 'FROM', - 'GRANT', - 'GROUP', - 'HAVING', - 'IDENTIFIED', - 'IMMEDIATE', - 'IN', - 'INCREMENT', - 'INDEX', - 'INITIAL', - 'INSERT', - 'INTEGER', - 'INTERSECT', - 'INTO', - 'IS', - 'LEVEL', - 'LIKE', - 'LOCK', - 'LONG', - 'MAXEXTENTS', - 'MINUS', - 'MODE', - 'MODIFY', - 'NOAUDIT', - 'NOCOMPRESS', - 'NOT', - 'NOTFOUND', - 'NOWAIT', - 'NULL', - 'NUMBER', - 'OF', - 'OFFLINE', - 'ON', - 'ONLINE', - 'OPTION', - 'OR', - 'ORDER', - 'PCTFREE', - 'PRIOR', - 'PRIVILEGES', - 'PUBLIC', - 'RAW', - 'RENAME', - 'RESOURCE', - 'REVOKE', - 'ROW', - 'ROWID', - 'ROWLABEL', - 'ROWNUM', - 'ROWS', - 'SELECT', - 'SESSION', - 'SET', - 'SHARE', - 'SIZE', - 'SMALLINT', - 'SQLBUF', - 'START', - 'SUCCESSFUL', - 'SYNONYM', - 'SYSDATE', - 'TABLE', - 'THEN', - 'TO', - 'TRIGGER', - 'UID', - 'UNION', - 'UNIQUE', - 'UPDATE', - 'USER', - 'VALIDATE', - 'VALUES', - 'VARCHAR', - 'VARCHAR2', - 'VIEW', - 'WHENEVER', - 'WHERE', - 'WITH', -]; -const JSON_FUNCTION_REGEX = /^\s*((?:[a-z]+_){0,2}jsonb?(?:_[a-z]+){0,2})\([^)]*\)/i; -const JSON_OPERATOR_REGEX = /^\s*(->>?|@>|<@|\?[|&]?|\|{2}|#-)/i; -const TOKEN_CAPTURE_REGEX = /^\s*((?:([`"'])(?:(?!\2).|\2{2})*\2)|[\w\d\s]+|[().,;+-])/i; - -export class OracleQueryGenerator extends OracleQueryGeneratorTypeScript { - listSchemasQuery() { - return 'SELECT USERNAME AS "schema" FROM ALL_USERS WHERE COMMON = (\'NO\') AND USERNAME != user'; - } - - dropSchemaQuery(schema) { - return [ - 'BEGIN', - 'EXECUTE IMMEDIATE ', - this.escape(`DROP USER ${this.quoteTable(schema)} CASCADE`), - ';', - 'EXCEPTION WHEN OTHERS THEN', - ' IF SQLCODE != -1918 THEN', - ' RAISE;', - ' END IF;', - 'END;', - ].join(' '); - } - - versionQuery() { - return `SELECT VERSION_FULL FROM PRODUCT_COMPONENT_VERSION WHERE PRODUCT LIKE 'Oracle%'`; - } - - createTableQuery(tableName, attributes, options) { - if (options) { - rejectInvalidOptions( - 'createTableQuery', - this.dialect, - CREATE_TABLE_QUERY_SUPPORTABLE_OPTIONS, - CREATE_TABLE_QUERY_SUPPORTED_OPTIONS, - options, - ); - } - - const primaryKeys = []; - const foreignKeys = Object.create(null); - const attrStr = []; - const checkStr = []; - - const values = { - table: this.quoteTable(tableName), - }; - - // Starting by dealing with all attributes - for (let attr in attributes) { - if (!Object.hasOwn(attributes, attr)) { - continue; - } - - const dataType = attributes[attr]; - attr = this.quoteIdentifier(attr); - - // ORACLE doesn't support inline REFERENCES declarations: move to the end - if (dataType.includes('PRIMARY KEY')) { - // Primary key - primaryKeys.push(attr); - if (dataType.includes('REFERENCES')) { - const match = dataType.match(/^(.+) (REFERENCES.*)$/); - attrStr.push(`${attr} ${match[1].replace(/PRIMARY KEY/, '')}`); - - // match[2] already has foreignKeys in correct format so we don't need to replace - foreignKeys[attr] = match[2]; - } else { - attrStr.push(`${attr} ${dataType.replace(/PRIMARY KEY/, '').trim()}`); - } - } else if (dataType.includes('REFERENCES')) { - // Foreign key - const match = dataType.match(/^(.+) (REFERENCES.*)$/); - attrStr.push(`${attr} ${match[1]}`); - - // match[2] already has foreignKeys in correct format so we don't need to replace - foreignKeys[attr] = match[2]; - } else { - attrStr.push(`${attr} ${dataType}`); - } - } - - values.attributes = attrStr.join(', '); - - const pkString = primaryKeys.join(', '); - - if (pkString.length > 0) { - values.attributes += `,PRIMARY KEY (${pkString})`; - } - - // Dealing with FKs - for (const fkey in foreignKeys) { - if (!Object.hasOwn(foreignKeys, fkey)) { - continue; - } - - // Oracle default response for FK, doesn't support if defined - if (foreignKeys[fkey].includes('ON DELETE NO ACTION')) { - foreignKeys[fkey] = foreignKeys[fkey].replace('ON DELETE NO ACTION', ''); - } - - values.attributes += `,FOREIGN KEY (${fkey}) ${foreignKeys[fkey]}`; - } - - if (checkStr.length > 0) { - values.attributes += `, ${checkStr.join(', ')}`; - } - - // Specific case for unique indexes with Oracle, we have to set the constraint on the column, if not, no FK will be possible (ORA-02270: no matching unique or primary key for this column-list) - if (options && options.indexes && options.indexes.length > 0) { - const idxToDelete = []; - options.indexes.forEach((index, idx) => { - if ( - 'unique' in index && - (index.unique === true || (index.unique.length > 0 && index.unique !== false)) - ) { - // If unique index, transform to unique constraint on column - const fields = index.fields.map(field => { - if (typeof field === 'string') { - return field; - } - - return field.attribute; - }); - - // Now we have to be sure that the constraint isn't already declared in uniqueKeys - let canContinue = true; - if (options.uniqueKeys) { - const keys = Object.keys(options.uniqueKeys); - - // eslint-disable-next-line unicorn/no-for-loop - for (let fieldIdx = 0; fieldIdx < keys.length; fieldIdx++) { - const currUnique = options.uniqueKeys[keys[fieldIdx]]; - - if (currUnique.fields.length === fields.length) { - let i; - // lengths are the same, possible same constraint - for (i = 0; i < currUnique.fields.length; i++) { - const field = currUnique.fields[i]; - - if (includes(fields, field)) { - canContinue = false; - } else { - // We have at least one different column, even if we found the same columns previously, we let the constraint be created - canContinue = true; - break; - } - } - - if (i === currUnique.fields.length) { - break; - } - } - } - - if (canContinue) { - const indexName = 'name' in index ? index.name : ''; - const constraintToAdd = { - name: indexName, - fields, - }; - if (!('uniqueKeys' in options)) { - options.uniqueKeys = {}; - } - - options.uniqueKeys[indexName] = constraintToAdd; - idxToDelete.push(idx); - } else { - // The constraint already exists, we remove it from the list - idxToDelete.push(idx); - } - } - } - }); - idxToDelete.forEach(idx => { - options.indexes.splice(idx, 1); - }); - } - - if (options?.uniqueKeys) { - // only need to sort primary keys once, don't do it in place - let sortedPrimaryKeys = [...primaryKeys]; - sortedPrimaryKeys = sortedPrimaryKeys.map(elem => { - return elem.replaceAll('"', ''); - }); - sortedPrimaryKeys.sort(); - each(options.uniqueKeys, (columns, indexName) => { - const sortedColumnFields = [...columns.fields]; - sortedColumnFields.sort(); - // if primary keys === unique keys, then skip adding new constraint - const uniqueIsPrimary = - sortedColumnFields.length === primaryKeys.length && - sortedColumnFields.every((value, index) => { - return value === sortedPrimaryKeys[index]; - }); - if (uniqueIsPrimary) { - return true; - } - - // generate Constraint name, if no indexName is given - if (typeof indexName !== 'string') { - indexName = `uniq_${tableName}_${columns.fields.join('_')}`; - } - - values.attributes += `, CONSTRAINT ${this.quoteIdentifier(indexName)} UNIQUE (${columns.fields.map(field => this.quoteIdentifier(field)).join(', ')})`; - }); - } - - // we replace single quotes by two quotes in order for the execute statement to work - const query = joinSQLFragments(['CREATE TABLE', values.table, `(${values.attributes})`]); - - return joinSQLFragments([ - 'BEGIN', - 'EXECUTE IMMEDIATE', - `${this.escape(query)};`, - 'EXCEPTION WHEN OTHERS THEN', - 'IF SQLCODE != -955 THEN', - 'RAISE;', - 'END IF;', - 'END;', - ]); - } - - tableExistsQuery(table) { - const [tableName, schemaName] = this.getSchemaNameAndTableName(table); - - return `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = ${this.escape(tableName)} AND OWNER = ${table.schema ? this.escape(schemaName) : 'USER'}`; - } - - showConstraintsQuery(tableName, options) { - if (options && options.constraintType === 'FOREIGN KEY') { - return this.getForeignKeysQuery(tableName); - } - - let table = this.extractTableDetails(tableName); - const schema = this.getCatalogName(table.schema); - table = this.getCatalogName(table.tableName); - - return joinSQLFragments([ - 'SELECT C.CONSTRAINT_NAME "constraintName",', - `CASE A.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType",`, - 'C.TABLE_NAME "tableName",', - 'C.OWNER "constraintSchema",', - 'C.COLUMN_NAME "columnNames"', - 'FROM ALL_CONS_COLUMNS C', - 'INNER JOIN ALL_CONSTRAINTS A ON C.CONSTRAINT_NAME = A.CONSTRAINT_NAME', - `WHERE C.TABLE_NAME =${this.escape(table)}`, - `AND C.OWNER =${this.escape(schema)}`, - options?.constraintName - ? `AND C.CONSTRAINT_NAME =${this.escape(options.constraintName)}` - : '', - options?.constraintType - ? `AND A.CONSTRAINT_TYPE =${this.escape(this._getConstraintType(options.constraintType))}` - : '', - 'ORDER BY C.CONSTRAINT_NAME', - ]); - } - - _getConstraintType(type) { - switch (type) { - case 'CHECK': - return 'C'; - case 'FOREIGN KEY': - return 'R'; - case 'PRIMARY KEY': - return 'P'; - case 'UNIQUE': - return 'U'; - default: - throw new Error(`Constraint type ${type} is not supported`); - } - } - - listTablesQuery(options) { - let query = `SELECT owner as "schema", table_name as "tableName" FROM all_tables where OWNER IN`; - if (options && options.schema) { - query += `(SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE ORACLE_MAINTAINED = 'N' AND USERNAME=${this.escape(options.schema)})`; - } else { - query += `(SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE ORACLE_MAINTAINED = 'N')`; - } - - return query; - } - - dropTableQuery(tableName) { - return joinSQLFragments([ - 'BEGIN ', - "EXECUTE IMMEDIATE 'DROP TABLE", - this.quoteTable(tableName), - "CASCADE CONSTRAINTS PURGE';", - 'EXCEPTION WHEN OTHERS THEN', - ' IF SQLCODE != -942 THEN', - ' RAISE;', - ' END IF;', - 'END;', - ]); - } - - /* - Modifying the indexname so that it is prefixed with the schema name - otherwise Oracle tries to add the index to the USER schema - @overide - */ - addIndexQuery(tableName, attributes, options, rawTablename) { - if (typeof tableName !== 'string' && attributes.name) { - attributes.name = `${tableName.schema}.${attributes.name}`; - } - - return super.addIndexQuery(tableName, attributes, options, rawTablename); - } - - // addConstraintQuery(tableName, options) { - // options = options || {}; - - // const constraintSnippet = this.getConstraintSnippet(tableName, options); - - // tableName = this.quoteTable(tableName); - // return `ALTER TABLE ${tableName} ADD ${constraintSnippet};`; - // } - - addColumnQuery(table, key, dataType, options) { - if (options) { - rejectInvalidOptions( - 'addColumnQuery', - this.dialect, - ADD_COLUMN_QUERY_SUPPORTABLE_OPTIONS, - EMPTY_SET, - options, - ); - } - - dataType = { - ...dataType, - field: key, - type: normalizeDataType(dataType.type, this.dialect), - }; - dataType.field = key; - - const attribute = joinSQLFragments([ - this.quoteIdentifier(key), - this.attributeToSQL(dataType, { - attributeName: key, - context: 'addColumn', - }), - ]); - - return joinSQLFragments(['ALTER TABLE', this.quoteTable(table), 'ADD', attribute, ';']); - } - - /** - * Function to add new foreign key to the attribute - * Block for add and drop foreign key constraint query - * taking the assumption that there is a single column foreign key reference always - * i.e. we always do - FOREIGN KEY (a) reference B(a) during createTable queryGenerator - * so there would be one and only one match for a constraint name for each column - * and every foreign keyed column would have a different constraint name - * Since sequelize doesn't support multiple column foreign key, added complexity to - * add the feature isn't needed - * - * @param {string} definition The operation that needs to be performed on the attribute - * @param {string|object} table The table that needs to be altered - * @param {string} attributeName The name of the attribute which would get altered - */ - _alterForeignKeyConstraint(definition, table, attributeName) { - const [tableName, schemaName] = this.getSchemaNameAndTableName(table); - const attributeNameConstant = this.escape(this.getCatalogName(attributeName)); - const schemaNameConstant = table.schema ? this.escape(this.getCatalogName(schemaName)) : 'USER'; - const tableNameConstant = this.escape(this.getCatalogName(tableName)); - const getConsNameQuery = [ - 'SELECT constraint_name INTO cons_name', - 'FROM (', - ' SELECT DISTINCT cc.owner, cc.table_name, cc.constraint_name, cc.column_name AS cons_columns', - ' FROM all_cons_columns cc, all_constraints c', - ' WHERE cc.owner = c.owner', - ' AND cc.table_name = c.table_name', - ' AND cc.constraint_name = c.constraint_name', - " AND c.constraint_type = 'R'", - ' GROUP BY cc.owner, cc.table_name, cc.constraint_name, cc.column_name', - ')', - 'WHERE owner =', - schemaNameConstant, - 'AND table_name =', - tableNameConstant, - 'AND cons_columns =', - attributeNameConstant, - ';', - ].join(' '); - const secondQuery = joinSQLFragments([ - `ALTER TABLE ${this.quoteTable(table)}`, - 'ADD FOREIGN KEY', - `(${this.quoteIdentifier(attributeName)})`, - definition.replace(/.+?(?=REFERENCES)/, ''), - ]); - - return [ - 'BEGIN', - getConsNameQuery, - 'EXCEPTION', - 'WHEN NO_DATA_FOUND THEN', - ' CONS_NAME := NULL;', - 'END;', - 'IF CONS_NAME IS NOT NULL THEN', - ` EXECUTE IMMEDIATE 'ALTER TABLE ${this.quoteTable(table)} DROP CONSTRAINT "'||CONS_NAME||'"';`, - 'END IF;', - `EXECUTE IMMEDIATE ${this.escape(secondQuery)};`, - ].join(' '); - } - - /** - * Function to alter table modify - * - * @param {string} definition The operation that needs to be performed on the attribute - * @param {object|string} table The table that needs to be altered - * @param {string} attributeName The name of the attribute which would get altered - */ - _modifyQuery(definition, table, attributeName) { - const query = joinSQLFragments([ - 'ALTER TABLE', - this.quoteTable(table), - 'MODIFY', - this.quoteIdentifier(attributeName), - definition, - ]); - const secondQuery = query.replace('NOT NULL', '').replace('NULL', ''); - - return [ - 'BEGIN', - `EXECUTE IMMEDIATE ${this.escape(query)};`, - 'EXCEPTION', - 'WHEN OTHERS THEN', - ' IF SQLCODE = -1442 OR SQLCODE = -1451 THEN', - // We execute the statement without the NULL / NOT NULL clause if the first statement failed due to this - ` EXECUTE IMMEDIATE ${this.escape(secondQuery)};`, - ' ELSE', - ' RAISE;', - ' END IF;', - 'END;', - ].join(' '); - } - - changeColumnQuery(table, attributes) { - const sql = ['DECLARE', 'CONS_NAME VARCHAR2(200);', 'BEGIN']; - for (const attributeName in attributes) { - if (!Object.hasOwn(attributes, attributeName)) { - continue; - } - - const definition = attributes[attributeName]; - // eslint-disable-next-line unicorn/prefer-regexp-test - if (definition.match(/REFERENCES/)) { - sql.push(this._alterForeignKeyConstraint(definition, table, attributeName)); - } else { - // Building the modify query - sql.push(this._modifyQuery(definition, table, attributeName)); - } - } - - sql.push('END;'); - - return sql.join(' '); - } - - renameColumnQuery(tableName, attrBefore, attributes) { - const newName = Object.keys(attributes)[0]; - - return `ALTER TABLE ${this.quoteTable(tableName)} RENAME COLUMN ${this.quoteIdentifier(attrBefore)} TO ${this.quoteIdentifier(newName)}`; - } - - /** - * Populates the returnAttributes array with outbind bindByPosition values - * and also the options.outBindAttributes map with bindDef for outbind of InsertQuery - * - * @param {Array} returningModelAttributes - * @param {Array} returnTypes - * @param {number} inbindLength - * @param {object} returnAttributes - * @param {object} options - * - * @private - */ - populateInsertQueryReturnIntoBinds( - returningModelAttributes, - returnTypes, - inbindLength, - returnAttributes, - options, - ) { - const oracledb = this.sequelize.dialect.connectionManager.lib; - const outBindAttributes = Object.create(null); - const outbind = {}; - const outbindParam = this.bindParam(outbind, inbindLength); - returningModelAttributes.forEach((element, index) => { - // generateReturnValues function quotes identifier based on the quoteIdentifier option - // If the identifier starts with a quote we remove it else we use it as is - if (element.startsWith('"')) { - element = element.slice(1, -1); - } - - outBindAttributes[element] = Object.assign(returnTypes[index]._getBindDef(oracledb), { - dir: oracledb.BIND_OUT, - }); - const returnAttribute = `${outbindParam(undefined)}`; - returnAttributes.push(returnAttribute); - }); - options.outBindAttributes = outBindAttributes; - } - - /** - * Override of upsertQuery, Oracle specific - * Using PL/SQL for finding the row - * - * @param {object|string} tableName - * @param {Array} insertValues - * @param {Array} updateValues - * @param {Array} where - * @param {object} model - * @param {object} options - */ - upsertQuery(tableName, insertValues, updateValues, where, model, options) { - const modelDefinition = model.modelDefinition; - const rawAttributes = getObjectFromMap(modelDefinition.attributes); - const updateQuery = this.updateQuery(tableName, updateValues, where, options, rawAttributes); - // This bind is passed so that the insert query starts appending to this same bind array - options.bind = updateQuery.bind; - const insertQuery = this.insertQuery(tableName, insertValues, rawAttributes, options); - - const sql = [ - 'DECLARE ', - 'BEGIN ', - updateQuery.query - ? [ - updateQuery.query, - '; ', - ' IF ( SQL%ROWCOUNT = 0 ) THEN ', - insertQuery.query, - ' :isUpdate := 0; ', - 'ELSE ', - ' :isUpdate := 1; ', - ' END IF; ', - ].join('') - : [ - insertQuery.query, - ' :isUpdate := 0; ', - // If there is a conflict on insert we ignore - 'EXCEPTION WHEN OTHERS THEN', - ' IF SQLCODE != -1 THEN', - ' RAISE;', - ' END IF;', - ].join(''), - 'END;', - ]; - - const query = sql.join(''); - - if (options.bindParam !== false) { - options.bind = updateQuery.bind || insertQuery.bind; - } - - return query; - } - - /** - * Returns an insert into command for multiple values. - * - * @param {string} tableName - * @param {object} fieldValueHashes - * @param {object} options - * @param {object} fieldMappedAttributes - * - * @private - */ - bulkInsertQuery(tableName, fieldValueHashes, options, fieldMappedAttributes) { - options = options || {}; - options.executeMany = true; - fieldMappedAttributes = fieldMappedAttributes || {}; - - const tuples = []; - const allColumns = {}; - const inBindBindDefMap = {}; - const outBindBindDefMap = {}; - const oracledb = this.sequelize.dialect.connectionManager.lib; - - // Generating the allColumns map - // The data is provided as an array of objects. - // Each object may contain differing numbers of attributes. - // A set of the attribute names that are used in all objects must be determined. - // The allColumns map contains the column names and indicates whether the value is generated or not - // We set allColumns[key] to true if the field is an - // auto-increment field and the value given is null and fieldMappedAttributes[key] - // is valid for the specific column else it is set to false - for (const fieldValueHash of fieldValueHashes) { - forOwn(fieldValueHash, (value, key) => { - allColumns[key] = - fieldMappedAttributes[key] && - fieldMappedAttributes[key].autoIncrement === true && - value === null; - }); - } - - // Building the inbind parameter - // A list that would have inbind positions like [:1, :2, :3...] to be used in generating sql string - let inBindPosition; - // Iterating over each row of the fieldValueHashes - for (const fieldValueHash of fieldValueHashes) { - // Has each column for a row after coverting it to appropriate format using this.format function - // like ['Mick', 'Broadstone', 2022-02-16T05:24:18.949Z, 2022-02-16T05:24:18.949Z], - let tuple = []; - const bindMap = {}; - // A function expression for this.bindParam/options.bindparam function - // This function is passed to this.format function which inserts column values to the tuple list - // using _bindParam/_stringify function in data-type.js file - const inbindParam = - options.bindParam === undefined ? this.bindParam(bindMap) : options.bindParam; - // We are iterating over each col - // and pushing the given values to tuple list using this.format function - // and also simultaneously generating the bindPosition - // tempBindPostions has the inbind positions - const tempBindPositions = Object.keys(allColumns).map(key => { - if (allColumns[key] === true) { - // We had set allAttributes[key] to true since at least one row for an auto increment column was null - // If we get any other row that has this specific column as non-null we must raise an error - // Since for an auto-increment column, either all row has to be null or all row has to be a non-null - if (fieldValueHash[key] !== null) { - throw new Error( - 'For an auto-increment column either all row must be null or non-null, a mix of null and non-null is not allowed!', - ); - } - - // Return DEFAULT for auto-increment column and if all values for the column is null in each row - return 'DEFAULT'; - } - - // Sanitizes the values given by the user and pushes it to the tuple list using inBindParam function and - // also generates the inbind position for the sql string for example (:1, :2, :3.....) which is a by product of the push - return this.escape(fieldValueHash[key] ?? null, { - model: options.model, - type: fieldMappedAttributes[key] ? fieldMappedAttributes[key].type : null, - bindParam: inbindParam, - }); - }); - - // Even though the bind variable positions are calculated for each row we only retain the values for the first row - // since the values will be identical - if (!inBindPosition) { - inBindPosition = tempBindPositions; - } - - tuple = Object.values(bindMap); - // Adding the row to the array of rows that will be supplied to executeMany() - tuples.push(tuple); - } - - // The columns that we are expecting to be returned from the DB like ["id1", "id2"...] - const returnColumn = []; - // The outbind positions for the returning columns like [:3, :4, :5....] - const returnColumnBindPositions = []; - // Has the columns name in which data would be inserted like ["id", "name".....] - const insertColumns = []; - // Iterating over the allColumns keys to get the bindDef for inbind and outbinds - // and also to get the list of insert and return column after applying this.quoteIdentifier - for (const key of Object.keys(allColumns)) { - // If fieldMappenAttributes[attr] is defined we generate the bindDef - // and return clause else we can skip it - if (fieldMappedAttributes[key]) { - // BindDef for the specific column - const bindDef = fieldMappedAttributes[key].type._getBindDef(oracledb); - if (allColumns[key]) { - // Binddef for outbinds - bindDef.dir = oracledb.BIND_OUT; - outBindBindDefMap[key] = bindDef; - - // Building the outbind parameter list - // ReturnColumn has the column name for example "id", "usedId", quoting depends on quoteIdentifier option - returnColumn.push(this.quoteIdentifier(key)); - // Pushing the outbind index to the returnColumnPositions to generate (:3, :4, :5) - // The start offset depend on the tuple length (bind array size of a particular row) - // the outbind position starts after the position where inbind position ends - returnColumnBindPositions.push(`:${tuples[0].length + returnColumn.length}`); - } else { - // Binddef for inbinds - bindDef.dir = oracledb.BIND_IN; - inBindBindDefMap[key] = bindDef; - } - } - - // Quoting and pushing each insert column based on quoteIdentifier option - insertColumns.push(this.quoteIdentifier(key)); - } - - // Generating the sql query - let query = joinSQLFragments([ - 'INSERT', - 'INTO', - // Table name for the table in which data needs to inserted - this.quoteTable(tableName), - // Columns names for the columns of the table (example "a", "b", "c" - quoting depends on the quoteidentifier option) - `(${insertColumns.join(',')})`, - 'VALUES', - // InBind position for the insert query (for example :1, :2, :3....) - `(${inBindPosition})`, - ]); - - // If returnColumn.length is > 0 - // then the returning into clause is needed - if (returnColumn.length > 0) { - options.outBindAttributes = outBindBindDefMap; - query = joinSQLFragments([ - query, - 'RETURNING', - // List of return column (for example "id", "userId"....) - `${returnColumn.join(',')}`, - 'INTO', - // List of outbindPosition (for example :4, :5, :6....) - // Start offset depends on where inbindPosition end - `${returnColumnBindPositions}`, - ]); - } - - // Binding the bind variable to result - const result = query; - // Binding the bindParam to result - // Tuple has each row for the insert query - options.bind = tuples; - // Setting options.inbindAttribute - options.inbindAttributes = inBindBindDefMap; - - return result; - } - - deleteQuery(tableName, where, options = EMPTY_OBJECT, model) { - const table = tableName; - - let whereClause = this.whereQuery(where, { ...options, model }); - whereClause = whereClause.replace('WHERE', ''); - let queryTmpl; - // delete with limit and optional condition on Oracle: DELETE FROM WHERE rowid in (SELECT rowid FROM WHERE AND rownum <= ) - // Note that the condition has to be in the subquery; otherwise, the subquery would select arbitrary rows. - if (options.limit) { - const whereTmpl = whereClause ? ` AND ${whereClause}` : ''; - queryTmpl = `DELETE FROM ${this.quoteTable(table)} WHERE rowid IN (SELECT rowid FROM ${this.quoteTable(table)} WHERE rownum <= ${this.escape(options.limit)}${whereTmpl})`; - } else { - const whereTmpl = whereClause ? ` WHERE${whereClause}` : ''; - queryTmpl = `DELETE FROM ${this.quoteTable(table)}${whereTmpl}`; - } - - return queryTmpl; - } - - attributeToSQL(attribute, options) { - if (!isPlainObject(attribute)) { - attribute = { - type: attribute, - }; - } - - // handle self referential constraints - if ( - attribute.references && - attribute.Model && - attribute.Model.tableName === attribute.references.tableName - ) { - this.sequelize.log( - 'Oracle does not support self referencial constraints, ' + - 'we will remove it but we recommend restructuring your query', - ); - attribute.onDelete = ''; - } - - let template; - - if (attribute.type instanceof DataTypes.ENUM) { - // enums are a special case - template = attribute.type.toSql({ dialect: this.dialect }); - template += ` CHECK (${this.quoteIdentifier(options.attributeName)} IN(${attribute.type.options.values - .map(value => { - return this.escape(value, undefined, {}); - }) - .join(', ')}))`; - - return template; - } - - if (attribute.type instanceof DataTypes.JSON) { - template = attribute.type.toSql(); - template += ` CHECK (${this.quoteIdentifier(options.attributeName)} IS JSON)`; - - return template; - } - - if (attribute.type instanceof DataTypes.BOOLEAN) { - template = attribute.type.toSql(); - template += ` CHECK (${this.quoteIdentifier(options.attributeName)} IN('1', '0'))`; - - return template; - } - - if (attribute.autoIncrement) { - template = ' NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY'; - } else if (attribute.type && attribute.type === 'DOUBLE') { - template = attribute.type.toSql(); - } else if (attribute.type) { - // setting it to false because oracle doesn't support unsigned int so put a check to make it behave like unsigned int - let unsignedTemplate = ''; - if (attribute.type?.options?.unsigned) { - attribute.type.options.unsigned = false; - unsignedTemplate += ` CHECK(${this.quoteIdentifier(options.attributeName)} >= 0)`; - } - - template = attribute.type.toString(); - - // Blobs/texts cannot have a defaultValue - if ( - attribute.type && - attribute.type !== 'TEXT' && - attribute.type._binary !== true && - defaultValueSchemable(attribute.defaultValue, this.dialect) - ) { - template += ` DEFAULT ${this.escape(attribute.defaultValue)}`; - } - - if (!attribute.autoIncrement) { - // If autoincrement, not null is set automatically - if (attribute.allowNull === false) { - template += ' NOT NULL'; - } else if ( - !attribute.primaryKey && - !defaultValueSchemable(attribute.defaultValue, this.dialect) - ) { - template += ' NULL'; - } - } - - template += unsignedTemplate; - } else { - template = ''; - } - - if (attribute.primaryKey) { - template += ' PRIMARY KEY'; - } - - if ((!options || !options.withoutForeignKeyConstraints) && attribute.references) { - template += ` REFERENCES ${this.quoteTable(attribute.references.table)}`; - - if (attribute.references.key) { - template += ` (${this.quoteIdentifier(attribute.references.key)})`; - } else { - template += ` (${this.quoteIdentifier('id')})`; - } - - if (attribute.onDelete && attribute.onDelete.toUpperCase() !== 'NO ACTION') { - template += ` ON DELETE ${attribute.onDelete.toUpperCase()}`; - } - } - - return template; - } - - attributesToSQL(attributes, options) { - const result = {}; - - for (const key in attributes) { - const attribute = attributes[key]; - const attributeName = attribute.field || key; - result[attributeName] = this.attributeToSQL(attribute, { attributeName, ...options }); - } - - return result; - } - - createTrigger() { - throwMethodUndefined('createTrigger'); - } - - dropTrigger() { - throwMethodUndefined('dropTrigger'); - } - - renameTrigger() { - throwMethodUndefined('renameTrigger'); - } - - createFunction() { - throwMethodUndefined('createFunction'); - } - - dropFunction() { - throwMethodUndefined('dropFunction'); - } - - renameFunction() { - throwMethodUndefined('renameFunction'); - } - - getConstraintsOnColumn(table, column) { - const [tableName, schemaName] = this.getSchemaNameAndTableName(table); - column = this.getCatalogName(column); - const sql = [ - 'SELECT CONSTRAINT_NAME FROM user_cons_columns WHERE TABLE_NAME = ', - this.escape(tableName), - ' and OWNER = ', - table.schema ? this.escape(schemaName) : 'USER', - ' and COLUMN_NAME = ', - this.escape(column), - ' AND POSITION IS NOT NULL ORDER BY POSITION', - ].join(''); - - return sql; - } - - getForeignKeysQuery(table) { - // We don't call quoteTable as we don't want the schema in the table name, Oracle seperates it on another field - const tableDetails = this.extractTableDetails(table); - const tableName = this.getCatalogName(tableDetails.tableName); - const schemaName = this.getCatalogName(tableDetails.schema); - const sql = [ - 'SELECT DISTINCT a.table_name "tableName", a.constraint_name "constraintName", a.owner "constraintSchema", a.column_name "columnNames",', - `CASE c.CONSTRAINT_TYPE WHEN 'P' THEN 'PRIMARY KEY' WHEN 'R' THEN 'FOREIGN KEY' WHEN 'C' THEN 'CHECK' WHEN 'U' THEN 'UNIQUE' ELSE NULL END "constraintType",`, - ' c.r_owner "referencedTableSchema",', - ' c.DELETE_RULE "deleteAction",', - ' b.table_name "referencedTableName", b.column_name "referencedColumnNames"', - ' FROM all_cons_columns a', - ' JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name', - ' JOIN all_cons_columns b ON c.owner = b.owner AND c.r_constraint_name = b.constraint_name', - " WHERE c.constraint_type = 'R'", - ' AND a.table_name = ', - this.escape(tableName), - ' AND a.owner = ', - tableDetails.schema && schemaName !== '' ? this.escape(schemaName) : 'USER', - ' ORDER BY a.table_name, a.column_name, b.column_name', - ].join(''); - - return sql; - } - - dropForeignKeyQuery(tableName, foreignKey) { - return this.dropConstraintQuery(tableName, foreignKey); - } - - getPrimaryKeyConstraintQuery(table) { - const [tableName, schemaName] = this.getSchemaNameAndTableName(table); - const sql = [ - 'SELECT cols.column_name, atc.identity_column ', - 'FROM all_constraints cons, all_cons_columns cols ', - 'INNER JOIN all_tab_columns atc ON(atc.table_name = cols.table_name AND atc.COLUMN_NAME = cols.COLUMN_NAME )', - 'WHERE cols.table_name = ', - this.escape(tableName), - 'AND cols.owner = ', - table.schema ? this.escape(schemaName) : 'USER ', - "AND cons.constraint_type = 'P' ", - 'AND cons.constraint_name = cols.constraint_name ', - 'AND cons.owner = cols.owner ', - 'ORDER BY cols.table_name, cols.position', - ].join(''); - - return sql; - } - - dropConstraintQuery(tableName, constraintName) { - return `ALTER TABLE ${this.quoteTable(tableName)} DROP CONSTRAINT ${constraintName}`; - } - - // handleSequelizeMethod(smth, tableName, factory, options, prepend) { - // let str; - // if (smth instanceof Utils.Json) { - // // Parse nested object - // if (smth.conditions) { - // const conditions = this.parseConditionObject(smth.conditions).map(condition => - // `${this.jsonPathExtractionQuery(condition.path[0], _.tail(condition.path))} = '${condition.value}'` - // ); - - // return conditions.join(' AND '); - // } - // if (smth.path) { - - // // Allow specifying conditions using the sqlite json functions - // if (this._checkValidJsonStatement(smth.path)) { - // str = smth.path; - // } else { - // // Also support json property accessors - // const paths = _.toPath(smth.path); - // const column = paths.shift(); - // str = this.jsonPathExtractionQuery(column, paths); - // } - // if (smth.value) { - // str += util.format(' = %s', this.escape(smth.value)); - // } - - // return str; - // } - // } - // if (smth instanceof Utils.Cast) { - // if (smth.val instanceof Utils.SequelizeMethod) { - // str = this.handleSequelizeMethod(smth.val, tableName, factory, options, prepend); - // if (smth.type === 'boolean') { - // str = `(CASE WHEN ${str}='true' THEN 1 ELSE 0 END)`; - // return `CAST(${str} AS NUMBER)`; - // } if (smth.type === 'timestamptz' && /json_value\(/.test(str)) { - // str = str.slice(0, -1); - // return `${str} RETURNING TIMESTAMP WITH TIME ZONE)`; - // } - // } - // } - // return super.handleSequelizeMethod(smth, tableName, factory, options, prepend); - // } - - _checkValidJsonStatement(stmt) { - if (typeof stmt !== 'string') { - return false; - } - - let currentIndex = 0; - let openingBrackets = 0; - let closingBrackets = 0; - let hasJsonFunction = false; - let hasInvalidToken = false; - - while (currentIndex < stmt.length) { - const string = stmt.slice(currentIndex); - const functionMatches = JSON_FUNCTION_REGEX.exec(string); - if (functionMatches) { - currentIndex += functionMatches[0].indexOf('('); - hasJsonFunction = true; - continue; - } - - const operatorMatches = JSON_OPERATOR_REGEX.exec(string); - if (operatorMatches) { - currentIndex += operatorMatches[0].length; - hasJsonFunction = true; - continue; - } - - const tokenMatches = TOKEN_CAPTURE_REGEX.exec(string); - if (tokenMatches) { - const capturedToken = tokenMatches[1]; - if (capturedToken === '(') { - openingBrackets++; - } else if (capturedToken === ')') { - closingBrackets++; - } else if (capturedToken === ';') { - hasInvalidToken = true; - break; - } - - currentIndex += tokenMatches[0].length; - continue; - } - - break; - } - - // Check invalid json statement - if (hasJsonFunction && (hasInvalidToken || openingBrackets !== closingBrackets)) { - throw new Error(`Invalid json statement: ${stmt}`); - } - - // return true if the statement has valid json function - return hasJsonFunction; - } - - isIdentifierQuoted(identifier) { - return /^\s*(?:([`"'])(?:(?!\1).|\1{2})*\1\.?)+\s*$/i.test(identifier); - } - - addTicks(identifier, tickChar) { - identifier = identifier.replaceAll(new RegExp(tickChar, 'g'), ''); - - return tickChar + identifier + tickChar; - } - - jsonPathExtractionQuery(column, path) { - let paths = toPath(path); - const quotedColumn = this.isIdentifierQuoted(column) ? column : this.quoteIdentifier(column); - - paths = paths.map(subPath => { - return /\D/.test(subPath) ? this.addTicks(subPath, '"') : subPath; - }); - - const pathStr = this.escape( - ['$'] - .concat(paths) - .join('.') - .replaceAll(/\.(\d+)(?:(?=\.)|$)/g, (__, digit) => `[${digit}]`), - ); - const extractQuery = `json_value(${quotedColumn},${pathStr})`; - - return extractQuery; - } - - booleanValue(value) { - return value ? 1 : 0; - } - - quoteIdentifier(identifier, force = false) { - const optForceQuote = force; - const optQuoteIdentifiers = this.options.quoteIdentifiers !== false; - const regExp = /^(([\w][\w\d_]*))$/g; - - if ( - optForceQuote !== true && - optQuoteIdentifiers === false && - regExp.test(identifier) && - !ORACLE_RESERVED_WORDS.includes(identifier.toUpperCase()) - ) { - // In Oracle, if tables, attributes or alias are created double-quoted, - // they are always case sensitive. If they contain any lowercase - // characters, they must always be double-quoted otherwise it - // would get uppercased by the DB. - // Here, we strip quotes if we don't want case sensitivity. - return identifier; - } - - return quoteIdentifier(identifier, this.dialect.TICK_CHAR_LEFT, this.dialect.TICK_CHAR_RIGHT); - } - - /** - * It causes bindbyPosition like :1, :2, :3 - * We pass the val parameter so that the outBind indexes - * starts after the inBind indexes end - * - * @param {Array} bind - * @param {number} posOffset - */ - bindParam(bind, posOffset = 0) { - let i = Object.keys(bind).length; - - return value => { - const bindName = `sequelize_${++i}`; - bind[bindName] = value; - - return `:${Object.keys(bind).length + posOffset}`; - }; - } - - /** - * Returns the authenticate test query string - */ - authTestQuery() { - return 'SELECT 1+1 AS result FROM DUAL'; - } -} - -/* istanbul ignore next */ -function throwMethodUndefined(methodName) { - throw new Error(`The method "${methodName}" is not defined! Please add it to your sql dialect.`); -} diff --git a/packages/oracle/src/query-interface-typescript.internal.ts b/packages/oracle/src/query-interface-typescript.internal.ts deleted file mode 100644 index 912f4df55061..000000000000 --- a/packages/oracle/src/query-interface-typescript.internal.ts +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -import type { FetchDatabaseVersionOptions, QiDropAllTablesOptions } from '@sequelize/core'; -import { AbstractQueryInterface } from '@sequelize/core'; -import { AbstractQueryInterfaceInternal } from '@sequelize/core/_non-semver-use-at-your-own-risk_/abstract-dialect/query-interface-internal.js'; -import type { OracleDialect } from './dialect.js'; - -export class OracleQueryInterfaceTypescript< - Dialect extends OracleDialect = OracleDialect, -> extends AbstractQueryInterface { - readonly #internalQueryInterface: AbstractQueryInterfaceInternal; - - constructor(dialect: Dialect, internalQueryInterface?: AbstractQueryInterfaceInternal) { - internalQueryInterface ??= new AbstractQueryInterfaceInternal(dialect); - - super(dialect, internalQueryInterface); - this.#internalQueryInterface = internalQueryInterface; - } - - async fetchDatabaseVersion(options?: FetchDatabaseVersionOptions): Promise { - const payload = await this.#internalQueryInterface.fetchDatabaseVersionRaw<{ - VERSION_FULL: string; - }>(options); - - return payload.VERSION_FULL; - } - - async dropAllTables(options?: QiDropAllTablesOptions | undefined): Promise { - const skip = options?.skip || []; - const allTables = await this.listTables(options); - const tableNames = allTables.filter(tableName => !skip.includes(tableName.tableName)); - - const dropOptions = { ...options }; - // enable "cascade" by default if supported by this dialect - if (this.sequelize.dialect.supports.dropTable.cascade && dropOptions.cascade === undefined) { - dropOptions.cascade = true; - } - - // Drop all the tables loop to avoid deadlocks and timeouts - for (const tableName of tableNames) { - // eslint-disable-next-line no-await-in-loop - await this.dropTable(tableName, dropOptions); - } - } -} diff --git a/packages/oracle/src/query-interface.d.ts b/packages/oracle/src/query-interface.d.ts deleted file mode 100644 index ce2c71a80cb3..000000000000 --- a/packages/oracle/src/query-interface.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -import type { OracleDialect } from './dialect.js'; -import { OracleQueryInterfaceTypescript } from './query-interface-typescript.internal.ts'; - -export class OracleQueryInterface< - Dialect extends OracleDialect = OracleDialect, -> extends OracleQueryInterfaceTypescript {} diff --git a/packages/oracle/src/query-interface.js b/packages/oracle/src/query-interface.js deleted file mode 100644 index 50e106879b48..000000000000 --- a/packages/oracle/src/query-interface.js +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -import { QueryTypes } from '@sequelize/core'; -import { assertNoReservedBind } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/sql.js'; - -const intersection = require('lodash/intersection'); -const uniq = require('lodash/uniq'); -const { OracleQueryInterfaceTypescript } = require('./query-interface-typescript.internal'); - -export class OracleQueryInterface extends OracleQueryInterfaceTypescript { - async upsert(tableName, insertValues, updateValues, where, options) { - if (options.bind) { - assertNoReservedBind(options.bind); - } - - options = { ...options }; - - const model = options.model; - const primaryKeys = Object.values(model.primaryKeys).map(item => item.field); - const uniqueKeys = Object.values(model.uniqueKeys) - .filter(c => c.fields.length > 0) - .map(c => c.fields); - const indexKeys = Object.values(model.getIndexes()) - .filter(c => c.unique && c.fields.length > 0) - .map(c => c.fields); - - options.type = QueryTypes.UPSERT; - options.updateOnDuplicate = Object.keys(updateValues); - options.upsertKeys = []; - - // For fields in updateValues, try to find a constraint or unique index - // that includes given field. Only first matching upsert key is used. - for (const field of options.updateOnDuplicate) { - const uniqueKey = uniqueKeys.find(fields => fields.includes(field)); - if (uniqueKey) { - options.upsertKeys = uniqueKey; - break; - } - - const indexKey = indexKeys.find(fields => fields.includes(field)); - if (indexKey) { - options.upsertKeys = indexKey; - break; - } - } - - // Always use PK, if no constraint available OR update data contains PK - if ( - options.upsertKeys.length === 0 || - intersection(options.updateOnDuplicate, primaryKeys).length - ) { - options.upsertKeys = primaryKeys; - } - - options.upsertKeys = uniq(options.upsertKeys); - - let whereHasNull = false; - - primaryKeys.forEach(element => { - if (where[element] === null) { - whereHasNull = true; - } - }); - - if (whereHasNull === true) { - where = options.upsertKeys.reduce((result, attribute) => { - result[attribute] = insertValues[attribute]; - - return result; - }, {}); - } - - if (typeof tableName === 'object') { - tableName = tableName.tableName; - } - - const sql = this.queryGenerator.upsertQuery( - tableName, - insertValues, - updateValues, - where, - model, - options, - ); - // we need set this to undefined otherwise sequelize would raise an error - // Error: Both `sql.bind` and `options.bind` cannot be set at the same time - if (sql.bind) { - options.bind = undefined; - } - - return await this.sequelize.query(sql, options); - } -} diff --git a/packages/oracle/src/query.d.ts b/packages/oracle/src/query.d.ts deleted file mode 100644 index 97668d29ed21..000000000000 --- a/packages/oracle/src/query.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -import { AbstractQuery } from '@sequelize/core'; - -export class OracleQuery extends AbstractQuery {} diff --git a/packages/oracle/src/query.js b/packages/oracle/src/query.js deleted file mode 100644 index 75d366b867a2..000000000000 --- a/packages/oracle/src/query.js +++ /dev/null @@ -1,755 +0,0 @@ -// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved - -import { - AbstractQuery, - DatabaseError, - ForeignKeyConstraintError, - UniqueConstraintError, - UnknownConstraintError, - ValidationErrorItem, -} from '@sequelize/core'; -import { logger } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/logger.js'; -import { nameIndex } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/string.js'; -import extend from 'lodash/extend'; -import isPlainObject from 'lodash/isPlainObject'; -import mapKeys from 'lodash/mapKeys'; -import mapValues from 'lodash/mapValues'; -import reduce from 'lodash/reduce'; -import toPairs from 'lodash/toPairs'; - -const debug = logger.debugContext('sql:oracle'); - -export class OracleQuery extends AbstractQuery { - constructor(connection, sequelize, options) { - super(connection, sequelize, options); - this.options = extend( - { - // eslint-disable-next-line no-console - logging: console.log, - plain: false, - raw: false, - }, - options || {}, - ); - - this.checkLoggingOption(); - this.outFormat = options.outFormat || this.sequelize.dialect.connectionManager.lib.OBJECT; - } - - getInsertIdField() { - return 'id'; - } - - getExecOptions() { - const execOpts = { outFormat: this.outFormat, autoCommit: this.autoCommit }; - - // We set the oracledb - const oracledb = this.sequelize.dialect.connectionManager.lib; - - if (this.model && this.isSelectQuery()) { - const fInfo = {}; - const keys = Object.keys(this.model.tableAttributes); - for (const key of keys) { - const keyValue = this.model.tableAttributes[key]; - if (keyValue.type.getDataTypeId() === 'DECIMAL') { - fInfo[key] = { type: oracledb.STRING }; - } - - // Fetching BIGINT as string since, node-oracledb doesn't support JS BIGINT yet - if (keyValue.type.getDataTypeId() === 'BIGINT') { - fInfo[key] = { type: oracledb.STRING }; - } - } - - if (fInfo) { - execOpts.fetchInfo = fInfo; - } - } - - return execOpts; - } - - /** - * convert binding values for unsupported - * types in connector library - * - * @param {string} bindingDictionary a string representing the key to scan - * @param {object} oracledb native oracle library - * @private - */ - _convertBindAttributes(bindingDictionary, oracledb) { - if (this.model && this.options[bindingDictionary]) { - // check against model if we have some BIGINT - const keys = Object.keys(this.model.tableAttributes); - for (const key of keys) { - const keyValue = this.model.tableAttributes[key]; - if (keyValue.type.getDataTypeId() === 'BIGINT') { - const oldBinding = this.options[bindingDictionary][key]; - if (oldBinding) { - this.options[bindingDictionary][key] = { - ...oldBinding, - type: oracledb.STRING, - maxSize: 10_000_000, // TOTALLY ARBITRARY Number to prevent query failure - }; - } - } - } - } - } - - async run(sql, parameters) { - // We set the oracledb - const oracledb = this.sequelize.dialect.connectionManager.lib; - const complete = this._logQuery(sql, debug, parameters); - const outParameters = []; - const bindParameters = []; - const bindDef = []; - - // eslint-disable-next-line unicorn/prefer-regexp-test - if (!sql.match(/END;$/)) { - this.sql = sql.replace(/; *$/, ''); - } else { - this.sql = sql; - } - - // When this.options.bindAttributes exists then it is an insertQuery/upsertQuery - // So we insert the return bind direction and type - if ( - this.options.outBindAttributes && - (Array.isArray(parameters) || isPlainObject(parameters)) - ) { - this._convertBindAttributes('outBindAttributes', oracledb); - outParameters.push(...Object.values(this.options.outBindAttributes)); - // For upsertQuery we need to push the bindDef for isUpdate - if (this.isUpsertQuery()) { - outParameters.push({ dir: oracledb.BIND_OUT }); - } - } - - this.bindParameters = outParameters; - // construct input binds from parameters for single row insert execute call - // ex: [3, 4,...] - if (Array.isArray(parameters) || isPlainObject(parameters)) { - if (this.options.executeMany) { - // Constructing BindDefs for ExecuteMany call - // Building the bindDef for in and out binds - this._convertBindAttributes('inbindAttributes', oracledb); - bindDef.push(...Object.values(this.options.inbindAttributes)); - // eslint-disable-next-line unicorn/no-array-push-push - bindDef.push(...outParameters); - this.bindParameters = parameters; - } else { - Object.values(parameters).forEach(value => { - bindParameters.push(value); - }); - bindParameters.push(...outParameters); - Object.assign(this.bindParameters, bindParameters); - } - } - - // TRANSACTION SUPPORT - if (this.sql.startsWith('BEGIN TRANSACTION')) { - this.autocommit = false; - - // eslint-disable-next-line unicorn/no-useless-promise-resolve-reject - return Promise.resolve(); - } - - if (this.sql.startsWith('SET AUTOCOMMIT ON')) { - this.autocommit = true; - - // eslint-disable-next-line unicorn/no-useless-promise-resolve-reject - return Promise.resolve(); - } - - if (this.sql.startsWith('SET AUTOCOMMIT OFF')) { - this.autocommit = false; - - // eslint-disable-next-line unicorn/no-useless-promise-resolve-reject - return Promise.resolve(); - } - - if (this.sql.startsWith('DECLARE x NUMBER')) { - // Calling a stored procedure for bulkInsert with NO attributes, returns nothing - if (this.autoCommit === undefined) { - if (this.connection.uuid) { - this.autoCommit = false; - } else { - this.autoCommit = true; - } - } - - try { - await this.connection.execute(this.sql, this.bindParameters, { - autoCommit: this.autoCommit, - }); - - return Object.create(null); - } catch (error) { - throw this.formatError(error); - } finally { - complete(); - } - } - - if (this.sql.startsWith('BEGIN')) { - // Call to stored procedures - BEGIN TRANSACTION has been treated before - if (this.autoCommit === undefined) { - if (this.connection.uuid) { - this.autoCommit = false; - } else { - this.autoCommit = true; - } - } - - try { - const result = await this.connection.execute(this.sql, this.bindParameters, { - outFormat: this.outFormat, - autoCommit: this.autoCommit, - }); - if (!Array.isArray(result.outBinds)) { - return [result.outBinds]; - } - - return result.outBinds; - } catch (error) { - throw this.formatError(error); - } finally { - complete(); - } - } - - if (this.sql.startsWith('COMMIT TRANSACTION')) { - try { - await this.connection.commit(); - - return Object.create(null); - } catch (error) { - throw this.formatError(error); - } finally { - complete(); - } - } - - if (this.sql.startsWith('ROLLBACK TRANSACTION')) { - try { - await this.connection.rollback(); - - return Object.create(null); - } catch (error) { - throw this.formatError(error); - } finally { - complete(); - } - } - - if (this.sql.startsWith('SET TRANSACTION')) { - try { - await this.connection.execute(this.sql, [], { autoCommit: false }); - - return Object.create(null); - } catch (error) { - throw this.formatError(error); - } finally { - complete(); - } - } - - // QUERY SUPPORT - // As Oracle does everything in transaction, if autoCommit is not defined, we set it to true - if (this.autoCommit === undefined) { - if (this.connection.uuid) { - this.autoCommit = false; - } else { - this.autoCommit = true; - } - } - - // inbind parameters added byname. merge them - if ('inputParameters' in this.options && this.options.inputParameters !== null) { - Object.assign(this.bindParameters, this.options.inputParameters); - } - - const execOpts = this.getExecOptions(); - if (this.options.executeMany && bindDef.length > 0) { - execOpts.bindDefs = bindDef; - } - - const executePromise = this.options.executeMany - ? this.connection.executeMany(this.sql, this.bindParameters, execOpts) - : this.connection.execute(this.sql, this.bindParameters, execOpts); - try { - const result = await executePromise; - - return this.formatResults(result); - } catch (error) { - throw this.formatError(error); - } finally { - complete(); - } - } - - /** - * The parameters to query.run function are built here - * - * @param {string} sql - * @param {Array} values - * @param {string} dialect - */ - static formatBindParameters(sql, values, dialect) { - const replacementFunc = (match, key, values) => { - if (values[key] !== undefined) { - return `:${key}`; - } - - return undefined; - }; - - sql = AbstractQuery.formatBindParameters(sql, values, dialect, replacementFunc)[0]; - - return [sql, values]; - } - - /** - * Building the attribute map by matching the column names received - * from DB and the one in rawAttributes - * to sequelize format - * - * @param {object} attrsMap - * @param {object} rawAttributes - * @private - */ - _getAttributeMap(attrsMap, rawAttributes) { - attrsMap = Object.assign( - attrsMap, - reduce( - rawAttributes, - (mp, _, key) => { - const catalogKey = this.sequelize.queryInterface.queryGenerator.getCatalogName(key); - mp[catalogKey] = key; - - return mp; - }, - {}, - ), - ); - } - - /** - * Process rows received from the DB. - * Use parse function to parse the returned value - * to sequelize format - * - * @param {Array} rows - * @private - */ - _processRows(rows) { - let result = rows; - let attrsMap = {}; - - // When quoteIdentifiers is false we need to map the DB column names - // To the one in attribute list - if (this.sequelize.options.quoteIdentifiers === false) { - // Building the attribute map from this.options.attributes - // Needed in case of an aggregate function - attrsMap = reduce( - this.options.attributes, - (mp, v) => { - // Aggregate function is of form - // Fn {fn: 'min', min}, so we have the name in index one of the object - if (typeof v === 'object') { - v = v[1]; - } - - const catalogv = this.sequelize.queryInterface.queryGenerator.getCatalogName(v); - mp[catalogv] = v; - - return mp; - }, - {}, - ); - - // Building the attribute map by matching the column names received - // from DB and the one in model.rawAttributes - if (this.model) { - const modelDefinition = this.model.modelDefinition; - this._getAttributeMap(attrsMap, modelDefinition.rawAttributes); - } - - // If aliasesmapping exists we update the attribute map - if (this.options.aliasesMapping) { - const obj = Object.fromEntries(this.options.aliasesMapping); - rows = rows.map(row => - toPairs(row).reduce((acc, [key, value]) => { - const mapping = Object.values(obj).find(element => { - const catalogElement = - this.sequelize.queryInterface.queryGenerator.getCatalogName(element); - - return catalogElement === key; - }); - if (mapping) { - acc[mapping || key] = value; - } - - return acc; - }, {}), - ); - } - - // Modify the keys into the format that sequelize expects - result = rows.map(row => { - return mapKeys(row, (value, key) => { - const targetAttr = attrsMap[key]; - if (typeof targetAttr === 'string' && targetAttr !== key) { - return targetAttr; - } - - return key; - }); - }); - } - - // We parse the value received from the DB based on its datatype - if (this.model) { - const modelDefinition = this.model.modelDefinition; - result = result.map(row => { - return mapValues(row, (value, key) => { - if (modelDefinition.rawAttributes[key] && modelDefinition.rawAttributes[key].type) { - let typeid = modelDefinition.rawAttributes[key].type.toLocaleString(); - if (modelDefinition.rawAttributes[key].type.getDataTypeId() === 'JSON') { - value = JSON.parse(value); - } - - // For some types, the "name" of the type is returned with the length, we remove it - // For Boolean we skip this because BOOLEAN is mapped to CHAR(1) and we dont' want to - // remove the (1) for BOOLEAN - if ( - typeid.includes('(') && - modelDefinition.rawAttributes[key].type.getDataTypeId() !== 'BOOLEAN' - ) { - typeid = typeid.slice(0, typeid.indexOf('(')); - } - - const parser = this.sequelize.dialect.getParserForDatabaseDataType(typeid); - if ((value !== null) & parser) { - value = parser(value); - } - } - - return value; - }); - }); - } - - return result; - } - - /** - * High level function that handles the results of a query execution. - * Example: - * Oracle format : - * { rows: //All rows - [ [ 'Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production' ], - [ 'PL/SQL Release 11.2.0.1.0 - Production' ], - [ 'CORE\t11.2.0.1.0\tProduction' ], - [ 'TNS for 64-bit Windows: Version 11.2.0.1.0 - Production' ], - [ 'NLSRTL Version 11.2.0.1.0 - Production' ] ], - resultSet: undefined, - outBinds: undefined, //Used for dbms_put.line - rowsAffected: undefined, //Number of rows affected - metaData: [ { name: 'BANNER' } ] } - * - * @param {Array} data - The result of the query execution. - */ - formatResults(data) { - let result = this.instance; - if (this.isInsertQuery(data)) { - let insertData; - if (data.outBinds) { - const keys = Object.keys(this.options.outBindAttributes); - insertData = data.outBinds; - // For one row insert out bind array is 1D array - // we convert it to 2D array for uniformity - if (this.instance) { - insertData = [insertData]; - } - - // Mapping the bind parameter to their values - const res = insertData.map(row => { - const obj = {}; - row.forEach((element, index) => { - obj[keys[index]] = element[0]; - }); - - return obj; - }); - insertData = res; - // For bulk insert this.insert is undefined - // we map result to res, for one row insert - // result needs to be this.instance - if (!this.instance) { - result = res; - } - } - - this.handleInsertQuery(insertData); - - return [result, data.rowsAffected]; - } - - if (this.isDescribeQuery()) { - result = {}; - // Getting the table name on which we are doing describe query - const table = Object.keys(this.sequelize.models); - const modelAttributes = {}; - // Get the model raw attributes - if (this.sequelize.models && table.length > 0) { - this._getAttributeMap( - modelAttributes, - this.sequelize.models[table[0]].modelDefinition.rawAttributes, - ); - } - - data.rows.forEach(_result => { - if (_result.Default) { - _result.Default = _result.Default.replace(`('`, '') - .replace(`')`, '') - // eslint-disable-next-line unicorn/prefer-string-replace-all - .replace(/'/g, ''); /* jshint ignore: line */ - } - - // no need to add additional entries for column already in. - if (!(modelAttributes[_result.COLUMN_NAME] in result) && !(_result.COLUMN_NAME in result)) { - let key = modelAttributes[_result.COLUMN_NAME]; - if (!key) { - key = _result.COLUMN_NAME; - } - - result[key] = { - type: _result.DATA_TYPE.toUpperCase(), - // eslint-disable-next-line no-unneeded-ternary - allowNull: _result.NULLABLE === 'N' ? false : true, - defaultValue: undefined, - primaryKey: _result.CONSTRAINT_TYPE === 'P', - }; - } - }); - } else if (this.isShowIndexesQuery()) { - result = this.handleShowIndexesQuery(data.rows); - } else if (this.isSelectQuery()) { - const rows = data.rows; - const result = this._processRows(rows); - - return this.handleSelectQuery(result); - } else if (this.isCallQuery()) { - result = data.rows[0]; - } else if (this.isUpdateQuery()) { - result = [result, data.rowsAffected]; - } else if (this.isBulkUpdateQuery()) { - result = data.rowsAffected; - } else if (this.isDeleteQuery()) { - result = data.rowsAffected; - } else if (this.isUpsertQuery()) { - // Upsert Query, will return nothing - data = data.outBinds; - const keys = Object.keys(this.options.outBindAttributes); - const obj = {}; - for (const k in keys) { - obj[keys[k]] = data[k]; - } - - // eslint-disable-next-line unicorn/prefer-at - obj.isUpdate = data[data.length - 1]; - data = obj; - // eslint-disable-next-line eqeqeq - result = [{ isNewRecord: data.isUpdate, value: data }, data.isUpdate == 0]; - } else if (this.isShowConstraintsQuery()) { - result = this.handleShowConstraintsQuery(data); - } else if (this.isRawQuery()) { - // If data.rows exists then it is a select query - // Hence we would have two components - // metaData and rows and we return them - // as [data.rows, data.metaData] - // Else it is result of update/upsert/insert query - // and it has no rows so we return [data, data] - if (data && data.rows) { - return [data.rows, data.metaData]; - } - - return [data, data]; - } - - return result; - } - - handleShowConstraintsQuery(data) { - // Convert snake_case keys to camelCase as its generated by stored procedure - return data.rows.map(result => { - const constraint = {}; - for (const key in result) { - constraint[key] = result[key]; - } - - return constraint; - }); - } - - formatError(err) { - let match; - // ORA-00001: unique constraint (USER.XXXXXXX) violated - match = err.message.match(/unique constraint ([\s\S]*) violated/); - if (match && match.length > 1) { - match[1] = match[1].replace('(', '').replace(')', '').split('.')[1]; // As we get (SEQUELIZE.UNIQNAME), we replace to have UNIQNAME - const errors = []; - let fields = []; - let message = 'Validation error'; - let uniqueKey = null; - - if (this.model) { - const uniqueKeys = this.model.getIndexes(); - - uniqueKey = uniqueKeys.find(key => { - // We check directly AND with quotes -> "a"" === a || "a" === "a" - return ( - key.name.toUpperCase() === match[1].toUpperCase() || - key.name.toUpperCase() === `"${match[1].toUpperCase()}"` - ); - }); - - if (uniqueKey) { - fields = uniqueKey.fields; - } - - // eslint-disable-next-line no-implicit-coercion - if (uniqueKey && !!uniqueKey.msg) { - message = uniqueKey.msg; - } - - fields.forEach(field => { - errors.push( - new ValidationErrorItem( - this.getUniqueConstraintErrorMessage(field), - 'unique violation', - field, - null, - ), - ); - }); - } - - return new UniqueConstraintError({ - message, - errors, - cause: err, - fields, - }); - } - - // ORA-02291: integrity constraint (string.string) violated - parent key not found / ORA-02292: integrity constraint (string.string) violated - child record found - match = err.message.match(/ORA-02291/) || err.message.match(/ORA-02292/); - if (match && match.length > 0) { - return new ForeignKeyConstraintError({ - fields: null, - index: match[1], - cause: err, - }); - } - - // ORA-02443: Cannot drop constraint - nonexistent constraint - match = err.message.match(/ORA-02443/); - if (match && match.length > 0) { - return new UnknownConstraintError(match[1]); - } - - return new DatabaseError(err); - } - - isShowIndexesQuery() { - // eslint-disable-next-line unicorn/prefer-includes - return this.sql.indexOf('SELECT i.index_name,i.table_name, i.column_name, u.uniqueness') > -1; - } - - isSelectCountQuery() { - return this.sql.toUpperCase().includes('SELECT COUNT('); - } - - handleShowIndexesQuery(data) { - const acc = []; - - // We first treat the datas - data.forEach(indexRecord => { - // We create the object - if (!acc[indexRecord.INDEX_NAME]) { - acc[indexRecord.INDEX_NAME] = { - unique: indexRecord.UNIQUENESS === 'UNIQUE', - primary: indexRecord.CONSTRAINT_TYPE === 'P', - name: indexRecord.INDEX_NAME, - tableName: indexRecord.TABLE_NAME.toLowerCase(), - type: undefined, - }; - acc[indexRecord.INDEX_NAME].fields = []; - } - - // We create the fields - acc[indexRecord.INDEX_NAME].fields.push({ - name: indexRecord.COLUMN_NAME, - length: undefined, - order: indexRecord.DESCEND, - collate: undefined, - }); - }); - - const returnIndexes = []; - const accKeys = Object.keys(acc); - for (const accKey of accKeys) { - const columns = {}; - columns.fields = acc[accKey].fields; - columns.unique = acc[accKey].unique; - // We are generating index field name in the format sequelize expects - // to avoid creating a unique index on auto-generated index name - // eslint-disable-next-line unicorn/prefer-regexp-test - if (acc[accKey].name.match(/SYS_C[0-9]*/)) { - acc[accKey].name = nameIndex(columns, acc[accKey].tableName).name; - } - - // eslint-disable-next-line array-callback-return - acc[accKey].fields.map(field => { - field.attribute = field.name; - delete field.name; - }); - returnIndexes.push(acc[accKey]); - } - - return returnIndexes; - } - - handleInsertQuery(results, metaData) { - if (this.instance && results && results.length > 0) { - if ('pkReturnVal' in results[0]) { - // The PK of the table is a reserved word (ex : uuid), we have to change the name in the result for the model to find the value correctly - results[0][this.model.primaryKeyAttribute] = results[0].pkReturnVal; - delete results[0].pkReturnVal; - } - - // add the inserted row id to the instance - const modelDefinition = this.model.modelDefinition; - const autoIncrementField = modelDefinition.autoIncrementAttributeName; - let id = null; - let autoIncrementAlias = null; - - if ( - Object.hasOwn(modelDefinition.rawAttributes, autoIncrementField) && - modelDefinition.rawAttributes[autoIncrementField].field !== undefined - ) { - autoIncrementAlias = modelDefinition.rawAttributes[autoIncrementField].field; - } - - id = id || (results && results[0][this.getInsertIdField()]); - id = id || (metaData && metaData[this.getInsertIdField()]); - id = id || (results && results[0][autoIncrementField]); - id = id || (autoIncrementAlias && results && results[0][autoIncrementAlias]); - - this.instance[autoIncrementField] = id; - } - } -} diff --git a/packages/oracle/tsconfig.json b/packages/oracle/tsconfig.json deleted file mode 100644 index cfbb24587f8d..000000000000 --- a/packages/oracle/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig-preset.json", - "compilerOptions": { - "outDir": "./lib", - "rootDir": "./src" - }, - "include": ["./src/**/*.ts"] -} diff --git a/packages/oracle/typedoc.json b/packages/oracle/typedoc.json deleted file mode 100644 index a6500efb0151..000000000000 --- a/packages/oracle/typedoc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": ["../../typedoc.base.json"], - "entryPoints": ["src/index.ts"], - "excludeExternals": true -} diff --git a/packages/snowflake/package.json b/packages/snowflake/package.json index dfa61834ae86..a6e3cd11fa91 100644 --- a/packages/snowflake/package.json +++ b/packages/snowflake/package.json @@ -38,7 +38,7 @@ "dependencies": { "@sequelize/core": "workspace:*", "@sequelize/utils": "workspace:*", - "@types/snowflake-sdk": "1.6.23", + "@types/snowflake-sdk": "^1.6.23", "lodash": "^4.17.21", "snowflake-sdk": "^1.10.0" } diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md new file mode 100644 index 000000000000..ad4758077967 --- /dev/null +++ b/packages/utils/CHANGELOG.md @@ -0,0 +1,8 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [7.0.0-alpha.41](https://github.com/sequelize/sequelize/compare/v7.0.0-alpha.40...v7.0.0-alpha.41) (2024-05-17) + +**Note:** Version bump only for package @sequelize/utils diff --git a/packages/validator-js/CHANGELOG.md b/packages/validator-js/CHANGELOG.md new file mode 100644 index 000000000000..cb2f514a2f3a --- /dev/null +++ b/packages/validator-js/CHANGELOG.md @@ -0,0 +1,8 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [7.0.0-alpha.41](https://github.com/sequelize/sequelize/compare/v7.0.0-alpha.40...v7.0.0-alpha.41) (2024-05-17) + +**Note:** Version bump only for package @sequelize/validator.js diff --git a/test/esm-named-exports.test.js b/test/esm-named-exports.test.js index cd2ac968f305..f9aa4f3533e2 100644 --- a/test/esm-named-exports.test.js +++ b/test/esm-named-exports.test.js @@ -64,7 +64,6 @@ const ignoredCjsKeysMap = { '@sequelize/mariadb': ['__esModule'], '@sequelize/mssql': ['__esModule'], '@sequelize/mysql': ['__esModule'], - '@sequelize/oracle': ['__esModule'], '@sequelize/postgres': ['__esModule'], '@sequelize/snowflake': ['__esModule'], '@sequelize/sqlite3': ['__esModule'], diff --git a/yarn.lock b/yarn.lock index 86cfbddebb63..d1643979d6d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,6 +5,13 @@ __metadata: version: 8 cacheKey: 10c0 +"@aashutoshrathi/word-wrap@npm:^1.2.3": + version: 1.2.6 + resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" + checksum: 10c0/53c2b231a61a46792b39a0d43bc4f4f776bb4542aa57ee04930676802e5501282c2fc8aac14e4cd1f1120ff8b52616b6ff5ab539ad30aa2277d726444b71619f + languageName: node + linkType: hard + "@ampproject/remapping@npm:^2.2.0": version: 2.3.0 resolution: "@ampproject/remapping@npm:2.3.0" @@ -1130,28 +1137,28 @@ __metadata: linkType: hard "@azure/abort-controller@npm:^2.0.0": - version: 2.1.2 - resolution: "@azure/abort-controller@npm:2.1.2" + version: 2.1.1 + resolution: "@azure/abort-controller@npm:2.1.1" dependencies: tslib: "npm:^2.6.2" - checksum: 10c0/3771b6820e33ebb56e79c7c68e2288296b8c2529556fbd29cf4cf2fbff7776e7ce1120072972d8df9f1bf50e2c3224d71a7565362b589595563f710b8c3d7b79 + checksum: 10c0/9dd6a0b240646d76abe9a92641755cd1e7ed87ef8caf4a16d737fe588a2f26e9a42dd9e1f77da7d10e8c8489ebe17a50a75837226a69c1ae8be83bf20e624aa3 languageName: node linkType: hard "@azure/core-auth@npm:^1.3.0, @azure/core-auth@npm:^1.4.0, @azure/core-auth@npm:^1.5.0": - version: 1.7.2 - resolution: "@azure/core-auth@npm:1.7.2" + version: 1.7.1 + resolution: "@azure/core-auth@npm:1.7.1" dependencies: "@azure/abort-controller": "npm:^2.0.0" "@azure/core-util": "npm:^1.1.0" tslib: "npm:^2.6.2" - checksum: 10c0/2b4c489855308cea46363dc8f216eeb63cb85aea08f1ab7cff0a6e47604eed2b0fc46415d7f6d71da0aa7922b81c631920d05698eb14454b65be07825c5c599a + checksum: 10c0/34ea323097174495cd4cfc291cc39de7af53523a7fbc31b6fd3468c8dd47aa214734b4ddb540c70da8d693fc57629ed52337b5d770a940a97e9edb18f3d285a7 languageName: node linkType: hard "@azure/core-client@npm:^1.3.0, @azure/core-client@npm:^1.4.0, @azure/core-client@npm:^1.5.0": - version: 1.9.2 - resolution: "@azure/core-client@npm:1.9.2" + version: 1.9.1 + resolution: "@azure/core-client@npm:1.9.1" dependencies: "@azure/abort-controller": "npm:^2.0.0" "@azure/core-auth": "npm:^1.4.0" @@ -1160,18 +1167,18 @@ __metadata: "@azure/core-util": "npm:^1.6.1" "@azure/logger": "npm:^1.0.0" tslib: "npm:^2.6.2" - checksum: 10c0/4dab1f3b070f7c2c5a8390f81c7afdf31c030ad0599e75e16b9684959fb666cb57d34b63977639a60a7535f63f30a8a708210e8e48ff68a30732b7518044ebce + checksum: 10c0/da0c7b54e9447b73674e178527a126068ad56f8de95cffa95be297674edd10233bed865b725eae7aef34d8f7ed3ef82bc4806f931207bdc3c6982413aae53f2f languageName: node linkType: hard "@azure/core-http-compat@npm:^2.0.1": - version: 2.1.2 - resolution: "@azure/core-http-compat@npm:2.1.2" + version: 2.1.1 + resolution: "@azure/core-http-compat@npm:2.1.1" dependencies: "@azure/abort-controller": "npm:^2.0.0" "@azure/core-client": "npm:^1.3.0" "@azure/core-rest-pipeline": "npm:^1.3.0" - checksum: 10c0/e7b5374819d740c96c075956c756a753b7e9f6d7774bbadcc5000c3c4f808554e4d7146ccde7b94bcb21c39ed4a7e5b043b2a3b7d208b959310ea7e1440decca + checksum: 10c0/4a8f1845b223be9f44d94b52d08223ca9e0d4036a91492a27d0d3cbd1cb9f696df794dba1d58a7530c5926d5dbe51123e063e3c2e559d01313ee498ee3b07661 languageName: node linkType: hard @@ -1198,39 +1205,39 @@ __metadata: linkType: hard "@azure/core-lro@npm:^2.2.0": - version: 2.7.2 - resolution: "@azure/core-lro@npm:2.7.2" + version: 2.7.1 + resolution: "@azure/core-lro@npm:2.7.1" dependencies: "@azure/abort-controller": "npm:^2.0.0" "@azure/core-util": "npm:^1.2.0" "@azure/logger": "npm:^1.0.0" tslib: "npm:^2.6.2" - checksum: 10c0/bee809e47661b40021bbbedf88de54019715fdfcc95ac552b1d901719c29d78e293eeab51257b8f5155aac768eb4ea420715004d00d6e32109f5f97db5960d39 + checksum: 10c0/55ce51fa74fbbb8f702e5fda1ab3983d9575fc6188be34473f339c2096be203fbc4bc38cc1aacc75576a654bbc319ae198e316a12745f56bac12d0c20baa98ca languageName: node linkType: hard "@azure/core-paging@npm:^1.1.1": - version: 1.6.2 - resolution: "@azure/core-paging@npm:1.6.2" + version: 1.6.1 + resolution: "@azure/core-paging@npm:1.6.1" dependencies: tslib: "npm:^2.6.2" - checksum: 10c0/c727782f8dc66eff50c03421af2ca55f497f33e14ec845f5918d76661c57bc8e3a7ca9fa3d39181287bfbfa45f28cb3d18b67c31fd36bbe34146387dbd07b440 + checksum: 10c0/a68e6cf2ec324022dc60065b8916576b2f85b0a2b038a9a501a97b38a1977b6c8fcf1adef4db615910c442dcf75123dee1fb2c7cbfa42a9730fd26d89a3b9f67 languageName: node linkType: hard "@azure/core-rest-pipeline@npm:^1.1.0, @azure/core-rest-pipeline@npm:^1.3.0, @azure/core-rest-pipeline@npm:^1.8.1, @azure/core-rest-pipeline@npm:^1.9.1": - version: 1.16.0 - resolution: "@azure/core-rest-pipeline@npm:1.16.0" + version: 1.15.1 + resolution: "@azure/core-rest-pipeline@npm:1.15.1" dependencies: "@azure/abort-controller": "npm:^2.0.0" "@azure/core-auth": "npm:^1.4.0" "@azure/core-tracing": "npm:^1.0.1" - "@azure/core-util": "npm:^1.9.0" + "@azure/core-util": "npm:^1.3.0" "@azure/logger": "npm:^1.0.0" http-proxy-agent: "npm:^7.0.0" https-proxy-agent: "npm:^7.0.0" tslib: "npm:^2.6.2" - checksum: 10c0/9a798563eb1514e1eabaa9c072c3dc0d25ca837e94bf1e778431a749b3634d661866fe00ac0f49dd2938917001a241ea2de84ac6ea5179b5410b3a0807054a0b + checksum: 10c0/11994f2c5b041bfe72892a3086a8ba23ddf700cb293ce0e36d1cd41676e492b0dae8f3a19aadaa315008d49811bfbacf567b2f363916cabf26d473d2d7c07bf0 languageName: node linkType: hard @@ -1245,21 +1252,21 @@ __metadata: linkType: hard "@azure/core-tracing@npm:^1.0.0, @azure/core-tracing@npm:^1.0.1": - version: 1.1.2 - resolution: "@azure/core-tracing@npm:1.1.2" + version: 1.1.1 + resolution: "@azure/core-tracing@npm:1.1.1" dependencies: tslib: "npm:^2.6.2" - checksum: 10c0/0e844d581117ae81318a503ddfc143146b847ed9152d0c84f20fdc4cb0b2187a4e9da29aed13d5b7a201f39fe601a59c4db6455005ed8e0d3b5aab0ee77a56e1 + checksum: 10c0/e8c77e6acfe74965cd25389132c2b8009f48cb146e6ef1fe472923e6719dcb3575175af68f56dd38b78493dfc4264f5ea79a37e12cb7ebac3e93f090d4cb8ba2 languageName: node linkType: hard -"@azure/core-util@npm:^1.0.0, @azure/core-util@npm:^1.1.0, @azure/core-util@npm:^1.1.1, @azure/core-util@npm:^1.2.0, @azure/core-util@npm:^1.6.1, @azure/core-util@npm:^1.9.0": - version: 1.9.0 - resolution: "@azure/core-util@npm:1.9.0" +"@azure/core-util@npm:^1.0.0, @azure/core-util@npm:^1.1.0, @azure/core-util@npm:^1.1.1, @azure/core-util@npm:^1.2.0, @azure/core-util@npm:^1.3.0, @azure/core-util@npm:^1.6.1": + version: 1.8.1 + resolution: "@azure/core-util@npm:1.8.1" dependencies: "@azure/abort-controller": "npm:^2.0.0" tslib: "npm:^2.6.2" - checksum: 10c0/6eb6efc8b8401fd6e3b56631e8e9a1dbc23a0048ae3bf498d10163624f805032a7730905465b2ebe95c840e5e939e66bf320448de8df50f66346e89b1295f9e7 + checksum: 10c0/a321e2dc06788a62cce7ec1fc2967a60818145c737694ea27c8cd60df52b076fbc338baa8a76b70706c6f3658f7f4e92cbf821f91efadefcc9286b14f1f45f98 languageName: node linkType: hard @@ -1305,44 +1312,44 @@ __metadata: linkType: hard "@azure/logger@npm:^1.0.0": - version: 1.1.2 - resolution: "@azure/logger@npm:1.1.2" + version: 1.1.1 + resolution: "@azure/logger@npm:1.1.1" dependencies: tslib: "npm:^2.6.2" - checksum: 10c0/829c1da363b8fe732ca26326400575dc824e1032974dc499db539e9599e0e4f1b1f4bf936b68329171fece7e2d4bba3ffaaebb35ac60b73db4715c6dc026147a + checksum: 10c0/79014d78774b7a24c236a9c83550e9769c39cb6d4469c23ab35998dd1a67fed8fd43c947eb7382cdeab826747fa7fabc686a37e4aee67535cc6ce5e0302c9323 languageName: node linkType: hard "@azure/msal-browser@npm:^3.5.0": - version: 3.14.0 - resolution: "@azure/msal-browser@npm:3.14.0" + version: 3.11.1 + resolution: "@azure/msal-browser@npm:3.11.1" dependencies: - "@azure/msal-common": "npm:14.10.0" - checksum: 10c0/435c06bdd09b8c8d393b74d901cecda702f6ec962c79e3a5baa5706bd1144679008469cef2c35f6c8e17db0c125134f61dc106b519c67b5b6ae3158548abb165 + "@azure/msal-common": "npm:14.8.1" + checksum: 10c0/3588a45e28be299a799c96bfabe6fad9aebdf92c37b523e9ea32d1e7abca57b19fa2a657f80764724899491d31469003cd7b486f040dbd26ef9ad8bdd633e41d languageName: node linkType: hard -"@azure/msal-common@npm:14.10.0": - version: 14.10.0 - resolution: "@azure/msal-common@npm:14.10.0" - checksum: 10c0/532aa92665f7ec91e57e96606bf2342ac751bc1f3054a094b26e376669732e8f7c957a5c65d62e381daa3cb097e2990d7cf077080e2d50159884f5ad573157d4 +"@azure/msal-common@npm:14.8.1": + version: 14.8.1 + resolution: "@azure/msal-common@npm:14.8.1" + checksum: 10c0/979b3715c77fd050416b5b804d5c421e6bdbe1d94e750b32bc7855c7fec80e76f4f0bf51626624211487412fdd30e41748f390f58514e8ae6bd98ffe0fa2023e languageName: node linkType: hard "@azure/msal-node@npm:^2.5.1": - version: 2.8.1 - resolution: "@azure/msal-node@npm:2.8.1" + version: 2.6.6 + resolution: "@azure/msal-node@npm:2.6.6" dependencies: - "@azure/msal-common": "npm:14.10.0" + "@azure/msal-common": "npm:14.8.1" jsonwebtoken: "npm:^9.0.0" uuid: "npm:^8.3.0" - checksum: 10c0/69332453c0d08f69c885542384244784197c252a22b715aa77a6d26913b892fb3fbdd1dbd493450e49605aca1d8990f1f4a84a21ab72f7e89972902ab8a99ade + checksum: 10c0/b9178b3716c1977da4c1c64c3d565b413d602c297368142bc0d9bb38ade7eda9951e3777741f55c9eafa3530977efc115c632251fe94809c63d2b289c6791ae9 languageName: node linkType: hard "@azure/storage-blob@npm:^12.11.0": - version: 12.18.0 - resolution: "@azure/storage-blob@npm:12.18.0" + version: 12.17.0 + resolution: "@azure/storage-blob@npm:12.17.0" dependencies: "@azure/abort-controller": "npm:^1.0.0" "@azure/core-http": "npm:^3.0.0" @@ -1352,7 +1359,7 @@ __metadata: "@azure/logger": "npm:^1.0.0" events: "npm:^3.0.0" tslib: "npm:^2.2.0" - checksum: 10c0/0bd50e1516ac8a137c3737fbf32b73b188936ed80400526eca07c737d9c9ad790465a4462157e8cbb2dc2e459bcb328c4dd31f6a39631505ed85304d452ecf72 + checksum: 10c0/462e04cdfcbc891a32522ba2c6cf922c2621996255b5d436411bc4c55f7bcd86ca2693881cad32df718187f574a2799cb118672ebf92f3842be02813735737ac languageName: node linkType: hard @@ -1397,16 +1404,16 @@ __metadata: linkType: hard "@babel/eslint-parser@npm:^7.21.3": - version: 7.24.5 - resolution: "@babel/eslint-parser@npm:7.24.5" + version: 7.24.1 + resolution: "@babel/eslint-parser@npm:7.24.1" dependencies: "@nicolo-ribaudo/eslint-scope-5-internals": "npm:5.1.1-v1" eslint-visitor-keys: "npm:^2.1.0" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 - checksum: 10c0/bf8e89a00bd0895962c8c592b3f81a21186a9002bbbc57b0d6d9a72a8aeb087858222842f094479dd96f1783a5a1744ba9f1e907fdba60aa92f4775275550097 + eslint: ^7.5.0 || ^8.0.0 + checksum: 10c0/76b066be5245fa24ea5726bea24ceca75811599dce43db5e120e91283f3a27be150a2b0559a8472bec2824f6abc66fb29e90b3f1889c596ec855a811fc83dc90 languageName: node linkType: hard @@ -1560,11 +1567,11 @@ __metadata: linkType: hard "@babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2": - version: 7.24.5 - resolution: "@babel/runtime@npm:7.24.5" + version: 7.24.4 + resolution: "@babel/runtime@npm:7.24.4" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: 10c0/05730e43e8ba6550eae9fd4fb5e7d9d3cb91140379425abcb2a1ff9cebad518a280d82c4c4b0f57ada26a863106ac54a748d90c775790c0e2cd0ddd85ccdf346 + checksum: 10c0/785aff96a3aa8ff97f90958e1e8a7b1d47f793b204b47c6455eaadc3f694f48c97cd5c0a921fe3596d818e71f18106610a164fb0f1c71fd68c622a58269d537c languageName: node linkType: hard @@ -1848,7 +1855,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.6.1": +"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": version: 4.10.0 resolution: "@eslint-community/regexpp@npm:4.10.0" checksum: 10c0/c5f60ef1f1ea7649fa7af0e80a5a79f64b55a8a8fa5086de4727eb4c86c652aedee407a9c143b8995d2c0b2d75c1222bec9ba5d73dbfc1f314550554f0979ef4 @@ -1911,25 +1918,27 @@ __metadata: linkType: hard "@google-cloud/storage@npm:^7.7.0": - version: 7.11.0 - resolution: "@google-cloud/storage@npm:7.11.0" + version: 7.9.0 + resolution: "@google-cloud/storage@npm:7.9.0" dependencies: "@google-cloud/paginator": "npm:^5.0.0" "@google-cloud/projectify": "npm:^4.0.0" "@google-cloud/promisify": "npm:^4.0.0" abort-controller: "npm:^3.0.0" async-retry: "npm:^1.3.3" + compressible: "npm:^2.0.12" duplexify: "npm:^4.1.3" + ent: "npm:^2.2.0" fast-xml-parser: "npm:^4.3.0" gaxios: "npm:^6.0.2" google-auth-library: "npm:^9.6.3" - html-entities: "npm:^2.5.2" mime: "npm:^3.0.0" + mime-types: "npm:^2.0.8" p-limit: "npm:^3.0.1" retry-request: "npm:^7.0.0" teeny-request: "npm:^9.0.0" uuid: "npm:^8.0.0" - checksum: 10c0/4f9dfd18033256eff8ba69c6f9bdd77b251ecf40627d745cfc92d221460b2f657982cbb0892e869e5654ba040d4727b8c9556b5bf5003b5a281bccb3aa2e060a + checksum: 10c0/20d4acfb2104ca2e1b167e4cc43f1303fb006fd546b7e76962789d1636e06a659f46be6db64333c4bc073f27962970de72593321f3578dcf5d5e567a0bc0c0d8 languageName: node linkType: hard @@ -2295,39 +2304,39 @@ __metadata: linkType: hard "@npmcli/fs@npm:^3.1.0": - version: 3.1.1 - resolution: "@npmcli/fs@npm:3.1.1" + version: 3.1.0 + resolution: "@npmcli/fs@npm:3.1.0" dependencies: semver: "npm:^7.3.5" - checksum: 10c0/c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99 + checksum: 10c0/162b4a0b8705cd6f5c2470b851d1dc6cd228c86d2170e1769d738c1fbb69a87160901411c3c035331e9e99db72f1f1099a8b734bf1637cc32b9a5be1660e4e1e languageName: node linkType: hard "@npmcli/git@npm:^5.0.0": - version: 5.0.7 - resolution: "@npmcli/git@npm:5.0.7" + version: 5.0.4 + resolution: "@npmcli/git@npm:5.0.4" dependencies: "@npmcli/promise-spawn": "npm:^7.0.0" lru-cache: "npm:^10.0.1" npm-pick-manifest: "npm:^9.0.0" - proc-log: "npm:^4.0.0" + proc-log: "npm:^3.0.0" promise-inflight: "npm:^1.0.1" promise-retry: "npm:^2.0.1" semver: "npm:^7.3.5" which: "npm:^4.0.0" - checksum: 10c0/d9895fce3e554e927411ead941d434233585a3edaf8d2ebe3e8d48fdd14e2ce238d227248df30e3300b1c050e982459f4d0b18375bd3c17c4edeb0621da33ade + checksum: 10c0/e70aa4d980c356cc97cb3c5b24d3fe88e3b26672ace60ad2ff1a7d2a9f139143ebb32975380bd5ad798a3ba13c91faf76de9a85dd1e8f731797a5c963b61b35a languageName: node linkType: hard "@npmcli/installed-package-contents@npm:^2.0.1": - version: 2.1.0 - resolution: "@npmcli/installed-package-contents@npm:2.1.0" + version: 2.0.2 + resolution: "@npmcli/installed-package-contents@npm:2.0.2" dependencies: npm-bundled: "npm:^3.0.0" npm-normalize-package-bin: "npm:^3.0.0" bin: - installed-package-contents: bin/index.js - checksum: 10c0/f5ecba0d45fc762f3e0d5def29fbfabd5d55e8147b01ae0a101769245c2e0038bc82a167836513a98aaed0a15c3d81fcdb232056bb8a962972a432533e518fce + installed-package-contents: lib/index.js + checksum: 10c0/03efadb365997e3b54d1d1ea30ef3555729a68939ab2b7b7800a4a2750afb53da222f52be36bd7c44950434c3e26cbe7be28dac093efdf7b1bbe9e025ab62a07 languageName: node linkType: hard @@ -2349,26 +2358,26 @@ __metadata: linkType: hard "@npmcli/package-json@npm:^5.0.0": - version: 5.1.0 - resolution: "@npmcli/package-json@npm:5.1.0" + version: 5.0.0 + resolution: "@npmcli/package-json@npm:5.0.0" dependencies: "@npmcli/git": "npm:^5.0.0" glob: "npm:^10.2.2" hosted-git-info: "npm:^7.0.0" json-parse-even-better-errors: "npm:^3.0.0" normalize-package-data: "npm:^6.0.0" - proc-log: "npm:^4.0.0" + proc-log: "npm:^3.0.0" semver: "npm:^7.5.3" - checksum: 10c0/81bcac33276da86aae5ae62bfc70bfa6da1c1e1a7b0b9ecf3586279186f7c5d2e056ea7323b658f08999fe474e1ae0334df00cbdf48521e2489115f74e28f6af + checksum: 10c0/489b0e42d05c1c3c43ba94b6435c062ae28bee3e8ebf3b8e0977fe4ab8eb37fe6ab019203b38f39b54a592d85df2a602c0d700fc23adc630f4e7bfb0207a8a9e languageName: node linkType: hard "@npmcli/promise-spawn@npm:^7.0.0": - version: 7.0.2 - resolution: "@npmcli/promise-spawn@npm:7.0.2" + version: 7.0.1 + resolution: "@npmcli/promise-spawn@npm:7.0.1" dependencies: which: "npm:^4.0.0" - checksum: 10c0/8f2af5bc2c1b1ccfb9bcd91da8873ab4723616d8bd5af877c0daa40b1e2cbfa4afb79e052611284179cae918c945a1b99ae1c565d78a355bec1a461011e89f71 + checksum: 10c0/441024049170fc9dd0c793fef7366fd1b2a36c06f1036c52ac4a5d0f2d46deced89f2a94fef20f51aa9934edb4d611ff76b060be2b82086d29d2094ee1b46122 languageName: node linkType: hard @@ -2988,26 +2997,6 @@ __metadata: languageName: unknown linkType: soft -"@sequelize/oracle@workspace:packages/oracle": - version: 0.0.0-use.local - resolution: "@sequelize/oracle@workspace:packages/oracle" - dependencies: - "@sequelize/core": "workspace:*" - "@sequelize/utils": "workspace:*" - "@types/chai": "npm:4.3.14" - "@types/mocha": "npm:10.0.6" - "@types/oracledb": "npm:^6.3" - "@types/sinon": "npm:17.0.3" - chai: "npm:4.4.1" - dayjs: "npm:^1.11.10" - lodash: "npm:4.17.21" - mocha: "npm:10.4.0" - oracledb: "npm:6.5" - semver: "npm:7.6.0" - sinon: "npm:18.0.0" - languageName: unknown - linkType: soft - "@sequelize/postgres@workspace:packages/postgres": version: 0.0.0-use.local resolution: "@sequelize/postgres@workspace:packages/postgres" @@ -3035,7 +3024,7 @@ __metadata: dependencies: "@sequelize/core": "workspace:*" "@sequelize/utils": "workspace:*" - "@types/snowflake-sdk": "npm:1.6.23" + "@types/snowflake-sdk": "npm:^1.6.23" lodash: "npm:^4.17.21" snowflake-sdk: "npm:^1.10.0" languageName: unknown @@ -3091,12 +3080,12 @@ __metadata: languageName: node linkType: hard -"@sigstore/bundle@npm:^2.3.2": - version: 2.3.2 - resolution: "@sigstore/bundle@npm:2.3.2" +"@sigstore/bundle@npm:^2.3.0, @sigstore/bundle@npm:^2.3.1": + version: 2.3.1 + resolution: "@sigstore/bundle@npm:2.3.1" dependencies: - "@sigstore/protobuf-specs": "npm:^0.3.2" - checksum: 10c0/872a95928236bd9950a2ecc66af1c60a82f6b482a62a20d0f817392d568a60739a2432cad70449ac01e44e9eaf85822d6d9ebc6ade6cb3e79a7d62226622eb5d + "@sigstore/protobuf-specs": "npm:^0.3.1" + checksum: 10c0/f5cc08e6420055ca20c1fa458725cf3d090974c3650aacfb6ba0b09d9c59149e5f4d8c5bfe9f2253daf2c29548262e9e4ea83b4b2fc4abbaf93cf49ee2687f05 languageName: node linkType: hard @@ -3114,10 +3103,10 @@ __metadata: languageName: node linkType: hard -"@sigstore/protobuf-specs@npm:^0.3.2": - version: 0.3.2 - resolution: "@sigstore/protobuf-specs@npm:0.3.2" - checksum: 10c0/108eed419181ff599763f2d28ff5087e7bce9d045919de548677520179fe77fb2e2b7290216c93c7a01bdb2972b604bf44599273c991bbdf628fbe1b9b70aacb +"@sigstore/protobuf-specs@npm:^0.3.0, @sigstore/protobuf-specs@npm:^0.3.1": + version: 0.3.1 + resolution: "@sigstore/protobuf-specs@npm:0.3.1" + checksum: 10c0/bc926aeb472dcd1f99e887d54d9402e259e186ee2a15cdb395cdb565fdd3457f84a044ef355c96359c3c625127a93fb3c45c7e3bd2f16ac0912a58a6bf3fc137 languageName: node linkType: hard @@ -3132,17 +3121,15 @@ __metadata: languageName: node linkType: hard -"@sigstore/sign@npm:^2.3.2": - version: 2.3.2 - resolution: "@sigstore/sign@npm:2.3.2" +"@sigstore/sign@npm:^2.3.0": + version: 2.3.0 + resolution: "@sigstore/sign@npm:2.3.0" dependencies: - "@sigstore/bundle": "npm:^2.3.2" + "@sigstore/bundle": "npm:^2.3.0" "@sigstore/core": "npm:^1.0.0" - "@sigstore/protobuf-specs": "npm:^0.3.2" - make-fetch-happen: "npm:^13.0.1" - proc-log: "npm:^4.2.0" - promise-retry: "npm:^2.0.1" - checksum: 10c0/a1e7908f3e4898f04db4d713fa10ddb3ae4f851592c9b554f1269073211e1417528b5088ecee60f27039fde5a5426ae573481d77cfd7e4395d2a0ddfcf5f365f + "@sigstore/protobuf-specs": "npm:^0.3.1" + make-fetch-happen: "npm:^13.0.0" + checksum: 10c0/e11b9318c283604747e0ff6084e17f9da210dd999e8c5c32a229db6b9a9faf54698994458c2a09dec0a1a43ac99eb0d278ca6d5d86045145a96c941aad969e1d languageName: node linkType: hard @@ -3156,24 +3143,24 @@ __metadata: languageName: node linkType: hard -"@sigstore/tuf@npm:^2.3.4": - version: 2.3.4 - resolution: "@sigstore/tuf@npm:2.3.4" +"@sigstore/tuf@npm:^2.3.1": + version: 2.3.2 + resolution: "@sigstore/tuf@npm:2.3.2" dependencies: - "@sigstore/protobuf-specs": "npm:^0.3.2" - tuf-js: "npm:^2.2.1" - checksum: 10c0/97839882d787196517933df5505fae4634975807cc7adcd1783c7840c2a9729efb83ada47556ec326d544b9cb0d1851af990dc46eebb5fe7ea17bf7ce1fc0b8c + "@sigstore/protobuf-specs": "npm:^0.3.0" + tuf-js: "npm:^2.2.0" + checksum: 10c0/c05008fa46efec1546cc2cdb46e54d6a4773cbd05efa3ad7272339b4f935d58634b9f8494b109197b506116fb894206bf1cdb1fc09351a00297c23ef3c2a1a01 languageName: node linkType: hard -"@sigstore/verify@npm:^1.2.1": - version: 1.2.1 - resolution: "@sigstore/verify@npm:1.2.1" +"@sigstore/verify@npm:^1.2.0": + version: 1.2.0 + resolution: "@sigstore/verify@npm:1.2.0" dependencies: - "@sigstore/bundle": "npm:^2.3.2" + "@sigstore/bundle": "npm:^2.3.1" "@sigstore/core": "npm:^1.1.0" - "@sigstore/protobuf-specs": "npm:^0.3.2" - checksum: 10c0/af06580a8d5357c31259da1ac7323137054e0ac41e933278d95a4bc409a4463620125cb4c00b502f6bc32fdd68c2293019391b0d31ed921ee3852a9e84358628 + "@sigstore/protobuf-specs": "npm:^0.3.1" + checksum: 10c0/ed0d9cb8c71bde23bd48e40725e5b4bd3ff1595b6d9e4b1ed4f2dfd06f6bf76a3dc69d86f8b2e4488a9cb4ade0d9a41718bd33119b9afca66f90badd52a373fe languageName: node linkType: hard @@ -3959,13 +3946,13 @@ __metadata: languageName: node linkType: hard -"@tufjs/models@npm:2.0.1": - version: 2.0.1 - resolution: "@tufjs/models@npm:2.0.1" +"@tufjs/models@npm:2.0.0": + version: 2.0.0 + resolution: "@tufjs/models@npm:2.0.0" dependencies: "@tufjs/canonical-json": "npm:2.0.0" - minimatch: "npm:^9.0.4" - checksum: 10c0/ad9e82fd921954501fd90ed34ae062254637595577ad13fdc1e076405c0ea5ee7d8aebad09e63032972fd92b07f1786c15b24a195a171fc8ac470ca8e2ffbcc4 + minimatch: "npm:^9.0.3" + checksum: 10c0/252f525b05526077430920b30b125e197a3d711f4c6d1ceeee9cea5044035e4d94e57db481d96bd8e9d1ce5ee23fcc9fe989e7e0c9c2aec7e1edc27326ee16e6 languageName: node linkType: hard @@ -4001,13 +3988,6 @@ __metadata: languageName: node linkType: hard -"@types/chai@npm:4.3.14": - version: 4.3.14 - resolution: "@types/chai@npm:4.3.14" - checksum: 10c0/7712594c1e457cb99c7227d0fe1afcbb900bbd1369494ec2d2b0d79a383057a09ab13d23d7b300287394b99995a8c017aa55e6b9a369b77910bc10310ba504af - languageName: node - linkType: hard - "@types/cli-progress@npm:^3.11.5": version: 3.11.5 resolution: "@types/cli-progress@npm:3.11.5" @@ -4074,7 +4054,7 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.9": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db @@ -4158,15 +4138,6 @@ __metadata: languageName: node linkType: hard -"@types/oracledb@npm:^6.3": - version: 6.4.1 - resolution: "@types/oracledb@npm:6.4.1" - dependencies: - "@types/node": "npm:*" - checksum: 10c0/938aca4cb1a65db7fbb18b9aa2ac63f4fee18607d9e60dc38ad458d0cecd35c4dcde61f700060b951d257931b5e4b05f26eea5f1a19064678929a2361fff8a3e - languageName: node - linkType: hard - "@types/pg@npm:^8.11.4": version: 8.11.6 resolution: "@types/pg@npm:8.11.6" @@ -4179,12 +4150,12 @@ __metadata: linkType: hard "@types/readable-stream@npm:^4.0.0": - version: 4.0.14 - resolution: "@types/readable-stream@npm:4.0.14" + version: 4.0.11 + resolution: "@types/readable-stream@npm:4.0.11" dependencies: "@types/node": "npm:*" safe-buffer: "npm:~5.1.1" - checksum: 10c0/28dee6f7ce67c5068f9eb6d6f72c4aa49c58d01c96fa343dcf8561b98f59bad559cb4a3d231eeaaed31fdc2b82f42e7ed0a509efc56b25a9c70de514fc341e24 + checksum: 10c0/62242febee3fbd4ff019a413cdc57d90aa12094b818eebf6f9cdfe32098fcb794af33157660bde17970b7b26fbb466df98e3fb745840bfe7b8f7ad665fa53866 languageName: node linkType: hard @@ -4200,7 +4171,7 @@ __metadata: languageName: node linkType: hard -"@types/semver@npm:7.5.8, @types/semver@npm:^7.3.12": +"@types/semver@npm:7.5.8, @types/semver@npm:^7.3.12, @types/semver@npm:^7.5.0": version: 7.5.8 resolution: "@types/semver@npm:7.5.8" checksum: 10c0/8663ff927234d1c5fcc04b33062cb2b9fcfbe0f5f351ed26c4d1e1581657deebd506b41ff7fdf89e787e3d33ce05854bc01686379b89e9c49b564c4cfa988efa @@ -4233,7 +4204,7 @@ __metadata: languageName: node linkType: hard -"@types/snowflake-sdk@npm:1.6.23": +"@types/snowflake-sdk@npm:^1.6.23": version: 1.6.23 resolution: "@types/snowflake-sdk@npm:1.6.23" dependencies: @@ -4297,43 +4268,45 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^7.2.0": - version: 7.10.0 - resolution: "@typescript-eslint/eslint-plugin@npm:7.10.0" - dependencies: - "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:7.10.0" - "@typescript-eslint/type-utils": "npm:7.10.0" - "@typescript-eslint/utils": "npm:7.10.0" - "@typescript-eslint/visitor-keys": "npm:7.10.0" + version: 7.5.0 + resolution: "@typescript-eslint/eslint-plugin@npm:7.5.0" + dependencies: + "@eslint-community/regexpp": "npm:^4.5.1" + "@typescript-eslint/scope-manager": "npm:7.5.0" + "@typescript-eslint/type-utils": "npm:7.5.0" + "@typescript-eslint/utils": "npm:7.5.0" + "@typescript-eslint/visitor-keys": "npm:7.5.0" + debug: "npm:^4.3.4" graphemer: "npm:^1.4.0" - ignore: "npm:^5.3.1" + ignore: "npm:^5.2.4" natural-compare: "npm:^1.4.0" - ts-api-utils: "npm:^1.3.0" + semver: "npm:^7.5.4" + ts-api-utils: "npm:^1.0.1" peerDependencies: "@typescript-eslint/parser": ^7.0.0 eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/bf3f0118ea5961c3eb01894678246458a329d82dda9ac7c2f5bfe77896410d05a08a4655e533bcb1ed2a3132ba6421981ec8c2ed0a3545779d9603ea231947ae + checksum: 10c0/932a7b5a09c0138ef5a0bf00f8e6039fa209d4047092ffc187de048543c21f7ce24dc14f25f4c87b6f3bbb62335fc952e259e271fde88baf793217bde6460cfa languageName: node linkType: hard "@typescript-eslint/parser@npm:^7.2.0": - version: 7.10.0 - resolution: "@typescript-eslint/parser@npm:7.10.0" + version: 7.5.0 + resolution: "@typescript-eslint/parser@npm:7.5.0" dependencies: - "@typescript-eslint/scope-manager": "npm:7.10.0" - "@typescript-eslint/types": "npm:7.10.0" - "@typescript-eslint/typescript-estree": "npm:7.10.0" - "@typescript-eslint/visitor-keys": "npm:7.10.0" + "@typescript-eslint/scope-manager": "npm:7.5.0" + "@typescript-eslint/types": "npm:7.5.0" + "@typescript-eslint/typescript-estree": "npm:7.5.0" + "@typescript-eslint/visitor-keys": "npm:7.5.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/4c4fbf43b5b05d75b766acb803d3dd078c6e080641a77f9e48ba005713466738ea4a71f0564fa3ce520988d65158d14c8c952ba01ccbc431ab4a05935db5ce6d + checksum: 10c0/65521202ff024e79594272fbb7e4731ecf9d2fdd2f58fc81450bfd2bca94ce9c17b0eadd7338c01701f5cf16d38b6c025ed3fc322380b1e4b5424b7484098cda languageName: node linkType: hard @@ -4347,30 +4320,30 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:7.10.0": - version: 7.10.0 - resolution: "@typescript-eslint/scope-manager@npm:7.10.0" +"@typescript-eslint/scope-manager@npm:7.5.0": + version: 7.5.0 + resolution: "@typescript-eslint/scope-manager@npm:7.5.0" dependencies: - "@typescript-eslint/types": "npm:7.10.0" - "@typescript-eslint/visitor-keys": "npm:7.10.0" - checksum: 10c0/1d4f7ee137b95bd423b5a1b0d03251202dfc19bd8b6adfa5ff5df25fd5aa30e2d8ca50ab0d8d2e92441670ecbc2a82b3c2dbe39a4f268ec1ee1c1e267f7fd1d1 + "@typescript-eslint/types": "npm:7.5.0" + "@typescript-eslint/visitor-keys": "npm:7.5.0" + checksum: 10c0/a017b151a6b39ef591f8e2e65598e005e1b4b2d5494e4b91bddb5856b3a4d57dd8a58d2bc7a140e627eb574f93a2c8fe55f1307aa264c928ffd31d9e190bc5dd languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:7.10.0": - version: 7.10.0 - resolution: "@typescript-eslint/type-utils@npm:7.10.0" +"@typescript-eslint/type-utils@npm:7.5.0": + version: 7.5.0 + resolution: "@typescript-eslint/type-utils@npm:7.5.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:7.10.0" - "@typescript-eslint/utils": "npm:7.10.0" + "@typescript-eslint/typescript-estree": "npm:7.5.0" + "@typescript-eslint/utils": "npm:7.5.0" debug: "npm:^4.3.4" - ts-api-utils: "npm:^1.3.0" + ts-api-utils: "npm:^1.0.1" peerDependencies: eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/55e9a6690f9cedb79d30abb1990b161affaa2684dac246b743223353812c9c1e3fd2d923c67b193c6a3624a07e1c82c900ce7bf5b6b9891c846f04cb480ebd9f + checksum: 10c0/12915d4d1872638f5281e222a0d191676c478f250699c84864862e95a59e708222acefbf7ffdafc0872a007261219a3a2b1e667ff45eeafea7c4bcc5b955262c languageName: node linkType: hard @@ -4381,10 +4354,17 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:7.10.0, @typescript-eslint/types@npm:^7.2.0": - version: 7.10.0 - resolution: "@typescript-eslint/types@npm:7.10.0" - checksum: 10c0/f01d9330b93cc362ba7967ab5037396f64742076450e1f93139fa69cbe93a6ece3ed55d68ab780c9b7d07ef4a7c645da410305216a2cfc5dec7eba49ee65ab23 +"@typescript-eslint/types@npm:7.5.0": + version: 7.5.0 + resolution: "@typescript-eslint/types@npm:7.5.0" + checksum: 10c0/f3394f71f422dbd89f63b230f20e9769c12e47a287ff30ca03a80714e57ea21279b6f12a8ab14bafb00b59926f20a88894b2d1e72679f7ff298bae112679d4b3 + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:^7.2.0": + version: 7.8.0 + resolution: "@typescript-eslint/types@npm:7.8.0" + checksum: 10c0/b2fdbfc21957bfa46f7d8809b607ad8c8b67c51821d899064d09392edc12f28b2318a044f0cd5d523d782e84e8f0558778877944964cf38e139f88790cf9d466 languageName: node linkType: hard @@ -4406,36 +4386,39 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:7.10.0": - version: 7.10.0 - resolution: "@typescript-eslint/typescript-estree@npm:7.10.0" +"@typescript-eslint/typescript-estree@npm:7.5.0": + version: 7.5.0 + resolution: "@typescript-eslint/typescript-estree@npm:7.5.0" dependencies: - "@typescript-eslint/types": "npm:7.10.0" - "@typescript-eslint/visitor-keys": "npm:7.10.0" + "@typescript-eslint/types": "npm:7.5.0" + "@typescript-eslint/visitor-keys": "npm:7.5.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" - minimatch: "npm:^9.0.4" - semver: "npm:^7.6.0" - ts-api-utils: "npm:^1.3.0" + minimatch: "npm:9.0.3" + semver: "npm:^7.5.4" + ts-api-utils: "npm:^1.0.1" peerDependenciesMeta: typescript: optional: true - checksum: 10c0/6200695834c566e52e2fa7331f1a05019f7815969d8c1e1e237b85a99664d36f41ccc16384eff3f8582a0ecb75f1cc315b56ee9283b818da37f24fa4d42f1d7a + checksum: 10c0/ea3a270c725d6be273188b86110e0393052cd64d1c54a56eb5ea405e6d3fbbe84fb3b1ce1b8496a4078ac1eefd37aedcf12be91876764f6de31d5aa5131c7bcd languageName: node linkType: hard -"@typescript-eslint/utils@npm:7.10.0": - version: 7.10.0 - resolution: "@typescript-eslint/utils@npm:7.10.0" +"@typescript-eslint/utils@npm:7.5.0": + version: 7.5.0 + resolution: "@typescript-eslint/utils@npm:7.5.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:7.10.0" - "@typescript-eslint/types": "npm:7.10.0" - "@typescript-eslint/typescript-estree": "npm:7.10.0" + "@types/json-schema": "npm:^7.0.12" + "@types/semver": "npm:^7.5.0" + "@typescript-eslint/scope-manager": "npm:7.5.0" + "@typescript-eslint/types": "npm:7.5.0" + "@typescript-eslint/typescript-estree": "npm:7.5.0" + semver: "npm:^7.5.4" peerDependencies: eslint: ^8.56.0 - checksum: 10c0/6724471f94f2788f59748f7efa2a3a53ea910099993bee2fa5746ab5acacecdc9fcb110c568b18099ddc946ea44919ed394bff2bd055ba81fc69f5e6297b73bf + checksum: 10c0/c815ed6909769648953d6963c069038f7cac0c979051b25718feb30e0d3337b9647b75b8de00ac03fe960f0cc8dc4e8a81d4aac4719090a99785e0068712bd24 languageName: node linkType: hard @@ -4467,13 +4450,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:7.10.0": - version: 7.10.0 - resolution: "@typescript-eslint/visitor-keys@npm:7.10.0" +"@typescript-eslint/visitor-keys@npm:7.5.0": + version: 7.5.0 + resolution: "@typescript-eslint/visitor-keys@npm:7.5.0" dependencies: - "@typescript-eslint/types": "npm:7.10.0" - eslint-visitor-keys: "npm:^3.4.3" - checksum: 10c0/049e812bcd28869059d04c7bf3543bb55f5205f468b777439c4f120417fb856fb6024cb1d25291aa12556bd08e84f043a96d754ffb2cde37abb604d6f3c51634 + "@typescript-eslint/types": "npm:7.5.0" + eslint-visitor-keys: "npm:^3.4.1" + checksum: 10c0/eecf02b8dd54e83738a143aca87b902af4b357028a90fd34ed7a2f40a3ae2f6a188b9ba53903f23c80e868f1fffbb039e9ddb63525438d659707cc7bfb269317 languageName: node linkType: hard @@ -4589,9 +4572,9 @@ __metadata: linkType: hard "adm-zip@npm:^0.5.10": - version: 0.5.12 - resolution: "adm-zip@npm:0.5.12" - checksum: 10c0/fca2893b416bfcbee8b371a403f4d2e980a3c1055ce7b9b0b2ac8540c8efe6bbb27cc63ddf64ff6e6ed40c84fcb1ede7e95d230e7a567025e03f1044efbf6be0 + version: 0.5.10 + resolution: "adm-zip@npm:0.5.10" + checksum: 10c0/1f391a4e02940688b6ca6d4b3ea96cc82a9dbe1596671d7dbc052f9a53ed2efa6ba9ba253f032ea16e70081f22d6ddd1af2d65d6be700853cdee9c2fc925c20e languageName: node linkType: hard @@ -5099,13 +5082,13 @@ __metadata: linkType: hard "axios@npm:^1.6.0, axios@npm:^1.6.2, axios@npm:^1.6.8": - version: 1.7.1 - resolution: "axios@npm:1.7.1" + version: 1.6.8 + resolution: "axios@npm:1.6.8" dependencies: follow-redirects: "npm:^1.15.6" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: 10c0/554395472f18f4ddb43b4be2900473bc1a4d589464a8ab16f6954c53d9cace4317d5c9e009d5bb05f098d9565b2fa45f152a5d4cecb87536c8f0c370c25a7770 + checksum: 10c0/0f22da6f490335479a89878bc7d5a1419484fbb437b564a80c34888fc36759ae4f56ea28d55a191695e5ed327f0bad56e7ff60fb6770c14d1be6501505d47ab9 languageName: node linkType: hard @@ -5366,11 +5349,11 @@ __metadata: linkType: hard "builtins@npm:^5.0.0": - version: 5.1.0 - resolution: "builtins@npm:5.1.0" + version: 5.0.1 + resolution: "builtins@npm:5.0.1" dependencies: semver: "npm:^7.0.0" - checksum: 10c0/3c32fe5bd7ed4ff7dbd6fb14bcb9d7eaa7e967327f1899cd336f8625d3f46fceead0a53528f1e332aeaee757034ebb307cb2f1a37af2b86a3c5ad4845d01c0c8 + checksum: 10c0/9390a51a9abbc0233dac79c66715f927508b9d0c62cb7a42448fe8c52def60c707e6e9eb2cc4c9b7aba11601899935bca4e4064ae5e19c04c7e1bb9309e69134 languageName: node linkType: hard @@ -5428,8 +5411,8 @@ __metadata: linkType: hard "cacache@npm:^18.0.0": - version: 18.0.3 - resolution: "cacache@npm:18.0.3" + version: 18.0.2 + resolution: "cacache@npm:18.0.2" dependencies: "@npmcli/fs": "npm:^3.1.0" fs-minipass: "npm:^3.0.0" @@ -5443,7 +5426,7 @@ __metadata: ssri: "npm:^10.0.0" tar: "npm:^6.1.11" unique-filename: "npm:^3.0.0" - checksum: 10c0/dfda92840bb371fb66b88c087c61a74544363b37a265023223a99965b16a16bbb87661fe4948718d79df6e0cc04e85e62784fbcf1832b2a5e54ff4c46fbb45b7 + checksum: 10c0/7992665305cc251a984f4fdbab1449d50e88c635bc43bf2785530c61d239c61b349e5734461baa461caaee65f040ab14e2d58e694f479c0810cffd181ba5eabc languageName: node linkType: hard @@ -5537,9 +5520,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.30001587": - version: 1.0.30001620 - resolution: "caniuse-lite@npm:1.0.30001620" - checksum: 10c0/3783117143fbdc98c1b91a579d0f2a7bcee7008f322ba7a2bf56a6c3d105400772c7ed8026840b4ea909ec7bf254bcc36532f2ce1b1a1240b00d0335da39b7ec + version: 1.0.30001606 + resolution: "caniuse-lite@npm:1.0.30001606" + checksum: 10c0/fc9816f7d073e4f655c00acf9d6625f923e722430545b0aabefb9dc01347f3093608eb18841cf981acbd464fcac918a708908549738a8cd9517a14ac005bf8fc languageName: node linkType: hard @@ -5602,15 +5585,15 @@ __metadata: linkType: hard "chai@npm:>1.9.0": - version: 5.1.1 - resolution: "chai@npm:5.1.1" + version: 5.1.0 + resolution: "chai@npm:5.1.0" dependencies: assertion-error: "npm:^2.0.1" - check-error: "npm:^2.1.1" + check-error: "npm:^2.0.0" deep-eql: "npm:^5.0.1" loupe: "npm:^3.1.0" pathval: "npm:^2.0.0" - checksum: 10c0/e7f00e5881e3d5224f08fe63966ed6566bd9fdde175863c7c16dd5240416de9b34c4a0dd925f4fd64ad56256ca6507d32cf6131c49e1db65c62578eb31d4566c + checksum: 10c0/15ff6799051f5e0080440297451f1ef47164b4e825105c8df75100a24d60e0aea24455cff7287afbff091ba7bedc6b42e12d6f0f8bfb5b47cc1bdb446336bba0 languageName: node linkType: hard @@ -5688,10 +5671,10 @@ __metadata: languageName: node linkType: hard -"check-error@npm:^2.1.1": - version: 2.1.1 - resolution: "check-error@npm:2.1.1" - checksum: 10c0/979f13eccab306cf1785fa10941a590b4e7ea9916ea2a4f8c87f0316fc3eab07eabefb6e587424ef0f88cbcd3805791f172ea739863ca3d7ce2afc54641c7f0e +"check-error@npm:^2.0.0": + version: 2.0.0 + resolution: "check-error@npm:2.0.0" + checksum: 10c0/31149712894c000a55ca87198930344e2440e258fec6679bf13b0714f850b0c5131ce2b3cdb3119d18a5286fb503dcd7382062f9209e2eca30c34ab616b64e48 languageName: node linkType: hard @@ -6021,6 +6004,15 @@ __metadata: languageName: node linkType: hard +"compressible@npm:^2.0.12": + version: 2.0.18 + resolution: "compressible@npm:2.0.18" + dependencies: + mime-db: "npm:>= 1.43.0 < 2" + checksum: 10c0/8a03712bc9f5b9fe530cc5a79e164e665550d5171a64575d7dcf3e0395d7b4afa2d79ab176c61b5b596e28228b350dd07c1a2a6ead12fd81d1b6cd632af2fef7 + languageName: node + linkType: hard + "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -6492,7 +6484,7 @@ __metadata: languageName: node linkType: hard -"define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": +"define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -6715,9 +6707,9 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.4.668": - version: 1.4.776 - resolution: "electron-to-chromium@npm:1.4.776" - checksum: 10c0/6bec4c2d17058ffead3b769c908c05c735e2f96014c19d90472863cff03f23f16b60e25fbaf53ccec1e12999fba98eeed88fbcfdd5e347d5aff33ed06c27538e + version: 1.4.729 + resolution: "electron-to-chromium@npm:1.4.729" + checksum: 10c0/9f093b873a5e02da5fd5db5a1038c3a3f84bd43ff6d0e894280848717e5892953cc814a4ddf1de2acbfa9af4fe356c714f036f39b82d52bc6c8c3aed6e97fbde languageName: node linkType: hard @@ -6775,12 +6767,12 @@ __metadata: linkType: hard "enhanced-resolve@npm:^5.12.0": - version: 5.16.1 - resolution: "enhanced-resolve@npm:5.16.1" + version: 5.16.0 + resolution: "enhanced-resolve@npm:5.16.0" dependencies: graceful-fs: "npm:^4.2.4" tapable: "npm:^2.2.0" - checksum: 10c0/57d52625b978f18b32351a03006699de1e3695ce27af936ab4f1f98d3a4c825b219b445910bb4eef398303bbb5f37d7e382f842513d0f3a32614b78f6fd07ab7 + checksum: 10c0/dd69669cbb638ccacefd03e04d5e195ee6a99b7f5f8012f86d2df7781834de357923e06064ea621137c4ce0b37cc12b872b4e6d1ac6ab15fe98e7f1dfbbb08c4 languageName: node linkType: hard @@ -6793,6 +6785,13 @@ __metadata: languageName: node linkType: hard +"ent@npm:^2.2.0": + version: 2.2.0 + resolution: "ent@npm:2.2.0" + checksum: 10c0/d12c504d93afb8b22551323f78f60f0a2660289cf2de2210bdd2fdb07ac204956da23510a7711bf48079aa0aa726e21724224de6c6289120ddcf27652b30cb17 + languageName: node + linkType: hard + "entities@npm:^4.4.0": version: 4.5.0 resolution: "entities@npm:4.5.0" @@ -6832,7 +6831,7 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.1, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3": +"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.1, es-abstract@npm:^1.23.2": version: 1.23.3 resolution: "es-abstract@npm:1.23.3" dependencies: @@ -6903,12 +6902,12 @@ __metadata: linkType: hard "es-iterator-helpers@npm:^1.0.15, es-iterator-helpers@npm:^1.0.17": - version: 1.0.19 - resolution: "es-iterator-helpers@npm:1.0.19" + version: 1.0.18 + resolution: "es-iterator-helpers@npm:1.0.18" dependencies: call-bind: "npm:^1.0.7" define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.3" + es-abstract: "npm:^1.23.0" es-errors: "npm:^1.3.0" es-set-tostringtag: "npm:^2.0.3" function-bind: "npm:^1.1.2" @@ -6920,7 +6919,7 @@ __metadata: internal-slot: "npm:^1.0.7" iterator.prototype: "npm:^1.1.2" safe-array-concat: "npm:^1.1.2" - checksum: 10c0/ae8f0241e383b3d197383b9842c48def7fce0255fb6ed049311b686ce295595d9e389b466f6a1b7d4e7bb92d82f5e716d6fae55e20c1040249bf976743b038c5 + checksum: 10c0/93be402e01fa3d8bf62fcadd2fb3055126ffcfe8846911b10b85918ef46775252696c84e6191ec8125bedb61e92242ad1a54a86118436ba19814720cb9ff4aed languageName: node linkType: hard @@ -7048,7 +7047,7 @@ __metadata: languageName: node linkType: hard -"escalade@npm:^3.1.1, escalade@npm:^3.1.2": +"escalade@npm:^3.1.1": version: 3.1.2 resolution: "escalade@npm:3.1.2" checksum: 10c0/6b4adafecd0682f3aa1cd1106b8fff30e492c7015b178bc81b2d2f75106dabea6c6d6e8508fc491bd58e597c74abb0e8e2368f943ecb9393d4162e3c2f3cf287 @@ -7246,11 +7245,11 @@ __metadata: linkType: hard "eslint-plugin-react-hooks@npm:^4.6.0": - version: 4.6.2 - resolution: "eslint-plugin-react-hooks@npm:4.6.2" + version: 4.6.0 + resolution: "eslint-plugin-react-hooks@npm:4.6.0" peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - checksum: 10c0/4844e58c929bc05157fb70ba1e462e34f1f4abcbc8dd5bbe5b04513d33e2699effb8bca668297976ceea8e7ebee4e8fc29b9af9d131bcef52886feaa2308b2cc + checksum: 10c0/58c7e10ea5792c33346fcf5cb4024e14837035ce412ff99c2dcb7c4f903dc9b17939078f80bfef826301ce326582c396c00e8e0ac9d10ac2cde2b42d33763c65 languageName: node linkType: hard @@ -7294,13 +7293,13 @@ __metadata: linkType: hard "eslint-plugin-sort-destructure-keys@npm:^1.5.0": - version: 1.6.0 - resolution: "eslint-plugin-sort-destructure-keys@npm:1.6.0" + version: 1.5.0 + resolution: "eslint-plugin-sort-destructure-keys@npm:1.5.0" dependencies: natural-compare-lite: "npm:^1.4.0" peerDependencies: - eslint: 3 - 9 - checksum: 10c0/274702971da1d179c2066f9beaa59d883e08cb7fbc257ea5826e8ffbca79c22b0a23c198d35857ac6364426e654eee91d6bd494f6124898ce0687da28f43a122 + eslint: 3 - 8 + checksum: 10c0/1ab8ff259cca162344f09a47b6bdeccf03a6780771e70bd750c9a41a3f0ebb8935a631bd0712492fd49ba3e8a40c8016aec0aa525bd5b896dfef7461c6cdd335 languageName: node linkType: hard @@ -7675,8 +7674,8 @@ __metadata: linkType: hard "fancy-test@npm:^3.0.15": - version: 3.0.16 - resolution: "fancy-test@npm:3.0.16" + version: 3.0.15 + resolution: "fancy-test@npm:3.0.15" dependencies: "@types/chai": "npm:*" "@types/lodash": "npm:*" @@ -7687,7 +7686,7 @@ __metadata: nock: "npm:^13.5.4" sinon: "npm:^16.1.3" stdout-stderr: "npm:^0.1.9" - checksum: 10c0/7085ea303039ab41b6a28a9461d9d424b259df6082821d10d35f589807eb7ff7aec1d870c9c347a22b8ce9f5cc2bc5e443c820b68e93d3b2244f12bfe75d66a2 + checksum: 10c0/3cee0ec858f5f7ccf1ce1326c55993b1ef455145ce62a5a2bc2cf46f7cfce599b04395cbefbeb955e15c5237da83db2f7d2ce890825c5f50fbf58f0b065b92d0 languageName: node linkType: hard @@ -7746,13 +7745,13 @@ __metadata: linkType: hard "fast-xml-parser@npm:^4.2.5, fast-xml-parser@npm:^4.3.0": - version: 4.4.0 - resolution: "fast-xml-parser@npm:4.4.0" + version: 4.3.6 + resolution: "fast-xml-parser@npm:4.3.6" dependencies: strnum: "npm:^1.0.5" bin: fxparser: src/cli/cli.js - checksum: 10c0/ce32fad713471a40bea67959894168f297a5dd0aba64b89a2abc71a4fec0b1ae1d49c2dd8d8719ca8beeedf477824358c8a486b360b9f3ef12abc2e355d11318 + checksum: 10c0/9ebe2ac142c6978cae423c39c2a9b561edb76be584317d578768ed4a006a61fc0e83abf8c6fe31029139c4ad15ea1f2e7b6720ba9e6eda0e5266d7f2770fb079 languageName: node linkType: hard @@ -8165,15 +8164,15 @@ __metadata: linkType: hard "gaxios@npm:^6.0.0, gaxios@npm:^6.0.2, gaxios@npm:^6.1.1": - version: 6.6.0 - resolution: "gaxios@npm:6.6.0" + version: 6.4.0 + resolution: "gaxios@npm:6.4.0" dependencies: extend: "npm:^3.0.2" https-proxy-agent: "npm:^7.0.1" is-stream: "npm:^2.0.0" node-fetch: "npm:^2.6.9" uuid: "npm:^9.0.1" - checksum: 10c0/45ddf2e3664eed37d62e9467bb3cf81519057797c3169c7762f1be2917019d7a53ce4ff2091266afd29d05cd56e0f507b6862214b51c3fbe7730b9a6b79cb6a2 + checksum: 10c0/b9bd31daa7e223a177f1ae9ea69db2ebce06d5870cfedb3eee2a19e26c31d0b1b9172569d44f89e0d6394bf6fc5b1d061ae78612c94b90b2b5c7cf92a9e6dab3 languageName: node linkType: hard @@ -8312,11 +8311,11 @@ __metadata: linkType: hard "get-tsconfig@npm:^4.5.0": - version: 4.7.5 - resolution: "get-tsconfig@npm:4.7.5" + version: 4.7.3 + resolution: "get-tsconfig@npm:4.7.3" dependencies: resolve-pkg-maps: "npm:^1.0.0" - checksum: 10c0/a917dff2ba9ee187c41945736bf9bbab65de31ce5bc1effd76267be483a7340915cff232199406379f26517d2d0a4edcdbcda8cca599c2480a0f2cf1e1de3efa + checksum: 10c0/b15ca9d5d0887ebfccadc9fe88b6ff3827a5691ec90e7608a5e9c74bef959c14aba62f6bb88ac7f50322395731789a2cf654244f00e10f4f76349911b6846d6f languageName: node linkType: hard @@ -8502,12 +8501,11 @@ __metadata: linkType: hard "globalthis@npm:^1.0.3": - version: 1.0.4 - resolution: "globalthis@npm:1.0.4" + version: 1.0.3 + resolution: "globalthis@npm:1.0.3" dependencies: - define-properties: "npm:^1.2.1" - gopd: "npm:^1.0.1" - checksum: 10c0/9d156f313af79d80b1566b93e19285f481c591ad6d0d319b4be5e03750d004dde40a39a0f26f7e635f9007a3600802f53ecd85a759b86f109e80a5f705e01846 + define-properties: "npm:^1.1.3" + checksum: 10c0/0db6e9af102a5254630351557ac15e6909bc7459d3e3f6b001e59fe784c96d31108818f032d9095739355a88467459e6488ff16584ee6250cd8c27dec05af4b0 languageName: node linkType: hard @@ -8539,8 +8537,8 @@ __metadata: linkType: hard "google-auth-library@npm:^9.6.3": - version: 9.10.0 - resolution: "google-auth-library@npm:9.10.0" + version: 9.7.0 + resolution: "google-auth-library@npm:9.7.0" dependencies: base64-js: "npm:^1.3.0" ecdsa-sig-formatter: "npm:^1.0.11" @@ -8548,7 +8546,7 @@ __metadata: gcp-metadata: "npm:^6.1.0" gtoken: "npm:^7.0.0" jws: "npm:^4.0.0" - checksum: 10c0/21acad6dc712a0a935c3608b92d9aab80b05f1d4e0be5fb7efe5b2069a6453f2cee12867b5fb0a724c01a167ed3f5e4280e30740d2c1bff86f153b187205d4ed + checksum: 10c0/158e00b3a177038db2b28c3f69f835278f9bbe101327742aff284afa51f98721feaa14480eb0fea2da2c365820d0dc05528bd969ad45f37f4da6e3599bf2e16c languageName: node linkType: hard @@ -8771,18 +8769,11 @@ __metadata: linkType: hard "hosted-git-info@npm:^7.0.0": - version: 7.0.2 - resolution: "hosted-git-info@npm:7.0.2" + version: 7.0.1 + resolution: "hosted-git-info@npm:7.0.1" dependencies: lru-cache: "npm:^10.0.1" - checksum: 10c0/b19dbd92d3c0b4b0f1513cf79b0fc189f54d6af2129eeb201de2e9baaa711f1936929c848b866d9c8667a0f956f34bf4f07418c12be1ee9ca74fd9246335ca1f - languageName: node - linkType: hard - -"html-entities@npm:^2.5.2": - version: 2.5.2 - resolution: "html-entities@npm:2.5.2" - checksum: 10c0/f20ffb4326606245c439c231de40a7c560607f639bf40ffbfb36b4c70729fd95d7964209045f1a4e62fe17f2364cef3d6e49b02ea09016f207fde51c2211e481 + checksum: 10c0/361c4254f717f06d581a5a90aa0156a945e662e05ebbb533c1fa9935f10886d8247db48cbbcf9667f02e519e6479bf16dcdcf3124c3030e76c4c3ca2c88ee9d3 languageName: node linkType: hard @@ -8967,11 +8958,11 @@ __metadata: linkType: hard "ignore-walk@npm:^6.0.4": - version: 6.0.5 - resolution: "ignore-walk@npm:6.0.5" + version: 6.0.4 + resolution: "ignore-walk@npm:6.0.4" dependencies: minimatch: "npm:^9.0.0" - checksum: 10c0/8bd6d37c82400016c7b6538b03422dde8c9d7d3e99051c8357dd205d499d42828522fb4fbce219c9c21b4b069079445bacdc42bbd3e2e073b52856c2646d8a39 + checksum: 10c0/6dd2ea369f3d32d90cb26ca6647bc6e112ed483433270ed89b8055dd708d00777c2cbc85b93b43f53e2100851277fd1539796a758ae4c64b84445d4f1da5fd8f languageName: node linkType: hard @@ -8982,7 +8973,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.0.4, ignore@npm:^5.0.5, ignore@npm:^5.2.0, ignore@npm:^5.2.4, ignore@npm:^5.3.1, ignore@npm:~5.3.1": +"ignore@npm:^5.0.4, ignore@npm:^5.0.5, ignore@npm:^5.2.0, ignore@npm:^5.2.4, ignore@npm:~5.3.1": version: 5.3.1 resolution: "ignore@npm:5.3.1" checksum: 10c0/703f7f45ffb2a27fb2c5a8db0c32e7dee66b33a225d28e8db4e1be6474795f606686a6e3bcc50e1aa12f2042db4c9d4a7d60af3250511de74620fbed052ea4cd @@ -9755,8 +9746,8 @@ __metadata: linkType: hard "jake@npm:^10.8.5": - version: 10.9.1 - resolution: "jake@npm:10.9.1" + version: 10.8.7 + resolution: "jake@npm:10.8.7" dependencies: async: "npm:^3.2.3" chalk: "npm:^4.0.2" @@ -9764,7 +9755,7 @@ __metadata: minimatch: "npm:^3.1.2" bin: jake: bin/cli.js - checksum: 10c0/dda972431a926462f08fcf583ea8997884216a43daa5cce81cb42e7e661dc244f836c0a802fde23439c6e1fc59743d1c0be340aa726d3b17d77557611a5cd541 + checksum: 10c0/89326d01a8bc110d02d973729a66394c79a34b34461116f5c530a2a2dbc30265683fe6737928f75df9178e9d369ff1442f5753fb983d525e740eefdadc56a103 languageName: node linkType: hard @@ -9896,9 +9887,9 @@ __metadata: linkType: hard "json-parse-even-better-errors@npm:^3.0.0": - version: 3.0.2 - resolution: "json-parse-even-better-errors@npm:3.0.2" - checksum: 10c0/147f12b005768abe9fab78d2521ce2b7e1381a118413d634a40e6d907d7d10f5e9a05e47141e96d6853af7cc36d2c834d0a014251be48791e037ff2f13d2b94b + version: 3.0.1 + resolution: "json-parse-even-better-errors@npm:3.0.1" + checksum: 10c0/bc40600b14231dff1ff911d269c7ed89fbf3dbedf25cad3f47c10ff9cbb998ce03921372a17f27f3c7cfed76e679bc6c02a7b4cb2604b0ba68cd51ed16899492 languageName: node linkType: hard @@ -10528,11 +10519,11 @@ __metadata: linkType: hard "loupe@npm:^3.1.0": - version: 3.1.1 - resolution: "loupe@npm:3.1.1" + version: 3.1.0 + resolution: "loupe@npm:3.1.0" dependencies: get-func-name: "npm:^2.0.1" - checksum: 10c0/99f88badc47e894016df0c403de846fedfea61154aadabbf776c8428dd59e8d8378007135d385d737de32ae47980af07d22ba7bec5ef7beebd721de9baa0a0af + checksum: 10c0/8c2aebbabb732945092de4c2193a319f79c7a28aa70a20c1e1cd50568116c9a3b1a0a132277a1706d8742cd582be91119a85b5cdb443f1f97f1a375381fa22c7 languageName: node linkType: hard @@ -10553,9 +10544,9 @@ __metadata: linkType: hard "lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.2.2 - resolution: "lru-cache@npm:10.2.2" - checksum: 10c0/402d31094335851220d0b00985084288136136992979d0e015f0f1697e15d1c86052d7d53ae86b614e5b058425606efffc6969a31a091085d7a2b80a8a1e26d6 + version: 10.2.0 + resolution: "lru-cache@npm:10.2.0" + checksum: 10c0/c9847612aa2daaef102d30542a8d6d9b2c2bb36581c1bf0dc3ebf5e5f3352c772a749e604afae2e46873b930a9e9523743faac4e5b937c576ab29196774712ee languageName: node linkType: hard @@ -10656,9 +10647,9 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^13.0.0, make-fetch-happen@npm:^13.0.1": - version: 13.0.1 - resolution: "make-fetch-happen@npm:13.0.1" +"make-fetch-happen@npm:^13.0.0": + version: 13.0.0 + resolution: "make-fetch-happen@npm:13.0.0" dependencies: "@npmcli/agent": "npm:^2.0.0" cacache: "npm:^18.0.0" @@ -10669,10 +10660,9 @@ __metadata: minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" negotiator: "npm:^0.6.3" - proc-log: "npm:^4.2.0" promise-retry: "npm:^2.0.1" ssri: "npm:^10.0.0" - checksum: 10c0/df5f4dbb6d98153b751bccf4dc4cc500de85a96a9331db9805596c46aa9f99d9555983954e6c1266d9f981ae37a9e4647f42b9a4bb5466f867f4012e582c9e7e + checksum: 10c0/43b9f6dcbc6fe8b8604cb6396957c3698857a15ba4dbc38284f7f0e61f248300585ef1eb8cc62df54e9c724af977e45b5cdfd88320ef7f53e45070ed3488da55 languageName: node linkType: hard @@ -10840,14 +10830,14 @@ __metadata: languageName: node linkType: hard -"mime-db@npm:1.52.0": +"mime-db@npm:1.52.0, mime-db@npm:>= 1.43.0 < 2": version: 1.52.0 resolution: "mime-db@npm:1.52.0" checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa languageName: node linkType: hard -"mime-types@npm:^2.1.12, mime-types@npm:^2.1.29": +"mime-types@npm:^2.0.8, mime-types@npm:^2.1.12, mime-types@npm:^2.1.29": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -11022,8 +11012,8 @@ __metadata: linkType: hard "minipass-fetch@npm:^3.0.0": - version: 3.0.5 - resolution: "minipass-fetch@npm:3.0.5" + version: 3.0.4 + resolution: "minipass-fetch@npm:3.0.4" dependencies: encoding: "npm:^0.1.13" minipass: "npm:^7.0.3" @@ -11032,7 +11022,7 @@ __metadata: dependenciesMeta: encoding: optional: true - checksum: 10c0/9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b + checksum: 10c0/1b63c1f3313e88eeac4689f1b71c9f086598db9a189400e3ee960c32ed89e06737fa23976c9305c2d57464fb3fcdc12749d3378805c9d6176f5569b0d0ee8a75 languageName: node linkType: hard @@ -11380,11 +11370,11 @@ __metadata: linkType: hard "node-abi@npm:^3.3.0": - version: 3.62.0 - resolution: "node-abi@npm:3.62.0" + version: 3.57.0 + resolution: "node-abi@npm:3.57.0" dependencies: semver: "npm:^7.3.5" - checksum: 10c0/62e11264cbb51387cf4599b04e0418c7eba725afe3a228504ade957d61f579a5cb24df79dad9d338b9beb58d723643d40c9fcae2cfc2fe775c0ef56bb0fd0ec8 + checksum: 10c0/8d78542e39a3c49ac476d12c70ef0366f26a40a215af44498656e75fc85e5646309765a3277e1cbb2ec40283a9e86f7aefcdd699e30576c582f6bb931e6c802b languageName: node linkType: hard @@ -11516,13 +11506,13 @@ __metadata: linkType: hard "nopt@npm:^7.0.0": - version: 7.2.1 - resolution: "nopt@npm:7.2.1" + version: 7.2.0 + resolution: "nopt@npm:7.2.0" dependencies: abbrev: "npm:^2.0.0" bin: nopt: bin/nopt.js - checksum: 10c0/a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81 + checksum: 10c0/9bd7198df6f16eb29ff16892c77bcf7f0cc41f9fb5c26280ac0def2cf8cf319f3b821b3af83eba0e74c85807cc430a16efe0db58fe6ae1f41e69519f585b6aff languageName: node linkType: hard @@ -11598,11 +11588,11 @@ __metadata: linkType: hard "npm-bundled@npm:^3.0.0": - version: 3.0.1 - resolution: "npm-bundled@npm:3.0.1" + version: 3.0.0 + resolution: "npm-bundled@npm:3.0.0" dependencies: npm-normalize-package-bin: "npm:^3.0.0" - checksum: 10c0/7975590a50b7ce80dd9f3eddc87f7e990c758f2f2c4d9313dd67a9aca38f1a5ac0abe20d514b850902c441e89d2346adfc3c6f1e9cbab3ea28ebb653c4442440 + checksum: 10c0/65fcc621ba6e183be2715e3bbbf29d85e65e986965f06ee5e96a293d62dfad59ee57a9dcdd1c591eab156e03d58b3c35926b4211ce792d683458e15bb9f642c7 languageName: node linkType: hard @@ -11653,14 +11643,14 @@ __metadata: linkType: hard "npm-package-arg@npm:^11.0.0": - version: 11.0.2 - resolution: "npm-package-arg@npm:11.0.2" + version: 11.0.1 + resolution: "npm-package-arg@npm:11.0.1" dependencies: hosted-git-info: "npm:^7.0.0" - proc-log: "npm:^4.0.0" + proc-log: "npm:^3.0.0" semver: "npm:^7.3.5" validate-npm-package-name: "npm:^5.0.0" - checksum: 10c0/d730572e128980db45c97c184a454cb565283bf849484bf92e3b4e8ec2d08a21bd4b2cba9467466853add3e8c7d81e5de476904ac241f3ae63e6905dfc8196d4 + checksum: 10c0/f5bc4056ffe46497847fb31e349c834efe01d36d170926d1032443e183219d5e6ce75a49c1d398caf2236d3a69180597d255bff685c68d6a81f2eac96262b94d languageName: node linkType: hard @@ -11688,14 +11678,14 @@ __metadata: linkType: hard "npm-pick-manifest@npm:^9.0.0": - version: 9.0.1 - resolution: "npm-pick-manifest@npm:9.0.1" + version: 9.0.0 + resolution: "npm-pick-manifest@npm:9.0.0" dependencies: npm-install-checks: "npm:^6.0.0" npm-normalize-package-bin: "npm:^3.0.0" npm-package-arg: "npm:^11.0.0" semver: "npm:^7.3.5" - checksum: 10c0/c9b93a533b599bccba4f5d7ba313725d83a0058d981e8318176bfbb3a6c9435acd1a995847eaa3ffb45162161947db9b0674ceee13cfe716b345573ca1073d8e + checksum: 10c0/930859b70fb7b8cd8aee1c9819c2fbe95db5ae246398fbd6eaa819793675e36be97da2b4d19e1b56a913a016f7a0a33070cd3ed363ad522d5dbced9c0d94d037 languageName: node linkType: hard @@ -11715,8 +11705,8 @@ __metadata: linkType: hard "npm-registry-fetch@npm:^16.0.0": - version: 16.2.1 - resolution: "npm-registry-fetch@npm:16.2.1" + version: 16.2.0 + resolution: "npm-registry-fetch@npm:16.2.0" dependencies: "@npmcli/redact": "npm:^1.1.0" make-fetch-happen: "npm:^13.0.0" @@ -11725,8 +11715,8 @@ __metadata: minipass-json-stream: "npm:^1.0.1" minizlib: "npm:^2.1.2" npm-package-arg: "npm:^11.0.0" - proc-log: "npm:^4.0.0" - checksum: 10c0/bccffc291771d55056a6ebedb7aaf431cecc663286e060dc2936e8e0deee454a4a71654f772afcaa44f0d74a2c02403d8b45486a0aa2dd6d2bd8c09c9134eeb9 + proc-log: "npm:^3.0.0" + checksum: 10c0/7b149b2b680c40e36b1f644e3a45c91c05014b1c648012f1d8f85a8f160fec3bc9b8379a74c1a3e3d78ce7395b755144de03a2216f9e246e73b9e69e8d0b2e10 languageName: node linkType: hard @@ -12113,16 +12103,16 @@ __metadata: linkType: hard "optionator@npm:^0.9.3": - version: 0.9.4 - resolution: "optionator@npm:0.9.4" + version: 0.9.3 + resolution: "optionator@npm:0.9.3" dependencies: + "@aashutoshrathi/word-wrap": "npm:^1.2.3" deep-is: "npm:^0.1.3" fast-levenshtein: "npm:^2.0.6" levn: "npm:^0.4.1" prelude-ls: "npm:^1.2.1" type-check: "npm:^0.4.0" - word-wrap: "npm:^1.2.5" - checksum: 10c0/4afb687a059ee65b61df74dfe87d8d6815cd6883cb8b3d5883a910df72d0f5d029821f37025e4bccf4048873dbdb09acc6d303d27b8f76b1a80dd5a7d5334675 + checksum: 10c0/66fba794d425b5be51353035cf3167ce6cfa049059cbb93229b819167687e0f48d2bc4603fcb21b091c99acb516aae1083624675b15c4765b2e4693a085e959c languageName: node linkType: hard @@ -12159,13 +12149,6 @@ __metadata: languageName: node linkType: hard -"oracledb@npm:6.5": - version: 6.5.0 - resolution: "oracledb@npm:6.5.0" - checksum: 10c0/a524673026a5df5187de7e6891c4d583ad70b04abbc0c69ac65922670d65f7b2187150b8c1059b669cfbae0c21dc206790c2aab2fec1931ceeee195916ee4c38 - languageName: node - linkType: hard - "os-tmpdir@npm:~1.0.2": version: 1.0.2 resolution: "os-tmpdir@npm:1.0.2" @@ -12368,8 +12351,8 @@ __metadata: linkType: hard "pacote@npm:^17.0.5": - version: 17.0.7 - resolution: "pacote@npm:17.0.7" + version: 17.0.6 + resolution: "pacote@npm:17.0.6" dependencies: "@npmcli/git": "npm:^5.0.0" "@npmcli/installed-package-contents": "npm:^2.0.1" @@ -12382,7 +12365,7 @@ __metadata: npm-packlist: "npm:^8.0.0" npm-pick-manifest: "npm:^9.0.0" npm-registry-fetch: "npm:^16.0.0" - proc-log: "npm:^4.0.0" + proc-log: "npm:^3.0.0" promise-retry: "npm:^2.0.1" read-package-json: "npm:^7.0.0" read-package-json-fast: "npm:^3.0.0" @@ -12391,7 +12374,7 @@ __metadata: tar: "npm:^6.1.11" bin: pacote: lib/bin.js - checksum: 10c0/05730d3233918e4d89a4b9f8b436cddbe5081a4922c26c8af7d8f7db3adc79b211edd0e1ef2fd1c5b280811fd93a4486d76188fe75f3172a09d864f099d61066 + checksum: 10c0/d8fc116cb91d453d2a42493ea5ced3ff57dbfdb6e5b9b514f1d0465422e80042c69013fb4f77be5f27751185c6b174a40d8a53debdfb57cc4ba82a9650d970db languageName: node linkType: hard @@ -12551,9 +12534,9 @@ __metadata: linkType: hard "path-to-regexp@npm:^6.2.1": - version: 6.2.2 - resolution: "path-to-regexp@npm:6.2.2" - checksum: 10c0/4b60852d3501fd05ca9dd08c70033d73844e5eca14e41f499f069afa8364f780f15c5098002f93bd42af8b3514de62ac6e82a53b5662de881d2b08c9ef21ea6b + version: 6.2.1 + resolution: "path-to-regexp@npm:6.2.1" + checksum: 10c0/7a73811ca703e5c199e5b50b9649ab8f6f7b458a37f7dff9ea338815203f5b1f95fe8cb24d4fdfe2eab5d67ce43562d92534330babca35cdf3231f966adb9360 languageName: node linkType: hard @@ -12699,10 +12682,10 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1": - version: 1.0.1 - resolution: "picocolors@npm:1.0.1" - checksum: 10c0/c63cdad2bf812ef0d66c8db29583802355d4ca67b9285d846f390cc15c2f6ccb94e8cb7eb6a6e97fc5990a6d3ad4ae42d86c84d3146e667c739a4234ed50d400 +"picocolors@npm:^1.0.0": + version: 1.0.0 + resolution: "picocolors@npm:1.0.0" + checksum: 10c0/20a5b249e331c14479d94ec6817a182fd7a5680debae82705747b2db7ec50009a5f6648d0621c561b0572703f84dbef0858abcbd5856d3c5511426afcb1961f7 languageName: node linkType: hard @@ -12920,13 +12903,6 @@ __metadata: languageName: node linkType: hard -"proc-log@npm:^4.0.0, proc-log@npm:^4.2.0": - version: 4.2.0 - resolution: "proc-log@npm:4.2.0" - checksum: 10c0/17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9 - languageName: node - linkType: hard - "process-nextick-args@npm:~2.0.0": version: 2.0.1 resolution: "process-nextick-args@npm:2.0.1" @@ -12975,11 +12951,11 @@ __metadata: linkType: hard "promzard@npm:^1.0.0": - version: 1.0.2 - resolution: "promzard@npm:1.0.2" + version: 1.0.1 + resolution: "promzard@npm:1.0.1" dependencies: read: "npm:^3.0.1" - checksum: 10c0/d53c4ecb8b606b7e4bdeab14ac22c5f81a57463d29de1b8fe43bbc661106d9e4a79d07044bd3f69bde82c7ebacba7307db90a9699bc20482ce637bdea5fb8e4b + checksum: 10c0/8445442ff1ff71a2ac2d91ca6a0908631cf6573745298afe52283af23ec00c2dc6276ac4e75cd9bb521c126d33d268c5e5682c93eda492a5dcca8a76e0f671b3 languageName: node linkType: hard @@ -13124,9 +13100,9 @@ __metadata: linkType: hard "react-is@npm:^18.0.0": - version: 18.3.1 - resolution: "react-is@npm:18.3.1" - checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072 + version: 18.2.0 + resolution: "react-is@npm:18.2.0" + checksum: 10c0/6eb5e4b28028c23e2bfcf73371e72cd4162e4ac7ab445ddae2afe24e347a37d6dc22fae6e1748632cd43c6d4f9b8f86dcf26bf9275e1874f436d129952528ae0 languageName: node linkType: hard @@ -13160,14 +13136,14 @@ __metadata: linkType: hard "read-package-json@npm:^7.0.0": - version: 7.0.1 - resolution: "read-package-json@npm:7.0.1" + version: 7.0.0 + resolution: "read-package-json@npm:7.0.0" dependencies: glob: "npm:^10.2.2" json-parse-even-better-errors: "npm:^3.0.0" normalize-package-data: "npm:^6.0.0" npm-normalize-package-bin: "npm:^3.0.0" - checksum: 10c0/4bb2ad7dc6f460d0db04c5ef6ad7e9644d9566f07fa3563a938aedf0ee4b5ea0f0e2c5a321f79a73b34488ade0bd5937a7671ee3b453c42cd9d5e7e9b07c57f3 + checksum: 10c0/a2d373d0f87613fe86ec49c7e4bcdaf2a14967c258c6ccfd9585dec8b21e3d5bfe422c460648fb30e8c93fc13579da0d9c9c65adc5ec4e95ec888d99e4bccc79 languageName: node linkType: hard @@ -13723,17 +13699,6 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.6.0": - version: 7.6.0 - resolution: "semver@npm:7.6.0" - dependencies: - lru-cache: "npm:^6.0.0" - bin: - semver: bin/semver.js - checksum: 10c0/fbfe717094ace0aa8d6332d7ef5ce727259815bd8d8815700853f4faf23aacbd7192522f0dc5af6df52ef4fa85a355ebd2f5d39f554bd028200d6cf481ab9b53 - languageName: node - linkType: hard - "semver@npm:^6.0.0, semver@npm:^6.1.2, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" @@ -13921,16 +13886,16 @@ __metadata: linkType: hard "sigstore@npm:^2.2.0": - version: 2.3.1 - resolution: "sigstore@npm:2.3.1" + version: 2.3.0 + resolution: "sigstore@npm:2.3.0" dependencies: - "@sigstore/bundle": "npm:^2.3.2" + "@sigstore/bundle": "npm:^2.3.1" "@sigstore/core": "npm:^1.0.0" - "@sigstore/protobuf-specs": "npm:^0.3.2" - "@sigstore/sign": "npm:^2.3.2" - "@sigstore/tuf": "npm:^2.3.4" - "@sigstore/verify": "npm:^1.2.1" - checksum: 10c0/8906b1074130d430d707e46f15c66eb6996891dc0d068705f1884fb1251a4a367f437267d44102cdebcee34f1768b3f30131a2ec8fb7aac74ba250903a459aa7 + "@sigstore/protobuf-specs": "npm:^0.3.1" + "@sigstore/sign": "npm:^2.3.0" + "@sigstore/tuf": "npm:^2.3.1" + "@sigstore/verify": "npm:^1.2.0" + checksum: 10c0/13271fc0d0960a61994faf1a9c165429e74b09d090fb3f9dbe63b8c4ce5e275ade8abf5c72b738684888a8b87538ec2c4691d7a06c6023c0f2ff8f1aea104f2d languageName: node linkType: hard @@ -14162,12 +14127,12 @@ __metadata: linkType: hard "socks@npm:^2.6.2, socks@npm:^2.7.1": - version: 2.8.3 - resolution: "socks@npm:2.8.3" + version: 2.8.1 + resolution: "socks@npm:2.8.1" dependencies: ip-address: "npm:^9.0.5" smart-buffer: "npm:^4.2.0" - checksum: 10c0/d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7 + checksum: 10c0/ac77b515c260473cc7c4452f09b20939e22510ce3ae48385c516d1d5784374d5cc75be3cb18ff66cc985a7f4f2ef8fef84e984c5ec70aad58355ed59241f40a8 languageName: node linkType: hard @@ -14355,11 +14320,11 @@ __metadata: linkType: hard "ssri@npm:^10.0.0, ssri@npm:^10.0.1": - version: 10.0.6 - resolution: "ssri@npm:10.0.6" + version: 10.0.5 + resolution: "ssri@npm:10.0.5" dependencies: minipass: "npm:^7.0.3" - checksum: 10c0/e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227 + checksum: 10c0/b091f2ae92474183c7ac5ed3f9811457e1df23df7a7e70c9476eaa9a0c4a0c8fc190fb45acefbf023ca9ee864dd6754237a697dc52a0fb182afe65d8e77443d8 languageName: node linkType: hard @@ -14956,7 +14921,7 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^1.3.0": +"ts-api-utils@npm:^1.0.1": version: 1.3.0 resolution: "ts-api-utils@npm:1.3.0" peerDependencies: @@ -15062,14 +15027,14 @@ __metadata: languageName: node linkType: hard -"tuf-js@npm:^2.2.1": - version: 2.2.1 - resolution: "tuf-js@npm:2.2.1" +"tuf-js@npm:^2.2.0": + version: 2.2.0 + resolution: "tuf-js@npm:2.2.0" dependencies: - "@tufjs/models": "npm:2.0.1" + "@tufjs/models": "npm:2.0.0" debug: "npm:^4.3.4" - make-fetch-happen: "npm:^13.0.1" - checksum: 10c0/7c17b097571f001730d7be0aeaec6bec46ed2f25bf73990b1133c383d511a1ce65f831e5d6d78770940a85b67664576ff0e4c98e5421bab6d33ff36e4be500c8 + make-fetch-happen: "npm:^13.0.0" + checksum: 10c0/9a11793feed2aa798c1a50107a0f031034b4a670016684e0d0b7d97be3fff7f98f53783c30120bce795c16d58f1b951410bb673aae92cc2437d641cc7457e215 languageName: node linkType: hard @@ -15403,16 +15368,16 @@ __metadata: linkType: hard "update-browserslist-db@npm:^1.0.13": - version: 1.0.16 - resolution: "update-browserslist-db@npm:1.0.16" + version: 1.0.13 + resolution: "update-browserslist-db@npm:1.0.13" dependencies: - escalade: "npm:^3.1.2" - picocolors: "npm:^1.0.1" + escalade: "npm:^3.1.1" + picocolors: "npm:^1.0.0" peerDependencies: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 10c0/5995399fc202adbb51567e4810e146cdf7af630a92cc969365a099150cb00597e425cc14987ca7080b09a4d0cfd2a3de53fbe72eebff171aed7f9bb81f9bf405 + checksum: 10c0/e52b8b521c78ce1e0c775f356cd16a9c22c70d25f3e01180839c407a5dc787fb05a13f67560cbaf316770d26fa99f78f1acd711b1b54a4f35d4820d4ea7136e6 languageName: node linkType: hard @@ -15501,7 +15466,7 @@ __metadata: languageName: node linkType: hard -"validate-npm-package-name@npm:5.0.0": +"validate-npm-package-name@npm:5.0.0, validate-npm-package-name@npm:^5.0.0": version: 5.0.0 resolution: "validate-npm-package-name@npm:5.0.0" dependencies: @@ -15519,13 +15484,6 @@ __metadata: languageName: node linkType: hard -"validate-npm-package-name@npm:^5.0.0": - version: 5.0.1 - resolution: "validate-npm-package-name@npm:5.0.1" - checksum: 10c0/903e738f7387404bb72f7ac34e45d7010c877abd2803dc2d614612527927a40a6d024420033132e667b1bade94544b8a1f65c9431a4eb30d0ce0d80093cd1f74 - languageName: node - linkType: hard - "validator@npm:^13.11.0": version: 13.12.0 resolution: "validator@npm:13.12.0" @@ -15769,7 +15727,7 @@ __metadata: languageName: node linkType: hard -"word-wrap@npm:^1.2.5, word-wrap@npm:~1.2.3": +"word-wrap@npm:~1.2.3": version: 1.2.5 resolution: "word-wrap@npm:1.2.5" checksum: 10c0/e0e4a1ca27599c92a6ca4c32260e8a92e8a44f4ef6ef93f803f8ed823f486e0889fc0b93be4db59c8d51b3064951d25e43d434e95dc8c960cc3a63d65d00ba20