/* * 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.integrationtests; import com.google.common.collect.ImmutableMap; import io.crate.testing.TestingHelpers; import io.crate.testing.UseJdbc; import org.junit.Before; import org.junit.Test; import java.util.Map; import static com.carrotsearch.randomizedtesting.RandomizedTest.$; import static com.carrotsearch.randomizedtesting.RandomizedTest.$$; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.core.Is.is; @UseJdbc public class GeoShapeIntegrationTest extends SQLTransportIntegrationTest { private static final Map GEO_SHAPE1 = ImmutableMap.of( "coordinates", new double[][]{ {0, 0}, {1, 1} }, "type", "LineString" ); private static final Map GEO_SHAPE2 = ImmutableMap.of( "coordinates", new double[][]{ {2, 2}, {3, 3} }, "type", "LineString" ); @Before public void prepare() throws Exception { execute("CREATE TABLE shaped (" + " id long primary key," + " shape geo_shape," + " shapes array(geo_shape)" + ") with (number_of_replicas=0)"); ensureGreen(); execute("INSERT INTO shaped (id, shape) VALUES (?, ?)", $$($(1L, "POINT (13.0 52.4)"), $(2L, GEO_SHAPE1))); execute("INSERT INTO shaped (id, shapes) VALUES (?, ?)", $(3, new Object[]{GEO_SHAPE1, GEO_SHAPE2})); execute("REFRESH TABLE shaped"); } @Test public void testSelectGeoShapeFromSource() throws Exception { execute("select shape from shaped where id in (1, 2) order by id"); assertThat(TestingHelpers.printedTable(response.rows()), is( "{coordinates=[13.0, 52.4], type=Point}\n" + "{coordinates=[[0.0, 0.0], [1.0, 1.0]], type=LineString}\n")); //TODO: Re-enable once SQLResponse also includes the data types for the columns // assertThat(response.columnTypes()[0], is((DataType) DataTypes.GEO_SHAPE)); assertThat(response.rows()[0][0], instanceOf(Map.class)); assertThat(response.rows()[1][0], instanceOf(Map.class)); execute("select shapes from shaped where id = 3"); assertThat(TestingHelpers.printedTable(response.rows()), is( "[{coordinates=[[0.0, 0.0], [1.0, 1.0]], type=LineString}, " + "{coordinates=[[2.0, 2.0], [3.0, 3.0]], type=LineString}]\n")); //TODO: Re-enable once SQLResponse also includes the data types for the columns // assertThat(response.columnTypes()[0], is((DataType) new ArrayType(DataTypes.GEO_SHAPE))); assertThat(response.rows()[0][0], instanceOf(Object[].class)); } @Test public void testIndexWithES() throws Exception { execute("create table test (shape geo_shape)"); ensureYellow(); client().prepareIndex("test", "default", "test").setSource(jsonBuilder().startObject() .startObject("shape") .field("type", "polygon") .startArray("coordinates").startArray() .startArray().value(-122.83).value(48.57).endArray() .startArray().value(-122.77).value(48.56).endArray() .startArray().value(-122.79).value(48.53).endArray() .startArray().value(-122.83).value(48.57).endArray() // close the polygon .endArray().endArray() .endObject() .endObject()).execute().actionGet(); execute("refresh table test"); execute("select shape from test"); assertThat(response.rowCount(), is(1L)); assertThat(TestingHelpers.printedTable(response.rows()), is( "{coordinates=[[[-122.83, 48.57], [-122.77, 48.56], [-122.79, 48.53], [-122.83, 48.57]]], type=polygon}\n")); //TODO: Re-enable once SQLResponse also includes the data types for the columns // assertThat(response.columnTypes()[0], is((DataType) DataTypes.GEO_SHAPE)); assertThat(response.rows()[0][0], instanceOf(Map.class)); } @Test public void testShowCreateTable() throws Exception { execute("create table test (" + "col1 geo_shape INDEX using QUADTREE with (precision='1m', distance_error_pct='0.25')" + ") " + "CLUSTERED INTO 1 SHARDS"); ensureYellow(); execute("show create table test"); String expected = "CREATE TABLE IF NOT EXISTS \"doc\".\"test\" (\n" + " \"col1\" GEO_SHAPE INDEX USING QUADTREE WITH (\n" + " distance_error_pct = 0.25,\n" + " precision = '1.0m'\n" + " )\n" + ")\n" + "CLUSTERED INTO 1 SHARDS\n" + "WITH (\n"; assertEquals(response.rowCount(), 1L); assertThat((String) response.rows()[0][0], startsWith(expected)); // execute the statement again and compare it with the SHOW CREATE TABLE result String stmt = (String) response.rows()[0][0]; execute("drop table test"); execute(stmt); ensureYellow(); execute("show create table test"); assertEquals(response.rows()[0][0], stmt); } @Test public void testShowCreateTableWithDefaultValues() throws Exception { execute("create table test (" + "col1 geo_shape" + ") " + "CLUSTERED INTO 1 SHARDS"); ensureYellow(); execute("show create table test"); String expected = "CREATE TABLE IF NOT EXISTS \"doc\".\"test\" (\n" + " \"col1\" GEO_SHAPE INDEX USING GEOHASH\n" + ")\n" + "CLUSTERED INTO 1 SHARDS\n" + "WITH (\n"; assertEquals(response.rowCount(), 1L); assertThat((String) response.rows()[0][0], startsWith(expected)); } @Test public void testGeoMatchTest() throws Exception { execute("select id from shaped where match(shape, " + "'POLYGON((12.998725175857544 52.40087142225922," + "13.002265691757202 52.40087142225922," + "13.002265691757202 52.39927416492016," + "12.998725175857544 52.39927416492016," + "12.998725175857544 52.40087142225922))')"); assertThat(response.rowCount(), is(1L)); assertThat(((long) response.rows()[0][0]), is(1L)); execute("delete from shaped where match(shape, " + "{" + " type='Polygon', " + " coordinates=[[[12.998725175857544, 52.40087142225922], " + " [13.002265691757202, 52.40087142225922], " + " [12.998725175857544, 52.39927416492016], " + " [12.998725175857544, 52.40087142225922]]]})"); execute("refresh table shaped"); execute("select count(*) from shaped"); assertThat(((long) response.rows()[0][0]), is(2L)); } @Test public void testSelectWhereIntersects() throws Exception { execute("select id from shaped where intersects(shape, ?) order by id", $("POLYGON(" + "(12.995452 52.417497," + " 13.051071 52.424407," + " 13.053474 52.403047," + " 13.046951 52.400743," + " 13.069953 52.391944," + " 13.024635 52.354425," + " 12.970390 52.347714," + " 12.995452 52.417497))")); assertThat(response.rowCount(), is(1L)); assertThat(response.rows()[0][0], is((Object) 1L)); } @Test public void testGeoPointInPolygonQueryLuceneBug() { // Relates to https://github.com/elastic/elasticsearch/issues/20333 // and fails if GeoPointInPolygonQuery is used in LuceneQueryBuilder.getPolygonQuery() execute("create table test(id integer, geopos geo_point)"); ensureYellow(); execute("insert into test (id, geopos) values(1, 'POINT(-0.35842 51.46961)')"); execute("refresh table test"); execute("select * from test where within(geopos, 'POLYGON((-0.129089 51.536726, -0.126686 51.536726, " + "-0.125999 51.536512, -0.125656 51.536512, -0.125312 51.536299, -0.125312 51.535444, " + "-0.125656 51.535231, -0.128402 51.53395, -0.128746 51.53395, -0.129432 51.533736, " + "-0.129776 51.533736, -0.130462 51.53395, -0.130805 51.53395, -0.131149 51.534163, " + "-0.131835 51.534804, -0.131835 51.535017, -0.131492 51.535444, -0.129776 51.536512, " + "-0.129089 51.536726))')"); assertThat(response.rowCount(), is(0L)); } }