Author: vgritsenko Date: Tue Jan 30 18:06:42 2007 New Revision: 501690 URL: http://svn.apache.org/viewvc?view=rev&rev=501690 Log: <action dev="VG" type="fix" fixes-bug="38886" due-to="Terry Rosenbaum"> Fix MemValueIndexer for starts-with queries. </action>
Added: xml/xindice/trunk/java/tests/src/org/apache/xindice/core/indexer/MemValueIndexerTest.java (with props) Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/MemValueIndexer.java xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/ValueIndexer.java xml/xindice/trunk/java/tests/src/org/apache/xindice/core/indexer/ValueIndexerTest.java xml/xindice/trunk/java/tests/src/org/apache/xindice/integration/client/services/IndexedSearchTest.java xml/xindice/trunk/status.xml Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/MemValueIndexer.java URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/MemValueIndexer.java?view=diff&rev=501690&r1=501689&r2=501690 ============================================================================== --- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/MemValueIndexer.java (original) +++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/MemValueIndexer.java Tue Jan 30 18:06:42 2007 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2005 The Apache Software Foundation. + * Copyright 1999-2007 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -87,7 +87,7 @@ private static final String CHAR_VAL = "char"; private static final String BOOLEAN_VAL = "boolean"; - private static final IndexMatch[] EMPTY_INDEX_MATCH_ARRAY = new IndexMatch[0]; + private final static IndexMatch[] EMPTY_INDEX_MATCH_ARRAY = new IndexMatch[0]; // // Instance variables @@ -410,17 +410,13 @@ // always compare against the String form of the comparator // to ensure that comparisons happen as Strings as specified by XPath // for starts-with - aLowEndpoint = aQueryValueList[0]; - if (itsValueType == TRIMMED) { - aLowEndpoint = QueryEngine.normalizeString((String) aLowEndpoint); - } else { - if (itsValueType != STRING) { - aLowEndpoint = ((String) aLowEndpoint).trim(); - } + if(! (aLowEndpoint instanceof String) ) + { + aLowEndpoint = aLowEndpoint.toString(); } // get the matching submap forcing String comparisons to be used regardless of stored type - aResult = getIndexMatchArray(getBWSubmap(aLowEndpoint, aLowEndpoint)); + aResult = getIndexMatchArray(getSWSubmap((String)aLowEndpoint)); break; case IndexQuery.IN: // In the (presumed sorted) set of specified query values @@ -447,13 +443,9 @@ // implement as LT or GT forcing String comparisons // we get the raw String match value and use that instead of the typed value // to force String comparisons (as required for starts-with) - aLowEndpoint = aQueryValueList[0]; - if (itsValueType == TRIMMED) { - aLowEndpoint = QueryEngine.normalizeString((String) aLowEndpoint); - } else { - if (itsValueType != STRING) { - aLowEndpoint = ((String) aLowEndpoint).trim(); - } + if(! (aLowEndpoint instanceof String) ) + { + aLowEndpoint = aLowEndpoint.toString(); } // get all matches below starts-with range and above starts-with range @@ -495,6 +487,31 @@ } /** + * Provides the submap containing the half-open range (inclusive of Low Endpoint but not High Endpoint) + * between the theLowEndpoint and getNextValueOf(theLowEndpoint, STRING). + * + * @param theLowEndpoint low endpoint to use + * @return a SortedMap containing the matches or null if no matches + */ + private SortedMap getSWSubmap(String theLowEndpoint) { + SortedMap aSubmap; + + // force computation of next value as STRING if key is String + // otherwise, next value will be of same type as stored values + String aHighEndpoint = (String) getNextValueOf(theLowEndpoint, STRING); + + if (aHighEndpoint == null) { + // return locators in tail map from low endpoint + aSubmap = itsValues.tailMap(theLowEndpoint); + } else { + // return locators in sub map inclusive of endpoints + aSubmap = itsValues.subMap(theLowEndpoint, aHighEndpoint); + } + + return aSubmap == null || aSubmap.size() == 0 ? null : aSubmap; + } + + /** * Provides the submap containing the closed range (inclusive of both endpoints) * between the specified endpoints. * @@ -1036,7 +1053,9 @@ return theValue + "\0"; } // return a string of the same length with the final character incremented by 1 - aReturn = ((String) theValue).substring(0, aLength - 1) + String.valueOf(aLastChar + 1); + // be sure to avoid upcasting to int which would happen if you do "a" + (aLastChar + 1) + aLastChar += 1; + aReturn = ((String) theValue).substring(0, aLength - 1) + aLastChar; break; case SHORT: { @@ -1477,4 +1496,4 @@ */ private final short itsAttributeID; } -} +} \ No newline at end of file Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/ValueIndexer.java URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/ValueIndexer.java?view=diff&rev=501690&r1=501689&r2=501690 ============================================================================== --- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/ValueIndexer.java (original) +++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/ValueIndexer.java Tue Jan 30 18:06:42 2007 @@ -43,7 +43,7 @@ * It is used for maintaining element and [EMAIL PROTECTED] value * indexes. * - * @version CVS $Revision$, $Date$ + * @version $Revision$, $Date$ */ public final class ValueIndexer extends BTree implements Indexer { Added: xml/xindice/trunk/java/tests/src/org/apache/xindice/core/indexer/MemValueIndexerTest.java URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/tests/src/org/apache/xindice/core/indexer/MemValueIndexerTest.java?view=auto&rev=501690 ============================================================================== --- xml/xindice/trunk/java/tests/src/org/apache/xindice/core/indexer/MemValueIndexerTest.java (added) +++ xml/xindice/trunk/java/tests/src/org/apache/xindice/core/indexer/MemValueIndexerTest.java Tue Jan 30 18:06:42 2007 @@ -0,0 +1,14 @@ +package org.apache.xindice.core.indexer; + +/** + * Tests MemValueIndexer + * + * @version $Revision$, $Date$ + */ +public class MemValueIndexerTest extends ValueIndexerTest { + + public MemValueIndexerTest(String name) { + super(name); + indexClass = "org.apache.xindice.core.indexer.MemValueIndexer"; + } +} Propchange: xml/xindice/trunk/java/tests/src/org/apache/xindice/core/indexer/MemValueIndexerTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: xml/xindice/trunk/java/tests/src/org/apache/xindice/core/indexer/MemValueIndexerTest.java ------------------------------------------------------------------------------ svn:keywords = Id Revision Author Date Modified: xml/xindice/trunk/java/tests/src/org/apache/xindice/core/indexer/ValueIndexerTest.java URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/tests/src/org/apache/xindice/core/indexer/ValueIndexerTest.java?view=diff&rev=501690&r1=501689&r2=501690 ============================================================================== --- xml/xindice/trunk/java/tests/src/org/apache/xindice/core/indexer/ValueIndexerTest.java (original) +++ xml/xindice/trunk/java/tests/src/org/apache/xindice/core/indexer/ValueIndexerTest.java Tue Jan 30 18:06:42 2007 @@ -36,10 +36,12 @@ private Database db; private Collection collection; + protected String indexClass; public ValueIndexerTest(String name) { super(name); + indexClass = "org.apache.xindice.core.indexer.ValueIndexer"; } public void setUp() throws Exception { @@ -48,8 +50,8 @@ db.setConfig(new Configuration(DOMParser.toDocument(DatabaseTest.DATABASE))); collection = db.createCollection(name, new Configuration( DOMParser.toDocument( - "<collection compressed=\"true\" name=\"" + name + "\" inline-metadata=\"true\">" + - "<filer class=\"org.apache.xindice.core.filer.BTreeFiler\" />" + + "<collection compressed='true' name='" + name + "' inline-metadata='true'>" + + "<filer class='org.apache.xindice.core.filer.BTreeFiler'/>" + "</collection>"), false )); } @@ -61,7 +63,7 @@ private Indexer createIndex(String name, String pattern, String type) throws Exception { String config = "<index name='" + name + "' " + - "class='org.apache.xindice.core.indexer.ValueIndexer' " + + "class='" + indexClass + "' " + "pattern='" + pattern + "' type='" + type + "'/>"; Indexer ind = collection.createIndexer(new Configuration(DOMParser.toDocument(config))); Thread.sleep(100); @@ -72,7 +74,27 @@ IndexPattern indPattern = new IndexPattern(collection.getSymbols(), pattern, null); IndexQuery query = new IndexQuery(indPattern, op, value); return ind.queryMatches(query); + } + + + public void testStringIndex() throws Exception { + Indexer ind = createIndex("StrIndex", "[EMAIL PROTECTED]", "string"); + + Document document = DOMParser.toDocument("<test value='abc'/>"); + collection.insertDocument("key1", document); + + document = DOMParser.toDocument("<test value='abe'/>"); + collection.insertDocument("key2", document); + document = DOMParser.toDocument("<test value='bcd'/>"); + collection.insertDocument("key3", document); + + document = DOMParser.toDocument("<test value='aac'/>"); + collection.insertDocument("key", document); + + IndexMatch[] match = query(ind, "[EMAIL PROTECTED]", "ab", IndexQuery.SW); + + assertEquals(2, match.length); } public void testLongIntIndex() throws Exception { @@ -119,7 +141,7 @@ document = DOMParser.toDocument("<test value='" + Double.POSITIVE_INFINITY + "'/>"); collection.insertDocument("key8", document); - IndexMatch[] match = query(ind, "[EMAIL PROTECTED]", "71.48940001", IndexQuery.LT); + IndexMatch[] match = query(ind, "[EMAIL PROTECTED]", "71.48941", IndexQuery.LT); assertEquals(6, match.length); match = query(ind, "[EMAIL PROTECTED]", "-211.499539", IndexQuery.LT); @@ -167,5 +189,4 @@ assertEquals(1, match.length); } - } Modified: xml/xindice/trunk/java/tests/src/org/apache/xindice/integration/client/services/IndexedSearchTest.java URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/tests/src/org/apache/xindice/integration/client/services/IndexedSearchTest.java?view=diff&rev=501690&r1=501689&r2=501690 ============================================================================== --- xml/xindice/trunk/java/tests/src/org/apache/xindice/integration/client/services/IndexedSearchTest.java (original) +++ xml/xindice/trunk/java/tests/src/org/apache/xindice/integration/client/services/IndexedSearchTest.java Tue Jan 30 18:06:42 2007 @@ -49,17 +49,20 @@ */ public class IndexedSearchTest extends AbstractXmlDbClientTest { + private static final Log itsLog = LogFactory.getLog(IndexedSearchTest.class); + /** * path of collection we use (and reuse to avoid document insertion overhead for each test case) */ - public static String PARENT_COLLECTION_PATH = XmlDbClientSetup.INSTANCE_NAME + "/" + XmlDbClientSetup.TEST_COLLECTION_NAME; - public static String SUBCOLLECTION_NAME = "indexedsearch"; - public static String INDEXED_SEARCH_TEST_COLLECTION_PATH = PARENT_COLLECTION_PATH + "/" + SUBCOLLECTION_NAME; + private static final String PARENT_COLLECTION_PATH = XmlDbClientSetup.INSTANCE_NAME + "/" + XmlDbClientSetup.TEST_COLLECTION_NAME; + private static final String COLLECTION_NAME = "indexedsearch"; + private static final String COLLECTION_PATH = PARENT_COLLECTION_PATH + "/" + COLLECTION_NAME; + + private static final String TEST_DOCUMENT_PREFIX = "indexedsearchtestdoc"; + private static final DocumentBuilderFactory itsDocumentBuilderFactory = DocumentBuilderFactory.newInstance(); + private static boolean docsCreated = false; private static boolean aCollectionCreated = false; - public final static String TEST_DOCUMENT_PREFIX = "indexedsearchtestdoc"; - private final static DocumentBuilderFactory itsDocumentBuilderFactory = DocumentBuilderFactory.newInstance(); - private static final Log itsLog = LogFactory.getLog(IndexedSearchTest.class); /** * Performs setup for each test case. @@ -69,13 +72,13 @@ if (!aCollectionCreated) { try { - this.client.dropCollection(PARENT_COLLECTION_PATH, SUBCOLLECTION_NAME); + this.client.dropCollection(PARENT_COLLECTION_PATH, COLLECTION_NAME); } catch (Exception anException) { - /** + /* * ignore problems during drop collection above... - **/ + */ } finally { - this.client.createCollection(PARENT_COLLECTION_PATH, SUBCOLLECTION_NAME); + this.client.createCollection(PARENT_COLLECTION_PATH, COLLECTION_NAME); aCollectionCreated = true; } } @@ -99,7 +102,7 @@ " <last>Jones" + aNumber + "</last>" + " <phone type='home'>555-345-6789</phone>" + "</person>"; - this.client.insertDocument(INDEXED_SEARCH_TEST_COLLECTION_PATH, "doc" + String.valueOf(anIndex), aDocument); + this.client.insertDocument(COLLECTION_PATH, "doc" + String.valueOf(anIndex), aDocument); } } @@ -240,7 +243,7 @@ * @return a Result containing the query result (ResourceSet) and elapsed time */ public Result runQuery() throws Exception { - Collection col = IndexedSearchTest.this.client.getCollection(IndexedSearchTest.INDEXED_SEARCH_TEST_COLLECTION_PATH); + Collection col = IndexedSearchTest.this.client.getCollection(IndexedSearchTest.COLLECTION_PATH); XPathQueryService xpathservice = (XPathQueryService) col.getService("XPathQueryService", "1.0"); org.apache.xindice.Stopwatch aStopwatch = new org.apache.xindice.Stopwatch("Non-indexed starts-with query", true); @@ -271,7 +274,7 @@ int anExpectedSourceDocumentIndex = ((Integer) itsExpectedResources[anIndex]).intValue(); String anExpected = "<?xml version=\"1.0\"?>\n" + addSource((String) itsExpectedResources[anIndex + 1], TEST_DOCUMENT_PREFIX + anIndex, - IndexedSearchTest.INDEXED_SEARCH_TEST_COLLECTION_PATH); + IndexedSearchTest.COLLECTION_PATH); String anActual = TextWriter.toString(aNode); //itsLog.info(itsDescription); //itsLog.info("Expected resource " + (anIndex / 2) + ":"); @@ -302,7 +305,7 @@ final String pfx = "src"; elm.setAttribute(NodeImpl.XMLNS_PREFIX + ":" + pfx, NodeSource.SOURCE_NS); elm.setAttribute(pfx + ":" + NodeSource.SOURCE_COL, - "/" + INDEXED_SEARCH_TEST_COLLECTION_PATH); + "/" + COLLECTION_PATH); elm.setAttribute(pfx + ":" + NodeSource.SOURCE_KEY, theKey); return TextWriter.toString(elm); } @@ -312,7 +315,7 @@ */ public void createIndex() throws Exception { if (!itsIndexCreated) { - IndexedSearchTest.this.client.createIndexer(INDEXED_SEARCH_TEST_COLLECTION_PATH, + IndexedSearchTest.this.client.createIndexer(COLLECTION_PATH, "<?xml version='1.0'?><index name='" + itsTestIndexName + "' " + "class='org.apache.xindice.core.indexer." + itsTestIndexType + "Indexer' " + "pattern='" + itsTestIndexPattern + "' />"); @@ -328,7 +331,7 @@ */ public void dropIndex() throws Exception { if (itsIndexCreated) { - IndexedSearchTest.this.client.dropIndexer(INDEXED_SEARCH_TEST_COLLECTION_PATH, itsTestIndexName); + IndexedSearchTest.this.client.dropIndexer(COLLECTION_PATH, itsTestIndexName); itsIndexCreated = false; } } @@ -341,7 +344,7 @@ for (int anIndex = 0; anIndex < itsTestDocuments.length; ++anIndex) { String aDocumentName = TEST_DOCUMENT_PREFIX + anIndex; IndexedSearchTest.this.client.insertDocument( - INDEXED_SEARCH_TEST_COLLECTION_PATH, + COLLECTION_PATH, aDocumentName, itsTestDocuments[anIndex]); } itsTestDocumentsAdded = true; @@ -356,7 +359,7 @@ for (int anIndex = 0; anIndex < itsTestDocuments.length; ++anIndex) { String aDocumentName = TEST_DOCUMENT_PREFIX + anIndex; IndexedSearchTest.this.client.removeDocument( - INDEXED_SEARCH_TEST_COLLECTION_PATH, + COLLECTION_PATH, aDocumentName); } itsTestDocumentsAdded = false; Modified: xml/xindice/trunk/status.xml URL: http://svn.apache.org/viewvc/xml/xindice/trunk/status.xml?view=diff&rev=501690&r1=501689&r2=501690 ============================================================================== --- xml/xindice/trunk/status.xml (original) +++ xml/xindice/trunk/status.xml Tue Jan 30 18:06:42 2007 @@ -75,6 +75,9 @@ <changes> <release version="1.1b5-dev" date="Jan 30 2007"> + <action dev="VG" type="fix" fixes-bug="38886" due-to="Terry Rosenbaum"> + Fix MemValueIndexer for starts-with queries. + </action> <action dev="VG" type="fix" fixes-bug="19203" due-to="Natalia Shilenkova"> Fix indexing of multi-byte numeric types (long, double, etc). Due to the change in the BTree, existing databases has to be re-built using