Fix joins tests for CockroachDB (#4721)

This commit is contained in:
Igor Savin 2021-10-10 17:16:47 +03:00 committed by GitHub
parent d9d6ac81a7
commit 33e8b9fcb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 2460 additions and 2315 deletions

View File

@ -14,6 +14,15 @@ const {
isPostgreSQL, isPostgreSQL,
} = require('../../util/db-helpers'); } = require('../../util/db-helpers');
const { DRIVER_NAMES: drivers } = require('../../util/constants'); const { DRIVER_NAMES: drivers } = require('../../util/constants');
const {
dropTables,
createAccounts,
createTestTableTwo,
} = require('../../util/tableCreatorHelper');
const {
insertTestTableTwoData,
insertAccounts,
} = require('../../util/dataInsertHelper');
module.exports = function (knex) { module.exports = function (knex) {
// Certain dialects do not have proper insert with returning, so if this is true // Certain dialects do not have proper insert with returning, so if this is true
@ -22,6 +31,15 @@ module.exports = function (knex) {
let fkid = 1; let fkid = 1;
describe('Transactions', function () { describe('Transactions', function () {
before(async () => {
await dropTables(knex);
await createAccounts(knex);
await createTestTableTwo(knex);
await insertAccounts(knex);
await insertTestTableTwoData(knex);
});
it('can run with asCallback', function (ok) { it('can run with asCallback', function (ok) {
knex knex
.transaction(function (t) { .transaction(function (t) {
@ -717,63 +735,63 @@ module.exports = function (knex) {
}) })
).to.be.rejected; ).to.be.rejected;
}); });
});
it('handles promise rejections in nested Transactions (#3706)', async function () { it('handles promise rejections in nested Transactions (#3706)', async function () {
const fn = sinon.stub(); const fn = sinon.stub();
process.on('unhandledRejection', fn); process.on('unhandledRejection', fn);
try { try {
await knex.transaction(async function (trx1) { await knex.transaction(async function (trx1) {
// These two lines together will cause the underlying Transaction // These two lines together will cause the underlying Transaction
// to be rejected. Prior to #3706, this rejection would be unhandled. // to be rejected. Prior to #3706, this rejection would be unhandled.
const trx2 = await trx1.transaction(undefined, { const trx2 = await trx1.transaction(undefined, {
doNotRejectOnRollback: false, doNotRejectOnRollback: false,
});
await trx2.rollback();
await expect(trx2.executionPromise).to.have.been.rejected;
}); });
await trx2.rollback();
await expect(trx2.executionPromise).to.have.been.rejected; expect(fn).have.not.been.called;
} finally {
process.removeListener('unhandledRejection', fn);
}
});
context('when a `connection` is passed in explicitly', function () {
beforeEach(function () {
this.sandbox = sinon.createSandbox();
}); });
expect(fn).have.not.been.called; afterEach(function () {
} finally { this.sandbox.restore();
process.removeListener('unhandledRejection', fn); });
}
});
context('when a `connection` is passed in explicitly', function () { it('assumes the caller will release the connection', async function () {
beforeEach(function () { this.sandbox.spy(knex.client, 'releaseConnection');
this.sandbox = sinon.createSandbox(); const conn = await knex.client.acquireConnection();
}); try {
await knex.transaction(
async function (trx) {
// Do nothing!
},
{ connection: conn }
);
} catch (err) {
// Do nothing. The transaction could have failed due to some other
// bug, and it might have still released the connection in the process.
}
afterEach(function () { expect(knex.client.releaseConnection).to.have.not.been.calledWith(conn);
this.sandbox.restore();
});
it('assumes the caller will release the connection', async function () { // By design, this line will only be reached if the connection
this.sandbox.spy(knex.client, 'releaseConnection'); // was never released.
const conn = await knex.client.acquireConnection(); knex.client.releaseConnection(conn);
try {
await knex.transaction(
async function (trx) {
// Do nothing!
},
{ connection: conn }
);
} catch (err) {
// Do nothing. The transaction could have failed due to some other
// bug, and it might have still released the connection in the process.
}
expect(knex.client.releaseConnection).to.have.not.been.calledWith(conn); // Note: It's still possible that the test might fail due to a Timeout
// even after concluding. This is because the underlying implementation
// By design, this line will only be reached if the connection // might have opened another connection by mistake, but never actually
// was never released. // closed it. (Ex: this was the case for OracleDB before fixing #3721)
knex.client.releaseConnection(conn); });
// Note: It's still possible that the test might fail due to a Timeout
// even after concluding. This is because the underlying implementation
// might have opened another connection by mistake, but never actually
// closed it. (Ex: this was the case for OracleDB before fixing #3721)
}); });
}); });
}; };

View File

@ -1,9 +1,18 @@
'use strict'; 'use strict';
const { isMysql, isPostgreSQL } = require('../../util/db-helpers'); const { isMysql, isPostgreSQL } = require('../../util/db-helpers');
const { dropTables, createAccounts } = require('../../util/tableCreatorHelper');
const { insertAccounts } = require('../../util/dataInsertHelper');
module.exports = function (knex) { module.exports = function (knex) {
describe('Aggregate', function () { describe('Aggregate', function () {
before(async () => {
await dropTables(knex);
await createAccounts(knex);
await insertAccounts(knex);
});
it('has a sum', function () { it('has a sum', function () {
return knex('accounts') return knex('accounts')
.sum('logins') .sum('logins')

File diff suppressed because it is too large Load Diff

View File

@ -1,346 +0,0 @@
'use strict';
const expect = require('chai').expect;
const {
isMssql,
isOracle,
isPgBased,
isSQLite,
} = require('../../util/db-helpers');
const { assertNumberArray } = require('../../util/assertHelper');
const {
dropTables,
createUsers,
createAccounts,
createCompositeKeyTable,
createTestTableTwo,
createDefaultTable,
} = require('../../util/tableCreatorHelper');
const { insertAccounts } = require('../../util/dataInsertHelper');
module.exports = function (knex) {
describe('unions', function () {
before(async () => {
await dropTables(knex);
await createUsers(knex);
await createAccounts(knex);
await createCompositeKeyTable(knex);
await createTestTableTwo(knex);
await createDefaultTable(knex);
await createDefaultTable(knex, true);
});
beforeEach(async () => {
await knex('accounts').truncate();
await insertAccounts(knex);
});
it('handles unions with a callback', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union(function () {
this.select('*').from('accounts').where('id', 2);
});
});
it('handles unions with an array of callbacks', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union([
function () {
this.select('*').from('accounts').where('id', 2);
},
function () {
this.select('*').from('accounts').where('id', 3);
},
]);
});
it('handles unions with a list of callbacks', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union(
function () {
this.select('*').from('accounts').where('id', 2);
},
function () {
this.select('*').from('accounts').where('id', 3);
}
);
});
it('handles unions with an array of builders', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union([
knex.select('*').from('accounts').where('id', 2),
knex.select('*').from('accounts').where('id', 3),
]);
});
it('handles unions with a list of builders', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union(
knex.select('*').from('accounts').where('id', 2),
knex.select('*').from('accounts').where('id', 3)
);
});
it('handles unions with a raw query', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union(
knex.raw('select * from ?? where ?? = ?', ['accounts', 'id', 2])
);
});
it('handles unions with an array raw queries', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union([
knex.raw('select * from ?? where ?? = ?', ['accounts', 'id', 2]),
knex.raw('select * from ?? where ?? = ?', ['accounts', 'id', 3]),
]);
});
it('handles unions with a list of raw queries', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union(
knex.raw('select * from ?? where ?? = ?', ['accounts', 'id', 2]),
knex.raw('select * from ?? where ?? = ?', ['accounts', 'id', 3])
);
});
});
if (isPgBased(knex) || isMssql(knex) || isOracle(knex) || isSQLite(knex)) {
describe('intersects', function () {
before(function () {
return knex.schema.createTable('intersect_test', function (t) {
t.integer('id');
t.integer('test_col_1');
t.integer('test_col_2');
t.integer('test_col_3');
});
});
beforeEach(function () {
return knex('intersect_test').insert([
{
id: 1,
test_col_1: 1,
test_col_2: 2,
test_col_3: 1,
},
{
id: 2,
test_col_1: 2,
test_col_2: 3,
test_col_3: 1,
},
{
id: 3,
test_col_1: 2,
test_col_2: 3,
test_col_3: 2,
},
{
id: 4,
test_col_1: 1,
test_col_2: 2,
test_col_3: 2,
},
{
id: 5,
test_col_1: 1,
test_col_2: 2,
test_col_3: 1,
},
]);
});
after(function () {
return knex.schema.dropTable('intersect_test');
});
it('handles intersects with a callback', function () {
return knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect(function () {
this.select('*').from('intersect_test').where('test_col_2', 2);
})
.then(function (result) {
expect(result.length).to.equal(3);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 4, 5]
);
});
});
it('handles intersects with an array of callbacks', function () {
return knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect([
function () {
this.select('*').from('intersect_test').where('test_col_2', 2);
},
function () {
this.select('*').from('intersect_test').where('test_col_3', 1);
},
])
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 5]
);
});
});
it('handles intersects with a list of callbacks', function () {
return knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect(
function () {
this.select('*').from('intersect_test').where('test_col_2', 2);
},
function () {
this.select('*').from('intersect_test').where('test_col_3', 1);
}
)
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 5]
);
});
});
it('handles intersects with an array of builders', function () {
return knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect([
knex.select('*').from('intersect_test').where('test_col_2', 2),
knex.select('*').from('intersect_test').where('test_col_3', 1),
])
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 5]
);
});
});
it('handles intersects with a list of builders', function () {
return knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect(
knex.select('*').from('intersect_test').where('test_col_2', 2),
knex.select('*').from('intersect_test').where('test_col_3', 1)
)
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 5]
);
});
});
it('handles intersects with a raw query', function () {
return knex('intersect_test')
.select('*')
.where('test_col_1', '=', 2)
.intersect(
knex.raw('select * from ?? where ?? = ?', [
'intersect_test',
'test_col_2',
3,
])
)
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[2, 3]
);
});
});
it('handles intersects with an array raw queries', function () {
return knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect([
knex.raw('select * from ?? where ?? = ?', [
'intersect_test',
'test_col_2',
2,
]),
knex.raw('select * from ?? where ?? = ?', [
'intersect_test',
'test_col_3',
1,
]),
])
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 5]
);
});
});
it('handles intersects with a list of raw queries', function () {
return knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect(
knex.raw('select * from ?? where ?? = ?', [
'intersect_test',
'test_col_2',
2,
]),
knex.raw('select * from ?? where ?? = ?', [
'intersect_test',
'test_col_3',
1,
])
)
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 5]
);
});
});
});
}
};

View File

@ -25,8 +25,6 @@ module.exports = function (knex) {
require('./migrate/migration-integration-tests')(knex); require('./migrate/migration-integration-tests')(knex);
require('./seed')(knex); require('./seed')(knex);
require('./query/unions')(knex);
require('./query/joins')(knex);
require('./query/aggregate')(knex); require('./query/aggregate')(knex);
require('./query/updates')(knex); require('./query/updates')(knex);
require('./execution/transaction')(knex); require('./execution/transaction')(knex);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,430 @@
'use strict';
const expect = require('chai').expect;
const {
isMssql,
isOracle,
isPgBased,
isSQLite,
} = require('../../../util/db-helpers');
const { assertNumberArray } = require('../../../util/assertHelper');
const {
dropTables,
createUsers,
createAccounts,
createCompositeKeyTable,
createTestTableTwo,
createDefaultTable,
} = require('../../../util/tableCreatorHelper');
const { insertAccounts } = require('../../../util/dataInsertHelper');
const {
getAllDbs,
getKnexForDb,
} = require('../../util/knex-instance-provider');
describe('unions', function () {
getAllDbs().forEach((db) => {
describe(db, () => {
let knex;
before(async () => {
knex = getKnexForDb(db);
await dropTables(knex);
await createUsers(knex);
await createAccounts(knex);
await createCompositeKeyTable(knex);
await createTestTableTwo(knex);
await createDefaultTable(knex);
await createDefaultTable(knex, true);
});
beforeEach(async () => {
await knex('accounts').truncate();
await insertAccounts(knex);
});
after(async () => {
await knex.destroy();
});
it('handles unions with a callback', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union(function () {
this.select('*').from('accounts').where('id', 2);
});
});
it('handles unions with an array of callbacks', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union([
function () {
this.select('*').from('accounts').where('id', 2);
},
function () {
this.select('*').from('accounts').where('id', 3);
},
]);
});
it('handles unions with a list of callbacks', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union(
function () {
this.select('*').from('accounts').where('id', 2);
},
function () {
this.select('*').from('accounts').where('id', 3);
}
);
});
it('handles unions with an array of builders', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union([
knex.select('*').from('accounts').where('id', 2),
knex.select('*').from('accounts').where('id', 3),
]);
});
it('handles unions with a list of builders', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union(
knex.select('*').from('accounts').where('id', 2),
knex.select('*').from('accounts').where('id', 3)
);
});
it('handles unions with a raw query', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union(
knex.raw('select * from ?? where ?? = ?', ['accounts', 'id', 2])
);
});
it('handles unions with an array raw queries', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union([
knex.raw('select * from ?? where ?? = ?', ['accounts', 'id', 2]),
knex.raw('select * from ?? where ?? = ?', ['accounts', 'id', 3]),
]);
});
it('handles unions with a list of raw queries', function () {
return knex('accounts')
.select('*')
.where('id', '=', 1)
.union(
knex.raw('select * from ?? where ?? = ?', ['accounts', 'id', 2]),
knex.raw('select * from ?? where ?? = ?', ['accounts', 'id', 3])
);
});
describe.only('intersects', function () {
before(async function () {
await knex.schema.createTable('intersect_test', function (t) {
t.integer('id');
t.integer('test_col_1');
t.integer('test_col_2');
t.integer('test_col_3');
});
});
beforeEach(function () {
return knex('intersect_test').insert([
{
id: 1,
test_col_1: 1,
test_col_2: 2,
test_col_3: 1,
},
{
id: 2,
test_col_1: 2,
test_col_2: 3,
test_col_3: 1,
},
{
id: 3,
test_col_1: 2,
test_col_2: 3,
test_col_3: 2,
},
{
id: 4,
test_col_1: 1,
test_col_2: 2,
test_col_3: 2,
},
{
id: 5,
test_col_1: 1,
test_col_2: 2,
test_col_3: 1,
},
]);
});
after(function () {
return knex.schema.dropTable('intersect_test');
});
it('handles intersects with a callback', async function () {
if (
!isPgBased(knex) &&
!isMssql(knex) &&
!isOracle(knex) &&
!isSQLite(knex)
) {
return this.skip();
}
await knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect(function () {
this.select('*').from('intersect_test').where('test_col_2', 2);
})
.then(function (result) {
expect(result.length).to.equal(3);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 4, 5]
);
});
});
it('handles intersects with an array of callbacks', async function () {
if (
!isPgBased(knex) &&
!isMssql(knex) &&
!isOracle(knex) &&
!isSQLite(knex)
) {
return this.skip();
}
await knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect([
function () {
this.select('*').from('intersect_test').where('test_col_2', 2);
},
function () {
this.select('*').from('intersect_test').where('test_col_3', 1);
},
])
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 5]
);
});
});
it('handles intersects with a list of callbacks', async function () {
if (
!isPgBased(knex) &&
!isMssql(knex) &&
!isOracle(knex) &&
!isSQLite(knex)
) {
return this.skip();
}
await knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect(
function () {
this.select('*').from('intersect_test').where('test_col_2', 2);
},
function () {
this.select('*').from('intersect_test').where('test_col_3', 1);
}
)
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 5]
);
});
});
it('handles intersects with an array of builders', async function () {
if (
!isPgBased(knex) &&
!isMssql(knex) &&
!isOracle(knex) &&
!isSQLite(knex)
) {
return this.skip();
}
await knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect([
knex.select('*').from('intersect_test').where('test_col_2', 2),
knex.select('*').from('intersect_test').where('test_col_3', 1),
])
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 5]
);
});
});
it('handles intersects with a list of builders', async function () {
if (
!isPgBased(knex) &&
!isMssql(knex) &&
!isOracle(knex) &&
!isSQLite(knex)
) {
return this.skip();
}
await knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect(
knex.select('*').from('intersect_test').where('test_col_2', 2),
knex.select('*').from('intersect_test').where('test_col_3', 1)
)
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 5]
);
});
});
it('handles intersects with a raw query', async function () {
if (
!isPgBased(knex) &&
!isMssql(knex) &&
!isOracle(knex) &&
!isSQLite(knex)
) {
return this.skip();
}
await knex('intersect_test')
.select('*')
.where('test_col_1', '=', 2)
.intersect(
knex.raw('select * from ?? where ?? = ?', [
'intersect_test',
'test_col_2',
3,
])
)
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[2, 3]
);
});
});
it('handles intersects with an array raw queries', async function () {
if (
!isPgBased(knex) &&
!isMssql(knex) &&
!isOracle(knex) &&
!isSQLite(knex)
) {
return this.skip();
}
await knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect([
knex.raw('select * from ?? where ?? = ?', [
'intersect_test',
'test_col_2',
2,
]),
knex.raw('select * from ?? where ?? = ?', [
'intersect_test',
'test_col_3',
1,
]),
])
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 5]
);
});
});
it('handles intersects with a list of raw queries', async function () {
if (
!isPgBased(knex) &&
!isMssql(knex) &&
!isOracle(knex) &&
!isSQLite(knex)
) {
return this.skip();
}
await knex('intersect_test')
.select('*')
.where('test_col_1', '=', 1)
.intersect(
knex.raw('select * from ?? where ?? = ?', [
'intersect_test',
'test_col_2',
2,
]),
knex.raw('select * from ?? where ?? = ?', [
'intersect_test',
'test_col_3',
1,
])
)
.then(function (result) {
expect(result.length).to.equal(2);
assertNumberArray(
knex,
result.map((r) => r.id),
[1, 5]
);
});
});
});
});
});
});