OCI8Connection.php 5.32 KB
Newer Older
1 2 3 4
<?php

namespace Doctrine\DBAL\Driver\OCI8;

Steve Müller's avatar
Steve Müller committed
5
use Doctrine\DBAL\Driver\Connection;
6
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
7
use Doctrine\DBAL\ParameterType;
8
use UnexpectedValueException;
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
use const OCI_COMMIT_ON_SUCCESS;
use const OCI_DEFAULT;
use const OCI_NO_AUTO_COMMIT;
use function addcslashes;
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;
25

26 27 28
/**
 * OCI8 implementation of the Connection interface.
 */
29
class OCI8Connection implements Connection, ServerInfoAwareConnection
30
{
31
    /** @var resource */
32
    protected $dbh;
33

34
    /** @var int */
35
    protected $executeMode = OCI_COMMIT_ON_SUCCESS;
36

37
    /**
Benjamin Morel's avatar
Benjamin Morel committed
38
     * Creates a Connection to an Oracle Database using oci8 extension.
39
     *
Sergei Morozov's avatar
Sergei Morozov committed
40 41 42 43 44 45
     * @param string $username
     * @param string $password
     * @param string $db
     * @param string $charset
     * @param int    $sessionMode
     * @param bool   $persistent
Benjamin Morel's avatar
Benjamin Morel committed
46 47
     *
     * @throws OCI8Exception
48
     */
Sergei Morozov's avatar
Sergei Morozov committed
49 50 51 52 53 54 55 56
    public function __construct(
        $username,
        $password,
        $db,
        $charset = '',
        $sessionMode = OCI_DEFAULT,
        $persistent = false
    ) {
Sergei Morozov's avatar
Sergei Morozov committed
57
        $dbh = $persistent
58 59
            ? @oci_pconnect($username, $password, $db, $charset, $sessionMode)
            : @oci_connect($username, $password, $db, $charset, $sessionMode);
60

Sergei Morozov's avatar
Sergei Morozov committed
61
        if ($dbh === false) {
62
            throw OCI8Exception::fromErrorInfo(oci_error());
63
        }
Sergei Morozov's avatar
Sergei Morozov committed
64 65

        $this->dbh = $dbh;
66
    }
67

68 69
    /**
     * {@inheritdoc}
70
     *
71 72
     * @throws UnexpectedValueException If the version string returned by the database server
     *                                  does not contain a parsable version number.
73 74 75
     */
    public function getServerVersion()
    {
Sergei Morozov's avatar
Sergei Morozov committed
76 77 78 79 80 81 82
        $version = oci_server_version($this->dbh);

        if ($version === false) {
            throw OCI8Exception::fromErrorInfo(oci_error($this->dbh));
        }

        if (! preg_match('/\s+(\d+\.\d+\.\d+\.\d+\.\d+)\s+/', $version, $matches)) {
83
            throw new UnexpectedValueException(
84 85 86
                sprintf(
                    'Unexpected database version string "%s". Cannot parse an appropriate version number from it. ' .
                    'Please report this database version string to the Doctrine team.',
Sergei Morozov's avatar
Sergei Morozov committed
87
                    $version
88 89
                )
            );
90 91
        }

Sergei Morozov's avatar
Sergei Morozov committed
92
        return $matches[1];
93 94 95 96 97 98 99 100 101 102
    }

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

103
    /**
Benjamin Morel's avatar
Benjamin Morel committed
104
     * {@inheritdoc}
105
     */
106 107
    public function prepare($prepareString)
    {
108
        return new OCI8Statement($this->dbh, $prepareString, $this);
109
    }
110 111

    /**
Benjamin Morel's avatar
Benjamin Morel committed
112
     * {@inheritdoc}
113
     */
114 115 116
    public function query()
    {
        $args = func_get_args();
117
        $sql  = $args[0];
118 119 120
        //$fetchMode = $args[1];
        $stmt = $this->prepare($sql);
        $stmt->execute();
Benjamin Morel's avatar
Benjamin Morel committed
121

122 123
        return $stmt;
    }
124 125

    /**
Benjamin Morel's avatar
Benjamin Morel committed
126
     * {@inheritdoc}
127
     */
128
    public function quote($value, $type = ParameterType::STRING)
129
    {
130 131 132 133
        if (is_int($value) || is_float($value)) {
            return $value;
        }
        $value = str_replace("'", "''", $value);
Benjamin Morel's avatar
Benjamin Morel committed
134

135
        return "'" . addcslashes($value, "\000\n\r\\\032") . "'";
136
    }
137 138

    /**
Benjamin Morel's avatar
Benjamin Morel committed
139
     * {@inheritdoc}
140
     */
141 142 143 144
    public function exec($statement)
    {
        $stmt = $this->prepare($statement);
        $stmt->execute();
Benjamin Morel's avatar
Benjamin Morel committed
145

146 147
        return $stmt->rowCount();
    }
148

149
    /**
Benjamin Morel's avatar
Benjamin Morel committed
150
     * {@inheritdoc}
151
     */
152 153
    public function lastInsertId($name = null)
    {
154 155 156 157 158 159
        if ($name === null) {
            return false;
        }

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

162
        if ($result === false) {
163
            throw new OCI8Exception('lastInsertId failed: Query was executed but no result was returned.');
164 165
        }

166
        return (int) $result;
167
    }
168

169
    /**
Benjamin Morel's avatar
Benjamin Morel committed
170 171
     * Returns the current execution mode.
     *
172
     * @return int
173 174 175
     */
    public function getExecuteMode()
    {
176
        return $this->executeMode;
177 178
    }

179
    /**
Benjamin Morel's avatar
Benjamin Morel committed
180
     * {@inheritdoc}
181
     */
182 183
    public function beginTransaction()
    {
184
        $this->executeMode = OCI_NO_AUTO_COMMIT;
Benjamin Morel's avatar
Benjamin Morel committed
185

186 187
        return true;
    }
188 189

    /**
Benjamin Morel's avatar
Benjamin Morel committed
190
     * {@inheritdoc}
191
     */
192 193
    public function commit()
    {
194
        if (! oci_commit($this->dbh)) {
195 196
            throw OCI8Exception::fromErrorInfo($this->errorInfo());
        }
197
        $this->executeMode = OCI_COMMIT_ON_SUCCESS;
Benjamin Morel's avatar
Benjamin Morel committed
198

199
        return true;
200
    }
201 202

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

212
        return true;
213
    }
214

Benjamin Morel's avatar
Benjamin Morel committed
215 216 217
    /**
     * {@inheritdoc}
     */
218 219
    public function errorCode()
    {
220
        $error = oci_error($this->dbh);
221 222 223
        if ($error !== false) {
            $error = $error['code'];
        }
Benjamin Morel's avatar
Benjamin Morel committed
224

225 226
        return $error;
    }
227

Benjamin Morel's avatar
Benjamin Morel committed
228 229 230
    /**
     * {@inheritdoc}
     */
231 232
    public function errorInfo()
    {
Sergei Morozov's avatar
Sergei Morozov committed
233 234 235 236 237 238 239
        $error = oci_error($this->dbh);

        if ($error === false) {
            return [];
        }

        return $error;
240
    }
241
}