From 3026bb163bccd0f327b54ca526f3832778282bcf Mon Sep 17 00:00:00 2001 From: Alyx <25337749+Alyxsqrd@users.noreply.github.com> Date: Fri, 5 Nov 2021 05:18:19 -0400 Subject: [PATCH] refactor: add missing sumDistinct method --- adonis-typings/model.ts | 1 + adonis-typings/querybuilder.ts | 1 + src/Database/QueryBuilder/Chainable.ts | 9 + test/database/query-builder.spec.ts | 301 +++++++++++++++++++++++++ 4 files changed, 312 insertions(+) diff --git a/adonis-typings/model.ts b/adonis-typings/model.ts index 44a19a98..530473e6 100644 --- a/adonis-typings/model.ts +++ b/adonis-typings/model.ts @@ -464,6 +464,7 @@ declare module '@ioc:Adonis/Lucid/Orm' { min: Aggregate max: Aggregate sum: Aggregate + sumDistinct: Aggregate avg: Aggregate avgDistinct: Aggregate diff --git a/adonis-typings/querybuilder.ts b/adonis-typings/querybuilder.ts index 934eafd8..cf295e05 100644 --- a/adonis-typings/querybuilder.ts +++ b/adonis-typings/querybuilder.ts @@ -745,6 +745,7 @@ declare module '@ioc:Adonis/Lucid/Database' { min: Aggregate max: Aggregate sum: Aggregate + sumDistinct: Aggregate avg: Aggregate avgDistinct: Aggregate diff --git a/src/Database/QueryBuilder/Chainable.ts b/src/Database/QueryBuilder/Chainable.ts index 5cdfb266..24faf46f 100644 --- a/src/Database/QueryBuilder/Chainable.ts +++ b/src/Database/QueryBuilder/Chainable.ts @@ -1582,6 +1582,15 @@ export abstract class Chainable extends Macroable implements ChainableContract { return this } + /** + * Make use of distinct `sum` aggregate function + */ + public sumDistinct(columns: any, alias?: any): this { + this.hasAggregates = true + this.knexQuery.sumDistinct(this.normalizeAggregateColumns(columns, alias)) + return this + } + /** * A shorthand for applying offset and limit based upon * the current page diff --git a/test/database/query-builder.spec.ts b/test/database/query-builder.spec.ts index e1ff9e46..7fca4476 100644 --- a/test/database/query-builder.spec.ts +++ b/test/database/query-builder.spec.ts @@ -9556,6 +9556,307 @@ test.group('Query Builder | sum', (group) => { }) }) +test.group('Query Builder | sumDistinct', (group) => { + group.before(async () => { + app = await setupApplication() + await setup() + }) + + group.after(async () => { + await cleanup() + await fs.cleanup() + }) + + group.afterEach(async () => { + app.container.use('Adonis/Core/Event').clearListeners('db:query') + await resetTables() + }) + + test('use sumDistinct function', async (assert) => { + const connection = new Connection('primary', getConfig(), app.logger) + connection.connect() + + let db = getQueryBuilder(getQueryClient(connection, app)) + const { sql, bindings } = db.from('users').sumDistinct('*', 'sumDistinct').toSQL() + + const { sql: knexSql, bindings: knexBindings } = connection + .client!.from('users') + .sumDistinct('*', { as: 'sumDistinct' }) + .toSQL() + + assert.equal(sql, knexSql) + assert.deepEqual(bindings, knexBindings) + + db = getQueryBuilder(getQueryClient(connection, app)) + db.keysResolver = (key) => `my_${key}` + + const { sql: resolverSql, bindings: resolverBindings } = db + .from('users') + .sumDistinct('*', 'sumDistinct') + .toSQL() + + const { sql: knexResolverSql, bindings: knexResolverBindings } = connection + .client!.from('users') + .sumDistinct('*', { as: 'sumDistinct' }) + .toSQL() + + assert.equal(resolverSql, knexResolverSql) + assert.deepEqual(resolverBindings, knexResolverBindings) + + await connection.disconnect() + }) + + test('use sumDistinct function for multiple times', async (assert) => { + const connection = new Connection('primary', getConfig(), app.logger) + connection.connect() + + let db = getQueryBuilder(getQueryClient(connection, app)) + const { sql, bindings } = db.from('users').sumDistinct({ u: 'username', e: 'email' }).toSQL() + + const { sql: knexSql, bindings: knexBindings } = connection + .client!.from('users') + .sumDistinct({ u: 'username', e: 'email' }) + .toSQL() + + assert.equal(sql, knexSql) + assert.deepEqual(bindings, knexBindings) + + db = getQueryBuilder(getQueryClient(connection, app)) + db.keysResolver = (key) => `my_${key}` + + const { sql: resolverSql, bindings: resolverBindings } = db + .from('users') + .sumDistinct({ u: 'username', e: 'email' }) + .toSQL() + + const { sql: knexResolverSql, bindings: knexResolverBindings } = connection + .client!.from('users') + .sumDistinct({ u: 'my_username', e: 'my_email' }) + .toSQL() + + assert.equal(resolverSql, knexResolverSql) + assert.deepEqual(resolverBindings, knexResolverBindings) + + await connection.disconnect() + }) + + test('use raw queries to compute sumDistinct', async (assert) => { + const connection = new Connection('primary', getConfig(), app.logger) + connection.connect() + + let db = getQueryBuilder(getQueryClient(connection, app)) + const { sql, bindings } = db + .from('users') + .sumDistinct( + getRawQueryBuilder( + getQueryClient(connection, app), + 'select * from profiles where is_verified = ?', + [true] + ), + 'u' + ) + .toSQL() + + const { sql: knexSql, bindings: knexBindings } = connection + .client!.from('users') + .sumDistinct({ + u: connection.client!.raw('select * from profiles where is_verified = ?', [true]), + }) + .toSQL() + + assert.equal(sql, knexSql) + assert.deepEqual(bindings, knexBindings) + + db = getQueryBuilder(getQueryClient(connection, app)) + db.keysResolver = (key) => `my_${key}` + + const { sql: resolverSql, bindings: resolverBindings } = db + .from('users') + .sumDistinct( + getRawQueryBuilder( + getQueryClient(connection, app), + 'select * from profiles where is_verified = ?', + [true] + ), + 'u' + ) + .toSQL() + + const { sql: knexResolverSql, bindings: knexResolverBindings } = connection + .client!.from('users') + .sumDistinct({ + u: connection.client!.raw('select * from profiles where is_verified = ?', [true]), + }) + .toSQL() + + assert.equal(resolverSql, knexResolverSql) + assert.deepEqual(resolverBindings, knexResolverBindings) + + await connection.disconnect() + }) + + test('use subqueries to compute sumDistinct', async (assert) => { + const connection = new Connection('primary', getConfig(), app.logger) + connection.connect() + + let db = getQueryBuilder(getQueryClient(connection, app)) + const { sql, bindings } = db + .from('users') + .sumDistinct( + getQueryBuilder(getQueryClient(connection, app)) + .where('is_verified', true) + .from('profiles'), + 'u' + ) + .toSQL() + + const { sql: knexSql, bindings: knexBindings } = connection + .client!.from('users') + .sumDistinct({ + u: connection.client!.where('is_verified', true).from('profiles'), + }) + .toSQL() + + assert.equal(sql, knexSql) + assert.deepEqual(bindings, knexBindings) + + db = getQueryBuilder(getQueryClient(connection, app)) + db.keysResolver = (key) => `my_${key}` + + const { sql: resolverSql, bindings: resolverBindings } = db + .from('users') + .sumDistinct( + getQueryBuilder(getQueryClient(connection, app)) + .where('is_verified', true) + .from('profiles'), + 'u' + ) + .toSQL() + + const { sql: knexResolverSql, bindings: knexResolverBindings } = connection + .client!.from('users') + .sumDistinct({ + u: connection.client!.where('is_verified', true).from('profiles'), + }) + .toSQL() + + assert.equal(resolverSql, knexResolverSql) + assert.deepEqual(resolverBindings, knexResolverBindings) + + await connection.disconnect() + }) + + test('use raw query to compute sumDistinct with multiple columns', async (assert) => { + const connection = new Connection('primary', getConfig(), app.logger) + connection.connect() + + let db = getQueryBuilder(getQueryClient(connection, app)) + const { sql, bindings } = db + .from('users') + .sumDistinct({ + u: getRawQueryBuilder( + getQueryClient(connection, app), + 'select * from profiles where is_verified = ?', + [true] + ), + e: 'email', + }) + .toSQL() + + const { sql: knexSql, bindings: knexBindings } = connection + .client!.from('users') + .sumDistinct({ + u: connection.client!.raw('select * from profiles where is_verified = ?', [true]), + e: 'email', + }) + .toSQL() + + assert.equal(sql, knexSql) + assert.deepEqual(bindings, knexBindings) + + db = getQueryBuilder(getQueryClient(connection, app)) + db.keysResolver = (key) => `my_${key}` + + const { sql: resolverSql, bindings: resolverBindings } = db + .from('users') + .sumDistinct({ + u: getRawQueryBuilder( + getQueryClient(connection, app), + 'select * from profiles where is_verified = ?', + [true] + ), + e: 'email', + }) + .toSQL() + + const { sql: knexResolverSql, bindings: knexResolverBindings } = connection + .client!.from('users') + .sumDistinct({ + u: connection.client!.raw('select * from profiles where is_verified = ?', [true]), + e: 'my_email', + }) + .toSQL() + + assert.equal(resolverSql, knexResolverSql) + assert.deepEqual(resolverBindings, knexResolverBindings) + + await connection.disconnect() + }) + + test('use subquery to compute sumDistinct with multiple columns', async (assert) => { + const connection = new Connection('primary', getConfig(), app.logger) + connection.connect() + + let db = getQueryBuilder(getQueryClient(connection, app)) + const { sql, bindings } = db + .from('users') + .sumDistinct({ + u: getQueryBuilder(getQueryClient(connection, app)) + .where('is_verified', true) + .from('profiles'), + e: 'email', + }) + .toSQL() + + const { sql: knexSql, bindings: knexBindings } = connection + .client!.from('users') + .sumDistinct({ + u: connection.client!.where('is_verified', true).from('profiles'), + e: 'email', + }) + .toSQL() + + assert.equal(sql, knexSql) + assert.deepEqual(bindings, knexBindings) + + db = getQueryBuilder(getQueryClient(connection, app)) + db.keysResolver = (key) => `my_${key}` + + const { sql: resolverSql, bindings: resolverBindings } = db + .from('users') + .sumDistinct({ + u: getQueryBuilder(getQueryClient(connection, app)) + .where('is_verified', true) + .from('profiles'), + e: 'email', + }) + .toSQL() + + const { sql: knexResolverSql, bindings: knexResolverBindings } = connection + .client!.from('users') + .sumDistinct({ + u: connection.client!.where('is_verified', true).from('profiles'), + e: 'my_email', + }) + .toSQL() + + assert.equal(resolverSql, knexResolverSql) + assert.deepEqual(resolverBindings, knexResolverBindings) + + await connection.disconnect() + }) +}) + test.group('Query Builder | avg', (group) => { group.before(async () => { app = await setupApplication()