Passed
Push — master ( 31f988...5e67da )
by Eugene
02:06
created

ExecuteTest::provideSeqScan()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 1
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 9
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
16
use Tarantool\Client\Keys;
17
use Tarantool\Client\Tests\Integration\ClientBuilder;
18
use Tarantool\Client\Tests\Integration\TestCase;
19
20
/**
21
 * @requires Tarantool >=2
22
 *
23
 * @sql DROP TABLE IF EXISTS exec_query
24
 * @sql CREATE TABLE exec_query (id INTEGER PRIMARY KEY, name VARCHAR(50))
25
 * @sql INSERT INTO exec_query VALUES (1, 'A'), (2, 'B')
26
 */
27
final class ExecuteTest extends TestCase
28
{
29
    private function provideSeqScan() : string
30
    {
31
        /**
32
         * SEQSCAN keyword is explicitly allowing to use seqscan:
33
         * https://github.com/tarantool/tarantool/commit/77648827326ad268ec0ffbcd620c2371b65ef2b4
34
         * It was introduced in Tarantool 2.11.0-rc1. If compat.sql_seq_scan_default set to "new"
35
         * (default value since 3.0), query returns error when trying to scan without keyword.
36
         */
37
        return $this->tarantoolVersionSatisfies('>=2.11.0-rc1') ? 'SEQSCAN' : '';
38
    }
39
40
    /**
41
     * @sql DROP TABLE IF EXISTS exec_update
42
     * @sql CREATE TABLE exec_update (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(50))
43
     */
44
    public function testExecuteInsertsRows() : void
45
    {
46
        $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

46
        /** @scrutinizer ignore-call */ 
47
        $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...
47
            'INSERT INTO exec_update VALUES (5, :name1), (null, :name2)',
48
            [':name1' => 'A'], [':name2' => 'B']
49
        );
50
51
        $expectedSqlInfo = [
52
            Keys::SQL_INFO_ROW_COUNT => 2,
53
            Keys::SQL_INFO_AUTO_INCREMENT_IDS => [6],
54
        ];
55
56
        self::assertSame($expectedSqlInfo, $response->getBodyField(Keys::SQL_INFO));
57
    }
58
59
    public function testExecuteFetchesAllRows() : void
60
    {
61
        $seqScan = self::provideSeqScan();
0 ignored issues
show
Bug Best Practice introduced by
The method Tarantool\Client\Tests\I...eTest::provideSeqScan() 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

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

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

171
        /** @scrutinizer ignore-call */ 
172
        $seqScan = self::provideSeqScan();
Loading history...
172
        $response = $client->executeQuery("SELECT * FROM $seqScan exec_query");
173
174
        self::assertSame([[
175
            Keys::METADATA_FIELD_NAME => 'ID',
176
            Keys::METADATA_FIELD_TYPE => 'integer',
177
        ], [
178
            Keys::METADATA_FIELD_NAME => 'NAME',
179
            Keys::METADATA_FIELD_TYPE => 'string',
180
        ]], $response->getMetadata());
181
    }
182
183
    /**
184
     * @requires Tarantool >=2.6
185
     *
186
     * @sql DROP TABLE IF EXISTS %target_method%
187
     * @sql CREATE TABLE %target_method% (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(50) COLLATE "unicode_ci")
188
     */
189
    public function testSqlQueryResultHoldsExtendedMetadata() : void
190
    {
191
        $client = ClientBuilder::createFromEnv()->build();
192
        $client->execute('SET SESSION "sql_full_metadata" = true');
193
194
        $tableName = $this->resolvePlaceholders('%target_method%');
195
196
        $seqScan = self::provideSeqScan();
0 ignored issues
show
Bug Best Practice introduced by
The method Tarantool\Client\Tests\I...eTest::provideSeqScan() 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

196
        /** @scrutinizer ignore-call */ 
197
        $seqScan = self::provideSeqScan();
Loading history...
197
        $response = $client->executeQuery("SELECT id, name as full_name FROM $seqScan $tableName");
198
199
        self::assertSame([[
200
            Keys::METADATA_FIELD_NAME => 'ID',
201
            Keys::METADATA_FIELD_TYPE => 'integer',
202
            Keys::METADATA_FIELD_IS_NULLABLE => false,
203
            Keys::METADATA_FIELD_IS_AUTOINCREMENT => true,
204
            Keys::METADATA_FIELD_SPAN => 'id',
205
        ], [
206
            Keys::METADATA_FIELD_NAME => 'FULL_NAME',
207
            Keys::METADATA_FIELD_TYPE => 'string',
208
            Keys::METADATA_FIELD_COLL => 'unicode_ci',
209
            Keys::METADATA_FIELD_IS_NULLABLE => true,
210
            Keys::METADATA_FIELD_SPAN => 'name',
211
        ]], $response->getMetadata());
212
    }
213
}
214