OCI8Connection.php 6.18 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
Benjamin Eberlei's avatar
Benjamin Eberlei committed
16
 * and is licensed under the MIT license. For more information, see
17 18 19 20 21
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\DBAL\Driver\OCI8;

Steve Müller's avatar
Steve Müller committed
22
use Doctrine\DBAL\Driver\Connection;
23
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
24
use Doctrine\DBAL\ParameterType;
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
use const OCI_COMMIT_ON_SUCCESS;
use const OCI_DEFAULT;
use const OCI_NO_AUTO_COMMIT;
use function addcslashes;
use function define;
use function defined;
use function func_get_args;
use function is_float;
use function is_int;
use function oci_commit;
use function oci_connect;
use function oci_error;
use function oci_pconnect;
use function oci_rollback;
use function oci_server_version;
use function preg_match;
use function sprintf;
use function str_replace;
43

44 45 46 47 48
/**
 * OCI8 implementation of the Connection interface.
 *
 * @since 2.0
 */
49
class OCI8Connection implements Connection, ServerInfoAwareConnection
50
{
51 52 53 54
    /**
     * @var resource
     */
    protected $dbh;
55

56
    /**
57
     * @var int
58
     */
59
    protected $executeMode = OCI_COMMIT_ON_SUCCESS;
60

61
    /**
Benjamin Morel's avatar
Benjamin Morel committed
62
     * Creates a Connection to an Oracle Database using oci8 extension.
63
     *
Benjamin Morel's avatar
Benjamin Morel committed
64 65 66 67
     * @param string      $username
     * @param string      $password
     * @param string      $db
     * @param string|null $charset
68 69
     * @param int         $sessionMode
     * @param bool        $persistent
Benjamin Morel's avatar
Benjamin Morel committed
70 71
     *
     * @throws OCI8Exception
72
     */
73
    public function __construct($username, $password, $db, $charset = null, $sessionMode = OCI_DEFAULT, $persistent = false)
74
    {
75 76 77 78
        if (!defined('OCI_NO_AUTO_COMMIT')) {
            define('OCI_NO_AUTO_COMMIT', 0);
        }

79
        $this->dbh = $persistent
80 81
            ? @oci_pconnect($username, $password, $db, $charset, $sessionMode)
            : @oci_connect($username, $password, $db, $charset, $sessionMode);
82

83
        if ( ! $this->dbh) {
84
            throw OCI8Exception::fromErrorInfo(oci_error());
85
        }
86
    }
87

88 89
    /**
     * {@inheritdoc}
90 91 92
     *
     * @throws \UnexpectedValueException if the version string returned by the database server
     *                                   does not contain a parsable version number.
93 94 95 96
     */
    public function getServerVersion()
    {
        if ( ! preg_match('/\s+(\d+\.\d+\.\d+\.\d+\.\d+)\s+/', oci_server_version($this->dbh), $version)) {
97 98 99 100 101 102 103
            throw new \UnexpectedValueException(
                sprintf(
                    'Unexpected database version string "%s". Cannot parse an appropriate version number from it. ' .
                    'Please report this database version string to the Doctrine team.',
                    oci_server_version($this->dbh)
                )
            );
104 105 106 107 108 109 110 111 112 113 114 115 116
        }

        return $version[1];
    }

    /**
     * {@inheritdoc}
     */
    public function requiresQueryForServerVersion()
    {
        return false;
    }

117
    /**
Benjamin Morel's avatar
Benjamin Morel committed
118
     * {@inheritdoc}
119
     */
120 121
    public function prepare($prepareString)
    {
122
        return new OCI8Statement($this->dbh, $prepareString, $this);
123
    }
124 125

    /**
Benjamin Morel's avatar
Benjamin Morel committed
126
     * {@inheritdoc}
127
     */
128 129 130 131 132 133 134
    public function query()
    {
        $args = func_get_args();
        $sql = $args[0];
        //$fetchMode = $args[1];
        $stmt = $this->prepare($sql);
        $stmt->execute();
Benjamin Morel's avatar
Benjamin Morel committed
135

136 137
        return $stmt;
    }
138 139

    /**
Benjamin Morel's avatar
Benjamin Morel committed
140
     * {@inheritdoc}
141
     */
142
    public function quote($value, $type = ParameterType::STRING)
143
    {
144 145 146 147
        if (is_int($value) || is_float($value)) {
            return $value;
        }
        $value = str_replace("'", "''", $value);
Benjamin Morel's avatar
Benjamin Morel committed
148

149
        return "'" . addcslashes($value, "\000\n\r\\\032") . "'";
150
    }
151 152

    /**
Benjamin Morel's avatar
Benjamin Morel committed
153
     * {@inheritdoc}
154
     */
155 156 157 158
    public function exec($statement)
    {
        $stmt = $this->prepare($statement);
        $stmt->execute();
Benjamin Morel's avatar
Benjamin Morel committed
159

160 161
        return $stmt->rowCount();
    }
162

163
    /**
Benjamin Morel's avatar
Benjamin Morel committed
164
     * {@inheritdoc}
165
     */
166 167
    public function lastInsertId($name = null)
    {
168 169 170 171 172 173
        if ($name === null) {
            return false;
        }

        $sql    = 'SELECT ' . $name . '.CURRVAL FROM DUAL';
        $stmt   = $this->query($sql);
174
        $result = $stmt->fetchColumn();
175

176
        if ($result === false) {
177 178 179
            throw new OCI8Exception("lastInsertId failed: Query was executed but no result was returned.");
        }

180
        return (int) $result;
181
    }
182

183
    /**
Benjamin Morel's avatar
Benjamin Morel committed
184 185
     * Returns the current execution mode.
     *
186
     * @return int
187 188 189
     */
    public function getExecuteMode()
    {
190
        return $this->executeMode;
191 192
    }

193
    /**
Benjamin Morel's avatar
Benjamin Morel committed
194
     * {@inheritdoc}
195
     */
196 197
    public function beginTransaction()
    {
198
        $this->executeMode = OCI_NO_AUTO_COMMIT;
Benjamin Morel's avatar
Benjamin Morel committed
199

200 201
        return true;
    }
202 203

    /**
Benjamin Morel's avatar
Benjamin Morel committed
204
     * {@inheritdoc}
205
     */
206 207
    public function commit()
    {
208
        if (!oci_commit($this->dbh)) {
209 210
            throw OCI8Exception::fromErrorInfo($this->errorInfo());
        }
211
        $this->executeMode = OCI_COMMIT_ON_SUCCESS;
Benjamin Morel's avatar
Benjamin Morel committed
212

213
        return true;
214
    }
215 216

    /**
Benjamin Morel's avatar
Benjamin Morel committed
217
     * {@inheritdoc}
218
     */
219 220
    public function rollBack()
    {
221
        if (!oci_rollback($this->dbh)) {
222 223
            throw OCI8Exception::fromErrorInfo($this->errorInfo());
        }
224
        $this->executeMode = OCI_COMMIT_ON_SUCCESS;
Benjamin Morel's avatar
Benjamin Morel committed
225

226
        return true;
227
    }
228

Benjamin Morel's avatar
Benjamin Morel committed
229 230 231
    /**
     * {@inheritdoc}
     */
232 233
    public function errorCode()
    {
234
        $error = oci_error($this->dbh);
235 236 237
        if ($error !== false) {
            $error = $error['code'];
        }
Benjamin Morel's avatar
Benjamin Morel committed
238

239 240
        return $error;
    }
241

Benjamin Morel's avatar
Benjamin Morel committed
242 243 244
    /**
     * {@inheritdoc}
     */
245 246
    public function errorInfo()
    {
247
        return oci_error($this->dbh);
248
    }
249
}