Skip to content

Commit

Permalink
Merge branch 'v6' into v6
Browse files Browse the repository at this point in the history
  • Loading branch information
hjamil-24 committed Sep 29, 2022
2 parents 1ec0344 + 7203b66 commit 95cb979
Show file tree
Hide file tree
Showing 16 changed files with 164 additions and 31 deletions.
11 changes: 8 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ jobs:
strategy:
fail-fast: false
matrix:
oracle-version: [18, 21]
node-version: [10, 18]
name: Oracle DB (Node ${{ matrix.node-version }})
name: Oracle DB ${{ matrix.oracle-version }} (Node ${{ matrix.node-version }})
runs-on: ubuntu-latest
env:
DIALECT: oracle
Expand All @@ -69,8 +70,12 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- run: yarn install --frozen-lockfile --ignore-engines
- name: Install Local Oracle DB
run: yarn start-oracle
- if: matrix.oracle-version == '18'
name: Install Local Oracle DB 18
run: yarn start-oracle-oldest
- if: matrix.oracle-version == '21'
name: Install Local Oracle DB 21
run: yarn start-oracle-latest
- name: Unit Tests
run: yarn test-unit
- name: Integration Tests
Expand Down
17 changes: 17 additions & 0 deletions dev/oracle/18-slim/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright (c) 2022, 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
61 changes: 61 additions & 0 deletions dev/oracle/18-slim/start.sh
Original file line number Diff line number Diff line change
@@ -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/217000/instantclient-basic-linux.x64-21.7.0.0.0dbru.zip --no-check-certificate &&
unzip instantclient-basic-linux.x64-21.7.0.0.0dbru.zip -d "$SEQ_WORKSPACE"/.oracle/ &&
rm instantclient-basic-linux.x64-21.7.0.0.0dbru.zip &&
mv "$SEQ_WORKSPACE"/.oracle/instantclient_21_7 "$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/18-slim/stop.sh
Original file line number Diff line number Diff line change
@@ -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)."
12 changes: 6 additions & 6 deletions dev/oracle/21-slim/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ docker-compose -p oraclexedb down --remove-orphans
docker-compose -p oraclexedb up -d

# Wait until Oracle DB is set up and docker state is healthy
./wait-until-healthy.sh oraclexedb
./../wait-until-healthy.sh oraclexedb

# Moving privileges.sql to docker container
docker cp privileges.sql oraclexedb:/opt/oracle/.
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
Expand All @@ -26,10 +26,10 @@ 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
wget https://download.oracle.com/otn_software/linux/instantclient/217000/instantclient-basic-linux.x64-21.7.0.0.0dbru.zip --no-check-certificate &&
unzip instantclient-basic-linux.x64-21.7.0.0.0dbru.zip -d "$SEQ_WORKSPACE"/.oracle/ &&
rm instantclient-basic-linux.x64-21.7.0.0.0dbru.zip &&
mv "$SEQ_WORKSPACE"/.oracle/instantclient_21_7 "$SEQ_WORKSPACE"/.oracle/instantclient

echo "Local Oracle instant client on Linux has been setup!"
elif [[ $(uname) == 'Darwin' ]]
Expand Down
File renamed without changes.
File renamed without changes.
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
"mysql2": "^2.3.3",
"node-hook": "^1.0.0",
"nyc": "^15.1.0",
"oracledb": "^5.4.0",
"oracledb": "^5.5.0",
"p-map": "^4.0.0",
"p-props": "^4.0.0",
"p-settle": "^4.1.1",
Expand Down Expand Up @@ -244,20 +244,23 @@
"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",
"start-oracle-oldest": "bash dev/oracle/18-slim/start.sh",
"start-oracle-latest": "bash dev/oracle/21-slim/start.sh",
"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",
"stop-oracle-oldest": "bash dev/oracle/18-slim/stop.sh",
"stop-oracle-latest": "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",
"restart-oracle-oldest": "npm run start-oracle-oldest",
"restart-oracle-latest": "npm run start-oracle-latest",
"----------------------------------------- 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 Down
24 changes: 19 additions & 5 deletions src/dialects/abstract/query-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class QueryGenerator {
/**
* Helper method for populating the returning into bind information
* that is needed by some dialects (currently Oracle)
*
*
* @private
*/
populateInsertQueryReturnIntoBinds() {
Expand Down Expand Up @@ -1352,8 +1352,8 @@ class QueryGenerator {
} else {
// Ordering is handled by the subqueries, so ordering the UNION'ed result is not needed
groupedLimitOrder = options.order;
// For the Oracle dialect, the result of a select is a set, not a sequence, and so is the result of UNION.

// For the Oracle dialect, 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;
Expand Down Expand Up @@ -1612,7 +1612,7 @@ class QueryGenerator {
} else if (/json_extract\(/.test(attr)) {
prefix = attr.replace(/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)}.`);
prefix = attr.replace(/json_value\(/i, `json_value(${this.quoteIdentifier(includeAs.internalAs)}.`);
} else {
prefix = `${this.quoteIdentifier(includeAs.internalAs)}.${this.quoteIdentifier(attr)}`;
}
Expand Down Expand Up @@ -2135,7 +2135,21 @@ class QueryGenerator {
const field = model.rawAttributes[order[0]] ? model.rawAttributes[order[0]].field : order[0];
const subQueryAlias = this._getAliasForField(this.quoteIdentifier(model.name), field, options);

subQueryOrder.push(this.quote(subQueryAlias === null ? order : subQueryAlias, model, '->'));
let parent = null;
let orderToQuote = [];

// we need to ensure that the parent is null if we use the subquery alias, else we'll get an exception since
// "model_name"."alias" doesn't exist - only "alias" does. we also need to ensure that we preserve order direction
// by pushing order[1] to the subQueryOrder as well - in case it doesn't exist, we want to push "ASC"
if (subQueryAlias === null) {
orderToQuote = order;
parent = model;
} else {
orderToQuote = [subQueryAlias, order.length > 1 ? order[1] : 'ASC'];
parent = null;
}

subQueryOrder.push(this.quote(orderToQuote, parent, '->'));
}

// Handle case where renamed attributes are used to order by,
Expand Down
3 changes: 3 additions & 0 deletions src/dialects/oracle/connection-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const AbstractConnectionManager = require('../abstract/connection-manager');
const SequelizeErrors = require('../../errors');
const parserStore = require('../parserStore')('oracle');
const { logger } = require('../../utils/logger');
const semver = require('semver');
const debug = logger.debugContext('connection:oracle');
const DataTypes = require('../../data-types').oracle;
const { promisify } = require('util');
Expand Down Expand Up @@ -103,6 +104,8 @@ export class OracleConnectionManager extends AbstractConnectionManager {

try {
const connection = await this.lib.getConnection(connectionConfig);
// Setting the sequelize database version to Oracle DB server version to remove the roundtrip for DB version query
this.sequelize.options.databaseVersion = semver.coerce(connection.oracleServerVersionString).version;

debug('connection acquired');
connection.on('error', error => {
Expand Down
2 changes: 1 addition & 1 deletion src/dialects/oracle/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ OracleDialect.prototype.supports = _.merge(_.cloneDeep(AbstractDialect.prototype
GEOMETRY: false
});

OracleDialect.prototype.defaultVersion = '18.4.0';
OracleDialect.prototype.defaultVersion = '18.0.0';
OracleDialect.prototype.Query = OracleQuery;
OracleDialect.prototype.queryGenerator = OracleQueryGenerator;
OracleDialect.prototype.DataTypes = DataTypes;
Expand Down
4 changes: 2 additions & 2 deletions src/dialects/oracle/query-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export class OracleQueryGenerator extends AbstractQueryGenerator {
}

versionQuery() {
return "SELECT VERSION FROM PRODUCT_COMPONENT_VERSION WHERE PRODUCT LIKE 'Oracle%'";
return "SELECT VERSION_FULL FROM PRODUCT_COMPONENT_VERSION WHERE PRODUCT LIKE 'Oracle%'";
}

createTableQuery(tableName, attributes, options) {
Expand Down Expand Up @@ -342,7 +342,7 @@ export class OracleQueryGenerator extends AbstractQueryGenerator {
? `WHERE (atc.OWNER = ${this.escape(schema)}) `
: 'WHERE atc.OWNER = USER ',
`AND (atc.TABLE_NAME = ${this.escape(currTableName)})`,
'ORDER BY atc.COLUMN_NAME'
'ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC'
].join('');
}

Expand Down
2 changes: 1 addition & 1 deletion src/dialects/oracle/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ export class OracleQuery extends AbstractQuery {
} else if (this.isBulkDeleteQuery()) {
result = data.rowsAffected;
} else if (this.isVersionQuery()) {
const version = data.rows[0].VERSION;
const version = data.rows[0].VERSION_FULL;
if (version) {
const versions = version.split('.');
result = `${versions[0]}.${versions[1]}.${versions[2]}`;
Expand Down
23 changes: 18 additions & 5 deletions test/integration/dialects/postgres/query.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,22 +124,35 @@ if (dialect.match(/^postgres/)) {
await Foo.create({ name: 'record1' });
await Foo.create({ name: 'record2' });

const thisWorks = (await Foo.findAll({
const baseTest = (await Foo.findAll({
subQuery: false,
order: sequelizeMinifyAliases.literal('"Foo".my_name')
})).map(f => f.name);
expect(thisWorks[0]).to.equal('record1');
expect(baseTest[0]).to.equal('record1');

const thisShouldAlsoWork = (await Foo.findAll({
const orderByAscSubquery = (await Foo.findAll({
attributes: {
include: [
[sequelizeMinifyAliases.literal('"Foo".my_name'), 'customAttribute']
]
},
subQuery: true,
order: ['customAttribute']
order: [['customAttribute']],
limit: 1
})).map(f => f.name);
expect(thisShouldAlsoWork[0]).to.equal('record1');
expect(orderByAscSubquery[0]).to.equal('record1');

const orderByDescSubquery = (await Foo.findAll({
attributes: {
include: [
[sequelizeMinifyAliases.literal('"Foo".my_name'), 'customAttribute']
]
},
subQuery: true,
order: [['customAttribute', 'DESC']],
limit: 1
})).map(f => f.name);
expect(orderByDescSubquery[0]).to.equal('record2');
});

it('returns the minified aliased attributes', async () => {
Expand Down
7 changes: 7 additions & 0 deletions test/integration/json.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,13 @@ describe('model', () => {
});

it('should be able to store strings', async function() {
if (dialect === 'oracle') {
const dbVersion = this.sequelize.options.databaseVersion;
// Oracle DB below 21c doesn't recognize a string as a valid json
if (dbVersion.localeCompare('21.0.0.0') === -1) {
this.skip();
}
}
await this.User.create({ username: 'swen', emergency_contact: 'joe' });
const user = await this.User.findOne({ where: { username: 'swen' } });
expect(user.emergency_contact).to.equal('joe');
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6393,10 +6393,10 @@ optionator@^0.9.1:
type-check "^0.4.0"
word-wrap "^1.2.3"

oracledb@^5.4.0:
version "5.4.0"
resolved "https://registry.yarnpkg.com/oracledb/-/oracledb-5.4.0.tgz#0ae79faa9a3c04d39b845b897d1e58342d275a85"
integrity sha512-JirwPg+HobTV6EuXcHoHA0n55wJiWCNHaS2TRSHLSxOB9WbDyrT8q6E5PPB7nre1V/kFCd5luHkV1z780Voyfw==
oracledb@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/oracledb/-/oracledb-5.5.0.tgz#0cf9af5d0c0815f74849ae9ed56aee823514d71b"
integrity sha512-i5cPvMENpZP8nnqptB6l0pjiOyySj1IISkbM4Hr3yZEDdANo2eezarwZb9NQ8fTh5pRjmgpZdSyIbnn9N3AENw==

ordered-read-streams@^1.0.0:
version "1.0.1"
Expand Down

0 comments on commit 95cb979

Please sign in to comment.