Index: trunk/nhibernate/src/NHibernate.Test/DialectTest/FirebirdDialectFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/DialectTest/FirebirdDialectFixture.cs (revision 0)
+++ trunk/nhibernate/src/NHibernate.Test/DialectTest/FirebirdDialectFixture.cs (revision 0)
@@ -0,0 +1,25 @@
+using NHibernate.Dialect;
+using NHibernate.SqlCommand;
+using NUnit.Framework;
+
+namespace NHibernate.Test.DialectTest
+{
+ [TestFixture]
+ public class FirebirdDialectFixture
+ {
+ [Test]
+ public void GetLimitString()
+ {
+ FirebirdDialect d = new FirebirdDialect();
+
+ SqlString str = d.GetLimitString(new SqlString("SELECT * FROM fish"), 0, 10);
+ Assert.AreEqual("SELECT first 10 * FROM fish", str.ToString());
+
+ str = d.GetLimitString(new SqlString("SELECT * FROM fish ORDER BY name"), 5, 15);
+ Assert.AreEqual("SELECT first 15 skip 5 * FROM fish ORDER BY name", str.ToString());
+
+ str = d.GetLimitString(new SqlString("SELECT * FROM fish ORDER BY name DESC"), 7, 28);
+ Assert.AreEqual("SELECT first 28 skip 7 * FROM fish ORDER BY name DESC", str.ToString());
+ }
+ }
+}
Index: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test-2.0.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test-2.0.csproj (revision 2194)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test-2.0.csproj (working copy)
@@ -75,6 +75,7 @@
+
Index: trunk/nhibernate/src/NHibernate/Dialect/FirebirdDialect.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Dialect/FirebirdDialect.cs (revision 2194)
+++ trunk/nhibernate/src/NHibernate/Dialect/FirebirdDialect.cs (working copy)
@@ -150,6 +150,69 @@
get { return true; }
}
+ public override bool SupportsLimit
+ {
+ get { return true; }
+ }
+
+ public override bool SupportsLimitOffset
+ {
+ get { return true; }
+ }
+
+ ///
+ /// Add a FIRST x [SKIP] y clause to the given SQL SELECT
+ ///
+ /// A Query in the form of a SqlString.
+ /// Maximum number of rows to be returned by the query
+ /// Offset of the first row to process in the result set
+ /// A new SqlString that contains the FIRST clause.
+ public override SqlString GetLimitString(SqlString querySqlString, int offset, int limit)
+ {
+ /*
+ * "SELECT FIRST x [SKIP y] rest-of-sql-statement"
+ */
+ querySqlString = querySqlString.Compact();
+ SqlStringBuilder pagingBuilder = new SqlStringBuilder();
+ bool firstAdded = false;
+ foreach (object sqlPart in querySqlString.SqlParts)
+ {
+ if (!firstAdded)
+ {
+ string sqlPartString = sqlPart as string;
+ if (sqlPartString != null)
+ {
+ string sqlFragment = sqlPartString.TrimStart();
+ int insertIndex = GetAfterSelectInsertPoint(sqlFragment);
+ if (insertIndex > 0)
+ {
+ string newFragment = string.Empty;
+
+ if (offset > 0)
+ {
+ newFragment = sqlFragment.Insert(insertIndex, " first " + limit.ToString() + " skip " + offset.ToString());
+ }
+ else
+ {
+ newFragment = sqlFragment.Insert(insertIndex, " first " + limit.ToString());
+ }
+ pagingBuilder.Add(newFragment);
+ firstAdded = true;
+ continue;
+ }
+ }
+ }
+ pagingBuilder.AddObject(sqlPart);
+ }
+
+ return pagingBuilder.ToSqlString();
+ }
+
+ public override bool SupportsVariableLimit
+ {
+ get { return false; }
+ }
+
public override string ForUpdateString
{
get { return " with lock"; }
@@ -164,5 +227,19 @@
{
return " for update of " + aliases + " with lock";
}
+
+ private static int GetAfterSelectInsertPoint(string fragment)
+ {
+ string fragmentLowerCased = fragment.ToLower(System.Globalization.CultureInfo.InvariantCulture);
+ if (fragmentLowerCased.StartsWith("select distinct"))
+ {
+ return 15;
+ }
+ else if (fragmentLowerCased.StartsWith("select"))
+ {
+ return 6;
+ }
+ return 0;
+ }
}
}
\ No newline at end of file