SQL Server 2005: "Protecting" stored procedures from FMTONLY mode used by MS Access

In some stored procedures, we have conditional logic, for example:

Create Procedure dbo.DoSomething(Some Parameters)
As
    ...
    If (Some Condition) Begin
        Set @SomeVariable = SomeValue                
    End
    ...
    Select ...

      

When such a stored procedure is used as a record source for an MS Access form and the user tries to use the built-in sort / filter functions of the form, MS Access tries to execute the stored procedure in FMTONLY mode (apparently hunting for the rowset metadata provided by the stored procedure).

As most people know (now including ourselves :-), when FMTONLY is ON, SQL Server ignores conditional statements. In the example below, the statement is executed regardless of whether the value is true, which obviously creates some problems for us. Set @SomeVariable = SomeValue

Some Condition

-- EXAMPLE
-- -------
Create Procedure dbo.DoSomething(..., @vcSomeDate as VarChar(50), ...)
As
   ...
   Declare @dtSomeDate As Datetime
   If (IsDate(@vcSomeDateOrAgeInDays)) Begin
       -- The next statement fails miserably when FMTONLY=ON
       Set @dtSomeDate = @vcSomeDateOrAgeInDays
   End Else Begin
       ...
   End
   ...

      

To work around this problem, we "wrap" the conditional logic (or any other code fragments affected by FMTONLY) as follows:

Create Procedure dbo.DoSomething(Some Parameters)
As
    ...

    -- HACK: Protection from unexpected FMTONLY mode
    Declare @wasFmtonlyOn As Bit; If (0 = 1) Set @wasFmtonlyOn = 1; SET FMTONLY OFF
    ...
    If (Some Condition) Begin
        Set @SomeVariable = SomeValue                
    End
    ...
    -- /HACK: Protection from unexpected FMTONLY mode
    If (@wasFmtonlyOn = 1) SET FMTONLY ON

    ...
    Select ...

      

(This ugly one-line "security code" formatting is intentional: we think that the hacks needed to solve some strange problems don't deserve proper formatting, on the contrary, we think they should fit on multiple lines as soon as possible. :-)

In any case, this "protection" works fine, but it is a little too verbose and not as encapsulated as we would like. For example, we would definitely prefer to hide the actual hacking logic behind a scalar UDF like this:

Create Procedure dbo.DoSomething(Some Parameters)
As
    ...

    declare @wasFmtonlyOn as bit; set @wasFmtonlyOn = dbo.SetFmtonly(0)
    ...
    If (Some Condition) Begin
        Set @SomeVariable = SomeValue                
    End
    ...
    dbo.SetFmtonly(@wasFmtonlyOn)

    ...
    Select ...

      

Unfortunately this doesn't seem to work - neither with scalar UDFs, nor with any other stored procedure. Looks like FMTONLY prevents any data from being returned from anywhere. So here's the main question :

If you also had to solve this problem (SQL Server ignores conditionals in FMTONLY mode), could you think of a better "security idiom" than the one described above?

By the way, I still don't understand one thing: is it a bug or a feature in SQL Server 2005? And if this is a feature, then what could it be a good reason for?

Thank!

0


source to share


1 answer


How about this?

If (Some Condition) Begin
    Set @SomeVariable = SomeValue
ELSE
    Set @SomeVariable = @SomeVariable --or dummy/default value?
End

      

Does your code mean two different sets of records (columns and types) based on this variable? If so, you need to split the saved proc by 2



Also, I found an article in KB that explains why.

Edit: Change the branch to inline code ...

Set @dtSomeDate = CASE WHEN ISDATE(@vcSomeDateOrAgeInDays) = 1 THEN @vcSomeDateOrAgeInDays ELSE NULL END

      

+1


source







All Articles