PrepareTest   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 117
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 57
c 5
b 0
f 0
dl 0
loc 117
rs 10
wmc 9

7 Methods

Rating   Name   Duplication   Size   Complexity  
A testPrepareResetsPreviouslyBoundParameters() 0 12 1
A testExecuteQueryReturnsResult() 0 17 2
A testCloseFailsOnNonexistentPreparedStatement() 0 7 1
A testCloseDeallocatesPreparedInLuaSqlStatement() 0 19 1
A testExecuteUpdateUpdatesRows() 0 15 1
A testPreparePreparesSqlStatement() 0 17 2
A testCloseDeallocatesPreparedStatement() 0 6 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\Tests\Integration\Requests;
15
16
use Tarantool\Client\Exception\RequestFailed;
17
use Tarantool\Client\PreparedStatement;
18
use Tarantool\Client\Tests\Integration\TestCase;
19
20
/**
21
 * @requires Tarantool >=2.3.2
22
 */
23
final class PrepareTest extends TestCase
24
{
25
    public function testPreparePreparesSqlStatement() : void
26
    {
27
        [$preparedCountBefore] = $this->client->evaluate('return box.info.sql().cache.stmt_count');
0 ignored issues
show
Bug introduced by
The method evaluate() 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

27
        /** @scrutinizer ignore-call */ 
28
        [$preparedCountBefore] = $this->client->evaluate('return box.info.sql().cache.stmt_count');

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...
28
        $stmt = $this->client->prepare('SELECT ?');
29
        [$preparedCountAfter] = $this->client->evaluate('return box.info.sql().cache.stmt_count');
30
31
        try {
32
            self::assertSame($preparedCountBefore + 1, $preparedCountAfter);
33
            self::assertIsInt($stmt->getId());
34
            self::assertSame(1, $stmt->getBindCount());
35
            self::assertSame([['?', 'ANY']], $stmt->getBindMetadata());
36
            // If the data type of NULL cannot be determined from context, it is BOOLEAN.
37
            // @see https://www.tarantool.io/en/doc/2.2/reference/reference_sql/sql/#column-definition-data-type
38
            $metaColumnName = $this->tarantoolVersionSatisfies('<2.6.0') ? '?' : 'COLUMN_1';
39
            self::assertSame([[$metaColumnName, 'boolean']], $stmt->getMetadata());
40
        } finally {
41
            $stmt->close();
42
        }
43
    }
44
45
    public function testExecuteQueryReturnsResult() : void
46
    {
47
        $stmt = $this->client->prepare('SELECT :v1, :v2');
48
49
        $selectResult1 = $stmt->executeQuery([':v1' => 1], [':v2' => 2]);
50
        $selectResult2 = $stmt->executeQuery([':v1' => 3], [':v2' => 4]);
51
52
        try {
53
            if ($this->tarantoolVersionSatisfies('<2.6.0')) {
54
                self::assertSame([':v1' => 1, ':v2' => 2], $selectResult1[0]);
55
                self::assertSame([':v1' => 3, ':v2' => 4], $selectResult2[0]);
56
            } else {
57
                self::assertSame(['COLUMN_1' => 1, 'COLUMN_2' => 2], $selectResult1[0]);
58
                self::assertSame(['COLUMN_1' => 3, 'COLUMN_2' => 4], $selectResult2[0]);
59
            }
60
        } finally {
61
            $stmt->close();
62
        }
63
    }
64
65
    /**
66
     * @sql DROP TABLE IF EXISTS prepare_execute
67
     * @sql CREATE TABLE prepare_execute (id INTEGER PRIMARY KEY, name VARCHAR(50))
68
     */
69
    public function testExecuteUpdateUpdatesRows() : void
70
    {
71
        $stmt = $this->client->prepare('INSERT INTO prepare_execute VALUES(:id, :name)');
72
73
        $insertResult1 = $stmt->executeUpdate(1, 'foo');
74
        $insertResult2 = $stmt->executeUpdate([':name' => 'bar'], [':id' => 2]);
75
76
        $selectResult = $this->client->executeQuery('SELECT * FROM prepare_execute WHERE id > 0 ORDER BY id');
77
78
        try {
79
            self::assertSame(1, $insertResult1->count());
80
            self::assertSame(1, $insertResult2->count());
81
            self::assertSame([[1, 'foo'], [2, 'bar']], $selectResult->getData());
82
        } finally {
83
            $stmt->close();
84
        }
85
    }
86
87
    public function testCloseDeallocatesPreparedStatement() : void
88
    {
89
        $stmt = $this->client->prepare('SELECT ?');
90
91
        $this->expectPreparedStatementToBeDeallocatedOnce();
92
        $stmt->close();
93
    }
94
95
    public function testCloseDeallocatesPreparedInLuaSqlStatement() : void
96
    {
97
        [$data] = $this->client->evaluate("s = box.prepare('SELECT ?') return {
98
            id=s.stmt_id,
99
            bind_metadata=s.params,
100
            metadata=s.metadata,
101
            bind_count=s.param_count
102
        }");
103
104
        $stmt = new PreparedStatement(
105
            $this->client->getHandler(),
106
            $data['id'],
107
            $data['bind_count'],
108
            $data['bind_metadata'],
109
            $data['metadata']
110
        );
111
112
        $this->expectPreparedStatementToBeDeallocatedOnce();
113
        $stmt->close();
114
    }
115
116
    public function testCloseFailsOnNonexistentPreparedStatement() : void
117
    {
118
        $stmt = new PreparedStatement($this->client->getHandler(), 42, 0, [], []);
119
120
        $this->expectException(RequestFailed::class);
121
        $this->expectExceptionMessage('Prepared statement with id 42 does not exist');
122
        $stmt->close();
123
    }
124
125
    /**
126
     * @see https://github.com/tarantool/tarantool/issues/4825
127
     */
128
    public function testPrepareResetsPreviouslyBoundParameters() : void
129
    {
130
        $stmt = $this->client->prepare('SELECT :a, :b');
131
132
        // Bind parameters to the current statement.
133
        $stmt->execute([':a' => 1], [':b' => 2]);
134
135
        $result = $stmt->executeQuery([':a' => 1]);
136
        self::assertSame([1, null], $result->getData()[0]);
137
138
        $result = $stmt->executeQuery();
139
        self::assertSame([null, null], $result->getData()[0]);
140
    }
141
}
142