Completed
Branch master (aa12c6)
by Eugene
01:39
created

Client::execute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
crap 1
1
<?php
2
3
/**
4
 * This file is part of the Tarantool Client package.
5
 *
6
 * (c) Eugene Leonovich <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Tarantool\Client;
15
16
use Tarantool\Client\Connection\StreamConnection;
17
use Tarantool\Client\Exception\RequestFailed;
18
use Tarantool\Client\Handler\DefaultHandler;
19
use Tarantool\Client\Handler\Handler;
20
use Tarantool\Client\Handler\MiddlewareHandler;
21
use Tarantool\Client\Middleware\AuthenticationMiddleware;
22
use Tarantool\Client\Middleware\Middleware;
23
use Tarantool\Client\Middleware\RetryMiddleware;
24
use Tarantool\Client\Packer\PackerFactory;
25
use Tarantool\Client\Request\CallRequest;
26
use Tarantool\Client\Request\EvaluateRequest;
27
use Tarantool\Client\Request\ExecuteRequest;
28
use Tarantool\Client\Request\PingRequest;
29
use Tarantool\Client\Schema\Criteria;
30
use Tarantool\Client\Schema\Space;
31
32
final class Client
33
{
34
    /** @var Handler */
35
    private $handler;
36
37
    /** @var array<array-key, Space> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, Space> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, Space>.
Loading history...
38
    private $spaces = [];
39
40 495
    public function __construct(Handler $handler)
41
    {
42 495
        $this->handler = $handler;
43 495
    }
44
45
    public static function fromDefaults() : self
46
    {
47
        return new self(new DefaultHandler(
48
            StreamConnection::createTcp(),
49
            PackerFactory::create()
50
        ));
51
    }
52
53 3
    public static function fromOptions(array $options) : self
54
    {
55 3
        $connectionOptions = [];
56 3
        if (isset($options['connect_timeout'])) {
57
            $connectionOptions['connect_timeout'] = $options['connect_timeout'];
58
        }
59 3
        if (isset($options['socket_timeout'])) {
60
            $connectionOptions['socket_timeout'] = $options['socket_timeout'];
61
        }
62 3
        if (isset($options['tcp_nodelay'])) {
63
            $connectionOptions['tcp_nodelay'] = $options['tcp_nodelay'];
64
        }
65 3
        if (isset($options['persistent'])) {
66
            $connectionOptions['persistent'] = $options['persistent'];
67
        }
68
69 3
        $connection = StreamConnection::create($options['uri'] ?? StreamConnection::DEFAULT_URI, $connectionOptions);
70 3
        $handler = new DefaultHandler($connection, PackerFactory::create());
71
72 3
        if (isset($options['max_retries']) && 0 !== $options['max_retries']) {
73 3
            $handler = MiddlewareHandler::create($handler, RetryMiddleware::linear($options['max_retries']));
74
        }
75 3
        if (isset($options['username'])) {
76 3
            $handler = MiddlewareHandler::create($handler, new AuthenticationMiddleware($options['username'], $options['password'] ?? ''));
77
        }
78
79 3
        return new self($handler);
80
    }
81
82
    public static function fromDsn(string $dsn) : self
83
    {
84
        $dsn = Dsn::parse($dsn);
85
86
        $connectionOptions = [];
87
        if (null !== $timeout = $dsn->getInt('connect_timeout')) {
88
            $connectionOptions['connect_timeout'] = $timeout;
89
        }
90
        if (null !== $timeout = $dsn->getInt('socket_timeout')) {
91
            $connectionOptions['socket_timeout'] = $timeout;
92
        }
93
        if (null !== $tcpNoDelay = $dsn->getBool('tcp_nodelay')) {
94
            $connectionOptions['tcp_nodelay'] = $tcpNoDelay;
95
        }
96
        if (null !== $persistent = $dsn->getBool('persistent')) {
97
            $connectionOptions['persistent'] = $persistent;
98
        }
99
100
        $connection = $dsn->isTcp()
101
            ? StreamConnection::createTcp($dsn->getConnectionUri(), $connectionOptions)
102
            : StreamConnection::createUds($dsn->getConnectionUri(), $connectionOptions);
103
104
        $handler = new DefaultHandler($connection, PackerFactory::create());
105
106
        if ($maxRetries = $dsn->getInt('max_retries')) {
107
            $handler = MiddlewareHandler::create($handler, RetryMiddleware::linear($maxRetries));
108
        }
109
        if ($username = $dsn->getUsername()) {
110
            $handler = MiddlewareHandler::create($handler, new AuthenticationMiddleware($username, $dsn->getPassword() ?? ''));
111
        }
112
113
        return new self($handler);
114
    }
115
116 6
    public function withMiddleware(Middleware $middleware, Middleware ...$middlewares) : self
117
    {
118 6
        $new = clone $this;
119 6
        $new->handler = MiddlewareHandler::create($new->handler, $middleware, ...$middlewares);
120
121 6
        return $new;
122
    }
123
124 51
    public function getHandler() : Handler
125
    {
126 51
        return $this->handler;
127
    }
128
129 173
    public function getSpace(string $spaceName) : Space
130
    {
131 173
        if (isset($this->spaces[$spaceName])) {
132 3
            return $this->spaces[$spaceName];
133
        }
134
135 173
        $spaceId = $this->getSpaceIdByName($spaceName);
136
137 167
        return $this->spaces[$spaceName] = $this->spaces[$spaceId] = new Space($this->handler, $spaceId);
138
    }
139
140 185
    public function getSpaceById(int $spaceId) : Space
141
    {
142 185
        if (isset($this->spaces[$spaceId])) {
143
            return $this->spaces[$spaceId];
144
        }
145
146 185
        return $this->spaces[$spaceId] = new Space($this->handler, $spaceId);
147
    }
148
149 97
    public function ping() : void
150
    {
151 97
        $this->handler->handle(new PingRequest());
152 16
    }
153
154
    /**
155
     * @param mixed ...$args
156
     */
157 6
    public function call(string $funcName, ...$args) : array
158
    {
159 6
        return $this->handler->handle(new CallRequest($funcName, $args))
160 6
            ->getBodyField(Keys::DATA);
161
    }
162
163
    /**
164
     * @param mixed ...$args
165
     */
166 239
    public function evaluate(string $expr, ...$args) : array
167
    {
168 239
        return $this->handler->handle(new EvaluateRequest($expr, $args))
169 230
            ->getBodyField(Keys::DATA);
170
    }
171
172
    /**
173
     * @param mixed ...$params
174
     */
175 6
    public function execute(string $sql, ...$params) : Response
176
    {
177 6
        return $this->handler->handle(new ExecuteRequest($sql, $params));
178
    }
179
180
    /**
181
     * @param mixed ...$params
182
     */
183 21
    public function executeQuery(string $sql, ...$params) : SqlQueryResult
184
    {
185 21
        $response = $this->handler->handle(new ExecuteRequest($sql, $params));
186
187 21
        return new SqlQueryResult(
188 21
            $response->getBodyField(Keys::DATA),
189 21
            $response->getBodyField(Keys::METADATA)
190
        );
191
    }
192
193
    /**
194
     * @param mixed ...$params
195
     */
196 9
    public function executeUpdate(string $sql, ...$params) : SqlUpdateResult
197
    {
198 9
        $response = $this->handler->handle(new ExecuteRequest($sql, $params));
199
200 9
        return new SqlUpdateResult($response->getBodyField(Keys::SQL_INFO));
201
    }
202
203 6
    public function flushSpaces() : void
204
    {
205 6
        $this->spaces = [];
206 6
    }
207
208 6
    public function __clone()
209
    {
210 6
        $this->spaces = [];
211 6
    }
212
213 173
    private function getSpaceIdByName(string $spaceName) : int
214
    {
215 173
        $schema = $this->getSpaceById(Space::VSPACE_ID);
216 173
        $data = $schema->select(Criteria::key([$spaceName])->andIndex(Space::VSPACE_NAME_INDEX));
217
218 173
        if ($data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
219 167
            return $data[0][0];
220
        }
221
222 6
        throw RequestFailed::unknownSpace($spaceName);
223
    }
224
}
225