Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(oracle): add oracle dialect support #14638

Merged
merged 20 commits into from Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Expand Up @@ -47,6 +47,34 @@ jobs:
- run: yarn install --frozen-lockfile
- run: yarn add --dev typescript@~${{ matrix.ts-version }}
- run: yarn test-typings
test-oracle:
strategy:
fail-fast: false
matrix:
node-version: [10, 18]
name: Oracle DB (Node ${{ matrix.node-version }})
runs-on: ubuntu-latest
env:
DIALECT: oracle
SEQ_ORACLE_USER: sequelizetest
SEQ_ORACLE_PW: sequelizepassword
SEQ_ORACLE_DB: XEPDB1
SEQ_ORACLE_HOST: localhost
SEQ_ORACLE_PORT: 1521
LD_LIBRARY_PATH: ${{ github.workspace }}/.oracle/instantclient
UV_THREADPOOL_SIZE: 128
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: yarn install --frozen-lockfile --ignore-engines
- name: Install Local Oracle DB
run: yarn start-oracle
- name: Unit Tests
run: yarn test-unit
- name: Integration Tests
run: yarn test-integration
test-db2:
strategy:
fail-fast: false
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -16,3 +16,4 @@ esdoc
node_modules
/lib
/types
.oracle/
17 changes: 17 additions & 0 deletions dev/oracle/21-slim/docker-compose.yml
@@ -0,0 +1,17 @@
# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved

services:
oraclexedb:
container_name: oraclexedb
image: gvenzl/oracle-xe:21-slim
environment:
ORACLE_PASSWORD: password
ports:
- 1521:1521
healthcheck:
test: ["CMD-SHELL", "sqlplus", "system/password@XEPDB1"]
retries: 10

networks:
default:
name: sequelize-oraclexedb-network
27 changes: 27 additions & 0 deletions dev/oracle/21-slim/privileges.sql
@@ -0,0 +1,27 @@
-- Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved

create user sequelizetest identified by sequelizepassword;
grant connect to sequelizetest with admin option;
grant create session to sequelizetest with admin option;
grant grant any privilege to sequelizetest with admin option;
grant grant any role to sequelizetest with admin option;
grant create any table to sequelizetest with admin option;
grant insert any table to sequelizetest with admin option;
grant select any table to sequelizetest with admin option;
grant update any table to sequelizetest with admin option;
grant delete any table to sequelizetest with admin option;
grant drop any table to sequelizetest with admin option;
grant create view to sequelizetest with admin option;
grant create user to sequelizetest with admin option;
grant drop user to sequelizetest with admin option;
grant create any trigger to sequelizetest with admin option;
grant create any procedure to sequelizetest with admin option;
grant create any sequence to sequelizetest with admin option;
grant select any sequence to sequelizetest with admin option;
grant drop any sequence to sequelizetest with admin option;
grant create any synonym to sequelizetest with admin option;
grant create any index to sequelizetest with admin option;
grant alter user to sequelizetest with admin option;
grant alter any table to sequelizetest with admin option;
alter user sequelizetest quota unlimited on users;
exit;
61 changes: 61 additions & 0 deletions dev/oracle/21-slim/start.sh
@@ -0,0 +1,61 @@
# Copyright (c) 2022, 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

SEQ_WORKSPACE="$PWD"/../../../

if [[ ! -d "$SEQ_WORKSPACE"/.oracle/ ]]
then
mkdir "$SEQ_WORKSPACE"/.oracle/
if [[ $(uname) == 'Linux' ]]
then
wget https://download.oracle.com/otn_software/linux/instantclient/216000/instantclient-basic-linux.x64-21.6.0.0.0dbru.zip --no-check-certificate &&
unzip instantclient-basic-linux.x64-21.6.0.0.0dbru.zip -d "$SEQ_WORKSPACE"/.oracle/ &&
rm instantclient-basic-linux.x64-21.6.0.0.0dbru.zip &&
mv "$SEQ_WORKSPACE"/.oracle/instantclient_21_6 "$SEQ_WORKSPACE"/.oracle/instantclient

echo "Local Oracle instant client on Linux has been setup!"
elif [[ $(uname) == 'Darwin' ]]
then
if [[ ! -d ~/Downloads/instantclient_19_8 ]]
then
curl -O https://download.oracle.com/otn_software/mac/instantclient/198000/instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg &&
hdiutil mount instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg &&
/Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru/install_ic.sh &&
hdiutil unmount /Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru &&
rm instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg &&
mv ~/Downloads/instantclient_19_8/ "$SEQ_WORKSPACE"/.oracle/instantclient
else
cp -rf ~/Downloads/instantclient_19_8/ "$SEQ_WORKSPACE"/.oracle/instantclient
fi
ln -s "$SEQ_WORKSPACE"/.oracle/instantclient/libclntsh.dylib "$SEQ_WORKSPACE"/node_modules/oracledb/build/Release/

echo "Local Oracle instant client on macOS has been setup!"
else
# Windows
curl -O https://download.oracle.com/otn_software/nt/instantclient/216000/instantclient-basic-windows.x64-21.6.0.0.0dbru.zip &&
unzip instantclient-basic-windows.x64-21.6.0.0.0dbru.zip -d "$SEQ_WORKSPACE"/.oracle/ &&
rm instantclient-basic-windows.x64-21.6.0.0.0dbru.zip &&
mv "$SEQ_WORKSPACE"/.oracle/instantclient_21_6/* "$SEQ_WORKSPACE"/node_modules/oracledb/build/Release

echo "Local Oracle instant client on $(uname) has been setup!"
fi
fi
echo "Local Oracle DB is ready for use!"
10 changes: 10 additions & 0 deletions dev/oracle/21-slim/stop.sh
@@ -0,0 +1,10 @@
# Copyright (c) 2022, 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)."
21 changes: 21 additions & 0 deletions dev/oracle/21-slim/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
sdepold marked this conversation as resolved.
Show resolved Hide resolved
exit 0
fi
sleep 6
done

>&2 echo "Timeout of 5m exceeded when waiting for container to be healthy: $1"
exit 1
14 changes: 13 additions & 1 deletion package.json
Expand Up @@ -106,6 +106,7 @@
"mysql2": "^2.3.3",
"node-hook": "^1.0.0",
"nyc": "^15.1.0",
"oracledb": "^5.4.0",
WikiRik marked this conversation as resolved.
Show resolved Hide resolved
"p-map": "^4.0.0",
"p-props": "^4.0.0",
"p-settle": "^4.1.1",
Expand Down Expand Up @@ -147,6 +148,9 @@
},
"tedious": {
"optional": true
},
"oracledb": {
"optional": true
}
},
"keywords": [
Expand All @@ -160,6 +164,7 @@
"db2",
"ibm_db",
"sql",
"oracledb",
"sqlserver",
"snowflake",
"orm",
Expand Down Expand Up @@ -239,17 +244,20 @@
"start-postgres": "bash dev/postgres/10/start.sh",
"start-mssql": "bash dev/mssql/2019/start.sh",
"start-db2": "bash dev/db2/11.5/start.sh",
"start-oracle": "bash dev/oracle/21-slim/start.sh",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supposed to work on Apple Silicone?

host logs

[v6][~/Projects/sequelize]$ yarn start-oracle
yarn run v1.22.15
$ bash dev/oracle/21-slim/start.sh
++ dirname -- dev/oracle/21-slim/start.sh
+ cd -P -- dev/oracle/21-slim
+ docker-compose -p oraclexedb down --remove-orphans
Removing oraclexedb ... done
Removing network sequelize-oraclexedb-network
+ docker-compose -p oraclexedb up -d
Creating network "sequelize-oraclexedb-network" with the default driver
Creating oraclexedb ... done
+ ./wait-until-healthy.sh oraclexedb
oraclexedb is healthy!
+ docker cp privileges.sql oraclexedb:/opt/oracle/.
+ docker exec -t oraclexedb sqlplus system/password@XEPDB1 @privileges.sql
Error response from daemon: Container 76313f78c153efd601426ac8534d2ac45d2666fc200b0c2a78b0e212e7fc1111 is not running
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

container logs

The command completed successfully
ERROR:
ORA-12547: TNS:lost contact


SP2-0306: Invalid option.
Usage: CONN[ECT] [{logon|/|proxy} [AS {SYSDBA|SYSOPER|SYSASM|SYSBACKUP|SYSDG|SYSKM|SYSRAC}] [edition=value]]
where <logon> ::= <username>[/<password>][@<connect_identifier>]
      <proxy> ::= <proxyuser>[<username>][/<password>][@<connect_identifier>]
SP2-0306: Invalid option.
Usage: CONN[ECT] [{logon|/|proxy} [AS {SYSDBA|SYSOPER|SYSASM|SYSBACKUP|SYSDG|SYSKM|SYSRAC}] [edition=value]]
where <logon> ::= <username>[/<password>][@<connect_identifier>]
      <proxy> ::= <proxyuser>[<username>][/<password>][@<connect_identifier>]
SP2-0157: unable to CONNECT to ORACLE after 3 attempts, exiting SQL*Plus

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would only work on Apple Silicon under Rosetta because the Oracle Instant Client is not available on Apple Silicon due to some 3rd party libraries not being available.

"stop-mariadb": "bash dev/mariadb/10.3/stop.sh",
"stop-mysql": "bash dev/mysql/5.7/stop.sh",
"stop-mysql-8": "bash dev/mysql/8.0/stop.sh",
"stop-postgres": "bash dev/postgres/10/stop.sh",
"stop-mssql": "bash dev/mssql/2019/stop.sh",
"stop-db2": "bash dev/db2/11.5/stop.sh",
"stop-oracle": "bash dev/oracle/21-slim/stop.sh",
"restart-mariadb": "npm run start-mariadb",
"restart-mysql": "npm run start-mysql",
"restart-postgres": "npm run start-postgres",
"restart-mssql": "npm run start-mssql",
"restart-db2": "npm run start-db2",
"restart-oracle": "npm run start-oracle",
"----------------------------------------- local tests ---------------------------------------------": "",
"test-unit-mariadb": "cross-env DIALECT=mariadb npm run test-unit",
"test-unit-mysql": "cross-env DIALECT=mysql npm run test-unit",
Expand All @@ -259,7 +267,8 @@
"test-unit-mssql": "cross-env DIALECT=mssql npm run test-unit",
"test-unit-db2": "cross-env DIALECT=db2 npm run test-unit",
"test-unit-snowflake": "cross-env DIALECT=snowflake npm run test-unit",
"test-unit-all": "npm run test-unit-mariadb && npm run test-unit-mysql && npm run test-unit-postgres && npm run test-unit-postgres-native && npm run test-unit-mssql && npm run test-unit-sqlite && npm run test-unit-snowflake && npm run test-unit-db2",
"test-unit-oracle": "cross-env DIALECT=oracle npm run test-unit",
sdepold marked this conversation as resolved.
Show resolved Hide resolved
"test-unit-all": "npm run test-unit-mariadb && npm run test-unit-mysql && npm run test-unit-postgres && npm run test-unit-postgres-native && npm run test-unit-mssql && npm run test-unit-sqlite && npm run test-unit-snowflake && npm run test-unit-db2 && npm run test-unit-oracle",
"test-integration-mariadb": "cross-env DIALECT=mariadb npm run test-integration",
"test-integration-mysql": "cross-env DIALECT=mysql npm run test-integration",
"test-integration-postgres": "cross-env DIALECT=postgres npm run test-integration",
Expand All @@ -268,13 +277,15 @@
"test-integration-mssql": "cross-env DIALECT=mssql npm run test-integration",
"test-integration-db2": "cross-env DIALECT=db2 npm run test-integration",
"test-integration-snowflake": "cross-env DIALECT=snowflake npm run test-integration",
"test-integration-oracle": "cross-env LD_LIBRARY_PATH=\"$PWD/.oracle/instantclient/\" DIALECT=oracle UV_THREADPOOL_SIZE=128 npm run test-integration",
"test-mariadb": "cross-env DIALECT=mariadb npm test",
"test-mysql": "cross-env DIALECT=mysql npm test",
"test-sqlite": "cross-env DIALECT=sqlite npm test",
"test-postgres": "cross-env DIALECT=postgres npm test",
"test-postgres-native": "cross-env DIALECT=postgres-native npm test",
"test-mssql": "cross-env DIALECT=mssql npm test",
"test-db2": "cross-env DIALECT=db2 npm test",
"test-oracle": "cross-env LD_LIBRARY_PATH=\"$PWD/.oracle/instantclient/\" DIALECT=oracle UV_THREADPOOL_SIZE=128 npm test",
"----------------------------------------- development ---------------------------------------------": "",
"sscce": "node sscce.js",
"sscce-mariadb": "cross-env DIALECT=mariadb node sscce.js",
Expand All @@ -284,6 +295,7 @@
"sscce-sqlite": "cross-env DIALECT=sqlite node sscce.js",
"sscce-mssql": "cross-env DIALECT=mssql node sscce.js",
"sscce-db2": "cross-env DIALECT=db2 node sscce.js",
"sscce-oracle": "cross-env LD_LIBRARY_PATH=\"$PWD/.oracle/instantclient/\" DIALECT=oracle UV_THREADPOOL_SIZE=128 node sscce.js",
"prepare": "npm run build && husky install",
"build": "node ./build.js",
"---------------------------------------------------------------------------------------------------": ""
Expand Down
1 change: 1 addition & 0 deletions src/data-types.js
Expand Up @@ -1060,6 +1060,7 @@ dialectMap.sqlite = require('./dialects/sqlite/data-types')(DataTypes);
dialectMap.mssql = require('./dialects/mssql/data-types')(DataTypes);
dialectMap.db2 = require('./dialects/db2/data-types')(DataTypes);
dialectMap.snowflake = require('./dialects/snowflake/data-types')(DataTypes);
dialectMap.oracle = require('./dialects/oracle/data-types')(DataTypes);

const dialectList = Object.values(dialectMap);

Expand Down