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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
|
//---------------------------------------------------------------------
// <copyright file="Vars.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Metadata.Edm;
using System.Diagnostics;
using System.Globalization;
using System.Text;
namespace System.Data.Query.InternalTrees
{
/// <summary>
/// Types of variable
/// </summary>
internal enum VarType
{
/// <summary>
/// a parameter
/// </summary>
Parameter,
/// <summary>
/// Column of a table
/// </summary>
Column,
/// <summary>
/// A Computed var
/// </summary>
Computed,
/// <summary>
/// Var for SetOps (Union, Intersect, Except)
/// </summary>
SetOp,
/// <summary>
/// NotValid
/// </summary>
NotValid
}
/// <summary>
/// Same as a ValRef in SqlServer. I just like changing names :-)
/// </summary>
internal abstract class Var
{
int m_id;
VarType m_varType;
TypeUsage m_type;
internal Var(int id, VarType varType, TypeUsage type)
{
m_id = id;
m_varType = varType;
m_type = type;
}
/// <summary>
/// Id of this var
/// </summary>
internal int Id { get { return m_id; } }
/// <summary>
/// Kind of Var
/// </summary>
internal VarType VarType { get { return m_varType; } }
/// <summary>
/// Datatype of this Var
/// </summary>
internal TypeUsage Type { get { return m_type; } }
/// <summary>
/// Try to get the name of this Var.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
internal virtual bool TryGetName(out string name)
{
name = null;
return false;
}
/// <summary>
/// Debugging support
/// </summary>
/// <returns></returns>
public override string ToString()
{
return String.Format(CultureInfo.InvariantCulture, "{0}", this.Id); ;
}
}
/// <summary>
/// Describes a query parameter
/// </summary>
internal sealed class ParameterVar : Var
{
string m_paramName;
internal ParameterVar(int id, TypeUsage type, string paramName)
: base(id, VarType.Parameter, type)
{
m_paramName = paramName;
}
/// <summary>
/// Name of the parameter
/// </summary>
internal string ParameterName { get { return m_paramName; } }
/// <summary>
/// Get the name of this Var
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
internal override bool TryGetName(out string name)
{
name = this.ParameterName;
return true;
}
}
/// <summary>
/// Describes a column of a table
/// </summary>
internal sealed class ColumnVar : Var
{
ColumnMD m_columnMetadata;
Table m_table;
/// <summary>
/// Constructor
/// </summary>
/// <param name="id"></param>
/// <param name="table"></param>
/// <param name="columnMetadata"></param>
internal ColumnVar(int id, Table table, ColumnMD columnMetadata)
: base(id, VarType.Column, columnMetadata.Type)
{
m_table = table;
m_columnMetadata = columnMetadata;
}
/// <summary>
/// The table instance containing this column reference
/// </summary>
internal Table Table { get { return m_table; } }
/// <summary>
/// The column metadata for this column
/// </summary>
internal ColumnMD ColumnMetadata { get { return m_columnMetadata; } }
/// <summary>
/// Get the name of this column var
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
internal override bool TryGetName(out string name)
{
name = m_columnMetadata.Name;
return true;
}
}
/// <summary>
/// A computed expression. Defined by a VarDefOp
/// </summary>
internal sealed class ComputedVar : Var
{
internal ComputedVar(int id, TypeUsage type) : base(id, VarType.Computed, type)
{
}
}
/// <summary>
/// A SetOp Var - used as the output var for set operations (Union, Intersect, Except)
/// </summary>
internal sealed class SetOpVar : Var
{
internal SetOpVar(int id, TypeUsage type) : base(id, VarType.SetOp, type) { }
}
//
/// <summary>
/// A VarVec is a compressed representation of a set of variables - with no duplicates
/// and no ordering
///
/// A VarVec should be used in many places where we expect a number of vars to be
/// passed around; and we don't care particularly about the ordering of the vars
///
/// This is obviously not suitable for representing sort keys, but is still
/// reasonable for representing group by keys, and a variety of others.
///
/// </summary>
internal class VarVec : IEnumerable<Var>
{
#region Nested Classes
/// <summary>
/// A VarVec enumerator is a specialized enumerator for a VarVec.
/// </summary>
internal class VarVecEnumerator : IEnumerator<Var>, IDisposable
{
#region private state
private int m_position;
private Command m_command;
private BitArray m_bitArray;
#endregion
#region Constructors
/// <summary>
/// Constructs a new enumerator for the specified Vec
/// </summary>
/// <param name="vec"></param>
internal VarVecEnumerator(VarVec vec)
{
Init(vec);
}
#endregion
#region public surface
/// <summary>
/// Initialize the enumerator to enumerate over the supplied Vec
/// </summary>
/// <param name="vec"></param>
internal void Init(VarVec vec)
{
m_position = -1;
m_command = vec.m_command;
m_bitArray = vec.m_bitVector;
}
#endregion
#region IEnumerator<Var> Members
/// <summary>
/// Get the Var at the current position
/// </summary>
public Var Current
{
get { return (m_position >= 0 && m_position < m_bitArray.Count) ? m_command.GetVar(m_position) : (Var)null; }
}
#endregion
#region IEnumerator Members
object IEnumerator.Current
{
get { return Current;}
}
/// <summary>
/// Move to the next position
/// </summary>
/// <returns></returns>
public bool MoveNext()
{
m_position++;
for (; m_position < m_bitArray.Count; m_position++)
{
if (m_bitArray[m_position])
{
return true;
}
}
return false;
}
/// <summary>
/// Reset enumerator to start off again
/// </summary>
public void Reset()
{
m_position = -1;
}
#endregion
#region IDisposable Members
/// <summary>
/// Dispose of the current enumerator - return it to the Command
/// </summary>
public void Dispose()
{
// Technically, calling GC.SuppressFinalize is not required because the class does not
// have a finalizer, but it does no harm, protects against the case where a finalizer is added
// in the future, and prevents an FxCop warning.
GC.SuppressFinalize(this);
m_bitArray = null;
m_command.ReleaseVarVecEnumerator(this);
}
#endregion
}
#endregion
#region public methods
internal void Clear()
{
m_bitVector.Length = 0;
}
internal void And(VarVec other)
{
Align(other);
m_bitVector.And(other.m_bitVector);
}
internal void Or(VarVec other)
{
Align(other);
m_bitVector.Or(other.m_bitVector);
}
/// <summary>
/// Computes (this Minus other) by performing (this And (Not(other)))
/// A temp VarVec is used and released at the end of the operation
/// </summary>
/// <param name="other"></param>
internal void Minus(VarVec other)
{
VarVec tmp = m_command.CreateVarVec(other);
tmp.m_bitVector.Length = m_bitVector.Length;
tmp.m_bitVector.Not();
this.And(tmp);
m_command.ReleaseVarVec(tmp);
}
/// <summary>
/// Does this have a non-zero overlap with the other vec
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
internal bool Overlaps(VarVec other)
{
VarVec otherCopy = m_command.CreateVarVec(other);
otherCopy.And(this);
bool overlaps = !otherCopy.IsEmpty;
m_command.ReleaseVarVec(otherCopy);
return overlaps;
}
/// <summary>
/// Does this Vec include every var in the other vec?
/// Written this way deliberately under the assumption that "other"
/// is a relatively small vec
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
internal bool Subsumes(VarVec other)
{
for (int i = 0; i < other.m_bitVector.Count; i++)
{
if (other.m_bitVector[i] &&
((i >= this.m_bitVector.Count) || !this.m_bitVector[i]))
{
return false;
}
}
return true;
}
internal void InitFrom(VarVec other)
{
this.Clear();
this.m_bitVector.Length = other.m_bitVector.Length;
this.m_bitVector.Or(other.m_bitVector);
}
internal void InitFrom(IEnumerable<Var> other)
{
InitFrom(other, false);
}
internal void InitFrom(IEnumerable<Var> other, bool ignoreParameters)
{
this.Clear();
foreach (Var v in other)
{
if (!ignoreParameters || (v.VarType != VarType.Parameter))
{
this.Set(v);
}
}
}
/// <summary>
/// The enumerator pattern
/// </summary>
/// <returns></returns>
public IEnumerator<Var> GetEnumerator()
{
return m_command.GetVarVecEnumerator(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
/// <summary>
/// Number of vars in this set
/// </summary>
internal int Count
{
get
{
int count = 0;
foreach (Var v in this)
count++;
return count;
}
}
internal bool IsSet(Var v)
{
Align(v.Id);
return m_bitVector.Get(v.Id);
}
internal void Set(Var v)
{
Align(v.Id);
m_bitVector.Set(v.Id, true);
}
internal void Clear(Var v)
{
Align(v.Id);
m_bitVector.Set(v.Id, false);
}
/// <summary>
/// Is this Vec empty?
/// </summary>
internal bool IsEmpty
{
get { return this.First == null;}
}
/// <summary>
/// Get me the first var that is set
/// </summary>
internal Var First
{
get
{
foreach (Var v in this)
{
return v;
}
return null;
}
}
/// <summary>
/// Walk through the input varVec, replace any vars that have been "renamed" based
/// on the input varMap, and return the new VarVec
/// </summary>
/// <param name="varMap">dictionary of renamed vars</param>
/// <returns>a new VarVec</returns>
internal VarVec Remap(Dictionary<Var, Var> varMap)
{
VarVec newVec = m_command.CreateVarVec();
foreach (Var v in this)
{
Var newVar;
if (!varMap.TryGetValue(v, out newVar))
{
newVar = v;
}
newVec.Set(newVar);
}
return newVec;
}
#endregion
#region constructors
internal VarVec(Command command)
{
m_bitVector = new BitArray(64);
m_command = command;
}
#endregion
#region private methods
private void Align(VarVec other)
{
if (other.m_bitVector.Count == this.m_bitVector.Count)
return;
if (other.m_bitVector.Count > this.m_bitVector.Count)
{
this.m_bitVector.Length = other.m_bitVector.Count;
}
else
{
other.m_bitVector.Length = this.m_bitVector.Count;
}
}
private void Align(int idx)
{
if (idx >= m_bitVector.Count)
{
m_bitVector.Length = idx + 1;
}
}
/// <summary>
/// Debugging support
/// provide a string representation for debugging.
/// <returns></returns>
/// </summary>
public override string ToString()
{
StringBuilder sb = new StringBuilder();
string separator = String.Empty;
foreach (Var v in this)
{
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", separator, v.Id);
separator = ",";
}
return sb.ToString();
}
#endregion
#region private state
private BitArray m_bitVector;
private Command m_command;
#endregion
#region Clone
/// <summary>
/// Create a clone of this vec
/// </summary>
/// <returns></returns>
public VarVec Clone()
{
VarVec newVec = m_command.CreateVarVec();
newVec.InitFrom(this);
return newVec;
}
#endregion
}
/// <summary>
/// An ordered list of Vars. Use this when you need an ordering.
/// </summary>
[DebuggerDisplay("{{{ToString()}}}")]
internal class VarList : List<Var>
{
#region constructors
/// <summary>
/// Trivial constructor
/// </summary>
internal VarList() : base() { }
/// <summary>
/// Not so trivial constructor
/// </summary>
/// <param name="vars"></param>
internal VarList(IEnumerable<Var> vars) : base(vars) { }
#endregion
#region public methods
/// <summary>
/// Debugging support
/// provide a string representation for debugging.
/// <returns></returns>
/// </summary>
public override string ToString()
{
StringBuilder sb = new StringBuilder();
string separator = String.Empty;
foreach (Var v in this)
{
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", separator, v.Id);
separator = ",";
}
return sb.ToString();
}
#endregion
}
#region VarMap
/// <summary>
/// Helps map one variable to the next.
/// </summary>
internal class VarMap: Dictionary<Var, Var>
{
#region public surfaces
internal VarMap GetReverseMap()
{
VarMap reverseMap = new VarMap();
foreach (KeyValuePair<Var, Var> kv in this)
{
Var x;
// On the odd chance that a var is in the varMap more than once, the first one
// is going to be the one we want to use, because it might be the discriminator
// var;
if (!reverseMap.TryGetValue(kv.Value, out x))
{
reverseMap[kv.Value] = kv.Key;
}
}
return reverseMap;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
string separator = string.Empty;
foreach (Var v in this.Keys)
{
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}({1},{2})", separator, v.Id, this[v].Id);
separator = ",";
}
return sb.ToString();
}
#endregion
#region constructors
internal VarMap() : base() { }
#endregion
}
#endregion
}
|