Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.Objects;
import org.seasar.doma.jdbc.criteria.option.LikeOption;
import org.seasar.doma.jdbc.criteria.tuple.Tuple2;
import org.seasar.doma.jdbc.criteria.tuple.Tuple3;

public interface Criterion {
void accept(Visitor visitor);
Expand Down Expand Up @@ -298,6 +299,72 @@ public void accept(Visitor visitor) {
}
}

class InTuple3 implements Criterion {
public final Tuple3<Operand.Prop, Operand.Prop, Operand.Prop> left;
public final List<Tuple3<Operand.Param, Operand.Param, Operand.Param>> right;

public InTuple3(
Tuple3<Operand.Prop, Operand.Prop, Operand.Prop> left,
List<Tuple3<Operand.Param, Operand.Param, Operand.Param>> right) {
this.left = Objects.requireNonNull(left);
this.right = Objects.requireNonNull(right);
}

@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

class NotInTuple3 implements Criterion {
public final Tuple3<Operand.Prop, Operand.Prop, Operand.Prop> left;
public final List<Tuple3<Operand.Param, Operand.Param, Operand.Param>> right;

public NotInTuple3(
Tuple3<Operand.Prop, Operand.Prop, Operand.Prop> left,
List<Tuple3<Operand.Param, Operand.Param, Operand.Param>> right) {
this.left = Objects.requireNonNull(left);
this.right = Objects.requireNonNull(right);
}

@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

class InTuple3SubQuery implements Criterion {
public final Tuple3<Operand.Prop, Operand.Prop, Operand.Prop> left;
public final SelectContext right;

public InTuple3SubQuery(
Tuple3<Operand.Prop, Operand.Prop, Operand.Prop> left, SelectContext right) {
this.left = Objects.requireNonNull(left);
this.right = Objects.requireNonNull(right);
}

@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

class NotInTuple3SubQuery implements Criterion {
public final Tuple3<Operand.Prop, Operand.Prop, Operand.Prop> left;
public final SelectContext right;

public NotInTuple3SubQuery(
Tuple3<Operand.Prop, Operand.Prop, Operand.Prop> left, SelectContext right) {
this.left = Objects.requireNonNull(left);
this.right = Objects.requireNonNull(right);
}

@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

class Exists implements Criterion {
public final SelectContext context;

Expand Down Expand Up @@ -405,6 +472,14 @@ interface Visitor {

void visit(NotInTuple2SubQuery criterion);

void visit(InTuple3 criterion);

void visit(NotInTuple3 criterion);

void visit(InTuple3SubQuery criterion);

void visit(NotInTuple3SubQuery criterion);

void visit(Exists criterion);

void visit(NotExists criterion);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.seasar.doma.jdbc.criteria.metamodel.PropertyMetamodel;
import org.seasar.doma.jdbc.criteria.option.LikeOption;
import org.seasar.doma.jdbc.criteria.tuple.Tuple2;
import org.seasar.doma.jdbc.criteria.tuple.Tuple3;

public abstract class ComparisonDeclaration {

Expand Down Expand Up @@ -519,6 +520,140 @@ public <PROPERTY1, PROPERTY2> void notIn(
add(new Criterion.NotInTuple2SubQuery(new Tuple2<>(prop1, prop2), right.get()));
}

/**
* Adds a {@code IN} operator.
*
* @param left the left hand operand
* @param right the right hand operand. If this value is null, the query condition doesn't include
* the operator.
* @param <PROPERTY1> the first property type
* @param <PROPERTY2> the second property type
* @param <PROPERTY3> the third property type
* @throws NullPointerException if {@code left} is null
*/
public <PROPERTY1, PROPERTY2, PROPERTY3> void in(
Tuple3<
PropertyMetamodel<PROPERTY1>,
PropertyMetamodel<PROPERTY2>,
PropertyMetamodel<PROPERTY3>>
left,
List<Tuple3<PROPERTY1, PROPERTY2, PROPERTY3>> right) {
Objects.requireNonNull(left);
if (right != null) {
Operand.Prop prop1 = new Operand.Prop(left.getItem1());
Operand.Prop prop2 = new Operand.Prop(left.getItem2());
Operand.Prop prop3 = new Operand.Prop(left.getItem3());
List<Tuple3<Operand.Param, Operand.Param, Operand.Param>> params =
right.stream()
.map(
triple -> {
Operand.Param param1 = new Operand.Param(left.getItem1(), triple.getItem1());
Operand.Param param2 = new Operand.Param(left.getItem2(), triple.getItem2());
Operand.Param param3 = new Operand.Param(left.getItem3(), triple.getItem3());
return new Tuple3<>(param1, param2, param3);
})
.collect(toList());
add(new Criterion.InTuple3(new Tuple3<>(prop1, prop2, prop3), params));
}
}

/**
* Adds a {@code NOT IN} operator.
*
* @param left the left hand operand
* @param right the right hand operand. If this value is null, the query condition doesn't include
* the operator.
* @param <PROPERTY1> the first property type
* @param <PROPERTY2> the second property type
* @param <PROPERTY3> the third property type
* @throws NullPointerException if {@code left} is null
*/
public <PROPERTY1, PROPERTY2, PROPERTY3> void notIn(
Tuple3<
PropertyMetamodel<PROPERTY1>,
PropertyMetamodel<PROPERTY2>,
PropertyMetamodel<PROPERTY3>>
left,
List<Tuple3<PROPERTY1, PROPERTY2, PROPERTY3>> right) {
Objects.requireNonNull(left);
if (right != null) {
Operand.Prop prop1 = new Operand.Prop(left.getItem1());
Operand.Prop prop2 = new Operand.Prop(left.getItem2());
Operand.Prop prop3 = new Operand.Prop(left.getItem3());
List<Tuple3<Operand.Param, Operand.Param, Operand.Param>> params =
right.stream()
.map(
triple -> {
Operand.Param param1 = new Operand.Param(left.getItem1(), triple.getItem1());
Operand.Param param2 = new Operand.Param(left.getItem2(), triple.getItem2());
Operand.Param param3 = new Operand.Param(left.getItem3(), triple.getItem3());
return new Tuple3<>(param1, param2, param3);
})
.collect(toList());
add(new Criterion.NotInTuple3(new Tuple3<>(prop1, prop2, prop3), params));
}
}

/**
* Adds a {@code IN} operator.
*
* @param left the left hand operand
* @param right the right hand operand
* @param <PROPERTY1> the first property type
* @param <PROPERTY2> the second property type
* @param <PROPERTY3> the third property type
* @throws NullPointerException if {@code left} or {@code right} is null
*/
public <PROPERTY1, PROPERTY2, PROPERTY3> void in(
Tuple3<
PropertyMetamodel<PROPERTY1>,
PropertyMetamodel<PROPERTY2>,
PropertyMetamodel<PROPERTY3>>
left,
SubSelectContext<
Tuple3<
PropertyMetamodel<PROPERTY1>,
PropertyMetamodel<PROPERTY2>,
PropertyMetamodel<PROPERTY3>>>
right) {
Objects.requireNonNull(left);
Objects.requireNonNull(right);
Operand.Prop prop1 = new Operand.Prop(left.getItem1());
Operand.Prop prop2 = new Operand.Prop(left.getItem2());
Operand.Prop prop3 = new Operand.Prop(left.getItem3());
add(new Criterion.InTuple3SubQuery(new Tuple3<>(prop1, prop2, prop3), right.get()));
}

/**
* Adds a {@code NOT IN} operator.
*
* @param left the left hand operand
* @param right the right hand operand
* @param <PROPERTY1> the first property type
* @param <PROPERTY2> the second property type
* @param <PROPERTY3> the third property type
* @throws NullPointerException if {@code left} or {@code right} is null
*/
public <PROPERTY1, PROPERTY2, PROPERTY3> void notIn(
Tuple3<
PropertyMetamodel<PROPERTY1>,
PropertyMetamodel<PROPERTY2>,
PropertyMetamodel<PROPERTY3>>
left,
SubSelectContext<
Tuple3<
PropertyMetamodel<PROPERTY1>,
PropertyMetamodel<PROPERTY2>,
PropertyMetamodel<PROPERTY3>>>
right) {
Objects.requireNonNull(left);
Objects.requireNonNull(right);
Operand.Prop prop1 = new Operand.Prop(left.getItem1());
Operand.Prop prop2 = new Operand.Prop(left.getItem2());
Operand.Prop prop3 = new Operand.Prop(left.getItem3());
add(new Criterion.NotInTuple3SubQuery(new Tuple3<>(prop1, prop2, prop3), right.get()));
}

/**
* Adds a {@code EXISTS} operator.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.seasar.doma.jdbc.criteria.metamodel.EntityMetamodel;
import org.seasar.doma.jdbc.criteria.metamodel.PropertyMetamodel;
import org.seasar.doma.jdbc.criteria.tuple.Tuple2;
import org.seasar.doma.jdbc.criteria.tuple.Tuple3;

public class SubSelectFromDeclaration<ENTITY> implements SubSelectContext<ENTITY> {

Expand Down Expand Up @@ -84,6 +85,21 @@ SubSelectContext<Tuple2<PropertyMetamodel<PROPERTY1>, PropertyMetamodel<PROPERTY
return () -> context;
}

public <PROPERTY1, PROPERTY2, PROPERTY3>
SubSelectContext<
Tuple3<
PropertyMetamodel<PROPERTY1>,
PropertyMetamodel<PROPERTY2>,
PropertyMetamodel<PROPERTY3>>>
select(
PropertyMetamodel<PROPERTY1> first,
PropertyMetamodel<PROPERTY2> second,
PropertyMetamodel<PROPERTY3> third) {
SelectContext context = declaration.getContext();
context.projection = new Projection.PropertyMetamodels(first, second, third);
return () -> context;
}

public SubSelectContext<List<PropertyMetamodel<?>>> select(
PropertyMetamodel<?> propertyMetamodel1,
PropertyMetamodel<?> propertyMetamodel2,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.seasar.doma.jdbc.criteria.metamodel.PropertyMetamodel;
import org.seasar.doma.jdbc.criteria.option.LikeOption;
import org.seasar.doma.jdbc.criteria.tuple.Tuple2;
import org.seasar.doma.jdbc.criteria.tuple.Tuple3;
import org.seasar.doma.jdbc.entity.EntityPropertyType;
import org.seasar.doma.jdbc.entity.EntityType;
import org.seasar.doma.message.Message;
Expand Down Expand Up @@ -231,6 +232,26 @@ public void visit(Criterion.NotInTuple2SubQuery c) {
inPairSubQuery(c.left, c.right, true);
}

@Override
public void visit(Criterion.InTuple3 c) {
inTriple(c.left, c.right, false);
}

@Override
public void visit(Criterion.NotInTuple3 c) {
inTriple(c.left, c.right, true);
}

@Override
public void visit(Criterion.InTuple3SubQuery c) {
inTripleSubQuery(c.left, c.right, false);
}

@Override
public void visit(Criterion.NotInTuple3SubQuery c) {
inTripleSubQuery(c.left, c.right, true);
}

@Override
public void visit(Criterion.Exists c) {
exists(c.context, false);
Expand Down Expand Up @@ -404,6 +425,58 @@ private void inPairSubQuery(
buf.appendSql(")");
}

private void inTriple(
Tuple3<Operand.Prop, Operand.Prop, Operand.Prop> left,
List<Tuple3<Operand.Param, Operand.Param, Operand.Param>> right,
boolean not) {
buf.appendSql("(");
column(left.getItem1());
buf.appendSql(", ");
column(left.getItem2());
buf.appendSql(", ");
column(left.getItem3());
buf.appendSql(")");
if (not) {
buf.appendSql(" not");
}
buf.appendSql(" in (");
if (right.isEmpty()) {
buf.appendSql("null, null, null");
} else {
right.forEach(
triple -> {
buf.appendSql("(");
param(triple.getItem1());
buf.appendSql(", ");
param(triple.getItem2());
buf.appendSql(", ");
param(triple.getItem3());
buf.appendSql("), ");
});
buf.cutBackSql(2);
}
buf.appendSql(")");
}

private void inTripleSubQuery(
Tuple3<Operand.Prop, Operand.Prop, Operand.Prop> left, SelectContext right, boolean not) {
buf.appendSql("(");
column(left.getItem1());
buf.appendSql(", ");
column(left.getItem2());
buf.appendSql(", ");
column(left.getItem3());
buf.appendSql(")");
if (not) {
buf.appendSql(" not");
}
buf.appendSql(" in (");
AliasManager child = new AliasManager(right, aliasManager);
SelectBuilder builder = new SelectBuilder(config, right, commenter, buf, child);
builder.interpret();
buf.appendSql(")");
}

public void exists(SelectContext context, boolean not) {
if (not) {
buf.appendSql("not ");
Expand Down
Loading