Failed Conditions
Pull Request — develop (#3367)
by Benjamin
14:32
created

SQLAnywhereConnection::exec()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
ccs 0
cts 6
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
namespace Doctrine\DBAL\Driver\SQLAnywhere;
4
5
use Doctrine\DBAL\Driver\Connection;
6
use Doctrine\DBAL\Driver\DriverException;
7
use Doctrine\DBAL\Driver\ResultStatement;
8
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
9
use Doctrine\DBAL\Driver\Statement as DriverStatement;
10
use InvalidArgumentException;
11
use function assert;
12
use function is_resource;
13
use function is_string;
14
use function sasql_affected_rows;
0 ignored issues
show
introduced by
The function sasql_affected_rows was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
15
use function sasql_commit;
0 ignored issues
show
introduced by
The function sasql_commit was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
16
use function sasql_connect;
0 ignored issues
show
introduced by
The function sasql_connect was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
17
use function sasql_error;
0 ignored issues
show
introduced by
The function sasql_error was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
18
use function sasql_errorcode;
0 ignored issues
show
introduced by
The function sasql_errorcode was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
19
use function sasql_escape_string;
0 ignored issues
show
introduced by
The function sasql_escape_string was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
20
use function sasql_insert_id;
0 ignored issues
show
introduced by
The function sasql_insert_id was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
21
use function sasql_pconnect;
0 ignored issues
show
introduced by
The function sasql_pconnect was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
22
use function sasql_real_query;
0 ignored issues
show
introduced by
The function sasql_real_query was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
23
use function sasql_rollback;
0 ignored issues
show
introduced by
The function sasql_rollback was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
24
use function sasql_set_option;
0 ignored issues
show
introduced by
The function sasql_set_option was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
25
26
/**
27
 * SAP Sybase SQL Anywhere implementation of the Connection interface.
28
 */
29
class SQLAnywhereConnection implements Connection, ServerInfoAwareConnection
30
{
31
    /** @var resource The SQL Anywhere connection resource. */
32
    private $connection;
33
34
    /**
35
     * Connects to database with given connection string.
36
     *
37
     * @param string $dsn        The connection string.
38
     * @param bool   $persistent Whether or not to establish a persistent connection.
39
     *
40
     * @throws DriverException
41
     */
42
    public function __construct($dsn, $persistent = false)
43
    {
44
        $this->connection = $persistent ? @sasql_pconnect($dsn) : @sasql_connect($dsn);
0 ignored issues
show
Bug introduced by
The function sasql_connect was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

44
        $this->connection = $persistent ? @sasql_pconnect($dsn) : @/** @scrutinizer ignore-call */ sasql_connect($dsn);
Loading history...
Bug introduced by
The function sasql_pconnect was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

44
        $this->connection = $persistent ? @/** @scrutinizer ignore-call */ sasql_pconnect($dsn) : @sasql_connect($dsn);
Loading history...
45
46
        if (! is_resource($this->connection)) {
47
            throw self::exceptionFromSQLAnywhereError();
48
        }
49
50
        // Disable PHP warnings on error.
51
        if (! sasql_set_option($this->connection, 'verbose_errors', false)) {
0 ignored issues
show
Bug introduced by
The function sasql_set_option was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

51
        if (! /** @scrutinizer ignore-call */ sasql_set_option($this->connection, 'verbose_errors', false)) {
Loading history...
52
            throw self::exceptionFromSQLAnywhereError($this->connection);
53
        }
54
55
        // Enable auto committing by default.
56
        if (! sasql_set_option($this->connection, 'auto_commit', 'on')) {
57
            throw self::exceptionFromSQLAnywhereError($this->connection);
58
        }
59
60
        // Enable exact, non-approximated row count retrieval.
61
        if (! sasql_set_option($this->connection, 'row_counts', true)) {
62
            throw self::exceptionFromSQLAnywhereError($this->connection);
63
        }
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69
    public function beginTransaction() : void
70
    {
71
        if (! sasql_set_option($this->connection, 'auto_commit', 'off')) {
0 ignored issues
show
Bug introduced by
The function sasql_set_option was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

71
        if (! /** @scrutinizer ignore-call */ sasql_set_option($this->connection, 'auto_commit', 'off')) {
Loading history...
72
            throw self::exceptionFromSQLAnywhereError($this->connection);
73
        }
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function commit() : void
80
    {
81
        if (! sasql_commit($this->connection)) {
0 ignored issues
show
Bug introduced by
The function sasql_commit was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

81
        if (! /** @scrutinizer ignore-call */ sasql_commit($this->connection)) {
Loading history...
82
            throw self::exceptionFromSQLAnywhereError($this->connection);
83
        }
84
85
        $this->endTransaction();
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91
    public function errorCode()
92
    {
93
        return sasql_errorcode($this->connection);
0 ignored issues
show
Bug introduced by
The function sasql_errorcode was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

93
        return /** @scrutinizer ignore-call */ sasql_errorcode($this->connection);
Loading history...
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99
    public function errorInfo()
100
    {
101
        return sasql_error($this->connection);
0 ignored issues
show
Bug introduced by
The function sasql_error was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

101
        return /** @scrutinizer ignore-call */ sasql_error($this->connection);
Loading history...
102
    }
103
104
    /**
105
     * {@inheritdoc}
106
     */
107
    public function exec(string $statement) : int
108
    {
109
        if (sasql_real_query($this->connection, $statement) === false) {
0 ignored issues
show
Bug introduced by
The function sasql_real_query was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

109
        if (/** @scrutinizer ignore-call */ sasql_real_query($this->connection, $statement) === false) {
Loading history...
110
            throw self::exceptionFromSQLAnywhereError($this->connection);
111
        }
112
113
        return sasql_affected_rows($this->connection);
0 ignored issues
show
Bug introduced by
The function sasql_affected_rows was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

113
        return /** @scrutinizer ignore-call */ sasql_affected_rows($this->connection);
Loading history...
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119
    public function getServerVersion()
120
    {
121
        $version = $this->query("SELECT PROPERTY('ProductVersion')")->fetchColumn();
122
123
        assert(is_string($version));
124
125
        return $version;
126
    }
127
128
    /**
129
     * {@inheritdoc}
130
     */
131
    public function lastInsertId(?string $name = null) : string
132
    {
133
        if ($name === null) {
134
            $result = sasql_insert_id($this->connection);
0 ignored issues
show
Bug introduced by
The function sasql_insert_id was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

134
            $result = /** @scrutinizer ignore-call */ sasql_insert_id($this->connection);
Loading history...
135
136
            if ($result === false) {
137
                throw self::exceptionFromSQLAnywhereError($this->connection);
138
            }
139
140
            if ($result === 0) {
141
                throw DriverException::noInsertId();
142
            }
143
144
            return (string) $result;
145
        }
146
147
        $result = $this->query('SELECT ' . $name . '.CURRVAL')->fetchColumn();
148
149
        if ($result === false) {
150
            throw DriverException::noSuchSequence($name);
151
        }
152
153
        return (string) $result;
154
    }
155
156
    /**
157
     * {@inheritdoc}
158
     */
159
    public function prepare(string $sql) : DriverStatement
160
    {
161
        return new SQLAnywhereStatement($this->connection, $sql);
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167
    public function query(string $sql) : ResultStatement
168
    {
169
        $stmt = $this->prepare($sql);
170
        $stmt->execute();
171
172
        return $stmt;
173
    }
174
175
    /**
176
     * {@inheritdoc}
177
     */
178
    public function quote(string $input) : string
179
    {
180
        return "'" . sasql_escape_string($this->connection, $input) . "'";
0 ignored issues
show
Bug introduced by
The function sasql_escape_string was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

180
        return "'" . /** @scrutinizer ignore-call */ sasql_escape_string($this->connection, $input) . "'";
Loading history...
181
    }
182
183
    /**
184
     * {@inheritdoc}
185
     */
186
    public function requiresQueryForServerVersion()
187
    {
188
        return true;
189
    }
190
191
    /**
192
     * {@inheritdoc}
193
     */
194
    public function rollBack() : void
195
    {
196
        if (! sasql_rollback($this->connection)) {
0 ignored issues
show
Bug introduced by
The function sasql_rollback was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

196
        if (! /** @scrutinizer ignore-call */ sasql_rollback($this->connection)) {
Loading history...
197
            throw self::exceptionFromSQLAnywhereError($this->connection);
198
        }
199
200
        $this->endTransaction();
201
    }
202
203
    /**
204
     * Ends transactional mode and enables auto commit again.
205
     *
206
     * @return bool Whether or not ending transactional mode succeeded.
207
     *
208
     * @throws DriverException
209
     */
210
    private function endTransaction()
211
    {
212
        if (! sasql_set_option($this->connection, 'auto_commit', 'on')) {
0 ignored issues
show
Bug introduced by
The function sasql_set_option was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

212
        if (! /** @scrutinizer ignore-call */ sasql_set_option($this->connection, 'auto_commit', 'on')) {
Loading history...
213
            throw self::exceptionFromSQLAnywhereError($this->connection);
214
        }
215
216
        return true;
217
    }
218
219
    /**
220
     * Helper method to turn SQL Anywhere error into exception.
221
     *
222
     * @param resource|null $conn The SQL Anywhere connection resource to retrieve the last error from.
223
     * @param resource|null $stmt The SQL Anywhere statement resource to retrieve the last error from.
224
     *
225
     * @return DriverException
226
     *
227
     * @throws InvalidArgumentException
228
     */
229
    public static function exceptionFromSQLAnywhereError($conn = null, $stmt = null) : DriverException
230
    {
231
        if ($conn !== null && ! is_resource($conn)) {
232
            throw new InvalidArgumentException('Invalid SQL Anywhere connection resource given: ' . $conn);
233
        }
234
235
        if ($stmt !== null && ! is_resource($stmt)) {
236
            throw new InvalidArgumentException('Invalid SQL Anywhere statement resource given: ' . $stmt);
237
        }
238
239
        $state   = $conn ? sasql_sqlstate($conn) : sasql_sqlstate();
0 ignored issues
show
Bug introduced by
The function sasql_sqlstate was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

239
        $state   = $conn ? /** @scrutinizer ignore-call */ sasql_sqlstate($conn) : sasql_sqlstate();
Loading history...
introduced by
$conn is of type null|resource, thus it always evaluated to false.
Loading history...
240
        $code    = null;
241
        $message = null;
242
243
        /**
244
         * Try retrieving the last error from statement resource if given
245
         */
246
        if ($stmt) {
0 ignored issues
show
introduced by
$stmt is of type null|resource, thus it always evaluated to false.
Loading history...
247
            $code    = sasql_stmt_errno($stmt);
0 ignored issues
show
Bug introduced by
The function sasql_stmt_errno was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

247
            $code    = /** @scrutinizer ignore-call */ sasql_stmt_errno($stmt);
Loading history...
248
            $message = sasql_stmt_error($stmt);
0 ignored issues
show
Bug introduced by
The function sasql_stmt_error was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

248
            $message = /** @scrutinizer ignore-call */ sasql_stmt_error($stmt);
Loading history...
249
        }
250
251
        /**
252
         * Try retrieving the last error from the connection resource
253
         * if either the statement resource is not given or the statement
254
         * resource is given but the last error could not be retrieved from it (fallback).
255
         * Depending on the type of error, it is sometimes necessary to retrieve
256
         * it from the connection resource even though it occurred during
257
         * a prepared statement.
258
         */
259
        if ($conn && ! $code) {
0 ignored issues
show
introduced by
$conn is of type null|resource, thus it always evaluated to false.
Loading history...
260
            $code    = sasql_errorcode($conn);
0 ignored issues
show
Bug introduced by
The function sasql_errorcode was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

260
            $code    = /** @scrutinizer ignore-call */ sasql_errorcode($conn);
Loading history...
261
            $message = sasql_error($conn);
0 ignored issues
show
Bug introduced by
The function sasql_error was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

261
            $message = /** @scrutinizer ignore-call */ sasql_error($conn);
Loading history...
262
        }
263
264
        /**
265
         * Fallback mode if either no connection resource is given
266
         * or the last error could not be retrieved from the given
267
         * connection / statement resource.
268
         */
269
        if (! $conn || ! $code) {
0 ignored issues
show
introduced by
$conn is of type null|resource, thus it always evaluated to false.
Loading history...
270
            $code    = sasql_errorcode();
271
            $message = sasql_error();
272
        }
273
274
        if ($message) {
275
            return new DriverException('SQLSTATE [' . $state . '] [' . $code . '] ' . $message, $state, $code);
276
        }
277
278
        return new DriverException('SQL Anywhere error occurred but no error message was retrieved from driver.', $state, $code);
279
    }
280
}
281