From 903ae8a581fac1e6917fc3e31d2ad8fb91df80c3 Mon Sep 17 00:00:00 2001 From: ctrlaltca <> Date: Thu, 12 Jul 2012 11:21:01 +0000 Subject: standardize the use of unix eol; use svn properties to enforce native eol --- .../Data/Common/Mssql/TMssqlCommandBuilder.php | 346 ++++++++++----------- 1 file changed, 173 insertions(+), 173 deletions(-) (limited to 'framework/Data/Common/Mssql/TMssqlCommandBuilder.php') diff --git a/framework/Data/Common/Mssql/TMssqlCommandBuilder.php b/framework/Data/Common/Mssql/TMssqlCommandBuilder.php index 8a1e4dd6..3485adaa 100644 --- a/framework/Data/Common/Mssql/TMssqlCommandBuilder.php +++ b/framework/Data/Common/Mssql/TMssqlCommandBuilder.php @@ -1,173 +1,173 @@ - - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id: TDbCommandBuilder.php 1863 2007-04-12 12:43:49Z wei $ - * @package System.Data.Common - */ - -Prado::using('System.Data.Common.TDbCommandBuilder'); - -/** - * TMssqlCommandBuilder provides specifics methods to create limit/offset query commands - * for MSSQL servers. - * - * @author Wei Zhuo - * @version $Id: TDbCommandBuilder.php 1863 2007-04-12 12:43:49Z wei $ - * @package System.Data.Common - * @since 3.1 - */ -class TMssqlCommandBuilder extends TDbCommandBuilder -{ - /** - * Overrides parent implementation. Uses "SELECT @@Identity". - * @return integer last insert id, null if none is found. - */ - public function getLastInsertID() - { - foreach($this->getTableInfo()->getColumns() as $column) - { - if($column->hasSequence()) - { - $command = $this->getDbConnection()->createCommand('SELECT @@Identity'); - return intval($command->queryScalar()); - } - } - } - - /** - * Overrides parent implementation. Alters the sql to apply $limit and $offset. - * The idea for limit with offset is done by modifying the sql on the fly - * with numerous assumptions on the structure of the sql string. - * The modification is done with reference to the notes from - * http://troels.arvin.dk/db/rdbms/#select-limit-offset - * - * - * SELECT * FROM ( - * SELECT TOP n * FROM ( - * SELECT TOP z columns -- (z=n+skip) - * FROM tablename - * ORDER BY key ASC - * ) AS FOO ORDER BY key DESC -- ('FOO' may be anything) - * ) AS BAR ORDER BY key ASC -- ('BAR' may be anything) - * - * - * Regular expressions are used to alter the SQL query. The resulting SQL query - * may be malformed for complex queries. The following restrictions apply - * - * - * - * @param string SQL query string. - * @param integer maximum number of rows, -1 to ignore limit. - * @param integer row offset, -1 to ignore offset. - * @return string SQL with limit and offset. - */ - public function applyLimitOffset($sql, $limit=-1, $offset=-1) - { - $limit = $limit!==null ? intval($limit) : -1; - $offset = $offset!==null ? intval($offset) : -1; - if ($limit > 0 && $offset <= 0) //just limit - $sql = preg_replace('/^([\s(])*SELECT( DISTINCT)?(?!\s*TOP\s*\()/i',"\\1SELECT\\2 TOP $limit", $sql); - else if($limit > 0 && $offset > 0) - $sql = $this->rewriteLimitOffsetSql($sql, $limit,$offset); - return $sql; - } - - /** - * Rewrite sql to apply $limit > and $offset > 0 for MSSQL database. - * See http://troels.arvin.dk/db/rdbms/#select-limit-offset - * @param string sql query - * @param integer $limit > 0 - * @param integer $offset > 0 - * @return sql modified sql query applied with limit and offset. - */ - protected function rewriteLimitOffsetSql($sql, $limit, $offset) - { - $fetch = $limit+$offset; - $sql = preg_replace('/^([\s(])*SELECT( DISTINCT)?(?!\s*TOP\s*\()/i',"\\1SELECT\\2 TOP $fetch", $sql); - $ordering = $this->findOrdering($sql); - - $orginalOrdering = $this->joinOrdering($ordering); - $reverseOrdering = $this->joinOrdering($this->reverseDirection($ordering)); - $sql = "SELECT * FROM (SELECT TOP {$limit} * FROM ($sql) as [__inner top table__] {$reverseOrdering}) as [__outer top table__] {$orginalOrdering}"; - return $sql; - } - - /** - * Base on simplified syntax http://msdn2.microsoft.com/en-us/library/aa259187(SQL.80).aspx - * - * @param string $sql - * @return array ordering expression as key and ordering direction as value - */ - protected function findOrdering($sql) - { - if(!preg_match('/ORDER BY/i', $sql)) - return array(); - $matches=array(); - $ordering=array(); - preg_match_all('/(ORDER BY)[\s"\[](.*)(ASC|DESC)?(?:[\s"\[]|$|COMPUTE|FOR)/i', $sql, $matches); - if(count($matches)>1 && count($matches[2]) > 0) - { - $parts = explode(',', $matches[2][0]); - foreach($parts as $part) - { - $subs=array(); - if(preg_match_all('/(.*)[\s"\]](ASC|DESC)$/i', trim($part), $subs)) - { - if(count($subs) > 1 && count($subs[2]) > 0) - { - $ordering[$subs[1][0]] = $subs[2][0]; - } - //else what? - } - else - $ordering[trim($part)] = 'ASC'; - } - } - return $ordering; - } - - /** - * @param array ordering obtained from findOrdering() - * @return string concat the orderings - */ - protected function joinOrdering($orders) - { - if(count($orders)>0) - { - $str=array(); - foreach($orders as $column => $direction) - $str[] = $column.' '.$direction; - return 'ORDER BY '.implode(', ', $str); - } - } - - /** - * @param array original ordering - * @return array ordering with reversed direction. - */ - protected function reverseDirection($orders) - { - foreach($orders as $column => $direction) - $orders[$column] = strtolower(trim($direction))==='desc' ? 'ASC' : 'DESC'; - return $orders; - } -} - + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id: TDbCommandBuilder.php 1863 2007-04-12 12:43:49Z wei $ + * @package System.Data.Common + */ + +Prado::using('System.Data.Common.TDbCommandBuilder'); + +/** + * TMssqlCommandBuilder provides specifics methods to create limit/offset query commands + * for MSSQL servers. + * + * @author Wei Zhuo + * @version $Id: TDbCommandBuilder.php 1863 2007-04-12 12:43:49Z wei $ + * @package System.Data.Common + * @since 3.1 + */ +class TMssqlCommandBuilder extends TDbCommandBuilder +{ + /** + * Overrides parent implementation. Uses "SELECT @@Identity". + * @return integer last insert id, null if none is found. + */ + public function getLastInsertID() + { + foreach($this->getTableInfo()->getColumns() as $column) + { + if($column->hasSequence()) + { + $command = $this->getDbConnection()->createCommand('SELECT @@Identity'); + return intval($command->queryScalar()); + } + } + } + + /** + * Overrides parent implementation. Alters the sql to apply $limit and $offset. + * The idea for limit with offset is done by modifying the sql on the fly + * with numerous assumptions on the structure of the sql string. + * The modification is done with reference to the notes from + * http://troels.arvin.dk/db/rdbms/#select-limit-offset + * + * + * SELECT * FROM ( + * SELECT TOP n * FROM ( + * SELECT TOP z columns -- (z=n+skip) + * FROM tablename + * ORDER BY key ASC + * ) AS FOO ORDER BY key DESC -- ('FOO' may be anything) + * ) AS BAR ORDER BY key ASC -- ('BAR' may be anything) + * + * + * Regular expressions are used to alter the SQL query. The resulting SQL query + * may be malformed for complex queries. The following restrictions apply + * + * + * + * @param string SQL query string. + * @param integer maximum number of rows, -1 to ignore limit. + * @param integer row offset, -1 to ignore offset. + * @return string SQL with limit and offset. + */ + public function applyLimitOffset($sql, $limit=-1, $offset=-1) + { + $limit = $limit!==null ? intval($limit) : -1; + $offset = $offset!==null ? intval($offset) : -1; + if ($limit > 0 && $offset <= 0) //just limit + $sql = preg_replace('/^([\s(])*SELECT( DISTINCT)?(?!\s*TOP\s*\()/i',"\\1SELECT\\2 TOP $limit", $sql); + else if($limit > 0 && $offset > 0) + $sql = $this->rewriteLimitOffsetSql($sql, $limit,$offset); + return $sql; + } + + /** + * Rewrite sql to apply $limit > and $offset > 0 for MSSQL database. + * See http://troels.arvin.dk/db/rdbms/#select-limit-offset + * @param string sql query + * @param integer $limit > 0 + * @param integer $offset > 0 + * @return sql modified sql query applied with limit and offset. + */ + protected function rewriteLimitOffsetSql($sql, $limit, $offset) + { + $fetch = $limit+$offset; + $sql = preg_replace('/^([\s(])*SELECT( DISTINCT)?(?!\s*TOP\s*\()/i',"\\1SELECT\\2 TOP $fetch", $sql); + $ordering = $this->findOrdering($sql); + + $orginalOrdering = $this->joinOrdering($ordering); + $reverseOrdering = $this->joinOrdering($this->reverseDirection($ordering)); + $sql = "SELECT * FROM (SELECT TOP {$limit} * FROM ($sql) as [__inner top table__] {$reverseOrdering}) as [__outer top table__] {$orginalOrdering}"; + return $sql; + } + + /** + * Base on simplified syntax http://msdn2.microsoft.com/en-us/library/aa259187(SQL.80).aspx + * + * @param string $sql + * @return array ordering expression as key and ordering direction as value + */ + protected function findOrdering($sql) + { + if(!preg_match('/ORDER BY/i', $sql)) + return array(); + $matches=array(); + $ordering=array(); + preg_match_all('/(ORDER BY)[\s"\[](.*)(ASC|DESC)?(?:[\s"\[]|$|COMPUTE|FOR)/i', $sql, $matches); + if(count($matches)>1 && count($matches[2]) > 0) + { + $parts = explode(',', $matches[2][0]); + foreach($parts as $part) + { + $subs=array(); + if(preg_match_all('/(.*)[\s"\]](ASC|DESC)$/i', trim($part), $subs)) + { + if(count($subs) > 1 && count($subs[2]) > 0) + { + $ordering[$subs[1][0]] = $subs[2][0]; + } + //else what? + } + else + $ordering[trim($part)] = 'ASC'; + } + } + return $ordering; + } + + /** + * @param array ordering obtained from findOrdering() + * @return string concat the orderings + */ + protected function joinOrdering($orders) + { + if(count($orders)>0) + { + $str=array(); + foreach($orders as $column => $direction) + $str[] = $column.' '.$direction; + return 'ORDER BY '.implode(', ', $str); + } + } + + /** + * @param array original ordering + * @return array ordering with reversed direction. + */ + protected function reverseDirection($orders) + { + foreach($orders as $column => $direction) + $orders[$column] = strtolower(trim($direction))==='desc' ? 'ASC' : 'DESC'; + return $orders; + } +} + -- cgit v1.2.3