Issue Details (XML | Word | Printable)

Key: HHH-160
Type: Improvement Improvement
Status: Open Open
Priority: Minor Minor
Assignee: Unassigned
Reporter: Markus Jessenitschnig
Votes: 9
Watchers: 8
Operations

If you were logged in you would be able to see more operations.
Hibernate Core

New query parser does not allow bitwise operations

Created: 01/Mar/05 01:42 AM   Updated: 27/Apr/08 04:33 PM
Component/s: core
Affects Version/s: 3.0 rc 1
Fix Version/s: None

Time Tracking:
Not Specified

Environment: Hibernate 3.0 rc1, MySQL


 Description  « Hide
The new query parser does not allow bitwise operations like bitwise-and and bitwise-or.

Example:

SELECT FIRSTNAME, SURNAME FROM EMPLOYEE WHERE (STATUS & 1) > 0

The Exception is:

org.hibernate.QueryException: unexpected char: '&'

 All   Comments   Work Log   Change History   FishEye      Sort Order: Ascending order - Click to sort in descending order
Gavin King added a comment - 17/Mar/05 10:49 PM
A workaround is to define a SQLFunctionTemplate on a Dialect subclass

Daniele Gariboldi added a comment - 25/May/06 11:27 AM
I need this function too (masking permission and quering for permitted objects in one shot).
Why it can't be standardize through all the dialect ? It's just a scalar function, could be andbit(a,b) and so on (orbit , xorbit).
bit_or is another function in postgresql, of type aggregate, thus my covention.

Max Rydahl Andersen added a comment - 25/May/06 11:37 AM
it can be standardized through the dialect just like Gavin wrote.

Daniele Gariboldi added a comment - 27/May/06 06:57 AM
I vote for one standard naming convention for bitwise functions in Hibernate distribution standard dialects.
Here is how I implement bitwise function (and aggregate bitwise functions found in group by clause) for PostgreSQL 8.1, hibernate 3.1.2.
Thank you for your work, hibernate community.


import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.QueryException;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.engine.Mapping;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.type.Type;

/**
 * Implements bitwise varargs (max 4) functions for PostgreSQL. Overload bit_and
 * and bit_or functions using 1 arg as aggreagate bitwise function.
 */
public class PostgreSQLDialect extends org.hibernate.dialect.PostgreSQLDialect {
public PostgreSQLDialect() {
super();
registerFunction("bit_and", new SQLFunctionTemplates(Hibernate.INTEGER, "bit_and(?1)", "?1 & ?2 & ?3 & ?4"));
registerFunction("bit_not", new SQLFunctionTemplate(Hibernate.INTEGER, "~?1"));
registerFunction("bit_or", new SQLFunctionTemplates(Hibernate.INTEGER, "bit_or(?1)", "?1 & ?2 & ?3 & ?4"));
}

public static class SQLFunctionTemplates implements SQLFunction {
private SQLFunctionTemplate template1arg;

private SQLFunctionTemplate templateNarg;

public SQLFunctionTemplates(Type type, String template1arg, String templateNarg) {
this.template1arg = new SQLFunctionTemplate(type, template1arg);
this.templateNarg = new SQLFunctionTemplate(type, templateNarg);
}

private SQLFunctionTemplate getSQLFunctionTemplate(List args) {
if (args.size() == 1)
return template1arg;
return templateNarg;
}

public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
return template1arg.getReturnType(columnType, mapping);
}

public boolean hasArguments() {
return true;
}

public boolean hasParenthesesIfNoArguments() {
return true;
}

public String render(List args, SessionFactoryImplementor factory) throws QueryException {
return getSQLFunctionTemplate(args).render(args, factory);
}
}
}

Daniele Gariboldi added a comment - 27/May/06 07:00 AM
Sorry, error in bit_or function.
Here is the right line: (copied and pasted without changing & with |).

registerFunction("bit_or", new SQLFunctionTemplates(Hibernate.INTEGER, "bit_or(?1)", "?1 | ?2 | ?3 | ?4"));

Chris Wood added a comment - 04/Oct/06 08:36 PM
To me it makes sense to include the bitwise operators as part of the syntax, rather than as functions, because then the correct operator precidence is available.

Chris Wood added a comment - 04/Oct/06 09:24 PM
BTW: the registerFunction line for bit_and and bit_or can take advantage of org.hibernate.dialect.function.VarArgsSQLFunction.

Using this you can get rid of the inner class, and just do the following in the constructor:

    registerFunction("bit_not", new SQLFunctionTemplate(Hibernate.INTEGER, "~?1"));
    registerFunction("bit_and", new VarArgsSQLFunction(Hibernate.INTEGER, "(", "&", ")"));
    registerFunction("bit_or", new VarArgsSQLFunction(Hibernate.INTEGER, "(", "|", ")"));

Note the additional surrounding brackets, this ensures the function-like behaviour rather than using the DB's operator precidence.