Passed
Pull Request — master (#84)
by
unknown
07:53
created

testExecuteQueryBindsMixedParameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 6
rs 10
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\Tests\Integration\Requests;
15
require __DIR__.'/../../../examples/bootstrap.php';
16
17
use Tarantool\Client\Keys;
18
use Tarantool\Client\Tests\Integration\ClientBuilder;
19
use Tarantool\Client\Tests\Integration\TestCase;
20
21
/**
22
 * @requires Tarantool >=2
23
 *
24
 * @sql DROP TABLE IF EXISTS exec_query
25
 * @sql CREATE TABLE exec_query (id INTEGER PRIMARY KEY, name VARCHAR(50))
26
 * @sql INSERT INTO exec_query VALUES (1, 'A'), (2, 'B')
27
 */
28
final class ExecuteTest extends TestCase
29
{
30
    private function provideScanQuery() : string
31
    {
32
        /**
33
         * SEQSCAN keyword is explicitly allowing to use seqscan:
34
         * https://github.com/tarantool/tarantool/commit/77648827326ad268ec0ffbcd620c2371b65ef2b4
35
         * It was introduced in Tarantool 2.11.0-rc1. If compat.sql_seq_scan_default set to "new"
36
         * (default value since 3.0), query returns error when trying to scan without keyword.
37
         */
38
        if (server_version_at_least('2.11', $this->client)) {
0 ignored issues
show
Bug introduced by
It seems like $this->client can also be of type null; however, parameter $client of server_version_at_least() does only seem to accept Tarantool\Client\Client, maybe add an additional type check? ( Ignorable by Annotation )

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

38
        if (server_version_at_least('2.11', /** @scrutinizer ignore-type */ $this->client)) {
Loading history...
39
            return 'SELECT * FROM SEQSCAN exec_query';
40
        }
41
        
42
        return 'SELECT * FROM exec_query';
43
    }
44
45
    /**
46
     * @sql DROP TABLE IF EXISTS exec_update
47
     * @sql CREATE TABLE exec_update (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(50))
48
     */
49
    public function testExecuteInsertsRows() : void
50
    {
51
        $response = $this->client->execute(
0 ignored issues
show
Bug introduced by
The method execute() does not exist on null. ( Ignorable by Annotation )

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

51
        /** @scrutinizer ignore-call */ 
52
        $response = $this->client->execute(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
52
            'INSERT INTO exec_update VALUES (5, :name1), (null, :name2)',
53
            [':name1' => 'A'], [':name2' => 'B']
54
        );
55
56
        $expectedSqlInfo = [
57
            Keys::SQL_INFO_ROW_COUNT => 2,
58
            Keys::SQL_INFO_AUTO_INCREMENT_IDS => [6],
59
        ];
60
61
        self::assertSame($expectedSqlInfo, $response->getBodyField(Keys::SQL_INFO));
62
    }
63
64
    public function testExecuteFetchesAllRows() : void
65
    {
66
        $response = $this->client->execute(self::provideScanQuery());
0 ignored issues
show
Bug Best Practice introduced by
The method Tarantool\Client\Tests\I...est::provideScanQuery() is not static, but was called statically. ( Ignorable by Annotation )

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

66
        $response = $this->client->execute(self::/** @scrutinizer ignore-call */ provideScanQuery());
Loading history...
67
68
        self::assertSame([[1, 'A'], [2, 'B']], $response->getBodyField(Keys::DATA));
69
    }
70
71
    /**
72
     * @sql DROP TABLE IF EXISTS exec_update
73
     * @sql CREATE TABLE exec_update (id INTEGER PRIMARY KEY, name VARCHAR(50))
74
     */
75
    public function testExecuteUpdateInsertsRows() : void
76
    {
77
        $result = $this->client->executeUpdate(
78
            'INSERT INTO exec_update VALUES (1, :name1), (2, :name2)',
79
            [':name1' => 'A'], [':name2' => 'B']
80
        );
81
82
        self::assertSame([], $result->getAutoincrementIds());
83
        self::assertSame(2, $result->count());
84
    }
85
86
    /**
87
     * @sql DROP TABLE IF EXISTS exec_update
88
     * @sql CREATE TABLE exec_update (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(50))
89
     */
90
    public function testExecuteUpdateInsertsRowsWithAutoIncrementedIds() : void
91
    {
92
        $result = $this->client->executeUpdate("INSERT INTO exec_update VALUES (100, 'A'), (null, 'B'), (120, 'C'), (null, 'D')");
93
94
        self::assertSame([101, 121], $result->getAutoincrementIds());
95
        self::assertSame(4, $result->count());
96
    }
97
98
    /**
99
     * @sql DROP TABLE IF EXISTS exec_update
100
     * @sql CREATE TABLE exec_update (id INTEGER PRIMARY KEY, name VARCHAR(50))
101
     * @sql INSERT INTO exec_update VALUES (1, 'A'), (2, 'B')
102
     */
103
    public function testExecuteUpdateUpdatesRow() : void
104
    {
105
        $result = $this->client->executeUpdate('UPDATE exec_update SET name = ? WHERE id = ?', 'BB', 2);
106
107
        self::assertSame([], $result->getAutoincrementIds());
108
        self::assertSame(1, $result->count());
109
    }
110
111
    public function testExecuteQueryFetchesAllRows() : void
112
    {
113
        $result = $this->client->executeQuery(self::provideScanQuery());
0 ignored issues
show
Bug Best Practice introduced by
The method Tarantool\Client\Tests\I...est::provideScanQuery() is not static, but was called statically. ( Ignorable by Annotation )

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

113
        $result = $this->client->executeQuery(self::/** @scrutinizer ignore-call */ provideScanQuery());
Loading history...
114
115
        self::assertSame([[1, 'A'], [2, 'B']], $result->getData());
116
        self::assertSame(2, $result->count());
117
    }
118
119
    public function testExecuteQueryFetchesOneRow() : void
120
    {
121
        $result = $this->client->executeQuery('SELECT * FROM exec_query WHERE id = 1');
122
123
        self::assertSame([[1, 'A']], $result->getData());
124
        self::assertSame(1, $result->count());
125
    }
126
127
    public function testExecuteQueryFetchesNoRows() : void
128
    {
129
        $result = $this->client->executeQuery('SELECT * FROM exec_query WHERE id = -1');
130
131
        self::assertSame([], $result->getData());
132
        self::assertSame(0, $result->count());
133
    }
134
135
    public function testExecuteQueryBindsPositionalParameters() : void
136
    {
137
        $result = $this->client->executeQuery('SELECT ?, ?', 2, 'B');
138
139
        self::assertSame([[2, 'B']], $result->getData());
140
        self::assertSame(1, $result->count());
141
    }
142
143
    public function testExecuteQueryBindsNamedParameters() : void
144
    {
145
        $result = $this->client->executeQuery('SELECT :id, :name', [':name' => 'B'], [':id' => 2]);
146
147
        self::assertSame([[2, 'B']], $result->getData());
148
        self::assertSame(1, $result->count());
149
    }
150
151
    public function testExecuteQueryBindsMixedParameters() : void
152
    {
153
        $result = $this->client->executeQuery('SELECT ?, :name', 2, [':name' => 'B']);
154
155
        self::assertSame([[2, 'B']], $result->getData());
156
        self::assertSame(1, $result->count());
157
    }
158
159
    /**
160
     * @see https://github.com/tarantool/tarantool/issues/4782
161
     */
162
    public function testExecuteQueryBindsMixedParametersAndSubstitutesPositionalOnes() : void
163
    {
164
        $result = $this->client->executeQuery('SELECT :id, ?', 'B', [':id' => 2]);
165
166
        self::assertSame([[2, null]], $result->getData());
167
        self::assertSame(1, $result->count());
168
    }
169
170
    public function testSqlQueryResultHoldsMetadata() : void
171
    {
172
        $client = ClientBuilder::createFromEnv()->build();
173
174
        $response = $client->executeQuery(self::provideScanQuery());
0 ignored issues
show
Bug Best Practice introduced by
The method Tarantool\Client\Tests\I...est::provideScanQuery() is not static, but was called statically. ( Ignorable by Annotation )

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

174
        $response = $client->executeQuery(self::/** @scrutinizer ignore-call */ provideScanQuery());
Loading history...
175
176
        self::assertSame([[
177
            Keys::METADATA_FIELD_NAME => 'ID',
178
            Keys::METADATA_FIELD_TYPE => 'integer',
179
        ], [
180
            Keys::METADATA_FIELD_NAME => 'NAME',
181
            Keys::METADATA_FIELD_TYPE => 'string',
182
        ]], $response->getMetadata());
183
    }
184
185
    /**
186
     * @requires Tarantool >=2.6
187
     *
188
     * @sql DROP TABLE IF EXISTS %target_method%
189
     * @sql CREATE TABLE %target_method% (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(50) COLLATE "unicode_ci")
190
     */
191
    public function testSqlQueryResultHoldsExtendedMetadata() : void
192
    {
193
        $client = ClientBuilder::createFromEnv()->build();
194
        $client->execute('SET SESSION "sql_full_metadata" = true');
195
196
        $tableName = $this->resolvePlaceholders('%target_method%');
197
198
        /**
199
         * SEQSCAN keyword is explicitly allowing to use seqscan:
200
         * https://github.com/tarantool/tarantool/commit/77648827326ad268ec0ffbcd620c2371b65ef2b4
201
         * It was introduced in Tarantool 2.11.0-rc1. If compat.sql_seq_scan_default set to "new"
202
         * (default value since 3.0), query returns error when trying to scan without keyword.
203
         */
204
        if (server_version_at_least('2.11', $this->client)) {
0 ignored issues
show
Bug introduced by
It seems like $this->client can also be of type null; however, parameter $client of server_version_at_least() does only seem to accept Tarantool\Client\Client, maybe add an additional type check? ( Ignorable by Annotation )

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

204
        if (server_version_at_least('2.11', /** @scrutinizer ignore-type */ $this->client)) {
Loading history...
205
            $scan_query = "SELECT id, name as full_name FROM SEQSCAN $tableName";
206
        } else {
207
            $scan_query = "SELECT id, name as full_name FROM $tableName";
208
        }
209
        $response = $client->executeQuery($scan_query);
210
211
        self::assertSame([[
212
            Keys::METADATA_FIELD_NAME => 'ID',
213
            Keys::METADATA_FIELD_TYPE => 'integer',
214
            Keys::METADATA_FIELD_IS_NULLABLE => false,
215
            Keys::METADATA_FIELD_IS_AUTOINCREMENT => true,
216
            Keys::METADATA_FIELD_SPAN => 'id',
217
        ], [
218
            Keys::METADATA_FIELD_NAME => 'FULL_NAME',
219
            Keys::METADATA_FIELD_TYPE => 'string',
220
            Keys::METADATA_FIELD_COLL => 'unicode_ci',
221
            Keys::METADATA_FIELD_IS_NULLABLE => true,
222
            Keys::METADATA_FIELD_SPAN => 'name',
223
        ]], $response->getMetadata());
224
    }
225
}
226