[#1202] Add support for the relational division operation: A.divideBy(B).on(A.ID.equal(B.A_ID)).returning(A.X, A.Y, ...)

This commit is contained in:
Lukas Eder 2012-03-03 13:44:12 +00:00
parent e914d2d037
commit 86402653ed
9 changed files with 689 additions and 6 deletions

View File

@ -40,6 +40,7 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.jooq.impl.Factory.avg;
import static org.jooq.impl.Factory.count;
import static org.jooq.impl.Factory.field;
import static org.jooq.impl.Factory.literal;
import static org.jooq.impl.Factory.max;
import static org.jooq.impl.Factory.sum;
@ -49,6 +50,7 @@ import static org.jooq.impl.Factory.val;
import org.jooq.Field;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.Table;
import org.jooq.TableRecord;
import org.jooq.UpdatableRecord;
import org.jooq.test.BaseTest;
@ -208,4 +210,40 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, D, T, U, I, IPK, T658, T725, T639
asList(1, 2, 0, 0, 0),
asList(result3.get(0).into(Integer[].class)));
}
@Test
public void testRelationalDivision() {
// Books and bookstores. There's only one book that is contained in
// every bookstore:
// ----------------------------------------------------------------
int id =
create().select()
.from(TBookToBookStore()
.divideBy(TBookStore())
.on(TBookToBookStore_BOOK_STORE_NAME().equal(TBookStore_NAME()))
.returning(TBookToBookStore_BOOK_ID()))
.fetchOne(0, Integer.class);
assertEquals(3, id);
// Test removing some bookstores in nested selects
Table<?> notAllBookStores =
create().select()
.from(TBookStore())
.where(TBookStore_NAME().notEqual("Buchhandlung im Volkshaus"))
.asTable("not_all_bookstores");
Result<?> result =
create().select()
.from(TBookToBookStore()
.divideBy(notAllBookStores)
.on(TBookToBookStore_BOOK_STORE_NAME().equal(notAllBookStores.getField(TBookStore_NAME())))
.returning(TBookToBookStore_BOOK_ID(), field("'abc'").as("abc")))
.orderBy(1)
.fetch();
assertEquals(asList((Object) 1, "abc"), asList(result.get(0).intoArray()));
assertEquals(asList((Object) 3, "abc"), asList(result.get(1).intoArray()));
}
}

View File

@ -1345,6 +1345,11 @@ public abstract class jOOQAbstractTest<
new ExoticTests(this).testPivotClause();
}
@Test
public void testRelationalDivision() throws Exception {
new ExoticTests(this).testRelationalDivision();
}
@Test
public void testExecuteListenerOnResultQuery() throws Exception {
new ExecuteListenerTests(this).testExecuteListenerOnResultQuery();

View File

@ -0,0 +1,159 @@
/**
* Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com
* All rights reserved.
*
* This software is licensed to you under the Apache License, Version 2.0
* (the "License"); You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* . Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* . Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* . Neither the name "jOOQ" nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.jooq;
import org.jooq.impl.Factory;
/**
* An intermediate type for the construction of a relational division. This type
* can be used as a convenience type for connecting more conditions.
*
* @author Lukas Eder
*/
public interface DivideByOnConditionStep extends DivideByReturningStep {
/**
* Combine the currently assembled conditions with another one using the
* {@link Operator#AND} operator.
*/
@Support
DivideByOnConditionStep and(Condition condition);
/**
* Combine the currently assembled conditions with another one using the
* {@link Operator#AND} operator.
* <p>
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
* guarantee syntax integrity. You may also create the possibility of
* malicious SQL injection. Be sure to properly use bind variables and/or
* escape literals when concatenated into SQL clauses!
*
* @see Factory#condition(String)
*/
@Support
DivideByOnConditionStep and(String sql);
/**
* Combine the currently assembled conditions with another one using the
* {@link Operator#AND} operator.
* <p>
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
* guarantee syntax integrity. You may also create the possibility of
* malicious SQL injection. Be sure to properly use bind variables and/or
* escape literals when concatenated into SQL clauses!
*
* @see Factory#condition(String, Object...)
*/
@Support
DivideByOnConditionStep and(String sql, Object... bindings);
/**
* Combine the currently assembled conditions with a negated other one using
* the {@link Operator#AND} operator.
*/
@Support
DivideByOnConditionStep andNot(Condition condition);
/**
* Combine the currently assembled conditions with an <code>EXISTS</code>
* clause using the {@link Operator#AND} operator.
*/
@Support
DivideByOnConditionStep andExists(Select<?> select);
/**
* Combine the currently assembled conditions with a <code>NOT EXISTS</code>
* clause using the {@link Operator#AND} operator.
*/
@Support
DivideByOnConditionStep andNotExists(Select<?> select);
/**
* Combine the currently assembled conditions with another one using the
* {@link Operator#OR} operator.
*/
@Support
DivideByOnConditionStep or(Condition condition);
/**
* Combine the currently assembled conditions with another one using the
* {@link Operator#OR} operator.
* <p>
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
* guarantee syntax integrity. You may also create the possibility of
* malicious SQL injection. Be sure to properly use bind variables and/or
* escape literals when concatenated into SQL clauses!
*
* @see Factory#condition(String)
*/
@Support
DivideByOnConditionStep or(String sql);
/**
* Combine the currently assembled conditions with another one using the
* {@link Operator#OR} operator.
* <p>
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
* guarantee syntax integrity. You may also create the possibility of
* malicious SQL injection. Be sure to properly use bind variables and/or
* escape literals when concatenated into SQL clauses!
*
* @see Factory#condition(String, Object...)
*/
@Support
DivideByOnConditionStep or(String sql, Object... bindings);
/**
* Combine the currently assembled conditions with a negated other one using
* the {@link Operator#OR} operator.
*/
@Support
DivideByOnConditionStep orNot(Condition condition);
/**
* Combine the currently assembled conditions with an <code>EXISTS</code>
* clause using the {@link Operator#OR} operator.
*/
@Support
DivideByOnConditionStep orExists(Select<?> select);
/**
* Combine the currently assembled conditions with a <code>NOT EXISTS</code>
* clause using the {@link Operator#OR} operator.
*/
@Support
DivideByOnConditionStep orNotExists(Select<?> select);
}

View File

@ -0,0 +1,78 @@
/**
* Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com
* All rights reserved.
*
* This software is licensed to you under the Apache License, Version 2.0
* (the "License"); You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* . Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* . Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* . Neither the name "jOOQ" nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.jooq;
import org.jooq.impl.Factory;
/**
* An intermediate type for the construction of a relational division
*
* @author Lukas Eder
*/
public interface DivideByOnStep {
/**
* Add a division condition to the <code>DIVIDE BY</code> clause
*/
@Support
DivideByOnConditionStep on(Condition... conditions);
/**
* Add a division condition to the <code>DIVIDE BY</code> clause
* <p>
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
* guarantee syntax integrity. You may also create the possibility of
* malicious SQL injection. Be sure to properly use bind variables and/or
* escape literals when concatenated into SQL clauses!
*
* @see Factory#condition(String)
*/
@Support
DivideByOnConditionStep on(String sql);
/**
* Add a division condition to the <code>DIVIDE BY</code> clause
* <p>
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
* guarantee syntax integrity. You may also create the possibility of
* malicious SQL injection. Be sure to properly use bind variables and/or
* escape literals when concatenated into SQL clauses!
*
* @see Factory#condition(String, Object...)
*/
@Support
DivideByOnConditionStep on(String sql, Object... bindings);
}

View File

@ -0,0 +1,58 @@
/**
* Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com
* All rights reserved.
*
* This software is licensed to you under the Apache License, Version 2.0
* (the "License"); You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* . Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* . Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* . Neither the name "jOOQ" nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.jooq;
import java.util.Collection;
/**
* An intermediate type for the construction of a relational division
*
* @author Lukas Eder
*/
public interface DivideByReturningStep {
/**
* Specify the fields that you want the division to return from the dividend
*/
@Support
Table<Record> returning(Field<?>... fields);
/**
* Specify the fields that you want the division to return from the dividend
*/
@Support
Table<Record> returning(Collection<? extends Field<?>> fields);
}

View File

@ -132,6 +132,55 @@ public interface Table<R extends Record> extends Type<R>, AliasProvider<Table<R>
@Support({ ORACLE })
PivotForStep pivot(Collection<? extends Field<?>> aggregateFunctions);
/**
* Create a new <code>TABLE</code> reference from this table, applying
* relational division.
* <p>
* Relational division is the inverse of a cross join operation. The
* following is an approximate definition of a relational division:
* <code><pre>
* Assume the following cross join / cartesian product
* C = A × B
*
* Then it can be said that
* A = C ÷ B
* B = C ÷ A
* </pre></code>
* <p>
* With jOOQ, you can simplify using relational divisions by using the
* following syntax: <code><pre>
* C.divideBy(B).on(C.ID.equal(B.C_ID)).returning(C.TEXT)
* </pre></code>
* <p>
* The above roughly translates to <code><pre>
* SELECT DISTINCT C.TEXT FROM C "c1"
* WHERE NOT EXISTS (
* SELECT 1 FROM B
* WHERE NOT EXISTS (
* SELECT 1 FROM C "c2"
* WHERE "c2".TEXT = "c1".TEXT
* AND "c2".ID = B.C_ID
* )
* )
* </pre></code>
* <p>
* Or in plain text: Find those TEXT values in C whose ID's correspond to
* all ID's in B.
* <p>
* For more information about relational division and some nice, real-life
* examples, see
* <ul>
* <li><a
* href="http://en.wikipedia.org/wiki/Relational_algebra#Division">http://en.wikipedia.org/wiki/Relational_algebra#Division</a></li>
* <li><a href=
* "http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/"
* >http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/</a></li>
* </ul>
* <p>
* This has been observed to work with all dialects
*/
DivideByOnStep divideBy(Table<?> divisor);
/**
* <code>INNER JOIN</code> a table to this table.
*/

View File

@ -43,6 +43,7 @@ import java.util.Collections;
import java.util.List;
import org.jooq.DataType;
import org.jooq.DivideByOnStep;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Identity;
@ -71,7 +72,7 @@ abstract class AbstractTable<R extends Record> extends AbstractType<R> implement
}
// ------------------------------------------------------------------------
// TableLike API
// XXX: TableLike API
// ------------------------------------------------------------------------
@Override
@ -85,7 +86,7 @@ abstract class AbstractTable<R extends Record> extends AbstractType<R> implement
}
// ------------------------------------------------------------------------
// Table API
// XXX: Table API
// ------------------------------------------------------------------------
/**
@ -137,7 +138,7 @@ abstract class AbstractTable<R extends Record> extends AbstractType<R> implement
}
// ------------------------------------------------------------------------
// PIVOT API
// XXX: PIVOT API
// ------------------------------------------------------------------------
@Override
@ -151,7 +152,16 @@ abstract class AbstractTable<R extends Record> extends AbstractType<R> implement
}
// ------------------------------------------------------------------------
// JOIN API
// XXX: DIVISION API
// ------------------------------------------------------------------------
@Override
public final DivideByOnStep divideBy(Table<?> divisor) {
return new DivideBy(this, divisor);
}
// ------------------------------------------------------------------------
// XXX: JOIN API
// ------------------------------------------------------------------------
@Override

View File

@ -0,0 +1,286 @@
/**
* Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com
* All rights reserved.
*
* This software is licensed to you under the Apache License, Version 2.0
* (the "License"); You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* . Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* . Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* . Neither the name "jOOQ" nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.jooq.impl;
import static org.jooq.impl.Factory.condition;
import static org.jooq.impl.Factory.exists;
import static org.jooq.impl.Factory.notExists;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.jooq.Attachable;
import org.jooq.BindContext;
import org.jooq.Condition;
import org.jooq.ConditionProvider;
import org.jooq.Configuration;
import org.jooq.DivideByOnConditionStep;
import org.jooq.DivideByOnStep;
import org.jooq.Field;
import org.jooq.Operator;
import org.jooq.Record;
import org.jooq.RenderContext;
import org.jooq.Select;
import org.jooq.Table;
/**
* @author Lukas Eder
*/
class DivideBy
extends AbstractTable<Record>
implements
DivideByOnStep,
DivideByOnConditionStep {
/**
* Generated UID
*/
private static final long serialVersionUID = -4999896035630325449L;
private final Table<?> dividend;
private final Table<?> divisor;
private final ConditionProviderImpl condition;
private final FieldList returning;
DivideBy(Table<?> dividend, Table<?> divisor) {
super("division");
this.dividend = dividend;
this.divisor = divisor;
this.condition = new ConditionProviderImpl();
this.returning = new FieldList();
}
// ------------------------------------------------------------------------
// XXX: Table API
// ------------------------------------------------------------------------
@Override
public final Class<? extends Record> getRecordType() {
return RecordImpl.class;
}
@Override
public final boolean declaresTables() {
return true;
}
@Override
public final void toSQL(RenderContext context) {
context.sql(table(context));
}
@Override
public final void bind(BindContext context) {
context.bind(table(context));
}
/**
* Transform the relational division operation into SQL.
* <p>
* Various nice examples of how this can be achieved are found here: <a
* href=
* "http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/"
* >http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-
* sql-of-relational-division/</a>
*/
private final Table<?> table(Configuration configuration) {
Factory create = create(configuration);
ConditionProviderImpl selfJoin = new ConditionProviderImpl();
FieldList select = new FieldList();
Table<?> outer = dividend.as("dividend");
for (Field<?> field : returning) {
Field<?> outerField = outer.getField(field);
// Fields from the RETURNING clause are added AS-IS to the SELECT
// statement, if they're not contained in the dividend table
if (outerField == null) {
select.add(field);
}
// Fields from the RETURNING clause need proper aliasing if they're
// contained in the dividend table
else {
select.add(outerField);
selfJoin(selfJoin, outer, dividend, field);
}
}
// Apply relational division using double-nested NOT EXISTS clauses
// There are more efficient ways to express division in SQL, but those
// are hard to simulate with jOOQ
return create.selectDistinct(select)
.from(outer)
.whereNotExists(create
.selectOne()
.from(divisor)
.whereNotExists(create
.selectOne()
.from(dividend)
.where(selfJoin)
.and(condition)))
.asTable();
}
/**
* Extracted method for type-safety
*/
private final <T> void selfJoin(ConditionProvider selfJoin, Table<?> outer, Table<?> inner, Field<T> field) {
Field<T> outerField = outer.getField(field);
Field<T> innerField = inner.getField(field);
if (outerField == null || innerField == null) {
return;
}
else {
selfJoin.addConditions(outerField.equal(innerField));
}
}
@Override
public final Table<Record> as(String alias) {
return new TableAlias<Record>(this, alias, true);
}
@Override
protected final FieldList getFieldList() {
return new FieldList();
}
@Override
protected final List<Attachable> getAttachables0() {
return getAttachables(dividend, divisor, condition, returning);
}
// ------------------------------------------------------------------------
// XXX: DivideBy API
// ------------------------------------------------------------------------
@Override
public final DivideBy on(Condition... conditions) {
condition.addConditions(conditions);
return this;
}
@Override
public final DivideBy on(String sql) {
and(sql);
return this;
}
@Override
public final DivideBy on(String sql, Object... bindings) {
and(sql, bindings);
return this;
}
@Override
public final DivideBy returning(Field<?>... fields) {
return returning(Arrays.asList(fields));
}
@Override
public final DivideBy returning(Collection<? extends Field<?>> fields) {
returning.addAll(fields);
return this;
}
@Override
public final DivideBy and(Condition c) {
condition.addConditions(c);
return this;
}
@Override
public final DivideBy and(String sql) {
return and(condition(sql));
}
@Override
public final DivideBy and(String sql, Object... bindings) {
return and(condition(sql, bindings));
}
@Override
public final DivideBy andNot(Condition c) {
return and(c.not());
}
@Override
public final DivideBy andExists(Select<?> select) {
return and(exists(select));
}
@Override
public final DivideBy andNotExists(Select<?> select) {
return and(notExists(select));
}
@Override
public final DivideBy or(Condition c) {
condition.addConditions(Operator.OR, c);
return this;
}
@Override
public final DivideBy or(String sql) {
return or(condition(sql));
}
@Override
public final DivideBy or(String sql, Object... bindings) {
return or(condition(sql, bindings));
}
@Override
public final DivideBy orNot(Condition c) {
return or(c.not());
}
@Override
public final DivideBy orExists(Select<?> select) {
return or(exists(select));
}
@Override
public final DivideBy orNotExists(Select<?> select) {
return or(notExists(select));
}
}

View File

@ -89,7 +89,7 @@ implements
}
// ------------------------------------------------------------------------
// Table API
// XXX: Table API
// ------------------------------------------------------------------------
@Override
@ -318,7 +318,7 @@ implements
}
// ------------------------------------------------------------------------
// Pivot API
// XXX: Pivot API
// ------------------------------------------------------------------------
@SuppressWarnings("unchecked")