Search code examples
phpsql-serverfreetdsadodb-php

ADODB / SQL Server mssql_execute stored procedure fails but works if debug is set to true


I am connecting to a SQL Server database from PHP using ADODB. I have several stored procedures that I have been executing just fine. The last call that I have created for some reason keeps failing. I put debug as true and it works just fine. I have no idea why this would be happening.

here is the error I get

Error: mssql_execute() [<a href='function.mssql-execute'>function.mssql-execute</a>]:      stored procedure execution failed  in /path/to/adodb/lib/adodb5/drivers/adodb-mssql.inc.php on line 768

Here is the method I created to pass all my stored procedures to, like I said it works fine with other stored procedures but this one and I have double checked that all the spellings of the parameters and stored procedure are correct.

protected function _getSpArray($db, $sp, array $spParams) {
    try {
        $stmt = $db->PrepareSP($sp);
        foreach ($spParams as $param) {
            $db->InParameter($stmt, $param[0], $param[1]);
        }
        $db->SetFetchMode(ADODB_FETCH_ASSOC);
        $rs = $db->Execute($stmt);
        $rsArray = array();
        if (!$rs) {
            echo 'No records found \n';
            return;
        }
        else {
            foreach ($rs as $k => $row) {
                $rsArray[$k] = $row;
            }
        }
        return $rsArray;
    } catch (ErrorException $e) {
        echo $e->getMessage();
    }
}

It is failing on this line #768 of adodb5/drivers/adodb-mssql.inc.php

$rez = mssql_execute($sql[1]);

and the sql array has these values

[0] stored_procedure_name
[1] resource id='657' type='mssql statement'

I have seen the following comments on PHP.net, I changed my freetds host name to be something different then the IP address and still nothing. I am not sure about the free result since I am using adodb.

http://www.php.net/manual/en/function.mssql-execute.php#93938

I am using adodb 5.11


Solution

  • When you set debug as true ADODB uses other function to execute the statement. In this case function _adodb_debug_execute(&$zthis, $sql, $inputarr)

    If debug is set to false ADODB uses function &_Execute($sql,$inputarr=false). When you check the source for both methods you can clearly see the difference.

    <?php
    function _adodb_debug_execute(&$zthis, $sql, $inputarr)
    {
        //ADODB prepares debug information dump...
    
        $qID = $zthis->_query($sql,$inputarr);
    
        //Here ADODB makes the difference
    
        if ($zthis->databaseType == 'mssql') { 
        // ErrorNo is a slow function call in mssql, and not reliable in PHP 4.0.6
            if($emsg = $zthis->ErrorMsg()) {
                if ($err = $zthis->ErrorNo()) ADOConnection::outp($err.': '.$emsg);
            }
        } else if (!$qID) {
            ADOConnection::outp($zthis->ErrorNo() .': '. $zthis->ErrorMsg());
        }
    
        if ($zthis->debug === 99) _adodb_backtrace(true,9999,2);
        return $qID;
    }
    ?>
    

    Here is the _Execute function

    <?php
    function &_Execute($sql,$inputarr=false){
            //Here ADODB chooses which fn to use
            if ($this->debug) {
                global $ADODB_INCLUDED_LIB;
                if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR.'/adodb-lib.inc.php');
                $this->_queryID = _adodb_debug_execute($this, $sql,$inputarr);
            } else {
                $this->_queryID = @$this->_query($sql,$inputarr);
            }
            //...
    
            if ($this->_queryID === false) { // error handling if query fails
                //If debug ADODB prints backtrace regardless the result
                if ($this->debug == 99) adodb_backtrace(true,5);    
                $fn = $this->raiseErrorFn;
                if ($fn) {
                    $fn($this->databaseType,'EXECUTE',$this->ErrorNo(),$this->ErrorMsg(),$sql,$inputarr,$this);
                } 
                $false = false;
                //Returns false no matter what...
                return $false;
            } 
            //...
        }
    ?>
    

    Try adding this to your script to test the behaviour of the script and keep in mind that if the execute fails it will return a false value. So take care with the returned value.

    protected function _getSpArray($db, $sp, array $spParams) {
        try {
            $stmt = $db->PrepareSP($sp);
            foreach ($spParams as $param) {
                $db->InParameter($stmt, $param[0], $param[1]);
            }
            $db->SetFetchMode(ADODB_FETCH_ASSOC);
            $rs = $db->Execute($stmt);
            $rsArray = array();
            if (!$rs) {
                echo 'No records found \n';
                return;
            }
            else {
                foreach ($rs as $k => $row) {
                    $rsArray[$k] = $row;
                }
            }
            //add this line to free the resources after use. 
            mssql_free_result($rs);
            return $rsArray;
        } catch (ErrorException $e) {
            echo $e->getMessage();
        }
    }
    

    Hope it helps!!