/*-
*
* This file is part of Oracle NoSQL Database
* Copyright (C) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
*
* If you have received this file as part of Oracle NoSQL Database the
* following applies to the work as a whole:
*
* Oracle NoSQL Database server software is free software: you can
* redistribute it and/or modify it under the terms of the GNU Affero
* General Public License as published by the Free Software Foundation,
* version 3.
*
* Oracle NoSQL Database is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* If you have received this file as part of Oracle NoSQL Database Client or
* distributed separately the following applies:
*
* Oracle NoSQL Database client software is free software: you can
* redistribute it and/or modify it under the terms of the Apache License
* as published by the Apache Software Foundation, version 2.0.
*
* You should have received a copy of the GNU Affero General Public License
* and/or the Apache License in the LICENSE file along with Oracle NoSQL
* Database client or server distribution. If not, see
* <http://www.gnu.org/licenses/>
* or
* <http://www.apache.org/licenses/LICENSE-2.0>.
*
* An active Oracle commercial licensing agreement for this product supersedes
* these licenses and in such case the license notices, but not the copyright
* notice, may be removed by you in connection with your distribution that is
* in accordance with the commercial licensing terms.
*
* For more information please contact:
*
* berkeleydb-info_us@oracle.com
*
*/
'use strict';
/*global thrift*/
/*global Logger*/
/*global LOG_LEVELS*/
/*global Errors*/
/*global Types*/
/*global fs*/
var EventEmitter = require('events').EventEmitter;
var Proxy = require('./proxy');
var Iterator = require('./iterator');
var ONDBClient = require('./thrift/ONDB');
var ttypes = require('./thrift/ondb_types');
var Types = require('./types')
var Parse = require('./parse');
var Stringify = require('./stringify');
var Stream = require('./readable');
var pack = JSON.parse(fs.readFileSync(__dirname + '/../package.json'));
util.inherits(Store, EventEmitter);
module.exports = Store;
/**
* Store constructor
* @param {Configuration} configuration Configuration object.
* @constructor
*/
function Store(/*Configuration*/ configuration) {
Logger.debug('New Store instance');
var self = this;
this._version = null;
var proxyConf = configuration.proxy;
Errors.missingParameter(configuration, 'configuration');
Errors.missingParameter(proxyConf, 'configuration.proxy');
Errors.missingParameter(proxyConf.startProxy,
'configuration.proxy.startProxy');
Errors.missingParameter(proxyConf.host, 'configuration.proxy.host');
Errors.missingParameter(configuration.storeName, 'configuration.storeName');
Errors.missingParameter(configuration.storeHelperHosts,
'configuration.storeHelperHosts');
configuration.requestTimeout = parseInt(configuration.requestTimeout);
// verify jars for proxy
if (proxyConf.startProxy === true) {
if (!fs.existsSync(proxyConf.KVCLIENT_JAR)) {
var error = new Errors.ParameterError('configuration.proxy.KVCLIENT_JAR',
'kvclient.jar file not found, KVCLIENT_JAR value: ' +
configuration.proxy.KVCLIENT_JAR
);
Logger.error(error);
throw error;
}
var proxyFile = path.normalize(proxyConf.KVPROXY_JAR);
if (!fs.existsSync(proxyFile)) {
var error = new Errors.ParameterError('proxy.KVPROXY_JAR',
'kvproxy.jar file not found, full path: ' +
proxyFile + ' using KVPROXY_JAR value: ' + proxyConf.KVPROXY_JAR
);
Logger.error(error);
throw error;
}
}
EventEmitter.call(this);
this.isConnected = false;
this.thriftClient = null;
this.configuration = configuration;
var thriftConnection;
this._verifyDefaultConsistency();
function setClient(callback) {
Logger.debug('Set NoSQL DB Proxy: ' + proxyConf.host);
callback = callback || function () {
};
var host;
var port;
var colon = proxyConf.host.indexOf(':');
if (colon) {
host = proxyConf.host.substr(0, colon);
port = proxyConf.host.substr(colon + 1);
if (proxyConf.startProxy === true) {
if (!(host == 'localhost') || (host == '127.0.0.1')) {
callback(new Errors.ParameterError(
'configuration.proxy.host',
'To start the proxy, the host should be localhost.'));
return;
}
}
} else {
callback(new Errors.ParameterError(
'configuration.proxy.host',
'The parameter must follow the format host:port'));
return;
}
var options = {
transport: thrift.TFramedTransport,
protocol: thrift.TBinaryProtocol
};
if (configuration.requestTimeout > 0)
options.timeout = configuration.requestTimeout;
thriftConnection = thrift.createConnection(host, port, options)
.on('error', function onErrorThrift(err) {
Logger.debug('Error on thrift Connection' + err);
callback(err);
thriftConnection.removeAllListeners('error');
thriftConnection.removeAllListeners('connect');
}).on('connect', function onConnectThrift(err) {
Logger.debug('Thrift Connection successful');
self.thriftClient = thrift.createClient(ONDBClient, thriftConnection);
callback();
thriftConnection.removeAllListeners('error');
thriftConnection.removeAllListeners('connect');
});
}
function verify(callback) {
Logger.debug('Starting verify process');
Logger.debug('kvStoreName: ' + configuration.storeName);
Logger.debug('kvStoreHelperHosts: ' + configuration.storeHelperHosts);
Logger.debug('username: ' + configuration.username);
Logger.debug('readZones: ' + configuration.readZones);
callback = callback || function () {
};
var verify = new Types.VerifyProperties({
kvStoreName: configuration.storeName,
kvStoreHelperHosts: configuration.storeHelperHosts,
username: configuration.username,
readZones: configuration.readZones,
driverProtocolVersion: pack.protocolVersion
});
var timeout = setTimeout(function () {
callback(new Errors.ConnectionError('Connection timeout'))
}, 2000);
self.thriftClient.verify(verify, function (err, result) {
if (err) {
if (callback)
callback(new Errors.ConnectionError('Verification error', err));
} else {
if (result) {
if (result.isConnected) {
if (result.proxyProtocolVersion) {
var found = false;
for (var index in pack.protocolSupported) {
if (pack.protocolSupported[index] ==
result.proxyProtocolVersion)
found = true;
}
if (found)
callback();
else
callback(new Errors.ConnectionError(
'Verification process failed.',
'This driver can\'t support ' +
' proxy protocol version: ' + result.proxyProtocolVersion));
} else
callback(new Errors.ConnectionError(
'Verification process failed.',
'Protocol version not set'));
} else
callback(new Errors.ConnectionError(
'Verification process failed.',
types.VerifyErrorDescription(result.errorType)));
} else
callback(new Errors.ConnectionError(
'Verification result not received', err));
}
callback = null;
clearTimeout(timeout);
});
}
/**
* This method opens a connection to a kvstore server. It tries to start a
* Thrift proxy if startProxy is set to true on configuration options. This
* process also calls the 'open' event in the listener protocol or 'error' if
* an error occurs during opening.
* @param {openCallback} [callback] Calls this function when the process
* finishes, will return an error object if the opening process fails.
* @method
*/
this.open = function open(/*function*/ callback, attempt, latestError) {
Logger.debug('Store open');
callback = callback || function () {
};
if (typeof attempt === 'undefined')
attempt = 1; else attempt++;
if (self.isConnected) {
var error =
new Errors.ConnectionError('This store is already connected');
self.reportError(error, callback);
callback = null;
return;
}
if (attempt > configuration.connectionAttempts) {
var errorMsg = 'Maximum connection attempts ' +
configuration.connectionAttempts +
' reached';
if (proxyConf.startProxy === true) {
errorMsg += ', latest proxy error: ' + latestError;
}
var error = new Errors.ConnectionError(errorMsg);
self.reportError(error, callback);
callback = null;
return;
}
Logger.debug('Setting client');
setClient(function (err) {
if (err !== undefined) {
if (err instanceof Errors.ParameterError) {
self.reportError(err, callback);
return;
}
if (proxyConf.startProxy === true)
Proxy.startProxy(configuration, function (err, output) {
self.open(callback, attempt, output);
});
else {
var error = new Errors.ConnectionError(
'Error connecting the proxy', err);
self.reportError(error, callback);
callback = null;
}
} else {
verify(function (err) { // Verify failed
if (err) {
var error = new Errors.ConnectionError(
'Error verifying the proxy connection', err);
self.reportError(error, callback);
callback = null;
thriftConnection.end();
} else {
Logger.debug('Store connected to proxy');
self.isConnected = true;
if (callback)
callback();
callback = null;
self.emit('open');
}
});
}
});
};
/**
* Closes the connection.
*/
this.close = function (callback) {
Logger.info('Store close');
callback = callback || function () {
};
if (self.isConnected) {
thriftConnection.end();
self.isConnected = false;
callback();
self.emit('close');
}
};
}
/**
* @callback openCallback
* @param {Error} error The error returned by the operation, if any, null
* otherwise.
*/
Store.prototype._verifyDefaultConsistency =
function _verifyDefaultConsistency() {
var self = this;
var consistency = self.configuration.defaultConsistency;
if (consistency !== undefined)
if (consistency)
if (!(
(consistency instanceof Types.Consistency) ||
(consistency instanceof Types.TimeConsistency) ||
(consistency instanceof Types.VersionConsistency)
))
throw new Error('Error in configuration.defaultConsistency, ' +
'is not a valid Consistency object.');
//Check for Time/Version default consistency
if (!(consistency instanceof Types.Consistency))
consistency = new Types.Consistency(consistency);
self.configuration.defaultConsistency = consistency;
};
Store.prototype._checkReadOptions =
function _checkReadOptions(/*ReadOptions*/ readOptions) {
var self = this;
// Default readoptions
readOptions = readOptions ||
new Types.ReadOptions(
self.configuration.defaultConsistency,
self.configuration.requestTimeout);
// Default consistency
var consistency =
readOptions.consistency || self.configuration.defaultConsistency;
// Check for true objects
if (!(
(consistency instanceof Types.Consistency) ||
(consistency instanceof Types.SimpleConsistency.NONE_REQUIRED_NO_MASTER)
||
(consistency instanceof Types.SimpleConsistency.NONE_REQUIRED) ||
(consistency instanceof Types.SimpleConsistency.ABSOLUTE) ||
(consistency instanceof Types.TimeConsistency) ||
(consistency instanceof Types.VersionConsistency) ))
throw new Error('Error in readOptions.consistency, ' +
'is not a valid Consistency object.');
// Check for Simple/Time/Version consistency
if (!(consistency instanceof Types.Consistency))
consistency = new Types.Consistency(readOptions.consistency);
readOptions.consistency = consistency;
return readOptions;
};
function checkWriteOptions(/*WriteOptions*/ writeOptions,
/*Configuration*/ configuration) {
writeOptions = writeOptions ||
new Types.WriteOptions(
configuration.defaultDurability,
configuration.requestTimeout);
writeOptions.durability = writeOptions.durability ||
configuration.defaultDurability;
return writeOptions;
}
Store.prototype.reportError = function reportError(error, callback) {
callback = callback || function () {
};
Logger.error(error);
callback(error);
try {
this.emit('error', error);
} catch (error) {
Logger.debug("No error event available to catch error: " + error);
}
};
Store.prototype.checkIsConnected = function checkIsConnected() {
var self = this;
if (!self.isConnected)
throw new Errors.ConnectionError(
'\nThe store is not connected.' +
'\nStore name: ' + self.configuration.storeName +
'\nStore helper hosts: ' + self.configuration.storeHelperHosts +
'\nUsername: ' + self.configuration.username +
'\nRead zones: ' + self.configuration.readZones +
'\nCheck your configuration and try again.');
};
/**
* Attempts to shutdown the proxy related to the configuration of this store.
* @param {shutdownProxyCallback} [callback] A function that is called when the
* process ends.
*/
Store.prototype.shutdownProxy = function shutdownProxy(callback) {
var self = this;
callback = callback || function () {
};
if (self.isConnected) {
self.close();
self.thriftClient.shutdown();
callback();
} else {
Proxy.stopProxy(self.configuration.proxy, callback);
}
};
/**
* @callback shutdownProxyCallback
* @param {Error} error The error returned by the operation, if any, null
* otherwise.
*/
/**
* Gets the Row associated with the primary key.
* @param {String} tableName The table name.
* @param {Object} primaryKey The primary key for a table. It must be a
* complete primary key, with all fields set.
* @param {ReadOptions} [readOptions] Non-default options for the operation or
* null to get default behavior.
* @param {getCallback} [callback] A function that is called when the process
* ends.
*
*/
Store.prototype.get = function get(/*String*/ tableName,
/*Object*/ primaryKey,
/*ReadOptions*/ readOptions,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(primaryKey, 'primaryKey');
primaryKey = new ttypes.TRow({jsonRow: Stringify(primaryKey)});
if (typeof readOptions === 'function') {
callback = readOptions;
readOptions = null;
}
readOptions = self._checkReadOptions(readOptions);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.get(tableName, primaryKey, readOptions,
function (err, response) {
Logger.debug('Return from get with err:' + err);
if (err) {
var error = Errors.getProxyError(err, 'get()');
self.reportError(error, callback);
} else {
var result = null;
if (response)
result = new Types.GetResult(response);
callback(null, result);
}
});
};
/**
* @callback getCallback
* @param {Error} error The error returned by the operation, if any, null
* otherwise.
* @param {GetResult} result The result associated with this operation.
*/
/**
* Returns the rows associated with a partial primary key in an atomic
* manner. Rows are returned in primary key order. The key used must contain
* all of the fields defined for the table's shard key.
* @param {String} tableName The table name.
* @param {Object} partialPrimaryKey The primary key for a table.
* It may be partial or complete. The key used must contain all of the fields
* defined for the table's shard key.
* @param {Object} [options] An object that includes the following
* parameters:
* { fieldRange: null,
* includedTables: null,
* readOptions: null }
* @param {FieldRange} options.fieldRange The FieldRange to be used to restrict
* the range of the operation.
* @param {Array} options.includedTables The list of tables to be included in
* an operation that returns multiple rows or keys.
* @param {ReadOptions} options.readOptions Non-default options for the
* operation or null to get default behavior.
* @param {multiGetCallback} [callback] A function that is called when the
* process ends.
*/
Store.prototype.multiGet = function multiGet(/*String*/ tableName,
/*Object*/ partialPrimaryKey,
/*Object*/ options,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(partialPrimaryKey, 'primaryKey');
partialPrimaryKey = new ttypes.TRow({jsonRow: Stringify(partialPrimaryKey)});
if (typeof options === 'function') {
callback = options;
options = null;
}
var fieldRange, includedTables, readOptions;
if (options) {
fieldRange = ('fieldRange' in options) ? options.fieldRange : null;
includedTables =
('includedTables' in options) ? options.includedTables : null;
readOptions = ('readOptions' in options) ? options.readOptions : null;
}
readOptions = self._checkReadOptions(readOptions);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.multiGet(tableName, partialPrimaryKey, fieldRange,
includedTables,
readOptions, function (err, response) {
if (err) {
var error = Errors.getProxyError(err, 'multiGet()');
self.reportError(error, callback);
} else {
var result = null;
if (response)
result = new Types.MultiGetResult(response);
callback(null, result);
}
});
};
/**
* @callback multiGetCallback
* @param {Error} error The error returned by the operation, if any, null
* otherwise.
* @param {MultiGetResult} result The result associated with this
* operation.
*/
/**
* Returns the rows associated with a partial primary key in an atomic manner.
* Keys are returned in primary key order. The key used must contain all of
* the fields defined for the table's shard key.
* @param {String} tableName The table name.
* @param {Object} primaryKey The primary key for a table. It must be a
* complete primary key, with all fields set.
* @param {Object} [options] An object that includes the following
* parameters:
* { fieldRange: null,
* includedTables: null,
* readOptions: null }
* @param {FieldRange} options.fieldRange The FieldRange to be used to restrict
* the range of the operation.
* @param {Array} options.includedTables The list of tables to be included in
* an operation that returns multiple rows or keys. the primaryKey parameter
* is always included as a target.
* @param {ReadOptions} options.readOptions Non-default options for the
* operation or null to get default behavior.
* @param {multiGetKeysCallback} [callback] A function that is called when the
* process ends.
*/
Store.prototype.multiGetKeys =
function multiGetKeys(/*String*/ tableName,
/*Object*/ primaryKey,
/*Object*/ options,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(primaryKey, 'primaryKey');
primaryKey = new ttypes.TRow({jsonRow: Stringify(primaryKey)});
if (typeof options === 'function') {
callback = options;
options = null;
}
var fieldRange, includedTables, readOptions;
if (options) {
fieldRange = ('fieldRange' in options) ? options.fieldRange : null;
includedTables =
('includedTables' in options) ? options.includedTables : null;
readOptions = ('readOptions' in options) ? options.readOptions : null;
}
readOptions = self._checkReadOptions(readOptions);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.multiGetKeys(tableName, primaryKey, fieldRange,
includedTables, readOptions, function (err,
response) {
if (err) {
var error = Errors.getProxyError(err, 'multiGetKeys()');
self.reportError(error, callback);
} else {
var result = null;
if (response && response.rowsWithMetadata)
result = new Types.MultiGetKeyResult(response);
callback(null, result);
}
});
};
/**
* @callback multiGetKeysCallback
* @param {Error} error The error returned by the operation, if any, null
* otherwise.
* @param {MultiGetKeyResult} result The result associated with this
* operation.
*/
/**
* Puts a row into a table. The row must contain a complete primary key and
* all required fields.
* @param {String} tableName The table name.
* @param {Object} row the primary key for a table. It must be a complete
* primary key, with all fields set.
* @param {WriteOptions} [writeOptions] Non-default arguments controlling the
* Durability of the operation, or null to get default behaviour.
* @param {putCallback} [callback] A function that is called when the process
* ends.
*/
Store.prototype.put = function put(/*String*/ tableName,
/*Object*/ row,
/*WriteOptions*/ writeOptions,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(row, 'row');
var ttl = row.ttl;
row = new ttypes.TRow({jsonRow: Stringify(row)});
row.ttl = ttl;
if (typeof writeOptions === 'function') {
callback = writeOptions;
writeOptions = null;
}
writeOptions = checkWriteOptions(writeOptions, self.configuration);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.put(tableName, row, writeOptions,
function (err, response) {
Logger.debug('Return from put with err:' + err);
if (err) {
var error = Errors.getProxyError(err, 'put()');
self.reportError(error, callback);
} else {
var result = null;
if (response)
result = new Types.PutResult(response);
callback(null, result);
}
});
};
/**
* Puts a row into a table, but only if the row does not exist. The row must
* contain a complete primary key and all required fields.
* @param {String} tableName The table name.
* @param {Object} row The primary key for a table. It must be a complete
* primary key, with all fields set.
* @param {WriteOptions} [writeOptions] Non-default arguments controlling the
* Durability of the operation, or null to get default behavior.
* @param {putCallback} [callback] A function that is called when the process
* ends.
*/
Store.prototype.putIfAbsent =
function putIfAbsent(/*String*/ tableName,
/*Object*/ row,
/*WriteOptions*/ writeOptions,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(row, 'row');
row = new ttypes.TRow({jsonRow: Stringify(row)});
if (typeof writeOptions === 'function') {
callback = writeOptions;
writeOptions = null;
}
writeOptions = checkWriteOptions(writeOptions, self.configuration);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.putIfAbsent(tableName, row, writeOptions,
function (err, response) {
Logger.debug('Return from putIfAbsent with err:' + err);
if (err) {
var error = Errors.getProxyError(err, 'putIfAbsent()');
self.reportError(error, callback);
} else {
var result = null;
if (response)
result = new Types.PutResult(response);
callback(null, result);
}
});
};
/**
* Puts a row into a table, but only if the row already exists. The row must
* contain a complete primary key and all required fields.
* @param {String} tableName The table name.
* @param {Object} row the primary key for a table. It must be a complete
* primary key, with all fields set.
* @param {WriteOptions} [writeOptions] Non-default arguments controlling the
* Durability of the operation, or null to get default behavior.
* @param {putCallback} [callback] A function that is called when the process
* ends.
*/
Store.prototype.putIfPresent =
function putIfPresent(/*String*/ tableName,
/*Object*/ row,
/*WriteOptions*/ writeOptions,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(row, 'row');
row = new ttypes.TRow({jsonRow: Stringify(row)});
if (typeof writeOptions === 'function') {
callback = writeOptions;
writeOptions = null;
}
writeOptions = checkWriteOptions(writeOptions, self.configuration);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.putIfPresent(tableName, row, writeOptions,
function (err, response) {
if (err) {
var error = Errors.getProxyError(err, 'putIfPresent()');
self.reportError(error, callback);
} else {
var result = null;
if (response)
result = new Types.PutResult(response);
callback(null, result);
}
});
};
/**
* Puts a row, but only if the version of the existing row matches the
* matchVersion argument. Used when updating a value to ensure that it has
* not changed since it was last read. The row must contain a complete
* primary key and all required fields.
* @param {String} tableName The table name.
* @param {Object} row The primary key for a table. It must be a complete
* primary key, with all fields set.
* @param {Buffer} matchVersion The version to match.
* @param {WriteOptions} [writeOptions] Non-default arguments controlling the
* Durability of the operation, or null to get default behavior.
* @param {putCallback} [callback] A function that is called when the process
* ends.
*/
Store.prototype.putIfVersion =
function putIfVersion(/*String*/ tableName,
/*Object*/ row,
/*Version*/ matchVersion,
/*WriteOptions*/ writeOptions,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(row, 'row');
Errors.missingParameter(matchVersion, 'matchVersion');
row = new ttypes.TRow({jsonRow: Stringify(row)});
if (typeof writeOptions === 'function') {
callback = writeOptions;
writeOptions = null;
}
writeOptions = checkWriteOptions(writeOptions, self.configuration);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.putIfVersion(tableName, row, matchVersion.id,
writeOptions, function (err, response) {
if (err) {
var error = Errors.getProxyError(err, 'putIfVersion()');
self.reportError(error, callback);
} else {
var result = null;
if (response)
result = new Types.PutResult(response);
callback(null, result);
}
});
};
/**
* @callback putCallback
* @param {Error} error The error returned by the operation, if any, null
* otherwise.
* @param {PutResult} result The result associated with this
* operation.
*/
/**
* Deletes a row from a table.
* @param {String} tableName The table name.
* @param {Object} primaryKey The primary key for a table. It must be a
* complete primary key, with all fields set.
* @param {WriteOptions} [writeOptions] Non-default arguments controlling the
* Durability of the operation, or null to get default behaviour.
* @param {deleteCallback} [callback] A function that is called when the process
* ends.
*/
Store.prototype.delete = function deleteRow(/*String*/ tableName,
/*Object*/ primaryKey,
/*WriteOptions*/ writeOptions,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(primaryKey, 'primaryKey');
primaryKey = new ttypes.TRow({jsonRow: Stringify(primaryKey)});
if (typeof writeOptions === 'function') {
callback = writeOptions;
writeOptions = null;
}
writeOptions = checkWriteOptions(writeOptions, self.configuration);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.deleteRow(tableName, primaryKey, writeOptions,
function (err, response) {
if (err) {
var error = Errors.getProxyError(err, 'deleteRow()');
self.reportError(error, callback);
} else {
var result = null;
if (response)
result = new Types.DeleteResult(response);
callback(null, result);
}
});
};
/**
* Deletes a row from a table but only if its version matches the one
* specified in matchVersion.
* @param {String} tableName The table name.
* @param {Object} primaryKey The primary key for a table. It must be a
* complete primary key, with all fields set.
* @param {Version} matchVersion The version to match.
* @param {WriteOptions} [writeOptions] Non-default arguments controlling the
* Durability of the operation, or null to get default behavior.
* @param {deleteCallback} [callback] A function that is called when the process
* ends.
*/
Store.prototype.deleteIfVersion =
function deleteIfVersion(/*String*/ tableName,
/*Object*/ primaryKey,
/*Version*/ matchVersion,
/*WriteOptions*/ writeOptions,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(primaryKey, 'primaryKey');
Errors.missingParameter(matchVersion, 'matchVersion');
primaryKey = new ttypes.TRow({jsonRow: Stringify(primaryKey)});
if (typeof writeOptions === 'function') {
callback = writeOptions;
writeOptions = null;
}
writeOptions = checkWriteOptions(writeOptions, self.configuration);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.deleteRowIfVersion(tableName, primaryKey, matchVersion.id,
writeOptions, function (err, response) {
if (err) {
var error = Errors.getProxyError(err, 'deleteRowIfVersion()');
self.reportError(error, callback);
} else {
var result = null;
if (response)
result = new Types.DeleteResult(response);
callback(null, result);
}
});
};
/**
* @callback deleteCallback
* @param {Error} error The error returned by the operation, if any, null
* otherwise.
* @param {DeleteResult} result The result associated with this
* operation.
*/
/**
* Deletes multiple rows from a table in an atomic operation. The key used
* may be partial but must contain all of the fields that are in the shard
* key.
* @param {String} tableName The table name.
* @param {Object} primaryKey The primary key for a table. It must be a
* complete primary key, with all fields set.
* @param {Object} [options] An object that includes the following
* parameters:
* { fieldRange: null,
* includedTables: null,
* writeOptions: null }
* @param {FieldRange} options.fieldRange The FieldRange to be used to restrict
* the range of the operation.
* @param {Array} options.includedTables The list of tables to be included in
* an operation that returns multiple rows or keys.
* @param {WriteOptions} options.writeOptions Non-default arguments controlling
* the Durability of the operation, or null to get default behavior.
* @param {multiDeleteCallback} [callback] A function that is called when the
* process ends.
*/
Store.prototype.multiDelete =
function multiDelete(/*String*/ tableName,
/*Object*/ primaryKey,
/*Object*/ options,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName', 'string');
Errors.missingParameter(primaryKey, 'primaryKey', 'object');
primaryKey = new ttypes.TRow({jsonRow: Stringify(primaryKey)});
if (typeof options === 'function') {
callback = options;
options = null;
}
var fieldRange, includedTables, writeOptions;
if (options) {
fieldRange = ('fieldRange' in options) ? options.fieldRange : null;
includedTables =
('includedTables' in options) ? options.includedTables : null;
writeOptions = ('readOptions' in options) ? options.readOptions : null;
}
writeOptions = checkWriteOptions(writeOptions, self.configuration);
callback = callback || function () {
};
self.checkIsConnected();
return self.thriftClient.multiDelete(
tableName,
primaryKey,
fieldRange,
includedTables,
writeOptions,
function (err, response) {
Logger.debug('Return from multiDelete with err:' + err);
if (err) {
var error = Errors.getProxyError(err, 'multiDelete()');
self.reportError(error, callback);
} else {
callback(null, response);
}
});
};
/**
* @callback multiDeleteCallback
* @param {Error} error The error returned by the operation, if any, null
* otherwise.
* @param {Number} result The number of rows deleted by this
* operation.
*/
/**
* Returns an iterator over the rows associated with a partial primary key.
* @param {String} tableName The table name.
* @param {Object} primaryKey The primary key for a table. It must be a
* complete primary key, with all fields set.
* @param {Object} [options] An object that includes the following
* parameters:
* { fieldRange: null,
* includedTables: null,
* readOptions: null,
* direction: null }
* @param {FieldRange} options.fieldRange The FieldRange to be used to restrict
* the range of the operation.
* @param {Array} options.includedTables The list of tables to be included in
* an operation that returns multiple rows or keys.
* @param {ReadOptions} options.readOptions Non-default options for the
* operation or null to get default behavior.
* @param {Direction} options.direction The Direction for this operation. If
* the primary key contains a complete shard key both Direction.FORWARD and
* Direction.REVERSE are allowed.
* @param {iteratorCallback} [callback] A function that is called when the
* process ends.
*/
Store.prototype.tableIterator =
function tableIterator(/*String*/ tableName,
/*Object*/ primaryKey,
/*Object*/ options,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(primaryKey, 'primaryKey');
primaryKey = new ttypes.TRow({jsonRow: Stringify(primaryKey)});
if (typeof options === 'function') {
callback = options;
options = null;
}
var fieldRange, includedTables, readOptions, direction;
if (options) {
fieldRange = ('fieldRange' in options) ? options.fieldRange : null;
includedTables =
('includedTables' in options) ? options.includedTables : null;
readOptions = ('readOptions' in options) ? options.readOptions : null;
direction = ('direction' in options) ? options.direction : null;
}
readOptions = self._checkReadOptions(readOptions);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.tableIterator(
tableName,
primaryKey,
fieldRange,
includedTables,
readOptions,
direction,
self.configuration.iteratorBufferSize,
function (err, result) {
if (err) {
var error = Errors.getProxyError(err, 'tableIterator()');
self.reportError(error, callback);
} else
callback(null,
new Iterator(self.thriftClient, result, Types.MultiGetResult));
});
};
/**
* Returns an iterator over the keys associated with a partial primary key.
* @param {String} tableName The table name.
* @param {Object} primaryKey The primary key for a table. It must be a
* complete primary key, with all fields set.
* @param {Object} [options] An object that includes the following
* parameters:
* { fieldRange: null,
* includedTables: null,
* readOptions: null,
* direction: null }
* @param {FieldRange} options.fieldRange The FieldRange to be used to restrict
* the range of the operation.
* @param {Array} options.includedTables The list of tables to be included in
* an operation that returns multiple rows or keys.
* @param {ReadOptions} options.readOptions Non-default options for the
* operation or null to get default behavior.
* @param {Direction} options.direction The Direction for this operation. If
* the primary key contains a complete shard key both Direction.FORWARD and
* Direction.REVERSE are allowed.
* @param {iteratorCallback} [callback] A function that is called when the
* process ends.
*/
Store.prototype.tableKeyIterator =
function tableKeyIterator(/*String*/ tableName,
/*Object*/ primaryKey,
/*Object*/ options,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(primaryKey, 'primaryKey');
primaryKey = new ttypes.TRow({jsonRow: Stringify(primaryKey)});
if (typeof options === 'function') {
callback = options;
options = null;
}
var fieldRange, includedTables, readOptions, direction;
if (options) {
fieldRange = ('fieldRange' in options) ? options.fieldRange : null;
includedTables =
('includedTables' in options) ? options.includedTables : null;
readOptions = ('readOptions' in options) ? options.readOptions : null;
direction = ('direction' in options) ? options.direction : null;
}
readOptions = self._checkReadOptions(readOptions);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.tableKeyIterator(
tableName,
primaryKey,
fieldRange,
includedTables,
readOptions,
direction,
self.configuration.iteratorBufferSize,
function (err, result) {
if (err) {
var error = Errors.getProxyError(err, 'tableKeyIterator()');
self.reportError(error, callback);
} else
callback(null,
new Iterator(self.thriftClient, result, Types.MultiGetKeyResult));
});
};
/**
* Returns an iterator over the rows associated with an index key. This
* method requires an additional database read on the server side to get row
* information for matching rows. Ancestor table rows for matching index rows
* may be returned as well if specified in the getOptions parameter. Index
* operations may not specify the return of child table rows.
* @param {String} tableName The table name.
* @param {String} indexName The index name.
* @param {Object} [options] An object that includes the following
* parameters:
* { indexKey: null,
* fieldRange: null,
* includedTables: null,
* readOptions: null,
* direction: null }
* @param {Object} options.indexKey The index key for the operation. It may be
* partial or complete. If the key has no fields set the entire index is
* matched.
* @param {FieldRange} options.fieldRange The FieldRange to be used to restrict
* the range of the operation.
* @param {Array} options.includedTables The list of tables to be included in
* an operation that returns multiple rows or keys.
* @param {ReadOptions} options.readOptions Non-default options for the
* operation or null to get default behavior.
* @param {Direction} options.direction The Direction for this operation. If
* the primary key contains a complete shard key both Direction.FORWARD and
* Direction.REVERSE are allowed.
* @param {iteratorCallback} [callback] A function that is called when the
* process ends.
*/
Store.prototype.indexIterator =
function indexIterator(/*String*/ tableName,
/*String*/ indexName,
/*Object*/ options,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(indexName, 'indexName');
if (typeof options === 'function') {
callback = options;
options = null;
}
var indexKey, fieldRange, includedTables, readOptions, direction;
if (options) {
indexKey = ('indexKey' in options) ?
new ttypes.TRow({jsonRow: Stringify(options.indexKey)}) : null;
fieldRange = ('fieldRange' in options) ? options.fieldRange : null;
includedTables =
('includedTables' in options) ? options.includedTables : null;
readOptions = ('readOptions' in options) ? options.readOptions : null;
direction = ('direction' in options) ? options.direction : null;
}
readOptions = self._checkReadOptions(readOptions);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.indexIterator(
tableName,
indexName,
indexKey,
fieldRange,
includedTables,
readOptions,
direction,
self.configuration.iteratorBufferSize,
function (err, result) {
if (err) {
var error = Errors.getProxyError(err, 'indexIterator()');
self.reportError(error, callback);
} else
callback(null,
new Iterator(self.thriftClient, result, Types.MultiGetResult));
});
};
/**
* Returns the KeyPair for matching rows associated with an index key. The
* iterator returned only references information directly available from the
* index -- the row's primary key and the matching index key for the entry.
* No extra fetch operations are performed. Ancestor table keys for
* matching index keys may be returned as well if specified in the getOptions
* parameter. Index operations may not specify the return of child table keys.
* @param {String} tableName The table name.
* @param {String} indexName The index name.
* @param {Object} [options] An object that includes the following
* parameters:
* { indexKey: null,
* fieldRange: null,
* includedTables: null,
* readOptions: null,
* direction: null }
* @param {Object} options.indexKey The index key for the operation. It may be
* partial or complete. If the key has no fields set the entire index is
* matched.
* @param {FieldRange} options.fieldRange The FieldRange to be used to restrict
* the range of the operation.
* @param {Array} options.includedTables The list of tables to be included in
* an operation that returns multiple rows or keys.
* @param {ReadOptions} options.readOptions Non-default options for the
* operation or null to get default behavior.
* @param {Direction} options.direction The Direction for this operation. If
* the primary key contains a complete shard key both Direction.FORWARD and
* Direction.REVERSE are allowed.
* @param {iteratorCallback} [callback] A function that is called when the
* process ends.
*/
Store.prototype.indexKeyIterator =
function indexKeyIterator(/*String*/ tableName,
/*String*/ indexName,
/*Object*/ options,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(indexName, 'indexName');
if (typeof options === 'function') {
callback = options;
options = null;
}
var indexKey, fieldRange, includedTables, readOptions, direction;
if (options) {
indexKey = ('indexKey' in options) ?
new ttypes.TRow({jsonRow: Stringify(options.indexKey)}) : null;
fieldRange = ('fieldRange' in options) ? options.fieldRange : null;
includedTables =
('includedTables' in options) ? options.includedTables : null;
readOptions = ('readOptions' in options) ? options.readOptions : null;
direction = ('direction' in options) ? options.direction : null;
}
readOptions = self._checkReadOptions(readOptions);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.indexKeyIterator(
tableName,
indexName,
indexKey,
fieldRange,
includedTables,
readOptions,
direction,
self.configuration.iteratorBufferSize,
function (err, result) {
if (err) {
var error = Errors.getProxyError(err, 'indexKeyIterator()');
self.reportError(error, callback);
} else
callback(null,
new Iterator(self.thriftClient, result, Types.KeyPairResult));
});
};
/**
* @callback iteratorCallback
* @param {Error} error The error returned by the operation, if any, null
* otherwise.
* @param {Iterator} result An Iterator object with the item results for this
* call.
*
*/
/**
* Refreshes cached information about the tables. This method is
* required before using any tables that had been modified.
* @param {function} [callback] A function that is called when the process
* ends.
*/
Store.prototype.refreshTables = function refreshTables(callback) {
var self = this;
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.refreshTables(function (err) {
if (err) {
var error = Errors.getProxyError(err, 'refreshTables()');
self.reportError(error, callback);
} //else
//callback();
});
// TODO: error in proxy, no return, use manual callback
callback();
};
/**
* Executes a table statement. Currently, table statements
* can be used to create or modify tables and indices.
* @param {String} statement The statement to be performed.
* @param {executeCallback} [callback] A function that is called when the
* process ends.
*/
Store.prototype.execute = function execute(/*String*/ statement,
/*function*/ callback) {
var self = this;
Errors.missingParameter(statement, 'statement');
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.executeSyncV2(statement, function (err, result) {
if (err) {
var error = Errors.getProxyError(err, 'execute()');
self.reportError(error, callback);
} else
callback(null, new Types.StatementResult(result));
})
};
/**
* Executes a table DDL statement in the server without waiting for a response.
* Currently, table statements can be used to create or modify tables and
* indices.
* @param {String} statement The statement to be performed.
* @param {executeFutureCallback} [callback] A function that is called when the
* process ends.
*/
Store.prototype.executeFuture =
function executeFuture(/*String*/ statement,
/*executeCallback*/ callback) {
var self = this;
Errors.missingParameter(statement, 'statement');
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.executeV2(statement, function (err, result) {
if (err) {
var error = Errors.getProxyError(err, 'executeBackground()');
self.reportError(error, callback);
} else
callback(null, new Types.ExecutionFuture(result, self));
})
};
/**
* @callback executeFutureCallback
* @param {Error} error The error returned by the operation, if any, null
* otherwise.
* @param {ExecutionFuture} result A statementResult object with information
* about the process.
*/
/**
* Creates an ExecutionFuture object from a ExecutionId object.
* @param {ExecutionId} executionId The ExecutionId from which the execution
* future is going to be constructed.
* @return {ExecutionFuture} executionFuture The ExecutionFuture object.
*/
Store.prototype.getExecutionFuture =
function getExecutionFuture(/*ExecutionId*/ executionId) {
var self = this;
Errors.missingParameter(executionId, 'executionId');
self.checkIsConnected();
return new Types.ExecutionFuture(executionId, self);
};
/**
* This method provides an efficient and transactional mechanism for
* executing a sequence of operations associated with tables that share
* the same shard key portion of their primary keys.
* @param {Array} operations The operations to be performed.
* @param {WriteOptions} [writeOptions] Non-default arguments controlling the
* Durability of the operation, or null to get default behaviour.
* For this method, returnChoice is not allowed within writeOptions object
* and it must be null, instead, every operation should handle their own
* returnChoice option.
* @param {executeUpdatesCallback} [callback] A function that is called when
* the process ends.
*/
Store.prototype.executeUpdates =
function executeUpdates(/*Array*/ operations,
/*WriteOptions*/ writeOptions,
/*function*/ callback) {
var self = this;
Errors.missingParameter(operations, 'operations');
if (!(operations instanceof Array)) // Only one operation sent
operations = [operations];
for (var key in operations)
if (!(operations[key] instanceof Types.Operation)) {
throw new Errors.ParameterError(
'operation[' + key + ']',
'The operation is invalid. ' +
'Create operations with Operation() constructor.');
}
if (operations.length <= 0)
throw new Errors.ParameterError(
'operations', 'The operations array is empty.');
// check for null versions
for (var key in operations) {
if (operations[key].tableName === null)
throw new Errors.ParameterError(
'operation[' + key + ']',
'The operation contains a null tableName.');
if (operations[key].type === null)
throw new Errors.ParameterError(
'operation[' + key + ']',
'The operation contains a null type.');
if (operations[key].row === null)
throw new Errors.ParameterError(
'operation[' + key + ']',
'The operation contains a null row.');
if ((operations[key].type === Types.OperationType.PUT_IF_VERSION) ||
(operations[key].type === Types.OperationType.DELETE_IF_VERSION))
if (operations[key].matchVersion instanceof Types.Version) {
if (operations[key].matchVersion.id !== undefined)
operations[key].matchVersion = operations[key].matchVersion.id;
} else
throw new Errors.ParameterError(
'operation[' + key + ']',
'The operation contains an invalid Version.');
//fix content
operations[key].row =
new ttypes.TRow({jsonRow: Stringify(operations[key].row)});
if (operations[key].ttl !== undefined)
if (operations[key].ttl)
operations[key].row.ttl = operations[key].ttl;
}
if (typeof writeOptions === 'function') {
callback = writeOptions;
writeOptions = null;
}
// Verify that returnChoice doesn't exist or is null
if (writeOptions) {
if (writeOptions.returnChoice) {
var error = new Errors.ParameterError('writeOptions.returnChoice',
'returnChoice is not allowed on writeOptions for executeUpdates(). ' +
'It must be used on each operation. ');
throw error;
}
}
writeOptions = checkWriteOptions(writeOptions, self.configuration);
callback = callback || function () {};
self.checkIsConnected();
self.thriftClient.executeUpdates(operations, writeOptions,
function (err, result) {
if (err) {
var error = Errors.getProxyError(err, 'executeUpdates()');
self.reportError(error, callback);
} else {
var finalResult = [];
if (result) {
for (var row in result)
finalResult.push(new Types.UpdateResult(result[row]))
}
callback(null, finalResult);
}
});
};
/**
* @callback executeUpdatesCallback
* @param {Error} error The error returned by the operation, if any, null
* otherwise.
* @param {UpdateResult} result A statementResult object with information
* about the process.
*/
/**
* Returns a Readable Stream over the rows associated with a partial primary
* key.
* @param {String} tableName The table name.
* @param {Object} primaryKey The primary key for a table. It must be a
* complete primary key, with all fields set.
* @param {Object} [options] An object that includes the following
* parameters:
* { fieldRange: null,
* includedTables: null,
* readOptions: null,
* direction: null }
* @param {FieldRange} options.fieldRange The FieldRange to be used to restrict
* the range of the operation.
* @param {Array} options.includedTables The list of tables to be included in
* an operation that returns multiple rows or keys.
* @param {ReadOptions} options.readOptions Non-default options for the
* operation or null to get default behavior.
* @param {Direction} options.direction The Direction for this operation. If
* the primary key contains a complete shard key both Direction.FORWARD and
* Direction.REVERSE are allowed.
* @param {streamCallback} [callback] A function that is called when the process
* ends.
*/
Store.prototype.tableStream = function tableStream(/*String*/ tableName,
/*Object*/ primaryKey,
/*Object*/ options,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(primaryKey, 'primaryKey');
primaryKey = new ttypes.TRow({jsonRow: Stringify(primaryKey)});
if (typeof options === 'function') {
callback = options;
options = null;
}
var fieldRange, includedTables, readOptions, direction;
if (options) {
fieldRange = ('fieldRange' in options) ? options.fieldRange : null;
includedTables =
('includedTables' in options) ? options.includedTables : null;
readOptions = ('readOptions' in options) ? options.readOptions : null;
direction = ('direction' in options) ? options.direction : null;
}
readOptions = self._checkReadOptions(readOptions);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.tableIterator(
tableName,
primaryKey,
fieldRange,
includedTables,
readOptions,
direction,
self.configuration.iteratorBufferSize,
function (err, result) {
if (err) {
var error = Errors.getProxyError(err, 'tableStream()');
self.reportError(error, callback);
} else
callback(null,
new Stream(self, result));
});
};
/**
* Returns a Readable Stream over the keys associated with a partial primary
* key.
* @param {String} tableName The table name.
* @param {Object} primaryKey The primary key for a table. It must be a
* complete primary key, with all fields set.
* @param {Object} [options] An object that includes the following
* parameters:
* { fieldRange: null,
* includedTables: null,
* readOptions: null,
* direction: null }
* @param {FieldRange} options.fieldRange The FieldRange to be used to restrict
* the range of the operation.
* @param {Array} options.includedTables The list of tables to be included in
* an operation that returns multiple rows or keys.
* @param {ReadOptions} options.readOptions Non-default options for the
* operation or null to get default behavior.
* @param {Direction} options.direction The Direction for this operation. If
* the primary key contains a complete shard key both Direction.FORWARD and
* Direction.REVERSE are allowed.
* @param {streamCallback} [callback] A function that is called when the process
* ends.
*/
Store.prototype.tableKeyStream =
function tableKeyStream(/*String*/ tableName,
/*Object*/ primaryKey,
/*Object*/ options,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(primaryKey, 'primaryKey');
primaryKey = new ttypes.TRow({jsonRow: Stringify(primaryKey)});
if (typeof options === 'function') {
callback = options;
options = null;
}
var fieldRange, includedTables, readOptions, direction;
if (options) {
fieldRange = ('fieldRange' in options) ? options.fieldRange : null;
includedTables =
('includedTables' in options) ? options.includedTables : null;
readOptions = ('readOptions' in options) ? options.readOptions : null;
direction = ('direction' in options) ? options.direction : null;
}
readOptions = self._checkReadOptions(readOptions);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.tableKeyIterator(
tableName,
primaryKey,
fieldRange,
includedTables,
readOptions,
direction,
self.configuration.iteratorBufferSize,
function (err, result) {
if (err) {
var error = Errors.getProxyError(err, 'tableKeyStream()');
self.reportError(error, callback);
} else
callback(null,
new Stream(self, result));
});
};
/**
* Returns a Readable Stream over the rows associated with an index key. This
* method requires an additional database read on the server side to get row
* information for matching rows. Ancestor table rows for matching index rows
* may be returned as well if specified in the getOptions parameter. Index
* operations may not specify the return of child table rows.
* @param {String} tableName The table name.
* @param {String} indexName The index name.
* @param {Object} [options] An object that includes the following
* parameters:
* { indexKey: null,
* fieldRange: null,
* includedTables: null,
* readOptions: null,
* direction: null }
* @param {Object} options.indexKey The index key for the operation. It may be
* partial or complete. If the key has no fields set the entire index is
* matched.
* @param {FieldRange} options.fieldRange The FieldRange to be used to restrict
* the range of the operation.
* @param {Array} options.includedTables The list of tables to be included in
* an operation that returns multiple rows or keys.
* @param {ReadOptions} options.readOptions Non-default options for the
* operation or null to get default behavior.
* @param {Direction} options.direction The Direction for this operation. If
* the primary key contains a complete shard key both Direction.FORWARD and
* Direction.REVERSE are allowed.
* @param {streamCallback} [callback] A function that is called when the process
* ends.
*/
Store.prototype.indexStream = function indexStream(/*String*/ tableName,
/*String*/ indexName,
/*Object*/ options,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(indexName, 'indexName');
if (typeof options === 'function') {
callback = options;
options = null;
}
var indexKey, fieldRange, includedTables, readOptions, direction;
if (options) {
indexKey = ('indexKey' in options) ?
new ttypes.TRow({jsonRow: Stringify(options.indexKey)}) : null;
fieldRange = ('fieldRange' in options) ? options.fieldRange : null;
includedTables =
('includedTables' in options) ? options.includedTables : null;
readOptions = ('readOptions' in options) ? options.readOptions : null;
direction = ('direction' in options) ? options.direction : null;
}
readOptions = self._checkReadOptions(readOptions);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.indexIterator(
tableName,
indexName,
indexKey,
fieldRange,
includedTables,
readOptions,
direction,
self.configuration.iteratorBufferSize,
function (err, result) {
if (err) {
var error = Errors.getProxyError(err, 'indexStream()');
self.reportError(error, callback);
} else
callback(null,
new Stream(self, result));
});
};
/**
* Return a Readable Stream with the KeyPairs for matching rows associated with
* an index key. The Stream returned only references information directly
* available from the index. No extra fetch operations are performed.
* Ancestor table keys for matching index keys may be returned as well if
* specified in the getOptions parameter. Index operations may not specify the
* return of child table keys.
* @param {String} tableName The table name.
* @param {String} indexName The index name.
* @param {Object} [options] An object that includes the following
* parameters:
* { indexKey: null,
* fieldRange: null,
* includedTables: null,
* readOptions: null,
* direction: null }
* @param {Object} options.indexKey The index key for the operation. It may be
* partial or complete. If the key has no fields set the entire index is
* matched.
* @param {FieldRange} options.fieldRange The FieldRange to be used to restrict
* the range of the operation.
* @param {Array} options.includedTables The list of tables to be included in
* an operation that returns multiple rows or keys.
* @param {ReadOptions} options.readOptions Non-default options for the
* operation or null to get default behavior.
* @param {Direction} options.direction The Direction for this operation. If
* the primary key contains a complete shard key both Direction.FORWARD and
* Direction.REVERSE are allowed.
* @param {streamCallback} [callback] A function that is called when the process
* ends.
*/
Store.prototype.indexKeyStream =
function indexKeyStream(/*String*/ tableName,
/*String*/ indexName,
/*Object*/ options,
/*function*/ callback) {
var self = this;
Errors.missingParameter(tableName, 'tableName');
Errors.missingParameter(indexName, 'indexName');
if (typeof options === 'function') {
callback = options;
options = null;
}
var indexKey, fieldRange, includedTables, readOptions, direction;
if (options) {
indexKey = ('indexKey' in options) ?
new ttypes.TRow({jsonRow: Stringify(options.indexKey)}) : null;
fieldRange = ('fieldRange' in options) ? options.fieldRange : null;
includedTables =
('includedTables' in options) ? options.includedTables : null;
readOptions = ('readOptions' in options) ? options.readOptions : null;
direction = ('direction' in options) ? options.direction : null;
}
readOptions = self._checkReadOptions(readOptions);
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.indexKeyIterator(
tableName,
indexName,
indexKey,
fieldRange,
includedTables,
readOptions,
direction,
self.configuration.iteratorBufferSize,
function (err, result) {
if (err) {
var error = Errors.getProxyError(err, 'indexKeyStream()');
self.reportError(error, callback);
} else
callback(null,
new Stream(self, result));
});
};
/**
* @callback streamCallback
* @param {Error} error The error returned by the operation, if any, null
* otherwise.
* @param {Readable} result A Stream object with the result of this operation.
*/
/**
* Return a String with the version of the Proxy/Java
* @param {ModuleInfo} moduleInfo This parameter indicates which module the
* version is asked.
* @param {versionCallback} [callback] A function that is called when the
* process ends.
*/
Store.prototype.version =
function version(/*ModuleInfo*/ moduleInfo, /*funcion*/ callback) {
var self = this;
Errors.missingParameter(moduleInfo, 'moduleInfo');
callback = callback || function () {
};
self.checkIsConnected();
if (moduleInfo == Types.ModuleInfo.JS_DRIVER) {
callback(null, pack.version);
} else
self.thriftClient.version(moduleInfo,
function (err, result) {
if (err) {
var error = Errors.getProxyError(err, 'version()');
self.reportError(error, callback);
} else {
callback(null, result);
}
});
};
/**
* Return a String with the status of the Proxy/Java.
* @param {ModuleInfo} moduleInfo This parameter indicates which module the
* version is asked.
* @param {versionCallback} [callback] A function that is called when the
* process ends.
*/
Store.prototype.status =
function status(/*ModuleInfo*/ moduleInfo, /*funcion*/ callback) {
var self = this;
Errors.missingParameter(moduleInfo, 'moduleInfo');
callback = callback || function () {
};
self.checkIsConnected();
self.thriftClient.status(moduleInfo,
function (err, result) {
if (err) {
var error = Errors.getProxyError(err, 'status()');
self.reportError(error, callback);
} else
callback(null, result);
});
};
/**
* Helper function to parse the results of a key-only iteration as a
* row with metadata or a plain key pair.
*/
Store.prototype.parseKeyPair =
function parseKeyPair(/*TRowWithMetadata*/ args) {
return new Types.KeyPair(args);
}
/**
* @callback versionCallback
* @param {Error} error The error returned by the operation, if any, null
* otherwise.
* @param {String} result A String with the result of this operation.
*/
/**
* Helper function to parse strings and convert them into Javascript objects,
* use it instead of common JSON.parse when you use long integers (64 bits).
* This function converts these long integers into Int64 objects.
* @type {parse|exports}
*/
Store.prototype.parse = Parse;
/**
* Helper function to convert Javascript objects into strings,
* use it instead of common JSON.strings when you use Int64 objects.
* This function converts these Int64 objects into correct long integer strings.
* @type {parse|exports}
*/
Store.prototype.stringify = Stringify;
/**
* Called when an error occurred
* @event Store#error
*/
/**
* Called when the Store is opened
* @event Store#open
*/
/**
* Called when the Store is closed
* @event Store#close
*/