mirror of
https://github.com/knex/knex.git
synced 2025-12-25 14:08:30 +00:00
Add support for dropForeign in SQLite (#4092)
Co-authored-by: Igor Savin <iselwin@gmail.com>
This commit is contained in:
parent
c47e00de64
commit
b7e1ffd7d5
@ -29,12 +29,15 @@ class Oracledb_Compiler extends Oracle_Compiler {
|
||||
insertValues.length === 1 &&
|
||||
isEmpty(insertValues[0])
|
||||
) {
|
||||
const returningFragment = this.single.returning
|
||||
? ' (' + this.formatter.wrap(this.single.returning) + ')'
|
||||
: '';
|
||||
|
||||
return this._addReturningToSqlAndConvert(
|
||||
'insert into ' +
|
||||
this.tableName +
|
||||
' (' +
|
||||
this.formatter.wrap(this.single.returning) +
|
||||
') values (default)',
|
||||
returningFragment +
|
||||
' values (default)',
|
||||
outBinding[0],
|
||||
this.tableName,
|
||||
returning
|
||||
|
||||
@ -309,6 +309,56 @@ assign(SQLite3_DDL.prototype, {
|
||||
);
|
||||
},
|
||||
|
||||
dropForeign: async function (columns, indexName) {
|
||||
return this.client.transaction(
|
||||
async (trx) => {
|
||||
this.trx = trx;
|
||||
|
||||
const sql = await this.getTableSql();
|
||||
|
||||
const createTable = sql[0];
|
||||
|
||||
const oneLineSql = createTable.sql.replace(/\s+/g, ' ');
|
||||
const matched = oneLineSql.match(/^CREATE TABLE\s+(\S+)\s*\((.*)\)/);
|
||||
|
||||
const defs = matched[2];
|
||||
|
||||
if (!defs) {
|
||||
throw new Error('No column definitions in this statement!');
|
||||
}
|
||||
|
||||
const updatedDefs = defs
|
||||
.split(',')
|
||||
.map((line) => line.trim())
|
||||
.filter((defLine) => {
|
||||
if (
|
||||
defLine.startsWith('constraint') === false &&
|
||||
defLine.includes('foreign key') === false
|
||||
)
|
||||
return true;
|
||||
|
||||
if (indexName) {
|
||||
if (defLine.includes(indexName)) return false;
|
||||
return true;
|
||||
} else {
|
||||
const matched = defLine.match(/\(`(\S+)`\)/);
|
||||
const columnName = matched[1];
|
||||
|
||||
return columns.includes(columnName) === false;
|
||||
}
|
||||
})
|
||||
.join(', ');
|
||||
|
||||
const newSql = oneLineSql.replace(defs, updatedDefs);
|
||||
|
||||
return this.reinsertMapped(createTable, newSql, (row) => {
|
||||
return row;
|
||||
});
|
||||
},
|
||||
{ connection: this.connection }
|
||||
);
|
||||
},
|
||||
|
||||
reinsertMapped(createTable, newSql, mapRow) {
|
||||
return Promise.resolve()
|
||||
.then(() => this.createTempTable(createTable))
|
||||
|
||||
@ -50,6 +50,20 @@ TableCompiler_SQLite3.prototype.dropUnique = function (columns, indexName) {
|
||||
this.pushQuery(`drop index ${indexName}`);
|
||||
};
|
||||
|
||||
// Compile a drop foreign key command.
|
||||
TableCompiler_SQLite3.prototype.dropForeign = function (columns, indexName) {
|
||||
const compiler = this;
|
||||
|
||||
this.pushQuery({
|
||||
sql: `PRAGMA table_info(${this.tableName()})`,
|
||||
output(pragma) {
|
||||
return compiler.client
|
||||
.ddl(compiler, pragma, this.connection)
|
||||
.dropForeign(columns, indexName);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
TableCompiler_SQLite3.prototype.dropIndex = function (columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
|
||||
@ -17,13 +17,16 @@
|
||||
"lint:everything": "npm run lint:types && npm run lint",
|
||||
"test:unit": "mocha --exit -t 10000 test/db-less-test-suite.js && npm run test:tape && npm run test:cli",
|
||||
"test:db": "mocha --exit -t 10000 test/integration-test-suite.js",
|
||||
"test:db:no-oracle": "cross-env DB=\"mssql mysql mysql2 postgres sqlite3\" mocha --exit -t 10000 test/integration-test-suite.js",
|
||||
"test": "mocha --exit -t 10000 test/all-tests-suite.js && npm run test:tape && npm run test:cli",
|
||||
"test:coverage": "nyc mocha --exit --check-leaks --globals __core-js_shared__ -t 10000 test/all-tests-suite.js && npm run test:tape && npm run test:cli",
|
||||
"test:everything": "npm run lint:everything && npm run test:coverage",
|
||||
"test:sqlite": "cross-env DB=sqlite3 npm test",
|
||||
"test:sqlite": "cross-env DB=sqlite3 npm run test:db",
|
||||
"test:postgres": "cross-env DB=postgres npm run test:db",
|
||||
"test:tape": "node test/tape/index.js | tap-spec",
|
||||
"test:cli": "cross-env KNEX_PATH=../knex.js KNEX=bin/cli.js jake -f test/jake/Jakefile",
|
||||
"db:start": "docker-compose -f scripts/docker-compose.yml up --build -d mysql oracledbxe postgres mssql; docker-compose -f scripts/docker-compose.yml up initmssqlknexdb waitmysql waitpostgres waitoracledbxe",
|
||||
"db:start:no-oracle": "docker-compose -f scripts/docker-compose.yml up --build -d mysql postgres mssql && docker-compose -f scripts/docker-compose.yml up initmssqlknexdb waitmysql waitpostgres",
|
||||
"db:stop": "docker-compose -f scripts/docker-compose.yml down",
|
||||
"db:start:postgres": "docker-compose -f scripts/docker-compose.yml up --build -d postgres && docker-compose -f scripts/docker-compose.yml up waitpostgres",
|
||||
"db:stop:postgres": "docker-compose -f scripts/docker-compose.yml down",
|
||||
|
||||
@ -12,6 +12,8 @@ describe('Query Building Tests', function () {
|
||||
this.timeout(process.env.KNEX_TEST_TIMEOUT || 5000);
|
||||
|
||||
require('./unit/query/builder');
|
||||
require('./unit/query/formatter');
|
||||
require('./unit/query/string');
|
||||
require('./unit/schema/mysql')('mysql');
|
||||
require('./unit/schema/mysql')('mysql2');
|
||||
require('./unit/schema/postgres');
|
||||
|
||||
@ -452,7 +452,7 @@ module.exports = function (knex) {
|
||||
.catch(expectQueryEventToHaveBeenTriggered);
|
||||
});
|
||||
|
||||
it('#1040, #1171 - When pool is filled with transaction connections, Non-transaction queries should not hang the application, but instead throw a timeout error', function () {
|
||||
it('#1040, #1171 - When pool is filled with transaction connections, Non-transaction queries should not hang the application, but instead throw a timeout error', async () => {
|
||||
//To make this test easier, I'm changing the pool settings to max 1.
|
||||
const knexConfig = _.clone(knex.client.config);
|
||||
knexConfig.pool.min = 0;
|
||||
@ -463,7 +463,7 @@ module.exports = function (knex) {
|
||||
|
||||
//Create a transaction that will occupy the only available connection, and avoid trx.commit.
|
||||
|
||||
return knexDb.transaction(function (trx) {
|
||||
await knexDb.transaction(function (trx) {
|
||||
let sql = 'SELECT 1';
|
||||
if (knex.client.driverName === 'oracledb') {
|
||||
sql = 'SELECT 1 FROM DUAL';
|
||||
@ -494,6 +494,8 @@ module.exports = function (knex) {
|
||||
trx.commit(); //Test done
|
||||
});
|
||||
});
|
||||
|
||||
await knexDb.destroy();
|
||||
});
|
||||
|
||||
it('#1694, #1703 it should return connections to pool if acquireConnectionTimeout is triggered', async function () {
|
||||
@ -509,6 +511,8 @@ module.exports = function (knex) {
|
||||
await expect(
|
||||
db.transaction(() => db.transaction(() => ({})))
|
||||
).to.be.rejectedWith(KnexTimeoutError);
|
||||
|
||||
await db.destroy();
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@ -15,7 +15,7 @@ const _ = require('lodash');
|
||||
const testMemoryMigrations = require('./memory-migrations');
|
||||
|
||||
module.exports = function (knex) {
|
||||
require('rimraf').sync(path.join(__dirname, './migration'));
|
||||
rimraf.sync(path.join(__dirname, './migration'));
|
||||
|
||||
before(function () {
|
||||
// make sure lock was not left from previous failed test run
|
||||
@ -84,11 +84,12 @@ module.exports = function (knex) {
|
||||
'test/integration/migrate/rename-and-drop-column-with-multiline-sql-from-legacy-db',
|
||||
},
|
||||
});
|
||||
|
||||
const db = logger(knexLib(knexConfig));
|
||||
const knexInstance = knexLib(knexConfig);
|
||||
const db = logger(knexInstance);
|
||||
|
||||
await db.migrate.latest();
|
||||
await db.migrate.rollback();
|
||||
await knexInstance.destroy();
|
||||
});
|
||||
}
|
||||
|
||||
@ -189,8 +190,8 @@ module.exports = function (knex) {
|
||||
});
|
||||
});
|
||||
|
||||
it('should return a positive number if the DB is ahead', function () {
|
||||
return Promise.all([
|
||||
it('should return a positive number if the DB is ahead', async () => {
|
||||
const [migration1, migration2, migration3] = await Promise.all([
|
||||
knex('knex_migrations').returning('id').insert({
|
||||
name: 'foobar',
|
||||
batch: 5,
|
||||
@ -206,26 +207,25 @@ module.exports = function (knex) {
|
||||
batch: 6,
|
||||
migration_time: new Date(),
|
||||
}),
|
||||
]).then(([migration1, migration2, migration3]) => {
|
||||
return knex.migrate
|
||||
.status({ directory: 'test/integration/migrate/test' })
|
||||
.then(function (migrationLevel) {
|
||||
expect(migrationLevel).to.equal(3);
|
||||
})
|
||||
.then(function () {
|
||||
// Cleanup the added migrations
|
||||
if (/redshift/.test(knex.client.driverName)) {
|
||||
return knex('knex_migrations')
|
||||
.where('name', 'like', '%foobar%')
|
||||
.del();
|
||||
}
|
||||
]);
|
||||
return knex.migrate
|
||||
.status({ directory: 'test/integration/migrate/test' })
|
||||
.then(function (migrationLevel) {
|
||||
expect(migrationLevel).to.equal(3);
|
||||
})
|
||||
.then(function () {
|
||||
// Cleanup the added migrations
|
||||
if (/redshift/.test(knex.client.driverName)) {
|
||||
return knex('knex_migrations')
|
||||
.where('id', migration1[0])
|
||||
.orWhere('id', migration2[0])
|
||||
.orWhere('id', migration3[0])
|
||||
.where('name', 'like', '%foobar%')
|
||||
.del();
|
||||
});
|
||||
});
|
||||
}
|
||||
return knex('knex_migrations')
|
||||
.where('id', migration1[0])
|
||||
.orWhere('id', migration2[0])
|
||||
.orWhere('id', migration3[0])
|
||||
.del();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -991,12 +991,13 @@ module.exports = function (knex) {
|
||||
const migrations = {
|
||||
migration1: {
|
||||
up(knex) {
|
||||
return knex.schema.createTable('migration_source_test_1', function (
|
||||
t
|
||||
) {
|
||||
t.increments();
|
||||
t.string('name');
|
||||
});
|
||||
return knex.schema.createTable(
|
||||
'migration_source_test_1',
|
||||
function (t) {
|
||||
t.increments();
|
||||
t.string('name');
|
||||
}
|
||||
);
|
||||
},
|
||||
down(knex) {
|
||||
return knex.schema.dropTable('migration_source_test_1');
|
||||
|
||||
71
test/integration/schema/foreign-keys.js
Normal file
71
test/integration/schema/foreign-keys.js
Normal file
@ -0,0 +1,71 @@
|
||||
const { expect } = require('chai');
|
||||
|
||||
module.exports = (knex) => {
|
||||
describe('Schema', () => {
|
||||
beforeEach(async () => {
|
||||
await knex.schema
|
||||
.createTable('foreign_keys_table_two', (table) => {
|
||||
table.increments();
|
||||
})
|
||||
.createTable('foreign_keys_table_three', (table) => {
|
||||
table.increments();
|
||||
})
|
||||
.createTable('foreign_keys_table_one', (table) => {
|
||||
table.increments();
|
||||
table.integer('fkey_two').unsigned().notNull();
|
||||
table.foreign('fkey_two').references('foreign_keys_table_two.id');
|
||||
table.integer('fkey_three').unsigned().notNull();
|
||||
table
|
||||
.foreign('fkey_three')
|
||||
.references('foreign_keys_table_three.id')
|
||||
.withKeyName('fk_fkey_threeee');
|
||||
});
|
||||
});
|
||||
afterEach(async () => {
|
||||
await knex.schema
|
||||
.dropTable('foreign_keys_table_one')
|
||||
.dropTable('foreign_keys_table_two')
|
||||
.dropTable('foreign_keys_table_three');
|
||||
});
|
||||
|
||||
describe('drop foreign key', () => {
|
||||
it('correctly drops foreign key', async () => {
|
||||
await knex('foreign_keys_table_two').insert({});
|
||||
await knex('foreign_keys_table_three').insert({});
|
||||
await knex('foreign_keys_table_one').insert({
|
||||
fkey_two: 1,
|
||||
fkey_three: 1,
|
||||
});
|
||||
try {
|
||||
await knex('foreign_keys_table_one').insert({
|
||||
fkey_two: 9999,
|
||||
fkey_three: 99,
|
||||
});
|
||||
throw new Error("Shouldn't reach this");
|
||||
} catch (err) {
|
||||
if (knex.client.driverName === 'sqlite3') {
|
||||
expect(err.message).to.equal(
|
||||
`insert into \`foreign_keys_table_one\` (\`fkey_three\`, \`fkey_two\`) values (99, 9999) - SQLITE_CONSTRAINT: FOREIGN KEY constraint failed`
|
||||
);
|
||||
}
|
||||
if (knex.client.driverName === 'postgres') {
|
||||
expect(err.message).to.equal(
|
||||
`insert into "foreign_keys_table_one" ("fkey_three", "fkey_two") values ($1, $2) - insert or update on table "foreign_keys_table_one" violates foreign key constraint "foreign_keys_table_one_fkey_two_foreign"`
|
||||
);
|
||||
}
|
||||
expect(err.message).to.include('constraint');
|
||||
}
|
||||
|
||||
await knex.schema.alterTable('foreign_keys_table_one', (table) => {
|
||||
table.dropForeign(['fkey_two']);
|
||||
table.dropForeign([], 'fk_fkey_threeee');
|
||||
});
|
||||
|
||||
await knex('foreign_keys_table_one').insert({
|
||||
fkey_two: 9999,
|
||||
fkey_three: 99,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -160,23 +160,25 @@ module.exports = (knex) => {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
before(() =>
|
||||
Promise.all([
|
||||
knex.schema.createTable('increments_columns_1_test', (table) => {
|
||||
before(async () => {
|
||||
await knex.schema.createTable(
|
||||
'increments_columns_1_test',
|
||||
(table) => {
|
||||
table.increments().comment('comment_1');
|
||||
}),
|
||||
knex.schema.createTable('increments_columns_2_test', (table) => {
|
||||
}
|
||||
);
|
||||
await knex.schema.createTable(
|
||||
'increments_columns_2_test',
|
||||
(table) => {
|
||||
table.increments('named_2').comment('comment_2');
|
||||
}),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(() =>
|
||||
Promise.all([
|
||||
knex.schema.dropTable('increments_columns_1_test'),
|
||||
knex.schema.dropTable('increments_columns_2_test'),
|
||||
])
|
||||
);
|
||||
after(async () => {
|
||||
await knex.schema.dropTable('increments_columns_1_test');
|
||||
await knex.schema.dropTable('increments_columns_2_test');
|
||||
});
|
||||
|
||||
it('#2210 - creates an incrementing column with a comment', () => {
|
||||
const table_name = 'increments_columns_1_test';
|
||||
@ -1154,8 +1156,8 @@ module.exports = (knex) => {
|
||||
|
||||
describe('renameColumn', () => {
|
||||
describe('without mappers', () => {
|
||||
before(() =>
|
||||
knex.schema
|
||||
before(async () => {
|
||||
await knex.schema
|
||||
.createTable('rename_column_test', (tbl) => {
|
||||
tbl.increments('id_test').unsigned().primary();
|
||||
tbl
|
||||
@ -1175,31 +1177,26 @@ module.exports = (knex) => {
|
||||
.createTable('rename_col_test', (tbl) => {
|
||||
tbl.integer('colnameint').defaultTo(1);
|
||||
tbl.string('colnamestring').defaultTo('knex').notNullable();
|
||||
})
|
||||
.then(() => {
|
||||
// without data, the column isn't found??
|
||||
return knex
|
||||
.insert({ parent_id_test: 1 })
|
||||
.into('rename_column_test');
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
after(() =>
|
||||
knex.schema
|
||||
after(async () => {
|
||||
await knex.schema
|
||||
.dropTable('rename_column_foreign_test')
|
||||
.dropTable('rename_column_test')
|
||||
.dropTable('rename_col_test')
|
||||
);
|
||||
.dropTable('rename_col_test');
|
||||
});
|
||||
|
||||
it('renames the column', () =>
|
||||
knex.schema
|
||||
.table('rename_column_test', (tbl) =>
|
||||
tbl.renameColumn('id_test', 'id')
|
||||
)
|
||||
.then(() => knex.schema.hasColumn('rename_column_test', 'id'))
|
||||
.then((exists) => {
|
||||
expect(exists).to.equal(true);
|
||||
}));
|
||||
it('renames the column', async () => {
|
||||
await knex.schema.table('rename_column_test', (tbl) =>
|
||||
tbl.renameColumn('id_test', 'id')
|
||||
);
|
||||
const exists = await knex.schema.hasColumn(
|
||||
'rename_column_test',
|
||||
'id'
|
||||
);
|
||||
expect(exists).to.equal(true);
|
||||
});
|
||||
|
||||
it('successfully renames a column referenced in a foreign key', () =>
|
||||
knex.schema.table('rename_column_test', (tbl) => {
|
||||
|
||||
@ -14,6 +14,7 @@ module.exports = function (knex) {
|
||||
});
|
||||
|
||||
require('./schema')(knex);
|
||||
require('./schema/foreign-keys')(knex);
|
||||
require('./migrate/migration-integration-tests')(knex);
|
||||
|
||||
require('./seed')(knex);
|
||||
|
||||
@ -25,7 +25,7 @@ const poolSqlite = {
|
||||
acquireTimeoutMillis: 1000,
|
||||
afterCreate: function (connection, callback) {
|
||||
assert.ok(typeof connection.__knexUid !== 'undefined');
|
||||
callback(null, connection);
|
||||
connection.run('PRAGMA foreign_keys = ON', callback);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -1,48 +1,203 @@
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const expect = require('chai').expect;
|
||||
const knex = require('../../../knex');
|
||||
const config = require('../../knexfile');
|
||||
const sinon = require('sinon');
|
||||
|
||||
describe('OracleDb externalAuth', function () {
|
||||
const knexInstance = knex({
|
||||
client: 'oracledb',
|
||||
connection: {
|
||||
user: 'user',
|
||||
password: 'password',
|
||||
connectString: 'connect-string',
|
||||
externalAuth: true,
|
||||
host: 'host',
|
||||
database: 'database',
|
||||
},
|
||||
});
|
||||
let spy;
|
||||
const knex = require('../../../knex');
|
||||
const config = require('../../knexfile');
|
||||
|
||||
before(function () {
|
||||
spy = sinon.spy(knexInstance.client.driver, 'getConnection');
|
||||
describe('Oracle', () => {
|
||||
describe('Compiler', () => {
|
||||
const knexInstance = knex({
|
||||
client: 'oracledb',
|
||||
connection: {
|
||||
user: 'user',
|
||||
password: 'password',
|
||||
connectString: 'connect-string',
|
||||
externalAuth: true,
|
||||
host: 'host',
|
||||
database: 'database',
|
||||
},
|
||||
});
|
||||
|
||||
it('correctly builds single value insert', async () => {
|
||||
const qb = knexInstance.client.queryBuilder();
|
||||
qb.insert({ value: 1 }).into('fakeTable');
|
||||
const compiler = knexInstance.client.queryCompiler(qb);
|
||||
const sql = compiler.insert();
|
||||
expect(sql).to.eql({
|
||||
sql: 'insert into "fakeTable" ("value") values (?)',
|
||||
outBinding: [[]],
|
||||
returning: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('correctly builds default values only insert', async () => {
|
||||
const qb = knexInstance.client.queryBuilder();
|
||||
qb.insert({}).into('fakeTable');
|
||||
const compiler = knexInstance.client.queryCompiler(qb);
|
||||
const sql = compiler.insert();
|
||||
expect(sql).to.eql({
|
||||
sql: 'insert into "fakeTable" values (default)',
|
||||
outBinding: [[]],
|
||||
returning: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('correctly builds default values only insert and returning', async () => {
|
||||
const qb = knexInstance.client.queryBuilder();
|
||||
qb.insert({}).into('fakeTable').returning('id');
|
||||
const compiler = knexInstance.client.queryCompiler(qb);
|
||||
const sql = compiler.insert();
|
||||
expect(sql).to.eql({
|
||||
sql:
|
||||
'insert into "fakeTable" ("id") values (default) returning "id" into ?',
|
||||
outBinding: [['id']],
|
||||
returning: ['id'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('externalAuth and connectString should be sent to the getConnection', function () {
|
||||
const connectionWithExternalAuth = {
|
||||
connectString: 'connect-string',
|
||||
externalAuth: true,
|
||||
};
|
||||
knexInstance.client.acquireRawConnection().then(
|
||||
function (resolve) {},
|
||||
function (reject) {}
|
||||
);
|
||||
expect(spy).to.have.callCount(1);
|
||||
expect(spy).to.have.been.calledWith(connectionWithExternalAuth);
|
||||
describe('OracleDb externalAuth', function () {
|
||||
const knexInstance = knex({
|
||||
client: 'oracledb',
|
||||
connection: {
|
||||
user: 'user',
|
||||
password: 'password',
|
||||
connectString: 'connect-string',
|
||||
externalAuth: true,
|
||||
host: 'host',
|
||||
database: 'database',
|
||||
},
|
||||
});
|
||||
let spy;
|
||||
|
||||
before(function () {
|
||||
spy = sinon.spy(knexInstance.client.driver, 'getConnection');
|
||||
});
|
||||
|
||||
it('externalAuth and connectString should be sent to the getConnection', function () {
|
||||
const connectionWithExternalAuth = {
|
||||
connectString: 'connect-string',
|
||||
externalAuth: true,
|
||||
};
|
||||
knexInstance.client.acquireRawConnection().then(
|
||||
function (resolve) {},
|
||||
function (reject) {}
|
||||
);
|
||||
expect(spy).to.have.callCount(1);
|
||||
expect(spy).to.have.been.calledWith(connectionWithExternalAuth);
|
||||
});
|
||||
|
||||
after(function () {
|
||||
knexInstance.client.driver.getConnection.restore();
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
knexInstance.client.driver.getConnection.restore();
|
||||
});
|
||||
});
|
||||
describe('OracleDb parameters', function () {
|
||||
describe('with fetchAsString parameter ', function () {
|
||||
let knexClient;
|
||||
|
||||
describe('OracleDb parameters', function () {
|
||||
describe('with fetchAsString parameter ', function () {
|
||||
before(function () {
|
||||
const conf = _.clone(config.oracledb);
|
||||
conf.fetchAsString = ['number', 'DATE', 'cLOb', 'BUFFER'];
|
||||
knexClient = knex(conf);
|
||||
return knexClient;
|
||||
});
|
||||
|
||||
it('on float', function () {
|
||||
return knexClient
|
||||
.raw('select 7.329 as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.be.a('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('on date', function () {
|
||||
return knexClient
|
||||
.raw('select CURRENT_DATE as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.be.a('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('on clob', function () {
|
||||
return knexClient
|
||||
.raw('select TO_CLOB(\'LONG CONTENT\') as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.be.equal('LONG CONTENT');
|
||||
});
|
||||
});
|
||||
|
||||
it('on raw', function () {
|
||||
return knexClient
|
||||
.raw('select UTL_RAW.CAST_TO_RAW(3) as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.be.equal('33');
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
return knexClient.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('without fetchAsString parameter', function () {
|
||||
let knexClient;
|
||||
|
||||
before(function () {
|
||||
knexClient = knex(config.oracledb);
|
||||
return knexClient;
|
||||
});
|
||||
|
||||
it('on float', function () {
|
||||
return knexClient
|
||||
.raw('select 7.329 as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.not.be.a('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('on date', function () {
|
||||
return knexClient
|
||||
.raw('select CURRENT_DATE as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.not.be.a('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('on blob', async () => {
|
||||
const result = await knexClient.raw(
|
||||
'select TO_BLOB(\'67c1a1acaaca11a1b36fa6636166709b\') as "field" from dual'
|
||||
);
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field.toString('hex')).to.be.equal(
|
||||
'67c1a1acaaca11a1b36fa6636166709b'
|
||||
);
|
||||
});
|
||||
|
||||
it('on raw', function () {
|
||||
return knexClient
|
||||
.raw('select UTL_RAW.CAST_TO_RAW(3) as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.be.instanceOf(Buffer);
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
return knexClient.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('OracleDb unit tests', function () {
|
||||
let knexClient;
|
||||
|
||||
before(function () {
|
||||
@ -52,160 +207,59 @@ describe('OracleDb parameters', function () {
|
||||
return knexClient;
|
||||
});
|
||||
|
||||
it('on float', function () {
|
||||
return knexClient
|
||||
.raw('select 7.329 as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.be.a('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('on date', function () {
|
||||
return knexClient
|
||||
.raw('select CURRENT_DATE as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.be.a('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('on clob', function () {
|
||||
return knexClient
|
||||
.raw('select TO_CLOB(\'LONG CONTENT\') as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.be.equal('LONG CONTENT');
|
||||
});
|
||||
});
|
||||
|
||||
it('on raw', function () {
|
||||
return knexClient
|
||||
.raw('select UTL_RAW.CAST_TO_RAW(3) as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.be.equal('33');
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
return knexClient.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('without fetchAsString parameter', function () {
|
||||
let knexClient;
|
||||
|
||||
before(function () {
|
||||
knexClient = knex(config.oracledb);
|
||||
return knexClient;
|
||||
});
|
||||
|
||||
it('on float', function () {
|
||||
return knexClient
|
||||
.raw('select 7.329 as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.not.be.a('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('on date', function () {
|
||||
return knexClient
|
||||
.raw('select CURRENT_DATE as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.not.be.a('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('on blob', async () => {
|
||||
const result = await knexClient.raw(
|
||||
'select TO_BLOB(\'67c1a1acaaca11a1b36fa6636166709b\') as "field" from dual'
|
||||
);
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field.toString('hex')).to.be.equal(
|
||||
'67c1a1acaaca11a1b36fa6636166709b'
|
||||
);
|
||||
});
|
||||
|
||||
it('on raw', function () {
|
||||
return knexClient
|
||||
.raw('select UTL_RAW.CAST_TO_RAW(3) as "field" from dual')
|
||||
.then(function (result) {
|
||||
expect(result[0]).to.be.ok;
|
||||
expect(result[0].field).to.be.instanceOf(Buffer);
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
return knexClient.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('OracleDb unit tests', function () {
|
||||
let knexClient;
|
||||
|
||||
before(function () {
|
||||
const conf = _.clone(config.oracledb);
|
||||
conf.fetchAsString = ['number', 'DATE', 'cLOb', 'BUFFER'];
|
||||
knexClient = knex(conf);
|
||||
return knexClient;
|
||||
});
|
||||
|
||||
it('disposes the connection on connection error', async function () {
|
||||
let spy = sinon.spy();
|
||||
// call the real acquireConnection but release the connection immediately to cause connection error
|
||||
const acquireConnection = knexClient.client.acquireConnection;
|
||||
sinon.stub(knexClient.client, 'acquireConnection').callsFake(async () => {
|
||||
const conn = await acquireConnection.call(knexClient.client);
|
||||
conn.release();
|
||||
spy = sinon.spy(conn, 'close');
|
||||
return conn;
|
||||
});
|
||||
|
||||
let exception;
|
||||
try {
|
||||
await knexClient.raw('insert into DUAL values(1)');
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
|
||||
expect(exception).not.to.equal(undefined);
|
||||
expect(exception.message).to.include('NJS-003: invalid connection');
|
||||
expect(spy.callCount).to.equal(1);
|
||||
});
|
||||
|
||||
it('clears the connection from the pool on disconnect during commit', async function () {
|
||||
const err = 'error message';
|
||||
const spy = sinon.spy(knexClient.client, 'releaseConnection');
|
||||
// call the real acquireConnection but ensure commitAsync fails simulating a disconnect
|
||||
const acquireConnection = knexClient.client.acquireConnection;
|
||||
sinon.stub(knexClient.client, 'acquireConnection').callsFake(async () => {
|
||||
const conn = await acquireConnection.call(knexClient.client);
|
||||
conn.commitAsync = () => Promise.reject(err);
|
||||
return conn;
|
||||
});
|
||||
|
||||
let exception;
|
||||
try {
|
||||
await knexClient.transaction(async (trx) => {
|
||||
await trx('DUAL').select('*');
|
||||
it('disposes the connection on connection error', async function () {
|
||||
let spy = sinon.spy();
|
||||
// call the real acquireConnection but release the connection immediately to cause connection error
|
||||
const acquireConnection = knexClient.client.acquireConnection;
|
||||
sinon.stub(knexClient.client, 'acquireConnection').callsFake(async () => {
|
||||
const conn = await acquireConnection.call(knexClient.client);
|
||||
conn.release();
|
||||
spy = sinon.spy(conn, 'close');
|
||||
return conn;
|
||||
});
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
|
||||
expect(spy.callCount).to.equal(1);
|
||||
expect(exception).to.equal(err);
|
||||
});
|
||||
let exception;
|
||||
try {
|
||||
await knexClient.raw('insert into DUAL values(1)');
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
|
||||
afterEach(function () {
|
||||
knexClient.client.acquireConnection.restore();
|
||||
});
|
||||
expect(exception).not.to.equal(undefined);
|
||||
expect(exception.message).to.include('NJS-003: invalid connection');
|
||||
expect(spy.callCount).to.equal(1);
|
||||
});
|
||||
|
||||
after(function () {
|
||||
return knexClient.destroy();
|
||||
it('clears the connection from the pool on disconnect during commit', async function () {
|
||||
const err = 'error message';
|
||||
const spy = sinon.spy(knexClient.client, 'releaseConnection');
|
||||
// call the real acquireConnection but ensure commitAsync fails simulating a disconnect
|
||||
const acquireConnection = knexClient.client.acquireConnection;
|
||||
sinon.stub(knexClient.client, 'acquireConnection').callsFake(async () => {
|
||||
const conn = await acquireConnection.call(knexClient.client);
|
||||
conn.commitAsync = () => Promise.reject(err);
|
||||
return conn;
|
||||
});
|
||||
|
||||
let exception;
|
||||
try {
|
||||
await knexClient.transaction(async (trx) => {
|
||||
await trx('DUAL').select('*');
|
||||
});
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
|
||||
expect(spy.callCount).to.equal(1);
|
||||
expect(exception).to.equal(err);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
knexClient.client.acquireConnection.restore();
|
||||
});
|
||||
|
||||
after(function () {
|
||||
return knexClient.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
31
test/unit/query/formatter.js
Normal file
31
test/unit/query/formatter.js
Normal file
@ -0,0 +1,31 @@
|
||||
const { expect } = require('chai');
|
||||
const Formatter = require('../../../lib/formatter');
|
||||
const Client = require('../../../lib/client');
|
||||
|
||||
describe('formatter', () => {
|
||||
const queryContext = () => {
|
||||
return {};
|
||||
};
|
||||
const client = new Client({ client: 'generic' });
|
||||
const formatter = new Formatter(client, { queryContext });
|
||||
|
||||
it('correctly handles single column value', () => {
|
||||
const columns = formatter.columnize('columnName');
|
||||
expect(columns).to.equal('"columnName"');
|
||||
});
|
||||
|
||||
it('correctly handles multiple column values', () => {
|
||||
const columns = formatter.columnize(['columnName1', 'columnName2']);
|
||||
expect(columns).to.equal('"columnName1", "columnName2"');
|
||||
});
|
||||
|
||||
it('correctly handles null', () => {
|
||||
const columns = formatter.columnize(null);
|
||||
expect(columns).to.equal('');
|
||||
});
|
||||
|
||||
it('correctly handles empty array', () => {
|
||||
const columns = formatter.columnize([]);
|
||||
expect(columns).to.equal('');
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user