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.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;
|
||||||
|
|||||||
Reference in New Issue
Block a user