Skip to content

Commit

Permalink
Accept custom column value (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
enapupe authored and felixmosh committed Aug 15, 2019
1 parent 36cf332 commit 7a8dbb1
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 4 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ To use this lib, first you will have to install it:
```
npm i knex-on-duplicate-update --save
```
or
```
yarn add knex-on-duplicate-update
```

Then, add the following lines to your Knex set up:

Expand All @@ -25,7 +29,7 @@ attachOnDuplicateUpdate();
## Function definition

```javascript
onDuplicateUpdate(...columns: string[]): Knex.QueryBuilder
onDuplicateUpdate(...columns: Array<{[key: string]: string} | string>): Knex.QueryBuilder
```

## How to use
Expand All @@ -37,4 +41,12 @@ await knex.insert({id: 1, name: 'John', email: 'john@mail.com'})
.onDuplicateUpdate('name', 'email');
```

Setting a fallback value for a column
```javascript
await knex.insert({id: 1, name: 'John', email: 'john@mail.com'})
.into('persons')
.onDuplicateUpdate('name', {email: 'john-exists@mail.com'});
```


This lib got inspiration from [`knex-paginator`](https://github.com/cannblw/knex-paginator).
19 changes: 19 additions & 0 deletions __tests__/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ describe('onDuplicateUpdate', () => {
expect(() => db.insert({ id: 1, name: 'test' }).into('persons').onDuplicateUpdate())
.toThrowError('onDuplicateUpdate error: please specify at least one column name.');
});
it('should throw if no columns are not string or object', () => {
expect(() => db.insert({ id: 1, name: 'test' }).into('persons').onDuplicateUpdate(false))
.toThrowError('onDuplicateUpdate error: expected column name to be string or object.');
});
});

describe('behaviour', () => {
Expand Down Expand Up @@ -68,5 +72,20 @@ describe('onDuplicateUpdate', () => {

expect(person).toEqual(expect.objectContaining({ name: 'test5', email: '5@5.com' }));
});

it('should allow specifying a value for a column when updating multiple', async () => {
const id = 5;
await db.insert({ id, name: 'test6', email: '6@6.com' }).into('persons');
await db.insert({
id,
name: 'test6',
email: '6@6.com'
}).into('persons').onDuplicateUpdate('name', {'email': 'updated-email'});
const person = await getById(id);
expect(person).toEqual(expect.objectContaining({
name: 'test6',
email: 'updated-email',
}));
});
});
});
25 changes: 23 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,32 @@ module.exports.attachOnDuplicateUpdate = function attachOnDuplicateUpdate() {
throw new Error('onDuplicateUpdate error: please specify at least one column name.');
}

const columnsPlaceHolders = columns.map(() => `??=Values(??)`).join(', ');
const columnsPlaceHolders = columns.map((column) => {
if (typeof column === 'string'){
return `??=Values(??)`
}
if (column && typeof column === 'object'){
return Object.keys(column).map(() => `??=?`).join(', ')
}
throw new Error('onDuplicateUpdate error: expected column name to be string or object.');
}).join(', ');

const binds = columns.reduce((bindings, column) => {
if (typeof column === 'string'){
return bindings.concat([column, column])
}
if (column && typeof column === 'object'){
const objectColumns = Object.keys(column).map((col) => {
return [col, column[col]]
})
return bindings.concat(...objectColumns)
}
throw new Error('onDuplicateUpdate error: expected column name to be string or object.');
}, [])

return this.client.raw(
`${this.toString()} on duplicate key update ${columnsPlaceHolders}`,
columns.reduce((bindings, column) => bindings.concat([column, column]), [])
binds
);
};
};
2 changes: 1 addition & 1 deletion types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { QueryBuilder as KnexQB } from 'knex';

declare module 'knex' {
interface QueryBuilder {
onDuplicateUpdate(...columnNames: string[]): KnexQB;
onDuplicateUpdate(...columnNames: Array<{[key: string]: string} | string>): KnexQB;
}
}

Expand Down

0 comments on commit 7a8dbb1

Please sign in to comment.