Issues

ZF-5775: Zend_Db_Table->find() returns all rows when passed empty array

Description

Not sure if this is a bug or a feature; it certainly contradicts the documentation which states: "If you specify multiple values in an array, the method returns at most as many rows as the number of distinct values you specify. "

Suggested fix, if this is not desired behaviour (it's certainly counter-intuitive), is to create & return an empty rowset of the correct class if there are no items in the whereList:


 <?php
      public function find()
    {
        $this->_setupPrimaryKey();
        $args = func_get_args();
        $keyNames = array_values((array) $this->_primary);

        if (count($args) < count($keyNames)) {
            require_once 'Zend/Db/Table/Exception.php';
            throw new Zend_Db_Table_Exception("Too few columns for the primary key");
        }

        if (count($args) > count($keyNames)) {
            require_once 'Zend/Db/Table/Exception.php';
            throw new Zend_Db_Table_Exception("Too many columns for the primary key");
        }

        $whereList = array();
        $numberTerms = 0;
        foreach ($args as $keyPosition => $keyValues) {
            // Coerce the values to an array.
            // Don't simply typecast to array, because the values
            // might be Zend_Db_Expr objects.
            if (!is_array($keyValues)) {
                $keyValues = array($keyValues);
            }
            if ($numberTerms == 0) {
                $numberTerms = count($keyValues);
            } else if (count($keyValues) != $numberTerms) {
                require_once 'Zend/Db/Table/Exception.php';
                throw new Zend_Db_Table_Exception("Missing value(s) for the primary key");
            }
            for ($i = 0; $i < count($keyValues); ++$i) {
                if (!isset($whereList[$i])) {
                    $whereList[$i] = array();
                }
                $whereList[$i][$keyPosition] = $keyValues[$i];
            }
        }

        $whereClause = null;
        if (count($whereList)) {
            $whereOrTerms = array();
            foreach ($whereList as $keyValueSets) {
                $whereAndTerms = array();
                foreach ($keyValueSets as $keyPosition => $keyValue) {
                    $type = $this->_metadata[$keyNames[$keyPosition]]['DATA_TYPE'];
                    $tableName = $this->_db->quoteTableAs($this->_name, null, true);
                    $columnName = $this->_db->quoteIdentifier($keyNames[$keyPosition], true);
                    $whereAndTerms[] = $this->_db->quoteInto(
                        $tableName . '.' . $columnName . ' = ?',
                        $keyValue, $type);
                }
                $whereOrTerms[] = '(' . implode(' AND ', $whereAndTerms) . ')';
            }
            $whereClause = '(' . implode(' OR ', $whereOrTerms) . ')';
            return $this->fetchAll($whereClause);
        }
        else
        {
          $data  = array(
              'table'    => $this,
              'readOnly' => $select->isReadOnly(),
              'rowClass' => $this->_rowClass,
              'stored'   => true
                );

          @Zend_Loader::loadClass($this->_rowsetClass);
          return new $this->_rowsetClass($data);
        }
        
    }

Comments

I'm happy to put together a patch & test for this issue, if I get some guidance as to whether it's a feature or a bug.

Let me know if there's another place I should be asking this kind of question.

Fixed in trunk in r17817, merged to branch release 1.9 in 17818