Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/format_request.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ async function format_request(options, dareInstance) {
} else if (
options.method === 'patch' &&
!options.parent &&
!dareInstance.applyTableAliasOnUpdate
!dareInstance.applyAliasesOnUpdate
) {
options.sql_alias = options.sql_table;
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,7 @@ Dare.prototype.patch = async function patch(table, filter, body, options = {}) {

// Construct a db update
const sql = SQL`
UPDATE ${raw(exec)}${raw(req.sql_table)} ${dareInstance.applyTableAliasOnUpdate ? raw(req.sql_alias) : empty}
UPDATE ${raw(exec)}${raw(req.sql_table)} ${dareInstance.applyAliasesOnUpdate ? raw(req.sql_alias) : empty}
${req.sql_joins.length ? join(req.sql_joins, '\n') : empty}
SET ${sql_set}
WHERE
Expand Down
6 changes: 0 additions & 6 deletions src/sqlite.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,6 @@ SQLiteDare.prototype.applySubqueryOnDML = true;
*/
SQLiteDare.prototype.applyAliasesOnUpdate = false;

/**
* SQLite does not support UPDATE tbl alias SET ...
* @type {boolean}
*/
SQLiteDare.prototype.applyTableAliasOnUpdate = false;

/**
* SQL insert suffix - SQLite uses RETURNING clause
* @type {string}
Expand Down
141 changes: 141 additions & 0 deletions test/integration/patch.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import assert from 'node:assert/strict';

import {DareError} from '../../src/index.js';
import defaultAPI from './helpers/api.js';

describe('dare.patch', () => {
let dare;

beforeEach(() => {
dare = defaultAPI();
});

it('should update a single record by id', async () => {
const username = 'patchUser';
const newName = 'patchedUser';

const {insertId} = await dare.post('users', {username});

const resp = await dare.patch(
'users',
{id: insertId},
{username: newName}
);

assert.strictEqual(resp.affectedRows, 1);

const result = await dare.get('users', ['username'], {id: insertId});
assert.strictEqual(result.username, newName);
});

it('should update multiple records with a limit', async () => {
const body = ['patchA', 'patchB', 'patchC'].map(username => ({
username,
}));
await dare.post('users', body);

const resp = await dare.patch({
table: 'users',
filter: {username: 'patch%'},
body: {first_name: 'updated'},
limit: 100,
});

assert.strictEqual(resp.affectedRows, 3);
});

it('should throw NOT_FOUND when no records match', async () => {
await assert.rejects(
dare.patch('users', {id: -999}, {username: 'nope'}),
error =>
error instanceof DareError && error.code === DareError.NOT_FOUND
);
});

it('should return notfound value when no records match and notfound option is set', async () => {
const notfound = null;

const resp = await dare.patch(
'users',
{id: -999},
{username: 'nope'},
{notfound}
);

assert.strictEqual(resp, notfound);
});

it('should support object-style request', async () => {
const username = 'objStylePatch';
const {insertId} = await dare.post('users', {username});

const resp = await dare.patch({
table: 'users',
filter: {id: insertId},
body: {username: 'objPatched'},
});

assert.strictEqual(resp.affectedRows, 1);

const result = await dare.get('users', ['username'], {id: insertId});
assert.strictEqual(result.username, 'objPatched');
});

it('should patch with a cross-table filter', async () => {
const code = 'PX';
const {insertId: country_id} = await dare.post('country', {code});

const {insertId} = await dare.post('users', {
username: 'crossPatch',
country_id,
});

const resp = await dare.patch({
table: 'users',
filter: {
id: insertId,
country: {code},
},
body: {username: 'crossPatched'},
});

assert.strictEqual(resp.affectedRows, 1);

const result = await dare.get('users', ['username'], {id: insertId});
assert.strictEqual(result.username, 'crossPatched');
});

it('should set a field to null', async () => {
const {insertId} = await dare.post('users', {
username: 'nullTest',
first_name: 'hasValue',
});

await dare.patch('users', {id: insertId}, {first_name: null});

const result = await dare.get('users', ['first_name'], {id: insertId});
assert.strictEqual(result.first_name, null);
});

it('should trigger model patch handler', async () => {
const {insertId} = await dare.post('users', {username: 'handlerTest'});

dare = dare.use({
models: {
users: {
patch(options) {
options.body.first_name = 'injected';
},
},
},
});

await dare.patch('users', {id: insertId}, {username: 'handlerPatched'});

const result = await dare.get('users', ['username', 'first_name'], {
id: insertId,
});
assert.strictEqual(result.username, 'handlerPatched');
assert.strictEqual(result.first_name, 'injected');
});
});
2 changes: 1 addition & 1 deletion test/specs/postgres/patch.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe('patch', () => {
const dareInst = dare.use({engine: 'postgres:16.3'});

dareInst.execute = async ({sql, values}) => {
sqlEqual(sql, 'UPDATE tbl a SET "name" = ? WHERE a.id = ?');
sqlEqual(sql, 'UPDATE tbl SET "name" = ? WHERE tbl.id = ?');
assert.deepStrictEqual(values, [name, id]);
return {success: true};
};
Expand Down
Loading