Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * This file contains the class XML_Query2XML_Driver_MDB2.
4
 *
5
 * PHP version 5
6
 *
7
 * @category  XML
8
 * @package   XML_Query2XML
9
 * @author    Lukas Feiler <lukas.feiler@lukasfeiler.com>
10
 * @copyright 2006 Lukas Feiler
11
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL Version 2.1
12
 * @version   CVS: $Id: MDB2.php 259451 2008-05-09 20:54:26Z lukasfeiler $
13
 * @link      http://pear.php.net/package/XML_Query2XML
14
 */
15
 
16
/**
17
 * XML_Query2XML_Driver_MDB2 extends XML_Query2XML_Driver.
18
 */
19
require_once 'XML/Query2XML.php';
20
 
21
/**
22
 * As the method PEAR::isError() is used within XML_Query2XML_Driver_MDB2
23
 * we require PEAR.php.
24
 */
25
require_once 'PEAR.php';
26
 
27
/**
28
 * Driver for the database abstraction layer PEAR MDB2.
29
 *
30
 * usage:
31
 * <code>
32
 * $driver = XML_Query2XML_Driver::factory(MDB2::factory(...));
33
 * </code>
34
 *
35
 * @category  XML
36
 * @package   XML_Query2XML
37
 * @author    Lukas Feiler <lukas.feiler@lukasfeiler.com>
38
 * @copyright 2006 Lukas Feiler
39
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL Version 2.1
40
 * @version   Release: 1.7.2
41
 * @link      http://pear.php.net/package/XML_Query2XML
42
 * @since     Release 1.5.0RC1
43
 */
44
class XML_Query2XML_Driver_MDB2 extends XML_Query2XML_Driver
45
{
46
    /**
47
     * In instance of a class that extends MDB2_Driver_Common.
48
     * @var MDB2_Driver_Common
49
     */
50
    private $_db = null;
51
 
52
    /**
53
     * Constructor
54
     *
55
     * @param MDB2_Driver_Common $db An instance of MDB2_Driver_Common.
56
     *
57
     * @throws XML_Query2XML_DBException If the fetch mode cannot be set to
58
     *                               MDB2_FETCHMODE_ASSOC.
59
     */
60
    public function __construct(MDB2_Driver_Common $db)
61
    {
62
        $fetchModeError = $db->setFetchMode(MDB2_FETCHMODE_ASSOC);
63
        if (PEAR::isError($fetchModeError)) {
64
            throw new XML_Query2XML_DBException(
65
                'Could not set fetch mode to DB_FETCHMODE_ASSOC: '
66
                . $fetchModeError->toString()
67
            );
68
        }
69
        $this->_db = $db;
70
    }
71
 
72
    /**
73
     * Pre-processes a query specification and returns a string representation
74
     * of the query.
75
     * This method will call parent::preprocessQuery(). Additionally it will
76
     * verify $query['limit'] and $query['offset'].
77
     *
78
     * @param mixed  &$query     A string or an array containing the element 'query'.
79
     * @param string $configPath The config path; used for exception messages.
80
     *
81
     * @return string The query statement as a string.
82
     * @throws XML_Query2XML_ConfigException If $query['limit'] or $query['offset']
83
     *                                       is set but not numeric. This exception
84
     *                                       might also bubble up from
85
     *                                       parent::preprocessQuery().
86
     */
87
    public function preprocessQuery(&$query, $configPath)
88
    {
89
        // will make $query an array if it is not already
90
        $queryString = parent::preprocessQuery($query, $configPath);
91
 
92
        foreach (array('limit', 'offset') as $sqlOption) {
93
            if (isset($query[$sqlOption])) {
94
                if (!is_numeric($query[$sqlOption])) {
95
                    /*
96
                     * unit test: getXML/
97
                     *  offsetlimit_throwConfigException_limit_not_numeric.phpt
98
                     *  offsetlimit_throwConfigException_offset_not_numeric.phpt
99
                     */
100
                    throw new XML_Query2XML_ConfigException(
101
                        $configPath . '[' . $sqlOption
102
                        . ']: integer expected, '
103
                        . gettype($query[$sqlOption]) . ' given.'
104
                    );
105
                }
106
            }
107
        }
108
        if (isset($query['limit'])) {
109
            if ($query['limit'] == 0) {
110
                // setting limit to 0 is like not setting it at all
111
                unset($query['limit']);
112
            } else {
113
                if (!isset($query['offset'])) {
114
                    // offset defaults to 0
115
                    $query['offset'] = 0;
116
                }
117
                $queryString .= '; LIMIT:' . $query['limit'];
118
                $queryString .= '; OFFSET:' . $query['offset'];
119
            }
120
        }
121
        return $queryString;
122
    }
123
 
124
    /**
125
     * Execute a SQL SELECT stement and fetch all records from the result set.
126
     *
127
     * @param mixed  $sql        The SQL query as a string or an array.
128
     * @param string $configPath The config path; used for exception messages.
129
     *
130
     * @return array An array of records.
131
     * @throws XML_Query2XML_DBException If a database related error occures.
132
     * @see XML_Query2XML_Driver::getAllRecords()
133
     */
134
    public function getAllRecords($sql, $configPath)
135
    {
136
        if (isset($sql['limit']) && $sql['limit'] < 0) {
137
            return array();
138
        }
139
        $result  =& $this->_prepareAndExecute($sql, $configPath);
140
        $records = array();
141
        while ($record = $result->fetchRow()) {
142
            if (PEAR::isError($record)) {
143
                // no unit test for this exception as it cannot be produced easily
144
                throw new XML_Query2XML_DBException(
145
                    $configPath . ': Could not fetch rows for the following '
146
                    . 'SQL query: ' . $sql['query'] . '; '
147
                    . $record->toString()
148
                );
149
            }
150
            $records[] = $record;
151
        }
152
        $result->free();
153
        return $records;
154
    }
155
 
156
    /**
157
     * Private method that will use MDB2_Driver_Common::query() for simple and
158
     * MDB2_Driver_Common::prepare() & MDB2_Statement_Common::execute() for complex
159
     * query specifications.
160
     *
161
     * @param mixed  $sql        A string or an array.
162
     * @param string $configPath The config path used for exception messages.
163
     *
164
     * @return MDB2_Result
165
     * @throws XML_Query2XML_DBException If a database related error occures.
166
     */
167
    private function _prepareAndExecute($sql, $configPath)
168
    {
169
        $preparedQuery = $sql['query'];
170
        if (isset($sql['limit'])) {
171
            $preparedQuery .= '; LIMIT:' . $sql['limit'];
172
            $preparedQuery .= '; OFFSET:' . $sql['offset'];
173
            $this->_db->setLimit($sql['limit'], $sql['offset']);
174
        }
175
 
176
        if (isset($this->_preparedQueries[$preparedQuery])) {
177
            $queryHandle = $this->_preparedQueries[$preparedQuery];
178
        } else {
179
            // PREPARE
180
            $queryHandle = $this->_db->prepare($sql['query']);
181
 
182
            if (PEAR::isError($queryHandle)) {
183
                /*
184
                 * unit tests: (only if mysql or pgsql is used)
185
                 *  MDB2/_prepareAndExecute/throwDBException_complexQuery.phpt
186
                 */
187
                throw new XML_Query2XML_DBException(
188
                    $configPath . ': Could not prepare the following SQL query: '
189
                    . $sql['query'] . '; ' . $queryHandle->toString()
190
                );
191
            }
192
            $this->_preparedQueries[$preparedQuery] =& $queryHandle;
193
        }
194
 
195
        // EXECUTE
196
        if (isset($sql['data'])) {
197
            $result = $queryHandle->execute($sql['data']);
198
        } else {
199
            $result = $queryHandle->execute();
200
        }
201
 
202
        if (PEAR::isError($result)) {
203
            /*
204
             * unit tests:
205
             *  if sqlite is used: MDB2/_prepareAndExecute/
206
             *   throwDBException_complexQuery.phpt
207
             *  if sqlite or mysql is sued: MDB2/getXML/
208
             *   throwDBException_nullResultSet_complexQuery_multipleRecords.phpt
209
             *   throwDBException_nullResultSet_complexQuery_singleRecord.phpt
210
             */
211
            throw new XML_Query2XML_DBException(
212
                $configPath . ': Could not execute the following SQL query: '
213
                . $sql['query'] . '; ' . $result->toString()
214
            );
215
        }
216
        return $result;
217
    }
218
}
219
?>