Index: MsSqlCe40Dialect.cs
===================================================================
--- MsSqlCe40Dialect.cs (revision 5853)
+++ MsSqlCe40Dialect.cs (working copy)
@@ -1,4 +1,7 @@
+using System;
+using System.Data.Common;
using NHibernate.Dialect.Function;
+using NHibernate.Dialect.Schema;
using NHibernate.SqlCommand;
namespace NHibernate.Dialect
@@ -7,26 +10,454 @@
{
public MsSqlCe40Dialect()
{
- RegisterFunction("concat", new VarArgsSQLFunction(NHibernateUtil.String, "(", "+", ")"));
+ RegisterKeywords();
+ RegisterFunctions();
}
+ ///
+ /// Does this Dialect have some kind of LIMIT syntax?
+ ///
+ /// True, we'll use the SELECT TOP nn syntax.
public override bool SupportsLimit
{
get { return true; }
}
+ ///
+ /// Does this Dialect support an offset?
+ ///
public override bool SupportsLimitOffset
{
get { return true; }
}
- public override SqlString GetLimitString(SqlString querySqlString, int offset, int limit)
- {
- if (querySqlString.IndexOfCaseInsensitive(" ORDER BY ") < 0)
- {
- querySqlString = querySqlString.Append(" ORDER BY GETDATE()");
- }
- return querySqlString.Append(string.Format(" OFFSET {0} ROWS FETCH NEXT {1} ROWS ONLY", offset, limit));
- }
+ protected virtual void RegisterKeywords()
+ {
+ RegisterKeyword("@@IDENTITY");
+ RegisterKeyword("ADD");
+ RegisterKeyword("ALL");
+ RegisterKeyword("ALTER");
+ RegisterKeyword("AND");
+ RegisterKeyword("ANY");
+ RegisterKeyword("AS");
+ RegisterKeyword("ASC");
+ RegisterKeyword("AUTHORIZATION");
+ RegisterKeyword("AVG");
+ RegisterKeyword("BACKUP");
+ RegisterKeyword("BEGIN");
+ RegisterKeyword("BETWEEN");
+ RegisterKeyword("BREAK");
+ RegisterKeyword("BROWSE");
+ RegisterKeyword("BULK");
+ RegisterKeyword("BY");
+ RegisterKeyword("CASCADE");
+ RegisterKeyword("CASE");
+ RegisterKeyword("CHECK");
+ RegisterKeyword("CHECKPOINT");
+ RegisterKeyword("CLOSE");
+ RegisterKeyword("CLUSTERED");
+ RegisterKeyword("COALESCE");
+ RegisterKeyword("COLLATE");
+ RegisterKeyword("COLUMN");
+ RegisterKeyword("COMMIT");
+ RegisterKeyword("COMPUTE");
+ RegisterKeyword("CONSTRAINT");
+ RegisterKeyword("CONTAINS");
+ RegisterKeyword("CONTAINSTABLE");
+ RegisterKeyword("CONTINUE");
+ RegisterKeyword("CONVERT");
+ RegisterKeyword("COUNT");
+ RegisterKeyword("CREATE");
+ RegisterKeyword("CROSS");
+ RegisterKeyword("CURRENT");
+ RegisterKeyword("CURRENT_DATE");
+ RegisterKeyword("CURRENT_TIME");
+ RegisterKeyword("CURRENT_TIMESTAMP");
+ RegisterKeyword("CURRENT_USER");
+ RegisterKeyword("CURSOR");
+ RegisterKeyword("DATABASE");
+ RegisterKeyword("DATABASEPASSWORD");
+ RegisterKeyword("DATEADD");
+ RegisterKeyword("DATEDIFF");
+ RegisterKeyword("DATENAME");
+ RegisterKeyword("DATEPART");
+ RegisterKeyword("DBCC");
+ RegisterKeyword("DEALLOCATE");
+ RegisterKeyword("DECLARE");
+ RegisterKeyword("DEFAULT");
+ RegisterKeyword("DELETE");
+ RegisterKeyword("DENY");
+ RegisterKeyword("DESC");
+ RegisterKeyword("DISK");
+ RegisterKeyword("DISTINCT");
+ RegisterKeyword("DISTRIBUTED");
+ RegisterKeyword("DOUBLE");
+ RegisterKeyword("DROP");
+ RegisterKeyword("DUMP");
+ RegisterKeyword("ELSE");
+ RegisterKeyword("ENCRYPTION");
+ RegisterKeyword("END");
+ RegisterKeyword("ERRLVL");
+ RegisterKeyword("ESCAPE");
+ RegisterKeyword("EXCEPT");
+ RegisterKeyword("EXEC");
+ RegisterKeyword("EXECUTE");
+ RegisterKeyword("EXISTS");
+ RegisterKeyword("EXIT");
+ RegisterKeyword("EXPRESSION");
+ RegisterKeyword("FETCH");
+ RegisterKeyword("FILE");
+ RegisterKeyword("FILLFACTOR");
+ RegisterKeyword("FOR");
+ RegisterKeyword("FOREIGN");
+ RegisterKeyword("FREETEXT");
+ RegisterKeyword("FREETEXTTABLE");
+ RegisterKeyword("FROM");
+ RegisterKeyword("FULL");
+ RegisterKeyword("FUNCTION");
+ RegisterKeyword("GOTO");
+ RegisterKeyword("GRANT");
+ RegisterKeyword("GROUP");
+ RegisterKeyword("HAVING");
+ RegisterKeyword("HOLDLOCK");
+ RegisterKeyword("IDENTITY");
+ RegisterKeyword("IDENTITY_INSERT");
+ RegisterKeyword("IDENTITYCOL");
+ RegisterKeyword("IF");
+ RegisterKeyword("IN");
+ RegisterKeyword("INDEX");
+ RegisterKeyword("INNER");
+ RegisterKeyword("INSERT");
+ RegisterKeyword("INTERSECT");
+ RegisterKeyword("INTO");
+ RegisterKeyword("IS");
+ RegisterKeyword("JOIN");
+ RegisterKeyword("KEY");
+ RegisterKeyword("KILL");
+ RegisterKeyword("LEFT");
+ RegisterKeyword("LIKE");
+ RegisterKeyword("LINENO");
+ RegisterKeyword("LOAD");
+ RegisterKeyword("MAX");
+ RegisterKeyword("MIN");
+ RegisterKeyword("NATIONAL");
+ RegisterKeyword("NOCHECK");
+ RegisterKeyword("NONCLUSTERED");
+ RegisterKeyword("NOT");
+ RegisterKeyword("NULL");
+ RegisterKeyword("NULLIF");
+ RegisterKeyword("OF");
+ RegisterKeyword("OFF");
+ RegisterKeyword("OFFSETS");
+ RegisterKeyword("ON");
+ RegisterKeyword("OPEN");
+ RegisterKeyword("OPENDATASOURCE");
+ RegisterKeyword("OPENQUERY");
+ RegisterKeyword("OPENROWSET");
+ RegisterKeyword("OPENXML");
+ RegisterKeyword("OPTION");
+ RegisterKeyword("OR");
+ RegisterKeyword("ORDER");
+ RegisterKeyword("OUTER");
+ RegisterKeyword("OVER");
+ RegisterKeyword("PERCENT");
+ RegisterKeyword("PLAN");
+ RegisterKeyword("PRECISION");
+ RegisterKeyword("PRIMARY");
+ RegisterKeyword("PRINT");
+ RegisterKeyword("PROC");
+ RegisterKeyword("PROCEDURE");
+ RegisterKeyword("PUBLIC");
+ RegisterKeyword("RAISERROR");
+ RegisterKeyword("READ");
+ RegisterKeyword("READTEXT");
+ RegisterKeyword("RECONFIGURE");
+ RegisterKeyword("REFERENCES");
+ RegisterKeyword("REPLICATION");
+ RegisterKeyword("RESTORE");
+ RegisterKeyword("RESTRICT");
+ RegisterKeyword("RETURN");
+ RegisterKeyword("REVOKE");
+ RegisterKeyword("RIGHT");
+ RegisterKeyword("ROLLBACK");
+ RegisterKeyword("ROWCOUNT");
+ RegisterKeyword("ROWGUIDCOL");
+ RegisterKeyword("RULE");
+ RegisterKeyword("SAVE");
+ RegisterKeyword("SCHEMA");
+ RegisterKeyword("SELECT");
+ RegisterKeyword("SESSION_USER");
+ RegisterKeyword("SET");
+ RegisterKeyword("SETUSER");
+ RegisterKeyword("SHUTDOWN");
+ RegisterKeyword("SOME");
+ RegisterKeyword("STATISTICS");
+ RegisterKeyword("SUM");
+ RegisterKeyword("SYSTEM_USER");
+ RegisterKeyword("TABLE");
+ RegisterKeyword("TEXTSIZE");
+ RegisterKeyword("THEN");
+ RegisterKeyword("TO");
+ RegisterKeyword("TOP");
+ RegisterKeyword("TRAN");
+ RegisterKeyword("TRANSACTION");
+ RegisterKeyword("TRIGGER");
+ RegisterKeyword("TRUNCATE");
+ RegisterKeyword("TSEQUAL");
+ RegisterKeyword("UNION");
+ RegisterKeyword("UNIQUE");
+ RegisterKeyword("UPDATE");
+ RegisterKeyword("UPDATETEXT");
+ RegisterKeyword("USE");
+ RegisterKeyword("USER");
+ RegisterKeyword("VALUES");
+ RegisterKeyword("VARYING");
+ RegisterKeyword("VIEW");
+ RegisterKeyword("WAITFOR");
+ RegisterKeyword("WHEN");
+ RegisterKeyword("WHERE");
+ RegisterKeyword("WHILE");
+ RegisterKeyword("WITH");
+ RegisterKeyword("WRITETEXT");
+ RegisterKeyword("smallint");
+ RegisterKeyword("int");
+ RegisterKeyword("real");
+ RegisterKeyword("float");
+ RegisterKeyword("money");
+ RegisterKeyword("bit");
+ RegisterKeyword("tinyint");
+ RegisterKeyword("bigint");
+ RegisterKeyword("uniqueidentifier");
+ RegisterKeyword("varbinary");
+ RegisterKeyword("binary");
+ RegisterKeyword("image");
+ RegisterKeyword("nvarchar");
+ RegisterKeyword("nchar");
+ RegisterKeyword("ntext");
+ RegisterKeyword("numeric");
+ RegisterKeyword("datetime");
+ RegisterKeyword("rowversion");
+ RegisterKeyword("@@DBTS");
+ RegisterKeyword("@@SHOWPLAN");
+ RegisterKeyword("ABS");
+ RegisterKeyword("ACOS");
+ RegisterKeyword("ASIN");
+ RegisterKeyword("ATAN");
+ RegisterKeyword("ATN2");
+ RegisterKeyword("CEILING");
+ RegisterKeyword("CHARINDEX");
+ RegisterKeyword("CAST");
+ RegisterKeyword("COS");
+ RegisterKeyword("COT");
+ RegisterKeyword("DATALENGTH");
+ RegisterKeyword("DEGREES");
+ RegisterKeyword("EXP");
+ RegisterKeyword("FLOOR");
+ RegisterKeyword("GETDATE");
+ RegisterKeyword("LEN");
+ RegisterKeyword("LOG");
+ RegisterKeyword("LOG10");
+ RegisterKeyword("LOWER");
+ RegisterKeyword("LTRIM");
+ RegisterKeyword("NCHAR");
+ RegisterKeyword("NEWID");
+ RegisterKeyword("PATINDEX");
+ RegisterKeyword("PI");
+ RegisterKeyword("POWER");
+ RegisterKeyword("RADIANS");
+ RegisterKeyword("RAND");
+ RegisterKeyword("REPLACE");
+ RegisterKeyword("REPLICATE");
+ RegisterKeyword("RTRIM");
+ RegisterKeyword("SHOWPLAN");
+ RegisterKeyword("XML");
+ RegisterKeyword("SIGN");
+ RegisterKeyword("SIN");
+ RegisterKeyword("SPACE");
+ RegisterKeyword("SQRT");
+ RegisterKeyword("STR");
+ RegisterKeyword("STUFF");
+ RegisterKeyword("SUBSTRING");
+ RegisterKeyword("TAN");
+ RegisterKeyword("UNICODE");
+ RegisterKeyword("UPPER");
+ RegisterKeyword("FORCE");
+ RegisterKeyword("ROWLOCK");
+ RegisterKeyword("PAGLOCK");
+ RegisterKeyword("TABLOCK");
+ RegisterKeyword("DBLOCK");
+ RegisterKeyword("UPDLOCK");
+ RegisterKeyword("XLOCK");
+ RegisterKeyword("HOLDLOCK");
+ RegisterKeyword("NOLOCK");
+ RegisterKeyword("GO");
+ RegisterKeyword("NEXT");
+ RegisterKeyword("OFFSET");
+ RegisterKeyword("ONLY");
+ RegisterKeyword("ROWS");
+ }
+
+ protected virtual void RegisterFunctions()
+ {
+ //Date and Time Functions
+ RegisterFunction("second", new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(second, ?1)"));
+ RegisterFunction("minute", new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(minute, ?1)"));
+ RegisterFunction("hour", new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(hour, ?1)"));
+ RegisterFunction("day", new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(day, ?1)"));
+ RegisterFunction("month", new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(month, ?1)"));
+ RegisterFunction("year", new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(year, ?1)"));
+ RegisterFunction("date", new SQLFunctionTemplate(NHibernateUtil.Date, "dateadd(dd, 0, datediff(dd, 0, ?1))"));
+ RegisterFunction("datename", new StandardSQLFunction("datename", NHibernateUtil.String));
+ RegisterFunction("current_timestamp", new NoArgSQLFunction("getdate", NHibernateUtil.DateTime, true));
+ RegisterFunction("datediff", new StandardSQLFunction("datediff", NHibernateUtil.Int32));
+
+ //Mathematical Functions
+ RegisterFunction("abs", new StandardSQLFunction("abs"));
+ RegisterFunction("acos", new StandardSQLFunction("acos", NHibernateUtil.Double));
+ RegisterFunction("asin", new StandardSQLFunction("asin", NHibernateUtil.Double));
+ RegisterFunction("atan", new StandardSQLFunction("atan", NHibernateUtil.Double));
+ RegisterFunction("atan2", new StandardSQLFunction("atan2", NHibernateUtil.Double));
+ RegisterFunction("ceiling", new StandardSQLFunction("ceiling"));
+ RegisterFunction("cos", new StandardSQLFunction("cos", NHibernateUtil.Double));
+ RegisterFunction("cot", new StandardSQLFunction("cot", NHibernateUtil.Double));
+ RegisterFunction("degrees", new StandardSQLFunction("degrees", NHibernateUtil.Double));
+ RegisterFunction("exp", new StandardSQLFunction("exp", NHibernateUtil.Double));
+ RegisterFunction("floor", new StandardSQLFunction("floor"));
+ RegisterFunction("log", new StandardSQLFunction("log", NHibernateUtil.Double));
+ RegisterFunction("log10", new StandardSQLFunction("log10", NHibernateUtil.Double));
+ RegisterFunction("pi", new NoArgSQLFunction("pi", NHibernateUtil.Double, true));
+ RegisterFunction("power", new StandardSQLFunction("power", NHibernateUtil.Double));
+ RegisterFunction("radians", new StandardSQLFunction("radians", NHibernateUtil.Double));
+ RegisterFunction("rand", new NoArgSQLFunction("rand", NHibernateUtil.Double));
+ RegisterFunction("round", new StandardSQLFunction("round"));
+ RegisterFunction("sign", new StandardSQLFunction("sign", NHibernateUtil.Int32));
+ RegisterFunction("sin", new StandardSQLFunction("sin", NHibernateUtil.Double));
+ RegisterFunction("sqrt", new StandardSQLFunction("sqrt", NHibernateUtil.Double));
+ RegisterFunction("tan", new StandardSQLFunction("tan", NHibernateUtil.Double));
+
+ //String Functions
+ RegisterFunction("locate", new StandardSQLFunction("charindex", NHibernateUtil.Int32));
+ RegisterFunction("length", new StandardSQLFunction("len", NHibernateUtil.Int32));
+ RegisterFunction("lower", new StandardSQLFunction("lower"));
+ RegisterFunction("ltrim", new StandardSQLFunction("ltrim"));
+ RegisterFunction("patindex", new StandardSQLFunction("patindex", NHibernateUtil.Int32));
+ RegisterFunction("replace", new StandardSafeSQLFunction("replace", NHibernateUtil.String, 3));
+ RegisterFunction("replicate", new StandardSQLFunction("replicate", NHibernateUtil.String));
+ RegisterFunction("rtrim", new StandardSQLFunction("rtrim", NHibernateUtil.String));
+ RegisterFunction("space", new StandardSQLFunction("space", NHibernateUtil.String));
+ RegisterFunction("str", new VarArgsSQLFunction(NHibernateUtil.String, "str(", ",", ")"));
+ RegisterFunction("stuff", new StandardSQLFunction("stuff", NHibernateUtil.String));
+ RegisterFunction("substring", new AnsiSubstringFunction());
+ RegisterFunction("unicode", new StandardSQLFunction("unicode", NHibernateUtil.Int32));
+ RegisterFunction("upper", new StandardSQLFunction("upper"));
+ RegisterFunction("trim", new AnsiTrimEmulationFunction());
+ RegisterFunction("concat", new VarArgsSQLFunction(NHibernateUtil.String, "(", "+", ")"));
+
+ //System Functions
+ RegisterFunction("coalesce", new VarArgsSQLFunction("coalesce(", ",", ")"));
+ RegisterFunction("newid", new NoArgSQLFunction("newid", NHibernateUtil.String, true));
+ }
+
+ public override string SelectGUIDString
+ {
+ get { return "select newid()"; }
+ }
+
+ public override bool SupportsIdentityColumns
+ {
+ get { return true; }
+ }
+
+ public override char CloseQuote
+ {
+ get { return ']'; }
+ }
+
+ public override char OpenQuote
+ {
+ get { return '['; }
+ }
+
+ ///
+ /// Can parameters be used for a statement containing a LIMIT?
+ ///
+ public override bool SupportsVariableLimit
+ {
+ get { return false; }
+ }
+
+ ///
+ /// Add a LIMIT (TOP) 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 LIMIT clause.
+ public override SqlString GetLimitString(SqlString querySqlString, int offset, int limit)
+ {
+ // In SQL CE: TOP and OFFSET clause cannot be used together in the same query
+ if (offset > 0)
+ {
+ if (querySqlString.IndexOfCaseInsensitive(" ORDER BY ") < 0)
+ {
+ querySqlString = querySqlString.Append(" ORDER BY GETDATE()");
+ }
+ return querySqlString.Append(string.Format(" OFFSET {0} ROWS FETCH NEXT {1} ROWS ONLY", offset, limit));
+ }
+
+ /*
+ * "SELECT TOP limit rest-of-sql-statement"
+ */
+
+ return querySqlString.Insert(GetAfterSelectInsertPoint(querySqlString), string.Format(" top ({0})", limit));
+ }
+
+ private static int GetAfterSelectInsertPoint(SqlString sql)
+ {
+ if (sql.StartsWithCaseInsensitive("select distinct"))
+ {
+ return 15;
+ }
+ else if (sql.StartsWithCaseInsensitive("select"))
+ {
+ return 6;
+ }
+ throw new NotSupportedException("The query should start with 'SELECT' or 'SELECT DISTINCT'");
+ }
+
+ ///
+ /// Does the LIMIT clause take a "maximum" row number
+ /// instead of a total number of returned rows?
+ ///
+ /// false, unless overridden
+ public override bool UseMaxForLimit
+ {
+ get { return true; }
+ }
+
+ public override bool SupportsSqlBatches
+ {
+ get { return false; }
+ }
+
+ public override bool IsKnownToken(string currentToken, string nextToken)
+ {
+ return currentToken == "n" && nextToken == "'"; // unicode character
+ }
+
+ public override bool SupportsUnionAll
+ {
+ get { return true; }
+ }
+
+ public override IDataBaseSchema GetDataBaseSchema(DbConnection connection)
+ {
+ return new MsSqlCeDataBaseSchema(connection);
+ }
+
+ public override bool SupportsCircularCascadeDeleteConstraints
+ {
+ get { return false; }
+ }
}
}
\ No newline at end of file