using System.Data;
using System.Data.Common;
using System.Data.SqlTypes;
+using System.Globalization;
+using System.Xml;
namespace System.Data.SqlClient
{
-#if NET_2_0
public class SqlDataReader : DbDataReader, IDataReader, IDisposable, IDataRecord
-#else
- public sealed class SqlDataReader : MarshalByRefObject, IEnumerable, IDataReader, IDisposable, IDataRecord
-#endif // NET_2_0
{
#region Fields
SqlCommand command;
- ArrayList dataTypeNames;
bool disposed;
- int fieldCount;
bool isClosed;
bool moreResults;
int resultsRead;
int rowsRead;
DataTable schemaTable;
- bool hasRows;
bool haveRead;
bool readResult;
bool readResultUsed;
-#if NET_2_0
int visibleFieldCount;
-#endif
#endregion // Fields
const int IS_HIDDEN_IDX = 20;
const int IS_LONG_IDX = 21;
const int IS_READ_ONLY_IDX = 22;
-
+ const int PROVIDER_SPECIFIC_TYPE_IDX = 23;
+ const int DATA_TYPE_NAME_IDX = 24;
+ const int XML_SCHEMA_COLLCTN_DB_IDX = 25;
+ const int XML_SCHEMA_COLLCTN_OWN_SCHEMA_IDX = 26;
+ const int XML_SCHEMA_COLLCTN_NAME_IDX = 27;
+ const int UDT_ASMBLY_QUALIFIED_NAME_IDX = 28;
+ const int NON_VER_PROVIDER_TYPE_IDX = 29;
+ const int IS_COLUMN_SET = 30;
+
#region Constructors
internal SqlDataReader (SqlCommand command)
{
- readResult = false;
- haveRead = false;
- readResultUsed = false;
this.command = command;
- resultsRead = 0;
- fieldCount = 0;
- isClosed = false;
command.Tds.RecordsAffected = -1;
-#if NET_2_0
- visibleFieldCount = 0;
-#endif
NextResult ();
}
#region Properties
public
-#if NET_2_0
override
-#endif // NET_2_0
int Depth {
get { return 0; }
}
public
-#if NET_2_0
override
-#endif // NET_2_0
int FieldCount {
- get { return fieldCount; }
+ get {
+ ValidateState ();
+ return command.Tds.Columns.Count;
+ }
}
public
-#if NET_2_0
override
-#endif // NET_2_0
bool IsClosed {
get { return isClosed; }
}
public
-#if NET_2_0
override
-#endif // NET_2_0
object this [int i] {
get { return GetValue (i); }
}
public
-#if NET_2_0
override
-#endif // NET_2_0
object this [string name] {
get { return GetValue (GetOrdinal (name)); }
}
public
-#if NET_2_0
override
-#endif // NET_2_0
int RecordsAffected {
get {
- return command.Tds.RecordsAffected;
+ return command.Tds.RecordsAffected;
}
}
public
-#if NET_2_0
override
-#endif // NET_2_0
bool HasRows {
get {
- if (haveRead)
- return readResult;
-
- haveRead = true;
- readResult = ReadRecord ();
+ ValidateState ();
+
+ if (rowsRead > 0)
+ return true;
+ if (!haveRead)
+ readResult = ReadRecord ();
return readResult;
}
}
-#if NET_2_0
public override int VisibleFieldCount {
get { return visibleFieldCount; }
}
protected bool IsCommandBehavior (CommandBehavior condition) {
return condition == command.CommandBehavior;
}
-#endif
#endregion // Properties
#region Methods
public
-#if NET_2_0
override
-#endif // NET_2_0
void Close ()
{
if (IsClosed)
while (NextResult ())
;
isClosed = true;
- command.CloseDataReader (moreResults);
+ command.CloseDataReader ();
}
private static DataTable ConstructSchemaTable ()
schemaTable.Columns.Add ("IsHidden", booleanType);
schemaTable.Columns.Add ("IsLong", booleanType);
schemaTable.Columns.Add ("IsReadOnly", booleanType);
-
+ schemaTable.Columns.Add ("ProviderSpecificDataType", typeType);
+ schemaTable.Columns.Add ("DataTypeName", stringType);
+ schemaTable.Columns.Add ("XmlSchemaCollectionDatabase", stringType);
+ schemaTable.Columns.Add ("XmlSchemaCollectionOwningSchema", stringType);
+ schemaTable.Columns.Add ("XmlSchemaCollectionName", stringType);
+ schemaTable.Columns.Add ("UdtAssemblyQualifiedName", stringType);
+ schemaTable.Columns.Add ("NonVersionedProviderType", intType);
+ schemaTable.Columns.Add ("IsColumnSet", booleanType);
+
return schemaTable;
}
+
+ private string GetSchemaRowTypeName (TdsColumnType ctype, int csize, short precision, short scale)
+ {
+ int dbType;
+ bool isLong;
+ Type fieldType;
+
+ string typeName;
+ GetSchemaRowType (ctype, csize, precision, scale,
+ out dbType, out fieldType, out isLong,
+ out typeName);
+ return typeName;
+ }
+
+ private Type GetSchemaRowFieldType (TdsColumnType ctype, int csize, short precision, short scale)
+ {
+ int dbType;
+ bool isLong;
+ Type fieldType;
+ string typeName;
+
+ GetSchemaRowType (ctype, csize, precision, scale,
+ out dbType, out fieldType, out isLong,
+ out typeName);
+ return fieldType;
+ }
+
+ SqlDbType GetSchemaRowDbType (int ordinal)
+ {
+ int csize;
+ short precision, scale;
+ TdsColumnType ctype;
+ TdsDataColumn column;
+
+ if (ordinal < 0 || ordinal >= command.Tds.Columns.Count)
+ throw new IndexOutOfRangeException ();
+
+ column = command.Tds.Columns [ordinal];
+ ctype = (TdsColumnType) column.ColumnType;
+ csize = (int) column.ColumnSize;
+ precision = (short) (column.NumericPrecision ?? 0);
+ scale = (short) (column.NumericScale ?? 0);
+ return GetSchemaRowDbType (ctype, csize, precision, scale);
+ }
+
+ private SqlDbType GetSchemaRowDbType (TdsColumnType ctype, int csize, short precision, short scale)
+ {
+ Type fieldType;
+ bool isLong;
+ string typeName;
+ int dbType;
+
+ GetSchemaRowType (ctype, csize, precision, scale,
+ out dbType, out fieldType, out isLong,
+ out typeName);
+ return (SqlDbType) dbType;
+ }
+
+ private void GetSchemaRowType (TdsColumnType ctype, int csize,
+ short precision, short scale,
+ out int dbType, out Type fieldType,
+ out bool isLong, out string typeName)
+ {
+ dbType = -1;
+ typeName = string.Empty;
+ isLong = false;
+ fieldType = typeof (Type);
+
+ switch (ctype) {
+ case TdsColumnType.Int1:
+ case TdsColumnType.Int2:
+ case TdsColumnType.Int4:
+ case TdsColumnType.IntN:
+ case TdsColumnType.BigInt:
+ switch (csize) {
+ case 1:
+ typeName = "tinyint";
+ dbType = (int) SqlDbType.TinyInt;
+ fieldType = typeof (byte);
+ isLong = false;
+ break;
+ case 2:
+ typeName = "smallint";
+ dbType = (int) SqlDbType.SmallInt;
+ fieldType = typeof (short);
+ isLong = false;
+ break;
+ case 4:
+ typeName = "int";
+ dbType = (int) SqlDbType.Int;
+ fieldType = typeof (int);
+ isLong = false;
+ break;
+ case 8:
+ typeName = "bigint";
+ dbType = (int) SqlDbType.BigInt;
+ fieldType = typeof (long);
+ isLong = false;
+ break;
+ }
+ break;
+ case TdsColumnType.Real:
+ case TdsColumnType.Float8:
+ case TdsColumnType.FloatN:
+ switch (csize) {
+ case 4:
+ typeName = "real";
+ dbType = (int) SqlDbType.Real;
+ fieldType = typeof (float);
+ isLong = false;
+ break;
+ case 8:
+ typeName = "float";
+ dbType = (int) SqlDbType.Float;
+ fieldType = typeof (double);
+ isLong = false;
+ break;
+ }
+ break;
+ case TdsColumnType.Image :
+ typeName = "image";
+ dbType = (int) SqlDbType.Image;
+ fieldType = typeof (byte[]);
+ isLong = true;
+ break;
+ case TdsColumnType.Text :
+ typeName = "text";
+ dbType = (int) SqlDbType.Text;
+ fieldType = typeof (string);
+ isLong = true;
+ break;
+ case TdsColumnType.UniqueIdentifier :
+ typeName = "uniqueidentifier";
+ dbType = (int) SqlDbType.UniqueIdentifier;
+ fieldType = typeof (Guid);
+ isLong = false;
+ break;
+ case TdsColumnType.VarBinary :
+ case TdsColumnType.BigVarBinary :
+ typeName = "varbinary";
+ dbType = (int) SqlDbType.VarBinary;
+ fieldType = typeof (byte[]);
+ isLong = false;
+ break;
+ case TdsColumnType.VarChar :
+ case TdsColumnType.BigVarChar :
+ typeName = "varchar";
+ dbType = (int) SqlDbType.VarChar;
+ fieldType = typeof (string);
+ isLong = false;
+ break;
+ case TdsColumnType.Binary :
+ case TdsColumnType.BigBinary :
+ typeName = "binary";
+ dbType = (int) SqlDbType.Binary;
+ fieldType = typeof (byte[]);
+ isLong = false;
+ break;
+ case TdsColumnType.Char :
+ case TdsColumnType.BigChar :
+ typeName = "char";
+ dbType = (int) SqlDbType.Char;
+ fieldType = typeof (string);
+ isLong = false;
+ break;
+ case TdsColumnType.Bit :
+ case TdsColumnType.BitN :
+ typeName = "bit";
+ dbType = (int) SqlDbType.Bit;
+ fieldType = typeof (bool);
+ isLong = false;
+ break;
+ case TdsColumnType.DateTime4 :
+ case TdsColumnType.DateTime :
+ case TdsColumnType.DateTimeN :
+ switch (csize) {
+ case 4:
+ typeName = "smalldatetime";
+ dbType = (int) SqlDbType.SmallDateTime;
+ fieldType = typeof (DateTime);
+ isLong = false;
+ break;
+ case 8:
+ typeName = "datetime";
+ dbType = (int) SqlDbType.DateTime;
+ fieldType = typeof (DateTime);
+ isLong = false;
+ break;
+ }
+ break;
+ case TdsColumnType.Money :
+ case TdsColumnType.MoneyN :
+ case TdsColumnType.Money4 :
+ switch (csize) {
+ case 4:
+ typeName = "smallmoney";
+ dbType = (int) SqlDbType.SmallMoney;
+ fieldType = typeof (decimal);
+ isLong = false;
+ break;
+ case 8:
+ typeName = "money";
+ dbType = (int) SqlDbType.Money;
+ fieldType = typeof (decimal);
+ isLong = false;
+ break;
+ }
+ break;
+ case TdsColumnType.NText :
+ typeName = "ntext";
+ dbType = (int) SqlDbType.NText;
+ fieldType = typeof (string);
+ isLong = true;
+ break;
+ case TdsColumnType.NVarChar :
+ typeName = "nvarchar";
+ dbType = (int) SqlDbType.NVarChar;
+ fieldType = typeof (string);
+ isLong = false;
+ break;
+ case TdsColumnType.Decimal :
+ case TdsColumnType.Numeric :
+ // TDS 7.0 returns bigint as decimal(19,0)
+ if (precision == 19 && scale == 0) {
+ typeName = "bigint";
+ dbType = (int) SqlDbType.BigInt;
+ fieldType = typeof (long);
+ } else {
+ typeName = "decimal";
+ dbType = (int) SqlDbType.Decimal;
+ fieldType = typeof (decimal);
+ }
+ isLong = false;
+ break;
+ case TdsColumnType.NChar :
+ typeName = "nchar";
+ dbType = (int) SqlDbType.NChar;
+ fieldType = typeof (string);
+ isLong = false;
+ break;
+ case TdsColumnType.SmallMoney :
+ typeName = "smallmoney";
+ dbType = (int) SqlDbType.SmallMoney;
+ fieldType = typeof (decimal);
+ isLong = false;
+ break;
+ default :
+ typeName = "variant";
+ dbType = (int) SqlDbType.Variant;
+ fieldType = typeof (object);
+ isLong = false;
+ break;
+ }
+ }
-#if NET_2_0
new
-#endif
void Dispose (bool disposing)
{
if (!disposed) {
}
public
-#if NET_2_0
override
-#endif // NET_2_0
bool GetBoolean (int i)
{
object value = GetValue (i);
}
public
-#if NET_2_0
override
-#endif // NET_2_0
byte GetByte (int i)
{
object value = GetValue (i);
}
public
-#if NET_2_0
override
-#endif // NET_2_0
long GetBytes (int i, long dataIndex, byte[] buffer, int bufferIndex, int length)
{
if ((command.CommandBehavior & CommandBehavior.SequentialAccess) != 0) {
+ ValidateState ();
+ EnsureDataAvailable ();
+
try {
long len = ((Tds)command.Tds).GetSequentialColumnValue (i, dataIndex, buffer, bufferIndex, length);
if (len == -1)
- throw new InvalidCastException ("Invalid attempt to GetBytes on column "
- + "'" + command.Tds.Columns[i]["ColumnName"] +
- "'." + "The GetBytes function"
- + " can only be used on columns of type Text, NText, or Image");
+ throw CreateGetBytesOnInvalidColumnTypeException (i);
+ if (len == -2)
+ throw new SqlNullValueException ();
return len;
} catch (TdsInternalException ex) {
command.Connection.Close ();
object value = GetValue (i);
if (!(value is byte [])) {
- if (value is DBNull) throw new SqlNullValueException ();
- throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+ SqlDbType type = GetSchemaRowDbType (i);
+ switch (type) {
+ case SqlDbType.Image:
+ if (value is DBNull)
+ throw new SqlNullValueException ();
+ break;
+ case SqlDbType.Text:
+ string text = value as string;
+ if (text != null)
+ value = Encoding.Default.GetBytes (text);
+ else
+ value = null;
+ break;
+ case SqlDbType.NText:
+ string ntext = value as string;
+ if (ntext != null)
+ value = Encoding.Unicode.GetBytes (ntext);
+ else
+ value = null;
+ break;
+ default:
+ throw CreateGetBytesOnInvalidColumnTypeException (i);
+ }
}
-
- if ( buffer == null )
+
+ if (buffer == null)
return ((byte []) value).Length; // Return length of data
// Copy data into buffer
int availLen = (int) ( ( (byte []) value).Length - dataIndex);
if (availLen < length)
length = availLen;
+ if (dataIndex < 0)
+ return 0;
+
Array.Copy ((byte []) value, (int) dataIndex, buffer, bufferIndex, length);
return length; // return actual read count
}
[EditorBrowsableAttribute (EditorBrowsableState.Never)]
public
-#if NET_2_0
override
-#endif // NET_2_0
char GetChar (int i)
{
- object value = GetValue (i);
- if (!(value is char)) {
- if (value is DBNull) throw new SqlNullValueException ();
- throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
- }
- return (char) value;
+ throw new NotSupportedException ();
}
public
-#if NET_2_0
override
-#endif // NET_2_0
long GetChars (int i, long dataIndex, char[] buffer, int bufferIndex, int length)
{
if ((command.CommandBehavior & CommandBehavior.SequentialAccess) != 0) {
+ ValidateState ();
+ EnsureDataAvailable ();
+
+ if (i < 0 || i >= command.Tds.Columns.Count)
+ throw new IndexOutOfRangeException ();
+
Encoding encoding = null;
byte mul = 1;
TdsColumnType colType = (TdsColumnType) command.Tds.Columns[i]["ColumnType"];
}
}
-#if !NET_2_0
- [EditorBrowsableAttribute (EditorBrowsableState.Never)]
- public new IDataReader GetData (int i)
- {
- return ((IDataReader) this [i]);
- }
-#endif
public
-#if NET_2_0
override
-#endif // NET_2_0
string GetDataTypeName (int i)
{
- if (i < 0 || i >= dataTypeNames.Count)
+ TdsDataColumn column;
+ TdsColumnType ctype;
+ int csize;
+ short precision;
+ short scale;
+
+ ValidateState ();
+
+ if (i < 0 || i >= command.Tds.Columns.Count)
throw new IndexOutOfRangeException ();
- return (string) dataTypeNames [i];
+
+ column = command.Tds.Columns [i];
+ ctype = (TdsColumnType) column.ColumnType;
+ csize = (int) column.ColumnSize;
+ precision = (short) (column.NumericPrecision ?? 0);
+ scale = (short) (column.NumericScale ?? 0);
+ return GetSchemaRowTypeName (ctype, csize, precision, scale);
}
public
-#if NET_2_0
override
-#endif // NET_2_0
DateTime GetDateTime (int i)
{
object value = GetValue (i);
return (DateTime) value;
}
+ [MonoTODO]
+ public virtual DateTimeOffset GetDateTimeOffset (int i)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ public virtual TimeSpan GetTimeSpan (int i)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ public virtual SqlChars GetSqlChars (int i)
+ {
+ throw new NotImplementedException ();
+ }
+
public
-#if NET_2_0
override
-#endif // NET_2_0
decimal GetDecimal (int i)
{
object value = GetValue (i);
}
public
-#if NET_2_0
override
-#endif // NET_2_0
double GetDouble (int i)
{
object value = GetValue (i);
}
public
-#if NET_2_0
override
-#endif // NET_2_0
Type GetFieldType (int i)
{
- if (schemaTable == null)
- schemaTable = ConstructSchemaTable ();
- if (i < 0 || i >= schemaTable.Rows.Count)
+ TdsDataColumn column;
+ TdsColumnType ctype;
+ int csize;
+ short precision;
+ short scale;
+
+ ValidateState ();
+
+ if (i < 0 || i >= command.Tds.Columns.Count)
throw new IndexOutOfRangeException ();
- return (Type) schemaTable.Rows[i]["DataType"];
+
+ column = command.Tds.Columns [i];
+ ctype = (TdsColumnType) column.ColumnType;
+ csize = (int) column.ColumnSize;
+ precision = (short) (column.NumericPrecision ?? 0);
+ scale = (short) (column.NumericScale ?? 0);
+ return GetSchemaRowFieldType (ctype, csize, precision,
+ scale);
}
public
-#if NET_2_0
override
-#endif // NET_2_0
float GetFloat (int i)
{
object value = GetValue (i);
}
public
-#if NET_2_0
override
-#endif // NET_2_0
Guid GetGuid (int i)
{
object value = GetValue (i);
}
public
-#if NET_2_0
override
-#endif // NET_2_0
short GetInt16 (int i)
{
object value = GetValue (i);
}
public
-#if NET_2_0
override
-#endif // NET_2_0
int GetInt32 (int i)
{
object value = GetValue (i);
}
public
-#if NET_2_0
override
-#endif // NET_2_0
long GetInt64 (int i)
{
object value = GetValue (i);
}
public
-#if NET_2_0
override
-#endif // NET_2_0
string GetName (int i)
{
- if (schemaTable == null)
- schemaTable = ConstructSchemaTable ();
- return (string) schemaTable.Rows[i]["ColumnName"];
+ ValidateState ();
+
+ if (i < 0 || i >= command.Tds.Columns.Count)
+ throw new IndexOutOfRangeException ();
+ return (string) command.Tds.Columns[i].ColumnName;
}
public
-#if NET_2_0
override
-#endif // NET_2_0
int GetOrdinal (string name)
{
- if (schemaTable == null)
- schemaTable = ConstructSchemaTable ();
- foreach (DataRow schemaRow in schemaTable.Rows)
- if (((string) schemaRow ["ColumnName"]).Equals (name))
- return (int) schemaRow ["ColumnOrdinal"];
- foreach (DataRow schemaRow in schemaTable.Rows)
- if (String.Compare (((string) schemaRow ["ColumnName"]), name, true) == 0)
- return (int) schemaRow ["ColumnOrdinal"];
+ ValidateState ();
+
+ if (name == null)
+ throw new ArgumentNullException ("fieldName");
+
+ string colName;
+ foreach (TdsDataColumn schema in command.Tds.Columns) {
+ colName = schema.ColumnName;
+ if (colName.Equals (name) || String.Compare (colName, name, true) == 0)
+ return (int) schema.ColumnOrdinal;
+ }
throw new IndexOutOfRangeException ();
}
public
-#if NET_2_0
override
-#endif // NET_2_0
DataTable GetSchemaTable ()
{
ValidateState ();
if (!moreResults)
return null;
- fieldCount = 0;
-
- dataTypeNames = new ArrayList (command.Tds.Columns.Count);
-
foreach (TdsDataColumn schema in command.Tds.Columns) {
DataRow row = schemaTable.NewRow ();
-#if NET_2_0
row [COLUMN_NAME_IDX] = GetSchemaValue (schema.ColumnName);
row [COLUMN_ORDINAL_IDX] = GetSchemaValue (schema.ColumnOrdinal);
row [IS_UNIQUE_IDX] = GetSchemaValue (schema.IsUnique);
row [IS_ROW_VERSION_IDX] = GetSchemaValue (schema.IsRowVersion);
row [IS_HIDDEN_IDX] = GetSchemaValue (schema.IsHidden);
row [IS_IDENTITY_IDX] = GetSchemaValue (schema.IsIdentity);
- row [COLUMN_SIZE_IDX] = GetSchemaValue (schema.ColumnSize);
row [NUMERIC_PRECISION_IDX] = GetSchemaValue (schema.NumericPrecision);
- row [NUMERIC_SCALE_IDX] = GetSchemaValue (schema.NumericScale);
row [IS_KEY_IDX] = GetSchemaValue (schema.IsKey);
row [IS_ALIASED_IDX] = GetSchemaValue (schema.IsAliased);
row [IS_EXPRESSION_IDX] = GetSchemaValue (schema.IsExpression);
row [BASE_SCHEMA_NAME_IDX] = GetSchemaValue (schema.BaseSchemaName);
row [BASE_TABLE_NAME_IDX] = GetSchemaValue (schema.BaseTableName);
row [ALLOW_DBNULL_IDX] = GetSchemaValue (schema.AllowDBNull);
-#else
- row ["ColumnName"] = GetSchemaValue (schema, "ColumnName");
- row ["ColumnOrdinal"] = GetSchemaValue (schema, "ColumnOrdinal");
- row ["IsUnique"] = GetSchemaValue (schema, "IsUnique");
- row ["IsAutoIncrement"] = GetSchemaValue (schema, "IsAutoIncrement");
- row ["IsRowVersion"] = GetSchemaValue (schema, "IsRowVersion");
- row ["IsHidden"] = GetSchemaValue (schema, "IsHidden");
- row ["IsIdentity"] = GetSchemaValue (schema, "IsIdentity");
- row ["ColumnSize"] = GetSchemaValue (schema, "ColumnSize");
- row ["NumericPrecision"] = GetSchemaValue (schema, "NumericPrecision");
- row ["NumericScale"] = GetSchemaValue (schema, "NumericScale");
- row ["IsKey"] = GetSchemaValue (schema, "IsKey");
- row ["IsAliased"] = GetSchemaValue (schema, "IsAliased");
- row ["IsExpression"] = GetSchemaValue (schema, "IsExpression");
- row ["IsReadOnly"] = GetSchemaValue (schema, "IsReadOnly");
- row ["BaseServerName"] = GetSchemaValue (schema, "BaseServerName");
- row ["BaseCatalogName"] = GetSchemaValue (schema, "BaseCatalogName");
- row ["BaseColumnName"] = GetSchemaValue (schema, "BaseColumnName");
- row ["BaseSchemaName"] = GetSchemaValue (schema, "BaseSchemaName");
- row ["BaseTableName"] = GetSchemaValue (schema, "BaseTableName");
- row ["AllowDBNull"] = GetSchemaValue (schema, "AllowDBNull");
-#endif
+ row [PROVIDER_SPECIFIC_TYPE_IDX] = DBNull.Value;
+ row [DATA_TYPE_NAME_IDX] = GetSchemaValue (schema.DataTypeName);
+ row [XML_SCHEMA_COLLCTN_DB_IDX] = DBNull.Value;
+ row [XML_SCHEMA_COLLCTN_OWN_SCHEMA_IDX] = DBNull.Value;
+ row [XML_SCHEMA_COLLCTN_NAME_IDX] = DBNull.Value;
+ row [UDT_ASMBLY_QUALIFIED_NAME_IDX] = DBNull.Value;
+ row [NON_VER_PROVIDER_TYPE_IDX] = DBNull.Value;
+ row [IS_COLUMN_SET] = DBNull.Value;
// We don't always get the base column name.
if (row [BASE_COLUMN_NAME_IDX] == DBNull.Value)
row [BASE_COLUMN_NAME_IDX] = row [COLUMN_NAME_IDX];
- int csize;
TdsColumnType ctype;
-
-#if NET_2_0
+ int csize, dbType;
+ Type fieldType;
+ bool isLong;
+ string typeName;
+ short precision;
+ short scale;
ctype = (TdsColumnType) schema.ColumnType;
-#else
- ctype = (TdsColumnType) schema ["ColumnType"];
-#endif
- switch (ctype) {
- case TdsColumnType.Int1:
- case TdsColumnType.Int2:
- case TdsColumnType.Int4:
- case TdsColumnType.IntN:
-#if NET_2_0
- csize = (int) schema.ColumnSize;
-#else
- csize = (int) schema ["ColumnSize"];
-#endif
- switch (csize) {
- case 1:
- dataTypeNames.Add ("tinyint");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.TinyInt;
- row [DATA_TYPE_IDX] = typeof (byte);
- row [IS_LONG_IDX] = false;
- break;
- case 2:
- dataTypeNames.Add ("smallint");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.SmallInt;
- row [DATA_TYPE_IDX] = typeof (short);
- row [IS_LONG_IDX] = false;
- break;
- case 4:
- dataTypeNames.Add ("int");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.Int;
- row [DATA_TYPE_IDX] = typeof (int);
- row [IS_LONG_IDX] = false;
- break;
- case 8:
- dataTypeNames.Add ("bigint");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.BigInt;
- row [DATA_TYPE_IDX] = typeof (long);
- row [IS_LONG_IDX] = false;
- break;
- }
- break;
- case TdsColumnType.Real:
- case TdsColumnType.Float8:
- case TdsColumnType.FloatN:
-#if NET_2_0
- csize = (int) schema.ColumnSize;
-#else
- csize = (int) schema ["ColumnSize"];
-#endif
- switch (csize) {
- case 4:
- dataTypeNames.Add ("real");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.Real;
- row [DATA_TYPE_IDX] = typeof (float);
- row [IS_LONG_IDX] = false;
- break;
- case 8:
- dataTypeNames.Add ("float");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.Float;
- row [DATA_TYPE_IDX] = typeof (double);
- row [IS_LONG_IDX] = false;
- break;
- }
- break;
- case TdsColumnType.Image :
- dataTypeNames.Add ("image");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.Image;
- row [DATA_TYPE_IDX] = typeof (byte[]);
- row [IS_LONG_IDX] = true;
- break;
- case TdsColumnType.Text :
- dataTypeNames.Add ("text");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.Text;
- row [DATA_TYPE_IDX] = typeof (string);
- row [IS_LONG_IDX] = true;
- break;
- case TdsColumnType.UniqueIdentifier :
- dataTypeNames.Add ("uniqueidentifier");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.UniqueIdentifier;
- row [DATA_TYPE_IDX] = typeof (Guid);
- row [IS_LONG_IDX] = false;
- break;
- case TdsColumnType.VarBinary :
- case TdsColumnType.BigVarBinary :
- dataTypeNames.Add ("varbinary");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.VarBinary;
- row [DATA_TYPE_IDX] = typeof (byte[]);
- row [IS_LONG_IDX] = true;
- break;
- case TdsColumnType.VarChar :
- case TdsColumnType.BigVarChar :
- dataTypeNames.Add ("varchar");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.VarChar;
- row [DATA_TYPE_IDX] = typeof (string);
- row [IS_LONG_IDX] = false;
- break;
- case TdsColumnType.Binary :
- case TdsColumnType.BigBinary :
- dataTypeNames.Add ("binary");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.Binary;
- row [DATA_TYPE_IDX] = typeof (byte[]);
- row [IS_LONG_IDX] = true;
- break;
- case TdsColumnType.Char :
- case TdsColumnType.BigChar :
- dataTypeNames.Add ("char");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.Char;
- row [DATA_TYPE_IDX] = typeof (string);
- row [IS_LONG_IDX] = false;
- break;
- case TdsColumnType.Bit :
- case TdsColumnType.BitN :
- dataTypeNames.Add ("bit");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.Bit;
- row [DATA_TYPE_IDX] = typeof (bool);
- row [IS_LONG_IDX] = false;
- break;
- case TdsColumnType.DateTime4 :
- case TdsColumnType.DateTime :
- case TdsColumnType.DateTimeN :
- dataTypeNames.Add ("datetime");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.DateTime;
- row [DATA_TYPE_IDX] = typeof (DateTime);
- row [IS_LONG_IDX] = false;
- break;
- case TdsColumnType.Money :
- case TdsColumnType.MoneyN :
- case TdsColumnType.Money4 :
- dataTypeNames.Add ("money");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.Money;
- row [DATA_TYPE_IDX] = typeof (decimal);
- row [IS_LONG_IDX] = false;
- break;
- case TdsColumnType.NText :
- dataTypeNames.Add ("ntext");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.NText;
- row [DATA_TYPE_IDX] = typeof (string);
- row [IS_LONG_IDX] = true;
- break;
- case TdsColumnType.NVarChar :
- dataTypeNames.Add ("nvarchar");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.NVarChar;
- row [DATA_TYPE_IDX] = typeof (string);
- row [IS_LONG_IDX] = false;
- break;
- case TdsColumnType.Decimal :
- case TdsColumnType.Numeric :
- dataTypeNames.Add ("decimal");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.Decimal;
- row [DATA_TYPE_IDX] = typeof (decimal);
- row [IS_LONG_IDX] = false;
- break;
- case TdsColumnType.NChar :
- dataTypeNames.Add ("nchar");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.NChar;
- row [DATA_TYPE_IDX] = typeof (string);
- row [IS_LONG_IDX] = false;
- break;
- case TdsColumnType.SmallMoney :
- dataTypeNames.Add ("smallmoney");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.SmallMoney;
- row [DATA_TYPE_IDX] = typeof (decimal);
- row [IS_LONG_IDX] = false;
- break;
- default :
- dataTypeNames.Add ("variant");
- row [PROVIDER_TYPE_IDX] = (int) SqlDbType.Variant;
- row [DATA_TYPE_IDX] = typeof (object);
- row [IS_LONG_IDX] = false;
- break;
- }
-#if NET_2_0
+ csize = (int) schema.ColumnSize;
+ precision = (short) GetSchemaValue (schema.NumericPrecision);
+ scale = (short) GetSchemaValue (schema.NumericScale);
+
+ GetSchemaRowType (ctype, csize, precision, scale,
+ out dbType, out fieldType, out isLong,
+ out typeName);
+
+ row [COLUMN_SIZE_IDX] = csize;
+ row [NUMERIC_PRECISION_IDX] = precision;
+ row [NUMERIC_SCALE_IDX] = scale;
+ row [PROVIDER_TYPE_IDX] = dbType;
+ row [DATA_TYPE_IDX] = fieldType;
+ row [IS_LONG_IDX] = isLong;
if ((bool)row [IS_HIDDEN_IDX] == false)
visibleFieldCount += 1;
-#endif
schemaTable.Rows.Add (row);
-
- fieldCount += 1;
}
return schemaTable;
}
}
public
-#if NET_2_0
virtual
-#endif
SqlBinary GetSqlBinary (int i)
{
object value = GetSqlValue (i);
}
public
-#if NET_2_0
virtual
-#endif
SqlBoolean GetSqlBoolean (int i)
{
object value = GetSqlValue (i);
}
public
-#if NET_2_0
virtual
-#endif
SqlByte GetSqlByte (int i)
{
object value = GetSqlValue (i);
}
public
-#if NET_2_0
virtual
-#endif
SqlDateTime GetSqlDateTime (int i)
{
object value = GetSqlValue (i);
}
public
-#if NET_2_0
virtual
-#endif
SqlDecimal GetSqlDecimal (int i)
{
object value = GetSqlValue (i);
}
public
-#if NET_2_0
virtual
-#endif
SqlDouble GetSqlDouble (int i)
{
object value = GetSqlValue (i);
}
public
-#if NET_2_0
virtual
-#endif
SqlGuid GetSqlGuid (int i)
{
object value = GetSqlValue (i);
}
public
-#if NET_2_0
virtual
-#endif
SqlInt16 GetSqlInt16 (int i)
{
object value = GetSqlValue (i);
}
public
-#if NET_2_0
virtual
-#endif
SqlInt32 GetSqlInt32 (int i)
{
object value = GetSqlValue (i);
}
public
-#if NET_2_0
virtual
-#endif
SqlInt64 GetSqlInt64 (int i)
{
object value = GetSqlValue (i);
- // TDS 7.0 returns bigint as decimal(19,0)
- if (value is SqlDecimal) {
- TdsDataColumn schema = command.Tds.Columns[i];
- byte precision, scale;
-
-#if NET_2_0
- precision = (byte)schema.NumericPrecision;
- scale = (byte)schema.NumericScale;
-#else
- precision = (byte)schema["NumericPrecision"];
- scale = (byte)schema["NumericScale"];
-#endif
- if (precision == 19 && scale == 0)
- value = (SqlInt64) (SqlDecimal) value;
- }
if (!(value is SqlInt64))
throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
return (SqlInt64) value;
}
public
-#if NET_2_0
virtual
-#endif
SqlMoney GetSqlMoney (int i)
{
object value = GetSqlValue (i);
}
public
-#if NET_2_0
virtual
-#endif
SqlSingle GetSqlSingle (int i)
{
object value = GetSqlValue (i);
}
public
-#if NET_2_0
virtual
-#endif
SqlString GetSqlString (int i)
{
object value = GetSqlValue (i);
return (SqlString) value;
}
-#if NET_2_0
public virtual SqlXml GetSqlXml (int i)
{
object value = GetSqlValue (i);
if (!(value is SqlXml)) {
- if (value is DBNull) throw new SqlNullValueException ();
- throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+ if (value is DBNull) {
+ throw new SqlNullValueException ();
+ } else if (command.Tds.TdsVersion <= TdsVersion.tds80 && value is SqlString) {
+ // Workaround for TDS 7/8/8.1 clients
+ // Xml column types are supported only from Sql Server 2005 / TDS 9, however
+ // when a TDS 7/8/8.1 client requests for Xml column data, Sql Server 2005 returns
+ // it as NTEXT
+ MemoryStream stream = null;
+ if (!((SqlString) value).IsNull)
+ stream = new MemoryStream (Encoding.Unicode.GetBytes (value.ToString()));
+ value = new SqlXml (stream);
+ } else {
+ throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+ }
}
return (SqlXml) value;
}
-#endif // NET_2_0
public
-#if NET_2_0
virtual
-#endif
object GetSqlValue (int i)
{
- if (schemaTable == null)
- schemaTable = ConstructSchemaTable ();
-
- SqlDbType type = (SqlDbType) (schemaTable.Rows [i]["ProviderType"]);
object value = GetValue (i);
-
+ //Console.WriteLine ("Type of value: {0}", value.GetType ());
+
+ SqlDbType type = GetSchemaRowDbType (i);
switch (type) {
case SqlDbType.BigInt:
if (value == DBNull.Value)
if (value == DBNull.Value)
return SqlDecimal.Null;
if (value is TdsBigDecimal)
- return SqlDecimal.FromTdsBigDecimal ((TdsBigDecimal) value);
+ return SqlDecimalExtensions.FromTdsBigDecimal ((TdsBigDecimal) value);
+ if (value is Int64)
+ return (SqlDecimal)((long) value);
return (SqlDecimal) ((decimal) value);
case SqlDbType.Float:
if (value == DBNull.Value)
if (value == DBNull.Value)
return SqlByte.Null;
return (SqlByte) ((byte) value);
-#if NET_2_0
case SqlDbType.Xml:
if (value == DBNull.Value)
return SqlByte.Null;
return (SqlXml) value;
-#endif
}
throw new InvalidOperationException ("The type of this column is unknown.");
}
public
-#if NET_2_0
virtual
-#endif
int GetSqlValues (object[] values)
{
- if (schemaTable == null)
- schemaTable = ConstructSchemaTable ();
+ ValidateState ();
+ EnsureDataAvailable ();
+
+ if (values == null)
+ throw new ArgumentNullException ("values");
int count = 0;
- int columnCount = schemaTable.Rows.Count;
+ int columnCount = command.Tds.Columns.Count;
int arrayCount = values.Length;
if (arrayCount > columnCount)
}
public
-#if NET_2_0
override
-#endif // NET_2_0
string GetString (int i)
{
object value = GetValue (i);
}
public
-#if NET_2_0
override
-#endif // NET_2_0
object GetValue (int i)
{
+ ValidateState ();
+ EnsureDataAvailable ();
+
if (i < 0 || i >= command.Tds.Columns.Count)
throw new IndexOutOfRangeException ();
}
public
-#if NET_2_0
override
-#endif // NET_2_0
int GetValues (object[] values)
{
+ ValidateState ();
+ EnsureDataAvailable ();
+
+ if (values == null)
+ throw new ArgumentNullException ("values");
+
int len = values.Length;
int bigDecimalIndex = command.Tds.ColumnValues.BigDecimalIndex;
return (len < FieldCount ? len : FieldCount);
}
-#if !NET_2_0
- void IDisposable.Dispose ()
- {
- Dispose (true);
- GC.SuppressFinalize (this);
- }
-#endif
-#if NET_2_0
public override IEnumerator GetEnumerator ()
-#else
- IEnumerator IEnumerable.GetEnumerator ()
-#endif
{
return new DbEnumerator (this);
}
public
-#if NET_2_0
override
-#endif // NET_2_0
bool IsDBNull (int i)
{
return GetValue (i) == DBNull.Value;
}
public
-#if NET_2_0
override
-#endif // NET_2_0
bool NextResult ()
{
ValidateState ();
- if ((command.CommandBehavior & CommandBehavior.SingleResult) != 0 && resultsRead > 0)
+ if ((command.CommandBehavior & CommandBehavior.SingleResult) != 0 && resultsRead > 0) {
+ moreResults = false;
+ rowsRead = 0;
+ haveRead = false;
return false;
+ }
try {
moreResults = command.Tds.NextResult ();
if (!moreResults)
command.GetOutputParameters ();
else {
- //new schema
+ // new schema - don't do anything except reset schemaTable as command.Tds.Columns is already updated
schemaTable = null;
- GetSchemaTable ();
}
rowsRead = 0;
+ haveRead = false;
resultsRead += 1;
return moreResults;
}
public
-#if NET_2_0
override
-#endif // NET_2_0
bool Read ()
{
ValidateState ();
- if ((command.CommandBehavior & CommandBehavior.SingleRow) != 0 && rowsRead > 0)
+ if (!haveRead || readResultUsed)
+ readResult = ReadRecord ();
+ readResultUsed = true;
+ return readResult;
+ }
+
+ internal bool ReadRecord ()
+ {
+ readResultUsed = false;
+
+ if ((command.CommandBehavior & CommandBehavior.SingleRow) != 0 && haveRead)
return false;
if ((command.CommandBehavior & CommandBehavior.SchemaOnly) != 0)
return false;
if (!moreResults)
return false;
-
- if ((haveRead) && (!readResultUsed))
- {
- readResultUsed = true;
- return true;
- }
- return (ReadRecord ());
- }
- internal bool ReadRecord ()
- {
try {
bool result = command.Tds.NextRow ();
-
- rowsRead += 1;
+ if (result)
+ rowsRead++;
+ haveRead = true;
return result;
} catch (TdsInternalException ex) {
command.Connection.Close ();
if (IsClosed)
throw new InvalidOperationException ("Invalid attempt to read data when reader is closed");
}
-
-#if NET_2_0
+
+ void EnsureDataAvailable ()
+ {
+ if (!readResult || !haveRead || !readResultUsed)
+ throw new InvalidOperationException ("No data available.");
+ }
+
+ InvalidCastException CreateGetBytesOnInvalidColumnTypeException (int ordinal)
+ {
+ string message = string.Format (CultureInfo.InvariantCulture,
+ "Invalid attempt to GetBytes on column '{0}'." +
+ "The GetBytes function can only be used on " +
+ "columns of type Text, NText, or Image.",
+ GetName (ordinal));
+ return new InvalidCastException (message);
+ }
+
public override Type GetProviderSpecificFieldType (int i)
{
return (GetSqlValue (i).GetType());
SqlBytes sb = new SqlBytes (val);
return (sb);
}
-#endif // NET_2_0
+
+ public override T GetFieldValue<T> (int i)
+ {
+ return (T)GetValue(i);
+ }
+
+ [MonoTODO]
+ public virtual XmlReader GetXmlReader (int i)
+ {
+ throw new NotImplementedException ();
+ }
#endregion // Methods
}