Welcome Guest, Not a member yet? Register   Sign In
Oracle stored procedures fail
#1

[eluser]Skeleton Man[/eluser]
Hi all,

I have been attemping to run oracle stored procedures as follows:


Code:
$package   = "AOBADM.MYIQ_BUILDING_PKG";
        $procedure = "p_building_fetch";

        $myiq_building = null;
        $group         = null;
        $key           = "";
        $return_code   = -1000;
        $return_text   = "UNDEF";

        // Get a cursor
        $p_buildings_cursor = $this->db->get_cursor();

        // Parameters must be in :<param_name> format
        // Input parameter value should be a string, int, etc
        // Output parameter value should be a reference to a variable

        // Input parameters
        $params[] = array('name'  => ':p_user_id',
                          'value' => $this->user_id,
                          'length' => -1,
                          'type' => SQLT_CHR);

        // Output parameters
        $params[] = array('name'  => ':p_buildings',
                          'value' => &$p_buildings_cursor,
                          'length' => -1,
                          'type'  => OCI_B_CURSOR); // pass by reference, sys_refcursor

        $params[] = array('name'  => ':p_status',
                          'value' => &$return_text, // pass by reference
                          'length' => -1,
                          'type' => SQLT_CHR);

        $params[] = array('name'  => ':p_code',
                          'value' => &$return_code,  // pass by reference
                          'length' => -1,
                          'type' => SQLT_CHR);

        $this->db->stored_procedure($package, $procedure, $params);

At first it was crashing PHP and returning "502 bad gateway", so I did some googling and found this post.

I patched oci8_driver.php and DB_driver.php per the suggestions, and it stopped PHP crashing, but now I get: "ociexecute() [function.ociexecute]: ORA-01008: not all variables bound".

It clearly isn't binding anything, judging by this sql:

begin AOBADM.MYIQ_BUILDING_PKG.p_building_fetch(:p_user_id,:p_buildings,:p_status,:p_code); end;

Can someone suggest how I can fix this ?

Chris
#2

[eluser]Skeleton Man[/eluser]
I ended up rolling my own and bypassing CI's database library for stored procedures with cursors:

Code:
class Db_util
{
    private $conn = null;
    private $stmt = null;
    private $curs = null;

    public function __construct()
    {
        require_once(APPPATH.'config/database.php');
        $this->conn = oci_connect($db['default']['username'],$db['default']['password'],$db['default']['hostname']);
    }

    public function stored_procedure($package,$procedure,$params)
    {
        // Start our query with the package/procedure name
        $sql = "begin {$package}.{$procedure}(";

        // Build a list of parameters
        foreach ($params as $param)
        {
            $sql .= $param['name'].',';
        }

        $sql = rtrim($sql,','); // Strip the trailing comma

        // End our query with the word 'end'
        $sql .= "); end;";

        // Parse our sql
        $this->stmt = oci_parse($this->conn,$sql);

        // Loop through parameters again, binding parameters, and checking if we have a cursor
        foreach ($params as $param)
        {
            if ($param['type'] == OCI_B_CURSOR)
            {
                // Get a cursor
                $this->curs = oci_new_cursor($this->conn);

                // Bind the cursor
                oci_bind_by_name($this->stmt,$param['name'],$this->curs,-1,OCI_B_CURSOR);
            }else{

                // Bind the parameter
                oci_bind_by_name($this->stmt,$param['name'],$param['value'],$param['length'],$param['type']);
            }
        }

        oci_execute($this->stmt);
        oci_execute($this->curs);
    }

    public function cursor_fetch_row()
    {
        return oci_fetch_row($this->curs);
    }

    public function cursor_fetch_object()
    {
        // Lower case is preferable
        $tmp = oci_fetch_object($this->curs);

        if (!is_object($tmp))
        {
            return false;
        }

        $new = new stdClass();

        foreach ($tmp as $key => $val)
        {
            $lower = strtolower($key);
            $new->{$lower} = $val;
        }

        return $new;
    }

    public function free_close()
    {
        oci_free_statement($this->stmt);
        oci_free_statement($this->curs);
        oci_close($conn);
    }
}

This is how it's called:

Code:
$package   = "AOBADM.MYIQ_BUILDING_PKG";
$procedure = "p_building_fetch";

$return_code   = '';
$return_text   = '';

// Parameters must be in :<param_name> format
// Input parameter value should be a string, int, etc
// Output parameter value should be a reference to a variable

// Input parameters
$params[] = array('name'   => ':p_user_id',
                  'value'  => 388,
                  'length' => -1,
                  'type'   => SQLT_CHR);

// Output parameters
$params[] = array('name'   => ':p_buildings',
                  'value'  => null,          // cursors are handled internally
                  'length' => -1,
                  'type'   => OCI_B_CURSOR);

$params[] = array('name'   => ':p_status',
                  'value'  => &$return_text, // pass by reference
                  'length' => 32,
                  'type'   => SQLT_CHR);

$params[] = array('name'   => ':p_code',
                  'value'  => &$return_code,  // pass by reference
                  'length' => 32,
                  'type'   => SQLT_CHR);

$db = new Db_util();
$db->stored_procedure($package,$procedure,$params);

print "{$return_code}\n{$return_text}\n\n";

while ($data = $db->cursor_fetch_object())
{
    print_r($data);
}

$db->free_close();

This removes the need for the calling code to create and pass a cursor, everything is handled by the wrapper. If someone wants to CI-ize my code, feel free - this was just a quick workaround.




Theme © iAndrew 2016 - Forum software by © MyBB