MergeTest.php 8.77 KB
Newer Older
1 2
<?php

3
namespace Drupal\KernelTests\Core\Database;
4 5 6 7 8

use Drupal\Core\Database\Query\Merge;
use Drupal\Core\Database\Query\InvalidMergeQueryException;

/**
9
 * Tests the MERGE query builder.
10 11
 *
 * @group Database
12 13 14 15
 */
class MergeTest extends DatabaseTestBase {

  /**
16
   * Confirms that we can merge-insert a record successfully.
17 18 19 20 21
   */
  function testMergeInsert() {
    $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();

    $result = db_merge('test_people')
22
      ->key('job', 'Presenter')
23 24 25 26 27 28
      ->fields(array(
        'age' => 31,
        'name' => 'Tiffany',
      ))
      ->execute();

29
    $this->assertEqual($result, Merge::STATUS_INSERT, 'Insert status returned.');
30 31

    $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
32
    $this->assertEqual($num_records_before + 1, $num_records_after, 'Merge inserted properly.');
33 34

    $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Presenter'))->fetch();
35 36 37
    $this->assertEqual($person->name, 'Tiffany', 'Name set correctly.');
    $this->assertEqual($person->age, 31, 'Age set correctly.');
    $this->assertEqual($person->job, 'Presenter', 'Job set correctly.');
38 39 40
  }

  /**
41
   * Confirms that we can merge-update a record successfully.
42 43 44 45 46
   */
  function testMergeUpdate() {
    $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();

    $result = db_merge('test_people')
47
      ->key('job', 'Speaker')
48 49 50 51 52 53
      ->fields(array(
        'age' => 31,
        'name' => 'Tiffany',
      ))
      ->execute();

54
    $this->assertEqual($result, Merge::STATUS_UPDATE, 'Update status returned.');
55 56

    $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
57
    $this->assertEqual($num_records_before, $num_records_after, 'Merge updated properly.');
58 59

    $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetch();
60 61 62
    $this->assertEqual($person->name, 'Tiffany', 'Name set correctly.');
    $this->assertEqual($person->age, 31, 'Age set correctly.');
    $this->assertEqual($person->job, 'Speaker', 'Job set correctly.');
63 64 65
  }

  /**
66 67 68 69
   * Confirms that we can merge-update a record successfully.
   *
   * This test varies from the previous test because it manually defines which
   * fields are inserted, and which fields are updated.
70 71 72 73 74
   */
  function testMergeUpdateExcept() {
    $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();

    db_merge('test_people')
75
      ->key('job', 'Speaker')
76 77 78 79 80
      ->insertFields(array('age' => 31))
      ->updateFields(array('name' => 'Tiffany'))
      ->execute();

    $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
81
    $this->assertEqual($num_records_before, $num_records_after, 'Merge updated properly.');
82 83

    $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetch();
84 85 86
    $this->assertEqual($person->name, 'Tiffany', 'Name set correctly.');
    $this->assertEqual($person->age, 30, 'Age skipped correctly.');
    $this->assertEqual($person->job, 'Speaker', 'Job set correctly.');
87 88 89
  }

  /**
90
   * Confirms that we can merge-update a record, with alternate replacement.
91 92 93 94 95
   */
  function testMergeUpdateExplicit() {
    $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();

    db_merge('test_people')
96
      ->key('job', 'Speaker')
97 98 99 100 101 102 103 104 105 106
      ->insertFields(array(
        'age' => 31,
        'name' => 'Tiffany',
      ))
      ->updateFields(array(
        'name' => 'Joe',
      ))
      ->execute();

    $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
107
    $this->assertEqual($num_records_before, $num_records_after, 'Merge updated properly.');
108 109

    $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetch();
110 111 112
    $this->assertEqual($person->name, 'Joe', 'Name set correctly.');
    $this->assertEqual($person->age, 30, 'Age skipped correctly.');
    $this->assertEqual($person->job, 'Speaker', 'Job set correctly.');
113 114 115
  }

  /**
116
   * Confirms that we can merge-update a record successfully, with expressions.
117 118 119 120 121 122 123 124 125 126 127 128
   */
  function testMergeUpdateExpression() {
    $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();

    $age_before = db_query('SELECT age FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetchField();

    // This is a very contrived example, as I have no idea why you'd want to
    // change age this way, but that's beside the point.
    // Note that we are also double-setting age here, once as a literal and
    // once as an expression. This test will only pass if the expression wins,
    // which is what is supposed to happen.
    db_merge('test_people')
129
      ->key('job', 'Speaker')
130 131 132 133 134 135
      ->fields(array('name' => 'Tiffany'))
      ->insertFields(array('age' => 31))
      ->expression('age', 'age + :age', array(':age' => 4))
      ->execute();

    $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
136
    $this->assertEqual($num_records_before, $num_records_after, 'Merge updated properly.');
137 138

    $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetch();
139 140 141
    $this->assertEqual($person->name, 'Tiffany', 'Name set correctly.');
    $this->assertEqual($person->age, $age_before + 4, 'Age updated correctly.');
    $this->assertEqual($person->job, 'Speaker', 'Job set correctly.');
142 143 144
  }

  /**
145
   * Tests that we can merge-insert without any update fields.
146 147 148 149 150
   */
  function testMergeInsertWithoutUpdate() {
    $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();

    db_merge('test_people')
151
      ->key('job', 'Presenter')
152 153 154
      ->execute();

    $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
155
    $this->assertEqual($num_records_before + 1, $num_records_after, 'Merge inserted properly.');
156 157

    $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Presenter'))->fetch();
158 159 160
    $this->assertEqual($person->name, '', 'Name set correctly.');
    $this->assertEqual($person->age, 0, 'Age set correctly.');
    $this->assertEqual($person->job, 'Presenter', 'Job set correctly.');
161 162 163
  }

  /**
164
   * Confirms that we can merge-update without any update fields.
165 166 167 168 169
   */
  function testMergeUpdateWithoutUpdate() {
    $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();

    db_merge('test_people')
170
      ->key('job', 'Speaker')
171 172 173
      ->execute();

    $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
174
    $this->assertEqual($num_records_before, $num_records_after, 'Merge skipped properly.');
175 176

    $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetch();
177 178 179
    $this->assertEqual($person->name, 'Meredith', 'Name skipped correctly.');
    $this->assertEqual($person->age, 30, 'Age skipped correctly.');
    $this->assertEqual($person->job, 'Speaker', 'Job skipped correctly.');
180 181

    db_merge('test_people')
182
      ->key('job', 'Speaker')
183 184 185 186
      ->insertFields(array('age' => 31))
      ->execute();

    $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
187
    $this->assertEqual($num_records_before, $num_records_after, 'Merge skipped properly.');
188 189

    $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetch();
190 191 192
    $this->assertEqual($person->name, 'Meredith', 'Name skipped correctly.');
    $this->assertEqual($person->age, 30, 'Age skipped correctly.');
    $this->assertEqual($person->job, 'Speaker', 'Job skipped correctly.');
193 194 195
  }

  /**
196
   * Tests that an invalid merge query throws an exception.
197 198 199
   */
  function testInvalidMerge() {
    try {
200
      // This query will fail because there is no key field specified.
201
      // Normally it would throw an exception but we are suppressing it with
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
      // the throw_exception option.
      $options['throw_exception'] = FALSE;
      db_merge('test_people', $options)
        ->fields(array(
          'age' => 31,
          'name' => 'Tiffany',
        ))
        ->execute();
      $this->pass('$options[\'throw_exception\'] is FALSE, no InvalidMergeQueryException thrown.');
    }
    catch (InvalidMergeQueryException $e) {
      $this->fail('$options[\'throw_exception\'] is FALSE, but InvalidMergeQueryException thrown for invalid query.');
      return;
    }

    try {
      // This query will fail because there is no key field specified.
219 220 221 222 223 224 225 226
      db_merge('test_people')
        ->fields(array(
          'age' => 31,
          'name' => 'Tiffany',
        ))
        ->execute();
    }
    catch (InvalidMergeQueryException $e) {
227
      $this->pass('InvalidMergeQueryException thrown for invalid query.');
228 229
      return;
    }
230
    $this->fail('No InvalidMergeQueryException thrown');
231 232
  }
}