Skip to content

Remove ConstantConverter #3395

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 0 additions & 51 deletions src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -547,64 +547,13 @@ public IASTNode Parse()
try
{
var ast = (IASTNode) parser.statement().Tree;

var walker = new NodeTraverser(new ConstantConverter(_sfi));
walker.TraverseDepthFirst(ast);

return ast;
}
finally
{
parser.ParseErrorHandler.ThrowQueryException();
}
}

class ConstantConverter : IVisitationStrategy
{
private IASTNode _dotRoot;
private readonly ISessionFactoryImplementor _sfi;

public ConstantConverter(ISessionFactoryImplementor sfi)
{
_sfi = sfi;
}

public void Visit(IASTNode node)
{
if (_dotRoot != null)
{
// we are already processing a dot-structure
if (ASTUtil.IsSubtreeChild(_dotRoot, node))
{
// ignore it...
return;
}

// we are now at a new tree level
_dotRoot = null;
}

if (_dotRoot == null && node.Type == HqlSqlWalker.DOT)
{
_dotRoot = node;
HandleDotStructure(_dotRoot);
}
}

private void HandleDotStructure(IASTNode dotStructureRoot)
{
var expression = ASTUtil.GetPathText(dotStructureRoot);

var constant = ReflectHelper.GetConstantValue(expression, _sfi);

if (constant != null)
{
dotStructureRoot.ClearChildren();
dotStructureRoot.Type = HqlSqlWalker.JAVA_CONSTANT;
dotStructureRoot.Text = expression;
}
}
}
}

internal class HqlSqlTranslator
Expand Down
28 changes: 26 additions & 2 deletions src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace NHibernate.Hql.Ast.ANTLR.Tree
/// Ported by: Steve Strong
/// </summary>
[CLSCompliant(false)]
public class DotNode : FromReferenceNode
public class DotNode : FromReferenceNode, IExpectedTypeAwareNode
{
private static readonly INHibernateLogger Log = NHibernateLogger.For(typeof(DotNode));

Expand Down Expand Up @@ -72,6 +72,8 @@ public class DotNode : FromReferenceNode
/// </summary>
private JoinType _joinType = JoinType.InnerJoin;

private object _constantValue;

public DotNode(IToken token) : base(token)
{
}
Expand Down Expand Up @@ -287,11 +289,14 @@ private IType GetDataType()
return DataType;
}

public void SetResolvedConstant(string text)
public void SetResolvedConstant(string text) => SetResolvedConstant(text, null);

public void SetResolvedConstant(string text, object value)
{
_path = text;
_dereferenceType = DerefJavaConstant;
IsResolved = true; // Don't resolve the node again.
_constantValue = value;
}

private static QueryException BuildIllegalCollectionDereferenceException(string propertyName, IASTNode lhs)
Expand Down Expand Up @@ -772,5 +777,24 @@ public void ResolveSelectExpression()
lhs = (FromReferenceNode)lhs.GetChild(0);
}
}

public IType ExpectedType
{
get => DataType;
set
{
if (Type != HqlSqlWalker.JAVA_CONSTANT)
return;

DataType = value;
}
}

public override SqlString RenderText(ISessionFactoryImplementor sessionFactory)
{
return Type == HqlSqlWalker.JAVA_CONSTANT
? JavaConstantNode.ResolveToLiteralString(DataType, _constantValue, sessionFactory.Dialect)
: base.RenderText(sessionFactory);
}
}
}
37 changes: 20 additions & 17 deletions src/NHibernate/Hql/Ast/ANTLR/Tree/JavaConstantNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,30 @@ public ISessionFactoryImplementor SessionFactory
set { _factory = value; }
}

public override SqlString RenderText(ISessionFactoryImplementor sessionFactory)
{
ProcessText();
public override SqlString RenderText(ISessionFactoryImplementor sessionFactory)
{
ProcessText();

IType type = _expectedType ?? _heuristicType;
return new SqlString(ResolveToLiteralString( type ));
return ResolveToLiteralString(type);
}

private string ResolveToLiteralString(IType type)
{
try
{
ILiteralType literalType = (ILiteralType)type;
Dialect.Dialect dialect = _factory.Dialect;
return literalType.ObjectToSQLString(_constantValue, dialect);
}
catch (Exception t)
{
throw new QueryException(LiteralProcessor.ErrorCannotFormatLiteral + Text, t);
}
}
private SqlString ResolveToLiteralString(IType type)
{
return ResolveToLiteralString(type, _constantValue, _factory.Dialect);
}

internal static SqlString ResolveToLiteralString(IType type, object constantValue, Dialect.Dialect dialect)
{
try
{
return new SqlString(((ILiteralType) type).ObjectToSQLString(constantValue, dialect));
}
catch (Exception t)
{
throw new QueryException(LiteralProcessor.ErrorCannotFormatLiteral + constantValue, t);
}
}

private void ProcessText()
{
Expand Down
74 changes: 5 additions & 69 deletions src/NHibernate/Hql/Ast/ANTLR/Util/LiteralProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public void LookupConstant(DotNode node)
}
else
{
Object value = ReflectHelper.GetConstantValue(text);
var value = ReflectHelper.GetConstantValue(text, _walker.SessionFactoryHelper.Factory);
if (value == null)
{
throw new InvalidPathException("Invalid path: '" + text + "'");
Expand Down Expand Up @@ -149,6 +149,7 @@ public void ProcessConstant(SqlNode constant, bool resolveIdent)
if (isIdent && queryable != null)
{
constant.Text = queryable.DiscriminatorSQLValue;
constant.DataType = queryable.DiscriminatorType;
}
// Otherwise, it's a literal.
else
Expand Down Expand Up @@ -275,74 +276,9 @@ private void SetConstantValue(DotNode node, string text, object value)

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);
node.Type = HqlSqlWalker.JAVA_CONSTANT;
node.DataType = TypeFactory.HeuristicType(value.GetType().Name);
node.SetResolvedConstant(text, value);
}

interface IDecimalFormatter
Expand Down
25 changes: 6 additions & 19 deletions src/NHibernate/Util/ReflectHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -820,31 +820,18 @@ private static MethodInfo SafeGetMethod(System.Type type, MethodInfo method, Sys
return foundMethod;
}

internal static object GetConstantValue(string qualifiedName)
{
return GetConstantValue(qualifiedName, null);
}

internal static object GetConstantValue(string qualifiedName, ISessionFactoryImplementor sfi)
{
string className = StringHelper.Qualifier(qualifiedName);

if (!string.IsNullOrEmpty(className))
{
System.Type t = System.Type.GetType(className);

if (t == null && sfi != null)
{
t = System.Type.GetType(sfi.GetImportedClassName(className));
}
if (string.IsNullOrEmpty(className))
return null;

if (t != null)
{
return GetConstantValue(t, StringHelper.Unqualify(qualifiedName));
}
}
var t = System.Type.GetType(sfi?.GetImportedClassName(className) ?? className);

return null;
return t == null
? null
: GetConstantValue(t, StringHelper.Unqualify(qualifiedName));
}

// Since v5
Expand Down