You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
619 lines
14 KiB
JavaScript
619 lines
14 KiB
JavaScript
/*
|
|
* Copyright DataStax, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const utils = require('./utils');
|
|
const types = require('./types');
|
|
const errors = require('./errors');
|
|
|
|
const proxyExecuteKey = 'ProxyExecute';
|
|
|
|
/**
|
|
* A base class that represents a wrapper around the user provided query options with getter methods and proper
|
|
* default values.
|
|
* <p>
|
|
* Note that getter methods might return <code>undefined</code> when not set on the query options or default
|
|
* {@link Client} options.
|
|
* </p>
|
|
*/
|
|
class ExecutionOptions {
|
|
|
|
/**
|
|
* Creates a new instance of {@link ExecutionOptions}.
|
|
*/
|
|
constructor() {
|
|
}
|
|
|
|
/**
|
|
* Creates an empty instance, where all methods return undefined, used internally.
|
|
* @ignore
|
|
* @return {ExecutionOptions}
|
|
*/
|
|
static empty() {
|
|
return new ExecutionOptions();
|
|
}
|
|
|
|
/**
|
|
* Determines if the stack trace before the query execution should be maintained.
|
|
* @abstract
|
|
* @returns {Boolean}
|
|
*/
|
|
getCaptureStackTrace() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the [Consistency level]{@link module:types~consistencies} to be used for the execution.
|
|
* @abstract
|
|
* @returns {Number}
|
|
*/
|
|
getConsistency() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Key-value payload to be passed to the server. On the server side, implementations of QueryHandler can use
|
|
* this data.
|
|
* @abstract
|
|
* @returns {Object}
|
|
*/
|
|
getCustomPayload() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the amount of rows to retrieve per page.
|
|
* @abstract
|
|
* @returns {Number}
|
|
*/
|
|
getFetchSize() {
|
|
|
|
}
|
|
|
|
/**
|
|
* When a fixed host is set on the query options and the query plan for the load-balancing policy is not used, it
|
|
* gets the host that should handle the query.
|
|
* @returns {Host}
|
|
*/
|
|
getFixedHost() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the type hints for parameters given in the query, ordered as for the parameters.
|
|
* @abstract
|
|
* @returns {Array|Array<Array>}
|
|
*/
|
|
getHints() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Determines whether the driver must retrieve the following result pages automatically.
|
|
* <p>
|
|
* This setting is only considered by the [Client#eachRow()]{@link Client#eachRow} method.
|
|
* </p>
|
|
* @abstract
|
|
* @returns {Boolean}
|
|
*/
|
|
isAutoPage() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Determines whether its a counter batch. Only valid for [Client#batch()]{@link Client#batch}, it will be ignored by
|
|
* other methods.
|
|
* @abstract
|
|
* @returns {Boolean} A <code>Boolean</code> value, it can't be <code>undefined</code>.
|
|
*/
|
|
isBatchCounter() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Determines whether the batch should be written to the batchlog. Only valid for
|
|
* [Client#batch()]{@link Client#batch}, it will be ignored by other methods.
|
|
* @abstract
|
|
* @returns {Boolean} A <code>Boolean</code> value, it can't be <code>undefined</code>.
|
|
*/
|
|
isBatchLogged() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Determines whether the query can be applied multiple times without changing the result beyond the initial
|
|
* application.
|
|
* @abstract
|
|
* @returns {Boolean}
|
|
*/
|
|
isIdempotent() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Determines whether the query must be prepared beforehand.
|
|
* @abstract
|
|
* @returns {Boolean} A <code>Boolean</code> value, it can't be <code>undefined</code>.
|
|
*/
|
|
isPrepared() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Determines whether query tracing is enabled for the execution.
|
|
* @abstract
|
|
* @returns {Boolean}
|
|
*/
|
|
isQueryTracing() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the keyspace for the query when set at query options level.
|
|
* <p>
|
|
* Note that this method will return <code>undefined</code> when the keyspace is not set at query options level.
|
|
* It will only return the keyspace name when the user provided a different keyspace than the current
|
|
* {@link Client} keyspace.
|
|
* </p>
|
|
* @abstract
|
|
* @returns {String}
|
|
*/
|
|
getKeyspace() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the load balancing policy used for this execution.
|
|
* @returns {LoadBalancingPolicy} A <code>LoadBalancingPolicy</code> instance, it can't be <code>undefined</code>.
|
|
*/
|
|
getLoadBalancingPolicy() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the Buffer representing the paging state.
|
|
* @abstract
|
|
* @returns {Buffer}
|
|
*/
|
|
getPageState() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Internal method that gets the preferred host.
|
|
* @abstract
|
|
* @ignore
|
|
*/
|
|
getPreferredHost() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the query options as provided to the execution method without setting the default values.
|
|
* @returns {QueryOptions}
|
|
*/
|
|
getRawQueryOptions() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the timeout in milliseconds to be used for the execution per coordinator.
|
|
* <p>
|
|
* A value of <code>0</code> disables client side read timeout for the execution. Default: <code>undefined</code>.
|
|
* </p>
|
|
* @abstract
|
|
* @returns {Number}
|
|
*/
|
|
getReadTimeout() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the [retry policy]{@link module:policies/retry} to be used.
|
|
* @abstract
|
|
* @returns {RetryPolicy} A <code>RetryPolicy</code> instance, it can't be <code>undefined</code>.
|
|
*/
|
|
getRetryPolicy() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Internal method to obtain the row callback, for "by row" results.
|
|
* @abstract
|
|
* @ignore
|
|
*/
|
|
getRowCallback() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Internal method to get or generate a timestamp for the request execution.
|
|
* @ignore
|
|
* @returns {Long|null}
|
|
*/
|
|
getOrGenerateTimestamp() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the index of the parameters that are part of the partition key to determine the routing.
|
|
* @abstract
|
|
* @ignore
|
|
* @returns {Array}
|
|
*/
|
|
getRoutingIndexes() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the partition key(s) to determine which coordinator should be used for the query.
|
|
* @abstract
|
|
* @returns {Buffer|Array<Buffer>}
|
|
*/
|
|
getRoutingKey() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the array of the parameters names that are part of the partition key to determine the
|
|
* routing. Only valid for non-prepared requests.
|
|
* @abstract
|
|
* @ignore
|
|
*/
|
|
getRoutingNames() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the the consistency level to be used for the serial phase of conditional updates.
|
|
* @abstract
|
|
* @returns {Number}
|
|
*/
|
|
getSerialConsistency() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the provided timestamp for the execution in microseconds from the unix epoch (00:00:00, January 1st, 1970).
|
|
* <p>When a timestamp generator is used, this method returns <code>undefined</code>.</p>
|
|
* @abstract
|
|
* @returns {Number|Long|undefined|null}
|
|
*/
|
|
getTimestamp() {
|
|
|
|
}
|
|
|
|
/**
|
|
* @param {Array} hints
|
|
* @abstract
|
|
* @ignore
|
|
*/
|
|
setHints(hints) {
|
|
|
|
}
|
|
|
|
/**
|
|
* Sets the keyspace for the execution.
|
|
* @ignore
|
|
* @abstract
|
|
* @param {String} keyspace
|
|
*/
|
|
setKeyspace(keyspace) {
|
|
|
|
}
|
|
|
|
/**
|
|
* @abstract
|
|
* @ignore
|
|
*/
|
|
setPageState() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Internal method that sets the preferred host.
|
|
* @abstract
|
|
* @ignore
|
|
*/
|
|
setPreferredHost() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Sets the index of the parameters that are part of the partition key to determine the routing.
|
|
* @param {Array} routingIndexes
|
|
* @abstract
|
|
* @ignore
|
|
*/
|
|
setRoutingIndexes(routingIndexes) {
|
|
|
|
}
|
|
|
|
/**
|
|
* Sets the routing key.
|
|
* @abstract
|
|
* @ignore
|
|
*/
|
|
setRoutingKey(value) {
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Internal implementation of {@link ExecutionOptions} that uses the value from the client options and execution
|
|
* profile into account.
|
|
* @ignore
|
|
*/
|
|
class DefaultExecutionOptions extends ExecutionOptions {
|
|
/**
|
|
* Creates a new instance of {@link ExecutionOptions}.
|
|
* @param {QueryOptions} queryOptions
|
|
* @param {Client} client
|
|
* @param {Function|null} rowCallback
|
|
*/
|
|
constructor(queryOptions, client, rowCallback) {
|
|
super();
|
|
|
|
this._queryOptions = queryOptions;
|
|
this._rowCallback = rowCallback;
|
|
this._routingKey = this._queryOptions.routingKey;
|
|
this._hints = this._queryOptions.hints;
|
|
this._keyspace = this._queryOptions.keyspace;
|
|
this._routingIndexes = this._queryOptions.routingIndexes;
|
|
this._pageState = typeof this._queryOptions.pageState === 'string' ?
|
|
utils.allocBufferFromString(this._queryOptions.pageState, 'hex') : this._queryOptions.pageState;
|
|
this._preferredHost = null;
|
|
|
|
this._client = client;
|
|
this._defaultQueryOptions = client.options.queryOptions;
|
|
this._profile = client.profileManager.getProfile(this._queryOptions.executionProfile);
|
|
|
|
// Build a custom payload object designed for DSE-specific functionality
|
|
this._customPayload = DefaultExecutionOptions.createCustomPayload(this._queryOptions, this._defaultQueryOptions);
|
|
|
|
if (!this._profile) {
|
|
throw new errors.ArgumentError(`Execution profile "${this._queryOptions.executionProfile}" not found`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a payload for given user.
|
|
* @param {QueryOptions} userOptions
|
|
* @param {QueryOptions} defaultQueryOptions
|
|
* @private
|
|
*/
|
|
static createCustomPayload(userOptions, defaultQueryOptions) {
|
|
let customPayload = userOptions.customPayload || defaultQueryOptions.customPayload;
|
|
const executeAs = userOptions.executeAs || defaultQueryOptions.executeAs;
|
|
|
|
if (executeAs) {
|
|
if (!customPayload) {
|
|
customPayload = {};
|
|
customPayload[proxyExecuteKey] = utils.allocBufferFromString(executeAs);
|
|
} else if (!customPayload[proxyExecuteKey]) {
|
|
// Avoid appending to the existing payload object
|
|
customPayload = utils.extend({}, customPayload);
|
|
customPayload[proxyExecuteKey] = utils.allocBufferFromString(executeAs);
|
|
}
|
|
}
|
|
|
|
return customPayload;
|
|
}
|
|
|
|
/**
|
|
* Creates a new instance {@link ExecutionOptions}, based on the query options.
|
|
* @param {QueryOptions|null} queryOptions
|
|
* @param {Client} client
|
|
* @param {Function|null} [rowCallback]
|
|
* @ignore
|
|
* @return {ExecutionOptions}
|
|
*/
|
|
static create(queryOptions, client, rowCallback) {
|
|
if (!queryOptions || typeof queryOptions === 'function') {
|
|
// queryOptions can be null/undefined and could be of type function when is an optional parameter
|
|
queryOptions = utils.emptyObject;
|
|
}
|
|
return new DefaultExecutionOptions(queryOptions, client, rowCallback);
|
|
}
|
|
|
|
getCaptureStackTrace() {
|
|
return ifUndefined(this._queryOptions.captureStackTrace, this._defaultQueryOptions.captureStackTrace);
|
|
}
|
|
|
|
getConsistency() {
|
|
return ifUndefined3(this._queryOptions.consistency, this._profile.consistency,
|
|
this._defaultQueryOptions.consistency);
|
|
}
|
|
|
|
getCustomPayload() {
|
|
return this._customPayload;
|
|
}
|
|
|
|
getFetchSize() {
|
|
return ifUndefined(this._queryOptions.fetchSize, this._defaultQueryOptions.fetchSize);
|
|
}
|
|
|
|
getFixedHost() {
|
|
return this._queryOptions.host;
|
|
}
|
|
|
|
getHints() {
|
|
return this._hints;
|
|
}
|
|
|
|
isAutoPage() {
|
|
return ifUndefined(this._queryOptions.autoPage, this._defaultQueryOptions.autoPage);
|
|
}
|
|
|
|
isBatchCounter() {
|
|
return ifUndefined(this._queryOptions.counter, false);
|
|
}
|
|
|
|
isBatchLogged() {
|
|
return ifUndefined3(this._queryOptions.logged, this._defaultQueryOptions.logged, true);
|
|
}
|
|
|
|
isIdempotent() {
|
|
return ifUndefined(this._queryOptions.isIdempotent, this._defaultQueryOptions.isIdempotent);
|
|
}
|
|
|
|
/**
|
|
* Determines if the query execution must be prepared beforehand.
|
|
* @return {Boolean}
|
|
*/
|
|
isPrepared() {
|
|
return ifUndefined(this._queryOptions.prepare, this._defaultQueryOptions.prepare);
|
|
}
|
|
|
|
isQueryTracing() {
|
|
return ifUndefined(this._queryOptions.traceQuery, this._defaultQueryOptions.traceQuery);
|
|
}
|
|
|
|
getKeyspace() {
|
|
return this._keyspace;
|
|
}
|
|
|
|
getLoadBalancingPolicy() {
|
|
return this._profile.loadBalancing;
|
|
}
|
|
|
|
getOrGenerateTimestamp() {
|
|
let result = this.getTimestamp();
|
|
|
|
if (result === undefined) {
|
|
const generator = this._client.options.policies.timestampGeneration;
|
|
|
|
if ( types.protocolVersion.supportsTimestamp(this._client.controlConnection.protocolVersion) && generator) {
|
|
result = generator.next(this._client);
|
|
} else {
|
|
result = null;
|
|
}
|
|
}
|
|
|
|
return typeof result === 'number' ? types.Long.fromNumber(result) : result;
|
|
}
|
|
|
|
getPageState() {
|
|
return this._pageState;
|
|
}
|
|
|
|
/**
|
|
* Gets the profile defined by the user or the default profile
|
|
* @internal
|
|
* @ignore
|
|
*/
|
|
getProfile() {
|
|
return this._profile;
|
|
}
|
|
|
|
getRawQueryOptions() {
|
|
return this._queryOptions;
|
|
}
|
|
|
|
getReadTimeout() {
|
|
return ifUndefined3(this._queryOptions.readTimeout, this._profile.readTimeout,
|
|
this._client.options.socketOptions.readTimeout);
|
|
}
|
|
|
|
getRetryPolicy() {
|
|
return ifUndefined3(this._queryOptions.retry, this._profile.retry, this._client.options.policies.retry);
|
|
}
|
|
|
|
getRoutingIndexes() {
|
|
return this._routingIndexes;
|
|
}
|
|
|
|
getRoutingKey() {
|
|
return this._routingKey;
|
|
}
|
|
|
|
getRoutingNames() {
|
|
return this._queryOptions.routingNames;
|
|
}
|
|
|
|
/**
|
|
* Internal method to obtain the row callback, for "by row" results.
|
|
* @ignore
|
|
*/
|
|
getRowCallback() {
|
|
return this._rowCallback;
|
|
}
|
|
|
|
getSerialConsistency() {
|
|
return ifUndefined3(
|
|
this._queryOptions.serialConsistency, this._profile.serialConsistency, this._defaultQueryOptions.serialConsistency);
|
|
}
|
|
|
|
getTimestamp() {
|
|
return this._queryOptions.timestamp;
|
|
}
|
|
|
|
/**
|
|
* Internal property to set the custom payload.
|
|
* @ignore
|
|
* @internal
|
|
* @param {Object} payload
|
|
*/
|
|
setCustomPayload(payload) {
|
|
this._customPayload = payload;
|
|
}
|
|
|
|
/**
|
|
* @param {Array} hints
|
|
*/
|
|
setHints(hints) {
|
|
this._hints = hints;
|
|
}
|
|
|
|
/**
|
|
* @param {String} keyspace
|
|
*/
|
|
setKeyspace(keyspace) {
|
|
this._keyspace = keyspace;
|
|
}
|
|
|
|
/**
|
|
* @param {Buffer} pageState
|
|
*/
|
|
setPageState(pageState) {
|
|
this._pageState = pageState;
|
|
}
|
|
|
|
/**
|
|
* @param {Array} routingIndexes
|
|
*/
|
|
setRoutingIndexes(routingIndexes) {
|
|
this._routingIndexes = routingIndexes;
|
|
}
|
|
|
|
setRoutingKey(value) {
|
|
this._routingKey = value;
|
|
}
|
|
}
|
|
|
|
function ifUndefined(v1, v2) {
|
|
return v1 !== undefined ? v1 : v2;
|
|
}
|
|
|
|
function ifUndefined3(v1, v2, v3) {
|
|
if (v1 !== undefined) {
|
|
return v1;
|
|
}
|
|
return v2 !== undefined ? v2 : v3;
|
|
}
|
|
|
|
module.exports = { ExecutionOptions, DefaultExecutionOptions, proxyExecuteKey }; |