Changeset 7042
- Timestamp:
- 01/14/08 08:02:39 (2 years ago)
- Files:
-
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/build-propel.xml (modified) (1 diff)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5NestedSetPeerBuilder.php (modified) (4 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5NodeBuilder.php (modified) (2 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5NodePeerBuilder.php (modified) (5 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5ObjectBuilder.php (modified) (14 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5PeerBuilder.php (modified) (22 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/database/model/Table.php (modified) (6 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/phing/PropelConvertConfTask.php (modified) (2 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/phing/PropelDataDumpTask.php (modified) (1 diff)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/projects/bookstore/schema.xml (modified) (6 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/resources/xsd/database.xsd (modified) (1 diff)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/test/classes/propel/GeneratedObjectRelTest.php (modified) (2 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/test/classes/propel/GeneratedObjectTest.php (modified) (8 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/test/classes/propel/util/BasePeerTest.php (modified) (2 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/test/classes/propel/util/CriteriaTest.php (modified) (1 diff)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel/Propel.php (modified) (9 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel/util/BasePeer.php (modified) (8 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel/util/Criteria.php (modified) (6 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel/util/DebugPDO.php (added)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel/util/DebugPDOStatement.php (added)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel/util/PropelPDO.php (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/build-propel.xml
r6506 r7042 477 477 outputDirectory="${propel.phpconf.dir}" 478 478 outputFile="${propel.runtime.phpconf.file}" 479 packageObjectModel="${propel.packageObjectModel}" 479 480 outputClassmapFile="${propel.runtime.phpconf-classmap.file}"> 480 481 <schemafileset dir="${propel.schema.dir}" branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5NestedSetPeerBuilder.php
r6597 r7042 2 2 3 3 /* 4 * $Id: PHP5NestedSetPeerBuilder.php 881 2007-12-19 21:39:50Z heltem$4 * $Id: PHP5NestedSetPeerBuilder.php 905 2008-01-09 04:12:34Z hans $ 5 5 * 6 6 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 949 949 { 950 950 if (\$con === null) { 951 \$con = Propel::getConnection($peerClassname::DATABASE_NAME );951 \$con = Propel::getConnection($peerClassname::DATABASE_NAME, Propel::CONNECTION_READ); 952 952 } 953 953 … … 1512 1512 { 1513 1513 if (\$con === null) { 1514 \$con = Propel::getConnection($peerClassname::DATABASE_NAME );1514 \$con = Propel::getConnection($peerClassname::DATABASE_NAME, Propel::CONNECTION_WRITE); 1515 1515 } 1516 1516 … … 1586 1586 { 1587 1587 if (\$con === null) { 1588 \$con = Propel::getConnection($peerClassname::DATABASE_NAME );1588 \$con = Propel::getConnection($peerClassname::DATABASE_NAME, Propel::CONNECTION_WRITE); 1589 1589 } 1590 1590 branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5NodeBuilder.php
r5662 r7042 2 2 3 3 /* 4 * $Id: PHP5NodeBuilder.php 712 2007-10-24 04:59:30Z gamr$4 * $Id: PHP5NodeBuilder.php 905 2008-01-09 04:12:34Z hans $ 5 5 * 6 6 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 664 664 665 665 if (\$con === null) 666 \$con = Propel::getConnection($peerClassname::DATABASE_NAME );666 \$con = Propel::getConnection($peerClassname::DATABASE_NAME, Propel::CONNECTION_WRITE); 667 667 668 668 try { branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5NodePeerBuilder.php
r6411 r7042 2 2 3 3 /* 4 * $Id: PHP5NodePeerBuilder.php 851 2007-12-05 02:21:29Z hans $4 * $Id: PHP5NodePeerBuilder.php 905 2008-01-09 04:12:34Z hans $ 5 5 * 6 6 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 207 207 { 208 208 if (\$con === null) 209 \$con = Propel::getConnection($peerClassname::DATABASE_NAME );209 \$con = Propel::getConnection($peerClassname::DATABASE_NAME, Propel::CONNECTION_WRITE); 210 210 211 211 try { … … 253 253 { 254 254 if (\$con === null) 255 \$con = Propel::getConnection($peerClassname::DATABASE_NAME );255 \$con = Propel::getConnection($peerClassname::DATABASE_NAME, Propel::CONNECTION_WRITE); 256 256 257 257 try { … … 428 428 429 429 if (\$con === null) 430 \$con = Propel::getConnection($peerClassname::DATABASE_NAME );430 \$con = Propel::getConnection($peerClassname::DATABASE_NAME, Propel::CONNECTION_WRITE); 431 431 432 432 /** … … 497 497 { 498 498 if (\$con === null) 499 \$con = Propel::getConnection($peerClassname::DATABASE_NAME );499 \$con = Propel::getConnection($peerClassname::DATABASE_NAME, Propel::CONNECTION_WRITE); 500 500 501 501 /** branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5ObjectBuilder.php
r6597 r7042 2 2 3 3 /* 4 * $Id: PHP5ObjectBuilder.php 871 2007-12-19 01:50:21Z hans $4 * $Id: PHP5ObjectBuilder.php 920 2008-01-13 22:26:02Z hans $ 5 5 * 6 6 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 207 207 $this->addFKMethods($script); 208 208 $this->addRefFKMethods($script); 209 $this->addClearAllReferences($script); 209 210 } 210 211 … … 605 606 try { 606 607 \$stmt = ".$this->getPeerClassname()."::doSelectStmt(\$c, \$con); 607 \$row = \$stmt->fetch(PDO::FETCH_NUM);"; 608 608 \$row = \$stmt->fetch(PDO::FETCH_NUM); 609 \$stmt->closeCursor();"; 610 609 611 $clo = strtolower($col->getName()); 610 612 if ($col->isLobType() && !$platform->hasStreamBlobImpl()) { … … 1290 1292 1291 1293 if (\$con === null) { 1292 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME );1294 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_WRITE); 1293 1295 } 1294 1296 … … 1335 1337 1336 1338 if (\$con === null) { 1337 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME );1339 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_READ); 1338 1340 } 1339 1341 … … 1343 1345 \$stmt = ".$this->getPeerClassname()."::doSelectStmt(\$this->buildPkeyCriteria(), \$con); 1344 1346 \$row = \$stmt->fetch(PDO::FETCH_NUM); 1347 \$stmt->closeCursor(); 1345 1348 if (!\$row) { 1346 1349 throw new PropelException('Cannot find matching row in the database to reload object values.'); … … 2570 2573 { 2571 2574 $table = $this->getTable(); 2572 2573 $script .= " 2574 /** 2575 * Stores the object in the database. 2575 2576 $reloadOnUpdate = $table->isReloadOnUpdate(); 2577 $reloadOnInsert = $table->isReloadOnInsert(); 2578 2579 $script .= " 2580 /** 2581 * Performs the work of inserting or updating the row in the database. 2576 2582 * 2577 2583 * If the object is new, it inserts it; otherwise an update is performed. 2578 2584 * All related objects are also updated in this method. 2579 2585 * 2580 * @param PropelPDO \$con 2586 * @param PropelPDO \$con"; 2587 if ($reloadOnUpdate || $reloadOnInsert) { 2588 $script .= " 2589 * @param boolean \$skipReload Whether to skip the reload for this object from database."; 2590 } 2591 $script .= " 2581 2592 * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. 2582 2593 * @throws PropelException 2583 2594 * @see save() 2584 2595 */ 2585 protected function doSave(PropelPDO \$con )2596 protected function doSave(PropelPDO \$con".($reloadOnUpdate || $reloadOnInsert ? ", \$skipReload = false" : "").") 2586 2597 { 2587 2598 \$affectedRows = 0; // initialize var to track total num of affected rows … … 2589 2600 \$this->alreadyInSave = true; 2590 2601 "; 2602 if ($reloadOnInsert || $reloadOnUpdate) { 2603 $script .= " 2604 \$reloadObject = false; 2605 "; 2606 } 2591 2607 2592 2608 if (count($table->getForeignKeys())) { 2593 2609 2594 2610 $script .= " 2595 2596 2611 // We call the save method on the following object(s) if they 2597 2612 // were passed to this object by their coresponding set … … 2630 2645 $script .= ") { 2631 2646 if (\$this->isNew()) { 2632 \$pk = ".$this->getPeerClassname()."::doInsert(\$this, \$con); 2647 \$pk = ".$this->getPeerClassname()."::doInsert(\$this, \$con);"; 2648 if ($reloadOnInsert) { 2649 $script .= " 2650 if (!\$skipReload) { 2651 \$reloadObject = true; 2652 }"; 2653 } 2654 $script .= " 2633 2655 \$affectedRows += 1; // we are assuming that there is only 1 row per doInsert() which 2634 2656 // should always be true here (even though technically … … 2650 2672 $script .= " 2651 2673 \$this->setNew(false); 2652 } else { 2674 } else {"; 2675 if ($reloadOnUpdate) { 2676 $script .= " 2677 if (!\$skipReload) { 2678 \$reloadObject = true; 2679 }"; 2680 } 2681 $script .= " 2653 2682 \$affectedRows += ".$this->getPeerClassname()."::doUpdate(\$this, \$con); 2654 2683 } … … 2684 2713 $script .= " 2685 2714 \$this->alreadyInSave = false; 2715 "; 2716 if ($reloadOnInsert || $reloadOnUpdate) { 2717 $script .= " 2718 if (\$reloadObject) { 2719 \$this->reload(\$con); 2720 } 2721 "; 2722 } 2723 $script .= " 2686 2724 } 2687 2725 return \$affectedRows; … … 2713 2751 protected function addSave(&$script) 2714 2752 { 2715 $script .= " 2716 /** 2717 * Stores the object in the database. If the object is new, 2718 * it inserts it; otherwise an update is performed. This method 2719 * wraps the doSave() worker method in a transaction. 2720 * 2721 * @param PropelPDO \$con 2753 $table = $this->getTable(); 2754 $reloadOnUpdate = $table->isReloadOnUpdate(); 2755 $reloadOnInsert = $table->isReloadOnInsert(); 2756 2757 $script .= " 2758 /** 2759 * Persists this object to the database. 2760 * 2761 * If the object is new, it inserts it; otherwise an update is performed. 2762 * All modified related objects will also be persisted in the doSave() 2763 * method. This method wraps all precipitate database operations in a 2764 * single transaction."; 2765 if ($reloadOnUpdate) { 2766 $script .= " 2767 * 2768 * Since this table was configured to reload rows on update, the object will 2769 * be reloaded from the database if an UPDATE operation is performed (unless 2770 * the \$skipReload parameter is TRUE)."; 2771 } 2772 if ($reloadOnInsert) { 2773 $script .= " 2774 * 2775 * Since this table was configured to reload rows on insert, the object will 2776 * be reloaded from the database if an INSERT operation is performed (unless 2777 * the \$skipReload parameter is TRUE)."; 2778 } 2779 $script .= " 2780 * 2781 * @param PropelPDO \$con"; 2782 if ($reloadOnUpdate || $reloadOnInsert) { 2783 $script .= " 2784 * @param boolean \$skipReload Whether to skip the reload for this object from database."; 2785 } 2786 $script .= " 2722 2787 * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. 2723 2788 * @throws PropelException 2724 2789 * @see doSave() 2725 2790 */ 2726 public function save(PropelPDO \$con = null )2791 public function save(PropelPDO \$con = null".($reloadOnUpdate || $reloadOnInsert ? ", \$skipReload = false" : "").") 2727 2792 { 2728 2793 if (\$this->isDeleted()) { … … 2731 2796 2732 2797 if (\$con === null) { 2733 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME );2798 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_WRITE); 2734 2799 } 2735 2800 2736 2801 try { 2737 2802 \$con->beginTransaction(); 2738 \$affectedRows = \$this->doSave(\$con );2803 \$affectedRows = \$this->doSave(\$con".($reloadOnUpdate || $reloadOnInsert ? ", \$skipReload" : "")."); 2739 2804 \$con->commit(); 2740 2805 ".$this->getPeerClassname()."::addInstanceToPool(\$this); … … 3072 3137 } // addCopyInto() 3073 3138 3074 3139 3140 /** 3141 * Adds clearAllReferencers() method which resets all the collections of referencing 3142 * fk objects. 3143 * @param string &$script The script will be modified in this method. 3144 */ 3145 protected function addClearAllReferences(&$script) 3146 { 3147 $table = $this->getTable(); 3148 $script .= " 3149 /** 3150 * Resets all collections of referencing foreign keys. 3151 * 3152 * This method is a user-space workaround for PHP's inability to garbage collect objects 3153 * with circular references. This is currently necessary when using Propel in certain 3154 * daemon or large-volumne/high-memory operations. 3155 * 3156 * @param boolean \$deep Whether to also clear the references on all associated objects. 3157 */ 3158 public function clearAllReferences(\$deep = false) 3159 { 3160 if (\$deep) {"; 3161 $vars = array(); 3162 foreach ($this->getTable()->getReferrers() as $refFK) { 3163 if ($refFK->isLocalPrimaryKey()) { 3164 $varName = $this->getPKRefFKVarName($refFK); 3165 $vars[] = $varName; 3166 $script .= " 3167 \$this->{$varName}->clearAllReferences(\$deep);"; 3168 } else { 3169 $varName = $this->getRefFKCollVarName($refFK); 3170 $vars[] = $varName; 3171 $script .= " 3172 foreach(\$this->$varName as \$o) { 3173 \$o->clearAllReferences(\$deep); 3174 }"; 3175 } 3176 } 3177 3178 $script .= " 3179 } // if (\$deep) 3180 "; 3181 3182 foreach($vars as $varName) { 3183 $script .= " 3184 \$this->$varName = null;"; 3185 } 3186 3187 $script .= " 3188 } 3189 "; 3190 } 3075 3191 3076 3192 } // PHP5ObjectBuilder branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5PeerBuilder.php
r6597 r7042 2 2 3 3 /* 4 * $Id: PHP5PeerBuilder.php 891 2007-12-19 23:09:57Z heltem$4 * $Id: PHP5PeerBuilder.php 917 2008-01-12 19:32:24Z hans $ 5 5 * 6 6 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 519 519 \$stmt = ".$this->getPeerClassname()."::doSelectStmt(\$criteria, \$con); 520 520 if (\$row = \$stmt->fetch(PDO::FETCH_NUM)) { 521 return(int) \$row[0];521 \$count = (int) \$row[0]; 522 522 } else { 523 // no rows returned; we infer that means 0 matches. 524 return 0; 525 } 523 \$count = 0; // no rows returned; we infer that means 0 matches. 524 } 525 \$stmt->closeCursor(); 526 return \$count; 526 527 }"; 527 528 } … … 601 602 { 602 603 if (\$con === null) { 603 \$con = Propel::getConnection( self::DATABASE_NAME);604 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_READ); 604 605 } 605 606 … … 855 856 \$key = ".$this->getPeerClassname()."::getPrimaryKeyHashFromRow(\$row, 0); 856 857 if (null !== (\$obj = ".$this->getPeerClassname()."::getInstanceFromPool(\$key))) { 857 \$obj->hydrate(\$row, 0, true); // rehydrate 858 // We no longer rehydrate the object, since this can cause data loss. 859 // See http://propel.phpdb.org/trac/ticket/509 860 // \$obj->hydrate(\$row, 0, true); // rehydrate 858 861 \$results[] = \$obj; 859 862 } else { … … 878 881 } // if key exists 879 882 } 883 \$stmt->closeCursor(); 880 884 return \$results; 881 885 }"; … … 1022 1026 { 1023 1027 if (\$con === null) { 1024 \$con = Propel::getConnection( self::DATABASE_NAME);1028 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_WRITE); 1025 1029 } 1026 1030 … … 1081 1085 { 1082 1086 if (\$con === null) { 1083 \$con = Propel::getConnection( self::DATABASE_NAME);1087 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_WRITE); 1084 1088 } 1085 1089 … … 1128 1132 { 1129 1133 if (\$con === null) { 1130 \$con = Propel::getConnection( self::DATABASE_NAME);1134 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_WRITE); 1131 1135 } 1132 1136 \$affectedRows = 0; // initialize var to track total num of affected rows … … 1177 1181 { 1178 1182 if (\$con === null) { 1179 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME );1183 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_READ); 1180 1184 } 1181 1185 … … 1550 1554 { 1551 1555 if (\$con === null) { 1552 \$con = Propel::getConnection( self::DATABASE_NAME);1556 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_READ); 1553 1557 } 1554 1558 … … 1600 1604 { 1601 1605 if (\$con === null) { 1602 \$con = Propel::getConnection( self::DATABASE_NAME);1606 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_READ); 1603 1607 } 1604 1608 … … 1669 1673 $script .= ", PropelPDO \$con = null) { 1670 1674 if (\$con === null) { 1671 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME );1675 \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_READ); 1672 1676 } 1673 1677 \$criteria = new Criteria(".$this->getPeerClassname()."::DATABASE_NAME);"; … … 1829 1833 \$key1 = ".$this->getPeerClassname()."::getPrimaryKeyHashFromRow(\$row, 0); 1830 1834 if (null !== (\$obj1 = ".$this->getPeerClassname()."::getInstanceFromPool(\$key1))) { 1831 \$obj1->hydrate(\$row, 0, true); // rehydrate 1835 // We no longer rehydrate the object, since this can cause data loss. 1836 // See http://propel.phpdb.org/trac/ticket/509 1837 // \$obj1->hydrate(\$row, 0, true); // rehydrate 1832 1838 } else { 1833 1839 "; … … 1877 1883 \$results[] = \$obj1; 1878 1884 } 1885 \$stmt->closeCursor(); 1879 1886 return \$results; 1880 1887 } … … 1953 1960 \$stmt = ".$this->getPeerClassname()."::doSelectStmt(\$criteria, \$con); 1954 1961 if (\$row = \$stmt->fetch(PDO::FETCH_NUM)) { 1955 return(int) \$row[0];1962 \$count = (int) \$row[0]; 1956 1963 } else { 1957 // no rows returned; we infer that means 0 matches. 1958 return 0; 1959 } 1964 \$count = 0; // no rows returned; we infer that means 0 matches. 1965 } 1966 \$stmt->closeCursor(); 1967 return \$count; 1960 1968 } 1961 1969 "; … … 2042 2050 \$key1 = ".$this->getPeerClassname()."::getPrimaryKeyHashFromRow(\$row, 0); 2043 2051 if (null !== (\$obj1 = ".$this->getPeerClassname()."::getInstanceFromPool(\$key1))) { 2044 \$obj1->hydrate(\$row, 0, true); // rehydrate 2052 // We no longer rehydrate the object, since this can cause data loss. 2053 // See http://propel.phpdb.org/trac/ticket/509 2054 // \$obj1->hydrate(\$row, 0, true); // rehydrate 2045 2055 } else {"; 2046 2056 … … 2111 2121 2112 2122 // Add the \$obj1 (".$this->getObjectClassname().") to the collection in \$obj".$index." (".$joinedTablePeerBuilder->getObjectClassname().") 2113 \$obj".$index."->".($fk->isLocalPrimaryKey() ? 'set' : 'add') . $joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = false)."(\$obj1); 2123 ".($fk->isLocalPrimaryKey() ? 2124 "\$obj1->set".$joinedTablePeerBuilder->getObjectClassname()."(\$obj".$index.");" : 2125 "\$obj".$index."->add".$joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = false)."(\$obj1);")." 2114 2126 } // if joined row not null 2115 2127 "; … … 2121 2133 \$results[] = \$obj1; 2122 2134 } 2135 \$stmt->closeCursor(); 2123 2136 return \$results; 2124 2137 } … … 2187 2200 \$stmt = ".$this->getPeerClassname()."::doSelectStmt(\$criteria, \$con); 2188 2201 if (\$row = \$stmt->fetch(PDO::FETCH_NUM)) { 2189 return (int) \$row[0]; 2190 } else { 2191 // no rows returned; we infer that means 0 matches. 2192 return 0; 2193 } 2202 \$count = (int) \$row[0]; 2203 } else { 2204 \$count = 0; // no rows returned; we infer that means 0 matches. 2205 } 2206 \$stmt->closeCursor(); 2207 return \$count; 2194 2208 } 2195 2209 "; … … 2297 2311 \$key1 = ".$this->getPeerClassname()."::getPrimaryKeyHashFromRow(\$row, 0); 2298 2312 if (null !== (".$this->getPeerClassname()."::getInstanceFromPool(\$key1))) { 2299 \$obj1->hydrate(\$row, 0, true); // rehydrate 2313 // We no longer rehydrate the object, since this can cause data loss. 2314 // See http://propel.phpdb.org/trac/ticket/509 2315 // \$obj1->hydrate(\$row, 0, true); // rehydrate 2300 2316 } else {"; 2301 2317 if ($table->getChildrenColumn()) { … … 2375 2391 \$results[] = \$obj1; 2376 2392 } 2393 \$stmt->closeCursor(); 2377 2394 return \$results; 2378 2395 } … … 2457 2474 \$stmt = ".$this->getPeerClassname()."::doSelectStmt(\$criteria, \$con); 2458 2475 if (\$row = \$stmt->fetch(PDO::FETCH_NUM)) { 2459 return(int) \$row[0];2476 \$count = (int) \$row[0]; 2460 2477 } else { 2461 // no rows returned; we infer that means 0 matches. 2462 return 0; 2463 } 2478 \$count = 0; // no rows returned; we infer that means 0 matches. 2479 } 2480 \$stmt->closeCursor(); 2481 return \$count; 2464 2482 } 2465 2483 "; branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/database/model/Table.php
r6294 r7042 2 2 3 3 /* 4 * $Id: Table.php 842 2007-12-02 16:28:20Z heltem$4 * $Id: Table.php 908 2008-01-10 15:48:59Z hans $ 5 5 * 6 6 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 41 41 * @author Daniel Rall <dlr@collab.net> (Torque) 42 42 * @author Byron Foster <byron_foster@yahoo.com> (Torque) 43 * @version $Revision: 842$43 * @version $Revision: 908 $ 44 44 * @package propel.engine.database.model 45 45 */ … … 80 80 private $forReferenceOnly; 81 81 private $treeMode; 82 82 private $reloadOnInsert; 83 private $reloadOnUpdate; 84 83 85 /** 84 86 * Constructs a table object with a name … … 127 129 $this->enterface = $this->getAttribute("interface"); // sic ('interface' is reserved word) 128 130 $this->treeMode = $this->getAttribute("treeMode"); 131 132 $this->reloadOnInsert = $this->booleanValue($this->getAttribute("reloadOnInsert")); 133 $this->reloadOnUpdate = $this->booleanValue($this->getAttribute("reloadOnUpdate")); 129 134 } 130 135 … … 671 676 $this->skipSql = $v; 672 677 } 678 679 /** 680 * Whether to force object to reload on INSERT. 681 * @return boolean 682 */ 683 public function isReloadOnInsert() 684 { 685 return $this->reloadOnInsert; 686 } 687 688 /** 689 * Whether to force object to reload on UPDATE. 690 * @return boolean 691 */ 692 public function isReloadOnUpdate() 693 { 694 return $this->reloadOnUpdate; 695 } 673 696 674 697 /** … … 996 1019 . '"'; 997 1020 } 998 1021 1022 if ($this->reloadOnInsert) { 1023 $result .= " reloadOnInsert=\"" 1024 . ($this->reloadOnInsert ? "true" : "false") 1025 . '"'; 1026 } 1027 1028 if ($this->reloadOnUpdate) { 1029 $result .= " reloadOnUpdate=\"" 1030 . ($this->reloadOnUpdate ? "true" : "false") 1031 . '"'; 1032 } 1033 999 1034 if ($this->forReferenceOnly) { 1000 1035 $result .= " forReferenceOnly=\"" branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/phing/PropelConvertConfTask.php
r6506 r7042 2 2 3 3 /* 4 * $Id: PropelConvertConfTask.php 866 2007-12-14 19:13:24Z hans $4 * $Id: PropelConvertConfTask.php 905 2008-01-09 04:12:34Z hans $ 5 5 * 6 6 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 269 269 $ar[$k] = $child; 270 270 } else { 271 // if the $ar[$k] element is not already an array, then we need to make it one 272 if ( !is_array( $ar[$k] ) ) { $ar[$k] = array( $ar[$k] ); } 271 // (This only applies to nested nodes that do not have an @id attribute) 272 273 // if the $ar[$k] element is not already an array, then we need to make it one. 274 // this is a bit of a hack, but here we check to also make sure that if it is an 275 // array, that it has numeric keys. this distinguishes it from simply having other 276 // nested element data. 277 278 if ( !is_array($ar[$k]) || !isset($ar[$k][0]) ) { $ar[$k] = array($ar[$k]); } 273 279 $ar[$k][] = $child; 274 280 } branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/phing/PropelDataDumpTask.php
r5248 r7042 1 <?php2 3 /*4 * $Id: PropelDataDumpTask.php 612 2007-03-27 09:39:00Z heltem $5 *6 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS7 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT8 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR9 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT10 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,11 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT12 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,13 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY14 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT15 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE16 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.17 *18 * This software consists of voluntary contributions made by many individuals19 * and is licensed under the LGPL. For more information please see20 * <http://propel.phpdb.org>.21 */22 23 /**24 * Dumps the contenst of selected databases to XML data dump file.25 *26 * The generated XML files can have corresponding DTD files generated using the27 * PropelDataDTDTask. The results of the data dump can be converted to SQL using28 * the PropelDataSQLTask class.29 *30 * The database may be specified (via 'databaseName' attribute) if you only want to dump31 * the contents of one database. Otherwise it is assumed that all databases described32 * by datamodel schema file(s) will be dumped.33 *34 * @author Hans Lellelid <hans@xmpl.org> (Propel)35 * @author Fedor Karpelevitch <fedor.karpelevitch@home.com> (Torque)36 * @author Jason van Zyl <jvanzyl@zenplex.com> (Torque)37 * @author Daniel Rall <dlr@finemaltcoding.com> (Torque)38 * @version $Revision: 612 $39 * @package propel.phing40 */41 class PropelDataDumpTask extends AbstractPropelDataModelTask {42 43 /**44 * Database name.45 * The database name may be optionally specified in the XML if you only want46 * to dump the contents of one database.47 */48 private $databaseName;49 50 /**51 * Database URL used for Creole connection.52 * This is a PEAR-compatible (loosely) DSN URL.53 */54 private $databaseUrl;55 56 /**57 * Database driver used for Creole connection.58 * This should normally be left blank so that default (Creole built-in) driver for database type is used.59 */60 private $databaseDriver;61 62 /**63 * Database user used for Creole connection.64 * @deprecated Put username in databaseUrl.65 */66 private $databaseUser;67 68 /**69 * Database password used for Creole connection.70 * @deprecated Put password in databaseUrl.71 */72 private $databasePassword;73 74 /**75 * Properties file that maps a data XML file to a particular database.76 * @var PhingFile77 */78 private $datadbmap;79 80 /**81 * The database connection used to retrieve the data to dump.82 * Needs to be public so that the TableInfo class can access it.83 */84 public $conn;85 86 /**87 * The statement used to acquire the data to dump.88 */89 private $stmt;90 91 /**92 * Set the file that maps between data XML files and databases.93 *94 * @param PhingFile $sqldbmap the db map95 * @return void96 */97 public function setDataDbMap(PhingFile $datadbmap)98 {99 $this->datadbmap = $datadbmap;100 }101 102 /**103 * Get the file that maps between data XML files and databases.104 *105 * @return PhingFile $datadbmap.106 */107 public function getDataDbMap()108 {109 return $this->datadbmap;110 }111 112 /**113 * Get the database name to dump114 *115 * @return The DatabaseName value116 */117 public function getDatabaseName()118 {119 return $this->databaseName;120 }121 122 /**123 * Set the database name124 *125 * @param v The new DatabaseName value126 */127 public function setDatabaseName($v)128 {129 $this->databaseName = $v;130 }131 132 /**133 * Get the database url134 *135 * @return The DatabaseUrl value136 */137 public function getDatabaseUrl()138 {139 return $this->databaseUrl;140 }141 142 /**143 * Set the database url144 *145 * @param string $v The PEAR-compatible database DSN URL.146 */147 public function setDatabaseUrl($v)148 {149 $this->databaseUrl = $v;150 }151 152 /**153 * Get the database user154 *155 * @return string database user156 * @deprecated157 */158 public function getDatabaseUser()159 {160 return $this->databaseUser;161 }162 163 /**164 * Set the database user165 *166 * @param string $v The new DatabaseUser value167 * @deprecated Specify user in DSN URL.168 */169 public function setDatabaseUser($v)170 {171 $this->databaseUser = $v;172 }173 174 /**175 * Get the database password176 *177 * @return string database password178 */179 public function getDatabasePassword()180 {181 return $this->databasePassword;182 }183 184 /**185 * Set the database password186 *187 * @param string $v The new DatabasePassword value188 * @deprecated Specify database password in DSN URL.189 */190 public function setDatabasePassword($v)191 {192 $this->databasePassword = $v;193 }194 195 /**196 * Get the database driver name197 *198 * @return string database driver name199 */200 public function getDatabaseDriver()201 {202 return $this->databaseDriver;203 }204 205 /**206 * Set the database driver name207 *208 * @param string $v The new DatabaseDriver value209 */210 public function setDatabaseDriver($v)211 {212 $this->databaseDriver = $v;213 }214 215 /**216 * Create the data XML -> database map.217 *218 * This is necessary because there is currently no other method of knowing which219 * data XML files correspond to which database. This map allows us to convert multiple220 * data XML files into SQL.221 *222 * @throws IOException - if unable to store properties223 */224 private function createDataDbMap()225 {226 if ($this->getDataDbMap() === null) {227 return;228 }229 230 // Produce the sql -> database map231 $datadbmap = new Properties();232 233 // Check to see if the sqldbmap has already been created.234 if ($this->getDataDbMap()->exists()) {235 $datadbmap->load($this->getDataDbMap());236 }237 238 foreach ($this->getDataModels() as $dataModel) { // there is really one 1 db per datamodel239 foreach ($dataModel->getDatabases() as $database) {240 241 // if database name is specified, then we only want to dump that one db.242 if (empty($this->databaseName) || ($this->databaseName && $database->getName() == $this->databaseName)) {243 $outFile = $this->getMappedFile($dataModel->getName());244 $datadbmap->setProperty($outFile->getName(), $database->getName());245 }246 }247 }248 249 try {250 $datadbmap->store($this->getDataDbMap(), "Data XML file -> Database map");251 } catch (IOException $e) {252 throw new IOException("Unable to store properties: ". $e->getMessage());253 }254 }255 256 /**257 * Iterates through each datamodel/database, dumps the contents of all tables and creates a DOM XML doc.258 *259 * @return void260 * @throws BuildException261 */262 public function main()263 {264 $this->validate();265 266 $buf = "Database settings:\n"267 . " driver: " . ($this->databaseDriver ? $this->databaseDriver : "(default)" ). "\n"268 . " URL: " . $this->databaseUrl . "\n"269 . ($this->databaseUser ? " user: " . $this->databaseUser . "\n" : "")270 . ($this->databasePassword ? " password: " . $this->databasePassword . "\n" : "");271 272 $this->log($buf, PROJECT_MSG_VERBOSE);273 274 // 1) First create the Data XML -> database name map.275 $this->createDataDbMap();276 277 // 2) Now go create the XML files from teh database(s)278 foreach ($this->getDataModels() as $dataModel) { // there is really one 1 db per datamodel279 foreach ($dataModel->getDatabases() as $database) {280 281 // if database name is specified, then we only want to dump that one db.282 if (empty($this->databaseName) || ($this->databaseName && $database->getName() == $this->databaseName)) {283 284 $outFile = $this->getMappedFile($dataModel->getName());285 286 $this->log("Dumping data to XML for database: " . $database->getName());287 $this->log("Writing to XML file: " . $outFile->getName());288 289 try {290 291 $url = str_replace("@DB@", $database->getName(), $this->databaseUrl);292 293 if ($url !== $this->databaseUrl) {294 $this->log("New (resolved) URL: " . $url, PROJECT_MSG_VERBOSE);295 }296 297 if (empty($url)) {298 throw new BuildException("Unable to connect to database; no PDO connection URL specified.", $this->getLocation());299 }300 301 $this->conn = new PDO($url, $this->databaseUser, $this->databasePassword);302 $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);303 304 $doc = $this->createXMLDoc($database);305 $doc->save($outFile->getAbsolutePath());306 307 } catch (SQLException $se) {308 $this->log("SQLException while connecting to DB: ". $se->getMessage(), PROJECT_MSG_ERR);309 throw new BuildException($se);310 }311 } // if databaseName && database->getName == databaseName312 } // foreach database313 } // foreach datamodel314 }315 316 /**317 * Gets ResultSet of query to fetch all data from a table.318 * @param string $tableName319 * @return ResultSet320 */321 private function getTableDataStmt($tableName) {322 // Set Statement object in associated PropelDataDump323 // instance.324 $stmt = $this->conn->prepare("SELECT * FROM " . $this->getPlatformForTargetDatabase()->quoteIdentifier ( $tableName ) );325 $stmt->execute();326 return $stmt;327 }328 329 /**330 * Creates a DOM document containing data for specified database.331 * @param Database $database332 * @return DOMDocument333 */334 private function createXMLDoc(Database $database) {335 336 $doc = new DOMDocument('1.0', 'utf-8');337 $doc->formatOutput = true; // pretty printing338 $doc->appendChild($doc->createComment("Created by data/dump/Control.tpl template."));339 340 $dsNode = $doc->createElement("dataset");341 $dsNode->setAttribute("name", "all");342 $doc->appendChild($dsNode);343 344 $this->log("Building DOM tree containing data from tables:");345 346 foreach ($database->getTables() as $tbl) {347 $this->log("\t+ " . $tbl->getName());348 $stmt = $this->getTableDataStmt($tbl->getName());349 while ($row = $stmt->fetch()) {350 $rowNode = $doc->createElement($tbl->getPhpName());351 foreach ($tbl->getColumns() as $col) {352 $cval = $row[$col->getName()];353 if ($cval !== null) {354 $rowNode->setAttribute($col->getPhpName(), iconv($this->dbEncoding, 'utf-8', $cval));355 }356 }357 $dsNode->appendChild($rowNode);358 unset($rowNode);359 }360 unset($stmt);361 }362 363 return $doc;364 }365 }branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/projects/bookstore/schema.xml
r6597 r7042 163 163 </table> 164 164 165 <!-- Test one-to-one relationship --> 166 <table name="bookstore_employee_account" 165 <!-- Test one-to-one relationship, default values --> 166 <table name="bookstore_employee_account" reloadOnInsert="true" 167 reloadOnUpdate="true" 167 168 description="A table that represents a bookstore employees login credentials."> 168 169 <column name="employee_id" type="INTEGER" primaryKey="true" … … 175 176 defaultExpr="CURRENT_TIMESTAMP" /> 176 177 <column name="role_id" type="INTEGER" required="false" /> 178 <column name="authenticator" type="VARCHAR" size="32" 179 defaultExpr="'Password'" /> 177 180 <foreign-key foreignTable="bookstore_employee" 178 181 onDelete="cascade"> … … 242 245 <column name="total_books" type="INTEGER" /> 243 246 <column name="store_open_time" type="TIME" /> 244 </table> 245 246 <!-- test default values on foreign keys --> 247 <table name="bookstore_sale"> 247 <column name="website" type="VARCHAR" size="255"/> 248 <validator column="website"> 249 <rule name="match" value="/^((ht|f)tp(s?)\:\/\/[a-zA-Z0-9\-\._]+(\.[a-zA-Z0-9\-\._]+){2,}(\/?)([a-zA-Z0-9\-\.\?\,'\/\\\+&amp;%\$#_]*)?$|$)/" message="wrong url"/> 250 </validator> 251 </table> 252 253 <!-- test default values on foreign keys, default expr w/ reloadOnUpdate="true" --> 254 <table name="bookstore_sale" reloadOnUpdate="true"> 248 255 <column name="id" type="INTEGER" primaryKey="true" 249 256 autoIncrement="true" /> … … 254 261 required="false" /> 255 262 <column name="discount" type="TINYINT" 256 description="Discount percentage" />263 description="Discount percentage" defaultExpr="10" /> 257 264 <foreign-key foreignTable="bookstore" onDelete="cascade"> 258 265 <reference local="bookstore_id" foreign="id" /> … … 267 274 autoIncrement="true" /> 268 275 <column name="name" type="VARCHAR" size="255" /> 269 <column name="join_date" type="DATE" />276 <column name="join_date" type="DATE" /> 270 277 </table> 271 278 … … 291 298 </table> 292 299 293 <table name="bookstore_contest_entry" >300 <table name="bookstore_contest_entry" reloadOnInsert="true"> 294 301 <column name="bookstore_id" type="INTEGER" primaryKey="true" /> 295 302 <column name="contest_id" type="INTEGER" primaryKey="true" /> branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/resources/xsd/database.xsd
r6471 r7042 364 364 <xs:attribute name="description" type="xs:string"/> 365 365 <xs:attribute name="treeMode" type="treemode" use="optional"/> 366 <xs:attribute name="reloadOnInsert" type="xs:boolean" default="false"/> 367 <xs:attribute name="reloadOnUpdate" type="xs:boolean" default="false"/> 366 368 </xs:complexType> 367 369 branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/test/classes/propel/GeneratedObjectRelTest.php
r6597 r7042 1 1 <?php 2 2 /* 3 * $Id: GeneratedObjectRelTest.php 875 2007-12-19 11:10:15Z heltem$3 * $Id: GeneratedObjectRelTest.php 907 2008-01-10 13:42:47Z hans $ 4 4 * 5 5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 202 202 $this->assertEquals(0, count($book->getReviews())); 203 203 } 204 205 /** 206 * This tests to see whether modified objects are being silently overwritten by calls to fk accessor methods. 207 * @link http://propel.phpdb.org/trac/ticket/509#comment:5 208 */ 209 public function testModifiedObjectOverwrite() 210 { 211 $author = new Author(); 212 $author->setFirstName("John"); 213 $author->setLastName("Public"); 214 215 $books = $author->getBooks(); // empty, of course 216 $this->assertEquals(array(), $books, "Expected empty array."); 217 218 $book = new Book(); 219 $book->setTitle("A sample book"); 220 $book->setISBN("INITIAL ISBN"); 221 222 $author->addBook($book); 223 224 $author->save(); 225 226 $book->setISBN("MODIFIED ISBN"); 227 228 $books = $author->getBooks(); 229 $this->assertEquals(1, count($books), "Expected 1 book."); 230 $this->assertSame($book, $books[0], "Expected the same object to be returned by fk accessor."); 231 $this->assertEquals("MODIFIED ISBN", $books[0]->getISBN(), "Expected the modified value NOT to have been overwritten."); 232 } 204 233 } branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/test/classes/propel/GeneratedObjectTest.php
r6294 r7042 1 1 <?php 2 2 /* 3 * $Id: GeneratedObjectTest.php 842 2007-12-02 16:28:20Z heltem$3 * $Id: GeneratedObjectTest.php 914 2008-01-11 20:39:14Z hans $ 4 4 * 5 5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 82 82 83 83 /** 84 * Tests the use of default expressions. 85 * (Also indirectly tests the reload() method.) 84 * Tests the use of default expressions and the reloadOnInsert and reloadOnUpdate attributes. 85 * 86 * @link http://propel.phpdb.org/trac/ticket/378 87 * @link http://propel.phpdb.org/trac/ticket/555 86 88 */ 87 89 public function testDefaultExpresions() … … 91 93 } 92 94 95 $b = new Bookstore(); 96 $b->setId(1); 97 $b->setStoreName("Foo!"); 98 $b->save(); 99 93 100 $employee = new BookstoreEmployee(); 94 101 $employee->setName("Johnny Walker"); … … 98 105 $acct->setLogin("test-login"); 99 106 100 $this->assertNull($acct->getCreated()); 107 $this->assertNull($acct->getCreated(), "Expected created column to be NULL."); 108 $this->assertNull($acct->getAuthenticator(), "Expected authenticator column to be NULL."); 101 109 102 110 $acct->save(); 103 111 104 // BookstoreEmployeeAccountPeer::removeInstanceFromPool($acct);105 106 112 $acct = BookstoreEmployeeAccountPeer::retrieveByPK($acct->getEmployeeId()); 113 114 $this->assertNotNull($acct->getAuthenticator(), "Expected a valid (non-NULL) authenticator column after save."); 115 $this->assertEquals('Password', $acct->getAuthenticator(), "Expected authenticator='Password' after save."); 107 116 $this->assertNotNull($acct->getCreated(), "Expected a valid date after retrieving saved object."); 108 117 … … 113 122 $this->assertEquals($now->format("Y-m-d"), $acct->getCreated("Y-m-d")); 114 123 124 // Unfortunately we can't really test the conjunction of reloadOnInsert and reloadOnUpdate when using just 125 // default values. (At least not in a cross-db way.) 126 } 127 128 /** 129 * Tests the use of default expressions and the reloadOnInsert attribute. 130 * 131 * @link http://propel.phpdb.org/trac/ticket/378 132 * @link http://propel.phpdb.org/trac/ticket/555 133 */ 134 public function testDefaultExpresions_ReloadOnInsert() 135 { 136 if (Propel::getDb(BookstoreEmployeePeer::DATABASE_NAME) instanceof DBSqlite) { 137 $this->markTestSkipped("Cannot test default date expressions with SQLite"); 138 } 139 140 // Create a new bookstore, contest, bookstore_contest, and bookstore_contest_entry 141 142 $b = new Bookstore(); 143 $b->setStoreName("Barnes & Noble"); 144 $b->save(); 145 146 $c = new Contest(); 147 $c->setName("Bookathon Contest"); 148 $c->save(); 149 150 $bc = new BookstoreContest(); 151 $bc->setBookstore($b); 152 $bc->setContest($c); 153 $bc->save(); 154 155 $c = new Customer(); 156 $c->setName("Happy Customer"); 157 $c->save(); 158 159 $bce = new BookstoreContestEntry(); 160 $bce->setBookstore($b); 161 $bce->setBookstoreContest($bc); 162 $bce->setCustomer($c); 163 $bce->save(); 164 165 $this->assertNotNull($bce->getEntryDate(), "Expected a non-null entry_date after save."); 166 } 167 168 /** 169 * Tests the overriding reloadOnInsert at runtime. 170 * 171 * @link http://propel.phpdb.org/trac/ticket/378 172 * @link http://propel.phpdb.org/trac/ticket/555 173 */ 174 public function testDefaultExpresions_ReloadOnInsert_Override() 175 { 176 if (Propel::getDb(BookstoreEmployeePeer::DATABASE_NAME) instanceof DBSqlite) { 177 $this->markTestSkipped("Cannot test default date expressions with SQLite"); 178 } 179 180 // Create a new bookstore, contest, bookstore_contest, and bookstore_contest_entry 181 $b = new Bookstore(); 182 $b->setStoreName("Barnes & Noble"); 183 $b->save(); 184 185 $c = new Contest(); 186 $c->setName("Bookathon Contest"); 187 $c->save(); 188 189 $bc = new BookstoreContest(); 190 $bc->setBookstore($b); 191 $bc->setContest($c); 192 $bc->save(); 193 194 $c = new Customer(); 195 $c->setName("Happy Customer"); 196 $c->save(); 197 198 $bce = new BookstoreContestEntry(); 199 $bce->setBookstore($b); 200 $bce->setBookstoreContest($bc); 201 $bce->setCustomer($c); 202 $bce->save(null, $skipReload=true); 203 204 $this->assertNull($bce->getEntryDate(), "Expected a NULL entry_date after save."); 205 } 206 207 /** 208 * Tests the use of default expressions and the reloadOnUpdate attribute. 209 * 210 * @link http://propel.phpdb.org/trac/ticket/555 211 */ 212 public function testDefaultExpresions_ReloadOnUpdate() 213 { 214 $b = new Bookstore(); 215 $b->setId(1); 216 $b->setStoreName("Foo!"); 217 $b->save(); 218 219 $sale = new BookstoreSale(); 220 $sale->setBookstore(BookstorePeer::doSelectOne(new Criteria())); 221 $sale->setSaleName("Spring Sale"); 222 $sale->save(); 223 224 // Expect that default values are set, but not default expressions 225 $this->assertNull($sale->getDiscount(), "Expected discount to be NULL."); 226 227 $sale->setSaleName("Winter Clearance"); 228 $sale->save(); 229 // Since reloadOnUpdate = true, we expect the discount to be set now. 230 231 $this->assertNotNull($sale->getDiscount(), "Expected discount to be non-NULL after save."); 232 } 233 234 /** 235 * Tests the overriding reloadOnUpdate at runtime. 236 * 237 * @link http://propel.phpdb.org/trac/ticket/378 238 * @link http://propel.phpdb.org/trac/ticket/555 239 */ 240 public function testDefaultExpresions_ReloadOnUpdate_Override() 241 { 242 $b = new Bookstore(); 243 $b->setId(1); 244 $b->setStoreName("Foo!"); 245 $b->save(); 246 247 $sale = new BookstoreSale(); 248 $sale->setBookstore(BookstorePeer::doSelectOne(new Criteria())); 249 $sale->setSaleName("Spring Sale"); 250 $sale->save(); 251 252 // Expect that default values are set, but not default expressions 253 $this->assertNull($sale->getDiscount(), "Expected discount to be NULL."); 254 255 $sale->setSaleName("Winter Clearance"); 256 $sale->save(null, $skipReload=true); 257 258 // Since reloadOnUpdate = true, we expect the discount to be set now. 259 260 $this->assertNull($sale->getDiscount(), "Expected NULL value for discount after save."); 115 261 } 116 262 … … 246 392 $this->assertSame($book, $book2, "Expected same book object instance"); 247 393 394 $this->assertEquals($pub1->getId(), $book->getPublisherId(), "Expected book to have OLD publisher id before reload()"); 395 396 $book->reload(); 397 248 398 $this->assertEquals($pub2->getId(), $book->getPublisherId(), "Expected book to have new publisher id"); 249 399 $this->assertSame($pub2, $book->getPublisher(), "Expected book to have new publisher object associated."); 250 400 251 // Now let's set it back and also verify that reload() works...401 // Now let's set it back, just to be double sure ... 252 402 253 403 $con->exec("UPDATE " . BookPeer::TABLE_NAME . " SET " … … 749 899 { 750 900 $sale = new BookstoreSale(); 751 $this->assertEquals(1, $sale->getBookstoreId(), "Expected BookstoreSale object to have a default ID.");901 $this->assertEquals(1, $sale->getBookstoreId(), "Expected BookstoreSale object to have a default bookstore_id of 1."); 752 902 753 903 $bookstore = BookstorePeer::doSelectOne(new Criteria()); … … 865 1015 $this->assertEquals($expectedDiff, $diffKeys); 866 1016 } 1017 1018 /** 1019 * Test regexp validator for ticket:542 1020 * @link http://propel.phpdb.org/trac/ticket/542 1021 */ 1022 public function testRegexValidator() 1023 { 1024 $b = new Bookstore(); 1025 $b->setWebsite("http://this.is.valid.com/foo.bar"); 1026 $res = $b->validate(); 1027 $this->assertTrue($res, "Expected URL to validate"); 1028 } 867 1029 } branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/test/classes/propel/util/BasePeerTest.php
r6294 r7042 1 1 <?php 2 2 /* 3 * $Id: BasePeerTest.php 842 2007-12-02 16:28:20Z heltem$3 * $Id: BasePeerTest.php 910 2008-01-11 15:07:02Z hans $ 4 4 * 5 5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 55 55 } 56 56 $stmt = BookPeer::doSelectStmt( $c ); 57 } catch ( Exception $x) {57 } catch (PropelException $x) { 58 58 $this->fail("Paring of nested functions failed: " . $x->getMessage()); 59 59 } branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/test/classes/propel/util/CriteriaTest.php
r6506 r7042 10 10 * @author <a href="mailto:celkins@scardini.com">Christopher Elkins</a> 11 11 * @author <a href="mailto:sam@neurogrid.com">Sam Joseph</a> 12 * @version $Id: CriteriaTest.php 857 2007-12-13 14:59:59Z heltem$12 * @version $Id: CriteriaTest.php 911 2008-01-11 15:08:46Z hans $ 13 13 */ 14 14 class CriteriaTest extends BaseTestCase { 15 15 16 /** The criteria to use in the test. */ 16 /** 17 * The criteria to use in the test. 18 * @var Criteria 19 */ 17 20 private $c; 18 19 /** 20 * Initializes the criteria. 21 */ 22 public function setUp() 21 22 /** 23 * DB adapter saved for later. 24 * 25 * @var DBAdapter 26 */ 27 private $savedAdapter; 28 29 protected function setUp() 23 30 { 24 31 parent::setUp(); 25 32 $this->c = new Criteria(); 33 $this->savedAdapter = Propel::getDB(null); 26 34 Propel::setDB(null, new DBSQLite()); 35 } 36 37 protected function tearDown() 38 { 39 Propel::setDB(null, $this->savedAdapter); 40 parent::tearDown(); 27 41 } 28 42 branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel/Propel.php
r6884 r7042 1 1 <?php 2 2 /* 3 * $Id: Propel.php 90 2 2008-01-02 09:49:16Z abeggchr$3 * $Id: Propel.php 909 2008-01-11 12:30:43Z hans $ 4 4 * 5 5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 38 38 * @author Henning P. Schmiedehausen <hps@intermeta.de> (Torque) 39 39 * @author Kurt Schrader <kschrader@karmalab.org> (Torque) 40 * @version $Revision: 90 2$40 * @version $Revision: 909 $ 41 41 * @package propel 42 42 */ … … 94 94 95 95 /** 96 * The class name for a PDO object 96 * The class name for a PDO object. 97 97 */ 98 98 const CLASS_PDO = 'PDO'; 99 99 100 /**101 * The class name for a PropelPDO object 100 /** 101 * The class name for a PropelPDO object. 102 102 */ 103 103 const CLASS_PROPEL_PDO = 'PropelPDO'; 104 104 105 /** 106 * The class name for a SlavePDO object 107 */ 108 const CLASS_SLAVE_PDO = 'SlavePDO'; 105 /** 106 * The class name for a DebugPDO object. 107 */ 108 const CLASS_DEBUG_PDO = 'DebugPDO'; 109 110 /** 111 * Constant used to request a READ connection (applies to replication). 112 */ 113 const CONNECTION_READ = 'read'; 114 115 /** 116 * Constant used to request a WRITE connection (applies to replication). 117 */ 118 const CONNECTION_WRITE = 'write'; 109 119 110 120 /** … … 152 162 */ 153 163 private static $instancePoolingEnabled = true; 164 165 /** 166 * @var bool For replication, whether to force the use of master connection. 167 */ 168 private static $forceMasterConnection = false; 154 169 155 170 /** … … 191 206 'PropelColumnTypes' => 'propel/util/PropelColumnTypes.php', 192 207 'PropelPDO' => 'propel/util/PropelPDO.php', 193 'SlavePDO' => 'propel/util/SlavePDO.php',194 208 'PropelPager' => 'propel/util/PropelPager.php', 195 209 'PropelDateTime' => 'propel/util/PropelDateTime.php', 196 210 'DebugPDO' => 'propel/util/DebugPDO.php', 211 'DebugPDOStatement' => 'propel/util/DebugPDOStatement.php', 212 197 213 'BasicValidator' => 'propel/validator/BasicValidator.php', 198 214 'MatchValidator' => 'propel/validator/MatchValidator.php', … … 439 455 440 456 /** 441 * Gets an already-opened PDO connection or opens a new one for passed-in db name. 442 * 443 * @param string The name that is used to look up the DSN from the runtime properties file. 444 * 445 * @return PDO A database connection 446 * 447 * @throws PropelException - if no conneciton params, or lower-level exception caught when trying to connect. 448 */ 449 public static function getConnection($name = null) 457 * For replication, set whether to always force the use of a master connection. 458 * 459 * @param boolean $bit True or False 460 */ 461 public static function setForceMasterConnection($bit) 462 { 463 self::$forceMasterConnection = (bool) $bit; 464 } 465 466 /** 467 * For replication, whether to always force the use of a master connection. 468 * 469 * @return boolean 470 */ 471 public static function getForceMasterConnection() 472 { 473 return self::$forceMasterConnection; 474 } 475 476 /** 477 * Sets a Connection for specified datasource name. 478 * 479 * @param string $name The datasource name for the connection being set. 480 * @param PropelPDO $con The PDO connection. 481 * @param string $mode Whether this is a READ or WRITE connection (Propel::CONNECTION_READ, Propel::CONNECTION_WRITE) 482 */ 483 public static function setConnection($name, PropelPDO $con, $mode = Propel::CONNECTION_WRITE) 450 484 { 451 485 if ($name === null) { 452 486 $name = self::getDefaultDB(); 453 487 } 454 455 if (!isset(self::$connectionMap[$name])) { 456 457 // load connection parameter for master connection 458 $conparams = isset(self::$configuration['datasources'][$name]['connection']) ? self::$configuration['datasources'][$name]['connection'] : null; 459 if ($conparams === null) { 460 throw new PropelException('No connection information in your runtime configuration file for datasource ['.$name.']'); 461 } 462 463 // initialize master connection 464 $con = Propel::initConnection($conparams, $name, Propel::CLASS_PROPEL_PDO); 465 self::$connectionMap[$name] = $con; 466 467 // load any slaves from the config file and add them to the master connection 468 $slaveparams = isset(self::$configuration['datasources'][$name]['slaves']) ? self::$configuration['datasources'][$name]['slaves'] : null; 469 if ($slaveparams != null) { 470 foreach ($slaveparams as $key => $slaveparam) { 471 $con->addSlave($slaveparam, $name); 488 if ($mode == Propel::CONNECTION_READ) { 489 self::$connectionMap[$name]['slave'] = $con; 490 } else { 491 self::$connectionMap[$name]['master'] = $con; 492 } 493 } 494 495 /** 496 * Gets an already-opened PDO connection or opens a new one for passed-in db name. 497 * 498 * @param string $name The datasource name that is used to look up the DSN from the runtime configuation file. 499 * @param string $mode The connection mode (this applies to replication systems). 500 * 501 * @return PDO A database connection 502 * 503 * @throws PropelException - if connection cannot be configured or initialized. 504 */ 505 public static function getConnection($name = null, $mode = Propel::CONNECTION_WRITE) 506 { 507 if ($name === null) { 508 $name = self::getDefaultDB(); 509 } 510 511 // IF a WRITE-mode connection was requested 512 // or Propel is configured to always use the master connection 513 // or the slave for this connection has already been set to FALSE (indicating no slave) 514 // THEN return the master connection. 515 if ($mode != Propel::CONNECTION_READ || self::$forceMasterConnection || (isset(self::$connectionMap[$name]['slave']) && self::$connectionMap[$name]['slave'] === false)) { 516 if (!isset(self::$connectionMap[$name]['master'])) { 517 // load connection parameter for master connection 518 $conparams = isset(self::$configuration['datasources'][$name]['connection']) ? self::$configuration['datasources'][$name]['connection'] : null; 519 if (empty($conparams)) { 520 throw new PropelException('No connection information in your runtime configuration file for datasource ['.$name.']'); 472 521 } 473 } 474 } 475 476 return self::$connectionMap[$name]; 477 } 522 // initialize master connection 523 $con = Propel::initConnection($conparams, $name); 524 self::$connectionMap[$name]['master'] = $con; 525 } 526 527 return self::$connectionMap[$name]['master']; 528 529 } else { 530 531 if (!isset(self::$connectionMap[$name]['slave'])) { 532 533 // we've already ensured that the configuration exists, in previous if-statement 534 $slaveconfigs = isset(self::$configuration['datasources'][$name]['slaves']) ? self::$configuration['datasources'][$name]['slaves'] : null; 535 536 if (empty($slaveconfigs)) { // no slaves configured for this datasource 537 self::$connectionMap[$name]['slave'] = false; 538 return self::getConnection($name, Propel::CONNECTION_WRITE); // Recurse to get the WRITE connection 539 } else { // Initialize a new slave 540 if (isset($slaveconfigs['connection']['dsn'])) { // only one slave connection configured 541 $conparams = $slaveconfigs['connection']; 542 } else { 543 $randkey = array_rand($slaveconfigs['connection']); 544 $conparams = $slaveconfigs['connection'][$randkey]; 545 if (empty($conparams)) { 546 throw new PropelException('No connection information in your runtime configuration file for SLAVE ['.$randkey.'] to datasource ['.$name.']'); 547 } 548 } 549 550 // initialize master connection 551 $con = Propel::initConnection($conparams, $name); 552 self::$connectionMap[$name]['slave'] = $con; 553 } 554 555 } // if datasource slave not set 556 557 return self::$connectionMap[$name]['slave']; 558 559 } // if mode == CONNECTION_WRITE 560 561 } // getConnection() 478 562 479 563 /** 480 564 * Opens a new PDO connection for passed-in db name. 481 565 * 482 * @param string[] connection paramters 483 * @param name 484 * 485 * @return object A database connection of the given class (PDO, PropelPDO, SlavePropelPDO) 566 * @param array $conparams Connection paramters. 567 * @param string $name Datasource name. 568 * @param string $defaultClass The PDO subclass to instantiate if there is no explicit classname 569 * specified in the connection params (default is Propel::CLASS_PROPEL_PDO) 570 * 571 * @return PDO A database connection of the given class (PDO, PropelPDO, SlavePDO or user-defined) 486 572 * 487 573 * @throws PropelException - if lower-level exception caught when trying to connect. 488 574 */ 489 public static function initConnection($conparams, $name )575 public static function initConnection($conparams, $name, $defaultClass = Propel::CLASS_PROPEL_PDO) 490 576 { 491 577 … … 493 579 if ($dsn === null) { 494 580 throw new PropelException('No dsn specified in your connection parameters for datasource ['.$name.']'); 581 } 582 583 if (isset($conparams['classname']) && !empty($conparams['classname'])) { 584 $classname = $conparams['classname']; 585 if (!class_exists($classname)) { 586 throw new PropelException('Unable to load specified PDO subclass: ' . $classname); 587 } 588 } else { 589 $classname = $defaultClass; 495 590 } 496 591 … … 510 605 511 606 try { 512 $con = new PropelPDO($dsn, $user, $password, $driver_options);607 $con = new $classname($dsn, $user, $password, $driver_options); 513 608 $con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 514 609 } catch (PDOException $e) { … … 635 730 public static function close() 636 731 { 637 foreach (self::$connectionMap as $ con) {638 $con = null; // close for PDO732 foreach (self::$connectionMap as $idx => $cons) { 733 unset(self::$connectionMap[$idx]); 639 734 } 640 735 } branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel/util/BasePeer.php
r6506 r7042 1 1 <?php 2 2 /* 3 * $Id: BasePeer.php 857 2007-12-13 14:59:59Z heltem$3 * $Id: BasePeer.php 919 2008-01-13 21:12:24Z hans $ 4 4 * 5 5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 36 36 * @author Brett McLaughlin <bmclaugh@algx.net> (Torque) 37 37 * @author Stephen Haberman <stephenh@chase3000.com> (Torque) 38 * @version $Revision: 857$38 * @version $Revision: 919 $ 39 39 * @package propel.util 40 40 */ … … 273 273 $columns = array(); // but just 'column' cols for the SQL 274 274 foreach ($qualifiedCols as $qualifiedCol) { 275 $columns[] = substr($qualifiedCol, str pos($qualifiedCol, '.') + 1);275 $columns[] = substr($qualifiedCol, strrpos($qualifiedCol, '.') + 1); 276 276 } 277 277 … … 356 356 $sql = "UPDATE " . $tableName . " SET "; 357 357 foreach ($updateTablesColumns[$tableName] as $col) { 358 $updateColumnName = substr($col, str pos($col, '.') + 1);358 $updateColumnName = substr($col, strrpos($col, '.') + 1); 359 359 // add identifiers for the actual database? 360 360 if ($db->useQuoteIdentifier()) { … … 431 431 432 432 if ($con === null) { 433 $con = Propel::getConnection($criteria->getDbName() );433 $con = Propel::getConnection($criteria->getDbName(), Propel::CONNECTION_READ); 434 434 } 435 435 … … 521 521 rewind($value); 522 522 } 523 524 if ($type == PropelColumnTypes::BLOB || $type == PropelColumnTypes::CLOB ) { 525 Propel::log("Binding [LOB value] at position $i w/ Propel type $type and PDO type $pdoType", Propel::LOG_DEBUG); 526 } else { 527 Propel::log("Binding " . var_export($value, true) . " at position $i w/ Propel type $type and PDO type $pdoType", Propel::LOG_DEBUG); 528 } 529 523 530 524 $stmt->bindValue($i++, $value, $pdoType); 531 525 } … … 648 642 $selectClause[] = $columnName; // the full column name: e.g. MAX(books.price) 649 643 650 $parenPos = str pos($columnName, '(');651 $dotPos = str pos($columnName, '.');644 $parenPos = strrpos($columnName, '('); 645 $dotPos = strrpos($columnName, '.', ($parenPos !== false ? $parenPos : 0)); 652 646 653 647 // [HL] I think we really only want to worry about adding stuff to … … 808 802 // Split orderByColumn (i.e. "table.column DESC") 809 803 810 $dotPos = str pos($orderByColumn, '.');804 $dotPos = strrpos($orderByColumn, '.'); 811 805 812 806 if ($dotPos !== false) { branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel/util/Criteria.php
r6294 r7042 1 1 <?php 2 2 /* 3 * $Id: Criteria.php 842 2007-12-02 16:28:20Z heltem$3 * $Id: Criteria.php 916 2008-01-12 19:09:39Z hans $ 4 4 * 5 5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 33 33 * @author Henning P. Schmiedehausen <hps@intermeta.de> (Torque) 34 34 * @author Sam Joseph <sam@neurogrid.com> (Torque) 35 * @version $Revision: 842$35 * @version $Revision: 916 $ 36 36 * @package propel.util 37 37 */ … … 389 389 $tables = array(); 390 390 foreach ( array_keys ( $this->map ) as $key) { 391 $t = substr ( $key, 0, str pos ( $key, '.' ) );391 $t = substr ( $key, 0, strrpos ( $key, '.' ) ); 392 392 if ( ! isset ( $tables[$t] ) ) { 393 393 $tables[$t] = array( $key ); … … 1195 1195 public function __construct(Criteria $outer, $column, $value, $comparison = null) 1196 1196 { 1197 list($this->table, $this->column) = explode('.', $column);1198 1197 $this->value = $value; 1198 $dotPos = strrpos($column,'.'); 1199 $this->table = substr($column, 0, $dotPos); 1200 $this->column = substr($column, $dotPos+1, strlen($column)); 1199 1201 $this->comparison = ($comparison === null ? Criteria::EQUAL : $comparison); 1200 1202 $this->init($outer); … … 1673 1675 public function getLeftColumnName() 1674 1676 { 1675 return substr($this->leftColumn, str pos($this->leftColumn, '.') + 1);1677 return substr($this->leftColumn, strrpos($this->leftColumn, '.') + 1); 1676 1678 } 1677 1679 1678 1680 public function getLeftTableName() 1679 1681 { 1680 return substr($this->leftColumn, 0, str pos($this->leftColumn, '.'));1682 return substr($this->leftColumn, 0, strrpos($this->leftColumn, '.')); 1681 1683 } 1682 1684 … … 1691 1693 public function getRightColumnName() 1692 1694 { 1693 return substr($this->rightColumn, str pos($this->rightColumn, '.') + 1);1695 return substr($this->rightColumn, strrpos($this->rightColumn, '.') + 1); 1694 1696 } 1695 1697 1696 1698 public function getRightTableName() 1697 1699 { 1698 return substr($this->rightColumn, 0, str pos($this->rightColumn, '.'));1700 return substr($this->rightColumn, 0, strrpos($this->rightColumn, '.')); 1699 1701 } 1700 1702 branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/vendor/propel/util/PropelPDO.php
r6884 r7042 1 1 <?php 2 2 /* 3 * $Id: PropelPDO.php 9 03 2008-01-02 10:03:51Z abeggchr$3 * $Id: PropelPDO.php 912 2008-01-11 16:13:57Z hans $ 4 4 * 5 5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 22 22 23 23 /** 24 * PDO connection subclass that provides some enhanced functionality needed by Propel.24 * PDO connection subclass that provides the basic fixes to PDO that are required by Propel. 25 25 * 26 26 * This class was designed to work around the limitation in PDO where attempting to begin … … 47 47 */ 48 48 protected $nestedTransactionCount = 0; 49 49 50 50 /** 51 * Array of slave connections51 * Cache of prepared statements (PDOStatement) keyed by md5 of SQL. 52 52 * 53 * keys: param, name, con (only after initialisation)53 * @var array [md5(sql) => PDOStatement] 54 54 */ 55 protected $slaves = array(); 56 57 /** 58 * A single slave connection 59 */ 60 protected $slave = null; 61 62 /** 63 * Use only the master connection 64 */ 65 protected $useMasterConnection = false; 66 55 protected $preparedStatements = array(); 56 67 57 /** 68 58 * Gets the current transaction depth. … … 123 113 return $return; 124 114 } 125 115 126 116 /** 127 117 * Overrides PDO::commit() to only commit the transaction if we are in the outermost … … 157 147 return $return; 158 148 } 159 149 160 150 /** 161 * Overrides PDO::prepare() to add logging and split r/w queries 151 * Overrides PDO::prepare() to add query caching support. 152 * . 153 * @param string $sql 154 * @param array 155 * @return PDOStatement 156 */ 157 public function prepare($sql, $driver_options = array()) 158 { 159 $key = md5($sql); 160 if(!isset($this->preparedStatements[$key])) { 161 $stmt = parent::prepare($sql, $driver_options); 162 $this->preparedStatements[$key] = $stmt; 163 return $stmt; 164 } else { 165 return $this->preparedStatements[$key]; 166 } 167 } 168 169 /** 170 * Clears any stored prepared statements for this connection. 162 171 */ 163 public function prepare($sql, $driver_options = array())172 public function clearStatementCache() 164 173 { 165 Propel::log($sql, Propel::LOG_DEBUG); 166 if ($this->isForSlave($sql)) { 167 if ($slave = $this->getSlave()) { 168 return $slave->prepare($sql, $driver_options); 169 } 170 } 171 return parent::prepare($sql, $driver_options); 174 $this->preparedStatements = array(); 172 175 } 173 176 174 /**175 * Overrides PDO::query() to add logging and split r/w queries176 */177 public function query($sql, $fetch = null, $input3=null, $input4=null) {178 Propel::log($sql, Propel::LOG_DEBUG);179 if ($this->isForSlave($sql)) {180 if ($slave = $this->getSlave()) {181 return $slave->query($sql, $fetch, $input3, $input4);182 }183 }184 return parent::query($sql, $fetch, $input3, $input4);185 }186 187 /**188 * Overrides PDO::exec() to add logging and split r/w queries189 */190 public function exec($sql) {191 Propel::log($sql, Propel::LOG_DEBUG);192 if ($this->isForSlave($sql)) {193 if ($slave = $this->getSlave()) {194 return $slave->exec($sql);195 }196 }197 return parent::exec($sql);198 }199 200 /**201 * Adds the configuration for a slave connection202 *203 * @param array slave param from config204 * @param string name of the connection205 * @return void206 */207 public function addSlave($slaveparam, $name) {208 $newIndex = count($this->slaves);209 $this->slaves[$newIndex]['param'] = $slaveparam;210 $this->slaves[$newIndex]['name'] = $name;211 }212 213 /**214 * Gets one of the slave connections for read only access215 *216 * @return SlavePDO or false if there are no slaves217 */218 private function getSlave() {219 220 if (isset($this->slave)) return $this->slave; // slave already initialised221 if (count($this->slaves) == 0) return false; // return the plain PDO object to avoid endless loops222 223 $random = mt_rand(0, count($this->slaves)-1);224 if (isset($this->slaves[$random]['con'])) {225 $this->slave = $this->slaves[$random]['con'];226 }227 else {228 $this->slaves[$random]['con'] = Propel::initConnection($this->slaves[$random]['param'], $this->slaves[$random]['name'], Propel::CLASS_SLAVE_PDO);229 $this->slave = $this->slaves[$random]['con'];230 }231 return $this->slave;232 }233 234 /**235 * Checks if a sql query should be handled by the slave connection236 *237 * @return boolean238 */239 private function isForSlave($sql) {240 241 // return false if the use of the master connection is forced242 if ($this->useMasterConnection) return false;243 244 // return false if a transaction is open245 $opcount = $this->getNestedTransactionCount();246 if ($opcount > 0) return false;247 248 // check if sql is read only249 return $this->isReadOnly($sql);250 }251 252 /**253 * Checks if a sql query is read only (e.g. starts with "select")254 *255 * @return boolean256 */257 public static function isReadOnly($sql) {258 259 // analyse sql260 $result = stripos($sql, "SELECT");261 if ($result === false) {262 // no select found263 return false;264 }265 else if ($result == 0) {266 // sql starts with select267 return true;268 }269 else {270 // select is somewhere else in string271 return false;272 }273 }274 275 /**276 * Forces the use of the master connection only277 *278 * @param boolean use master connection only279 * @return void280 */281 public function setUseMasterConnection($useMasterConnection) {282 if (is_bool($useMasterConnection)) {283 $this->useMasterConnection = $useMasterConnection;284 }285 else throw new PropelException("Parameter of setUseMasterConnection must be boolean");286 }287 177 }

