You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by rh...@apache.org on 2014/06/27 19:44:21 UTC

svn commit: r1606161 - in /db/derby/code/trunk: java/optional/org/apache/derby/optional/api/ java/optional/org/apache/derby/optional/lucene/ java/testing/org/apache/derbyTesting/functionTests/tests/lang/ tools/javadoc/

Author: rhillegas
Date: Fri Jun 27 17:44:20 2014
New Revision: 1606161

URL: http://svn.apache.org/r1606161
Log:
DERBY-590: Add multi-field support to the Lucene plugin; commit derby-590-31-aa-multiField.diff.

Added:
    db/derby/code/trunk/java/optional/org/apache/derby/optional/api/LuceneIndexDescriptor.java   (with props)
Modified:
    db/derby/code/trunk/java/optional/org/apache/derby/optional/api/LuceneUtils.java
    db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneListIndexesVTI.java
    db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneQueryVTI.java
    db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneSupport.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneBackupTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCoarseAuthorizationTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCollationTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneInMemoryTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneJarLoadingTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportPermsTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/myLuceneClasses.jar
    db/derby/code/trunk/tools/javadoc/publishedapi.ant

Added: db/derby/code/trunk/java/optional/org/apache/derby/optional/api/LuceneIndexDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/optional/org/apache/derby/optional/api/LuceneIndexDescriptor.java?rev=1606161&view=auto
==============================================================================
--- db/derby/code/trunk/java/optional/org/apache/derby/optional/api/LuceneIndexDescriptor.java (added)
+++ db/derby/code/trunk/java/optional/org/apache/derby/optional/api/LuceneIndexDescriptor.java Fri Jun 27 17:44:20 2014
@@ -0,0 +1,47 @@
+/*
+
+   Derby - Class org.apache.derby.optional.api.LuceneIndexDescriptor
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF 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.
+
+ */
+
+package org.apache.derby.optional.api;
+
+import java.sql.SQLException;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.queryparser.classic.QueryParser;
+
+/**
+ * <p>
+ * A descriptor for how a Lucene index is created and queried.
+ * </p>
+ */
+public interface LuceneIndexDescriptor
+{
+    /**
+     * Get the names of the fields which are created when text is indexed.
+     * These fields can be mentioned later on when querying the index.
+     */
+    public  String[]    getFieldNames();
+    
+    /** Get the Analyzer used to create index terms */
+    public Analyzer getAnalyzer()   throws SQLException;
+
+    /** Get the QueryParser used to parse query text */
+    public  QueryParser getQueryParser()    throws SQLException;
+}

Propchange: db/derby/code/trunk/java/optional/org/apache/derby/optional/api/LuceneIndexDescriptor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/optional/org/apache/derby/optional/api/LuceneUtils.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/optional/org/apache/derby/optional/api/LuceneUtils.java?rev=1606161&r1=1606160&r2=1606161&view=diff
==============================================================================
--- db/derby/code/trunk/java/optional/org/apache/derby/optional/api/LuceneUtils.java (original)
+++ db/derby/code/trunk/java/optional/org/apache/derby/optional/api/LuceneUtils.java Fri Jun 27 17:44:20 2014
@@ -29,9 +29,12 @@ import java.util.Locale;
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
 import org.apache.lucene.queryparser.classic.QueryParser;
 import org.apache.lucene.util.Version;
 
+import org.apache.derby.iapi.error.PublicAPI;
+import org.apache.derby.iapi.error.StandardException;
 import org.apache.derby.iapi.sql.conn.ConnectionUtil;
 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
 
@@ -48,6 +51,8 @@ public abstract class LuceneUtils
     //
     /////////////////////////////////////////////////////////////////
 
+    public  static  final   String  TEXT_FIELD_NAME = "luceneTextField";
+
     /////////////////////////////////////////////////////////////////
     //
     //  STATE
@@ -126,7 +131,7 @@ public abstract class LuceneUtils
      * </p>
      */
     public  static  Analyzer    defaultAnalyzer()
-        throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, SQLException
+        throws SQLException
     {
         return getAnalyzerForLocale( ConnectionUtil.getCurrentLCC().getDatabase().getLocale() );
     }
@@ -137,19 +142,25 @@ public abstract class LuceneUtils
      * </p>
      */
     public  static  Analyzer    getAnalyzerForLocale( Locale locale )
-        throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
+        throws SQLException
     {
         String          language = locale.getLanguage();
 
-        Class<? extends Analyzer>   analyzerClass = _analyzerClasses.get( language );
+        try {
+            Class<? extends Analyzer>   analyzerClass = _analyzerClasses.get( language );
         
-        if ( analyzerClass == null )    { return standardAnalyzer(); }
-        else
-        {
-            Constructor<? extends Analyzer> constructor = analyzerClass.getConstructor( Version.class );
+            if ( analyzerClass == null )    { return standardAnalyzer(); }
+            else
+            {
+                Constructor<? extends Analyzer> constructor = analyzerClass.getConstructor( Version.class );
 
-            return constructor.newInstance( currentVersion() );
+                return constructor.newInstance( currentVersion() );
+            }
         }
+        catch (IllegalAccessException iae) { throw wrap( iae ); }
+        catch (InstantiationException ie)   { throw wrap( ie ); }
+        catch (InvocationTargetException ite)   { throw wrap( ite ); }
+        catch (NoSuchMethodException nsme)  { throw wrap( nsme ); }
     }
 
     /**
@@ -170,11 +181,22 @@ public abstract class LuceneUtils
     public  static  QueryParser defaultQueryParser
         (
          Version version,
-         String fieldName,
+         String[] fieldNames,
          Analyzer analyzer
          )
     {
-        return new QueryParser( version, fieldName, analyzer );
+        return new MultiFieldQueryParser( version, fieldNames, analyzer );
+    }
+    
+    /**
+     * <p>
+     * Get the default index descriptor. This has a single field named TEXT,
+     * a defaultAnalyzer() and a defaultQueryParser().
+     * </p>
+     */
+    public  static  LuceneIndexDescriptor   defaultIndexDescriptor()
+    {
+        return new DefaultIndexDescriptor();
     }
     
     /////////////////////////////////////////////////////////////////
@@ -204,4 +226,49 @@ public abstract class LuceneUtils
         return languageCode;
     }
 
+    /** Wrap an external exception */
+    private  static  SQLException    wrap( Throwable t )
+    {
+        return sqlException( StandardException.plainWrapException( t ) );
+    }
+    
+    /** Turn a StandardException into a SQLException */
+    private  static  SQLException    sqlException( StandardException se )
+    {
+        return PublicAPI.wrapStandardException( se );
+    }
+
+    /////////////////////////////////////////////////////////////////
+    //
+    //  NESTED CLASSES
+    //
+    /////////////////////////////////////////////////////////////////
+
+    /** The default LuceneIndexDescriptor */
+    public  static  class   DefaultIndexDescriptor  implements LuceneIndexDescriptor
+    {
+        public  DefaultIndexDescriptor()    {}
+
+        /** Return the default array of field names { TEXT_FIELD_NAME }. */
+        public  String[]    getFieldNames() { return new String[] { TEXT_FIELD_NAME }; }
+
+        /** Return LuceneUtils.defaultAnalyzer() */
+        public Analyzer getAnalyzer()   throws SQLException
+        { return LuceneUtils.defaultAnalyzer(); }
+
+        /**
+         * Return LuceneUtils.defaultQueryParser(  LuceneUtils.currentVersion(), getFieldNames(), getAnalyzer() ).
+         */
+        public  QueryParser getQueryParser()
+            throws SQLException
+        {
+            return LuceneUtils.defaultQueryParser
+                (
+                 LuceneUtils.currentVersion(),
+                 getFieldNames(),
+                 getAnalyzer()
+                 );
+        }
+    }
+    
 }

Modified: db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneListIndexesVTI.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneListIndexesVTI.java?rev=1606161&r1=1606160&r2=1606161&view=diff
==============================================================================
--- db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneListIndexesVTI.java (original)
+++ db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneListIndexesVTI.java Fri Jun 27 17:44:20 2014
@@ -70,7 +70,7 @@ class LuceneListIndexesVTI extends Strin
                     "LASTUPDATED",
                     "LUCENEVERSION",
                     "ANALYZER",
-                    "ANALYZERMAKER",
+                    "INDEXDESCRIPTORMAKER",
                 }
               );
 		
@@ -144,7 +144,7 @@ class LuceneListIndexesVTI extends Strin
         case 3: return column;
         case 5: return getProperty( LuceneSupport.LUCENE_VERSION );
         case 6: return getProperty( LuceneSupport.ANALYZER );
-        case 7: return getProperty( LuceneSupport.ANALYZER_MAKER );
+        case 7: return getProperty( LuceneSupport.INDEX_DESCRIPTOR_MAKER );
         default:
             throw LuceneSupport.newSQLException
                 (

Modified: db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneQueryVTI.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneQueryVTI.java?rev=1606161&r1=1606160&r2=1606161&view=diff
==============================================================================
--- db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneQueryVTI.java (original)
+++ db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneQueryVTI.java Fri Jun 27 17:44:20 2014
@@ -37,6 +37,7 @@ import java.util.Properties;
 import org.apache.derby.iapi.services.loader.ClassInspector;
 import org.apache.derby.io.StorageFile;
 import org.apache.derby.shared.common.reference.SQLState;
+import org.apache.derby.optional.api.LuceneIndexDescriptor;
 import org.apache.derby.optional.api.LuceneUtils;
 import org.apache.derby.vti.StringColumnVTI;
 import org.apache.derby.vti.VTIContext;
@@ -73,8 +74,6 @@ class LuceneQueryVTI extends StringColum
     //
     /////////////////////////////////////////////////////////////////////
 
-    public  static  final   String  TEXT_FIELD_NAME = "luceneTextField";
-
     /////////////////////////////////////////////////////////////////////
     //
     //  STATE
@@ -84,7 +83,6 @@ class LuceneQueryVTI extends StringColum
     // constructor args
     private Connection  _connection;
     private String  _queryText;
-    private String  _queryParserMaker;
     private int         _windowSize;
     private Float   _scoreCeiling;
 
@@ -118,7 +116,6 @@ class LuceneQueryVTI extends StringColum
 	LuceneQueryVTI
         (
          String queryText,
-         String queryParserMaker,
          int    windowSize,
          Float scoreCeiling
          )
@@ -130,7 +127,6 @@ class LuceneQueryVTI extends StringColum
         
         _connection = LuceneSupport.getDefaultConnection();
         _queryText = queryText;
-        _queryParserMaker = queryParserMaker;
         _windowSize = windowSize;
         _scoreCeiling = scoreCeiling;
 	}
@@ -464,24 +460,16 @@ class LuceneQueryVTI extends StringColum
             DerbyLuceneDir  derbyLuceneDir = LuceneSupport.getDerbyLuceneDir( _connection, _schema, _table, _column );
             StorageFile propertiesFile = LuceneSupport.getIndexPropertiesFile( derbyLuceneDir );
             Properties  indexProperties = readIndexProperties( propertiesFile );
-            String          analyzerMaker = indexProperties.getProperty( LuceneSupport.ANALYZER_MAKER );
-            Analyzer    analyzer = getAnalyzer( analyzerMaker );
+            String          indexDescriptorMaker = indexProperties.getProperty( LuceneSupport.INDEX_DESCRIPTOR_MAKER );
+            LuceneIndexDescriptor   indexDescriptor = getIndexDescriptor( indexDescriptorMaker );
+            Analyzer    analyzer = indexDescriptor.getAnalyzer( );
+            QueryParser qp = indexDescriptor.getQueryParser();
 
             vetLuceneVersion( indexProperties.getProperty( LuceneSupport.LUCENE_VERSION ) );
 
             _indexReader = getIndexReader( derbyLuceneDir );
             _searcher = new IndexSearcher( _indexReader );
 
-            QueryParser qp = getQueryParser
-                (
-                 _queryParserMaker == null ?
-                 LuceneUtils.class.getName() + ".defaultQueryParser" : _queryParserMaker,
-                 
-                 LuceneUtils.currentVersion(),
-                 TEXT_FIELD_NAME,
-                 analyzer
-                 );
-				
             Query luceneQuery = qp.parse( _queryText );
             TopScoreDocCollector tsdc = TopScoreDocCollector.create( _windowSize, true);
             if ( _scoreCeiling != null ) {
@@ -550,45 +538,6 @@ class LuceneQueryVTI extends StringColum
     }
     
 	/**
-	 * Invoke a static method (possibly supplied by the user) to instantiate a QueryParser.
-     *
-     * @param queryParserMaker  Full name of public, static method whicn instantiates a QueryParser given the following arguments.
-     * @param version   Lucene version.
-     * @param fieldName Name of field holding the indexed text.
-     * @param analyzer  Analyzer used to index the text.
-	 */
-	private static QueryParser getQueryParser
-        (
-         final String queryParserMaker,
-         final Version version,
-         final String fieldName,
-         final Analyzer analyzer
-         )
-        throws PrivilegedActionException, SQLException
-    {
-        return AccessController.doPrivileged
-            (
-             new PrivilegedExceptionAction<QueryParser>()
-             {
-                 public QueryParser run()
-                     throws ClassNotFoundException, IllegalAccessException,
-                     InvocationTargetException, NoSuchMethodException,
-                     SQLException
-                 {
-                     int    lastDotIdx = queryParserMaker.lastIndexOf( "." );
-                     String className = queryParserMaker.substring( 0, lastDotIdx );
-                     ClassInspector  ci = LuceneSupport.getClassFactory().getClassInspector();
-                     Class<? extends Object>  klass = ci.getClass( className );
-                     String methodName = queryParserMaker.substring( lastDotIdx + 1, queryParserMaker.length() );
-                     Method method = klass.getDeclaredMethod( methodName, Version.class, String.class, Analyzer.class );
-                     
-                     return (QueryParser) method.invoke( null, version, fieldName, analyzer );
-                 }
-             }
-             );
-	}
-	
-	/**
 	 * Returns a Lucene IndexReader, which reads from the indicated Lucene index.
 	 * 
 	 * @param indexHome The directory holding the Lucene index.
@@ -633,22 +582,22 @@ class LuceneQueryVTI extends StringColum
     }
 
 	/**
-	 * Invoke a static method (possibly supplied by the user) to instantiate an Analyzer.
+	 * Invoke a static method (possibly supplied by the user) to instantiate an index descriptor.
      * The method has no arguments.
 	 */
-	private static Analyzer getAnalyzer( final String analyzerMaker )
+	private static LuceneIndexDescriptor getIndexDescriptor( final String indexDescriptorMaker )
         throws PrivilegedActionException, SQLException
     {
         return AccessController.doPrivileged
             (
-             new PrivilegedExceptionAction<Analyzer>()
+             new PrivilegedExceptionAction<LuceneIndexDescriptor>()
              {
-                 public Analyzer run()
+                 public LuceneIndexDescriptor run()
                      throws ClassNotFoundException, IllegalAccessException,
                      InvocationTargetException, NoSuchMethodException,
                      SQLException
                  {
-                     return LuceneSupport.getAnalyzerNoPrivs( analyzerMaker );
+                     return LuceneSupport.getIndexDescriptorNoPrivs( indexDescriptorMaker );
                  }
              }
              );

Modified: db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneSupport.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneSupport.java?rev=1606161&r1=1606160&r2=1606161&view=diff
==============================================================================
--- db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneSupport.java (original)
+++ db/derby/code/trunk/java/optional/org/apache/derby/optional/lucene/LuceneSupport.java Fri Jun 27 17:44:20 2014
@@ -61,6 +61,7 @@ import org.apache.derby.impl.jdbc.EmbedC
 import org.apache.derby.io.StorageFactory;
 import org.apache.derby.io.StorageFile;
 import org.apache.derby.shared.common.reference.SQLState;
+import org.apache.derby.optional.api.LuceneIndexDescriptor;
 import org.apache.derby.optional.api.LuceneUtils;
 import org.apache.derby.vti.VTITemplate;
 
@@ -106,7 +107,7 @@ public class LuceneSupport implements Op
     // properties which go in that file
 
     /** property identifying the static method which materializes an Analyzer for the index */
-    public  static  final   String  ANALYZER_MAKER = "derby.lucene.analyzer.maker";
+    public  static  final   String  INDEX_DESCRIPTOR_MAKER = "derby.lucene.index.descriptor.maker";
 
     /** class name of the Analyzer used for the index */
     public  static  final   String  ANALYZER = "derby.lucene.analyzer";
@@ -176,7 +177,7 @@ public class LuceneSupport implements Op
 		listFunction.append("lastupdated timestamp,");
 		listFunction.append("luceneversion varchar( 20 ),");
 		listFunction.append("analyzer varchar( 32672 ),");
-		listFunction.append("analyzermaker varchar( 32672 )");
+		listFunction.append("indexdescriptormaker varchar( 32672 )");
 		listFunction.append(")");
 		listFunction.append("language java ");
 		listFunction.append("parameter style DERBY_JDBC_RESULT_SET ");
@@ -190,7 +191,7 @@ public class LuceneSupport implements Op
 		createProcedure.append(" (schemaname varchar( 128 ),");
 		createProcedure.append("tablename varchar( 128 ),");
 		createProcedure.append("textcolumn varchar( 128 ),");
-		createProcedure.append("analyzerMaker varchar( 32672 ),");
+		createProcedure.append("indexdescriptormaker varchar( 32672 ),");
 		createProcedure.append("keyColumns varchar( 32672 )...)");
 		createProcedure.append("parameter style derby modifies sql data language java external name ");
 		createProcedure.append("'" + getClass().getName() + ".createIndex'");
@@ -212,7 +213,7 @@ public class LuceneSupport implements Op
 		updateProcedure.append(" (schemaname varchar( 128 ),");
 		updateProcedure.append("tablename varchar( 128 ),");
 		updateProcedure.append("textcolumn varchar( 128 ),");
-		updateProcedure.append("analyzerMaker varchar( 32672 ))");
+		updateProcedure.append("indexdescriptormaker varchar( 32672 ))");
 		updateProcedure.append("parameter style java reads sql data language java external name ");
 		updateProcedure.append("'" + getClass().getName() + ".updateIndex'");
 		
@@ -317,13 +318,12 @@ public class LuceneSupport implements Op
 	public static LuceneQueryVTI luceneQuery
         (
          String queryText,
-         String queryParserMaker,
          int    windowSize,
          Float scoreCeiling
          )
         throws ParseException, IOException, SQLException
     {
-		LuceneQueryVTI lqvti = new LuceneQueryVTI( queryText, queryParserMaker, windowSize, scoreCeiling );
+		LuceneQueryVTI lqvti = new LuceneQueryVTI( queryText, windowSize, scoreCeiling );
 		return lqvti;
 	}
 	
@@ -356,11 +356,11 @@ public class LuceneSupport implements Op
 	 * @param schema Schema where the indexed column resides
 	 * @param table table where the indexed column resides
 	 * @param textcol the indexed column
-	 * @param analyzerMaker name of static method which instantiates an Analyzer. may be null.
+	 * @param indexDescriptorMaker name of static method which instantiates the index configuration. may be null.
 	 * @throws SQLException
 	 * @throws IOException
 	 */
-	public static void updateIndex( String schema, String table, String textcol, String analyzerMaker )
+	public static void updateIndex( String schema, String table, String textcol, String indexDescriptorMaker )
         throws SQLException, IOException, PrivilegedActionException
     {
         forbidReadOnlyConnections();
@@ -377,7 +377,7 @@ public class LuceneSupport implements Op
             throw newSQLException( SQLState.LUCENE_INDEX_DOES_NOT_EXIST );
         }
 
-        createOrRecreateIndex( conn, schema, table, textcol, analyzerMaker, false );
+        createOrRecreateIndex( conn, schema, table, textcol, indexDescriptorMaker, false );
 	}
 	
     /////////////////////////////////////////////////////////////////////
@@ -392,7 +392,7 @@ public class LuceneSupport implements Op
 	 * @param schema The schema of the column to index
 	 * @param table The table or view containing the indexable column
 	 * @param textcol The column to create the Lucene index on
-	 * @param analyzerMaker name of static method which instantiates an Analyzer. may be null.
+	 * @param indexDescriptorMaker name of static method which instantiates the index configuration. may be null.
 	 * @param keyColumns names of key columns if we're indexing a column in a view
 	 * @throws SQLException
 	 * @throws IOException
@@ -402,7 +402,7 @@ public class LuceneSupport implements Op
          String schema,
          String table,
          String textcol,
-         String analyzerMaker,
+         String indexDescriptorMaker,
          String... keyColumns
          )
         throws SQLException, IOException, PrivilegedActionException
@@ -417,7 +417,7 @@ public class LuceneSupport implements Op
         // First make sure that the text column exists and is a String type
         vetTextColumn( dbmd, schema, table, textcol );
 
-        createOrRecreateIndex( conn, schema, table, textcol, analyzerMaker, true, keyColumns );
+        createOrRecreateIndex( conn, schema, table, textcol, indexDescriptorMaker, true, keyColumns );
 	}
 
 	/**
@@ -426,7 +426,7 @@ public class LuceneSupport implements Op
 	 * @param schema The schema of the column to index
 	 * @param table The table of the column to index
 	 * @param textcol The column to create the Lucene index on
-	 * @param analyzerMaker name of static method which instantiates an Analyzer. may be null.
+	 * @param indexDescriptorMaker name of static method which instantiates the index configuration. may be null.
 	 * @param create True if the index is to be created, false if it is to be recreated
 	 * @throws SQLException
 	 * @throws IOException
@@ -437,7 +437,7 @@ public class LuceneSupport implements Op
          String schema,
          String table,
          String textcol,
-         String analyzerMaker,
+         String indexDescriptorMaker,
          boolean create,
          String... keyColumns
          )
@@ -484,19 +484,21 @@ public class LuceneSupport implements Op
         // create the new directory
         DerbyLuceneDir  derbyLuceneDir = getDerbyLuceneDir( conn, schema, table, textcol );
 
-        // get the Analyzer. use the default if the user didn't specify an override
-        if ( analyzerMaker == null ) { analyzerMaker = LuceneUtils.class.getName() + ".defaultAnalyzer"; }
-        Analyzer    analyzer = getAnalyzer( analyzerMaker );
+        // get the Analyzer and the field names. use the default if the user didn't specify an override
+        if ( indexDescriptorMaker == null ) { indexDescriptorMaker = LuceneUtils.class.getName() + ".defaultIndexDescriptor"; }
+        LuceneIndexDescriptor   indexDescriptor = getIndexDescriptor( indexDescriptorMaker );
+        String[]  fieldNames = indexDescriptor.getFieldNames();
+        Analyzer    analyzer = indexDescriptor.getAnalyzer();
 
         Properties  indexProperties = new Properties();
         indexProperties.setProperty( LUCENE_VERSION, luceneVersion.toString() );
         indexProperties.setProperty( UPDATE_TIMESTAMP, Long.toString( System.currentTimeMillis() ) );
-        indexProperties.setProperty( ANALYZER_MAKER, analyzerMaker );
+        indexProperties.setProperty( INDEX_DESCRIPTOR_MAKER, indexDescriptorMaker );
         indexProperties.setProperty( ANALYZER, analyzer.getClass().getName() );
             
         StringBuilder   tableFunction = new StringBuilder();
         tableFunction.append( "create function " + makeTableFunctionName( schema, table, textcol ) + "\n" );
-        tableFunction.append( "( query varchar( 32672 ), queryParserMaker varchar( 32672 ), windowSize int, scoreCeiling real )\n" );
+        tableFunction.append( "( query varchar( 32672 ), windowSize int, scoreCeiling real )\n" );
         tableFunction.append( "returns table\n(" );
 
         writeIndexProperties( propertiesFile, indexProperties );
@@ -553,7 +555,10 @@ public class LuceneSupport implements Op
                 String  textcolValue = rs.getString( keyCount + 1 );
                 if ( textcolValue != null )
                 {
-                    doc.add(new TextField( LuceneQueryVTI.TEXT_FIELD_NAME, textcolValue, Store.NO));
+                    for ( String fieldName : fieldNames )
+                    {
+                        doc.add( new TextField( fieldName, textcolValue, Store.NO ) );
+                    }
                 }
                 addDocument( iw, doc );
             }
@@ -1711,43 +1716,43 @@ public class LuceneSupport implements Op
     }
 
 	/**
-	 * Invoke a static method (possibly supplied by the user) to instantiate an Analyzer.
+	 * Invoke a static method (possibly supplied by the user) to instantiate an index descriptor.
      * The method has no arguments.
 	 */
-	private static Analyzer getAnalyzer( final String analyzerMaker )
+	private static LuceneIndexDescriptor getIndexDescriptor( final String indexDescriptorMaker )
         throws PrivilegedActionException, SQLException
     {
         return AccessController.doPrivileged
             (
-             new PrivilegedExceptionAction<Analyzer>()
+             new PrivilegedExceptionAction<LuceneIndexDescriptor>()
              {
-                 public Analyzer run()
+                 public LuceneIndexDescriptor run()
                      throws ClassNotFoundException, IllegalAccessException,
                      InvocationTargetException, NoSuchMethodException,
                      SQLException
                  {
-                     return getAnalyzerNoPrivs( analyzerMaker );
+                     return getIndexDescriptorNoPrivs( indexDescriptorMaker );
                  }
              }
              );
 	}
 	
 	/**
-	 * Invoke a static method (possibly supplied by the user) to instantiate an Analyzer.
+	 * Invoke a static method (possibly supplied by the user) to instantiate an index descriptor.
      * The method has no arguments.
 	 */
-	static Analyzer getAnalyzerNoPrivs( String analyzerMaker )
+	static LuceneIndexDescriptor getIndexDescriptorNoPrivs( String indexDescriptorMaker )
         throws ClassNotFoundException, IllegalAccessException, InvocationTargetException,
                NoSuchMethodException, SQLException
     {
-        int    lastDotIdx = analyzerMaker.lastIndexOf( "." );
-        String  className = analyzerMaker.substring( 0, lastDotIdx );
+        int    lastDotIdx = indexDescriptorMaker.lastIndexOf( "." );
+        String  className = indexDescriptorMaker.substring( 0, lastDotIdx );
         ClassInspector  ci = getClassFactory().getClassInspector();
         Class<? extends Object>  klass = ci.getClass( className );
-        String methodName = analyzerMaker.substring( lastDotIdx + 1, analyzerMaker.length() );
+        String methodName = indexDescriptorMaker.substring( lastDotIdx + 1, indexDescriptorMaker.length() );
         Method method = klass.getDeclaredMethod( methodName );
                      
-        return (Analyzer) method.invoke( null );
+        return (LuceneIndexDescriptor) method.invoke( null );
 	}
 
 	/**

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneBackupTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneBackupTest.java?rev=1606161&r1=1606160&r2=1606161&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneBackupTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneBackupTest.java Fri Jun 27 17:44:20 2014
@@ -77,7 +77,7 @@ public class LuceneBackupTest extends Ge
 
     private static  final   String      READ_POEMS_INDEX =
         "select p.originalAuthor, i.score\n" +
-        "from ruth.poems p, table ( ruth.poems__poemText( 'star', null, 1000, null ) ) i\n" +
+        "from ruth.poems p, table ( ruth.poems__poemText( 'star', 1000, null ) ) i\n" +
         "where p.poemID = i.poemID and p.versionStamp = i.versionStamp\n" +
         "order by i.score desc\n";
     private static  final   String[][]  DEFAULT_POEMS_RESULT =

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCoarseAuthorizationTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCoarseAuthorizationTest.java?rev=1606161&r1=1606160&r2=1606161&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCoarseAuthorizationTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCoarseAuthorizationTest.java Fri Jun 27 17:44:20 2014
@@ -45,6 +45,7 @@ import org.apache.lucene.analysis.Analyz
 import junit.framework.Test;
 import junit.framework.TestSuite;
 import org.apache.derby.iapi.sql.conn.ConnectionUtil;
+import org.apache.derby.optional.api.LuceneIndexDescriptor;
 import org.apache.derby.optional.api.LuceneUtils;
 import org.apache.derbyTesting.junit.BaseJDBCTestCase;
 import org.apache.derbyTesting.junit.JDBC;
@@ -72,15 +73,17 @@ public class LuceneCoarseAuthorizationTe
     private static  final   String      READ_WRITE_USER = "READWRITEUSER";
     private static  final   String[]    LEGAL_USERS = { RUTH, READ_ONLY_USER, READ_WRITE_USER };
 
-    private static  final   String      ENGLISH_ANALYZER =
+    public  static  final   String      ENGLISH_ANALYZER =
         "org.apache.derbyTesting.functionTests.tests.lang.LuceneCoarseAuthorizationTest.getEnglishAnalyzer";
+    public  static  final   String      STANDARD_ANALYZER =
+        "org.apache.derbyTesting.functionTests.tests.lang.LuceneCoarseAuthorizationTest.getStandardAnalyzer";
 
     private static  final   String      LOAD_TOOL = "call syscs_util.syscs_register_tool( 'luceneSupport', true )";
     private static  final   String      UNLOAD_TOOL = "call syscs_util.syscs_register_tool( 'luceneSupport', false )";
     private static  final   String      INDEX_POEMS =
         "call LuceneSupport.createIndex( 'ruth', 'poems', 'poemText', '" + ENGLISH_ANALYZER + "' )";
     private static  final   String      UPDATE_POEMS_INDEX =
-        "call LuceneSupport.updateIndex( 'ruth', 'poems', 'poemText', 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer' )";
+        "call LuceneSupport.updateIndex( 'ruth', 'poems', 'poemText', '" + STANDARD_ANALYZER + "' )";
     private static  final   String      DROP_POEMS_INDEX = "call LuceneSupport.dropIndex( 'ruth', 'poems', 'poemText' )";
 
     private static  final   String      ILLEGAL_FOR_READONLY = "25502";
@@ -178,7 +181,7 @@ public class LuceneCoarseAuthorizationTe
 
         String  readPoemsIndex =
             "select p.originalAuthor, i.score\n" +
-            "from ruth.poems p, table ( ruth.poems__poemText( 'star', null, 1000, null ) ) i\n" +
+            "from ruth.poems p, table ( ruth.poems__poemText( 'star', 1000, null ) ) i\n" +
             "where p.poemID = i.poemID and p.versionStamp = i.versionStamp\n" +
             "order by i.score desc\n";
         String[][]  defaultPoemResults =
@@ -205,7 +208,7 @@ public class LuceneCoarseAuthorizationTe
              );
 
         String  listIndexes =
-            "select schemaName, tableName, columnName, analyzerMaker from table( LuceneSupport.listIndexes() ) l";
+            "select schemaName, tableName, columnName, indexDescriptorMaker from table( LuceneSupport.listIndexes() ) l";
         String[][]  defaultIndexList =
             new String[][]
             {
@@ -260,7 +263,7 @@ public class LuceneCoarseAuthorizationTe
         String[][]  standardIndexList =
             new String[][]
             {
-                { "RUTH", "POEMS", "POEMTEXT", "org.apache.derby.optional.api.LuceneUtils.standardAnalyzer" },
+                { "RUTH", "POEMS", "POEMTEXT", STANDARD_ANALYZER },
             };
 
         assertResults
@@ -304,11 +307,18 @@ public class LuceneCoarseAuthorizationTe
     //
     ///////////////////////////////////////////////////////////////////////////////////
 
-    /** Return the Analyzer for an English Locale */
-    public  static  Analyzer    getEnglishAnalyzer()
+    /** Return an index descriptor with an Analyzer for an English Locale */
+    public  static  LuceneIndexDescriptor    getEnglishAnalyzer()
         throws Exception
     {
-        return LuceneUtils.getAnalyzerForLocale( Locale.US );
+        return new EnglishIndexDescriptor();
+    }
+    
+    /** Return an index descriptor with a StandardAnalyzer */
+    public  static  LuceneIndexDescriptor    getStandardAnalyzer()
+        throws Exception
+    {
+        return new StandardIndexDescriptor();
     }
     
 
@@ -385,5 +395,31 @@ public class LuceneCoarseAuthorizationTe
         ps.close();
     }
 
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // NESTED CLASSES
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    public  static  class   EnglishIndexDescriptor extends LuceneUtils.DefaultIndexDescriptor
+    {
+        public  EnglishIndexDescriptor() { super(); }
+        
+        public  Analyzer    getAnalyzer()   throws SQLException
+        {
+            return LuceneUtils.getAnalyzerForLocale( Locale.US );
+        }
+    }
+
+    public  static  class   StandardIndexDescriptor extends LuceneUtils.DefaultIndexDescriptor
+    {
+        public  StandardIndexDescriptor() { super(); }
+        
+        public  Analyzer    getAnalyzer()   throws SQLException
+        {
+            return LuceneUtils.standardAnalyzer();
+        }
+    }
+
 
 }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCollationTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCollationTest.java?rev=1606161&r1=1606160&r2=1606161&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCollationTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCollationTest.java Fri Jun 27 17:44:20 2014
@@ -150,7 +150,7 @@ public class LuceneCollationTest extends
         assertResults
             (
              conn,
-             "select * from table ( ruth.poems__poemText( 'star', null, 1000, null ) ) luceneResults order by poemID",
+             "select * from table ( ruth.poems__poemText( 'star', 1000, null ) ) luceneResults order by poemID",
              new String[][]
              {
                  { "3", "3", "2", "0.22933942" },

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneInMemoryTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneInMemoryTest.java?rev=1606161&r1=1606160&r2=1606161&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneInMemoryTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneInMemoryTest.java Fri Jun 27 17:44:20 2014
@@ -47,13 +47,10 @@ public class LuceneInMemoryTest extends 
     //
     ///////////////////////////////////////////////////////////////////////////////////
 
-    private static  final   String      ENGLISH_ANALYZER =
-        "org.apache.derbyTesting.functionTests.tests.lang.LuceneCoarseAuthorizationTest.getEnglishAnalyzer";
-
     private static  final   String      LOAD_TOOL = "call syscs_util.syscs_register_tool( 'luceneSupport', true )";
     private static  final   String      UNLOAD_TOOL = "call syscs_util.syscs_register_tool( 'luceneSupport', false )";
     private static  final   String      INDEX_POEMS =
-        "call LuceneSupport.createIndex( 'app', 'poems', 'poemText', '" + ENGLISH_ANALYZER + "' )";
+        "call LuceneSupport.createIndex( 'app', 'poems', 'poemText', '" + LuceneCoarseAuthorizationTest.ENGLISH_ANALYZER + "' )";
     private static  final   String      DROP_POEMS_INDEX = "call LuceneSupport.dropIndex( 'app', 'poems', 'poemText' )";
 
     ///////////////////////////////////////////////////////////////////////////////////
@@ -136,7 +133,7 @@ public class LuceneInMemoryTest extends 
 
         String  readPoemsIndex =
             "select p.originalAuthor, i.score\n" +
-            "from poems p, table ( poems__poemText( 'star', null, 1000, null ) ) i\n" +
+            "from poems p, table ( poems__poemText( 'star', 1000, null ) ) i\n" +
             "where p.poemID = i.poemID and p.versionStamp = i.versionStamp\n" +
             "order by i.score desc\n";
         String[][]  defaultPoemResults =
@@ -156,11 +153,11 @@ public class LuceneInMemoryTest extends 
              );
 
         String  listIndexes =
-            "select schemaName, tableName, columnName, analyzerMaker from table( LuceneSupport.listIndexes() ) l";
+            "select schemaName, tableName, columnName, indexDescriptorMaker from table( LuceneSupport.listIndexes() ) l";
         String[][]  defaultIndexList =
             new String[][]
             {
-                { "APP", "POEMS", "POEMTEXT", ENGLISH_ANALYZER },
+                { "APP", "POEMS", "POEMTEXT", LuceneCoarseAuthorizationTest.ENGLISH_ANALYZER },
             };
 
         assertResults

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneJarLoadingTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneJarLoadingTest.java?rev=1606161&r1=1606160&r2=1606161&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneJarLoadingTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneJarLoadingTest.java Fri Jun 27 17:44:20 2014
@@ -72,7 +72,7 @@ public class LuceneJarLoadingTest extend
 
     private static  final   String      LOAD_TOOL = "call syscs_util.syscs_register_tool( 'luceneSupport', true )";
     private static  final   String      UNLOAD_TOOL = "call syscs_util.syscs_register_tool( 'luceneSupport', false )";
-    private static  final   String      MY_ANALYZER = "MyAnalyzer.makeMyAnalyzer";
+    private static  final   String      MY_ANALYZER = "MyAnalyzer.makeMyIndexDescriptor";
     private static  final   String      INDEX_TEXT_TABLE =
         "call LuceneSupport.createIndex( 'ruth', 'textTable', 'textCol', '" + MY_ANALYZER + "' )";
     private static  final   String      DROP_TEXT_INDEX = "call LuceneSupport.dropIndex( 'ruth', 'textTable', 'textCol' )";
@@ -83,7 +83,6 @@ public class LuceneJarLoadingTest extend
         "  ruth.textTable__textCol\n" +
         "  (\n" +
         "    'one two three four five six seven eight nine ten',\n" +
-        "    'MyQueryParser.makeMyQueryParser',\n" +
         "    100, null\n" +
         "  )\n" +
         ") t\n";

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportPermsTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportPermsTest.java?rev=1606161&r1=1606160&r2=1606161&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportPermsTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportPermsTest.java Fri Jun 27 17:44:20 2014
@@ -44,6 +44,7 @@ import java.util.Locale;
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.queryparser.classic.ParseException;
+import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
 import org.apache.lucene.queryparser.classic.QueryParser;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.util.Version;
@@ -51,6 +52,9 @@ import org.apache.lucene.util.Version;
 import junit.framework.Test;
 import junit.framework.TestSuite;
 
+import org.apache.derby.optional.api.LuceneIndexDescriptor;
+import org.apache.derby.optional.api.LuceneUtils;
+
 import org.apache.derby.iapi.sql.conn.ConnectionUtil;
 import org.apache.derbyTesting.junit.BaseJDBCTestCase;
 import org.apache.derbyTesting.junit.JDBC;
@@ -118,6 +122,9 @@ public class LuceneSupportPermsTest exte
     private static  final   String      LANGUAGE = "en";
     private static  final   String      COUNTRY = "US";
 
+    private static  final   String      DEFAULT_INDEX_DESCRIPTOR = "org.apache.derby.optional.api.LuceneUtils.defaultIndexDescriptor";
+    private static  final   String      CONSTANT_QUERY_PARSER = "org.apache.derbyTesting.functionTests.tests.lang.LuceneSupportPermsTest.constantStringIndexDescriptor";
+    
     ///////////////////////////////////////////////////////////////////////////////////
     //
     // STATE
@@ -210,7 +217,7 @@ public class LuceneSupportPermsTest exte
             ( ruthConnection, NONEXISTENT_INDEX, "call LuceneSupport.updateIndex( 'ruth', 'poems', 'originalAuthor', null )" );
 
         // alice can't view an index created by ruth
-        String  viewPoemsIndex = "select * from table ( ruth.poems__poemText( 'star', null, 1000, null ) ) luceneResults order by poemID";
+        String  viewPoemsIndex = "select * from table ( ruth.poems__poemText( 'star', 1000, null ) ) luceneResults order by poemID";
         expectExecutionError( aliceConnection, LACK_EXECUTE_PRIV, viewPoemsIndex );
 
         // but ruth can
@@ -319,7 +326,7 @@ public class LuceneSupportPermsTest exte
         }
 
         // but alice still needs select privilege on the base table columns
-        String  viewPoemsIndex = "select * from table ( ruth.poems__poemText( 'star', null, 1000, null ) ) luceneResults order by poemid";
+        String  viewPoemsIndex = "select * from table ( ruth.poems__poemText( 'star', 1000, null ) ) luceneResults order by poemid";
         String[][]  viewPoemsIndexResults = new String[][]
             {
                 { "3", "3", "2", "0.22933942" },
@@ -463,7 +470,7 @@ public class LuceneSupportPermsTest exte
             (
              ruthConnection,
              "select p.originalAuthor, i.score\n" +
-             "from ruth.poems p, table ( ruth.poems__poemText( 'star', null, 1000, null ) ) i\n" +
+             "from ruth.poems p, table ( ruth.poems__poemText( 'star', 1000, null ) ) i\n" +
              "where p.poemID = i.poemID and p.versionStamp = i.versionStamp\n" +
              "order by i.score desc\n",
              new String[][]
@@ -512,7 +519,7 @@ public class LuceneSupportPermsTest exte
         expectCompilationError
             (
              ruthConnection, NONEXISTENT_TABLE_FUNCTION,
-             "select * from table( ruth.textTable__textCol( 'one two three four five six seven eight nine ten', null, 100, null ) ) t"
+             "select * from table( ruth.textTable__textCol( 'one two three four five six seven eight nine ten', 100, null ) ) t"
              );
 
         goodStatement( dboConnection, UNLOAD_TOOL );
@@ -549,7 +556,7 @@ public class LuceneSupportPermsTest exte
 
         String  query =
             "select p.originalAuthor, i.score\n" +
-            "from ruth.poems p, table ( ruth.poems__poemText( 'star', null, 1000, null ) ) i\n" +
+            "from ruth.poems p, table ( ruth.poems__poemText( 'star', 1000, null ) ) i\n" +
             "where p.poemID = i.poemID and p.versionStamp = i.versionStamp\n" +
             "order by i.score desc\n";
 
@@ -569,7 +576,7 @@ public class LuceneSupportPermsTest exte
         // now switch the Analyzer and re-run the query
         goodStatement
             ( ruthConnection,
-              "call LuceneSupport.updateIndex( 'ruth', 'poems', 'poemText', 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer' )" );
+              "call LuceneSupport.updateIndex( 'ruth', 'poems', 'poemText', '" + LuceneCoarseAuthorizationTest.STANDARD_ANALYZER + "' )" );
 
         assertResults
             (
@@ -590,7 +597,7 @@ public class LuceneSupportPermsTest exte
         assertResults
             (
              ruthConnection,
-             "select schemaName, tableName, columnName, luceneVersion, analyzer, analyzerMaker\n" +
+             "select schemaName, tableName, columnName, luceneVersion, analyzer, indexDescriptorMaker\n" +
              "from table( LuceneSupport.listIndexes() ) l\n" +
              "order by schemaName, tableName, columnName\n",
              new String[][]
@@ -598,12 +605,12 @@ public class LuceneSupportPermsTest exte
                  {
                      "RUTH", "POEMS", "ORIGINALAUTHOR", LUCENE_VERSION,
                      "org.apache.lucene.analysis.en.EnglishAnalyzer",
-                     "org.apache.derby.optional.api.LuceneUtils.defaultAnalyzer",
+                     DEFAULT_INDEX_DESCRIPTOR
                  },
                  {
                      "RUTH", "POEMS", "POEMTEXT", LUCENE_VERSION,
                      "org.apache.lucene.analysis.standard.StandardAnalyzer",
-                     "org.apache.derby.optional.api.LuceneUtils.standardAnalyzer",
+                     LuceneCoarseAuthorizationTest.STANDARD_ANALYZER
                  },
              },
              false
@@ -657,7 +664,7 @@ public class LuceneSupportPermsTest exte
         // vet index contents
         String  selectFromViewIndex =
             "select p.originalAuthor, i.score\n" +
-            "from ruth.poems p, table ( ruth.poemView__poemText( 'star', null, 1000, null ) ) i\n" +
+            "from ruth.poems p, table ( ruth.poemView__poemText( 'star', 1000, null ) ) i\n" +
             "where p.poemID = i.poemID and p.versionStamp = i.versionStamp\n" +
             "order by i.score desc\n";
         assertResults
@@ -675,7 +682,7 @@ public class LuceneSupportPermsTest exte
 
         // vet index list
         String  selectIndexes =
-            "select schemaName, tableName, columnName, analyzerMaker\n" +
+            "select schemaName, tableName, columnName, indexDescriptorMaker\n" +
             "from table( LuceneSupport.listIndexes() ) l\n" +
             "order by schemaName, tableName, columnName\n";
         assertResults
@@ -686,11 +693,11 @@ public class LuceneSupportPermsTest exte
              {
                  {
                      "RUTH", "POEMS", "POEMTEXT",
-                     "org.apache.derby.optional.api.LuceneUtils.defaultAnalyzer",
+                     DEFAULT_INDEX_DESCRIPTOR
                  },
                  {
                      "RUTH", "POEMVIEW", "POEMTEXT",
-                     "org.apache.derby.optional.api.LuceneUtils.defaultAnalyzer",
+                     DEFAULT_INDEX_DESCRIPTOR
                  },
              },
              false
@@ -700,7 +707,7 @@ public class LuceneSupportPermsTest exte
         goodStatement
             (
              ruthConnection,
-             "call LuceneSupport.updateIndex( 'ruth', 'poemView', 'poemText', 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer' )"
+             "call LuceneSupport.updateIndex( 'ruth', 'poemView', 'poemText', '" + LuceneCoarseAuthorizationTest.STANDARD_ANALYZER + "' )"
              );
         assertResults
             (
@@ -721,11 +728,11 @@ public class LuceneSupportPermsTest exte
              {
                  {
                      "RUTH", "POEMS", "POEMTEXT",
-                     "org.apache.derby.optional.api.LuceneUtils.defaultAnalyzer",
+                     DEFAULT_INDEX_DESCRIPTOR
                  },
                  {
                      "RUTH", "POEMVIEW", "POEMTEXT",
-                     "org.apache.derby.optional.api.LuceneUtils.standardAnalyzer",
+                     LuceneCoarseAuthorizationTest.STANDARD_ANALYZER
                  },
              },
              false
@@ -745,7 +752,7 @@ public class LuceneSupportPermsTest exte
              {
                  {
                      "RUTH", "POEMS", "POEMTEXT",
-                     "org.apache.derby.optional.api.LuceneUtils.defaultAnalyzer",
+                     DEFAULT_INDEX_DESCRIPTOR
                  },
              },
              false
@@ -762,7 +769,7 @@ public class LuceneSupportPermsTest exte
             (
              ruthConnection,
              "select *\n" +
-             "from table ( ruth.poems__poemText( 'star', null, 1000, null ) ) i\n" +
+             "from table ( ruth.poems__poemText( 'star', 1000, null ) ) i\n" +
              "order by i.score desc\n",
              new String[][]
              {
@@ -846,7 +853,7 @@ public class LuceneSupportPermsTest exte
         assertResults
             (
              ruthConnection,
-             "select * from table( ruth.textTable__textCol( 'one two three four five six seven eight nine ten', null, 100, null ) ) t",
+             "select * from table( ruth.textTable__textCol( 'one two three four five six seven eight nine ten', 100, null ) ) t",
              new String[][]
              {
                  { "10", "9", "2.2791052" },
@@ -867,7 +874,7 @@ public class LuceneSupportPermsTest exte
         assertResults
             (
              ruthConnection,
-             "select * from table( ruth.textTable__textCol( 'one two three four five six seven eight nine ten', null, 3, null ) ) t",
+             "select * from table( ruth.textTable__textCol( 'one two three four five six seven eight nine ten', 3, null ) ) t",
              new String[][]
              {
                  { "10", "9", "2.2791052" },
@@ -881,7 +888,7 @@ public class LuceneSupportPermsTest exte
         assertResults
             (
              ruthConnection,
-             "select * from table( ruth.textTable__textCol( 'one two three four five six seven eight nine ten', null, 4, 1.0 ) ) t",
+             "select * from table( ruth.textTable__textCol( 'one two three four five six seven eight nine ten', 4, 1.0 ) ) t",
              new String[][]
              {
                  { "7", "6", "0.97469425" },
@@ -896,7 +903,7 @@ public class LuceneSupportPermsTest exte
         assertResults
             (
              ruthConnection,
-             "select * from table( ruth.textTable__textCol( 'one two three four five six seven eight nine ten', null, 100, 0.2 ) ) t",
+             "select * from table( ruth.textTable__textCol( 'one two three four five six seven eight nine ten', 100, 0.2 ) ) t",
              new String[][]
              {
                  { "3", "2", "0.17799875" },
@@ -907,10 +914,16 @@ public class LuceneSupportPermsTest exte
              );
         
         // try a different query parser
+        goodStatement( ruthConnection, "call LuceneSupport.dropIndex( 'ruth', 'textTable', 'textCol' )" );
+        goodStatement
+            (
+             ruthConnection,
+             "call LuceneSupport.createIndex( 'ruth', 'textTable', 'textCol', '" + CONSTANT_QUERY_PARSER + "' )"
+             );
         assertResults
             (
              ruthConnection,
-             "select * from table( ruth.textTable__textCol( 'one two three four five six seven eight nine ten', 'org.apache.derbyTesting.functionTests.tests.lang.LuceneSupportPermsTest.constantStringQueryParser', 100, null ) ) t",
+             "select * from table( ruth.textTable__textCol( 'one two three four five six seven eight nine ten', 100, null ) ) t",
              new String[][]
              {
                  { "1", "0", "1.597837" },
@@ -1069,7 +1082,7 @@ public class LuceneSupportPermsTest exte
             (
              conn,
              "call lucenesupport.createindex\n" +
-             "( 'TEST_DBO', 't_6602', 'textcol', 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer', ? )\n"
+             "( 'TEST_DBO', 't_6602', 'textcol', '" + LuceneCoarseAuthorizationTest.STANDARD_ANALYZER + "', ? )"
              );
         ps.setString( 1, cd.name );
         ps.execute();
@@ -1077,7 +1090,7 @@ public class LuceneSupportPermsTest exte
         assertResults
             (
              conn,
-             "select * from table( t_6602__textcol( 'abc or def', null, 3, null ) ) tc order by documentid",
+             "select * from table( t_6602__textcol( 'abc or def', 3, null ) ) tc order by documentid",
              new String[][]
              {
                  { null, "0", "0.35355338" },
@@ -1106,25 +1119,25 @@ public class LuceneSupportPermsTest exte
         // create index errors
         expectExecutionError
             ( dboConnection, ILLEGAL_NULL_ARG,
-              "call lucenesupport.createindex( null, 't_6596', 'c', 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer' )" );
+              "call lucenesupport.createindex( null, 't_6596', 'c',  '" + LuceneCoarseAuthorizationTest.STANDARD_ANALYZER + "' )" );
         expectExecutionError
             ( dboConnection, ILLEGAL_NULL_ARG,
-              "call lucenesupport.createindex( 'TEST_DBO', null, 'c', 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer' )" );
+              "call lucenesupport.createindex( 'TEST_DBO', null, 'c',  '" + LuceneCoarseAuthorizationTest.STANDARD_ANALYZER + "' )" );
         expectExecutionError
             ( dboConnection, ILLEGAL_NULL_ARG,
-              "call lucenesupport.createindex( 'TEST_DBO', 't_6596', null, 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer' )" );
+              "call lucenesupport.createindex( 'TEST_DBO', 't_6596', null,  '" + LuceneCoarseAuthorizationTest.STANDARD_ANALYZER + "' )" );
         expectExecutionError
             ( dboConnection, ILLEGAL_NULL_ARG,
-              "call lucenesupport.createindex( 'TEST_DBO', 't_6596', 'c', 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer', null )" );
+              "call lucenesupport.createindex( 'TEST_DBO', 't_6596', 'c',  '" + LuceneCoarseAuthorizationTest.STANDARD_ANALYZER + "', null )" );
         expectExecutionError
             ( dboConnection, ILLEGAL_NULL_ARG,
-              "call lucenesupport.createindex( 'TEST_DBO', 't_6596', 'c', 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer', 'x', null )" );
+              "call lucenesupport.createindex( 'TEST_DBO', 't_6596', 'c',  '" + LuceneCoarseAuthorizationTest.STANDARD_ANALYZER + "', 'x', null )" );
 
-        goodStatement( dboConnection, "call lucenesupport.createindex( 'TEST_DBO', 't_6596', 'c', 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer' )" );
+        goodStatement( dboConnection, "call lucenesupport.createindex( 'TEST_DBO', 't_6596', 'c',  '" + LuceneCoarseAuthorizationTest.STANDARD_ANALYZER + "' )" );
         assertResults
             (
              dboConnection,
-             "select * from table( t_6596__c( 'abc or def', null, 3, null ) ) tc order by documentid",
+             "select * from table( t_6596__c( 'abc or def', 3, null ) ) tc order by documentid",
              new String[][]
              {
                  { "1", "0", "0.35355338" },
@@ -1132,26 +1145,26 @@ public class LuceneSupportPermsTest exte
              },
              false
              );
-        goodStatement( dboConnection, "call lucenesupport.updateindex( 'TEST_DBO', 't_6596', 'c', 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer' )" );
+        goodStatement( dboConnection, "call lucenesupport.updateindex( 'TEST_DBO', 't_6596', 'c',  '" + LuceneCoarseAuthorizationTest.STANDARD_ANALYZER + "' )" );
         
         // update index errors
         expectExecutionError
             ( dboConnection, ILLEGAL_NULL_ARG,
-              "call lucenesupport.updateindex( null, 't_6596', 'c', 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer' )" );
+              "call lucenesupport.updateindex( null, 't_6596', 'c',  '" + LuceneCoarseAuthorizationTest.STANDARD_ANALYZER + "' )" );
         expectExecutionError
             ( dboConnection, ILLEGAL_NULL_ARG,
-              "call lucenesupport.updateindex( 'TEST_DBO', null, 'c', 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer' )" );
+              "call lucenesupport.updateindex( 'TEST_DBO', null, 'c',  '" + LuceneCoarseAuthorizationTest.STANDARD_ANALYZER + "' )" );
         expectExecutionError
             ( dboConnection, ILLEGAL_NULL_ARG,
-              "call lucenesupport.updateindex( 'TEST_DBO', 't_6596', null, 'org.apache.derby.optional.api.LuceneUtils.standardAnalyzer' )" );
+              "call lucenesupport.updateindex( 'TEST_DBO', 't_6596', null,  '" + LuceneCoarseAuthorizationTest.STANDARD_ANALYZER + "' )" );
 
         // query errors
         expectExecutionError
             ( dboConnection, ILLEGAL_NULL_ARG,
-              "select * from table( t_6596__c( null, null, 3, null ) ) tc order by documentid" );
+              "select * from table( t_6596__c( null, 3, null ) ) tc order by documentid" );
         expectExecutionError
             ( dboConnection, NULL_PRIMITIVE_ARG,
-              "select * from table( t_6596__c( 'abc or def', null, null, null ) ) tc order by documentid" );
+              "select * from table( t_6596__c( 'abc or def', null, null ) ) tc order by documentid" );
 
         // drop index errors
         expectExecutionError
@@ -1416,14 +1429,9 @@ public class LuceneSupportPermsTest exte
     }
 
     /** Alternative QueryParser maker, which forces the text to be a constant string */
-    public  static  QueryParser constantStringQueryParser
-        (
-         Version version,
-         String fieldName,
-         Analyzer analyzer
-         )
+    public  static  LuceneIndexDescriptor constantStringIndexDescriptor()
     {
-        return new ConstantQueryParser( version, fieldName, analyzer );
+        return new ConstantIndexDescriptor();
     }
     
     /**
@@ -1498,16 +1506,16 @@ public class LuceneSupportPermsTest exte
     //
     ///////////////////////////////////////////////////////////////////////////////////
 
-    public  static  class   ConstantQueryParser extends QueryParser
+    public  static  class   ConstantQueryParser extends MultiFieldQueryParser
     {
         public  ConstantQueryParser
             (
              Version version,
-             String fieldName,
+             String[] fieldNames,
              Analyzer analyzer
              )
         {
-            super( version, fieldName, analyzer );
+            super( version, fieldNames, analyzer );
         }
 
         public Query parse( String query )  throws ParseException
@@ -1530,4 +1538,20 @@ public class LuceneSupportPermsTest exte
         public  String  toString() { return "[ " + name + ", " + type + " ]"; }
     }
 
+    public  static  class   ConstantIndexDescriptor extends LuceneUtils.DefaultIndexDescriptor
+    {
+        public  ConstantIndexDescriptor() { super(); }
+        
+        public  QueryParser getQueryParser()
+            throws SQLException
+        {
+            return new ConstantQueryParser
+                (
+                 LuceneUtils.currentVersion(),
+                 getFieldNames(),
+                 getAnalyzer()
+                 );
+        }
+    }
+
 }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportTest.java?rev=1606161&r1=1606160&r2=1606161&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportTest.java Fri Jun 27 17:44:20 2014
@@ -20,14 +20,39 @@
  */
 package org.apache.derbyTesting.functionTests.tests.lang;
 
+import java.io.IOException;
+import java.io.Reader;
 import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Locale;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
 
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.analysis.Tokenizer;
+import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
+import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
+import org.apache.lucene.queryparser.classic.QueryParser;
+import org.apache.lucene.util.Version;
+
+import org.apache.derby.optional.api.LuceneIndexDescriptor;
+import org.apache.derby.optional.api.LuceneUtils;
+
 import org.apache.derby.shared.common.reference.SQLState;
 import org.apache.derbyTesting.junit.BaseJDBCTestCase;
 import org.apache.derbyTesting.junit.JDBC;
@@ -98,7 +123,7 @@ public class LuceneSupportTest extends B
             (
              s.executeQuery
              (
-              "select * from table ( lucenetest.titles__title( 'grapes', null, 1000, null ) ) luceneResults"
+              "select * from table ( lucenetest.titles__title( 'grapes', 1000, null ) ) luceneResults"
               ),
              expectedRows
              );
@@ -111,7 +136,7 @@ public class LuceneSupportTest extends B
             (
              s.executeQuery
              (
-              "select * from table ( lucenetest.titles__title( 'grapes', null, 1000, .75 ) ) luceneResults"
+              "select * from table ( lucenetest.titles__title( 'grapes', 1000, .75 ) ) luceneResults"
               ),
              expectedRows
              );
@@ -120,7 +145,7 @@ public class LuceneSupportTest extends B
             (
              s.executeQuery
              (
-              "select * from table ( lucenetest.titles__title( 'grapes',  null, 1000, 0.5) ) luceneResults"
+              "select * from table ( lucenetest.titles__title( 'grapes',  1000, 0.5) ) luceneResults"
               )
              );
 
@@ -134,7 +159,7 @@ public class LuceneSupportTest extends B
              s.executeQuery
              (
               "select title, author, publisher, documentID\n" +
-              "from lucenetest.titles t, table ( lucenetest.titles__title( 'grapes', null, 1000, null ) ) l\n" +
+              "from lucenetest.titles t, table ( lucenetest.titles__title( 'grapes', 1000, null ) ) l\n" +
               "where t.id = l.id\n" 
               ),
              expectedRows
@@ -159,7 +184,7 @@ public class LuceneSupportTest extends B
              s.executeQuery
              (
               "select *\n" +
-              "from table ( lucenetest.titles__title( 'mice', null, 1000, null ) ) luceneResults\n"
+              "from table ( lucenetest.titles__title( 'mice', 1000, null ) ) luceneResults\n"
               )
              );
 	    
@@ -171,7 +196,7 @@ public class LuceneSupportTest extends B
              s.executeQuery
              (
               "select *\n" +
-              "from table ( lucenetest.titles__title( 'mice', null, 1000, null ) ) luceneResults\n"
+              "from table ( lucenetest.titles__title( 'mice', 1000, null ) ) luceneResults\n"
               )
              );
 	    
@@ -188,7 +213,7 @@ public class LuceneSupportTest extends B
              s.executeQuery
              (
               "select *\n" +
-              "from table ( lucenetest.titles__title( 'mice', null, 1000, null ) ) luceneResults\n"
+              "from table ( lucenetest.titles__title( 'mice', 1000, null ) ) luceneResults\n"
               ),
              expectedRows
              );
@@ -265,6 +290,216 @@ public class LuceneSupportTest extends B
 		assertCallError( ILLEGAL_CHARACTER, "call LuceneSupport.dropIndex('','','../')");
 		
 	}
+
+    //////////////////////////////////////////////////////////////
+    //
+    //  BEGIN TEST FOR MULTIPLE FIELDS
+    //
+    //////////////////////////////////////////////////////////////
+	
+    public void testMultipleFields() throws SQLException
+    {
+        println( "Running multi-field test." );
+        
+        Statement s = createStatement();
+
+        s.execute("create table multifield(id int primary key, c clob)");
+        s.execute("insert into multifield values "
+                + "(1, '<document><secret/>No one must know!</document>'), "
+                + "(2, '<document>No secret here!</document>')");
+
+        s.execute("call lucenesupport.createindex('lucenetest', 'multifield', "
+                  + "'c', '" + getClass().getName() + ".makeMultiFieldIndexDescriptor')");
+
+        PreparedStatement ps = prepareStatement(
+                "select id from table(multifield__c(?, 100, null)) t");
+
+        String[][] bothRows = { {"1"}, {"2"} };
+
+        ps.setString(1, "text:secret");
+        JDBC.assertSingleValueResultSet(ps.executeQuery(), "2");
+        ps.setString(1, "tags:secret");
+        JDBC.assertSingleValueResultSet(ps.executeQuery(), "1");
+        ps.setString(1, "secret");
+        JDBC.assertUnorderedResultSet(ps.executeQuery(), bothRows);
+    }
+
+    /** Create the custom index descriptor for the multi-field test */
+    public  static  LuceneIndexDescriptor   makeMultiFieldIndexDescriptor()
+    {
+        return new MultiFieldIndexDescriptor();
+    }
+    /**
+     * Create a simple query parser for multiple fields, which uses
+     * StandardAnalyzer instead of the XMLAnalyzer that was used to create
+     * the index.
+     */
+    public static QueryParser createXMLQueryParser(
+            Version version, String[] fields, Analyzer analyzer) {
+        return new MultiFieldQueryParser(
+                version, fields, new StandardAnalyzer(version));
+    }
+
+    /**
+     * Custom analyzer for XML files. It indexes the tags and the text
+     * separately.
+     */
+    public static class XMLAnalyzer extends Analyzer {
+
+        public XMLAnalyzer() {
+            // We want different tokenizers for different fields. Set reuse
+            // policy to per-field to achieve that.
+            super(PER_FIELD_REUSE_STRATEGY);
+        }
+
+        @Override
+        protected TokenStreamComponents createComponents(
+                String fieldName, Reader reader) {
+
+            if (fieldName.equals("text")) {
+                return new TokenStreamComponents(new XMLTextTokenizer(reader));
+            }
+
+            if (fieldName.equals("tags")) {
+                return new TokenStreamComponents(new XMLTagsTokenizer(reader));
+            }
+
+            fail("unknown field name: " + fieldName);
+            return null;
+        }
+    }
+
+    /** Common logic for XMLTextTokenizer and XMLTagsTokenizer. */
+    private abstract static class AbstractTokenizer extends Tokenizer {
+        Iterator<String> tokens;
+        final CharTermAttribute charTermAttr =
+                addAttribute(CharTermAttribute.class);
+        final PositionIncrementAttribute posIncrAttr
+                = addAttribute(PositionIncrementAttribute.class);
+
+        AbstractTokenizer(Reader reader) {
+            super(reader);
+        }
+
+        @Override
+        public boolean incrementToken() throws IOException {
+            if (tokens == null) {
+                tokens = getTokens().iterator();
+            }
+
+            if (tokens.hasNext()) {
+                charTermAttr.setEmpty();
+                charTermAttr.append(tokens.next());
+                posIncrAttr.setPositionIncrement(1);
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public void reset() throws IOException {
+            tokens = null;
+            super.reset();
+        }
+
+        abstract Iterable<String> getTokens();
+    }
+
+    private static class XMLTextTokenizer extends AbstractTokenizer {
+
+        XMLTextTokenizer(Reader in) {
+            super(in);
+        }
+
+        @Override
+        Iterable<String> getTokens() {
+            StringBuilder text = new StringBuilder();
+            getAllText(parseXMLDocument(input), text);
+            return Arrays.asList(text.toString().split("[ \r\n\t]"));
+        }
+
+    }
+
+    private static class XMLTagsTokenizer extends AbstractTokenizer {
+
+        XMLTagsTokenizer(Reader in) {
+            super(in);
+        }
+
+        @Override
+        Iterable<String> getTokens() {
+            return getAllXMLTags(parseXMLDocument(input));
+        }
+
+    }
+
+    /** Parse an XML document from a Reader. */
+    private static Document parseXMLDocument(Reader reader) {
+        Document doc = null;
+
+        try {
+            doc = DocumentBuilderFactory.newInstance()
+                    .newDocumentBuilder().parse(new InputSource(reader));
+            reader.close();
+        } catch (Exception e) {
+            fail("Failed to parse XML document", e);
+        }
+
+        return doc;
+    }
+
+    /** Get a list of all the XML tags in a node. */
+    private static List<String> getAllXMLTags(Node node) {
+        ArrayList<String> list = new ArrayList<String>();
+        NodeList nl = node.getChildNodes();
+        for (int i = 0; i < nl.getLength(); i++) {
+            Node n = nl.item(i);
+            if (n.getNodeType() == Node.ELEMENT_NODE) {
+                list.add(n.getNodeName());
+                list.addAll(getAllXMLTags(n));
+            }
+        }
+        return list;
+    }
+
+    /** Strip out all tags from an XML node, so that only the text is left. */
+    private static void getAllText(Node node, StringBuilder sb) {
+        if (node.getNodeType() == Node.TEXT_NODE) {
+            sb.append(node.getNodeValue());
+        } else {
+            NodeList nl = node.getChildNodes();
+            for (int i = 0; i < nl.getLength(); i++) {
+                getAllText(nl.item(i), sb);
+            }
+        }
+    }
+
+    public static class MultiFieldIndexDescriptor implements LuceneIndexDescriptor
+    {
+        public  String[]    getFieldNames() { return new String[] { "tags", "text" }; }
+    
+        public Analyzer getAnalyzer()   { return new XMLAnalyzer(); }
+
+        public  QueryParser getQueryParser()
+        {
+            Version version = LuceneUtils.currentVersion();
+            
+            return new MultiFieldQueryParser
+                (
+                 version,
+                 getFieldNames(),
+                 new StandardAnalyzer( version )
+                 );
+        }
+
+    }
+
+    //////////////////////////////////////////////////////////////
+    //
+    //  END TEST FOR MULTIPLE FIELDS
+    //
+    //////////////////////////////////////////////////////////////
 	
 	protected void setUp() throws SQLException {
 		CallableStatement cSt;			    

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/myLuceneClasses.jar
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/myLuceneClasses.jar?rev=1606161&r1=1606160&r2=1606161&view=diff
==============================================================================
Binary files - no diff available.

Modified: db/derby/code/trunk/tools/javadoc/publishedapi.ant
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/tools/javadoc/publishedapi.ant?rev=1606161&r1=1606160&r2=1606161&view=diff
==============================================================================
--- db/derby/code/trunk/tools/javadoc/publishedapi.ant (original)
+++ db/derby/code/trunk/tools/javadoc/publishedapi.ant Fri Jun 27 17:44:20 2014
@@ -79,5 +79,6 @@ org/apache/derby/security/SystemPermissi
 
 # package: org.apache.derby.optional.api
 
+org/apache/derby/optional/api/LuceneIndexDescriptor.java
 org/apache/derby/optional/api/LuceneUtils.java