2 // System.Data.SqlTypes.SqlString
5 // Rodrigo Moya (rodrigo@ximian.com)
6 // Daniel Morgan (danmorg@sc.rr.com)
7 // Tim Coleman (tim@timcoleman.com)
8 // Ville Palo (vi64pa@koti.soon.fi)
10 // (C) Ximian, Inc. 2002
11 // (C) Copyright 2002 Tim Coleman
15 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
17 // Permission is hereby granted, free of charge, to any person obtaining
18 // a copy of this software and associated documentation files (the
19 // "Software"), to deal in the Software without restriction, including
20 // without limitation the rights to use, copy, modify, merge, publish,
21 // distribute, sublicense, and/or sell copies of the Software, and to
22 // permit persons to whom the Software is furnished to do so, subject to
23 // the following conditions:
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 using System.Threading;
41 using System.Xml.Schema;
42 using System.Globalization;
43 using System.Xml.Serialization;
45 namespace System.Data.SqlTypes
48 /// A variable-length stream of characters
49 /// to be stored in or retrieved from the database
52 [SerializableAttribute]
53 [XmlSchemaProvider ("GetXsdType")]
55 public struct SqlString : INullable, IComparable
67 // FIXME: locale id is not working yet
69 private SqlCompareOptions compareOptions;
71 public static readonly int BinarySort = 0x8000;
72 public static readonly int IgnoreCase = 0x1;
73 public static readonly int IgnoreKanaType = 0x8;
74 public static readonly int IgnoreNonSpace = 0x2;
75 public static readonly int IgnoreWidth = 0x10;
76 public static readonly SqlString Null;
78 internal static NumberFormatInfo DecimalFormat;
85 DecimalFormat = (NumberFormatInfo) NumberFormatInfo.InvariantInfo.Clone ();
86 DecimalFormat.NumberDecimalDigits = 13;
87 DecimalFormat.NumberGroupSeparator = String.Empty;
90 // init with a string data
91 public SqlString (string data)
94 lcid = CultureInfo.CurrentCulture.LCID;
99 this.compareOptions = SqlCompareOptions.IgnoreCase |
100 SqlCompareOptions.IgnoreKanaType |
101 SqlCompareOptions.IgnoreWidth;
104 // init with a string data and locale id values.
105 public SqlString (string data, int lcid)
113 this.compareOptions = SqlCompareOptions.IgnoreCase |
114 SqlCompareOptions.IgnoreKanaType |
115 SqlCompareOptions.IgnoreWidth;
118 // init with locale id, compare options,
119 // and an array of bytes data
120 public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data)
121 : this (lcid, compareOptions, data, true) { }
123 // init with string data, locale id, and compare options
124 public SqlString (string data, int lcid, SqlCompareOptions compareOptions)
128 this.compareOptions = compareOptions;
135 // init with locale id, compare options, array of bytes data,
136 // and whether unicode is encoded or not
137 public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data, bool fUnicode)
139 Encoding encoding = (fUnicode ? Encoding.Unicode : Encoding.ASCII);
140 this.value = encoding.GetString (data);
142 this.compareOptions = compareOptions;
149 // init with locale id, compare options, array of bytes data,
150 // starting index in the byte array,
151 // and number of bytes to copy
152 public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data,
153 int index, int count)
154 : this (lcid, compareOptions, data, index, count, true) { }
156 // init with locale id, compare options, array of bytes data,
157 // starting index in the byte array, number of byte to copy,
158 // and whether unicode is encoded or not
159 public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data, int index, int count, bool fUnicode)
161 Encoding encoding = (fUnicode ? Encoding.Unicode : Encoding.ASCII);
162 this.value = encoding.GetString (data, index, count);
164 this.compareOptions = compareOptions;
171 #endregion // Constructors
174 #region Public Properties
176 public CompareInfo CompareInfo {
178 return new CultureInfo (lcid).CompareInfo;
182 public CultureInfo CultureInfo {
184 return new CultureInfo (lcid);
189 get { return !notNull; }
192 // geographics location and language (locale id)
199 public SqlCompareOptions SqlCompareOptions {
201 return compareOptions;
205 public string Value {
208 throw new SqlNullValueException (Locale.GetText ("The property contains Null."));
214 #endregion // Public Properties
216 #region Private Properties
218 private CompareOptions CompareOptions {
221 (this.compareOptions & SqlCompareOptions.BinarySort) != 0 ?
222 CompareOptions.Ordinal :
223 // 27 == all SqlCompareOptions - BinarySort
224 // (1,2,8,24 are common to CompareOptions)
225 (CompareOptions)((int)this.compareOptions & 27);
229 #endregion Private Properties
231 #region Public Methods
233 public SqlString Clone()
235 return new SqlString (value, lcid, compareOptions);
238 public static CompareOptions CompareOptionsFromSqlCompareOptions (SqlCompareOptions compareOptions)
240 CompareOptions options = CompareOptions.None;
242 if ((compareOptions & SqlCompareOptions.IgnoreCase) != 0)
243 options |= CompareOptions.IgnoreCase;
244 if ((compareOptions & SqlCompareOptions.IgnoreKanaType) != 0)
245 options |= CompareOptions.IgnoreKanaType;
246 if ((compareOptions & SqlCompareOptions.IgnoreNonSpace) != 0)
247 options |= CompareOptions.IgnoreNonSpace;
248 if ((compareOptions & SqlCompareOptions.IgnoreWidth) != 0)
249 options |= CompareOptions.IgnoreWidth;
250 if ((compareOptions & SqlCompareOptions.BinarySort) != 0)
251 // FIXME: Exception string
252 throw new ArgumentOutOfRangeException ();
257 // **********************************
258 // Comparison Methods
259 // **********************************
261 public int CompareTo (object value)
265 else if (!(value is SqlString))
266 throw new ArgumentException (Locale.GetText ("Value is not a System.Data.SqlTypes.SqlString"));
268 return CompareSqlString ((SqlString)value);
272 private int CompareSqlString (SqlString value)
276 else if (value.CompareOptions != this.CompareOptions)
277 throw new SqlTypeException (Locale.GetText ("Two strings to be compared have different collation"));
279 // return String.Compare (this.value, ((SqlString)value).Value, (this.SqlCompareOptions & SqlCompareOptions.IgnoreCase) != 0, this.CultureInfo);
280 return CultureInfo.CompareInfo.Compare (this.value, value.Value, this.CompareOptions);
283 public static SqlString Concat(SqlString x, SqlString y)
288 public override bool Equals(object value)
290 if (!(value is SqlString))
293 return ((SqlString)value).IsNull;
294 else if (((SqlString)value).IsNull)
297 return (bool) (this == (SqlString)value);
300 public static SqlBoolean Equals(SqlString x, SqlString y)
305 public override int GetHashCode()
308 for (int i = 0; i < value.Length; i++)
309 result = 91 * result + (int)(value [i] ^ (value [i] >> 32));
311 result = 91 * result + lcid.GetHashCode ();
312 result = 91 * result + (int)compareOptions;
317 public byte[] GetNonUnicodeBytes()
319 return Encoding.ASCII.GetBytes (value);
322 public byte[] GetUnicodeBytes()
324 return Encoding.Unicode.GetBytes (value);
327 public static SqlBoolean GreaterThan(SqlString x, SqlString y)
332 public static SqlBoolean GreaterThanOrEqual(SqlString x, SqlString y)
337 public static SqlBoolean LessThan(SqlString x, SqlString y)
342 public static SqlBoolean LessThanOrEqual(SqlString x, SqlString y)
347 public static SqlBoolean NotEquals(SqlString x, SqlString y)
352 // ****************************************
353 // Type Conversions From SqlString To ...
354 // ****************************************
356 public SqlBoolean ToSqlBoolean()
358 return ((SqlBoolean)this);
361 public SqlByte ToSqlByte()
363 return ((SqlByte)this);
366 public SqlDateTime ToSqlDateTime()
368 return ((SqlDateTime)this);
371 public SqlDecimal ToSqlDecimal()
373 return ((SqlDecimal)this);
376 public SqlDouble ToSqlDouble()
378 return ((SqlDouble)this);
381 public SqlGuid ToSqlGuid()
383 return ((SqlGuid)this);
386 public SqlInt16 ToSqlInt16()
388 return ((SqlInt16)this);
391 public SqlInt32 ToSqlInt32()
393 return ((SqlInt32)this);
396 public SqlInt64 ToSqlInt64()
398 return ((SqlInt64)this);
401 public SqlMoney ToSqlMoney()
403 return ((SqlMoney)this);
406 public SqlSingle ToSqlSingle()
408 return ((SqlSingle)this);
411 public override string ToString()
415 return ((string)this);
418 // ***********************************
420 // ***********************************
423 public static SqlString operator + (SqlString x, SqlString y)
425 if (x.IsNull || y.IsNull)
426 return SqlString.Null;
428 return new SqlString (x.Value + y.Value);
432 public static SqlBoolean operator == (SqlString x, SqlString y)
434 if (x.IsNull || y.IsNull)
435 return SqlBoolean.Null;
437 return new SqlBoolean (x.Value == y.Value);
441 public static SqlBoolean operator > (SqlString x, SqlString y)
443 if (x.IsNull || y.IsNull)
444 return SqlBoolean.Null;
446 return new SqlBoolean (x.CompareTo (y) > 0);
449 // Greater Than Or Equal
450 public static SqlBoolean operator >= (SqlString x, SqlString y)
452 if (x.IsNull || y.IsNull)
453 return SqlBoolean.Null;
455 return new SqlBoolean (x.CompareTo (y) >= 0);
458 public static SqlBoolean operator != (SqlString x, SqlString y)
460 if (x.IsNull || y.IsNull)
461 return SqlBoolean.Null;
463 return new SqlBoolean (x.Value != y.Value);
467 public static SqlBoolean operator < (SqlString x, SqlString y)
469 if (x.IsNull || y.IsNull)
470 return SqlBoolean.Null;
472 return new SqlBoolean (x.CompareTo (y) < 0);
475 // Less Than Or Equal
476 public static SqlBoolean operator <= (SqlString x, SqlString y)
478 if (x.IsNull || y.IsNull)
479 return SqlBoolean.Null;
481 return new SqlBoolean (x.CompareTo (y) <= 0);
484 // **************************************
486 // **************************************
488 public static explicit operator SqlString (SqlBoolean x)
493 return new SqlString (x.Value.ToString ());
496 public static explicit operator SqlString (SqlByte x)
501 return new SqlString (x.Value.ToString ());
504 public static explicit operator SqlString (SqlDateTime x)
509 return new SqlString (x.Value.ToString ());
512 public static explicit operator SqlString (SqlDecimal x)
517 return new SqlString (x.Value.ToString ());
518 // return new SqlString (x.Value.ToString ("N", DecimalFormat));
521 public static explicit operator SqlString (SqlDouble x)
526 return new SqlString (x.Value.ToString ());
529 public static explicit operator SqlString (SqlGuid x)
534 return new SqlString (x.Value.ToString ());
537 public static explicit operator SqlString (SqlInt16 x)
542 return new SqlString (x.Value.ToString ());
545 public static explicit operator SqlString (SqlInt32 x)
550 return new SqlString (x.Value.ToString ());
553 public static explicit operator SqlString (SqlInt64 x)
558 return new SqlString (x.Value.ToString ());
561 public static explicit operator SqlString (SqlMoney x)
566 return new SqlString (x.ToString ());
569 public static explicit operator SqlString (SqlSingle x)
574 return new SqlString (x.Value.ToString ());
577 public static explicit operator string (SqlString x)
582 public static implicit operator SqlString (string x)
584 return new SqlString (x);
588 public static SqlString Add (SqlString x, SqlString y)
593 public int CompareTo (SqlString value)
595 return CompareSqlString (value);
601 #endregion // Public Methods
603 public static XmlQualifiedName GetXsdType (XmlSchemaSet schemaSet)
605 if (schemaSet != null && schemaSet.Count == 0) {
606 XmlSchema xs = new XmlSchema ();
607 XmlSchemaComplexType ct = new XmlSchemaComplexType ();
612 return new XmlQualifiedName ("string", "http://www.w3.org/2001/XMLSchema");
615 XmlSchema IXmlSerializable.GetSchema ()
620 void IXmlSerializable.ReadXml (XmlReader reader)
625 switch (reader.ReadState) {
626 case ReadState.EndOfFile:
627 case ReadState.Error:
628 case ReadState.Closed:
631 // Skip XML declaration and prolog
632 // or do I need to validate for the <string> tag?
633 reader.MoveToContent ();
638 if (reader.NodeType == XmlNodeType.EndElement)
641 if (reader.Value.Length > 0) {
642 if (String.Compare ("Null", reader.Value) == 0) {
643 // means a null reference/invalid value
647 // FIXME: Validate the value for expected format
648 this.value = reader.Value;
650 this.compareOptions = SqlCompareOptions.IgnoreCase |
651 SqlCompareOptions.IgnoreKanaType |
652 SqlCompareOptions.IgnoreWidth;
656 void IXmlSerializable.WriteXml (XmlWriter writer)
658 writer.WriteString (this.ToString ());