SmiMetaData.cs 88 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712
  1. //------------------------------------------------------------------------------
  2. // <copyright file="SmiMetaData.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">Microsoft</owner>
  6. // <owner current="true" primary="false">Microsoft</owner>
  7. //------------------------------------------------------------------------------
  8. namespace Microsoft.SqlServer.Server {
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Diagnostics;
  12. using System.Data;
  13. using System.Data.Sql;
  14. using System.Data.SqlTypes;
  15. using System.Globalization;
  16. // DESIGN NOTES
  17. //
  18. // The following classes are a tight inheritance heirarchy, and are not designed for
  19. // being inherited outside of this file. Instances are guaranteed to be immutable, and
  20. // outside classes rely on this fact.
  21. //
  22. // The various levels may not all be used outside of this file, but for clarity of purpose
  23. // they are all usefull distinctions to make.
  24. //
  25. // In general, moving lower in the type heirarchy exposes less portable values. Thus,
  26. // the root metadata can be readily shared across different (MSSQL) servers and clients,
  27. // while QueryMetaData has attributes tied to a specific query, running against specific
  28. // data storage on a specific server.
  29. //
  30. // The SmiMetaData heirarchy does not do data validation on retail builds! It will assert
  31. // that the values passed to it have been validated externally, however.
  32. //
  33. // SmiMetaData
  34. //
  35. // Root of the heirarchy.
  36. // Represents the minimal amount of metadata required to represent any Sql Server datum
  37. // without any references to any particular server or schema (thus, no server-specific multi-part names).
  38. // It could be used to communicate solely between two disconnected clients, for instance.
  39. //
  40. // NOTE: It currently does not contain sufficient information to describe typed XML, since we
  41. // don't have a good server-independent mechanism for such.
  42. //
  43. // This class is also used as implementation for the public SqlMetaData class.
  44. internal class SmiMetaData {
  45. private SqlDbType _databaseType; // Main enum that determines what is valid for other attributes.
  46. private long _maxLength; // Varies for variable-length types, others are fixed value per type
  47. private byte _precision; // Varies for SqlDbType.Decimal, others are fixed value per type
  48. private byte _scale; // Varies for SqlDbType.Decimal, others are fixed value per type
  49. private long _localeId; // Valid only for character types, others are 0
  50. private SqlCompareOptions _compareOptions; // Valid only for character types, others are SqlCompareOptions.Default
  51. private Type _clrType; // Varies for SqlDbType.Udt, others are fixed value per type.
  52. private string _udtAssemblyQualifiedName; // Valid only for UDT types when _clrType is not available
  53. private bool _isMultiValued; // Multiple instances per value? (I.e. tables, arrays)
  54. private IList<SmiExtendedMetaData> _fieldMetaData; // Metadata of fields for structured types
  55. private SmiMetaDataPropertyCollection _extendedProperties; // Extended properties, Key columns, sort order, etc.
  56. // DevNote: For now, since the list of extended property types is small, we can handle them in a simple list.
  57. // In the future, we may need to create a more performant storage & lookup mechanism, such as a hash table
  58. // of lists indexed by type of property or an array of lists with a well-known index for each type.
  59. // Limits for attributes (SmiMetaData will assert that these limits as applicable in constructor)
  60. internal const long UnlimitedMaxLengthIndicator = -1; // unlimited (except by implementation) max-length.
  61. internal const long MaxUnicodeCharacters = 4000; // Maximum for limited type
  62. internal const long MaxANSICharacters = 8000; // Maximum for limited type
  63. internal const long MaxBinaryLength = 8000; // Maximum for limited type
  64. internal const int MinPrecision = 1; // SqlDecimal defines max precision
  65. internal const int MinScale = 0; // SqlDecimal defines max scale
  66. internal const int MaxTimeScale = 7; // Max scale for time, datetime2, and datetimeoffset
  67. internal static readonly DateTime MaxSmallDateTime = new DateTime(2079, 06, 06, 23, 59, 29, 998);
  68. internal static readonly DateTime MinSmallDateTime = new DateTime(1899, 12, 31, 23, 59, 29, 999);
  69. internal static readonly SqlMoney MaxSmallMoney = new SqlMoney( ( (Decimal)Int32.MaxValue ) / 10000 );
  70. internal static readonly SqlMoney MinSmallMoney = new SqlMoney( ( (Decimal)Int32.MinValue ) / 10000 );
  71. internal const SqlCompareOptions DefaultStringCompareOptions = SqlCompareOptions.IgnoreCase
  72. | SqlCompareOptions.IgnoreKanaType | SqlCompareOptions.IgnoreWidth;
  73. internal const long MaxNameLength = 128; // maximum length in the server is 128.
  74. private static readonly IList<SmiExtendedMetaData> __emptyFieldList = new List<SmiExtendedMetaData>().AsReadOnly();
  75. // Precision to max length lookup table
  76. private static byte[] __maxLenFromPrecision = new byte[] {5,5,5,5,5,5,5,5,5,9,9,9,9,9,
  77. 9,9,9,9,9,13,13,13,13,13,13,13,13,13,17,17,17,17,17,17,17,17,17,17};
  78. // Scale offset to max length lookup table
  79. private static byte[] __maxVarTimeLenOffsetFromScale = new byte[] { 2, 2, 2, 1, 1, 0, 0, 0 };
  80. // Defaults
  81. // SmiMetaData(SqlDbType, MaxLen, Prec, Scale, CompareOptions)
  82. internal static readonly SmiMetaData DefaultBigInt = new SmiMetaData(SqlDbType.BigInt, 8, 19, 0, SqlCompareOptions.None); // SqlDbType.BigInt
  83. internal static readonly SmiMetaData DefaultBinary = new SmiMetaData(SqlDbType.Binary, 1, 0, 0, SqlCompareOptions.None); // SqlDbType.Binary
  84. internal static readonly SmiMetaData DefaultBit = new SmiMetaData(SqlDbType.Bit, 1, 1, 0, SqlCompareOptions.None); // SqlDbType.Bit
  85. internal static readonly SmiMetaData DefaultChar_NoCollation = new SmiMetaData(SqlDbType.Char, 1, 0, 0, DefaultStringCompareOptions);// SqlDbType.Char
  86. internal static readonly SmiMetaData DefaultDateTime = new SmiMetaData(SqlDbType.DateTime, 8, 23, 3, SqlCompareOptions.None); // SqlDbType.DateTime
  87. internal static readonly SmiMetaData DefaultDecimal = new SmiMetaData(SqlDbType.Decimal, 9, 18, 0, SqlCompareOptions.None); // SqlDbType.Decimal
  88. internal static readonly SmiMetaData DefaultFloat = new SmiMetaData(SqlDbType.Float, 8, 53, 0, SqlCompareOptions.None); // SqlDbType.Float
  89. internal static readonly SmiMetaData DefaultImage = new SmiMetaData(SqlDbType.Image, UnlimitedMaxLengthIndicator,0, 0, SqlCompareOptions.None); // SqlDbType.Image
  90. internal static readonly SmiMetaData DefaultInt = new SmiMetaData(SqlDbType.Int, 4, 10, 0, SqlCompareOptions.None); // SqlDbType.Int
  91. internal static readonly SmiMetaData DefaultMoney = new SmiMetaData(SqlDbType.Money, 8, 19, 4, SqlCompareOptions.None); // SqlDbType.Money
  92. internal static readonly SmiMetaData DefaultNChar_NoCollation = new SmiMetaData(SqlDbType.NChar, 1, 0, 0, DefaultStringCompareOptions);// SqlDbType.NChar
  93. internal static readonly SmiMetaData DefaultNText_NoCollation = new SmiMetaData(SqlDbType.NText, UnlimitedMaxLengthIndicator,0, 0, DefaultStringCompareOptions);// SqlDbType.NText
  94. internal static readonly SmiMetaData DefaultNVarChar_NoCollation = new SmiMetaData(SqlDbType.NVarChar, MaxUnicodeCharacters, 0, 0, DefaultStringCompareOptions);// SqlDbType.NVarChar
  95. internal static readonly SmiMetaData DefaultReal = new SmiMetaData(SqlDbType.Real, 4, 24, 0, SqlCompareOptions.None); // SqlDbType.Real
  96. internal static readonly SmiMetaData DefaultUniqueIdentifier = new SmiMetaData(SqlDbType.UniqueIdentifier, 16, 0, 0, SqlCompareOptions.None); // SqlDbType.UniqueIdentifier
  97. internal static readonly SmiMetaData DefaultSmallDateTime = new SmiMetaData(SqlDbType.SmallDateTime, 4, 16, 0, SqlCompareOptions.None); // SqlDbType.SmallDateTime
  98. internal static readonly SmiMetaData DefaultSmallInt = new SmiMetaData(SqlDbType.SmallInt, 2, 5, 0, SqlCompareOptions.None); // SqlDbType.SmallInt
  99. internal static readonly SmiMetaData DefaultSmallMoney = new SmiMetaData(SqlDbType.SmallMoney, 4, 10, 4, SqlCompareOptions.None); // SqlDbType.SmallMoney
  100. internal static readonly SmiMetaData DefaultText_NoCollation = new SmiMetaData(SqlDbType.Text, UnlimitedMaxLengthIndicator,0, 0, DefaultStringCompareOptions);// SqlDbType.Text
  101. internal static readonly SmiMetaData DefaultTimestamp = new SmiMetaData(SqlDbType.Timestamp, 8, 0, 0, SqlCompareOptions.None); // SqlDbType.Timestamp
  102. internal static readonly SmiMetaData DefaultTinyInt = new SmiMetaData(SqlDbType.TinyInt, 1, 3, 0, SqlCompareOptions.None); // SqlDbType.TinyInt
  103. internal static readonly SmiMetaData DefaultVarBinary = new SmiMetaData(SqlDbType.VarBinary, MaxBinaryLength, 0, 0, SqlCompareOptions.None); // SqlDbType.VarBinary
  104. internal static readonly SmiMetaData DefaultVarChar_NoCollation = new SmiMetaData(SqlDbType.VarChar, MaxANSICharacters, 0, 0, DefaultStringCompareOptions);// SqlDbType.VarChar
  105. internal static readonly SmiMetaData DefaultVariant = new SmiMetaData(SqlDbType.Variant, 8016, 0, 0, SqlCompareOptions.None); // SqlDbType.Variant
  106. internal static readonly SmiMetaData DefaultXml = new SmiMetaData(SqlDbType.Xml, UnlimitedMaxLengthIndicator,0, 0, DefaultStringCompareOptions);// SqlDbType.Xml
  107. internal static readonly SmiMetaData DefaultUdt_NoType = new SmiMetaData(SqlDbType.Udt, 0, 0, 0, SqlCompareOptions.None); // SqlDbType.Udt
  108. internal static readonly SmiMetaData DefaultStructured = new SmiMetaData(SqlDbType.Structured, 0, 0, 0, SqlCompareOptions.None); // SqlDbType.Structured
  109. internal static readonly SmiMetaData DefaultDate = new SmiMetaData(SqlDbType.Date, 3, 10, 0, SqlCompareOptions.None); // SqlDbType.Date
  110. internal static readonly SmiMetaData DefaultTime = new SmiMetaData(SqlDbType.Time, 5, 0, 7, SqlCompareOptions.None); // SqlDbType.Time
  111. internal static readonly SmiMetaData DefaultDateTime2 = new SmiMetaData(SqlDbType.DateTime2, 8, 0, 7, SqlCompareOptions.None); // SqlDbType.DateTime2
  112. internal static readonly SmiMetaData DefaultDateTimeOffset = new SmiMetaData(SqlDbType.DateTimeOffset, 10, 0, 7, SqlCompareOptions.None); // SqlDbType.DateTimeOffset
  113. // No default for generic UDT
  114. // character defaults hook thread-local culture to get collation
  115. internal static SmiMetaData DefaultChar {
  116. get {
  117. return new SmiMetaData(
  118. DefaultChar_NoCollation.SqlDbType,
  119. DefaultChar_NoCollation.MaxLength,
  120. DefaultChar_NoCollation.Precision,
  121. DefaultChar_NoCollation.Scale,
  122. System.Globalization.CultureInfo.CurrentCulture.LCID,
  123. SqlCompareOptions.IgnoreCase | SqlCompareOptions.IgnoreKanaType | SqlCompareOptions.IgnoreWidth,
  124. null
  125. );
  126. }
  127. }
  128. internal static SmiMetaData DefaultNChar {
  129. get {
  130. return new SmiMetaData(
  131. DefaultNChar_NoCollation.SqlDbType,
  132. DefaultNChar_NoCollation.MaxLength,
  133. DefaultNChar_NoCollation.Precision,
  134. DefaultNChar_NoCollation.Scale,
  135. System.Globalization.CultureInfo.CurrentCulture.LCID,
  136. SqlCompareOptions.IgnoreCase | SqlCompareOptions.IgnoreKanaType | SqlCompareOptions.IgnoreWidth,
  137. null
  138. );
  139. }
  140. }
  141. internal static SmiMetaData DefaultNText {
  142. get {
  143. return new SmiMetaData(
  144. DefaultNText_NoCollation.SqlDbType,
  145. DefaultNText_NoCollation.MaxLength,
  146. DefaultNText_NoCollation.Precision,
  147. DefaultNText_NoCollation.Scale,
  148. System.Globalization.CultureInfo.CurrentCulture.LCID,
  149. SqlCompareOptions.IgnoreCase | SqlCompareOptions.IgnoreKanaType | SqlCompareOptions.IgnoreWidth,
  150. null
  151. );
  152. }
  153. }
  154. internal static SmiMetaData DefaultNVarChar {
  155. get {
  156. return new SmiMetaData(
  157. DefaultNVarChar_NoCollation.SqlDbType,
  158. DefaultNVarChar_NoCollation.MaxLength,
  159. DefaultNVarChar_NoCollation.Precision,
  160. DefaultNVarChar_NoCollation.Scale,
  161. System.Globalization.CultureInfo.CurrentCulture.LCID,
  162. SqlCompareOptions.IgnoreCase | SqlCompareOptions.IgnoreKanaType | SqlCompareOptions.IgnoreWidth,
  163. null
  164. );
  165. }
  166. }
  167. internal static SmiMetaData DefaultText {
  168. get {
  169. return new SmiMetaData(
  170. DefaultText_NoCollation.SqlDbType,
  171. DefaultText_NoCollation.MaxLength,
  172. DefaultText_NoCollation.Precision,
  173. DefaultText_NoCollation.Scale,
  174. System.Globalization.CultureInfo.CurrentCulture.LCID,
  175. SqlCompareOptions.IgnoreCase | SqlCompareOptions.IgnoreKanaType | SqlCompareOptions.IgnoreWidth,
  176. null
  177. );
  178. }
  179. }
  180. internal static SmiMetaData DefaultVarChar {
  181. get {
  182. return new SmiMetaData(
  183. DefaultVarChar_NoCollation.SqlDbType,
  184. DefaultVarChar_NoCollation.MaxLength,
  185. DefaultVarChar_NoCollation.Precision,
  186. DefaultVarChar_NoCollation.Scale,
  187. System.Globalization.CultureInfo.CurrentCulture.LCID,
  188. SqlCompareOptions.IgnoreCase | SqlCompareOptions.IgnoreKanaType | SqlCompareOptions.IgnoreWidth,
  189. null
  190. );
  191. }
  192. }
  193. // The one and only constructor for use by outside code.
  194. //
  195. // Parameters that matter for given values of dbType (other parameters are ignored in favor of internal defaults).
  196. // Thus, if dbType parameter value is SqlDbType.Decimal, the values of precision and scale passed in are used, but
  197. // maxLength, localeId, compareOptions, etc are set to defaults for the Decimal type:
  198. // SqlDbType.BigInt: dbType
  199. // SqlDbType.Binary: dbType, maxLength
  200. // SqlDbType.Bit: dbType
  201. // SqlDbType.Char: dbType, maxLength, localeId, compareOptions
  202. // SqlDbType.DateTime: dbType
  203. // SqlDbType.Decimal: dbType, precision, scale
  204. // SqlDbType.Float: dbType
  205. // SqlDbType.Image: dbType
  206. // SqlDbType.Int: dbType
  207. // SqlDbType.Money: dbType
  208. // SqlDbType.NChar: dbType, maxLength, localeId, compareOptions
  209. // SqlDbType.NText: dbType, localeId, compareOptions
  210. // SqlDbType.NVarChar: dbType, maxLength, localeId, compareOptions
  211. // SqlDbType.Real: dbType
  212. // SqlDbType.UniqueIdentifier: dbType
  213. // SqlDbType.SmallDateTime: dbType
  214. // SqlDbType.SmallInt: dbType
  215. // SqlDbType.SmallMoney: dbType
  216. // SqlDbType.Text: dbType, localeId, compareOptions
  217. // SqlDbType.Timestamp: dbType
  218. // SqlDbType.TinyInt: dbType
  219. // SqlDbType.VarBinary: dbType, maxLength
  220. // SqlDbType.VarChar: dbType, maxLength, localeId, compareOptions
  221. // SqlDbType.Variant: dbType
  222. // PlaceHolder for value 24
  223. // SqlDbType.Xml: dbType
  224. // Placeholder for value 26
  225. // Placeholder for value 27
  226. // Placeholder for value 28
  227. // SqlDbType.Udt: dbType, userDefinedType
  228. //
  229. [ObsoleteAttribute( "Not supported as of SMI v2. Will be removed when v1 support dropped. Use ctor without columns param." )]
  230. internal SmiMetaData(
  231. SqlDbType dbType,
  232. long maxLength,
  233. byte precision,
  234. byte scale,
  235. long localeId,
  236. SqlCompareOptions compareOptions,
  237. Type userDefinedType,
  238. SmiMetaData[] columns) :
  239. // Implement as calling the new ctor
  240. this(
  241. dbType,
  242. maxLength,
  243. precision,
  244. scale,
  245. localeId,
  246. compareOptions,
  247. userDefinedType ) {
  248. Debug.Assert( null == columns, "Row types not supported" );
  249. }
  250. // SMI V100 (aka V3) constructor. Superceded in V200.
  251. internal SmiMetaData(
  252. SqlDbType dbType,
  253. long maxLength,
  254. byte precision,
  255. byte scale,
  256. long localeId,
  257. SqlCompareOptions compareOptions,
  258. Type userDefinedType) :
  259. this( dbType,
  260. maxLength,
  261. precision,
  262. scale,
  263. localeId,
  264. compareOptions,
  265. userDefinedType,
  266. false,
  267. null,
  268. null ) {
  269. }
  270. // SMI V200 ctor.
  271. internal SmiMetaData(
  272. SqlDbType dbType,
  273. long maxLength,
  274. byte precision,
  275. byte scale,
  276. long localeId,
  277. SqlCompareOptions compareOptions,
  278. Type userDefinedType,
  279. bool isMultiValued,
  280. IList<SmiExtendedMetaData> fieldTypes,
  281. SmiMetaDataPropertyCollection extendedProperties)
  282. :
  283. this(dbType,
  284. maxLength,
  285. precision,
  286. scale,
  287. localeId,
  288. compareOptions,
  289. userDefinedType,
  290. null,
  291. isMultiValued,
  292. fieldTypes,
  293. extendedProperties) {
  294. }
  295. // SMI V220 ctor.
  296. internal SmiMetaData(
  297. SqlDbType dbType,
  298. long maxLength,
  299. byte precision,
  300. byte scale,
  301. long localeId,
  302. SqlCompareOptions compareOptions,
  303. Type userDefinedType,
  304. string udtAssemblyQualifiedName,
  305. bool isMultiValued,
  306. IList<SmiExtendedMetaData> fieldTypes,
  307. SmiMetaDataPropertyCollection extendedProperties) {
  308. Debug.Assert( IsSupportedDbType(dbType), "Invalid SqlDbType: " + dbType );
  309. SetDefaultsForType( dbType );
  310. //
  311. switch ( dbType ) {
  312. case SqlDbType.BigInt:
  313. case SqlDbType.Bit:
  314. case SqlDbType.DateTime:
  315. case SqlDbType.Float:
  316. case SqlDbType.Image:
  317. case SqlDbType.Int:
  318. case SqlDbType.Money:
  319. case SqlDbType.Real:
  320. case SqlDbType.SmallDateTime:
  321. case SqlDbType.SmallInt:
  322. case SqlDbType.SmallMoney:
  323. case SqlDbType.Timestamp:
  324. case SqlDbType.TinyInt:
  325. case SqlDbType.UniqueIdentifier:
  326. case SqlDbType.Variant:
  327. case SqlDbType.Xml:
  328. case SqlDbType.Date:
  329. break;
  330. case SqlDbType.Binary:
  331. case SqlDbType.VarBinary:
  332. _maxLength = maxLength;
  333. break;
  334. case SqlDbType.Char:
  335. case SqlDbType.NChar:
  336. case SqlDbType.NVarChar:
  337. case SqlDbType.VarChar:
  338. // locale and compare options are not validated until they get to the server
  339. _maxLength = maxLength;
  340. _localeId = localeId;
  341. _compareOptions = compareOptions;
  342. break;
  343. case SqlDbType.NText:
  344. case SqlDbType.Text:
  345. _localeId = localeId;
  346. _compareOptions = compareOptions;
  347. break;
  348. case SqlDbType.Decimal:
  349. Debug.Assert( MinPrecision <= precision && SqlDecimal.MaxPrecision >= precision, "Invalid precision: " + precision );
  350. Debug.Assert( MinScale <= scale && SqlDecimal.MaxScale >= scale, "Invalid scale: " + scale );
  351. Debug.Assert( scale <= precision, "Precision: " + precision + " greater than scale: " + scale );
  352. _precision = precision;
  353. _scale = scale;
  354. _maxLength = __maxLenFromPrecision[precision - 1];
  355. break;
  356. case SqlDbType.Udt:
  357. // Assert modified for VSFTDEVDIV479492 - for SqlParameter both userDefinedType and udtAssemblyQualifiedName
  358. // can be NULL, we are checking only maxLength if it will be used (i.e. userDefinedType is NULL)
  359. Debug.Assert((null != userDefinedType) || (0 <= maxLength || UnlimitedMaxLengthIndicator == maxLength),
  360. String.Format((IFormatProvider)null, "SmiMetaData.ctor: Udt name={0}, maxLength={1}", udtAssemblyQualifiedName, maxLength));
  361. // Type not validated until matched to a server. Could be null if extended metadata supplies three-part name!
  362. _clrType = userDefinedType;
  363. if (null != userDefinedType) {
  364. _maxLength = SerializationHelperSql9.GetUdtMaxLength(userDefinedType);
  365. }
  366. else {
  367. _maxLength = maxLength;
  368. }
  369. _udtAssemblyQualifiedName = udtAssemblyQualifiedName;
  370. break;
  371. case SqlDbType.Structured:
  372. if (null != fieldTypes) {
  373. _fieldMetaData = (new List<SmiExtendedMetaData>(fieldTypes)).AsReadOnly();
  374. }
  375. _isMultiValued = isMultiValued;
  376. _maxLength = _fieldMetaData.Count;
  377. break;
  378. case SqlDbType.Time:
  379. Debug.Assert(MinScale <= scale && scale <= MaxTimeScale, "Invalid time scale: " + scale);
  380. _scale = scale;
  381. _maxLength = 5 - __maxVarTimeLenOffsetFromScale[scale];
  382. break;
  383. case SqlDbType.DateTime2:
  384. Debug.Assert(MinScale <= scale && scale <= MaxTimeScale, "Invalid time scale: " + scale);
  385. _scale = scale;
  386. _maxLength = 8 - __maxVarTimeLenOffsetFromScale[scale];
  387. break;
  388. case SqlDbType.DateTimeOffset:
  389. Debug.Assert(MinScale <= scale && scale <= MaxTimeScale, "Invalid time scale: " + scale);
  390. _scale = scale;
  391. _maxLength = 10 - __maxVarTimeLenOffsetFromScale[scale];
  392. break;
  393. default:
  394. Debug.Assert( false, "How in the world did we get here? :" + dbType );
  395. break;
  396. }
  397. if (null != extendedProperties) {
  398. extendedProperties.SetReadOnly();
  399. _extendedProperties = extendedProperties;
  400. }
  401. // properties and fields must meet the following conditions at this point:
  402. // 1) not null
  403. // 2) read only
  404. // 3) same number of columns in each list (0 count acceptable for properties that are "unused")
  405. Debug.Assert(null != _extendedProperties && _extendedProperties.IsReadOnly, "SmiMetaData.ctor: _extendedProperties is " + (null!=_extendedProperties?"writeable":"null"));
  406. Debug.Assert(null != _fieldMetaData && _fieldMetaData.IsReadOnly, "SmiMetaData.ctor: _fieldMetaData is " + (null!=_fieldMetaData?"writeable":"null"));
  407. #if DEBUG
  408. ((SmiDefaultFieldsProperty)_extendedProperties[SmiPropertySelector.DefaultFields]).CheckCount(_fieldMetaData.Count);
  409. ((SmiOrderProperty)_extendedProperties[SmiPropertySelector.SortOrder]).CheckCount(_fieldMetaData.Count);
  410. ((SmiUniqueKeyProperty)_extendedProperties[SmiPropertySelector.UniqueKey]).CheckCount(_fieldMetaData.Count);
  411. #endif
  412. }
  413. internal bool IsValidMaxLengthForCtorGivenType( SqlDbType dbType, long maxLength ) {
  414. bool result = true;
  415. switch( dbType ) {
  416. case SqlDbType.BigInt:
  417. case SqlDbType.Bit:
  418. case SqlDbType.DateTime:
  419. case SqlDbType.Float:
  420. case SqlDbType.Image:
  421. case SqlDbType.Int:
  422. case SqlDbType.Money:
  423. case SqlDbType.Real:
  424. case SqlDbType.SmallDateTime:
  425. case SqlDbType.SmallInt:
  426. case SqlDbType.SmallMoney:
  427. case SqlDbType.Timestamp:
  428. case SqlDbType.TinyInt:
  429. case SqlDbType.UniqueIdentifier:
  430. case SqlDbType.Variant:
  431. case SqlDbType.Xml:
  432. case SqlDbType.NText:
  433. case SqlDbType.Text:
  434. case SqlDbType.Decimal:
  435. case SqlDbType.Udt:
  436. case SqlDbType.Structured: //
  437. case SqlDbType.Date:
  438. case SqlDbType.Time:
  439. case SqlDbType.DateTime2:
  440. case SqlDbType.DateTimeOffset:
  441. break;
  442. case SqlDbType.Binary:
  443. result = 0 < maxLength && MaxBinaryLength >= maxLength;
  444. break;
  445. case SqlDbType.VarBinary:
  446. result = UnlimitedMaxLengthIndicator == maxLength || ( 0 < maxLength && MaxBinaryLength >= maxLength );
  447. break;
  448. case SqlDbType.Char:
  449. result = 0 < maxLength && MaxANSICharacters >= maxLength;
  450. break;
  451. case SqlDbType.NChar:
  452. result = 0 < maxLength && MaxUnicodeCharacters >= maxLength;
  453. break;
  454. case SqlDbType.NVarChar:
  455. result = UnlimitedMaxLengthIndicator == maxLength || ( 0 < maxLength && MaxUnicodeCharacters >= maxLength );
  456. break;
  457. case SqlDbType.VarChar:
  458. result = UnlimitedMaxLengthIndicator == maxLength || ( 0 < maxLength && MaxANSICharacters >= maxLength );
  459. break;
  460. default:
  461. Debug.Assert( false, "How in the world did we get here? :" + dbType );
  462. break;
  463. }
  464. return result;
  465. }
  466. // Sql-style compare options for character types.
  467. internal SqlCompareOptions CompareOptions {
  468. get {
  469. return _compareOptions;
  470. }
  471. }
  472. // LCID for type. 0 for non-character types.
  473. internal long LocaleId {
  474. get{
  475. return _localeId;
  476. }
  477. }
  478. // Units of length depend on type.
  479. // NVarChar, NChar, NText: # of unicode characters
  480. // Everything else: # of bytes
  481. internal long MaxLength {
  482. get {
  483. return _maxLength;
  484. }
  485. }
  486. internal byte Precision {
  487. get {
  488. return _precision;
  489. }
  490. }
  491. internal byte Scale {
  492. get {
  493. return _scale;
  494. }
  495. }
  496. internal SqlDbType SqlDbType {
  497. get {
  498. return _databaseType;
  499. }
  500. }
  501. // Clr Type instance for user-defined types
  502. internal Type Type {
  503. get {
  504. // Fault-in UDT clr types on access if have assembly-qualified name
  505. if (null == _clrType && SqlDbType.Udt == _databaseType && _udtAssemblyQualifiedName != null) {
  506. _clrType = Type.GetType(_udtAssemblyQualifiedName, true);
  507. }
  508. return _clrType;
  509. }
  510. }
  511. // Clr Type instance for user-defined types in cases where we don't want to throw if the assembly isn't available
  512. internal Type TypeWithoutThrowing {
  513. get {
  514. // Fault-in UDT clr types on access if have assembly-qualified name
  515. if (null == _clrType && SqlDbType.Udt == _databaseType && _udtAssemblyQualifiedName != null) {
  516. _clrType = Type.GetType(_udtAssemblyQualifiedName, false);
  517. }
  518. return _clrType;
  519. }
  520. }
  521. internal string TypeName {
  522. get {
  523. string result = null;
  524. if (SqlDbType.Udt == _databaseType) {
  525. Debug.Assert(String.Empty == __typeNameByDatabaseType[(int)_databaseType], "unexpected udt?");
  526. result = Type.FullName;
  527. }
  528. else {
  529. result = __typeNameByDatabaseType[(int)_databaseType];
  530. Debug.Assert(null != result, "unknown type name?");
  531. }
  532. return result;
  533. }
  534. }
  535. internal string AssemblyQualifiedName {
  536. get {
  537. string result = null;
  538. if (SqlDbType.Udt == _databaseType) {
  539. // Fault-in assembly-qualified name if type is available
  540. if (_udtAssemblyQualifiedName == null && _clrType != null) {
  541. _udtAssemblyQualifiedName = _clrType.AssemblyQualifiedName;
  542. }
  543. result = _udtAssemblyQualifiedName;
  544. }
  545. return result;
  546. }
  547. }
  548. internal bool IsMultiValued {
  549. get {
  550. return _isMultiValued;
  551. }
  552. }
  553. // Returns read-only list of field metadata
  554. internal IList<SmiExtendedMetaData> FieldMetaData {
  555. get {
  556. return _fieldMetaData;
  557. }
  558. }
  559. // Returns read-only list of extended properties
  560. internal SmiMetaDataPropertyCollection ExtendedProperties {
  561. get {
  562. return _extendedProperties;
  563. }
  564. }
  565. internal static bool IsSupportedDbType(SqlDbType dbType) {
  566. // Hole in SqlDbTypes between Xml and Udt for non-WinFS scenarios.
  567. return (SqlDbType.BigInt <= dbType && SqlDbType.Xml >= dbType) ||
  568. (SqlDbType.Udt <= dbType && SqlDbType.DateTimeOffset >= dbType);
  569. }
  570. // Only correct access point for defaults per SqlDbType.
  571. internal static SmiMetaData GetDefaultForType( SqlDbType dbType ) {
  572. Debug.Assert( IsSupportedDbType(dbType), "Unsupported SqlDbtype: " + dbType);
  573. return __defaultValues[(int)dbType];
  574. }
  575. // Private constructor used only to initialize default instance array elements.
  576. // DO NOT EXPOSE OUTSIDE THIS CLASS!
  577. private SmiMetaData (
  578. SqlDbType sqlDbType,
  579. long maxLength,
  580. byte precision,
  581. byte scale,
  582. SqlCompareOptions compareOptions) {
  583. _databaseType = sqlDbType;
  584. _maxLength = maxLength;
  585. _precision = precision;
  586. _scale = scale;
  587. _compareOptions = compareOptions;
  588. // defaults are the same for all types for the following attributes.
  589. _localeId = 0;
  590. _clrType = null;
  591. _isMultiValued = false;
  592. _fieldMetaData = __emptyFieldList;
  593. _extendedProperties = SmiMetaDataPropertyCollection.EmptyInstance;
  594. }
  595. // static array of default-valued metadata ordered by corresponding SqlDbType.
  596. // NOTE: INDEXED BY SqlDbType ENUM! MUST UPDATE THIS ARRAY WHEN UPDATING SqlDbType!
  597. // ONLY ACCESS THIS GLOBAL FROM GetDefaultForType!
  598. private static SmiMetaData[] __defaultValues =
  599. {
  600. DefaultBigInt, // SqlDbType.BigInt
  601. DefaultBinary, // SqlDbType.Binary
  602. DefaultBit, // SqlDbType.Bit
  603. DefaultChar_NoCollation, // SqlDbType.Char
  604. DefaultDateTime, // SqlDbType.DateTime
  605. DefaultDecimal, // SqlDbType.Decimal
  606. DefaultFloat, // SqlDbType.Float
  607. DefaultImage, // SqlDbType.Image
  608. DefaultInt, // SqlDbType.Int
  609. DefaultMoney, // SqlDbType.Money
  610. DefaultNChar_NoCollation, // SqlDbType.NChar
  611. DefaultNText_NoCollation, // SqlDbType.NText
  612. DefaultNVarChar_NoCollation, // SqlDbType.NVarChar
  613. DefaultReal, // SqlDbType.Real
  614. DefaultUniqueIdentifier, // SqlDbType.UniqueIdentifier
  615. DefaultSmallDateTime, // SqlDbType.SmallDateTime
  616. DefaultSmallInt, // SqlDbType.SmallInt
  617. DefaultSmallMoney, // SqlDbType.SmallMoney
  618. DefaultText_NoCollation, // SqlDbType.Text
  619. DefaultTimestamp, // SqlDbType.Timestamp
  620. DefaultTinyInt, // SqlDbType.TinyInt
  621. DefaultVarBinary, // SqlDbType.VarBinary
  622. DefaultVarChar_NoCollation, // SqlDbType.VarChar
  623. DefaultVariant, // SqlDbType.Variant
  624. DefaultNVarChar_NoCollation, // Placeholder for value 24
  625. DefaultXml, // SqlDbType.Xml
  626. DefaultNVarChar_NoCollation, // Placeholder for value 26
  627. DefaultNVarChar_NoCollation, // Placeholder for value 27
  628. DefaultNVarChar_NoCollation, // Placeholder for value 28
  629. DefaultUdt_NoType, // Generic Udt
  630. DefaultStructured, // Generic structured type
  631. DefaultDate, // SqlDbType.Date
  632. DefaultTime, // SqlDbType.Time
  633. DefaultDateTime2, // SqlDbType.DateTime2
  634. DefaultDateTimeOffset, // SqlDbType.DateTimeOffset
  635. };
  636. // static array of type names ordered by corresponding SqlDbType.
  637. // NOTE: INDEXED BY SqlDbType ENUM! MUST UPDATE THIS ARRAY WHEN UPDATING SqlDbType!
  638. // ONLY ACCESS THIS GLOBAL FROM get_TypeName!
  639. private static string[] __typeNameByDatabaseType =
  640. {
  641. "bigint", // SqlDbType.BigInt
  642. "binary", // SqlDbType.Binary
  643. "bit", // SqlDbType.Bit
  644. "char", // SqlDbType.Char
  645. "datetime", // SqlDbType.DateTime
  646. "decimal", // SqlDbType.Decimal
  647. "float", // SqlDbType.Float
  648. "image", // SqlDbType.Image
  649. "int", // SqlDbType.Int
  650. "money", // SqlDbType.Money
  651. "nchar", // SqlDbType.NChar
  652. "ntext", // SqlDbType.NText
  653. "nvarchar", // SqlDbType.NVarChar
  654. "real", // SqlDbType.Real
  655. "uniqueidentifier", // SqlDbType.UniqueIdentifier
  656. "smalldatetime", // SqlDbType.SmallDateTime
  657. "smallint", // SqlDbType.SmallInt
  658. "smallmoney", // SqlDbType.SmallMoney
  659. "text", // SqlDbType.Text
  660. "timestamp", // SqlDbType.Timestamp
  661. "tinyint", // SqlDbType.TinyInt
  662. "varbinary", // SqlDbType.VarBinary
  663. "varchar", // SqlDbType.VarChar
  664. "sql_variant", // SqlDbType.Variant
  665. null, // placeholder for 24
  666. "xml", // SqlDbType.Xml
  667. null, // placeholder for 26
  668. null, // placeholder for 27
  669. null, // placeholder for 28
  670. String.Empty, // SqlDbType.Udt -- get type name from Type.FullName instead.
  671. String.Empty, // Structured types have user-defined type names.
  672. "date", // SqlDbType.Date
  673. "time", // SqlDbType.Time
  674. "datetime2", // SqlDbType.DateTime2
  675. "datetimeoffset", // SqlDbType.DateTimeOffset
  676. };
  677. // Internal setter to be used by constructors only! Modifies state!
  678. private void SetDefaultsForType( SqlDbType dbType )
  679. {
  680. SmiMetaData smdDflt = GetDefaultForType( dbType );
  681. _databaseType = dbType;
  682. _maxLength = smdDflt.MaxLength;
  683. _precision = smdDflt.Precision;
  684. _scale = smdDflt.Scale;
  685. _localeId = smdDflt.LocaleId;
  686. _compareOptions = smdDflt.CompareOptions;
  687. _clrType = null;
  688. _isMultiValued = smdDflt._isMultiValued;
  689. _fieldMetaData = smdDflt._fieldMetaData; // This is ok due to immutability
  690. _extendedProperties = smdDflt._extendedProperties; // This is ok due to immutability
  691. }
  692. internal string TraceString() {
  693. return TraceString(0);
  694. }
  695. virtual internal string TraceString(int indent) {
  696. string indentStr = new String(' ', indent);
  697. string fields = String.Empty;
  698. if (null != _fieldMetaData) {
  699. foreach(SmiMetaData fieldMd in _fieldMetaData) {
  700. fields = String.Format(CultureInfo.InvariantCulture,
  701. "{0}{1}\n\t", fields, fieldMd.TraceString(indent+5));
  702. }
  703. }
  704. string properties = String.Empty;
  705. if (null != _extendedProperties) {
  706. foreach(SmiMetaDataProperty property in _extendedProperties.Values) {
  707. properties = String.Format(CultureInfo.InvariantCulture,
  708. "{0}{1} {2}\n\t", properties, indentStr, property.TraceString());
  709. }
  710. }
  711. return String.Format(CultureInfo.InvariantCulture, "\n\t"
  712. +"{0} SqlDbType={1:g}\n\t"
  713. +"{0} MaxLength={2:d}\n\t"
  714. +"{0} Precision={3:d}\n\t"
  715. +"{0} Scale={4:d}\n\t"
  716. +"{0} LocaleId={5:x}\n\t"
  717. +"{0} CompareOptions={6:g}\n\t"
  718. +"{0} Type={7}\n\t"
  719. +"{0} MultiValued={8}\n\t"
  720. +"{0} fields=\n\t{9}"
  721. +"{0} properties=\n\t{10}",
  722. indentStr,
  723. SqlDbType,
  724. MaxLength,
  725. Precision,
  726. Scale,
  727. LocaleId,
  728. CompareOptions,
  729. (null!=Type) ? Type.ToString():"<null>",
  730. IsMultiValued,
  731. fields,
  732. properties);
  733. }
  734. }
  735. // SmiExtendedMetaData
  736. //
  737. // Adds server-specific type extension information to base metadata, but still portable across a specific server.
  738. //
  739. internal class SmiExtendedMetaData : SmiMetaData {
  740. private string _name; // context-dependant identifier, ie. parameter name for parameters, column name for columns, etc.
  741. // three-part name for typed xml schema and for udt names
  742. private string _typeSpecificNamePart1;
  743. private string _typeSpecificNamePart2;
  744. private string _typeSpecificNamePart3;
  745. [ObsoleteAttribute( "Not supported as of SMI v2. Will be removed when v1 support dropped. Use ctor without columns param." )]
  746. internal SmiExtendedMetaData(
  747. SqlDbType dbType,
  748. long maxLength,
  749. byte precision,
  750. byte scale,
  751. long localeId,
  752. SqlCompareOptions compareOptions,
  753. Type userDefinedType,
  754. SmiMetaData[] columns,
  755. string name,
  756. string typeSpecificNamePart1,
  757. string typeSpecificNamePart2,
  758. string typeSpecificNamePart3) :
  759. // Implement as calling the new ctor
  760. this(
  761. dbType,
  762. maxLength,
  763. precision,
  764. scale,
  765. localeId,
  766. compareOptions,
  767. userDefinedType,
  768. name,
  769. typeSpecificNamePart1,
  770. typeSpecificNamePart2,
  771. typeSpecificNamePart3 ) {
  772. Debug.Assert( null == columns, "Row types not supported" );
  773. }
  774. internal SmiExtendedMetaData(
  775. SqlDbType dbType,
  776. long maxLength,
  777. byte precision,
  778. byte scale,
  779. long localeId,
  780. SqlCompareOptions compareOptions,
  781. Type userDefinedType,
  782. string name,
  783. string typeSpecificNamePart1,
  784. string typeSpecificNamePart2,
  785. string typeSpecificNamePart3) :
  786. this(
  787. dbType,
  788. maxLength,
  789. precision,
  790. scale,
  791. localeId,
  792. compareOptions,
  793. userDefinedType,
  794. false,
  795. null,
  796. null,
  797. name,
  798. typeSpecificNamePart1,
  799. typeSpecificNamePart2,
  800. typeSpecificNamePart3) {
  801. }
  802. // SMI V200 ctor.
  803. internal SmiExtendedMetaData(
  804. SqlDbType dbType,
  805. long maxLength,
  806. byte precision,
  807. byte scale,
  808. long localeId,
  809. SqlCompareOptions compareOptions,
  810. Type userDefinedType,
  811. bool isMultiValued,
  812. IList<SmiExtendedMetaData> fieldMetaData,
  813. SmiMetaDataPropertyCollection extendedProperties,
  814. string name,
  815. string typeSpecificNamePart1,
  816. string typeSpecificNamePart2,
  817. string typeSpecificNamePart3) :
  818. this( dbType,
  819. maxLength,
  820. precision,
  821. scale,
  822. localeId,
  823. compareOptions,
  824. userDefinedType,
  825. null,
  826. isMultiValued,
  827. fieldMetaData,
  828. extendedProperties,
  829. name,
  830. typeSpecificNamePart1,
  831. typeSpecificNamePart2,
  832. typeSpecificNamePart3) {
  833. }
  834. // SMI V220 ctor.
  835. internal SmiExtendedMetaData(
  836. SqlDbType dbType,
  837. long maxLength,
  838. byte precision,
  839. byte scale,
  840. long localeId,
  841. SqlCompareOptions compareOptions,
  842. Type userDefinedType,
  843. string udtAssemblyQualifiedName,
  844. bool isMultiValued,
  845. IList<SmiExtendedMetaData> fieldMetaData,
  846. SmiMetaDataPropertyCollection extendedProperties,
  847. string name,
  848. string typeSpecificNamePart1,
  849. string typeSpecificNamePart2,
  850. string typeSpecificNamePart3 ):
  851. base( dbType,
  852. maxLength,
  853. precision,
  854. scale,
  855. localeId,
  856. compareOptions,
  857. userDefinedType,
  858. udtAssemblyQualifiedName,
  859. isMultiValued,
  860. fieldMetaData,
  861. extendedProperties) {
  862. Debug.Assert(null == name || MaxNameLength >= name.Length, "Name is too long");
  863. _name = name;
  864. _typeSpecificNamePart1 = typeSpecificNamePart1;
  865. _typeSpecificNamePart2 = typeSpecificNamePart2;
  866. _typeSpecificNamePart3 = typeSpecificNamePart3;
  867. }
  868. internal string Name {
  869. get {
  870. return _name;
  871. }
  872. }
  873. internal string TypeSpecificNamePart1 {
  874. get {
  875. return _typeSpecificNamePart1;
  876. }
  877. }
  878. internal string TypeSpecificNamePart2 {
  879. get {
  880. return _typeSpecificNamePart2;
  881. }
  882. }
  883. internal string TypeSpecificNamePart3 {
  884. get {
  885. return _typeSpecificNamePart3;
  886. }
  887. }
  888. internal override string TraceString(int indent) {
  889. return String.Format(CultureInfo.InvariantCulture,
  890. "{2} Name={0}"
  891. +"{1}"
  892. +"{2}TypeSpecificNamePart1='{3}'\n\t"
  893. +"{2}TypeSpecificNamePart2='{4}'\n\t"
  894. +"{2}TypeSpecificNamePart3='{5}'\n\t",
  895. (null!=_name) ? _name : "<null>",
  896. base.TraceString(indent),
  897. new String(' ', indent),
  898. (null!=TypeSpecificNamePart1) ? TypeSpecificNamePart1:"<null>",
  899. (null!=TypeSpecificNamePart2) ? TypeSpecificNamePart2:"<null>",
  900. (null!=TypeSpecificNamePart3) ? TypeSpecificNamePart3:"<null>");
  901. }
  902. }
  903. // SmiParameterMetaData
  904. //
  905. // MetaData class to send parameter definitions to server.
  906. // Sealed because we don't need to derive from it yet.
  907. // IMPORTANT DEVNOTE: This class is being used for parameter encryption functionality, to get the type_info TDS object from SqlParameter.
  908. // Please consider impact to that when changing this class. Refer to the callers of SqlParameter.GetMetadataForTypeInfo().
  909. internal sealed class SmiParameterMetaData : SmiExtendedMetaData {
  910. private ParameterDirection _direction;
  911. [ObsoleteAttribute( "Not supported as of SMI v2. Will be removed when v1 support dropped. Use ctor without columns param." )]
  912. internal SmiParameterMetaData(
  913. SqlDbType dbType,
  914. long maxLength,
  915. byte precision,
  916. byte scale,
  917. long localeId,
  918. SqlCompareOptions compareOptions,
  919. Type userDefinedType,
  920. SmiMetaData[] columns,
  921. string name,
  922. string typeSpecificNamePart1,
  923. string typeSpecificNamePart2,
  924. string typeSpecificNamePart3,
  925. ParameterDirection direction) :
  926. // Implement as calling the new ctor
  927. this (
  928. dbType,
  929. maxLength,
  930. precision,
  931. scale,
  932. localeId,
  933. compareOptions,
  934. userDefinedType,
  935. name,
  936. typeSpecificNamePart1,
  937. typeSpecificNamePart2,
  938. typeSpecificNamePart3,
  939. direction ) {
  940. Debug.Assert( null == columns, "Row types not supported" );
  941. }
  942. // SMI V100 (aka V3) ctor
  943. internal SmiParameterMetaData(
  944. SqlDbType dbType,
  945. long maxLength,
  946. byte precision,
  947. byte scale,
  948. long localeId,
  949. SqlCompareOptions compareOptions,
  950. Type userDefinedType,
  951. string name,
  952. string typeSpecificNamePart1,
  953. string typeSpecificNamePart2,
  954. string typeSpecificNamePart3,
  955. ParameterDirection direction) :
  956. this(
  957. dbType,
  958. maxLength,
  959. precision,
  960. scale,
  961. localeId,
  962. compareOptions,
  963. userDefinedType,
  964. false,
  965. null,
  966. null,
  967. name,
  968. typeSpecificNamePart1,
  969. typeSpecificNamePart2,
  970. typeSpecificNamePart3,
  971. direction) {
  972. }
  973. // SMI V200 ctor.
  974. internal SmiParameterMetaData(
  975. SqlDbType dbType,
  976. long maxLength,
  977. byte precision,
  978. byte scale,
  979. long localeId,
  980. SqlCompareOptions compareOptions,
  981. Type userDefinedType,
  982. bool isMultiValued,
  983. IList<SmiExtendedMetaData> fieldMetaData,
  984. SmiMetaDataPropertyCollection extendedProperties,
  985. string name,
  986. string typeSpecificNamePart1,
  987. string typeSpecificNamePart2,
  988. string typeSpecificNamePart3,
  989. ParameterDirection direction) :
  990. this( dbType,
  991. maxLength,
  992. precision,
  993. scale,
  994. localeId,
  995. compareOptions,
  996. userDefinedType,
  997. null,
  998. isMultiValued,
  999. fieldMetaData,
  1000. extendedProperties,
  1001. name,
  1002. typeSpecificNamePart1,
  1003. typeSpecificNamePart2,
  1004. typeSpecificNamePart3,
  1005. direction) {
  1006. }
  1007. // SMI V220 ctor.
  1008. internal SmiParameterMetaData(
  1009. SqlDbType dbType,
  1010. long maxLength,
  1011. byte precision,
  1012. byte scale,
  1013. long localeId,
  1014. SqlCompareOptions compareOptions,
  1015. Type userDefinedType,
  1016. string udtAssemblyQualifiedName,
  1017. bool isMultiValued,
  1018. IList<SmiExtendedMetaData> fieldMetaData,
  1019. SmiMetaDataPropertyCollection extendedProperties,
  1020. string name,
  1021. string typeSpecificNamePart1,
  1022. string typeSpecificNamePart2,
  1023. string typeSpecificNamePart3,
  1024. ParameterDirection direction) :
  1025. base( dbType,
  1026. maxLength,
  1027. precision,
  1028. scale,
  1029. localeId,
  1030. compareOptions,
  1031. userDefinedType,
  1032. udtAssemblyQualifiedName,
  1033. isMultiValued,
  1034. fieldMetaData,
  1035. extendedProperties,
  1036. name,
  1037. typeSpecificNamePart1,
  1038. typeSpecificNamePart2,
  1039. typeSpecificNamePart3) {
  1040. Debug.Assert( ParameterDirection.Input == direction
  1041. || ParameterDirection.Output == direction
  1042. || ParameterDirection.InputOutput == direction
  1043. || ParameterDirection.ReturnValue == direction, "Invalid direction: " + direction );
  1044. _direction = direction;
  1045. }
  1046. internal ParameterDirection Direction {
  1047. get {
  1048. return _direction;
  1049. }
  1050. }
  1051. internal override string TraceString(int indent) {
  1052. return String.Format(CultureInfo.InvariantCulture, "{0}"
  1053. +"{1} Direction={2:g}\n\t",
  1054. base.TraceString(indent),
  1055. new String(' ', indent),
  1056. Direction);
  1057. }
  1058. }
  1059. // SmiStorageMetaData
  1060. //
  1061. // This class represents the addition of storage-level attributes to the heirarchy (i.e. attributes from
  1062. // underlying table, source variables, or whatever).
  1063. //
  1064. // Most values use Null (either IsNullable == true or CLR null) to indicate "Not specified" state. Selection
  1065. // of which values allow "not specified" determined by backward compatibility.
  1066. //
  1067. // Maps approximately to TDS' COLMETADATA token with TABNAME and part of COLINFO thrown in.
  1068. internal class SmiStorageMetaData : SmiExtendedMetaData {
  1069. // AllowsDBNull is the only value required to be specified.
  1070. private bool _allowsDBNull; // could the column return nulls? equivalent to TDS's IsNullable bit
  1071. private string _serverName; // underlying column's server
  1072. private string _catalogName; // underlying column's database
  1073. private string _schemaName; // underlying column's schema
  1074. private string _tableName; // underlying column's table
  1075. private string _columnName; // underlying column's name
  1076. private SqlBoolean _isKey; // Is this one of a set of key columns that uniquely identify an underlying table?
  1077. private bool _isIdentity; // Is this from an identity column
  1078. private bool _isColumnSet; // Is this column the XML representation of a columnset?
  1079. [ObsoleteAttribute( "Not supported as of SMI v2. Will be removed when v1 support dropped. Use ctor without columns param." )]
  1080. internal SmiStorageMetaData(
  1081. SqlDbType dbType,
  1082. long maxLength,
  1083. byte precision,
  1084. byte scale,
  1085. long localeId,
  1086. SqlCompareOptions compareOptions,
  1087. Type userDefinedType,
  1088. SmiMetaData[] columns,
  1089. string name,
  1090. string typeSpecificNamePart1,
  1091. string typeSpecificNamePart2,
  1092. string typeSpecificNamePart3,
  1093. bool allowsDBNull,
  1094. string serverName,
  1095. string catalogName,
  1096. string schemaName,
  1097. string tableName,
  1098. string columnName,
  1099. SqlBoolean isKey,
  1100. bool isIdentity) :
  1101. // Implement as calling the new ctor
  1102. this (
  1103. dbType,
  1104. maxLength,
  1105. precision,
  1106. scale,
  1107. localeId,
  1108. compareOptions,
  1109. userDefinedType,
  1110. name,
  1111. typeSpecificNamePart1,
  1112. typeSpecificNamePart2,
  1113. typeSpecificNamePart3,
  1114. allowsDBNull,
  1115. serverName,
  1116. catalogName,
  1117. schemaName,
  1118. tableName,
  1119. columnName,
  1120. isKey,
  1121. isIdentity) {
  1122. Debug.Assert( null == columns, "Row types not supported" );
  1123. }
  1124. internal SmiStorageMetaData(
  1125. SqlDbType dbType,
  1126. long maxLength,
  1127. byte precision,
  1128. byte scale,
  1129. long localeId,
  1130. SqlCompareOptions compareOptions,
  1131. Type userDefinedType,
  1132. string name,
  1133. string typeSpecificNamePart1,
  1134. string typeSpecificNamePart2,
  1135. string typeSpecificNamePart3,
  1136. bool allowsDBNull,
  1137. string serverName,
  1138. string catalogName,
  1139. string schemaName,
  1140. string tableName,
  1141. string columnName,
  1142. SqlBoolean isKey,
  1143. bool isIdentity) :
  1144. this(dbType,
  1145. maxLength,
  1146. precision,
  1147. scale,
  1148. localeId,
  1149. compareOptions,
  1150. userDefinedType,
  1151. false,
  1152. null,
  1153. null,
  1154. name,
  1155. typeSpecificNamePart1,
  1156. typeSpecificNamePart2,
  1157. typeSpecificNamePart3,
  1158. allowsDBNull,
  1159. serverName,
  1160. catalogName,
  1161. schemaName,
  1162. tableName,
  1163. columnName,
  1164. isKey,
  1165. isIdentity) {
  1166. }
  1167. // SMI V200 ctor.
  1168. internal SmiStorageMetaData(
  1169. SqlDbType dbType,
  1170. long maxLength,
  1171. byte precision,
  1172. byte scale,
  1173. long localeId,
  1174. SqlCompareOptions compareOptions,
  1175. Type userDefinedType,
  1176. bool isMultiValued,
  1177. IList<SmiExtendedMetaData> fieldMetaData,
  1178. SmiMetaDataPropertyCollection extendedProperties,
  1179. string name,
  1180. string typeSpecificNamePart1,
  1181. string typeSpecificNamePart2,
  1182. string typeSpecificNamePart3,
  1183. bool allowsDBNull,
  1184. string serverName,
  1185. string catalogName,
  1186. string schemaName,
  1187. string tableName,
  1188. string columnName,
  1189. SqlBoolean isKey,
  1190. bool isIdentity) :
  1191. this( dbType,
  1192. maxLength,
  1193. precision,
  1194. scale,
  1195. localeId,
  1196. compareOptions,
  1197. userDefinedType,
  1198. null,
  1199. isMultiValued,
  1200. fieldMetaData,
  1201. extendedProperties,
  1202. name,
  1203. typeSpecificNamePart1,
  1204. typeSpecificNamePart2,
  1205. typeSpecificNamePart3,
  1206. allowsDBNull,
  1207. serverName,
  1208. catalogName,
  1209. schemaName,
  1210. tableName,
  1211. columnName,
  1212. isKey,
  1213. isIdentity,
  1214. false) {
  1215. }
  1216. // SMI V220 ctor.
  1217. internal SmiStorageMetaData(
  1218. SqlDbType dbType,
  1219. long maxLength,
  1220. byte precision,
  1221. byte scale,
  1222. long localeId,
  1223. SqlCompareOptions compareOptions,
  1224. Type userDefinedType,
  1225. string udtAssemblyQualifiedName,
  1226. bool isMultiValued,
  1227. IList<SmiExtendedMetaData> fieldMetaData,
  1228. SmiMetaDataPropertyCollection extendedProperties,
  1229. string name,
  1230. string typeSpecificNamePart1,
  1231. string typeSpecificNamePart2,
  1232. string typeSpecificNamePart3,
  1233. bool allowsDBNull,
  1234. string serverName,
  1235. string catalogName,
  1236. string schemaName,
  1237. string tableName,
  1238. string columnName,
  1239. SqlBoolean isKey,
  1240. bool isIdentity,
  1241. bool isColumnSet) :
  1242. base( dbType,
  1243. maxLength,
  1244. precision,
  1245. scale,
  1246. localeId,
  1247. compareOptions,
  1248. userDefinedType,
  1249. udtAssemblyQualifiedName,
  1250. isMultiValued,
  1251. fieldMetaData,
  1252. extendedProperties,
  1253. name,
  1254. typeSpecificNamePart1,
  1255. typeSpecificNamePart2,
  1256. typeSpecificNamePart3) {
  1257. _allowsDBNull = allowsDBNull;
  1258. _serverName = serverName;
  1259. _catalogName = catalogName;
  1260. _schemaName = schemaName;
  1261. _tableName = tableName;
  1262. _columnName = columnName;
  1263. _isKey = isKey;
  1264. _isIdentity = isIdentity;
  1265. _isColumnSet = isColumnSet;
  1266. }
  1267. internal bool AllowsDBNull {
  1268. get {
  1269. return _allowsDBNull;
  1270. }
  1271. }
  1272. internal string ServerName {
  1273. get {
  1274. return _serverName;
  1275. }
  1276. }
  1277. internal string CatalogName {
  1278. get {
  1279. return _catalogName;
  1280. }
  1281. }
  1282. internal string SchemaName {
  1283. get {
  1284. return _schemaName;
  1285. }
  1286. }
  1287. internal string TableName {
  1288. get {
  1289. return _tableName;
  1290. }
  1291. }
  1292. internal string ColumnName {
  1293. get {
  1294. return _columnName;
  1295. }
  1296. }
  1297. internal SqlBoolean IsKey {
  1298. get {
  1299. return _isKey;
  1300. }
  1301. }
  1302. internal bool IsIdentity {
  1303. get {
  1304. return _isIdentity;
  1305. }
  1306. }
  1307. internal bool IsColumnSet {
  1308. get {
  1309. return _isColumnSet;
  1310. }
  1311. }
  1312. internal override string TraceString(int indent) {
  1313. return String.Format(CultureInfo.InvariantCulture, "{0}"
  1314. +"{1} AllowsDBNull={2}\n\t"
  1315. +"{1} ServerName='{3}'\n\t"
  1316. +"{1} CatalogName='{4}'\n\t"
  1317. +"{1} SchemaName='{5}'\n\t"
  1318. +"{1} TableName='{6}'\n\t"
  1319. +"{1} ColumnName='{7}'\n\t"
  1320. +"{1} IsKey={8}\n\t"
  1321. +"{1} IsIdentity={9}\n\t",
  1322. base.TraceString(indent),
  1323. new String(' ', indent),
  1324. AllowsDBNull,
  1325. (null!=ServerName) ? ServerName:"<null>",
  1326. (null!=CatalogName) ? CatalogName:"<null>",
  1327. (null!=SchemaName) ? SchemaName:"<null>",
  1328. (null!=TableName) ? TableName:"<null>",
  1329. (null!=ColumnName) ? ColumnName:"<null>",
  1330. IsKey,
  1331. IsIdentity);
  1332. }
  1333. }
  1334. // SmiQueryMetaData
  1335. //
  1336. // Adds Query-specific attributes.
  1337. // Sealed since we don't need to extend it for now.
  1338. // Maps to full COLMETADATA + COLINFO + TABNAME tokens on TDS.
  1339. internal class SmiQueryMetaData : SmiStorageMetaData {
  1340. private bool _isReadOnly;
  1341. private SqlBoolean _isExpression;
  1342. private SqlBoolean _isAliased;
  1343. private SqlBoolean _isHidden;
  1344. [ObsoleteAttribute( "Not supported as of SMI v2. Will be removed when v1 support dropped. Use ctor without columns param." )]
  1345. internal SmiQueryMetaData(
  1346. SqlDbType dbType,
  1347. long maxLength,
  1348. byte precision,
  1349. byte scale,
  1350. long localeId,
  1351. SqlCompareOptions compareOptions,
  1352. Type userDefinedType,
  1353. SmiMetaData[] columns,
  1354. string name,
  1355. string typeSpecificNamePart1,
  1356. string typeSpecificNamePart2,
  1357. string typeSpecificNamePart3,
  1358. bool allowsDBNull,
  1359. string serverName,
  1360. string catalogName,
  1361. string schemaName,
  1362. string tableName,
  1363. string columnName,
  1364. SqlBoolean isKey,
  1365. bool isIdentity,
  1366. bool isReadOnly,
  1367. SqlBoolean isExpression,
  1368. SqlBoolean isAliased,
  1369. SqlBoolean isHidden ) :
  1370. // Implement as calling the new ctor
  1371. this (
  1372. dbType,
  1373. maxLength,
  1374. precision,
  1375. scale,
  1376. localeId,
  1377. compareOptions,
  1378. userDefinedType,
  1379. name,
  1380. typeSpecificNamePart1,
  1381. typeSpecificNamePart2,
  1382. typeSpecificNamePart3,
  1383. allowsDBNull,
  1384. serverName,
  1385. catalogName,
  1386. schemaName,
  1387. tableName,
  1388. columnName,
  1389. isKey,
  1390. isIdentity,
  1391. isReadOnly,
  1392. isExpression,
  1393. isAliased,
  1394. isHidden ) {
  1395. Debug.Assert( null == columns, "Row types not supported" );
  1396. }
  1397. internal SmiQueryMetaData( SqlDbType dbType,
  1398. long maxLength,
  1399. byte precision,
  1400. byte scale,
  1401. long localeId,
  1402. SqlCompareOptions compareOptions,
  1403. Type userDefinedType,
  1404. string name,
  1405. string typeSpecificNamePart1,
  1406. string typeSpecificNamePart2,
  1407. string typeSpecificNamePart3,
  1408. bool allowsDBNull,
  1409. string serverName,
  1410. string catalogName,
  1411. string schemaName,
  1412. string tableName,
  1413. string columnName,
  1414. SqlBoolean isKey,
  1415. bool isIdentity,
  1416. bool isReadOnly,
  1417. SqlBoolean isExpression,
  1418. SqlBoolean isAliased,
  1419. SqlBoolean isHidden ) :
  1420. this( dbType,
  1421. maxLength,
  1422. precision,
  1423. scale,
  1424. localeId,
  1425. compareOptions,
  1426. userDefinedType,
  1427. false,
  1428. null,
  1429. null,
  1430. name,
  1431. typeSpecificNamePart1,
  1432. typeSpecificNamePart2,
  1433. typeSpecificNamePart3,
  1434. allowsDBNull,
  1435. serverName,
  1436. catalogName,
  1437. schemaName,
  1438. tableName,
  1439. columnName,
  1440. isKey,
  1441. isIdentity,
  1442. isReadOnly,
  1443. isExpression,
  1444. isAliased,
  1445. isHidden) {
  1446. }
  1447. // SMI V200 ctor.
  1448. internal SmiQueryMetaData( SqlDbType dbType,
  1449. long maxLength,
  1450. byte precision,
  1451. byte scale,
  1452. long localeId,
  1453. SqlCompareOptions compareOptions,
  1454. Type userDefinedType,
  1455. bool isMultiValued,
  1456. IList<SmiExtendedMetaData> fieldMetaData,
  1457. SmiMetaDataPropertyCollection extendedProperties,
  1458. string name,
  1459. string typeSpecificNamePart1,
  1460. string typeSpecificNamePart2,
  1461. string typeSpecificNamePart3,
  1462. bool allowsDBNull,
  1463. string serverName,
  1464. string catalogName,
  1465. string schemaName,
  1466. string tableName,
  1467. string columnName,
  1468. SqlBoolean isKey,
  1469. bool isIdentity,
  1470. bool isReadOnly,
  1471. SqlBoolean isExpression,
  1472. SqlBoolean isAliased,
  1473. SqlBoolean isHidden) :
  1474. this( dbType,
  1475. maxLength,
  1476. precision,
  1477. scale,
  1478. localeId,
  1479. compareOptions,
  1480. userDefinedType,
  1481. null,
  1482. isMultiValued,
  1483. fieldMetaData,
  1484. extendedProperties,
  1485. name,
  1486. typeSpecificNamePart1,
  1487. typeSpecificNamePart2,
  1488. typeSpecificNamePart3,
  1489. allowsDBNull,
  1490. serverName,
  1491. catalogName,
  1492. schemaName,
  1493. tableName,
  1494. columnName,
  1495. isKey,
  1496. isIdentity,
  1497. false,
  1498. isReadOnly,
  1499. isExpression,
  1500. isAliased,
  1501. isHidden ) {
  1502. }
  1503. // SMI V220 ctor.
  1504. internal SmiQueryMetaData( SqlDbType dbType,
  1505. long maxLength,
  1506. byte precision,
  1507. byte scale,
  1508. long localeId,
  1509. SqlCompareOptions compareOptions,
  1510. Type userDefinedType,
  1511. string udtAssemblyQualifiedName,
  1512. bool isMultiValued,
  1513. IList<SmiExtendedMetaData> fieldMetaData,
  1514. SmiMetaDataPropertyCollection extendedProperties,
  1515. string name,
  1516. string typeSpecificNamePart1,
  1517. string typeSpecificNamePart2,
  1518. string typeSpecificNamePart3,
  1519. bool allowsDBNull,
  1520. string serverName,
  1521. string catalogName,
  1522. string schemaName,
  1523. string tableName,
  1524. string columnName,
  1525. SqlBoolean isKey,
  1526. bool isIdentity,
  1527. bool isColumnSet,
  1528. bool isReadOnly,
  1529. SqlBoolean isExpression,
  1530. SqlBoolean isAliased,
  1531. SqlBoolean isHidden ) :
  1532. base( dbType,
  1533. maxLength,
  1534. precision,
  1535. scale,
  1536. localeId,
  1537. compareOptions,
  1538. userDefinedType,
  1539. udtAssemblyQualifiedName,
  1540. isMultiValued,
  1541. fieldMetaData,
  1542. extendedProperties,
  1543. name,
  1544. typeSpecificNamePart1,
  1545. typeSpecificNamePart2,
  1546. typeSpecificNamePart3,
  1547. allowsDBNull,
  1548. serverName,
  1549. catalogName,
  1550. schemaName,
  1551. tableName,
  1552. columnName,
  1553. isKey,
  1554. isIdentity,
  1555. isColumnSet ) {
  1556. _isReadOnly = isReadOnly;
  1557. _isExpression = isExpression;
  1558. _isAliased = isAliased;
  1559. _isHidden = isHidden;
  1560. }
  1561. internal bool IsReadOnly {
  1562. get {
  1563. return _isReadOnly;
  1564. }
  1565. }
  1566. internal SqlBoolean IsExpression {
  1567. get {
  1568. return _isExpression;
  1569. }
  1570. }
  1571. internal SqlBoolean IsAliased {
  1572. get {
  1573. return _isAliased;
  1574. }
  1575. }
  1576. internal SqlBoolean IsHidden {
  1577. get {
  1578. return _isHidden;
  1579. }
  1580. }
  1581. internal override string TraceString(int indent) {
  1582. return String.Format(CultureInfo.InvariantCulture, "{0}"
  1583. +"{1} IsReadOnly={2}\n\t"
  1584. +"{1} IsExpression={3}\n\t"
  1585. +"{1} IsAliased={4}\n\t"
  1586. +"{1} IsHidden={5}",
  1587. base.TraceString(indent),
  1588. new String(' ', indent),
  1589. AllowsDBNull,
  1590. IsExpression,
  1591. IsAliased,
  1592. IsHidden);
  1593. }
  1594. }
  1595. }