source: branches/version-2_13-dev/data/module/MDB2/Driver/Datatype/pgsql.php @ 23022

Revision 23022, 19.5 KB checked in by Seasoft, 11 years ago (diff)

#2322 (セッションのGC処理がエラーとなる)

  • Property svn:eol-style set to LF
  • Property svn:mime-type set to text/x-httpd-php; charset=UTF-8
Line 
1<?php
2// +----------------------------------------------------------------------+
3// | PHP versions 4 and 5                                                 |
4// +----------------------------------------------------------------------+
5// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
6// | Stig. S. Bakken, Lukas Smith                                         |
7// | All rights reserved.                                                 |
8// +----------------------------------------------------------------------+
9// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
10// | API as well as database abstraction for PHP applications.            |
11// | This LICENSE is in the BSD license style.                            |
12// |                                                                      |
13// | Redistribution and use in source and binary forms, with or without   |
14// | modification, are permitted provided that the following conditions   |
15// | are met:                                                             |
16// |                                                                      |
17// | Redistributions of source code must retain the above copyright       |
18// | notice, this list of conditions and the following disclaimer.        |
19// |                                                                      |
20// | Redistributions in binary form must reproduce the above copyright    |
21// | notice, this list of conditions and the following disclaimer in the  |
22// | documentation and/or other materials provided with the distribution. |
23// |                                                                      |
24// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
25// | Lukas Smith nor the names of his contributors may be used to endorse |
26// | or promote products derived from this software without specific prior|
27// | written permission.                                                  |
28// |                                                                      |
29// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
30// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
31// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
32// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
33// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
34// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
35// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
36// |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
37// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
38// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
39// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
40// | POSSIBILITY OF SUCH DAMAGE.                                          |
41// +----------------------------------------------------------------------+
42// | Author: Paul Cooper <pgc@ucecom.com>                                 |
43// +----------------------------------------------------------------------+
44//
45// $Id: pgsql.php 327310 2012-08-27 15:16:18Z danielc $
46
47require_once 'MDB2/Driver/Datatype/Common.php';
48
49/**
50 * MDB2 PostGreSQL driver
51 *
52 * @package MDB2
53 * @category Database
54 * @author  Paul Cooper <pgc@ucecom.com>
55 */
56class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common
57{
58    // {{{ _baseConvertResult()
59
60    /**
61     * General type conversion method
62     *
63     * @param mixed   $value refernce to a value to be converted
64     * @param string  $type  specifies which type to convert to
65     * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
66     * @return object a MDB2 error on failure
67     * @access protected
68     */
69    function _baseConvertResult($value, $type, $rtrim = true)
70    {
71        if (null === $value) {
72            return null;
73        }
74        switch ($type) {
75        case 'boolean':
76            return ($value == 'f')? false : !empty($value);
77        case 'float':
78            return doubleval($value);
79        case 'date':
80            return $value;
81        case 'time':
82            return substr($value, 0, strlen('HH:MM:SS'));
83        case 'timestamp':
84            return substr($value, 0, strlen('YYYY-MM-DD HH:MM:SS'));
85        case 'blob':
86            $value = pg_unescape_bytea($value);
87            return parent::_baseConvertResult($value, $type, $rtrim);
88        }
89        return parent::_baseConvertResult($value, $type, $rtrim);
90    }
91
92    // }}}
93    // {{{ getTypeDeclaration()
94
95    /**
96     * Obtain DBMS specific SQL code portion needed to declare an text type
97     * field to be used in statements like CREATE TABLE.
98     *
99     * @param array $field  associative array with the name of the properties
100     *      of the field being declared as array indexes. Currently, the types
101     *      of supported field properties are as follows:
102     *
103     *      length
104     *          Integer value that determines the maximum length of the text
105     *          field. If this argument is missing the field should be
106     *          declared to have the longest length allowed by the DBMS.
107     *
108     *      default
109     *          Text value to be used as default for this field.
110     *
111     *      notnull
112     *          Boolean flag that indicates whether this field is constrained
113     *          to not be set to null.
114     * @return string  DBMS specific SQL code portion that should be used to
115     *      declare the specified field.
116     * @access public
117     */
118    function getTypeDeclaration($field)
119    {
120        $db = $this->getDBInstance();
121        if (MDB2::isError($db)) {
122            return $db;
123        }
124
125        switch ($field['type']) {
126        case 'text':
127            $length = !empty($field['length']) ? $field['length'] : false;
128            $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
129            return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
130                : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
131        case 'clob':
132            return 'TEXT';
133        case 'blob':
134            return 'BYTEA';
135        case 'integer':
136            if (!empty($field['autoincrement'])) {
137                if (!empty($field['length'])) {
138                    $length = $field['length'];
139                    if ($length > 4) {
140                        return 'BIGSERIAL PRIMARY KEY';
141                    }
142                }
143                return 'SERIAL PRIMARY KEY';
144            }
145            if (!empty($field['length'])) {
146                $length = $field['length'];
147                if ($length <= 2) {
148                    return 'SMALLINT';
149                } elseif ($length == 3 || $length == 4) {
150                    return 'INT';
151                } elseif ($length > 4) {
152                    return 'BIGINT';
153                }
154            }
155            return 'INT';
156        case 'boolean':
157            return 'BOOLEAN';
158        case 'date':
159            return 'DATE';
160        case 'time':
161            return 'TIME without time zone';
162        case 'timestamp':
163            return 'TIMESTAMP without time zone';
164        case 'float':
165            return 'FLOAT8';
166        case 'decimal':
167            $length = !empty($field['length']) ? $field['length'] : 18;
168            $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
169            return 'NUMERIC('.$length.','.$scale.')';
170        }
171    }
172
173    // }}}
174    // {{{ _getIntegerDeclaration()
175
176    /**
177     * Obtain DBMS specific SQL code portion needed to declare an integer type
178     * field to be used in statements like CREATE TABLE.
179     *
180     * @param string $name name the field to be declared.
181     * @param array $field associative array with the name of the properties
182     *       of the field being declared as array indexes. Currently, the types
183     *       of supported field properties are as follows:
184     *
185     *       unsigned
186     *           Boolean flag that indicates whether the field should be
187     *           declared as unsigned integer if possible.
188     *
189     *       default
190     *           Integer value to be used as default for this field.
191     *
192     *       notnull
193     *           Boolean flag that indicates whether this field is constrained
194     *           to not be set to null.
195     * @return string DBMS specific SQL code portion that should be used to
196     *       declare the specified field.
197     * @access protected
198     */
199    function _getIntegerDeclaration($name, $field)
200    {
201        $db = $this->getDBInstance();
202        if (MDB2::isError($db)) {
203            return $db;
204        }
205
206        if (!empty($field['unsigned'])) {
207            $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
208        }
209        if (!empty($field['autoincrement'])) {
210            $name = $db->quoteIdentifier($name, true);
211            return $name.' '.$this->getTypeDeclaration($field);
212        }
213        $default = '';
214        if (array_key_exists('default', $field)) {
215            if ($field['default'] === '') {
216                $field['default'] = empty($field['notnull']) ? null : 0;
217            }
218            $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
219        }
220
221        $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
222        if (empty($default) && empty($notnull)) {
223            $default = ' DEFAULT NULL';
224        }
225        $name = $db->quoteIdentifier($name, true);
226        return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
227    }
228
229    // }}}
230    // {{{ _quoteCLOB()
231
232    /**
233     * Convert a text value into a DBMS specific format that is suitable to
234     * compose query statements.
235     *
236     * @param string $value text string value that is intended to be converted.
237     * @param bool $quote determines if the value should be quoted and escaped
238     * @param bool $escape_wildcards if to escape escape wildcards
239     * @return string text string that represents the given argument value in
240     *      a DBMS specific format.
241     * @access protected
242     */
243    function _quoteCLOB($value, $quote, $escape_wildcards)
244    {
245        $db = $this->getDBInstance();
246        if (MDB2::isError($db)) {
247            return $db;
248        }
249        if ($db->options['lob_allow_url_include']) {
250            $value = $this->_readFile($value);
251            if (MDB2::isError($value)) {
252                return $value;
253            }
254        }
255        return $this->_quoteText($value, $quote, $escape_wildcards);
256    }
257
258    // }}}
259    // {{{ _quoteBLOB()
260
261    /**
262     * Convert a text value into a DBMS specific format that is suitable to
263     * compose query statements.
264     *
265     * @param string $value text string value that is intended to be converted.
266     * @param bool $quote determines if the value should be quoted and escaped
267     * @param bool $escape_wildcards if to escape escape wildcards
268     * @return string text string that represents the given argument value in
269     *      a DBMS specific format.
270     * @access protected
271     */
272    function _quoteBLOB($value, $quote, $escape_wildcards)
273    {
274        if (!$quote) {
275            return $value;
276        }
277        $db = $this->getDBInstance();
278        if (MDB2::isError($db)) {
279            return $db;
280        }
281        if ($db->options['lob_allow_url_include']) {
282            $value = $this->_readFile($value);
283            if (MDB2::isError($value)) {
284                return $value;
285            }
286        }
287        if (version_compare(PHP_VERSION, '5.2.0RC6', '>=')) {
288            $connection = $db->getConnection();
289            if (MDB2::isError($connection)) {
290                return $connection;
291            }
292            $value = @pg_escape_bytea($connection, $value);
293        } else {
294            $value = @pg_escape_bytea($value);
295        }
296        return "'".$value."'";
297    }
298
299    // }}}
300    // {{{ _quoteBoolean()
301
302    /**
303     * Convert a text value into a DBMS specific format that is suitable to
304     * compose query statements.
305     *
306     * @param string $value text string value that is intended to be converted.
307     * @param bool $quote determines if the value should be quoted and escaped
308     * @param bool $escape_wildcards if to escape escape wildcards
309     * @return string text string that represents the given argument value in
310     *       a DBMS specific format.
311     * @access protected
312     */
313    function _quoteBoolean($value, $quote, $escape_wildcards)
314    {
315        $value = $value ? 't' : 'f';
316        if (!$quote) {
317            return $value;
318        }
319        return "'".$value."'";
320    }
321
322    // }}}
323    // {{{ matchPattern()
324
325    /**
326     * build a pattern matching string
327     *
328     * @access public
329     *
330     * @param array $pattern even keys are strings, odd are patterns (% and _)
331     * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
332     * @param string $field optional field name that is being matched against
333     *                  (might be required when emulating ILIKE)
334     *
335     * @return string SQL pattern
336     */
337    function matchPattern($pattern, $operator = null, $field = null)
338    {
339        $db = $this->getDBInstance();
340        if (MDB2::isError($db)) {
341            return $db;
342        }
343
344        $match = '';
345        if (null !== $operator) {
346            $field = (null === $field) ? '' : $field.' ';
347            $operator = strtoupper($operator);
348            switch ($operator) {
349            // case insensitive
350            case 'ILIKE':
351                $match = $field.'ILIKE ';
352                break;
353            case 'NOT ILIKE':
354                $match = $field.'NOT ILIKE ';
355                break;
356            // case sensitive
357            case 'LIKE':
358                $match = $field.'LIKE ';
359                break;
360            case 'NOT LIKE':
361                $match = $field.'NOT LIKE ';
362                break;
363            default:
364                return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
365                    'not a supported operator type:'. $operator, __FUNCTION__);
366            }
367        }
368        $match.= "'";
369        foreach ($pattern as $key => $value) {
370            if ($key % 2) {
371                $match.= $value;
372            } else {
373                $match.= $db->escapePattern($db->escape($value));
374            }
375        }
376        $match.= "'";
377        $match.= $this->patternEscapeString();
378        return $match;
379    }
380
381    // }}}
382    // {{{ patternEscapeString()
383
384    /**
385     * build string to define escape pattern string
386     *
387     * @access public
388     *
389     *
390     * @return string define escape pattern
391     */
392    function patternEscapeString()
393    {
394        $db = $this->getDBInstance();
395        if (MDB2::isError($db)) {
396            return $db;
397        }
398        return ' ESCAPE '.$this->quote($db->string_quoting['escape_pattern']);
399    }
400
401    // }}}
402    // {{{ _mapNativeDatatype()
403
404    /**
405     * Maps a native array description of a field to a MDB2 datatype and length
406     *
407     * @param array  $field native field description
408     * @return array containing the various possible types, length, sign, fixed
409     * @access public
410     */
411    function _mapNativeDatatype($field)
412    {
413        $db_type = strtolower($field['type']);
414        $length = $field['length'];
415        $type = array();
416        $unsigned = $fixed = null;
417        switch ($db_type) {
418        case 'smallint':
419        case 'int2':
420            $type[] = 'integer';
421            $unsigned = false;
422            $length = 2;
423            if ($length == '2') {
424                $type[] = 'boolean';
425                if (preg_match('/^(is|has)/', $field['name'])) {
426                    $type = array_reverse($type);
427                }
428            }
429            break;
430        case 'int':
431        case 'int4':
432        case 'integer':
433        case 'serial':
434        case 'serial4':
435            $type[] = 'integer';
436            $unsigned = false;
437            $length = 4;
438            break;
439        case 'bigint':
440        case 'int8':
441        case 'bigserial':
442        case 'serial8':
443            $type[] = 'integer';
444            $unsigned = false;
445            $length = 8;
446            break;
447        case 'bool':
448        case 'boolean':
449            $type[] = 'boolean';
450            $length = null;
451            break;
452        case 'text':
453        case 'varchar':
454            $fixed = false;
455        case 'unknown':
456        case 'char':
457        case 'bpchar':
458            $type[] = 'text';
459            if ($length == '1') {
460                $type[] = 'boolean';
461                if (preg_match('/^(is|has)/', $field['name'])) {
462                    $type = array_reverse($type);
463                }
464            } elseif (strstr($db_type, 'text')) {
465                $type[] = 'clob';
466                $type = array_reverse($type);
467            }
468            if ($fixed !== false) {
469                $fixed = true;
470            }
471            break;
472        case 'date':
473            $type[] = 'date';
474            $length = null;
475            break;
476        case 'datetime':
477        case 'timestamp':
478        case 'timestamptz':
479            $type[] = 'timestamp';
480            $length = null;
481            break;
482        case 'time':
483            $type[] = 'time';
484            $length = null;
485            break;
486        case 'float':
487        case 'float4':
488        case 'float8':
489        case 'double':
490        case 'real':
491            $type[] = 'float';
492            break;
493        case 'decimal':
494        case 'money':
495        case 'numeric':
496            $type[] = 'decimal';
497            if (isset($field['scale'])) {
498                $length = $length.','.$field['scale'];
499            }
500            break;
501        case 'tinyblob':
502        case 'mediumblob':
503        case 'longblob':
504        case 'blob':
505        case 'bytea':
506            $type[] = 'blob';
507            $length = null;
508            break;
509        case 'oid':
510            $type[] = 'blob';
511            $type[] = 'clob';
512            $length = null;
513            break;
514        case 'year':
515            $type[] = 'integer';
516            $type[] = 'date';
517            $length = null;
518            break;
519        default:
520            $db = $this->getDBInstance();
521            if (MDB2::isError($db)) {
522                return $db;
523            }
524            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
525                'unknown database attribute type: '.$db_type, __FUNCTION__);
526        }
527
528        if ((int)$length <= 0) {
529            $length = null;
530        }
531
532        return array($type, $length, $unsigned, $fixed);
533    }
534
535    // }}}
536    // {{{ mapPrepareDatatype()
537
538    /**
539     * Maps an mdb2 datatype to native prepare type
540     *
541     * @param string $type
542     * @return string
543     * @access public
544     */
545    function mapPrepareDatatype($type)
546    {
547        $db = $this->getDBInstance();
548        if (MDB2::isError($db)) {
549            return $db;
550        }
551
552        if (!empty($db->options['datatype_map'][$type])) {
553            $type = $db->options['datatype_map'][$type];
554            if (!empty($db->options['datatype_map_callback'][$type])) {
555                $parameter = array('type' => $type);
556                return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
557            }
558        }
559
560        switch ($type) {
561            case 'integer':
562                return 'int';
563            case 'boolean':
564                return 'bool';
565            case 'decimal':
566            case 'float':
567                return 'numeric';
568            case 'clob':
569                return 'text';
570            case 'blob':
571                return 'bytea';
572            default:
573                break;
574        }
575        return $type;
576    }
577    // }}}
578}
579?>
Note: See TracBrowser for help on using the repository browser.