blob: e2a163a0796b9e3ee6ac236b66d8a4459249f414 [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.
*/
package org.apache.geode.cache.query.cq;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.util.Properties;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientCacheFactory;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.apache.geode.cache.query.CqAttributes;
import org.apache.geode.cache.query.CqAttributesFactory;
import org.apache.geode.cache.query.QueryInvalidException;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
import org.apache.geode.test.junit.categories.ClientSubscriptionTest;
/**
* Test to make sure CQs that have invalid syntax throw QueryInvalidException, and CQs that have
* unsupported CQ features throw UnsupportedOperationException
*/
@Category(ClientSubscriptionTest.class)
public class ContinuousQueryValidationDUnitTest {
private QueryService queryService;
@Rule
public ClusterStartupRule clusterStartupRule = new ClusterStartupRule();
@Before
public void setUp() {
MemberVM locator = clusterStartupRule.startLocatorVM(1, new Properties());
MemberVM cacheServer = clusterStartupRule.startServerVM(2, locator.getPort());
cacheServer.invoke(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
ClusterStartupRule.getCache().createRegionFactory(RegionShortcut.REPLICATE).create("region");
});
ClientCacheFactory clientCacheFactory = new ClientCacheFactory();
clientCacheFactory.addPoolLocator("localhost", locator.getPort());
clientCacheFactory.setPoolSubscriptionEnabled(true);
ClientCache clientCache = clientCacheFactory.create();
clientCache.createClientRegionFactory(ClientRegionShortcut.PROXY).create("region");
queryService = clientCache.getQueryService();
}
@Test
public void creationShouldSucceedForValidQueries() {
CqAttributes attrs = new CqAttributesFactory().create();
String[] validQueries = new String[] {
"SELECT * FROM /region WHERE id = 1",
"SELECT * FROM /region WHERE id <> 1",
"SELECT * FROM /region WHERE id < 100",
"SELECT * FROM /region WHERE status = 'active'",
"SELECT * FROM /region t WHERE t.price > 100.00"
};
for (String queryString : validQueries) {
assertThatCode(() -> queryService.newCq(queryString, attrs))
.as(String.format("Query creation failed for %s but should have succeeded.", queryString))
.doesNotThrowAnyException();
}
}
@Test
public void creationShouldThrowQueryInvalidExceptionForInvalidQueries() {
CqAttributes attrs = new CqAttributesFactory().create();
String[] invalidQueries = new String[] {
"I AM NOT A QUERY",
"SELECT * FROM /region WHERE MIN(id) > 0",
"SELECT * FROM /region WHERE MAX(id) > 0",
"SELECT * FROM /region WHERE AVG(id) > 0",
"SELECT * FROM /region WHERE SUM(id) > 0",
"SELECT * FROM /region WHERE COUNT(id) > 0",
};
for (String queryString : invalidQueries) {
assertThatThrownBy(() -> queryService.newCq(queryString, attrs))
.as(String.format("Query creation succeeded for %s but should have failed.", queryString))
.isInstanceOf(QueryInvalidException.class);
}
}
@Test
public void creationShouldThrowUnsupportedOperationExceptionForUnsupportedQueries() {
CqAttributes attrs = new CqAttributesFactory().create();
String[] unsupportedCQs = new String[] {
// not "just" a select statement
"(SELECT * FROM /region WHERE status = 'active').isEmpty",
// cannot be DISTINCT
"SELECT DISTINCT * FROM /region WHERE status = 'active'",
// references more than one region
"SELECT * FROM /region1 r1, /region2 r2 WHERE r1 = r2",
// where clause refers to a region
"SELECT * FROM /region r WHERE r.val = /region.size",
// more than one iterator in FROM clause
"SELECT * FROM /portfolios p1, p1.positions p2 WHERE p2.id = 'IBM'",
// first iterator in FROM clause is not just a region path
"SELECT * FROM /region.entries e WHERE e.value.id = 23",
// has projections
"SELECT id FROM /region WHERE status = 'active'",
// has ORDER BY
"SELECT * FROM /region WHERE status = 'active' ORDER BY id",
// has aggregates
"SELECT MIN(id) FROM /region WHERE status = 'active'",
"SELECT MAX(id) FROM /region WHERE status = 'active'",
"SELECT SUM(id) FROM /region WHERE status = 'active'",
"SELECT AVG(id) FROM /region WHERE status = 'active'",
"SELECT COUNT(id) FROM /region WHERE status = 'active'",
};
for (String queryString : unsupportedCQs) {
assertThatThrownBy(() -> queryService.newCq(queryString, attrs))
.as(String.format("Query creation succeeded for %s but should have failed.", queryString))
.isInstanceOf(UnsupportedOperationException.class);
}
}
}