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:
@@ -55,8 +55,9 @@ import com.samskivert.depot.expression.LiteralExp;
|
||||
import com.samskivert.depot.expression.SQLExpression;
|
||||
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.FullTextMatch;
|
||||
import com.samskivert.depot.operator.Conditionals.FullText;
|
||||
import com.samskivert.depot.operator.Conditionals.In;
|
||||
import com.samskivert.depot.operator.Conditionals.IsNull;
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// no arguments
|
||||
|
||||
@@ -50,8 +50,9 @@ import com.samskivert.depot.expression.FunctionExp;
|
||||
import com.samskivert.depot.expression.LiteralExp;
|
||||
import com.samskivert.depot.expression.SQLExpression;
|
||||
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.FullTextMatch;
|
||||
import com.samskivert.depot.operator.Conditionals.FullText;
|
||||
import com.samskivert.depot.operator.Conditionals.In;
|
||||
import com.samskivert.depot.operator.Conditionals.IsNull;
|
||||
import com.samskivert.depot.operator.Logic.Not;
|
||||
@@ -216,7 +217,24 @@ public abstract class BuildVisitor implements ExpressionVisitor
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -41,10 +41,11 @@ import com.samskivert.depot.expression.FunctionExp;
|
||||
import com.samskivert.depot.expression.LiteralExp;
|
||||
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.FullText;
|
||||
import com.samskivert.depot.operator.Conditionals.In;
|
||||
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.SQLOperator.BinaryOperator;
|
||||
import com.samskivert.depot.operator.SQLOperator.MultiOperator;
|
||||
@@ -67,7 +68,8 @@ public interface ExpressionVisitor
|
||||
public void visit (BinaryOperator binaryOperator);
|
||||
public void visit (IsNull isNull);
|
||||
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 (Not not);
|
||||
public void visit (GroupBy groupBy);
|
||||
@@ -87,4 +89,5 @@ public interface ExpressionVisitor
|
||||
public void visit (InsertClause insertClause);
|
||||
public void visit (CreateIndexClause createIndexClause);
|
||||
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.operator.Arithmetic.BitAnd;
|
||||
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.Logic.Or;
|
||||
import com.samskivert.depot.operator.SQLOperator.BinaryOperator;
|
||||
import com.samskivert.depot.operator.SQLOperator.MultiOperator;
|
||||
|
||||
import com.samskivert.depot.impl.clause.CreateIndexClause;
|
||||
|
||||
@@ -62,20 +62,20 @@ public class HSQLBuilder
|
||||
{
|
||||
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
|
||||
// (lower(COL1) like '%foo%') OR (lower(COL1) like '%bar%') OR ...
|
||||
// (lower(COL2) like '%foo%') OR (lower(COL2) like '%bar%') OR ...
|
||||
// ... 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
|
||||
String[] fields = _types.getMarshaller(pClass).
|
||||
getFullTextIndex(match.getName()).fields();
|
||||
getFullTextIndex(match.getDefinition().getName()).fields();
|
||||
|
||||
// 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 the query led with whitespace, the first 'word' will be empty; strip it
|
||||
ftsWords = ArrayUtil.splice(ftsWords, 0, 1);
|
||||
@@ -95,19 +95,38 @@ public class HSQLBuilder
|
||||
_ftsCondition.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit (BinaryOperator binaryOperator)
|
||||
@Override public void visit (FullText.Rank rank)
|
||||
{
|
||||
// HSQL doesn't handle & and | operators
|
||||
if (binaryOperator instanceof BitAnd) {
|
||||
_builder.append("BITAND(?, ?)");
|
||||
// not implemented for HSQL
|
||||
_builder.append("0");
|
||||
}
|
||||
|
||||
} else if (binaryOperator instanceof BitOr) {
|
||||
_builder.append("BITOR(?, ?)");
|
||||
@Override
|
||||
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 {
|
||||
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)
|
||||
@@ -146,7 +165,7 @@ public class HSQLBuilder
|
||||
super(types, conn, stmt);
|
||||
}
|
||||
|
||||
@Override public void visit (FullTextMatch match) {
|
||||
@Override public void visit (FullText.Match match) {
|
||||
_ftsCondition.accept(this);
|
||||
_ftsCondition = null;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ import com.samskivert.depot.clause.OrderBy.Order;
|
||||
import com.samskivert.depot.expression.ColumnExp;
|
||||
import com.samskivert.depot.expression.EpochSeconds;
|
||||
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.ByteArrayMarshaller;
|
||||
@@ -65,19 +65,14 @@ public class MySQLBuilder
|
||||
{
|
||||
public class MSBuildVisitor extends BuildVisitor
|
||||
{
|
||||
@Override public void visit (FullTextMatch match)
|
||||
@Override public void visit (FullText.Match match)
|
||||
{
|
||||
_builder.append("match(");
|
||||
Class<? extends PersistentRecord> pClass = match.getPersistentClass();
|
||||
String[] fields =
|
||||
_types.getMarshaller(pClass).getFullTextIndex(match.getName()).fields();
|
||||
for (int ii = 0; ii < fields.length; ii ++) {
|
||||
if (ii > 0) {
|
||||
_builder.append(", ");
|
||||
renderMatch(match.getDefinition());
|
||||
}
|
||||
new ColumnExp(pClass, fields[ii]).accept(this);
|
||||
}
|
||||
_builder.append(") against (? in boolean mode)");
|
||||
|
||||
@Override public void visit (FullText.Rank rank)
|
||||
{
|
||||
renderMatch(rank.getDefinition());
|
||||
}
|
||||
|
||||
@Override public void visit (DeleteClause deleteClause)
|
||||
@@ -146,6 +141,21 @@ public class MySQLBuilder
|
||||
{
|
||||
_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
|
||||
@@ -154,12 +164,22 @@ public class MySQLBuilder
|
||||
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 {
|
||||
_stmt.setString(_argIdx++, match.getQuery());
|
||||
_stmt.setString(_argIdx++, fullText.getQuery());
|
||||
} catch (SQLException sqe) {
|
||||
throw new DatabaseException("Failed to configure full-text match column " +
|
||||
"[idx=" + (_argIdx-1) + ", match=" + match + "]", sqe);
|
||||
throw new DatabaseException(
|
||||
"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.annotation.FullTextIndex;
|
||||
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;
|
||||
|
||||
@@ -50,9 +50,15 @@ public class PostgreSQLBuilder
|
||||
{
|
||||
public class PGBuildVisitor extends BuildVisitor
|
||||
{
|
||||
@Override public void visit (FullTextMatch match) {
|
||||
appendIdentifier("ftsCol_" + match.getName());
|
||||
_builder.append(" @@ TO_TSQUERY('default', ?)");
|
||||
@Override public void visit (FullText.Match match) {
|
||||
appendIdentifier("ftsCol_" + match.getDefinition().getName());
|
||||
_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) {
|
||||
@@ -78,7 +84,28 @@ public class PostgreSQLBuilder
|
||||
|
||||
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
|
||||
// (foo&bar)|goop
|
||||
// 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) {
|
||||
searchTerms = ArrayUtil.splice(searchTerms, 0, 1);
|
||||
}
|
||||
String query = 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);
|
||||
}
|
||||
return StringUtil.join(searchTerms, "|");
|
||||
}
|
||||
|
||||
// TODO: enable when we can require 1.6 support
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
package com.samskivert.depot.operator;
|
||||
|
||||
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
|
||||
@@ -30,16 +31,16 @@ import com.samskivert.depot.operator.SQLOperator.BinaryOperator;
|
||||
public abstract class Arithmetic
|
||||
{
|
||||
/** The SQL '+' operator. */
|
||||
public static class Add extends BinaryOperator
|
||||
public static class Add extends MultiOperator
|
||||
{
|
||||
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()
|
||||
@@ -49,16 +50,16 @@ public abstract class Arithmetic
|
||||
}
|
||||
|
||||
/** The SQL '-' operator. */
|
||||
public static class Sub extends BinaryOperator
|
||||
public static class Sub extends MultiOperator
|
||||
{
|
||||
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()
|
||||
@@ -68,16 +69,16 @@ public abstract class Arithmetic
|
||||
}
|
||||
|
||||
/** The SQL '*' operator. */
|
||||
public static class Mul extends BinaryOperator
|
||||
public static class Mul extends MultiOperator
|
||||
{
|
||||
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()
|
||||
@@ -87,16 +88,16 @@ public abstract class Arithmetic
|
||||
}
|
||||
|
||||
/** The SQL '/' operator. */
|
||||
public static class Div extends BinaryOperator
|
||||
public static class Div extends MultiOperator
|
||||
{
|
||||
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()
|
||||
@@ -106,16 +107,16 @@ public abstract class Arithmetic
|
||||
}
|
||||
|
||||
/** The SQL '&' operator. */
|
||||
public static class BitAnd extends BinaryOperator
|
||||
public static class BitAnd extends MultiOperator
|
||||
{
|
||||
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()
|
||||
@@ -125,16 +126,16 @@ public abstract class Arithmetic
|
||||
}
|
||||
|
||||
/** The SQL '|' operator. */
|
||||
public static class BitOr extends BinaryOperator
|
||||
public static class BitOr extends MultiOperator
|
||||
{
|
||||
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()
|
||||
|
||||
@@ -21,12 +21,15 @@
|
||||
package com.samskivert.depot.operator;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.samskivert.depot.PersistentRecord;
|
||||
import com.samskivert.depot.clause.SelectClause;
|
||||
import com.samskivert.depot.expression.ColumnExp;
|
||||
import com.samskivert.depot.expression.SQLExpression;
|
||||
import com.samskivert.depot.impl.ExpressionVisitor;
|
||||
import com.samskivert.util.Tuple;
|
||||
|
||||
/**
|
||||
* A convenient container for implementations of conditional operators. Classes that value brevity
|
||||
@@ -270,11 +273,13 @@ public abstract class Conditionals
|
||||
_clause = clause;
|
||||
}
|
||||
|
||||
// from SQLExpression
|
||||
public void accept (ExpressionVisitor builder)
|
||||
{
|
||||
builder.visit(this);
|
||||
}
|
||||
|
||||
// from SQLExpression
|
||||
public void addClasses (Collection<Class<? extends PersistentRecord>> classSet)
|
||||
{
|
||||
_clause.addClasses(classSet);
|
||||
@@ -294,20 +299,142 @@ public abstract class Conditionals
|
||||
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
|
||||
* PostgreSQL's @@ TO_TSQUERY(...) abilities.
|
||||
*/
|
||||
public static class FullTextMatch
|
||||
public static class FullText
|
||||
{
|
||||
public class Rank
|
||||
implements SQLOperator
|
||||
{
|
||||
public FullTextMatch (Class<? extends PersistentRecord> pClass, String name, String query)
|
||||
// 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;
|
||||
_name = name;
|
||||
_query = query;
|
||||
}
|
||||
|
||||
public SQLOperator match ()
|
||||
{
|
||||
return new Match();
|
||||
}
|
||||
|
||||
public SQLOperator rank ()
|
||||
{
|
||||
return new Rank();
|
||||
}
|
||||
|
||||
public Class<? extends PersistentRecord> getPersistentClass ()
|
||||
{
|
||||
return _pClass;
|
||||
@@ -323,21 +450,9 @@ public abstract class Conditionals
|
||||
return _name;
|
||||
}
|
||||
|
||||
// from SQLExpression
|
||||
public void accept (ExpressionVisitor builder)
|
||||
protected String toString (String subType)
|
||||
{
|
||||
builder.visit(this);
|
||||
}
|
||||
|
||||
// from SQLExpression
|
||||
public void addClasses (Collection<Class<? extends PersistentRecord>> classSet)
|
||||
{
|
||||
}
|
||||
|
||||
@Override // from Object
|
||||
public String toString ()
|
||||
{
|
||||
return "FullText(" + _name + "=" + _query + ")";
|
||||
return "FullText." + subType + "(" + _name + "=" + _query + ")";
|
||||
}
|
||||
|
||||
protected Class<? extends PersistentRecord> _pClass;
|
||||
|
||||
Reference in New Issue
Block a user