Skip to content

Nh 3899 Fixes to avoid too long column aliases #503

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion src/NHibernate.Test/MappingTest/ColumnFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,53 @@ public void StringSqlType()
column.Length = 100;
Assert.AreEqual("NVARCHAR(100)", column.GetSqlType(_dialect, null));
}


[TestCase("xxxxyyyyz")]
[TestCase("xxxxyyyyzz")]
[TestCase("xxxxyyyyzzz")]
[TestCase("xxxxyyy4z", Description = "Non-letter digit character would be cut, make sure we don't skip length check.")]
[TestCase("xxxxyyyz4z", Description = "Non-letter digit character would be cut, make sure we don't skip length check.")]
[TestCase("xxxxyyyzz4z", Description = "Non-letter digit character would be cut, make sure we don't skip length check.")]
[TestCase("xxxxyyyy4", Description = "Non-letter digit character would be cut, make sure we don't skip length check.")]
[TestCase("xxxxyyyyz4", Description = "Non-letter digit character would be cut, make sure we don't skip length check.")]
[TestCase("xxxxyyyyzz4", Description = "Non-letter digit character would be cut, make sure we don't skip length check.")]
public void GetAliasRespectsMaxAliasLength(string columnName)
{
var dialect = new GenericDialect();

// Verify test case assumption.
Assert.That(dialect.MaxAliasLength, Is.EqualTo(10));

var column = new Column(columnName);
string generatedAlias = column.GetAlias(dialect);

Assert.That(generatedAlias, Has.Length.LessThanOrEqualTo(dialect.MaxAliasLength));
}


[TestCase("xxxxyyyyz")]
[TestCase("xxxxyyyyzz")]
[TestCase("xxxxyyyyzzz")]
[TestCase("xxxxyyy4z")]
[TestCase("xxxxyyyz4z")]
[TestCase("xxxxyyyzz4z")]
[TestCase("xxxxyyyy4")]
[TestCase("xxxxyyyyz4")]
[TestCase("xxxxyyyyzz4")]
public void GetAliasWithTableSuffixRespectsMaxAliasLength(string columnName)
{
var dialect = new GenericDialect();

// Verify test case assumption.
Assert.That(dialect.MaxAliasLength, Is.EqualTo(10));

var table = new Table();
var column = new Column(columnName);

string generatedAlias = column.GetAlias(dialect, table);

Assert.That(generatedAlias, Has.Length.LessThanOrEqualTo(dialect.MaxAliasLength));
}
}
}
}
56 changes: 36 additions & 20 deletions src/NHibernate/Mapping/Column.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,21 @@ public string GetQuotedName(Dialect.Dialect d)
return IsQuoted ? d.QuoteForColumnName(_name) : _name;
}

/**
* For any column name, generate an alias that is unique
* to that column name, and also 10 characters or less
* in length.
*/

/// <summary>
/// For any column name, generate an alias that is unique to that
/// column name, and also take Dialect.MaxAliasLength into account.
/// </summary>
public string GetAlias(Dialect.Dialect dialect)
{
return GetAlias(dialect.MaxAliasLength);
}

private string GetAlias(int maxAliasLength)
{
string alias = _name;
string suffix = UniqueInteger.ToString() + '_';
string suffix = UniqueInteger.ToString() + StringHelper.Underscore;

int lastLetter = StringHelper.LastIndexOfLetter(_name);
if (lastLetter == -1)
{
Expand All @@ -134,27 +139,38 @@ public string GetAlias(Dialect.Dialect dialect)
{
alias = _name.Substring(0, lastLetter + 1);
}
if (alias.Length > dialect.MaxAliasLength)
{
alias = alias.Substring(0, dialect.MaxAliasLength - suffix.Length);
}
bool useRawName = _name.Equals(alias) &&
!_quoted &&
!StringHelper.EqualsCaseInsensitive(_name, "rowid");

if (useRawName)
{
return alias;
}
else
// Updated logic ported from Hibernate's fix for HHH-8073.
// https://github.com/hibernate/hibernate-orm/commit/79073a98f0e4ed225fe4608b67594196f86d48d7
// To my mind it is weird - since the suffix is now always used, it
// seems "useRawName" is a misleading choice of variable name. For the same
// reason, the checks for "_quoted" and "rowid" looks redundant. If you remove
// those checks, then the double checks for total length can be reduced to one.
// But I will leave it like this for now to make it look similar. /Oskar 2016-08-20
bool useRawName = _name.Length + suffix.Length <= maxAliasLength &&
!_quoted &&
!StringHelper.EqualsCaseInsensitive(_name, "rowid");
if (!useRawName)
{
return alias + suffix;
if (suffix.Length >= maxAliasLength)
{
throw new MappingException(
string.Format(
"Unique suffix {0} length must be less than maximum {1} characters.",
suffix,
maxAliasLength));
}
if (alias.Length + suffix.Length > maxAliasLength)
alias = alias.Substring(0, maxAliasLength - suffix.Length);
}
return alias + suffix;
}

public string GetAlias(Dialect.Dialect dialect, Table table)
{
return GetAlias(dialect) + table.UniqueInteger + StringHelper.Underscore;
string suffix = table.UniqueInteger.ToString() + StringHelper.Underscore;
int maxAliasLength = dialect.MaxAliasLength - suffix.Length;
return GetAlias(maxAliasLength) + suffix;
}


Expand Down