internal void SetInputValue(object value, ODBC32.SQL_C sql_c_type, int cbsize, int sizeorprecision, int offset, CNativeBuffer parameterBuffer) { if ((ParameterDirection.Input != this._internalDirection) && (ParameterDirection.InputOutput != this._internalDirection)) { this._internalValue = null; parameterBuffer.WriteIntPtr(this._preparedIntOffset, (IntPtr)(-1)); } else if (value == null) { parameterBuffer.WriteIntPtr(this._preparedIntOffset, (IntPtr)(-5)); } else if (Convert.IsDBNull(value)) { parameterBuffer.WriteIntPtr(this._preparedIntOffset, (IntPtr)(-1)); } else { switch (sql_c_type) { case ODBC32.SQL_C.WCHAR: case ODBC32.SQL_C.BINARY: case ODBC32.SQL_C.CHAR: parameterBuffer.WriteIntPtr(this._preparedIntOffset, (IntPtr)cbsize); break; default: parameterBuffer.WriteIntPtr(this._preparedIntOffset, IntPtr.Zero); break; } parameterBuffer.MarshalToNative(this._preparedValueOffset, value, sql_c_type, sizeorprecision, offset); } }
internal static extern /*SQLRETURN*/ ODBC32.RetCode SQLGetData( /*SQLHSTMT*/ OdbcStatementHandle StatementHandle, /*SQLUSMALLINT*/ ushort ColumnNumber, /*SQLSMALLINT*/ ODBC32.SQL_C TargetType, /*SQLPOINTER*/ CNativeBuffer TargetValue, /*SQLLEN*/ IntPtr BufferLength, // sql.h differs from MSDN /*SQLLEN* */ out IntPtr StrLen_or_Ind);
internal static extern /*SQLRETURN*/ ODBC32.RetCode SQLBindCol( /*SQLHSTMT*/ OdbcStatementHandle StatementHandle, /*SQLUSMALLINT*/ ushort ColumnNumber, /*SQLSMALLINT*/ ODBC32.SQL_C TargetType, /*SQLPOINTER*/ IntPtr TargetValue, /*SQLLEN*/ IntPtr BufferLength, /*SQLLEN* */ IntPtr StrLen_or_Ind);
internal object MarshalToManaged(int offset, ODBC32.SQL_C sqlctype, int cb) { switch (sqlctype) { case ODBC32.SQL_C.SLONG: return(base.ReadInt32(offset)); case ODBC32.SQL_C.SSHORT: return(base.ReadInt16(offset)); case ODBC32.SQL_C.SBIGINT: return(base.ReadInt64(offset)); case ODBC32.SQL_C.UTINYINT: return(base.ReadByte(offset)); case ODBC32.SQL_C.GUID: return(base.ReadGuid(offset)); case ODBC32.SQL_C.WCHAR: if (cb != -3) { cb = Math.Min((int)(cb / 2), (int)((base.Length - 2) / 2)); return(base.PtrToStringUni(offset, cb)); } return(base.PtrToStringUni(offset)); case ODBC32.SQL_C.BIT: return(base.ReadByte(offset) != 0); case ODBC32.SQL_C.BINARY: case ODBC32.SQL_C.CHAR: cb = Math.Min(cb, base.Length); return(base.ReadBytes(offset, cb)); case ODBC32.SQL_C.NUMERIC: return(base.ReadNumeric(offset)); case ODBC32.SQL_C.REAL: return(base.ReadSingle(offset)); case ODBC32.SQL_C.DOUBLE: return(base.ReadDouble(offset)); case ODBC32.SQL_C.TYPE_DATE: return(base.ReadDate(offset)); case ODBC32.SQL_C.TYPE_TIME: return(base.ReadTime(offset)); case ODBC32.SQL_C.TYPE_TIMESTAMP: return(base.ReadDateTime(offset)); } return(null); }
internal static extern /*SQLRETURN*/ ODBC32.RetCode SQLBindParameter( /*SQLHSTMT*/ OdbcStatementHandle StatementHandle, /*SQLUSMALLINT*/ ushort ParameterNumber, /*SQLSMALLINT*/ short ParamDirection, /*SQLSMALLINT*/ ODBC32.SQL_C SQLCType, /*SQLSMALLINT*/ short SQLType, /*SQLULEN*/ IntPtr cbColDef, /*SQLSMALLINT*/ IntPtr ibScale, /*SQLPOINTER*/ HandleRef rgbValue, /*SQLLEN*/ IntPtr BufferLength, /*SQLLEN* */ HandleRef StrLen_or_Ind);
internal static partial /*SQLRETURN*/ ODBC32.SQLRETURN SQLBindCol( /*SQLHSTMT*/ OdbcStatementHandle StatementHandle, /*SQLUSMALLINT*/ ushort ColumnNumber, /*SQLSMALLINT*/ ODBC32.SQL_C TargetType, /*SQLPOINTER*/ #if NET7_0_OR_GREATER [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef TargetValue, /*SQLLEN*/ IntPtr BufferLength, /*SQLLEN* */ IntPtr StrLen_or_Ind);
internal ODBC32.RetCode GetData(int index, ODBC32.SQL_C sqlctype, CNativeBuffer buffer, int cb, out IntPtr cbActual) { ODBC32.RetCode retcode = Interop.Odbc.SQLGetData(this, checked ((ushort)index), sqlctype, buffer, new IntPtr(cb), out cbActual); ODBC.TraceODBC(3, "SQLGetData", retcode); return(retcode); }
private TypeMap(OdbcType odbcType, DbType dbType, Type type, ODBC32.SQL_TYPE sql_type, ODBC32.SQL_C sql_c, ODBC32.SQL_C param_sql_c, int bsize, int csize, bool signType) { this._odbcType = odbcType; this._dbType = dbType; this._type = type; this._sql_type = sql_type; this._sql_c = sql_c; this._param_sql_c = param_sql_c; this._bufferSize = bsize; this._columnSize = csize; this._signType = signType; }
internal readonly bool _signType; // this type may be has signature information private TypeMap(OdbcType odbcType, DbType dbType, Type type, ODBC32.SQL_TYPE sql_type, ODBC32.SQL_C sql_c, ODBC32.SQL_C param_sql_c, int bsize, int csize, bool signType) { _odbcType = odbcType; _dbType = dbType; _type = type; _sql_type = sql_type; _sql_c = sql_c; _param_sql_c = param_sql_c; // alternative sql_c type for parameters _bufferSize = bsize; _columnSize = csize; _signType = signType; }
internal void SetInputValue(object value, ODBC32.SQL_C sql_c_type, int cbsize, int sizeorprecision, int offset, CNativeBuffer parameterBuffer) { //Handle any input params if ((ParameterDirection.Input == _internalDirection) || (ParameterDirection.InputOutput == _internalDirection)) { //Note: (lang) "null" means to use the servers default (not DBNull). //We probably should just not have bound this parameter, period, but that //would mess up the users question marks, etc... if ((null == value)) { parameterBuffer.WriteIntPtr(_preparedIntOffset, (IntPtr)ODBC32.SQL_DEFAULT_PARAM); } else if (Convert.IsDBNull(value)) { parameterBuffer.WriteIntPtr(_preparedIntOffset, (IntPtr)ODBC32.SQL_NULL_DATA); } else { switch (sql_c_type) { case ODBC32.SQL_C.CHAR: case ODBC32.SQL_C.WCHAR: case ODBC32.SQL_C.BINARY: //StrLen_or_IndPtr is ignored except for Character or Binary or data. parameterBuffer.WriteIntPtr(_preparedIntOffset, (IntPtr)cbsize); break; default: parameterBuffer.WriteIntPtr(_preparedIntOffset, IntPtr.Zero); break; } //Place the input param value into the native buffer parameterBuffer.MarshalToNative(_preparedValueOffset, value, sql_c_type, sizeorprecision, offset); } } else { // always set ouput only and return value parameter values to null when executing _internalValue = null; //Always initialize the intbuffer (for output params). Since we need to know //if/when the parameters are available for output. (ie: when is the buffer valid...) //if (_sqldirection != ODBC32.SQL_PARAM.INPUT) parameterBuffer.WriteIntPtr(_preparedIntOffset, (IntPtr)ODBC32.SQL_NULL_DATA); } }
internal static partial /*SQLRETURN*/ ODBC32.SQLRETURN SQLBindParameter( /*SQLHSTMT*/ OdbcStatementHandle StatementHandle, /*SQLUSMALLINT*/ ushort ParameterNumber, /*SQLSMALLINT*/ short ParamDirection, /*SQLSMALLINT*/ ODBC32.SQL_C SQLCType, /*SQLSMALLINT*/ short SQLType, /*SQLULEN*/ IntPtr cbColDef, /*SQLSMALLINT*/ IntPtr ibScale, /*SQLPOINTER*/ #if NET7_0_OR_GREATER [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef rgbValue, /*SQLLEN*/ IntPtr BufferLength, /*SQLLEN* */ #if NET7_0_OR_GREATER [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef StrLen_or_Ind);
internal ODBC32.RetCode BindColumn3(int columnNumber, ODBC32.SQL_C targetType, IntPtr srLen_or_Ind) { ODBC32.RetCode retcode = Interop.Odbc.SQLBindCol(this, checked ((ushort)columnNumber), targetType, ADP.PtrZero, ADP.PtrZero, srLen_or_Ind); ODBC.TraceODBC(3, "SQLBindCol", retcode); return(retcode); }
internal ODBC32.RetCode BindColumn2(int columnNumber, ODBC32.SQL_C targetType, HandleRef buffer, IntPtr length, IntPtr srLen_or_Ind) { ODBC32.RetCode retcode = Interop.Odbc.SQLBindCol(this, checked ((ushort)columnNumber), targetType, buffer, length, srLen_or_Ind); ODBC.TraceODBC(3, "SQLBindCol", retcode); return(retcode); }
internal static extern ODBC32.RetCode SQLGetData(OdbcStatementHandle StatementHandle, ushort ColumnNumber, ODBC32.SQL_C TargetType, CNativeBuffer TargetValue, IntPtr BufferLength, out IntPtr StrLen_or_Ind);
internal static extern ODBC32.RetCode SQLBindCol(OdbcStatementHandle StatementHandle, ushort ColumnNumber, ODBC32.SQL_C TargetType, HandleRef TargetValue, IntPtr BufferLength, IntPtr StrLen_or_Ind);
internal void PrepareForBind(OdbcCommand command, short ordinal, ref int parameterBufferSize) { // make a snapshot of the current properties. Properties may change while we work on them // CopyParameterInternal(); object value = ProcessAndGetParameterValue(); int offset = _internalOffset; int size = _internalSize; ODBC32.SQL_C sql_c_type; // offset validation based on the values type // if (offset > 0) { if (value is string) { if (offset > ((string)value).Length) { throw ADP.OffsetOutOfRangeException(); } } else if (value is char[]) { if (offset > ((char[])value).Length) { throw ADP.OffsetOutOfRangeException(); } } else if (value is byte[]) { if (offset > ((byte[])value).Length) { throw ADP.OffsetOutOfRangeException(); } } else { // for all other types offset has no meaning // this is important since we might upgrade some types to strings offset = 0; } } // type support verification for certain data types // switch(_bindtype._sql_type) { case ODBC32.SQL_TYPE.DECIMAL: case ODBC32.SQL_TYPE.NUMERIC: if ( !command.Connection.IsV3Driver // for non V3 driver we always do the conversion || !command.Connection.TestTypeSupport(ODBC32.SQL_TYPE.NUMERIC) // otherwise we convert if the driver does not support numeric || command.Connection.TestRestrictedSqlBindType(_bindtype._sql_type)// or the type is not supported ){ // No support for NUMERIC // Change the type _bindtype = TypeMap._VarChar; if ((null != value) && !Convert.IsDBNull(value)) { value = ((Decimal)value).ToString(CultureInfo.CurrentCulture); size = ((string)value).Length; offset = 0; } } break; case ODBC32.SQL_TYPE.BIGINT: if (!command.Connection.IsV3Driver){ // No support for BIGINT // Change the type _bindtype = TypeMap._VarChar; if ((null != value) && !Convert.IsDBNull(value)) { value = ((Int64)value).ToString(CultureInfo.CurrentCulture); size = ((string)value).Length; offset = 0; } } break; case ODBC32.SQL_TYPE.WCHAR: // MDAC 68993 case ODBC32.SQL_TYPE.WVARCHAR: case ODBC32.SQL_TYPE.WLONGVARCHAR: if (value is Char) { value = value.ToString(); size = ((string)value).Length; offset = 0; } if (!command.Connection.TestTypeSupport (_bindtype._sql_type)) { // No support for WCHAR, WVARCHAR or WLONGVARCHAR // Change the type if (ODBC32.SQL_TYPE.WCHAR == _bindtype._sql_type) { _bindtype = TypeMap._Char; } else if (ODBC32.SQL_TYPE.WVARCHAR == _bindtype._sql_type) { _bindtype = TypeMap._VarChar; } else if (ODBC32.SQL_TYPE.WLONGVARCHAR == _bindtype._sql_type) { _bindtype = TypeMap._Text; } } break; } // end switch // Conversation from WCHAR to CHAR, VARCHAR or LONVARCHAR (AnsiString) is different for some providers // we need to chonvert WCHAR to CHAR and bind as sql_c_type = CHAR // sql_c_type = _bindtype._sql_c; if (!command.Connection.IsV3Driver) { if (sql_c_type == ODBC32.SQL_C.WCHAR) { sql_c_type = ODBC32.SQL_C.CHAR; if (null != value){ if (!Convert.IsDBNull(value) && value is string) { int lcid = System.Globalization.CultureInfo.CurrentCulture.LCID; CultureInfo culInfo = new CultureInfo(lcid); Encoding cpe = System.Text.Encoding.GetEncoding(culInfo.TextInfo.ANSICodePage); value = cpe.GetBytes(value.ToString()); size = ((byte[])value).Length; } } } }; int cbParameterSize = GetParameterSize(value, offset, ordinal); // count of bytes for the data, for SQLBindParameter // here we upgrade the datatypes if the given values size is bigger than the types columnsize // switch(_bindtype._sql_type) { case ODBC32.SQL_TYPE.VARBINARY: // MDAC 74372 // Note: per definition DbType.Binary does not support more than 8000 bytes so we change the type for binding if ((cbParameterSize > 8000)) { _bindtype = TypeMap._Image; } // will change to LONGVARBINARY break; case ODBC32.SQL_TYPE.VARCHAR: // MDAC 74372 // Note: per definition DbType.Binary does not support more than 8000 bytes so we change the type for binding if ((cbParameterSize > 8000)) { _bindtype = TypeMap._Text; } // will change to LONGVARCHAR break; case ODBC32.SQL_TYPE.WVARCHAR : // MDAC 75099 // Note: per definition DbType.Binary does not support more than 8000 bytes so we change the type for binding if ((cbParameterSize > 4000)) { _bindtype = TypeMap._NText; } // will change to WLONGVARCHAR break; } _prepared_Sql_C_Type = sql_c_type; _preparedOffset = offset; _preparedSize = size; _preparedValue = value; _preparedBufferSize = cbParameterSize; _preparedIntOffset = parameterBufferSize; _preparedValueOffset = _preparedIntOffset + IntPtr.Size; parameterBufferSize += (cbParameterSize + IntPtr.Size); }
internal void PrepareForBind(OdbcCommand command, short ordinal, ref int parameterBufferSize) { this.CopyParameterInternal(); object bytes = this.ProcessAndGetParameterValue(); int offset = this._internalOffset; int length = this._internalSize; if (offset > 0) { if (bytes is string) { if (offset > ((string)bytes).Length) { throw ADP.OffsetOutOfRangeException(); } } else if (bytes is char[]) { if (offset > ((char[])bytes).Length) { throw ADP.OffsetOutOfRangeException(); } } else if (bytes is byte[]) { if (offset > ((byte[])bytes).Length) { throw ADP.OffsetOutOfRangeException(); } } else { offset = 0; } } switch (this._bindtype._sql_type) { case ODBC32.SQL_TYPE.WLONGVARCHAR: case ODBC32.SQL_TYPE.WVARCHAR: case ODBC32.SQL_TYPE.WCHAR: if (bytes is char) { bytes = bytes.ToString(); length = ((string)bytes).Length; offset = 0; } if (!command.Connection.TestTypeSupport(this._bindtype._sql_type)) { if (ODBC32.SQL_TYPE.WCHAR == this._bindtype._sql_type) { this._bindtype = TypeMap._Char; } else if (ODBC32.SQL_TYPE.WVARCHAR == this._bindtype._sql_type) { this._bindtype = TypeMap._VarChar; } else if (ODBC32.SQL_TYPE.WLONGVARCHAR == this._bindtype._sql_type) { this._bindtype = TypeMap._Text; } } break; case ODBC32.SQL_TYPE.BIGINT: if (!command.Connection.IsV3Driver) { this._bindtype = TypeMap._VarChar; if ((bytes != null) && !Convert.IsDBNull(bytes)) { bytes = ((long)bytes).ToString(CultureInfo.CurrentCulture); length = ((string)bytes).Length; offset = 0; } } break; case ODBC32.SQL_TYPE.NUMERIC: case ODBC32.SQL_TYPE.DECIMAL: if ((!command.Connection.IsV3Driver || !command.Connection.TestTypeSupport(ODBC32.SQL_TYPE.NUMERIC)) || command.Connection.TestRestrictedSqlBindType(this._bindtype._sql_type)) { this._bindtype = TypeMap._VarChar; if ((bytes != null) && !Convert.IsDBNull(bytes)) { bytes = ((decimal)bytes).ToString(CultureInfo.CurrentCulture); length = ((string)bytes).Length; offset = 0; } } break; } ODBC32.SQL_C cHAR = this._bindtype._sql_c; if (!command.Connection.IsV3Driver && (cHAR == ODBC32.SQL_C.WCHAR)) { cHAR = ODBC32.SQL_C.CHAR; if (((bytes != null) && !Convert.IsDBNull(bytes)) && (bytes is string)) { CultureInfo info = new CultureInfo(CultureInfo.CurrentCulture.LCID); bytes = Encoding.GetEncoding(info.TextInfo.ANSICodePage).GetBytes(bytes.ToString()); length = ((byte[])bytes).Length; } } int num2 = this.GetParameterSize(bytes, offset, ordinal); switch (this._bindtype._sql_type) { case ODBC32.SQL_TYPE.WVARCHAR: if (num2 > 0xfa0) { this._bindtype = TypeMap._NText; } break; case ODBC32.SQL_TYPE.VARBINARY: if (num2 > 0x1f40) { this._bindtype = TypeMap._Image; } break; case ODBC32.SQL_TYPE.VARCHAR: if (num2 > 0x1f40) { this._bindtype = TypeMap._Text; } break; } this._prepared_Sql_C_Type = cHAR; this._preparedOffset = offset; this._preparedSize = length; this._preparedValue = bytes; this._preparedBufferSize = num2; this._preparedIntOffset = parameterBufferSize; this._preparedValueOffset = this._preparedIntOffset + IntPtr.Size; parameterBufferSize += num2 + IntPtr.Size; }
internal object MarshalToManaged(int offset, ODBC32.SQL_C sqlctype, int cb) { object value; switch (sqlctype) { case ODBC32.SQL_C.WCHAR: //Note: We always bind as unicode if (cb == ODBC32.SQL_NTS) { value = PtrToStringUni(offset); break; } Debug.Assert((cb > 0), "Character count negative "); Debug.Assert((Length >= cb), "Native buffer too small "); cb = Math.Min(cb / 2, (Length - 2) / 2); value = PtrToStringUni(offset, cb); break; case ODBC32.SQL_C.CHAR: case ODBC32.SQL_C.BINARY: Debug.Assert((cb > 0), "Character count negative "); Debug.Assert((Length >= cb), "Native buffer too small "); cb = Math.Min(cb, Length); value = ReadBytes(offset, cb); break; case ODBC32.SQL_C.SSHORT: value = ReadInt16(offset); break; case ODBC32.SQL_C.SLONG: value = ReadInt32(offset); break; case ODBC32.SQL_C.SBIGINT: value = ReadInt64(offset); break; case ODBC32.SQL_C.BIT: byte b = ReadByte(offset); value = (b != 0x00); break; case ODBC32.SQL_C.REAL: value = ReadSingle(offset); break; case ODBC32.SQL_C.DOUBLE: value = ReadDouble(offset); break; case ODBC32.SQL_C.UTINYINT: value = ReadByte(offset); break; case ODBC32.SQL_C.GUID: value = ReadGuid(offset); break; case ODBC32.SQL_C.TYPE_TIMESTAMP: //So we are mapping this ourselves. //typedef struct tagTIMESTAMP_STRUCT //{ // SQLSMALLINT year; // SQLUSMALLINT month; // SQLUSMALLINT day; // SQLUSMALLINT hour; // SQLUSMALLINT minute; // SQLUSMALLINT second; // SQLUINTEGER fraction; (billoniths of a second) //} value = ReadDateTime(offset); break; // Note: System does not provide a date-only type case ODBC32.SQL_C.TYPE_DATE: // typedef struct tagDATE_STRUCT // { // SQLSMALLINT year; // SQLUSMALLINT month; // SQLUSMALLINT day; // } DATE_STRUCT; value = ReadDate(offset); break; // Note: System does not provide a date-only type case ODBC32.SQL_C.TYPE_TIME: // typedef struct tagTIME_STRUCT // { // SQLUSMALLINT hour; // SQLUSMALLINT minute; // SQLUSMALLINT second; // } TIME_STRUCT; value = ReadTime(offset); break; case ODBC32.SQL_C.NUMERIC: //Note: Unfortunatly the ODBC NUMERIC structure and the URT DECIMAL structure do not //align, so we can't so do the typical "PtrToStructure" call (below) like other types //We actually have to go through the pain of pulling our raw bytes and building the decimal // Marshal.PtrToStructure(buffer, typeof(decimal)); //So we are mapping this ourselves //typedef struct tagSQL_NUMERIC_STRUCT //{ // SQLCHAR precision; // SQLSCHAR scale; // SQLCHAR sign; /* 1 if positive, 0 if negative */ // SQLCHAR val[SQL_MAX_NUMERIC_LEN]; //} SQL_NUMERIC_STRUCT; value = ReadNumeric(offset); break; default: Debug.Fail("UnknownSQLCType"); value = null; break; } ; return(value); }
internal void Bind(OdbcStatementHandle hstmt, OdbcCommand command, short ordinal, CNativeBuffer parameterBuffer, bool allowReentrance) { ODBC32.SQL_C sql_c = this._prepared_Sql_C_Type; ODBC32.SQL_PARAM sql_param = this.SqlDirectionFromParameterDirection(); int offset = this._preparedOffset; int sizeorprecision = this._preparedSize; object obj2 = this._preparedValue; int valueSize = this.GetValueSize(obj2, offset); int num4 = this.GetColumnSize(obj2, offset, ordinal); byte parameterPrecision = this.GetParameterPrecision(obj2); byte parameterScale = this.GetParameterScale(obj2); HandleRef buffer = parameterBuffer.PtrOffset(this._preparedValueOffset, this._preparedBufferSize); HandleRef intbuffer = parameterBuffer.PtrOffset(this._preparedIntOffset, IntPtr.Size); if (ODBC32.SQL_C.NUMERIC == sql_c) { if (((ODBC32.SQL_PARAM.INPUT_OUTPUT == sql_param) && (obj2 is decimal)) && (parameterScale < this._internalScale)) { while (parameterScale < this._internalScale) { obj2 = ((decimal)obj2) * 10M; parameterScale = (byte)(parameterScale + 1); } } this.SetInputValue(obj2, sql_c, valueSize, parameterPrecision, 0, parameterBuffer); if (ODBC32.SQL_PARAM.INPUT != sql_param) { parameterBuffer.WriteInt16(this._preparedValueOffset, (short)((parameterScale << 8) | parameterPrecision)); } } else { this.SetInputValue(obj2, sql_c, valueSize, sizeorprecision, offset, parameterBuffer); } if (((this._hasChanged || (this._boundSqlCType != sql_c)) || ((this._boundParameterType != this._bindtype._sql_type) || (this._boundSize != num4))) || (((this._boundScale != parameterScale) || (this._boundBuffer != buffer.Handle)) || (this._boundIntbuffer != intbuffer.Handle))) { ODBC32.RetCode retcode = hstmt.BindParameter(ordinal, (short)sql_param, sql_c, this._bindtype._sql_type, (IntPtr)num4, (IntPtr)parameterScale, buffer, (IntPtr)this._preparedBufferSize, intbuffer); if (retcode != ODBC32.RetCode.SUCCESS) { if ("07006" == command.GetDiagSqlState()) { Bid.Trace("<odbc.OdbcParameter.Bind|ERR> Call to BindParameter returned errorcode [07006]\n"); command.Connection.FlagRestrictedSqlBindType(this._bindtype._sql_type); if (allowReentrance) { this.Bind(hstmt, command, ordinal, parameterBuffer, false); return; } } command.Connection.HandleError(hstmt, retcode); } this._hasChanged = false; this._boundSqlCType = sql_c; this._boundParameterType = this._bindtype._sql_type; this._boundSize = num4; this._boundScale = parameterScale; this._boundBuffer = buffer.Handle; this._boundIntbuffer = intbuffer.Handle; if (ODBC32.SQL_C.NUMERIC == sql_c) { OdbcDescriptorHandle descriptorHandle = command.GetDescriptorHandle(ODBC32.SQL_ATTR.APP_PARAM_DESC); retcode = descriptorHandle.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.TYPE, (IntPtr)2L); if (retcode != ODBC32.RetCode.SUCCESS) { command.Connection.HandleError(hstmt, retcode); } int num2 = parameterPrecision; retcode = descriptorHandle.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.PRECISION, (IntPtr)num2); if (retcode != ODBC32.RetCode.SUCCESS) { command.Connection.HandleError(hstmt, retcode); } num2 = parameterScale; retcode = descriptorHandle.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.SCALE, (IntPtr)num2); if (retcode != ODBC32.RetCode.SUCCESS) { command.Connection.HandleError(hstmt, retcode); } retcode = descriptorHandle.SetDescriptionField2(ordinal, ODBC32.SQL_DESC.DATA_PTR, buffer); if (retcode != ODBC32.RetCode.SUCCESS) { command.Connection.HandleError(hstmt, retcode); } } } }
internal void PrepareForBind(OdbcCommand command, short ordinal, ref int parameterBufferSize) { // make a snapshot of the current properties. Properties may change while we work on them // CopyParameterInternal(); object value = ProcessAndGetParameterValue(); int offset = _internalOffset; int size = _internalSize; ODBC32.SQL_C sql_c_type; // offset validation based on the values type // if (offset > 0) { if (value is string) { if (offset > ((string)value).Length) { throw ADP.OffsetOutOfRangeException(); } } else if (value is char[]) { if (offset > ((char[])value).Length) { throw ADP.OffsetOutOfRangeException(); } } else if (value is byte[]) { if (offset > ((byte[])value).Length) { throw ADP.OffsetOutOfRangeException(); } } else { // for all other types offset has no meaning // this is important since we might upgrade some types to strings offset = 0; } } // type support verification for certain data types // switch (_bindtype._sql_type) { case ODBC32.SQL_TYPE.DECIMAL: case ODBC32.SQL_TYPE.NUMERIC: if ( !command.Connection.IsV3Driver || // for non V3 driver we always do the conversion !command.Connection.TestTypeSupport(ODBC32.SQL_TYPE.NUMERIC) || // otherwise we convert if the driver does not support numeric command.Connection.TestRestrictedSqlBindType(_bindtype._sql_type) // or the type is not supported ) { // No support for NUMERIC // Change the type _bindtype = TypeMap._VarChar; if ((null != value) && !Convert.IsDBNull(value)) { value = ((Decimal)value).ToString(CultureInfo.CurrentCulture); size = ((string)value).Length; offset = 0; } } break; case ODBC32.SQL_TYPE.BIGINT: if (!command.Connection.IsV3Driver) { // No support for BIGINT // Change the type _bindtype = TypeMap._VarChar; if ((null != value) && !Convert.IsDBNull(value)) { value = ((Int64)value).ToString(CultureInfo.CurrentCulture); size = ((string)value).Length; offset = 0; } } break; case ODBC32.SQL_TYPE.WCHAR: // MDAC 68993 case ODBC32.SQL_TYPE.WVARCHAR: case ODBC32.SQL_TYPE.WLONGVARCHAR: if (value is char) { value = value.ToString(); size = ((string)value).Length; offset = 0; } if (!command.Connection.TestTypeSupport(_bindtype._sql_type)) { // No support for WCHAR, WVARCHAR or WLONGVARCHAR // Change the type if (ODBC32.SQL_TYPE.WCHAR == _bindtype._sql_type) { _bindtype = TypeMap._Char; } else if (ODBC32.SQL_TYPE.WVARCHAR == _bindtype._sql_type) { _bindtype = TypeMap._VarChar; } else if (ODBC32.SQL_TYPE.WLONGVARCHAR == _bindtype._sql_type) { _bindtype = TypeMap._Text; } } break; } // end switch // Conversation from WCHAR to CHAR, VARCHAR or LONVARCHAR (AnsiString) is different for some providers // we need to chonvert WCHAR to CHAR and bind as sql_c_type = CHAR // sql_c_type = _bindtype._sql_c; if (!command.Connection.IsV3Driver) { if (sql_c_type == ODBC32.SQL_C.WCHAR) { sql_c_type = ODBC32.SQL_C.CHAR; if (null != value) { if (!Convert.IsDBNull(value) && value is string) { int lcid = System.Globalization.CultureInfo.CurrentCulture.LCID; CultureInfo culInfo = new CultureInfo(lcid); Encoding cpe = System.Text.Encoding.GetEncoding(culInfo.TextInfo.ANSICodePage); value = cpe.GetBytes(value.ToString()); size = ((byte[])value).Length; } } } } ; int cbParameterSize = GetParameterSize(value, offset, ordinal); // count of bytes for the data, for SQLBindParameter // Upgrade input value type if the size of input value is bigger than the max size of the input value type. switch (_bindtype._sql_type) { case ODBC32.SQL_TYPE.VARBINARY: // Max length of VARBINARY is 8,000 of byte array. if (size > 8000) { _bindtype = TypeMap._Image; // will change to LONGVARBINARY } break; case ODBC32.SQL_TYPE.VARCHAR: // Max length of VARCHAR is 8,000 of non-unicode characters. if (size > 8000) { _bindtype = TypeMap._Text; // will change to LONGVARCHAR } break; case ODBC32.SQL_TYPE.WVARCHAR: // Max length of WVARCHAR (NVARCHAR) is 4,000 of unicode characters. if (size > 4000) { _bindtype = TypeMap._NText; // will change to WLONGVARCHAR } break; } _prepared_Sql_C_Type = sql_c_type; _preparedOffset = offset; _preparedSize = size; _preparedValue = value; _preparedBufferSize = cbParameterSize; _preparedIntOffset = parameterBufferSize; _preparedValueOffset = _preparedIntOffset + IntPtr.Size; parameterBufferSize += (cbParameterSize + IntPtr.Size); }
static internal Exception UnknownSQLCType(ODBC32.SQL_C sqlctype) { return(Argument(Res.GetString(GetCultureInfo(), Res.Odbc_UnknownSQLCType, sqlctype.ToString()))); }
internal void MarshalToNative(int offset, object value, ODBC32.SQL_C sqlctype, int sizeorprecision, int valueOffset) { ODBC32.SQL_C sql_c = sqlctype; if (sql_c <= ODBC32.SQL_C.SSHORT) { if (sql_c != ODBC32.SQL_C.UTINYINT) { switch (sql_c) { case ODBC32.SQL_C.SLONG: base.WriteInt32(offset, (int)value); return; case ODBC32.SQL_C.SSHORT: base.WriteInt16(offset, (short)value); return; case ODBC32.SQL_C.SBIGINT: base.WriteInt64(offset, (long)value); return; } } else { base.WriteByte(offset, (byte)value); } } else if (sql_c <= ODBC32.SQL_C.NUMERIC) { switch (sql_c) { case ODBC32.SQL_C.GUID: base.WriteGuid(offset, (Guid)value); return; case ~(ODBC32.SQL_C.CHAR | ODBC32.SQL_C.DOUBLE): case ~ODBC32.SQL_C.DOUBLE: case ((ODBC32.SQL_C)(-1)): case ((ODBC32.SQL_C) 0): return; case ODBC32.SQL_C.WCHAR: int num; char[] chArray; if (value is string) { num = Math.Max(0, ((string)value).Length - valueOffset); if ((sizeorprecision > 0) && (sizeorprecision < num)) { num = sizeorprecision; } chArray = ((string)value).ToCharArray(valueOffset, num); base.WriteCharArray(offset, chArray, 0, chArray.Length); base.WriteInt16(offset + (chArray.Length * 2), 0); return; } num = Math.Max(0, ((char[])value).Length - valueOffset); if ((sizeorprecision > 0) && (sizeorprecision < num)) { num = sizeorprecision; } chArray = (char[])value; base.WriteCharArray(offset, chArray, valueOffset, num); base.WriteInt16(offset + (chArray.Length * 2), 0); return; case ODBC32.SQL_C.BIT: base.WriteByte(offset, ((bool)value) ? ((byte)1) : ((byte)0)); return; case ODBC32.SQL_C.BINARY: case ODBC32.SQL_C.CHAR: { byte[] source = (byte[])value; int length = source.Length; length -= valueOffset; if ((sizeorprecision > 0) && (sizeorprecision < length)) { length = sizeorprecision; } base.WriteBytes(offset, source, valueOffset, length); return; } case ODBC32.SQL_C.NUMERIC: base.WriteNumeric(offset, (decimal)value, (byte)sizeorprecision); return; } } else { switch (sql_c) { case ODBC32.SQL_C.REAL: base.WriteSingle(offset, (float)value); return; case ODBC32.SQL_C.DOUBLE: base.WriteDouble(offset, (double)value); return; case ODBC32.SQL_C.TYPE_DATE: base.WriteDate(offset, (DateTime)value); return; case ODBC32.SQL_C.TYPE_TIME: base.WriteTime(offset, (TimeSpan)value); return; case ODBC32.SQL_C.TYPE_TIMESTAMP: this.WriteODBCDateTime(offset, (DateTime)value); return; default: return; } } }
internal void Bind(OdbcStatementHandle hstmt, OdbcCommand command, short ordinal, CNativeBuffer parameterBuffer, bool allowReentrance) { ODBC32.SQL_C sql_c = this._prepared_Sql_C_Type; ODBC32.SQL_PARAM sql_param = this.SqlDirectionFromParameterDirection(); int offset = this._preparedOffset; int sizeorprecision = this._preparedSize; object obj2 = this._preparedValue; int valueSize = this.GetValueSize(obj2, offset); int num4 = this.GetColumnSize(obj2, offset, ordinal); byte parameterPrecision = this.GetParameterPrecision(obj2); byte parameterScale = this.GetParameterScale(obj2); HandleRef buffer = parameterBuffer.PtrOffset(this._preparedValueOffset, this._preparedBufferSize); HandleRef intbuffer = parameterBuffer.PtrOffset(this._preparedIntOffset, IntPtr.Size); if (ODBC32.SQL_C.NUMERIC == sql_c) { if (((ODBC32.SQL_PARAM.INPUT_OUTPUT == sql_param) && (obj2 is decimal)) && (parameterScale < this._internalScale)) { while (parameterScale < this._internalScale) { obj2 = ((decimal) obj2) * 10M; parameterScale = (byte) (parameterScale + 1); } } this.SetInputValue(obj2, sql_c, valueSize, parameterPrecision, 0, parameterBuffer); if (ODBC32.SQL_PARAM.INPUT != sql_param) { parameterBuffer.WriteInt16(this._preparedValueOffset, (short) ((parameterScale << 8) | parameterPrecision)); } } else { this.SetInputValue(obj2, sql_c, valueSize, sizeorprecision, offset, parameterBuffer); } if (((this._hasChanged || (this._boundSqlCType != sql_c)) || ((this._boundParameterType != this._bindtype._sql_type) || (this._boundSize != num4))) || (((this._boundScale != parameterScale) || (this._boundBuffer != buffer.Handle)) || (this._boundIntbuffer != intbuffer.Handle))) { ODBC32.RetCode retcode = hstmt.BindParameter(ordinal, (short) sql_param, sql_c, this._bindtype._sql_type, (IntPtr) num4, (IntPtr) parameterScale, buffer, (IntPtr) this._preparedBufferSize, intbuffer); if (retcode != ODBC32.RetCode.SUCCESS) { if ("07006" == command.GetDiagSqlState()) { Bid.Trace("<odbc.OdbcParameter.Bind|ERR> Call to BindParameter returned errorcode [07006]\n"); command.Connection.FlagRestrictedSqlBindType(this._bindtype._sql_type); if (allowReentrance) { this.Bind(hstmt, command, ordinal, parameterBuffer, false); return; } } command.Connection.HandleError(hstmt, retcode); } this._hasChanged = false; this._boundSqlCType = sql_c; this._boundParameterType = this._bindtype._sql_type; this._boundSize = num4; this._boundScale = parameterScale; this._boundBuffer = buffer.Handle; this._boundIntbuffer = intbuffer.Handle; if (ODBC32.SQL_C.NUMERIC == sql_c) { OdbcDescriptorHandle descriptorHandle = command.GetDescriptorHandle(ODBC32.SQL_ATTR.APP_PARAM_DESC); retcode = descriptorHandle.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.TYPE, (IntPtr) 2L); if (retcode != ODBC32.RetCode.SUCCESS) { command.Connection.HandleError(hstmt, retcode); } int num2 = parameterPrecision; retcode = descriptorHandle.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.PRECISION, (IntPtr) num2); if (retcode != ODBC32.RetCode.SUCCESS) { command.Connection.HandleError(hstmt, retcode); } num2 = parameterScale; retcode = descriptorHandle.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.SCALE, (IntPtr) num2); if (retcode != ODBC32.RetCode.SUCCESS) { command.Connection.HandleError(hstmt, retcode); } retcode = descriptorHandle.SetDescriptionField2(ordinal, ODBC32.SQL_DESC.DATA_PTR, buffer); if (retcode != ODBC32.RetCode.SUCCESS) { command.Connection.HandleError(hstmt, retcode); } } } }
internal void Bind(OdbcStatementHandle hstmt, OdbcCommand command, short ordinal, CNativeBuffer parameterBuffer, bool allowReentrance) { ODBC32.RetCode retcode; ODBC32.SQL_C sql_c_type = _prepared_Sql_C_Type; ODBC32.SQL_PARAM sqldirection = SqlDirectionFromParameterDirection(); int offset = _preparedOffset; int size = _preparedSize; object value = _preparedValue; int cbValueSize = GetValueSize(value, offset); // count of bytes for the data int cchSize = GetColumnSize(value, offset, ordinal); // count of bytes for the data, used to allocate the buffer length byte precision = GetParameterPrecision(value); byte scale = GetParameterScale(value); int cbActual; HandleRef valueBuffer = parameterBuffer.PtrOffset(_preparedValueOffset, _preparedBufferSize); HandleRef intBuffer = parameterBuffer.PtrOffset(_preparedIntOffset, IntPtr.Size); // for the numeric datatype we need to do some special case handling ... // if (ODBC32.SQL_C.NUMERIC == sql_c_type) { // for input/output parameters we need to adjust the scale of the input value since the convert function in // sqlsrv32 takes this scale for the output parameter (possible bug in sqlsrv32?) // if ((ODBC32.SQL_PARAM.INPUT_OUTPUT == sqldirection) && (value is Decimal)) { if (scale < _internalScale) { while (scale < _internalScale) { value = ((decimal)value ) * 10; scale++; } } } SetInputValue(value, sql_c_type, cbValueSize, precision, 0, parameterBuffer); // for output parameters we need to write precision and scale to the buffer since the convert function in // sqlsrv32 expects these values there (possible bug in sqlsrv32?) // if (ODBC32.SQL_PARAM.INPUT != sqldirection) { parameterBuffer.WriteInt16(_preparedValueOffset, (short)(((ushort)scale << 8) | (ushort)precision)); } } else { SetInputValue(value, sql_c_type, cbValueSize, size, offset, parameterBuffer); } // Try to reuse existing bindings if // the binding is valid (means we already went through binding all parameters) // the parametercollection is bound already // the bindtype ParameterType did not change (forced upgrade) if (!_hasChanged && (_boundSqlCType == sql_c_type) && (_boundParameterType == _bindtype._sql_type) && (_boundSize == cchSize) && (_boundScale == scale) && (_boundBuffer == valueBuffer.Handle) && (_boundIntbuffer == intBuffer.Handle) ) { return; } //SQLBindParameter retcode = hstmt.BindParameter( ordinal, // Parameter Number (short)sqldirection, // InputOutputType sql_c_type, // ValueType _bindtype._sql_type, // ParameterType (IntPtr)cchSize, // ColumnSize (IntPtr)scale, // DecimalDigits valueBuffer, // ParameterValuePtr (IntPtr)_preparedBufferSize, intBuffer); // StrLen_or_IndPtr if (ODBC32.RetCode.SUCCESS != retcode) { if ("07006" == command.GetDiagSqlState()) { Bid.Trace("<odbc.OdbcParameter.Bind|ERR> Call to BindParameter returned errorcode [07006]\n"); command.Connection.FlagRestrictedSqlBindType(_bindtype._sql_type); if (allowReentrance) { this.Bind(hstmt, command, ordinal, parameterBuffer, false); return; } } command.Connection.HandleError(hstmt, retcode); } _hasChanged = false; _boundSqlCType = sql_c_type; _boundParameterType = _bindtype._sql_type; _boundSize = cchSize; _boundScale = scale; _boundBuffer = valueBuffer.Handle; _boundIntbuffer = intBuffer.Handle; if (ODBC32.SQL_C.NUMERIC == sql_c_type) { OdbcDescriptorHandle hdesc = command.GetDescriptorHandle(ODBC32.SQL_ATTR.APP_PARAM_DESC); // descriptor handle is cached on command wrapper, don't release it // Set descriptor Type // //SQLSetDescField(hdesc, i+1, SQL_DESC_TYPE, (void *)SQL_C_NUMERIC, 0); retcode = hdesc.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.TYPE, (IntPtr)ODBC32.SQL_C.NUMERIC); if (ODBC32.RetCode.SUCCESS != retcode) { command.Connection.HandleError(hstmt, retcode); } // Set precision // cbActual= (int)precision; //SQLSetDescField(hdesc, i+1, SQL_DESC_PRECISION, (void *)precision, 0); retcode = hdesc.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.PRECISION, (IntPtr)cbActual); if (ODBC32.RetCode.SUCCESS != retcode) { command.Connection.HandleError(hstmt, retcode); } // Set scale // // SQLSetDescField(hdesc, i+1, SQL_DESC_SCALE, (void *)llen, 0); cbActual= (int)scale; retcode = hdesc.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.SCALE, (IntPtr)cbActual); if (ODBC32.RetCode.SUCCESS != retcode) { command.Connection.HandleError(hstmt, retcode); } // Set data pointer // // SQLSetDescField(hdesc, i+1, SQL_DESC_DATA_PTR, (void *)&numeric, 0); retcode = hdesc.SetDescriptionField2(ordinal, ODBC32.SQL_DESC.DATA_PTR, valueBuffer); if (ODBC32.RetCode.SUCCESS != retcode) { command.Connection.HandleError(hstmt, retcode); } } }
internal ODBC32.RetCode BindParameter(short ordinal, short parameterDirection, ODBC32.SQL_C sqlctype, ODBC32.SQL_TYPE sqltype, IntPtr cchSize, IntPtr scale, HandleRef buffer, IntPtr bufferLength, HandleRef intbuffer) { ODBC32.RetCode retcode = Interop.Odbc.SQLBindParameter(this, checked ((ushort)ordinal), // Parameter Number parameterDirection, // InputOutputType sqlctype, // ValueType checked ((short)sqltype), // ParameterType cchSize, // ColumnSize scale, // DecimalDigits buffer, // ParameterValuePtr bufferLength, // BufferLength intbuffer); // StrLen_or_IndPtr ODBC.TraceODBC(3, "SQLBindParameter", retcode); return(retcode); }
// if sizeorprecision applies only for wchar and numeric values // for wchar the a value of null means take the value's size // internal void MarshalToNative(int offset, object value, ODBC32.SQL_C sqlctype, int sizeorprecision, int valueOffset) { switch (sqlctype) { case ODBC32.SQL_C.WCHAR: { //Note: We always bind as unicode //Note: StructureToPtr fails indicating string it a non-blittable type //and there is no MarshalStringTo* that moves to an existing buffer, //they all alloc and return a new one, not at all what we want... //So we have to copy the raw bytes of the string ourself?! char[] rgChars; int length; Debug.Assert(value is string || value is char[], "Only string or char[] can be marshaled to WCHAR"); if (value is string) { length = Math.Max(0, ((string)value).Length - valueOffset); if ((sizeorprecision > 0) && (sizeorprecision < length)) { length = sizeorprecision; } rgChars = ((string)value).ToCharArray(valueOffset, length); Debug.Assert(rgChars.Length < (base.Length - valueOffset), "attempting to extend parameter buffer!"); WriteCharArray(offset, rgChars, 0, rgChars.Length); WriteInt16(offset + (rgChars.Length * 2), 0); // Add the null terminator } else { length = Math.Max(0, ((char[])value).Length - valueOffset); if ((sizeorprecision > 0) && (sizeorprecision < length)) { length = sizeorprecision; } rgChars = (char[])value; Debug.Assert(rgChars.Length < (base.Length - valueOffset), "attempting to extend parameter buffer!"); WriteCharArray(offset, rgChars, valueOffset, length); WriteInt16(offset + (rgChars.Length * 2), 0); // Add the null terminator } break; } case ODBC32.SQL_C.BINARY: case ODBC32.SQL_C.CHAR: { byte[] rgBytes = (byte[])value; int length = rgBytes.Length; Debug.Assert((valueOffset <= length), "Offset out of Range"); // reduce length by the valueOffset // length -= valueOffset; // reduce length to be no more than size (if size is given) // if ((sizeorprecision > 0) && (sizeorprecision < length)) { length = sizeorprecision; } //AdjustSize(rgBytes.Length+1); //buffer = DangerousAllocateAndGetHandle(); // Realloc may have changed buffer address Debug.Assert(length < (base.Length - valueOffset), "attempting to extend parameter buffer!"); WriteBytes(offset, rgBytes, valueOffset, length); break; } case ODBC32.SQL_C.UTINYINT: WriteByte(offset, (byte)value); break; case ODBC32.SQL_C.SSHORT: //Int16 WriteInt16(offset, (short)value); break; case ODBC32.SQL_C.SLONG: //Int32 WriteInt32(offset, (int)value); break; case ODBC32.SQL_C.REAL: //float WriteSingle(offset, (float)value); break; case ODBC32.SQL_C.SBIGINT: //Int64 WriteInt64(offset, (long)value); break; case ODBC32.SQL_C.DOUBLE: //Double WriteDouble(offset, (double)value); break; case ODBC32.SQL_C.GUID: //Guid WriteGuid(offset, (Guid)value); break; case ODBC32.SQL_C.BIT: WriteByte(offset, (byte)(((bool)value) ? 1 : 0)); break; case ODBC32.SQL_C.TYPE_TIMESTAMP: { //typedef struct tagTIMESTAMP_STRUCT //{ // SQLSMALLINT year; // SQLUSMALLINT month; // SQLUSMALLINT day; // SQLUSMALLINT hour; // SQLUSMALLINT minute; // SQLUSMALLINT second; // SQLUINTEGER fraction; (billoniths of a second) //} //We have to map this ourselves, due to the different structures between //ODBC TIMESTAMP and URT DateTime, (ie: can't use StructureToPtr) WriteODBCDateTime(offset, (DateTime)value); break; } // Note: System does not provide a date-only type case ODBC32.SQL_C.TYPE_DATE: { // typedef struct tagDATE_STRUCT // { // SQLSMALLINT year; // SQLUSMALLINT month; // SQLUSMALLINT day; // } DATE_STRUCT; WriteDate(offset, (DateTime)value); break; } // Note: System does not provide a date-only type case ODBC32.SQL_C.TYPE_TIME: { // typedef struct tagTIME_STRUCT // { // SQLUSMALLINT hour; // SQLUSMALLINT minute; // SQLUSMALLINT second; // } TIME_STRUCT; WriteTime(offset, (TimeSpan)value); break; } case ODBC32.SQL_C.NUMERIC: { WriteNumeric(offset, (decimal)value, checked ((byte)sizeorprecision)); break; } default: Debug.Fail("UnknownSQLCType"); break; } }
internal ODBC32.RetCode GetData(int index, ODBC32.SQL_C sqlctype, CNativeBuffer buffer, int cb, out IntPtr cbActual) { ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetData(this, (ushort)index, sqlctype, buffer, new IntPtr(cb), out cbActual); ODBC.TraceODBC(3, "SQLGetData", retcode); return(retcode); }
internal static extern ODBC32.RetCode SQLBindParameter(OdbcStatementHandle StatementHandle, ushort ParameterNumber, short ParamDirection, ODBC32.SQL_C SQLCType, short SQLType, IntPtr cbColDef, IntPtr ibScale, HandleRef rgbValue, IntPtr BufferLength, HandleRef StrLen_or_Ind);
internal ODBC32.RetCode BindColumn2(int columnNumber, ODBC32.SQL_C targetType, HandleRef buffer, IntPtr length, IntPtr srLen_or_Ind) { ODBC32.RetCode retcode = UnsafeNativeMethods.SQLBindCol(this, (ushort)columnNumber, targetType, buffer, length, srLen_or_Ind); ODBC.TraceODBC(3, "SQLBindCol", retcode); return(retcode); }
internal void PrepareForBind(OdbcCommand command, short ordinal, ref int parameterBufferSize) { this.CopyParameterInternal(); object bytes = this.ProcessAndGetParameterValue(); int offset = this._internalOffset; int length = this._internalSize; if (offset > 0) { if (bytes is string) { if (offset > ((string) bytes).Length) { throw ADP.OffsetOutOfRangeException(); } } else if (bytes is char[]) { if (offset > ((char[]) bytes).Length) { throw ADP.OffsetOutOfRangeException(); } } else if (bytes is byte[]) { if (offset > ((byte[]) bytes).Length) { throw ADP.OffsetOutOfRangeException(); } } else { offset = 0; } } switch (this._bindtype._sql_type) { case ODBC32.SQL_TYPE.WLONGVARCHAR: case ODBC32.SQL_TYPE.WVARCHAR: case ODBC32.SQL_TYPE.WCHAR: if (bytes is char) { bytes = bytes.ToString(); length = ((string) bytes).Length; offset = 0; } if (!command.Connection.TestTypeSupport(this._bindtype._sql_type)) { if (ODBC32.SQL_TYPE.WCHAR == this._bindtype._sql_type) { this._bindtype = TypeMap._Char; } else if (ODBC32.SQL_TYPE.WVARCHAR == this._bindtype._sql_type) { this._bindtype = TypeMap._VarChar; } else if (ODBC32.SQL_TYPE.WLONGVARCHAR == this._bindtype._sql_type) { this._bindtype = TypeMap._Text; } } break; case ODBC32.SQL_TYPE.BIGINT: if (!command.Connection.IsV3Driver) { this._bindtype = TypeMap._VarChar; if ((bytes != null) && !Convert.IsDBNull(bytes)) { bytes = ((long) bytes).ToString(CultureInfo.CurrentCulture); length = ((string) bytes).Length; offset = 0; } } break; case ODBC32.SQL_TYPE.NUMERIC: case ODBC32.SQL_TYPE.DECIMAL: if ((!command.Connection.IsV3Driver || !command.Connection.TestTypeSupport(ODBC32.SQL_TYPE.NUMERIC)) || command.Connection.TestRestrictedSqlBindType(this._bindtype._sql_type)) { this._bindtype = TypeMap._VarChar; if ((bytes != null) && !Convert.IsDBNull(bytes)) { bytes = ((decimal) bytes).ToString(CultureInfo.CurrentCulture); length = ((string) bytes).Length; offset = 0; } } break; } ODBC32.SQL_C cHAR = this._bindtype._sql_c; if (!command.Connection.IsV3Driver && (cHAR == ODBC32.SQL_C.WCHAR)) { cHAR = ODBC32.SQL_C.CHAR; if (((bytes != null) && !Convert.IsDBNull(bytes)) && (bytes is string)) { CultureInfo info = new CultureInfo(CultureInfo.CurrentCulture.LCID); bytes = Encoding.GetEncoding(info.TextInfo.ANSICodePage).GetBytes(bytes.ToString()); length = ((byte[]) bytes).Length; } } int num2 = this.GetParameterSize(bytes, offset, ordinal); switch (this._bindtype._sql_type) { case ODBC32.SQL_TYPE.WVARCHAR: if (num2 > 0xfa0) { this._bindtype = TypeMap._NText; } break; case ODBC32.SQL_TYPE.VARBINARY: if (num2 > 0x1f40) { this._bindtype = TypeMap._Image; } break; case ODBC32.SQL_TYPE.VARCHAR: if (num2 > 0x1f40) { this._bindtype = TypeMap._Text; } break; } this._prepared_Sql_C_Type = cHAR; this._preparedOffset = offset; this._preparedSize = length; this._preparedValue = bytes; this._preparedBufferSize = num2; this._preparedIntOffset = parameterBufferSize; this._preparedValueOffset = this._preparedIntOffset + IntPtr.Size; parameterBufferSize += num2 + IntPtr.Size; }
internal ODBC32.RetCode BindColumn3(int columnNumber, ODBC32.SQL_C targetType, IntPtr srLen_or_Ind) { ODBC32.RetCode retcode = UnsafeNativeMethods.SQLBindCol(this, (ushort)columnNumber, targetType, ADP.PtrZero, ADP.PtrZero, srLen_or_Ind); ODBC.TraceODBC(3, "SQLBindCol", retcode); return(retcode); }
internal ODBC32.RetCode BindParameter(short ordinal, short parameterDirection, ODBC32.SQL_C sqlctype, ODBC32.SQL_TYPE sqltype, IntPtr cchSize, IntPtr scale, HandleRef buffer, IntPtr bufferLength, HandleRef intbuffer) { ODBC32.RetCode retcode = UnsafeNativeMethods.SQLBindParameter(this, (ushort)ordinal, parameterDirection, sqlctype, (short)sqltype, cchSize, scale, buffer, bufferLength, intbuffer); ODBC.TraceODBC(3, "SQLBindParameter", retcode); return(retcode); }
internal void Bind(OdbcStatementHandle hstmt, OdbcCommand command, short ordinal, CNativeBuffer parameterBuffer, bool allowReentrance) { ODBC32.RetCode retcode; ODBC32.SQL_C sql_c_type = _prepared_Sql_C_Type; ODBC32.SQL_PARAM sqldirection = SqlDirectionFromParameterDirection(); int offset = _preparedOffset; int size = _preparedSize; object value = _preparedValue; int cbValueSize = GetValueSize(value, offset); // count of bytes for the data int cchSize = GetColumnSize(value, offset, ordinal); // count of bytes for the data, used to allocate the buffer length byte precision = GetParameterPrecision(value); byte scale = GetParameterScale(value); int cbActual; HandleRef valueBuffer = parameterBuffer.PtrOffset(_preparedValueOffset, _preparedBufferSize); HandleRef intBuffer = parameterBuffer.PtrOffset(_preparedIntOffset, IntPtr.Size); // for the numeric datatype we need to do some special case handling ... // if (ODBC32.SQL_C.NUMERIC == sql_c_type) { // for input/output parameters we need to adjust the scale of the input value since the convert function in // sqlsrv32 takes this scale for the output parameter (possible bug in sqlsrv32?) // if ((ODBC32.SQL_PARAM.INPUT_OUTPUT == sqldirection) && (value is decimal)) { if (scale < _internalScale) { while (scale < _internalScale) { value = ((decimal)value) * 10; scale++; } } } SetInputValue(value, sql_c_type, cbValueSize, precision, 0, parameterBuffer); // for output parameters we need to write precision and scale to the buffer since the convert function in // sqlsrv32 expects these values there (possible bug in sqlsrv32?) // if (ODBC32.SQL_PARAM.INPUT != sqldirection) { parameterBuffer.WriteInt16(_preparedValueOffset, (short)(((ushort)scale << 8) | (ushort)precision)); } } else { SetInputValue(value, sql_c_type, cbValueSize, size, offset, parameterBuffer); } // Try to reuse existing bindings if // the binding is valid (means we already went through binding all parameters) // the parametercollection is bound already // the bindtype ParameterType did not change (forced upgrade) if (!_hasChanged && (_boundSqlCType == sql_c_type) && (_boundParameterType == _bindtype._sql_type) && (_boundSize == cchSize) && (_boundScale == scale) && (_boundBuffer == valueBuffer.Handle) && (_boundIntbuffer == intBuffer.Handle) ) { return; } //SQLBindParameter retcode = hstmt.BindParameter( ordinal, // Parameter Number (short)sqldirection, // InputOutputType sql_c_type, // ValueType _bindtype._sql_type, // ParameterType (IntPtr)cchSize, // ColumnSize (IntPtr)scale, // DecimalDigits valueBuffer, // ParameterValuePtr (IntPtr)_preparedBufferSize, intBuffer); // StrLen_or_IndPtr if (ODBC32.RetCode.SUCCESS != retcode) { if ("07006" == command.GetDiagSqlState()) { command.Connection.FlagRestrictedSqlBindType(_bindtype._sql_type); if (allowReentrance) { this.Bind(hstmt, command, ordinal, parameterBuffer, false); return; } } command.Connection.HandleError(hstmt, retcode); } _hasChanged = false; _boundSqlCType = sql_c_type; _boundParameterType = _bindtype._sql_type; _boundSize = cchSize; _boundScale = scale; _boundBuffer = valueBuffer.Handle; _boundIntbuffer = intBuffer.Handle; if (ODBC32.SQL_C.NUMERIC == sql_c_type) { OdbcDescriptorHandle hdesc = command.GetDescriptorHandle(ODBC32.SQL_ATTR.APP_PARAM_DESC); // descriptor handle is cached on command wrapper, don't release it // Set descriptor Type // //SQLSetDescField(hdesc, i+1, SQL_DESC_TYPE, (void *)SQL_C_NUMERIC, 0); retcode = hdesc.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.TYPE, (IntPtr)ODBC32.SQL_C.NUMERIC); if (ODBC32.RetCode.SUCCESS != retcode) { command.Connection.HandleError(hstmt, retcode); } // Set precision // cbActual = (int)precision; //SQLSetDescField(hdesc, i+1, SQL_DESC_PRECISION, (void *)precision, 0); retcode = hdesc.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.PRECISION, (IntPtr)cbActual); if (ODBC32.RetCode.SUCCESS != retcode) { command.Connection.HandleError(hstmt, retcode); } // Set scale // // SQLSetDescField(hdesc, i+1, SQL_DESC_SCALE, (void *)llen, 0); cbActual = (int)scale; retcode = hdesc.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.SCALE, (IntPtr)cbActual); if (ODBC32.RetCode.SUCCESS != retcode) { command.Connection.HandleError(hstmt, retcode); } // Set data pointer // // SQLSetDescField(hdesc, i+1, SQL_DESC_DATA_PTR, (void *)&numeric, 0); retcode = hdesc.SetDescriptionField2(ordinal, ODBC32.SQL_DESC.DATA_PTR, valueBuffer); if (ODBC32.RetCode.SUCCESS != retcode) { command.Connection.HandleError(hstmt, retcode); } } }
internal void MarshalToNative(object value, ODBC32.SQL_C sqlctype, byte precision) { IntPtr buffer = this.Ptr; switch (sqlctype) { /* #if DEBUG * case ODBC32.SQL_C.CHAR: * Debug.Assert(false, "should have bound as SQL_C.WCHAR"); * goto default; #endif */ case ODBC32.SQL_C.WCHAR: { //Note: We always bind as unicode //Note: StructureToPtr fails indicating string it a non-blittable type //and there is no MarshalStringTo* that moves to an existing buffer, //they all alloc and return a new one, not at all what we want... //So we have to copy the raw bytes of the string ourself?! Char[] rgChars = ((string)value).ToCharArray(); EnsureAlloc((rgChars.Length + 1) * 2); buffer = this.Ptr; // Realloc may have changed buffer address Marshal.Copy(rgChars, 0, buffer, rgChars.Length); Marshal.WriteInt16(buffer, rgChars.Length * 2, 0); // Add the null terminator break; } case ODBC32.SQL_C.BINARY: case ODBC32.SQL_C.CHAR: { Byte[] rgBytes = (Byte[])value; EnsureAlloc(rgBytes.Length + 1); buffer = this.Ptr; // Realloc may have changed buffer address Marshal.Copy(rgBytes, 0, buffer, rgBytes.Length); break; } case ODBC32.SQL_C.UTINYINT: Debug.Assert((Length >= 1), "Native buffer too small "); Marshal.WriteByte(buffer, (Byte)value); break; case ODBC32.SQL_C.SSHORT: //Int16 Debug.Assert((Length >= 2), "Native buffer too small "); Marshal.WriteInt16(buffer, (Int16)value); break; case ODBC32.SQL_C.SLONG: //Int32 case ODBC32.SQL_C.REAL: //float Debug.Assert((Length >= 4), "Native buffer too small "); Marshal.StructureToPtr(value, buffer, false /*deleteold*/); break; case ODBC32.SQL_C.SBIGINT: //Int64 case ODBC32.SQL_C.DOUBLE: //Double Debug.Assert((Length >= 8), "Native buffer too small "); Marshal.StructureToPtr(value, buffer, false /*deleteold*/); break; case ODBC32.SQL_C.GUID: //Guid //All of these we can just delegate Debug.Assert(16 <= Length, "Native buffer too small "); Marshal.StructureToPtr(value, buffer, false /*deleteold*/); break; case ODBC32.SQL_C.BIT: Debug.Assert((Length >= 1), "Native buffer too small "); Marshal.WriteByte(buffer, (Byte)(((bool)value) ? 1 : 0)); break; case ODBC32.SQL_C.TYPE_TIMESTAMP: { //typedef struct tagTIMESTAMP_STRUCT //{ // SQLSMALLINT year; // SQLUSMALLINT month; // SQLUSMALLINT day; // SQLUSMALLINT hour; // SQLUSMALLINT minute; // SQLUSMALLINT second; // SQLUINTEGER fraction; (billoniths of a second) //} //We have to map this ourselves, due to the different structures between //ODBC TIMESTAMP and URT DateTime, (ie: can't use StructureToPtr) Debug.Assert(16 <= Length, "Native buffer too small "); DateTime datetime = (DateTime)value; Marshal.WriteInt16(buffer, 0, (short)datetime.Year); //year Marshal.WriteInt16(buffer, 2, (short)datetime.Month); //month Marshal.WriteInt16(buffer, 4, (short)datetime.Day); //day Marshal.WriteInt16(buffer, 6, (short)datetime.Hour); //hour Marshal.WriteInt16(buffer, 8, (short)datetime.Minute); //minute Marshal.WriteInt16(buffer, 10, (short)datetime.Second); //second Marshal.WriteInt32(buffer, 12, datetime.Millisecond * 1000000); //fraction break; } // Note: System does not provide a date-only type case ODBC32.SQL_C.TYPE_DATE: { // typedef struct tagDATE_STRUCT // { // SQLSMALLINT year; // SQLUSMALLINT month; // SQLUSMALLINT day; // } DATE_STRUCT; Debug.Assert(6 <= Length, "Native buffer too small "); DateTime datetime = (DateTime)value; Marshal.WriteInt16(buffer, 0, (short)datetime.Year); //year Marshal.WriteInt16(buffer, 2, (short)datetime.Month); //month Marshal.WriteInt16(buffer, 4, (short)datetime.Day); //day break; } // Note: System does not provide a date-only type case ODBC32.SQL_C.TYPE_TIME: { // typedef struct tagTIME_STRUCT // { // SQLUSMALLINT hour; // SQLUSMALLINT minute; // SQLUSMALLINT second; // } TIME_STRUCT; Debug.Assert(6 <= Length, "Native buffer too small "); TimeSpan timespan = (TimeSpan)value; Marshal.WriteInt16(buffer, 0, (short)timespan.Hours); //hours Marshal.WriteInt16(buffer, 2, (short)timespan.Minutes); //minutes Marshal.WriteInt16(buffer, 4, (short)timespan.Seconds); //seconds break; } case ODBC32.SQL_C.NUMERIC: { //Note: Unfortunatly the ODBC NUMERIC structure and the URT DECIMAL structure do not //align, so we can't so do the typical "PtrToStructure" call (below) like other types //We actually have to go through the pain of pulling our raw bytes and building the decimal // Marshal.PtrToStructure(buffer, typeof(decimal)); //So we are mapping this ourselves //typedef struct tagSQL_NUMERIC_STRUCT //{ // SQLCHAR precision; // SQLSCHAR scale; // SQLCHAR sign; // SQLCHAR val[SQL_MAX_NUMERIC_LEN]; //} SQL_NUMERIC_STRUCT; int[] parts = Decimal.GetBits((Decimal)value); byte[] bits = BitConverter.GetBytes(parts[3]); Debug.Assert(19 <= Length, "Native buffer too small "); Marshal.WriteByte(buffer, 0, (Byte)precision); //precision Marshal.WriteByte(buffer, 1, bits[2]); //Bits 16-23 scale Marshal.WriteByte(buffer, 2, (Byte)((0 == bits[3]) ? 1 : 0)); //Bit 31 - sign(isnegative) Marshal.WriteInt32(buffer, 3, parts[0]); //val(low) Marshal.WriteInt32(buffer, 7, parts[1]); //val(mid) Marshal.WriteInt32(buffer, 11, parts[2]); //val(hi) Marshal.WriteInt32(buffer, 15, 0); //val(xhi) break; } default: throw ODC.UnknownSQLCType(sqlctype); } ; }