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

Participants: Chris Wood, Daniele Gariboldi, Gavin King, Markus Jessenitschnig and Max Rydahl Andersen


 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: '&'



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.