/*
* Licensed to Crate under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership. Crate 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.
*
* However, if you have executed another commercial license agreement
* with Crate these terms will supersede the license and you may use the
* software solely pursuant to the terms of the relevant commercial
* agreement.
*/
package io.crate.analyze;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import io.crate.sql.tree.Expression;
import io.crate.sql.tree.Literal;
import io.crate.sql.tree.ObjectLiteral;
import io.crate.sql.tree.SetStatement;
import io.crate.test.integration.CrateDummyClusterServiceUnitTest;
import io.crate.testing.SQLExecutor;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import java.util.Set;
import static org.hamcrest.Matchers.*;
public class SetAnalyzerTest extends CrateDummyClusterServiceUnitTest {
private SQLExecutor executor;
@Before
public void prepare() {
executor = SQLExecutor.builder(clusterService).build();
}
private <T> T analyze(String stmt) {
return executor.analyze(stmt);
}
@Test
public void testSetGlobal() throws Exception {
SetAnalyzedStatement analysis = analyze("SET GLOBAL PERSISTENT stats.operations_log_size=1");
assertThat(analysis.isPersistent(), is(true));
assertThat(analysis.scope(), is(SetStatement.Scope.GLOBAL));
assertThat(
analysis.settings().get("stats.operations_log_size").get(0),
Matchers.<Expression>is(Literal.fromObject(1))
);
analysis = analyze("SET GLOBAL TRANSIENT stats.jobs_log_size=2");
assertThat(analysis.isPersistent(), is(false));
assertThat(analysis.scope(), is(SetStatement.Scope.GLOBAL));
assertThat(
analysis.settings().get("stats.jobs_log_size").get(0),
Matchers.<Expression>is(Literal.fromObject(2))
);
analysis = analyze("SET GLOBAL TRANSIENT stats.enabled=false, stats.operations_log_size=0, stats.jobs_log_size=0");
assertThat(analysis.scope(), is(SetStatement.Scope.GLOBAL));
assertThat(analysis.isPersistent(), is(false));
assertThat(
analysis.settings().get("stats.operations_log_size").get(0),
Matchers.<Expression>is(Literal.fromObject(0))
);
assertThat(
analysis.settings().get("stats.jobs_log_size").get(0),
Matchers.<Expression>is(Literal.fromObject(0))
);
}
@Test
public void testSetLocal() throws Exception {
SetAnalyzedStatement analysis = analyze("SET LOCAL something TO 2");
assertThat(analysis.scope(), is(SetStatement.Scope.LOCAL));
assertThat(analysis.settings().get("something").get(0), Matchers.<Expression>is(Literal.fromObject(2)));
analysis = analyze("SET LOCAL something TO DEFAULT");
assertThat(analysis.scope(), is(SetStatement.Scope.LOCAL));
assertThat(analysis.settings().get("something").size(), is(0));
}
@Test
public void testSetSession() throws Exception {
SetAnalyzedStatement analysis = analyze("SET SESSION something TO 2");
assertThat(analysis.scope(), is(SetStatement.Scope.SESSION));
assertThat(analysis.settings().get("something").size(), is(1));
assertThat(analysis.settings().get("something").get(0), Matchers.<Expression>is(Literal.fromObject(2)));
analysis = analyze("SET SESSION something = 1,2,3");
assertThat(analysis.scope(), is(SetStatement.Scope.SESSION));
assertThat(analysis.settings().get("something").size(), is(3));
assertThat(analysis.settings().get("something").get(1), Matchers.<Expression>is(Literal.fromObject(2)));
}
@Test
public void testSet() throws Exception {
SetAnalyzedStatement analysis = analyze("SET something TO 2");
assertThat(analysis.scope(), is(SetStatement.Scope.SESSION));
assertThat(analysis.settings().get("something").get(0), Matchers.<Expression>is(Literal.fromObject(2)));
analysis = analyze("SET something = DEFAULT");
assertThat(analysis.scope(), is(SetStatement.Scope.SESSION));
assertThat(analysis.settings().get("something").size(), is(0));
analysis = analyze("SET something = default");
assertThat(analysis.scope(), is(SetStatement.Scope.SESSION));
assertThat(analysis.settings().get("something").size(), is(0));
}
@Test
public void testSetFullQualified() throws Exception {
SetAnalyzedStatement analysis = analyze("SET GLOBAL PERSISTENT stats['operations_log_size']=1");
assertThat(analysis.isPersistent(), is(true));
assertThat(analysis.settings().get("stats.operations_log_size").get(0), Matchers.<Expression>is(Literal.fromObject(1)));
}
@Test
public void testSetSessionInvalidSetting() throws Exception {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("GLOBAL Cluster setting 'stats.operations_log_size' cannot be used with SET SESSION / LOCAL");
analyze("SET SESSION stats.operations_log_size=1");
}
@Test
public void testObjectValue() throws Exception {
SetAnalyzedStatement analysis = analyze("SET GLOBAL PERSISTENT cluster.graceful_stop = {timeout='1h'}");
Multimap<String, Expression> map = LinkedListMultimap.create();
map.put("timeout", Literal.fromObject("1h"));
Literal expected = new ObjectLiteral(map);
assertThat(analysis.settings().get("cluster.graceful_stop").get(0), Matchers.<Expression>is(expected));
}
@Test
public void testSetRuntimeSettingSubscript() {
SetAnalyzedStatement analysis =
analyze("SET GLOBAL TRANSIENT cluster['routing']['allocation']['include'] = {_host = 'host1.example.com'}");
Expression expression = analysis.settings().get("cluster.routing.allocation.include").get(0);
assertThat(expression.toString(), is("{\"_host\"= 'host1.example.com'}"));
}
@Test
public void testReset() throws Exception {
ResetAnalyzedStatement analysis = analyze("RESET GLOBAL stats.enabled");
assertThat(analysis.settingsToRemove(), contains("stats.enabled"));
analysis = analyze("RESET GLOBAL stats");
assertThat(
analysis.settingsToRemove(),
containsInAnyOrder(
"stats.breaker.log.operations.limit",
"stats.breaker.log.operations.overhead",
"stats.breaker.log.jobs.limit",
"stats.breaker.log.jobs.overhead",
"stats.enabled",
"stats.jobs_log_size",
"stats.jobs_log_expiration",
"stats.operations_log_size",
"stats.operations_log_expiration",
"stats.service.interval")
);
}
@Test
public void testSetNonRuntimeSetting() {
expectedException.expect(UnsupportedOperationException.class);
expectedException.expectMessage("Setting 'gateway.recover_after_time' cannot be set/reset at runtime");
analyze("SET GLOBAL TRANSIENT gateway.recover_after_time = '5m'");
}
@Test
public void testResetNonRuntimeSetting() {
expectedException.expect(UnsupportedOperationException.class);
expectedException.expectMessage("Setting 'gateway.recover_after_nodes' cannot be set/reset at runtime");
analyze("RESET GLOBAL gateway.recover_after_nodes");
}
@Test
public void testSetNonRuntimeSettingObject() {
expectedException.expect(UnsupportedOperationException.class);
expectedException.expectMessage("Setting 'gateway.recover_after_nodes' cannot be set/reset at runtime");
analyze("SET GLOBAL TRANSIENT gateway = {recover_after_nodes = 3}");
}
@Test
public void testResetNonRuntimeSettingObject() {
expectedException.expect(UnsupportedOperationException.class);
expectedException.expectMessage("Setting 'gateway.recover_after_nodes' cannot be set/reset at runtime");
analyze("RESET GLOBAL gateway");
}
@Test
public void testSetLoggingSetting() {
SetAnalyzedStatement analysis = analyze("SET GLOBAL TRANSIENT \"logger.action\" = 'INFo'");
assertThat(analysis.isPersistent(), is(false));
assertThat(
analysis.settings().get("logger.action").get(0),
Matchers.<Expression>is(Literal.fromObject("INFo"))
);
}
@Test
public void testResetLoggingSetting() {
ResetAnalyzedStatement analysis = analyze("RESET GLOBAL \"logger.action\"");
assertThat(analysis.settingsToRemove(), Matchers.<Set<String>>is(ImmutableSet.of("logger.action")));
}
}