Skip to content

Commit

Permalink
Merge pull request #24 from ejyager00/subquery-join
Browse files Browse the repository at this point in the history
Allow use of subqueries in join clauses
  • Loading branch information
G4brym authored Jun 17, 2023
2 parents 501f540 + b47631b commit 1f5c6aa
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 2 deletions.
6 changes: 5 additions & 1 deletion src/Builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,11 @@ export class QueryBuilder<GenericResult, GenericResultOne> {
const joinQuery: Array<string> = []
value.forEach((item: Join) => {
const type = item.type ? `${item.type} ` : ''
joinQuery.push(`${type}JOIN ${item.table} ON ${item.on}`)
joinQuery.push(
`${type}JOIN ${typeof item.table === 'string' ? item.table : `(${this._select(item.table)})`}${
item.alias ? ` AS ${item.alias}` : ''
} ON ${item.on}`
)
})

return ' ' + joinQuery.join(' ')
Expand Down
3 changes: 2 additions & 1 deletion src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ export interface Where {

export interface Join {
type?: string | JoinTypes
table: string
table: string | SelectAll
on: string
alias?: string
}

export interface SelectOne {
Expand Down
61 changes: 61 additions & 0 deletions test/Builder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,67 @@ describe('QueryBuilder', () => {
)
})

test('select with subquery join', async () => {
const query = new QuerybuilderTest()._select({
tableName: 'testTable',
fields: '*',
where: {
conditions: 'field = ?1',
params: ['test'],
},
join: {
table: {
tableName: 'otherTable',
fields: ['test_table_id', 'GROUP_CONCAT(attribute) AS attributes'],
groupBy: 'test_table_id',
},
on: 'testTable.id = otherTableGrouped.test_table_id',
alias: 'otherTableGrouped',
},
})

expect(query).toEqual(
'SELECT * FROM testTable JOIN (SELECT test_table_id, GROUP_CONCAT(attribute) AS attributes FROM otherTable GROUP BY test_table_id) AS otherTableGrouped ON testTable.id = otherTableGrouped.test_table_id WHERE field = ?1'
)
})

test('select with nested subquery joins', async () => {
const query = new QuerybuilderTest()._select({
tableName: 'testTable',
fields: '*',
where: {
conditions: 'field = ?1',
params: ['test'],
},
join: {
table: {
tableName: 'otherTable',
fields: [
'test_table_id',
'GROUP_CONCAT(attribute) AS attributes',
'GROUP_CONCAT(other_attributes, ";") AS other_attributes',
],
groupBy: 'test_table_id',
join: {
table: {
tableName: 'otherTableTwo',
fields: ['other_table_id', 'GROUP_CONCAT(other_attribute) AS other_attributes'],
groupBy: 'other_table_id',
},
on: 'otherTable.id = otherTableTwoGrouped.other_table_id',
alias: 'otherTableTwoGrouped',
},
},
on: 'testTable.id = otherTableGrouped.test_table_id',
alias: 'otherTableGrouped',
},
})

expect(query).toEqual(
'SELECT * FROM testTable JOIN (SELECT test_table_id, GROUP_CONCAT(attribute) AS attributes, GROUP_CONCAT(other_attributes, ";") AS other_attributes FROM otherTable JOIN (SELECT other_table_id, GROUP_CONCAT(other_attribute) AS other_attributes FROM otherTableTwo GROUP BY other_table_id) AS otherTableTwoGrouped ON otherTable.id = otherTableTwoGrouped.other_table_id GROUP BY test_table_id) AS otherTableGrouped ON testTable.id = otherTableGrouped.test_table_id WHERE field = ?1'
)
})

test('select with one where no parameters', async () => {
const query = new QuerybuilderTest()._select({
tableName: 'testTable',
Expand Down

0 comments on commit 1f5c6aa

Please sign in to comment.