lucene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From yo...@apache.org
Subject svn commit: r1131228 - in /lucene/dev/trunk/solr: ./ src/java/org/apache/solr/schema/ src/java/org/apache/solr/search/ src/java/org/apache/solr/search/function/ src/test/org/apache/solr/search/ src/test/org/apache/solr/search/function/
Date Fri, 03 Jun 2011 20:48:48 GMT
Author: yonik
Date: Fri Jun  3 20:48:47 2011
New Revision: 1131228

URL: http://svn.apache.org/viewvc?rev=1131228&view=rev
Log:
SOLR-2136: function queries - add bool type and functions

Added:
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/MutableValueBool.java   (with props)
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/BoolDocValues.java   (with props)
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/BoolFunction.java   (with props)
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DefFunction.java   (with props)
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/IfFunction.java   (with props)
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/MultiBoolFunction.java   (with props)
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/MultiFunction.java   (with props)
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/SimpleBoolFunction.java   (with props)
Modified:
    lucene/dev/trunk/solr/CHANGES.txt
    lucene/dev/trunk/solr/src/java/org/apache/solr/schema/BoolField.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/FunctionQParser.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/ValueSourceParser.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstNumberSource.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstValueSource.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DocValues.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleConstValueSource.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleDocValues.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleFieldSource.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/LongDocValues.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/StrDocValues.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/StringIndexDocValues.java
    lucene/dev/trunk/solr/src/test/org/apache/solr/search/TestQueryTypes.java
    lucene/dev/trunk/solr/src/test/org/apache/solr/search/function/TestFunctionQuery.java

Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Fri Jun  3 20:48:47 2011
@@ -144,6 +144,10 @@ New Features
   to IndexReader.open (in the case you have a custom IndexReaderFactory).
   (simonw via rmuir)
 
+* SOLR-2136: Boolean type added to function queries, along with
+  new functions exists(), if(), and(), or(), xor(), not(), def(),
+  and true and false constants. (yonik) 
+
 
 Optimizations
 ----------------------

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/schema/BoolField.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/schema/BoolField.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/schema/BoolField.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/schema/BoolField.java Fri Jun  3 20:48:47 2011
@@ -17,12 +17,16 @@
 
 package org.apache.solr.schema;
 
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.CharsRef;
+import org.apache.solr.search.MutableValue;
+import org.apache.solr.search.MutableValueBool;
+import org.apache.solr.search.MutableValueInt;
 import org.apache.solr.search.QParser;
-import org.apache.solr.search.function.ValueSource;
-import org.apache.solr.search.function.OrdFieldSource;
+import org.apache.solr.search.function.*;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.Tokenizer;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
@@ -50,7 +54,7 @@ public class BoolField extends FieldType
   @Override
   public ValueSource getValueSource(SchemaField field, QParser qparser) {
     field.checkFieldCacheSource(qparser);
-    return new OrdFieldSource(field.name);
+    return new BoolFieldSource(field.name);
   }
 
   // avoid instantiating every time...
@@ -121,7 +125,7 @@ public class BoolField extends FieldType
 
   @Override
   public Object toObject(SchemaField sf, BytesRef term) {
-    return term.bytes[0] == 'T';
+    return term.bytes[term.offset] == 'T';
   }
 
   @Override
@@ -145,6 +149,83 @@ public class BoolField extends FieldType
 
   @Override
   public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
-    writer.writeBool(name, f.stringValue().charAt(0) =='T');
+    writer.writeBool(name, f.stringValue().charAt(0) == 'T');
   }
 }
+
+// TODO - this can be much more efficient - use OpenBitSet or Bits
+class BoolFieldSource extends ValueSource {
+  protected String field;
+
+  public BoolFieldSource(String field) {
+    this.field = field;
+  }
+
+  @Override
+  public String description() {
+    return "bool(" + field + ')';
+  }
+
+
+  @Override
+  public DocValues getValues(Map context, IndexReader.AtomicReaderContext readerContext) throws IOException {
+    final FieldCache.DocTermsIndex sindex = FieldCache.DEFAULT.getTermsIndex(readerContext.reader, field);
+
+    // figure out what ord maps to true
+    int nord = sindex.numOrd();
+    BytesRef br = new BytesRef();
+    int tord = -1;
+    for (int i=1; i<nord; i++) {
+      sindex.lookup(i, br);
+      if (br.length==1 && br.bytes[br.offset]=='T') {
+        tord = i;
+        break;
+      }
+    }
+
+    final int trueOrd = tord;
+
+    return new BoolDocValues(this) {
+      @Override
+      public boolean boolVal(int doc) {
+        return sindex.getOrd(doc) == trueOrd;
+      }
+
+      @Override
+      public boolean exists(int doc) {
+        return sindex.getOrd(doc) != 0;
+      }
+
+      @Override
+      public ValueFiller getValueFiller() {
+        return new ValueFiller() {
+          private final MutableValueBool mval = new MutableValueBool();
+
+          @Override
+          public MutableValue getValue() {
+            return mval;
+          }
+
+          @Override
+          public void fillValue(int doc) {
+            int ord = sindex.getOrd(doc);
+            mval.value = (ord == trueOrd);
+            mval.exists = (ord != 0);
+          }
+        };
+      }
+    };
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    return o.getClass() == BoolFieldSource.class && this.field.equals(((BoolFieldSource)o).field);
+  }
+
+  private static final int hcode = OrdFieldSource.class.hashCode();
+  @Override
+  public int hashCode() {
+    return hcode + field.hashCode();
+  };
+
+}

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/FunctionQParser.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/FunctionQParser.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/FunctionQParser.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/FunctionQParser.java Fri Jun  3 20:48:47 2011
@@ -364,8 +364,14 @@ public class FunctionQParser extends QPa
         sp.expect(")");
       }
       else {
-        SchemaField f = req.getSchema().getField(id);
-        valueSource = f.getType().getValueSource(f, this);
+        if ("true".equals(id)) {
+          valueSource = new BoolConstValueSource(true);
+        } else if ("false".equals(id)) {
+          valueSource = new BoolConstValueSource(false);
+        } else {
+          SchemaField f = req.getSchema().getField(id);
+          valueSource = f.getType().getValueSource(f, this);
+        }
       }
 
     }

Added: lucene/dev/trunk/solr/src/java/org/apache/solr/search/MutableValueBool.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/MutableValueBool.java?rev=1131228&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/MutableValueBool.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/MutableValueBool.java Fri Jun  3 20:48:47 2011
@@ -0,0 +1,60 @@
+/**
+ * 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.solr.search;
+
+public class MutableValueBool extends MutableValue {
+  public boolean value;
+
+  @Override
+  public Object toObject() {
+    return exists ? value : null;
+  }
+
+  @Override
+  public void copy(MutableValue source) {
+    MutableValueBool s = (MutableValueBool) source;
+    value = s.value;
+    exists = s.exists;
+  }
+
+  @Override
+  public MutableValue duplicate() {
+    MutableValueBool v = new MutableValueBool();
+    v.value = this.value;
+    v.exists = this.exists;
+    return v;
+  }
+
+  @Override
+  public boolean equalsSameType(Object other) {
+    MutableValueBool b = (MutableValueBool)other;
+    return value == b.value && exists == b.exists;
+  }
+
+  @Override
+  public int compareSameType(Object other) {
+    MutableValueBool b = (MutableValueBool)other;
+    if (value != b.value) return value ? 1 : 0;
+    if (exists == b.exists) return 0;
+    return exists ? 1 : -1;
+  }
+
+  @Override
+  public int hashCode() {
+    return value ? 2 : (exists ? 1 : 0);
+  }
+}

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/ValueSourceParser.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/ValueSourceParser.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/ValueSourceParser.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/ValueSourceParser.java Fri Jun  3 20:48:47 2011
@@ -579,6 +579,134 @@ public abstract class ValueSourceParser 
         return new NumDocsValueSource();
       }
     });
+
+    addParser("true", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws ParseException {
+        return new BoolConstValueSource(true);
+      }
+    });
+
+    addParser("false", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws ParseException {
+        return new BoolConstValueSource(false);
+      }
+    });
+
+    addParser("exists", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws ParseException {
+        ValueSource vs = fp.parseValueSource();
+        return new SimpleBoolFunction(vs) {
+          @Override
+          protected String name() {
+            return "exists";
+          }
+          @Override
+          protected boolean func(int doc, DocValues vals) {
+            return vals.exists(doc);
+          }
+        };
+      }
+    });
+
+    addParser("not", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws ParseException {
+        ValueSource vs = fp.parseValueSource();
+        return new SimpleBoolFunction(vs) {
+          @Override
+          protected boolean func(int doc, DocValues vals) {
+            return !vals.boolVal(doc);
+          }
+          @Override
+          protected String name() {
+            return "not";
+          }
+        };
+      }
+    });
+
+
+    addParser("and", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws ParseException {
+        List<ValueSource> sources = fp.parseValueSourceList();
+        return new MultiBoolFunction(sources) {
+          @Override
+          protected String name() {
+            return "and";
+          }
+          @Override
+          protected boolean func(int doc, DocValues[] vals) {
+            for (DocValues dv : vals)
+              if (!dv.boolVal(doc)) return false;
+            return true;
+          }
+        };
+      }
+    });
+
+    addParser("or", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws ParseException {
+        List<ValueSource> sources = fp.parseValueSourceList();
+        return new MultiBoolFunction(sources) {
+          @Override
+          protected String name() {
+            return "or";
+          }
+          @Override
+          protected boolean func(int doc, DocValues[] vals) {
+            for (DocValues dv : vals)
+              if (dv.boolVal(doc)) return true;
+            return false;
+          }
+        };
+      }
+    });
+
+    addParser("xor", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws ParseException {
+        List<ValueSource> sources = fp.parseValueSourceList();
+        return new MultiBoolFunction(sources) {
+          @Override
+          protected String name() {
+            return "xor";
+          }
+          @Override
+          protected boolean func(int doc, DocValues[] vals) {
+            int nTrue=0, nFalse=0;
+            for (DocValues dv : vals) {
+              if (dv.boolVal(doc)) nTrue++;
+              else nFalse++;
+            }
+            return nTrue != 0 && nFalse != 0;
+          }
+        };
+      }
+    });
+
+    addParser("if", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws ParseException {
+        ValueSource ifValueSource = fp.parseValueSource();
+        ValueSource trueValueSource = fp.parseValueSource();
+        ValueSource falseValueSource = fp.parseValueSource();
+
+        return new IfFunction(ifValueSource, trueValueSource, falseValueSource);
+      }
+    });
+
+    addParser("def", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws ParseException {
+        return new DefFunction(fp.parseValueSourceList());
+      }
+    });
+
   }
 
   private static TInfo parseTerm(FunctionQParser fp) throws ParseException {
@@ -857,6 +985,11 @@ class LongConstValueSource extends Const
   public Number getNumber() {
     return constant;
   }
+
+  @Override
+  public boolean getBool() {
+    return constant != 0;
+  }
 }
 
 
@@ -981,3 +1114,69 @@ abstract class Double2Parser extends Nam
   }
 
 }
+
+
+class BoolConstValueSource extends ConstNumberSource {
+  final boolean constant;
+
+  public BoolConstValueSource(boolean constant) {
+    this.constant = constant;
+  }
+
+  @Override
+  public String description() {
+    return "const(" + constant + ")";
+  }
+
+  @Override
+  public DocValues getValues(Map context, AtomicReaderContext readerContext) throws IOException {
+    return new BoolDocValues(this) {
+      @Override
+      public boolean boolVal(int doc) {
+        return constant;
+      }
+    };
+  }
+
+  @Override
+  public int hashCode() {
+    return constant ? 0x12345678 : 0x87654321;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (BoolConstValueSource.class != o.getClass()) return false;
+    BoolConstValueSource other = (BoolConstValueSource) o;
+    return this.constant == other.constant;
+  }
+
+    @Override
+  public int getInt() {
+    return constant ? 1 : 0;
+  }
+
+  @Override
+  public long getLong() {
+    return constant ? 1 : 0;
+  }
+
+  @Override
+  public float getFloat() {
+    return constant ? 1 : 0;
+  }
+
+  @Override
+  public double getDouble() {
+    return constant ? 1 : 0;
+  }
+
+  @Override
+  public Number getNumber() {
+    return constant ? 1 : 0;
+  }
+
+  @Override
+  public boolean getBool() {
+    return constant;
+  }
+}

Added: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/BoolDocValues.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/BoolDocValues.java?rev=1131228&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/BoolDocValues.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/BoolDocValues.java Fri Jun  3 20:48:47 2011
@@ -0,0 +1,79 @@
+package org.apache.solr.search.function;
+
+import org.apache.solr.search.MutableValue;
+import org.apache.solr.search.MutableValueBool;
+import org.apache.solr.search.MutableValueInt;
+
+public abstract class BoolDocValues extends DocValues {
+  protected final ValueSource vs;
+
+  public BoolDocValues(ValueSource vs) {
+    this.vs = vs;
+  }
+
+  @Override
+  public abstract boolean boolVal(int doc);
+
+  @Override
+  public byte byteVal(int doc) {
+    return boolVal(doc) ? (byte)1 : (byte)0;
+  }
+
+  @Override
+  public short shortVal(int doc) {
+    return boolVal(doc) ? (short)1 : (short)0;
+  }
+
+  @Override
+  public float floatVal(int doc) {
+    return boolVal(doc) ? (float)1 : (float)0;
+  }
+
+  @Override
+  public int intVal(int doc) {
+    return boolVal(doc) ? 1 : 0;
+  }
+
+  @Override
+  public long longVal(int doc) {
+    return boolVal(doc) ? (long)1 : (long)0;
+  }
+
+  @Override
+  public double doubleVal(int doc) {
+    return boolVal(doc) ? (double)1 : (double)0;
+  }
+
+  @Override
+  public String strVal(int doc) {
+    return Boolean.toString(boolVal(doc));
+  }
+
+  @Override
+  public Object objectVal(int doc) {
+    return exists(doc) ? boolVal(doc) : null;
+  }
+
+  @Override
+  public String toString(int doc) {
+    return vs.description() + '=' + strVal(doc);
+  }
+
+  @Override
+  public ValueFiller getValueFiller() {
+    return new ValueFiller() {
+      private final MutableValueBool mval = new MutableValueBool();
+
+      @Override
+      public MutableValue getValue() {
+        return mval;
+      }
+
+      @Override
+      public void fillValue(int doc) {
+        mval.value = boolVal(doc);
+        mval.exists = exists(doc);
+      }
+    };
+  }
+}

Added: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/BoolFunction.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/BoolFunction.java?rev=1131228&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/BoolFunction.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/BoolFunction.java Fri Jun  3 20:48:47 2011
@@ -0,0 +1,23 @@
+/**
+ * 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.solr.search.function;
+
+
+public abstract class BoolFunction extends ValueSource {
+  // TODO: placeholder to return type, among other common future functionality
+}

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstNumberSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstNumberSource.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstNumberSource.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstNumberSource.java Fri Jun  3 20:48:47 2011
@@ -26,4 +26,5 @@ public abstract class ConstNumberSource 
   public abstract float getFloat();
   public abstract double getDouble();  
   public abstract Number getNumber();  
+  public abstract boolean getBool();
 }

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstValueSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstValueSource.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstValueSource.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstValueSource.java Fri Jun  3 20:48:47 2011
@@ -66,6 +66,10 @@ public class ConstValueSource extends Co
       public Object objectVal(int doc) {
         return constant;
       }
+      @Override
+      public boolean boolVal(int doc) {
+        return constant != 0.0f;
+      }
     };
   }
 
@@ -105,4 +109,9 @@ public class ConstValueSource extends Co
   public Number getNumber() {
     return constant;
   }
+
+  @Override
+  public boolean getBool() {
+    return constant != 0.0f;
+  }
 }

Added: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DefFunction.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DefFunction.java?rev=1131228&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DefFunction.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DefFunction.java Fri Jun  3 20:48:47 2011
@@ -0,0 +1,124 @@
+package org.apache.solr.search.function;
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.util.BytesRef;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+public class DefFunction extends MultiFunction {
+  public DefFunction(List<ValueSource> sources) {
+    super(sources);
+  }
+
+  @Override
+  protected String name() {
+    return "def";
+  }
+
+
+  @Override
+  public DocValues getValues(Map fcontext, AtomicReaderContext readerContext) throws IOException {
+
+
+    return new Values(valsArr(sources, fcontext, readerContext)) {
+      final int upto = valsArr.length - 1;
+
+      private DocValues get(int doc) {
+        for (int i=0; i<upto; i++) {
+          DocValues vals = valsArr[i];
+          if (vals.exists(doc)) {
+            return vals;
+          }
+        }
+        return valsArr[upto];
+      }
+
+      @Override
+      public byte byteVal(int doc) {
+        return get(doc).byteVal(doc);
+      }
+
+      @Override
+      public short shortVal(int doc) {
+        return get(doc).shortVal(doc);
+      }
+
+      @Override
+      public float floatVal(int doc) {
+        return get(doc).floatVal(doc);
+      }
+
+      @Override
+      public int intVal(int doc) {
+        return get(doc).intVal(doc);
+      }
+
+      @Override
+      public long longVal(int doc) {
+        return get(doc).longVal(doc);
+      }
+
+      @Override
+      public double doubleVal(int doc) {
+        return get(doc).doubleVal(doc);
+      }
+
+      @Override
+      public String strVal(int doc) {
+        return get(doc).strVal(doc);
+      }
+
+      @Override
+      public boolean boolVal(int doc) {
+        return get(doc).boolVal(doc);
+      }
+
+      @Override
+      public boolean bytesVal(int doc, BytesRef target) {
+        return get(doc).bytesVal(doc, target);
+      }
+
+      @Override
+      public Object objectVal(int doc) {
+        return get(doc).objectVal(doc);
+      }
+
+      @Override
+      public boolean exists(int doc) {
+        // return true if any source is exists?
+        for (DocValues vals : valsArr) {
+          if (vals.exists(doc)) {
+            return true;
+          }
+        }
+        return false;
+      }
+
+      @Override
+      public ValueFiller getValueFiller() {
+        // TODO: need ValueSource.type() to determine correct type
+        return super.getValueFiller();
+      }
+    };
+  }
+}
\ No newline at end of file

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DocValues.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DocValues.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DocValues.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DocValues.java Fri Jun  3 20:48:47 2011
@@ -48,6 +48,10 @@ public abstract class DocValues {
   // TODO: should we make a termVal, returns BytesRef?
   public String strVal(int doc) { throw new UnsupportedOperationException(); }
 
+  public boolean boolVal(int doc) {
+    return intVal(doc) != 0;
+  }
+
   /** returns the bytes representation of the string val - TODO: should this return the indexed raw bytes not? */
   public boolean bytesVal(int doc, BytesRef target) {
     String s = strVal(doc);

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleConstValueSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleConstValueSource.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleConstValueSource.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleConstValueSource.java Fri Jun  3 20:48:47 2011
@@ -115,4 +115,9 @@ public class DoubleConstValueSource exte
   public Number getNumber() {
     return constant;
   }
+
+  @Override
+  public boolean getBool() {
+    return constant != 0;
+  }
 }

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleDocValues.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleDocValues.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleDocValues.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleDocValues.java Fri Jun  3 20:48:47 2011
@@ -36,6 +36,11 @@ public abstract class DoubleDocValues ex
   }
 
   @Override
+  public boolean boolVal(int doc) {
+    return doubleVal(doc) != 0;
+  }
+
+  @Override
   public abstract double doubleVal(int doc);
 
   @Override

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleFieldSource.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleFieldSource.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleFieldSource.java Fri Jun  3 20:48:47 2011
@@ -53,40 +53,15 @@ public class DoubleFieldSource extends N
     final double[] arr = vals.values;
     final Bits valid = vals.valid;
     
-    return new DocValues() {
-      @Override
-      public float floatVal(int doc) {
-        return (float) arr[doc];
-      }
-
-      @Override
-      public int intVal(int doc) {
-        return (int) arr[doc];
-      }
-
-      @Override
-      public long longVal(int doc) {
-        return (long) arr[doc];
-      }
-
+    return new DoubleDocValues(this) {
       @Override
       public double doubleVal(int doc) {
         return arr[doc];
       }
 
       @Override
-      public String strVal(int doc) {
-        return Double.toString(arr[doc]);
-      }
-
-      @Override
-      public Object objectVal(int doc) {
-        return valid.get(doc) ? arr[doc] : null;
-      }
-
-      @Override
-      public String toString(int doc) {
-        return description() + '=' + doubleVal(doc);
+      public boolean exists(int doc) {
+        return valid.get(doc);
       }
 
       @Override
@@ -147,7 +122,7 @@ public class DoubleFieldSource extends N
         }
       }
 
-            @Override
+      @Override
       public ValueFiller getValueFiller() {
         return new ValueFiller() {
           private final double[] doubleArr = arr;

Added: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/IfFunction.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/IfFunction.java?rev=1131228&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/IfFunction.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/IfFunction.java Fri Jun  3 20:48:47 2011
@@ -0,0 +1,148 @@
+/**
+ * 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.solr.search.function;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.util.BytesRef;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+
+public class IfFunction extends BoolFunction {
+  private ValueSource ifSource;
+  private ValueSource trueSource;
+  private ValueSource falseSource;
+
+
+  public IfFunction(ValueSource ifSource, ValueSource trueSource, ValueSource falseSource) {
+    this.ifSource = ifSource;
+    this.trueSource = trueSource;
+    this.falseSource = falseSource;
+  }
+
+  @Override
+  public DocValues getValues(Map context, AtomicReaderContext readerContext) throws IOException {
+    final DocValues ifVals = ifSource.getValues(context, readerContext);
+    final DocValues trueVals = trueSource.getValues(context, readerContext);
+    final DocValues falseVals = falseSource.getValues(context, readerContext);
+
+    return new DocValues() {
+      @Override
+      public byte byteVal(int doc) {
+        return ifVals.boolVal(doc) ? trueVals.byteVal(doc) : falseVals.byteVal(doc);
+      }
+
+      @Override
+      public short shortVal(int doc) {
+        return ifVals.boolVal(doc) ? trueVals.shortVal(doc) : falseVals.shortVal(doc);
+      }
+
+      @Override
+      public float floatVal(int doc) {
+        return ifVals.boolVal(doc) ? trueVals.floatVal(doc) : falseVals.floatVal(doc);
+      }
+
+      @Override
+      public int intVal(int doc) {
+        return ifVals.boolVal(doc) ? trueVals.intVal(doc) : falseVals.intVal(doc);
+      }
+
+      @Override
+      public long longVal(int doc) {
+        return ifVals.boolVal(doc) ? trueVals.longVal(doc) : falseVals.longVal(doc);
+      }
+
+      @Override
+      public double doubleVal(int doc) {
+        return ifVals.boolVal(doc) ? trueVals.doubleVal(doc) : falseVals.doubleVal(doc);
+      }
+
+      @Override
+      public String strVal(int doc) {
+        return ifVals.boolVal(doc) ? trueVals.strVal(doc) : falseVals.strVal(doc);
+      }
+
+      @Override
+      public boolean boolVal(int doc) {
+        return ifVals.boolVal(doc) ? trueVals.boolVal(doc) : falseVals.boolVal(doc);
+      }
+
+      @Override
+      public boolean bytesVal(int doc, BytesRef target) {
+        return ifVals.boolVal(doc) ? trueVals.bytesVal(doc, target) : falseVals.bytesVal(doc, target);
+      }
+
+      @Override
+      public Object objectVal(int doc) {
+        return ifVals.boolVal(doc) ? trueVals.objectVal(doc) : falseVals.objectVal(doc);
+      }
+
+      @Override
+      public boolean exists(int doc) {
+        return true; // TODO: flow through to any sub-sources?
+      }
+
+      @Override
+      public ValueFiller getValueFiller() {
+        // TODO: we need types of trueSource / falseSource to handle this
+        // for now, use float.
+        return super.getValueFiller();
+      }
+
+      @Override
+      public String toString(int doc) {
+        return "if(" + ifVals.toString(doc) + ',' + trueVals.toString(doc) + ',' + falseVals.toString(doc) + ')';
+      }
+    };
+
+  }
+
+  @Override
+  public String description() {
+    return "if(" + ifSource.description() + ',' + trueSource.description() + ',' + falseSource + ')';
+  }
+
+  @Override
+  public int hashCode() {
+    int h = ifSource.hashCode();
+    h = h * 31 + trueSource.hashCode();
+    h = h * 31 + falseSource.hashCode();
+    return h;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof IfFunction)) return false;
+    IfFunction other = (IfFunction)o;
+    return ifSource.equals(other.ifSource)
+        && trueSource.equals(other.trueSource)
+        && falseSource.equals(other.falseSource);
+  }
+
+  @Override
+  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+    ifSource.createWeight(context, searcher);
+    trueSource.createWeight(context, searcher);
+    falseSource.createWeight(context, searcher);
+  }
+}
\ No newline at end of file

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/LongDocValues.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/LongDocValues.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/LongDocValues.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/LongDocValues.java Fri Jun  3 20:48:47 2011
@@ -39,6 +39,11 @@ public abstract class LongDocValues exte
   }
 
   @Override
+  public boolean boolVal(int doc) {
+    return longVal(doc) != 0;
+  }
+
+  @Override
   public String strVal(int doc) {
     return Long.toString(longVal(doc));
   }

Added: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/MultiBoolFunction.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/MultiBoolFunction.java?rev=1131228&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/MultiBoolFunction.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/MultiBoolFunction.java Fri Jun  3 20:48:47 2011
@@ -0,0 +1,105 @@
+/**
+ * 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.solr.search.function;
+
+import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.search.IndexSearcher;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+
+public abstract class MultiBoolFunction extends BoolFunction {
+  protected final List<ValueSource> sources;
+
+  public MultiBoolFunction(List<ValueSource> sources) {
+    this.sources = sources;
+  }
+
+  protected abstract String name();
+
+  protected abstract boolean func(int doc, DocValues[] vals);
+
+  @Override
+  public BoolDocValues getValues(Map context, AtomicReaderContext readerContext) throws IOException {
+    final DocValues[] vals =  new DocValues[sources.size()];
+    int i=0;
+    for (ValueSource source : sources) {
+      vals[i++] = source.getValues(context, readerContext);
+    }
+
+    return new BoolDocValues(this) {
+      @Override
+      public boolean boolVal(int doc) {
+	      return func(doc, vals);
+      }
+
+      @Override
+      public String toString(int doc) {
+        StringBuilder sb = new StringBuilder(name());
+        sb.append('(');
+        boolean first = true;
+        for (DocValues dv : vals) {
+          if (first) {
+            first = false;
+          } else {
+            sb.append(',');
+          }
+          sb.append(dv.toString(doc));
+        }
+        return sb.toString();
+      }
+    };
+  }
+
+  @Override
+  public String description() {
+    StringBuilder sb = new StringBuilder(name());
+    sb.append('(');
+    boolean first = true;
+    for (ValueSource source : sources) {
+      if (first) {
+        first = false;
+      } else {
+        sb.append(',');
+      }
+      sb.append(source.description());
+    }
+    return sb.toString();
+  }
+
+  @Override
+  public int hashCode() {
+    return sources.hashCode() + name().hashCode();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this.getClass() != o.getClass()) return false;
+    MultiBoolFunction other = (MultiBoolFunction)o;
+    return this.sources.equals(other.sources);
+  }
+
+  @Override
+  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+    for (ValueSource source : sources) {
+      source.createWeight(context, searcher);
+    }
+  }
+}
\ No newline at end of file

Added: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/MultiFunction.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/MultiFunction.java?rev=1131228&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/MultiFunction.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/MultiFunction.java Fri Jun  3 20:48:47 2011
@@ -0,0 +1,122 @@
+package org.apache.solr.search.function;
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.util.BytesRef;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+
+public abstract class MultiFunction extends ValueSource {
+  protected final List<ValueSource> sources;
+
+  public MultiFunction(List<ValueSource> sources) {
+    this.sources = sources;
+  }
+
+  abstract protected String name();
+
+  @Override
+  public String description() {
+    return description(name(), sources);
+  }
+
+  public static String description(String name, List<ValueSource> sources) {
+    StringBuilder sb = new StringBuilder();
+    sb.append(name).append('(');
+    boolean firstTime=true;
+    for (ValueSource source : sources) {
+      if (firstTime) {
+        firstTime=false;
+      } else {
+        sb.append(',');
+      }
+      sb.append(source);
+    }
+    sb.append(')');
+    return sb.toString();
+  }
+
+  public static DocValues[] valsArr(List<ValueSource> sources, Map fcontext, AtomicReaderContext readerContext) throws IOException {
+    final DocValues[] valsArr = new DocValues[sources.size()];
+    int i=0;
+    for (ValueSource source : sources) {
+      valsArr[i++] = source.getValues(fcontext, readerContext);
+    }
+    return valsArr;
+  }
+
+  public class Values extends DocValues {
+    final DocValues[] valsArr;
+
+    public Values(DocValues[] valsArr) {
+      this.valsArr = valsArr;
+    }
+
+    @Override
+    public String toString(int doc) {
+      return MultiFunction.toString(name(), valsArr, doc);
+    }
+
+    @Override
+    public ValueFiller getValueFiller() {
+      // TODO: need ValueSource.type() to determine correct type
+      return super.getValueFiller();
+    }
+  }
+
+
+  public static String toString(String name, DocValues[] valsArr, int doc) {
+    StringBuilder sb = new StringBuilder();
+    sb.append(name).append('(');
+    boolean firstTime=true;
+    for (DocValues vals : valsArr) {
+      if (firstTime) {
+        firstTime=false;
+      } else {
+        sb.append(',');
+      }
+      sb.append(vals.toString(doc));
+    }
+    sb.append(')');
+    return sb.toString();
+  }
+
+  @Override
+  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+    for (ValueSource source : sources)
+      source.createWeight(context, searcher);
+  }
+
+  @Override
+  public int hashCode() {
+    return sources.hashCode() + name().hashCode();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this.getClass() != o.getClass()) return false;
+    MultiFunction other = (MultiFunction)o;
+    return this.sources.equals(other.sources);
+  }
+}
+

Added: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/SimpleBoolFunction.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/SimpleBoolFunction.java?rev=1131228&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/SimpleBoolFunction.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/SimpleBoolFunction.java Fri Jun  3 20:48:47 2011
@@ -0,0 +1,74 @@
+/**
+ * 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.solr.search.function;
+
+import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.search.IndexSearcher;
+
+import java.io.IOException;
+import java.util.Map;
+
+
+public abstract class SimpleBoolFunction extends BoolFunction {
+  protected final ValueSource source;
+
+  public SimpleBoolFunction(ValueSource source) {
+    this.source = source;
+  }
+
+  protected abstract String name();
+
+  protected abstract boolean func(int doc, DocValues vals);
+
+  @Override
+  public BoolDocValues getValues(Map context, AtomicReaderContext readerContext) throws IOException {
+    final DocValues vals =  source.getValues(context, readerContext);
+    return new BoolDocValues(this) {
+      @Override
+      public boolean boolVal(int doc) {
+	      return func(doc, vals);
+      }
+      @Override
+      public String toString(int doc) {
+	      return name() + '(' + vals.toString(doc) + ')';
+      }
+    };
+  }
+
+  @Override
+  public String description() {
+    return name() + '(' + source.description() + ')';
+  }
+
+  @Override
+  public int hashCode() {
+    return source.hashCode() + name().hashCode();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this.getClass() != o.getClass()) return false;
+    SingleFunction other = (SingleFunction)o;
+    return this.source.equals(other.source);
+  }
+
+  @Override
+  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+    source.createWeight(context, searcher);
+  }
+}
\ No newline at end of file

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/StrDocValues.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/StrDocValues.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/StrDocValues.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/StrDocValues.java Fri Jun  3 20:48:47 2011
@@ -22,6 +22,11 @@ public abstract class StrDocValues exten
   }
 
   @Override
+  public boolean boolVal(int doc) {
+    return exists(doc);
+  }
+
+  @Override
   public String toString(int doc) {
     return vs.description() + "='" + strVal(doc) + "'";
   }

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/StringIndexDocValues.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/StringIndexDocValues.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/StringIndexDocValues.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/StringIndexDocValues.java Fri Jun  3 20:48:47 2011
@@ -78,6 +78,10 @@ public abstract class StringIndexDocValu
     return spareChars.toString();
   }
 
+  @Override
+  public boolean boolVal(int doc) {
+    return exists(doc);
+  }
 
   @Override
   public abstract Object objectVal(int doc);  // force subclasses to override

Modified: lucene/dev/trunk/solr/src/test/org/apache/solr/search/TestQueryTypes.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test/org/apache/solr/search/TestQueryTypes.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/test/org/apache/solr/search/TestQueryTypes.java (original)
+++ lucene/dev/trunk/solr/src/test/org/apache/solr/search/TestQueryTypes.java Fri Jun  3 20:48:47 2011
@@ -119,7 +119,29 @@ public class TestQueryTypes extends Abst
       assertQ(req( "q", "{!frange v="+f+" l='"+v+"' u='"+v+"'}" )
               ,"//result[@numFound='1']"
               );
-      
+
+      // exists()
+      assertQ(req( "fq","id:999", "q", "{!frange l=1 u=1}if(exists("+f+"),1,0)" )
+              ,"//result[@numFound='1']"
+              );
+
+      // boolean value of non-zero values (just leave off the exists from the prev test)
+      assertQ(req( "fq","id:999", "q", "{!frange l=1 u=1}if("+f+",1,0)" )
+              ,"//result[@numFound='1']"
+              );
+
+      if (!"id".equals(f)) {
+        assertQ(req( "fq","id:1", "q", "{!frange l=1 u=1}if(exists("+f+"),1,0)" )
+            ,"//result[@numFound='0']"
+        );
+
+       // boolean value of zero/missing values (just leave off the exists from the prev test)
+       assertQ(req( "fq","id:1", "q", "{!frange l=1 u=1}if("+f+",1,0)" )
+            ,"//result[@numFound='0']"
+        );
+
+      }
+
       // function query... just make sure it doesn't throw an exception
       if ("v_s".equals(f)) continue;  // in this context, functions must be able to be interpreted as a float
       assertQ(req( "q", "+id:999 _val_:\"" + f + "\"")

Modified: lucene/dev/trunk/solr/src/test/org/apache/solr/search/function/TestFunctionQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test/org/apache/solr/search/function/TestFunctionQuery.java?rev=1131228&r1=1131227&r2=1131228&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/test/org/apache/solr/search/function/TestFunctionQuery.java (original)
+++ lucene/dev/trunk/solr/src/test/org/apache/solr/search/function/TestFunctionQuery.java Fri Jun  3 20:48:47 2011
@@ -581,4 +581,56 @@ public class TestFunctionQuery extends S
     purgeFieldCache(FieldCache.DEFAULT);   // avoid FC insanity    
   }
 
+    @Test
+  public void testBooleanFunctions() throws Exception {
+    assertU(adoc("id", "1", "text", "hello", "foo_s","A", "foo_ti", "0", "foo_tl","0"));
+    assertU(adoc("id", "2"                              , "foo_ti","10", "foo_tl","11"));
+    assertU(commit());
+
+    // true and false functions and constants
+    assertJQ(req("q", "id:1", "fl", "t:true(),f:false(),tt:{!func}true,ff:{!func}false")
+        , "/response/docs/[0]=={'t':true,'f':false,'tt':true,'ff':false}");
+
+    // test that exists(query) depends on the query matching the document
+    assertJQ(req("q", "id:1", "fl", "t:exists(query($q1)),f:exists(query($q2))", "q1","text:hello", "q2","text:there")
+        , "/response/docs/[0]=={'t':true,'f':false}");
+
+    // test if()
+    assertJQ(req("q", "id:1", "fl", "a1:if(true,'A','B')", "fl","b1:if(false,'A','B')")
+        , "/response/docs/[0]=={'a1':'A', 'b1':'B'}");
+
+    // test boolean operators
+    assertJQ(req("q", "id:1", "fl", "t1:and(true,true)", "fl","f1:and(true,false)", "fl","f2:and(false,true)", "fl","f3:and(false,false)")
+        , "/response/docs/[0]=={'t1':true, 'f1':false, 'f2':false, 'f3':false}");
+    assertJQ(req("q", "id:1", "fl", "t1:or(true,true)", "fl","t2:or(true,false)", "fl","t3:or(false,true)", "fl","f1:or(false,false)")
+        , "/response/docs/[0]=={'t1':true, 't2':true, 't3':true, 'f1':false}");
+    assertJQ(req("q", "id:1", "fl", "f1:xor(true,true)", "fl","t1:xor(true,false)", "fl","t2:xor(false,true)", "fl","f2:xor(false,false)")
+        , "/response/docs/[0]=={'t1':true, 't2':true, 'f1':false, 'f2':false}");
+    assertJQ(req("q", "id:1", "fl", "t:not(false),f:not(true)")
+        , "/response/docs/[0]=={'t':true, 'f':false}");
+
+
+    // def(), the default function that returns the first value that exists
+    assertJQ(req("q", "id:1", "fl", "x:def(id,123.0), y:def(foo_f,234.0)")
+        , "/response/docs/[0]=={'x':1.0, 'y':234.0}");
+    assertJQ(req("q", "id:1", "fl", "x:def(foo_s,'Q'), y:def(missing_s,'W')")
+        , "/response/docs/[0]=={'x':'A', 'y':'W'}");
+
+    // test constant conversion to boolean
+    assertJQ(req("q", "id:1", "fl", "a:not(0), b:not(1), c:not(0.0), d:not(1.1), e:not('A')")
+        , "/response/docs/[0]=={'a':true, 'b':false, 'c':true, 'd':false, 'e':false}");
+
+  }
+
+
+  @Test
+  public void testPseudoFieldFunctions() throws Exception {
+    assertU(adoc("id", "1", "text", "hello", "foo_s","A"));
+    assertU(adoc("id", "2"));
+    assertU(commit());
+
+    assertJQ(req("q", "id:1", "fl", "a:1,b:2.0,c:'X',d:{!func}foo_s,e:{!func}bar_s")  // if exists() is false, no pseudo-field should be added
+        , "/response/docs/[0]=={'a':1, 'b':2.0,'c':'X','d':'A'}");
+  }
+
 }



Mime
View raw message