loopbackio / loopback-connector-cassandra

Cassandra connector for the LoopBack framework.
Other
13 stars 22 forks source link

Model.updateAttributes doesn't consider composite primary keys #61

Closed shenghu closed 6 years ago

shenghu commented 6 years ago

Description/Steps to reproduce

  1. Create a table w/ composite primary key, e.g.
    CASS_SORTABLE = db.define('CASS_SORTABLE', {
      patBool: {type: Boolean, id: 2},
      str: String,
      patStr: {type: String, id: true},
      num: Number,
      patNum: {type: Number, id: 1},
      yearMonth: {type: String, index: true},
      }, {
      cassandra: {
        clusteringKeys: ['str', 'num DESC'],
        },
      });
  1. Insert a record
    var ROW
    CASS_SORTABLE.create({
      str: cassTestString + '10',
      num: 10,
      patBool: true,
      patNum: 100,
      patStr: cassTestString + '100',
    }, function(err, m) {
      ROW = m;
    });
  2. Update attributes of the row,
    ROW_1.updateAttributes({ 
      str: ROW_1.str,
      num: ROW_1.num,
      patBool: ROW_1.patBool,
      patNum: ROW_1.patNum,
      patStr: ROW_1.patStr,
      yearMonth: '2018-06'}, function(err, rows) {
      });

The update failed w/ error

     Uncaught AssertionError: expected ResponseError {
  name: 'ResponseError',
  info: 'Represents an error message from the server',
  message: 'PRIMARY KEY part str found in SET part',
  code: 8704,
  query: 'UPDATE "CASS_SORTABLE" SET "str"=?,"num"=?,"yearMonth"=? WHERE "patStr"=?'
} to not exist

Link to reproduction sandbox

Expected result

The operation is expected to succeed.

Additional information

ROW.updateAttributes called these codes, SQLConnector.prototype.updateAttributes = function(model, id, data, options, cb) , which is called by DataAccessObject.prototype.updateAttributes.

In DataAccessObject.prototype.updateAttributes, it calls

              invokeConnectorMethod(connector, 'updateAttributes', Model,
                [getIdValue(Model, inst), Model._forDB(context.data)],
                options, updateAttributesCallback);

getIdValue(Model, inst) doesn't consider the composite primary key.

The ideal fix is in juggler to get an object from getIdValue(Model, inst) instead of a string value. But before that, a workaround can be in SQLConnector.prototype.updateAttributes, to put primary keys inwhere and remove them from data.

shenghu commented 6 years ago

Basically when where is needed, primary ids will be excluded from data. If where doesn't include all primary ids, the operation will fail.

When where is not available, primary ids in data will be used to form where predicate.