-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Convert HQL to SQL?
PostPosted: Thu Mar 22, 2007 2:27 pm 
Newbie

Joined: Tue Mar 20, 2007 4:38 pm
Posts: 3
Location: Gainesville, FL
Hi all,
I currently have an HQL query that I use to query my database for a result set. It is a generated query based off of what could be a little or a lot of user interaction (in all actuality it is a search query that is generated by a user). The problem lies in that I need to use this query as a base in an update, insert, and delete (merge) function. Being a search query it could effect several 100 thousand records. From my understanding of NHibernate and the way our system is designed, it appears that this will generate more overhead than we want in our system (using NHibernate to do the merge that is).

My ideal solution would be to give some function the base HQL for the merge function, have it converted as NHibernate would (our product can run on various DBs), and then store it for a system agent. This system agent could then use this SQL as a base to do this merge function all batched up like. Does NHibernate expose this functionality by default? As a requirement for our system we do not wish to edit the source of NHibernate. I know NHibernate must translate the query to SQL, but I'm kind of leaning towards that this functionality is not exposed to implementers.

If this is not exposed (again I have a feeling that it is not) is there a way that I can use some code from NHibernates source inside our project to provide a method that I can pass a string of HQL to and get back a string of SQL. That might be a round-about way of doing things since I'm sure that it isn't that easy (dialects have to be included somewhere).

Any help in this regards would be great. Several other methods, such as catching the query at the database, just don't look as if they're acceptable. I was mostly hoping that there was something already available to developers that I could use.

Thanks!

Mike


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 22, 2007 6:03 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
For diagnostic purposes only, we use this hack (NHibernate 1.20):
Code:
public string ToSql(string hqlQueryText)
{
    string sqlText = String.Empty;

    if (!string.IsNullOrEmpty(hqlQueryText))
    {
        IDictionary enabledFilters = new Hashtable();

        NHibernate.Hql.Classic.QueryTranslator translator =
            new NHibernate.Hql.Classic.QueryTranslator(
                (NHibernate.Engine.ISessionFactoryImplementor) YourSessionFactory,
                hqlQueryText,
                enabledFilters);

        translator.Compile(
            YourReplacements,
            false);

        // Aaargh, the property we want is protected ...
        // get at it through reflection

        sqlText = GetPropertyValue(translator, "SqlString").ToString();
    }

    return sqlText;
}

public PropertyInfo GetProperty(object instance, string propertyName)
{
    ocArgumentHelper.RequireValue("instance", instance);
    ocArgumentHelper.RequireValue("propertyName", propertyName);

    Type searchType = instance.GetType();
    return GetProperty(searchType, propertyName, BindingFlags.Instance);
}

public PropertyInfo GetProperty(Type searchType, string propertyName)
{
    return GetProperty(searchType, propertyName, BindingFlags.Instance);
}

public PropertyInfo GetProperty(Type searchType, string propertyName, BindingFlags bindingFlags)
{
    bindingFlags |= BindingFlags.Public;
    bindingFlags |= BindingFlags.NonPublic;
    bindingFlags |= BindingFlags.DeclaredOnly;

    while (searchType != null)
    {
        foreach (PropertyInfo property in searchType.GetProperties(bindingFlags))
        {
            if (property.Name == propertyName)
            {
                return property;
            }
        }

        if (searchType.IsInterface)
        {
            PropertyInfo inheritedInterfaceProperty;
            foreach (Type subInterfaceType in searchType.GetInterfaces())
            {
                inheritedInterfaceProperty = GetProperty(
                    subInterfaceType, propertyName, bindingFlags);

                if (inheritedInterfaceProperty != null)
                {
                    return inheritedInterfaceProperty;
                }
            }
        }
        else
        {
            searchType = searchType.BaseType;
        }
    }

    return null;
}

public object GetPropertyValue(object instance, string propertyName)
{
PropertyInfo property = GetProperty(instance.GetType(), propertyName, BindingFlags.Instance);
if (property == null)
{
    throw new MissingMemberException(instance.GetType().Name, propertyName);
}

return property.GetValue(instance, null);
}



Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 22, 2007 6:57 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
BTW, we use this to reformat the SQL so that it's readable:

Code:
public string FormatSql(string sqlText)
{
    string NL = Environment.NewLine;

    string formattedSqlText = sqlText
        .Replace("select ",                       "SELECT           ")
        .Replace(" as ",                          " AS "            )
        .Replace(",",                 "," +  NL + "                ")
        .Replace(" from ",                   NL + "FROM             ")
        .Replace(" left join ",              NL + "LEFT JOIN        ")
        .Replace(" left outer join ",        NL + "LEFT OUTER JOIN  ")
        .Replace(" inner join ",             NL + "INNER JOIN       ")
        .Replace(" on ",                          " ON ")
        .Replace(" where ",                  NL + "WHERE            ")
        .Replace(")OR(",                          ") OR ("           )
        .Replace(")AND(",                         ") AND ("          )
        .Replace(" AND ",                    NL + "AND              ")
        .Replace(" group by ",               NL + "GROUP BY         ")
        .Replace(" having ",                 NL + "HAVING           ")
        .Replace(" order by ",               NL + "ORDER BY        ");

    return formattedSqlText;
}


Top
 Profile  
 
 Post subject: Thanks!
PostPosted: Fri Mar 23, 2007 9:03 am 
Newbie

Joined: Tue Mar 20, 2007 4:38 pm
Posts: 3
Location: Gainesville, FL
Thanks for that bit of code. I haven't implemented it yet, but it gives me a great start. I don't know how many times I looked over the NHibernate namespace and never thought to look in the classic sub namespace. I found the interface for IQueryTraslator, but just didn't see that an implementing class was there. Thanks again!


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 16, 2007 1:02 am 
Beginner
Beginner

Joined: Fri Jan 12, 2007 1:08 am
Posts: 41
This method is great but the HQL parameters are not converted. Does anyone know how to convert these too?

Actually ignore that. The parameter that I was looking at contained invalid HQL but an error was not being thrown.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.