InsertTest.php 7.83 KB
Newer Older
1 2
<?php

3
namespace Drupal\KernelTests\Core\Database;
4 5

/**
6
 * Tests the insert builder.
7 8
 *
 * @group Database
9 10 11 12
 */
class InsertTest extends DatabaseTestBase {

  /**
13
   * Tests very basic insert functionality.
14
   */
15
  public function testSimpleInsert() {
16 17 18
    $num_records_before = db_query('SELECT COUNT(*) FROM {test}')->fetchField();

    $query = db_insert('test');
19
    $query->fields([
20 21
      'name' => 'Yoko',
      'age' => '29',
22
    ]);
23 24 25

    // Check how many records are queued for insertion.
    $this->assertIdentical($query->count(), 1, 'One record is queued for insertion.');
26 27 28
    $query->execute();

    $num_records_after = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
29
    $this->assertSame($num_records_before + 1, (int) $num_records_after, 'Record inserts correctly.');
30
    $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Yoko'])->fetchField();
31
    $this->assertIdentical($saved_age, '29', 'Can retrieve after inserting.');
32 33 34
  }

  /**
35
   * Tests that we can insert multiple records in one query object.
36
   */
37
  public function testMultiInsert() {
38 39 40
    $num_records_before = (int) db_query('SELECT COUNT(*) FROM {test}')->fetchField();

    $query = db_insert('test');
41
    $query->fields([
42 43
      'name' => 'Larry',
      'age' => '30',
44
    ]);
45 46

    // We should be able to specify values in any order if named.
47
    $query->values([
48 49
      'age' => '31',
      'name' => 'Curly',
50
    ]);
51

52 53 54
    // Check how many records are queued for insertion.
    $this->assertIdentical($query->count(), 2, 'Two records are queued for insertion.');

55 56
    // We should be able to say "use the field order".
    // This is not the recommended mechanism for most cases, but it should work.
57
    $query->values(['Moe', '32']);
58 59 60

    // Check how many records are queued for insertion.
    $this->assertIdentical($query->count(), 3, 'Three records are queued for insertion.');
61 62 63
    $query->execute();

    $num_records_after = (int) db_query('SELECT COUNT(*) FROM {test}')->fetchField();
64
    $this->assertSame($num_records_before + 3, $num_records_after, 'Record inserts correctly.');
65
    $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Larry'])->fetchField();
66
    $this->assertIdentical($saved_age, '30', 'Can retrieve after inserting.');
67
    $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Curly'])->fetchField();
68
    $this->assertIdentical($saved_age, '31', 'Can retrieve after inserting.');
69
    $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Moe'])->fetchField();
70
    $this->assertIdentical($saved_age, '32', 'Can retrieve after inserting.');
71 72 73
  }

  /**
74
   * Tests that an insert object can be reused with new data after it executes.
75
   */
76
  public function testRepeatedInsert() {
77 78 79 80
    $num_records_before = db_query('SELECT COUNT(*) FROM {test}')->fetchField();

    $query = db_insert('test');

81
    $query->fields([
82 83
      'name' => 'Larry',
      'age' => '30',
84
    ]);
85 86
    // Check how many records are queued for insertion.
    $this->assertIdentical($query->count(), 1, 'One record is queued for insertion.');
87 88 89
    $query->execute();  // This should run the insert, but leave the fields intact.

    // We should be able to specify values in any order if named.
90
    $query->values([
91 92
      'age' => '31',
      'name' => 'Curly',
93
    ]);
94 95
    // Check how many records are queued for insertion.
    $this->assertIdentical($query->count(), 1, 'One record is queued for insertion.');
96 97 98
    $query->execute();

    // We should be able to say "use the field order".
99
    $query->values(['Moe', '32']);
100 101 102

    // Check how many records are queued for insertion.
    $this->assertIdentical($query->count(), 1, 'One record is queued for insertion.');
103 104 105
    $query->execute();

    $num_records_after = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
106
    $this->assertSame((int) $num_records_before + 3, (int) $num_records_after, 'Record inserts correctly.');
107
    $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Larry'])->fetchField();
108
    $this->assertIdentical($saved_age, '30', 'Can retrieve after inserting.');
109
    $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Curly'])->fetchField();
110
    $this->assertIdentical($saved_age, '31', 'Can retrieve after inserting.');
111
    $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Moe'])->fetchField();
112
    $this->assertIdentical($saved_age, '32', 'Can retrieve after inserting.');
113 114 115
  }

  /**
116
   * Tests that we can specify fields without values and specify values later.
117
   */
118
  public function testInsertFieldOnlyDefinition() {
119 120 121
    // This is useful for importers, when we want to create a query and define
    // its fields once, then loop over a multi-insert execution.
    db_insert('test')
122 123 124 125
      ->fields(['name', 'age'])
      ->values(['Larry', '30'])
      ->values(['Curly', '31'])
      ->values(['Moe', '32'])
126
      ->execute();
127
    $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Larry'])->fetchField();
128
    $this->assertIdentical($saved_age, '30', 'Can retrieve after inserting.');
129
    $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Curly'])->fetchField();
130
    $this->assertIdentical($saved_age, '31', 'Can retrieve after inserting.');
131
    $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Moe'])->fetchField();
132
    $this->assertIdentical($saved_age, '32', 'Can retrieve after inserting.');
133 134 135
  }

  /**
136
   * Tests that inserts return the proper auto-increment ID.
137
   */
138
  public function testInsertLastInsertID() {
139
    $id = db_insert('test')
140
      ->fields([
141 142
        'name' => 'Larry',
        'age' => '30',
143
      ])
144 145
      ->execute();

146
    $this->assertIdentical($id, '5', 'Auto-increment ID returned successfully.');
147 148 149
  }

  /**
150
   * Tests that the INSERT INTO ... SELECT (fields) ... syntax works.
151
   */
152
  public function testInsertSelectFields() {
153 154 155 156 157 158
    $query = db_select('test_people', 'tp');
    // The query builder will always append expressions after fields.
    // Add the expression first to test that the insert fields are correctly
    // re-ordered.
    $query->addExpression('tp.age', 'age');
    $query
159
      ->fields('tp', ['name', 'job'])
160 161 162 163 164 165 166 167 168 169 170
      ->condition('tp.name', 'Meredith');

    // The resulting query should be equivalent to:
    // INSERT INTO test (age, name, job)
    // SELECT tp.age AS age, tp.name AS name, tp.job AS job
    // FROM test_people tp
    // WHERE tp.name = 'Meredith'
    db_insert('test')
      ->from($query)
      ->execute();

171
    $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Meredith'])->fetchField();
172
    $this->assertIdentical($saved_age, '30', 'Can retrieve after inserting.');
173
  }
174 175 176 177

  /**
   * Tests that the INSERT INTO ... SELECT * ... syntax works.
   */
178
  public function testInsertSelectAll() {
179 180 181 182 183 184 185 186 187 188 189 190 191
    $query = db_select('test_people', 'tp')
      ->fields('tp')
      ->condition('tp.name', 'Meredith');

    // The resulting query should be equivalent to:
    // INSERT INTO test_people_copy
    // SELECT *
    // FROM test_people tp
    // WHERE tp.name = 'Meredith'
    db_insert('test_people_copy')
      ->from($query)
      ->execute();

192
    $saved_age = db_query('SELECT age FROM {test_people_copy} WHERE name = :name', [':name' => 'Meredith'])->fetchField();
193 194 195
    $this->assertIdentical($saved_age, '30', 'Can retrieve after inserting.');
  }

196 197 198
  /**
   * Tests that we can INSERT INTO a special named column.
   */
199
  public function testSpecialColumnInsert() {
200
    $id = db_insert('test_special_columns')
201
      ->fields([
202 203
        'id' => 2,
        'offset' => 'Offset value 2',
204
      ])
205
      ->execute();
206
    $saved_value = db_query('SELECT "offset" FROM {test_special_columns} WHERE id = :id', [':id' => 2])->fetchField();
207 208
    $this->assertIdentical($saved_value, 'Offset value 2', 'Can retrieve special column name value after inserting.');
  }
209

210
}