/**
*
* Copyright (c) 2006-2017, Speedment, Inc. All Rights Reserved.
*
* Licensed 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 com.speedment.runtime.core.internal.manager.sql;
import com.speedment.runtime.core.db.FieldPredicateView;
import com.speedment.runtime.core.db.SqlPredicateFragment;
import static com.speedment.runtime.core.internal.manager.sql.AbstractFieldPredicateView.of;
import static com.speedment.runtime.field.internal.predicate.PredicateUtil.getFirstOperandAsRaw;
import static com.speedment.runtime.field.internal.predicate.PredicateUtil.getFirstOperandAsRawSet;
import static com.speedment.runtime.field.internal.predicate.PredicateUtil.getInclusionOperand;
import static com.speedment.runtime.field.internal.predicate.PredicateUtil.getSecondOperand;
import com.speedment.runtime.field.predicate.FieldPredicate;
import com.speedment.runtime.field.predicate.Inclusion;
import java.util.Set;
import static java.util.stream.Collectors.joining;
/**
*
* @author Emil Forslund
*/
@SuppressWarnings("rawtypes")
public final class MySqlSpeedmentPredicateView extends AbstractFieldPredicateView implements FieldPredicateView {
/*
create table colltest (
name character(20)
) charset latin1
insert into colltest (name) values ('olle');
insert into colltest (name) values ('sven');
select * from colltest where name = 'olle' collate utf8_bin;
*/
private enum Collation {
UTF8_BIN, UTF8_GENERAL_CI;
private final String collateCommand;
private Collation() {
this.collateCommand = "COLLATE " + name().toLowerCase();
}
String getCollateCommand() {
return collateCommand;
}
}
@Override
protected SqlPredicateFragment equalIgnoreCaseHelper(String cn, FieldPredicate<?> model, boolean negated) {
return of(compare(cn, " = ?", Collation.UTF8_GENERAL_CI), negated).add(getFirstOperandAsRaw(model));
}
@Override
protected SqlPredicateFragment startsWithHelper(String cn, FieldPredicate<?> model, boolean negated) {
return of("(" + cn + " LIKE BINARY CONCAT(? ,'%'))", negated).add(getFirstOperandAsRaw(model));
// Todo: Use collation like this:
// return of("(" + cn + " " + Collation.UTF8_BIN.getCollateCommand() + " LIKE CONCAT(? ,'%'))", negated).add(getFirstOperandAsRaw(model));
}
@Override
protected SqlPredicateFragment startsWithIgnoreCaseHelper(String cn, FieldPredicate<?> model, boolean negated) {
return of("(LOWER(" + cn + ") LIKE BINARY CONCAT(LOWER(?) ,'%'))", negated).add(getFirstOperandAsRaw(model));
// Todo: Use collation like this:
// return of("(" + cn + " " + Collation.UTF8_GENERAL_CI.getCollateCommand() + " LIKE BINARY CONCAT(? ,'%'))", negated).add(getFirstOperandAsRaw(model));
}
@Override
protected SqlPredicateFragment endsWithHelper(String cn, FieldPredicate<?> model, boolean negated) {
return of("(" + cn + " LIKE BINARY CONCAT('%', ?))", negated).add(getFirstOperandAsRaw(model));
// Todo: Use collation like this:
// return of("(" + cn + " " + Collation.UTF8_BIN.getCollateCommand() + " LIKE CONCAT('%', ?))", negated).add(getFirstOperandAsRaw(model));
}
@Override
protected SqlPredicateFragment endsWithIgnoreCaseHelper(String cn, FieldPredicate<?> model, boolean negated) {
return of("(LOWER(" + cn + ") LIKE BINARY CONCAT('%', LOWER(?)))", negated).add(getFirstOperandAsRaw(model));
// Todo: Use collation like this:
// return of("(" + cn + " " + Collation.UTF8_GENERAL_CI.getCollateCommand() +" LIKE CONCAT('%', ?))", negated).add(getFirstOperandAsRaw(model));
}
@Override
protected SqlPredicateFragment containsHelper(String cn, FieldPredicate<?> model, boolean negated) {
return of("(" + cn + " LIKE BINARY CONCAT('%', ? ,'%'))", negated).add(getFirstOperandAsRaw(model));
// Todo: Use collation like this:
// return of("(" + cn + " " + Collation.UTF8_BIN.getCollateCommand() +" LIKE CONCAT('%', ? ,'%'))", negated).add(getFirstOperandAsRaw(model));
}
@Override
protected SqlPredicateFragment containsIgnoreCaseHelper(String cn, FieldPredicate<?> model, boolean negated) {
return of("(LOWER(" + cn + ") LIKE BINARY CONCAT('%', LOWER(?) ,'%'))", negated).add(getFirstOperandAsRaw(model));
// Todo: Use collation like this:
//return of("(" + cn + " "+Collation.UTF8_GENERAL_CI.getCollateCommand()+" LIKE CONCAT('%', ? ,'%'))", negated).add(getFirstOperandAsRaw(model));
}
@Override
protected SqlPredicateFragment equalString(String cn, FieldPredicate<?> model) {
return of(compare(cn, " = ?", Collation.UTF8_BIN)).add(getFirstOperandAsRaw(model));
}
@Override
protected SqlPredicateFragment notEqualString(String cn, FieldPredicate<?> model) {
return of("(NOT " + compare(cn, " = ?", Collation.UTF8_BIN) + ")").add(getFirstOperandAsRaw(model));
}
@Override
protected SqlPredicateFragment inString(String cn, FieldPredicate<?> model) {
return inStringHelper(cn, model, false);
}
@Override
protected SqlPredicateFragment notInString(String cn, FieldPredicate<?> model) {
return inStringHelper(cn, model, true);
}
private SqlPredicateFragment inStringHelper(String cn, FieldPredicate<?> model, boolean negated) {
final Set<?> set = getFirstOperandAsRawSet(model);
return of("(" + cn + " " + Collation.UTF8_BIN.getCollateCommand() + " IN (" + set.stream().map($ -> "?").collect(joining(",")) + "))", negated).addAll(set);
}
@Override
protected SqlPredicateFragment betweenString(String cn, FieldPredicate<?> model) {
return betweenStringHelper(cn, model, false);
}
@Override
protected SqlPredicateFragment notBetweenString(String cn, FieldPredicate<?> model) {
return betweenStringHelper(cn, model, true);
}
private SqlPredicateFragment betweenStringHelper(String cn, FieldPredicate<?> model, boolean negated) {
final Inclusion inclusion = getInclusionOperand(model);
switch (inclusion) {
case START_EXCLUSIVE_END_EXCLUSIVE: {
return of(
"(" + greaterThanString(cn) + " AND " + lessThanString(cn) + ")",
negated
).add(getFirstOperandAsRaw(model)).add(getSecondOperand(model));
}
case START_INCLUSIVE_END_EXCLUSIVE: {
return of(
"(" + greaterOrEqualString(cn) + " AND " + lessThanString(cn) + ")",
negated
).add(getFirstOperandAsRaw(model)).add(getSecondOperand(model));
}
case START_EXCLUSIVE_END_INCLUSIVE: {
return of(
"(" + greaterThanString(cn) + " AND " + lessOrEqualString(cn) + ")",
negated
).add(getFirstOperandAsRaw(model)).add(getSecondOperand(model));
}
case START_INCLUSIVE_END_INCLUSIVE: {
return of(
"(" + greaterOrEqualString(cn) + " AND " + lessOrEqualString(cn) + ")",
negated
).add(getFirstOperandAsRaw(model)).add(getSecondOperand(model));
}
}
throw new IllegalArgumentException("Unknown Inclusion:" + inclusion);
}
@Override
protected SqlPredicateFragment lessOrEqualString(String cn, FieldPredicate<?> model) {
return of(lessOrEqualString(cn)).add(getFirstOperandAsRaw(model));
}
@Override
protected SqlPredicateFragment lessThanString(String cn, FieldPredicate<?> model) {
return of(lessThanString(cn)).add(getFirstOperandAsRaw(model));
}
@Override
protected SqlPredicateFragment greaterOrEqualString(String cn, FieldPredicate<?> model) {
return of(greaterOrEqualString(cn)).add(getFirstOperandAsRaw(model));
}
@Override
protected SqlPredicateFragment greaterThanString(String cn, FieldPredicate<?> model) {
return of(greaterThanString(cn)).add(getFirstOperandAsRaw(model));
}
private String lessOrEqualString(String cn) {
return compare(cn, "<= ?", Collation.UTF8_BIN);
}
private String lessThanString(String cn) {
return compare(cn, "< ?", Collation.UTF8_BIN);
}
private String greaterOrEqualString(String cn) {
return compare(cn, ">= ?", Collation.UTF8_BIN);
}
private String greaterThanString(String cn) {
return compare(cn, "> ?", Collation.UTF8_BIN);
}
private String compare(String cn, String operator, Collation collation) {
return new StringBuilder()
.append('(')
.append(cn)
.append(' ')
.append(operator)
.append(' ')
.append(collation.getCollateCommand())
.append(')')
.toString();
}
}