// *****************************************************************************
// Copyright 2021-2023 Aerospike, 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 as = require('bindings')('aerospike.node')
const exp = as.exp
const writeFlags = as.expWriteFlags
const readFlags = as.expReadFlags
const BIN_TYPE_UNDEF = 0
/**
* @module aerospike/exp
* @summary {@link module:aerospike/exp|aerospike/exp} module
*
* @description This module defines a filter expression that is
* a mechanism for additional filtering.
*
* The resultset of a primary index (PI) query (scan) or secondary
* index (SI) query operation can be filtered through the QueryPolicy
* and ScanPolicy classes. It can also filter single key operations and
* batch operations through the filterExpression field of their policy class.
*
* Filter Expressions replace PredicateExpression filtering,
* which was deprecated in server 5.2 and
* removed in server 6.0.
*
* @see {@link ReadPolicy#filterExpression}
* @see {@link OperatePolicy#filterExpression}
* @see {@link RemovePolicy#filterExpression}
* @see {@link WritePolicy#filterExpression}
* @see {@link BatchPolicy#filterExpression}
* @see {@link ScanPolicy#filterExpression}
* @see {@link QueryPolicy#filterExpression}
*
* @example
*
* <caption>Expressions using the operate API</caption>
* const Aerospike = require('aerospike')
* const op = Aerospike.operations
* const exp = Aerospike.exp
* const key = new Aerospike.Key('test', 'demo', 'mykey1')
* const tempBin = 'ExpVar' // this bin is to hold expression read operation output
*
* // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE!
* const config = {
* hosts: '192.168.33.10:3000',
* // Timeouts disabled, latency dependent on server location. Configure as needed.
* policies: {
* operate : new Aerospike.OperatePolicy({socketTimeout : 0, totalTimeout : 0}),
* write : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0})
* }
* }
*
* var ops = [
* op.append('a', 'xyz'),
* op.incr('b', 10),
* exp.operations.read(tempBin,
* exp.add(exp.binInt('b'), exp.binInt('b')),
* 0),
* op.read('a'),
* op.read('b')
* ]
*
* Aerospike.connect(config, (error, client) => {
* if (error) throw error
* client.put(key, { a: 'abc', b: 42 }, (error) => {
* if (error) throw error
* client.operate(key, ops, (error, record) => {
* if (error) throw error
* console.log(record.bins) // => { a: 'abcxyz', b: 52, ExpVar: 104 }
* client.close()
* })
* })
* })
*
* @example
*
* <caption>Expressions using the query API</caption>
* const Aerospike = require('aerospike')
* const op = Aerospike.operations
* const exp = Aerospike.exp
* const key = new Aerospike.Key('test', 'demo', 'mykey1')
* const tempBin = 'ExpVar' // this bin is to hold expression read operation output
*
* // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE!
* const config = {
* hosts: '192.168.33.10:3000',
* // Timeouts disabled, latency dependent on server location. Configure as needed.
* policies: {
* query : new Aerospike.QueryPolicy({socketTimeout : 0, totalTimeout : 0}),
* write : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0, exists : Aerospike.policy.exists.REPLACE})
* }
* }
*
* Aerospike.connect(config, (error, client) => {
* if (error) throw error
* client.put(key, { a: 'abc', b: 42 }, (error) => {
* if (error) throw error
* var query = client.query('test', 'demo')
* const queryPolicy = { filterExpression: exp.eq(exp.binInt('b'), exp.int(42))}
* query.nobins = false
* const stream = query.foreach(queryPolicy)
* stream.on('error', (error) => {
* console.error(error)
* throw error
* })
* stream.on('data', (record) => {
* console.info(record.bins) // => { a: 'abc', b: 42}
* })
* stream.on('end', () => {
* client.close()
* })
* })
* })
*
*/
/*********************************************************************************
* VALUE EXPRESSIONS
*********************************************************************************/
const _valueExp = (op, valName) => (value) => [{ op, [valName]: value }]
const _valueExpBytes = (op, valName, sizeName) => (value, size) => [{ op, [valName]: value, [sizeName]: size }]
/**
* Create boolean value.
*
* @function
* @param {boolean} value boolean value.
* @return {AerospikeExp}
*/
exports.bool = _valueExp(exp.ops.VAL_BOOL, 'boolVal')
/**
* Create 64 bit signed integer value.
*
* @function
* @param {number} number value integer value.
* @return {AerospikeExp}
*/
exports.int = _valueExp(exp.ops.VAL_INT, 'intVal')
const _int = exports.int
/**
* Create 64 bit unsigned integer value.
*
* @function
* @param {number} number value unsigned integer value.
* @return {AerospikeExp}
*/
exports.uint = _valueExp(exp.ops.VAL_UINT, 'uintVal')
/**
* Create 64 bit floating point value.
*
* @function
* @param {number} value floating point value.
* @return {AerospikeExp}
*/
exports.float = _valueExp(exp.ops.VAL_FLOAT, 'floatVal')
/**
* Create string value.
*
* @function
* @param {string} value string value.
* @return {AerospikeExp}
*/
exports.str = _valueExp(exp.ops.VAL_STR, 'strVal')
/**
* Create byte array value.
* *
* @function
* @param {string[]} value byte array value.
* @param {number} size number of bytes.
* @return {AerospikeExp}
*/
exports.bytes = _valueExpBytes(exp.ops.VAL_BYTES, 'bytesVal', 'sz')
/**
* Create geojson value.
*
* @function
* @param {Object} value geojson value.
* @return {AerospikeExp}
*/
exports.geo = _valueExp(exp.ops.VAL_GEO, 'value')
/**
* Create 'nil' value.
*
* @function
* @return {AerospikeExp}
*/
exports.nil = () => [{ op: exp.ops.AS_VAL, value: null }]
/**
* Create 'inf' value.
*
* @function
* @return {AerospikeExp}
*/
exports.inf = () => [{ op: exp.ops.AS_VAL, inf: null }]
/**
* Create 'wildcard' value.
*
* @function
* @return {AerospikeExp}
*/
exports.wildcard = () => [{ op: exp.ops.AS_VAL, wildcard: null }]
const _val = _valueExp(exp.ops.AS_VAL, 'value')
/**
* Create list value.
*
* @function
* @param {array} value list value
* @return {AerospikeExp}
*/
exports.list = _val
/**
* Create map value.
*
* @function
* @param {array} value map value
* @return {AerospikeExp}
*/
exports.map = _val
/*********************************************************************************
* KEY EXPRESSIONS
*********************************************************************************/
const _keyTypeExp = (type) => () => [
{ op: exp.ops.KEY, count: 2 },
..._int(type)
]
/**
* Create expression that returns the key as an integer. Returns 'unknown' if
* the key is not an integer.
*
* @function
* @param {number} integer value Integer value of the key if the key is an integer.
* @return {AerospikeExp}
*/
exports.keyInt = _keyTypeExp(exp.type.INT)
/**
* Create expression that returns the key as an string. Returns 'unknown' if
* the key is not a string.
*
* @function
* @param {string} string value String value of the key if the key is a string.
* @return {AerospikeExp}
*/
exports.keyStr = _keyTypeExp(exp.type.STR)
/**
* Create expression that returns the key as an blob. Returns 'unknown' if
* the key is not an blob.
*
* @function
* @param {Object} blob Blob value of the key if the key is a blob.
* @return {AerospikeExp}
*/
exports.keyBlob = _keyTypeExp(exp.type.BLOB)
/**
* Create expression that returns if the primary key is stored in the record meta
* data as a boolean expression. This would occur when "policy write key" is
* SEND on record write.
*
* @function
* @param {boolean} - value True if the record has a stored key, false otherwise.
* @return {AerospikeExp}
*/
exports.keyExist = () => [{ op: exp.ops.KEY_EXIST, count: 1 }]
/*********************************************************************************
* BIN EXPRESSIONS
*********************************************************************************/
const _rawStr = (value) => [{ op: exp.ops.VAL_RAWSTR, strVal: value }]
const _binTypeExp = (type) => (binName) => [
{ op: exp.ops.BIN, count: 3 },
..._int(type),
..._rawStr(binName)
]
/**
* Create expression that returns a bin as a boolean value. Returns 'unknown'
* if the bin is not a boolean.
*
* @function
* @param {string }binName Bin name.
* @return {AerospikeExp} boolean bin
*/
exports.binBool = _binTypeExp(exp.type.BOOL)
/**
* Create expression that returns a bin as a signed integer. Returns 'unknown'
* if the bin is not an integer.
*
* @function
* @param {string} binName Bin name.
* @return {AerospikeExp} integer bin
*/
exports.binInt = _binTypeExp(exp.type.INT)
/**
* Create expression that returns a bin as a float. Returns 'unknown' if the bin
* is not an float.
*
* @function
* @param {string} binName Bin name.
* @return {AerospikeExp} float bin
*/
exports.binFloat = _binTypeExp(exp.type.FLOAT)
/**
* Create expression that returns a bin as a string. Returns 'unknown' if the
* bin is not an string.
*
* @function
* @param {string} binName Bin name.
* @return {AerospikeExp} string bin
*/
exports.binStr = _binTypeExp(exp.type.STR)
/**
* Create expression that returns a bin as a blob. Returns 'unknown' if the bin
* is not an blob.
*
* @function
* @param {string} binName Bin name.
* @return {AerospikeExp} blob bin
*/
exports.binBlob = _binTypeExp(exp.type.BLOB)
/**
* Create expression that returns a bin as a geojson. Returns 'unknown' if the
* bin is not geojson.
*
* @function
* @param {string} binName Bin name.
* @return {AerospikeExp} geojson bin
*/
exports.binGeo = _binTypeExp(exp.type.GEOJSON)
/**
* Create expression that returns a bin as a list. Returns 'unknown' if the bin
* is not an list.
*
* @function
* @param {string} binName Bin name.
* @return {AerospikeExp} list bin
*/
exports.binList = _binTypeExp(exp.type.LIST)
/**
* Create expression that returns a bin as a map. Returns 'unknown' if the bin
* is not an map.
*
* @function
* @param {string} binName Bin name.
* @return {AerospikeExp} map bin
*/
exports.binMap = _binTypeExp(exp.type.MAP)
/**
* Create expression that returns a bin as a HyperLogLog (hll). Returns
* 'unknown' if the bin is not a HyperLogLog (hll).
*
* @function
* @param {string} binName Bin name.
* @return {AerospikeExp} hll bin
*/
exports.binHll = _binTypeExp(exp.type.HLL)
exports.binType = (binName) => [
{ op: exp.ops.BIN_TYPE, count: 2 },
..._rawStr(binName)
]
const _binType = exports.binType
/**
* Create expression that returns if bin of specified name exists.
*
* @function
* @param {string} binName Bin name.
* @return {boolean} - value True if the bin exists, false otherwise.
*/
exports.binExists = (binName) => _ne(_binType(binName), _int(BIN_TYPE_UNDEF))
/*********************************************************************************
* METADATA EXPRESSIONS
*********************************************************************************/
const _metaExp = (op) => () => [{ op, count: 1 }]
/**
* Create expression that returns record set name string. This expression usually
* evaluates quickly because record meta data is cached in memory.
*
* @function
* @return {AerospikeExp} string value Name of the set this record belongs to.
*/
exports.setName = _metaExp(exp.ops.SET_NAME)
/**
* Create expression that returns record size on disk. If server storage-engine is
* memory, then zero is returned. This expression usually evaluates quickly
* because record meta data is cached in memory.
* Requires server version between 5.3.0 inclusive and 7.0 exclusive.
* Use {@link #recordSize} for server version 7.0+.
*
* @function
* @return {AerospikeExp} integer value Uncompressed storage size of the record.
*/
exports.deviceSize = _metaExp(exp.ops.DEVICE_SIZE)
/**
* Create expression that returns record last update time expressed as 64 bit
* integer nanoseconds since 1970-01-01 epoch.
*
* @function
* @return {AerospikeExp} integer value When the record was last updated.
*/
exports.lastUpdate = _metaExp(exp.ops.LAST_UPDATE)
/**
* Create expression that returns milliseconds since the record was last updated.
* This expression usually evaluates quickly because record meta data is cached
* in memory.
*
* @function
* @return {AerospikeExp} integer value Number of milliseconds since last updated.
*/
exports.sinceUpdate = _metaExp(exp.ops.SINCE_UPDATE)
/**
* Create expression that returns record expiration time expressed as 64 bit
* integer nanoseconds since 1970-01-01 epoch.
*
* @function
* @return {AerospikeExp} integer value Expiration time in nanoseconds since 1970-01-01.
*/
exports.voidTime = _metaExp(exp.ops.VOID_TIME)
/**
* Create expression that returns record expiration time (time to live) in integer
* seconds.
*
* @function
* @return {AerospikeExp} integer value Number of seconds till the record will expire,
* returns -1 if the record never expires.
*/
exports.ttl = _metaExp(exp.ops.TTL)
/**
* Create expression that returns if record has been deleted and is still in
* tombstone state. This expression usually evaluates quickly because record
* meta data is cached in memory.
*
* @function
* @return {AerospikeExp} - value True if the record is a tombstone, false otherwise.
*/
exports.isTombstone = _metaExp(exp.ops.IS_TOMBSTONE)
/**
* Create expression that returns record size in memory when either the
* storage-engine is memory or data-in-memory is true, otherwise returns 0.
* This expression usually evaluates quickly because record meta data is cached
* in memory.
* Requires server version between 5.3.0 inclusive and 7.0 exclusive.
* Use {@link #recordSize} for server version 7.0+.
*
* @function
* @return {AerospikeExp} integer value memory size of the record.
*/
exports.memorySize = _metaExp(exp.ops.MEMORY_SIZE)
/**
* Create expression that returns the record size. This expression usually evaluates
* quickly because record meta data is cached in memory.
* Requires server version 7.0+. This expression replaces {@link #deviceSize} and
* {@link #memorySize} since those older expressions are equivalent on server version 7.0+.
*
* @function
* @return {AerospikeExp} integer value size of the record in Megabytes.
*/
exports.recordSize = _metaExp(exp.ops.RECORD_SIZE)
/**
* Create expression that returns record digest modulo as integer.
*
* @function
* @param {number} mod Divisor used to divide the digest to get a remainder.
* @return {AerospikeExp} integer value Value in range 0 and mod (exclusive)..
*/
exports.digestModulo = _metaExp(exp.ops.DIGEST_MODULO)
/*********************************************************************************
* COMPARISON EXPRESSIONS
*********************************************************************************/
const _cmpExp = (op) => (left, right) => [{ op, count: 3 }].concat(left, right)
/**
* Create equals (==) expression.
*
* @function
* @param {number} left left expression in comparison.
* @param {number} right right expression in comparison.
* @return {AerospikeExp} - boolean value
*/
exports.eq = _cmpExp(exp.ops.CMP_EQ)
/**
* Create not equal (!=) expression.
*
* @function
* @param {number} left left expression in comparison.
* @param {number} right right expression in comparison.
* @return {AerospikeExp} - boolean value
*/
exports.ne = _cmpExp(exp.ops.CMP_NE)
const _ne = exports.ne
/**
* Create a greater than (>) expression.
*
* @function
* @param {number} left left expression in comparison.
* @param {number} right right expression in comparison.
* @return {AerospikeExp} - boolean value
*/
exports.gt = _cmpExp(exp.ops.CMP_GT)
/**
* Create a greater than or equals (>=) expression.
*
* @function
* @param {number} left left expression in comparison.
* @param {number} right right expression in comparison.
* @return {AerospikeExp} - boolean value
*/
exports.ge = _cmpExp(exp.ops.CMP_GE)
/**
* Create a less than (<) expression.
*
* @function
* @param {number} left left expression in comparison.
* @param {number} right right expression in comparison.
* @return {AerospikeExp} - boolean value
*/
exports.lt = _cmpExp(exp.ops.CMP_LT)
/**
* Create a less than or equals (<=) expression.
*
* @function
* @param {number} left left expression in comparison.
* @param {number} right right expression in comparison.
* @return {AerospikeExp} - boolean value
*/
exports.le = _cmpExp(exp.ops.CMP_LE)
/**
* Create expression that performs a regex match on a string bin or value
* expression.
*
* @function
* @param {number} options POSIX regex flags defined in regex.h.
* @param {string} regex POSIX regex string.
* @param {AerospikeExp} cmpStr String expression to compare against.
* @return {AerospikeExp} - boolean value
*/
exports.cmpRegex = (options, regex, cmpStr) => [
{ op: exp.ops.CMP_REGEX, count: 4 },
..._int(options),
..._rawStr(regex),
...cmpStr
]
/**
* Create a point within region or region contains point expression.
*
* @function
* @param {number} left left expression in comparison.
* @param {number} right right expression in comparison.
* @return {AerospikeExp} - boolean value
*/
exports.cmpGeo = _cmpExp(exp.ops.CMP_GEO)
/*********************************************************************************
* LOGICAL EXPRESSIONS
*********************************************************************************/
/**
* Create "not" (!) operator expression.
*
* @function
* @param {AerospikeExp} expr Boolean expression to negate.
* @return {AerospikeExp} - boolean value
*/
exports.not = (expr) => [
{ op: exp.ops.NOT, count: 2 },
...expr
]
const _VAExp = (op) => (...expr) => [].concat(
{ op },
...expr,
{ op: exp.ops.END_OF_VA_ARGS }
)
/**
* Create "and" (&&) operator that applies to a variable number of expressions.
*
* @function
* @param {AerospikeExp} ... Variable number of boolean expressions.
* @return {AerospikeExp} - boolean value
*/
exports.and = _VAExp(exp.ops.AND)
/**
* Create "or" (||) operator that applies to a variable number of expressions.
*
* @function
* @param {AerospikeExp} ... Variable number of boolean expressions.
* @return {AerospikeExp} - boolean value
*/
exports.or = _VAExp(exp.ops.OR)
/**
* Create expression that returns true if only one of the expressions are true.
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp} ... Variable number of boolean expressions.
* @return {AerospikeExp} - boolean value
*/
exports.exclusive = _VAExp(exp.ops.EXCLUSIVE)
/*********************************************************************************
* ARITHMETIC EXPRESSIONS
*********************************************************************************/
/**
* Create "add" (+) operator that applies to a variable number of expressions.
* Return the sum of all arguments.
* All arguments must be the same type (integer or float).
* Requires server version 5.6.0+.
*
* @function
* @param {number[]} ... Variable number of integer or float expressions.
* @return {AerospikeExp} integer or float value
*/
exports.add = _VAExp(exp.ops.ADD)
/**
* Create "subtract" (-) operator that applies to a variable number of expressions.
* If only one argument is provided, return the negation of that argument.
* Otherwise, return the sum of the 2nd to Nth argument subtracted from the 1st
* argument. All arguments must resolve to the same type (integer or float).
* Requires server version 5.6.0+.
*
* @function
* @param {number[]} ... Variable number of integer or float expressions.
* @return {AerospikeExp} integer or float value
*/
exports.sub = _VAExp(exp.ops.SUB)
/**
* Create "multiply" (*) operator that applies to a variable number of expressions.
* Return the product of all arguments. If only one argument is supplied, return
* that argument. All arguments must resolve to the same type (integer or float).
* Requires server version 5.6.0+.
*
* @function
* @param {number[]} ... Variable number of integer or float expressions.
* @return {AerospikeExp} integer or float value
*/
exports.mul = _VAExp(exp.ops.MUL)
/**
* Create "divide" (/) operator that applies to a variable number of expressions.
* If there is only one argument, returns the reciprocal for that argument.
* Otherwise, return the first argument divided by the product of the rest.
* All arguments must resolve to the same type (integer or float).
* Requires server version 5.6.0+.
*
* @function
* @param {number[]} ... Variable number of integer or float expressions.
* @return {AerospikeExp} integer or float value
*/
exports.div = _VAExp(exp.ops.DIV)
const _paramsExp = (op) => (...params) => [
{ op, count: params.length + 1 },
...params
]
/**
* Create "pow" operator that raises a "base" to the "exponent" power.
* All arguments must resolve to floats.
* Requires server version 5.6.0+.
*
* @function
* @param {number} base Base value.
* @param {number} exponent Exponent value.
* @return {AerospikeExp} float value
*/
exports.pow = _paramsExp(exp.ops.POW)
/**
* Create "log" operator for logarithm of "num" with base "base".
* All arguments must resolve to floats.
* Requires server version 5.6.0+.
*
* @function
* @param {number} num Number.
* @param {number}base Base value.
* @return {AerospikeExp} float value
*/
exports.log = _paramsExp(exp.ops.LOG)
/**
* Create "modulo" (%) operator that determines the remainder of "numerator"
* divided by "denominator". All arguments must resolve to integers.
* Requires server version 5.6.0+.
*
* @function
* @return {AerospikeExp} integer value
*/
exports.mod = _paramsExp(exp.ops.MOD)
/**
* Create operator that returns absolute value of a number.
* All arguments must resolve to integer or float.
* Requires server version 5.6.0+.
*
* @function
* @return {AerospikeExp} number value
*/
exports.abs = _paramsExp(exp.ops.ABS)
/**
* Create expression that rounds a floating point number down to the closest integer value.
* Requires server version 5.6.0+.
*
* @function
* @param {number} num Floating point value to round down.
* @return {AerospikeExp} float-value
*/
exports.floor = _paramsExp(exp.ops.FLOOR)
/**
* Create expression that rounds a floating point number up to the closest integer value.
* Requires server version 5.6.0+.
*
* @function
* @param {number} num Floating point value to round up.
* @return {AerospikeExp} integer-value
*/
exports.ceil = _paramsExp(exp.ops.CEIL)
/**
* Create expression that converts a float to an integer.
* Requires server version 5.6.0+.
*
* @function
* @param {number} num Integer to convert to a float
* @return {AerospikeExp} float value
*/
exports.toInt = _paramsExp(exp.ops.TO_INT)
/**
* Create expression that converts an integer to a float.
* Requires server version 5.6.0+.
*
* @function
* @param {number} num Integer to convert to a float
* @return {AerospikeExp} float value
*/
exports.toFloat = _paramsExp(exp.ops.TO_FLOAT)
/**
* Create integer "and" (&) operator that is applied to two or more integers.
* All arguments must resolve to integers.
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp} ... Variable number of integer expressions.
* @return {AerospikeExp} integer value
*/
exports.intAnd = _VAExp(exp.ops.INT_AND)
/**
* Create integer "or" (|) operator that is applied to two or more integers.
* All arguments must resolve to integers.
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp} ... Variable number of integer expressions.
* @return {AerospikeExp} integer value
*/
exports.intOr = _VAExp(exp.ops.INT_OR)
/**
* Create integer "xor" (^) operator that is applied to two or more integers.
* All arguments must resolve to integers.
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp} ... Variable number of integer expressions.
* @return {AerospikeExp} integer value
*/
exports.intXor = _VAExp(exp.ops.INT_XOR)
/**
* Create integer "not" (~) operator.
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp} expr Integer expression.
* @return {AerospikeExp} integer value
*/
exports.intNot = _paramsExp(exp.ops.INT_NOT)
/**
* Create integer "left shift" (<<) operator.
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp} value Integer expression.
* @param {number} shift Number of bits to shift by.
* @return {AerospikeExp} integer value
*/
exports.intLshift = _paramsExp(exp.ops.INT_LSHIFT)
/**
* Create integer "logical right shift" (>>>) operator.
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp} value Integer expression.
* @param {number} shift Number of bits to shift by.
* @return {AerospikeExp} integer value
*/
exports.intRshift = _paramsExp(exp.ops.INT_RSHIFT)
/**
* Create integer "arithmetic right shift" (>>) operator.
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp} value Integer expression.
* @param {number} shift Number of bits to shift by.
* @return {AerospikeExp} integer value
*/
exports.intArshift = _paramsExp(exp.ops.INT_ARSHIFT)
/**
* Create expression that returns count of integer bits that are set to 1.
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp}
* @return {AerospikeExp} integer value
*/
exports.intCount = _paramsExp(exp.ops.INT_COUNT)
/**
* Create expression that scans integer bits from left (most significant bit) to
* right (least significant bit), looking for a search bit value. When the
* search value is found, the index of that bit (where the most significant bit is
* index 0) is returned. If "search" is true, the scan will search for the bit
* value 1. If "search" is false it will search for bit value 0.
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp}
* @return {AerospikeExp} integer value
*/
exports.intLscan = _paramsExp(exp.ops.INT_LSCAN)
/**
* Create expression that scans integer bits from right (least significant bit) to
* left (most significant bit), looking for a search bit value. When the
* search value is found, the index of that bit (where the most significant bit is
* index 0) is returned. If "search" is true, the scan will search for the bit
* value 1. If "search" is false it will search for bit value 0.
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp}
* @return {AerospikeExp} integer value
*/
exports.intRscan = _paramsExp(exp.ops.INT_RSCAN)
/**
* Create expression that returns the minimum value in a variable number of expressions.
* All arguments must be the same type (integer or float).
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp} ... Variable number of integer or float expressions.
* @return {AerospikeExp} integer or float value
*/
exports.min = _VAExp(exp.ops.MIN)
/**
* Create expression that returns the maximum value in a variable number of expressions.
* All arguments must be the same type (integer or float).
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp} ... Variable number of integer or float expressions.
* @return {AerospikeExp} integer or float value
*/
exports.max = _VAExp(exp.ops.MAX)
/*********************************************************************************
* FLOW CONTROL AND VARIABLE EXPRESSIONS
*********************************************************************************/
/**
* Conditionally select an expression from a variable number of expression pairs
* followed by default expression action. Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp}
* @return {AerospikeExp} first action expression where bool expression is true or action-default.
*/
exports.cond = _VAExp(exp.ops.COND)
/**
* Define variables and expressions in scope.
* Requires server version 5.6.0+.
*
* @function
* @param {AerospikeExp} ... Variable number of expression def followed by a scoped
* expression.
* @return {AerospikeExp} result of scoped expression.
*/
exports.let = _VAExp(exp.ops.LET)
/**
* Assign variable to an expression that can be accessed later.
* Requires server version 5.6.0+.
*
* @function
* @param {string} varName Variable name.
* @param {AerospikeExp} expr The variable is set to the result of expr.
* @return {AerospikeExp} A variable name expression pair.
*/
exports.def = (varName, expr) => [
..._rawStr(varName),
...expr
]
/**
* Retrieve expression value from a variable.
* Requires server version 5.6.0+.
*
* @function
* @param {string} varName Variable name.
* @return {AerospikeExp} value stored in variable.
*/
exports.var = (varName) => [
{ op: exp.ops.VAR, count: 2 },
..._rawStr(varName)
]
/**
* The {@link module:aerospike/exp/lists|aerospike/exp/lists} module defines functions
* for expressions on the List datatype.
*
* @summary List expressions.
*/
exports.lists = require('./exp_lists')
/**
* The {@link module:aerospike/exp/maps|aerospike/exp/maps} module defines functions
* for expressions on the Map datatype.
*
* @summary Map expressions.
*/
exports.maps = require('./exp_maps')
/**
* The {@link module:aerospike/exp/bit|aerospike/exp/bit} module defines functions
* for expressions on the Blob datatype
*
* @summary Blob expressions.
*/
exports.bit = require('./exp_bit')
/**
* The {@link module:aerospike/exp/hll|aerospike/exp/hll} module defines functions
* for expressions on the HyperLogLog datatype
*
* @summary HyperLogLog expressions.
*/
exports.hll = require('./exp_hll')
/**
*
* @readonly
* @enum {number}
* @description Expression read bit flags. Use BITWISE OR to combine flags.
*/
exports.expReadFlags = {
/**
* Default.
* @const {number}
*/
DEFAULT: readFlags.DEFAULT,
/**
* Ignore failures caused by the expression resolving to unknown or a non-bin type.
* @const {number}
*/
EVAL_NO_FAIL: readFlags.EVAL_NO_FAIL
}
/**
*
* @readonly
* @enum {number}
* @description Expression write bit flags. Use BITWISE OR to combine flags.
*/
exports.expWriteFlags = {
/**
* Default.
* @const {number}
*/
DEFAULT: writeFlags.DEFAULT,
/**
* If bin does not exist, a new bin will be created.
* @const {number}
*/
CREATE_ONLY: writeFlags.CREATE_ONLY,
/**
* If bin exists, the bin will be overwritten.
* @const {number}
*/
UPDATE_ONLY: writeFlags.UPDATE_ONLY,
/**
* If expression results in nil value, then delete the bin.
* @const {number}
*/
ALLOW_DELETE: writeFlags.ALLOW_DELETE,
/**
* Do not raise error if operation is denied.
* @const {number}
*/
POLICY_NO_FAIL: writeFlags.POLICY_NO_FAIL,
/**
* Ignore failures caused by the expression resolving to unknown or a non-bin type.
* @const {number}
*/
EVAL_NO_FAIL: writeFlags.EVAL_NO_FAIL
}