Ok, this is a curly one. I’m working on some Delphi code that I didn’t write, and I’m encountering a very strange problem. One of my stored procedures’ parameters is coming through as null, even though it’s definitely being sent 1.
The Delphi code uses a TADOQuery to execute the stored procedure (anonymized):
ADOQuery1.SQL.Text := 'exec MyStoredProcedure :Foo,:Bar,:Baz,:Qux,:Smang,:Jimmy'; ADOQuery1.Parameters.ParamByName('Foo').Value := Integer(someFunction()); // other parameters all set similarly ADOQuery1.ExecSQL;
Integer(SomeFunction()) currently always returns 1 – I checked with the debugger.
However, in my stored proc ( altered for debug purposes ):
create procedure MyStoredProcedure ( @Foo int, @Bar int, @Baz int, @Qux int, @Smang int, @Jimmy varchar(20) ) as begin -- temp debug if ( @Foo is null ) begin insert into TempLog values ( 'oh crap' ) end -- do the rest of the stuff here.. end
TempLog does indeed end up with ‘oh crap’ in it (side question: there must be a better way of debugging stored procs: what is it?).
Here’s an example trace from profiler:
exec [MYDB]..sp_procedure_params_rowset N'MyStoredProcedure',1,NULL,NULL declare @p3 int set @p3=NULL exec sp_executesql N'exec MyStoredProcedure @P1,@P2,@P3,@P4,@P5,@P6', N'@P1 int OUTPUT,@P2 int,@P3 int,@P4 int,@P5 int,@P6 int', @p3 output,1,1,1,0,200 select @p3
This looks a little strange to me. Notice that it’s using @p3 and @P3 – could this be causing my issue?
The other strange thing is that it seems to depend on which TADOConnection I use.
The project is a dll which is passed a TADOConnection from another application. It calls all the stored procedures using this connection.
If instead of using this connection, I first do this:
ConnectionNew := TADOQuery.Create(ConnectionOld.Owner); ConnectionNew.ConnectionString := ConnectionOld.ConnectionString; TADOQuery1.Connection := ConnectionNew;
Then the issue does not occur! The trace from this situation is this:
exec [MYDB]..sp_procedure_params_rowset N'MyStoredProcedure',1,NULL,NULL declare @p1 int set @p1=64 exec sp_prepare @p1 output, N'@P1 int,@P2 int,@P3 int,@P4 int,@P5 int,@P6 varchar(20)', N'exec MyStoredProcedure @P1,@P2,@P3,@P4,@P5,@P6', 1 select @p1 SET FMTONLY ON exec sp_execute 64,0,0,0,0,0,' ' SET FMTONLY OFF exec sp_unprepare 64 SET NO_BROWSETABLE OFF exec sp_executesql N'exec MyStoredProcedure @P1,@P2,@P3,@P4,@P5,@P6', N'@P1 int,@P2 int,@P3 int,@P4 int,@P5 int,@P6 varchar(20)', 1,1,1,3,0,'400.00'
Which is a bit much for lil ol’ me to follow, unfortunately. What sort of TADOConnection options could be influencing this?
Does anyone have any ideas?
Edit: Update below (didn’t want to make this question any longer :P)
Ok, progress is made.. sort of.
@Robsoft was correct, setting the parameter direction to
pdInputfixed the issue.I traced into the VCL code, and it came down to
TParameters.InternalRefresh.RefreshFromOleDB. This function is being called when I set the SQL.Text. Here’s the (abridged) code:So,
OLEDBParameters.GetParameterInfois returning the wrong flags for some reason.I’ve verified that with the original connection,
(dwFlags and $F)is2(DBPARAMFLAGS_ISOUTPUT), and with the new connection, it’s1(DBPARAMFLAGS_ISINPUT).I’m not really sure I want to dig any deeper than that, for now at least.
Until I have more time and inclination, I’ll just make sure all parameters are set to
pdInputbefore I open the query.Unless anyone has any more bright ideas now..?
Anyway, thanks everyone for your suggestions so far.