AST Parser & Bitwise queries

Description

Seeing the same behavious as https://nhibernate.jira.com/browse/NH-1775#icft=NH-1775 which is closed.

Using trunk revision 4453 from 2009-06-11.

const string hql =
@"SELECT dt FROM DocumentType dt, AbstractConcept c JOIN c.ActivityGroups ag JOIN ag.Activities a JOIN a.ActivityTemplate at JOIN at.Action ac JOIN ac.Code co
WHERE dt.SystemAction & :sysAct = :sysAct AND dt.Code = co AND c = :concept";

IQuery query = ((HibernateWorkspace)
Workspace).Session.CreateQuery(hql);
query.SetMaxResults(1);
query.SetEnum("sysAct", systemAction);
query.SetEntity("concept", concept);
return query.UniqueResult<IDocumentType>();

at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.logicalExpr() in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: line 4589
at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.logicalExpr() in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: line 4585
at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.whereClause() in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: line 4419
at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.query() in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: line 1566
at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.selectStatement() in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: line 532
at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.statement() in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: line 431
at NHibernate.Hql.Ast.ANTLR.HqlSqlTranslator.Translate() in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Hql\Ast\ANTLR\QueryTranslatorImpl.cs: line 600
at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.Analyze(HqlParseEngine parser, String collectionRole) in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Hql\Ast\ANTLR\QueryTranslatorImpl.cs: line 423
at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.DoCompile(IDictionary`2 replacements, Boolean shallow, String collectionRole) in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Hql\Ast\ANTLR\QueryTranslatorImpl.cs: line 320
at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.Compile(IDictionary`2 replacements, Boolean shallow) in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Hql\Ast\ANTLR\QueryTranslatorImpl.cs: line 69
at NHibernate.Engine.Query.HQLQueryPlan..ctor(String hql, String collectionRole, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory) in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Engine\Query\HQLQueryPlan.cs: line 57
at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(String queryString, Boolean shallow, IDictionary`2 enabledFilters) in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Engine\Query\QueryPlanCache.cs: line 61
at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(String query, Boolean shallow) in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Impl\AbstractSessionImpl.cs: line 274
at NHibernate.Impl.AbstractSessionImpl.CreateQuery(String queryString) in C:\Work\EBHFinans\NHibernate2.0-src\src\NHibernate\Impl\AbstractSessionImpl.cs: line 253
at EBH.GuG.DomainModel.Impl.Concept.ConceptRepository.GetDocumentTypeBySystemAction(IConcept concept, SystemAction systemAction) in ConceptRepository.cs: line 273
at EBH.GuG.DomainModel.Impl.Concept.Tests.ConceptTests.ShouldFindDocumentTypeInConceptBasedOnSystemAction() in ConceptTestsPartial.cs: line 159

Environment

None

Activity

Show:

Carsten Hess June 15, 2009 at 12:49 AM

My workaroundcode was copied from wrong place, here is the correct one:

@"SELECT dt FROM DocumentType dt, AbstractConcept c JOIN c.ActivityGroups ag JOIN ag.Activities a JOIN a.ActivityTemplate at JOIN at.Action ac JOIN ac.Code co
WHERE (dt.SystemAction & :sysAct) = :sysAct AND dt.Code = co AND c = :concept"

Mappings:

<class name="DocumentType" table="documents_documenttype" batch-size="10">
<cache usage="nonstrict-read-write"></cache>
<id name="oid" type="System.Guid" unsaved-value="00000000-0000-0000-0000-000000000000" access="field.camelcase">
<generator class="guid.comb" />
</id>
<many-to-one name="Code" class="EBH.GuG.DomainModel.Impl.SystemAdministration.Codes.Code" access="field.camelcase" cascade="save-update" lazy="false" />
<property name="UsageFlags" access="field.camelcase"/>
<property name="LookupFrom" access="field.camelcase"/>
<property name="TrayType" access="field.camelcase"/>
<property name="RequiresCentralPrint" access="field.camelcase"/>
<property name="SaveInDokit" access="field.camelcase" />
<property name="ConceptIndependent" access="field.camelcase"/>
<property name="SystemAction" access="field.camelcase"/>
</class>

<class name="AbstractConcept" table="concepts" lazy="true" batch-size="100" dynamic-update="true" discriminator-value="SUPER">
<cache usage="nonstrict-read-write"></cache>
<id name="oid" column="concept_oid" type="System.Guid" access="field.camelcase">
<generator class="guid.comb" />
</id>
<discriminator column="discriminator" type="string" />
<property name="Name" access="field.camelcase"/>
<property name="Description" access="field.camelcase"/>
<property name="ConceptType" access="field.camelcase"/>
<property name="UsageTypes" access="field.camelcase"/>
<list name="ActivityGroups" access="field.camelcase" cascade="all-delete-orphan" lazy="true" batch-size="100" >
<cache usage="nonstrict-read-write"></cache>
<key>
<column name="concept_oid" index="concept_oid_ix"/>
</key>
<index column="activitygroup_index"/>
<one-to-many class="ActivityGroup"/>
</list>

<many-to-one name="DocumentMatrixSet" access="field.camelcase" class="EBH.GuG.DomainModel.Impl.DocumentSelection.DocumentMatrixSet" not-null="false" lazy="proxy"/>

<class name="ActivityElement" table="conceptactivityelements" batch-size="100" dynamic-update="true">
<cache usage="nonstrict-read-write"></cache>
<id name="oid" column="activityelement_oid" type="System.Guid" access="field.camelcase">
<generator class="guid.comb" />
</id>
<property name="Description" access="field.camelcase" length="2000"/>
<property name="ExpressionStr" access="field.camelcase" length="2000"/>
</class>

<joined-subclass name="Activity" table="conceptactivities" extends="ActivityElement" lazy="true" dynamic-update="true">
<key column="activity_oid" />
<property name="Delay" access="field.camelcase"/>
<property name="Elastics" access="field.camelcase"/>
<property name="IsLockedForChanges" access="field.camelcase"/>
<many-to-one name="ActivityGroup" access="field.camelcase" class="ActivityGroup" not-null="true" lazy="proxy">
<column name="activitygroup_oid" index="activitygroup_oid_ix"/>
</many-to-one>
<many-to-one name="ActivityTemplate" access="field.camelcase" class="ActivityTemplate" lazy="false"/>
</joined-subclass>

<joined-subclass name="ActivityGroup" table="conceptactivitygroups" extends="ActivityElement" lazy="true" dynamic-update="true">
<key column="activitygroup_oid" />
<property name="Category" access="field.camelcase"/>
<property name="UsageType" access="field.camelcase"/>
<property name="MustBeAuthorized" access="field.camelcase"/>
<property name="MayBeTransferredToCampaign" access="field.camelcase"/>
<many-to-one name="NextActivityGroup" access="field.camelcase" class="ActivityGroup" not-null="false" lazy="proxy"/>
<list name="Activities" access="field.camelcase" cascade="all-delete-orphan" lazy="true" batch-size="100">
<cache usage="nonstrict-read-write"></cache>
<key column="activitygroup_oid"/>
<index column="activity_index"/>
<one-to-many class="Activity"/>
</list>
<property name="Name" access="field.camelcase"/>
</joined-subclass>

<class name="ActivityTemplate" table="conceptactivitytemplates" lazy="false" dynamic-update="true">
<cache usage="nonstrict-read-write"></cache>
<id name="oid" column="activitytemplate_oid" type="System.Guid" access="field.camelcase">
<generator class="guid.comb" />
</id>
<property name="Description" access="field.camelcase" length="2000"/>
<property name="ExpressionStr" access="field.camelcase" length="2000"/>
<property name="Delay" access="field.camelcase"/>
<property name="Elastics" access="field.camelcase"/>
<many-to-one name="Action" access="field.camelcase" class="EBH.GuG.DomainModel.Impl.Concept.Actions.AbstractAction" cascade="all-delete-orphan" lazy="false"/>
<property name="ActivityFolder" access="field.camelcase"/>
<property name="Name" access="field.camelcase" />
</class>

<class name="EBH.GuG.DomainModel.Impl.Concept.Actions.AbstractAction" table="conceptactions" batch-size="100" lazy="false">
<cache usage="nonstrict-read-write"></cache>
<id name="oid" type="System.Guid" unsaved-value="00000000-0000-0000-0000-000000000000" access="field.camelcase">
<generator class="guid.comb" />
</id>
<discriminator column="actiontype" type="string"/>

<many-to-one name="Code" class="EBH.GuG.DomainModel.Impl.SystemAdministration.Codes.Code" access="field.camelcase" lazy="false" />

<subclass name="EBH.GuG.DomainModel.Impl.Concept.Actions.AutomaticLetterAction" discriminator-value="AL" lazy="true">
</subclass>
<subclass name="EBH.GuG.DomainModel.Impl.Concept.Actions.IndividualFollowUpAction" discriminator-value="IF" lazy="true">
</subclass>
</class>

<class name="Code" table="code" lazy="true" batch-size="100">
<cache usage="nonstrict-read-write"/>
<id name="oid" type="System.Guid" unsaved-value="00000000-0000-0000-0000-000000000000" access="field.camelcase">
<generator class="guid.comb" />
</id>

<property name="GroupType" access="field.camelcase" index="grouptype_ix" />
<property name="Locked" access="field.camelcase" />
<property name="Name" access="field.camelcase" />
<property name="Description" access="field.camelcase" />
<property name="Number" access="field.camelcase" />
<component name="Amount" class="EBH.GuG.Util.CommonTypes.Money, EBH.GuG.Util.CommonTypes" access="field.camelcase">
<property name="Amount" column="amount" access="field.camelcase"/>
<property name="CurrencyAsStr" column="currency"/>
</component>
<property name="Text" access="field.camelcase" length="2000" />

<!-- ITrackChanges properties -->
<property name="Created" access="field.camelcase" />
<property name="CreatedBy" access="field.camelcase" />
<property name="LastEdited" access="field.camelcase" />
<property name="LastEditedBy" access="field.camelcase" />

</class>

Classes:
internal class DocumentType : Entity, IDocumentType
{
DocumentUsageFlags usageFlags;
SystemAction systemAction = 0;
ICode code;
LookupFrom lookupFrom;
TrayType trayType;
bool requiresCentralPrint;
private bool saveInDokit;
bool conceptIndependent;

public abstract class AbstractConcept : Entity, IConcept
{
private IList<IActivityGroup> activityGroups = new List<IActivityGroup>();
private string name;
private string description;
private IDocumentMatrixSet documentMatrixSet;
private ConceptType conceptType;
private ActivityGroupUsageType usageTypes;

public class ActivityGroup : ActivityElement, IActivityGroup
{
private string name;
private ActivityGroupCategory category = ActivityGroupCategory.Normal;
private IList<Activity> activities = new List<Activity>();
private ActivityGroup nextActivityGroup;
private ILog log = LogManager.GetLogger(typeof(ActivityGroup));
private bool mustBeAuthorized;
private ActivityGroupUsageType? usageType;

public class Activity : ActivityElement, IActivity
{
private ActivityGroup activityGroup;
private int delay;
private int elastics;
private IActivityTemplate activityTemplate;
private bool isLockedForChanges = true;

public class ActivityTemplate : Entity, IActivityTemplate
{
private string description;
private int delay;
private int elastics;
private string expressionStr;
private IAction action;
private string activityFolder;
private string name;

public class Code : EntityTrackChanges, ICode
{
private bool locked;
private string name;
private string description;
private int? number;
private Money amount;
private string text;
private CodeGroupTypes groupType;

[Flags]
[Serializable]
public enum SystemAction : long
{
P10 = 0x01 << 0,
Denunciation = 0x01 << 1,
WarnedOfInterest = 0x01 << 2,
Individual = 0x01 << 3,
...

Fabio Maulo June 11, 2009 at 11:04 AM

Carsten, please provide, at least, classes and mappings please.
Thanks.

Carsten Hess June 11, 2009 at 8:36 AM

The exception which is thrown is: System.InvalidCastException : Unable to cast object of type 'Antlr.Runtime.Tree.CommonTree' to type 'NHibernate.Hql.Ast.ANTLR.Tree.IASTNode'.

Luckily it can be work-arounded by adding paranthesis to the bitwise or expression:

HibernateWorkspace ws = (HibernateWorkspace)Workspace;
IQuery query = ws.Session.CreateQuery("FROM DocumentType dt WHERE (dt.SystemAction & :dt_Action) = :dt_Action");
query.SetParameter("dt_Action", action);
return query.List<IDocumentType>();

Carsten Hess June 11, 2009 at 4:15 AM

:sysAct is a flagged enum:

[Flags]
[Serializable]
public enum SystemAction : long
{
P10 = 0x01 << 0,
Denunciation = 0x01 << 1,
WarnedOfInterest = 0x01 << 2,
Individual = 0x01 << 3,
...

Fixed

Details

Assignee

Reporter

Components

Fix versions

Affects versions

Priority

Who's Looking?

Open Who's Looking?
Created June 11, 2009 at 4:05 AM
Updated October 2, 2013 at 8:57 AM
Resolved June 19, 2009 at 9:11 PM
Who's Looking?