Welcome Guest, Not a member yet? Register   Sign In
ActiveRecord Update ignores LIKE
#1

[eluser]Unknown[/eluser]
I recently ran into this issue and it caused a major problem with one of the systems I built.
Turns out there was already a bug report filed 14 months ago that still has not been dealt with:

http://codeigniter.com/bug_tracker/bug/5940/

This:
Code:
$data = array(
    'label' => 'example2'
);
$this->db->like('label', 'example');
$this->db->update('example_table', $data);


Produces this:
Code:
UPDATE `example_table`
SET `label` = 'example2'


Which is WRONG. What it should produce is:
Code:
UPDATE `example_table`
SET `label` = 'example2'
WHERE `label` LIKE '%example%'
#2

[eluser]Shay Falador[/eluser]
Well I found out the problem, at least for MySQL.
In /system/database/DB_active_red.php there is that update method:
Code:
function update($table = '', $set = NULL, $where = NULL, $limit = NULL)
    {
        // Combine any cached components with the current statements
        $this->_merge_cache();

        if ( ! is_null($set))
        {
            $this->set($set);
        }
    
        if (count($this->ar_set) == 0)
        {
            if ($this->db_debug)
            {
                return $this->display_error('db_must_use_set');
            }
            return FALSE;
        }

        if ($table == '')
        {
            if ( ! isset($this->ar_from[0]))
            {
                if ($this->db_debug)
                {
                    return $this->display_error('db_must_set_table');
                }
                return FALSE;
            }
            
            $table = $this->ar_from[0];
        }
        
        if ($where != NULL)
        {
            $this->where($where);
        }

        if ($limit != NULL)
        {
            $this->limit($limit);
        }
        
        $sql = $this->_update($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit);
        
        $this->_reset_write();
        return $this->query($sql);
    }
In /system/database/drivers/mysql/mysql_driver.php there is that _update method:
Code:
function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
    {
        foreach($values as $key => $val)
        {
            $valstr[] = $key." = ".$val;
        }
        
        $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
        
        $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
    
        $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);

        $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';

        $sql .= $orderby.$limit;
        
        return $sql;
    }

In order to fix it we need to change the update method in the active record file, and add the like data to the _update call:
Code:
function _update($table, $values, $where, $like, $orderby = array(), $limit = FALSE)
    {
        foreach($values as $key => $val)
        {
            $valstr[] = $key." = ".$val;
        }
        
        $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
        
        $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
    
        $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);

        $sql .= (($where != '' AND count($where) >=1) OR ($like != '' AND count($like) >=1)) ? " WHERE ".implode(" ", $where) : '';

        if (count($like) > 0)
        {
            $sql .= (count($where) > 0) ? "AND " : '';
            $sql .= implode("\n", $like);
        }

        $sql .= $orderby.$limit;
        
        return $sql;
    }

I think it will work...
Any way, you need to change core files to do so, which I don't recommend. This might help.

Good luck!
#3

[eluser]benster[/eluser]
Hi Shay,

Do you know if this was ever addressed as part of the core product? It appears to still be an issue.

Regards, Ben.




Theme © iAndrew 2016 - Forum software by © MyBB