source: github/program/lib/MDB2/Driver/Datatype/mssql.php @ 95ebbc98

HEADcourier-fixdev-browser-capabilitiespdorelease-0.6release-0.7release-0.8
Last change on this file since 95ebbc98 was 95ebbc98, checked in by till <till@…>, 5 years ago
  • putting latest MDB2 into SVN
  • adding MDB2 drivers for mssql, mysql, mysqli, pgsql, sqlite
  • Property mode set to 100644
File size: 19.1 KB
Line 
1<?php
2// vim: set et ts=4 sw=4 fdm=marker:
3// +----------------------------------------------------------------------+
4// | PHP versions 4 and 5                                                 |
5// +----------------------------------------------------------------------+
6// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
7// | Stig. S. Bakken, Lukas Smith                                         |
8// | All rights reserved.                                                 |
9// +----------------------------------------------------------------------+
10// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
11// | API as well as database abstraction for PHP applications.            |
12// | This LICENSE is in the BSD license style.                            |
13// |                                                                      |
14// | Redistribution and use in source and binary forms, with or without   |
15// | modification, are permitted provided that the following conditions   |
16// | are met:                                                             |
17// |                                                                      |
18// | Redistributions of source code must retain the above copyright       |
19// | notice, this list of conditions and the following disclaimer.        |
20// |                                                                      |
21// | Redistributions in binary form must reproduce the above copyright    |
22// | notice, this list of conditions and the following disclaimer in the  |
23// | documentation and/or other materials provided with the distribution. |
24// |                                                                      |
25// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
26// | Lukas Smith nor the names of his contributors may be used to endorse |
27// | or promote products derived from this software without specific prior|
28// | written permission.                                                  |
29// |                                                                      |
30// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
31// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
32// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
33// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
34// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
35// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
36// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
37// |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
38// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
39// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
40// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
41// | POSSIBILITY OF SUCH DAMAGE.                                          |
42// +----------------------------------------------------------------------+
43// | Authors: Lukas Smith <smith@pooteeweet.org>                          |
44// |          Daniel Convissor <danielc@php.net>                          |
45// +----------------------------------------------------------------------+
46//
47// $Id: mssql.php,v 1.59 2007/12/03 20:59:50 quipo Exp $
48//
49
50require_once 'MDB2/Driver/Datatype/Common.php';
51
52/**
53 * MDB2 MS SQL driver
54 *
55 * @package MDB2
56 * @category Database
57 * @author  Lukas Smith <smith@pooteeweet.org>
58 */
59class MDB2_Driver_Datatype_mssql extends MDB2_Driver_Datatype_Common
60{
61    // {{{ _baseConvertResult()
62
63    /**
64     * general type conversion method
65     *
66     * @param mixed   $value refernce to a value to be converted
67     * @param string  $type  specifies which type to convert to
68     * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
69     * @return object a MDB2 error on failure
70     * @access protected
71     */
72    function _baseConvertResult($value, $type, $rtrim = true)
73    {
74        if (is_null($value)) {
75            return null;
76        }
77        switch ($type) {
78        case 'boolean':
79            return $value == '1';
80        case 'date':
81            if (strlen($value) > 10) {
82                $value = substr($value,0,10);
83            }
84            return $value;
85        case 'time':
86            if (strlen($value) > 8) {
87                $value = substr($value,11,8);
88            }
89            return $value;
90        }
91        return parent::_baseConvertResult($value, $type, $rtrim);
92    }
93
94    // }}}
95    // {{{ _getCollationFieldDeclaration()
96
97    /**
98     * Obtain DBMS specific SQL code portion needed to set the COLLATION
99     * of a field declaration to be used in statements like CREATE TABLE.
100     *
101     * @param string $collation name of the collation
102     *
103     * @return string DBMS specific SQL code portion needed to set the COLLATION
104     *                of a field declaration.
105     */
106    function _getCollationFieldDeclaration($collation)
107    {
108        return 'COLLATE '.$collation;
109    }
110
111    // }}}
112    // {{{ getTypeDeclaration()
113
114    /**
115     * Obtain DBMS specific SQL code portion needed to declare an text type
116     * field to be used in statements like CREATE TABLE.
117     *
118     * @param array $field  associative array with the name of the properties
119     *      of the field being declared as array indexes. Currently, the types
120     *      of supported field properties are as follows:
121     *
122     *      length
123     *          Integer value that determines the maximum length of the text
124     *          field. If this argument is missing the field should be
125     *          declared to have the longest length allowed by the DBMS.
126     *
127     *      default
128     *          Text value to be used as default for this field.
129     *
130     *      notnull
131     *          Boolean flag that indicates whether this field is constrained
132     *          to not be set to null.
133     * @return string  DBMS specific SQL code portion that should be used to
134     *      declare the specified field.
135     * @access public
136     */
137    function getTypeDeclaration($field)
138    {
139        $db =& $this->getDBInstance();
140        if (PEAR::isError($db)) {
141            return $db;
142        }
143
144        switch ($field['type']) {
145        case 'text':
146            $length = !empty($field['length'])
147                ? $field['length'] : false;
148            $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
149            return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
150                : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
151        case 'clob':
152            if (!empty($field['length'])) {
153                $length = $field['length'];
154                if ($length <= 8000) {
155                    return 'VARCHAR('.$length.')';
156                }
157             }
158             return 'TEXT';
159        case 'blob':
160            if (!empty($field['length'])) {
161                $length = $field['length'];
162                if ($length <= 8000) {
163                    return "VARBINARY($length)";
164                }
165            }
166            return 'IMAGE';
167        case 'integer':
168            return 'INT';
169        case 'boolean':
170            return 'BIT';
171        case 'date':
172            return 'CHAR ('.strlen('YYYY-MM-DD').')';
173        case 'time':
174            return 'CHAR ('.strlen('HH:MM:SS').')';
175        case 'timestamp':
176            return 'CHAR ('.strlen('YYYY-MM-DD HH:MM:SS').')';
177        case 'float':
178            return 'FLOAT';
179        case 'decimal':
180            $length = !empty($field['length']) ? $field['length'] : 18;
181            $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
182            return 'DECIMAL('.$length.','.$scale.')';
183        }
184        return '';
185    }
186
187    // }}}
188    // {{{ _getDeclaration()
189
190    /**
191     * Obtain DBMS specific SQL code portion needed to declare a generic type
192     * field to be used in statements like CREATE TABLE.
193     *
194     * @param string $name   name the field to be declared.
195     * @param array  $field  associative array with the name of the properties
196     *      of the field being declared as array indexes. Currently, the types
197     *      of supported field properties are as follows:
198     *
199     *      length
200     *          Integer value that determines the maximum length of the text
201     *          field. If this argument is missing the field should be
202     *          declared to have the longest length allowed by the DBMS.
203     *
204     *      default
205     *          Text value to be used as default for this field.
206     *
207     *      notnull
208     *          Boolean flag that indicates whether this field is constrained
209     *          to not be set to null.
210     * @return string  DBMS specific SQL code portion that should be used to
211     *      declare the specified field.
212     * @access protected
213     */
214    function _getDeclarationOptions($field)
215    {
216        $charset = empty($field['charset']) ? '' :
217            ' '.$this->_getCharsetFieldDeclaration($field['charset']);
218
219        $default = '';
220        if (array_key_exists('default', $field)) {
221            if ($field['default'] === '') {
222                $db =& $this->getDBInstance();
223                if (PEAR::isError($db)) {
224                    return $db;
225                }
226                $field['default'] = empty($field['notnull'])
227                    ? null : $this->valid_default_values[$field['type']];
228                if ($field['default'] === ''
229                    && ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)
230                ) {
231                    $field['default'] = ' ';
232                }
233            }
234            $default = ' DEFAULT '.$this->quote($field['default'], $field['type']);
235        } elseif (empty($field['notnull'])) {
236            $default = ' DEFAULT NULL';
237        }
238
239        $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
240        if ($default == ' DEFAULT NULL' && $notnull == ' NULL') {
241            $notnull = '';
242        }
243
244        $collation = empty($field['collation']) ? '' :
245            ' '.$this->_getCollationFieldDeclaration($field['collation']);
246        return $charset.$default.$notnull.$collation;
247    }
248
249    // }}}
250    // {{{ _getIntegerDeclaration()
251
252    /**
253     * Obtain DBMS specific SQL code portion needed to declare an integer type
254     * field to be used in statements like CREATE TABLE.
255     *
256     * @param string  $name   name the field to be declared.
257     * @param string  $field  associative array with the name of the properties
258     *                        of the field being declared as array indexes.
259     *                        Currently, the types of supported field
260     *                        properties are as follows:
261     *
262     *                       unsigned
263     *                        Boolean flag that indicates whether the field
264     *                        should be declared as unsigned integer if
265     *                        possible.
266     *
267     *                       default
268     *                        Integer value to be used as default for this
269     *                        field.
270     *
271     *                       notnull
272     *                        Boolean flag that indicates whether this field is
273     *                        constrained to not be set to null.
274     * @return string  DBMS specific SQL code portion that should be used to
275     *                 declare the specified field.
276     * @access protected
277     */
278    function _getIntegerDeclaration($name, $field)
279    {
280        $db =& $this->getDBInstance();
281        if (PEAR::isError($db)) {
282            return $db;
283        }
284
285        $default = $autoinc = '';;
286        if (!empty($field['autoincrement'])) {
287            $autoinc = ' IDENTITY PRIMARY KEY';
288        } elseif (array_key_exists('default', $field)) {
289            if ($field['default'] === '') {
290                $field['default'] = empty($field['notnull']) ? null : 0;
291            }
292            $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
293        } elseif (empty($field['notnull'])) {
294            $default = ' DEFAULT NULL';
295        }
296
297        $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
298        if ($default == ' DEFAULT NULL' && $notnull == ' NULL') {
299            $notnull = '';
300        }
301        if (!empty($field['unsigned'])) {
302            $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
303        }
304        $name = $db->quoteIdentifier($name, true);
305        return $name.' '.$this->getTypeDeclaration($field).$default.$notnull.$autoinc;
306    }
307
308    // }}}
309    // {{{ _getCLOBDeclaration()
310
311    /**
312     * Obtain DBMS specific SQL code portion needed to declare an character
313     * large object type field to be used in statements like CREATE TABLE.
314     *
315     * @param string $name name the field to be declared.
316     * @param array $field associative array with the name of the properties
317     *        of the field being declared as array indexes. Currently, the types
318     *        of supported field properties are as follows:
319     *
320     *        length
321     *            Integer value that determines the maximum length of the large
322     *            object field. If this argument is missing the field should be
323     *            declared to have the longest length allowed by the DBMS.
324     *
325     *        notnull
326     *            Boolean flag that indicates whether this field is constrained
327     *            to not be set to null.
328     * @return string DBMS specific SQL code portion that should be used to
329     *        declare the specified field.
330     * @access public
331     */
332    function _getCLOBDeclaration($name, $field)
333    {
334        $db =& $this->getDBInstance();
335        if (PEAR::isError($db)) {
336            return $db;
337        }
338
339        $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
340        $name = $db->quoteIdentifier($name, true);
341        return $name.' '.$this->getTypeDeclaration($field).$notnull;
342    }
343
344    // }}}
345    // {{{ _getBLOBDeclaration()
346
347    /**
348     * Obtain DBMS specific SQL code portion needed to declare an binary large
349     * object type field to be used in statements like CREATE TABLE.
350     *
351     * @param string $name name the field to be declared.
352     * @param array $field associative array with the name of the properties
353     *        of the field being declared as array indexes. Currently, the types
354     *        of supported field properties are as follows:
355     *
356     *        length
357     *            Integer value that determines the maximum length of the large
358     *            object field. If this argument is missing the field should be
359     *            declared to have the longest length allowed by the DBMS.
360     *
361     *        notnull
362     *            Boolean flag that indicates whether this field is constrained
363     *            to not be set to null.
364     * @return string DBMS specific SQL code portion that should be used to
365     *        declare the specified field.
366     * @access protected
367     */
368    function _getBLOBDeclaration($name, $field)
369    {
370        $db =& $this->getDBInstance();
371        if (PEAR::isError($db)) {
372            return $db;
373        }
374
375        $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
376        $name = $db->quoteIdentifier($name, true);
377        return $name.' '.$this->getTypeDeclaration($field).$notnull;
378    }
379
380    // }}}
381    // {{{ _quoteBLOB()
382
383    /**
384     * Convert a text value into a DBMS specific format that is suitable to
385     * compose query statements.
386     *
387     * @param string $value text string value that is intended to be converted.
388     * @param bool $quote determines if the value should be quoted and escaped
389     * @param bool $escape_wildcards if to escape escape wildcards
390     * @return string  text string that represents the given argument value in
391     *                 a DBMS specific format.
392     * @access protected
393     */
394    function _quoteBLOB($value, $quote, $escape_wildcards)
395    {
396        if (!$quote) {
397            return $value;
398        }
399        $value = bin2hex("0x".$this->_readFile($value));
400        return $value;
401    }
402
403    // }}}
404    // {{{ _mapNativeDatatype()
405
406    /**
407     * Maps a native array description of a field to a MDB2 datatype and length
408     *
409     * @param array  $field native field description
410     * @return array containing the various possible types, length, sign, fixed
411     * @access public
412     */
413    function _mapNativeDatatype($field)
414    {
415        // todo: handle length of various int variations
416        $db_type = preg_replace('/\d/', '', strtolower($field['type']));
417        $length = $field['length'];
418        $type = array();
419        // todo: unsigned handling seems to be missing
420        $unsigned = $fixed = null;
421        switch ($db_type) {
422        case 'bit':
423            $type[0] = 'boolean';
424            break;
425        case 'tinyint':
426            $type[0] = 'integer';
427            $length = 1;
428            break;
429        case 'smallint':
430            $type[0] = 'integer';
431            $length = 2;
432            break;
433        case 'int':
434            $type[0] = 'integer';
435            $length = 4;
436            break;
437        case 'bigint':
438            $type[0] = 'integer';
439            $length = 8;
440            break;
441        case 'datetime':
442            $type[0] = 'timestamp';
443            break;
444        case 'float':
445        case 'real':
446        case 'numeric':
447            $type[0] = 'float';
448            break;
449        case 'decimal':
450        case 'money':
451            $type[0] = 'decimal';
452            $length = $field['numeric_precision'].','.$field['numeric_scale'];
453            break;
454        case 'text':
455        case 'ntext':
456        case 'varchar':
457        case 'nvarchar':
458            $fixed = false;
459        case 'char':
460        case 'nchar':
461            $type[0] = 'text';
462            if ($length == '1') {
463                $type[] = 'boolean';
464                if (preg_match('/^(is|has)/', $field['name'])) {
465                    $type = array_reverse($type);
466                }
467            } elseif (strstr($db_type, 'text')) {
468                $type[] = 'clob';
469                $type = array_reverse($type);
470            }
471            if ($fixed !== false) {
472                $fixed = true;
473            }
474            break;
475        case 'image':
476        case 'varbinary':
477            $type[] = 'blob';
478            $length = null;
479            break;
480        default:
481            $db =& $this->getDBInstance();
482            if (PEAR::isError($db)) {
483                return $db;
484            }
485            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
486                'unknown database attribute type: '.$db_type, __FUNCTION__);
487        }
488
489        if ((int)$length <= 0) {
490            $length = null;
491        }
492
493        return array($type, $length, $unsigned, $fixed);
494    }
495    // }}}
496}
497
498?>
Note: See TracBrowser for help on using the repository browser.