public void LookupConstant(DotNode node) { string text = ASTUtil.GetPathText(node); IQueryable persister = _walker.SessionFactoryHelper.FindQueryableUsingImports(text); if (persister != null) { // the name of an entity class string discrim = persister.DiscriminatorSQLValue; node.DataType = persister.DiscriminatorType; if (InFragment.Null == discrim || InFragment.NotNull == discrim) { throw new InvalidPathException("subclass test not allowed for null or not null discriminator: '" + text + "'"); } else { SetSQLValue(node, text, discrim); //the class discriminator value } } else { Object value = ReflectHelper.GetConstantValue(text); if (value == null) { throw new InvalidPathException("Invalid path: '" + text + "'"); } else { SetConstantValue(node, text, value); } } }
private bool ResolveAsNakedComponentPropertyRefLhs(DotNode parent) { FromElement fromElement = LocateSingleFromElement(); if (fromElement == null) { return(false); } IType componentType = GetNakedPropertyType(fromElement); if (componentType == null) { throw new QueryException("Unable to resolve path [" + parent.Path + "], unexpected token [" + OriginalText + "]"); } if (!componentType.IsComponentType) { throw new QueryException("Property '" + OriginalText + "' is not a component. Use an alias to reference associations or collections."); } IType propertyType; // used to set the type of the parent dot node string propertyPath = Text + "." + NextSibling.Text; try { // check to see if our "propPath" actually // represents a property on the persister propertyType = fromElement.GetPropertyType(Text, propertyPath); } catch (Exception) { // assume we do *not* refer to a property on the given persister return(false); } FromElement = fromElement; parent.PropertyPath = propertyPath; parent.DataType = propertyType; return(true); }
private void DereferenceEntityIdentifier(string propertyName, DotNode dotParent) { // special shortcut for id properties, skip the join! // this must only occur at the _end_ of a path expression if (Log.IsDebugEnabled) { Log.Debug("dereferenceShortcut() : property " + propertyName + " in " + FromElement.ClassName + " does not require a join."); } InitText(); SetPropertyNameAndPath(dotParent); // Set the unresolved path in this node and the parent. // Set the text for the parent. if (dotParent != null) { dotParent._dereferenceType = DerefIdentifier; dotParent.Text = Text; dotParent._columns = GetColumns(); } }
private void SetPropertyNameAndPath(IASTNode parent) { if (IsDotNode(parent)) { DotNode dotNode = (DotNode)parent; IASTNode rhs = dotNode.GetChild(1); _propertyName = rhs.Text; _propertyPath = _propertyPath + "." + _propertyName; // Append the new property name onto the unresolved path. dotNode._propertyPath = _propertyPath; if (Log.IsDebugEnabled) { Log.Debug("Unresolved property path is now '" + dotNode._propertyPath + "'"); } } else { if (Log.IsDebugEnabled) { Log.Debug("terminal propertyPath = [" + _propertyPath + "]"); } } }
private void SetConstantValue(DotNode node, string text, object value) { if (log.IsDebugEnabled) { log.Debug("setConstantValue() " + text + " -> " + value + " " + value.GetType().Name); } node.ClearChildren(); // Chop off the rest of the tree. if (value is string) { node.Type = HqlSqlWalker.QUOTED_String; } else if (value is char) { node.Type = HqlSqlWalker.QUOTED_String; } else if (value is byte) { node.Type = HqlSqlWalker.NUM_INT; } else if (value is short) { node.Type = HqlSqlWalker.NUM_INT; } else if (value is int) { node.Type = HqlSqlWalker.NUM_INT; } else if (value is long) { node.Type = HqlSqlWalker.NUM_LONG; } else if (value is double) { node.Type = HqlSqlWalker.NUM_DOUBLE; } else if (value is decimal) { node.Type = HqlSqlWalker.NUM_DECIMAL; } else if (value is float) { node.Type = HqlSqlWalker.NUM_FLOAT; } else { node.Type = HqlSqlWalker.CONSTANT; } IType type; try { type = TypeFactory.HeuristicType(value.GetType().Name); } catch (MappingException me) { throw new QueryException(me); } if (type == null) { throw new QueryException(LiteralProcessor.ErrorCannotDetermineType + node.Text); } try { ILiteralType literalType = (ILiteralType)type; NHibernate.Dialect.Dialect dialect = _walker.SessionFactoryHelper.Factory.Dialect; node.Text = literalType.ObjectToSQLString(value, dialect); } catch (Exception e) { throw new QueryException(LiteralProcessor.ErrorCannotFormatLiteral + node.Text, e); } node.DataType = type; node.SetResolvedConstant(text); }
private static void SetSQLValue(DotNode node, string text, string value) { if (log.IsDebugEnabled) { log.Debug("setSQLValue() " + text + " -> " + value); } node.ClearChildren(); // Chop off the rest of the tree. node.Type = HqlSqlWalker.SQL_TOKEN; node.Text = value; node.SetResolvedConstant(text); }
private void DereferenceEntity(EntityType entityType, bool implicitJoin, string classAlias, bool generateJoin, IASTNode parent) { CheckForCorrelatedSubquery("dereferenceEntity"); // three general cases we check here as to whether to render a physical SQL join: // 1) is our parent a DotNode as well? If so, our property reference is // being further de-referenced... // 2) is this a DML statement // 3) we were asked to generate any needed joins (generateJoins==true) *OR* // we are currently processing a select or from clause // (an additional check is the REGRESSION_STYLE_JOIN_SUPPRESSION check solely intended for the test suite) // // The REGRESSION_STYLE_JOIN_SUPPRESSION is an additional check // intended solely for use within the test suite. This forces the // implicit join resolution to behave more like the classic parser. // The underlying issue is that classic translator is simply wrong // about its decisions on whether or not to render an implicit join // into a physical SQL join in a lot of cases. The piece it generally // tends to miss is that INNER joins effect the results by further // restricting the data set! A particular manifestation of this is // the fact that the classic translator will skip the physical join // for ToOne implicit joins *if the query is shallow*; the result // being that Query.list() and Query.iterate() could return // different number of results! DotNode parentAsDotNode = null; string property = _propertyName; bool joinIsNeeded; if (IsDotNode(parent)) { // our parent is another dot node, meaning we are being further dereferenced. // thus we need to generate a join unless the parent refers to the associated // entity's PK (because 'our' table would know the FK). parentAsDotNode = ( DotNode )parent; property = parentAsDotNode._propertyName; joinIsNeeded = generateJoin && !IsReferenceToPrimaryKey(parentAsDotNode._propertyName, entityType); } else if (!Walker.IsSelectStatement) { // in non-select queries, the only time we should need to join is if we are in a subquery from clause joinIsNeeded = Walker.CurrentStatementType == HqlSqlWalker.SELECT && Walker.IsInFrom; } else if (REGRESSION_STYLE_JOIN_SUPPRESSION) { // this is the regression style determination which matches the logic of the classic translator joinIsNeeded = generateJoin && (!Walker.IsInSelect || !Walker.IsShallowQuery); } else { joinIsNeeded = generateJoin || (Walker.IsInSelect || Walker.IsInFrom); } if (joinIsNeeded) { DereferenceEntityJoin(classAlias, entityType, implicitJoin, parent); } else { DereferenceEntityIdentifier(property, parentAsDotNode); } }
public override object Create(IToken payload) { if (payload == null) { return base.Create(payload); } object ret; switch (payload.Type) { case HqlSqlWalker.SELECT: case HqlSqlWalker.QUERY: ret = new QueryNode(payload); break; case HqlSqlWalker.UPDATE: ret = new UpdateStatement(payload); break; case HqlSqlWalker.DELETE: ret = new DeleteStatement(payload); break; case HqlSqlWalker.INSERT: ret = new InsertStatement(payload); break; case HqlSqlWalker.INTO: ret = new IntoClause(payload); break; case HqlSqlWalker.FROM: ret = new FromClause(payload); break; case HqlSqlWalker.FROM_FRAGMENT: ret = new FromElement(payload); break; case HqlSqlWalker.IMPLIED_FROM: ret = new ImpliedFromElement(payload); break; case HqlSqlWalker.DOT: ret = new DotNode(payload); break; case HqlSqlWalker.INDEX_OP: ret = new IndexNode(payload); break; // Alias references and identifiers use the same node class. case HqlSqlWalker.ALIAS_REF: case HqlSqlWalker.IDENT: ret = new IdentNode(payload); break; case HqlSqlWalker.SQL_TOKEN: ret = new SqlFragment(payload); break; case HqlSqlWalker.METHOD_CALL: ret = new MethodNode(payload); break; case HqlSqlWalker.ELEMENTS: case HqlSqlWalker.INDICES: ret = new CollectionFunction(payload); break; case HqlSqlWalker.SELECT_CLAUSE: ret = new SelectClause(payload); break; case HqlSqlWalker.SELECT_EXPR: ret = new SelectExpressionImpl(payload); break; case HqlSqlWalker.AGGREGATE: ret = new AggregateNode(payload); break; case HqlSqlWalker.COUNT: ret = new CountNode(payload); break; case HqlSqlWalker.CONSTRUCTOR: ret = new ConstructorNode(payload); break; case HqlSqlWalker.NUM_INT: case HqlSqlWalker.NUM_FLOAT: case HqlSqlWalker.NUM_LONG: case HqlSqlWalker.NUM_DOUBLE: case HqlSqlWalker.NUM_DECIMAL: case HqlSqlWalker.QUOTED_String: ret = new LiteralNode(payload); break; case HqlSqlWalker.TRUE: case HqlSqlWalker.FALSE: ret = new BooleanLiteralNode(payload); break; case HqlSqlWalker.JAVA_CONSTANT: ret = new JavaConstantNode(payload); break; case HqlSqlWalker.ORDER: ret = new OrderByClause(payload); break; case HqlSqlWalker.PLUS: case HqlSqlWalker.MINUS: case HqlSqlWalker.STAR: case HqlSqlWalker.DIV: case HqlSqlWalker.BAND: case HqlSqlWalker.BOR: case HqlSqlWalker.BXOR: ret = new BinaryArithmeticOperatorNode(payload); break; case HqlSqlWalker.UNARY_MINUS: case HqlSqlWalker.UNARY_PLUS: case HqlSqlWalker.BNOT: ret = new UnaryArithmeticNode(payload); break; case HqlSqlWalker.CASE2: ret = new Case2Node(payload); break; case HqlSqlWalker.CASE: ret = new CaseNode(payload); break; case HqlSqlWalker.PARAM: case HqlSqlWalker.NAMED_PARAM: ret = new ParameterNode(payload); break; case HqlSqlWalker.EQ: case HqlSqlWalker.NE: case HqlSqlWalker.LT: case HqlSqlWalker.GT: case HqlSqlWalker.LE: case HqlSqlWalker.GE: case HqlSqlWalker.LIKE: case HqlSqlWalker.NOT_LIKE: ret = new BinaryLogicOperatorNode(payload); break; case HqlSqlWalker.IN: case HqlSqlWalker.NOT_IN: ret = new InLogicOperatorNode(payload); break; case HqlSqlWalker.BETWEEN: case HqlSqlWalker.NOT_BETWEEN: ret = new BetweenOperatorNode(payload); break; case HqlSqlWalker.IS_NULL: ret = new IsNullLogicOperatorNode(payload); break; case HqlSqlWalker.IS_NOT_NULL: ret = new IsNotNullLogicOperatorNode(payload); break; case HqlSqlWalker.EXISTS: ret = new UnaryLogicOperatorNode(payload); break; default: ret = new SqlNode(payload); break; } Initialise(ret); return ret; }
private void DereferenceEntityIdentifier(string propertyName, DotNode dotParent) { // special shortcut for id properties, skip the join! // this must only occur at the _end_ of a path expression if (Log.IsDebugEnabled) { Log.Debug("dereferenceShortcut() : property " + propertyName + " in " + FromElement.ClassName + " does not require a join."); } InitText(); SetPropertyNameAndPath(dotParent); // Set the unresolved path in this node and the parent. // Set the text for the parent. if (dotParent != null) { dotParent._dereferenceType = DerefIdentifier; dotParent.Text = Text; dotParent._columns = GetColumns(); } }
public override void Resolve(bool generateJoin, bool implicitJoin, string classAlias, IASTNode parent) { if (!IsResolved) { if (Walker.CurrentFromClause.IsFromElementAlias(Text)) { if (ResolveAsAlias()) { IsResolved = true; // We represent a from-clause alias } } else if (parent != null && parent.Type == HqlSqlWalker.DOT) { DotNode dot = (DotNode)parent; if (parent.GetFirstChild() == this) { if (ResolveAsNakedComponentPropertyRefLhs(dot)) { // we are the LHS of the DOT representing a naked comp-prop-ref IsResolved = true; } } else { if (ResolveAsNakedComponentPropertyRefRhs(dot)) { // we are the RHS of the DOT representing a naked comp-prop-ref IsResolved = true; } } } else { int result = ResolveAsNakedPropertyRef(); if (result == PropertyRef) { // we represent a naked (simple) prop-ref IsResolved = true; } else if (result == ComponentRef) { // EARLY EXIT!!! return so the resolve call explicitly coming from DotNode can // resolve this... return; } } // if we are still not resolved, we might represent a constant. // needed to add this here because the allowance of // naked-prop-refs in the grammar collides with the // definition of literals/constants ("nondeterminism"). // TODO: cleanup the grammar so that "processConstants" is always just handled from here if (!IsResolved) { try { Walker.LiteralProcessor.ProcessConstant(this, false); } catch (Exception) { // just ignore it for now, it'll get resolved later... } } } }
public override object Create(IToken payload) { if (payload == null) { return(base.Create(payload)); } object ret; switch (payload.Type) { case HqlSqlWalker.SELECT: case HqlSqlWalker.QUERY: ret = new QueryNode(payload); break; case HqlSqlWalker.UPDATE: ret = new UpdateStatement(payload); break; case HqlSqlWalker.DELETE: ret = new DeleteStatement(payload); break; case HqlSqlWalker.INSERT: ret = new InsertStatement(payload); break; case HqlSqlWalker.INTO: ret = new IntoClause(payload); break; case HqlSqlWalker.FROM: ret = new FromClause(payload); break; case HqlSqlWalker.FROM_FRAGMENT: ret = new FromElement(payload); break; case HqlSqlWalker.IMPLIED_FROM: ret = new ImpliedFromElement(payload); break; case HqlSqlWalker.DOT: ret = new DotNode(payload); break; case HqlSqlWalker.INDEX_OP: ret = new IndexNode(payload); break; // Alias references and identifiers use the same node class. case HqlSqlWalker.ALIAS_REF: case HqlSqlWalker.IDENT: ret = new IdentNode(payload); break; case HqlSqlWalker.SQL_TOKEN: ret = new SqlFragment(payload); break; case HqlSqlWalker.METHOD_CALL: ret = new MethodNode(payload); break; case HqlSqlWalker.ELEMENTS: case HqlSqlWalker.INDICES: ret = new CollectionFunction(payload); break; case HqlSqlWalker.SELECT_CLAUSE: ret = new SelectClause(payload); break; case HqlSqlWalker.SELECT_EXPR: ret = new SelectExpressionImpl(payload); break; case HqlSqlWalker.AGGREGATE: ret = new AggregateNode(payload); break; case HqlSqlWalker.COUNT: ret = new CountNode(payload); break; case HqlSqlWalker.CONSTRUCTOR: ret = new ConstructorNode(payload); break; case HqlSqlWalker.NUM_INT: case HqlSqlWalker.NUM_FLOAT: case HqlSqlWalker.NUM_LONG: case HqlSqlWalker.NUM_DOUBLE: case HqlSqlWalker.QUOTED_String: ret = new LiteralNode(payload); break; case HqlSqlWalker.TRUE: case HqlSqlWalker.FALSE: ret = new BooleanLiteralNode(payload); break; case HqlSqlWalker.JAVA_CONSTANT: ret = new JavaConstantNode(payload); break; case HqlSqlWalker.ORDER: ret = new OrderByClause(payload); break; case HqlSqlWalker.PLUS: case HqlSqlWalker.MINUS: case HqlSqlWalker.STAR: case HqlSqlWalker.DIV: case HqlSqlWalker.BAND: case HqlSqlWalker.BOR: case HqlSqlWalker.BXOR: ret = new BinaryArithmeticOperatorNode(payload); break; case HqlSqlWalker.UNARY_MINUS: case HqlSqlWalker.UNARY_PLUS: case HqlSqlWalker.BNOT: ret = new UnaryArithmeticNode(payload); break; case HqlSqlWalker.CASE2: ret = new Case2Node(payload); break; case HqlSqlWalker.CASE: ret = new CaseNode(payload); break; case HqlSqlWalker.PARAM: case HqlSqlWalker.NAMED_PARAM: ret = new ParameterNode(payload); break; case HqlSqlWalker.EQ: case HqlSqlWalker.NE: case HqlSqlWalker.LT: case HqlSqlWalker.GT: case HqlSqlWalker.LE: case HqlSqlWalker.GE: case HqlSqlWalker.LIKE: case HqlSqlWalker.NOT_LIKE: ret = new BinaryLogicOperatorNode(payload); break; case HqlSqlWalker.IN: case HqlSqlWalker.NOT_IN: ret = new InLogicOperatorNode(payload); break; case HqlSqlWalker.BETWEEN: case HqlSqlWalker.NOT_BETWEEN: ret = new BetweenOperatorNode(payload); break; case HqlSqlWalker.IS_NULL: ret = new IsNullLogicOperatorNode(payload); break; case HqlSqlWalker.IS_NOT_NULL: ret = new IsNotNullLogicOperatorNode(payload); break; case HqlSqlWalker.EXISTS: ret = new UnaryLogicOperatorNode(payload); break; default: ret = new SqlNode(payload); break; } Initialise(ret); return(ret); }
private static void PrepareAnyImplicitJoins(DotNode dotNode) { if ( dotNode.GetLhs() is DotNode ) { DotNode lhs = ( DotNode ) dotNode.GetLhs(); FromElement lhsOrigin = lhs.FromElement; if ( lhsOrigin != null && "" == lhsOrigin.Text ) { String lhsOriginText = lhsOrigin.Queryable.TableName + " " + lhsOrigin.TableAlias; lhsOrigin.Text = lhsOriginText; } PrepareAnyImplicitJoins( lhs ); } }
private bool ResolveAsNakedComponentPropertyRefRhs(DotNode parent) { FromElement fromElement = LocateSingleFromElement(); if (fromElement == null) { return false; } IType propertyType; string propertyPath = parent.GetLhs().Text + "." + Text; try { // check to see if our "propPath" actually // represents a property on the persister propertyType = fromElement.GetPropertyType(Text, propertyPath); } catch (Exception) { // assume we do *not* refer to a property on the given persister return false; } FromElement = fromElement; // this piece is needed for usage in select clause DataType = propertyType; _nakedPropertyRef = true; return true; }
private bool ResolveAsNakedComponentPropertyRefLhs(DotNode parent) { FromElement fromElement = LocateSingleFromElement(); if (fromElement == null) { return false; } IType componentType = GetNakedPropertyType(fromElement); if (componentType == null) { throw new QueryException("Unable to resolve path [" + parent.Path + "], unexpected token [" + OriginalText + "]"); } if (!componentType.IsComponentType) { throw new QueryException("Property '" + OriginalText + "' is not a component. Use an alias to reference associations or collections."); } IType propertyType ; // used to set the type of the parent dot node string propertyPath = Text + "." + NextSibling.Text; try { // check to see if our "propPath" actually // represents a property on the persister propertyType = fromElement.GetPropertyType(Text, propertyPath); } catch (Exception) { // assume we do *not* refer to a property on the given persister return false; } FromElement = fromElement; parent.PropertyPath = propertyPath; parent.DataType = propertyType; return true; }