| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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'; |
| |
| import * as Util from "util"; |
| import {BaseCursor, Cursor, SqlFieldsCursor} from "./Cursor"; |
| import ArgumentChecker from "./internal/ArgumentChecker"; |
| import BinaryCommunicator from "./internal/BinaryCommunicator"; |
| import BinaryUtils, {OPERATION} from "./internal/BinaryUtils"; |
| import { CompositeType } from "./ObjectType"; |
| import { PRIMITIVE_TYPE } from "./internal/Constants"; |
| import MessageBuffer from "./internal/MessageBuffer"; |
| import {CacheEntry} from "./CacheClient"; |
| |
| const PAGE_SIZE_DEFAULT = 1024; |
| |
| const DeprecateSetLocal = Util.deprecate(() => {}, "Query.setLocal is deprecated. It will be removed in later versions."); |
| |
| /** |
| * Base class representing an Ignite SQL or Scan query. |
| * |
| * The class has no public constructor. Only subclasses may be instantiated. |
| * |
| * @hideconstructor |
| */ |
| abstract class Query<T> { |
| |
| protected _local: boolean; |
| |
| protected _pageSize: number; |
| |
| protected _operation: OPERATION; |
| |
| /** |
| * Set local query flag. |
| * |
| * @param {boolean} local - local query flag: true or false. |
| * |
| * @return {Query} - the same instance of the Query. |
| */ |
| setLocal(local: boolean): Query<T> { |
| DeprecateSetLocal(); |
| this._local = local; |
| return this; |
| } |
| |
| /** |
| * Set {@link Cursor} page size. |
| * |
| * @param {number} pageSize - cursor page size. |
| * |
| * @return {Query} - the same instance of the Query. |
| */ |
| setPageSize(pageSize: number): Query<T> { |
| this._pageSize = pageSize; |
| return this; |
| } |
| |
| /** Private methods */ |
| |
| /** |
| * @ignore |
| */ |
| constructor(operation: OPERATION) { |
| this._operation = operation; |
| this._local = false; |
| this._pageSize = PAGE_SIZE_DEFAULT; |
| } |
| |
| abstract _getCursor(communicator, payload, keyType, valueType): Promise<BaseCursor<T>>; |
| } |
| |
| /** |
| * Class representing an SQL query which returns the whole cache entries (key-value pairs). |
| * @extends Query |
| */ |
| export class SqlQuery extends Query<CacheEntry> { |
| |
| private _type: string; |
| |
| protected _sql: string; |
| |
| private _argTypes: (PRIMITIVE_TYPE | CompositeType)[]; |
| |
| protected _distributedJoins: boolean; |
| |
| protected _replicatedOnly: boolean; |
| |
| protected _timeout: number; |
| |
| private _args: object[]; |
| |
| /** |
| * Public constructor. |
| * |
| * Requires name of a type (or SQL table) and SQL query string to be specified. |
| * Other SQL query settings have the following defaults: |
| * <pre> |
| * SQL Query setting : Default value |
| * Local query flag : false |
| * Cursor page size : 1024 |
| * Query arguments : not specified |
| * Distributed joins flag : false |
| * Replicated only flag : false |
| * Timeout : 0 (disabled) |
| * </pre> |
| * Every setting may be changed using set methods. |
| * |
| * @param {string} type - name of a type or SQL table. |
| * @param {string} sql - SQL query string. |
| * |
| * @return {SqlQuery} - new SqlQuery instance. |
| */ |
| constructor(type: string, sql: string) { |
| super(BinaryUtils.OPERATION.QUERY_SQL); |
| this.setType(type); |
| this.setSql(sql); |
| this._args = null; |
| this._argTypes = null; |
| this._distributedJoins = false; |
| this._replicatedOnly = false; |
| this._timeout = 0; |
| } |
| |
| /** |
| * Set name of a type or SQL table. |
| * |
| * @param {string} type - name of a type or SQL table. |
| * |
| * @return {SqlQuery} - the same instance of the SqlQuery. |
| */ |
| setType(type: string): SqlQuery { |
| if (this instanceof SqlFieldsQuery) { |
| ArgumentChecker.invalidArgument(type, 'type', SqlFieldsQuery); |
| } |
| else { |
| ArgumentChecker.notNull(type, 'type'); |
| } |
| this._type = type; |
| return this; |
| } |
| |
| /** |
| * Set SQL query string. |
| * |
| * @param {string} sql - SQL query string. |
| * |
| * @return {SqlQuery} - the same instance of the SqlQuery. |
| */ |
| setSql(sql: string): SqlQuery { |
| ArgumentChecker.notNull(sql, 'sql'); |
| this._sql = sql; |
| return this; |
| } |
| |
| /** |
| * Set query arguments. |
| * |
| * Type of any argument may be specified using setArgTypes() method. |
| * If type of an argument is not specified then during operations the Ignite client |
| * will try to make automatic mapping between JavaScript types and Ignite object types - |
| * according to the mapping table defined in the description of the {@link ObjectType} class. |
| * |
| * @param {...*} args - Query arguments. |
| * |
| * @return {SqlQuery} - the same instance of the SqlQuery. |
| */ |
| setArgs(...args: object[]): SqlQuery { |
| this._args = args; |
| return this; |
| } |
| |
| /** |
| * Specifies types of query arguments. |
| * |
| * Query arguments itself are set using setArgs() method. |
| * By default, a type of every argument is not specified that means during operations the Ignite client |
| * will try to make automatic mapping between JavaScript types and Ignite object types - |
| * according to the mapping table defined in the description of the {@link ObjectType} class. |
| * |
| * @param {...ObjectType.PRIMITIVE_TYPE | CompositeType} argTypes - types of Query arguments. |
| * The order of types must follow the order of arguments in the setArgs() method. |
| * A type of every argument can be: |
| * - either a type code of primitive (simple) type |
| * - or an instance of class representing non-primitive (composite) type |
| * - or null (means the type is not specified) |
| * |
| * @return {SqlQuery} - the same instance of the SqlQuery. |
| */ |
| setArgTypes(...argTypes: (PRIMITIVE_TYPE | CompositeType)[]): SqlQuery { |
| this._argTypes = argTypes; |
| return this; |
| } |
| |
| /** |
| * Set distributed joins flag. |
| * |
| * @param {boolean} distributedJoins - distributed joins flag: true or false. |
| * |
| * @return {SqlQuery} - the same instance of the SqlQuery. |
| */ |
| setDistributedJoins(distributedJoins: boolean): SqlQuery { |
| this._distributedJoins = distributedJoins; |
| return this; |
| } |
| |
| /** |
| * Set replicated only flag. |
| * |
| * @param {boolean} replicatedOnly - replicated only flag: true or false. |
| * |
| * @return {SqlQuery} - the same instance of the SqlQuery. |
| */ |
| setReplicatedOnly(replicatedOnly: boolean): SqlQuery { |
| this._replicatedOnly = replicatedOnly; |
| return this; |
| } |
| |
| /** |
| * Set timeout. |
| * |
| * @param {number} timeout - timeout value in milliseconds. |
| * Must be non-negative. Zero value disables timeout. |
| * |
| * @return {SqlQuery} - the same instance of the SqlQuery. |
| */ |
| setTimeout(timeout: number): SqlQuery { |
| this._timeout = timeout; |
| return this; |
| } |
| |
| /** Private methods */ |
| |
| /** |
| * @ignore |
| */ |
| async _write(communicator: BinaryCommunicator, buffer: MessageBuffer) { |
| BinaryCommunicator.writeString(buffer, this._type); |
| BinaryCommunicator.writeString(buffer, this._sql); |
| await this._writeArgs(communicator, buffer); |
| buffer.writeBoolean(this._distributedJoins); |
| buffer.writeBoolean(this._local); |
| buffer.writeBoolean(this._replicatedOnly); |
| buffer.writeInteger(this._pageSize); |
| buffer.writeLong(this._timeout); |
| } |
| |
| /** |
| * @ignore |
| */ |
| async _writeArgs(communicator: BinaryCommunicator, buffer: MessageBuffer) { |
| const argsLength = this._args ? this._args.length : 0; |
| buffer.writeInteger(argsLength); |
| if (argsLength > 0) { |
| let argType; |
| for (let i = 0; i < argsLength; i++) { |
| argType = this._argTypes && i < this._argTypes.length ? this._argTypes[i] : null; |
| await communicator.writeObject(buffer, this._args[i], argType); |
| } |
| } |
| } |
| |
| /** |
| * @ignore |
| */ |
| async _getCursor(communicator, payload, keyType = null, valueType = null): Promise<BaseCursor<CacheEntry>> { |
| const cursor = new Cursor(communicator, BinaryUtils.OPERATION.QUERY_SQL_CURSOR_GET_PAGE, payload, keyType, valueType); |
| cursor._readId(payload); |
| return cursor; |
| } |
| } |
| |
| /** |
| * Statement type of SQL Fields query. |
| * @typedef SqlFieldsQuery.STATEMENT_TYPE |
| * @enum |
| * @readonly |
| * @property ANY 0 |
| * @property SELECT 1 |
| * @property UPDATE 2 |
| */ |
| export enum STATEMENT_TYPE { |
| ANY = 0, |
| SELECT = 1, |
| UPDATE = 2 |
| } |
| |
| |
| /** |
| * Class representing an SQL Fields query. |
| * @extends SqlQuery |
| */ |
| export class SqlFieldsQuery extends SqlQuery { |
| |
| private _schema: string; |
| |
| private _maxRows: number; |
| |
| private _statementType: STATEMENT_TYPE; |
| |
| private _enforceJoinOrder: boolean; |
| |
| private _collocated: boolean; |
| |
| private _lazy: boolean; |
| |
| private _includeFieldNames: boolean; |
| |
| /** |
| * Public constructor. |
| * |
| * Requires SQL query string to be specified. |
| * Other SQL Fields query settings have the following defaults: |
| * <pre> |
| * SQL Fields Query setting : Default value |
| * Local query flag : false |
| * Cursor page size : 1024 |
| * Query arguments : not specified |
| * Distributed joins flag : false |
| * Replicated only flag : false |
| * Timeout : 0 (disabled) |
| * Schema for the query : not specified |
| * Max rows : -1 |
| * Statement type : STATEMENT_TYPE.ANY |
| * Enforce join order flag : false |
| * Collocated flag : false |
| * Lazy query execution flag : false |
| * Include field names flag : false |
| * </pre> |
| * Every setting may be changed using set methods. |
| * |
| * @param {string} sql - SQL query string. |
| * |
| * @return {SqlFieldsQuery} - new SqlFieldsQuery instance. |
| */ |
| constructor(sql: string) { |
| super(null, sql); |
| this._operation = OPERATION.QUERY_SQL_FIELDS; |
| this._schema = null; |
| this._maxRows = -1; |
| this._statementType = STATEMENT_TYPE.ANY; |
| this._enforceJoinOrder = false; |
| this._collocated = false; |
| this._lazy = false; |
| this._includeFieldNames = false; |
| } |
| |
| static get STATEMENT_TYPE() { |
| return STATEMENT_TYPE; |
| } |
| |
| /** |
| * Set schema for the query. |
| * |
| * @param {string} schema - schema for the query. |
| * |
| * @return {SqlFieldsQuery} - the same instance of the SqlFieldsQuery. |
| */ |
| setSchema(schema: string): SqlFieldsQuery { |
| this._schema = schema; |
| return this; |
| } |
| |
| /** |
| * Set max rows. |
| * |
| * @param {number} maxRows - max rows. |
| * |
| * @return {SqlFieldsQuery} - the same instance of the SqlFieldsQuery. |
| */ |
| setMaxRows(maxRows: number): SqlFieldsQuery { |
| this._maxRows = maxRows; |
| return this; |
| } |
| |
| /** |
| * Set statement type. |
| * |
| * @param {STATEMENT_TYPE} type - statement type. |
| * |
| * @return {SqlFieldsQuery} - the same instance of the SqlFieldsQuery. |
| */ |
| setStatementType(type: STATEMENT_TYPE): SqlFieldsQuery { |
| this._statementType = type; |
| return this; |
| } |
| |
| /** |
| * Set enforce join order flag. |
| * |
| * @param {boolean} enforceJoinOrder - enforce join order flag: true or false. |
| * |
| * @return {SqlFieldsQuery} - the same instance of the SqlFieldsQuery. |
| */ |
| setEnforceJoinOrder(enforceJoinOrder: boolean): SqlFieldsQuery { |
| this._enforceJoinOrder = enforceJoinOrder; |
| return this; |
| } |
| |
| /** |
| * Set collocated flag. |
| * |
| * @param {boolean} collocated - collocated flag: true or false. |
| * |
| * @return {SqlFieldsQuery} - the same instance of the SqlFieldsQuery. |
| */ |
| setCollocated(collocated: boolean): SqlFieldsQuery { |
| this._collocated = collocated; |
| return this; |
| } |
| |
| /** |
| * Set lazy query execution flag. |
| * |
| * @param {boolean} lazy - lazy query execution flag: true or false. |
| * |
| * @return {SqlFieldsQuery} - the same instance of the SqlFieldsQuery. |
| */ |
| setLazy(lazy: boolean): SqlFieldsQuery { |
| this._lazy = lazy; |
| return this; |
| } |
| |
| /** |
| * Set include field names flag. |
| * |
| * @param {boolean} includeFieldNames - include field names flag: true or false. |
| * |
| * @return {SqlFieldsQuery} - the same instance of the SqlFieldsQuery. |
| */ |
| setIncludeFieldNames(includeFieldNames: boolean): SqlFieldsQuery { |
| this._includeFieldNames = includeFieldNames; |
| return this; |
| } |
| |
| /** Private methods */ |
| |
| /** |
| * @ignore |
| */ |
| async _write(communicator, buffer) { |
| BinaryCommunicator.writeString(buffer, this._schema); |
| buffer.writeInteger(this._pageSize); |
| buffer.writeInteger(this._maxRows); |
| BinaryCommunicator.writeString(buffer, this._sql); |
| await this._writeArgs(communicator, buffer) |
| buffer.writeByte(this._statementType); |
| buffer.writeBoolean(this._distributedJoins); |
| buffer.writeBoolean(this._local); |
| buffer.writeBoolean(this._replicatedOnly); |
| buffer.writeBoolean(this._enforceJoinOrder); |
| buffer.writeBoolean(this._collocated); |
| buffer.writeBoolean(this._lazy); |
| buffer.writeLong(this._timeout); |
| buffer.writeBoolean(this._includeFieldNames); |
| } |
| |
| // noinspection JSAnnotator |
| /** |
| * @ignore |
| */ |
| // @ts-ignore |
| async _getCursor(communicator, payload, keyType = null, valueType = null): Promise<BaseCursor<Array<object>>> { |
| const cursor = new SqlFieldsCursor(communicator, payload); |
| await cursor._readFieldNames(payload, this._includeFieldNames); |
| return cursor; |
| } |
| } |
| |
| /** |
| * Class representing a Scan query which returns the whole cache entries (key-value pairs). |
| * |
| * This version of the class does not support a possibility to specify a Filter object for the query. |
| * The query returns all entries from the entire cache or from the specified partition. |
| * @extends Query |
| */ |
| export class ScanQuery extends Query<CacheEntry> { |
| |
| private _partitionNumber: number; |
| |
| /** |
| * Public constructor. |
| * |
| * Scan query settings have the following defaults: |
| * <pre> |
| * Scan Query setting : Default value |
| * Local query flag : false |
| * Cursor page size : 1024 |
| * Partition number : -1 (entire cache) |
| * Filter object : null (not supported) |
| * </pre> |
| * Every setting (except Filter object) may be changed using set methods. |
| * |
| * @return {ScanQuery} - new ScanQuery instance. |
| */ |
| constructor() { |
| super(OPERATION.QUERY_SCAN); |
| this._partitionNumber = -1; |
| } |
| |
| /** |
| * Sets a partition number over which this query should iterate. |
| * |
| * If negative, the query will iterate over all partitions in the cache. |
| * |
| * @param {number} partitionNumber - partition number over which this query should iterate. |
| * |
| * @return {ScanQuery} - the same instance of the ScanQuery. |
| */ |
| setPartitionNumber(partitionNumber: number): ScanQuery { |
| this._partitionNumber = partitionNumber; |
| return this; |
| } |
| |
| /** Private methods */ |
| |
| /** |
| * @ignore |
| */ |
| async _write(communicator: BinaryCommunicator, buffer: MessageBuffer) { |
| // filter |
| await communicator.writeObject(buffer, null); |
| buffer.writeInteger(this._pageSize); |
| buffer.writeInteger(this._partitionNumber); |
| buffer.writeBoolean(this._local); |
| } |
| |
| /** |
| * @ignore |
| */ |
| async _getCursor(communicator: BinaryCommunicator, payload, keyType = null, valueType = null) { |
| const cursor = new Cursor(communicator, OPERATION.QUERY_SCAN_CURSOR_GET_PAGE, payload, keyType, valueType); |
| cursor._readId(payload); |
| return cursor; |
| } |
| } |