Welcome Guest, Not a member yet? Register   Sign In
Issues with MYSQL date function WEEK, MONTH, YEAR
#1

[eluser]Matthew Lanham[/eluser]
There seems to be an escaping issue when using mysql date functions like WEEK, MONTH, YEAR, it seems to be a cause of the following function:

_protect_identifiers

Located in DB_driver.php line 1193

here is a typical query which doesn't work:

SELECT `tasks`.* FROM (`tasks`) LEFT JOIN `_tasks_weddings` ON `tasks`.`id` = `_tasks_weddings`.`task_id` LEFT JOIN `weddings` ON `weddings`.`id` = `_tasks_weddings`.`wedding_id` WHERE `tasks`.`deleted` = 0 AND `WEEK(tasks`.`due)` IN ('03', '04') AND `weddings`.`id` = 1

As you can see it has escaped this statement, incorrectly:
`WEEK(tasks`.`due)` IN ('03', '04')

this should be:

WEEK(tasks.due) IN ('03', '04')
#2

[eluser]Matthew Lanham[/eluser]
In the meantime i have added the following to line 1195 so stop it from escaping these parts until i/you find a more suitable fix Smile
Code:
if(strstr($item, 'WEEK') OR strstr($item, 'YEAR') OR strstr($item, 'MONTH'))
        {
            return $item;
        }
#3

[eluser]Matthew Lanham[/eluser]
Sorry to keep hitting this topic, but i think i've solved it you had the following peice of code:

From line 1292 to 1300 in DB_driver.php
Code:
// This is basically a bug fix for queries that use MAX, MIN, etc.
// If a parenthesis is found we know that we do not need to
// escape the data or add a prefix.  There's probably a more graceful
// way to deal with this, but I'm not thinking of it -- Rick
if (strpos($item, '(') !== FALSE)
{
    return $item.$alias;
}

I move this up before some of the other code, and this seems to solve it, i think it has just been too far down in the function, i have it sitting on line 1245 to 1253.

Here is the full function code with my adjustment:
Code:
function _protect_identifiers($item, $prefix_single = FALSE, $protect_identifiers = NULL, $field_exists = TRUE)
    {
        /*
        if(strstr($item, 'WEEK') OR strstr($item, 'YEAR') OR strstr($item, 'MONTH'))
        {
            return $item;
        }
        */
        if ( ! is_bool($protect_identifiers))
        {
            $protect_identifiers = $this->_protect_identifiers;
        }
        
        // Convert tabs or multiple spaces into single spaces
        $item = preg_replace('/[\t| ]+/', ' ', $item);
    
        // If the item has an alias declaration we remove it and set it aside.
        // Basically we remove everything to the right of the first space
        $alias = '';
        if (strpos($item, ' ') !== FALSE)
        {        
            $alias = strstr($item, " ");
            $item = substr($item, 0, - strlen($alias));
        }

        // Break the string apart if it contains periods, then insert the table prefix
        // in the correct location, assuming the period doesn't indicate that we're dealing
        // with an alias. While we're at it, we will escape the components
        if (strpos($item, '.') !== FALSE)
        {
            $parts    = explode('.', $item);
            
            // Does the first segment of the exploded item match
            // one of the aliases previously identified?  If so,
            // we have nothing more to do other then escape the item
            if (in_array($parts[0], $this->ar_aliased_tables))
            {                
                if ($protect_identifiers === TRUE)
                {
                    foreach ($parts as $key => $val)
                    {
                        if ( ! in_array($val, $this->_reserved_identifiers))
                        {
                            $parts[$key] = $this->_escape_identifiers($val);
                        }
                    }
                
                    $item = implode('.', $parts);
                }            
                return $item.$alias;
            }
            
            // This is basically a bug fix for queries that use MAX, MIN, etc.
            // If a parenthesis is found we know that we do not need to
            // escape the data or add a prefix.  There's probably a more graceful
            // way to deal with this, but I'm not thinking of it -- Rick
            if (strpos($item, '(') !== FALSE)
            {

                return $item.$alias;
            }
            
            // Is there a table prefix defined in the config file?  If not, no need to do anything
            if ($this->dbprefix != '')
            {
                // We now add the table prefix based on some logic.
                // Do we have 4 segments (hostname.database.table.column)?
                // If so, we add the table prefix to the column name in the 3rd segment.
                if (isset($parts[3]))
                {
                    $i = 2;
                }
                // Do we have 3 segments (database.table.column)?
                // If so, we add the table prefix to the column name in 2nd position
                elseif (isset($parts[2]))
                {
                    $i = 1;
                }
                // Do we have 2 segments (table.column)?
                // If so, we add the table prefix to the column name in 1st segment
                else
                {
                    $i = 0;
                }
                
                // This flag is set when the supplied $item does not contain a field name.
                // This can happen when this function is being called from a JOIN.
                if ($field_exists == FALSE)
                {
                    $i++;
                }
                
                // We only add the table prefix if it does not already exist
                if (substr($parts[$i], 0, strlen($this->dbprefix)) != $this->dbprefix)
                {
                    $parts[$i] = $this->dbprefix.$parts[$i];
                }
                
                // Put the parts back together
                $item = implode('.', $parts);
            }

            if ($protect_identifiers === TRUE)
            {
                $item = $this->_escape_identifiers($item);
            }
            
            return $item.$alias;
        }
        
        // Is there a table prefix?  If not, no need to insert it
        if ($this->dbprefix != '')
        {
            // Do we prefix an item with no segments?
            if ($prefix_single == TRUE AND substr($item, 0, strlen($this->dbprefix)) != $this->dbprefix)
            {
                $item = $this->dbprefix.$item;
            }        
        }
        
        if ($protect_identifiers === TRUE AND ! in_array($item, $this->_reserved_identifiers))
        {
            $item = $this->_escape_identifiers($item);
        }
        
        return $item.$alias;
    }




Theme © iAndrew 2016 - Forum software by © MyBB