Skip to content

Commit

Permalink
Merge pull request #20 from slack/insert-ignore
Browse files Browse the repository at this point in the history
Fix insert ignore to ignore the duplicate row
  • Loading branch information
Scott Sandler authored and GitHub Enterprise committed Jul 17, 2019
2 parents 90d0a30 + abb989a commit f6cc0ce
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 28 deletions.
56 changes: 28 additions & 28 deletions src/Query/InsertQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,34 +45,34 @@ public function execute(AsyncMysqlConnection $conn): int {
// throw for nonexistent fields
$row = DataIntegrity::coerceToSchema($row, $schema);

// check for unique key violations unless INSERT IGNORE was specified
if (!$this->ignoreDupes) {

$unique_key_violation = DataIntegrity::checkUniqueConstraints($table, $row, $schema);
if ($unique_key_violation is nonnull) {
list($msg, $row_id) = $unique_key_violation;
// is this an "INSERT ... ON DUPLICATE KEY UPDATE?"
// if so, this is where we apply the updates
if (!C\is_empty($this->updateExpressions)) {
$existing_row = $table[$row_id];
list($affected, $table) = $this->applySet(
$conn,
$database,
$table_name,
dict[$row_id => $existing_row],
$table,
$this->updateExpressions,
$schema,
$row,
);
// MySQL always counts dupe inserts twice intentionally
$rows_affected += $affected * 2;
continue;
} else if (!QueryContext::$relaxUniqueConstraints) {
throw new SQLFakeUniqueKeyViolation($msg);
} else {
continue;
}
// check for unique key violations
$unique_key_violation = DataIntegrity::checkUniqueConstraints($table, $row, $schema);
if ($unique_key_violation is nonnull) {
list($msg, $row_id) = $unique_key_violation;
// is this an "INSERT ... ON DUPLICATE KEY UPDATE?"
// if so, this is where we apply the updates
if (!C\is_empty($this->updateExpressions)) {
$existing_row = $table[$row_id];
list($affected, $table) = $this->applySet(
$conn,
$database,
$table_name,
dict[$row_id => $existing_row],
$table,
$this->updateExpressions,
$schema,
$row,
);
// MySQL always counts dupe inserts twice intentionally
$rows_affected += $affected * 2;
continue;
} elseif ($this->ignoreDupes) {
// silently continue if INSERT IGNORE was specified
continue;
} elseif (!QueryContext::$relaxUniqueConstraints) {
throw new SQLFakeUniqueKeyViolation($msg);
} else {
continue;
}
}
$table[] = $row;
Expand Down
14 changes: 14 additions & 0 deletions tests/InsertQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ final class InsertQueryTest extends HackTest {
expect(() ==> $conn->query("INSERT IGNORE INTO table1 (id, name) VALUES (1, 'test2')"))->notToThrow(
SQLFakeUniqueKeyViolation::class,
);
$results = await $conn->query("SELECT * FROM table1");
expect($results->rows())->toBeSame(
vec[dict[
'id' => 1,
'name' => 'test',
]],
);
}

public async function testPKViolationWithinMultiInsert(): Awaitable<void> {
Expand All @@ -86,6 +93,13 @@ final class InsertQueryTest extends HackTest {
expect(() ==> $conn->query("INSERT IGNORE INTO table1 (id, name) VALUES (2, 'test')"))->notToThrow(
SQLFakeUniqueKeyViolation::class,
);
$results = await $conn->query("SELECT * FROM table1");
expect($results->rows())->toBeSame(
vec[dict[
'id' => 1,
'name' => 'test',
]],
);
}

public async function testPartialValuesList(): Awaitable<void> {
Expand Down

0 comments on commit f6cc0ce

Please sign in to comment.