1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
30: class DibiMsSql2005Driver extends DibiObject implements IDibiDriver, IDibiResultDriver
31: {
32:
33: private $connection;
34:
35:
36: private $resultSet;
37:
38:
39:
40: 41: 42:
43: public function __construct()
44: {
45: if (!extension_loaded('sqlsrv')) {
46: throw new DibiDriverException("PHP extension 'sqlsrv' is not loaded.");
47: }
48: }
49:
50:
51:
52: 53: 54: 55: 56:
57: public function connect(array &$config)
58: {
59: DibiConnection::alias($config, 'options|UID', 'username');
60: DibiConnection::alias($config, 'options|PWD', 'password');
61: DibiConnection::alias($config, 'options|Database', 'database');
62:
63: if (isset($config['resource'])) {
64: $this->connection = $config['resource'];
65:
66: } else {
67: $this->connection = sqlsrv_connect($config['host'], (array) $config['options']);
68: }
69:
70: if (!is_resource($this->connection)) {
71: $info = sqlsrv_errors();
72: throw new DibiDriverException($info[0]['message'], $info[0]['code']);
73: }
74: }
75:
76:
77:
78: 79: 80: 81:
82: public function disconnect()
83: {
84: sqlsrv_close($this->connection);
85: }
86:
87:
88:
89: 90: 91: 92: 93: 94:
95: public function query($sql)
96: {
97: $this->resultSet = sqlsrv_query($this->connection, $sql);
98:
99: if ($this->resultSet === FALSE) {
100: $info = sqlsrv_errors();
101: throw new DibiDriverException($info[0]['message'], $info[0]['code'], $sql);
102: }
103:
104: return is_resource($this->resultSet) ? clone $this : NULL;
105: }
106:
107:
108:
109: 110: 111: 112:
113: public function getAffectedRows()
114: {
115: return sqlsrv_rows_affected($this->resultSet);
116: }
117:
118:
119:
120: 121: 122: 123:
124: public function getInsertId($sequence)
125: {
126: $res = sqlsrv_query($this->connection, 'SELECT @@IDENTITY');
127: if (is_resource($res)) {
128: $row = sqlsrv_fetch_array($res, SQLSRV_FETCH_NUMERIC);
129: return $row[0];
130: }
131: return FALSE;
132: }
133:
134:
135:
136: 137: 138: 139: 140: 141:
142: public function begin($savepoint = NULL)
143: {
144: $this->query('BEGIN TRANSACTION');
145: }
146:
147:
148:
149: 150: 151: 152: 153: 154:
155: public function commit($savepoint = NULL)
156: {
157: $this->query('COMMIT');
158: }
159:
160:
161:
162: 163: 164: 165: 166: 167:
168: public function rollback($savepoint = NULL)
169: {
170: $this->query('ROLLBACK');
171: }
172:
173:
174:
175: 176: 177: 178:
179: public function getResource()
180: {
181: return $this->connection;
182: }
183:
184:
185:
186: 187: 188: 189:
190: public function getReflector()
191: {
192: throw new NotSupportedException;
193: }
194:
195:
196:
197:
198:
199:
200:
201: 202: 203: 204: 205: 206: 207:
208: public function escape($value, $type)
209: {
210: switch ($type) {
211: case dibi::TEXT:
212: case dibi::BINARY:
213: return "'" . str_replace("'", "''", $value) . "'";
214:
215: case dibi::IDENTIFIER:
216: 217: return '[' . str_replace(array('[', ']'), array('[[', ']]'), $value) . ']';
218:
219: case dibi::BOOL:
220: return $value ? 1 : 0;
221:
222: case dibi::DATE:
223: return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
224:
225: case dibi::DATETIME:
226: return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
227:
228: default:
229: throw new InvalidArgumentException('Unsupported type.');
230: }
231: }
232:
233:
234:
235: 236: 237: 238: 239: 240:
241: public function escapeLike($value, $pos)
242: {
243: $value = strtr($value, array("'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]'));
244: return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
245: }
246:
247:
248:
249: 250: 251: 252: 253: 254: 255:
256: public function unescape($value, $type)
257: {
258: if ($type === dibi::BINARY) {
259: return $value;
260: }
261: throw new InvalidArgumentException('Unsupported type.');
262: }
263:
264:
265:
266: 267: 268: 269: 270: 271: 272:
273: public function applyLimit(&$sql, $limit, $offset)
274: {
275: 276: if ($limit >= 0) {
277: $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
278: }
279:
280: if ($offset) {
281: throw new NotImplementedException('Offset is not implemented.');
282: }
283: }
284:
285:
286:
287:
288:
289:
290:
291: 292: 293: 294:
295: public function getRowCount()
296: {
297: throw new NotSupportedException('Row count is not available for unbuffered queries.');
298: }
299:
300:
301:
302: 303: 304: 305: 306:
307: public function fetch($assoc)
308: {
309: return sqlsrv_fetch_array($this->resultSet, $assoc ? SQLSRV_FETCH_ASSOC : SQLSRV_FETCH_NUMERIC);
310: }
311:
312:
313:
314: 315: 316: 317: 318:
319: public function seek($row)
320: {
321: throw new NotSupportedException('Cannot seek an unbuffered result set.');
322: }
323:
324:
325:
326: 327: 328: 329:
330: public function free()
331: {
332: sqlsrv_free_stmt($this->resultSet);
333: $this->resultSet = NULL;
334: }
335:
336:
337:
338: 339: 340: 341:
342: public function getResultColumns()
343: {
344: $count = sqlsrv_num_fields($this->resultSet);
345: $columns = array();
346: for ($i = 0; $i < $count; $i++) {
347: $row = (array) sqlsrv_field_metadata($this->resultSet, $i);
348: $columns[] = array(
349: 'name' => $row['Name'],
350: 'fullname' => $row['Name'],
351: 'nativetype' => $row['Type'],
352: );
353: }
354: return $columns;
355: }
356:
357:
358:
359: 360: 361: 362:
363: public function getResultResource()
364: {
365: return $this->resultSet;
366: }
367:
368: }
369: