Changeset 4372
- Timestamp:
- 05/17/08 13:01:48 (8 months ago)
- Location:
- branches/0.11
- Files:
-
- 5 modified
-
lib/Doctrine/Connection.php (modified) (1 diff)
-
lib/Doctrine/Connection/Db2.php (modified) (1 diff)
-
lib/Doctrine/Connection/Oracle.php (modified) (3 diffs)
-
lib/Doctrine/Query.php (modified) (4 diffs)
-
tests/Query/DriverTestCase.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/0.11/lib/Doctrine/Connection.php
r4366 r4372 1504 1504 * Some dbms require specific functionality for this. Check the other connection adapters for examples 1505 1505 * 1506 * @return void1506 * @return string 1507 1507 */ 1508 1508 public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false) 1509 1509 { 1510 1510 return $query; 1511 } 1512 1513 /** 1514 * Creates dbms specific LIMIT/OFFSET SQL for the subqueries that are used in the 1515 * context of the limit-subquery algorithm. 1516 * 1517 * @return string 1518 */ 1519 public function modifyLimitSubquery(Doctrine_Table $rootTable, $query, $limit = false, 1520 $offset = false, $isManip = false) 1521 { 1522 return $this->modifyLimitQuery($query, $limit, $offset, $isManip); 1511 1523 } 1512 1524 -
branches/0.11/lib/Doctrine/Connection/Db2.php
r4252 r4372 56 56 57 57 $sql = 'WITH OFFSET AS(' . $select . ', ROW_NUMBER() ' . 58 'OVER(ORDER BY ' . $col[1] . ') AS d ctrn_rownum FROM ' . $table . ')' .59 $select . 'FROM OFFSET WHERE d ctrn_rownum BETWEEN ' . $offset .58 'OVER(ORDER BY ' . $col[1] . ') AS doctrine_rownum FROM ' . $table . ')' . 59 $select . 'FROM OFFSET WHERE doctrine_rownum BETWEEN ' . $offset . 60 60 'AND ' . ($offset + $limit - 1); 61 61 return $sql; -
branches/0.11/lib/Doctrine/Connection/Oracle.php
r4362 r4372 83 83 public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false) 84 84 { 85 return $this->_createLimitSubquery($query, $limit, $offset); 86 } 87 88 private function _createLimitSubquery($query, $limit, $offset, $column = null) 89 { 85 90 $limit = (int) $limit; 86 91 $offset = (int) $offset; … … 90 95 } 91 96 if ($limit > 0) { 92 // taken from http://svn.ez.no/svn/ezcomponents/packages/Database93 97 $max = $offset + $limit; 98 $column = $column === null ? '*' : $column; 94 99 if ($offset > 0) { 95 100 $min = $offset + 1; 96 $query = 'SELECT b. * FROM (97 SELECT a.*, ROWNUM AS doctrine_rownum FROM ('98 . $query . ') a99 ) b100 WHERE b.doctrine_rownum BETWEEN ' . $min . ' AND ' . $max;101 $query = 'SELECT b.'.$column.' FROM ('. 102 'SELECT a.*, ROWNUM AS doctrine_rownum FROM (' 103 . $query . ') a '. 104 ') b '. 105 'WHERE doctrine_rownum BETWEEN ' . $min . ' AND ' . $max; 101 106 } else { 102 $query = 'SELECT a. *FROM (' . $query .') a WHERE ROWNUM <= ' . $max;107 $query = 'SELECT a.'.$column.' FROM (' . $query .') a WHERE ROWNUM <= ' . $max; 103 108 } 104 109 } … … 106 111 return $query; 107 112 } 113 114 /** 115 * Creates the SQL for Oracle that can be used in the subquery for the limit-subquery 116 * algorithm. 117 */ 118 public function modifyLimitSubquery(Doctrine_Table $rootTable, $query, $limit = false, 119 $offset = false, $isManip = false) 120 { 121 // NOTE: no composite key support 122 $columnNames = $rootTable->getIdentifierColumnNames(); 123 if (count($columnNames) > 1) { 124 throw new Doctrine_Connection_Exception("Composite keys in LIMIT queries are " 125 . "currently not supported."); 126 } 127 $column = $columnNames[0]; 128 return $this->_createLimitSubquery($query, $limit, $offset, $column); 129 } 108 130 } -
branches/0.11/lib/Doctrine/Query.php
r4274 r4372 1202 1202 $modifyLimit = true; 1203 1203 if ( ! empty($this->_sqlParts['limit']) || ! empty($this->_sqlParts['offset'])) { 1204 1205 1204 if ($needsSubQuery) { 1206 1205 $subquery = $this->getLimitSubquery(); … … 1210 1209 case 'mysql': 1211 1210 // mysql doesn't support LIMIT in subqueries 1212 $list = $this->_conn->execute($subquery, $params)->fetchAll(Doctrine::FETCH_COLUMN);1211 $list = $this->_conn->execute($subquery, $params)->fetchAll(Doctrine::FETCH_COLUMN); 1213 1212 $subquery = implode(', ', array_map(array($this->_conn, 'quote'), $list)); 1214 1213 break; … … 1264 1263 public function getLimitSubquery() 1265 1264 { 1266 $map = reset($this->_queryComponents);1267 $table = $map['table'];1265 $map = reset($this->_queryComponents); 1266 $table = $map['table']; 1268 1267 $componentAlias = key($this->_queryComponents); 1269 1268 1270 1269 // get short alias 1271 $alias = $this->getTableAlias($componentAlias);1270 $alias = $this->getTableAlias($componentAlias); 1272 1271 // what about composite keys? 1273 1272 $primaryKey = $alias . '.' . $table->getColumnName($table->getIdentifier()); 1274 1273 1275 1274 // initialize the base of the subquery 1276 $subquery = 'SELECT DISTINCT ' . $this->_conn->quoteIdentifier($primaryKey);1275 $subquery = 'SELECT DISTINCT ' . $this->_conn->quoteIdentifier($primaryKey); 1277 1276 1278 1277 $driverName = $this->_conn->getAttribute(Doctrine::ATTR_DRIVER_NAME); … … 1332 1331 1333 1332 // add driver specific limit clause 1334 $subquery = $this->_conn->modifyLimit Query($subquery, $this->_sqlParts['limit'], $this->_sqlParts['offset']);1333 $subquery = $this->_conn->modifyLimitSubquery($table, $subquery, $this->_sqlParts['limit'], $this->_sqlParts['offset']); 1335 1334 1336 1335 $parts = $this->_tokenizer->quoteExplode($subquery, ' ', "'", "'"); -
branches/0.11/tests/Query/DriverTestCase.php
r3884 r4372 100 100 $q->from('User u')->limit(5)->offset(2); 101 101 102 $this->assertEqual($q->getSql(), 'SELECT * FROM (SELECT a.*, ROWNUM dctrn_rownum FROM (SELECT e.id AS e__id, e.name AS e__name, e.loginname AS e__loginname, e.password AS e__password, e.type AS e__type, e.created AS e__created, e.updated AS e__updated, e.email_id AS e__email_id FROM entity e WHERE (e.type = 0)) a WHERE ROWNUM <= 7) WHERE dctrn_rownum >= 3');102 $this->assertEqual($q->getSql(), 'SELECT b.* FROM (SELECT a.*, ROWNUM AS doctrine_rownum FROM (SELECT e.id AS e__id, e.name AS e__name, e.loginname AS e__loginname, e.password AS e__password, e.type AS e__type, e.created AS e__created, e.updated AS e__updated, e.email_id AS e__email_id FROM entity e WHERE (e.type = 0)) a ) b WHERE doctrine_rownum BETWEEN 3 AND 7'); 103 103 } 104 105 public function testLimitOffsetLimitSubqueriesForOracle() 106 { 107 $this->dbh = new Doctrine_Adapter_Mock('oracle'); 108 $conn = $this->manager->openConnection($this->dbh); 109 $q = new Doctrine_Query($conn); 110 $q->from('User u')->innerJoin('u.Phonenumber p')->limit(5)->offset(2); 111 112 $correctSql = "SELECT e.id AS e__id, e.name AS e__name, e.loginname AS e__loginname, " 113 . "e.password AS e__password, e.type AS e__type, e.created AS e__created, " 114 . "e.updated AS e__updated, e.email_id AS e__email_id, p.id AS p__id, " 115 . "p.phonenumber AS p__phonenumber, p.entity_id AS p__entity_id " 116 . "FROM entity e " 117 . "INNER JOIN phonenumber p ON e.id = p.entity_id " 118 . "WHERE e.id IN (" 119 . "SELECT b.id FROM (" 120 . "SELECT a.*, ROWNUM AS doctrine_rownum " 121 . "FROM (" 122 . "SELECT DISTINCT e2.id " 123 . "FROM entity e2 " 124 . "INNER JOIN phonenumber p2 ON e2.id = p2.entity_id " 125 . "WHERE (e2.type = 0)" 126 . ") a" 127 . " ) b " 128 . "WHERE doctrine_rownum BETWEEN 3 AND 7" 129 . ") AND (e.type = 0)"; 130 131 $this->assertEqual($q->getSql(), $correctSql); 132 } 133 104 134 }