简体   繁体   中英

Getting BYTEA from PostgreSQL in Sails.js

I have a problem in dealing with PostgreSQL BYTEA type in Sails.js.

Table definition (yes it is odd to create binary PK, but some_data is always small):

CREATE TABLE data_blobs (
  some_data BYTEA PRIMARY KEY,
  my_date_time TIMESTAMP WITH TIME ZONE NOT NULL);

Model configuration looks like this:

module.exports = {
  tableName: 'data_blobs',
  autoCreatedAt: false,
  autoUpdatedAt: false,
  autoPK: false,
  attributes: {
    some_data: {
      type: 'binary',
      primaryKey: true
    },
    my_date_time: 'datetime',
};

When I query table from node.js using node-postgres (pg) the result contains Node Buffer with some_data which is very easy to use.

But when I query table from Sails.js using code like this one:

DataBlobs.find().then(function(result){
  console.log('Result: ');
  console.log(result);
});

The result looks this way:

{
  some_data: 
  { '0': 1,
    '1': 79,
    '2': 95,
    ...
    '19': 216,
    length: 20,
    parent: 
    { '0': 47,
      ...
      '8191': 0 }
  },
  my_date_time: '2015-08-24T10:43:11.959Z'
}

It seems to me that Waterline transforms Node Buffer to something strange and quite useless (without additional transformation). I could not find any documentation about data conversion not in Waterline docs and not in sails-postgresql docs.

I see two options to deal with this situation:

  1. Somehow to prevent Waterline from converting Buffer and to do conversion on my own.
  2. To grab Waterline output and convert it in controllers.

Second option seems less effective because the original data is appended with large 'parent' and there would be two conversions Buffer->Waterline->MyFormat instead of simple Buffer->MyFormat.

The first solution I found is based on the idea to override Waterline Model function toJSON ( https://github.com/balderdashy/waterline#model ).

I wrote a conversion function:

function internalWaterlineBinaryToBase64(waterlineBinaryRepresentation) {
  var temporaryArray = [];
  for(var i = 0, arrLength = waterlineBinaryRepresentation.length; i < arrLength; i++) {
    temporaryArray.push(waterlineBinaryRepresentation[i.toString()]);
  }

  var temporaryBuffer = new Buffer(temporaryArray);

  return temporaryBuffer.toString('base64');
}

and adjusted my model:

module.exports = {
  tableName: 'data_blobs',
  autoCreatedAt: false,
  autoUpdatedAt: false,
  autoPK: false,
  attributes: {
    some_data: {
      type: 'binary',
      primaryKey: true
    },
    my_date_time: 'datetime',
    toJSON: function() {
      var obj = this.toObject();

      if(obj.some_data) {
        obj.some_data = internalWaterlineBinaryToBase64(obj.some_data);
      }

      return obj;
    }
};

It works fine, but it seems to me that there should be a less expensive method (waterline converts original Buffer to an object, then I convert it to Array, then to Buffer and then to String).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM