Редакция 2 | Только различия | Учитывать пробелы | Содержимое файла | Авторство | Последнее изменение | Открыть журнал | RSS
Редакция 2 | Редакция 87 | ||
---|---|---|---|
1 | <?php
|
1 | <?php
|
2 | 2 | ||
3 | /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
3 | /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
4 | 4 | ||
5 | /**
|
5 | /**
|
6 | * The PEAR DB driver for PHP's mssql extension
|
6 | * The PEAR DB driver for PHP's mssql extension
|
7 | * for interacting with Microsoft SQL Server databases
|
7 | * for interacting with Microsoft SQL Server databases
|
8 | *
|
8 | *
|
9 | * PHP versions 4 and 5
|
9 | * PHP versions 4 and 5
|
10 | *
|
10 | *
|
11 | * LICENSE: This source file is subject to version 3.0 of the PHP license
|
11 | * LICENSE: This source file is subject to version 3.0 of the PHP license
|
12 | * that is available through the world-wide-web at the following URI:
|
12 | * that is available through the world-wide-web at the following URI:
|
13 | * http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
13 | * http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
14 | * the PHP License and are unable to obtain it through the web, please
|
14 | * the PHP License and are unable to obtain it through the web, please
|
15 | * send a note to license@php.net so we can mail you a copy immediately.
|
15 | * send a note to license@php.net so we can mail you a copy immediately.
|
16 | *
|
16 | *
|
17 | * @category Database
|
17 | * @category Database
|
18 | * @package DB
|
18 | * @package DB
|
19 | * @author Sterling Hughes <sterling@php.net>
|
19 | * @author Sterling Hughes <sterling@php.net>
|
20 | * @author Daniel Convissor <danielc@php.net>
|
20 | * @author Daniel Convissor <danielc@php.net>
|
21 | * @copyright 1997-2007 The PHP Group
|
21 | * @copyright 1997-2007 The PHP Group
|
22 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
22 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
23 | * @version CVS: $Id: mssql.php,v 1.92 2007/09/21 13:40:41 aharvey Exp $
|
23 | * @version CVS: $Id: mssql.php,v 1.92 2007/09/21 13:40:41 aharvey Exp $
|
24 | * @link http://pear.php.net/package/DB
|
24 | * @link http://pear.php.net/package/DB
|
25 | */
|
25 | */
|
26 | 26 | ||
27 | /**
|
27 | /**
|
28 | * Obtain the DB_common class so it can be extended from
|
28 | * Obtain the DB_common class so it can be extended from
|
29 | */
|
29 | */
|
30 | require_once 'DB/common.php'; |
30 | require_once 'DB/common.php'; |
31 | 31 | ||
32 | /**
|
32 | /**
|
33 | * The methods PEAR DB uses to interact with PHP's mssql extension
|
33 | * The methods PEAR DB uses to interact with PHP's mssql extension
|
34 | * for interacting with Microsoft SQL Server databases
|
34 | * for interacting with Microsoft SQL Server databases
|
35 | *
|
35 | *
|
36 | * These methods overload the ones declared in DB_common.
|
36 | * These methods overload the ones declared in DB_common.
|
37 | *
|
37 | *
|
38 | * DB's mssql driver is only for Microsfoft SQL Server databases.
|
38 | * DB's mssql driver is only for Microsfoft SQL Server databases.
|
39 | *
|
39 | *
|
40 | * If you're connecting to a Sybase database, you MUST specify "sybase"
|
40 | * If you're connecting to a Sybase database, you MUST specify "sybase"
|
41 | * as the "phptype" in the DSN.
|
41 | * as the "phptype" in the DSN.
|
42 | *
|
42 | *
|
43 | * This class only works correctly if you have compiled PHP using
|
43 | * This class only works correctly if you have compiled PHP using
|
44 | * --with-mssql=[dir_to_FreeTDS].
|
44 | * --with-mssql=[dir_to_FreeTDS].
|
45 | *
|
45 | *
|
46 | * @category Database
|
46 | * @category Database
|
47 | * @package DB
|
47 | * @package DB
|
48 | * @author Sterling Hughes <sterling@php.net>
|
48 | * @author Sterling Hughes <sterling@php.net>
|
49 | * @author Daniel Convissor <danielc@php.net>
|
49 | * @author Daniel Convissor <danielc@php.net>
|
50 | * @copyright 1997-2007 The PHP Group
|
50 | * @copyright 1997-2007 The PHP Group
|
51 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
51 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
52 | * @version Release: 1.7.13
|
52 | * @version Release: 1.7.13
|
53 | * @link http://pear.php.net/package/DB
|
53 | * @link http://pear.php.net/package/DB
|
54 | */
|
54 | */
|
55 | class DB_mssql extends DB_common |
55 | class DB_mssql extends DB_common |
56 | {
|
56 | {
|
57 | // {{{ properties
|
57 | // {{{ properties
|
58 | 58 | ||
59 | /**
|
59 | /**
|
60 | * The DB driver type (mysql, oci8, odbc, etc.)
|
60 | * The DB driver type (mysql, oci8, odbc, etc.)
|
61 | * @var string
|
61 | * @var string
|
62 | */
|
62 | */
|
63 | var $phptype = 'mssql'; |
63 | var $phptype = 'mssql'; |
64 | 64 | ||
65 | /**
|
65 | /**
|
66 | * The database syntax variant to be used (db2, access, etc.), if any
|
66 | * The database syntax variant to be used (db2, access, etc.), if any
|
67 | * @var string
|
67 | * @var string
|
68 | */
|
68 | */
|
69 | var $dbsyntax = 'mssql'; |
69 | var $dbsyntax = 'mssql'; |
70 | 70 | ||
71 | /**
|
71 | /**
|
72 | * The capabilities of this DB implementation
|
72 | * The capabilities of this DB implementation
|
73 | *
|
73 | *
|
74 | * The 'new_link' element contains the PHP version that first provided
|
74 | * The 'new_link' element contains the PHP version that first provided
|
75 | * new_link support for this DBMS. Contains false if it's unsupported.
|
75 | * new_link support for this DBMS. Contains false if it's unsupported.
|
76 | *
|
76 | *
|
77 | * Meaning of the 'limit' element:
|
77 | * Meaning of the 'limit' element:
|
78 | * + 'emulate' = emulate with fetch row by number
|
78 | * + 'emulate' = emulate with fetch row by number
|
79 | * + 'alter' = alter the query
|
79 | * + 'alter' = alter the query
|
80 | * + false = skip rows
|
80 | * + false = skip rows
|
81 | *
|
81 | *
|
82 | * @var array
|
82 | * @var array
|
83 | */
|
83 | */
|
84 | var $features = array( |
84 | var $features = array( |
85 | 'limit' => 'emulate', |
85 | 'limit' => 'emulate', |
86 | 'new_link' => false, |
86 | 'new_link' => false, |
87 | 'numrows' => true, |
87 | 'numrows' => true, |
88 | 'pconnect' => true, |
88 | 'pconnect' => true, |
89 | 'prepare' => false, |
89 | 'prepare' => false, |
90 | 'ssl' => false, |
90 | 'ssl' => false, |
91 | 'transactions' => true, |
91 | 'transactions' => true, |
92 | ); |
92 | ); |
93 | 93 | ||
94 | /**
|
94 | /**
|
95 | * A mapping of native error codes to DB error codes
|
95 | * A mapping of native error codes to DB error codes
|
96 | * @var array
|
96 | * @var array
|
97 | */
|
97 | */
|
98 | // XXX Add here error codes ie: 'S100E' => DB_ERROR_SYNTAX
|
98 | // XXX Add here error codes ie: 'S100E' => DB_ERROR_SYNTAX
|
99 | var $errorcode_map = array( |
99 | var $errorcode_map = array( |
100 | 102 => DB_ERROR_SYNTAX, |
100 | 102 => DB_ERROR_SYNTAX, |
101 | 110 => DB_ERROR_VALUE_COUNT_ON_ROW, |
101 | 110 => DB_ERROR_VALUE_COUNT_ON_ROW, |
102 | 155 => DB_ERROR_NOSUCHFIELD, |
102 | 155 => DB_ERROR_NOSUCHFIELD, |
103 | 156 => DB_ERROR_SYNTAX, |
103 | 156 => DB_ERROR_SYNTAX, |
104 | 170 => DB_ERROR_SYNTAX, |
104 | 170 => DB_ERROR_SYNTAX, |
105 | 207 => DB_ERROR_NOSUCHFIELD, |
105 | 207 => DB_ERROR_NOSUCHFIELD, |
106 | 208 => DB_ERROR_NOSUCHTABLE, |
106 | 208 => DB_ERROR_NOSUCHTABLE, |
107 | 245 => DB_ERROR_INVALID_NUMBER, |
107 | 245 => DB_ERROR_INVALID_NUMBER, |
108 | 319 => DB_ERROR_SYNTAX, |
108 | 319 => DB_ERROR_SYNTAX, |
109 | 321 => DB_ERROR_NOSUCHFIELD, |
109 | 321 => DB_ERROR_NOSUCHFIELD, |
110 | 325 => DB_ERROR_SYNTAX, |
110 | 325 => DB_ERROR_SYNTAX, |
111 | 336 => DB_ERROR_SYNTAX, |
111 | 336 => DB_ERROR_SYNTAX, |
112 | 515 => DB_ERROR_CONSTRAINT_NOT_NULL, |
112 | 515 => DB_ERROR_CONSTRAINT_NOT_NULL, |
113 | 547 => DB_ERROR_CONSTRAINT, |
113 | 547 => DB_ERROR_CONSTRAINT, |
114 | 1018 => DB_ERROR_SYNTAX, |
114 | 1018 => DB_ERROR_SYNTAX, |
115 | 1035 => DB_ERROR_SYNTAX, |
115 | 1035 => DB_ERROR_SYNTAX, |
116 | 1913 => DB_ERROR_ALREADY_EXISTS, |
116 | 1913 => DB_ERROR_ALREADY_EXISTS, |
117 | 2209 => DB_ERROR_SYNTAX, |
117 | 2209 => DB_ERROR_SYNTAX, |
118 | 2223 => DB_ERROR_SYNTAX, |
118 | 2223 => DB_ERROR_SYNTAX, |
119 | 2248 => DB_ERROR_SYNTAX, |
119 | 2248 => DB_ERROR_SYNTAX, |
120 | 2256 => DB_ERROR_SYNTAX, |
120 | 2256 => DB_ERROR_SYNTAX, |
121 | 2257 => DB_ERROR_SYNTAX, |
121 | 2257 => DB_ERROR_SYNTAX, |
122 | 2627 => DB_ERROR_CONSTRAINT, |
122 | 2627 => DB_ERROR_CONSTRAINT, |
123 | 2714 => DB_ERROR_ALREADY_EXISTS, |
123 | 2714 => DB_ERROR_ALREADY_EXISTS, |
124 | 3607 => DB_ERROR_DIVZERO, |
124 | 3607 => DB_ERROR_DIVZERO, |
125 | 3701 => DB_ERROR_NOSUCHTABLE, |
125 | 3701 => DB_ERROR_NOSUCHTABLE, |
126 | 7630 => DB_ERROR_SYNTAX, |
126 | 7630 => DB_ERROR_SYNTAX, |
127 | 8134 => DB_ERROR_DIVZERO, |
127 | 8134 => DB_ERROR_DIVZERO, |
128 | 9303 => DB_ERROR_SYNTAX, |
128 | 9303 => DB_ERROR_SYNTAX, |
129 | 9317 => DB_ERROR_SYNTAX, |
129 | 9317 => DB_ERROR_SYNTAX, |
130 | 9318 => DB_ERROR_SYNTAX, |
130 | 9318 => DB_ERROR_SYNTAX, |
131 | 9331 => DB_ERROR_SYNTAX, |
131 | 9331 => DB_ERROR_SYNTAX, |
132 | 9332 => DB_ERROR_SYNTAX, |
132 | 9332 => DB_ERROR_SYNTAX, |
133 | 15253 => DB_ERROR_SYNTAX, |
133 | 15253 => DB_ERROR_SYNTAX, |
134 | ); |
134 | ); |
135 | 135 | ||
136 | /**
|
136 | /**
|
137 | * The raw database connection created by PHP
|
137 | * The raw database connection created by PHP
|
138 | * @var resource
|
138 | * @var resource
|
139 | */
|
139 | */
|
140 | var $connection; |
140 | var $connection; |
141 | 141 | ||
142 | /**
|
142 | /**
|
143 | * The DSN information for connecting to a database
|
143 | * The DSN information for connecting to a database
|
144 | * @var array
|
144 | * @var array
|
145 | */
|
145 | */
|
146 | var $dsn = array(); |
146 | var $dsn = array(); |
147 | 147 | ||
148 | 148 | ||
149 | /**
|
149 | /**
|
150 | * Should data manipulation queries be committed automatically?
|
150 | * Should data manipulation queries be committed automatically?
|
151 | * @var bool
|
151 | * @var bool
|
152 | * @access private
|
152 | * @access private
|
153 | */
|
153 | */
|
154 | var $autocommit = true; |
154 | var $autocommit = true; |
155 | 155 | ||
156 | /**
|
156 | /**
|
157 | * The quantity of transactions begun
|
157 | * The quantity of transactions begun
|
158 | *
|
158 | *
|
159 | * {@internal While this is private, it can't actually be designated
|
159 | * {@internal While this is private, it can't actually be designated
|
160 | * private in PHP 5 because it is directly accessed in the test suite.}}
|
160 | * private in PHP 5 because it is directly accessed in the test suite.}}
|
161 | *
|
161 | *
|
162 | * @var integer
|
162 | * @var integer
|
163 | * @access private
|
163 | * @access private
|
164 | */
|
164 | */
|
165 | var $transaction_opcount = 0; |
165 | var $transaction_opcount = 0; |
166 | 166 | ||
167 | /**
|
167 | /**
|
168 | * The database specified in the DSN
|
168 | * The database specified in the DSN
|
169 | *
|
169 | *
|
170 | * It's a fix to allow calls to different databases in the same script.
|
170 | * It's a fix to allow calls to different databases in the same script.
|
171 | *
|
171 | *
|
172 | * @var string
|
172 | * @var string
|
173 | * @access private
|
173 | * @access private
|
174 | */
|
174 | */
|
175 | var $_db = null; |
175 | var $_db = null; |
176 | 176 | ||
177 | 177 | ||
178 | // }}}
|
178 | // }}}
|
179 | // {{{ constructor
|
179 | // {{{ constructor
|
180 | 180 | ||
181 | /**
|
181 | /**
|
182 | * This constructor calls <kbd>$this->DB_common()</kbd>
|
182 | * This constructor calls <kbd>$this->DB_common()</kbd>
|
183 | *
|
183 | *
|
184 | * @return void
|
184 | * @return void
|
185 | */
|
185 | */
|
186 | function DB_mssql() |
186 | function DB_mssql() |
187 | {
|
187 | {
|
188 | $this->DB_common(); |
188 | $this->DB_common(); |
189 | }
|
189 | }
|
190 | 190 | ||
191 | // }}}
|
191 | // }}}
|
192 | // {{{ connect()
|
192 | // {{{ connect()
|
193 | 193 | ||
194 | /**
|
194 | /**
|
195 | * Connect to the database server, log in and open the database
|
195 | * Connect to the database server, log in and open the database
|
196 | *
|
196 | *
|
197 | * Don't call this method directly. Use DB::connect() instead.
|
197 | * Don't call this method directly. Use DB::connect() instead.
|
198 | *
|
198 | *
|
199 | * @param array $dsn the data source name
|
199 | * @param array $dsn the data source name
|
200 | * @param bool $persistent should the connection be persistent?
|
200 | * @param bool $persistent should the connection be persistent?
|
201 | *
|
201 | *
|
202 | * @return int DB_OK on success. A DB_Error object on failure.
|
202 | * @return int DB_OK on success. A DB_Error object on failure.
|
203 | */
|
203 | */
|
204 | function connect($dsn, $persistent = false) |
204 | function connect($dsn, $persistent = false) |
205 | {
|
205 | {
|
206 | if (!PEAR::loadExtension('mssql') && !PEAR::loadExtension('sybase') |
206 | if (!PEAR::loadExtension('mssql') && !PEAR::loadExtension('sybase') |
207 | && !PEAR::loadExtension('sybase_ct')) |
207 | && !PEAR::loadExtension('sybase_ct')) |
208 | {
|
208 | {
|
209 | return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
209 | return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
210 | }
|
210 | }
|
211 | 211 | ||
212 | $this->dsn = $dsn; |
212 | $this->dsn = $dsn; |
213 | if ($dsn['dbsyntax']) { |
213 | if ($dsn['dbsyntax']) { |
214 | $this->dbsyntax = $dsn['dbsyntax']; |
214 | $this->dbsyntax = $dsn['dbsyntax']; |
215 | }
|
215 | }
|
216 | 216 | ||
217 | $params = array( |
217 | $params = array( |
218 | $dsn['hostspec'] ? $dsn['hostspec'] : 'localhost', |
218 | $dsn['hostspec'] ? $dsn['hostspec'] : 'localhost', |
219 | $dsn['username'] ? $dsn['username'] : null, |
219 | $dsn['username'] ? $dsn['username'] : null, |
220 | $dsn['password'] ? $dsn['password'] : null, |
220 | $dsn['password'] ? $dsn['password'] : null, |
221 | ); |
221 | ); |
222 | if ($dsn['port']) { |
222 | if ($dsn['port']) { |
223 | $params[0] .= ((substr(PHP_OS, 0, 3) == 'WIN') ? ',' : ':') |
223 | $params[0] .= ((substr(PHP_OS, 0, 3) == 'WIN') ? ',' : ':') |
224 | . $dsn['port']; |
224 | . $dsn['port']; |
225 | }
|
225 | }
|
226 | 226 | ||
227 | $connect_function = $persistent ? 'mssql_pconnect' : 'mssql_connect'; |
227 | $connect_function = $persistent ? 'mssql_pconnect' : 'mssql_connect'; |
228 | 228 | ||
229 | $this->connection = @call_user_func_array($connect_function, $params); |
229 | $this->connection = @call_user_func_array($connect_function, $params); |
230 | 230 | ||
231 | if (!$this->connection) { |
231 | if (!$this->connection) { |
232 | return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
232 | return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
233 | null, null, null, |
233 | null, null, null, |
234 | @mssql_get_last_message()); |
234 | @mssql_get_last_message()); |
235 | }
|
235 | }
|
236 | if ($dsn['database']) { |
236 | if ($dsn['database']) { |
237 | if (!@mssql_select_db($dsn['database'], $this->connection)) { |
237 | if (!@mssql_select_db($dsn['database'], $this->connection)) { |
238 | return $this->raiseError(DB_ERROR_NODBSELECTED, |
238 | return $this->raiseError(DB_ERROR_NODBSELECTED, |
239 | null, null, null, |
239 | null, null, null, |
240 | @mssql_get_last_message()); |
240 | @mssql_get_last_message()); |
241 | }
|
241 | }
|
242 | $this->_db = $dsn['database']; |
242 | $this->_db = $dsn['database']; |
243 | }
|
243 | }
|
244 | return DB_OK; |
244 | return DB_OK; |
245 | }
|
245 | }
|
246 | 246 | ||
247 | // }}}
|
247 | // }}}
|
248 | // {{{ disconnect()
|
248 | // {{{ disconnect()
|
249 | 249 | ||
250 | /**
|
250 | /**
|
251 | * Disconnects from the database server
|
251 | * Disconnects from the database server
|
252 | *
|
252 | *
|
253 | * @return bool TRUE on success, FALSE on failure
|
253 | * @return bool TRUE on success, FALSE on failure
|
254 | */
|
254 | */
|
255 | function disconnect() |
255 | function disconnect() |
256 | {
|
256 | {
|
257 | $ret = @mssql_close($this->connection); |
257 | $ret = @mssql_close($this->connection); |
258 | $this->connection = null; |
258 | $this->connection = null; |
259 | return $ret; |
259 | return $ret; |
260 | }
|
260 | }
|
261 | 261 | ||
262 | // }}}
|
262 | // }}}
|
263 | // {{{ simpleQuery()
|
263 | // {{{ simpleQuery()
|
264 | 264 | ||
265 | /**
|
265 | /**
|
266 | * Sends a query to the database server
|
266 | * Sends a query to the database server
|
267 | *
|
267 | *
|
268 | * @param string the SQL query string
|
268 | * @param string the SQL query string
|
269 | *
|
269 | *
|
270 | * @return mixed + a PHP result resrouce for successful SELECT queries
|
270 | * @return mixed + a PHP result resrouce for successful SELECT queries
|
271 | * + the DB_OK constant for other successful queries
|
271 | * + the DB_OK constant for other successful queries
|
272 | * + a DB_Error object on failure
|
272 | * + a DB_Error object on failure
|
273 | */
|
273 | */
|
274 | function simpleQuery($query) |
274 | function simpleQuery($query) |
275 | {
|
275 | {
|
276 | $ismanip = $this->_checkManip($query); |
276 | $ismanip = $this->_checkManip($query); |
277 | $this->last_query = $query; |
277 | $this->last_query = $query; |
278 | if (!@mssql_select_db($this->_db, $this->connection)) { |
278 | if (!@mssql_select_db($this->_db, $this->connection)) { |
279 | return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
279 | return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
280 | }
|
280 | }
|
281 | $query = $this->modifyQuery($query); |
281 | $query = $this->modifyQuery($query); |
282 | if (!$this->autocommit && $ismanip) { |
282 | if (!$this->autocommit && $ismanip) { |
283 | if ($this->transaction_opcount == 0) { |
283 | if ($this->transaction_opcount == 0) { |
284 | $result = @mssql_query('BEGIN TRAN', $this->connection); |
284 | $result = @mssql_query('BEGIN TRAN', $this->connection); |
285 | if (!$result) { |
285 | if (!$result) { |
286 | return $this->mssqlRaiseError(); |
286 | return $this->mssqlRaiseError(); |
287 | }
|
287 | }
|
288 | }
|
288 | }
|
289 | $this->transaction_opcount++; |
289 | $this->transaction_opcount++; |
290 | }
|
290 | }
|
291 | $result = @mssql_query($query, $this->connection); |
291 | $result = @mssql_query($query, $this->connection); |
292 | if (!$result) { |
292 | if (!$result) { |
293 | return $this->mssqlRaiseError(); |
293 | return $this->mssqlRaiseError(); |
294 | }
|
294 | }
|
295 | // Determine which queries that should return data, and which
|
295 | // Determine which queries that should return data, and which
|
296 | // should return an error code only.
|
296 | // should return an error code only.
|
297 | return $ismanip ? DB_OK : $result; |
297 | return $ismanip ? DB_OK : $result; |
298 | }
|
298 | }
|
299 | 299 | ||
300 | // }}}
|
300 | // }}}
|
301 | // {{{ nextResult()
|
301 | // {{{ nextResult()
|
302 | 302 | ||
303 | /**
|
303 | /**
|
304 | * Move the internal mssql result pointer to the next available result
|
304 | * Move the internal mssql result pointer to the next available result
|
305 | *
|
305 | *
|
306 | * @param a valid fbsql result resource
|
306 | * @param a valid fbsql result resource
|
307 | *
|
307 | *
|
308 | * @access public
|
308 | * @access public
|
309 | *
|
309 | *
|
310 | * @return true if a result is available otherwise return false
|
310 | * @return true if a result is available otherwise return false
|
311 | */
|
311 | */
|
312 | function nextResult($result) |
312 | function nextResult($result) |
313 | {
|
313 | {
|
314 | return @mssql_next_result($result); |
314 | return @mssql_next_result($result); |
315 | }
|
315 | }
|
316 | 316 | ||
317 | // }}}
|
317 | // }}}
|
318 | // {{{ fetchInto()
|
318 | // {{{ fetchInto()
|
319 | 319 | ||
320 | /**
|
320 | /**
|
321 | * Places a row from the result set into the given array
|
321 | * Places a row from the result set into the given array
|
322 | *
|
322 | *
|
323 | * Formating of the array and the data therein are configurable.
|
323 | * Formating of the array and the data therein are configurable.
|
324 | * See DB_result::fetchInto() for more information.
|
324 | * See DB_result::fetchInto() for more information.
|
325 | *
|
325 | *
|
326 | * This method is not meant to be called directly. Use
|
326 | * This method is not meant to be called directly. Use
|
327 | * DB_result::fetchInto() instead. It can't be declared "protected"
|
327 | * DB_result::fetchInto() instead. It can't be declared "protected"
|
328 | * because DB_result is a separate object.
|
328 | * because DB_result is a separate object.
|
329 | *
|
329 | *
|
330 | * @param resource $result the query result resource
|
330 | * @param resource $result the query result resource
|
331 | * @param array $arr the referenced array to put the data in
|
331 | * @param array $arr the referenced array to put the data in
|
332 | * @param int $fetchmode how the resulting array should be indexed
|
332 | * @param int $fetchmode how the resulting array should be indexed
|
333 | * @param int $rownum the row number to fetch (0 = first row)
|
333 | * @param int $rownum the row number to fetch (0 = first row)
|
334 | *
|
334 | *
|
335 | * @return mixed DB_OK on success, NULL when the end of a result set is
|
335 | * @return mixed DB_OK on success, NULL when the end of a result set is
|
336 | * reached or on failure
|
336 | * reached or on failure
|
337 | *
|
337 | *
|
338 | * @see DB_result::fetchInto()
|
338 | * @see DB_result::fetchInto()
|
339 | */
|
339 | */
|
340 | function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
340 | function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
341 | {
|
341 | {
|
342 | if ($rownum !== null) { |
342 | if ($rownum !== null) { |
343 | if (!@mssql_data_seek($result, $rownum)) { |
343 | if (!@mssql_data_seek($result, $rownum)) { |
344 | return null; |
344 | return null; |
345 | }
|
345 | }
|
346 | }
|
346 | }
|
347 | if ($fetchmode & DB_FETCHMODE_ASSOC) { |
347 | if ($fetchmode & DB_FETCHMODE_ASSOC) { |
348 | $arr = @mssql_fetch_assoc($result); |
348 | $arr = @mssql_fetch_assoc($result); |
349 | if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { |
349 | if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { |
350 | $arr = array_change_key_case($arr, CASE_LOWER); |
350 | $arr = array_change_key_case($arr, CASE_LOWER); |
351 | }
|
351 | }
|
352 | } else { |
352 | } else { |
353 | $arr = @mssql_fetch_row($result); |
353 | $arr = @mssql_fetch_row($result); |
354 | }
|
354 | }
|
355 | if (!$arr) { |
355 | if (!$arr) { |
356 | return null; |
356 | return null; |
357 | }
|
357 | }
|
358 | if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
358 | if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
359 | $this->_rtrimArrayValues($arr); |
359 | $this->_rtrimArrayValues($arr); |
360 | }
|
360 | }
|
361 | if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
361 | if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
362 | $this->_convertNullArrayValuesToEmpty($arr); |
362 | $this->_convertNullArrayValuesToEmpty($arr); |
363 | }
|
363 | }
|
364 | return DB_OK; |
364 | return DB_OK; |
365 | }
|
365 | }
|
366 | 366 | ||
367 | // }}}
|
367 | // }}}
|
368 | // {{{ freeResult()
|
368 | // {{{ freeResult()
|
369 | 369 | ||
370 | /**
|
370 | /**
|
371 | * Deletes the result set and frees the memory occupied by the result set
|
371 | * Deletes the result set and frees the memory occupied by the result set
|
372 | *
|
372 | *
|
373 | * This method is not meant to be called directly. Use
|
373 | * This method is not meant to be called directly. Use
|
374 | * DB_result::free() instead. It can't be declared "protected"
|
374 | * DB_result::free() instead. It can't be declared "protected"
|
375 | * because DB_result is a separate object.
|
375 | * because DB_result is a separate object.
|
376 | *
|
376 | *
|
377 | * @param resource $result PHP's query result resource
|
377 | * @param resource $result PHP's query result resource
|
378 | *
|
378 | *
|
379 | * @return bool TRUE on success, FALSE if $result is invalid
|
379 | * @return bool TRUE on success, FALSE if $result is invalid
|
380 | *
|
380 | *
|
381 | * @see DB_result::free()
|
381 | * @see DB_result::free()
|
382 | */
|
382 | */
|
383 | function freeResult($result) |
383 | function freeResult($result) |
384 | {
|
384 | {
|
385 | return is_resource($result) ? mssql_free_result($result) : false; |
385 | return is_resource($result) ? mssql_free_result($result) : false; |
386 | }
|
386 | }
|
387 | 387 | ||
388 | // }}}
|
388 | // }}}
|
389 | // {{{ numCols()
|
389 | // {{{ numCols()
|
390 | 390 | ||
391 | /**
|
391 | /**
|
392 | * Gets the number of columns in a result set
|
392 | * Gets the number of columns in a result set
|
393 | *
|
393 | *
|
394 | * This method is not meant to be called directly. Use
|
394 | * This method is not meant to be called directly. Use
|
395 | * DB_result::numCols() instead. It can't be declared "protected"
|
395 | * DB_result::numCols() instead. It can't be declared "protected"
|
396 | * because DB_result is a separate object.
|
396 | * because DB_result is a separate object.
|
397 | *
|
397 | *
|
398 | * @param resource $result PHP's query result resource
|
398 | * @param resource $result PHP's query result resource
|
399 | *
|
399 | *
|
400 | * @return int the number of columns. A DB_Error object on failure.
|
400 | * @return int the number of columns. A DB_Error object on failure.
|
401 | *
|
401 | *
|
402 | * @see DB_result::numCols()
|
402 | * @see DB_result::numCols()
|
403 | */
|
403 | */
|
404 | function numCols($result) |
404 | function numCols($result) |
405 | {
|
405 | {
|
406 | $cols = @mssql_num_fields($result); |
406 | $cols = @mssql_num_fields($result); |
407 | if (!$cols) { |
407 | if (!$cols) { |
408 | return $this->mssqlRaiseError(); |
408 | return $this->mssqlRaiseError(); |
409 | }
|
409 | }
|
410 | return $cols; |
410 | return $cols; |
411 | }
|
411 | }
|
412 | 412 | ||
413 | // }}}
|
413 | // }}}
|
414 | // {{{ numRows()
|
414 | // {{{ numRows()
|
415 | 415 | ||
416 | /**
|
416 | /**
|
417 | * Gets the number of rows in a result set
|
417 | * Gets the number of rows in a result set
|
418 | *
|
418 | *
|
419 | * This method is not meant to be called directly. Use
|
419 | * This method is not meant to be called directly. Use
|
420 | * DB_result::numRows() instead. It can't be declared "protected"
|
420 | * DB_result::numRows() instead. It can't be declared "protected"
|
421 | * because DB_result is a separate object.
|
421 | * because DB_result is a separate object.
|
422 | *
|
422 | *
|
423 | * @param resource $result PHP's query result resource
|
423 | * @param resource $result PHP's query result resource
|
424 | *
|
424 | *
|
425 | * @return int the number of rows. A DB_Error object on failure.
|
425 | * @return int the number of rows. A DB_Error object on failure.
|
426 | *
|
426 | *
|
427 | * @see DB_result::numRows()
|
427 | * @see DB_result::numRows()
|
428 | */
|
428 | */
|
429 | function numRows($result) |
429 | function numRows($result) |
430 | {
|
430 | {
|
431 | $rows = @mssql_num_rows($result); |
431 | $rows = @mssql_num_rows($result); |
432 | if ($rows === false) { |
432 | if ($rows === false) { |
433 | return $this->mssqlRaiseError(); |
433 | return $this->mssqlRaiseError(); |
434 | }
|
434 | }
|
435 | return $rows; |
435 | return $rows; |
436 | }
|
436 | }
|
437 | 437 | ||
438 | // }}}
|
438 | // }}}
|
439 | // {{{ autoCommit()
|
439 | // {{{ autoCommit()
|
440 | 440 | ||
441 | /**
|
441 | /**
|
442 | * Enables or disables automatic commits
|
442 | * Enables or disables automatic commits
|
443 | *
|
443 | *
|
444 | * @param bool $onoff true turns it on, false turns it off
|
444 | * @param bool $onoff true turns it on, false turns it off
|
445 | *
|
445 | *
|
446 | * @return int DB_OK on success. A DB_Error object if the driver
|
446 | * @return int DB_OK on success. A DB_Error object if the driver
|
447 | * doesn't support auto-committing transactions.
|
447 | * doesn't support auto-committing transactions.
|
448 | */
|
448 | */
|
449 | function autoCommit($onoff = false) |
449 | function autoCommit($onoff = false) |
450 | {
|
450 | {
|
451 | // XXX if $this->transaction_opcount > 0, we should probably
|
451 | // XXX if $this->transaction_opcount > 0, we should probably
|
452 | // issue a warning here.
|
452 | // issue a warning here.
|
453 | $this->autocommit = $onoff ? true : false; |
453 | $this->autocommit = $onoff ? true : false; |
454 | return DB_OK; |
454 | return DB_OK; |
455 | }
|
455 | }
|
456 | 456 | ||
457 | // }}}
|
457 | // }}}
|
458 | // {{{ commit()
|
458 | // {{{ commit()
|
459 | 459 | ||
460 | /**
|
460 | /**
|
461 | * Commits the current transaction
|
461 | * Commits the current transaction
|
462 | *
|
462 | *
|
463 | * @return int DB_OK on success. A DB_Error object on failure.
|
463 | * @return int DB_OK on success. A DB_Error object on failure.
|
464 | */
|
464 | */
|
465 | function commit() |
465 | function commit() |
466 | {
|
466 | {
|
467 | if ($this->transaction_opcount > 0) { |
467 | if ($this->transaction_opcount > 0) { |
468 | if (!@mssql_select_db($this->_db, $this->connection)) { |
468 | if (!@mssql_select_db($this->_db, $this->connection)) { |
469 | return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
469 | return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
470 | }
|
470 | }
|
471 | $result = @mssql_query('COMMIT TRAN', $this->connection); |
471 | $result = @mssql_query('COMMIT TRAN', $this->connection); |
472 | $this->transaction_opcount = 0; |
472 | $this->transaction_opcount = 0; |
473 | if (!$result) { |
473 | if (!$result) { |
474 | return $this->mssqlRaiseError(); |
474 | return $this->mssqlRaiseError(); |
475 | }
|
475 | }
|
476 | }
|
476 | }
|
477 | return DB_OK; |
477 | return DB_OK; |
478 | }
|
478 | }
|
479 | 479 | ||
480 | // }}}
|
480 | // }}}
|
481 | // {{{ rollback()
|
481 | // {{{ rollback()
|
482 | 482 | ||
483 | /**
|
483 | /**
|
484 | * Reverts the current transaction
|
484 | * Reverts the current transaction
|
485 | *
|
485 | *
|
486 | * @return int DB_OK on success. A DB_Error object on failure.
|
486 | * @return int DB_OK on success. A DB_Error object on failure.
|
487 | */
|
487 | */
|
488 | function rollback() |
488 | function rollback() |
489 | {
|
489 | {
|
490 | if ($this->transaction_opcount > 0) { |
490 | if ($this->transaction_opcount > 0) { |
491 | if (!@mssql_select_db($this->_db, $this->connection)) { |
491 | if (!@mssql_select_db($this->_db, $this->connection)) { |
492 | return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
492 | return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
493 | }
|
493 | }
|
494 | $result = @mssql_query('ROLLBACK TRAN', $this->connection); |
494 | $result = @mssql_query('ROLLBACK TRAN', $this->connection); |
495 | $this->transaction_opcount = 0; |
495 | $this->transaction_opcount = 0; |
496 | if (!$result) { |
496 | if (!$result) { |
497 | return $this->mssqlRaiseError(); |
497 | return $this->mssqlRaiseError(); |
498 | }
|
498 | }
|
499 | }
|
499 | }
|
500 | return DB_OK; |
500 | return DB_OK; |
501 | }
|
501 | }
|
502 | 502 | ||
503 | // }}}
|
503 | // }}}
|
504 | // {{{ affectedRows()
|
504 | // {{{ affectedRows()
|
505 | 505 | ||
506 | /**
|
506 | /**
|
507 | * Determines the number of rows affected by a data maniuplation query
|
507 | * Determines the number of rows affected by a data maniuplation query
|
508 | *
|
508 | *
|
509 | * 0 is returned for queries that don't manipulate data.
|
509 | * 0 is returned for queries that don't manipulate data.
|
510 | *
|
510 | *
|
511 | * @return int the number of rows. A DB_Error object on failure.
|
511 | * @return int the number of rows. A DB_Error object on failure.
|
512 | */
|
512 | */
|
513 | function affectedRows() |
513 | function affectedRows() |
514 | {
|
514 | {
|
515 | if ($this->_last_query_manip) { |
515 | if ($this->_last_query_manip) { |
516 | $res = @mssql_query('select @@rowcount', $this->connection); |
516 | $res = @mssql_query('select @@rowcount', $this->connection); |
517 | if (!$res) { |
517 | if (!$res) { |
518 | return $this->mssqlRaiseError(); |
518 | return $this->mssqlRaiseError(); |
519 | }
|
519 | }
|
520 | $ar = @mssql_fetch_row($res); |
520 | $ar = @mssql_fetch_row($res); |
521 | if (!$ar) { |
521 | if (!$ar) { |
522 | $result = 0; |
522 | $result = 0; |
523 | } else { |
523 | } else { |
524 | @mssql_free_result($res); |
524 | @mssql_free_result($res); |
525 | $result = $ar[0]; |
525 | $result = $ar[0]; |
526 | }
|
526 | }
|
527 | } else { |
527 | } else { |
528 | $result = 0; |
528 | $result = 0; |
529 | }
|
529 | }
|
530 | return $result; |
530 | return $result; |
531 | }
|
531 | }
|
532 | 532 | ||
533 | // }}}
|
533 | // }}}
|
534 | // {{{ nextId()
|
534 | // {{{ nextId()
|
535 | 535 | ||
536 | /**
|
536 | /**
|
537 | * Returns the next free id in a sequence
|
537 | * Returns the next free id in a sequence
|
538 | *
|
538 | *
|
539 | * @param string $seq_name name of the sequence
|
539 | * @param string $seq_name name of the sequence
|
540 | * @param boolean $ondemand when true, the seqence is automatically
|
540 | * @param boolean $ondemand when true, the seqence is automatically
|
541 | * created if it does not exist
|
541 | * created if it does not exist
|
542 | *
|
542 | *
|
543 | * @return int the next id number in the sequence.
|
543 | * @return int the next id number in the sequence.
|
544 | * A DB_Error object on failure.
|
544 | * A DB_Error object on failure.
|
545 | *
|
545 | *
|
546 | * @see DB_common::nextID(), DB_common::getSequenceName(),
|
546 | * @see DB_common::nextID(), DB_common::getSequenceName(),
|
547 | * DB_mssql::createSequence(), DB_mssql::dropSequence()
|
547 | * DB_mssql::createSequence(), DB_mssql::dropSequence()
|
548 | */
|
548 | */
|
549 | function nextId($seq_name, $ondemand = true) |
549 | function nextId($seq_name, $ondemand = true) |
550 | {
|
550 | {
|
551 | $seqname = $this->getSequenceName($seq_name); |
551 | $seqname = $this->getSequenceName($seq_name); |
552 | if (!@mssql_select_db($this->_db, $this->connection)) { |
552 | if (!@mssql_select_db($this->_db, $this->connection)) { |
553 | return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
553 | return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
554 | }
|
554 | }
|
555 | $repeat = 0; |
555 | $repeat = 0; |
556 | do { |
556 | do { |
557 | $this->pushErrorHandling(PEAR_ERROR_RETURN); |
557 | $this->pushErrorHandling(PEAR_ERROR_RETURN); |
558 | $result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)"); |
558 | $result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)"); |
559 | $this->popErrorHandling(); |
559 | $this->popErrorHandling(); |
560 | if ($ondemand && DB::isError($result) && |
560 | if ($ondemand && DB::isError($result) && |
561 | ($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE)) |
561 | ($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE)) |
562 | {
|
562 | {
|
563 | $repeat = 1; |
563 | $repeat = 1; |
564 | $result = $this->createSequence($seq_name); |
564 | $result = $this->createSequence($seq_name); |
565 | if (DB::isError($result)) { |
565 | if (DB::isError($result)) { |
566 | return $this->raiseError($result); |
566 | return $this->raiseError($result); |
567 | }
|
567 | }
|
568 | } elseif (!DB::isError($result)) { |
568 | } elseif (!DB::isError($result)) { |
569 | $result = $this->query("SELECT IDENT_CURRENT('$seqname')"); |
569 | $result = $this->query("SELECT IDENT_CURRENT('$seqname')"); |
570 | if (DB::isError($result)) { |
570 | if (DB::isError($result)) { |
571 | /* Fallback code for MS SQL Server 7.0, which doesn't have
|
571 | /* Fallback code for MS SQL Server 7.0, which doesn't have
|
572 | * IDENT_CURRENT. This is *not* safe for concurrent
|
572 | * IDENT_CURRENT. This is *not* safe for concurrent
|
573 | * requests, and really, if you're using it, you're in a
|
573 | * requests, and really, if you're using it, you're in a
|
574 | * world of hurt. Nevertheless, it's here to ensure BC. See
|
574 | * world of hurt. Nevertheless, it's here to ensure BC. See
|
575 | * bug #181 for the gory details.*/
|
575 | * bug #181 for the gory details.*/
|
576 | $result = $this->query("SELECT @@IDENTITY FROM $seqname"); |
576 | $result = $this->query("SELECT @@IDENTITY FROM $seqname"); |
577 | }
|
577 | }
|
578 | $repeat = 0; |
578 | $repeat = 0; |
579 | } else { |
579 | } else { |
580 | $repeat = false; |
580 | $repeat = false; |
581 | }
|
581 | }
|
582 | } while ($repeat); |
582 | } while ($repeat); |
583 | if (DB::isError($result)) { |
583 | if (DB::isError($result)) { |
584 | return $this->raiseError($result); |
584 | return $this->raiseError($result); |
585 | }
|
585 | }
|
586 | $result = $result->fetchRow(DB_FETCHMODE_ORDERED); |
586 | $result = $result->fetchRow(DB_FETCHMODE_ORDERED); |
587 | return $result[0]; |
587 | return $result[0]; |
588 | }
|
588 | }
|
589 | 589 | ||
590 | /**
|
590 | /**
|
591 | * Creates a new sequence
|
591 | * Creates a new sequence
|
592 | *
|
592 | *
|
593 | * @param string $seq_name name of the new sequence
|
593 | * @param string $seq_name name of the new sequence
|
594 | *
|
594 | *
|
595 | * @return int DB_OK on success. A DB_Error object on failure.
|
595 | * @return int DB_OK on success. A DB_Error object on failure.
|
596 | *
|
596 | *
|
597 | * @see DB_common::createSequence(), DB_common::getSequenceName(),
|
597 | * @see DB_common::createSequence(), DB_common::getSequenceName(),
|
598 | * DB_mssql::nextID(), DB_mssql::dropSequence()
|
598 | * DB_mssql::nextID(), DB_mssql::dropSequence()
|
599 | */
|
599 | */
|
600 | function createSequence($seq_name) |
600 | function createSequence($seq_name) |
601 | {
|
601 | {
|
602 | return $this->query('CREATE TABLE ' |
602 | return $this->query('CREATE TABLE ' |
603 | . $this->getSequenceName($seq_name) |
603 | . $this->getSequenceName($seq_name) |
604 | . ' ([id] [int] IDENTITY (1, 1) NOT NULL,' |
604 | . ' ([id] [int] IDENTITY (1, 1) NOT NULL,' |
605 | . ' [vapor] [int] NULL)'); |
605 | . ' [vapor] [int] NULL)'); |
606 | }
|
606 | }
|
607 | 607 | ||
608 | // }}}
|
608 | // }}}
|
609 | // {{{ dropSequence()
|
609 | // {{{ dropSequence()
|
610 | 610 | ||
611 | /**
|
611 | /**
|
612 | * Deletes a sequence
|
612 | * Deletes a sequence
|
613 | *
|
613 | *
|
614 | * @param string $seq_name name of the sequence to be deleted
|
614 | * @param string $seq_name name of the sequence to be deleted
|
615 | *
|
615 | *
|
616 | * @return int DB_OK on success. A DB_Error object on failure.
|
616 | * @return int DB_OK on success. A DB_Error object on failure.
|
617 | *
|
617 | *
|
618 | * @see DB_common::dropSequence(), DB_common::getSequenceName(),
|
618 | * @see DB_common::dropSequence(), DB_common::getSequenceName(),
|
619 | * DB_mssql::nextID(), DB_mssql::createSequence()
|
619 | * DB_mssql::nextID(), DB_mssql::createSequence()
|
620 | */
|
620 | */
|
621 | function dropSequence($seq_name) |
621 | function dropSequence($seq_name) |
622 | {
|
622 | {
|
623 | return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); |
623 | return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); |
624 | }
|
624 | }
|
625 | 625 | ||
626 | // }}}
|
626 | // }}}
|
627 | // {{{ quoteIdentifier()
|
627 | // {{{ quoteIdentifier()
|
628 | 628 | ||
629 | /**
|
629 | /**
|
630 | * Quotes a string so it can be safely used as a table or column name
|
630 | * Quotes a string so it can be safely used as a table or column name
|
631 | *
|
631 | *
|
632 | * @param string $str identifier name to be quoted
|
632 | * @param string $str identifier name to be quoted
|
633 | *
|
633 | *
|
634 | * @return string quoted identifier string
|
634 | * @return string quoted identifier string
|
635 | *
|
635 | *
|
636 | * @see DB_common::quoteIdentifier()
|
636 | * @see DB_common::quoteIdentifier()
|
637 | * @since Method available since Release 1.6.0
|
637 | * @since Method available since Release 1.6.0
|
638 | */
|
638 | */
|
639 | function quoteIdentifier($str) |
639 | function quoteIdentifier($str) |
640 | {
|
640 | {
|
641 | return '[' . str_replace(']', ']]', $str) . ']'; |
641 | return '[' . str_replace(']', ']]', $str) . ']'; |
642 | }
|
642 | }
|
643 | 643 | ||
644 | // }}}
|
644 | // }}}
|
645 | // {{{ mssqlRaiseError()
|
645 | // {{{ mssqlRaiseError()
|
646 | 646 | ||
647 | /**
|
647 | /**
|
648 | * Produces a DB_Error object regarding the current problem
|
648 | * Produces a DB_Error object regarding the current problem
|
649 | *
|
649 | *
|
650 | * @param int $errno if the error is being manually raised pass a
|
650 | * @param int $errno if the error is being manually raised pass a
|
651 | * DB_ERROR* constant here. If this isn't passed
|
651 | * DB_ERROR* constant here. If this isn't passed
|
652 | * the error information gathered from the DBMS.
|
652 | * the error information gathered from the DBMS.
|
653 | *
|
653 | *
|
654 | * @return object the DB_Error object
|
654 | * @return object the DB_Error object
|
655 | *
|
655 | *
|
656 | * @see DB_common::raiseError(),
|
656 | * @see DB_common::raiseError(),
|
657 | * DB_mssql::errorNative(), DB_mssql::errorCode()
|
657 | * DB_mssql::errorNative(), DB_mssql::errorCode()
|
658 | */
|
658 | */
|
659 | function mssqlRaiseError($code = null) |
659 | function mssqlRaiseError($code = null) |
660 | {
|
660 | {
|
661 | $message = @mssql_get_last_message(); |
661 | $message = @mssql_get_last_message(); |
662 | if (!$code) { |
662 | if (!$code) { |
663 | $code = $this->errorNative(); |
663 | $code = $this->errorNative(); |
664 | }
|
664 | }
|
665 | return $this->raiseError($this->errorCode($code, $message), |
665 | return $this->raiseError($this->errorCode($code, $message), |
666 | null, null, null, "$code - $message"); |
666 | null, null, null, "$code - $message"); |
667 | }
|
667 | }
|
668 | 668 | ||
669 | // }}}
|
669 | // }}}
|
670 | // {{{ errorNative()
|
670 | // {{{ errorNative()
|
671 | 671 | ||
672 | /**
|
672 | /**
|
673 | * Gets the DBMS' native error code produced by the last query
|
673 | * Gets the DBMS' native error code produced by the last query
|
674 | *
|
674 | *
|
675 | * @return int the DBMS' error code
|
675 | * @return int the DBMS' error code
|
676 | */
|
676 | */
|
677 | function errorNative() |
677 | function errorNative() |
678 | {
|
678 | {
|
679 | $res = @mssql_query('select @@ERROR as ErrorCode', $this->connection); |
679 | $res = @mssql_query('select @@ERROR as ErrorCode', $this->connection); |
680 | if (!$res) { |
680 | if (!$res) { |
681 | return DB_ERROR; |
681 | return DB_ERROR; |
682 | }
|
682 | }
|
683 | $row = @mssql_fetch_row($res); |
683 | $row = @mssql_fetch_row($res); |
684 | return $row[0]; |
684 | return $row[0]; |
685 | }
|
685 | }
|
686 | 686 | ||
687 | // }}}
|
687 | // }}}
|
688 | // {{{ errorCode()
|
688 | // {{{ errorCode()
|
689 | 689 | ||
690 | /**
|
690 | /**
|
691 | * Determines PEAR::DB error code from mssql's native codes.
|
691 | * Determines PEAR::DB error code from mssql's native codes.
|
692 | *
|
692 | *
|
693 | * If <var>$nativecode</var> isn't known yet, it will be looked up.
|
693 | * If <var>$nativecode</var> isn't known yet, it will be looked up.
|
694 | *
|
694 | *
|
695 | * @param mixed $nativecode mssql error code, if known
|
695 | * @param mixed $nativecode mssql error code, if known
|
696 | * @return integer an error number from a DB error constant
|
696 | * @return integer an error number from a DB error constant
|
697 | * @see errorNative()
|
697 | * @see errorNative()
|
698 | */
|
698 | */
|
699 | function errorCode($nativecode = null, $msg = '') |
699 | function errorCode($nativecode = null, $msg = '') |
700 | {
|
700 | {
|
701 | if (!$nativecode) { |
701 | if (!$nativecode) { |
702 | $nativecode = $this->errorNative(); |
702 | $nativecode = $this->errorNative(); |
703 | }
|
703 | }
|
704 | if (isset($this->errorcode_map[$nativecode])) { |
704 | if (isset($this->errorcode_map[$nativecode])) { |
705 | if ($nativecode == 3701 |
705 | if ($nativecode == 3701 |
706 | && preg_match('/Cannot drop the index/i', $msg)) |
706 | && preg_match('/Cannot drop the index/i', $msg)) |
707 | {
|
707 | {
|
708 | return DB_ERROR_NOT_FOUND; |
708 | return DB_ERROR_NOT_FOUND; |
709 | }
|
709 | }
|
710 | return $this->errorcode_map[$nativecode]; |
710 | return $this->errorcode_map[$nativecode]; |
711 | } else { |
711 | } else { |
712 | return DB_ERROR; |
712 | return DB_ERROR; |
713 | }
|
713 | }
|
714 | }
|
714 | }
|
715 | 715 | ||
716 | // }}}
|
716 | // }}}
|
717 | // {{{ tableInfo()
|
717 | // {{{ tableInfo()
|
718 | 718 | ||
719 | /**
|
719 | /**
|
720 | * Returns information about a table or a result set
|
720 | * Returns information about a table or a result set
|
721 | *
|
721 | *
|
722 | * NOTE: only supports 'table' and 'flags' if <var>$result</var>
|
722 | * NOTE: only supports 'table' and 'flags' if <var>$result</var>
|
723 | * is a table name.
|
723 | * is a table name.
|
724 | *
|
724 | *
|
725 | * @param object|string $result DB_result object from a query or a
|
725 | * @param object|string $result DB_result object from a query or a
|
726 | * string containing the name of a table.
|
726 | * string containing the name of a table.
|
727 | * While this also accepts a query result
|
727 | * While this also accepts a query result
|
728 | * resource identifier, this behavior is
|
728 | * resource identifier, this behavior is
|
729 | * deprecated.
|
729 | * deprecated.
|
730 | * @param int $mode a valid tableInfo mode
|
730 | * @param int $mode a valid tableInfo mode
|
731 | *
|
731 | *
|
732 | * @return array an associative array with the information requested.
|
732 | * @return array an associative array with the information requested.
|
733 | * A DB_Error object on failure.
|
733 | * A DB_Error object on failure.
|
734 | *
|
734 | *
|
735 | * @see DB_common::tableInfo()
|
735 | * @see DB_common::tableInfo()
|
736 | */
|
736 | */
|
737 | function tableInfo($result, $mode = null) |
737 | function tableInfo($result, $mode = null) |
738 | {
|
738 | {
|
739 | if (is_string($result)) { |
739 | if (is_string($result)) { |
740 | /*
|
740 | /*
|
741 | * Probably received a table name.
|
741 | * Probably received a table name.
|
742 | * Create a result resource identifier.
|
742 | * Create a result resource identifier.
|
743 | */
|
743 | */
|
744 | if (!@mssql_select_db($this->_db, $this->connection)) { |
744 | if (!@mssql_select_db($this->_db, $this->connection)) { |
745 | return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
745 | return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
746 | }
|
746 | }
|
747 | $id = @mssql_query("SELECT * FROM $result WHERE 1=0", |
747 | $id = @mssql_query("SELECT * FROM $result WHERE 1=0", |
748 | $this->connection); |
748 | $this->connection); |
749 | $got_string = true; |
749 | $got_string = true; |
750 | } elseif (isset($result->result)) { |
750 | } elseif (isset($result->result)) { |
751 | /*
|
751 | /*
|
752 | * Probably received a result object.
|
752 | * Probably received a result object.
|
753 | * Extract the result resource identifier.
|
753 | * Extract the result resource identifier.
|
754 | */
|
754 | */
|
755 | $id = $result->result; |
755 | $id = $result->result; |
756 | $got_string = false; |
756 | $got_string = false; |
757 | } else { |
757 | } else { |
758 | /*
|
758 | /*
|
759 | * Probably received a result resource identifier.
|
759 | * Probably received a result resource identifier.
|
760 | * Copy it.
|
760 | * Copy it.
|
761 | * Deprecated. Here for compatibility only.
|
761 | * Deprecated. Here for compatibility only.
|
762 | */
|
762 | */
|
763 | $id = $result; |
763 | $id = $result; |
764 | $got_string = false; |
764 | $got_string = false; |
765 | }
|
765 | }
|
766 | 766 | ||
767 | if (!is_resource($id)) { |
767 | if (!is_resource($id)) { |
768 | return $this->mssqlRaiseError(DB_ERROR_NEED_MORE_DATA); |
768 | return $this->mssqlRaiseError(DB_ERROR_NEED_MORE_DATA); |
769 | }
|
769 | }
|
770 | 770 | ||
771 | if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
771 | if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
772 | $case_func = 'strtolower'; |
772 | $case_func = 'strtolower'; |
773 | } else { |
773 | } else { |
774 | $case_func = 'strval'; |
774 | $case_func = 'strval'; |
775 | }
|
775 | }
|
776 | 776 | ||
777 | $count = @mssql_num_fields($id); |
777 | $count = @mssql_num_fields($id); |
778 | $res = array(); |
778 | $res = array(); |
779 | 779 | ||
780 | if ($mode) { |
780 | if ($mode) { |
781 | $res['num_fields'] = $count; |
781 | $res['num_fields'] = $count; |
782 | }
|
782 | }
|
783 | 783 | ||
784 | for ($i = 0; $i < $count; $i++) { |
784 | for ($i = 0; $i < $count; $i++) { |
785 | if ($got_string) { |
785 | if ($got_string) { |
786 | $flags = $this->_mssql_field_flags($result, |
786 | $flags = $this->_mssql_field_flags($result, |
787 | @mssql_field_name($id, $i)); |
787 | @mssql_field_name($id, $i)); |
788 | if (DB::isError($flags)) { |
788 | if (DB::isError($flags)) { |
789 | return $flags; |
789 | return $flags; |
790 | }
|
790 | }
|
791 | } else { |
791 | } else { |
792 | $flags = ''; |
792 | $flags = ''; |
793 | }
|
793 | }
|
794 | 794 | ||
795 | $res[$i] = array( |
795 | $res[$i] = array( |
796 | 'table' => $got_string ? $case_func($result) : '', |
796 | 'table' => $got_string ? $case_func($result) : '', |
797 | 'name' => $case_func(@mssql_field_name($id, $i)), |
797 | 'name' => $case_func(@mssql_field_name($id, $i)), |
798 | 'type' => @mssql_field_type($id, $i), |
798 | 'type' => @mssql_field_type($id, $i), |
799 | 'len' => @mssql_field_length($id, $i), |
799 | 'len' => @mssql_field_length($id, $i), |
800 | 'flags' => $flags, |
800 | 'flags' => $flags, |
801 | ); |
801 | ); |
802 | if ($mode & DB_TABLEINFO_ORDER) { |
802 | if ($mode & DB_TABLEINFO_ORDER) { |
803 | $res['order'][$res[$i]['name']] = $i; |
803 | $res['order'][$res[$i]['name']] = $i; |
804 | }
|
804 | }
|
805 | if ($mode & DB_TABLEINFO_ORDERTABLE) { |
805 | if ($mode & DB_TABLEINFO_ORDERTABLE) { |
806 | $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
806 | $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
807 | }
|
807 | }
|
808 | }
|
808 | }
|
809 | 809 | ||
810 | // free the result only if we were called on a table
|
810 | // free the result only if we were called on a table
|
811 | if ($got_string) { |
811 | if ($got_string) { |
812 | @mssql_free_result($id); |
812 | @mssql_free_result($id); |
813 | }
|
813 | }
|
814 | return $res; |
814 | return $res; |
815 | }
|
815 | }
|
816 | 816 | ||
817 | // }}}
|
817 | // }}}
|
818 | // {{{ _mssql_field_flags()
|
818 | // {{{ _mssql_field_flags()
|
819 | 819 | ||
820 | /**
|
820 | /**
|
821 | * Get a column's flags
|
821 | * Get a column's flags
|
822 | *
|
822 | *
|
823 | * Supports "not_null", "primary_key",
|
823 | * Supports "not_null", "primary_key",
|
824 | * "auto_increment" (mssql identity), "timestamp" (mssql timestamp),
|
824 | * "auto_increment" (mssql identity), "timestamp" (mssql timestamp),
|
825 | * "unique_key" (mssql unique index, unique check or primary_key) and
|
825 | * "unique_key" (mssql unique index, unique check or primary_key) and
|
826 | * "multiple_key" (multikey index)
|
826 | * "multiple_key" (multikey index)
|
827 | *
|
827 | *
|
828 | * mssql timestamp is NOT similar to the mysql timestamp so this is maybe
|
828 | * mssql timestamp is NOT similar to the mysql timestamp so this is maybe
|
829 | * not useful at all - is the behaviour of mysql_field_flags that primary
|
829 | * not useful at all - is the behaviour of mysql_field_flags that primary
|
830 | * keys are alway unique? is the interpretation of multiple_key correct?
|
830 | * keys are alway unique? is the interpretation of multiple_key correct?
|
831 | *
|
831 | *
|
832 | * @param string $table the table name
|
832 | * @param string $table the table name
|
833 | * @param string $column the field name
|
833 | * @param string $column the field name
|
834 | *
|
834 | *
|
835 | * @return string the flags
|
835 | * @return string the flags
|
836 | *
|
836 | *
|
837 | * @access private
|
837 | * @access private
|
838 | * @author Joern Barthel <j_barthel@web.de>
|
838 | * @author Joern Barthel <j_barthel@web.de>
|
839 | */
|
839 | */
|
840 | function _mssql_field_flags($table, $column) |
840 | function _mssql_field_flags($table, $column) |
841 | {
|
841 | {
|
842 | static $tableName = null; |
842 | static $tableName = null; |
843 | static $flags = array(); |
843 | static $flags = array(); |
844 | 844 | ||
845 | if ($table != $tableName) { |
845 | if ($table != $tableName) { |
846 | 846 | ||
847 | $flags = array(); |
847 | $flags = array(); |
848 | $tableName = $table; |
848 | $tableName = $table; |
849 | 849 | ||
850 | // get unique and primary keys
|
850 | // get unique and primary keys
|
851 | $res = $this->getAll("EXEC SP_HELPINDEX $table", DB_FETCHMODE_ASSOC); |
851 | $res = $this->getAll("EXEC SP_HELPINDEX $table", DB_FETCHMODE_ASSOC); |
852 | if (DB::isError($res)) { |
852 | if (DB::isError($res)) { |
853 | return $res; |
853 | return $res; |
854 | }
|
854 | }
|
855 | 855 | ||
856 | foreach ($res as $val) { |
856 | foreach ($res as $val) { |
857 | $keys = explode(', ', $val['index_keys']); |
857 | $keys = explode(', ', $val['index_keys']); |
858 | 858 | ||
859 | if (sizeof($keys) > 1) { |
859 | if (sizeof($keys) > 1) { |
860 | foreach ($keys as $key) { |
860 | foreach ($keys as $key) { |
861 | $this->_add_flag($flags[$key], 'multiple_key'); |
861 | $this->_add_flag($flags[$key], 'multiple_key'); |
862 | }
|
862 | }
|
863 | }
|
863 | }
|
864 | 864 | ||
865 | if (strpos($val['index_description'], 'primary key')) { |
865 | if (strpos($val['index_description'], 'primary key')) { |
866 | foreach ($keys as $key) { |
866 | foreach ($keys as $key) { |
867 | $this->_add_flag($flags[$key], 'primary_key'); |
867 | $this->_add_flag($flags[$key], 'primary_key'); |
868 | }
|
868 | }
|
869 | } elseif (strpos($val['index_description'], 'unique')) { |
869 | } elseif (strpos($val['index_description'], 'unique')) { |
870 | foreach ($keys as $key) { |
870 | foreach ($keys as $key) { |
871 | $this->_add_flag($flags[$key], 'unique_key'); |
871 | $this->_add_flag($flags[$key], 'unique_key'); |
872 | }
|
872 | }
|
873 | }
|
873 | }
|
874 | }
|
874 | }
|
875 | 875 | ||
876 | // get auto_increment, not_null and timestamp
|
876 | // get auto_increment, not_null and timestamp
|
877 | $res = $this->getAll("EXEC SP_COLUMNS $table", DB_FETCHMODE_ASSOC); |
877 | $res = $this->getAll("EXEC SP_COLUMNS $table", DB_FETCHMODE_ASSOC); |
878 | if (DB::isError($res)) { |
878 | if (DB::isError($res)) { |
879 | return $res; |
879 | return $res; |
880 | }
|
880 | }
|
881 | 881 | ||
882 | foreach ($res as $val) { |
882 | foreach ($res as $val) { |
883 | $val = array_change_key_case($val, CASE_LOWER); |
883 | $val = array_change_key_case($val, CASE_LOWER); |
884 | if ($val['nullable'] == '0') { |
884 | if ($val['nullable'] == '0') { |
885 | $this->_add_flag($flags[$val['column_name']], 'not_null'); |
885 | $this->_add_flag($flags[$val['column_name']], 'not_null'); |
886 | }
|
886 | }
|
887 | if (strpos($val['type_name'], 'identity')) { |
887 | if (strpos($val['type_name'], 'identity')) { |
888 | $this->_add_flag($flags[$val['column_name']], 'auto_increment'); |
888 | $this->_add_flag($flags[$val['column_name']], 'auto_increment'); |
889 | }
|
889 | }
|
890 | if (strpos($val['type_name'], 'timestamp')) { |
890 | if (strpos($val['type_name'], 'timestamp')) { |
891 | $this->_add_flag($flags[$val['column_name']], 'timestamp'); |
891 | $this->_add_flag($flags[$val['column_name']], 'timestamp'); |
892 | }
|
892 | }
|
893 | }
|
893 | }
|
894 | }
|
894 | }
|
895 | 895 | ||
896 | if (array_key_exists($column, $flags)) { |
896 | if (array_key_exists($column, $flags)) { |
897 | return(implode(' ', $flags[$column])); |
897 | return(implode(' ', $flags[$column])); |
898 | }
|
898 | }
|
899 | return ''; |
899 | return ''; |
900 | }
|
900 | }
|
901 | 901 | ||
902 | // }}}
|
902 | // }}}
|
903 | // {{{ _add_flag()
|
903 | // {{{ _add_flag()
|
904 | 904 | ||
905 | /**
|
905 | /**
|
906 | * Adds a string to the flags array if the flag is not yet in there
|
906 | * Adds a string to the flags array if the flag is not yet in there
|
907 | * - if there is no flag present the array is created
|
907 | * - if there is no flag present the array is created
|
908 | *
|
908 | *
|
909 | * @param array &$array the reference to the flag-array
|
909 | * @param array &$array the reference to the flag-array
|
910 | * @param string $value the flag value
|
910 | * @param string $value the flag value
|
911 | *
|
911 | *
|
912 | * @return void
|
912 | * @return void
|
913 | *
|
913 | *
|
914 | * @access private
|
914 | * @access private
|
915 | * @author Joern Barthel <j_barthel@web.de>
|
915 | * @author Joern Barthel <j_barthel@web.de>
|
916 | */
|
916 | */
|
917 | function _add_flag(&$array, $value) |
917 | function _add_flag(&$array, $value) |
918 | {
|
918 | {
|
919 | if (!is_array($array)) { |
919 | if (!is_array($array)) { |
920 | $array = array($value); |
920 | $array = array($value); |
921 | } elseif (!in_array($value, $array)) { |
921 | } elseif (!in_array($value, $array)) { |
922 | array_push($array, $value); |
922 | array_push($array, $value); |
923 | }
|
923 | }
|
924 | }
|
924 | }
|
925 | 925 | ||
926 | // }}}
|
926 | // }}}
|
927 | // {{{ getSpecialQuery()
|
927 | // {{{ getSpecialQuery()
|
928 | 928 | ||
929 | /**
|
929 | /**
|
930 | * Obtains the query string needed for listing a given type of objects
|
930 | * Obtains the query string needed for listing a given type of objects
|
931 | *
|
931 | *
|
932 | * @param string $type the kind of objects you want to retrieve
|
932 | * @param string $type the kind of objects you want to retrieve
|
933 | *
|
933 | *
|
934 | * @return string the SQL query string or null if the driver doesn't
|
934 | * @return string the SQL query string or null if the driver doesn't
|
935 | * support the object type requested
|
935 | * support the object type requested
|
936 | *
|
936 | *
|
937 | * @access protected
|
937 | * @access protected
|
938 | * @see DB_common::getListOf()
|
938 | * @see DB_common::getListOf()
|
939 | */
|
939 | */
|
940 | function getSpecialQuery($type) |
940 | function getSpecialQuery($type) |
941 | {
|
941 | {
|
942 | switch ($type) { |
942 | switch ($type) { |
943 | case 'tables': |
943 | case 'tables': |
944 | return "SELECT name FROM sysobjects WHERE type = 'U'" |
944 | return "SELECT name FROM sysobjects WHERE type = 'U'" |
945 | . ' ORDER BY name'; |
945 | . ' ORDER BY name'; |
946 | case 'views': |
946 | case 'views': |
947 | return "SELECT name FROM sysobjects WHERE type = 'V'"; |
947 | return "SELECT name FROM sysobjects WHERE type = 'V'"; |
948 | default: |
948 | default: |
949 | return null; |
949 | return null; |
950 | }
|
950 | }
|
951 | }
|
951 | }
|
952 | 952 | ||
953 | // }}}
|
953 | // }}}
|
954 | }
|
954 | }
|
955 | 955 | ||
956 | /*
|
956 | /*
|
957 | * Local variables:
|
957 | * Local variables:
|
958 | * tab-width: 4
|
958 | * tab-width: 4
|
959 | * c-basic-offset: 4
|
959 | * c-basic-offset: 4
|
960 | * End:
|
960 | * End:
|
961 | */
|
961 | */
|
962 | 962 | ||
963 | ?>
|
963 | ?>
|
964 | 964 |