From: <fab...@us...> - 2009-04-17 18:01:48
|
Revision: 4185 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4185&view=rev Author: fabiomaulo Date: 2009-04-17 18:01:35 +0000 (Fri, 17 Apr 2009) Log Message: ----------- Fix NH-1701 BREAKING CHANGES : see releasenotes.txt Modified Paths: -------------- trunk/nhibernate/releasenotes.txt trunk/nhibernate/src/NHibernate/Cfg/Environment.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate/Tool/hbm2ddl/SchemaExport.cs trunk/nhibernate/src/NHibernate/nhibernate-configuration.xsd trunk/nhibernate/src/NHibernate.Test/CfgTest/ConfigurationSerializationTests.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1443/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1521/Fixture.cs trunk/nhibernate/src/NHibernate.Test/Tools/hbm2ddl/SchemaExportTests/WithColumnTagFixture.cs trunk/nhibernate/src/NHibernate.Test/Tools/hbm2ddl/SchemaUpdate/MigrationFixture.cs trunk/nhibernate/src/NHibernate.Test/Tools/hbm2ddl/SchemaValidator/SchemaValidateFixture.cs Added Paths: ----------- trunk/nhibernate/src/NHibernate/Pretty/ trunk/nhibernate/src/NHibernate/Pretty/DdlFormatter.cs Modified: trunk/nhibernate/releasenotes.txt =================================================================== --- trunk/nhibernate/releasenotes.txt 2009-04-17 15:18:39 UTC (rev 4184) +++ trunk/nhibernate/releasenotes.txt 2009-04-17 18:01:35 UTC (rev 4185) @@ -6,6 +6,7 @@ * If you want work using lazy loading with Castle.DynamicProxy2 now you must deploy NHibernate.ByteCode.Castle.dll * If you want work using lazy loading with Spring.Aop now you must deploy NHibernate.ByteCode.Spring.dll * compatible only with .NET2.0 SP1 or above (System.DateTimeOffset) + * In SchemaExport.Execute the parameter "format" was removed; (NH-1701) enabled configuration property format_sql (default true) ##### Possible Breaking Changes for external frameworks ##### * ISession interface has additional methods Modified: trunk/nhibernate/src/NHibernate/Cfg/Environment.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/Environment.cs 2009-04-17 15:18:39 UTC (rev 4184) +++ trunk/nhibernate/src/NHibernate/Cfg/Environment.cs 2009-04-17 18:01:35 UTC (rev 4185) @@ -95,6 +95,9 @@ public const string CurrentSessionContextClass = "current_session_context_class"; public const string UseSqlComments = "use_sql_comments"; + /// <summary> Enable formatting of SQL logged to the console</summary> + public const string FormatSql = "format_sql"; + // Unused, Java-specific public const string UseGetGeneratedKeys = "jdbc.use_get_generated_keys"; Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-04-17 15:18:39 UTC (rev 4184) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-04-17 18:01:35 UTC (rev 4185) @@ -479,6 +479,7 @@ <Compile Include="Impl\FutureQueryBatch.cs" /> <Compile Include="Impl\FutureCriteriaBatch.cs" /> <Compile Include="Impl\FutureValue.cs" /> + <Compile Include="Pretty\DdlFormatter.cs" /> <Compile Include="Properties\BackFieldStrategy.cs" /> <Compile Include="Bytecode\CodeDom\BytecodeProviderImpl.cs" /> <Compile Include="Bytecode\IAccessOptimizer.cs" /> Added: trunk/nhibernate/src/NHibernate/Pretty/DdlFormatter.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Pretty/DdlFormatter.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Pretty/DdlFormatter.cs 2009-04-17 18:01:35 UTC (rev 4185) @@ -0,0 +1,157 @@ +using System.Collections.Generic; +using System.Text; +using NHibernate.Util; + +namespace NHibernate.Pretty +{ + public class DdlFormatter + { + private const string Indent1 = "\n "; + private const string Indent2 = "\n "; + private const string Indent3 = "\n "; + + private readonly string sql; + + public DdlFormatter(string sql) + { + this.sql = sql; + } + + /// <summary> Format an SQL statement using simple rules: + /// a) Insert newline after each comma; + /// b) Indent three spaces after each inserted newline; + /// If the statement contains single/double quotes return unchanged, + /// it is too complex and could be broken by simple formatting. + /// </summary> + public virtual string Format() + { + if (sql.ToLowerInvariant().StartsWith("create table")) + { + return FormatCreateTable(); + } + else if (sql.ToLowerInvariant().StartsWith("alter table")) + { + return FormatAlterTable(); + } + else if (sql.ToLowerInvariant().StartsWith("comment on")) + { + return FormatCommentOn(); + } + else + { + return Indent1 + sql; + } + } + + private string FormatCommentOn() + { + StringBuilder result = new StringBuilder(60).Append(Indent1); + IEnumerator<string> tokens = (new StringTokenizer(sql, " '[]\"", true)).GetEnumerator(); + + bool quoted = false; + while (tokens.MoveNext()) + { + string token = tokens.Current; + result.Append(token); + if (IsQuote(token)) + { + quoted = !quoted; + } + else if (!quoted) + { + if ("is".Equals(token)) + { + result.Append(Indent2); + } + } + } + + return result.ToString(); + } + + private string FormatAlterTable() + { + StringBuilder result = new StringBuilder(60).Append(Indent1); + IEnumerator<string> tokens = (new StringTokenizer(sql, " (,)'[]\"", true)).GetEnumerator(); + + bool quoted = false; + while (tokens.MoveNext()) + { + string token = tokens.Current; + if (IsQuote(token)) + { + quoted = !quoted; + } + else if (!quoted) + { + if (IsBreak(token)) + { + result.Append(Indent3); + } + } + result.Append(token); + } + + return result.ToString(); + } + + private string FormatCreateTable() + { + StringBuilder result = new StringBuilder(60).Append(Indent1); + IEnumerator<string> tokens = (new StringTokenizer(sql, "(,)'[]\"", true)).GetEnumerator(); + + int depth = 0; + bool quoted = false; + while (tokens.MoveNext()) + { + string token = tokens.Current; + if (IsQuote(token)) + { + quoted = !quoted; + result.Append(token); + } + else if (quoted) + { + result.Append(token); + } + else + { + if (")".Equals(token)) + { + depth--; + if (depth == 0) + { + result.Append(Indent1); + } + } + result.Append(token); + if (",".Equals(token) && depth == 1) + { + result.Append(Indent2); + } + if ("(".Equals(token)) + { + depth++; + if (depth == 1) + { + result.Append(Indent3); + } + } + } + } + + return result.ToString(); + } + + private static bool IsBreak(string token) + { + return "drop".Equals(token) || "add".Equals(token) || "references".Equals(token) || "foreign".Equals(token) + || "on".Equals(token); + } + + private static bool IsQuote(string token) + { + return "\"".Equals(token) || "`".Equals(token) || "]".Equals(token) || "[".Equals(token) || "'".Equals(token); + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Tool/hbm2ddl/SchemaExport.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tool/hbm2ddl/SchemaExport.cs 2009-04-17 15:18:39 UTC (rev 4184) +++ trunk/nhibernate/src/NHibernate/Tool/hbm2ddl/SchemaExport.cs 2009-04-17 18:01:35 UTC (rev 4185) @@ -2,11 +2,12 @@ using System.Collections.Generic; using System.Data; using System.IO; -using System.Text; using log4net; using NHibernate.Cfg; using NHibernate.Connection; +using NHibernate.Pretty; using NHibernate.Util; +using Environment=NHibernate.Cfg.Environment; namespace NHibernate.Tool.hbm2ddl { @@ -20,12 +21,13 @@ public class SchemaExport { private static readonly ILog log = LogManager.GetLogger(typeof (SchemaExport)); - private readonly IDictionary<string, string> connectionProperties; + private readonly IDictionary<string, string> configProperties; private readonly string[] createSQL; private readonly Dialect.Dialect dialect; private readonly string[] dropSQL; private string delimiter; private string outputFile; + private readonly bool format; /// <summary> /// Create a schema exported for a given Configuration @@ -38,13 +40,14 @@ /// database connection properties /// </summary> /// <param name="cfg">The NHibernate Configuration to generate the schema from.</param> - /// <param name="connectionProperties">The Properties to use when connecting to the Database.</param> - public SchemaExport(Configuration cfg, IDictionary<string, string> connectionProperties) + /// <param name="configProperties">The Properties to use when connecting to the Database.</param> + public SchemaExport(Configuration cfg, IDictionary<string, string> configProperties) { - this.connectionProperties = connectionProperties; - dialect = Dialect.Dialect.GetDialect(connectionProperties); + this.configProperties = configProperties; + dialect = Dialect.Dialect.GetDialect(configProperties); dropSQL = cfg.GenerateDropSchemaScript(dialect); createSQL = cfg.GenerateSchemaCreationScript(dialect); + format = PropertiesHelper.GetBoolean(Environment.FormatSql, configProperties, true); } /// <summary> @@ -75,17 +78,17 @@ /// <param name="script"><see langword="true" /> if the ddl should be outputted in the Console.</param> /// <param name="export"><see langword="true" /> if the ddl should be executed against the Database.</param> /// <remarks> - /// This is a convenience method that calls <see cref="Execute(bool, bool, bool, bool)"/> and sets - /// the justDrop parameter to false and the format parameter to true. + /// This is a convenience method that calls <see cref="Execute(bool, bool, bool)"/> and sets + /// the justDrop parameter to false. /// </remarks> public void Create(bool script, bool export) { - Execute(script, export, false, true); + Execute(script, export, false); } public void Create(Action<string> scriptAction, bool export) { - Execute(scriptAction, export, false, true); + Execute(scriptAction, export, false); } /// <summary> @@ -94,28 +97,20 @@ /// <param name="script"><see langword="true" /> if the ddl should be outputted in the Console.</param> /// <param name="export"><see langword="true" /> if the ddl should be executed against the Database.</param> /// <remarks> - /// This is a convenience method that calls <see cref="Execute(bool, bool, bool, bool)"/> and sets - /// the justDrop and format parameter to true. + /// This is a convenience method that calls <see cref="Execute(bool, bool, bool)"/> and sets + /// the justDrop parameter to true. /// </remarks> public void Drop(bool script, bool export) { - Execute(script, export, true, true); + Execute(script, export, true); } - private void Execute(Action<string> scriptAction, bool export, bool format, bool throwOnError, TextWriter exportOutput, + private void Execute(Action<string> scriptAction, bool export, bool throwOnError, TextWriter exportOutput, IDbCommand statement, string sql) { try { - string formatted; - if (format) - { - formatted = Format(sql); - } - else - { - formatted = sql; - } + string formatted = Format(sql); if (delimiter != null) { @@ -154,7 +149,6 @@ /// <param name="script"><see langword="true" /> if the ddl should be outputted in the Console.</param> /// <param name="export"><see langword="true" /> if the ddl should be executed against the Database.</param> /// <param name="justDrop"><see langword="true" /> if only the ddl to drop the Database objects should be executed.</param> - /// <param name="format"><see langword="true" /> if the ddl should be nicely formatted instead of one statement per line.</param> /// <param name="connection"> /// The connection to use when executing the commands when export is <see langword="true" />. /// Must be an opened connection. The method doesn't close the connection. @@ -165,20 +159,20 @@ /// This overload is provided mainly to enable use of in memory databases. /// It does NOT close the given connection! /// </remarks> - public void Execute(bool script, bool export, bool justDrop, bool format, IDbConnection connection, + public void Execute(bool script, bool export, bool justDrop, IDbConnection connection, TextWriter exportOutput) { if (script) { - Execute(Console.WriteLine, export, justDrop, format, connection, exportOutput); + Execute(Console.WriteLine, export, justDrop, connection, exportOutput); } else { - Execute(null, export, justDrop, format, connection, exportOutput); + Execute(null, export, justDrop, connection, exportOutput); } } - public void Execute(Action<string> scriptAction, bool export, bool justDrop, bool format, IDbConnection connection, + public void Execute(Action<string> scriptAction, bool export, bool justDrop, IDbConnection connection, TextWriter exportOutput) { IDbCommand statement = null; @@ -196,14 +190,14 @@ { for (int i = 0; i < dropSQL.Length; i++) { - Execute(scriptAction, export, format, false, exportOutput, statement, dropSQL[i]); + Execute(scriptAction, export, false, exportOutput, statement, dropSQL[i]); } if (!justDrop) { for (int j = 0; j < createSQL.Length; j++) { - Execute(scriptAction, export, format, true, exportOutput, statement, createSQL[j]); + Execute(scriptAction, export, true, exportOutput, statement, createSQL[j]); } } } @@ -240,23 +234,22 @@ /// <param name="script"><see langword="true" /> if the ddl should be outputted in the Console.</param> /// <param name="export"><see langword="true" /> if the ddl should be executed against the Database.</param> /// <param name="justDrop"><see langword="true" /> if only the ddl to drop the Database objects should be executed.</param> - /// <param name="format"><see langword="true" /> if the ddl should be nicely formatted instead of one statement per line.</param> /// <remarks> /// This method allows for both the drop and create ddl script to be executed. /// </remarks> - public void Execute(bool script, bool export, bool justDrop, bool format) + public void Execute(bool script, bool export, bool justDrop) { if (script) { - Execute(Console.WriteLine, export, justDrop, format); + Execute(Console.WriteLine, export, justDrop); } else { - Execute(null, export, justDrop, format); + Execute(null, export, justDrop); } } - public void Execute(Action<string> scriptAction, bool export, bool justDrop, bool format) + public void Execute(Action<string> scriptAction, bool export, bool justDrop) { IDbConnection connection = null; StreamWriter fileOutput = null; @@ -268,9 +261,9 @@ props[de.Key] = de.Value; } - if (connectionProperties != null) + if (configProperties != null) { - foreach (var de in connectionProperties) + foreach (var de in configProperties) { props[de.Key] = de.Value; } @@ -289,7 +282,7 @@ connection = connectionProvider.GetConnection(); } - Execute(scriptAction, export, justDrop, format, connection, fileOutput); + Execute(scriptAction, export, justDrop, connection, fileOutput); } catch (HibernateException) { @@ -312,76 +305,13 @@ } /// <summary> - /// Format an SQL statement using simple rules + /// Format an SQL statement. /// </summary> /// <param name="sql">The string containing the sql to format.</param> /// <returns>A string that contains formatted sql.</returns> - /// <remarks> - /// The simple rules to used when formatting are: - /// <list type="number"> - /// <item> - /// <description>Insert a newline after each comma</description> - /// </item> - /// <item> - /// <description>Indent three spaces after each inserted newline</description> - /// </item> - /// <item> - /// <description> - /// If the statement contains single/double quotes return unchanged because - /// it is too complex and could be broken by simple formatting. - /// </description> - /// </item> - /// </list> - /// </remarks> - private static string Format(string sql) + private string Format(string sql) { - if (sql.IndexOf("\"") > 0 || sql.IndexOf("'") > 0) - { - return sql; - } - - string formatted; - - if (StringHelper.StartsWithCaseInsensitive(sql, "create table")) - { - var result = new StringBuilder(60); - var tokens = new StringTokenizer(sql, "(,)", true); - - int depth = 0; - - foreach (string tok in tokens) - { - if (StringHelper.ClosedParen.Equals(tok)) - { - depth--; - if (depth == 0) - { - result.Append("\n"); - } - } - result.Append(tok); - if (StringHelper.Comma.Equals(tok) && depth == 1) - { - result.Append("\n "); - } - if (StringHelper.OpenParen.Equals(tok)) - { - depth++; - if (depth == 1) - { - result.Append("\n "); - } - } - } - - formatted = result.ToString(); - } - else - { - formatted = sql; - } - - return formatted; + return format ? new DdlFormatter(sql).Format() : sql; } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/nhibernate-configuration.xsd =================================================================== --- trunk/nhibernate/src/NHibernate/nhibernate-configuration.xsd 2009-04-17 15:18:39 UTC (rev 4184) +++ trunk/nhibernate/src/NHibernate/nhibernate-configuration.xsd 2009-04-17 18:01:35 UTC (rev 4185) @@ -98,7 +98,8 @@ <xs:enumeration value="adonet.factory_class" /> <xs:enumeration value="default_batch_fetch_size" /> <xs:enumeration value="default_entity_mode" /> - <xs:enumeration value="use_sql_comments" /> + <xs:enumeration value="use_sql_comments" /> + <xs:enumeration value="format_sql" /> </xs:restriction> </xs:simpleType> </xs:attribute> Modified: trunk/nhibernate/src/NHibernate.Test/CfgTest/ConfigurationSerializationTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/CfgTest/ConfigurationSerializationTests.cs 2009-04-17 15:18:39 UTC (rev 4184) +++ trunk/nhibernate/src/NHibernate.Test/CfgTest/ConfigurationSerializationTests.cs 2009-04-17 18:01:35 UTC (rev 4185) @@ -37,7 +37,7 @@ Assert.That(cfg, Is.Not.Null); var export = new SchemaExport(cfg); - export.Execute(true, true, false, true); + export.Execute(true, true, false); ISessionFactory sf = cfg.BuildSessionFactory(); using (ISession session = sf.OpenSession()) { Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1443/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1443/Fixture.cs 2009-04-17 15:18:39 UTC (rev 4184) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1443/Fixture.cs 2009-04-17 18:01:35 UTC (rev 4185) @@ -13,7 +13,7 @@ { var su = new SchemaExport(cfg); var sb = new StringBuilder(500); - su.Execute(x => sb.AppendLine(x), false, false, true); + su.Execute(x => sb.AppendLine(x), false, false); string script = sb.ToString(); Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1521/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1521/Fixture.cs 2009-04-17 15:18:39 UTC (rev 4184) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1521/Fixture.cs 2009-04-17 18:01:35 UTC (rev 4185) @@ -20,7 +20,7 @@ { var su = new SchemaExport(configuration); var sb = new StringBuilder(500); - su.Execute(x => sb.AppendLine(x), false, false, true); + su.Execute(x => sb.AppendLine(x), false, false); string script = sb.ToString(); Assert.That(script, Text.Contains("if exists (select * from dbo.sysobjects where id = object_id(N'nhibernate.dbo.Aclass') and OBJECTPROPERTY(id, N'IsUserTable') = 1)")); } Modified: trunk/nhibernate/src/NHibernate.Test/Tools/hbm2ddl/SchemaExportTests/WithColumnTagFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Tools/hbm2ddl/SchemaExportTests/WithColumnTagFixture.cs 2009-04-17 15:18:39 UTC (rev 4184) +++ trunk/nhibernate/src/NHibernate.Test/Tools/hbm2ddl/SchemaExportTests/WithColumnTagFixture.cs 2009-04-17 18:01:35 UTC (rev 4185) @@ -20,7 +20,7 @@ Configuration cfg = TestConfigurationHelper.GetDefaultConfiguration(); using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(mapping)) cfg.AddInputStream(stream); - new SchemaExport(cfg).Execute(s => script.AppendLine(s), false, false, false); + new SchemaExport(cfg).Execute(s => script.AppendLine(s), false, false); string wholeScript = script.ToString(); Assert.That(wholeScript, Text.Contains("default SYSTEM_USER")); Modified: trunk/nhibernate/src/NHibernate.Test/Tools/hbm2ddl/SchemaUpdate/MigrationFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Tools/hbm2ddl/SchemaUpdate/MigrationFixture.cs 2009-04-17 15:18:39 UTC (rev 4184) +++ trunk/nhibernate/src/NHibernate.Test/Tools/hbm2ddl/SchemaUpdate/MigrationFixture.cs 2009-04-17 18:01:35 UTC (rev 4185) @@ -19,7 +19,7 @@ Configuration v1cfg = TestConfigurationHelper.GetDefaultConfiguration(); using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource1)) v1cfg.AddInputStream(stream); - new SchemaExport(v1cfg).Execute(false, true, true, false); + new SchemaExport(v1cfg).Execute(false, true, true); Tool.hbm2ddl.SchemaUpdate v1schemaUpdate = new Tool.hbm2ddl.SchemaUpdate(v1cfg); v1schemaUpdate.Execute(true, true); Modified: trunk/nhibernate/src/NHibernate.Test/Tools/hbm2ddl/SchemaValidator/SchemaValidateFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Tools/hbm2ddl/SchemaValidator/SchemaValidateFixture.cs 2009-04-17 15:18:39 UTC (rev 4184) +++ trunk/nhibernate/src/NHibernate.Test/Tools/hbm2ddl/SchemaValidator/SchemaValidateFixture.cs 2009-04-17 18:01:35 UTC (rev 4185) @@ -19,7 +19,7 @@ string resource1 = "NHibernate.Test.Tools.hbm2ddl.SchemaValidator.1_Version.hbm.xml"; Configuration v1cfg = TestConfigurationHelper.GetDefaultConfiguration(); using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource1)) - new NHibernate.Tool.hbm2ddl.SchemaExport(v1cfg).Execute(true,true,false,true); + new NHibernate.Tool.hbm2ddl.SchemaExport(v1cfg).Execute(true,true,false); var v1schemaValidator = new NHibernate.Tool.hbm2ddl.SchemaValidator((v1cfg)); v1schemaValidator.Validate(); @@ -37,7 +37,7 @@ v1cfg.AddInputStream(stream); using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource2)) v2cfg.AddInputStream(stream); - new NHibernate.Tool.hbm2ddl.SchemaExport(v1cfg).Execute(true, true, false, true); + new NHibernate.Tool.hbm2ddl.SchemaExport(v1cfg).Execute(true, true, false); var v2schemaValidator = new NHibernate.Tool.hbm2ddl.SchemaValidator((v2cfg)); try { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |