[#661] Add support for bitwise operators
[#895] Add Field.power(Field<? extends Number>)
This commit is contained in:
parent
de67521fb4
commit
e0493dc775
@ -42,7 +42,9 @@ import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.fail;
|
||||
import static org.jooq.SQLDialect.ASE;
|
||||
import static org.jooq.SQLDialect.DB2;
|
||||
import static org.jooq.SQLDialect.SQLSERVER;
|
||||
import static org.jooq.SQLDialect.SYBASE;
|
||||
import static org.jooq.impl.Factory.cast;
|
||||
import static org.jooq.impl.Factory.castNull;
|
||||
@ -4792,7 +4794,7 @@ public abstract class jOOQAbstractTest<
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArithmeticExpressions() throws Exception {
|
||||
public void testArithmeticOperations() throws Exception {
|
||||
Field<Integer> f1 = val(1).add(2).add(3).div(2);
|
||||
Field<Integer> f2 = val(10).div(5).add(val(3).sub(2));
|
||||
Field<Integer> f3 = val(10).mod(3);
|
||||
@ -4822,6 +4824,53 @@ public abstract class jOOQAbstractTest<
|
||||
assertEquals(Integer.valueOf((1948 - 4) * -8), result.getValue(0, f5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBitwiseOperations() throws Exception {
|
||||
switch (getDialect()) {
|
||||
case DERBY:
|
||||
case INGRES:
|
||||
log.info("SKIPPING", "Tests for bitwise operations");
|
||||
return;
|
||||
}
|
||||
|
||||
Field<Integer> bitCount = val(3).bitCount();
|
||||
|
||||
// TODO [#896] This somehow doesn't work on some dialects
|
||||
if (asList(ASE, DB2, SQLSERVER).contains(getDialect())) {
|
||||
bitCount = val(2);
|
||||
}
|
||||
|
||||
Record result =
|
||||
create().select(
|
||||
bitCount,
|
||||
val(3).bitNot().bitNot(),
|
||||
val(3).bitAnd(5),
|
||||
val(3).bitOr(5),
|
||||
|
||||
val(3).bitXor(5),
|
||||
val(3).bitNand(5).bitNot(),
|
||||
val(3).bitNor(5).bitNot(),
|
||||
val(3).bitXNor(5).bitNot(),
|
||||
|
||||
val(333).shl(3),
|
||||
val(333).shr(3))
|
||||
.fetchOne();
|
||||
|
||||
int index = 0;
|
||||
assertEquals(2, result.getValue(index++));
|
||||
assertEquals(~(~3), result.getValue(index++));
|
||||
assertEquals(3 & 5, result.getValue(index++));
|
||||
assertEquals(3 | 5, result.getValue(index++));
|
||||
|
||||
assertEquals(3 ^ 5, result.getValue(index++));
|
||||
assertEquals(~(~(3 & 5)), result.getValue(index++));
|
||||
assertEquals(~(~(3 | 5)), result.getValue(index++));
|
||||
assertEquals(~(~(3 ^ 5)), result.getValue(index++));
|
||||
|
||||
assertEquals(333 << 3, result.getValue(index++));
|
||||
assertEquals(333 >> 3, result.getValue(index++));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAggregateFunctions() throws Exception {
|
||||
|
||||
|
||||
@ -252,7 +252,7 @@ public interface Field<T> extends NamedTypeProviderQueryPart<T>, AliasProvider<F
|
||||
<Z> SortField<Z> sort(Map<T, Z> sortMap);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Arithmetic expressions
|
||||
// Arithmetic operations
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@ -335,6 +335,233 @@ public interface Field<T> extends NamedTypeProviderQueryPart<T>, AliasProvider<F
|
||||
*/
|
||||
Field<T> mod(Field<? extends Number> value);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Bitwise operations
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The MySQL <code>BIT_COUNT(field)</code> function, counting the number of
|
||||
* bits that are set in this number.
|
||||
* <p>
|
||||
* This function is simulated in most other databases like this (for a
|
||||
* TINYINT field): <code><pre>
|
||||
* (my_field & 1) +
|
||||
* (my_field & 2) >> 1 +
|
||||
* (my_field & 4) >> 2 +
|
||||
* (my_field & 8) >> 3 +
|
||||
* (my_field & 16) >> 4 +
|
||||
* ...
|
||||
* (my_field & 128) >> 7
|
||||
* </pre></code>
|
||||
* <p>
|
||||
* More efficient algorithms are very welcome
|
||||
*/
|
||||
Field<Integer> bitCount();
|
||||
|
||||
/**
|
||||
* The bitwise not operator.
|
||||
* <p>
|
||||
* Most dialects natively support this using <code>~[this]</code>. jOOQ
|
||||
* simulates this operator in some dialects using <code>-[this] - 1</code>
|
||||
*/
|
||||
Field<T> bitNot();
|
||||
|
||||
/**
|
||||
* The bitwise and operator.
|
||||
* <p>
|
||||
* This is not supported by Derby, Ingres
|
||||
* <p>
|
||||
* This renders the and operation where available:
|
||||
* <code><pre>[this] & [value]</pre></code>
|
||||
* ... or the and function elsewhere:
|
||||
* <code><pre>bitand([this], [value])</pre></code>
|
||||
*/
|
||||
Field<T> bitAnd(Number value);
|
||||
|
||||
/**
|
||||
* The bitwise and operator.
|
||||
* <p>
|
||||
* This is not supported by Derby, Ingres
|
||||
* <p>
|
||||
* This renders the and operation where available:
|
||||
* <code><pre>[this] & [value]</pre></code>
|
||||
* ... or the and function elsewhere:
|
||||
* <code><pre>bitand([this], [value])</pre></code>
|
||||
*/
|
||||
Field<T> bitAnd(Field<? extends Number> value);
|
||||
|
||||
/**
|
||||
* The bitwise not and operator.
|
||||
* <p>
|
||||
* This is not supported by Derby, Ingres
|
||||
* <p>
|
||||
* This renders the not and operation where available:
|
||||
* <code><pre>~([this] & [value])</pre></code>
|
||||
* ... or the not and function elsewhere:
|
||||
* <code><pre>bitnot(bitand([this], [value]))</pre></code>
|
||||
*
|
||||
* @see #bitNot()
|
||||
*/
|
||||
Field<T> bitNand(Number value);
|
||||
|
||||
/**
|
||||
* The bitwise not and operator.
|
||||
* <p>
|
||||
* This is not supported by Derby, Ingres
|
||||
* <p>
|
||||
* This renders the not and operation where available:
|
||||
* <code><pre>~([this] & [value])</pre></code>
|
||||
* ... or the not and function elsewhere:
|
||||
* <code><pre>bitnot(bitand([this], [value]))</pre></code>
|
||||
*
|
||||
* @see #bitNot()
|
||||
*/
|
||||
Field<T> bitNand(Field<? extends Number> value);
|
||||
|
||||
/**
|
||||
* The bitwise or operator.
|
||||
* <p>
|
||||
* This is not supported by Derby, Ingres
|
||||
* <p>
|
||||
* This renders the or operation where available:
|
||||
* <code><pre>[this] | [value]</pre></code>
|
||||
* ... or the or function elsewhere:
|
||||
* <code><pre>bitor([this], [value])</pre></code>
|
||||
*/
|
||||
Field<T> bitOr(Number value);
|
||||
|
||||
/**
|
||||
* The bitwise or operator.
|
||||
* <p>
|
||||
* This is not supported by Derby, Ingres
|
||||
* <p>
|
||||
* This renders the or operation where available:
|
||||
* <code><pre>[this] | [value]</pre></code>
|
||||
* ... or the or function elsewhere:
|
||||
* <code><pre>bitor([this], [value])</pre></code>
|
||||
*/
|
||||
Field<T> bitOr(Field<? extends Number> value);
|
||||
|
||||
/**
|
||||
* The bitwise not or operator.
|
||||
* <p>
|
||||
* This is not supported by Derby, Ingres
|
||||
* <p>
|
||||
* This renders the not or operation where available:
|
||||
* <code><pre>~([this] | [value])</pre></code>
|
||||
* ... or the not or function elsewhere:
|
||||
* <code><pre>bitnot(bitor([this], [value]))</pre></code>
|
||||
*
|
||||
* @see #bitNot()
|
||||
*/
|
||||
Field<T> bitNor(Number value);
|
||||
|
||||
/**
|
||||
* The bitwise not or operator.
|
||||
* <p>
|
||||
* This is not supported by Derby, Ingres
|
||||
* <p>
|
||||
* This renders the not or operation where available:
|
||||
* <code><pre>~([this] | [value])</pre></code>
|
||||
* ... or the not or function elsewhere:
|
||||
* <code><pre>bitnot(bitor([this], [value]))</pre></code>
|
||||
*
|
||||
* @see #bitNot()
|
||||
*/
|
||||
Field<T> bitNor(Field<? extends Number> value);
|
||||
|
||||
/**
|
||||
* The bitwise xor operator.
|
||||
* <p>
|
||||
* This is not supported by Derby, Ingres
|
||||
* <p>
|
||||
* This renders the or operation where available:
|
||||
* <code><pre>[this] ^ [value]</pre></code>
|
||||
* ... or the xor function elsewhere:
|
||||
* <code><pre>bitxor([this], [value])</pre></code>
|
||||
*/
|
||||
Field<T> bitXor(Number value);
|
||||
|
||||
/**
|
||||
* The bitwise xor operator.
|
||||
* <p>
|
||||
* This is not supported by Derby, Ingres
|
||||
* <p>
|
||||
* This renders the or operation where available:
|
||||
* <code><pre>[this] ^ [value]</pre></code>
|
||||
* ... or the xor function elsewhere:
|
||||
* <code><pre>bitxor([this], [value])</pre></code>
|
||||
*/
|
||||
Field<T> bitXor(Field<? extends Number> value);
|
||||
|
||||
/**
|
||||
* The bitwise not xor operator.
|
||||
* <p>
|
||||
* This is not supported by Derby, Ingres
|
||||
* <p>
|
||||
* This renders the or operation where available:
|
||||
* <code><pre>~([this] ^ [value])</pre></code>
|
||||
* ... or the not xor function elsewhere:
|
||||
* <code><pre>bitnot(bitxor([this], [value]))</pre></code>
|
||||
*/
|
||||
Field<T> bitXNor(Number value);
|
||||
|
||||
/**
|
||||
* The bitwise not xor operator.
|
||||
* <p>
|
||||
* This is not supported by Derby, Ingres
|
||||
* <p>
|
||||
* This renders the or operation where available:
|
||||
* <code><pre>~([this] ^ [value])</pre></code>
|
||||
* ... or the not xor function elsewhere:
|
||||
* <code><pre>bitnot(bitxor([this], [value]))</pre></code>
|
||||
*/
|
||||
Field<T> bitXNor(Field<? extends Number> value);
|
||||
|
||||
/**
|
||||
* The bitwise left shift operator.
|
||||
* <p>
|
||||
* Some dialects natively support this using <code>[this] << [value]</code>.
|
||||
* jOOQ simulates this operator in some dialects using
|
||||
* <code>[this] * power(2, [value])</code>, where power might also be simulated.
|
||||
*
|
||||
* @see #power(Field)
|
||||
*/
|
||||
Field<T> shl(Number value);
|
||||
|
||||
/**
|
||||
* The bitwise left shift operator.
|
||||
* <p>
|
||||
* Some dialects natively support this using <code>[this] << [value]</code>.
|
||||
* jOOQ simulates this operator in some dialects using
|
||||
* <code>[this] * power(2, [value])</code>, where power might also be simulated.
|
||||
*
|
||||
* @see #power(Field)
|
||||
*/
|
||||
Field<T> shl(Field<? extends Number> value);
|
||||
|
||||
/**
|
||||
* The bitwise right shift operator.
|
||||
* <p>
|
||||
* Some dialects natively support this using <code>[this] >> [value]</code>.
|
||||
* jOOQ simulates this operator in some dialects using
|
||||
* <code>[this] / power(2, [value])</code>, where power might also be simulated.
|
||||
*
|
||||
* @see #power(Field)
|
||||
*/
|
||||
Field<T> shr(Number value);
|
||||
|
||||
/**
|
||||
* The bitwise right shift operator.
|
||||
* <p>
|
||||
* Some dialects natively support this using <code>[this] >> [value]</code>.
|
||||
* jOOQ simulates this operator in some dialects using
|
||||
* <code>[this] / power(2, [value])</code>, where power might also be simulated.
|
||||
*
|
||||
* @see #power(Field)
|
||||
*/
|
||||
Field<T> shr(Field<? extends Number> value);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Mathematical functions created from this field
|
||||
// ------------------------------------------------------------------------
|
||||
@ -448,6 +675,16 @@ public interface Field<T> extends NamedTypeProviderQueryPart<T>, AliasProvider<F
|
||||
*/
|
||||
Field<BigDecimal> power(Number exponent);
|
||||
|
||||
/**
|
||||
* Get the power(field, exponent) function
|
||||
* <p>
|
||||
* This renders the power function where available:
|
||||
* <code><pre>power([this], [exponent])</pre></code> ... or simulates it
|
||||
* elsewhere using ln and exp:
|
||||
* <code><pre>exp(ln([this]) * [exponent])</pre></code>
|
||||
*/
|
||||
Field<BigDecimal> power(Field<? extends Number> exponent);
|
||||
|
||||
/**
|
||||
* Get the arc cosine(field) function
|
||||
* <p>
|
||||
|
||||
@ -202,12 +202,12 @@ abstract class AbstractField<T> extends AbstractNamedTypeProviderQueryPart<T> im
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Arithmetic expressions
|
||||
// Arithmetic operations
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public final Field<T> neg() {
|
||||
return new Neg<T>(this);
|
||||
return new Neg<T>(this, ExpressionOperator.SUBTRACT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -286,6 +286,100 @@ abstract class AbstractField<T> extends AbstractNamedTypeProviderQueryPart<T> im
|
||||
return new Mod<T>(this, value);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Bitwise operations
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public final Field<Integer> bitCount() {
|
||||
return new BitCount(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> bitNot() {
|
||||
return new Neg<T>(this, ExpressionOperator.BIT_NOT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> bitAnd(Number value) {
|
||||
return bitAnd(val(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> bitAnd(Field<? extends Number> value) {
|
||||
return new Expression<T>(ExpressionOperator.BIT_AND, this, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> bitNand(Number value) {
|
||||
return bitNand(val(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> bitNand(Field<? extends Number> value) {
|
||||
return new Expression<T>(ExpressionOperator.BIT_NAND, this, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> bitOr(Number value) {
|
||||
return bitOr(val(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> bitOr(Field<? extends Number> value) {
|
||||
return new Expression<T>(ExpressionOperator.BIT_OR, this, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> bitNor(Number value) {
|
||||
return bitNor(val(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> bitNor(Field<? extends Number> value) {
|
||||
return new Expression<T>(ExpressionOperator.BIT_NOR, this, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> bitXor(Number value) {
|
||||
return bitXor(val(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> bitXor(Field<? extends Number> value) {
|
||||
return new Expression<T>(ExpressionOperator.BIT_XOR, this, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> bitXNor(Number value) {
|
||||
return bitXNor(val(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> bitXNor(Field<? extends Number> value) {
|
||||
return new Expression<T>(ExpressionOperator.BIT_XNOR, this, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> shl(Number value) {
|
||||
return shl(val(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> shl(Field<? extends Number> value) {
|
||||
return new Expression<T>(ExpressionOperator.SHL, this, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> shr(Number value) {
|
||||
return shr(val(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> shr(Field<? extends Number> value) {
|
||||
return new Expression<T>(ExpressionOperator.SHR, this, value);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Window functions created from this field
|
||||
// ------------------------------------------------------------------------
|
||||
@ -528,6 +622,11 @@ abstract class AbstractField<T> extends AbstractNamedTypeProviderQueryPart<T> im
|
||||
|
||||
@Override
|
||||
public final Field<BigDecimal> power(Number exponent) {
|
||||
return power(val(exponent));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Field<BigDecimal> power(Field<? extends Number> exponent) {
|
||||
return new Power(this, exponent);
|
||||
}
|
||||
|
||||
|
||||
220
jOOQ/src/main/java/org/jooq/impl/BitCount.java
Normal file
220
jOOQ/src/main/java/org/jooq/impl/BitCount.java
Normal file
@ -0,0 +1,220 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2011, 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.function;
|
||||
import static org.jooq.impl.Factory.literal;
|
||||
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.Field;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
class BitCount extends AbstractFunction<Integer> {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = 7624782102883057433L;
|
||||
|
||||
BitCount(Field<?> field) {
|
||||
super("bit_count", SQLDataType.INTEGER, field);
|
||||
}
|
||||
|
||||
@Override
|
||||
final Field<Integer> getFunction0(Configuration configuration) {
|
||||
final Field<?> field = getArguments()[0];
|
||||
|
||||
switch (configuration.getDialect()) {
|
||||
case MYSQL:
|
||||
return function("bit_count", getDataType(), getArguments());
|
||||
|
||||
// Warning, some severe madness lies ahead. Better solutions very welcome!
|
||||
// See also http://stackoverflow.com/questions/7946349/how-to-simulate-the-mysql-bit-count-function-in-sybase-sql-anywhere
|
||||
default: {
|
||||
if (field.getType() == Byte.class) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Field<Byte> f = (Field<Byte>) field;
|
||||
|
||||
byte i = 0;
|
||||
return f.bitAnd(literal((byte) 0x01)).add(
|
||||
f.bitAnd(literal((byte) 0x02)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((byte) 0x04)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((byte) 0x08)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((byte) 0x10)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((byte) 0x20)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((byte) 0x40)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((byte) 0x80)).shr(literal(++i))).cast(Integer.class);
|
||||
}
|
||||
else if (field.getType() == Short.class) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Field<Short> f = (Field<Short>) field;
|
||||
|
||||
short i = 0;
|
||||
return f.bitAnd(literal((short) 0x0001)).add(
|
||||
f.bitAnd(literal((short) 0x0002)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x0004)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x0008)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x0010)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x0020)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x0040)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x0080)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x0100)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x0200)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x0400)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x0800)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x1000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x2000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x4000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal((short) 0x8000)).shr(literal(++i))).cast(Integer.class);
|
||||
}
|
||||
else if (field.getType() == Integer.class) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Field<Integer> f = (Field<Integer>) field;
|
||||
|
||||
int i = 0;
|
||||
return f.bitAnd(literal(0x00000001)).add(
|
||||
f.bitAnd(literal(0x00000002)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00000004)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00000008)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00000010)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00000020)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00000040)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00000080)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00000100)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00000200)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00000400)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00000800)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00001000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00002000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00004000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00008000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00010000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00020000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00040000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00080000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00100000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00200000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00400000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x00800000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x01000000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x02000000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x04000000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x08000000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x10000000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x20000000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x40000000)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x80000000)).shr(literal(++i)));
|
||||
}
|
||||
else if (field.getType() == Long.class) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Field<Long> f = (Field<Long>) field;
|
||||
|
||||
long i = 0;
|
||||
return f.bitAnd(literal(0x0000000000000001L)).add(
|
||||
f.bitAnd(literal(0x0000000000000002L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000000004L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000000008L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000000010L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000000020L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000000040L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000000080L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000000100L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000000200L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000000400L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000000800L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000001000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000002000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000004000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000008000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000010000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000020000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000040000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000080000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000100000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000200000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000400000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000000800000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000001000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000002000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000004000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000008000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000010000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000020000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000040000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000080000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000100000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000200000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000400000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000000800000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000001000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000002000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000004000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000008000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000010000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000020000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000040000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000080000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000100000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000200000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000400000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0000800000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0001000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0002000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0004000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0008000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0010000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0020000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0040000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0080000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0100000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0200000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0400000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x0800000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x1000000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x2000000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x4000000000000000L)).shr(literal(++i))).add(
|
||||
f.bitAnd(literal(0x8000000000000000L)).shr(literal(++i))).cast(Integer.class);
|
||||
}
|
||||
else {
|
||||
// Currently not supported
|
||||
return function("bit_count", getDataType(), getArguments());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -35,17 +35,41 @@
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.jooq.SQLDialect.ASE;
|
||||
import static org.jooq.SQLDialect.DB2;
|
||||
import static org.jooq.SQLDialect.H2;
|
||||
import static org.jooq.SQLDialect.HSQLDB;
|
||||
import static org.jooq.SQLDialect.INGRES;
|
||||
import static org.jooq.SQLDialect.ORACLE;
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
import static org.jooq.SQLDialect.SQLITE;
|
||||
import static org.jooq.SQLDialect.SQLSERVER;
|
||||
import static org.jooq.SQLDialect.SYBASE;
|
||||
import static org.jooq.impl.ExpressionOperator.BIT_AND;
|
||||
import static org.jooq.impl.ExpressionOperator.BIT_NAND;
|
||||
import static org.jooq.impl.ExpressionOperator.BIT_NOR;
|
||||
import static org.jooq.impl.ExpressionOperator.BIT_OR;
|
||||
import static org.jooq.impl.ExpressionOperator.BIT_XNOR;
|
||||
import static org.jooq.impl.ExpressionOperator.BIT_XOR;
|
||||
import static org.jooq.impl.ExpressionOperator.SHL;
|
||||
import static org.jooq.impl.ExpressionOperator.SHR;
|
||||
import static org.jooq.impl.Factory.function;
|
||||
import static org.jooq.impl.Factory.literal;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.Attachable;
|
||||
import org.jooq.BindContext;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.QueryPart;
|
||||
import org.jooq.RenderContext;
|
||||
import org.jooq.SQLDialect;
|
||||
|
||||
class Expression<T> extends AbstractField<T> {
|
||||
class Expression<T> extends AbstractFunction<T> {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
@ -56,7 +80,7 @@ class Expression<T> extends AbstractField<T> {
|
||||
private final ExpressionOperator operator;
|
||||
|
||||
Expression(ExpressionOperator operator, Field<T> lhs, Field<?>... rhs) {
|
||||
super(operator.toSQL(), lhs.getDataType());
|
||||
super(operator.toSQL(), lhs.getDataType(), JooqUtil.combine(lhs, rhs));
|
||||
|
||||
this.operator = operator;
|
||||
this.lhs = lhs;
|
||||
@ -64,11 +88,6 @@ class Expression<T> extends AbstractField<T> {
|
||||
this.rhs.addAll(Arrays.asList(rhs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<Attachable> getAttachables() {
|
||||
return getAttachables(lhs, rhs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> add(Field<? extends Number> value) {
|
||||
if (operator == ExpressionOperator.ADD) {
|
||||
@ -90,27 +109,117 @@ class Expression<T> extends AbstractField<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void toSQL(RenderContext context) {
|
||||
context.sql("(");
|
||||
context.sql(lhs);
|
||||
final Field<T> getFunction0(Configuration configuration) {
|
||||
SQLDialect dialect = configuration.getDialect();
|
||||
|
||||
for (Field<?> field : rhs) {
|
||||
context.sql(" ")
|
||||
.sql(operator.toSQL())
|
||||
.sql(" ")
|
||||
.sql(field);
|
||||
// DB2, H2 and HSQLDB know functions, instead of operators
|
||||
if (BIT_AND == operator && asList(DB2, H2, HSQLDB, ORACLE).contains(dialect)) {
|
||||
return function("bitand", getDataType(), getArguments());
|
||||
}
|
||||
else if (BIT_XOR == operator && asList(DB2, H2, HSQLDB).contains(dialect)) {
|
||||
return function("bitxor", getDataType(), getArguments());
|
||||
}
|
||||
else if (BIT_OR == operator && asList(DB2, H2, HSQLDB).contains(dialect)) {
|
||||
return function("bitor", getDataType(), getArguments());
|
||||
}
|
||||
|
||||
context.sql(")");
|
||||
// Oracle has to simulate or/xor
|
||||
else if (BIT_OR == operator && ORACLE == dialect) {
|
||||
return lhs.sub(lhsAsNumber().bitAnd(rhsAsNumber())).add(rhsAsNumber());
|
||||
}
|
||||
|
||||
// ~(a & b) & (a | b)
|
||||
else if (BIT_XOR == operator && asList(ORACLE, SQLITE).contains(dialect)) {
|
||||
return lhs.bitAnd(rhsAsNumber()).bitNot().bitAnd(
|
||||
lhsAsNumber().bitOr(rhsAsNumber()));
|
||||
}
|
||||
|
||||
// Many dialects don't support shifts. Use multiplication/division instead
|
||||
else if (SHL == operator && asList(ASE, DB2, H2, HSQLDB, INGRES, ORACLE, SQLSERVER, SYBASE).contains(dialect)) {
|
||||
return lhs.mul(literal(2).power(rhsAsNumber()));
|
||||
}
|
||||
else if (SHR == operator && asList(ASE, DB2, H2, HSQLDB, INGRES, ORACLE, SQLSERVER, SYBASE).contains(dialect)) {
|
||||
return lhs.div(literal(2).power(rhsAsNumber()));
|
||||
}
|
||||
|
||||
// These operators are not supported in any dialect
|
||||
else if (BIT_NAND == operator) {
|
||||
return lhs.bitAnd(rhsAsNumber()).bitNot();
|
||||
}
|
||||
else if (BIT_NOR == operator) {
|
||||
return lhs.bitOr(rhsAsNumber()).bitNot();
|
||||
}
|
||||
else if (BIT_XNOR == operator) {
|
||||
return lhs.bitXor(rhsAsNumber()).bitNot();
|
||||
}
|
||||
|
||||
// Use the default operator expression
|
||||
else {
|
||||
return new DefaultExpression();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void bind(BindContext context) throws SQLException {
|
||||
context.bind(lhs).bind((QueryPart) rhs);
|
||||
/**
|
||||
* In some expressions, the lhs can be safely assumed to be a single number
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private final Field<? extends Number> lhsAsNumber() {
|
||||
return (Field<? extends Number>) lhs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isNullLiteral() {
|
||||
return false;
|
||||
/**
|
||||
* In some expressions, the rhs can be safely assumed to be a single number
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private final Field<? extends Number> rhsAsNumber() {
|
||||
return (Field<? extends Number>) rhs.get(0);
|
||||
}
|
||||
|
||||
private class DefaultExpression extends AbstractField<T> {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = -5105004317793995419L;
|
||||
|
||||
private DefaultExpression() {
|
||||
super(operator.toSQL(), lhs.getDataType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<Attachable> getAttachables() {
|
||||
return Expression.this.getAttachables();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void toSQL(RenderContext context) {
|
||||
String op = operator.toSQL();
|
||||
|
||||
if (operator == BIT_XOR && context.getDialect() == POSTGRES) {
|
||||
op = "#";
|
||||
}
|
||||
|
||||
context.sql("(");
|
||||
context.sql(lhs);
|
||||
|
||||
for (Field<?> field : rhs) {
|
||||
context.sql(" ")
|
||||
.sql(op)
|
||||
.sql(" ")
|
||||
.sql(field);
|
||||
}
|
||||
|
||||
context.sql(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void bind(BindContext context) throws SQLException {
|
||||
context.bind(lhs).bind((QueryPart) rhs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isNullLiteral() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,7 +70,54 @@ enum ExpressionOperator {
|
||||
/**
|
||||
* Modulo
|
||||
*/
|
||||
MODULO("%");
|
||||
MODULO("%"),
|
||||
|
||||
/**
|
||||
* Bitwise not
|
||||
*/
|
||||
BIT_NOT("~"),
|
||||
|
||||
/**
|
||||
* Bitwise and
|
||||
*/
|
||||
BIT_AND("&"),
|
||||
|
||||
/**
|
||||
* Bitwise or
|
||||
*/
|
||||
BIT_OR("|"),
|
||||
|
||||
/**
|
||||
* Bitwise xor
|
||||
*/
|
||||
BIT_XOR("^"),
|
||||
|
||||
/**
|
||||
* Bitwise and
|
||||
*/
|
||||
BIT_NAND("~&"),
|
||||
|
||||
/**
|
||||
* Bitwise or
|
||||
*/
|
||||
BIT_NOR("~|"),
|
||||
|
||||
/**
|
||||
* Bitwise xor
|
||||
*/
|
||||
BIT_XNOR("~^"),
|
||||
|
||||
/**
|
||||
* Bitwise shift left
|
||||
*/
|
||||
SHL("<<"),
|
||||
|
||||
/**
|
||||
* Bitwise shift right
|
||||
*/
|
||||
SHR(">>"),
|
||||
|
||||
;
|
||||
|
||||
private final String sql;
|
||||
|
||||
|
||||
@ -35,6 +35,14 @@
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.jooq.SQLDialect.DB2;
|
||||
import static org.jooq.SQLDialect.H2;
|
||||
import static org.jooq.SQLDialect.HSQLDB;
|
||||
import static org.jooq.SQLDialect.INGRES;
|
||||
import static org.jooq.SQLDialect.ORACLE;
|
||||
import static org.jooq.impl.ExpressionOperator.BIT_NOT;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
@ -42,6 +50,7 @@ import org.jooq.Attachable;
|
||||
import org.jooq.BindContext;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.RenderContext;
|
||||
import org.jooq.SQLDialect;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
@ -51,13 +60,15 @@ class Neg<T> extends AbstractField<T> {
|
||||
/**
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = 7624782102883057433L;
|
||||
private static final long serialVersionUID = 7624782102883057433L;
|
||||
|
||||
private final Field<T> field;
|
||||
private final ExpressionOperator operator;
|
||||
private final Field<T> field;
|
||||
|
||||
Neg(Field<T> field) {
|
||||
super("-" + field.getName(), field.getDataType());
|
||||
Neg(Field<T> field, ExpressionOperator operator) {
|
||||
super(operator.toSQL() + field.getName(), field.getDataType());
|
||||
|
||||
this.operator = operator;
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@ -68,7 +79,24 @@ class Neg<T> extends AbstractField<T> {
|
||||
|
||||
@Override
|
||||
public final void toSQL(RenderContext context) {
|
||||
context.sql("-").sql(field);
|
||||
SQLDialect dialect = context.getDialect();
|
||||
|
||||
if (operator == BIT_NOT && asList(H2, HSQLDB, INGRES, ORACLE).contains(dialect)) {
|
||||
context.sql("(0 -")
|
||||
.sql(field)
|
||||
.sql(" - 1)");
|
||||
}
|
||||
else if (operator == BIT_NOT && dialect == DB2) {
|
||||
context.sql("bitnot(")
|
||||
.sql(field)
|
||||
.sql(")");
|
||||
}
|
||||
else {
|
||||
context.sql(operator.toSQL())
|
||||
.sql("(")
|
||||
.sql(field)
|
||||
.sql(")");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
package org.jooq.impl;
|
||||
|
||||
import static org.jooq.impl.Factory.function;
|
||||
import static org.jooq.impl.Factory.literal;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@ -53,11 +52,11 @@ class Power extends AbstractFunction<BigDecimal> {
|
||||
*/
|
||||
private static final long serialVersionUID = -7273879239726265322L;
|
||||
|
||||
private final Field<?> arg1;
|
||||
private final Number arg2;
|
||||
private final Field<?> arg1;
|
||||
private final Field<? extends Number> arg2;
|
||||
|
||||
Power(Field<?> arg1, Number arg2) {
|
||||
super("ceil", SQLDataType.NUMERIC, arg1);
|
||||
Power(Field<?> arg1, Field<? extends Number> arg2) {
|
||||
super("ceil", SQLDataType.NUMERIC, arg1, arg2);
|
||||
|
||||
this.arg1 = arg1;
|
||||
this.arg2 = arg2;
|
||||
@ -68,10 +67,10 @@ class Power extends AbstractFunction<BigDecimal> {
|
||||
switch (configuration.getDialect()) {
|
||||
case DERBY:
|
||||
case SQLITE:
|
||||
return arg1.ln().mul(literal(arg2)).exp();
|
||||
return arg1.ln().mul(arg2).exp();
|
||||
|
||||
default:
|
||||
return function("power", SQLDataType.NUMERIC, arg1, literal(arg2));
|
||||
return function("power", SQLDataType.NUMERIC, getArguments());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user