UNPKG

kvclient-js

Version:

Oracle NoSQL Database node.js Client API.

1,048 lines (985 loc) 48.1 kB
/*- * * This file is part of Oracle NoSQL Database * Copyright (C) 2011, 2014 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 kvLogger*/ /*global LOG_LEVELS*/ /*global Errors*/ /*global Types*/ 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 Parse = require('./Parse').parse; var Stringify = require('./Stringify').stringify; var Readable = require('./Readable'); module.exports = Store; util.inherits(Store, EventEmitter); /** * Store constructor * @param {Configuration} configuration configuration object * @constructor */ function Store ( /*Configuration*/ configuration ) { kvLogger.info('New Store instance'); EventEmitter.call(this); var self = this; var isConnected = false; var thriftClient, thriftConnection; var proxyConf = configuration.proxyConfiguration; function setClient(callback) { callback = callback || function(){}; kvLogger.debug('Set kvClient to Proxy: ' + proxyConf.host); var host, port; if (proxyConf.startProxy) { host = "localhost"; port = "5010"; } else { var colon = proxyConf.host.indexOf(':'); if (colon) { host = proxyConf.host.substr(0, colon); port = proxyConf.host.substr(colon + 1); } else { callback(new Error(Errors.PROXY_HOST_ERROR)); } } thriftConnection = thrift.createConnection(host, port, { transport: thrift.TFramedTransport, protocol: thrift.TBinaryProtocol }).on('error', function (err) { kvLogger.debug('Error on thrift Connection' + err); callback(err); thriftConnection.removeAllListeners('error'); thriftConnection.removeAllListeners('connect'); }).on('connect', function (err) { kvLogger.debug('Thrift Connection successful'); thriftClient = thrift.createClient(ONDBClient, thriftConnection); callback(); thriftConnection.removeAllListeners('error'); thriftConnection.removeAllListeners('connect'); }); } function verify(callback) { kvLogger.debug('Starting verify process'); kvLogger.debug(configuration); callback = callback || function(){}; var verify = new Types.VerifyProperties( proxyConf.kvStoreName, proxyConf.kvStoreHelperHosts, proxyConf.username ); kvLogger.debug(verify); var timeout = setTimeout(function () { callback(new Error(Errors.PROXY_TIMEOUT)) }, 2000); thriftClient.verify(verify, function (err) { if (err) callback(new Error(err)); else callback(); callback = null; clearTimeout(timeout); }); } /** * This methods opens a connection to a kvstore server, it tries to start a thrift proxy if this is not specified * on configuration options. This process also calls the 'open' event in the listener protocol or 'error' if an error * occurs during opening. * @param {function} callback calls this function when the process finishes, will return an error object * if the opening process fail. * @method */ this.open = function open( /*function*/ callback, attempt ) { kvLogger.info('Store open'); callback = callback || function(){}; if (typeof attempt === 'undefined') attempt = 1; else attempt++; if (isConnected) { kvLogger.error(Errors.ALREADY_CONNECTED); callback(new Error(Errors.ALREADY_CONNECTED)); callback = null; self.emit('error', new Error(Errors.ALREADY_CONNECTED)); return; } if (attempt > proxyConf.connectionAttempts) { kvLogger.error(Errors.CONNECTION_ATTEMPTS); callback(new Error(Errors.CONNECTION_ATTEMPTS)); callback = null; self.emit('error', new Error(Errors.CONNECTION_ATTEMPTS)); return; } kvLogger.debug('Attempt to open: ' + attempt); kvLogger.info('Setting client'); setClient(function (err) { if (err) { if (proxyConf.startProxy) Proxy.startProxy(proxyConf, function (err) { self.open(callback, attempt); }); else { kvLogger.error(Errors.PROXY_CONNECTION_ERROR); callback(new Error(Errors.PROXY_CONNECTION_ERROR)); callback = null; self.emit('error', new Error(Errors.PROXY_CONNECTION_ERROR)); } } else { verify(function (err) { // verify failed if (err) { kvLogger.error(Errors.PROXY_VERIFY_ERROR); callback(err); callback = null; self.emit('error', err); } else { kvLogger.debug('Store connected to proxy'); isConnected = true; callback(); callback = null; self.emit('open'); } }); } }); }; /** * Closes the connection. */ this.close = function () { kvLogger.info('Store close'); if (isConnected) { thriftConnection.end(); isConnected = false; self.emit('close'); } }; /** * Attempt to shutdown the proxy related to the configuration of this Store */ this.shutdownProxy = function (callback) { self.close(); Proxy.stopProxy(proxyConf, callback ); }; /** * 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 {function} callback a function that is called when the process finish. * */ this.get = function ( /*String*/ tableName, /*Object*/ primaryKey, /*ReadOptions*/ readOptions, /*function*/ callback) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } var _primaryKey; if (primaryKey) _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); thriftClient.get(tableName, _primaryKey, readOptions, function (err, response) { if (kvLogger.logLevel >= LOG_LEVELS.DEBUG) // avoid unnecessary call kvLogger.debug('Return from get with err:' + err); if (err) err = new Error(err); // return an Error object if (response) response.currentRow = Parse(response.currentRow.jsonRow); callback(err, response); }); }; /** * Returns the rows associated with a partial primary key in an atomic manner. Rows are returned in primary key order. * The key used must ontain 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 {FieldRange} fieldRange The FieldRange to be used to restrict the range of the operation. * @param {Array} includedTables The list of tables to be included in an operation that returns * multiple rows or keys. * @param {ReadOptions} readOptions non-default options for the operation or null to get default behavior. * @param {function} callback a function that is called when the process finish. */ this.multiGet = function ( /*String*/ tableName, /*Object*/ primaryKey, /*FieldRange*/ fieldRange, /*Array*/ includedTables, /*ReadOptions*/ readOptions, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } var _primaryKey; if (primaryKey) _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); thriftClient.multiGet(tableName, _primaryKey, fieldRange, includedTables, readOptions, function (err, response) { if (err) err = new Error(err); // return an Error object if (response) { for (var index = 0; index < response.rowsWithMetadata.length; index++) { response.rowsWithMetadata[index].row = Parse(response.rowsWithMetadata[index].jsonRow); delete response.rowsWithMetadata[index].jsonRow; } } callback(err, response); }); }; /** * Return 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 {FieldRange} fieldRange The FieldRange to be used to restrict the range of the operation. * @param {Array} 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} readOptions non-default options for the operation or null to get default behavior. * @param {function} callback a function that is called when the process finish. */ this.multiGetKeys = function ( /*String*/ tableName, /*Object*/ primaryKey, /*FieldRange*/ fieldRange, /*Array*/ includedTables, /*ReadOptions*/ readOptions, /*function*/ callback) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } var _primaryKey; if (primaryKey) _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); thriftClient.multiGetKeys(tableName, _primaryKey, fieldRange, includedTables, readOptions, function (err, response) { if (err) err = new Error(err); // return an Error object if (response) { for (var index = 0; index < response.rowsWithMetadata.length; index++) { response.rowsWithMetadata[index].key = Parse(response.rowsWithMetadata[index].jsonRow); delete response.rowsWithMetadata[index].jsonRow; } } callback(err, response); }); }; /** * 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 {function} callback a function that is called when the process finish. */ this.put = function ( /*String*/ tableName, /*Object*/ row, /*WriteOptions*/ writeOptions, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } var _row = new ttypes.TRow({ jsonRow: Stringify(row) }); thriftClient.put(tableName, _row, writeOptions, function (err, response) { if (kvLogger.logLevel >= LOG_LEVELS.DEBUG) // avoid unnecessary call kvLogger.debug('Return from put with err:' + err); if (err) err = new Error(err); // return an Error object if (response) response.previousRow = Parse(response.previousRow.jsonRow); callback(err, response); }); }; /** * 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 behaviour. * @param {function} callback a function that is called when the process finish. */ this.putIfAbsent = function ( /*String*/ tableName, /*Object*/ row, /*WriteOptions*/ writeOptions, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } var _row = new ttypes.TRow({ jsonRow: Stringify(row) }); thriftClient.putIfAbsent(tableName, _row, writeOptions, function (err, response) { if (kvLogger.logLevel >= LOG_LEVELS.DEBUG) // avoid unnecessary call kvLogger.debug('Return from putIfAbsent with err:' + err); if (err) err = new Error(err); // return an Error object if (response) response.previousRow = Parse(response.previousRow.jsonRow); callback(err, response); }); }; /** * 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 behaviour. * @param {function} callback a function that is called when the process finish. */ this.putIfPresent = function ( /*String*/ tableName, /*Object*/ row, /*WriteOptions*/ writeOptions, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } var _row = new ttypes.TRow({ jsonRow: Stringify(row) }); thriftClient.putIfPresent(tableName, _row, writeOptions, function (err, response) { if (kvLogger.logLevel >= LOG_LEVELS.DEBUG) // avoid unnecessary call kvLogger.debug('Return from putIfPresent with err:' + err); if (err) err = new Error(err); // return an Error object if (response) response.previousRow = Parse(response.previousRow.jsonRow); callback(err, response); }); }; /** * 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 behaviour. * @param {function} callback a function that is called when the process finish. */ this.putIfVersion = function ( /*String*/ tableName, /*Object*/ row, /*Buffer*/ matchVersion, /*WriteOptions*/ writeOptions, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } var _row = new ttypes.TRow({ jsonRow: Stringify(row) }); thriftClient.putIfVersion(tableName, _row, matchVersion, writeOptions, function (err, response) { if (kvLogger.logLevel >= LOG_LEVELS.DEBUG) // avoid unnecessary call kvLogger.debug('Return from putIfVersion with err:' + err); if (err) err = new Error(err); // return an Error object if (response) response.previousRow = Parse(response.previousRow.jsonRow); callback(err, response); }); }; /** * 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 {function} callback a function that is called when the process finish. */ this.deleteRow = function ( /*String*/ tableName, /*Object*/ primaryKey, /*WriteOptions*/ writeOptions, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } var _primaryKey; if (primaryKey) _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); thriftClient.deleteRow(tableName, _primaryKey, writeOptions, function (err, response) { if (kvLogger.logLevel >= LOG_LEVELS.DEBUG) // avoid unnecessary call kvLogger.debug('Return from deleteRow with err:' + err); if (err) err = new Error(err); // return an Error object if (response) response.previousRow = Parse(response.previousRow.jsonRow); callback(err, response); }); }; /** * 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 {Buffer} matchVersion the version to match. * @param {WriteOptions} writeOptions non-default arguments controlling the Durability of the operation, * or null to get default behaviour. * @param {function} callback a function that is called when the process finish. */ this.deleteRowIfVersion = function ( /*String*/ tableName, /*Object*/ primaryKey, /*Buffer*/ matchVersion, /*WriteOptions*/ writeOptions, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } var _primaryKey; if (primaryKey) _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); thriftClient.deleteRowIfVersion(tableName, _primaryKey, matchVersion, writeOptions, function (err, response) { if (kvLogger.logLevel >= LOG_LEVELS.DEBUG) // avoid unnecessary call kvLogger.debug('Return from deleteRowIfVersion with err:' + err); if (err) err = new Error(err); // return an Error object if (response) response.previousRow = Parse(response.previousRow.jsonRow); callback(err, response); }); }; /** * 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 {FieldRange} fieldRange The FieldRange to be used to restrict the range of the operation. * @param {Array} includedTables The list of tables to be included in an operation that returns * multiple rows or keys. * @param {WriteOptions} writeOptions non-default arguments controlling the Durability of the operation, * or null to get default behaviour. * @param {function} callback a function that is called when the process finish. */ this.multiDelete = function ( /*String*/ tableName, /*Object*/ primaryKey, /*FieldRange*/ fieldRange, /*Array*/ includedTables, /*WriteOptions*/ writeOptions, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } var _primaryKey; if (primaryKey) _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); return thriftClient.multiDelete(tableName, _primaryKey, fieldRange, includedTables, writeOptions, function (err, response) { if (kvLogger.logLevel >= LOG_LEVELS.DEBUG) // avoid unnecessary call kvLogger.debug('Return from multiDelete with err:' + err); if (err) err = new Error(err); // return an Error object callback(err, response); }); }; /** * 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 {FieldRange} fieldRange The FieldRange to be used to restrict the range of the operation. * @param {Array} includedTables The list of tables to be included in an operation that returns * multiple rows or keys. * @param {ReadOptions} readOptions non-default options for the operation or null to get default behavior. * @param {Direction} direction The Direction for this operation. If the primary key contains a complete shard key * both Direction.FORWARD and Direction.REVERSE are allowed. * @param {function} callback a function that is called when the process finish. */ this.tableIterator = function tableIterator( /*String*/ tableName, /*Object*/ primaryKey, /*FieldRange*/ fieldRange, /*Array*/ includedTables, /*ReadOptions*/ readOptions, /*Direction*/ direction, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } primaryKey = primaryKey || {}; var _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); thriftClient.tableIterator( tableName, _primaryKey, fieldRange, includedTables, readOptions, direction, configuration.iteratorBufferSize, function (err, result) { if (err) callback(err); else callback(null, new Iterator(thriftClient, result)); }); }; /** * 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 {FieldRange} fieldRange The FieldRange to be used to restrict the range of the operation. * @param {Array} includedTables The list of tables to be included in an operation that returns * multiple rows or keys. * @param {ReadOptions} readOptions non-default options for the operation or null to get default behavior. * @param {Direction} direction The Direction for this operation. If the primary key contains a complete shard key * both Direction.FORWARD and Direction.REVERSE are allowed. * @param {function} callback a function that is called when the process finish. */ this.tableKeyIterator = function ( /*String*/ tableName, /*Object*/ primaryKey, /*FieldRange*/ fieldRange, /*Array*/ includedTables, /*ReadOptions*/ readOptions, /*Direction*/ direction, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } primaryKey = primaryKey || {}; var _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); thriftClient.tableKeyIterator( tableName, _primaryKey, fieldRange, includedTables, readOptions, direction, configuration.iteratorBufferSize, function (err, result) { if (err) callback(err); else callback(null, new Iterator(thriftClient, result)); }); }; /** * 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 paramter. 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} primaryKey the primary key for a table. It must be a complete primary key, with all fields set. * @param {FieldRange} fieldRange The FieldRange to be used to restrict the range of the operation. * @param {Array} includedTables The list of tables to be included in an operation that returns * multiple rows or keys. * @param {ReadOptions} readOptions non-default options for the operation or null to get default behavior. * @param {Direction} direction The Direction for this operation. If the primary key contains a complete shard key * both Direction.FORWARD and Direction.REVERSE are allowed. * @param {function} callback a function that is called when the process finish. */ this.indexIterator = function ( /*String*/ tableName, /*String*/ indexName, /*Object*/ primaryKey, /*FieldRange*/ fieldRange, /*Array*/ includedTables, /*ReadOptions*/ readOptions, /*Direction*/ direction, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } primaryKey = primaryKey || {}; var _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); thriftClient.indexIterator( tableName, indexName, _primaryKey, fieldRange, includedTables, readOptions, direction, configuration.iteratorBufferSize, function (err, result) { if (err) callback(err); else callback(null, new Iterator(thriftClient, result)); }); }; /** * Return the keys for matching rows associated with an index key. The iterator 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 paramter. 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} primaryKey the primary key for a table. It must be a complete primary key, with all fields set. * @param {FieldRange} fieldRange The FieldRange to be used to restrict the range of the operation. * @param {Array} includedTables The list of tables to be included in an operation that returns * multiple rows or keys. * @param {ReadOptions} readOptions non-default options for the operation or null to get default behavior. * @param {Direction} direction The Direction for this operation. If the primary key contains a complete shard key * both Direction.FORWARD and Direction.REVERSE are allowed. * @param {function} callback a function that is called when the process finish. */ this.indexKeyIterator = function ( /*String*/ tableName, /*String*/ indexName, /*Object*/ primaryKey, /*FieldRange*/ fieldRange, /*Array*/ includedTables, /*ReadOptions*/ readOptions, /*Direction*/ direction, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } primaryKey = primaryKey || {}; var _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); thriftClient.indexKeyIterator( tableName, indexName, _primaryKey, fieldRange, includedTables, readOptions, direction, configuration.iteratorBufferSize, function (err, result) { if (err) callback(err); else callback(null, new Iterator(thriftClient, result)); }); }; /** * Refreshes cached information about the tables. This method is * required before using any tables that had been modified. */ this.refreshTables = function(callback) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); } thriftClient.refreshTables(function(err) { callback(err); }); }; /** * 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 {function} callback a function that is called when the process finish. */ this.execute = function ( /*String*/ statement, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); } thriftClient.executeSync(statement, function(err, result){ callback(err, result); }) }; /** * Executes a table statement in the server asynchronously. * Currently, table statements can be used to create or modify tables and indices. * The operation is asynchronous in server side and may not be finished when * the method call the callback function. * * A execution identifier is returned and can be used to get * information about the status of the operation. * * If the statement is for an administrative command, and the store is * currently executing an administrative command that is the logical * equivalent the action specified by the statement, the method will * return a execution identifier that serves as a handle to that * operation, rather than starting a new invocation of the command. * * @param {String} statement the statement to be performed. * @param {function} callback a function that is called when the process finish. */ this.executeAsync = function ( /*String*/ statement, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); } thriftClient.execute(statement, function(err, result){ callback(err, result); }) }; /** * Attempts to cancel execution of a statement, execution identifier * of the statement must be provided. Return false if the * statement couldn't be cancelled, possibly because it has already * finished. If the statement hasn't succeeded already, and can be stopped, * the operation will transition to the FAILED state. * @param {Number} statement the statement to be performed. * @param {function} callback a function that is called when the process finish. */ this.executeCancel = function ( /*Number*/ planId, /*Bool*/ interruptIfRunning, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); } thriftClient.executionFutureCancel(planId, interruptIfRunning, function(err, result){ callback(err, result); }); }; /** * Callback until the command represented by a execution identifier completes. * Returns information about the execution of the statement. * This call will result in communication with the kvstore server. */ this.executeCallback = function ( /*Number*/ planId, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); } thriftClient.executionFutureGet(planId, function(err, result){ callback(err, result); }); }; /** * Callback until the command represented by a execution identifier completes * or the timeout period is exceeded. * This call will result in communication with the kvstore server. */ this.executeTimeout = function ( /*Number*/ planId, /*Number*/ timeout, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); } thriftClient.executionFutureGetTimeout(planId, timeout, function(err, result){ callback(err, result); }); }; /** * Returns information about the execution of the statement. If the * statement is still executing, this call will result in communication * with the kvstore server to obtain up to date status, and the status * returned will reflect interim information. */ this.executeStatus = function ( /*Number*/ planId, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); } thriftClient.executionFutureUpdateStatus(planId, function(err, result){ callback(err, result); }); }; /** * 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. */ this.executeOperations = function ( /*Array*/ operations, /*WriteOptions*/ writeOptions, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); } if (typeof operations !== 'array') { operations = [operations]; } thriftClient.executeUpdates(operations, writeOptions, function(err, result){ if (result) for(var row in result) { if (result[row].previousRow.jsonRow) result[row].previousRow = Parse(result[row].previousRow.jsonRow); } callback(err, result); }); }; /** * 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 {FieldRange} fieldRange The FieldRange to be used to restrict the range of the operation. * @param {Array} includedTables The list of tables to be included in an operation that returns * multiple rows or keys. * @param {ReadOptions} readOptions non-default options for the operation or null to get default behavior. * @param {Direction} direction The Direction for this operation. If the primary key contains a complete shard key * both Direction.FORWARD and Direction.REVERSE are allowed. * @param {function} callback a function that is called when the process finish. */ this.tableStream = function tableStream( /*String*/ tableName, /*Object*/ primaryKey, /*FieldRange*/ fieldRange, /*Array*/ includedTables, /*ReadOptions*/ readOptions, /*Direction*/ direction, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } primaryKey = primaryKey || {}; var _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); thriftClient.tableIterator( tableName, _primaryKey, fieldRange, includedTables, readOptions, direction, configuration.iteratorBufferSize, function (err, result) { if (err) callback(err); else callback(null, new Readable(thriftClient, 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 {FieldRange} fieldRange The FieldRange to be used to restrict the range of the operation. * @param {Array} includedTables The list of tables to be included in an operation that returns * multiple rows or keys. * @param {ReadOptions} readOptions non-default options for the operation or null to get default behavior. * @param {Direction} direction The Direction for this operation. If the primary key contains a complete shard key * both Direction.FORWARD and Direction.REVERSE are allowed. * @param {function} callback a function that is called when the process finish. */ this.tableKeyStream = function ( /*String*/ tableName, /*Object*/ primaryKey, /*FieldRange*/ fieldRange, /*Array*/ includedTables, /*ReadOptions*/ readOptions, /*Direction*/ direction, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } primaryKey = primaryKey || {}; var _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); thriftClient.tableKeyIterator( tableName, _primaryKey, fieldRange, includedTables, readOptions, direction, configuration.iteratorBufferSize, function (err, result) { if (err) callback(err); else callback(null, new Readable(thriftClient, 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 paramter. 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} primaryKey the primary key for a table. It must be a complete primary key, with all fields set. * @param {FieldRange} fieldRange The FieldRange to be used to restrict the range of the operation. * @param {Array} includedTables The list of tables to be included in an operation that returns * multiple rows or keys. * @param {ReadOptions} readOptions non-default options for the operation or null to get default behavior. * @param {Direction} direction The Direction for this operation. If the primary key contains a complete shard key * both Direction.FORWARD and Direction.REVERSE are allowed. * @param {function} callback a function that is called when the process finish. */ this.indexStream = function ( /*String*/ tableName, /*String*/ indexName, /*Object*/ primaryKey, /*FieldRange*/ fieldRange, /*Array*/ includedTables, /*ReadOptions*/ readOptions, /*Direction*/ direction, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } primaryKey = primaryKey || {}; var _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); thriftClient.indexIterator( tableName, indexName, _primaryKey, fieldRange, includedTables, readOptions, direction, configuration.iteratorBufferSize, function (err, result) { if (err) callback(err); else callback(null, new Readable(thriftClient, result)); }); }; /** * Return a Readable Stream with the keys 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 paramter. 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} primaryKey the primary key for a table. It must be a complete primary key, with all fields set. * @param {FieldRange} fieldRange The FieldRange to be used to restrict the range of the operation. * @param {Array} includedTables The list of tables to be included in an operation that returns * multiple rows or keys. * @param {ReadOptions} readOptions non-default options for the operation or null to get default behavior. * @param {Direction} direction The Direction for this operation. If the primary key contains a complete shard key * both Direction.FORWARD and Direction.REVERSE are allowed. * @param {function} callback a function that is called when the process finish. */ this.indexKeyStream = function ( /*String*/ tableName, /*String*/ indexName, /*Object*/ primaryKey, /*FieldRange*/ fieldRange, /*Array*/ includedTables, /*ReadOptions*/ readOptions, /*Direction*/ direction, /*function*/ callback ) { callback = callback || function(){}; if (!isConnected) { callback(new Error(Errors.NOT_CONNECTED)); return; } primaryKey = primaryKey || {}; var _primaryKey = new ttypes.TRow({ jsonRow: Stringify(primaryKey) }); thriftClient.indexKeyIterator( tableName, indexName, _primaryKey, fieldRange, includedTables, readOptions, direction, configuration.iteratorBufferSize, function (err, result) { if (err) callback(err); else callback(null, new Readable(thriftClient, result)); }); }; } //EOF