/* * 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.action.sql.SQLActionException; import org.elasticsearch.common.collect.MapBuilder; import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import java.util.HashMap; import java.util.Map; import static org.hamcrest.Matchers.is; public class ObjectColumnTest extends SQLTransportIntegrationTest { private Setup setup = new Setup(sqlExecutor); @Before public void initTestData() { this.setup.setUpObjectTable(); ensureYellow(); } @Test public void testInsertIntoDynamicObject() throws Exception { Map<String, Object> authorMap = new HashMap<String, Object>() {{ put("name", new HashMap<String, Object>() {{ put("first_name", "Douglas"); put("last_name", "Adams"); }}); put("age", 49); }}; execute("insert into ot (title, author) values (?, ?)", new Object[]{ "Life, the Universe and Everything", authorMap }); refresh(); execute("select title, author from ot order by title"); assertEquals(2, response.rowCount()); assertEquals("Life, the Universe and Everything", response.rows()[0][0]); assertEquals(authorMap, response.rows()[0][1]); } @Test public void testAddColumnToDynamicObject() throws Exception { Map<String, Object> authorMap = new HashMap<String, Object>() {{ put("name", new HashMap<String, Object>() {{ put("first_name", "Douglas"); put("last_name", "Adams"); }}); put("dead", true); put("age", 49); }}; execute("insert into ot (title, author) values (?, ?)", new Object[]{ "Life, the Universe and Everything", authorMap }); refresh(); waitForMappingUpdateOnAll("ot", "author.dead"); execute("select title, author, author['dead'] from ot order by title"); assertEquals(2, response.rowCount()); assertEquals("Life, the Universe and Everything", response.rows()[0][0]); assertEquals(authorMap, response.rows()[0][1]); assertEquals(true, response.rows()[0][2]); } @Test public void testAddColumnToIgnoredObject() throws Exception { Map<String, Object> detailMap = new HashMap<String, Object>() {{ put("num_pages", 240); put("publishing_date", "1982-01-01"); put("isbn", "978-0345391827"); put("weight", 4.8d); }}; execute("insert into ot (title, details) values (?, ?)", new Object[]{ "Life, the Universe and Everything", detailMap }); refresh(); execute("select title, details, details['weight'], details['publishing_date'] from ot order by title"); assertEquals(2, response.rowCount()); assertEquals("Life, the Universe and Everything", response.rows()[0][0]); assertEquals(detailMap, response.rows()[0][1]); assertEquals(4.8d, response.rows()[0][2]); assertEquals("1982-01-01", response.rows()[0][3]); } @Test public void testAddColumnToStrictObject() throws Exception { expectedException.expect(SQLActionException.class); expectedException.expectMessage("Column author['name']['middle_name'] unknown"); Map<String, Object> authorMap = new HashMap<String, Object>() {{ put("name", new HashMap<String, Object>() {{ put("first_name", "Douglas"); put("middle_name", "Noel"); put("last_name", "Adams"); }}); put("age", 49); }}; execute("insert into ot (title, author) values (?, ?)", new Object[]{ "Life, the Universe and Everything", authorMap }); } @Test public void updateToDynamicObject() throws Exception { execute("update ot set author['job']='Writer' " + "where author['name']['first_name']='Douglas' and author['name']['last_name']='Adams'"); refresh(); waitForMappingUpdateOnAll("ot", "author.job"); execute("select author, author['job'] from ot " + "where author['name']['first_name']='Douglas' and author['name']['last_name']='Adams'"); assertEquals(1, response.rowCount()); assertEquals( new HashMap<String, Object>() {{ put("name", new HashMap<String, Object>() {{ put("first_name", "Douglas"); put("last_name", "Adams"); }}); put("age", 49); put("job", "Writer"); }}, response.rows()[0][0] ); assertEquals("Writer", response.rows()[0][1]); } @Test public void updateToIgnoredObject() throws Exception { execute("update ot set details['published']='1978-01-01' " + "where title=?", new Object[]{"The Hitchhiker's Guide to the Galaxy"}); refresh(); execute("select details, details['published'] from ot where title=?", new Object[]{"The Hitchhiker's Guide to the Galaxy"}); assertEquals(1, response.rowCount()); assertEquals( new HashMap<String, Object>() {{ put("num_pages", 224); put("published", "1978-01-01"); }}, response.rows()[0][0] ); assertEquals("1978-01-01", response.rows()[0][1]); } @Test public void updateToStrictObject() throws Exception { expectedException.expect(SQLActionException.class); expectedException.expectMessage("Column author['name']['middle_name'] unknown"); execute("update ot set author['name']['middle_name']='Noel' " + "where author['name']['first_name']='Douglas' and author['name']['last_name']='Adams'"); } @Test public void selectDynamicAddedColumnWhere() throws Exception { Map<String, Object> authorMap = new HashMap<String, Object>() {{ put("name", new HashMap<String, Object>() {{ put("first_name", "Douglas"); put("last_name", "Adams"); }}); put("dead", true); put("age", 49); }}; execute("insert into ot (title, author) values (?, ?)", new Object[]{ "Life, the Universe and Everything", authorMap }); refresh(); waitForMappingUpdateOnAll("ot", "author.dead"); execute("select author from ot where author['dead']=true"); assertEquals(1, response.rowCount()); assertEquals(authorMap, response.rows()[0][0]); } @Test public void selectIgnoredAddedColumnWhere() throws Exception { Map<String, Object> detailMap = new HashMap<String, Object>() {{ put("num_pages", 240); put("publishing_date", "1982-01-01"); put("isbn", "978-0345391827"); put("weight", 4.8d); }}; execute("insert into ot (title, details) values (?, ?)", new Object[]{ "Life, the Universe and Everything", detailMap }); refresh(); execute("select details from ot where details['isbn']='978-0345391827'"); assertEquals(1, response.rowCount()); execute("select details from ot where details['num_pages']>224"); assertEquals(1, response.rowCount()); assertEquals(detailMap, response.rows()[0][0]); } @Test public void selectDynamicAddedColumnOrderBy() throws Exception { Map<String, Object> authorMap = new HashMap<String, Object>() {{ put("name", new HashMap<String, Object>() {{ put("first_name", "Douglas"); put("last_name", "Adams"); }}); put("dead", true); put("age", 49); }}; execute("insert into ot (title, author) values (?, ?)", new Object[]{ "Life, the Universe and Everything", authorMap } ); execute("insert into ot (title, author) values (?, ?)", new Object[]{ "Don't Panic: Douglas Adams and the \"Hitchhiker's Guide to the Galaxy\"", new HashMap<String, Object>() {{ put("name", new HashMap<String, Object>() {{ put("first_name", "Neil"); put("last_name", "Gaiman"); }}); put("dead", false); put("age", 53); }} } ); refresh(); waitForMappingUpdateOnAll("ot", "author.dead"); execute("select title, author['dead'] from ot order by author['dead'] desc"); assertEquals(3, response.rowCount()); assertEquals("The Hitchhiker's Guide to the Galaxy", response.rows()[0][0]); assertNull(response.rows()[0][1]); assertEquals("Life, the Universe and Everything", response.rows()[1][0]); assertEquals(true, response.rows()[1][1]); assertEquals("Don't Panic: Douglas Adams and the \"Hitchhiker's Guide to the Galaxy\"", response.rows()[2][0]); assertEquals(false, response.rows()[2][1]); } @Test public void testSelectDynamicObjectNewColumns() throws Exception { execute("create table test (message string, person object(dynamic)) with (number_of_replicas=0)"); ensureYellow(); execute("insert into test (message, person) values " + "('I''m addicted to kite', {name='Youri', addresses=[{city='Dirksland', country='NL'}]})"); execute("refresh table test"); waitForMappingUpdateOnAll("test", "person.name"); execute("select message, person['name'], person['addresses']['city'] from test " + "where person['name'] = 'Youri'"); assertEquals(1L, response.rowCount()); assertArrayEquals(new String[]{"message", "person['name']", "person['addresses']['city']"}, response.cols()); assertArrayEquals( new Object[]{"I'm addicted to kite", "Youri", new Object[]{"Dirksland"}}, response.rows()[0] ); } @Test public void testSelectObject() throws Exception { execute("create table test (a object as (nested integer)) with (number_of_replicas=0)"); ensureYellow(); execute("insert into test (a) values (?)", new Object[]{ new MapBuilder<String, Object>().put("nested", 2).map() }); refresh(); execute("select a from test"); assertArrayEquals(new String[]{"a"}, response.cols()); assertEquals(1, response.rowCount()); assertEquals(1, response.rows()[0].length); assertThat((Map<String, Object>) response.rows()[0][0], Matchers.<String, Object>hasEntry("nested", 2)); } @Test public void testAddRestrictedColumnName() throws Exception { execute("create table test (foo object)"); ensureYellow(); execute("INSERT INTO test (o) (select {\"_w\"= 20})"); refresh(); execute("select count(*) from test"); assertThat(response.rows()[0][0], is(0L)); } }