Skip to content
Open
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 lib/sql.js
Original file line number Diff line number Diff line change
Expand Up @@ -1326,7 +1326,7 @@ SQLConnector.prototype._buildFieldsForKeys = function(model, data, keys, exclude
continue;
}
const k = this.columnEscaped(model, key);
const v = this.toColumnValue(p, data[key]);
const v = this.toColumnValue(p, data[key], undefined, k);
if (v !== undefined) {
fields.names.push(k);
if (v instanceof ParameterizedSQL) {
Expand Down
107 changes: 107 additions & 0 deletions test/sql.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -626,4 +626,111 @@ describe('sql connector', function() {
});
});
});

describe('toColumnValue with column name parameter', function() {
it('should pass escaped column name as fourth parameter', function() {
let capturedColumnName;
const originalToColumnValue = connector.toColumnValue;

// Override toColumnValue to capture the fourth parameter
connector.toColumnValue = function(prop, val, escaping, columnName) {
capturedColumnName = columnName;
return originalToColumnValue.call(this, prop, val, escaping);
};

try {
const fields = connector.buildFields('customer', {
name: 'John',
vip: true,
});

// Verify that the escaped column name was passed
expect(capturedColumnName).to.be.oneOf(['`NAME`', '`VIP`']);
} finally {
// Restore original method
connector.toColumnValue = originalToColumnValue;
}
});

it('should enable partial JSON updates with column-specific logic', function() {
const originalToColumnValue = connector.toColumnValue;
const ParameterizedSQL = require('../lib/sql').ParameterizedSQL;

// Mock connector that handles JSON columns differently
connector.toColumnValue = function(prop, val, escaping, columnName) {
// Example: Enable partial JSON update for specific columns
if (columnName === '`ADDRESS`' && typeof val === 'object' && val !== null) {
// For JSON columns, connector can use database-specific JSON update syntax
// e.g., PostgreSQL: column = column || '{"new": "data"}'::jsonb
// This demonstrates how the column name enables column-specific handling
return new ParameterizedSQL('jsonb_set(' + columnName + ', ?, ?)',
['{path}', JSON.stringify(val)]);
}
return originalToColumnValue.call(this, prop, val, escaping);
};

try {
const fields = connector.buildFields('customer', {
address: {city: 'Miami', zip: '33101'},
});

// Verify that column-specific logic was applied
expect(fields.columnValues).to.have.lengthOf(1);
expect(fields.columnValues[0].toJSON()).to.deep.equal({
sql: 'jsonb_set(`ADDRESS`, ?, ?)',
params: ['{path}', '{"city":"Miami","zip":"33101"}'],
});
} finally {
connector.toColumnValue = originalToColumnValue;
}
});

it('should work with buildFieldsForUpdate', function() {
const capturedColumnNames = [];
const originalToColumnValue = connector.toColumnValue;

connector.toColumnValue = function(prop, val, escaping, columnName) {
if (columnName) {
capturedColumnNames.push(columnName);
}
return originalToColumnValue.call(this, prop, val, escaping);
};

try {
connector.buildFieldsForUpdate('customer', {
lastName: 'Doe',
vip: true,
});

// Verify column names were passed for UPDATE operations
expect(capturedColumnNames).to.include.members(['`LASTNAME`', '`VIP`']);
} finally {
connector.toColumnValue = originalToColumnValue;
}
});

it('should work with buildFieldsFromArray for bulk inserts', function() {
const capturedColumnNames = [];
const originalToColumnValue = connector.toColumnValue;

connector.toColumnValue = function(prop, val, escaping, columnName) {
if (columnName && !capturedColumnNames.includes(columnName)) {
capturedColumnNames.push(columnName);
}
return originalToColumnValue.call(this, prop, val, escaping);
};

try {
connector.buildFieldsFromArray('customer', [
{name: 'John', vip: true},
{name: 'Jane', vip: false},
]);

// Verify column names were passed for all rows
expect(capturedColumnNames).to.include.members(['`NAME`', '`VIP`']);
} finally {
connector.toColumnValue = originalToColumnValue;
}
});
});
});