Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAtsushi Eno <atsushieno@gmail.com>2015-05-07 13:03:11 +0300
committerAtsushi Eno <atsushieno@gmail.com>2015-05-07 13:03:11 +0300
commit8abe9d21b6ddf023423fe31a76246b73e37436d2 (patch)
tree1ba2ba434166513a660fc923ed406facfa5cc487 /mcs/class/Mono.Data.Tds
parent371944bed96981702f5e7a32b30b9fc214db4fbf (diff)
parentf055c46a24ab01049ba6457d225259da948cdd30 (diff)
Merge pull request #1773 from ztzg/sql-server-datetime2
Allow transferring datetime2/datetimeoffset to/from SQL Server 2012
Diffstat (limited to 'mcs/class/Mono.Data.Tds')
-rw-r--r--mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs9
-rw-r--r--mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/TdsColumnType.cs2
-rw-r--r--mcs/class/Mono.Data.Tds/Mono.Data.Tds/TdsMetaParameter.cs92
3 files changed, 97 insertions, 6 deletions
diff --git a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs
index 54210049067..725248a8fc0 100644
--- a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs
+++ b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs
@@ -586,6 +586,13 @@ namespace Mono.Data.Tds.Protocol
} else if (colType == TdsColumnType.BigVarBinary) {
if (size > 8000)
colType = TdsColumnType.Image;
+ } else if (colType == TdsColumnType.DateTime2 ||
+ colType == TdsColumnType.DateTimeOffset) {
+ // HACK: Wire-level DateTime{2,Offset}
+ // require TDS 7.3, which this driver
+ // does not implement correctly--so we
+ // serialize to ASCII instead.
+ colType = TdsColumnType.Char;
}
// Calculation of TypeInfo field
/*
@@ -715,6 +722,8 @@ namespace Mono.Data.Tds.Protocol
case "nchar" :
case "text" :
case "ntext" :
+ case "datetime2":
+ case "datetimeoffset":
byte [] tmp = param.GetBytes ();
Comm.Append (tmp);
break;
diff --git a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/TdsColumnType.cs b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/TdsColumnType.cs
index af3f2271647..bc1f7fb0ba1 100644
--- a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/TdsColumnType.cs
+++ b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/TdsColumnType.cs
@@ -35,6 +35,8 @@ namespace Mono.Data.Tds.Protocol {
Char = 0x2f, // SYBCHAR
DateTime = 0x3d, // SYBDATETIME
DateTime4 = 0x3a, // SYBDATETIME4
+ DateTime2 = 0x2a, // SYBMSDATETIME2
+ DateTimeOffset = 0x2b, // SYBMSDATETIMEOFFSET
DateTimeN = 0x6f, // SYBDATETIMN
Decimal = 0x6a, // SYBDECIMAL
Real = 0x3b, // SYBREAL
diff --git a/mcs/class/Mono.Data.Tds/Mono.Data.Tds/TdsMetaParameter.cs b/mcs/class/Mono.Data.Tds/Mono.Data.Tds/TdsMetaParameter.cs
index b569f643072..e00b9e4e236 100644
--- a/mcs/class/Mono.Data.Tds/Mono.Data.Tds/TdsMetaParameter.cs
+++ b/mcs/class/Mono.Data.Tds/Mono.Data.Tds/TdsMetaParameter.cs
@@ -287,18 +287,31 @@ namespace Mono.Data.Tds {
internal string Prepare ()
{
string typeName = TypeName;
-
- if (typeName == "varbinary") {
- int size = Size;
+ // Cf. GetDateTimeString
+ TdsColumnType actualType = TdsColumnType.Char;
+ int size;
+
+ switch (typeName) {
+ case "varbinary":
+ size = Size;
if (size <= 0) {
size = GetActualSize ();
}
-
+
if (size > 8000) {
typeName = "varbinary(max)";
}
+ break;
+ case "datetime2":
+ actualType = TdsColumnType.DateTime2;
+ typeName = "char";
+ break;
+ case "datetimeoffset":
+ actualType = TdsColumnType.DateTimeOffset;
+ typeName = "char";
+ break;
}
-
+
string includeAt = "@";
if (ParameterName [0] == '@')
includeAt = "";
@@ -313,7 +326,7 @@ namespace Mono.Data.Tds {
case "varchar":
case "varbinary":
//A size of 0 is not allowed in declarations.
- int size = Size;
+ size = Size;
if (size <= 0) {
size = GetActualSize ();
if (size <= 0)
@@ -326,6 +339,14 @@ namespace Mono.Data.Tds {
result.Append (paramSize > 0 ? (paramSize > 4000 ? "(max)" : String.Format ("({0})", paramSize)) : "(4000)");
break;
case "char":
+ size = -1;
+ if (actualType != TdsColumnType.Char)
+ size = GetDateTimeStringLength (actualType);
+ else if (isSizeSet)
+ size = Size;
+ if (size > 0)
+ result.Append (String.Format ("({0})", size));
+ break;
case "nchar":
case "binary":
if (isSizeSet && Size > 0)
@@ -366,6 +387,10 @@ namespace Mono.Data.Tds {
case "float":
case "money":
return 8;
+ case "datetime2":
+ return GetDateTimeStringLength (TdsColumnType.DateTime2);
+ case "datetimeoffset":
+ return GetDateTimeStringLength (TdsColumnType.DateTimeOffset);
case "int":
case "real":
case "smalldatetime":
@@ -386,6 +411,53 @@ namespace Mono.Data.Tds {
return size;
}
+ private int GetDateTimePrecision ()
+ {
+ int precision = Precision;
+
+ // http://msdn.microsoft.com/en-us/library/bb677335.aspx
+ // says that default precision is 7. How do
+ // we distinguish that from zero?
+ if (precision == 0 || precision > 7)
+ precision = 7;
+
+ return precision;
+ }
+
+ private int GetDateTimeStringLength (TdsColumnType type)
+ {
+ int precision = GetDateTimePrecision ();
+ int len = precision == 0 ? 19 : 20 + precision;
+
+ if (type == TdsColumnType.DateTimeOffset)
+ len += 6;
+
+ return len;
+ }
+
+ // HACK: Wire-level DateTime{2,Offset} require TDS
+ // 7.3, which this driver does not implement
+ // correctly--so we serialize to ASCII instead.
+ private string GetDateTimeString (TdsColumnType type)
+ {
+ int precision = GetDateTimePrecision ();
+ string fmt = "yyyy-MM-dd'T'HH':'mm':'ss";
+
+ if (precision > 0)
+ fmt += ".fffffff".Substring(0, precision + 1);
+
+ switch (type) {
+ case TdsColumnType.DateTime2:
+ DateTime dt = (DateTime)Value;
+ return dt.ToString(fmt);
+ case TdsColumnType.DateTimeOffset:
+ DateTimeOffset dto = (DateTimeOffset)Value;
+ return dto.ToString(fmt + "zzz");
+ }
+
+ throw new ApplicationException("Should be unreachable");
+ }
+
internal byte[] GetBytes ()
{
byte[] result = {};
@@ -403,6 +475,10 @@ namespace Mono.Data.Tds {
case "char" :
case "text" :
return Encoding.Default.GetBytes ((string)Value);
+ case "datetime2":
+ return Encoding.Default.GetBytes (GetDateTimeString (TdsColumnType.DateTime2));
+ case "datetimeoffset":
+ return Encoding.Default.GetBytes (GetDateTimeString (TdsColumnType.DateTimeOffset));
default :
return ((byte[]) Value);
}
@@ -441,6 +517,10 @@ namespace Mono.Data.Tds {
if (IsNullable)
return TdsColumnType.DateTimeN;
return TdsColumnType.DateTime4;
+ case "datetime2":
+ return TdsColumnType.DateTime2;
+ case "datetimeoffset":
+ return TdsColumnType.DateTimeOffset;
case "float":
if (IsNullable)
return TdsColumnType.FloatN ;