1) Broaden FullText to include ranking abilities along with matching, 2) Implement CASE WHEN ELSE END, 3) Let the people do 1 + 2 + 3 rathern 1 + (2 + 3), and so forth.

This commit is contained in:
Par Winzell
2009-03-18 19:01:20 +00:00
parent 830e830100
commit fa7d2c0a7f
8 changed files with 309 additions and 94 deletions
@@ -55,8 +55,9 @@ import com.samskivert.depot.expression.LiteralExp;
import com.samskivert.depot.expression.SQLExpression; import com.samskivert.depot.expression.SQLExpression;
import com.samskivert.depot.expression.ValueExp; import com.samskivert.depot.expression.ValueExp;
import com.samskivert.depot.operator.Conditionals.Case;
import com.samskivert.depot.operator.Conditionals.Exists; import com.samskivert.depot.operator.Conditionals.Exists;
import com.samskivert.depot.operator.Conditionals.FullTextMatch; import com.samskivert.depot.operator.Conditionals.FullText;
import com.samskivert.depot.operator.Conditionals.In; import com.samskivert.depot.operator.Conditionals.In;
import com.samskivert.depot.operator.Conditionals.IsNull; import com.samskivert.depot.operator.Conditionals.IsNull;
import com.samskivert.depot.operator.Logic.Not; import com.samskivert.depot.operator.Logic.Not;
@@ -141,11 +142,28 @@ public class BindVisitor implements ExpressionVisitor
} }
} }
public void visit (FullTextMatch match) public void visit (FullText.Match match)
{ {
// we never get here // we never get here
} }
public void visit (FullText.Rank rank)
{
// we never get here
}
public void visit (Case caseExp)
{
for (Tuple<SQLExpression, SQLExpression> tuple : caseExp.getWhenExps()) {
tuple.left.accept(this);
tuple.right.accept(this);
}
SQLExpression elseExp = caseExp.getElseExp();
if (elseExp != null) {
elseExp.accept(this);
}
}
public void visit (ColumnExp columnExp) public void visit (ColumnExp columnExp)
{ {
// no arguments // no arguments
@@ -50,8 +50,9 @@ import com.samskivert.depot.expression.FunctionExp;
import com.samskivert.depot.expression.LiteralExp; import com.samskivert.depot.expression.LiteralExp;
import com.samskivert.depot.expression.SQLExpression; import com.samskivert.depot.expression.SQLExpression;
import com.samskivert.depot.expression.ValueExp; import com.samskivert.depot.expression.ValueExp;
import com.samskivert.depot.operator.Conditionals.Case;
import com.samskivert.depot.operator.Conditionals.Exists; import com.samskivert.depot.operator.Conditionals.Exists;
import com.samskivert.depot.operator.Conditionals.FullTextMatch; import com.samskivert.depot.operator.Conditionals.FullText;
import com.samskivert.depot.operator.Conditionals.In; import com.samskivert.depot.operator.Conditionals.In;
import com.samskivert.depot.operator.Conditionals.IsNull; import com.samskivert.depot.operator.Conditionals.IsNull;
import com.samskivert.depot.operator.Logic.Not; import com.samskivert.depot.operator.Logic.Not;
@@ -216,8 +217,25 @@ public abstract class BuildVisitor implements ExpressionVisitor
public abstract void visit (EpochSeconds seconds); public abstract void visit (EpochSeconds seconds);
public abstract void visit (FullTextMatch match); public abstract void visit (FullText.Match match);
public void visit (Case caseExp)
{
_builder.append("(case ");
for (Tuple<SQLExpression, SQLExpression> tuple : caseExp.getWhenExps()) {
_builder.append(" when ");
tuple.left.accept(this);
_builder.append(" then ");
tuple.right.accept(this);
}
SQLExpression elseExp = caseExp.getElseExp();
if (elseExp != null) {
_builder.append(" else ");
elseExp.accept(this);
}
_builder.append(" end)");
}
public void visit (ColumnExp columnExp) public void visit (ColumnExp columnExp)
{ {
appendRhsColumn(columnExp.getPersistentClass(), columnExp.getField()); appendRhsColumn(columnExp.getPersistentClass(), columnExp.getField());
@@ -41,10 +41,11 @@ import com.samskivert.depot.expression.FunctionExp;
import com.samskivert.depot.expression.LiteralExp; import com.samskivert.depot.expression.LiteralExp;
import com.samskivert.depot.expression.ValueExp; import com.samskivert.depot.expression.ValueExp;
import com.samskivert.depot.operator.Conditionals.Case;
import com.samskivert.depot.operator.Conditionals.Exists; import com.samskivert.depot.operator.Conditionals.Exists;
import com.samskivert.depot.operator.Conditionals.FullText;
import com.samskivert.depot.operator.Conditionals.In; import com.samskivert.depot.operator.Conditionals.In;
import com.samskivert.depot.operator.Conditionals.IsNull; import com.samskivert.depot.operator.Conditionals.IsNull;
import com.samskivert.depot.operator.Conditionals.FullTextMatch;
import com.samskivert.depot.operator.Logic.Not; import com.samskivert.depot.operator.Logic.Not;
import com.samskivert.depot.operator.SQLOperator.BinaryOperator; import com.samskivert.depot.operator.SQLOperator.BinaryOperator;
import com.samskivert.depot.operator.SQLOperator.MultiOperator; import com.samskivert.depot.operator.SQLOperator.MultiOperator;
@@ -67,7 +68,8 @@ public interface ExpressionVisitor
public void visit (BinaryOperator binaryOperator); public void visit (BinaryOperator binaryOperator);
public void visit (IsNull isNull); public void visit (IsNull isNull);
public void visit (In in); public void visit (In in);
public void visit (FullTextMatch match); public void visit (FullText.Match match);
public void visit (FullText.Rank rank);
public void visit (ColumnExp columnExp); public void visit (ColumnExp columnExp);
public void visit (Not not); public void visit (Not not);
public void visit (GroupBy groupBy); public void visit (GroupBy groupBy);
@@ -87,4 +89,5 @@ public interface ExpressionVisitor
public void visit (InsertClause insertClause); public void visit (InsertClause insertClause);
public void visit (CreateIndexClause createIndexClause); public void visit (CreateIndexClause createIndexClause);
public void visit (DropIndexClause<? extends PersistentRecord> dropIndexClause); public void visit (DropIndexClause<? extends PersistentRecord> dropIndexClause);
public void visit (Case caseExp);
} }
@@ -50,10 +50,10 @@ import com.samskivert.depot.expression.FunctionExp;
import com.samskivert.depot.expression.SQLExpression; import com.samskivert.depot.expression.SQLExpression;
import com.samskivert.depot.operator.Arithmetic.BitAnd; import com.samskivert.depot.operator.Arithmetic.BitAnd;
import com.samskivert.depot.operator.Arithmetic.BitOr; import com.samskivert.depot.operator.Arithmetic.BitOr;
import com.samskivert.depot.operator.Conditionals.FullTextMatch; import com.samskivert.depot.operator.Conditionals.FullText;
import com.samskivert.depot.operator.Conditionals.Like; import com.samskivert.depot.operator.Conditionals.Like;
import com.samskivert.depot.operator.Logic.Or; import com.samskivert.depot.operator.Logic.Or;
import com.samskivert.depot.operator.SQLOperator.BinaryOperator; import com.samskivert.depot.operator.SQLOperator.MultiOperator;
import com.samskivert.depot.impl.clause.CreateIndexClause; import com.samskivert.depot.impl.clause.CreateIndexClause;
@@ -62,20 +62,20 @@ public class HSQLBuilder
{ {
public class HBuildVisitor extends BuildVisitor public class HBuildVisitor extends BuildVisitor
{ {
@Override public void visit (FullTextMatch match) @Override public void visit (FullText.Match match)
{ {
// HSQL doesn't have real full text search, so we fake it by creating a condition like // HSQL doesn't have real full text search, so we fake it by creating a condition like
// (lower(COL1) like '%foo%') OR (lower(COL1) like '%bar%') OR ... // (lower(COL1) like '%foo%') OR (lower(COL1) like '%bar%') OR ...
// (lower(COL2) like '%foo%') OR (lower(COL2) like '%bar%') OR ... // (lower(COL2) like '%foo%') OR (lower(COL2) like '%bar%') OR ...
// ... and so on. Not efficient, but basically functional. // ... and so on. Not efficient, but basically functional.
Class<? extends PersistentRecord> pClass = match.getPersistentClass(); Class<? extends PersistentRecord> pClass = match.getDefinition().getPersistentClass();
// find the fields involved // find the fields involved
String[] fields = _types.getMarshaller(pClass). String[] fields = _types.getMarshaller(pClass).
getFullTextIndex(match.getName()).fields(); getFullTextIndex(match.getDefinition().getName()).fields();
// explode the query into words // explode the query into words
String[] ftsWords = match.getQuery().toLowerCase().split("\\W+"); String[] ftsWords = match.getDefinition().getQuery().toLowerCase().split("\\W+");
if (ftsWords.length > 0 && ftsWords[0].length() == 0) { if (ftsWords.length > 0 && ftsWords[0].length() == 0) {
// if the query led with whitespace, the first 'word' will be empty; strip it // if the query led with whitespace, the first 'word' will be empty; strip it
ftsWords = ArrayUtil.splice(ftsWords, 0, 1); ftsWords = ArrayUtil.splice(ftsWords, 0, 1);
@@ -95,19 +95,38 @@ public class HSQLBuilder
_ftsCondition.accept(this); _ftsCondition.accept(this);
} }
@Override @Override public void visit (FullText.Rank rank)
public void visit (BinaryOperator binaryOperator)
{ {
// HSQL doesn't handle & and | operators // not implemented for HSQL
if (binaryOperator instanceof BitAnd) { _builder.append("0");
_builder.append("BITAND(?, ?)"); }
} else if (binaryOperator instanceof BitOr) { @Override
_builder.append("BITOR(?, ?)"); public void visit (MultiOperator operator)
{
String op;
// HSQL doesn't handle & and | operators
if (operator instanceof BitAnd) {
op = "bitand";
} else if (operator instanceof BitOr) {
op = "bitor";
} else { } else {
super.visit(binaryOperator); super.visit(operator);
return;
} }
_builder.append(op).append("(");
boolean virgin = true;
for (SQLExpression bit: operator.getConditions()) {
if (!virgin) {
_builder.append(", ");
}
_builder.append("?");
virgin = false;
}
_builder.append(")");
} }
public void visit (EpochSeconds epochSeconds) public void visit (EpochSeconds epochSeconds)
@@ -146,7 +165,7 @@ public class HSQLBuilder
super(types, conn, stmt); super(types, conn, stmt);
} }
@Override public void visit (FullTextMatch match) { @Override public void visit (FullText.Match match) {
_ftsCondition.accept(this); _ftsCondition.accept(this);
_ftsCondition = null; _ftsCondition = null;
} }
@@ -41,7 +41,7 @@ import com.samskivert.depot.clause.OrderBy.Order;
import com.samskivert.depot.expression.ColumnExp; import com.samskivert.depot.expression.ColumnExp;
import com.samskivert.depot.expression.EpochSeconds; import com.samskivert.depot.expression.EpochSeconds;
import com.samskivert.depot.expression.SQLExpression; import com.samskivert.depot.expression.SQLExpression;
import com.samskivert.depot.operator.Conditionals.FullTextMatch; import com.samskivert.depot.operator.Conditionals.FullText;
import com.samskivert.depot.impl.FieldMarshaller.BooleanMarshaller; import com.samskivert.depot.impl.FieldMarshaller.BooleanMarshaller;
import com.samskivert.depot.impl.FieldMarshaller.ByteArrayMarshaller; import com.samskivert.depot.impl.FieldMarshaller.ByteArrayMarshaller;
@@ -65,19 +65,14 @@ public class MySQLBuilder
{ {
public class MSBuildVisitor extends BuildVisitor public class MSBuildVisitor extends BuildVisitor
{ {
@Override public void visit (FullTextMatch match) @Override public void visit (FullText.Match match)
{ {
_builder.append("match("); renderMatch(match.getDefinition());
Class<? extends PersistentRecord> pClass = match.getPersistentClass(); }
String[] fields =
_types.getMarshaller(pClass).getFullTextIndex(match.getName()).fields(); @Override public void visit (FullText.Rank rank)
for (int ii = 0; ii < fields.length; ii ++) { {
if (ii > 0) { renderMatch(rank.getDefinition());
_builder.append(", ");
}
new ColumnExp(pClass, fields[ii]).accept(this);
}
_builder.append(") against (? in boolean mode)");
} }
@Override public void visit (DeleteClause deleteClause) @Override public void visit (DeleteClause deleteClause)
@@ -146,6 +141,21 @@ public class MySQLBuilder
{ {
_builder.append(field); _builder.append(field);
} }
protected void renderMatch (FullText fullText)
{
_builder.append("match(");
Class<? extends PersistentRecord> pClass = fullText.getPersistentClass();
String[] fields = _types.getMarshaller(pClass).getFullTextIndex(
fullText.getName()).fields();
for (int ii = 0; ii < fields.length; ii ++) {
if (ii > 0) {
_builder.append(", ");
}
new ColumnExp(pClass, fields[ii]).accept(this);
}
_builder.append(") against (? in boolean mode)");
}
} }
public class MSBindVisitor extends BindVisitor public class MSBindVisitor extends BindVisitor
@@ -154,12 +164,22 @@ public class MySQLBuilder
super(types, conn, stmt); super(types, conn, stmt);
} }
@Override public void visit (FullTextMatch match) { @Override public void visit (FullText.Match match) {
bindMatch(match.getDefinition());
}
@Override public void visit (FullText.Rank rank) {
bindMatch(rank.getDefinition());
}
protected void bindMatch (FullText fullText)
{
try { try {
_stmt.setString(_argIdx++, match.getQuery()); _stmt.setString(_argIdx++, fullText.getQuery());
} catch (SQLException sqe) { } catch (SQLException sqe) {
throw new DatabaseException("Failed to configure full-text match column " + throw new DatabaseException(
"[idx=" + (_argIdx-1) + ", match=" + match + "]", sqe); "Failed to configure full-text match column [idx=" + (_argIdx-1) +
", match=" + fullText + "]", sqe);
} }
} }
} }
@@ -41,7 +41,7 @@ import com.samskivert.depot.DatabaseException;
import com.samskivert.depot.PersistentRecord; import com.samskivert.depot.PersistentRecord;
import com.samskivert.depot.annotation.FullTextIndex; import com.samskivert.depot.annotation.FullTextIndex;
import com.samskivert.depot.expression.EpochSeconds; import com.samskivert.depot.expression.EpochSeconds;
import com.samskivert.depot.operator.Conditionals.FullTextMatch; import com.samskivert.depot.operator.Conditionals.FullText;
import static com.samskivert.Log.log; import static com.samskivert.Log.log;
@@ -50,9 +50,15 @@ public class PostgreSQLBuilder
{ {
public class PGBuildVisitor extends BuildVisitor public class PGBuildVisitor extends BuildVisitor
{ {
@Override public void visit (FullTextMatch match) { @Override public void visit (FullText.Match match) {
appendIdentifier("ftsCol_" + match.getName()); appendIdentifier("ftsCol_" + match.getDefinition().getName());
_builder.append(" @@ TO_TSQUERY('default', ?)"); _builder.append(" @@ to_tsquery('default', ?)");
}
@Override public void visit (FullText.Rank rank) {
_builder.append("rank(");
appendIdentifier("ftsCol_" + rank.getDefinition().getName());
_builder.append(", to_tsquery('default', ?), 32)");
} }
@Override public void visit (EpochSeconds epochSeconds) { @Override public void visit (EpochSeconds epochSeconds) {
@@ -78,7 +84,28 @@ public class PostgreSQLBuilder
public class PGBindVisitor extends BindVisitor public class PGBindVisitor extends BindVisitor
{ {
@Override public void visit (FullTextMatch match) { @Override public void visit (FullText.Rank rank) {
String query = massageQuery(rank.getDefinition());
try {
_stmt.setString(_argIdx++, query);
} catch (SQLException sqe) {
throw new DatabaseException("Failed to configure full-text match column " +
"[idx=" + (_argIdx-1) + ", query=" + query + "]", sqe);
}
}
@Override public void visit (FullText.Match match) {
String query = massageQuery(match.getDefinition());
try {
_stmt.setString(_argIdx++, query);
} catch (SQLException sqe) {
throw new DatabaseException("Failed to configure full-text match column " +
"[idx=" + (_argIdx-1) + ", query=" + query + "]", sqe);
}
}
protected String massageQuery (FullText match)
{
// The tsearch2 engine takes queries on the form // The tsearch2 engine takes queries on the form
// (foo&bar)|goop // (foo&bar)|goop
// so in this first simple implementation, we just take the user query, chop it into // so in this first simple implementation, we just take the user query, chop it into
@@ -88,13 +115,7 @@ public class PostgreSQLBuilder
if (searchTerms.length > 0 && searchTerms[0].length() == 0) { if (searchTerms.length > 0 && searchTerms[0].length() == 0) {
searchTerms = ArrayUtil.splice(searchTerms, 0, 1); searchTerms = ArrayUtil.splice(searchTerms, 0, 1);
} }
String query = StringUtil.join(searchTerms, "|"); return StringUtil.join(searchTerms, "|");
try {
_stmt.setString(_argIdx++, query);
} catch (SQLException sqe) {
throw new DatabaseException("Failed to configure full-text match column " +
"[idx=" + (_argIdx-1) + ", query=" + query + "]", sqe);
}
} }
// TODO: enable when we can require 1.6 support // TODO: enable when we can require 1.6 support
@@ -21,7 +21,8 @@
package com.samskivert.depot.operator; package com.samskivert.depot.operator;
import com.samskivert.depot.expression.SQLExpression; import com.samskivert.depot.expression.SQLExpression;
import com.samskivert.depot.operator.SQLOperator.BinaryOperator; import com.samskivert.depot.expression.ValueExp;
import com.samskivert.depot.operator.SQLOperator.MultiOperator;
/** /**
* A convenient container for implementations of arithmetic operators. Classes that value brevity * A convenient container for implementations of arithmetic operators. Classes that value brevity
@@ -30,16 +31,16 @@ import com.samskivert.depot.operator.SQLOperator.BinaryOperator;
public abstract class Arithmetic public abstract class Arithmetic
{ {
/** The SQL '+' operator. */ /** The SQL '+' operator. */
public static class Add extends BinaryOperator public static class Add extends MultiOperator
{ {
public Add (SQLExpression column, Comparable<?> value) public Add (SQLExpression column, Comparable<?> value)
{ {
super(column, value); super(column, new ValueExp(value));
} }
public Add (SQLExpression column, SQLExpression value) public Add (SQLExpression... values)
{ {
super(column, value); super(values);
} }
@Override public String operator() @Override public String operator()
@@ -49,16 +50,16 @@ public abstract class Arithmetic
} }
/** The SQL '-' operator. */ /** The SQL '-' operator. */
public static class Sub extends BinaryOperator public static class Sub extends MultiOperator
{ {
public Sub (SQLExpression column, Comparable<?> value) public Sub (SQLExpression column, Comparable<?> value)
{ {
super(column, value); super(column, new ValueExp(value));
} }
public Sub (SQLExpression column, SQLExpression value) public Sub (SQLExpression... values)
{ {
super(column, value); super(values);
} }
@Override public String operator() @Override public String operator()
@@ -68,16 +69,16 @@ public abstract class Arithmetic
} }
/** The SQL '*' operator. */ /** The SQL '*' operator. */
public static class Mul extends BinaryOperator public static class Mul extends MultiOperator
{ {
public Mul (SQLExpression column, Comparable<?> value) public Mul (SQLExpression column, Comparable<?> value)
{ {
super(column, value); super(column, new ValueExp(value));
} }
public Mul (SQLExpression column, SQLExpression value) public Mul (SQLExpression... values)
{ {
super(column, value); super(values);
} }
@Override public String operator() @Override public String operator()
@@ -87,16 +88,16 @@ public abstract class Arithmetic
} }
/** The SQL '/' operator. */ /** The SQL '/' operator. */
public static class Div extends BinaryOperator public static class Div extends MultiOperator
{ {
public Div (SQLExpression column, Comparable<?> value) public Div (SQLExpression column, Comparable<?> value)
{ {
super(column, value); super(column, new ValueExp(value));
} }
public Div (SQLExpression column, SQLExpression value) public Div (SQLExpression... values)
{ {
super(column, value); super(values);
} }
@Override public String operator() @Override public String operator()
@@ -106,16 +107,16 @@ public abstract class Arithmetic
} }
/** The SQL '&' operator. */ /** The SQL '&' operator. */
public static class BitAnd extends BinaryOperator public static class BitAnd extends MultiOperator
{ {
public BitAnd (SQLExpression column, Comparable<?> value) public BitAnd (SQLExpression column, Comparable<?> value)
{ {
super(column, value); super(column, new ValueExp(value));
} }
public BitAnd (SQLExpression column, SQLExpression value) public BitAnd (SQLExpression... values)
{ {
super(column, value); super(values);
} }
@Override public String operator() @Override public String operator()
@@ -125,16 +126,16 @@ public abstract class Arithmetic
} }
/** The SQL '|' operator. */ /** The SQL '|' operator. */
public static class BitOr extends BinaryOperator public static class BitOr extends MultiOperator
{ {
public BitOr (SQLExpression column, Comparable<?> value) public BitOr (SQLExpression column, Comparable<?> value)
{ {
super(column, value); super(column, new ValueExp(value));
} }
public BitOr (SQLExpression column, SQLExpression value) public BitOr (SQLExpression... values)
{ {
super(column, value); super(values);
} }
@Override public String operator() @Override public String operator()
@@ -21,12 +21,15 @@
package com.samskivert.depot.operator; package com.samskivert.depot.operator;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import com.google.common.collect.Lists;
import com.samskivert.depot.PersistentRecord; import com.samskivert.depot.PersistentRecord;
import com.samskivert.depot.clause.SelectClause; import com.samskivert.depot.clause.SelectClause;
import com.samskivert.depot.expression.ColumnExp; import com.samskivert.depot.expression.ColumnExp;
import com.samskivert.depot.expression.SQLExpression; import com.samskivert.depot.expression.SQLExpression;
import com.samskivert.depot.impl.ExpressionVisitor; import com.samskivert.depot.impl.ExpressionVisitor;
import com.samskivert.util.Tuple;
/** /**
* A convenient container for implementations of conditional operators. Classes that value brevity * A convenient container for implementations of conditional operators. Classes that value brevity
@@ -67,7 +70,7 @@ public abstract class Conditionals
protected ColumnExp _column; protected ColumnExp _column;
} }
/** The SQL '=' operator. */ /** The SQL '=' operator. */
public static class Equals extends SQLOperator.BinaryOperator public static class Equals extends SQLOperator.BinaryOperator
{ {
@@ -270,11 +273,13 @@ public abstract class Conditionals
_clause = clause; _clause = clause;
} }
// from SQLExpression
public void accept (ExpressionVisitor builder) public void accept (ExpressionVisitor builder)
{ {
builder.visit(this); builder.visit(this);
} }
// from SQLExpression
public void addClasses (Collection<Class<? extends PersistentRecord>> classSet) public void addClasses (Collection<Class<? extends PersistentRecord>> classSet)
{ {
_clause.addClasses(classSet); _clause.addClasses(classSet);
@@ -293,21 +298,143 @@ public abstract class Conditionals
protected SelectClause<T> _clause; protected SelectClause<T> _clause;
} }
public static class Case implements SQLOperator
{
public Case (SQLExpression... exps)
{
int i = 0;
while (i+1 < exps.length) {
_whenExps.add(Tuple.newTuple(exps[i], exps[i+1]));
i += 2;
}
_elseExp = (i < exps.length) ? exps[i] : null;
}
// from SQLExpression
public void accept (ExpressionVisitor builder)
{
builder.visit(this);
}
// from SQLExpression
public void addClasses (Collection<Class<? extends PersistentRecord>> classSet)
{
for (Tuple<SQLExpression, SQLExpression> tuple : _whenExps) {
tuple.left.addClasses(classSet);
tuple.right.addClasses(classSet);
}
if (_elseExp != null) {
_elseExp.addClasses(classSet);
}
}
public List<Tuple<SQLExpression, SQLExpression>> getWhenExps ()
{
return _whenExps;
}
public SQLExpression getElseExp ()
{
return _elseExp;
}
@Override // from Object
public String toString ()
{
StringBuilder builder = new StringBuilder();
builder.append("Case(");
for (Tuple<SQLExpression, SQLExpression> tuple : _whenExps) {
builder.append(tuple.left.toString()).append("->");
builder.append(tuple.right.toString()).append(",");
}
if (_elseExp != null) {
builder.append(_elseExp.toString()).append(")");
}
return builder.toString();
}
protected List<Tuple<SQLExpression, SQLExpression>> _whenExps = Lists.newArrayList();
protected SQLExpression _elseExp;
}
/** /**
* An attempt at a dialect-agnostic full-text search condition, such as MySQL's MATCH() and * An attempt at a dialect-agnostic full-text search condition, such as MySQL's MATCH() and
* PostgreSQL's @@ TO_TSQUERY(...) abilities. * PostgreSQL's @@ TO_TSQUERY(...) abilities.
*/ */
public static class FullTextMatch public static class FullText
implements SQLOperator
{ {
public FullTextMatch (Class<? extends PersistentRecord> pClass, String name, String query) public class Rank
implements SQLOperator
{
// from SQLExpression
public void accept (ExpressionVisitor builder)
{
builder.visit(this);
}
// from SQLExpression
public void addClasses (Collection<Class<? extends PersistentRecord>> classSet)
{
}
@Override // from Object
public String toString ()
{
return FullText.this.toString("Rank");
}
public FullText getDefinition ()
{
return FullText.this;
}
}
public class Match
implements SQLOperator
{
// from SQLExpression
public void accept (ExpressionVisitor builder)
{
builder.visit(this);
}
public FullText getDefinition ()
{
return FullText.this;
}
// from SQLExpression
public void addClasses (Collection<Class<? extends PersistentRecord>> classSet)
{
}
@Override // from Object
public String toString ()
{
return FullText.this.toString("Match");
}
}
public FullText (Class<? extends PersistentRecord> pClass, String name, String query)
{ {
_pClass = pClass; _pClass = pClass;
_name = name; _name = name;
_query = query; _query = query;
} }
public SQLOperator match ()
{
return new Match();
}
public SQLOperator rank ()
{
return new Rank();
}
public Class<? extends PersistentRecord> getPersistentClass () public Class<? extends PersistentRecord> getPersistentClass ()
{ {
return _pClass; return _pClass;
@@ -323,23 +450,11 @@ public abstract class Conditionals
return _name; return _name;
} }
// from SQLExpression protected String toString (String subType)
public void accept (ExpressionVisitor builder)
{ {
builder.visit(this); return "FullText." + subType + "(" + _name + "=" + _query + ")";
} }
// from SQLExpression
public void addClasses (Collection<Class<? extends PersistentRecord>> classSet)
{
}
@Override // from Object
public String toString ()
{
return "FullText(" + _name + "=" + _query + ")";
}
protected Class<? extends PersistentRecord> _pClass; protected Class<? extends PersistentRecord> _pClass;
protected String _name; protected String _name;
protected String _query; protected String _query;