/*
* Licensed to CRATE Technology GmbH ("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.integrationtests;
import io.crate.Constants;
import io.crate.action.sql.SQLActionException;
import io.crate.metadata.PartitionName;
import io.crate.metadata.TableIdent;
import io.crate.metadata.table.ColumnPolicy;
import io.crate.testing.TestingHelpers;
import io.crate.testing.UseJdbc;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.test.ESIntegTestCase;
import org.hamcrest.Matchers;
import org.junit.Test;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.Matchers.*;
@ESIntegTestCase.ClusterScope(numDataNodes = 1)
@UseJdbc
public class ColumnPolicyIntegrationTest extends SQLTransportIntegrationTest {
private String copyFilePath = Paths.get(getClass().getResource("/essetup/data/copy").toURI()).toUri().toString();
public ColumnPolicyIntegrationTest() throws URISyntaxException {
}
public MappingMetaData getMappingMetadata(String index) {
return clusterService().state().metaData().indices()
.get(index)
.getMappings().get(Constants.DEFAULT_MAPPING_TYPE);
}
public Map<String, Object> getSourceMap(String index) throws IOException {
return getMappingMetadata(index).getSourceAsMap();
}
@Test
public void testInsertNewColumnTableStrictColumnPolicy() throws Exception {
execute("create table strict_table (" +
" id integer primary key, " +
" name string" +
") with (column_policy='strict', number_of_replicas=0)");
ensureYellow();
execute("insert into strict_table (id, name) values (1, 'Ford')");
execute("refresh table strict_table");
execute("select * from strict_table");
assertThat(response.rowCount(), is(1L));
assertThat(response.cols(), is(arrayContaining("id", "name")));
assertThat(response.rows()[0], is(Matchers.<Object>arrayContaining(1, "Ford")));
expectedException.expect(SQLActionException.class);
expectedException.expectMessage("Column boo unknown");
execute("insert into strict_table (id, name, boo) values (2, 'Trillian', true)");
}
@Test
public void testUpdateNewColumnTableStrictColumnPolicy() throws Exception {
execute("create table strict_table (" +
" id integer primary key, " +
" name string" +
") with (column_policy='strict', number_of_replicas=0)");
ensureYellow();
execute("insert into strict_table (id, name) values (1, 'Ford')");
execute("refresh table strict_table");
execute("select * from strict_table");
assertThat(response.rowCount(), is(1L));
assertThat(response.cols(), is(arrayContaining("id", "name")));
assertThat(response.rows()[0], is(Matchers.<Object>arrayContaining(1, "Ford")));
expectedException.expect(SQLActionException.class);
expectedException.expectMessage("Column boo unknown");
execute("update strict_table set name='Trillian', boo=true where id=1");
}
@Test
public void testCopyFromFileStrictTable() throws Exception {
execute("create table quotes (id int primary key) with (column_policy='strict', number_of_replicas = 0)");
ensureYellow();
execute("copy quotes from ?", new Object[]{copyFilePath + "test_copy_from.json"});
assertThat(response.rowCount(), is(0L));
}
@Test
public void testInsertNewColumnTableDynamic() throws Exception {
execute("create table dynamic_table (" +
" id integer primary key, " +
" name string" +
") with (column_policy='dynamic', number_of_replicas=0)");
ensureYellow();
execute("insert into dynamic_table (id, name) values (1, 'Ford')");
execute("refresh table dynamic_table");
execute("select * from dynamic_table");
assertThat(response.rowCount(), is(1L));
assertThat(response.cols(), is(arrayContaining("id", "name")));
assertThat(response.rows()[0], is(Matchers.<Object>arrayContaining(1, "Ford")));
execute("insert into dynamic_table (id, name, boo) values (2, 'Trillian', true)");
execute("refresh table dynamic_table");
waitForMappingUpdateOnAll("dynamic_table", "boo");
execute("select * from dynamic_table order by id");
assertThat(response.rowCount(), is(2L));
assertThat(response.cols().length, is(3));
assertThat(response.cols(), is(arrayContaining("boo", "id", "name")));
assertThat(TestingHelpers.printedTable(response.rows()), is(
"NULL| 1| Ford\n" +
"true| 2| Trillian\n"));
}
@Test
public void testInsertArrayIntoDynamicTable() throws Exception {
execute("create table dynamic_table (" +
" meta string" +
") with (column_policy='dynamic', number_of_replicas=0)");
ensureYellow();
execute("insert into dynamic_table (new, meta) values(['a', 'b', 'c'], 'hello')");
execute("insert into dynamic_table (new) values(['d', 'e', 'f'])");
waitForMappingUpdateOnAll("dynamic_table", "new", "meta");
Map<String, Object> sourceMap = getSourceMap("dynamic_table");
assertThat(String.valueOf(nestedValue(sourceMap, "properties.new.type")), is("array"));
assertThat(String.valueOf(nestedValue(sourceMap, "properties.new.inner.type")), is("keyword"));
assertThat(String.valueOf(nestedValue(sourceMap, "properties.meta.type")), is("keyword"));
}
@Test
public void testInsertDynamicObjectArray() throws Exception {
execute("create table dynamic_table (person object(dynamic)) with (number_of_replicas=0)");
ensureYellow();
execute("insert into dynamic_table (person) values " +
"({name='Ford', addresses=[{city='West Country', country='GB'}]})");
refresh();
waitForMappingUpdateOnAll("dynamic_table", "person.name");
Map<String, Object> sourceMap = getSourceMap("dynamic_table");
assertThat(String.valueOf(nestedValue(sourceMap, "properties.person.properties.addresses.type")), is("array"));
assertThat(String.valueOf(nestedValue(sourceMap, "properties.person.properties.name.type")), is("keyword"));
assertThat(String.valueOf(nestedValue(sourceMap, "properties.person.properties.addresses.inner.properties.city.type")), is("keyword"));
assertThat(String.valueOf(nestedValue(sourceMap, "properties.person.properties.addresses.inner.properties.country.type")), is("keyword"));
execute("select person['name'], person['addresses']['city'] from dynamic_table ");
assertEquals(1L, response.rowCount());
assertArrayEquals(new String[]{"person['name']", "person['addresses']['city']"},
response.cols());
assertArrayEquals(new Object[]{"Ford", new Object[]{"West Country"}},
response.rows()[0]
);
}
@Test
public void testInsertNestedArrayIntoDynamicTable() throws Exception {
execute("create table dynamic_table (" +
" meta string" +
") with (column_policy='dynamic', number_of_replicas=0)");
ensureYellow();
execute("insert into dynamic_table (new, meta) values({a=['a', 'b', 'c'], nest={a=['a','b']}}, 'hello')");
execute("refresh table dynamic_table");
execute("insert into dynamic_table (new) values({a=['d', 'e', 'f']})");
execute("refresh table dynamic_table");
execute("insert into dynamic_table (new) values({nest={}, new={}})");
waitForMappingUpdateOnAll("dynamic_table", "new");
Map<String, Object> sourceMap = getSourceMap("dynamic_table");
assertThat(String.valueOf(nestedValue(sourceMap, "properties.new.properties.a.type")), is("array"));
assertThat(String.valueOf(nestedValue(sourceMap, "properties.new.properties.a.inner.type")), is("keyword"));
assertThat(String.valueOf(nestedValue(sourceMap, "properties.new.properties.nest.properties.a.type")), is("array"));
assertThat(String.valueOf(nestedValue(sourceMap, "properties.new.properties.nest.properties.a.inner.type")), is("keyword"));
assertThat(String.valueOf(nestedValue(sourceMap, "properties.meta.type")), is("keyword"));
}
@Test
public void testInsertNestedObjectOnCustomSchemaTable() throws Exception {
execute("create table c.dynamic_table (" +
" meta object(strict) as (" +
" meta object" +
" )" +
") with (column_policy='dynamic', number_of_replicas=0)");
ensureYellow();
execute("insert into c.dynamic_table (meta) values({meta={a=['a','b']}})");
execute("refresh table c.dynamic_table");
execute("insert into c.dynamic_table (meta) values({meta={a=['c','d']}})");
waitForMappingUpdateOnAll(new TableIdent("c", "dynamic_table"), "meta.meta.a");
Map<String, Object> sourceMap = getSourceMap("c.dynamic_table");
assertThat(String.valueOf(nestedValue(sourceMap, "properties.meta.properties.meta.properties.a.type")), is("array"));
assertThat(String.valueOf(nestedValue(sourceMap, "properties.meta.properties.meta.properties.a.inner.type")), is("keyword"));
}
@Test
public void testInsertMultipleValuesDynamic() throws Exception {
execute("create table dynamic_table (" +
" my_object object " +
") with (column_policy='dynamic', number_of_replicas=0)");
ensureYellow();
execute("insert into dynamic_table (my_object) values ({a=['a','b']}),({b=['a']})");
execute("refresh table dynamic_table");
waitForMappingUpdateOnAll("dynamic_table", "my_object.a", "my_object.b");
Map<String, Object> sourceMap = getSourceMap("dynamic_table");
assertThat(String.valueOf(nestedValue(sourceMap, "properties.my_object.properties.a.type")), is("array"));
assertThat(String.valueOf(nestedValue(sourceMap, "properties.my_object.properties.a.inner.type")), is("keyword"));
assertThat(String.valueOf(nestedValue(sourceMap, "properties.my_object.properties.b.type")), is("array"));
assertThat(String.valueOf(nestedValue(sourceMap, "properties.my_object.properties.b.inner.type")), is("keyword"));
}
@Test
public void testAddColumnToStrictObject() throws Exception {
execute("create table books(" +
" author object(dynamic) as (" +
" name object(strict) as (" +
" first_name string" +
" )" +
" )," +
" title string" +
")");
ensureYellow();
Map<String, Object> authorMap = new HashMap<String, Object>() {{
put("name", new HashMap<String, Object>() {{
put("first_name", "Douglas");
}});
}};
execute("insert into books (title, author) values (?,?)",
new Object[]{
"The Hitchhiker's Guide to the Galaxy",
authorMap
});
execute("refresh table books");
expectedException.expect(SQLActionException.class);
expectedException.expectMessage("Column author['name']['middle_name'] unknown");
authorMap = new HashMap<String, Object>() {{
put("name", new HashMap<String, Object>() {{
put("first_name", "Douglas");
put("middle_name", "Noel");
}});
}};
execute("insert into books (title, author) values (?,?)",
new Object[]{
"Life, the Universe and Everything",
authorMap
});
}
public Object nestedValue(Map<String, Object> map, String dottedPath) {
String[] paths = dottedPath.split("\\.");
Object value = null;
for (String key : paths) {
value = map.get(key);
if (value instanceof Map) {
map = (Map<String, Object>) map.get(key);
}
}
return value;
}
@Test
public void testUpdateNewColumnTableDynamic() throws Exception {
execute("create table dynamic_table (" +
" id integer primary key, " +
" name string" +
") with (column_policy='dynamic', number_of_replicas=0)");
ensureYellow();
execute("insert into dynamic_table (id, name) values (1, 'Ford')");
execute("refresh table dynamic_table");
execute("select * from dynamic_table");
assertThat(response.rowCount(), is(1L));
assertThat(response.cols(), is(arrayContaining("id", "name")));
assertThat(response.rows()[0], is(Matchers.<Object>arrayContaining(1, "Ford")));
execute("update dynamic_table set name='Trillian', boo=true where name='Ford'");
execute("refresh table dynamic_table");
waitForMappingUpdateOnAll("dynamic_table", "boo");
execute("select * from dynamic_table");
assertThat(response.rowCount(), is(1L));
assertThat(response.cols(), is(arrayContaining("boo", "id", "name")));
assertThat(response.rows()[0], is(Matchers.<Object>arrayContaining(true, 1, "Trillian")));
}
@Test
public void testInsertNewColumnTableDefault() throws Exception {
execute("create table dynamic_table (" +
" id integer primary key, " +
" score double" +
") with (number_of_replicas=0)");
ensureYellow();
execute("insert into dynamic_table (id, score) values (1, 42.24)");
execute("refresh table dynamic_table");
execute("select * from dynamic_table");
assertThat(response.rowCount(), is(1L));
assertThat(response.cols(), is(arrayContaining("id", "score")));
assertThat(response.rows()[0], is(Matchers.<Object>arrayContaining(1, 42.24D)));
execute("insert into dynamic_table (id, score, good) values (2, -0.01, false)");
execute("refresh table dynamic_table");
waitForMappingUpdateOnAll("dynamic_table", "good");
execute("select * from dynamic_table order by id");
assertThat(response.rowCount(), is(2L));
assertThat(response.cols(), is(arrayContaining("good", "id", "score")));
assertThat(TestingHelpers.printedTable(response.rows()), is(
"NULL| 1| 42.24\n" +
"false| 2| -0.01\n"));
}
@Test
public void testUpdateNewColumnTableDefault() throws Exception {
execute("create table dynamic_table (" +
" id integer primary key, " +
" score double" +
") with (number_of_replicas=0)");
ensureYellow();
execute("insert into dynamic_table (id, score) values (1, 4656234.345)");
execute("refresh table dynamic_table");
execute("select * from dynamic_table");
assertThat(response.rowCount(), is(1L));
assertThat(response.cols(), is(arrayContaining("id", "score")));
assertThat(response.rows()[0], is(Matchers.<Object>arrayContaining(1, 4656234.345D)));
execute("update dynamic_table set name='Trillian', good=true where score > 0.0");
execute("refresh table dynamic_table");
waitForMappingUpdateOnAll("dynamic_table", "name");
execute("select * from dynamic_table");
assertThat(response.rowCount(), is(1L));
assertThat(response.cols(), is(arrayContaining("good", "id", "name", "score")));
assertThat(response.rows()[0], is(Matchers.<Object>arrayContaining(true, 1, "Trillian", 4656234.345D)));
}
@Test
public void testStrictPartitionedTableInsert() throws Exception {
execute("create table numbers (" +
" num int, " +
" odd boolean," +
" prime boolean" +
") partitioned by (odd) with (column_policy='strict', number_of_replicas=0)");
ensureYellow();
GetIndexTemplatesResponse response = client().admin().indices()
.prepareGetTemplates(PartitionName.templateName(null, "numbers"))
.execute().actionGet();
assertThat(response.getIndexTemplates().size(), is(1));
IndexTemplateMetaData template = response.getIndexTemplates().get(0);
CompressedXContent mappingStr = template.mappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(mappingStr, is(notNullValue()));
Tuple<XContentType, Map<String, Object>> typeAndMap = XContentHelper.convertToMap(mappingStr.compressedReference(), false);
@SuppressWarnings("unchecked")
Map<String, Object> mapping = (Map<String, Object>) typeAndMap.v2().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(mapping.get("dynamic")), is(ColumnPolicy.STRICT.value()));
execute("insert into numbers (num, odd, prime) values (?, ?, ?)",
new Object[]{6, true, false});
execute("refresh table numbers");
MappingMetaData partitionMetaData = clusterService().state().metaData().indices()
.get(new PartitionName("numbers", Arrays.asList(new BytesRef("true"))).asIndexName())
.getMappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(partitionMetaData.getSourceAsMap().get("dynamic")), is(ColumnPolicy.STRICT.value()));
expectedException.expect(SQLActionException.class);
expectedException.expectMessage("Column perfect unknown");
execute("insert into numbers (num, odd, prime, perfect) values (?, ?, ?, ?)",
new Object[]{28, true, false, true});
}
@Test
public void testStrictPartitionedTableUpdate() throws Exception {
execute("create table numbers (" +
" num int, " +
" odd boolean," +
" prime boolean" +
") partitioned by (odd) with (column_policy='strict', number_of_replicas=0)");
ensureYellow();
GetIndexTemplatesResponse response = client().admin().indices()
.prepareGetTemplates(PartitionName.templateName(null, "numbers"))
.execute().actionGet();
assertThat(response.getIndexTemplates().size(), is(1));
IndexTemplateMetaData template = response.getIndexTemplates().get(0);
CompressedXContent mappingStr = template.mappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(mappingStr, is(notNullValue()));
Tuple<XContentType, Map<String, Object>> typeAndMap = XContentHelper.convertToMap(mappingStr.compressedReference(), false);
@SuppressWarnings("unchecked")
Map<String, Object> mapping = (Map<String, Object>) typeAndMap.v2().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(mapping.get("dynamic")), is(ColumnPolicy.STRICT.value()));
execute("insert into numbers (num, odd, prime) values (?, ?, ?)",
new Object[]{6, true, false});
execute("refresh table numbers");
MappingMetaData partitionMetaData = clusterService().state().metaData().indices()
.get(new PartitionName("numbers", Arrays.asList(new BytesRef("true"))).asIndexName())
.getMappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(partitionMetaData.getSourceAsMap().get("dynamic")), is(ColumnPolicy.STRICT.value()));
expectedException.expect(SQLActionException.class);
expectedException.expectMessage("Column perfect unknown");
execute("update numbers set num=?, perfect=? where num=6",
new Object[]{28, true});
}
@Test
public void testDynamicPartitionedTable() throws Exception {
execute("create table numbers (" +
" num int, " +
" odd boolean," +
" prime boolean" +
") partitioned by (odd) with (column_policy='dynamic', number_of_replicas=0)");
ensureYellow();
GetIndexTemplatesResponse templateResponse = client().admin().indices()
.prepareGetTemplates(PartitionName.templateName(null, "numbers"))
.execute().actionGet();
assertThat(templateResponse.getIndexTemplates().size(), is(1));
IndexTemplateMetaData template = templateResponse.getIndexTemplates().get(0);
CompressedXContent mappingStr = template.mappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(mappingStr, is(notNullValue()));
Tuple<XContentType, Map<String, Object>> typeAndMap = XContentHelper.convertToMap(mappingStr.compressedReference(), false);
@SuppressWarnings("unchecked")
Map<String, Object> mapping = (Map<String, Object>) typeAndMap.v2().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(mapping.get("dynamic")), is("true"));
execute("insert into numbers (num, odd, prime) values (?, ?, ?)",
new Object[]{6, true, false});
execute("refresh table numbers");
MappingMetaData partitionMetaData = clusterService().state().metaData().indices()
.get(new PartitionName("numbers", Collections.singletonList(new BytesRef("true"))).asIndexName())
.getMappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(partitionMetaData.getSourceAsMap().get("dynamic")), is("true"));
execute("insert into numbers (num, odd, prime, perfect) values (?, ?, ?, ?)",
new Object[]{28, true, false, true});
ensureYellow();
execute("refresh table numbers");
waitForMappingUpdateOnAll("numbers", "perfect");
execute("select * from numbers order by num");
assertThat(response.rowCount(), is(2L));
assertThat(response.cols(), arrayContaining("num", "odd", "perfect", "prime"));
assertThat(TestingHelpers.printedTable(response.rows()), is(
"6| true| NULL| false\n" +
"28| true| true| false\n"));
execute("update numbers set prime=true, changed='2014-10-23T10:20', author='troll' where num=28");
assertThat(response.rowCount(), is(1L));
waitForMappingUpdateOnAll("numbers", "changed");
}
@Test
public void testAlterDynamicTable() throws Exception {
execute("create table dynamic_table (" +
" id integer primary key, " +
" score double" +
") with (number_of_replicas=0)");
ensureYellow();
execute("alter table dynamic_table set (column_policy = 'strict')");
waitNoPendingTasksOnAll();
expectedException.expect(SQLActionException.class);
expectedException.expectMessage("Column new_col unknown");
execute("insert into dynamic_table (id, score, new_col) values (1, 4656234.345, 'hello')");
}
@Test
public void testAlterTable() throws Exception {
execute("create table dynamic_table (" +
" id integer primary key, " +
" score double" +
") with (number_of_replicas=0, column_policy='strict')");
ensureYellow();
execute("insert into dynamic_table (id, score) values (1, 42)");
execute("alter table dynamic_table set (column_policy = 'dynamic')");
waitNoPendingTasksOnAll();
execute("insert into dynamic_table (id, score, new_col) values (2, 4656234.345, 'hello')");
}
@Test
public void testResetColumnPolicy() throws Exception {
execute("create table dynamic_table (" +
" id integer, " +
" score double" +
") with (number_of_replicas=0)");
ensureYellow();
execute("alter table dynamic_table set (column_policy = 'strict')");
waitNoPendingTasksOnAll();
MappingMetaData partitionMetaData = clusterService().state().metaData().indices()
.get("dynamic_table")
.getMappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(partitionMetaData.getSourceAsMap().get("dynamic")), is(ColumnPolicy.STRICT.value()));
execute("alter table dynamic_table reset (column_policy)");
waitNoPendingTasksOnAll();
partitionMetaData = clusterService().state().metaData().indices()
.get("dynamic_table")
.getMappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(partitionMetaData.getSourceAsMap().get("dynamic")), is(String.valueOf(ColumnPolicy.DYNAMIC.mappingValue())));
}
@Test
public void testResetColumnPolicyPartitioned() throws Exception {
execute("create table dynamic_table (" +
" id integer, " +
" score double" +
") partitioned by (score) with (number_of_replicas=0)");
ensureYellow();
execute("insert into dynamic_table (id, score) values (1, 10)");
execute("refresh table dynamic_table");
execute("alter table dynamic_table set (column_policy = 'strict')");
waitNoPendingTasksOnAll();
MappingMetaData partitionMetaData = clusterService().state().metaData().indices()
.get(new PartitionName("dynamic_table", Arrays.asList(new BytesRef("10.0"))).asIndexName())
.getMappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(partitionMetaData.getSourceAsMap().get("dynamic")), is(ColumnPolicy.STRICT.value()));
execute("alter table dynamic_table reset (column_policy)");
waitNoPendingTasksOnAll();
partitionMetaData = clusterService().state().metaData().indices()
.get(new PartitionName("dynamic_table", Arrays.asList(new BytesRef("10.0"))).asIndexName())
.getMappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(partitionMetaData.getSourceAsMap().get("dynamic")), is(String.valueOf(ColumnPolicy.DYNAMIC.mappingValue())));
}
@Test
public void testAlterColumnPolicyOnPartitionedTableWithExistingPartitions() throws Exception {
execute("create table dynamic_table (" +
" id integer, " +
" score double" +
") partitioned by (score) with (number_of_replicas=0, column_policy='strict')");
ensureYellow();
// create at least 2 partitions to test real multi partition logic (1 partition would behave similar to 1 normal table)
execute("insert into dynamic_table (id, score) values (1, 10)");
execute("insert into dynamic_table (id, score) values (1, 20)");
execute("refresh table dynamic_table");
ensureYellow();
execute("alter table dynamic_table set (column_policy = 'dynamic')");
waitNoPendingTasksOnAll();
// After changing the column_policy it's possible to add new columns to existing and new
// partitions
execute("insert into dynamic_table (id, score, comment) values (2, 10, 'this is a new column')");
execute("insert into dynamic_table (id, score, new_comment) values (2, 5, 'this is a new column on a new partition')");
execute("refresh table dynamic_table");
ensureYellow();
GetIndexTemplatesResponse response = client().admin().indices()
.prepareGetTemplates(PartitionName.templateName(null, "dynamic_table"))
.execute().actionGet();
assertThat(response.getIndexTemplates().size(), is(1));
IndexTemplateMetaData template = response.getIndexTemplates().get(0);
CompressedXContent mappingStr = template.mappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(mappingStr, is(notNullValue()));
Tuple<XContentType, Map<String, Object>> typeAndMap = XContentHelper.convertToMap(mappingStr.compressedReference(), false);
@SuppressWarnings("unchecked")
Map<String, Object> mapping = (Map<String, Object>) typeAndMap.v2().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(mapping.get("dynamic")), is(String.valueOf(ColumnPolicy.DYNAMIC.mappingValue())));
execute("insert into dynamic_table (id, score, new_col) values (?, ?, ?)",
new Object[]{6, 3, "hello"});
execute("refresh table dynamic_table");
ensureYellow();
MappingMetaData partitionMetaData = clusterService().state().metaData().indices()
.get(new PartitionName("dynamic_table", Arrays.asList(new BytesRef("10.0"))).asIndexName())
.getMappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(partitionMetaData.getSourceAsMap().get("dynamic")), is(String.valueOf(ColumnPolicy.DYNAMIC.mappingValue())));
partitionMetaData = clusterService().state().metaData().indices()
.get(new PartitionName("dynamic_table", Arrays.asList(new BytesRef("5.0"))).asIndexName())
.getMappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(partitionMetaData.getSourceAsMap().get("dynamic")), is(String.valueOf(ColumnPolicy.DYNAMIC.mappingValue())));
partitionMetaData = clusterService().state().metaData().indices()
.get(new PartitionName("dynamic_table", Arrays.asList(new BytesRef("3.0"))).asIndexName())
.getMappings().get(Constants.DEFAULT_MAPPING_TYPE);
assertThat(String.valueOf(partitionMetaData.getSourceAsMap().get("dynamic")), is(String.valueOf(ColumnPolicy.DYNAMIC.mappingValue())));
}
}