Failed Conditions
Pull Request — master (#2762)
by Evgenij
04:45
created

testMultiInsertWithColumnSpecification()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 30
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 21
nc 1
nop 0
1
<?php
2
3
namespace Doctrine\Tests\DBAL\Query;
4
5
use Doctrine\DBAL\Query\BulkInsertQuery;
6
use Doctrine\Tests\DBAL\Mocks\MockPlatform;
7
8
/**
9
 * @group DBAL-218
10
 */
11
class BulkInsertQueryTest extends \Doctrine\Tests\DbalTestCase
12
{
13
    /**
14
     * @var \Doctrine\DBAL\Connection|\PHPUnit_Framework_MockObject_MockObject
15
     */
16
    protected $connection;
17
18
    /**
19
     * {@inheritdoc}
20
     */
21
    protected function setUp()
22
    {
23
        $this->connection = $this->getMockBuilder('Doctrine\DBAL\Connection')
24
            ->disableOriginalConstructor()
25
            ->getMock();
26
27
        $this->connection->expects($this->any())
28
            ->method('getDatabasePlatform')
29
            ->will($this->returnValue(new MockPlatform()));
30
    }
31
32
    /**
33
     * @expectedException \LogicException
34
     * @expectedExceptionMessage You need to add at least one set of values before generating the SQL.
35
     */
36
    public function testGetSQLWithoutSpecifiedValuesThrowsException()
37
    {
38
        $query = new BulkInsertQuery($this->connection, 'foo');
39
40
        $query->getSQL();
41
    }
42
43
    public function testEmptyInsertWithoutColumnSpecification()
44
    {
45
        $query = new BulkInsertQuery($this->connection, 'foo');
46
47
        $query->addValues(array());
48
49
        $this->assertSame("INSERT INTO foo VALUES ()", $query->getSQL());
50
        $this->assertSame(array(), $query->getParameters());
51
        $this->assertSame(array(), $query->getParameterTypes());
52
53
        $query = new BulkInsertQuery($this->connection, 'foo');
54
55
        $query->addValues(array(), array(\PDO::PARAM_BOOL));
56
57
        $this->assertSame("INSERT INTO foo VALUES ()", $query->getSQL());
58
        $this->assertSame(array(), $query->getParameters());
59
        $this->assertSame(array(), $query->getParameterTypes());
60
    }
61
62
    public function testSingleInsertWithoutColumnSpecification()
63
    {
64
        $query = new BulkInsertQuery($this->connection, 'foo');
65
66
        $query->addValues(array('bar', 'baz', 'named' => 'bloo'));
67
68
        $this->assertSame("INSERT INTO foo VALUES (?, ?, ?)", $query->getSQL());
69
        $this->assertSame(array('bar', 'baz', 'bloo'), $query->getParameters());
70
        $this->assertSame(array(null, null, null), $query->getParameterTypes());
71
72
        $query = new BulkInsertQuery($this->connection, 'foo');
73
74
        $query->addValues(
75
            array('bar', 'baz', 'named' => 'bloo'),
76
            array('named' => \PDO::PARAM_BOOL, null, \PDO::PARAM_INT)
77
        );
78
79
        $this->assertSame("INSERT INTO foo VALUES (?, ?, ?)", $query->getSQL());
80
        $this->assertSame(array('bar', 'baz', 'bloo'), $query->getParameters());
81
        $this->assertSame(array(null, \PDO::PARAM_INT, \PDO::PARAM_BOOL), $query->getParameterTypes());
82
    }
83
84
    public function testMultiInsertWithoutColumnSpecification()
85
    {
86
        $query = new BulkInsertQuery($this->connection, 'foo');
87
88
        $query->addValues(array());
89
        $query->addValues(array('bar', 'baz'));
90
        $query->addValues(array('bar', 'baz', 'bloo'));
91
        $query->addValues(array('bar', 'baz', 'named' => 'bloo'));
92
93
        $this->assertSame("INSERT INTO foo VALUES (), (?, ?), (?, ?, ?), (?, ?, ?)", $query->getSQL());
94
        $this->assertSame(array('bar', 'baz', 'bar', 'baz', 'bloo', 'bar', 'baz', 'bloo'), $query->getParameters());
95
        $this->assertSame(array(null, null, null, null, null, null, null, null), $query->getParameterTypes());
96
97
        $query = new BulkInsertQuery($this->connection, 'foo');
98
99
        $query->addValues(array(), array(\PDO::PARAM_INT));
100
        $query->addValues(array('bar', 'baz'), array(1 => \PDO::PARAM_BOOL));
101
        $query->addValues(array('bar', 'baz', 'bloo'), array(\PDO::PARAM_INT, null, \PDO::PARAM_BOOL));
102
        $query->addValues(
103
            array('bar', 'baz', 'named' => 'bloo'),
104
            array('named' => \PDO::PARAM_INT, null, \PDO::PARAM_BOOL)
105
        );
106
107
        $this->assertSame("INSERT INTO foo VALUES (), (?, ?), (?, ?, ?), (?, ?, ?)", $query->getSQL());
108
        $this->assertSame(array('bar', 'baz', 'bar', 'baz', 'bloo', 'bar', 'baz', 'bloo'), $query->getParameters());
109
        $this->assertSame(
110
            array(null, \PDO::PARAM_BOOL, \PDO::PARAM_INT, null, \PDO::PARAM_BOOL, null, \PDO::PARAM_BOOL, \PDO::PARAM_INT),
111
            $query->getParameterTypes()
112
        );
113
    }
114
115
    public function testSingleInsertWithColumnSpecificationAndPositionalTypeValues()
116
    {
117
        $query = new BulkInsertQuery($this->connection, 'foo', array('bar', 'baz'));
118
119
        $query->addValues(array('bar', 'baz'));
120
121
        $this->assertSame("INSERT INTO foo (bar, baz) VALUES (?, ?)", $query->getSQL());
122
        $this->assertSame(array('bar', 'baz'), $query->getParameters());
123
        $this->assertSame(array(null, null), $query->getParameterTypes());
124
125
        $query = new BulkInsertQuery($this->connection, 'foo', array('bar', 'baz'));
126
127
        $query->addValues(array('bar', 'baz'), array(1 => \PDO::PARAM_BOOL));
128
129
        $this->assertSame("INSERT INTO foo (bar, baz) VALUES (?, ?)", $query->getSQL());
130
        $this->assertSame(array('bar', 'baz'), $query->getParameters());
131
        $this->assertSame(array(null, \PDO::PARAM_BOOL), $query->getParameterTypes());
132
    }
133
134 View Code Duplication
    public function testSingleInsertWithColumnSpecificationAndNamedTypeValues()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
135
    {
136
        $query = new BulkInsertQuery($this->connection, 'foo', array('bar', 'baz'));
137
138
        $query->addValues(array('baz' => 'baz', 'bar' => 'bar'));
139
140
        $this->assertSame("INSERT INTO foo (bar, baz) VALUES (?, ?)", $query->getSQL());
141
        $this->assertSame(array('bar', 'baz'), $query->getParameters());
142
        $this->assertSame(array(null, null), $query->getParameterTypes());
143
144
        $query = new BulkInsertQuery($this->connection, 'foo', array('bar', 'baz'));
145
146
        $query->addValues(array('baz' => 'baz', 'bar' => 'bar'), array(null, \PDO::PARAM_INT));
147
148
        $this->assertSame("INSERT INTO foo (bar, baz) VALUES (?, ?)", $query->getSQL());
149
        $this->assertSame(array('bar', 'baz'), $query->getParameters());
150
        $this->assertSame(array(null, \PDO::PARAM_INT), $query->getParameterTypes());
151
    }
152
153 View Code Duplication
    public function testSingleInsertWithColumnSpecificationAndMixedTypeValues()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
154
    {
155
        $query = new BulkInsertQuery($this->connection, 'foo', array('bar', 'baz'));
156
157
        $query->addValues(array(1 => 'baz', 'bar' => 'bar'));
158
159
        $this->assertSame("INSERT INTO foo (bar, baz) VALUES (?, ?)", $query->getSQL());
160
        $this->assertSame(array('bar', 'baz'), $query->getParameters());
161
        $this->assertSame(array(null, null), $query->getParameterTypes());
162
163
        $query = new BulkInsertQuery($this->connection, 'foo', array('bar', 'baz'));
164
165
        $query->addValues(array(1 => 'baz', 'bar' => 'bar'), array(\PDO::PARAM_INT, \PDO::PARAM_BOOL));
166
167
        $this->assertSame("INSERT INTO foo (bar, baz) VALUES (?, ?)", $query->getSQL());
168
        $this->assertSame(array('bar', 'baz'), $query->getParameters());
169
        $this->assertSame(array(\PDO::PARAM_INT, \PDO::PARAM_BOOL), $query->getParameterTypes());
170
    }
171
172
    public function testMultiInsertWithColumnSpecification()
173
    {
174
        $query = new BulkInsertQuery($this->connection, 'foo', array('bar', 'baz'));
175
176
        $query->addValues(array('bar', 'baz'));
177
        $query->addValues(array(1 => 'baz', 'bar' => 'bar'));
178
        $query->addValues(array('bar', 'baz' => 'baz'));
179
        $query->addValues(array('bar' => 'bar', 'baz' => 'baz'));
180
181
        $this->assertSame("INSERT INTO foo (bar, baz) VALUES (?, ?), (?, ?), (?, ?), (?, ?)", $query->getSQL());
182
        $this->assertSame(array('bar', 'baz', 'bar', 'baz', 'bar', 'baz', 'bar', 'baz'), $query->getParameters());
183
        $this->assertSame(array(null, null, null, null, null, null, null, null), $query->getParameterTypes());
184
185
        $query = new BulkInsertQuery($this->connection, 'foo', array('bar', 'baz'));
186
187
        $query->addValues(array('bar', 'baz'), array('baz' => \PDO::PARAM_BOOL, 'bar' => \PDO::PARAM_INT));
188
        $query->addValues(array(1 => 'baz', 'bar' => 'bar'), array(1 => \PDO::PARAM_BOOL, 'bar' => \PDO::PARAM_INT));
189
        $query->addValues(array('bar', 'baz' => 'baz'), array(null, null));
190
        $query->addValues(
191
            array('bar' => 'bar', 'baz' => 'baz'),
192
            array('bar' => \PDO::PARAM_INT, 'baz' => \PDO::PARAM_BOOL)
193
        );
194
195
        $this->assertSame("INSERT INTO foo (bar, baz) VALUES (?, ?), (?, ?), (?, ?), (?, ?)", $query->getSQL());
196
        $this->assertSame(array('bar', 'baz', 'bar', 'baz', 'bar', 'baz', 'bar', 'baz'), $query->getParameters());
197
        $this->assertSame(
198
            array(\PDO::PARAM_INT, \PDO::PARAM_BOOL, \PDO::PARAM_INT, \PDO::PARAM_BOOL, null, null, \PDO::PARAM_INT, \PDO::PARAM_BOOL),
199
            $query->getParameterTypes()
200
        );
201
    }
202
203
    /**
204
     * @expectedException \InvalidArgumentException
205
     * @expectedExceptionMessage No value specified for column bar (index 0).
206
     */
207
    public function testEmptyInsertWithColumnSpecificationThrowsException()
208
    {
209
        $query = new BulkInsertQuery($this->connection, 'foo', array('bar', 'baz'));
210
211
        $query->addValues(array());
212
    }
213
214
    /**
215
     * @expectedException \InvalidArgumentException
216
     * @expectedExceptionMessage Multiple values specified for column baz (index 1).
217
     */
218
    public function testInsertWithColumnSpecificationAndMultipleValuesForColumnThrowsException()
219
    {
220
        $query = new BulkInsertQuery($this->connection, 'foo', array('bar', 'baz'));
221
222
        $query->addValues(array('bar', 'baz', 'baz' => 666));
223
    }
224
225
    /**
226
     * @expectedException \InvalidArgumentException
227
     * @expectedExceptionMessage Multiple types specified for column baz (index 1).
228
     */
229
    public function testInsertWithColumnSpecificationAndMultipleTypesForColumnThrowsException()
230
    {
231
        $query = new BulkInsertQuery($this->connection, 'foo', array('bar', 'baz'));
232
233
        $query->addValues(array('bar', 'baz'), array(\PDO::PARAM_INT, \PDO::PARAM_INT, 'baz' => \PDO::PARAM_STR));
234
    }
235
236
    public function testExecuteWithMaxInsertRowsPerStatementExceededThrowsException()
237
    {
238
        $this->connection->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\DBAL\Connection.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
239
            ->method('isTransactionActive')
240
            ->will($this->returnValue(false));
241
242
        $platform = $this->connection->getDatabasePlatform();
0 ignored issues
show
Bug introduced by
The method getDatabasePlatform does only exist in Doctrine\DBAL\Connection, but not in PHPUnit_Framework_MockObject_MockObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
243
        $insertMaxRows = $platform->getInsertMaxRows();
244
245
        $this->expectException(
246
            '\Doctrine\DBAL\Query\QueryException',
247
            sprintf(
0 ignored issues
show
Unused Code introduced by
The call to BulkInsertQueryTest::expectException() has too many arguments starting with sprintf('You can only in..., $platform->getName()).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
248
                'You can only insert %d rows in a single INSERT statement with platform "%s".',
249
                $insertMaxRows,
250
                $platform->getName()
251
            )
252
        );
253
254
        $query = new BulkInsertQuery($this->connection, 'foo');
255
256
        for ($i = 0; $i <= $insertMaxRows; $i++) {
257
            $query->addValues(array());
258
        }
259
260
        $query->execute();
261
    }
262
263
    /**
264
     * testAllValuesInserted
265
     *
266
     * @return void
267
     */
268
    public function testAllValuesInserted()
269
    {
270
        $platform = $this->connection->getDatabasePlatform();
0 ignored issues
show
Bug introduced by
The method getDatabasePlatform does only exist in Doctrine\DBAL\Connection, but not in PHPUnit_Framework_MockObject_MockObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
271
        $insertMaxRows = $platform->getInsertMaxRows();
272
273
        $this->connection->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\DBAL\Connection.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
274
            ->method('isTransactionActive')
275
            ->will($this->returnValue(true));
276
277
        $actualTypes      = [];
278
        $actualParameters = [];
279
280
        $this->connection->expects($this->exactly(5))
281
            ->method('executeUpdate')
282
            ->will($this->returnCallback(
283
                function (string $sql, array $parameters, array $types) use (&$actualParameters, &$actualTypes) {
284
                    $valueSet = [];
285
                    $parameterCount = count($parameters);
286
                    for ($i = 0; $i < $parameterCount; $i++) {
287
                        $valueSet[] = "\\(\\?\\)";
288
                    }
289
                    $sqlRegExp = "INSERT\\s+INTO\\s+foo\\s+\\(id\\)\s+VALUES\\s+" . implode("\\s*,\\s*", $valueSet);
290
291
                    self::assertRegExp("/$sqlRegExp/", $sql, 'Incorrect sql received');
292
                    $actualParameters = array_merge($actualParameters, $parameters);
293
                    $actualTypes = array_merge($actualTypes, $types);
294
295
                    return $parameterCount;
296
                }
297
            )
298
        );
299
300
        $query = new BulkInsertQuery($this->connection, 'foo', ['id']);
301
302
        $numberOfRows = 4*$insertMaxRows + (int) ceil($insertMaxRows / 2);
303
        for ($i = 0; $i < $numberOfRows; $i++) {
304
            $query->addValues(array('id' => $i), array('id' => 'type' . $i));
305
        }
306
307
        $inserted = $query->execute();
308
        $this->assertSame($numberOfRows, $inserted, 'Unexpected number of inserted rows returned');
309
310
        $this->assertSame($query->getParameters(), $actualParameters, 'Incorrect parameters were passed into the query');
311
        $this->assertSame($query->getParameterTypes(), $actualTypes, 'Incorrect types were passed into the query');
312
    }
313
}
314