pg-large-object
Version:
Large object support for PostgreSQL clients (node-postgres)
308 lines (281 loc) • 10.4 kB
JavaScript
;
var promiseFromCallback = require('./promiseFromCallback');
var ReadStream = require('./ReadStream');
var WriteStream = require('./WriteStream');
/** Represents an opened large object.
*
* @constructor
* @exports pg-large-object/lib/LargeObject
*/
function LargeObject(query, oid, fd)
{
this._query = query;
this.oid = oid;
this._fd = fd;
}
/**
* A seek from the beginning of a object
* @constant {Number}
*/
LargeObject.SEEK_SET = 0;
/**
* A seek from the current position
* @constant {Number}
*/
LargeObject.SEEK_CUR = 1;
/**
* A seek from the end of a object
* @constant {Number}
*/
LargeObject.SEEK_END = 2;
/** @callback module:pg-large-object/lib/LargeObject~closeCallback
* @param {?Error} error If set, an error occurred.
*/
/** Closes this large object.
* You should no longer call any methods on this object.
* @param {module:pg-large-object/lib/LargeObject~closeCallback} [callback]
*/
LargeObject.prototype.close = function(callback)
{
this._query(
{name: "npg_lo_close", text:"SELECT lo_close($1) as ok", values: [this._fd]},
callback ? function(err, result)
{
callback(err);
} : undefined
);
};
/** Closes this large object.
* You should no longer call any methods on this object.
* @returns {Promise}
*/
LargeObject.prototype.closeAsync = function()
{
return promiseFromCallback(function(callback)
{
this.close(callback);
}, this);
};
/** @callback module:pg-large-object/lib/LargeObject~readCallback
* @param {?Error} error If set, an error occurred.
* @param {Buffer} data The binary data that was read.
* If the length of this buffer is less than the supplied
* length param, there is no more data to be read.
*/
/** Reads some data from the large object.
* @param {Number} length How many bytes to read
* @param {module:pg-large-object/lib/LargeObject~readCallback} callback
*/
LargeObject.prototype.read = function(length, callback)
{
this._query(
{name: "npg_loread", text:"SELECT loread($1, $2) as data", values: [this._fd, length]},
function(err, result)
{
if (err) return callback(err);
var data = result.rows[0].data;
callback(null, data);
}
);
};
/** Reads some data from the large object.
* @param {Number} length How many bytes to read
* @returns {Promise.<Buffer>} The binary data that was read.
* If the length of this buffer is less than the supplied
* length param, there is no more data to be read.
*/
LargeObject.prototype.readAsync = function(length)
{
return promiseFromCallback(function(callback)
{
this.read(length, callback);
}, this);
};
/** @callback module:pg-large-object/lib/LargeObject~writeCallback
* @param {?Error} error If set, an error occurred.
*/
/** Writes some data to the large object.
* @param {Buffer} buffer data to write
* @param {module:pg-large-object/lib/LargeObject~writeCallback} [callback]
*/
LargeObject.prototype.write = function(buffer, callback)
{
this._query(
{name: "npg_lowrite", text:"SELECT lowrite($1, $2)", values: [this._fd, buffer]},
callback ? function(err, result)
{
callback(err);
} : undefined
);
};
/** Writes some data to the large object.
* @param {Buffer} buffer data to write
* @returns {Promise}
*/
LargeObject.prototype.writeAsync = function(buffer)
{
return promiseFromCallback(function(callback)
{
this.write(buffer, callback);
}, this);
};
/** @callback module:pg-large-object/lib/LargeObject~seekCallback
* @param {?Error} error If set, an error occurred.
* @param {Number} position The new position
*/
/** Sets the position within the large object.
* Beware floating point rounding with values greater than 2^53 (8192 TiB)
* @param {Number} position
* @param {Number} ref One of SEEK_SET, SEEK_CUR, SEEK_END
* @param {module:pg-large-object/lib/LargeObject~seekCallback} [callback]
*/
LargeObject.prototype.seek = function(position, ref, callback)
{
this._query(
{name: "npg_lo_lseek64", text:"SELECT lo_lseek64($1, $2, $3) as location", values: [this._fd, position, ref]},
callback ? function(err, result)
{
if (err) return callback(err);
var location = result.rows[0].location;
callback(null, location);
} : undefined
);
};
/** Sets the position within the large object.
* Beware floating point rounding with values greater than 2^53 (8192 TiB)
* @param {Number} position
* @param {Number} ref One of SEEK_SET, SEEK_CUR, SEEK_END
* @returns {Promise.<number>} The new position
*/
LargeObject.prototype.seekAsync = function(position, ref)
{
return promiseFromCallback(function(callback)
{
this.seek(position, ref, callback);
}, this);
};
/** @callback module:pg-large-object/lib/LargeObject~tellCallback
* @param {?Error} error If set, an error occurred.
* @param {Number} position The position
*/
/** Retrieves the current position within the large object.
* Beware floating point rounding with values greater than 2^53 (8192 TiB)
* @param {module:pg-large-object/lib/LargeObject~tellCallback} callback
*/
LargeObject.prototype.tell = function(callback)
{
this._query(
{name: "npg_lo_tell64", text:"SELECT lo_tell64($1) as location", values: [this._fd]},
function(err, result)
{
if (err) return callback(err);
var location = result.rows[0].location;
callback(null, location);
}
);
};
/** Retrieves the current position within the large object.
* Beware floating point rounding with values greater than 2^53 (8192 TiB)
* @returns {Promise.<number>}
*/
LargeObject.prototype.tellAsync = function()
{
return promiseFromCallback(function(callback)
{
this.tell(callback);
}, this);
};
/** @callback module:pg-large-object/lib/LargeObject~sizeCallback
* @param {?Error} error If set, an error occurred.
* @param {Number} size Object size in bytes
*/
/** Find the total size of the large object.
* @param {module:pg-large-object/lib/LargeObject~sizeCallback} callback
*/
LargeObject.prototype.size = function(callback)
{
var text = "SELECT lo_lseek64($1, location, 0), seek.size FROM " +
"(SELECT lo_lseek64($1, 0, 2) AS SIZE, tell.location FROM " +
"(SELECT lo_tell64($1) AS location) tell) "+
"seek;";
this._query(
{name: "npg_size", text: text, values: [this._fd]},
function(err, result)
{
if (err) return callback(err);
var size = result.rows[0].size;
callback(null, size);
}
);
};
/** Find the total size of the large object.
* @returns {Promise.<number>}
*/
LargeObject.prototype.sizeAsync = function()
{
return promiseFromCallback(function(callback)
{
this.size(callback);
}, this);
};
/** @callback module:pg-large-object/lib/LargeObject~truncateCallback
* @param {?Error} error If set, an error occurred.
*/
/** Truncates the large object to the given length in bytes.
* If the number of bytes is larger than the current large
* object length, the large object will be filled with zero
* bytes. This method does not modify the current file offset.
* @param {Number} length
* @param {module:pg-large-object/lib/LargeObject~truncateCallback} [callback]
*/
LargeObject.prototype.truncate = function(length, callback)
{
this._query(
{name: "npg_lo_truncate64", text:"SELECT lo_truncate64($1, $2)", values: [this._fd, length]},
callback ? function(err, result)
{
callback(err);
} : undefined
);
};
/** Truncates the large object to the given length in bytes.
* If the number of bytes is larger than the current large
* object length, the large object will be filled with zero
* bytes. This method does not modify the current file offset.
* @param {Number} length
* @returns {Promise}
*/
LargeObject.prototype.truncateAsync = function(length)
{
return promiseFromCallback(function(callback)
{
this.truncate(length, callback);
}, this);
};
/** Return a stream to read this large object.
* Call this within a transaction block.
* @param {Number} [bufferSize=16384] A larger buffer size will
* require more memory on both the server and client, however it will make
* transfers faster because there is less overhead (less read calls to the server).
* his overhead is most noticeable on high latency connections because each
* ransfered chunk will incur at least RTT of additional transfer time.
* @returns {module:pg-large-object/lib/ReadStream}
*/
LargeObject.prototype.getReadableStream = function(bufferSize)
{
return new ReadStream(this, bufferSize);
};
/** Return a stream to write to this large object.
* Call this within a transaction block.
* @param {Number} [bufferSize=16384] A larger buffer size will
* require more memory on both the server and client, however it will make
* transfers faster because there is less overhead (less read calls to the server).
* his overhead is most noticeable on high latency connections because each
* ransfered chunk will incur at least RTT of additional transfer time.
* @returns {module:pg-large-object/lib/WriteStream}
*/
LargeObject.prototype.getWritableStream = function(bufferSize)
{
return new WriteStream(this, bufferSize);
};
module.exports = LargeObject;