/* * 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. */ package org.apache.ignite.cache.query; import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.ignite.IgniteCache; import org.apache.ignite.internal.processors.query.QueryUtils; import org.apache.ignite.internal.util.tostring.GridToStringInclude; import org.apache.ignite.internal.util.typedef.internal.A; import org.apache.ignite.internal.util.typedef.internal.S; import org.jetbrains.annotations.Nullable; /** * SQL Fields query. This query can return specific fields of data based * on SQL {@code 'select'} clause, as opposed to {@link SqlQuery}, which always returns * the whole key and value objects back. * <h1 class="header">Collocated Flag</h1> * Collocation flag is used for optimization purposes. Whenever Ignite executes * a distributed query, it sends sub-queries to individual cluster members. * If you know in advance that the elements of your query selection are collocated * together on the same node, usually based on some <b>affinity-key</b>, Ignite * can make significant performance and network optimizations. * <p> * For example, in case of Word-Count example, we know that all identical words * are processed on the same cluster member, because we use the {@code word} itself * as affinity key. This allows Ignite to execute the {@code 'limit'} clause on * the remote nodes and bring back only the small data set specified within the 'limit' clause, * instead of the whole query result as would happen in a non-collocated execution. * * @see IgniteCache#query(Query) */ public class SqlFieldsQuery extends Query<List<?>> { /** */ private static final long serialVersionUID = 0L; /** SQL Query. */ private String sql; /** Arguments. */ @GridToStringInclude private Object[] args; /** Collocation flag. */ private boolean collocated; /** Query timeout in millis. */ private int timeout; /** */ private boolean enforceJoinOrder; /** */ private boolean distributedJoins; /** */ private boolean replicatedOnly; /** Partitions for query */ private int[] parts; /** * Constructs SQL fields query. * * @param sql SQL query. */ public SqlFieldsQuery(String sql) { setSql(sql); } /** * Constructs SQL fields query. * * @param sql SQL query. * @param collocated Collocated flag. */ public SqlFieldsQuery(String sql, boolean collocated) { this.sql = sql; this.collocated = collocated; } /** * Gets SQL clause. * * @return SQL clause. */ public String getSql() { return sql; } /** * Sets SQL clause. * * @param sql SQL clause. * @return {@code this} For chaining. */ public SqlFieldsQuery setSql(String sql) { A.notNull(sql, "sql"); this.sql = sql; return this; } /** * Gets SQL arguments. * * @return SQL arguments. */ public Object[] getArgs() { return args; } /** * Sets SQL arguments. * * @param args SQL arguments. * @return {@code this} For chaining. */ public SqlFieldsQuery setArgs(Object... args) { this.args = args; return this; } /** * Gets the query execution timeout in milliseconds. * * @return Timeout value. */ public int getTimeout() { return timeout; } /** * Sets the query execution timeout. Query will be automatically cancelled if the execution timeout is exceeded. * @param timeout Timeout value. Zero value disables timeout. * @param timeUnit Time unit. * @return {@code this} For chaining. */ public SqlFieldsQuery setTimeout(int timeout, TimeUnit timeUnit) { this.timeout = QueryUtils.validateTimeout(timeout, timeUnit); return this; } /** * Checks if this query is collocated. * * @return {@code true} If the query is collocated. */ public boolean isCollocated() { return collocated; } /** * Sets flag defining if this query is collocated. * * Collocation flag is used for optimization purposes of queries with GROUP BY statements. * Whenever Ignite executes a distributed query, it sends sub-queries to individual cluster members. * If you know in advance that the elements of your query selection are collocated together on the same node and * you group by collocated key (primary or affinity key), then Ignite can make significant performance and network * optimizations by grouping data on remote nodes. * * @param collocated Flag value. * @return {@code this} For chaining. */ public SqlFieldsQuery setCollocated(boolean collocated) { this.collocated = collocated; return this; } /** * Checks if join order of tables if enforced. * * @return Flag value. */ public boolean isEnforceJoinOrder() { return enforceJoinOrder; } /** * Sets flag to enforce join order of tables in the query. If set to {@code true} * query optimizer will not reorder tables in join. By default is {@code false}. * <p> * It is not recommended to enable this property until you are sure that * your indexes and the query itself are correct and tuned as much as possible but * query optimizer still produces wrong join order. * * @param enforceJoinOrder Flag value. * @return {@code this} For chaining. */ public SqlFieldsQuery setEnforceJoinOrder(boolean enforceJoinOrder) { this.enforceJoinOrder = enforceJoinOrder; return this; } /** * Specify if distributed joins are enabled for this query. * * @param distributedJoins Distributed joins enabled. * @return {@code this} For chaining. */ public SqlFieldsQuery setDistributedJoins(boolean distributedJoins) { this.distributedJoins = distributedJoins; return this; } /** * Check if distributed joins are enabled for this query. * * @return {@code true} If distributed joind enabled. */ public boolean isDistributedJoins() { return distributedJoins; } /** {@inheritDoc} */ @Override public SqlFieldsQuery setPageSize(int pageSize) { return (SqlFieldsQuery)super.setPageSize(pageSize); } /** {@inheritDoc} */ @Override public SqlFieldsQuery setLocal(boolean loc) { return (SqlFieldsQuery)super.setLocal(loc); } /** * Specify if the query contains only replicated tables. * This is a hint for potentially more effective execution. * * @param replicatedOnly The query contains only replicated tables. * @return {@code this} For chaining. */ public SqlFieldsQuery setReplicatedOnly(boolean replicatedOnly) { this.replicatedOnly = replicatedOnly; return this; } /** * Check is the query contains only replicated tables. * * @return {@code true} If the query contains only replicated tables. */ public boolean isReplicatedOnly() { return replicatedOnly; } /** * Gets partitions for query, in ascending order. */ @Nullable public int[] getPartitions() { return parts; } /** * Sets partitions for a query. * The query will be executed only on nodes which are primary for specified partitions. * <p> * Note what passed array'll be sorted in place for performance reasons, if it wasn't sorted yet. * * @param parts Partitions. * @return {@code this} for chaining. */ public SqlFieldsQuery setPartitions(@Nullable int... parts) { this.parts = prepare(parts); return this; } /** {@inheritDoc} */ @Override public String toString() { return S.toString(SqlFieldsQuery.class, this); } }