blob: e8f7ee172800180d5ecad8b067d3a888e9e204af [file] [log] [blame]
/*
* 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;
}
}