/[cvs]/nfo/php/libs/net.php.pear/DB/mssql.php
ViewVC logotype

Contents of /nfo/php/libs/net.php.pear/DB/mssql.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Tue Oct 29 19:11:41 2002 UTC (21 years, 8 months ago) by cvsjoko
Branch: MAIN
CVS Tags: HEAD
+ new pear-libraries

1 <?php
2 //
3 // +----------------------------------------------------------------------+
4 // | PHP Version 4 |
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997-2002 The PHP Group |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 2.02 of the PHP license, |
9 // | that is bundled with this package in the file LICENSE, and is |
10 // | available at through the world-wide-web at |
11 // | http://www.php.net/license/2_02.txt. |
12 // | If you did not receive a copy of the PHP license and are unable to |
13 // | obtain it through the world-wide-web, please send a note to |
14 // | license@php.net so we can mail you a copy immediately. |
15 // +----------------------------------------------------------------------+
16 // | Author: Sterling Hughes <sterling@php.net> |
17 // +----------------------------------------------------------------------+
18 //
19 // $Id: mssql.php,v 1.40 2002/02/28 08:27:10 sebastian Exp $
20 //
21 // Database independent query interface definition for PHP's Microsoft SQL Server
22 // extension.
23 //
24
25 require_once 'DB/common.php';
26
27 class DB_mssql extends DB_common
28 {
29 var $connection;
30 var $phptype, $dbsyntax;
31 var $prepare_tokens = array();
32 var $prepare_types = array();
33 var $transaction_opcount = 0;
34 var $autocommit = true;
35
36 function DB_mssql()
37 {
38 $this->DB_common();
39 $this->phptype = 'mssql';
40 $this->dbsyntax = 'mssql';
41 $this->features = array(
42 'prepare' => false,
43 'pconnect' => true,
44 'transactions' => true,
45 'limit' => 'emulate'
46 );
47 // XXX Add here error codes ie: 'S100E' => DB_ERROR_SYNTAX
48 $this->errorcode_map = array(
49
50 );
51 }
52
53 function connect($dsninfo, $persistent = false)
54 {
55 if (!DB::assertExtension('mssql') && !DB::assertExtension('sybase')
56 && !DB::assertExtension('sybase_ct'))
57 {
58 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
59 }
60 $this->dsn = $dsninfo;
61 $user = $dsninfo['username'];
62 $pw = $dsninfo['password'];
63 $dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
64
65 $connect_function = $persistent ? 'mssql_pconnect' : 'mssql_connect';
66
67 if ($dbhost && $user && $pw) {
68 $conn = @$connect_function($dbhost, $user, $pw);
69 } elseif ($dbhost && $user) {
70 $conn = @$connect_function($dbhost, $user);
71 } else {
72 $conn = @$connect_function($dbhost);
73 }
74 if (!$conn) {
75 return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
76 null, mssql_get_last_message());
77 }
78 if ($dsninfo['database']) {
79 if (!@mssql_select_db($dsninfo['database'], $conn)) {
80 return $this->raiseError(DB_ERROR_NODBSELECTED, null, null,
81 null, mssql_get_last_message());
82 }
83 }
84 $this->connection = $conn;
85 return DB_OK;
86 }
87
88 function disconnect()
89 {
90 $ret = @mssql_close($this->connection);
91 $this->connection = null;
92 return $ret;
93 }
94
95 function simpleQuery($query)
96 {
97 $ismanip = DB::isManip($query);
98 $this->last_query = $query;
99 $query = $this->modifyQuery($query);
100 if (!$this->autocommit && $ismanip) {
101 if ($this->transaction_opcount == 0) {
102 $result = @mssql_query('BEGIN TRAN', $this->connection);
103 if (!$result) {
104 return $this->mssqlRaiseError();
105 }
106 }
107 $this->transaction_opcount++;
108 }
109 $result = @mssql_query($query, $this->connection);
110 if (!$result) {
111 return $this->mssqlRaiseError();
112 }
113 // Determine which queries that should return data, and which
114 // should return an error code only.
115 return $ismanip ? DB_OK : $result;
116 }
117
118 // {{{ nextResult()
119
120 /**
121 * Move the internal mssql result pointer to the next available result
122 *
123 * @param a valid fbsql result resource
124 *
125 * @access public
126 *
127 * @return true if a result is available otherwise return false
128 */
129 function nextResult($result)
130 {
131 return mssql_next_result($result);
132 }
133
134 // }}}
135
136 function &fetchRow($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
137 {
138 if ($fetchmode == DB_FETCHMODE_DEFAULT) {
139 $fetchmode = $this->fetchmode;
140 }
141 $res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
142 if ($res !== DB_OK) {
143 return $res;
144 }
145 return $arr;
146 }
147
148 function fetchInto($result, &$ar, $fetchmode, $rownum=null)
149 {
150 if ($rownum !== null) {
151 if (!@mssql_data_seek($result, $rownum)) {
152 return null;
153 }
154 }
155 if ($fetchmode & DB_FETCHMODE_ASSOC) {
156 $ar = @mssql_fetch_array($result);
157 } else {
158 $ar = @mssql_fetch_row($result);
159 }
160 if (!$ar) {
161 /* This throws informative error messages,
162 don't use it for now
163 if ($msg = mssql_get_last_message()) {
164 return $this->raiseError($msg);
165 }
166 */
167 return null;
168 }
169 return DB_OK;
170 }
171
172 function freeResult($result)
173 {
174 if (is_resource($result)) {
175 return @mssql_free_result($result);
176 }
177 if (!isset($this->prepare_tokens[$result])) {
178 return false;
179 }
180 unset($this->prepare_tokens[$result]);
181 unset($this->prepare_types[$result]);
182 return true;
183 }
184
185 function numCols($result)
186 {
187 $cols = @mssql_num_fields($result);
188 if (!$cols) {
189 return $this->mssqlRaiseError();
190 }
191 return $cols;
192 }
193
194 function numRows($result)
195 {
196 $rows = @mssql_num_rows($result);
197 if ($rows === false) {
198 return $this->mssqlRaiseError();
199 }
200 return $rows;
201 }
202
203 /**
204 * Enable/disable automatic commits
205 */
206 function autoCommit($onoff = false)
207 {
208 // XXX if $this->transaction_opcount > 0, we should probably
209 // issue a warning here.
210 $this->autocommit = $onoff ? true : false;
211 return DB_OK;
212 }
213
214 // }}}
215 // {{{ commit()
216
217 /**
218 * Commit the current transaction.
219 */
220 function commit()
221 {
222 if ($this->transaction_opcount > 0) {
223 $result = @mssql_query('COMMIT TRAN', $this->connection);
224 $this->transaction_opcount = 0;
225 if (!$result) {
226 return $this->mssqlRaiseError();
227 }
228 }
229 return DB_OK;
230 }
231
232 // }}}
233 // {{{ rollback()
234
235 /**
236 * Roll back (undo) the current transaction.
237 */
238 function rollback()
239 {
240 if ($this->transaction_opcount > 0) {
241 $result = @mssql_query('ROLLBACK TRAN', $this->connection);
242 $this->transaction_opcount = 0;
243 if (!$result) {
244 return $this->mssqlRaiseError();
245 }
246 }
247 return DB_OK;
248 }
249
250 // }}}
251 // {{{ affectedRows()
252
253 /**
254 * Gets the number of rows affected by the last query.
255 * if the last query was a select, returns 0.
256 *
257 * @return number of rows affected by the last query or DB_ERROR
258 */
259 function affectedRows()
260 {
261 if (DB::isManip($this->last_query)) {
262 $res = @mssql_query('select @@rowcount', $this->connection);
263 if (!$res) {
264 return $this->mssqlRaiseError();
265 }
266 $ar = @mssql_fetch_row($res);
267 if (!$ar) {
268 $result = 0;
269 } else {
270 @mssql_free_result($res);
271 $result = $ar[0];
272 }
273 } else {
274 $result = 0;
275 }
276 return $result;
277 }
278 // {{{ nextId()
279
280 /**
281 * Get the next value in a sequence. We emulate sequences
282 * for MSSQL. Will create the sequence if it does not exist.
283 *
284 * @access public
285 *
286 * @param $seq_name the name of the sequence
287 *
288 * @param $ondemand whether to create the sequence table on demand
289 * (default is true)
290 *
291 * @return a sequence integer, or a DB error
292 */
293 function nextId($seq_name, $ondemand = true)
294 {
295 $seqname = $this->getSequenceName($seq_name);
296 $repeat = 0;
297 do {
298 $this->pushErrorHandling(PEAR_ERROR_RETURN);
299 $result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)");
300 $this->popErrorHandling();
301 if ($ondemand && DB::isError($result) &&
302 ($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE))
303 {
304 $repeat = 1;
305 $result = $this->createSequence($seq_name);
306 if (DB::isError($result)) {
307 return $result;
308 }
309 } else {
310 $result = $this->query("SELECT @@IDENTITY FROM $seqname");
311 $repeat = 0;
312 }
313 } while ($repeat);
314 if (DB::isError($result)) {
315 return $this->raiseError($result);
316 }
317 $result = $result->fetchRow(DB_FETCHMODE_ORDERED);
318 return $result[0];
319 }
320
321 // }}}
322 // {{{ createSequence()
323
324 function createSequence($seq_name)
325 {
326 $seqname = $this->getSequenceName($seq_name);
327 return $this->query("CREATE TABLE $seqname ".
328 '([id] [int] IDENTITY (1, 1) NOT NULL ,' .
329 '[vapor] [int] NULL)');
330 }
331 // }}}
332 // {{{ dropSequence()
333
334 function dropSequence($seq_name)
335 {
336 $seqname = $this->getSequenceName($seq_name);
337 return $this->query("DROP TABLE $seqname");
338 }
339 // }}}
340
341 function errorCode()
342 {
343 $this->pushErrorHandling(PEAR_ERROR_RETURN);
344 $error_code = $this->getOne('select @@ERROR as ErrorCode');
345 $this->popErrorHandling();
346 // XXX Debug
347 if (!isset($this->errorcode_map[$error_code])) {
348 return DB_ERROR;
349 }
350 return $error_code;
351 }
352
353 function mssqlRaiseError($code = null)
354 {
355 if ($code !== null) {
356 $code = $this->errorCode();
357 if (DB::isError($code)) {
358 return $this->raiseError($code);
359 }
360 }
361 return $this->raiseError($code, null, null, null,
362 mssql_get_last_message());
363 }
364
365 /**
366
367 * Returns information about a table or a result set
368 *
369 * NOTE: doesn't support table name and flags if called from a db_result
370 *
371 * @param mixed $resource SQL Server result identifier or table name
372 * @param int $mode A valid tableInfo mode (DB_TABLEINFO_ORDERTABLE or
373 * DB_TABLEINFO_ORDER)
374 *
375 * @return array An array with all the information
376 */
377
378 function tableInfo($result, $mode = null)
379 {
380
381 $count = 0;
382 $id = 0;
383 $res = array();
384
385 /*
386 * depending on $mode, metadata returns the following values:
387 *
388 * - mode is false (default):
389 * $result[]:
390 * [0]["table"] table name
391 * [0]["name"] field name
392 * [0]["type"] field type
393 * [0]["len"] field length
394 * [0]["flags"] field flags
395 *
396 * - mode is DB_TABLEINFO_ORDER
397 * $result[]:
398 * ["num_fields"] number of metadata records
399 * [0]["table"] table name
400 * [0]["name"] field name
401 * [0]["type"] field type
402 * [0]["len"] field length
403 * [0]["flags"] field flags
404 * ["order"][field name] index of field named "field name"
405 * The last one is used, if you have a field name, but no index.
406 * Test: if (isset($result['meta']['myfield'])) { ...
407 *
408 * - mode is DB_TABLEINFO_ORDERTABLE
409 * the same as above. but additionally
410 * ["ordertable"][table name][field name] index of field
411 * named "field name"
412 *
413 * this is, because if you have fields from different
414 * tables with the same field name * they override each
415 * other with DB_TABLEINFO_ORDER
416 *
417 * you can combine DB_TABLEINFO_ORDER and
418 * DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
419 * DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
420 */
421
422 // if $result is a string, then we want information about a
423 // table without a resultset
424
425 if (is_string($result)) {
426 $id = mssql_query("SELECT * FROM $result", $this->connection);
427 if (empty($id)) {
428 return $this->mssqlRaiseError();
429 }
430 } else { // else we want information about a resultset
431 $id = $result;
432 if (empty($id)) {
433 return $this->mssqlRaiseError();
434 }
435 }
436
437 $count = @mssql_num_fields($id);
438
439 // made this IF due to performance (one if is faster than $count if's)
440 if (empty($mode)) {
441
442 for ($i=0; $i<$count; $i++) {
443 $res[$i]['table'] = (is_string($result)) ? $result : '';
444 $res[$i]['name'] = @mssql_field_name($id, $i);
445 $res[$i]['type'] = @mssql_field_type($id, $i);
446 $res[$i]['len'] = @mssql_field_length($id, $i);
447 $res[$i]['flags'] = '';
448 }
449
450 } else { // full
451 $res['num_fields']= $count;
452
453 for ($i=0; $i<$count; $i++) {
454 $res[$i]['table'] = (is_string($result)) ? $result : '';
455 $res[$i]['name'] = @mssql_field_name($id, $i);
456 $res[$i]['type'] = @mssql_field_type($id, $i);
457 $res[$i]['len'] = @mssql_field_length($id, $i);
458 $res[$i]['flags'] = '';
459 if ($mode & DB_TABLEINFO_ORDER) {
460 $res['order'][$res[$i]['name']] = $i;
461 }
462 if ($mode & DB_TABLEINFO_ORDERTABLE) {
463 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
464 }
465 }
466 }
467
468 // free the result only if we were called on a table
469 if (is_string($result)) {
470 @mssql_free_result($id);
471 }
472 return $res;
473 }
474
475 // {{{ getSpecialQuery()
476
477 /**
478 * Returns the query needed to get some backend info
479 * @param string $type What kind of info you want to retrieve
480 * @return string The SQL query string
481 */
482 function getSpecialQuery($type)
483 {
484 switch ($type) {
485 case 'tables':
486 $sql = "select name from sysobjects where type = 'U' order by name";
487 break;
488 case 'views':
489 $sql = "select name from sysobjects where type = 'V'";
490 break;
491 default:
492 return null;
493 }
494 return $sql;
495 }
496
497 // }}}
498
499 }
500 ?>

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed