Failed Conditions
Pull Request — develop (#3367)
by Benjamin
12:53
created

SQLAnywhereConnection::query()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 6
ccs 0
cts 5
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
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 Doctrine\DBAL\ParameterType;
11
use InvalidArgumentException;
12
use function assert;
13
use function is_float;
14
use function is_int;
15
use function is_resource;
16
use function is_string;
17
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...
18
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...
19
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...
20
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...
21
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...
22
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...
23
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...
24
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...
25
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...
26
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...
27
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...
28
29
/**
30
 * SAP Sybase SQL Anywhere implementation of the Connection interface.
31
 */
32
class SQLAnywhereConnection implements Connection, ServerInfoAwareConnection
33
{
34
    /** @var resource The SQL Anywhere connection resource. */
35
    private $connection;
36
37
    /**
38
     * Connects to database with given connection string.
39
     *
40
     * @param string $dsn        The connection string.
41
     * @param bool   $persistent Whether or not to establish a persistent connection.
42
     *
43
     * @throws DriverException
44
     */
45
    public function __construct($dsn, $persistent = false)
46
    {
47
        $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

47
        $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

47
        $this->connection = $persistent ? @/** @scrutinizer ignore-call */ sasql_pconnect($dsn) : @sasql_connect($dsn);
Loading history...
48
49
        if (! is_resource($this->connection)) {
50
            throw self::exceptionFromSQLAnywhereError();
51
        }
52
53
        // Disable PHP warnings on error.
54
        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

54
        if (! /** @scrutinizer ignore-call */ sasql_set_option($this->connection, 'verbose_errors', false)) {
Loading history...
55
            throw self::exceptionFromSQLAnywhereError($this->connection);
56
        }
57
58
        // Enable auto committing by default.
59
        if (! sasql_set_option($this->connection, 'auto_commit', 'on')) {
60
            throw self::exceptionFromSQLAnywhereError($this->connection);
61
        }
62
63
        // Enable exact, non-approximated row count retrieval.
64
        if (! sasql_set_option($this->connection, 'row_counts', true)) {
65
            throw self::exceptionFromSQLAnywhereError($this->connection);
66
        }
67
    }
68
69
    /**
70
     * {@inheritdoc}
71
     */
72
    public function beginTransaction()
73
    {
74
        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

74
        if (! /** @scrutinizer ignore-call */ sasql_set_option($this->connection, 'auto_commit', 'off')) {
Loading history...
75
            throw self::exceptionFromSQLAnywhereError($this->connection);
76
        }
77
78
        return true;
79
    }
80
81
    /**
82
     * {@inheritdoc}
83
     */
84
    public function commit()
85
    {
86
        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

86
        if (! /** @scrutinizer ignore-call */ sasql_commit($this->connection)) {
Loading history...
87
            throw self::exceptionFromSQLAnywhereError($this->connection);
88
        }
89
90
        $this->endTransaction();
91
92
        return true;
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98
    public function errorCode()
99
    {
100
        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

100
        return /** @scrutinizer ignore-call */ sasql_errorcode($this->connection);
Loading history...
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function errorInfo()
107
    {
108
        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

108
        return /** @scrutinizer ignore-call */ sasql_error($this->connection);
Loading history...
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114
    public function exec(string $statement) : int
115
    {
116
        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

116
        if (/** @scrutinizer ignore-call */ sasql_real_query($this->connection, $statement) === false) {
Loading history...
117
            throw self::exceptionFromSQLAnywhereError($this->connection);
118
        }
119
120
        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

120
        return /** @scrutinizer ignore-call */ sasql_affected_rows($this->connection);
Loading history...
121
    }
122
123
    /**
124
     * {@inheritdoc}
125
     */
126
    public function getServerVersion()
127
    {
128
        $version = $this->query("SELECT PROPERTY('ProductVersion')")->fetchColumn();
129
130
        assert(is_string($version));
131
132
        return $version;
133
    }
134
135
    /**
136
     * {@inheritdoc}
137
     */
138
    public function lastInsertId($name = null)
139
    {
140
        if ($name === null) {
141
            return 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

141
            return /** @scrutinizer ignore-call */ sasql_insert_id($this->connection);
Loading history...
142
        }
143
144
        return $this->query('SELECT ' . $name . '.CURRVAL')->fetchColumn();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->query('SEL...URRVAL')->fetchColumn() also could return the type false which is incompatible with the return type mandated by Doctrine\DBAL\Driver\Connection::lastInsertId() of string.
Loading history...
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150
    public function prepare(string $sql) : DriverStatement
151
    {
152
        return new SQLAnywhereStatement($this->connection, $sql);
153
    }
154
155
    /**
156
     * {@inheritdoc}
157
     */
158
    public function query(string $sql) : ResultStatement
159
    {
160
        $stmt = $this->prepare($sql);
161
        $stmt->execute();
162
163
        return $stmt;
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     */
169
    public function quote($input, $type = ParameterType::STRING)
170
    {
171
        if (is_int($input) || is_float($input)) {
172
            return $input;
173
        }
174
175
        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

175
        return "'" . /** @scrutinizer ignore-call */ sasql_escape_string($this->connection, $input) . "'";
Loading history...
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181
    public function requiresQueryForServerVersion()
182
    {
183
        return true;
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189
    public function rollBack()
190
    {
191
        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

191
        if (! /** @scrutinizer ignore-call */ sasql_rollback($this->connection)) {
Loading history...
192
            throw self::exceptionFromSQLAnywhereError($this->connection);
193
        }
194
195
        $this->endTransaction();
196
197
        return true;
198
    }
199
200
    /**
201
     * Ends transactional mode and enables auto commit again.
202
     *
203
     * @return bool Whether or not ending transactional mode succeeded.
204
     *
205
     * @throws DriverException
206
     */
207
    private function endTransaction()
208
    {
209
        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

209
        if (! /** @scrutinizer ignore-call */ sasql_set_option($this->connection, 'auto_commit', 'on')) {
Loading history...
210
            throw self::exceptionFromSQLAnywhereError($this->connection);
211
        }
212
213
        return true;
214
    }
215
216
    /**
217
     * Helper method to turn SQL Anywhere error into exception.
218
     *
219
     * @param resource|null $conn The SQL Anywhere connection resource to retrieve the last error from.
220
     * @param resource|null $stmt The SQL Anywhere statement resource to retrieve the last error from.
221
     *
222
     * @throws InvalidArgumentException
223
     */
224
    public static function exceptionFromSQLAnywhereError($conn = null, $stmt = null) : DriverException
225
    {
226
        if ($conn !== null && ! is_resource($conn)) {
227
            throw new InvalidArgumentException('Invalid SQL Anywhere connection resource given: ' . $conn);
228
        }
229
230
        if ($stmt !== null && ! is_resource($stmt)) {
231
            throw new InvalidArgumentException('Invalid SQL Anywhere statement resource given: ' . $stmt);
232
        }
233
234
        $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

234
        $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...
235
        $code    = null;
236
        $message = null;
237
238
        /**
239
         * Try retrieving the last error from statement resource if given
240
         */
241
        if ($stmt) {
0 ignored issues
show
introduced by
$stmt is of type null|resource, thus it always evaluated to false.
Loading history...
242
            $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

242
            $code    = /** @scrutinizer ignore-call */ sasql_stmt_errno($stmt);
Loading history...
243
            $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

243
            $message = /** @scrutinizer ignore-call */ sasql_stmt_error($stmt);
Loading history...
244
        }
245
246
        /**
247
         * Try retrieving the last error from the connection resource
248
         * if either the statement resource is not given or the statement
249
         * resource is given but the last error could not be retrieved from it (fallback).
250
         * Depending on the type of error, it is sometimes necessary to retrieve
251
         * it from the connection resource even though it occurred during
252
         * a prepared statement.
253
         */
254
        if ($conn && ! $code) {
0 ignored issues
show
introduced by
$conn is of type null|resource, thus it always evaluated to false.
Loading history...
255
            $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

255
            $code    = /** @scrutinizer ignore-call */ sasql_errorcode($conn);
Loading history...
256
            $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

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