Completed
Branch trunk (78000f)
by SuperNova.WS
25:55 queued 09:00
created

DbQueryTest::testInsertBatch()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 36
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 24
nc 1
nop 0
dl 0
loc 36
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * Created by Gorlum 07.08.2016 18:45
4
 */
5
6
use \DBAL\DbQuery;
7
8
class DbEscape {
9
  public function db_escape($value) {
10
    // Characters encoded are NUL (ASCII 0), \n, \r, \, ', ", and Control-Z.
11
    return str_replace(
12
      array("\\", "\0", "\n", "\r", "'", "\"", "\z",),
13
      array('\\\\', '\0', '\n', '\r', '\\\'', '\"', '\z',),
14
      $value
15
    );
16
  }
17
}
18
19
/**
20
 * Class DbQueryTest
21
 * @coversDefaultClass \DBAL\DbQuery
22
 */
23
class DbQueryTest extends PHPUnit_Framework_TestCase {
24
25
  /**
26
   * @var DbQuery $object
27
   */
28
  protected $object;
29
30
  protected $db;
31
32
  public function setUp() {
33
    parent::setUp();
34
35
    $this->db = new DbEscape();
36
    $this->object = new DbQuery($this->db);
37
  }
38
39
  public function tearDown() {
40
    unset($this->object);
41
    parent::tearDown();
42
  }
43
44
  /**
45
   * @covers ::__construct
46
   */
47
  public function test__construct() {
48
    $this->assertAttributeEquals($this->db, 'db', $this->object);
49
  }
50
51
  /**
52
   * @covers ::build
53
   */
54
  public function testBuild() {
55
    $this->assertEquals('DBAL\DbQuery', get_class($query = DbQuery::build($this->db)));
56
    $this->assertAttributeEquals($this->db, 'db', $query);
57
  }
58
59
  /**
60
   * @covers ::escape
61
   */
62
  public function testEscape() {
63
    // TODO - create real DB connection here
64
    $this->assertEquals('\0\n\r \\\\z \\\\ \\\' \"', $result = invokeMethod($this->object, 'escape', array("\0\n\r \z \\ ' \"")));
65
    $this->assertEquals(19, strlen($result));
66
  }
67
68
  /**
69
   * @covers ::escapeEmulator
70
   */
71
  public function testEscapeEmulator() {
72
    $this->assertEquals('\0\n\r \\\\z \\\\ \\\' \"', $result = invokeMethod($this->object, 'escapeEmulator', array("\0\n\r \z \\ ' \"")));
73
    $this->assertEquals(19, strlen($result));
74
  }
75
76
  /**
77
   * @covers ::stringValue
78
   */
79
  public function testStringValue() {
80
    $this->assertEquals('\'The\"test\\\\of\\\'escape\'', $result = invokeMethod($this->object, 'stringValue', array('The"test\of\'escape')));
81
  }
82
83
  /**
84
   * @covers ::quote
85
   */
86
  public function testQuote() {
87
    $this->assertEquals('`The\"test\\\\of\\\'escape`', $result = invokeMethod($this->object, 'quote', array('The"test\of\'escape')));
88
  }
89
90
  /**
91
   * @covers ::makeAdjustString
92
   */
93
  public function testMakeAdjustString() {
94
    $this->assertEquals("'test'", $result = invokeMethod($this->object, 'makeAdjustString', array('test', 1)));
95
    $this->assertEquals("`f1` = `f1` + ('v1')", $result = invokeMethod($this->object, 'makeAdjustString', array('v1', 'f1')));
96
  }
97
98
  /**
99
   * @covers ::makeFieldEqualValue
100
   */
101
  public function testMakeFieldEqualValue() {
102
    $this->assertEquals("'test2'", $result = invokeMethod($this->object, 'makeFieldEqualValue', array('test2', 1)));
103
    $this->assertEquals("`f2` = 'v2'", $result = invokeMethod($this->object, 'makeFieldEqualValue', array('v2', 'f2')));
104
  }
105
106
  /**
107
   * @covers ::quoteTable
108
   */
109
  public function testQuoteTable() {
110
    $this->assertEquals('`{{The\"test\\\\of\\\'escape}}`', $result = invokeMethod($this->object, 'quoteTable', array('The"test\of\'escape')));
111
  }
112
113
  public function dataCastAsDbValue() {
114
    return array(
115
      array(10, TYPE_INTEGER, 10, TYPE_INTEGER),
116
      array(PHP_INT_MAX, TYPE_INTEGER, PHP_INT_MAX, TYPE_INTEGER),
117
118
      array(11.0, TYPE_DOUBLE, 11.0, TYPE_DOUBLE),
119
      array(PHP_INT_MAX + 1, TYPE_DOUBLE, PHP_INT_MAX + 1, TYPE_DOUBLE),
120
121
      array(0, TYPE_INTEGER, false, TYPE_BOOLEAN),
122
      array(1, TYPE_INTEGER, true, TYPE_BOOLEAN),
123
124
      array('NULL', TYPE_STRING, null, TYPE_NULL),
125
126
      array('\'\'', TYPE_STRING, '', TYPE_EMPTY),
127
128
      array('\'\'', TYPE_STRING, '', TYPE_STRING),
129
      array('\'\0\n\r \\\\z \\\\ \\\' \"\'', TYPE_STRING, "\0\n\r \z \\ ' \"", TYPE_STRING),
130
      array('\'The\"test\\\\of\\\'escape\'', TYPE_STRING, 'The"test\of\'escape', TYPE_STRING),
131
132
      array('\'a:0:{}\'', TYPE_STRING, array(), TYPE_ARRAY),
133
      array('\'a:1:{s:4:\"k\\\'ey\";s:9:\"st\\\'ri\"n\\\\g\";}\'', TYPE_STRING, array('k\'ey' => 'st\'ri"n\\g'), TYPE_ARRAY),
134
    );
135
  }
136
137
  /**
138
   * @covers ::makeValueSafe
139
   * @dataProvider dataCastAsDbValue
140
   */
141
  public function testCastAsDbValue($expected, $type, $value, $originalType) {
142
    if ($originalType != TYPE_NULL && $originalType != TYPE_EMPTY) {
143
      $this->assertInternalType($originalType, $value);
144
    }
145
    $this->assertEquals($expected, invokeMethod($this->object, 'makeValueSafe', array($value)));
146
    $this->assertInternalType($type, invokeMethod($this->object, 'makeValueSafe', array($value)));
147
  }
148
149
  /**
150
   * @covers ::setTable
151
   * @covers ::setOneRow
152
   * @covers ::setValues
153
   * @covers ::setValuesDanger
154
   * @covers ::setAdjust
155
   * @covers ::setAdjustDanger
156
   * @covers ::setFields
157
   * @covers ::setWhereArray
158
   * @covers ::setWhereArrayDanger
159
   */
160
  public function testSetters() {
161
    $result = $this->object
162
      ->setTable('table')
163
      ->setOneRow(DbQuery::DB_RECORD_ONE)
164
      ->setValues(array('f1' => 'v1'))
165
      ->setValuesDanger(array('f2 <= v1'))
166
      ->setAdjust(array('f7' => '7'))
167
      ->setAdjustDanger(array('f3' => '3'))
168
      ->setFields(array('f4' => 'v4'))
169
      ->setWhereArray(array('f5' => '5'))
170
      ->setWhereArrayDanger(array('f6' => '6'));
171
172
    // Fluid interface is working
173
    $this->assertEquals($this->object, $result);
174
175
    $this->assertAttributeEquals('table', 'table', $this->object);
176
    $this->assertAttributeEquals(DbQuery::DB_RECORD_ONE, 'isOneRow', $this->object);
177
    $this->assertAttributeEquals(array('f1' => 'v1'), 'values', $this->object);
178
    $this->assertAttributeEquals(array('f2 <= v1'), 'valuesDanger', $this->object);
179
    $this->assertAttributeEquals(array('f7' => '7'), 'adjust', $this->object);
180
    $this->assertAttributeEquals(array('f3' => '3'), 'adjustDanger', $this->object);
181
    $this->assertAttributeEquals(array('f4' => 'v4'), 'fields', $this->object);
182
    $this->assertAttributeEquals(array('f5' => '5'), 'where', $this->object);
183
    $this->assertAttributeEquals(array('f6' => '6'), 'whereDanger', $this->object);
184
  }
185
186
  public function dataBuildCommand() {
187
    return array(
188
      array('', ''),
189
      array('SELECT', DbQuery::SELECT),
190
      array('INSERT INTO `{{theTable}}`', DbQuery::INSERT),
191
      array('INSERT IGNORE INTO `{{theTable}}`', DbQuery::INSERT_IGNORE),
192
      array('REPLACE INTO `{{theTable}}`', DbQuery::REPLACE),
193
      array('UPDATE `{{theTable}}`', DbQuery::UPDATE),
194
      array('DELETE FROM `{{theTable}}`', DbQuery::DELETE),
195
    );
196
  }
197
198
  /**
199
   * @covers ::buildCommand
200
   * @covers ::__toString
201
   * @dataProvider dataBuildCommand
202
   */
203
  public function testBuildCommand($expected, $command) {
204
    $this->object->setTable('theTable');
205
//    $property = getPrivateProperty($this->object, 'command');
206
//    $property->setValue($this->object, $command);
207
    invokeMethod($this->object, 'buildCommand', array($command));
208
    $this->assertEquals($expected, $this->object->__toString());
209
  }
210
211
212
  /**
213
   * @covers ::buildSetFields
214
   */
215
  public function testBuildSetFields() {
216
    $this->object
217
      ->setValues(array('f1' => 's1', 'f2' => 1))
218
      ->setValuesDanger(array('f3 = 5, f4 = "str4"  '))
219
      ->setAdjust(array('f5' => 1, 'f6' => 'str6', 0 => 'quotedString'))
220
      ->setAdjustDanger(array('f7 = f7 + 2  '));
221
222
    invokeMethod($this->object, 'buildSetFields', array());
223
    $this->assertEquals(" SET f3 = 5, f4 = \"str4\"  ,`f1` = 's1',`f2` = 1,f7 = f7 + 2  ,`f5` = `f5` + (1),`f6` = `f6` + ('str6'),'quotedString'", $this->object->__toString());
224
  }
225
226
227
  /**
228
   * @covers ::buildFieldNames
229
   */
230
  public function testBuildFieldNames() {
231
    $this->object->setFields(array('v1', 'v2'));
232
    invokeMethod($this->object, 'buildFieldNames', array());
233
    $this->assertEquals('`v1`,`v2`', $this->object->__toString());
234
  }
235
236
  /**
237
   * @covers ::buildValuesVector
238
   */
239
  public function testBuildValuesVector() {
240
    $this->object->setValues(array(
241
      array('f1' => 'string', 'f2' => 1, 'f3' => null),
242
      array('f1' => 'v1', 'f2' => 2, 'f3' => null),
243
    ));
244
    $this->object->setValuesDanger('(DANGER!)');
245
    invokeMethod($this->object, 'buildValuesVector', array());
246
    $this->assertEquals("(DANGER!),('string',1,NULL),('v1',2,NULL)", $this->object->__toString());
247
  }
248
249
250
  /**
251
   * @covers ::buildWhere
252
   */
253
  public function testBuildWhere() {
254
    invokeMethod($this->object, 'buildWhere', array());
255
    $this->assertEquals('', $this->object->__toString());
256
257
    $this->object
258
      ->setWhereArray(array('f1' => 's1', 0 => 'quotedString'))
259
      ->setWhereArrayDanger(array('f2' => 's2'));
260
    invokeMethod($this->object, 'buildWhere', array());
261
    $this->assertEquals(" WHERE s2 AND `f1` = 's1' AND 'quotedString'", $this->object->__toString());
262
  }
263
264
265
  /**
266
   * @covers ::buildLimit
267
   */
268
  public function testBuildLimit() {
269
    $this->object->setOneRow(DbQuery::DB_RECORD_ONE);
270
    invokeMethod($this->object, 'buildLimit', array());
271
    $this->assertEquals(" LIMIT 1", $this->object->__toString());
272
  }
273
274
275
  /**
276
   * @covers ::delete
277
   */
278
  public function testDelete() {
279
    $this->object
280
      ->setTable('aT')
281
      ->setWhereArray(array('f1' => 's1', 0 => 'ANDinQuote'))
282
      ->setWhereArrayDanger(array('f2' => 'f3 = 1'))
283
      ->setOneRow(DbQuery::DB_RECORD_ONE);
284
    $this->assertEquals("DELETE FROM `{{aT}}` WHERE f3 = 1 AND `f1` = 's1' AND 'ANDinQuote' LIMIT 1", $this->object->delete());
285
  }
286
287
288
  /**
289
   * @covers ::update
290
   */
291
  public function testUpdate() {
292
    $this->object
293
      ->setTable('aT')
294
      ->setValues(array('f1' => 's1'))
295
      ->setValuesDanger(array(' f3 = 5 '))
296
      ->setAdjust(array('f5' => 1, 'f6' => -1))
297
      ->setAdjustDanger(array(' f7 = f7 + 2 '))
298
      ->setWhereArray(array('f1' => 's1'))
299
      ->setWhereArrayDanger(array('f2' => 'f3 = 1'))
300
      ->setOneRow(DbQuery::DB_RECORD_ONE);
301
    $this->assertEquals(
302
      "UPDATE `{{aT}}`" .
303
      " SET  f3 = 5 ,`f1` = 's1'," .
304
      " f7 = f7 + 2 ,`f5` = `f5` + (1),`f6` = `f6` + (-1)" .
305
      " WHERE f3 = 1 AND `f1` = 's1' LIMIT 1",
306
      $this->object->update()
307
    );
308
  }
309
310
311
312
  /**
313
   * Insert SET test
314
   *
315
   * @covers ::insert
316
   * @covers ::setInsertCommand
317
   */
318
  public function testInsertSet() {
319
    $this->object
320
      ->setTable('aT')
321
      ->setValues(array('f1' => 's1'))
322
      ->setValuesDanger(array(' f3 = 5 '))
323
      ->setAdjust(array('f5' => 1, 'f6' => -1))
324
      ->setAdjustDanger(array(' f7 = f7 + 2 '));
325
    $this->assertEquals(
326
      "INSERT INTO `{{aT}}`" .
327
      " SET  f3 = 5 ,`f1` = 's1'," .
328
      " f7 = f7 + 2 ,`f5` = `f5` + (1),`f6` = `f6` + (-1)",
329
      invokeMethod($this->object, 'insert', array(DbQuery::DB_INSERT_PLAIN))
330
    );
331
332
    $this->object->setTable('aT2')->setAdjust(array('f25' => 21, 'f26' => -21));
333
    $this->assertEquals(
334
      "INSERT IGNORE INTO `{{aT2}}`" .
335
      " SET  f3 = 5 ,`f1` = 's1'," .
336
      " f7 = f7 + 2 ,`f5` = `f5` + (1),`f6` = `f6` + (-1)," .
337
      "`f25` = `f25` + (21),`f26` = `f26` + (-21)",
338
      invokeMethod($this->object, 'insert', array(DbQuery::DB_INSERT_IGNORE))
339
    );
340
341
    $this->object->setTable('aT2')->setAdjust(array('f36' => -31));
342
    $this->assertEquals(
343
      "REPLACE INTO `{{aT2}}`" .
344
      " SET  f3 = 5 ,`f1` = 's1'," .
345
      " f7 = f7 + 2 ,`f5` = `f5` + (1),`f6` = `f6` + (-1)," .
346
      "`f25` = `f25` + (21),`f26` = `f26` + (-21),`f36` = `f36` + (-31)",
347
      invokeMethod($this->object, 'insert', array(DbQuery::DB_INSERT_REPLACE))
348
    );
349
  }
350
351
352
  /**
353
   * Insert BATCH test
354
   *
355
   * @covers ::insert
356
   * @covers ::setInsertCommand
357
   */
358
  public function testInsertBatch() {
359
    $this->object
360
      ->setTable('aT')
361
      ->setFields(array('f1', 'f2'))
362
      ->setValues(array(array('v1', 1)))
363
    ;
364
    $this->assertEquals(
365
      "INSERT INTO `{{aT}}` (`f1`,`f2`) VALUES " .
366
      "('v1',1)"
367
      ,
368
      invokeMethod($this->object, 'insert', array(DbQuery::DB_INSERT_PLAIN))
369
    );
370
371
    $this->object
372
      ->setTable('aT2')
373
      ->setValues(array(array('v2', 2)))
374
    ;
375
    $this->assertEquals(
376
      "INSERT IGNORE INTO `{{aT2}}` (`f1`,`f2`) VALUES " .
377
      "('v1',1),('v2',2)"
378
      ,
379
      invokeMethod($this->object, 'insert', array(DbQuery::DB_INSERT_IGNORE))
380
    );
381
382
    $this->object
383
      ->setTable('aT2')
384
      ->setValues(array(array('v3', 3),array('v4', 4)))
385
      ->setValuesDanger(array('this IS danger!'))
386
    ;
387
    $this->assertEquals(
388
      "REPLACE INTO `{{aT2}}` (`f1`,`f2`) VALUES " .
389
      "this IS danger!,('v1',1),('v2',2),('v3',3),('v4',4)"
390
      ,
391
      invokeMethod($this->object, 'insert', array(DbQuery::DB_INSERT_REPLACE))
392
    );
393
  }
394
395
  /**
396
   * @covers ::select
397
   */
398
  public function testSelect() {
399
    $this->object
400
      ->setTable('aT')
401
      // ->setFields(array('f1', 'f2')) // TODO - unused
402
      ->setWhereArray(array('f1' => 's1'))
403
      ->setWhereArrayDanger(array('f2' => '(f3 = 1 OR f3 = 2)'))
404
      ->setOneRow(DbQuery::DB_RECORD_ONE)
405
    ;
406
    $this->assertEquals(
407
      "SELECT * FROM `{{aT}}` WHERE (f3 = 1 OR f3 = 2) AND `f1` = 's1' LIMIT 1",
408
      $this->object->select()
409
    );
410
  }
411
412
}
413