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