UpdateOperation.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. const { ref } = require('../../queryBuilder/ReferenceBuilder');
  2. const { afterReturn } = require('../../utils/promiseUtils');
  3. const { isKnexRaw, isKnexQueryBuilder } = require('../../utils/knexUtils');
  4. const QueryBuilderOperation = require('./QueryBuilderOperation');
  5. class UpdateOperation extends QueryBuilderOperation {
  6. constructor(name, opt) {
  7. super(name, opt);
  8. this.model = null;
  9. this.modelOptions = Object.assign({}, this.opt.modelOptions || {});
  10. }
  11. onAdd(builder, args) {
  12. const json = args[0];
  13. const modelClass = builder.modelClass();
  14. this.model = modelClass.ensureModel(json, this.modelOptions);
  15. return true;
  16. }
  17. onBefore2(builder, result) {
  18. const maybePromise = this.model.$beforeUpdate(this.modelOptions, builder.context());
  19. return afterReturn(maybePromise, result);
  20. }
  21. onBuildKnex(knexBuilder, builder) {
  22. const json = this.model.$toDatabaseJson(builder.knex());
  23. const convertedJson = this.convertFieldExpressionsToRaw(builder, json);
  24. knexBuilder.update(convertedJson);
  25. }
  26. onAfter2(builder, numUpdated) {
  27. const maybePromise = this.model.$afterUpdate(this.modelOptions, builder.context());
  28. return afterReturn(maybePromise, numUpdated);
  29. }
  30. convertFieldExpressionsToRaw(builder, json) {
  31. const knex = builder.knex();
  32. const convertedJson = {};
  33. const keys = Object.keys(json);
  34. for (let i = 0, l = keys.length; i < l; ++i) {
  35. let key = keys[i];
  36. let val = json[key];
  37. if (key.indexOf(':') > -1) {
  38. // 'col:attr' : ref('other:lol') is transformed to
  39. // "col" : raw(`jsonb_set("col", '{attr}', to_jsonb("other"#>'{lol}'), true)`)
  40. let parsed = ref(key);
  41. let jsonRefs = '{' + parsed.reference.access.map(it => it.ref).join(',') + '}';
  42. let valuePlaceholder = '?';
  43. if (isKnexQueryBuilder(val) || isKnexRaw(val)) {
  44. valuePlaceholder = 'to_jsonb(?)';
  45. } else {
  46. val = JSON.stringify(val);
  47. }
  48. convertedJson[parsed.column] = knex.raw(
  49. `jsonb_set(??, '${jsonRefs}', ${valuePlaceholder}, true)`,
  50. [convertedJson[parsed.column] || parsed.column, val]
  51. );
  52. } else {
  53. convertedJson[key] = val;
  54. }
  55. }
  56. return convertedJson;
  57. }
  58. }
  59. module.exports = UpdateOperation;