# Coverage for Doctrine_Connection_Mssql

Back to coverage report

1 | <?php
2 | /*
3 | * $Id: Mssql.php 2963 2007-10-21 06:23:59Z Jonathan.Wage $
4 | *
5 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | *
17 | * This software consists of voluntary contributions made by many individuals
18 | * and is licensed under the LGPL. For more information, see
19 | * <http://www.phpdoctrine.org>.
20 | */
21 | Doctrine::autoload('Doctrine_Connection');
22 | /**
23 | * Doctrine_Connection_Mssql
24 | *
25 | * @package Doctrine
26 | * @subpackage Connection
27 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
28 | * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
29 | * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
30 | * @version $Revision: 2963 $
31 | * @link www.phpdoctrine.org
32 | * @since 1.0
33 | */
34 | class Doctrine_Connection_Mssql extends Doctrine_Connection
35 | {
36 | /**
37 | * @var string $driverName the name of this connection driver
38 | */
39 | protected $driverName = 'Mssql';
40 |
41 | /**
42 | * the constructor
43 | *
44 | * @param Doctrine_Manager $manager
45 | * @param PDO $pdo database handle
46 | */
47 | public function __construct(Doctrine_Manager $manager, $adapter)
48 | {
49 | // initialize all driver options
50 | $this->supported = array(
51 | 'sequences' => 'emulated',
52 | 'indexes' => true,
53 | 'affected_rows' => true,
54 | 'transactions' => true,
55 | 'summary_functions' => true,
56 | 'order_by_text' => true,
57 | 'current_id' => 'emulated',
58 | 'limit_queries' => 'emulated',
59 | 'LOBs' => true,
60 | 'replace' => 'emulated',
61 | 'sub_selects' => true,
62 | 'auto_increment' => true,
63 | 'primary_key' => true,
64 | 'result_introspection' => true,
65 | 'prepared_statements' => 'emulated',
66 | );
67 |
68 | parent::__construct($manager, $adapter);
69 | }
70 |
71 | /**
72 | * quoteIdentifier
73 | * Quote a string so it can be safely used as a table / column name
74 | *
75 | * Quoting style depends on which database driver is being used.
76 | *
77 | * @param string $identifier identifier name to be quoted
78 | * @param bool $checkOption check the 'quote_identifier' option
79 | *
80 | * @return string quoted identifier string
81 | */
82 | public function quoteIdentifier($identifier, $checkOption = false)
83 | {
84 | if ($checkOption && ! $this->getAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER)) {
85 | return $identifier;
86 | }
87 | return '[' . str_replace(']', ']]', $identifier) . ']';
88 | }
89 |
90 | /**
91 | * Adds an adapter-specific LIMIT clause to the SELECT statement.
92 | * [ borrowed from Zend Framework ]
93 | *
94 | * @param string $query
95 | * @param mixed $limit
96 | * @param mixed $offset
97 | * @link http://lists.bestpractical.com/pipermail/rt-devel/2005-June/007339.html
98 | * @return string
99 | */
100 | public function modifyLimitQuery($query, $limit, $offset, $isManip = false)
101 | {
102 | if ($limit > 0) {
103 | $count = intval($limit);
104 |
105 | $offset = intval($offset);
106 | if ($offset < 0) {
107 | throw new Doctrine_Connection_Exception("LIMIT argument offset=$offset is not valid");
108 | }
109 |
110 | $orderby = stristr($query, 'ORDER BY');
111 | if ($orderby !== false) {
112 | $sort = (stripos($orderby, 'desc') !== false) ? 'desc' : 'asc';
113 | $order = str_ireplace('ORDER BY', '', $orderby);
114 | $order = trim(preg_replace('/ASC|DESC/i', '', $order));
115 | }
116 |
117 | $query = preg_replace('/^SELECT\s/i', 'SELECT TOP ' . ($count+$offset) . ' ', $query);
118 |
119 | $query = 'SELECT * FROM (SELECT TOP ' . $count . ' * FROM (' . $query . ') AS inner_tbl';
120 | if ($orderby !== false) {
121 | $query .= ' ORDER BY ' . $order . ' ';
122 | $query .= (stripos($sort, 'asc') !== false) ? 'DESC' : 'ASC';
123 | }
124 | $query .= ') AS outer_tbl';
125 | if ($orderby !== false) {
126 | $query .= ' ORDER BY ' . $order . ' ' . $sort;
127 | }
128 |
129 | return $query;
130 |
131 | }
132 |
133 | return $query;
134 | }
135 |
136 | /**
137 | * return version information about the server
138 | *
139 | * @param bool $native determines if the raw version string should be returned
140 | * @return mixed array/string with version information or MDB2 error object
141 | */
142 | public function getServerVersion($native = false)
143 | {
144 | if ($this->serverInfo) {
145 | $serverInfo = $this->serverInfo;
146 | } else {
147 | $query = 'SELECT @@VERSION';
148 | $serverInfo = $this->fetchOne($query);
149 | }
150 | // cache server_info
151 | $this->serverInfo = $serverInfo;
152 | if ( ! $native) {
153 | if (preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $serverInfo, $tmp)) {
154 | $serverInfo = array(
155 | 'major' => $tmp[1],
156 | 'minor' => $tmp[2],
157 | 'patch' => $tmp[3],
158 | 'extra' => null,
159 | 'native' => $serverInfo,
160 | );
161 | } else {
162 | $serverInfo = array(
163 | 'major' => null,
164 | 'minor' => null,
165 | 'patch' => null,
166 | 'extra' => null,
167 | 'native' => $serverInfo,
168 | );
169 | }
170 | }
171 | return $serverInfo;
172 | }
173 |
174 | /**
175 | * Checks if there's a sequence that exists.
176 | *
177 | * @param string $seq_name The sequence name to verify.
178 | * @return boolean The value if the table exists or not
179 | */
180 | public function checkSequence($seqName)
181 | {
182 | $query = 'SELECT * FROM ' . $seqName;
183 | try {
184 | $this->exec($query);
185 | } catch(Doctrine_Connection_Exception $e) {
186 | if ($e->getPortableCode() == Doctrine::ERR_NOSUCHTABLE) {
187 | return false;
188 | }
189 |
190 | throw $e;
191 | }
192 | return true;
193 | }
194 | }