Hello!
Trying to create a having cluse with the criteria interface after
reading this
http://nhjira.koah.net/browse/NH-1280.
I want to extend the having cluse using ISqlFunctions:
ISQLFunction arithmaticAddition = new VarArgsSQLFunction("(",
"+", ")");
ISQLFunction arithmaticSubstract = new VarArgsSQLFunction("(",
"-", ")");
to generate a having clause like this:
having dbo.Hour((max(Time + dbo.Minute(Length)) - min(Time))) > 7) as
lectureInner
Maybe I am doing wrong but seems to be a problem when nesting
projections.
I have created a relevant testcase, according to the NhForge HowTo.
See code and mappings below.
Regards
Cws
Code:
PropertyProjection length = Projections.GroupProperty("Length");
IProjection dateOnly = Projections.SqlFunction
("DateOnly", NHibernateUtil.DateTime, time);
IProjection inner1 = Projections.Max
(Projections.SqlFunction(arithmaticAddition, NHibernateUtil.DateTime,
time, length));
IProjection inner2 = Projections.Min(time);
IProjection inner = Projections.SqlFunction
(arithmaticSubstract, NHibernateUtil.DateTime, inner1, inner2);
IProjection hour = Projections.SqlFunction("Hour",
NHibernateUtil.Int32, inner);
ICriteria criteria = session.CreateCriteria(typeof
(Lecture))
.SetProjection(dateOnly)
.Add(Restrictions.Gt(hour, 7));
IList list2 = criteria.List();
Mappings:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernate.Test"
namespace="NHibernate.Test.NHSpecificTest.NHCriteriaHaving">
<class name="Lecture" table="Lecture" dynamic-insert="true"
dynamic-update="true" >
<id name="ID" column="id" type="Int32" >
<generator class="hilo"/>
</id>
<property name="Time" column="time" type="DateTime" not-
null="false" />
<property name="Length" column="length" type="Int32" not-
null="false" />
</class>
<database-object>
<create>
create function [dbo].[DateOnly](@DateTime DateTime)
-- Returns @DateTime at midnight; i.e., it removes the time
portion of a DateTime value.
returns datetime
as
begin
return dateadd(dd,0, datediff(dd,0,@DateTime))
end
</create>
<drop>
DROP FUNCTION [dbo].[DateOnly]
</drop>
<dialect-scope name="NHibernate.Dialect.MsSql2000Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2005Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2008Dialect"/>
</database-object>
<database-object>
<create>
create function [dbo].[Date](@Year int, @Month int, @Day int)
-- returns a datetime value for the specified year, month and
day
-- Thank you to Michael Valentine Jones for this formula (see
comments).
returns datetime
as
begin
return dateadd(month,((@Year-1900)*12)+@Month-1,@Day-1)
end
</create>
<drop>
DROP FUNCTION [dbo].[Date]
</drop>
<dialect-scope name="NHibernate.Dialect.MsSql2000Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2005Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2008Dialect"/>
</database-object>
<database-object>
<create>
create function [dbo].[Time](@Hour int, @Minute int, @Second
int)
-- Returns a datetime value for the specified time at the "base"
date (1/1/1900)
-- Many thanks to MVJ for providing this formula (see comments).
returns datetime
as
begin
return dateadd(ss,(@Hour*3600)+(@Minute*60)+@Second,0)
end
</create>
<drop>
DROP FUNCTION [dbo].[Time]
</drop>
<dialect-scope name="NHibernate.Dialect.MsSql2000Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2005Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2008Dialect"/>
</database-object>
<database-object>
<create>
create function [dbo].[NextDay](@DateTime DateTime)
-- Returns a datetime + 1 day from
returns datetime
as
begin
return dateadd(dd, 1, @DateTime)
end
</create>
<drop>
DROP FUNCTION [dbo].[NextDay]
</drop>
<dialect-scope name="NHibernate.Dialect.MsSql2000Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2005Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2008Dialect"/>
</database-object>
<database-object>
<create>
create function [dbo].[TimeOnly](@DateTime DateTime)
-- returns only the time portion of a DateTime, at the "base"
date (1/1/1900)
-- Thanks, Peso!
returns datetime
as
begin
return dateadd(day, -datediff(day, 0, @datetime), @datetime)
end
</create>
<drop>
DROP FUNCTION [dbo].[TimeOnly]
</drop>
<dialect-scope name="NHibernate.Dialect.MsSql2000Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2005Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2008Dialect"/>
</database-object>
<database-object>
<create>
create function [dbo].[DateTime](@Year int, @Month int, @Day
int, @Hour int, @Minute int, @Second int)
-- returns a dateTime value for the date and time specified.
returns datetime
as
begin
return dbo.Date(@Year,@Month,@Day) + dbo.Time(@Hour,
@Minute,@Second)
end
</create>
<drop>
DROP FUNCTION [dbo].[DateTime]
</drop>
<dialect-scope name="NHibernate.Dialect.MsSql2000Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2005Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2008Dialect"/>
</database-object>
<database-object>
<create>
create function [dbo].[Hour](@DateTime DateTime)
-- returns a dateTime value for the date and time specified.
returns int
as
begin
return DatePart(Hour, @DateTime)
end
</create>
<drop>
DROP FUNCTION [dbo].[Hour]
</drop>
<dialect-scope name="NHibernate.Dialect.MsSql2000Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2005Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2008Dialect"/>
</database-object>
<database-object>
<create>
create function [dbo].[Minute](@DateTime DateTime)
-- returns a dateTime value for the date and time specified.
returns int
as
begin
return DatePart(Minute, @DateTime)
end
</create>
<drop>
DROP FUNCTION [dbo].[Minute]
</drop>
<dialect-scope name="NHibernate.Dialect.MsSql2000Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2005Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2008Dialect"/>
</database-object>
<!-- Oracle need this stats only -->
<database-object>
<create>
CREATE TABLE [dbo].[hibernate_unique_key](
[next_hi] [int] NULL
) ON [PRIMARY]
</create>
<!--<drop>
DROP STATISTICS PeopleByCityAndLastName
</drop>-->
<drop>
</drop>
<dialect-scope name="NHibernate.Dialect.SQLiteDialect"/>
</database-object>
</hibernate-mapping>