Skip to content

Commit

Permalink
Fixed #9105
Browse files Browse the repository at this point in the history
  • Loading branch information
wolf4ood committed Jan 10, 2020
1 parent fb674f0 commit 1a4c8fa
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,22 @@
*/
public class OLuceneResultSet implements Set<OIdentifiable> {

private static Integer PAGE_SIZE = 10000;
private final Query query;
private final OLuceneIndexEngine engine;
private final OLuceneQueryContext queryContext;
private final String indexName;
private final Highlighter highlighter;
private final List<String> highlighted;
private final int maxNumFragments;
private static Integer PAGE_SIZE = 10000;
private Query query;
private OLuceneIndexEngine engine;
private OLuceneQueryContext queryContext;
private String indexName;
private Highlighter highlighter;
private List<String> highlighted;
private int maxNumFragments;
private TopDocs topDocs;
private long deletedMatchCount = 0;

private long deletedMatchCount = 0;
private boolean closed = false;
boolean closed = false;

protected OLuceneResultSet() {

}

public OLuceneResultSet(OLuceneIndexEngine engine, OLuceneQueryContext queryContext, ODocument metadata) {
this.engine = engine;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
*
* * Copyright 2010-2016 OrientDB LTD (http://orientdb.com)
* *
* * Licensed 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 com.orientechnologies.lucene.collections;

import com.orientechnologies.common.exception.OException;
import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.lucene.engine.OLuceneIndexEngine;
import com.orientechnologies.lucene.engine.OLuceneIndexEngineAbstract;
import com.orientechnologies.lucene.engine.OLuceneIndexEngineUtils;
import com.orientechnologies.lucene.exception.OLuceneIndexException;
import com.orientechnologies.lucene.query.OLuceneQueryContext;
import com.orientechnologies.lucene.tx.OLuceneTxChangesAbstract;
import com.orientechnologies.orient.core.command.OCommandContext;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.id.OContextualRecordId;
import com.orientechnologies.orient.core.record.impl.ODocument;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Formatter;
import org.apache.lucene.search.highlight.*;

import java.io.IOException;
import java.util.*;

/**
* Created by Enrico Risa on 16/09/15.
*/
public class OLuceneResultSetEmpty extends OLuceneResultSet {

public OLuceneResultSetEmpty() {
super();
}

@Override
public Iterator<OIdentifiable> iterator() {
return Collections.emptyIterator();
}
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
/*
* Copyright 2010-2016 OrientDB LTD (http://orientdb.com)
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* Licensed 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.
* 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.
* <p>
* For more information: http://www.orientdb.com
*/
package com.orientechnologies.spatial.engine;

import com.orientechnologies.common.exception.OException;
import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.lucene.collections.OLuceneResultSet;
import com.orientechnologies.lucene.collections.OLuceneResultSetEmpty;
import com.orientechnologies.lucene.query.OLuceneQueryContext;
import com.orientechnologies.lucene.tx.OLuceneTxChanges;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.id.OContextualRecordId;
import com.orientechnologies.orient.core.id.ORID;
import com.orientechnologies.orient.core.index.OIndexDefinition;
import com.orientechnologies.orient.core.index.OIndexEngineException;
import com.orientechnologies.orient.core.index.OIndexKeyUpdater;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.storage.OStorage;
Expand Down Expand Up @@ -72,10 +72,15 @@ public Set<OIdentifiable> getInTx(Object key, OLuceneTxChanges changes) {

}
} catch (Exception e) {
OLogManager.instance().error(this, "Error on getting entry against Lucene index", e);
if (e instanceof OException) {
OException forward = (OException) e;
throw forward;
} else {
throw OException.wrapException(new OIndexEngineException("Error parsing lucene query"), e);
}
}

return null;
return new OLuceneResultSetEmpty();
}

private Set<OIdentifiable> newGeoSearch(Map<String, Object> key, OLuceneTxChanges changes) throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,24 @@
package com.orientechnologies.spatial.functions;

import com.orientechnologies.lucene.collections.OLuceneResultSet;
import com.orientechnologies.lucene.collections.OLuceneResultSetEmpty;
import com.orientechnologies.orient.core.command.OCommandContext;
import com.orientechnologies.orient.core.db.ODatabaseDocumentInternal;
import com.orientechnologies.orient.core.db.ODatabaseRecordThreadLocal;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.exception.OCommandExecutionException;
import com.orientechnologies.orient.core.index.OIndex;
import com.orientechnologies.orient.core.metadata.OMetadata;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.sql.executor.OResult;
import com.orientechnologies.orient.core.sql.executor.OResultInternal;
import com.orientechnologies.orient.core.sql.functions.OIndexableSQLFunction;
import com.orientechnologies.orient.core.sql.parser.*;
import com.orientechnologies.spatial.index.OLuceneSpatialIndex;
import com.orientechnologies.spatial.shape.OShapeFactory;
import com.orientechnologies.spatial.strategy.SpatialQueryBuilderAbstract;

import java.text.CollationKey;
import java.util.*;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -82,6 +87,37 @@ protected OLuceneResultSet results(OFromClause target, OExpression[] args, OComm
} else {
shape = args[1].execute((OIdentifiable) null, ctx);
}

if (shape instanceof Collection) {
int size = ((Collection) shape).size();

if (size == 0) {
return new OLuceneResultSetEmpty();
}
if (size == 1) {

Object next = ((Collection) shape).iterator().next();

if (next instanceof OResult) {
OResult inner = (OResult) next;
Set<String> propertyNames = inner.getPropertyNames();
if (propertyNames.size() == 1) {
Object property = inner.getProperty(propertyNames.iterator().next());
if (property instanceof OResult) {
shape = ((OResult) property).toElement();
}
} else {
return new OLuceneResultSetEmpty();
}
}
} else {
throw new OCommandExecutionException("The collection in input cannot be major than 1");
}
}

if (shape instanceof OResultInternal) {
shape = ((OResultInternal) shape).toElement();
}
queryParams.put(SpatialQueryBuilderAbstract.SHAPE, shape);

onAfterParsing(queryParams, args, ctx, rightValue);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
/**
* Copyright 2010-2016 OrientDB LTD (http://orientdb.com)
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* Licensed 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.
* 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.
* <p>
* For more information: http://www.orientdb.com
*/
Expand All @@ -32,13 +29,13 @@
*/
public abstract class SpatialQueryBuilderAbstract {

public static final String GEO_FILTER = "geo_filter";
public static final String SHAPE = "shape";
public static final String SHAPE_TYPE = "type";
public static final String COORDINATES = "coordinates";
public static final String MAX_DISTANCE = "maxDistance";
protected OLuceneSpatialIndexContainer manager;
protected OShapeBuilder factory;
public final static String GEO_FILTER = "geo_filter";
public final static String SHAPE = "shape";
public final static String SHAPE_TYPE = "type";
public final static String COORDINATES = "coordinates";
public final static String MAX_DISTANCE = "maxDistance";
protected OLuceneSpatialIndexContainer manager;
protected OShapeBuilder factory;

public SpatialQueryBuilderAbstract(OLuceneSpatialIndexContainer manager, OShapeBuilder factory) {
this.manager = manager;
Expand All @@ -54,7 +51,12 @@ protected Shape parseShape(Map<String, Object> query) {
if (geometry == null) {
throw new OIndexEngineException("Invalid spatial query. Missing shape field " + query, null);
}
return factory.fromObject(geometry);
Shape parsed = factory.fromObject(geometry);

if (parsed == null) {
throw new OIndexEngineException("Invalid spatial query. Invalid shape field. Found: " + geometry.getClass().getName(), null);
}
return parsed;
}

protected boolean isOnlyBB(SpatialStrategy spatialStrategy) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* Copyright 2010-2016 OrientDB LTD (http://orientdb.com)
* <p>
* Licensed 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.
* <p>
* For more information: http://www.orientdb.com
*/
package com.orientechnologies.spatial;

import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.lucene.test.BaseLuceneTest;
import com.orientechnologies.orient.core.Orient;
import com.orientechnologies.orient.core.exception.OCommandExecutionException;
import com.orientechnologies.orient.core.intent.OIntentMassiveInsert;
import com.orientechnologies.orient.core.metadata.schema.OClass;
import com.orientechnologies.orient.core.metadata.schema.OSchema;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.sql.OCommandSQL;
import com.orientechnologies.orient.core.sql.executor.OResultSet;
import com.orientechnologies.orient.core.sql.query.OSQLSynchQuery;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Created by Enrico Risa on 02/10/14.
*/
public class LuceneSpatialQueryIntegrationTest extends BaseLuceneTest {

@Test
public void testIssueGH9105() {

db.command("create class Country extends V").close();
db.command("create property Country.name STRING").close();
db.command("create property Country.geometry EMBEDDED OMultiPolygon").close();
db.command("create class POI extends V").close();
db.command("create property POI.name STRING").close();
db.command("create property POI.location EMBEDDED OPoint").close();
db.command("insert into POI(name, location) values(\"zeropoint\", St_GeomFromText(\"Point(0 0)\"))").close();
db.command(
"insert into Country(name, geometry) values(\"zeroland\", St_GeomFromText(\"MultiPolygon(((1 1, 1 -1, -1 -1, -1 1, 1 1)))\"))")
.close();
db.command("CREATE INDEX POI.location ON POI(location) SPATIAL ENGINE LUCENE");
db.command("CREATE INDEX Country.geometry ON Country(geometry) SPATIAL ENGINE LUCENE;");

try (OResultSet resultSet = db.query(
"select name from Country let locations = (select from Poi) where ST_Contains(geometry, $locations[0].location) = true")) {

assertThat(resultSet.stream().count()).isEqualTo(1);
}

try (OResultSet resultSet = db
.query("select name from Country where ST_Contains(geometry, (select location from POI)) = true;")) {

assertThat(resultSet.stream().count()).isEqualTo(1);
}

try (OResultSet resultSet = db
.query("select name from Country where ST_Contains(geometry, (select name,location from POI)) = true;")) {

assertThat(resultSet.stream().count()).isEqualTo(0);
}

db.command("insert into POI(name, location) values(\"zeropoint\", St_GeomFromText(\"Point(0 0)\"))").close();

try (OResultSet resultSet = db
.query("select name from Country where ST_Contains(geometry, (select location from POI)) = true;")) {

Assert.fail("It should throw an exception");
} catch (Exception e) {
Assert.assertTrue(e instanceof OCommandExecutionException);
}

db.command("delete vertex Poi").close();

try (OResultSet resultSet = db
.query("select name from Country where ST_Contains(geometry, (select location from POI)) = true;")) {

assertThat(resultSet.stream().count()).isEqualTo(0);
}

}
}

0 comments on commit 1a4c8fa

Please sign in to comment.