sqlnorm.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. //------------------------------------------------------------------------------
  2. // <copyright file="SqlNorm.cs" company="Microsoft Corporation">
  3. // Copyright (c) Microsoft Corporation. All Rights Reserved.
  4. // Information Contained Herein is Proprietary and Confidential.
  5. // </copyright>
  6. // <owner current="true" primary="true">[....]</owner>
  7. // <owner current="true" primary="true">[....]</owner>
  8. // <owner current="true" primary="true">daltudov</owner>
  9. // <owner current="true" primary="true">[....]</owner>
  10. // <owner current="true" primary="false">beysims</owner>
  11. // <owner current="true" primary="false">[....]</owner>
  12. // <owner current="true" primary="false">vadimt</owner>
  13. // <owner current="false" primary="false">[....]</owner>
  14. // <owner current="false" primary="false">venkar</owner>
  15. //------------------------------------------------------------------------------
  16. //devnote: perf optimization: consider changing the calls to Array.Reverse to inline unsafe code
  17. using System;
  18. using System.Collections;
  19. using System.Diagnostics;
  20. using System.Data;
  21. using System.IO;
  22. using System.Globalization;
  23. using System.Reflection;
  24. using System.Runtime.InteropServices;
  25. using System.Security.Permissions;
  26. using System.Text;
  27. using System.Runtime.CompilerServices;
  28. namespace Microsoft.SqlServer.Server {
  29. // The class that holds the offset, field, and normalizer for
  30. // a particular field.
  31. internal sealed class FieldInfoEx: IComparable {
  32. internal readonly int offset;
  33. internal readonly FieldInfo fieldInfo;
  34. internal readonly Normalizer normalizer;
  35. internal FieldInfoEx(FieldInfo fi, int offset, Normalizer normalizer) {
  36. this.fieldInfo = fi;
  37. this.offset = offset;
  38. Debug.Assert(normalizer!=null, "normalizer argument should not be null!");
  39. this.normalizer = normalizer;
  40. }
  41. // Sort fields by field offsets.
  42. public int CompareTo(object other) {
  43. FieldInfoEx otherF = other as FieldInfoEx;
  44. if (otherF == null)
  45. return -1;
  46. return this.offset.CompareTo(otherF.offset);
  47. }
  48. }
  49. // The most complex normalizer, a udt normalizer
  50. internal sealed class BinaryOrderedUdtNormalizer: Normalizer {
  51. internal readonly FieldInfoEx[] m_fieldsToNormalize;
  52. private int m_size;
  53. private byte[] m_PadBuffer;
  54. internal readonly object NullInstance;
  55. //a boolean that tells us if a udt is a "top-level" udt,
  56. //i.e. one that does not require a null byte header.
  57. private bool m_isTopLevelUdt;
  58. [System.Security.Permissions.ReflectionPermission(System.Security.Permissions.SecurityAction.Assert, MemberAccess=true)]
  59. private FieldInfo[] GetFields (Type t) {
  60. return t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  61. }
  62. internal BinaryOrderedUdtNormalizer(Type t, bool isTopLevelUdt) {
  63. this.m_skipNormalize = false;
  64. if (this.m_skipNormalize) {
  65. //if skipping normalization, dont write the null
  66. //byte header for IsNull
  67. this.m_isTopLevelUdt = true;
  68. }
  69. //top level udt logic is disabled until we decide
  70. //what to do about nested udts
  71. this.m_isTopLevelUdt = true;
  72. // else
  73. // this.m_isTopLevelUdt = isTopLevelUdt;
  74. //get all the fields
  75. FieldInfo[] fields = GetFields (t);
  76. m_fieldsToNormalize = new FieldInfoEx[fields.Length];
  77. int i = 0;
  78. foreach (FieldInfo fi in fields) {
  79. int offset = Marshal.OffsetOf(fi.DeclaringType, fi.Name).ToInt32();
  80. m_fieldsToNormalize[i++] = new FieldInfoEx(fi, offset, GetNormalizer(fi.FieldType));
  81. }
  82. //sort by offset
  83. Array.Sort(m_fieldsToNormalize);
  84. //if this is not a top-level udt, do setup for null values.
  85. //null values need to compare less than all other values,
  86. //so prefix a null byte indicator.
  87. if (!this.m_isTopLevelUdt) {
  88. //get the null value for this type, special case for sql types, which
  89. //have a null field
  90. if (typeof(System.Data.SqlTypes.INullable).IsAssignableFrom(t)) {
  91. PropertyInfo pi = t.GetProperty("Null",
  92. BindingFlags.Public | BindingFlags.Static);
  93. if (pi == null || pi.PropertyType != t) {
  94. FieldInfo fi = t.GetField("Null", BindingFlags.Public | BindingFlags.Static);
  95. if (fi == null || fi.FieldType != t)
  96. throw new Exception("could not find Null field/property in nullable type " + t);
  97. else
  98. this.NullInstance = fi.GetValue(null);
  99. }
  100. else {
  101. this.NullInstance = pi.GetValue(null, null);
  102. }
  103. //create the padding buffer
  104. this.m_PadBuffer = new byte[this.Size-1];
  105. }
  106. }
  107. }
  108. internal bool IsNullable {
  109. get {
  110. return this.NullInstance != null;
  111. }
  112. }
  113. // Normalize the top-level udt
  114. internal void NormalizeTopObject(object udt, Stream s) {
  115. Normalize(null, udt, s);
  116. }
  117. // Denormalize a top-level udt and return it
  118. internal object DeNormalizeTopObject(Type t, Stream s) {
  119. return DeNormalizeInternal(t, s);
  120. }
  121. // Prevent inlining so that reflection calls are not moved to caller that may be in a different assembly that may have a different grant set.
  122. [MethodImpl(MethodImplOptions.NoInlining)]
  123. private object DeNormalizeInternal(Type t, Stream s) {
  124. object result = null;
  125. //if nullable and not the top object, read the null marker
  126. if (!this.m_isTopLevelUdt && typeof(System.Data.SqlTypes.INullable).IsAssignableFrom(t)) {
  127. byte nullByte = (byte) s.ReadByte();
  128. if (nullByte == 0) {
  129. result = this.NullInstance;
  130. s.Read(m_PadBuffer, 0, m_PadBuffer.Length);
  131. return result;
  132. }
  133. }
  134. if (result == null)
  135. result = Activator.CreateInstance(t);
  136. foreach (FieldInfoEx myField in m_fieldsToNormalize) {
  137. myField.normalizer.DeNormalize(myField.fieldInfo, result, s);
  138. }
  139. return result;
  140. }
  141. internal override void Normalize(FieldInfo fi, object obj, Stream s) {
  142. // if (fi != null)
  143. // Console.WriteLine("normalizing " + fi.FieldType + " pos " + s.Position);
  144. object inner;
  145. if (fi == null) {
  146. inner = obj;
  147. }
  148. else {
  149. inner = GetValue(fi, obj);
  150. }
  151. //If nullable and not the top object, write a null indicator
  152. System.Data.SqlTypes.INullable oNullable = inner as System.Data.SqlTypes.INullable;
  153. if (oNullable != null && !this.m_isTopLevelUdt) {
  154. if (oNullable.IsNull) {
  155. s.WriteByte(0);
  156. s.Write(m_PadBuffer, 0, m_PadBuffer.Length);
  157. return;
  158. }
  159. else {
  160. s.WriteByte(1);
  161. }
  162. }
  163. foreach (FieldInfoEx myField in m_fieldsToNormalize) {
  164. myField.normalizer.Normalize(myField.fieldInfo, inner, s);
  165. }
  166. }
  167. internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
  168. SetValue(fi, recvr, DeNormalizeInternal(fi.FieldType, s));
  169. }
  170. internal override int Size {
  171. get {
  172. if (m_size != 0)
  173. return m_size;
  174. if (this.IsNullable && !this.m_isTopLevelUdt)
  175. m_size = 1;
  176. foreach (FieldInfoEx myField in m_fieldsToNormalize) {
  177. m_size += myField.normalizer.Size;
  178. }
  179. return m_size;
  180. }
  181. }
  182. }
  183. internal abstract class Normalizer {
  184. /*
  185. protected internal static string GetString(byte[] array)
  186. {
  187. StringBuilder sb = new StringBuilder();
  188. //sb.Append("0x");
  189. foreach (byte b in array)
  190. {
  191. sb.Append(b.ToString("X2", CultureInfo.InvariantCulture));
  192. }
  193. return sb.ToString();
  194. }
  195. */
  196. protected bool m_skipNormalize;
  197. /*
  198. internal static bool IsByteOrderedUdt(Type t)
  199. {
  200. SqlUserDefinedTypeAttribute a = SerializationHelper.GetUdtAttribute(t);
  201. return a.IsByteOrdered;
  202. }
  203. */
  204. internal static Normalizer GetNormalizer(Type t) {
  205. Normalizer n = null;
  206. if (t.IsPrimitive) {
  207. if (t == typeof(byte))
  208. n = new ByteNormalizer();
  209. else if (t == typeof(sbyte))
  210. n = new SByteNormalizer();
  211. else if (t == typeof(bool))
  212. n = new BooleanNormalizer();
  213. else if (t == typeof(short))
  214. n = new ShortNormalizer();
  215. else if (t == typeof(ushort))
  216. n = new UShortNormalizer();
  217. else if (t == typeof(int))
  218. n = new IntNormalizer();
  219. else if (t == typeof(uint))
  220. n = new UIntNormalizer();
  221. else if (t == typeof(float))
  222. n = new FloatNormalizer();
  223. else if (t == typeof(double))
  224. n = new DoubleNormalizer();
  225. else if (t == typeof(long))
  226. n = new LongNormalizer();
  227. else if (t == typeof(ulong))
  228. n = new ULongNormalizer();
  229. }
  230. else if (t.IsValueType) {
  231. n = new BinaryOrderedUdtNormalizer(t, false);
  232. }
  233. if (n == null)
  234. throw new Exception(Res.GetString(Res.Sql_CanotCreateNormalizer, t.FullName));
  235. n.m_skipNormalize = false;
  236. return n;
  237. }
  238. internal abstract void Normalize(FieldInfo fi, object recvr, Stream s);
  239. internal abstract void DeNormalize(FieldInfo fi, object recvr, Stream s);
  240. protected void FlipAllBits(byte[] b) {
  241. for (int i = 0; i < b.Length; i++)
  242. b[i] = (byte) ~b[i];
  243. }
  244. [System.Security.Permissions.ReflectionPermission(System.Security.Permissions.SecurityAction.Assert, MemberAccess=true)]
  245. protected object GetValue(FieldInfo fi, object obj) {
  246. return fi.GetValue(obj);
  247. }
  248. [System.Security.Permissions.ReflectionPermission(System.Security.Permissions.SecurityAction.Assert, MemberAccess=true)]
  249. protected void SetValue(FieldInfo fi, object recvr, object value) {
  250. fi.SetValue(recvr, value);
  251. }
  252. internal abstract int Size { get; }
  253. }
  254. internal sealed class BooleanNormalizer: Normalizer {
  255. internal override void Normalize(FieldInfo fi, object obj, Stream s) {
  256. bool b = (bool) GetValue(fi, obj);
  257. // Console.WriteLine("normalized " + fi.FieldType + " " + fi.GetValue(obj)
  258. // + " to " + (b?"01":"00") + " pos " + s.Position);
  259. s.WriteByte((byte)(b?1:0));
  260. }
  261. internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
  262. byte b = (byte) s.ReadByte();
  263. SetValue(fi, recvr, b==1);
  264. }
  265. internal override int Size { get { return 1; } }
  266. }
  267. // I could not find a simple way to convert a sbyte to a byte
  268. // and vice versa in the framework api. Convert.ToSByte() checks that
  269. // the value is in range.
  270. // So, we just do the conversion inline.
  271. internal sealed class SByteNormalizer: Normalizer {
  272. internal override void Normalize(FieldInfo fi, object obj, Stream s) {
  273. sbyte sb = (sbyte) GetValue(fi, obj);
  274. byte b;
  275. unchecked {
  276. b = (byte) sb;
  277. }
  278. if (!this.m_skipNormalize)
  279. b ^= 0x80; //flip the sign bit
  280. s.WriteByte(b);
  281. }
  282. internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
  283. byte b = (byte) s.ReadByte();
  284. if (!this.m_skipNormalize)
  285. b ^= 0x80; //flip the sign bit
  286. sbyte sb;
  287. unchecked {
  288. sb = (sbyte) b;
  289. }
  290. SetValue(fi, recvr, sb);
  291. }
  292. internal override int Size { get { return 1; } }
  293. }
  294. internal sealed class ByteNormalizer: Normalizer {
  295. internal override void Normalize(FieldInfo fi, object obj, Stream s) {
  296. byte b = (byte) GetValue(fi, obj);
  297. s.WriteByte(b);
  298. }
  299. internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
  300. byte b = (byte) s.ReadByte();
  301. SetValue(fi, recvr, b);
  302. }
  303. internal override int Size { get { return 1; } }
  304. }
  305. internal sealed class ShortNormalizer: Normalizer {
  306. internal override void Normalize(FieldInfo fi, object obj, Stream s) {
  307. byte[] b = BitConverter.GetBytes((short) GetValue(fi, obj));
  308. if (!m_skipNormalize) {
  309. Array.Reverse(b);
  310. b[0] ^= 0x80;
  311. }
  312. s.Write(b, 0, b.Length);
  313. }
  314. internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
  315. byte[] b = new Byte[2];
  316. s.Read(b, 0, b.Length);
  317. if (!m_skipNormalize) {
  318. b[0] ^= 0x80;
  319. Array.Reverse(b);
  320. }
  321. SetValue(fi, recvr, BitConverter.ToInt16(b, 0));
  322. }
  323. internal override int Size { get { return 2; } }
  324. }
  325. internal sealed class UShortNormalizer: Normalizer {
  326. internal override void Normalize(FieldInfo fi, object obj, Stream s) {
  327. byte[] b = BitConverter.GetBytes((ushort) GetValue(fi, obj));
  328. if (!m_skipNormalize) {
  329. Array.Reverse(b);
  330. }
  331. s.Write(b, 0, b.Length);
  332. }
  333. internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
  334. byte[] b = new Byte[2];
  335. s.Read(b, 0, b.Length);
  336. if (!m_skipNormalize) {
  337. Array.Reverse(b);
  338. }
  339. SetValue(fi, recvr, BitConverter.ToUInt16(b, 0));
  340. }
  341. internal override int Size { get { return 2; } }
  342. }
  343. internal sealed class IntNormalizer: Normalizer {
  344. internal override void Normalize(FieldInfo fi, object obj, Stream s) {
  345. byte[] b = BitConverter.GetBytes((int) GetValue(fi, obj));
  346. if (!m_skipNormalize) {
  347. Array.Reverse(b);
  348. b[0] ^= 0x80;
  349. }
  350. // Console.WriteLine("normalized " + fi.FieldType + " " + fi.GetValue(obj)
  351. // + " to " + GetString(b) + " pos " + s.Position);
  352. s.Write(b, 0, b.Length);
  353. }
  354. internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
  355. byte[] b = new Byte[4];
  356. s.Read(b, 0, b.Length);
  357. if (!m_skipNormalize) {
  358. b[0] ^= 0x80;
  359. Array.Reverse(b);
  360. }
  361. SetValue(fi, recvr, BitConverter.ToInt32(b, 0));
  362. }
  363. internal override int Size { get { return 4; } }
  364. }
  365. internal sealed class UIntNormalizer: Normalizer {
  366. internal override void Normalize(FieldInfo fi, object obj, Stream s) {
  367. byte[] b = BitConverter.GetBytes((uint) GetValue(fi, obj));
  368. if (!m_skipNormalize) {
  369. Array.Reverse(b);
  370. }
  371. s.Write(b, 0, b.Length);
  372. }
  373. internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
  374. byte[] b = new byte[4];
  375. s.Read(b, 0, b.Length);
  376. if (!m_skipNormalize) {
  377. Array.Reverse(b);
  378. }
  379. SetValue(fi, recvr, BitConverter.ToUInt32(b, 0));
  380. }
  381. internal override int Size { get { return 4; } }
  382. }
  383. internal sealed class LongNormalizer: Normalizer {
  384. internal override void Normalize(FieldInfo fi, object obj, Stream s) {
  385. byte[] b = BitConverter.GetBytes((long) GetValue(fi, obj));
  386. if (!m_skipNormalize) {
  387. Array.Reverse(b);
  388. b[0] ^= 0x80;
  389. }
  390. s.Write(b, 0, b.Length);
  391. }
  392. internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
  393. byte[] b = new Byte[8];
  394. s.Read(b, 0, b.Length);
  395. if (!m_skipNormalize) {
  396. b[0] ^= 0x80;
  397. Array.Reverse(b);
  398. }
  399. SetValue(fi, recvr, BitConverter.ToInt64(b, 0));
  400. }
  401. internal override int Size { get { return 8; } }
  402. }
  403. internal sealed class ULongNormalizer: Normalizer {
  404. internal override void Normalize(FieldInfo fi, object obj, Stream s) {
  405. byte[] b = BitConverter.GetBytes((ulong) GetValue(fi, obj));
  406. if (!m_skipNormalize) {
  407. Array.Reverse(b);
  408. }
  409. // Console.WriteLine("normalized " + fi.FieldType + " " + fi.GetValue(obj)
  410. // + " to " + GetString(b));
  411. s.Write(b, 0, b.Length);
  412. }
  413. internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
  414. byte[] b = new Byte[8];
  415. s.Read(b, 0, b.Length);
  416. if (!m_skipNormalize) {
  417. Array.Reverse(b);
  418. }
  419. SetValue(fi, recvr, BitConverter.ToUInt64(b, 0));
  420. }
  421. internal override int Size { get { return 8; } }
  422. }
  423. internal sealed class FloatNormalizer: Normalizer {
  424. internal override void Normalize(FieldInfo fi, object obj, Stream s) {
  425. float f = (float) GetValue(fi, obj);
  426. byte[] b = BitConverter.GetBytes(f);
  427. if (!m_skipNormalize) {
  428. Array.Reverse(b);
  429. if ((b[0] & 0x80) == 0) {
  430. // This is a positive number.
  431. // Flip the highest bit
  432. b[0] ^= 0x80;
  433. }
  434. else {
  435. // This is a negative number.
  436. // If all zeroes, means it was a negative zero.
  437. // Treat it same as positive zero, so that
  438. // the normalized key will compare equal.
  439. if (f < 0)
  440. FlipAllBits(b);
  441. }
  442. }
  443. s.Write(b, 0, b.Length);
  444. }
  445. internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
  446. byte[] b = new Byte[4];
  447. s.Read(b, 0, b.Length);
  448. if (!m_skipNormalize) {
  449. if ((b[0] & 0x80) > 0) {
  450. // This is a positive number.
  451. // Flip the highest bit
  452. b[0] ^= 0x80;
  453. }
  454. else {
  455. // This is a negative number.
  456. FlipAllBits(b);
  457. }
  458. Array.Reverse(b);
  459. }
  460. SetValue(fi, recvr, BitConverter.ToSingle(b, 0));
  461. }
  462. internal override int Size { get { return 4; } }
  463. }
  464. internal sealed class DoubleNormalizer: Normalizer {
  465. internal override void Normalize(FieldInfo fi, object obj, Stream s) {
  466. double d = (double) GetValue(fi, obj);
  467. byte[] b = BitConverter.GetBytes(d);
  468. if (!m_skipNormalize) {
  469. Array.Reverse(b);
  470. if ((b[0] & 0x80) == 0) {
  471. // This is a positive number.
  472. // Flip the highest bit
  473. b[0] ^= 0x80;
  474. }
  475. else {
  476. // This is a negative number.
  477. if (d < 0) {
  478. // If all zeroes, means it was a negative zero.
  479. // Treat it same as positive zero, so that
  480. // the normalized key will compare equal.
  481. FlipAllBits(b);
  482. }
  483. }
  484. }
  485. // Console.WriteLine("normalized " + fi.FieldType + " " + fi.GetValue(obj)
  486. // + " to " + GetString(b));
  487. s.Write(b, 0, b.Length);
  488. }
  489. internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
  490. byte[] b = new Byte[8];
  491. s.Read(b, 0, b.Length);
  492. if (!m_skipNormalize) {
  493. if ((b[0] & 0x80) > 0) {
  494. // This is a positive number.
  495. // Flip the highest bit
  496. b[0] ^= 0x80;
  497. }
  498. else {
  499. // This is a negative number.
  500. FlipAllBits(b);
  501. }
  502. Array.Reverse(b);
  503. }
  504. SetValue(fi, recvr, BitConverter.ToDouble(b, 0));
  505. }
  506. internal override int Size { get { return 8; } }
  507. }
  508. }