1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Data.SqlClient;
using System.Data.Metadata.Edm;
using System.Data.Common.CommandTrees;
namespace SampleEntityFrameworkProvider
{
/// <summary>
/// <see cref="SymbolTable"/>
/// This class represents an extent/nested select statement,
/// or a column.
///
/// The important fields are Name, Type and NewName.
/// NewName starts off the same as Name, and is then modified as necessary.
///
///
/// The rest are used by special symbols.
/// e.g. NeedsRenaming is used by columns to indicate that a new name must
/// be picked for the column in the second phase of translation.
///
/// IsUnnest is used by symbols for a collection expression used as a from clause.
/// This allows <see cref="SqlGenerator.AddFromSymbol(SqlSelectStatement, string, Symbol, bool)"/> to add the column list
/// after the alias.
///
/// </summary>
class Symbol : ISqlFragment
{
private Dictionary<string, Symbol> columns = new Dictionary<string, Symbol>(StringComparer.CurrentCultureIgnoreCase);
internal Dictionary<string, Symbol> Columns
{
get { return columns; }
}
private bool needsRenaming = false;
internal bool NeedsRenaming
{
get { return needsRenaming; }
set { needsRenaming = value; }
}
bool isUnnest = false;
internal bool IsUnnest
{
get { return isUnnest; }
set { isUnnest = value; }
}
string name;
public string Name
{
get { return name; }
}
string newName;
public string NewName
{
get { return newName; }
set { newName = value; }
}
private TypeUsage type;
internal TypeUsage Type
{
get { return type; }
set { type = value; }
}
public Symbol(string name, TypeUsage type)
{
this.name = name;
this.newName = name;
this.Type = type;
}
#region ISqlFragment Members
/// <summary>
/// Write this symbol out as a string for sql. This is just
/// the new name of the symbol (which could be the same as the old name).
///
/// We rename columns here if necessary.
/// </summary>
/// <param name="writer"></param>
/// <param name="sqlGenerator"></param>
public void WriteSql(SqlWriter writer, SqlGenerator sqlGenerator)
{
if (this.NeedsRenaming)
{
string newName;
int i = sqlGenerator.AllColumnNames[this.NewName];
do
{
++i;
newName = this.Name + i.ToString(System.Globalization.CultureInfo.InvariantCulture);
} while (sqlGenerator.AllColumnNames.ContainsKey(newName));
sqlGenerator.AllColumnNames[this.NewName] = i;
// Prevent it from being renamed repeatedly.
this.NeedsRenaming = false;
this.NewName = newName;
// Add this column name to list of known names so that there are no subsequent
// collisions
sqlGenerator.AllColumnNames[newName] = 0;
}
writer.Write(SqlGenerator.QuoteIdentifier(this.NewName));
}
#endregion
}
}
|