Skip to content

Commit

Permalink
feat: add support for insert object values to be a raw query
Browse files Browse the repository at this point in the history
FIXES #723
  • Loading branch information
Harminder Virk authored and Harminder Virk committed Oct 25, 2021
1 parent 5fe4155 commit d2f961f
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/Database/QueryBuilder/Insert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import {
InsertQueryBuilderContract,
} from '@ioc:Adonis/Lucid/Database'

import { RawQueryBuilder } from './Raw'
import { QueryRunner } from '../../QueryRunner'
import { RawBuilder } from '../StaticBuilder/Raw'
import { ReferenceBuilder } from '../StaticBuilder/Reference'

/**
* Exposes the API for performing SQL inserts
Expand Down Expand Up @@ -57,6 +60,37 @@ export class InsertQueryBuilder extends Macroable implements InsertQueryBuilderC
}
}

/**
* Transforms the value to something that knex can internally understand and
* handle. It includes.
*
* 1. Returning the `knexBuilder` for sub queries.
* 2. Returning the `knexBuilder` for raw queries.
*/
protected transformValue(value: any) {
if (value instanceof ReferenceBuilder) {
return value.toKnex(this.knexQuery.client)
}

return this.transformRaw(value)
}

/**
* Returns the underlying knex raw query builder for Lucid raw
* query builder
*/
protected transformRaw(value: any) {
if (value instanceof RawQueryBuilder) {
return value['knexQuery']
}

if (value instanceof RawBuilder) {
return value.toKnex(this.knexQuery.client)
}

return value
}

/**
* Define custom reporter data. It will be merged with
* the existing data
Expand Down Expand Up @@ -101,6 +135,22 @@ export class InsertQueryBuilder extends Macroable implements InsertQueryBuilderC
* Perform insert query
*/
public insert(columns: any): this {
if (columns && Array.isArray(columns)) {
columns = columns.map((column) => {
return column && typeof column === 'object'
? Object.keys(column).reduce((result, key) => {
result[key] = this.transformValue(column[key])
return result
}, {})
: column
})
} else if (columns && typeof columns === 'object') {
columns = Object.keys(columns).reduce((result, key) => {
result[key] = this.transformValue(columns[key])
return result
}, {})
}

this.knexQuery.insert(columns)
return this
}
Expand Down
30 changes: 30 additions & 0 deletions test/database/insert-query-builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
getQueryClient,
getInsertBuilder,
setupApplication,
getRawQueryBuilder,
} from '../../test-helpers'

let app: ApplicationContract
Expand Down Expand Up @@ -96,4 +97,33 @@ test.group('Query Builder | insert', (group) => {
assert.deepEqual(bindings, knexBindings)
await connection.disconnect()
})

test('derive key value from raw query', async (assert) => {
const connection = new Connection('primary', getConfig(), app.logger)
connection.connect()

const db = getInsertBuilder(getQueryClient(connection, app))

const { sql, bindings } = db
.table('users')
.insert({
username: getRawQueryBuilder(
getQueryClient(connection, app),
`ST_GeomFromText(POINT('row.lat_lng'))`
),
})
.toSQL()

const { sql: knexSql, bindings: knexBindings } = connection
.client!.from('users')
.insert({
username: connection.client!.raw(`ST_GeomFromText(POINT('row.lat_lng'))`),
})
.toSQL()

assert.equal(sql, knexSql)
assert.deepEqual(bindings, knexBindings)

await connection.disconnect()
})
})

0 comments on commit d2f961f

Please sign in to comment.