internal ODBC32.RetCode ColumnAttribute(int columnNumber, short fieldIdentifier, CNativeBuffer characterAttribute, out short stringLength, out SQLLEN numericAttribute) { IntPtr ptr; ODBC32.RetCode retcode = UnsafeNativeMethods.SQLColAttributeW(this, (short) columnNumber, fieldIdentifier, characterAttribute, characterAttribute.ShortLength, out stringLength, out ptr); numericAttribute = new SQLLEN(ptr); ODBC.TraceODBC(3, "SQLColAttributeW", retcode); return retcode; }
internal void Dispose() { if (this._dataReaderBuf != null) { this._dataReaderBuf.Dispose(); this._dataReaderBuf = null; } this.DisposeStatementHandle(); CNativeBuffer buffer = this._nativeParameterBuffer; this._nativeParameterBuffer = null; if (buffer != null) { buffer.Dispose(); } this._ssKeyInfoModeOn = false; this._ssKeyInfoModeOff = false; }
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 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); } } }
private OdbcDataReader ExecuteReaderObject(CommandBehavior behavior, string method, bool needReader, object?[]?methodArguments, ODBC32.SQL_API odbcApiMethod) { // MDAC 68324 OdbcDataReader?localReader = null; try { DisposeDeadDataReader(); // this is a no-op if cmdState is not Fetching ValidateConnectionAndTransaction(method); // cmdState will change to Executing if (0 != (CommandBehavior.SingleRow & behavior)) { // CommandBehavior.SingleRow implies CommandBehavior.SingleResult behavior |= CommandBehavior.SingleResult; } ODBC32.RetCode retcode; OdbcStatementHandle stmt = GetStatementHandle().StatementHandle !; _cmdWrapper !.Canceling = false; if (null != _weakDataReaderReference) { if (_weakDataReaderReference.IsAlive) { object?target = _weakDataReaderReference.Target; if (null != target && _weakDataReaderReference.IsAlive) { if (!((OdbcDataReader)target).IsClosed) { throw ADP.OpenReaderExists(); // MDAC 66411 } } } } localReader = new OdbcDataReader(this, _cmdWrapper, behavior); //Set command properties //Not all drivers support timeout. So fail silently if error if (!Connection !.ProviderInfo.NoQueryTimeout) { TrySetStatementAttribute(stmt, ODBC32.SQL_ATTR.QUERY_TIMEOUT, (IntPtr)this.CommandTimeout); } // todo: If we remember the state we can omit a lot of SQLSetStmtAttrW calls ... // if we do not create a reader we do not even need to do that if (needReader) { if (Connection.IsV3Driver) { if (!Connection.ProviderInfo.NoSqlSoptSSNoBrowseTable && !Connection.ProviderInfo.NoSqlSoptSSHiddenColumns) { // Need to get the metadata information //SQLServer actually requires browse info turned on ahead of time... //Note: We ignore any failures, since this is SQLServer specific //We won't specialcase for SQL Server but at least for non-V3 drivers if (localReader.IsBehavior(CommandBehavior.KeyInfo)) { if (!_cmdWrapper._ssKeyInfoModeOn) { TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.NOBROWSETABLE, (IntPtr)ODBC32.SQL_NB.ON); TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.HIDDEN_COLUMNS, (IntPtr)ODBC32.SQL_HC.ON); _cmdWrapper._ssKeyInfoModeOff = false; _cmdWrapper._ssKeyInfoModeOn = true; } } else { if (!_cmdWrapper._ssKeyInfoModeOff) { TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.NOBROWSETABLE, (IntPtr)ODBC32.SQL_NB.OFF); TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.HIDDEN_COLUMNS, (IntPtr)ODBC32.SQL_HC.OFF); _cmdWrapper._ssKeyInfoModeOff = true; _cmdWrapper._ssKeyInfoModeOn = false; } } } } } if (localReader.IsBehavior(CommandBehavior.KeyInfo) || localReader.IsBehavior(CommandBehavior.SchemaOnly)) { retcode = stmt.Prepare(CommandText); if (ODBC32.RetCode.SUCCESS != retcode) { _connection !.HandleError(stmt, retcode); } } bool mustRelease = false; CNativeBuffer?parameterBuffer = _cmdWrapper._nativeParameterBuffer; try { //Handle Parameters //Note: We use the internal variable as to not instante a new object collection, //for the common case of using no parameters. if ((null != _parameterCollection) && (0 < _parameterCollection.Count)) { int parameterBufferSize = _parameterCollection.CalcParameterBufferSize(this); if (null == parameterBuffer || parameterBuffer.Length < parameterBufferSize) { if (null != parameterBuffer) { parameterBuffer.Dispose(); } parameterBuffer = new CNativeBuffer(parameterBufferSize); _cmdWrapper._nativeParameterBuffer = parameterBuffer; } else { parameterBuffer.ZeroMemory(); } parameterBuffer.DangerousAddRef(ref mustRelease); _parameterCollection.Bind(this, _cmdWrapper, parameterBuffer); } if (!localReader.IsBehavior(CommandBehavior.SchemaOnly)) { // Can't get the KeyInfo after command execution (SQL Server only since it does not support multiple // results on the same connection). Stored procedures (SP) do not return metadata before actual execution // Need to check the column count since the command type may not be set to SP for a SP. if ((localReader.IsBehavior(CommandBehavior.KeyInfo) || localReader.IsBehavior(CommandBehavior.SchemaOnly)) && (CommandType != CommandType.StoredProcedure)) { short cColsAffected; retcode = stmt.NumberOfResultColumns(out cColsAffected); if (retcode == ODBC32.RetCode.SUCCESS || retcode == ODBC32.RetCode.SUCCESS_WITH_INFO) { if (cColsAffected > 0) { localReader.GetSchemaTable(); } } else if (retcode == ODBC32.RetCode.NO_DATA) { // do nothing } else { // any other returncode indicates an error _connection !.HandleError(stmt, retcode); } } switch (odbcApiMethod) { case ODBC32.SQL_API.SQLEXECDIRECT: if (localReader.IsBehavior(CommandBehavior.KeyInfo) || _isPrepared) { //Already prepared, so use SQLExecute retcode = stmt.Execute(); // Build metadata here // localReader.GetSchemaTable(); } else { #if DEBUG //if (AdapterSwitches.OleDbTrace.TraceInfo) { // ADP.DebugWriteLine("SQLExecDirectW: " + CommandText); //} #endif //SQLExecDirect retcode = stmt.ExecuteDirect(CommandText); } break; case ODBC32.SQL_API.SQLTABLES: retcode = stmt.Tables((string)methodArguments ![0] !, //TableCatalog (string)methodArguments[1] !, //TableSchema, (string)methodArguments[2] !, //TableName (string)methodArguments[3] !); //TableType break;
internal ODBC32.RetCode ColumnAttribute(int columnNumber, short fieldIdentifier, CNativeBuffer characterAttribute, out short stringLength, out SQLLEN numericAttribute) { IntPtr result; ODBC32.RetCode retcode = Interop.Odbc.SQLColAttributeW(this, checked ((short)columnNumber), fieldIdentifier, characterAttribute, characterAttribute.ShortLength, out stringLength, out result); numericAttribute = new SQLLEN(result); ODBC.TraceODBC(3, "SQLColAttributeW", retcode); return(retcode); }
internal ODBC32.RetCode GetData(int index, ODBC32.SQL_C sqlctype, CNativeBuffer buffer, int cb, out IntPtr cbActual) { ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetData(this, checked((ushort)index), sqlctype, buffer, new IntPtr(cb), out cbActual); ODBC.TraceODBC(3, "SQLGetData", retcode); return retcode; }
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 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 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 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); } } } }
private OdbcDataReader ExecuteReaderObject(CommandBehavior behavior, string method, bool needReader, object[] methodArguments, ODBC32.SQL_API odbcApiMethod) { OdbcDataReader target = null; try { ODBC32.RetCode typeInfo; this.DisposeDeadDataReader(); this.ValidateConnectionAndTransaction(method); if ((CommandBehavior.SingleRow & behavior) != CommandBehavior.Default) { behavior |= CommandBehavior.SingleResult; } OdbcStatementHandle statementHandle = this.GetStatementHandle().StatementHandle; this._cmdWrapper.Canceling = false; if ((this.weakDataReaderReference != null) && this.weakDataReaderReference.IsAlive) { object obj2 = this.weakDataReaderReference.Target; if (((obj2 != null) && this.weakDataReaderReference.IsAlive) && !((OdbcDataReader) obj2).IsClosed) { throw ADP.OpenReaderExists(); } } target = new OdbcDataReader(this, this._cmdWrapper, behavior); if (!this.Connection.ProviderInfo.NoQueryTimeout) { this.TrySetStatementAttribute(statementHandle, ODBC32.SQL_ATTR.QUERY_TIMEOUT, (IntPtr) this.CommandTimeout); } if ((needReader && this.Connection.IsV3Driver) && (!this.Connection.ProviderInfo.NoSqlSoptSSNoBrowseTable && !this.Connection.ProviderInfo.NoSqlSoptSSHiddenColumns)) { if (target.IsBehavior(CommandBehavior.KeyInfo)) { if (!this._cmdWrapper._ssKeyInfoModeOn) { this.TrySetStatementAttribute(statementHandle, (ODBC32.SQL_ATTR) 0x4cc, (IntPtr) 1L); this.TrySetStatementAttribute(statementHandle, ODBC32.SQL_ATTR.SQL_COPT_SS_TXN_ISOLATION, (IntPtr) 1L); this._cmdWrapper._ssKeyInfoModeOff = false; this._cmdWrapper._ssKeyInfoModeOn = true; } } else if (!this._cmdWrapper._ssKeyInfoModeOff) { this.TrySetStatementAttribute(statementHandle, (ODBC32.SQL_ATTR) 0x4cc, (IntPtr) 0L); this.TrySetStatementAttribute(statementHandle, ODBC32.SQL_ATTR.SQL_COPT_SS_TXN_ISOLATION, (IntPtr) 0L); this._cmdWrapper._ssKeyInfoModeOff = true; this._cmdWrapper._ssKeyInfoModeOn = false; } } if (target.IsBehavior(CommandBehavior.KeyInfo) || target.IsBehavior(CommandBehavior.SchemaOnly)) { typeInfo = statementHandle.Prepare(this.CommandText); if (typeInfo != ODBC32.RetCode.SUCCESS) { this._connection.HandleError(statementHandle, typeInfo); } } bool success = false; CNativeBuffer parameterBuffer = this._cmdWrapper._nativeParameterBuffer; RuntimeHelpers.PrepareConstrainedRegions(); try { if ((this._parameterCollection != null) && (0 < this._parameterCollection.Count)) { int initialSize = this._parameterCollection.CalcParameterBufferSize(this); if ((parameterBuffer == null) || (parameterBuffer.Length < initialSize)) { if (parameterBuffer != null) { parameterBuffer.Dispose(); } parameterBuffer = new CNativeBuffer(initialSize); this._cmdWrapper._nativeParameterBuffer = parameterBuffer; } else { parameterBuffer.ZeroMemory(); } parameterBuffer.DangerousAddRef(ref success); this._parameterCollection.Bind(this, this._cmdWrapper, parameterBuffer); } if (target.IsBehavior(CommandBehavior.SchemaOnly)) { goto Label_0443; } if ((target.IsBehavior(CommandBehavior.KeyInfo) || target.IsBehavior(CommandBehavior.SchemaOnly)) && (this.CommandType != System.Data.CommandType.StoredProcedure)) { short num2; typeInfo = statementHandle.NumberOfResultColumns(out num2); switch (typeInfo) { case ODBC32.RetCode.SUCCESS: case ODBC32.RetCode.SUCCESS_WITH_INFO: if (num2 > 0) { target.GetSchemaTable(); } goto Label_029A; } if (typeInfo != ODBC32.RetCode.NO_DATA) { this._connection.HandleError(statementHandle, typeInfo); } } Label_029A: switch (odbcApiMethod) { case ODBC32.SQL_API.SQLEXECDIRECT: if (target.IsBehavior(CommandBehavior.KeyInfo) || this._isPrepared) { typeInfo = statementHandle.Execute(); } else { typeInfo = statementHandle.ExecuteDirect(this.CommandText); } break; case ODBC32.SQL_API.SQLCOLUMNS: typeInfo = statementHandle.Columns((string) methodArguments[0], (string) methodArguments[1], (string) methodArguments[2], (string) methodArguments[3]); break; case ODBC32.SQL_API.SQLSTATISTICS: typeInfo = statementHandle.Statistics((string) methodArguments[0], (string) methodArguments[1], (string) methodArguments[2], (short) methodArguments[3], (short) methodArguments[4]); break; case ODBC32.SQL_API.SQLTABLES: typeInfo = statementHandle.Tables((string) methodArguments[0], (string) methodArguments[1], (string) methodArguments[2], (string) methodArguments[3]); break; case ODBC32.SQL_API.SQLGETTYPEINFO: typeInfo = statementHandle.GetTypeInfo((short) methodArguments[0]); break; case ODBC32.SQL_API.SQLPROCEDURECOLUMNS: typeInfo = statementHandle.ProcedureColumns((string) methodArguments[0], (string) methodArguments[1], (string) methodArguments[2], (string) methodArguments[3]); break; case ODBC32.SQL_API.SQLPROCEDURES: typeInfo = statementHandle.Procedures((string) methodArguments[0], (string) methodArguments[1], (string) methodArguments[2]); break; default: throw ADP.InvalidOperation(method.ToString()); } if ((typeInfo != ODBC32.RetCode.SUCCESS) && (ODBC32.RetCode.NO_DATA != typeInfo)) { this._connection.HandleError(statementHandle, typeInfo); } } finally { if (success) { parameterBuffer.DangerousRelease(); } } Label_0443: this.weakDataReaderReference = new WeakReference(target); if (!target.IsBehavior(CommandBehavior.SchemaOnly)) { target.FirstResult(); } this.cmdState = ConnectionState.Fetching; } finally { if (ConnectionState.Fetching != this.cmdState) { if (target != null) { if (this._parameterCollection != null) { this._parameterCollection.ClearBindings(); } target.Dispose(); } if (this.cmdState != ConnectionState.Closed) { this.cmdState = ConnectionState.Closed; } } } return target; }
internal static extern ODBC32.RetCode SQLGetDescFieldW(OdbcDescriptorHandle StatementHandle, short RecNumber, ODBC32.SQL_DESC FieldIdentifier, CNativeBuffer ValuePointer, int BufferLength, out int StringLength);
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 SQLColAttributeW(OdbcStatementHandle StatementHandle, short ColumnNumber, short FieldIdentifier, CNativeBuffer CharacterAttribute, short BufferLength, out short StringLength, out IntPtr NumericAttribute);
internal void Bind(HandleRef hstmt, OdbcCommand parent, short ordinal, CNativeBuffer buffer, CNativeBuffer intbuffer) { ODBC32.RETCODE retcode; int cbActual; ODBC32.SQL_C sql_c_type; object value = GetParameterValue(); switch (Direction) { case ParameterDirection.Input: Marshal.WriteInt32(intbuffer.Ptr, 0); break; case ParameterDirection.Output: case ParameterDirection.ReturnValue: Marshal.WriteInt32(intbuffer.Ptr, ODBC32.SQL_NULL_DATA); break; case ParameterDirection.InputOutput: Marshal.WriteInt32(intbuffer.Ptr, 0); break; default: throw ADP.InvalidParameterDirection((int)value, ParameterName); } // before we can do anything we need to verify if there is support // for certain data types // switch (_bindtype._sql_type) { case ODBC32.SQL_TYPE.DECIMAL: case ODBC32.SQL_TYPE.NUMERIC: Debug.Assert((null == value) || Convert.IsDBNull(value) || (value is Decimal), "value not decimal"); if ((_parent.Connection.OdbcMajorVersion < 3) || !((OdbcParameterCollection)_parent).Connection.TestTypeSupport(ODBC32.SQL_TYPE.NUMERIC)) { // No support for NUMERIC // Change the type _bindtype = TypeMap._VarChar; if ((null != value) && !Convert.IsDBNull(value)) { value = ((Decimal)value).ToString(); } } break; case ODBC32.SQL_TYPE.BIGINT: Debug.Assert((null == value) || Convert.IsDBNull(value) || (value is Int64), "value not Int64"); if (_parent.Connection.OdbcMajorVersion < 3) { // No support for BIGINT // Change the type _bindtype = TypeMap._VarChar; if ((null != value) && !Convert.IsDBNull(value)) { value = ((Int64)value).ToString(); } } break; case ODBC32.SQL_TYPE.WCHAR: // MDAC 68993 case ODBC32.SQL_TYPE.WVARCHAR: case ODBC32.SQL_TYPE.WLONGVARCHAR: Debug.Assert((null == value) || Convert.IsDBNull(value) || (value is String), "value not string"); if (!((OdbcParameterCollection)_parent).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 // WARNING: this is very UGLY code but an internal compilererror forces me to do so // (MDAC BUG 72163) // // 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 = (_parent.Connection.OdbcMajorVersion >= 3) ? _bindtype._sql_c : _bindtype._param_sql_c; if ((_parent.Connection.OdbcMajorVersion < 3) && (_bindtype._param_sql_c == ODBC32.SQL_C.CHAR)) { if ((value is String) && (null != value) && !Convert.IsDBNull(value)) { 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()); } } int cbParameterSize = GetParameterSize(value); // count of bytes for the data, for SQLBindParameter int cbValueSize = GetValueSize(value); // count of bytes for the data int cchSize = GetColumnSize(value); // count of bytes for the data, used to allocate the buffer length // 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; } // end switch //Allocate a our buffer to hold the input/output data //Note: cbValueSize is used in the SetInputValue to indicate how many bytes of variable //length data (which doesn't include the null terminator as spec'd), however our raw //buffer needs extra room for this buffer.EnsureAlloc(cbParameterSize); byte precision = GetParameterPrecision(value); byte scale = GetParameterScale(value); // 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 < this.scale) { while (scale < this.scale) { value = ((decimal)value) * 10; scale++; } } } SetInputValue(cbValueSize, value, precision, buffer, intbuffer); // 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) { Marshal.WriteByte(buffer.Ptr, 0, (byte)precision); Marshal.WriteByte(buffer.Ptr, 1, (byte)scale); } } else { SetInputValue(cbValueSize, value, precision, buffer, intbuffer); } // Try to reuse existing bindings // if (_parent.BindingIsValid && _parent.CollectionIsBound) { return; } //SQLBindParameter retcode = (ODBC32.RETCODE) UnsafeNativeMethods.Odbc32.SQLBindParameter( hstmt, // StatementHandle ordinal, // Parameter Number (short)this._sqldirection, // InputOutputType (short)sql_c_type, // ValueType (short)_bindtype._sql_type, // ParameterType (IntPtr)cchSize, // ColumnSize (IntPtr)scale, // DecimalDigits buffer, // ParameterValuePtr (IntPtr)buffer.Length, // BufferLength intbuffer.Ptr); // StrLen_or_IndPtr if (ODBC32.RETCODE.SUCCESS != retcode) { ((OdbcParameterCollection)_parent).Connection.HandleError(hstmt, ODBC32.SQL_HANDLE.STMT, retcode); } if (ODBC32.SQL_C.NUMERIC == sql_c_type) { HandleRef hdesc = parent.GetDescriptorHandle(); // Set descriptor Type // //SQLSetDescField(hdesc, i+1, SQL_DESC_TYPE, (void *)SQL_C_NUMERIC, 0); retcode = (ODBC32.RETCODE) UnsafeNativeMethods.Odbc32.SQLSetDescFieldW( hdesc, ordinal, (short)ODBC32.SQL_DESC.TYPE, new HandleRef(null, (IntPtr)ODBC32.SQL_C.NUMERIC), 0); if (ODBC32.RETCODE.SUCCESS != retcode) { ((OdbcParameterCollection)_parent).Connection.HandleError(hstmt, ODBC32.SQL_HANDLE.STMT, retcode); } // Set precision // cbActual = (int)precision; //SQLSetDescField(hdesc, i+1, SQL_DESC_PRECISION, (void *)precision, 0); retcode = (ODBC32.RETCODE) UnsafeNativeMethods.Odbc32.SQLSetDescFieldW( hdesc, ordinal, (short)ODBC32.SQL_DESC.PRECISION, new HandleRef(this, (IntPtr)cbActual), 0); if (ODBC32.RETCODE.SUCCESS != retcode) { ((OdbcParameterCollection)_parent).Connection.HandleError(hstmt, ODBC32.SQL_HANDLE.STMT, retcode); } // Set scale // // SQLSetDescField(hdesc, i+1, SQL_DESC_SCALE, (void *)llen, 0); cbActual = (int)scale; retcode = (ODBC32.RETCODE) UnsafeNativeMethods.Odbc32.SQLSetDescFieldW( hdesc, ordinal, (short)ODBC32.SQL_DESC.SCALE, new HandleRef(this, (IntPtr)cbActual), 0); if (ODBC32.RETCODE.SUCCESS != retcode) { ((OdbcParameterCollection)_parent).Connection.HandleError(hstmt, ODBC32.SQL_HANDLE.STMT, retcode); } // Set data pointer // // SQLSetDescField(hdesc, i+1, SQL_DESC_DATA_PTR, (void *)&numeric, 0); retcode = (ODBC32.RETCODE) UnsafeNativeMethods.Odbc32.SQLSetDescFieldW( hdesc, ordinal, (short)ODBC32.SQL_DESC.DATA_PTR, buffer, 0); if (ODBC32.RETCODE.SUCCESS != retcode) { ((OdbcParameterCollection)_parent).Connection.HandleError(hstmt, ODBC32.SQL_HANDLE.STMT, retcode); } // Don't free handle descriptors. They are not allocated. // retcode = (ODBC32.RETCODE) UnsafeNativeMethods.Odbc32.SQLFreeHandle( (short)ODBC32.SQL_HANDLE.DESC, hdesc); } }
static internal extern /*SQLRETURN*/ODBC32.RetCode SQLColAttributeW ( /*SQLHSTMT*/OdbcStatementHandle StatementHandle, /*SQLUSMALLINT*/Int16 ColumnNumber, /*SQLUSMALLINT*/Int16 FieldIdentifier, /*SQLPOINTER*/CNativeBuffer CharacterAttribute, /*SQLSMALLINT*/Int16 BufferLength, /*SQLSMALLINT* */out Int16 StringLength, /*SQLPOINTER*/out IntPtr NumericAttribute);
private OdbcDataReader ExecuteReaderObject(CommandBehavior behavior, string method, bool needReader, object[] methodArguments, ODBC32.SQL_API odbcApiMethod) { OdbcDataReader target = null; try { ODBC32.RetCode typeInfo; this.DisposeDeadDataReader(); this.ValidateConnectionAndTransaction(method); if ((CommandBehavior.SingleRow & behavior) != CommandBehavior.Default) { behavior |= CommandBehavior.SingleResult; } OdbcStatementHandle statementHandle = this.GetStatementHandle().StatementHandle; this._cmdWrapper.Canceling = false; if ((this.weakDataReaderReference != null) && this.weakDataReaderReference.IsAlive) { object obj2 = this.weakDataReaderReference.Target; if (((obj2 != null) && this.weakDataReaderReference.IsAlive) && !((OdbcDataReader)obj2).IsClosed) { throw ADP.OpenReaderExists(); } } target = new OdbcDataReader(this, this._cmdWrapper, behavior); if (!this.Connection.ProviderInfo.NoQueryTimeout) { this.TrySetStatementAttribute(statementHandle, ODBC32.SQL_ATTR.QUERY_TIMEOUT, (IntPtr)this.CommandTimeout); } if ((needReader && this.Connection.IsV3Driver) && (!this.Connection.ProviderInfo.NoSqlSoptSSNoBrowseTable && !this.Connection.ProviderInfo.NoSqlSoptSSHiddenColumns)) { if (target.IsBehavior(CommandBehavior.KeyInfo)) { if (!this._cmdWrapper._ssKeyInfoModeOn) { this.TrySetStatementAttribute(statementHandle, (ODBC32.SQL_ATTR) 0x4cc, (IntPtr)1L); this.TrySetStatementAttribute(statementHandle, ODBC32.SQL_ATTR.SQL_COPT_SS_TXN_ISOLATION, (IntPtr)1L); this._cmdWrapper._ssKeyInfoModeOff = false; this._cmdWrapper._ssKeyInfoModeOn = true; } } else if (!this._cmdWrapper._ssKeyInfoModeOff) { this.TrySetStatementAttribute(statementHandle, (ODBC32.SQL_ATTR) 0x4cc, (IntPtr)0L); this.TrySetStatementAttribute(statementHandle, ODBC32.SQL_ATTR.SQL_COPT_SS_TXN_ISOLATION, (IntPtr)0L); this._cmdWrapper._ssKeyInfoModeOff = true; this._cmdWrapper._ssKeyInfoModeOn = false; } } if (target.IsBehavior(CommandBehavior.KeyInfo) || target.IsBehavior(CommandBehavior.SchemaOnly)) { typeInfo = statementHandle.Prepare(this.CommandText); if (typeInfo != ODBC32.RetCode.SUCCESS) { this._connection.HandleError(statementHandle, typeInfo); } } bool success = false; CNativeBuffer parameterBuffer = this._cmdWrapper._nativeParameterBuffer; RuntimeHelpers.PrepareConstrainedRegions(); try { if ((this._parameterCollection != null) && (0 < this._parameterCollection.Count)) { int initialSize = this._parameterCollection.CalcParameterBufferSize(this); if ((parameterBuffer == null) || (parameterBuffer.Length < initialSize)) { if (parameterBuffer != null) { parameterBuffer.Dispose(); } parameterBuffer = new CNativeBuffer(initialSize); this._cmdWrapper._nativeParameterBuffer = parameterBuffer; } else { parameterBuffer.ZeroMemory(); } parameterBuffer.DangerousAddRef(ref success); this._parameterCollection.Bind(this, this._cmdWrapper, parameterBuffer); } if (target.IsBehavior(CommandBehavior.SchemaOnly)) { goto Label_0443; } if ((target.IsBehavior(CommandBehavior.KeyInfo) || target.IsBehavior(CommandBehavior.SchemaOnly)) && (this.CommandType != System.Data.CommandType.StoredProcedure)) { short num2; typeInfo = statementHandle.NumberOfResultColumns(out num2); switch (typeInfo) { case ODBC32.RetCode.SUCCESS: case ODBC32.RetCode.SUCCESS_WITH_INFO: if (num2 > 0) { target.GetSchemaTable(); } goto Label_029A; } if (typeInfo != ODBC32.RetCode.NO_DATA) { this._connection.HandleError(statementHandle, typeInfo); } } Label_029A: switch (odbcApiMethod) { case ODBC32.SQL_API.SQLEXECDIRECT: if (target.IsBehavior(CommandBehavior.KeyInfo) || this._isPrepared) { typeInfo = statementHandle.Execute(); } else { typeInfo = statementHandle.ExecuteDirect(this.CommandText); } break; case ODBC32.SQL_API.SQLCOLUMNS: typeInfo = statementHandle.Columns((string)methodArguments[0], (string)methodArguments[1], (string)methodArguments[2], (string)methodArguments[3]); break; case ODBC32.SQL_API.SQLSTATISTICS: typeInfo = statementHandle.Statistics((string)methodArguments[0], (string)methodArguments[1], (string)methodArguments[2], (short)methodArguments[3], (short)methodArguments[4]); break; case ODBC32.SQL_API.SQLTABLES: typeInfo = statementHandle.Tables((string)methodArguments[0], (string)methodArguments[1], (string)methodArguments[2], (string)methodArguments[3]); break; case ODBC32.SQL_API.SQLGETTYPEINFO: typeInfo = statementHandle.GetTypeInfo((short)methodArguments[0]); break; case ODBC32.SQL_API.SQLPROCEDURECOLUMNS: typeInfo = statementHandle.ProcedureColumns((string)methodArguments[0], (string)methodArguments[1], (string)methodArguments[2], (string)methodArguments[3]); break; case ODBC32.SQL_API.SQLPROCEDURES: typeInfo = statementHandle.Procedures((string)methodArguments[0], (string)methodArguments[1], (string)methodArguments[2]); break; default: throw ADP.InvalidOperation(method.ToString()); } if ((typeInfo != ODBC32.RetCode.SUCCESS) && (ODBC32.RetCode.NO_DATA != typeInfo)) { this._connection.HandleError(statementHandle, typeInfo); } } finally { if (success) { parameterBuffer.DangerousRelease(); } } Label_0443: this.weakDataReaderReference = new WeakReference(target); if (!target.IsBehavior(CommandBehavior.SchemaOnly)) { target.FirstResult(); } this.cmdState = ConnectionState.Fetching; } finally { if (ConnectionState.Fetching != this.cmdState) { if (target != null) { if (this._parameterCollection != null) { this._parameterCollection.ClearBindings(); } target.Dispose(); } if (this.cmdState != ConnectionState.Closed) { this.cmdState = ConnectionState.Closed; } } } return(target); }
internal void GetOutputValue(CNativeBuffer parameterBuffer) { if (!this._hasChanged && ((this._bindtype != null) && (this._internalDirection != ParameterDirection.Input))) { TypeMap map = this._bindtype; this._bindtype = null; int cb = (int) parameterBuffer.ReadIntPtr(this._preparedIntOffset); if (-1 == cb) { this.Value = DBNull.Value; } else if ((0 <= cb) || (cb == -3)) { this.Value = parameterBuffer.MarshalToManaged(this._preparedValueOffset, this._boundSqlCType, cb); if (((this._boundSqlCType == ODBC32.SQL_C.CHAR) && (this.Value != null)) && !Convert.IsDBNull(this.Value)) { CultureInfo info = new CultureInfo(CultureInfo.CurrentCulture.LCID); this.Value = Encoding.GetEncoding(info.TextInfo.ANSICodePage).GetString((byte[]) this.Value); } if (((map != this._typemap) && (this.Value != null)) && (!Convert.IsDBNull(this.Value) && (this.Value.GetType() != this._typemap._type))) { this.Value = decimal.Parse((string) this.Value, CultureInfo.CurrentCulture); } } } }
private OdbcDataReader ExecuteReaderObject(CommandBehavior behavior, string method, bool needReader, object[] methodArguments, ODBC32.SQL_API odbcApiMethod) { // MDAC 68324 OdbcDataReader localReader = null; try { DisposeDeadDataReader(); // this is a no-op if cmdState is not Fetching ValidateConnectionAndTransaction(method); // cmdState will change to Executing if(0 != (CommandBehavior.SingleRow & behavior)) { // CommandBehavior.SingleRow implies CommandBehavior.SingleResult behavior |= CommandBehavior.SingleResult; } ODBC32.RetCode retcode; OdbcStatementHandle stmt = GetStatementHandle().StatementHandle; _cmdWrapper.Canceling = false; if(null != weakDataReaderReference) { if(weakDataReaderReference.IsAlive) { object target = weakDataReaderReference.Target; if(null != target && weakDataReaderReference.IsAlive) { if(!((OdbcDataReader)target).IsClosed) { throw ADP.OpenReaderExists(); // MDAC 66411 } } } } localReader = new OdbcDataReader(this, _cmdWrapper, behavior); //Set command properties //Not all drivers support timeout. So fail silently if error if(!Connection.ProviderInfo.NoQueryTimeout) { TrySetStatementAttribute(stmt, ODBC32.SQL_ATTR.QUERY_TIMEOUT, (IntPtr)this.CommandTimeout); } // todo: If we remember the state we can omit a lot of SQLSetStmtAttrW calls ... // if we do not create a reader we do not even need to do that if(needReader) { if(Connection.IsV3Driver) { if(!Connection.ProviderInfo.NoSqlSoptSSNoBrowseTable && !Connection.ProviderInfo.NoSqlSoptSSHiddenColumns) { // Need to get the metadata information //SQLServer actually requires browse info turned on ahead of time... //Note: We ignore any failures, since this is SQLServer specific //We won't specialcase for SQL Server but at least for non-V3 drivers if(localReader.IsBehavior(CommandBehavior.KeyInfo)) { if(!_cmdWrapper._ssKeyInfoModeOn) { TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.NOBROWSETABLE, (IntPtr)ODBC32.SQL_NB.ON); TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.HIDDEN_COLUMNS, (IntPtr)ODBC32.SQL_HC.ON); _cmdWrapper._ssKeyInfoModeOff = false; _cmdWrapper._ssKeyInfoModeOn = true; } } else { if(!_cmdWrapper._ssKeyInfoModeOff) { TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.NOBROWSETABLE, (IntPtr)ODBC32.SQL_NB.OFF); TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.HIDDEN_COLUMNS, (IntPtr)ODBC32.SQL_HC.OFF); _cmdWrapper._ssKeyInfoModeOff = true; _cmdWrapper._ssKeyInfoModeOn = false; } } } } } if(localReader.IsBehavior(CommandBehavior.KeyInfo) || localReader.IsBehavior(CommandBehavior.SchemaOnly)) { retcode = stmt.Prepare(CommandText); if(ODBC32.RetCode.SUCCESS != retcode) { _connection.HandleError(stmt, retcode); } } bool mustRelease = false; CNativeBuffer parameterBuffer = _cmdWrapper._nativeParameterBuffer; RuntimeHelpers.PrepareConstrainedRegions(); try { //Handle Parameters //Note: We use the internal variable as to not instante a new object collection, //for the the common case of using no parameters. if((null != _parameterCollection) && (0 < _parameterCollection.Count)) { int parameterBufferSize = _parameterCollection.CalcParameterBufferSize(this); if(null == parameterBuffer || parameterBuffer.Length < parameterBufferSize) { if (null != parameterBuffer) { parameterBuffer.Dispose(); } parameterBuffer = new CNativeBuffer(parameterBufferSize); _cmdWrapper._nativeParameterBuffer = parameterBuffer; } else { parameterBuffer.ZeroMemory(); } parameterBuffer.DangerousAddRef(ref mustRelease); _parameterCollection.Bind(this, _cmdWrapper, parameterBuffer); } if(!localReader.IsBehavior(CommandBehavior.SchemaOnly)) { // Can't get the KeyInfo after command execution (SQL Server only since it does not support multiple // results on the same connection). Stored procedures (SP) do not return metadata before actual execution // Need to check the column count since the command type may not be set to SP for a SP. if((localReader.IsBehavior(CommandBehavior.KeyInfo) || localReader.IsBehavior(CommandBehavior.SchemaOnly)) && (CommandType != CommandType.StoredProcedure)) { Int16 cColsAffected; retcode = stmt.NumberOfResultColumns(out cColsAffected); if(retcode == ODBC32.RetCode.SUCCESS || retcode == ODBC32.RetCode.SUCCESS_WITH_INFO) { if(cColsAffected > 0) { localReader.GetSchemaTable(); } } else if(retcode == ODBC32.RetCode.NO_DATA) { // do nothing } else { // any other returncode indicates an error _connection.HandleError(stmt, retcode); } } switch(odbcApiMethod) { case ODBC32.SQL_API.SQLEXECDIRECT: if(localReader.IsBehavior(CommandBehavior.KeyInfo) || _isPrepared) { //Already prepared, so use SQLExecute retcode = stmt.Execute(); // Build metadata here // localReader.GetSchemaTable(); } else { #if DEBUG //if (AdapterSwitches.OleDbTrace.TraceInfo) { // ADP.DebugWriteLine("SQLExecDirectW: " + CommandText); //} #endif //SQLExecDirect retcode = stmt.ExecuteDirect(CommandText); } break; case ODBC32.SQL_API.SQLTABLES: retcode = stmt.Tables((string)methodArguments[0], //TableCatalog (string)methodArguments[1], //TableSchema, (string)methodArguments[2], //TableName (string)methodArguments[3]); //TableType break; case ODBC32.SQL_API.SQLCOLUMNS: retcode = stmt.Columns((string)methodArguments[0], //TableCatalog (string)methodArguments[1], //TableSchema (string)methodArguments[2], //TableName (string)methodArguments[3]); //ColumnName break; case ODBC32.SQL_API.SQLPROCEDURES: retcode = stmt.Procedures((string)methodArguments[0], //ProcedureCatalog (string)methodArguments[1], //ProcedureSchema (string)methodArguments[2]); //procedureName break; case ODBC32.SQL_API.SQLPROCEDURECOLUMNS: retcode = stmt.ProcedureColumns((string)methodArguments[0], //ProcedureCatalog (string)methodArguments[1], //ProcedureSchema (string)methodArguments[2], //procedureName (string)methodArguments[3]); //columnName break; case ODBC32.SQL_API.SQLSTATISTICS: retcode = stmt.Statistics((string)methodArguments[0], //TableCatalog (string)methodArguments[1], //TableSchema (string)methodArguments[2], //TableName (Int16)methodArguments[3], //IndexTrpe (Int16)methodArguments[4]); //Accuracy break; case ODBC32.SQL_API.SQLGETTYPEINFO: retcode = stmt.GetTypeInfo((Int16)methodArguments[0]); //SQL Type break; default: // this should NEVER happen Debug.Assert(false, "ExecuteReaderObjectcalled with unsupported ODBC API method."); throw ADP.InvalidOperation(method.ToString()); } //Note: Execute will return NO_DATA for Update/Delete non-row returning queries if((ODBC32.RetCode.SUCCESS != retcode) && (ODBC32.RetCode.NO_DATA != retcode)) { _connection.HandleError(stmt, retcode); } } // end SchemaOnly } finally { if(mustRelease) { parameterBuffer.DangerousRelease(); } } this.weakDataReaderReference = new WeakReference(localReader); // XXXCommand.Execute should position reader on first row returning result // any exceptions in the initial non-row returning results should be thrown // from from ExecuteXXX not the DataReader if(!localReader.IsBehavior(CommandBehavior.SchemaOnly)) { localReader.FirstResult(); } cmdState = ConnectionState.Fetching; } finally { if(ConnectionState.Fetching != cmdState) { if(null != localReader) { // clear bindings so we don't grab output parameters on a failed execute if(null != _parameterCollection) { _parameterCollection.ClearBindings(); } ((IDisposable)localReader).Dispose(); } if(ConnectionState.Closed != cmdState) { cmdState = ConnectionState.Closed; } } } return localReader; }
internal void Dispose() { if (null != _dataReaderBuf) { _dataReaderBuf.Dispose(); _dataReaderBuf = null; } DisposeStatementHandle(); CNativeBuffer buffer = _nativeParameterBuffer; _nativeParameterBuffer = null; if (null != buffer) { buffer.Dispose(); } _ssKeyInfoModeOn = false; _ssKeyInfoModeOff = false; }
internal ODBC32.RetCode GetDescriptionField(int i, ODBC32.SQL_DESC attribute, CNativeBuffer buffer, out int numericAttribute) { ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetDescFieldW(this, checked((short)i), attribute, buffer, buffer.ShortLength, out numericAttribute); ODBC.TraceODBC(3, "SQLGetDescFieldW", retcode); return retcode; }
internal ODBC32.RetCode GetDescriptionField(int i, ODBC32.SQL_DESC attribute, CNativeBuffer buffer, out int numericAttribute) { ODBC32.RetCode retcode = Interop.Odbc.SQLGetDescFieldW(this, checked ((short)i), attribute, buffer, buffer.ShortLength, out numericAttribute); ODBC.TraceODBC(3, "SQLGetDescFieldW", retcode); return(retcode); }
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); } }
private OdbcDataReader ExecuteReaderObject(CommandBehavior behavior, string method, bool needReader, object[] methodArguments, ODBC32.SQL_API odbcApiMethod) // MDAC 68324 { OdbcDataReader localReader = null; try { DisposeDeadDataReader(); // this is a no-op if cmdState is not Fetching ValidateConnectionAndTransaction(method); // cmdState will change to Executing if (0 != (CommandBehavior.SingleRow & behavior)) { // CommandBehavior.SingleRow implies CommandBehavior.SingleResult behavior |= CommandBehavior.SingleResult; } ODBC32.RetCode retcode; OdbcStatementHandle stmt = GetStatementHandle().StatementHandle; _cmdWrapper.Canceling = false; if (null != weakDataReaderReference) { if (weakDataReaderReference.IsAlive) { object target = weakDataReaderReference.Target; if (null != target && weakDataReaderReference.IsAlive) { if (!((OdbcDataReader)target).IsClosed) { throw ADP.OpenReaderExists(); // MDAC 66411 } } } } localReader = new OdbcDataReader(this, _cmdWrapper, behavior); //Set command properties //Not all drivers support timeout. So fail silently if error if (!Connection.ProviderInfo.NoQueryTimeout) { TrySetStatementAttribute(stmt, ODBC32.SQL_ATTR.QUERY_TIMEOUT, (IntPtr)this.CommandTimeout); } // todo: If we remember the state we can omit a lot of SQLSetStmtAttrW calls ... // if we do not create a reader we do not even need to do that if (needReader) { if (Connection.IsV3Driver) { if (!Connection.ProviderInfo.NoSqlSoptSSNoBrowseTable && !Connection.ProviderInfo.NoSqlSoptSSHiddenColumns) { // Need to get the metadata information //SQLServer actually requires browse info turned on ahead of time... //Note: We ignore any failures, since this is SQLServer specific //We won't specialcase for SQL Server but at least for non-V3 drivers if (localReader.IsBehavior(CommandBehavior.KeyInfo)) { if (!_cmdWrapper._ssKeyInfoModeOn) { TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.NOBROWSETABLE, (IntPtr)ODBC32.SQL_NB.ON); TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.HIDDEN_COLUMNS, (IntPtr)ODBC32.SQL_HC.ON); _cmdWrapper._ssKeyInfoModeOff = false; _cmdWrapper._ssKeyInfoModeOn = true; } } else { if (!_cmdWrapper._ssKeyInfoModeOff) { TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.NOBROWSETABLE, (IntPtr)ODBC32.SQL_NB.OFF); TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.HIDDEN_COLUMNS, (IntPtr)ODBC32.SQL_HC.OFF); _cmdWrapper._ssKeyInfoModeOff = true; _cmdWrapper._ssKeyInfoModeOn = false; } } } } } if (localReader.IsBehavior(CommandBehavior.KeyInfo) || localReader.IsBehavior(CommandBehavior.SchemaOnly)) { retcode = stmt.Prepare(CommandText); if (ODBC32.RetCode.SUCCESS != retcode) { _connection.HandleError(stmt, retcode); } } bool mustRelease = false; CNativeBuffer parameterBuffer = _cmdWrapper._nativeParameterBuffer; RuntimeHelpers.PrepareConstrainedRegions(); try { //Handle Parameters //Note: We use the internal variable as to not instante a new object collection, //for the the common case of using no parameters. if ((null != _parameterCollection) && (0 < _parameterCollection.Count)) { int parameterBufferSize = _parameterCollection.CalcParameterBufferSize(this); if (null == parameterBuffer || parameterBuffer.Length < parameterBufferSize) { if (null != parameterBuffer) { parameterBuffer.Dispose(); } parameterBuffer = new CNativeBuffer(parameterBufferSize); _cmdWrapper._nativeParameterBuffer = parameterBuffer; } else { parameterBuffer.ZeroMemory(); } parameterBuffer.DangerousAddRef(ref mustRelease); _parameterCollection.Bind(this, _cmdWrapper, parameterBuffer); } if (!localReader.IsBehavior(CommandBehavior.SchemaOnly)) { // Can't get the KeyInfo after command execution (SQL Server only since it does not support multiple // results on the same connection). Stored procedures (SP) do not return metadata before actual execution // Need to check the column count since the command type may not be set to SP for a SP. if ((localReader.IsBehavior(CommandBehavior.KeyInfo) || localReader.IsBehavior(CommandBehavior.SchemaOnly)) && (CommandType != CommandType.StoredProcedure)) { Int16 cColsAffected; retcode = stmt.NumberOfResultColumns(out cColsAffected); if (retcode == ODBC32.RetCode.SUCCESS || retcode == ODBC32.RetCode.SUCCESS_WITH_INFO) { if (cColsAffected > 0) { localReader.GetSchemaTable(); } } else if (retcode == ODBC32.RetCode.NO_DATA) { // do nothing } else { // any other returncode indicates an error _connection.HandleError(stmt, retcode); } } switch (odbcApiMethod) { case ODBC32.SQL_API.SQLEXECDIRECT: if (localReader.IsBehavior(CommandBehavior.KeyInfo) || _isPrepared) { //Already prepared, so use SQLExecute retcode = stmt.Execute(); // Build metadata here // localReader.GetSchemaTable(); } else { #if DEBUG //if (AdapterSwitches.OleDbTrace.TraceInfo) { // ADP.DebugWriteLine("SQLExecDirectW: " + CommandText); //} #endif //SQLExecDirect retcode = stmt.ExecuteDirect(CommandText); } break; case ODBC32.SQL_API.SQLTABLES: retcode = stmt.Tables((string)methodArguments[0], //TableCatalog (string)methodArguments[1], //TableSchema, (string)methodArguments[2], //TableName (string)methodArguments[3]); //TableType break; case ODBC32.SQL_API.SQLCOLUMNS: retcode = stmt.Columns((string)methodArguments[0], //TableCatalog (string)methodArguments[1], //TableSchema (string)methodArguments[2], //TableName (string)methodArguments[3]); //ColumnName break; case ODBC32.SQL_API.SQLPROCEDURES: retcode = stmt.Procedures((string)methodArguments[0], //ProcedureCatalog (string)methodArguments[1], //ProcedureSchema (string)methodArguments[2]); //procedureName break; case ODBC32.SQL_API.SQLPROCEDURECOLUMNS: retcode = stmt.ProcedureColumns((string)methodArguments[0], //ProcedureCatalog (string)methodArguments[1], //ProcedureSchema (string)methodArguments[2], //procedureName (string)methodArguments[3]); //columnName break; case ODBC32.SQL_API.SQLSTATISTICS: retcode = stmt.Statistics((string)methodArguments[0], //TableCatalog (string)methodArguments[1], //TableSchema (string)methodArguments[2], //TableName (Int16)methodArguments[3], //IndexTrpe (Int16)methodArguments[4]); //Accuracy break; case ODBC32.SQL_API.SQLGETTYPEINFO: retcode = stmt.GetTypeInfo((Int16)methodArguments[0]); //SQL Type break; default: // this should NEVER happen Debug.Assert(false, "ExecuteReaderObjectcalled with unsupported ODBC API method."); throw ADP.InvalidOperation(method.ToString()); } //Note: Execute will return NO_DATA for Update/Delete non-row returning queries if ((ODBC32.RetCode.SUCCESS != retcode) && (ODBC32.RetCode.NO_DATA != retcode)) { _connection.HandleError(stmt, retcode); } } // end SchemaOnly } finally { if (mustRelease) { parameterBuffer.DangerousRelease(); } } this.weakDataReaderReference = new WeakReference(localReader); // XXXCommand.Execute should position reader on first row returning result // any exceptions in the initial non-row returning results should be thrown // from from ExecuteXXX not the DataReader if (!localReader.IsBehavior(CommandBehavior.SchemaOnly)) { localReader.FirstResult(); } cmdState = ConnectionState.Fetching; } finally { if (ConnectionState.Fetching != cmdState) { if (null != localReader) { // clear bindings so we don't grab output parameters on a failed execute if (null != _parameterCollection) { _parameterCollection.ClearBindings(); } ((IDisposable)localReader).Dispose(); } if (ConnectionState.Closed != cmdState) { cmdState = ConnectionState.Closed; } } } return(localReader); }
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 ODBC32.RetCode GetDescriptionField(int i, ODBC32.SQL_DESC attribute, CNativeBuffer buffer, out int numericAttribute) { ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetDescFieldW(this, (short)i, attribute, buffer, buffer.ShortLength, out numericAttribute); ODBC.TraceODBC(3, "SQLGetDescFieldW", retcode); return(retcode); }
static internal extern /*SQLRETURN*/ODBC32.RetCode SQLGetData( /*SQLHSTMT*/OdbcStatementHandle StatementHandle, /*SQLUSMALLINT*/UInt16 ColumnNumber, /*SQLSMALLINT*/ODBC32.SQL_C TargetType, /*SQLPOINTER*/CNativeBuffer TargetValue, /*SQLLEN*/IntPtr BufferLength, // sql.h differs from MSDN /*SQLLEN* */out IntPtr StrLen_or_Ind);
internal void GetOutputValue(CNativeBuffer parameterBuffer) { //Handle any output params // No value is available if the user fiddles with the parameters properties // if (_hasChanged) return; if ((null != _bindtype) && (_internalDirection != ParameterDirection.Input)) { TypeMap typemap = _bindtype; _bindtype = null; int cbActual = (int)parameterBuffer.ReadIntPtr(_preparedIntOffset); if (ODBC32.SQL_NULL_DATA == cbActual) { Value = DBNull.Value; } else if ((0 <= cbActual) || (cbActual == ODBC32.SQL_NTS)){ // safeguard Value = parameterBuffer.MarshalToManaged(_preparedValueOffset, _boundSqlCType, cbActual); if (_boundSqlCType== ODBC32.SQL_C.CHAR) { if ((null != Value) && !Convert.IsDBNull(Value)) { int lcid = System.Globalization.CultureInfo.CurrentCulture.LCID; CultureInfo culInfo = new CultureInfo(lcid); Encoding cpe = System.Text.Encoding.GetEncoding(culInfo.TextInfo.ANSICodePage); Value = cpe.GetString((Byte[])Value); } } if ((typemap != _typemap) && (null != Value) && !Convert.IsDBNull(Value) && (Value.GetType() != _typemap._type)) { Debug.Assert(ODBC32.SQL_C.NUMERIC == _typemap._sql_c, "unexpected"); Value = Decimal.Parse((string)Value, System.Globalization.CultureInfo.CurrentCulture); } } } }
static internal extern /*SQLRETURN*/ODBC32.RetCode SQLGetDescFieldW ( /*SQLHSTMT*/OdbcDescriptorHandle StatementHandle, /*SQLUSMALLINT*/Int16 RecNumber, /*SQLUSMALLINT*/ODBC32.SQL_DESC FieldIdentifier, /*SQLPOINTER*/CNativeBuffer ValuePointer, /*SQLINTEGER*/Int32 BufferLength, /*SQLINTEGER* */out Int32 StringLength);
internal void Bind(OdbcCommand command, CMDWrapper cmdWrapper, CNativeBuffer parameterBuffer) { for (int i = 0; i < this.Count; i++) { this[i].Bind(cmdWrapper.StatementHandle, command, (short) (i + 1), parameterBuffer, true); } this._rebindCollection = false; }
internal void SetInputValue(int size, object value, byte precision, CNativeBuffer buffer, CNativeBuffer intbuffer) //Handle any input params { #if DEBUG if (AdapterSwitches.DataValue.TraceVerbose) { Debug.WriteLine("SQLBindParameter:" + _typemap._odbcType.ToString("G") + " " + _bindtype._odbcType.ToString("G") + "(" + size + ")=" + ADP.ValueToString(value)); } #endif if ((ODBC32.SQL_PARAM.INPUT == _sqldirection) || (ODBC32.SQL_PARAM.INPUT_OUTPUT == _sqldirection)) { ODBC32.SQL_C sql_c_type; sql_c_type = (_parent.Connection.OdbcMajorVersion >= 3) ? _bindtype._sql_c : _bindtype._param_sql_c; //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)) { Marshal.WriteInt32(intbuffer.Ptr, ODBC32.SQL_DEFAULT_PARAM); } else if (Convert.IsDBNull(value)) { Marshal.WriteInt32(intbuffer.Ptr, ODBC32.SQL_NULL_DATA); } else { // Clear previous NULL_DATA status Marshal.WriteInt32(intbuffer.Ptr, 0); 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. Marshal.WriteInt32(intbuffer.Ptr, size); break; } //Place the input param value into the native buffer buffer.MarshalToNative(value, sql_c_type, precision); } } else { // always set ouput only and return value parameter values to null when executing Value = 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) Marshal.WriteInt32(intbuffer.Ptr, ODBC32.SQL_NULL_DATA); } }