Monday, January 14, 2008 22:51:22
F:\xampp\htdocs\Zend\Db\Table\Abstract.phpF:\library\Zend\library\Zend\Db\Table\Abstract.php
11<?php
22 
33/**
44 * Zend Framework
55 *
66 * LICENSE
77 *
88 * This source file is subject to the new BSD license that is bundled
99 * with this package in the file LICENSE.txt.
1010 * It is also available through the world-wide-web at this URL:
1111 * http://framework.zend.com/license/new-bsd
1212 * If you did not receive a copy of the license and are unable to
1313 * obtain it through the world-wide-web, please send an email
1414 * to license@zend.com so we can send you a copy immediately.
1515 *
1616 * @category Zend
1717 * @package Zend_Db
1818 * @subpackage Table
1919 * @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
2020 * @license http://framework.zend.com/license/new-bsd New BSD License
2121 * @version $Id: Abstract.php 6748 2007-11-06 01:46:25Z peptolab $
2222 */
2323 
2424/**
2525 * @see Zend_Db_Adapter_Abstract
2626 */
2727require_once 'Zend/Db/Adapter/Abstract.php';
2828 
2929/**
3030 * @see Zend_Db
3131 */
3232require_once 'Zend/Db.php';
3333 
3434/**
3535 * Class for SQL table interface.
3636 *
3737 * @category Zend
3838 * @package Zend_Db
3939 * @subpackage Table
4040 * @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
4141 * @license http://framework.zend.com/license/new-bsd New BSD License
4242 */
4343abstract class Zend_Db_Table_Abstract
4444{
4545 
4646    const ADAPTER = 'db';
4747    const SCHEMA = 'schema';
4848    const NAME = 'name';
4949    const PRIMARY = 'primary';
5050    const COLS = 'cols';
5151    const METADATA = 'metadata';
5252    const METADATA_CACHE = 'metadataCache';
5353    const ROW_CLASS = 'rowClass';
5454    const ROWSET_CLASS = 'rowsetClass';
5555    const REFERENCE_MAP = 'referenceMap';
5656    const DEPENDENT_TABLES = 'dependentTables';
5757    const SEQUENCE = 'sequence';
5858 
5959    const COLUMNS = 'columns';
6060    const REF_TABLE_CLASS = 'refTableClass';
6161    const REF_COLUMNS = 'refColumns';
6262    const ON_DELETE = 'onDelete';
6363    const ON_UPDATE = 'onUpdate';
6464 
6565    const CASCADE = 'cascade';
6666    const RESTRICT = 'restrict';
6767    const SET_NULL = 'setNull';
6868 
6969    /**
7070     * Default Zend_Db_Adapter_Abstract object.
7171     *
7272     * @var Zend_Db_Adapter_Abstract
7373     */
7474    protected static $_defaultDb;
7575 
7676    /**
7777     * Default cache for information provided by the adapter's describeTable() method.
7878     *
7979     * @var Zend_Cache_Core
8080     */
8181    protected static $_defaultMetadataCache = null;
8282 
8383    /**
8484     * Zend_Db_Adapter_Abstract object.
8585     *
8686     * @var Zend_Db_Adapter_Abstract
8787     */
8888    protected $_db;
8989 
9090    /**
9191     * The schema name (default null means current schema)
9292     *
9393     * @var array
9494     */
9595    protected $_schema = null;
9696 
9797    /**
9898     * The table name.
9999     *
100100     * @var array
101101     */
102102    protected $_name = null;
103103 
104104    /**
105105     * The table column names derived from Zend_Db_Adapter_Abstract::describeTable().
106106     *
107107     * @var array
108108     */
109109    protected $_cols;
110110 
111111    /**
112112     * The primary key column or columns.
113113     * A compound key should be declared as an array.
114114     * You may declare a single-column primary key
115115     * as a string.
116116     *
117117     * @var mixed
118118     */
119119    protected $_primary = null;
120120 
121121    /**
122122     * If your primary key is a compound key, and one of the columns uses
123123     * an auto-increment or sequence-generated value, set _identity
124124     * to the ordinal index in the $_primary array for that column.
125125     * Note this index is the position of the column in the primary key,
126126     * not the position of the column in the table. The primary key
127127     * array is 1-based.
128128     *
129129     * @var integer
130130     */
131131    protected $_identity = 1;
132132 
133133    /**
134134     * Define the logic for new values in the primary key.
135135     * May be a string, boolean true, or boolean false.
136136     *
137137     * @var mixed
138138     */
139139    protected $_sequence = true;
140140 
141141    /**
142142     * Information provided by the adapter's describeTable() method.
143143     *
144144     * @var array
145145     */
146146    protected $_metadata = array();
147147 
148148    /**
149149     * Cache for information provided by the adapter's describeTable() method.
150150     *
151151     * @var Zend_Cache_Core
152152     */
153153    protected $_metadataCache = null;
154154 
155155    /**
156156     * Classname for row
157157     *
158158     * @var string
159159     */
160160    protected $_rowClass = 'Zend_Db_Table_Row';
161161 
162162    /**
163163     * Classname for rowset
164164     *
165165     * @var string
166166     */
167167    protected $_rowsetClass = 'Zend_Db_Table_Rowset';
168168 
169169    /**
170170     * Associative array map of declarative referential integrity rules.
171171     * This array has one entry per foreign key in the current table.
172172     * Each key is a mnemonic name for one reference rule.
173173     *
174174     * Each value is also an associative array, with the following keys:
175175     * - columns = array of names of column(s) in the child table.
176176     * - refTableClass = class name of the parent table.
177177     * - refColumns = array of names of column(s) in the parent table,
178178     * in the same order as those in the 'columns' entry.
179179     * - onDelete = "cascade" means that a delete in the parent table also
180180     * causes a delete of referencing rows in the child table.
181181     * - onUpdate = "cascade" means that an update of primary key values in
182182     * the parent table also causes an update of referencing
183183     * rows in the child table.
184184     *
185185     * @var array
186186     */
187187    protected $_referenceMap = array();
188188 
189189    /**
190190     * Simple array of class names of tables that are "children" of the current
191191     * table, in other words tables that contain a foreign key to this one.
192192     * Array elements are not table names; they are class names of classes that
193193     * extend Zend_Db_Table_Abstract.
194194     *
195195     * @var array
196196     */
197197    protected $_dependentTables = array();
198198    
199199    /**
200     * Define if use default values from databese 
201     * 
202     * @var bool 
203     */ 
204    protected $_useDefaultValues = true ; 
205  
206    /** 
207200     * Constructor.
208201     *
209202     * Supported params for $config are:
210203     * - db = user-supplied instance of database connector,
211204     * or key name of registry instance.
212205     * - name = table name.
213206     * - primary = string or array of primary key(s).
214207     * - rowClass = row class name.
215208     * - rowsetClass = rowset class name.
216209     * - referenceMap = array structure to declare relationship
217210     * to parent tables.
218211     * - dependentTables = array of child tables.
219212     * - metadataCache = cache for information from adapter describeTable().
220213     *
221214     * @param mixed $config Array of user-specified config options, or just the Db Adapter.
222215     * @return void
223216     */
224217    public function __construct($config = array())
225218    {
226219        /**
227220         * Allow a scalar argument to be the Adapter object or Registry key.
228221         */
229222        if (!is_array($config)) {
230223            $config = array(self::ADAPTER => $config);
231224        }
232225 
233226        foreach ($config as $key => $value) {
234227            switch ($key) {
235228                case self::ADAPTER:
236229                    $this->_setAdapter($value);
237230                    break;
238231                case self::SCHEMA:
239232                    $this->_schema = (string) $value;
240233                    break;
241234                case self::NAME:
242235                    $this->_name = (string) $value;
243236                    break;
244237                case self::PRIMARY:
245238                    $this->_primary = (array) $value;
246239                    break;
247240                case self::ROW_CLASS:
248241                    $this->setRowClass($value);
249242                    break;
250243                case self::ROWSET_CLASS:
251244                    $this->setRowsetClass($value);
252245                    break;
253246                case self::REFERENCE_MAP:
254247                    $this->setReferences($value);
255248                    break;
256249                case self::DEPENDENT_TABLES:
257250                    $this->setDependentTables($value);
258251                    break;
259252                case self::METADATA_CACHE:
260253                    $this->_setMetadataCache($value);
261254                    break;
262255                case self::SEQUENCE:
263256                    $this->_setSequence($value);
264257                    break;
265258                default:
266259                    // ignore unrecognized configuration directive
267260                    break;
268261            }
269262        }
270263 
271264        $this->_setup();
272265    }
273266 
274267    /**
275268     * @param string $classname
276269     * @return Zend_Db_Table_Abstract Provides a fluent interface
277270     */
278271    public function setRowClass($classname)
279272    {
280273        $this->_rowClass = (string) $classname;
281274 
282275        return $this;
283276    }
284277 
285278    /**
286279     * @return string
287280     */
288281    public function getRowClass()
289282    {
290283        return $this->_rowClass;
291284    }
292285 
293286    /**
294287     * @param string $classname
295288     * @return Zend_Db_Table_Abstract Provides a fluent interface
296289     */
297290    public function setRowsetClass($classname)
298291    {
299292        $this->_rowsetClass = (string) $classname;
300293 
301294        return $this;
302295    }
303296 
304297    /**
305298     * @return string
306299     */
307300    public function getRowsetClass()
308301    {
309302        return $this->_rowsetClass;
310303    }
311304 
312305    /**
313306     * @param array $referenceMap
314307     * @return Zend_Db_Table_Abstract Provides a fluent interface
315308     */
316309    public function setReferences(array $referenceMap)
317310    {
318311        $this->_referenceMap = $referenceMap;
319312 
320313        return $this;
321314    }
322315 
323316    /**
324317     * @param string $tableClassname
325318     * @param string $ruleKey OPTIONAL
326319     * @return array
327320     * @throws Zend_Db_Table_Exception
328321     */
329322    public function getReference($tableClassname, $ruleKey = null)
330323    {
331324        $thisClass = get_class($this);
332325        $refMap = $this->_getReferenceMapNormalized();
333326        if ($ruleKey !== null) {
334327            if (!isset($refMap[$ruleKey])) {
335328                require_once "Zend/Db/Table/Exception.php";
336329                throw new Zend_Db_Table_Exception("No reference rule \"$ruleKey\" from table $thisClass to table $tableClassname");
337330            }
338331            if ($refMap[$ruleKey][self::REF_TABLE_CLASS] != $tableClassname) {
339332                require_once "Zend/Db/Table/Exception.php";
340333                throw new Zend_Db_Table_Exception("Reference rule \"$ruleKey\" does not reference table $tableClassname");
341334            }
342335            return $refMap[$ruleKey];
343336        }
344337        foreach ($refMap as $reference) {
345338            if ($reference[self::REF_TABLE_CLASS] == $tableClassname) {
346339                return $reference;
347340            }
348341        }
349342        require_once "Zend/Db/Table/Exception.php";
350343        throw new Zend_Db_Table_Exception("No reference from table $thisClass to table $tableClassname");
351344    }
352345 
353346    /**
354347     * @param array $dependentTables
355348     * @return Zend_Db_Table_Abstract Provides a fluent interface
356349     */
357350    public function setDependentTables(array $dependentTables)
358351    {
359352        $this->_dependentTables = $dependentTables;
360353 
361354        return $this;
362355    }
363356 
364357    /**
365358     * @return array
366359     */
367360    public function getDependentTables()
368361    {
369362        return $this->_dependentTables;
370363    }
371364 
372365    /**
373366     * Sets the default Zend_Db_Adapter_Abstract for all Zend_Db_Table objects.
374367     *
375368     * @param mixed $db Either an Adapter object, or a string naming a Registry key
376369     * @return void
377370     */
378371    public static final function setDefaultAdapter($db = null)
379372    {
380373        Zend_Db_Table_Abstract::$_defaultDb = self::_setupAdapter($db);
381374    }
382375 
383376    /**
384377     * Gets the default Zend_Db_Adapter_Abstract for all Zend_Db_Table objects.
385378     *
386379     * @return Zend_Db_Adapter_Abstract or null
387380     */
388381    public static final function getDefaultAdapter()
389382    {
390383        return self::$_defaultDb;
391384    }
392385 
393386    /**
394387     * @param mixed $db Either an Adapter object, or a string naming a Registry key
395388     * @return Zend_Db_Table_Abstract Provides a fluent interface
396389     */
397390    protected final function _setAdapter($db)
398391    {
399392        $this->_db = self::_setupAdapter($db);
400393        return $this;
401394    }
402395 
403396    /**
404397     * Gets the Zend_Db_Adapter_Abstract for this particular Zend_Db_Table object.
405398     *
406399     * @return Zend_Db_Adapter_Abstract
407400     */
408401    public final function getAdapter()
409402    {
410403        return $this->_db;
411404    }
412405 
413406    /**
414407     * @param mixed $db Either an Adapter object, or a string naming a Registry key
415408     * @return Zend_Db_Adapter_Abstract
416409     * @throws Zend_Db_Table_Exception
417410     */
418411    protected static final function _setupAdapter($db)
419412    {
420413        if ($db === null) {
421414            return null;
422415        }
423416        if (is_string($db)) {
424417            require_once 'Zend/Registry.php';
425418            $db = Zend_Registry::get($db);
426419        }
427420        if (!$db instanceof Zend_Db_Adapter_Abstract) {
428421            require_once 'Zend/Db/Table/Exception.php';
429422            throw new Zend_Db_Table_Exception('Argument must be of type Zend_Db_Adapter_Abstract, or a Registry key where a Zend_Db_Adapter_Abstract object is stored');
430423        }
431424        return $db;
432425    }
433426 
434427    /**
435428     * Sets the default metadata cache for information returned by Zend_Db_Adapter_Abstract::describeTable().
436429     *
437430     * If $defaultMetadataCache is null, then no metadata cache is used by default.
438431     *
439432     * @param mixed $metadataCache Either a Cache object, or a string naming a Registry key
440433     * @return void
441434     */
442435    public static function setDefaultMetadataCache($metadataCache = null)
443436    {
444437        self::$_defaultMetadataCache = self::_setupMetadataCache($metadataCache);
445438    }
446439 
447440    /**
448441     * Gets the default metadata cache for information returned by Zend_Db_Adapter_Abstract::describeTable().
449442     *
450443     * @return Zend_Cache_Core or null
451444     */
452445    public static function getDefaultMetadataCache()
453446    {
454447        return self::$_defaultMetadataCache;
455448    }
456449 
457450    /**
458451     * Sets the metadata cache for information returned by Zend_Db_Adapter_Abstract::describeTable().
459452     *
460453     * If $metadataCache is null, then no metadata cache is used. Since there is no opportunity to reload metadata
461454     * after instantiation, this method need not be public, particularly because that it would have no effect
462455     * results in unnecessary API complexity. To configure the metadata cache, use the metadataCache configuration
463456     * option for the class constructor upon instantiation.
464457     *
465458     * @param mixed $metadataCache Either a Cache object, or a string naming a Registry key
466459     * @return Zend_Db_Table_Abstract Provides a fluent interface
467460     */
468461    protected function _setMetadataCache($metadataCache)
469462    {
470463        $this->_metadataCache = self::_setupMetadataCache($metadataCache);
471464        return $this;
472465    }
473466 
474467    /**
475468     * Gets the metadata cache for information returned by Zend_Db_Adapter_Abstract::describeTable().
476469     *
477470     * @return Zend_Cache_Core or null
478471     */
479472    public function getMetadataCache()
480473    {
481474        return $this->_metadataCache;
482475    }
483476 
484477    /**
485478     * @param mixed $metadataCache Either a Cache object, or a string naming a Registry key
486479     * @return Zend_Cache_Core
487480     * @throws Zend_Db_Table_Exception
488481     */
489482    protected static final function _setupMetadataCache($metadataCache)
490483    {
491484        if ($metadataCache === null) {
492485            return null;
493486        }
494487        if (is_string($metadataCache)) {
495488            require_once 'Zend/Registry.php';
496489            $metadataCache = Zend_Registry::get($metadataCache);
497490        }
498491        if (!$metadataCache instanceof Zend_Cache_Core) {
499492            require_once 'Zend/Db/Table/Exception.php';
500493            throw new Zend_Db_Table_Exception('Argument must be of type Zend_Cache_Core, or a Registry key where a Zend_Cache_Core object is stored');
501494        }
502495        return $metadataCache;
503496    }
504497 
505498    /**
506499     * Sets the sequence member, which defines the behavior for generating
507500     * primary key values in new rows.
508501     * - If this is a string, then the string names the sequence object.
509502     * - If this is boolean true, then the key uses an auto-incrementing
510503     * or identity mechanism.
511504     * - If this is boolean false, then the key is user-defined.
512505     * Use this for natural keys, for example.
513506     *
514507     * @param mixed $sequence
515508     * @return Zend_Db_Table_Adapter_Abstract Provides a fluent interface
516509     */
517510    protected function _setSequence($sequence)
518511    {
519512        $this->_sequence = $sequence;
520513 
521514        return $this;
522515    }
523516 
524517    /**
525518     * Turnkey for initialization of a table object.
526519     * Calls other protected methods for individual tasks, to make it easier
527520     * for a subclass to override part of the setup logic.
528521     *
529522     * @return void
530523     */
531524    protected function _setup()
532525    {
533526        $this->_setupDatabaseAdapter();
534527        $this->_setupTableName();
535528        $this->_setupMetadata();
536529        $this->_setupPrimaryKey();
537530    }
538531 
539532    /**
540533     * Initialize database adapter.
541534     *
542535     * @return void
543536     */
544537    protected function _setupDatabaseAdapter()
545538    {
546539        if (! $this->_db) {
547540            $this->_db = self::getDefaultAdapter();
548541        }
549542    }
550543 
551544    /**
552545     * Initialize table and schema names.
553546     *
554547     * If the table name is not set in the class definition,
555548     * use the class name itself as the table name.
556549     *
557550     * A schema name provided with the table name (e.g., "schema.table") overrides
558551     * any existing value for $this->_schema.
559552     *
560553     * @return void
561554     */
562555    protected function _setupTableName()
563556    {
564557        if (! $this->_name) {
565558            $this->_name = get_class($this);
566559        } else if (strpos($this->_name, '.')) {
567560            list($this->_schema, $this->_name) = explode('.', $this->_name);
568561        }
569562    }
570563 
571564    /**
572565     * Initializes metadata.
573566     *
574567     * If metadata cannot be loaded from cache, adapter's describeTable() method is called to discover metadata
575568     * information. Returns true if and only if the metadata are loaded from cache.
576569     *
577570     * @return boolean
578571     * @throws Zend_Db_Table_Exception
579572     */
580573    protected function _setupMetadata()
581574    {
582575        // Assume that metadata will be loaded from cache
583576        $isMetadataFromCache = true;
584577 
585578        // If $this has no metadata cache but the class has a default metadata cache
586579        if (null === $this->_metadataCache && null !== self::$_defaultMetadataCache) {
587580            // Make $this use the default metadata cache of the class
588581            $this->_setMetadataCache(self::$_defaultMetadataCache);
589582        }
590583 
591584        // If $this has a metadata cache
592585        if (null !== $this->_metadataCache) {
593586            // Define the cache identifier where the metadata are saved
594587            $cacheId = md5("$this->_schema.$this->_name");
595588        }
596589 
597590        // If $this has no metadata cache or metadata cache misses
598591        if (null === $this->_metadataCache || !($metadata = $this->_metadataCache->load($cacheId))) {
599592            // Metadata are not loaded from cache
600593            $isMetadataFromCache = false;
601594            // Fetch metadata from the adapter's describeTable() method
602595            $metadata = $this->_db->describeTable($this->_name, $this->_schema);
603596            // If $this has a metadata cache, then cache the metadata
604597            if (null !== $this->_metadataCache && !$this->_metadataCache->save($metadata, $cacheId)) {
605598                /**
606599                 * @see Zend_Db_Table_Exception
607600                 */
608601                require_once 'Zend/Db/Table/Exception.php';
609602                throw new Zend_Db_Table_Exception('Failed saving metadata to metadataCache');
610603            }
611604        }
612605 
613606        // Assign the metadata to $this
614607        $this->_metadata = $metadata;
615608 
616609        // Update the columns
617610        $this->_cols = array_keys($this->_metadata);
618611 
619612        // Return whether the metadata were loaded from cache
620613        return $isMetadataFromCache;
621614    }
622615 
623616    /**
624617     * Initialize primary key from metadata.
625618     * If $_primary is not defined, discover primary keys
626619     * from the information returned by describeTable().
627620     *
628621     * @return void
629622     * @throws Zend_Db_Table_Exception
630623     */
631624    protected function _setupPrimaryKey()
632625    {
633626        if (!$this->_primary) {
634627            $this->_primary = array();
635628            foreach ($this->_metadata as $col) {
636629                if ($col['PRIMARY']) {
637630                    $this->_primary[ $col['PRIMARY_POSITION'] ] = $col['COLUMN_NAME'];
638631                    if ($col['IDENTITY']) {
639632                        $this->_identity = $col['PRIMARY_POSITION'];
640633                    }
641634                }
642635            }
643636            // if no primary key was specified and none was found in the metadata
644637            // then throw an exception.
645638            if (empty($this->_primary)) {
646639                require_once 'Zend/Db/Table/Exception.php';
647640                throw new Zend_Db_Table_Exception('A table must have a primary key, but none was found');
648641            }
649642        } else if (!is_array($this->_primary)) {
650643            $this->_primary = array(1 => $this->_primary);
651644        } else if (isset($this->_primary[0])) {
652645            array_unshift($this->_primary, null);
653646            unset($this->_primary[0]);
654647        }
655648 
656649        if (! array_intersect((array) $this->_primary, $this->_cols) == (array) $this->_primary) {
657650            require_once 'Zend/Db/Table/Exception.php';
658651            throw new Zend_Db_Table_Exception("Primary key column(s) ("
659652                . implode(',', (array) $this->_primary)
660653                . ") are not columns in this table ("
661654                . implode(',', $this->_cols)
662655                . ")");
663656        }
664657 
665658        $primary = (array) $this->_primary;
666659        $pkIdentity = $primary[(int) $this->_identity];
667660 
668661        /**
669662         * Special case for PostgreSQL: a SERIAL key implicitly uses a sequence
670663         * object whose name is "<table>_<column>_seq".
671664         */
672665        if ($this->_sequence === true && $this->_db instanceof Zend_Db_Adapter_Pdo_Pgsql) {
673666            $this->_sequence = "{$this->_name}_{$pkIdentity}_seq";
674667            if ($this->_schema) {
675668                $this->_sequence = $this->_schema . '.' . $this->_sequence;
676669            }
677670        }
678671    }
679672 
680673    /**
681674     * Returns a normalized version of the reference map
682675     *
683676     * @return array
684677     */
685678    protected function _getReferenceMapNormalized()
686679    {
687680        $referenceMapNormalized = array();
688681 
689682        foreach ($this->_referenceMap as $rule => $map) {
690683 
691684            $referenceMapNormalized[$rule] = array();
692685 
693686            foreach ($map as $key => $value) {
694687                switch ($key) {
695688 
696689                    // normalize COLUMNS and REF_COLUMNS to arrays
697690                    case self::COLUMNS:
698691                    case self::REF_COLUMNS:
699692                        if (!is_array($value)) {
700693                            $referenceMapNormalized[$rule][$key] = array($value);
701694                        } else {
702695                            $referenceMapNormalized[$rule][$key] = $value;
703696                        }
704697                        break;
705698 
706699                    // other values are copied as-is
707700                    default:
708701                        $referenceMapNormalized[$rule][$key] = $value;
709702                        break;
710703                }
711704            }
712705        }
713706 
714707        return $referenceMapNormalized;
715708    }
716709 
717710    /**
718     * sets the use defaults property 
719     * 
720     * @param bool $value 
721     */ 
722    public function setUseDefaultValues($value) 
723    { 
724        $this->_useDefaultValues = $value; 
725    } 
726     
727    /** 
728     * get the use defaults property 
729     * 
730     * @return bool 
731     */ 
732    public function getUseDefaultValues() 
733    { 
734        return $this->_useDefaultValues; 
735    } 
736     
737    /** 
738711     * Returns table information.
739712     *
740713     * @return array
741714     */
742715    public function info()
743716    {
744717        return array(
745718            self::SCHEMA => $this->_schema,
746719            self::NAME => $this->_name,
747720            self::COLS => (array) $this->_cols,
748721            self::PRIMARY => (array) $this->_primary,
749722            self::METADATA => $this->_metadata,
750723            self::ROW_CLASS => $this->_rowClass,
751724            self::ROWSET_CLASS => $this->_rowsetClass,
752725            self::REFERENCE_MAP => $this->_referenceMap,
753726            self::DEPENDENT_TABLES => $this->_dependentTables,
754727            self::SEQUENCE => $this->_sequence
755728        );
756729    }
757730 
758731    /**
759732     * Inserts a new row.
760733     *
761734     * @param array $data Column-value pairs.
762735     * @return mixed The primary key of the row inserted.
763736     */
764737    public function insert(array $data)
765738    {
766739        /**
767740         * Zend_Db_Table assumes that if you have a compound primary key
768741         * and one of the columns in the key uses a sequence,
769742         * it's the _first_ column in the compound key.
770743         */
771744        $primary = (array) $this->_primary;
772745        $pkIdentity = $primary[(int)$this->_identity];
773746 
774747        /**
775748         * If this table uses a database sequence object and the data does not
776749         * specify a value, then get the next ID from the sequence and add it
777750         * to the row. We assume that only the first column in a compound
778751         * primary key takes a value from a sequence.
779752         */
780753        if (is_string($this->_sequence) && !isset($data[$pkIdentity])) {
781754            $data[$pkIdentity] = $this->_db->nextSequenceId($this->_sequence);
782755        }
783756 
784757        /**
785758         * If the primary key can be generated automatically, and no value was
786759         * specified in the user-supplied data, then omit it from the tuple.
787760         */
788761        if (array_key_exists($pkIdentity, $data) && $data[$pkIdentity] === null) {
789762            unset($data[$pkIdentity]);
790763        }
791  
792        /** 
793         * Use defauls 
794         */ 
795         
796        if($this->getUseDefaultValues()== true) { 
797            $defaults= array(); 
798            $primary = (array)$this->_primary; 
799            foreach ($this->_cols as $col) { 
800                if (in_array($col, $primary)) { 
801                    $defaults[$col] = null; 
802                } 
803                else if (isset($this->_metadata[$col]) && array_key_exists('DEFAULT', $this->_metadata[$col])) { 
804                    $defaults[$col] = new Zend_Db_Expr('DEFAULT'); 
805                } 
806             } 
807             $data= array_merge($defaults,$data); 
808        } 
809         
810764        
811765        /**
812766         * INSERT the new row.
813767         */
814768        $tableSpec = ($this->_schema ? $this->_schema . '.' : '') . $this->_name;
815769        $this->_db->insert($tableSpec, $data);
816770 
817771        /**
818772         * Fetch the most recent ID generated by an auto-increment
819773         * or IDENTITY column, unless the user has specified a value,
820774         * overriding the auto-increment mechanism.
821775         */
822776        if ($this->_sequence === true && !isset($data[$pkIdentity])) {
823777            $data[$pkIdentity] = $this->_db->lastInsertId();
824778        }
825779 
826780        /**
827781         * Return the primary key value if the PK is a single column,
828782         * else return an associative array of the PK column/value pairs.
829783         */
830784        $pkData = array_intersect_key($data, array_flip($primary));
831785        if (count($primary) == 1) {
832786            return current($pkData);
833787        } else {
834788            return $pkData;
835789        }
836790 
837791        /**
838792         * The last case: the user did not specify a value for the primary
839793         * key, nor is this table class declared to use an auto-increment key.
840794         * Since the insert did not fail, we can assume this is one of the edge
841795         * cases, which may include:
842796         * - the table has no primary key defined;
843797         * - the database table uses a trigger to set a primary key value;
844798         * - the RDBMS permits primary keys to be NULL or have a value set
845799         * to the column's DEFAULT
846800         */
847801        return null;
848802    }
849803 
850804    /**
851805     * Updates existing rows.
852806     *
853807     * @param array $data Column-value pairs.
854808     * @param array|string $where An SQL WHERE clause, or an array of SQL WHERE clauses.
855809     * @return int The number of rows updated.
856810     */
857811    public function update(array $data, $where)
858812    {
859813        $tableSpec = ($this->_schema ? $this->_schema . '.' : '') . $this->_name;
860814        return $this->_db->update($tableSpec, $data, $where);
861815    }
862816 
863817    /**
864818     * Called by a row object for the parent table's class during save() method.
865819     *
866820     * @param string $parentTableClassname
867821     * @param array $oldPrimaryKey
868822     * @param array $newPrimaryKey
869823     * @return int
870824     */
871825    public function _cascadeUpdate($parentTableClassname, array $oldPrimaryKey, array $newPrimaryKey)
872826    {
873827        $rowsAffected = 0;
874828        foreach ($this->_getReferenceMapNormalized() as $rule => $map) {
875829            if ($map[self::REF_TABLE_CLASS] == $parentTableClassname && isset($map[self::ON_UPDATE])) {
876830                switch ($map[self::ON_UPDATE]) {
877831                    case self::CASCADE:
878832                        $newRefs = array();
879833                        for ($i = 0; $i < count($map[self::COLUMNS]); ++$i) {
880834                            $col = $this->_db->foldCase($map[self::COLUMNS][$i]);
881835                            $refCol = $this->_db->foldCase($map[self::REF_COLUMNS][$i]);
882836                            if (array_key_exists($refCol, $newPrimaryKey)) {
883837                                $newRefs[$col] = $newPrimaryKey[$refCol];
884838                            }
885839                            $type = $this->_metadata[$col]['DATA_TYPE'];
886840                            $where[] = $this->_db->quoteInto(
887841                                $this->_db->quoteIdentifier($col, true) . ' = ?',
888842                                $oldPrimaryKey[$refCol], $type);
889843                        }
890844                        $rowsAffected += $this->update($newRefs, $where);
891845                        break;
892846                    default:
893847                        // no action
894848                        break;
895849                }
896850            }
897851        }
898852        return $rowsAffected;
899853    }
900854 
901855    /**
902856     * Deletes existing rows.
903857     *
904858     * @param array|string $where SQL WHERE clause(s).
905859     * @return int The number of rows deleted.
906860     */
907861    public function delete($where)
908862    {
909863        $tableSpec = ($this->_schema ? $this->_schema . '.' : '') . $this->_name;
910864        return $this->_db->delete($tableSpec, $where);
911865    }
912866 
913867    /**
914868     * Called by parent table's class during delete() method.
915869     *
916870     * @param string $parentTableClassname
917871     * @param array $primaryKey
918872     * @return int Number of affected rows
919873     */
920874    public function _cascadeDelete($parentTableClassname, array $primaryKey)
921875    {
922876        $rowsAffected = 0;
923877        foreach ($this->_getReferenceMapNormalized() as $rule => $map) {
924878            if ($map[self::REF_TABLE_CLASS] == $parentTableClassname && isset($map[self::ON_DELETE])) {
925879                switch ($map[self::ON_DELETE]) {
926880                    case self::CASCADE:
927881                        for ($i = 0; $i < count($map[self::COLUMNS]); ++$i) {
928882                            $col = $this->_db->foldCase($map[self::COLUMNS][$i]);
929883                            $refCol = $this->_db->foldCase($map[self::REF_COLUMNS][$i]);
930884                            $type = $this->_metadata[$col]['DATA_TYPE'];
931885                            $where[] = $this->_db->quoteInto(
932886                                $this->_db->quoteIdentifier($col, true) . ' = ?',
933887                                $primaryKey[$refCol], $type);
934888                        }
935889                        $rowsAffected += $this->delete($where);
936890                        break;
937891                    default:
938892                        // no action
939893                        break;
940894                }
941895            }
942896        }
943897        return $rowsAffected;
944898    }
945899 
946900    /**
947901     * Fetches rows by primary key. The argument specifies one or more primary
948902     * key value(s). To find multiple rows by primary key, the argument must
949903     * be an array.
950904     *
951905     * This method accepts a variable number of arguments. If the table has a
952906     * multi-column primary key, the number of arguments must be the same as
953907     * the number of columns in the primary key. To find multiple rows in a
954908     * table with a multi-column primary key, each argument must be an array
955909     * with the same number of elements.
956910     *
957911     * The find() method always returns a Rowset object, even if only one row
958912     * was found.
959913     *
960914     * @param mixed $key The value(s) of the primary keys.
961915     * @return Zend_Db_Table_Rowset_Abstract Row(s) matching the criteria.
962916     * @throws Zend_Db_Table_Exception
963917     */
964918    public function find($key)
965919    {
966920        $args = func_get_args();
967921        $keyNames = array_values((array) $this->_primary);
968922 
969923        if (count($args) < count($keyNames)) {
970924            require_once 'Zend/Db/Table/Exception.php';
971925            throw new Zend_Db_Table_Exception("Too few columns for the primary key");
972926        }
973927 
974928        if (count($args) > count($keyNames)) {
975929            require_once 'Zend/Db/Table/Exception.php';
976930            throw new Zend_Db_Table_Exception("Too many columns for the primary key");
977931        }
978932 
979933        $whereList = array();
980934        $numberTerms = 0;
981935        foreach ($args as $keyPosition => $keyValues) {
982936            // Coerce the values to an array.
983937            // Don't simply typecast to array, because the values
984938            // might be Zend_Db_Expr objects.
985939            if (!is_array($keyValues)) {
986940                $keyValues = array($keyValues);
987941            }
988942            if ($numberTerms == 0) {
989943                $numberTerms = count($keyValues);
990944            } else if (count($keyValues) != $numberTerms) {
991945                require_once 'Zend/Db/Table/Exception.php';
992946                throw new Zend_Db_Table_Exception("Missing value(s) for the primary key");
993947            }
994948            for ($i = 0; $i < count($keyValues); ++$i) {
995949                $whereList[$i][$keyPosition] = $keyValues[$i];
996950            }
997951        }
998952 
999953        $whereClause = null;
1000954        if (count($whereList)) {
1001955            $whereOrTerms = array();
1002956            foreach ($whereList as $keyValueSets) {
1003957                $whereAndTerms = array();
1004958                foreach ($keyValueSets as $keyPosition => $keyValue) {
1005959                    $type = $this->_metadata[$keyNames[$keyPosition]]['DATA_TYPE'];
1006960                    $whereAndTerms[] = $this->_db->quoteInto(
1007961                        $this->_db->quoteIdentifier($keyNames[$keyPosition], true) . ' = ?',
1008962                        $keyValue, $type);
1009963                }
1010964                $whereOrTerms[] = '(' . implode(' AND ', $whereAndTerms) . ')';
1011965            }
1012966            $whereClause = '(' . implode(' OR ', $whereOrTerms) . ')';
1013967        }
1014968 
1015969        return $this->fetchAll($whereClause);
1016970    }
1017971 
1018972    /**
1019973     * Fetches all rows.
1020974     *
1021975     * Honors the Zend_Db_Adapter fetch mode.
1022976     *
1023977     * @param string|array $where OPTIONAL An SQL WHERE clause.
1024978     * @param string|array $order OPTIONAL An SQL ORDER clause.
1025979     * @param int $count OPTIONAL An SQL LIMIT count.
1026980     * @param int $offset OPTIONAL An SQL LIMIT offset.
1027981     * @return Zend_Db_Table_Rowset_Abstract The row results per the Zend_Db_Adapter fetch mode.
1028982     */
1029983    public function fetchAll($where = null, $order = null, $count = null, $offset = null)
1030984    {
1031985        $data = array(
1032986            'table' => $this,
1033987            'data' => $this->_fetch($where, $order, $count, $offset),
1034988            'rowClass' => $this->_rowClass,
1035989            'stored' => true
1036990        );
1037991 
1038992        Zend_Loader::loadClass($this->_rowsetClass);
1039993        return new $this->_rowsetClass($data);
1040994    }
1041995 
1042996    /**
1043997     * Fetches one row in an object of type Zend_Db_Table_Row_Abstract,
1044998     * or returns null if no row matches the specified criteria.
1045999     *
10461000     * @param string|array $where OPTIONAL An SQL WHERE clause.
10471001     * @param string|array $order OPTIONAL An SQL ORDER clause.
10481002     * @return Zend_Db_Table_Row_Abstract The row results per the
10491003     * Zend_Db_Adapter fetch mode, or null if no row found.
10501004     */
10511005    public function fetchRow($where = null, $order = null)
10521006    {
10531007        $keys = array_values((array) $this->_primary);
10541008        $vals = array_fill(0, count($keys), null);
10551009        $primary = array_combine($keys, $vals);
10561010 
10571011        $rows = $this->_fetch($where, $order, 1);
10581012 
10591013        if (count($rows) == 0) {
10601014            return null;
10611015        }
10621016 
10631017        $data = array(
10641018            'table' => $this,
10651019            'data' => $rows[0],
10661020            'stored' => true
10671021        );
10681022 
10691023        Zend_Loader::loadClass($this->_rowClass);
10701024        return new $this->_rowClass($data);
10711025    }
10721026 
10731027    /**
10741028     * Fetches a new blank row (not from the database).
10751029     *
10761030     * @return Zend_Db_Table_Row_Abstract
10771031     * @deprecated since 0.9.3 - use createRow() instead.
10781032     */
10791033    public function fetchNew()
10801034    {
10811035        return $this->createRow();
10821036    }
10831037 
10841038    /**
10851039     * Fetches a new blank row (not from the database).
10861040     *
10871041     * @param array $data OPTIONAL data to populate in the new row.
10881042     * @return Zend_Db_Table_Row_Abstract
10891043     */
10901044    public function createRow(array $data = array())
10911045    {
10921046        $defaults = array_combine($this->_cols, array_fill(0, count($this->_cols), null));
10931047        $keys = array_flip($this->_cols);
10941048        $data = array_intersect_key($data, $keys);
10951049        $data = array_merge($defaults, $data);
10961050 
10971051        $config = array(
10981052            'table' => $this,
10991053            'data' => $data,
11001054            'stored' => false
11011055        );
11021056 
11031057        Zend_Loader::loadClass($this->_rowClass);
11041058        return new $this->_rowClass($config);
11051059    }
11061060 
11071061    /**
11081062     * Support method for fetching rows.
11091063     *
11101064     * @param string|array $where OPTIONAL An SQL WHERE clause.
11111065     * @param string|array $order OPTIONAL An SQL ORDER clause.
11121066     * @param int $count OPTIONAL An SQL LIMIT count.
11131067     * @param int $offset OPTIONAL An SQL LIMIT offset.
11141068     * @return array The row results, in FETCH_ASSOC mode.
11151069     */
11161070    protected function _fetch($where = null, $order = null, $count = null, $offset = null)
11171071    {
11181072        // selection tool
11191073        $select = $this->_db->select();
11201074 
11211075        // the FROM clause
11221076        $select->from($this->_name, $this->_cols, $this->_schema);
11231077 
11241078        // the WHERE clause
11251079        $where = (array) $where;
11261080        foreach ($where as $key => $val) {
11271081            // is $key an int?
11281082            if (is_int($key)) {
11291083                // $val is the full condition
11301084                $select->where($val);
11311085            } else {
11321086                // $key is the condition with placeholder,
11331087                // and $val is quoted into the condition
11341088                $select->where($key, $val);
11351089            }
11361090        }
11371091 
11381092        // the ORDER clause
11391093        if (!is_array($order)) {
11401094            $order = array($order);
11411095        }
11421096        foreach ($order as $val) {
11431097            $select->order($val);
11441098        }
11451099 
11461100        // the LIMIT clause
11471101        $select->limit($count, $offset);
11481102 
11491103        // return the results
11501104        $stmt = $this->_db->query($select);
11511105        $data = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
11521106        return $data;
11531107    }
11541108 
11551109}
11561110