diff --git a/src/NHibernate.Test/Tools/hbm2ddl/SchemaMetadataUpdaterTest/HeavyEntity.cs b/src/NHibernate.Test/Tools/hbm2ddl/SchemaMetadataUpdaterTest/HeavyEntity.cs index 62ceb5e32a2..57057031360 100644 --- a/src/NHibernate.Test/Tools/hbm2ddl/SchemaMetadataUpdaterTest/HeavyEntity.cs +++ b/src/NHibernate.Test/Tools/hbm2ddl/SchemaMetadataUpdaterTest/HeavyEntity.cs @@ -7,5 +7,6 @@ public class Order public string And { get; set; } public string Column { get; set; } public string Name { get; set; } + public string Abracadabra { get; set; } } } \ No newline at end of file diff --git a/src/NHibernate.Test/Tools/hbm2ddl/SchemaMetadataUpdaterTest/HeavyEntity.hbm.xml b/src/NHibernate.Test/Tools/hbm2ddl/SchemaMetadataUpdaterTest/HeavyEntity.hbm.xml index 4ad993f11dd..631c22b0094 100644 --- a/src/NHibernate.Test/Tools/hbm2ddl/SchemaMetadataUpdaterTest/HeavyEntity.hbm.xml +++ b/src/NHibernate.Test/Tools/hbm2ddl/SchemaMetadataUpdaterTest/HeavyEntity.hbm.xml @@ -13,6 +13,7 @@ + \ No newline at end of file diff --git a/src/NHibernate.Test/Tools/hbm2ddl/SchemaMetadataUpdaterTest/SchemaMetadataUpdaterFixture.cs b/src/NHibernate.Test/Tools/hbm2ddl/SchemaMetadataUpdaterTest/SchemaMetadataUpdaterFixture.cs index 2091b6f5637..6e3fa36cd0d 100644 --- a/src/NHibernate.Test/Tools/hbm2ddl/SchemaMetadataUpdaterTest/SchemaMetadataUpdaterFixture.cs +++ b/src/NHibernate.Test/Tools/hbm2ddl/SchemaMetadataUpdaterTest/SchemaMetadataUpdaterFixture.cs @@ -1,10 +1,13 @@ +using System; using System.Collections.Generic; using System.Linq; -using NHibernate.Cfg; +using NHibernate.Dialect; +using NHibernate.Driver; using NHibernate.Engine; using NHibernate.Mapping; using NHibernate.Tool.hbm2ddl; using NUnit.Framework; +using Environment = NHibernate.Cfg.Environment; namespace NHibernate.Test.Tools.hbm2ddl.SchemaMetadataUpdaterTest { @@ -23,8 +26,8 @@ public void CanRetrieveReservedWords() var metaData = dialect.GetDataBaseSchema(connectionHelper.Connection); var reserved = metaData.GetReservedWords(); Assert.That(reserved, Is.Not.Empty); - Assert.That(reserved, Has.Member("SELECT")); - Assert.That(reserved, Has.Member("FROM")); + Assert.That(reserved, Has.Member("SELECT").IgnoreCase); + Assert.That(reserved, Has.Member("FROM").IgnoreCase); } finally { @@ -35,7 +38,7 @@ public void CanRetrieveReservedWords() [Test] public void UpdateReservedWordsInDialect() { - var reservedDb = new HashSet(); + var reservedDb = new HashSet(StringComparer.OrdinalIgnoreCase); var configuration = TestConfigurationHelper.GetDefaultConfiguration(); var dialect = Dialect.Dialect.GetDialect(configuration.Properties); var connectionHelper = new ManagedProviderConnectionHelper(configuration.Properties); @@ -55,10 +58,98 @@ public void UpdateReservedWordsInDialect() var sf = (ISessionFactoryImplementor) configuration.BuildSessionFactory(); SchemaMetadataUpdater.Update(sf); - var match = reservedDb.Intersect(sf.Dialect.Keywords); + var match = reservedDb.Intersect(sf.Dialect.Keywords, StringComparer.OrdinalIgnoreCase); + + // tests that nothing in the first metaData.GetReservedWords() is left out of the second metaData.GetReservedWords() call. + // i.e. always passes. + Assert.That(match, Is.EquivalentTo(reservedDb)); + } + + [Test] + public void EnsureReservedWordsHardCodedInDialect() + { + var reservedDb = new HashSet(); + var configuration = TestConfigurationHelper.GetDefaultConfiguration(); + var dialect = Dialect.Dialect.GetDialect(configuration.Properties); + var connectionHelper = new ManagedProviderConnectionHelper(configuration.Properties); + connectionHelper.Prepare(); + try + { + var metaData = dialect.GetDataBaseSchema(connectionHelper.Connection); + foreach (var rw in metaData.GetReservedWords()) + { + if (rw.Contains(" ")) continue; + reservedDb.Add(rw.ToLowerInvariant()); + } + } + finally + { + connectionHelper.Release(); + } + + var sf = (ISessionFactoryImplementor)configuration.BuildSessionFactory(); + + // use the dialect as configured, with no update + var match = reservedDb.Intersect(sf.Dialect.Keywords).ToList(); + + // tests that nothing in metaData.GetReservedWords() is left out of the Dialect.Keywords (without a refresh). + var differences = reservedDb.Except(match).ToList(); + if (differences.Count > 0) + { + Console.WriteLine("Update Dialect {0} with RegisterKeyword:", sf.Dialect.GetType().Name); + foreach (var keyword in differences.OrderBy(x => x)) + { + Console.WriteLine(" RegisterKeyword(\"{0}\");", keyword); + } + } + + if (sf.ConnectionProvider.Driver is OdbcDriver) + { + Assert.Inconclusive("ODBC has excess keywords reserved"); + } + Assert.That(match, Is.EquivalentTo(reservedDb)); } + [Test, Explicit] + public void CheckForExcessReservedWordsHardCodedInDialect() + { + var reservedDb = new HashSet(); + var configuration = TestConfigurationHelper.GetDefaultConfiguration(); + var dialect = Dialect.Dialect.GetDialect(configuration.Properties); + var connectionHelper = new ManagedProviderConnectionHelper(configuration.Properties); + connectionHelper.Prepare(); + try + { + var metaData = dialect.GetDataBaseSchema(connectionHelper.Connection); + foreach (var rw in metaData.GetReservedWords()) + { + reservedDb.Add(rw.ToLowerInvariant()); + } + } + finally + { + connectionHelper.Release(); + } + + var sf = (ISessionFactoryImplementor)configuration.BuildSessionFactory(); + + // use the dialect as configured, with no update + // tests that nothing in Dialect.Keyword is not in metaData.GetReservedWords() + var differences = sf.Dialect.Keywords.Except(reservedDb).Except(AnsiSqlKeywords.Sql2003).ToList(); + if (differences.Count > 0) + { + Console.WriteLine("Excess RegisterKeyword in Dialect {0}:", sf.Dialect.GetType().Name); + foreach (var keyword in differences.OrderBy(x => x)) + { + Console.WriteLine(" RegisterKeyword(\"{0}\");", keyword); + } + } + + // Don't fail incase the driver returns nothing. + // This is an info-only test. + } + [Test] public void ExplicitAutoQuote() { @@ -66,7 +157,11 @@ public void ExplicitAutoQuote() configuration.AddResource("NHibernate.Test.Tools.hbm2ddl.SchemaMetadataUpdaterTest.HeavyEntity.hbm.xml", GetType().Assembly); - SchemaMetadataUpdater.QuoteTableAndColumns(configuration); + var dialect = Dialect.Dialect.GetDialect(configuration.GetDerivedProperties()); + dialect.Keywords.Add("Abracadabra"); + + SchemaMetadataUpdater.Update(configuration, dialect); + SchemaMetadataUpdater.QuoteTableAndColumns(configuration, dialect); var cm = configuration.GetClassMapping(typeof(Order)); Assert.That(cm.Table.IsQuoted); @@ -74,6 +169,7 @@ public void ExplicitAutoQuote() Assert.That(GetColumnByName(culs, "From").IsQuoted); Assert.That(GetColumnByName(culs, "And").IsQuoted); Assert.That(GetColumnByName(culs, "Select").IsQuoted); + Assert.That(GetColumnByName(culs, "Abracadabra").IsQuoted); Assert.That(!GetColumnByName(culs, "Name").IsQuoted); } @@ -97,7 +193,7 @@ public void AutoQuoteTableAndColumnsAtStratup() [Test] public void AutoQuoteTableAndColumnsAtStratupIncludeKeyWordsImport() { - var reservedDb = new HashSet(); + var reservedDb = new HashSet(StringComparer.OrdinalIgnoreCase); var configuration = TestConfigurationHelper.GetDefaultConfiguration(); var dialect = Dialect.Dialect.GetDialect(configuration.Properties); var connectionHelper = new ManagedProviderConnectionHelper(configuration.Properties); @@ -119,8 +215,8 @@ public void AutoQuoteTableAndColumnsAtStratupIncludeKeyWordsImport() configuration.AddResource("NHibernate.Test.Tools.hbm2ddl.SchemaMetadataUpdaterTest.HeavyEntity.hbm.xml", GetType().Assembly); var sf = (ISessionFactoryImplementor)configuration.BuildSessionFactory(); - var match = reservedDb.Intersect(sf.Dialect.Keywords); - Assert.That(match, Is.EquivalentTo(reservedDb)); + var match = reservedDb.Intersect(sf.Dialect.Keywords, StringComparer.OrdinalIgnoreCase); + Assert.That(match, Is.EquivalentTo(reservedDb).IgnoreCase); } private static Column GetColumnByName(IEnumerable columns, string colName) @@ -167,7 +263,11 @@ public void WhenConfiguredOnlyExplicitAutoQuote() configuration.AddResource("NHibernate.Test.Tools.hbm2ddl.SchemaMetadataUpdaterTest.HeavyEntity.hbm.xml", GetType().Assembly); - SchemaMetadataUpdater.QuoteTableAndColumns(configuration); + var dialect = Dialect.Dialect.GetDialect(configuration.GetDerivedProperties()); + dialect.Keywords.Add("Abracadabra"); + + SchemaMetadataUpdater.Update(configuration, dialect); + SchemaMetadataUpdater.QuoteTableAndColumns(configuration, dialect); var cm = configuration.GetClassMapping(typeof(Order)); Assert.That(cm.Table.IsQuoted); @@ -175,6 +275,7 @@ public void WhenConfiguredOnlyExplicitAutoQuote() Assert.That(GetColumnByName(culs, "From").IsQuoted); Assert.That(GetColumnByName(culs, "And").IsQuoted); Assert.That(GetColumnByName(culs, "Select").IsQuoted); + Assert.That(GetColumnByName(culs, "Abracadabra").IsQuoted); Assert.That(!GetColumnByName(culs, "Name").IsQuoted); } } diff --git a/src/NHibernate/Dialect/AnsiSqlKeywords.cs b/src/NHibernate/Dialect/AnsiSqlKeywords.cs new file mode 100644 index 00000000000..47a238fa2fc --- /dev/null +++ b/src/NHibernate/Dialect/AnsiSqlKeywords.cs @@ -0,0 +1,267 @@ +using System.Collections.Generic; + +namespace NHibernate.Dialect +{ + /// + /// Maintains the set of ANSI SQL keywords + /// + public class AnsiSqlKeywords + { + /// + /// Retrieve all keywords defined by ANSI SQL:2003 + /// + public static readonly IReadOnlyCollection Sql2003; + + static AnsiSqlKeywords() + { + var keywordsSql2003 = new [] + { + "add", + "all", + "allocate", + "alter", + "and", + "any", + "are", + "array", + "as", + "asensitive", + "asymmetric", + "at", + "atomic", + "authorization", + "begin", + "between", + "bigint", + "binary", + "blob", + "both", + "by", + "call", + "called", + "cascaded", + "case", + "cast", + "char", + "character", + "check", + "clob", + "close", + "collate", + "column", + "commit", + "condition", + "connect", + "constraint", + "continue", + "corresponding", + "create", + "cross", + "cube", + "current", + "current_date", + "current_path", + "current_role", + "current_time", + "current_timestamp", + "current_user", + "cursor", + "cycle", + "date", + "day", + "deallocate", + "dec", + "decimal", + "declare", + "default", + "delete", + "deref", + "describe", + "deterministic", + "disconnect", + "distinct", + "do", + "double", + "drop", + "dynamic", + "each", + "element", + "else", + "elsif", + "end", + "escape", + "except", + "exec", + "execute", + "exists", + "exit", + "external", + "false", + "fetch", + "filter", + "float", + "for", + "foreign", + "free", + "from", + "full", + "function", + "get", + "global", + "grant", + "group", + "grouping", + "handler", + "having", + "hold", + "hour", + "identity", + "if", + "immediate", + "in", + "indicator", + "inner", + "inout", + "input", + "insensitive", + "insert", + "int", + "integer", + "intersect", + "interval", + "into", + "is", + "iterate", + "join", + "language", + "large", + "lateral", + "leading", + "leave", + "left", + "like", + "local", + "localtime", + "localtimestamp", + "loop", + "match", + "member", + "merge", + "method", + "minute", + "modifies", + "module", + "month", + "multiset", + "national", + "natural", + "nchar", + "nclob", + "new", + "no", + "none", + "not", + "null", + "numeric", + "of", + "old", + "on", + "only", + "open", + "or", + "order", + "out", + "outer", + "output", + "over", + "overlaps", + "parameter", + "partition", + "precision", + "prepare", + "primary", + "procedure", + "range", + "reads", + "real", + "recursive", + "ref", + "references", + "referencing", + "release", + "repeat", + "resignal", + "result", + "return", + "returns", + "revoke", + "right", + "rollback", + "rollup", + "row", + "rows", + "savepoint", + "scroll", + "search", + "second", + "select", + "sensitive", + "session_use", + "set", + "signal", + "similar", + "smallint", + "some", + "specific", + "specifictype", + "sql", + "sqlexception", + "sqlstate", + "sqlwarning", + "start", + "static", + "submultiset", + "symmetric", + "system", + "system_user", + "table", + "tablesample", + "then", + "time", + "timestamp", + "timezone_hour", + "timezone_minute", + "to", + "trailing", + "translation", + "treat", + "trigger", + "true", + "undo", + "union", + "unique", + "unknown", + "unnest", + "until", + "update", + "user", + "using", + "value", + "values", + "varchar", + "varying", + "when", + "whenever", + "where", + "while", + "window", + "with", + "within", + "without", + "year", + }; + + Sql2003 = keywordsSql2003; + } + } +} diff --git a/src/NHibernate/Dialect/Dialect.cs b/src/NHibernate/Dialect/Dialect.cs index d0a188f8c07..1114b879fbb 100644 --- a/src/NHibernate/Dialect/Dialect.cs +++ b/src/NHibernate/Dialect/Dialect.cs @@ -44,7 +44,6 @@ public abstract class Dialect private readonly TypeNames _hibernateTypeNames = new TypeNames(); private readonly IDictionary _properties = new Dictionary(); private readonly IDictionary _sqlFunctions; - private readonly HashSet _sqlKeywords = new HashSet(); private static readonly IDictionary StandardAggregateFunctions = CollectionHelper.CreateCaseInsensitiveHashtable(); @@ -81,7 +80,9 @@ protected Dialect() Log.Info("Using dialect: " + this); _sqlFunctions = CollectionHelper.CreateCaseInsensitiveHashtable(StandardAggregateFunctions); - + + Keywords = new HashSet(AnsiSqlKeywords.Sql2003, StringComparer.OrdinalIgnoreCase); + // standard sql92 functions (can be overridden by subclasses) RegisterFunction("substring", new AnsiSubstringFunction()); RegisterFunction("locate", new StandardSQLFunction("locate", NHibernateUtil.Int32)); @@ -2086,10 +2087,7 @@ public virtual IDictionary Functions get { return _sqlFunctions; } } - public HashSet Keywords - { - get { return _sqlKeywords; } - } + public HashSet Keywords { get; } /// /// Get the command used to select a GUID from the underlying database. @@ -2246,6 +2244,21 @@ protected void RegisterKeyword(string word) Keywords.Add(word); } + protected internal void RegisterKeywords(params string[] keywords) + { + Keywords.UnionWith(keywords); + } + + protected internal void RegisterKeywords(IEnumerable keywords) + { + Keywords.UnionWith(keywords); + } + + public bool IsKeyword(string str) + { + return Keywords.Contains(str); + } + protected void RegisterFunction(string name, ISQLFunction function) { _sqlFunctions[name] = function; @@ -2281,4 +2294,4 @@ public virtual ISQLExceptionConverter BuildSQLExceptionConverter() return new SQLStateConverter(ViolatedConstraintNameExtracter); } } -} \ No newline at end of file +} diff --git a/src/NHibernate/Dialect/FirebirdDialect.cs b/src/NHibernate/Dialect/FirebirdDialect.cs index f58a54a887e..673c07c729e 100644 --- a/src/NHibernate/Dialect/FirebirdDialect.cs +++ b/src/NHibernate/Dialect/FirebirdDialect.cs @@ -268,9 +268,133 @@ public SqlString Render(IList args, ISessionFactoryImplementor factory) } } + #region private static readonly string[] DialectKeywords = { ... } + + private static readonly string[] DialectKeywords = + { + "action", + "active", + "admin", + "after", + "asc", + "ascending", + "auto", + "avg", + "base_name", + "before", + "blob sub_type 1", + "break", + "cache", + "cascade", + "check_point_length", + "coalesce", + "committed", + "computed", + "conditional", + "connection_id", + "containing", + "count", + "cstring", + "database", + "debug", + "desc", + "descending", + "descriptor", + "domain", + "double precision", + "entry_point", + "exception", + "extract", + "file", + "first", + "free_it", + "gdscode", + "gen_id", + "generator", + "group_commit_wait_time", + "inactive", + "index", + "input_type", + "isolation", + "key", + "last", + "length", + "level", + "lock", + "log_buffer_size", + "logfile", + "long", + "manual", + "max", + "maximum_segment", + "message", + "min", + "module_name", + "names", + "nullif", + "nulls", + "num_log_buffers", + "option", + "output_type", + "overflow", + "page", + "page_size", + "pages", + "password", + "plan", + "position", + "post_event", + "privileges", + "protected", + "raw_partitions", + "rdb$db_key", + "read", + "record_version", + "recreate", + "reserv", + "reserving", + "restrict", + "retain", + "returning_values", + "role", + "rows_affected", + "schema", + "segment", + "shadow", + "shared", + "singular", + "size", + "skip", + "snapshot", + "sort", + "sqlcode", + "stability", + "starting", + "starts", + "statistics", + "sub_type", + "substring", + "sum", + "suspend", + "transaction", + "transaction_id", + "type", + "uncommitted", + "upper", + "variable", + "view", + "wait", + "weekday", + "work", + "write", + "yearday", + }; + + #endregion + protected virtual void RegisterKeywords() { - RegisterKeyword("date"); + RegisterKeywords(DialectKeywords); } protected virtual void RegisterColumnTypes() diff --git a/src/NHibernate/Dialect/MsSql2000Dialect.cs b/src/NHibernate/Dialect/MsSql2000Dialect.cs index 64395166a24..3bd6d58fa14 100644 --- a/src/NHibernate/Dialect/MsSql2000Dialect.cs +++ b/src/NHibernate/Dialect/MsSql2000Dialect.cs @@ -64,37 +64,215 @@ protected virtual void RegisterDefaultProperties() DefaultProperties[Environment.QuerySubstitutions] = "true 1, false 0, yes 'Y', no 'N'"; } + #region private static readonly string[] DialectKeywords = { ... } + + private static readonly string[] DialectKeywords = + { + "absolute", + "action", + "ada", + "admin", + "after", + "aggregate", + "alias", + "asc", + "assertion", + "avg", + "backup", + "before", + "bit", + "bit_length", + "boolean", + "breadth", + "break", + "browse", + "bulk", + "cascade", + "catalog", + "char_length", + "character_length", + "checkpoint", + "class", + "clustered", + "coalesce", + "collation", + "completion", + "compute", + "connection", + "constraints", + "constructor", + "contains", + "containstable", + "convert", + "count", + "data", + "database", + "datetime", + "dbcc", + "deferrable", + "deferred", + "deny", + "depth", + "desc", + "descriptor", + "destroy", + "destructor", + "diagnostics", + "dictionary", + "disk", + "distributed", + "domain", + "dummy", + "dump", + "end-exec", + "equals", + "errlvl", + "every", + "exception", + "extract", + "file", + "fillfactor", + "first", + "fortran", + "found", + "freetext", + "freetexttable", + "general", + "go", + "goto", + "holdlock", + "host", + "identity_insert", + "identitycol", + "ignore", + "image", + "include", + "index", + "initialize", + "initially", + "isolation", + "key", + "kill", + "last", + "less", + "level", + "limit", + "lineno", + "load", + "locator", + "lower", + "map", + "max", + "min", + "modify", + "money", + "names", + "national ", + "next", + "nocheck", + "nonclustered", + "ntext", + "nullif", + "nvarchar", + "object", + "octet_length", + "off", + "offsets", + "opendatasource", + "openquery", + "openrowset", + "openxml", + "operation", + "option", + "ordinality", + "pad", + "parameters", + "partial", + "pascal", + "path", + "percent", + "plan", + "position", + "postfix", + "prefix", + "preorder", + "preserve", + "print", + "prior", + "privileges", + "proc", + "public", + "raiserror", + "read", + "readtext", + "reconfigure", + "relative", + "replication", + "restore", + "restrict", + "role", + "routine", + "rowcount", + "rowguidcol", + "rule", + "save", + "schema", + "scope", + "section", + "sequence", + "session", + "session_user", + "sets", + "setuser", + "shutdown", + "size", + "smalldatetime", + "smallmoney", + "space", + "sql_variant", + "sqlca", + "sqlcode", + "sqlerror", + "state", + "statement", + "statistics", + "structure", + "substring", + "sum", + "temporary", + "terminate", + "text", + "textsize", + "than", + "tinyint", + "top", + "tran", + "transaction", + "translate", + "trim", + "truncate", + "tsequal", + "under", + "uniqueidentifier", + "updatetext", + "upper", + "usage", + "use", + "varbinary", + "variable", + "view", + "waitfor", + "work", + "write", + "writetext", + "zone", + }; + + #endregion + protected virtual void RegisterKeywords() { - RegisterKeyword("top"); - RegisterKeyword("int"); - RegisterKeyword("integer"); // a commonly-used alias for 'int' - RegisterKeyword("tinyint"); - RegisterKeyword("smallint"); - RegisterKeyword("bigint"); - RegisterKeyword("numeric"); - RegisterKeyword("decimal"); - RegisterKeyword("bit"); - RegisterKeyword("money"); - RegisterKeyword("smallmoney"); - RegisterKeyword("float"); - RegisterKeyword("real"); - RegisterKeyword("datetime"); - RegisterKeyword("smalldatetime"); - RegisterKeyword("char"); - RegisterKeyword("varchar"); - RegisterKeyword("text"); - RegisterKeyword("nchar"); - RegisterKeyword("nvarchar"); - RegisterKeyword("ntext"); - RegisterKeyword("binary"); - RegisterKeyword("varbinary"); - RegisterKeyword("image"); - RegisterKeyword("cursor"); - RegisterKeyword("timestamp"); - RegisterKeyword("uniqueidentifier"); - RegisterKeyword("sql_variant"); - RegisterKeyword("table"); + RegisterKeywords(DialectKeywords); } protected virtual void RegisterFunctions() diff --git a/src/NHibernate/Dialect/MsSql2008Dialect.cs b/src/NHibernate/Dialect/MsSql2008Dialect.cs index b1ac6b6e39f..6da8c5a144b 100644 --- a/src/NHibernate/Dialect/MsSql2008Dialect.cs +++ b/src/NHibernate/Dialect/MsSql2008Dialect.cs @@ -26,10 +26,8 @@ protected override void RegisterFunctions() protected override void RegisterKeywords() { base.RegisterKeywords(); - RegisterKeyword("date"); RegisterKeyword("datetimeoffset"); RegisterKeyword("datetime2"); - RegisterKeyword("time"); RegisterKeyword("hierarchyid"); } diff --git a/src/NHibernate/Dialect/MsSqlCeDialect.cs b/src/NHibernate/Dialect/MsSqlCeDialect.cs index a5160f249cd..e216b9cc8b8 100644 --- a/src/NHibernate/Dialect/MsSqlCeDialect.cs +++ b/src/NHibernate/Dialect/MsSqlCeDialect.cs @@ -17,6 +17,124 @@ namespace NHibernate.Dialect public class MsSqlCeDialect : Dialect { public MsSqlCeDialect() + { + RegisterTypeMapping(); + + RegisterFunctions(); + + RegisterKeywords(); + + RegisterDefaultProperties(); + } + + #region private static readonly string[] DialectKeywords = { ... } + + private static readonly string[] DialectKeywords = + { + "apply", + "asc", + "backup", + "bit", + "break", + "browse", + "bulk", + "cascade", + "checkpoint", + "clustered", + "coalesce", + "compute", + "contains", + "containstable", + "convert", + "database", + "datetime", + "dbcc", + "deny", + "desc", + "disk", + "distributed", + "dump", + "errlvl", + "file", + "fillfactor", + "first", + "freetext", + "freetexttable", + "goto", + "holdlock", + "identity_insert", + "identitycol", + "image", + "index", + "key", + "kill", + "lineno", + "load", + "money", + "next", + "nocheck", + "nonclustered", + "ntext", + "nullif", + "nvarchar", + "off", + "offset", + "offsets", + "opendatasource", + "openquery", + "openrowset", + "openxml", + "option", + "percent", + "pivot", + "plan", + "print", + "proc", + "public", + "raiserror", + "read", + "readtext", + "reconfigure", + "replication", + "restore", + "restrict", + "revert", + "rowcount", + "rowguidcol", + "rowversion", + "rule", + "save", + "schema", + "session_user", + "setuser", + "shutdown", + "statistics", + "textsize", + "tinyint", + "top", + "tran", + "transaction", + "truncate", + "tsequal", + "uniqueidentifier", + "unpivot", + "updatetext", + "use", + "varbinary", + "view", + "waitfor", + "writetext", + "xmlunnest", + }; + + #endregion + + protected virtual void RegisterKeywords() + { + RegisterKeywords(DialectKeywords); + } + + protected virtual void RegisterTypeMapping() { RegisterColumnType(DbType.AnsiStringFixedLength, "NCHAR(255)"); RegisterColumnType(DbType.AnsiStringFixedLength, 4000, "NCHAR($l)"); @@ -45,9 +163,12 @@ public MsSqlCeDialect() RegisterColumnType(DbType.String, 4000, "NVARCHAR($l)"); RegisterColumnType(DbType.String, 1073741823, "NTEXT"); RegisterColumnType(DbType.Time, "DATETIME"); + } + protected virtual void RegisterFunctions() + { RegisterFunction("substring", new EmulatedLengthSubstringFunction()); - RegisterFunction("str", new SQLFunctionTemplate(NHibernateUtil.String, "cast(?1 as nvarchar)")); + RegisterFunction("str", new SQLFunctionTemplate(NHibernateUtil.String, "cast(?1 as nvarchar)")); RegisterFunction("date", new SQLFunctionTemplate(NHibernateUtil.DateTime, "dateadd(dd, 0, datediff(dd, 0, ?1))")); RegisterFunction("second", new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(second, ?1)")); @@ -70,7 +191,10 @@ public MsSqlCeDialect() RegisterFunction("concat", new VarArgsSQLFunction(NHibernateUtil.String, "(", "+", ")")); RegisterFunction("round", new StandardSQLFunction("round")); + } + protected virtual void RegisterDefaultProperties() + { DefaultProperties[Environment.ConnectionDriver] = "NHibernate.Driver.SqlServerCeDriver"; DefaultProperties[Environment.PrepareSql] = "false"; } diff --git a/src/NHibernate/Dialect/MySQLDialect.cs b/src/NHibernate/Dialect/MySQLDialect.cs index 9997784542d..63d8cd89943 100644 --- a/src/NHibernate/Dialect/MySQLDialect.cs +++ b/src/NHibernate/Dialect/MySQLDialect.cs @@ -106,6 +106,8 @@ public MySQLDialect() //special: RegisterColumnType(DbType.Guid, "VARCHAR(40)"); + RegisterKeywords(); + RegisterCastTypes(); //functions: @@ -114,6 +116,130 @@ public MySQLDialect() DefaultProperties[Environment.ConnectionDriver] = "NHibernate.Driver.MySqlDataDriver"; } + #region private static readonly string[] DialectKeywords = { ... } + + private static readonly string[] DialectKeywords = + { + "accessible", + "analyze", + "asc", + "before", + "bit", + "cascade", + "change", + "connection", + "contributors", + "convert", + "database", + "databases", + "datetime", + "day_hour", + "day_microsecond", + "day_minute", + "day_second", + "delayed", + "desc", + "distinctrow", + "div", + "dual", + "elseif", + "enclosed", + "enum", + "escaped", + "explain", + "float4", + "float8", + "force", + "fulltext", + "high_priority", + "hour_microsecond", + "hour_minute", + "hour_second", + "ignore", + "index", + "infile", + "int1", + "int2", + "int3", + "int4", + "int8", + "key", + "keys", + "kill", + "limit", + "linear", + "lines", + "load", + "lock", + "long", + "longblob", + "longtext", + "low_priority", + "mediumblob", + "mediumint", + "mediumtext", + "middleint", + "minute_microsecond", + "minute_second", + "mod", + "no_write_to_binlog", + "nvarchar", + "optimize", + "option", + "optionally", + "outfile", + "purge", + "read", + "read_only", + "read_write", + "regexp", + "rename", + "replace", + "require", + "restrict", + "rlike", + "schema", + "schemas", + "second_microsecond", + "separator", + "show", + "spatial", + "sql_big_result", + "sql_calc_found_rows", + "sql_small_result", + "ssl", + "starting", + "straight_join", + "terminated", + "text", + "tiny int", + "tinyblob", + "tinyint", + "tinytext", + "unlock", + "unsigned", + "upgrade", + "usage", + "use", + "utc_date", + "utc_time", + "utc_timestamp", + "varbinary", + "varcharacter", + "write", + "x509", + "xor", + "year_month", + "zerofill", + }; + + #endregion + + protected virtual void RegisterKeywords() + { + RegisterKeywords(DialectKeywords); + } + protected virtual void RegisterFunctions() { RegisterFunction("iif", new StandardSQLFunction("if")); diff --git a/src/NHibernate/Dialect/Oracle8iDialect.cs b/src/NHibernate/Dialect/Oracle8iDialect.cs index 323c0ed4a56..41bf5441bac 100644 --- a/src/NHibernate/Dialect/Oracle8iDialect.cs +++ b/src/NHibernate/Dialect/Oracle8iDialect.cs @@ -75,9 +75,57 @@ public Oracle8iDialect() RegisterFunctions(); + RegisterKeywords(); + RegisterDefaultProperties(); } + #region private static readonly string[] DialectKeywords = { ... } + + private static readonly string[] DialectKeywords = + { + "asc", + "bfile", + "binary_double", + "binary_float", + "cluster", + "compress", + "desc", + "exclusive", + "identified", + "index", + "lock", + "long", + "long raw", + "minus", + "mode", + "nocompress", + "nowait", + "number", + "nvarchar2", + "option", + "pctfree", + "prior", + "public", + "raw", + "rename", + "resource", + "rowid", + "share", + "size", + "synonym", + "varchar2", + "view", + "xmltype", + }; + + #endregion + + protected virtual void RegisterKeywords() + { + RegisterKeywords(DialectKeywords); + } + protected virtual void RegisterGuidTypeMapping() { RegisterColumnType(DbType.Guid, "RAW(16)"); diff --git a/src/NHibernate/Dialect/PostgreSQLDialect.cs b/src/NHibernate/Dialect/PostgreSQLDialect.cs index c20ee556d13..f33ce63a5d6 100644 --- a/src/NHibernate/Dialect/PostgreSQLDialect.cs +++ b/src/NHibernate/Dialect/PostgreSQLDialect.cs @@ -82,6 +82,41 @@ public PostgreSQLDialect() // Register the date function, since when used in LINQ select clauses, NH must know the data type. RegisterFunction("date", new SQLFunctionTemplate(NHibernateUtil.Date, "cast(?1 as date)")); + + RegisterKeywords(); + } + + #region private static readonly string[] DialectKeywords = { ... } + + private static readonly string[] DialectKeywords = + { + "analyse", + "analyze", + "asc", + "concurrently", + "current_catalog", + "current_schema", + "deferrable", + "desc", + "freeze", + "ilike", + "initially", + "isnull", + "limit", + "notnull", + "offset", + "placing", + "returning", + "session_user", + "variadic", + "verbose", + }; + + #endregion + + protected virtual void RegisterKeywords() + { + RegisterKeywords(DialectKeywords); } public override string AddColumnString diff --git a/src/NHibernate/Dialect/SQLiteDialect.cs b/src/NHibernate/Dialect/SQLiteDialect.cs index 52d8ae8642e..da47b16ceee 100644 --- a/src/NHibernate/Dialect/SQLiteDialect.cs +++ b/src/NHibernate/Dialect/SQLiteDialect.cs @@ -88,35 +88,90 @@ protected virtual void RegisterFunctions() RegisterFunction("round", new StandardSQLFunction("round")); } + #region private static readonly string[] DialectKeywords = { ... } + + private static readonly string[] DialectKeywords = + { + "abort", + "action", + "after", + "analyze", + "asc", + "attach", + "autoincrement", + "before", + "bit", + "bool", + "boolean", + "cascade", + "conflict", + "counter", + "currency", + "database", + "datetime", + "deferrable", + "deferred", + "desc", + "detach", + "exclusive", + "explain", + "fail", + "general", + "glob", + "guid", + "ignore", + "image", + "index", + "indexed", + "initially", + "instead", + "isnull", + "key", + "limit", + "logical", + "long", + "longtext", + "memo", + "money", + "note", + "notnull", + "ntext", + "nvarchar", + "offset", + "oleobject", + "plan", + "pragma", + "query", + "raise", + "regexp", + "reindex", + "rename", + "replace", + "restrict", + "single", + "smalldate", + "smalldatetime", + "smallmoney", + "sql_variant", + "string", + "temp", + "temporary", + "text", + "tinyint", + "transaction", + "uniqueidentifier", + "vacuum", + "varbinary", + "view", + "virtual", + "yesno", + }; + + #endregion + protected virtual void RegisterKeywords() { - RegisterKeyword("int"); // Used in our function templates. - RegisterKeyword("integer"); // a commonly-used alias for 'int' - RegisterKeyword("tinyint"); - RegisterKeyword("smallint"); - RegisterKeyword("bigint"); - RegisterKeyword("numeric"); - RegisterKeyword("decimal"); - RegisterKeyword("bit"); - RegisterKeyword("money"); - RegisterKeyword("smallmoney"); - RegisterKeyword("float"); - RegisterKeyword("real"); - RegisterKeyword("datetime"); - RegisterKeyword("smalldatetime"); - RegisterKeyword("char"); - RegisterKeyword("varchar"); - RegisterKeyword("text"); - RegisterKeyword("nchar"); - RegisterKeyword("nvarchar"); - RegisterKeyword("ntext"); - RegisterKeyword("binary"); - RegisterKeyword("varbinary"); - RegisterKeyword("image"); - RegisterKeyword("cursor"); - RegisterKeyword("timestamp"); - RegisterKeyword("uniqueidentifier"); - RegisterKeyword("sql_variant"); + RegisterKeywords(DialectKeywords); } protected virtual void RegisterDefaultProperties() diff --git a/src/NHibernate/Dialect/Schema/AbstractDataBaseSchema.cs b/src/NHibernate/Dialect/Schema/AbstractDataBaseSchema.cs index 66e4b986ab4..5ae17dbd564 100644 --- a/src/NHibernate/Dialect/Schema/AbstractDataBaseSchema.cs +++ b/src/NHibernate/Dialect/Schema/AbstractDataBaseSchema.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Data; using System.Data.Common; @@ -26,6 +27,8 @@ protected DbConnection Connection get { return connection; } } + public virtual bool IncludeDataTypesInReservedWords => true; + #region IDataBaseSchema Members public virtual bool StoresMixedCaseQuotedIdentifiers @@ -93,12 +96,22 @@ public virtual DataTable GetForeignKeys(string catalog, string schema, string ta public virtual ISet GetReservedWords() { - var result = new HashSet(); + var result = new HashSet(StringComparer.OrdinalIgnoreCase); DataTable dtReservedWords = connection.GetSchema(DbMetaDataCollectionNames.ReservedWords); foreach (DataRow row in dtReservedWords.Rows) { result.Add(row["ReservedWord"].ToString()); } + + if (IncludeDataTypesInReservedWords) + { + DataTable dtTypes = connection.GetSchema(DbMetaDataCollectionNames.DataTypes); + foreach (DataRow row in dtTypes.Rows) + { + result.Add(row["TypeName"].ToString()); + } + } + return result; } @@ -109,4 +122,4 @@ protected virtual string ForeignKeysSchemaName #endregion } -} \ No newline at end of file +} diff --git a/src/NHibernate/Dialect/Schema/PostgreSQLMetadata.cs b/src/NHibernate/Dialect/Schema/PostgreSQLMetadata.cs index bbb4c4369c7..b4977075e99 100644 --- a/src/NHibernate/Dialect/Schema/PostgreSQLMetadata.cs +++ b/src/NHibernate/Dialect/Schema/PostgreSQLMetadata.cs @@ -9,6 +9,8 @@ public class PostgreSQLDataBaseMetadata : AbstractDataBaseSchema { public PostgreSQLDataBaseMetadata(DbConnection connection) : base(connection) { } + public override bool IncludeDataTypesInReservedWords => false; + public override ITableMetadata GetTableMetadata(DataRow rs, bool extras) { return new PostgreSQLTableMetadata(rs, this, extras); diff --git a/src/NHibernate/Dialect/Schema/SybaseAnywhereMetaData.cs b/src/NHibernate/Dialect/Schema/SybaseAnywhereMetaData.cs index 08e312f2572..61b82c1386f 100644 --- a/src/NHibernate/Dialect/Schema/SybaseAnywhereMetaData.cs +++ b/src/NHibernate/Dialect/Schema/SybaseAnywhereMetaData.cs @@ -18,7 +18,7 @@ public override ITableMetadata GetTableMetadata(DataRow rs, bool extras) public override ISet GetReservedWords() { - var result = new HashSet(); + var result = new HashSet(StringComparer.OrdinalIgnoreCase); DataTable dtReservedWords = Connection.GetSchema(DbMetaDataCollectionNames.ReservedWords); foreach (DataRow row in dtReservedWords.Rows) { @@ -143,4 +143,4 @@ public SybaseAnywhereForeignKeyMetaData(DataRow rs) : base(rs) Name = (string) rs["COLUMN_NAME"]; } } -} \ No newline at end of file +} diff --git a/src/NHibernate/Dialect/SybaseSQLAnywhere10Dialect.cs b/src/NHibernate/Dialect/SybaseSQLAnywhere10Dialect.cs index c2622f0e148..a1094fcd836 100644 --- a/src/NHibernate/Dialect/SybaseSQLAnywhere10Dialect.cs +++ b/src/NHibernate/Dialect/SybaseSQLAnywhere10Dialect.cs @@ -344,18 +344,134 @@ protected virtual void RegisterMiscellaneousFunctions() RegisterFunction("watcomsql", new StandardSQLFunction("watcomsql", NHibernateUtil.String)); } + #region private static readonly string[] DialectKeywords = { ... } + + private static readonly string[] DialectKeywords = + { + "aes_decrypt", + "asc", + "attach", + "backup", + "bit", + "bottom", + "break", + "capability", + "cascade", + "char_convert", + "checkpoint", + "clear", + "comment", + "compressed", + "conflict", + "convert", + "dbspace", + "deleting", + "desc", + "detach", + "elseif", + "encrypted", + "endif", + "exception", + "existing", + "externlogin", + "force", + "forward", + "goto", + "holdlock", + "identified", + "index", + "inserting", + "install", + "instead", + "integrated", + "iq", + "isolation", + "json", + "kerberos", + "key", + "lock", + "login", + "long", + "membership", + "message", + "mode", + "modify", + "noholdlock", + "notify", + "nvarchar", + "off", + "openstring", + "openxml", + "option", + "options", + "others", + "passthrough", + "print", + "privileges", + "proc", + "publication", + "raiserror", + "readtext", + "reference", + "refresh", + "remote", + "remove", + "rename", + "reorganize", + "resource", + "restore", + "restrict", + "rowtype", + "save", + "session", + "setuser", + "share", + "spatial", + "sqlcode", + "stop", + "subtrans", + "subtransaction", + "synchronize", + "temporary", + "timeline", + "tinyint", + "truncate", + "tsequal", + "unbounded", + "uniqueidentifier", + "unsigned", + "updating", + "validate", + "varbinary", + "varbit", + "variable", + "varray", + "view", + "wait", + "waitfor", + "work", + "writetext", + "xml", + }; + + #endregion + protected virtual void RegisterKeywords() { - RegisterKeyword("TOP"); - RegisterKeyword("FIRST"); - RegisterKeyword("FETCH"); - RegisterKeyword("START"); - RegisterKeyword("AT"); - RegisterKeyword("WITH"); - RegisterKeyword("CONTAINS"); - RegisterKeyword("REGEXP"); - RegisterKeyword("SIMILAR"); - RegisterKeyword("SEQUENCE"); + // Register driver returned keywords for SQL Anywhere 16 + RegisterKeywords(DialectKeywords); + + // Keywords originally registered for SQL Anywhere 10 (none are in the above list) + RegisterKeyword("top"); + RegisterKeyword("first"); + RegisterKeyword("fetch"); + RegisterKeyword("start"); + RegisterKeyword("at"); + RegisterKeyword("with"); + RegisterKeyword("contains"); + RegisterKeyword("regexp"); + RegisterKeyword("similar"); + RegisterKeyword("sequence"); } #region IDENTITY or AUTOINCREMENT support diff --git a/src/NHibernate/Dialect/SybaseSQLAnywhere12Dialect.cs b/src/NHibernate/Dialect/SybaseSQLAnywhere12Dialect.cs index d7075f0411c..e99a40a3b26 100644 --- a/src/NHibernate/Dialect/SybaseSQLAnywhere12Dialect.cs +++ b/src/NHibernate/Dialect/SybaseSQLAnywhere12Dialect.cs @@ -63,10 +63,10 @@ public SybaseSQLAnywhere12Dialect() new protected void RegisterKeywords() { - RegisterKeyword("NEAR"); - RegisterKeyword("LIMIT"); - RegisterKeyword("OFFSET"); - RegisterKeyword("DATETIMEOFFSET"); + RegisterKeyword("near"); + RegisterKeyword("limit"); + RegisterKeyword("offset"); + RegisterKeyword("datetimeoffset"); } new void RegisterDateTimeTypeMappings() diff --git a/src/NHibernate/Impl/SessionFactoryImpl.cs b/src/NHibernate/Impl/SessionFactoryImpl.cs index 33f3bfab4bf..df7867f830c 100644 --- a/src/NHibernate/Impl/SessionFactoryImpl.cs +++ b/src/NHibernate/Impl/SessionFactoryImpl.cs @@ -201,7 +201,7 @@ public SessionFactoryImpl(Configuration cfg, IMapping mapping, Settings settings } if (settings.IsAutoQuoteEnabled) { - SchemaMetadataUpdater.QuoteTableAndColumns(cfg); + SchemaMetadataUpdater.QuoteTableAndColumns(cfg, Dialect); } } catch (NotSupportedException) diff --git a/src/NHibernate/NHibernate.csproj b/src/NHibernate/NHibernate.csproj index 6841701fd9e..d1053596580 100644 --- a/src/NHibernate/NHibernate.csproj +++ b/src/NHibernate/NHibernate.csproj @@ -145,6 +145,7 @@ + diff --git a/src/NHibernate/SqlCommand/Template.cs b/src/NHibernate/SqlCommand/Template.cs index 16fc8fbbebc..b1fc30c1198 100644 --- a/src/NHibernate/SqlCommand/Template.cs +++ b/src/NHibernate/SqlCommand/Template.cs @@ -308,7 +308,7 @@ private static bool IsFunctionOrKeyword(string lcToken, string nextToken, Dialec return "(".Equals(nextToken) || Keywords.Contains(lcToken) || functionRegistry.HasFunction(lcToken) || - dialect.Keywords.Contains(lcToken) || + dialect.IsKeyword(lcToken) || dialect.IsKnownToken(lcToken, nextToken) || FunctionKeywords.Contains(lcToken); } @@ -321,4 +321,4 @@ private static bool IsIdentifier(string token, Dialect.Dialect dialect) ); } } -} \ No newline at end of file +} diff --git a/src/NHibernate/Tool/hbm2ddl/SchemaExport.cs b/src/NHibernate/Tool/hbm2ddl/SchemaExport.cs index 742653c698b..badd97585d0 100644 --- a/src/NHibernate/Tool/hbm2ddl/SchemaExport.cs +++ b/src/NHibernate/Tool/hbm2ddl/SchemaExport.cs @@ -56,14 +56,16 @@ private void Initialize() { return; } + dialect = Dialect.Dialect.GetDialect(configProperties); + string autoKeyWordsImport = PropertiesHelper.GetString(Environment.Hbm2ddlKeyWords, configProperties, "not-defined"); autoKeyWordsImport = autoKeyWordsImport.ToLowerInvariant(); if (autoKeyWordsImport == Hbm2DDLKeyWords.AutoQuote) { - SchemaMetadataUpdater.QuoteTableAndColumns(cfg); + SchemaMetadataUpdater.Update(cfg, dialect); + SchemaMetadataUpdater.QuoteTableAndColumns(cfg, dialect); } - dialect = Dialect.Dialect.GetDialect(configProperties); dropSQL = cfg.GenerateDropSchemaScript(dialect); createSQL = cfg.GenerateSchemaCreationScript(dialect); formatter = (PropertiesHelper.GetBoolean(Environment.FormatSql, configProperties, true) ? FormatStyle.Ddl : FormatStyle.None).Formatter; diff --git a/src/NHibernate/Tool/hbm2ddl/SchemaMetadataUpdater.cs b/src/NHibernate/Tool/hbm2ddl/SchemaMetadataUpdater.cs index 0b4b760f305..2ebccd46af5 100644 --- a/src/NHibernate/Tool/hbm2ddl/SchemaMetadataUpdater.cs +++ b/src/NHibernate/Tool/hbm2ddl/SchemaMetadataUpdater.cs @@ -1,3 +1,4 @@ +using System; using NHibernate.Cfg; using NHibernate.Engine; using NHibernate.Mapping; @@ -8,71 +9,73 @@ namespace NHibernate.Tool.hbm2ddl // Candidate to be exstensions of ISessionFactory and Configuration public static class SchemaMetadataUpdater { - public static void Update(ISessionFactory sessionFactory) + public static void Update(ISessionFactoryImplementor sessionFactory) { - var factory = (ISessionFactoryImplementor) sessionFactory; - var dialect = factory.Dialect; - var connectionHelper = new SuppliedConnectionProviderConnectionHelper(factory.ConnectionProvider); - factory.Dialect.Keywords.UnionWith(GetReservedWords(dialect, connectionHelper)); + UpdateDialectKeywords( + sessionFactory.Dialect, + new SuppliedConnectionProviderConnectionHelper(sessionFactory.ConnectionProvider)); } - public static void QuoteTableAndColumns(Configuration configuration) + public static void Update(Configuration configuration, Dialect.Dialect dialect) { - ISet reservedDb = GetReservedWords(configuration.GetDerivedProperties()); - foreach (var cm in configuration.ClassMappings) - { - QuoteTable(cm.Table, reservedDb); - } - foreach (var cm in configuration.CollectionMappings) - { - QuoteTable(cm.Table, reservedDb); - } + UpdateDialectKeywords( + dialect, + new ManagedProviderConnectionHelper(configuration.GetDerivedProperties())); } - private static ISet GetReservedWords(IDictionary cfgProperties) + static void UpdateDialectKeywords(Dialect.Dialect dialect, IConnectionHelper connectionHelper) { - var dialect = Dialect.Dialect.GetDialect(cfgProperties); - var connectionHelper = new ManagedProviderConnectionHelper(cfgProperties); - return GetReservedWords(dialect, connectionHelper); + dialect.RegisterKeywords(GetReservedWords(dialect, connectionHelper)); } - private static ISet GetReservedWords(Dialect.Dialect dialect, IConnectionHelper connectionHelper) + static IEnumerable GetReservedWords(Dialect.Dialect dialect, IConnectionHelper connectionHelper) { - ISet reservedDb = new HashSet(); connectionHelper.Prepare(); try { var metaData = dialect.GetDataBaseSchema(connectionHelper.Connection); - foreach (var rw in metaData.GetReservedWords()) - { - reservedDb.Add(rw.ToLowerInvariant()); - } + return metaData.GetReservedWords(); } finally { connectionHelper.Release(); } - return reservedDb; } - private static void QuoteTable(Table table, ICollection reservedDb) + [Obsolete("Use the overload that passes dialect so keywords will be updated and persisted before auto-quoting")] + public static void QuoteTableAndColumns(Configuration configuration) + { + // Instantiates a new instance of the dialect so doesn't benefit from the Update call. + var dialect = Dialect.Dialect.GetDialect(configuration.GetDerivedProperties()); + Update(configuration, dialect); + QuoteTableAndColumns(configuration, dialect); + } + + public static void QuoteTableAndColumns(Configuration configuration, Dialect.Dialect dialect) { - if (!table.IsQuoted && reservedDb.Contains(table.Name.ToLowerInvariant())) + foreach (var cm in configuration.ClassMappings) { - table.Name = GetNhQuoted(table.Name); + QuoteTable(cm.Table, dialect); } - foreach (var column in table.ColumnIterator) + foreach (var cm in configuration.CollectionMappings) { - if (!column.IsQuoted && reservedDb.Contains(column.Name.ToLowerInvariant())) - { - column.Name = GetNhQuoted(column.Name); - } + QuoteTable(cm.Table, dialect); } } - private static string GetNhQuoted(string name) + private static void QuoteTable(Table table, Dialect.Dialect dialect) { - return "`" + name + "`"; + if (!table.IsQuoted && dialect.IsKeyword(table.Name)) + { + table.IsQuoted = true; + } + foreach (var column in table.ColumnIterator) + { + if (!column.IsQuoted && dialect.IsKeyword(column.Name)) + { + column.IsQuoted = true; + } + } } } -} \ No newline at end of file +} diff --git a/src/NHibernate/Tool/hbm2ddl/SchemaUpdate.cs b/src/NHibernate/Tool/hbm2ddl/SchemaUpdate.cs index 6224e13e2d0..24842177754 100644 --- a/src/NHibernate/Tool/hbm2ddl/SchemaUpdate.cs +++ b/src/NHibernate/Tool/hbm2ddl/SchemaUpdate.cs @@ -11,6 +11,7 @@ namespace NHibernate.Tool.hbm2ddl public class SchemaUpdate { private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof (SchemaUpdate)); + private bool wasInitialized; private readonly Configuration configuration; private readonly IConnectionHelper connectionHelper; private readonly Dialect.Dialect dialect; @@ -42,6 +43,24 @@ public SchemaUpdate(Configuration cfg, Settings settings) formatter = (settings.SqlStatementLogger.FormatSql ? FormatStyle.Ddl : FormatStyle.None).Formatter; } + private void Initialize() + { + if (wasInitialized) + { + return; + } + + string autoKeyWordsImport = PropertiesHelper.GetString(Environment.Hbm2ddlKeyWords, configuration.Properties, "not-defined"); + autoKeyWordsImport = autoKeyWordsImport.ToLowerInvariant(); + if (autoKeyWordsImport == Hbm2DDLKeyWords.AutoQuote) + { + SchemaMetadataUpdater.Update(configuration, dialect); + SchemaMetadataUpdater.QuoteTableAndColumns(configuration, dialect); + } + + wasInitialized = true; + } + /// /// Returns a List of all Exceptions which occurred during the export. /// @@ -137,12 +156,7 @@ public void Execute(Action scriptAction, bool doUpdate) { log.Info("Running hbm2ddl schema update"); - string autoKeyWordsImport = PropertiesHelper.GetString(Environment.Hbm2ddlKeyWords, configuration.Properties, "not-defined"); - autoKeyWordsImport = autoKeyWordsImport.ToLowerInvariant(); - if (autoKeyWordsImport == Hbm2DDLKeyWords.AutoQuote) - { - SchemaMetadataUpdater.QuoteTableAndColumns(configuration); - } + Initialize(); DbConnection connection; DbCommand stmt = null;